@phis/ui 0.4.2 → 0.4.3

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 (241) 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-bullet-list-control.js +31 -2
  7. package/components/controls/phi-ribbon-control.d.ts +29 -0
  8. package/components/controls/phi-ribbon-control.js +53 -0
  9. package/components/controls/phi-table-control.d.ts +3 -0
  10. package/components/controls/phi-table-control.js +13 -1
  11. package/components/controls/phi-tree-control.js +3 -3
  12. package/components/forms/shared-form-provider-registry.js +1 -4
  13. package/components/media/asset-collection-runtime.js +6 -16
  14. package/components/media/media-font-metrics.d.ts +3 -0
  15. package/components/media/media-font-metrics.js +43 -0
  16. package/components/media/phi-area-upload-widget.js +53 -97
  17. package/components/media/phi-image-preview-data.d.ts +13 -0
  18. package/components/media/phi-image-preview-data.js +184 -9
  19. package/components/media/phi-media-picker-binding.js +16 -13
  20. package/components/media/phi-media-upload.d.ts +15 -8
  21. package/components/media/phi-media-upload.js +18 -9
  22. package/components/media/phi-site-font-assets.js +7 -8
  23. package/components/overlays/phi-overlay-container-client.js +16 -1
  24. package/components/regions/presets/phi-settings-page-shell-tree.js +48 -1
  25. package/components/runtime/runtime-controller-materialization.js +12 -1
  26. package/components/state/scoped-state-store.js +20 -3
  27. package/components/tables/client/phi-table-binding.d.ts +2 -1
  28. package/components/tables/client/phi-table-binding.js +45 -21
  29. package/components/trees/client/phi-tree-binding.js +19 -11
  30. package/components/widgets/client/bullet-list-entries-editor.d.ts +26 -0
  31. package/components/widgets/client/bullet-list-entries-editor.js +103 -0
  32. package/components/widgets/config/choice-shared.js +12 -13
  33. package/components/widgets/config/command-buttons.d.ts +5 -1
  34. package/components/widgets/config/command-buttons.js +38 -81
  35. package/components/widgets/config/control-signal-config.d.ts +3 -1
  36. package/components/widgets/config/control-signal-config.js +19 -17
  37. package/components/widgets/config/image-source-parser.d.ts +1 -0
  38. package/components/widgets/config/image-source-parser.js +7 -8
  39. package/components/widgets/config/mask.d.ts +6 -1
  40. package/components/widgets/config/mask.js +24 -1
  41. package/components/widgets/config/parser-primitives.js +72 -0
  42. package/components/widgets/config/stack-tabs.d.ts +1 -1
  43. package/components/widgets/config/stack-tabs.js +2 -3
  44. package/components/widgets/config/strict-config-reader.d.ts +40 -0
  45. package/components/widgets/config/strict-config-reader.js +174 -0
  46. package/components/widgets/label-sets/effects.js +2 -0
  47. package/components/widgets/label-types/effects.d.ts +1 -0
  48. package/components/widgets/label-types/effects.js +1 -0
  49. package/components/widgets/navigation-descriptor-resolver.server.js +20 -8
  50. package/components/widgets/shared/bullet-list-vocabulary.d.ts +17 -1
  51. package/components/widgets/shared/bullet-list-vocabulary.js +19 -2
  52. package/components/widgets/shared/card-body-client.d.ts +16 -4
  53. package/components/widgets/shared/card-body-client.js +81 -24
  54. package/components/widgets/shared/card-vocabulary.d.ts +21 -4
  55. package/components/widgets/shared/card-vocabulary.js +28 -2
  56. package/components/widgets/signals/control-signal-capabilities.d.ts +0 -18
  57. package/components/widgets/signals/control-signal-capabilities.js +10 -22
  58. package/components/workspace/catalog-store.d.ts +4 -3
  59. package/components/workspace/catalog-store.js +6 -5
  60. package/gateway/dashboard-cards-route.js +1 -0
  61. package/gateway/internal-references.d.ts +6 -1
  62. package/gateway/internal-references.js +48 -23
  63. package/gateway/site-cms-write-validation.d.ts +9 -0
  64. package/gateway/site-cms-write-validation.js +78 -0
  65. package/gateway/site-proxy.js +19 -3
  66. package/helpers/renderable-block-serialization.js +1 -1
  67. package/next/config.d.mts +3 -0
  68. package/next/config.mjs +28 -1
  69. package/package.json +2 -2
  70. package/plugins/runtime/phi-slot-child-viewport-effects-observer.js +5 -1
  71. package/plugins/runtime-modules/accounting/presets.d.ts +9 -0
  72. package/plugins/runtime-modules/accounting/presets.js +37 -0
  73. package/plugins/runtime-modules/accounting/server.d.ts +1 -4
  74. package/plugins/runtime-modules/accounting/server.js +4 -7
  75. package/plugins/runtime-modules/app/presets.d.ts +18 -0
  76. package/plugins/runtime-modules/app/presets.js +67 -0
  77. package/plugins/runtime-modules/app/server.d.ts +1 -4
  78. package/plugins/runtime-modules/app/server.js +4 -7
  79. package/plugins/runtime-modules/asset/controller/runtime.js +2 -2
  80. package/plugins/runtime-modules/asset/services/collection.js +9 -1
  81. package/plugins/runtime-modules/asset/services/options.js +2 -2
  82. package/plugins/runtime-modules/builder/area-settings-answer.js +2 -1
  83. package/plugins/runtime-modules/builder/authoring-canvas.js +6 -6
  84. package/plugins/runtime-modules/builder/cards.js +3 -5
  85. package/plugins/runtime-modules/builder/clients/builder-region-overrides.js +3 -3
  86. package/plugins/runtime-modules/builder/clients/canvas-widget.js +15 -54
  87. package/plugins/runtime-modules/builder/clients/inspector-config-field.d.ts +4 -1
  88. package/plugins/runtime-modules/builder/clients/inspector-config-field.js +5 -34
  89. package/plugins/runtime-modules/builder/clients/inspector-link-target-field.js +1 -1
  90. package/plugins/runtime-modules/builder/clients/inspector-section-widget.js +8 -8
  91. package/plugins/runtime-modules/builder/clients/inspector-title.js +6 -6
  92. package/plugins/runtime-modules/builder/clients/layout-inspector.d.ts +1 -1
  93. package/plugins/runtime-modules/builder/clients/layout-inspector.js +11 -25
  94. package/plugins/runtime-modules/builder/clients/mode-switch.js +1 -1
  95. package/plugins/runtime-modules/builder/clients/pages-header.js +11 -11
  96. package/plugins/runtime-modules/builder/clients/pages-workspace.js +1 -1
  97. package/plugins/runtime-modules/builder/clients/region-visibility-fields.js +1 -1
  98. package/plugins/runtime-modules/builder/clients/runtime-module-authoring-boundary.js +1 -1
  99. package/plugins/runtime-modules/builder/clients/shells-workspace.js +15 -31
  100. package/plugins/runtime-modules/builder/clients/structure-canvas.js +1 -1
  101. package/plugins/runtime-modules/builder/clients/use-region-draft-hydration.d.ts +26 -0
  102. package/plugins/runtime-modules/builder/clients/use-region-draft-hydration.js +36 -0
  103. package/plugins/runtime-modules/builder/clients/widget-effects-editor.js +1 -1
  104. package/plugins/runtime-modules/builder/clients/widget-inspector.js +1 -0
  105. package/plugins/runtime-modules/builder/clients/workspace-scope-boundary.js +2 -2
  106. package/plugins/runtime-modules/builder/cms-instance-allocator.js +8 -28
  107. package/plugins/runtime-modules/builder/controller/client.d.ts +0 -15
  108. package/plugins/runtime-modules/builder/controller/definition.d.ts +0 -15
  109. package/plugins/runtime-modules/builder/controller/definition.js +0 -8
  110. package/plugins/runtime-modules/builder/controller/draft-command-controller.d.ts +1 -2
  111. package/plugins/runtime-modules/builder/controller/draft-command-controller.js +11 -30
  112. package/plugins/runtime-modules/builder/controller/draft-status-controller.js +15 -2
  113. package/plugins/runtime-modules/builder/controller/inspector-controller.d.ts +1 -2
  114. package/plugins/runtime-modules/builder/controller/inspector-controller.js +4 -7
  115. package/plugins/runtime-modules/builder/controller/page-controller.d.ts +1 -2
  116. package/plugins/runtime-modules/builder/controller/page-controller.js +16 -68
  117. package/plugins/runtime-modules/builder/controller/server-definition.d.ts +0 -15
  118. package/plugins/runtime-modules/builder/controller/signal-wiring-controller.d.ts +2 -5
  119. package/plugins/runtime-modules/builder/controller/signal-wiring-controller.js +6 -50
  120. package/plugins/runtime-modules/builder/controller/workspace-controller.d.ts +2 -3
  121. package/plugins/runtime-modules/builder/controller/workspace-controller.js +89 -153
  122. package/plugins/runtime-modules/builder/data-providers.d.ts +1 -0
  123. package/plugins/runtime-modules/builder/data-providers.js +1 -0
  124. package/plugins/runtime-modules/builder/definition.d.ts +1 -0
  125. package/plugins/runtime-modules/builder/developer-workspace-store.d.ts +64 -30
  126. package/plugins/runtime-modules/builder/developer-workspace-store.js +255 -61
  127. package/plugins/runtime-modules/builder/edit-scaffold-drawer.js +1 -1
  128. package/plugins/runtime-modules/builder/history.d.ts +3 -1
  129. package/plugins/runtime-modules/builder/options-providers.js +3 -2
  130. package/plugins/runtime-modules/builder/page-catalog-client.js +19 -7
  131. package/plugins/runtime-modules/builder/page-meta-form.js +1 -0
  132. package/plugins/runtime-modules/builder/page-references-provider.js +1 -1
  133. package/plugins/runtime-modules/builder/persistence.js +33 -69
  134. package/plugins/runtime-modules/builder/public-route-collisions.d.ts +2 -2
  135. package/plugins/runtime-modules/builder/public-route-collisions.js +6 -19
  136. package/plugins/runtime-modules/builder/render-root-node-preview.server.js +20 -3
  137. package/plugins/runtime-modules/builder/render-root-node-scaffold.js +3 -3
  138. package/plugins/runtime-modules/builder/runtime-module-selection.d.ts +2 -12
  139. package/plugins/runtime-modules/builder/runtime-module-selection.js +16 -42
  140. package/plugins/runtime-modules/builder/services/navigation-table.js +9 -15
  141. package/plugins/runtime-modules/builder/services/page-source-tree.js +8 -8
  142. package/plugins/runtime-modules/builder/services/runtime-modules-table.js +10 -10
  143. package/plugins/runtime-modules/builder/services/signal-routes-table.js +3 -3
  144. package/plugins/runtime-modules/builder/signal-route-selection.d.ts +1 -2
  145. package/plugins/runtime-modules/builder/signal-route-selection.js +2 -2
  146. package/plugins/runtime-modules/builder/signal-wiring-options.js +3 -2
  147. package/plugins/runtime-modules/builder/structure-dnd.js +8 -61
  148. package/plugins/runtime-modules/builder/trees/phi-default-builder-area-preset-tree.js +13 -10
  149. package/plugins/runtime-modules/builder/widgets/structure-region/built-in.js +12 -18
  150. package/plugins/runtime-modules/builder/workspace-catalog-actions.d.ts +55 -0
  151. package/plugins/runtime-modules/builder/workspace-catalog-actions.js +142 -0
  152. package/plugins/runtime-modules/client-manifests/common.js +1 -1
  153. package/plugins/runtime-modules/{runtime-calendar-adapters.js → core/calendar-adapters.js} +2 -2
  154. package/plugins/runtime-modules/{client-calendar-adapters/core.js → core/client-calendar-adapters.js} +1 -1
  155. package/plugins/runtime-modules/core/content-entries/table.js +1 -1
  156. package/plugins/runtime-modules/core/data-providers.d.ts +3 -0
  157. package/plugins/runtime-modules/core/data-providers.js +2 -1
  158. package/plugins/runtime-modules/core/definition.d.ts +3 -0
  159. package/plugins/runtime-modules/core/definition.js +1 -1
  160. package/plugins/runtime-modules/core/messaging/data-providers.d.ts +1 -0
  161. package/plugins/runtime-modules/core/messaging/data-providers.js +1 -0
  162. package/plugins/runtime-modules/core/messaging/thread-inbox-table.js +1 -1
  163. package/plugins/runtime-modules/core/server.js +1 -1
  164. package/plugins/runtime-modules/core/themes.d.ts +44 -0
  165. package/plugins/runtime-modules/core/themes.js +12 -0
  166. package/plugins/runtime-modules/core/widgets/card/collection-view-binding.js +25 -9
  167. package/plugins/runtime-modules/core/widgets/card/config.d.ts +296 -254
  168. package/plugins/runtime-modules/core/widgets/card/config.js +52 -3
  169. package/plugins/runtime-modules/core/widgets/card/editor.js +30 -3
  170. package/plugins/runtime-modules/core/widgets/card/server.d.ts +3 -0
  171. package/plugins/runtime-modules/core/widgets/card/server.js +31 -3
  172. package/plugins/runtime-modules/core/widgets/collection-view/asset-binding.js +7 -6
  173. package/plugins/runtime-modules/core/widgets/collection-view/config.js +9 -2
  174. package/plugins/runtime-modules/core/widgets/description/config.d.ts +1 -25
  175. package/plugins/runtime-modules/core/widgets/description/editor.js +4 -61
  176. package/plugins/runtime-modules/core/widgets/entry-list/config.d.ts +1 -25
  177. package/plugins/runtime-modules/core/widgets/gallery/config.d.ts +1 -25
  178. package/plugins/runtime-modules/core/widgets/image/config.js +2 -2
  179. package/plugins/runtime-modules/core/widgets/markdown/editor.js +2 -3
  180. package/plugins/runtime-modules/core/widgets/result/config.d.ts +4 -25
  181. package/plugins/runtime-modules/core/widgets/result/config.js +2 -0
  182. package/plugins/runtime-modules/core/widgets/result/server.js +25 -19
  183. package/plugins/runtime-modules/core/widgets/simple-text/config.d.ts +1 -25
  184. package/plugins/runtime-modules/core/widgets/slot-upload/client.js +11 -2
  185. package/plugins/runtime-modules/core/widgets/table/client.js +8 -4
  186. package/plugins/runtime-modules/core/widgets/table/config.d.ts +3 -83
  187. package/plugins/runtime-modules/core/widgets/table/config.js +302 -452
  188. package/plugins/runtime-modules/core/widgets/tree/config.js +5 -2
  189. package/plugins/runtime-modules/dashboard/card-rows.d.ts +5 -0
  190. package/plugins/runtime-modules/dashboard/card-rows.js +59 -0
  191. package/plugins/runtime-modules/dashboard/clients/dashboard-card-view.js +4 -6
  192. package/plugins/runtime-modules/dashboard/services/collection.js +17 -7
  193. package/plugins/runtime-modules/groups/data-providers.d.ts +2 -0
  194. package/plugins/runtime-modules/groups/data-providers.js +3 -3
  195. package/plugins/runtime-modules/groups/definition.d.ts +2 -0
  196. package/plugins/runtime-modules/localization/data-providers.d.ts +3 -0
  197. package/plugins/runtime-modules/localization/data-providers.js +2 -0
  198. package/plugins/runtime-modules/localization/definition.d.ts +3 -0
  199. package/plugins/runtime-modules/localization/services/table.js +3 -7
  200. package/plugins/runtime-modules/observability/data-providers.d.ts +1 -0
  201. package/plugins/runtime-modules/observability/data-providers.js +1 -0
  202. package/plugins/runtime-modules/observability/definition.d.ts +1 -0
  203. package/plugins/runtime-modules/observability/module.d.ts +1 -0
  204. package/plugins/runtime-modules/observability/services/table.js +1 -1
  205. package/plugins/runtime-modules/phi-default-site-area-preset-tree.js +2 -105
  206. package/plugins/runtime-modules/public/presets.d.ts +115 -0
  207. package/plugins/runtime-modules/{area-base-presets.js → public/presets.js} +19 -119
  208. package/plugins/runtime-modules/public/server.d.ts +1 -4
  209. package/plugins/runtime-modules/public/server.js +4 -7
  210. package/plugins/runtime-modules/public/trees/phi-default-pub-error-page-tree.js +7 -8
  211. package/plugins/runtime-modules/public-base-page-references.d.ts +1 -1
  212. package/plugins/runtime-modules/public-base-page-references.js +1 -1
  213. package/plugins/runtime-modules/revisions/controller/client.js +11 -11
  214. package/plugins/runtime-modules/revisions/services/table.js +3 -3
  215. package/plugins/runtime-modules/theme/trees/phi-default-builder-theme-page-tree.js +22 -0
  216. package/plugins/runtime-modules/theme/widgets/brand-controls/client.d.ts +2 -1
  217. package/plugins/runtime-modules/theme/widgets/brand-controls/client.js +93 -58
  218. package/plugins/runtime-modules/theme/widgets/brand-controls/config.d.ts +2 -1
  219. package/plugins/runtime-modules/theme/widgets/brand-controls/config.js +23 -22
  220. package/plugins/runtime-modules/theme/widgets/brand-controls/plugin.js +1 -1
  221. package/plugins/runtime-modules/theme-descriptors.js +1 -1
  222. package/plugins/runtime-modules/user-management/data-providers.d.ts +2 -0
  223. package/plugins/runtime-modules/user-management/data-providers.js +1 -0
  224. package/plugins/runtime-modules/user-management/definition.d.ts +2 -0
  225. package/styles/control-shape.css +11 -11
  226. package/styles/controls.css +3 -3
  227. package/styles/layout.css +16 -7
  228. package/types/cms-config.js +142 -185
  229. package/types/cms-plugins.d.ts +4 -11
  230. package/types/core-widget-placements.d.ts +14 -3
  231. package/types/dashboard-cards.d.ts +9 -0
  232. package/types/media.d.ts +0 -3
  233. package/types/renderable-block.d.ts +6 -1
  234. package/types/table-widget.d.ts +9 -0
  235. package/types/table-widget.js +20 -0
  236. package/types.d.ts +1 -1
  237. package/widget-config.d.ts +2 -0
  238. package/widget-config.js +6 -0
  239. package/plugins/runtime-modules/area-base-presets.d.ts +0 -139
  240. /package/plugins/runtime-modules/{runtime-calendar-adapters.d.ts → core/calendar-adapters.d.ts} +0 -0
  241. /package/plugins/runtime-modules/{client-calendar-adapters/core.d.ts → core/client-calendar-adapters.d.ts} +0 -0
