@acronis-platform/ui-react 0.54.0 → 0.55.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 (65) hide show
  1. package/dist/components/ui/avatar/avatar.js +1 -1
  2. package/dist/components/ui/avatar/avatar.js.map +1 -1
  3. package/dist/components/ui/breadcrumb/breadcrumb.js +5 -5
  4. package/dist/components/ui/breadcrumb/breadcrumb.js.map +1 -1
  5. package/dist/components/ui/chip/chip.js +1 -1
  6. package/dist/components/ui/chip/chip.js.map +1 -1
  7. package/dist/components/ui/combobox/combobox.js +51 -47
  8. package/dist/components/ui/combobox/combobox.js.map +1 -1
  9. package/dist/components/ui/data-table/data-table-column-header.js +7 -7
  10. package/dist/components/ui/data-table/data-table-column-header.js.map +1 -1
  11. package/dist/components/ui/data-table/data-table-view-options.js +4 -4
  12. package/dist/components/ui/data-table/data-table-view-options.js.map +1 -1
  13. package/dist/components/ui/data-table/data-table.js +1 -1
  14. package/dist/components/ui/data-table/data-table.js.map +1 -1
  15. package/dist/components/ui/dialog/dialog.js +36 -35
  16. package/dist/components/ui/dialog/dialog.js.map +1 -1
  17. package/dist/components/ui/dropdown-menu/dropdown-menu.js +55 -54
  18. package/dist/components/ui/dropdown-menu/dropdown-menu.js.map +1 -1
  19. package/dist/components/ui/filter-search/filter-search.js +28 -0
  20. package/dist/components/ui/filter-search/filter-search.js.map +1 -0
  21. package/dist/components/ui/input-date-picker/input-date-picker.js +8 -8
  22. package/dist/components/ui/input-date-picker/input-date-picker.js.map +1 -1
  23. package/dist/components/ui/input-search/input-search.js +11 -12
  24. package/dist/components/ui/input-search/input-search.js.map +1 -1
  25. package/dist/components/ui/input-select/input-select.js +72 -68
  26. package/dist/components/ui/input-select/input-select.js.map +1 -1
  27. package/dist/components/ui/input-text/input-text.js +6 -6
  28. package/dist/components/ui/input-text/input-text.js.map +1 -1
  29. package/dist/components/ui/popover/popover.js +18 -17
  30. package/dist/components/ui/popover/popover.js.map +1 -1
  31. package/dist/components/ui/resizable/resizable.js +24 -32
  32. package/dist/components/ui/resizable/resizable.js.map +1 -1
  33. package/dist/components/ui/sheet/sheet.js +38 -37
  34. package/dist/components/ui/sheet/sheet.js.map +1 -1
  35. package/dist/components/ui/sidebar-primary/sidebar-primary.js +200 -134
  36. package/dist/components/ui/sidebar-primary/sidebar-primary.js.map +1 -1
  37. package/dist/components/ui/sidebar-secondary/sidebar-secondary.js +511 -357
  38. package/dist/components/ui/sidebar-secondary/sidebar-secondary.js.map +1 -1
  39. package/dist/components/ui/switch/switch.js +6 -6
  40. package/dist/components/ui/switch/switch.js.map +1 -1
  41. package/dist/components/ui/table/table.js +7 -7
  42. package/dist/components/ui/table/table.js.map +1 -1
  43. package/dist/components/ui/tabs/tabs.js +11 -11
  44. package/dist/components/ui/tabs/tabs.js.map +1 -1
  45. package/dist/components/ui/toast/toast.js +35 -33
  46. package/dist/components/ui/toast/toast.js.map +1 -1
  47. package/dist/components/ui/tooltip/tooltip.js +41 -37
  48. package/dist/components/ui/tooltip/tooltip.js.map +1 -1
  49. package/dist/index.js +356 -355
  50. package/dist/index.js.map +1 -1
  51. package/dist/lib/portal-container.js +14 -0
  52. package/dist/lib/portal-container.js.map +1 -0
  53. package/dist/react.js +356 -355
  54. package/dist/react.js.map +1 -1
  55. package/dist/src/components/ui/filter-search/filter-search.d.ts +6 -0
  56. package/dist/src/components/ui/filter-search/index.d.ts +2 -0
  57. package/dist/src/components/ui/resizable/index.d.ts +2 -1
  58. package/dist/src/components/ui/resizable/resizable.d.ts +2 -5
  59. package/dist/src/components/ui/sidebar-primary/sidebar-primary.d.ts +48 -3
  60. package/dist/src/components/ui/sidebar-secondary/index.d.ts +1 -1
  61. package/dist/src/components/ui/sidebar-secondary/sidebar-secondary.d.ts +38 -33
  62. package/dist/src/index.d.ts +2 -0
  63. package/dist/src/lib/portal-container.d.ts +36 -0
  64. package/dist/ui-react.css +1 -1
  65. package/package.json +1 -1
@@ -1,76 +1,89 @@
1
- import { jsx as i, jsxs as y, Fragment as w } from "react/jsx-runtime";
2
- import * as t from "react";
3
- import { mergeProps as x } from "@base-ui/react/merge-props";
1
+ import { jsx as i, jsxs as v, Fragment as _ } from "react/jsx-runtime";
2
+ import * as n from "react";
3
+ import { mergeProps as y } from "@base-ui/react/merge-props";
4
4
  import { useRender as f } from "@base-ui/react/use-render";
