@ada-cx/lovelace 1.0.0 → 1.1.0

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 (60) hide show
  1. package/dist/components/Checkbox/Checkbox.css.d.ts +19 -5
  2. package/dist/components/Checkbox/Checkbox.css.js +11 -2
  3. package/dist/components/Checkbox/Checkbox.css.js.map +1 -1
  4. package/dist/components/Checkbox/Checkbox.d.ts +8 -1
  5. package/dist/components/Checkbox/Checkbox.js +12 -34
  6. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  7. package/dist/components/Checkbox/CheckboxIndicator.d.ts +23 -0
  8. package/dist/components/Checkbox/CheckboxIndicator.js +40 -0
  9. package/dist/components/Checkbox/CheckboxIndicator.js.map +1 -0
  10. package/dist/components/Checkbox/index.d.ts +1 -1
  11. package/dist/components/MenuItem/MenuItem.css.d.ts +0 -2
  12. package/dist/components/MenuItem/MenuItem.css.js +2 -2
  13. package/dist/components/MenuItem/MenuItem.css.js.map +1 -1
  14. package/dist/components/MenuItem/MenuItem.d.ts +12 -6
  15. package/dist/components/MenuItem/MenuItem.js +11 -7
  16. package/dist/components/MenuItem/MenuItem.js.map +1 -1
  17. package/dist/components/MenuItem/MenuItemCheckbox.d.ts +12 -0
  18. package/dist/components/MenuItem/MenuItemCheckbox.js +13 -0
  19. package/dist/components/MenuItem/MenuItemCheckbox.js.map +1 -0
  20. package/dist/components/MenuItem/MenuItemLabel.d.ts +15 -0
  21. package/dist/components/MenuItem/MenuItemLabel.js +14 -0
  22. package/dist/components/MenuItem/MenuItemLabel.js.map +1 -0
  23. package/dist/components/MenuItem/MenuItemRadio.d.ts +11 -0
  24. package/dist/components/MenuItem/MenuItemRadio.js +13 -0
  25. package/dist/components/MenuItem/MenuItemRadio.js.map +1 -0
  26. package/dist/components/MenuItem/MenuItemRoot.d.ts +11 -5
  27. package/dist/components/MenuItem/MenuItemRoot.js +16 -7
  28. package/dist/components/MenuItem/MenuItemRoot.js.map +1 -1
  29. package/dist/components/MenuItem/MenuItemToggle.d.ts +12 -0
  30. package/dist/components/MenuItem/MenuItemToggle.js +13 -0
  31. package/dist/components/MenuItem/MenuItemToggle.js.map +1 -0
  32. package/dist/components/MenuItem/index.d.ts +1 -1
  33. package/dist/components/Radio/Radio.css.d.ts +23 -2
  34. package/dist/components/Radio/Radio.css.js +11 -2
  35. package/dist/components/Radio/Radio.css.js.map +1 -1
  36. package/dist/components/Radio/Radio.d.ts +8 -1
  37. package/dist/components/Radio/Radio.js +11 -13
  38. package/dist/components/Radio/Radio.js.map +1 -1
  39. package/dist/components/Radio/RadioIndicator.d.ts +22 -0
  40. package/dist/components/Radio/RadioIndicator.js +18 -0
  41. package/dist/components/Radio/RadioIndicator.js.map +1 -0
  42. package/dist/components/Radio/index.d.ts +1 -1
  43. package/dist/components/Sheet/Sheet.css.js.map +1 -1
  44. package/dist/components/Toggle/Toggle.css.d.ts +16 -5
  45. package/dist/components/Toggle/Toggle.css.js +2 -2
  46. package/dist/components/Toggle/Toggle.css.js.map +1 -1
  47. package/dist/components/Toggle/Toggle.js +3 -5
  48. package/dist/components/Toggle/Toggle.js.map +1 -1
  49. package/dist/components/Toggle/ToggleIndicator.d.ts +21 -0
  50. package/dist/components/Toggle/ToggleIndicator.js +18 -0
  51. package/dist/components/Toggle/ToggleIndicator.js.map +1 -0
  52. package/dist/style.css +1 -1
  53. package/dist/styles/row.d.ts +22 -0
  54. package/package.json +1 -1
  55. package/dist/components/MenuItem/MenuItemLeading.d.ts +0 -11
  56. package/dist/components/MenuItem/MenuItemLeading.js +0 -17
  57. package/dist/components/MenuItem/MenuItemLeading.js.map +0 -1
  58. package/dist/components/MenuItem/MenuItemTrailing.d.ts +0 -14
  59. package/dist/components/MenuItem/MenuItemTrailing.js +0 -17
  60. package/dist/components/MenuItem/MenuItemTrailing.js.map +0 -1
