@pantheon-systems/puck-css 0.4.2 → 0.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/dist/core/config.d.ts +3 -0
  2. package/dist/core/config.d.ts.map +1 -1
  3. package/dist/core/config.js +5 -6
  4. package/dist/core/config.js.map +1 -1
  5. package/dist/core/featureConfig.d.ts +2 -0
  6. package/dist/core/featureConfig.d.ts.map +1 -1
  7. package/dist/core/featureConfig.js +4 -0
  8. package/dist/core/featureConfig.js.map +1 -1
  9. package/dist/core/types.d.ts +58 -1
  10. package/dist/core/types.d.ts.map +1 -1
  11. package/dist/data/dal/index.d.ts +5 -1
  12. package/dist/data/dal/index.d.ts.map +1 -1
  13. package/dist/data/dal/index.js +22 -1
  14. package/dist/data/dal/index.js.map +1 -1
  15. package/dist/data/dal/init.d.ts.map +1 -1
  16. package/dist/data/dal/init.js +22 -14
  17. package/dist/data/dal/init.js.map +1 -1
  18. package/dist/data/dal/p1-store.d.ts +15 -1
  19. package/dist/data/dal/p1-store.d.ts.map +1 -1
  20. package/dist/data/dal/p1-store.js +51 -5
  21. package/dist/data/dal/p1-store.js.map +1 -1
  22. package/dist/data/dal/types.d.ts +13 -1
  23. package/dist/data/dal/types.d.ts.map +1 -1
  24. package/dist/data/page-store.d.ts +17 -2
  25. package/dist/data/page-store.d.ts.map +1 -1
  26. package/dist/data/page-store.js +47 -5
  27. package/dist/data/page-store.js.map +1 -1
  28. package/dist/data/route-templates.js +1 -1
  29. package/dist/data/route-templates.js.map +1 -1
  30. package/dist/editor/P1App.d.ts.map +1 -1
  31. package/dist/editor/P1App.js +1 -1
  32. package/dist/editor/P1App.js.map +1 -1
  33. package/dist/editor/P1PuckProvider.d.ts.map +1 -1
  34. package/dist/editor/P1PuckProvider.js +175 -66
  35. package/dist/editor/P1PuckProvider.js.map +1 -1
  36. package/dist/editor/plugin/P1Plugin.d.ts +16 -1
  37. package/dist/editor/plugin/P1Plugin.d.ts.map +1 -1
  38. package/dist/editor/plugin/P1Plugin.js +35 -4
  39. package/dist/editor/plugin/P1Plugin.js.map +1 -1
  40. package/dist/editor/plugin/createP1Overrides.d.ts.map +1 -1
  41. package/dist/editor/plugin/createP1Overrides.js +4 -1
  42. package/dist/editor/plugin/createP1Overrides.js.map +1 -1
  43. package/dist/editor/useDocuments.d.ts +4 -1
  44. package/dist/editor/useDocuments.d.ts.map +1 -1
  45. package/dist/editor/useDocuments.js +5 -2
  46. package/dist/editor/useDocuments.js.map +1 -1
  47. package/dist/editor/useP1Editor.d.ts +12 -0
  48. package/dist/editor/useP1Editor.d.ts.map +1 -1
  49. package/dist/editor/useP1Editor.js +40 -5
  50. package/dist/editor/useP1Editor.js.map +1 -1
  51. package/dist/editor/useP1Plugin.d.ts +1 -1
  52. package/dist/editor/useP1Plugin.d.ts.map +1 -1
  53. package/dist/editor/useP1Plugin.js +2 -0
  54. package/dist/editor/useP1Plugin.js.map +1 -1
  55. package/dist/editor/useRealtime.d.ts +9 -4
  56. package/dist/editor/useRealtime.d.ts.map +1 -1
  57. package/dist/editor/useRealtime.js +11 -6
  58. package/dist/editor/useRealtime.js.map +1 -1
  59. package/dist/features/content-type-templates/editor/useTemplateEditor.d.ts +20 -0
  60. package/dist/features/content-type-templates/editor/useTemplateEditor.d.ts.map +1 -0
  61. package/dist/features/content-type-templates/editor/useTemplateEditor.js +62 -0
  62. package/dist/features/content-type-templates/editor/useTemplateEditor.js.map +1 -0
  63. package/dist/features/content-type-templates/editor/useTemplatePermissions.d.ts +7 -0
  64. package/dist/features/content-type-templates/editor/useTemplatePermissions.d.ts.map +1 -0
  65. package/dist/features/content-type-templates/editor/useTemplatePermissions.js +12 -0
  66. package/dist/features/content-type-templates/editor/useTemplatePermissions.js.map +1 -0
  67. package/dist/features/content-type-templates/editor/useTemplateScaffold.d.ts +19 -0
  68. package/dist/features/content-type-templates/editor/useTemplateScaffold.d.ts.map +1 -0
  69. package/dist/features/content-type-templates/editor/useTemplateScaffold.js +37 -0
  70. package/dist/features/content-type-templates/editor/useTemplateScaffold.js.map +1 -0
  71. package/dist/features/content-type-templates/hooks/useTemplateList.d.ts +41 -0
  72. package/dist/features/content-type-templates/hooks/useTemplateList.d.ts.map +1 -0
  73. package/dist/features/content-type-templates/hooks/useTemplateList.js +72 -0
  74. package/dist/features/content-type-templates/hooks/useTemplateList.js.map +1 -0
  75. package/dist/features/content-type-templates/index.d.ts +18 -0
  76. package/dist/features/content-type-templates/index.d.ts.map +1 -0
  77. package/dist/features/content-type-templates/index.js +13 -0
  78. package/dist/features/content-type-templates/index.js.map +1 -0
  79. package/dist/features/content-type-templates/permissions/createPuckPermissions.d.ts +68 -0
  80. package/dist/features/content-type-templates/permissions/createPuckPermissions.d.ts.map +1 -0
  81. package/dist/features/content-type-templates/permissions/createPuckPermissions.js +90 -0
  82. package/dist/features/content-type-templates/permissions/createPuckPermissions.js.map +1 -0
  83. package/dist/features/content-type-templates/permissions/role-permissions.d.ts +49 -0
  84. package/dist/features/content-type-templates/permissions/role-permissions.d.ts.map +1 -0
  85. package/dist/features/content-type-templates/permissions/role-permissions.js +79 -0
  86. package/dist/features/content-type-templates/permissions/role-permissions.js.map +1 -0
  87. package/dist/features/content-type-templates/permissions/useContentRole.d.ts +37 -0
  88. package/dist/features/content-type-templates/permissions/useContentRole.d.ts.map +1 -0
  89. package/dist/features/content-type-templates/permissions/useContentRole.js +34 -0
  90. package/dist/features/content-type-templates/permissions/useContentRole.js.map +1 -0
  91. package/dist/features/content-type-templates/permissions/useResolveContentRole.d.ts +38 -0
  92. package/dist/features/content-type-templates/permissions/useResolveContentRole.d.ts.map +1 -0
  93. package/dist/features/content-type-templates/permissions/useResolveContentRole.js +83 -0
  94. package/dist/features/content-type-templates/permissions/useResolveContentRole.js.map +1 -0
  95. package/dist/features/content-type-templates/stores/index.d.ts +9 -0
  96. package/dist/features/content-type-templates/stores/index.d.ts.map +1 -0
  97. package/dist/features/content-type-templates/stores/index.js +8 -0
  98. package/dist/features/content-type-templates/stores/index.js.map +1 -0
  99. package/dist/features/content-type-templates/stores/template-store-api.d.ts +17 -0
  100. package/dist/features/content-type-templates/stores/template-store-api.d.ts.map +1 -0
  101. package/dist/features/content-type-templates/stores/template-store-api.js +56 -0
  102. package/dist/features/content-type-templates/stores/template-store-api.js.map +1 -0
  103. package/dist/features/content-type-templates/stores/template-store.d.ts +54 -0
  104. package/dist/features/content-type-templates/stores/template-store.d.ts.map +1 -0
  105. package/dist/features/content-type-templates/stores/template-store.js +80 -0
  106. package/dist/features/content-type-templates/stores/template-store.js.map +1 -0
  107. package/dist/features/content-type-templates/types.d.ts +114 -0
  108. package/dist/features/content-type-templates/types.d.ts.map +1 -0
  109. package/dist/features/content-type-templates/types.js +7 -0
  110. package/dist/features/content-type-templates/types.js.map +1 -0
  111. package/dist/features/content-type-templates/ui/ActionBarPinButton.d.ts +3 -0
  112. package/dist/features/content-type-templates/ui/ActionBarPinButton.d.ts.map +1 -0
  113. package/dist/features/content-type-templates/ui/ActionBarPinButton.js +77 -0
  114. package/dist/features/content-type-templates/ui/ActionBarPinButton.js.map +1 -0
  115. package/dist/features/content-type-templates/ui/TemplateManagerOverlay.d.ts +18 -0
  116. package/dist/features/content-type-templates/ui/TemplateManagerOverlay.d.ts.map +1 -0
  117. package/dist/features/content-type-templates/ui/TemplateManagerOverlay.js +167 -0
  118. package/dist/features/content-type-templates/ui/TemplateManagerOverlay.js.map +1 -0
  119. package/dist/features/content-type-templates/ui/TemplatePinPanel.d.ts +18 -0
  120. package/dist/features/content-type-templates/ui/TemplatePinPanel.d.ts.map +1 -0
  121. package/dist/features/content-type-templates/ui/TemplatePinPanel.js +11 -0
  122. package/dist/features/content-type-templates/ui/TemplatePinPanel.js.map +1 -0
  123. package/dist/features/content-type-templates/ui/TemplateSelector.d.ts +41 -0
  124. package/dist/features/content-type-templates/ui/TemplateSelector.d.ts.map +1 -0
  125. package/dist/features/content-type-templates/ui/TemplateSelector.js +32 -0
  126. package/dist/features/content-type-templates/ui/TemplateSelector.js.map +1 -0
  127. package/dist/features/content-type-templates/ui/dataToTemplate.d.ts +25 -0
  128. package/dist/features/content-type-templates/ui/dataToTemplate.d.ts.map +1 -0
  129. package/dist/features/content-type-templates/ui/dataToTemplate.js +37 -0
  130. package/dist/features/content-type-templates/ui/dataToTemplate.js.map +1 -0
  131. package/dist/features/content-type-templates/validation/structural-validation.d.ts +29 -0
  132. package/dist/features/content-type-templates/validation/structural-validation.d.ts.map +1 -0
  133. package/dist/features/content-type-templates/validation/structural-validation.js +69 -0
  134. package/dist/features/content-type-templates/validation/structural-validation.js.map +1 -0
  135. package/dist/index.d.ts +8 -1
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/index.js +6 -1
  138. package/dist/index.js.map +1 -1
  139. package/dist/p1/editor/connect/connect-field-modal.d.ts.map +1 -1
  140. package/dist/p1/editor/connect/connect-field-modal.js +23 -1
  141. package/dist/p1/editor/connect/connect-field-modal.js.map +1 -1
  142. package/dist/p1/editor/connect/field-connect-plugin.d.ts.map +1 -1
  143. package/dist/p1/editor/connect/field-connect-plugin.js +2 -6
  144. package/dist/p1/editor/connect/field-connect-plugin.js.map +1 -1
  145. package/dist/p1/pages/conflict-resolution-panel.d.ts +17 -0
  146. package/dist/p1/pages/conflict-resolution-panel.d.ts.map +1 -0
  147. package/dist/p1/pages/conflict-resolution-panel.js +74 -0
  148. package/dist/p1/pages/conflict-resolution-panel.js.map +1 -0
  149. package/dist/p1/pages/content-type-template-list.d.ts +7 -0
  150. package/dist/p1/pages/content-type-template-list.d.ts.map +1 -0
  151. package/dist/p1/pages/content-type-template-list.js +108 -0
  152. package/dist/p1/pages/content-type-template-list.js.map +1 -0
  153. package/dist/p1/pages/create-content-type-form.d.ts +7 -0
  154. package/dist/p1/pages/create-content-type-form.d.ts.map +1 -0
  155. package/dist/p1/pages/create-content-type-form.js +102 -0
  156. package/dist/p1/pages/create-content-type-form.js.map +1 -0
  157. package/dist/p1/pages/create-page-form.d.ts +8 -1
  158. package/dist/p1/pages/create-page-form.d.ts.map +1 -1
  159. package/dist/p1/pages/create-page-form.js +67 -8
  160. package/dist/p1/pages/create-page-form.js.map +1 -1
  161. package/dist/p1/pages/create-template-form.d.ts +6 -1
  162. package/dist/p1/pages/create-template-form.d.ts.map +1 -1
  163. package/dist/p1/pages/create-template-form.js +61 -15
  164. package/dist/p1/pages/create-template-form.js.map +1 -1
  165. package/dist/p1/pages/hooks.d.ts +6 -1
  166. package/dist/p1/pages/hooks.d.ts.map +1 -1
  167. package/dist/p1/pages/hooks.js +13 -2
  168. package/dist/p1/pages/hooks.js.map +1 -1
  169. package/dist/p1/pages/index.d.ts +5 -0
  170. package/dist/p1/pages/index.d.ts.map +1 -1
  171. package/dist/p1/pages/index.js +5 -0
  172. package/dist/p1/pages/index.js.map +1 -1
  173. package/dist/p1/pages/migration-conflict-queue.d.ts +8 -0
  174. package/dist/p1/pages/migration-conflict-queue.d.ts.map +1 -0
  175. package/dist/p1/pages/migration-conflict-queue.js +62 -0
  176. package/dist/p1/pages/migration-conflict-queue.js.map +1 -0
  177. package/dist/p1/pages/migration-preview-panel.d.ts +12 -0
  178. package/dist/p1/pages/migration-preview-panel.d.ts.map +1 -0
  179. package/dist/p1/pages/migration-preview-panel.js +157 -0
  180. package/dist/p1/pages/migration-preview-panel.js.map +1 -0
  181. package/dist/p1/pages/migration-status-panel.d.ts +7 -0
  182. package/dist/p1/pages/migration-status-panel.d.ts.map +1 -0
  183. package/dist/p1/pages/migration-status-panel.js +198 -0
  184. package/dist/p1/pages/migration-status-panel.js.map +1 -0
  185. package/dist/p1/pages/structure-page.d.ts.map +1 -1
  186. package/dist/p1/pages/structure-page.js +75 -18
  187. package/dist/p1/pages/structure-page.js.map +1 -1
  188. package/dist/p1/pages/structure-tabs.d.ts +11 -0
  189. package/dist/p1/pages/structure-tabs.d.ts.map +1 -0
  190. package/dist/p1/pages/structure-tabs.js +45 -0
  191. package/dist/p1/pages/structure-tabs.js.map +1 -0
  192. package/dist/pds/components/P1EditorHeader.d.ts +6 -2
  193. package/dist/pds/components/P1EditorHeader.d.ts.map +1 -1
  194. package/dist/pds/components/P1EditorHeader.js +6 -3
  195. package/dist/pds/components/P1EditorHeader.js.map +1 -1
  196. package/dist/pds/components/PageNavigator.d.ts +7 -2
  197. package/dist/pds/components/PageNavigator.d.ts.map +1 -1
  198. package/dist/pds/components/PageNavigator.js +28 -7
  199. package/dist/pds/components/PageNavigator.js.map +1 -1
  200. package/dist/pds/components/PageNavigator.module.css +70 -0
  201. package/package.json +3 -3
  202. package/src/styles.css +331 -0
