@espressif/dashboard-ui-components 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import { getStrictContext, Button, Avatar, AvatarImage, AvatarFallback, AvatarBadge, useControlledState, useIsMobile, Separator, Skeleton, useDataState, Collapsible, CollapsibleTrigger, CollapsibleContent } from './chunk-F5P6S7K2.js';
2
2
  import { cn, resolveColor, isPresetColor } from './chunk-VU4CZ76T.js';
3
- import { LoaderCircle, EyeOffIcon, EyeIcon, User, CheckIcon, CircleIcon, ChevronRightIcon, ArrowUpRightIcon, CopyIcon, XIcon, PanelLeftIcon, X, ChevronDown, ChevronRight } from 'lucide-react';
3
+ import { LoaderCircle, EyeOffIcon, EyeIcon, User, CheckIcon, CircleIcon, ChevronRightIcon, ArrowUpRightIcon, CopyIcon, XIcon, PanelLeftIcon, X, ChevronDown, CircleDot, Circle, ChevronRight } from 'lucide-react';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
- import * as React6 from 'react';
6
- import React6__default, { useState, useMemo, useRef, useEffect } from 'react';
5
+ import * as React from 'react';
6
+ import React__default, { useState, useMemo, useRef, useEffect } from 'react';
7
7
  import { Slot as Slot$2, DropdownMenu as DropdownMenu$1, Dialog } from 'radix-ui';
8
8
  import { motion, LayoutGroup, AnimatePresence, isMotionComponent, useInView } from 'motion/react';
9
9
  import * as motion5 from 'motion/react-client';
@@ -65,9 +65,9 @@ var DEFAULT_BOUNDS_OFFSET = {
65
65
  width: 0,
66
66
  height: 0
67
67
  };
