@stealthscale/component-screen 0.2.1 → 0.2.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 (44) hide show
  1. package/dist/cyclonedx/bom.json +1 -1
  2. package/dist/index.d.ts +3 -3
  3. package/dist/index.js +1 -8216
  4. package/dist/pages/action-bar/action-bar.js +471 -0
  5. package/dist/pages/action-bar/action-bar.props.js +3 -0
  6. package/dist/pages/app-shell/app-shell.js +4899 -0
  7. package/dist/pages/app-shell/app-shell.props.js +3 -0
  8. package/dist/pages/floating-panel/floating-panel.js +995 -0
  9. package/dist/pages/floating-panel/floating-panel.props.js +3 -0
  10. package/dist/pages/locale-switcher/locale-switcher.js +180 -0
  11. package/dist/pages/locale-switcher/locale-switcher.props.js +3 -0
  12. package/dist/pages/page/page.js +2308 -0
  13. package/dist/pages/page/page.props.js +3 -0
  14. package/dist/pages/pages.json +123 -0
  15. package/dist/pages/section/section.js +1241 -0
  16. package/dist/pages/section/section.props.js +3 -0
  17. package/dist/pages/sidebar/sidebar.js +1743 -0
  18. package/dist/pages/sidebar/sidebar.props.js +3 -0
  19. package/dist/pages/splitter/splitter.js +1563 -0
  20. package/dist/pages/splitter/splitter.props.js +3 -0
  21. package/dist/pages/switcher/switcher.js +900 -0
  22. package/dist/pages/switcher/switcher.props.js +3 -0
  23. package/dist/pages/theme-switcher/theme-switcher.js +180 -0
  24. package/dist/pages/theme-switcher/theme-switcher.props.js +3 -0
  25. package/dist/pages/toolbar/toolbar.js +1045 -0
  26. package/dist/pages/toolbar/toolbar.props.js +3 -0
  27. package/dist/{recipe-sZAQY6Kq.js → recipes-Cmy1leBm.js} +312 -30
  28. package/dist/shared-DxlFabHA.js +9547 -0
  29. package/dist/shell.js +1 -165
  30. package/dist/theme.js +3 -4
  31. package/locales/en/specimen/action-bar.json +46 -0
  32. package/locales/en/specimen/app-shell.json +288 -0
  33. package/locales/en/specimen/floating-panel.json +70 -0
  34. package/locales/en/specimen/locale-switcher.json +15 -0
  35. package/locales/en/specimen/page.json +198 -0
  36. package/locales/en/specimen/section.json +91 -0
  37. package/locales/en/specimen/sidebar.json +87 -0
  38. package/locales/en/specimen/splitter.json +93 -0
  39. package/locales/en/specimen/switcher.json +61 -0
  40. package/locales/en/specimen/theme-switcher.json +15 -0
  41. package/locales/en/specimen/toolbar.json +80 -0
  42. package/package.json +25 -24
  43. package/dist/recipe-DRMsitrw.js +0 -283
  44. package/dist/root-qEh4u7y5.js +0 -1182