@@ -0,0 +1,26 @@
1
+ import type { PhiDeveloperBuilderRegionDraft } from "../developer-workspace-types";
2
+ import type { PhiBuilderPreviewRegionDraft } from "../preview-transport";
3
+ /**
4
+ * Brings the server's Region drafts into the Builder store -- only the ones the store does not hold yet.
5
+ *
6
+ * The Shells and the Pages workspace each did this for themselves, and differently. The Shells workspace
7
+ * merged every server draft of an Area whenever the Area changed, over whatever the store held: an
8
+ * unsaved edit to the Public shell was gone after a look at the Admin shell and back, while the Undo
9
+ * button still offered to take it back. A draft in the store is the author's; the server's answer only
10
+ * fills what is missing.
11
+ *
12
+ * It renders again only when the set of missing drafts changes. Subscribing to the whole draft map for
13
+ * that question re-rendered the workspace, and every Region scaffold below it, on every write to any
14
+ * draft.
15
+ *
16
+ * A preview snapshot is the exception: in preview mode the drafts it carries are what is being looked at,
17
+ * so they are merged as they are.
18
+ */
19
+ export declare function usePhiBuilderRegionDraftHydration({ draftKeys, serverDrafts, builderMode, previewRegionDrafts, }: {
20
+ /** The drafts this workspace shows. */
21
+ draftKeys: readonly string[];
22
+ /** What the server answered for them, keyed like the store. */
23
+ serverDrafts: Readonly<Record<string, PhiDeveloperBuilderRegionDraft | null | undefined>> | null | undefined;
24
+ builderMode: string;
25
+ previewRegionDrafts: Record<string, PhiBuilderPreviewRegionDraft> | null | undefined;
26
+ }): void;
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import { useCallback, useEffect } from "react";
3
+ import { getPhiDeveloperRegionDraftsSnapshot, mergePhiDeveloperRegionDrafts, usePhiDeveloperRegionDraftsValue, } from "../developer-workspace-store";
4
+ /**
5
+ * Brings the server's Region drafts into the Builder store -- only the ones the store does not hold yet.
6
+ *
7
+ * The Shells and the Pages workspace each did this for themselves, and differently. The Shells workspace
8
+ * merged every server draft of an Area whenever the Area changed, over whatever the store held: an
9
+ * unsaved edit to the Public shell was gone after a look at the Admin shell and back, while the Undo
10
+ * button still offered to take it back. A draft in the store is the author's; the server's answer only
11
+ * fills what is missing.
12
+ *
13
+ * It renders again only when the set of missing drafts changes. Subscribing to the whole draft map for
14
+ * that question re-rendered the workspace, and every Region scaffold below it, on every write to any
15
+ * draft.
16
+ *
17
+ * A preview snapshot is the exception: in preview mode the drafts it carries are what is being looked at,
18
+ * so they are merged as they are.
19
+ */
20
+ export function usePhiBuilderRegionDraftHydration({ draftKeys, serverDrafts, builderMode, previewRegionDrafts, }) {
21
+ const missingDraftKeys = usePhiDeveloperRegionDraftsValue(useCallback((drafts) => draftKeys.filter((draftKey) => drafts[draftKey] == null).join("\u0000"), [draftKeys]));
22
+ useEffect(() => {
23
+ if (builderMode === "preview" && previewRegionDrafts && Object.keys(previewRegionDrafts).length > 0) {
24
+ mergePhiDeveloperRegionDrafts(previewRegionDrafts);
25
+ }
26
+ if (!missingDraftKeys || !serverDrafts) {
27
+ return;
28
+ }
29
+ // `missingDraftKeys` is the reason to run again; the snapshot is what is read.
30
+ const regionDrafts = getPhiDeveloperRegionDraftsSnapshot();
31
+ const missingDrafts = Object.fromEntries(Object.entries(serverDrafts).filter((entry) => entry[1] != null && regionDrafts[entry[0]] == null));
32
+ if (Object.keys(missingDrafts).length > 0) {
33
+ mergePhiDeveloperRegionDrafts(missingDrafts);
34
+ }
35
+ }, [builderMode, missingDraftKeys, previewRegionDrafts, serverDrafts]);
36
+ }
@@ -9,7 +9,7 @@ export function PhiWidgetEffectsToolButton({ effects, target, disabled = false,
9
9
  const open = () => {
10
10
  if (disabled || !onChange)
11
11
  return;
12
- openPhiDeveloperBuilderEffectsEditor("public", effects ?? {}, target, onChange);
12
+ openPhiDeveloperBuilderEffectsEditor(effects ?? {}, target, onChange);
13
13
  };
14
14
  return (_jsx("div", { className: "phi-layout-affordance phi-layout-affordance--effects", onMouseDown: (event) => { event.preventDefault(); event.stopPropagation(); }, onClick: (event) => event.stopPropagation(), style: { "--phi-layout-affordance-size": "var(--ant-control-height-sm)" }, children: _jsx(PhiButtonControl, { ariaLabel: labels.openEditor, tooltip: labels.openEditor, icon: _jsx(PhiIcon, { name: "node-index", size: "inherit" }), type: "text", size: "small", disabled: disabled || !onChange, onClick: open }) }));
15
15
  }
@@ -74,6 +74,7 @@ export function PhiDeveloperBuilderWidgetInspectorWidgetClient({ section, builde
74
74
  widgetReferenceOptions,
75
75
  backgroundLabels,
76
76
  borderLabels,
77
+ renderMediaPicker,
77
78
  colorPickerLabels,
78
79
  iconPickerLabels,
79
80
  fieldLabels,
@@ -8,8 +8,8 @@ import { usePhiSignalIdentity } from "../../../../components/runtime/runtime-sig
8
8
  import { usePhiVisualAnchorParts } from "../../../../components/runtime/runtime-visual-anchors";
9
9
  import { PHI_BUILDER_PAGE_REGION_KEYS, PHI_BUILDER_SHELL_REGION_KEYS } from "../region-keys";
10
10
  export function PhiBuilderWorkspaceScopeBoundary({ kind, targetArea, targetPageKey, children, }) {
11
- const activeArea = usePhiDeveloperBuilderStateValue("public", (state) => state.area);
12
- const activePageKey = usePhiDeveloperBuilderStateValue("public", (state) => state.pageKey);
11
+ const activeArea = usePhiDeveloperBuilderStateValue((state) => state.area);
12
+ const activePageKey = usePhiDeveloperBuilderStateValue((state) => state.pageKey);
13
13
  const scopeMatches = activeArea === targetArea &&
14
14
  (targetPageKey == null || activePageKey === targetPageKey);
15
15
  /*
@@ -2,7 +2,7 @@
2
2
  import { createPhiDraftCmsInstanceId } from "../../../types/cms-instance-id";
3
3
  import { isPhiBuilderPageScopedRegion } from "./region-keys";
4
4
  import { getPhiDeveloperBuilderDraftAllocation, savePhiDeveloperBuilderDraft, } from "./persistence";
5
- import { builderWorkspaceStore, getPhiDeveloperBuilderStateSnapshot, getPhiDeveloperRegionDraftsSnapshot, } from "./developer-workspace-store";
5
+ import { takePhiBuilderDraftNodeSequence, getPhiDeveloperBuilderStateSnapshot, getPhiDeveloperRegionDraftsSnapshot, } from "./developer-workspace-store";
6
6
  import { createPhiBuilderDraftAllocationKey } from "./draft-allocation-key";
7
7
  import { resolvePhiBuilderActivePageCatalog } from "../../../helpers/cms-page-catalog";
8
8
  const pendingDraftCreations = new Map();
@@ -11,13 +11,13 @@ function getPhiBuilderDraftAllocationKey(area, pageKey, regionKey) {
11
11
  }
12
12
  async function ensurePhiBuilderDraftAllocation(input) {
13
13
  const allocationKey = getPhiBuilderDraftAllocationKey(input.area, input.pageKey, input.regionKey);
14
- if (getPhiDeveloperBuilderStateSnapshot("public").draftAllocations[allocationKey]) {
14
+ if (getPhiDeveloperBuilderStateSnapshot().draftAllocations[allocationKey]) {
15
15
  return;
16
16
  }
17
17
  let pending = pendingDraftCreations.get(allocationKey);
18
18
  if (!pending) {
19
19
  pending = (async () => {
20
- const state = getPhiDeveloperBuilderStateSnapshot("public");
20
+ const state = getPhiDeveloperBuilderStateSnapshot();
21
21
  const workspaceKind = isPhiBuilderPageScopedRegion(input.regionKey) ? "pages" : "structure";
22
22
  const existing = await getPhiDeveloperBuilderDraftAllocation({
23
23
  area: input.area,
@@ -44,30 +44,10 @@ async function ensurePhiBuilderDraftAllocation(input) {
44
44
  export async function allocatePhiBuilderCmsInstanceId(input) {
45
45
  await ensurePhiBuilderDraftAllocation(input);
46
46
  const allocationKey = getPhiBuilderDraftAllocationKey(input.area, input.pageKey, input.regionKey);
47
- let allocated = null;
48
- builderWorkspaceStore.patch("public", (current) => {
49
- const allocation = current.draftAllocations[allocationKey];
50
- if (!allocation) {
51
- throw new Error(`Missing Draft allocation state for "${allocationKey}".`);
52
- }
53
- allocated = createPhiDraftCmsInstanceId({
54
- domain: isPhiBuilderPageScopedRegion(input.regionKey) ? "page" : "area",
55
- draftRevisionId: allocation.revisionId,
56
- sequence: allocation.nextNodeSequence,
57
- });
58
- return {
59
- ...current,
60
- draftAllocations: {
61
- ...current.draftAllocations,
62
- [allocationKey]: {
63
- ...allocation,
64
- nextNodeSequence: allocation.nextNodeSequence + 1,
65
- },
66
- },
67
- };
47
+ const allocation = takePhiBuilderDraftNodeSequence(allocationKey);
48
+ return createPhiDraftCmsInstanceId({
49
+ domain: isPhiBuilderPageScopedRegion(input.regionKey) ? "page" : "area",
50
+ draftRevisionId: allocation.revisionId,
51
+ sequence: allocation.nextNodeSequence,
68
52
  });
69
- if (!allocated) {
70
- throw new Error(`Failed to allocate a CMS instance id for "${allocationKey}".`);
71
- }
72
- return allocated;
73
53
  }
@@ -11,20 +11,10 @@ export declare const PHI_BUILDER_RUNTIME_CONTROLLER_PLUGIN: {
11
11
  allowedMountScopes: "area"[];
12
12
  runtimeSignals: {
13
13
  emits: ({
14
- id: string;
15
- action: "start";
16
- valueType: "json";
17
- valueSchema: `${string}/signals/${string}`;
18
- } | {
19
14
  id: string;
20
15
  action: "change";
21
16
  valueType: "json";
22
17
  valueSchema: `${string}/signals/${string}`;
23
- } | {
24
- id: string;
25
- action: "stop";
26
- valueType: "json";
27
- valueSchema: `${string}/signals/${string}`;
28
18
  } | {
29
19
  id: string;
30
20
  action: "activate";
@@ -48,11 +38,6 @@ export declare const PHI_BUILDER_RUNTIME_CONTROLLER_PLUGIN: {
48
38
  action: "change";
49
39
  valueType: "boolean";
50
40
  valueSchema?: undefined;
51
- } | {
52
- id: string;
53
- action: "drop";
54
- valueType: "json";
55
- valueSchema: `${string}/signals/${string}`;
56
41
  })[];
57
42
  listens: ({
58
43
  id: string;
@@ -60,20 +60,10 @@ export declare const PHI_BUILDER_RUNTIME_CONTROLLER_DEFINITION: {
60
60
  allowedMountScopes: "area"[];
61
61
  runtimeSignals: {
62
62
  emits: ({
63
- id: string;
64
- action: "start";
65
- valueType: "json";
66
- valueSchema: `${string}/signals/${string}`;
67
- } | {
68
63
  id: string;
69
64
  action: "change";
70
65
  valueType: "json";
71
66
  valueSchema: `${string}/signals/${string}`;
72
- } | {
73
- id: string;
74
- action: "stop";
75
- valueType: "json";
76
- valueSchema: `${string}/signals/${string}`;
77
67
  } | {
78
68
  id: string;
79
69
  action: "activate";
@@ -97,11 +87,6 @@ export declare const PHI_BUILDER_RUNTIME_CONTROLLER_DEFINITION: {
97
87
  action: "change";
98
88
  valueType: "boolean";
99
89
  valueSchema?: undefined;
100
- } | {
101
- id: string;
102
- action: "drop";
103
- valueType: "json";
104
- valueSchema: `${string}/signals/${string}`;
105
90
  })[];
106
91
  listens: ({
107
92
  id: string;
@@ -1,6 +1,5 @@
1
1
  import { PHI_SIGNAL_VALUE_SCHEMAS, readPhiSignalRouteSet, } from "../../../../types/signals";
2
2
  import { PHI_BUILDER_CONTROLLER_KEY, PHI_BUILDER_CONTROLLER_PLUGIN_KEY } from "./address";
3
- import { PHI_DRAG_SOURCE_CONTROL_SIGNALS } from "../../../../components/widgets/signals/control-signal-capabilities";
4
3
  import { PHI_BUILDER_CHROME_WIDGET_DEFAULT_LABELS } from "../../../../components/widgets/label-types/builder-chrome";
5
4
  /** The three Effects Forms, each with its own values, submit and reset. */
6
5
  export const PHI_BUILDER_EFFECTS_CAPABILITY_SECTIONS = ["appearance", "transitions", "viewport"];
@@ -136,13 +135,6 @@ export const PHI_BUILDER_RUNTIME_CONTROLLER_DEFINITION = {
136
135
  ...dialogEmits("publicRoutes"),
137
136
  { id: "publicRoutesReload", action: "activate", valueType: "none" },
138
137
  { id: "modulesTableReload", action: "activate", valueType: "none" },
139
- ...PHI_DRAG_SOURCE_CONTROL_SIGNALS.emits,
140
- {
141
- id: "drop",
142
- action: "drop",
143
- valueType: "json",
144
- valueSchema: PHI_SIGNAL_VALUE_SCHEMAS.dragDrop,
145
- },
146
138
  ],
147
139
  listens: [
148
140
  {
@@ -2,8 +2,7 @@ import { type PhiHistoryLabels } from "../../../../components/widgets/label-type
2
2
  import type { PhiBuilderSavedHistoryHead } from "./draft-status-controller";
3
3
  import type { PhiDeveloperBuilderArea, PhiDeveloperBuilderRegionDraft, PhiDeveloperBuilderWorkspaceState } from "../developer-workspace-types";
4
4
  export type PhiDeveloperBuilderToolbarCommand = "save" | "preview" | "publish" | "undo" | "redo" | "reset";
5
- export declare function usePhiBuilderDraftCommandController({ defaultArea, effectiveArea, effectiveNavKey, effectivePageKey, pathname, captureHistoryHead, reportSaved, hasUnsavedChanges, shellPresetDraftsByArea, state, historyLabels, }: {
6
- defaultArea: PhiDeveloperBuilderArea;
5
+ export declare function usePhiBuilderDraftCommandController({ effectiveArea, effectiveNavKey, effectivePageKey, pathname, captureHistoryHead, reportSaved, hasUnsavedChanges, shellPresetDraftsByArea, state, historyLabels, }: {
7
6
  effectiveArea: PhiDeveloperBuilderArea;
8
7
  effectiveNavKey: string;
9
8
  effectivePageKey: string;
@@ -12,15 +12,14 @@ import { deleteCmsDraft } from "../../../../helpers/cms-draft-delete";
12
12
  import { buildPhiBuilderLiveHref, clearPhiDeveloperBuilderDraftAllocation, createPhiDeveloperBuilderInitialPageDrafts, getPhiDeveloperBuilderModulesDraftAllocation, savePhiDeveloperBuilderModulesDraft, publishPhiDeveloperBuilderModulesDraft, previewPhiDeveloperBuilderDraft, publishPhiDeveloperBuilderDraft, savePhiDeveloperBuilderDraft, } from "../persistence";
13
13
  import { clearPhiBuilderNavigationDraft, getPhiBuilderNavigationDraftSnapshot, updatePhiBuilderNavigationDraft, restorePhiBuilderNavigationDraft, setPhiBuilderNavigationDraft, } from "../navigation-store";
14
14
  import { deletePhiBuilderNavigationDraft, loadPhiBuilderNavigationDraft, loadPhiBuilderNavigationScope, publishPhiBuilderNavigationDraft, savePhiBuilderNavigationDraft, } from "../navigation-persistence";
15
- import { builderWorkspaceStore, splitWorkspacePatch, getPhiDeveloperRegionDraftsSnapshot, mergePhiDeveloperRegionDrafts, restorePhiDeveloperBuilderAreaMeta, restorePhiDeveloperRegionDrafts, setPhiDeveloperBuilderAreaRootRoute, } from "../developer-workspace-store";
15
+ import { clearPhiBuilderModuleAreasDirty, getPhiDeveloperRegionDraftsSnapshot, markPhiBuilderPageDeleted, restorePhiBuilderWorkspaceState, mergePhiDeveloperRegionDrafts, restorePhiDeveloperBuilderAreaMeta, restorePhiDeveloperRegionDrafts, setPhiDeveloperBuilderAreaRootRoute, } from "../developer-workspace-store";
16
16
  import { findPhiBuilderNavigationSurface } from "../../../../helpers/cms-navigation-catalog";
17
17
  import { createPhiBuilderHistoryContext, phiBuilderHistory, } from "../history";
18
18
  import { usePhiBuilderModuleMetas } from "../plugin-meta-store";
19
- import { clearPhiBuilderModuleAreasDirty } from "../runtime-module-selection";
20
- import { phiWorkspaceCatalogStore } from "../../../../components/workspace/catalog-store";
19
+ import { setPhiWorkspaceModuleSelection } from "../workspace-catalog-actions";
21
20
  import { applyPhiBuilderNavigationFolderTargets, refreshPhiBuilderNavigationFolderAddresses, } from "../navigation-folder-address";
22
21
  import { createPhiBuilderNavigationPathContext } from "../navigation-path-context";
23
- export function usePhiBuilderDraftCommandController({ defaultArea, effectiveArea, effectiveNavKey, effectivePageKey, pathname, captureHistoryHead, reportSaved, hasUnsavedChanges, shellPresetDraftsByArea, state, historyLabels, }) {
22
+ export function usePhiBuilderDraftCommandController({ effectiveArea, effectiveNavKey, effectivePageKey, pathname, captureHistoryHead, reportSaved, hasUnsavedChanges, shellPresetDraftsByArea, state, historyLabels, }) {
24
23
  /*
25
24
  * Every one of these is a command from a toolbar somewhere else, so there is nothing on screen to
26
25
  * hang a Popconfirm on. Drawn as a Dialog by this Controller rather than asked of Ant Design's
@@ -212,7 +211,7 @@ export function usePhiBuilderDraftCommandController({ defaultArea, effectiveArea
212
211
  scope: { area },
213
212
  });
214
213
  }
215
- clearPhiBuilderModuleAreasDirty(defaultArea);
214
+ clearPhiBuilderModuleAreasDirty();
216
215
  reportSaved("published", null, savedAt);
217
216
  showMessage({
218
217
  level: "success",
@@ -387,13 +386,7 @@ export function usePhiBuilderDraftCommandController({ defaultArea, effectiveArea
387
386
  });
388
387
  const pageDeleteDraftKey = getPhiBuilderRegionDraftKey(effectiveArea, "page_delete", effectivePageKey);
389
388
  mergePhiDeveloperRegionDrafts(nextDrafts);
390
- builderWorkspaceStore.patch(defaultArea, (current) => ({
391
- ...current,
392
- deletedPageDrafts: {
393
- ...current.deletedPageDrafts,
394
- [pageDeleteDraftKey]: true,
395
- },
396
- }));
389
+ markPhiBuilderPageDeleted(pageDeleteDraftKey);
397
390
  const result = await savePhiDeveloperBuilderDraft({
398
391
  ...state,
399
392
  deletedPageDrafts: {
@@ -524,30 +517,18 @@ export function usePhiBuilderDraftCommandController({ defaultArea, effectiveArea
524
517
  return;
525
518
  }
526
519
  if (snapshot.kind === "modules") {
527
- phiWorkspaceCatalogStore.patch(defaultArea, (current) => ({
528
- ...current,
529
- runtimeModuleIdsByArea: {
530
- ...(current.runtimeModuleIdsByArea ?? {}),
531
- // `null` recorded "no selection stored", which resolves to the Area's default set.
532
- ...Object.fromEntries(Object.entries(snapshot.moduleIdsByArea).map(([area, moduleIds]) => [
533
- area,
534
- moduleIds ? [...moduleIds] : createPhiDefaultAreaRuntimeModuleIds(area),
535
- ])),
536
- },
537
- }));
520
+ setPhiWorkspaceModuleSelection(Object.fromEntries(Object.entries(snapshot.moduleIdsByArea).map(([area, moduleIds]) => [
521
+ area,
522
+ // `null` recorded "no selection stored", which resolves to the Area's default set.
523
+ moduleIds ? [...moduleIds] : createPhiDefaultAreaRuntimeModuleIds(area),
524
+ ])));
538
525
  return;
539
526
  }
540
527
  /*
541
528
  * A workspace snapshot spans both halves -- customPages belongs to the catalog, the page drafts
542
529
  * to the Builder -- so undo has to put each back where it lives.
543
530
  */
544
- const { catalog, tool } = splitWorkspacePatch(snapshot.state);
545
- if (Object.keys(catalog).length > 0) {
546
- phiWorkspaceCatalogStore.patch(defaultArea, (current) => ({ ...current, ...catalog }));
547
- }
548
- if (Object.keys(tool).length > 0) {
549
- builderWorkspaceStore.patch(defaultArea, (current) => ({ ...current, ...tool }));
550
- }
531
+ restorePhiBuilderWorkspaceState(snapshot.state);
551
532
  };
552
533
  /*
553
534
  * An undo says what it took back. The canvas changes in place, and a step that moved a node out of
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { useCallback, useEffect, useState } from "react";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
3
  import { PHI_SIGNAL_VALUE_SCHEMAS } from "../../../../types/signals";
4
4
  import { usePhiSignalDispatcher, usePhiSignalListener } from "../../../../components/runtime/runtime-signal-bus";
5
5
  import { resolvePhiBuilderCmsStoragePath } from "../../../../helpers/cms-paths";
@@ -82,6 +82,13 @@ export function usePhiBuilderDraftStatusController({ commandWorkspace, effective
82
82
  const subject = target?.subject ?? null;
83
83
  const historyContext = target?.historyContext ?? null;
84
84
  const [stored, setStored] = useState(null);
85
+ /*
86
+ * The history head each target was last saved or first read at. The status is read again whenever the
87
+ * target changes -- an Area switched away from and back -- and taking the head at that moment called
88
+ * every edit made before it saved: back on an Area with an unsaved edit, the badge said "Published".
89
+ * A target keeps the head it was read or saved at until it is saved again.
90
+ */
91
+ const savedHeadsRef = useRef(new Map());
85
92
  const historyHead = phiBuilderHistory.useHead(historyContext ?? PHI_BUILDER_NO_DRAFT_HISTORY_CONTEXT);
86
93
  useEffect(() => {
87
94
  if (targetUrl === null) {
@@ -95,7 +102,12 @@ export function usePhiBuilderDraftStatusController({ commandWorkspace, effective
95
102
  setStored({
96
103
  requestKey: targetUrl,
97
104
  ...next,
98
- savedHead: historyContext === null ? null : phiBuilderHistory.getHead(historyContext),
105
+ savedHead: (() => {
106
+ if (!savedHeadsRef.current.has(targetUrl)) {
107
+ savedHeadsRef.current.set(targetUrl, historyContext === null ? null : phiBuilderHistory.getHead(historyContext));
108
+ }
109
+ return savedHeadsRef.current.get(targetUrl);
110
+ })(),
99
111
  });
100
112
  };
101
113
  void fetch(targetUrl, { method: "GET", cache: "no-store" })
@@ -177,6 +189,7 @@ export function usePhiBuilderDraftStatusController({ commandWorkspace, effective
177
189
  if (targetUrl === null) {
178
190
  return;
179
191
  }
192
+ savedHeadsRef.current.set(targetUrl, savedAt.head);
180
193
  setStored({
181
194
  requestKey: targetUrl,
182
195
  status,
@@ -1,3 +1,2 @@
1
1
  import type { PhiBuilderInspectorAction } from "../inspector-actions";
2
- import type { PhiDeveloperBuilderArea } from "../developer-workspace-types";
3
- export declare function runPhiDeveloperBuilderInspectorAction(defaultArea: PhiDeveloperBuilderArea, action: PhiBuilderInspectorAction): void;
2
+ export declare function runPhiDeveloperBuilderInspectorAction(action: PhiBuilderInspectorAction): void;
@@ -5,7 +5,7 @@ import { findPhiBuilderTreeNode, writePhiBuilderNode } from "../node-config-writ
5
5
  import { getDefaultRegionDraft, resolveRegionDraftKey, } from "../developer-region-drafts";
6
6
  import { getPhiBuilderRegionDraftKey, isPhiBuilderPageScopedRegion, } from "../region-keys";
7
7
  import { createPhiBuilderRegionHistoryContext } from "../history";
8
- import { builderWorkspaceStore, getPhiDeveloperRegionDraftsSnapshot, setPhiDeveloperRegionDraft, getPhiDeveloperBuilderStateSnapshot, } from "../developer-workspace-store";
8
+ import { setPhiBuilderSelectedLayoutAnchor, getPhiDeveloperRegionDraftsSnapshot, setPhiDeveloperRegionDraft, getPhiDeveloperBuilderStateSnapshot, } from "../developer-workspace-store";
9
9
  function resolveWidgetSizeFromGeometry(geometry) {
10
10
  return {
11
11
  size: geometry.size ?? undefined,
@@ -85,8 +85,8 @@ function readRecordPatch(value) {
85
85
  ? value
86
86
  : null;
87
87
  }
88
- export function runPhiDeveloperBuilderInspectorAction(defaultArea, action) {
89
- const state = getPhiDeveloperBuilderStateSnapshot(defaultArea);
88
+ export function runPhiDeveloperBuilderInspectorAction(action) {
89
+ const state = getPhiDeveloperBuilderStateSnapshot();
90
90
  if (action.kind === "patchSelectedRegionDraft") {
91
91
  const patch = readRecordPatch(action.patch);
92
92
  const selectedRegionKey = state.nodeKind === "region" ? state.nodeKey.replace(/^region:/, "") : null;
@@ -161,10 +161,7 @@ export function runPhiDeveloperBuilderInspectorAction(defaultArea, action) {
161
161
  return;
162
162
  }
163
163
  patchSelectedStructureDraftConfig(state, "anchor", (config) => ({ ...config, anchor: selectedLayoutAnchor }));
164
- builderWorkspaceStore.patch(defaultArea, (current) => ({
165
- ...current,
166
- selectedLayoutAnchor: selectedLayoutAnchor,
167
- }));
164
+ setPhiBuilderSelectedLayoutAnchor(selectedLayoutAnchor);
168
165
  return;
169
166
  }
170
167
  if (action.kind === "patchSelectedLayoutPadding") {
@@ -3,10 +3,9 @@ import { type PhiSignalValue } from "../../../../types/signals";
3
3
  import type { PhiBuilderPageMetaPresentationLabels } from "../controller/definition";
4
4
  type PhiBuilderPageControllerState = Pick<PhiDeveloperBuilderWorkspaceState, "customPages" | "modulePresetPagesByArea" | "pageMetaDrafts" | "persistedPageCatalogByArea">;
5
5
  type PhiPageMetaDialogMode = "create" | "update";
6
- export declare function usePhiBuilderPageController({ emitCapability, defaultArea, effectiveArea, effectivePageKey, pageMetaLabels, state, }: {
6
+ export declare function usePhiBuilderPageController({ emitCapability, effectiveArea, effectivePageKey, pageMetaLabels, state, }: {
7
7
  /** The Builder Controller's own output: the Page metadata dialog is routed by the Pages Page. */
8
8
  emitCapability: (capabilityId: string, value: PhiSignalValue, correlationId?: string | null) => void;
9
- defaultArea: PhiDeveloperBuilderArea;
10
9
  effectiveArea: PhiDeveloperBuilderArea;
11
10
  effectivePageKey: string;
12
11
  pageMetaLabels: PhiBuilderPageMetaPresentationLabels;
@@ -13,16 +13,16 @@ import { collectPhiDeveloperBuilderPageKeys, collectPhiDeveloperBuilderPageStora
13
13
  import { createPhiDeveloperBuilderInitialPageDrafts, createPhiDeveloperBuilderPageDraft, PhiBuilderPageExistsError, } from "../persistence";
14
14
  import { describePhiBuilderPageAddressConflict, findPhiBuilderSitePageAddressConflict, } from "../page-address-rule";
15
15
  import { PHI_BUILDER_AREA_SEARCH_PARAM, PHI_BUILDER_PAGE_SEARCH_PARAM, } from "../../../../helpers/cms-scope-search-params";
16
- import { builderWorkspaceStore, mergePhiDeveloperRegionDrafts, resetPhiBuilderSelectionToPage, getPhiDeveloperBuilderStateSnapshot, } from "../developer-workspace-store";
16
+ import { mergePhiDeveloperRegionDrafts, openPhiBuilderPage, setPhiBuilderPageMetaDraft, startPhiBuilderNewPageDrafts, getPhiDeveloperBuilderStateSnapshot, } from "../developer-workspace-store";
17
17
  import { getPhiBuilderRegionDraftKey } from "../region-keys";
18
18
  import { capturePhiBuilderWorkspaceHistoryState, createPhiBuilderHistoryContext, phiBuilderHistory, } from "../history";
19
19
  import { createPhiBuilderControllerAddress } from "../controller/address";
20
20
  import { PHI_SIGNAL_VALUE_SCHEMAS } from "../../../../types/signals";
21
21
  import { readPhiRuntimeFormValuesSignalValue } from "../../../../components/forms/runtime-form-state";
22
22
  import { emitPhiPageTitleInputSignal } from "../page-title-signal";
23
- import { phiWorkspaceCatalogStore } from "../../../../components/workspace/catalog-store";
23
+ import { addPhiWorkspaceCustomPage, storePhiWorkspacePersistedPages, } from "../workspace-catalog-actions";
24
24
  import { usePhiPathname } from "../../../../components/runtime/use-phi-pathname";
25
- export function usePhiBuilderPageController({ emitCapability, defaultArea, effectiveArea, effectivePageKey, pageMetaLabels, state, }) {
25
+ export function usePhiBuilderPageController({ emitCapability, effectiveArea, effectivePageKey, pageMetaLabels, state, }) {
26
26
  const { showMessage } = usePhiApplicationFeedback();
27
27
  const router = useRouter();
28
28
  const pathname = usePhiPathname();
@@ -59,25 +59,10 @@ export function usePhiBuilderPageController({ emitCapability, defaultArea, effec
59
59
  }, [effectiveArea, emitSignal, resolvePageTitleForInput]);
60
60
  async function reloadPersistedPageCatalog(area) {
61
61
  const pages = await loadPhiBuilderPersistedPageCatalog(area, { refresh: true });
62
- phiWorkspaceCatalogStore.patch(defaultArea, (current) => ({
63
- ...current,
64
- persistedPageCatalogByArea: {
65
- ...current.persistedPageCatalogByArea,
66
- [area]: pages,
67
- },
68
- pageCatalogHydratedByArea: {
69
- ...current.pageCatalogHydratedByArea,
70
- [area]: true,
71
- },
72
- }));
62
+ storePhiWorkspacePersistedPages(area, pages);
73
63
  }
74
64
  function navigateToBuilderPage(pageKey) {
75
- phiWorkspaceCatalogStore.patch(defaultArea, (current) => ({
76
- ...current,
77
- area: effectiveArea,
78
- pageKey,
79
- }));
80
- builderWorkspaceStore.patch(defaultArea, (current) => resetPhiBuilderSelectionToPage(current, pageKey, { closePages: true }));
65
+ openPhiBuilderPage(effectiveArea, pageKey, { closePages: true });
81
66
  if (typeof pathname === "string") {
82
67
  const nextSearchParams = new URLSearchParams(searchParams.toString());
83
68
  nextSearchParams.set(PHI_BUILDER_AREA_SEARCH_PARAM, effectiveArea);
@@ -180,22 +165,8 @@ export function usePhiBuilderPageController({ emitCapability, defaultArea, effec
180
165
  })
181
166
  : null;
182
167
  const pageMetaDraftKey = getPhiBuilderRegionDraftKey(effectiveArea, "page_meta", effectivePageKey);
183
- const historyBefore = capturePhiBuilderWorkspaceHistoryState(getPhiDeveloperBuilderStateSnapshot(defaultArea));
184
- // replace writes the whole tool state, so it must read the tool state -- not the merged view.
185
- const current = builderWorkspaceStore.getSnapshot(defaultArea);
186
- const next = {
187
- ...current,
188
- pageMetaDrafts: {
189
- ...current.pageMetaDrafts,
190
- [pageMetaDraftKey]: {
191
- ...(current.pageMetaDrafts[pageMetaDraftKey] ?? {}),
192
- title: editedTitle,
193
- description,
194
- ...indexPatch,
195
- },
196
- },
197
- };
198
- builderWorkspaceStore.replace(defaultArea, next);
168
+ const historyBefore = capturePhiBuilderWorkspaceHistoryState(getPhiDeveloperBuilderStateSnapshot());
169
+ setPhiBuilderPageMetaDraft(pageMetaDraftKey, { title: editedTitle, description, ...indexPatch });
199
170
  phiBuilderHistory.record(createPhiBuilderHistoryContext({
200
171
  workspace: "pages",
201
172
  area: effectiveArea,
@@ -208,13 +179,13 @@ export function usePhiBuilderPageController({ emitCapability, defaultArea, effec
208
179
  },
209
180
  after: {
210
181
  kind: "workspace",
211
- state: capturePhiBuilderWorkspaceHistoryState(getPhiDeveloperBuilderStateSnapshot(defaultArea)),
182
+ state: capturePhiBuilderWorkspaceHistoryState(getPhiDeveloperBuilderStateSnapshot()),
212
183
  },
213
184
  });
214
185
  emitPageTitleInputValue(effectivePageKey, editedTitle);
215
186
  if (pathResult) {
216
187
  await reloadPersistedPageCatalog(effectiveArea);
217
- const refreshed = getPhiDeveloperBuilderStateSnapshot(defaultArea);
188
+ const refreshed = getPhiDeveloperBuilderStateSnapshot();
218
189
  const refreshedPages = resolvePhiBuilderActivePageCatalog(effectiveArea, refreshed.modulePresetPagesByArea, refreshed.customPages, refreshed.persistedPageCatalogByArea);
219
190
  const nextPageKey = resolvePhiBuilderPageKeyFromCatalogPath(effectiveArea, pathResult.path, refreshedPages);
220
191
  if (nextPageKey)
@@ -275,36 +246,13 @@ export function usePhiBuilderPageController({ emitCapability, defaultArea, effec
275
246
  pathname,
276
247
  });
277
248
  mergePhiDeveloperRegionDrafts(nextDrafts);
278
- phiWorkspaceCatalogStore.patch(defaultArea, (current) => ({
279
- ...current,
280
- customPages: {
281
- ...current.customPages,
282
- [effectiveArea]: [
283
- ...(current.customPages[effectiveArea] ?? []),
284
- {
285
- key: requestedKey,
286
- title,
287
- storagePath: requestedStoragePath,
288
- },
289
- ],
290
- },
291
- }));
249
+ addPhiWorkspaceCustomPage(effectiveArea, { key: requestedKey, title, storagePath: requestedStoragePath });
292
250
  // The page's meta and delete drafts are edits in progress, so they stay with the Builder.
293
- builderWorkspaceStore.patch(defaultArea, (current) => ({
294
- ...current,
295
- pageMetaDrafts: {
296
- ...current.pageMetaDrafts,
297
- [getPhiBuilderRegionDraftKey(effectiveArea, "page_meta", requestedKey)]: {
298
- title,
299
- description,
300
- ...indexPatch,
301
- },
302
- },
303
- deletedPageDrafts: {
304
- ...current.deletedPageDrafts,
305
- [getPhiBuilderRegionDraftKey(effectiveArea, "page_delete", requestedKey)]: false,
306
- },
307
- }));
251
+ startPhiBuilderNewPageDrafts({
252
+ metaDraftKey: getPhiBuilderRegionDraftKey(effectiveArea, "page_meta", requestedKey),
253
+ meta: { title, description, ...indexPatch },
254
+ deleteDraftKey: getPhiBuilderRegionDraftKey(effectiveArea, "page_delete", requestedKey),
255
+ });
308
256
  await reloadPersistedPageCatalog(effectiveArea);
309
257
  navigateToBuilderPage(requestedKey);
310
258
  emitPageTitleInputValue(requestedKey, title);
@@ -315,7 +263,7 @@ export function usePhiBuilderPageController({ emitCapability, defaultArea, effec
315
263
  if (error instanceof PhiBuilderPageExistsError && !error.tombstoned) {
316
264
  // Somebody created it meanwhile: open that Page rather than failing on the path it holds.
317
265
  await reloadPersistedPageCatalog(effectiveArea);
318
- const refreshed = getPhiDeveloperBuilderStateSnapshot(defaultArea);
266
+ const refreshed = getPhiDeveloperBuilderStateSnapshot();
319
267
  const refreshedPages = resolvePhiBuilderActivePageCatalog(effectiveArea, refreshed.modulePresetPagesByArea, refreshed.customPages, refreshed.persistedPageCatalogByArea);
320
268
  const existingKey = resolvePhiBuilderPageKeyFromCatalogPath(effectiveArea, error.path, refreshedPages);
321
269
  if (existingKey)
@@ -33,20 +33,10 @@ export declare const PHI_BUILDER_RUNTIME_CONTROLLER_SERVER_DEFINITION: {
33
33
  allowedMountScopes: "area"[];
34
34
  runtimeSignals: {
35
35
  emits: ({
36
- id: string;
37
- action: "start";
38
- valueType: "json";
39
- valueSchema: `${string}/signals/${string}`;
40
- } | {
41
36
  id: string;
42
37
  action: "change";
43
38
  valueType: "json";
44
39
  valueSchema: `${string}/signals/${string}`;
45
- } | {
46
- id: string;
47
- action: "stop";
48
- valueType: "json";
49
- valueSchema: `${string}/signals/${string}`;
50
40
  } | {
51
41
  id: string;
52
42
  action: "activate";
@@ -70,11 +60,6 @@ export declare const PHI_BUILDER_RUNTIME_CONTROLLER_SERVER_DEFINITION: {
70
60
  action: "change";
71
61
  valueType: "boolean";
72
62
  valueSchema?: undefined;
73
- } | {
74
- id: string;
75
- action: "drop";
76
- valueType: "json";
77
- valueSchema: `${string}/signals/${string}`;
78
63
  })[];
79
64
  listens: ({
80
65
  id: string;
@@ -1,7 +1,4 @@
1
1
  import { type PhiSignalRouteSet } from "../../../../types/signals";
2
- import type { PhiDeveloperBuilderArea } from "../developer-workspace-types";
3
- export declare function patchPhiBuilderSignalWiringSession(defaultArea: PhiDeveloperBuilderArea, values: Record<string, unknown>): void;
4
- export declare function resetPhiBuilderSignalWiringSession(defaultArea: PhiDeveloperBuilderArea): void;
5
2
  export type PhiBuilderSignalWiringResult = {
6
3
  kind: "applied";
7
4
  routes: PhiSignalRouteSet;
@@ -19,7 +16,7 @@ export type PhiBuilderSignalWiringResult = {
19
16
  * selection change, and a route whose value the receiver cannot read is worse than no route at all --
20
17
  * nothing reports it at runtime.
21
18
  */
22
- export declare function resolvePhiBuilderSignalWiringRoutes(defaultArea: PhiDeveloperBuilderArea): PhiBuilderSignalWiringResult;
19
+ export declare function resolvePhiBuilderSignalWiringRoutes(): PhiBuilderSignalWiringResult;
23
20
  /**
24
21
  * Removes one route from the selected block by its key.
25
22
  *
@@ -27,4 +24,4 @@ export declare function resolvePhiBuilderSignalWiringRoutes(defaultArea: PhiDeve
27
24
  * so its rows come straight from the draft config rather than from a staged copy. Removing therefore
28
25
  * writes to the same place Apply does, and the Table is reloaded afterwards.
29
26
  */
30
- export declare function resolvePhiBuilderSignalWiringRoutesWithout(defaultArea: PhiDeveloperBuilderArea, routeKey: string): PhiSignalRouteSet | null;
27
+ export declare function resolvePhiBuilderSignalWiringRoutesWithout(routeKey: string): PhiSignalRouteSet | null;