Full Site Editing - Version 0.10

Version Description

  • Update page template selector with template preview.
Download this release

Release Info

Developer obenland
Plugin Icon wp plugin Full Site Editing
Version 0.10
Comparing to
See all releases

Code changes from version 0.9 to 0.10

Files changed (22) hide show
  1. full-site-editing-plugin.php +2 -2
  2. full-site-editing/dist/full-site-editing.js +1 -1
  3. readme.txt +4 -3
  4. starter-page-templates/class-starter-page-templates.php +51 -4
  5. starter-page-templates/dist/starter-page-templates.css +1 -1
  6. starter-page-templates/dist/starter-page-templates.deps.json +1 -1
  7. starter-page-templates/dist/starter-page-templates.js +2 -2
  8. starter-page-templates/dist/starter-page-templates.rtl.css +1 -1
  9. starter-page-templates/page-template-modal/components/block-preview.js +27 -0
  10. starter-page-templates/page-template-modal/components/block-template-preview.js +4 -2
  11. starter-page-templates/page-template-modal/components/preview-template-title.js +2 -2
  12. starter-page-templates/page-template-modal/components/template-selector-control.js +51 -32
  13. starter-page-templates/page-template-modal/components/template-selector-item.js +41 -12
  14. starter-page-templates/page-template-modal/components/template-selector-preview.js +35 -9
  15. starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-control-test.js.snap +124 -0
  16. starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-preview-test.js.snap +44 -0
  17. starter-page-templates/page-template-modal/components/test/helpers/templates-blocks-helpers.js +58 -0
  18. starter-page-templates/page-template-modal/components/test/template-selector-control-test.js +200 -0
  19. starter-page-templates/page-template-modal/components/test/template-selector-preview-test.js +65 -0
  20. starter-page-templates/page-template-modal/index.js +185 -56
  21. starter-page-templates/page-template-modal/styles/starter-page-templates-editor.scss +343 -23
  22. starter-page-templates/page-template-modal/utils/replace-placeholders.js +4 -0
full-site-editing-plugin.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Plugin Name: Full Site Editing
4
  * Description: Enhances your page creation workflow within the Block Editor.
5
- * Version: 0.9
6
  * Author: Automattic
7
  * Author URI: https://automattic.com/wordpress-plugins/
8
  * License: GPLv2 or later
@@ -20,7 +20,7 @@ namespace A8C\FSE;
20
  *
21
  * @var string
22
  */
23
- define( 'PLUGIN_VERSION', '0.9' );
24
 
25
  // Themes which are supported by Full Site Editing (not the same as the SPT themes).
26
  const SUPPORTED_THEMES = [ 'maywood' ];
2
  /**
3
  * Plugin Name: Full Site Editing
4
  * Description: Enhances your page creation workflow within the Block Editor.
5
+ * Version: 0.10
6
  * Author: Automattic
7
  * Author URI: https://automattic.com/wordpress-plugins/
8
  * License: GPLv2 or later
20
  *
21
  * @var string
22
  */
23
+ define( 'PLUGIN_VERSION', '0.10' );
24
 
25
  // Themes which are supported by Full Site Editing (not the same as the SPT themes).
26
  const SUPPORTED_THEMES = [ 'maywood' ];
full-site-editing/dist/full-site-editing.js CHANGED
@@ -9,4 +9,4 @@
9
  Licensed under the MIT License (MIT), see
10
  http://jedwatson.github.io/classnames
11
  */
