@phis/ui 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/components/cms/phi-cms-layout-renderer.js +4 -3
  2. package/components/cms/phi-cms-page-render-scope.d.ts +4 -5
  3. package/components/cms/phi-cms-page-render-scope.js +43 -22
  4. package/components/cms/phi-cms-render-diagnostic-client.js +7 -3
  5. package/components/cms/phi-cms-render-error-boundary.js +2 -1
  6. package/components/controls/phi-bullet-list-control.js +31 -2
  7. package/components/controls/phi-ribbon-control.d.ts +29 -0
  8. package/components/controls/phi-ribbon-control.js +53 -0
  9. package/components/controls/phi-table-control.d.ts +3 -0
  10. package/components/controls/phi-table-control.js +13 -1
  11. package/components/controls/phi-tree-control.js +3 -3
  12. package/components/forms/shared-form-provider-registry.js +1 -4
  13. package/components/media/asset-collection-runtime.js +6 -16
  14. package/components/media/media-font-metrics.d.ts +3 -0
  15. package/components/media/media-font-metrics.js +43 -0
  16. package/components/media/phi-area-upload-widget.js +53 -97
  17. package/components/media/phi-image-preview-data.d.ts +13 -0
  18. package/components/media/phi-image-preview-data.js +184 -9
  19. package/components/media/phi-media-picker-binding.js +16 -13
  20. package/components/media/phi-media-upload.d.ts +15 -8
  21. package/components/media/phi-media-upload.js +18 -9
  22. package/components/media/phi-site-font-assets.js +7 -8
  23. package/components/overlays/phi-overlay-container-client.js +16 -1
  24. package/components/regions/presets/phi-settings-page-shell-tree.js +48 -1
  25. package/components/runtime/runtime-controller-materialization.js +12 -1
  26. package/components/state/scoped-state-store.js +20 -3
  27. package/components/tables/client/phi-table-binding.d.ts +2 -1
  28. package/components/tables/client/phi-table-binding.js +45 -21
  29. package/components/trees/client/phi-tree-binding.js +19 -11
  30. package/components/widgets/client/bullet-list-entries-editor.d.ts +26 -0
  31. package/components/widgets/client/bullet-list-entries-editor.js +103 -0
  32. package/components/widgets/config/choice-shared.js +12 -13
  33. package/components/widgets/config/command-buttons.d.ts +5 -1
  34. package/components/widgets/config/command-buttons.js +38 -81
  35. package/components/widgets/config/control-signal-config.d.ts +3 -1
  36. package/components/widgets/config/control-signal-config.js +19 -17
  37. package/components/widgets/config/image-source-parser.d.ts +1 -0
  38. package/components/widgets/config/image-source-parser.js +7 -8
  39. package/components/widgets/config/mask.d.ts +6 -1
  40. package/components/widgets/config/mask.js +24 -1
  41. package/components/widgets/config/parser-primitives.js +72 -0
  42. package/components/widgets/config/stack-tabs.d.ts +1 -1
  43. package/components/widgets/config/stack-tabs.js +2 -3
  44. package/components/widgets/config/strict-config-reader.d.ts +40 -0
  45. package/components/widgets/config/strict-config-reader.js +174 -0
  46. package/components/widgets/label-sets/effects.js +2 -0
  47. package/components/widgets/label-types/effects.d.ts +1 -0
  48. package/components/widgets/label-types/effects.js +1 -0
  49. package/components/widgets/navigation-descriptor-resolver.server.js +20 -8
  50. package/components/widgets/shared/bullet-list-vocabulary.d.ts +17 -1
  51. package/components/widgets/shared/bullet-list-vocabulary.js +19 -2
  52. package/components/widgets/shared/card-body-client.d.ts +16 -4
  53. package/components/widgets/shared/card-body-client.js +81 -24
  54. package/components/widgets/shared/card-vocabulary.d.ts +21 -4
  55. package/components/widgets/shared/card-vocabulary.js +28 -2
  56. package/components/widgets/signals/control-signal-capabilities.d.ts +0 -18
  57. package/components/widgets/signals/control-signal-capabilities.js +10 -22
  58. package/components/workspace/catalog-store.d.ts +4 -3
  59. package/components/workspace/catalog-store.js +6 -5
  60. package/gateway/dashboard-cards-route.js +1 -0
  61. package/gateway/internal-references.d.ts +6 -1
  62. package/gateway/internal-references.js +48 -23
  63. package/gateway/site-cms-write-validation.d.ts +9 -0
  64. package/gateway/site-cms-write-validation.js +78 -0
  65. package/gateway/site-proxy.js +19 -3
  66. package/helpers/renderable-block-serialization.js +1 -1
  67. package/next/config.d.mts +3 -0
  68. package/next/config.mjs +28 -1
  69. package/package.json +2 -2
  70. package/plugins/runtime/phi-slot-child-viewport-effects-observer.js +5 -1
  71. package/plugins/runtime-modules/accounting/presets.d.ts +9 -0
  72. package/plugins/runtime-modules/accounting/presets.js +37 -0
  73. package/plugins/runtime-modules/accounting/server.d.ts +1 -4
  74. package/plugins/runtime-modules/accounting/server.js +4 -7
  75. package/plugins/runtime-modules/app/presets.d.ts +18 -0
  76. package/plugins/runtime-modules/app/presets.js +67 -0
  77. package/plugins/runtime-modules/app/server.d.ts +1 -4
  78. package/plugins/runtime-modules/app/server.js +4 -7
  79. package/plugins/runtime-modules/asset/controller/runtime.js +2 -2
  80. package/plugins/runtime-modules/asset/services/collection.js +9 -1
  81. package/plugins/runtime-modules/asset/services/options.js +2 -2
  82. package/plugins/runtime-modules/builder/area-settings-answer.js +2 -1
  83. package/plugins/runtime-modules/builder/authoring-canvas.js +6 -6
  84. package/plugins/runtime-modules/builder/cards.js +3 -5
  85. package/plugins/runtime-modules/builder/clients/builder-region-overrides.js +3 -3
  86. package/plugins/runtime-modules/builder/clients/canvas-widget.js +15 -54
  87. package/plugins/runtime-modules/builder/clients/inspector-config-field.d.ts +4 -1
  88. package/plugins/runtime-modules/builder/clients/inspector-config-field.js +5 -34
  89. package/plugins/runtime-modules/builder/clients/inspector-link-target-field.js +1 -1
  90. package/plugins/runtime-modules/builder/clients/inspector-section-widget.js +8 -8
  91. package/plugins/runtime-modules/builder/clients/inspector-title.js +6 -6
  92. package/plugins/runtime-modules/builder/clients/layout-inspector.d.ts +1 -1
  93. package/plugins/runtime-modules/builder/clients/layout-inspector.js +11 -25
  94. package/plugins/runtime-modules/builder/clients/mode-switch.js +1 -1
  95. package/plugins/runtime-modules/builder/clients/pages-header.js +11 -11
  96. package/plugins/runtime-modules/builder/clients/pages-workspace.js +1 -1
  97. package/plugins/runtime-modules/builder/clients/region-visibility-fields.js +1 -1
  98. package/plugins/runtime-modules/builder/clients/runtime-module-authoring-boundary.js +1 -1
  99. package/plugins/runtime-modules/builder/clients/shells-workspace.js +15 -31
  100. package/plugins/runtime-modules/builder/clients/structure-canvas.js +1 -1
  101. package/plugins/runtime-modules/builder/clients/use-region-draft-hydration.d.ts +26 -0
  102. package/plugins/runtime-modules/builder/clients/use-region-draft-hydration.js +36 -0
  103. package/plugins/runtime-modules/builder/clients/widget-effects-editor.js +1 -1
  104. package/plugins/runtime-modules/builder/clients/widget-inspector.js +1 -0
  105. package/plugins/runtime-modules/builder/clients/workspace-scope-boundary.js +2 -2
  106. package/plugins/runtime-modules/builder/cms-instance-allocator.js +8 -28
  107. package/plugins/runtime-modules/builder/controller/client.d.ts +0 -15
  108. package/plugins/runtime-modules/builder/controller/definition.d.ts +0 -15
  109. package/plugins/runtime-modules/builder/controller/definition.js +0 -8
  110. package/plugins/runtime-modules/builder/controller/draft-command-controller.d.ts +1 -2
  111. package/plugins/runtime-modules/builder/controller/draft-command-controller.js +11 -30
  112. package/plugins/runtime-modules/builder/controller/draft-status-controller.js +15 -2
  113. package/plugins/runtime-modules/builder/controller/inspector-controller.d.ts +1 -2
  114. package/plugins/runtime-modules/builder/controller/inspector-controller.js +4 -7
  115. package/plugins/runtime-modules/builder/controller/page-controller.d.ts +1 -2
  116. package/plugins/runtime-modules/builder/controller/page-controller.js +16 -68
  117. package/plugins/runtime-modules/builder/controller/server-definition.d.ts +0 -15
  118. package/plugins/runtime-modules/builder/controller/signal-wiring-controller.d.ts +2 -5
  119. package/plugins/runtime-modules/builder/controller/signal-wiring-controller.js +6 -50
  120. package/plugins/runtime-modules/builder/controller/workspace-controller.d.ts +2 -3
  121. package/plugins/runtime-modules/builder/controller/workspace-controller.js +89 -153
  122. package/plugins/runtime-modules/builder/data-providers.d.ts +1 -0
  123. package/plugins/runtime-modules/builder/data-providers.js +1 -0
  124. package/plugins/runtime-modules/builder/definition.d.ts +1 -0
  125. package/plugins/runtime-modules/builder/developer-workspace-store.d.ts +64 -30
  126. package/plugins/runtime-modules/builder/developer-workspace-store.js +255 -61
  127. package/plugins/runtime-modules/builder/edit-scaffold-drawer.js +1 -1
  128. package/plugins/runtime-modules/builder/history.d.ts +3 -1
  129. package/plugins/runtime-modules/builder/options-providers.js +3 -2
  130. package/plugins/runtime-modules/builder/page-catalog-client.js +19 -7
  131. package/plugins/runtime-modules/builder/page-meta-form.js +1 -0
  132. package/plugins/runtime-modules/builder/page-references-provider.js +1 -1
  133. package/plugins/runtime-modules/builder/persistence.js +33 -69
  134. package/plugins/runtime-modules/builder/public-route-collisions.d.ts +2 -2
  135. package/plugins/runtime-modules/builder/public-route-collisions.js +6 -19
  136. package/plugins/runtime-modules/builder/render-root-node-preview.server.js +20 -3
  137. package/plugins/runtime-modules/builder/render-root-node-scaffold.js +3 -3
  138. package/plugins/runtime-modules/builder/runtime-module-selection.d.ts +2 -12
  139. package/plugins/runtime-modules/builder/runtime-module-selection.js +16 -42
  140. package/plugins/runtime-modules/builder/services/navigation-table.js +9 -15
  141. package/plugins/runtime-modules/builder/services/page-source-tree.js +8 -8
  142. package/plugins/runtime-modules/builder/services/runtime-modules-table.js +10 -10
  143. package/plugins/runtime-modules/builder/services/signal-routes-table.js +3 -3
  144. package/plugins/runtime-modules/builder/signal-route-selection.d.ts +1 -2
  145. package/plugins/runtime-modules/builder/signal-route-selection.js +2 -2
  146. package/plugins/runtime-modules/builder/signal-wiring-options.js +3 -2
  147. package/plugins/runtime-modules/builder/structure-dnd.js +8 -61
  148. package/plugins/runtime-modules/builder/trees/phi-default-builder-area-preset-tree.js +13 -10
  149. package/plugins/runtime-modules/builder/widgets/structure-region/built-in.js +12 -18
  150. package/plugins/runtime-modules/builder/workspace-catalog-actions.d.ts +55 -0
  151. package/plugins/runtime-modules/builder/workspace-catalog-actions.js +142 -0
  152. package/plugins/runtime-modules/client-manifests/common.js +1 -1
  153. package/plugins/runtime-modules/{runtime-calendar-adapters.js → core/calendar-adapters.js} +2 -2
  154. package/plugins/runtime-modules/{client-calendar-adapters/core.js → core/client-calendar-adapters.js} +1 -1
  155. package/plugins/runtime-modules/core/content-entries/table.js +1 -1
  156. package/plugins/runtime-modules/core/data-providers.d.ts +3 -0
  157. package/plugins/runtime-modules/core/data-providers.js +2 -1
  158. package/plugins/runtime-modules/core/definition.d.ts +3 -0
  159. package/plugins/runtime-modules/core/definition.js +1 -1
  160. package/plugins/runtime-modules/core/messaging/data-providers.d.ts +1 -0
  161. package/plugins/runtime-modules/core/messaging/data-providers.js +1 -0
  162. package/plugins/runtime-modules/core/messaging/thread-inbox-table.js +1 -1
  163. package/plugins/runtime-modules/core/server.js +1 -1
  164. package/plugins/runtime-modules/core/themes.d.ts +44 -0
  165. package/plugins/runtime-modules/core/themes.js +12 -0
  166. package/plugins/runtime-modules/core/widgets/card/collection-view-binding.js +25 -9
  167. package/plugins/runtime-modules/core/widgets/card/config.d.ts +296 -254
  168. package/plugins/runtime-modules/core/widgets/card/config.js +52 -3
  169. package/plugins/runtime-modules/core/widgets/card/editor.js +30 -3
  170. package/plugins/runtime-modules/core/widgets/card/server.d.ts +3 -0
  171. package/plugins/runtime-modules/core/widgets/card/server.js +31 -3
  172. package/plugins/runtime-modules/core/widgets/collection-view/asset-binding.js +7 -6
  173. package/plugins/runtime-modules/core/widgets/collection-view/config.js +9 -2
  174. package/plugins/runtime-modules/core/widgets/description/config.d.ts +1 -25
  175. package/plugins/runtime-modules/core/widgets/description/editor.js +4 -61
  176. package/plugins/runtime-modules/core/widgets/entry-list/config.d.ts +1 -25
  177. package/plugins/runtime-modules/core/widgets/gallery/config.d.ts +1 -25
  178. package/plugins/runtime-modules/core/widgets/image/config.js +2 -2
  179. package/plugins/runtime-modules/core/widgets/markdown/editor.js +2 -3
  180. package/plugins/runtime-modules/core/widgets/result/config.d.ts +4 -25
  181. package/plugins/runtime-modules/core/widgets/result/config.js +2 -0
  182. package/plugins/runtime-modules/core/widgets/result/server.js +25 -19
  183. package/plugins/runtime-modules/core/widgets/simple-text/config.d.ts +1 -25
  184. package/plugins/runtime-modules/core/widgets/slot-upload/client.js +11 -2
  185. package/plugins/runtime-modules/core/widgets/table/client.js +8 -4
  186. package/plugins/runtime-modules/core/widgets/table/config.d.ts +3 -83
  187. package/plugins/runtime-modules/core/widgets/table/config.js +302 -452
  188. package/plugins/runtime-modules/core/widgets/tree/config.js +5 -2
  189. package/plugins/runtime-modules/dashboard/card-rows.d.ts +5 -0
  190. package/plugins/runtime-modules/dashboard/card-rows.js +59 -0
  191. package/plugins/runtime-modules/dashboard/clients/dashboard-card-view.js +4 -6
  192. package/plugins/runtime-modules/dashboard/services/collection.js +17 -7
  193. package/plugins/runtime-modules/groups/data-providers.d.ts +2 -0
  194. package/plugins/runtime-modules/groups/data-providers.js +3 -3
  195. package/plugins/runtime-modules/groups/definition.d.ts +2 -0
  196. package/plugins/runtime-modules/localization/data-providers.d.ts +3 -0
  197. package/plugins/runtime-modules/localization/data-providers.js +2 -0
  198. package/plugins/runtime-modules/localization/definition.d.ts +3 -0
  199. package/plugins/runtime-modules/localization/services/table.js +3 -7
  200. package/plugins/runtime-modules/observability/data-providers.d.ts +1 -0
  201. package/plugins/runtime-modules/observability/data-providers.js +1 -0
  202. package/plugins/runtime-modules/observability/definition.d.ts +1 -0
  203. package/plugins/runtime-modules/observability/module.d.ts +1 -0
  204. package/plugins/runtime-modules/observability/services/table.js +1 -1
  205. package/plugins/runtime-modules/phi-default-site-area-preset-tree.js +2 -105
  206. package/plugins/runtime-modules/public/presets.d.ts +115 -0
  207. package/plugins/runtime-modules/{area-base-presets.js → public/presets.js} +19 -119
  208. package/plugins/runtime-modules/public/server.d.ts +1 -4
  209. package/plugins/runtime-modules/public/server.js +4 -7
  210. package/plugins/runtime-modules/public/trees/phi-default-pub-error-page-tree.js +7 -8
  211. package/plugins/runtime-modules/public-base-page-references.d.ts +1 -1
  212. package/plugins/runtime-modules/public-base-page-references.js +1 -1
  213. package/plugins/runtime-modules/revisions/controller/client.js +11 -11
  214. package/plugins/runtime-modules/revisions/services/table.js +3 -3
  215. package/plugins/runtime-modules/theme/trees/phi-default-builder-theme-page-tree.js +22 -0
  216. package/plugins/runtime-modules/theme/widgets/brand-controls/client.d.ts +2 -1
  217. package/plugins/runtime-modules/theme/widgets/brand-controls/client.js +93 -58
  218. package/plugins/runtime-modules/theme/widgets/brand-controls/config.d.ts +2 -1
  219. package/plugins/runtime-modules/theme/widgets/brand-controls/config.js +23 -22
  220. package/plugins/runtime-modules/theme/widgets/brand-controls/plugin.js +1 -1
  221. package/plugins/runtime-modules/theme-descriptors.js +1 -1
  222. package/plugins/runtime-modules/user-management/data-providers.d.ts +2 -0
  223. package/plugins/runtime-modules/user-management/data-providers.js +1 -0
  224. package/plugins/runtime-modules/user-management/definition.d.ts +2 -0
  225. package/styles/control-shape.css +11 -11
  226. package/styles/controls.css +3 -3
  227. package/styles/layout.css +16 -7
  228. package/types/cms-config.js +142 -185
  229. package/types/cms-plugins.d.ts +4 -11
  230. package/types/core-widget-placements.d.ts +14 -3
  231. package/types/dashboard-cards.d.ts +9 -0
  232. package/types/media.d.ts +0 -3
  233. package/types/renderable-block.d.ts +6 -1
  234. package/types/table-widget.d.ts +9 -0
  235. package/types/table-widget.js +20 -0
  236. package/types.d.ts +1 -1
  237. package/widget-config.d.ts +2 -0
  238. package/widget-config.js +6 -0
  239. package/plugins/runtime-modules/area-base-presets.d.ts +0 -139
  240. /package/plugins/runtime-modules/{runtime-calendar-adapters.d.ts → core/calendar-adapters.d.ts} +0 -0
  241. /package/plugins/runtime-modules/{client-calendar-adapters/core.d.ts → core/client-calendar-adapters.d.ts} +0 -0
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore, } from "react";
4
4
  import { usePhiSignalDispatcher, usePhiSignalListener } from "../../../../../components/runtime/runtime-signal-bus";