@@ -1,13 +1,27 @@
1
- /** The RAC `Checkbox` label: lays out the box + optional inline label on one row. */
2
- export declare const checkboxRoot: string;
1
+ /**
2
+ * The RAC `Checkbox` label. `inline` lays the box out beside an optional label;
3
+ * `row` is the 40px selectable row Figma draws for a menu item, for a
4
+ * `CheckboxGroup` rendered as a list of options.
5
+ */
6
+ export declare const checkboxRoot: import("@vanilla-extract/recipes").RuntimeFn<{
7
+ variant: {
8
+ inline: {
9
+ display: "inline-flex";
10
+ alignItems: "center";
11
+ gap: "var(--lovelace-color-neutral-0)" | "var(--lovelace-color-neutral-50)" | "var(--lovelace-color-neutral-100)" | "var(--lovelace-color-neutral-200)" | "var(--lovelace-color-neutral-300)" | "var(--lovelace-color-neutral-400)" | "var(--lovelace-color-neutral-500)" | "var(--lovelace-color-neutral-600)" | "var(--lovelace-color-neutral-700)" | "var(--lovelace-color-neutral-800)" | "var(--lovelace-color-neutral-900)" | "var(--lovelace-color-red-50)" | "var(--lovelace-color-orange-50)" | "var(--lovelace-color-green-50)" | "var(--lovelace-color-green-100)" | "var(--lovelace-color-green-200)" | "var(--lovelace-color-green-300)" | "var(--lovelace-color-green-400)" | "var(--lovelace-color-green-500)" | "var(--lovelace-color-green-600)" | "var(--lovelace-color-green-700)" | "var(--lovelace-color-green-800)" | "var(--lovelace-color-green-900)" | "var(--lovelace-color-orange-100)" | "var(--lovelace-color-orange-200)" | "var(--lovelace-color-orange-300)" | "var(--lovelace-color-orange-400)" | "var(--lovelace-color-orange-500)" | "var(--lovelace-color-orange-600)" | "var(--lovelace-color-orange-700)" | "var(--lovelace-color-orange-800)" | "var(--lovelace-color-orange-900)" | "var(--lovelace-color-red-100)" | "var(--lovelace-color-red-200)" | "var(--lovelace-color-red-300)" | "var(--lovelace-color-red-400)" | "var(--lovelace-color-red-500)" | "var(--lovelace-color-red-600)" | "var(--lovelace-color-red-700)" | "var(--lovelace-color-red-800)" | "var(--lovelace-color-red-900)" | "var(--lovelace-spacing-4)" | "var(--lovelace-spacing-8)" | "var(--lovelace-spacing-12)" | "var(--lovelace-spacing-16)" | "var(--lovelace-spacing-20)" | "var(--lovelace-spacing-24)" | "var(--lovelace-spacing-32)" | "var(--lovelace-spacing-40)" | "var(--lovelace-spacing-48)" | "var(--lovelace-font-weight-400)" | "var(--lovelace-font-weight-500)" | "var(--lovelace-font-weight-600)" | "var(--lovelace-color-blue-50)" | "var(--lovelace-color-blue-100)" | "var(--lovelace-color-blue-200)" | "var(--lovelace-color-blue-300)" | "var(--lovelace-color-blue-400)" | "var(--lovelace-color-blue-500)" | "var(--lovelace-color-blue-600)" | "var(--lovelace-color-blue-700)" | "var(--lovelace-color-blue-800)" | "var(--lovelace-color-blue-900)" | "var(--lovelace-font-size-12)" | "var(--lovelace-font-size-14)" | "var(--lovelace-font-size-16)" | "var(--lovelace-font-size-18)" | "var(--lovelace-font-size-20)" | "var(--lovelace-font-size-22)" | "var(--lovelace-font-size-24)" | "var(--lovelace-font-size-26)" | "var(--lovelace-font-size-28)" | "var(--lovelace-font-line-height-16)" | "var(--lovelace-font-line-height-18)" | "var(--lovelace-font-line-height-22)" | "var(--lovelace-font-line-height-24)" | "var(--lovelace-font-line-height-26)" | "var(--lovelace-font-line-height-28)" | "var(--lovelace-font-line-height-30)" | "var(--lovelace-font-line-height-32)" | "var(--lovelace-font-line-height-34)" | "var(--lovelace-border-radius-0)" | "var(--lovelace-p-border-radius-6)" | "var(--lovelace-p-border-radius-10)" | "var(--lovelace-p-border-radius-14)" | "var(--lovelace-p-border-radius-20)" | "var(--lovelace-p-border-radius-24)" | "var(--lovelace-border-radius-999)" | "var(--lovelace-font-paragraph-spacing-4)" | "var(--lovelace-font-paragraph-spacing-6)" | "var(--lovelace-font-paragraph-spacing-8)" | "var(--lovelace-font-paragraph-spacing-10)" | "var(--lovelace-font-paragraph-spacing-12)" | "var(--lovelace-color-accent-50)" | "var(--lovelace-color-accent-100)" | "var(--lovelace-color-accent-200)" | "var(--lovelace-color-accent-300)" | "var(--lovelace-color-accent-400)" | "var(--lovelace-color-accent-500)" | "var(--lovelace-color-accent-600)" | "var(--lovelace-color-accent-700)" | "var(--lovelace-color-accent-800)" | "var(--lovelace-color-accent-900)" | "var(--lovelace-font-family-sans-serif)" | "var(--lovelace-font-family-mono)" | "var(--lovelace-border-width-1)" | "var(--lovelace-border-width-2)" | "var(--lovelace-dimension-16)" | "var(--lovelace-dimension-20)" | "var(--lovelace-dimension-22)" | "var(--lovelace-dimension-24)" | "var(--lovelace-dimension-32)" | "var(--lovelace-dimension-36)" | "var(--lovelace-color-content-default)" | "var(--lovelace-color-content-secondary)" | "var(--lovelace-color-content-secondary-inverse)" | "var(--lovelace-color-content-disabled)" | "var(--lovelace-color-content-inverse)" | "var(--lovelace-color-background-default)" | "var(--lovelace-color-background-secondary)" | "var(--lovelace-color-background-tertiary)" | "var(--lovelace-color-background-quaternary)" | "var(--lovelace-color-background-disabled)" | "var(--lovelace-color-background-inverse)" | "var(--lovelace-color-background-neutral-overlay)" | "var(--lovelace-color-border-default)" | "var(--lovelace-color-border-medium)" | "var(--lovelace-color-border-strong)" | "var(--lovelace-color-content-link)" | "var(--lovelace-color-background-destructive)" | "var(--lovelace-color-content-destructive)" | "var(--lovelace-color-background-destructive-light)" | "var(--lovelace-color-border-destructive)" | "var(--lovelace-color-content-on-destructive)" | "var(--lovelace-color-content-warning)" | "var(--lovelace-color-background-warning)" | "var(--lovelace-color-background-warning-light)" | "var(--lovelace-color-border-warning)" | "var(--lovelace-color-content-success)" | "var(--lovelace-color-background-success)" | "var(--lovelace-color-background-success-light)" | "var(--lovelace-color-border-success)" | "var(--lovelace-color-content-accent)" | "var(--lovelace-color-content-on-accent)" | "var(--lovelace-color-content-on-scrim)" | "var(--lovelace-color-background-accent)" | "var(--lovelace-color-background-highlight-overlay)" | "var(--lovelace-color-border-focus)" | "var(--lovelace-color-border-accent)" | "var(--lovelace-color-border-highlight)" | "var(--lovelace-font-weight-regular)" | "var(--lovelace-font-size-caption)" | "var(--lovelace-line-height-caption)" | "var(--lovelace-paragraph-spacing-caption)" | "var(--lovelace-paragraph-spacing-body)" | "var(--lovelace-paragraph-spacing-title)" | "var(--lovelace-line-height-body)" | "var(--lovelace-line-height-title-small)" | "var(--lovelace-line-height-title-large)" | "var(--lovelace-font-size-body)" | "var(--lovelace-font-size-title-small)" | "var(--lovelace-font-size-title-large)" | "var(--lovelace-font-weight-medium)" | "var(--lovelace-font-weight-semi-bold)" | "var(--lovelace-font-family-body)" | "var(--lovelace-font-family-heading)" | "var(--lovelace-font-family-code)" | "var(--lovelace-border-radius-none)" | "var(--lovelace-border-radius-6)" | "var(--lovelace-border-radius-10)" | "var(--lovelace-border-radius-14)" | "var(--lovelace-border-radius-20)" | "var(--lovelace-border-radius-24)" | "var(--lovelace-border-radius-full)" | "var(--lovelace-padding-4)" | "var(--lovelace-padding-8)" | "var(--lovelace-padding-12)" | "var(--lovelace-gap-4)" | "var(--lovelace-padding-16)" | "var(--lovelace-gap-8)" | "var(--lovelace-gap-12)" | "var(--lovelace-gap-16)" | "var(--lovelace-gap-20)" | "var(--lovelace-padding-20)" | "var(--lovelace-border-width-default)" | "var(--lovelace-border-width-focus)" | "var(--lovelace-opacity-state-hover)" | "var(--lovelace-opacity-state-focus)" | "var(--lovelace-opacity-state-pressed)" | "var(--lovelace-icon-size-sm)" | "var(--lovelace-icon-size-md)" | "var(--lovelace-icon-size-control)" | "var(--lovelace-icon-size-lg)" | "var(--lovelace-easing-standard)" | "var(--lovelace-easing-emphasized)" | "var(--lovelace-easing-decelerate)" | "var(--lovelace-easing-accelerate)" | "var(--lovelace-duration-fast)" | "var(--lovelace-duration-medium)" | "var(--lovelace-duration-slow)" | "var(--lovelace-message-user-background)" | "var(--lovelace-message-user-content)" | "var(--lovelace-button-primary-background)" | "var(--lovelace-button-primary-content)" | "var(--lovelace-header-background)" | "var(--lovelace-pill-content-primary)" | "var(--lovelace-header-content)" | "var(--lovelace-chip-background-selected)" | "var(--lovelace-chatfab-background)" | "var(--lovelace-chatfab-content)" | "var(--lovelace-composer-background)" | "var(--lovelace-composer-border-default)" | "var(--lovelace-composer-content-default)" | "var(--lovelace-composer-content-secondary)" | "var(--lovelace-composer-border-focus)" | "var(--lovelace-composer-border-active)" | "var(--lovelace-avatar-background)" | "var(--lovelace-avatar-content)" | "var(--lovelace-scrollmarker-background)" | "var(--lovelace-scrollmarker-content)" | "var(--lovelace-send-button-background)" | "var(--lovelace-chat-background)" | "var(--lovelace-border-radius-button)" | "var(--lovelace-border-radius-message)" | "var(--lovelace-border-radius-input)" | "var(--lovelace-border-radius-composer)" | "var(--lovelace-border-radius-avatar)" | "var(--lovelace-border-radius-pill)" | "var(--lovelace-border-radius-media-preview)" | "var(--lovelace-border-radius-container)";
12
+ };
13
+ row: (string | import("@vanilla-extract/css").StyleRule)[];
14
+ };
15
+ }>;
3
16
  /**
4
17
  * The 24px indicator. Its geometry is fixed in every state — a rigid `border-box`
5
18
  * square with an always-present 1px border (transparent when filled) and a
6
19
  * `box-shadow` focus ring — so selecting/focusing never reflows it.
7
20
  *
8
- * Selection/interaction state lives on the RAC label (`checkboxRoot`), so the
9
- * state rules below are ancestor selectors driven from it. `color` is the inverse
10
- * content color: it feeds both the glyph stroke and the `currentColor` state-layer
21
+ * Selection/interaction state lives on the host element (the RAC label, or a
22
+ * `MenuItem` row), so the state rules below are child selectors driven from
23
+ * whichever host carries React Aria's `data-*`. `color` is the inverse content
24
+ * color: it feeds both the glyph stroke and the `currentColor` state-layer
11
25
  * overlay, so the overlay is invisible over the light unchecked box (Figma changes
12
26
  * only the border on hover) yet lightens the dark filled box.
13
27
  */
@@ -1,7 +1,16 @@
1
+ import { createRuntimeFn as e } from "../../vendor/@vanilla-extract/recipes/dist/createRuntimeFn-62c9670f.esm.js";
1
2
  /* empty css */
2
3
  //#region src/components/Checkbox/Checkbox.css.ts
3
- var e = "s7h2sn0", t = "s7h2sn1", n = "s7h2sn2";
4
+ var t = e({
5
+ defaultClassName: "s7h2sn1",
6
+ variantClassNames: { variant: {
7
+ inline: "s7h2sn2",
8
+ row: "s7h2sn3 s7h2sn0"
9
+ } },
10
+ defaultVariants: { variant: "inline" },
11
+ compoundVariants: []
12
+ }), n = "s7h2sn4", r = "s7h2sn5";
4
13
  //#endregion
5
- export { t as checkboxBox, n as checkboxGlyph, e as checkboxRoot };
14
+ export { n as checkboxBox, r as checkboxGlyph, t as checkboxRoot };
6
15
 
