@phis/ui 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 (335) hide show
  1. package/components/cms/phi-cms-layout-renderer.js +4 -3
  2. package/components/cms/phi-cms-page-render-scope.d.ts +4 -5
  3. package/components/cms/phi-cms-page-render-scope.js +43 -22
  4. package/components/cms/phi-cms-render-diagnostic-client.js +7 -3
  5. package/components/cms/phi-cms-render-error-boundary.js +2 -1
  6. package/components/controls/phi-anchor-nav-control.js +4 -1
  7. package/components/controls/phi-background-control.js +21 -6
  8. package/components/controls/phi-bullet-list-control.d.ts +7 -2
  9. package/components/controls/phi-bullet-list-control.js +35 -5
  10. package/components/controls/phi-color-control.js +4 -2
  11. package/components/controls/phi-drawer-control-adapter.js +3 -2
  12. package/components/controls/phi-inline-text-editor.js +7 -1
  13. package/components/controls/phi-length-control.js +1 -1
  14. package/components/controls/phi-ribbon-control.d.ts +38 -0
  15. package/components/controls/phi-ribbon-control.js +57 -0
  16. package/components/controls/phi-ribbon-wrap-control.d.ts +26 -0
  17. package/components/controls/phi-ribbon-wrap-control.js +25 -0
  18. package/components/controls/phi-select-control.js +5 -2
  19. package/components/controls/phi-series-chart-control.d.ts +48 -0
  20. package/components/controls/phi-series-chart-control.js +82 -0
  21. package/components/controls/phi-table-control.d.ts +3 -0
  22. package/components/controls/phi-table-control.js +13 -1
  23. package/components/controls/phi-text-control.js +57 -3
  24. package/components/controls/phi-tree-control.js +4 -4
  25. package/components/controls/phi-truncated-hover-text.d.ts +15 -0
  26. package/components/controls/phi-truncated-hover-text.js +25 -0
  27. package/components/forms/link-target-form-control.d.ts +1 -1
  28. package/components/forms/link-target-form-control.js +2 -45
  29. package/components/forms/phi-form-widget-frame.js +4 -2
  30. package/components/forms/shared-form-provider-registry.js +1 -4
  31. package/components/layouts/clients/phi-three-column-layout-client.js +10 -1
  32. package/components/media/asset-collection-runtime.js +6 -16
  33. package/components/media/media-font-metrics.d.ts +3 -0
  34. package/components/media/media-font-metrics.js +43 -0
  35. package/components/media/phi-area-upload-widget.js +53 -97
  36. package/components/media/phi-image-preview-data.d.ts +13 -0
  37. package/components/media/phi-image-preview-data.js +184 -9
  38. package/components/media/phi-media-picker-binding.js +16 -13
  39. package/components/media/phi-media-upload.d.ts +15 -8
  40. package/components/media/phi-media-upload.js +18 -9
  41. package/components/media/phi-site-font-assets.js +7 -8
  42. package/components/navigation/phi-link.js +6 -1
  43. package/components/overlays/phi-overlay-container-client.js +16 -1
  44. package/components/regions/clients/cms-region-container-client.js +6 -1
  45. package/components/regions/phi-cms-region-container.js +3 -0
  46. package/components/regions/phi-cms-region-shell.d.ts +12 -1
  47. package/components/regions/phi-cms-region-shell.js +81 -19
  48. package/components/regions/presets/phi-settings-page-shell-tree.js +48 -1
  49. package/components/root/phi-config-provider.d.ts +13 -0
  50. package/components/root/phi-config-provider.js +12 -1
  51. package/components/root/phi-root-background.d.ts +7 -0
  52. package/components/root/phi-root-background.js +20 -1
  53. package/components/root/phi-root-theme-resolver.js +3 -0
  54. package/components/root/phi-shell-chrome-overlay.d.ts +12 -1
  55. package/components/root/phi-shell-chrome-overlay.js +19 -3
  56. package/components/runtime/runtime-controller-materialization.js +12 -1
  57. package/components/shell/phi-antd-icon.d.ts +1 -0
  58. package/components/shell/phi-antd-icon.js +3 -0
  59. package/components/shell/use-phi-shell-sticky-top.js +61 -16
  60. package/components/state/scoped-state-store.js +20 -3
  61. package/components/surface/phi-surface-tone.d.ts +13 -0
  62. package/components/surface/phi-surface-tone.js +21 -0
  63. package/components/tables/client/phi-table-binding.d.ts +2 -1
  64. package/components/tables/client/phi-table-binding.js +45 -21
  65. package/components/trees/client/phi-tree-binding.js +19 -11
  66. package/components/widgets/client/bullet-list-entries-editor.d.ts +26 -0
  67. package/components/widgets/client/bullet-list-entries-editor.js +109 -0
  68. package/components/widgets/client/html-editor.js +1 -1
  69. package/components/widgets/client/shared/use-page-reference-options.d.ts +17 -0
  70. package/components/widgets/client/shared/use-page-reference-options.js +57 -0
  71. package/components/widgets/config/background.d.ts +32 -1
  72. package/components/widgets/config/background.js +41 -2
  73. package/components/widgets/config/choice-shared.js +12 -13
  74. package/components/widgets/config/command-buttons.d.ts +5 -1
  75. package/components/widgets/config/command-buttons.js +38 -81
  76. package/components/widgets/config/control-signal-config.d.ts +3 -1
  77. package/components/widgets/config/control-signal-config.js +19 -17
  78. package/components/widgets/config/image-source-parser.d.ts +1 -0
  79. package/components/widgets/config/image-source-parser.js +7 -8
  80. package/components/widgets/config/mask.d.ts +6 -1
  81. package/components/widgets/config/mask.js +24 -1
  82. package/components/widgets/config/parser-primitives.js +72 -0
  83. package/components/widgets/config/stack-tabs.d.ts +1 -1
  84. package/components/widgets/config/stack-tabs.js +2 -3
  85. package/components/widgets/config/strict-config-reader.d.ts +40 -0
  86. package/components/widgets/config/strict-config-reader.js +174 -0
  87. package/components/widgets/label-sets/background.js +2 -0
  88. package/components/widgets/label-sets/effects.js +2 -0
  89. package/components/widgets/label-types/background.d.ts +1 -0
  90. package/components/widgets/label-types/background.js +1 -0
  91. package/components/widgets/label-types/effects.d.ts +1 -0
  92. package/components/widgets/label-types/effects.js +1 -0
  93. package/components/widgets/navigation-descriptor-resolver.server.js +20 -8
  94. package/components/widgets/shared/bullet-list-vocabulary.d.ts +27 -1
  95. package/components/widgets/shared/bullet-list-vocabulary.js +24 -4
  96. package/components/widgets/shared/card-body-client.d.ts +18 -4
  97. package/components/widgets/shared/card-body-client.js +126 -26
  98. package/components/widgets/shared/card-vocabulary.d.ts +31 -4
  99. package/components/widgets/shared/card-vocabulary.js +35 -2
  100. package/components/widgets/shared/markdown-body-client.js +39 -10
  101. package/components/widgets/signals/control-signal-capabilities.d.ts +0 -18
  102. package/components/widgets/signals/control-signal-capabilities.js +10 -22
  103. package/components/workspace/catalog-store.d.ts +4 -3
  104. package/components/workspace/catalog-store.js +6 -5
  105. package/gateway/dashboard-cards-route.js +1 -0
  106. package/gateway/internal-references.d.ts +6 -1
  107. package/gateway/internal-references.js +48 -23
  108. package/gateway/site-cms-write-validation.d.ts +9 -0
  109. package/gateway/site-cms-write-validation.js +78 -0
  110. package/gateway/site-proxy.js +19 -3
  111. package/helpers/cms-container-chrome.js +6 -1
  112. package/helpers/locale.d.ts +8 -0
  113. package/helpers/locale.js +18 -0
  114. package/helpers/renderable-block-serialization.js +1 -1
  115. package/helpers/shell-region-style.js +2 -1
  116. package/helpers/surface-style.d.ts +12 -1
  117. package/helpers/surface-style.js +28 -2
  118. package/module-dashboard-cards.d.ts +1 -1
  119. package/module-dashboard-cards.js +1 -1
  120. package/next/config.d.mts +3 -0
  121. package/next/config.mjs +28 -1
  122. package/package.json +2 -2
  123. package/plugins/runtime/phi-slot-child-viewport-effects-observer.js +5 -1
  124. package/plugins/runtime-modules/accounting/presets.d.ts +9 -0
  125. package/plugins/runtime-modules/accounting/presets.js +37 -0
  126. package/plugins/runtime-modules/accounting/server.d.ts +1 -4
  127. package/plugins/runtime-modules/accounting/server.js +4 -7
  128. package/plugins/runtime-modules/app/presets.d.ts +18 -0
  129. package/plugins/runtime-modules/app/presets.js +67 -0
  130. package/plugins/runtime-modules/app/server.d.ts +1 -4
  131. package/plugins/runtime-modules/app/server.js +4 -7
  132. package/plugins/runtime-modules/area-definitions.d.ts +0 -42
  133. package/plugins/runtime-modules/area-definitions.js +3 -8
  134. package/plugins/runtime-modules/asset/controller/runtime.js +2 -2
  135. package/plugins/runtime-modules/asset/services/collection.js +9 -1
  136. package/plugins/runtime-modules/asset/services/options.js +2 -2
  137. package/plugins/runtime-modules/builder/area-settings-answer.js +2 -1
  138. package/plugins/runtime-modules/builder/authoring-canvas.js +6 -6
  139. package/plugins/runtime-modules/builder/cards.js +3 -5
  140. package/plugins/runtime-modules/builder/clients/builder-region-overrides.js +3 -3
  141. package/plugins/runtime-modules/builder/clients/canvas-widget.js +15 -54
  142. package/plugins/runtime-modules/builder/clients/inspector-config-field.d.ts +4 -1
  143. package/plugins/runtime-modules/builder/clients/inspector-config-field.js +25 -35
  144. package/plugins/runtime-modules/builder/clients/inspector-link-target-field.js +1 -1
  145. package/plugins/runtime-modules/builder/clients/inspector-section-widget.js +8 -8
  146. package/plugins/runtime-modules/builder/clients/inspector-title.js +6 -6
  147. package/plugins/runtime-modules/builder/clients/layout-inspector.d.ts +1 -1
  148. package/plugins/runtime-modules/builder/clients/layout-inspector.js +11 -25
  149. package/plugins/runtime-modules/builder/clients/layout-scaffold-overlays.js +10 -5
  150. package/plugins/runtime-modules/builder/clients/mode-switch.js +1 -1
  151. package/plugins/runtime-modules/builder/clients/pages-header.js +11 -11
  152. package/plugins/runtime-modules/builder/clients/pages-workspace.js +1 -1
  153. package/plugins/runtime-modules/builder/clients/region-visibility-fields.js +1 -1
  154. package/plugins/runtime-modules/builder/clients/runtime-module-authoring-boundary.js +1 -1
  155. package/plugins/runtime-modules/builder/clients/shells-workspace.js +15 -31
  156. package/plugins/runtime-modules/builder/clients/structure-canvas.js +1 -1
  157. package/plugins/runtime-modules/builder/clients/use-region-draft-hydration.d.ts +26 -0
  158. package/plugins/runtime-modules/builder/clients/use-region-draft-hydration.js +36 -0
  159. package/plugins/runtime-modules/builder/clients/widget-effects-editor.js +1 -1
  160. package/plugins/runtime-modules/builder/clients/widget-inspector.js +1 -0
  161. package/plugins/runtime-modules/builder/clients/workspace-scope-boundary.js +2 -2
  162. package/plugins/runtime-modules/builder/cms-instance-allocator.js +8 -28
  163. package/plugins/runtime-modules/builder/controller/client.d.ts +0 -15
  164. package/plugins/runtime-modules/builder/controller/definition.d.ts +0 -15
  165. package/plugins/runtime-modules/builder/controller/definition.js +0 -8
  166. package/plugins/runtime-modules/builder/controller/draft-command-controller.d.ts +1 -2
  167. package/plugins/runtime-modules/builder/controller/draft-command-controller.js +11 -30
  168. package/plugins/runtime-modules/builder/controller/draft-status-controller.js +15 -2
  169. package/plugins/runtime-modules/builder/controller/inspector-controller.d.ts +1 -2
  170. package/plugins/runtime-modules/builder/controller/inspector-controller.js +4 -7
  171. package/plugins/runtime-modules/builder/controller/page-controller.d.ts +1 -2
  172. package/plugins/runtime-modules/builder/controller/page-controller.js +16 -68
  173. package/plugins/runtime-modules/builder/controller/server-definition.d.ts +0 -15
  174. package/plugins/runtime-modules/builder/controller/signal-wiring-controller.d.ts +2 -5
  175. package/plugins/runtime-modules/builder/controller/signal-wiring-controller.js +6 -50
  176. package/plugins/runtime-modules/builder/controller/workspace-controller.d.ts +2 -3
  177. package/plugins/runtime-modules/builder/controller/workspace-controller.js +89 -153
  178. package/plugins/runtime-modules/builder/data-providers.d.ts +1 -0
  179. package/plugins/runtime-modules/builder/data-providers.js +1 -0
  180. package/plugins/runtime-modules/builder/definition.d.ts +1 -0
  181. package/plugins/runtime-modules/builder/developer-workspace-store.d.ts +64 -30
  182. package/plugins/runtime-modules/builder/developer-workspace-store.js +255 -61
  183. package/plugins/runtime-modules/builder/edit-scaffold-drawer.js +4 -3
  184. package/plugins/runtime-modules/builder/history.d.ts +3 -1
  185. package/plugins/runtime-modules/builder/options-providers.js +3 -2
  186. package/plugins/runtime-modules/builder/page-catalog-client.js +19 -7
  187. package/plugins/runtime-modules/builder/page-meta-form.js +1 -0
  188. package/plugins/runtime-modules/builder/page-references-provider.js +1 -1
  189. package/plugins/runtime-modules/builder/persistence.js +33 -69
  190. package/plugins/runtime-modules/builder/public-route-collisions.d.ts +2 -2
  191. package/plugins/runtime-modules/builder/public-route-collisions.js +6 -19
  192. package/plugins/runtime-modules/builder/render-root-node-preview.server.js +20 -3
  193. package/plugins/runtime-modules/builder/render-root-node-scaffold.js +28 -18
  194. package/plugins/runtime-modules/builder/runtime-module-selection.d.ts +2 -12
  195. package/plugins/runtime-modules/builder/runtime-module-selection.js +16 -42
  196. package/plugins/runtime-modules/builder/services/navigation-table.js +9 -15
  197. package/plugins/runtime-modules/builder/services/page-source-tree.js +8 -8
  198. package/plugins/runtime-modules/builder/services/runtime-modules-table.js +10 -10
  199. package/plugins/runtime-modules/builder/services/signal-routes-table.js +3 -3
  200. package/plugins/runtime-modules/builder/signal-route-selection.d.ts +1 -2
  201. package/plugins/runtime-modules/builder/signal-route-selection.js +2 -2
  202. package/plugins/runtime-modules/builder/signal-wiring-options.js +3 -2
  203. package/plugins/runtime-modules/builder/structure-dnd.js +8 -61
  204. package/plugins/runtime-modules/builder/trees/phi-default-builder-area-preset-tree.js +17 -10
  205. package/plugins/runtime-modules/builder/widgets/structure-region/built-in.js +27 -22
  206. package/plugins/runtime-modules/builder/workspace-catalog-actions.d.ts +55 -0
  207. package/plugins/runtime-modules/builder/workspace-catalog-actions.js +142 -0
  208. package/plugins/runtime-modules/client-authoring-module.d.ts +8 -1
  209. package/plugins/runtime-modules/client-authoring-module.js +13 -3
  210. package/plugins/runtime-modules/client-manifests/common.js +1 -1
  211. package/plugins/runtime-modules/{runtime-calendar-adapters.js → core/calendar-adapters.js} +2 -2
  212. package/plugins/runtime-modules/{client-calendar-adapters/core.js → core/client-calendar-adapters.js} +1 -1
  213. package/plugins/runtime-modules/core/content-entries/table.js +1 -1
  214. package/plugins/runtime-modules/core/data-providers.d.ts +3 -0
  215. package/plugins/runtime-modules/core/data-providers.js +2 -1
  216. package/plugins/runtime-modules/core/definition.d.ts +3 -0
  217. package/plugins/runtime-modules/core/definition.js +1 -1
  218. package/plugins/runtime-modules/core/messaging/data-providers.d.ts +1 -0
  219. package/plugins/runtime-modules/core/messaging/data-providers.js +1 -0
  220. package/plugins/runtime-modules/core/messaging/thread-inbox-table.js +1 -1
  221. package/plugins/runtime-modules/core/server.js +1 -1
  222. package/plugins/runtime-modules/core/themes.d.ts +44 -0
  223. package/plugins/runtime-modules/core/themes.js +12 -0
  224. package/plugins/runtime-modules/core/widgets/brand/client.d.ts +12 -3
  225. package/plugins/runtime-modules/core/widgets/brand/client.js +3 -11
  226. package/plugins/runtime-modules/core/widgets/brand/home.d.ts +15 -0
  227. package/plugins/runtime-modules/core/widgets/brand/home.js +18 -0
  228. package/plugins/runtime-modules/core/widgets/brand/plugin.js +3 -2
  229. package/plugins/runtime-modules/core/widgets/brand/server.d.ts +2 -2
  230. package/plugins/runtime-modules/core/widgets/brand/server.js +2 -2
  231. package/plugins/runtime-modules/core/widgets/card/collection-view-binding.js +25 -9
  232. package/plugins/runtime-modules/core/widgets/card/config.d.ts +301 -254
  233. package/plugins/runtime-modules/core/widgets/card/config.js +68 -3
  234. package/plugins/runtime-modules/core/widgets/card/editor.js +41 -4
  235. package/plugins/runtime-modules/core/widgets/card/server.d.ts +3 -0
  236. package/plugins/runtime-modules/core/widgets/card/server.js +32 -3
  237. package/plugins/runtime-modules/core/widgets/collection-view/asset-binding.js +7 -6
  238. package/plugins/runtime-modules/core/widgets/collection-view/config.js +9 -2
  239. package/plugins/runtime-modules/core/widgets/description/client.js +3 -3
  240. package/plugins/runtime-modules/core/widgets/description/config.d.ts +2 -25
  241. package/plugins/runtime-modules/core/widgets/description/editor.js +7 -63
  242. package/plugins/runtime-modules/core/widgets/description/server.js +3 -2
  243. package/plugins/runtime-modules/core/widgets/entry-list/config.d.ts +2 -25
  244. package/plugins/runtime-modules/core/widgets/gallery/config.d.ts +2 -25
  245. package/plugins/runtime-modules/core/widgets/header-navigation/client.js +2 -2
  246. package/plugins/runtime-modules/core/widgets/html/client.js +1 -1
  247. package/plugins/runtime-modules/core/widgets/image/config.js +2 -2
  248. package/plugins/runtime-modules/core/widgets/markdown/config.d.ts +320 -2
  249. package/plugins/runtime-modules/core/widgets/markdown/config.js +18 -4
  250. package/plugins/runtime-modules/core/widgets/markdown/editor.js +11 -4
  251. package/plugins/runtime-modules/core/widgets/markdown-toc/client.js +6 -1
  252. package/plugins/runtime-modules/core/widgets/markdown-toc/config.d.ts +14 -0
  253. package/plugins/runtime-modules/core/widgets/markdown-toc/config.js +14 -2
  254. package/plugins/runtime-modules/core/widgets/quick-links/authoring.js +7 -2
  255. package/plugins/runtime-modules/core/widgets/quick-links/client.js +2 -2
  256. package/plugins/runtime-modules/core/widgets/quick-links/items.d.ts +0 -2
  257. package/plugins/runtime-modules/core/widgets/quick-links/items.js +0 -15
  258. package/plugins/runtime-modules/core/widgets/result/config.d.ts +5 -25
  259. package/plugins/runtime-modules/core/widgets/result/config.js +2 -0
  260. package/plugins/runtime-modules/core/widgets/result/server.js +25 -19
  261. package/plugins/runtime-modules/core/widgets/sidebar-navigation/authoring.js +1 -1
  262. package/plugins/runtime-modules/core/widgets/sidebar-navigation/client.js +1 -1
  263. package/plugins/runtime-modules/core/widgets/simple-text/client.js +8 -3
  264. package/plugins/runtime-modules/core/widgets/simple-text/config.d.ts +2 -25
  265. package/plugins/runtime-modules/core/widgets/simple-text/editor.js +2 -2
  266. package/plugins/runtime-modules/core/widgets/slot-upload/client.js +11 -2
  267. package/plugins/runtime-modules/core/widgets/table/client.js +8 -4
  268. package/plugins/runtime-modules/core/widgets/table/config.d.ts +6 -83
  269. package/plugins/runtime-modules/core/widgets/table/config.js +302 -452
  270. package/plugins/runtime-modules/core/widgets/tree/config.js +5 -2
  271. package/plugins/runtime-modules/dashboard/card-rows.d.ts +7 -0
  272. package/plugins/runtime-modules/dashboard/card-rows.js +87 -0
  273. package/plugins/runtime-modules/dashboard/clients/dashboard-card-view.js +32 -12
  274. package/plugins/runtime-modules/dashboard/services/collection.js +17 -7
  275. package/plugins/runtime-modules/dashboard/trees/phi-default-builder-dashboard-page-tree.js +5 -40
  276. package/plugins/runtime-modules/groups/data-providers.d.ts +2 -0
  277. package/plugins/runtime-modules/groups/data-providers.js +3 -3
  278. package/plugins/runtime-modules/groups/definition.d.ts +2 -0
  279. package/plugins/runtime-modules/localization/data-providers.d.ts +3 -0
  280. package/plugins/runtime-modules/localization/data-providers.js +2 -0
  281. package/plugins/runtime-modules/localization/definition.d.ts +3 -0
  282. package/plugins/runtime-modules/localization/services/table.js +3 -7
  283. package/plugins/runtime-modules/observability/data-providers.d.ts +1 -0
  284. package/plugins/runtime-modules/observability/data-providers.js +1 -0
  285. package/plugins/runtime-modules/observability/definition.d.ts +1 -0
  286. package/plugins/runtime-modules/observability/module.d.ts +1 -0
  287. package/plugins/runtime-modules/observability/services/table.js +1 -1
  288. package/plugins/runtime-modules/phi-default-site-area-preset-tree.js +2 -105
  289. package/plugins/runtime-modules/public/presets.d.ts +115 -0
  290. package/plugins/runtime-modules/{area-base-presets.js → public/presets.js} +19 -119
  291. package/plugins/runtime-modules/public/server.d.ts +1 -4
  292. package/plugins/runtime-modules/public/server.js +4 -7
  293. package/plugins/runtime-modules/public/trees/phi-default-pub-error-page-tree.js +7 -8
  294. package/plugins/runtime-modules/public-base-page-references.d.ts +1 -1
  295. package/plugins/runtime-modules/public-base-page-references.js +1 -1
  296. package/plugins/runtime-modules/revisions/controller/client.js +11 -11
  297. package/plugins/runtime-modules/revisions/services/table.js +3 -3
  298. package/plugins/runtime-modules/theme/trees/phi-default-builder-theme-page-tree.js +22 -0
  299. package/plugins/runtime-modules/theme/widgets/brand-controls/client.d.ts +2 -1
  300. package/plugins/runtime-modules/theme/widgets/brand-controls/client.js +111 -72
  301. package/plugins/runtime-modules/theme/widgets/brand-controls/config.d.ts +2 -1
  302. package/plugins/runtime-modules/theme/widgets/brand-controls/config.js +28 -31
  303. package/plugins/runtime-modules/theme/widgets/brand-controls/plugin.js +1 -1
  304. package/plugins/runtime-modules/theme-descriptors.js +1 -1
  305. package/plugins/runtime-modules/user-management/data-providers.d.ts +2 -0
  306. package/plugins/runtime-modules/user-management/data-providers.js +1 -0
  307. package/plugins/runtime-modules/user-management/definition.d.ts +2 -0
  308. package/server-helpers/cms-link-targets.js +6 -0
  309. package/styles/control-shape.css +11 -11
  310. package/styles/controls.css +67 -5
  311. package/styles/layout.css +61 -9
  312. package/styles/shell.css +73 -0
  313. package/theme/phi-antd-token-resolver.js +20 -1
  314. package/theme/phi-theme-tokens.d.ts +1 -1
  315. package/theme/phi-theme-tokens.js +1 -0
  316. package/theme/phi-theme.d.ts +5 -0
  317. package/theme/phi-theme.js +21 -0
  318. package/theme/phi-tokens.d.ts +16 -15
  319. package/theme/phi-tokens.js +16 -15
  320. package/types/cms-config.js +142 -185
  321. package/types/cms-plugins.d.ts +6 -11
  322. package/types/core-widget-placements.d.ts +14 -3
  323. package/types/dashboard-cards.d.ts +48 -4
  324. package/types/dashboard-cards.js +6 -0
  325. package/types/media.d.ts +0 -3
  326. package/types/renderable-block.d.ts +6 -1
  327. package/types/site-theme.d.ts +10 -2
  328. package/types/table-widget.d.ts +9 -0
  329. package/types/table-widget.js +20 -0
  330. package/types.d.ts +1 -1
  331. package/widget-config.d.ts +2 -0
  332. package/widget-config.js +6 -0
  333. package/plugins/runtime-modules/area-base-presets.d.ts +0 -139
  334. /package/plugins/runtime-modules/{runtime-calendar-adapters.d.ts → core/calendar-adapters.d.ts} +0 -0
  335. /package/plugins/runtime-modules/{client-calendar-adapters/core.d.ts → core/client-calendar-adapters.d.ts} +0 -0