5
5
  import { usePhiSignalIdentity } from "../../../../../components/runtime/runtime-signal-identity";
6
+ import { usePhiControlSignalController } from "../../../../../components/widgets/client/shared/phi-control-signals";
6
7
  import { PHI_SIGNAL_VALUE_SCHEMAS } from "../../../../../types/signals";
7
8
  import { createPhiThemeControllerAddress } from "../../../../../plugins/runtime-modules/theme/controller/address";
8
9
  import { PHI_THEME_SIGNAL_CHANNELS } from "../../../../../plugins/runtime-modules/theme/controller/signals";
@@ -484,6 +485,35 @@ function readEffectiveTokenString(token, key, fallback) {
484
485
  const value = token[key];
485
486
  return typeof value === "string" && value.trim() ? value : fallback;
486
487
  }
488
+ /*
489
+ * A value the alias resolver always sets (`resolvePhiAntdAliasTokens`), read without a stand-in. The
490
+ * previews used to carry a hex fallback beside each of these, which could only ever show if the resolver
491
+ * broke -- and then showed a colour that was nobody's Theme instead of saying so.
492
+ */
493
+ function readAliasTokenString(token, key) {
494
+ const value = token[key];
495
+ if (typeof value !== "string" || !value.trim()) {
496
+ throw new Error(`The resolved Theme has no "${key}".`);
497
+ }
498
+ return value;
499
+ }
500
+ function readAliasTokenNumber(token, key) {
501
+ const value = token[key];
502
+ if (typeof value !== "number" || !Number.isFinite(value)) {
503
+ throw new Error(`The resolved Theme has no "${key}".`);
504
+ }
505
+ return value;
506
+ }
507
+ /** A draft's alias tokens for one mode, its blocks folded in, as the live render resolves a Theme. */
508
+ function resolveBrandDraftAliasTokens(resolvedTheme, preset, mode, fonts = {}) {
509
+ return resolvePhiAntdAliasTokens(mode, {
510
+ ...buildPhiEffectiveNonColorThemeTokens(resolvedTheme),
511
+ ...resolvePhiThemeColorTokens(preset, resolvedTheme.palette, mode),
512
+ ...(resolvedTheme.style?.token ?? {}),
513
+ ...(fonts.body ? { fontFamily: fonts.body } : {}),
514
+ ...(fonts.mono ? { fontFamilyCode: fonts.mono } : {}),
515
+ });
516
+ }
487
517
  function readEffectiveTokenNumber(token, key, fallback) {
488
518
  const value = token[key];
489
519
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -808,18 +838,23 @@ function subscribePhiBrandPreviewMode(listener) {
808
838
  phiBrandPreviewModeListeners.delete(listener);
809
839
  };
810
840
  }