@@ -0,0 +1,3 @@
1
+ export const dropped = {"ActionProps": {"conditions": 284, "foreign": 1049}, "CenterProps": {"conditions": 284, "foreign": 1041}, "EndProps": {"conditions": 284, "foreign": 1041}, "GroupProps": {"conditions": 284, "foreign": 1040}, "ItemProps": {"conditions": 284, "foreign": 1040}, "LinkProps": {"conditions": 284, "foreign": 1049}, "RootProps": {"conditions": 284, "foreign": 1045}, "SearchProps": {"conditions": 284, "foreign": 1071}, "SeparatorProps": {"conditions": 284, "foreign": 1042}, "StartProps": {"conditions": 284, "foreign": 1041}, "TitleProps": {"conditions": 284, "foreign": 1041}};
2
+ export const parts = {"ActionProps": [{"accepts": "\"glow\" | \"pulse\"", "fallback": "", "kind": "variant", "name": "effect", "refers": [], "required": false, "says": "The halo around the button, in the palette's solid at half opacity."}, {"accepts": "Lift", "fallback": "", "kind": "variant", "name": "elevation", "refers": ["kit.Lift"], "required": false, "says": ""}, {"accepts": "ReactNode", "fallback": "", "kind": "option", "name": "icon", "refers": ["react.ReactElement", "react.ReactPortal"], "required": false, "says": "Icon before the words, which a narrow row shows alone."}, {"accepts": "((event: MouseEvent<HTMLElement, MouseEvent>) => void)", "fallback": "", "kind": "option", "name": "onClick", "refers": ["react.MouseEvent"], "required": false, "says": "Handler the button or the menu row calls when a reader presses it."}, {"accepts": "\"accent\" | \"error\" | \"info\" | \"neutral\" | \"primary\" | \"secondary\" | \"success\" | \"warning\"", "fallback": "", "kind": "variant", "name": "palette", "refers": [], "required": false, "says": "Palette of every look. The base sets `primary`."}, {"accepts": "boolean", "fallback": "", "kind": "option", "name": "primary", "refers": [], "required": false, "says": "Whether the action is the row's primary action, which renders solid and keeps its words."}, {"accepts": "Priority", "fallback": "", "kind": "option", "name": "priority", "refers": ["kit.Priority"], "required": false, "says": "Priority that decides how a narrow row folds the action, in place of the one `icon` and `primary` imply."}, {"accepts": "\"square\"", "fallback": "", "kind": "variant", "name": "shape", "refers": [], "required": false, "says": ""}, {"accepts": "Scale", "fallback": "", "kind": "variant", "name": "size", "refers": ["kit.Scale"], "required": false, "says": ""}, {"accepts": "\"ghost\" | \"glass\" | \"outline\" | \"plain\" | \"solid\" | \"subtle\" | \"surface\"", "fallback": "", "kind": "variant", "name": "variant", "refers": [], "required": false, "says": ""}], "CenterProps": [], "EndProps": [], "GroupProps": [{"accepts": "Align", "fallback": "", "kind": "variant", "name": "align", "refers": ["kit.Align"], "required": false, "says": "Cross-axis alignment of the children."}, {"accepts": "boolean", "fallback": "", "kind": "variant", "name": "attached", "refers": [], "required": false, "says": "Joins the children into one control."}, {"accepts": "boolean", "fallback": "", "kind": "variant", "name": "dim", "refers": [], "required": false, "says": "Dims every child except a hovered, keyboard-focused or pressed one."}, {"accepts": "ConditionalValue<number | \"-0.5\" | \"-1\" | \"-1.5\" | \"-10\" | \"-11\" | \"-12\" | \"-14\" | \"-16\" | \"-2\" | \"-2.5\" | \"-20\" | \"-24\" | \"-28\" | \"-3\" | \"-3.5\" | \"-32\" | \"-36\" | \"-4\" | \"-4.5\" | \"-40\" | \"-44\" | \"-48\" | ... 105 more ... | (string & {})>", "fallback": "", "kind": "variant", "name": "gap", "refers": [], "required": false, "says": "Gap token between the children, from `xs` to `xl`."}, {"accepts": "boolean", "fallback": "", "kind": "variant", "name": "grow", "refers": [], "required": false, "says": "Makes the group full width and gives every child an equal share of it."}, {"accepts": "Justify", "fallback": "", "kind": "variant", "name": "justify", "refers": ["kit.Justify"], "required": false, "says": "Distribution of the space left over along the main axis."}, {"accepts": "\"horizontal\" | \"vertical\"", "fallback": "", "kind": "variant", "name": "orientation", "refers": [], "required": false, "says": "Direction the children run in."}], "ItemProps": [{"accepts": "Drawn", "fallback": "", "kind": "option", "name": "as", "refers": ["kit.Drawn"], "required": false, "says": "The element or component the control renders as: a `button`, or an `a` when `href` is set."}, {"accepts": "string", "fallback": "", "kind": "option", "name": "href", "refers": [], "required": false, "says": "The link's target, which renders the control as an `a`."}], "LinkProps": [{"accepts": "boolean", "fallback": "", "kind": "option", "name": "current", "refers": [], "required": false, "says": "Whether the link is the reader's current page."}, {"accepts": "\"glow\" | \"pulse\"", "fallback": "", "kind": "variant", "name": "effect", "refers": [], "required": false, "says": "The halo around the button, in the palette's solid at half opacity."}, {"accepts": "Lift", "fallback": "", "kind": "variant", "name": "elevation", "refers": ["kit.Lift"], "required": false, "says": ""}, {"accepts": "string", "fallback": "", "kind": "option", "name": "href", "refers": [], "required": true, "says": "Target of the link."}, {"accepts": "ReactNode", "fallback": "", "kind": "option", "name": "icon", "refers": ["react.ReactElement", "react.ReactPortal"], "required": false, "says": "Icon before the words, which a narrow row shows alone."}, {"accepts": "MouseEventHandler<HTMLElement>", "fallback": "", "kind": "option", "name": "onClick", "refers": ["react.MouseEvent", "react.MouseEventHandler"], "required": false, "says": "Handler the link or the menu row calls when a reader presses it. React's handler type accepts a router's anchor handler."}, {"accepts": "\"accent\" | \"error\" | \"info\" | \"neutral\" | \"primary\" | \"secondary\" | \"success\" | \"warning\"", "fallback": "", "kind": "variant", "name": "palette", "refers": [], "required": false, "says": "Palette of every look. The base sets `primary`."}, {"accepts": "Priority", "fallback": "", "kind": "option", "name": "priority", "refers": ["kit.Priority"], "required": false, "says": "Priority that decides how a narrow row folds the link, in place of the one `icon` implies."}, {"accepts": "\"square\"", "fallback": "", "kind": "variant", "name": "shape", "refers": [], "required": false, "says": ""}, {"accepts": "Scale", "fallback": "", "kind": "variant", "name": "size", "refers": ["kit.Scale"], "required": false, "says": ""}, {"accepts": "\"ghost\" | \"glass\" | \"outline\" | \"plain\" | \"solid\" | \"subtle\" | \"surface\"", "fallback": "", "kind": "variant", "name": "variant", "refers": [], "required": false, "says": ""}], "RootProps": [{"accepts": "string", "fallback": "", "kind": "option", "name": "aria-label", "refers": [], "required": true, "says": "The accessible name of the row."}, {"accepts": "string", "fallback": "", "kind": "option", "name": "more", "refers": [], "required": false, "says": "Words that name the menu of folded actions. Defaults to `More actions`."}, {"accepts": "ReactNode", "fallback": "", "kind": "option", "name": "moreIcon", "refers": ["react.ReactElement", "react.ReactPortal"], "required": false, "says": "Mark the menu's trigger shows in place of its words."}, {"accepts": "\"l1\" | \"l2\" | \"l3\"", "fallback": "", "kind": "variant", "name": "radius", "refers": [], "required": false, "says": "Corner radius of an outlined or surface row."}, {"accepts": "Scale", "fallback": "", "kind": "variant", "name": "size", "refers": ["kit.Scale"], "required": false, "says": "Size of the gap and of the separator's block margin."}, {"accepts": "\"outline\" | \"plain\" | \"surface\"", "fallback": "", "kind": "variant", "name": "variant", "refers": [], "required": false, "says": "Look of the row."}], "SearchProps": [{"accepts": "Scale", "fallback": "", "kind": "variant", "name": "size", "refers": ["kit.Scale"], "required": false, "says": "Row height, text size and inline inset. The height reads the control scale, the text the label role at the normal weight, and the inset the inset scale one size smaller."}, {"accepts": "\"error\" | \"info\" | \"success\" | \"warning\"", "fallback": "", "kind": "variant", "name": "status", "refers": [], "required": false, "says": "Status the group reports. Each value sets the edge and the focus ring from that status's palette."}, {"accepts": "\"flushed\" | \"outline\" | \"subtle\"", "fallback": "", "kind": "variant", "name": "variant", "refers": [], "required": false, "says": "Edges and surface of the box, and the fill of a filled addon."}], "SeparatorProps": [{"accepts": "Placement", "fallback": "", "kind": "variant", "name": "labelPlacement", "refers": ["kit.Placement"], "required": false, "says": "Place of a label between its lines. `start` and `end` follow the writing direction and drop the line on their side. A divider without a label renders no line for it to drop."}, {"accepts": "\"horizontal\" | \"vertical\"", "fallback": "", "kind": "variant", "name": "orientation", "refers": [], "required": false, "says": "Direction of the line. `vertical` stretches to the height of a row and renders no label."}], "StartProps": [], "TitleProps": []};
3
+ export const shapes = {"react.ReactElement": [{"accepts": "string | JSXElementConstructor<any>", "name": "type", "says": ""}, {"accepts": "unknown", "name": "props", "says": ""}, {"accepts": "string | null", "name": "key", "says": ""}], "react.ReactPortal": [{"accepts": "ReactNode", "name": "children", "says": ""}, {"accepts": "string | JSXElementConstructor<any>", "name": "type", "says": ""}, {"accepts": "unknown", "name": "props", "says": ""}, {"accepts": "string | null", "name": "key", "says": ""}], "kit.Priority": [{"accepts": "", "name": "\"primary\"", "says": ""}, {"accepts": "", "name": "\"secondary\"", "says": ""}, {"accepts": "", "name": "\"tertiary\"", "says": ""}], "kit.Lift": [{"accepts": "", "name": "\"floating\"", "says": ""}, {"accepts": "", "name": "\"raised\"", "says": ""}], "kit.Scale": [{"accepts": "", "name": "\"2xl\"", "says": ""}, {"accepts": "", "name": "\"3xl\"", "says": ""}, {"accepts": "", "name": "\"4xl\"", "says": ""}, {"accepts": "", "name": "\"lg\"", "says": ""}, {"accepts": "", "name": "\"md\"", "says": ""}, {"accepts": "", "name": "\"sm\"", "says": ""}, {"accepts": "", "name": "\"xl\"", "says": ""}, {"accepts": "", "name": "\"xs\"", "says": ""}], "kit.Align": [{"accepts": "", "name": "\"baseline\"", "says": ""}, {"accepts": "", "name": "\"flex-end\"", "says": ""}, {"accepts": "", "name": "\"flex-start\"", "says": ""}, {"accepts": "", "name": "\"stretch\"", "says": ""}], "kit.Justify": [{"accepts": "", "name": "\"around\"", "says": ""}, {"accepts": "", "name": "\"between\"", "says": ""}, {"accepts": "", "name": "\"center\"", "says": ""}, {"accepts": "", "name": "\"end\"", "says": ""}, {"accepts": "", "name": "\"evenly\"", "says": ""}, {"accepts": "", "name": "\"start\"", "says": ""}], "kit.Drawn": [{"accepts": "(() => string) | (() => string)", "name": "toString", "says": "Returns a string representation of a string. Returns a string representation of a function."}, {"accepts": "number", "name": "length", "says": "Returns the length of a String object."}, {"accepts": "(() => Object) | (() => string)", "name": "valueOf", "says": "Returns the primitive value of the specified object."}], "kit.Placement": [{"accepts": "", "name": "\"center\"", "says": ""}, {"accepts": "", "name": "\"end\"", "says": ""}, {"accepts": "", "name": "\"start\"", "says": ""}]};
@@ -1,5 +1,4 @@
1
- import { i as NARROW$1, n as FOLDING } from "./recipe-DRMsitrw.js";
2
- import { CONTROL_INSET_END, CONTROL_INSET_START, axis, below, cornerVariants, defineSlotRecipe, dense, divider, interactive, motion, onSlot, onSlots, paletteVariants, sizeVariants, surface, truncate } from "@stealthscale/theme/authoring";
1
+ import { CONTROL_INSET_END, CONTROL_INSET_START, axis, below, cornerVariants, defineSlotRecipe, dense, divider, interactive, lookVariants, motion, onSlot, onSlots, paletteVariants, sizeVariants, surface, truncate } from "@stealthscale/theme/authoring";
3
2
  //#region src/action-bar/recipe.ts