@@ -0,0 +1,56 @@
1
+ /**
2
+ * API-Backed Template Store
3
+ *
4
+ * Production template store implementation using the backend API.
5
+ */
6
+ /**
7
+ * Create a template store backed by the P1 API.
8
+ *
9
+ * @param client - P1Client instance
10
+ * @param siteId - Site ID
11
+ * @param branchId - Branch ID
12
+ * @returns TemplateStore instance
13
+ */
14
+ export function createApiTemplateStore(client, siteId, branchId) {
15
+ return {
16
+ async create(params) {
17
+ const template = await client.templates.create(siteId, branchId, params);
18
+ return template;
19
+ },
20
+ async get(id) {
21
+ try {
22
+ const template = await client.templates.get(siteId, branchId, id);
23
+ return template;
24
+ }
25
+ catch (error) {
26
+ // Return undefined for 404s
27
+ if (error && typeof error === 'object' && 'status' in error && error.status === 404) {
28
+ return undefined;
29
+ }
30
+ throw error;
31
+ }
32
+ },
33
+ async list() {
34
+ return await client.templates.list(siteId, branchId);
35
+ },
36
+ async update(id, params) {
37
+ return await client.templates.update(siteId, branchId, id, params);
38
+ },
39
+ async delete(id) {
40
+ await client.templates.delete(siteId, branchId, id);
41
+ },
42
+ async getBinding(_documentId) {
43
+ return undefined;
44
+ },
45
+ async setBinding(_documentId, _templateId, _templateVersion) {
46
+ throw new Error('Template bindings are managed server-side via document metadata. Use the documents API to set template_id.');
47
+ },
48
+ async listBindings(_templateId) {
49
+ return [];
50
+ },
51
+ async removeBinding(_documentId) {
52
+ throw new Error('Template bindings are managed server-side via document metadata. Use the documents API to update template_id.');
53
+ },
54
+ };
55
+ }
56
+ //# sourceMappingURL=template-store-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-store-api.js","sourceRoot":"","sources":["../../../../src/features/content-type-templates/stores/template-store-api.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAgB,EAChB,MAAc,EACd,QAAgB;IAEhB,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,MAA4B;YACvC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;YACzE,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,EAAU;YAClB,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;gBAClE,OAAO,QAAQ,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,4BAA4B;gBAC5B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBACpF,OAAO,SAAS,CAAC;gBACnB,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI;YACR,OAAO,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACvD,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,MAA4B;YACnD,OAAO,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;QACrE,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAU;YACrB,MAAM,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QACtD,CAAC;QAED,KAAK,CAAC,UAAU,CAAC,WAAmB;YAClC,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,KAAK,CAAC,UAAU,CACd,WAAmB,EACnB,WAAmB,EACnB,gBAAwB;YAExB,MAAM,IAAI,KAAK,CAAC,4GAA4G,CAAC,CAAC;QAChI,CAAC;QAED,KAAK,CAAC,YAAY,CAAC,WAAmB;YACpC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,KAAK,CAAC,aAAa,CAAC,WAAmB;YACrC,MAAM,IAAI,KAAK,CAAC,+GAA+G,CAAC,CAAC;QACnI,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Template Store Interface
3
+ *
4
+ * Defines the contract for template storage and retrieval.
5
+ * Implementations can use localStorage, CSS documents, or backend API.
6
+ */
7
+ import type { Template, TemplateBinding, CreateTemplateParams, UpdateTemplateParams } from '../types.js';
8
+ /**
9
+ * Template store interface for CRUD operations and bindings.
10
+ */
11
+ export interface TemplateStore {
12
+ /**
13
+ * Create a new template.
14
+ */
15
+ create(params: CreateTemplateParams): Promise<Template>;
16
+ /**
17
+ * Get a template by ID.
18
+ */
19
+ get(id: string): Promise<Template | undefined>;
20
+ /**
21
+ * List all templates.
22
+ */
23
+ list(): Promise<Template[]>;
24
+ /**
25
+ * Update an existing template.
26
+ * Increments the version number.
27
+ */
28
+ update(id: string, params: UpdateTemplateParams): Promise<Template>;
29
+ /**
30
+ * Delete a template.
31
+ */
32
+ delete(id: string): Promise<void>;
33
+ /**
34
+ * Get the template binding for a document.
35
+ */
36
+ getBinding(documentId: string): Promise<TemplateBinding | undefined>;
37
+ /**
38
+ * Set a template binding for a document.
39
+ */
40
+ setBinding(documentId: string, templateId: string, templateVersion: number): Promise<void>;
41
+ /**
42
+ * List all document bindings for a template.
43
+ */
44
+ listBindings(templateId: string): Promise<TemplateBinding[]>;
45
+ /**
46
+ * Remove a template binding for a document.
47
+ */
48
+ removeBinding(documentId: string): Promise<void>;
49
+ }
50
+ /**
51
+ * Create an in-memory template store for testing and development.
52
+ */
53
+ export declare function createInMemoryTemplateStore(): TemplateStore;
54
+ //# sourceMappingURL=template-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-store.d.ts","sourceRoot":"","sources":["../../../../src/features/content-type-templates/stores/template-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,eAAe,EACf,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,MAAM,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAExD;;OAEG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC,CAAC;IAE/C;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAE5B;;;OAGG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEpE;;OAEG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElC;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;IAErE;;OAEG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3F;;OAEG;IACH,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAE7D;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AASD;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,aAAa,CA+E3D"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Template Store Interface
3
+ *
4
+ * Defines the contract for template storage and retrieval.
5
+ * Implementations can use localStorage, CSS documents, or backend API.
6
+ */
7
+ /**
8
+ * Generate a unique template ID.
9
+ */
10
+ function generateId() {
11
+ return `tmpl_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
12
+ }
13
+ /**
14
+ * Create an in-memory template store for testing and development.
15
+ */
16
+ export function createInMemoryTemplateStore() {
17
+ const templates = new Map();
18
+ const bindings = new Map();
19
+ return {
20
+ async create(params) {
21
+ const now = new Date().toISOString();
22
+ const template = {
23
+ id: generateId(),
24
+ name: params.name,
25
+ label: params.label,
26
+ description: params.description,
27
+ defaultUrlPattern: params.defaultUrlPattern,
28
+ version: 1,
29
+ components: params.components,
30
+ createdAt: now,
31
+ updatedAt: now,
32
+ };
33
+ templates.set(template.id, template);
34
+ return template;
35
+ },
36
+ async get(id) {
37
+ return templates.get(id);
38
+ },
39
+ async list() {
40
+ return Array.from(templates.values());
41
+ },
42
+ async update(id, params) {
43
+ const existing = templates.get(id);
44
+ if (!existing) {
45
+ throw new Error('Template not found');
46
+ }
47
+ const updated = {
48
+ ...existing,
49
+ label: params.label ?? existing.label,
50
+ description: params.description ?? existing.description,
51
+ defaultUrlPattern: params.defaultUrlPattern ?? existing.defaultUrlPattern,
52
+ components: params.components ?? existing.components,
53
+ version: existing.version + 1,
54
+ updatedAt: new Date().toISOString(),
55
+ };
56
+ templates.set(id, updated);
57
+ return updated;
58
+ },
59
+ async delete(id) {
60
+ templates.delete(id);
61
+ },
62
+ async getBinding(documentId) {
63
+ return bindings.get(documentId);
64
+ },
65
+ async setBinding(documentId, templateId, templateVersion) {
66
+ bindings.set(documentId, {
67
+ documentId,
68
+ templateId,
69
+ templateVersion,
70
+ });
71
+ },
72
+ async listBindings(templateId) {
73
+ return Array.from(bindings.values()).filter((b) => b.templateId === templateId);
74
+ },
75
+ async removeBinding(documentId) {
76
+ bindings.delete(documentId);
77
+ },
78
+ };
79
+ }
80
+ //# sourceMappingURL=template-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-store.js","sourceRoot":"","sources":["../../../../src/features/content-type-templates/stores/template-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Content Type Templates - Core Types
3
+ *
4
+ * TypeScript types and interfaces for the content type templates feature.
5
+ */
6
+ import type { Data } from '@puckeditor/core';
7
+ /**
8
+ * User role for content editing.
9
+ *
10
+ * - admin: Full access - can create/edit templates, full structural control
11
+ * - editor: Pinned components locked (cannot move/delete), can add/remove non-pinned
12
+ * - junior-editor: View/edit props only, no structural changes
13
+ */
14
+ export type ContentRole = 'admin' | 'editor' | 'junior-editor';
15
+ /**
16
+ * Template metadata stored in root.props._templateMeta.
17
+ */
18
+ export interface TemplateMetadata {
19
+ /** Unique template name (kebab-case identifier) */
20
+ name: string;
21
+ /** Human-readable label */
22
+ label: string;
23
+ /** Optional description */
24
+ description?: string;
25
+ /** Optional default URL pattern for documents created from this template */
26
+ defaultUrlPattern?: string;
27
+ /** Template version number (incremented on each save) */
28
+ version: number;
29
+ }
30
+ /**
31
+ * A component in the template skeleton with pinned status.
32
+ */
33
+ export interface TemplateComponent {
34
+ /** Component type (e.g., "HeadingBlock", "TextBlock") */
35
+ type: string;
36
+ /** Whether this component is pinned (locked position) */
37
+ pinned: boolean;
38
+ /** Default props for this component */
39
+ defaultProps: Record<string, unknown>;
40
+ }
41
+ /**
42
+ * A complete template definition.
43
+ */
44
+ export interface Template {
45
+ /** Unique template ID */
46
+ id: string;
47
+ /** Template name (kebab-case identifier) */
48
+ name: string;
49
+ /** Human-readable label */
50
+ label: string;
51
+ /** Optional description */
52
+ description?: string;
53
+ /** Optional default URL pattern */
54
+ defaultUrlPattern?: string;
55
+ /** Template version number */
56
+ version: number;
57
+ /** Whether this template is deprecated */
58
+ deprecated?: boolean;
59
+ /** Component skeleton */
60
+ components: TemplateComponent[];
61
+ /** Creation timestamp (not returned by all endpoints) */
62
+ createdAt?: string;
63
+ /** Last update timestamp */
64
+ updatedAt: string;
65
+ }
66
+ /**
67
+ * Document-to-template binding.
68
+ * Stored in documents table columns (template_id, template_version).
69
+ */
70
+ export interface TemplateBinding {
71
+ /** Document ID */
72
+ documentId: string;
73
+ /** Template ID this document is bound to */
74
+ templateId: string;
75
+ /** Template version this document was created from or migrated to */
76
+ templateVersion: number;
77
+ }
78
+ /**
79
+ * Parameters for creating a template.
80
+ */
81
+ export interface CreateTemplateParams {
82
+ /** Template name (kebab-case identifier) */
83
+ name: string;
84
+ /** Human-readable label */
85
+ label: string;
86
+ /** Optional description */
87
+ description?: string;
88
+ /** Optional default URL pattern */
89
+ defaultUrlPattern?: string;
90
+ /** Initial component skeleton */
91
+ components: TemplateComponent[];
92
+ }
93
+ /**
94
+ * Parameters for updating a template.
95
+ */
96
+ export interface UpdateTemplateParams {
97
+ /** Updated label */
98
+ label?: string;
99
+ /** Updated description */
100
+ description?: string;
101
+ /** Updated default URL pattern */
102
+ defaultUrlPattern?: string;
103
+ /** Updated component skeleton */
104
+ components?: TemplateComponent[];
105
+ }
106
+ /**
107
+ * Template with full Puck data for editing.
108
+ * Used when editing a template document in the editor.
109
+ */
110
+ export interface TemplateDocument extends Template {
111
+ /** Full Puck data structure */
112
+ data: Data;
113
+ }
114
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/features/content-type-templates/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,QAAQ,GAAG,eAAe,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IAEb,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IAEd,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IAEb,yDAAyD;IACzD,MAAM,EAAE,OAAO,CAAC;IAEhB,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IAEX,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IAEb,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IAEd,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAEhB,0CAA0C;IAC1C,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB,yBAAyB;IACzB,UAAU,EAAE,iBAAiB,EAAE,CAAC;IAEhC,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IAEnB,4CAA4C;IAC5C,UAAU,EAAE,MAAM,CAAC;IAEnB,qEAAqE;IACrE,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,IAAI,EAAE,MAAM,CAAC;IAEb,2BAA2B;IAC3B,KAAK,EAAE,MAAM,CAAC;IAEd,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mCAAmC;IACnC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,iCAAiC;IACjC,UAAU,EAAE,iBAAiB,EAAE,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,kCAAkC;IAClC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,iCAAiC;IACjC,UAAU,CAAC,EAAE,iBAAiB,EAAE,CAAC;CAClC;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,QAAQ;IAChD,+BAA+B;IAC/B,IAAI,EAAE,IAAI,CAAC;CACZ"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Content Type Templates - Core Types
3
+ *
4
+ * TypeScript types and interfaces for the content type templates feature.
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/features/content-type-templates/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ export declare function ActionBarPinButton(): React.ReactElement | null;
3
+ //# sourceMappingURL=ActionBarPinButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionBarPinButton.d.ts","sourceRoot":"","sources":["../../../../src/features/content-type-templates/ui/ActionBarPinButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAiCrD,wBAAgB,kBAAkB,IAAI,KAAK,CAAC,YAAY,GAAG,IAAI,CAqF9D"}
@@ -0,0 +1,77 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useCallback, useState } from 'react';
3
+ import { ActionBar, createUsePuck, usePuck } from '@puckeditor/core';
4
+ import { Icon } from '@pantheon-systems/pds-toolkit-react';
5
+ import { useP1PuckOptional } from '../../../core/P1PuckContext.js';
6
+ const usePuckState = createUsePuck();
7
+ function resolveTemplate(css) {
8
+ if (css.currentTemplate)
9
+ return css.currentTemplate;
10
+ const path = css.currentDocument?.path;
11
+ if (!path)
12
+ return null;
13
+ const match = path.match(/^_registry\/templates\/(.+)$/);
14
+ if (!match)
15
+ return null;
16
+ return css.templates.find((t) => t.name === match[1]) ?? null;
17
+ }
18
+ export function ActionBarPinButton() {
19
+ const css = useP1PuckOptional();
20
+ const selectedItem = usePuckState((s) => s.selectedItem);
21
+ const content = usePuckState((s) => s.appState?.data?.content);
22
+ const rootProps = usePuckState((s) => s.appState?.data?.root?.props);
23
+ const { dispatch, refreshPermissions } = usePuck();
24
+ const [toggling, setToggling] = useState(false);
25
+ const template = css ? resolveTemplate(css) : null;
26
+ const pinMap = rootProps?._pinMap ?? {};
27
+ const handleTogglePin = useCallback(async () => {
28
+ if (!css || !template || !selectedItem || !content || toggling)
29
+ return;
30
+ setToggling(true);
31
+ const compId = selectedItem.props.id;
32
+ const newPinned = !pinMap[compId];
33
+ const updatedPinMap = { ...pinMap, [compId]: newPinned };
34
+ dispatch({
35
+ type: 'setData',
36
+ data: (prev) => ({
37
+ ...prev,
38
+ root: {
39
+ ...prev.root,
40
+ props: {
41
+ ...prev.root.props,
42
+ _pinMap: updatedPinMap,
43
+ },
44
+ },
45
+ }),
46
+ });
47
+ // Puck caches resolvePermissions results per component instance and only
48
+ // re-resolves when the component's own data changes. Since _pinMap lives
49
+ // in root props, toggling it doesn't invalidate per-component caches.
50
+ // Force a full re-resolution so the updated pinMap is respected immediately.
51
+ void refreshPermissions();
52
+ const updatedComponents = content.map((c) => {
53
+ const existing = template.components?.find((tc) => tc.type === c.type);
54
+ return {
55
+ type: c.type,
56
+ pinned: updatedPinMap[c.props.id] ?? false,
57
+ defaultProps: existing?.defaultProps ?? {},
58
+ };
59
+ });
60
+ try {
61
+ await css.client.templates.update(css.siteId, css.branchId, template.id, {
62
+ components: updatedComponents,
63
+ });
64
+ await css.refreshTemplates();
65
+ }
66
+ finally {
67
+ setToggling(false);
68
+ }
69
+ }, [css, template, selectedItem, content, pinMap, dispatch, refreshPermissions, toggling]);
70
+ if (!css || !template || !selectedItem || !content) {
71
+ return null;
72
+ }
73
+ const isAdmin = css.userRole === 'admin';
74
+ const isPinned = pinMap[selectedItem.props.id] ?? false;
75
+ return (_jsx(ActionBar.Action, { label: isPinned ? 'Unpin component' : 'Pin component', onClick: handleTogglePin, active: isPinned, disabled: toggling || !isAdmin, children: _jsx(Icon, { iconName: isPinned ? 'lock' : 'lockOpen', iconSize: "s", "aria-hidden": "true" }) }));
76
+ }
77
+ //# sourceMappingURL=ActionBarPinButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ActionBarPinButton.js","sourceRoot":"","sources":["../../../../src/features/content-type-templates/ui/ActionBarPinButton.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * TemplateManagerOverlay
3
+ *
4
+ * Full-screen overlay for managing content type templates.
5
+ * Provides a list view of templates and a Puck-based editor for
6
+ * creating and editing templates.
7
+ */
8
+ import React from 'react';
9
+ import type { P1Client } from '@pantheon-systems/css-client';
10
+ export interface TemplateManagerOverlayProps {
11
+ client: P1Client;
12
+ siteId: string;
13
+ branchId: string;
14
+ puckConfig: unknown;
15
+ onClose: () => void;
16
+ }
17
+ export declare function TemplateManagerOverlay({ client, siteId, branchId, puckConfig, onClose, }: TemplateManagerOverlayProps): React.ReactElement;
18
+ //# sourceMappingURL=TemplateManagerOverlay.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemplateManagerOverlay.d.ts","sourceRoot":"","sources":["../../../../src/features/content-type-templates/ui/TemplateManagerOverlay.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA2C,MAAM,OAAO,CAAC;AAEhE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAQ7D,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,QAAQ,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAUD,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,MAAM,EACN,QAAQ,EACR,UAAU,EACV,OAAO,GACR,EAAE,2BAA2B,GAAG,KAAK,CAAC,YAAY,CAkSlD"}
@@ -0,0 +1,167 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * TemplateManagerOverlay
4
+ *
5
+ * Full-screen overlay for managing content type templates.
6
+ * Provides a list view of templates and a Puck-based editor for
7
+ * creating and editing templates.
8
+ */
9
+ import { useState, useCallback, useEffect } from 'react';
10
+ import { createPortal } from 'react-dom';
11
+ import { useTemplateList } from '../hooks/useTemplateList.js';
12
+ import { scaffoldFromTemplate } from '../editor/useTemplateScaffold.js';
13
+ import { TemplatePinPanel } from './TemplatePinPanel.js';
14
+ import { dataToCreateParams, dataToUpdateParams } from './dataToTemplate.js';
15
+ export function TemplateManagerOverlay({ client, siteId, branchId, puckConfig, onClose, }) {
16
+ const { templates, loading, refresh } = useTemplateList(client, siteId, branchId);
17
+ const [mode, setMode] = useState('list');
18
+ const [editingTemplate, setEditingTemplate] = useState(null);
19
+ const [saving, setSaving] = useState(false);
20
+ const [error, setError] = useState(null);
21
+ // Editor state
22
+ const [editorData, setEditorData] = useState({
23
+ content: [],
24
+ root: { props: {} },
25
+ });
26
+ const [pinMap, setPinMap] = useState(new Map());
27
+ const [metadata, setMetadata] = useState({
28
+ name: '',
29
+ label: '',
30
+ description: '',
31
+ });
32
+ const handleCreate = useCallback(() => {
33
+ setMode('create');
34
+ setEditingTemplate(null);
35
+ setEditorData({ content: [], root: { props: {} } });
36
+ setPinMap(new Map());
37
+ setMetadata({ name: '', label: '', description: '' });
38
+ setError(null);
39
+ }, []);
40
+ const handleEdit = useCallback((template) => {
41
+ setMode('edit');
42
+ setEditingTemplate(template);
43
+ const data = scaffoldFromTemplate(template);
44
+ setEditorData(data);
45
+ const newPinMap = new Map();
46
+ data.content.forEach((comp, idx) => {
47
+ const compId = comp.props.id;
48
+ newPinMap.set(compId, (template.components ?? [])[idx]?.pinned ?? false);
49
+ });
50
+ setPinMap(newPinMap);
51
+ setMetadata({
52
+ name: template.name,
53
+ label: template.label,
54
+ description: template.description ?? '',
55
+ defaultUrlPattern: template.defaultUrlPattern ?? '',
56
+ });
57
+ setError(null);
58
+ }, []);
59
+ const handleDelete = useCallback(async (templateId) => {
60
+ if (!window.confirm('Delete this template? Documents using it will not be affected.'))
61
+ return;
62
+ try {
63
+ await client.templates.delete(siteId, branchId, templateId);
64
+ await refresh();
65
+ }
66
+ catch (err) {
67
+ setError(err instanceof Error ? err.message : 'Failed to delete template');
68
+ }
69
+ }, [client, siteId, branchId, refresh]);
70
+ const handleSave = useCallback(async () => {
71
+ if (!metadata.name.trim() || !metadata.label.trim()) {
72
+ setError('Name and label are required');
73
+ return;
74
+ }
75
+ const pattern = metadata.defaultUrlPattern?.trim() ?? '';
76
+ if (pattern && !pattern.startsWith('/')) {
77
+ setError('URL pattern must start with /');
78
+ return;
79
+ }
80
+ if (pattern && /[?#]/.test(pattern)) {
81
+ setError('URL pattern must not contain ? or #');
82
+ return;
83
+ }
84
+ if (saving)
85
+ return;
86
+ setSaving(true);
87
+ setError(null);
88
+ try {
89
+ if (mode === 'create') {
90
+ const params = dataToCreateParams(editorData, pinMap, metadata);
91
+ await client.templates.create(siteId, branchId, params);
92
+ }
93
+ else if (editingTemplate) {
94
+ const params = dataToUpdateParams(editorData, pinMap, metadata);
95
+ await client.templates.update(siteId, branchId, editingTemplate.id, params);
96
+ }
97
+ await refresh();
98
+ setMode('list');
99
+ }
100
+ catch (err) {
101
+ setError(err instanceof Error ? err.message : 'Failed to save template');
102
+ }
103
+ finally {
104
+ setSaving(false);
105
+ }
106
+ }, [mode, editingTemplate, editorData, pinMap, metadata, client, siteId, branchId, refresh]);
107
+ const handleCancel = useCallback(() => {
108
+ setMode('list');
109
+ setEditingTemplate(null);
110
+ setError(null);
111
+ }, []);
112
+ const handleTogglePin = useCallback((componentId, pinned) => {
113
+ setPinMap((prev) => {
114
+ const next = new Map(prev);
115
+ next.set(componentId, pinned);
116
+ return next;
117
+ });
118
+ }, []);
119
+ const handlePuckChange = useCallback((data) => {
120
+ const d = data;
121
+ setEditorData(d);
122
+ // Preserve pin state for existing components, default new ones to unpinned
123
+ setPinMap((prev) => {
124
+ const next = new Map();
125
+ for (const comp of d.content) {
126
+ const id = comp.props.id;
127
+ next.set(id, prev.get(id) ?? false);
128
+ }
129
+ return next;
130
+ });
131
+ }, []);
132
+ // Close on Escape
133
+ useEffect(() => {
134
+ const handler = (e) => {
135
+ if (e.key === 'Escape') {
136
+ if (mode === 'list')
137
+ onClose();
138
+ else
139
+ handleCancel();
140
+ }
141
+ };
142
+ window.addEventListener('keydown', handler);
143
+ return () => window.removeEventListener('keydown', handler);
144
+ }, [mode, onClose, handleCancel]);
145
+ const components = editorData.content.map((c) => ({
146
+ id: c.props.id,
147
+ type: c.type,
148
+ }));
149
+ const overlay = (_jsxs("div", { className: "template-manager-overlay", role: "dialog", "aria-label": "Template Manager", children: [_jsxs("div", { className: "template-manager-overlay__header", children: [_jsx("h2", { className: "template-manager-overlay__title", children: mode === 'list' ? 'Manage Templates' : mode === 'create' ? 'New Template' : `Edit: ${editingTemplate?.label}` }), _jsx("button", { type: "button", className: "template-manager-overlay__close", onClick: mode === 'list' ? onClose : handleCancel, "aria-label": "Close template manager", children: mode === 'list' ? '×' : '← Back' })] }), error && (_jsx("div", { role: "alert", className: "template-manager-overlay__error", children: error })), mode === 'list' ? (_jsxs("div", { className: "template-manager-overlay__list", children: [_jsx("button", { type: "button", className: "pds-button pds-button--primary", onClick: handleCreate, children: "+ New Template" }), loading ? (_jsx("div", { className: "template-manager-overlay__loading", children: "Loading templates..." })) : templates.length === 0 ? (_jsx("div", { className: "template-manager-overlay__empty", children: "No templates yet. Create one to get started." })) : (_jsx("ul", { className: "template-manager-overlay__template-list", children: templates.map((t) => (_jsxs("li", { className: "template-manager-overlay__template-item", children: [_jsxs("div", { className: "template-manager-overlay__template-info", children: [_jsx("span", { className: "template-manager-overlay__template-label", children: t.label || t.name }), _jsxs("span", { className: "template-manager-overlay__template-meta", children: [(t.components ?? []).length, " component", (t.components ?? []).length !== 1 ? 's' : '', " \u00B7 v", t.version] })] }), _jsxs("div", { className: "template-manager-overlay__template-actions", children: [_jsx("button", { type: "button", className: "pds-button pds-button--secondary pds-button--sm", onClick: () => handleEdit(t), children: "Edit" }), _jsx("button", { type: "button", className: "pds-button pds-button--critical-secondary pds-button--sm", onClick: () => handleDelete(t.id), "aria-label": `Delete ${t.label}`, children: "Delete" })] })] }, t.id))) }))] })) : (_jsxs("div", { className: "template-manager-overlay__editor", children: [_jsxs("div", { className: "template-manager-overlay__editor-sidebar", children: [_jsxs("div", { className: "template-manager-overlay__metadata", children: [_jsxs("label", { className: "template-manager-overlay__field", children: [_jsx("span", { className: "template-manager-overlay__field-label", children: "Name" }), _jsx("input", { type: "text", value: metadata.name, onChange: (e) => setMetadata((m) => ({ ...m, name: e.target.value })), placeholder: "blog-post", disabled: mode === 'edit', className: "template-manager-overlay__input" })] }), _jsxs("label", { className: "template-manager-overlay__field", children: [_jsx("span", { className: "template-manager-overlay__field-label", children: "Label" }), _jsx("input", { type: "text", value: metadata.label, onChange: (e) => setMetadata((m) => ({ ...m, label: e.target.value })), placeholder: "Blog Post", className: "template-manager-overlay__input" })] }), _jsxs("label", { className: "template-manager-overlay__field", children: [_jsx("span", { className: "template-manager-overlay__field-label", children: "Description" }), _jsx("textarea", { value: metadata.description, onChange: (e) => setMetadata((m) => ({ ...m, description: e.target.value })), placeholder: "Optional description", rows: 2, className: "template-manager-overlay__textarea" })] }), _jsxs("label", { className: "template-manager-overlay__field", children: [_jsx("span", { className: "template-manager-overlay__field-label", children: "Default URL pattern" }), _jsx("input", { type: "text", value: metadata.defaultUrlPattern ?? '', onChange: (e) => setMetadata((m) => ({ ...m, defaultUrlPattern: e.target.value })), placeholder: "/blog/:year/:month/:slug", className: "template-manager-overlay__input" })] })] }), _jsx(TemplatePinPanel, { components: components, pinMap: pinMap, onTogglePin: handleTogglePin }), _jsxs("div", { className: "template-manager-overlay__save-actions", children: [_jsx("button", { type: "button", className: "pds-button pds-button--primary", onClick: handleSave, disabled: saving, children: saving ? 'Saving...' : mode === 'create' ? 'Create Template' : 'Save Changes' }), _jsx("button", { type: "button", className: "pds-button pds-button--secondary", onClick: handleCancel, children: "Cancel" })] })] }), _jsx("div", { className: "template-manager-overlay__editor-canvas", children: _jsx(PuckEditor, { config: puckConfig, data: editorData, onChange: handlePuckChange }) })] }))] }));
150
+ return createPortal(overlay, document.body);
151
+ }
152
+ /**
153
+ * Wrapper that lazily loads and renders Puck for template editing.
154
+ */
155
+ function PuckEditor({ config, data, onChange, }) {
156
+ const [Puck, setPuck] = useState(null);
157
+ useEffect(() => {
158
+ import('@puckeditor/core').then((mod) => {
159
+ setPuck(() => mod.Puck);
160
+ });
161
+ }, []);
162
+ if (!Puck) {
163
+ return _jsx("div", { className: "template-manager-overlay__puck-loading", children: "Loading editor..." });
164
+ }
165
+ return _jsx(Puck, { config: config, data: data, onChange: onChange });
166
+ }
167
+ //# sourceMappingURL=TemplateManagerOverlay.js.map