@@ -13,8 +13,10 @@ import { resolvePhiCmsRegionType } from "../../../helpers/cms-region-keys";
13
13
  import { resolvePhiAuthUiProviderModuleId, resolvePhiDeclaredMediaSpaces, resolvePhiDeclaredSeeds, resolvePhiDeclaredThreadKinds, resolvePhiRuntimeModuleIdsForArea, } from "../../../plugins/runtime-modules/settings";
14
14
  import { isPhiRuntimeAreaBaseModuleId } from "../../../plugins/runtime-modules/area-definitions";
15
15
  import { createPhiBuilderDraftAllocationKey } from "./draft-allocation-key";
16
- import { builderWorkspaceStore, commitPhiDeveloperBuilderAreaConfig, readPhiBuilderEffectiveAreaRootRoute, readPhiBuilderEffectiveAreaMeta, } from "./developer-workspace-store";
16
+ import { clearPhiBuilderDraftAllocation, storePhiBuilderDraftAllocation, commitPhiDeveloperBuilderAreaConfig, readPhiBuilderEffectiveAreaRootRoute, readPhiBuilderEffectiveAreaMeta, } from "./developer-workspace-store";
17
17
  import { resolvePhiBuilderActivePageCatalog, resolvePhiBuilderPageDefaultFlags, resolvePhiBuilderPagePresetSource, } from "../../../helpers/cms-page-catalog";
