@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
@@ -0,0 +1,57 @@
1
+ "use client";
2
+ import { useEffect, useState } from "react";
3
+ /*
4
+ * One request per Area for as long as the page lives: the create and the edit dialog offer the same
5
+ * Pages, and a list that changed meanwhile is a Page somebody published while this one was being written.
6
+ * A failed request is forgotten, so the next dialog asks again.
7
+ */
8
+ const pageOptionsByArea = new Map();
9
+ function loadPageOptions(area) {
10
+ const cached = pageOptionsByArea.get(area);
11
+ if (cached)
12
+ return cached;
13
+ const request = (async () => {
14
+ const response = await fetch(`/api/site/page-references?area=${encodeURIComponent(area)}`, {
15
+ cache: "no-store",
16
+ credentials: "same-origin",
17
+ headers: { accept: "application/json" },
18
+ });
19
+ const payload = (await response.json().catch(() => null));
20
+ if (!response.ok || !Array.isArray(payload?.options)) {
21
+ throw new Error(`Page references for "${area}" answered ${response.status}.`);
22
+ }
23
+ return payload.options;
24
+ })();
25
+ pageOptionsByArea.set(area, request);
26
+ request.catch(() => pageOptionsByArea.delete(area));
27
+ return request;
28
+ }
29
+ /**
30
+ * The Pages of one Area a link may point at, as the tree `PhiLinkTargetControl` offers, for a surface
31
+ * that stands outside the Builder's own catalog: a Form's `link-target` field, the Theme's Brand.
32
+ *
33
+ * Answered by `/api/site/page-references` (`gateway/page-references-route.ts`), which merges the Area's
34
+ * Module Pages and Core's the way the Builder's picker does. `failed` is set when the list could not be
35
+ * read, so the surface can say so instead of showing an empty list that looks like a Site without Pages.
36
+ */
37
+ export function usePhiPageReferenceOptions(area, logScope) {
38
+ const [options, setOptions] = useState([]);
39
+ const [failed, setFailed] = useState(false);
40
+ useEffect(() => {
41
+ let current = true;
42
+ loadPageOptions(area).then((next) => {
43
+ if (current) {
44
+ setOptions(next);
45
+ setFailed(false);
46
+ }
47
+ }, (error) => {
48
+ console.warn(`[${logScope}] Page references could not be loaded.`, { area, error });
49
+ if (current)
50
+ setFailed(true);
51
+ });
52
+ return () => {
53
+ current = false;
54
+ };
55
+ }, [area, logScope]);
56
+ return { options, failed };
57
+ }
@@ -18,6 +18,19 @@ export type PhiBackgroundBaseColor = {
18
18
  export type PhiBackgroundBaseNone = {
19
19
  kind: "none";
20
20
  };
21
+ /**
22
+ * The Theme's Chrome Overlay as the ground (LAYOUTING.md "Surface tone", SHELL.md "Root Background and
23
+ * Shell Backdrop Layers").
24
+ *
25
+ * The box paints what the Theme workspace calls the Chrome Overlay -- its colour or picture and its glass
26
+ * pane -- instead of a ground of its own. It carries nothing else: the Overlay is the Theme's, per mode
27
+ * (`root.chrome[mode]`), and the box reads the mode it stands in. A Surface `tone` is that mode, so an
28
+ * `inverse` Footer is the dark Overlay on a light page and the light one on a dark page. It is a stated
29
+ * ground: a tone does not paint its own container ground beneath it.
30
+ */
31
+ export type PhiBackgroundBaseTheme = {
32
+ kind: "theme";
33
+ };
21
34
  export type PhiBackgroundBaseGradient = {
22
35
  kind: "gradient";
23
36
  direction: PhiBackgroundDirection;
@@ -50,6 +63,24 @@ export type PhiBackgroundImageSourceKind = "asset" | "url";
50
63
  */
51
64
  export declare const PHI_BACKGROUND_IMAGE_SOURCE_KINDS: readonly PhiBackgroundImageSourceKind[];
52
65
  export declare const PHI_BACKGROUND_BASE_KINDS: readonly PhiCmsBackgroundWidgetConfig["base"]["kind"][];
66
+ /**
67
+ * The container ground of the mode a box stands in. What a toned Surface paints where it states no
68
+ * ground (`PHI_SURFACE_TONE_GROUND`), and what a `theme` ground falls back to where the Theme's Overlay
69
+ * is not published.
70
+ */
71
+ export declare const PHI_BACKGROUND_CONTAINER_GROUND = "var(--ant-color-bg-container)";
72
+ /**
73
+ * What a `theme` Base paints: the Shell Chrome Overlay's custom properties, the same ones the Shell's
74
+ * chrome panes paint from (components/shell/phi-cms-shell.tsx).
75
+ *
76
+ * The Root Layout publishes them for the page's mode, and `styles/shell.css` publishes them again under a
77
+ * tone's class for the tone's mode, so the box needs no colour of its own and turns with the mode switch.
78
+ * Outside the Root Layout -- a Modal or Drawer portalled to `<body>` -- nothing publishes them, and the box
79
+ * takes the container ground of its mode instead: the tone's ground, or the Overlay's own where it has no
80
+ * tone. Fixed attachment for the reason the Chrome Regions have it: every box is a window onto one
81
+ * viewport-sized painting.
82
+ */
83
+ export declare const PHI_BACKGROUND_THEME_STYLE: Readonly<CSSProperties>;
53
84
  export declare const PHI_BACKGROUND_MOTION_MODES: readonly PhiBackgroundMotionMode[];
54
85
  export type PhiBackgroundMotionDirection = "natural" | "reverse";
55
86
  /**
@@ -103,7 +134,7 @@ export type PhiBackgroundOverlay = PhiBackgroundColorOverlay | PhiBackgroundPatt
103
134
  /** What an Overlay that states no opacity is painted at, shared by every kind. */
104
135
  export declare const PHI_BACKGROUND_OVERLAY_DEFAULT_OPACITY = 0.14;
105
136
  export type PhiCmsBackgroundWidgetConfig = {
106
- base: PhiBackgroundBaseColor | PhiBackgroundBaseGradient | PhiBackgroundBaseImage | PhiBackgroundBaseNone;
137
+ base: PhiBackgroundBaseColor | PhiBackgroundBaseGradient | PhiBackgroundBaseImage | PhiBackgroundBaseNone | PhiBackgroundBaseTheme;
107
138
  overlay?: PhiBackgroundOverlay | null;
108
139
  filter?: PhiBackgroundFilter | null;
109
140
  motion?: PhiBackgroundMotion | null;
@@ -30,7 +30,35 @@ export const PHI_BACKGROUND_BASE_KINDS = [
30
30
  "color",
31
31
  "gradient",
32
32
  "image",
33
+ "theme",
33
34
  ];
35
+ /**
36
+ * The container ground of the mode a box stands in. What a toned Surface paints where it states no
37
+ * ground (`PHI_SURFACE_TONE_GROUND`), and what a `theme` ground falls back to where the Theme's Overlay
38
+ * is not published.
39
+ */
40
+ export const PHI_BACKGROUND_CONTAINER_GROUND = "var(--ant-color-bg-container)";
41
+ /**
42
+ * What a `theme` Base paints: the Shell Chrome Overlay's custom properties, the same ones the Shell's
43
+ * chrome panes paint from (components/shell/phi-cms-shell.tsx).
44
+ *
45
+ * The Root Layout publishes them for the page's mode, and `styles/shell.css` publishes them again under a
46
+ * tone's class for the tone's mode, so the box needs no colour of its own and turns with the mode switch.
47
+ * Outside the Root Layout -- a Modal or Drawer portalled to `<body>` -- nothing publishes them, and the box
48
+ * takes the container ground of its mode instead: the tone's ground, or the Overlay's own where it has no
49
+ * tone. Fixed attachment for the reason the Chrome Regions have it: every box is a window onto one
50
+ * viewport-sized painting.
51
+ */
52
+ export const PHI_BACKGROUND_THEME_STYLE = {
53
+ backgroundColor: `var(--phi-shell-chrome-color, ${PHI_BACKGROUND_CONTAINER_GROUND})`,
54
+ backgroundImage: "var(--phi-shell-chrome-image, none)",
55
+ backgroundSize: "var(--phi-shell-chrome-size, auto)",
56
+ backgroundPosition: "var(--phi-shell-chrome-position, 0 0)",
57
+ backgroundRepeat: "var(--phi-shell-chrome-repeat, repeat)",
58
+ backgroundAttachment: "fixed",
59
+ backdropFilter: "var(--phi-shell-chrome-filter, none)",
60
+ WebkitBackdropFilter: "var(--phi-shell-chrome-filter, none)",
61
+ };
34
62
  export const PHI_BACKGROUND_MOTION_MODES = [
35
63
  "static",
36
64
  "fixed",
@@ -145,7 +173,7 @@ function normalizePhiBackgroundBase(value) {
145
173
  ? { ...normalized, ...source }
146
174
  : { ...normalized, ...source };
147
175
  }
148
- if (kind === "none")
176
+ if (kind === "none" || kind === "theme")
149
177
  return { kind };
150
178
  if (kind === "color") {
151
179
  const color = readString(raw.color);
@@ -253,6 +281,10 @@ export function normalizePhiBackgroundWidgetConfig(config) {
253
281
  }
254
282
  const raw = config;
255
283
  const base = normalizePhiBackgroundBase(raw.base) ?? normalizePhiBackgroundBase(raw) ?? { kind: "none" };
284
+ // The Theme's Overlay is the whole ground: it carries its own Overlay and pane, and takes none of the box's.
285
+ if (base.kind === "theme") {
286
+ return { base, overlay: null, filter: null, motion: null };
287
+ }
256
288
  return {
257
289
  base,
258
290
  overlay: readBackgroundOverlay(raw.overlay),
@@ -278,6 +310,9 @@ export function readPhiBackgroundPatternInkFromCss(css) {
278
310
  export function serializePhiBackgroundBaseCss(base) {
279
311
  if (base.kind === "none")
280
312
  return "none";
313
+ // Not a value a Base can be read back from: the Overlay's colour, as far as one CSS value can say it.
314
+ if (base.kind === "theme")
315
+ return String(PHI_BACKGROUND_THEME_STYLE.backgroundColor);
281
316
  if (base.kind === "color")
282
317
  return base.color;
283
318
  if (base.kind === "gradient") {
@@ -320,6 +355,9 @@ function resolvePhiBackgroundOverlayLayer(overlay) {
320
355
  export function resolvePhiBackgroundWidgetStyle(config) {
321
356
  const normalized = normalizePhiBackgroundWidgetConfig(config);
322
357
  const base = normalized.base;
358
+ if (base.kind === "theme") {
359
+ return { ...PHI_BACKGROUND_THEME_STYLE };
360
+ }
323
361
  const style = {};
324
362
  if (base.kind === "color")
325
363
  style.backgroundColor = base.color;
@@ -397,7 +435,8 @@ export function phiBackgroundWidgetConfigPaintsGround(config) {
397
435
  * nor honoured there.
398
436
  */
399
437
  export function phiBackgroundBaseSupportsGlassEffect(base) {
400
- return base.kind !== "image" && base.kind !== "gradient";
438
+ // The Theme's Overlay brings its own pane, and a second one over it is nothing anybody asked for.
439
+ return base.kind !== "image" && base.kind !== "gradient" && base.kind !== "theme";
401
440
  }
402
441
  /**
403
442
  * Whether `blur` has anything to soften: a picture, a gradient, or a patterned Overlay.
@@ -1,5 +1,5 @@
1
1
  import { parsePhiControlOptionsProviderConfig, readPhiControlOptions, } from "../../controls/phi-control-options";
2
- import { readBoolean, readString } from "./parser-primitives";
2
+ import { createPhiConfigReader } from "./strict-config-reader";
3
3
  import { PHI_CONTROL_PRESENTATION_FIELDS, PHI_CONTROL_STATE_FIELDS, parsePhiControlConfig, } from "./control-signal-config";
4
4
  export function buildPhiChoiceControlOptionFields(editorPlacement = "inspector") {
5
5
  return [{
@@ -28,9 +28,10 @@ export function buildPhiChoiceControlOptionFields(editorPlacement = "inspector")
28
28
  }
29
29
  export const PHI_CHOICE_CONTROL_OPTION_FIELDS = buildPhiChoiceControlOptionFields();
30
30
  export function parsePhiChoiceOptionsConfig(config) {
31
+ const reader = createPhiConfigReader(config);
31
32
  return {
32
- optionsProvider: parsePhiControlOptionsProviderConfig(config.optionsProvider),
33
- options: readPhiControlOptions(config.options),
33
+ optionsProvider: reader.value("optionsProvider", "an options provider", (value) => parsePhiControlOptionsProviderConfig(value) ?? undefined) ?? null,
34
+ options: reader.value("options", "a list of options", (value) => (Array.isArray(value) ? readPhiControlOptions(value) : undefined)) ?? readPhiControlOptions(undefined),
34
35
  };
35
36
  }
36
37
  export const PHI_CHOICE_CONTROL_CONFIG_FIELDS = [
@@ -46,27 +47,25 @@ export const PHI_CHOICE_CONTROL_VALUE_MODE_FIELD = {
46
47
  { value: "stack-slot-index", label: "Stack Slot Index" },
47
48
  ],
48
49
  };
49
- function readPhiChoiceValueMode(value) {
50
- return readString(value) === "stack-slot-index" ? "stack-slot-index" : "raw";
51
- }
52
50
  export function parsePhiChoiceControlConfig(config) {
53
51
  const controlState = parsePhiControlConfig(config, {
54
52
  key: "choice",
55
53
  });
54
+ const reader = createPhiConfigReader(config);
56
55
  return {
57
56
  ...controlState,
58
- label: readString(config.label),
59
- description: readString(config.description),
60
- value: readString(config.value),
61
- placeholder: readString(config.placeholder),
62
- presentation: readString(config.presentation) === "autocomplete" ? "autocomplete" : "select",
63
- allowCustom: readBoolean(config.allowCustom),
57
+ label: reader.string("label"),
58
+ description: reader.string("description"),
59
+ value: reader.string("value"),
60
+ placeholder: reader.string("placeholder"),
61
+ presentation: reader.oneOf("presentation", ["select", "autocomplete"]) ?? "select",
62
+ allowCustom: reader.boolean("allowCustom"),
64
63
  ...parsePhiChoiceOptionsConfig(config),
65
64
  };
66
65
  }
67
66
  export function parsePhiStackChoiceControlConfig(config) {
68
67
  return {
69
68
  ...parsePhiChoiceControlConfig(config),
70
- valueMode: readPhiChoiceValueMode(config.valueMode),
69
+ valueMode: createPhiConfigReader(config).oneOf("valueMode", ["raw", "stack-slot-index"]) ?? "raw",
71
70
  };
72
71
  }
@@ -2,7 +2,11 @@ import type { PhiCommandButtonConfig } from "../../../types/core-widget-placemen
2
2
  import type { PhiCmsConfigField } from "../../../types";
3
3
  import type { PhiCmsConfigFieldVisibilityRule } from "../../../types/cms-plugins";
4
4
  import { type PhiAccessViewer, type PhiRoleProviderId } from "../../../types/access";
5
- export declare function readPhiCommandButtons(value: unknown): PhiCommandButtonConfig[];
5
+ /**
6
+ * A Widget's buttons. Strict (`strict-config-reader.ts`): a button without a key or without an emit is
7
+ * an error naming it, not a button left out.
8
+ */
9
+ export declare function readPhiCommandButtons(value: unknown, path?: string): PhiCommandButtonConfig[];
6
10
  export declare function filterPhiCommandButtonsForViewer(buttons: readonly PhiCommandButtonConfig[], viewer: PhiAccessViewer, ownerProviderId?: PhiRoleProviderId | null): PhiCommandButtonConfig[];
7
11
  /**
8
12
  * A new button: the first free `buttonN` key, labelled after it, sending its key as the command. The
@@ -4,7 +4,7 @@ import { PHI_COMMON_CONTROL_DEFAULT_LABELS, readPhiCommonControlActionKey, } fro
4
4
  import { PHI_BUTTON_VARIANT_FIELD_OPTIONS, readPhiButtonVariant } from "./button-variant";
5
5
  import { createPhiCommonActionField, readPhiControlLabel } from "./common-action-field";
6
6
  import { PHI_CONTROL_BADGE_FIELDS, parsePhiControlBadgeConfig } from "./control-signal-config";
7
- import { readBoolean, readNumber, readString } from "./parser-primitives";
7
+ import { createPhiConfigReader } from "./strict-config-reader";
8
8
  /*
9
9
  * The buttons of a Widget that holds several: the Command Toolbar's row, and the Float Button's corner.
10
10
  *
@@ -12,102 +12,59 @@ import { readBoolean, readNumber, readString } from "./parser-primitives";
12
12
  * emit, and the Signals panel wires both. The two Widgets differ in how the buttons stand, never in what
13
13
  * a button is, so the parser, the Inspector fields, the viewer filter and the scaffold's count are one.
14
14
  */
15
+ /** What a button sends: a text, a number, true/false, a list of texts or of numbers, or an object. */
15
16
  function readButtonEmitValue(value) {
16
- const stringValue = readString(value);
17
- if (stringValue !== undefined) {
18
- return stringValue;
19
- }
20
- const numberValue = readNumber(value);
21
- if (numberValue !== undefined) {
22
- return numberValue;
23
- }
24
- const booleanValue = readBoolean(value);
25
- if (booleanValue !== undefined) {
26
- return booleanValue;
27
- }
28
- if (value == null) {
29
- return undefined;
30
- }
17
+ if (typeof value === "string" || typeof value === "boolean")
18
+ return value;
19
+ if (typeof value === "number")
20
+ return Number.isFinite(value) ? value : undefined;
31
21
  if (Array.isArray(value)) {
32
- const stringItems = value.filter((item) => typeof item === "string");
33
- if (stringItems.length === value.length) {
34
- return stringItems;
35
- }
36
- const numberItems = value.filter((item) => typeof item === "number" && Number.isFinite(item));
37
- if (numberItems.length === value.length) {
38
- return numberItems;
39
- }
22
+ if (value.every((item) => typeof item === "string"))
23
+ return value;
24
+ if (value.every((item) => typeof item === "number" && Number.isFinite(item)))
25
+ return value;
40
26
  return undefined;
41
27
  }
42
- if (typeof value === "object") {
43
- return value;
44
- }
45
- return undefined;
28
+ return isPhiRecord(value) ? value : undefined;
46
29
  }
47
- function readCommandButtonEmitConfig(value) {
48
- if (!isPhiRecord(value)) {
49
- return null;
50
- }
51
- const record = value;
52
- const capabilityId = readString(record.capabilityId);
53
- if (!capabilityId) {
54
- return null;
55
- }
30
+ function readCommandButtonEmitConfig(reader) {
56
31
  return {
57
- capabilityId,
58
- value: readButtonEmitValue(record.value),
32
+ capabilityId: reader.string("capabilityId") ?? reader.fail("capabilityId", "a capability id"),
33
+ value: reader.value("value", "a text, number, true/false, list or object", readButtonEmitValue),
59
34
  };
60
35
  }
61
- function readCommandButtonEmits(value) {
62
- if (!Array.isArray(value)) {
63
- return [];
64
- }
65
- return value
66
- .map(readCommandButtonEmitConfig)
67
- .filter((item) => item != null);
68
- }
69
- function readCommandButtonConfig(value) {
70
- if (!isPhiRecord(value)) {
71
- return null;
72
- }
73
- const record = value;
74
- const key = readString(record.key);
75
- const emits = readCommandButtonEmits(record.emits);
76
- if (!key || emits.length === 0) {
77
- return null;
78
- }
79
- const hasAccessPolicy = Object.prototype.hasOwnProperty.call(record, "accessPolicy");
80
- const accessPolicy = hasAccessPolicy
81
- ? readPhiViewerAccessPolicy(record.accessPolicy)
36
+ function readCommandButtonConfig(reader) {
37
+ const key = reader.string("key") ?? reader.fail("key", "a text");
38
+ const emits = reader.list("emits", readCommandButtonEmitConfig) ?? [];
39
+ if (emits.length === 0)
40
+ reader.fail("emits", "at least one emit");
41
+ const accessPolicy = Object.prototype.hasOwnProperty.call(reader.record, "accessPolicy")
42
+ ? readPhiViewerAccessPolicy(reader.record.accessPolicy) ?? reader.fail("accessPolicy", "an access policy")
82
43
  : null;
83
- if (hasAccessPolicy && !accessPolicy) {
84
- return null;
85
- }
86
44
  return {
87
45
  key,
88
46
  emits,
89
47
  ...(accessPolicy ? { accessPolicy } : {}),
90
- ...parsePhiControlBadgeConfig(record),
91
- action: readPhiCommonControlActionKey(readString(record.action)) ?? undefined,
92
- label: readPhiControlLabel(record.label),
93
- tooltip: readString(record.tooltip),
94
- icon: readString(record.icon),
95
- display: record.display === "icon" || record.display === "label" || record.display === "icon-label"
96
- ? record.display
97
- : undefined,
98
- danger: readBoolean(record.danger),
99
- disabled: readBoolean(record.disabled),
100
- readOnly: readBoolean(record.readOnly),
101
- variant: readPhiButtonVariant(record.variant),
48
+ ...parsePhiControlBadgeConfig(reader.record, reader.path),
49
+ action: reader.value("action", "a common action", (value) => typeof value === "string" ? readPhiCommonControlActionKey(value) ?? undefined : undefined),
50
+ label: readPhiControlLabel(reader.record.label),
51
+ tooltip: reader.string("tooltip"),
52
+ icon: reader.string("icon"),
53
+ display: reader.oneOf("display", ["icon", "label", "icon-label"]),
54
+ danger: reader.boolean("danger"),
55
+ disabled: reader.boolean("disabled"),
56
+ readOnly: reader.boolean("readOnly"),
57
+ variant: reader.value("variant", "a button variant", readPhiButtonVariant),
102
58
  };
103
59
  }
104
- export function readPhiCommandButtons(value) {
105
- if (!Array.isArray(value)) {
60
+ /**
61
+ * A Widget's buttons. Strict (`strict-config-reader.ts`): a button without a key or without an emit is
62
+ * an error naming it, not a button left out.
63
+ */
64
+ export function readPhiCommandButtons(value, path = "buttons") {
65
+ if (value === undefined || value === null)
106
66
  return [];
107
- }
108
- return value
109
- .map(readCommandButtonConfig)
110
- .filter((item) => item != null);
67
+ return createPhiConfigReader({ [path]: value }).list(path, readCommandButtonConfig) ?? [];
111
68
  }
112
69
  export function filterPhiCommandButtonsForViewer(buttons, viewer, ownerProviderId) {
113
70
  return buttons.filter((button) => canPhiViewerAccessOwnedPolicy(viewer, button.accessPolicy, ownerProviderId));
@@ -143,4 +143,6 @@ export declare function parsePhiControlSignalConfig(config: Record<string, unkno
143
143
  export declare function parsePhiControlStateConfig(config: Record<string, unknown>, defaults: PhiControlSignalConfigDefaults): Required<Pick<PhiControlStateConfig, "key">> & Pick<PhiControlStateConfig, "signalRoutes" | "readOnly" | "disabled">;
144
144
  export declare function parsePhiControlPresentationConfig<TSize extends PhiControlSize = PhiControlSize>(config: Record<string, unknown>, allowedSizes?: readonly TSize[]): PhiControlPresentationConfig<TSize>;
145
145
  export declare function parsePhiControlConfig<TSize extends PhiControlSize = PhiControlSize>(config: Record<string, unknown>, defaults: PhiControlSignalConfigDefaults, allowedSizes?: readonly TSize[]): Required<Pick<PhiControlConfig<TSize>, "key">> & Pick<PhiControlConfig<TSize>, "signalRoutes" | "readOnly" | "disabled" | "controlSize">;
146
- export declare function parsePhiControlBadgeConfig(config: Record<string, unknown>): PhiControlBadgeConfig;
146
+ export declare function parsePhiControlBadgeConfig(config: Record<string, unknown>,
147
+ /** Where the config stands, when it is an entry of a list -- a button of a toolbar. */
148
+ path?: string): PhiControlBadgeConfig;
@@ -1,6 +1,6 @@
1
1
  import { readPhiSignalRouteSet, } from "../../../types/signals";
2
- import { PHI_CONTROL_SIZES, readPhiControlSize, } from "../../../types/control";
3
- import { readBoolean, readNumber, readString } from "./parser-primitives";
2
+ import { PHI_CONTROL_SIZES, } from "../../../types/control";
3
+ import { createPhiConfigReader } from "./strict-config-reader";
4
4
  export const PHI_CONTROL_READ_ONLY_FIELD = {
5
5
  key: "readOnly",
6
6
  type: "boolean",
@@ -83,23 +83,22 @@ export const PHI_CONTROL_BADGE_FIELDS = [
83
83
  export function parsePhiControlSignalConfig(config, defaults) {
84
84
  return {
85
85
  signalRoutes: readPhiSignalRouteSet(config.signalRoutes),
86
- key: readString(config.key) ?? defaults.key,
86
+ key: createPhiConfigReader(config).string("key") ?? defaults.key,
87
87
  };
88
88
  }
89
89
  export function parsePhiControlStateConfig(config, defaults) {
90
+ const reader = createPhiConfigReader(config);
90
91
  return {
91
92
  ...parsePhiControlSignalConfig(config, defaults),
92
- readOnly: readBoolean(config.readOnly),
93
- disabled: readBoolean(config.disabled),
93
+ readOnly: reader.boolean("readOnly"),
94
+ disabled: reader.boolean("disabled"),
94
95
  };
95
96
  }
96
97
  export function parsePhiControlPresentationConfig(config, allowedSizes) {
97
- const controlSize = readPhiControlSize(config.controlSize);
98
- const resolvedAllowedSizes = allowedSizes ?? PHI_CONTROL_SIZES;
98
+ // A size this Control does not offer is an error, not the default in its place.
99
+ const resolvedAllowedSizes = (allowedSizes ?? PHI_CONTROL_SIZES);
99
100
  return {
100
- controlSize: controlSize != null && resolvedAllowedSizes.includes(controlSize)
101
- ? controlSize
102
- : undefined,
101
+ controlSize: createPhiConfigReader(config).oneOf("controlSize", resolvedAllowedSizes),
103
102
  };
104
103
  }
105
104
  export function parsePhiControlConfig(config, defaults, allowedSizes) {
@@ -113,13 +112,16 @@ export function parsePhiControlConfig(config, defaults, allowedSizes) {
113
112
  controlSize: controlSize ?? ((allowedSizes ?? PHI_CONTROL_SIZES).includes("medium") ? "medium" : undefined),
114
113
  };
115
114
  }
116
- export function parsePhiControlBadgeConfig(config) {
115
+ export function parsePhiControlBadgeConfig(config,
116
+ /** Where the config stands, when it is an entry of a list -- a button of a toolbar. */
117
+ path = "") {
118
+ const reader = createPhiConfigReader(config, path);
117
119
  return {
118
- badgeEnabled: readBoolean(config.badgeEnabled),
119
- badgeText: readString(config.badgeText),
120
- badgeCount: readNumber(config.badgeCount),
121
- badgeShowZero: readBoolean(config.badgeShowZero),
122
- badgeOverflowCount: readNumber(config.badgeOverflowCount),
123
- badgeColor: readString(config.badgeColor),
120
+ badgeEnabled: reader.boolean("badgeEnabled"),
121
+ badgeText: reader.string("badgeText"),
122
+ badgeCount: reader.number("badgeCount"),
123
+ badgeShowZero: reader.boolean("badgeShowZero"),
124
+ badgeOverflowCount: reader.number("badgeOverflowCount"),
125
+ badgeColor: reader.string("badgeColor"),
124
126
  };
125
127
  }
@@ -1,2 +1,3 @@
1
1
  import type { PhiMediaImageSourceConfig } from "../../../types/media";
2
+ /** Where an image comes from: an Asset of the Media library, or a URL. Strict: an unknown kind is an error. */
2
3
  export declare function readPhiMediaImageSourceConfig(value: Record<string, unknown>): PhiMediaImageSourceConfig;
@@ -1,19 +1,18 @@
1
1
  import { normalizePhiImageAssetVariantKey } from "../../../constants/media";
2
- import { readNumber, readString } from "./parser-primitives";
3
- function readPhiImageSourceKind(value) {
4
- return readString(value) === "asset" ? "asset" : "url";
5
- }
2
+ import { createPhiConfigReader } from "./strict-config-reader";
3
+ /** Where an image comes from: an Asset of the Media library, or a URL. Strict: an unknown kind is an error. */
6
4
  export function readPhiMediaImageSourceConfig(value) {
7
- if (readPhiImageSourceKind(value.sourceKind) === "asset") {
5
+ const reader = createPhiConfigReader(value);
6
+ if ((reader.oneOf("sourceKind", ["url", "asset"]) ?? "url") === "asset") {
8
7
  return {
9
8
  sourceKind: "asset",
10
- assetId: readNumber(value.assetId),
9
+ assetId: reader.number("assetId"),
11
10
  variantKey: normalizePhiImageAssetVariantKey(value.variantKey),
12
- variantVersion: readNumber(value.variantVersion),
11
+ variantVersion: reader.number("variantVersion"),
13
12
  };
14
13
  }
15
14
  return {
16
15
  sourceKind: "url",
17
- sourceUrl: readString(value.sourceUrl),
16
+ sourceUrl: reader.string("sourceUrl"),
18
17
  };
19
18
  }
@@ -24,7 +24,12 @@ export declare const PHI_MASK_PRESET_OPTIONS: ReadonlyArray<{
24
24
  label: string;
25
25
  }>;
26
26
  export declare function resolvePhiMaskStyle(mask: PhiMaskConfig | null | undefined): CSSProperties | undefined;
27
- export declare function normalizePhiMaskConfig(value: unknown): PhiMaskConfig | undefined;
27
+ /**
28
+ * A stored mask, read strictly (`strict-config-reader.ts`) before it is normalized: a field that is
29
+ * there and of the wrong kind is an error naming it. The normalization below stays lenient for the
30
+ * editor, which normalizes drafts while an author is still choosing.
31
+ */
32
+ export declare function readPhiMaskConfig(value: unknown, path?: string): PhiMaskConfig | undefined;
28
33
  export declare function mergePhiMaskConfigDefaults(mask: PhiMaskConfig | null | undefined): PhiMaskConfig;
29
34
  /** A picker's change on top of the current mask: the defaults filled, the patch applied, the mask enabled. */
30
35
  export declare function mergePhiMaskConfigPatch(mask: PhiMaskConfig | null | undefined, patch: PhiMaskConfig): PhiMaskConfig;
@@ -1,5 +1,6 @@
1
1
  import { isPhiRecord } from "../../../helpers/is-record";
2
2
  import { readBoolean, readCssSize, readNumber, readString } from "./parser-primitives";
3
+ import { createPhiConfigReader } from "./strict-config-reader";
3
4
  /** The preset shapes and their names, in the order a picker lists them. */
4
5
  const PHI_MASK_PRESET_ENTRIES = [
5
6
  ["circle", "Circle"],
@@ -129,7 +130,29 @@ function readMaskRotation(value) {
129
130
  }
130
131
  return Math.min(180, Math.max(-180, rotation));
131
132
  }
132
- export function normalizePhiMaskConfig(value) {
133
+ /**
134
+ * A stored mask, read strictly (`strict-config-reader.ts`) before it is normalized: a field that is
135
+ * there and of the wrong kind is an error naming it. The normalization below stays lenient for the
136
+ * editor, which normalizes drafts while an author is still choosing.
137
+ */
138
+ export function readPhiMaskConfig(value, path = "mask") {
139
+ createPhiConfigReader({ [path]: value }).object(path, (reader) => {
140
+ reader.boolean("enabled");
141
+ reader.oneOf("source", ["asset", "preset"]);
142
+ reader.oneOf("preset", [...PHI_MASK_PRESETS]);
143
+ reader.number("assetId");
144
+ reader.string("assetUrl");
145
+ reader.number("scale");
146
+ reader.number("offsetX");
147
+ reader.number("offsetY");
148
+ reader.number("rotationDeg");
149
+ reader.value("position", "a CSS position", (position) => typeof position === "string" || (typeof position === "number" && Number.isFinite(position)) ? position : undefined);
150
+ reader.oneOf("repeat", ["repeat", "no-repeat"]);
151
+ reader.oneOf("mode", ["luminance", "alpha"]);
152
+ });
153
+ return normalizePhiMaskConfig(value);
154
+ }
155
+ function normalizePhiMaskConfig(value) {
133
156
  if (!isPhiRecord(value)) {
134
157
  return undefined;
135
158
  }