7
16
  //# sourceMappingURL=Checkbox.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.css.js","names":[],"sources":["../../../src/components/Checkbox/Checkbox.css.ts"],"sourcesContent":["import { globalStyle, style } from \"@vanilla-extract/css\";\nimport { t } from \"../../tokens/index.js\";\n\nconst STATE_OPACITY = { hover: 0.08, focus: 0.1, pressed: 0.1 } as const;\n\n// 24px box + 16px glyph mirror Figma's fixed frame sizes (button-size/xs,\n// icon-size/md), which the token set does not expose as spacing values.\nconst BOX_SIZE = \"24px\";\nconst GLYPH_SIZE = \"16px\";\n\n/** The RAC `Checkbox` label: lays out the box + optional inline label on one row. */\nexport const checkboxRoot = style({\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tgap: t(\"gap-12\"),\n\tfontFamily: t(\"font-family-body\"),\n\tfontWeight: t(\"font-weight-regular\"),\n\tfontSize: t(\"font-size-body\"),\n\tlineHeight: t(\"line-height-body\"),\n\tcolor: t(\"color-content-default\"),\n\tcursor: \"pointer\",\n\tuserSelect: \"none\",\n\toutline: \"none\",\n\tselectors: {\n\t\t\"&[data-disabled]\": {\n\t\t\tcursor: \"not-allowed\",\n\t\t\tcolor: t(\"color-content-disabled\"),\n\t\t},\n\t},\n});\n\n/**\n * The 24px indicator. Its geometry is fixed in every state — a rigid `border-box`\n * square with an always-present 1px border (transparent when filled) and a\n * `box-shadow` focus ring — so selecting/focusing never reflows it.\n *\n * Selection/interaction state lives on the RAC label (`checkboxRoot`), so the\n * state rules below are ancestor selectors driven from it. `color` is the inverse\n * content color: it feeds both the glyph stroke and the `currentColor` state-layer\n * overlay, so the overlay is invisible over the light unchecked box (Figma changes\n * only the border on hover) yet lightens the dark filled box.\n */\nexport const checkboxBox = style({\n\tposition: \"relative\",\n\tisolation: \"isolate\",\n\tboxSizing: \"border-box\",\n\tflexShrink: 0,\n\twidth: BOX_SIZE,\n\theight: BOX_SIZE,\n\tborderRadius: t(\"border-radius-6\"),\n\tborderStyle: \"solid\",\n\tborderWidth: t(\"border-width-default\"),\n\tborderColor: t(\"color-border-default\"),\n\tbackgroundColor: t(\"color-background-default\"),\n\tcolor: t(\"color-content-inverse\"),\n\t// No background-color transition, so the fill flips instantly and lands with the glyph.\n\ttransition: \"border-color 120ms ease, box-shadow 120ms ease\",\n\t\"::after\": {\n\t\tcontent: '\"\"',\n\t\tposition: \"absolute\",\n\t\tinset: 0,\n\t\tborderRadius: \"inherit\",\n\t\tbackgroundColor: \"currentColor\",\n\t\topacity: 0,\n\t\tpointerEvents: \"none\",\n\t\tzIndex: -1,\n\t\ttransition: \"opacity 120ms ease\",\n\t},\n});\n\n/**\n * Checkmark / dash glyph — absolutely centered and toggled by opacity, never\n * in-flow, so revealing it can never shift the box.\n */\nexport const checkboxGlyph = style({\n\tposition: \"absolute\",\n\tinset: 0,\n\tmargin: \"auto\",\n\twidth: GLYPH_SIZE,\n\theight: GLYPH_SIZE,\n\tcolor: \"currentColor\",\n\topacity: 0,\n\tpointerEvents: \"none\",\n});\n\n// Border goes transparent when filled so it folds into the fill (no ring).\nglobalStyle(\n\t`${checkboxRoot}[data-selected] ${checkboxBox}, ${checkboxRoot}[data-indeterminate] ${checkboxBox}`,\n\t{\n\t\tbackgroundColor: t(\"color-background-inverse\"),\n\t\tborderColor: \"transparent\",\n\t},\n);\n\n// Unchecked hover darkens the border (Figma color/border/medium).\nglobalStyle(\n\t`${checkboxRoot}[data-hovered]:not([data-disabled]):not([data-selected]):not([data-indeterminate]) ${checkboxBox}`,\n\t{ borderColor: t(\"color-border-medium\") },\n);\n\n// State layer — currentColor overlay at per-state opacity, tracking box content color.\nglobalStyle(\n\t`${checkboxRoot}[data-hovered]:not([data-disabled]) ${checkboxBox}::after`,\n\t{ opacity: STATE_OPACITY.hover },\n);\nglobalStyle(\n\t`${checkboxRoot}[data-focus-visible]:not([data-disabled]) ${checkboxBox}::after`,\n\t{ opacity: STATE_OPACITY.focus },\n);\nglobalStyle(\n\t`${checkboxRoot}[data-pressed]:not([data-disabled]) ${checkboxBox}::after`,\n\t{ opacity: STATE_OPACITY.pressed },\n);\n\n// Focus ring — box-shadow, so it never changes the box's size.\nglobalStyle(\n\t`${checkboxRoot}[data-focus-visible]:not([data-disabled]) ${checkboxBox}`,\n\t{ boxShadow: `0 0 0 ${t(\"border-width-focus\")} ${t(\"color-border-focus\")}` },\n);\n\nglobalStyle(\n\t`${checkboxRoot}[data-focus-visible]:not([data-disabled]) ${checkboxBox}`,\n\t{\n\t\t\"@media\": {\n\t\t\t\"(forced-colors: active)\": {\n\t\t\t\toutline: \"2px solid Highlight\",\n\t\t\t\toutlineOffset: \"2px\",\n\t\t\t},\n\t\t},\n\t},\n);\n\n// Disabled wins over the filled rule: light fill, default border, faded glyph\n// (Figma color/content/disabled).\nglobalStyle(`${checkboxRoot}[data-disabled] ${checkboxBox}`, {\n\tbackgroundColor: t(\"color-background-disabled\"),\n\tborderColor: t(\"color-border-default\"),\n\tcolor: t(\"color-content-disabled\"),\n});\n\n// Reveal the matching glyph. Dash wins for the mixed state; the check shows only\n// when selected and not indeterminate.\nglobalStyle(\n\t`${checkboxRoot}[data-selected]:not([data-indeterminate]) ${checkboxGlyph}[data-glyph=\"check\"]`,\n\t{ opacity: 1 },\n);\nglobalStyle(\n\t`${checkboxRoot}[data-indeterminate] ${checkboxGlyph}[data-glyph=\"dash\"]`,\n\t{ opacity: 1 },\n);\n"],"mappings":""}
1
+ {"version":3,"file":"Checkbox.css.js","names":[],"sources":["../../../src/components/Checkbox/Checkbox.css.ts"],"sourcesContent":["import { globalStyle, style } from \"@vanilla-extract/css\";\nimport { recipe } from \"@vanilla-extract/recipes\";\nimport { rowFrame, rowSlotRules } from \"../../styles/row.js\";\nimport { t } from \"../../tokens/index.js\";\n\n// 24px box + 16px glyph mirror Figma's fixed frame sizes (button-size/xs,\n// icon-size/md), which the token set does not expose as spacing values.\nconst BOX_SIZE = \"24px\";\nconst GLYPH_SIZE = \"16px\";\n\n// Empty handle classes: a recipe can't target a descendant, so the row variant's\n// slot rules are attached to a stable class instead (same trick as Button's base).\nconst checkboxRowBase = style({});\n\n/**\n * The RAC `Checkbox` label. `inline` lays the box out beside an optional label;\n * `row` is the 40px selectable row Figma draws for a menu item, for a\n * `CheckboxGroup` rendered as a list of options.\n */\nexport const checkboxRoot = recipe({\n\tbase: {\n\t\tfontFamily: t(\"font-family-body\"),\n\t\tfontWeight: t(\"font-weight-regular\"),\n\t\tfontSize: t(\"font-size-body\"),\n\t\tlineHeight: t(\"line-height-body\"),\n\t\tcolor: t(\"color-content-default\"),\n\t\tcursor: \"pointer\",\n\t\tuserSelect: \"none\",\n\t\toutline: \"none\",\n\t\tselectors: {\n\t\t\t\"&[data-disabled]\": {\n\t\t\t\tcursor: \"not-allowed\",\n\t\t\t\tcolor: t(\"color-content-disabled\"),\n\t\t\t},\n\t\t},\n\t},\n\tvariants: {\n\t\tvariant: {\n\t\t\tinline: {\n\t\t\t\tdisplay: \"inline-flex\",\n\t\t\t\talignItems: \"center\",\n\t\t\t\tgap: t(\"gap-12\"),\n\t\t\t},\n\t\t\trow: [checkboxRowBase, rowFrame],\n\t\t},\n\t},\n\tdefaultVariants: { variant: \"inline\" },\n});\n\nglobalStyle(`${checkboxRowBase} > [data-slot=\"icon\"]`, rowSlotRules.icon);\nglobalStyle(`${checkboxRowBase} > [data-slot=\"label\"]`, rowSlotRules.label);\n\n/**\n * The 24px indicator. Its geometry is fixed in every state — a rigid `border-box`\n * square with an always-present 1px border (transparent when filled) and a\n * `box-shadow` focus ring — so selecting/focusing never reflows it.\n *\n * Selection/interaction state lives on the host element (the RAC label, or a\n * `MenuItem` row), so the state rules below are child selectors driven from\n * whichever host carries React Aria's `data-*`. `color` is the inverse content\n * color: it feeds both the glyph stroke and the `currentColor` state-layer\n * overlay, so the overlay is invisible over the light unchecked box (Figma changes\n * only the border on hover) yet lightens the dark filled box.\n */\nexport const checkboxBox = style({\n\tposition: \"relative\",\n\tisolation: \"isolate\",\n\tboxSizing: \"border-box\",\n\tflexShrink: 0,\n\twidth: BOX_SIZE,\n\theight: BOX_SIZE,\n\tborderRadius: t(\"border-radius-6\"),\n\tborderStyle: \"solid\",\n\tborderWidth: t(\"border-width-default\"),\n\tborderColor: t(\"color-border-default\"),\n\tbackgroundColor: t(\"color-background-default\"),\n\tcolor: t(\"color-content-inverse\"),\n\t// No background-color transition, so the fill flips instantly and lands with the glyph.\n\ttransitionProperty: \"border-color, box-shadow\",\n\ttransitionDuration: t(\"duration-fast\"),\n\ttransitionTimingFunction: t(\"easing-standard\"),\n\t\"::after\": {\n\t\tcontent: '\"\"',\n\t\tposition: \"absolute\",\n\t\tinset: 0,\n\t\tborderRadius: \"inherit\",\n\t\tbackgroundColor: \"currentColor\",\n\t\topacity: 0,\n\t\tpointerEvents: \"none\",\n\t\tzIndex: -1,\n\t\ttransition: `opacity ${t(\"duration-fast\")} ${t(\"easing-standard\")}`,\n\t},\n});\n\n/**\n * Checkmark / dash glyph — absolutely centered and toggled by opacity, never\n * in-flow, so revealing it can never shift the box.\n */\nexport const checkboxGlyph = style({\n\tposition: \"absolute\",\n\tinset: 0,\n\tmargin: \"auto\",\n\twidth: GLYPH_SIZE,\n\theight: GLYPH_SIZE,\n\tcolor: \"currentColor\",\n\topacity: 0,\n\tpointerEvents: \"none\",\n});\n\n// Selection and disabled are host-agnostic: any element carrying React Aria's\n// `data-*` drives the box directly below it. Interaction (hover border, state\n// layer, focus ring) additionally requires `[data-state-layer]`, which the\n// indicator sets only when it is the sole affordance — inside a row the row\n// paints those itself.\n\n// Border goes transparent when filled so it folds into the fill (no ring).\nglobalStyle(\n\t`[data-selected] > ${checkboxBox}, [data-indeterminate] > ${checkboxBox}`,\n\t{\n\t\tbackgroundColor: t(\"color-background-inverse\"),\n\t\tborderColor: \"transparent\",\n\t},\n);\n\n// Unchecked hover darkens the border (Figma color/border/medium).\nglobalStyle(\n\t`[data-hovered]:not([data-disabled]):not([data-selected]):not([data-indeterminate]) > ${checkboxBox}[data-state-layer]`,\n\t{ borderColor: t(\"color-border-medium\") },\n);\n\n// State layer — currentColor overlay at per-state opacity, tracking box content color.\nglobalStyle(\n\t`[data-hovered]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-hover\") },\n);\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-focus\") },\n);\nglobalStyle(\n\t`[data-pressed]:not([data-disabled]) > ${checkboxBox}[data-state-layer]::after`,\n\t{ opacity: t(\"opacity-state-pressed\") },\n);\n\n// Focus ring — box-shadow, so it never changes the box's size.\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]`,\n\t{ boxShadow: `0 0 0 ${t(\"border-width-focus\")} ${t(\"color-border-focus\")}` },\n);\n\nglobalStyle(\n\t`[data-focus-visible]:not([data-disabled]) > ${checkboxBox}[data-state-layer]`,\n\t{\n\t\t\"@media\": {\n\t\t\t\"(forced-colors: active)\": {\n\t\t\t\toutline: \"2px solid Highlight\",\n\t\t\t\toutlineOffset: \"2px\",\n\t\t\t},\n\t\t},\n\t},\n);\n\n// Disabled wins over the filled rule: light fill, default border, faded glyph\n// (Figma color/content/disabled).\nglobalStyle(`[data-disabled] > ${checkboxBox}`, {\n\tbackgroundColor: t(\"color-background-disabled\"),\n\tborderColor: t(\"color-border-default\"),\n\tcolor: t(\"color-content-disabled\"),\n});\n\n// Reveal the matching glyph. Dash wins for the mixed state; the check shows only\n// when selected and not indeterminate.\nglobalStyle(\n\t`[data-selected]:not([data-indeterminate]) > ${checkboxBox} > ${checkboxGlyph}[data-glyph=\"check\"]`,\n\t{ opacity: 1 },\n);\nglobalStyle(\n\t`[data-indeterminate] > ${checkboxBox} > ${checkboxGlyph}[data-glyph=\"dash\"]`,\n\t{ opacity: 1 },\n);\n"],"mappings":""}
@@ -1,6 +1,13 @@
1
1
  import type { CSSProperties, ReactNode, Ref } from "react";