18
+ import { isPhiRuntimeModuleId } from "../../../constants/module-identity";
19
+ import { createPhiResponseReader, requirePhiField } from "../../../components/widgets/config/strict-config-reader";
18
20
  import { PHI_AREA_CONFIG_MODULES_NAMESPACE, PHI_AREA_CONFIG_SHELL_NAMESPACE, PHI_AREA_PUBLIC_ROUTE_PATHS_KEY, PHI_AREA_ROOT_ROUTE_KEY, PHI_AREA_META_KEY, normalizePhiAreaPublicRoutePaths, } from "../../../helpers/cms-area-config";
19
21
  /**
20
22
  * A save that was refused because there is nothing to patch yet -- an Area with no stored revision at
@@ -194,22 +196,33 @@ async function postCmsDraft(path, payload) {
194
196
  const addressRefused = body?.error === "path_collision" || body?.error === "path_nested";
195
197
  throw response.status === 409 && !addressRefused ? new CmsDraftConflictError(message) : new Error(message);
196
198
  }
197
- if (!Number.isSafeInteger(body?.revisionId) ||
198
- body?.revisionId < 1 ||
199
- !Number.isSafeInteger(body?.version) ||
200
- body?.version < 1 ||
201
- !Number.isSafeInteger(body?.nextNodeSequence) ||
202
- body?.nextNodeSequence < 1) {
203
- throw new Error("CMS draft save returned invalid Draft allocation metadata.");
204
- }
205
- if (!Object.prototype.hasOwnProperty.call(body, "sourcePreset")) {
206
- throw new Error("CMS draft save returned no preset source metadata.");
207
- }
199
+ return readPhiDraftAllocation(body, "The CMS draft save");
200
+ }
201
+ /**
202
+ * What a Draft save or read answers about the Draft it now stands on: its revision, version and node
203
+ * sequence, all positive, and the preset it came from -- stated as `null` when it came from none, never
204
+ * left out. Read field by field; each was checked before and then cast, and the preset source was not
205
+ * checked at all.
206
+ */
207
+ function readPhiDraftAllocation(body, source) {
208
+ const reader = createPhiResponseReader(body, source);
209
+ const positive = (key) => {
210
+ const value = requirePhiField(reader, key, "a positive whole number", reader.integer);
211
+ return value >= 1 ? value : reader.fail(key, "a positive whole number");
212
+ };
213
+ if (!Object.prototype.hasOwnProperty.call(reader.record, "sourcePreset")) {
214
+ reader.fail("sourcePreset", "a preset source or null");
215
+ }
216
+ const sourcePreset = reader.object("sourcePreset", (preset) => ({
217
+ ownerModuleId: requirePhiField(preset, "ownerModuleId", "a Module id", (key) => preset.value(key, "a Module id", (value) => (isPhiRuntimeModuleId(value) ? value : undefined))),
218
+ presetKey: requirePhiField(preset, "presetKey", "a text", preset.string),
219
+ sourcePresetVersion: requirePhiField(preset, "sourcePresetVersion", "a whole number", preset.integer),
220
+ })) ?? null;
208
221
  return {
209
- revisionId: body.revisionId,
210
- version: body.version,
211
- nextNodeSequence: body.nextNodeSequence,
212
- sourcePreset: body.sourcePreset ?? null,
222
+ revisionId: positive("revisionId"),
223
+ version: positive("version"),
224
+ nextNodeSequence: positive("nextNodeSequence"),
225
+ sourcePreset,
213
226
  };
214
227
  }
