@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
@@ -3,7 +3,8 @@ import { PhiCmsWidgetType } from "../../../../../constants/cms-widget-types";
3
3
  import { readPhiLinkTarget } from "../../../../../types/references";
4
4
  import { readPhiMediaImageSourceConfig } from "../../../../../components/widgets/config/image-source-parser";
5
5
  import { PHI_SURFACE_CARD } from "../../../../../helpers/surface-presets";
6
- import { PHI_CARD_HEADING_LEVELS, PHI_CARD_HOVER_EFFECTS, PHI_CARD_ICON_PLACEMENTS, PHI_CARD_TEXT_ALIGNS, PHI_CARD_VARIANTS, } from "../../../../../components/widgets/shared/card-vocabulary";
6
+ import { buildPhiBulletListFields, readPhiBulletListEntries, readPhiBulletListStyle, } from "../../../../../components/widgets/shared/bullet-list-vocabulary";
7
+ import { PHI_CARD_HEADING_LEVELS, PHI_CARD_HOVER_EFFECTS, PHI_CARD_ICON_PLACEMENTS, PHI_CARD_TEXT_ALIGNS, PHI_CARD_BADGE_STYLES, PHI_CARD_VARIANTS, readPhiCardBillingPeriod, } from "../../../../../components/widgets/shared/card-vocabulary";
7
8
  import { readPhiControlLabel } from "../../../../../components/widgets/config/common-action-field";
8
9
  import { PHI_CARD_SIGNALS } from "../../../../../components/widgets/signals/control-signal-capabilities";
9
10
  import { readPhiSignalRouteSet } from "../../../../../types/signals";
