@phis/ui 0.4.3 → 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 (132) hide show
  1. package/components/controls/phi-anchor-nav-control.js +4 -1
  2. package/components/controls/phi-background-control.js +21 -6
  3. package/components/controls/phi-bullet-list-control.d.ts +7 -2
  4. package/components/controls/phi-bullet-list-control.js +4 -3
  5. package/components/controls/phi-color-control.js +4 -2
  6. package/components/controls/phi-drawer-control-adapter.js +3 -2
  7. package/components/controls/phi-inline-text-editor.js +7 -1
  8. package/components/controls/phi-length-control.js +1 -1
  9. package/components/controls/phi-ribbon-control.d.ts +13 -4
  10. package/components/controls/phi-ribbon-control.js +10 -6
  11. package/components/controls/phi-ribbon-wrap-control.d.ts +26 -0
  12. package/components/controls/phi-ribbon-wrap-control.js +25 -0
  13. package/components/controls/phi-select-control.js +5 -2
  14. package/components/controls/phi-series-chart-control.d.ts +48 -0
  15. package/components/controls/phi-series-chart-control.js +82 -0
  16. package/components/controls/phi-text-control.js +57 -3
  17. package/components/controls/phi-tree-control.js +1 -1
  18. package/components/controls/phi-truncated-hover-text.d.ts +15 -0
  19. package/components/controls/phi-truncated-hover-text.js +25 -0
  20. package/components/forms/link-target-form-control.d.ts +1 -1
  21. package/components/forms/link-target-form-control.js +2 -45
  22. package/components/forms/phi-form-widget-frame.js +4 -2
  23. package/components/layouts/clients/phi-three-column-layout-client.js +10 -1
  24. package/components/navigation/phi-link.js +6 -1
  25. package/components/regions/clients/cms-region-container-client.js +6 -1
  26. package/components/regions/phi-cms-region-container.js +3 -0
  27. package/components/regions/phi-cms-region-shell.d.ts +12 -1
  28. package/components/regions/phi-cms-region-shell.js +81 -19
  29. package/components/root/phi-config-provider.d.ts +13 -0
  30. package/components/root/phi-config-provider.js +12 -1
  31. package/components/root/phi-root-background.d.ts +7 -0
  32. package/components/root/phi-root-background.js +20 -1
  33. package/components/root/phi-root-theme-resolver.js +3 -0
  34. package/components/root/phi-shell-chrome-overlay.d.ts +12 -1
  35. package/components/root/phi-shell-chrome-overlay.js +19 -3
  36. package/components/shell/phi-antd-icon.d.ts +1 -0
  37. package/components/shell/phi-antd-icon.js +3 -0
  38. package/components/shell/use-phi-shell-sticky-top.js +61 -16
  39. package/components/surface/phi-surface-tone.d.ts +13 -0
  40. package/components/surface/phi-surface-tone.js +21 -0
  41. package/components/widgets/client/bullet-list-entries-editor.js +7 -1
  42. package/components/widgets/client/html-editor.js +1 -1
  43. package/components/widgets/client/shared/use-page-reference-options.d.ts +17 -0
  44. package/components/widgets/client/shared/use-page-reference-options.js +57 -0
  45. package/components/widgets/config/background.d.ts +32 -1
  46. package/components/widgets/config/background.js +41 -2
  47. package/components/widgets/label-sets/background.js +2 -0
  48. package/components/widgets/label-types/background.d.ts +1 -0
  49. package/components/widgets/label-types/background.js +1 -0
  50. package/components/widgets/shared/bullet-list-vocabulary.d.ts +10 -0
  51. package/components/widgets/shared/bullet-list-vocabulary.js +5 -2
  52. package/components/widgets/shared/card-body-client.d.ts +5 -3
  53. package/components/widgets/shared/card-body-client.js +49 -6
  54. package/components/widgets/shared/card-vocabulary.d.ts +12 -2
  55. package/components/widgets/shared/card-vocabulary.js +7 -0
  56. package/components/widgets/shared/markdown-body-client.js +39 -10
  57. package/helpers/cms-container-chrome.js +6 -1
  58. package/helpers/locale.d.ts +8 -0
  59. package/helpers/locale.js +18 -0
  60. package/helpers/shell-region-style.js +2 -1
  61. package/helpers/surface-style.d.ts +12 -1
  62. package/helpers/surface-style.js +28 -2
  63. package/module-dashboard-cards.d.ts +1 -1
  64. package/module-dashboard-cards.js +1 -1
  65. package/package.json +1 -1
  66. package/plugins/runtime-modules/area-definitions.d.ts +0 -42
  67. package/plugins/runtime-modules/area-definitions.js +3 -8
  68. package/plugins/runtime-modules/builder/clients/inspector-config-field.js +20 -1
  69. package/plugins/runtime-modules/builder/clients/layout-scaffold-overlays.js +10 -5
  70. package/plugins/runtime-modules/builder/edit-scaffold-drawer.js +3 -2
  71. package/plugins/runtime-modules/builder/render-root-node-scaffold.js +25 -15
  72. package/plugins/runtime-modules/builder/trees/phi-default-builder-area-preset-tree.js +4 -0
  73. package/plugins/runtime-modules/builder/widgets/structure-region/built-in.js +15 -4
  74. package/plugins/runtime-modules/client-authoring-module.d.ts +8 -1
  75. package/plugins/runtime-modules/client-authoring-module.js +13 -3
  76. package/plugins/runtime-modules/core/widgets/brand/client.d.ts +12 -3
  77. package/plugins/runtime-modules/core/widgets/brand/client.js +3 -11
  78. package/plugins/runtime-modules/core/widgets/brand/home.d.ts +15 -0
  79. package/plugins/runtime-modules/core/widgets/brand/home.js +18 -0
  80. package/plugins/runtime-modules/core/widgets/brand/plugin.js +3 -2
  81. package/plugins/runtime-modules/core/widgets/brand/server.d.ts +2 -2
  82. package/plugins/runtime-modules/core/widgets/brand/server.js +2 -2
  83. package/plugins/runtime-modules/core/widgets/card/config.d.ts +6 -1
  84. package/plugins/runtime-modules/core/widgets/card/config.js +19 -3
  85. package/plugins/runtime-modules/core/widgets/card/editor.js +13 -3
  86. package/plugins/runtime-modules/core/widgets/card/server.js +1 -0
  87. package/plugins/runtime-modules/core/widgets/description/client.js +3 -3
  88. package/plugins/runtime-modules/core/widgets/description/config.d.ts +1 -0
  89. package/plugins/runtime-modules/core/widgets/description/editor.js +3 -2
  90. package/plugins/runtime-modules/core/widgets/description/server.js +3 -2
  91. package/plugins/runtime-modules/core/widgets/entry-list/config.d.ts +1 -0
  92. package/plugins/runtime-modules/core/widgets/gallery/config.d.ts +1 -0
  93. package/plugins/runtime-modules/core/widgets/header-navigation/client.js +2 -2
  94. package/plugins/runtime-modules/core/widgets/html/client.js +1 -1
  95. package/plugins/runtime-modules/core/widgets/markdown/config.d.ts +320 -2
  96. package/plugins/runtime-modules/core/widgets/markdown/config.js +18 -4
  97. package/plugins/runtime-modules/core/widgets/markdown/editor.js +9 -1
  98. package/plugins/runtime-modules/core/widgets/markdown-toc/client.js +6 -1
  99. package/plugins/runtime-modules/core/widgets/markdown-toc/config.d.ts +14 -0
  100. package/plugins/runtime-modules/core/widgets/markdown-toc/config.js +14 -2
  101. package/plugins/runtime-modules/core/widgets/quick-links/authoring.js +7 -2
  102. package/plugins/runtime-modules/core/widgets/quick-links/client.js +2 -2
  103. package/plugins/runtime-modules/core/widgets/quick-links/items.d.ts +0 -2
  104. package/plugins/runtime-modules/core/widgets/quick-links/items.js +0 -15
  105. package/plugins/runtime-modules/core/widgets/result/config.d.ts +1 -0
  106. package/plugins/runtime-modules/core/widgets/sidebar-navigation/authoring.js +1 -1
  107. package/plugins/runtime-modules/core/widgets/sidebar-navigation/client.js +1 -1
  108. package/plugins/runtime-modules/core/widgets/simple-text/client.js +8 -3
  109. package/plugins/runtime-modules/core/widgets/simple-text/config.d.ts +1 -0
  110. package/plugins/runtime-modules/core/widgets/simple-text/editor.js +2 -2
  111. package/plugins/runtime-modules/core/widgets/table/config.d.ts +3 -0
  112. package/plugins/runtime-modules/dashboard/card-rows.d.ts +3 -1
  113. package/plugins/runtime-modules/dashboard/card-rows.js +30 -2
  114. package/plugins/runtime-modules/dashboard/clients/dashboard-card-view.js +29 -7
  115. package/plugins/runtime-modules/dashboard/trees/phi-default-builder-dashboard-page-tree.js +5 -40
  116. package/plugins/runtime-modules/theme/widgets/brand-controls/client.js +19 -15
  117. package/plugins/runtime-modules/theme/widgets/brand-controls/config.js +5 -9
  118. package/server-helpers/cms-link-targets.js +6 -0
  119. package/styles/controls.css +64 -2
  120. package/styles/layout.css +45 -2
  121. package/styles/shell.css +73 -0
  122. package/theme/phi-antd-token-resolver.js +20 -1
  123. package/theme/phi-theme-tokens.d.ts +1 -1
  124. package/theme/phi-theme-tokens.js +1 -0
  125. package/theme/phi-theme.d.ts +5 -0
  126. package/theme/phi-theme.js +21 -0
  127. package/theme/phi-tokens.d.ts +16 -15
  128. package/theme/phi-tokens.js +16 -15
  129. package/types/cms-plugins.d.ts +2 -0
  130. package/types/dashboard-cards.d.ts +39 -4
  131. package/types/dashboard-cards.js +6 -0
  132. package/types/site-theme.d.ts +10 -2