215
228
  async function postCmsAction(path, payload) {
@@ -247,23 +260,7 @@ async function getCmsDraft(path, payload) {
247
260
  const detail = body?.details?.length ? ` ${body.details.join(" ")}` : "";
248
261
  throw new Error(`${body?.error ?? "CMS draft read failed."}${detail}`);
249
262
  }
250
- if (!Number.isSafeInteger(body?.revisionId) ||
251
- body?.revisionId < 1 ||
252
- !Number.isSafeInteger(body?.version) ||
253
- body?.version < 1 ||
254
- !Number.isSafeInteger(body?.nextNodeSequence) ||
255
- body?.nextNodeSequence < 1) {
256
- throw new Error("CMS draft read returned invalid Draft allocation metadata.");
257
- }
258
- if (!Object.prototype.hasOwnProperty.call(body, "sourcePreset")) {
259
- throw new Error("CMS draft read returned no preset source metadata.");
260
- }
261
- return {
262
- revisionId: body.revisionId,
263
- version: body.version,
264
- nextNodeSequence: body.nextNodeSequence,
265
- sourcePreset: body.sourcePreset ?? null,
266
- };
263
+ return readPhiDraftAllocation(body, "The CMS draft read");
267
264
  }
268
265
  /**
269
266
  * The href a preview opens, with no locale in it.
@@ -294,37 +291,11 @@ export function buildPhiBuilderLiveHref(area, pageKey, pages, workspaceKind) {
294
291
  return `${url.pathname}${url.search}${url.hash}`;
295
292
  }
296
293
  function storePhiDeveloperBuilderDraftAllocation(allocationKey, saved) {
297
- builderWorkspaceStore.patch("public", (current) => {
298
- const currentAllocation = current.draftAllocations[allocationKey];
299
- const nextNodeSequence = currentAllocation?.revisionId === saved.revisionId
300
- ? Math.max(currentAllocation.nextNodeSequence, saved.nextNodeSequence)
301
- : saved.nextNodeSequence;
302
- return {
303
- ...current,
304
- draftAllocations: {
305
- ...current.draftAllocations,
306
- [allocationKey]: {
307
- revisionId: saved.revisionId,
308
- version: currentAllocation?.revisionId === saved.revisionId
309
- ? Math.max(currentAllocation.version, saved.version)
310
- : saved.version,
311
- nextNodeSequence,
312
- sourcePreset: saved.sourcePreset,
313
- },
314
- },
315
- };
316
- });
294
+ storePhiBuilderDraftAllocation(allocationKey, saved);
317
295
  }
318
296
  export function clearPhiDeveloperBuilderDraftAllocation(input) {
319
297
  const allocationKey = createPhiBuilderDraftAllocationKey(input.area, input.pageKey, input.workspaceKind === "pages" ? "page" : "area");
320
- builderWorkspaceStore.patch("public", (current) => {
321
- if (!current.draftAllocations[allocationKey]) {
322
- return current;
323
- }
324
- const draftAllocations = { ...current.draftAllocations };
325
- delete draftAllocations[allocationKey];
326
- return { ...current, draftAllocations };
327
- });
298
+ clearPhiBuilderDraftAllocation(allocationKey);
328
299
  }
329
300
  export async function getPhiDeveloperBuilderDraftAllocation(input) {
330
301
  const cmsArea = resolvePhiBuilderAreaAsCmsArea(input.area);
@@ -368,14 +339,7 @@ export async function getPhiDeveloperBuilderModulesDraftAllocation(input) {
368
339
  }
369
340
  function clearPhiDeveloperBuilderModulesDraftAllocation(area) {
370
341
  const allocationKey = createPhiBuilderDraftAllocationKey(area, area, "modules");
371
- builderWorkspaceStore.patch("public", (current) => {
372
- if (!current.draftAllocations[allocationKey]) {
373
- return current;
374
- }
375
- const draftAllocations = { ...current.draftAllocations };
376
- delete draftAllocations[allocationKey];
377
- return { ...current, draftAllocations };
378
- });
342
+ clearPhiBuilderDraftAllocation(allocationKey);
379
343
  }
380
344
  /**
381
345
  * What a tree tells its Controllers, as it arrived with the workspace. The Builder edits none of it but
@@ -1,5 +1,5 @@
1
1
  import type { PhiRuntimeModuleId } from "../../../types";
2
- import type { PhiBuilderPublicRouteCollisionAnswer, PhiBuilderPublicRouteCollisionRequest, PhiDeveloperBuilderArea, PhiDeveloperBuilderWorkspaceState } from "./developer-workspace-types";
2
+ import type { PhiBuilderPublicRouteCollisionAnswer, PhiBuilderPublicRouteCollisionRequest, PhiDeveloperBuilderWorkspaceState } from "./developer-workspace-types";
3
3
  /**
4
4
  * The question to put to the Builder before a Module may be enabled for Public.
5
5
  *
@@ -22,4 +22,4 @@ export declare function findPhiBuilderPublicRouteAnswerProblem(state: Pick<PhiDe
22
22
  * alone, including those of Modules that are switched off -- an assignment outlives its Module being
23
23
  * disabled, which is why nobody is asked the same question twice.
24
24
  */
