diff --git a/assets/css/build/admin.css b/assets/css/build/admin.css index fd55287..f7b7492 100644 --- a/assets/css/build/admin.css +++ b/assets/css/build/admin.css @@ -130,13 +130,58 @@ body.admin-color-sunrise { box-shadow: -2px -2px 0 0 var(--t3-background), 0 -2px 0 0 var(--t3-background), -2px 0 0 0 var(--t3-background), 0 2px 0 0 var(--t3-background), 2px 0 0 0 var(--t3-background), 0 0 0 2px var(--t3-text), -4px -4px 0 0 var(--t3-text), 0 -4px 0 0 var(--t3-text), -4px 0 0 0 var(--t3-text), 0 4px 0 0 var(--t3-text), 4px 0 0 0 var(--t3-text); } -.tumblr-theme-thumbnail { +.tumblr-theme-details { width: calc(100% - 4px); + border: 2px solid var(--t3-secondary); + border-radius: 4px; + display: block; + position: relative; + overflow: hidden; + padding: 0; +} +.tumblr-theme-details label { + display: none; + z-index: 2; + position: absolute; +} +.tumblr-theme-details img { + width: 100%; height: auto; aspect-ratio: 100/67; object-fit: contain; - border: 2px solid var(--t3-secondary); + margin-bottom: -6px; + z-index: 1; +} +.tumblr-theme-details:hover label { + top: 0; + left: 0; + width: 100%; + height: auto; + aspect-ratio: 100/67; + object-fit: contain; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + background: radial-gradient(closest-side, rgba(0, 0, 0, 0) calc(100% - 1px), var(--t3-background)) 0/3px 3px space; +} +.tumblr-theme-details:hover .tumblr-theme-detail-button { + display: inline-block; + line-height: 24px; + padding: 0 20px; + font-size: 1em; + text-decoration: none; border-radius: 4px; + color: var(--t3-button-text); + border: 1px solid var(--t3-primary); + background: var(--t3-primary); + background: repeating-linear-gradient(90deg, var(--t3-red) 0%, var(--t3-orange), var(--t3-yellow), var(--t3-green), var(--t3-violet), var(--t3-red) 50%); + background-size: 90px 100%; + animation: play 1.5s linear infinite; + color: #000; + font-size: 16px; + font-weight: 600; + padding: 5px 20px; } .tumblr-theme-title { @@ -152,41 +197,25 @@ body.admin-color-sunrise { box-shadow: -2px 4px 0 var(--t3-background), 0 -2px 0 var(--t3-background), -2px 0 0 var(--t3-background), 2px 0 0 var(--t3-background), 4px 2px 0 var(--t3-background), 6px 4px 0 var(--t3-background), 8px 6px 0 var(--t3-background), 10px 8px 0 var(--t3-background), 12px 10px 0 var(--t3-background), 14px 12px 0 var(--t3-background), 16px 14px 0 var(--t3-background), 18px 16px 0 var(--t3-background), 20px 18px 0 var(--t3-background), -4px 0 0 var(--t3-text), 0 -4px 0 var(--t3-text), -2px -2px 0 var(--t3-text), 2px -2px 0 var(--t3-text), 4px 0 0 var(--t3-text), 6px 2px 0 var(--t3-text), 8px 4px 0 var(--t3-text), 10px 6px 0 var(--t3-text), 12px 8px 0 var(--t3-text), 14px 10px 0 var(--t3-text), 16px 12px 0 var(--t3-text), 18px 14px 0 var(--t3-text), 20px 16px 0 var(--t3-text); } -.tumblr-theme-buttons { - display: flex; - justify-content: flex-end; - align-items: center; +.tumblr-theme-footer { position: relative; + text-align: right; margin: 10px 0 0; padding: 0; width: 100%; } - -.tumblr-theme-buttons li { - flex: none; - display: block; - overflow: hidden; - position: relative; - margin-left: 10px; - border-radius: 4px; -} - -.tumblr-theme-buttons li a { +.tumblr-theme-footer a { display: inline-block; - overflow: hidden; - width: 90px; line-height: 24px; + padding: 0 20px; font-size: 1em; - white-space: nowrap; - text-align: center; text-decoration: none; - border-radius: inherit; + border-radius: 4px; color: var(--t3-button-text); border: 1px solid var(--t3-primary); background: var(--t3-primary); } - -.tumblr-theme-buttons li a:hover { +.tumblr-theme-footer a:hover { background: repeating-linear-gradient(90deg, var(--t3-red) 0%, var(--t3-orange), var(--t3-yellow), var(--t3-green), var(--t3-violet), var(--t3-red) 50%); background-size: 90px 100%; animation: play 1.5s linear infinite; diff --git a/assets/css/build/admin.css.map b/assets/css/build/admin.css.map index 5b32c41..059979a 100644 --- a/assets/css/build/admin.css.map +++ b/assets/css/build/admin.css.map @@ -1 +1 @@ -{"version":3,"sources":["../src/admin/_theme_garden.scss","../src/admin.scss"],"names":[],"mappings":"AAEA;EACC,qBAAA;EACA,uBAAA;EACA,wBAAA;EACA,kBAAA;EACA,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,oBAAA;EACA,mBAAA;EACA,oBAAA;ACDD;;ADIA;EACC,qBAAA;EACA,uBAAA;EACA,eAAA;ACDD;;ADIA;EACC,qBAAA;EACA,kBAAA;ACDD;;ADIA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;ACDD;;ADIA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;ACDD;;ADIA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;ACDD;;ADIA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;ACDD;;ADIA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;ACDD;;ADIA;EACC,qBAAA;EACA,uBAAA;EACA,eAAA;ACDD;;ADIA;EACC,aAAA;EACA,0BAAA;EACA,uBAAA;EACA,UAAA;EACA,cAAA;ACDD;;ADIA;EACC,WAAA;EACA,qBAAA;EACA,mBAAA;EACA,sBAAA;EACA,6CAAA;ACDD;ADGC;EACC,gDAAA;ACDF;ADIC;EACC,gDAAA;ACFF;ADKC;EACC,+CAAA;ACHF;ADMC;EACC,gDAAA;ACJF;;ADQA;EAEC;IACC,sCAAA;IACA,8BAAA;ECNA;AACF;ADSA;EAEC;IACC,kCAAA;IACA,8BAAA;ECRA;AACF;ADWA;EAEC;IACC,8BAAA;IACA,8BAAA;ECVA;AACF;ADaA;EACC,aAAA;EACA,uBAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,uBAAA;EACA,YAAA;ACXD;;ADcA;EACC,aAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,sBAAA;EACA,cAAA;EACA,uBAAA;ACXD;;ADcA;EACC,sCAAA;EACA,aAAA;EACA,kVACC;ACZF;;ADyBA;EACC,uBAAA;EACA,YAAA;EACA,oBAAA;EACA,mBAAA;EACA,qCAAA;EACA,kBAAA;ACtBD;;ADyBA;EACC,cAAA;EACA,kBAAA;EACA,sCAAA;EACA,wBAAA;EACA,YAAA;EACA,iBAAA;EACA,sBAAA;EACA,cAAA;EACA,gBAAA;EACA,6wBACC;ACvBF;;ADmDA;EACC,aAAA;EACA,yBAAA;EACA,mBAAA;EACA,kBAAA;EACA,gBAAA;EACA,UAAA;EACA,WAAA;AChDD;;ADmDA;EACC,UAAA;EACA,cAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,kBAAA;AChDD;;ADoDA;EACC,qBAAA;EACA,gBAAA;EACA,WAAA;EACA,iBAAA;EACA,cAAA;EACA,mBAAA;EACA,kBAAA;EACA,qBAAA;EACA,sBAAA;EACA,4BAAA;EACA,mCAAA;EACA,6BAAA;ACjDD;;ADoDA;EACC,wJAAA;EASA,0BAAA;EACA,oCAAA;EACA,WAAA;ACzDD;;AD6DA;EACC,YAAA;AC1DD;;AD6DA;EACC,eAAA;AC1DD;;AD6DA;EACC;IACC,8BAAA;EC1DA;AACF;AD6DA;EACC,aAAA;EACA,mBAAA;AC3DD;;AD8DA;EACC,WAAA;EACA,cAAA;AC3DD;;AD8DA;EACC,iBAAA;EACA,gBAAA;EACA,kBAAA;AC3DD;;AD8DA;EACC,eAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,YAAA;EACA,qDAAA;UAAA,6CAAA;EACA,wJAAA;AC3DD;;ADsEA;EACC,oCAAA;ACnED;;ADsEA;EACC,cAAA;ACnED","file":"admin.css","sourcesContent":["$buttonWidth: 70px;\n\nbody {\n\t--t3-primary: #49a2c4;\n\t--t3-secondary: #8eb2c0;\n\t--t3-background: #f1f1f1;\n\t--t3-text: #49a2c4;\n\t--t3-button-text: #fff;\n\t--t3-red: #f8c7c3;\n\t--t3-orange: #f8d8bf;\n\t--t3-yellow: #f0e794;\n\t--t3-green: #b9ebc8;\n\t--t3-violet: #d4caf7;\n}\n\nbody.admin-color-light {\n\t--t3-primary: #04a4cc;\n\t--t3-secondary: #e5e5e5;\n\t--t3-text: #999;\n}\n\nbody.admin-color-modern {\n\t--t3-primary: #3858e9;\n\t--t3-text: #1e1e1e;\n}\n\nbody.admin-color-blue {\n\t--t3-primary: #4796b3;\n\t--t3-secondary: #74b6ce;\n\t--t3-text: #096484;\n}\n\nbody.admin-color-coffee {\n\t--t3-primary: #c7a589;\n\t--t3-secondary: #9ea476;\n\t--t3-text: #46403c;\n}\n\nbody.admin-color-ectoplasm {\n\t--t3-primary: #a3b745;\n\t--t3-secondary: #a3b745;\n\t--t3-text: #523f6d;\n}\n\nbody.admin-color-midnight {\n\t--t3-primary: #e14d43;\n\t--t3-secondary: #363b3f;\n\t--t3-text: #25282b;\n}\n\nbody.admin-color-ocean {\n\t--t3-primary: #9ebaa0;\n\t--t3-secondary: #738e96;\n\t--t3-text: #627c83;\n}\n\nbody.admin-color-sunrise {\n\t--t3-primary: #dd823b;\n\t--t3-secondary: #e5e5e5;\n\t--t3-text: #000;\n}\n\n.tumblr-themes {\n\tdisplay: grid;\n\tgrid-template-columns: 95%;\n\tjustify-content: center;\n\twidth: 98%;\n\tmargin: 0 auto;\n}\n\n.tumblr-theme {\n\twidth: 100%;\n\tcolor: var(--t3-text);\n\tmargin-bottom: 40px;\n\tfont-family: monospace;\n\tfilter: drop-shadow(-8px 8px 0 var(--t3-red));\n\n\t&:nth-child(5n + 2) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-orange));\n\t}\n\n\t&:nth-child(5n + 3) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-yellow));\n\t}\n\n\t&:nth-child(5n + 4) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-green));\n\t}\n\n\t&:nth-child(5n + 5) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-violet));\n\t}\n}\n\n@media screen and (min-width: 1601px) {\n\n\t.tumblr-themes {\n\t\tgrid-template-columns: 22% 22% 22% 22%;\n\t\tjustify-content: space-between;\n\t}\n}\n\n@media screen and (min-width: 1301px) and (max-width: 1600px) {\n\n\t.tumblr-themes {\n\t\tgrid-template-columns: 30% 30% 30%;\n\t\tjustify-content: space-between;\n\t}\n}\n\n@media screen and (min-width: 730px) and (max-width: 1300px) {\n\n\t.tumblr-themes {\n\t\tgrid-template-columns: 47% 47%;\n\t\tjustify-content: space-between;\n\t}\n}\n\n.tumblr-theme-header {\n\tdisplay: flex;\n\talign-items: flex-start;\n\toverflow: hidden;\n\tposition: relative;\n\tmargin-left: -8px;\n\twidth: calc(100% + 8px);\n\theight: 26px;\n}\n\n.tumblr-theme-title-wrapper {\n\tflex: initial;\n\tdisplay: block;\n\tposition: relative;\n\tmargin-left: 4px;\n\tpadding: 4px 4px 0 4px;\n\tmax-width: 80%;\n\ttext-overflow: ellipsis;\n}\n\n.tumblr-theme-content {\n\tbackground-color: var(--t3-background);\n\tpadding: 10px;\n\tbox-shadow:\n\t\t-2px -2px 0 0 var(--t3-background),\n\t\t0 -2px 0 0 var(--t3-background),\n\t\t-2px 0 0 0 var(--t3-background),\n\t\t0 2px 0 0 var(--t3-background),\n\t\t2px 0 0 0 var(--t3-background),\n\t\t0 0 0 2px var(--t3-text),\n\t\t-4px -4px 0 0 var(--t3-text),\n\t\t0 -4px 0 0 var(--t3-text),\n\t\t-4px 0 0 0 var(--t3-text),\n\t\t0 4px 0 0 var(--t3-text),\n\t\t4px 0 0 0 var(--t3-text);\n}\n\n.tumblr-theme-thumbnail {\n\twidth: calc(100% - 4px);\n\theight: auto;\n\taspect-ratio: 100/67;\n\tobject-fit: contain;\n\tborder: 2px solid var(--t3-secondary);\n\tborder-radius: 4px;\n}\n\n.tumblr-theme-title {\n\tdisplay: block;\n\tposition: relative;\n\tbackground-color: var(--t3-background);\n\tpadding: 3px 12px 0 10px;\n\theight: 18px;\n\tline-height: 18px;\n\tfont-family: monospace;\n\tfont-size: 1em;\n\tfont-weight: 700;\n\tbox-shadow:\n\t\t-2px 4px 0 var(--t3-background),\n\t\t0 -2px 0 var(--t3-background),\n\t\t-2px 0 0 var(--t3-background),\n\t\t2px 0 0 var(--t3-background),\n\t\t4px 2px 0 var(--t3-background),\n\t\t6px 4px 0 var(--t3-background),\n\t\t8px 6px 0 var(--t3-background),\n\t\t10px 8px 0 var(--t3-background),\n\t\t12px 10px 0 var(--t3-background),\n\t\t14px 12px 0 var(--t3-background),\n\t\t16px 14px 0 var(--t3-background),\n\t\t18px 16px 0 var(--t3-background),\n\t\t20px 18px 0 var(--t3-background),\n\t\t-4px 0 0 var(--t3-text),\n\t\t0 -4px 0 var(--t3-text),\n\t\t-2px -2px 0 var(--t3-text),\n\t\t2px -2px 0 var(--t3-text),\n\t\t4px 0 0 var(--t3-text),\n\t\t6px 2px 0 var(--t3-text),\n\t\t8px 4px 0 var(--t3-text),\n\t\t10px 6px 0 var(--t3-text),\n\t\t12px 8px 0 var(--t3-text),\n\t\t14px 10px 0 var(--t3-text),\n\t\t16px 12px 0 var(--t3-text),\n\t\t18px 14px 0 var(--t3-text),\n\t\t20px 16px 0 var(--t3-text);\n}\n\n.tumblr-theme-buttons {\n\tdisplay: flex;\n\tjustify-content: flex-end;\n\talign-items: center;\n\tposition: relative;\n\tmargin: 10px 0 0;\n\tpadding: 0;\n\twidth: 100%;\n}\n\n.tumblr-theme-buttons li {\n\tflex: none;\n\tdisplay: block;\n\toverflow: hidden;\n\tposition: relative;\n\tmargin-left: 10px;\n\tborder-radius: 4px;\n}\n\n\n.tumblr-theme-buttons li a {\n\tdisplay: inline-block;\n\toverflow: hidden;\n\twidth: 90px;\n\tline-height: 24px;\n\tfont-size: 1em;\n\twhite-space: nowrap;\n\ttext-align: center;\n\ttext-decoration: none;\n\tborder-radius: inherit;\n\tcolor: var(--t3-button-text);\n\tborder: 1px solid var(--t3-primary);\n\tbackground: var(--t3-primary);\n}\n\n.tumblr-theme-buttons li a:hover {\n\tbackground: repeating-linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--t3-red) 0%,\n\t\t\tvar(--t3-orange),\n\t\t\tvar(--t3-yellow),\n\t\t\tvar(--t3-green),\n\t\t\tvar(--t3-violet),\n\t\t\tvar(--t3-red) 50%\n\t);\n\tbackground-size: 90px 100%;\n\tanimation: play 1.5s linear infinite;\n\tcolor: #000;\n}\n\n\n#t3-categories {\n\tmargin: 10px;\n}\n\n#t3-category-select-form {\n\tdisplay: inline;\n}\n\n@keyframes play {\n\t100% {\n\t\tbackground-position: -90px top;\n\t}\n}\n\n#theme-garden-heading {\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.tumblr-logo-icon {\n\twidth: 30px;\n\tmargin: 0 12px;\n}\n\n.tumblr-theme-garden-list-item {\n\tpadding: 4px 10px;\n\tbackground: #000;\n\tborder-radius: 6px;\n}\n\n.tumblr-theme-garden-link {\n\tcursor: pointer;\n\tborder: none;\n\toutline: none;\n\twidth: 80px;\n\theight: 16px;\n\tmask-image: url(../../images/tumblr-logo.png) ;\n\tbackground: repeating-linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--t3-red) 0%,\n\t\t\tvar(--t3-orange),\n\t\t\tvar(--t3-yellow),\n\t\t\tvar(--t3-green),\n\t\t\tvar(--t3-violet),\n\t\t\tvar(--t3-red) 50%\n\t);\n}\n\n.tumblr-theme-garden-link:hover {\n\tanimation: play 1.5s linear infinite;\n}\n\n#tumblr-no-themes {\n\tdisplay: block;\n}\n","@import \"admin/theme_garden\";\n"]} \ No newline at end of file +{"version":3,"sources":["../src/admin/_theme_garden.scss","../src/admin.scss"],"names":[],"mappings":"AA6BA;EACC,qBAAA;EACA,uBAAA;EACA,wBAAA;EACA,kBAAA;EACA,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,oBAAA;EACA,mBAAA;EACA,oBAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,uBAAA;EACA,eAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,kBAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,uBAAA;EACA,kBAAA;AC5BD;;AD+BA;EACC,qBAAA;EACA,uBAAA;EACA,eAAA;AC5BD;;AD+BA;EACC,aAAA;EACA,0BAAA;EACA,uBAAA;EACA,UAAA;EACA,cAAA;AC5BD;;AD+BA;EACC,WAAA;EACA,qBAAA;EACA,mBAAA;EACA,sBAAA;EACA,6CAAA;AC5BD;AD8BC;EACC,gDAAA;AC5BF;AD+BC;EACC,gDAAA;AC7BF;ADgCC;EACC,+CAAA;AC9BF;ADiCC;EACC,gDAAA;AC/BF;;ADmCA;EAEC;IACC,sCAAA;IACA,8BAAA;ECjCA;AACF;ADoCA;EAEC;IACC,kCAAA;IACA,8BAAA;ECnCA;AACF;ADsCA;EAEC;IACC,8BAAA;IACA,8BAAA;ECrCA;AACF;ADwCA;EACC,aAAA;EACA,uBAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,uBAAA;EACA,YAAA;ACtCD;;ADyCA;EACC,aAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,sBAAA;EACA,cAAA;EACA,uBAAA;ACtCD;;ADyCA;EACC,sCAAA;EACA,aAAA;EACA,kVACC;ACvCF;;ADoDA;EACC,uBAAA;EACA,qCAAA;EACA,kBAAA;EACA,cAAA;EACA,kBAAA;EACA,gBAAA;EACA,UAAA;ACjDD;ADmDC;EACC,aAAA;EACA,UAAA;EACA,kBAAA;ACjDF;ADoDC;EACC,WAAA;EACA,YAAA;EACA,oBAAA;EACA,mBAAA;EACA,mBAAA;EACA,UAAA;AClDF;ADsDE;EACC,MAAA;EACA,OAAA;EACA,WAAA;EACA,YAAA;EACA,oBAAA;EACA,mBAAA;EACA,aAAA;EACA,mBAAA;EACA,uBAAA;EACA,eAAA;EACA,kHAAA;ACpDH;AD2DE;EA9ND,qBAAA;EACA,iBAAA;EACA,eAAA;EACA,cAAA;EACA,qBAAA;EACA,kBAAA;EACA,4BAAA;EACA,mCAAA;EACA,6BAAA;EAIA,wJAAA;EASA,0BAAA;EACA,oCAAA;EACA,WAAA;EA0ME,eAAA;EACA,gBAAA;EACA,iBAAA;AC9CH;;ADmDA;EACC,cAAA;EACA,kBAAA;EACA,sCAAA;EACA,wBAAA;EACA,YAAA;EACA,iBAAA;EACA,sBAAA;EACA,cAAA;EACA,gBAAA;EACA,6wBACC;ACjDF;;AD6EA;EACC,kBAAA;EACA,iBAAA;EACA,gBAAA;EACA,UAAA;EACA,WAAA;AC1ED;AD4EC;EAtRA,qBAAA;EACA,iBAAA;EACA,eAAA;EACA,cAAA;EACA,qBAAA;EACA,kBAAA;EACA,4BAAA;EACA,mCAAA;EACA,6BAAA;AC6MD;ADoEE;EA7QD,wJAAA;EASA,0BAAA;EACA,oCAAA;EACA,WAAA;ACoMD;;ADoEA;EACC,YAAA;ACjED;;ADoEA;EACC,eAAA;ACjED;;ADoEA;EACC;IACC,8BAAA;ECjEA;AACF;ADoEA;EACC,aAAA;EACA,mBAAA;AClED;;ADqEA;EACC,WAAA;EACA,cAAA;AClED;;ADqEA;EACC,iBAAA;EACA,gBAAA;EACA,kBAAA;AClED;;ADqEA;EACC,eAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,YAAA;EACA,qDAAA;UAAA,6CAAA;EACA,wJAAA;AClED;;AD6EA;EACC,oCAAA;AC1ED;;AD6EA;EACC,cAAA;AC1ED","file":"admin.css","sourcesContent":["$buttonWidth: 70px;\n\n@mixin rainbow-button {\n\tdisplay: inline-block;\n\tline-height: 24px;\n\tpadding: 0 20px;\n\tfont-size: 1em;\n\ttext-decoration: none;\n\tborder-radius: 4px;\n\tcolor: var(--t3-button-text);\n\tborder: 1px solid var(--t3-primary);\n\tbackground: var(--t3-primary);\n}\n\n@mixin rainbow-button-hover {\n\tbackground: repeating-linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--t3-red) 0%,\n\t\t\tvar(--t3-orange),\n\t\t\tvar(--t3-yellow),\n\t\t\tvar(--t3-green),\n\t\t\tvar(--t3-violet),\n\t\t\tvar(--t3-red) 50%\n\t);\n\tbackground-size: 90px 100%;\n\tanimation: play 1.5s linear infinite;\n\tcolor: #000;\n}\n\nbody {\n\t--t3-primary: #49a2c4;\n\t--t3-secondary: #8eb2c0;\n\t--t3-background: #f1f1f1;\n\t--t3-text: #49a2c4;\n\t--t3-button-text: #fff;\n\t--t3-red: #f8c7c3;\n\t--t3-orange: #f8d8bf;\n\t--t3-yellow: #f0e794;\n\t--t3-green: #b9ebc8;\n\t--t3-violet: #d4caf7;\n}\n\nbody.admin-color-light {\n\t--t3-primary: #04a4cc;\n\t--t3-secondary: #e5e5e5;\n\t--t3-text: #999;\n}\n\nbody.admin-color-modern {\n\t--t3-primary: #3858e9;\n\t--t3-text: #1e1e1e;\n}\n\nbody.admin-color-blue {\n\t--t3-primary: #4796b3;\n\t--t3-secondary: #74b6ce;\n\t--t3-text: #096484;\n}\n\nbody.admin-color-coffee {\n\t--t3-primary: #c7a589;\n\t--t3-secondary: #9ea476;\n\t--t3-text: #46403c;\n}\n\nbody.admin-color-ectoplasm {\n\t--t3-primary: #a3b745;\n\t--t3-secondary: #a3b745;\n\t--t3-text: #523f6d;\n}\n\nbody.admin-color-midnight {\n\t--t3-primary: #e14d43;\n\t--t3-secondary: #363b3f;\n\t--t3-text: #25282b;\n}\n\nbody.admin-color-ocean {\n\t--t3-primary: #9ebaa0;\n\t--t3-secondary: #738e96;\n\t--t3-text: #627c83;\n}\n\nbody.admin-color-sunrise {\n\t--t3-primary: #dd823b;\n\t--t3-secondary: #e5e5e5;\n\t--t3-text: #000;\n}\n\n.tumblr-themes {\n\tdisplay: grid;\n\tgrid-template-columns: 95%;\n\tjustify-content: center;\n\twidth: 98%;\n\tmargin: 0 auto;\n}\n\n.tumblr-theme {\n\twidth: 100%;\n\tcolor: var(--t3-text);\n\tmargin-bottom: 40px;\n\tfont-family: monospace;\n\tfilter: drop-shadow(-8px 8px 0 var(--t3-red));\n\n\t&:nth-child(5n + 2) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-orange));\n\t}\n\n\t&:nth-child(5n + 3) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-yellow));\n\t}\n\n\t&:nth-child(5n + 4) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-green));\n\t}\n\n\t&:nth-child(5n + 5) {\n\t\tfilter: drop-shadow(-8px 8px 0 var(--t3-violet));\n\t}\n}\n\n@media screen and (min-width: 1601px) {\n\n\t.tumblr-themes {\n\t\tgrid-template-columns: 22% 22% 22% 22%;\n\t\tjustify-content: space-between;\n\t}\n}\n\n@media screen and (min-width: 1301px) and (max-width: 1600px) {\n\n\t.tumblr-themes {\n\t\tgrid-template-columns: 30% 30% 30%;\n\t\tjustify-content: space-between;\n\t}\n}\n\n@media screen and (min-width: 730px) and (max-width: 1300px) {\n\n\t.tumblr-themes {\n\t\tgrid-template-columns: 47% 47%;\n\t\tjustify-content: space-between;\n\t}\n}\n\n.tumblr-theme-header {\n\tdisplay: flex;\n\talign-items: flex-start;\n\toverflow: hidden;\n\tposition: relative;\n\tmargin-left: -8px;\n\twidth: calc(100% + 8px);\n\theight: 26px;\n}\n\n.tumblr-theme-title-wrapper {\n\tflex: initial;\n\tdisplay: block;\n\tposition: relative;\n\tmargin-left: 4px;\n\tpadding: 4px 4px 0 4px;\n\tmax-width: 80%;\n\ttext-overflow: ellipsis;\n}\n\n.tumblr-theme-content {\n\tbackground-color: var(--t3-background);\n\tpadding: 10px;\n\tbox-shadow:\n\t\t-2px -2px 0 0 var(--t3-background),\n\t\t0 -2px 0 0 var(--t3-background),\n\t\t-2px 0 0 0 var(--t3-background),\n\t\t0 2px 0 0 var(--t3-background),\n\t\t2px 0 0 0 var(--t3-background),\n\t\t0 0 0 2px var(--t3-text),\n\t\t-4px -4px 0 0 var(--t3-text),\n\t\t0 -4px 0 0 var(--t3-text),\n\t\t-4px 0 0 0 var(--t3-text),\n\t\t0 4px 0 0 var(--t3-text),\n\t\t4px 0 0 0 var(--t3-text);\n}\n\n.tumblr-theme-details {\n\twidth: calc(100% - 4px);\n\tborder: 2px solid var(--t3-secondary);\n\tborder-radius: 4px;\n\tdisplay: block;\n\tposition: relative;\n\toverflow: hidden;\n\tpadding: 0;\n\n\tlabel {\n\t\tdisplay: none;\n\t\tz-index: 2;\n\t\tposition: absolute;\n\t}\n\n\timg {\n\t\twidth: 100%;\n\t\theight: auto;\n\t\taspect-ratio: 100/67;\n\t\tobject-fit: contain;\n\t\tmargin-bottom: -6px;\n\t\tz-index: 1;\n\t}\n\n\t&:hover {\n\t\tlabel {\n\t\t\ttop: 0;\n\t\t\tleft: 0;\n\t\t\twidth: 100%;\n\t\t\theight: auto;\n\t\t\taspect-ratio: 100/67;\n\t\t\tobject-fit: contain;\n\t\t\tdisplay: flex;\n\t\t\talign-items: center;\n\t\t\tjustify-content: center;\n\t\t\tcursor: pointer;\n\t\t\tbackground: radial-gradient(\n\t\t\t\t\tclosest-side,\n\t\t\t\t\t#0000 calc(100% - 1px),\n\t\t\t\t\tvar(--t3-background)\n\t\t\t) 0/ 3px 3px space;\n\t\t}\n\n\t\t.tumblr-theme-detail-button {\n\t\t\t@include rainbow-button;\n\t\t\t@include rainbow-button-hover;\n\t\t\tfont-size: 16px;\n\t\t\tfont-weight: 600;\n\t\t\tpadding: 5px 20px;\n\t\t}\n\t}\n}\n\n.tumblr-theme-title {\n\tdisplay: block;\n\tposition: relative;\n\tbackground-color: var(--t3-background);\n\tpadding: 3px 12px 0 10px;\n\theight: 18px;\n\tline-height: 18px;\n\tfont-family: monospace;\n\tfont-size: 1em;\n\tfont-weight: 700;\n\tbox-shadow:\n\t\t-2px 4px 0 var(--t3-background),\n\t\t0 -2px 0 var(--t3-background),\n\t\t-2px 0 0 var(--t3-background),\n\t\t2px 0 0 var(--t3-background),\n\t\t4px 2px 0 var(--t3-background),\n\t\t6px 4px 0 var(--t3-background),\n\t\t8px 6px 0 var(--t3-background),\n\t\t10px 8px 0 var(--t3-background),\n\t\t12px 10px 0 var(--t3-background),\n\t\t14px 12px 0 var(--t3-background),\n\t\t16px 14px 0 var(--t3-background),\n\t\t18px 16px 0 var(--t3-background),\n\t\t20px 18px 0 var(--t3-background),\n\t\t-4px 0 0 var(--t3-text),\n\t\t0 -4px 0 var(--t3-text),\n\t\t-2px -2px 0 var(--t3-text),\n\t\t2px -2px 0 var(--t3-text),\n\t\t4px 0 0 var(--t3-text),\n\t\t6px 2px 0 var(--t3-text),\n\t\t8px 4px 0 var(--t3-text),\n\t\t10px 6px 0 var(--t3-text),\n\t\t12px 8px 0 var(--t3-text),\n\t\t14px 10px 0 var(--t3-text),\n\t\t16px 12px 0 var(--t3-text),\n\t\t18px 14px 0 var(--t3-text),\n\t\t20px 16px 0 var(--t3-text);\n}\n\n.tumblr-theme-footer {\n\tposition: relative;\n\ttext-align: right;\n\tmargin: 10px 0 0;\n\tpadding: 0;\n\twidth: 100%;\n\n\ta {\n\t\t@include rainbow-button;\n\n\t\t&:hover {\n\t\t\t@include rainbow-button-hover;\n\t\t}\n\t}\n}\n\n#t3-categories {\n\tmargin: 10px;\n}\n\n#t3-category-select-form {\n\tdisplay: inline;\n}\n\n@keyframes play {\n\t100% {\n\t\tbackground-position: -90px top;\n\t}\n}\n\n#theme-garden-heading {\n\tdisplay: flex;\n\talign-items: center;\n}\n\n.tumblr-logo-icon {\n\twidth: 30px;\n\tmargin: 0 12px;\n}\n\n.tumblr-theme-garden-list-item {\n\tpadding: 4px 10px;\n\tbackground: #000;\n\tborder-radius: 6px;\n}\n\n.tumblr-theme-garden-link {\n\tcursor: pointer;\n\tborder: none;\n\toutline: none;\n\twidth: 80px;\n\theight: 16px;\n\tmask-image: url(../../images/tumblr-logo.png) ;\n\tbackground: repeating-linear-gradient(\n\t\t\t90deg,\n\t\t\tvar(--t3-red) 0%,\n\t\t\tvar(--t3-orange),\n\t\t\tvar(--t3-yellow),\n\t\t\tvar(--t3-green),\n\t\t\tvar(--t3-violet),\n\t\t\tvar(--t3-red) 50%\n\t);\n}\n\n.tumblr-theme-garden-link:hover {\n\tanimation: play 1.5s linear infinite;\n}\n\n#tumblr-no-themes {\n\tdisplay: block;\n}\n","@import \"admin/theme_garden\";\n"]} \ No newline at end of file diff --git a/assets/css/build/index.css b/assets/css/build/index.css index 841e011..ceeffe7 100644 --- a/assets/css/build/index.css +++ b/assets/css/build/index.css @@ -5,6 +5,17 @@ body > .iframe-container { body iframe[src*="https://www.tumblr.com/dashboard/iframe"] { display: none; } +body div.jetpack-likes-widget-wrapper.t3-likes { + min-height: 0px; + position: static; +} +body div.jetpack-likes-widget-wrapper.t3-likes .likes-widget-placeholder.post-likes-widget-placeholder { + display: none; +} +body div.jetpack-likes-widget-wrapper.t3-likes iframe { + width: 20px !important; + height: 20px !important; +} p.npf_quote { font-family: Georgia, Times, "Times New Roman", serif; @@ -297,4 +308,4 @@ body div.npf_row + div.npf_row { font-size: 0.875em; line-height: 1.5; } -/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5zY3NzJTIzc2FzcyIsIi4uL3NyYy9mcm9udGVuZC9fZ2xvYmFsLnNjc3MiLCIuLi9zcmMvaW5kZXguc2NzcyIsIi4uL3NyYy9mcm9udGVuZC9fdGV4dC5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL192YXJpYWJsZXMuc2NzcyIsIi4uL3NyYy9mcm9udGVuZC9fbGluay5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL192aWRlby5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL19pbWFnZS5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL19hdWRpby5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGlHQUFBO0FDQ0M7RUNDRCxhQUFBO0FBQ0E7QURFQztFQ0FELGFBQUE7QUFDQTs7QUNEQTtFQUNDLHFEQUFBO0VBQ0EsZUFBQTtBRElEOztBQ0RBO0VBQ0MsNkJBQUE7RUFDQSxlQ29CNEI7RURuQjVCLGtCQ29COEI7QUZoQi9COztBQ0RBO0VBQ0MseUNBQUE7QURJRDs7QUNEQTs7RUFFQyxjQ3FEWTtBRmpEYjs7QUNEQTs7RUFFQyxjQ2lEYztBRjdDZjs7QUNEQTs7RUFFQyxjQzZDYztBRnpDZjs7QUNEQTs7RUFFQyxjQ3lDWTtBRnJDYjs7QUNEQTs7RUFFQyxjQ3FDYztBRmpDZjs7QUNEQTs7RUFFQyxjQ2lDZ0I7QUY3QmpCOztBQ0RBOztFQUVDLGNDK0JhO0FGM0JkOztBQ0RBOztFQUVDLGNDS3dCO0FGRHpCOztBQ0RBOztFQUVDLGNDc0JjO0FGbEJmOztBR3ZEQTtFQUNDLG1CQUFBO0VBQ0EsdUNBQUE7RUFDQSxrQkFBQTtFQUNBLGFBQUE7RUFDQSx1QkFBQTtFQUNBLGNBQUE7RUFDQSxnQkFBQTtBSDBERDtBR3hEQztFQUNDLGNBQUE7RUFDQSxXQUFBO0VBQ0EscUJBQUE7QUgwREY7QUd2REM7RUFDQyxlQUFBO0VBQ0EsaUJBMUJrQjtFQTJCbEIsaUJBQUE7RUF2QkQsZ0JBQUE7RUFDQSx1QkFBQTtFQUNBLHVCQUFBO0FIaUZEO0FHdkRDO0VBQ0Msb0JBQUE7QUh5REY7QUd0REM7RUFDQyxtQkFBQTtFQUNBLDJCQUFBO0VBQ0EsNEJBQUE7RUFDQSxzQkFBQTtFQUNBLDRCQUFBO0VBQ0EsOENBQUE7RUFDQSxhQUFBO0VBQ0EsYUFBQTtFQUNBLHVCQUFBO0VBQ0Esa0JBQUE7QUh3REY7QUd0REU7RUFDQyxnQkRRVztFQ1BYLFdBQUE7RUFDQSxjQUFBO0VBQ0EsWUFBQTtFQUNBLFlBQUE7RUFDQSxrQkFBQTtFQUNBLFdBQUE7QUh3REg7QUdyREU7RUFDQyxXREhXO0VDSVgsZ0JBQUE7RUFDQSxrQkFBQTtFQUNBLGtCQUFBO0VBQ0Esa0JBQUE7QUh1REg7QUduREM7RUFDQyxjQUFBO0VBQ0EsaUJBQUE7RUFDQSxzQkFBQTtBSHFERjtBR25ERTtFQUNDLGNBQUE7RUFDQSxlQUFBO0VBQ0EsaUJBMUV1QjtFQTJFdkIsU0FBQTtFQUNBLGdCQUFBO0VBekVGLGdCQUFBO0VBQ0EsdUJBQUE7RUFDQSx1QkFBQTtBSCtIRDtBR25ERTtFQUNDLGNBQUE7RUFDQSxpQkFBQTtFQUNBLGdCQUFBO0VBQ0EsaUJBQUE7RUFDQSxnQkFBQTtFQUNBLGFBQUE7RUFDQSx5QkFBQTtBSHFESDs7QUkvSUE7Ozs7O0VBS0MsZUFBQTtBSmtKRDs7QUkvSUE7RUFDQyxZQUFBO0VBQ0EsV0FBQTtBSmtKRDs7QUt0Skk7OztFQUNJLG9CQUFBO0VBQ0EsYUFBQTtFQUNBLGFBQUE7RUFDQSxnQkFBQTtBTDJKUjtBS3pKUTs7O0VBQ0ksT0FBQTtFQUNBLDhCQUFBO0VBQ0EsU0FBQTtFQUNBLGtCQUFBO0FMNkpaO0FLMUpROzs7Ozs7RUFFSSxhQUFBO0VBQ0Esc0JBQUE7RUFDQSxpQkFBQTtFQUNBLGtCQUFBO0FMZ0taO0FLOUpZOzs7Ozs7RUFDSSxlQUFBO0FMcUtoQjtBS2xLWTs7Ozs7O0VBQ0ksZ0JBQUE7QUx5S2hCO0FLcktROzs7RUFDSSxZQUFBO0FMeUtaO0FLdEtROzs7RUFDSSxPQUFBO0FMMEtaO0FLeEtZOzs7RUFDSSxrQkFBQTtFQUNBLFdBQUE7RUFDQSxTQUFBO0VBQ0EsZ0JBQUE7QUw0S2hCO0FLMUtnQjs7O0VBQ0ksV0FBQTtFQUNBLFlBQUE7RUFDQSxpQkFBQTtBTDhLcEI7QUszS2dCOzs7RUFDSSxzQkFBQTtFQUNBLFdBQUE7QUwrS3BCO0FLektJOzs7RUFDSSxlQUFBO0FMNktSO0FLMUtJOzs7RUFDSSxlQUFBO0VBQ0EsT0FBQTtFQUNBLHFCQUFBO0FMOEtSO0FLM0tJOzs7Ozs7RUFFSSxnQkFBQTtBTGlMUjtBSzdLSTs7Ozs7O0VBRUksZ0JBQUE7QUxtTFI7QUsvS0k7Ozs7OztFQUVJLGVBQUE7QUxxTFI7O0FNNVFBO0VBQ0ksV0FBQTtBTitRSjs7QU01UUE7RUFDSSxhQUFBO0VBQ0EsbUJBQUE7QU4rUUo7QU03UUk7RUFDSSxXQUFBO0VBQ0EsWUFBQTtBTitRUjtBTTVRSTtFQUNJLGFBQUE7RUFDQSxjQUFBO0VBQ0Esc0JBQUE7RUFDQSx1QkFBQTtFQUNBLHVCQUFBO0VBQ0EsZUFBQTtBTjhRUjtBTTNRSTtFQUNJLGlCQUFBO0VBQ0EsZ0JBQUE7QU42UVI7QU0xUUk7O0VBRUksa0JBQUE7RUFDQSxnQkFBQTtBTjRRUiIsImZpbGUiOiJpbmRleC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBodHRwczovL2dpdGh1Yi50dW1ibHIubmV0L1R1bWJsci90dW1ibHIvdHJlZS9tYXN0ZXIvY2xpZW50L3N0YW5kYWxvbmUvYmxvZy1uZXR3b3JrLW5wZi9zdHlsZXMqL1xuQGltcG9ydCBcImZyb250ZW5kL3ZhcmlhYmxlc1wiO1xuQGltcG9ydCBcImZyb250ZW5kL2dsb2JhbFwiO1xuQGltcG9ydCBcImZyb250ZW5kL3RleHRcIjtcbkBpbXBvcnQgXCJmcm9udGVuZC9saW5rXCI7XG5AaW1wb3J0IFwiZnJvbnRlbmQvdmlkZW9cIjtcbkBpbXBvcnQgXCJmcm9udGVuZC9pbWFnZVwiO1xuQGltcG9ydCBcImZyb250ZW5kL2F1ZGlvXCI7XG4iLCJib2R5IHtcblx0PiAuaWZyYW1lLWNvbnRhaW5lciB7XG5cdFx0ZGlzcGxheTogbm9uZTtcblx0fVxuXG5cdGlmcmFtZVtzcmMqPVwiaHR0cHM6Ly93d3cudHVtYmxyLmNvbS9kYXNoYm9hcmQvaWZyYW1lXCJdIHtcblx0XHRkaXNwbGF5OiBub25lO1xuXHR9XG59IiwiLy8gaHR0cHM6Ly9naXRodWIudHVtYmxyLm5ldC9UdW1ibHIvdHVtYmxyL3RyZWUvbWFzdGVyL2NsaWVudC9zdGFuZGFsb25lL2Jsb2ctbmV0d29yay1ucGYvc3R5bGVzXG5AaW1wb3J0IFwiZnJvbnRlbmQvdmFyaWFibGVzXCI7XG5AaW1wb3J0IFwiZnJvbnRlbmQvZ2xvYmFsXCI7XG5AaW1wb3J0IFwiZnJvbnRlbmQvdGV4dFwiO1xuQGltcG9ydCBcImZyb250ZW5kL2xpbmtcIjtcbkBpbXBvcnQgXCJmcm9udGVuZC92aWRlb1wiO1xuQGltcG9ydCBcImZyb250ZW5kL2ltYWdlXCI7XG5AaW1wb3J0IFwiZnJvbnRlbmQvYXVkaW9cIjtcbiIsIi8vIE5QRiB0ZXh0IGJsb2NrIHN0eWxlcyAtIG5hbWVseSwgdG8gYWRkIE5QRiBjb2xvcnMuXG5cbi8vIERpc2FibGVkIFNlbGVjdG9yRm9ybWF0IHRvIHVzZSB1bmRlcnNjb3JlZCBzZWxlY3RvciBuYW1lc1xuLy8gc2Nzcy1saW50OmRpc2FibGUgU2VsZWN0b3JGb3JtYXRcblxucC5ucGZfcXVvdGUge1xuXHRmb250LWZhbWlseTogR2VvcmdpYSwgVGltZXMsIFwiVGltZXMgTmV3IFJvbWFuXCIsIHNlcmlmO1xuXHRmb250LXNpemU6IDIzcHg7XG59XG5cbnAubnBmX3F1aXJreSB7XG5cdGZvbnQtZmFtaWx5OiBGYWlyd2F0ZXIsIHNlcmlmO1xuXHRmb250LXNpemU6ICRmb250LXNpemUtcG9zdC10ZXh0LXF1aXJreTtcblx0bGluZS1oZWlnaHQ6ICRsaW5lLWhlaWdodC1wb3N0LXRleHQtcXVpcmt5O1xufVxuXG5wLm5wZl9jaGF0IHtcblx0Zm9udC1mYW1pbHk6IFwiU291cmNlIENvZGUgUHJvXCIsIG1vbm9zcGFjZTtcbn1cblxucC5ucGZfY29sb3Jfam9leSxcbnNwYW4ubnBmX2NvbG9yX2pvZXkge1xuXHRjb2xvcjogJGNvbG9yLWpvZXk7XG59XG5cbnAubnBmX2NvbG9yX21vbmljYSxcbnNwYW4ubnBmX2NvbG9yX21vbmljYSB7XG5cdGNvbG9yOiAkY29sb3ItbW9uaWNhO1xufVxuXG5wLm5wZl9jb2xvcl9waG9lYmUsXG5zcGFuLm5wZl9jb2xvcl9waG9lYmUge1xuXHRjb2xvcjogJGNvbG9yLXBob2ViZTtcbn1cblxucC5ucGZfY29sb3Jfcm9zcyxcbnNwYW4ubnBmX2NvbG9yX3Jvc3Mge1xuXHRjb2xvcjogJGNvbG9yLXJvc3M7XG59XG5cbnAubnBmX2NvbG9yX3JhY2hlbCxcbnNwYW4ubnBmX2NvbG9yX3JhY2hlbCB7XG5cdGNvbG9yOiAkY29sb3ItcmFjaGVsO1xufVxuXG5wLm5wZl9jb2xvcl9jaGFuZGxlcixcbnNwYW4ubnBmX2NvbG9yX2NoYW5kbGVyIHtcblx0Y29sb3I6ICRjb2xvci1jaGFuZGxlcjtcbn1cblxucC5ucGZfY29sb3JfbmlsZXMsXG5zcGFuLm5wZl9jb2xvcl9uaWxlcyB7XG5cdGNvbG9yOiAkY29sb3ItbmlsZXM7XG59XG5cbnAubnBmX2NvbG9yX2ZyYXNpZXIsXG5zcGFuLm5wZl9jb2xvcl9mcmFzaWVyIHtcblx0Y29sb3I6ICRjb2xvci1mcmFzaWVyO1xufVxuXG5wLm5wZl9jb2xvcl9tcl9iaWcsXG5zcGFuLm5wZl9jb2xvcl9tcl9iaWcge1xuXHRjb2xvcjogJGNvbG9yLW1yLWJpZztcbn1cbiIsIkB1c2UgXCJzYXNzOm1hdGhcIjtcblxuJHBvc3QtZnVsbC13aWR0aDogNTQwcHg7XG4kcG9zdC1mdWxsLXJhZGl1czogM3B4O1xuJHBvc3QtZnVsbC12LXBhZGRpbmc6IDE1cHg7XG4kcG9zdC1mdWxsLWgtcGFkZGluZzogMjBweDtcbiRwb3N0LWZ1bGwtbm90ZS1pdGVtLWgtcGFkZGluZzogMTRweDtcbiRjb2xvci1wb3N0LW1lbWJlcnMtb25seTogIzkwMDAyMDtcblxuJGZvbnQtc2l6ZS1jb250ZW50OiAxNHB4O1xuJGxpbmUtaGVpZ2h0LWNvbnRlbnQ6IG1hdGgucm91bmQoMS41ICogJGZvbnQtc2l6ZS1jb250ZW50KTtcblxuLy8gdGhvc2UgbWF0Y2ggTlBGIGhlYWRpbmcgc2l6ZSBiZXR0ZXJcbiRmb250LXNpemUtY29udGVudC1oZWFkaW5nMTogMjZweDtcbiRsaW5lLWhlaWdodC1jb250ZW50LWhlYWRpbmcxOiBtYXRoLnJvdW5kKDEuMyAqICRmb250LXNpemUtY29udGVudC1oZWFkaW5nMSk7XG4kZm9udC1zaXplLWNvbnRlbnQtaGVhZGluZzI6IDIwcHg7XG4kbGluZS1oZWlnaHQtY29udGVudC1oZWFkaW5nMjogbWF0aC5yb3VuZCgxLjMgKiAkZm9udC1zaXplLWNvbnRlbnQtaGVhZGluZzIpO1xuXG4kZm9udC1zaXplLWNvbnRlbnQtaGVhZGluZy1tZWRpdW06IDMwcHg7XG4kbGluZS1oZWlnaHQtY29udGVudC1oZWFkaW5nLW1lZGl1bTogbWF0aC5yb3VuZCgxLjMgKiAkZm9udC1zaXplLWNvbnRlbnQtaGVhZGluZy1tZWRpdW0pO1xuJGZvbnQtc2l6ZS1jb250ZW50LWhlYWRpbmctbGFyZ2U6IDM2cHg7XG4kbGluZS1oZWlnaHQtY29udGVudC1oZWFkaW5nLWxhcmdlOiBtYXRoLnJvdW5kKDEuMyAqICRmb250LXNpemUtY29udGVudC1oZWFkaW5nLWxhcmdlKTtcblxuJGZvbnQtc2l6ZS1wcmU6IDExcHg7XG4kbGluZS1oZWlnaHQtcHJlOiAkZm9udC1zaXplLXByZTtcblxuJGZvbnQtc2l6ZS1pY29uOiAyNHB4O1xuJGxpbmUtaGVpZ2h0LWljb246IDI0cHg7XG5cbiRmb250LXNpemUtYmFzZTogJGZvbnQtc2l6ZS1jb250ZW50O1xuJGxpbmUtaGVpZ2h0LWJhc2U6IDEuNDtcblxuJGZvbnQtc2l6ZS1wb3N0LXRleHQtcXVpcmt5OiAyNHB4O1xuJGxpbmUtaGVpZ2h0LXBvc3QtdGV4dC1xdWlya3k6IDEuM2VtO1xuXG4vLyBUaGVzZSBvbWl0IGBzZXJpZmAgYW5kIGBzYW5zLXNlcmZgIHRvIG1ha2UgaXRcbi8vIHBvc3NpYmxlIHRvIHNwbGljZSBpbiBhZGRpdGlvbmFsIGZhbGxiYWNrc1xuJGZvbnQtZmFtaWx5LXNhbnMtZmFjZTogXCJIZWx2ZXRpY2EgTmV1ZVwiLCBcIkhlbHZldGljYU5ldWVcIiwgaGVsdmV0aWNhLCBhcmlhbDtcbiRmb250LWZhbWlseS1zZXJpZi1mYWNlOiBnZW9yZ2lhLCB0aW1lcywgXCJUaW1lcyBOZXcgUm9tYW5cIjtcbiRmb250LWZhbWlseS1tb25vc3BhY2UtZmFjZTogY291cmllcjtcblxuLy8gU3RhbmRhcmQgZmFjZXNcbiRmb250LWZhbWlseS1zYW5zOiAkZm9udC1mYW1pbHktc2Fucy1mYWNlLCBzYW5zLXNlcmlmO1xuJGZvbnQtZmFtaWx5LXNlcmlmOiBnZW9yZ2lhLCB0aW1lcywgXCJUaW1lcyBOZXcgUm9tYW5cIiwgc2VyaWY7XG4kZm9udC1mYW1pbHktbW9ub3NwYWNlOiAkZm9udC1mYW1pbHktbW9ub3NwYWNlLWZhY2UsIG1vbm9zcGFjZTtcbiRmb250LWZhbWlseS1rb3JlYW46ICRmb250LWZhbWlseS1zYW5zLWZhY2UsIFwiQXBwbGVHb3RoaWNcIiwgXCJNYWxndW4gR290aGljXCIsIFwiRG90dW1cIiwgXCJHdWxpbVwiLCBzYW5zLXNlcmlmO1xuXG4vLyBOYW1lZCBmYWNlc1xuJGZvbnQtZmFtaWx5LWdpYnNvbjogXCJHaWJzb25cIiwgJGZvbnQtZmFtaWx5LXNhbnM7XG4kZm9udC1mYW1pbHktd2Fsc2hlaW06IFwiV2Fsc2hlaW1cIiwgXCJIZWx2ZXRpY2EgTmV1ZVwiLCBcIkhlbHZldGljYU5ldWVcIiwgaGVsdmV0aWNhLCBhcmlhbCwgc2Fucy1zZXJpZjtcbiRmb250LWZhbWlseS1mcmFua2xpbi1tZWRpdW06IFwiRnJhbmtsaW4gR290aGljIE1lZGl1bVwiLCAkZm9udC1mYW1pbHktc2FucztcbiRmb250LWZhbWlseS1mcmFua2xpbi1tZWRpdW0tY29uZGVuc2VkOiBcIkZyYW5rbGluIEdvdGhpYyBNZWRpdW0gQ29uZGVuc2VkXCIsICRmb250LWZhbWlseS1zYW5zO1xuJGZvbnQtZmFtaWx5LWZyYW5rbGluLWNvbXByZXNzZWQ6IFwiRnJhbmtsaW4gR290aGljIENvbXByZXNzZWRcIiwgJGZvbnQtZmFtaWx5LXNhbnM7XG4kZm9udC1mYW1pbHktc291cmNlLWNvZGUtcHJvOiBcIlNvdXJjZSBDb2RlIFByb1wiLCAkZm9udC1mYW1pbHktbW9ub3NwYWNlO1xuXG4vLyBEZWZhdWx0IFwiYXBwXCIgZm9udCBmYW1pbHlcbiRmb250LWZhbWlseS1iYXNlOiAkZm9udC1mYW1pbHktc2FucztcblxuJGNvbG9yLXdoaXRlOiAjZmZmO1xuJGNvbG9yLWJsYWNrOiAjMDAwO1xuJGNvbG9yLXR1bWJsci1ibGFjazogIzQ0NDtcbiRjb2xvci10dW1ibHItYmx1ZTogIzM2NDY1ZDtcbiRjb2xvci10dW1ibHItZGFyay1ibHVlOiAjMDAxOTM1O1xuXG4kY29sb3ItZGFuay1zbW9rZTogIzlkYTZhZjtcbiRjb2xvci1nbG9vbXktY2xvdWQ6ICM3NDgwODk7XG4vLyBUaGUgYmVsb3cgaGF2ZSBOZXVlIENvbG9yIHZhcmlhbnRzXG4kY29sb3ItbGlrYWJsZS1yZWQ6ICNkOTVlNDA7XG4kY29sb3ItY2hlZXpib3J0OiAjZjI5OTJlO1xuJGNvbG9yLWFsd2F5cy1zdW5ueTogI2Y3ZGQzODtcbiRjb2xvci1yZWJsb2ctZ3JlZW46ICM1NmJjOGE7XG4kY29sb3ItbmVhdC1ibHVlOiAjNTI5ZWNjO1xuJGNvbG9yLXB1cnBsZS1yYWluOiAjYTc3ZGMyO1xuXG4vLyBUaGVzZSByZXBsYWNlIG9sZCBhY2NlbnQgY29sb3JzXG4kY29sb3Itam9leTogI2ZmNDkyZjsgLy8gUmVkXG4kY29sb3ItbW9uaWNhOiAjZmY4YTAwOyAvLyBPcmFuZ2VcbiRjb2xvci1waG9lYmU6ICNlOGQ3M2E7IC8vIFllbGxvd1xuJGNvbG9yLXJvc3M6ICMwMGNmMzU7IC8vIEdyZWVuXG4kY29sb3ItcmFjaGVsOiAjMDBiOGZmOyAvLyBMaWdodCBCbHVlXG4kY29sb3ItY2hhbmRsZXI6ICM3YzVjZmY7IC8vIFB1cnBsZVxuLy8gVGhlc2UgYXJlIG5ld1xuJGNvbG9yLWZyYXNpZXI6ICRjb2xvci10dW1ibHItZGFyay1ibHVlOyAvLyBEYXJrIEJsdWUsIG5ldyBicmFuZCBjb2xvclxuJGNvbG9yLW5pbGVzOiAjZmY2MmNlOyAvLyBQaW5rXG4kY29sb3ItbXItYmlnOiAjMDAwYzFhOyAvLyBPZmYtQmxhY2tcbiRjb2xvci1leHBsaWNpdC1yZWQ6ICNmZjQ5MzA7IC8vIHByb2plY3QgeCByZWRcblxuXG4kY29sb3ItZ3JheS0xMDA6ICRjb2xvci10dW1ibHItYmxhY2s7IC8vICM0NDQ0NDRcblxuJGNvbG9yLWdyYXktNjA6IHByaW1hLW1peCgkY29sb3ItdHVtYmxyLWJsYWNrLCAwLjYpOyAvLyAjOGY4ZjhmXG4kY29sb3ItZ3JheS00MDogcHJpbWEtbWl4KCRjb2xvci10dW1ibHItYmxhY2ssIDAuNCk7IC8vICNiNGI0YjRcbiRjb2xvci1ncmF5LTI1OiBwcmltYS1taXgoJGNvbG9yLXR1bWJsci1ibGFjaywgMC4yNSk7IC8vICNkMGQwZDBcbiRjb2xvci1ncmF5LTEzOiBwcmltYS1taXgoJGNvbG9yLXR1bWJsci1ibGFjaywgMC4xMyk7IC8vICNlN2U3ZTdcbiRjb2xvci1ncmF5LTc6IHByaW1hLW1peCgkY29sb3ItdHVtYmxyLWJsYWNrLCAwLjA3KTsgLy8gI2YyZjJmMlxuXG5cbiRjb2xvci1ncmF5LTYwLXRyYW5zcGFyZW50OiB1bm1hdHRlLWdyYXkoJGNvbG9yLWdyYXktNjApOyAvLyByZ2JhKDAsIDAsIDAsIDAuNDM5MjE2KVxuJGNvbG9yLWdyYXktNDAtdHJhbnNwYXJlbnQ6IHVubWF0dGUtZ3JheSgkY29sb3ItZ3JheS00MCk7IC8vIHJnYmEoMCwgMCwgMCwgMC4yOTQxMTgpXG4kY29sb3ItZ3JheS0yNS10cmFuc3BhcmVudDogdW5tYXR0ZS1ncmF5KCRjb2xvci1ncmF5LTI1KTsgLy8gcmdiYSgwLCAwLCAwLCAwLjE4NDMxNClcbiRjb2xvci1ncmF5LTEzLXRyYW5zcGFyZW50OiB1bm1hdHRlLWdyYXkoJGNvbG9yLWdyYXktMTMpOyAvLyByZ2JhKDAsIDAsIDAsIDAuMDk0MTE3NilcbiRjb2xvci1ncmF5LTctdHJhbnNwYXJlbnQ6IHVubWF0dGUtZ3JheSgkY29sb3ItZ3JheS03KTsgLy8gcmdiYSgwLCAwLCAwLCAwLjA1MDk4MDQpXG5cblxuJGNvbG9yLXdoaXRlLTYwLXRyYW5zcGFyZW50OiBwcmltYS1taXgoJGNvbG9yLXdoaXRlLCAwLjYsIHRyYW5zcGFyZW50KTsgLy8gcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjYpO1xuJGNvbG9yLXdoaXRlLTQwLXRyYW5zcGFyZW50OiBwcmltYS1taXgoJGNvbG9yLXdoaXRlLCAwLjQsIHRyYW5zcGFyZW50KTsgLy8gcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjQpO1xuJGNvbG9yLXdoaXRlLTI1LXRyYW5zcGFyZW50OiBwcmltYS1taXgoJGNvbG9yLXdoaXRlLCAwLjI1LCB0cmFuc3BhcmVudCk7IC8vIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4yNSk7XG4kY29sb3Itd2hpdGUtMTMtdHJhbnNwYXJlbnQ6IHByaW1hLW1peCgkY29sb3Itd2hpdGUsIDAuMTMsIHRyYW5zcGFyZW50KTsgLy8gcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjEzKTtcbiRjb2xvci13aGl0ZS03LXRyYW5zcGFyZW50OiBwcmltYS1taXgoJGNvbG9yLXdoaXRlLCAwLjA3LCB0cmFuc3BhcmVudCk7IC8vIHJnYmEoMjU1LCAyNTUsIDI1NSwgMC4wNyk7XG5cblxuQG1peGluIGJyYW5kQmx1ZSgkcHJvcCkge1xuXHQjeyRwcm9wfTogJGNvbG9yLXR1bWJsci1kYXJrLWJsdWU7XG59XG5cbkBtaXhpbiBicmFuZEJsdWVHcmF5KCRwcm9wLCAkcGVyY2VudCkge1xuXHQjeyRwcm9wfTogcHJpbWEtbWl4KCRjb2xvci13aGl0ZSwgMSAtICRwZXJjZW50LCAkY29sb3ItdHVtYmxyLWRhcmstYmx1ZSk7XG59XG5cbkBtaXhpbiB0cmFuc3BhcmVudEJyYW5kQmx1ZSgkcHJvcCwgJG9wYWNpdHkpIHtcblx0I3skcHJvcH06IHJnYmEoJGNvbG9yLXR1bWJsci1kYXJrLWJsdWUsICRvcGFjaXR5KTtcbn1cblxuJGFjY2VudENvbG9yczogKFxuXHRcInJlZFwiOiAkY29sb3Itam9leSxcblx0XCJvcmFuZ2VcIjogJGNvbG9yLW1vbmljYSxcblx0XCJ5ZWxsb3dcIjogJGNvbG9yLXBob2ViZSxcblx0XCJncmVlblwiOiAkY29sb3Itcm9zcyxcblx0XCJibHVlXCI6ICRjb2xvci1yYWNoZWwsXG5cdFwicHVycGxlXCI6ICRjb2xvci1jaGFuZGxlcixcblx0XCJibGFja1wiOiAkY29sb3ItYmxhY2ssXG5cblx0XCJ2aWRlb1wiOiAkY29sb3ItbmlsZXMsXG4pO1xuXG5AZnVuY3Rpb24gbmV3QWNjZW50Q29sb3IoJGNvbG9yKSB7XG5cblx0QGlmIChub3QgbWFwX2hhc19rZXkoJGFjY2VudENvbG9ycywgJGNvbG9yKSkge1xuXG5cdFx0QGVycm9yICdVbnJlY29nbml6ZWQgYWNjZW50IGNvbG9yIFwiI3skY29sb3J9XCIgaW4gYWNjZW50Q29sb3IgbWl4aW4nO1xuXHR9XG5cblx0QHJldHVybiBtYXAtZ2V0KCRhY2NlbnRDb2xvcnMsICRjb2xvcik7XG59XG5cbkBtaXhpbiBhY2NlbnRDb2xvcigkcHJvcCwgJGNvbG9yKSB7XG5cdCN7JHByb3B9OiBuZXdhY2NlbnRjb2xvcigkY29sb3IpO1xufVxuXG5AbWl4aW4gdXBkYXRlZFdoaXRlKCRvcGFjaXR5OiAxLCAkcHJvcDogY29sb3IpIHtcblx0I3skcHJvcH06IHJnYmEoJGNvbG9yLXdoaXRlLCAkb3BhY2l0eSk7XG59XG5cbkBtaXhpbiB1cGRhdGVkQmxhY2soJG9wYWNpdHk6IDEsICRwcm9wOiBjb2xvcikge1xuXHQjeyRwcm9wfTogcmdiYSgkY29sb3ItYmxhY2ssICRvcGFjaXR5KTtcbn1cbiIsIi8vIE5QRiBsaW5rIGJsb2NrIHN0eWxlc1xuXG4kdGl0bGUtbGluZS1oZWlnaHQ6IDM0cHg7XG4kZGVzY3JpcHRpb24tbGluZS1oZWlnaHQ6IDI0cHg7XG5cbkBtaXhpbiB0ZXh0LWN1dG9mZiB7XG5cdG92ZXJmbG93OiBoaWRkZW47XG5cdG92ZXJmbG93LXdyYXA6IGFueXdoZXJlO1xuXHR0ZXh0LW92ZXJmbG93OiBlbGxpcHNpcztcbn1cblxuZGl2Lm5wZi1saW5rLWJsb2NrIHtcblx0YWxpZ24taXRlbXM6IGNlbnRlcjtcblx0Ym9yZGVyOiAxcHggc29saWQgJGNvbG9yLWdyYXktMjU7XG5cdGJvcmRlci1yYWRpdXM6IDZweDtcblx0ZGlzcGxheTogZmxleDtcblx0anVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG5cdG1hcmdpbjogMTVweCAwO1xuXHRvdmVyZmxvdzogaGlkZGVuO1xuXG5cdD4gYSB7XG5cdFx0Y29sb3I6IGluaGVyaXQ7XG5cdFx0d2lkdGg6IDEwMCU7XG5cdFx0dGV4dC1kZWNvcmF0aW9uOiBub25lO1xuXHR9XG5cblx0LnRpdGxlIHtcblx0XHRmb250LXNpemU6IDI1cHg7XG5cdFx0bGluZS1oZWlnaHQ6ICR0aXRsZS1saW5lLWhlaWdodDtcblx0XHRtYXgtaGVpZ2h0OiAkdGl0bGUtbGluZS1oZWlnaHQgKiA0OyAvLyBUaGlzIG5lZWRzIHRvIGJlIGVxdWFsIHRvIChsaW5lLWhlaWdodCAqIDQpIC0gV2Ugd2FudCB0byBzaG93IGEgbWF4aW11bSBvZiA0IGxpbmVzIGhlcmVcblxuXHRcdEBpbmNsdWRlIHRleHQtY3V0b2ZmO1xuXHR9XG5cblx0Ji5uby1wb3N0ZXIgLnRpdGxlIHtcblx0XHRwYWRkaW5nOiAxNnB4IDEycHggMDtcblx0fVxuXG5cdC5wb3N0ZXIge1xuXHRcdGFsaWduLWl0ZW1zOiBjZW50ZXI7XG5cdFx0YmFja2dyb3VuZC1wb3NpdGlvbjogY2VudGVyO1xuXHRcdGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7XG5cdFx0YmFja2dyb3VuZC1zaXplOiBjb3Zlcjtcblx0XHRiYWNrZ3JvdW5kLWNsaXA6IGNvbnRlbnQtYm94O1xuXHRcdGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAkY29sb3ItZ3JheS0yNTtcblx0XHRkaXNwbGF5OiBmbGV4O1xuXHRcdGhlaWdodDogMjUwcHg7XG5cdFx0anVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG5cdFx0cG9zaXRpb246IHJlbGF0aXZlO1xuXG5cdFx0Jjo6YmVmb3JlIHtcblx0XHRcdGJhY2tncm91bmQ6ICRjb2xvci1ibGFjaztcblx0XHRcdGNvbnRlbnQ6IFwiXCI7XG5cdFx0XHRkaXNwbGF5OiBibG9jaztcblx0XHRcdGhlaWdodDogMTAwJTtcblx0XHRcdG9wYWNpdHk6IDAuNDtcblx0XHRcdHBvc2l0aW9uOiBhYnNvbHV0ZTtcblx0XHRcdHdpZHRoOiAxMDAlO1xuXHRcdH1cblxuXHRcdC50aXRsZSB7XG5cdFx0XHRjb2xvcjogJGNvbG9yLXdoaXRlO1xuXHRcdFx0Zm9udC13ZWlnaHQ6IDQwMDtcblx0XHRcdHBhZGRpbmc6IDE2cHggMTJweDtcblx0XHRcdHBvc2l0aW9uOiBhYnNvbHV0ZTtcblx0XHRcdHRleHQtYWxpZ246IGNlbnRlcjtcblx0XHR9XG5cdH1cblxuXHQuYm90dG9tIHtcblx0XHRjb2xvcjogaW5oZXJpdDtcblx0XHRsaW5lLWhlaWdodDogMjRweDtcblx0XHRwYWRkaW5nOiA4cHggMTJweCAxNnB4O1xuXG5cdFx0LmRlc2NyaXB0aW9uIHtcblx0XHRcdGNvbG9yOiBpbmhlcml0O1xuXHRcdFx0Zm9udC1zaXplOiAxNnB4O1xuXHRcdFx0bGluZS1oZWlnaHQ6ICRkZXNjcmlwdGlvbi1saW5lLWhlaWdodDtcblx0XHRcdG1hcmdpbjogMDtcblx0XHRcdG1heC1oZWlnaHQ6ICRkZXNjcmlwdGlvbi1saW5lLWhlaWdodCAqIDI7IC8vIFRoaXMgbmVlZHMgdG8gYmUgZXF1YWwgdG8gKGxpbmUtaGVpZ2h0ICogMikgLSBXZSB3YW50IHRvIHNob3cgYSBtYXhpbXVtIG9mIDIgbGluZXMgaGVyZVxuXG5cdFx0XHRAaW5jbHVkZSB0ZXh0LWN1dG9mZjtcblx0XHR9XG5cblx0XHQuc2l0ZS1uYW1lIHtcblx0XHRcdGNvbG9yOiBpbmhlcml0O1xuXHRcdFx0Zm9udC1zaXplOiAxMi41cHg7XG5cdFx0XHRmb250LXdlaWdodDogNDAwO1xuXHRcdFx0bGluZS1oZWlnaHQ6IDE4cHg7XG5cdFx0XHRtYXJnaW4tdG9wOiAxMHB4O1xuXHRcdFx0b3BhY2l0eTogMC42NTtcblx0XHRcdHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7XG5cdFx0fVxuXHR9XG59XG4iLCIvLyBOUEYgdmlkZW8gYmxvY2sgc3R5bGVzXG52aWRlbyxcbmF1ZGlvLFxuaW1nLFxuLndwLWNhcHRpb24sXG5pZnJhbWUge1xuXHRtYXgtd2lkdGg6IDEwMCU7XG59XG5cbi50bWJsci1mdWxsID4gdmlkZW8ge1xuXHRoZWlnaHQ6IDEwMCU7XG5cdHdpZHRoOiAxMDAlO1xufVxuIiwiLy8gTlBGIGltYWdlIGJsb2NrIHN0eWxlcyAtIG1vc3QgaW1wb3J0YW50bHksIHRvIHJlbmRlciBOUEYtY3JlYXRlZCBwaG90b3NldHMuXG4vLyBzdHlsZWxpbnQtZGlzYWJsZSBuby1kZXNjZW5kaW5nLXNwZWNpZmljaXR5IC0tIHVubmVjZXNzYXJ5LlxuXG4ucG9zdCxcbi5wb3N0LWNvbnRlbnQsXG5ib2R5IHtcbiAgICAvLyBOUEYgcGhvdG9zZXQgd3JhcHBlclxuICAgIGRpdi5ucGZfcm93IHtcbiAgICAgICAgYWxpZ24taXRlbXM6IHN0cmV0Y2g7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIG1hcmdpbi10b3A6IDA7XG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG5cbiAgICAgICAgZmlndXJlLnRtYmxyLWZ1bGwge1xuICAgICAgICAgICAgZmxleDogMTtcbiAgICAgICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICAgICAgICAgIG1hcmdpbjogMDtcbiAgICAgICAgICAgIG92ZXJmbG93LXk6IGhpZGRlbjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZpZ3VyZS50bWJsci1mdWxsLFxuICAgICAgICAubnBmX2NvbCB7XG4gICAgICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgICAgICAgIHBhZGRpbmctbGVmdDogMnB4O1xuICAgICAgICAgICAgcGFkZGluZy1yaWdodDogMnB4O1xuXG4gICAgICAgICAgICAmOmZpcnN0LWNoaWxkIHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nLWxlZnQ6IDA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICY6bGFzdC1jaGlsZCB7XG4gICAgICAgICAgICAgICAgcGFkZGluZy1yaWdodDogMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGltZyB7XG4gICAgICAgICAgICBoZWlnaHQ6IGF1dG87XG4gICAgICAgIH1cblxuICAgICAgICAubnBmX2NvbCB7XG4gICAgICAgICAgICBmbGV4OiAxO1xuXG4gICAgICAgICAgICBmaWd1cmUge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcbiAgICAgICAgICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgICAgICAgICBtYXJnaW46IDA7XG4gICAgICAgICAgICAgICAgdGV4dC1hbGlnbjogbGVmdDtcblxuICAgICAgICAgICAgICAgIGltZyB7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC1maXQ6IGNvdmVyO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHAudG1ibHItYXR0cmlidXRpb24ge1xuICAgICAgICAgICAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAgICAgICAgICAgICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmaWd1cmVbZGF0YS1lbmFibGUtbGlnaHRib3g9XCIxXCJdIHtcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgIH1cblxuICAgIGEucG9zdF9tZWRpYV9waG90b19hbmNob3Ige1xuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICAgIGZsZXg6IDE7XG4gICAgICAgIHRleHQtZGVjb3JhdGlvbjogbm9uZTtcbiAgICB9XG5cbiAgICBwICsgZGl2Lm5wZl9yb3csXG4gICAgZGl2Lm5wZl9yb3cgKyBwIHtcbiAgICAgICAgbWFyZ2luLXRvcDogMTVweDtcbiAgICB9XG5cbiAgICAvLyBBZGQgYSBtYXJnaW4gaWYgZm9sbG93aW5nL3ByZWNlZGluZyBhIHZpZGVvXG4gICAgLmNydC12aWRlbyArIGRpdi5ucGZfcm93LFxuICAgIGRpdi5ucGZfcm93ICsgLmNydC12aWRlbyB7XG4gICAgICAgIG1hcmdpbi10b3A6IDE1cHg7XG4gICAgfVxuXG4gICAgLy8gSG9yaXpvbnRhbCBtYXJnaW5zIGJldHdlZW4gcGhvdG9zZXQgcm93c1xuICAgIGRpdi5ucGZfcm93ICsgZmlndXJlLnRtYmxyLWZ1bGwsXG4gICAgZGl2Lm5wZl9yb3cgKyBkaXYubnBmX3JvdyB7XG4gICAgICAgIG1hcmdpbi10b3A6IDRweDtcbiAgICB9XG59XG4iLCIudG1ibHItZnVsbCA+IGF1ZGlvIHtcbiAgICB3aWR0aDogMTAwJTtcbn1cblxuLnRtYmxyLWZ1bGwgPiAuYXVkaW8tY2FwdGlvbiB7XG4gICAgZGlzcGxheTogZmxleDtcbiAgICBmbGV4LWRpcmVjdGlvbjogcm93O1xuXG4gICAgLmFsYnVtLWNvdmVyIHtcbiAgICAgICAgd2lkdGg6IDg1cHg7XG4gICAgICAgIGhlaWdodDogODVweDtcbiAgICB9XG5cbiAgICAuYXVkaW8tZGV0YWlscyB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXg6IDEgMCBhdXRvO1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgICAgYWxpZ24taXRlbXM6IGZsZXgtc3RhcnQ7XG4gICAgICAgIHBhZGRpbmc6IDAgMjBweDtcbiAgICB9XG5cbiAgICAudGl0bGUge1xuICAgICAgICBmb250LXdlaWdodDogYm9sZDtcbiAgICAgICAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgICB9XG5cbiAgICAuYXJ0aXN0LFxuICAgIC5hbGJ1bSB7XG4gICAgICAgIGZvbnQtc2l6ZTogMC44NzVlbTtcbiAgICAgICAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgICB9XG59XG4iXX0= */ \ No newline at end of file +/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC5zY3NzJTIzc2FzcyIsIi4uL3NyYy9mcm9udGVuZC9fZ2xvYmFsLnNjc3MiLCIuLi9zcmMvaW5kZXguc2NzcyIsIi4uL3NyYy9mcm9udGVuZC9fdGV4dC5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL192YXJpYWJsZXMuc2NzcyIsIi4uL3NyYy9mcm9udGVuZC9fbGluay5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL192aWRlby5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL19pbWFnZS5zY3NzIiwiLi4vc3JjL2Zyb250ZW5kL19hdWRpby5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGlHQUFBO0FDQ0M7RUNDRCxhQUFBO0FBQ0E7QURFQztFQ0FELGFBQUE7QUFDQTtBREdDO0VBQ0MsZUFBQTtFQUNBLGdCQUFBO0FDREY7QURHRTtFQUNDLGFBQUE7QUNESDtBRElFO0VBQ0Msc0JBQUE7RUFDQSx1QkFBQTtBQ0ZIOztBQ1pBO0VBQ0MscURBQUE7RUFDQSxlQUFBO0FEZUQ7O0FDWkE7RUFDQyw2QkFBQTtFQUNBLGVDb0I0QjtFRG5CNUIsa0JDb0I4QjtBRkwvQjs7QUNaQTtFQUNDLHlDQUFBO0FEZUQ7O0FDWkE7O0VBRUMsY0NxRFk7QUZ0Q2I7O0FDWkE7O0VBRUMsY0NpRGM7QUZsQ2Y7O0FDWkE7O0VBRUMsY0M2Q2M7QUY5QmY7O0FDWkE7O0VBRUMsY0N5Q1k7QUYxQmI7O0FDWkE7O0VBRUMsY0NxQ2M7QUZ0QmY7O0FDWkE7O0VBRUMsY0NpQ2dCO0FGbEJqQjs7QUNaQTs7RUFFQyxjQytCYTtBRmhCZDs7QUNaQTs7RUFFQyxjQ0t3QjtBRlV6Qjs7QUNaQTs7RUFFQyxjQ3NCYztBRlBmOztBR2xFQTtFQUNDLG1CQUFBO0VBQ0EsdUNBQUE7RUFDQSxrQkFBQTtFQUNBLGFBQUE7RUFDQSx1QkFBQTtFQUNBLGNBQUE7RUFDQSxnQkFBQTtBSHFFRDtBR25FQztFQUNDLGNBQUE7RUFDQSxXQUFBO0VBQ0EscUJBQUE7QUhxRUY7QUdsRUM7RUFDQyxlQUFBO0VBQ0EsaUJBMUJrQjtFQTJCbEIsaUJBQUE7RUF2QkQsZ0JBQUE7RUFDQSx1QkFBQTtFQUNBLHVCQUFBO0FINEZEO0FHbEVDO0VBQ0Msb0JBQUE7QUhvRUY7QUdqRUM7RUFDQyxtQkFBQTtFQUNBLDJCQUFBO0VBQ0EsNEJBQUE7RUFDQSxzQkFBQTtFQUNBLDRCQUFBO0VBQ0EsOENBQUE7RUFDQSxhQUFBO0VBQ0EsYUFBQTtFQUNBLHVCQUFBO0VBQ0Esa0JBQUE7QUhtRUY7QUdqRUU7RUFDQyxnQkRRVztFQ1BYLFdBQUE7RUFDQSxjQUFBO0VBQ0EsWUFBQTtFQUNBLFlBQUE7RUFDQSxrQkFBQTtFQUNBLFdBQUE7QUhtRUg7QUdoRUU7RUFDQyxXREhXO0VDSVgsZ0JBQUE7RUFDQSxrQkFBQTtFQUNBLGtCQUFBO0VBQ0Esa0JBQUE7QUhrRUg7QUc5REM7RUFDQyxjQUFBO0VBQ0EsaUJBQUE7RUFDQSxzQkFBQTtBSGdFRjtBRzlERTtFQUNDLGNBQUE7RUFDQSxlQUFBO0VBQ0EsaUJBMUV1QjtFQTJFdkIsU0FBQTtFQUNBLGdCQUFBO0VBekVGLGdCQUFBO0VBQ0EsdUJBQUE7RUFDQSx1QkFBQTtBSDBJRDtBRzlERTtFQUNDLGNBQUE7RUFDQSxpQkFBQTtFQUNBLGdCQUFBO0VBQ0EsaUJBQUE7RUFDQSxnQkFBQTtFQUNBLGFBQUE7RUFDQSx5QkFBQTtBSGdFSDs7QUkxSkE7Ozs7O0VBS0MsZUFBQTtBSjZKRDs7QUkxSkE7RUFDQyxZQUFBO0VBQ0EsV0FBQTtBSjZKRDs7QUtqS0k7OztFQUNJLG9CQUFBO0VBQ0EsYUFBQTtFQUNBLGFBQUE7RUFDQSxnQkFBQTtBTHNLUjtBS3BLUTs7O0VBQ0ksT0FBQTtFQUNBLDhCQUFBO0VBQ0EsU0FBQTtFQUNBLGtCQUFBO0FMd0taO0FLcktROzs7Ozs7RUFFSSxhQUFBO0VBQ0Esc0JBQUE7RUFDQSxpQkFBQTtFQUNBLGtCQUFBO0FMMktaO0FLektZOzs7Ozs7RUFDSSxlQUFBO0FMZ0xoQjtBSzdLWTs7Ozs7O0VBQ0ksZ0JBQUE7QUxvTGhCO0FLaExROzs7RUFDSSxZQUFBO0FMb0xaO0FLakxROzs7RUFDSSxPQUFBO0FMcUxaO0FLbkxZOzs7RUFDSSxrQkFBQTtFQUNBLFdBQUE7RUFDQSxTQUFBO0VBQ0EsZ0JBQUE7QUx1TGhCO0FLckxnQjs7O0VBQ0ksV0FBQTtFQUNBLFlBQUE7RUFDQSxpQkFBQTtBTHlMcEI7QUt0TGdCOzs7RUFDSSxzQkFBQTtFQUNBLFdBQUE7QUwwTHBCO0FLcExJOzs7RUFDSSxlQUFBO0FMd0xSO0FLckxJOzs7RUFDSSxlQUFBO0VBQ0EsT0FBQTtFQUNBLHFCQUFBO0FMeUxSO0FLdExJOzs7Ozs7RUFFSSxnQkFBQTtBTDRMUjtBS3hMSTs7Ozs7O0VBRUksZ0JBQUE7QUw4TFI7QUsxTEk7Ozs7OztFQUVJLGVBQUE7QUxnTVI7O0FNdlJBO0VBQ0ksV0FBQTtBTjBSSjs7QU12UkE7RUFDSSxhQUFBO0VBQ0EsbUJBQUE7QU4wUko7QU14Ukk7RUFDSSxXQUFBO0VBQ0EsWUFBQTtBTjBSUjtBTXZSSTtFQUNJLGFBQUE7RUFDQSxjQUFBO0VBQ0Esc0JBQUE7RUFDQSx1QkFBQTtFQUNBLHVCQUFBO0VBQ0EsZUFBQTtBTnlSUjtBTXRSSTtFQUNJLGlCQUFBO0VBQ0EsZ0JBQUE7QU53UlI7QU1yUkk7O0VBRUksa0JBQUE7RUFDQSxnQkFBQTtBTnVSUiIsImZpbGUiOiJpbmRleC5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBodHRwczovL2dpdGh1Yi50dW1ibHIubmV0L1R1bWJsci90dW1ibHIvdHJlZS9tYXN0ZXIvY2xpZW50L3N0YW5kYWxvbmUvYmxvZy1uZXR3b3JrLW5wZi9zdHlsZXMqL1xuQGltcG9ydCBcImZyb250ZW5kL3ZhcmlhYmxlc1wiO1xuQGltcG9ydCBcImZyb250ZW5kL2dsb2JhbFwiO1xuQGltcG9ydCBcImZyb250ZW5kL3RleHRcIjtcbkBpbXBvcnQgXCJmcm9udGVuZC9saW5rXCI7XG5AaW1wb3J0IFwiZnJvbnRlbmQvdmlkZW9cIjtcbkBpbXBvcnQgXCJmcm9udGVuZC9pbWFnZVwiO1xuQGltcG9ydCBcImZyb250ZW5kL2F1ZGlvXCI7XG4iLCJib2R5IHtcblx0Pi5pZnJhbWUtY29udGFpbmVyIHtcblx0XHRkaXNwbGF5OiBub25lO1xuXHR9XG5cblx0aWZyYW1lW3NyYyo9XCJodHRwczovL3d3dy50dW1ibHIuY29tL2Rhc2hib2FyZC9pZnJhbWVcIl0ge1xuXHRcdGRpc3BsYXk6IG5vbmU7XG5cdH1cblxuXHRkaXYuamV0cGFjay1saWtlcy13aWRnZXQtd3JhcHBlci50My1saWtlcyB7XG5cdFx0bWluLWhlaWdodDogMHB4O1xuXHRcdHBvc2l0aW9uOiBzdGF0aWM7XG5cblx0XHQubGlrZXMtd2lkZ2V0LXBsYWNlaG9sZGVyLnBvc3QtbGlrZXMtd2lkZ2V0LXBsYWNlaG9sZGVyIHtcblx0XHRcdGRpc3BsYXk6IG5vbmU7XG5cdFx0fVxuXG5cdFx0aWZyYW1lIHtcblx0XHRcdHdpZHRoOiAyMHB4ICFpbXBvcnRhbnQ7XG5cdFx0XHRoZWlnaHQ6IDIwcHggIWltcG9ydGFudDtcblx0XHR9XG5cdH1cbn0iLCIvLyBodHRwczovL2dpdGh1Yi50dW1ibHIubmV0L1R1bWJsci90dW1ibHIvdHJlZS9tYXN0ZXIvY2xpZW50L3N0YW5kYWxvbmUvYmxvZy1uZXR3b3JrLW5wZi9zdHlsZXNcbkBpbXBvcnQgXCJmcm9udGVuZC92YXJpYWJsZXNcIjtcbkBpbXBvcnQgXCJmcm9udGVuZC9nbG9iYWxcIjtcbkBpbXBvcnQgXCJmcm9udGVuZC90ZXh0XCI7XG5AaW1wb3J0IFwiZnJvbnRlbmQvbGlua1wiO1xuQGltcG9ydCBcImZyb250ZW5kL3ZpZGVvXCI7XG5AaW1wb3J0IFwiZnJvbnRlbmQvaW1hZ2VcIjtcbkBpbXBvcnQgXCJmcm9udGVuZC9hdWRpb1wiO1xuIiwiLy8gTlBGIHRleHQgYmxvY2sgc3R5bGVzIC0gbmFtZWx5LCB0byBhZGQgTlBGIGNvbG9ycy5cblxuLy8gRGlzYWJsZWQgU2VsZWN0b3JGb3JtYXQgdG8gdXNlIHVuZGVyc2NvcmVkIHNlbGVjdG9yIG5hbWVzXG4vLyBzY3NzLWxpbnQ6ZGlzYWJsZSBTZWxlY3RvckZvcm1hdFxuXG5wLm5wZl9xdW90ZSB7XG5cdGZvbnQtZmFtaWx5OiBHZW9yZ2lhLCBUaW1lcywgXCJUaW1lcyBOZXcgUm9tYW5cIiwgc2VyaWY7XG5cdGZvbnQtc2l6ZTogMjNweDtcbn1cblxucC5ucGZfcXVpcmt5IHtcblx0Zm9udC1mYW1pbHk6IEZhaXJ3YXRlciwgc2VyaWY7XG5cdGZvbnQtc2l6ZTogJGZvbnQtc2l6ZS1wb3N0LXRleHQtcXVpcmt5O1xuXHRsaW5lLWhlaWdodDogJGxpbmUtaGVpZ2h0LXBvc3QtdGV4dC1xdWlya3k7XG59XG5cbnAubnBmX2NoYXQge1xuXHRmb250LWZhbWlseTogXCJTb3VyY2UgQ29kZSBQcm9cIiwgbW9ub3NwYWNlO1xufVxuXG5wLm5wZl9jb2xvcl9qb2V5LFxuc3Bhbi5ucGZfY29sb3Jfam9leSB7XG5cdGNvbG9yOiAkY29sb3Itam9leTtcbn1cblxucC5ucGZfY29sb3JfbW9uaWNhLFxuc3Bhbi5ucGZfY29sb3JfbW9uaWNhIHtcblx0Y29sb3I6ICRjb2xvci1tb25pY2E7XG59XG5cbnAubnBmX2NvbG9yX3Bob2ViZSxcbnNwYW4ubnBmX2NvbG9yX3Bob2ViZSB7XG5cdGNvbG9yOiAkY29sb3ItcGhvZWJlO1xufVxuXG5wLm5wZl9jb2xvcl9yb3NzLFxuc3Bhbi5ucGZfY29sb3Jfcm9zcyB7XG5cdGNvbG9yOiAkY29sb3Itcm9zcztcbn1cblxucC5ucGZfY29sb3JfcmFjaGVsLFxuc3Bhbi5ucGZfY29sb3JfcmFjaGVsIHtcblx0Y29sb3I6ICRjb2xvci1yYWNoZWw7XG59XG5cbnAubnBmX2NvbG9yX2NoYW5kbGVyLFxuc3Bhbi5ucGZfY29sb3JfY2hhbmRsZXIge1xuXHRjb2xvcjogJGNvbG9yLWNoYW5kbGVyO1xufVxuXG5wLm5wZl9jb2xvcl9uaWxlcyxcbnNwYW4ubnBmX2NvbG9yX25pbGVzIHtcblx0Y29sb3I6ICRjb2xvci1uaWxlcztcbn1cblxucC5ucGZfY29sb3JfZnJhc2llcixcbnNwYW4ubnBmX2NvbG9yX2ZyYXNpZXIge1xuXHRjb2xvcjogJGNvbG9yLWZyYXNpZXI7XG59XG5cbnAubnBmX2NvbG9yX21yX2JpZyxcbnNwYW4ubnBmX2NvbG9yX21yX2JpZyB7XG5cdGNvbG9yOiAkY29sb3ItbXItYmlnO1xufVxuIiwiQHVzZSBcInNhc3M6bWF0aFwiO1xuXG4kcG9zdC1mdWxsLXdpZHRoOiA1NDBweDtcbiRwb3N0LWZ1bGwtcmFkaXVzOiAzcHg7XG4kcG9zdC1mdWxsLXYtcGFkZGluZzogMTVweDtcbiRwb3N0LWZ1bGwtaC1wYWRkaW5nOiAyMHB4O1xuJHBvc3QtZnVsbC1ub3RlLWl0ZW0taC1wYWRkaW5nOiAxNHB4O1xuJGNvbG9yLXBvc3QtbWVtYmVycy1vbmx5OiAjOTAwMDIwO1xuXG4kZm9udC1zaXplLWNvbnRlbnQ6IDE0cHg7XG4kbGluZS1oZWlnaHQtY29udGVudDogbWF0aC5yb3VuZCgxLjUgKiAkZm9udC1zaXplLWNvbnRlbnQpO1xuXG4vLyB0aG9zZSBtYXRjaCBOUEYgaGVhZGluZyBzaXplIGJldHRlclxuJGZvbnQtc2l6ZS1jb250ZW50LWhlYWRpbmcxOiAyNnB4O1xuJGxpbmUtaGVpZ2h0LWNvbnRlbnQtaGVhZGluZzE6IG1hdGgucm91bmQoMS4zICogJGZvbnQtc2l6ZS1jb250ZW50LWhlYWRpbmcxKTtcbiRmb250LXNpemUtY29udGVudC1oZWFkaW5nMjogMjBweDtcbiRsaW5lLWhlaWdodC1jb250ZW50LWhlYWRpbmcyOiBtYXRoLnJvdW5kKDEuMyAqICRmb250LXNpemUtY29udGVudC1oZWFkaW5nMik7XG5cbiRmb250LXNpemUtY29udGVudC1oZWFkaW5nLW1lZGl1bTogMzBweDtcbiRsaW5lLWhlaWdodC1jb250ZW50LWhlYWRpbmctbWVkaXVtOiBtYXRoLnJvdW5kKDEuMyAqICRmb250LXNpemUtY29udGVudC1oZWFkaW5nLW1lZGl1bSk7XG4kZm9udC1zaXplLWNvbnRlbnQtaGVhZGluZy1sYXJnZTogMzZweDtcbiRsaW5lLWhlaWdodC1jb250ZW50LWhlYWRpbmctbGFyZ2U6IG1hdGgucm91bmQoMS4zICogJGZvbnQtc2l6ZS1jb250ZW50LWhlYWRpbmctbGFyZ2UpO1xuXG4kZm9udC1zaXplLXByZTogMTFweDtcbiRsaW5lLWhlaWdodC1wcmU6ICRmb250LXNpemUtcHJlO1xuXG4kZm9udC1zaXplLWljb246IDI0cHg7XG4kbGluZS1oZWlnaHQtaWNvbjogMjRweDtcblxuJGZvbnQtc2l6ZS1iYXNlOiAkZm9udC1zaXplLWNvbnRlbnQ7XG4kbGluZS1oZWlnaHQtYmFzZTogMS40O1xuXG4kZm9udC1zaXplLXBvc3QtdGV4dC1xdWlya3k6IDI0cHg7XG4kbGluZS1oZWlnaHQtcG9zdC10ZXh0LXF1aXJreTogMS4zZW07XG5cbi8vIFRoZXNlIG9taXQgYHNlcmlmYCBhbmQgYHNhbnMtc2VyZmAgdG8gbWFrZSBpdFxuLy8gcG9zc2libGUgdG8gc3BsaWNlIGluIGFkZGl0aW9uYWwgZmFsbGJhY2tzXG4kZm9udC1mYW1pbHktc2Fucy1mYWNlOiBcIkhlbHZldGljYSBOZXVlXCIsIFwiSGVsdmV0aWNhTmV1ZVwiLCBoZWx2ZXRpY2EsIGFyaWFsO1xuJGZvbnQtZmFtaWx5LXNlcmlmLWZhY2U6IGdlb3JnaWEsIHRpbWVzLCBcIlRpbWVzIE5ldyBSb21hblwiO1xuJGZvbnQtZmFtaWx5LW1vbm9zcGFjZS1mYWNlOiBjb3VyaWVyO1xuXG4vLyBTdGFuZGFyZCBmYWNlc1xuJGZvbnQtZmFtaWx5LXNhbnM6ICRmb250LWZhbWlseS1zYW5zLWZhY2UsIHNhbnMtc2VyaWY7XG4kZm9udC1mYW1pbHktc2VyaWY6IGdlb3JnaWEsIHRpbWVzLCBcIlRpbWVzIE5ldyBSb21hblwiLCBzZXJpZjtcbiRmb250LWZhbWlseS1tb25vc3BhY2U6ICRmb250LWZhbWlseS1tb25vc3BhY2UtZmFjZSwgbW9ub3NwYWNlO1xuJGZvbnQtZmFtaWx5LWtvcmVhbjogJGZvbnQtZmFtaWx5LXNhbnMtZmFjZSwgXCJBcHBsZUdvdGhpY1wiLCBcIk1hbGd1biBHb3RoaWNcIiwgXCJEb3R1bVwiLCBcIkd1bGltXCIsIHNhbnMtc2VyaWY7XG5cbi8vIE5hbWVkIGZhY2VzXG4kZm9udC1mYW1pbHktZ2lic29uOiBcIkdpYnNvblwiLCAkZm9udC1mYW1pbHktc2FucztcbiRmb250LWZhbWlseS13YWxzaGVpbTogXCJXYWxzaGVpbVwiLCBcIkhlbHZldGljYSBOZXVlXCIsIFwiSGVsdmV0aWNhTmV1ZVwiLCBoZWx2ZXRpY2EsIGFyaWFsLCBzYW5zLXNlcmlmO1xuJGZvbnQtZmFtaWx5LWZyYW5rbGluLW1lZGl1bTogXCJGcmFua2xpbiBHb3RoaWMgTWVkaXVtXCIsICRmb250LWZhbWlseS1zYW5zO1xuJGZvbnQtZmFtaWx5LWZyYW5rbGluLW1lZGl1bS1jb25kZW5zZWQ6IFwiRnJhbmtsaW4gR290aGljIE1lZGl1bSBDb25kZW5zZWRcIiwgJGZvbnQtZmFtaWx5LXNhbnM7XG4kZm9udC1mYW1pbHktZnJhbmtsaW4tY29tcHJlc3NlZDogXCJGcmFua2xpbiBHb3RoaWMgQ29tcHJlc3NlZFwiLCAkZm9udC1mYW1pbHktc2FucztcbiRmb250LWZhbWlseS1zb3VyY2UtY29kZS1wcm86IFwiU291cmNlIENvZGUgUHJvXCIsICRmb250LWZhbWlseS1tb25vc3BhY2U7XG5cbi8vIERlZmF1bHQgXCJhcHBcIiBmb250IGZhbWlseVxuJGZvbnQtZmFtaWx5LWJhc2U6ICRmb250LWZhbWlseS1zYW5zO1xuXG4kY29sb3Itd2hpdGU6ICNmZmY7XG4kY29sb3ItYmxhY2s6ICMwMDA7XG4kY29sb3ItdHVtYmxyLWJsYWNrOiAjNDQ0O1xuJGNvbG9yLXR1bWJsci1ibHVlOiAjMzY0NjVkO1xuJGNvbG9yLXR1bWJsci1kYXJrLWJsdWU6ICMwMDE5MzU7XG5cbiRjb2xvci1kYW5rLXNtb2tlOiAjOWRhNmFmO1xuJGNvbG9yLWdsb29teS1jbG91ZDogIzc0ODA4OTtcbi8vIFRoZSBiZWxvdyBoYXZlIE5ldWUgQ29sb3IgdmFyaWFudHNcbiRjb2xvci1saWthYmxlLXJlZDogI2Q5NWU0MDtcbiRjb2xvci1jaGVlemJvcnQ6ICNmMjk5MmU7XG4kY29sb3ItYWx3YXlzLXN1bm55OiAjZjdkZDM4O1xuJGNvbG9yLXJlYmxvZy1ncmVlbjogIzU2YmM4YTtcbiRjb2xvci1uZWF0LWJsdWU6ICM1MjllY2M7XG4kY29sb3ItcHVycGxlLXJhaW46ICNhNzdkYzI7XG5cbi8vIFRoZXNlIHJlcGxhY2Ugb2xkIGFjY2VudCBjb2xvcnNcbiRjb2xvci1qb2V5OiAjZmY0OTJmOyAvLyBSZWRcbiRjb2xvci1tb25pY2E6ICNmZjhhMDA7IC8vIE9yYW5nZVxuJGNvbG9yLXBob2ViZTogI2U4ZDczYTsgLy8gWWVsbG93XG4kY29sb3Itcm9zczogIzAwY2YzNTsgLy8gR3JlZW5cbiRjb2xvci1yYWNoZWw6ICMwMGI4ZmY7IC8vIExpZ2h0IEJsdWVcbiRjb2xvci1jaGFuZGxlcjogIzdjNWNmZjsgLy8gUHVycGxlXG4vLyBUaGVzZSBhcmUgbmV3XG4kY29sb3ItZnJhc2llcjogJGNvbG9yLXR1bWJsci1kYXJrLWJsdWU7IC8vIERhcmsgQmx1ZSwgbmV3IGJyYW5kIGNvbG9yXG4kY29sb3ItbmlsZXM6ICNmZjYyY2U7IC8vIFBpbmtcbiRjb2xvci1tci1iaWc6ICMwMDBjMWE7IC8vIE9mZi1CbGFja1xuJGNvbG9yLWV4cGxpY2l0LXJlZDogI2ZmNDkzMDsgLy8gcHJvamVjdCB4IHJlZFxuXG5cbiRjb2xvci1ncmF5LTEwMDogJGNvbG9yLXR1bWJsci1ibGFjazsgLy8gIzQ0NDQ0NFxuXG4kY29sb3ItZ3JheS02MDogcHJpbWEtbWl4KCRjb2xvci10dW1ibHItYmxhY2ssIDAuNik7IC8vICM4ZjhmOGZcbiRjb2xvci1ncmF5LTQwOiBwcmltYS1taXgoJGNvbG9yLXR1bWJsci1ibGFjaywgMC40KTsgLy8gI2I0YjRiNFxuJGNvbG9yLWdyYXktMjU6IHByaW1hLW1peCgkY29sb3ItdHVtYmxyLWJsYWNrLCAwLjI1KTsgLy8gI2QwZDBkMFxuJGNvbG9yLWdyYXktMTM6IHByaW1hLW1peCgkY29sb3ItdHVtYmxyLWJsYWNrLCAwLjEzKTsgLy8gI2U3ZTdlN1xuJGNvbG9yLWdyYXktNzogcHJpbWEtbWl4KCRjb2xvci10dW1ibHItYmxhY2ssIDAuMDcpOyAvLyAjZjJmMmYyXG5cblxuJGNvbG9yLWdyYXktNjAtdHJhbnNwYXJlbnQ6IHVubWF0dGUtZ3JheSgkY29sb3ItZ3JheS02MCk7IC8vIHJnYmEoMCwgMCwgMCwgMC40MzkyMTYpXG4kY29sb3ItZ3JheS00MC10cmFuc3BhcmVudDogdW5tYXR0ZS1ncmF5KCRjb2xvci1ncmF5LTQwKTsgLy8gcmdiYSgwLCAwLCAwLCAwLjI5NDExOClcbiRjb2xvci1ncmF5LTI1LXRyYW5zcGFyZW50OiB1bm1hdHRlLWdyYXkoJGNvbG9yLWdyYXktMjUpOyAvLyByZ2JhKDAsIDAsIDAsIDAuMTg0MzE0KVxuJGNvbG9yLWdyYXktMTMtdHJhbnNwYXJlbnQ6IHVubWF0dGUtZ3JheSgkY29sb3ItZ3JheS0xMyk7IC8vIHJnYmEoMCwgMCwgMCwgMC4wOTQxMTc2KVxuJGNvbG9yLWdyYXktNy10cmFuc3BhcmVudDogdW5tYXR0ZS1ncmF5KCRjb2xvci1ncmF5LTcpOyAvLyByZ2JhKDAsIDAsIDAsIDAuMDUwOTgwNClcblxuXG4kY29sb3Itd2hpdGUtNjAtdHJhbnNwYXJlbnQ6IHByaW1hLW1peCgkY29sb3Itd2hpdGUsIDAuNiwgdHJhbnNwYXJlbnQpOyAvLyByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNik7XG4kY29sb3Itd2hpdGUtNDAtdHJhbnNwYXJlbnQ6IHByaW1hLW1peCgkY29sb3Itd2hpdGUsIDAuNCwgdHJhbnNwYXJlbnQpOyAvLyByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNCk7XG4kY29sb3Itd2hpdGUtMjUtdHJhbnNwYXJlbnQ6IHByaW1hLW1peCgkY29sb3Itd2hpdGUsIDAuMjUsIHRyYW5zcGFyZW50KTsgLy8gcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjI1KTtcbiRjb2xvci13aGl0ZS0xMy10cmFuc3BhcmVudDogcHJpbWEtbWl4KCRjb2xvci13aGl0ZSwgMC4xMywgdHJhbnNwYXJlbnQpOyAvLyByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMTMpO1xuJGNvbG9yLXdoaXRlLTctdHJhbnNwYXJlbnQ6IHByaW1hLW1peCgkY29sb3Itd2hpdGUsIDAuMDcsIHRyYW5zcGFyZW50KTsgLy8gcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjA3KTtcblxuXG5AbWl4aW4gYnJhbmRCbHVlKCRwcm9wKSB7XG5cdCN7JHByb3B9OiAkY29sb3ItdHVtYmxyLWRhcmstYmx1ZTtcbn1cblxuQG1peGluIGJyYW5kQmx1ZUdyYXkoJHByb3AsICRwZXJjZW50KSB7XG5cdCN7JHByb3B9OiBwcmltYS1taXgoJGNvbG9yLXdoaXRlLCAxIC0gJHBlcmNlbnQsICRjb2xvci10dW1ibHItZGFyay1ibHVlKTtcbn1cblxuQG1peGluIHRyYW5zcGFyZW50QnJhbmRCbHVlKCRwcm9wLCAkb3BhY2l0eSkge1xuXHQjeyRwcm9wfTogcmdiYSgkY29sb3ItdHVtYmxyLWRhcmstYmx1ZSwgJG9wYWNpdHkpO1xufVxuXG4kYWNjZW50Q29sb3JzOiAoXG5cdFwicmVkXCI6ICRjb2xvci1qb2V5LFxuXHRcIm9yYW5nZVwiOiAkY29sb3ItbW9uaWNhLFxuXHRcInllbGxvd1wiOiAkY29sb3ItcGhvZWJlLFxuXHRcImdyZWVuXCI6ICRjb2xvci1yb3NzLFxuXHRcImJsdWVcIjogJGNvbG9yLXJhY2hlbCxcblx0XCJwdXJwbGVcIjogJGNvbG9yLWNoYW5kbGVyLFxuXHRcImJsYWNrXCI6ICRjb2xvci1ibGFjayxcblxuXHRcInZpZGVvXCI6ICRjb2xvci1uaWxlcyxcbik7XG5cbkBmdW5jdGlvbiBuZXdBY2NlbnRDb2xvcigkY29sb3IpIHtcblxuXHRAaWYgKG5vdCBtYXBfaGFzX2tleSgkYWNjZW50Q29sb3JzLCAkY29sb3IpKSB7XG5cblx0XHRAZXJyb3IgJ1VucmVjb2duaXplZCBhY2NlbnQgY29sb3IgXCIjeyRjb2xvcn1cIiBpbiBhY2NlbnRDb2xvciBtaXhpbic7XG5cdH1cblxuXHRAcmV0dXJuIG1hcC1nZXQoJGFjY2VudENvbG9ycywgJGNvbG9yKTtcbn1cblxuQG1peGluIGFjY2VudENvbG9yKCRwcm9wLCAkY29sb3IpIHtcblx0I3skcHJvcH06IG5ld2FjY2VudGNvbG9yKCRjb2xvcik7XG59XG5cbkBtaXhpbiB1cGRhdGVkV2hpdGUoJG9wYWNpdHk6IDEsICRwcm9wOiBjb2xvcikge1xuXHQjeyRwcm9wfTogcmdiYSgkY29sb3Itd2hpdGUsICRvcGFjaXR5KTtcbn1cblxuQG1peGluIHVwZGF0ZWRCbGFjaygkb3BhY2l0eTogMSwgJHByb3A6IGNvbG9yKSB7XG5cdCN7JHByb3B9OiByZ2JhKCRjb2xvci1ibGFjaywgJG9wYWNpdHkpO1xufVxuIiwiLy8gTlBGIGxpbmsgYmxvY2sgc3R5bGVzXG5cbiR0aXRsZS1saW5lLWhlaWdodDogMzRweDtcbiRkZXNjcmlwdGlvbi1saW5lLWhlaWdodDogMjRweDtcblxuQG1peGluIHRleHQtY3V0b2ZmIHtcblx0b3ZlcmZsb3c6IGhpZGRlbjtcblx0b3ZlcmZsb3ctd3JhcDogYW55d2hlcmU7XG5cdHRleHQtb3ZlcmZsb3c6IGVsbGlwc2lzO1xufVxuXG5kaXYubnBmLWxpbmstYmxvY2sge1xuXHRhbGlnbi1pdGVtczogY2VudGVyO1xuXHRib3JkZXI6IDFweCBzb2xpZCAkY29sb3ItZ3JheS0yNTtcblx0Ym9yZGVyLXJhZGl1czogNnB4O1xuXHRkaXNwbGF5OiBmbGV4O1xuXHRqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcblx0bWFyZ2luOiAxNXB4IDA7XG5cdG92ZXJmbG93OiBoaWRkZW47XG5cblx0PiBhIHtcblx0XHRjb2xvcjogaW5oZXJpdDtcblx0XHR3aWR0aDogMTAwJTtcblx0XHR0ZXh0LWRlY29yYXRpb246IG5vbmU7XG5cdH1cblxuXHQudGl0bGUge1xuXHRcdGZvbnQtc2l6ZTogMjVweDtcblx0XHRsaW5lLWhlaWdodDogJHRpdGxlLWxpbmUtaGVpZ2h0O1xuXHRcdG1heC1oZWlnaHQ6ICR0aXRsZS1saW5lLWhlaWdodCAqIDQ7IC8vIFRoaXMgbmVlZHMgdG8gYmUgZXF1YWwgdG8gKGxpbmUtaGVpZ2h0ICogNCkgLSBXZSB3YW50IHRvIHNob3cgYSBtYXhpbXVtIG9mIDQgbGluZXMgaGVyZVxuXG5cdFx0QGluY2x1ZGUgdGV4dC1jdXRvZmY7XG5cdH1cblxuXHQmLm5vLXBvc3RlciAudGl0bGUge1xuXHRcdHBhZGRpbmc6IDE2cHggMTJweCAwO1xuXHR9XG5cblx0LnBvc3RlciB7XG5cdFx0YWxpZ24taXRlbXM6IGNlbnRlcjtcblx0XHRiYWNrZ3JvdW5kLXBvc2l0aW9uOiBjZW50ZXI7XG5cdFx0YmFja2dyb3VuZC1yZXBlYXQ6IG5vLXJlcGVhdDtcblx0XHRiYWNrZ3JvdW5kLXNpemU6IGNvdmVyO1xuXHRcdGJhY2tncm91bmQtY2xpcDogY29udGVudC1ib3g7XG5cdFx0Ym9yZGVyLWJvdHRvbTogMXB4IHNvbGlkICRjb2xvci1ncmF5LTI1O1xuXHRcdGRpc3BsYXk6IGZsZXg7XG5cdFx0aGVpZ2h0OiAyNTBweDtcblx0XHRqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcblx0XHRwb3NpdGlvbjogcmVsYXRpdmU7XG5cblx0XHQmOjpiZWZvcmUge1xuXHRcdFx0YmFja2dyb3VuZDogJGNvbG9yLWJsYWNrO1xuXHRcdFx0Y29udGVudDogXCJcIjtcblx0XHRcdGRpc3BsYXk6IGJsb2NrO1xuXHRcdFx0aGVpZ2h0OiAxMDAlO1xuXHRcdFx0b3BhY2l0eTogMC40O1xuXHRcdFx0cG9zaXRpb246IGFic29sdXRlO1xuXHRcdFx0d2lkdGg6IDEwMCU7XG5cdFx0fVxuXG5cdFx0LnRpdGxlIHtcblx0XHRcdGNvbG9yOiAkY29sb3Itd2hpdGU7XG5cdFx0XHRmb250LXdlaWdodDogNDAwO1xuXHRcdFx0cGFkZGluZzogMTZweCAxMnB4O1xuXHRcdFx0cG9zaXRpb246IGFic29sdXRlO1xuXHRcdFx0dGV4dC1hbGlnbjogY2VudGVyO1xuXHRcdH1cblx0fVxuXG5cdC5ib3R0b20ge1xuXHRcdGNvbG9yOiBpbmhlcml0O1xuXHRcdGxpbmUtaGVpZ2h0OiAyNHB4O1xuXHRcdHBhZGRpbmc6IDhweCAxMnB4IDE2cHg7XG5cblx0XHQuZGVzY3JpcHRpb24ge1xuXHRcdFx0Y29sb3I6IGluaGVyaXQ7XG5cdFx0XHRmb250LXNpemU6IDE2cHg7XG5cdFx0XHRsaW5lLWhlaWdodDogJGRlc2NyaXB0aW9uLWxpbmUtaGVpZ2h0O1xuXHRcdFx0bWFyZ2luOiAwO1xuXHRcdFx0bWF4LWhlaWdodDogJGRlc2NyaXB0aW9uLWxpbmUtaGVpZ2h0ICogMjsgLy8gVGhpcyBuZWVkcyB0byBiZSBlcXVhbCB0byAobGluZS1oZWlnaHQgKiAyKSAtIFdlIHdhbnQgdG8gc2hvdyBhIG1heGltdW0gb2YgMiBsaW5lcyBoZXJlXG5cblx0XHRcdEBpbmNsdWRlIHRleHQtY3V0b2ZmO1xuXHRcdH1cblxuXHRcdC5zaXRlLW5hbWUge1xuXHRcdFx0Y29sb3I6IGluaGVyaXQ7XG5cdFx0XHRmb250LXNpemU6IDEyLjVweDtcblx0XHRcdGZvbnQtd2VpZ2h0OiA0MDA7XG5cdFx0XHRsaW5lLWhlaWdodDogMThweDtcblx0XHRcdG1hcmdpbi10b3A6IDEwcHg7XG5cdFx0XHRvcGFjaXR5OiAwLjY1O1xuXHRcdFx0dGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTtcblx0XHR9XG5cdH1cbn1cbiIsIi8vIE5QRiB2aWRlbyBibG9jayBzdHlsZXNcbnZpZGVvLFxuYXVkaW8sXG5pbWcsXG4ud3AtY2FwdGlvbixcbmlmcmFtZSB7XG5cdG1heC13aWR0aDogMTAwJTtcbn1cblxuLnRtYmxyLWZ1bGwgPiB2aWRlbyB7XG5cdGhlaWdodDogMTAwJTtcblx0d2lkdGg6IDEwMCU7XG59XG4iLCIvLyBOUEYgaW1hZ2UgYmxvY2sgc3R5bGVzIC0gbW9zdCBpbXBvcnRhbnRseSwgdG8gcmVuZGVyIE5QRi1jcmVhdGVkIHBob3Rvc2V0cy5cbi8vIHN0eWxlbGludC1kaXNhYmxlIG5vLWRlc2NlbmRpbmctc3BlY2lmaWNpdHkgLS0gdW5uZWNlc3NhcnkuXG5cbi5wb3N0LFxuLnBvc3QtY29udGVudCxcbmJvZHkge1xuICAgIC8vIE5QRiBwaG90b3NldCB3cmFwcGVyXG4gICAgZGl2Lm5wZl9yb3cge1xuICAgICAgICBhbGlnbi1pdGVtczogc3RyZXRjaDtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgbWFyZ2luLXRvcDogMDtcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcblxuICAgICAgICBmaWd1cmUudG1ibHItZnVsbCB7XG4gICAgICAgICAgICBmbGV4OiAxO1xuICAgICAgICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xuICAgICAgICAgICAgbWFyZ2luOiAwO1xuICAgICAgICAgICAgb3ZlcmZsb3cteTogaGlkZGVuO1xuICAgICAgICB9XG5cbiAgICAgICAgZmlndXJlLnRtYmxyLWZ1bGwsXG4gICAgICAgIC5ucGZfY29sIHtcbiAgICAgICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICAgICAgcGFkZGluZy1sZWZ0OiAycHg7XG4gICAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAycHg7XG5cbiAgICAgICAgICAgICY6Zmlyc3QtY2hpbGQge1xuICAgICAgICAgICAgICAgIHBhZGRpbmctbGVmdDogMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJjpsYXN0LWNoaWxkIHtcbiAgICAgICAgICAgICAgICBwYWRkaW5nLXJpZ2h0OiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaW1nIHtcbiAgICAgICAgICAgIGhlaWdodDogYXV0bztcbiAgICAgICAgfVxuXG4gICAgICAgIC5ucGZfY29sIHtcbiAgICAgICAgICAgIGZsZXg6IDE7XG5cbiAgICAgICAgICAgIGZpZ3VyZSB7XG4gICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICAgICAgICAgIG1hcmdpbjogMDtcbiAgICAgICAgICAgICAgICB0ZXh0LWFsaWduOiBsZWZ0O1xuXG4gICAgICAgICAgICAgICAgaW1nIHtcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LWZpdDogY292ZXI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcC50bWJsci1hdHRyaWJ1dGlvbiB7XG4gICAgICAgICAgICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZpZ3VyZVtkYXRhLWVuYWJsZS1saWdodGJveD1cIjFcIl0ge1xuICAgICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgfVxuXG4gICAgYS5wb3N0X21lZGlhX3Bob3RvX2FuY2hvciB7XG4gICAgICAgIGN1cnNvcjogcG9pbnRlcjtcbiAgICAgICAgZmxleDogMTtcbiAgICAgICAgdGV4dC1kZWNvcmF0aW9uOiBub25lO1xuICAgIH1cblxuICAgIHAgKyBkaXYubnBmX3JvdyxcbiAgICBkaXYubnBmX3JvdyArIHAge1xuICAgICAgICBtYXJnaW4tdG9wOiAxNXB4O1xuICAgIH1cblxuICAgIC8vIEFkZCBhIG1hcmdpbiBpZiBmb2xsb3dpbmcvcHJlY2VkaW5nIGEgdmlkZW9cbiAgICAuY3J0LXZpZGVvICsgZGl2Lm5wZl9yb3csXG4gICAgZGl2Lm5wZl9yb3cgKyAuY3J0LXZpZGVvIHtcbiAgICAgICAgbWFyZ2luLXRvcDogMTVweDtcbiAgICB9XG5cbiAgICAvLyBIb3Jpem9udGFsIG1hcmdpbnMgYmV0d2VlbiBwaG90b3NldCByb3dzXG4gICAgZGl2Lm5wZl9yb3cgKyBmaWd1cmUudG1ibHItZnVsbCxcbiAgICBkaXYubnBmX3JvdyArIGRpdi5ucGZfcm93IHtcbiAgICAgICAgbWFyZ2luLXRvcDogNHB4O1xuICAgIH1cbn1cbiIsIi50bWJsci1mdWxsID4gYXVkaW8ge1xuICAgIHdpZHRoOiAxMDAlO1xufVxuXG4udG1ibHItZnVsbCA+IC5hdWRpby1jYXB0aW9uIHtcbiAgICBkaXNwbGF5OiBmbGV4O1xuICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG5cbiAgICAuYWxidW0tY292ZXIge1xuICAgICAgICB3aWR0aDogODVweDtcbiAgICAgICAgaGVpZ2h0OiA4NXB4O1xuICAgIH1cblxuICAgIC5hdWRpby1kZXRhaWxzIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleDogMSAwIGF1dG87XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbiAgICAgICAgcGFkZGluZzogMCAyMHB4O1xuICAgIH1cblxuICAgIC50aXRsZSB7XG4gICAgICAgIGZvbnQtd2VpZ2h0OiBib2xkO1xuICAgICAgICBsaW5lLWhlaWdodDogMS41O1xuICAgIH1cblxuICAgIC5hcnRpc3QsXG4gICAgLmFsYnVtIHtcbiAgICAgICAgZm9udC1zaXplOiAwLjg3NWVtO1xuICAgICAgICBsaW5lLWhlaWdodDogMS41O1xuICAgIH1cbn1cbiJdfQ== */ \ No newline at end of file diff --git a/assets/css/build/index.css.map b/assets/css/build/index.css.map index f23650e..f23bc37 100644 --- a/assets/css/build/index.css.map +++ b/assets/css/build/index.css.map @@ -1 +1 @@ -{"version":3,"sources":["../src/index.scss%23sass","../src/frontend/_global.scss","../src/index.scss","../src/frontend/_text.scss","../src/frontend/_variables.scss","../src/frontend/_link.scss","../src/frontend/_video.scss","../src/frontend/_image.scss","../src/frontend/_audio.scss"],"names":[],"mappings":"AAAA,iGAAA;ACCC;ECCD,aAAA;AACA;ADEC;ECAD,aAAA;AACA;;ACDA;EACC,qDAAA;EACA,eAAA;ADID;;ACDA;EACC,6BAAA;EACA,eCoB4B;EDnB5B,kBCoB8B;AFhB/B;;ACDA;EACC,yCAAA;ADID;;ACDA;;EAEC,cCqDY;AFjDb;;ACDA;;EAEC,cCiDc;AF7Cf;;ACDA;;EAEC,cC6Cc;AFzCf;;ACDA;;EAEC,cCyCY;AFrCb;;ACDA;;EAEC,cCqCc;AFjCf;;ACDA;;EAEC,cCiCgB;AF7BjB;;ACDA;;EAEC,cC+Ba;AF3Bd;;ACDA;;EAEC,cCKwB;AFDzB;;ACDA;;EAEC,cCsBc;AFlBf;;AGvDA;EACC,mBAAA;EACA,uCAAA;EACA,kBAAA;EACA,aAAA;EACA,uBAAA;EACA,cAAA;EACA,gBAAA;AH0DD;AGxDC;EACC,cAAA;EACA,WAAA;EACA,qBAAA;AH0DF;AGvDC;EACC,eAAA;EACA,iBA1BkB;EA2BlB,iBAAA;EAvBD,gBAAA;EACA,uBAAA;EACA,uBAAA;AHiFD;AGvDC;EACC,oBAAA;AHyDF;AGtDC;EACC,mBAAA;EACA,2BAAA;EACA,4BAAA;EACA,sBAAA;EACA,4BAAA;EACA,8CAAA;EACA,aAAA;EACA,aAAA;EACA,uBAAA;EACA,kBAAA;AHwDF;AGtDE;EACC,gBDQW;ECPX,WAAA;EACA,cAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,WAAA;AHwDH;AGrDE;EACC,WDHW;ECIX,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,kBAAA;AHuDH;AGnDC;EACC,cAAA;EACA,iBAAA;EACA,sBAAA;AHqDF;AGnDE;EACC,cAAA;EACA,eAAA;EACA,iBA1EuB;EA2EvB,SAAA;EACA,gBAAA;EAzEF,gBAAA;EACA,uBAAA;EACA,uBAAA;AH+HD;AGnDE;EACC,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,aAAA;EACA,yBAAA;AHqDH;;AI/IA;;;;;EAKC,eAAA;AJkJD;;AI/IA;EACC,YAAA;EACA,WAAA;AJkJD;;AKtJI;;;EACI,oBAAA;EACA,aAAA;EACA,aAAA;EACA,gBAAA;AL2JR;AKzJQ;;;EACI,OAAA;EACA,8BAAA;EACA,SAAA;EACA,kBAAA;AL6JZ;AK1JQ;;;;;;EAEI,aAAA;EACA,sBAAA;EACA,iBAAA;EACA,kBAAA;ALgKZ;AK9JY;;;;;;EACI,eAAA;ALqKhB;AKlKY;;;;;;EACI,gBAAA;ALyKhB;AKrKQ;;;EACI,YAAA;ALyKZ;AKtKQ;;;EACI,OAAA;AL0KZ;AKxKY;;;EACI,kBAAA;EACA,WAAA;EACA,SAAA;EACA,gBAAA;AL4KhB;AK1KgB;;;EACI,WAAA;EACA,YAAA;EACA,iBAAA;AL8KpB;AK3KgB;;;EACI,sBAAA;EACA,WAAA;AL+KpB;AKzKI;;;EACI,eAAA;AL6KR;AK1KI;;;EACI,eAAA;EACA,OAAA;EACA,qBAAA;AL8KR;AK3KI;;;;;;EAEI,gBAAA;ALiLR;AK7KI;;;;;;EAEI,gBAAA;ALmLR;AK/KI;;;;;;EAEI,eAAA;ALqLR;;AM5QA;EACI,WAAA;AN+QJ;;AM5QA;EACI,aAAA;EACA,mBAAA;AN+QJ;AM7QI;EACI,WAAA;EACA,YAAA;AN+QR;AM5QI;EACI,aAAA;EACA,cAAA;EACA,sBAAA;EACA,uBAAA;EACA,uBAAA;EACA,eAAA;AN8QR;AM3QI;EACI,iBAAA;EACA,gBAAA;AN6QR;AM1QI;;EAEI,kBAAA;EACA,gBAAA;AN4QR","file":"index.css","sourcesContent":["/* https://github.tumblr.net/Tumblr/tumblr/tree/master/client/standalone/blog-network-npf/styles*/\n@import \"frontend/variables\";\n@import \"frontend/global\";\n@import \"frontend/text\";\n@import \"frontend/link\";\n@import \"frontend/video\";\n@import \"frontend/image\";\n@import \"frontend/audio\";\n","body {\n\t> .iframe-container {\n\t\tdisplay: none;\n\t}\n\n\tiframe[src*=\"https://www.tumblr.com/dashboard/iframe\"] {\n\t\tdisplay: none;\n\t}\n}","// https://github.tumblr.net/Tumblr/tumblr/tree/master/client/standalone/blog-network-npf/styles\n@import \"frontend/variables\";\n@import \"frontend/global\";\n@import \"frontend/text\";\n@import \"frontend/link\";\n@import \"frontend/video\";\n@import \"frontend/image\";\n@import \"frontend/audio\";\n","// NPF text block styles - namely, to add NPF colors.\n\n// Disabled SelectorFormat to use underscored selector names\n// scss-lint:disable SelectorFormat\n\np.npf_quote {\n\tfont-family: Georgia, Times, \"Times New Roman\", serif;\n\tfont-size: 23px;\n}\n\np.npf_quirky {\n\tfont-family: Fairwater, serif;\n\tfont-size: $font-size-post-text-quirky;\n\tline-height: $line-height-post-text-quirky;\n}\n\np.npf_chat {\n\tfont-family: \"Source Code Pro\", monospace;\n}\n\np.npf_color_joey,\nspan.npf_color_joey {\n\tcolor: $color-joey;\n}\n\np.npf_color_monica,\nspan.npf_color_monica {\n\tcolor: $color-monica;\n}\n\np.npf_color_phoebe,\nspan.npf_color_phoebe {\n\tcolor: $color-phoebe;\n}\n\np.npf_color_ross,\nspan.npf_color_ross {\n\tcolor: $color-ross;\n}\n\np.npf_color_rachel,\nspan.npf_color_rachel {\n\tcolor: $color-rachel;\n}\n\np.npf_color_chandler,\nspan.npf_color_chandler {\n\tcolor: $color-chandler;\n}\n\np.npf_color_niles,\nspan.npf_color_niles {\n\tcolor: $color-niles;\n}\n\np.npf_color_frasier,\nspan.npf_color_frasier {\n\tcolor: $color-frasier;\n}\n\np.npf_color_mr_big,\nspan.npf_color_mr_big {\n\tcolor: $color-mr-big;\n}\n","@use \"sass:math\";\n\n$post-full-width: 540px;\n$post-full-radius: 3px;\n$post-full-v-padding: 15px;\n$post-full-h-padding: 20px;\n$post-full-note-item-h-padding: 14px;\n$color-post-members-only: #900020;\n\n$font-size-content: 14px;\n$line-height-content: math.round(1.5 * $font-size-content);\n\n// those match NPF heading size better\n$font-size-content-heading1: 26px;\n$line-height-content-heading1: math.round(1.3 * $font-size-content-heading1);\n$font-size-content-heading2: 20px;\n$line-height-content-heading2: math.round(1.3 * $font-size-content-heading2);\n\n$font-size-content-heading-medium: 30px;\n$line-height-content-heading-medium: math.round(1.3 * $font-size-content-heading-medium);\n$font-size-content-heading-large: 36px;\n$line-height-content-heading-large: math.round(1.3 * $font-size-content-heading-large);\n\n$font-size-pre: 11px;\n$line-height-pre: $font-size-pre;\n\n$font-size-icon: 24px;\n$line-height-icon: 24px;\n\n$font-size-base: $font-size-content;\n$line-height-base: 1.4;\n\n$font-size-post-text-quirky: 24px;\n$line-height-post-text-quirky: 1.3em;\n\n// These omit `serif` and `sans-serf` to make it\n// possible to splice in additional fallbacks\n$font-family-sans-face: \"Helvetica Neue\", \"HelveticaNeue\", helvetica, arial;\n$font-family-serif-face: georgia, times, \"Times New Roman\";\n$font-family-monospace-face: courier;\n\n// Standard faces\n$font-family-sans: $font-family-sans-face, sans-serif;\n$font-family-serif: georgia, times, \"Times New Roman\", serif;\n$font-family-monospace: $font-family-monospace-face, monospace;\n$font-family-korean: $font-family-sans-face, \"AppleGothic\", \"Malgun Gothic\", \"Dotum\", \"Gulim\", sans-serif;\n\n// Named faces\n$font-family-gibson: \"Gibson\", $font-family-sans;\n$font-family-walsheim: \"Walsheim\", \"Helvetica Neue\", \"HelveticaNeue\", helvetica, arial, sans-serif;\n$font-family-franklin-medium: \"Franklin Gothic Medium\", $font-family-sans;\n$font-family-franklin-medium-condensed: \"Franklin Gothic Medium Condensed\", $font-family-sans;\n$font-family-franklin-compressed: \"Franklin Gothic Compressed\", $font-family-sans;\n$font-family-source-code-pro: \"Source Code Pro\", $font-family-monospace;\n\n// Default \"app\" font family\n$font-family-base: $font-family-sans;\n\n$color-white: #fff;\n$color-black: #000;\n$color-tumblr-black: #444;\n$color-tumblr-blue: #36465d;\n$color-tumblr-dark-blue: #001935;\n\n$color-dank-smoke: #9da6af;\n$color-gloomy-cloud: #748089;\n// The below have Neue Color variants\n$color-likable-red: #d95e40;\n$color-cheezbort: #f2992e;\n$color-always-sunny: #f7dd38;\n$color-reblog-green: #56bc8a;\n$color-neat-blue: #529ecc;\n$color-purple-rain: #a77dc2;\n\n// These replace old accent colors\n$color-joey: #ff492f; // Red\n$color-monica: #ff8a00; // Orange\n$color-phoebe: #e8d73a; // Yellow\n$color-ross: #00cf35; // Green\n$color-rachel: #00b8ff; // Light Blue\n$color-chandler: #7c5cff; // Purple\n// These are new\n$color-frasier: $color-tumblr-dark-blue; // Dark Blue, new brand color\n$color-niles: #ff62ce; // Pink\n$color-mr-big: #000c1a; // Off-Black\n$color-explicit-red: #ff4930; // project x red\n\n\n$color-gray-100: $color-tumblr-black; // #444444\n\n$color-gray-60: prima-mix($color-tumblr-black, 0.6); // #8f8f8f\n$color-gray-40: prima-mix($color-tumblr-black, 0.4); // #b4b4b4\n$color-gray-25: prima-mix($color-tumblr-black, 0.25); // #d0d0d0\n$color-gray-13: prima-mix($color-tumblr-black, 0.13); // #e7e7e7\n$color-gray-7: prima-mix($color-tumblr-black, 0.07); // #f2f2f2\n\n\n$color-gray-60-transparent: unmatte-gray($color-gray-60); // rgba(0, 0, 0, 0.439216)\n$color-gray-40-transparent: unmatte-gray($color-gray-40); // rgba(0, 0, 0, 0.294118)\n$color-gray-25-transparent: unmatte-gray($color-gray-25); // rgba(0, 0, 0, 0.184314)\n$color-gray-13-transparent: unmatte-gray($color-gray-13); // rgba(0, 0, 0, 0.0941176)\n$color-gray-7-transparent: unmatte-gray($color-gray-7); // rgba(0, 0, 0, 0.0509804)\n\n\n$color-white-60-transparent: prima-mix($color-white, 0.6, transparent); // rgba(255, 255, 255, 0.6);\n$color-white-40-transparent: prima-mix($color-white, 0.4, transparent); // rgba(255, 255, 255, 0.4);\n$color-white-25-transparent: prima-mix($color-white, 0.25, transparent); // rgba(255, 255, 255, 0.25);\n$color-white-13-transparent: prima-mix($color-white, 0.13, transparent); // rgba(255, 255, 255, 0.13);\n$color-white-7-transparent: prima-mix($color-white, 0.07, transparent); // rgba(255, 255, 255, 0.07);\n\n\n@mixin brandBlue($prop) {\n\t#{$prop}: $color-tumblr-dark-blue;\n}\n\n@mixin brandBlueGray($prop, $percent) {\n\t#{$prop}: prima-mix($color-white, 1 - $percent, $color-tumblr-dark-blue);\n}\n\n@mixin transparentBrandBlue($prop, $opacity) {\n\t#{$prop}: rgba($color-tumblr-dark-blue, $opacity);\n}\n\n$accentColors: (\n\t\"red\": $color-joey,\n\t\"orange\": $color-monica,\n\t\"yellow\": $color-phoebe,\n\t\"green\": $color-ross,\n\t\"blue\": $color-rachel,\n\t\"purple\": $color-chandler,\n\t\"black\": $color-black,\n\n\t\"video\": $color-niles,\n);\n\n@function newAccentColor($color) {\n\n\t@if (not map_has_key($accentColors, $color)) {\n\n\t\t@error 'Unrecognized accent color \"#{$color}\" in accentColor mixin';\n\t}\n\n\t@return map-get($accentColors, $color);\n}\n\n@mixin accentColor($prop, $color) {\n\t#{$prop}: newaccentcolor($color);\n}\n\n@mixin updatedWhite($opacity: 1, $prop: color) {\n\t#{$prop}: rgba($color-white, $opacity);\n}\n\n@mixin updatedBlack($opacity: 1, $prop: color) {\n\t#{$prop}: rgba($color-black, $opacity);\n}\n","// NPF link block styles\n\n$title-line-height: 34px;\n$description-line-height: 24px;\n\n@mixin text-cutoff {\n\toverflow: hidden;\n\toverflow-wrap: anywhere;\n\ttext-overflow: ellipsis;\n}\n\ndiv.npf-link-block {\n\talign-items: center;\n\tborder: 1px solid $color-gray-25;\n\tborder-radius: 6px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tmargin: 15px 0;\n\toverflow: hidden;\n\n\t> a {\n\t\tcolor: inherit;\n\t\twidth: 100%;\n\t\ttext-decoration: none;\n\t}\n\n\t.title {\n\t\tfont-size: 25px;\n\t\tline-height: $title-line-height;\n\t\tmax-height: $title-line-height * 4; // This needs to be equal to (line-height * 4) - We want to show a maximum of 4 lines here\n\n\t\t@include text-cutoff;\n\t}\n\n\t&.no-poster .title {\n\t\tpadding: 16px 12px 0;\n\t}\n\n\t.poster {\n\t\talign-items: center;\n\t\tbackground-position: center;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-size: cover;\n\t\tbackground-clip: content-box;\n\t\tborder-bottom: 1px solid $color-gray-25;\n\t\tdisplay: flex;\n\t\theight: 250px;\n\t\tjustify-content: center;\n\t\tposition: relative;\n\n\t\t&::before {\n\t\t\tbackground: $color-black;\n\t\t\tcontent: \"\";\n\t\t\tdisplay: block;\n\t\t\theight: 100%;\n\t\t\topacity: 0.4;\n\t\t\tposition: absolute;\n\t\t\twidth: 100%;\n\t\t}\n\n\t\t.title {\n\t\t\tcolor: $color-white;\n\t\t\tfont-weight: 400;\n\t\t\tpadding: 16px 12px;\n\t\t\tposition: absolute;\n\t\t\ttext-align: center;\n\t\t}\n\t}\n\n\t.bottom {\n\t\tcolor: inherit;\n\t\tline-height: 24px;\n\t\tpadding: 8px 12px 16px;\n\n\t\t.description {\n\t\t\tcolor: inherit;\n\t\t\tfont-size: 16px;\n\t\t\tline-height: $description-line-height;\n\t\t\tmargin: 0;\n\t\t\tmax-height: $description-line-height * 2; // This needs to be equal to (line-height * 2) - We want to show a maximum of 2 lines here\n\n\t\t\t@include text-cutoff;\n\t\t}\n\n\t\t.site-name {\n\t\t\tcolor: inherit;\n\t\t\tfont-size: 12.5px;\n\t\t\tfont-weight: 400;\n\t\t\tline-height: 18px;\n\t\t\tmargin-top: 10px;\n\t\t\topacity: 0.65;\n\t\t\ttext-transform: uppercase;\n\t\t}\n\t}\n}\n","// NPF video block styles\nvideo,\naudio,\nimg,\n.wp-caption,\niframe {\n\tmax-width: 100%;\n}\n\n.tmblr-full > video {\n\theight: 100%;\n\twidth: 100%;\n}\n","// NPF image block styles - most importantly, to render NPF-created photosets.\n// stylelint-disable no-descending-specificity -- unnecessary.\n\n.post,\n.post-content,\nbody {\n // NPF photoset wrapper\n div.npf_row {\n align-items: stretch;\n display: flex;\n margin-top: 0;\n overflow: hidden;\n\n figure.tmblr-full {\n flex: 1;\n justify-content: space-between;\n margin: 0;\n overflow-y: hidden;\n }\n\n figure.tmblr-full,\n .npf_col {\n display: flex;\n flex-direction: column;\n padding-left: 2px;\n padding-right: 2px;\n\n &:first-child {\n padding-left: 0;\n }\n\n &:last-child {\n padding-right: 0;\n }\n }\n\n img {\n height: auto;\n }\n\n .npf_col {\n flex: 1;\n\n figure {\n position: relative;\n width: 100%;\n margin: 0;\n text-align: left;\n\n img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n p.tmblr-attribution {\n box-sizing: border-box;\n width: 100%;\n }\n }\n }\n }\n\n figure[data-enable-lightbox=\"1\"] {\n cursor: pointer;\n }\n\n a.post_media_photo_anchor {\n cursor: pointer;\n flex: 1;\n text-decoration: none;\n }\n\n p + div.npf_row,\n div.npf_row + p {\n margin-top: 15px;\n }\n\n // Add a margin if following/preceding a video\n .crt-video + div.npf_row,\n div.npf_row + .crt-video {\n margin-top: 15px;\n }\n\n // Horizontal margins between photoset rows\n div.npf_row + figure.tmblr-full,\n div.npf_row + div.npf_row {\n margin-top: 4px;\n }\n}\n",".tmblr-full > audio {\n width: 100%;\n}\n\n.tmblr-full > .audio-caption {\n display: flex;\n flex-direction: row;\n\n .album-cover {\n width: 85px;\n height: 85px;\n }\n\n .audio-details {\n display: flex;\n flex: 1 0 auto;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n padding: 0 20px;\n }\n\n .title {\n font-weight: bold;\n line-height: 1.5;\n }\n\n .artist,\n .album {\n font-size: 0.875em;\n line-height: 1.5;\n }\n}\n"]} \ No newline at end of file +{"version":3,"sources":["../src/index.scss%23sass","../src/frontend/_global.scss","../src/index.scss","../src/frontend/_text.scss","../src/frontend/_variables.scss","../src/frontend/_link.scss","../src/frontend/_video.scss","../src/frontend/_image.scss","../src/frontend/_audio.scss"],"names":[],"mappings":"AAAA,iGAAA;ACCC;ECCD,aAAA;AACA;ADEC;ECAD,aAAA;AACA;ADGC;EACC,eAAA;EACA,sBAAA;ACDF;;ACLA;EACC,qDAAA;EACA,eAAA;ADQD;;ACLA;EACC,6BAAA;EACA,eCoB4B;EDnB5B,kBCoB8B;AFZ/B;;ACLA;EACC,yCAAA;ADQD;;ACLA;;EAEC,cCqDY;AF7Cb;;ACLA;;EAEC,cCiDc;AFzCf;;ACLA;;EAEC,cC6Cc;AFrCf;;ACLA;;EAEC,cCyCY;AFjCb;;ACLA;;EAEC,cCqCc;AF7Bf;;ACLA;;EAEC,cCiCgB;AFzBjB;;ACLA;;EAEC,cC+Ba;AFvBd;;ACLA;;EAEC,cCKwB;AFGzB;;ACLA;;EAEC,cCsBc;AFdf;;AG3DA;EACC,mBAAA;EACA,uCAAA;EACA,kBAAA;EACA,aAAA;EACA,uBAAA;EACA,cAAA;EACA,gBAAA;AH8DD;AG5DC;EACC,cAAA;EACA,WAAA;EACA,qBAAA;AH8DF;AG3DC;EACC,eAAA;EACA,iBA1BkB;EA2BlB,iBAAA;EAvBD,gBAAA;EACA,uBAAA;EACA,uBAAA;AHqFD;AG3DC;EACC,oBAAA;AH6DF;AG1DC;EACC,mBAAA;EACA,2BAAA;EACA,4BAAA;EACA,sBAAA;EACA,4BAAA;EACA,8CAAA;EACA,aAAA;EACA,aAAA;EACA,uBAAA;EACA,kBAAA;AH4DF;AG1DE;EACC,gBDQW;ECPX,WAAA;EACA,cAAA;EACA,YAAA;EACA,YAAA;EACA,kBAAA;EACA,WAAA;AH4DH;AGzDE;EACC,WDHW;ECIX,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,kBAAA;AH2DH;AGvDC;EACC,cAAA;EACA,iBAAA;EACA,sBAAA;AHyDF;AGvDE;EACC,cAAA;EACA,eAAA;EACA,iBA1EuB;EA2EvB,SAAA;EACA,gBAAA;EAzEF,gBAAA;EACA,uBAAA;EACA,uBAAA;AHmID;AGvDE;EACC,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,aAAA;EACA,yBAAA;AHyDH;;AInJA;;;;;EAKC,eAAA;AJsJD;;AInJA;EACC,YAAA;EACA,WAAA;AJsJD;;AK1JI;;;EACI,oBAAA;EACA,aAAA;EACA,aAAA;EACA,gBAAA;AL+JR;AK7JQ;;;EACI,OAAA;EACA,8BAAA;EACA,SAAA;EACA,kBAAA;ALiKZ;AK9JQ;;;;;;EAEI,aAAA;EACA,sBAAA;EACA,iBAAA;EACA,kBAAA;ALoKZ;AKlKY;;;;;;EACI,eAAA;ALyKhB;AKtKY;;;;;;EACI,gBAAA;AL6KhB;AKzKQ;;;EACI,YAAA;AL6KZ;AK1KQ;;;EACI,OAAA;AL8KZ;AK5KY;;;EACI,kBAAA;EACA,WAAA;EACA,SAAA;EACA,gBAAA;ALgLhB;AK9KgB;;;EACI,WAAA;EACA,YAAA;EACA,iBAAA;ALkLpB;AK/KgB;;;EACI,sBAAA;EACA,WAAA;ALmLpB;AK7KI;;;EACI,eAAA;ALiLR;AK9KI;;;EACI,eAAA;EACA,OAAA;EACA,qBAAA;ALkLR;AK/KI;;;;;;EAEI,gBAAA;ALqLR;AKjLI;;;;;;EAEI,gBAAA;ALuLR;AKnLI;;;;;;EAEI,eAAA;ALyLR;;AMhRA;EACI,WAAA;ANmRJ;;AMhRA;EACI,aAAA;EACA,mBAAA;ANmRJ;AMjRI;EACI,WAAA;EACA,YAAA;ANmRR;AMhRI;EACI,aAAA;EACA,cAAA;EACA,sBAAA;EACA,uBAAA;EACA,uBAAA;EACA,eAAA;ANkRR;AM/QI;EACI,iBAAA;EACA,gBAAA;ANiRR;AM9QI;;EAEI,kBAAA;EACA,gBAAA;ANgRR","file":"index.css","sourcesContent":["/* https://github.tumblr.net/Tumblr/tumblr/tree/master/client/standalone/blog-network-npf/styles*/\n@import \"frontend/variables\";\n@import \"frontend/global\";\n@import \"frontend/text\";\n@import \"frontend/link\";\n@import \"frontend/video\";\n@import \"frontend/image\";\n@import \"frontend/audio\";\n","body {\n\t> .iframe-container {\n\t\tdisplay: none;\n\t}\n\n\tiframe[src*=\"https://www.tumblr.com/dashboard/iframe\"] {\n\t\tdisplay: none;\n\t}\n\n\t.t3-likes {\n\t\tmin-height: 0px;\n\t\theight: 0px !important;\n\t}\n}","// https://github.tumblr.net/Tumblr/tumblr/tree/master/client/standalone/blog-network-npf/styles\n@import \"frontend/variables\";\n@import \"frontend/global\";\n@import \"frontend/text\";\n@import \"frontend/link\";\n@import \"frontend/video\";\n@import \"frontend/image\";\n@import \"frontend/audio\";\n","// NPF text block styles - namely, to add NPF colors.\n\n// Disabled SelectorFormat to use underscored selector names\n// scss-lint:disable SelectorFormat\n\np.npf_quote {\n\tfont-family: Georgia, Times, \"Times New Roman\", serif;\n\tfont-size: 23px;\n}\n\np.npf_quirky {\n\tfont-family: Fairwater, serif;\n\tfont-size: $font-size-post-text-quirky;\n\tline-height: $line-height-post-text-quirky;\n}\n\np.npf_chat {\n\tfont-family: \"Source Code Pro\", monospace;\n}\n\np.npf_color_joey,\nspan.npf_color_joey {\n\tcolor: $color-joey;\n}\n\np.npf_color_monica,\nspan.npf_color_monica {\n\tcolor: $color-monica;\n}\n\np.npf_color_phoebe,\nspan.npf_color_phoebe {\n\tcolor: $color-phoebe;\n}\n\np.npf_color_ross,\nspan.npf_color_ross {\n\tcolor: $color-ross;\n}\n\np.npf_color_rachel,\nspan.npf_color_rachel {\n\tcolor: $color-rachel;\n}\n\np.npf_color_chandler,\nspan.npf_color_chandler {\n\tcolor: $color-chandler;\n}\n\np.npf_color_niles,\nspan.npf_color_niles {\n\tcolor: $color-niles;\n}\n\np.npf_color_frasier,\nspan.npf_color_frasier {\n\tcolor: $color-frasier;\n}\n\np.npf_color_mr_big,\nspan.npf_color_mr_big {\n\tcolor: $color-mr-big;\n}\n","@use \"sass:math\";\n\n$post-full-width: 540px;\n$post-full-radius: 3px;\n$post-full-v-padding: 15px;\n$post-full-h-padding: 20px;\n$post-full-note-item-h-padding: 14px;\n$color-post-members-only: #900020;\n\n$font-size-content: 14px;\n$line-height-content: math.round(1.5 * $font-size-content);\n\n// those match NPF heading size better\n$font-size-content-heading1: 26px;\n$line-height-content-heading1: math.round(1.3 * $font-size-content-heading1);\n$font-size-content-heading2: 20px;\n$line-height-content-heading2: math.round(1.3 * $font-size-content-heading2);\n\n$font-size-content-heading-medium: 30px;\n$line-height-content-heading-medium: math.round(1.3 * $font-size-content-heading-medium);\n$font-size-content-heading-large: 36px;\n$line-height-content-heading-large: math.round(1.3 * $font-size-content-heading-large);\n\n$font-size-pre: 11px;\n$line-height-pre: $font-size-pre;\n\n$font-size-icon: 24px;\n$line-height-icon: 24px;\n\n$font-size-base: $font-size-content;\n$line-height-base: 1.4;\n\n$font-size-post-text-quirky: 24px;\n$line-height-post-text-quirky: 1.3em;\n\n// These omit `serif` and `sans-serf` to make it\n// possible to splice in additional fallbacks\n$font-family-sans-face: \"Helvetica Neue\", \"HelveticaNeue\", helvetica, arial;\n$font-family-serif-face: georgia, times, \"Times New Roman\";\n$font-family-monospace-face: courier;\n\n// Standard faces\n$font-family-sans: $font-family-sans-face, sans-serif;\n$font-family-serif: georgia, times, \"Times New Roman\", serif;\n$font-family-monospace: $font-family-monospace-face, monospace;\n$font-family-korean: $font-family-sans-face, \"AppleGothic\", \"Malgun Gothic\", \"Dotum\", \"Gulim\", sans-serif;\n\n// Named faces\n$font-family-gibson: \"Gibson\", $font-family-sans;\n$font-family-walsheim: \"Walsheim\", \"Helvetica Neue\", \"HelveticaNeue\", helvetica, arial, sans-serif;\n$font-family-franklin-medium: \"Franklin Gothic Medium\", $font-family-sans;\n$font-family-franklin-medium-condensed: \"Franklin Gothic Medium Condensed\", $font-family-sans;\n$font-family-franklin-compressed: \"Franklin Gothic Compressed\", $font-family-sans;\n$font-family-source-code-pro: \"Source Code Pro\", $font-family-monospace;\n\n// Default \"app\" font family\n$font-family-base: $font-family-sans;\n\n$color-white: #fff;\n$color-black: #000;\n$color-tumblr-black: #444;\n$color-tumblr-blue: #36465d;\n$color-tumblr-dark-blue: #001935;\n\n$color-dank-smoke: #9da6af;\n$color-gloomy-cloud: #748089;\n// The below have Neue Color variants\n$color-likable-red: #d95e40;\n$color-cheezbort: #f2992e;\n$color-always-sunny: #f7dd38;\n$color-reblog-green: #56bc8a;\n$color-neat-blue: #529ecc;\n$color-purple-rain: #a77dc2;\n\n// These replace old accent colors\n$color-joey: #ff492f; // Red\n$color-monica: #ff8a00; // Orange\n$color-phoebe: #e8d73a; // Yellow\n$color-ross: #00cf35; // Green\n$color-rachel: #00b8ff; // Light Blue\n$color-chandler: #7c5cff; // Purple\n// These are new\n$color-frasier: $color-tumblr-dark-blue; // Dark Blue, new brand color\n$color-niles: #ff62ce; // Pink\n$color-mr-big: #000c1a; // Off-Black\n$color-explicit-red: #ff4930; // project x red\n\n\n$color-gray-100: $color-tumblr-black; // #444444\n\n$color-gray-60: prima-mix($color-tumblr-black, 0.6); // #8f8f8f\n$color-gray-40: prima-mix($color-tumblr-black, 0.4); // #b4b4b4\n$color-gray-25: prima-mix($color-tumblr-black, 0.25); // #d0d0d0\n$color-gray-13: prima-mix($color-tumblr-black, 0.13); // #e7e7e7\n$color-gray-7: prima-mix($color-tumblr-black, 0.07); // #f2f2f2\n\n\n$color-gray-60-transparent: unmatte-gray($color-gray-60); // rgba(0, 0, 0, 0.439216)\n$color-gray-40-transparent: unmatte-gray($color-gray-40); // rgba(0, 0, 0, 0.294118)\n$color-gray-25-transparent: unmatte-gray($color-gray-25); // rgba(0, 0, 0, 0.184314)\n$color-gray-13-transparent: unmatte-gray($color-gray-13); // rgba(0, 0, 0, 0.0941176)\n$color-gray-7-transparent: unmatte-gray($color-gray-7); // rgba(0, 0, 0, 0.0509804)\n\n\n$color-white-60-transparent: prima-mix($color-white, 0.6, transparent); // rgba(255, 255, 255, 0.6);\n$color-white-40-transparent: prima-mix($color-white, 0.4, transparent); // rgba(255, 255, 255, 0.4);\n$color-white-25-transparent: prima-mix($color-white, 0.25, transparent); // rgba(255, 255, 255, 0.25);\n$color-white-13-transparent: prima-mix($color-white, 0.13, transparent); // rgba(255, 255, 255, 0.13);\n$color-white-7-transparent: prima-mix($color-white, 0.07, transparent); // rgba(255, 255, 255, 0.07);\n\n\n@mixin brandBlue($prop) {\n\t#{$prop}: $color-tumblr-dark-blue;\n}\n\n@mixin brandBlueGray($prop, $percent) {\n\t#{$prop}: prima-mix($color-white, 1 - $percent, $color-tumblr-dark-blue);\n}\n\n@mixin transparentBrandBlue($prop, $opacity) {\n\t#{$prop}: rgba($color-tumblr-dark-blue, $opacity);\n}\n\n$accentColors: (\n\t\"red\": $color-joey,\n\t\"orange\": $color-monica,\n\t\"yellow\": $color-phoebe,\n\t\"green\": $color-ross,\n\t\"blue\": $color-rachel,\n\t\"purple\": $color-chandler,\n\t\"black\": $color-black,\n\n\t\"video\": $color-niles,\n);\n\n@function newAccentColor($color) {\n\n\t@if (not map_has_key($accentColors, $color)) {\n\n\t\t@error 'Unrecognized accent color \"#{$color}\" in accentColor mixin';\n\t}\n\n\t@return map-get($accentColors, $color);\n}\n\n@mixin accentColor($prop, $color) {\n\t#{$prop}: newaccentcolor($color);\n}\n\n@mixin updatedWhite($opacity: 1, $prop: color) {\n\t#{$prop}: rgba($color-white, $opacity);\n}\n\n@mixin updatedBlack($opacity: 1, $prop: color) {\n\t#{$prop}: rgba($color-black, $opacity);\n}\n","// NPF link block styles\n\n$title-line-height: 34px;\n$description-line-height: 24px;\n\n@mixin text-cutoff {\n\toverflow: hidden;\n\toverflow-wrap: anywhere;\n\ttext-overflow: ellipsis;\n}\n\ndiv.npf-link-block {\n\talign-items: center;\n\tborder: 1px solid $color-gray-25;\n\tborder-radius: 6px;\n\tdisplay: flex;\n\tjustify-content: center;\n\tmargin: 15px 0;\n\toverflow: hidden;\n\n\t> a {\n\t\tcolor: inherit;\n\t\twidth: 100%;\n\t\ttext-decoration: none;\n\t}\n\n\t.title {\n\t\tfont-size: 25px;\n\t\tline-height: $title-line-height;\n\t\tmax-height: $title-line-height * 4; // This needs to be equal to (line-height * 4) - We want to show a maximum of 4 lines here\n\n\t\t@include text-cutoff;\n\t}\n\n\t&.no-poster .title {\n\t\tpadding: 16px 12px 0;\n\t}\n\n\t.poster {\n\t\talign-items: center;\n\t\tbackground-position: center;\n\t\tbackground-repeat: no-repeat;\n\t\tbackground-size: cover;\n\t\tbackground-clip: content-box;\n\t\tborder-bottom: 1px solid $color-gray-25;\n\t\tdisplay: flex;\n\t\theight: 250px;\n\t\tjustify-content: center;\n\t\tposition: relative;\n\n\t\t&::before {\n\t\t\tbackground: $color-black;\n\t\t\tcontent: \"\";\n\t\t\tdisplay: block;\n\t\t\theight: 100%;\n\t\t\topacity: 0.4;\n\t\t\tposition: absolute;\n\t\t\twidth: 100%;\n\t\t}\n\n\t\t.title {\n\t\t\tcolor: $color-white;\n\t\t\tfont-weight: 400;\n\t\t\tpadding: 16px 12px;\n\t\t\tposition: absolute;\n\t\t\ttext-align: center;\n\t\t}\n\t}\n\n\t.bottom {\n\t\tcolor: inherit;\n\t\tline-height: 24px;\n\t\tpadding: 8px 12px 16px;\n\n\t\t.description {\n\t\t\tcolor: inherit;\n\t\t\tfont-size: 16px;\n\t\t\tline-height: $description-line-height;\n\t\t\tmargin: 0;\n\t\t\tmax-height: $description-line-height * 2; // This needs to be equal to (line-height * 2) - We want to show a maximum of 2 lines here\n\n\t\t\t@include text-cutoff;\n\t\t}\n\n\t\t.site-name {\n\t\t\tcolor: inherit;\n\t\t\tfont-size: 12.5px;\n\t\t\tfont-weight: 400;\n\t\t\tline-height: 18px;\n\t\t\tmargin-top: 10px;\n\t\t\topacity: 0.65;\n\t\t\ttext-transform: uppercase;\n\t\t}\n\t}\n}\n","// NPF video block styles\nvideo,\naudio,\nimg,\n.wp-caption,\niframe {\n\tmax-width: 100%;\n}\n\n.tmblr-full > video {\n\theight: 100%;\n\twidth: 100%;\n}\n","// NPF image block styles - most importantly, to render NPF-created photosets.\n// stylelint-disable no-descending-specificity -- unnecessary.\n\n.post,\n.post-content,\nbody {\n // NPF photoset wrapper\n div.npf_row {\n align-items: stretch;\n display: flex;\n margin-top: 0;\n overflow: hidden;\n\n figure.tmblr-full {\n flex: 1;\n justify-content: space-between;\n margin: 0;\n overflow-y: hidden;\n }\n\n figure.tmblr-full,\n .npf_col {\n display: flex;\n flex-direction: column;\n padding-left: 2px;\n padding-right: 2px;\n\n &:first-child {\n padding-left: 0;\n }\n\n &:last-child {\n padding-right: 0;\n }\n }\n\n img {\n height: auto;\n }\n\n .npf_col {\n flex: 1;\n\n figure {\n position: relative;\n width: 100%;\n margin: 0;\n text-align: left;\n\n img {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n\n p.tmblr-attribution {\n box-sizing: border-box;\n width: 100%;\n }\n }\n }\n }\n\n figure[data-enable-lightbox=\"1\"] {\n cursor: pointer;\n }\n\n a.post_media_photo_anchor {\n cursor: pointer;\n flex: 1;\n text-decoration: none;\n }\n\n p + div.npf_row,\n div.npf_row + p {\n margin-top: 15px;\n }\n\n // Add a margin if following/preceding a video\n .crt-video + div.npf_row,\n div.npf_row + .crt-video {\n margin-top: 15px;\n }\n\n // Horizontal margins between photoset rows\n div.npf_row + figure.tmblr-full,\n div.npf_row + div.npf_row {\n margin-top: 4px;\n }\n}\n",".tmblr-full > audio {\n width: 100%;\n}\n\n.tmblr-full > .audio-caption {\n display: flex;\n flex-direction: row;\n\n .album-cover {\n width: 85px;\n height: 85px;\n }\n\n .audio-details {\n display: flex;\n flex: 1 0 auto;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n padding: 0 20px;\n }\n\n .title {\n font-weight: bold;\n line-height: 1.5;\n }\n\n .artist,\n .album {\n font-size: 0.875em;\n line-height: 1.5;\n }\n}\n"]} \ No newline at end of file diff --git a/assets/css/src/admin/_theme_garden.scss b/assets/css/src/admin/_theme_garden.scss index 16f6deb..1205b4b 100644 --- a/assets/css/src/admin/_theme_garden.scss +++ b/assets/css/src/admin/_theme_garden.scss @@ -1,5 +1,32 @@ $buttonWidth: 70px; +@mixin rainbow-button { + display: inline-block; + line-height: 24px; + padding: 0 20px; + font-size: 1em; + text-decoration: none; + border-radius: 4px; + color: var(--t3-button-text); + border: 1px solid var(--t3-primary); + background: var(--t3-primary); +} + +@mixin rainbow-button-hover { + background: repeating-linear-gradient( + 90deg, + var(--t3-red) 0%, + var(--t3-orange), + var(--t3-yellow), + var(--t3-green), + var(--t3-violet), + var(--t3-red) 50% + ); + background-size: 90px 100%; + animation: play 1.5s linear infinite; + color: #000; +} + body { --t3-primary: #49a2c4; --t3-secondary: #8eb2c0; @@ -153,13 +180,57 @@ body.admin-color-sunrise { 4px 0 0 0 var(--t3-text); } -.tumblr-theme-thumbnail { +.tumblr-theme-details { width: calc(100% - 4px); - height: auto; - aspect-ratio: 100/67; - object-fit: contain; border: 2px solid var(--t3-secondary); border-radius: 4px; + display: block; + position: relative; + overflow: hidden; + padding: 0; + + label { + display: none; + z-index: 2; + position: absolute; + } + + img { + width: 100%; + height: auto; + aspect-ratio: 100/67; + object-fit: contain; + margin-bottom: -6px; + z-index: 1; + } + + &:hover { + label { + top: 0; + left: 0; + width: 100%; + height: auto; + aspect-ratio: 100/67; + object-fit: contain; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + background: radial-gradient( + closest-side, + #0000 calc(100% - 1px), + var(--t3-background) + ) 0/ 3px 3px space; + } + + .tumblr-theme-detail-button { + @include rainbow-button; + @include rainbow-button-hover; + font-size: 16px; + font-weight: 600; + padding: 5px 20px; + } + } } .tumblr-theme-title { @@ -201,57 +272,22 @@ body.admin-color-sunrise { 20px 16px 0 var(--t3-text); } -.tumblr-theme-buttons { - display: flex; - justify-content: flex-end; - align-items: center; +.tumblr-theme-footer { position: relative; + text-align: right; margin: 10px 0 0; padding: 0; width: 100%; -} - -.tumblr-theme-buttons li { - flex: none; - display: block; - overflow: hidden; - position: relative; - margin-left: 10px; - border-radius: 4px; -} + a { + @include rainbow-button; -.tumblr-theme-buttons li a { - display: inline-block; - overflow: hidden; - width: 90px; - line-height: 24px; - font-size: 1em; - white-space: nowrap; - text-align: center; - text-decoration: none; - border-radius: inherit; - color: var(--t3-button-text); - border: 1px solid var(--t3-primary); - background: var(--t3-primary); -} - -.tumblr-theme-buttons li a:hover { - background: repeating-linear-gradient( - 90deg, - var(--t3-red) 0%, - var(--t3-orange), - var(--t3-yellow), - var(--t3-green), - var(--t3-violet), - var(--t3-red) 50% - ); - background-size: 90px 100%; - animation: play 1.5s linear infinite; - color: #000; + &:hover { + @include rainbow-button-hover; + } + } } - #t3-categories { margin: 10px; } diff --git a/assets/css/src/frontend/_global.scss b/assets/css/src/frontend/_global.scss index 02ce30e..3e284a3 100644 --- a/assets/css/src/frontend/_global.scss +++ b/assets/css/src/frontend/_global.scss @@ -1,9 +1,23 @@ body { - > .iframe-container { + >.iframe-container { display: none; } iframe[src*="https://www.tumblr.com/dashboard/iframe"] { display: none; } + + div.jetpack-likes-widget-wrapper.t3-likes { + min-height: 0px; + position: static; + + .likes-widget-placeholder.post-likes-widget-placeholder { + display: none; + } + + iframe { + width: 20px !important; + height: 20px !important; + } + } } \ No newline at end of file diff --git a/assets/js/build/customizer-rtl.css b/assets/js/build/customizer-rtl.css new file mode 100644 index 0000000..6a5e47f --- /dev/null +++ b/assets/js/build/customizer-rtl.css @@ -0,0 +1 @@ +.customize-control-code_editor .CodeMirror,.customize-control-code_editor textarea{height:100%}.customizer-resizer{display:none}.wp-full-overlay-sidebar{max-width:100%}.resizable .customizer-resizer{content:"";display:block;height:100%;width:4px;position:absolute;left:-4px;margin-top:-30px;cursor:pointer;cursor:col-resize;z-index:9999999;opacity:.8}.resizable .wp-full-overlay-sidebar{border-left-width:4px}.resizable .wp-full-overlay.collapsed .wp-full-overlay-sidebar{margin-right:-286px}.resizable.wp-core-ui .wp-full-overlay .collapse-sidebar{right:22px}.no-animation .wp-full-overlay,.no-animation .wp-full-overlay-sidebar,.no-animation .wp-full-overlay .collapse-sidebar,.no-animation .wp-full-overlay-main{transition:none}.fullwidth-customizer #customize-controls{width:100%}.fullwidth-customizer .wp-full-overlay.expanded{margin-right:0}.fullwidth-customizer .wp-full-overlay-sidebar .wp-full-overlay-sidebar-content{bottom:0}.fullwidth-customizer .customize-controls-preview-toggle{display:block;position:absolute;top:0;right:48px;line-height:45px;font-size:14px;padding:0 12px;margin:0;height:45px;background:#eee;border-left:1px solid #ddd;color:#444;cursor:pointer;transition:color .1s ease-in-out,background .1s ease-in-out}.fullwidth-customizer #customize-footer-actions,.fullwidth-customizer #customize-preview,.fullwidth-customizer .customize-controls-preview-toggle .controls,.fullwidth-customizer .preview-only .wp-full-overlay-sidebar-content,.fullwidth-customizer .preview-only .customize-controls-preview-toggle .preview{display:none}.fullwidth-customizer .customize-controls-preview-toggle .preview:before,.fullwidth-customizer .customize-controls-preview-toggle .controls:before{font:normal 20px/1 dashicons;content:"";position:relative;top:4px;margin-left:6px}.fullwidth-customizer .customize-controls-preview-toggle .controls:before{content:""}.fullwidth-customizer .preview-only #customize-controls{height:45px}.fullwidth-customizer .preview-only #customize-preview,.fullwidth-customizer .preview-only .customize-controls-preview-toggle .controls{display:block}.fullwidth-customizer #customize-preview{top:45px;bottom:0;height:auto}.fullwidth-customizer.wp-core-ui.wp-customizer .button{padding:6px 14px;line-height:normal;font-size:14px;vertical-align:middle;height:auto;margin-bottom:4px}.fullwidth-customizer.wp-core-ui.wp-customizer #customize-header-actions .button-primary{margin-top:6px} diff --git a/assets/js/build/customizer.asset.php b/assets/js/build/customizer.asset.php new file mode 100644 index 0000000..5ca915e --- /dev/null +++ b/assets/js/build/customizer.asset.php @@ -0,0 +1 @@ + array(), 'version' => '50d298de0e00f7abc982'); diff --git a/assets/js/build/customizer.css b/assets/js/build/customizer.css new file mode 100644 index 0000000..edc2789 --- /dev/null +++ b/assets/js/build/customizer.css @@ -0,0 +1 @@ +.customize-control-code_editor .CodeMirror,.customize-control-code_editor textarea{height:100%}.customizer-resizer{display:none}.wp-full-overlay-sidebar{max-width:100%}.resizable .customizer-resizer{content:"";display:block;height:100%;width:4px;position:absolute;right:-4px;margin-top:-30px;cursor:pointer;cursor:col-resize;z-index:9999999;opacity:.8}.resizable .wp-full-overlay-sidebar{border-right-width:4px}.resizable .wp-full-overlay.collapsed .wp-full-overlay-sidebar{margin-left:-286px}.resizable.wp-core-ui .wp-full-overlay .collapse-sidebar{left:22px}.no-animation .wp-full-overlay,.no-animation .wp-full-overlay-sidebar,.no-animation .wp-full-overlay .collapse-sidebar,.no-animation .wp-full-overlay-main{transition:none}.fullwidth-customizer #customize-controls{width:100%}.fullwidth-customizer .wp-full-overlay.expanded{margin-left:0}.fullwidth-customizer .wp-full-overlay-sidebar .wp-full-overlay-sidebar-content{bottom:0}.fullwidth-customizer .customize-controls-preview-toggle{display:block;position:absolute;top:0;left:48px;line-height:45px;font-size:14px;padding:0 12px;margin:0;height:45px;background:#eee;border-right:1px solid #ddd;color:#444;cursor:pointer;transition:color .1s ease-in-out,background .1s ease-in-out}.fullwidth-customizer #customize-footer-actions,.fullwidth-customizer #customize-preview,.fullwidth-customizer .customize-controls-preview-toggle .controls,.fullwidth-customizer .preview-only .wp-full-overlay-sidebar-content,.fullwidth-customizer .preview-only .customize-controls-preview-toggle .preview{display:none}.fullwidth-customizer .customize-controls-preview-toggle .preview:before,.fullwidth-customizer .customize-controls-preview-toggle .controls:before{font:normal 20px/1 dashicons;content:"";position:relative;top:4px;margin-right:6px}.fullwidth-customizer .customize-controls-preview-toggle .controls:before{content:""}.fullwidth-customizer .preview-only #customize-controls{height:45px}.fullwidth-customizer .preview-only #customize-preview,.fullwidth-customizer .preview-only .customize-controls-preview-toggle .controls{display:block}.fullwidth-customizer #customize-preview{top:45px;bottom:0;height:auto}.fullwidth-customizer.wp-core-ui.wp-customizer .button{padding:6px 14px;line-height:normal;font-size:14px;vertical-align:middle;height:auto;margin-bottom:4px}.fullwidth-customizer.wp-core-ui.wp-customizer #customize-header-actions .button-primary{margin-top:6px} diff --git a/assets/js/build/customizer.js b/assets/js/build/customizer.js new file mode 100644 index 0000000..6044dc5 --- /dev/null +++ b/assets/js/build/customizer.js @@ -0,0 +1 @@ +(()=>{"use strict";window.wp=window.wp||{},window.wp.customize=window.wp.customize||{},function(e,n,i,o){const t={};o.customize.resizer=t;let s=0,r=!1;t.cache=function(){t.$={},t.$.window=i(e),t.$.body=i(n.body),t.$.customizer=i(n.getElementById("customize-controls")),t.$.overlay=i(".wp-full-overlay.expanded"),t.$.collapser=i(".collapse-sidebar-label")},t.init=function(){t.cache(),t.$.customizer.append('
'),t.$.resizer=i(".customizer-resizer"),t.checkWidth(),t.events()},t.events=function(){t.initIframeMouseEvents(),t.$.resizer.on("mousedown",t.resizerEngage),t.$.collapser.on("click",t.snapToDefault),i(e).resize(_.debounce(t.checkWidth,50))},t.checkWidth=function(){if(t.$.window.width()<640)return r=!1,t.$.body.removeClass("resizable"),t.snapToDefault();r||(t.$.body.addClass("resizable"),r=!0)},t.resizerEngage=function(e){const o=t.$.window.width(),s=o-t.$.customizer.width();e.preventDefault(),s<100?(t.sizeCustomizer(o-320),t.fullWidth("no")):(t.$.customizer.addClass("no-animation"),i(n).on("mousemove",t.resizerMovement),i(n).on("mouseup",t.resizerDisengage))},t.resizerMovement=function(e){const n=s100?(t.snapToDefault(),t.resizerDisengage(),t.fullWidth("yes")):(t.fullWidth("no"),s>=320||s>=300&&n?t.sizeCustomizer(s):!n&&s>270&&s<320?t.snapToDefault():void(s<270&&(t.snapToDefault(),t.resizerDisengage(),t.$.collapser.trigger("click"))))},t.resizerDisengage=function(){i(n).off("mousemove",t.resizerMovement),i(n).off("mouseup",t.resizerDisengage),t.$.customizer.removeClass("no-animation")},t.fullWidth=function(e){const n="yes"===e?"addClass":"removeClass";t.$.body[n]("fullwidth-customizer")},t.snapToDefault=function(){t.sizeCustomizer()},t.sizeCustomizer=function(e){e=e||"",t.$.overlay.css({"margin-left":e}),t.$.resizer.css({"margin-left":e?e-5:e}),t.$.customizer.width(e)},t.initIframeMouseEvents=function(){setTimeout((function(){const e=t.$.overlay.find("iframe");e.length?(t.bubbleMouseEvent(e[0],"mousemove"),t.bubbleMouseEvent(e[0],"mouseup")):t.initIframeMouseEvents()}),500)},t.bubbleMouseEvent=function(i,o){const t="on"+o,s=i.contentWindow[t];i.contentWindow[t]=function(t){s&&s(t);const r=n.createEvent("MouseEvents"),u=i.getBoundingClientRect();r.initMouseEvent(o,!0,!1,e,t.detail,t.screenX,t.screenY,t.clientX+u.left,t.clientY+u.top,t.ctrlKey,t.altKey,t.shiftKey,t.metaKey,t.button,null),i.dispatchEvent(r)}},o.customize.bind("ready",t.init)}(window,document,jQuery,window.wp)})(); \ No newline at end of file diff --git a/assets/js/build/theme-garden.asset.php b/assets/js/build/theme-garden.asset.php index ba9ec76..fe561d5 100644 --- a/assets/js/build/theme-garden.asset.php +++ b/assets/js/build/theme-garden.asset.php @@ -1 +1 @@ - array('react', 'wp-api-fetch', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'fd810d3ceda54951e88a'); + array('react', 'wp-api-fetch', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '9727829e65ee1958b005'); diff --git a/assets/js/build/theme-garden.js b/assets/js/build/theme-garden.js index 58a588a..afe21f9 100644 --- a/assets/js/build/theme-garden.js +++ b/assets/js/build/theme-garden.js @@ -1 +1 @@ -(()=>{"use strict";var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var a in r)e.o(r,a)&&!e.o(t,a)&&Object.defineProperty(t,a,{enumerable:!0,get:r[a]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const t=window.React,r=window.wp.element,a=window.wp.i18n,s=window.wp.data,n=window.wp.compose,l=window.wp.apiFetch;var m=e.n(l);const c={logoUrl:themeGardenData.logoUrl,themes:themeGardenData.themes,categories:themeGardenData.categories,selectedCategory:themeGardenData.selectedCategory,search:themeGardenData.search,baseUrl:themeGardenData.baseUrl,isFetchingThemes:!1},o={receiveThemes:e=>({type:"RECEIVE_THEMES",themes:e}),prefetchThemes:()=>({type:"PREFETCH_THEMES"}),*fetchThemes(e){try{return i.FETCH_THEMES(e)}catch(e){throw new Error("Failed to update settings")}},*searchThemes(e){try{return i.SEARCH_THEMES(e)}catch(e){throw new Error("Failed to update settings")}}},h={getLogoUrl:()=>c.logoUrl,getInitialFilterBarProps:()=>({categories:c.categories,selectedCategory:c.selectedCategory,baseUrl:c.baseUrl,search:c.search}),getIsFetchingThemes:e=>e.isFetchingThemes,getThemes:e=>e.themes},i={FETCH_THEMES:e=>m()({path:"/tumblr3/v1/themes?category="+e,method:"GET"}).then((e=>e)).catch((e=>{throw e})),SEARCH_THEMES:e=>m()({path:"/tumblr3/v1/themes?search="+e,method:"GET"}).then((e=>e)).catch((e=>{throw console.error("API Error:",e),e}))},u=(0,s.createReduxStore)("tumblr3/theme-garden-store",{reducer:(e=c,t)=>{switch(t.type){case"PREFETCH_THEMES":return{...e,isFetchingThemes:!0};case"RECEIVE_THEMES":return{...e,themes:t.themes,isFetchingThemes:!1};default:return e}},actions:o,selectors:h,controls:i,resolvers:{}});(0,s.register)(u);const d=(0,n.compose)((0,s.withSelect)((e=>({initialProps:e("tumblr3/theme-garden-store").getInitialFilterBarProps(),themes:e("tumblr3/theme-garden-store").getThemes()}))),(0,s.withDispatch)((e=>({prefetchThemes:()=>e("tumblr3/theme-garden-store").prefetchThemes(),fetchThemes:t=>e("tumblr3/theme-garden-store").fetchThemes(t),searchThemes:t=>e("tumblr3/theme-garden-store").searchThemes(t),receiveThemes:t=>e("tumblr3/theme-garden-store").receiveThemes(t)}))))((({initialProps:{baseUrl:e,selectedCategory:s,categories:n,search:l},themes:m,fetchThemes:c,receiveThemes:o,prefetchThemes:h,searchThemes:i})=>{const[u,d]=(0,r.useState)(s),[g,E]=(0,r.useState)(l),[p,w]=(0,r.useState)(m),T=(0,r.useRef)();(0,r.useEffect)((()=>{w(m)}),[m]),(0,r.useEffect)((()=>(window.addEventListener("popstate",y),()=>{window.removeEventListener("popstate",y)})),[]);const b=async e=>{h();const t=await c(e);o(t)},y=async()=>{const e=new URLSearchParams(window.location.search),t=e.get("category")||"featured",r=e.get("search")||"";""!==r?E(r):(await b(t),d(t))};return(0,t.createElement)("div",{className:"wp-filter"},(0,t.createElement)("div",{className:"filter-count"},(0,t.createElement)("span",{className:"count"},p.length)),(0,t.createElement)("label",{htmlFor:"t3-categories"},(0,a.__)("Categories","tumblr3")),(0,t.createElement)("select",{id:"t3-categories",name:"category",onChange:async({currentTarget:t})=>{const r=t.value;await b(r),d(r),E(""),window.history.pushState({},"",e+"&category="+r)}},(0,t.createElement)("option",{value:"featured"},(0,a._x)("Featured","The name of a category in a list of categories.","tumblr3")),n.map((e=>(0,t.createElement)("option",{key:e.text_key,value:e.text_key,selected:u===e.text_key},e.name)))),(0,t.createElement)("p",{className:"search-box"},(0,t.createElement)("label",{htmlFor:"wp-filter-search-input"},"Search Themes"),(0,t.createElement)("input",{type:"search","aria-describedby":"live-search-desc",id:"wp-filter-search-input",className:"wp-filter-search",name:"search",value:g,onChange:async({currentTarget:t})=>{const r=t.value;clearTimeout(T.current),E(r),T.current=setTimeout((async()=>{await(async e=>{h();const t=await i(e);o(t)})(r),window.history.pushState({},"",e+"&search="+r),d("")}),500)}})))})),g=()=>{const e=[(0,a._x)("Sadly, nothing.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Tragically, nothing.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("We found nothing. Here it isn’t.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Couldn’t find that. Please, don’t be upset. Please.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Sincerely, we found nothing.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Nothing to see here.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("If you were looking for nothing, congrats, you found it.","The message displayed when no themes were found.","tumblr3")],r=Math.floor(Math.random()*e.length);return(0,t.createElement)("p",{className:"no-themes",id:"tumblr-no-themes"},e[r])},E=(0,n.compose)((0,s.withSelect)((e=>({themes:e("tumblr3/theme-garden-store").getThemes(),isFetchingThemes:e("tumblr3/theme-garden-store").getIsFetchingThemes()}))))((({themes:e,isFetchingThemes:s})=>{const[n,l]=(0,r.useState)(e);return(0,r.useEffect)((()=>{l(e)}),[e]),s?(0,t.createElement)("div",{className:"loading-content"},(0,t.createElement)("span",{className:"spinner"})):0===n.length?(0,t.createElement)(g,null):(0,t.createElement)("div",{className:"tumblr-themes"},e.map((e=>(0,t.createElement)("article",{className:"tumblr-theme",key:e.title},(0,t.createElement)("header",{className:"tumblr-theme-header"},(0,t.createElement)("div",{className:"tumblr-theme-title-wrapper"},(0,t.createElement)("span",{className:"tumblr-theme-title"},e.title))),(0,t.createElement)("div",{className:"tumblr-theme-content"},(0,t.createElement)("img",{className:"tumblr-theme-thumbnail",src:e.thumbnail,alt:""}),(0,t.createElement)("ul",{className:"tumblr-theme-buttons"},(0,t.createElement)("li",null,(0,t.createElement)("a",{href:e.activate_url},(0,a._x)("Activate","Text on a button to activate a theme.","tumblr3")))))))))})),p=(0,n.compose)((0,s.withSelect)((e=>({logoUrl:e("tumblr3/theme-garden-store").getLogoUrl()}))))((({logoUrl:e})=>(0,t.createElement)("div",{className:"wrap"},(0,t.createElement)("h1",{className:"wp-heading-inline",id:"theme-garden-heading"},(0,t.createElement)("img",{className:"tumblr-logo-icon",src:e,alt:""}),(0,t.createElement)("span",null,(0,a.__)("Tumblr Themes","tumblr3"))),(0,t.createElement)(d,null),(0,t.createElement)(E,null)))),w=document.getElementById("tumblr-theme-garden");w?(0,r.createRoot)(w).render((0,t.createElement)(p,null)):console.error("Failed to find the root element for the settings panel.")})(); \ No newline at end of file +(()=>{var e={942:(e,t)=>{var r;!function(){"use strict";var a={}.hasOwnProperty;function s(){for(var e="",t=0;t{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},r.d=(e,t)=>{for(var a in t)r.o(t,a)&&!r.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:t[a]})},r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{"use strict";const e=window.React,t=window.wp.element,a=window.wp.i18n,s=window.wp.data,n=window.wp.compose,l=window.wp.apiFetch;var c=r.n(l);const h={logoUrl:themeGardenData.logoUrl,categories:themeGardenData.categories,baseUrl:themeGardenData.baseUrl,themes:themeGardenData.themes,selectedCategory:themeGardenData.selectedCategory,search:themeGardenData.search,selectedThemeId:themeGardenData.selectedThemeId,themeDetails:themeGardenData.themeDetails,isFetchingThemes:!1,isOverlayOpen:!!themeGardenData.selectedThemeId,isFetchingTheme:!1},m={closeOverlay:()=>({type:"CLOSE_OVERLAY"}),receiveTheme:(e,t)=>({type:"RECEIVE_THEME",theme:e,id:t}),receiveThemes:(e,t,r)=>({type:"RECEIVE_THEMES",themes:e,category:t,search:r}),beforeFetchTheme:()=>({type:"BEFORE_FETCH_THEME"}),beforeFetchThemes:()=>({type:"BEFORE_FETCH_THEMES"}),*fetchThemes(e){try{return i.FETCH_THEMES(e)}catch(e){throw new Error("Failed to fetch themes")}},*searchThemes(e){try{return i.SEARCH_THEMES(e)}catch(e){throw new Error("Failed to search themes")}},*fetchTheme(e){try{return i.FETCH_THEME(e)}catch(e){throw new Error("Failed to fetch theme")}}},o={getBaseUrl:()=>h.baseUrl,getCategories:()=>h.categories,getLogoUrl:()=>h.logoUrl,getSelectedCategory:e=>e.selectedCategory,getSearch:e=>e.search,getIsFetchingThemes:e=>e.isFetchingThemes,getIsFetchingTheme:e=>e.isFetchingTheme,getThemes:e=>e.themes,getIsOverlayOpen:e=>e.isOverlayOpen,getThemeDetails:e=>e.themeDetails},i={FETCH_THEMES:e=>c()({path:"/tumblr3/v1/themes?category="+e,method:"GET"}).then((e=>e)).catch((e=>{throw e})),SEARCH_THEMES:e=>c()({path:"/tumblr3/v1/themes?search="+e,method:"GET"}).then((e=>e)).catch((e=>{throw console.error("API Error:",e),e})),FETCH_THEME:e=>c()({path:"/tumblr3/v1/theme?theme="+e,method:"GET"}).then((e=>e)).catch((e=>{throw console.error("API Error:",e),e}))},d=(0,s.createReduxStore)("tumblr3/theme-garden-store",{reducer:(e=h,t)=>{switch(t.type){case"BEFORE_FETCH_THEMES":return{...e,isFetchingThemes:!0};case"BEFORE_FETCH_THEME":return{...e,isFetchingTheme:!0,isOverlayOpen:!0};case"RECEIVE_THEMES":return{...e,themes:t.themes,isFetchingThemes:!1,selectedCategory:t.category,search:t.search};case"RECEIVE_THEME":return{...e,isFetchingTheme:!1,themeDetails:t.theme,selectedThemeId:t.id};case"CLOSE_OVERLAY":return{...e,isOverlayOpen:!1,isFetchingTheme:!1,themeDetails:null};default:return e}},actions:m,selectors:o,controls:i});(0,s.register)(d);const u=(0,n.compose)((0,s.withSelect)((e=>({baseUrl:e("tumblr3/theme-garden-store").getBaseUrl(),selectedCategory:e("tumblr3/theme-garden-store").getSelectedCategory(),categories:e("tumblr3/theme-garden-store").getCategories(),search:e("tumblr3/theme-garden-store").getSearch(),themes:e("tumblr3/theme-garden-store").getThemes()}))))((({baseUrl:r,selectedCategory:s,categories:n,search:l,themes:c,fetchThemesByQuery:h,fetchThemesByCategory:m})=>{const[o,i]=(0,t.useState)(s),[d,u]=(0,t.useState)(l),[g,E]=(0,t.useState)(c),b=(0,t.useRef)();return(0,t.useEffect)((()=>{E(c)}),[c]),(0,t.useEffect)((()=>{i(s)}),[s]),(0,t.useEffect)((()=>{u(l)}),[l]),(0,e.createElement)("div",{className:"wp-filter"},(0,e.createElement)("div",{className:"filter-count"},(0,e.createElement)("span",{className:"count"},g.length)),(0,e.createElement)("label",{htmlFor:"t3-categories"},(0,a._x)("Categories","label for a dropdown list of theme categories","tumblr3")),(0,e.createElement)("select",{id:"t3-categories",name:"category",onChange:async({currentTarget:e})=>{const t=e.value;i(t),await m(t),window.history.pushState({},"",r+"&category="+t)}},(0,e.createElement)("option",{value:"featured"},(0,a._x)("Featured","The name of a category in a list of categories.","tumblr3")),n.map((t=>(0,e.createElement)("option",{key:t.text_key,value:t.text_key,selected:o===t.text_key},t.name)))),(0,e.createElement)("p",{className:"search-box"},(0,e.createElement)("label",{htmlFor:"wp-filter-search-input"},(0,a._x)("Search Themes","label for a text input","tumblr3")),(0,e.createElement)("input",{type:"search","aria-describedby":"live-search-desc",id:"wp-filter-search-input",className:"wp-filter-search",name:"search",value:d,onChange:async({currentTarget:e})=>{const t=e.value;u(t),clearTimeout(b.current),b.current=setTimeout((async()=>{await h(t),window.history.pushState({},"",r+"&search="+t)}),500)}})))})),g=()=>{const t=[(0,a._x)("Sadly, nothing.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Tragically, nothing.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("We found nothing. Here it isn’t.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Couldn’t find that. Please, don’t be upset. Please.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Sincerely, we found nothing.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("Nothing to see here.","The message displayed when no themes were found.","tumblr3"),(0,a._x)("If you were looking for nothing, congrats, you found it.","The message displayed when no themes were found.","tumblr3")],r=Math.floor(Math.random()*t.length);return(0,e.createElement)("p",{className:"no-themes",id:"tumblr-no-themes"},t[r])},E=(0,n.compose)((0,s.withSelect)((e=>({themes:e("tumblr3/theme-garden-store").getThemes(),isFetchingThemes:e("tumblr3/theme-garden-store").getIsFetchingThemes()}))),(0,s.withDispatch)((e=>({closeOverlay:()=>e("tumblr3/theme-garden-store").closeOverlay()}))))((({themes:r,isFetchingThemes:s,fetchThemeById:n})=>{const[l,c]=(0,t.useState)(r);(0,t.useEffect)((()=>{c(r)}),[r]);const h=async({currentTarget:{value:e}})=>{const t=new URL(window.location.href),r=new URLSearchParams(t.search);r.append("theme",e),t.search=r.toString(),await n(e),window.history.pushState({},"",t.toString())};return s?(0,e.createElement)("div",{className:"loading-content"},(0,e.createElement)("span",{className:"spinner"})):0===l.length?(0,e.createElement)(g,null):(0,e.createElement)("div",{className:"tumblr-themes"},r.map((t=>{const r=`t3-theme-details-${t.id}`;return(0,e.createElement)("article",{className:"tumblr-theme",key:t.title},(0,e.createElement)("header",{className:"tumblr-theme-header"},(0,e.createElement)("div",{className:"tumblr-theme-title-wrapper"},(0,e.createElement)("span",{className:"tumblr-theme-title"},t.title))),(0,e.createElement)("div",{className:"tumblr-theme-content"},(0,e.createElement)("button",{className:"tumblr-theme-details",onClick:h,value:t.id,id:r},(0,e.createElement)("label",{htmlFor:r},(0,e.createElement)("span",{className:"tumblr-theme-detail-button"},(0,a._x)("Theme details","Text on a button that will show more information about a Tumblr theme","tumblr3"))),(0,e.createElement)("img",{src:t.thumbnail,alt:""})),(0,e.createElement)("div",{className:"tumblr-theme-footer"},(0,e.createElement)("a",{className:"rainbow-button",href:t.activate_url},"Activate"))))})))}));var b=r(942),p=r.n(b);const w=(0,n.compose)((0,s.withSelect)((e=>({themes:e("tumblr3/theme-garden-store").getThemes(),isOverlayOpen:e("tumblr3/theme-garden-store").getIsOverlayOpen(),isFetchingTheme:e("tumblr3/theme-garden-store").getIsFetchingTheme(),themeDetails:e("tumblr3/theme-garden-store").getThemeDetails()}))),(0,s.withDispatch)((e=>({closeOverlay:()=>e("tumblr3/theme-garden-store").closeOverlay()}))))((({themes:r,isOverlayOpen:s,isFetchingTheme:n,closeOverlay:l,themeDetails:c,fetchThemeById:h})=>{const m=(0,t.useCallback)((()=>{const e=new URL(window.location.href),t=new URLSearchParams(e.search);t.delete("theme"),e.search=t.toString(),window.history.pushState({},"",e.toString()),l()}),[l]),o=(0,t.useCallback)((()=>n||!c?(0,e.createElement)("div",{className:"loading-content wp-clearfix"},(0,e.createElement)("span",{className:"spinner"})):(0,e.createElement)("div",{className:"theme-about wp-clearfix"},(0,e.createElement)("div",{className:"theme-screenshots"},(0,e.createElement)("div",{className:"screenshot"},(0,e.createElement)("img",{src:c.screenshots[0],alt:""}))),(0,e.createElement)("div",{className:"theme-info"},(0,e.createElement)("h2",{className:"theme-name"},c.title),(0,e.createElement)("div",{dangerouslySetInnerHTML:{__html:c.description}})))),[c,n]),i=(0,t.useCallback)((async e=>{const t=new URL(window.location.href),a=new URLSearchParams(t.search),s=r[e].id;a.delete("theme"),a.append("theme",s),t.search=a.toString(),await h(s),window.history.pushState({},"",t.toString())}),[r,h]),d=(0,t.useCallback)((()=>{const t=r.findIndex((e=>e.id===c.id)),s=-1===t||0===t,n=-1===t||t===r.length-1;return(0,e.createElement)("div",{className:"theme-header"},(0,e.createElement)("button",{className:p()("left","dashicons","dashicons-no",{disabled:s}),disabled:s,onClick:()=>i(t-1)},(0,e.createElement)("span",{className:"screen-reader-text"},(0,a._x)("Show previous theme","label for a button that will navigate to previous theme","tumblr3"))),(0,e.createElement)("button",{className:p()("right","dashicons","dashicons-no",{disabled:n}),disabled:n,onClick:()=>i(t+1)},(0,e.createElement)("span",{className:"screen-reader-text"},(0,a._x)("Show next theme","label for a button that will navigate to next theme","tumblr3"))),(0,e.createElement)("button",{className:"close dashicons dashicons-no",onClick:m},(0,e.createElement)("span",{className:"screen-reader-text"},(0,a._x)("Close theme details overlay","label for a button that will close an overlay","tumblr3"))))}),[c,r,i,m]);return s&&c?(0,e.createElement)("div",{className:"theme-overlay",id:"tumblr-theme-overlay"},(0,e.createElement)("div",{className:"theme-backdrop"}),(0,e.createElement)("div",{className:"theme-wrap wp-clearfix"},d(),o())):null})),T=(0,n.compose)((0,s.withSelect)((e=>({logoUrl:e("tumblr3/theme-garden-store").getLogoUrl(),selectedCategory:e("tumblr3/theme-garden-store").getSelectedCategory(),search:e("tumblr3/theme-garden-store").getSearch()}))),(0,s.withDispatch)((e=>({beforeFetchThemes:()=>e("tumblr3/theme-garden-store").beforeFetchThemes(),fetchThemes:t=>e("tumblr3/theme-garden-store").fetchThemes(t),searchThemes:t=>e("tumblr3/theme-garden-store").searchThemes(t),receiveThemes:(t,r,a)=>e("tumblr3/theme-garden-store").receiveThemes(t,r,a),beforeFetchTheme:()=>e("tumblr3/theme-garden-store").beforeFetchTheme(),fetchTheme:t=>e("tumblr3/theme-garden-store").fetchTheme(t),receiveTheme:(t,r)=>e("tumblr3/theme-garden-store").receiveTheme(t,r),closeOverlay:()=>e("tumblr3/theme-garden-store").closeOverlay()}))))((({logoUrl:r,beforeFetchThemes:s,fetchThemes:n,receiveThemes:l,searchThemes:c,beforeFetchTheme:h,fetchTheme:m,receiveTheme:o,closeOverlay:i,search:d,selectedCategory:g})=>{const b=(0,t.useCallback)((async e=>{s();const t=await n(e);l(t,e,"")}),[s,l,n]),p=(0,t.useCallback)((async e=>{s();const t=await c(e);l(t,"",e)}),[s,l,c]),T=(0,t.useCallback)((async()=>{const e=new URLSearchParams(window.location.search),t=e.get("category")||"featured",r=e.get("search")||"",a=e.get("theme")||"";if(""!==r&&r!==d?await p(r):""!==t&&t!==g&&await b(t),""!==a){h();const e=await m(a);o(e,a)}else i()}),[g,d,h,i,m,b,p,o]);(0,t.useEffect)((()=>(window.addEventListener("popstate",T),()=>{window.removeEventListener("popstate",T)})),[T]);const y=(0,t.useCallback)((async e=>{h();const t=await m(e);o(t,e)}),[h,o,m]);return(0,e.createElement)("div",{className:"wrap"},(0,e.createElement)("h1",{className:"wp-heading-inline",id:"theme-garden-heading"},(0,e.createElement)("img",{className:"tumblr-logo-icon",src:r,alt:""}),(0,e.createElement)("span",null,(0,a.__)("Tumblr Themes","tumblr3"))),(0,e.createElement)(u,{fetchThemesByCategory:b,fetchThemesByQuery:p}),(0,e.createElement)(E,{fetchThemeById:y}),(0,e.createElement)(w,{fetchThemeById:y}))})),y=document.getElementById("tumblr-theme-garden");y?(0,t.createRoot)(y).render((0,e.createElement)(T,null)):console.error("Failed to find the root element for the settings panel.")})()})(); \ No newline at end of file diff --git a/assets/js/src/components/theme-garden-filterbar.js b/assets/js/src/components/theme-garden-filterbar.js index 412f2c4..fac720f 100644 --- a/assets/js/src/components/theme-garden-filterbar.js +++ b/assets/js/src/components/theme-garden-filterbar.js @@ -1,115 +1,77 @@ import { useState, useEffect, useRef } from '@wordpress/element'; -import { __, _x } from '@wordpress/i18n'; -import { withDispatch, withSelect } from '@wordpress/data'; +import { _x } from '@wordpress/i18n'; +import { withSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; import './theme-garden-store'; /** * This component appears at the top of the theme browser, and has a category selector and a search bar. * - * Class names reference built-in wp-admin styles, and styles declared in _theme_garden.scss. + * CSS classNames reference built-in wp-admin styles, and styles declared in _theme_garden.scss. * * @param {Object} props - * @param {Object} props.initialProps - * @param {string} props.initialProps.baseUrl - * @param {string} props.initialProps.selectedCategory - * @param {Array} props.initialProps.categories - * @param {string } props.initialProps.search + * @param {string} props.baseUrl + * @param {string} props.selectedCategory + * @param {Array} props.categories + * @param {string } props.search * @param {Array} props.themes - * @param {Function} props.fetchThemes - * @param {Function} props.receiveThemes - * @param {Function} props.prefetchThemes - * @param {Function} props.searchThemes + * @param {Function} props.fetchThemesByCategory + * @param {Function} props.fetchThemesByQuery */ const _ThemeGardenFilterBar = ( { - initialProps: { - baseUrl, - selectedCategory: initialSelectedCategory, - categories, - search: initialSearch, - }, + baseUrl, + selectedCategory, + categories, + search, themes, - fetchThemes, - receiveThemes, - prefetchThemes, - searchThemes, + fetchThemesByQuery, + fetchThemesByCategory, } ) => { - const [ selectedCategory, setSelectedCategory ] = useState( initialSelectedCategory ); - const [ search, setSearch ] = useState( initialSearch ); - const [ themeList, setThemeList ] = useState( themes ); + const [ localSelectedCategory, setLocalSelectedCategory ] = useState( selectedCategory ); + const [ localSearch, setLocalSearch ] = useState( search ); + const [ localThemes, setLocalThemes ] = useState( themes ); const timerRef = useRef(); /** - * Whenever themes from the store change, re-render the component. + * Listeners to detect changes in the store, and update local state. + * Changes in the store will come from back/forward browser navigation which is handled in theme-garden.js. */ useEffect( () => { - setThemeList( themes ); + setLocalThemes( themes ); }, [ themes ] ); - - /** - * Detect backwards and forwards browser navigation. - */ useEffect( () => { - window.addEventListener( 'popstate', onBrowserNavigation ); - return () => { - window.removeEventListener( 'popstate', onBrowserNavigation ); - }; - }, [] ); - - const fetchThemesByCategory = async category => { - prefetchThemes(); - const response = await fetchThemes( category ); - receiveThemes( response ); - }; - - const fetchThemesByQuery = async newSearch => { - prefetchThemes(); - const response = await searchThemes( newSearch ); - receiveThemes( response ); - }; - - /** - * After backwards or forwards navigation, check URL search params for indicators that we have to re-fetch themes. - * - * @return {Promise} - */ - const onBrowserNavigation = async () => { - const urlParams = new URLSearchParams( window.location.search ); - const category = urlParams.get( 'category' ) || 'featured'; - const searchParam = urlParams.get( 'search' ) || ''; - if ( searchParam !== '' ) { - setSearch( searchParam ); - } else { - await fetchThemesByCategory( category ); - setSelectedCategory( category ); - } - }; + setLocalSelectedCategory( selectedCategory ); + }, [ selectedCategory ] ); + useEffect( () => { + setLocalSearch( search ); + }, [ search ] ); const onChangeCategory = async ( { currentTarget } ) => { const newCategory = currentTarget.value; + setLocalSelectedCategory( newCategory ); await fetchThemesByCategory( newCategory ); - setSelectedCategory( newCategory ); - setSearch( '' ); window.history.pushState( {}, '', baseUrl + '&category=' + newCategory ); }; const onChangeSearch = async ( { currentTarget } ) => { const newSearch = currentTarget.value; + setLocalSearch( newSearch ); + // Debounce so we don't send multiple requests while user is typing. clearTimeout( timerRef.current ); - setSearch( newSearch ); timerRef.current = setTimeout( async () => { await fetchThemesByQuery( newSearch ); window.history.pushState( {}, '', baseUrl + '&search=' + newSearch ); - setSelectedCategory( '' ); }, 500 ); }; return (
- { themeList.length } + { localThemes.length }
- +

- +

@@ -144,21 +108,10 @@ const _ThemeGardenFilterBar = ( { export const ThemeGardenFilterBar = compose( withSelect( select => ( { - initialProps: select( 'tumblr3/theme-garden-store' ).getInitialFilterBarProps(), + baseUrl: select( 'tumblr3/theme-garden-store' ).getBaseUrl(), + selectedCategory: select( 'tumblr3/theme-garden-store' ).getSelectedCategory(), + categories: select( 'tumblr3/theme-garden-store' ).getCategories(), + search: select( 'tumblr3/theme-garden-store' ).getSearch(), themes: select( 'tumblr3/theme-garden-store' ).getThemes(), - } ) ), - withDispatch( dispatch => ( { - prefetchThemes: () => { - return dispatch( 'tumblr3/theme-garden-store' ).prefetchThemes(); - }, - fetchThemes: category => { - return dispatch( 'tumblr3/theme-garden-store' ).fetchThemes( category ); - }, - searchThemes: query => { - return dispatch( 'tumblr3/theme-garden-store' ).searchThemes( query ); - }, - receiveThemes: themes => { - return dispatch( 'tumblr3/theme-garden-store' ).receiveThemes( themes ); - }, } ) ) )( _ThemeGardenFilterBar ); diff --git a/assets/js/src/components/theme-garden-list.js b/assets/js/src/components/theme-garden-list.js index d31535c..d9aa799 100644 --- a/assets/js/src/components/theme-garden-list.js +++ b/assets/js/src/components/theme-garden-list.js @@ -1,5 +1,5 @@ import { useEffect, useState } from '@wordpress/element'; -import { withSelect } from '@wordpress/data'; +import { withDispatch, withSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; import { _x } from '@wordpress/i18n'; import { ThemeGardenNoThemes } from './theme-garden-no-themes'; @@ -8,19 +8,29 @@ import './theme-garden-store'; /** * Displays a list of Tumblr themes. * - * Class names reference built-in wp-admin styles, and styles declared in _theme_garden.scss. + * CSS classNames reference built-in wp-admin styles, and styles declared in _theme_garden.scss. * - * @param {Object} props - * @param {Array} props.themes - * @param {boolean} props.isFetchingThemes + * @param {Object} props + * @param {Array} props.themes + * @param {boolean} props.isFetchingThemes + * @param {Function} props.fetchThemeById */ -const _ThemeGardenList = ( { themes, isFetchingThemes } ) => { +const _ThemeGardenList = ( { themes, isFetchingThemes, fetchThemeById } ) => { const [ localThemes, setLocalThemes ] = useState( themes ); useEffect( () => { setLocalThemes( themes ); }, [ themes ] ); + const handleDetailsClick = async ( { currentTarget: { value: themeId } } ) => { + const currentUrl = new URL( window.location.href ); + const params = new URLSearchParams( currentUrl.search ); + params.append( 'theme', themeId ); + currentUrl.search = params.toString(); + await fetchThemeById( themeId ); + window.history.pushState( {}, '', currentUrl.toString() ); + }; + if ( isFetchingThemes ) { return (
@@ -35,25 +45,42 @@ const _ThemeGardenList = ( { themes, isFetchingThemes } ) => { return ( +
+ + ); + } ) }
); }; @@ -62,5 +89,10 @@ export const ThemeGardenList = compose( withSelect( select => ( { themes: select( 'tumblr3/theme-garden-store' ).getThemes(), isFetchingThemes: select( 'tumblr3/theme-garden-store' ).getIsFetchingThemes(), + } ) ), + withDispatch( dispatch => ( { + closeOverlay: () => { + return dispatch( 'tumblr3/theme-garden-store' ).closeOverlay(); + }, } ) ) )( _ThemeGardenList ); diff --git a/assets/js/src/components/theme-garden-no-themes.js b/assets/js/src/components/theme-garden-no-themes.js index f17b92a..a520391 100644 --- a/assets/js/src/components/theme-garden-no-themes.js +++ b/assets/js/src/components/theme-garden-no-themes.js @@ -3,7 +3,7 @@ import { _x } from '@wordpress/i18n'; /** * These playful messages were written by Tumblr staff. * - * Class names reference built-in wp-admin styles, and styles declared in _theme_garden.scss. + * CSS classNames reference built-in wp-admin styles, and styles declared in _theme_garden.scss. */ export const ThemeGardenNoThemes = () => { const playfulNoThemesText = [ diff --git a/assets/js/src/components/theme-garden-overlay.js b/assets/js/src/components/theme-garden-overlay.js new file mode 100644 index 0000000..78eb7fb --- /dev/null +++ b/assets/js/src/components/theme-garden-overlay.js @@ -0,0 +1,152 @@ +import { useCallback } from '@wordpress/element'; +import { withDispatch, withSelect } from '@wordpress/data'; +import { compose } from '@wordpress/compose'; +import { _x } from '@wordpress/i18n'; +import classNames from 'classnames'; + +/** + * Displays an overlay with details about a Tumblr theme. + * + * CSS classNames reference built-in wp-admin styles, and styles declared in _theme_garden.scss. + * + * @param {Object} props + * @param {Array} props.themes + * @param {boolean} props.isOverlayOpen + * @param {boolean} props.isFetchingTheme + * @param {Function} props.closeOverlay + * @param {Object} props.themeDetails + * @param {Function} props.fetchThemeById + */ +const _ThemeGardenOverlay = ( { + themes, + isOverlayOpen, + isFetchingTheme, + closeOverlay, + themeDetails, + fetchThemeById, +} ) => { + const handleCloseClick = useCallback( () => { + const currentUrl = new URL( window.location.href ); + const params = new URLSearchParams( currentUrl.search ); + params.delete( 'theme' ); + currentUrl.search = params.toString(); + window.history.pushState( {}, '', currentUrl.toString() ); + closeOverlay(); + }, [ closeOverlay ] ); + + const renderThemeDetails = useCallback( () => { + if ( isFetchingTheme || ! themeDetails ) { + return ( +
+ +
+ ); + } + + return ( +
+
+
+ +
+
+
+

{ themeDetails.title }

+
+
+
+ ); + }, [ themeDetails, isFetchingTheme ] ); + + const onClickNavigate = useCallback( + async nextIndex => { + const currentUrl = new URL( window.location.href ); + const params = new URLSearchParams( currentUrl.search ); + const nextId = themes[ nextIndex ].id; + params.delete( 'theme' ); + params.append( 'theme', nextId ); + currentUrl.search = params.toString(); + await fetchThemeById( nextId ); + window.history.pushState( {}, '', currentUrl.toString() ); + }, + [ themes, fetchThemeById ] + ); + + const renderThemeHeader = useCallback( () => { + const currentIndex = themes.findIndex( theme => theme.id === themeDetails.id ); + const prevButtonDisabled = currentIndex === -1 || currentIndex === 0; + const nextButtonDisabled = currentIndex === -1 || currentIndex === themes.length - 1; + + return ( +
+ + + +
+ ); + }, [ themeDetails, themes, onClickNavigate, handleCloseClick ] ); + + if ( ! isOverlayOpen || ! themeDetails ) { + return null; + } + + return ( +
+
+
+ { renderThemeHeader() } + { renderThemeDetails() } +
+
+ ); +}; + +export const ThemeGardenOverlay = compose( + withSelect( select => ( { + themes: select( 'tumblr3/theme-garden-store' ).getThemes(), + isOverlayOpen: select( 'tumblr3/theme-garden-store' ).getIsOverlayOpen(), + isFetchingTheme: select( 'tumblr3/theme-garden-store' ).getIsFetchingTheme(), + themeDetails: select( 'tumblr3/theme-garden-store' ).getThemeDetails(), + } ) ), + withDispatch( dispatch => ( { + closeOverlay: () => { + return dispatch( 'tumblr3/theme-garden-store' ).closeOverlay(); + }, + } ) ) +)( _ThemeGardenOverlay ); diff --git a/assets/js/src/components/theme-garden-store.js b/assets/js/src/components/theme-garden-store.js index 373235c..1ab58c1 100644 --- a/assets/js/src/components/theme-garden-store.js +++ b/assets/js/src/components/theme-garden-store.js @@ -4,74 +4,132 @@ import { createReduxStore, register } from '@wordpress/data'; /** * Default state is loaded from an inline script declared in ThemeGarden.php. */ - -/*ignore jslint start*/ const DEFAULT_STATE = { + // The following properties are static and will not change. logoUrl: themeGardenData.logoUrl, // eslint-disable-line no-undef - themes: themeGardenData.themes, // eslint-disable-line no-undef categories: themeGardenData.categories, // eslint-disable-line no-undef + baseUrl: themeGardenData.baseUrl, // eslint-disable-line no-undef + + // The following properties will change during usage of the app. + themes: themeGardenData.themes, // eslint-disable-line no-undef selectedCategory: themeGardenData.selectedCategory, // eslint-disable-line no-undef search: themeGardenData.search, // eslint-disable-line no-undef - baseUrl: themeGardenData.baseUrl, // eslint-disable-line no-undef + selectedThemeId: themeGardenData.selectedThemeId, // eslint-disable-line no-undef + themeDetails: themeGardenData.themeDetails, // eslint-disable-line no-undef isFetchingThemes: false, + isOverlayOpen: !! themeGardenData.selectedThemeId, // eslint-disable-line no-undef + isFetchingTheme: false, }; -/*ignore jslint end*/ const reducer = ( state = DEFAULT_STATE, action ) => { switch ( action.type ) { - case 'PREFETCH_THEMES': + case 'BEFORE_FETCH_THEMES': return { ...state, isFetchingThemes: true }; + case 'BEFORE_FETCH_THEME': + return { ...state, isFetchingTheme: true, isOverlayOpen: true }; case 'RECEIVE_THEMES': - return { ...state, themes: action.themes, isFetchingThemes: false }; + return { + ...state, + themes: action.themes, + isFetchingThemes: false, + selectedCategory: action.category, + search: action.search, + }; + case 'RECEIVE_THEME': + return { + ...state, + isFetchingTheme: false, + themeDetails: action.theme, + selectedThemeId: action.id, + }; + case 'CLOSE_OVERLAY': + return { ...state, isOverlayOpen: false, isFetchingTheme: false, themeDetails: null }; default: return state; } }; const actions = { - receiveThemes( themes ) { + closeOverlay() { + return { + type: 'CLOSE_OVERLAY', + }; + }, + receiveTheme( theme, id ) { + return { + type: 'RECEIVE_THEME', + theme, + id, + }; + }, + receiveThemes( themes, category, search ) { return { type: 'RECEIVE_THEMES', themes, + category, + search, }; }, - prefetchThemes() { - return { type: 'PREFETCH_THEMES' }; + beforeFetchTheme() { + return { type: 'BEFORE_FETCH_THEME' }; + }, + beforeFetchThemes() { + return { type: 'BEFORE_FETCH_THEMES' }; }, *fetchThemes( category ) { try { return controls.FETCH_THEMES( category ); } catch ( error ) { - throw new Error( 'Failed to update settings' ); + throw new Error( 'Failed to fetch themes' ); } }, *searchThemes( query ) { try { return controls.SEARCH_THEMES( query ); } catch ( error ) { - throw new Error( 'Failed to update settings' ); + throw new Error( 'Failed to search themes' ); + } + }, + *fetchTheme( id ) { + try { + return controls.FETCH_THEME( id ); + } catch ( error ) { + throw new Error( 'Failed to fetch theme' ); } }, }; const selectors = { + getBaseUrl() { + return DEFAULT_STATE.baseUrl; + }, + getCategories() { + return DEFAULT_STATE.categories; + }, getLogoUrl() { return DEFAULT_STATE.logoUrl; }, - getInitialFilterBarProps() { - return { - categories: DEFAULT_STATE.categories, - selectedCategory: DEFAULT_STATE.selectedCategory, - baseUrl: DEFAULT_STATE.baseUrl, - search: DEFAULT_STATE.search, - }; + getSelectedCategory( state ) { + return state.selectedCategory; + }, + getSearch( state ) { + return state.search; }, getIsFetchingThemes( state ) { return state.isFetchingThemes; }, + getIsFetchingTheme( state ) { + return state.isFetchingTheme; + }, getThemes( state ) { return state.themes; }, + getIsOverlayOpen( state ) { + return state.isOverlayOpen; + }, + getThemeDetails( state ) { + return state.themeDetails; + }, }; const controls = { @@ -100,16 +158,26 @@ const controls = { throw error; } ); }, + FETCH_THEME( id ) { + return apiFetch( { + path: '/tumblr3/v1/theme?theme=' + id, + method: 'GET', + } ) + .then( response => { + return response; + } ) + .catch( error => { + console.error( 'API Error:', error ); // eslint-disable-line no-console + throw error; + } ); + }, }; -const resolvers = {}; - const store = createReduxStore( 'tumblr3/theme-garden-store', { reducer, actions, selectors, controls, - resolvers, } ); register( store ); diff --git a/assets/js/src/customizer.js b/assets/js/src/customizer.js new file mode 100644 index 0000000..c64e1e0 --- /dev/null +++ b/assets/js/src/customizer.js @@ -0,0 +1,207 @@ +/* global _ */ +/* global jQuery */ + +import './customizer.scss'; + +window.wp = window.wp || {}; +window.wp.customize = window.wp.customize || {}; + +( function ( window, document, $, wp ) { + 'use strict'; + + const app = {}; + wp.customize.resizer = app; + let mouseLeft = 0; + let expanded = false; + + app.cache = function () { + app.$ = {}; + app.$.window = $( window ); + app.$.body = $( document.body ); + app.$.customizer = $( document.getElementById( 'customize-controls' ) ); + app.$.overlay = $( '.wp-full-overlay.expanded' ); + app.$.collapser = $( '.collapse-sidebar-label' ); + }; + + app.init = function () { + app.cache(); + + app.$.customizer.append( '
' ); + app.$.resizer = $( '.customizer-resizer' ); + app.checkWidth(); + + app.events(); + }; + + app.events = function () { + // We need the iframe to bubble up mouse events + app.initIframeMouseEvents(); + + app.$.resizer.on( 'mousedown', app.resizerEngage ); + app.$.collapser.on( 'click', app.snapToDefault ); + $( window ).resize( _.debounce( app.checkWidth, 50 ) ); + }; + + app.checkWidth = function () { + const winWidth = app.$.window.width(); + + // the breakpoint where mobile view is triggered. + if ( winWidth < 640 ) { + expanded = false; + app.$.body.removeClass( 'resizable' ); + return app.snapToDefault(); + } + + if ( ! expanded ) { + app.$.body.addClass( 'resizable' ); + expanded = true; + } + }; + + app.resizerEngage = function ( evt ) { + const winWidth = app.$.window.width(); + const iframeWidth = winWidth - app.$.customizer.width(); + + evt.preventDefault(); + + if ( iframeWidth < 100 ) { + /* + Decrease customizer width below + threshold where it snaps to full-width + */ + app.sizeCustomizer( winWidth - 320 ); + app.fullWidth( 'no' ); + } else { + // Disable customizer sizing animation + app.$.customizer.addClass( 'no-animation' ); + + // add event listeners for the dragging duration + $( document ).on( 'mousemove', app.resizerMovement ); + $( document ).on( 'mouseup', app.resizerDisengage ); + } + }; + + app.resizerMovement = function ( evt ) { + // Check if the customizer is expanding (vs shrinking) + const expanding = mouseLeft < evt.pageX; + // Re-cache mouseLeft + mouseLeft = evt.pageX; + + const iframeWidth = app.$.window.width() - mouseLeft; + + // If iframe width is less than a workable width, snap full-screen + if ( iframeWidth < 300 && iframeWidth > 100 ) { + app.snapToDefault(); + app.resizerDisengage(); + + return app.fullWidth( 'yes' ); + } + + app.fullWidth( 'no' ); + + // If we're expanding larger than default, increae the width + if ( mouseLeft >= 320 || ( mouseLeft >= 300 && expanding ) ) { + return app.sizeCustomizer( mouseLeft ); + } + + // If we're condensing, and close to our default, snap to it + if ( ! expanding && mouseLeft > 270 && mouseLeft < 320 ) { + return app.snapToDefault(); + } + + // If we're condensing past our default, just trigger the collapse + if ( mouseLeft < 270 ) { + app.snapToDefault(); + app.resizerDisengage(); + app.$.collapser.trigger( 'click' ); + } + }; + + app.resizerDisengage = function () { + // remove temp. event listeners + $( document ).off( 'mousemove', app.resizerMovement ); + $( document ).off( 'mouseup', app.resizerDisengage ); + + // Re-enable customizer sizing animation + app.$.customizer.removeClass( 'no-animation' ); + }; + + app.fullWidth = function ( makeFull ) { + const method = 'yes' === makeFull ? 'addClass' : 'removeClass'; + app.$.body[ method ]( 'fullwidth-customizer' ); + }; + + app.snapToDefault = function () { + app.sizeCustomizer(); + }; + + app.sizeCustomizer = function ( size ) { + size = size || ''; + // Overlay margin needs to be nudged (give more space) + app.$.overlay.css( { 'margin-left': size } ); + // Move the resizer handle + app.$.resizer.css( { 'margin-left': size ? size - 5 : size } ); + // And of course, resize the customizer + app.$.customizer.width( size ); + }; + + app.initIframeMouseEvents = function () { + // Need to recursively check for existence of iframe + setTimeout( function () { + const $iframe = app.$.overlay.find( 'iframe' ); + + if ( $iframe.length ) { + // Setup iframe bubbling + app.bubbleMouseEvent( $iframe[ 0 ], 'mousemove' ); + app.bubbleMouseEvent( $iframe[ 0 ], 'mouseup' ); + } else { + app.initIframeMouseEvents(); + } + }, 500 ); + }; + + app.bubbleMouseEvent = function ( iframe, evtName ) { + const longName = 'on' + evtName; + // Save any previous handler + const existingMouseEvt = iframe.contentWindow[ longName ]; + + // Attach a new listener + iframe.contentWindow[ longName ] = function ( evt ) { + // Fire existing listener + if ( existingMouseEvt ) { + existingMouseEvt( evt ); + } + + // Create a new event for the this window + const newEvt = document.createEvent( 'MouseEvents' ); + + // We'll need this to offset the mouse appropriately + const boundingClientRect = iframe.getBoundingClientRect(); + + // Initialize the event, copying exiting event values + // for the most part + newEvt.initMouseEvent( + evtName, + true, // bubbles + false, // not cancelable + window, + evt.detail, + evt.screenX, + evt.screenY, + evt.clientX + boundingClientRect.left, + evt.clientY + boundingClientRect.top, + evt.ctrlKey, + evt.altKey, + evt.shiftKey, + evt.metaKey, + evt.button, + null // no related element + ); + + // Dispatch the event on the iframe element + iframe.dispatchEvent( newEvt ); + }; + }; + + wp.customize.bind( 'ready', app.init ); +} )( window, document, jQuery, window.wp ); diff --git a/assets/js/src/customizer.scss b/assets/js/src/customizer.scss new file mode 100644 index 0000000..2f7e38d --- /dev/null +++ b/assets/js/src/customizer.scss @@ -0,0 +1,140 @@ +.customize-control-code_editor .CodeMirror, +.customize-control-code_editor textarea { + height: 100%; +} + +.customizer-resizer { + display: none; +} + +.wp-full-overlay-sidebar { + max-width: 100%; +} + +.resizable { + .customizer-resizer { + content: ''; + display: block; + height: 100%; + width: 4px; + position: absolute; + right: -4px; + margin-top: -30px; + cursor: pointer; + cursor: col-resize; + z-index: 9999999; + opacity: 0.8; + } + + .wp-full-overlay-sidebar { + border-right-width: 4px; + } + + .wp-full-overlay.collapsed .wp-full-overlay-sidebar { + margin-left: -286px; + } + + &.wp-core-ui .wp-full-overlay .collapse-sidebar { + left: 22px; + } +} + +.no-animation { + + .wp-full-overlay, + .wp-full-overlay-sidebar, + .wp-full-overlay .collapse-sidebar, + .wp-full-overlay-main { + -webkit-transition: none; + transition: none; + } +} + +// Mimic @media screen and ( max-width: 640px ) styles when body has .fullwidth-customizer +.fullwidth-customizer { + #customize-controls { + width: 100%; + } + + .wp-full-overlay.expanded { + margin-left: 0; + } + + .wp-full-overlay-sidebar .wp-full-overlay-sidebar-content { + bottom: 0; + } + + .customize-controls-preview-toggle { + display: block; + position: absolute; + top: 0; + left: 48px; + line-height: 45px; + font-size: 14px; + padding: 0 12px; + margin: 0; + height: 45px; + background: #eee; + border-right: 1px solid #ddd; + color: #444; + cursor: pointer; + -webkit-transition: color 0.1s ease-in-out, background 0.1s ease-in-out; + transition: color 0.1s ease-in-out, background 0.1s ease-in-out; + } + + #customize-footer-actions, + #customize-preview, + .customize-controls-preview-toggle .controls, + .preview-only .wp-full-overlay-sidebar-content, + .preview-only .customize-controls-preview-toggle .preview { + display: none; + } + + .customize-controls-preview-toggle { + + .preview:before, + .controls:before { + font: normal 20px/1 dashicons; + content: "\f177"; + position: relative; + top: 4px; + margin-right: 6px; + } + + .controls:before { + content: "\f540"; + } + } + + .preview-only { + #customize-controls { + height: 45px; + } + + #customize-preview, + .customize-controls-preview-toggle .controls { + display: block; + } + } + + #customize-preview { + top: 45px; + bottom: 0; + height: auto; + } + + &.wp-core-ui.wp-customizer { + .button { + padding: 6px 14px; + line-height: normal; + font-size: 14px; + vertical-align: middle; + height: auto; + margin-bottom: 4px; + } + + #customize-header-actions .button-primary { + margin-top: 6px; + } + } +} \ No newline at end of file diff --git a/assets/js/src/theme-garden.js b/assets/js/src/theme-garden.js index c73ec51..8654fce 100644 --- a/assets/js/src/theme-garden.js +++ b/assets/js/src/theme-garden.js @@ -1,30 +1,127 @@ -import { createRoot } from '@wordpress/element'; +import { createRoot, useEffect, useCallback } from '@wordpress/element'; import { ThemeGardenFilterBar } from './components/theme-garden-filterbar'; import { ThemeGardenList } from './components/theme-garden-list'; import { __ } from '@wordpress/i18n'; -import { withSelect } from '@wordpress/data'; +import { withDispatch, withSelect } from '@wordpress/data'; import { compose } from '@wordpress/compose'; import './components/theme-garden-store'; +import { ThemeGardenOverlay } from './components/theme-garden-overlay'; /** * ThemeGarden Component * * This component provides a user interface for browsing themes from Tumblr's theme garden. * - * Class names reference built-in wp-admin styles, and styles declared in _theme_garden.scss. + * CSS classNames reference built-in wp-admin styles, and styles declared in _theme_garden.scss. * - * @param {Object} props - * @param {string} props.logoUrl + * @param {Object} props + * @param {string} props.logoUrl + * @param {Function} props.beforeFetchThemes + * @param {Function} props.fetchThemes + * @param {Function} props.receiveThemes + * @param {Function} props.searchThemes + * @param {Function} props.beforeFetchTheme + * @param {Function} props.fetchTheme + * @param {Function} props.receiveTheme + * @param {Function} props.closeOverlay + * @param {string} props.selectedCategory + * @param {string} props.search */ -const ThemeGarden = ( { logoUrl } ) => { +const ThemeGarden = ( { + logoUrl, + beforeFetchThemes, + fetchThemes, + receiveThemes, + searchThemes, + beforeFetchTheme, + fetchTheme, + receiveTheme, + closeOverlay, + search, + selectedCategory, +} ) => { + const fetchThemesByCategory = useCallback( + async category => { + beforeFetchThemes(); + const response = await fetchThemes( category ); + receiveThemes( response, category, '' ); + }, + [ beforeFetchThemes, receiveThemes, fetchThemes ] + ); + + const fetchThemesByQuery = useCallback( + async newSearch => { + beforeFetchThemes(); + const response = await searchThemes( newSearch ); + receiveThemes( response, '', newSearch ); + }, + [ beforeFetchThemes, receiveThemes, searchThemes ] + ); + /** + * After backwards or forwards navigation, check URL search params for indicators that we have to re-fetch themes. + * + * @return {Promise} + */ + const onBrowserNavigation = useCallback( async () => { + const urlParams = new URLSearchParams( window.location.search ); + const category = urlParams.get( 'category' ) || 'featured'; + const searchParam = urlParams.get( 'search' ) || ''; + const theme = urlParams.get( 'theme' ) || ''; + + if ( searchParam !== '' && searchParam !== search ) { + await fetchThemesByQuery( searchParam ); + } else if ( category !== '' && category !== selectedCategory ) { + await fetchThemesByCategory( category ); + } + + if ( theme !== '' ) { + beforeFetchTheme(); + const response = await fetchTheme( theme ); + receiveTheme( response, theme ); + } else { + closeOverlay(); + } + }, [ + selectedCategory, + search, + beforeFetchTheme, + closeOverlay, + fetchTheme, + fetchThemesByCategory, + fetchThemesByQuery, + receiveTheme, + ] ); + /** + * Detect backwards and forwards browser navigation. + */ + useEffect( () => { + window.addEventListener( 'popstate', onBrowserNavigation ); + return () => { + window.removeEventListener( 'popstate', onBrowserNavigation ); + }; + }, [ onBrowserNavigation ] ); + + const fetchThemeById = useCallback( + async themeId => { + beforeFetchTheme(); + const response = await fetchTheme( themeId ); + receiveTheme( response, themeId ); + }, + [ beforeFetchTheme, receiveTheme, fetchTheme ] + ); + return (

{ __( 'Tumblr Themes', 'tumblr3' ) }

- - + + +
); }; @@ -32,6 +129,34 @@ const ThemeGarden = ( { logoUrl } ) => { export const ConnectedThemeGarden = compose( withSelect( select => ( { logoUrl: select( 'tumblr3/theme-garden-store' ).getLogoUrl(), + selectedCategory: select( 'tumblr3/theme-garden-store' ).getSelectedCategory(), + search: select( 'tumblr3/theme-garden-store' ).getSearch(), + } ) ), + withDispatch( dispatch => ( { + beforeFetchThemes: () => { + return dispatch( 'tumblr3/theme-garden-store' ).beforeFetchThemes(); + }, + fetchThemes: category => { + return dispatch( 'tumblr3/theme-garden-store' ).fetchThemes( category ); + }, + searchThemes: query => { + return dispatch( 'tumblr3/theme-garden-store' ).searchThemes( query ); + }, + receiveThemes: ( themes, category, search ) => { + return dispatch( 'tumblr3/theme-garden-store' ).receiveThemes( themes, category, search ); + }, + beforeFetchTheme: () => { + return dispatch( 'tumblr3/theme-garden-store' ).beforeFetchTheme(); + }, + fetchTheme: id => { + return dispatch( 'tumblr3/theme-garden-store' ).fetchTheme( id ); + }, + receiveTheme: ( theme, themeId ) => { + return dispatch( 'tumblr3/theme-garden-store' ).receiveTheme( theme, themeId ); + }, + closeOverlay: () => { + return dispatch( 'tumblr3/theme-garden-store' ).closeOverlay(); + }, } ) ) )( ThemeGarden ); diff --git a/includes/tag-functions.php b/includes/tag-functions.php index 0b27681..7c64143 100644 --- a/includes/tag-functions.php +++ b/includes/tag-functions.php @@ -1883,27 +1883,35 @@ public function __construct( $id ) { $block ); - // Get the iFrame src from the rendered block. - $src = ''; $processor = new CupcakeLabs\T3\Processor( $block_output ); + // The standard block output won't work, we need to extract details from the block. while ( $processor->next_tag( array( 'tag_name' => 'div', 'class_name' => 'sharedaddy', ) ) ) { - $src = $processor->get_attribute( 'data-src' ); + $class = $processor->get_attribute( 'class' ); + $id = $processor->get_attribute( 'id' ); + $data_src = $processor->get_attribute( 'data-src' ); + $data_name = $processor->get_attribute( 'data-name' ); + $data_title = $processor->get_attribute( 'data-title' ); } - // If no iFrame src is found, return an empty string. - if ( '' === $src ) { + // The processor never found the block, return an empty string. + if ( ! isset( $class ) ) { return ''; } + // Here we reconstruct the like button with the extracted details. return sprintf( - '', - esc_url( $src ) + '', + $class, + $id, + $data_src, + $data_name, + $data_title ); } add_shortcode( 'tag_likebutton', 'tumblr3_tag_likebutton' ); diff --git a/includes/tumblr-theme-language/blocks.php b/includes/tumblr-theme-language/blocks.php index 984f23a..b4b2886 100644 --- a/includes/tumblr-theme-language/blocks.php +++ b/includes/tumblr-theme-language/blocks.php @@ -200,4 +200,5 @@ 'block:SubmitEnabled', 'block:Regular', // https://github.tumblr.net/Tumblr/tumblr/blob/5e69aae5fd71f2a151078abf11a4d146d3aa6bd7/app/controllers/tumblelog.php#L2988 'block:Conversation', + 'block:TaggedPage', ); diff --git a/includes/tumblr-theme-language/missing-blocks.php b/includes/tumblr-theme-language/missing-blocks.php index 10e3d71..32356b0 100644 --- a/includes/tumblr-theme-language/missing-blocks.php +++ b/includes/tumblr-theme-language/missing-blocks.php @@ -145,4 +145,5 @@ 'block_blogs', 'block_nofollowing', 'block_answer', + 'block_taggedpage', ); diff --git a/package-lock.json b/package-lock.json index 5e16499..ddc0b19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "GPL-2.0-or-later", "dependencies": { "@gsap/react": "^2.1.1", + "classnames": "^2.5.1", "gsap": "^3.12.5", "use-debounce": "^10.0.4" }, @@ -5743,6 +5744,12 @@ "dev": true, "license": "MIT" }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, "node_modules/clean-webpack-plugin": { "version": "3.0.0", "dev": true, diff --git a/package.json b/package.json index 7e27756..746f14e 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ }, "dependencies": { "@gsap/react": "^2.1.1", + "classnames": "^2.5.1", "gsap": "^3.12.5", "use-debounce": "^10.0.4" } diff --git a/src/BlockExtensions.php b/src/BlockExtensions.php new file mode 100644 index 0000000..8398857 --- /dev/null +++ b/src/BlockExtensions.php @@ -0,0 +1,80 @@ +is_tumblr3_active = $is_tumblr3_active; + + // Only run if the Tumblr3 theme is active. + if ( $this->is_tumblr3_active ) { + add_filter( 'render_block', array( $this, 'tumblr_audio_block_output' ), 10, 2 ); + } + } + + /** + * Modifies the front-end rendering of the audio block to render Tumblr audio block markup. + * + * @param string $block_content The block content. + * @param array $block The full block, including name and attributes. + * @return string Modified block content. + */ + public function tumblr_audio_block_output( $block_content, $block ) { + if ( get_post_format() !== false && $block['blockName'] !== 'core/audio' ) { + return $block_content; + } + + $attrs = $block['attrs']; + + // Only modify if we have the Tumblr custom attributes + if ( $this->is_tumblr3_active && empty( $attrs['mediaURL'] ) && empty( $attrs['mediaTitle'] ) ) { + return $block_content; + } + + $media_url = $attrs['mediaURL'] ?? ''; + $media_title = $attrs['mediaTitle'] ?? ''; + $media_artist = $attrs['mediaArtist'] ?? ''; + $media_album = $attrs['mediaAlbum'] ?? ''; + $poster_url = $attrs['poster']['url'] ?? ''; + + $output = sprintf( + '
+
+ + %s + %s + %s + + %s +
+ +
', + esc_html( $media_title ), + esc_html( $media_artist ), + esc_html( $media_album ), + $poster_url ? sprintf( 'image', esc_url( $poster_url ) ) : '', + esc_url( $media_url ) + ); + + return $output; + } +} diff --git a/src/Customizer.php b/src/Customizer.php index 0e2f315..f3e3b64 100644 --- a/src/Customizer.php +++ b/src/Customizer.php @@ -29,6 +29,7 @@ public function initialize( $is_tumblr3_active ): void { // Only run the rest of the actions if the Tumblr3 theme is active. if ( $is_tumblr3_active ) { + add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_customizer_scripts' ) ); add_action( 'customize_register', array( $this, 'global_options' ) ); add_action( 'customize_register', array( $this, 'theme_specific_options' ) ); add_filter( 'customize_panel_active', array( $this, 'customize_panel_active' ), 10, 2 ); @@ -36,6 +37,25 @@ public function initialize( $is_tumblr3_active ): void { } } + public function enqueue_customizer_scripts(): void { + $deps = tumblr3_get_asset_meta( TUMBLR3_PATH . 'assets/js/build/customizer.asset.php' ); + + wp_enqueue_script( + 'tumblr3-customizer', + TUMBLR3_URL . 'assets/js/build/customizer.js', + $deps['dependencies'], + $deps['version'], + true + ); + + wp_enqueue_style( + 'tumblr3-customizer', + TUMBLR3_URL . 'assets/js/build/customizer.css', + array(), + $deps['version'] + ); + } + /** * Add Tumblr theme HTML options. * @@ -48,8 +68,14 @@ public function tumblr_html_options( $wp_customize ): void { $wp_customize->add_section( 'tumblr3_html', array( - 'title' => __( 'Tumblr Theme HTML', 'tumblr3' ), - 'priority' => 30, + 'title' => __( 'Tumblr Theme HTML', 'tumblr3' ), + 'priority' => 30, + 'description' => sprintf( + '%s
%s', + __( 'Want to create a custom look for your blog? Read:', 'tumblr3' ), + __( 'Tumblr Theme Documentation', 'tumblr3' ) + ), + 'description_hidden' => true, ) ); @@ -68,15 +94,29 @@ public function tumblr_html_options( $wp_customize ): void { ) ); - $wp_customize->add_control( + /** + * @see https://github.com/WordPress/WordPress/blob/master/wp-includes/customize/class-wp-customize-code-editor-control.php + */ + $editor = new \WP_Customize_Code_Editor_Control( + $wp_customize, 'tumblr3_theme_html', array( - 'label' => __( 'HTML', 'tumblr3' ), + 'label' => '', 'section' => 'tumblr3_html', - 'type' => 'textarea', 'priority' => 10, ) ); + + $editor->code_type = 'text/html'; + $editor->editor_settings = array( + 'codemirror' => array( + 'indentUnit' => 2, + 'tabSize' => 2, + 'lint' => false, + ), + ); + + $wp_customize->add_control( $editor ); } /** @@ -317,7 +357,7 @@ public function theme_specific_options( $wp_customize ): void { $wp_customize->add_section( 'tumblr3_select', array( - 'title' => __( 'Theme Select Options', 'tumblr3' ), + 'title' => __( 'Tumblr Theme Select Options', 'tumblr3' ), 'priority' => 30, ) ); @@ -326,7 +366,7 @@ public function theme_specific_options( $wp_customize ): void { $wp_customize->add_section( 'tumblr3_text', array( - 'title' => __( 'Theme Text Options', 'tumblr3' ), + 'title' => __( 'Tumblr Theme Text Options', 'tumblr3' ), 'priority' => 30, ) ); @@ -335,7 +375,7 @@ public function theme_specific_options( $wp_customize ): void { $wp_customize->add_section( 'tumblr3_font', array( - 'title' => __( 'Theme Font Options', 'tumblr3' ), + 'title' => __( 'Tumblr Theme Font Options', 'tumblr3' ), 'priority' => 30, ) ); @@ -344,7 +384,7 @@ public function theme_specific_options( $wp_customize ): void { $wp_customize->add_section( 'tumblr3_boolean', array( - 'title' => __( 'Theme Boolean Options', 'tumblr3' ), + 'title' => __( 'Tumblr Theme Checkbox Options', 'tumblr3' ), 'priority' => 30, ) ); @@ -353,7 +393,7 @@ public function theme_specific_options( $wp_customize ): void { $wp_customize->add_section( 'tumblr3_image', array( - 'title' => __( 'Theme Image Options', 'tumblr3' ), + 'title' => __( 'Tumblr Theme Image Options', 'tumblr3' ), 'priority' => 30, ) ); diff --git a/src/Plugin.php b/src/Plugin.php index 22866f2..fa67789 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -67,6 +67,16 @@ class Plugin { */ public ?Parser $parser = null; + /** + * The block extensions component. + * + * @since 1.0.0 + * @version 1.0.0 + * + * @var BlockExtensions|null + */ + public ?BlockExtensions $block_extensions = null; + /** * Plugin constructor. * @@ -141,6 +151,9 @@ public function initialize(): void { $this->theme_garden = new ThemeGarden(); $this->theme_garden->initialize(); + $this->block_extensions = new BlockExtensions(); + $this->block_extensions->initialize( $this->tumblr3_active ); + // In the frontend, setup the parser. if ( ! is_admin() ) { $this->parser = new Parser(); diff --git a/src/ThemeGarden.php b/src/ThemeGarden.php index 6c588a7..48f097e 100644 --- a/src/ThemeGarden.php +++ b/src/ThemeGarden.php @@ -16,18 +16,27 @@ */ class ThemeGarden { const THEME_GARDEN_ENDPOINT = 'https://www.tumblr.com/api/v2/theme_garden'; + const ADMIN_MENU_SLUG = 'tumblr-themes'; /** - * This holds the currently selected category of themes. + * The `category` param in the current URL. If present, we'll search Tumblr's API for the given category. + * Defaults to featured if no param is present. * - * @var string + * @var string $selected_category */ public string $selected_category = 'featured'; /** - * This holds the current search query. + * The `theme` param in the current URL. If present, we'll render a theme details overlay. * - * @var string + * @var string $selected_theme_id + */ + public string $selected_theme_id = ''; + + /** + * The `search` param in the current URL. If present, we'll search Tumblr's API for the given query. + * + * @var string $search */ public string $search = ''; @@ -57,6 +66,9 @@ public function initialize(): void { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is verified in maybe_activate_theme. $this->search = ( isset( $_GET['search'] ) ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : ''; + + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Nonce is verified in maybe_activate_theme. + $this->selected_theme_id = ( isset( $_GET['theme'] ) ) ? sanitize_text_field( wp_unslash( $_GET['theme'] ) ) : ''; } /** @@ -67,10 +79,11 @@ public function initialize(): void { * @return void */ public function enqueue_assets( string $hook ): void { - if ( 'appearance_page_tumblr-themes' === $hook ) { + if ( 'appearance_page_' . self::ADMIN_MENU_SLUG === $hook ) { $deps = tumblr3_get_asset_meta( TUMBLR3_PATH . 'assets/js/build/theme-garden.asset.php' ); $this->enqueue_admin_styles( $deps['version'] ); $themes_and_categories = $this->get_themes_and_categories(); + $theme_details = $this->selected_theme_id ? $this->get_theme($this->selected_theme_id) : null; wp_enqueue_script( 'tumblr-theme-garden', TUMBLR3_URL . 'assets/js/build/theme-garden.js', @@ -88,6 +101,8 @@ public function enqueue_assets( string $hook ): void { 'selectedCategory' => $this->selected_category, 'search' => $this->search, 'baseUrl' => admin_url( 'admin.php?page=tumblr-themes' ), + 'selectedThemeId' => $this->selected_theme_id, + 'themeDetails' => $theme_details, ) ), 'before' @@ -108,7 +123,7 @@ public function enqueue_assets( string $hook ): void { 'tumblr-theme-install', 'const T3_Install = ' . wp_json_encode( array( - 'browseUrl' => admin_url( 'admin.php?page=tumblr-themes' ), + 'browseUrl' => admin_url( 'admin.php?page=' . self::ADMIN_MENU_SLUG ), 'buttonText' => __( 'Browse Tumblr themes', 'tumblr3' ), ) ), @@ -142,6 +157,30 @@ public function enqueue_admin_styles( $version ): void { ); } + /** + * Fetches and theme object from Tumblr's API. + * + * @param string $theme_id The theme id to send to Tumblr's API. + * + * @return \WP_Error | object + */ + public function get_theme( string $theme_id ) { + $response = wp_remote_get( self::THEME_GARDEN_ENDPOINT . '/theme/' . esc_attr( $theme_id ) . '?time=' . time() ); + $status = wp_remote_retrieve_response_code( $response ); + + if ( 200 !== $status ) { + return new \WP_Error(); + } + + $body = json_decode( wp_remote_retrieve_body( $response ) ); + + if ( ! isset( $body->response->theme ) ) { + return new \WP_Error(); + } + + return $body->response; + } + /** * Register REST routes. * @@ -153,7 +192,19 @@ public function register_rest_routes(): void { '/themes', array( 'methods' => 'GET', - 'callback' => array( $this, 'get_themes' ), + 'callback' => array( $this, 'rest_api_get_themes' ), + 'permission_callback' => function () { + return current_user_can( 'manage_options' ); + }, + ) + ); + + register_rest_route( + 'tumblr3/v1', + '/theme', + array( + 'methods' => 'GET', + 'callback' => array( $this, 'rest_api_get_theme' ), 'permission_callback' => function () { return current_user_can( 'manage_options' ); }, @@ -166,11 +217,21 @@ public function register_rest_routes(): void { * * @return \WP_REST_Response The settings for the queue. */ - public function get_themes(): \WP_REST_Response { + public function rest_api_get_themes(): \WP_REST_Response { $themes_and_categories = $this->get_themes_and_categories(); return new \WP_REST_Response( $themes_and_categories['themes'], 200 ); } + /** + * Gets theme details for an ajax request. + * + * @return \WP_REST_Response The settings for the queue. + */ + public function rest_api_get_theme(): \WP_REST_Response { + $theme = $this->get_theme( $this->selected_theme_id ); + return new \WP_REST_Response( $theme, 200 ); + } + /** * Checks URL query for a tumblr theme id to activate. * @@ -181,45 +242,29 @@ public function maybe_activate_theme(): void { return; } - $theme_id = isset( $_GET['activate_tumblr_theme'] ) ? absint( wp_unslash( $_GET['activate_tumblr_theme'] ) ) : 0; - - // Returns early if theme id was not set. - if ( 0 === $theme_id ) { - return; - } - - // During development, we don't want to be so limited by cache. So we'll send a cache invalidator to every request. - // TODO: remove once we are confident that api response will be stable. - $response = wp_remote_get( self::THEME_GARDEN_ENDPOINT . '/theme/' . esc_attr( $theme_id ) . '?time=' . time() ); - $status = wp_remote_retrieve_response_code( $response ); + $theme_id_to_activate = sanitize_text_field( wp_unslash( $_GET['activate_tumblr_theme'] ) ); + $theme = $this->get_theme( $theme_id_to_activate ); - if ( 200 !== $status ) { + if ( is_wp_error( $theme ) ) { return; } - - $body = json_decode( wp_remote_retrieve_body( $response ) ); - - if ( ! isset( $body->response->theme ) ) { - return; - } - // Save theme details to options. - update_option( 'tumblr3_theme_html', $body->response->theme ); + update_option( 'tumblr3_theme_html', $theme->theme ); // Save all external theme details to an option. $external_theme_details = array( - 'id' => $theme_id, - 'title' => isset( $body->response->title ) ? $body->response->title : '', - 'thumbnail' => isset( $body->response->thumbnail ) ? $body->response->thumbnail : '', - 'author_name' => isset( $body->response->author->name ) ? $body->response->author->name : '', - 'author_url' => isset( $body->response->author->url ) ? $body->response->author->url : '', + 'id' => $theme_id_to_activate, + 'title' => isset( $theme->title ) ? $theme->title : '', + 'thumbnail' => isset( $theme->thumbnail ) ? $theme->thumbnail : '', + 'author_name' => isset( $theme->author->name) ? $theme->author->name : '', + 'author_url' => isset( $theme->author->url ) ? $theme->author->url : '', ); update_option( 'tumblr3_external_theme', $external_theme_details ); update_option( 'tumblr3_use_theme', '1' ); // Setup theme option defaults. - $this->option_defaults_helper( maybe_unserialize( $body->response->default_params ) ); + $this->option_defaults_helper( maybe_unserialize( $theme->default_params ) ); // Finally, redirect to the customizer with the new theme active. wp_safe_redirect( wp_customize_url() );