@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
@@ -293,10 +293,10 @@ export function PhiBuilderRuntimeModulesTableProviderClient({ children }) {
293
293
  * they run -- which is also what a mutation has to do, since the answer it writes back is to the
294
294
  * selection as it stands then, not as it stood when the provider registered.
295
295
  */
296
- const runtimeModuleDefinitions = usePhiDeveloperBuilderStateValue("public", (state) => state.runtimeModuleDefinitions);
297
- const runtimeModuleIdsByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.runtimeModuleIdsByArea);
298
- const unresolvedModuleIdsByArea = usePhiDeveloperBuilderStateValue("public", (state) => state.unresolvedModuleIdsByArea);
299
- const serverUnavailableModules = usePhiDeveloperBuilderStateValue("public", (state) => state.serverUnavailableModules);
296
+ const runtimeModuleDefinitions = usePhiDeveloperBuilderStateValue((state) => state.runtimeModuleDefinitions);
297
+ const runtimeModuleIdsByArea = usePhiDeveloperBuilderStateValue((state) => state.runtimeModuleIdsByArea);
298
+ const unresolvedModuleIdsByArea = usePhiDeveloperBuilderStateValue((state) => state.unresolvedModuleIdsByArea);
299
+ const serverUnavailableModules = usePhiDeveloperBuilderStateValue((state) => state.serverUnavailableModules);
300
300
  const registration = useMemo(() => {
301
301
  const descriptor = PHI_BUILDER_RUNTIME_DATA_PROVIDER_DESCRIPTORS.find((candidate) => candidate.key === PHI_BUILDER_RUNTIME_DATA_PROVIDER_KEYS.runtimeModulesTable);
302
302
  const resources = descriptor?.kind === "table" ? descriptor.resources : [];
@@ -309,7 +309,7 @@ export function PhiBuilderRuntimeModulesTableProviderClient({ children }) {
309
309
  throw new Error("Runtime Modules Table provider descriptor has no resource.");
310
310
  }
311
311
  const query = async (request) => {
312
- const builderState = getPhiDeveloperBuilderStateSnapshot("public");
312
+ const builderState = getPhiDeveloperBuilderStateSnapshot();
313
313
  if (request.resourceKey === DETAIL_RESOURCE_KEY) {
314
314
  const moduleId = typeof request.params?.moduleId === "string" ? request.params.moduleId : "";
315
315
  const areaLabels = readAreaLabels(request.params);
@@ -360,7 +360,7 @@ export function PhiBuilderRuntimeModulesTableProviderClient({ children }) {
360
360
  }, { ...request, query: filteredQuery });
361
361
  };
362
362
  const mutate = async (request) => {
363
- const builderState = getPhiDeveloperBuilderStateSnapshot("public");
363
+ const builderState = getPhiDeveloperBuilderStateSnapshot();
364
364
  if (request.resourceKey === MODULE_USAGE_RESOURCE_KEY) {
365
365
  return { status: "rejected", invalidation: "none", errorCode: "unsupported-mutation" };
366
366
  }
@@ -369,7 +369,7 @@ export function PhiBuilderRuntimeModulesTableProviderClient({ children }) {
369
369
  return { status: "rejected", invalidation: "none", errorCode: "unsupported-mutation" };
370
370
  }
371
371
  const path = typeof request.proposedValue === "string" ? request.proposedValue.trim() : "";
372
- answerPhiBuilderPublicRouteCollision("public", String(request.rowIdentity), path);
372
+ answerPhiBuilderPublicRouteCollision(String(request.rowIdentity), path);
373
373
  return { status: "accepted", invalidation: "none", rowPatch: { path } };
374
374
  }
375
375
  if (request.resourceKey !== RESOURCE_KEY) {
@@ -409,7 +409,7 @@ export function PhiBuilderRuntimeModulesTableProviderClient({ children }) {
409
409
  if (answers.length === 0) {
410
410
  return false;
411
411
  }
412
- openPhiBuilderPublicRouteCollisionRequest("public", {
412
+ openPhiBuilderPublicRouteCollisionRequest({
413
413
  moduleId: definition.moduleId,
414
414
  moduleTitle: definition.title,
415
415
  areas: cmsAreas.filter((areaKey) => isPhiBuilderAreaKey(areaKey)),
@@ -456,7 +456,7 @@ export function PhiBuilderRuntimeModulesTableProviderClient({ children }) {
456
456
  if (usage.length === 0) {
457
457
  return false;
458
458
  }
459
- openPhiBuilderModuleDeactivationRequest("public", {
459
+ openPhiBuilderModuleDeactivationRequest({
460
460
  moduleId: definition.moduleId,
461
461
  moduleTitle: definition.title,
462
462
  areas,
@@ -476,7 +476,7 @@ export function PhiBuilderRuntimeModulesTableProviderClient({ children }) {
476
476
  : currentModuleIds.filter((candidateId) => candidateId !== definition.moduleId),
477
477
  };
478
478
  });
479
- applyPhiBuilderRuntimeModuleSelectionChanges(changes, "public");
479
+ applyPhiBuilderRuntimeModuleSelectionChanges(changes);
480
480
  };
481
481
  // The row's switch: the Module as a whole, i.e. every eligible Area in one gesture.
482
482
  if (request.fieldKey === "active") {
@@ -50,8 +50,8 @@ export function PhiBuilderSignalRoutesTableProviderClient({ children }) {
50
50
  }
51
51
  const sessionKey = readSessionKey(request);
52
52
  const currentRoutes = sessionKey
53
- ? routeTableSessions.current.get(sessionKey) ?? getPhiDeveloperSelectedSignalRoutes("public")
54
- : getPhiDeveloperSelectedSignalRoutes("public");
53
+ ? routeTableSessions.current.get(sessionKey) ?? getPhiDeveloperSelectedSignalRoutes()
54
+ : getPhiDeveloperSelectedSignalRoutes();
55
55
  if (sessionKey && !routeTableSessions.current.has(sessionKey)) {
56
56
  routeTableSessions.current.set(sessionKey, currentRoutes ?? {});
57
57
  }
@@ -72,7 +72,7 @@ export function PhiBuilderSignalRoutesTableProviderClient({ children }) {
72
72
  throw new Error("Invalid Signal Routes Table mutation.");
73
73
  }
74
74
  const current = routeTableSessions.current.get(sessionKey) ??
75
- getPhiDeveloperSelectedSignalRoutes("public") ?? {};
75
+ getPhiDeveloperSelectedSignalRoutes() ?? {};
76
76
  if (request.actionKey === "cancel") {
77
77
  routeTableSessions.current.delete(sessionKey);
78
78
  }
@@ -1,3 +1,2 @@
1
1
  import { type PhiSignalRouteSet } from "../../../types/signals";
2
- import type { PhiDeveloperBuilderArea } from "./developer-workspace-types";
3
- export declare function getPhiDeveloperSelectedSignalRoutes(defaultArea: PhiDeveloperBuilderArea): PhiSignalRouteSet | null;
2
+ export declare function getPhiDeveloperSelectedSignalRoutes(): PhiSignalRouteSet | null;
@@ -25,7 +25,7 @@ function resolveSelectedSignalRouteConfig(state, drafts = getPhiDeveloperRegionD
25
25
  }
26
26
  return null;
27
27
  }
28
- export function getPhiDeveloperSelectedSignalRoutes(defaultArea) {
29
- const state = getPhiDeveloperBuilderStateSnapshot(defaultArea);
28
+ export function getPhiDeveloperSelectedSignalRoutes() {
29
+ const state = getPhiDeveloperBuilderStateSnapshot();
30
30
  return readPhiSignalRouteSet(resolveSelectedSignalRouteConfig(state)?.signalRoutes);
31
31
  }
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { PHI_WORKSPACE_CATALOG_SCOPE } from "../../../components/workspace/catalog-store";
2
3
  import { PHI_BUILDER_RUNTIME_DATA_PROVIDER_KEYS } from "./ids";
3
4
  import { createPhiControlOptionsProviderClient, } from "../../../components/controls/phi-options-provider";
4
5
  import { readPhiBuilderBoundCollectionResource } from "./selected-collection-source";
@@ -193,8 +194,8 @@ function resolveReceiverCapabilityOptions(context) {
193
194
  };
194
195
  }
195
196
  const wiringProviderStore = {
196
- subscribe: (listener) => builderWorkspaceStore.subscribe("public", listener),
197
- getSnapshot: () => getPhiDeveloperBuilderStateSnapshot("public"),
197
+ subscribe: (listener) => builderWorkspaceStore.subscribe(PHI_WORKSPACE_CATALOG_SCOPE, listener),
198
+ getSnapshot: () => getPhiDeveloperBuilderStateSnapshot(),
198
199
  };
199
200
  export const PhiBuilderSignalSendersOptionsProviderClient = createPhiControlOptionsProviderClient({
200
201
  key: PHI_BUILDER_RUNTIME_DATA_PROVIDER_KEYS.signalSenders,
@@ -2,9 +2,6 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { DndContext, DragOverlay, PointerSensor, pointerWithin, useDraggable, useDroppable, useSensor, useSensors, } from "@dnd-kit/core";
4
4
  import { createContext, useContext, useEffect, useMemo, useRef, useState, } from "react";
5
- import { PHI_SIGNAL_VALUE_SCHEMAS } from "../../../types/signals";
6
- import { usePhiSignalDispatcher } from "../../../components/runtime/runtime-signal-bus";
7
- import { createPhiBuilderControllerAddress } from "./controller/address";
8
5
  const PhiStructureDndContext = createContext({
9
6
  active: null,
10
7
  acceptedTargetId: null,
@@ -61,47 +58,18 @@ function PhiStructureDragSnapshot({ source, }) {
61
58
  } }));
62
59
  }
63
60
  export function PhiStructureDndProvider({ children, }) {
64
- const emitSignal = usePhiSignalDispatcher();
65
61
  const sensors = useSensors(useSensor(PointerSensor, {
66
62
  activationConstraint: { distance: 4 },
67
63
  }));
68
64
  const [active, setActive] = useState(null);
69
65
  const [acceptedTargetId, setAcceptedTargetId] = useState(null);
70
- const lastOverTargetIdRef = useRef(null);
71
66
  const previewElement = active?.getPreviewElement() ?? null;
72
- const emitDragSignal = (source, input) => {
73
- const controller = createPhiBuilderControllerAddress();
74
- emitSignal({
75
- scope: source.pageScoped ? "page" : "area",
76
- channel: input.channel,
77
- action: input.action,
78
- value: {
79
- area: source.area,
80
- pageKey: source.pageKey,
81
- sourceRegionKey: source.regionKey,
82
- sourceNodeId: source.nodeId,
83
- sourceNodeKind: source.nodeKind,
84
- targetRegionKey: input.target?.regionKey ?? null,
85
- targetKey: input.target?.id ?? null,
86
- targetNodeId: input.target?.targetNodeId ?? null,
87
- dropMode: input.target?.dropMode ?? null,
88
- accepted: input.accepted ?? null,
89
- },
90
- valueType: "json",
91
- valueSchema: PHI_SIGNAL_VALUE_SCHEMAS.dragDrop,
92
- sender: controller,
93
- receiver: controller,
94
- timestamp: Date.now(),
95
- });
96
- };
97
- const finish = (source) => {
98
- if (source) {
99
- emitDragSignal(source, {
100
- channel: "drag",
101
- action: "stop",
102
- });
103
- }
104
- lastOverTargetIdRef.current = null;
67
+ /*
68
+ * The drag stays inside this context: the drop moves the node through its target, and nothing is
69
+ * signalled. The Builder Controller used to send `drag/*` and `drop/drop` here, addressed to itself,
70
+ * which answers nothing under its own address -- four declared outputs that never reached anybody.
71
+ */
72
+ const finish = () => {
105
73
  setAcceptedTargetId(null);
106
74
  setActive(null);
107
75
  };
@@ -111,10 +79,6 @@ export function PhiStructureDndProvider({ children, }) {
111
79
  return;
112
80
  }
113
81
  setActive(source);
114
- emitDragSignal(source, {
115
- channel: "drag",
116
- action: "start",
117
- });
118
82
  };
119
83
  const handleDragOver = (event) => {
120
84
  const source = readStructureDragData(event);
@@ -122,17 +86,6 @@ export function PhiStructureDndProvider({ children, }) {
122
86
  const accepted = !!source && !!target && target.accepts(source);
123
87
  const nextTargetId = accepted ? target.id : null;
124
88
  setAcceptedTargetId((current) => current === nextTargetId ? current : nextTargetId);
125
- if (source &&
126
- target &&
127
- lastOverTargetIdRef.current !== `${target.id}:${accepted}`) {
128
- lastOverTargetIdRef.current = `${target.id}:${accepted}`;
129
- emitDragSignal(source, {
130
- channel: "drag",
131
- action: "change",
132
- target,
133
- accepted,
134
- });
135
- }
136
89
  };
137
90
  const handleDragEnd = (event) => {
138
91
  const source = readStructureDragData(event);
@@ -140,14 +93,8 @@ export function PhiStructureDndProvider({ children, }) {
140
93
  const accepted = !!source && !!target && target.accepts(source);
141
94
  if (source && target && accepted) {
142
95
  target.drop(source);
143
- emitDragSignal(source, {
144
- channel: "drop",
145
- action: "drop",
146
- target,
147
- accepted: true,
148
- });
149
96
  }
150
- finish(source);
97
+ finish();
151
98
  };
152
99
  const contextValue = useMemo(() => ({ active, acceptedTargetId }), [acceptedTargetId, active]);
153
100
  useEffect(() => {
@@ -156,7 +103,7 @@ export function PhiStructureDndProvider({ children, }) {
156
103
  document.documentElement.removeAttribute("data-phi-structure-drop-accepted");
157
104
  };
158
105
  }, [acceptedTargetId]);
159
- return (_jsx(DndContext, { sensors: sensors, collisionDetection: pointerWithin, onDragStart: handleDragStart, onDragOver: handleDragOver, onDragEnd: handleDragEnd, onDragCancel: () => finish(active), children: _jsxs(PhiStructureDndContext.Provider, { value: contextValue, children: [children, _jsx(DragOverlay, { dropAnimation: null, children: active ? _jsx(PhiStructureDragSnapshot, { source: previewElement }) : null })] }) }));
106
+ return (_jsx(DndContext, { sensors: sensors, collisionDetection: pointerWithin, onDragStart: handleDragStart, onDragOver: handleDragOver, onDragEnd: handleDragEnd, onDragCancel: finish, children: _jsxs(PhiStructureDndContext.Provider, { value: contextValue, children: [children, _jsx(DragOverlay, { dropAnimation: null, children: active ? _jsx(PhiStructureDragSnapshot, { source: previewElement }) : null })] }) }));
160
107
  }
161
108
  export function usePhiStructureDraggable(id, data) {
162
109
  return useDraggable({
@@ -273,17 +273,20 @@ function remapBuilderPresetTreeInstanceIds(tree, ownerModuleId, presetKey) {
273
273
  from: createPhiSignalAddress("cms", from),
274
274
  to: createPhiSignalAddress("cms", to),
275
275
  }));
276
- const remapInstanceId = (value) => value == null ? null : (instanceIdRemaps.get(value) ?? value);
276
+ // One id stays one id: a node whose id is not remapped keeps its own, so nothing here can come back
277
+ // empty. The nullable form is for the links a tree may leave unset, and only for those.
278
+ const remapInstanceId = (value) => instanceIdRemaps.get(value) ?? value;
279
+ const remapOptionalInstanceId = (value) => value == null ? null : remapInstanceId(value);
277
280
  return {
278
281
  ...tree,
279
282
  page: {
280
283
  ...tree.page,
281
- heroRootLayoutNodeId: remapInstanceId(tree.page.heroRootLayoutNodeId),
282
- headerBottomRootLayoutNodeId: remapInstanceId(tree.page.headerBottomRootLayoutNodeId),
283
- siderRightRootLayoutNodeId: remapInstanceId(tree.page.siderRightRootLayoutNodeId),
284
- footerTopRootLayoutNodeId: remapInstanceId(tree.page.footerTopRootLayoutNodeId),
285
- drawerRightRootLayoutNodeId: remapInstanceId(tree.page.drawerRightRootLayoutNodeId),
286
- contentRootLayoutNodeId: remapInstanceId(tree.page.contentRootLayoutNodeId),
284
+ heroRootLayoutNodeId: remapOptionalInstanceId(tree.page.heroRootLayoutNodeId),
285
+ headerBottomRootLayoutNodeId: remapOptionalInstanceId(tree.page.headerBottomRootLayoutNodeId),
286
+ siderRightRootLayoutNodeId: remapOptionalInstanceId(tree.page.siderRightRootLayoutNodeId),
287
+ footerTopRootLayoutNodeId: remapOptionalInstanceId(tree.page.footerTopRootLayoutNodeId),
288
+ drawerRightRootLayoutNodeId: remapOptionalInstanceId(tree.page.drawerRightRootLayoutNodeId),
289
+ contentRootLayoutNodeId: remapOptionalInstanceId(tree.page.contentRootLayoutNodeId),
287
290
  },
288
291
  regions: tree.regions.map((region) => ({
289
292
  ...region,
@@ -292,7 +295,7 @@ function remapBuilderPresetTreeInstanceIds(tree, ownerModuleId, presetKey) {
292
295
  overlays: tree.overlays.map((overlay) => ({
293
296
  ...overlay,
294
297
  id: remapInstanceId(overlay.id),
295
- headerLayoutNodeId: remapInstanceId(overlay.headerLayoutNodeId),
298
+ headerLayoutNodeId: remapOptionalInstanceId(overlay.headerLayoutNodeId),
296
299
  bodyLayoutNodeId: remapInstanceId(overlay.bodyLayoutNodeId),
297
300
  ...(overlay.footerPresentation === "none"
298
301
  ? { footerPresentation: "none", footerLayoutNodeId: null }
@@ -305,7 +308,7 @@ function remapBuilderPresetTreeInstanceIds(tree, ownerModuleId, presetKey) {
305
308
  layoutNodes: tree.layoutNodes.map((node) => ({
306
309
  ...node,
307
310
  id: remapInstanceId(node.id),
308
- parentLayoutNodeId: remapInstanceId(node.parentLayoutNodeId),
311
+ parentLayoutNodeId: remapOptionalInstanceId(node.parentLayoutNodeId),
309
312
  config: remapPhiSignalRoutesInConfig(node.config, signalRemaps),
310
313
  })),
311
314
  // The Controller's routes name the same receivers the nodes' routes do, so they move with them.
@@ -1487,14 +1490,18 @@ async function buildPhiDefaultBuilderPagePresetTemplateTree({ page, runtime, pre
1487
1490
  key: "createPage",
1488
1491
  emits: [{ capabilityId: "command", value: "createPage" }],
1489
1492
  label: labels.pages.newPage,
1493
+ tooltip: labels.pages.newPage,
1490
1494
  icon: "plus",
1495
+ display: "icon",
1491
1496
  variant: "primary",
1492
1497
  },
1493
1498
  {
1494
1499
  key: "editPageMeta",
1495
1500
  emits: [{ capabilityId: "command", value: "editPageMeta" }],
1496
1501
  label: labels.pages.pageMeta,
1502
+ tooltip: labels.pages.pageMeta,
1497
1503
  icon: "edit",
1504
+ display: "icon",
1498
1505
  },
1499
1506
  {
1500
1507
  key: "deletePage",
@@ -1880,7 +1887,7 @@ async function buildPhiDefaultBuilderPagePresetTemplateTree({ page, runtime, pre
1880
1887
  },
1881
1888
  }),
1882
1889
  ]
1883
- : isNavigationPage
1890
+ : navigationLabels
1884
1891
  ? [
1885
1892
  nodes.widget({
1886
1893
  typeKey: "command-toolbar",
@@ -40,6 +40,7 @@ import { PhiTypographyControl } from "../../../../../components/controls/phi-typ
40
40
  import { PhiIcon } from "../../../../../components/shell/phi-icon";
41
41
  import { PhiSurfaceTone } from "../../../../../components/surface/phi-surface-tone";
42
42
  import { resolvePhiSurfaceToneClassName } from "../../../../../types/surface";
43
+ import { PHI_SURFACE_TONE_GROUND, phiSurfaceTakesToneGround } from "../../../../../helpers/surface-style";
43
44
  /** The Region's root Layout placed into another tree, at the slot it is moved to. */
44
45
  function buildStructureRootLayoutNode(draft, parentLayoutNodeId, slotIndex) {
45
46
  if (!draft.rootNode) {
@@ -296,13 +297,13 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
296
297
  const activeModules = usePhiRuntimeModuleState();
297
298
  const authoringCanvas = usePhiBuilderAuthoringCanvas();
298
299
  const builderState = {
299
- area: usePhiDeveloperBuilderStateValue("public", (state) => state.area),
300
- pageKey: usePhiDeveloperBuilderStateValue("public", (state) => state.pageKey),
301
- builderMode: usePhiDeveloperBuilderStateValue("public", (state) => state.builderMode),
302
- debugScaffold: usePhiDeveloperBuilderStateValue("public", (state) => state.debugScaffold),
303
- pickerWidgetCategoryFilters: usePhiDeveloperBuilderStateValue("public", (state) => state.pickerWidgetCategoryFilters),
304
- selectedLayoutAnchor: usePhiDeveloperBuilderStateValue("public", (state) => state.selectedRootRegionKey === config.regionKey ? state.selectedLayoutAnchor : null),
305
- regionSelected: usePhiDeveloperBuilderStateValue("public", (state) => state.nodeKind === "region" && state.selectedRegionKey === config.regionKey),
300
+ area: usePhiDeveloperBuilderStateValue((state) => state.area),
301
+ pageKey: usePhiDeveloperBuilderStateValue((state) => state.pageKey),
302
+ builderMode: usePhiDeveloperBuilderStateValue((state) => state.builderMode),
303
+ debugScaffold: usePhiDeveloperBuilderStateValue((state) => state.debugScaffold),
304
+ pickerWidgetCategoryFilters: usePhiDeveloperBuilderStateValue((state) => state.pickerWidgetCategoryFilters),
305
+ selectedLayoutAnchor: usePhiDeveloperBuilderStateValue((state) => state.selectedRootRegionKey === config.regionKey ? state.selectedLayoutAnchor : null),
306
+ regionSelected: usePhiDeveloperBuilderStateValue((state) => state.nodeKind === "region" && state.selectedRegionKey === config.regionKey),
306
307
  };
307
308
  const builderModuleMetas = usePhiBuilderModuleMetas(builderState.area);
308
309
  const layoutMetasByType = useMemo(() => buildPhiBuilderContainerMetaMap(builderModuleMetas.plugins), [builderModuleMetas.plugins]);
@@ -353,16 +354,26 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
353
354
  const shouldStretchAvailableHeight = shouldFillAvailableHeight || shouldStretchContentRegion;
354
355
  const hasExplicitSidebarWidth = isFullHeightRegion && draftGeometry.explicitInline;
355
356
  const regionToneClassName = resolvePhiSurfaceToneClassName(effectiveDraft?.surface?.tone);
356
- const slotBackgroundStyle = effectiveDraft?.surface?.background
357
- ? resolvePhiBackgroundWidgetStyle(effectiveDraft.surface.background)
358
- : {};
359
357
  /*
360
358
  * Whether the author gave this Region a ground. The Builder writes a Background config onto every
361
359
  * Region draft it persists, so only a config that paints something counts. An unauthored Region is
362
360
  * transparent in the live Shell, and the Canvas keeps that legible: its slot paints a half-transparent
363
361
  * container tint, so the Theme Root Background stays visible through it.
364
362
  */
365
- const hasAuthoredGround = phiBackgroundWidgetConfigPaintsGround(effectiveDraft?.surface?.background ?? null);
363
+ const paintsAuthoredGround = phiBackgroundWidgetConfigPaintsGround(effectiveDraft?.surface?.background ?? null);
364
+ /*
365
+ * A toned Region takes its tone's ground where its Background paints none, by the rule the live Region
366
+ * shell follows (`phiSurfaceTakesToneGround`). The slot carries the tone's class, so the ground resolves
367
+ * in the tone's mode; it is a ground of the Region's own, so the Canvas tint does not cover it.
368
+ */
369
+ const toneGround = phiSurfaceTakesToneGround(effectiveDraft?.surface?.tone, paintsAuthoredGround);
370
+ const hasAuthoredGround = paintsAuthoredGround || toneGround;
371
+ const slotBackgroundStyle = {
372
+ ...(effectiveDraft?.surface?.background
373
+ ? resolvePhiBackgroundWidgetStyle(effectiveDraft.surface.background)
374
+ : {}),
375
+ ...(toneGround ? { backgroundColor: PHI_SURFACE_TONE_GROUND } : {}),
376
+ };
366
377
  const slotBorderStyle = effectiveDraft?.surface?.border ? resolvePhiBorderWidgetStyle(effectiveDraft.surface.border) : {};
367
378
  const regionConfig = (effectiveDraft?.regionConfig ?? null);
368
379
  const regionPaddingStyle = resolvePhiPaddingStyle(normalizePhiPaddingWidgetConfig(effectiveDraft?.regionConfig) ?? {});
@@ -424,9 +435,7 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
424
435
  if (!hasRootNode || isPreviewMode || !rootNodeKind) {
425
436
  return;
426
437
  }
427
- selectPhiDeveloperBuilderNode("public", {
428
- area: builderState.area,
429
- pageKey: builderState.pageKey,
438
+ selectPhiDeveloperBuilderNode({
430
439
  regionKey: config.regionKey,
431
440
  nodeId: options?.nodeId ?? rootNodeId,
432
441
  nodeKey: options?.nodeKey ?? rootNodeTypeKey,
@@ -1026,7 +1035,7 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
1026
1035
  }, [builderMode, isPicking]);
1027
1036
  useEffect(() => {
1028
1037
  if (!Array.isArray(builderState.pickerWidgetCategoryFilters)) {
1029
- patchPhiDeveloperBuilderState("public", { pickerWidgetCategoryFilters: [] });
1038
+ patchPhiDeveloperBuilderState({ pickerWidgetCategoryFilters: [] });
1030
1039
  }
1031
1040
  }, [builderState.pickerWidgetCategoryFilters]);
1032
1041
  useEffect(() => {
@@ -1074,9 +1083,7 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
1074
1083
  if (!config.allowSelect || isPreviewMode) {
1075
1084
  return;
1076
1085
  }
1077
- selectPhiDeveloperBuilderNode("public", {
1078
- area: builderState.area,
1079
- pageKey: builderState.pageKey,
1086
+ selectPhiDeveloperBuilderNode({
1080
1087
  nodeKind: "region",
1081
1088
  nodeKey: `region:${config.regionKey}`,
1082
1089
  regionKey: config.regionKey,
@@ -1113,9 +1120,7 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
1113
1120
  setSlotPickerContext(nextSlotPickerContext);
1114
1121
  setPickSection(nextDefaultPickSection);
1115
1122
  setIsPicking(true);
1116
- selectPhiDeveloperBuilderNode("public", {
1117
- area: builderState.area,
1118
- pageKey: builderState.pageKey,
1123
+ selectPhiDeveloperBuilderNode({
1119
1124
  regionKey: config.regionKey,
1120
1125
  nodeKey: `slot:${config.regionKey}`,
1121
1126
  nodeKind: "slot",
@@ -1150,7 +1155,7 @@ export function PhiStructureRegionScaffold({ config, serverPreview, structureDra
1150
1155
  if (!nextOpen && isActiveTarget)
1151
1156
  closePicker();
1152
1157
  }, onSectionChange: setPickSection, onPackageFiltersChange: setPickPackageFilters, onWidgetCategoryFiltersChange: (filters) => {
1153
- patchPhiDeveloperBuilderState("public", { pickerWidgetCategoryFilters: filters });
1158
+ patchPhiDeveloperBuilderState({ pickerWidgetCategoryFilters: filters });
1154
1159
  }, onChange: (item) => void insertPickedItem(item) }, key));
1155
1160
  }
1156
1161
  /*
@@ -0,0 +1,55 @@
1
+ import { type PhiWorkspaceCatalogState } from "../../../components/workspace/catalog-store";
2
+ import type { PhiBuilderPersistedPageCatalogEntry, PhiPresetPageNode } from "../../../helpers/cms-page-catalog";
3
+ import type { PhiCmsResolvedNavigationSurface } from "../../../types/cms-module-descriptors";
4
+ import type { PhiRuntimeModuleId } from "../../../types";
5
+ import type { PhiDeveloperBuilderArea } from "./developer-workspace-types";
6
+ /** The Area and Page being worked on. Leaves the catalog as it is when both are already open. */
7
+ export declare function openPhiWorkspacePage(area: PhiDeveloperBuilderArea, pageKey: string): void;
8
+ /** The Page being worked on, within the Area that is open. */
9
+ export declare function setPhiWorkspacePageKey(pageKey: string): void;
10
+ /** The Site's own Pages of one Area, as the server answered them; the Area's catalog counts as read. */
11
+ export declare function storePhiWorkspacePersistedPages(area: PhiDeveloperBuilderArea, pages: PhiBuilderPersistedPageCatalogEntry[]): void;
12
+ /** A Page created in the Builder and not saved yet. */
13
+ export declare function addPhiWorkspaceCustomPage(area: PhiDeveloperBuilderArea, page: PhiPresetPageNode): void;
14
+ /** A navigation created in the Builder, added to the surfaces of its Area. */
15
+ export declare function addPhiWorkspaceNavigationSurface(area: PhiDeveloperBuilderArea, surface: PhiCmsResolvedNavigationSurface): void;
16
+ /** The Pages and navigation surfaces the active Modules contribute, when the Module selection changed. */
17
+ export declare function setPhiWorkspaceActiveCatalogs(catalogs: Pick<PhiWorkspaceCatalogState, "modulePresetPagesByArea" | "navigationSurfacesByArea">): void;
18
+ /** The Module selection of the named Areas; the other Areas keep theirs. */
19
+ export declare function setPhiWorkspaceModuleSelection(moduleIdsByArea: Partial<Record<PhiDeveloperBuilderArea, PhiRuntimeModuleId[]>>): void;
20
+ /**
21
+ * The Public addresses one Module's Pages take, as the collision dialog answered them. The Module's
22
+ * other assignments, and every other Module's, stay.
23
+ */
24
+ export declare function assignPhiWorkspacePublicRoutePaths(moduleId: PhiRuntimeModuleId, answers: ReadonlyMap<string, string>): void;
25
+ /** Catalog fields an undo or redo puts back (`splitWorkspacePatch`). */
26
+ export declare function restorePhiWorkspaceCatalog(fields: Partial<PhiWorkspaceCatalogState>): void;
27
+ /** What the server rendered the Builder with, as its preload hands it in. */
28
+ export type PhiWorkspaceCatalogPreload = Pick<PhiWorkspaceCatalogState, "areaPresetSourcesByArea" | "unresolvedModuleIdsByArea" | "serverUnavailableModules" | "publicRouteClaims" | "publicRoutePaths"> & {
29
+ runtimeModuleDefinitions: readonly PhiWorkspaceCatalogState["runtimeModuleDefinitions"][number][];
30
+ runtimeModuleIdsByArea: Readonly<Record<string, PhiRuntimeModuleId[]>>;
31
+ /** The Pages and surfaces of the active Modules, which is what the catalog holds. */
32
+ activeCatalogs: Pick<PhiWorkspaceCatalogState, "modulePresetPagesByArea" | "navigationSurfacesByArea">;
33
+ /**
34
+ * The server's answer, serialized, per field: a field is taken again only when this differs from what
35
+ * the catalog holds, so an unsaved edit -- a Module selection, a collision answer -- survives a
36
+ * re-render that brought nothing new.
37
+ */
38
+ keys: {
39
+ runtimeModuleDefinitions: string;
40
+ modulePresetPagesByArea: string;
41
+ areaPresetSourcesByArea: string;
42
+ navigationSurfacesByArea: string;
43
+ unresolvedModuleIdsByArea: string;
44
+ publicRouteClaims: string;
45
+ serverUnavailableModules: string;
46
+ publicRoutePaths: string;
47
+ };
48
+ normalizeArea: (area: string) => PhiDeveloperBuilderArea;
49
+ };
50
+ /**
51
+ * Feeds the server's preload into the catalog, and answers the Page it opened when none was open yet --
52
+ * the caller selects that Page in the Builder. Nothing else is written from inside the update, so the
53
+ * Builder's own store is never patched from within the catalog's.
54
+ */
55
+ export declare function applyPhiWorkspaceCatalogPreload(preload: PhiWorkspaceCatalogPreload): string | null;
@@ -0,0 +1,142 @@
1
+ "use client";
2
+ import { PHI_WORKSPACE_CATALOG_SCOPE, phiWorkspaceCatalogStore, } from "../../../components/workspace/catalog-store";
3
+ import { resolvePhiBuilderActivePageKey } from "../../../helpers/cms-page-catalog";
4
+ import { normalizePhiAreaPublicRoutePaths } from "../../../helpers/cms-area-config";
5
+ /*
6
+ * Every write the Builder makes to the workspace catalog (`components/workspace/catalog-store.ts`).
7
+ *
8
+ * The catalog is the Foundation's -- revisions read it, and the Editor will feed it -- but on this side
9
+ * only the Builder feeds it, and it does so here and nowhere else. Each write is a named action, so
10
+ * "who changes which Area is open" has one answer; before, fourteen places in six files patched the
11
+ * store with whatever they held. `scripts/validate-builder-store-ownership.mjs` keeps it that way.
12
+ */
13
+ function patchCatalog(update) {
14
+ phiWorkspaceCatalogStore.patch(PHI_WORKSPACE_CATALOG_SCOPE, update);
15
+ }
16
+ /** The Area and Page being worked on. Leaves the catalog as it is when both are already open. */
17
+ export function openPhiWorkspacePage(area, pageKey) {
18
+ patchCatalog((current) => (current.area === area && current.pageKey === pageKey
19
+ ? current
20
+ : { ...current, area, pageKey }));
21
+ }
22
+ /** The Page being worked on, within the Area that is open. */
23
+ export function setPhiWorkspacePageKey(pageKey) {
24
+ patchCatalog((current) => (current.pageKey === pageKey ? current : { ...current, pageKey }));
25
+ }
26
+ /** The Site's own Pages of one Area, as the server answered them; the Area's catalog counts as read. */
27
+ export function storePhiWorkspacePersistedPages(area, pages) {
28
+ patchCatalog((current) => ({
29
+ ...current,
30
+ persistedPageCatalogByArea: { ...current.persistedPageCatalogByArea, [area]: pages },
31
+ pageCatalogHydratedByArea: { ...current.pageCatalogHydratedByArea, [area]: true },
32
+ }));
33
+ }
34
+ /** A Page created in the Builder and not saved yet. */
35
+ export function addPhiWorkspaceCustomPage(area, page) {
36
+ patchCatalog((current) => ({
37
+ ...current,
38
+ customPages: { ...current.customPages, [area]: [...(current.customPages[area] ?? []), page] },
39
+ }));
40
+ }
41
+ /** A navigation created in the Builder, added to the surfaces of its Area. */
42
+ export function addPhiWorkspaceNavigationSurface(area, surface) {
43
+ patchCatalog((current) => ({
44
+ ...current,
45
+ navigationSurfacesByArea: {
46
+ ...current.navigationSurfacesByArea,
47
+ [area]: [...(current.navigationSurfacesByArea[area] ?? []), surface],
48
+ },
49
+ }));
50
+ }
51
+ /** The Pages and navigation surfaces the active Modules contribute, when the Module selection changed. */
52
+ export function setPhiWorkspaceActiveCatalogs(catalogs) {
53
+ patchCatalog((current) => (JSON.stringify(current.modulePresetPagesByArea) === JSON.stringify(catalogs.modulePresetPagesByArea) &&
54
+ JSON.stringify(current.navigationSurfacesByArea) === JSON.stringify(catalogs.navigationSurfacesByArea)
55
+ ? current
56
+ : { ...current, ...catalogs }));
57
+ }
58
+ /** The Module selection of the named Areas; the other Areas keep theirs. */
59
+ export function setPhiWorkspaceModuleSelection(moduleIdsByArea) {
60
+ patchCatalog((current) => ({
61
+ ...current,
62
+ runtimeModuleIdsByArea: { ...(current.runtimeModuleIdsByArea ?? {}), ...moduleIdsByArea },
63
+ }));
64
+ }
65
+ /**
66
+ * The Public addresses one Module's Pages take, as the collision dialog answered them. The Module's
67
+ * other assignments, and every other Module's, stay.
68
+ */
69
+ export function assignPhiWorkspacePublicRoutePaths(moduleId, answers) {
70
+ patchCatalog((current) => {
71
+ const kept = (current.publicRoutePaths ?? []).filter((assignment) => assignment.ownerModuleId !== moduleId || !answers.has(assignment.presetKey));
72
+ return {
73
+ ...current,
74
+ publicRoutePaths: normalizePhiAreaPublicRoutePaths([
75
+ ...kept,
76
+ ...[...answers.entries()].map(([presetKey, path]) => ({ ownerModuleId: moduleId, presetKey, path })),
77
+ ]),
78
+ };
79
+ });
80
+ }
81
+ /** Catalog fields an undo or redo puts back (`splitWorkspacePatch`). */
82
+ export function restorePhiWorkspaceCatalog(fields) {
83
+ if (Object.keys(fields).length === 0)
84
+ return;
85
+ patchCatalog((current) => ({ ...current, ...fields }));
86
+ }
87
+ /**
88
+ * Feeds the server's preload into the catalog, and answers the Page it opened when none was open yet --
89
+ * the caller selects that Page in the Builder. Nothing else is written from inside the update, so the
90
+ * Builder's own store is never patched from within the catalog's.
91
+ */
92
+ export function applyPhiWorkspaceCatalogPreload(preload) {
93
+ let openedPageKey = null;
94
+ patchCatalog((current) => {
95
+ let changed = false;
96
+ const definitionsChanged = JSON.stringify(current.runtimeModuleDefinitions ?? []) !== preload.keys.runtimeModuleDefinitions;
97
+ const modulePresetPagesChanged = JSON.stringify(current.modulePresetPagesByArea) !== preload.keys.modulePresetPagesByArea;
98
+ const areaPresetSourcesChanged = JSON.stringify(current.areaPresetSourcesByArea) !== preload.keys.areaPresetSourcesByArea;
99
+ const navigationSurfacesChanged = JSON.stringify(current.navigationSurfacesByArea) !== preload.keys.navigationSurfacesByArea;
100
+ const unresolvedModuleIdsChanged = JSON.stringify(current.unresolvedModuleIdsByArea) !== preload.keys.unresolvedModuleIdsByArea;
101
+ const publicRouteClaimsChanged = JSON.stringify(current.publicRouteClaims) !== preload.keys.publicRouteClaims;
102
+ const serverUnavailableModulesChanged = JSON.stringify(current.serverUnavailableModules) !== preload.keys.serverUnavailableModules;
103
+ /*
104
+ * The assignments arrive with the Modules draft and are edited by the collision dialog, so this
105
+ * follows the same rule as the Module selection beside it: what the server sent replaces what is
106
+ * here when the server's answer changed, and an unsaved answer survives a re-render.
107
+ */
108
+ const publicRoutePathsChanged = JSON.stringify(current.publicRoutePaths) !== preload.keys.publicRoutePaths;
109
+ const catalogHydrationChanged = !current.catalogHydrated;
110
+ const initialPageKey = current.pageKey ||
111
+ resolvePhiBuilderActivePageKey(null, preload.activeCatalogs.modulePresetPagesByArea[current.area]) || "";
112
+ const initialPageChanged = initialPageKey !== current.pageKey;
113
+ const nextModuleIdsByArea = { ...(current.runtimeModuleIdsByArea ?? {}) };
114
+ for (const [area, moduleIds] of Object.entries(preload.runtimeModuleIdsByArea)) {
115
+ const builderArea = preload.normalizeArea(area);
116
+ if (JSON.stringify(nextModuleIdsByArea[builderArea] ?? []) !== JSON.stringify(moduleIds ?? [])) {
117
+ nextModuleIdsByArea[builderArea] = moduleIds;
118
+ changed = true;
119
+ }
120
+ }
121
+ openedPageKey = initialPageChanged ? initialPageKey : null;
122
+ return changed || definitionsChanged || modulePresetPagesChanged || areaPresetSourcesChanged ||
123
+ navigationSurfacesChanged || unresolvedModuleIdsChanged || serverUnavailableModulesChanged ||
124
+ publicRouteClaimsChanged || publicRoutePathsChanged || catalogHydrationChanged || initialPageChanged
125
+ ? {
126
+ ...current,
127
+ ...(initialPageChanged ? { pageKey: initialPageKey } : {}),
128
+ runtimeModuleDefinitions: [...preload.runtimeModuleDefinitions],
129
+ runtimeModuleIdsByArea: nextModuleIdsByArea,
130
+ catalogHydrated: true,
131
+ modulePresetPagesByArea: preload.activeCatalogs.modulePresetPagesByArea,
132
+ areaPresetSourcesByArea: preload.areaPresetSourcesByArea,
133
+ navigationSurfacesByArea: preload.activeCatalogs.navigationSurfacesByArea,
134
+ unresolvedModuleIdsByArea: preload.unresolvedModuleIdsByArea,
135
+ serverUnavailableModules: preload.serverUnavailableModules,
136
+ publicRouteClaims: preload.publicRouteClaims,
137
+ ...(publicRoutePathsChanged ? { publicRoutePaths: preload.publicRoutePaths } : {}),
138
+ }
139
+ : current;
140
+ });
141
+ return openedPageKey;
142
+ }
@@ -28,4 +28,11 @@ export declare function createPhiRuntimeModuleAuthoringClient({ moduleId, Widget
28
28
  layouts?: readonly PhiAuthoringLayoutModuleLoader[];
29
29
  }): ComponentType<PhiRuntimeModuleAuthoringClientProps>;
30
30
  export declare function usePhiRuntimeModuleAuthoringRegistration(moduleId: PhiRuntimeModuleId | null | undefined): PhiRuntimeModuleAuthoringRegistration | null;
31
- export declare function usePhiAuthoringLayoutDefinition(type: string): PhiAuthoringLayoutDefinition | null;
31
+ /**
32
+ * The authoring Layout definitions, as a lookup by type rather than one type's answer.
33
+ *
34
+ * A Layout names its nested Layouts only while it renders its children, and a parent Layout sizes each
35
+ * slot by the props of the element standing in it, before that element renders: a nested Layout's
36
+ * element has to carry its policy already, and a hook inside it would be too late.
37
+ */
38
+ export declare function usePhiAuthoringLayoutDefinitionResolver(): (type: string) => PhiAuthoringLayoutDefinition | null;