4
3
  /**
5
4
  * Styles the action bar, a panel fixed to the bottom of the window with the actions for what a
@@ -39,7 +38,7 @@ const ALIGNED = {
39
38
  /**
40
39
  * Defines the action bar recipe, which places the bar in the middle of the bottom edge by default.
41
40
  */
42
- const recipe$7 = defineSlotRecipe({
41
+ const recipe$8 = defineSlotRecipe({
43
42
  base: {
44
43
  closeTrigger: { flexShrink: "0" },
45
44
  content: {
@@ -452,7 +451,7 @@ const RAIL = {
452
451
  * `staticCss` lists every value of `content`, `scroll` and `variant`. A product's frame states
453
452
  * them as data, and the compiler emits a variant only where a source states it as a literal.
454
453
  */
455
- const recipe$6 = defineSlotRecipe({
454
+ const recipe$7 = defineSlotRecipe({
456
455
  base: {
457
456
  aside: {
458
457
  ...PANEL,
@@ -756,7 +755,7 @@ const RING_OFFSET = "--scroll-area-ring-offset";
756
755
  /**
757
756
  * Defines the floating panel recipe.
758
757
  */
759
- const recipe$5 = defineSlotRecipe({
758
+ const recipe$6 = defineSlotRecipe({
760
759
  base: {
761
760
  body: {
762
761
  textStyle: "body.sm",
@@ -869,6 +868,63 @@ const recipe$5 = defineSlotRecipe({
869
868
  ]
870
869
  });
871
870
  //#endregion
871
+ //#region src/folding/folding.ts
872
+ /**
873
+ * Styles an action that folds to its icon while its row is narrow, for the page, the toolbar and
874
+ * the section.
875
+ *
876
+ * @remarks
877
+ * A secondary action shows its icon alone, and its words remain for a screen reader. A tertiary
878
+ * action renders nothing on a narrow row and runs from the row's menu, which the action registers
879
+ * with. The row measures its own width, so a row beside an open sidebar folds on its own width
880
+ * and the caller does not write a breakpoint.
881
+ */
882
+ /**
883
+ * Attribute an action sets on itself while its own row is narrow.
884
+ *
885
+ * @remarks
886
+ * The action reads the state from its row's context, so a narrow ancestor folds no action of a
887
+ * wider row inside it. A bar fixed to the window is wider than the page around it in the
888
+ * document.
889
+ */
890
+ const NARROW$2 = "data-narrow";
891
+ /**
892
+ * Attribute a toolbar control sets to the id it registers its menu row under, while a narrow row
893
+ * can move it into the row's menu.
894
+ *
895
+ * @remarks
896
+ * The row reads the attribute in document order. It moves the control nearest its end first, and
897
+ * its menu lists the moved controls in the row's order.
898
+ */
899
+ const FOLDS$1 = "data-folds";
900
+ /**
901
+ * Attribute an action sets to its priority.
902
+ *
903
+ * @remarks
904
+ * The priority is an attribute and not an axis, because a slot recipe resolves its variants once,
905
+ * at the root, and each action in a row folds on its own priority.
906
+ */
907
+ const PRIORITY = "data-priority";
908
+ /**
909
+ * Styles an action by its priority while its row is narrow.
910
+ *
911
+ * @remarks
912
+ * Every action keeps its words on one line at every width, because a wrapped control would make
913
+ * the row taller. A secondary action hides its element children other than its icon with
914
+ * `srOnly`, so it keeps its accessible name, and renders as a square around its icon. Its words
915
+ * must be in an element, because a CSS selector cannot select a bare text node. A primary action
916
+ * is unchanged.
917
+ */
918
+ const FOLDING = {
919
+ [`&[${PRIORITY}=secondary]`]: { [`&[${NARROW$2}]`]: {
920
+ "& > :not(svg)": { srOnly: true },
921
+ aspectRatio: "square",
922
+ justifyContent: "center",
923
+ paddingInline: "0"
924
+ } },
925
+ whiteSpace: "nowrap"
926
+ };
927
+ //#endregion
872
928
  //#region src/page/metrics.ts
873
929
  /**
874
930
  * Computes the rules the page recipe writes at each of its sizes: the padding and gaps of the
@@ -1071,7 +1127,8 @@ const SIZES = onSlots({
1071
1127
  * sidebar's picker as a band above the body. A sticky aside keeps to the top of its row, under
1072
1128
  * the shell's sticky bars, and so does a sticky sidebar. The recipe has no `palette` axis,
1073
1129
  * because a page is layout on the page's surface, and no `effect` axis, because a page is not a
1074
- * control.
1130
+ * control. `staticCss` lists `folded`, because the root sets it from its measured width, so an
1131
+ * application's stylesheet compiler does not read the value.
1075
1132
  */
1076
1133
  /**
1077
1134
  * Custom property the root sets to the room at the page's inline edges.
@@ -1161,7 +1218,7 @@ const CAPPED_COLUMN = {
1161
1218
  /**
1162
1219
  * Styles a row that centres its items, wraps and shrinks.
1163
1220
  */
1164
- const ROW$1 = {
1221
+ const ROW$2 = {
1165
1222
  alignItems: "center",
1166
1223
  display: "flex",
1167
1224
  flexWrap: "wrap",
@@ -1223,14 +1280,14 @@ const SIDEBAR_AND_ASIDE = {
1223
1280
  /**
1224
1281
  * Defines the page recipe: a full-width page at size `md` by default.
1225
1282
  */
1226
- const recipe$4 = defineSlotRecipe({
1283
+ const recipe$5 = defineSlotRecipe({
1227
1284
  base: {
1228
1285
  action: {
1229
1286
  ...FOLDING,
1230
1287
  flexShrink: "0"
1231
1288
  },
1232
1289
  actions: {
1233
- ...ROW$1,
1290
+ ...ROW$2,
1234
1291
  flexWrap: "nowrap",
1235
1292
  gridArea: "actions",
1236
1293
  justifySelf: "end",
@@ -1278,7 +1335,7 @@ const recipe$4 = defineSlotRecipe({
1278
1335
  minBlockSize: "0"
1279
1336
  },
1280
1337
  context: {
1281
- ...ROW$1,
1338
+ ...ROW$2,
1282
1339
  gridArea: "context",
1283
1340
  minInlineSize: "0"
1284
1341
  },
@@ -1296,7 +1353,7 @@ const recipe$4 = defineSlotRecipe({
1296
1353
  */
1297
1354
  footer: {
1298
1355
  ...BAND$1,
1299
- ...ROW$1,
1356
+ ...ROW$2,
1300
1357
  "&[data-sticky]": {
1301
1358
  ...STUCK,
1302
1359
  insetBlockEnd: "0",
@@ -1328,7 +1385,7 @@ const recipe$4 = defineSlotRecipe({
1328
1385
  marginInlineEnd: dense("{spacing.gap.lg}")
1329
1386
  },
1330
1387
  meta: {
1331
- ...ROW$1,
1388
+ ...ROW$2,
1332
1389
  gridArea: "meta"
1333
1390
  },
1334
1391
  nav: {
@@ -1426,7 +1483,7 @@ const recipe$4 = defineSlotRecipe({
1426
1483
  },
1427
1484
  toolbar: {
1428
1485
  ...BAND$1,
1429
- ...ROW$1,
1486
+ ...ROW$2,
1430
1487
  "&[data-sticky]": STUCK,
1431
1488
  gridArea: "toolbar"
1432
1489
  },
@@ -1500,6 +1557,7 @@ const recipe$4 = defineSlotRecipe({
1500
1557
  "footer",
1501
1558
  "trail"
1502
1559
  ],
1560
+ staticCss: [{ folded: ["true"] }],
1503
1561
  variants: {
1504
1562
  /**
1505
1563
  * Position of the content when the measure is narrower than the page.
@@ -1614,7 +1672,7 @@ const AFTER = `.${CLASS$2}__root + &`;
1614
1672
  /**
1615
1673
  * Selects a band of a narrow section.
1616
1674
  */
1617
- const NARROW = `.${CLASS$2}__root[data-narrow] > &`;
1675
+ const NARROW$1 = `.${CLASS$2}__root[data-narrow] > &`;
1618
1676
  /**
1619
1677
  * Selects the actions of a narrow section.
1620
1678
  */
@@ -1658,7 +1716,7 @@ const SPACED = {
1658
1716
  /**
1659
1717
  * Styles a row that centres its items, wraps and shrinks.
1660
1718
  */
1661
- const ROW = {
1719
+ const ROW$1 = {
1662
1720
  alignItems: "center",
1663
1721
  display: "flex",
1664
1722
  flexWrap: "wrap",
@@ -1667,14 +1725,14 @@ const ROW = {
1667
1725
  /**
1668
1726
  * Defines the section recipe: a plain section at size `md` by default.
1669
1727
  */
1670
- const recipe$3 = defineSlotRecipe({
1728
+ const recipe$4 = defineSlotRecipe({
1671
1729
  base: {
1672
1730
  action: {
1673
1731
  ...FOLDING,
1674
1732
  flexShrink: "0"
1675
1733
  },
1676
1734
  actions: {
1677
- ...ROW,
1735
+ ...ROW$1,
1678
1736
  flexWrap: "nowrap",
1679
1737
  gridArea: "actions",
1680
1738
  justifySelf: "end",
@@ -1689,7 +1747,7 @@ const recipe$3 = defineSlotRecipe({
1689
1747
  minInlineSize: "0"
1690
1748
  },
1691
1749
  footer: {
1692
- ...ROW,
1750
+ ...ROW$1,
1693
1751
  "& > :last-child:not(:first-child)": { marginInlineStart: "auto" },
1694
1752
  justifyContent: "space-between"
1695
1753
  },
@@ -1800,7 +1858,7 @@ const recipe$3 = defineSlotRecipe({
1800
1858
  }
1801
1859
  },
1802
1860
  header: {
1803
- [NARROW]: { marginBlockEnd: `var(${BANDS})` },
1861
+ [NARROW$1]: { marginBlockEnd: `var(${BANDS})` },
1804
1862
  padding: "0"
1805
1863
  },
1806
1864
  root: {
@@ -1923,7 +1981,7 @@ const recipe$3 = defineSlotRecipe({
1923
1981
  /**
1924
1982
  * Selects a part inside a sidebar collapsed to a rail.
1925
1983
  */
1926
- const ICONIC = "[data-iconic] &";
1984
+ const ICONIC$1 = "[data-iconic] &";
1927
1985
  /**
1928
1986
  * Selects the children of a band that fold to an icon by themselves: a search, a nav block, a
1929
1987
  * navigation list and a switcher.
@@ -1951,7 +2009,7 @@ const BANDED = {
1951
2009
  display: "flex",
1952
2010
  flexDirection: "column",
1953
2011
  flexShrink: "0",
1954
- [ICONIC]: {
2012
+ [ICONIC$1]: {
1955
2013
  alignItems: "center",
1956
2014
  [WORDS]: { srOnly: true }
1957
2015
  },
@@ -2025,7 +2083,7 @@ function banded(size) {
2025
2083
  * whatever its `size`, a product's frame states the size and the look as data, and the compiler
2026
2084
  * emits a variant only where a source states it as a literal.
2027
2085
  */
2028
- const recipe$2 = defineSlotRecipe({
2086
+ const recipe$3 = defineSlotRecipe({
2029
2087
  base: {
2030
2088
  content: {
2031
2089
  display: "flex",
@@ -2033,7 +2091,7 @@ const recipe$2 = defineSlotRecipe({
2033
2091
  },
2034
2092
  empty: {
2035
2093
  color: "fg.muted",
2036
- [ICONIC]: { display: "none" },
2094
+ [ICONIC$1]: { display: "none" },
2037
2095
  textAlign: "center"
2038
2096
  },
2039
2097
  footer: BANDED,
@@ -2061,7 +2119,7 @@ const recipe$2 = defineSlotRecipe({
2061
2119
  display: "flex",
2062
2120
  flexShrink: "0",
2063
2121
  gridColumn: "2 / 3",
2064
- [ICONIC]: { display: "none" },
2122
+ [ICONIC$1]: { display: "none" },
2065
2123
  justifyContent: "center",
2066
2124
  padding: "0"
2067
2125
  },
@@ -2072,7 +2130,7 @@ const recipe$2 = defineSlotRecipe({
2072
2130
  display: "flex",
2073
2131
  fontWeight: "medium",
2074
2132
  gridColumn: "1 / 2",
2075
- [ICONIC]: { srOnly: true },
2133
+ [ICONIC$1]: { srOnly: true },
2076
2134
  textTransform: "uppercase"
2077
2135
  },
2078
2136
  navLabel: {
@@ -2083,7 +2141,7 @@ const recipe$2 = defineSlotRecipe({
2083
2141
  display: "flex",
2084
2142
  fontWeight: "medium",
2085
2143
  gridColumn: "1 / 2",
2086
- [ICONIC]: { srOnly: true },
2144
+ [ICONIC$1]: { srOnly: true },
2087
2145
  textTransform: "uppercase"
2088
2146
  },
2089
2147
  root: {
@@ -2098,7 +2156,7 @@ const recipe$2 = defineSlotRecipe({
2098
2156
  minBlockSize: "0"
2099
2157
  },
2100
2158
  search: {
2101
- [ICONIC]: {
2159
+ [ICONIC$1]: {
2102
2160
  display: "flex",
2103
2161
  justifyContent: "center"
2104
2162
  },
@@ -2314,7 +2372,7 @@ const PILLED = `&:has(> .${CLASS$1}__resizeTriggerIndicator)`;
2314
2372
  /**
2315
2373
  * Defines the splitter recipe, in the primary palette by default.
2316
2374
  */
2317
- const recipe$1 = defineSlotRecipe({
2375
+ const recipe$2 = defineSlotRecipe({
2318
2376
  base: {
2319
2377
  panel: {
2320
2378
  display: "flex",
@@ -2447,6 +2505,230 @@ const recipe$1 = defineSlotRecipe({
2447
2505
  palette: onSlot("root", paletteVariants()) }
2448
2506
  });
2449
2507
  //#endregion
2508
+ //#region src/switcher/recipe.ts
2509
+ /**
2510
+ * Declares the switcher's slot recipe, which styles the control that shows the current workspace,
2511
+ * project or environment and opens the menu of the others.
2512
+ *
2513
+ * @remarks
2514
+ * The recipe has six slots. The root slot is the trigger, and the mark, the label, the name, the
2515
+ * detail and the indicator are inside it. `Switcher.Root` is the disclosure package's menu, so
2516
+ * the menu's recipe styles the panel and its rows. The trigger takes the button's looks and
2517
+ * palettes from the same layer styles, so an outlined switcher has the button's light edge. The
2518
+ * mark renders an initial, an icon or an avatar in the palette's ink, without a fill. The name
2519
+ * and the detail truncate to keep the control at one height. A pair of chevrons marks a control
2520
+ * that switches and not a direction, so the indicator does not rotate while the menu is open. In
2521
+ * a sidebar closed to icons, and in a narrow toolbar for a switcher with a mark, the control is
2522
+ * its mark alone, square. The words remain in the accessible name in both.
2523
+ */
2524
+ /**
2525
+ * Selects a part of a switcher drawn as its mark alone, in a sidebar closed to icons.
2526
+ */
2527
+ const ICONIC = ".switcher__root[data-iconic] &";
2528
+ /**
2529
+ * Selects a part of a switcher with a mark in a toolbar too narrow for the name. A switcher
2530
+ * without a mark keeps its name, because the name is the only content that identifies it.
2531
+ */
2532
+ const NARROW = ".switcher__root[data-narrow]:has(.switcher__mark) &";
2533
+ /**
2534
+ * Custom property the size axis sets to the height of a button at the switcher's size.
2535
+ */
2536
+ const HEIGHT = "--switcher-height";
2537
+ /**
2538
+ * Styles a control that is one line as wide as its words: in a toolbar and on its own.
2539
+ *
2540
+ * @remarks
2541
+ * `inlineSize: fit` keeps the control as wide as its words, because a flex container fills its
2542
+ * line otherwise. The detail is hidden, because the control is one line tall. The control is at
2543
+ * least as tall as a button of its size, so it lines up with the buttons in a toolbar: 36px at
2544
+ * `sm` and 40px at `md`. In a narrow toolbar a control with a mark is a square of that height
2545
+ * around the mark, as an action with an icon is.
2546
+ */
2547
+ const INLINE = {
2548
+ detail: { display: "none" },
2549
+ root: {
2550
+ "&[data-narrow]:has(.switcher__mark)": {
2551
+ aspectRatio: "square",
2552
+ inlineSize: "auto",
2553
+ justifyContent: "center",
2554
+ paddingInline: "0"
2555
+ },
2556
+ inlineSize: "fit",
2557
+ minBlockSize: `var(${HEIGHT})`
2558
+ }
2559
+ };
2560
+ /**
2561
+ * Styles the control in a sidebar: a row as wide as the column, and the mark alone on a rail.
2562
+ *
2563
+ * @remarks
2564
+ * On a rail the control has no padding and no edge, so it is the mark's square, as tall as the
2565
+ * rows under it: 32px at `md`.
2566
+ */
2567
+ const ROW = { root: {
2568
+ "&[data-iconic]": {
2569
+ alignSelf: "center",
2570
+ aspectRatio: "square",
2571
+ borderWidth: "0",
2572
+ inlineSize: "auto",
2573
+ justifyContent: "center",
2574
+ padding: "0"
2575
+ },
2576
+ inlineSize: "full"
2577
+ } };
2578
+ /**
2579
+ * Styles a ghost switcher at the middle size, alone.
2580
+ */
2581
+ const recipe$1 = defineSlotRecipe({
2582
+ base: {
2583
+ detail: {
2584
+ ...truncate(),
2585
+ textStyle: "caption",
2586
+ color: "fg.subtle"
2587
+ },
2588
+ indicator: {
2589
+ _open: { rotate: "0deg" },
2590
+ alignItems: "center",
2591
+ color: "fg.subtle",
2592
+ display: "inline-flex",
2593
+ flexShrink: "0",
2594
+ [ICONIC]: { display: "none" },
2595
+ justifyContent: "center",
2596
+ marginInlineStart: "auto",
2597
+ [NARROW]: { display: "none" },
2598
+ transitionDuration: "press",
2599
+ transitionProperty: "common",
2600
+ transitionTimingFunction: "press"
2601
+ },
2602
+ label: {
2603
+ display: "flex",
2604
+ flex: "1",
2605
+ flexDirection: "column",
2606
+ [ICONIC]: { srOnly: true },
2607
+ minInlineSize: "0",
2608
+ [NARROW]: { srOnly: true },
2609
+ textAlign: "start"
2610
+ },
2611
+ mark: {
2612
+ alignItems: "center",
2613
+ color: "colorPalette.fg",
2614
+ display: "inline-flex",
2615
+ flexShrink: "0",
2616
+ fontWeight: "semibold",
2617
+ justifyContent: "center",
2618
+ lineHeight: "tight",
2619
+ overflow: "clip"
2620
+ },
2621
+ name: {
2622
+ ...truncate(),
2623
+ fontWeight: "medium"
2624
+ },
2625
+ root: {
2626
+ ...interactive(),
2627
+ alignItems: "center",
2628
+ appearance: "none",
2629
+ borderColor: "transparent",
2630
+ borderWidth: "control",
2631
+ colorPalette: "neutral",
2632
+ display: "flex",
2633
+ minInlineSize: "0"
2634
+ }
2635
+ },
2636
+ className: "switcher",
2637
+ compoundVariants: [{
2638
+ css: { mark: {
2639
+ boxSize: dense("{sizes.icon.lg}"),
2640
+ fontSize: "xs"
2641
+ } },
2642
+ name: "marked",
2643
+ placement: ["alone", "toolbar"]
2644
+ }, (
2645
+ /**
2646
+ * Sets the detail and the indicator in the trigger's own ink on the solid look, where the
2647
+ * page's subtle ink is not read against the fill.
2648
+ */
2649
+ {
2650
+ css: {
2651
+ detail: { color: "inherit" },
2652
+ indicator: { color: "inherit" }
2653
+ },
2654
+ name: "inked",
2655
+ variant: "solid"
2656
+ })],
2657
+ defaultVariants: {
2658
+ placement: "alone",
2659
+ size: "md",
2660
+ variant: "ghost"
2661
+ },
2662
+ jsx: [/^Switcher(\.\w+)?$/u],
2663
+ slots: [
2664
+ "root",
2665
+ "mark",
2666
+ "label",
2667
+ "name",
2668
+ "detail",
2669
+ "indicator"
2670
+ ],
2671
+ variants: {
2672
+ /**
2673
+ * The palette of the look and the mark.
2674
+ */
2675
+ palette: onSlot("root", paletteVariants()),
2676
+ /**
2677
+ * Where the control is placed, which sets its width and its lines.
2678
+ *
2679
+ * @remarks
2680
+ * `Switcher.Root` reads the placement from the sidebar or the toolbar around it unless a
2681
+ * caller states one. The `marked` compound sizes the mark to `icon.lg` on one line, because
2682
+ * the size axis sizes it for a sidebar and a compound applies over an axis.
2683
+ */
2684
+ placement: {
2685
+ alone: INLINE,
2686
+ sidebar: ROW,
2687
+ toolbar: INLINE
2688
+ },
2689
+ size: onSlots({
2690
+ indicator: sizeVariants((size) => ({ boxSize: dense(`{sizes.icon.${below(size)}}`) }), [
2691
+ "sm",
2692
+ "md",
2693
+ "lg"
2694
+ ]),
2695
+ mark: sizeVariants((size) => ({
2696
+ boxSize: dense(`{sizes.control.${below(below(size))}}`),
2697
+ fontSize: below(size)
2698
+ }), [
2699
+ "sm",
2700
+ "md",
2701
+ "lg"
2702
+ ]),
2703
+ name: sizeVariants((size) => ({ textStyle: `body.${below(size)}` }), [
2704
+ "sm",
2705
+ "md",
2706
+ "lg"
2707
+ ]),
2708
+ root: sizeVariants((size) => ({
2709
+ textStyle: `body.${below(size)}`,
2710
+ borderRadius: "l2",
2711
+ gap: dense(`{spacing.gap.${size}}`),
2712
+ [HEIGHT]: dense(`{sizes.control.${size}}`),
2713
+ paddingBlock: dense(`{spacing.gap.${below(size)}}`),
2714
+ paddingInline: dense(`{spacing.gap.${size}}`)
2715
+ }), [
2716
+ "sm",
2717
+ "md",
2718
+ "lg"
2719
+ ])
2720
+ }),
2721
+ /**
2722
+ * The button's six looks, each one of the theme's layer styles.
2723
+ *
2724
+ * @remarks
2725
+ * `ghost`, the default, has no fill at rest, so a switcher at the head of a sidebar shows the
2726
+ * sidebar's own ground and fills under a pointer.
2727
+ */
2728
+ variant: onSlot("root", lookVariants())
2729
+ }
2730
+ });
2731
+ //#endregion
2450
2732
  //#region src/toolbar/recipe.ts
2451
2733
  /**
2452
2734
  * Recipe for a toolbar: a row of controls with a start, a centre and an end band, and a search.
@@ -2554,7 +2836,7 @@ const recipe = defineSlotRecipe({
2554
2836
  },
2555
2837
  title: {
2556
2838
  ...BAND,
2557
- [`&[${NARROW$1}]`]: { marginInlineEnd: "0" },
2839
+ [`&[${NARROW$2}]`]: { marginInlineEnd: "0" },
2558
2840
  flexShrink: "0",
2559
2841
  fontWeight: "semibold",
2560
2842
  marginInlineEnd: `calc(var(${GAP}) * 2)`
@@ -2620,4 +2902,4 @@ const recipe = defineSlotRecipe({
2620
2902
  }
2621
2903
  });
2622
2904
  //#endregion
2623
- export { lengthOf as C, keyedWidth as S, STICKY_OFFSET$1 as _, SCROLLPORT as a, clamped as b, STICKY_TOP as c, recipe$6 as d, PANEL_RAIL as f, SETTLED as g, PANE_TOP as h, recipe$3 as i, recipe$4 as l, PANEL_TOP as m, recipe$1 as n, SIDEBAR_SIZE as o, PANEL_SIZE as p, recipe$2 as r, STICKY_OFFSET as s, recipe as t, recipe$5 as u, WINDOW_HEIGHT as v, recipe$7 as w, growthOf as x, RESIZING as y };
2905
+ export { RESIZING as C, lengthOf as D, keyedWidth as E, recipe$8 as O, WINDOW_HEIGHT as S, growthOf as T, PANEL_SIZE as _, recipe$4 as a, SETTLED as b, STICKY_OFFSET as c, FOLDS$1 as d, NARROW$2 as f, PANEL_RAIL as g, recipe$7 as h, recipe$3 as i, STICKY_TOP as l, recipe$6 as m, recipe$1 as n, SCROLLPORT as o, PRIORITY as p, recipe$2 as r, SIDEBAR_SIZE as s, recipe as t, recipe$5 as u, PANEL_TOP as v, clamped as w, STICKY_OFFSET$1 as x, PANE_TOP as y };