25
- export declare function applyPhiBuilderPublicRouteAssignments(scopeKey: PhiDeveloperBuilderArea, request: Pick<PhiBuilderPublicRouteCollisionRequest, "moduleId" | "answers">): void;
25
+ export declare function applyPhiBuilderPublicRouteAssignments(request: Pick<PhiBuilderPublicRouteCollisionRequest, "moduleId" | "answers">): void;
@@ -1,8 +1,8 @@
1
1
  import { buildPhiRuntimeModulePackageRoutePrefix } from "../../../helpers/runtime-module-route-path";
2
2
  import { buildPhiPublicRouteAddressMap, findPhiPublicRoutePathCollisions, } from "../../../helpers/public-route-claims";
3
- import { isPhiAssignablePublicRoutePath, normalizePhiAreaPublicRoutePaths, } from "../../../helpers/cms-area-config";
4
- import { phiWorkspaceCatalogStore } from "../../../components/workspace/catalog-store";
5
- import { markPhiBuilderModuleAreasDirty } from "./runtime-module-selection";
3
+ import { isPhiAssignablePublicRoutePath, } from "../../../helpers/cms-area-config";
4
+ import { assignPhiWorkspacePublicRoutePaths } from "./workspace-catalog-actions";
5
+ import { markPhiBuilderModuleAreasDirty } from "./developer-workspace-store";
6
6
  /**
7
7
  * Which Public addresses a Site Page already occupies.
8
8
  *
@@ -121,21 +121,8 @@ export function findPhiBuilderPublicRouteAnswerProblem(state, request) {
121
121
  * alone, including those of Modules that are switched off -- an assignment outlives its Module being
122
122
  * disabled, which is why nobody is asked the same question twice.
123
123
  */