811
- function usePhiBrandPreviewMode(initialMode) {
841
+ function usePhiBrandPreviewMode(initialMode, signalRoutes) {
812
842
  const heard = useSyncExternalStore(subscribePhiBrandPreviewMode, () => phiBrandPreviewModeHeard, () => null);
813
- usePhiSignalListener((signal) => {
814
- if (signal.scope === "page" &&
815
- signal.receiver === "broadcast" &&
816
- signal.channel === PHI_THEME_SIGNAL_CHANNELS.previewThemeMode &&
817
- signal.action === "change" &&
818
- signal.valueType === "boolean") {
843
+ /* Through the routes the panel's tree wrote for `previewThemeMode`, as every Widget input arrives. */
844
+ usePhiControlSignalController({
845
+ key: "brandPreviewThemeMode",
846
+ valueType: "boolean",
847
+ sender: usePhiSignalIdentity().receiver ?? null,
848
+ signalRoutes,
849
+ onReceiveCapability: (capabilityId, signal) => {
850
+ if (capabilityId !== "previewThemeMode" || signal.valueType !== "boolean") {
851
+ return false;
852
+ }
819
853
  phiBrandPreviewModeHeard = signal.value === true ? "dark" : "light";
820
854
  for (const listener of phiBrandPreviewModeListeners)
821
855
  listener();
822
- }
856
+ return true;
857
+ },
823
858
  });
824
859
  return heard ?? initialMode;
825
860
  }
@@ -986,7 +1021,7 @@ export function PhiBuilderBrandThemeControlsWidgetClient({ runtime, config, colo
986
1021
  const colorControlWidth = clientToken.controlHeight * 5.5;
987
1022
  const themeKey = resolveThemeKey(config);
988
1023
  const { state, draftRef, publishDraft, pickerTransaction } = usePhiBrandThemeDraft(runtime, themeKey);
989
- const previewMode = usePhiBrandPreviewMode(resolveThemePayloadMode(state.draft));
1024
+ const previewMode = usePhiBrandPreviewMode(resolveThemePayloadMode(state.draft), config?.signalRoutes);
990
1025
  const loading = false;
991
1026
  const saving = false;
992
1027
  const [activeColorSection, changeActiveColorSection] = usePhiBrandAccordionSection(BRAND_THEME_COLOR_COLLAPSE_STORAGE_KEY, BRAND_THEME_COLOR_SECTION_KEYS);
@@ -1374,11 +1409,19 @@ const PHI_THEME_WORDMARK_WEIGHT_OPTIONS = [
1374
1409
  * from, which is a different job from authoring them.
1375
1410
  */
1376
1411
  export function PhiBuilderBrandIdentityControlsWidgetClient({ runtime, config, }) {
1377
- const { token: clientToken } = usePhiConfig();
1412
+ const { presets: themePresets, token: clientToken } = usePhiConfig();
1378
1413
  const themeBlocks = usePhiThemeBlockCatalog();
1379
1414
  const themeKey = resolveThemeKey(config);
1380
1415
  const { state, publishDraft } = usePhiBrandThemeDraft(runtime, themeKey);
1381
- const mode = usePhiBrandPreviewMode(resolveThemePayloadMode(state.draft));
1416
+ const mode = usePhiBrandPreviewMode(resolveThemePayloadMode(state.draft), config?.signalRoutes);
1417
+ /*
1418
+ * The ground the Logo of the mode being authored stands on: the draft's own container colour in that
1419
+ * mode, not a fixed black or white -- a Theme whose dark ground is navy shows its dark Logo on navy.
1420
+ */
1421
+ const logoGroundToken = useMemo(() => {
1422
+ const resolvedDraft = resolvePhiThemeRuntimePayload(state.draft, themeBlocks).theme;
1423
+ return resolveBrandDraftAliasTokens(resolvedDraft, resolveThemePayloadPreset(resolvedDraft, themePresets), mode);
1424
+ }, [mode, state.draft, themeBlocks, themePresets]);
1382
1425
  const [activeIdentitySection, changeActiveIdentitySection] = usePhiBrandAccordionSection(BRAND_THEME_IDENTITY_COLLAPSE_STORAGE_KEY, BRAND_THEME_IDENTITY_SECTION_KEYS);
1383
1426
  const brand = state.draft.brand ?? {};
1384
1427
  /*
@@ -1453,8 +1496,8 @@ export function PhiBuilderBrandIdentityControlsWidgetClient({ runtime, config, }
1453
1496
  height: 48,
1454
1497
  paddingInline: clientToken.paddingSM,
1455
1498
  borderRadius: clientToken.borderRadius,
1456
- border: `1px solid ${clientToken.colorBorderSecondary}`,
1457
- background: mode === "dark" ? "#141414" : "#ffffff",
1499
+ border: `1px solid ${readAliasTokenString(logoGroundToken, "colorBorderSecondary")}`,
1500
+ background: readAliasTokenString(logoGroundToken, "colorBgContainer"),
1458
1501
  }, children: logoPreviewUrl ? (_jsx("span", { style: {
1459
1502
  display: "block",
1460
1503
  width: "100%",
@@ -1463,7 +1506,7 @@ export function PhiBuilderBrandIdentityControlsWidgetClient({ runtime, config, }
1463
1506
  backgroundSize: "contain",
1464
1507
  backgroundRepeat: "no-repeat",
1465
1508
  backgroundPosition: "left center",
1466
- } })) : (_jsx(PhiTypographyControl, { type: "secondary", style: { color: mode === "dark" ? "rgba(255, 255, 255, 0.45)" : undefined }, children: "No Logo" })) }), _jsxs(PhiFlexControl, { align: "center", gap: clientToken.paddingXXS, style: { flexShrink: 0 }, children: [_jsx(PhiBrandBlockResetButton, { disabled: brand.logo?.[mode] == null, blockTitle: markSet.title, onReset: () => publishDraft(mergeThemeBrandLogo(state.draft, mode, undefined)) }), _jsx(PhiBrandCopyModeButton, { mode: mode, disabled: JSON.stringify(logo) === JSON.stringify(logos[otherMode] ?? null), onCopy: () => publishDraft(mergeThemeBrandLogo(state.draft, otherMode, logo ?? { sourceKind: "none" })) })] })] }), _jsx(PhiMediaPickerBinding, { config: {
1509
+ } })) : (_jsx(PhiTypographyControl, { type: "secondary", style: { color: readAliasTokenString(logoGroundToken, "colorTextTertiary") }, children: "No Logo" })) }), _jsxs(PhiFlexControl, { align: "center", gap: clientToken.paddingXXS, style: { flexShrink: 0 }, children: [_jsx(PhiBrandBlockResetButton, { disabled: brand.logo?.[mode] == null, blockTitle: markSet.title, onReset: () => publishDraft(mergeThemeBrandLogo(state.draft, mode, undefined)) }), _jsx(PhiBrandCopyModeButton, { mode: mode, disabled: JSON.stringify(logo) === JSON.stringify(logos[otherMode] ?? null), onCopy: () => publishDraft(mergeThemeBrandLogo(state.draft, otherMode, logo ?? { sourceKind: "none" })) })] })] }), _jsx(PhiMediaPickerBinding, { config: {
1467
1510
  mediaType: PhiMediaKind.Image,
1468
1511
  pageSize: 12,
1469
1512
  showPagination: true,
@@ -1545,7 +1588,7 @@ export function PhiBuilderBrandBackgroundControlsWidgetClient({ runtime, config,
1545
1588
  const themeBlocks = usePhiThemeBlockCatalog();
1546
1589
  const themeKey = resolveThemeKey(config);
1547
1590
  const { state, publishDraft, editTransaction } = usePhiBrandThemeDraft(runtime, themeKey);
1548
- const mode = usePhiBrandPreviewMode(resolveThemePayloadMode(state.draft));
1591
+ const mode = usePhiBrandPreviewMode(resolveThemePayloadMode(state.draft), config?.signalRoutes);
1549
1592
  const composition = resolvePhiThemeComposition(state.draft, themeBlocks);
1550
1593
  const [activeBackgroundSection, changeActiveBackgroundSection] = usePhiBrandAccordionSection(BRAND_THEME_BACKGROUND_COLLAPSE_STORAGE_KEY, BRAND_THEME_BACKGROUND_SECTION_KEYS);
1551
1594
  const modeLabel = mode === "dark" ? "Dark mode" : "Light mode";
@@ -1642,7 +1685,7 @@ function PhiBrandChromePreviewShell({ overlayStyle, paneShadows, rootBackgroundS
1642
1685
  overflow: "hidden",
1643
1686
  }, children: brand }), _jsxs("div", { "aria-hidden": true, style: { position: "absolute", inset: 0, fontSize: 11, color: labelColor, pointerEvents: "none" }, children: [_jsx("span", { style: { position: "absolute", left: 8, top: header + 8 }, children: "Sider" }), _jsx("span", { style: { position: "absolute", left: sider + 8, bottom: (footer - 14) / 2 }, children: "Footer" })] }), _jsx("div", { style: { display: "flex", flexDirection: "column", gap: padding, padding, minWidth: 0 }, children: children })] }));
1644
1687
  }
1645
- export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1688
+ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, config, }) {
1646
1689
  // The sample field is typed into like a real one, so what the Theme does to a filled field shows too.
1647
1690
  const [previewInput, setPreviewInput] = useState("");
1648
1691
  const { presets: themePresets, token: clientToken } = usePhiConfig();
@@ -1669,7 +1712,7 @@ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1669
1712
  emitThemeHydrateRequest(dispatchSignal, selfAddress);
1670
1713
  }
1671
1714
  }, [dispatchSignal, selfAddress]);
1672
- const mode = usePhiBrandPreviewMode(resolveThemePayloadMode(fallbackTheme));
1715
+ const mode = usePhiBrandPreviewMode(resolveThemePayloadMode(fallbackTheme), config?.signalRoutes);
1673
1716
  const previewPreset = resolveThemePayloadPreset(previewThemeResolved, themePresets);
1674
1717
  const previewFontStacks = usePhiThemeFontStacks(previewThemeResolved.fonts);
1675
1718
  const previewHeadingFontFamily = resolvePhiThemeHeadingFontFamily(previewThemeResolved.typography, {
@@ -1684,14 +1727,8 @@ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1684
1727
  */
1685
1728
  const previewBodyFontStack = previewFontStacks.body.stack;
1686
1729
  const previewMonoFontStack = previewFontStacks.mono.stack;
1687
- const previewEffectiveToken = useMemo(() => resolvePhiAntdAliasTokens(mode, {
1688
- ...buildPhiEffectiveNonColorThemeTokens(previewThemeResolved),
1689
- ...resolvePhiThemeColorTokens(previewPreset, previewThemeResolved.palette, mode),
1690
- ...(previewThemeResolved.style?.token ?? {}),
1691
- // The draft's lettering, applied as the root theme applies the Site's: body text and code.
1692
- ...(previewBodyFontStack ? { fontFamily: previewBodyFontStack } : {}),
1693
- ...(previewMonoFontStack ? { fontFamilyCode: previewMonoFontStack } : {}),
1694
- }), [mode, previewBodyFontStack, previewMonoFontStack, previewPreset, previewThemeResolved]);
1730
+ // The draft's lettering, applied as the root theme applies the Site's: body text and code.
1731
+ const previewEffectiveToken = useMemo(() => resolveBrandDraftAliasTokens(previewThemeResolved, previewPreset, mode, { body: previewBodyFontStack, mono: previewMonoFontStack }), [mode, previewBodyFontStack, previewMonoFontStack, previewPreset, previewThemeResolved]);
1695
1732
  const columns = [
1696
1733
  { title: "Name", key: "name", fieldPath: "name", sizing: { mode: "fill" } },
1697
1734
  { title: "Status", key: "status", fieldPath: "status", sizing: { mode: "content" }, render: (value) => _jsx(PhiTagControl, { color: "processing", children: String(value) }) },
@@ -1727,8 +1764,8 @@ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1727
1764
  previewShapedComponents: applyPhiSurfaceShapeComponentTokens(applyPhiControlShapeComponentTokens({ ...(applyPhiButtonShadowComponentTokens(previewThemeResolved.components, previewThemeResolved.buttons, mode) ?? {}) }, previewControlShape, previewEffectiveToken), previewControlShape, previewEffectiveToken),
1728
1765
  };
1729
1766
  }, [mode, previewEffectiveToken, previewThemeResolved]);
1730
- const previewCardBackground = readEffectiveTokenString(previewEffectiveToken, "colorBgContainer", mode === "dark" ? "#141414" : "#ffffff");
1731
- const previewSurfaceBackground = readEffectiveTokenString(previewEffectiveToken, "colorBgLayout", mode === "dark" ? "#000000" : "#f5f5f5");
1767
+ const previewCardBackground = readAliasTokenString(previewEffectiveToken, "colorBgContainer");
1768
+ const previewSurfaceBackground = readAliasTokenString(previewEffectiveToken, "colorBgLayout");
1732
1769
  /*
1733
1770
  * The Theme Root Background, on the surface the preview treats as the page ground -- the same layer
1734
1771
  * the Site paints behind everything, in the mode the preview switch is showing. A mode with no
@@ -1741,38 +1778,36 @@ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1741
1778
  * only one the preview draws.
1742
1779
  */
1743
1780
  const previewPaneShadows = resolvePhiShellChromePaneShadows(previewThemeResolved.root);
1744
- const previewTextColor = readEffectiveTokenString(previewEffectiveToken, "colorText", mode === "dark" ? "rgba(255,255,255,0.85)" : "rgba(0,0,0,0.88)");
1745
- const previewTextSecondaryColor = readEffectiveTokenString(previewEffectiveToken, "colorTextSecondary", mode === "dark" ? "rgba(255,255,255,0.65)" : "rgba(0,0,0,0.65)");
1746
- const previewTextTertiaryColor = readEffectiveTokenString(previewEffectiveToken, "colorTextTertiary", mode === "dark" ? "rgba(255,255,255,0.45)" : "rgba(0,0,0,0.45)");
1747
- const previewLinkColor = readEffectiveTokenString(previewEffectiveToken, "colorLink", readEffectiveTokenString(previewEffectiveToken, "colorPrimary", "#1677ff"));
1781
+ const previewTextColor = readAliasTokenString(previewEffectiveToken, "colorText");
1782
+ const previewTextSecondaryColor = readAliasTokenString(previewEffectiveToken, "colorTextSecondary");
1783
+ const previewTextTertiaryColor = readAliasTokenString(previewEffectiveToken, "colorTextTertiary");
1784
+ const previewLinkColor = readAliasTokenString(previewEffectiveToken, "colorLink");
1748
1785
  /*
1749
1786
  * What the sample swatch shows: the brand colour, so the hex beside it moves the moment the seed does.
1750
1787
  */
1751
- const previewSwatchColor = readEffectiveTokenString(previewEffectiveToken, "colorPrimary", "#1677ff");
1752
- const previewLinkHoverColor = readEffectiveTokenString(previewEffectiveToken, "colorLinkHover", previewLinkColor);
1753
- const previewLinkActiveColor = readEffectiveTokenString(previewEffectiveToken, "colorLinkActive", previewLinkColor);
1788
+ const previewSwatchColor = readAliasTokenString(previewEffectiveToken, "colorPrimary");
1789
+ const previewLinkHoverColor = readAliasTokenString(previewEffectiveToken, "colorLinkHover");
1790
+ const previewLinkActiveColor = readAliasTokenString(previewEffectiveToken, "colorLinkActive");
1754
1791
  /*
1755
1792
  * Four status colours, one shape: text, ground and border, each with its hover. Info's border falls
1756
1793
  * back to the link colour where the others fall back to their own base, which is how it always was.
1757
1794
  */
1758
1795
  const statusPreviewItems = [
1759
- { key: "info", label: "Info", prefix: "colorInfo", base: "#1677ff", hover: "#4096ff", borderFallback: previewLinkColor },
1760
- { key: "success", label: "Success", prefix: "colorSuccess", base: "#52c41a", hover: "#73d13d" },
1761
- { key: "warning", label: "Warning", prefix: "colorWarning", base: "#faad14", hover: "#ffc53d" },
1762
- { key: "error", label: "Error", prefix: "colorError", base: "#ff4d4f", hover: "#ff7875" },
1763
- ].map(({ key, label, prefix, base, hover, ...item }) => {
1764
- const read = (suffix, fallback) => readEffectiveTokenString(previewEffectiveToken, `${prefix}${suffix}`, fallback);
1765
- const baseColor = read("", base);
1766
- const hoverColor = read("Hover", hover);
1796
+ { key: "info", label: "Info", prefix: "colorInfo" },
1797
+ { key: "success", label: "Success", prefix: "colorSuccess" },
1798
+ { key: "warning", label: "Warning", prefix: "colorWarning" },
1799
+ { key: "error", label: "Error", prefix: "colorError" },
1800
+ ].map(({ key, label, prefix }) => {
1801
+ const read = (suffix) => readAliasTokenString(previewEffectiveToken, `${prefix}${suffix}`);
1767
1802
  return {
1768
1803
  key,
1769
1804
  label,
1770
- color: read("Text", baseColor),
1771
- background: read("Bg", previewCardBackground),
1772
- border: read("Border", "borderFallback" in item ? item.borderFallback : baseColor),
1773
- hoverColor: read("TextHover", hoverColor),
1774
- hoverBackground: read("BgHover", previewCardBackground),
1775
- hoverBorder: read("BorderHover", hoverColor),
1805
+ color: read("Text"),
1806
+ background: read("Bg"),
1807
+ border: read("Border"),
1808
+ hoverColor: read("TextHover"),
1809
+ hoverBackground: read("BgHover"),
1810
+ hoverBorder: read("BorderHover"),
1776
1811
  };
1777
1812
  });
1778
1813
  const fontPreviewItems = [
@@ -1816,34 +1851,34 @@ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1816
1851
  {
1817
1852
  key: "sm",
1818
1853
  label: "Small",
1819
- value: readEffectiveTokenNumber(previewEffectiveToken, "borderRadiusSM", PHI_RADII.xs),
1854
+ value: readAliasTokenNumber(previewEffectiveToken, "borderRadiusSM"),
1820
1855
  },
1821
1856
  {
1822
1857
  key: "base",
1823
1858
  label: "Base",
1824
- value: readEffectiveTokenNumber(previewEffectiveToken, "borderRadius", PHI_RADII.sm),
1859
+ value: readAliasTokenNumber(previewEffectiveToken, "borderRadius"),
1825
1860
  },
1826
1861
  {
1827
1862
  key: "lg",
1828
1863
  label: "Large",
1829
- value: readEffectiveTokenNumber(previewEffectiveToken, "borderRadiusLG", PHI_RADII.base),
1864
+ value: readAliasTokenNumber(previewEffectiveToken, "borderRadiusLG"),
1830
1865
  },
1831
1866
  ];
1832
1867
  const controlHeightPreviewItems = [
1833
1868
  {
1834
1869
  key: "sm",
1835
1870
  label: "Small",
1836
- value: readEffectiveTokenNumber(previewEffectiveToken, "controlHeightSM", PHI_CONTROL_HEIGHTS.sm),
1871
+ value: readAliasTokenNumber(previewEffectiveToken, "controlHeightSM"),
1837
1872
  },
1838
1873
  {
1839
1874
  key: "base",
1840
1875
  label: "Base",
1841
- value: readEffectiveTokenNumber(previewEffectiveToken, "controlHeight", PHI_CONTROL_HEIGHTS.md),
1876
+ value: readAliasTokenNumber(previewEffectiveToken, "controlHeight"),
1842
1877
  },
1843
1878
  {
1844
1879
  key: "lg",
1845
1880
  label: "Large",
1846
- value: readEffectiveTokenNumber(previewEffectiveToken, "controlHeightLG", PHI_CONTROL_HEIGHTS.lg),
1881
+ value: readAliasTokenNumber(previewEffectiveToken, "controlHeightLG"),
1847
1882
  },
1848
1883
  ];
1849
1884
  const wireframeEnabled = readEffectiveTokenBoolean(previewEffectiveToken, "wireframe", true);
@@ -1856,7 +1891,7 @@ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1856
1891
  * variable is inherited, and the Builder's own Root carries the published Theme's.
1857
1892
  */
1858
1893
  ...{
1859
- [PHI_THEME_HEADING_FONT_VARIABLE]: previewHeadingFontFamily ?? readEffectiveTokenString(previewEffectiveToken, "fontFamily", clientToken.fontFamily),
1894
+ [PHI_THEME_HEADING_FONT_VARIABLE]: previewHeadingFontFamily ?? readAliasTokenString(previewEffectiveToken, "fontFamily"),
1860
1895
  },
1861
1896
  /*
1862
1897
  * Small and large Control radii are inherited custom properties, so the preview declares its
@@ -1888,15 +1923,15 @@ export function PhiBuilderBrandThemePreviewWidgetClient({ runtime, }) {
1888
1923
  minWidth: 0,
1889
1924
  }, children: fontPreviewItems.map((item) => (_jsxs("div", { style: {
1890
1925
  minWidth: 0,
1891
- border: `1px solid ${readEffectiveTokenString(previewEffectiveToken, "colorBorderSecondary", "rgba(0,0,0,0.06)")}`,
1892
- borderRadius: `${readEffectiveTokenNumber(previewEffectiveToken, "borderRadius", PHI_RADII.sm)}px`,
1926
+ border: `1px solid ${readAliasTokenString(previewEffectiveToken, "colorBorderSecondary")}`,
1927
+ borderRadius: `${readAliasTokenNumber(previewEffectiveToken, "borderRadius")}px`,
1893
1928
  background: previewCardBackground,
1894
1929
  padding: clientToken.paddingXS,
1895
1930
  }, children: [_jsx(PhiTypographyControl, { type: "secondary", style: { display: "block" }, children: item.label }), _jsx(PhiTypographyControl, { style: { display: "block", color: previewTextColor, fontFamily: item.family }, children: item.sample }), item.value ? (_jsx(PhiTypographyControl, { type: "secondary", style: { display: "block", fontFamily: item.family }, children: item.value })) : null] }, item.key))) })] }), _jsx(PhiFlexControl, { gap: clientToken.padding, wrap: "wrap", children: _jsxs(PhiFlexControl, { vertical: true, gap: clientToken.paddingSM, style: { flex: "1 1 260px", minWidth: 0 }, children: [_jsx(PhiTypographyControl, { presentation: "title", level: 5, style: { margin: 0, color: previewTextColor }, children: "Border Radius" }), _jsx(PhiFlexControl, { gap: clientToken.paddingXS, wrap: "wrap", children: radiusPreviewItems.map((item) => (_jsxs("div", { style: {
1896
1931
  // The tokens are numbers; `calc(40 * 2)` is no length, and the sample lost its size.
1897
1932
  width: clientToken.controlHeightLG * 2,
1898
1933
  minHeight: clientToken.controlHeight * 1.25,
1899
- border: `1px solid ${readEffectiveTokenString(previewEffectiveToken, "colorBorder", "rgba(0,0,0,0.15)")}`,
1934
+ border: `1px solid ${readAliasTokenString(previewEffectiveToken, "colorBorder")}`,
1900
1935
  borderRadius: item.value,
1901
1936
  background: previewCardBackground,
1902
1937
  padding: clientToken.paddingXS,
@@ -1,6 +1,7 @@
1
1
  import type { PhiCmsWidgetPlugin } from "../../../../../types";
2
2
  import { type PhiCmsAreaKey } from "../../../../../constants/cms-areas";
3
- export type PhiBuilderBrandWidgetConfig = {
3
+ import { type PhiControlSignalConfig } from "../../../../../components/widgets/config/control-signal-config";
4
+ export type PhiBuilderBrandWidgetConfig = Pick<PhiControlSignalConfig, "key" | "signalRoutes"> & {
4
5
  themeKey?: string;
5
6
  reviewArea?: PhiCmsAreaKey;
6
7
  };
@@ -4,13 +4,32 @@ import { PHI_AUTHORING_OPTION_PROVIDER_KEYS } from "../../../../../constants/aut
4
4
  import { PHI_THEME_SIGNAL_CHANNELS } from "../../../../../plugins/runtime-modules/theme/controller/signals";
5
5
  import { createPhiCmsWidgetDefinition } from "../../../../../components/widgets/config/helpers";
6
6
  import { readString } from "../../../../../components/widgets/config/parser-primitives";
7
+ import { parsePhiControlSignalConfig, } from "../../../../../components/widgets/config/control-signal-config";
7
8
  function parseBuilderBrandWidgetConfig(config) {
8
9
  const reviewArea = readString(config.reviewArea);
9
10
  return {
11
+ /*
12
+ * The routes are read like any Widget's: the preview mode reaches a panel through the route its tree
13
+ * wrote, so a route an author adds in the Builder works as well. The parser dropped them once and
14
+ * the panels listened to a hard-coded broadcast, which left the declared input decoration.
15
+ */
16
+ ...parsePhiControlSignalConfig(config, { key: "brandPreviewThemeMode" }),
10
17
  themeKey: readString(config.themeKey),
11
18
  reviewArea: isPhiCmsAreaKey(reviewArea) ? reviewArea : undefined,
12
19
  };
13
20
  }
21
+ /** Every panel that draws in the preview's mode follows the mode switch. */
22
+ const PHI_BUILDER_BRAND_PREVIEW_MODE_SIGNALS = {
23
+ emits: [],
24
+ listens: [
25
+ {
26
+ id: "previewThemeMode",
27
+ channel: PHI_THEME_SIGNAL_CHANNELS.previewThemeMode,
28
+ action: "change",
29
+ valueType: "boolean",
30
+ },
31
+ ],
32
+ };
14
33
  export const PHI_BUILDER_BRAND_THEME_CONTROLS_WIDGET_DEFINITION = createPhiCmsWidgetDefinition({
15
34
  typeKey: "builder-brand-theme-controls",
16
35
  title: "Builder Brand Theme Controls",
@@ -18,6 +37,7 @@ export const PHI_BUILDER_BRAND_THEME_CONTROLS_WIDGET_DEFINITION = createPhiCmsWi
18
37
  category: "configuration",
19
38
  iconFamily: "theme",
20
39
  slotSizePolicy: "fill-inline",
40
+ runtimeSignals: PHI_BUILDER_BRAND_PREVIEW_MODE_SIGNALS,
21
41
  fields: [
22
42
  { key: "themeKey", type: "string", label: "Theme Key" },
23
43
  { key: "reviewArea", type: "string", label: "Review Area" },
@@ -41,6 +61,7 @@ export const PHI_BUILDER_BRAND_IDENTITY_CONTROLS_WIDGET_DEFINITION = createPhiCm
41
61
  PHI_MEDIA_LIBRARY_DATA_PROVIDER_KEYS.collection,
42
62
  PHI_AUTHORING_OPTION_PROVIDER_KEYS.pages,
43
63
  ],
64
+ runtimeSignals: PHI_BUILDER_BRAND_PREVIEW_MODE_SIGNALS,
44
65
  fields: [
45
66
  { key: "themeKey", type: "string", label: "Theme Key" },
46
67
  { key: "reviewArea", type: "string", label: "Review Area" },
@@ -76,17 +97,7 @@ export const PHI_BUILDER_BRAND_BACKGROUND_CONTROLS_WIDGET_DEFINITION = createPhi
76
97
  * library, on a Page where the Assets Module was active the whole time.
77
98
  */
78
99
  requiredDataProviders: [PHI_MEDIA_LIBRARY_DATA_PROVIDER_KEYS.collection],
79
- runtimeSignals: {
80
- emits: [],
81
- listens: [
82
- {
83
- id: "previewThemeMode",
84
- channel: PHI_THEME_SIGNAL_CHANNELS.previewThemeMode,
85
- action: "change",
86
- valueType: "boolean",
87
- },
88
- ],
89
- },
100
+ runtimeSignals: PHI_BUILDER_BRAND_PREVIEW_MODE_SIGNALS,
90
101
  fields: [
91
102
  { key: "themeKey", type: "string", label: "Theme Key" },
92
103
  { key: "reviewArea", type: "string", label: "Review Area" },
@@ -100,17 +111,7 @@ export const PHI_BUILDER_BRAND_THEME_PREVIEW_WIDGET_DEFINITION = createPhiCmsWid
100
111
  category: "configuration",
101
112
  iconFamily: "theme",
102
113
  slotSizePolicy: "fill-inline",
103
- runtimeSignals: {
104
- emits: [],
105
- listens: [
106
- {
107
- id: "previewThemeMode",
108
- channel: PHI_THEME_SIGNAL_CHANNELS.previewThemeMode,
109
- action: "change",
110
- valueType: "boolean",
111
- },
112
- ],
113
- },
114
+ runtimeSignals: PHI_BUILDER_BRAND_PREVIEW_MODE_SIGNALS,
114
115
  fields: [
115
116
  { key: "themeKey", type: "string", label: "Theme Key" },
116
117
  { key: "reviewArea", type: "string", label: "Review Area" },
@@ -11,7 +11,7 @@ export const PHI_BUILDER_BRAND_THEME_CONTROLS_WIDGET_PLUGIN = {
11
11
  };
12
12
  export const PHI_BUILDER_BRAND_THEME_PREVIEW_WIDGET_PLUGIN = {
13
13
  ...PHI_BUILDER_BRAND_THEME_PREVIEW_WIDGET_DEFINITION,
14
- render: ({ runtime }) => _jsx(PhiBuilderBrandThemePreviewWidgetClient, { runtime: runtime }),
14
+ render: ({ runtime, config }) => _jsx(PhiBuilderBrandThemePreviewWidgetClient, { runtime: runtime, config: config }),
15
15
  renderPreview: ({ runtime }) => _jsx(PhiBuilderBrandThemePreviewWidgetClient, { runtime: runtime }),
16
16
  };
17
17
  export const PHI_BUILDER_BRAND_STYLE_CONTROLS_WIDGET_PLUGIN = {
@@ -1,4 +1,4 @@
1
- import { PHI_CORE_RUNTIME_MODULE_THEMES } from "./area-base-presets";
1
+ import { PHI_CORE_RUNTIME_MODULE_THEMES } from "./core/themes";
2
2
  import { PHI_CORE_RUNTIME_MODULE_ID } from "./core/ids";
3
3
  import { readAllPhiSiteModuleServerAreaContributions } from "./site-module-contributions";
4
4
  import { PHI_THEME_RUNTIME_MODULE_BLOCKS } from "./theme/block-descriptors";
@@ -77,6 +77,7 @@ export declare const PHI_USER_MANAGEMENT_RUNTIME_DATA_PROVIDER_DESCRIPTORS: {
77
77
  filterFields: string[];
78
78
  sorting: "single";
79
79
  pagination: "offset";
80
+ total: true;
80
81
  };
81
82
  actions: ({
82
83
  key: string;
@@ -149,6 +150,7 @@ export declare const PHI_USER_MANAGEMENT_RUNTIME_DATA_PROVIDER_DESCRIPTORS: {
149
150
  sorting: "none";
150
151
  pagination: "none";
151
152
  search?: undefined;
153
+ total?: undefined;
152
154
  };
153
155
  recordRead?: undefined;
154
156
  summaryFields?: undefined;
@@ -47,6 +47,7 @@ export const PHI_USER_MANAGEMENT_RUNTIME_DATA_PROVIDER_DESCRIPTORS = [
47
47
  filterFields: ["accountType", "enabled"],
48
48
  sorting: "single",
49
49
  pagination: "offset",
50
+ total: true,
50
51
  },
51
52
  actions: [
52
53
  {
@@ -105,6 +105,7 @@ export declare const PHI_USER_MANAGEMENT_RUNTIME_MODULE_DEFINITION: {
105
105
  filterFields: string[];
106
106
  sorting: "single";
107
107
  pagination: "offset";
108
+ total: true;
108
109
  };
109
110
  actions: ({
110
111
  key: string;
@@ -177,6 +178,7 @@ export declare const PHI_USER_MANAGEMENT_RUNTIME_MODULE_DEFINITION: {
177
178
  sorting: "none";
178
179
  pagination: "none";
179
180
  search?: undefined;
181
+ total?: undefined;
180
182
  };
181
183
  recordRead?: undefined;
182
184
  summaryFields?: undefined;
@@ -34,7 +34,7 @@
34
34
  .ant-picker-small.ant-picker-small:not(:where(.ant-picker-underlined)),
35
35
  .ant-segmented.ant-segmented-sm.ant-segmented-sm,
36
36
  .ant-color-picker-trigger.ant-color-picker-sm.ant-color-picker-sm {
37
- border-radius: var(--phi-control-radius-sm, var(--ant-border-radius-sm));
37
+ border-radius: var(--phi-control-radius-sm);
38
38
  }
39
39
 
40
40
  .ant-btn-lg.ant-btn-lg,
@@ -45,7 +45,7 @@
45
45
  .ant-picker-large.ant-picker-large:not(:where(.ant-picker-underlined)),
46
46
  .ant-segmented.ant-segmented-lg.ant-segmented-lg,
47
47
  .ant-color-picker-trigger.ant-color-picker-lg.ant-color-picker-lg {
48
- border-radius: var(--phi-control-radius-lg, var(--ant-border-radius-lg));
48
+ border-radius: var(--phi-control-radius-lg);
49
49
  }
50
50
 
51
51
  /*
@@ -56,17 +56,17 @@
56
56
  */
57
57
  .ant-segmented.ant-segmented .ant-segmented-item.ant-segmented-item,
58
58
  .ant-segmented.ant-segmented .ant-segmented-thumb.ant-segmented-thumb {
59
- border-radius: var(--phi-control-radius-inner-md, var(--ant-border-radius-sm));
59
+ border-radius: var(--phi-control-radius-inner-md);
60
60
  }
61
61
 
62
62
  .ant-segmented.ant-segmented-sm .ant-segmented-item.ant-segmented-item,
63
63
  .ant-segmented.ant-segmented-sm .ant-segmented-thumb.ant-segmented-thumb {
64
- border-radius: var(--phi-control-radius-inner-sm, var(--ant-border-radius-xs));
64
+ border-radius: var(--phi-control-radius-inner-sm);
65
65
  }
66
66
 
67
67
  .ant-segmented.ant-segmented-lg .ant-segmented-item.ant-segmented-item,
68
68
  .ant-segmented.ant-segmented-lg .ant-segmented-thumb.ant-segmented-thumb {
69
- border-radius: var(--phi-control-radius-inner-lg, var(--ant-border-radius));
69
+ border-radius: var(--phi-control-radius-inner-lg);
70
70
  }
71
71
 
72
72
  /*
@@ -90,15 +90,15 @@
90
90
  */
91
91
  .ant-color-picker-trigger.ant-color-picker-trigger .ant-color-picker-color-block.ant-color-picker-color-block {
92
92
  margin-inline-start: 2px;
93
- border-radius: var(--phi-control-radius-inner-md, var(--ant-border-radius-sm));
93
+ border-radius: var(--phi-control-radius-inner-md);
94
94
  }
95
95
 
96
96
  .ant-color-picker-trigger.ant-color-picker-sm .ant-color-picker-color-block.ant-color-picker-color-block {
97
- border-radius: var(--phi-control-radius-inner-sm, var(--ant-border-radius-xs));
97
+ border-radius: var(--phi-control-radius-inner-sm);
98
98
  }
99
99
 
100
100
  .ant-color-picker-trigger.ant-color-picker-lg .ant-color-picker-color-block.ant-color-picker-color-block {
101
- border-radius: var(--phi-control-radius-inner-lg, var(--ant-border-radius));
101
+ border-radius: var(--phi-control-radius-inner-lg);
102
102
  }
103
103
 
104
104
  /*
@@ -127,21 +127,21 @@ textarea.ant-input.ant-input:not(:where(.ant-input-sm, .ant-input-lg, .ant-input
127
127
  .ant-input-textarea-affix-wrapper.ant-input-textarea-affix-wrapper:not(:where(.ant-input-affix-wrapper-sm, .ant-input-affix-wrapper-lg, .ant-input-underlined)),
128
128
  .ant-select-multiple.ant-select-multiple:not(:where(.ant-select-sm, .ant-select-lg, .ant-select-underlined)),
129
129
  .ant-mentions.ant-mentions:not(:where(.ant-mentions-sm, .ant-mentions-lg, .ant-mentions-underlined)) {
130
- border-radius: var(--phi-control-radius-grown-md, var(--ant-border-radius));
130
+ border-radius: var(--phi-control-radius-grown-md);
131
131
  }
132
132
 
133
133
  textarea.ant-input-sm.ant-input-sm:not(:where(.ant-input-underlined, .ant-input-affix-wrapper > textarea)),
134
134
  .ant-input-textarea-affix-wrapper.ant-input-affix-wrapper-sm.ant-input-affix-wrapper-sm:not(:where(.ant-input-underlined)),
135
135
  .ant-select-multiple.ant-select-sm.ant-select-sm:not(:where(.ant-select-underlined)),
136
136
  .ant-mentions-sm.ant-mentions-sm:not(:where(.ant-mentions-underlined)) {
137
- border-radius: var(--phi-control-radius-grown-sm, var(--ant-border-radius-sm));
137
+ border-radius: var(--phi-control-radius-grown-sm);
138
138
  }
139
139
 
140
140
  textarea.ant-input-lg.ant-input-lg:not(:where(.ant-input-underlined, .ant-input-affix-wrapper > textarea)),
141
141
  .ant-input-textarea-affix-wrapper.ant-input-affix-wrapper-lg.ant-input-affix-wrapper-lg:not(:where(.ant-input-underlined)),
142
142
  .ant-select-multiple.ant-select-lg.ant-select-lg:not(:where(.ant-select-underlined)),
143
143
  .ant-mentions-lg.ant-mentions-lg:not(:where(.ant-mentions-underlined)) {
144
- border-radius: var(--phi-control-radius-grown-lg, var(--ant-border-radius-lg));
144
+ border-radius: var(--phi-control-radius-grown-lg);
145
145
  }
146
146
 
147
147
  /*
@@ -313,7 +313,7 @@ h5.phi-typography, .phi-typography h5 {
313
313
  * is the Theme's surface step; everything else is the token variable the primitive read.
314
314
  */
315
315
  .phi-card-control {
316
- --phi-card-control-radius: var(--phi-surface-radius, var(--ant-border-radius-lg));
316
+ --phi-card-control-radius: var(--phi-surface-radius);
317
317
  --phi-card-control-line: var(--ant-line-width) var(--ant-line-type) var(--ant-color-border-secondary);
318
318
  position: relative;
319
319
  box-sizing: border-box;
@@ -506,8 +506,8 @@ h5.phi-typography, .phi-typography h5 {
506
506
  }
507
507
 
508
508
  .phi-table-control.phi-table-control--closing-block [class~="ant-table"] {
509
- border-end-start-radius: var(--phi-surface-radius, var(--ant-border-radius-lg));
510
- border-end-end-radius: var(--phi-surface-radius, var(--ant-border-radius-lg));
509
+ border-end-start-radius: var(--phi-surface-radius);
510
+ border-end-end-radius: var(--phi-surface-radius);
511
511
  /* `clip`, not `hidden`, so the corners are cut without making this the sticky header's scroller. */
512
512
  overflow: clip;
513
513
  }
package/styles/layout.css CHANGED
@@ -561,6 +561,11 @@
561
561
  /*
562
562
  * Hover effects: a card answers the pointer, and only a pointer that hovers.
563
563
  * Keyboard focus gets the same answer, so the effect never says something a keyboard reader misses.
564
+ *
565
+ * Lift raises the card and gives it the Theme's next shadow up. The resting shadow is the Surface's,
566
+ * written on the card itself, so the raised one has to be `!important` to stand over it; a card whose
567
+ * Surface has no shadow gets one when it lifts, which is what lifting means. Two pixels and the same
568
+ * shadow read as nothing at all; zoom at 4 % did not read either.
564
569
  */
565
570
  :where(.phi-card--hover-lift, .phi-card--hover-zoom) {
566
571
  transition: translate 200ms ease, box-shadow 200ms ease;
@@ -573,25 +578,29 @@
573
578
 
574
579
  @media (hover: hover) {
575
580
  :where(.phi-card--hover-lift):hover {
576
- translate: 0 -2px;
581
+ translate: 0 -4px;
582
+ box-shadow: var(--ant-box-shadow-secondary) !important;
577
583
  }
578
584
 
579
585
  :where(.phi-card--hover-zoom):hover :where(.phi-card__ground, .phi-card__media img) {
580
- scale: 1.04;
586
+ scale: 1.08;
581
587
  }
582
588
  }
583
589
 
584
590
  :where(.phi-card--hover-lift):focus-within {
585
- translate: 0 -2px;
591
+ translate: 0 -4px;
592
+ box-shadow: var(--ant-box-shadow-secondary) !important;
586
593
  }
587
594
 
588
595
  :where(.phi-card--hover-zoom):focus-within :where(.phi-card__ground, .phi-card__media img) {
589
- scale: 1.04;
596
+ scale: 1.08;
590
597
  }
591
598
 
592
599
  /*
593
600
  * The icon paints the colours the card hands it as custom properties, so that the `icon` effect can turn
594
- * them round: the colour becomes the ground and the ground the colour. A change of colour, not a
601
+ * them round: the colour becomes the ground, and the mark takes `--phi-card-icon-hover-color` -- the
602
+ * stated ground where one was stated, the container's otherwise. Not simply the ground: the Theme's
603
+ * ground for a mark is a fill a few percent opaque, and a mark painted in it vanished. A change of colour, not a
595
604
  * movement, so it is not taken back for a reader who asked for less motion -- only its easing is.
596
605
  */
597
606
  :where(.phi-card__icon) {
@@ -605,13 +614,13 @@
605
614
 
606
615
  @media (hover: hover) {
607
616
  :where(.phi-card--hover-icon):hover :where(.phi-card__icon) {
608
- color: var(--phi-card-icon-background);
617
+ color: var(--phi-card-icon-hover-color);
609
618
  background: var(--phi-card-icon-color);
610
619
  }
611
620
  }
612
621
 
613
622
  :where(.phi-card--hover-icon):focus-within :where(.phi-card__icon) {
614
- color: var(--phi-card-icon-background);
623
+ color: var(--phi-card-icon-hover-color);
615
624
  background: var(--phi-card-icon-color);
616
625
  }
617
626