@@ -24,7 +25,17 @@ function parsePhiCmsCardWidgetConfig(config) {
24
25
  description: readString(config.description),
25
26
  meta: readString(config.meta),
26
27
  value: readString(config.value),
27
- body: readChoice(readString(config.body), ["text", "stat"]),
28
+ badge: readString(config.badge),
29
+ badgeColor: readString(config.badgeColor),
30
+ badgeStyle: readChoice(readString(config.badgeStyle), PHI_CARD_BADGE_STYLES),
31
+ price: readString(config.price),
32
+ pricePeriod: readString(config.pricePeriod),
33
+ priceYearly: readString(config.priceYearly),
34
+ pricePeriodYearly: readString(config.pricePeriodYearly),
35
+ billingPeriod: readPhiCardBillingPeriod(config.billingPeriod),
36
+ features: config.features === undefined ? undefined : readPhiBulletListEntries(config.features),
37
+ featureList: readPhiBulletListStyle(config.featureList),
38
+ body: readChoice(readString(config.body), ["text", "stat", "plan"]),
28
39
  headingLevel: readChoice(readString(config.headingLevel), PHI_CARD_HEADING_LEVELS),
29
40
  textAlign: readChoice(readString(config.textAlign), PHI_CARD_TEXT_ALIGNS),
30
41
  icon: readString(config.icon),
@@ -58,6 +69,7 @@ const PHI_CARD_DEFAULT_CONFIG = {
58
69
  imageOpacity: 100,
59
70
  headingLevel: "h3",
60
71
  textAlign: "start",
72
+ badgeStyle: "none",
61
73
  };
62
74
  export const PHI_CARD_WIDGET_DEFINITION = {
63
75
  kind: "widget",
@@ -69,7 +81,17 @@ export const PHI_CARD_WIDGET_DEFINITION = {
69
81
  icon: "antd:idcard-outlined",
70
82
  iconFamily: "basic",
71
83
  translatesOwnText: true,
72
- slotSizePolicy: "fill-inline",
84
+ /*
85
+ * A card fills its slot both ways, as a Layout does.
86
+ *
87
+ * It filled only across, and stood at its own content's height inside the slot: three cards whose
88
+ * texts differ, side by side in a Grid row, ended at three different lines although the row had laid
89
+ * their slots out at one height. Filling the block axis lets the row's height reach the card. Where
90
+ * the slot has no height of its own -- a Stack or a Masonry column of content height -- a percentage
91
+ * against it stays auto and the card is as tall as its content, as before. A card in a container of
92
+ * fixed height grows into it, as a Layout there does; a card that should not says so with a height.
93
+ */
94
+ slotSizePolicy: "fill",
73
95
  /*
74
96
  * The card draws its Surface itself: its picture zooms inside the box under the pointer, and the box
75
97
  * clips it to its corners, so the ground has to be the card's own and not the slot frame's.
@@ -102,6 +124,22 @@ export const PHI_CARD_WIDGET_DEFINITION = {
102
124
  options: [
103
125
  { value: "text", label: "Text" },
104
126
  { value: "stat", label: "Statistic" },
127
+ { value: "plan", label: "Plan" },
128
+ ],
129
+ },
130
+ /*
131
+ * The prices and the features are written on the card; asked here is only which price it shows
132
+ * first. The canvas shows that one, so the yearly price is written by choosing Yearly here.
133
+ */
134
+ {
135
+ key: "billingPeriod",
136
+ type: "choice",
137
+ label: "Price shown",
138
+ presentation: "segmented",
139
+ visibleWhen: { field: "body", equals: "plan" },
140
+ options: [
141
+ { value: "monthly", label: "Monthly" },
142
+ { value: "yearly", label: "Yearly" },
105
143
  ],
106
144
  },
107
145
  {
@@ -223,6 +261,33 @@ export const PHI_CARD_WIDGET_DEFINITION = {
223
261
  ],
224
262
  },
225
263
  { key: "highlight", type: "boolean", label: "Highlight" },
264
+ /* The band's words are written on the card; how it is drawn and its colour are asked here. */
265
+ {
266
+ key: "badgeStyle",
267
+ type: "choice",
268
+ heading: "Badge",
269
+ label: "Style",
270
+ presentation: "segmented",
271
+ description: "Corner: a band in the card's top corner. Tag: a rounded mark a little down the edge. Ribbon: hangs over the card's edge with a fold, and needs room beside the card -- a Layout that clips at the card's edge cuts it off. None: hides the badge and keeps its words.",
272
+ options: [
273
+ { value: "none", label: "None" },
274
+ { value: "corner", label: "Corner" },
275
+ { value: "tag", label: "Tag" },
276
+ { value: "ribbon", label: "Ribbon" },
277
+ ],
278
+ },
279
+ {
280
+ key: "badgeColor",
281
+ type: "color",
282
+ label: "Color",
283
+ visibleWhen: { field: "badgeStyle", notEquals: "none" },
284
+ mode: "single",
285
+ defaultToken: "colorPrimary",
286
+ },
287
+ ...buildPhiBulletListFields("featureList", "Features").map((field) => ({
288
+ ...field,
289
+ visibleWhen: { field: "body", equals: "plan" },
290
+ })),
226
291
  ],
227
292
  parseConfig: parsePhiCmsCardWidgetConfig,
228
293
  };
@@ -8,17 +8,38 @@ import { PhiInlineTextEditor } from "../../../../../components/controls/phi-inli
8
8
  import { PhiTypographyControl } from "../../../../../components/controls/phi-typography-control";
9
9
  import { PhiCardWidgetClient, } from "../../../../../components/widgets/shared/card-body-client";
10
10
  import { PHI_CARD_WIDGET_DEFAULT_LABELS } from "../../../../../components/widgets/label-types/card";
11
+ import { PhiBulletListEntriesEditor } from "../../../../../components/widgets/client/bullet-list-entries-editor";
12
+ import { resolvePhiBulletListStyle, } from "../../../../../components/widgets/shared/bullet-list-vocabulary";
13
+ /* One empty list for every card without features, so the list editor's draft is not reset per render. */
14
+ const PHI_CARD_NO_FEATURES = [];
11
15
  const PHI_CARD_TEXT_PLACEHOLDERS = {
12
16
  eyebrow: "Eyebrow",
13
17
  title: "Title",
14
18
  description: "Description",
15
19
  meta: "Meta",
16
20
  value: "Value",
21
+ badge: "Badge",
22
+ price: "Price",
23
+ pricePeriod: "/ month",
24
+ priceYearly: "Yearly price",
25
+ pricePeriodYearly: "/ year",
26
+ };
27
+ /* Slots only one body draws; under any other the editor offers no field for them. */
28
+ const PHI_CARD_BODY_TEXT_SLOTS = {
29
+ value: "stat",
30
+ price: "plan",
31
+ pricePeriod: "plan",
32
+ priceYearly: "plan",
33
+ pricePeriodYearly: "plan",
17
34
  };
18
35
  /*
19
36
  * Slots a card often goes without. Empty, they stand on the canvas only while the card is under the
20
37
  * pointer or being written in (`styles/layout.css`), so an empty card does not read as four empty lines.
21
38
  */
39
+ /*
40
+ * Not the badge: it is drawn only once a style is chosen for it, and a band or ribbon that disappeared
41
+ * whenever the pointer left the card left nothing to see of the choice just made.
42
+ */
22
43
  const PHI_CARD_OPTIONAL_TEXT_SLOTS = new Set(["eyebrow", "meta"]);
23
44
  /**
24
45
  * One of the card's words, edited where it stands: underlined, in the type of the text it edits.
@@ -38,7 +59,12 @@ function PhiCardInlineText({ slot, text, onCommit, }) {
38
59
  * into beside them, and its wrapping is the card's own anyway. The text still wraps and aligns as
39
60
  * the card sets it.
40
61
  */
41
- style: { width: "100%" },
62
+ /*
63
+ * The ground stays the card's, here as well as on the text: with a clear button the field is a
64
+ * wrapper around the text, and Ant Design's underlined wrapper paints the container ground -- white
65
+ * over the badge's band, whose light words then vanished on it.
66
+ */
67
+ style: { width: "100%", backgroundColor: "transparent" },
42
68
  /* The text's own type, and the page showing through: an edit in place reads like what it edits. */
43
69
  inputStyle: {
44
70
  paddingInline: 0,
@@ -99,15 +125,21 @@ export function PhiCardWidgetEditor({ config, onChange }) {
99
125
  && presentation.width != null
100
126
  && canvasWidth != null
101
127
  && presentation.width < canvasWidth;
102
- return (_jsxs("div", { ref: canvasRef, className: "phi-card-editor", style: { position: "relative", width: "100%" }, children: [_jsx(PhiCardWidgetClient, { labels: {
128
+ return (_jsxs("div", { ref: canvasRef, className: "phi-card-editor", style: { position: "relative", display: "flex", width: "100%" }, children: [_jsx(PhiCardWidgetClient, { labels: {
103
129
  eyebrow: config.eyebrow,
104
130
  title: config.title,
105
131
  description: config.description,
106
132
  meta: config.meta,
107
133
  actionLabel: config.actionLabel ?? PHI_CARD_WIDGET_DEFAULT_LABELS.actionLabel,
108
134
  value: config.value,
135
+ badge: config.badge,
136
+ price: config.price,
137
+ pricePeriod: config.pricePeriod,
138
+ priceYearly: config.priceYearly,
139
+ pricePeriodYearly: config.pricePeriodYearly,
109
140
  }, renderText: (slot, text) => {
110
- if (slot === "value" && config.body !== "stat")
141
+ const onlyUnder = PHI_CARD_BODY_TEXT_SLOTS[slot];
142
+ if (onlyUnder && (config.body ?? "text") !== onlyUnder)
111
143
  return null;
112
144
  const field = (_jsx(PhiCardInlineText, { slot: slot, text: text ?? "", ...(onChange ? { onCommit: (next) => onChange({ [slot]: next || undefined }) } : {}) }));
113
145
  return !text && PHI_CARD_OPTIONAL_TEXT_SLOTS.has(slot)
@@ -141,8 +173,13 @@ export function PhiCardWidgetEditor({ config, onChange }) {
141
173
  variant: config.variant,
142
174
  body: config.body,
143
175
  highlight: config.highlight,
176
+ badgeColor: config.badgeColor,
177
+ badgeStyle: config.badgeStyle,
178
+ billingPeriod: config.billingPeriod,
144
179
  hoverEffect: config.linkTarget ? config.hoverEffect : undefined,
145
- } }), pictureTooNarrow ? (_jsx(PhiTypographyControl, { style: {
180
+ }, ...(config.body === "plan" ? {
181
+ listContent: (_jsx(PhiBulletListEntriesEditor, { entries: config.features ?? PHI_CARD_NO_FEATURES, listStyle: resolvePhiBulletListStyle(config.featureList), states: true, ...(onChange ? { onCommit: (features) => onChange({ features }) } : {}) })),
182
+ } : {}) }), pictureTooNarrow ? (_jsx(PhiTypographyControl, { style: {
146
183
  position: "absolute",
147
184
  left: "0.375rem",
148
185
  top: "0.375rem",
@@ -7,6 +7,9 @@ export type PhiCardWidgetLabels = {
7
7
  description?: string;
8
8
  meta?: string;
9
9
  actionLabel?: string;
10
+ badge?: string;
11
+ pricePeriod?: string;
12
+ pricePeriodYearly?: string;
10
13
  };
11
14
  export type PhiCardWidgetProps = PhiServerBlockBaseProps<PhiCardWidgetLabels, PhiCmsCardWidgetConfig> & {
12
15
  links?: PhiResolvedLinkTargets | null;
@@ -7,6 +7,9 @@ import { resolvePhiLinkHref } from "../../../../../helpers/link-target";
7
7
  import { PhiCmsWidgetType } from "../../../../../constants/cms-widget-types";
8
8
  import { PhiRuntimeModuleRenderClientHost } from "../../../../../components/runtime/runtime-module-render-client-manifest";
9
9
  import { getPhiCardWidgetLabelsForRuntime } from "../../../../../components/widgets/label-sets/card";
10
+ import { PhiBulletListControl } from "../../../../../components/controls/phi-bullet-list-control";
11
+ import { buildPhiBulletListTree, resolvePhiBulletListStyle, } from "../../../../../components/widgets/shared/bullet-list-vocabulary";
12
+ import { maskPhiTextPlaceholders, resolvePhiTextPlaceholders } from "../../../../../helpers/text-placeholders";
10
13
  export async function PhiCardWidget({ labels, config, runtime, links, translate, preview = false, }) {
11
14
  /*
12
15
  * The button's words: the author's, or none where they emptied them for an icon-only button, or the
@@ -15,19 +18,36 @@ export async function PhiCardWidget({ labels, config, runtime, links, translate,
15
18
  const actionEnabled = config?.actionEnabled === true;
16
19
  const defaultLabels = actionEnabled ? await getPhiCardWidgetLabelsForRuntime(runtime) : null;
17
20
  const ownActionLabel = labels.actionLabel ?? config?.actionLabel;
21
+ const plan = config?.body === "plan";
18
22
  const textEntries = [
19
23
  ["eyebrow", labels.eyebrow ?? config?.eyebrow],
20
24
  ["title", labels.title ?? config?.title],
21
25
  ["description", labels.description ?? config?.description],
22
26
  ["meta", labels.meta ?? config?.meta],
23
27
  ["actionLabel", actionEnabled ? ownActionLabel : undefined],
28
+ ["badge", labels.badge ?? config?.badge],
29
+ ["pricePeriod", plan ? labels.pricePeriod ?? config?.pricePeriod : undefined],
30
+ ["pricePeriodYearly", plan ? labels.pricePeriodYearly ?? config?.pricePeriodYearly : undefined],
24
31
  ];
32
+ /*
33
+ * A plan's features, masked as every list entry is: their values stand as `%1` onwards and never reach
34
+ * a translator, and `{site.name}` is filled after (`helpers/text-placeholders.ts`).
35
+ */
36
+ const features = plan ? (config?.features ?? []).filter((entry) => Boolean(entry.text)) : [];
37
+ const maskedFeatures = features.map((entry) => maskPhiTextPlaceholders(entry.text, entry.values?.length ?? 0));
38
+ const sourceTexts = [...textEntries.map(([, value]) => value ?? ""), ...maskedFeatures.map((masked) => masked.text)];
25
39
  const translatedTexts = translate
26
40
  ? await (runtime?.locale.current
27
- ? trBulkForLocale(runtime.locale.current, textEntries.map(([, value]) => value ?? ""))
28
- : trBulk(textEntries.map(([, value]) => value ?? "")))
29
- : textEntries.map(([, value]) => value ?? "");
41
+ ? trBulkForLocale(runtime.locale.current, sourceTexts)
42
+ : trBulk(sourceTexts))
43
+ : sourceTexts;
30
44
  const translatedByKey = new Map(textEntries.map(([key], index) => [key, translatedTexts[index] || undefined]));
45
+ const translatedFeatures = features.map((entry, index) => ({
46
+ ...entry,
47
+ text: resolvePhiTextPlaceholders(translatedTexts[textEntries.length + index] ?? entry.text, maskedFeatures[index].names, runtime, entry.values),
48
+ }));
49
+ /* Drawn here, so the list Control never reaches the browser with the Card (`listContent`). */
50
+ const featureList = translatedFeatures.length > 0 ? (_jsx(PhiBulletListControl, { listStyle: resolvePhiBulletListStyle(config?.featureList), items: buildPhiBulletListTree(translatedFeatures, (entry) => entry.text) })) : null;
31
51
  /*
32
52
  * The figure is left out of the translation on purpose: a Site's own number is not a word, and
33
53
  * `translate` is a per-Widget switch, so a stat card that turned it off to protect the figure would
@@ -92,6 +112,9 @@ export async function PhiCardWidget({ labels, config, runtime, links, translate,
92
112
  variant: config?.variant,
93
113
  body: config?.body,
94
114
  highlight: config?.highlight,
115
+ badgeColor: config?.badgeColor,
116
+ badgeStyle: config?.badgeStyle,
117
+ billingPeriod: config?.billingPeriod,
95
118
  // Only a card that leads somewhere answers the pointer; the preview has no link but shows it.
96
119
  hoverEffect: config?.linkTarget ? config.hoverEffect : undefined,
97
120
  signalRoutes: preview ? null : config?.signalRoutes ?? null,
@@ -106,7 +129,13 @@ export async function PhiCardWidget({ labels, config, runtime, links, translate,
106
129
  ? defaultLabels?.actionLabel
107
130
  : translatedByKey.get("actionLabel") ?? "",
108
131
  value,
132
+ badge: translatedByKey.get("badge"),
133
+ price: plan ? config?.price : undefined,
134
+ pricePeriod: translatedByKey.get("pricePeriod"),
135
+ priceYearly: plan ? config?.priceYearly : undefined,
136
+ pricePeriodYearly: translatedByKey.get("pricePeriodYearly"),
109
137
  },
110
138
  config: clientConfig,
139
+ ...(featureList ? { listContent: featureList } : {}),
111
140
  } }));
112
141
  }
@@ -23,6 +23,7 @@ import { buildPhiMediaSpaceOptions, usePhiMediaSpaceSelectionAllowed, } from "..
23
23
  import { buildPhiMediaFolderCascaderOptions, buildPhiMediaFolderValueById, combinePhiMediaFlagValues, resolvePhiMediaFolderIdFromValue, } from "../../../../../components/media/media-folder-options";
24
24
  import { PHI_ASSET_CONTROLLER_STORE_KEY } from "../../../../../components/media/asset-controller-signals";
25
25
  import { applyPhiAssetCollectionData } from "../../../../../components/media/asset-collection-runtime";
26
+ import { readPhiMediaAssetTiles, readPhiMediaFolders } from "../../../../../components/media/phi-image-preview-data";
26
27
  import { PhiAssetFolderControl } from "../../../../../components/media/phi-asset-folder-control";
27
28
  import { PhiAreaUploadBinding } from "../../../../../components/media/phi-area-upload-widget";
28
29
  import { PHI_MEDIA_WIDGET_DEFAULT_LABELS } from "../../../../../components/media/media-widget-labels";
@@ -65,10 +66,9 @@ export function PhiAssetCollectionViewBinding({ config, binding, labels: rawLabe
65
66
  const selectionState = usePhiImagePreviewStore(PHI_ASSET_CONTROLLER_STORE_KEY);
66
67
  const query = binding.query;
67
68
  const setQuery = binding.setQuery;
68
- const assets = (binding.data?.items ?? []);
69
- const folders = Array.isArray(binding.data?.meta?.folders)
70
- ? binding.data.meta.folders
71
- : [];
69
+ // A Collection carries items of no particular type; they are read as tiles, not cast to them.
70
+ const assets = useMemo(() => readPhiMediaAssetTiles(binding.data?.items ?? []), [binding.data?.items]);
71
+ const folders = useMemo(() => readPhiMediaFolders(binding.data?.meta?.folders), [binding.data?.meta?.folders]);
72
72
  const queryKind = query.filters?.kind;
73
73
  const queryFlags = query.filters?.presentationFlags;
74
74
  const queryFolderId = query.filters?.folderId;
@@ -82,7 +82,8 @@ export function PhiAssetCollectionViewBinding({ config, binding, labels: rawLabe
82
82
  pageSize: query.pageSize ?? 20,
83
83
  assets,
84
84
  folders,
85
- pagination: { total: binding.data?.total ?? assets.length },
85
+ // Nothing read yet is nothing counted yet; the assets of a page are never the count.
86
+ pagination: { total: binding.data?.total ?? 0 },
86
87
  loading: binding.loading,
87
88
  error: binding.error,
88
89
  uploadPanelOpen: binding.openPanelKey === "upload",
@@ -259,7 +260,7 @@ export function PhiAssetCollectionViewBinding({ config, binding, labels: rawLabe
259
260
  } })) : null, diagnostics: state.error ? _jsx(PhiAlertControl, { level: "error", showIcon: true, title: state.error }) : null, body: body, items: state.assets.map((asset) => (_jsx(PhiMediaAssetTileControl, { asset: asset, minColumnWidth: minColumnWidth, selected: state.selectedAssetId === asset.id, mode: mode, deleting: deletingAssetIds.includes(asset.id), onSelect: selectAsset, onDelete: (nextAsset) => { void deleteAsset(nextAsset); }, deleteLabel: labels.grid.deleteLabel, showTypeLabel: true, showDeleteAction: true, showDimensions: true, showIdLabel: true }, asset.id))), mode: mode, gap: gap, minColumnWidth: minColumnWidth, pagination: features.pagination?.enabled === false ? null : {
260
261
  page: state.page,
261
262
  pageSize: state.pageSize,
262
- total: state.pagination?.total ?? state.assets.length,
263
+ total: state.pagination?.total ?? 0,
263
264
  simple: features.pagination?.compact,
264
265
  showSizeChanger: (features.pagination?.pageSizes?.length ?? 0) > 0,
265
266
  pageSizeOptions: features.pagination?.pageSizes,
@@ -1,5 +1,5 @@
1
1
  import { resolvePhiCmsWidgetPluginKey } from "../../../../../constants/cms-widget-types";
2
- import { PHI_CARD_VARIANTS } from "../../../../../components/widgets/shared/card-vocabulary";
2
+ import { PHI_CARD_VARIANTS, readPhiCardBillingPeriod } from "../../../../../components/widgets/shared/card-vocabulary";
3
3
  import { PhiCmsWidgetType } from "../../../../../constants/cms-widget-types";
4
4
  import { readPhiProviderResourceSource } from "../../../../../types/runtime-data-provider";
5
5
  import { PHI_SIGNAL_VALUE_SCHEMAS, readPhiSignalRouteSet } from "../../../../../types/signals";
@@ -25,8 +25,15 @@ function readCardPresentation(value) {
25
25
  actionLabel: readString(value.actionLabel),
26
26
  actionHref: readString(value.actionHref),
27
27
  variant: PHI_CARD_VARIANTS.find((candidate) => candidate === variant),
28
- body: value.body === "text" || value.body === "stat" ? value.body : undefined,
28
+ body: value.body === "text" || value.body === "stat" || value.body === "plan" ? value.body : undefined,
29
29
  highlight: readString(value.highlight),
30
+ badge: readString(value.badge),
31
+ price: readString(value.price),
32
+ pricePeriod: readString(value.pricePeriod),
33
+ priceYearly: readString(value.priceYearly),
34
+ pricePeriodYearly: readString(value.pricePeriodYearly),
35
+ features: readString(value.features),
36
+ billingPeriod: readPhiCardBillingPeriod(value.billingPeriod),
30
37
  };
31
38
  }
32
39
  function readMode(value) {
@@ -8,7 +8,6 @@ import { PhiBulletListControl } from "../../../../../components/controls/phi-bul
8
8
  import { buildPhiBulletListTree, resolvePhiBulletListStyle, } from "../../../../../components/widgets/shared/bullet-list-vocabulary";
9
9
  import { resolvePhiTextPlaceholders } from "../../../../../helpers/text-placeholders";
10
10
  const PHI_LINE_HEIGHT_BASE = 1.5;
11
- const PHI_LINE_HEIGHT_LG = 1.6;
12
11
  const PHI_FONT_WEIGHT_STRONG = 600;
13
12
  export function PhiDescriptionWidgetClient({ labels, config, }) {
14
13
  const { token } = usePhiConfig();
@@ -18,6 +17,7 @@ export function PhiDescriptionWidgetClient({ labels, config, }) {
18
17
  borderRadius: 999,
19
18
  paddingInline: token.paddingSM,
20
19
  paddingBlock: token.paddingXXS,
20
+ fontSize: token.fontSizeSM,
21
21
  fontWeight: PHI_FONT_WEIGHT_STRONG,
22
22
  letterSpacing: "0.04em",
23
23
  color: token.colorTextTertiary,
@@ -26,8 +26,8 @@ export function PhiDescriptionWidgetClient({ labels, config, }) {
26
26
  }, children: labels.eyebrow })) : null, labels.title || labels.description ? (_jsxs("div", { children: [labels.title ? (_jsx(PhiTypographyControl, { presentation: "title", level: 2, style: { marginBottom: labels.description ? token.paddingXS : 0 }, children: labels.title })) : null, labels.description ? (_jsx(PhiTypographyControl, { presentation: "paragraph", type: config?.tone, style: {
27
27
  marginBottom: 0,
28
28
  color: config?.tone ? undefined : token.colorTextSecondary,
29
- fontSize: token.fontSizeLG,
30
- lineHeight: PHI_LINE_HEIGHT_LG,
29
+ fontSize: token.fontSize,
30
+ lineHeight: PHI_LINE_HEIGHT_BASE,
31
31
  }, children: labels.description })) : null] })) : null, labels.asideTitle || asideItems.length > 0 ? (_jsxs(PhiFlexControl, { vertical: true, gap: token.paddingMD, style: { width: "100%" }, children: [labels.asideTitle ? (_jsx(PhiTypographyControl, { strong: true, style: {
32
32
  fontSize: token.fontSize,
33
33
  lineHeight: PHI_LINE_HEIGHT_BASE,
@@ -39,6 +39,7 @@ export declare const PHI_DESCRIPTION_WIDGET_DEFINITION: {
39
39
  } & {
40
40
  type: "string" | "url" | "icon";
41
41
  emptyValue?: "";
42
+ placeholder?: string;
42
43
  }) | ({
43
44
  key: string;
44
45
  label: string;
@@ -312,30 +313,6 @@ export declare const PHI_DESCRIPTION_WIDGET_DEFINITION: {
312
313
  editorPlacement?: "inspector" | "geometry" | "toolbar";
313
314
  visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
314
315
  heading?: string;
315
- } & {
316
- type: "background";
317
- section?: string;
318
- storage?: import("../../../../../types").PhiCmsConfigFieldValueStorage;
319
- }) | ({
320
- key: string;
321
- label: string;
322
- description?: string;
323
- required?: boolean;
324
- editorPlacement?: "inspector" | "geometry" | "toolbar";
325
- visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
326
- heading?: string;
327
- } & {
328
- type: "border";
329
- section?: string;
330
- storage?: import("../../../../../types").PhiCmsConfigFieldValueStorage;
331
- }) | ({
332
- key: string;
333
- label: string;
334
- description?: string;
335
- required?: boolean;
336
- editorPlacement?: "inspector" | "geometry" | "toolbar";
337
- visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
338
- heading?: string;
339
316
  } & {
340
317
  type: "surface";
341
318
  tone?: false;
@@ -348,7 +325,7 @@ export declare const PHI_DESCRIPTION_WIDGET_DEFINITION: {
348
325
  visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
349
326
  heading?: string;
350
327
  } & {
351
- type: "shadow" | "grid-placement" | "column-count";
328
+ type: "grid-placement" | "column-count";
352
329
  section?: string;
353
330
  }) | {
354
331
  key: string;
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useMemo, useRef, useState } from "react";
3
+ import { useMemo, useState } from "react";
4
4
  import { PhiTagControl } from "../../../../../components/controls/phi-tag-control";
5
5
  import { PhiTextControl } from "../../../../../components/controls/phi-text-control";
6
6
  import { PhiFlexControl } from "../../../../../components/controls/phi-flex-control";
7
7
  import { resolvePhiDescriptionEditorSections } from "../../../../../components/widgets/client/description-editor-sections";
8
- import { PhiBulletListControl } from "../../../../../components/controls/phi-bullet-list-control";
9
- import { buildPhiBulletListTree, resolvePhiBulletListLevel, resolvePhiBulletListStyle, } from "../../../../../components/widgets/shared/bullet-list-vocabulary";
8
+ import { PhiBulletListEntriesEditor } from "../../../../../components/widgets/client/bullet-list-entries-editor";
9
+ import { resolvePhiBulletListStyle, } from "../../../../../components/widgets/shared/bullet-list-vocabulary";
10
10
  function resolveEditorConfig(config) {
11
11
  return {
12
12
  eyebrow: config?.eyebrow ?? "",
@@ -36,7 +36,6 @@ export function PhiDescriptionWidgetEditor({ config, onChange, }) {
36
36
  * would be gone before its blur could write the empty value.
37
37
  */
38
38
  const sections = resolvePhiDescriptionEditorSections(resolvedConfig, Boolean(onChange));
39
- const asideListRef = useRef(null);
40
39
  /*
41
40
  * Typing changes the draft and nothing else.
42
41
  *
@@ -56,56 +55,12 @@ export function PhiDescriptionWidgetEditor({ config, onChange, }) {
56
55
  }
57
56
  onChange?.({ [key]: draft[key] });
58
57
  }
59
- function updateAsideItem(index, value) {
60
- setDraftState((current) => {
61
- const currentDraft = current.source === config ? current.value : resolvedConfig;
62
- const nextItems = [...currentDraft.asideItems];
63
- nextItems[index] = { ...nextItems[index], text: value };
64
- return {
65
- source: config,
66
- value: {
67
- ...currentDraft,
68
- asideItems: nextItems,
69
- },
70
- };
71
- });
72
- }
73
- function commitAsideItems(items = draft.asideItems) {
74
- if (JSON.stringify(items) === JSON.stringify(resolvedConfig.asideItems)) {
75
- return;
76
- }
77
- onChange?.({ asideItems: items });
78
- }
79
- /*
80
- * Tab moves an entry a level down and Shift+Tab a level up, as in every outline editor. The move is
81
- * written at once, with whatever was typed into the entry so far: it is a change of structure, and
82
- * waiting for the blur would let the entry jump back as the tree is drawn again.
83
- */
84
- function shiftAsideItemLevel(index, delta) {
85
- const items = draft.asideItems;
86
- const entry = items[index];
87
- if (!entry)
88
- return;
89
- const level = resolvePhiBulletListLevel((entry.level ?? 1) + delta);
90
- if (level === (entry.level ?? 1))
91
- return;
92
- const { level: _level, ...rest } = entry;
93
- void _level;
94
- const next = items.map((item, itemIndex) => (itemIndex === index ? (level > 1 ? { ...rest, level } : rest) : item));
95
- setDraftState({ source: config, value: { ...draft, asideItems: next } });
96
- commitAsideItems(next);
97
- // The entry now hangs elsewhere in the tree and its field is a new one; the caret goes back into it.
98
- requestAnimationFrame(() => {
99
- const field = asideListRef.current?.querySelectorAll("textarea")[index];
100
- field?.focus();
101
- field?.setSelectionRange(field.value.length, field.value.length);
102
- });
103
- }
104
58
  return (_jsx(PhiFlexControl, { vertical: true, gap: 16, style: { width: "100%", minWidth: 0 }, children: _jsxs(PhiFlexControl, { vertical: true, gap: 10, style: { width: "100%", minWidth: 0 }, children: [sections.eyebrowTag ? (_jsx(PhiTagControl, { color: "default", style: {
105
59
  width: "fit-content",
106
60
  borderRadius: 999,
107
61
  paddingInline: "var(--ant-padding-sm)",
108
62
  paddingBlock: "var(--ant-padding-xxs)",
63
+ fontSize: "var(--ant-font-size-sm)",
109
64
  fontWeight: 600,
110
65
  letterSpacing: "0.04em",
111
66
  color: "var(--ant-color-text-tertiary)",
@@ -120,24 +75,13 @@ export function PhiDescriptionWidgetEditor({ config, onChange, }) {
120
75
  } }), _jsx(PhiTextControl, { presentation: "textarea", value: draft.description, readOnly: !onChange, variant: "borderless", placeholder: "Description", autoSize: { minRows: 2, maxRows: 8 }, onChange: (value) => updateField("description", value ?? ""), onBlur: () => commitField("description"), style: {
121
76
  ...EDITOR_TEXTAREA_STYLE,
122
77
  color: "var(--ant-color-text-secondary)",
123
- fontSize: "1.125rem",
124
- lineHeight: 1.6,
78
+ fontSize: "var(--ant-font-size)",
79
+ lineHeight: 1.5,
125
80
  } })] })) : null, sections.aside ? (_jsxs(PhiFlexControl, { vertical: true, gap: 12, style: { width: "100%" }, children: [_jsx(PhiTextControl, { presentation: "textarea", value: draft.asideTitle, readOnly: !onChange, variant: "borderless", placeholder: "Aside title", autoSize: { minRows: 1, maxRows: 3 }, onChange: (value) => updateField("asideTitle", value ?? ""), onBlur: () => commitField("asideTitle"), style: {
126
81
  ...EDITOR_TEXTAREA_STYLE,
127
82
  color: "var(--ant-color-text-heading)",
128
83
  fontWeight: 600,
129
- } }), _jsx("div", { ref: asideListRef, style: { width: "100%", minWidth: 0 }, children: _jsx(PhiBulletListControl, { listStyle: resolvePhiBulletListStyle(config?.asideList),
130
- // Each entry is a borderless text field, whose first line stands at the field's height.
131
- markerLineHeight: "var(--ant-control-height)", items: buildPhiBulletListTree(draft.asideItems, (item, index) => (_jsx(PhiTextControl, { presentation: "textarea", value: item.text, readOnly: !onChange, variant: "borderless", placeholder: `Item ${index + 1}`, autoSize: { minRows: 1, maxRows: 6 }, onChange: (value) => updateAsideItem(index, value ?? ""), onBlur: () => commitAsideItems(), onKeyDown: (event) => {
132
- if (event.key !== "Tab" || !onChange)
133
- return;
134
- event.preventDefault();
135
- shiftAsideItemLevel(index, event.shiftKey ? -1 : 1);
136
- }, style: {
137
- ...EDITOR_TEXTAREA_STYLE,
138
- borderBottom: "none",
139
- paddingBlock: 0,
140
- } }))) }) })] })) : null, _jsx(PhiTextControl, { presentation: "textarea", value: draft.footer, readOnly: !onChange, variant: "borderless", placeholder: "Footer", autoSize: { minRows: 1, maxRows: 5 }, onChange: (value) => updateField("footer", value ?? ""), onBlur: () => commitField("footer"), style: {
84
+ } }), _jsx(PhiBulletListEntriesEditor, { entries: resolvedConfig.asideItems, listStyle: resolvePhiBulletListStyle(config?.asideList), ...(onChange ? { onCommit: (asideItems) => onChange({ asideItems }) } : {}) })] })) : null, _jsx(PhiTextControl, { presentation: "textarea", value: draft.footer, readOnly: !onChange, variant: "borderless", placeholder: "Footer", autoSize: { minRows: 1, maxRows: 5 }, onChange: (value) => updateField("footer", value ?? ""), onBlur: () => commitField("footer"), style: {
141
85
  ...EDITOR_TEXTAREA_STYLE,
142
86
  color: "var(--ant-color-text-tertiary)",
143
87
  } })] }) }));
@@ -64,6 +64,7 @@ export async function PhiDescriptionWidget({ labels, config, runtime, translate,
64
64
  borderRadius: "9999px",
65
65
  paddingInline: PHI_SPACE.sm,
66
66
  paddingBlock: PHI_SPACE.xxs,
67
+ fontSize: PHI_FONT_SIZE.sm,
67
68
  fontWeight: 600,
68
69
  letterSpacing: "0.04em",
69
70
  color: PHI_COLOR.textTertiary,
@@ -82,8 +83,8 @@ export async function PhiDescriptionWidget({ labels, config, runtime, translate,
82
83
  margin: 0,
83
84
  marginBottom: 0,
84
85
  color: resolveDescriptionToneColor(config?.tone),
85
- fontSize: PHI_FONT_SIZE.lg,
86
- lineHeight: PHI_LINE_HEIGHT.lg,
86
+ fontSize: PHI_FONT_SIZE.base,
87
+ lineHeight: PHI_LINE_HEIGHT.base,
87
88
  }, children: description })) : null] })) : null, asideTitle || resolvedAsideItems.length > 0 ? (_jsxs("div", { style: subStackStyle, children: [asideTitle ? (_jsx("span", { style: {
88
89
  display: "block",
89
90
  fontSize: PHI_FONT_SIZE.base,
@@ -83,6 +83,7 @@ export declare const PHI_ENTRY_LIST_WIDGET_DEFINITION: {
83
83
  } & {
84
84
  type: "string" | "url" | "icon";
85
85
  emptyValue?: "";
86
+ placeholder?: string;
86
87
  }) | ({
87
88
  key: string;
88
89
  label: string;
@@ -356,30 +357,6 @@ export declare const PHI_ENTRY_LIST_WIDGET_DEFINITION: {
356
357
  editorPlacement?: "inspector" | "geometry" | "toolbar";
357
358
  visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
358
359
  heading?: string;
359
- } & {
360
- type: "background";
361
- section?: string;
362
- storage?: import("../../../../../types").PhiCmsConfigFieldValueStorage;
363
- }) | ({
364
- key: string;
365
- label: string;
366
- description?: string;
367
- required?: boolean;
368
- editorPlacement?: "inspector" | "geometry" | "toolbar";
369
- visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
370
- heading?: string;
371
- } & {
372
- type: "border";
373
- section?: string;
374
- storage?: import("../../../../../types").PhiCmsConfigFieldValueStorage;
375
- }) | ({
376
- key: string;
377
- label: string;
378
- description?: string;
379
- required?: boolean;
380
- editorPlacement?: "inspector" | "geometry" | "toolbar";
381
- visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
382
- heading?: string;
383
360
  } & {
384
361
  type: "surface";
385
362
  tone?: false;
@@ -392,7 +369,7 @@ export declare const PHI_ENTRY_LIST_WIDGET_DEFINITION: {
392
369
  visibleWhen?: import("../../../../../types").PhiCmsConfigFieldVisibilityRule | readonly import("../../../../../types").PhiCmsConfigFieldVisibilityRule[];
393
370
  heading?: string;
394
371
  } & {
395
- type: "shadow" | "grid-placement" | "column-count";
372
+ type: "grid-placement" | "column-count";
396
373
  section?: string;
397
374
  }) | {
398
375
  key: string;