@epilot/zenith-react 0.2.0-next.5 → 0.2.0-next.7

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.
@@ -1,77 +1,77 @@
1
- import { jsx as h, jsxs as $ } from "react/jsx-runtime";
2
- import * as f from "react";
3
- import { useRef as G, useState as v, useCallback as E, useLayoutEffect as I } from "react";
4
- import { Radio as O } from "../../_virtual/_zenith-runtime-family_radio.js";
5
- import { SLOT_ATTR as e, mergeClasses as w, shorthands as n } from "@epilot/zenith-runtime/v1";
6
- import { makeZenithStyles as V } from "../../styles/make-styles.js";
7
- import { boxModel as s, nativeControl as P } from "../../styles/host-reset.js";
8
- import { accentDefault as T, accentA8 as Y, accentSoft as A, fontWeightSemibold as Z, leadingXs as J, textXs as K, spacingElement1 as p, spacingElement3 as W, body as Q } from "../../tokens/index.js";
9
- import { RadioGroupBase as U } from "../radio/radio-group-base.js";
10
- const z = f.createContext({
1
+ import { jsx as b, jsxs as $ } from "react/jsx-runtime";
2
+ import * as m from "react";
3
+ import { useRef as G, useState as w, useCallback as R, useLayoutEffect as I } from "react";
4
+ import { Radio as V } from "../../_virtual/_zenith-runtime-family_radio.js";
5
+ import { SLOT_ATTR as t, mergeClasses as E, shorthands as n } from "@epilot/zenith-runtime/v1";
6
+ import { makeZenithStyles as P } from "../../styles/make-styles.js";
7
+ import { boxModel as l, nativeControl as Y } from "../../styles/host-reset.js";
8
+ import { accentDefault as T, accentA8 as Z, accentSoft as W, fontWeightSemibold as J, leadingXs as K, textXs as Q, spacingElement1 as g, spacingElement3 as z, body as U } from "../../tokens/index.js";
9
+ import { RadioGroupBase as ee } from "../radio/radio-group-base.js";
10
+ const F = m.createContext({
11
11
  layout: "hug"
12
- }), N = V({
12
+ }), q = P({
13
13
  group: {
14
- ...s,
14
+ ...l,
15
15
  position: "relative",
16
16
  display: "inline-flex",
17
17
  alignItems: "center",
18
- ...n.gap(p),
18
+ ...n.gap(g),
19
19
  ...n.borderRadius("9999px"),
20
- backgroundColor: A,
21
- ...n.padding(p),
20
+ backgroundColor: W,
21
+ ...n.padding(g),
22
22
  ...n.border("0"),
23
23
  boxShadow: "none"
24
24
  },
25
25
  groupStretch: {
26
- ...s,
26
+ ...l,
27
27
  display: "flex",
28
28
  width: "100%"
29
29
  },
30
30
  groupVertical: {
31
- ...s,
31
+ ...l,
32
32
  flexDirection: "column",
33
33
  display: "inline-flex",
34
34
  width: "fit-content"
35
35
  },
36
36
  indicator: {
37
- ...s,
37
+ ...l,
38
38
  pointerEvents: "none",
39
39
  position: "absolute",
40
40
  top: 0,
41
41
  left: 0,
42
42
  zIndex: 0,
43
43
  ...n.borderRadius("9999px"),
44
- backgroundColor: Q,
44
+ backgroundColor: U,
45
45
  // Tailwind `shadow-sm`
46
46
  boxShadow: "0 1px 2px 0 #0000000d"
47
47
  },
48
48
  indicatorAnimated: {
49
- ...s,
49
+ ...l,
50
50
  transitionProperty: "transform, width, height",
51
51
  transitionDuration: "150ms",
52
52
  transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)"
53
53
  },
54
54
  item: {
55
- ...P,
55
+ ...Y,
56
56
  position: "relative",
57
57
  zIndex: 1,
58
58
  display: "inline-flex",
59
59
  alignItems: "center",
60
60
  justifyContent: "center",
61
- ...n.gap(p),
61
+ ...n.gap(g),
62
62
  ...n.borderRadius("9999px"),
63
63
  minWidth: "3rem",
64
64
  // v1 uses Tailwind's `px-3` = 0.75rem here. The semantic spacing scale has NO 0.75rem
65
65
  // token -- it runs 0.25/0.5/0.5/1/1.5/2 -- so this is a literal by necessity.
66
66
  // `spacingGroup1` is 0.5rem and reaching for it by name (as three components did)
67
67
  // silently loses 4px per side. See STATUS: the scale gap is the root cause.
68
- paddingLeft: W,
69
- paddingRight: W,
70
- paddingTop: p,
71
- paddingBottom: p,
72
- fontSize: K,
73
- lineHeight: J,
74
- fontWeight: Z,
68
+ paddingLeft: z,
69
+ paddingRight: z,
70
+ paddingTop: g,
71
+ paddingBottom: g,
72
+ fontSize: Q,
73
+ lineHeight: K,
74
+ fontWeight: J,
75
75
  color: T,
76
76
  cursor: "pointer",
77
77
  userSelect: "none",
@@ -86,12 +86,12 @@ const z = f.createContext({
86
86
  transitionDuration: "150ms",
87
87
  transitionTimingFunction: "cubic-bezier(0.4, 0, 0.2, 1)",
88
88
  ":hover:not([data-checked])": {
89
- backgroundColor: A
89
+ backgroundColor: W
90
90
  },
91
91
  ":focus-visible": {
92
92
  outlineWidth: "2px",
93
93
  outlineStyle: "solid",
94
- outlineColor: Y
94
+ outlineColor: Z
95
95
  },
96
96
  "&[data-disabled]": {
97
97
  pointerEvents: "none",
@@ -105,12 +105,12 @@ const z = f.createContext({
105
105
  "&[data-checked][data-disabled]": {
106
106
  backgroundColor: "transparent"
107
107
  },
108
- [`& [${e}="radio-group-indicator"]`]: {
108
+ [`& [${t}="radio-group-indicator"]`]: {
109
109
  display: "none"
110
110
  },
111
111
  // Keyed on SLOT_ATTR, never data-slot (rule 4): the composed RadioGroup emits both, and
112
112
  // data-slot values are shared with v1 so such a rule would also match v1-rendered DOM.
113
- [`[${e}='radio-group-indicator']`]: {
113
+ [`[${t}='radio-group-indicator']`]: {
114
114
  display: "none"
115
115
  }
116
116
  },
@@ -120,7 +120,7 @@ const z = f.createContext({
120
120
  flexBasis: "0%"
121
121
  },
122
122
  icon: {
123
- ...s,
123
+ ...l,
124
124
  flexShrink: 0,
125
125
  width: "1rem",
126
126
  height: "1rem",
@@ -138,136 +138,147 @@ const z = f.createContext({
138
138
  textOverflow: "ellipsis",
139
139
  whiteSpace: "nowrap"
140
140
  }
141
- }), dt = f.forwardRef(function({
142
- className: x,
141
+ }), le = m.forwardRef(function({
142
+ className: v,
143
143
  layout: o = "hug",
144
- orientation: c = "horizontal",
145
- value: r,
146
- defaultValue: y,
147
- onValueChange: d,
148
- children: S,
149
- asChild: R,
150
- ...i
151
- }, a) {
152
- const l = N(), m = G(null), [M, _] = v(y), [C, q] = v(!1), [B, F] = v({
144
+ orientation: u = "horizontal",
145
+ value: s,
146
+ defaultValue: C,
147
+ onValueChange: f,
148
+ children: x,
149
+ asChild: A,
150
+ ...c
151
+ }, d) {
152
+ const p = q(), r = G(null), [L, M] = w(C), [k, _] = w(!1), [B, O] = w({
153
153
  opacity: 0
154
- }), g = r !== void 0, j = g ? r : M, k = E(() => {
155
- if (!m.current) return;
156
- const t = m.current.querySelector(
157
- `[${e}="segmented-control-item"][data-checked]`
154
+ }), y = s !== void 0, j = y ? s : L, h = R(() => {
155
+ if (!r.current) return;
156
+ const e = r.current.querySelector(
157
+ `[${t}="segmented-control-item"][data-checked]`
158
158
  );
159
- t && (F({
159
+ e && (O({
160
160
  opacity: 1,
161
- width: t.offsetWidth,
162
- height: t.offsetHeight,
163
- transform: `translate(${t.offsetLeft}px, ${t.offsetTop}px)`
164
- }), q(!0));
165
- }, []);
166
- I(() => {
167
- if (!m.current) return;
168
- const t = Array.from(
169
- m.current.querySelectorAll(
170
- `[${e}="segmented-control-item"]`
161
+ width: e.offsetWidth,
162
+ height: e.offsetHeight,
163
+ transform: `translate(${e.offsetLeft}px, ${e.offsetTop}px)`
164
+ }), _(!0));
165
+ }, []), S = R(() => {
166
+ if (!r.current) return;
167
+ const e = Array.from(
168
+ r.current.querySelectorAll(
169
+ `[${t}="segmented-control-item"]`
171
170
  )
172
171
  );
173
- if (!t.length || (t.forEach((u) => u.style.minWidth = ""), o !== "equal")) return;
174
- const b = Math.max(...t.map((u) => u.offsetWidth));
175
- t.forEach((u) => u.style.minWidth = `${b}px`);
176
- }, [o]), I(() => {
177
- if (!C) {
178
- k();
172
+ if (!e.length || (e.forEach((a) => a.style.minWidth = ""), o !== "equal")) return;
173
+ const i = Math.max(...e.map((a) => a.offsetWidth));
174
+ e.forEach((a) => a.style.minWidth = `${i}px`);
175
+ }, [o]);
176
+ I(S, [S]), I(() => {
177
+ if (!k) {
178
+ h();
179
179
  return;
180
180
  }
181
- const t = requestAnimationFrame(k);
182
- return () => cancelAnimationFrame(t);
183
- }, [j, C, k]);
184
- const D = E(
185
- (t, b) => {
186
- d == null || d(t, b), !g && !b.isCanceled && _(t);
181
+ const e = requestAnimationFrame(h);
182
+ return () => cancelAnimationFrame(e);
183
+ }, [j, k, h]), m.useEffect(() => {
184
+ if (!r.current || typeof ResizeObserver > "u") return;
185
+ let e;
186
+ const i = new ResizeObserver(() => {
187
+ e !== void 0 && cancelAnimationFrame(e), e = requestAnimationFrame(() => {
188
+ e = void 0, S(), h();
189
+ });
190
+ });
191
+ return r.current.querySelectorAll(`[${t}="segmented-control-item"]`).forEach((a) => i.observe(a, { box: "border-box" })), () => {
192
+ i.disconnect(), e !== void 0 && cancelAnimationFrame(e);
193
+ };
194
+ }, [x, h, S]);
195
+ const D = R(
196
+ (e, i) => {
197
+ f == null || f(e, i), !y && !i.isCanceled && M(e);
187
198
  },
188
- [g, d]
189
- ), H = (t) => {
190
- m.current = t, typeof a == "function" ? a(t) : a && (a.current = t);
191
- }, X = f.useMemo(() => ({ layout: o }), [o]);
192
- return /* @__PURE__ */ h(z.Provider, { value: X, children: /* @__PURE__ */ $(
193
- U,
199
+ [y, f]
200
+ ), H = (e) => {
201
+ r.current = e, typeof d == "function" ? d(e) : d && (d.current = e);
202
+ }, X = m.useMemo(() => ({ layout: o }), [o]);
203
+ return /* @__PURE__ */ b(F.Provider, { value: X, children: /* @__PURE__ */ $(
204
+ ee,
194
205
  {
195
206
  ref: H,
196
207
  "data-slot": "segmented-control",
197
- [e]: "segmented-control",
208
+ [t]: "segmented-control",
198
209
  "data-layout": o,
199
- value: g ? r : void 0,
200
- defaultValue: y,
210
+ value: y ? s : void 0,
211
+ defaultValue: C,
201
212
  onValueChange: D,
202
- orientation: c,
203
- className: w(
204
- l.group,
205
- o === "stretch" && l.groupStretch,
206
- c === "vertical" && l.groupVertical,
207
- x
213
+ orientation: u,
214
+ className: E(
215
+ p.group,
216
+ o === "stretch" && p.groupStretch,
217
+ u === "vertical" && p.groupVertical,
218
+ v
208
219
  ),
209
- ...i,
220
+ ...c,
210
221
  children: [
211
- /* @__PURE__ */ h(
222
+ /* @__PURE__ */ b(
212
223
  "span",
213
224
  {
214
225
  "aria-hidden": "true",
215
226
  "data-slot": "segmented-control-indicator",
216
- [e]: "segmented-control-indicator",
217
- className: w(
218
- l.indicator,
219
- C && l.indicatorAnimated
227
+ [t]: "segmented-control-indicator",
228
+ className: E(
229
+ p.indicator,
230
+ k && p.indicatorAnimated
220
231
  ),
221
232
  style: B
222
233
  }
223
234
  ),
224
- S
235
+ x
225
236
  ]
226
237
  }
227
238
  ) });
228
- }), tt = /* @__PURE__ */ h("button", { type: "button" }), lt = f.forwardRef(function({
229
- className: x,
239
+ }), te = /* @__PURE__ */ b("button", { type: "button" }), me = m.forwardRef(function({
240
+ className: v,
230
241
  value: o,
231
- icon: c,
232
- children: r,
233
- asChild: y,
234
- checked: d,
235
- ...S
236
- }, R) {
237
- const i = N(), { layout: a } = f.useContext(z);
242
+ icon: u,
243
+ children: s,
244
+ asChild: C,
245
+ checked: f,
246
+ ...x
247
+ }, A) {
248
+ const c = q(), { layout: d } = m.useContext(F);
238
249
  return /* @__PURE__ */ $(
239
- O.Root,
250
+ V.Root,
240
251
  {
241
- ref: R,
252
+ ref: A,
242
253
  nativeButton: !0,
243
- render: tt,
254
+ render: te,
244
255
  value: o,
245
256
  "data-slot": "segmented-control-item",
246
- [e]: "segmented-control-item",
247
- className: w(
248
- i.item,
249
- a === "stretch" && i.itemStretch,
250
- x
257
+ [t]: "segmented-control-item",
258
+ className: E(
259
+ c.item,
260
+ d === "stretch" && c.itemStretch,
261
+ v
251
262
  ),
252
- ...S,
263
+ ...x,
253
264
  children: [
254
- c && /* @__PURE__ */ h(
265
+ u && /* @__PURE__ */ b(
255
266
  "span",
256
267
  {
257
268
  "aria-hidden": "true",
258
269
  "data-slot": "segmented-control-item-icon",
259
- [e]: "segmented-control-item-icon",
260
- className: i.icon,
261
- children: c
270
+ [t]: "segmented-control-item-icon",
271
+ className: c.icon,
272
+ children: u
262
273
  }
263
274
  ),
264
- r && /* @__PURE__ */ h(
275
+ s && /* @__PURE__ */ b(
265
276
  "span",
266
277
  {
267
278
  "data-slot": "segmented-control-item-label",
268
- [e]: "segmented-control-item-label",
269
- className: i.label,
270
- children: r
279
+ [t]: "segmented-control-item-label",
280
+ className: c.label,
281
+ children: s
271
282
  }
272
283
  )
273
284
  ]
@@ -275,7 +286,7 @@ const z = f.createContext({
275
286
  );
276
287
  });
277
288
  export {
278
- dt as SegmentedControl,
279
- lt as SegmentedControlItem
289
+ le as SegmentedControl,
290
+ me as SegmentedControlItem
280
291
  };
281
292
  //# sourceMappingURL=segmented-control.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"segmented-control.js","sources":["../../../src/components/segmented-control/segmented-control.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { useCallback, useLayoutEffect, useRef, useState } from \"react\"\nimport { Radio } from \"@base-ui/react/radio\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport { boxModel, nativeControl } from \"../../styles/host-reset\"\nimport * as tokens from \"../../tokens\"\nimport {\n RadioGroupBase,\n type RadioGroupBaseProps,\n} from \"../radio/radio-group-base\"\nimport type {\n RadioGroupChangeDetails,\n RadioGroupItemProps,\n RadioGroupProps,\n} from \"../radio/radio\"\n\nexport type SegmentedControlLayout = \"hug\" | \"equal\" | \"stretch\"\n\nexport type SegmentedControlProps = RadioGroupProps & {\n layout?: SegmentedControlLayout\n}\n\nexport type SegmentedControlItemProps = RadioGroupItemProps & {\n icon?: React.ReactNode\n}\n\ninterface SegmentedControlContextValue {\n layout: SegmentedControlLayout\n}\n\nconst SegmentedControlContext =\n React.createContext<SegmentedControlContextValue>({\n layout: \"hug\",\n })\n\nconst useStyles = makeZenithStyles({\n group: {\n ...boxModel,\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n ...shorthands.gap(tokens.spacingElement1),\n ...shorthands.borderRadius(\"9999px\"),\n backgroundColor: tokens.accentSoft,\n ...shorthands.padding(tokens.spacingElement1),\n ...shorthands.border(\"0\"),\n boxShadow: \"none\",\n },\n groupStretch: {\n ...boxModel,\n display: \"flex\",\n width: \"100%\",\n },\n groupVertical: {\n ...boxModel,\n flexDirection: \"column\",\n display: \"inline-flex\",\n width: \"fit-content\",\n },\n indicator: {\n ...boxModel,\n pointerEvents: \"none\",\n position: \"absolute\",\n top: 0,\n left: 0,\n zIndex: 0,\n ...shorthands.borderRadius(\"9999px\"),\n backgroundColor: tokens.body,\n // Tailwind `shadow-sm`\n boxShadow: \"0 1px 2px 0 #0000000d\",\n },\n indicatorAnimated: {\n ...boxModel,\n transitionProperty: \"transform, width, height\",\n transitionDuration: \"150ms\",\n transitionTimingFunction: \"cubic-bezier(0.4, 0, 0.2, 1)\",\n },\n item: {\n ...nativeControl,\n position: \"relative\",\n zIndex: 1,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n ...shorthands.gap(tokens.spacingElement1),\n ...shorthands.borderRadius(\"9999px\"),\n minWidth: \"3rem\",\n // v1 uses Tailwind's `px-3` = 0.75rem here. The semantic spacing scale has NO 0.75rem\n // token -- it runs 0.25/0.5/0.5/1/1.5/2 -- so this is a literal by necessity.\n // `spacingGroup1` is 0.5rem and reaching for it by name (as three components did)\n // silently loses 4px per side. See STATUS: the scale gap is the root cause.\n paddingLeft: tokens.spacingElement3,\n paddingRight: tokens.spacingElement3,\n paddingTop: tokens.spacingElement1,\n paddingBottom: tokens.spacingElement1,\n fontSize: tokens.textXs,\n lineHeight: tokens.leadingXs,\n fontWeight: tokens.fontWeightSemibold,\n color: tokens.accentDefault,\n cursor: \"pointer\",\n userSelect: \"none\",\n backgroundColor: \"transparent\",\n outlineStyle: \"none\",\n ...shorthands.border(\"0\"),\n boxShadow: \"none\",\n aspectRatio: \"auto\",\n width: \"auto\",\n height: \"auto\",\n transitionProperty: \"background-color, color\",\n transitionDuration: \"150ms\",\n transitionTimingFunction: \"cubic-bezier(0.4, 0, 0.2, 1)\",\n \":hover:not([data-checked])\": {\n backgroundColor: tokens.accentSoft,\n },\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineColor: tokens.accentA8,\n },\n \"&[data-disabled]\": {\n pointerEvents: \"none\",\n opacity: 0.5,\n backgroundColor: \"transparent\",\n },\n \"&[data-checked]\": {\n backgroundColor: \"transparent\",\n color: tokens.accentDefault,\n },\n \"&[data-checked][data-disabled]\": {\n backgroundColor: \"transparent\",\n },\n [`& [${SLOT_ATTR}=\"radio-group-indicator\"]`]: {\n display: \"none\",\n },\n // Keyed on SLOT_ATTR, never data-slot (rule 4): the composed RadioGroup emits both, and\n // data-slot values are shared with v1 so such a rule would also match v1-rendered DOM.\n [`[${SLOT_ATTR}='radio-group-indicator']`]: {\n display: \"none\",\n },\n },\n itemStretch: {\n flexGrow: 1,\n flexShrink: 1,\n flexBasis: \"0%\",\n },\n icon: {\n ...boxModel,\n flexShrink: 0,\n width: \"1rem\",\n height: \"1rem\",\n pointerEvents: \"none\",\n \"& svg\": {\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n },\n },\n label: {\n lineHeight: \"1rem\",\n overflowX: \"hidden\",\n overflowY: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n})\n\nexport const SegmentedControl = React.forwardRef<\n HTMLDivElement,\n SegmentedControlProps\n>(function SegmentedControl(\n {\n className,\n layout = \"hug\",\n orientation = \"horizontal\",\n value: valueProp,\n defaultValue,\n onValueChange,\n children,\n asChild: _asChild,\n ...props\n },\n forwardedRef\n) {\n const styles = useStyles()\n const rootRef = useRef<HTMLDivElement>(null)\n const [trackedValue, setTrackedValue] = useState(defaultValue)\n // Starts false to prevent CSS transition flash on SSR hydration\n const [indicatorReady, setIndicatorReady] = useState(false)\n const [indicatorStyle, setIndicatorStyle] = useState<React.CSSProperties>({\n opacity: 0,\n })\n\n const isControlled = valueProp !== undefined\n const currentValue = isControlled ? valueProp : trackedValue\n\n const updateIndicator = useCallback(() => {\n if (!rootRef.current) return\n const el = rootRef.current.querySelector<HTMLElement>(\n `[${SLOT_ATTR}=\"segmented-control-item\"][data-checked]`\n )\n if (!el) return\n setIndicatorStyle({\n opacity: 1,\n width: el.offsetWidth,\n height: el.offsetHeight,\n transform: `translate(${el.offsetLeft}px, ${el.offsetTop}px)`,\n })\n setIndicatorReady(true)\n }, [])\n\n // Must run before indicator effect so equalized widths are measured correctly\n useLayoutEffect(() => {\n if (!rootRef.current) return\n const items = Array.from(\n rootRef.current.querySelectorAll<HTMLElement>(\n `[${SLOT_ATTR}=\"segmented-control-item\"]`\n )\n )\n if (!items.length) return\n items.forEach((el) => (el.style.minWidth = \"\"))\n if (layout !== \"equal\") return\n const max = Math.max(...items.map((el) => el.offsetWidth))\n items.forEach((el) => (el.style.minWidth = `${max}px`))\n }, [layout])\n\n useLayoutEffect(() => {\n if (!indicatorReady) {\n updateIndicator()\n return\n }\n const raf = requestAnimationFrame(updateIndicator)\n return () => cancelAnimationFrame(raf)\n }, [currentValue, indicatorReady, updateIndicator])\n\n const handleValueChange = useCallback(\n (value: string, eventDetails: RadioGroupChangeDetails) => {\n onValueChange?.(value, eventDetails)\n if (!isControlled && !eventDetails.isCanceled) setTrackedValue(value)\n },\n [isControlled, onValueChange]\n )\n\n const handleRef = (node: HTMLDivElement | null) => {\n rootRef.current = node\n if (typeof forwardedRef === \"function\") {\n forwardedRef(node)\n } else if (forwardedRef) {\n forwardedRef.current = node\n }\n }\n\n const contextValue = React.useMemo(() => ({ layout }), [layout])\n\n return (\n <SegmentedControlContext.Provider value={contextValue}>\n <RadioGroupBase\n ref={handleRef}\n data-slot=\"segmented-control\"\n {...{ [SLOT_ATTR]: \"segmented-control\" }}\n data-layout={layout}\n value={isControlled ? valueProp : undefined}\n defaultValue={defaultValue}\n onValueChange={handleValueChange}\n orientation={orientation}\n className={mergeClasses(\n styles.group,\n layout === \"stretch\" && styles.groupStretch,\n orientation === \"vertical\" && styles.groupVertical,\n className\n )}\n {...(props as RadioGroupBaseProps)}\n >\n <span\n aria-hidden=\"true\"\n data-slot=\"segmented-control-indicator\"\n {...{ [SLOT_ATTR]: \"segmented-control-indicator\" }}\n className={mergeClasses(\n styles.indicator,\n indicatorReady && styles.indicatorAnimated\n )}\n style={indicatorStyle}\n />\n {children}\n </RadioGroupBase>\n </SegmentedControlContext.Provider>\n )\n})\n\n// Base UI renders a <span> by default; a native button keeps the HTMLButtonElement ref, native\n// disabled and the id Radix had on the item.\nconst ITEM_ELEMENT = <button type=\"button\" />\n\nexport const SegmentedControlItem = React.forwardRef<\n HTMLButtonElement,\n SegmentedControlItemProps\n>(function SegmentedControlItem(\n {\n className,\n value,\n icon,\n children,\n asChild: _asChild,\n checked: _checked,\n ...props\n },\n ref\n) {\n const styles = useStyles()\n const { layout } = React.useContext(SegmentedControlContext)\n\n return (\n <Radio.Root\n ref={ref}\n nativeButton\n render={ITEM_ELEMENT}\n value={value}\n data-slot=\"segmented-control-item\"\n {...{ [SLOT_ATTR]: \"segmented-control-item\" }}\n className={mergeClasses(\n styles.item,\n layout === \"stretch\" && styles.itemStretch,\n className\n )}\n {...(props as Omit<Radio.Root.Props<string>, \"value\">)}\n >\n {icon && (\n <span\n aria-hidden=\"true\"\n data-slot=\"segmented-control-item-icon\"\n {...{ [SLOT_ATTR]: \"segmented-control-item-icon\" }}\n className={styles.icon}\n >\n {icon}\n </span>\n )}\n {children && (\n <span\n data-slot=\"segmented-control-item-label\"\n {...{ [SLOT_ATTR]: \"segmented-control-item-label\" }}\n className={styles.label}\n >\n {children}\n </span>\n )}\n </Radio.Root>\n )\n})\n"],"names":["SegmentedControlContext","React","useStyles","makeZenithStyles","boxModel","shorthands","tokens.spacingElement1","tokens.accentSoft","tokens.body","nativeControl","tokens.spacingElement3","tokens.textXs","tokens.leadingXs","tokens.fontWeightSemibold","tokens.accentDefault","tokens.accentA8","SLOT_ATTR","SegmentedControl","className","layout","orientation","valueProp","defaultValue","onValueChange","children","_asChild","props","forwardedRef","styles","rootRef","useRef","trackedValue","setTrackedValue","useState","indicatorReady","setIndicatorReady","indicatorStyle","setIndicatorStyle","isControlled","currentValue","updateIndicator","useCallback","el","useLayoutEffect","items","max","raf","handleValueChange","value","eventDetails","handleRef","node","contextValue","jsx","jsxs","RadioGroupBase","mergeClasses","ITEM_ELEMENT","SegmentedControlItem","icon","_checked","ref","Radio"],"mappings":"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"}
1
+ {"version":3,"file":"segmented-control.js","sources":["../../../src/components/segmented-control/segmented-control.tsx"],"sourcesContent":["import * as React from \"react\"\nimport { useCallback, useLayoutEffect, useRef, useState } from \"react\"\nimport { Radio } from \"@base-ui/react/radio\"\n\nimport { mergeClasses, shorthands } from \"@epilot/zenith-runtime/v1\"\n\nimport { SLOT_ATTR } from \"../../renderer/contract\"\nimport { makeZenithStyles } from \"../../styles/make-styles\"\nimport { boxModel, nativeControl } from \"../../styles/host-reset\"\nimport * as tokens from \"../../tokens\"\nimport {\n RadioGroupBase,\n type RadioGroupBaseProps,\n} from \"../radio/radio-group-base\"\nimport type {\n RadioGroupChangeDetails,\n RadioGroupItemProps,\n RadioGroupProps,\n} from \"../radio/radio\"\n\nexport type SegmentedControlLayout = \"hug\" | \"equal\" | \"stretch\"\n\nexport type SegmentedControlProps = RadioGroupProps & {\n layout?: SegmentedControlLayout\n}\n\nexport type SegmentedControlItemProps = RadioGroupItemProps & {\n icon?: React.ReactNode\n}\n\ninterface SegmentedControlContextValue {\n layout: SegmentedControlLayout\n}\n\nconst SegmentedControlContext =\n React.createContext<SegmentedControlContextValue>({\n layout: \"hug\",\n })\n\nconst useStyles = makeZenithStyles({\n group: {\n ...boxModel,\n position: \"relative\",\n display: \"inline-flex\",\n alignItems: \"center\",\n ...shorthands.gap(tokens.spacingElement1),\n ...shorthands.borderRadius(\"9999px\"),\n backgroundColor: tokens.accentSoft,\n ...shorthands.padding(tokens.spacingElement1),\n ...shorthands.border(\"0\"),\n boxShadow: \"none\",\n },\n groupStretch: {\n ...boxModel,\n display: \"flex\",\n width: \"100%\",\n },\n groupVertical: {\n ...boxModel,\n flexDirection: \"column\",\n display: \"inline-flex\",\n width: \"fit-content\",\n },\n indicator: {\n ...boxModel,\n pointerEvents: \"none\",\n position: \"absolute\",\n top: 0,\n left: 0,\n zIndex: 0,\n ...shorthands.borderRadius(\"9999px\"),\n backgroundColor: tokens.body,\n // Tailwind `shadow-sm`\n boxShadow: \"0 1px 2px 0 #0000000d\",\n },\n indicatorAnimated: {\n ...boxModel,\n transitionProperty: \"transform, width, height\",\n transitionDuration: \"150ms\",\n transitionTimingFunction: \"cubic-bezier(0.4, 0, 0.2, 1)\",\n },\n item: {\n ...nativeControl,\n position: \"relative\",\n zIndex: 1,\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n ...shorthands.gap(tokens.spacingElement1),\n ...shorthands.borderRadius(\"9999px\"),\n minWidth: \"3rem\",\n // v1 uses Tailwind's `px-3` = 0.75rem here. The semantic spacing scale has NO 0.75rem\n // token -- it runs 0.25/0.5/0.5/1/1.5/2 -- so this is a literal by necessity.\n // `spacingGroup1` is 0.5rem and reaching for it by name (as three components did)\n // silently loses 4px per side. See STATUS: the scale gap is the root cause.\n paddingLeft: tokens.spacingElement3,\n paddingRight: tokens.spacingElement3,\n paddingTop: tokens.spacingElement1,\n paddingBottom: tokens.spacingElement1,\n fontSize: tokens.textXs,\n lineHeight: tokens.leadingXs,\n fontWeight: tokens.fontWeightSemibold,\n color: tokens.accentDefault,\n cursor: \"pointer\",\n userSelect: \"none\",\n backgroundColor: \"transparent\",\n outlineStyle: \"none\",\n ...shorthands.border(\"0\"),\n boxShadow: \"none\",\n aspectRatio: \"auto\",\n width: \"auto\",\n height: \"auto\",\n transitionProperty: \"background-color, color\",\n transitionDuration: \"150ms\",\n transitionTimingFunction: \"cubic-bezier(0.4, 0, 0.2, 1)\",\n \":hover:not([data-checked])\": {\n backgroundColor: tokens.accentSoft,\n },\n \":focus-visible\": {\n outlineWidth: \"2px\",\n outlineStyle: \"solid\",\n outlineColor: tokens.accentA8,\n },\n \"&[data-disabled]\": {\n pointerEvents: \"none\",\n opacity: 0.5,\n backgroundColor: \"transparent\",\n },\n \"&[data-checked]\": {\n backgroundColor: \"transparent\",\n color: tokens.accentDefault,\n },\n \"&[data-checked][data-disabled]\": {\n backgroundColor: \"transparent\",\n },\n [`& [${SLOT_ATTR}=\"radio-group-indicator\"]`]: {\n display: \"none\",\n },\n // Keyed on SLOT_ATTR, never data-slot (rule 4): the composed RadioGroup emits both, and\n // data-slot values are shared with v1 so such a rule would also match v1-rendered DOM.\n [`[${SLOT_ATTR}='radio-group-indicator']`]: {\n display: \"none\",\n },\n },\n itemStretch: {\n flexGrow: 1,\n flexShrink: 1,\n flexBasis: \"0%\",\n },\n icon: {\n ...boxModel,\n flexShrink: 0,\n width: \"1rem\",\n height: \"1rem\",\n pointerEvents: \"none\",\n \"& svg\": {\n width: \"100%\",\n height: \"100%\",\n display: \"block\",\n },\n },\n label: {\n lineHeight: \"1rem\",\n overflowX: \"hidden\",\n overflowY: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n },\n})\n\nexport const SegmentedControl = React.forwardRef<\n HTMLDivElement,\n SegmentedControlProps\n>(function SegmentedControl(\n {\n className,\n layout = \"hug\",\n orientation = \"horizontal\",\n value: valueProp,\n defaultValue,\n onValueChange,\n children,\n asChild: _asChild,\n ...props\n },\n forwardedRef\n) {\n const styles = useStyles()\n const rootRef = useRef<HTMLDivElement>(null)\n const [trackedValue, setTrackedValue] = useState(defaultValue)\n // Starts false to prevent CSS transition flash on SSR hydration\n const [indicatorReady, setIndicatorReady] = useState(false)\n const [indicatorStyle, setIndicatorStyle] = useState<React.CSSProperties>({\n opacity: 0,\n })\n\n const isControlled = valueProp !== undefined\n const currentValue = isControlled ? valueProp : trackedValue\n\n const updateIndicator = useCallback(() => {\n if (!rootRef.current) return\n const el = rootRef.current.querySelector<HTMLElement>(\n `[${SLOT_ATTR}=\"segmented-control-item\"][data-checked]`\n )\n if (!el) return\n setIndicatorStyle({\n opacity: 1,\n width: el.offsetWidth,\n height: el.offsetHeight,\n transform: `translate(${el.offsetLeft}px, ${el.offsetTop}px)`,\n })\n setIndicatorReady(true)\n }, [])\n\n const updateItemWidths = useCallback(() => {\n if (!rootRef.current) return\n const items = Array.from(\n rootRef.current.querySelectorAll<HTMLElement>(\n `[${SLOT_ATTR}=\"segmented-control-item\"]`\n )\n )\n if (!items.length) return\n items.forEach((el) => (el.style.minWidth = \"\"))\n if (layout !== \"equal\") return\n const max = Math.max(...items.map((el) => el.offsetWidth))\n items.forEach((el) => (el.style.minWidth = `${max}px`))\n }, [layout])\n\n // Must run before indicator effect so equalized widths are measured correctly.\n useLayoutEffect(updateItemWidths, [updateItemWidths])\n\n useLayoutEffect(() => {\n if (!indicatorReady) {\n updateIndicator()\n return\n }\n const raf = requestAnimationFrame(updateIndicator)\n return () => cancelAnimationFrame(raf)\n }, [currentValue, indicatorReady, updateIndicator])\n\n React.useEffect(() => {\n if (!rootRef.current || typeof ResizeObserver === \"undefined\") return\n let frame: number | undefined\n const observer = new ResizeObserver(() => {\n if (frame !== undefined) cancelAnimationFrame(frame)\n // Equalizing one item can resize its siblings. Write in the next frame rather\n // than during observer delivery, and measure the pill after the width pass.\n frame = requestAnimationFrame(() => {\n frame = undefined\n updateItemWidths()\n updateIndicator()\n })\n })\n rootRef.current\n .querySelectorAll<HTMLElement>(`[${SLOT_ATTR}=\"segmented-control-item\"]`)\n .forEach((item) => observer.observe(item, { box: \"border-box\" }))\n return () => {\n observer.disconnect()\n if (frame !== undefined) cancelAnimationFrame(frame)\n }\n }, [children, updateIndicator, updateItemWidths])\n\n const handleValueChange = useCallback(\n (value: string, eventDetails: RadioGroupChangeDetails) => {\n onValueChange?.(value, eventDetails)\n if (!isControlled && !eventDetails.isCanceled) setTrackedValue(value)\n },\n [isControlled, onValueChange]\n )\n\n const handleRef = (node: HTMLDivElement | null) => {\n rootRef.current = node\n if (typeof forwardedRef === \"function\") {\n forwardedRef(node)\n } else if (forwardedRef) {\n forwardedRef.current = node\n }\n }\n\n const contextValue = React.useMemo(() => ({ layout }), [layout])\n\n return (\n <SegmentedControlContext.Provider value={contextValue}>\n <RadioGroupBase\n ref={handleRef}\n data-slot=\"segmented-control\"\n {...{ [SLOT_ATTR]: \"segmented-control\" }}\n data-layout={layout}\n value={isControlled ? valueProp : undefined}\n defaultValue={defaultValue}\n onValueChange={handleValueChange}\n orientation={orientation}\n className={mergeClasses(\n styles.group,\n layout === \"stretch\" && styles.groupStretch,\n orientation === \"vertical\" && styles.groupVertical,\n className\n )}\n {...(props as RadioGroupBaseProps)}\n >\n <span\n aria-hidden=\"true\"\n data-slot=\"segmented-control-indicator\"\n {...{ [SLOT_ATTR]: \"segmented-control-indicator\" }}\n className={mergeClasses(\n styles.indicator,\n indicatorReady && styles.indicatorAnimated\n )}\n style={indicatorStyle}\n />\n {children}\n </RadioGroupBase>\n </SegmentedControlContext.Provider>\n )\n})\n\n// Base UI renders a <span> by default; a native button keeps the HTMLButtonElement ref, native\n// disabled and the id Radix had on the item.\nconst ITEM_ELEMENT = <button type=\"button\" />\n\nexport const SegmentedControlItem = React.forwardRef<\n HTMLButtonElement,\n SegmentedControlItemProps\n>(function SegmentedControlItem(\n {\n className,\n value,\n icon,\n children,\n asChild: _asChild,\n checked: _checked,\n ...props\n },\n ref\n) {\n const styles = useStyles()\n const { layout } = React.useContext(SegmentedControlContext)\n\n return (\n <Radio.Root\n ref={ref}\n nativeButton\n render={ITEM_ELEMENT}\n value={value}\n data-slot=\"segmented-control-item\"\n {...{ [SLOT_ATTR]: \"segmented-control-item\" }}\n className={mergeClasses(\n styles.item,\n layout === \"stretch\" && styles.itemStretch,\n className\n )}\n {...(props as Omit<Radio.Root.Props<string>, \"value\">)}\n >\n {icon && (\n <span\n aria-hidden=\"true\"\n data-slot=\"segmented-control-item-icon\"\n {...{ [SLOT_ATTR]: \"segmented-control-item-icon\" }}\n className={styles.icon}\n >\n {icon}\n </span>\n )}\n {children && (\n <span\n data-slot=\"segmented-control-item-label\"\n {...{ [SLOT_ATTR]: \"segmented-control-item-label\" }}\n className={styles.label}\n >\n {children}\n </span>\n )}\n </Radio.Root>\n )\n})\n"],"names":["SegmentedControlContext","React","useStyles","makeZenithStyles","boxModel","shorthands","tokens.spacingElement1","tokens.accentSoft","tokens.body","nativeControl","tokens.spacingElement3","tokens.textXs","tokens.leadingXs","tokens.fontWeightSemibold","tokens.accentDefault","tokens.accentA8","SLOT_ATTR","SegmentedControl","className","layout","orientation","valueProp","defaultValue","onValueChange","children","_asChild","props","forwardedRef","styles","rootRef","useRef","trackedValue","setTrackedValue","useState","indicatorReady","setIndicatorReady","indicatorStyle","setIndicatorStyle","isControlled","currentValue","updateIndicator","useCallback","el","updateItemWidths","items","max","useLayoutEffect","raf","frame","observer","item","handleValueChange","value","eventDetails","handleRef","node","contextValue","jsx","jsxs","RadioGroupBase","mergeClasses","ITEM_ELEMENT","SegmentedControlItem","icon","_checked","ref","Radio"],"mappings":"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"}