2
2
  import type { CheckboxProps as AriaCheckboxProps } from "react-aria-components";
3
+ export type CheckboxVariant = "inline" | "row";
3
4
  export interface CheckboxProps extends Omit<AriaCheckboxProps, "children" | "className" | "style"> {
5
+ /**
6
+ * `inline` (default) sits the box beside its label at content width. `row`
7
+ * renders the 40px selectable row Figma draws for a menu item — use it for a
8
+ * `CheckboxGroup` presented as a list of options.
9
+ */
10
+ variant?: CheckboxVariant;
4
11
  className?: string;
5
12
  style?: CSSProperties;
6
13
  ref?: Ref<HTMLLabelElement>;
@@ -19,4 +26,4 @@ export interface CheckboxProps extends Omit<AriaCheckboxProps, "children" | "cla
19
26
  * renders the mixed state. Interaction states (hover/focus/pressed/disabled) and RTL
20
27
  * are handled by RAC `data-*` and ambient `dir` — not props.
21
28
  */
22
- export declare function Checkbox({ className, children, ...rest }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
29
+ export declare function Checkbox({ variant, className, children, ...rest }: CheckboxProps): import("react/jsx-runtime").JSX.Element;
@@ -1,42 +1,20 @@
1
1
  import { cx as e } from "../../utils/cx.js";
2
- import { checkboxBox as t, checkboxGlyph as n, checkboxRoot as r } from "./Checkbox.css.js";
3
- import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
- import { Checkbox as o } from "react-aria-components";
2
+ import { checkboxRoot as t } from "./Checkbox.css.js";
3
+ import { CheckboxIndicator as n } from "./CheckboxIndicator.js";
4
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
5
+ import { Checkbox as a } from "react-aria-components";
5
6
  //#region src/components/Checkbox/Checkbox.tsx
6
- function s({ className: s, children: c, ...l }) {
7
- return /* @__PURE__ */ a(o, {
7
+ function o({ variant: o = "inline", className: s, children: c, ...l }) {
8
+ return /* @__PURE__ */ i(a, {
8
9
  ...l,
9
- className: e(r, s),
10
- children: [/* @__PURE__ */ a("span", {
11
- "data-slot": "box",
12
- className: t,
13
- children: [/* @__PURE__ */ i("svg", {
14
- "data-glyph": "check",
15
- className: n,
16
- viewBox: "0 0 16 16",
17
- fill: "none",
18
- stroke: "currentColor",
19
- strokeWidth: "2",
20
- strokeLinecap: "round",
21
- strokeLinejoin: "round",
22
- "aria-hidden": "true",
23
- children: /* @__PURE__ */ i("path", { d: "M3.5 8L6.5 11L12.5 5" })
24
- }), /* @__PURE__ */ i("svg", {
25
- "data-glyph": "dash",
26
- className: n,
27
- viewBox: "0 0 16 16",
28
- fill: "none",
29
- stroke: "currentColor",
30
- strokeWidth: "2",
31
- strokeLinecap: "round",
32
- strokeLinejoin: "round",
33
- "aria-hidden": "true",
34
- children: /* @__PURE__ */ i("path", { d: "M4 8H12" })
35
- })]
36
- }), c]
10
+ className: e(t({ variant: o }), s),
11
+ children: [/* @__PURE__ */ r(n, { hasStateLayer: o === "inline" }), c != null && typeof c != "boolean" && /* @__PURE__ */ r("span", {
12
+ "data-slot": "label",
13
+ children: c
14
+ })]
37
15
  });
38
16
  }
39
17
  //#endregion
40
- export { s as Checkbox };
18
+ export { o as Checkbox };
41
19
 
42
20
  //# sourceMappingURL=Checkbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.js","names":[],"sources":["../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode, Ref } from \"react\";\nimport type { CheckboxProps as AriaCheckboxProps } from \"react-aria-components\";\nimport { Checkbox as AriaCheckbox } from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport { checkboxBox, checkboxGlyph, checkboxRoot } from \"./Checkbox.css.js\";\n\nexport interface CheckboxProps\n\textends Omit<AriaCheckboxProps, \"children\" | \"className\" | \"style\"> {\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tref?: Ref<HTMLLabelElement>;\n\t/**\n\t * Inline label. Omit for a standalone box — then pass `aria-label`\n\t * (or `aria-labelledby`) so the control has an accessible name.\n\t */\n\tchildren?: ReactNode;\n}\n\n/**\n * Selection control with an optional inline label. Use to select any number of\n * options, or as a single on/off toggle; for one choice among mutually exclusive\n * options use Radio.\n *\n * Selection is `isSelected`/`defaultSelected`/`onChange` (React Aria); `isIndeterminate`\n * renders the mixed state. Interaction states (hover/focus/pressed/disabled) and RTL\n * are handled by RAC `data-*` and ambient `dir` — not props.\n */\nexport function Checkbox({ className, children, ...rest }: CheckboxProps) {\n\treturn (\n\t\t<AriaCheckbox {...rest} className={cx(checkboxRoot, className)}>\n\t\t\t<span data-slot=\"box\" className={checkboxBox}>\n\t\t\t\t<svg\n\t\t\t\t\tdata-glyph=\"check\"\n\t\t\t\t\tclassName={checkboxGlyph}\n\t\t\t\t\tviewBox=\"0 0 16 16\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<path d=\"M3.5 8L6.5 11L12.5 5\" />\n\t\t\t\t</svg>\n\t\t\t\t<svg\n\t\t\t\t\tdata-glyph=\"dash\"\n\t\t\t\t\tclassName={checkboxGlyph}\n\t\t\t\t\tviewBox=\"0 0 16 16\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t>\n\t\t\t\t\t<path d=\"M4 8H12\" />\n\t\t\t\t</svg>\n\t\t\t</span>\n\t\t\t{children}\n\t\t</AriaCheckbox>\n\t);\n}\n"],"mappings":";;;;;AA2BA,SAAgB,EAAS,EAAE,cAAW,aAAU,GAAG,KAAuB;AACzE,QACC,kBAAC,GAAD;EAAc,GAAI;EAAM,WAAW,EAAG,GAAc,EAAU;YAA9D,CACC,kBAAC,QAAD;GAAM,aAAU;GAAM,WAAW;aAAjC,CACC,kBAAC,OAAD;IACC,cAAW;IACX,WAAW;IACX,SAAQ;IACR,MAAK;IACL,QAAO;IACP,aAAY;IACZ,eAAc;IACd,gBAAe;IACf,eAAY;cAEZ,kBAAC,QAAD,EAAM,GAAE,wBAAyB,CAAA;IAC5B,CAAA,EACN,kBAAC,OAAD;IACC,cAAW;IACX,WAAW;IACX,SAAQ;IACR,MAAK;IACL,QAAO;IACP,aAAY;IACZ,eAAc;IACd,gBAAe;IACf,eAAY;cAEZ,kBAAC,QAAD,EAAM,GAAE,WAAY,CAAA;IACf,CAAA,CACA;MACN,EACa"}
1
+ {"version":3,"file":"Checkbox.js","names":[],"sources":["../../../src/components/Checkbox/Checkbox.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode, Ref } from \"react\";\nimport type { CheckboxProps as AriaCheckboxProps } from \"react-aria-components\";\nimport { Checkbox as AriaCheckbox } from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport { checkboxRoot } from \"./Checkbox.css.js\";\nimport { CheckboxIndicator } from \"./CheckboxIndicator.js\";\n\nexport type CheckboxVariant = \"inline\" | \"row\";\n\nexport interface CheckboxProps\n\textends Omit<AriaCheckboxProps, \"children\" | \"className\" | \"style\"> {\n\t/**\n\t * `inline` (default) sits the box beside its label at content width. `row`\n\t * renders the 40px selectable row Figma draws for a menu item — use it for a\n\t * `CheckboxGroup` presented as a list of options.\n\t */\n\tvariant?: CheckboxVariant;\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tref?: Ref<HTMLLabelElement>;\n\t/**\n\t * Inline label. Omit for a standalone box — then pass `aria-label`\n\t * (or `aria-labelledby`) so the control has an accessible name.\n\t */\n\tchildren?: ReactNode;\n}\n\n/**\n * Selection control with an optional inline label. Use to select any number of\n * options, or as a single on/off toggle; for one choice among mutually exclusive\n * options use Radio.\n *\n * Selection is `isSelected`/`defaultSelected`/`onChange` (React Aria); `isIndeterminate`\n * renders the mixed state. Interaction states (hover/focus/pressed/disabled) and RTL\n * are handled by RAC `data-*` and ambient `dir` — not props.\n */\nexport function Checkbox({\n\tvariant = \"inline\",\n\tclassName,\n\tchildren,\n\t...rest\n}: CheckboxProps) {\n\treturn (\n\t\t<AriaCheckbox\n\t\t\t{...rest}\n\t\t\tclassName={cx(checkboxRoot({ variant }), className)}\n\t\t>\n\t\t\t<CheckboxIndicator hasStateLayer={variant === \"inline\"} />\n\t\t\t{children != null && typeof children !== \"boolean\" && (\n\t\t\t\t<span data-slot=\"label\">{children}</span>\n\t\t\t)}\n\t\t</AriaCheckbox>\n\t);\n}\n"],"mappings":";;;;;;AAoCA,SAAgB,EAAS,EACxB,aAAU,UACV,cACA,aACA,GAAG,KACc;AACjB,QACC,kBAAC,GAAD;EACC,GAAI;EACJ,WAAW,EAAG,EAAa,EAAE,YAAS,CAAC,EAAE,EAAU;YAFpD,CAIC,kBAAC,GAAD,EAAmB,eAAe,MAAY,UAAY,CAAA,EACzD,KAAY,QAAQ,OAAO,KAAa,aACxC,kBAAC,QAAD;GAAM,aAAU;GAAS;GAAgB,CAAA,CAE5B"}
@@ -0,0 +1,23 @@
1
+ import type { Ref } from "react";
2
+ export interface CheckboxIndicatorProps {
3
+ /**
4
+ * Draw the box's own hover/focus/pressed state layer and focus ring. True for a
5
+ * standalone `Checkbox`, where the box is the only affordance; false inside a
6
+ * row, which draws those on the row itself — leaving it true there would paint
7
+ * both.
8
+ */
9
+ hasStateLayer?: boolean;
10
+ className?: string;
11
+ ref?: Ref<HTMLSpanElement>;
12
+ }
13
+ /**
14
+ * The 24px checkbox box and its check/dash glyphs, with no control of its own.
15
+ *
16
+ * Selection and disabled state are read from whichever ancestor element carries
17
+ * React Aria's `data-selected` / `data-indeterminate` / `data-disabled` — the RAC
18
+ * `Checkbox` label, or a `MenuItem` row — so the same markup and the same styles
19
+ * serve both hosts and cannot drift apart. It must stay a **direct** child of that
20
+ * element; the state rules use a child selector so an unrelated selected ancestor
21
+ * can't reach in.
22
+ */
23
+ export declare function CheckboxIndicator({ hasStateLayer, className, ref, }: CheckboxIndicatorProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,40 @@
1
+ import { cx as e } from "../../utils/cx.js";
2
+ import { checkboxBox as t, checkboxGlyph as n } from "./Checkbox.css.js";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
+ //#region src/components/Checkbox/CheckboxIndicator.tsx
5
+ function a({ hasStateLayer: a = !0, className: o, ref: s }) {
6
+ return /* @__PURE__ */ i("span", {
7
+ ref: s,
8
+ "data-slot": "indicator",
9
+ "data-state-layer": a || void 0,
10
+ className: e(t, o),
11
+ "aria-hidden": "true",
12
+ children: [/* @__PURE__ */ r("svg", {
13
+ "data-glyph": "check",
14
+ className: n,
15
+ viewBox: "0 0 16 16",
16
+ fill: "none",
17
+ stroke: "currentColor",
18
+ strokeWidth: "2",
19
+ strokeLinecap: "round",
20
+ strokeLinejoin: "round",
21
+ "aria-hidden": "true",
22
+ children: /* @__PURE__ */ r("path", { d: "M3.5 8L6.5 11L12.5 5" })
23
+ }), /* @__PURE__ */ r("svg", {
24
+ "data-glyph": "dash",
25
+ className: n,
26
+ viewBox: "0 0 16 16",
27
+ fill: "none",
28
+ stroke: "currentColor",
29
+ strokeWidth: "2",
30
+ strokeLinecap: "round",
31
+ strokeLinejoin: "round",
32
+ "aria-hidden": "true",
33
+ children: /* @__PURE__ */ r("path", { d: "M4 8H12" })
34
+ })]
35
+ });
36
+ }
37
+ //#endregion
38
+ export { a as CheckboxIndicator };
39
+
40
+ //# sourceMappingURL=CheckboxIndicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckboxIndicator.js","names":[],"sources":["../../../src/components/Checkbox/CheckboxIndicator.tsx"],"sourcesContent":["import type { Ref } from \"react\";\nimport { cx } from \"../../utils/cx.js\";\nimport { checkboxBox, checkboxGlyph } from \"./Checkbox.css.js\";\n\nexport interface CheckboxIndicatorProps {\n\t/**\n\t * Draw the box's own hover/focus/pressed state layer and focus ring. True for a\n\t * standalone `Checkbox`, where the box is the only affordance; false inside a\n\t * row, which draws those on the row itself — leaving it true there would paint\n\t * both.\n\t */\n\thasStateLayer?: boolean;\n\tclassName?: string;\n\tref?: Ref<HTMLSpanElement>;\n}\n\n/**\n * The 24px checkbox box and its check/dash glyphs, with no control of its own.\n *\n * Selection and disabled state are read from whichever ancestor element carries\n * React Aria's `data-selected` / `data-indeterminate` / `data-disabled` — the RAC\n * `Checkbox` label, or a `MenuItem` row — so the same markup and the same styles\n * serve both hosts and cannot drift apart. It must stay a **direct** child of that\n * element; the state rules use a child selector so an unrelated selected ancestor\n * can't reach in.\n */\nexport function CheckboxIndicator({\n\thasStateLayer = true,\n\tclassName,\n\tref,\n}: CheckboxIndicatorProps) {\n\treturn (\n\t\t<span\n\t\t\tref={ref}\n\t\t\tdata-slot=\"indicator\"\n\t\t\tdata-state-layer={hasStateLayer || undefined}\n\t\t\tclassName={cx(checkboxBox, className)}\n\t\t\taria-hidden=\"true\"\n\t\t>\n\t\t\t<svg\n\t\t\t\tdata-glyph=\"check\"\n\t\t\t\tclassName={checkboxGlyph}\n\t\t\t\tviewBox=\"0 0 16 16\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<path d=\"M3.5 8L6.5 11L12.5 5\" />\n\t\t\t</svg>\n\t\t\t<svg\n\t\t\t\tdata-glyph=\"dash\"\n\t\t\t\tclassName={checkboxGlyph}\n\t\t\t\tviewBox=\"0 0 16 16\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tstroke=\"currentColor\"\n\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\taria-hidden=\"true\"\n\t\t\t>\n\t\t\t\t<path d=\"M4 8H12\" />\n\t\t\t</svg>\n\t\t</span>\n\t);\n}\n"],"mappings":";;;;AA0BA,SAAgB,EAAkB,EACjC,mBAAgB,IAChB,cACA,UAC0B;AAC1B,QACC,kBAAC,QAAD;EACM;EACL,aAAU;EACV,oBAAkB,KAAiB,KAAA;EACnC,WAAW,EAAG,GAAa,EAAU;EACrC,eAAY;YALb,CAOC,kBAAC,OAAD;GACC,cAAW;GACX,WAAW;GACX,SAAQ;GACR,MAAK;GACL,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;GACf,eAAY;aAEZ,kBAAC,QAAD,EAAM,GAAE,wBAAyB,CAAA;GAC5B,CAAA,EACN,kBAAC,OAAD;GACC,cAAW;GACX,WAAW;GACX,SAAQ;GACR,MAAK;GACL,QAAO;GACP,aAAY;GACZ,eAAc;GACd,gBAAe;GACf,eAAY;aAEZ,kBAAC,QAAD,EAAM,GAAE,WAAY,CAAA;GACf,CAAA,CACA"}
@@ -1 +1 @@
1
- export { Checkbox, type CheckboxProps } from "./Checkbox.js";
1
+ export { Checkbox, type CheckboxProps, type CheckboxVariant, } from "./Checkbox.js";
@@ -1,4 +1,2 @@
1
1
  export declare const menu: string;
2
2
  export declare const menuItem: string;
3
- export declare const menuItemLeading: string;
4
- export declare const menuItemTrailing: string;
@@ -1,7 +1,7 @@
1
1
  /* empty css */
2
2
  //#region src/components/MenuItem/MenuItem.css.ts
3
- var e = "fa1x5n0", t = "fa1x5n1", n = "fa1x5n2", r = "fa1x5n3";
3
+ var e = "fa1x5n0", t = "fa1x5n1";
4
4
  //#endregion
5
- export { e as menu, t as menuItem, n as menuItemLeading, r as menuItemTrailing };
5
+ export { e as menu, t as menuItem };
6
6
 
7
7
  //# sourceMappingURL=MenuItem.css.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MenuItem.css.js","names":[],"sources":["../../../src/components/MenuItem/MenuItem.css.ts"],"sourcesContent":["import { style } from \"@vanilla-extract/css\";\nimport { t } from \"../../tokens/index.js\";\n\n// The row is a fixed 40px control frame and each slot a fixed 24px box — Figma\n// pins both as literals (no control-size token tier exists yet), the same\n// treatment as Chip's height and Radio's control size.\nconst ROW_HEIGHT = \"40px\";\nconst SLOT_SIZE = \"24px\";\n\n// Shared 24px slot box that centres an icon or a selection indicator. `fontSize`\n// drives a slotted `<Icon>`'s 1em glyph up to the slot size; `color: inherit`\n// lets the glyph track the row's content colour (and its disabled dim).\nconst slotBase = {\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"center\",\n\tboxSizing: \"border-box\",\n\tflexShrink: 0,\n\twidth: SLOT_SIZE,\n\theight: SLOT_SIZE,\n\tfontSize: t(\"icon-size-lg\"),\n\tcolor: \"inherit\",\n} as const;\n\nexport const menu = style({\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\toutline: \"none\",\n});\n\nexport const menuItem = style({\n\tposition: \"relative\",\n\tisolation: \"isolate\",\n\tboxSizing: \"border-box\",\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: t(\"gap-12\"),\n\theight: ROW_HEIGHT,\n\tpaddingInline: t(\"padding-8\"),\n\tborderRadius: t(\"border-radius-button\"),\n\tborder: `${t(\"border-width-default\")} solid transparent`,\n\tbackgroundColor: t(\"color-background-default\"),\n\tcolor: t(\"color-content-default\"),\n\tfontFamily: t(\"font-family-body\"),\n\tfontSize: t(\"font-size-body\"),\n\tfontWeight: t(\"font-weight-regular\"),\n\tlineHeight: t(\"line-height-body\"),\n\ttextAlign: \"start\",\n\tcursor: \"pointer\",\n\tuserSelect: \"none\",\n\toutline: \"none\",\n\ttransitionProperty: \"background-color, border-color\",\n\ttransitionDuration: t(\"duration-fast\"),\n\ttransitionTimingFunction: t(\"easing-standard\"),\n\t\"::after\": {\n\t\tcontent: '\"\"',\n\t\tposition: \"absolute\",\n\t\tinset: 0,\n\t\tborderRadius: \"inherit\",\n\t\tbackgroundColor: \"currentColor\",\n\t\topacity: 0,\n\t\tpointerEvents: \"none\",\n\t\tzIndex: -1,\n\t\ttransition: `opacity ${t(\"duration-fast\")} ${t(\"easing-standard\")}`,\n\t},\n\tselectors: {\n\t\t\"&[data-hovered]:not([data-disabled])::after\": {\n\t\t\topacity: t(\"opacity-state-hover\"),\n\t\t},\n\t\t\"&[data-focus-visible]:not([data-disabled])::after\": {\n\t\t\topacity: t(\"opacity-state-focus\"),\n\t\t},\n\t\t\"&[data-pressed]:not([data-disabled])::after\": {\n\t\t\topacity: t(\"opacity-state-pressed\"),\n\t\t},\n\t\t// Focus: inner 1px accent border + outer 2px focus ring (Figma double ring).\n\t\t\"&[data-focus-visible]:not([data-disabled])\": {\n\t\t\tborderColor: t(\"color-border-accent\"),\n\t\t\tboxShadow: `0 0 0 ${t(\"border-width-focus\")} ${t(\"color-border-focus\")}`,\n\t\t},\n\t\t\"&[data-disabled]\": {\n\t\t\tcursor: \"not-allowed\",\n\t\t\tcolor: t(\"color-content-disabled\"),\n\t\t},\n\t},\n\t\"@media\": {\n\t\t// Custom colors flatten to system colors here, so the token focus ring is\n\t\t// lost — redraw it with a system color (matches Button/Chip/Radio).\n\t\t\"(forced-colors: active)\": {\n\t\t\tselectors: {\n\t\t\t\t\"&[data-focus-visible]:not([data-disabled])\": {\n\t\t\t\t\toutline: \"2px solid Highlight\",\n\t\t\t\t\toutlineOffset: \"2px\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t},\n});\n\nexport const menuItemLeading = style(slotBase);\n\n// A trailing slot pins to the row's end (auto inline-start margin, which mirrors\n// under `dir=\"rtl\"`), so the label between the slots takes the remaining space\n// without needing a wrapper element.\nexport const menuItemTrailing = style({\n\t...slotBase,\n\tmarginInlineStart: \"auto\",\n});\n"],"mappings":""}
1
+ {"version":3,"file":"MenuItem.css.js","names":[],"sources":["../../../src/components/MenuItem/MenuItem.css.ts"],"sourcesContent":["import { globalStyle, style } from \"@vanilla-extract/css\";\nimport { rowFrame, rowSlotRules } from \"../../styles/row.js\";\n\nexport const menu = style({\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\toutline: \"none\",\n});\n\nexport const menuItem = style(rowFrame);\n\nglobalStyle(`${menuItem} > [data-slot=\"icon\"]`, rowSlotRules.icon);\nglobalStyle(`${menuItem} > [data-slot=\"label\"]`, rowSlotRules.label);\n"],"mappings":""}
@@ -1,10 +1,16 @@
1
- import { MenuItemLeading } from "./MenuItemLeading.js";
1
+ import { MenuItemCheckbox } from "./MenuItemCheckbox.js";
2
+ import { MenuItemLabel } from "./MenuItemLabel.js";
3
+ import { MenuItemRadio } from "./MenuItemRadio.js";
2
4
  import { MenuItemRoot } from "./MenuItemRoot.js";
3
- import { MenuItemTrailing } from "./MenuItemTrailing.js";
4
- export type { MenuItemLeadingProps } from "./MenuItemLeading.js";
5
+ import { MenuItemToggle } from "./MenuItemToggle.js";
6
+ export type { MenuItemCheckboxProps } from "./MenuItemCheckbox.js";
7
+ export type { MenuItemLabelProps } from "./MenuItemLabel.js";
8
+ export type { MenuItemRadioProps } from "./MenuItemRadio.js";
5
9
  export type { MenuItemProps } from "./MenuItemRoot.js";
6
- export type { MenuItemTrailingProps } from "./MenuItemTrailing.js";
10
+ export type { MenuItemToggleProps } from "./MenuItemToggle.js";
7
11
  export declare const MenuItem: typeof MenuItemRoot & {
8
- Leading: typeof MenuItemLeading;
9
- Trailing: typeof MenuItemTrailing;
12
+ Label: typeof MenuItemLabel;
13
+ Checkbox: typeof MenuItemCheckbox;
14
+ Radio: typeof MenuItemRadio;
15
+ Toggle: typeof MenuItemToggle;
10
16
  };
@@ -1,12 +1,16 @@
1
- import { MenuItemLeading as e } from "./MenuItemLeading.js";
2
- import { MenuItemRoot as t } from "./MenuItemRoot.js";
3
- import { MenuItemTrailing as n } from "./MenuItemTrailing.js";
1
+ import { MenuItemCheckbox as e } from "./MenuItemCheckbox.js";
2
+ import { MenuItemLabel as t } from "./MenuItemLabel.js";
3
+ import { MenuItemRadio as n } from "./MenuItemRadio.js";
4
+ import { MenuItemRoot as r } from "./MenuItemRoot.js";
5
+ import { MenuItemToggle as i } from "./MenuItemToggle.js";
4
6
  //#region src/components/MenuItem/MenuItem.tsx
5
- var r = Object.assign(t, {
6
- Leading: e,
7
- Trailing: n
7
+ var a = Object.assign(r, {
8
+ Label: t,
9
+ Checkbox: e,
10
+ Radio: n,
11
+ Toggle: i
8
12
  });
9
13
  //#endregion
10
- export { r as MenuItem };
14
+ export { a as MenuItem };
11
15
 
12
16
  //# sourceMappingURL=MenuItem.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MenuItem.js","names":[],"sources":["../../../src/components/MenuItem/MenuItem.tsx"],"sourcesContent":["import { MenuItemLeading } from \"./MenuItemLeading.js\";\nimport { MenuItemRoot } from \"./MenuItemRoot.js\";\nimport { MenuItemTrailing } from \"./MenuItemTrailing.js\";\n\nexport type { MenuItemLeadingProps } from \"./MenuItemLeading.js\";\nexport type { MenuItemProps } from \"./MenuItemRoot.js\";\nexport type { MenuItemTrailingProps } from \"./MenuItemTrailing.js\";\n\nexport const MenuItem = Object.assign(MenuItemRoot, {\n\tLeading: MenuItemLeading,\n\tTrailing: MenuItemTrailing,\n});\n"],"mappings":";;;;AAQA,IAAa,IAAW,OAAO,OAAO,GAAc;CACnD,SAAS;CACT,UAAU;CACV,CAAC"}
1
+ {"version":3,"file":"MenuItem.js","names":[],"sources":["../../../src/components/MenuItem/MenuItem.tsx"],"sourcesContent":["import { MenuItemCheckbox } from \"./MenuItemCheckbox.js\";\nimport { MenuItemLabel } from \"./MenuItemLabel.js\";\nimport { MenuItemRadio } from \"./MenuItemRadio.js\";\nimport { MenuItemRoot } from \"./MenuItemRoot.js\";\nimport { MenuItemToggle } from \"./MenuItemToggle.js\";\n\nexport type { MenuItemCheckboxProps } from \"./MenuItemCheckbox.js\";\nexport type { MenuItemLabelProps } from \"./MenuItemLabel.js\";\nexport type { MenuItemRadioProps } from \"./MenuItemRadio.js\";\nexport type { MenuItemProps } from \"./MenuItemRoot.js\";\nexport type { MenuItemToggleProps } from \"./MenuItemToggle.js\";\n\nexport const MenuItem = Object.assign(MenuItemRoot, {\n\tLabel: MenuItemLabel,\n\tCheckbox: MenuItemCheckbox,\n\tRadio: MenuItemRadio,\n\tToggle: MenuItemToggle,\n});\n"],"mappings":";;;;;;AAYA,IAAa,IAAW,OAAO,OAAO,GAAc;CACnD,OAAO;CACP,UAAU;CACV,OAAO;CACP,QAAQ;CACR,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { CheckboxIndicatorProps } from "../Checkbox/CheckboxIndicator.js";
2
+ export type MenuItemCheckboxProps = Omit<CheckboxIndicatorProps, "hasStateLayer">;
3
+ /**
4
+ * A checkbox box drawn inside a menu row, for a `Menu` with
5
+ * `selectionMode="multiple"`. It renders no control of its own — the row is
6
+ * already `role="menuitemcheckbox"` and owns the selection, so a real `Checkbox`
7
+ * here would be an interactive element nested inside an interactive row.
8
+ *
9
+ * Same markup and styles as the standalone `Checkbox`'s box, minus the box's own
10
+ * state layer: the row paints hover and focus.
11
+ */
12
+ export declare function MenuItemCheckbox(props: MenuItemCheckboxProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { CheckboxIndicator as e } from "../Checkbox/CheckboxIndicator.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/components/MenuItem/MenuItemCheckbox.tsx
4
+ function n(n) {
5
+ return /* @__PURE__ */ t(e, {
6
+ ...n,
7
+ hasStateLayer: !1
8
+ });
9
+ }
10
+ //#endregion
11
+ export { n as MenuItemCheckbox };
12
+
13
+ //# sourceMappingURL=MenuItemCheckbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuItemCheckbox.js","names":[],"sources":["../../../src/components/MenuItem/MenuItemCheckbox.tsx"],"sourcesContent":["import type { CheckboxIndicatorProps } from \"../Checkbox/CheckboxIndicator.js\";\nimport { CheckboxIndicator } from \"../Checkbox/CheckboxIndicator.js\";\n\nexport type MenuItemCheckboxProps = Omit<\n\tCheckboxIndicatorProps,\n\t\"hasStateLayer\"\n>;\n\n/**\n * A checkbox box drawn inside a menu row, for a `Menu` with\n * `selectionMode=\"multiple\"`. It renders no control of its own — the row is\n * already `role=\"menuitemcheckbox\"` and owns the selection, so a real `Checkbox`\n * here would be an interactive element nested inside an interactive row.\n *\n * Same markup and styles as the standalone `Checkbox`'s box, minus the box's own\n * state layer: the row paints hover and focus.\n */\nexport function MenuItemCheckbox(props: MenuItemCheckboxProps) {\n\treturn <CheckboxIndicator {...props} hasStateLayer={false} />;\n}\n"],"mappings":";;;AAiBA,SAAgB,EAAiB,GAA8B;AAC9D,QAAO,kBAAC,GAAD;EAAmB,GAAI;EAAO,eAAe;EAAS,CAAA"}
@@ -0,0 +1,15 @@
1
+ import type { HTMLAttributes, ReactNode, Ref } from "react";
2
+ export interface MenuItemLabelProps extends HTMLAttributes<HTMLSpanElement> {
3
+ ref?: Ref<HTMLSpanElement>;
4
+ /** The row's text. Keep it a plain string so `textValue` can be derived from it. */
5
+ children?: ReactNode;
6
+ }
7
+ /**
8
+ * The row's text, and the element that lays the row out: it takes the remaining
9
+ * width, so anything rendered before it sits at the row start and anything after
10
+ * it pins to the row end — no slot wrapper needed either side.
11
+ *
12
+ * `MenuItem` reads its string child as the item's `textValue`, which React Aria
13
+ * needs for typeahead.
14
+ */
15
+ export declare function MenuItemLabel({ children, ref, ...rest }: MenuItemLabelProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ //#region src/components/MenuItem/MenuItemLabel.tsx
3
+ function t({ children: t, ref: n, ...r }) {
4
+ return /* @__PURE__ */ e("span", {
5
+ ref: n,
6
+ ...r,
7
+ "data-slot": "label",
8
+ children: t
9
+ });
10
+ }
11
+ //#endregion
12
+ export { t as MenuItemLabel };
13
+
14
+ //# sourceMappingURL=MenuItemLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuItemLabel.js","names":[],"sources":["../../../src/components/MenuItem/MenuItemLabel.tsx"],"sourcesContent":["import type { HTMLAttributes, ReactNode, Ref } from \"react\";\n\nexport interface MenuItemLabelProps extends HTMLAttributes<HTMLSpanElement> {\n\tref?: Ref<HTMLSpanElement>;\n\t/** The row's text. Keep it a plain string so `textValue` can be derived from it. */\n\tchildren?: ReactNode;\n}\n\n/**\n * The row's text, and the element that lays the row out: it takes the remaining\n * width, so anything rendered before it sits at the row start and anything after\n * it pins to the row end — no slot wrapper needed either side.\n *\n * `MenuItem` reads its string child as the item's `textValue`, which React Aria\n * needs for typeahead.\n */\nexport function MenuItemLabel({ children, ref, ...rest }: MenuItemLabelProps) {\n\treturn (\n\t\t<span ref={ref} {...rest} data-slot=\"label\">\n\t\t\t{children}\n\t\t</span>\n\t);\n}\n"],"mappings":";;AAgBA,SAAgB,EAAc,EAAE,aAAU,QAAK,GAAG,KAA4B;AAC7E,QACC,kBAAC,QAAD;EAAW;EAAK,GAAI;EAAM,aAAU;EAClC;EACK,CAAA"}
@@ -0,0 +1,11 @@
1
+ import type { RadioIndicatorProps } from "../Radio/RadioIndicator.js";
2
+ export type MenuItemRadioProps = Omit<RadioIndicatorProps, "hasStateLayer">;
3
+ /**
4
+ * A radio circle drawn inside a menu row, for a `Menu` with
5
+ * `selectionMode="single"`. It renders no control of its own — the row is already
6
+ * `role="menuitemradio"` and owns the selection.
7
+ *
8
+ * Same markup and styles as the standalone `Radio`'s circle, minus the circle's
9
+ * own hover border and focus ring: the row paints those.
10
+ */
11
+ export declare function MenuItemRadio(props: MenuItemRadioProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { RadioIndicator as e } from "../Radio/RadioIndicator.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/components/MenuItem/MenuItemRadio.tsx
4
+ function n(n) {
5
+ return /* @__PURE__ */ t(e, {
6
+ ...n,
7
+ hasStateLayer: !1
8
+ });
9
+ }
10
+ //#endregion
11
+ export { n as MenuItemRadio };
12
+
13
+ //# sourceMappingURL=MenuItemRadio.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuItemRadio.js","names":[],"sources":["../../../src/components/MenuItem/MenuItemRadio.tsx"],"sourcesContent":["import type { RadioIndicatorProps } from \"../Radio/RadioIndicator.js\";\nimport { RadioIndicator } from \"../Radio/RadioIndicator.js\";\n\nexport type MenuItemRadioProps = Omit<RadioIndicatorProps, \"hasStateLayer\">;\n\n/**\n * A radio circle drawn inside a menu row, for a `Menu` with\n * `selectionMode=\"single\"`. It renders no control of its own — the row is already\n * `role=\"menuitemradio\"` and owns the selection.\n *\n * Same markup and styles as the standalone `Radio`'s circle, minus the circle's\n * own hover border and focus ring: the row paints those.\n */\nexport function MenuItemRadio(props: MenuItemRadioProps) {\n\treturn <RadioIndicator {...props} hasStateLayer={false} />;\n}\n"],"mappings":";;;AAaA,SAAgB,EAAc,GAA2B;AACxD,QAAO,kBAAC,GAAD;EAAgB,GAAI;EAAO,eAAe;EAAS,CAAA"}
@@ -10,9 +10,15 @@ export interface MenuItemProps extends Omit<AriaMenuItemProps, "className" | "st
10
10
  * `menuitemcheckbox`/`menuitemradio` when the `Menu` sets `selectionMode`.
11
11
  * Hover/focus/pressed/selected/disabled states come from the data-attributes
12
12
  * React Aria sets, so this takes no state props; pass `isDisabled` to disable
13
- * and `onAction` to handle activation. Compose row content with the
14
- * `MenuItem.Leading` / `MenuItem.Trailing` slots around a text label, and supply
15
- * `textValue` when the label isn't a plain string child. Children may be a
16
- * render function to react to `isSelected` / `isFocused`.
13
+ * and `onAction` to handle activation.
14
+ *
15
+ * Compose the row in child order around a required `MenuItem.Label`, which takes
16
+ * the remaining width: content before it sits at the row start, content after it
17
+ * pins to the row end. Use `MenuItem.Checkbox` / `.Radio` / `.Toggle` for a
18
+ * selection indicator and `<Icon>` for an icon.
19
+ *
20
+ * `textValue` is derived from the `Label`'s string child; pass it explicitly when
21
+ * the label isn't a plain string. Children may be a render function to react to
22
+ * `isSelected` / `isFocused`, in which case pass `textValue` yourself.
17
23
  */
18
- export declare function MenuItemRoot({ className, ...rest }: MenuItemProps): import("react/jsx-runtime").JSX.Element;
24
+ export declare function MenuItemRoot({ className, children, textValue, ...rest }: MenuItemProps): import("react/jsx-runtime").JSX.Element;
@@ -1,15 +1,24 @@
1
1
  import { cx as e } from "../../utils/cx.js";
2
2
  import { menuItem as t } from "./MenuItem.css.js";
3
- import { jsx as n } from "react/jsx-runtime";
4
- import { MenuItem as r } from "react-aria-components";
3
+ import { MenuItemLabel as n } from "./MenuItemLabel.js";
4
+ import { jsx as r } from "react/jsx-runtime";
5
+ import { MenuItem as i } from "react-aria-components";
6
+ import { Children as a, isValidElement as o } from "react";
5
7
  //#region src/components/MenuItem/MenuItemRoot.tsx
6
- function i({ className: i, ...a }) {
7
- return /* @__PURE__ */ n(r, {
8
- ...a,
9
- className: e(t, i)
8
+ function s(e) {
9
+ let t = a.toArray(e).find((e) => o(e) && e.type === n);
10
+ if (o(t)) return typeof t.props.children == "string" ? t.props.children : void 0;
11
+ }
12
+ function c({ className: n, children: a, textValue: o, ...c }) {
13
+ let l = s(typeof a == "function" ? null : a);
14
+ return /* @__PURE__ */ r(i, {
15
+ ...c,
16
+ textValue: o ?? l,
17
+ className: e(t, n),
18
+ children: a
10
19
  });
11
20
  }
12
21
  //#endregion
13
- export { i as MenuItemRoot };
22
+ export { c as MenuItemRoot };
14
23
 
15
24
  //# sourceMappingURL=MenuItemRoot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MenuItemRoot.js","names":[],"sources":["../../../src/components/MenuItem/MenuItemRoot.tsx"],"sourcesContent":["import type { CSSProperties, Ref } from \"react\";\nimport type { MenuItemProps as AriaMenuItemProps } from \"react-aria-components\";\nimport { MenuItem as AriaMenuItem } from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport { menuItem } from \"./MenuItem.css.js\";\n\nexport interface MenuItemProps\n\textends Omit<AriaMenuItemProps, \"className\" | \"style\"> {\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tref?: Ref<HTMLDivElement>;\n}\n\n/**\n * A selectable row within a `Menu` — `role=\"menuitem\"`, or\n * `menuitemcheckbox`/`menuitemradio` when the `Menu` sets `selectionMode`.\n * Hover/focus/pressed/selected/disabled states come from the data-attributes\n * React Aria sets, so this takes no state props; pass `isDisabled` to disable\n * and `onAction` to handle activation. Compose row content with the\n * `MenuItem.Leading` / `MenuItem.Trailing` slots around a text label, and supply\n * `textValue` when the label isn't a plain string child. Children may be a\n * render function to react to `isSelected` / `isFocused`.\n */\nexport function MenuItemRoot({ className, ...rest }: MenuItemProps) {\n\treturn <AriaMenuItem {...rest} className={cx(menuItem, className)} />;\n}\n"],"mappings":";;;;;AAuBA,SAAgB,EAAa,EAAE,cAAW,GAAG,KAAuB;AACnE,QAAO,kBAAC,GAAD;EAAc,GAAI;EAAM,WAAW,EAAG,GAAU,EAAU;EAAI,CAAA"}
1
+ {"version":3,"file":"MenuItemRoot.js","names":[],"sources":["../../../src/components/MenuItem/MenuItemRoot.tsx"],"sourcesContent":["import type { CSSProperties, ReactNode, Ref } from \"react\";\nimport { Children, isValidElement } from \"react\";\nimport type { MenuItemProps as AriaMenuItemProps } from \"react-aria-components\";\nimport { MenuItem as AriaMenuItem } from \"react-aria-components\";\nimport { cx } from \"../../utils/cx.js\";\nimport { menuItem } from \"./MenuItem.css.js\";\nimport { MenuItemLabel } from \"./MenuItemLabel.js\";\n\nexport interface MenuItemProps\n\textends Omit<AriaMenuItemProps, \"className\" | \"style\"> {\n\tclassName?: string;\n\tstyle?: CSSProperties;\n\tref?: Ref<HTMLDivElement>;\n}\n\n/** Read the row's text off its `MenuItem.Label` child, for React Aria's typeahead. */\nfunction readLabelTextValue(children: ReactNode): string | undefined {\n\tconst label = Children.toArray(children).find(\n\t\t(child) => isValidElement(child) && child.type === MenuItemLabel,\n\t);\n\tif (!isValidElement<{ children?: ReactNode }>(label)) {\n\t\treturn undefined;\n\t}\n\treturn typeof label.props.children === \"string\"\n\t\t? label.props.children\n\t\t: undefined;\n}\n\n/**\n * A selectable row within a `Menu` — `role=\"menuitem\"`, or\n * `menuitemcheckbox`/`menuitemradio` when the `Menu` sets `selectionMode`.\n * Hover/focus/pressed/selected/disabled states come from the data-attributes\n * React Aria sets, so this takes no state props; pass `isDisabled` to disable\n * and `onAction` to handle activation.\n *\n * Compose the row in child order around a required `MenuItem.Label`, which takes\n * the remaining width: content before it sits at the row start, content after it\n * pins to the row end. Use `MenuItem.Checkbox` / `.Radio` / `.Toggle` for a\n * selection indicator and `<Icon>` for an icon.\n *\n * `textValue` is derived from the `Label`'s string child; pass it explicitly when\n * the label isn't a plain string. Children may be a render function to react to\n * `isSelected` / `isFocused`, in which case pass `textValue` yourself.\n */\nexport function MenuItemRoot({\n\tclassName,\n\tchildren,\n\ttextValue,\n\t...rest\n}: MenuItemProps) {\n\tconst labelTextValue = readLabelTextValue(\n\t\ttypeof children === \"function\" ? null : children,\n\t);\n\treturn (\n\t\t<AriaMenuItem\n\t\t\t{...rest}\n\t\t\ttextValue={textValue ?? labelTextValue}\n\t\t\tclassName={cx(menuItem, className)}\n\t\t>\n\t\t\t{children}\n\t\t</AriaMenuItem>\n\t);\n}\n"],"mappings":";;;;;;;AAgBA,SAAS,EAAmB,GAAyC;CACpE,IAAM,IAAQ,EAAS,QAAQ,EAAS,CAAC,MACvC,MAAU,EAAe,EAAM,IAAI,EAAM,SAAS,EACnD;AACI,OAAyC,EAAM,CAGpD,QAAO,OAAO,EAAM,MAAM,YAAa,WACpC,EAAM,MAAM,WACZ,KAAA;;AAmBJ,SAAgB,EAAa,EAC5B,cACA,aACA,cACA,GAAG,KACc;CACjB,IAAM,IAAiB,EACtB,OAAO,KAAa,aAAa,OAAO,EACxC;AACD,QACC,kBAAC,GAAD;EACC,GAAI;EACJ,WAAW,KAAa;EACxB,WAAW,EAAG,GAAU,EAAU;EAEjC;EACa,CAAA"}
@@ -0,0 +1,12 @@
1
+ import type { ToggleIndicatorProps } from "../Toggle/ToggleIndicator.js";
2
+ export type MenuItemToggleProps = Omit<ToggleIndicatorProps, "hasStateLayer">;
3
+ /**
4
+ * A toggle track drawn inside a menu row, for a `Menu` with
5
+ * `selectionMode="multiple"` where the row reads as a setting rather than a
6
+ * command. It renders no `Switch` of its own — the row is already
7
+ * `role="menuitemcheckbox"` and owns the state, so activating the row flips it.
8
+ *
9
+ * For a settings list that is not a menu, use `Toggle` with its own accessible
10
+ * name instead; that is a `role="switch"` control, not a menu row.
11
+ */
12
+ export declare function MenuItemToggle(props: MenuItemToggleProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,13 @@
1
+ import { ToggleIndicator as e } from "../Toggle/ToggleIndicator.js";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/components/MenuItem/MenuItemToggle.tsx
4
+ function n(n) {
5
+ return /* @__PURE__ */ t(e, {
6
+ ...n,
7
+ hasStateLayer: !1
8
+ });
9
+ }
10
+ //#endregion
11
+ export { n as MenuItemToggle };
12
+
13
+ //# sourceMappingURL=MenuItemToggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MenuItemToggle.js","names":[],"sources":["../../../src/components/MenuItem/MenuItemToggle.tsx"],"sourcesContent":["import type { ToggleIndicatorProps } from \"../Toggle/ToggleIndicator.js\";\nimport { ToggleIndicator } from \"../Toggle/ToggleIndicator.js\";\n\nexport type MenuItemToggleProps = Omit<ToggleIndicatorProps, \"hasStateLayer\">;\n\n/**\n * A toggle track drawn inside a menu row, for a `Menu` with\n * `selectionMode=\"multiple\"` where the row reads as a setting rather than a\n * command. It renders no `Switch` of its own — the row is already\n * `role=\"menuitemcheckbox\"` and owns the state, so activating the row flips it.\n *\n * For a settings list that is not a menu, use `Toggle` with its own accessible\n * name instead; that is a `role=\"switch\"` control, not a menu row.\n */\nexport function MenuItemToggle(props: MenuItemToggleProps) {\n\treturn <ToggleIndicator {...props} hasStateLayer={false} />;\n}\n"],"mappings":";;;AAcA,SAAgB,EAAe,GAA4B;AAC1D,QAAO,kBAAC,GAAD;EAAiB,GAAI;EAAO,eAAe;EAAS,CAAA"}
@@ -1,4 +1,4 @@
1
1
  export type { MenuProps } from "./Menu.js";
2
2
  export { Menu } from "./Menu.js";
3
- export type { MenuItemLeadingProps, MenuItemProps, MenuItemTrailingProps, } from "./MenuItem.js";
3
+ export type { MenuItemCheckboxProps, MenuItemLabelProps, MenuItemProps, MenuItemRadioProps, MenuItemToggleProps, } from "./MenuItem.js";
4
4
  export { MenuItem } from "./MenuItem.js";