5
- import { SquareArrowUpRightIcon as S } from "@acronis-platform/icons-react/stroke-mono";
6
- import { cva as P } from "../../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
7
- import { cn as l } from "../../../lib/utils.js";
8
- import { ScrollArea as R } from "../scroll-area/scroll-area.js";
9
- const h = t.createContext(null);
5
+ import { SquareArrowUpRightIcon as T } from "@acronis-platform/icons-react/stroke-mono";
6
+ import { cva as E } from "../../../node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.js";
7
+ import { cn as m } from "../../../lib/utils.js";
8
+ import { Tooltip as x, TooltipTrigger as h, TooltipContent as w } from "../tooltip/tooltip.js";
9
+ import { ScrollArea as I } from "../scroll-area/scroll-area.js";
10
+ const N = n.createContext(null);
10
11
  function g() {
11
- return t.useContext(h) ?? {
12
+ return n.useContext(N) ?? {
12
13
  expanded: !0,
13
14
  toggleExpanded: () => {
14
15
  }
15
16
  };
16
17
  }
17
- function _(a, e, r) {
18
- const [n, d] = t.useState(e), o = a !== void 0, m = o ? a : n, u = t.useCallback(
19
- (s) => {
20
- o || d(s), r == null || r(s);
18
+ function M(a, e, r) {
19
+ const [s, t] = n.useState(e), o = a !== void 0, l = o ? a : s, d = n.useCallback(
20
+ (c) => {
21
+ o || t(c), r == null || r(c);
21
22
  },
22
23
  [o, r]
23
24
  );
24
- return [m, u];
25
+ return [l, d];
25
26
  }
26
- const E = t.forwardRef(
27
+ function S(a, { enabled: e }) {
28
+ const [r, s] = n.useState(!1);
29
+ return n.useEffect(() => {
30
+ const t = a.current;
31
+ if (!e || !t) {
32
+ s(!1);
33
+ return;
34
+ }
35
+ const o = () => s(t.scrollWidth > t.clientWidth);
36
+ o();
37
+ const l = new ResizeObserver(o);
38
+ return l.observe(t), () => l.disconnect();
39
+ }, [a, e]), r;
40
+ }
41
+ const k = n.forwardRef(
27
42
  ({
28
43
  className: a,
29
44
  expanded: e,
30
45
  defaultExpanded: r = !0,
31
- onExpandedChange: n,
32
- "aria-label": d = "Primary",
46
+ onExpandedChange: s,
47
+ "aria-label": t = "Primary",
33
48
  render: o,
34
- children: m,
35
- ...u
36
- }, s) => {
37
- const [c, p] = _(
49
+ children: l,
50
+ ...d
51
+ }, c) => {
52
+ const [u, p] = M(
38
53
  e,
39
54
  r,
40
- n
41
- ), v = t.useMemo(
42
- () => ({ expanded: c, toggleExpanded: () => p(!c) }),
43
- [c, p]
44
- ), b = f({
55
+ s
56
+ ), b = n.useMemo(
57
+ () => ({ expanded: u, toggleExpanded: () => p(!u) }),
58
+ [u, p]
59
+ ), R = f({
45
60
  render: o,
46
- ref: s,
61
+ ref: c,
47
62
  defaultTagName: "nav",
48
- props: x(
63
+ props: y(
49
64
  {
50
- "aria-label": d,
51
- "data-state": c ? "expanded" : "collapsed",
52
- className: l(
65
+ "aria-label": t,
66
+ "data-state": u ? "expanded" : "collapsed",
67
+ className: m(
53
68
  "group/sidebar flex h-full flex-col bg-[var(--ui-sidebar-primary-global-container-color)] w-[var(--ui-sidebar-primary-collapsed-container-width)] data-[state=expanded]:w-[var(--ui-sidebar-primary-expanded-container-width)] transition-[width]",
54
69
  a
55
70
  ),
56
- children: m
71
+ children: l
57
72
  },
58
- u
73
+ d
59
74
  )
60
75
  });
61
- return /* @__PURE__ */ i(h.Provider, { value: v, children: b });
76
+ return /* @__PURE__ */ i(N.Provider, { value: b, children: R });
62
77
  }
63
78
  );
64
- E.displayName = "SidebarPrimary";
65
- const M = t.forwardRef(({ className: a, ...e }, r) => (
66
- // Hosts a consumer-provided logo (R7 — no Logo part is built). Padding and the
67
- // logo height switch on expanded/collapsed; `[&_*]:h-…` sizes whatever the
68
- // consumer slots in. The logo color token tints any `currentColor` mark.
69
- /* @__PURE__ */ i(
79
+ k.displayName = "SidebarPrimary";
80
+ const z = n.forwardRef(({ className: a, logo: e, collapsedLogo: r, children: s, ...t }, o) => {
81
+ const { expanded: l } = g(), c = e != null || r != null ? l ? e ?? r : r ?? e : s;
82
+ return /* @__PURE__ */ i(
70
83
  "div",
71
84
  {
72
- ref: r,
73
- className: l(
85
+ ref: o,
86
+ className: m(
74
87
  "flex items-center shrink-0 text-[var(--ui-sidebar-primary-global-logo-color)]",
75
88
  "px-[var(--ui-sidebar-primary-collapsed-container-header-padding-x)] py-[var(--ui-sidebar-primary-collapsed-container-header-padding-y)]",
76
89
  "[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-collapsed-logo-height)] [&_:where(img,svg)]:w-auto",
@@ -78,62 +91,79 @@ const M = t.forwardRef(({ className: a, ...e }, r) => (
78
91
  "group-data-[state=expanded]/sidebar:[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-expanded-logo-height)]",
79
92
  a
80
93
  ),
81
- ...e
94
+ ...t,
95
+ children: c
82
96
  }
83
- )
84
- ));
85
- M.displayName = "SidebarPrimaryHeader";
86
- const k = t.forwardRef(({ className: a, children: e, ...r }, n) => (
97
+ );
98
+ });
99
+ z.displayName = "SidebarPrimaryHeader";
100
+ const O = n.forwardRef(({ className: a, children: e, ...r }, s) => (
87
101
  // The section list scrolls inside a ScrollArea: its overlay scrollbar floats
88
102
  // over the content and reserves no gutter, so the full-bleed selected row is
89
103
  // never cropped — on every OS, unlike a native `overflow` scrollbar.
90
- /* @__PURE__ */ i(R, { ref: n, className: l("min-h-0 flex-1", a), ...r, children: /* @__PURE__ */ i("div", { className: "flex flex-col gap-[var(--ui-sidebar-primary-global-section-list-gap)]", children: e }) })
104
+ //
105
+ // Base UI's Scroll Area Content sets `min-width: fit-content` inline (it
106
+ // needs the content's true intrinsic width to detect horizontal overflow),
107
+ // which forces every row wider than the rail — overriding `min-w-0` +
108
+ // `truncate` on a long label, since intrinsic-width calculations ignore
109
+ // `text-overflow`. We only ever scroll vertically here, so cancel it: the
110
+ // `!` (important) is required to beat the inline style's specificity.
111
+ /* @__PURE__ */ i(
112
+ I,
113
+ {
114
+ ref: s,
115
+ className: m(
116
+ "min-h-0 flex-1 [&_[data-slot=scroll-area-content]]:min-w-0!",
117
+ a
118
+ ),
119
+ ...r,
120
+ children: /* @__PURE__ */ i("div", { className: "flex flex-col gap-[var(--ui-sidebar-primary-global-section-list-gap)]", children: e })
121
+ }
122
+ )
91
123
  ));
92
- k.displayName = "SidebarPrimaryContent";
93
- const I = t.forwardRef(({ className: a, ...e }, r) => /* @__PURE__ */ i(
124
+ O.displayName = "SidebarPrimaryContent";
125
+ const C = n.forwardRef(({ className: a, ...e }, r) => /* @__PURE__ */ i(
94
126
  "div",
95
127
  {
96
128
  ref: r,
97
- className: l(
129
+ className: m(
98
130
  "flex flex-col shrink-0 gap-[var(--ui-sidebar-primary-global-footer-list-gap)]",
99
131
  "border-t border-[var(--ui-sidebar-primary-global-container-footer-border-color)] [border-top-width:var(--ui-sidebar-primary-global-container-footer-border-width)]",
100
- "py-[var(--ui-sidebar-primary-section-container-padding-y)]",
101
132
  a
102
133
  ),
103
134
  ...e
104
135
  }
105
136
  ));
106
- I.displayName = "SidebarPrimaryFooter";
107
- const z = t.forwardRef(({ className: a, ...e }, r) => (
108
- // `firstSection` in Figma only toggles the top divider — derive it from DOM
137
+ C.displayName = "SidebarPrimaryFooter";
138
+ const F = n.forwardRef(({ className: a, ...e }, r) => (
109
139
  // position (`:not(:first-child)`) instead of a prop.
110
140
  /* @__PURE__ */ i(
111
141
  "div",
112
142
  {
113
143
  ref: r,
114
- className: l(
115
- "flex flex-col py-[var(--ui-sidebar-primary-section-container-padding-y)]",
116
- "[&:not(:first-child)]:border-t [&:not(:first-child)]:border-[var(--ui-sidebar-primary-section-container-border-color)] [&:not(:first-child)]:[border-top-width:var(--ui-sidebar-primary-section-container-border-width)]",
144
+ className: m(
145
+ "flex flex-col pb-[var(--ui-sidebar-primary-section-container-padding-y)]",
146
+ "[&:not(:first-child)]:border-t [&:not(:first-child)]:border-[var(--ui-sidebar-primary-section-container-border-color)] [&:not(:first-child)]:[border-top-width:var(--ui-sidebar-primary-section-container-border-width)] [&:not(:first-child)]:pt-[var(--ui-sidebar-primary-section-container-padding-y)]",
117
147
  a
118
148
  ),
119
149
  ...e
120
150
  }
121
151
  )
122
152
  ));
123
- z.displayName = "SidebarPrimarySection";
124
- const T = t.forwardRef(({ className: a, ...e }, r) => /* @__PURE__ */ i(
153
+ F.displayName = "SidebarPrimarySection";
154
+ const L = n.forwardRef(({ className: a, ...e }, r) => /* @__PURE__ */ i(
125
155
  "ul",
126
156
  {
127
157
  ref: r,
128
- className: l(
158
+ className: m(
129
159
  "flex flex-col gap-[var(--ui-sidebar-primary-section-menu-item-list-gap)]",
130
160
  a
131
161
  ),
132
162
  ...e
133
163
  }
134
164
  ));
135
- T.displayName = "SidebarPrimaryMenu";
136
- const N = P(
165
+ L.displayName = "SidebarPrimaryMenu";
166
+ const P = E(
137
167
  "group/menu-item flex w-full items-center gap-[var(--ui-sidebar-primary-menu-item-global-container-gap)] h-[var(--ui-sidebar-primary-menu-item-global-container-height)] px-[var(--ui-sidebar-primary-menu-item-global-container-padding-x)] py-[var(--ui-sidebar-primary-menu-item-global-container-padding-y)] no-underline ui-sidebar-primary-menu-item-global-label-text-style transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-focus-brand)] focus-visible:ring-inset [&_svg]:shrink-0 [&_svg]:size-[var(--ui-sidebar-primary-menu-item-global-icon-size)]",
138
168
  {
139
169
  variants: {
@@ -146,62 +176,69 @@ const N = P(
146
176
  variant: "unselected"
147
177
  }
148
178
  }
149
- ), C = t.forwardRef(({ className: a, selected: e = !1, icon: r, render: n, children: d, ...o }, m) => {
150
- const { expanded: u } = g(), s = t.Children.toArray(d), c = s.filter(
151
- (b) => t.isValidElement(b) && b.type.displayName === "SidebarPrimaryMenuItemExtras"
152
- ), p = s.filter(
153
- (b) => !c.includes(b)
154
- ), v = f({
155
- render: n,
156
- ref: m,
157
- defaultTagName: "a",
158
- props: x(
159
- {
160
- className: l(
161
- N({
162
- variant: e ? "selected" : "unselected"
163
- }),
164
- a
165
- ),
166
- "aria-current": e ? "page" : void 0,
167
- children: /* @__PURE__ */ y(w, { children: [
168
- r != null && /* @__PURE__ */ i("span", { className: "flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)]", children: r }),
169
- /* @__PURE__ */ i(
170
- "span",
171
- {
172
- className: l(
173
- "min-w-0 flex-1 truncate text-left",
174
- !u && "sr-only"
175
- ),
176
- children: p
177
- }
179
+ ), V = n.forwardRef(
180
+ ({ className: a, selected: e = !1, icon: r, render: s, children: t, extras: o, ...l }, d) => {
181
+ const { expanded: c } = g(), u = n.useRef(null), p = S(u, { enabled: c }), b = f({
182
+ render: s,
183
+ ref: d,
184
+ defaultTagName: "a",
185
+ props: y(
186
+ {
187
+ className: m(
188
+ P({
189
+ variant: e ? "selected" : "unselected"
190
+ }),
191
+ a
178
192
  ),
179
- c.length > 0 && /* @__PURE__ */ i("span", { className: "flex shrink-0 items-center", children: c })
180
- ] })
181
- },
182
- o
183
- )
184
- });
185
- return /* @__PURE__ */ i("li", { className: "contents", children: v });
186
- });
187
- C.displayName = "SidebarPrimaryMenuItem";
188
- const V = t.forwardRef(({ className: a, variant: e, shortcut: r, tag: n, children: d, ...o }, m) => {
189
- const { expanded: u } = g(), s = e === "tag" || e === "tag-externalLink", c = e === "externalLink" || e === "tag-externalLink", p = e === "shortcut";
190
- return /* @__PURE__ */ y(
193
+ "aria-current": e ? "page" : void 0,
194
+ children: /* @__PURE__ */ v(_, { children: [
195
+ r != null && /* @__PURE__ */ i("span", { className: "flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)]", children: r }),
196
+ /* @__PURE__ */ v(x, { disabled: !p, children: [
197
+ /* @__PURE__ */ i(
198
+ h,
199
+ {
200
+ render: /* @__PURE__ */ i(
201
+ "span",
202
+ {
203
+ ref: u,
204
+ className: m(
205
+ "min-w-0 flex-1 truncate text-start",
206
+ !c && "sr-only"
207
+ )
208
+ }
209
+ ),
210
+ children: t
211
+ }
212
+ ),
213
+ /* @__PURE__ */ i(w, { children: t })
214
+ ] }),
215
+ o != null && /* @__PURE__ */ i("span", { className: m(!c && "hidden"), children: o })
216
+ ] })
217
+ },
218
+ l
219
+ )
220
+ });
221
+ return /* @__PURE__ */ i("li", { className: "contents", children: b });
222
+ }
223
+ );
224
+ V.displayName = "SidebarPrimaryMenuItem";
225
+ const j = n.forwardRef(({ className: a, variant: e, shortcut: r, tag: s, children: t, ...o }, l) => {
226
+ const { expanded: d } = g(), c = e === "tag" || e === "tag-externalLink", u = e === "externalLink" || e === "tag-externalLink", p = e === "shortcut";
227
+ return /* @__PURE__ */ v(
191
228
  "span",
192
229
  {
193
- ref: m,
194
- className: l(
230
+ ref: l,
231
+ className: m(
195
232
  "inline-flex items-center gap-[var(--ui-sidebar-primary-menu-item-extras-global-container-gap)]",
196
- !u && "hidden",
233
+ !d && "hidden",
197
234
  a
198
235
  ),
199
236
  ...o,
200
237
  children: [
201
- s && (n ?? d),
202
- p && /* @__PURE__ */ i("span", { className: "ui-sidebar-primary-menu-item-extras-global-shortcut-text-style text-[var(--ui-sidebar-primary-menu-item-extras-global-shortcut-color)]", children: r ?? d }),
203
- c && /* @__PURE__ */ i(
204
- S,
238
+ c && (s ?? t),
239
+ p && /* @__PURE__ */ i("span", { className: "ui-sidebar-primary-menu-item-extras-global-shortcut-text-style text-[var(--ui-sidebar-primary-menu-item-extras-global-shortcut-color)]", children: r ?? t }),
240
+ u && /* @__PURE__ */ i(
241
+ T,
205
242
  {
206
243
  size: 16,
207
244
  className: "text-[var(--ui-sidebar-primary-menu-item-extras-global-external-icon-color)] size-[var(--ui-sidebar-primary-menu-item-extras-global-external-icon-size)]"
@@ -211,42 +248,71 @@ const V = t.forwardRef(({ className: a, variant: e, shortcut: r, tag: n, childre
211
248
  }
212
249
  );
213
250
  });
214
- V.displayName = "SidebarPrimaryMenuItemExtras";
215
- const A = t.forwardRef(({ className: a, icon: e, children: r, onClick: n, ...d }, o) => {
216
- const { expanded: m, toggleExpanded: u } = g();
217
- return /* @__PURE__ */ i("li", { className: "contents", children: /* @__PURE__ */ y(
251
+ j.displayName = "SidebarPrimaryMenuItemExtras";
252
+ const A = n.forwardRef(({ className: a, icon: e, children: r, extras: s, onClick: t, ...o }, l) => {
253
+ const { expanded: d, toggleExpanded: c } = g(), u = n.useRef(null), p = S(u, { enabled: d });
254
+ return /* @__PURE__ */ i("li", { className: "contents", children: /* @__PURE__ */ v(
218
255
  "button",
219
256
  {
220
- ref: o,
257
+ ref: l,
221
258
  type: "button",
222
- "aria-expanded": m,
223
- className: l(
224
- N({ variant: "unselected" }),
225
- "text-left",
259
+ "aria-expanded": d,
260
+ className: m(
261
+ P({ variant: "unselected" }),
262
+ "text-start",
226
263
  a
227
264
  ),
228
- onClick: (s) => {
229
- n == null || n(s), s.defaultPrevented || u();
265
+ onClick: (b) => {
266
+ t == null || t(b), b.defaultPrevented || c();
230
267
  },
231
- ...d,
268
+ ...o,
232
269
  children: [
233
- e != null && /* @__PURE__ */ i("span", { className: "flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)]", children: e }),
234
- /* @__PURE__ */ i("span", { className: l("flex-1 truncate", !m && "sr-only"), children: r })
270
+ e != null && /* @__PURE__ */ i(
271
+ "span",
272
+ {
273
+ className: m(
274
+ "flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)] transition-transform",
275
+ d ? "rtl:rotate-180" : "ltr:rotate-180"
276
+ ),
277
+ children: e
278
+ }
279
+ ),
280
+ /* @__PURE__ */ v(x, { disabled: !p, children: [
281
+ /* @__PURE__ */ i(
282
+ h,
283
+ {
284
+ render: /* @__PURE__ */ i(
285
+ "span",
286
+ {
287
+ ref: u,
288
+ className: m(
289
+ "min-w-0 flex-1 truncate",
290
+ !d && "sr-only"
291
+ )
292
+ }
293
+ ),
294
+ children: r
295
+ }
296
+ ),
297
+ /* @__PURE__ */ i(w, { children: r })
298
+ ] }),
299
+ s != null && /* @__PURE__ */ i("span", { className: m(!d && "hidden"), children: s })
235
300
  ]
236
301
  }
237
302
  ) });
238
303
  });
239
304
  A.displayName = "SidebarPrimaryCollapseTrigger";
240
305
  export {
241
- E as SidebarPrimary,
306
+ k as SidebarPrimary,
242
307
  A as SidebarPrimaryCollapseTrigger,
243
- k as SidebarPrimaryContent,
244
- I as SidebarPrimaryFooter,
245
- M as SidebarPrimaryHeader,
246
- T as SidebarPrimaryMenu,
247
- C as SidebarPrimaryMenuItem,
248
- V as SidebarPrimaryMenuItemExtras,
249
- z as SidebarPrimarySection,
250
- N as sidebarPrimaryMenuItemVariants
308
+ O as SidebarPrimaryContent,
309
+ C as SidebarPrimaryFooter,
310
+ z as SidebarPrimaryHeader,
311
+ L as SidebarPrimaryMenu,
312
+ V as SidebarPrimaryMenuItem,
313
+ j as SidebarPrimaryMenuItemExtras,
314
+ F as SidebarPrimarySection,
315
+ P as sidebarPrimaryMenuItemVariants,
316
+ S as useIsOverflowing
251
317
  };
252
318
  //# sourceMappingURL=sidebar-primary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar-primary.js","sources":["../../../../src/components/ui/sidebar-primary/sidebar-primary.tsx"],"sourcesContent":["import * as React from 'react';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport { SquareArrowUpRightIcon } from '@acronis-platform/icons-react/stroke-mono';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nimport { ScrollArea } from '../scroll-area';\n\n// Composable SidebarPrimary primitives mirroring the Figma \"SidebarPrimary\"\n// component set (node 2092:4359, variant expanded|collapsed). Every color and\n// metric is wired to a next-gen `--ui-sidebar-primary-*` token from\n// @acronis-platform/tokens-pd — no hex, no invented tokens.\n//\n// expanded/collapsed is a width-reflow state, not a panel show/hide, so it is\n// modelled as a controlled/uncontrolled `expanded` prop (default true) that sets\n// `data-state=\"expanded|collapsed\"` on the root. Every metric token has a\n// distinct `collapsed-*` / `expanded-*` name, switched via `data-[state=…]`\n// attribute selectors — Base UI Collapsible would fight this (it hides a panel;\n// the rail never hides). Layout state is shared to descendants through a small\n// context so menu items know whether to show or `sr-only` their label/extras.\n//\n// R2 (menu-item border-radius): the token tier ships no radius token. Verified\n// against the Figma node — the menu-item COMPONENT and its container frame both\n// report cornerRadius=None (the only radius in the node is the COMPONENT_SET's\n// own variant-container chrome). Rows are therefore SQUARE; no `rounded-*` is\n// applied. The focus ring uses the shared `--ui-focus-brand` (no sidebar focus\n// token exists — R1), matching Button/Breadcrumb.\n\ninterface SidebarPrimaryContextValue {\n expanded: boolean;\n /** Flip the rail width — drives the controlled/uncontrolled `expanded` state. */\n toggleExpanded: () => void;\n}\n\nconst SidebarPrimaryContext =\n React.createContext<SidebarPrimaryContextValue | null>(null);\n\nfunction useSidebarPrimaryContext(): SidebarPrimaryContextValue {\n // Default to expanded so parts render standalone (e.g. in isolation tests /\n // stories) without a wrapping root; the toggle is a no-op outside a root.\n return (\n React.useContext(SidebarPrimaryContext) ?? {\n expanded: true,\n toggleExpanded: () => {},\n }\n );\n}\n\n/**\n * Controlled + uncontrolled boolean state (the Base UI idiom). When `controlled`\n * is provided it wins and the setter only emits the change callback; otherwise\n * the setter updates internal state. `onChange` is ALWAYS invoked with the next\n * value so a consumer can react in either mode.\n */\nfunction useControllableBoolean(\n controlled: boolean | undefined,\n defaultValue: boolean,\n onChange?: (next: boolean) => void\n): [boolean, (next: boolean) => void] {\n const [uncontrolled, setUncontrolled] = React.useState(defaultValue);\n const isControlled = controlled !== undefined;\n const value = isControlled ? controlled : uncontrolled;\n const setValue = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolled(next);\n onChange?.(next);\n },\n [isControlled, onChange]\n );\n return [value, setValue];\n}\n\nexport interface SidebarPrimaryProps\n extends React.ComponentPropsWithoutRef<'nav'> {\n /** Controlled expanded (rail width) state. */\n expanded?: boolean;\n /** Uncontrolled initial expanded state. Defaults to `true` (full width). */\n defaultExpanded?: boolean;\n /** Fires when the expanded state changes (e.g. a consumer toggle). */\n onExpandedChange?: (expanded: boolean) => void;\n /**\n * Replace the rendered `<nav>` with another element or component\n * (Base UI composition). Accepts a React element or a render function.\n */\n render?: useRender.RenderProp;\n}\n\nconst SidebarPrimary = React.forwardRef<HTMLElement, SidebarPrimaryProps>(\n (\n {\n className,\n expanded: expandedProp,\n defaultExpanded = true,\n onExpandedChange,\n 'aria-label': ariaLabel = 'Primary',\n render,\n children,\n ...props\n },\n ref\n ) => {\n const [expanded, setExpanded] = useControllableBoolean(\n expandedProp,\n defaultExpanded,\n onExpandedChange\n );\n\n // Collapse is driven by the consumer through the layout context — the\n // `SidebarPrimaryCollapseTrigger` (the Figma \"Collapse menu\" footer item)\n // calls `toggleExpanded`, which updates uncontrolled state and always emits\n // `onExpandedChange`. Controlled consumers ignore the internal state and\n // react to the callback.\n const context = React.useMemo<SidebarPrimaryContextValue>(\n () => ({ expanded, toggleExpanded: () => setExpanded(!expanded) }),\n [expanded, setExpanded]\n );\n\n const element = useRender({\n render,\n ref,\n defaultTagName: 'nav',\n props: mergeProps<'nav'>(\n {\n 'aria-label': ariaLabel,\n // `data-state` drives every collapsed/expanded token switch via\n // attribute selectors; typed loosely because React's nav attribute\n // map doesn't include arbitrary data-* keys as literals.\n ...({ 'data-state': expanded ? 'expanded' : 'collapsed' } as Record<\n string,\n string\n >),\n className: cn(\n 'group/sidebar flex h-full flex-col bg-[var(--ui-sidebar-primary-global-container-color)] w-[var(--ui-sidebar-primary-collapsed-container-width)] data-[state=expanded]:w-[var(--ui-sidebar-primary-expanded-container-width)] transition-[width]',\n className\n ),\n children,\n },\n props\n ),\n });\n\n return (\n <SidebarPrimaryContext.Provider value={context}>\n {element}\n </SidebarPrimaryContext.Provider>\n );\n }\n);\nSidebarPrimary.displayName = 'SidebarPrimary';\n\nconst SidebarPrimaryHeader = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, ...props }, ref) => (\n // Hosts a consumer-provided logo (R7 — no Logo part is built). Padding and the\n // logo height switch on expanded/collapsed; `[&_*]:h-…` sizes whatever the\n // consumer slots in. The logo color token tints any `currentColor` mark.\n <div\n ref={ref}\n className={cn(\n 'flex items-center shrink-0 text-[var(--ui-sidebar-primary-global-logo-color)]',\n 'px-[var(--ui-sidebar-primary-collapsed-container-header-padding-x)] py-[var(--ui-sidebar-primary-collapsed-container-header-padding-y)]',\n '[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-collapsed-logo-height)] [&_:where(img,svg)]:w-auto',\n 'group-data-[state=expanded]/sidebar:px-[var(--ui-sidebar-primary-expanded-container-header-padding-x)] group-data-[state=expanded]/sidebar:py-[var(--ui-sidebar-primary-expanded-container-header-padding-y)]',\n 'group-data-[state=expanded]/sidebar:[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-expanded-logo-height)]',\n className\n )}\n {...props}\n />\n));\nSidebarPrimaryHeader.displayName = 'SidebarPrimaryHeader';\n\nconst SidebarPrimaryContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, children, ...props }, ref) => (\n // The section list scrolls inside a ScrollArea: its overlay scrollbar floats\n // over the content and reserves no gutter, so the full-bleed selected row is\n // never cropped — on every OS, unlike a native `overflow` scrollbar.\n <ScrollArea ref={ref} className={cn('min-h-0 flex-1', className)} {...props}>\n <div className=\"flex flex-col gap-[var(--ui-sidebar-primary-global-section-list-gap)]\">\n {children}\n </div>\n </ScrollArea>\n));\nSidebarPrimaryContent.displayName = 'SidebarPrimaryContent';\n\nconst SidebarPrimaryFooter = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col shrink-0 gap-[var(--ui-sidebar-primary-global-footer-list-gap)]',\n 'border-t border-[var(--ui-sidebar-primary-global-container-footer-border-color)] [border-top-width:var(--ui-sidebar-primary-global-container-footer-border-width)]',\n 'py-[var(--ui-sidebar-primary-section-container-padding-y)]',\n className\n )}\n {...props}\n />\n));\nSidebarPrimaryFooter.displayName = 'SidebarPrimaryFooter';\n\nconst SidebarPrimarySection = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, ...props }, ref) => (\n // `firstSection` in Figma only toggles the top divider — derive it from DOM\n // position (`:not(:first-child)`) instead of a prop.\n <div\n ref={ref}\n className={cn(\n 'flex flex-col py-[var(--ui-sidebar-primary-section-container-padding-y)]',\n '[&:not(:first-child)]:border-t [&:not(:first-child)]:border-[var(--ui-sidebar-primary-section-container-border-color)] [&:not(:first-child)]:[border-top-width:var(--ui-sidebar-primary-section-container-border-width)]',\n className\n )}\n {...props}\n />\n));\nSidebarPrimarySection.displayName = 'SidebarPrimarySection';\n\nconst SidebarPrimaryMenu = React.forwardRef<\n HTMLUListElement,\n React.ComponentPropsWithoutRef<'ul'>\n>(({ className, ...props }, ref) => (\n <ul\n ref={ref}\n className={cn(\n 'flex flex-col gap-[var(--ui-sidebar-primary-section-menu-item-list-gap)]',\n className\n )}\n {...props}\n />\n));\nSidebarPrimaryMenu.displayName = 'SidebarPrimaryMenu';\n\n// Primary recolors the container, the icon AND the label per variant\n// (selected|unselected) × interaction state (idle/hover/active). Every state is\n// wired to its own token even where acronis's value is unchanged, because these\n// are runtime `var()` references — a brand override is only honored if the\n// matching state token is referenced. (This is why Primary cannot share a cva\n// with Secondary, which recolors only the container — DESIGN §6.2.)\nconst sidebarPrimaryMenuItemVariants = cva(\n 'group/menu-item flex w-full items-center gap-[var(--ui-sidebar-primary-menu-item-global-container-gap)] h-[var(--ui-sidebar-primary-menu-item-global-container-height)] px-[var(--ui-sidebar-primary-menu-item-global-container-padding-x)] py-[var(--ui-sidebar-primary-menu-item-global-container-padding-y)] no-underline ui-sidebar-primary-menu-item-global-label-text-style transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-focus-brand)] focus-visible:ring-inset [&_svg]:shrink-0 [&_svg]:size-[var(--ui-sidebar-primary-menu-item-global-icon-size)]',\n {\n variants: {\n variant: {\n unselected:\n 'bg-[var(--ui-sidebar-primary-menu-item-unselected-container-color-idle)] text-[var(--ui-sidebar-primary-menu-item-unselected-label-color-idle)] [&_svg]:text-[var(--ui-sidebar-primary-menu-item-unselected-icon-color-idle)] hover:bg-[var(--ui-sidebar-primary-menu-item-unselected-container-color-hover)] hover:text-[var(--ui-sidebar-primary-menu-item-unselected-label-color-hover)] hover:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-unselected-icon-color-hover)] active:bg-[var(--ui-sidebar-primary-menu-item-unselected-container-color-active)] active:text-[var(--ui-sidebar-primary-menu-item-unselected-label-color-active)] active:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-unselected-icon-color-active)]',\n selected:\n 'bg-[var(--ui-sidebar-primary-menu-item-selected-container-color-idle)] text-[var(--ui-sidebar-primary-menu-item-selected-label-color-idle)] [&_svg]:text-[var(--ui-sidebar-primary-menu-item-selected-icon-color-idle)] hover:bg-[var(--ui-sidebar-primary-menu-item-selected-container-color-hover)] hover:text-[var(--ui-sidebar-primary-menu-item-selected-label-color-hover)] hover:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-selected-icon-color-hover)] active:bg-[var(--ui-sidebar-primary-menu-item-selected-container-color-active)] active:text-[var(--ui-sidebar-primary-menu-item-selected-label-color-active)] active:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-selected-icon-color-active)]',\n },\n },\n defaultVariants: {\n variant: 'unselected',\n },\n }\n);\n\nexport interface SidebarPrimaryMenuItemProps\n extends Omit<React.ComponentPropsWithoutRef<'a'>, 'children'>,\n Omit<VariantProps<typeof sidebarPrimaryMenuItemVariants>, 'variant'> {\n /** Marks the current route: sets the `selected` variant + `aria-current=\"page\"`. */\n selected?: boolean;\n /** Leading 16px icon (from `@acronis-platform/icons-react`). */\n icon?: React.ReactNode;\n children?: React.ReactNode;\n /**\n * Replace the rendered `<a>` with another element or component (e.g. a router\n * `Link` or a `<button>`) via Base UI composition.\n */\n render?: useRender.RenderProp;\n}\n\nconst SidebarPrimaryMenuItem = React.forwardRef<\n HTMLAnchorElement,\n SidebarPrimaryMenuItemProps\n>(({ className, selected = false, icon, render, children, ...props }, ref) => {\n const { expanded } = useSidebarPrimaryContext();\n\n // Trailing extras (tag / shortcut / external link) are passed as children but\n // belong at the right edge of the row — split them out so the title takes the\n // remaining width and truncates with an ellipsis, while the extras stay\n // `shrink-0` on the right (the row's `gap` is their left margin).\n const items = React.Children.toArray(children);\n const extras = items.filter(\n (child): child is React.ReactElement =>\n React.isValidElement(child) &&\n (child.type as { displayName?: string }).displayName ===\n 'SidebarPrimaryMenuItemExtras'\n );\n const label = items.filter(\n (child) => !extras.includes(child as React.ReactElement)\n );\n\n const inner = useRender({\n render,\n ref,\n defaultTagName: 'a',\n props: mergeProps<'a'>(\n {\n className: cn(\n sidebarPrimaryMenuItemVariants({\n variant: selected ? 'selected' : 'unselected',\n }),\n className\n ),\n 'aria-current': selected ? 'page' : undefined,\n children: (\n <>\n {icon != null && (\n <span className=\"flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)]\">\n {icon}\n </span>\n )}\n {/* Keep the label in the DOM in collapsed/rail mode as `sr-only` so\n the icon-only row keeps an accessible name (a11y §7) — never\n `display:none` the text. Extras are visually dropped when\n collapsed but stay queryable for the same reason. */}\n <span\n className={cn(\n 'min-w-0 flex-1 truncate text-left',\n !expanded && 'sr-only'\n )}\n >\n {label}\n </span>\n {extras.length > 0 && (\n <span className=\"flex shrink-0 items-center\">{extras}</span>\n )}\n </>\n ),\n },\n props\n ),\n });\n\n return <li className=\"contents\">{inner}</li>;\n});\nSidebarPrimaryMenuItem.displayName = 'SidebarPrimaryMenuItem';\n\nexport interface SidebarPrimaryMenuItemExtrasProps\n extends React.ComponentPropsWithoutRef<'span'> {\n /** Which trailing affordance to render. */\n variant: 'tag' | 'externalLink' | 'shortcut' | 'tag-externalLink';\n /** Shortcut text (e.g. \"⌘H\") for the `shortcut` variant. */\n shortcut?: string;\n /** Tag content for the `tag` / `tag-externalLink` variants. */\n tag?: React.ReactNode;\n}\n\nconst SidebarPrimaryMenuItemExtras = React.forwardRef<\n HTMLSpanElement,\n SidebarPrimaryMenuItemExtrasProps\n>(({ className, variant, shortcut, tag, children, ...props }, ref) => {\n const { expanded } = useSidebarPrimaryContext();\n const showTag = variant === 'tag' || variant === 'tag-externalLink';\n const showExternal =\n variant === 'externalLink' || variant === 'tag-externalLink';\n const showShortcut = variant === 'shortcut';\n\n return (\n <span\n ref={ref}\n // The extras cluster is rail-mode noise — drop it when collapsed.\n className={cn(\n 'inline-flex items-center gap-[var(--ui-sidebar-primary-menu-item-extras-global-container-gap)]',\n !expanded && 'hidden',\n className\n )}\n {...props}\n >\n {showTag && (tag ?? children)}\n {showShortcut && (\n <span className=\"ui-sidebar-primary-menu-item-extras-global-shortcut-text-style text-[var(--ui-sidebar-primary-menu-item-extras-global-shortcut-color)]\">\n {shortcut ?? children}\n </span>\n )}\n {showExternal && (\n <SquareArrowUpRightIcon\n size={16}\n className=\"text-[var(--ui-sidebar-primary-menu-item-extras-global-external-icon-color)] size-[var(--ui-sidebar-primary-menu-item-extras-global-external-icon-size)]\"\n />\n )}\n </span>\n );\n});\nSidebarPrimaryMenuItemExtras.displayName = 'SidebarPrimaryMenuItemExtras';\n\nexport interface SidebarPrimaryCollapseTriggerProps\n extends Omit<React.ComponentPropsWithoutRef<'button'>, 'children'> {\n /** Leading 16px icon (e.g. a panel-left glyph). */\n icon?: React.ReactNode;\n children?: React.ReactNode;\n}\n\n// The footer \"Collapse menu\" affordance (Figma). A menu-item-styled `<button>`\n// that flips the rail width via the layout context — this is the live wiring\n// for the controllable `expanded` state (B1). In collapsed mode it keeps its\n// label as `sr-only` like every other row.\nconst SidebarPrimaryCollapseTrigger = React.forwardRef<\n HTMLButtonElement,\n SidebarPrimaryCollapseTriggerProps\n>(({ className, icon, children, onClick, ...props }, ref) => {\n const { expanded, toggleExpanded } = useSidebarPrimaryContext();\n\n return (\n <li className=\"contents\">\n <button\n ref={ref}\n type=\"button\"\n aria-expanded={expanded}\n className={cn(\n sidebarPrimaryMenuItemVariants({ variant: 'unselected' }),\n 'text-left',\n className\n )}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) toggleExpanded();\n }}\n {...props}\n >\n {icon != null && (\n <span className=\"flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)]\">\n {icon}\n </span>\n )}\n <span className={cn('flex-1 truncate', !expanded && 'sr-only')}>\n {children}\n </span>\n </button>\n </li>\n );\n});\nSidebarPrimaryCollapseTrigger.displayName = 'SidebarPrimaryCollapseTrigger';\n\nexport {\n SidebarPrimary,\n SidebarPrimaryHeader,\n SidebarPrimaryContent,\n SidebarPrimaryFooter,\n SidebarPrimarySection,\n SidebarPrimaryMenu,\n SidebarPrimaryMenuItem,\n SidebarPrimaryMenuItemExtras,\n SidebarPrimaryCollapseTrigger,\n sidebarPrimaryMenuItemVariants,\n};\n"],"names":["SidebarPrimaryContext","React","useSidebarPrimaryContext","useControllableBoolean","controlled","defaultValue","onChange","uncontrolled","setUncontrolled","isControlled","value","setValue","next","SidebarPrimary","className","expandedProp","defaultExpanded","onExpandedChange","ariaLabel","render","children","props","ref","expanded","setExpanded","context","element","useRender","mergeProps","cn","SidebarPrimaryHeader","jsx","SidebarPrimaryContent","ScrollArea","SidebarPrimaryFooter","SidebarPrimarySection","SidebarPrimaryMenu","sidebarPrimaryMenuItemVariants","cva","SidebarPrimaryMenuItem","selected","icon","items","extras","child","label","inner","jsxs","Fragment","SidebarPrimaryMenuItemExtras","variant","shortcut","tag","showTag","showExternal","showShortcut","SquareArrowUpRightIcon","SidebarPrimaryCollapseTrigger","onClick","toggleExpanded","event"],"mappings":"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"}
1
+ {"version":3,"file":"sidebar-primary.js","sources":["../../../../src/components/ui/sidebar-primary/sidebar-primary.tsx"],"sourcesContent":["import * as React from 'react';\nimport { mergeProps } from '@base-ui/react/merge-props';\nimport { useRender } from '@base-ui/react/use-render';\nimport { SquareArrowUpRightIcon } from '@acronis-platform/icons-react/stroke-mono';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nimport { ScrollArea } from '../scroll-area';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../tooltip';\n\n// Composable SidebarPrimary primitives mirroring the Figma \"SidebarPrimary\"\n// component set (node 2092:4359, variant expanded|collapsed). Every color and\n// metric is wired to a next-gen `--ui-sidebar-primary-*` token from\n// @acronis-platform/tokens-pd — no hex, no invented tokens.\n//\n// expanded/collapsed is a width-reflow state, not a panel show/hide, so it is\n// modelled as a controlled/uncontrolled `expanded` prop (default true) that sets\n// `data-state=\"expanded|collapsed\"` on the root. Every metric token has a\n// distinct `collapsed-*` / `expanded-*` name, switched via `data-[state=…]`\n// attribute selectors — Base UI Collapsible would fight this (it hides a panel;\n// the rail never hides). Layout state is shared to descendants through a small\n// context so menu items know whether to show or `sr-only` their label/extras.\n//\n// R2 (menu-item border-radius): the token tier ships no radius token. Verified\n// against the Figma node — the menu-item COMPONENT and its container frame both\n// report cornerRadius=None (the only radius in the node is the COMPONENT_SET's\n// own variant-container chrome). Rows are therefore SQUARE; no `rounded-*` is\n// applied. The focus ring uses the shared `--ui-focus-brand` (no sidebar focus\n// token exists — R1), matching Button/Breadcrumb.\n\ninterface SidebarPrimaryContextValue {\n expanded: boolean;\n /** Flip the rail width — drives the controlled/uncontrolled `expanded` state. */\n toggleExpanded: () => void;\n}\n\nconst SidebarPrimaryContext =\n React.createContext<SidebarPrimaryContextValue | null>(null);\n\nfunction useSidebarPrimaryContext(): SidebarPrimaryContextValue {\n // Default to expanded so parts render standalone (e.g. in isolation tests /\n // stories) without a wrapping root; the toggle is a no-op outside a root.\n return (\n React.useContext(SidebarPrimaryContext) ?? {\n expanded: true,\n toggleExpanded: () => {},\n }\n );\n}\n\n/**\n * Controlled + uncontrolled boolean state (the Base UI idiom). When `controlled`\n * is provided it wins and the setter only emits the change callback; otherwise\n * the setter updates internal state. `onChange` is ALWAYS invoked with the next\n * value so a consumer can react in either mode.\n */\nfunction useControllableBoolean(\n controlled: boolean | undefined,\n defaultValue: boolean,\n onChange?: (next: boolean) => void\n): [boolean, (next: boolean) => void] {\n const [uncontrolled, setUncontrolled] = React.useState(defaultValue);\n const isControlled = controlled !== undefined;\n const value = isControlled ? controlled : uncontrolled;\n const setValue = React.useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolled(next);\n onChange?.(next);\n },\n [isControlled, onChange]\n );\n return [value, setValue];\n}\n\n/**\n * Tracks whether `ref`'s element is clipping its own content (`scrollWidth >\n * clientWidth`) — used to gate a tooltip so it only opens when a truncated\n * label is actually cut off. Re-measures via `ResizeObserver` (covers the\n * rail's expand/collapse width transition); `enabled` skips measurement\n * entirely (e.g. while collapsed, where the label is `sr-only`).\n */\nfunction useIsOverflowing<T extends Element>(\n ref: React.RefObject<T | null>,\n { enabled }: { enabled: boolean }\n): boolean {\n const [isOverflowing, setIsOverflowing] = React.useState(false);\n\n React.useEffect(() => {\n const element = ref.current;\n if (!enabled || !element) {\n setIsOverflowing(false);\n return;\n }\n const measure = () =>\n setIsOverflowing(element.scrollWidth > element.clientWidth);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n return () => observer.disconnect();\n }, [ref, enabled]);\n\n return isOverflowing;\n}\n\nexport interface SidebarPrimaryProps\n extends React.ComponentPropsWithoutRef<'nav'> {\n /** Controlled expanded (rail width) state. */\n expanded?: boolean;\n /** Uncontrolled initial expanded state. Defaults to `true` (full width). */\n defaultExpanded?: boolean;\n /** Fires when the expanded state changes (e.g. a consumer toggle). */\n onExpandedChange?: (expanded: boolean) => void;\n /**\n * Replace the rendered `<nav>` with another element or component\n * (Base UI composition). Accepts a React element or a render function.\n */\n render?: useRender.RenderProp;\n}\n\nconst SidebarPrimary = React.forwardRef<HTMLElement, SidebarPrimaryProps>(\n (\n {\n className,\n expanded: expandedProp,\n defaultExpanded = true,\n onExpandedChange,\n 'aria-label': ariaLabel = 'Primary',\n render,\n children,\n ...props\n },\n ref\n ) => {\n const [expanded, setExpanded] = useControllableBoolean(\n expandedProp,\n defaultExpanded,\n onExpandedChange\n );\n\n // Collapse is driven by the consumer through the layout context — the\n // `SidebarPrimaryCollapseTrigger` (the Figma \"Collapse menu\" footer item)\n // calls `toggleExpanded`, which updates uncontrolled state and always emits\n // `onExpandedChange`. Controlled consumers ignore the internal state and\n // react to the callback.\n const context = React.useMemo<SidebarPrimaryContextValue>(\n () => ({ expanded, toggleExpanded: () => setExpanded(!expanded) }),\n [expanded, setExpanded]\n );\n\n const element = useRender({\n render,\n ref,\n defaultTagName: 'nav',\n props: mergeProps<'nav'>(\n {\n 'aria-label': ariaLabel,\n // `data-state` drives every collapsed/expanded token switch via\n // attribute selectors; typed loosely because React's nav attribute\n // map doesn't include arbitrary data-* keys as literals.\n ...({ 'data-state': expanded ? 'expanded' : 'collapsed' } as Record<\n string,\n string\n >),\n className: cn(\n 'group/sidebar flex h-full flex-col bg-[var(--ui-sidebar-primary-global-container-color)] w-[var(--ui-sidebar-primary-collapsed-container-width)] data-[state=expanded]:w-[var(--ui-sidebar-primary-expanded-container-width)] transition-[width]',\n className\n ),\n children,\n },\n props\n ),\n });\n\n return (\n <SidebarPrimaryContext.Provider value={context}>\n {element}\n </SidebarPrimaryContext.Provider>\n );\n }\n);\nSidebarPrimary.displayName = 'SidebarPrimary';\n\nexport interface SidebarPrimaryHeaderProps\n extends React.ComponentPropsWithoutRef<'div'> {\n /**\n * Logo content shown while the rail is expanded (e.g. a full lockup).\n * Pairs with `collapsedLogo` to swap distinct graphics per rail state\n * instead of resizing one. When neither `logo` nor `collapsedLogo` is\n * given, `children` renders in both states (the original single-slot\n * behavior).\n */\n logo?: React.ReactNode;\n /**\n * Logo content shown while the rail is collapsed (e.g. a monogram mark).\n * Falls back to `logo` when omitted.\n */\n collapsedLogo?: React.ReactNode;\n}\n\nconst SidebarPrimaryHeader = React.forwardRef<\n HTMLDivElement,\n SidebarPrimaryHeaderProps\n>(({ className, logo, collapsedLogo, children, ...props }, ref) => {\n // Hosts a consumer-provided logo (R7 — no Logo part is built). Padding and the\n // logo height switch on expanded/collapsed; `[&_*]:h-…` sizes whatever the\n // consumer slots in. The logo color token tints any `currentColor` mark.\n const { expanded } = useSidebarPrimaryContext();\n const hasTwinLogos = logo != null || collapsedLogo != null;\n const content = hasTwinLogos\n ? expanded\n ? (logo ?? collapsedLogo)\n : (collapsedLogo ?? logo)\n : children;\n\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center shrink-0 text-[var(--ui-sidebar-primary-global-logo-color)]',\n 'px-[var(--ui-sidebar-primary-collapsed-container-header-padding-x)] py-[var(--ui-sidebar-primary-collapsed-container-header-padding-y)]',\n '[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-collapsed-logo-height)] [&_:where(img,svg)]:w-auto',\n 'group-data-[state=expanded]/sidebar:px-[var(--ui-sidebar-primary-expanded-container-header-padding-x)] group-data-[state=expanded]/sidebar:py-[var(--ui-sidebar-primary-expanded-container-header-padding-y)]',\n 'group-data-[state=expanded]/sidebar:[&_:where(img,svg)]:h-[var(--ui-sidebar-primary-expanded-logo-height)]',\n className\n )}\n {...props}\n >\n {content}\n </div>\n );\n});\nSidebarPrimaryHeader.displayName = 'SidebarPrimaryHeader';\n\nconst SidebarPrimaryContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, children, ...props }, ref) => (\n // The section list scrolls inside a ScrollArea: its overlay scrollbar floats\n // over the content and reserves no gutter, so the full-bleed selected row is\n // never cropped — on every OS, unlike a native `overflow` scrollbar.\n //\n // Base UI's Scroll Area Content sets `min-width: fit-content` inline (it\n // needs the content's true intrinsic width to detect horizontal overflow),\n // which forces every row wider than the rail — overriding `min-w-0` +\n // `truncate` on a long label, since intrinsic-width calculations ignore\n // `text-overflow`. We only ever scroll vertically here, so cancel it: the\n // `!` (important) is required to beat the inline style's specificity.\n <ScrollArea\n ref={ref}\n className={cn(\n 'min-h-0 flex-1 [&_[data-slot=scroll-area-content]]:min-w-0!',\n className\n )}\n {...props}\n >\n <div className=\"flex flex-col gap-[var(--ui-sidebar-primary-global-section-list-gap)]\">\n {children}\n </div>\n </ScrollArea>\n));\nSidebarPrimaryContent.displayName = 'SidebarPrimaryContent';\n\nconst SidebarPrimaryFooter = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'flex flex-col shrink-0 gap-[var(--ui-sidebar-primary-global-footer-list-gap)]',\n 'border-t border-[var(--ui-sidebar-primary-global-container-footer-border-color)] [border-top-width:var(--ui-sidebar-primary-global-container-footer-border-width)]',\n className\n )}\n {...props}\n />\n));\nSidebarPrimaryFooter.displayName = 'SidebarPrimaryFooter';\n\nconst SidebarPrimarySection = React.forwardRef<\n HTMLDivElement,\n React.ComponentPropsWithoutRef<'div'>\n>(({ className, ...props }, ref) => (\n // position (`:not(:first-child)`) instead of a prop.\n <div\n ref={ref}\n className={cn(\n 'flex flex-col pb-[var(--ui-sidebar-primary-section-container-padding-y)]',\n '[&:not(:first-child)]:border-t [&:not(:first-child)]:border-[var(--ui-sidebar-primary-section-container-border-color)] [&:not(:first-child)]:[border-top-width:var(--ui-sidebar-primary-section-container-border-width)] [&:not(:first-child)]:pt-[var(--ui-sidebar-primary-section-container-padding-y)]',\n className\n )}\n {...props}\n />\n));\nSidebarPrimarySection.displayName = 'SidebarPrimarySection';\n\nconst SidebarPrimaryMenu = React.forwardRef<\n HTMLUListElement,\n React.ComponentPropsWithoutRef<'ul'>\n>(({ className, ...props }, ref) => (\n <ul\n ref={ref}\n className={cn(\n 'flex flex-col gap-[var(--ui-sidebar-primary-section-menu-item-list-gap)]',\n className\n )}\n {...props}\n />\n));\nSidebarPrimaryMenu.displayName = 'SidebarPrimaryMenu';\n\n// Primary recolors the container, the icon AND the label per variant\n// (selected|unselected) × interaction state (idle/hover/active). Every state is\n// wired to its own token even where acronis's value is unchanged, because these\n// are runtime `var()` references — a brand override is only honored if the\n// matching state token is referenced. (This is why Primary cannot share a cva\n// with Secondary, which recolors only the container — DESIGN §6.2.)\nconst sidebarPrimaryMenuItemVariants = cva(\n 'group/menu-item flex w-full items-center gap-[var(--ui-sidebar-primary-menu-item-global-container-gap)] h-[var(--ui-sidebar-primary-menu-item-global-container-height)] px-[var(--ui-sidebar-primary-menu-item-global-container-padding-x)] py-[var(--ui-sidebar-primary-menu-item-global-container-padding-y)] no-underline ui-sidebar-primary-menu-item-global-label-text-style transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-focus-brand)] focus-visible:ring-inset [&_svg]:shrink-0 [&_svg]:size-[var(--ui-sidebar-primary-menu-item-global-icon-size)]',\n {\n variants: {\n variant: {\n unselected:\n 'bg-[var(--ui-sidebar-primary-menu-item-unselected-container-color-idle)] text-[var(--ui-sidebar-primary-menu-item-unselected-label-color-idle)] [&_svg]:text-[var(--ui-sidebar-primary-menu-item-unselected-icon-color-idle)] hover:bg-[var(--ui-sidebar-primary-menu-item-unselected-container-color-hover)] hover:text-[var(--ui-sidebar-primary-menu-item-unselected-label-color-hover)] hover:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-unselected-icon-color-hover)] active:bg-[var(--ui-sidebar-primary-menu-item-unselected-container-color-active)] active:text-[var(--ui-sidebar-primary-menu-item-unselected-label-color-active)] active:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-unselected-icon-color-active)]',\n selected:\n 'bg-[var(--ui-sidebar-primary-menu-item-selected-container-color-idle)] text-[var(--ui-sidebar-primary-menu-item-selected-label-color-idle)] [&_svg]:text-[var(--ui-sidebar-primary-menu-item-selected-icon-color-idle)] hover:bg-[var(--ui-sidebar-primary-menu-item-selected-container-color-hover)] hover:text-[var(--ui-sidebar-primary-menu-item-selected-label-color-hover)] hover:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-selected-icon-color-hover)] active:bg-[var(--ui-sidebar-primary-menu-item-selected-container-color-active)] active:text-[var(--ui-sidebar-primary-menu-item-selected-label-color-active)] active:[&_svg]:text-[var(--ui-sidebar-primary-menu-item-selected-icon-color-active)]',\n },\n },\n defaultVariants: {\n variant: 'unselected',\n },\n }\n);\n\nexport interface SidebarPrimaryMenuItemProps\n extends Omit<React.ComponentPropsWithoutRef<'a'>, 'children'>,\n Omit<VariantProps<typeof sidebarPrimaryMenuItemVariants>, 'variant'> {\n /** Marks the current route: sets the `selected` variant + `aria-current=\"page\"`. */\n selected?: boolean;\n /** Leading 16px icon (from `@acronis-platform/icons-react`). */\n icon?: React.ReactNode;\n children?: React.ReactNode;\n /**\n * Trailing affordance — a `SidebarPrimaryMenuItemExtras` element. Rendered as\n * a flex sibling of the label (its own `gap` from `_global/container/gap`),\n * not nested inside the label's truncating span — nesting it there collapses\n * the row gap and lets `truncate` clip the affordance. Hidden in collapsed/rail\n * mode regardless of node type — the parent wraps it, so this holds even for\n * a raw node rather than `SidebarPrimaryMenuItemExtras`.\n */\n extras?: React.ReactNode;\n /**\n * Replace the rendered `<a>` with another element or component (e.g. a router\n * `Link` or a `<button>`) via Base UI composition.\n */\n render?: useRender.RenderProp;\n}\n\nconst SidebarPrimaryMenuItem = React.forwardRef<\n HTMLAnchorElement,\n SidebarPrimaryMenuItemProps\n>(\n (\n { className, selected = false, icon, render, children, extras, ...props },\n ref\n ) => {\n const { expanded } = useSidebarPrimaryContext();\n const labelRef = React.useRef<HTMLSpanElement>(null);\n const isOverflowing = useIsOverflowing(labelRef, { enabled: expanded });\n\n const inner = useRender({\n render,\n ref,\n defaultTagName: 'a',\n props: mergeProps<'a'>(\n {\n className: cn(\n sidebarPrimaryMenuItemVariants({\n variant: selected ? 'selected' : 'unselected',\n }),\n className\n ),\n 'aria-current': selected ? 'page' : undefined,\n children: (\n <>\n {icon != null && (\n <span className=\"flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)]\">\n {icon}\n </span>\n )}\n {/* Keep the label in the DOM in collapsed/rail mode as `sr-only` so\n the icon-only row keeps an accessible name (a11y §7) — never\n `display:none` the text. Extras are visually dropped when\n collapsed but stay queryable for the same reason. The tooltip\n trigger is the label span itself, not the row — it must not\n open when hovering the icon or extras, and only ever opens\n when the label is actually clipped. */}\n <Tooltip disabled={!isOverflowing}>\n <TooltipTrigger\n render={\n <span\n ref={labelRef}\n className={cn(\n 'min-w-0 flex-1 truncate text-start',\n !expanded && 'sr-only'\n )}\n />\n }\n >\n {children}\n </TooltipTrigger>\n <TooltipContent>{children}</TooltipContent>\n </Tooltip>\n {extras != null && (\n <span className={cn(!expanded && 'hidden')}>{extras}</span>\n )}\n </>\n ),\n },\n props\n ),\n });\n\n return <li className=\"contents\">{inner}</li>;\n }\n);\nSidebarPrimaryMenuItem.displayName = 'SidebarPrimaryMenuItem';\n\nexport interface SidebarPrimaryMenuItemExtrasProps\n extends React.ComponentPropsWithoutRef<'span'> {\n /** Which trailing affordance to render. */\n variant: 'tag' | 'externalLink' | 'shortcut' | 'tag-externalLink';\n /** Shortcut text (e.g. \"⌘H\") for the `shortcut` variant. */\n shortcut?: string;\n /**\n * Tag content for the `tag` / `tag-externalLink` variants. Figma constrains\n * this slot's `Tag` instance to `size=\"sm\"` (no other size is offered on\n * MenuItemExtras) — always pass a `<Tag variant=\"info\" size=\"sm\">`, never the\n * default size.\n */\n tag?: React.ReactNode;\n}\n\nconst SidebarPrimaryMenuItemExtras = React.forwardRef<\n HTMLSpanElement,\n SidebarPrimaryMenuItemExtrasProps\n>(({ className, variant, shortcut, tag, children, ...props }, ref) => {\n const { expanded } = useSidebarPrimaryContext();\n const showTag = variant === 'tag' || variant === 'tag-externalLink';\n const showExternal =\n variant === 'externalLink' || variant === 'tag-externalLink';\n const showShortcut = variant === 'shortcut';\n\n return (\n <span\n ref={ref}\n // The extras cluster is rail-mode noise — drop it when collapsed.\n className={cn(\n 'inline-flex items-center gap-[var(--ui-sidebar-primary-menu-item-extras-global-container-gap)]',\n !expanded && 'hidden',\n className\n )}\n {...props}\n >\n {showTag && (tag ?? children)}\n {showShortcut && (\n <span className=\"ui-sidebar-primary-menu-item-extras-global-shortcut-text-style text-[var(--ui-sidebar-primary-menu-item-extras-global-shortcut-color)]\">\n {shortcut ?? children}\n </span>\n )}\n {showExternal && (\n <SquareArrowUpRightIcon\n size={16}\n className=\"text-[var(--ui-sidebar-primary-menu-item-extras-global-external-icon-color)] size-[var(--ui-sidebar-primary-menu-item-extras-global-external-icon-size)]\"\n />\n )}\n </span>\n );\n});\nSidebarPrimaryMenuItemExtras.displayName = 'SidebarPrimaryMenuItemExtras';\n\nexport interface SidebarPrimaryCollapseTriggerProps\n extends Omit<React.ComponentPropsWithoutRef<'button'>, 'children'> {\n /** Leading 16px icon (e.g. a panel-left glyph). */\n icon?: React.ReactNode;\n children?: React.ReactNode;\n /**\n * Trailing affordance — a `SidebarPrimaryMenuItemExtras` element (Figma\n * shows a `⌘H` shortcut here). Rendered as a flex sibling of the label, same\n * as `SidebarPrimaryMenuItem`'s `extras` prop.\n */\n extras?: React.ReactNode;\n}\n\n// The footer \"Collapse menu\" affordance (Figma). A menu-item-styled `<button>`\n// that flips the rail width via the layout context — this is the live wiring\n// for the controllable `expanded` state (B1). In collapsed mode it keeps its\n// label as `sr-only` like every other row.\nconst SidebarPrimaryCollapseTrigger = React.forwardRef<\n HTMLButtonElement,\n SidebarPrimaryCollapseTriggerProps\n>(({ className, icon, children, extras, onClick, ...props }, ref) => {\n const { expanded, toggleExpanded } = useSidebarPrimaryContext();\n const labelRef = React.useRef<HTMLSpanElement>(null);\n const isOverflowing = useIsOverflowing(labelRef, { enabled: expanded });\n\n return (\n <li className=\"contents\">\n <button\n ref={ref}\n type=\"button\"\n aria-expanded={expanded}\n className={cn(\n sidebarPrimaryMenuItemVariants({ variant: 'unselected' }),\n 'text-start',\n className\n )}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) toggleExpanded();\n }}\n {...props}\n >\n {icon != null && (\n <span\n className={cn(\n 'flex shrink-0 items-center self-start mt-[var(--ui-sidebar-primary-menu-item-global-icon-margin-t)] transition-transform',\n expanded ? 'rtl:rotate-180' : 'ltr:rotate-180'\n )}\n >\n {icon}\n </span>\n )}\n <Tooltip disabled={!isOverflowing}>\n <TooltipTrigger\n render={\n <span\n ref={labelRef}\n className={cn(\n 'min-w-0 flex-1 truncate',\n !expanded && 'sr-only'\n )}\n />\n }\n >\n {children}\n </TooltipTrigger>\n <TooltipContent>{children}</TooltipContent>\n </Tooltip>\n {extras != null && (\n <span className={cn(!expanded && 'hidden')}>{extras}</span>\n )}\n </button>\n </li>\n );\n});\nSidebarPrimaryCollapseTrigger.displayName = 'SidebarPrimaryCollapseTrigger';\n\nexport {\n SidebarPrimary,\n SidebarPrimaryHeader,\n SidebarPrimaryContent,\n SidebarPrimaryFooter,\n SidebarPrimarySection,\n SidebarPrimaryMenu,\n SidebarPrimaryMenuItem,\n SidebarPrimaryMenuItemExtras,\n SidebarPrimaryCollapseTrigger,\n useIsOverflowing,\n sidebarPrimaryMenuItemVariants,\n};\n"],"names":["SidebarPrimaryContext","React","useSidebarPrimaryContext","useControllableBoolean","controlled","defaultValue","onChange","uncontrolled","setUncontrolled","isControlled","value","setValue","next","useIsOverflowing","ref","enabled","isOverflowing","setIsOverflowing","element","measure","observer","SidebarPrimary","className","expandedProp","defaultExpanded","onExpandedChange","ariaLabel","render","children","props","expanded","setExpanded","context","useRender","mergeProps","cn","SidebarPrimaryHeader","logo","collapsedLogo","content","jsx","SidebarPrimaryContent","ScrollArea","SidebarPrimaryFooter","SidebarPrimarySection","SidebarPrimaryMenu","sidebarPrimaryMenuItemVariants","cva","SidebarPrimaryMenuItem","selected","icon","extras","labelRef","inner","jsxs","Fragment","Tooltip","TooltipTrigger","TooltipContent","SidebarPrimaryMenuItemExtras","variant","shortcut","tag","showTag","showExternal","showShortcut","SquareArrowUpRightIcon","SidebarPrimaryCollapseTrigger","onClick","toggleExpanded","event"],"mappings":"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"}