12
- !function(){"use strict";var n={}.hasOwnProperty;function o(){for(var t=[],e=0;e<arguments.length;e++){var r=arguments[e];if(r){var i=typeof r;if("string"===i||"number"===i)t.push(r);else if(Array.isArray(r)&&r.length){var c=o.apply(null,r);c&&t.push(c)}else if("object"===i)for(var a in r)n.call(r,a)&&r[a]&&t.push(a)}}return t.join(" ")}t.exports?(o.default=o,t.exports=o):void 0===(r=function(){return o}.apply(e,[]))||(t.exports=r)}()},function(t,e){!function(){t.exports=this.wp.hooks}()},function(t,e){t.exports=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}},function(t,e){!function(){t.exports=this.wp.components}()},function(t,e){function n(){return t.exports=n=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},n.apply(this,arguments)}t.exports=n},function(t,e){!function(){t.exports=this.wp.domReady}()},function(t,e){!function(){t.exports=this.wp.keycodes}()},function(t,e,n){var r=n(33),o=n(34),i=n(35);t.exports=function(t,e){return r(t)||o(t,e)||i()}},function(t,e){!function(){t.exports=this.wp.apiFetch}()},function(t,e){!function(){t.exports=this.wp.htmlEntities}()},function(t,e,n){},function(t,e){!function(){t.exports=this.wp.serverSideRender}()},function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},function(t,e){function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}t.exports=function(t,e,r){return e&&n(t.prototype,e),r&&n(t,r),t}},function(t,e,n){var r=n(29),o=n(30);t.exports=function(t,e){return!e||"object"!==r(e)&&"function"!=typeof e?o(t):e}},function(t,e){function n(e){return t.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},n(e)}t.exports=n},function(t,e,n){var r=n(31);t.exports=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&r(t,e)}},function(t,e){!function(){t.exports=this.wp.url}()},function(t,e,n){var r=n(38),o=n(39),i=n(40);t.exports=function(t){return r(t)||o(t)||i()}},function(t,e){!function(){t.exports=this.wp.plugins}()},function(t,e,n){},function(t,e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function r(e){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?t.exports=r=function(t){return n(t)}:t.exports=r=function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":n(t)},r(e)}t.exports=r},function(t,e){t.exports=function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}},function(t,e){function n(e,r){return t.exports=n=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},n(e,r)}t.exports=n},function(t,e,n){},function(t,e){t.exports=function(t){if(Array.isArray(t))return t}},function(t,e){t.exports=function(t,e){var n=[],r=!0,o=!1,i=void 0;try{for(var c,a=t[Symbol.iterator]();!(r=(c=a.next()).done)&&(n.push(c.value),!e||n.length!==e);r=!0);}catch(l){o=!0,i=l}finally{try{r||null==a.return||a.return()}finally{if(o)throw i}}return n}},function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(t,e,n){},function(t,e,n){},function(t,e){t.exports=function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}},function(t,e){t.exports=function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}},function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(t,e,n){},function(t,e,n){"use strict";n.r(e);var r=n(0),o=n(4),i=n(1),c=n(19),a=n.n(c),l=function(){return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(a.a,{block:"a8c/navigation-menu"}))},s=(n(28),Object(r.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(r.createElement)("path",{fill:"none",d:"M0 0h24v24H0V0z"}),Object(r.createElement)("path",{d:"M12 7.27l4.28 10.43-3.47-1.53-.81-.36-.81.36-3.47 1.53L12 7.27M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71L12 2z"})));Object(o.registerBlockType)("a8c/navigation-menu",{title:Object(i.__)("Navigation Menu"),description:Object(i.__)("Visual placeholder for site-wide navigation and menus."),icon:s,category:"layout",supports:{align:["wide","full"],html:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"}},edit:l,save:function(){return null}});var u=n(12),p=n.n(u),d=n(3),f=n(9),b=n(10),m=n.n(b),O=n(20),g=n.n(O),v=n(21),y=n.n(v),h=n(22),j=n.n(h),E=n(23),_=n.n(E),w=n(24),S=n.n(w),k=n(8),P=n.n(k),x=n(2),T=n(5),I=function(t){function e(){return g()(this,e),j()(this,_()(e).apply(this,arguments))}return S()(e,t),y()(e,[{key:"toggleEditing",value:function(){var t=this.props,e=t.isEditing;(0,t.setState)({isEditing:!e})}},{key:"onSelectPost",value:function(t){var e=t.id,n=t.type;this.props.setState({isEditing:!1,selectedPostId:e,selectedPostType:n})}},{key:"render",value:function(){var t=this.props.attributes.align;return Object(r.createElement)(r.Fragment,null,Object(r.createElement)("div",{className:P()("post-content-block",m()({},"align".concat(t),t))},Object(r.createElement)(T.PostTitle,null),Object(r.createElement)(T.InnerBlocks,{templateLock:!1})))}}]),e}(r.Component),B=Object(d.compose)([Object(d.withState)({isEditing:!1,selectedPostId:void 0,selectedPostType:void 0}),Object(x.withSelect)(function(t,e){var n=e.selectedPostId,r=e.selectedPostType;return{selectedPost:(0,t("core").getEntityRecord)("postType",r,n)}})])(I);n(32);Object(o.registerBlockType)("a8c/post-content",{title:Object(i.__)("Content"),description:Object(i.__)("The page content."),icon:"layout",category:"layout",supports:{align:["full"],anchor:!1,customClassName:!1,html:!1,inserter:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"full"}},edit:B,save:function(){return Object(r.createElement)(T.InnerBlocks.Content,null)}});var C=Object(d.createHigherOrderComponent)(function(t){return function(e){return"a8c/post-content"!==e.name?Object(r.createElement)(t,e):Object(r.createElement)(t,p()({},e,{className:"post-content__block"}))}},"addContentSlotClassname");Object(f.addFilter)("editor.BlockListBlock","full-site-editing/blocks/post-content",C,9);var D=n(14),N=n(6),L=n.n(N),A=n(15),F=n.n(A),M=n(16),R=n.n(M),U=n(17);function H(t){var e=Object(r.useRef)();return Object(r.useEffect)(function(){e.current=t},[t]),e.current}function q(t,e,n,o,c,a){var l=Object(r.useState)({option:e,previousOption:"",loaded:!1,error:!1}),s=F()(l,2),u=s[0],p=s[1],d=H(o),f=H(c);function b(){p(L()({},u,{option:u.previousOption,isSaving:!1}))}return Object(r.useEffect)(function(){u.loaded||u.error?function(){var e=u.option,r=u.previousOption,a=e&&e.trim()===r.trim(),l=!e||0===e.trim().length;!o&&d&&l&&b();if(!c||a)return;!f&&c&&function(e){p(L()({},u,{isSaving:!0})),R()({path:"/wp/v2/settings",method:"POST",data:m()({},t,e)}).then(function(){return function(t){p(L()({},u,{previousOption:t,isDirty:!1,isSaving:!1}))}(e)}).catch(function(){n(Object(i.sprintf)(Object(i.__)("Unable to save site %s"),t)),b()})}(e)}():R()({path:"/wp/v2/settings"}).then(function(e){return p(L()({},u,{option:Object(U.decodeEntities)(e[t]),previousOption:Object(U.decodeEntities)(e[t]),loaded:!0,error:!1}))}).catch(function(){n(Object(i.sprintf)(Object(i.__)("Unable to load site %s"),t)),p(L()({},u,{option:Object(i.sprintf)(Object(i.__)("Error loading site %s"),t),error:!0}))})}),{siteOptions:u,handleChange:function(t){a({updated:Date.now()}),p(L()({},u,{option:t}))}}}var z=Object(d.compose)([Object(x.withSelect)(function(t,e){var n=e.clientId,r=t("core/editor"),o=r.isSavingPost,i=r.isPublishingPost,c=r.isAutosavingPost,a=r.isCurrentPostPublished,l=t("core/block-editor"),s=l.getBlockIndex,u=l.getBlockRootClientId,p=l.getTemplateLock,d=u(n);return{blockIndex:s(n,d),isLocked:!!p(d),rootClientId:d,shouldUpdateSiteOption:(o()&&a()||i())&&!c()}}),Object(x.withDispatch)(function(t,e){var n=e.blockIndex,r=e.rootClientId;return{createErrorNotice:t("core/notices").createErrorNotice,insertDefaultBlock:function(){return t("core/block-editor").insertDefaultBlock({},r,n+1)}}})])(function(t){var e=t.className,n=t.createErrorNotice,o=t.shouldUpdateSiteOption,c=t.isSelected,a=t.setAttributes,l=t.isLocked,s=t.insertDefaultBlock,u=q("description",Object(i.__)("Site description loading…"),n,c,o,a),p=u.siteOptions,d=u.handleChange,f=p.option;return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(T.PlainText,{className:P()("site-description",e),value:f,onChange:function(t){return d(t)},onKeyDown:function(t){t.keyCode===D.ENTER&&(t.preventDefault(),l||s())},placeholder:Object(i.__)("Add a Site Description"),"aria-label":Object(i.__)("Site Description")}))});n(36);Object(o.registerBlockType)("a8c/site-description",{title:Object(i.__)("Site Description"),description:Object(i.__)("Site description, also known as the tagline."),icon:Object(r.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24"},Object(r.createElement)("path",{fill:"none",d:"M0 0h24v24H0z"}),Object(r.createElement)("path",{d:"M4 9h16v2H4V9zm0 4h10v2H4v-2z"})),category:"layout",supports:{align:["wide","full"],html:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"}},edit:z,save:function(){return null}});var V=Object(d.compose)([Object(x.withSelect)(function(t,e){var n=e.clientId,r=t("core/editor"),o=r.isSavingPost,i=r.isPublishingPost,c=r.isAutosavingPost,a=r.isCurrentPostPublished,l=t("core/block-editor"),s=l.getBlockIndex,u=l.getBlockRootClientId,p=l.getTemplateLock,d=u(n);return{blockIndex:s(n,d),isLocked:!!p(d),rootClientId:d,shouldUpdateSiteOption:(o()&&a()||i())&&!c()}}),Object(x.withDispatch)(function(t,e){var n=e.blockIndex,r=e.rootClientId;return{createErrorNotice:t("core/notices").createErrorNotice,insertDefaultBlock:function(){return t("core/block-editor").insertDefaultBlock({},r,n+1)}}})])(function(t){var e=t.className,n=t.createErrorNotice,o=t.shouldUpdateSiteOption,c=t.isSelected,a=t.setAttributes,l=t.isLocked,s=t.insertDefaultBlock,u=q("title",Object(i.__)("Site title loading…"),n,c,o,a),p=u.siteOptions,d=u.handleChange,f=p.option;return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(T.PlainText,{className:P()("site-title",e),value:f,onChange:function(t){return d(t)},onKeyDown:function(t){t.keyCode===D.ENTER&&(t.preventDefault(),l||s())},placeholder:Object(i.__)("Add a Site Title"),"aria-label":Object(i.__)("Site Title")}))});n(37);Object(o.registerBlockType)("a8c/site-title",{title:Object(i.__)("Site Title"),description:Object(i.__)("Your site title."),icon:"layout",category:"layout",supports:{align:["wide","full"],html:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"}},edit:V,save:function(){return null}});var G=n(7),W=n(11),K=n(25),Q=(n(18),Object(d.compose)(Object(d.withState)({templateClientId:null}),Object(x.withSelect)(function(t,e){var n=e.attributes,r=e.templateClientId,o=t("core").getEntityRecord,i=t("core/editor"),c=i.getCurrentPostId,a=i.isEditedPostDirty,l=t("core/block-editor"),s=l.getBlock,u=l.getSelectedBlock,p=t("core/edit-post").isEditorSidebarOpened,d=n.templateId,f=c(),b=d&&o("postType","wp_template_part",d),m=Object(K.addQueryArgs)(fullSiteEditing.editTemplateBaseUrl,{post:d,fse_parent_post:f}),O=u();return{currentPostId:f,editTemplateUrl:m,template:b,templateBlock:s(r),templateTitle:Object(G.get)(b,["title","rendered"],""),isDirty:a(),isEditorSidebarOpened:!!p(),isAnyTemplateBlockSelected:O&&"a8c/template"===O.name}}),Object(x.withDispatch)(function(t,e){var n=t("core/block-editor").receiveBlocks,r=t("core/edit-post").openGeneralSidebar,i=e.template,c=e.templateClientId,a=e.setState;return{savePost:t("core/editor").savePost,receiveTemplateBlocks:function(){if(i&&!c){var t=Object(o.parse)(Object(G.get)(i,["content","raw"],"")),e=Object(o.createBlock)("core/group",{},t);n([e]),a({templateClientId:e.clientId})}},openGeneralSidebar:r}}))(function(t){var e,n=t.attributes,o=t.editTemplateUrl,c=t.receiveTemplateBlocks,a=t.template,l=t.templateBlock,s=t.templateTitle,u=t.isDirty,p=t.savePost,d=t.isEditorSidebarOpened,f=t.openGeneralSidebar,b=t.isAnyTemplateBlockSelected;if(!a)return Object(r.createElement)(W.Placeholder,null,Object(r.createElement)(W.Spinner,null));var O=Object(r.createRef)(),g=Object(r.useState)(!1),v=F()(g,2),y=v[0],h=v[1];Object(r.useEffect)(function(){y&&!u&&O.current.click(),c()}),Object(r.useEffect)(function(){var t=document.querySelector(".edit-post-sidebar__panel-tabs ul li:last-child");if(d&&t){if(b)return f("edit-post/document"),void t.classList.add("hidden");t.classList.remove("hidden")}},[b,d,f]);var j=n.align,E=n.className;return Object(r.createElement)("div",{className:P()("template-block",(e={},m()(e,"align".concat(j),j),m()(e,"is-navigating-to-template",y),e))},l&&Object(r.createElement)(r.Fragment,null,Object(r.createElement)(W.Disabled,null,Object(r.createElement)("div",{className:E},Object(r.createElement)(T.BlockEdit,{attributes:l.attributes,block:l,clientId:l.clientId,isSelected:!1,name:l.name,setAttributes:G.noop}))),Object(r.createElement)(W.Placeholder,{className:"template-block__overlay"},y&&Object(r.createElement)("div",{className:"template-block__loading"},Object(r.createElement)(W.Spinner,null)," ",Object(i.sprintf)(Object(i.__)("Loading %s Editor"),s)),Object(r.createElement)(W.Button,{className:y?"hidden":null,href:o,onClick:function(t){h(!0),u&&(t.preventDefault(),p())},isDefault:!0,isLarge:!0,ref:O},Object(i.sprintf)(Object(i.__)("Edit %s"),s)))))})),Y=Object(d.createHigherOrderComponent)(function(t){return function(e){return"fse-site-logo"!==e.attributes.className?Object(r.createElement)(t,e):Object(r.createElement)(t,p()({},e,{className:"template__site-logo"}))}},"addFSESiteLogoClassname");Object(f.addFilter)("editor.BlockListBlock","full-site-editing/blocks/template",Y),"wp_template_part"!==fullSiteEditing.editorPostType&&Object(o.registerBlockType)("a8c/template",{title:Object(i.__)("Template Part"),description:Object(i.__)("Display a Template Part."),icon:"layout",category:"layout",attributes:{templateId:{type:"number"},className:{type:"string"}},supports:{anchor:!1,customClassName:!1,html:!1,inserter:!1,reusable:!1},edit:Q,save:function(){return null},getEditWrapperProps:function(){return{"data-align":"full"}}});var J=Object(d.createHigherOrderComponent)(function(t){return function(e){return"a8c/template"!==e.name?Object(r.createElement)(t,e):Object(r.createElement)(t,p()({},e,{className:"template__block-container"}))}},"addFSETemplateClassname");Object(f.addFilter)("editor.BlockListBlock","full-site-editing/blocks/template",J,9);var X=n(13),Z=n.n(X);Z()(function(){var t=fullSiteEditing,e=t.closeButtonLabel,n=t.closeButtonUrl,r=t.editorPostType,o=setInterval(function(){var t=document.querySelector(".edit-post-fullscreen-mode-close__toolbar a");if(t&&(clearInterval(o),"wp_template_part"===r&&n)){var i=document.createElement("a");i.href=n,i.innerHTML=e,i.className="components-button components-icon-button is-button is-default",i.setAttribute("aria-label",e),document.querySelector(".edit-post-fullscreen-mode-close__toolbar").replaceChild(i,t)}})});var $=n(26),tt=n.n($),et=n(27),nt=Object(x.withSelect)(function(t){var e=t("core").getEntityRecord,n=t("core/editor").getEditedPostAttribute;return{templateClasses:Object(G.map)(n("template_part_types"),function(t){var n=Object(G.get)(e("taxonomy","wp_template_part_type",t),"name","");return Object(G.endsWith)(n,"-header")?"site-header site-branding":Object(G.endsWith)(n,"-footer")?"site-footer":void 0})}})(function(t){var e=t.templateClasses,n=setInterval(function(){var t=document.querySelector(".block-editor-writing-flow.editor-writing-flow > div");t&&(clearInterval(n),t.className=P.a.apply(void 0,["a8c-template-editor"].concat(tt()(e))))});return null});"wp_template_part"===fullSiteEditing.editorPostType&&Object(et.registerPlugin)("fse-editor-template-classes",{render:nt}),Z()(function(){"wp_template_part"===fullSiteEditing.editorPostType&&Object(x.dispatch)("core/notices").createNotice("info",Object(i.__)("Updates to this template will affect all pages on your site."),{isDismissible:!1})});var rt=Object(d.compose)(Object(x.withSelect)(function(t){var e=t("core/editor"),n=e.getBlocks,r=e.getEditorSettings,o=t("core/edit-post").getEditorMode,i=n().find(function(t){return"a8c/post-content"===t.name});return{rootClientId:i?i.clientId:"",showInserter:"visual"===o()&&r().richEditingEnabled}}))(function(t){var e=t.rootClientId,n=t.showInserter;return Object(r.createElement)(T.Inserter,{rootClientId:e,disabled:!n,position:"bottom right"})});Z()(function(){return function(){if("page"===fullSiteEditing.editorPostType)var t=setInterval(function(){var e=document.querySelector(".edit-post-header-toolbar");if(e){clearInterval(t);var n=document.createElement("div");n.classList.add("fse-post-content-block-inserter"),e.insertBefore(n,e.firstChild),Object(r.render)(Object(r.createElement)(rt,null),n)}})}()});var ot=Object(x.subscribe)(function(){if("page"!==fullSiteEditing.editorPostType)return ot();!1===Object(x.select)("core/editor").isValidTemplate()&&Object(x.dispatch)("core/editor").setTemplateValidity(!0)}),it=["logo","brand","emblem","hallmark"];Object(f.addFilter)("blocks.registerBlockType","full-site-editing/editor/image-block-keywords",function(t,e){return"core/image"!==e?t:t=Object(G.assign)({},t,{keywords:t.keywords.concat(it)})});n(41);Object(x.use)(function(t){return{dispatch:function(e){var n=L()({},t.dispatch(e)),r=fullSiteEditing.editorPostType;return"core/editor"===e&&n.trashPost&&"wp_template_part"===r&&(n.trashPost=function(){}),n}}}),Object(x.use)(function(t){return{dispatch:function(e){var n=L()({},t.dispatch(e)),r=fullSiteEditing.editorPostType;if("core/editor"===e&&n.editPost&&"wp_template_part"===r){var o=n.editPost;n.editPost=function(t){"draft"!==t.status&&o(t)}}return n}}});var ct=Object(x.subscribe)(function(){var t=Object(x.dispatch)("core/edit-post").removeEditorPanel;return"page"===fullSiteEditing.editorPostType&&t("featured-image"),"wp_template_part"===fullSiteEditing.editorPostType&&t("post-status"),ct()})}]));
9
  Licensed under the MIT License (MIT), see
10
  http://jedwatson.github.io/classnames
11
  */
12
+ !function(){"use strict";var n={}.hasOwnProperty;function o(){for(var t=[],e=0;e<arguments.length;e++){var r=arguments[e];if(r){var i=typeof r;if("string"===i||"number"===i)t.push(r);else if(Array.isArray(r)&&r.length){var c=o.apply(null,r);c&&t.push(c)}else if("object"===i)for(var a in r)n.call(r,a)&&r[a]&&t.push(a)}}return t.join(" ")}t.exports?(o.default=o,t.exports=o):void 0===(r=function(){return o}.apply(e,[]))||(t.exports=r)}()},function(t,e){!function(){t.exports=this.wp.hooks}()},function(t,e){t.exports=function(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}},function(t,e){!function(){t.exports=this.wp.components}()},function(t,e){function n(){return t.exports=n=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},n.apply(this,arguments)}t.exports=n},function(t,e){!function(){t.exports=this.wp.domReady}()},function(t,e){!function(){t.exports=this.wp.keycodes}()},function(t,e,n){var r=n(33),o=n(34),i=n(35);t.exports=function(t,e){return r(t)||o(t,e)||i()}},function(t,e){!function(){t.exports=this.wp.apiFetch}()},function(t,e){!function(){t.exports=this.wp.htmlEntities}()},function(t,e,n){},function(t,e){!function(){t.exports=this.wp.serverSideRender}()},function(t,e){t.exports=function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}},function(t,e){function n(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}t.exports=function(t,e,r){return e&&n(t.prototype,e),r&&n(t,r),t}},function(t,e,n){var r=n(29),o=n(30);t.exports=function(t,e){return!e||"object"!==r(e)&&"function"!=typeof e?o(t):e}},function(t,e){function n(e){return t.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},n(e)}t.exports=n},function(t,e,n){var r=n(31);t.exports=function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&r(t,e)}},function(t,e){!function(){t.exports=this.wp.url}()},function(t,e,n){var r=n(38),o=n(39),i=n(40);t.exports=function(t){return r(t)||o(t)||i()}},function(t,e){!function(){t.exports=this.wp.plugins}()},function(t,e,n){},function(t,e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function r(e){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?t.exports=r=function(t){return n(t)}:t.exports=r=function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":n(t)},r(e)}t.exports=r},function(t,e){t.exports=function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}},function(t,e){function n(e,r){return t.exports=n=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},n(e,r)}t.exports=n},function(t,e,n){},function(t,e){t.exports=function(t){if(Array.isArray(t))return t}},function(t,e){t.exports=function(t,e){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t)){var n=[],r=!0,o=!1,i=void 0;try{for(var c,a=t[Symbol.iterator]();!(r=(c=a.next()).done)&&(n.push(c.value),!e||n.length!==e);r=!0);}catch(l){o=!0,i=l}finally{try{r||null==a.return||a.return()}finally{if(o)throw i}}return n}}},function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(t,e,n){},function(t,e,n){},function(t,e){t.exports=function(t){if(Array.isArray(t)){for(var e=0,n=new Array(t.length);e<t.length;e++)n[e]=t[e];return n}}},function(t,e){t.exports=function(t){if(Symbol.iterator in Object(t)||"[object Arguments]"===Object.prototype.toString.call(t))return Array.from(t)}},function(t,e){t.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(t,e,n){},function(t,e,n){"use strict";n.r(e);var r=n(0),o=n(4),i=n(1),c=n(19),a=n.n(c),l=function(){return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(a.a,{block:"a8c/navigation-menu"}))},s=(n(28),Object(r.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24"},Object(r.createElement)("path",{fill:"none",d:"M0 0h24v24H0V0z"}),Object(r.createElement)("path",{d:"M12 7.27l4.28 10.43-3.47-1.53-.81-.36-.81.36-3.47 1.53L12 7.27M12 2L4.5 20.29l.71.71L12 18l6.79 3 .71-.71L12 2z"})));Object(o.registerBlockType)("a8c/navigation-menu",{title:Object(i.__)("Navigation Menu"),description:Object(i.__)("Visual placeholder for site-wide navigation and menus."),icon:s,category:"layout",supports:{align:["wide","full"],html:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"}},edit:l,save:function(){return null}});var u=n(12),p=n.n(u),d=n(3),f=n(9),b=n(10),m=n.n(b),O=n(20),g=n.n(O),y=n(21),v=n.n(y),h=n(22),j=n.n(h),E=n(23),_=n.n(E),w=n(24),S=n.n(w),k=n(8),P=n.n(k),x=n(2),T=n(5),I=function(t){function e(){return g()(this,e),j()(this,_()(e).apply(this,arguments))}return S()(e,t),v()(e,[{key:"toggleEditing",value:function(){var t=this.props,e=t.isEditing;(0,t.setState)({isEditing:!e})}},{key:"onSelectPost",value:function(t){var e=t.id,n=t.type;this.props.setState({isEditing:!1,selectedPostId:e,selectedPostType:n})}},{key:"render",value:function(){var t=this.props.attributes.align;return Object(r.createElement)(r.Fragment,null,Object(r.createElement)("div",{className:P()("post-content-block",m()({},"align".concat(t),t))},Object(r.createElement)(T.PostTitle,null),Object(r.createElement)(T.InnerBlocks,{templateLock:!1})))}}]),e}(r.Component),B=Object(d.compose)([Object(d.withState)({isEditing:!1,selectedPostId:void 0,selectedPostType:void 0}),Object(x.withSelect)(function(t,e){var n=e.selectedPostId,r=e.selectedPostType;return{selectedPost:(0,t("core").getEntityRecord)("postType",r,n)}})])(I);n(32);Object(o.registerBlockType)("a8c/post-content",{title:Object(i.__)("Content"),description:Object(i.__)("The page content."),icon:"layout",category:"layout",supports:{align:["full"],anchor:!1,customClassName:!1,html:!1,inserter:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"full"}},edit:B,save:function(){return Object(r.createElement)(T.InnerBlocks.Content,null)}});var C=Object(d.createHigherOrderComponent)(function(t){return function(e){return"a8c/post-content"!==e.name?Object(r.createElement)(t,e):Object(r.createElement)(t,p()({},e,{className:"post-content__block"}))}},"addContentSlotClassname");Object(f.addFilter)("editor.BlockListBlock","full-site-editing/blocks/post-content",C,9);var D=n(14),N=n(6),A=n.n(N),L=n(15),F=n.n(L),M=n(16),R=n.n(M),U=n(17);function H(t){var e=Object(r.useRef)();return Object(r.useEffect)(function(){e.current=t},[t]),e.current}function q(t,e,n,o,c,a){var l=Object(r.useState)({option:e,previousOption:"",loaded:!1,error:!1}),s=F()(l,2),u=s[0],p=s[1],d=H(o),f=H(c);function b(){p(A()({},u,{option:u.previousOption,isSaving:!1}))}return Object(r.useEffect)(function(){u.loaded||u.error?function(){var e=u.option,r=u.previousOption,a=e&&e.trim()===r.trim(),l=!e||0===e.trim().length;!o&&d&&l&&b();if(!c||a)return;!f&&c&&function(e){p(A()({},u,{isSaving:!0})),R()({path:"/wp/v2/settings",method:"POST",data:m()({},t,e)}).then(function(){return function(t){p(A()({},u,{previousOption:t,isDirty:!1,isSaving:!1}))}(e)}).catch(function(){n(Object(i.sprintf)(Object(i.__)("Unable to save site %s"),t)),b()})}(e)}():R()({path:"/wp/v2/settings"}).then(function(e){return p(A()({},u,{option:Object(U.decodeEntities)(e[t]),previousOption:Object(U.decodeEntities)(e[t]),loaded:!0,error:!1}))}).catch(function(){n(Object(i.sprintf)(Object(i.__)("Unable to load site %s"),t)),p(A()({},u,{option:Object(i.sprintf)(Object(i.__)("Error loading site %s"),t),error:!0}))})}),{siteOptions:u,handleChange:function(t){a({updated:Date.now()}),p(A()({},u,{option:t}))}}}var z=Object(d.compose)([Object(x.withSelect)(function(t,e){var n=e.clientId,r=t("core/editor"),o=r.isSavingPost,i=r.isPublishingPost,c=r.isAutosavingPost,a=r.isCurrentPostPublished,l=t("core/block-editor"),s=l.getBlockIndex,u=l.getBlockRootClientId,p=l.getTemplateLock,d=u(n);return{blockIndex:s(n,d),isLocked:!!p(d),rootClientId:d,shouldUpdateSiteOption:(o()&&a()||i())&&!c()}}),Object(x.withDispatch)(function(t,e){var n=e.blockIndex,r=e.rootClientId;return{createErrorNotice:t("core/notices").createErrorNotice,insertDefaultBlock:function(){return t("core/block-editor").insertDefaultBlock({},r,n+1)}}})])(function(t){var e=t.className,n=t.createErrorNotice,o=t.shouldUpdateSiteOption,c=t.isSelected,a=t.setAttributes,l=t.isLocked,s=t.insertDefaultBlock,u=q("description",Object(i.__)("Site description loading…"),n,c,o,a),p=u.siteOptions,d=u.handleChange,f=p.option;return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(T.PlainText,{className:P()("site-description",e),value:f,onChange:function(t){return d(t)},onKeyDown:function(t){t.keyCode===D.ENTER&&(t.preventDefault(),l||s())},placeholder:Object(i.__)("Add a Site Description"),"aria-label":Object(i.__)("Site Description")}))});n(36);Object(o.registerBlockType)("a8c/site-description",{title:Object(i.__)("Site Description"),description:Object(i.__)("Site description, also known as the tagline."),icon:Object(r.createElement)("svg",{xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24"},Object(r.createElement)("path",{fill:"none",d:"M0 0h24v24H0z"}),Object(r.createElement)("path",{d:"M4 9h16v2H4V9zm0 4h10v2H4v-2z"})),category:"layout",supports:{align:["wide","full"],html:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"}},edit:z,save:function(){return null}});var V=Object(d.compose)([Object(x.withSelect)(function(t,e){var n=e.clientId,r=t("core/editor"),o=r.isSavingPost,i=r.isPublishingPost,c=r.isAutosavingPost,a=r.isCurrentPostPublished,l=t("core/block-editor"),s=l.getBlockIndex,u=l.getBlockRootClientId,p=l.getTemplateLock,d=u(n);return{blockIndex:s(n,d),isLocked:!!p(d),rootClientId:d,shouldUpdateSiteOption:(o()&&a()||i())&&!c()}}),Object(x.withDispatch)(function(t,e){var n=e.blockIndex,r=e.rootClientId;return{createErrorNotice:t("core/notices").createErrorNotice,insertDefaultBlock:function(){return t("core/block-editor").insertDefaultBlock({},r,n+1)}}})])(function(t){var e=t.className,n=t.createErrorNotice,o=t.shouldUpdateSiteOption,c=t.isSelected,a=t.setAttributes,l=t.isLocked,s=t.insertDefaultBlock,u=q("title",Object(i.__)("Site title loading…"),n,c,o,a),p=u.siteOptions,d=u.handleChange,f=p.option;return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(T.PlainText,{className:P()("site-title",e),value:f,onChange:function(t){return d(t)},onKeyDown:function(t){t.keyCode===D.ENTER&&(t.preventDefault(),l||s())},placeholder:Object(i.__)("Add a Site Title"),"aria-label":Object(i.__)("Site Title")}))});n(37);Object(o.registerBlockType)("a8c/site-title",{title:Object(i.__)("Site Title"),description:Object(i.__)("Your site title."),icon:"layout",category:"layout",supports:{align:["wide","full"],html:!1,multiple:!1,reusable:!1},attributes:{align:{type:"string",default:"wide"}},edit:V,save:function(){return null}});var G=n(7),W=n(11),K=n(25),Q=(n(18),Object(d.compose)(Object(d.withState)({templateClientId:null}),Object(x.withSelect)(function(t,e){var n=e.attributes,r=e.templateClientId,o=t("core").getEntityRecord,i=t("core/editor"),c=i.getCurrentPostId,a=i.isEditedPostDirty,l=t("core/block-editor"),s=l.getBlock,u=l.getSelectedBlock,p=t("core/edit-post").isEditorSidebarOpened,d=n.templateId,f=c(),b=d&&o("postType","wp_template_part",d),m=Object(K.addQueryArgs)(fullSiteEditing.editTemplateBaseUrl,{post:d,fse_parent_post:f}),O=u();return{currentPostId:f,editTemplateUrl:m,template:b,templateBlock:s(r),templateTitle:Object(G.get)(b,["title","rendered"],""),isDirty:a(),isEditorSidebarOpened:!!p(),isAnyTemplateBlockSelected:O&&"a8c/template"===O.name}}),Object(x.withDispatch)(function(t,e){var n=t("core/block-editor").receiveBlocks,r=t("core/edit-post").openGeneralSidebar,i=e.template,c=e.templateClientId,a=e.setState;return{savePost:t("core/editor").savePost,receiveTemplateBlocks:function(){if(i&&!c){var t=Object(o.parse)(Object(G.get)(i,["content","raw"],"")),e=Object(o.createBlock)("core/group",{},t);n([e]),a({templateClientId:e.clientId})}},openGeneralSidebar:r}}))(function(t){var e,n=t.attributes,o=t.editTemplateUrl,c=t.receiveTemplateBlocks,a=t.template,l=t.templateBlock,s=t.templateTitle,u=t.isDirty,p=t.savePost,d=t.isEditorSidebarOpened,f=t.openGeneralSidebar,b=t.isAnyTemplateBlockSelected;if(!a)return Object(r.createElement)(W.Placeholder,null,Object(r.createElement)(W.Spinner,null));var O=Object(r.createRef)(),g=Object(r.useState)(!1),y=F()(g,2),v=y[0],h=y[1];Object(r.useEffect)(function(){v&&!u&&O.current.click(),c()}),Object(r.useEffect)(function(){var t=document.querySelector(".edit-post-sidebar__panel-tabs ul li:last-child");if(d&&t){if(b)return f("edit-post/document"),void t.classList.add("hidden");t.classList.remove("hidden")}},[b,d,f]);var j=n.align,E=n.className;return Object(r.createElement)("div",{className:P()("template-block",(e={},m()(e,"align".concat(j),j),m()(e,"is-navigating-to-template",v),e))},l&&Object(r.createElement)(r.Fragment,null,Object(r.createElement)(W.Disabled,null,Object(r.createElement)("div",{className:E},Object(r.createElement)(T.BlockEdit,{attributes:l.attributes,block:l,clientId:l.clientId,isSelected:!1,name:l.name,setAttributes:G.noop}))),Object(r.createElement)(W.Placeholder,{className:"template-block__overlay"},v&&Object(r.createElement)("div",{className:"template-block__loading"},Object(r.createElement)(W.Spinner,null)," ",Object(i.sprintf)(Object(i.__)("Loading %s Editor"),s)),Object(r.createElement)(W.Button,{className:v?"hidden":null,href:o,onClick:function(t){h(!0),u&&(t.preventDefault(),p())},isDefault:!0,isLarge:!0,ref:O},Object(i.sprintf)(Object(i.__)("Edit %s"),s)))))})),Y=Object(d.createHigherOrderComponent)(function(t){return function(e){return"fse-site-logo"!==e.attributes.className?Object(r.createElement)(t,e):Object(r.createElement)(t,p()({},e,{className:"template__site-logo"}))}},"addFSESiteLogoClassname");Object(f.addFilter)("editor.BlockListBlock","full-site-editing/blocks/template",Y),"wp_template_part"!==fullSiteEditing.editorPostType&&Object(o.registerBlockType)("a8c/template",{title:Object(i.__)("Template Part"),description:Object(i.__)("Display a Template Part."),icon:"layout",category:"layout",attributes:{templateId:{type:"number"},className:{type:"string"}},supports:{anchor:!1,customClassName:!1,html:!1,inserter:!1,reusable:!1},edit:Q,save:function(){return null},getEditWrapperProps:function(){return{"data-align":"full"}}});var J=Object(d.createHigherOrderComponent)(function(t){return function(e){return"a8c/template"!==e.name?Object(r.createElement)(t,e):Object(r.createElement)(t,p()({},e,{className:"template__block-container"}))}},"addFSETemplateClassname");Object(f.addFilter)("editor.BlockListBlock","full-site-editing/blocks/template",J,9);var X=n(13),Z=n.n(X);Z()(function(){var t=fullSiteEditing,e=t.closeButtonLabel,n=t.closeButtonUrl,r=t.editorPostType,o=setInterval(function(){var t=document.querySelector(".edit-post-fullscreen-mode-close__toolbar a");if(t&&(clearInterval(o),"wp_template_part"===r&&n)){var i=document.createElement("a");i.href=n,i.innerHTML=e,i.className="components-button components-icon-button is-button is-default",i.setAttribute("aria-label",e),document.querySelector(".edit-post-fullscreen-mode-close__toolbar").replaceChild(i,t)}})});var $=n(26),tt=n.n($),et=n(27),nt=Object(x.withSelect)(function(t){var e=t("core").getEntityRecord,n=t("core/editor").getEditedPostAttribute;return{templateClasses:Object(G.map)(n("template_part_types"),function(t){var n=Object(G.get)(e("taxonomy","wp_template_part_type",t),"name","");return Object(G.endsWith)(n,"-header")?"site-header site-branding":Object(G.endsWith)(n,"-footer")?"site-footer":void 0})}})(function(t){var e=t.templateClasses,n=setInterval(function(){var t=document.querySelector(".block-editor-writing-flow.editor-writing-flow > div");t&&(clearInterval(n),t.className=P.a.apply(void 0,["a8c-template-editor"].concat(tt()(e))))});return null});"wp_template_part"===fullSiteEditing.editorPostType&&Object(et.registerPlugin)("fse-editor-template-classes",{render:nt}),Z()(function(){"wp_template_part"===fullSiteEditing.editorPostType&&Object(x.dispatch)("core/notices").createNotice("info",Object(i.__)("Updates to this template will affect all pages on your site."),{isDismissible:!1})});var rt=Object(d.compose)(Object(x.withSelect)(function(t){var e=t("core/editor"),n=e.getBlocks,r=e.getEditorSettings,o=t("core/edit-post").getEditorMode,i=n().find(function(t){return"a8c/post-content"===t.name});return{rootClientId:i?i.clientId:"",showInserter:"visual"===o()&&r().richEditingEnabled}}))(function(t){var e=t.rootClientId,n=t.showInserter;return Object(r.createElement)(T.Inserter,{rootClientId:e,disabled:!n,position:"bottom right"})});Z()(function(){return function(){if("page"===fullSiteEditing.editorPostType)var t=setInterval(function(){var e=document.querySelector(".edit-post-header-toolbar");if(e){clearInterval(t);var n=document.createElement("div");n.classList.add("fse-post-content-block-inserter"),e.insertBefore(n,e.firstChild),Object(r.render)(Object(r.createElement)(rt,null),n)}})}()});var ot=Object(x.subscribe)(function(){if("page"!==fullSiteEditing.editorPostType)return ot();!1===Object(x.select)("core/editor").isValidTemplate()&&Object(x.dispatch)("core/editor").setTemplateValidity(!0)}),it=["logo","brand","emblem","hallmark"];Object(f.addFilter)("blocks.registerBlockType","full-site-editing/editor/image-block-keywords",function(t,e){return"core/image"!==e?t:t=Object(G.assign)({},t,{keywords:t.keywords.concat(it)})});n(41);Object(x.use)(function(t){return{dispatch:function(e){var n=A()({},t.dispatch(e)),r=fullSiteEditing.editorPostType;return"core/editor"===e&&n.trashPost&&"wp_template_part"===r&&(n.trashPost=function(){}),n}}}),Object(x.use)(function(t){return{dispatch:function(e){var n=A()({},t.dispatch(e)),r=fullSiteEditing.editorPostType;if("core/editor"===e&&n.editPost&&"wp_template_part"===r){var o=n.editPost;n.editPost=function(t){"draft"!==t.status&&o(t)}}return n}}});var ct=Object(x.subscribe)(function(){var t=Object(x.dispatch)("core/edit-post").removeEditorPanel;return"page"===fullSiteEditing.editorPostType&&t("featured-image"),"wp_template_part"===fullSiteEditing.editorPostType&&t("post-status"),ct()})}]));
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: alexislloyd, allancole, automattic, codebykat, copons, dmsnell, get_dave, glendaviesnz, gwwar, iamtakashi, Joen, kwight, marekhrabe, mattwiebe, mmtr86, mppfeiffer, nrqsnchz, obenland, okenobi, vindl, noahtallen, owolski
3
  Tags: block, blocks, editor, gutenberg, page
4
  Requires at least: 5.0
5
- Tested up to: 5.2
6
- Stable tag: 0.9
7
  Requires PHP: 5.6.20
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -39,9 +39,10 @@ It adds an excerpt! And meta information! It really is much more useful, especia
39
  This plugin is experimental, so we don't provide any support for it outside of websites hosted on WordPress.com at this time.
40
 
41
  == Changelog ==
 
 
42
 
43
  = 0.9 =
44
-
45
  * Rename wp_template CPT to wp_template_part.
46
 
47
  = 0.7 =
2
  Contributors: alexislloyd, allancole, automattic, codebykat, copons, dmsnell, get_dave, glendaviesnz, gwwar, iamtakashi, Joen, kwight, marekhrabe, mattwiebe, mmtr86, mppfeiffer, nrqsnchz, obenland, okenobi, vindl, noahtallen, owolski
3
  Tags: block, blocks, editor, gutenberg, page
4
  Requires at least: 5.0
5
+ Tested up to: 5.3
6
+ Stable tag: 0.10
7
  Requires PHP: 5.6.20
8
  License: GPLv2 or later
9
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
39
  This plugin is experimental, so we don't provide any support for it outside of websites hosted on WordPress.com at this time.
40
 
41
  == Changelog ==
42
+ = 0.10 =
43
+ * Update page template selector with template preview.
44
 
45
  = 0.9 =
 
46
  * Rename wp_template CPT to wp_template_part.
47
 
48
  = 0.7 =
starter-page-templates/class-starter-page-templates.php CHANGED
@@ -19,13 +19,33 @@ class Starter_Page_Templates {
19
  */
20
  private static $instance = null;
21
 
 
 
 
 
 
 
 
22
  /**
23
  * Starter_Page_Templates constructor.
24
  */
25
  private function __construct() {
 
 
 
 
 
 
 
 
 
 
26
  add_action( 'init', [ $this, 'register_scripts' ] );
27
  add_action( 'init', [ $this, 'register_meta_field' ] );
 
28
  add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_assets' ] );
 
 
29
  }
30
 
31
  /**
@@ -71,6 +91,15 @@ class Starter_Page_Templates {
71
  register_meta( 'post', '_starter_page_template', $args );
72
  }
73
 
 
 
 
 
 
 
 
 
 
74
  /**
75
  * Pass error message to frontend JavaScript console.
76
  *
@@ -170,12 +199,11 @@ class Starter_Page_Templates {
170
  * @return array Containing vertical name and template list or nothing if an error occurred.
171
  */
172
  public function fetch_vertical_data() {
173
- $vertical_id = get_option( 'site_vertical', 'default' );
174
- $transient_key = implode( '_', [ 'starter_page_templates', PLUGIN_VERSION, $vertical_id, get_locale() ] );
175
- $vertical_templates = get_transient( $transient_key );
176
 
177
  // Load fresh data if we don't have any or vertical_id doesn't match.
178
  if ( false === $vertical_templates || ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) {
 
179
  $request_url = add_query_arg(
180
  [
181
  '_locale' => $this->get_iso_639_locale(),
@@ -188,12 +216,31 @@ class Starter_Page_Templates {
188
  return [];
189
  }
190
  $vertical_templates = json_decode( wp_remote_retrieve_body( $response ), true );
191
- set_transient( $transient_key, $vertical_templates, DAY_IN_SECONDS );
192
  }
193
 
194
  return $vertical_templates;
195
  }
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  /**
198
  * Returns ISO 639 conforming locale string.
199
  *
19
  */
20
  private static $instance = null;
21
 
22
+ /**
23
+ * Cache key for templates array.
24
+ *
25
+ * @var string
26
+ */
27
+ public $templates_cache_key;
28
+
29
  /**
30
  * Starter_Page_Templates constructor.
31
  */
32
  private function __construct() {
33
+ $this->templates_cache_key = implode(
34
+ '_',
35
+ [
36
+ 'starter_page_templates',
37
+ PLUGIN_VERSION,
38
+ get_option( 'site_vertical', 'default' ),
39
+ get_locale(),
40
+ ]
41
+ );
42
+
43
  add_action( 'init', [ $this, 'register_scripts' ] );
44
  add_action( 'init', [ $this, 'register_meta_field' ] );
45
+ add_action( 'rest_api_init', [ $this, 'register_rest_api' ] );
46
  add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_assets' ] );
47
+ add_action( 'delete_attachment', [ $this, 'clear_sideloaded_image_cache' ] );
48
+ add_action( 'switch_theme', [ $this, 'clear_templates_cache' ] );
49
  }
50
 
51
  /**
91
  register_meta( 'post', '_starter_page_template', $args );
92
  }
93
 
94
+ /**
95
+ * Register rest api endpoint for side-loading images.
96
+ */
97
+ public function register_rest_api() {
98
+ require_once __DIR__ . '/class-wp-rest-sideload-image-controller.php';
99
+
100
+ ( new WP_REST_Sideload_Image_Controller() )->register_routes();
101
+ }
102
+
103
  /**
104
  * Pass error message to frontend JavaScript console.
105
  *
199
  * @return array Containing vertical name and template list or nothing if an error occurred.
200
  */
201
  public function fetch_vertical_data() {
202
+ $vertical_templates = get_transient( $this->templates_cache_key );
 
 
203
 
204
  // Load fresh data if we don't have any or vertical_id doesn't match.
205
  if ( false === $vertical_templates || ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ) {
206
+ $vertical_id = get_option( 'site_vertical', 'default' );
207
  $request_url = add_query_arg(
208
  [
209
  '_locale' => $this->get_iso_639_locale(),
216
  return [];
217
  }
218
  $vertical_templates = json_decode( wp_remote_retrieve_body( $response ), true );
219
+ set_transient( $this->templates_cache_key, $vertical_templates, DAY_IN_SECONDS );
220
  }
221
 
222
  return $vertical_templates;
223
  }
224
 
225
+ /**
226
+ * Deletes cached attachment data when attachment gets deleted.
227
+ *
228
+ * @param int $id Attachment ID of the attachment to be deleted.
229
+ */
230
+ public function clear_sideloaded_image_cache( $id ) {
231
+ $url = get_post_meta( $id, '_sideloaded_url', true );
232
+ if ( ! empty( $url ) ) {
233
+ delete_transient( 'fse_sideloaded_image_' . hash( 'crc32b', $url ) );
234
+ }
235
+ }
236
+
237
+ /**
238
+ * Deletes cached templates data when theme switches.
239
+ */
240
+ public function clear_templates_cache() {
241
+ delete_transient( $this->templates_cache_key );
242
+ }
243
+
244
  /**
245
  * Returns ISO 639 conforming locale string.
246
  *
starter-page-templates/dist/starter-page-templates.css CHANGED
@@ -1 +1 @@
1
- .page-template-modal-screen-overlay{animation:none}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{left:36px}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{left:160px}}body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:46px}@media screen and (min-width:783px){body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:32px}}.page-template-modal{width:100%;height:100vh;max-width:800px;animation:none}.page-template-modal .components-modal__header-heading-container{justify-content:center}.page-template-modal .components-modal__content{overflow-y:scroll;-webkit-overflow-scrolling:touch}.page-template-modal__inner{max-width:720px;margin:0 auto;padding:0}@media screen and (max-width:659px){.page-template-modal__inner{padding-bottom:3em}}.page-template-modal__list .components-base-control__label{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__list .template-selector-control__options{display:grid;grid-template-columns:1fr 1fr;grid-gap:1.75em}@media screen and (min-width:660px){.page-template-modal__list .template-selector-control__options{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}}.page-template-modal__list .template-selector-control__option{margin-bottom:4px}.page-template-modal__list .template-selector-control__label{display:block;width:100%;font-size:14px;text-align:center;border:1px solid #a1aab2;border-radius:6px;cursor:pointer;background:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0 0 14px;overflow:hidden}.page-template-modal__list .template-selector-control__label:focus,.page-template-modal__list .template-selector-control__label:hover{border-color:#2562b7;box-shadow:0 0 0 1px #2562b7;outline:1px solid transparent;outline-offset:-1px}.page-template-modal__list .template-selector-control__media-wrap{width:100%;display:block;margin:0 auto 14px;border-bottom:1px solid #a1aab2;background:#f6f6f6;border-radius:0;overflow:hidden;padding-bottom:110%;box-sizing:content-box;position:relative;pointer-events:none}.page-template-modal__list .template-selector-control__media{width:100%;display:block;position:absolute;top:0;left:0}.page-template-modal__actions{display:flex;flex-direction:column;align-items:center}@media screen and (min-width:960px){.page-template-modal__actions{flex-direction:row;justify-content:flex-end}}@media screen and (max-width:960px){.page-template-modal__action{margin-bottom:1em}}@media screen and (min-width:960px){.page-template-modal__action-use{margin-right:1em}}
1
+ .page-template-modal-screen-overlay{animation:none;background-color:transparent}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{left:36px}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{left:160px}}body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:46px}@media screen and (min-width:783px){body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:32px}}.page-template-modal{width:100%;height:100vh;animation:none;box-shadow:none;border:none;top:0;left:0;right:0;bottom:0;transform:none;max-width:none;max-height:none;background-color:#eee}.page-template-modal .components-modal__header-heading-container{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal .components-modal__header:after,.page-template-modal__close-button{display:none}body.is-fullscreen-mode .page-template-modal__close-button{display:block;position:absolute;z-index:20;top:9px;width:36px;height:36px;left:8px}body.is-fullscreen-mode .page-template-modal .components-modal__header:after{display:block;position:absolute;content:" ";border-right:1px solid #e2e4e7;height:100%;left:54px}.page-template-modal .components-modal__content{overflow-y:scroll;-webkit-overflow-scrolling:touch}.page-template-modal__inner{position:relative;margin:0 auto;padding:0}@media screen and (max-width:659px){.page-template-modal__inner{padding:0 14% 3em}}@media screen and (max-width:440px){.page-template-modal__inner{padding:0 15px 3em}}@media screen and (min-width:1200px){.page-template-modal__inner{max-width:100%}}.page-template-modal__list .components-base-control__label{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__list .template-selector-control__options{display:grid;grid-template-columns:1fr;grid-gap:1.75em}@media screen and (min-width:660px){.page-template-modal__list .template-selector-control__options{margin-top:0;grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}}@media screen and (min-width:1200px){.page-template-modal__list .template-selector-control__options{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}}.page-template-modal__list .template-selector-control__option{margin-bottom:4px}.page-template-modal__list .template-selector-item__label{display:block;width:100%;font-size:14px;text-align:center;border:2px solid #e2e4e7;border-radius:6px;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;overflow:hidden;background-color:#fff;position:relative}.page-template-modal__list .template-selector-item__label .template-selector-item__template-title{width:100%;position:absolute;bottom:0;left:0;height:40px;line-height:40px;background-color:#fff}.page-template-modal__list .template-selector-item__label:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;outline:2px solid transparent}.page-template-modal__list .template-selector-item__label:hover{border:2px solid #c9c9ca}.page-template-modal__list .template-selector-item__label.is-selected{border:2px solid #555d66;outline:2px solid transparent;outline-offset:-2px}.page-template-modal__list .template-selector-item__label.is-selected:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;border:2px solid #555d66;outline:4px solid transparent;outline-offset:-4px}.page-template-modal__list .template-selector-item__preview-wrap{width:100%;display:block;margin:0 auto;background:#fff;border-radius:0;overflow:hidden;height:0;padding-top:100%;box-sizing:content-box;position:relative;pointer-events:none;opacity:1}@media screen and (max-width:659px){.page-template-modal__list .template-selector-item__preview-wrap{padding-top:120%}}.page-template-modal__list .template-selector-item__preview-wrap.is-rendering{opacity:.5}.page-template-modal__list .template-selector-item__preview-wrap .block-editor-block-list__block,.page-template-modal__list .template-selector-item__preview-wrap .block-editor-block-list__layout{padding:inherit}.page-template-modal__list .template-selector-item__media{width:100%;display:block;position:absolute;top:0;left:0}@media screen and (max-width:659px){.page-template-modal__list .template-selector-control__template:first-child .template-selector-item__preview-wrap{padding-top:0;height:70px}}@media screen and (max-width:659px){.page-template-modal__list .template-selector-control__template:first-child .template-selector-item__template-title{height:70px;line-height:70px}}.page-template-modal__actions{display:flex;flex-direction:column;align-items:center}@media screen and (min-width:960px){.page-template-modal__actions{flex-direction:row;justify-content:flex-end}}@media screen and (max-width:960px){.page-template-modal__action{margin-bottom:1em}}@media screen and (min-width:960px){.page-template-modal__action-use{margin-right:1em}}@media screen and (min-width:660px){.page-template-modal__form{max-width:50%}}.page-template-modal__form-title{font-weight:700;margin-bottom:1em}@media screen and (max-width:659px){.page-template-modal__form-title{text-align:center}}.page-template-modal__buttons{position:absolute;right:0;top:0;z-index:10;height:56px;display:flex;align-items:center;padding-right:24px}@media screen and (max-width:659px){.page-template-modal__buttons{display:none}}.page-template-modal__buttons.is-visually-hidden{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__buttons .components-button{height:33px;line-height:32px}.template-selector-preview{position:fixed;top:111px;bottom:24px;right:24px;width:calc(50% - 50px);background:#fff;border-radius:2px;overflow-x:hidden;overflow-y:auto;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.12),0 1px 5px 0 rgba(0,0,0,.2)}@media screen and (max-width:659px){.template-selector-preview{display:none}}.template-selector-preview .edit-post-visual-editor{margin:0;padding:0}.template-selector-preview .editor-styles-wrapper .template-selector-preview__offset-correction{position:relative;top:120px}.template-selector-preview .editor-styles-wrapper .editor-post-title{transform-origin:top left;width:960px;display:block;position:absolute;top:0}.template-selector-preview .editor-styles-wrapper .editor-post-title,.template-selector-preview .editor-styles-wrapper .editor-post-title__block,.template-selector-preview .editor-styles-wrapper .editor-post-title__input{padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0}.template-selector-preview .editor-styles-wrapper .editor-post-title .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__block .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__input .editor-post-title__input{margin:0;padding:0;height:120px;line-height:120px}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .template-selector-preview{width:calc(50% - 84px)}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .template-selector-preview{width:calc(50% - 160px)}}.template-selector-preview__placeholder{position:absolute;top:50%;left:50%;transform:translateX(-50%);width:80%;text-align:center}.block-editor-block-preview__container .editor-styles-wrapper .wp-block,.template-selector-preview .editor-styles-wrapper .wp-block{width:100%}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full],.template-selector-preview .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full]{margin:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full] .wp-block-cover,.template-selector-preview .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full] .wp-block-cover{padding:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block-columns>.editor-inner-blocks>.editor-block-list__layout>[data-type="core/column"]>.editor-block-list__block-edit>div>.block-core-columns>.editor-inner-blocks,.template-selector-preview .editor-styles-wrapper .wp-block-columns>.editor-inner-blocks>.editor-block-list__layout>[data-type="core/column"]>.editor-block-list__block-edit>div>.block-core-columns>.editor-inner-blocks{margin-top:0;margin-bottom:0}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block[data-align=full],.template-selector-preview .editor-styles-wrapper .block-editor-block-list__block[data-align=full]{margin:0}@media screen and (min-width:600px){.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block .block-editor-block-list__block-edit,.template-selector-preview .editor-styles-wrapper .block-editor-block-list__block .block-editor-block-list__block-edit{margin:0}}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block,.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__layout,.template-selector-preview .editor-styles-wrapper .block-editor-block-list__block,.template-selector-preview .editor-styles-wrapper .block-editor-block-list__layout{padding:inherit}.template-selector-item__preview-wrap .components-disabled,.template-selector-item__preview-wrap .components-disabled .editor-styles-wrapper,.template-selector-item__preview-wrap .edit-post-visual-editor,.template-selector-item__preview-wrap .edit-post-visual-editor .editor-styles-wrapper,.template-selector-preview .components-disabled,.template-selector-preview .components-disabled .editor-styles-wrapper,.template-selector-preview .edit-post-visual-editor,.template-selector-preview .edit-post-visual-editor .editor-styles-wrapper{height:100%}.page-template-modal__loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:flex;align-items:flex-end}.page-template-modal__loading .components-spinner{float:none}
starter-page-templates/dist/starter-page-templates.deps.json CHANGED
@@ -1 +1 @@
1
- ["lodash","wp-blocks","wp-components","wp-compose","wp-data","wp-element","wp-i18n","wp-nux","wp-plugins","wp-polyfill"]
1
+ ["lodash","wp-api-fetch","wp-block-editor","wp-blocks","wp-components","wp-compose","wp-data","wp-element","wp-i18n","wp-nux","wp-plugins","wp-polyfill","wp-url"]
starter-page-templates/dist/starter-page-templates.js CHANGED
@@ -1,4 +1,4 @@
1
- !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=21)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){!function(){e.exports=this.lodash}()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t){!function(){e.exports=this.wp.compose}()},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t,n){var o=n(3);function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,o)}return n}e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(n,!0).forEach(function(t){o(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(n).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}},function(e,t){!function(){e.exports=this.wp.data}()},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}e.exports=function(e,t,o){return t&&n(e.prototype,t),o&&n(e,o),e}},function(e,t,n){var o=n(17),r=n(4);e.exports=function(e,t){return!t||"object"!==o(t)&&"function"!=typeof t?r(e):t}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t,n){var o=n(18);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&o(e,t)}},function(e,t){!function(){e.exports=this.wp.plugins}()},function(e,t){!function(){e.exports=this.wp.blocks}()},function(e,t,n){var o;
2
  /*!
3
  Copyright (c) 2017 Jed Watson.
4
  Licensed under the MIT License (MIT), see
@@ -9,4 +9,4 @@
9
  Licensed under the MIT License (MIT), see
10
  http://jedwatson.github.io/classnames
11
  */
12
- !function(){"use strict";var n={}.hasOwnProperty;function r(){for(var e=[],t=0;t<arguments.length;t++){var o=arguments[t];if(o){var i=typeof o;if("string"===i||"number"===i)e.push(o);else if(Array.isArray(o)&&o.length){var c=r.apply(null,o);c&&e.push(c)}else if("object"===i)for(var l in o)n.call(o,l)&&o[l]&&e.push(l)}}return e.join(" ")}e.exports?(r.default=r,e.exports=r):void 0===(o=function(){return r}.apply(t,[]))||(e.exports=o)}()},function(e,t){function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function o(t){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?e.exports=o=function(e){return n(e)}:e.exports=o=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":n(e)},o(t)}e.exports=o},function(e,t){function n(t,o){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,o)}e.exports=n},function(e,t){!function(){e.exports=this.wp.nux}()},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var o=n(7),r=n.n(o),i=n(9),c=n.n(i),l=n(10),a=n.n(l),s=n(11),u=n.n(s),p=n(12),f=n.n(p),m=n(4),d=n.n(m),b=n(13),y=n.n(b),v=n(3),_=n.n(v),g=n(0),O=n(2),h=n(1),j=n(5),w=n(6),x=n(14),P=n(8),E=n(15),S=(n(19),{Address:Object(h._x)("123 Main St","default address","full-site-editing"),Phone:Object(h._x)("555-555-5555","default phone number","full-site-editing"),CompanyName:Object(h._x)("Your Company Name","default company name","full-site-editing"),Vertical:Object(h._x)("Business","default vertical name","full-site-editing")}),k={CompanyName:"title",Address:"address",Phone:"phone",Vertical:"vertical"},C=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e.replace(/{{(\w+)}}/g,function(e,n){var o=S[n];return t[k[n]]||o||n})},N=(n(20),n(16)),T=n.n(N);var M=Object(j.withInstanceId)(function(e){var t=e.label,n=e.className,o=e.help,r=e.instanceId,i=e.onClick,c=e.templates,l=void 0===c?[]:c,a="template-selector-control-".concat(r),s=function(e){return i(e.target.value)};return Object(O.isEmpty)(l)?null:Object(g.createElement)(w.BaseControl,{label:t,id:a,help:o,className:T()(n,"template-selector-control")},Object(g.createElement)("ul",{className:"template-selector-control__options"},l.map(function(e,t){return Object(g.createElement)("li",{key:"".concat(a,"-").concat(t),className:"template-selector-control__option"},Object(g.createElement)("button",{type:"button",id:"".concat(a,"-").concat(t),className:"template-selector-control__label",value:e.value,onClick:s,"aria-describedby":o?"".concat(a,"__help"):void 0},Object(g.createElement)("div",{className:"template-selector-control__media-wrap"},e.preview&&Object(g.createElement)("img",{className:"template-selector-control__media",src:e.preview,alt:e.previewAlt||""})),e.label))})))});window._tkq=window._tkq||[];var I,q=null,A=function(e,t){q&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_dismiss",{blog_id:q.blogid,segment_id:e,vertical_id:t}])},B=function(e,t,n){q&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_template_selected",{blog_id:q.blogid,segment_id:e,vertical_id:t,template:n}])},D=function(e){function t(e){var n;return c()(this,t),n=u()(this,f()(t).call(this)),_()(d()(n),"state",{isLoading:!1}),_()(d()(n),"selectTemplate",function(e){n.setState({isOpen:!1}),B(n.props.segment.id,n.props.vertical.id,e);var t=n.props.templates[e];if(n.props.saveTemplateChoice(t),Object(O.has)(t,"content")){var o=r()({},t,{title:C(t.title,n.props.siteInformation),content:C(t.content,n.props.siteInformation)});n.props.insertTemplate(o)}}),_()(d()(n),"closeModal",function(){n.setState({isOpen:!1}),A(n.props.segment.id,n.props.vertical.id)}),n.state.isOpen=!Object(O.isEmpty)(e.templates),n}return y()(t,e),a()(t,[{key:"componentDidMount",value:function(){var e,t;this.state.isOpen&&(e=this.props.segment.id,t=this.props.vertical.id,q&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_view",{blog_id:q.blogid,segment_id:e,vertical_id:t}]))}},{key:"render",value:function(){var e=this;return this.state.isOpen?Object(g.createElement)(w.Modal,{title:Object(h.__)("Select Page Template","full-site-editing"),onRequestClose:this.closeModal,className:"page-template-modal",overlayClassName:"page-template-modal-screen-overlay"},Object(g.createElement)("div",{className:"page-template-modal__inner"},Object(g.createElement)("form",{className:"page-template-modal__form"},Object(g.createElement)("fieldset",{className:"page-template-modal__list"},Object(g.createElement)(M,{label:Object(h.__)("Template","full-site-editing"),templates:Object(O.map)(this.props.templates,function(e){return{label:e.title,value:e.slug,preview:e.preview,previewAlt:e.description}}),onClick:function(t){return e.selectTemplate(t)}}))))):null}}]),t}(g.Component),R=Object(j.compose)(Object(P.withSelect)(function(e){return{getMeta:function(){return e("core/editor").getEditedPostAttribute("meta")},postContentBlock:e("core/editor").getBlocks().find(function(e){return"a8c/post-content"===e.name})}}),Object(P.withDispatch)(function(e,t){e("core/nux").disableTips();var n=e("core/editor");return{saveTemplateChoice:function(e){var o=t.getMeta();n.editPost({meta:r()({},o,{_starter_page_template:e.slug})})},insertTemplate:function(e){n.editPost({title:e.title});var o=t.postContentBlock,r=Object(E.parse)(e.content);n.insertBlocks(r,0,o?o.clientId:"",!1)}}}))(D),U=window.starterPageTemplatesConfig,V=U.siteInformation,L=void 0===V?{}:V,Y=U.templates,z=void 0===Y?[]:Y,F=U.vertical,G=U.segment,H=U.tracksUserData;H&&(q=I=H,window._tkq.push(["identifyUser",I.userid,I.username])),Object(x.registerPlugin)("page-templates",{render:function(){return Object(g.createElement)(R,{templates:Object(O.keyBy)(z,"slug"),vertical:F,segment:G,siteInformation:L})}})}]));
1
+ !function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=33)}([function(e,t){!function(){e.exports=this.wp.element}()},function(e,t){!function(){e.exports=this.lodash}()},function(e,t){!function(){e.exports=this.wp.i18n}()},function(e,t){!function(){e.exports=this.wp.components}()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){var r;
2
  /*!
3
  Copyright (c) 2017 Jed Watson.
4
  Licensed under the MIT License (MIT), see
9
  Licensed under the MIT License (MIT), see
10
  http://jedwatson.github.io/classnames
11
  */
12
+ !function(){"use strict";var n={}.hasOwnProperty;function i(){for(var e=[],t=0;t<arguments.length;t++){var r=arguments[t];if(r){var o=typeof r;if("string"===o||"number"===o)e.push(r);else if(Array.isArray(r)&&r.length){var a=i.apply(null,r);a&&e.push(a)}else if("object"===o)for(var c in r)n.call(r,c)&&r[c]&&e.push(c)}}return e.join(" ")}e.exports?(i.default=i,e.exports=i):void 0===(r=function(){return i}.apply(t,[]))||(e.exports=r)}()},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}},function(e,t,n){var r=n(4);function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}e.exports=function(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(n,!0).forEach(function(t){r(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(n).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}},function(e,t){!function(){e.exports=this.wp.compose}()},function(e,t){!function(){e.exports=this.wp.blockEditor}()},function(e,t){!function(){e.exports=this.wp.data}()},function(e,t,n){var r=n(27),i=n(28),o=n(29);e.exports=function(e,t){return r(e)||i(e,t)||o()}},function(e,t){function n(e,t,n,r,i,o,a){try{var c=e[o](a),l=c.value}catch(s){return void n(s)}c.done?t(l):Promise.resolve(l).then(r,i)}e.exports=function(e){return function(){var t=this,r=arguments;return new Promise(function(i,o){var a=e.apply(t,r);function c(e){n(a,i,o,c,l,"next",e)}function l(e){n(a,i,o,c,l,"throw",e)}c(void 0)})}}},function(e,t,n){var r=n(30),i=n(31),o=n(32);e.exports=function(e){return r(e)||i(e)||o()}},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}},function(e,t){function n(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}e.exports=function(e,t,r){return t&&n(e.prototype,t),r&&n(e,r),e}},function(e,t,n){var r=n(23),i=n(6);e.exports=function(e,t){return!t||"object"!==r(t)&&"function"!=typeof t?i(e):t}},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},n(t)}e.exports=n},function(e,t,n){var r=n(24);e.exports=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&r(e,t)}},function(e,t){!function(){e.exports=this.wp.plugins}()},function(e,t){!function(){e.exports=this.wp.blocks}()},function(e,t){!function(){e.exports=this.wp.apiFetch}()},function(e,t){!function(){e.exports=this.wp.url}()},function(e,t){function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(t){return"function"==typeof Symbol&&"symbol"===n(Symbol.iterator)?e.exports=r=function(e){return n(e)}:e.exports=r=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":n(e)},r(t)}e.exports=r},function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},n(t,r)}e.exports=n},function(e,t){!function(){e.exports=this.wp.nux}()},function(e,t,n){},function(e,t){e.exports=function(e){if(Array.isArray(e))return e}},function(e,t){e.exports=function(e,t){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)){var n=[],r=!0,i=!1,o=void 0;try{for(var a,c=e[Symbol.iterator]();!(r=(a=c.next()).done)&&(n.push(a.value),!t||n.length!==t);r=!0);}catch(l){i=!0,o=l}finally{try{r||null==c.return||c.return()}finally{if(i)throw o}}return n}}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}},function(e,t){e.exports=function(e){if(Array.isArray(e)){for(var t=0,n=new Array(e.length);t<e.length;t++)n[t]=e[t];return n}}},function(e,t){e.exports=function(e){if(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e))return Array.from(e)}},function(e,t){e.exports=function(){throw new TypeError("Invalid attempt to spread non-iterable instance")}},function(e,t,n){"use strict";n.r(t);var r=n(7),i=n.n(r),o=n(14),a=n.n(o),c=n(15),l=n.n(c),s=n(16),u=n.n(s),p=n(17),m=n.n(p),f=n(6),d=n.n(f),b=n(18),v=n.n(b),y=n(4),g=n.n(y),O=n(0),h=n(1),j=n(5),w=n.n(j),_=(n(25),n(2)),E=n(8),k=n(3),x=n(19),S=n(10),T=n(20),P=(n(26),n(9)),N=function(e){var t=e.blocks,n=void 0===t?[]:t,r=e.viewportWidth;return n&&n.length?Object(O.createElement)("div",{className:"edit-post-visual-editor"},Object(O.createElement)("div",{className:"editor-styles-wrapper"},Object(O.createElement)("div",{className:"editor-writing-flow"},Object(O.createElement)(P.BlockPreview,{blocks:n,viewportWidth:r})))):null},B=function(e){var t=e.id,n=e.value,r=e.onSelect,i=e.label,o=e.useDynamicPreview,a=void 0!==o&&o,c=e.staticPreviewImg,l=e.staticPreviewImgAlt,s=void 0===l?"":l,u=e.blocks,p=void 0===u?[]:u,m=e.isSelected,f=e.handleTemplateConfirmation;if(Object(h.isNil)(t)||Object(h.isNil)(i)||Object(h.isNil)(n))return null;if(a&&(Object(h.isNil)(p)||Object(h.isEmpty)(p)))return null;var d=a?Object(O.createElement)(k.Disabled,null,Object(O.createElement)(N,{blocks:p,viewportWidth:960})):Object(O.createElement)("img",{className:"template-selector-item__media",src:c,alt:s}),b="label-".concat(t,"-").concat(n);return Object(O.createElement)("button",{type:"button",className:w()("template-selector-item__label",{"is-selected":m}),value:n,onClick:function(){var e=window.matchMedia("(min-width: 660px)").matches;r(n),e||f(n)},"aria-labelledby":"".concat(t," ").concat(b)},Object(O.createElement)("div",{className:"template-selector-item__preview-wrap"},d),Object(O.createElement)("span",{className:"template-selector-item__template-title",id:b},i))},C={Address:Object(_._x)("123 Main St","default address","full-site-editing"),Phone:Object(_._x)("555-555-5555","default phone number","full-site-editing"),CompanyName:Object(_._x)("Your Company Name","default company name","full-site-editing"),Vertical:Object(_._x)("Business","default vertical name","full-site-editing")},I={CompanyName:"title",Address:"address",Phone:"phone",Vertical:"vertical"},A=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return e?e.replace(/{{(\w+)}}/g,function(e,n){var r=C[n];return t[I[n]]||r||n}):""},D=Object(E.compose)(O.memo,E.withInstanceId)(function(e){var t=e.label,n=e.className,r=e.help,i=e.instanceId,o=e.templates,a=void 0===o?[]:o,c=e.blocksByTemplates,l=void 0===c?{}:c,s=e.useDynamicPreview,u=void 0!==s&&s,p=e.onTemplateSelect,m=void 0===p?h.noop:p,f=e.siteInformation,d=void 0===f?{}:f,b=e.selectedTemplate,v=e.handleTemplateConfirmation,y=void 0===v?h.noop:v;if(Object(h.isEmpty)(a)||!Object(h.isArray)(a))return null;if(!0===u&&Object(h.isEmpty)(l))return null;var g="template-selector-control-".concat(i);return Object(O.createElement)(k.BaseControl,{label:t,id:g,help:r,className:w()(n,"template-selector-control")},Object(O.createElement)("ul",{className:"template-selector-control__options","data-testid":"template-selector-control-options"},Object(h.map)(a,function(e){var t=e.slug,n=e.title,i=e.preview,o=e.previewAlt;return Object(O.createElement)("li",{key:"".concat(g,"-").concat(t),className:"template-selector-control__template"},Object(O.createElement)(B,{id:g,value:t,label:A(n,d),help:r,onSelect:m,staticPreviewImg:i,staticPreviewImgAlt:o,blocks:l.hasOwnProperty(t)?l[t]:[],useDynamicPreview:u,isSelected:t===b,handleTemplateConfirmation:y}))})))}),M=n(11),q=n.n(M),L=function(e){var t=e.title,n=e.transform;return Object(O.createElement)("div",{className:"editor-post-title",style:{transform:n}},Object(O.createElement)("div",{className:"wp-block editor-post-title__block"},Object(O.createElement)("textarea",{className:"editor-post-title__input",value:t,onChange:function(){}})))},R=function(e){return Object(O.createElement)(P.BlockPreview,e)},U=function(e){var t=e.blocks,n=e.viewportWidth,r=e.title,i=w()("template-selector-preview","editor-styles-wrapper"),o=Object(O.useState)("hidden"),a=q()(o,2),c=a[0],l=a[1],s=Object(O.useRef)(null),u=Object(O.useReducer)(function(e){return e+1},0),p=q()(u,2),m=p[0],f=p[1],d=function(){setTimeout(function(){if(s&&s.current){var e=s.current.querySelector(".block-editor-block-preview__content");if(e){var t=window.getComputedStyle(e);if(t&&t.transform){var n=s.current.querySelector(".editor-post-title");n&&(n.style.transform=t.transform);var r=t.transform.replace(/matrix\((.+)\)$/i,"$1").split(",");r=r&&r.length?Number(r[0]):null,r=isNaN(r)?null:r;var i=e.closest(".template-selector-preview__offset-correction");if(i&&r){var o=n?n.offsetHeight:null;i.style.top="".concat(o*r,"px")}}l("visible")}}},300)};return Object(O.useLayoutEffect)(function(){l("hidden"),d()},[t]),Object(O.useEffect)(function(){if(t&&t.length){var e=Object(h.debounce)(function(){d(),f()},300);return window.addEventListener("resize",e),function(){window.removeEventListener("resize",e)}}},[t]),Object(h.isEmpty)(t)||!Object(h.isArray)(t)?Object(O.createElement)("div",{className:i},Object(O.createElement)("div",{className:"template-selector-preview__placeholder"},Object(_.__)("Select a page template to preview.","full-site-editing"))):Object(O.createElement)("div",{className:i},Object(O.createElement)(k.Disabled,null,Object(O.createElement)("div",{ref:s,className:"edit-post-visual-editor"},Object(O.createElement)("div",{className:"editor-styles-wrapper",style:{visibility:c}},Object(O.createElement)("div",{className:"editor-writing-flow"},Object(O.createElement)(L,{title:r}),Object(O.createElement)("div",{className:"template-selector-preview__offset-correction"},Object(O.createElement)(R,{key:m,blocks:t,viewportWidth:n})))))))};window._tkq=window._tkq||[];var W,V=null,z=function(e,t){V&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_dismiss",{blog_id:V.blogid,segment_id:e,vertical_id:t}])},F=function(e,t,n){V&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_template_selected",{blog_id:V.blogid,segment_id:e,vertical_id:t,template:n}])},G=n(12),$=n.n(G),H=n(13),Q=n.n(H),Y=n(21),J=n.n(Y),K=n(22),X=function(e,t,n){var r=e[t=Object(K.removeQueryArgs)(t,"w","s")]||{url:t,usages:[]};return i()({},e,g()({},t,i()({},r,{usages:[].concat(Q()(r.usages),Q()(n))})))},Z=function e(t,n){switch(t.blocksByClientId[n.clientId]=n,n.name){case"core/cover":case"core/image":var r=n.attributes.url;r&&(t.assets=X(t.assets,r,[{prop:"url",path:[n.clientId,"attributes","url"]},{prop:"id",path:[n.clientId,"attributes","id"]}]));case"core/media-text":var i=n.attributes.mediaUrl;i&&"image"===n.attributes.mediaType&&(t.assets=X(t.assets,i,[{prop:"url",path:[n.clientId,"attributes","mediaUrl"]},{prop:"id",path:[n.clientId,"attributes","mediaId"]}]));case"core/gallery":Object(h.forEach)(n.attributes.images,function(e,r){t.assets=X(t.assets,e.url,[{prop:"url",path:[n.clientId,"attributes","images",r,"url"]},{prop:"url",path:[n.clientId,"attributes","images",r,"link"]},{prop:"id",path:[n.clientId,"attributes","images",r,"id"]},{prop:"id",path:[n.clientId,"attributes","ids",r]}])})}return Object(h.isEmpty)(n.innerBlocks)?t:Object(h.reduce)(n.innerBlocks,e,t)},ee=function(){var e=$()(regeneratorRuntime.mark(function e(t){return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:return e.next=2,J()({method:"POST",path:"/fse/v1/sideload/image/batch",data:{resources:Object(h.map)(t)}}).then(function(e){return Object(h.reduce)(t,function(t,n){var r=e.shift(),o=r.id,a=r.source_url;return i()({},t,g()({},n.url,{id:o,url:a}))},{})});case 2:return e.abrupt("return",e.sent);case 3:case"end":return e.stop()}},e)}));return function(t){return e.apply(this,arguments)}}(),te=function(e,t){return Object(h.forEach)(e.assets,function(n){var r=t[n.url];r&&Object(h.forEach)(n.usages,function(t){Object(h.set)(e.blocksByClientId,t.path,r[t.prop])})}),e.blocks},ne=function(){var e=$()(regeneratorRuntime.mark(function e(t){var n;return regeneratorRuntime.wrap(function(e){for(;;)switch(e.prev=e.next){case 0:if(n=Object(h.reduce)(t,Z,{assets:{},blocksByClientId:{},blocks:t}),!Object(h.isEmpty)(n.assets)){e.next=3;break}return e.abrupt("return",t);case 3:return e.abrupt("return",ee(n.assets).then(function(e){return te(n,e)}));case 4:case"end":return e.stop()}},e)}));return function(t){return e.apply(this,arguments)}}(),re=window.starterPageTemplatesConfig,ie=re.templates,oe=void 0===ie?[]:ie,ae=re.vertical,ce=re.segment,le=re.tracksUserData,se=re.siteInformation,ue=void 0===se?{}:se,pe=function(e){function t(e){var n;a()(this,t),n=u()(this,m()(t).call(this)),g()(d()(n),"state",{isLoading:!1,previewedTemplate:null,blocksByTemplateSlug:{},titlesByTemplateSlug:{},error:null,isOpen:!1}),g()(d()(n),"setTemplate",function(e){F(n.props.segment.id,n.props.vertical.id,e),n.props.saveTemplateChoice(e);var t=n.getBlocksByTemplateSlug(e),r=n.getTitleByTemplateSlug(e);t&&t.length?(n.setState({error:null,isLoading:!0}),n.maybePrefetchAssets(t).then(function(e){n.state.isOpen&&(n.props.insertTemplate(r,e),n.setState({isOpen:!1}))}).catch(function(e){n.setState({isLoading:!1,error:e})})):n.setState({isOpen:!1})}),g()(d()(n),"maybePrefetchAssets",function(e){return n.props.shouldPrefetchAssets?ne(e):Promise.resolve(e)}),g()(d()(n),"handleConfirmation",function(e){"string"!=typeof e&&(e=n.state.previewedTemplate),n.setTemplate(e)}),g()(d()(n),"previewTemplate",function(e){return n.setState({previewedTemplate:e})}),g()(d()(n),"closeModal",function(e){if(e.target.matches("button.template-selector-item__label"))return!1;z(n.props.segment.id,n.props.vertical.id);var t=Object(h.get)(window,["calypsoifyGutenberg","closeUrl"]);window.top.location=t||"edit.php?post_type=page"});var r=!Object(h.isEmpty)(e.templates);return n.state.isOpen=r,r&&(n.state.previewedTemplate=Object(h.get)(e.templates,[0,"slug"]),n.state.titlesByTemplateSlug=Object(h.mapValues)(Object(h.keyBy)(e.templates,"slug"),"title")),n}return v()(t,e),l()(t,[{key:"componentDidMount",value:function(){var e,t;this.state.isOpen&&(e=this.props.segment.id,t=this.props.vertical.id,V&&window._tkq.push(["recordEvent","a8c_full_site_editing_template_selector_view",{blog_id:V.blogid,segment_id:e,vertical_id:t}]));var n=Object(h.reduce)(oe,function(e,t){var n=t.slug,r=t.content;return e[n]=r?Object(T.parse)(A(r,ue)):[],e},{});this.setState({blocksByTemplateSlug:n})}},{key:"getBlocksByTemplateSlug",value:function(e){return Object(h.get)(this.state.blocksByTemplateSlug,[e],[])}},{key:"getTitleByTemplateSlug",value:function(e){return Object(h.get)(this.state.titlesByTemplateSlug,[e],"")}},{key:"render",value:function(){var e=this.state,t=e.previewedTemplate,n=e.isOpen,r=e.isLoading,i=e.blocksByTemplateSlug,o=this.props.templates;return n?Object(O.createElement)(k.Modal,{title:Object(_.__)("Select Page Template","full-site-editing"),className:"page-template-modal",overlayClassName:"page-template-modal-screen-overlay",shouldCloseOnClickOutside:!1,isDismissable:!1,isDismissible:!1},Object(O.createElement)(k.IconButton,{className:"page-template-modal__close-button components-icon-button",onClick:this.closeModal,icon:"arrow-left-alt2",label:Object(_.__)("Go back")}),Object(O.createElement)("div",{className:"page-template-modal__inner"},r?Object(O.createElement)("div",{className:"page-template-modal__loading"},Object(O.createElement)(k.Spinner,null),Object(_.__)("Inserting template…","full-site-editing")):Object(O.createElement)(O.Fragment,null,Object(O.createElement)("form",{className:"page-template-modal__form"},Object(O.createElement)("fieldset",{className:"page-template-modal__list"},Object(O.createElement)("legend",{className:"page-template-modal__form-title"},Object(_.__)("Choose a template…","full-site-editing")),Object(O.createElement)(D,{label:Object(_.__)("Template","full-site-editing"),templates:o,blocksByTemplates:i,onTemplateSelect:this.previewTemplate,useDynamicPreview:!1,siteInformation:ue,selectedTemplate:t,handleTemplateConfirmation:this.handleConfirmation}))),Object(O.createElement)(U,{blocks:this.getBlocksByTemplateSlug(t),viewportWidth:960,title:this.getTitleByTemplateSlug(t)}))),Object(O.createElement)("div",{className:w()("page-template-modal__buttons",{"is-visually-hidden":Object(h.isEmpty)(t)||r})},Object(O.createElement)(k.Button,{isPrimary:!0,isLarge:!0,disabled:Object(h.isEmpty)(t)||r,onClick:this.handleConfirmation},Object(_.sprintf)(Object(_.__)("Use %s template","full-site-editing"),this.getTitleByTemplateSlug(t))))):null}}]),t}(O.Component),me=Object(E.compose)(Object(S.withSelect)(function(e){return{getMeta:function(){return e("core/editor").getEditedPostAttribute("meta")},postContentBlock:e("core/editor").getBlocks().find(function(e){return"a8c/post-content"===e.name})}}),Object(S.withDispatch)(function(e,t){e("core/nux").disableTips();var n=e("core/editor");return{saveTemplateChoice:function(e){var r=t.getMeta();n.editPost({meta:i()({},r,{_starter_page_template:e})})},insertTemplate:function(r,i){n.editPost({title:r});var o=t.postContentBlock;e("core/block-editor").insertBlocks(i,0,o?o.clientId:"",!1)}}}))(pe);le&&(V=W=le,window._tkq.push(["identifyUser",W.userid,W.username])),Object(x.registerPlugin)("page-templates",{render:function(){return Object(O.createElement)(me,{shouldPrefetchAssets:!1,templates:oe,vertical:ae,segment:ce})}})}]));
starter-page-templates/dist/starter-page-templates.rtl.css CHANGED
@@ -1 +1 @@
1
- .page-template-modal-screen-overlay{animation:none}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{right:36px}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{right:160px}}body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:46px}@media screen and (min-width:783px){body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:32px}}.page-template-modal{width:100%;height:100vh;max-width:800px;animation:none}.page-template-modal .components-modal__header-heading-container{justify-content:center}.page-template-modal .components-modal__content{overflow-y:scroll;-webkit-overflow-scrolling:touch}.page-template-modal__inner{max-width:720px;margin:0 auto;padding:0}@media screen and (max-width:659px){.page-template-modal__inner{padding-bottom:3em}}.page-template-modal__list .components-base-control__label{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__list .template-selector-control__options{display:grid;grid-template-columns:1fr 1fr;grid-gap:1.75em}@media screen and (min-width:660px){.page-template-modal__list .template-selector-control__options{grid-template-columns:repeat(auto-fit,minmax(200px,1fr))}}.page-template-modal__list .template-selector-control__option{margin-bottom:4px}.page-template-modal__list .template-selector-control__label{display:block;width:100%;font-size:14px;text-align:center;border:1px solid #a1aab2;border-radius:6px;cursor:pointer;background:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0 0 14px;overflow:hidden}.page-template-modal__list .template-selector-control__label:focus,.page-template-modal__list .template-selector-control__label:hover{border-color:#2562b7;box-shadow:0 0 0 1px #2562b7;outline:1px solid transparent;outline-offset:-1px}.page-template-modal__list .template-selector-control__media-wrap{width:100%;display:block;margin:0 auto 14px;border-bottom:1px solid #a1aab2;background:#f6f6f6;border-radius:0;overflow:hidden;padding-bottom:110%;box-sizing:content-box;position:relative;pointer-events:none}.page-template-modal__list .template-selector-control__media{width:100%;display:block;position:absolute;top:0;right:0}.page-template-modal__actions{display:flex;flex-direction:column;align-items:center}@media screen and (min-width:960px){.page-template-modal__actions{flex-direction:row;justify-content:flex-end}}@media screen and (max-width:960px){.page-template-modal__action{margin-bottom:1em}}@media screen and (min-width:960px){.page-template-modal__action-use{margin-left:1em}}
1
+ .page-template-modal-screen-overlay{animation:none;background-color:transparent}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{right:36px}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{right:160px}}body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:46px}@media screen and (min-width:783px){body.admin-bar:not(.is-fullscreen-mode) .page-template-modal-screen-overlay{top:32px}}.page-template-modal{width:100%;height:100vh;animation:none;box-shadow:none;border:none;top:0;right:0;left:0;bottom:0;transform:none;max-width:none;max-height:none;background-color:#eee}.page-template-modal .components-modal__header-heading-container{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal .components-modal__header:after,.page-template-modal__close-button{display:none}body.is-fullscreen-mode .page-template-modal__close-button{display:block;position:absolute;z-index:20;top:9px;width:36px;height:36px;right:8px}body.is-fullscreen-mode .page-template-modal .components-modal__header:after{display:block;position:absolute;content:" ";border-left:1px solid #e2e4e7;height:100%;right:54px}.page-template-modal .components-modal__content{overflow-y:scroll;-webkit-overflow-scrolling:touch}.page-template-modal__inner{position:relative;margin:0 auto;padding:0}@media screen and (max-width:659px){.page-template-modal__inner{padding:0 14% 3em}}@media screen and (max-width:440px){.page-template-modal__inner{padding:0 15px 3em}}@media screen and (min-width:1200px){.page-template-modal__inner{max-width:100%}}.page-template-modal__list .components-base-control__label{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__list .template-selector-control__options{display:grid;grid-template-columns:1fr;grid-gap:1.75em}@media screen and (min-width:660px){.page-template-modal__list .template-selector-control__options{margin-top:0;grid-template-columns:repeat(auto-fit,minmax(110px,1fr))}}@media screen and (min-width:1200px){.page-template-modal__list .template-selector-control__options{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}}.page-template-modal__list .template-selector-control__option{margin-bottom:4px}.page-template-modal__list .template-selector-item__label{display:block;width:100%;font-size:14px;text-align:center;border:2px solid #e2e4e7;border-radius:6px;cursor:pointer;-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;overflow:hidden;background-color:#fff;position:relative}.page-template-modal__list .template-selector-item__label .template-selector-item__template-title{width:100%;position:absolute;bottom:0;right:0;height:40px;line-height:40px;background-color:#fff}.page-template-modal__list .template-selector-item__label:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;outline:2px solid transparent}.page-template-modal__list .template-selector-item__label:hover{border:2px solid #c9c9ca}.page-template-modal__list .template-selector-item__label.is-selected{border:2px solid #555d66;outline:2px solid transparent;outline-offset:-2px}.page-template-modal__list .template-selector-item__label.is-selected:focus{box-shadow:0 0 0 1px #fff,0 0 0 3px #00a0d2;border:2px solid #555d66;outline:4px solid transparent;outline-offset:-4px}.page-template-modal__list .template-selector-item__preview-wrap{width:100%;display:block;margin:0 auto;background:#fff;border-radius:0;overflow:hidden;height:0;padding-top:100%;box-sizing:content-box;position:relative;pointer-events:none;opacity:1}@media screen and (max-width:659px){.page-template-modal__list .template-selector-item__preview-wrap{padding-top:120%}}.page-template-modal__list .template-selector-item__preview-wrap.is-rendering{opacity:.5}.page-template-modal__list .template-selector-item__preview-wrap .block-editor-block-list__block,.page-template-modal__list .template-selector-item__preview-wrap .block-editor-block-list__layout{padding:inherit}.page-template-modal__list .template-selector-item__media{width:100%;display:block;position:absolute;top:0;right:0}@media screen and (max-width:659px){.page-template-modal__list .template-selector-control__template:first-child .template-selector-item__preview-wrap{padding-top:0;height:70px}}@media screen and (max-width:659px){.page-template-modal__list .template-selector-control__template:first-child .template-selector-item__template-title{height:70px;line-height:70px}}.page-template-modal__actions{display:flex;flex-direction:column;align-items:center}@media screen and (min-width:960px){.page-template-modal__actions{flex-direction:row;justify-content:flex-end}}@media screen and (max-width:960px){.page-template-modal__action{margin-bottom:1em}}@media screen and (min-width:960px){.page-template-modal__action-use{margin-left:1em}}@media screen and (min-width:660px){.page-template-modal__form{max-width:50%}}.page-template-modal__form-title{font-weight:700;margin-bottom:1em}@media screen and (max-width:659px){.page-template-modal__form-title{text-align:center}}.page-template-modal__buttons{position:absolute;left:0;top:0;z-index:10;height:56px;display:flex;align-items:center;padding-left:24px}@media screen and (max-width:659px){.page-template-modal__buttons{display:none}}.page-template-modal__buttons.is-visually-hidden{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal!important}.page-template-modal__buttons .components-button{height:33px;line-height:32px}.template-selector-preview{position:fixed;top:111px;bottom:24px;left:24px;width:calc(50% - 50px);background:#fff;border-radius:2px;overflow-x:hidden;overflow-y:auto;box-shadow:0 2px 2px 0 rgba(0,0,0,.14),0 3px 1px -2px rgba(0,0,0,.12),0 1px 5px 0 rgba(0,0,0,.2)}@media screen and (max-width:659px){.template-selector-preview{display:none}}.template-selector-preview .edit-post-visual-editor{margin:0;padding:0}.template-selector-preview .editor-styles-wrapper .template-selector-preview__offset-correction{position:relative;top:120px}.template-selector-preview .editor-styles-wrapper .editor-post-title{transform-origin:top right;width:960px;display:block;position:absolute;top:0}.template-selector-preview .editor-styles-wrapper .editor-post-title,.template-selector-preview .editor-styles-wrapper .editor-post-title__block,.template-selector-preview .editor-styles-wrapper .editor-post-title__input{padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0}.template-selector-preview .editor-styles-wrapper .editor-post-title .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__block .editor-post-title__input,.template-selector-preview .editor-styles-wrapper .editor-post-title__input .editor-post-title__input{margin:0;padding:0;height:120px;line-height:120px}@media screen and (min-width:783px){body:not(.is-fullscreen-mode) .template-selector-preview{width:calc(50% - 84px)}}@media screen and (min-width:961px){body:not(.is-fullscreen-mode) .template-selector-preview{width:calc(50% - 160px)}}.template-selector-preview__placeholder{position:absolute;top:50%;right:50%;transform:translateX(50%);width:80%;text-align:center}.block-editor-block-preview__container .editor-styles-wrapper .wp-block,.template-selector-preview .editor-styles-wrapper .wp-block{width:100%}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full],.template-selector-preview .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full]{margin:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full] .wp-block-cover,.template-selector-preview .editor-styles-wrapper .wp-block[data-type="core/cover"][data-align=full] .wp-block-cover{padding:0}.block-editor-block-preview__container .editor-styles-wrapper .wp-block-columns>.editor-inner-blocks>.editor-block-list__layout>[data-type="core/column"]>.editor-block-list__block-edit>div>.block-core-columns>.editor-inner-blocks,.template-selector-preview .editor-styles-wrapper .wp-block-columns>.editor-inner-blocks>.editor-block-list__layout>[data-type="core/column"]>.editor-block-list__block-edit>div>.block-core-columns>.editor-inner-blocks{margin-top:0;margin-bottom:0}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block[data-align=full],.template-selector-preview .editor-styles-wrapper .block-editor-block-list__block[data-align=full]{margin:0}@media screen and (min-width:600px){.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block .block-editor-block-list__block-edit,.template-selector-preview .editor-styles-wrapper .block-editor-block-list__block .block-editor-block-list__block-edit{margin:0}}.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__block,.block-editor-block-preview__container .editor-styles-wrapper .block-editor-block-list__layout,.template-selector-preview .editor-styles-wrapper .block-editor-block-list__block,.template-selector-preview .editor-styles-wrapper .block-editor-block-list__layout{padding:inherit}.template-selector-item__preview-wrap .components-disabled,.template-selector-item__preview-wrap .components-disabled .editor-styles-wrapper,.template-selector-item__preview-wrap .edit-post-visual-editor,.template-selector-item__preview-wrap .edit-post-visual-editor .editor-styles-wrapper,.template-selector-preview .components-disabled,.template-selector-preview .components-disabled .editor-styles-wrapper,.template-selector-preview .edit-post-visual-editor,.template-selector-preview .edit-post-visual-editor .editor-styles-wrapper{height:100%}.page-template-modal__loading{position:absolute;top:50%;right:50%;transform:translate(50%,-50%);display:flex;align-items:flex-end}.page-template-modal__loading .components-spinner{float:none}
starter-page-templates/page-template-modal/components/block-preview.js ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * External dependencies
3
+ */
4
+
5
+ /**
6
+ * Internal dependencies
7
+ */
8
+
9
+ /**
10
+ * WordPress dependencies
11
+ */
12
+ /* eslint-disable import/no-extraneous-dependencies */
13
+ import { BlockPreview } from '@wordpress/block-editor';
14
+ /* eslint-enable import/no-extraneous-dependencies */
15
+
16
+ // Exists as a pass through component to simplying testing
17
+ // components which consume `BlockPreview` from
18
+ // `@wordpress/block-editor`. This is because jest cannot mock
19
+ // node modules that are not part of the root node modules.
20
+ // Due to the way this projects dependencies are defined
21
+ // `@wordpress/block-editor` does not exist within `node_modules`
22
+ // and it is there impossible to mock it without providing a wrapping
23
+ // component to act as a pass though.
24
+ // See https://jestjs.io/docs/en/manual-mocks
25
+ export default function( props ) {
26
+ return <BlockPreview { ...props } />;
27
+ }
starter-page-templates/page-template-modal/components/block-template-preview.js CHANGED
@@ -9,9 +9,11 @@
9
  /**
10
  * WordPress dependencies
11
  */
 
12
  import { BlockPreview } from '@wordpress/block-editor';
 
13
 
14
- const BlockTemplatePreview = ( { blocks, viewportWidth } ) => {
15
  if ( ! blocks || ! blocks.length ) {
16
  return null;
17
  }
@@ -21,7 +23,7 @@ const BlockTemplatePreview = ( { blocks, viewportWidth } ) => {
21
  <div className="edit-post-visual-editor">
22
  <div className="editor-styles-wrapper">
23
  <div className="editor-writing-flow">
24
- { blocks && <BlockPreview blocks={ blocks } viewportWidth={ viewportWidth } /> }
25
  </div>
26
  </div>
27
  </div>
9
  /**
10
  * WordPress dependencies
11
  */
12
+ /* eslint-disable import/no-extraneous-dependencies */
13
  import { BlockPreview } from '@wordpress/block-editor';
14
+ /* eslint-enable import/no-extraneous-dependencies */
15
 
16
+ const BlockTemplatePreview = ( { blocks = [], viewportWidth } ) => {
17
  if ( ! blocks || ! blocks.length ) {
18
  return null;
19
  }
23
  <div className="edit-post-visual-editor">
24
  <div className="editor-styles-wrapper">
25
  <div className="editor-writing-flow">
26
+ <BlockPreview blocks={ blocks } viewportWidth={ viewportWidth } />
27
  </div>
28
  </div>
29
  </div>
starter-page-templates/page-template-modal/components/preview-template-title.js CHANGED
@@ -10,8 +10,8 @@
10
  const PreviewTemplateTitle = ( { title, transform } ) => (
11
  /* eslint-disable wpcalypso/jsx-classname-namespace */
12
  <div className="editor-post-title" style={ { transform } }>
13
- <div className="editor-post-title__block">
14
- <textarea className="editor-post-title__input" value={ title } />
15
  </div>
16
  </div>
17
  /* eslint-enable wpcalypso/jsx-classname-namespace */
10
  const PreviewTemplateTitle = ( { title, transform } ) => (
11
  /* eslint-disable wpcalypso/jsx-classname-namespace */
12
  <div className="editor-post-title" style={ { transform } }>
13
+ <div className="wp-block editor-post-title__block">
14
+ <textarea className="editor-post-title__input" value={ title } onChange={ () => {} } />
15
  </div>
16
  </div>
17
  /* eslint-enable wpcalypso/jsx-classname-namespace */
starter-page-templates/page-template-modal/components/template-selector-control.js CHANGED
@@ -1,30 +1,49 @@
1
  /**
2
  * External dependencies
3
  */
4
- import { isEmpty } from 'lodash';
 
 
5
  import classnames from 'classnames';
6
 
7
  /**
8
  * WordPress dependencies
9
  */
10
- import { withInstanceId } from '@wordpress/compose';
 
11
  import { BaseControl } from '@wordpress/components';
 
 
12
 
13
- function TemplateSelectorControl( {
 
 
 
 
 
 
14
  label,
15
  className,
16
  help,
17
  instanceId,
18
- onClick,
19
  templates = [],
20
- } ) {
21
- const id = `template-selector-control-${ instanceId }`;
22
- const handleButtonClick = event => onClick( event.target.value );
 
 
 
 
 
 
 
23
 
24
- if ( isEmpty( templates ) ) {
25
  return null;
26
  }
27
 
 
 
28
  return (
29
  <BaseControl
30
  label={ label }
@@ -32,33 +51,33 @@ function TemplateSelectorControl( {
32
  help={ help }
33
  className={ classnames( className, 'template-selector-control' ) }
34
  >
35
- <ul className="template-selector-control__options">
36
- { templates.map( ( option, index ) => (
37
- <li key={ `${ id }-${ index }` } className="template-selector-control__option">
38
- <button
39
- type="button"
40
- id={ `${ id }-${ index }` }
41
- className="template-selector-control__label"
42
- value={ option.value }
43
- onClick={ handleButtonClick }
44
- aria-describedby={ help ? `${ id }__help` : undefined }
45
- >
46
- <div className="template-selector-control__media-wrap">
47
- { option.preview && (
48
- <img
49
- className="template-selector-control__media"
50
- src={ option.preview }
51
- alt={ option.previewAlt || '' }
52
- />
53
- ) }
54
- </div>
55
- { option.label }
56
- </button>
57
  </li>
58
  ) ) }
59
  </ul>
60
  </BaseControl>
61
  );
62
- }
63
 
64
- export default withInstanceId( TemplateSelectorControl );
 
 
 
1
  /**
2
  * External dependencies
3
  */
4
+ /* eslint-disable import/no-extraneous-dependencies */
5
+ import { isEmpty, isArray, noop, map } from 'lodash';
6
+ /* eslint-enable import/no-extraneous-dependencies */
7
  import classnames from 'classnames';
8
 
9
  /**
10
  * WordPress dependencies
11
  */
12
+ /* eslint-disable import/no-extraneous-dependencies */
13
+ import { withInstanceId, compose } from '@wordpress/compose';
14
  import { BaseControl } from '@wordpress/components';
15
+ import { memo } from '@wordpress/element';
16
+ /* eslint-enable import/no-extraneous-dependencies */
17
 
18
+ /**
19
+ * Internal dependencies
20
+ */
21
+ import TemplateSelectorItem from './template-selector-item';
22
+ import replacePlaceholders from '../utils/replace-placeholders';
23
+
24
+ export const TemplateSelectorControl = ( {
25
  label,
26
  className,
27
  help,
28
  instanceId,
 
29
  templates = [],
30
+ blocksByTemplates = {},
31
+ useDynamicPreview = false,
32
+ onTemplateSelect = noop,
33
+ siteInformation = {},
34
+ selectedTemplate,
35
+ handleTemplateConfirmation = noop,
36
+ } ) => {
37
+ if ( isEmpty( templates ) || ! isArray( templates ) ) {
38
+ return null;
39
+ }
40
 
41
+ if ( true === useDynamicPreview && isEmpty( blocksByTemplates ) ) {
42
  return null;
43
  }
44
 
45
+ const id = `template-selector-control-${ instanceId }`;
46
+
47
  return (
48
  <BaseControl
49
  label={ label }
51
  help={ help }
52
  className={ classnames( className, 'template-selector-control' ) }
53
  >
54
+ <ul
55
+ className="template-selector-control__options"
56
+ data-testid="template-selector-control-options"
57
+ >
58
+ { map( templates, ( { slug, title, preview, previewAlt } ) => (
59
+ <li key={ `${ id }-${ slug }` } className="template-selector-control__template">
60
+ <TemplateSelectorItem
61
+ id={ id }
62
+ value={ slug }
63
+ label={ replacePlaceholders( title, siteInformation ) }
64
+ help={ help }
65
+ onSelect={ onTemplateSelect }
66
+ staticPreviewImg={ preview }
67
+ staticPreviewImgAlt={ previewAlt }
68
+ blocks={ blocksByTemplates.hasOwnProperty( slug ) ? blocksByTemplates[ slug ] : [] }
69
+ useDynamicPreview={ useDynamicPreview }
70
+ isSelected={ slug === selectedTemplate }
71
+ handleTemplateConfirmation={ handleTemplateConfirmation }
72
+ />
 
 
 
73
  </li>
74
  ) ) }
75
  </ul>
76
  </BaseControl>
77
  );
78
+ };
79
 
80
+ export default compose(
81
+ memo,
82
+ withInstanceId
83
+ )( TemplateSelectorControl );
starter-page-templates/page-template-modal/components/template-selector-item.js CHANGED
@@ -1,31 +1,41 @@
1
  /**
2
  * External dependencies
3
  */
4
-
5
- /**
6
- * Internal dependencies
7
- */
8
 
9
  /**
10
  * WordPress dependencies
11
  */
12
  import BlockPreview from './block-template-preview';
 
13
  import { Disabled } from '@wordpress/components';
 
14
 
15
  const TemplateSelectorItem = props => {
16
  const {
17
  id,
18
  value,
19
- help,
20
- onFocus,
21
  onSelect,
22
  label,
23
  useDynamicPreview = false,
24
  staticPreviewImg,
25
  staticPreviewImgAlt = '',
26
  blocks = [],
 
 
27
  } = props;
28
 
 
 
 
 
 
 
 
 
29
  // Define static or dynamic preview.
30
  const innerPreview = useDynamicPreview ? (
31
  <Disabled>
@@ -39,18 +49,37 @@ const TemplateSelectorItem = props => {
39
  />
40
  );
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  return (
43
  <button
44
  type="button"
45
- id={ `${ id }-${ value }` }
46
- className="template-selector-item__label"
 
47
  value={ value }
48
- onMouseEnter={ () => onFocus( value, label ) }
49
- onClick={ () => onSelect( value, label ) }
50
- aria-describedby={ help ? `${ id }__help` : undefined }
51
  >
52
  <div className="template-selector-item__preview-wrap">{ innerPreview }</div>
53
- { label }
 
 
54
  </button>
55
  );
56
  };
1
  /**
2
  * External dependencies
3
  */
4
+ /* eslint-disable import/no-extraneous-dependencies */
5
+ import { isNil, isEmpty } from 'lodash';
6
+ /* eslint-enable import/no-extraneous-dependencies */
7
+ import classnames from 'classnames';
8
 
9
  /**
10
  * WordPress dependencies
11
  */
12
  import BlockPreview from './block-template-preview';
13
+ /* eslint-disable import/no-extraneous-dependencies */
14
  import { Disabled } from '@wordpress/components';
15
+ /* eslint-enable import/no-extraneous-dependencies */
16
 
17
  const TemplateSelectorItem = props => {
18
  const {
19
  id,
20
  value,
 
 
21
  onSelect,
22
  label,
23
  useDynamicPreview = false,
24
  staticPreviewImg,
25
  staticPreviewImgAlt = '',
26
  blocks = [],
27
+ isSelected,
28
+ handleTemplateConfirmation,
29
  } = props;
30
 
31
+ if ( isNil( id ) || isNil( label ) || isNil( value ) ) {
32
+ return null;
33
+ }
34
+
35
+ if ( useDynamicPreview && ( isNil( blocks ) || isEmpty( blocks ) ) ) {
36
+ return null;
37
+ }
38
+
39
  // Define static or dynamic preview.
40
  const innerPreview = useDynamicPreview ? (
41
  <Disabled>
49
  />
50
  );
51
 
52
+ const labelId = `label-${ id }-${ value }`;
53
+
54
+ /**
55
+ * Determines (based on whether the large preview is able to be visible at the
56
+ * current breakpoint) whether or not the Template selection UI interaction model
57
+ * should be select _and_ confirm or simply a single "tap to confirm".
58
+ */
59
+ const handleLabelClick = () => {
60
+ const largeTplPreviewVisible = window.matchMedia( '(min-width: 660px)' ).matches;
61
+ // In both cases set the template as being selected
62
+ onSelect( value );
63
+ // Confirm the template when large preview isn't visible
64
+ if ( ! largeTplPreviewVisible ) {
65
+ handleTemplateConfirmation( value );
66
+ }
67
+ };
68
+
69
  return (
70
  <button
71
  type="button"
72
+ className={ classnames( 'template-selector-item__label', {
73
+ 'is-selected': isSelected,
74
+ } ) }
75
  value={ value }
76
+ onClick={ handleLabelClick }
77
+ aria-labelledby={ `${ id } ${ labelId }` }
 
78
  >
79
  <div className="template-selector-item__preview-wrap">{ innerPreview }</div>
80
+ <span className="template-selector-item__template-title" id={ labelId }>
81
+ { label }
82
+ </span>
83
  </button>
84
  );
85
  };
starter-page-templates/page-template-modal/components/template-selector-preview.js CHANGED
@@ -2,26 +2,29 @@
2
  * External dependencies
3
  */
4
  import classnames from 'classnames';
5
- import { isEmpty, debounce } from 'lodash';
 
 
6
 
7
  /**
8
  * WordPress dependencies
9
  */
 
10
  import { __ } from '@wordpress/i18n';
11
- import { BlockPreview } from '@wordpress/block-editor';
12
  import { Disabled } from '@wordpress/components';
13
  import { useState, useEffect, useLayoutEffect, useRef, useReducer } from '@wordpress/element';
 
14
 
15
  /**
16
  * Internal dependencies
17
  */
18
  import PreviewTemplateTitle from './preview-template-title';
 
19
 
20
  const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
21
  const THRESHOLD_RESIZE = 300;
22
 
23
  const previewElClasses = classnames( 'template-selector-preview', 'editor-styles-wrapper' );
24
- const [ transform, setTransform ] = useState( 'none' );
25
  const [ visibility, setVisibility ] = useState( 'hidden' );
26
  const ref = useRef( null );
27
 
@@ -42,7 +45,9 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
42
  }
43
 
44
  // Try to get the preview content element.
45
- const previewContainerEl = ref.current.querySelector( '.block-editor-block-preview__content' );
 
 
46
  if ( ! previewContainerEl ) {
47
  return;
48
  }
@@ -50,7 +55,26 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
50
  // Try to get the `transform` css rule from the preview container element.
51
  const elStyles = window.getComputedStyle( previewContainerEl );
52
  if ( elStyles && elStyles.transform ) {
53
- setTransform( elStyles.transform ); // apply the same transform css rule to template title.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  }
55
 
56
  setVisibility( 'visible' );
@@ -63,7 +87,7 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
63
  }, [ blocks ] );
64
 
65
  useEffect( () => {
66
- if ( ! blocks.length ) {
67
  return;
68
  }
69
 
@@ -80,7 +104,7 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
80
  };
81
  }, [ blocks ] );
82
 
83
- if ( isEmpty( blocks ) ) {
84
  return (
85
  <div className={ previewElClasses }>
86
  <div className="template-selector-preview__placeholder">
@@ -97,8 +121,10 @@ const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
97
  <div ref={ ref } className="edit-post-visual-editor">
98
  <div className="editor-styles-wrapper" style={ { visibility } }>
99
  <div className="editor-writing-flow">
100
- <PreviewTemplateTitle title={ title } transform={ transform } />
101
- <BlockPreview key={ recompute } blocks={ blocks } viewportWidth={ viewportWidth } />
 
 
102
  </div>
103
  </div>
104
  </div>
2
  * External dependencies
3
  */
4
  import classnames from 'classnames';
5
+ /* eslint-disable import/no-extraneous-dependencies */
6
+ import { isEmpty, isArray, debounce } from 'lodash';
7
+ /* eslint-enable import/no-extraneous-dependencies */
8
 
9
  /**
10
  * WordPress dependencies
11
  */
12
+ /* eslint-disable import/no-extraneous-dependencies */
13
  import { __ } from '@wordpress/i18n';
 
14
  import { Disabled } from '@wordpress/components';
15
  import { useState, useEffect, useLayoutEffect, useRef, useReducer } from '@wordpress/element';
16
+ /* eslint-enable import/no-extraneous-dependencies */
17
 
18
  /**
19
  * Internal dependencies
20
  */
21
  import PreviewTemplateTitle from './preview-template-title';
22
+ import BlockPreview from './block-preview';
23
 
24
  const TemplateSelectorPreview = ( { blocks, viewportWidth, title } ) => {
25
  const THRESHOLD_RESIZE = 300;
26
 
27
  const previewElClasses = classnames( 'template-selector-preview', 'editor-styles-wrapper' );
 
28
  const [ visibility, setVisibility ] = useState( 'hidden' );
29
  const ref = useRef( null );
30
 
45
  }
46
 
47
  // Try to get the preview content element.
48
+ const previewContainerEl = ref.current.querySelector(
49
+ '.block-editor-block-preview__content'
50
+ );
51
  if ( ! previewContainerEl ) {
52
  return;
53
  }
55
  // Try to get the `transform` css rule from the preview container element.
56
  const elStyles = window.getComputedStyle( previewContainerEl );
57
  if ( elStyles && elStyles.transform ) {
58
+ const titleElement = ref.current.querySelector( '.editor-post-title' );
59
+ if ( titleElement ) {
60
+ // Apply the same transform css rule at template title element.
61
+ titleElement.style.transform = elStyles.transform;
62
+ }
63
+
64
+ // Pick up scale factor from `transform` css.
65
+ let scale = elStyles.transform.replace( /matrix\((.+)\)$/i, '$1' ).split( ',' );
66
+ scale = scale && scale.length ? Number( scale[ 0 ] ) : null;
67
+ scale = isNaN( scale ) ? null : scale;
68
+
69
+ // Try to adjust vertical offset of the large preview.
70
+ const offsetCorrectionEl = previewContainerEl.closest(
71
+ '.template-selector-preview__offset-correction'
72
+ );
73
+
74
+ if ( offsetCorrectionEl && scale ) {
75
+ const titleHeight = titleElement ? titleElement.offsetHeight : null;
76
+ offsetCorrectionEl.style.top = `${ titleHeight * scale }px`;
77
+ }
78
  }
79
 
80
  setVisibility( 'visible' );
87
  }, [ blocks ] );
88
 
89
  useEffect( () => {
90
+ if ( ! blocks || ! blocks.length ) {
91
  return;
92
  }
93
 
104
  };
105
  }, [ blocks ] );
106
 
107
+ if ( isEmpty( blocks ) || ! isArray( blocks ) ) {
108
  return (
109
  <div className={ previewElClasses }>
110
  <div className="template-selector-preview__placeholder">
121
  <div ref={ ref } className="edit-post-visual-editor">
122
  <div className="editor-styles-wrapper" style={ { visibility } }>
123
  <div className="editor-writing-flow">
124
+ <PreviewTemplateTitle title={ title } />
125
+ <div className="template-selector-preview__offset-correction">
126
+ <BlockPreview key={ recompute } blocks={ blocks } viewportWidth={ viewportWidth } />
127
+ </div>
128
  </div>
129
  </div>
130
  </div>
starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-control-test.js.snap ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TemplateSelectorControl Basic rendering renders with required props 1`] = `
4
+ <div>
5
+ <div
6
+ class="components-base-control template-selector-control"
7
+ >
8
+ <div
9
+ class="components-base-control__field"
10
+ >
11
+ <label
12
+ class="components-base-control__label"
13
+ for="template-selector-control-17"
14
+ >
15
+ Select a Template...
16
+ </label>
17
+ <ul
18
+ class="template-selector-control__options"
19
+ data-testid="template-selector-control-options"
20
+ >
21
+ <li
22
+ class="template-selector-control__template"
23
+ >
24
+ <button
25
+ aria-labelledby="template-selector-control-17 label-template-selector-control-17-blank"
26
+ class="template-selector-item__label"
27
+ type="button"
28
+ value="blank"
29
+ >
30
+ <div
31
+ class="template-selector-item__preview-wrap"
32
+ >
33
+ <img
34
+ alt=""
35
+ class="template-selector-item__media"
36
+ />
37
+ </div>
38
+ <span
39
+ id="label-template-selector-control-17-blank"
40
+ >
41
+ Blank
42
+ </span>
43
+ </button>
44
+ </li>
45
+ <li
46
+ class="template-selector-control__template"
47
+ >
48
+ <button
49
+ aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-1"
50
+ class="template-selector-item__label"
51
+ type="button"
52
+ value="template-1"
53
+ >
54
+ <div
55
+ class="template-selector-item__preview-wrap"
56
+ >
57
+ <img
58
+ alt="Testing alt"
59
+ class="template-selector-item__media"
60
+ src="https://via.placeholder.com/350x150"
61
+ />
62
+ </div>
63
+ <span
64
+ id="label-template-selector-control-17-template-1"
65
+ >
66
+ Template 1
67
+ </span>
68
+ </button>
69
+ </li>
70
+ <li
71
+ class="template-selector-control__template"
72
+ >
73
+ <button
74
+ aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-2"
75
+ class="template-selector-item__label"
76
+ type="button"
77
+ value="template-2"
78
+ >
79
+ <div
80
+ class="template-selector-item__preview-wrap"
81
+ >
82
+ <img
83
+ alt="Testing alt 2"
84
+ class="template-selector-item__media"
85
+ src="https://via.placeholder.com/300x250"
86
+ />
87
+ </div>
88
+ <span
89
+ id="label-template-selector-control-17-template-2"
90
+ >
91
+ Template 2
92
+ </span>
93
+ </button>
94
+ </li>
95
+ <li
96
+ class="template-selector-control__template"
97
+ >
98
+ <button
99
+ aria-labelledby="template-selector-control-17 label-template-selector-control-17-template-3"
100
+ class="template-selector-item__label"
101
+ type="button"
102
+ value="template-3"
103
+ >
104
+ <div
105
+ class="template-selector-item__preview-wrap"
106
+ >
107
+ <img
108
+ alt="Testing alt 3"
109
+ class="template-selector-item__media"
110
+ src="https://via.placeholder.com/500x200"
111
+ />
112
+ </div>
113
+ <span
114
+ id="label-template-selector-control-17-template-3"
115
+ >
116
+ Template 3
117
+ </span>
118
+ </button>
119
+ </li>
120
+ </ul>
121
+ </div>
122
+ </div>
123
+ </div>
124
+ `;
starter-page-templates/page-template-modal/components/test/__snapshots__/template-selector-preview-test.js.snap ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`TemplateSelectorPreview Basic rendering renders the preview when blocks are provided 1`] = `
4
+ <div>
5
+ <div
6
+ class="template-selector-preview editor-styles-wrapper"
7
+ >
8
+ <div
9
+ class="components-disabled"
10
+ >
11
+ <div
12
+ class="edit-post-visual-editor"
13
+ >
14
+ <div
15
+ class="editor-styles-wrapper"
16
+ style="visibility: hidden;"
17
+ >
18
+ <div
19
+ class="editor-writing-flow"
20
+ >
21
+ <div
22
+ class="editor-post-title"
23
+ style="transform: none;"
24
+ >
25
+ <div
26
+ class="editor-post-title__block"
27
+ >
28
+ <textarea
29
+ class="editor-post-title__input"
30
+ />
31
+ </div>
32
+ </div>
33
+ <div
34
+ data-testid="block-template-preview"
35
+ >
36
+ MockedBlockPreview
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ </div>
44
+ `;
starter-page-templates/page-template-modal/components/test/helpers/templates-blocks-helpers.js ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * External dependencies
3
+ */
4
+ /* eslint-disable import/no-extraneous-dependencies */
5
+ import { uniqueId, range, toArray } from 'lodash';
6
+ /* eslint-enable import/no-extraneous-dependencies */
7
+
8
+ export const templatesFixture = [
9
+ {
10
+ slug: 'blank',
11
+ title: 'Blank',
12
+ },
13
+ {
14
+ slug: 'template-1',
15
+ title: 'Template 1',
16
+ preview: 'https://via.placeholder.com/350x150',
17
+ previewAlt: 'Testing alt',
18
+ },
19
+ {
20
+ slug: 'template-2',
21
+ title: 'Template 2',
22
+ preview: 'https://via.placeholder.com/300x250',
23
+ previewAlt: 'Testing alt 2',
24
+ },
25
+ {
26
+ slug: 'template-3',
27
+ title: 'Template 3',
28
+ preview: 'https://via.placeholder.com/500x200',
29
+ previewAlt: 'Testing alt 3',
30
+ },
31
+ ];
32
+
33
+ export const blocksByTemplatesFixture = templatesFixture.reduce( ( acc, curr ) => {
34
+ acc[ curr.slug ] = range( 4 ).map( () => {
35
+ return {
36
+ clientId: uniqueId(),
37
+ name: 'core/paragraph',
38
+ isValid: true,
39
+ attributes: {
40
+ align: 'left',
41
+ content:
42
+ 'Visitors will want to know who is on the other side of the page. Use this space to write about yourself, your site, your business, or anything you want. Use the testimonials below to quote others, talking about the same thing – in their own words.',
43
+ dropCap: false,
44
+ fontWeight: '',
45
+ textTransform: '',
46
+ noBottomSpacing: false,
47
+ noTopSpacing: false,
48
+ coblocks: [],
49
+ },
50
+ innerBlocks: [],
51
+ originalContent:
52
+ '<p style="text-align:left;">Visitors will want to know who is on the other side of the page. Use this space to write about yourself, your site, your business, or anything you want. Use the testimonials below to quote others, talking about the same thing – in their own words.</p>',
53
+ };
54
+ } );
55
+ return acc;
56
+ }, {} );
57
+
58
+ export const blocksFixture = toArray( blocksByTemplatesFixture );
starter-page-templates/page-template-modal/components/test/template-selector-control-test.js ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * External dependencies
3
+ */
4
+ /* eslint-disable import/no-extraneous-dependencies */
5
+ import { uniqueId, omit } from 'lodash';
6
+ /* eslint-enable import/no-extraneous-dependencies */
7
+
8
+ import { render, fireEvent } from '@testing-library/react';
9
+
10
+ import { templatesFixture, blocksByTemplatesFixture } from './helpers/templates-blocks-helpers';
11
+ import { TemplateSelectorControl } from '../template-selector-control';
12
+
13
+ // Mock out this component until @wordpress/block-editor
14
+ // `BlockPreview` component is available as default export.
15
+ // Once available, swap this mock to mocking out `BlockPreview`
16
+ // directly as it causes too many knock on effects when rendering
17
+ jest.mock( '../block-template-preview', () => () => {
18
+ return <div data-testid="block-template-preview">MockedBlockPreview</div>;
19
+ } );
20
+
21
+ // Required to handle `BlockPreview` usage of Mutation Observer
22
+ beforeAll(
23
+ ( global.MutationObserver = jest.fn( () => {
24
+ return {
25
+ observe: jest.fn(),
26
+ disconnect: jest.fn(),
27
+ };
28
+ } ) )
29
+ );
30
+
31
+ afterAll( () => {
32
+ global.MutationObserver.mockRestore();
33
+ } );
34
+
35
+ const testUniqueId = uniqueId();
36
+
37
+ describe( 'TemplateSelectorControl', () => {
38
+ const siteInformation = {
39
+ title: 'gutenberg-training',
40
+ vertical: 'Business',
41
+ };
42
+
43
+ describe( 'Basic rendering', () => {
44
+ it( 'renders with required props', () => {
45
+ const { getByText, container } = render(
46
+ <TemplateSelectorControl
47
+ label="Select a Template..."
48
+ instanceId={ testUniqueId }
49
+ templates={ templatesFixture }
50
+ blocksByTemplates={ blocksByTemplatesFixture }
51
+ siteInformation={ siteInformation }
52
+ />
53
+ );
54
+
55
+ expect( getByText( 'Select a Template...' ) ).toBeInTheDocument();
56
+ expect( getByText( 'Blank' ) ).toBeInTheDocument();
57
+ expect( document.querySelectorAll( 'button.template-selector-item__label' ) ).toHaveLength(
58
+ 4
59
+ );
60
+ expect( document.querySelectorAll( 'button.is-selected' ) ).toHaveLength( 0 );
61
+ expect( container ).toMatchSnapshot();
62
+ } );
63
+
64
+ it( 'highlights the selected template', () => {
65
+ render(
66
+ <TemplateSelectorControl
67
+ label="Select a Template..."
68
+ instanceId={ testUniqueId }
69
+ templates={ templatesFixture }
70
+ blocksByTemplates={ blocksByTemplatesFixture }
71
+ siteInformation={ siteInformation }
72
+ selectedTemplate={ templatesFixture[ 0 ].slug }
73
+ />
74
+ );
75
+
76
+ expect( document.querySelectorAll( 'button.is-selected' ) ).toHaveLength( 1 );
77
+ } );
78
+
79
+ it( 'does not render when missing templates prop', () => {
80
+ const { queryByText, queryByTestId } = render(
81
+ <TemplateSelectorControl
82
+ label="Select a Template..."
83
+ instanceId={ testUniqueId }
84
+ blocksByTemplates={ blocksByTemplatesFixture }
85
+ />
86
+ );
87
+
88
+ // use `queryBy` to avoid throwing an error with `getBy`
89
+ expect( queryByText( 'Select a Template...' ) ).not.toBeInTheDocument();
90
+ expect( queryByTestId( 'template-selector-control-options' ) ).not.toBeInTheDocument();
91
+ } );
92
+
93
+ it( 'does not render when templates prop is not an Array', () => {
94
+ const { queryByText, queryByTestId } = render(
95
+ <TemplateSelectorControl
96
+ label="Select a Template..."
97
+ instanceId={ testUniqueId }
98
+ templates={ 'evil stuff here' }
99
+ blocksByTemplates={ blocksByTemplatesFixture }
100
+ />
101
+ );
102
+
103
+ expect( queryByText( 'Select a Template...' ) ).not.toBeInTheDocument();
104
+ expect( queryByTestId( 'template-selector-control-options' ) ).not.toBeInTheDocument();
105
+ } );
106
+ } );
107
+
108
+ describe( 'Event handlers', () => {
109
+ it( 'calls onTemplateSelect prop when template is clicked', () => {
110
+ const onSelectSpy = jest.fn();
111
+
112
+ const { getByText } = render(
113
+ <TemplateSelectorControl
114
+ label="Select a Template..."
115
+ instanceId={ testUniqueId }
116
+ templates={ templatesFixture }
117
+ blocksByTemplates={ blocksByTemplatesFixture }
118
+ siteInformation={ siteInformation }
119
+ onTemplateSelect={ onSelectSpy }
120
+ />
121
+ );
122
+
123
+ fireEvent.click( getByText( 'Template 3' ) );
124
+
125
+ expect( onSelectSpy ).toHaveBeenCalled();
126
+ } );
127
+ } );
128
+
129
+ describe( 'Static previews', () => {
130
+ it( 'renders in static preview mode by default ', () => {
131
+ const { getByAltText } = render(
132
+ <TemplateSelectorControl
133
+ label="Select a Template..."
134
+ instanceId={ testUniqueId }
135
+ templates={ templatesFixture }
136
+ blocksByTemplates={ blocksByTemplatesFixture }
137
+ siteInformation={ siteInformation }
138
+ />
139
+ );
140
+
141
+ expect( getByAltText( 'Testing alt 2' ) ).toBeInTheDocument();
142
+ expect( document.querySelectorAll( 'img.template-selector-item__media' ) ).toHaveLength( 4 );
143
+ } );
144
+
145
+ it( 'renders in "blank" mode when static preview is not provided ', () => {
146
+ const templatesFixtureWithoutPreviews = templatesFixture.map( template =>
147
+ omit( template, 'preview' )
148
+ );
149
+
150
+ const { getByText } = render(
151
+ <TemplateSelectorControl
152
+ label="Select a Template..."
153
+ instanceId={ testUniqueId }
154
+ templates={ templatesFixtureWithoutPreviews }
155
+ blocksByTemplates={ blocksByTemplatesFixture }
156
+ siteInformation={ siteInformation }
157
+ />
158
+ );
159
+
160
+ expect( getByText( 'Select a Template...' ) ).toBeInTheDocument();
161
+ expect( getByText( 'Blank' ) ).toBeInTheDocument();
162
+ } );
163
+ } );
164
+
165
+ describe( 'Dynamic previews', () => {
166
+ it( 'renders in dynamic preview mode when useDynamicPreview is true', () => {
167
+ const { queryByAltText, getAllByTestId } = render(
168
+ <TemplateSelectorControl
169
+ label="Select a Template..."
170
+ instanceId={ testUniqueId }
171
+ templates={ templatesFixture }
172
+ blocksByTemplates={ blocksByTemplatesFixture }
173
+ siteInformation={ siteInformation }
174
+ useDynamicPreview={ true }
175
+ />
176
+ );
177
+
178
+ const mockedBlockTemplatePreviews = getAllByTestId( 'block-template-preview' );
179
+
180
+ expect( mockedBlockTemplatePreviews ).toHaveLength( 4 );
181
+ expect( queryByAltText( 'Testing alt 2' ) ).not.toBeInTheDocument();
182
+ expect( document.querySelectorAll( 'img.template-selector-item__media' ) ).toHaveLength( 0 );
183
+ } );
184
+
185
+ it( 'does not render without blocksByTemplatesFixture prop when in dynamic mode', () => {
186
+ const { queryByLabelText, queryByTestId } = render(
187
+ <TemplateSelectorControl
188
+ label="Select a Template..."
189
+ instanceId={ testUniqueId }
190
+ templates={ templatesFixture }
191
+ siteInformation={ siteInformation }
192
+ useDynamicPreview={ true }
193
+ />
194
+ );
195
+
196
+ expect( queryByLabelText( 'Select a Template...' ) ).not.toBeInTheDocument();
197
+ expect( queryByTestId( 'template-selector-control-options' ) ).not.toBeInTheDocument();
198
+ } );
199
+ } );
200
+ } );
starter-page-templates/page-template-modal/components/test/template-selector-preview-test.js ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import { render } from '@testing-library/react';
5
+ import { blocksFixture } from './helpers/templates-blocks-helpers';
6
+ import TemplateSelectorPreview from '../template-selector-preview';
7
+
8
+ // Mock the "pass through" version of the `BlockPreview` component
9
+ // See `components/block-preview.js`
10
+ jest.mock( '../block-preview', () => () => {
11
+ return <div data-testid="block-template-preview">MockedBlockPreview</div>;
12
+ } );
13
+
14
+ // Required to handle `BlockPreview` usage of Mutation Observer
15
+ beforeAll(
16
+ ( global.MutationObserver = jest.fn( () => {
17
+ return {
18
+ observe: jest.fn(),
19
+ disconnect: jest.fn(),
20
+ };
21
+ } ) )
22
+ );
23
+
24
+ afterAll( () => {
25
+ global.MutationObserver.mockRestore();
26
+ } );
27
+
28
+ describe( 'TemplateSelectorPreview', () => {
29
+ describe( 'Basic rendering', () => {
30
+ it( 'renders the preview when blocks are provided', () => {
31
+ const { queryByTestId, container } = render(
32
+ <TemplateSelectorPreview blocks={ blocksFixture } viewportWidth={ 960 } />
33
+ );
34
+
35
+ expect( queryByTestId( 'block-template-preview' ) ).toBeInTheDocument();
36
+ expect( container ).toMatchSnapshot();
37
+ } );
38
+
39
+ it( 'renders placeholder when no blocks are provided', () => {
40
+ const { getByText, queryByTestId } = render(
41
+ <TemplateSelectorPreview viewportWidth={ 960 } />
42
+ );
43
+
44
+ expect( getByText( 'Select a page template to preview.' ) ).toBeInTheDocument();
45
+ expect( queryByTestId( 'block-template-preview' ) ).not.toBeInTheDocument();
46
+ } );
47
+
48
+ it( 'renders placeholder when blocks is not an array', () => {
49
+ const invalidBlocksProp = {
50
+ 'some-block-1': {
51
+ block: 'foo',
52
+ },
53
+ 'some-block-2': {
54
+ block: 'bar',
55
+ },
56
+ };
57
+ const { getByText, queryByTestId } = render(
58
+ <TemplateSelectorPreview blocks={ invalidBlocksProp } viewportWidth={ 960 } />
59
+ );
60
+
61
+ expect( getByText( 'Select a page template to preview.' ) ).toBeInTheDocument();
62
+ expect( queryByTestId( 'block-template-preview' ) ).not.toBeInTheDocument();
63
+ } );
64
+ } );
65
+ } );
starter-page-templates/page-template-modal/index.js CHANGED
@@ -1,93 +1,234 @@
 
1
  /**
2
  * External dependencies
3
  */
4
- import { has, isEmpty, keyBy, map } from 'lodash';
5
- import { __ } from '@wordpress/i18n';
 
 
6
  import { compose } from '@wordpress/compose';
7
- import { Modal } from '@wordpress/components';
8
  import { registerPlugin } from '@wordpress/plugins';
9
  import { withDispatch, withSelect } from '@wordpress/data';
10
- import { parse as parseBlocks } from '@wordpress/blocks';
11
  import { Component } from '@wordpress/element';
12
- import '@wordpress/nux';
13
 
14
  /**
15
  * Internal dependencies
16
  */
17
- import replacePlaceholders from './utils/replace-placeholders';
18
  import './styles/starter-page-templates-editor.scss';
19
  import TemplateSelectorControl from './components/template-selector-control';
 
20
  import { trackDismiss, trackSelection, trackView, initializeWithIdentity } from './utils/tracking';
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  class PageTemplateModal extends Component {
23
  state = {
24
  isLoading: false,
 
 
 
 
 
25
  };
26
 
27
  constructor( props ) {
28
  super();
29
- this.state.isOpen = ! isEmpty( props.templates );
 
 
 
 
 
 
 
30
  }
31
 
32
  componentDidMount() {
33
  if ( this.state.isOpen ) {
34
  trackView( this.props.segment.id, this.props.vertical.id );
35
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  }
37
 
38
- selectTemplate = newTemplate => {
39
- this.setState( { isOpen: false } );
40
- trackSelection( this.props.segment.id, this.props.vertical.id, newTemplate );
 
41
 
42
- const template = this.props.templates[ newTemplate ];
43
- this.props.saveTemplateChoice( template );
 
44
 
45
  // Skip inserting if there's nothing to insert.
46
- if ( ! has( template, 'content' ) ) {
 
47
  return;
48
  }
49
 
50
- const processedTemplate = {
51
- ...template,
52
- title: replacePlaceholders( template.title, this.props.siteInformation ),
53
- content: replacePlaceholders( template.content, this.props.siteInformation ),
54
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- this.props.insertTemplate( processedTemplate );
 
57
  };
58
 
59
- closeModal = () => {
60
- this.setState( { isOpen: false } );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  trackDismiss( this.props.segment.id, this.props.vertical.id );
 
 
 
 
62
  };
63
 
 
 
 
 
 
 
 
 
64
  render() {
65
- if ( ! this.state.isOpen ) {
 
 
 
 
 
66
  return null;
67
  }
68
 
69
  return (
70
  <Modal
71
  title={ __( 'Select Page Template', 'full-site-editing' ) }
72
- onRequestClose={ this.closeModal }
73
  className="page-template-modal"
74
  overlayClassName="page-template-modal-screen-overlay"
 
 
 
 
75
  >
 
 
 
 
 
 
 
76
  <div className="page-template-modal__inner">
77
- <form className="page-template-modal__form">
78
- <fieldset className="page-template-modal__list">
79
- <TemplateSelectorControl
80
- label={ __( 'Template', 'full-site-editing' ) }
81
- templates={ map( this.props.templates, template => ( {
82
- label: template.title,
83
- value: template.slug,
84
- preview: template.preview,
85
- previewAlt: template.description,
86
- } ) ) }
87
- onClick={ newTemplate => this.selectTemplate( newTemplate ) }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
  />
89
- </fieldset>
90
- </form>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  </div>
92
  </Modal>
93
  );
@@ -107,26 +248,23 @@ const PageTemplatesPlugin = compose(
107
 
108
  const editorDispatcher = dispatch( 'core/editor' );
109
  return {
110
- saveTemplateChoice: template => {
111
  // Save selected template slug in meta.
112
  const currentMeta = ownProps.getMeta();
113
  editorDispatcher.editPost( {
114
  meta: {
115
  ...currentMeta,
116
- _starter_page_template: template.slug,
117
  },
118
  } );
119
  },
120
- insertTemplate: template => {
121
  // Set post title.
122
- editorDispatcher.editPost( {
123
- title: template.title,
124
- } );
125
 
126
  // Insert blocks.
127
  const postContentBlock = ownProps.postContentBlock;
128
- const blocks = parseBlocks( template.content );
129
- editorDispatcher.insertBlocks(
130
  blocks,
131
  0,
132
  postContentBlock ? postContentBlock.clientId : '',
@@ -137,27 +275,18 @@ const PageTemplatesPlugin = compose(
137
  } )
138
  )( PageTemplateModal );
139
 
140
- // Load config passed from backend.
141
- const {
142
- siteInformation = {},
143
- templates = [],
144
- vertical,
145
- segment,
146
- tracksUserData,
147
- } = window.starterPageTemplatesConfig;
148
-
149
  if ( tracksUserData ) {
150
  initializeWithIdentity( tracksUserData );
151
  }
152
 
153
  registerPlugin( 'page-templates', {
154
- render: function() {
155
  return (
156
  <PageTemplatesPlugin
157
- templates={ keyBy( templates, 'slug' ) }
 
158
  vertical={ vertical }
159
  segment={ segment }
160
- siteInformation={ siteInformation }
161
  />
162
  );
163
  },
1
+ /* eslint-disable import/no-extraneous-dependencies */
2
  /**
3
  * External dependencies
4
  */
5
+ import { isEmpty, reduce, get, keyBy, mapValues } from 'lodash';
6
+ import classnames from 'classnames';
7
+ import '@wordpress/nux';
8
+ import { __, sprintf } from '@wordpress/i18n';
9
  import { compose } from '@wordpress/compose';
10
+ import { Button, Modal, Spinner, IconButton } from '@wordpress/components';
11
  import { registerPlugin } from '@wordpress/plugins';
12
  import { withDispatch, withSelect } from '@wordpress/data';
 
13
  import { Component } from '@wordpress/element';
14
+ import { parse as parseBlocks } from '@wordpress/blocks';
15
 
16
  /**
17
  * Internal dependencies
18
  */
 
19
  import './styles/starter-page-templates-editor.scss';
20
  import TemplateSelectorControl from './components/template-selector-control';
21
+ import TemplateSelectorPreview from './components/template-selector-preview';
22
  import { trackDismiss, trackSelection, trackView, initializeWithIdentity } from './utils/tracking';
23
+ import replacePlaceholders from './utils/replace-placeholders';
24
+ import ensureAssets from './utils/ensure-assets';
25
+ /* eslint-enable import/no-extraneous-dependencies */
26
+
27
+ // Load config passed from backend.
28
+ const {
29
+ templates = [],
30
+ vertical,
31
+ segment,
32
+ tracksUserData,
33
+ siteInformation = {},
34
+ } = window.starterPageTemplatesConfig;
35
 
36
  class PageTemplateModal extends Component {
37
  state = {
38
  isLoading: false,
39
+ previewedTemplate: null,
40
+ blocksByTemplateSlug: {},
41
+ titlesByTemplateSlug: {},
42
+ error: null,
43
+ isOpen: false,
44
  };
45
 
46
  constructor( props ) {
47
  super();
48
+ const hasTemplates = ! isEmpty( props.templates );
49
+ this.state.isOpen = hasTemplates;
50
+ if ( hasTemplates ) {
51
+ // Select the first template automatically.
52
+ this.state.previewedTemplate = get( props.templates, [ 0, 'slug' ] );
53
+ // Extract titles for faster lookup.
54
+ this.state.titlesByTemplateSlug = mapValues( keyBy( props.templates, 'slug' ), 'title' );
55
+ }
56
  }
57
 
58
  componentDidMount() {
59
  if ( this.state.isOpen ) {
60
  trackView( this.props.segment.id, this.props.vertical.id );
61
  }
62
+
63
+ // Parse templates blocks and store them into the state.
64
+ const blocksByTemplateSlug = reduce(
65
+ templates,
66
+ ( prev, { slug, content } ) => {
67
+ prev[ slug ] = content
68
+ ? parseBlocks( replacePlaceholders( content, siteInformation ) )
69
+ : [];
70
+ return prev;
71
+ },
72
+ {}
73
+ );
74
+
75
+ // eslint-disable-next-line react/no-did-mount-set-state
76
+ this.setState( { blocksByTemplateSlug } );
77
  }
78
 
79
+ setTemplate = slug => {
80
+ // Track selection and mark post as using a template in its postmeta.
81
+ trackSelection( this.props.segment.id, this.props.vertical.id, slug );
82
+ this.props.saveTemplateChoice( slug );
83
 
84
+ // Load content.
85
+ const blocks = this.getBlocksByTemplateSlug( slug );
86
+ const title = this.getTitleByTemplateSlug( slug );
87
 
88
  // Skip inserting if there's nothing to insert.
89
+ if ( ! blocks || ! blocks.length ) {
90
+ this.setState( { isOpen: false } );
91
  return;
92
  }
93
 
94
+ // Show loading state.
95
+ this.setState( {
96
+ error: null,
97
+ isLoading: true,
98
+ } );
99
+
100
+ // Make sure all blocks use local assets before inserting.
101
+ this.maybePrefetchAssets( blocks )
102
+ .then( blocksWithAssets => {
103
+ // Don't insert anything if the user clicked Cancel/Close
104
+ // before we loaded everything.
105
+ if ( ! this.state.isOpen ) {
106
+ return;
107
+ }
108
+
109
+ this.props.insertTemplate( title, blocksWithAssets );
110
+ this.setState( { isOpen: false } );
111
+ } )
112
+ .catch( error => {
113
+ this.setState( {
114
+ isLoading: false,
115
+ error,
116
+ } );
117
+ } );
118
+ };
119
 
120
+ maybePrefetchAssets = blocks => {
121
+ return this.props.shouldPrefetchAssets ? ensureAssets( blocks ) : Promise.resolve( blocks );
122
  };
123
 
124
+ handleConfirmation = slug => {
125
+ if ( typeof slug !== 'string' ) {
126
+ slug = this.state.previewedTemplate;
127
+ }
128
+
129
+ this.setTemplate( slug );
130
+ };
131
+
132
+ previewTemplate = slug => this.setState( { previewedTemplate: slug } );
133
+
134
+ closeModal = event => {
135
+ // Check to see if the Blur event occurred on the buttons inside of the Modal.
136
+ // If it did then we don't want to dismiss the Modal for this type of Blur.
137
+ if ( event.target.matches( 'button.template-selector-item__label' ) ) {
138
+ return false;
139
+ }
140
+
141
  trackDismiss( this.props.segment.id, this.props.vertical.id );
142
+
143
+ // Try if we have specific URL to go back to, otherwise go to the page list.
144
+ const calypsoifyCloseUrl = get( window, [ 'calypsoifyGutenberg', 'closeUrl' ] );
145
+ window.top.location = calypsoifyCloseUrl || 'edit.php?post_type=page';
146
  };
147
 
148
+ getBlocksByTemplateSlug( slug ) {
149
+ return get( this.state.blocksByTemplateSlug, [ slug ], [] );
150
+ }
151
+
152
+ getTitleByTemplateSlug( slug ) {
153
+ return get( this.state.titlesByTemplateSlug, [ slug ], '' );
154
+ }
155
+
156
  render() {
157
+ /* eslint-disable no-shadow */
158
+ const { previewedTemplate, isOpen, isLoading, blocksByTemplateSlug } = this.state;
159
+ const { templates } = this.props;
160
+ /* eslint-enable no-shadow */
161
+
162
+ if ( ! isOpen ) {
163
  return null;
164
  }
165
 
166
  return (
167
  <Modal
168
  title={ __( 'Select Page Template', 'full-site-editing' ) }
 
169
  className="page-template-modal"
170
  overlayClassName="page-template-modal-screen-overlay"
171
+ shouldCloseOnClickOutside={ false }
172
+ // Using both variants here to be compatible with new Gutenberg and old (older than 6.6).
173
+ isDismissable={ false }
174
+ isDismissible={ false }
175
  >
176
+ <IconButton
177
+ className="page-template-modal__close-button components-icon-button"
178
+ onClick={ this.closeModal }
179
+ icon="arrow-left-alt2"
180
+ label={ __( 'Go back' ) }
181
+ />
182
+
183
  <div className="page-template-modal__inner">
184
+ { isLoading ? (
185
+ <div className="page-template-modal__loading">
186
+ <Spinner />
187
+ { __( 'Inserting template…', 'full-site-editing' ) }
188
+ </div>
189
+ ) : (
190
+ <>
191
+ <form className="page-template-modal__form">
192
+ <fieldset className="page-template-modal__list">
193
+ <legend className="page-template-modal__form-title">
194
+ { __( 'Choose a template…', 'full-site-editing' ) }
195
+ </legend>
196
+ <TemplateSelectorControl
197
+ label={ __( 'Template', 'full-site-editing' ) }
198
+ templates={ templates }
199
+ blocksByTemplates={ blocksByTemplateSlug }
200
+ onTemplateSelect={ this.previewTemplate }
201
+ useDynamicPreview={ false }
202
+ siteInformation={ siteInformation }
203
+ selectedTemplate={ previewedTemplate }
204
+ handleTemplateConfirmation={ this.handleConfirmation }
205
+ />
206
+ </fieldset>
207
+ </form>
208
+ <TemplateSelectorPreview
209
+ blocks={ this.getBlocksByTemplateSlug( previewedTemplate ) }
210
+ viewportWidth={ 960 }
211
+ title={ this.getTitleByTemplateSlug( previewedTemplate ) }
212
  />
213
+ </>
214
+ ) }
215
+ </div>
216
+ <div
217
+ className={ classnames( 'page-template-modal__buttons', {
218
+ 'is-visually-hidden': isEmpty( previewedTemplate ) || isLoading,
219
+ } ) }
220
+ >
221
+ <Button
222
+ isPrimary
223
+ isLarge
224
+ disabled={ isEmpty( previewedTemplate ) || isLoading }
225
+ onClick={ this.handleConfirmation }
226
+ >
227
+ { sprintf(
228
+ __( 'Use %s template', 'full-site-editing' ),
229
+ this.getTitleByTemplateSlug( previewedTemplate )
230
+ ) }
231
+ </Button>
232
  </div>
233
  </Modal>
234
  );
248
 
249
  const editorDispatcher = dispatch( 'core/editor' );
250
  return {
251
+ saveTemplateChoice: slug => {
252
  // Save selected template slug in meta.
253
  const currentMeta = ownProps.getMeta();
254
  editorDispatcher.editPost( {
255
  meta: {
256
  ...currentMeta,
257
+ _starter_page_template: slug,
258
  },
259
  } );
260
  },
261
+ insertTemplate: ( title, blocks ) => {
262
  // Set post title.
263
+ editorDispatcher.editPost( { title } );
 
 
264
 
265
  // Insert blocks.
266
  const postContentBlock = ownProps.postContentBlock;
267
+ dispatch( 'core/block-editor' ).insertBlocks(
 
268
  blocks,
269
  0,
270
  postContentBlock ? postContentBlock.clientId : '',
275
  } )
276
  )( PageTemplateModal );
277
 
 
 
 
 
 
 
 
 
 
278
  if ( tracksUserData ) {
279
  initializeWithIdentity( tracksUserData );
280
  }
281
 
282
  registerPlugin( 'page-templates', {
283
+ render: () => {
284
  return (
285
  <PageTemplatesPlugin
286
+ shouldPrefetchAssets={ false }
287
+ templates={ templates }
288
  vertical={ vertical }
289
  segment={ segment }
 
290
  />
291
  );
292
  },
starter-page-templates/page-template-modal/styles/starter-page-templates-editor.scss CHANGED
@@ -11,19 +11,33 @@
11
  word-wrap: normal !important;
12
  }
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  // Modal Overlay
15
  .page-template-modal-screen-overlay {
16
  animation: none;
 
17
  }
18
 
19
  // When not in fullscreen mode allow space for WP.org sidebar
20
  body:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
21
  @media screen and ( min-width: 783px ) {
22
- left: 36px;
23
  }
24
 
25
  @media screen and ( min-width: 961px ) {
26
- left: 160px;
27
  }
28
  }
29
 
@@ -40,12 +54,50 @@ body.admin-bar:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
40
  .page-template-modal {
41
  width: 100%;
42
  height: 100vh;
43
- max-width: 800px;
44
  animation: none;
 
 
 
 
 
 
 
 
 
 
45
  }
46
 
47
  .page-template-modal .components-modal__header-heading-container {
48
- justify-content: center;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
 
51
  .page-template-modal .components-modal__content {
@@ -54,12 +106,20 @@ body.admin-bar:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
54
  }
55
 
56
  .page-template-modal__inner {
57
- max-width: 720px;
58
  margin: 0 auto;
59
  padding: 0;
60
 
61
  @media screen and ( max-width: 659px ) {
62
- padding-bottom: 3em;
 
 
 
 
 
 
 
 
63
  }
64
  }
65
 
@@ -71,14 +131,24 @@ body.admin-bar:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
71
  .template-selector-control__options {
72
  display: grid;
73
  // stylelint-disable-next-line unit-whitelist
74
- grid-template-columns: 1fr 1fr; // force 2 col on small screens to ensure blank isn't the only option visible on load
75
  grid-gap: 1.75em;
76
 
77
  @media screen and ( min-width: 660px ) {
 
 
 
 
 
 
 
 
 
 
78
  // stylelint-disable unit-whitelist
79
  grid-template-columns: repeat(
80
  auto-fit,
81
- minmax( 200px, 1fr )
82
  ); // allow grid to take over number of cols on large screens
83
  // stylelint-enable unit-whitelist
84
  }
@@ -88,49 +158,112 @@ body.admin-bar:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
88
  margin-bottom: 4px;
89
  }
90
 
91
- .template-selector-control__label {
92
  display: block;
93
  width: 100%;
94
  font-size: 14px;
95
  text-align: center;
96
- border: 1px solid #a1aab2;
97
  border-radius: 6px;
98
  cursor: pointer;
99
- background: none;
100
  appearance: none;
101
- padding: 0 0 14px;
102
  overflow: hidden;
 
 
 
 
 
 
 
 
 
 
 
 
103
 
104
- &:hover,
105
  &:focus {
106
- border-color: #2562b7;
107
- box-shadow: 0 0 0 1px #2562b7;
108
- outline: 1px solid transparent;
109
- outline-offset: -1px;
110
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
 
113
- .template-selector-control__media-wrap {
114
  width: 100%;
115
  display: block;
116
- margin: 0 auto 14px;
117
- border-bottom: 1px solid #a1aab2;
118
- background: #f6f6f6;
119
  border-radius: 0;
120
  overflow: hidden;
121
- padding-bottom: 110%;
 
122
  box-sizing: content-box;
123
  position: relative;
124
  pointer-events: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
 
127
- .template-selector-control__media {
128
  width: 100%;
129
  display: block;
130
  position: absolute;
131
  top: 0;
132
  left: 0;
133
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  }
135
 
136
  .page-template-modal__actions {
@@ -155,3 +288,190 @@ body.admin-bar:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
155
  margin-right: 1em;
156
  }
157
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  word-wrap: normal !important;
12
  }
13
 
14
+ $template-selector-border-color: #e2e4e7;
15
+ $template-selector-border-color-selected: #555d66;
16
+ $template-selector-border-color-active: #00a0d2;
17
+ $template-selector-border-color-hover: #c9c9ca;
18
+ $template-selector-empty-background: #fff;
19
+ $template-selector-modal-offset-bottom: 25px;
20
+ $template-selector-modal-offset-right: 32px;
21
+ $template-selector-blank-template-mobile-height: 70px;
22
+ $template-large-preview-title-height: 120px;
23
+
24
+ $wp-org-sidebar-reduced: 36px;
25
+ $wp-org-sidebar-full: 160px;
26
+
27
  // Modal Overlay
28
  .page-template-modal-screen-overlay {
29
  animation: none;
30
+ background-color: transparent; // hide the overlay visually
31
  }
32
 
33
  // When not in fullscreen mode allow space for WP.org sidebar
34
  body:not( .is-fullscreen-mode ) .page-template-modal-screen-overlay {
35
  @media screen and ( min-width: 783px ) {
36
+ left: $wp-org-sidebar-reduced;
37
  }
38
 
39
  @media screen and ( min-width: 961px ) {
40
+ left: $wp-org-sidebar-full;
41
  }
42
  }
43
 
54
  .page-template-modal {
55
  width: 100%;
56
  height: 100vh;
 
57
  animation: none;
58
+ box-shadow: none; // cancel "modal" appearance
59
+ border: none; // cancel "modal" appearance
60
+ top: 0; // overlay the Block Editor toolbar
61
+ left: 0;
62
+ right: 0;
63
+ bottom: 0;
64
+ transform: none;
65
+ max-width: none;
66
+ max-height: none;
67
+ background-color: #eeeeee;
68
  }
69
 
70
  .page-template-modal .components-modal__header-heading-container {
71
+ @include screen-reader-text();
72
+ }
73
+
74
+ // Show close button only in full screen mode.
75
+ .page-template-modal .components-modal__header::after,
76
+ .page-template-modal__close-button {
77
+ display: none;
78
+ }
79
+
80
+ body.is-fullscreen-mode {
81
+ .page-template-modal__close-button {
82
+ display: block;
83
+ position: absolute;
84
+ z-index: 20;
85
+ top: 9px;
86
+ width: 36px;
87
+ height: 36px;
88
+ left: 8px;
89
+ }
90
+
91
+ .page-template-modal .components-modal__header {
92
+ &::after {
93
+ display: block;
94
+ position: absolute;
95
+ content: ' ';
96
+ border-right: 1px solid #e2e4e7;
97
+ height: 100%;
98
+ left: 54px;
99
+ }
100
+ }
101
  }
102
 
103
  .page-template-modal .components-modal__content {
106
  }
107
 
108
  .page-template-modal__inner {
109
+ position: relative;
110
  margin: 0 auto;
111
  padding: 0;
112
 
113
  @media screen and ( max-width: 659px ) {
114
+ padding: 0 14% 3em;
115
+ }
116
+
117
+ @media screen and ( max-width: 440px ) {
118
+ padding: 0 15px 3em;
119
+ }
120
+
121
+ @media screen and ( min-width: 1200px ) {
122
+ max-width: 100%;
123
  }
124
  }
125
 
131
  .template-selector-control__options {
132
  display: grid;
133
  // stylelint-disable-next-line unit-whitelist
134
+ grid-template-columns: 1fr;
135
  grid-gap: 1.75em;
136
 
137
  @media screen and ( min-width: 660px ) {
138
+ margin-top: 0;
139
+ // stylelint-disable unit-whitelist
140
+ grid-template-columns: repeat(
141
+ auto-fit,
142
+ minmax( 110px, 1fr )
143
+ ); // allow grid to take over number of cols on large screens
144
+ // stylelint-enable unit-whitelist
145
+ }
146
+
147
+ @media screen and ( min-width: 1200px ) {
148
  // stylelint-disable unit-whitelist
149
  grid-template-columns: repeat(
150
  auto-fit,
151
+ minmax( 150px, 1fr )
152
  ); // allow grid to take over number of cols on large screens
153
  // stylelint-enable unit-whitelist
154
  }
158
  margin-bottom: 4px;
159
  }
160
 
161
+ .template-selector-item__label {
162
  display: block;
163
  width: 100%;
164
  font-size: 14px;
165
  text-align: center;
166
+ border: solid 2px $template-selector-border-color;
167
  border-radius: 6px;
168
  cursor: pointer;
 
169
  appearance: none;
170
+ padding: 0;
171
  overflow: hidden;
172
+ background-color: #fff;
173
+ position: relative;
174
+
175
+ .template-selector-item__template-title {
176
+ width: 100%;
177
+ position: absolute;
178
+ bottom: 0;
179
+ left: 0;
180
+ height: 40px;
181
+ line-height: 40px;
182
+ background-color: #fff;
183
+ }
184
 
 
185
  &:focus {
186
+ box-shadow: 0 0 0 1px #fff, 0 0 0 3px $template-selector-border-color-active;
187
+
188
+ // Windows High Contrast mode will show this outline, but not the box-shadow.
189
+ outline: 2px solid transparent;
190
  }
191
+
192
+ &:hover {
193
+ border: solid 2px $template-selector-border-color-hover;
194
+ }
195
+
196
+ &.is-selected {
197
+ border: solid 2px $template-selector-border-color-selected;
198
+
199
+ // Windows High Contrast mode will show this outline, but not the box-shadow.
200
+ outline: 2px solid transparent;
201
+ outline-offset: -2px;
202
+
203
+ &:focus {
204
+ box-shadow: 0 0 0 1px #fff, 0 0 0 3px $template-selector-border-color-active;
205
+ border: solid 2px $template-selector-border-color-selected;
206
+
207
+ // Windows High Contrast mode will show this outline, but not the box-shadow.
208
+ outline: 4px solid transparent;
209
+ outline-offset: -4px;
210
+ }
211
+ }
212
+
213
+
214
  }
215
 
216
+ .template-selector-item__preview-wrap {
217
  width: 100%;
218
  display: block;
219
+ margin: 0 auto;
220
+ background: $template-selector-empty-background;
 
221
  border-radius: 0;
222
  overflow: hidden;
223
+ height: 0;
224
+ padding-top: 100%; // Aspect radio boxes. It will take the 100% of width.
225
  box-sizing: content-box;
226
  position: relative;
227
  pointer-events: none;
228
+ opacity: 1;
229
+
230
+ @media screen and ( max-width: 659px ) {
231
+ padding-top: 120%;
232
+ }
233
+
234
+ &.is-rendering {
235
+ opacity: 0.5;
236
+ }
237
+
238
+ .block-editor-block-list__layout,
239
+ .block-editor-block-list__block {
240
+ padding: inherit;
241
+ }
242
  }
243
 
244
+ .template-selector-item__media {
245
  width: 100%;
246
  display: block;
247
  position: absolute;
248
  top: 0;
249
  left: 0;
250
  }
251
+
252
+ // Blank template
253
+ .template-selector-control__template:first-child {
254
+ .template-selector-item__preview-wrap {
255
+ @media screen and ( max-width: 659px ) {
256
+ padding-top: 0%;
257
+ height: $template-selector-blank-template-mobile-height;
258
+ }
259
+ }
260
+ .template-selector-item__template-title {
261
+ @media screen and ( max-width: 659px ) {
262
+ height: $template-selector-blank-template-mobile-height;
263
+ line-height: $template-selector-blank-template-mobile-height;
264
+ }
265
+ }
266
+ }
267
  }
268
 
269
  .page-template-modal__actions {
288
  margin-right: 1em;
289
  }
290
  }
291
+
292
+ .page-template-modal__form {
293
+ @media screen and ( min-width: 660px ) {
294
+ max-width: 50%;
295
+ }
296
+ }
297
+
298
+ .page-template-modal__form-title {
299
+ font-weight: bold;
300
+ margin-bottom: 1em;
301
+ @media screen and ( max-width: 659px ) {
302
+ text-align: center;
303
+ }
304
+ }
305
+
306
+ .page-template-modal__buttons {
307
+ position: absolute;
308
+ right: 0;
309
+ top: 0;
310
+ z-index: 10;
311
+ height: 56px;
312
+ display: flex;
313
+ align-items: center;
314
+ padding-right: 24px;
315
+
316
+ @media screen and ( max-width: 659px ) {
317
+ display: none;
318
+ }
319
+
320
+ &.is-visually-hidden {
321
+ @include screen-reader-text();
322
+ }
323
+
324
+ .components-button {
325
+ height: 33px; // match to Gutenberg toolbar styles
326
+ line-height: 32px; // match to Gutenberg toolbar styles
327
+ }
328
+ }
329
+
330
+ // Template Selector Preview
331
+ .template-selector-preview {
332
+ @media screen and ( max-width: 659px ) {
333
+ display: none;
334
+ }
335
+
336
+ position: fixed;
337
+ top: 111px;
338
+ bottom: 24px;
339
+ right: 24px;
340
+ width: calc( 50% - 50px );
341
+ background: $template-selector-empty-background;
342
+ border-radius: 2px;
343
+ overflow-x: hidden;
344
+ overflow-y: auto;
345
+ box-shadow: 0 2px 2px 0 rgba( 0, 0, 0, 0.14 ), 0 3px 1px -2px rgba( 0, 0, 0, 0.12 ), 0 1px 5px 0 rgba( 0, 0, 0, 0.2 );
346
+
347
+ .edit-post-visual-editor {
348
+ margin: 0;
349
+ padding: 0;
350
+ }
351
+
352
+ .editor-styles-wrapper {
353
+ .template-selector-preview__offset-correction {
354
+ position: relative;
355
+ top: $template-large-preview-title-height;
356
+ }
357
+
358
+ .editor-post-title {
359
+ transform-origin: top left;
360
+ width: 960px;
361
+ display: block;
362
+ position: absolute;
363
+ top: 0;
364
+ }
365
+
366
+ .editor-post-title,
367
+ .editor-post-title__block,
368
+ .editor-post-title__input {
369
+ padding-top: 0;
370
+ padding-bottom: 0;
371
+ margin-top: 0;
372
+ margin-bottom: 0;
373
+ .editor-post-title__input {
374
+ margin: 0;
375
+ padding: 0;
376
+ height: $template-large-preview-title-height;
377
+ line-height: $template-large-preview-title-height;
378
+ }
379
+ }
380
+ }
381
+ }
382
+
383
+ body:not( .is-fullscreen-mode ) .template-selector-preview {
384
+ @media screen and ( min-width: 783px ) {
385
+ width: calc( 50% - #{$wp-org-sidebar-reduced + (24px * 2 ) } );
386
+ }
387
+
388
+ @media screen and ( min-width: 961px ) {
389
+ width: calc( 50% - #{$wp-org-sidebar-full } );
390
+ }
391
+ }
392
+
393
+ .template-selector-preview__placeholder {
394
+ position: absolute;
395
+ top: 50%;
396
+ left: 50%;
397
+ transform: translateX( -50% );
398
+ width: 80%;
399
+ text-align: center;
400
+ }
401
+
402
+ // Preview adjustments.
403
+ // Tweak styles which are inside of the preview container.
404
+ .block-editor-block-preview__container,
405
+ .template-selector-preview {
406
+ .editor-styles-wrapper {
407
+ .wp-block {
408
+ width: 100%;
409
+ }
410
+
411
+ .wp-block[data-align='wide'] {
412
+ //max-width: 800px;
413
+ }
414
+
415
+ // `core/cover`
416
+ .wp-block[data-type='core/cover'][data-align='full'] {
417
+ margin: 0;
418
+ .wp-block-cover {
419
+ padding: 0;
420
+ }
421
+ }
422
+
423
+ // `core/columns`
424
+ .wp-block-columns > .editor-inner-blocks > .editor-block-list__layout > [data-type='core/column'] {
425
+ //margin-left: -14px;
426
+ //margin-right: -14px;
427
+
428
+ & > .editor-block-list__block-edit > div > .block-core-columns > .editor-inner-blocks {
429
+ margin-top: 0;
430
+ margin-bottom: 0;
431
+ }
432
+ }
433
+
434
+ .block-editor-block-list__block {
435
+ &[data-align='full'] {
436
+ margin: 0;
437
+ }
438
+
439
+ .block-editor-block-list__block-edit {
440
+ @media screen and ( min-width: 600px ) {
441
+ margin: 0;
442
+ }
443
+ }
444
+ }
445
+
446
+ // Fix upstream: https://github.com/WordPress/gutenberg/pull/17202.
447
+ .block-editor-block-list__layout,
448
+ .block-editor-block-list__block {
449
+ padding: inherit;
450
+ }
451
+ }
452
+ }
453
+
454
+ // Set full height to preview container to inherits styles defined for themes.
455
+ .template-selector-preview .components-disabled,
456
+ .template-selector-preview .edit-post-visual-editor,
457
+ .template-selector-item__preview-wrap .components-disabled,
458
+ .template-selector-item__preview-wrap .edit-post-visual-editor {
459
+ height: 100%;
460
+
461
+ .editor-styles-wrapper {
462
+ height: 100%;
463
+ }
464
+ }
465
+
466
+ .page-template-modal__loading {
467
+ position: absolute;
468
+ top: 50%;
469
+ left: 50%;
470
+ transform: translate( -50%, -50% );
471
+ display: flex;
472
+ align-items: flex-end;
473
+
474
+ .components-spinner {
475
+ float: none;
476
+ }
477
+ }
starter-page-templates/page-template-modal/utils/replace-placeholders.js CHANGED
@@ -18,6 +18,10 @@ const KEY_MAP = {
18
  };
19
 
20
  const replacePlaceholders = ( pageContent, siteInformation = {} ) => {
 
 
 
 
21
  return pageContent.replace( /{{(\w+)}}/g, ( match, placeholder ) => {
22
  const defaultValue = PLACEHOLDER_DEFAULTS[ placeholder ];
23
  const key = KEY_MAP[ placeholder ];
18
  };
19
 
20
  const replacePlaceholders = ( pageContent, siteInformation = {} ) => {
21
+ if ( ! pageContent ) {
22
+ return '';
23
+ }
24
+
25
  return pageContent.replace( /{{(\w+)}}/g, ( match, placeholder ) => {
26
  const defaultValue = PLACEHOLDER_DEFAULTS[ placeholder ];
27
  const key = KEY_MAP[ placeholder ];