68
- var HighlightContext = React6.createContext(void 0);
68
+ var HighlightContext = React.createContext(void 0);
69
69
  function useHighlight() {
70
- const context = React6.useContext(HighlightContext);
70
+ const context = React.useContext(HighlightContext);
71
71
  if (!context) {
72
72
  throw new Error("useHighlight must be used within a HighlightProvider");
73
73
  }
@@ -94,8 +94,8 @@ function Highlight({
94
94
  exitDelay = 200,
95
95
  mode = "children"
96
96
  } = props;
97
- const localRef = React6.useRef(null);
98
- React6.useImperativeHandle(ref, () => localRef.current);
97
+ const localRef = React.useRef(null);
98
+ React.useImperativeHandle(ref, () => localRef.current);
99
99
  const parentProps = props;
100
100
  const propsBoundsOffset = parentProps?.boundsOffset;
101
101
  const boundsOffset = propsBoundsOffset ?? DEFAULT_BOUNDS_OFFSET;
@@ -105,7 +105,7 @@ function Highlight({
105
105
  const boundsOffsetHeight = boundsOffset.height ?? 0;
106
106
  const variant = parentProps?.variant;
107
107
  const lineHeight = parentProps?.lineHeight ?? 2;
108
- const boundsOffsetRef = React6.useRef({
108
+ const boundsOffsetRef = React.useRef({
109
109
  top: boundsOffsetTop,
110
110
  left: boundsOffsetLeft,
111
111
  width: boundsOffsetWidth,
@@ -113,7 +113,7 @@ function Highlight({
113
113
  variant,
114
114
  lineHeight
115
115
  });
116
- React6.useEffect(() => {
116
+ React.useEffect(() => {
117
117
  boundsOffsetRef.current = {
118
118
  top: boundsOffsetTop,
119
119
  left: boundsOffsetLeft,
@@ -130,11 +130,13 @@ function Highlight({
130
130
  variant,
131
131
  lineHeight
132
132
  ]);
133
- const [activeValue, setActiveValue] = React6.useState(
133
+ const [activeValue, setActiveValue] = React.useState(
134
134
  value ?? defaultValue ?? null
135
135
  );
136
- const [boundsState, setBoundsState] = React6.useState(null);
137
- const [activeClassNameState, setActiveClassNameState] = React6.useState("");
136
+ const [boundsState, setBoundsState] = React.useState(
137
+ null
138
+ );
139
+ const [activeClassNameState, setActiveClassNameState] = React.useState("");
138
140
  const safeSetActiveValue = (id2) => {
139
141
  setActiveValue((prev) => {
140
142
  if (prev !== id2) {
@@ -144,9 +146,9 @@ function Highlight({
144
146
  return prev;
145
147
  });
146
148
  };
147
- const safeSetBoundsRef = React6.useRef(void 0);
148
- React6.useEffect(() => {
149
- safeSetBoundsRef.current = (bounds) => {
149
+ const safeSetBoundsRef = React.useRef(void 0);
150
+ React.useEffect(() => {
151
+ safeSetBoundsRef.current = (bounds, opts) => {
150
152
  if (!localRef.current) return;
151
153
  const containerRect = localRef.current.getBoundingClientRect();
152
154
  const offset = boundsOffsetRef.current;
@@ -168,47 +170,62 @@ function Highlight({
168
170
  if (prev && prev.top === newBounds.top && prev.left === newBounds.left && prev.width === newBounds.width && prev.height === newBounds.height) {
169
171
  return prev;
170
172
  }
171
- return newBounds;
173
+ return {
174
+ ...newBounds,
175
+ instant: prev ? opts?.instant ?? false : false
176
+ };
172
177
  });
173
178
  };
174
179
  });
175
- const safeSetBounds = (bounds) => {
176
- safeSetBoundsRef.current?.(bounds);
180
+ const safeSetBounds = (bounds, opts) => {
181
+ safeSetBoundsRef.current?.(bounds, opts);
177
182
  };
178
- const clearBounds = React6.useCallback(() => {
183
+ const clearBounds = React.useCallback(() => {
179
184
  setBoundsState((prev) => prev === null ? prev : null);
180
185
  }, []);
181
- React6.useEffect(() => {
186
+ React.useEffect(() => {
182
187
  if (value !== void 0) setActiveValue(value);
183
188
  else if (defaultValue !== void 0) setActiveValue(defaultValue);
184
189
  }, [value, defaultValue]);
185
- const id = React6.useId();
186
- React6.useEffect(() => {
187
- if (mode !== "parent") return;
190
+ const id = React.useId();
191
+ const getActiveElement = React.useCallback(() => {
188
192
  const container = localRef.current;
189
- if (!container) return;
190
- const onScroll = () => {
191
- if (!activeValue) return;
192
- const activeEl = container.querySelector(
193
- `[data-value="${activeValue}"][data-highlight="true"]`
194
- );
193
+ if (mode !== "parent" || !activeValue || !container) return null;
194
+ return container.querySelector(
195
+ `[data-value="${activeValue}"][data-highlight="true"]`
196
+ );
197
+ }, [mode, activeValue]);
198
+ const measureActiveRef = React.useRef(void 0);
199
+ React.useEffect(() => {
200
+ measureActiveRef.current = (opts) => {
201
+ const activeEl = getActiveElement();
195
202
  if (activeEl)
196
- safeSetBoundsRef.current?.(activeEl.getBoundingClientRect());
203
+ safeSetBoundsRef.current?.(activeEl.getBoundingClientRect(), opts);
197
204
  };
205
+ });
206
+ React.useEffect(() => {
207
+ if (mode !== "parent") return;
208
+ const container = localRef.current;
209
+ if (!container) return;
210
+ const onScroll = () => measureActiveRef.current?.();
198
211
  container.addEventListener("scroll", onScroll, { passive: true });
199
212
  return () => container.removeEventListener("scroll", onScroll);
200
- }, [mode, activeValue]);
201
- React6.useLayoutEffect(() => {
202
- if (mode !== "parent" || !activeValue) return;
213
+ }, [mode]);
214
+ React.useEffect(() => {
215
+ if (mode !== "parent") return;
203
216
  const container = localRef.current;
204
- if (!container) return;
205
- const raf = requestAnimationFrame(() => {
206
- const activeEl = container.querySelector(
207
- `[data-value="${activeValue}"][data-highlight="true"]`
208
- );
209
- if (activeEl)
210
- safeSetBoundsRef.current?.(activeEl.getBoundingClientRect());
211
- });
217
+ if (!container || typeof ResizeObserver === "undefined") return;
218
+ const observer = new ResizeObserver(
219
+ () => measureActiveRef.current?.({ instant: true })
220
+ );
221
+ observer.observe(container);
222
+ const activeEl = getActiveElement();
223
+ if (activeEl) observer.observe(activeEl);
224
+ return () => observer.disconnect();
225
+ }, [mode, getActiveElement]);
226
+ React.useLayoutEffect(() => {
227
+ if (mode !== "parent" || !activeValue) return;
228
+ const raf = requestAnimationFrame(() => measureActiveRef.current?.());
212
229
  return () => cancelAnimationFrame(raf);
213
230
  }, [mode, activeValue]);
214
231
  const render = (children2) => {
@@ -246,7 +263,7 @@ function Highlight({
246
263
  delay: (transition?.delay ?? 0) + (exitDelay ?? 0) / 1e3
247
264
  }
248
265
  },
249
- transition,
266
+ transition: boundsState.instant ? { duration: 0 } : transition,
250
267
  style: { position: "absolute", zIndex: 0, ...style },
251
268
  className: cn(className, activeClassNameState)
252
269
  }
@@ -281,7 +298,7 @@ function Highlight({
281
298
  forceUpdateBounds: props?.forceUpdateBounds
282
299
  },
283
300
  children: enabled ? controlledItems ? render(children) : render(
284
- React6.Children.map(children, (child, index) => /* @__PURE__ */ jsx(HighlightItem, { className: props?.itemsClassName, children: child }, index))
301
+ React.Children.map(children, (child, index) => /* @__PURE__ */ jsx(HighlightItem, { className: props?.itemsClassName, children: child }, index))
285
302
  ) : children
286
303
  }
287
304
  );
@@ -313,7 +330,7 @@ function HighlightItem({
313
330
  forceUpdateBounds,
314
331
  ...props
315
332
  }) {
316
- const itemId = React6.useId();
333
+ const itemId = React.useId();
317
334
  const {
318
335
  activeValue,
319
336
  setActiveValue,
@@ -338,12 +355,12 @@ function HighlightItem({
338
355
  const isActive = activeValue === childValue;
339
356
  const isDisabled = disabled === void 0 ? contextDisabled : disabled;
340
357
  const itemTransition = transition ?? contextTransition;
341
- const localRef = React6.useRef(null);
342
- React6.useImperativeHandle(ref, () => localRef.current);
343
- const refCallback = React6.useCallback((node) => {
358
+ const localRef = React.useRef(null);
359
+ React.useImperativeHandle(ref, () => localRef.current);
360
+ const refCallback = React.useCallback((node) => {
344
361
  localRef.current = node;
345
362
  }, []);
346
- React6.useEffect(() => {
363
+ React.useEffect(() => {
347
364
  if (mode !== "parent") return;
348
365
  let rafId;
349
366
  let previousBounds = null;
@@ -377,7 +394,7 @@ function HighlightItem({
377
394
  forceUpdateBounds,
378
395
  contextForceUpdateBounds
379
396
  ]);
380
- if (!React6.isValidElement(children)) return children;
397
+ if (!React.isValidElement(children)) return children;
381
398
  const dataAttributes = {
382
399
  "data-active": isActive ? "true" : "false",
383
400
  "aria-selected": isActive,
@@ -406,7 +423,7 @@ function HighlightItem({
406
423
  } : {};
407
424
  if (asChild) {
408
425
  if (mode === "children") {
409
- return React6.cloneElement(
426
+ return React.cloneElement(
410
427
  element,
411
428
  {
412
429
  key: childValue,
@@ -458,7 +475,7 @@ function HighlightItem({
458
475
  ] })
459
476
  );
460
477
  }
461
- return React6.cloneElement(element, {
478
+ return React.cloneElement(element, {
462
479
  ref: refCallback,
463
480
  ...getNonOverridingDataAttributes(element, {
464
481
  ...dataAttributes,
@@ -502,7 +519,7 @@ function HighlightItem({
502
519
  ...dataAttributes
503
520
  }
504
521
  ) }),
505
- React6.cloneElement(element, {
522
+ React.cloneElement(element, {
506
523
  style: { position: "relative", zIndex: 1 },
507
524
  className: element.props.className,
508
525
  ...getNonOverridingDataAttributes(element, {
@@ -523,7 +540,7 @@ function DropdownMenu(props) {
523
540
  defaultValue: props?.defaultOpen,
524
541
  onChange: props?.onOpenChange
525
542
  });
526
- const [highlightedValue, setHighlightedValue] = React6.useState(
543
+ const [highlightedValue, setHighlightedValue] = React.useState(
527
544
  null
528
545
  );
529
546
  return /* @__PURE__ */ jsx(
@@ -1122,7 +1139,7 @@ var sizeStyles = {
1122
1139
  lg: "text-base py-2 px-3"
1123
1140
  };
1124
1141
  function isListItem(item) {
1125
- return typeof item === "object" && item !== null && !React6__default.isValidElement(item) && "id" in item && "label" in item && typeof item.id === "string" && typeof item.label === "string";
1142
+ return typeof item === "object" && item !== null && !React__default.isValidElement(item) && "id" in item && "label" in item && typeof item.id === "string" && typeof item.label === "string";
1126
1143
  }
1127
1144
  function getItemStyles(item) {
1128
1145
  const color = item.color || "default";
@@ -1324,7 +1341,7 @@ function List({
1324
1341
  const shouldShowSeparators = showSeparators && items.length > 1;
1325
1342
  const isDropdown = role === "dropdown-list";
1326
1343
  const ItemComponent = isDropdown ? DropdownListItem : StandardListItem;
1327
- const Wrapper = isDropdown ? React6__default.Fragment : ({ children }) => /* @__PURE__ */ jsx(
1344
+ const Wrapper = isDropdown ? React__default.Fragment : ({ children }) => /* @__PURE__ */ jsx(
1328
1345
  "div",
1329
1346
  {
1330
1347
  className: cn(LIST_CLASS_NAMES.container, "flex flex-col", className),
@@ -1343,7 +1360,7 @@ function List({
1343
1360
  !isDropdown && "px-2.5 py-1.5",
1344
1361
  group.labelClassName
1345
1362
  );
1346
- return /* @__PURE__ */ jsxs(React6__default.Fragment, { children: [
1363
+ return /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
1347
1364
  group.label && (isDropdown ? /* @__PURE__ */ jsx(DropdownMenuLabel2, { className: labelClassName, children: labelContent }) : /* @__PURE__ */ jsx("div", { className: labelClassName, children: labelContent })),
1348
1365
  group.items.map((item, index) => {
1349
1366
  if (isListItem(item)) {
@@ -1423,11 +1440,11 @@ function Slot({
1423
1440
  ...props
1424
1441
  }) {
1425
1442
  const isAlreadyMotion = typeof children.type === "object" && children.type !== null && isMotionComponent(children.type);
1426
- const Base = React6.useMemo(
1443
+ const Base = React.useMemo(
1427
1444
  () => isAlreadyMotion ? children.type : motion.create(children.type),
1428
1445
  [isAlreadyMotion, children.type]
1429
1446
  );
1430
- if (!React6.isValidElement(children)) return null;
1447
+ if (!React.isValidElement(children)) return null;
1431
1448
  const { ref: childRef, ...childProps } = children.props;
1432
1449
  const mergedProps = mergeProps(childProps, props);
1433
1450
  return /* @__PURE__ */ jsx(Base, { ...mergedProps, ref: mergeRefs(childRef, ref) });
@@ -1455,12 +1472,12 @@ function TooltipProvider({
1455
1472
  closeDelay = 300,
1456
1473
  transition = { type: "spring", stiffness: 300, damping: 35 }
1457
1474
  }) {
1458
- const globalId = React6.useId();
1459
- const [currentTooltip, setCurrentTooltip] = React6.useState(null);
1460
- const timeoutRef = React6.useRef(null);
1461
- const lastCloseTimeRef = React6.useRef(0);
1462
- const referenceElRef = React6.useRef(null);
1463
- const showTooltip = React6.useCallback(
1475
+ const globalId = React.useId();
1476
+ const [currentTooltip, setCurrentTooltip] = React.useState(null);
1477
+ const timeoutRef = React.useRef(null);
1478
+ const lastCloseTimeRef = React.useRef(0);
1479
+ const referenceElRef = React.useRef(null);
1480
+ const showTooltip = React.useCallback(
1464
1481
  (data) => {
1465
1482
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
1466
1483
  if (currentTooltip !== null) {
@@ -1476,22 +1493,22 @@ function TooltipProvider({
1476
1493
  },
1477
1494
  [openDelay, closeDelay, currentTooltip]
1478
1495
  );
1479
- const hideTooltip = React6.useCallback(() => {
1496
+ const hideTooltip = React.useCallback(() => {
1480
1497
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
1481
1498
  timeoutRef.current = window.setTimeout(() => {
1482
1499
  setCurrentTooltip(null);
1483
1500
  lastCloseTimeRef.current = Date.now();
1484
1501
  }, closeDelay);
1485
1502
  }, [closeDelay]);
1486
- const hideImmediate = React6.useCallback(() => {
1503
+ const hideImmediate = React.useCallback(() => {
1487
1504
  if (timeoutRef.current) clearTimeout(timeoutRef.current);
1488
1505
  setCurrentTooltip(null);
1489
1506
  lastCloseTimeRef.current = Date.now();
1490
1507
  }, []);
1491
- const setReferenceEl = React6.useCallback((el) => {
1508
+ const setReferenceEl = React.useCallback((el) => {
1492
1509
  referenceElRef.current = el;
1493
1510
  }, []);
1494
- React6.useEffect(() => {
1511
+ React.useEffect(() => {
1495
1512
  const onKeyDown = (e) => {
1496
1513
  if (e.key === "Escape") hideImmediate();
1497
1514
  };
@@ -1535,7 +1552,7 @@ function TooltipArrow({
1535
1552
  const { side, align, open } = useRenderedTooltip();
1536
1553
  const { context, arrowRef } = useFloatingContext();
1537
1554
  const { transition, globalId } = useGlobalTooltip();
1538
- React6.useImperativeHandle(ref, () => arrowRef.current);
1555
+ React.useImperativeHandle(ref, () => arrowRef.current);
1539
1556
  const deg = { top: 0, right: 90, bottom: 180, left: -90 }[side];
1540
1557
  return /* @__PURE__ */ jsx(
1541
1558
  MotionTooltipArrow,
@@ -1558,8 +1575,8 @@ function TooltipPortal(props) {
1558
1575
  }
1559
1576
  function TooltipOverlay() {
1560
1577
  const { currentTooltip, transition, globalId, referenceElRef } = useGlobalTooltip();
1561
- const [rendered, setRendered] = React6.useState({ data: null, open: false });
1562
- const arrowRef = React6.useRef(null);
1578
+ const [rendered, setRendered] = React.useState({ data: null, open: false });
1579
+ const arrowRef = React.useRef(null);
1563
1580
  const side = rendered.data?.side ?? "top";
1564
1581
  const align = rendered.data?.align ?? "center";
1565
1582
  const { refs, x, y, strategy, context, update } = useFloating({
@@ -1575,14 +1592,14 @@ function TooltipOverlay() {
1575
1592
  arrow({ element: arrowRef })
1576
1593
  ]
1577
1594
  });
1578
- React6.useEffect(() => {
1595
+ React.useEffect(() => {
1579
1596
  if (currentTooltip) {
1580
1597
  setRendered({ data: currentTooltip, open: true });
1581
1598
  } else {
1582
1599
  setRendered((p) => p.data ? { ...p, open: false } : p);
1583
1600
  }
1584
1601
  }, [currentTooltip]);
1585
- React6.useLayoutEffect(() => {
1602
+ React.useLayoutEffect(() => {
1586
1603
  if (referenceElRef.current) {
1587
1604
  refs.setReference(referenceElRef.current);
1588
1605
  update();
@@ -1661,9 +1678,9 @@ function Tooltip({
1661
1678
  align = "center",
1662
1679
  alignOffset = 0
1663
1680
  }) {
1664
- const id = React6.useId();
1665
- const [props, setProps] = React6.useState({});
1666
- const [asChild, setAsChild] = React6.useState(false);
1681
+ const id = React.useId();
1682
+ const [props, setProps] = React.useState({});
1683
+ const [asChild, setAsChild] = React.useState(false);
1667
1684
  return /* @__PURE__ */ jsx(
1668
1685
  LocalTooltipProvider,
1669
1686
  {
@@ -1695,16 +1712,16 @@ function shallowEqualWithoutChildren(a, b) {
1695
1712
  }
1696
1713
  function TooltipContent({ asChild = false, ...props }) {
1697
1714
  const { setProps, setAsChild } = useTooltip();
1698
- const lastPropsRef = React6.useRef(
1715
+ const lastPropsRef = React.useRef(
1699
1716
  void 0
1700
1717
  );
1701
- React6.useEffect(() => {
1718
+ React.useEffect(() => {
1702
1719
  if (!shallowEqualWithoutChildren(lastPropsRef.current, props)) {
1703
1720
  lastPropsRef.current = props;
1704
1721
  setProps(props);
1705
1722
  }
1706
1723
  }, [props, setProps]);
1707
- React6.useEffect(() => {
1724
+ React.useEffect(() => {
1708
1725
  setAsChild(asChild);
1709
1726
  }, [asChild, setAsChild]);
1710
1727
  return null;
@@ -1735,10 +1752,10 @@ function TooltipTrigger({
1735
1752
  currentTooltip,
1736
1753
  setReferenceEl
1737
1754
  } = useGlobalTooltip();
1738
- const triggerRef = React6.useRef(null);
1739
- React6.useImperativeHandle(ref, () => triggerRef.current);
1740
- const suppressNextFocusRef = React6.useRef(false);
1741
- const handleOpen = React6.useCallback(() => {
1755
+ const triggerRef = React.useRef(null);
1756
+ React.useImperativeHandle(ref, () => triggerRef.current);
1757
+ const suppressNextFocusRef = React.useRef(false);
1758
+ const handleOpen = React.useCallback(() => {
1742
1759
  if (!triggerRef.current) return;
1743
1760
  setReferenceEl(triggerRef.current);
1744
1761
  const rect = triggerRef.current.getBoundingClientRect();
@@ -1763,7 +1780,7 @@ function TooltipTrigger({
1763
1780
  alignOffset,
1764
1781
  id
1765
1782
  ]);
1766
- const handlePointerDown = React6.useCallback(
1783
+ const handlePointerDown = React.useCallback(
1767
1784
  (e) => {
1768
1785
  onPointerDown?.(e);
1769
1786
  if (currentTooltip?.id === id) {
@@ -1776,21 +1793,21 @@ function TooltipTrigger({
1776
1793
  },
1777
1794
  [onPointerDown, currentTooltip?.id, id, hideImmediate]
1778
1795
  );
1779
- const handleMouseEnter = React6.useCallback(
1796
+ const handleMouseEnter = React.useCallback(
1780
1797
  (e) => {
1781
1798
  onMouseEnter?.(e);
1782
1799
  handleOpen();
1783
1800
  },
1784
1801
  [handleOpen, onMouseEnter]
1785
1802
  );
1786
- const handleMouseLeave = React6.useCallback(
1803
+ const handleMouseLeave = React.useCallback(
1787
1804
  (e) => {
1788
1805
  onMouseLeave?.(e);
1789
1806
  hideTooltip();
1790
1807
  },
1791
1808
  [hideTooltip, onMouseLeave]
1792
1809
  );
1793
- const handleFocus = React6.useCallback(
1810
+ const handleFocus = React.useCallback(
1794
1811
  (e) => {
1795
1812
  onFocus?.(e);
1796
1813
  if (suppressNextFocusRef.current) return;
@@ -1798,7 +1815,7 @@ function TooltipTrigger({
1798
1815
  },
1799
1816
  [handleOpen, onFocus]
1800
1817
  );
1801
- const handleBlur = React6.useCallback(
1818
+ const handleBlur = React.useCallback(
1802
1819
  (e) => {
1803
1820
  onBlur?.(e);
1804
1821
  hideTooltip();
@@ -1963,8 +1980,8 @@ var presetFocusVisibleRingColors = {
1963
1980
  mist: "focus-visible:ring-mist-border"
1964
1981
  };
1965
1982
  function ProgressBarOverlay() {
1966
- const [progress, setProgress] = React6.useState(10);
1967
- React6.useEffect(() => {
1983
+ const [progress, setProgress] = React.useState(10);
1984
+ React.useEffect(() => {
1968
1985
  if (progress >= 90) return;
1969
1986
  const timeout = setTimeout(() => {
1970
1987
  const increment = Math.random() * 15 + 5;
@@ -1983,7 +2000,7 @@ function ProgressBarOverlay() {
1983
2000
  );
1984
2001
  }
1985
2002
  var iconAnimateClasses = "transition-transform duration-200";
1986
- var Button2 = React6.forwardRef(
2003
+ var Button2 = React.forwardRef(
1987
2004
  ({
1988
2005
  children,
1989
2006
  color = "primary",
@@ -2091,7 +2108,7 @@ var buttonVariants2 = cva(
2091
2108
  }
2092
2109
  }
2093
2110
  );
2094
- var Button3 = React6.forwardRef(
2111
+ var Button3 = React.forwardRef(
2095
2112
  ({ className, variant, size, asChild = false, type, ...props }, ref) => {
2096
2113
  const Comp = asChild ? Slot$1 : "button";
2097
2114
  return /* @__PURE__ */ jsx(
@@ -2106,7 +2123,7 @@ var Button3 = React6.forwardRef(
2106
2123
  }
2107
2124
  );
2108
2125
  Button3.displayName = "Button";
2109
- var CraftButtonContext = React6.createContext({});
2126
+ var CraftButtonContext = React.createContext({});
2110
2127
  function CraftButtonLabel({ children, className }) {
2111
2128
  return /* @__PURE__ */ jsx(
2112
2129
  "span",
@@ -2120,7 +2137,7 @@ function CraftButtonLabel({ children, className }) {
2120
2137
  );
2121
2138
  }
2122
2139
  function CraftButtonIcon({ children, className }) {
2123
- const { size } = React6.useContext(CraftButtonContext);
2140
+ const { size } = React.useContext(CraftButtonContext);
2124
2141
  const iconSize = size === "lg" ? "size-6" : size === "sm" ? "size-4" : "size-5";
2125
2142
  return /* @__PURE__ */ jsxs("span", { className: cn("relative z-1", iconSize, className), children: [
2126
2143
  /* @__PURE__ */ jsx(
@@ -2222,7 +2239,7 @@ function CopyButton({
2222
2239
  value: copied,
2223
2240
  onChange: onCopiedChange
2224
2241
  });
2225
- const handleCopy = React6.useCallback(
2242
+ const handleCopy = React.useCallback(
2226
2243
  (e) => {
2227
2244
  onClick?.(e);
2228
2245
  if (copied) return;
@@ -2264,7 +2281,7 @@ function CopyButton({
2264
2281
  }
2265
2282
  );
2266
2283
  }
2267
- var ScrollArea = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
2284
+ var ScrollArea = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
2268
2285
  ScrollAreaPrimitive.Root,
2269
2286
  {
2270
2287
  ref,
@@ -2278,7 +2295,7 @@ var ScrollArea = React6.forwardRef(({ className, children, ...props }, ref) => /
2278
2295
  }
2279
2296
  ));
2280
2297
  ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
2281
- var ScrollBar = React6.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
2298
+ var ScrollBar = React.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ jsx(
2282
2299
  ScrollAreaPrimitive.ScrollAreaScrollbar,
2283
2300
  {
2284
2301
  ref,
@@ -2325,7 +2342,7 @@ var sizeClasses2 = {
2325
2342
  default: "h-10 px-3 py-2 text-base md:text-sm",
2326
2343
  lg: "h-12 px-4 text-lg"
2327
2344
  };
2328
- var Input = React6.forwardRef(
2345
+ var Input = React.forwardRef(
2329
2346
  ({
2330
2347
  className,
2331
2348
  type,
@@ -2353,15 +2370,15 @@ var Input = React6.forwardRef(
2353
2370
  placeholder,
2354
2371
  ...restProps
2355
2372
  }, ref) => {
2356
- const autoId = React6.useId();
2373
+ const autoId = React.useId();
2357
2374
  const inputId = id || autoId;
2358
- const [charCount, setCharCount] = React6.useState(() => {
2375
+ const [charCount, setCharCount] = React.useState(() => {
2359
2376
  if (charLimit === void 0) return 0;
2360
2377
  if (typeof value === "string") return value.length;
2361
2378
  if (typeof defaultValue === "string") return defaultValue.length;
2362
2379
  return 0;
2363
2380
  });
2364
- React6.useEffect(() => {
2381
+ React.useEffect(() => {
2365
2382
  if (charLimit !== void 0 && typeof value === "string") {
2366
2383
  setCharCount(value.length);
2367
2384
  }
@@ -2396,6 +2413,18 @@ var Input = React6.forwardRef(
2396
2413
  onChange?.(e);
2397
2414
  };
2398
2415
  const effectivePlaceholder = floatingLabel ? " " : placeholder;
2416
+ const resolveAddOn = (content, text) => content != null && content !== false && content !== "" ? content : text || void 0;
2417
+ const startAddOnNode = resolveAddOn(startAddOnContent, startAddOn);
2418
+ const endAddOnNode = resolveAddOn(endAddOnContent, endAddOn);
2419
+ const hasAddOn = startAddOnNode != null || endAddOnNode != null;
2420
+ const hasOverlay = !!startIcon || !!endIcon || charLimit !== void 0 || !!floatingLabel;
2421
+ const helperStartId = `${inputId}-helper-start`;
2422
+ const helperEndId = `${inputId}-helper-end`;
2423
+ const describedBy = [
2424
+ errorContent && `${inputId}-error`,
2425
+ startHelperContent && !errorContent && helperStartId,
2426
+ endHelperContent && !errorContent && helperEndId
2427
+ ].filter(Boolean).join(" ") || void 0;
2399
2428
  const inputClasses = cn(
2400
2429
  "flex w-full border border-input bg-background ring-offset-background transition-[box-shadow,border-color] duration-200 ease-in-out file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 read-only:bg-muted z-10",
2401
2430
  floatingLabel ? "h-12 px-3 pt-4 pb-1 text-base md:text-sm" : sizeClasses2[effectiveSize],
@@ -2404,11 +2433,13 @@ var Input = React6.forwardRef(
2404
2433
  startIcon && "ps-9",
2405
2434
  endIcon && "pe-9",
2406
2435
  charLimit !== void 0 && !endIcon && "pe-14",
2407
- startAddOnContent && "-ms-px rounded-s-none shadow-none",
2408
- endAddOnContent && "-me-px rounded-e-none shadow-none",
2409
- startAddOn && "rounded-s-none shadow-none",
2410
- endAddOn && "rounded-e-none shadow-none",
2411
- floatingLabel && "peer placeholder:text-transparent",
2436
+ charLimit !== void 0 && endIcon && "pe-20",
2437
+ startAddOnNode != null && "rounded-s-none shadow-none",
2438
+ endAddOnNode != null && "rounded-e-none shadow-none",
2439
+ // `peer` is a marker only; the overlay decorators are later siblings and
2440
+ // rely on it for `peer-disabled:` / `peer-placeholder-shown:` variants.
2441
+ "peer",
2442
+ floatingLabel && "placeholder:text-transparent",
2412
2443
  className
2413
2444
  );
2414
2445
  const inputElement = /* @__PURE__ */ jsx(
@@ -2420,7 +2451,7 @@ var Input = React6.forwardRef(
2420
2451
  className: inputClasses,
2421
2452
  required,
2422
2453
  "aria-invalid": hasError || void 0,
2423
- "aria-describedby": errorContent ? `${inputId}-error` : startHelperContent || endHelperContent ? `${inputId}-helper` : void 0,
2454
+ "aria-describedby": describedBy,
2424
2455
  onChange: handleChange,
2425
2456
  value,
2426
2457
  defaultValue,
@@ -2429,28 +2460,18 @@ var Input = React6.forwardRef(
2429
2460
  ...restProps
2430
2461
  }
2431
2462
  );
2432
- let inputContainer;
2433
- if (startAddOn || endAddOn) {
2434
- inputContainer = /* @__PURE__ */ jsxs("div", { className: "flex rounded-lg", children: [
2435
- startAddOn && /* @__PURE__ */ jsx("span", { className: "-me-px inline-flex items-center rounded-s-lg border border-input bg-background px-3 text-sm text-muted-foreground", children: startAddOn }),
2436
- inputElement,
2437
- endAddOn && /* @__PURE__ */ jsx("span", { className: "-ms-px inline-flex items-center rounded-e-lg border border-input bg-background px-3 text-sm text-muted-foreground", children: endAddOn })
2438
- ] });
2439
- } else if (startAddOnContent || endAddOnContent) {
2440
- inputContainer = /* @__PURE__ */ jsxs("div", { className: "flex rounded-lg", children: [
2441
- startAddOnContent && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-s-lg border border-input bg-background px-3 text-sm text-muted-foreground", children: startAddOnContent }),
2442
- inputElement,
2443
- endAddOnContent && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-e-lg border border-input bg-background px-3 text-sm text-muted-foreground", children: endAddOnContent })
2444
- ] });
2445
- } else if (startIcon || endIcon || charLimit !== void 0 || floatingLabel) {
2446
- inputContainer = /* @__PURE__ */ jsxs("div", { className: "group relative", children: [
2463
+ let inputContainer = inputElement;
2464
+ if (hasOverlay) {
2465
+ inputContainer = /* @__PURE__ */ jsxs("div", { className: "group relative min-w-0 flex-1", children: [
2447
2466
  inputElement,
2448
2467
  startIcon && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 start-0 flex items-center justify-center ps-3 text-muted-foreground/80 peer-disabled:opacity-50", children: startIcon }),
2449
- endIcon && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-y-0 end-0 flex items-center justify-center pe-3 text-muted-foreground/80 peer-disabled:opacity-50", children: endIcon }),
2450
- charLimit !== void 0 && /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute inset-y-0 end-0 flex items-center justify-center pe-3 text-xs tabular-nums text-muted-foreground peer-disabled:opacity-50", children: [
2451
- charCount,
2452
- "/",
2453
- charLimit
2468
+ (endIcon || charLimit !== void 0) && /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute inset-y-0 end-0 flex items-center justify-center gap-2 pe-3 text-muted-foreground/80 peer-disabled:opacity-50", children: [
2469
+ charLimit !== void 0 && /* @__PURE__ */ jsxs("span", { className: "text-xs tabular-nums text-muted-foreground", children: [
2470
+ charCount,
2471
+ "/",
2472
+ charLimit
2473
+ ] }),
2474
+ endIcon
2454
2475
  ] }),
2455
2476
  floatingLabel && label && /* @__PURE__ */ jsxs(
2456
2477
  "label",
@@ -2464,8 +2485,13 @@ var Input = React6.forwardRef(
2464
2485
  }
2465
2486
  )
2466
2487
  ] });
2467
- } else {
2468
- inputContainer = inputElement;
2488
+ }
2489
+ if (hasAddOn) {
2490
+ inputContainer = /* @__PURE__ */ jsxs("div", { className: "flex rounded-lg", children: [
2491
+ startAddOnNode != null && /* @__PURE__ */ jsx("span", { className: "-me-px inline-flex items-center rounded-s-lg border border-input bg-background px-3 text-sm text-muted-foreground", children: startAddOnNode }),
2492
+ inputContainer,
2493
+ endAddOnNode != null && /* @__PURE__ */ jsx("span", { className: "-ms-px inline-flex items-center rounded-e-lg border border-input bg-background px-3 text-sm text-muted-foreground", children: endAddOnNode })
2494
+ ] });
2469
2495
  }
2470
2496
  return /* @__PURE__ */ jsxs("div", { className: "space-y-2 flex-1", children: [
2471
2497
  label && !floatingLabel && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
@@ -2478,18 +2504,11 @@ var Input = React6.forwardRef(
2478
2504
  !label && hintContent && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: hintContent }),
2479
2505
  inputContainer,
2480
2506
  errorContent && /* @__PURE__ */ jsx("div", { id: `${inputId}-error`, className: "text-sm text-destructive", children: errorContent }),
2481
- startHelperContent && !errorContent && /* @__PURE__ */ jsx(
2482
- "div",
2483
- {
2484
- id: `${inputId}-helper`,
2485
- className: "text-sm text-muted-foreground",
2486
- children: startHelperContent
2487
- }
2488
- ),
2507
+ startHelperContent && !errorContent && /* @__PURE__ */ jsx("div", { id: helperStartId, className: "text-sm text-muted-foreground", children: startHelperContent }),
2489
2508
  endHelperContent && !errorContent && /* @__PURE__ */ jsx(
2490
2509
  "div",
2491
2510
  {
2492
- id: `${inputId}-helper`,
2511
+ id: helperEndId,
2493
2512
  className: "text-sm text-end text-muted-foreground",
2494
2513
  children: endHelperContent
2495
2514
  }
@@ -2498,7 +2517,7 @@ var Input = React6.forwardRef(
2498
2517
  }
2499
2518
  );
2500
2519
  Input.displayName = "Input";
2501
- var InputPassword = React6.forwardRef(
2520
+ var InputPassword = React.forwardRef(
2502
2521
  ({ className, ...props }, ref) => {
2503
2522
  const [isVisible, setIsVisible] = useState(false);
2504
2523
  return /* @__PURE__ */ jsx(
@@ -2621,8 +2640,8 @@ function SheetTitle(props) {
2621
2640
  function SheetDescription(props) {
2622
2641
  return /* @__PURE__ */ jsx(Dialog.Description, { "data-slot": "sheet-description", ...props });
2623
2642
  }
2624
- var SheetFloatingContext = React6.createContext(false);
2625
- var SheetDismissContext = React6.createContext({
2643
+ var SheetFloatingContext = React.createContext(false);
2644
+ var SheetDismissContext = React.createContext({
2626
2645
  closeOnEscape: true,
2627
2646
  closeOnOutsideClick: true
2628
2647
  });
@@ -2632,7 +2651,7 @@ function Sheet2({
2632
2651
  closeOnOutsideClick = true,
2633
2652
  ...props
2634
2653
  }) {
2635
- const dismissBehavior = React6.useMemo(
2654
+ const dismissBehavior = React.useMemo(
2636
2655
  () => ({ closeOnEscape, closeOnOutsideClick }),
2637
2656
  [closeOnEscape, closeOnOutsideClick]
2638
2657
  );
@@ -2662,8 +2681,8 @@ function SheetContent2({
2662
2681
  onPointerDownOutside,
2663
2682
  ...props
2664
2683
  }) {
2665
- const floating = React6.useContext(SheetFloatingContext);
2666
- const { closeOnEscape, closeOnOutsideClick } = React6.useContext(SheetDismissContext);
2684
+ const floating = React.useContext(SheetFloatingContext);
2685
+ const { closeOnEscape, closeOnOutsideClick } = React.useContext(SheetDismissContext);
2667
2686
  const closeClassName = "ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none";
2668
2687
  if (floating) {
2669
2688
  return /* @__PURE__ */ jsxs(SheetPortal, { children: [
@@ -2787,10 +2806,10 @@ function SidebarProvider({
2787
2806
  ...props
2788
2807
  }) {
2789
2808
  const isMobile = useIsMobile();
2790
- const [openMobile, setOpenMobile] = React6.useState(false);
2791
- const [_open, _setOpen] = React6.useState(defaultOpen);
2809
+ const [openMobile, setOpenMobile] = React.useState(false);
2810
+ const [_open, _setOpen] = React.useState(defaultOpen);
2792
2811
  const open = openProp ?? _open;
2793
- const setOpen = React6.useCallback(
2812
+ const setOpen = React.useCallback(
2794
2813
  (value) => {
2795
2814
  const openState = typeof value === "function" ? value(open) : value;
2796
2815
  if (setOpenProp) {
@@ -2802,10 +2821,10 @@ function SidebarProvider({
2802
2821
  },
2803
2822
  [setOpenProp, open]
2804
2823
  );
2805
- const toggleSidebar = React6.useCallback(() => {
2824
+ const toggleSidebar = React.useCallback(() => {
2806
2825
  return isMobile ? setOpenMobile((open2) => !open2) : setOpen((open2) => !open2);
2807
2826
  }, [isMobile, setOpen, setOpenMobile]);
2808
- React6.useEffect(() => {
2827
+ React.useEffect(() => {
2809
2828
  const handleKeyDown = (event) => {
2810
2829
  if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
2811
2830
  event.preventDefault();
@@ -2816,7 +2835,7 @@ function SidebarProvider({
2816
2835
  return () => window.removeEventListener("keydown", handleKeyDown);
2817
2836
  }, [toggleSidebar]);
2818
2837
  const state = open ? "expanded" : "collapsed";
2819
- const contextValue = React6.useMemo(
2838
+ const contextValue = React.useMemo(
2820
2839
  () => ({
2821
2840
  state,
2822
2841
  open,
@@ -3308,7 +3327,7 @@ function SidebarMenuSkeleton({
3308
3327
  showIcon = false,
3309
3328
  ...props
3310
3329
  }) {
3311
- const width = React6.useMemo(() => {
3330
+ const width = React.useMemo(() => {
3312
3331
  return `${Math.floor(Math.random() * 40) + 50}%`;
3313
3332
  }, []);
3314
3333
  return /* @__PURE__ */ jsxs(
@@ -3398,41 +3417,31 @@ function SidebarMenuSubButton({
3398
3417
  function isSidebarGroup(entry) {
3399
3418
  return "items" in entry;
3400
3419
  }
3420
+
3421
+ // src/utils/path-match.ts
3422
+ function isPathPrefixOf(prefix, fullPath) {
3423
+ if (prefix === fullPath) return true;
3424
+ return fullPath.startsWith(prefix) && (prefix.endsWith("/") || fullPath[prefix.length] === "/");
3425
+ }
3401
3426
  var sidebarGroupClassName = "py-0 px-2";
3427
+ var rowIconClass = "[&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0";
3428
+ var rowFontStyle = {
3429
+ fontSize: "var(--espd-sidebar-item-font-size, 0.875rem)",
3430
+ lineHeight: "1.25rem"
3431
+ };
3432
+ var flyoutGroupLabelStyle = {
3433
+ fontSize: "var(--espd-sidebar-flyout-group-label-font-size, 0.875rem)",
3434
+ lineHeight: "1.25rem"
3435
+ };
3402
3436
  function ItemIcon({
3403
3437
  icon: Icon,
3404
- label,
3405
- className = "h-4 w-4"
3438
+ active,
3439
+ className
3406
3440
  }) {
3407
3441
  if (Icon) return /* @__PURE__ */ jsx(Icon, { className });
3408
- return /* @__PURE__ */ jsx(
3409
- Avatar2,
3410
- {
3411
- name: label,
3412
- size: "sm",
3413
- className: "shrink-0 !h-4 !w-4 bg-sidebar-foreground/15 text-sidebar-foreground"
3414
- }
3415
- );
3442
+ if (active) return /* @__PURE__ */ jsx(CircleDot, { className });
3443
+ return /* @__PURE__ */ jsx(Circle, { className: cn("opacity-50", className) });
3416
3444
  }
3417
- function GroupIconEl({
3418
- icon: Icon,
3419
- label,
3420
- className = "h-4 w-4 shrink-0"
3421
- }) {
3422
- if (Icon) return /* @__PURE__ */ jsx(Icon, { className });
3423
- return /* @__PURE__ */ jsx(
3424
- Avatar2,
3425
- {
3426
- name: label,
3427
- size: "sm",
3428
- className: "shrink-0 !h-4 !w-4 bg-sidebar-foreground/15 text-sidebar-foreground"
3429
- }
3430
- );
3431
- }
3432
- var sidebarItemFontStyle = { fontSize: "var(--espd-sidebar-item-font-size, 0.875rem)" };
3433
- var flyoutGroupLabelStyle = {
3434
- fontSize: "var(--espd-sidebar-flyout-group-label-font-size, 1rem)"
3435
- };
3436
3445
  function GroupMenuItems({
3437
3446
  group,
3438
3447
  isSelected,
@@ -3443,10 +3452,14 @@ function GroupMenuItems({
3443
3452
  /* @__PURE__ */ jsxs(
3444
3453
  DropdownMenuLabel2,
3445
3454
  {
3446
- className: "flex items-center gap-2 px-3 py-2 font-normal text-muted-foreground",
3455
+ className: cn(
3456
+ "flex items-center gap-2 px-3 py-2 font-normal text-muted-foreground",
3457
+ // DropdownMenuLabel, unlike DropdownMenuItem, ships no svg sizing of its own.
3458
+ rowIconClass
3459
+ ),
3447
3460
  style: flyoutGroupLabelStyle,
3448
3461
  children: [
3449
- group.icon ? /* @__PURE__ */ jsx(GroupIconEl, { icon: group.icon, label: group.label, className: "h-4 w-4 shrink-0 text-foreground" }) : null,
3462
+ group.icon ? /* @__PURE__ */ jsx(ItemIcon, { icon: group.icon, className: "text-foreground" }) : null,
3450
3463
  /* @__PURE__ */ jsx("span", { className: "truncate", children: group.label })
3451
3464
  ]
3452
3465
  }
@@ -3454,8 +3467,8 @@ function GroupMenuItems({
3454
3467
  /* @__PURE__ */ jsx(DropdownMenuSeparator2, {}),
3455
3468
  group.items.map((item) => {
3456
3469
  const active = isSelected(item.path);
3457
- return /* @__PURE__ */ jsx(DropdownMenuItem2, { className: active ? "bg-accent" : "", style: sidebarItemFontStyle, children: /* @__PURE__ */ jsx(LinkComponent, { to: item.path, className: "flex items-center gap-2 cursor-pointer w-full", children: /* @__PURE__ */ jsxs("span", { className: "contents", onClick: onItemClick, children: [
3458
- /* @__PURE__ */ jsx(ItemIcon, { icon: item.icon, label: item.label }),
3470
+ return /* @__PURE__ */ jsx(DropdownMenuItem2, { className: active ? "bg-accent" : "", style: rowFontStyle, children: /* @__PURE__ */ jsx(LinkComponent, { to: item.path, className: "flex items-center gap-2 cursor-pointer w-full", children: /* @__PURE__ */ jsxs("span", { className: "contents", onClick: onItemClick, children: [
3471
+ /* @__PURE__ */ jsx(ItemIcon, { icon: item.icon, active }),
3459
3472
  /* @__PURE__ */ jsx("span", { className: active ? "font-semibold" : "font-medium", children: item.label })
3460
3473
  ] }) }) }, item.id);
3461
3474
  })
@@ -3468,7 +3481,7 @@ function CollapsedSidebarGroup({
3468
3481
  }) {
3469
3482
  const [open, setOpen] = useState(false);
3470
3483
  return /* @__PURE__ */ jsx(SidebarGroup, { className: sidebarGroupClassName, children: /* @__PURE__ */ jsx(SidebarMenu, { className: "w-auto", children: /* @__PURE__ */ jsx(SidebarMenuItem, { children: /* @__PURE__ */ jsxs(DropdownMenu2, { open, onOpenChange: setOpen, children: [
3471
- /* @__PURE__ */ jsx(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx(SidebarMenuButton, { size: "sm", tooltip: group.label, children: /* @__PURE__ */ jsx(GroupIconEl, { icon: group.icon, label: group.label, className: "h-5 w-5 shrink-0" }) }) }),
3484
+ /* @__PURE__ */ jsx(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsx(SidebarMenuButton, { size: "sm", tooltip: group.label, className: rowIconClass, children: /* @__PURE__ */ jsx(ItemIcon, { icon: group.icon }) }) }),
3472
3485
  /* @__PURE__ */ jsx(
3473
3486
  DropdownMenuContent2,
3474
3487
  {
@@ -3490,7 +3503,14 @@ function CollapsedSidebarGroup({
3490
3503
  )
3491
3504
  ] }) }) }) });
3492
3505
  }
3493
- var groupHeaderClass = "flex flex-1 items-center gap-2 rounded-md p-2 h-7 font-medium text-sidebar-foreground hover:bg-sidebar-accent/50 transition-colors cursor-pointer";
3506
+ var groupHeaderClass = cn(
3507
+ // No `flex-1`: this button is a column flex item, so growing made it take its
3508
+ // content height (36px) and render taller than the `h-7` item rows below it.
3509
+ // `w-full` keeps the full-width hit area, `overflow-hidden` makes the label truncate.
3510
+ "flex w-full items-center gap-2 rounded-md p-2 h-7 overflow-hidden font-medium text-sidebar-foreground hover:bg-sidebar-accent/50 transition-colors cursor-pointer",
3511
+ // Sizes both the group icon and the expand/collapse chevron.
3512
+ rowIconClass
3513
+ );
3494
3514
  function ExpandedSidebarGroup({
3495
3515
  group,
3496
3516
  isGroupOpen,
@@ -3498,12 +3518,12 @@ function ExpandedSidebarGroup({
3498
3518
  renderMenuItem
3499
3519
  }) {
3500
3520
  return /* @__PURE__ */ jsx(Collapsible, { open: isGroupOpen, onOpenChange: onToggle, children: /* @__PURE__ */ jsxs(SidebarGroup, { className: sidebarGroupClassName, children: [
3501
- /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("button", { type: "button", className: groupHeaderClass, style: sidebarItemFontStyle, children: [
3502
- /* @__PURE__ */ jsx(GroupIconEl, { icon: group.icon, label: group.label }),
3521
+ /* @__PURE__ */ jsx(CollapsibleTrigger, { asChild: true, children: /* @__PURE__ */ jsxs("button", { type: "button", className: groupHeaderClass, style: rowFontStyle, children: [
3522
+ /* @__PURE__ */ jsx(ItemIcon, { icon: group.icon }),
3503
3523
  /* @__PURE__ */ jsx("span", { className: "truncate", children: group.label }),
3504
- isGroupOpen ? /* @__PURE__ */ jsx(ChevronDown, { className: "ml-auto h-3.5 w-3.5 shrink-0 transition-transform" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto h-3.5 w-3.5 shrink-0 transition-transform" })
3524
+ isGroupOpen ? /* @__PURE__ */ jsx(ChevronDown, { className: "ml-auto transition-transform" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "ml-auto transition-transform" })
3505
3525
  ] }) }),
3506
- /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { className: "pl-3", children: group.items.map((item) => renderMenuItem(item)) }) }) })
3526
+ /* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx(SidebarGroupContent, { children: /* @__PURE__ */ jsx(SidebarMenu, { className: "pl-6 pt-1", children: group.items.map((item) => renderMenuItem(item)) }) }) })
3507
3527
  ] }) });
3508
3528
  }
3509
3529
  function TopLevelLinkRow({
@@ -3546,32 +3566,52 @@ function Sidebar2({
3546
3566
  });
3547
3567
  };
3548
3568
  const isSelected = (path) => {
3549
- return currentPath.startsWith(path);
3569
+ return isPathPrefixOf(path, currentPath);
3550
3570
  };
3551
3571
  const renderMenuItem = (item) => {
3552
- const Icon = item.icon;
3553
3572
  const EndActionIcon = item.endAction?.icon;
3554
3573
  const active = isSelected(item.path);
3555
3574
  return /* @__PURE__ */ jsxs(SidebarMenuItem, { children: [
3556
- /* @__PURE__ */ jsx(SidebarMenuButton, { asChild: true, isActive: active, size: "sm", tooltip: item.label, children: /* @__PURE__ */ jsx(LinkComponent, { to: item.path, children: /* @__PURE__ */ jsxs("span", { className: "contents", onClick: closeMobileSidebar, children: [
3557
- Icon ? /* @__PURE__ */ jsx(Icon, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx(
3558
- Avatar2,
3559
- {
3560
- name: item.label,
3561
- size: "sm",
3562
- className: "shrink-0 !h-4 !w-4 bg-sidebar-foreground/15 text-sidebar-foreground"
3563
- }
3564
- ),
3565
- /* @__PURE__ */ jsx(
3566
- "span",
3567
- {
3568
- className: `whitespace-nowrap max-w-[168px] truncate text-sidebar-foreground ${active ? "font-semibold" : "font-medium"}`,
3569
- style: sidebarItemFontStyle,
3570
- children: item.label
3571
- }
3572
- )
3573
- ] }) }) }),
3574
- item.endAction && EndActionIcon && /* @__PURE__ */ jsx(Tooltip3, { content: item.endAction.tooltip, side: "right", sideOffset: 8, children: /* @__PURE__ */ jsx(SidebarMenuAction, { asChild: true, children: /* @__PURE__ */ jsx(LinkComponent, { to: item.endAction.path, children: /* @__PURE__ */ jsx("span", { className: "contents", onClick: closeMobileSidebar, children: /* @__PURE__ */ jsx(EndActionIcon, {}) }) }) }) })
3575
+ /* @__PURE__ */ jsx(
3576
+ SidebarMenuButton,
3577
+ {
3578
+ asChild: true,
3579
+ isActive: active,
3580
+ size: "sm",
3581
+ tooltip: item.label,
3582
+ className: cn(
3583
+ rowIconClass,
3584
+ // Selected-row fill spelled out here rather than left to the primitive's
3585
+ // `data-[active=true]:bg-sidebar-accent`: that rule needs `data-active` on the
3586
+ // rendered element, and `asChild` hands the data attributes to the app's
3587
+ // LinkComponent, which need not forward them. `className` is the one prop every
3588
+ // LinkComponent takes, so it is the only reliable channel. `isActive` above
3589
+ // still sets `data-active` for apps that do forward it, and for test selectors.
3590
+ active && "bg-sidebar-accent text-sidebar-accent-foreground",
3591
+ // Reserve room for the endAction. The primitive does this with
3592
+ // `:has([data-sidebar=menu-action])`, which cannot fire here: `asChild` hands
3593
+ // its data attributes to the app's LinkComponent, which need not forward them.
3594
+ item.endAction && "pr-8"
3595
+ ),
3596
+ children: /* @__PURE__ */ jsx(LinkComponent, { to: item.path, children: /* @__PURE__ */ jsxs("span", { className: "contents", onClick: closeMobileSidebar, children: [
3597
+ /* @__PURE__ */ jsx(ItemIcon, { icon: item.icon, active }),
3598
+ /* @__PURE__ */ jsx(
3599
+ "span",
3600
+ {
3601
+ className: cn(
3602
+ "whitespace-nowrap max-w-[168px] truncate",
3603
+ // Set on the label, so it has to restate the row's colour: a plain
3604
+ // `text-sidebar-foreground` here would beat the parent's accent colour.
3605
+ active ? "font-semibold text-sidebar-accent-foreground" : "font-medium text-sidebar-foreground"
3606
+ ),
3607
+ style: rowFontStyle,
3608
+ children: item.label
3609
+ }
3610
+ )
3611
+ ] }) })
3612
+ }
3613
+ ),
3614
+ item.endAction && EndActionIcon && /* @__PURE__ */ jsx(Tooltip3, { content: item.endAction.tooltip, side: "right", sideOffset: 8, children: /* @__PURE__ */ jsx(SidebarMenuAction, { asChild: true, className: cn(rowIconClass, "right-1.5"), children: /* @__PURE__ */ jsx(LinkComponent, { to: item.endAction.path, children: /* @__PURE__ */ jsx("span", { className: "contents", onClick: closeMobileSidebar, children: /* @__PURE__ */ jsx(EndActionIcon, {}) }) }) }) })
3575
3615
  ] }, item.id);
3576
3616
  };
3577
3617
  const renderGroup = (group) => {
@@ -3664,7 +3704,7 @@ function renderIconSlot(icon) {
3664
3704
  if (icon == null) return null;
3665
3705
  return /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: icon });
3666
3706
  }
3667
- var Link = React6.forwardRef(
3707
+ var Link = React.forwardRef(
3668
3708
  function Link2({
3669
3709
  to,
3670
3710
  params,
@@ -3881,8 +3921,8 @@ function HighlightText({
3881
3921
  transition = { duration: 2, ease: "easeInOut" },
3882
3922
  ...props
3883
3923
  }) {
3884
- const localRef = React6.useRef(null);
3885
- React6.useImperativeHandle(ref, () => localRef.current);
3924
+ const localRef = React.useRef(null);
3925
+ React.useImperativeHandle(ref, () => localRef.current);
3886
3926
  const inViewResult = useInView(localRef, {
3887
3927
  once: inViewOnce,
3888
3928
  margin: inViewMargin
@@ -4007,4 +4047,4 @@ function parseTextMarkup(text) {
4007
4047
  return parts;
4008
4048
  }
4009
4049
 
4010
- export { Avatar2 as Avatar, Button2 as Button, CopyButton, DropdownMenu2 as DropdownMenu, DropdownMenuCheckboxItem2 as DropdownMenuCheckboxItem, DropdownMenuContent2 as DropdownMenuContent, DropdownMenuGroup2 as DropdownMenuGroup, DropdownMenuItem2 as DropdownMenuItem, DropdownMenuLabel2 as DropdownMenuLabel, DropdownMenuRadioGroup2 as DropdownMenuRadioGroup, DropdownMenuRadioItem2 as DropdownMenuRadioItem, DropdownMenuSeparator2 as DropdownMenuSeparator, DropdownMenuShortcut2 as DropdownMenuShortcut, DropdownMenuSub2 as DropdownMenuSub, DropdownMenuSubContent2 as DropdownMenuSubContent, DropdownMenuSubTrigger2 as DropdownMenuSubTrigger, DropdownMenuTrigger2 as DropdownMenuTrigger, GlitchText, GradientText, Highlight, HighlightItem, HighlightText, Input, InputPassword, InvertButton, LIST_CLASS_NAMES, Link, List, Menu, ScrollArea, ScrollBar, Sheet2 as Sheet, SheetClose2 as SheetClose, SheetContent2 as SheetContent, SheetDescription2 as SheetDescription, SheetFooter2 as SheetFooter, SheetHeader2 as SheetHeader, SheetTitle2 as SheetTitle, SheetTrigger2 as SheetTrigger, ShimmeringText, Sidebar, Sidebar2, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Slot, Tooltip2 as Tooltip, Tooltip3 as Tooltip2, TooltipContent2 as TooltipContent, TooltipProvider2 as TooltipProvider, TooltipTrigger2 as TooltipTrigger, inputLabelClassName, isSidebarGroup, parseTextMarkup, useSidebar };
4050
+ export { Avatar2 as Avatar, Button2 as Button, CopyButton, DropdownMenu2 as DropdownMenu, DropdownMenuCheckboxItem2 as DropdownMenuCheckboxItem, DropdownMenuContent2 as DropdownMenuContent, DropdownMenuGroup2 as DropdownMenuGroup, DropdownMenuItem2 as DropdownMenuItem, DropdownMenuLabel2 as DropdownMenuLabel, DropdownMenuRadioGroup2 as DropdownMenuRadioGroup, DropdownMenuRadioItem2 as DropdownMenuRadioItem, DropdownMenuSeparator2 as DropdownMenuSeparator, DropdownMenuShortcut2 as DropdownMenuShortcut, DropdownMenuSub2 as DropdownMenuSub, DropdownMenuSubContent2 as DropdownMenuSubContent, DropdownMenuSubTrigger2 as DropdownMenuSubTrigger, DropdownMenuTrigger2 as DropdownMenuTrigger, GlitchText, GradientText, Highlight, HighlightItem, HighlightText, Input, InputPassword, InvertButton, LIST_CLASS_NAMES, Link, List, Menu, ScrollArea, ScrollBar, Sheet2 as Sheet, SheetClose2 as SheetClose, SheetContent2 as SheetContent, SheetDescription2 as SheetDescription, SheetFooter2 as SheetFooter, SheetHeader2 as SheetHeader, SheetTitle2 as SheetTitle, SheetTrigger2 as SheetTrigger, ShimmeringText, Sidebar, Sidebar2, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Slot, Tooltip2 as Tooltip, Tooltip3 as Tooltip2, TooltipContent2 as TooltipContent, TooltipProvider2 as TooltipProvider, TooltipTrigger2 as TooltipTrigger, buttonVariants3 as buttonVariants, inputLabelClassName, isPathPrefixOf, isSidebarGroup, parseTextMarkup, useSidebar };