@epilot/zenith-react 0.1.0-next.1 → 0.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 (113) hide show
  1. package/README.md +45 -10
  2. package/dist/components/appearance-boundary/appearance-boundary.js +32 -34
  3. package/dist/components/appearance-boundary/appearance-boundary.js.map +1 -1
  4. package/dist/components/badge/badge.js +1 -1
  5. package/dist/components/badge/badge.js.map +1 -1
  6. package/dist/components/breadcrumb/breadcrumb.js +10 -10
  7. package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
  8. package/dist/components/button/button.js +28 -28
  9. package/dist/components/button/button.js.map +1 -1
  10. package/dist/components/callout/callout.js +13 -13
  11. package/dist/components/callout/callout.js.map +1 -1
  12. package/dist/components/checkbox/checkbox.js +13 -13
  13. package/dist/components/checkbox/checkbox.js.map +1 -1
  14. package/dist/components/code-block/code-block.js +6 -6
  15. package/dist/components/code-block/code-block.js.map +1 -1
  16. package/dist/components/code-editor/code-editor.js +1 -1
  17. package/dist/components/code-editor/code-editor.js.map +1 -1
  18. package/dist/components/command/command.js +6 -6
  19. package/dist/components/command/command.js.map +1 -1
  20. package/dist/components/data-table/data-table-body.js +120 -66
  21. package/dist/components/data-table/data-table-body.js.map +1 -1
  22. package/dist/components/data-table/data-table-column-header.js +7 -7
  23. package/dist/components/data-table/data-table-column-header.js.map +1 -1
  24. package/dist/components/data-table/data-table-column-order.js +277 -0
  25. package/dist/components/data-table/data-table-column-order.js.map +1 -0
  26. package/dist/components/data-table/data-table-content.js +72 -58
  27. package/dist/components/data-table/data-table-content.js.map +1 -1
  28. package/dist/components/data-table/data-table-context.js +8 -4
  29. package/dist/components/data-table/data-table-context.js.map +1 -1
  30. package/dist/components/data-table/data-table-footer.js +31 -0
  31. package/dist/components/data-table/data-table-footer.js.map +1 -0
  32. package/dist/components/data-table/data-table-header-draggable.js +151 -0
  33. package/dist/components/data-table/data-table-header-draggable.js.map +1 -0
  34. package/dist/components/data-table/data-table-header.js +130 -57
  35. package/dist/components/data-table/data-table-header.js.map +1 -1
  36. package/dist/components/data-table/data-table-resize-handle.js +137 -0
  37. package/dist/components/data-table/data-table-resize-handle.js.map +1 -0
  38. package/dist/components/data-table/data-table.js +184 -156
  39. package/dist/components/data-table/data-table.js.map +1 -1
  40. package/dist/components/data-table/hooks/use-data-table-virtualizer.js +9 -0
  41. package/dist/components/data-table/hooks/use-data-table-virtualizer.js.map +1 -0
  42. package/dist/components/date-range-picker/date-range-picker.js +194 -187
  43. package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
  44. package/dist/components/date-time-picker/calendar.js +29 -29
  45. package/dist/components/date-time-picker/calendar.js.map +1 -1
  46. package/dist/components/date-time-picker/time-picker.js +55 -55
  47. package/dist/components/date-time-picker/time-picker.js.map +1 -1
  48. package/dist/components/dialog/dialog.js +1 -1
  49. package/dist/components/dialog/dialog.js.map +1 -1
  50. package/dist/components/drawer/drawer.js +5 -5
  51. package/dist/components/drawer/drawer.js.map +1 -1
  52. package/dist/components/dropdown-menu/dropdown-menu.js +36 -36
  53. package/dist/components/dropdown-menu/dropdown-menu.js.map +1 -1
  54. package/dist/components/field/field-combobox.js +4 -4
  55. package/dist/components/field/field-combobox.js.map +1 -1
  56. package/dist/components/field/field.js +40 -40
  57. package/dist/components/field/field.js.map +1 -1
  58. package/dist/components/list/list.js +40 -40
  59. package/dist/components/list/list.js.map +1 -1
  60. package/dist/components/option-card/option-card.js +27 -25
  61. package/dist/components/option-card/option-card.js.map +1 -1
  62. package/dist/components/pill/pill.js +9 -9
  63. package/dist/components/pill/pill.js.map +1 -1
  64. package/dist/components/radio/radio.js +14 -14
  65. package/dist/components/radio/radio.js.map +1 -1
  66. package/dist/components/scroll-area/scroll-area.js +9 -9
  67. package/dist/components/scroll-area/scroll-area.js.map +1 -1
  68. package/dist/components/segmented-control/segmented-control.js +1 -1
  69. package/dist/components/segmented-control/segmented-control.js.map +1 -1
  70. package/dist/components/select/select.js +11 -11
  71. package/dist/components/select/select.js.map +1 -1
  72. package/dist/components/spinner/spinner.js.map +1 -1
  73. package/dist/components/switch/switch.js +11 -11
  74. package/dist/components/switch/switch.js.map +1 -1
  75. package/dist/components/table/table-pagination.js +1 -1
  76. package/dist/components/table/table-pagination.js.map +1 -1
  77. package/dist/components/table/table.js +15 -15
  78. package/dist/components/table/table.js.map +1 -1
  79. package/dist/components/text/text.js +10 -1
  80. package/dist/components/text/text.js.map +1 -1
  81. package/dist/components/toast/toast.js +26 -26
  82. package/dist/components/toast/toast.js.map +1 -1
  83. package/dist/components/toggle/toggle.js +20 -20
  84. package/dist/components/toggle/toggle.js.map +1 -1
  85. package/dist/index.d.ts +1930 -1867
  86. package/dist/index.js +133 -121
  87. package/dist/index.js.map +1 -1
  88. package/dist/packages/tokens/dist/generated/core.generated.js +13 -22
  89. package/dist/packages/tokens/dist/generated/core.generated.js.map +1 -1
  90. package/dist/packages/tokens/dist/generated/palette.generated.js +5 -5
  91. package/dist/packages/tokens/dist/generated/palette.generated.js.map +1 -1
  92. package/dist/packages/tokens/dist/install.js +5 -5
  93. package/dist/packages/tokens/dist/install.js.map +1 -1
  94. package/dist/tokens/core.meta.generated.js +2 -2
  95. package/dist/tokens/core.meta.generated.js.map +1 -1
  96. package/dist/tokens/index.d.ts +1029 -1104
  97. package/dist/tokens/index.js +1031 -1106
  98. package/dist/tokens/index.js.map +1 -1
  99. package/dist/tokens/palette.generated.js +2 -2
  100. package/dist/tokens/palette.generated.js.map +1 -1
  101. package/dist/tokens.json +605 -755
  102. package/dist/vendor/.bun/@dnd-kit_core@6.3.1_6f4b9a1cfb20c0ae/vendor/@dnd-kit/core/dist/core.esm.js +385 -340
  103. package/dist/vendor/.bun/@dnd-kit_core@6.3.1_6f4b9a1cfb20c0ae/vendor/@dnd-kit/core/dist/core.esm.js.map +1 -1
  104. package/dist/vendor/.bun/@dnd-kit_sortable@10.0.0_1d291640e1250bbe/vendor/@dnd-kit/sortable/dist/sortable.esm.js +344 -229
  105. package/dist/vendor/.bun/@dnd-kit_sortable@10.0.0_1d291640e1250bbe/vendor/@dnd-kit/sortable/dist/sortable.esm.js.map +1 -1
  106. package/dist/vendor/.bun/@dnd-kit_utilities@3.2.2_62547eec5a2188e3/vendor/@dnd-kit/utilities/dist/utilities.esm.js +1 -1
  107. package/dist/vendor/.bun/@tanstack_react-virtual@3.11.2_6f4b9a1cfb20c0ae/vendor/@tanstack/react-virtual/dist/esm/index.js +36 -0
  108. package/dist/vendor/.bun/@tanstack_react-virtual@3.11.2_6f4b9a1cfb20c0ae/vendor/@tanstack/react-virtual/dist/esm/index.js.map +1 -0
  109. package/dist/vendor/.bun/@tanstack_virtual-core@3.11.2/vendor/@tanstack/virtual-core/dist/esm/index.js +450 -0
  110. package/dist/vendor/.bun/@tanstack_virtual-core@3.11.2/vendor/@tanstack/virtual-core/dist/esm/index.js.map +1 -0
  111. package/dist/vendor/.bun/@tanstack_virtual-core@3.11.2/vendor/@tanstack/virtual-core/dist/esm/utils.js +50 -0
  112. package/dist/vendor/.bun/@tanstack_virtual-core@3.11.2/vendor/@tanstack/virtual-core/dist/esm/utils.js.map +1 -0
  113. package/package.json +5 -3
package/README.md CHANGED
@@ -20,7 +20,6 @@ shared component-library import map.
20
20
 
21
21
  ```tsx
22
22
  import { Button } from "@epilot/zenith-react"
23
- import { gray11 } from "@epilot/zenith-react/tokens"
24
23
 
25
24
  export const Example = () => <Button variant="primary">Continue</Button>
26
25
  ```
@@ -34,8 +33,16 @@ import { prepareCoreTokens } from "@epilot/zenith-react/delivery"
34
33
  await prepareCoreTokens()