package/styles/shell.css CHANGED
@@ -294,6 +294,33 @@
294
294
  --phi-shell-chrome-filter: var(--phi-shell-chrome-filter-dark, none);
295
295
  }
296
296
 
297
+ /* The Overlay in a tone's mode (LAYOUTING.md "Surface tone"), for a box whose Background is the Theme's
298
+ (`PHI_BACKGROUND_THEME_STYLE`). The tone's class publishes the Overlay of the mode it asks for, so the
299
+ box -- and an untoned box inside it -- reads that mode's variables; `inverse` is read against the page's
300
+ mode, as the tone scope reads it, and turns with the mode switch. Inside the Root Layout only: a Modal
301
+ or Drawer portalled to `<body>` has no Overlay published, and its box falls back to the container
302
+ ground of the tone's mode. The Root Layout's own values above stay what the Chrome Regions and panes
303
+ read; those are computed on the Root Layout and inherited, so a tone below cannot touch them. */
304
+ :where([data-phi-root-layout="true"]) :where(.phi-tone-light),
305
+ :where([data-phi-root-layout="true"][data-phi-theme-mode="dark"]) :where(.phi-tone-inverse) {
306
+ --phi-shell-chrome-image: var(--phi-shell-chrome-image-light, none);
307
+ --phi-shell-chrome-size: var(--phi-shell-chrome-size-light, auto);
308
+ --phi-shell-chrome-position: var(--phi-shell-chrome-position-light, 0 0);
309
+ --phi-shell-chrome-repeat: var(--phi-shell-chrome-repeat-light, repeat);
310
+ --phi-shell-chrome-color: var(--phi-shell-chrome-color-light, transparent);
311
+ --phi-shell-chrome-filter: var(--phi-shell-chrome-filter-light, none);
312
+ }
313
+
314
+ :where([data-phi-root-layout="true"]) :where(.phi-tone-dark),
315
+ :where([data-phi-root-layout="true"]:not([data-phi-theme-mode="dark"])) :where(.phi-tone-inverse) {
316
+ --phi-shell-chrome-image: var(--phi-shell-chrome-image-dark, none);
317
+ --phi-shell-chrome-size: var(--phi-shell-chrome-size-dark, auto);
318
+ --phi-shell-chrome-position: var(--phi-shell-chrome-position-dark, 0 0);
319
+ --phi-shell-chrome-repeat: var(--phi-shell-chrome-repeat-dark, repeat);
320
+ --phi-shell-chrome-color: var(--phi-shell-chrome-color-dark, transparent);
321
+ --phi-shell-chrome-filter: var(--phi-shell-chrome-filter-dark, none);
322
+ }
323
+
297
324
  /* A Chrome Region carries the marker only while it authored no ground of its own, so there is nothing
298
325
  left to fall back through here: the shared colour is the ground. It needs no light and dark pair
299
326
  either, because the pair above has already resolved the mode. This rule follows the two that set the
@@ -332,6 +359,17 @@
332
359
  z-index: 50;
333
360
  }
334
361
 
362
+ /*
363
+ * The Header's panes stand above every Sider's. Both are grid items at the same level, and a Sider's
364
+ * pane comes later in the DOM, so at an equal `z-index` it painted over the Header's where the two meet:
365
+ * the Sider's ground hid the Header's and cut its Shadow at the Sider's edge. Still below every Chrome
366
+ * Region (100 and up).
367
+ */
368
+ .phi-shell-chrome-pane--header,
369
+ .phi-shell-chrome-pane--header-bottom {
370
+ z-index: 51;
371
+ }
372
+
335
373
  /*
336
374
  * What the pane paints is set inline by the Shell, not here.
337
375
  *
@@ -430,6 +468,41 @@
430
468
  --phi-region-chrome-attachment: scroll;
431
469
  }
432
470
 
471
+ /*
472
+ * A toned band takes no paint from its family's pane (LAYOUTING.md "Surface tone").
473
+ *
474
+ * A toned Chrome Region paints its own ground -- the tone's container ground, a stated Background, or
475
+ * the Overlay of its tone's mode -- and never carries the marker. The pane behind it keeps the page's
476
+ * mode, so where that ground lets anything through, the page-mode glass showed under the tone's. The
477
+ * pane cannot be cut around one band without knowing its height, so it stops painting for the whole
478
+ * family and the family's marker bands paint the Overlay themselves, as they do without panes. Its
479
+ * geometry and Shadow stay: the frame's edge is where it was, and the Header still stands over the
480
+ * Sider. The pane's paint is inline and reads these properties on the pane itself, so they are set
481
+ * there. Untoned families match nothing here.
482
+ */
483
+ .shell-sider-full:has(> :is([data-phi-region-key="header_top"], [data-phi-region-key="header_main"], [data-phi-region-key="header_bottom"]):is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse)) > .phi-shell-chrome-pane--header,
484
+ .shell-sider-embedded:has(> :is([data-phi-region-key="header_top"], [data-phi-region-key="header_main"]):is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse)) > .phi-shell-chrome-pane--header,
485
+ .shell-sider-embedded:has(> [data-phi-region-key="header_bottom"]:is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse)) > .phi-shell-chrome-pane--header-bottom,
486
+ [data-phi-shell-chrome-panes="true"]:has(> [data-phi-region-key="sider_left"]:is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse)) > .phi-shell-chrome-pane--sider,
487
+ [data-phi-shell-chrome-panes="true"]:has(> [data-phi-region-key="sider_right"]:is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse)) > .phi-shell-chrome-pane--sider-right,
488
+ [data-phi-shell-chrome-panes="true"]:has(> :is([data-phi-region-key="footer_top"], [data-phi-region-key="footer_main"], [data-phi-region-key="footer_bottom"]):is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse)) > .phi-shell-chrome-pane--footer {
489
+ --phi-shell-chrome-image: none;
490
+ --phi-shell-chrome-color: transparent;
491
+ --phi-shell-chrome-filter: none;
492
+ }
493
+
494
+ .shell-sider-full:has(> :is([data-phi-region-key="header_top"], [data-phi-region-key="header_main"], [data-phi-region-key="header_bottom"]):is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse))
495
+ > .phi-cms-region-shell[data-phi-shell-chrome="true"]:is([data-phi-region-key="header_top"], [data-phi-region-key="header_main"], [data-phi-region-key="header_bottom"]),
496
+ .shell-sider-embedded:has(> :is([data-phi-region-key="header_top"], [data-phi-region-key="header_main"]):is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse))
497
+ > .phi-cms-region-shell[data-phi-shell-chrome="true"]:is([data-phi-region-key="header_top"], [data-phi-region-key="header_main"]),
498
+ [data-phi-shell-chrome-panes="true"]:has(> :is([data-phi-region-key="footer_top"], [data-phi-region-key="footer_main"], [data-phi-region-key="footer_bottom"]):is(.phi-tone-light, .phi-tone-dark, .phi-tone-inverse))
499
+ > .phi-cms-region-shell[data-phi-shell-chrome="true"]:is([data-phi-region-key="footer_top"], [data-phi-region-key="footer_main"], [data-phi-region-key="footer_bottom"]) {
500
+ --phi-region-chrome-image: var(--phi-shell-chrome-image, none);
501
+ --phi-region-chrome-color: var(--phi-shell-chrome-color, transparent);
502
+ --phi-region-chrome-filter: var(--phi-shell-chrome-filter, none);
503
+ --phi-region-chrome-attachment: fixed;
504
+ }
505
+
433
506
  /* ---------------------------------------------------------------------------------------------
434
507
  Revealing `header_top` (SHELL.md "Region visibility per Page")
435
508
 
@@ -1,4 +1,5 @@
1
1
  import darkAlgorithm from "antd/es/theme/themes/dark";
2
+ import { generateColorPalettes as generateDarkColorPalettes } from "antd/es/theme/themes/dark/colors";
2
3
  import defaultAlgorithm from "antd/es/theme/themes/default";
3
4
  import seedToken from "antd/es/theme/themes/seed";
4
5
  import formatToken from "antd/es/theme/util/alias";
@@ -34,13 +35,31 @@ export function createPhiAntdThemeCssVarKey(scope, identity) {
34
35
  .replace(/^-+|-+$/g, "") || "theme";
35
36
  return `phi-${normalizedScope}-${hashPhiAntdThemeIdentity(identity)}`;
36
37
  }
38
+ /*
39
+ * A link and an info colour pointed at turn lighter in the dark mode, as a primary button does.
40
+ *
41
+ * Ant Design takes both hovers from step 4 of the colour's palette in either mode. In the light palette
42
+ * that step is a lighter tint; the dark algorithm reorders its palette so the low steps fade into the dark
43
+ * ground for borders and fills, and step 4 there is the border's -- darker than the colour itself, so a
44
+ * link went dim on a dark ground when pointed at (#3867b5 to #274069 on #08153a). The primary hover takes
45
+ * step 5, which in the dark palette is the lighter one; these take it too. A hover a Theme states itself
46
+ * still wins: `formatToken` lays the stated tokens over this.
47
+ */
48
+ function withPhiDarkHoverSteps(seed, derived) {
49
+ const linkBase = seed.colorLink || seed.colorInfo;
50
+ return {
51
+ ...derived,
52
+ ...(linkBase ? { colorLinkHover: generateDarkColorPalettes(linkBase)[5] } : {}),
53
+ ...(seed.colorInfo ? { colorInfoHover: generateDarkColorPalettes(seed.colorInfo)[5] } : {}),
54
+ };
55
+ }
37
56
  export function resolvePhiAntdAliasTokens(mode, token) {
38
57
  const mergedSeedToken = {
39
58
  ...seedToken,
40
59
  ...token,
41
60
  };
42
61
  const derivativeToken = mode === "dark"
43
- ? darkAlgorithm(mergedSeedToken)
62
+ ? withPhiDarkHoverSteps(mergedSeedToken, darkAlgorithm(mergedSeedToken))
44
63
  : defaultAlgorithm(mergedSeedToken);
45
64
  return formatToken({
46
65
  ...derivativeToken,
@@ -22,7 +22,7 @@ import type { PhiThemePalette } from "./phi-theme-presets";
22
22
  * Who may still speak Ant Design directly is a separate question, and `scripts/validate-control-boundaries.mjs`
23
23
  * answers it: the alias resolver, the root adapter, the two font helpers and this file.
24
24
  */
25
- export declare const PHI_THEME_TOKEN_KEYS: readonly ["colorBgContainer", "colorBgElevated", "colorBgMask", "colorBgSpotlight", "colorBorder", "colorBorderSecondary", "colorSplit", "colorFillAlter", "colorFill", "colorBgLayout", "colorFillQuaternary", "colorFillSecondary", "colorFillTertiary", "colorText", "colorTextBase", "colorTextHeading", "colorTextSecondary", "colorTextTertiary", "colorTextQuaternary", "colorTextDescription", "colorTextDisabled", "colorTextLabel", "colorTextPlaceholder", "colorTextLightSolid", "colorPrimary", "colorPrimaryBg", "colorPrimaryBgHover", "colorPrimaryBorder", "colorPrimaryBorderHover", "colorPrimaryHover", "colorPrimaryActive", "colorPrimaryText", "colorPrimaryTextHover", "colorPrimaryTextActive", "colorInfo", "colorInfoBg", "colorInfoBgHover", "colorInfoBorder", "colorInfoBorderHover", "colorInfoText", "colorInfoTextHover", "colorSuccess", "colorSuccessBg", "colorSuccessBgHover", "colorSuccessBorder", "colorSuccessBorderHover", "colorSuccessText", "colorWarning", "colorWarningBg", "colorWarningBgHover", "colorWarningBorder", "colorWarningBorderHover", "colorWarningText", "colorError", "colorErrorBg", "colorErrorText", "colorErrorTextHover", "colorErrorTextActive", "colorLink", "colorLinkHover", "colorLinkActive", "padding", "paddingXXS", "paddingXS", "paddingSM", "paddingMD", "paddingLG", "paddingXL", "margin", "marginXXS", "marginXS", "marginSM", "marginMD", "marginLG", "marginXL", "marginXXL", "sizeXS", "sizeSM", "sizeMD", "sizeLG", "borderRadius", "borderRadiusXS", "borderRadiusSM", "borderRadiusLG", "borderRadiusOuter", "lineWidth", "lineType", "boxShadow", "boxShadowSecondary", "boxShadowTertiary", "controlHeight", "controlHeightXS", "controlHeightSM", "controlHeightLG", "fontFamily", "fontFamilyCode", "fontSize", "fontSizeSM", "fontSizeLG", "fontSizeXL", "fontSizeHeading1", "fontSizeHeading2", "fontSizeHeading3", "fontSizeHeading4", "fontSizeHeading5", "fontWeightStrong", "lineHeight", "lineHeightLG", "lineHeightHeading1", "lineHeightHeading2", "lineHeightHeading3", "lineHeightHeading4", "lineHeightHeading5", "motionDurationMid", "motionDurationSlow", "motionEaseInOut", "motionEaseOut"];
25
+ export declare const PHI_THEME_TOKEN_KEYS: readonly ["colorBgContainer", "colorBgElevated", "colorBgMask", "colorBgSpotlight", "colorBorder", "colorBorderSecondary", "colorSplit", "colorFillAlter", "colorFill", "colorBgLayout", "colorFillQuaternary", "colorFillSecondary", "colorFillTertiary", "colorText", "colorTextBase", "colorTextHeading", "colorTextSecondary", "colorTextTertiary", "colorTextQuaternary", "colorTextDescription", "colorTextDisabled", "colorTextLabel", "colorTextPlaceholder", "colorTextLightSolid", "colorPrimary", "colorPrimaryBg", "colorPrimaryBgHover", "colorPrimaryBorder", "colorPrimaryBorderHover", "colorPrimaryHover", "colorPrimaryActive", "colorPrimaryText", "colorPrimaryTextHover", "colorPrimaryTextActive", "colorInfo", "colorInfoBg", "colorInfoBgHover", "colorInfoBorder", "colorInfoBorderHover", "colorInfoText", "colorInfoTextHover", "colorSuccess", "colorSuccessBg", "colorSuccessBgHover", "colorSuccessBorder", "colorSuccessBorderHover", "colorSuccessText", "colorWarning", "colorWarningBg", "colorWarningBgHover", "colorWarningBorder", "colorWarningBorderHover", "colorWarningText", "colorError", "colorErrorBg", "colorErrorText", "colorErrorTextHover", "colorErrorTextActive", "colorLink", "colorLinkHover", "colorLinkActive", "padding", "paddingXXS", "paddingXS", "paddingSM", "paddingMD", "paddingLG", "paddingXL", "margin", "marginXXS", "marginXS", "marginSM", "marginMD", "marginLG", "marginXL", "marginXXL", "sizeXS", "sizeSM", "sizeMD", "sizeLG", "borderRadius", "borderRadiusXS", "borderRadiusSM", "borderRadiusLG", "borderRadiusOuter", "lineWidth", "lineType", "boxShadow", "boxShadowSecondary", "boxShadowTertiary", "controlHeight", "controlHeightXS", "controlHeightSM", "controlHeightLG", "fontFamily", "fontFamilyCode", "fontSize", "fontSizeSM", "fontSizeLG", "fontSizeXL", "fontSizeHeading1", "fontSizeHeading2", "fontSizeHeading3", "fontSizeHeading4", "fontSizeHeading5", "fontWeightStrong", "lineHeight", "lineHeightSM", "lineHeightLG", "lineHeightHeading1", "lineHeightHeading2", "lineHeightHeading3", "lineHeightHeading4", "lineHeightHeading5", "motionDurationMid", "motionDurationSlow", "motionEaseInOut", "motionEaseOut"];
26
26
  /**
27
27
  * The names this house adds to Ant Design's set.
28
28
  *
@@ -138,6 +138,7 @@ export const PHI_THEME_TOKEN_KEYS = [
138
138
  "fontSizeHeading5",
139
139
  "fontWeightStrong",
140
140
  "lineHeight",
141
+ "lineHeightSM",
141
142
  "lineHeightLG",
142
143
  "lineHeightHeading1",
143
144
  "lineHeightHeading2",
@@ -16,6 +16,11 @@ export type PhiComponentTokenOptions = {
16
16
  overrides?: Record<string, unknown>;
17
17
  };
18
18
  menu?: Record<string, unknown>;
19
+ /** The Theme's small size (`fontSizeSM`), for the parts that take it; absent, the scale's `sm`. */
20
+ fontSizeSM?: number;
21
+ /** The Theme's body size and line height (`fontSize`, `lineHeight`); absent, the scale's `base`. */
22
+ fontSize?: number;
23
+ lineHeight?: number;
19
24
  overrides?: Record<string, Record<string, unknown>>;
20
25
  };
21
26
  export type PhiThemeTokens = {
@@ -65,6 +65,9 @@ export function buildPhiThemeStructuralTokens(options = {}) {
65
65
  return Object.fromEntries(Object.entries(buildPhiThemeTokens(options)).filter(([key]) => !key.startsWith("color")));
66
66
  }
67
67
  export function buildPhiComponentTokens(options = {}) {
68
+ const fontSizeSM = options.fontSizeSM ?? PHI_FONT_SIZES.sm;
69
+ const fontSize = options.fontSize ?? PHI_FONT_SIZES.base;
70
+ const lineHeight = options.lineHeight ?? lineHeightFor(PHI_FONT_SIZES.base);
68
71
  return {
69
72
  Layout: {
70
73
  headerHeight: PHI_LAYOUT.headerHeight,
@@ -81,6 +84,24 @@ export function buildPhiComponentTokens(options = {}) {
81
84
  itemMarginInline: PHI_SPACE.sm,
82
85
  ...options.menu,
83
86
  },
87
+ /*
88
+ * The parts that take the scale's small size rather than the body's. A table is read across, not down:
89
+ * its cells are small, as a plain table's are (controls.css). A compact control -- `size="small"` --
90
+ * is small in its words as well as its height; Ant Design gives it the body size unless told.
91
+ */
92
+ Table: { cellFontSize: fontSizeSM, cellFontSizeMD: fontSizeSM, cellFontSizeSM: fontSizeSM },
93
+ // A Tree lists rows like a Table and writes like one: its titles, and the switcher's icon with them.
94
+ Tree: { fontSize: fontSizeSM },
95
+ // A contents list beside a text is a list like a Tree's, and writes as small.
96
+ Anchor: { fontSize: fontSizeSM },
97
+ // A Divider's words label a section; Ant Design sets them at `lg`, which the scale made a heading's size.
98
+ Divider: { fontSizeLG: fontSize },
99
+ Input: { inputFontSizeSM: fontSizeSM },
100
+ InputNumber: { inputFontSizeSM: fontSizeSM },
101
+ DatePicker: { inputFontSizeSM: fontSizeSM },
102
+ Button: { contentFontSizeSM: fontSizeSM },
103
+ // An Overlay's title is a label over its body, in the body's size; Ant Design gives a Modal the h5's.
104
+ Modal: { titleFontSize: fontSize, titleLineHeight: lineHeight },
84
105
  ...options.overrides,
85
106
  };
86
107
  }
@@ -19,28 +19,29 @@ export declare const PHI_PADDING: {
19
19
  /**
20
20
  * The type scale: one list for every size a Phi surface states.
21
21
  *
22
- * Two halves. Up to `lg` it climbs in steps of 2 px, because an interface needs its small sizes close
23
- * together -- a caption, a tag, a label, the text beside them. From `xl` it is the spacing sequence, where
24
- * the steps are meant to be far apart. Every size is set rather than left to Ant Design's curve, which
25
- * lands between the steps.
22
+ * A ladder of phi from the body size 16 -- the browser's own, and what reading text on the web is set in.
23
+ * `sm`, `lg`, `xxl` and `display` are the Fibonacci sizes around it (13, 21, 34, 55), `xl` is 16 x phi (26),
24
+ * between 21 and 34 where their geometric mean falls, and `xs` keeps the 9 a counter or a superscript needs.
25
+ * Every size is set rather than left to Ant Design's curve, which lands between the steps.
26
26
  *
27
27
  * `sm` to `xl` are handed to Ant Design as its tokens; `xs`, `xxl` and `display` have none and are read
28
- * from here, fixed until v1. The headings take their sizes from the same list: `h4` and `h5` are both the
29
- * body size and differ by weight and colour alone. `display` is no heading level but a size, for a hero's
30
- * or a landing's title, and is not offered beside the others.
28
+ * from here, fixed until v1. The headings take their sizes from the same list: `h1` the page's title at
29
+ * `xxl`, about twice the body, then `xl`, `lg`, and `h4` and `h5` at the body and `sm` sizes, set apart by
30
+ * weight and colour. `display` is no heading level but a size, for a hero's or a landing's title, and is
31
+ * not offered beside the others.
31
32
  */
32
33
  export declare const PHI_FONT_SIZES: {
33
34
  readonly xs: 9;
34
- readonly sm: 11;
35
- readonly base: 13;
36
- readonly lg: 15;
37
- readonly xl: 21;
35
+ readonly sm: 13;
36
+ readonly base: 16;
37
+ readonly lg: 21;
38
+ readonly xl: 26;
38
39
  readonly xxl: 34;
39
40
  readonly display: 55;
40
41
  readonly heading1: 34;
41
- readonly heading2: 21;
42
- readonly heading3: 15;
43
- readonly heading4: 13;
42
+ readonly heading2: 26;
43
+ readonly heading3: 21;
44
+ readonly heading4: 16;
44
45
  readonly heading5: 13;
45
46
  };
46
47
  export declare const PHI_RADII: {
@@ -54,7 +55,7 @@ export declare const PHI_RADII: {
54
55
  readonly xxl: 89;
55
56
  };
56
57
  export declare const PHI_CONTROL_HEIGHTS: {
57
- readonly sm: 21;
58
+ readonly sm: 26;
58
59
  readonly md: 34;
59
60
  readonly lg: 55;
60
61
  };
@@ -19,28 +19,29 @@ export const PHI_PADDING = {
19
19
  /**
20
20
  * The type scale: one list for every size a Phi surface states.
21
21
  *
22
- * Two halves. Up to `lg` it climbs in steps of 2 px, because an interface needs its small sizes close
23
- * together -- a caption, a tag, a label, the text beside them. From `xl` it is the spacing sequence, where
24
- * the steps are meant to be far apart. Every size is set rather than left to Ant Design's curve, which
25
- * lands between the steps.
22
+ * A ladder of phi from the body size 16 -- the browser's own, and what reading text on the web is set in.
23
+ * `sm`, `lg`, `xxl` and `display` are the Fibonacci sizes around it (13, 21, 34, 55), `xl` is 16 x phi (26),
24
+ * between 21 and 34 where their geometric mean falls, and `xs` keeps the 9 a counter or a superscript needs.
25
+ * Every size is set rather than left to Ant Design's curve, which lands between the steps.
26
26
  *
27
27
  * `sm` to `xl` are handed to Ant Design as its tokens; `xs`, `xxl` and `display` have none and are read
28
- * from here, fixed until v1. The headings take their sizes from the same list: `h4` and `h5` are both the
29
- * body size and differ by weight and colour alone. `display` is no heading level but a size, for a hero's
30
- * or a landing's title, and is not offered beside the others.
28
+ * from here, fixed until v1. The headings take their sizes from the same list: `h1` the page's title at
29
+ * `xxl`, about twice the body, then `xl`, `lg`, and `h4` and `h5` at the body and `sm` sizes, set apart by
30
+ * weight and colour. `display` is no heading level but a size, for a hero's or a landing's title, and is
31
+ * not offered beside the others.
31
32
  */
32
33
  export const PHI_FONT_SIZES = {
33
34
  xs: 9,
34
- sm: 11,
35
- base: 13,
36
- lg: 15,
37
- xl: 21,
35
+ sm: 13,
36
+ base: 16,
37
+ lg: 21,
38
+ xl: 26,
38
39
  xxl: 34,
39
40
  display: 55,
40
41
  heading1: 34,
41
- heading2: 21,
42
- heading3: 15,
43
- heading4: 13,
42
+ heading2: 26,
43
+ heading3: 21,
44
+ heading4: 16,
44
45
  heading5: 13,
45
46
  };
46
47
  export const PHI_RADII = {
@@ -54,7 +55,7 @@ export const PHI_RADII = {
54
55
  xxl: 89,
55
56
  };
56
57
  export const PHI_CONTROL_HEIGHTS = {
57
- sm: 21,
58
+ sm: 26,
58
59
  md: 34,
59
60
  lg: 55,
60
61
  };
@@ -114,6 +114,8 @@ export type PhiCmsConfigField = (PhiCmsConfigFieldBase & {
114
114
  * Button that is only its icon.
115
115
  */
116
116
  emptyValue?: "";
117
+ /** What an empty box shows: what an unset value means, such as `Auto`. Not stored. */
118
+ placeholder?: string;
117
119
  }) | (PhiCmsConfigFieldBase & {
118
120
  /**
119
121
  * One link, chosen rather than typed.
@@ -31,15 +31,48 @@ export declare function createPhiDashboardCardId(moduleId: string, leaf: string)
31
31
  * `stat` is a figure, what it is, and where to go for more. `list` is a handful of entries -- what
32
32
  * changed, what is waiting -- each a line with an optional time and tone; the Builder's Dashboard is the
33
33
  * case that asked for it, because what a structure author looks for first is what is open rather than
34
- * how many. The form names a renderer and the payload fills it, and a form Core offers is a promise it
35
- * then keeps: a series card stays open until somebody has a series (DASHBOARD.md section 9).
34
+ * how many. `series` is a figure over time -- a day's views, clones or downloads for the last month --
35
+ * drawn as a line per series under its headline; the project-stats Add-on is the case that asked for it
36
+ * (DASHBOARD.md section 9). The form names a renderer and the payload fills it, and a form Core offers
37
+ * is a promise it then keeps.
36
38
  */
37
- export type PhiDashboardCardForm = "stat" | "list";
39
+ export type PhiDashboardCardForm = "stat" | "list" | "series";
38
40
  /**
39
41
  * How many entries a `list` card draws. A card shows little and leads out (DASHBOARD.md section 2); a
40
42
  * provider that has more says so in `meta` and lets the card's target show the rest.
41
43
  */
42
44
  export declare const PHI_DASHBOARD_CARD_LIST_LIMIT = 5;
45
+ /**
46
+ * How many series a `series` card draws. Two or three lines on a card's width still read as a comparison
47
+ * -- views and unique visitors -- and a fourth is a chart that wants a page of its own; a provider that has
48
+ * more puts them on separate cards or on the card's target.
49
+ */
50
+ export declare const PHI_DASHBOARD_CARD_SERIES_LIMIT = 3;
51
+ /**
52
+ * A `series` card's figures over time.
53
+ *
54
+ * Point by point, oldest first, because that is how a provider counts: one row per day, each with a value
55
+ * for every series. `labels` names the series in the order each point's `values` states them, so a point
56
+ * carries exactly one number per label -- a day nothing was counted on is a `0`, not a missing value,
57
+ * because a gap a line would have to bridge or break is a decision the card should not be making.
58
+ *
59
+ * `at` is when the point stands: an ISO date (`2026-11-05`) for a day, or an instant. The card formats it
60
+ * in the page's locale, a date as the calendar day it names. `unit` is a word for what is counted,
61
+ * already translated ("views", "downloads"), drawn after the figure in the chart's spoken label.
62
+ *
63
+ * The headline is the payload's `value`, as on a `stat` card: a figure the provider states -- a total
64
+ * over the period, which the points cannot add up to when the provider counts uniques. Absent, the card
65
+ * shows the latest point of the first series.
66
+ */
67
+ export type PhiDashboardCardSeries = {
68
+ labels: string[];
69
+ points: PhiDashboardCardSeriesPoint[];
70
+ unit?: string;
71
+ };
72
+ export type PhiDashboardCardSeriesPoint = {
73
+ at: string;
74
+ values: number[];
75
+ };
43
76
  export type PhiDashboardCardDescriptor = {
44
77
  cardId: PhiDashboardCardId;
45
78
  form: PhiDashboardCardForm;
@@ -96,7 +129,7 @@ export type PhiDashboardCardDescriptor = {
96
129
  */
97
130
  export type PhiDashboardCardPayload = {
98
131
  cardId: PhiDashboardCardId;
99
- /** A `stat` card's figure, drawn under the descriptor's title. */
132
+ /** A `stat` card's figure, drawn under the descriptor's title, and a `series` card's headline. */
100
133
  value?: string;
101
134
  /**
102
135
  * A `list` card's entries, newest or most pressing first, at most `PHI_DASHBOARD_CARD_LIST_LIMIT` of
@@ -104,6 +137,8 @@ export type PhiDashboardCardPayload = {
104
137
  * card formats in the page's locale, or in words where words are what the provider has.
105
138
  */
106
139
  entries?: PhiTimelineEntry[];
140
+ /** A `series` card's points, drawn under the headline `value`. */
141
+ series?: PhiDashboardCardSeries;
107
142
  description?: string;
108
143
  meta?: string;
109
144
  error?: string | null;
@@ -18,3 +18,9 @@ export function createPhiDashboardCardId(moduleId, leaf) {
18
18
  * provider that has more says so in `meta` and lets the card's target show the rest.
19
19
  */
20
20
  export const PHI_DASHBOARD_CARD_LIST_LIMIT = 5;
21
+ /**
22
+ * How many series a `series` card draws. Two or three lines on a card's width still read as a comparison
23
+ * -- views and unique visitors -- and a fourth is a chart that wants a page of its own; a provider that has
24
+ * more puts them on separate cards or on the card's target.
25
+ */
26
+ export const PHI_DASHBOARD_CARD_SERIES_LIMIT = 3;
@@ -1,4 +1,5 @@
1
1
  import type { PhiShadow } from "./layout-style";
2
+ import type { PhiLinkTarget } from "./references";
2
3
  import type { PhiCmsBackgroundWidgetConfig } from "../components/widgets/config/background";
3
4
  /**
4
5
  * The Theme Root Background (SHELL.md "Root Background and Shell Backdrop Layers"): painted once at
@@ -113,8 +114,15 @@ export type PhiSiteThemeBrandLine = {
113
114
  * decides is whether and how the Brand Widget appears; what it shows is decided here.
114
115
  */
115
116
  export type PhiSiteThemeBrand = {
116
- /** Where the Brand Widget leads when it is clicked. The Site root where nothing says otherwise. */
117
- homeHref?: string | null;
117
+ /**
118
+ * Where the Brand Widget leads when it is clicked. The Site root where nothing says otherwise.
119
+ *
120
+ * A link target like every other destination an author picks (`REFERENCES.md`): a Page by reference,
121
+ * resolved to its address per render, so a Page that is renamed or moved keeps the Brand leading to
122
+ * it. A Page that no longer resolves leads to the Site root rather than to a 404. The key ends in
123
+ * `LinkTarget`, which is what the reference collectors go by.
124
+ */
125
+ homeLinkTarget?: PhiLinkTarget | null;
118
126
  /** The small line above the Wordmark, for Sites whose name needs a word of context. */
119
127
  eyebrow?: string | null;
120
128
  /** The Logo, one picture per mode. A mode the record says nothing about wears the Theme Set's. */