124
- export function applyPhiBuilderPublicRouteAssignments(scopeKey, request) {
124
+ export function applyPhiBuilderPublicRouteAssignments(request) {
125
125
  const answered = new Map(request.answers.map((answer) => [answer.presetKey, answer.path.trim()]));
126
- phiWorkspaceCatalogStore.patch(scopeKey, (catalog) => {
127
- const kept = (catalog.publicRoutePaths ?? []).filter((assignment) => assignment.ownerModuleId !== request.moduleId || !answered.has(assignment.presetKey));
128
- return {
129
- ...catalog,
130
- publicRoutePaths: normalizePhiAreaPublicRoutePaths([
131
- ...kept,
132
- ...[...answered.entries()].map(([presetKey, path]) => ({
133
- ownerModuleId: request.moduleId,
134
- presetKey,
135
- path,
136
- })),
137
- ]),
138
- };
139
- });
140
- markPhiBuilderModuleAreasDirty(["public"], scopeKey);
126
+ assignPhiWorkspacePublicRoutePaths(request.moduleId, answered);
127
+ markPhiBuilderModuleAreasDirty(["public"]);
141
128
  }
@@ -46,12 +46,29 @@ function mergePreviewTreeNodes(tree, extraPreviewNodes) {
46
46
  function resolveRootNodeFromPreviewDraft(draft) {
47
47
  return draft?.rootNode ? readPhiBuilderRootNodeDraft(draft.rootNode) : null;
48
48
  }
49
+ /*
50
+ * The nodes of every Region in one preview snapshot, built once per snapshot.
51
+ *
52
+ * Each of the ten Region previews needs all of them -- a signal route may name a node in another Region
53
+ * -- and each used to build every Region's tree again: about a hundred tree builds for one preview
54
+ * request. A snapshot is one parsed object per request and nothing here writes the result, so it is kept
55
+ * by that object and dropped with it.
56
+ */
57
+ const previewSnapshotNodes = new WeakMap();
49
58
  function buildPreviewSnapshotNodes(snapshot) {
50
- const layoutNodes = [];
51
- const contentWidgets = [];
52
59
  if (!snapshot) {
53
- return { layoutNodes, contentWidgets };
60
+ return { layoutNodes: [], contentWidgets: [] };
61
+ }
62
+ let nodes = previewSnapshotNodes.get(snapshot);
63
+ if (!nodes) {
64
+ nodes = collectPreviewSnapshotNodes(snapshot);
65
+ previewSnapshotNodes.set(snapshot, nodes);
54
66
  }
67
+ return nodes;
68
+ }
69
+ function collectPreviewSnapshotNodes(snapshot) {
70
+ const layoutNodes = [];
71
+ const contentWidgets = [];
55
72
  for (const [draftKey, draft] of Object.entries(snapshot.regionDrafts)) {
56
73
  const regionKey = draftKey.split(":").at(-1);
57
74
  const rootNode = resolveRootNodeFromPreviewDraft(draft);
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { cloneElement, isValidElement, Suspense, useCallback, useEffect, useRef, useState } from "react";
4
- import { usePhiConfig } from "../../../components/root/phi-config-provider";
4
+ import { usePhiPageModeToken } from "../../../components/root/phi-config-provider";
5
+ import { usePhiPageModeTone } from "../../../components/surface/phi-surface-tone";
5
6
  import { PhiEditScaffoldDrawer } from "./edit-scaffold-drawer";
6
7
  import { comparePhiCmsInstanceIds } from "../../../types/cms-instance-id";
7
8
  import { PhiSlotChildFrame } from "../../../plugins/runtime/phi-slot-child-frame";
@@ -10,7 +11,7 @@ import { PhiPlusButtonWidget, } from "./clients/layout-scaffold-buttons";
10
11
  import { usePhiStructureDroppable, } from "./structure-dnd";
11
12
  import { PhiInlineTextEditor } from "../../../components/controls/phi-inline-text-editor";
12
13
  import { PhiButtonControl } from "../../../components/controls/phi-button-control";
13
- import { usePhiAuthoringLayoutDefinition, usePhiRuntimeModuleAuthoringRegistration, } from "../../../plugins/runtime-modules/client-authoring-module";
14
+ import { usePhiAuthoringLayoutDefinitionResolver, usePhiRuntimeModuleAuthoringRegistration, } from "../../../plugins/runtime-modules/client-authoring-module";
14
15
  import { usePhiRuntimeModuleState } from "../../../components/runtime/runtime-module-context";
15
16
  import { PhiCmsRenderDiagnostic } from "../../../components/cms/phi-cms-render-diagnostic";
16
17
  import { PhiCmsRenderErrorBoundary } from "../../../components/cms/phi-cms-render-error-boundary";
@@ -116,7 +117,8 @@ function PhiAuthoringWidgetLoader({ widget, config, slotSizePolicy, demandContro
116
117
  function PhiAuthoringLayoutLoader({ type, kind, blockId, children, }) {
117
118
  const activeModules = usePhiRuntimeModuleState();
118
119
  const layoutType = resolvePhiAuthoringLayoutType(type);
119
- const definition = usePhiAuthoringLayoutDefinition(layoutType);
120
+ const resolveLayoutDefinition = usePhiAuthoringLayoutDefinitionResolver();
121
+ const definition = resolveLayoutDefinition(layoutType);
120
122
  if (!definition) {
121
123
  return _jsx(PhiCmsRenderDiagnostic, { issue: {
122
124
  code: "missing-renderer",
@@ -138,7 +140,7 @@ function PhiAuthoringLayoutLoader({ type, kind, blockId, children, }) {
138
140
  } });
139
141
  }
140
142
  const LazyAuthoringLayout = definition.component;
141
- return (_jsx(PhiCmsRenderErrorBoundary, { kind: kind, blockId: blockId, typeKey: type, moduleId: definition.ownerModuleId, children: _jsx(Suspense, { fallback: null, children: _jsx(LazyAuthoringLayout, { children: (plugin) => children(plugin, definition, activeModules.widgetDefinitionsByType) }) }) }));
143
+ return (_jsx(PhiCmsRenderErrorBoundary, { kind: kind, blockId: blockId, typeKey: type, moduleId: definition.ownerModuleId, children: _jsx(Suspense, { fallback: null, children: _jsx(LazyAuthoringLayout, { children: (plugin) => children(plugin, definition, activeModules.widgetDefinitionsByType, resolveLayoutDefinition) }) }) }));
142
144
  }
143
145
  function resolveRootNodeEditSlotAnchor(rootNode) {
144
146
  return rootNode.editSlotAnchor ?? undefined;
@@ -206,10 +208,12 @@ function resolveEffectsPreviewDurationMs(config) {
206
208
  }
207
209
  function PhiEffectsPreviewButton({ config, blockKind, onRun, }) {
208
210
  const previewLabel = formatEffectsPreviewLabel(config, blockKind);
211
+ // In the editor's mode, not a tone's: the button is the Builder's, whatever mode the Widget is drawn in.
212
+ const pageModeTone = usePhiPageModeTone();
209
213
  return (_jsx("span", { style: { display: "contents" }, onMouseDown: (event) => {
210
214
  event.preventDefault();
211
215
  event.stopPropagation();
212
- }, onClick: (event) => event.stopPropagation(), children: _jsx(PhiButtonControl, { className: "phi-layout-affordance phi-layout-affordance--effects-preview", ariaLabel: previewLabel, tooltip: previewLabel, icon: _jsx(PhiIcon, { name: "node-index", size: "inherit" }), type: "text", size: "small", onClick: onRun, style: {
216
+ }, onClick: (event) => event.stopPropagation(), children: pageModeTone.wrap(_jsx(PhiButtonControl, { className: "phi-layout-affordance phi-layout-affordance--effects-preview", ariaLabel: previewLabel, tooltip: previewLabel, icon: _jsx(PhiIcon, { name: "node-index", size: "inherit" }), type: "text", size: "small", onClick: onRun, style: {
213
217
  position: "absolute",
214
218
  top: "50%",
215
219
  left: "50%",
@@ -219,7 +223,7 @@ function PhiEffectsPreviewButton({ config, blockKind, onRun, }) {
219
223
  // whose children `styles/layout.css` stretches, and a stylesheet answer did not hold there.
220
224
  width: "var(--ant-control-height)",
221
225
  "--phi-layout-affordance-size": "var(--ant-control-height)",
222
- } }) }));
226
+ } })) }));
223
227
  }
224
228
  function PhiSignalWiringToolButton({ onOpen }) {
225
229
  return (_jsx("span", { style: { display: "contents" }, onPointerDown: (event) => {
@@ -264,8 +268,9 @@ function findPhiWidgetAuthoringTextTarget(container, clientX, clientY) {
264
268
  }) ?? null;
265
269
  }
266
270
  function PhiWidgetEffectsPreviewFrame({ kind, slotSizePolicy, surfacePolicy, blockId, regionKey, config: committedConfig, title, scaffoldLabel, editorInteraction = "inert", onSelect, dropTarget, tools, style, children, }) {
267
- const { token } = usePhiConfig();
268
- const selected = usePhiDeveloperBuilderStateValue("public", (state) => blockId != null &&
271
+ // The editor's colours, not a tone's: a Widget inside a toned Surface is marked in the page's mode.
272
+ const token = usePhiPageModeToken();
273
+ const selected = usePhiDeveloperBuilderStateValue((state) => blockId != null &&
269
274
  regionKey != null &&
270
275
  state.selectedRootRegionKey === regionKey &&
271
276
  state.nodeKind === "widget" &&
@@ -278,7 +283,7 @@ function PhiWidgetEffectsPreviewFrame({ kind, slotSizePolicy, surfacePolicy, blo
278
283
  * still under the finger; the draft learns it when Save is pressed. Overlaying the whole `effects`
279
284
  * rather than one property keeps this the editor's picture and not a second opinion about it.
280
285
  */
281
- const effectsPreview = usePhiDeveloperBuilderStateValue("public", (state) => readPhiDeveloperBuilderEffectsPreview(state, "widget", blockId ?? null));
286
+ const effectsPreview = usePhiDeveloperBuilderStateValue((state) => readPhiDeveloperBuilderEffectsPreview(state, "widget", blockId ?? null));
282
287
  const config = effectsPreview
283
288
  ? { ...committedConfig, effects: effectsPreview }
284
289
  : committedConfig;
@@ -493,7 +498,7 @@ function PhiWidgetEffectsPreviewFrame({ kind, slotSizePolicy, surfacePolicy, blo
493
498
  }
494
499
  function PhiLayoutEffectsPreviewFrame({ kind, slotSizePolicy, blockId, config: committedConfig, explicitInlineSize, explicitBlockSize, children, }) {
495
500
  // The same live picture the Widget frame draws, for the Layout whose own toolbar opened the editor.
496
- const effectsPreview = usePhiDeveloperBuilderStateValue("public", (state) => readPhiDeveloperBuilderEffectsPreview(state, "layout", blockId ?? null));
501
+ const effectsPreview = usePhiDeveloperBuilderStateValue((state) => readPhiDeveloperBuilderEffectsPreview(state, "layout", blockId ?? null));
497
502
  const config = effectsPreview
498
503
  ? { ...committedConfig, effects: effectsPreview }
499
504
  : committedConfig;
@@ -525,10 +530,6 @@ function PhiLayoutEffectsPreviewFrame({ kind, slotSizePolicy, blockId, config: c
525
530
  });
526
531
  } })) : null] }, hasPreviewEffects ? `layout-effects-preview-${blockId ?? "root"}-${previewRunId}` : undefined));
527
532
  }
528
- function PhiAuthoringLayoutEffectsPreviewFrame({ type, ...props }) {
529
- const definition = usePhiAuthoringLayoutDefinition(resolvePhiAuthoringLayoutType(type));
530
- return (_jsx(PhiLayoutEffectsPreviewFrame, { ...props, slotSizePolicy: definition?.slotSizePolicy }));
531
- }
532
533
  /**
533
534
  * The band under a scaffold: what this node is called, and then what it is.
534
535
  *
@@ -821,11 +822,20 @@ export function renderPhiRootNodeScaffold(rootNode, onOpenInsert, onOpenInspecto
821
822
  nodeKind: normalizedRootNode.kind,
822
823
  })
823
824
  : undefined, chrome: renderRootScaffoldToolbar(), children: wrapRootScaffoldChild(child) }));
824
- const renderChildLayoutNode = (node) => {
825
+ /*
826
+ * A nested Layout's frame states its policy on the element the parent Layout sizes its slot by.
827
+ *
828
+ * It was looked up inside that element, which is too late: the parent reads the element's props
829
+ * before it renders, found a Layout with no policy, took the Layout default -- fill both ways -- and
830
+ * let the slot grow and shrink in its column. A Grid of cards in a Flex was squeezed below its
831
+ * content on the canvas and the cards ran out of their scaffold, while the page laid it out at its
832
+ * content height, as its `fill-inline` says.
833
+ */
834
+ const renderChildLayoutNodeWith = (resolveLayoutDefinition) => function renderChildLayoutNode(node) {
825
835
  const nodeKind = "layout";
826
836
  const rootProps = resolveLayoutNodeRootProps(node);
827
837
  const rootPropsGeometry = resolvePhiRenderableBlockGeometry(normalizePhiBuilderRootNodeDraft(rootProps).rootNodeGeometry);
828
- return (_jsx(PhiAuthoringLayoutEffectsPreviewFrame, { type: node.widgetType, kind: nodeKind, blockId: node.id, config: node.config, explicitInlineSize: rootPropsGeometry.explicitInline, explicitBlockSize: rootPropsGeometry.explicitBlock, children: renderPhiRootNodeScaffold({ ...rootProps, regionKey }, (options) => onOpenInsert?.({
838
+ return (_jsx(PhiLayoutEffectsPreviewFrame, { kind: nodeKind, slotSizePolicy: resolveLayoutDefinition(resolvePhiAuthoringLayoutType(node.widgetType))?.slotSizePolicy, blockId: node.id, config: node.config, explicitInlineSize: rootPropsGeometry.explicitInline, explicitBlockSize: rootPropsGeometry.explicitBlock, children: renderPhiRootNodeScaffold({ ...rootProps, regionKey }, (options) => onOpenInsert?.({
829
839
  ...options,
830
840
  slotIndex: options?.slotIndex ?? 0,
831
841
  targetNodeId: node.id,
@@ -861,8 +871,8 @@ export function renderPhiRootNodeScaffold(rootNode, onOpenInsert, onOpenInspecto
861
871
  renderInsertPicker: options?.renderInsertPicker,
862
872
  }) }));
863
873
  };
864
- const scaffold = (_jsx(PhiAuthoringLayoutLoader, { type: normalizedRootNode.typeKey, kind: "layout", blockId: normalizedRootNode.id ?? -1, children: (plugin, definition, widgetDefinitionsByType) => {
865
- const rendered = resolvePhiRootNodeRenderedBody(normalizedRootNode, "editor", plugin, definition, widgetDefinitionsByType, regionKey, renderChildLayoutNode, onDeleteRootNode
874
+ const scaffold = (_jsx(PhiAuthoringLayoutLoader, { type: normalizedRootNode.typeKey, kind: "layout", blockId: normalizedRootNode.id ?? -1, children: (plugin, definition, widgetDefinitionsByType, resolveLayoutDefinition) => {
875
+ const rendered = resolvePhiRootNodeRenderedBody(normalizedRootNode, "editor", plugin, definition, widgetDefinitionsByType, regionKey, renderChildLayoutNodeWith(resolveLayoutDefinition), onDeleteRootNode
866
876
  ? (widget) => onDeleteRootNode({
867
877
  nodeId: widget.id,
868
878
  nodeKey: widget.widgetType,
@@ -1,6 +1,4 @@
1
- import type { PhiRuntimeModuleId } from "../../../types";
2
1
  import type { PhiDeveloperBuilderArea } from "./developer-workspace-types";
3
- export declare function areRuntimeModuleIdsEqual(left: readonly PhiRuntimeModuleId[] | null | undefined, right: readonly PhiRuntimeModuleId[] | null | undefined): boolean;
4
2
  /**
5
3
  * Applies a new Module selection to one or more Areas: validates each Area's list, patches the
6
4
  * catalog, and records the whole gesture as ONE history entry -- the one place all of this happens,
@@ -15,13 +13,5 @@ export declare function areRuntimeModuleIdsEqual(left: readonly PhiRuntimeModule
15
13
  export declare function applyPhiBuilderRuntimeModuleSelectionChanges(changes: ReadonlyArray<{
16
14
  area: PhiDeveloperBuilderArea;
17
15
  selectedIds: readonly string[];
18
- }>, defaultArea: PhiDeveloperBuilderArea): void;
19
- export declare function applyPhiBuilderRuntimeModuleSelectionChange(area: PhiDeveloperBuilderArea, selectedIds: readonly string[], defaultArea: PhiDeveloperBuilderArea): `${string}/${string}`[];
20
- /**
21
- * The Areas whose Module selection has unsaved edits, kept as Builder tool state so the Modules
22
- * workspace commands know which Areas a site-wide save or publish has to reach. Undo does not clear
23
- * an Area from here -- a save of an unchanged selection is a no-op draft, while a missed Area would
24
- * silently publish stale state.
25
- */
26
- export declare function markPhiBuilderModuleAreasDirty(areas: readonly PhiDeveloperBuilderArea[], defaultArea: PhiDeveloperBuilderArea): void;
27
- export declare function clearPhiBuilderModuleAreasDirty(defaultArea: PhiDeveloperBuilderArea): void;
16
+ }>): void;
17
+ export declare function applyPhiBuilderRuntimeModuleSelectionChange(area: PhiDeveloperBuilderArea, selectedIds: readonly string[]): `${string}/${string}`[];
@@ -1,13 +1,13 @@
1
1
  import { resolvePhiBuilderAreaAsCmsArea } from "../../../constants/cms-areas";
2
2
  import { isPhiRuntimeAreaBaseModuleId, resolvePhiRuntimeAreaDefinition, } from "../area-definitions";
3
3
  import { assertPhiRuntimeModuleIdsAllowedForArea } from "../settings";
4
- import { phiWorkspaceCatalogStore } from "../../../components/workspace/catalog-store";
5
- import { builderWorkspaceStore, getPhiDeveloperBuilderStateSnapshot } from "./developer-workspace-store";
4
+ import { getPhiDeveloperBuilderStateSnapshot, markPhiBuilderModuleAreasDirty } from "./developer-workspace-store";
5
+ import { setPhiWorkspaceModuleSelection } from "./workspace-catalog-actions";
6
6
  import { capturePhiBuilderModulesHistoryState, createPhiBuilderHistoryContext, phiBuilderHistory, } from "./history";
7
7
  function serializeRuntimeModuleIds(moduleIds) {
8
8
  return JSON.stringify(moduleIds ?? []);
9
9
  }
10
- export function areRuntimeModuleIdsEqual(left, right) {
10
+ function areRuntimeModuleIdsEqual(left, right) {
11
11
  return serializeRuntimeModuleIds(left) === serializeRuntimeModuleIds(right);
12
12
  }
13
13
  /**
@@ -52,8 +52,8 @@ function normalizeRuntimeModuleSelection(selectedIds, area, definitions) {
52
52
  * switched on in one Area and off in another is named once; the step's sentence says that the
53
53
  * selection of these changed, not which way.
54
54
  */
55
- function describeModuleSelectionChange(effective, before, defaultArea) {
56
- const definitions = getPhiDeveloperBuilderStateSnapshot(defaultArea).runtimeModuleDefinitions;
55
+ function describeModuleSelectionChange(effective, before) {
56
+ const definitions = getPhiDeveloperBuilderStateSnapshot().runtimeModuleDefinitions;
57
57
  const titleById = new Map(definitions.map((definition) => [definition.moduleId, definition.title]));
58
58
  const changed = new Set();
59
59
  for (const { area, moduleIds } of effective) {
@@ -79,8 +79,8 @@ function describeModuleSelectionChange(effective, before, defaultArea) {
79
79
  * the switch exists to avoid. Areas whose normalized list already matches what is live are dropped;
80
80
  * if nothing remains, nothing is recorded.
81
81
  */
82
- export function applyPhiBuilderRuntimeModuleSelectionChanges(changes, defaultArea) {
83
- const current = getPhiDeveloperBuilderStateSnapshot(defaultArea);
82
+ export function applyPhiBuilderRuntimeModuleSelectionChanges(changes) {
83
+ const current = getPhiDeveloperBuilderStateSnapshot();
84
84
  const effective = [];
85
85
  for (const change of changes) {
86
86
  const currentModuleIds = current.runtimeModuleIdsByArea?.[change.area] ?? [];
@@ -93,42 +93,16 @@ export function applyPhiBuilderRuntimeModuleSelectionChanges(changes, defaultAre
93
93
  return;
94
94
  }
95
95
  const changedAreas = effective.map(({ area }) => area);
96
- const historyBefore = capturePhiBuilderModulesHistoryState(getPhiDeveloperBuilderStateSnapshot(defaultArea), changedAreas);
97
- phiWorkspaceCatalogStore.patch(defaultArea, (catalog) => ({
98
- ...catalog,
99
- runtimeModuleIdsByArea: {
100
- ...(catalog.runtimeModuleIdsByArea ?? {}),
101
- ...Object.fromEntries(effective.map(({ area, moduleIds }) => [area, moduleIds])),
102
- },
103
- }));
104
- markPhiBuilderModuleAreasDirty(changedAreas, defaultArea);
105
- phiBuilderHistory.record(createPhiBuilderHistoryContext({ workspace: "modules", area: defaultArea }), {
106
- action: { key: "changeModules", subject: describeModuleSelectionChange(effective, historyBefore, defaultArea) },
96
+ const historyBefore = capturePhiBuilderModulesHistoryState(getPhiDeveloperBuilderStateSnapshot(), changedAreas);
97
+ setPhiWorkspaceModuleSelection(Object.fromEntries(effective.map(({ area, moduleIds }) => [area, moduleIds])));
98
+ markPhiBuilderModuleAreasDirty(changedAreas);
99
+ phiBuilderHistory.record(createPhiBuilderHistoryContext({ workspace: "modules" }), {
100
+ action: { key: "changeModules", subject: describeModuleSelectionChange(effective, historyBefore) },
107
101
  before: historyBefore,
108
- after: capturePhiBuilderModulesHistoryState(getPhiDeveloperBuilderStateSnapshot(defaultArea), changedAreas),
102
+ after: capturePhiBuilderModulesHistoryState(getPhiDeveloperBuilderStateSnapshot(), changedAreas),
109
103
  });
110
104
  }
111
- export function applyPhiBuilderRuntimeModuleSelectionChange(area, selectedIds, defaultArea) {
112
- applyPhiBuilderRuntimeModuleSelectionChanges([{ area, selectedIds }], defaultArea);
113
- return getPhiDeveloperBuilderStateSnapshot(defaultArea).runtimeModuleIdsByArea?.[area] ?? [];
114
- }
115
- /**
116
- * The Areas whose Module selection has unsaved edits, kept as Builder tool state so the Modules
117
- * workspace commands know which Areas a site-wide save or publish has to reach. Undo does not clear
118
- * an Area from here -- a save of an unchanged selection is a no-op draft, while a missed Area would
119
- * silently publish stale state.
120
- */
121
- export function markPhiBuilderModuleAreasDirty(areas, defaultArea) {
122
- builderWorkspaceStore.patch(defaultArea, (tool) => {
123
- const next = new Set(tool.modulesDirtyAreas ?? []);
124
- for (const area of areas) {
125
- next.add(area);
126
- }
127
- return next.size === (tool.modulesDirtyAreas ?? []).length
128
- ? tool
129
- : { ...tool, modulesDirtyAreas: [...next] };
130
- });
131
- }
132
- export function clearPhiBuilderModuleAreasDirty(defaultArea) {
133
- builderWorkspaceStore.patch(defaultArea, (tool) => (tool.modulesDirtyAreas?.length ?? 0) === 0 ? tool : { ...tool, modulesDirtyAreas: [] });
105
+ export function applyPhiBuilderRuntimeModuleSelectionChange(area, selectedIds) {
106
+ applyPhiBuilderRuntimeModuleSelectionChanges([{ area, selectedIds }]);
107
+ return getPhiDeveloperBuilderStateSnapshot().runtimeModuleIdsByArea?.[area] ?? [];
134
108
  }
@@ -23,7 +23,7 @@ import { PHI_BUILDER_RUNTIME_DATA_PROVIDER_DESCRIPTORS } from "../../../../plugi
23
23
  import { isPhiExternalHref } from "../../../../helpers/external-href";
24
24
  import { createPhiPageUri, readPhiInternalReference } from "../../../../types/references";
25
25
  import { buildPhiBuilderNavigationContainerFromCatalogFolder, findPhiBuilderCatalogNode, } from "../navigation-folder-drop";
26
- import { phiWorkspaceCatalogStore } from "../../../../components/workspace/catalog-store";
26
+ import { addPhiWorkspaceNavigationSurface } from "../workspace-catalog-actions";
27
27
  /**
28
28
  * The "404" choice of the Path cell. On a container it is how a folder address is cleared, and what a
29
29
  * choice that is no longer a direct child reads as; on a page link it is what a deleted target reads as,
@@ -196,11 +196,11 @@ export function PhiBuilderNavigationTableProviderClient({ children }) {
196
196
  * Inspector and every slider step -- each one a reload of the navigation. The functions below read the
197
197
  * state snapshot when they run; these subscriptions only say when a change is worth a new registration.
198
198
  */
199
- const area = usePhiDeveloperBuilderStateValue("public", (state) => state.area);
200
- const customPages = usePhiDeveloperBuilderStateValue("public", (state) => state.customPages);
201
- const modulePresetPagesByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.modulePresetPagesByArea);
202
- const persistedPageCatalogByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.persistedPageCatalogByArea);
203
- const navigationSurfacesByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.navigationSurfacesByArea);
199
+ const area = usePhiDeveloperBuilderStateValue((state) => state.area);
200
+ const customPages = usePhiDeveloperBuilderStateValue((state) => state.customPages);
201
+ const modulePresetPagesByArea = usePhiDeveloperBuilderStateValue((state) => state.modulePresetPagesByArea);
202
+ const persistedPageCatalogByArea = usePhiDeveloperBuilderStateValue((state) => state.persistedPageCatalogByArea);
203
+ const navigationSurfacesByArea = usePhiDeveloperBuilderStateValue((state) => state.navigationSurfacesByArea);
204
204
  const activeNavigationKey = resolvePhiBuilderNavigationWidgetNavKey(undefined, navigationSearchValue, area);
205
205
  const activeNavigationDraft = usePhiBuilderNavigationDraft(activeNavigationKey);
206
206
  const loaded = useRef(new Map());
@@ -209,7 +209,7 @@ export function PhiBuilderNavigationTableProviderClient({ children }) {
209
209
  const initializedHistoryScopes = useRef(new Set());
210
210
  const registration = useMemo(() => {
211
211
  const resolveScope = (params) => {
212
- const state = getPhiDeveloperBuilderStateSnapshot("public");
212
+ const state = getPhiDeveloperBuilderStateSnapshot();
213
213
  const requestedNavKey = typeof params?.navKey === "string" ? params.navKey : navigationSearchValue;
214
214
  const navKey = resolvePhiBuilderNavigationWidgetNavKey(undefined, requestedNavKey ?? null, state.area);
215
215
  const surfaces = state.navigationSurfacesByArea[state.area];
@@ -345,7 +345,7 @@ export function PhiBuilderNavigationTableProviderClient({ children }) {
345
345
  if (!localKey) {
346
346
  return { status: "rejected", invalidation: "none", errorCode: "invalid-navigation-key", message: "Navigation key is invalid." };
347
347
  }
348
- const state = getPhiDeveloperBuilderStateSnapshot("public");
348
+ const state = getPhiDeveloperBuilderStateSnapshot();
349
349
  const cmsArea = resolvePhiBuilderAreaAsCmsArea(state.area);
350
350
  const navKey = formatPhiBuilderNavigationScopeKey(cmsArea, localKey);
351
351
  const surfaces = state.navigationSurfacesByArea[state.area] ?? [];
@@ -353,13 +353,7 @@ export function PhiBuilderNavigationTableProviderClient({ children }) {
353
353
  return { status: "rejected", invalidation: "none", errorCode: "navigation-exists", message: "Navigation already exists." };
354
354
  }
355
355
  const surface = createPhiBuilderCustomNavigationSurface(navKey, localKey);
356
- phiWorkspaceCatalogStore.patch("public", (current) => ({
357
- ...current,
358
- navigationSurfacesByArea: {
359
- ...current.navigationSurfacesByArea,
360
- [state.area]: [...(current.navigationSurfacesByArea[state.area] ?? []), surface],
361
- },
362
- }));
356
+ addPhiWorkspaceNavigationSurface(state.area, surface);
363
357
  const navigation = (await loadPhiBuilderNavigationScope(navKey, surface)).navigation;
364
358
  const saved = await savePhiBuilderNavigationDraft(navigation);
365
359
  setPhiBuilderNavigationDraft(navKey, {
@@ -47,13 +47,13 @@ export function PhiBuilderPageSourceTreeProviderClient({ children }) {
47
47
  * The slices the offered catalog is built from; the query reads the state when it runs. Subscribed
48
48
  * to the whole state, every selection renewed the registration and reloaded the tree.
49
49
  */
50
- const area = usePhiDeveloperBuilderStateValue("public", (state) => state.area);
51
- const customPages = usePhiDeveloperBuilderStateValue("public", (state) => state.customPages);
52
- const modulePresetPagesByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.modulePresetPagesByArea);
53
- const navigationSurfacesByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.navigationSurfacesByArea);
54
- const persistedPageCatalogByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.persistedPageCatalogByArea);
55
- const runtimeModuleIdsByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.runtimeModuleIdsByArea);
56
- const areaRootRoutes = usePhiDeveloperBuilderStateValue("public", (state) => state.areaRootRoutes);
50
+ const area = usePhiDeveloperBuilderStateValue((state) => state.area);
51
+ const customPages = usePhiDeveloperBuilderStateValue((state) => state.customPages);
52
+ const modulePresetPagesByArea = usePhiDeveloperBuilderStateValue((state) => state.modulePresetPagesByArea);
53
+ const navigationSurfacesByArea = usePhiDeveloperBuilderStateValue((state) => state.navigationSurfacesByArea);
54
+ const persistedPageCatalogByArea = usePhiDeveloperBuilderStateValue((state) => state.persistedPageCatalogByArea);
55
+ const runtimeModuleIdsByArea = usePhiDeveloperBuilderStateValue((state) => state.runtimeModuleIdsByArea);
56
+ const areaRootRoutes = usePhiDeveloperBuilderStateValue((state) => state.areaRootRoutes);
57
57
  const registration = useMemo(() => {
58
58
  const descriptor = PHI_BUILDER_RUNTIME_DATA_PROVIDER_DESCRIPTORS.find((candidate) => candidate.key === PHI_BUILDER_RUNTIME_DATA_PROVIDER_KEYS.pageSourceTree);
59
59
  return {
@@ -65,7 +65,7 @@ export function PhiBuilderPageSourceTreeProviderClient({ children }) {
65
65
  : field),
66
66
  })) : [],
67
67
  query: async (request) => {
68
- const state = getPhiDeveloperBuilderStateSnapshot("public");
68
+ const state = getPhiDeveloperBuilderStateSnapshot();
69
69
  const requestedArea = isBuilderArea(request.params?.area) ? request.params.area : state.area;
70
70
  /*
71
71
  * What the Area answers with, not what is installed in it. The active catalog mirrors the route