35
34
  ```
36
35
 
37
- Optional; no network. Do not add the token CSS as a second stylesheet, and do
38
- not write generated namespace hashes by hand.
36
+ Optional; no network.
37
+
38
+ Application styles that need a design token import a named binding from
39
+ `@epilot/zenith-react/tokens`. Do not add the token CSS as a second stylesheet,
40
+ and do not write generated `--zenith-<hash>-*` names by hand.
41
+
42
+ Zenith ships no `.css` files, and its `exports` map has no stylesheet entry:
43
+ there is nothing to import. Porting from Volt, drop its `style.css`,
44
+ `preflight.css` and `font.css` imports and add no replacement — the token CSS
45
+ above is the only stylesheet, and the package installs it itself.
39
46
 
40
47
  Use `AppearanceBoundary` for a scoped appearance that must also reach portalled
41
48
  content — a theme or surface attribute on a subtree does not follow a Dialog,
@@ -57,16 +64,41 @@ selectors or internal DOM structure from another component system. Where APIs
57
64
  differ, adapt at the application boundary and remove the adapter once the
58
65
  surface is fully on Zenith.
59
66
 
67
+ ## Connect an MCP client
68
+
69
+ A read-only Model Context Protocol (MCP) server for Zenith runs dynamically on
70
+ the documentation site at `/api/mcp`. It serves component APIs, design tokens,
71
+ and design guidelines directly to AI coding tools.
72
+
73
+ The catalogue is built from the commit the current `latest` release was
74
+ published from, so it describes exactly what `npm install @epilot/zenith-react`
75
+ installs — not unreleased work on `main`.
76
+
77
+ Point an MCP client (such as Cursor or Claude) at the Streamable HTTP endpoint:
78
+
79
+ ```json
80
+ {
81
+ "mcpServers": {
82
+ "zenith": {
83
+ "url": "https://main.d8s2wyuq7fsgk.amplifyapp.com/api/mcp"
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ Replace `https://main.d8s2wyuq7fsgk.amplifyapp.com` with your custom domain if
90
+ configured. All queries and tools are strictly read-only and require no
91
+ credentials.
92
+
60
93
  ## Which version you get
61
94
 
62
- `npm install @epilot/zenith-react` resolves the `latest` dist-tag, which only
63
- ever points at a deliberately promoted version. Until a first promotion happens,
64
- `latest` does not exist.
95
+ `npm install @epilot/zenith-react` resolves the `latest` dist-tag, which points
96
+ at `0.1.0` — published to `next`, verified, then promoted by hand.
65
97
 
66
- Unproven builds go to `next` with a prerelease version:
98
+ Unproven builds stay on `next` with a prerelease version:
67
99
 
68
100
  ```sh
69
- npm install @epilot/zenith-react@next # e.g. 0.1.0-next.0
101
+ npm install @epilot/zenith-react@next
70
102
  ```
71
103
 
72
104
  These are opt-in twice over — you name the tag, and a range like `^0.1.0` never
@@ -76,5 +108,8 @@ resolves a prerelease. Pin an exact version if you adopt one.
76
108
 
77
109
  The package is ESM-only and tree-shakeable. Resolved literal token values are in
78
110
  `@epilot/zenith-react/tokens.json`, and an optional Jest helper in
79
- `@epilot/zenith-react/testing/jest-preset.cjs`. Development rules are in
80
- `AGENTS.md`.
111
+ `@epilot/zenith-react/testing/jest-preset.cjs`.
112
+
113
+ Component reference, guidelines and examples are on the documentation site — the
114
+ same catalogue the MCP endpoint above serves. Development and contribution rules
115
+ live in the repository.
@@ -1,53 +1,51 @@
1
- import { jsx as o } from "react/jsx-runtime";
2
- import * as t from "react";
3
- import { ComposeAsChild as f } from "../slot/compose-as-child.js";
4
- import { SLOT_ATTR as A } from "@epilot/zenith-runtime/v1";
5
- const l = ["light", "dark"], C = [
6
- "plain",
7
- "bordered",
8
- "glass",
9
- "tint",
10
- "card"
11
- ], h = (e) => ({
12
- mode: l.includes(e.mode) ? e.mode : "light",
13
- surface: C.includes(e.surface) ? e.surface : "plain"
14
- }), i = t.createContext(void 0), O = t.forwardRef(function({ mode: r, surface: n, asChild: m = !1, className: c, children: s, ...d }, u) {
15
- const a = t.useMemo(
16
- () => h({ mode: r, surface: n }),
17
- [r, n]
18
- ), p = m ? /* @__PURE__ */ o(
19
- f,
1
+ import { jsx as s } from "react/jsx-runtime";
2
+ import * as o from "react";
3
+ import { mergeClasses as v, SLOT_ATTR as y } from "@epilot/zenith-runtime/v1";
4
+ import { makeZenithStyles as h } from "../../styles/make-styles.js";
5
+ import { body as b } from "../../tokens/index.js";
6
+ import { ComposeAsChild as S } from "../slot/compose-as-child.js";
7
+ const g = ["light", "dark"], x = ["flat", "bordered"], N = (e) => ({
8
+ mode: g.includes(e.mode) ? e.mode : "light",
9
+ surface: x.includes(e.surface) ? e.surface : "flat"
10
+ }), p = o.createContext(void 0), O = h({
11
+ canvas: { backgroundColor: b }
12
+ }), B = o.forwardRef(function({ mode: r, surface: c, asChild: l = !1, className: n, children: d, ...m }, u) {
13
+ const a = o.useMemo(
14
+ () => N({ mode: r, surface: c }),
15
+ [r, c]
16
+ ), t = i(), A = O(), f = (t == null ? void 0 : t.mode) === a.mode ? n : v(A.canvas, n), C = l ? /* @__PURE__ */ s(
17
+ S,
20
18
  {
21
- ...d,
19
+ ...m,
22
20
  ref: u,
23
- className: c,
21
+ className: f,
24
22
  forceProps: { "data-theme": a.mode, "data-surface": a.surface },
25
23
  "data-theme": a.mode,
26
24
  "data-surface": a.surface,
27
- children: s
25
+ children: d
28
26
  }
29
- ) : /* @__PURE__ */ o(
27
+ ) : /* @__PURE__ */ s(
30
28
  "div",
31
29
  {
32
30
  ref: u,
33
31
  "data-slot": "appearance-boundary",
34
- [A]: "appearance-boundary",
35
- className: c,
36
- ...d,
32
+ [y]: "appearance-boundary",
33
+ className: f,
34
+ ...m,
37
35
  "data-theme": a.mode,
38
36
  "data-surface": a.surface,
39
- children: s
37
+ children: d
40
38
  }
41
39
  );
42
- return /* @__PURE__ */ o(i.Provider, { value: a, children: p });
43
- }), v = () => t.useContext(i), R = () => {
44
- const e = v();
40
+ return /* @__PURE__ */ s(p.Provider, { value: a, children: C });
41
+ }), i = () => o.useContext(p), E = () => {
42
+ const e = i();
45
43
  return e === void 0 ? {} : { "data-theme": e.mode, "data-surface": e.surface };
46
44
  };
47
45
  export {
48
- O as AppearanceBoundary,
49
- h as canonicalAppearance,
50
- v as useAppearance,
51
- R as useAppearanceAttributes
46
+ B as AppearanceBoundary,
47
+ N as canonicalAppearance,
48
+ i as useAppearance,
49
+ E as useAppearanceAttributes
52
50
  };
53
51
  //# sourceMappingURL=appearance-boundary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"appearance-boundary.js","sources":["../../../src/components/appearance-boundary/appearance-boundary.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { ComposeAsChild } from \"../slot/compose-as-child\"\n\n/**\n * A region that carries its own appearance — `packages/tokens/SPEC.md` §2 rule 3's document\n * boundary, as a component instead of two hand-written DOM attributes.\n */\n\nexport type AppearanceMode = \"light\" | \"dark\"\n\nexport type AppearanceSurface = \"plain\" | \"bordered\" | \"glass\" | \"tint\" | \"card\"\n\nexport type Appearance = {\n mode: AppearanceMode\n surface: AppearanceSurface\n}\n\nconst CANONICAL_MODES: readonly AppearanceMode[] = [\"light\", \"dark\"]\nconst CANONICAL_SURFACES: readonly AppearanceSurface[] = [\n \"plain\",\n \"bordered\",\n \"glass\",\n \"tint\",\n \"card\",\n]\n\n/** Per-axis normalization of invalid runtime input, mirroring `canonicalDensity`. */\nexport const canonicalAppearance = (appearance: Appearance): Appearance => ({\n mode: CANONICAL_MODES.includes(appearance.mode) ? appearance.mode : \"light\",\n surface: CANONICAL_SURFACES.includes(appearance.surface)\n ? appearance.surface\n : \"plain\",\n})\n\n/**\n * Unexported, same as `DensityContext` — read only through `useAppearance()`. Default `undefined`:\n * a component with no `AppearanceBoundary` ancestor gets `undefined`, never a fabricated\n * `{light, plain}`, which would be this package inventing a reading of the live shell attributes it\n * deliberately does not read.\n */\nconst AppearanceContext = React.createContext<Appearance | undefined>(undefined)\n\ntype AppearanceBoundaryBaseProps = Omit<\n React.ComponentProps<\"div\">,\n \"children\"\n> & {\n /** The mode this region renders in, regardless of the page's. No default. */\n mode: AppearanceMode\n /** The treatment this region restates. Required — see the note on both props above. */\n surface: AppearanceSurface\n}\n\nexport type AppearanceBoundaryProps =\n | (AppearanceBoundaryBaseProps & {\n asChild?: false\n children?: React.ReactNode\n })\n | (AppearanceBoundaryBaseProps & {\n asChild: true\n children: React.ReactElement\n })\n\n/**\n * The default is one ordinary HTML div. `asChild` stamps the same authoritative pair on one actual\n * child without a wrapper, while keeping the context provider around it so portal descendants keep\n * their nearest explicit appearance. Child markers remain the child's identity.\n */\nexport const AppearanceBoundary = React.forwardRef<\n HTMLDivElement,\n AppearanceBoundaryProps\n>(function AppearanceBoundary(\n { mode, surface, asChild = false, className, children, ...props },\n ref\n) {\n const value = React.useMemo(\n () => canonicalAppearance({ mode, surface }),\n [mode, surface]\n )\n\n const content = asChild ? (\n <ComposeAsChild\n {...props}\n ref={ref}\n className={className}\n forceProps={{ \"data-theme\": value.mode, \"data-surface\": value.surface }}\n // Authoritative, spread LAST: required normalized props win over conflicting child attrs.\n data-theme={value.mode}\n data-surface={value.surface}\n >\n {children as React.ReactElement}\n </ComposeAsChild>\n ) : (\n <div\n ref={ref}\n data-slot=\"appearance-boundary\"\n {...{ [SLOT_ATTR]: \"appearance-boundary\" }}\n className={className}\n {...props}\n // Authoritative, spread LAST — the same ordering rule `DensityProvider` applies to\n // `data-density`. `AppearanceBoundaryProps` extends every native div prop, so a caller can\n // pass a raw conflicting `data-theme`/`data-surface`; the normalized required props win, and\n // the DOM attributes then always agree with the context value below.\n data-theme={value.mode}\n data-surface={value.surface}\n >\n {children}\n </div>\n )\n\n return (\n <AppearanceContext.Provider value={value}>\n {content}\n </AppearanceContext.Provider>\n )\n})\n\n/**\n * The nearest explicit boundary, or `undefined` when there is none. Package-internal — NOT exported\n * from `src/index.ts`; `AppearanceBoundary` is the whole public surface. Never reads\n * `getComputedStyle` or `documentElement`: `undefined` means \"no explicit boundary in the React\n * tree\", not \"the ambient appearance is unknown\".\n */\nexport const useAppearance = (): Appearance | undefined =>\n React.useContext(AppearanceContext)\n\n/**\n * The attributes a portal-content element re-stamps, or nothing at all. Portalled content is a\n * React-tree descendant but a DOM sibling, so a boundary's DOM attributes do not reach it while\n * its context does — exactly the asymmetry `DensityProvider` was built around (DENSITY-SPEC.md\n * §4.4).\n */\nexport const useAppearanceAttributes = (): {\n \"data-theme\"?: AppearanceMode\n \"data-surface\"?: AppearanceSurface\n} => {\n const appearance = useAppearance()\n return appearance === undefined\n ? {}\n : { \"data-theme\": appearance.mode, \"data-surface\": appearance.surface }\n}\n"],"names":["CANONICAL_MODES","CANONICAL_SURFACES","canonicalAppearance","appearance","AppearanceContext","React","AppearanceBoundary","mode","surface","asChild","className","children","props","ref","value","content","jsx","ComposeAsChild","SLOT_ATTR","useAppearance","useAppearanceAttributes"],"mappings":";;;;AAmBA,MAAMA,IAA6C,CAAC,SAAS,MAAM,GAC7DC,IAAmD;AAAA,EACvD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAGaC,IAAsB,CAACC,OAAwC;AAAA,EAC1E,MAAMH,EAAgB,SAASG,EAAW,IAAI,IAAIA,EAAW,OAAO;AAAA,EACpE,SAASF,EAAmB,SAASE,EAAW,OAAO,IACnDA,EAAW,UACX;AACN,IAQMC,IAAoBC,EAAM,cAAsC,MAAS,GA2BlEC,IAAqBD,EAAM,WAGtC,SACA,EAAE,MAAAE,GAAM,SAAAC,GAAS,SAAAC,IAAU,IAAO,WAAAC,GAAW,UAAAC,GAAU,GAAGC,EAAA,GAC1DC,GACA;AACA,QAAMC,IAAQT,EAAM;AAAA,IAClB,MAAMH,EAAoB,EAAE,MAAAK,GAAM,SAAAC,GAAS;AAAA,IAC3C,CAACD,GAAMC,CAAO;AAAA,EAAA,GAGVO,IAAUN,IACd,gBAAAO;AAAA,IAACC;AAAA,IAAA;AAAA,MACE,GAAGL;AAAA,MACJ,KAAAC;AAAA,MACA,WAAAH;AAAA,MACA,YAAY,EAAE,cAAcI,EAAM,MAAM,gBAAgBA,EAAM,QAAA;AAAA,MAE9D,cAAYA,EAAM;AAAA,MAClB,gBAAcA,EAAM;AAAA,MAEnB,UAAAH;AAAA,IAAA;AAAA,EAAA,IAGH,gBAAAK;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAH;AAAA,MACA,aAAU;AAAA,MACJ,CAACK,CAAS,GAAG;AAAA,MACnB,WAAAR;AAAA,MACC,GAAGE;AAAA,MAKJ,cAAYE,EAAM;AAAA,MAClB,gBAAcA,EAAM;AAAA,MAEnB,UAAAH;AAAA,IAAA;AAAA,EAAA;AAIL,SACE,gBAAAK,EAACZ,EAAkB,UAAlB,EAA2B,OAAAU,GACzB,UAAAC,GACH;AAEJ,CAAC,GAQYI,IAAgB,MAC3Bd,EAAM,WAAWD,CAAiB,GAQvBgB,IAA0B,MAGlC;AACH,QAAMjB,IAAagB,EAAA;AACnB,SAAOhB,MAAe,SAClB,CAAA,IACA,EAAE,cAAcA,EAAW,MAAM,gBAAgBA,EAAW,QAAA;AAClE;"}
1
+ {"version":3,"file":"appearance-boundary.js","sources":["../../../src/components/appearance-boundary/appearance-boundary.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { mergeClasses } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport * as tokens from \"../../tokens\"\nimport { ComposeAsChild } from \"../slot/compose-as-child\"\n\n/**\n * A region that carries its own appearance — `packages/tokens/SPEC.md` §2 rule 3's document\n * boundary, as a component instead of two hand-written DOM attributes.\n */\n\nexport type AppearanceMode = \"light\" | \"dark\"\n\n/**\n * Reduced from five to two on 2026-09-17: `glass`, `tint` and `card` were removed and `plain`\n * was renamed `flat`. `flat` is the root anchor, `bordered` the inheritance base (SPEC §2 rule 3).\n */\nexport type AppearanceSurface = \"flat\" | \"bordered\"\n\nexport type Appearance = {\n mode: AppearanceMode\n surface: AppearanceSurface\n}\n\nconst CANONICAL_MODES: readonly AppearanceMode[] = [\"light\", \"dark\"]\nconst CANONICAL_SURFACES: readonly AppearanceSurface[] = [\"flat\", \"bordered\"]\n\n/** Per-axis normalization of invalid runtime input, mirroring `canonicalDensity`. */\nexport const canonicalAppearance = (appearance: Appearance): Appearance => ({\n mode: CANONICAL_MODES.includes(appearance.mode) ? appearance.mode : \"light\",\n surface: CANONICAL_SURFACES.includes(appearance.surface)\n ? appearance.surface\n : \"flat\",\n})\n\n/**\n * Unexported, same as `DensityContext` — read only through `useAppearance()`. Default `undefined`:\n * a component with no `AppearanceBoundary` ancestor gets `undefined`, never a fabricated\n * `{light, plain}`, which would be this package inventing a reading of the live shell attributes it\n * deliberately does not read.\n */\nconst AppearanceContext = React.createContext<Appearance | undefined>(undefined)\n\n/**\n * A mode is a canvas, so a region that restates one has to paint it. `flat` leaves\n * `surface.object` transparent, which means a boundary that only stamped the attributes let the\n * page behind it show through: a `mode=\"light\"` region on a dark page rendered light ink onto the\n * dark page at 1.08:1. Painting `body` is what makes \"regardless of the page's\" true.\n *\n * Skipped when the nearest ancestor boundary already declares this mode, so restating a mode\n * inside a region that has one stays transparent and composes as before.\n */\nconst useCanvasStyles = makeZenithStyles({\n canvas: { backgroundColor: tokens.body },\n})\n\ntype AppearanceBoundaryBaseProps = Omit<\n React.ComponentProps<\"div\">,\n \"children\"\n> & {\n /** The mode this region renders in, regardless of the page's. No default. */\n mode: AppearanceMode\n /** The treatment this region restates. Required — see the note on both props above. */\n surface: AppearanceSurface\n}\n\nexport type AppearanceBoundaryProps =\n | (AppearanceBoundaryBaseProps & {\n asChild?: false\n children?: React.ReactNode\n })\n | (AppearanceBoundaryBaseProps & {\n asChild: true\n children: React.ReactElement\n })\n\n/**\n * The default is one ordinary HTML div. `asChild` stamps the same authoritative pair on one actual\n * child without a wrapper, while keeping the context provider around it so portal descendants keep\n * their nearest explicit appearance. Child markers remain the child's identity.\n */\nexport const AppearanceBoundary = React.forwardRef<\n HTMLDivElement,\n AppearanceBoundaryProps\n>(function AppearanceBoundary(\n { mode, surface, asChild = false, className, children, ...props },\n ref\n) {\n const value = React.useMemo(\n () => canonicalAppearance({ mode, surface }),\n [mode, surface]\n )\n\n const inherited = useAppearance()\n const styles = useCanvasStyles()\n const merged =\n inherited?.mode === value.mode\n ? className\n : mergeClasses(styles.canvas, className)\n\n const content = asChild ? (\n <ComposeAsChild\n {...props}\n ref={ref}\n className={merged}\n forceProps={{ \"data-theme\": value.mode, \"data-surface\": value.surface }}\n // Authoritative, spread LAST: required normalized props win over conflicting child attrs.\n data-theme={value.mode}\n data-surface={value.surface}\n >\n {children as React.ReactElement}\n </ComposeAsChild>\n ) : (\n <div\n ref={ref}\n data-slot=\"appearance-boundary\"\n {...{ [SLOT_ATTR]: \"appearance-boundary\" }}\n className={merged}\n {...props}\n // Authoritative, spread LAST — the same ordering rule `DensityProvider` applies to\n // `data-density`. `AppearanceBoundaryProps` extends every native div prop, so a caller can\n // pass a raw conflicting `data-theme`/`data-surface`; the normalized required props win, and\n // the DOM attributes then always agree with the context value below.\n data-theme={value.mode}\n data-surface={value.surface}\n >\n {children}\n </div>\n )\n\n return (\n <AppearanceContext.Provider value={value}>\n {content}\n </AppearanceContext.Provider>\n )\n})\n\n/**\n * The nearest explicit boundary, or `undefined` when there is none. Package-internal — NOT exported\n * from `src/index.ts`; `AppearanceBoundary` is the whole public surface. Never reads\n * `getComputedStyle` or `documentElement`: `undefined` means \"no explicit boundary in the React\n * tree\", not \"the ambient appearance is unknown\".\n */\nexport const useAppearance = (): Appearance | undefined =>\n React.useContext(AppearanceContext)\n\n/**\n * The attributes a portal-content element re-stamps, or nothing at all. Portalled content is a\n * React-tree descendant but a DOM sibling, so a boundary's DOM attributes do not reach it while\n * its context does — exactly the asymmetry `DensityProvider` was built around (DENSITY-SPEC.md\n * §4.4).\n */\nexport const useAppearanceAttributes = (): {\n \"data-theme\"?: AppearanceMode\n \"data-surface\"?: AppearanceSurface\n} => {\n const appearance = useAppearance()\n return appearance === undefined\n ? {}\n : { \"data-theme\": appearance.mode, \"data-surface\": appearance.surface }\n}\n"],"names":["CANONICAL_MODES","CANONICAL_SURFACES","canonicalAppearance","appearance","AppearanceContext","React","useCanvasStyles","makeZenithStyles","tokens.body","AppearanceBoundary","mode","surface","asChild","className","children","props","ref","value","inherited","useAppearance","styles","merged","mergeClasses","content","jsx","ComposeAsChild","SLOT_ATTR","useAppearanceAttributes"],"mappings":";;;;;;AA2BA,MAAMA,IAA6C,CAAC,SAAS,MAAM,GAC7DC,IAAmD,CAAC,QAAQ,UAAU,GAG/DC,IAAsB,CAACC,OAAwC;AAAA,EAC1E,MAAMH,EAAgB,SAASG,EAAW,IAAI,IAAIA,EAAW,OAAO;AAAA,EACpE,SAASF,EAAmB,SAASE,EAAW,OAAO,IACnDA,EAAW,UACX;AACN,IAQMC,IAAoBC,EAAM,cAAsC,MAAS,GAWzEC,IAAkBC,EAAiB;AAAA,EACvC,QAAQ,EAAE,iBAAiBC,EAAO;AACpC,CAAC,GA2BYC,IAAqBJ,EAAM,WAGtC,SACA,EAAE,MAAAK,GAAM,SAAAC,GAAS,SAAAC,IAAU,IAAO,WAAAC,GAAW,UAAAC,GAAU,GAAGC,EAAA,GAC1DC,GACA;AACA,QAAMC,IAAQZ,EAAM;AAAA,IAClB,MAAMH,EAAoB,EAAE,MAAAQ,GAAM,SAAAC,GAAS;AAAA,IAC3C,CAACD,GAAMC,CAAO;AAAA,EAAA,GAGVO,IAAYC,EAAA,GACZC,IAASd,EAAA,GACTe,KACJH,KAAA,gBAAAA,EAAW,UAASD,EAAM,OACtBJ,IACAS,EAAaF,EAAO,QAAQP,CAAS,GAErCU,IAAUX,IACd,gBAAAY;AAAA,IAACC;AAAA,IAAA;AAAA,MACE,GAAGV;AAAA,MACJ,KAAAC;AAAA,MACA,WAAWK;AAAA,MACX,YAAY,EAAE,cAAcJ,EAAM,MAAM,gBAAgBA,EAAM,QAAA;AAAA,MAE9D,cAAYA,EAAM;AAAA,MAClB,gBAAcA,EAAM;AAAA,MAEnB,UAAAH;AAAA,IAAA;AAAA,EAAA,IAGH,gBAAAU;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAR;AAAA,MACA,aAAU;AAAA,MACJ,CAACU,CAAS,GAAG;AAAA,MACnB,WAAWL;AAAA,MACV,GAAGN;AAAA,MAKJ,cAAYE,EAAM;AAAA,MAClB,gBAAcA,EAAM;AAAA,MAEnB,UAAAH;AAAA,IAAA;AAAA,EAAA;AAIL,SACE,gBAAAU,EAACpB,EAAkB,UAAlB,EAA2B,OAAAa,GACzB,UAAAM,GACH;AAEJ,CAAC,GAQYJ,IAAgB,MAC3Bd,EAAM,WAAWD,CAAiB,GAQvBuB,IAA0B,MAGlC;AACH,QAAMxB,IAAagB,EAAA;AACnB,SAAOhB,MAAe,SAClB,CAAA,IACA,EAAE,cAAcA,EAAW,MAAM,gBAAgBA,EAAW,QAAA;AAClE;"}
@@ -31,7 +31,7 @@ const X = [
31
31
  "bronze"
32
32
  ], o = "--zenith-badge-bg", a = "--zenith-badge-fg", s = "--zenith-badge-bd", m = (e) => e === "neutral" ? "gray" : e, d = (e) => I(e) ? W : E, n = (e, r) => {
33
33
  const t = m(e);
34
- return `var(--zenith-${d(t)}-sem-${t}-${r})`;
34
+ return `var(--zenith-${d(t)}-${t}-${r})`;
35
35
  }, F = (e, r) => {
36
36
  const t = m(e);
37
37
  return `var(--zenith-${d(t)}-${t}-${r})`;
@@ -1 +1 @@
1
- {"version":3,"file":"badge.js","sources":["../../../src/components/badge/badge.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport { NS, PALETTE_NS } from \"../../tokens\"\nimport { isCoreFamily } from \"../../tokens/install\"\nimport { useZenithPaletteTokensFor } from \"../../tokens/use-palette-tokens\"\nimport * as tokens from \"../../tokens\"\n\n/**\n * REFERENCE COMPONENT — the colour-matrix collapse. Read this before writing another component\n * that takes a `color` prop.\n */\n\nconst COLORS = [\n \"accent\",\n \"neutral\",\n \"gray\",\n \"success\",\n \"warning\",\n \"error\",\n \"info\",\n \"blue\",\n \"sky\",\n \"mint\",\n \"lime\",\n \"green\",\n \"teal\",\n \"cyan\",\n \"indigo\",\n \"purple\",\n \"pink\",\n \"red\",\n \"orange\",\n \"yellow\",\n \"bronze\",\n] as const\n\nexport type BadgeColor = (typeof COLORS)[number]\nexport type BadgeVariant = \"soft\" | \"solid\" | \"surface\"\nexport type BadgeSize = \"sm\" | \"base\" | \"lg\"\n\n/** The three slots a variant can paint. Set inline; read by the atoms below. */\nconst BG = \"--zenith-badge-bg\"\nconst FG = \"--zenith-badge-fg\"\nconst BD = \"--zenith-badge-bd\"\n\nconst resolveColor = (color: BadgeColor): string =>\n color === \"neutral\" ? \"gray\" : color\n\n/**\n * The namespace fix. `resolveColor` runs FIRST so `neutral` is classified as `gray` (core) rather\n * than as the literal string \"neutral\" (which is in neither sheet's family list) — same order\n * `semantic`/`primitive` already apply it in.\n */\nconst namespaceFor = (family: string): string =>\n isCoreFamily(family) ? NS : PALETTE_NS\n\nconst semantic = (color: BadgeColor, slot: string): string => {\n const family = resolveColor(color)\n return `var(--zenith-${namespaceFor(family)}-sem-${family}-${slot})`\n}\nconst primitive = (color: BadgeColor, step: string): string => {\n const family = resolveColor(color)\n return `var(--zenith-${namespaceFor(family)}-${family}-${step})`\n}\n\n/**\n * Which token each variant pulls into each slot. This replaces the 60-entry compound matrix: it is\n * data about three variants, not about 60 combinations.\n */\nconst VARIANT_SLOTS: Record<\n BadgeVariant,\n (color: BadgeColor) => Record<string, string>\n> = {\n soft: (c) => ({\n [BG]: semantic(c, \"soft\"),\n [FG]: semantic(c, \"default\"),\n [BD]: \"transparent\",\n }),\n solid: (c) => ({\n [BG]: semantic(c, \"solid\"),\n [FG]: semantic(c, \"contrast\"),\n [BD]: \"transparent\",\n }),\n surface: (c) => ({\n [BG]: semantic(c, \"surface\"),\n [FG]: semantic(c, \"default\"),\n [BD]: primitive(c, \"a6\"),\n }),\n}\n\nconst useStyles = makeZenithStyles({\n root: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"fit-content\",\n whiteSpace: \"nowrap\",\n flexShrink: 0,\n overflow: \"hidden\",\n fontWeight: tokens.fontWeightNormal,\n // NEVER write a CSS shorthand in a Griffel style object. Atoms are one declaration each, so a\n // shorthand cannot be resolved against a longhand — `border` and a later `borderColor` would\n // both survive with the winner decided by insertion order. Griffel warns at runtime, which\n // means the mistake ships silently in production where nobody reads the console.\n // `shorthands.*` expands to the individual longhands.\n ...shorthands.border(\"1px\", \"solid\", `var(${BD})`),\n // The whole point: one rule each, colour supplied per instance.\n backgroundColor: `var(${BG})`,\n color: `var(${FG})`,\n transitionProperty: \"color, box-shadow\",\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineOffset: \"2px\",\n outlineColor: tokens.accentA8,\n },\n // v1 `aria-invalid:outline-error-a8`. Declared after the focus ring so an invalid focused\n // badge paints the error ring, matching v1's variant ordering.\n \"&[aria-invalid]\": {\n outlineColor: tokens.errorA8,\n },\n \"& > svg\": { pointerEvents: \"none\" },\n },\n sm: {\n fontSize: tokens.textXs,\n lineHeight: \"1rem\",\n letterSpacing: \"0.04px\",\n gap: tokens.spacingElement1,\n paddingInline: tokens.spacingElement1,\n minWidth: \"1rem\",\n borderRadius: \"3px\",\n \"& > svg\": { width: \"0.75rem\", height: \"0.75rem\" },\n },\n base: {\n fontSize: tokens.textSm,\n lineHeight: \"1.25rem\",\n gap: tokens.spacingElement1,\n paddingInline: tokens.spacingElement2,\n minWidth: \"1.25rem\",\n borderRadius: tokens.radiusSm,\n \"& > svg\": { width: \"1rem\", height: \"1rem\" },\n },\n lg: {\n fontSize: tokens.textBase,\n lineHeight: \"1.5rem\",\n gap: tokens.spacingElement1,\n paddingInline: tokens.spacingElement3,\n minWidth: \"1.5rem\",\n borderRadius: tokens.radiusMd,\n \"& > svg\": { width: \"1rem\", height: \"1rem\" },\n },\n})\n\nexport type BadgeProps = Omit<React.ComponentProps<\"span\">, \"color\"> & {\n color?: BadgeColor\n /**\n * Named `variant`, not `style`. v1 called this `style`, which shadows the HTML `style` attribute\n * and made a badge unable to take both a visual treatment and an inline style. Retrocompat is\n * not a requirement here, so the collision is fixed rather than inherited.\n */\n variant?: BadgeVariant\n size?: BadgeSize\n}\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n function Badge(\n {\n className,\n color = \"accent\",\n variant = \"soft\",\n size = \"base\",\n style,\n ...props\n },\n ref\n ) {\n // A decorative family can still arrive from an expression the build cannot see, so this has to\n // be re-evaluated every commit (WP2B2 — the hook closes over this render's resolved value) —\n // but it is the resolved family that decides, and a core one needs no palette sheet.\n useZenithPaletteTokensFor(color)\n\n const styles = useStyles()\n\n return (\n <span\n ref={ref}\n data-slot=\"badge\"\n {...{ [SLOT_ATTR]: \"badge\" }}\n className={mergeClasses(styles.root, styles[size], className)}\n style={\n { ...VARIANT_SLOTS[variant](color), ...style } as React.CSSProperties\n }\n {...props}\n />\n )\n }\n)\n\nexport { COLORS as BADGE_COLORS }\n"],"names":["COLORS","BG","FG","BD","resolveColor","color","namespaceFor","family","isCoreFamily","NS","PALETTE_NS","semantic","slot","primitive","step","VARIANT_SLOTS","c","useStyles","makeZenithStyles","tokens.fontWeightNormal","shorthands","tokens.accentA8","tokens.errorA8","tokens.textXs","tokens.spacingElement1","tokens.textSm","tokens.spacingElement2","tokens.radiusSm","tokens.textBase","tokens.spacingElement3","tokens.radiusMd","Badge","React","className","variant","size","style","props","ref","useZenithPaletteTokensFor","styles","jsx","SLOT_ATTR","mergeClasses"],"mappings":"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"}
1
+ {"version":3,"file":"badge.js","sources":["../../../src/components/badge/badge.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport { NS, PALETTE_NS } from \"../../tokens\"\nimport { isCoreFamily } from \"../../tokens/install\"\nimport { useZenithPaletteTokensFor } from \"../../tokens/use-palette-tokens\"\nimport * as tokens from \"../../tokens\"\n\n/**\n * REFERENCE COMPONENT — the colour-matrix collapse. Read this before writing another component\n * that takes a `color` prop.\n */\n\nconst COLORS = [\n \"accent\",\n \"neutral\",\n \"gray\",\n \"success\",\n \"warning\",\n \"error\",\n \"info\",\n \"blue\",\n \"sky\",\n \"mint\",\n \"lime\",\n \"green\",\n \"teal\",\n \"cyan\",\n \"indigo\",\n \"purple\",\n \"pink\",\n \"red\",\n \"orange\",\n \"yellow\",\n \"bronze\",\n] as const\n\nexport type BadgeColor = (typeof COLORS)[number]\nexport type BadgeVariant = \"soft\" | \"solid\" | \"surface\"\nexport type BadgeSize = \"sm\" | \"base\" | \"lg\"\n\n/** The three slots a variant can paint. Set inline; read by the atoms below. */\nconst BG = \"--zenith-badge-bg\"\nconst FG = \"--zenith-badge-fg\"\nconst BD = \"--zenith-badge-bd\"\n\nconst resolveColor = (color: BadgeColor): string =>\n color === \"neutral\" ? \"gray\" : color\n\n/**\n * The namespace fix. `resolveColor` runs FIRST so `neutral` is classified as `gray` (core) rather\n * than as the literal string \"neutral\" (which is in neither sheet's family list) — same order\n * `semantic`/`primitive` already apply it in.\n */\nconst namespaceFor = (family: string): string =>\n isCoreFamily(family) ? NS : PALETTE_NS\n\nconst semantic = (color: BadgeColor, slot: string): string => {\n const family = resolveColor(color)\n return `var(--zenith-${namespaceFor(family)}-${family}-${slot})`\n}\nconst primitive = (color: BadgeColor, step: string): string => {\n const family = resolveColor(color)\n return `var(--zenith-${namespaceFor(family)}-${family}-${step})`\n}\n\n/**\n * Which token each variant pulls into each slot. This replaces the 60-entry compound matrix: it is\n * data about three variants, not about 60 combinations.\n */\nconst VARIANT_SLOTS: Record<\n BadgeVariant,\n (color: BadgeColor) => Record<string, string>\n> = {\n soft: (c) => ({\n [BG]: semantic(c, \"soft\"),\n [FG]: semantic(c, \"default\"),\n [BD]: \"transparent\",\n }),\n solid: (c) => ({\n [BG]: semantic(c, \"solid\"),\n [FG]: semantic(c, \"contrast\"),\n [BD]: \"transparent\",\n }),\n surface: (c) => ({\n [BG]: semantic(c, \"surface\"),\n [FG]: semantic(c, \"default\"),\n [BD]: primitive(c, \"a6\"),\n }),\n}\n\nconst useStyles = makeZenithStyles({\n root: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: \"fit-content\",\n whiteSpace: \"nowrap\",\n flexShrink: 0,\n overflow: \"hidden\",\n fontWeight: tokens.fontWeightNormal,\n // NEVER write a CSS shorthand in a Griffel style object. Atoms are one declaration each, so a\n // shorthand cannot be resolved against a longhand — `border` and a later `borderColor` would\n // both survive with the winner decided by insertion order. Griffel warns at runtime, which\n // means the mistake ships silently in production where nobody reads the console.\n // `shorthands.*` expands to the individual longhands.\n ...shorthands.border(\"1px\", \"solid\", `var(${BD})`),\n // The whole point: one rule each, colour supplied per instance.\n backgroundColor: `var(${BG})`,\n color: `var(${FG})`,\n transitionProperty: \"color, box-shadow\",\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineOffset: \"2px\",\n outlineColor: tokens.accentA8,\n },\n // v1 `aria-invalid:outline-error-a8`. Declared after the focus ring so an invalid focused\n // badge paints the error ring, matching v1's variant ordering.\n \"&[aria-invalid]\": {\n outlineColor: tokens.errorA8,\n },\n \"& > svg\": { pointerEvents: \"none\" },\n },\n sm: {\n fontSize: tokens.textXs,\n lineHeight: \"1rem\",\n letterSpacing: \"0.04px\",\n gap: tokens.spacingElement1,\n paddingInline: tokens.spacingElement1,\n minWidth: \"1rem\",\n borderRadius: \"3px\",\n \"& > svg\": { width: \"0.75rem\", height: \"0.75rem\" },\n },\n base: {\n fontSize: tokens.textSm,\n lineHeight: \"1.25rem\",\n gap: tokens.spacingElement1,\n paddingInline: tokens.spacingElement2,\n minWidth: \"1.25rem\",\n borderRadius: tokens.radiusSm,\n \"& > svg\": { width: \"1rem\", height: \"1rem\" },\n },\n lg: {\n fontSize: tokens.textBase,\n lineHeight: \"1.5rem\",\n gap: tokens.spacingElement1,\n paddingInline: tokens.spacingElement3,\n minWidth: \"1.5rem\",\n borderRadius: tokens.radiusMd,\n \"& > svg\": { width: \"1rem\", height: \"1rem\" },\n },\n})\n\nexport type BadgeProps = Omit<React.ComponentProps<\"span\">, \"color\"> & {\n color?: BadgeColor\n /**\n * Named `variant`, not `style`. v1 called this `style`, which shadows the HTML `style` attribute\n * and made a badge unable to take both a visual treatment and an inline style. Retrocompat is\n * not a requirement here, so the collision is fixed rather than inherited.\n */\n variant?: BadgeVariant\n size?: BadgeSize\n}\n\nexport const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(\n function Badge(\n {\n className,\n color = \"accent\",\n variant = \"soft\",\n size = \"base\",\n style,\n ...props\n },\n ref\n ) {\n // A decorative family can still arrive from an expression the build cannot see, so this has to\n // be re-evaluated every commit (WP2B2 — the hook closes over this render's resolved value) —\n // but it is the resolved family that decides, and a core one needs no palette sheet.\n useZenithPaletteTokensFor(color)\n\n const styles = useStyles()\n\n return (\n <span\n ref={ref}\n data-slot=\"badge\"\n {...{ [SLOT_ATTR]: \"badge\" }}\n className={mergeClasses(styles.root, styles[size], className)}\n style={\n { ...VARIANT_SLOTS[variant](color), ...style } as React.CSSProperties\n }\n {...props}\n />\n )\n }\n)\n\nexport { COLORS as BADGE_COLORS }\n"],"names":["COLORS","BG","FG","BD","resolveColor","color","namespaceFor","family","isCoreFamily","NS","PALETTE_NS","semantic","slot","primitive","step","VARIANT_SLOTS","c","useStyles","makeZenithStyles","tokens.fontWeightNormal","shorthands","tokens.accentA8","tokens.errorA8","tokens.textXs","tokens.spacingElement1","tokens.textSm","tokens.spacingElement2","tokens.radiusSm","tokens.textBase","tokens.spacingElement3","tokens.radiusMd","Badge","React","className","variant","size","style","props","ref","useZenithPaletteTokensFor","styles","jsx","SLOT_ATTR","mergeClasses"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { jsx as e, jsxs as x } from "react/jsx-runtime";
2
2
  import * as o from "react";
3
3
  import { SLOT_ATTR as c, mergeClasses as u, shorthands as b } from "@epilot/zenith-runtime/v1";
4
4
  import { makeZenithStyles as B } from "../../styles/make-styles.js";
5
- import { semGrayDefault as p, fontWeightSemibold as f, accentA8 as L, semGrayLight as g, leadingBase as R, textBase as S, spacingElement1 as I, spacingElement2 as N } from "../../tokens/index.js";
5
+ import { grayDefault as p, fontWeightSemibold as f, accentA8 as L, grayLight as g, leadingBase as R, textBase as S, spacingElement1 as I, spacingElement2 as N } from "../../tokens/index.js";
6
6
  import { Root as T } from "../../vendor/.bun/@radix-ui_react-slot@1.2.4_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js";
7
7
  const h = B({
8
8
  list: {
@@ -45,24 +45,24 @@ const h = B({
45
45
  color: p
46
46
  }
47
47
  }), w = o.forwardRef(
48
- function({ separator: t = "/", className: a, children: i, ...n }, s) {
49
- const l = h(), m = o.Children.toArray(i).filter(o.isValidElement);
48
+ function({ separator: t = "/", className: a, children: i, ...n }, l) {
49
+ const s = h(), m = o.Children.toArray(i).filter(o.isValidElement);
50
50
  return /* @__PURE__ */ e(
51
51
  "nav",
52
52
  {
53
- ref: s,
53
+ ref: l,
54
54
  "data-slot": "breadcrumb",
55
55
  [c]: "breadcrumb",
56
56
  "aria-label": "Breadcrumb",
57
57
  className: a,
58
58
  ...n,
59
- children: /* @__PURE__ */ e("ol", { className: l.list, children: m.map((r, d) => /* @__PURE__ */ x(o.Fragment, { children: [
59
+ children: /* @__PURE__ */ e("ol", { className: s.list, children: m.map((r, d) => /* @__PURE__ */ x(o.Fragment, { children: [
60
60
  d > 0 && /* @__PURE__ */ e(
61
61
  "li",
62
62
  {
63
63
  role: "presentation",
64
64
  "aria-hidden": "true",
65
- className: l.separator,
65
+ className: s.separator,
66
66
  children: t
67
67
  }
68
68
  ),
@@ -71,16 +71,16 @@ const h = B({
71
71
  }
72
72
  );
73
73
  }
74
- ), z = o.forwardRef(function({ href: t, isCurrent: a = !1, className: i, children: n, asChild: s = !1, ...l }, m) {
75
- const r = h(), y = !!t || s ? /* @__PURE__ */ e(
76
- s ? T : "a",
74
+ ), z = o.forwardRef(function({ href: t, isCurrent: a = !1, className: i, children: n, asChild: l = !1, ...s }, m) {
75
+ const r = h(), y = !!t || l ? /* @__PURE__ */ e(
76
+ l ? T : "a",
77
77
  {
78
78
  "data-slot": "breadcrumb-link",
79
79
  [c]: "breadcrumb-link",
80
80
  ...t ? { href: t } : {},
81
81
  className: u(r.link, i),
82
82
  ...a ? { "aria-current": "page" } : {},
83
- ...l,
83
+ ...s,
84
84
  children: n
85
85
  }
86
86
  ) : /* @__PURE__ */ e(
@@ -1 +1 @@
1
- {"version":3,"file":"breadcrumb.js","sources":["../../../src/components/breadcrumb/breadcrumb.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport * as tokens from \"../../tokens\"\nimport { Slot } from \"@radix-ui/react-slot\"\n\n/** Breadcrumb — Card's compound pattern applied to the nav / ol / li structure. */\n\nexport type BreadcrumbProps = React.ComponentProps<\"nav\"> & {\n separator?: React.ReactNode\n}\n\nconst useStyles = makeZenithStyles({\n list: {\n display: \"flex\",\n alignItems: \"center\",\n // gap-2\n ...shorthands.gap(tokens.spacingElement2),\n fontSize: tokens.textBase,\n lineHeight: tokens.leadingBase,\n },\n separator: {\n color: tokens.semGrayLight,\n },\n item: {\n display: \"inline-flex\",\n alignItems: \"center\",\n // gap-1\n ...shorthands.gap(tokens.spacingElement1),\n },\n link: {\n fontWeight: tokens.fontWeightSemibold,\n color: tokens.semGrayLight,\n transitionProperty:\n \"color, background-color, border-color, text-decoration-color, fill, stroke\",\n transitionDuration: \"150ms\",\n transitionTimingFunction: \"cubic-bezier(0.4, 0, 0.2, 1)\",\n cursor: \"pointer\",\n \":hover\": {\n color: tokens.semGrayDefault,\n textDecorationLine: \"underline\",\n },\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineOffset: \"2px\",\n outlineColor: tokens.accentA8,\n },\n },\n page: {\n fontWeight: tokens.fontWeightSemibold,\n color: tokens.semGrayDefault,\n },\n})\n\nexport const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(\n function Breadcrumb({ separator = \"/\", className, children, ...props }, ref) {\n const styles = useStyles()\n const items = React.Children.toArray(children).filter(React.isValidElement)\n\n return (\n <nav\n ref={ref}\n data-slot=\"breadcrumb\"\n {...{ [SLOT_ATTR]: \"breadcrumb\" }}\n aria-label=\"Breadcrumb\"\n className={className}\n {...props}\n >\n <ol className={styles.list}>\n {items.map((child, index) => (\n <React.Fragment key={index}>\n {index > 0 && (\n <li\n role=\"presentation\"\n aria-hidden=\"true\"\n className={styles.separator}\n >\n {separator}\n </li>\n )}\n {child}\n </React.Fragment>\n ))}\n </ol>\n </nav>\n )\n }\n)\n\nexport type BreadcrumbItemProps = Omit<React.ComponentProps<\"a\">, \"href\"> & {\n href?: string\n isCurrent?: boolean\n /**\n * Render the child instead of the built-in `a`, keeping the link styling and slot markers. This\n * is how a consumer supplies a router link. v1 supports it; it was dropped here while the package\n * was on Base UI and restored once it moved back to Radix.\n */\n asChild?: boolean\n}\n\nexport const BreadcrumbItem = React.forwardRef<\n HTMLLIElement,\n BreadcrumbItemProps\n>(function BreadcrumbItem(\n { href, isCurrent = false, className, children, asChild = false, ...props },\n ref\n) {\n const styles = useStyles()\n const isLink = !!href\n\n const LinkRoot = asChild ? Slot : \"a\"\n\n const content =\n isLink || asChild ? (\n <LinkRoot\n data-slot=\"breadcrumb-link\"\n {...{ [SLOT_ATTR]: \"breadcrumb-link\" }}\n {...(href ? { href } : {})}\n className={mergeClasses(styles.link, className)}\n {...(isCurrent ? { \"aria-current\": \"page\" as const } : {})}\n {...props}\n >\n {children}\n </LinkRoot>\n ) : (\n <span\n data-slot=\"breadcrumb-page\"\n {...{ [SLOT_ATTR]: \"breadcrumb-page\" }}\n className={mergeClasses(styles.page, className)}\n {...(isCurrent ? { \"aria-current\": \"page\" as const } : {})}\n >\n {children}\n </span>\n )\n\n return (\n <li\n ref={ref}\n data-slot=\"breadcrumb-item\"\n {...{ [SLOT_ATTR]: \"breadcrumb-item\" }}\n className={styles.item}\n >\n {content}\n </li>\n )\n})\n"],"names":["useStyles","makeZenithStyles","shorthands","tokens.spacingElement2","tokens.textBase","tokens.leadingBase","tokens.semGrayLight","tokens.spacingElement1","tokens.fontWeightSemibold","tokens.semGrayDefault","tokens.accentA8","Breadcrumb","React","separator","className","children","props","ref","styles","items","jsx","SLOT_ATTR","child","index","jsxs","BreadcrumbItem","href","isCurrent","asChild","content","Slot","mergeClasses"],"mappings":"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"}
1
+ {"version":3,"file":"breadcrumb.js","sources":["../../../src/components/breadcrumb/breadcrumb.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport * as tokens from \"../../tokens\"\nimport { Slot } from \"@radix-ui/react-slot\"\n\n/** Breadcrumb — Card's compound pattern applied to the nav / ol / li structure. */\n\nexport type BreadcrumbProps = React.ComponentProps<\"nav\"> & {\n separator?: React.ReactNode\n}\n\nconst useStyles = makeZenithStyles({\n list: {\n display: \"flex\",\n alignItems: \"center\",\n // gap-2\n ...shorthands.gap(tokens.spacingElement2),\n fontSize: tokens.textBase,\n lineHeight: tokens.leadingBase,\n },\n separator: {\n color: tokens.grayLight,\n },\n item: {\n display: \"inline-flex\",\n alignItems: \"center\",\n // gap-1\n ...shorthands.gap(tokens.spacingElement1),\n },\n link: {\n fontWeight: tokens.fontWeightSemibold,\n color: tokens.grayLight,\n transitionProperty:\n \"color, background-color, border-color, text-decoration-color, fill, stroke\",\n transitionDuration: \"150ms\",\n transitionTimingFunction: \"cubic-bezier(0.4, 0, 0.2, 1)\",\n cursor: \"pointer\",\n \":hover\": {\n color: tokens.grayDefault,\n textDecorationLine: \"underline\",\n },\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineOffset: \"2px\",\n outlineColor: tokens.accentA8,\n },\n },\n page: {\n fontWeight: tokens.fontWeightSemibold,\n color: tokens.grayDefault,\n },\n})\n\nexport const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(\n function Breadcrumb({ separator = \"/\", className, children, ...props }, ref) {\n const styles = useStyles()\n const items = React.Children.toArray(children).filter(React.isValidElement)\n\n return (\n <nav\n ref={ref}\n data-slot=\"breadcrumb\"\n {...{ [SLOT_ATTR]: \"breadcrumb\" }}\n aria-label=\"Breadcrumb\"\n className={className}\n {...props}\n >\n <ol className={styles.list}>\n {items.map((child, index) => (\n <React.Fragment key={index}>\n {index > 0 && (\n <li\n role=\"presentation\"\n aria-hidden=\"true\"\n className={styles.separator}\n >\n {separator}\n </li>\n )}\n {child}\n </React.Fragment>\n ))}\n </ol>\n </nav>\n )\n }\n)\n\nexport type BreadcrumbItemProps = Omit<React.ComponentProps<\"a\">, \"href\"> & {\n href?: string\n isCurrent?: boolean\n /**\n * Render the child instead of the built-in `a`, keeping the link styling and slot markers. This\n * is how a consumer supplies a router link. v1 supports it; it was dropped here while the package\n * was on Base UI and restored once it moved back to Radix.\n */\n asChild?: boolean\n}\n\nexport const BreadcrumbItem = React.forwardRef<\n HTMLLIElement,\n BreadcrumbItemProps\n>(function BreadcrumbItem(\n { href, isCurrent = false, className, children, asChild = false, ...props },\n ref\n) {\n const styles = useStyles()\n const isLink = !!href\n\n const LinkRoot = asChild ? Slot : \"a\"\n\n const content =\n isLink || asChild ? (\n <LinkRoot\n data-slot=\"breadcrumb-link\"\n {...{ [SLOT_ATTR]: \"breadcrumb-link\" }}\n {...(href ? { href } : {})}\n className={mergeClasses(styles.link, className)}\n {...(isCurrent ? { \"aria-current\": \"page\" as const } : {})}\n {...props}\n >\n {children}\n </LinkRoot>\n ) : (\n <span\n data-slot=\"breadcrumb-page\"\n {...{ [SLOT_ATTR]: \"breadcrumb-page\" }}\n className={mergeClasses(styles.page, className)}\n {...(isCurrent ? { \"aria-current\": \"page\" as const } : {})}\n >\n {children}\n </span>\n )\n\n return (\n <li\n ref={ref}\n data-slot=\"breadcrumb-item\"\n {...{ [SLOT_ATTR]: \"breadcrumb-item\" }}\n className={styles.item}\n >\n {content}\n </li>\n )\n})\n"],"names":["useStyles","makeZenithStyles","shorthands","tokens.spacingElement2","tokens.textBase","tokens.leadingBase","tokens.grayLight","tokens.spacingElement1","tokens.fontWeightSemibold","tokens.grayDefault","tokens.accentA8","Breadcrumb","React","separator","className","children","props","ref","styles","items","jsx","SLOT_ATTR","child","index","jsxs","BreadcrumbItem","href","isCurrent","asChild","content","Slot","mergeClasses"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as b } from "react/jsx-runtime";
2
- import * as s from "react";
2
+ import * as a from "react";
3
3
  import { mergeClasses as w, SLOT_ATTR as B, shorthands as n } from "@epilot/zenith-runtime/v1";
4
4
  import { makeZenithStyles as H } from "../../styles/make-styles.js";
5
- import { capTrim as E } from "../../styles/text-box.js";
6
- import { radiusLg as A, buttonIconSize as g, leadingLg as R, textLg as I, leadingBase as z, textBase as L, buttonBaseMinHeight as O, leadingSm as T, textSm as D, leadingXs as P, textXs as X, semErrorSoft as h, errorA11 as $, semErrorSoftHover as V, semErrorOnSoft as W, semErrorSolidHover as u, semErrorContrast as j, semErrorSolid as F, semAccentSoft as d, grayA12 as M, accentA11 as N, semAccentSoftHover as K, semAccentOnSoft as Z, semAccentSolidHover as p, semAccentContrast as _, semAccentSolid as q, semFocusRing as G, fontWeightSemibold as J, buttonBasePaddingInline as Q, spacingElement3 as U } from "../../tokens/index.js";
5
+ import { capTrim as R } from "../../styles/text-box.js";
6
+ import { radiusLg as I, buttonIconSize as m, leadingLg as z, textLg as E, leadingBase as L, textBase as O, buttonBaseMinHeight as T, leadingSm as A, textSm as D, leadingXs as P, textXs as X, errorSoft as h, errorA11 as $, errorSoftHover as V, errorOnSoft as W, errorSolidHover as u, errorContrast as j, errorSolid as M, accentSoft as d, grayA12 as N, accentA11 as F, accentSoftHover as K, accentOnSoft as Z, accentSolidHover as p, accentContrast as _, accentSolid as q, focusRing as G, fontWeightSemibold as J, buttonBasePaddingInline as Q, spacingElement3 as U } from "../../tokens/index.js";
7
7
  import { Root as Y } from "../../vendor/.bun/@radix-ui_react-slot@1.2.4_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js";
8
8
  const ee = "button", oe = H({
9
9
  root: {
@@ -33,7 +33,7 @@ const ee = "button", oe = H({
33
33
  color: "currentColor"
34
34
  }
35
35
  },
36
- label: E,
36
+ label: R,
37
37
  primary: {
38
38
  backgroundColor: q,
39
39
  color: _,
@@ -47,16 +47,16 @@ const ee = "button", oe = H({
47
47
  },
48
48
  tertiary: {
49
49
  backgroundColor: "transparent",
50
- color: N,
50
+ color: F,
51
51
  ":hover:not(:disabled)": { backgroundColor: d }
52
52
  },
53
53
  ghost: {
54
54
  backgroundColor: "transparent",
55
- color: M,
55
+ color: N,
56
56
  ":hover:not(:disabled)": { backgroundColor: d }
57
57
  },
58
58
  primaryDestructive: {
59
- backgroundColor: F,
59
+ backgroundColor: M,
60
60
  color: j,
61
61
  ":hover:not(:disabled)": { backgroundColor: u },
62
62
  ":active:not(:disabled)": { backgroundColor: u }
@@ -88,7 +88,7 @@ const ee = "button", oe = H({
88
88
  // As above, the fixed 28px size is part of Button's contract, independent of its label box.
89
89
  minHeight: "1.75rem",
90
90
  fontSize: D,
91
- lineHeight: T,
91
+ lineHeight: A,
92
92
  gap: "0.375rem",
93
93
  "& svg": { width: "0.875rem", height: "0.875rem" }
94
94
  },
@@ -99,9 +99,9 @@ const ee = "button", oe = H({
99
99
  // explicit minHeight above the natural content box, same mechanism `lg` already uses).
100
100
  ...n.paddingInline(Q),
101
101
  ...n.paddingBlock("0.25rem"),
102
- minHeight: O,
103
- fontSize: L,
104
- lineHeight: z,
102
+ minHeight: T,
103
+ fontSize: O,
104
+ lineHeight: L,
105
105
  gap: "0.5rem",
106
106
  "& svg": { width: "1rem", height: "1rem" }
107
107
  },
@@ -109,8 +109,8 @@ const ee = "button", oe = H({
109
109
  ...n.paddingInline("1.25rem"),
110
110
  ...n.paddingBlock("0.25rem"),
111
111
  minHeight: "2.5rem",
112
- fontSize: I,
113
- lineHeight: R,
112
+ fontSize: E,
113
+ lineHeight: z,
114
114
  gap: "0.5rem",
115
115
  "& svg": { width: "1rem", height: "1rem" }
116
116
  },
@@ -127,8 +127,8 @@ const ee = "button", oe = H({
127
127
  icon: {
128
128
  // Density-bound: a fixed square, no line-height floor (unlike `base`), so compact/comfortable
129
129
  // both move freely (DENSITY-SPEC.md §2.4).
130
- width: g,
131
- height: g,
130
+ width: m,
131
+ height: m,
132
132
  "& svg": { width: "1.125rem", height: "1.125rem" }
133
133
  },
134
134
  iconLg: {
@@ -136,13 +136,13 @@ const ee = "button", oe = H({
136
136
  height: "2.5rem",
137
137
  "& svg": { width: "1.5rem", height: "1.5rem" }
138
138
  },
139
- normal: { borderRadius: A },
139
+ normal: { borderRadius: I },
140
140
  rounded: { borderRadius: "9999px" }
141
141
  });
142
142
  function f(c, i = "button") {
143
- return s.Children.toArray(c).flatMap((e, t) => {
144
- const l = s.isValidElement(e) && e.key !== null ? String(e.key) : String(t), o = `${i}/${l}`;
145
- return s.isValidElement(e) && e.type === s.Fragment ? f(e.props.children, o) : [{ node: e, keyPath: o }];
143
+ return a.Children.toArray(c).flatMap((e, t) => {
144
+ const l = a.isValidElement(e) && e.key !== null ? String(e.key) : String(t), o = `${i}/${l}`;
145
+ return a.isValidElement(e) && e.type === a.Fragment ? f(e.props.children, o) : [{ node: e, keyPath: o }];
146
146
  });
147
147
  }
148
148
  function te(c, i) {
@@ -170,12 +170,12 @@ function te(c, i) {
170
170
  continue;
171
171
  }
172
172
  l(), e.push(
173
- s.isValidElement(o.node) ? s.cloneElement(o.node, { key: o.keyPath }) : o.node
173
+ a.isValidElement(o.node) ? a.cloneElement(o.node, { key: o.keyPath }) : o.node
174
174
  );
175
175
  }
176
176
  return l(), e;
177
177
  }
178
- const ce = s.forwardRef(
178
+ const ce = a.forwardRef(
179
179
  function({
180
180
  variant: i = "primary",
181
181
  size: e = "base",
@@ -183,10 +183,10 @@ const ce = s.forwardRef(
183
183
  destructive: l = !1,
184
184
  className: o,
185
185
  asChild: r = !1,
186
- children: m,
186
+ children: g,
187
187
  ...S
188
188
  }, y) {
189
- const a = oe(), k = l && i !== "ghost" ? `${i}Destructive` : i, v = {
189
+ const s = oe(), k = l && i !== "ghost" ? `${i}Destructive` : i, v = {
190
190
  xs: "xs",
191
191
  sm: "sm",
192
192
  base: "base",
@@ -195,7 +195,7 @@ const ce = s.forwardRef(
195
195
  "icon-sm": "iconSm",
196
196
  icon: "icon",
197
197
  "icon-lg": "iconLg"
198
- }[e], C = r ? Y : ee, x = r ? m : te(m, a.label);
198
+ }[e], C = r ? Y : ee, x = r ? g : te(g, s.label);
199
199
  return /* @__PURE__ */ b(
200
200
  C,
201
201
  {
@@ -203,10 +203,10 @@ const ce = s.forwardRef(
203
203
  "data-slot": "button",
204
204
  [B]: "button",
205
205
  className: w(
206
- a.root,
207
- a[k],
208
- a[v],
209
- a[t],
206
+ s.root,
207
+ s[k],
208
+ s[v],
209
+ s[t],
210
210
  o
211
211
  ),
212
212
  ...S,
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sources":["../../../src/components/button/button.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport { capTrim } from \"../../styles/text-box\"\nimport * as tokens from \"../../tokens\"\nimport { Slot } from \"@radix-ui/react-slot\"\n\n/**\n * Base UI's type declarations resolve `react` from the hoisted root's `@types/react` (v19), while\n * this package pins `@types/react` 18 in its own node_modules. Re-typing the primitive onto OUR\n * `React` keeps the button's pass-through props and ref on one React type for this package.\n */\n/**\n * A native `<button>`, no primitive.\n *\n * v1's only Radix use here is `Slot`, purely to implement `asChild`, and this does the same. Base\n * UI's button primitive supplied nothing v1 had: it added a dependency, and with it the\n * `@types/react` 19 requirement, for a plain element.\n */\nconst ButtonBase = \"button\" as const\n\nconst useStyles = makeZenithStyles({\n root: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontWeight: tokens.fontWeightSemibold,\n whiteSpace: \"nowrap\",\n transitionProperty: \"all\",\n cursor: \"pointer\",\n flexShrink: 0,\n // Disabled keeps pointer events so a Tooltip can still explain why, but shows none of the\n // hover or press feedback (every variant guards those with `:not(:disabled)`) and no pointer.\n \":disabled\": { opacity: 0.5, cursor: \"not-allowed\" },\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineOffset: \"2px\",\n outlineColor: tokens.semFocusRing,\n },\n \"@media (prefers-reduced-motion: reduce)\": {\n transitionDuration: \"0.01ms\",\n },\n \"& svg\": {\n flexShrink: 0,\n pointerEvents: \"none\",\n color: \"currentColor\",\n },\n },\n label: capTrim,\n primary: {\n backgroundColor: tokens.semAccentSolid,\n color: tokens.semAccentContrast,\n \":hover:not(:disabled)\": { backgroundColor: tokens.semAccentSolidHover },\n \":active:not(:disabled)\": { backgroundColor: tokens.semAccentSolidHover },\n },\n secondary: {\n backgroundColor: tokens.semAccentSoft,\n color: tokens.semAccentOnSoft,\n \":hover:not(:disabled)\": { backgroundColor: tokens.semAccentSoftHover },\n },\n tertiary: {\n backgroundColor: \"transparent\",\n color: tokens.accentA11,\n \":hover:not(:disabled)\": { backgroundColor: tokens.semAccentSoft },\n },\n ghost: {\n backgroundColor: \"transparent\",\n color: tokens.grayA12,\n \":hover:not(:disabled)\": { backgroundColor: tokens.semAccentSoft },\n },\n primaryDestructive: {\n backgroundColor: tokens.semErrorSolid,\n color: tokens.semErrorContrast,\n \":hover:not(:disabled)\": { backgroundColor: tokens.semErrorSolidHover },\n \":active:not(:disabled)\": { backgroundColor: tokens.semErrorSolidHover },\n },\n secondaryDestructive: {\n backgroundColor: tokens.semErrorSoft,\n color: tokens.semErrorOnSoft,\n \":hover:not(:disabled)\": { backgroundColor: tokens.semErrorSoftHover },\n },\n tertiaryDestructive: {\n backgroundColor: \"transparent\",\n color: tokens.errorA11,\n \":hover:not(:disabled)\": { backgroundColor: tokens.semErrorSoft },\n },\n xs: {\n ...shorthands.paddingInline(\"0.5rem\"),\n ...shorthands.paddingBlock(\"0.25rem\"),\n // Cap trimming removes the line-height's leading from direct text. Keep the established\n // 24px control geometry explicitly instead of relying on that incidental text height.\n minHeight: \"1.5rem\",\n fontSize: tokens.textXs,\n lineHeight: tokens.leadingXs,\n gap: \"4px\",\n \"& svg\": { width: \"0.75rem\", height: \"0.75rem\" },\n },\n sm: {\n ...shorthands.paddingInline(tokens.spacingElement3),\n ...shorthands.paddingBlock(\"0.25rem\"),\n // As above, the fixed 28px size is part of Button's contract, independent of its label box.\n minHeight: \"1.75rem\",\n fontSize: tokens.textSm,\n lineHeight: tokens.leadingSm,\n gap: \"0.375rem\",\n \"& svg\": { width: \"0.875rem\", height: \"0.875rem\" },\n },\n base: {\n // Density-bound (DENSITY-SPEC.md §2.4, WP9B1-ACCEPTANCE-WP9B2A): padding-inline is the\n // compact/comfortable lever; min-height is floored by the fixed line-height + padding-block\n // below and cannot shrink, so it is bound too (compact === normal, comfortable raised via an\n // explicit minHeight above the natural content box, same mechanism `lg` already uses).\n ...shorthands.paddingInline(tokens.buttonBasePaddingInline),\n ...shorthands.paddingBlock(\"0.25rem\"),\n minHeight: tokens.buttonBaseMinHeight,\n fontSize: tokens.textBase,\n lineHeight: tokens.leadingBase,\n gap: \"0.5rem\",\n \"& svg\": { width: \"1rem\", height: \"1rem\" },\n },\n lg: {\n ...shorthands.paddingInline(\"1.25rem\"),\n ...shorthands.paddingBlock(\"0.25rem\"),\n minHeight: \"2.5rem\",\n fontSize: tokens.textLg,\n lineHeight: tokens.leadingLg,\n gap: \"0.5rem\",\n \"& svg\": { width: \"1rem\", height: \"1rem\" },\n },\n iconXs: {\n width: \"1.5rem\",\n height: \"1.5rem\",\n \"& svg\": { width: \"0.75rem\", height: \"0.75rem\" },\n },\n iconSm: {\n width: \"1.75rem\",\n height: \"1.75rem\",\n \"& svg\": { width: \"0.875rem\", height: \"0.875rem\" },\n },\n icon: {\n // Density-bound: a fixed square, no line-height floor (unlike `base`), so compact/comfortable\n // both move freely (DENSITY-SPEC.md §2.4).\n width: tokens.buttonIconSize,\n height: tokens.buttonIconSize,\n \"& svg\": { width: \"1.125rem\", height: \"1.125rem\" },\n },\n iconLg: {\n width: \"2.5rem\",\n height: \"2.5rem\",\n \"& svg\": { width: \"1.5rem\", height: \"1.5rem\" },\n },\n normal: { borderRadius: tokens.radiusLg },\n rounded: { borderRadius: \"9999px\" },\n})\n\ntype FlatButtonChild = {\n node: React.ReactNode\n keyPath: string\n}\n\n/**\n * Fragments do not create boxes, so flatten them to the same leaf order the flex container sees.\n * React.Children.toArray handles nested arrays and gives keyed elements a stable local key; the\n * parent fragment path keeps equal keys from separate fragment scopes distinct.\n */\nfunction flattenButtonChildren(\n children: React.ReactNode,\n parentPath = \"button\"\n): FlatButtonChild[] {\n return React.Children.toArray(children).flatMap((node, index) => {\n const localKey =\n React.isValidElement(node) && node.key !== null\n ? String(node.key)\n : String(index)\n const keyPath = `${parentPath}/${localKey}`\n\n if (\n React.isValidElement<{ children?: React.ReactNode }>(node) &&\n node.type === React.Fragment\n ) {\n return flattenButtonChildren(node.props.children, keyPath)\n }\n\n return [{ node, keyPath }]\n })\n}\n\n/**\n * A flex container's direct text becomes an anonymous flex item, which `text-box` cannot select.\n * Recreate exactly those contiguous text runs as real label boxes. Consumer elements stay direct\n * children and whitespace-only runs stay raw, preserving today's element order and flex gaps.\n */\nfunction wrapButtonTextRuns(\n children: React.ReactNode,\n labelClassName: string\n): React.ReactNode[] {\n const output: React.ReactNode[] = []\n let textRun: FlatButtonChild[] = []\n\n const flushTextRun = () => {\n if (!textRun.length) return\n\n const whitespaceOnly = textRun.every(\n ({ node }) => typeof node === \"string\" && node.trim() === \"\"\n )\n if (whitespaceOnly) {\n output.push(...textRun.map(({ node }) => node))\n } else {\n output.push(\n <span\n key={`button-label:${textRun[0].keyPath}`}\n data-slot=\"button-label\"\n className={labelClassName}\n >\n {textRun.map(({ node }) => node)}\n </span>\n )\n }\n textRun = []\n }\n\n for (const child of flattenButtonChildren(children)) {\n if (typeof child.node === \"string\" || typeof child.node === \"number\") {\n textRun.push(child)\n continue\n }\n\n flushTextRun()\n output.push(\n React.isValidElement(child.node)\n ? React.cloneElement(child.node, { key: child.keyPath })\n : child.node\n )\n }\n flushTextRun()\n\n return output\n}\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"tertiary\" | \"ghost\"\nexport type ButtonSize =\n \"xs\" | \"sm\" | \"base\" | \"lg\" | \"icon-xs\" | \"icon-sm\" | \"icon\" | \"icon-lg\"\nexport type ButtonShape = \"normal\" | \"rounded\"\n\nexport type ButtonProps = Omit<\n React.ComponentProps<\"button\">,\n \"variant\" | \"size\" | \"shape\" | \"destructive\" | \"className\" | \"render\"\n> & {\n variant?: ButtonVariant\n size?: ButtonSize\n shape?: ButtonShape\n destructive?: boolean\n className?: string\n /**\n * Render the child element instead of a `button`, keeping Button's styling and slot markers.\n * v1 supports this and consumers rely on it to wrap links; it was dropped here while the package\n * was briefly on Base UI, and restored once it moved back to Radix.\n */\n asChild?: boolean\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n {\n variant = \"primary\",\n size = \"base\",\n shape = \"rounded\",\n destructive = false,\n className,\n asChild = false,\n children,\n ...props\n },\n ref\n ) {\n const styles = useStyles()\n const variantSlot:\n | ButtonVariant\n | \"primaryDestructive\"\n | \"secondaryDestructive\"\n | \"tertiaryDestructive\" =\n destructive && variant !== \"ghost\"\n ? (`${variant}Destructive` as\n | \"primaryDestructive\"\n | \"secondaryDestructive\"\n | \"tertiaryDestructive\")\n : variant\n const sizeSlot:\n \"xs\" | \"sm\" | \"base\" | \"lg\" | \"iconXs\" | \"iconSm\" | \"icon\" | \"iconLg\" = (\n {\n xs: \"xs\",\n sm: \"sm\",\n base: \"base\",\n lg: \"lg\",\n \"icon-xs\": \"iconXs\",\n \"icon-sm\": \"iconSm\",\n icon: \"icon\",\n \"icon-lg\": \"iconLg\",\n } as const\n )[size]\n\n const Root = asChild ? Slot : ButtonBase\n const content = asChild\n ? children\n : wrapButtonTextRuns(children, styles.label)\n\n return (\n <Root\n ref={ref}\n data-slot=\"button\"\n {...{ [SLOT_ATTR]: \"button\" }}\n className={mergeClasses(\n styles.root,\n styles[variantSlot],\n styles[sizeSlot],\n styles[shape],\n className\n )}\n {...props}\n >\n {content}\n </Root>\n )\n }\n)\n"],"names":["ButtonBase","useStyles","makeZenithStyles","tokens.fontWeightSemibold","tokens.semFocusRing","capTrim","tokens.semAccentSolid","tokens.semAccentContrast","tokens.semAccentSolidHover","tokens.semAccentSoft","tokens.semAccentOnSoft","tokens.semAccentSoftHover","tokens.accentA11","tokens.grayA12","tokens.semErrorSolid","tokens.semErrorContrast","tokens.semErrorSolidHover","tokens.semErrorSoft","tokens.semErrorOnSoft","tokens.semErrorSoftHover","tokens.errorA11","shorthands","tokens.textXs","tokens.leadingXs","tokens.spacingElement3","tokens.textSm","tokens.leadingSm","tokens.buttonBasePaddingInline","tokens.buttonBaseMinHeight","tokens.textBase","tokens.leadingBase","tokens.textLg","tokens.leadingLg","tokens.buttonIconSize","tokens.radiusLg","flattenButtonChildren","children","parentPath","React","node","index","localKey","keyPath","wrapButtonTextRuns","labelClassName","output","textRun","flushTextRun","jsx","child","Button","variant","size","shape","destructive","className","asChild","props","ref","styles","variantSlot","sizeSlot","Root","Slot","content","SLOT_ATTR","mergeClasses"],"mappings":"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"}
1
+ {"version":3,"file":"button.js","sources":["../../../src/components/button/button.tsx"],"sourcesContent":["import * as React from \"react\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport { capTrim } from \"../../styles/text-box\"\nimport * as tokens from \"../../tokens\"\nimport { Slot } from \"@radix-ui/react-slot\"\n\n/**\n * Base UI's type declarations resolve `react` from the hoisted root's `@types/react` (v19), while\n * this package pins `@types/react` 18 in its own node_modules. Re-typing the primitive onto OUR\n * `React` keeps the button's pass-through props and ref on one React type for this package.\n */\n/**\n * A native `<button>`, no primitive.\n *\n * v1's only Radix use here is `Slot`, purely to implement `asChild`, and this does the same. Base\n * UI's button primitive supplied nothing v1 had: it added a dependency, and with it the\n * `@types/react` 19 requirement, for a plain element.\n */\nconst ButtonBase = \"button\" as const\n\nconst useStyles = makeZenithStyles({\n root: {\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontWeight: tokens.fontWeightSemibold,\n whiteSpace: \"nowrap\",\n transitionProperty: \"all\",\n cursor: \"pointer\",\n flexShrink: 0,\n // Disabled keeps pointer events so a Tooltip can still explain why, but shows none of the\n // hover or press feedback (every variant guards those with `:not(:disabled)`) and no pointer.\n \":disabled\": { opacity: 0.5, cursor: \"not-allowed\" },\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineOffset: \"2px\",\n outlineColor: tokens.focusRing,\n },\n \"@media (prefers-reduced-motion: reduce)\": {\n transitionDuration: \"0.01ms\",\n },\n \"& svg\": {\n flexShrink: 0,\n pointerEvents: \"none\",\n color: \"currentColor\",\n },\n },\n label: capTrim,\n primary: {\n backgroundColor: tokens.accentSolid,\n color: tokens.accentContrast,\n \":hover:not(:disabled)\": { backgroundColor: tokens.accentSolidHover },\n \":active:not(:disabled)\": { backgroundColor: tokens.accentSolidHover },\n },\n secondary: {\n backgroundColor: tokens.accentSoft,\n color: tokens.accentOnSoft,\n \":hover:not(:disabled)\": { backgroundColor: tokens.accentSoftHover },\n },\n tertiary: {\n backgroundColor: \"transparent\",\n color: tokens.accentA11,\n \":hover:not(:disabled)\": { backgroundColor: tokens.accentSoft },\n },\n ghost: {\n backgroundColor: \"transparent\",\n color: tokens.grayA12,\n \":hover:not(:disabled)\": { backgroundColor: tokens.accentSoft },\n },\n primaryDestructive: {\n backgroundColor: tokens.errorSolid,\n color: tokens.errorContrast,\n \":hover:not(:disabled)\": { backgroundColor: tokens.errorSolidHover },\n \":active:not(:disabled)\": { backgroundColor: tokens.errorSolidHover },\n },\n secondaryDestructive: {\n backgroundColor: tokens.errorSoft,\n color: tokens.errorOnSoft,\n \":hover:not(:disabled)\": { backgroundColor: tokens.errorSoftHover },\n },\n tertiaryDestructive: {\n backgroundColor: \"transparent\",\n color: tokens.errorA11,\n \":hover:not(:disabled)\": { backgroundColor: tokens.errorSoft },\n },\n xs: {\n ...shorthands.paddingInline(\"0.5rem\"),\n ...shorthands.paddingBlock(\"0.25rem\"),\n // Cap trimming removes the line-height's leading from direct text. Keep the established\n // 24px control geometry explicitly instead of relying on that incidental text height.\n minHeight: \"1.5rem\",\n fontSize: tokens.textXs,\n lineHeight: tokens.leadingXs,\n gap: \"4px\",\n \"& svg\": { width: \"0.75rem\", height: \"0.75rem\" },\n },\n sm: {\n ...shorthands.paddingInline(tokens.spacingElement3),\n ...shorthands.paddingBlock(\"0.25rem\"),\n // As above, the fixed 28px size is part of Button's contract, independent of its label box.\n minHeight: \"1.75rem\",\n fontSize: tokens.textSm,\n lineHeight: tokens.leadingSm,\n gap: \"0.375rem\",\n \"& svg\": { width: \"0.875rem\", height: \"0.875rem\" },\n },\n base: {\n // Density-bound (DENSITY-SPEC.md §2.4, WP9B1-ACCEPTANCE-WP9B2A): padding-inline is the\n // compact/comfortable lever; min-height is floored by the fixed line-height + padding-block\n // below and cannot shrink, so it is bound too (compact === normal, comfortable raised via an\n // explicit minHeight above the natural content box, same mechanism `lg` already uses).\n ...shorthands.paddingInline(tokens.buttonBasePaddingInline),\n ...shorthands.paddingBlock(\"0.25rem\"),\n minHeight: tokens.buttonBaseMinHeight,\n fontSize: tokens.textBase,\n lineHeight: tokens.leadingBase,\n gap: \"0.5rem\",\n \"& svg\": { width: \"1rem\", height: \"1rem\" },\n },\n lg: {\n ...shorthands.paddingInline(\"1.25rem\"),\n ...shorthands.paddingBlock(\"0.25rem\"),\n minHeight: \"2.5rem\",\n fontSize: tokens.textLg,\n lineHeight: tokens.leadingLg,\n gap: \"0.5rem\",\n \"& svg\": { width: \"1rem\", height: \"1rem\" },\n },\n iconXs: {\n width: \"1.5rem\",\n height: \"1.5rem\",\n \"& svg\": { width: \"0.75rem\", height: \"0.75rem\" },\n },\n iconSm: {\n width: \"1.75rem\",\n height: \"1.75rem\",\n \"& svg\": { width: \"0.875rem\", height: \"0.875rem\" },\n },\n icon: {\n // Density-bound: a fixed square, no line-height floor (unlike `base`), so compact/comfortable\n // both move freely (DENSITY-SPEC.md §2.4).\n width: tokens.buttonIconSize,\n height: tokens.buttonIconSize,\n \"& svg\": { width: \"1.125rem\", height: \"1.125rem\" },\n },\n iconLg: {\n width: \"2.5rem\",\n height: \"2.5rem\",\n \"& svg\": { width: \"1.5rem\", height: \"1.5rem\" },\n },\n normal: { borderRadius: tokens.radiusLg },\n rounded: { borderRadius: \"9999px\" },\n})\n\ntype FlatButtonChild = {\n node: React.ReactNode\n keyPath: string\n}\n\n/**\n * Fragments do not create boxes, so flatten them to the same leaf order the flex container sees.\n * React.Children.toArray handles nested arrays and gives keyed elements a stable local key; the\n * parent fragment path keeps equal keys from separate fragment scopes distinct.\n */\nfunction flattenButtonChildren(\n children: React.ReactNode,\n parentPath = \"button\"\n): FlatButtonChild[] {\n return React.Children.toArray(children).flatMap((node, index) => {\n const localKey =\n React.isValidElement(node) && node.key !== null\n ? String(node.key)\n : String(index)\n const keyPath = `${parentPath}/${localKey}`\n\n if (\n React.isValidElement<{ children?: React.ReactNode }>(node) &&\n node.type === React.Fragment\n ) {\n return flattenButtonChildren(node.props.children, keyPath)\n }\n\n return [{ node, keyPath }]\n })\n}\n\n/**\n * A flex container's direct text becomes an anonymous flex item, which `text-box` cannot select.\n * Recreate exactly those contiguous text runs as real label boxes. Consumer elements stay direct\n * children and whitespace-only runs stay raw, preserving today's element order and flex gaps.\n */\nfunction wrapButtonTextRuns(\n children: React.ReactNode,\n labelClassName: string\n): React.ReactNode[] {\n const output: React.ReactNode[] = []\n let textRun: FlatButtonChild[] = []\n\n const flushTextRun = () => {\n if (!textRun.length) return\n\n const whitespaceOnly = textRun.every(\n ({ node }) => typeof node === \"string\" && node.trim() === \"\"\n )\n if (whitespaceOnly) {\n output.push(...textRun.map(({ node }) => node))\n } else {\n output.push(\n <span\n key={`button-label:${textRun[0].keyPath}`}\n data-slot=\"button-label\"\n className={labelClassName}\n >\n {textRun.map(({ node }) => node)}\n </span>\n )\n }\n textRun = []\n }\n\n for (const child of flattenButtonChildren(children)) {\n if (typeof child.node === \"string\" || typeof child.node === \"number\") {\n textRun.push(child)\n continue\n }\n\n flushTextRun()\n output.push(\n React.isValidElement(child.node)\n ? React.cloneElement(child.node, { key: child.keyPath })\n : child.node\n )\n }\n flushTextRun()\n\n return output\n}\n\nexport type ButtonVariant = \"primary\" | \"secondary\" | \"tertiary\" | \"ghost\"\nexport type ButtonSize =\n \"xs\" | \"sm\" | \"base\" | \"lg\" | \"icon-xs\" | \"icon-sm\" | \"icon\" | \"icon-lg\"\nexport type ButtonShape = \"normal\" | \"rounded\"\n\nexport type ButtonProps = Omit<\n React.ComponentProps<\"button\">,\n \"variant\" | \"size\" | \"shape\" | \"destructive\" | \"className\" | \"render\"\n> & {\n variant?: ButtonVariant\n size?: ButtonSize\n shape?: ButtonShape\n destructive?: boolean\n className?: string\n /**\n * Render the child element instead of a `button`, keeping Button's styling and slot markers.\n * v1 supports this and consumers rely on it to wrap links; it was dropped here while the package\n * was briefly on Base UI, and restored once it moved back to Radix.\n */\n asChild?: boolean\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n function Button(\n {\n variant = \"primary\",\n size = \"base\",\n shape = \"rounded\",\n destructive = false,\n className,\n asChild = false,\n children,\n ...props\n },\n ref\n ) {\n const styles = useStyles()\n const variantSlot:\n | ButtonVariant\n | \"primaryDestructive\"\n | \"secondaryDestructive\"\n | \"tertiaryDestructive\" =\n destructive && variant !== \"ghost\"\n ? (`${variant}Destructive` as\n | \"primaryDestructive\"\n | \"secondaryDestructive\"\n | \"tertiaryDestructive\")\n : variant\n const sizeSlot:\n \"xs\" | \"sm\" | \"base\" | \"lg\" | \"iconXs\" | \"iconSm\" | \"icon\" | \"iconLg\" = (\n {\n xs: \"xs\",\n sm: \"sm\",\n base: \"base\",\n lg: \"lg\",\n \"icon-xs\": \"iconXs\",\n \"icon-sm\": \"iconSm\",\n icon: \"icon\",\n \"icon-lg\": \"iconLg\",\n } as const\n )[size]\n\n const Root = asChild ? Slot : ButtonBase\n const content = asChild\n ? children\n : wrapButtonTextRuns(children, styles.label)\n\n return (\n <Root\n ref={ref}\n data-slot=\"button\"\n {...{ [SLOT_ATTR]: \"button\" }}\n className={mergeClasses(\n styles.root,\n styles[variantSlot],\n styles[sizeSlot],\n styles[shape],\n className\n )}\n {...props}\n >\n {content}\n </Root>\n )\n }\n)\n"],"names":["ButtonBase","useStyles","makeZenithStyles","tokens.fontWeightSemibold","tokens.focusRing","capTrim","tokens.accentSolid","tokens.accentContrast","tokens.accentSolidHover","tokens.accentSoft","tokens.accentOnSoft","tokens.accentSoftHover","tokens.accentA11","tokens.grayA12","tokens.errorSolid","tokens.errorContrast","tokens.errorSolidHover","tokens.errorSoft","tokens.errorOnSoft","tokens.errorSoftHover","tokens.errorA11","shorthands","tokens.textXs","tokens.leadingXs","tokens.spacingElement3","tokens.textSm","tokens.leadingSm","tokens.buttonBasePaddingInline","tokens.buttonBaseMinHeight","tokens.textBase","tokens.leadingBase","tokens.textLg","tokens.leadingLg","tokens.buttonIconSize","tokens.radiusLg","flattenButtonChildren","children","parentPath","React","node","index","localKey","keyPath","wrapButtonTextRuns","labelClassName","output","textRun","flushTextRun","jsx","child","Button","variant","size","shape","destructive","className","asChild","props","ref","styles","variantSlot","sizeSlot","Root","Slot","content","SLOT_ATTR","mergeClasses"],"mappings":"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"}