@stealthscale/component-screen 0.2.2 → 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-BWmweBfv.js → recipes-Cmy1leBm.js} +309 -29
  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 +24 -23
  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
@@ -1162,7 +1218,7 @@ const CAPPED_COLUMN = {
1162
1218
  /**
1163
1219
  * Styles a row that centres its items, wraps and shrinks.
1164
1220
  */
1165
- const ROW$1 = {
1221
+ const ROW$2 = {
1166
1222
  alignItems: "center",
1167
1223
  display: "flex",
1168
1224
  flexWrap: "wrap",
@@ -1224,14 +1280,14 @@ const SIDEBAR_AND_ASIDE = {
1224
1280
  /**
1225
1281
  * Defines the page recipe: a full-width page at size `md` by default.
1226
1282
  */
1227
- const recipe$4 = defineSlotRecipe({
1283
+ const recipe$5 = defineSlotRecipe({
1228
1284
  base: {
1229
1285
  action: {
1230
1286
  ...FOLDING,
1231
1287
  flexShrink: "0"
1232
1288
  },
1233
1289
  actions: {
1234
- ...ROW$1,
1290
+ ...ROW$2,
1235
1291
  flexWrap: "nowrap",
1236
1292
  gridArea: "actions",
1237
1293
  justifySelf: "end",
@@ -1279,7 +1335,7 @@ const recipe$4 = defineSlotRecipe({
1279
1335
  minBlockSize: "0"
1280
1336
  },
1281
1337
  context: {
1282
- ...ROW$1,
1338
+ ...ROW$2,
1283
1339
  gridArea: "context",
1284
1340
  minInlineSize: "0"
1285
1341
  },
@@ -1297,7 +1353,7 @@ const recipe$4 = defineSlotRecipe({
1297
1353
  */
1298
1354
  footer: {
1299
1355
  ...BAND$1,
1300
- ...ROW$1,
1356
+ ...ROW$2,
1301
1357
  "&[data-sticky]": {
1302
1358
  ...STUCK,
1303
1359
  insetBlockEnd: "0",
@@ -1329,7 +1385,7 @@ const recipe$4 = defineSlotRecipe({
1329
1385
  marginInlineEnd: dense("{spacing.gap.lg}")
1330
1386
  },
1331
1387
  meta: {
1332
- ...ROW$1,
1388
+ ...ROW$2,
1333
1389
  gridArea: "meta"
1334
1390
  },
1335
1391
  nav: {
@@ -1427,7 +1483,7 @@ const recipe$4 = defineSlotRecipe({
1427
1483
  },
1428
1484
  toolbar: {
1429
1485
  ...BAND$1,
1430
- ...ROW$1,
1486
+ ...ROW$2,
1431
1487
  "&[data-sticky]": STUCK,
1432
1488
  gridArea: "toolbar"
1433
1489
  },
@@ -1616,7 +1672,7 @@ const AFTER = `.${CLASS$2}__root + &`;
1616
1672
  /**
1617
1673
  * Selects a band of a narrow section.
1618
1674
  */
1619
- const NARROW = `.${CLASS$2}__root[data-narrow] > &`;
1675
+ const NARROW$1 = `.${CLASS$2}__root[data-narrow] > &`;
1620
1676
  /**
1621
1677
  * Selects the actions of a narrow section.
1622
1678
  */
@@ -1660,7 +1716,7 @@ const SPACED = {
1660
1716
  /**
1661
1717
  * Styles a row that centres its items, wraps and shrinks.
1662
1718
  */
1663
- const ROW = {
1719
+ const ROW$1 = {
1664
1720
  alignItems: "center",
1665
1721
  display: "flex",
1666
1722
  flexWrap: "wrap",
@@ -1669,14 +1725,14 @@ const ROW = {
1669
1725
  /**
1670
1726
  * Defines the section recipe: a plain section at size `md` by default.
1671
1727
  */
1672
- const recipe$3 = defineSlotRecipe({
1728
+ const recipe$4 = defineSlotRecipe({
1673
1729
  base: {
1674
1730
  action: {
1675
1731
  ...FOLDING,
1676
1732
  flexShrink: "0"
1677
1733
  },
1678
1734
  actions: {
1679
- ...ROW,
1735
+ ...ROW$1,
1680
1736
  flexWrap: "nowrap",
1681
1737
  gridArea: "actions",
1682
1738
  justifySelf: "end",
@@ -1691,7 +1747,7 @@ const recipe$3 = defineSlotRecipe({
1691
1747
  minInlineSize: "0"
1692
1748
  },
1693
1749
  footer: {
1694
- ...ROW,
1750
+ ...ROW$1,
1695
1751
  "& > :last-child:not(:first-child)": { marginInlineStart: "auto" },
1696
1752
  justifyContent: "space-between"
1697
1753
  },
@@ -1802,7 +1858,7 @@ const recipe$3 = defineSlotRecipe({
1802
1858
  }
1803
1859
  },
1804
1860
  header: {
1805
- [NARROW]: { marginBlockEnd: `var(${BANDS})` },
1861
+ [NARROW$1]: { marginBlockEnd: `var(${BANDS})` },
1806
1862
  padding: "0"
1807
1863
  },
1808
1864
  root: {
@@ -1925,7 +1981,7 @@ const recipe$3 = defineSlotRecipe({
1925
1981
  /**
1926
1982
  * Selects a part inside a sidebar collapsed to a rail.
1927
1983
  */
1928
- const ICONIC = "[data-iconic] &";
1984
+ const ICONIC$1 = "[data-iconic] &";
1929
1985
  /**
1930
1986
  * Selects the children of a band that fold to an icon by themselves: a search, a nav block, a
1931
1987
  * navigation list and a switcher.
@@ -1953,7 +2009,7 @@ const BANDED = {
1953
2009
  display: "flex",
1954
2010
  flexDirection: "column",
1955
2011
  flexShrink: "0",
1956
- [ICONIC]: {
2012
+ [ICONIC$1]: {
1957
2013
  alignItems: "center",
1958
2014
  [WORDS]: { srOnly: true }
1959
2015
  },
@@ -2027,7 +2083,7 @@ function banded(size) {
2027
2083
  * whatever its `size`, a product's frame states the size and the look as data, and the compiler
2028
2084
  * emits a variant only where a source states it as a literal.
2029
2085
  */
2030
- const recipe$2 = defineSlotRecipe({
2086
+ const recipe$3 = defineSlotRecipe({
2031
2087
  base: {
2032
2088
  content: {
2033
2089
  display: "flex",
@@ -2035,7 +2091,7 @@ const recipe$2 = defineSlotRecipe({
2035
2091
  },
2036
2092
  empty: {
2037
2093
  color: "fg.muted",
2038
- [ICONIC]: { display: "none" },
2094
+ [ICONIC$1]: { display: "none" },
2039
2095
  textAlign: "center"
2040
2096
  },
2041
2097
  footer: BANDED,
@@ -2063,7 +2119,7 @@ const recipe$2 = defineSlotRecipe({
2063
2119
  display: "flex",
2064
2120
  flexShrink: "0",
2065
2121
  gridColumn: "2 / 3",
2066
- [ICONIC]: { display: "none" },
2122
+ [ICONIC$1]: { display: "none" },
2067
2123
  justifyContent: "center",
2068
2124
  padding: "0"
2069
2125
  },
@@ -2074,7 +2130,7 @@ const recipe$2 = defineSlotRecipe({
2074
2130
  display: "flex",
2075
2131
  fontWeight: "medium",
2076
2132
  gridColumn: "1 / 2",
2077
- [ICONIC]: { srOnly: true },
2133
+ [ICONIC$1]: { srOnly: true },
2078
2134
  textTransform: "uppercase"
2079
2135
  },
2080
2136
  navLabel: {
@@ -2085,7 +2141,7 @@ const recipe$2 = defineSlotRecipe({
2085
2141
  display: "flex",
2086
2142
  fontWeight: "medium",
2087
2143
  gridColumn: "1 / 2",
2088
- [ICONIC]: { srOnly: true },
2144
+ [ICONIC$1]: { srOnly: true },
2089
2145
  textTransform: "uppercase"
2090
2146
  },
2091
2147
  root: {
@@ -2100,7 +2156,7 @@ const recipe$2 = defineSlotRecipe({
2100
2156
  minBlockSize: "0"
2101
2157
  },
2102
2158
  search: {
2103
- [ICONIC]: {
2159
+ [ICONIC$1]: {
2104
2160
  display: "flex",
2105
2161
  justifyContent: "center"
2106
2162
  },
@@ -2316,7 +2372,7 @@ const PILLED = `&:has(> .${CLASS$1}__resizeTriggerIndicator)`;
2316
2372
  /**
2317
2373
  * Defines the splitter recipe, in the primary palette by default.
2318
2374
  */
2319
- const recipe$1 = defineSlotRecipe({
2375
+ const recipe$2 = defineSlotRecipe({
2320
2376
  base: {
2321
2377
  panel: {
2322
2378
  display: "flex",
@@ -2449,6 +2505,230 @@ const recipe$1 = defineSlotRecipe({
2449
2505
  palette: onSlot("root", paletteVariants()) }
2450
2506
  });
2451
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
2452
2732
  //#region src/toolbar/recipe.ts
2453
2733
  /**
2454
2734
  * Recipe for a toolbar: a row of controls with a start, a centre and an end band, and a search.
@@ -2556,7 +2836,7 @@ const recipe = defineSlotRecipe({
2556
2836
  },
2557
2837
  title: {
2558
2838
  ...BAND,
2559
- [`&[${NARROW$1}]`]: { marginInlineEnd: "0" },
2839
+ [`&[${NARROW$2}]`]: { marginInlineEnd: "0" },
2560
2840
  flexShrink: "0",
2561
2841
  fontWeight: "semibold",
2562
2842
  marginInlineEnd: `calc(var(${GAP}) * 2)`
@@ -2622,4 +2902,4 @@ const recipe = defineSlotRecipe({
2622
2902
  }
2623
2903
  });
2624
2904
  //#endregion
2625
- 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 };