gridsmith-ui 0.7.0 → 0.9.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.
package/dist/index.js CHANGED
@@ -1,18 +1,20 @@
1
+ import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from './chunk-5B2ZFL2H.js';
1
2
  import { Skeleton } from './chunk-M3AARGLI.js';
2
3
  export { Skeleton } from './chunk-M3AARGLI.js';
3
4
  import { useOverlayLayer, useCloseOnFocusOut, useReturnFocus, focusInitial, useFocusTrap, OVERLAY_CLOSE_ATTR, useNonModalDialog, rovingTabStop } from './chunk-RLUK575N.js';
4
- import { Link } from './chunk-G6KC5YNY.js';
5
- export { CodeBlock, Divider, Link } from './chunk-G6KC5YNY.js';
6
- import { Badge } from './chunk-QVNGQ64Q.js';
7
- export { Badge } from './chunk-QVNGQ64Q.js';
8
- import { useBreakpoint } from './chunk-EKQHHP72.js';
9
- export { BreakpointWidthProvider, useBreakpoint } from './chunk-EKQHHP72.js';
5
+ import { Link } from './chunk-X27PSHOH.js';
6
+ export { CodeBlock, Divider, Link } from './chunk-X27PSHOH.js';
7
+ import { Badge } from './chunk-PHQWHAT3.js';
8
+ export { Badge } from './chunk-PHQWHAT3.js';
9
+ import { inferColumnKinds } from './chunk-PDZL4A6K.js';
10
+ import { useBreakpoint, readBreakpointPx } from './chunk-CRQ6KCRD.js';
11
+ export { BreakpointWidthProvider, useBreakpoint } from './chunk-CRQ6KCRD.js';
10
12
  import { Tooltip, useTextOverflow, usePosition, Slot } from './chunk-RLNIRPOH.js';
11
13
  export { Tooltip, useTextOverflow } from './chunk-RLNIRPOH.js';
12
14
  import { useLatest } from './chunk-WH2FUFAC.js';
13
15
  import { Icon } from './chunk-X4CNZFWC.js';
14
16
  import { cn, GLASS_SURFACE, ACTIVE_RING, GLASS_BACKDROP, GLASS_DROPDOWN, lockBodyScroll, unlockBodyScroll, GLASS_OVERLAY, ERROR_ACTIVE_RING, ERROR_FOCUS_RING, FOCUS_RING, ERROR_HAS_FOCUS_RING, HAS_FOCUS_RING, ERROR_FOCUS_WITHIN_RING, FOCUS_WITHIN_RING } from './chunk-4KVFH5KC.js';
15
- import { createContext, forwardRef, useContext, useState, memo, useCallback, useRef, useEffect, useLayoutEffect, Children, useId, isValidElement, cloneElement, Fragment as Fragment$1, useMemo, useSyncExternalStore } from 'react';
17
+ import { createContext, forwardRef, useContext, useState, memo, useCallback, useRef, useEffect, isValidElement, useLayoutEffect, Children, useId, cloneElement, useMemo, Fragment as Fragment$1, useSyncExternalStore } from 'react';
16
18
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
17
19
  import { createPortal } from 'react-dom';
18
20
 
@@ -36,7 +38,8 @@ function Spinner({ size = "md", color = "default", label = "Loading", className
36
38
  }
37
39
  );
38
40
  }
39
- var ButtonSizeContext = createContext(null);
41
+ var ControlSizeContext = createContext(null);
42
+ var ButtonSizeContext = ControlSizeContext;
40
43
  var variantStyles = {
41
44
  default: "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box] text-[var(--ds-text-on-primary)] border-transparent hover:bg-[var(--ds-accent-primary-hover)] hover:brightness-110",
42
45
  secondary: "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)] border-[var(--ds-border-default)] hover:bg-[var(--ds-bg-muted)]",
@@ -51,13 +54,13 @@ var variantStyles = {
51
54
  var sizeStyles = {
52
55
  // xs / icon-xs: dense tool chrome (builder toolbars, inline row actions).
53
56
  xs: "h-ds-6 px-ds-3 py-0 text-xs",
54
- sm: "h-ds-8 px-ds-4 py-ds-1 text-xs",
55
- md: "h-ds-10 px-ds-6 py-ds-2 text-sm",
56
- lg: "h-ds-12 px-ds-8 py-ds-3 text-base",
57
+ sm: "h-[var(--ds-control-height-sm)] px-ds-4 py-ds-1 text-xs",
58
+ md: "h-[var(--ds-control-height-md)] px-ds-6 py-ds-2 text-sm",
59
+ lg: "h-[var(--ds-control-height-lg)] px-ds-8 py-ds-3 text-base",
57
60
  "icon-xs": "h-ds-6 w-ds-6 p-0",
58
- "icon-sm": "h-ds-8 w-ds-8 p-0",
59
- icon: "h-ds-10 w-ds-10 p-0",
60
- "icon-lg": "h-ds-12 w-ds-12 p-0"
61
+ "icon-sm": "h-[var(--ds-control-height-sm)] w-[var(--ds-control-height-sm)] p-0",
62
+ icon: "h-[var(--ds-control-height-md)] w-[var(--ds-control-height-md)] p-0",
63
+ "icon-lg": "h-[var(--ds-control-height-lg)] w-[var(--ds-control-height-lg)] p-0"
61
64
  };
62
65
  var linkSizeStyles = {
63
66
  xs: "text-xs",
@@ -77,7 +80,7 @@ var iconPaddingReduce = {
77
80
  };
78
81
  var HOVER_SCALE_CAP = { "--_btn-scale": "min(var(--ds-hover-scale), 1.02)" };
79
82
  var Button = forwardRef(function Button2({ variant = "default", size: sizeProp, iconLeft, iconRight, loading, className, children, disabled, style, onClick, ...props }, ref) {
80
- const contextSize = useContext(ButtonSizeContext);
83
+ const contextSize = useContext(ControlSizeContext);
81
84
  const size = sizeProp ?? contextSize ?? "md";
82
85
  const isLink = variant === "link";
83
86
  const spinnerSize = size === "lg" || size === "icon-lg" ? "md" : "sm";
@@ -336,7 +339,19 @@ function BulkActionBar({ selectedCount, actions, onClearSelection, className })
336
339
  }
337
340
  );
338
341
  }
339
- function Input({ className, size = "md", error = false, prefix, suffix, ...props }) {
342
+ var INPUT_HEIGHT = {
343
+ sm: "h-[var(--ds-control-height-sm)]",
344
+ md: "h-[var(--ds-control-height-md)]",
345
+ lg: "h-[var(--ds-control-height-lg)]"
346
+ };
347
+ var INPUT_TEXT = {
348
+ sm: "px-ds-2 py-ds-1 text-xs",
349
+ md: "px-ds-3 py-ds-2 text-sm",
350
+ lg: "px-ds-4 py-ds-3 text-base"
351
+ };
352
+ function Input({ className, size: sizeProp, error = false, prefix, suffix, ...props }) {
353
+ const contextSize = useContext(ControlSizeContext);
354
+ const size = sizeProp ?? contextSize ?? "md";
340
355
  const borderColor = error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]";
341
356
  const hoverBorder = !error && !props.disabled && !props.readOnly ? "hover:border-[var(--ds-input-border-hover)]" : "";
342
357
  if (prefix || suffix) {
@@ -345,7 +360,7 @@ function Input({ className, size = "md", error = false, prefix, suffix, ...props
345
360
  {
346
361
  className: cn(
347
362
  "flex items-center w-full",
348
- size === "sm" ? "h-[var(--ds-control-height-sm)]" : "h-[var(--ds-control-height-md)]",
363
+ INPUT_HEIGHT[size],
349
364
  "bg-[var(--ds-input-bg)]",
350
365
  "border-[length:var(--ds-border-width)]",
351
366
  borderColor,
@@ -366,7 +381,7 @@ function Input({ className, size = "md", error = false, prefix, suffix, ...props
366
381
  "aria-invalid": error || void 0,
367
382
  className: cn(
368
383
  "flex-1 min-w-0 bg-transparent outline-none",
369
- size === "sm" ? "px-ds-2 py-ds-1 text-xs" : "px-ds-3 py-ds-2 text-sm",
384
+ INPUT_TEXT[size],
370
385
  "text-[var(--ds-text-primary)]",
371
386
  "placeholder:text-[var(--ds-text-muted)]",
372
387
  "disabled:cursor-not-allowed",
@@ -386,7 +401,8 @@ function Input({ className, size = "md", error = false, prefix, suffix, ...props
386
401
  "aria-invalid": error || void 0,
387
402
  className: cn(
388
403
  "flex w-full",
389
- size === "sm" ? "px-ds-2 py-ds-1 text-xs h-[var(--ds-control-height-sm)]" : "px-ds-3 py-ds-2 text-sm h-[var(--ds-control-height-md)]",
404
+ INPUT_TEXT[size],
405
+ INPUT_HEIGHT[size],
390
406
  "bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]",
391
407
  "border-[length:var(--ds-border-width)]",
392
408
  borderColor,
@@ -428,7 +444,7 @@ function Textarea({ className, autoResize, maxRows, error = false, ref, ...props
428
444
  ref: textareaRef,
429
445
  "aria-invalid": error || void 0,
430
446
  className: cn(
431
- "flex min-h-[80px] w-full px-ds-3 py-ds-2 text-sm",
447
+ "flex min-h-[var(--ds-control-height-md)] w-full px-ds-3 py-ds-2 text-sm",
432
448
  "bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]",
433
449
  "border-[length:var(--ds-border-width)]",
434
450
  error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)] hover:border-[var(--ds-input-border-hover)]",
@@ -526,6 +542,11 @@ function Toggle({ checked, onChange, label, disabled, error = false, layout = "f
526
542
  }
527
543
  );
528
544
  }
545
+ var DROPDOWN_HEIGHT = {
546
+ sm: "px-ds-2 py-ds-1 text-xs h-[var(--ds-control-height-sm)]",
547
+ md: "px-ds-3 py-ds-2 text-sm h-[var(--ds-control-height-md)]",
548
+ lg: "px-ds-4 py-ds-3 text-base h-[var(--ds-control-height-lg)]"
549
+ };
529
550
  function Dropdown({
530
551
  options,
531
552
  value,
@@ -535,7 +556,7 @@ function Dropdown({
535
556
  placeholder = "Select...",
536
557
  multiple,
537
558
  searchable,
538
- size = "md",
559
+ size: sizeProp,
539
560
  className,
540
561
  ref,
541
562
  container,
@@ -543,6 +564,8 @@ function Dropdown({
543
564
  showChips = true,
544
565
  "aria-label": ariaLabel
545
566
  }) {
567
+ const contextSize = useContext(ControlSizeContext);
568
+ const size = sizeProp ?? contextSize ?? "md";
546
569
  const [open, setOpen] = useState(false);
547
570
  const [search, setSearch] = useState("");
548
571
  const [positioned, setPositioned] = useState(false);
@@ -710,7 +733,7 @@ function Dropdown({
710
733
  "aria-label": ariaLabel,
711
734
  className: cn(
712
735
  "w-full flex items-center justify-between gap-ds-2",
713
- size === "sm" ? "px-ds-2 py-ds-1 text-xs h-[var(--ds-control-height-sm)]" : "px-ds-3 py-ds-2 text-sm h-[var(--ds-control-height-md)]",
736
+ DROPDOWN_HEIGHT[size],
714
737
  "bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]",
715
738
  "border-[length:var(--ds-border-width)]",
716
739
  error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
@@ -847,7 +870,19 @@ function OptionButton({
847
870
  }
848
871
  );
849
872
  }
850
- function Combobox({ value, onChange, options, placeholder = "Search\u2026", disabled, loading = false, className, ref, container, error = false }) {
873
+ var CONTROL_HEIGHT = {
874
+ sm: "h-[var(--ds-control-height-sm)]",
875
+ md: "h-[var(--ds-control-height-md)]",
876
+ lg: "h-[var(--ds-control-height-lg)]"
877
+ };
878
+ var TEXT_SIZE = {
879
+ sm: "text-xs",
880
+ md: "text-sm",
881
+ lg: "text-base"
882
+ };
883
+ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disabled, loading = false, className, ref, container, error = false, size: sizeProp }) {
884
+ const contextSize = useContext(ControlSizeContext);
885
+ const size = sizeProp ?? contextSize ?? "md";
851
886
  const [open, setOpen] = useState(false);
852
887
  useOverlayLayer(open);
853
888
  const [query, setQuery] = useState("");
@@ -938,7 +973,7 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
938
973
  {
939
974
  className: cn(
940
975
  "flex items-center",
941
- "h-[var(--ds-control-height-md)]",
976
+ CONTROL_HEIGHT[size],
942
977
  "border-[length:var(--ds-border-width)]",
943
978
  error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
944
979
  "bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
@@ -974,7 +1009,9 @@ function Combobox({ value, onChange, options, placeholder = "Search\u2026", disa
974
1009
  onBlur: handleBlur,
975
1010
  onKeyDown: handleKeyDown,
976
1011
  className: cn(
977
- "flex-1 bg-transparent text-sm text-[var(--ds-text-primary)] placeholder:text-[var(--ds-text-muted)]",
1012
+ "flex-1 bg-transparent",
1013
+ TEXT_SIZE[size],
1014
+ "text-[var(--ds-text-primary)] placeholder:text-[var(--ds-text-muted)]",
978
1015
  "outline-none min-w-0",
979
1016
  "py-ds-2 px-ds-2"
980
1017
  )
@@ -1224,6 +1261,16 @@ function RadioGroup({ value, onChange, options, orientation = "vertical", classN
1224
1261
  )
1225
1262
  ] });
1226
1263
  }
1264
+ var CONTROL_HEIGHT2 = {
1265
+ sm: "h-[var(--ds-control-height-sm)]",
1266
+ md: "h-[var(--ds-control-height-md)]",
1267
+ lg: "h-[var(--ds-control-height-lg)]"
1268
+ };
1269
+ var TEXT_SIZE2 = {
1270
+ sm: "text-xs",
1271
+ md: "text-sm",
1272
+ lg: "text-base"
1273
+ };
1227
1274
  var DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
1228
1275
  var MONTHS = [
1229
1276
  "January",
@@ -1251,7 +1298,9 @@ function isSameDay(a, b) {
1251
1298
  function formatDate(d) {
1252
1299
  return `${MONTHS[d.getMonth()].slice(0, 3)} ${d.getDate()}, ${d.getFullYear()}`;
1253
1300
  }
1254
- function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, min, max, range }) {
1301
+ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, size: sizeProp, min, max, range }) {
1302
+ const contextSize = useContext(ControlSizeContext);
1303
+ const size = sizeProp ?? contextSize ?? "md";
1255
1304
  const [open, setOpen] = useState(false);
1256
1305
  const [hover, setHover] = useState(null);
1257
1306
  const [viewDate, setViewDate] = useState(() => value ?? range?.start ?? range?.end ?? /* @__PURE__ */ new Date());
@@ -1327,8 +1376,9 @@ function DatePicker({ value, onChange, placeholder = "Pick a date", disabled, cl
1327
1376
  "aria-haspopup": "dialog",
1328
1377
  "aria-expanded": open,
1329
1378
  className: cn(
1330
- "flex items-center gap-ds-2 text-sm w-full",
1331
- "h-[var(--ds-control-height-md)]",
1379
+ "flex items-center gap-ds-2 w-full",
1380
+ CONTROL_HEIGHT2[size],
1381
+ TEXT_SIZE2[size],
1332
1382
  "border-[length:var(--ds-border-width)]",
1333
1383
  error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
1334
1384
  "bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
@@ -1621,6 +1671,16 @@ function getOverlappingGroups(events) {
1621
1671
  function timeToFraction(d) {
1622
1672
  return (d.getHours() * 60 + d.getMinutes()) / (24 * 60);
1623
1673
  }
1674
+ var CONTROL_HEIGHT3 = {
1675
+ sm: "h-[var(--ds-control-height-sm)]",
1676
+ md: "h-[var(--ds-control-height-md)]",
1677
+ lg: "h-[var(--ds-control-height-lg)]"
1678
+ };
1679
+ var TEXT_SIZE3 = {
1680
+ sm: "text-xs",
1681
+ md: "text-sm",
1682
+ lg: "text-base"
1683
+ };
1624
1684
  var MONTHS2 = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
1625
1685
  function fmt(d) {
1626
1686
  return `${MONTHS2[d.getMonth()].slice(0, 3)} ${d.getDate()}, ${d.getFullYear()}`;
@@ -1661,8 +1721,11 @@ function DateRangePicker({
1661
1721
  min,
1662
1722
  max,
1663
1723
  presets = DEFAULT_DATE_RANGE_PRESETS,
1664
- weekStartsOn = 0
1724
+ weekStartsOn = 0,
1725
+ size: sizeProp
1665
1726
  }) {
1727
+ const contextSize = useContext(ControlSizeContext);
1728
+ const size = sizeProp ?? contextSize ?? "md";
1666
1729
  const [open, setOpen] = useState(false);
1667
1730
  const [viewDate, setViewDate] = useState(() => value.start ?? /* @__PURE__ */ new Date());
1668
1731
  const [hover, setHover] = useState(null);
@@ -1733,8 +1796,9 @@ function DateRangePicker({
1733
1796
  "aria-haspopup": "dialog",
1734
1797
  "aria-expanded": open,
1735
1798
  className: cn(
1736
- "flex items-center gap-ds-2 text-sm w-full",
1737
- "h-[var(--ds-control-height-md)]",
1799
+ "flex items-center gap-ds-2 w-full",
1800
+ CONTROL_HEIGHT3[size],
1801
+ TEXT_SIZE3[size],
1738
1802
  "border-[length:var(--ds-border-width)]",
1739
1803
  error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
1740
1804
  "bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
@@ -2154,6 +2218,16 @@ function SliderRange({
2154
2218
  )
2155
2219
  ] });
2156
2220
  }
2221
+ var CONTROL_HEIGHT4 = {
2222
+ sm: "h-[var(--ds-control-height-sm)]",
2223
+ md: "h-[var(--ds-control-height-md)]",
2224
+ lg: "h-[var(--ds-control-height-lg)]"
2225
+ };
2226
+ var TEXT_SIZE4 = {
2227
+ sm: "text-xs",
2228
+ md: "text-sm",
2229
+ lg: "text-base"
2230
+ };
2157
2231
  function pad(n) {
2158
2232
  return n.toString().padStart(2, "0");
2159
2233
  }
@@ -2189,8 +2263,11 @@ function TimePicker({
2189
2263
  ref,
2190
2264
  container,
2191
2265
  error = false,
2192
- id
2266
+ id,
2267
+ size: sizeProp
2193
2268
  }) {
2269
+ const contextSize = useContext(ControlSizeContext);
2270
+ const size = sizeProp ?? contextSize ?? "md";
2194
2271
  const [open, setOpen] = useState(false);
2195
2272
  const triggerRef = useRef(null);
2196
2273
  const panelRef = useRef(null);
@@ -2271,7 +2348,9 @@ function TimePicker({
2271
2348
  "aria-expanded": open,
2272
2349
  "aria-controls": open ? listboxId : void 0,
2273
2350
  className: cn(
2274
- "flex w-full items-center gap-ds-2 text-sm",
2351
+ "flex w-full items-center gap-ds-2",
2352
+ CONTROL_HEIGHT4[size],
2353
+ TEXT_SIZE4[size],
2275
2354
  "border-[length:var(--ds-border-width)]",
2276
2355
  error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
2277
2356
  "bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
@@ -2367,9 +2446,9 @@ function TimePicker({
2367
2446
  ] });
2368
2447
  }
2369
2448
  var sizes2 = {
2370
- sm: { input: "text-xs h-8", btn: "w-7 text-xs" },
2371
- md: { input: "text-sm h-10", btn: "w-9 text-sm" },
2372
- lg: { input: "text-base h-12", btn: "w-10 text-base" }
2449
+ sm: { box: "h-[var(--ds-control-height-sm)]", input: "text-xs self-stretch", btn: "w-7 text-xs" },
2450
+ md: { box: "h-[var(--ds-control-height-md)]", input: "text-sm self-stretch", btn: "w-9 text-sm" },
2451
+ lg: { box: "h-[var(--ds-control-height-lg)]", input: "text-base self-stretch", btn: "w-10 text-base" }
2373
2452
  };
2374
2453
  function NumberInput({
2375
2454
  value,
@@ -2381,12 +2460,14 @@ function NumberInput({
2381
2460
  placeholder = "0",
2382
2461
  prefix,
2383
2462
  suffix,
2384
- size = "md",
2463
+ size: sizeProp,
2385
2464
  className,
2386
2465
  error = false,
2387
2466
  allowDecimals,
2388
2467
  id
2389
2468
  }) {
2469
+ const contextSize = useContext(ControlSizeContext);
2470
+ const size = sizeProp ?? contextSize ?? "md";
2390
2471
  const intervalRef = useRef(void 0);
2391
2472
  const timeoutRef = useRef(void 0);
2392
2473
  const inputRef = useRef(null);
@@ -2479,6 +2560,7 @@ function NumberInput({
2479
2560
  {
2480
2561
  className: cn(
2481
2562
  "flex items-center w-full",
2563
+ s.box,
2482
2564
  "border-[length:var(--ds-border-width)]",
2483
2565
  error ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
2484
2566
  "rounded-[var(--ds-radius-md)]",
@@ -2802,9 +2884,9 @@ function TagInput({
2802
2884
  );
2803
2885
  }
2804
2886
  var sizes3 = {
2805
- sm: "w-8 h-8 text-sm",
2806
- md: "w-10 h-10 text-base",
2807
- lg: "w-12 h-12 text-lg"
2887
+ sm: "w-[var(--ds-control-height-sm)] h-[var(--ds-control-height-sm)] text-sm",
2888
+ md: "w-[var(--ds-control-height-md)] h-[var(--ds-control-height-md)] text-base",
2889
+ lg: "w-[var(--ds-control-height-lg)] h-[var(--ds-control-height-lg)] text-lg"
2808
2890
  };
2809
2891
  function PinInput({
2810
2892
  value,
@@ -2812,11 +2894,13 @@ function PinInput({
2812
2894
  length = 6,
2813
2895
  mask = false,
2814
2896
  disabled = false,
2815
- size = "md",
2897
+ size: sizeProp,
2816
2898
  className,
2817
2899
  error = false,
2818
2900
  id
2819
2901
  }) {
2902
+ const contextSize = useContext(ControlSizeContext);
2903
+ const size = sizeProp ?? contextSize ?? "md";
2820
2904
  const inputsRef = useRef([]);
2821
2905
  const digits = value.padEnd(length, " ").slice(0, length).split("");
2822
2906
  const focusAt = useCallback((idx) => {
@@ -3345,55 +3429,1220 @@ function Field({ label, children, hint, error, required, labelAction, id: idProp
3345
3429
  hasError && /* @__PURE__ */ jsx(InlineFieldError, { id: errorId, message: error, className: "mt-0" })
3346
3430
  ] });
3347
3431
  }
3348
- var FormCtx = createContext(null);
3349
- function useFormContext() {
3350
- const ctx = useContext(FormCtx);
3351
- if (!ctx) throw new Error("useFormContext must be used within FormWrapper");
3352
- return ctx;
3353
- }
3354
- function FormWrapper({ onSubmit, validationMode = "onSubmit", children, className, ref }) {
3355
- const [errors, setErrors] = useState({});
3356
- const [submitted, setSubmitted] = useState(false);
3357
- const errorsRef = useLatest(errors);
3358
- const pendingSubmit = useRef(false);
3359
- const onSubmitRef = useLatest(onSubmit);
3360
- useEffect(() => {
3361
- if (pendingSubmit.current && submitted) {
3362
- pendingSubmit.current = false;
3363
- onSubmitRef.current(errorsRef.current);
3432
+ var variantStyles3 = {
3433
+ info: "border-[var(--ds-accent-primary)] bg-[var(--ds-accent-subtle)]",
3434
+ success: "border-[var(--ds-status-success)] bg-[var(--ds-status-success-bg)]",
3435
+ warning: "border-[var(--ds-status-warning)] bg-[var(--ds-status-warning-bg)]",
3436
+ error: "border-[var(--ds-status-error)] bg-[var(--ds-status-error-bg)]"
3437
+ };
3438
+ var indicators = {
3439
+ info: "bg-[var(--ds-accent-primary)]",
3440
+ success: "bg-[var(--ds-status-success)]",
3441
+ warning: "bg-[var(--ds-status-warning)]",
3442
+ error: "bg-[var(--ds-status-error)]"
3443
+ };
3444
+ var actionColorsByVariant = {
3445
+ info: "text-[var(--ds-accent-primary)] hover:bg-[var(--ds-accent-muted)]",
3446
+ success: "text-[var(--ds-status-success)] hover:bg-[color-mix(in_srgb,var(--ds-status-success)_12%,transparent)]",
3447
+ warning: "text-[var(--ds-status-warning)] hover:bg-[color-mix(in_srgb,var(--ds-status-warning)_15%,transparent)]",
3448
+ error: "text-[var(--ds-status-error)] hover:bg-[color-mix(in_srgb,var(--ds-status-error)_12%,transparent)]"
3449
+ };
3450
+ var Alert = forwardRef(function Alert2({
3451
+ variant,
3452
+ title,
3453
+ children,
3454
+ dismissible,
3455
+ onDismiss,
3456
+ action,
3457
+ actions,
3458
+ placement = "inline",
3459
+ expandableContent,
3460
+ className
3461
+ }, ref) {
3462
+ const [detailsExpanded, setDetailsExpanded] = useState(false);
3463
+ const isMobile = useBreakpoint("sm");
3464
+ const resolvedActions = actions ?? (action ? [action] : []);
3465
+ const shouldCollapseActions = isMobile && resolvedActions.length > 1;
3466
+ const placementClasses = placement === "page-top" ? "sticky top-0 z-[var(--ds-z-sticky)] rounded-none" : placement === "section-top" ? "rounded-[var(--ds-radius-md)] my-ds-4" : "rounded-[var(--ds-radius-md)]";
3467
+ return /* @__PURE__ */ jsxs(
3468
+ "div",
3469
+ {
3470
+ ref,
3471
+ role: "alert",
3472
+ className: cn(
3473
+ "flex items-start gap-ds-3 p-ds-4",
3474
+ "border-[length:var(--ds-border-width)]",
3475
+ "shadow-[var(--ds-shadow-sm)]",
3476
+ "text-sm text-[var(--ds-text-primary)]",
3477
+ variantStyles3[variant],
3478
+ placementClasses,
3479
+ className
3480
+ ),
3481
+ children: [
3482
+ /* @__PURE__ */ jsx("div", { className: cn("mt-[0.3125em] w-3 h-3 shrink-0 rounded-[var(--ds-radius-sm)]", indicators[variant]) }),
3483
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
3484
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-3", children: [
3485
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
3486
+ resolvedActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: shouldCollapseActions ? /* @__PURE__ */ jsx(
3487
+ DropdownMenu,
3488
+ {
3489
+ trigger: /* @__PURE__ */ jsx(
3490
+ "button",
3491
+ {
3492
+ className: cn(
3493
+ "shrink-0 text-xs font-medium px-ds-2.5 py-ds-1 rounded-[var(--ds-radius-sm)]",
3494
+ "transition-colors cursor-pointer",
3495
+ "border-[length:var(--ds-border-width)] border-current",
3496
+ actionColorsByVariant[variant]
3497
+ ),
3498
+ children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-ds-1", children: [
3499
+ /* @__PURE__ */ jsx(Icon, { name: "more-vertical", size: 12 }),
3500
+ "Actions"
3501
+ ] })
3502
+ }
3503
+ ),
3504
+ items: resolvedActions.map((a) => ({
3505
+ label: a.label,
3506
+ onClick: a.onClick
3507
+ })),
3508
+ align: "end"
3509
+ }
3510
+ ) : resolvedActions.map((a, i) => {
3511
+ const effectiveVariant = a.variant ?? (i === 0 ? "secondary" : "outline");
3512
+ const isAccent = effectiveVariant === "secondary";
3513
+ return /* @__PURE__ */ jsxs(
3514
+ "button",
3515
+ {
3516
+ onClick: a.onClick,
3517
+ className: cn(
3518
+ "shrink-0 text-xs font-medium px-ds-2.5 py-ds-1 rounded-[var(--ds-radius-sm)]",
3519
+ "transition-colors cursor-pointer",
3520
+ isAccent ? cn("border-[length:var(--ds-border-width)] border-current", actionColorsByVariant[variant]) : cn("border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]", "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)]")
3521
+ ),
3522
+ children: [
3523
+ a.iconLeft && /* @__PURE__ */ jsx("span", { className: "inline-flex mr-ds-1", children: a.iconLeft }),
3524
+ a.label
3525
+ ]
3526
+ },
3527
+ i
3528
+ );
3529
+ }) })
3530
+ ] }),
3531
+ children && /* @__PURE__ */ jsx("div", { className: "mt-ds-1 text-xs text-[var(--ds-text-secondary)]", children }),
3532
+ expandableContent && /* @__PURE__ */ jsxs("div", { className: "mt-ds-2", children: [
3533
+ /* @__PURE__ */ jsxs(
3534
+ "button",
3535
+ {
3536
+ onClick: () => setDetailsExpanded(!detailsExpanded),
3537
+ "aria-expanded": detailsExpanded,
3538
+ className: cn(
3539
+ "inline-flex items-center gap-ds-1 text-xs font-medium cursor-pointer",
3540
+ "transition-colors duration-[var(--ds-transition-speed)]",
3541
+ actionColorsByVariant[variant],
3542
+ "rounded-[var(--ds-radius-sm)] px-ds-1.5 py-ds-0.5"
3543
+ ),
3544
+ children: [
3545
+ /* @__PURE__ */ jsx(
3546
+ Icon,
3547
+ {
3548
+ name: "chevron-right",
3549
+ size: 12,
3550
+ className: cn("transition-transform duration-[var(--ds-transition-speed)]", detailsExpanded && "rotate-90")
3551
+ }
3552
+ ),
3553
+ detailsExpanded ? "Hide details" : "Show details"
3554
+ ]
3555
+ }
3556
+ ),
3557
+ detailsExpanded && /* @__PURE__ */ jsx("div", { className: "mt-ds-2 text-xs text-[var(--ds-text-secondary)] border-l-2 border-current/20 pl-ds-3", children: expandableContent })
3558
+ ] })
3559
+ ] }),
3560
+ dismissible && /* @__PURE__ */ jsx(
3561
+ "button",
3562
+ {
3563
+ onClick: onDismiss,
3564
+ className: "shrink-0 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
3565
+ "aria-label": "Dismiss",
3566
+ children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 })
3567
+ }
3568
+ )
3569
+ ]
3570
+ }
3571
+ );
3572
+ });
3573
+ var CardCtx = createContext(false);
3574
+ var CardSurfaceCtx = createContext(false);
3575
+ var variantStyles4 = {
3576
+ default: `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] ${GLASS_SURFACE}`,
3577
+ featured: [
3578
+ `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] ${GLASS_SURFACE}`,
3579
+ "[transition:var(--ds-transition-ambient)]",
3580
+ "hover:scale-[var(--ds-ambient-hover-scale)] hover:-translate-y-[var(--ds-ambient-hover-lift)]"
3581
+ ].join(" "),
3582
+ interactive: [
3583
+ `bg-[var(--ds-bg-surface)] cursor-pointer ${GLASS_SURFACE}`,
3584
+ "border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
3585
+ "[transition:var(--ds-transition-interactive)]",
3586
+ "hover:border-[var(--ds-accent-primary)] hover:shadow-[var(--ds-shadow-card),var(--ds-glass-inset)] hover:bg-[var(--ds-bg-surface-elevated)]",
3587
+ "hover:scale-[var(--_card-scale)] hover:-translate-y-[var(--ds-hover-lift)]"
3588
+ ].join(" "),
3589
+ outline: `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] ${GLASS_SURFACE}`,
3590
+ ghost: "bg-transparent border-none shadow-none"
3591
+ };
3592
+ var INTERACTIVE_SCALE_CAP = { "--_card-scale": "min(var(--ds-hover-scale), 1.04)" };
3593
+ function RadioIndicator({ checked, disabled }) {
3594
+ return /* @__PURE__ */ jsx(
3595
+ "span",
3596
+ {
3597
+ className: cn(
3598
+ "flex items-center justify-center shrink-0 rounded-[var(--ds-radius-full)]",
3599
+ "h-[18px] w-[18px]",
3600
+ "border-[length:var(--ds-border-width)] bg-[var(--ds-input-bg)]",
3601
+ "transition-colors duration-[var(--ds-transition-speed)]",
3602
+ disabled && "opacity-disabled",
3603
+ checked ? "border-[var(--ds-check-border)]" : "border-[var(--ds-input-border)]"
3604
+ ),
3605
+ children: /* @__PURE__ */ jsx(
3606
+ "span",
3607
+ {
3608
+ className: cn(
3609
+ "h-2.5 w-2.5 rounded-[var(--ds-radius-full)] transition-transform duration-[var(--ds-transition-speed)]",
3610
+ checked ? "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] scale-100" : "scale-0"
3611
+ )
3612
+ }
3613
+ )
3364
3614
  }
3365
- }, [submitted, errors, errorsRef, onSubmitRef]);
3366
- const setError = useCallback((field, message) => {
3367
- setErrors((prev) => ({ ...prev, [field]: message }));
3368
- }, []);
3369
- const clearErrors = useCallback(() => {
3370
- setErrors({});
3371
- setSubmitted(false);
3372
- }, []);
3373
- const handleSubmit = useCallback(
3374
- (e) => {
3375
- e.preventDefault();
3376
- pendingSubmit.current = true;
3377
- setSubmitted(true);
3378
- },
3379
- []
3380
3615
  );
3381
- return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted }, children: /* @__PURE__ */ jsx("form", { ref, onSubmit: handleSubmit, className, noValidate: true, children }) });
3382
3616
  }
3383
- function TransferList({
3384
- available,
3385
- selected,
3386
- onChange,
3387
- availableTitle = "Available",
3388
- selectedTitle = "Selected",
3389
- searchable = true,
3390
- className,
3391
- ref
3392
- }) {
3393
- const [checkedAvailable, setCheckedAvailable] = useState(/* @__PURE__ */ new Set());
3394
- const [checkedSelected, setCheckedSelected] = useState(/* @__PURE__ */ new Set());
3395
- const [searchLeft, setSearchLeft] = useState("");
3396
- const [searchRight, setSearchRight] = useState("");
3617
+ function CheckboxIndicator({ checked, indeterminate, disabled }) {
3618
+ const filled = checked || indeterminate;
3619
+ return /* @__PURE__ */ jsx(
3620
+ "span",
3621
+ {
3622
+ className: cn(
3623
+ "flex items-center justify-center shrink-0",
3624
+ "h-[18px] w-[18px]",
3625
+ "rounded-[calc(var(--ds-radius-sm)*0.6)]",
3626
+ "border-[2px] transition-all duration-[var(--ds-transition-speed)]",
3627
+ disabled && "opacity-disabled",
3628
+ filled ? "bg-[var(--ds-check-bg)] [background-image:var(--ds-gradient)] border-[var(--ds-check-border)]" : "bg-[var(--ds-input-bg)] border-[var(--ds-input-border)]"
3629
+ ),
3630
+ children: /* @__PURE__ */ jsx(
3631
+ "svg",
3632
+ {
3633
+ width: "12",
3634
+ height: "12",
3635
+ viewBox: "0 0 12 12",
3636
+ fill: "none",
3637
+ className: cn(
3638
+ "text-[var(--ds-check-fg)] transition-opacity",
3639
+ filled ? "opacity-100" : "opacity-0"
3640
+ ),
3641
+ children: indeterminate ? /* @__PURE__ */ jsx("path", { d: "M3 6H9", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }) : /* @__PURE__ */ jsx("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })
3642
+ }
3643
+ )
3644
+ }
3645
+ );
3646
+ }
3647
+ function ToggleIndicator({ checked, disabled }) {
3648
+ return /* @__PURE__ */ jsx(
3649
+ "span",
3650
+ {
3651
+ className: cn(
3652
+ "relative inline-flex shrink-0 items-center overflow-hidden",
3653
+ "border-[length:var(--ds-border-width)] rounded-[var(--ds-radius-full)]",
3654
+ "transition-colors duration-[var(--ds-transition-speed)]",
3655
+ disabled && "opacity-disabled",
3656
+ checked ? "bg-[var(--ds-accent-primary)] border-transparent" : "bg-[var(--ds-bg-muted)] border-[var(--ds-border-default)]"
3657
+ ),
3658
+ style: { width: 44, height: 24 },
3659
+ children: /* @__PURE__ */ jsx(
3660
+ "span",
3661
+ {
3662
+ className: "pointer-events-none inline-block shrink-0 bg-[var(--ds-bg-surface)] rounded-[var(--ds-radius-full)] transition-transform",
3663
+ style: {
3664
+ width: 16,
3665
+ height: 16,
3666
+ transform: checked ? "translateX(calc(25px - var(--ds-border-width)))" : "translateX(calc(1px + var(--ds-border-width)))"
3667
+ }
3668
+ }
3669
+ )
3670
+ }
3671
+ );
3672
+ }
3673
+ var Card = forwardRef(function Card2({
3674
+ variant = "default",
3675
+ loading = false,
3676
+ selected,
3677
+ selectable,
3678
+ selectType,
3679
+ onSelectedChange,
3680
+ name,
3681
+ indeterminate,
3682
+ disabled = false,
3683
+ checkable = false,
3684
+ className,
3685
+ children,
3686
+ onClick,
3687
+ style,
3688
+ ...props
3689
+ }, ref) {
3690
+ const isSelectable = selectable || !!selectType;
3691
+ const isToggle = selectType === "toggle";
3692
+ const hasSelectType = !!selectType;
3693
+ const handleClick = isSelectable && !disabled ? (e) => {
3694
+ onSelectedChange?.(!selected);
3695
+ onClick?.(e);
3696
+ } : onClick;
3697
+ const handleKeyDown = isSelectable && !disabled ? (e) => {
3698
+ if (e.key === "Enter" || e.key === " ") {
3699
+ e.preventDefault();
3700
+ onSelectedChange?.(!selected);
3701
+ }
3702
+ } : void 0;
3703
+ const handleCheckableClick = (e) => {
3704
+ e.stopPropagation();
3705
+ onSelectedChange?.(!selected);
3706
+ };
3707
+ const role = selectType === "radio" ? "radio" : selectType === "checkbox" ? "checkbox" : selectType === "toggle" ? "switch" : isSelectable ? "button" : void 0;
3708
+ const ariaAttr = selectType === "radio" || selectType === "checkbox" || selectType === "toggle" ? { "aria-checked": !!selected } : isSelectable ? { "aria-pressed": !!selected } : {};
3709
+ const showRing = isSelectable && !isToggle && !hasSelectType && selected;
3710
+ const indicator = selectType === "radio" ? /* @__PURE__ */ jsx(RadioIndicator, { checked: !!selected, disabled }) : selectType === "checkbox" ? /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected, indeterminate, disabled }) : selectType === "toggle" ? /* @__PURE__ */ jsx(ToggleIndicator, { checked: !!selected, disabled }) : null;
3711
+ const defaultCheckBadge = !hasSelectType && !checkable && selected && !loading ? /* @__PURE__ */ jsx("div", { className: "absolute top-ds-3 right-ds-3 w-5 h-5 rounded-[var(--ds-radius-full)] bg-[var(--ds-accent-primary)] flex items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { name: "check", size: 12, className: "text-[var(--ds-text-on-primary)]" }) }) : null;
3712
+ return /* @__PURE__ */ jsxs(
3713
+ "div",
3714
+ {
3715
+ ref,
3716
+ "data-card": "",
3717
+ role,
3718
+ tabIndex: isSelectable ? 0 : void 0,
3719
+ "aria-disabled": isSelectable && disabled ? true : void 0,
3720
+ ...name && selectType === "radio" ? { "data-radio-group": name } : {},
3721
+ style: variant === "interactive" ? { ...INTERACTIVE_SCALE_CAP, ...style } : style,
3722
+ className: cn(
3723
+ "rounded-[var(--ds-radius-md)] flex flex-col relative",
3724
+ variantStyles4[variant],
3725
+ isSelectable && !disabled && "cursor-pointer select-none transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
3726
+ isSelectable && !disabled && !selected && "hover:border-[var(--ds-accent-primary)]",
3727
+ isSelectable && "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
3728
+ (showRing || hasSelectType && selected) && ACTIVE_RING,
3729
+ hasSelectType && selected && "bg-[var(--ds-accent-subtle)]",
3730
+ disabled && "opacity-disabled cursor-not-allowed",
3731
+ className
3732
+ ),
3733
+ onClick: handleClick,
3734
+ onKeyDown: handleKeyDown,
3735
+ ...ariaAttr,
3736
+ ...props,
3737
+ children: [
3738
+ defaultCheckBadge,
3739
+ indicator && /* @__PURE__ */ jsx("div", { className: "absolute top-ds-3 right-ds-3 z-[1]", children: indicator }),
3740
+ checkable && /* @__PURE__ */ jsx(
3741
+ "div",
3742
+ {
3743
+ className: "absolute top-ds-3 left-ds-3 z-[1] cursor-pointer",
3744
+ onClick: handleCheckableClick,
3745
+ role: "checkbox",
3746
+ "aria-checked": !!selected,
3747
+ tabIndex: 0,
3748
+ onKeyDown: (e) => {
3749
+ if (e.key === "Enter" || e.key === " ") {
3750
+ e.preventDefault();
3751
+ e.stopPropagation();
3752
+ onSelectedChange?.(!selected);
3753
+ }
3754
+ },
3755
+ children: /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected })
3756
+ }
3757
+ ),
3758
+ /* @__PURE__ */ jsx(CardSurfaceCtx, { value: true, children: /* @__PURE__ */ jsx(CardCtx, { value: checkable, children: loading ? /* @__PURE__ */ jsxs("div", { className: "space-y-ds-3", children: [
3759
+ /* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-4 w-1/3" }),
3760
+ /* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-full" }),
3761
+ /* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-2/3" })
3762
+ ] }) : children }) })
3763
+ ]
3764
+ }
3765
+ );
3766
+ });
3767
+ var CardHeader = forwardRef(function CardHeader2({ className, children, actions, icon, menuItems, ...props }, ref) {
3768
+ const isCheckable = useContext(CardCtx);
3769
+ const hasActions = actions || menuItems;
3770
+ const pl = isCheckable ? "pl-ds-10" : "pl-ds-5";
3771
+ const actionsBlock = hasActions ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 shrink-0", children: [
3772
+ actions,
3773
+ menuItems && /* @__PURE__ */ jsx(
3774
+ DropdownMenu,
3775
+ {
3776
+ trigger: /* @__PURE__ */ jsx(
3777
+ "button",
3778
+ {
3779
+ type: "button",
3780
+ className: cn(
3781
+ "inline-flex items-center justify-center h-8 w-8 rounded-[var(--ds-radius-md)]",
3782
+ "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]",
3783
+ "transition-colors duration-[var(--ds-transition-speed)]"
3784
+ ),
3785
+ onClick: (e) => e.stopPropagation(),
3786
+ children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: 16 })
3787
+ }
3788
+ ),
3789
+ items: menuItems
3790
+ }
3791
+ )
3792
+ ] }) : null;
3793
+ const iconBlock = icon ? /* @__PURE__ */ jsx("span", { className: "shrink-0 h-10 w-10 rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-muted)] flex items-center justify-center mb-ds-1", children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 20, className: "text-[var(--ds-text-secondary)]" }) }) : null;
3794
+ if (hasActions) {
3795
+ return /* @__PURE__ */ jsx("div", { ref, className: cn(pl, "pr-ds-5 pt-ds-4 last:pb-ds-4", className), ...props, children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-ds-4", children: [
3796
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-ds-1.5 min-w-0", children: [
3797
+ iconBlock,
3798
+ children
3799
+ ] }),
3800
+ actionsBlock
3801
+ ] }) });
3802
+ }
3803
+ return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col space-y-ds-1.5 pr-ds-5 pt-ds-4 last:pb-ds-4", pl, className), ...props, children: [
3804
+ iconBlock,
3805
+ children
3806
+ ] });
3807
+ });
3808
+ var cardLineClampClasses = {
3809
+ 1: "truncate",
3810
+ 2: "line-clamp-2",
3811
+ 3: "line-clamp-3",
3812
+ 4: "line-clamp-4",
3813
+ 5: "line-clamp-5",
3814
+ 6: "line-clamp-6"
3815
+ };
3816
+ var CardTitle = forwardRef(function CardTitle2({ className, children, lines = 2, ...props }, forwardedRef) {
3817
+ const { ref: overflowRef, isTruncated } = useTextOverflow({ lines, disabled: lines === 0 });
3818
+ const lineClampClass = lines > 0 ? cardLineClampClasses[lines] || `line-clamp-[${lines}]` : "";
3819
+ const heading = /* @__PURE__ */ jsx(
3820
+ "h3",
3821
+ {
3822
+ ref: (node) => {
3823
+ overflowRef(lines > 0 ? node : null);
3824
+ if (typeof forwardedRef === "function") forwardedRef(node);
3825
+ else if (forwardedRef) forwardedRef.current = node;
3826
+ },
3827
+ className: cn("font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", lines > 0 && lineClampClass, className),
3828
+ ...props,
3829
+ children
3830
+ }
3831
+ );
3832
+ if (!isTruncated || lines === 0) return heading;
3833
+ return /* @__PURE__ */ jsx(Tooltip, { content: children, children: heading });
3834
+ });
3835
+ var CardDescription = forwardRef(function CardDescription2({ className, children, lines = 2, ...props }, forwardedRef) {
3836
+ const { ref: overflowRef, isTruncated } = useTextOverflow({ lines, disabled: lines === 0 });
3837
+ const lineClampClass = lines > 0 ? cardLineClampClasses[lines] || `line-clamp-[${lines}]` : "";
3838
+ const el = /* @__PURE__ */ jsx(
3839
+ "p",
3840
+ {
3841
+ ref: (node) => {
3842
+ if (lines > 0) overflowRef(node);
3843
+ if (typeof forwardedRef === "function") forwardedRef(node);
3844
+ else if (forwardedRef) forwardedRef.current = node;
3845
+ },
3846
+ className: cn("text-sm text-[var(--ds-text-muted)]", lines > 0 && lineClampClass, className),
3847
+ ...props,
3848
+ children
3849
+ }
3850
+ );
3851
+ if (!isTruncated || lines === 0) return el;
3852
+ return /* @__PURE__ */ jsx(Tooltip, { content: children, children: el });
3853
+ });
3854
+ var CardContent = forwardRef(function CardContent2({ className, children, ...props }, ref) {
3855
+ const isCheckable = useContext(CardCtx);
3856
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("flex-1 pr-ds-5 py-ds-4", isCheckable ? "pl-ds-10" : "pl-ds-5", className), ...props, children });
3857
+ });
3858
+ var CardFooter = forwardRef(function CardFooter2({ className, children, ...props }, ref) {
3859
+ const isCheckable = useContext(CardCtx);
3860
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center pr-ds-5 pb-ds-4 pt-ds-2 mt-auto min-w-0", isCheckable ? "pl-ds-10" : "pl-ds-5", className), ...props, children });
3861
+ });
3862
+ function transitionMs(el) {
3863
+ const cs = getComputedStyle(el);
3864
+ const parse = (list) => list.split(",").map((raw) => {
3865
+ const s = raw.trim();
3866
+ if (!s) return 0;
3867
+ const n = parseFloat(s);
3868
+ if (Number.isNaN(n)) return 0;
3869
+ return s.endsWith("ms") ? n : n * 1e3;
3870
+ });
3871
+ const durations = parse(cs.transitionDuration || "0s");
3872
+ const delays = parse(cs.transitionDelay || "0s");
3873
+ let max = 0;
3874
+ durations.forEach((d, i) => {
3875
+ const total = d + (delays[i] ?? delays[0] ?? 0);
3876
+ if (total > max) max = total;
3877
+ });
3878
+ return max;
3879
+ }
3880
+ function useCloseSettle(open, elRef, onSettled) {
3881
+ const cb = useLatest(onSettled);
3882
+ useEffect(() => {
3883
+ if (open) return;
3884
+ const el = elRef.current;
3885
+ const ms = el ? transitionMs(el) : 0;
3886
+ let done = false;
3887
+ const finish = () => {
3888
+ if (done) return;
3889
+ done = true;
3890
+ cb.current();
3891
+ };
3892
+ if (!el || ms === 0) {
3893
+ const t2 = setTimeout(finish, 0);
3894
+ return () => clearTimeout(t2);
3895
+ }
3896
+ const onEnd = (e) => {
3897
+ if (e.target === el) finish();
3898
+ };
3899
+ el.addEventListener("transitionend", onEnd);
3900
+ const t = setTimeout(finish, ms + 50);
3901
+ return () => {
3902
+ el.removeEventListener("transitionend", onEnd);
3903
+ clearTimeout(t);
3904
+ };
3905
+ }, [open, elRef, cb]);
3906
+ }
3907
+ var STEP = 16;
3908
+ var BIG_STEP = 64;
3909
+ function clamp(v, min, max) {
3910
+ return Math.min(Math.max(v, min), max);
3911
+ }
3912
+ function ResizeEdge({ edge, width, min, max, defaultWidth, onResize, label, onDraggingChange, className }) {
3913
+ const [dragging, setDragging] = useState(false);
3914
+ const start = useRef(null);
3915
+ const latestOnResize = useLatest(onResize);
3916
+ const direction = edge === "left" ? -1 : 1;
3917
+ const onPointerDown = useCallback(
3918
+ (e) => {
3919
+ if (e.button !== 0) return;
3920
+ e.preventDefault();
3921
+ start.current = { x: e.clientX, width };
3922
+ setDragging(true);
3923
+ e.currentTarget.setPointerCapture(e.pointerId);
3924
+ },
3925
+ [width]
3926
+ );
3927
+ const onPointerMove = useCallback(
3928
+ (e) => {
3929
+ if (!start.current) return;
3930
+ const next = clamp(start.current.width + direction * (e.clientX - start.current.x), min, max());
3931
+ latestOnResize.current(next);
3932
+ },
3933
+ [direction, min, max, latestOnResize]
3934
+ );
3935
+ const endDrag = useCallback(() => {
3936
+ start.current = null;
3937
+ setDragging(false);
3938
+ }, []);
3939
+ const latestOnDraggingChange = useLatest(onDraggingChange);
3940
+ useEffect(() => {
3941
+ latestOnDraggingChange.current?.(dragging);
3942
+ }, [dragging, latestOnDraggingChange]);
3943
+ useEffect(() => {
3944
+ if (!dragging) return;
3945
+ const onKey = (e) => {
3946
+ if (e.key !== "Escape" || !start.current) return;
3947
+ latestOnResize.current(start.current.width);
3948
+ endDrag();
3949
+ };
3950
+ document.addEventListener("keydown", onKey);
3951
+ return () => document.removeEventListener("keydown", onKey);
3952
+ }, [dragging, endDrag, latestOnResize]);
3953
+ const onKeyDown = (e) => {
3954
+ const step = e.shiftKey ? BIG_STEP : STEP;
3955
+ let next = null;
3956
+ if (e.key === "ArrowLeft") next = width - direction * step;
3957
+ else if (e.key === "ArrowRight") next = width + direction * step;
3958
+ else if (e.key === "Home") next = min;
3959
+ else if (e.key === "End") next = max();
3960
+ else if (e.key === "Enter") next = defaultWidth;
3961
+ if (next === null) return;
3962
+ e.preventDefault();
3963
+ onResize(clamp(next, min, max()));
3964
+ };
3965
+ return /* @__PURE__ */ jsx(
3966
+ "div",
3967
+ {
3968
+ role: "separator",
3969
+ tabIndex: 0,
3970
+ "aria-orientation": "vertical",
3971
+ "aria-label": label,
3972
+ "aria-valuemin": min,
3973
+ "aria-valuemax": max(),
3974
+ "aria-valuenow": Math.round(width),
3975
+ "data-resize-edge": edge,
3976
+ "data-dragging": dragging || void 0,
3977
+ onPointerDown,
3978
+ onPointerMove,
3979
+ onPointerUp: endDrag,
3980
+ onPointerCancel: endDrag,
3981
+ onDoubleClick: () => onResize(clamp(defaultWidth, min, max())),
3982
+ onKeyDown,
3983
+ className: cn(
3984
+ // A narrow absolutely-positioned strip over the edge — never a flex child that takes width.
3985
+ "group/edge absolute top-0 bottom-0 z-10 w-ds-2 cursor-col-resize touch-none select-none outline-none",
3986
+ edge === "left" ? "-left-ds-1" : "-right-ds-1",
3987
+ className
3988
+ ),
3989
+ children: /* @__PURE__ */ jsx(
3990
+ "div",
3991
+ {
3992
+ "aria-hidden": "true",
3993
+ className: cn(
3994
+ "absolute top-0 bottom-0 left-1/2 w-px -translate-x-1/2 transition-[width,background-color] duration-[var(--ds-transition-speed)]",
3995
+ "group-hover/edge:w-[3px] group-hover/edge:bg-[var(--ds-accent-primary)]",
3996
+ "group-focus-visible/edge:w-[3px] group-focus-visible/edge:bg-[var(--ds-accent-primary)]",
3997
+ dragging && "w-[3px] bg-[var(--ds-accent-primary)]"
3998
+ )
3999
+ }
4000
+ )
4001
+ }
4002
+ );
4003
+ }
4004
+ var remembered = /* @__PURE__ */ new Map();
4005
+ function useRememberedWidth(key) {
4006
+ const [width, setWidth] = useState(() => key ? remembered.get(key) ?? null : null);
4007
+ const remember = useCallback(
4008
+ (w) => {
4009
+ setWidth(w);
4010
+ if (!key) return;
4011
+ if (w === null) remembered.delete(key);
4012
+ else remembered.set(key, w);
4013
+ },
4014
+ [key]
4015
+ );
4016
+ return [width, remember];
4017
+ }
4018
+ function pxOf(length) {
4019
+ if (!length) return null;
4020
+ const m = /^(\d+(?:\.\d+)?)px$/.exec(length.trim());
4021
+ return m ? parseFloat(m[1]) : null;
4022
+ }
4023
+ function defaultMaxWidth(container) {
4024
+ const base = container instanceof HTMLElement ? container.clientWidth : typeof window !== "undefined" ? window.innerWidth : 1200;
4025
+ return Math.round(base * 0.6);
4026
+ }
4027
+ function useDirtyGuard(dirty, onClose, onDiscard) {
4028
+ const [confirming, setConfirming] = useState(false);
4029
+ useEffect(() => {
4030
+ if (!dirty) setConfirming(false);
4031
+ }, [dirty]);
4032
+ const requestClose = useCallback(() => {
4033
+ if (!dirty) {
4034
+ onClose();
4035
+ return;
4036
+ }
4037
+ setConfirming((c) => !c);
4038
+ }, [dirty, onClose]);
4039
+ const keep = useCallback(() => setConfirming(false), []);
4040
+ const discard = useCallback(() => {
4041
+ setConfirming(false);
4042
+ onDiscard?.();
4043
+ onClose();
4044
+ }, [onClose, onDiscard]);
4045
+ return { confirming, requestClose, keep, discard };
4046
+ }
4047
+ function DiscardConfirm({ open, onKeep, onDiscard }) {
4048
+ const keepRef = useRef(null);
4049
+ const returnTo = useRef(null);
4050
+ const overlay = useRef(null);
4051
+ useEffect(() => {
4052
+ if (!open) return;
4053
+ const active = document.activeElement instanceof HTMLElement ? document.activeElement : null;
4054
+ overlay.current = keepRef.current?.closest("[role='dialog'], [role='alertdialog']") ?? null;
4055
+ returnTo.current = active && active !== document.body && overlay.current?.contains(active) ? active : null;
4056
+ keepRef.current?.focus();
4057
+ return () => {
4058
+ if (document.activeElement !== document.body) return;
4059
+ const back = returnTo.current;
4060
+ if (back && back.isConnected) {
4061
+ back.focus();
4062
+ return;
4063
+ }
4064
+ const first = overlay.current?.querySelector("button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex='-1'])");
4065
+ (first ?? overlay.current)?.focus();
4066
+ };
4067
+ }, [open]);
4068
+ if (!open) return null;
4069
+ return /* @__PURE__ */ jsxs(
4070
+ "div",
4071
+ {
4072
+ role: "group",
4073
+ "aria-label": "Unsaved changes",
4074
+ "data-discard-confirm": "",
4075
+ className: "shrink-0 flex flex-wrap items-center justify-between gap-ds-3 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-status-warning-bg)]",
4076
+ style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
4077
+ children: [
4078
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-[var(--ds-text-primary)]", children: "You have unsaved changes." }),
4079
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
4080
+ /* @__PURE__ */ jsx(Button, { ref: keepRef, variant: "secondary", size: "sm", onClick: onKeep, children: "Keep editing" }),
4081
+ /* @__PURE__ */ jsx(Button, { variant: "destructive", size: "sm", onClick: onDiscard, children: "Discard changes" })
4082
+ ] })
4083
+ ]
4084
+ }
4085
+ );
4086
+ }
4087
+ function Sheet({ open, onClose, title, children, footer, confirm, snapPoints = [0.5, 0.92], container, flush, keepMounted = false, id, labelledBy }) {
4088
+ const titleId = useId();
4089
+ const panelRef = useRef(null);
4090
+ const [mounted, setMounted] = useState(open);
4091
+ const [hidden, setHidden] = useState(!open);
4092
+ const [snapIdx, setSnapIdx] = useState(0);
4093
+ const [dragOffset, setDragOffset] = useState(0);
4094
+ const [dragging, setDragging] = useState(false);
4095
+ const dragStartY = useRef(0);
4096
+ const startHeight = useRef(0);
4097
+ const onCloseRef = useLatest(onClose);
4098
+ const [prevOpen, setPrevOpen] = useState(open);
4099
+ if (open !== prevOpen) {
4100
+ setPrevOpen(open);
4101
+ if (open) {
4102
+ setMounted(true);
4103
+ setHidden(false);
4104
+ setSnapIdx(0);
4105
+ setDragOffset(0);
4106
+ }
4107
+ }
4108
+ const viewportHeight = useCallback(
4109
+ () => container instanceof HTMLElement ? container.clientHeight : window.innerHeight,
4110
+ [container]
4111
+ );
4112
+ useCloseSettle(open, panelRef, () => {
4113
+ if (keepMounted) setHidden(true);
4114
+ else setMounted(false);
4115
+ });
4116
+ useReturnFocus(open);
4117
+ useEffect(() => {
4118
+ if (!open || !mounted) return;
4119
+ const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
4120
+ return () => cancelAnimationFrame(raf);
4121
+ }, [open, mounted]);
4122
+ const isTopLayer = useOverlayLayer(open);
4123
+ useFocusTrap(panelRef, open, isTopLayer);
4124
+ useEffect(() => {
4125
+ if (!open) return;
4126
+ const onKeyDown = (e) => {
4127
+ if (e.key === "Escape" && isTopLayer()) onCloseRef.current();
4128
+ };
4129
+ document.addEventListener("keydown", onKeyDown);
4130
+ if (!container) lockBodyScroll();
4131
+ return () => {
4132
+ document.removeEventListener("keydown", onKeyDown);
4133
+ if (!container) unlockBodyScroll();
4134
+ };
4135
+ }, [open, container, onCloseRef, isTopLayer]);
4136
+ const handlePointerDown = useCallback((e) => {
4137
+ setDragging(true);
4138
+ dragStartY.current = e.clientY;
4139
+ startHeight.current = (snapPoints[snapIdx] ?? snapPoints[0]) * viewportHeight();
4140
+ setDragOffset(0);
4141
+ e.target.setPointerCapture(e.pointerId);
4142
+ }, [snapIdx, snapPoints, viewportHeight]);
4143
+ const handlePointerMove = useCallback((e) => {
4144
+ if (!dragging) return;
4145
+ const delta = dragStartY.current - e.clientY;
4146
+ setDragOffset(delta);
4147
+ }, [dragging]);
4148
+ const handlePointerUp = useCallback(() => {
4149
+ if (!dragging) return;
4150
+ setDragging(false);
4151
+ const currentHeightPx = startHeight.current + dragOffset;
4152
+ const currentFraction = currentHeightPx / viewportHeight();
4153
+ if (currentFraction < snapPoints[0] * 0.6) {
4154
+ onClose();
4155
+ setDragOffset(0);
4156
+ return;
4157
+ }
4158
+ let bestIdx = 0;
4159
+ let bestDist = Math.abs(currentFraction - snapPoints[0]);
4160
+ for (let i = 1; i < snapPoints.length; i++) {
4161
+ const dist = Math.abs(currentFraction - snapPoints[i]);
4162
+ if (dist < bestDist) {
4163
+ bestDist = dist;
4164
+ bestIdx = i;
4165
+ }
4166
+ }
4167
+ setSnapIdx(bestIdx);
4168
+ setDragOffset(0);
4169
+ }, [dragging, dragOffset, snapPoints, onClose, viewportHeight]);
4170
+ if (!mounted) return null;
4171
+ const baseHeight = (snapPoints[snapIdx] ?? snapPoints[0]) * 100;
4172
+ const heightUnit = container ? "%" : "vh";
4173
+ const dragPx = dragging ? dragOffset : 0;
4174
+ const positionClass = container ? "absolute" : "fixed";
4175
+ return createPortal(
4176
+ /* @__PURE__ */ jsxs(
4177
+ "div",
4178
+ {
4179
+ hidden: keepMounted && hidden ? true : void 0,
4180
+ className: cn(
4181
+ `${positionClass} inset-0 z-[var(--ds-z-modal)] transition-opacity duration-[var(--ds-transition-speed)]`,
4182
+ open ? "pointer-events-auto" : "pointer-events-none"
4183
+ ),
4184
+ children: [
4185
+ /* @__PURE__ */ jsx(
4186
+ "div",
4187
+ {
4188
+ className: cn(
4189
+ "absolute inset-0 bg-black/50 transition-opacity duration-[var(--ds-transition-speed)]",
4190
+ open ? "opacity-100" : "opacity-0"
4191
+ ),
4192
+ onClick: onClose
4193
+ }
4194
+ ),
4195
+ /* @__PURE__ */ jsxs(
4196
+ "div",
4197
+ {
4198
+ ref: panelRef,
4199
+ id,
4200
+ role: "dialog",
4201
+ "aria-modal": "true",
4202
+ "aria-labelledby": title ? titleId : labelledBy,
4203
+ "data-ds-sheet": "",
4204
+ className: cn(
4205
+ `${positionClass} bottom-0 left-0 right-0 z-10 flex flex-col`,
4206
+ "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
4207
+ GLASS_OVERLAY,
4208
+ "border-t-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
4209
+ "rounded-t-[var(--ds-radius-xl)]",
4210
+ !dragging && "transition-[transform,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
4211
+ open ? "translate-y-0" : "translate-y-full"
4212
+ ),
4213
+ style: {
4214
+ containerType: "inline-size",
4215
+ height: dragPx ? `calc(${baseHeight}${heightUnit} + ${dragPx}px)` : `${baseHeight}${heightUnit}`
4216
+ },
4217
+ children: [
4218
+ /* @__PURE__ */ jsx(
4219
+ "div",
4220
+ {
4221
+ className: "flex justify-center pt-ds-2 pb-ds-1 cursor-grab active:cursor-grabbing touch-none",
4222
+ onPointerDown: handlePointerDown,
4223
+ onPointerMove: handlePointerMove,
4224
+ onPointerUp: handlePointerUp,
4225
+ onPointerCancel: handlePointerUp,
4226
+ children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-[var(--ds-radius-full)] bg-[var(--ds-border-default)]" })
4227
+ }
4228
+ ),
4229
+ title && /* @__PURE__ */ jsxs(
4230
+ "div",
4231
+ {
4232
+ className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
4233
+ style: { padding: "var(--ds-space-2) var(--ds-space-5)" },
4234
+ children: [
4235
+ /* @__PURE__ */ jsx("h2", { id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
4236
+ /* @__PURE__ */ jsx(
4237
+ "button",
4238
+ {
4239
+ onClick: onClose,
4240
+ ...{ [OVERLAY_CLOSE_ATTR]: "" },
4241
+ className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
4242
+ "aria-label": "Close",
4243
+ children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
4244
+ }
4245
+ )
4246
+ ]
4247
+ }
4248
+ ),
4249
+ /* @__PURE__ */ jsx(
4250
+ "div",
4251
+ {
4252
+ className: "flex-1 overflow-y-auto",
4253
+ style: flush ? void 0 : { padding: "var(--ds-space-5)" },
4254
+ children
4255
+ }
4256
+ ),
4257
+ confirm,
4258
+ footer && /* @__PURE__ */ jsx(
4259
+ "div",
4260
+ {
4261
+ className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
4262
+ style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
4263
+ children: footer
4264
+ }
4265
+ )
4266
+ ]
4267
+ }
4268
+ )
4269
+ ]
4270
+ }
4271
+ ),
4272
+ container ?? document.body
4273
+ );
4274
+ }
4275
+ var DrawerFooterCtx = createContext(null);
4276
+ var slideClasses = {
4277
+ right: {
4278
+ panel: "top-0 right-0 h-full",
4279
+ open: "translate-x-0",
4280
+ closed: "translate-x-full"
4281
+ },
4282
+ left: {
4283
+ panel: "top-0 left-0 h-full",
4284
+ open: "translate-x-0",
4285
+ closed: "-translate-x-full"
4286
+ },
4287
+ bottom: {
4288
+ panel: "bottom-0 left-0 right-0",
4289
+ open: "translate-y-0",
4290
+ closed: "translate-y-full"
4291
+ }
4292
+ };
4293
+ var borderByPosition = {
4294
+ right: "border-l-[length:var(--ds-border-width)] border-l-[var(--ds-border-default)]",
4295
+ left: "border-r-[length:var(--ds-border-width)] border-r-[var(--ds-border-default)]",
4296
+ bottom: "border-t-[length:var(--ds-border-width)] border-t-[var(--ds-border-default)]"
4297
+ };
4298
+ function Drawer(props) {
4299
+ const { position = "right", mobile, snapPoints, open, onClose, title, children, footer, container, flush, keepMounted, id, labelledBy, dirty, onDiscard } = props;
4300
+ const isPhone = useBreakpoint("sm");
4301
+ const mobileMode = mobile ?? (position === "left" ? "panel" : "sheet");
4302
+ const guard = useDirtyGuard(dirty, onClose, onDiscard);
4303
+ const confirm = /* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard });
4304
+ const [actionsMap, setActionsMap] = useState(/* @__PURE__ */ new Map());
4305
+ const registerActions = useCallback((formId, acts) => {
4306
+ setActionsMap((prev) => new Map(prev).set(formId, acts));
4307
+ }, []);
4308
+ const unregisterActions = useCallback((formId) => {
4309
+ setActionsMap((prev) => {
4310
+ const next = new Map(prev);
4311
+ next.delete(formId);
4312
+ return next;
4313
+ });
4314
+ }, []);
4315
+ const registeredActions = actionsMap.size > 0 ? /* @__PURE__ */ jsx(Fragment, { children: Array.from(actionsMap.values()) }) : null;
4316
+ const effectiveFooter = footer ?? registeredActions;
4317
+ const footerCtx = useMemo(
4318
+ () => ({ registerActions, unregisterActions }),
4319
+ [registerActions, unregisterActions]
4320
+ );
4321
+ if (isPhone && mobileMode === "sheet") {
4322
+ return /* @__PURE__ */ jsx(DrawerFooterCtx, { value: footerCtx, children: /* @__PURE__ */ jsx(Sheet, { open, onClose: guard.requestClose, title, footer: effectiveFooter, confirm, container, flush, snapPoints, keepMounted, id, labelledBy, children }) });
4323
+ }
4324
+ return /* @__PURE__ */ jsx(DrawerFooterCtx, { value: footerCtx, children: /* @__PURE__ */ jsx(DrawerPanel, { ...props, footer: effectiveFooter, onClose: guard.requestClose, confirm }) });
4325
+ }
4326
+ function DrawerPanel({ open, onClose, position = "right", width = "400px", title, children, footer, container, flush, lightBackdrop, topOffset, modal = true, keepMounted = false, id, labelledBy, resizable = false, maxWidth, confirm }) {
4327
+ const nonModal = !modal;
4328
+ const [chosen, remember] = useRememberedWidth(id ?? labelledBy);
4329
+ const canResize = nonModal && resizable && position !== "bottom";
4330
+ const effectiveWidth = canResize && chosen !== null ? `${chosen}px` : width;
4331
+ const minPx = pxOf(width) ?? 320;
4332
+ const maxPx = () => pxOf(maxWidth) ?? defaultMaxWidth(container instanceof Element ? container : null);
4333
+ const titleId = useId();
4334
+ const { ref: titleOverflowRef, isTruncated: titleTruncated } = useTextOverflow({ lines: 1 });
4335
+ const isMobile = useBreakpoint("sm");
4336
+ const panelRef = useRef(null);
4337
+ const [mounted, setMounted] = useState(open);
4338
+ const [hidden, setHidden] = useState(!open);
4339
+ const onCloseRef = useLatest(onClose);
4340
+ if (open && !mounted) setMounted(true);
4341
+ if (open && hidden) setHidden(false);
4342
+ const isTopLayer = useOverlayLayer(open);
4343
+ useEffect(() => {
4344
+ if (!open || nonModal) return;
4345
+ const onKeyDown = (e) => {
4346
+ if (e.key === "Escape" && isTopLayer()) onCloseRef.current();
4347
+ };
4348
+ document.addEventListener("keydown", onKeyDown);
4349
+ if (!container) lockBodyScroll();
4350
+ return () => {
4351
+ document.removeEventListener("keydown", onKeyDown);
4352
+ if (!container) unlockBodyScroll();
4353
+ };
4354
+ }, [open, nonModal, container, onCloseRef, isTopLayer]);
4355
+ useReturnFocus(open && !nonModal);
4356
+ useFocusTrap(panelRef, open && !topOffset && !nonModal, isTopLayer);
4357
+ useEffect(() => {
4358
+ if (!open || !mounted || nonModal) return;
4359
+ const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
4360
+ return () => cancelAnimationFrame(raf);
4361
+ }, [open, mounted, nonModal]);
4362
+ useNonModalDialog(panelRef, open && mounted && nonModal, onClose, isTopLayer);
4363
+ useCloseSettle(open, panelRef, () => {
4364
+ if (keepMounted) setHidden(true);
4365
+ else setMounted(false);
4366
+ });
4367
+ if (!mounted) return null;
4368
+ const slide = slideClasses[position];
4369
+ const isHorizontal = position === "left" || position === "right";
4370
+ const positionClass = container ? "absolute" : "fixed";
4371
+ return createPortal(
4372
+ /* @__PURE__ */ jsxs(
4373
+ "div",
4374
+ {
4375
+ hidden: keepMounted && hidden ? true : void 0,
4376
+ className: cn(
4377
+ `${positionClass} transition-opacity duration-[var(--ds-transition-speed)]`,
4378
+ // A non-modal panel never intercepts the page: the wrapper is inert to the
4379
+ // pointer and only the panel itself accepts events.
4380
+ nonModal ? "z-[var(--ds-z-overlay)] pointer-events-none" : cn("z-[var(--ds-z-modal)]", open ? "pointer-events-auto" : "pointer-events-none"),
4381
+ topOffset ? "left-0 right-0 bottom-0" : "inset-0"
4382
+ ),
4383
+ style: topOffset ? { top: topOffset } : void 0,
4384
+ children: [
4385
+ !nonModal && /* @__PURE__ */ jsx(
4386
+ "div",
4387
+ {
4388
+ className: cn(
4389
+ "absolute inset-0 transition-opacity duration-[var(--ds-transition-speed)]",
4390
+ lightBackdrop ? "bg-black/15" : cn("bg-black/50", "[backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]"),
4391
+ open ? "opacity-100" : "opacity-0"
4392
+ ),
4393
+ onClick: onClose
4394
+ }
4395
+ ),
4396
+ /* @__PURE__ */ jsxs(
4397
+ "div",
4398
+ {
4399
+ ref: panelRef,
4400
+ id,
4401
+ role: "dialog",
4402
+ "aria-modal": nonModal ? void 0 : "true",
4403
+ "aria-labelledby": title ? titleId : labelledBy,
4404
+ style: {
4405
+ containerType: "inline-size",
4406
+ width: isHorizontal ? effectiveWidth : void 0,
4407
+ maxWidth: isHorizontal ? "100%" : void 0,
4408
+ height: isMobile ? "100%" : void 0,
4409
+ maxHeight: !isMobile && !isHorizontal ? "80vh" : void 0
4410
+ },
4411
+ className: cn(
4412
+ `${positionClass} z-10 flex flex-col`,
4413
+ nonModal && "pointer-events-auto",
4414
+ "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
4415
+ GLASS_OVERLAY,
4416
+ // flush drops the edge border for children that draw their own (the mobile
4417
+ // menu's Sidebar); a non-modal panel has no backdrop to separate it from
4418
+ // the page, so it always keeps the border.
4419
+ (!flush || nonModal) && borderByPosition[position],
4420
+ "transition-transform duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
4421
+ isHorizontal && position === "left" && "rounded-r-[var(--ds-radius-lg)] overflow-hidden",
4422
+ isHorizontal && position === "right" && "rounded-l-[var(--ds-radius-lg)] overflow-hidden",
4423
+ !isHorizontal && "rounded-t-[var(--ds-radius-lg)] overflow-hidden",
4424
+ (lightBackdrop || nonModal) && "shadow-[var(--ds-shadow-overlay)]",
4425
+ slide.panel,
4426
+ open ? slide.open : slide.closed
4427
+ ),
4428
+ children: [
4429
+ canResize && open && /* @__PURE__ */ jsx(
4430
+ ResizeEdge,
4431
+ {
4432
+ edge: position === "right" ? "left" : "right",
4433
+ width: chosen ?? minPx,
4434
+ min: minPx,
4435
+ max: maxPx,
4436
+ defaultWidth: minPx,
4437
+ onResize: (w) => remember(w === minPx ? null : w),
4438
+ label: "Resize panel"
4439
+ }
4440
+ ),
4441
+ title && /* @__PURE__ */ jsxs(
4442
+ "div",
4443
+ {
4444
+ className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
4445
+ style: {
4446
+ padding: "var(--ds-space-3) var(--ds-space-6)",
4447
+ minHeight: "calc(var(--ds-space-unit) * 6 + 1.75rem + 2px + var(--ds-border-width))"
4448
+ },
4449
+ children: [
4450
+ titleTruncated ? /* @__PURE__ */ jsx(Tooltip, { content: title, children: /* @__PURE__ */ jsx("h2", { ref: titleOverflowRef, id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }) }) : /* @__PURE__ */ jsx("h2", { ref: titleOverflowRef, id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
4451
+ /* @__PURE__ */ jsx(
4452
+ "button",
4453
+ {
4454
+ onClick: onClose,
4455
+ ...{ [OVERLAY_CLOSE_ATTR]: "" },
4456
+ className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
4457
+ "aria-label": "Close",
4458
+ children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
4459
+ }
4460
+ )
4461
+ ]
4462
+ }
4463
+ ),
4464
+ /* @__PURE__ */ jsx(
4465
+ "div",
4466
+ {
4467
+ className: "flex-1 overflow-y-auto",
4468
+ style: flush ? void 0 : { padding: "var(--ds-space-5)" },
4469
+ children
4470
+ }
4471
+ ),
4472
+ confirm,
4473
+ footer && /* @__PURE__ */ jsx(
4474
+ "div",
4475
+ {
4476
+ className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
4477
+ style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
4478
+ children: footer
4479
+ }
4480
+ )
4481
+ ]
4482
+ }
4483
+ )
4484
+ ]
4485
+ }
4486
+ ),
4487
+ container ?? document.body
4488
+ );
4489
+ }
4490
+ function stampFormId(node, formId) {
4491
+ return Children.map(node, (child) => {
4492
+ if (!isValidElement(child)) return child;
4493
+ if (child.type === Fragment$1) return stampFormId(child.props.children, formId);
4494
+ return cloneElement(child, { form: formId });
4495
+ });
4496
+ }
4497
+ var FormCtx = createContext(null);
4498
+ function useFormContext() {
4499
+ const ctx = useContext(FormCtx);
4500
+ if (!ctx) throw new Error("useFormContext must be used within FormWrapper");
4501
+ return ctx;
4502
+ }
4503
+ function collectInvalidFields(form) {
4504
+ const out = [];
4505
+ for (const el of Array.from(form.querySelectorAll("[aria-invalid='true']"))) {
4506
+ const id = el.id || "";
4507
+ const label = id && form.querySelector(`label[for="${CSS.escape(id)}"]`)?.textContent?.replace(/\*\s*$/, "").trim() || el.getAttribute("aria-label") || el.closest("[data-field]")?.querySelector("label")?.textContent?.trim() || id || "A field";
4508
+ const described = (el.getAttribute("aria-describedby") ?? "").split(/\s+/).filter(Boolean);
4509
+ const message = described.map((d) => document.getElementById(d)?.textContent?.trim()).find((t) => t && /error|invalid|required|must|enter|choose|select|please/i.test(t)) ?? described.map((d) => document.getElementById(d)?.textContent?.trim()).filter(Boolean).pop() ?? "Needs attention";
4510
+ out.push({ id, label, message });
4511
+ }
4512
+ return out;
4513
+ }
4514
+ function FormWrapper({ onSubmit, validationMode = "onSubmit", children, actions, actionsAlign = "end", focusFirstError = true, errorSummary = true, className, ref }) {
4515
+ const [errors, setErrors] = useState({});
4516
+ const [submitted, setSubmitted] = useState(false);
4517
+ const [submitCount, setSubmitCount] = useState(0);
4518
+ const [summary, setSummary] = useState([]);
4519
+ const errorsRef = useLatest(errors);
4520
+ const formRef = useRef(null);
4521
+ const setRefs = useCallback((node) => {
4522
+ formRef.current = node;
4523
+ if (typeof ref === "function") ref(node);
4524
+ else if (ref) ref.current = node;
4525
+ }, [ref]);
4526
+ const inCard = useContext(CardSurfaceCtx);
4527
+ const drawerFooter = useContext(DrawerFooterCtx);
4528
+ const formId = useId();
4529
+ useEffect(() => {
4530
+ if (!drawerFooter || !actions) return;
4531
+ drawerFooter.registerActions(formId, stampFormId(actions, formId));
4532
+ return () => drawerFooter.unregisterActions(formId);
4533
+ }, [drawerFooter, actions, formId]);
4534
+ const pendingSubmit = useRef(false);
4535
+ const pendingFocus = useRef(false);
4536
+ const onSubmitRef = useLatest(onSubmit);
4537
+ useEffect(() => {
4538
+ if (pendingSubmit.current && submitted) {
4539
+ pendingSubmit.current = false;
4540
+ onSubmitRef.current(errorsRef.current);
4541
+ }
4542
+ }, [submitted, submitCount, errors, errorsRef, onSubmitRef]);
4543
+ const settle = useCallback(() => {
4544
+ const form = formRef.current;
4545
+ if (!form) return;
4546
+ const invalid = collectInvalidFields(form);
4547
+ const next = invalid.length >= 2 ? invalid : [];
4548
+ setSummary((prev) => prev.length === next.length && prev.every((f, i) => f.id === next[i].id && f.message === next[i].message && f.label === next[i].label) ? prev : next);
4549
+ if (pendingFocus.current && invalid.length > 0) {
4550
+ pendingFocus.current = false;
4551
+ const first = form.querySelector("[aria-invalid='true']");
4552
+ if (first) {
4553
+ if (typeof first.scrollIntoView === "function") first.scrollIntoView({ block: "center", behavior: "smooth" });
4554
+ first.focus({ preventScroll: true });
4555
+ }
4556
+ }
4557
+ }, []);
4558
+ useLayoutEffect(() => {
4559
+ if (!submitted) return;
4560
+ settle();
4561
+ }, [submitted, submitCount, errors, settle]);
4562
+ useEffect(() => {
4563
+ const form = formRef.current;
4564
+ if (!form || typeof MutationObserver === "undefined") return;
4565
+ const obs = new MutationObserver(() => settle());
4566
+ obs.observe(form, { subtree: true, childList: true, attributes: true, attributeFilter: ["aria-invalid"] });
4567
+ return () => obs.disconnect();
4568
+ }, [settle]);
4569
+ const userActed = useCallback((e) => {
4570
+ if (!pendingFocus.current) return;
4571
+ const target = e.target;
4572
+ if (target && target.closest("button[type='submit']")) return;
4573
+ pendingFocus.current = false;
4574
+ }, []);
4575
+ const setError = useCallback((field, message) => {
4576
+ setErrors((prev) => ({ ...prev, [field]: message }));
4577
+ }, []);
4578
+ const clearErrors = useCallback(() => {
4579
+ setErrors({});
4580
+ setSubmitted(false);
4581
+ setSummary([]);
4582
+ }, []);
4583
+ const handleSubmit = useCallback(
4584
+ (e) => {
4585
+ e.preventDefault();
4586
+ pendingSubmit.current = true;
4587
+ pendingFocus.current = focusFirstError;
4588
+ setSubmitted(true);
4589
+ setSubmitCount((c) => c + 1);
4590
+ },
4591
+ [focusFirstError]
4592
+ );
4593
+ const focusField = (id) => (e) => {
4594
+ e.preventDefault();
4595
+ const el = id ? document.getElementById(id) : null;
4596
+ if (el) {
4597
+ el.scrollIntoView?.({ block: "center" });
4598
+ el.focus();
4599
+ }
4600
+ };
4601
+ const summaryNode = errorSummary && summary.length >= 2 ? typeof errorSummary === "function" ? errorSummary(summary) : /* @__PURE__ */ jsx(Alert, { variant: "error", title: `${summary.length} fields need attention`, className: "mb-ds-4", children: /* @__PURE__ */ jsx("ul", { className: "list-disc pl-ds-5 flex flex-col gap-ds-1", children: summary.map((f) => /* @__PURE__ */ jsxs("li", { children: [
4602
+ /* @__PURE__ */ jsx("a", { href: f.id ? `#${f.id}` : void 0, onClick: focusField(f.id), className: "underline underline-offset-2 text-[var(--ds-text-primary)]", children: f.label }),
4603
+ ": ",
4604
+ f.message
4605
+ ] }, f.id || f.label)) }) }) : null;
4606
+ let actionsNode = null;
4607
+ if (actions && !drawerFooter) {
4608
+ if (inCard) {
4609
+ actionsNode = /* @__PURE__ */ jsx(
4610
+ "div",
4611
+ {
4612
+ "data-form-actions": "",
4613
+ "data-form-actions-surface": "card",
4614
+ className: cn(
4615
+ "border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
4616
+ "flex flex-wrap items-center gap-ds-2 pt-ds-4 mt-ds-6",
4617
+ actionsAlign === "end" ? "justify-end" : "justify-start"
4618
+ ),
4619
+ children: actions
4620
+ }
4621
+ );
4622
+ } else {
4623
+ actionsNode = /* @__PURE__ */ jsx("div", { "data-form-actions": "", className: cn("flex flex-wrap items-center gap-ds-2 pt-ds-4 mt-ds-2", actionsAlign === "end" ? "justify-end" : "justify-start"), children: actions });
4624
+ }
4625
+ }
4626
+ return /* @__PURE__ */ jsx(FormCtx.Provider, { value: { errors, setError, clearErrors, validationMode, submitted }, children: /* @__PURE__ */ jsxs("form", { ref: setRefs, id: drawerFooter ? formId : void 0, onSubmit: handleSubmit, onFocusCapture: userActed, onInputCapture: userActed, className, noValidate: true, children: [
4627
+ summaryNode && /* @__PURE__ */ jsx("div", { "data-form-error-summary": "", children: summaryNode }),
4628
+ children,
4629
+ actionsNode
4630
+ ] }) });
4631
+ }
4632
+ function TransferList({
4633
+ available,
4634
+ selected,
4635
+ onChange,
4636
+ availableTitle = "Available",
4637
+ selectedTitle = "Selected",
4638
+ searchable = true,
4639
+ className,
4640
+ ref
4641
+ }) {
4642
+ const [checkedAvailable, setCheckedAvailable] = useState(/* @__PURE__ */ new Set());
4643
+ const [checkedSelected, setCheckedSelected] = useState(/* @__PURE__ */ new Set());
4644
+ const [searchLeft, setSearchLeft] = useState("");
4645
+ const [searchRight, setSearchRight] = useState("");
3397
4646
  const filteredAvailable = useMemo(
3398
4647
  () => searchLeft ? available.filter((i) => i.label.toLowerCase().includes(searchLeft.toLowerCase())) : available,
3399
4648
  [available, searchLeft]
@@ -3853,397 +5102,110 @@ function MentionInput({
3853
5102
  setActiveIndex((i) => (i - 1 + filtered.length) % filtered.length);
3854
5103
  } else if (e.key === "Enter" || e.key === "Tab") {
3855
5104
  e.preventDefault();
3856
- insertMention(filtered[activeIndex]);
3857
- } else if (e.key === "Escape") {
3858
- setShowPopup(false);
3859
- }
3860
- };
3861
- useEffect(() => {
3862
- if (!showPopup) return;
3863
- const handler = (e) => {
3864
- if (popupRef.current && !popupRef.current.contains(e.target) && inputRef.current && !inputRef.current.contains(e.target)) {
3865
- setShowPopup(false);
3866
- }
3867
- };
3868
- document.addEventListener("mousedown", handler);
3869
- return () => document.removeEventListener("mousedown", handler);
3870
- }, [showPopup]);
3871
- return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
3872
- /* @__PURE__ */ jsx(
3873
- "textarea",
3874
- {
3875
- ref: inputRef,
3876
- value,
3877
- onChange: handleInput,
3878
- onKeyDown: handleKeyDown,
3879
- placeholder,
3880
- disabled,
3881
- rows: 3,
3882
- className: cn(
3883
- "flex w-full px-ds-3 py-ds-2 text-sm resize-none",
3884
- "bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]",
3885
- "border-[length:var(--ds-border-width)] border-[var(--ds-input-border)]",
3886
- "rounded-[var(--ds-radius-md)]",
3887
- "shadow-[var(--ds-input-shadow)]",
3888
- "placeholder:text-[var(--ds-text-muted)]",
3889
- "hover:border-[var(--ds-input-border-hover)]",
3890
- FOCUS_RING,
3891
- "disabled:cursor-not-allowed disabled:opacity-disabled disabled:hover:border-[var(--ds-input-border)]",
3892
- "transition-colors duration-[var(--ds-transition-speed)]"
3893
- )
3894
- }
3895
- ),
3896
- /* @__PURE__ */ jsx(
3897
- "div",
3898
- {
3899
- ref: mirrorRef,
3900
- "aria-hidden": true,
3901
- className: "fixed top-0 left-0 -z-50 opacity-0 pointer-events-none"
3902
- }
3903
- ),
3904
- showPopup && filtered.length > 0 && createPortal(
3905
- /* @__PURE__ */ jsx(
3906
- "div",
3907
- {
3908
- ref: popupRef,
3909
- role: "listbox",
3910
- className: cn(
3911
- "fixed z-[var(--ds-z-popover)] min-w-[200px] max-h-[200px] overflow-y-auto",
3912
- "bg-[var(--ds-bg-surface-elevated)]",
3913
- "[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
3914
- "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
3915
- "rounded-[var(--ds-radius-md)] shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]",
3916
- "py-ds-1"
3917
- ),
3918
- style: { top: popupPos.top, left: popupPos.left },
3919
- children: filtered.map((s, i) => /* @__PURE__ */ jsxs(
3920
- "button",
3921
- {
3922
- type: "button",
3923
- role: "option",
3924
- "aria-selected": i === activeIndex,
3925
- className: cn(
3926
- "flex items-center gap-ds-2.5 w-full px-ds-3 py-ds-1.5 text-left text-sm cursor-pointer",
3927
- "transition-colors duration-[var(--ds-transition-speed)]",
3928
- i === activeIndex ? "bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] hover:text-[var(--ds-text-primary)]"
3929
- ),
3930
- onMouseDown: (e) => {
3931
- e.preventDefault();
3932
- insertMention(s);
3933
- },
3934
- onMouseEnter: () => setActiveIndex(i),
3935
- children: [
3936
- /* @__PURE__ */ jsx(
3937
- Avatar,
3938
- {
3939
- src: s.avatar,
3940
- initials: s.label.charAt(0).toUpperCase(),
3941
- alt: s.label,
3942
- size: "sm",
3943
- className: "!h-6 !w-6 !text-2xs"
3944
- }
3945
- ),
3946
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
3947
- /* @__PURE__ */ jsx("div", { className: "font-medium text-[var(--ds-text-primary)] truncate", children: s.label }),
3948
- s.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--ds-text-muted)] truncate", children: s.description })
3949
- ] })
3950
- ]
3951
- },
3952
- s.id
3953
- ))
3954
- }
3955
- ),
3956
- document.body
3957
- )
3958
- ] });
3959
- }
3960
- var CardCtx = createContext(false);
3961
- var variantStyles3 = {
3962
- default: `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] ${GLASS_SURFACE}`,
3963
- featured: [
3964
- `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] ${GLASS_SURFACE}`,
3965
- "[transition:var(--ds-transition-ambient)]",
3966
- "hover:scale-[var(--ds-ambient-hover-scale)] hover:-translate-y-[var(--ds-ambient-hover-lift)]"
3967
- ].join(" "),
3968
- interactive: [
3969
- `bg-[var(--ds-bg-surface)] cursor-pointer ${GLASS_SURFACE}`,
3970
- "border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
3971
- "[transition:var(--ds-transition-interactive)]",
3972
- "hover:border-[var(--ds-accent-primary)] hover:shadow-[var(--ds-shadow-card),var(--ds-glass-inset)] hover:bg-[var(--ds-bg-surface-elevated)]",
3973
- "hover:scale-[var(--_card-scale)] hover:-translate-y-[var(--ds-hover-lift)]"
3974
- ].join(" "),
3975
- outline: `bg-[var(--ds-bg-surface)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)] ${GLASS_SURFACE}`,
3976
- ghost: "bg-transparent border-none shadow-none"
3977
- };
3978
- var INTERACTIVE_SCALE_CAP = { "--_card-scale": "min(var(--ds-hover-scale), 1.04)" };
3979
- function RadioIndicator({ checked, disabled }) {
3980
- return /* @__PURE__ */ jsx(
3981
- "span",
3982
- {
3983
- className: cn(
3984
- "flex items-center justify-center shrink-0 rounded-[var(--ds-radius-full)]",
3985
- "h-[18px] w-[18px]",
3986
- "border-[length:var(--ds-border-width)] bg-[var(--ds-input-bg)]",
3987
- "transition-colors duration-[var(--ds-transition-speed)]",
3988
- disabled && "opacity-disabled",
3989
- checked ? "border-[var(--ds-check-border)]" : "border-[var(--ds-input-border)]"
3990
- ),
3991
- children: /* @__PURE__ */ jsx(
3992
- "span",
3993
- {
3994
- className: cn(
3995
- "h-2.5 w-2.5 rounded-[var(--ds-radius-full)] transition-transform duration-[var(--ds-transition-speed)]",
3996
- checked ? "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] scale-100" : "scale-0"
3997
- )
3998
- }
3999
- )
4000
- }
4001
- );
4002
- }
4003
- function CheckboxIndicator({ checked, indeterminate, disabled }) {
4004
- const filled = checked || indeterminate;
4005
- return /* @__PURE__ */ jsx(
4006
- "span",
4007
- {
4008
- className: cn(
4009
- "flex items-center justify-center shrink-0",
4010
- "h-[18px] w-[18px]",
4011
- "rounded-[calc(var(--ds-radius-sm)*0.6)]",
4012
- "border-[2px] transition-all duration-[var(--ds-transition-speed)]",
4013
- disabled && "opacity-disabled",
4014
- filled ? "bg-[var(--ds-check-bg)] [background-image:var(--ds-gradient)] border-[var(--ds-check-border)]" : "bg-[var(--ds-input-bg)] border-[var(--ds-input-border)]"
4015
- ),
4016
- children: /* @__PURE__ */ jsx(
4017
- "svg",
4018
- {
4019
- width: "12",
4020
- height: "12",
4021
- viewBox: "0 0 12 12",
4022
- fill: "none",
4023
- className: cn(
4024
- "text-[var(--ds-check-fg)] transition-opacity",
4025
- filled ? "opacity-100" : "opacity-0"
4026
- ),
4027
- children: indeterminate ? /* @__PURE__ */ jsx("path", { d: "M3 6H9", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }) : /* @__PURE__ */ jsx("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })
4028
- }
4029
- )
4030
- }
4031
- );
4032
- }
4033
- function ToggleIndicator({ checked, disabled }) {
4034
- return /* @__PURE__ */ jsx(
4035
- "span",
4036
- {
4037
- className: cn(
4038
- "relative inline-flex shrink-0 items-center overflow-hidden",
4039
- "border-[length:var(--ds-border-width)] rounded-[var(--ds-radius-full)]",
4040
- "transition-colors duration-[var(--ds-transition-speed)]",
4041
- disabled && "opacity-disabled",
4042
- checked ? "bg-[var(--ds-accent-primary)] border-transparent" : "bg-[var(--ds-bg-muted)] border-[var(--ds-border-default)]"
4043
- ),
4044
- style: { width: 44, height: 24 },
4045
- children: /* @__PURE__ */ jsx(
4046
- "span",
4047
- {
4048
- className: "pointer-events-none inline-block shrink-0 bg-[var(--ds-bg-surface)] rounded-[var(--ds-radius-full)] transition-transform",
4049
- style: {
4050
- width: 16,
4051
- height: 16,
4052
- transform: checked ? "translateX(calc(25px - var(--ds-border-width)))" : "translateX(calc(1px + var(--ds-border-width)))"
4053
- }
4054
- }
4055
- )
4056
- }
4057
- );
4058
- }
4059
- var Card = forwardRef(function Card2({
4060
- variant = "default",
4061
- loading = false,
4062
- selected,
4063
- selectable,
4064
- selectType,
4065
- onSelectedChange,
4066
- name,
4067
- indeterminate,
4068
- disabled = false,
4069
- checkable = false,
4070
- className,
4071
- children,
4072
- onClick,
4073
- style,
4074
- ...props
4075
- }, ref) {
4076
- const isSelectable = selectable || !!selectType;
4077
- const isToggle = selectType === "toggle";
4078
- const hasSelectType = !!selectType;
4079
- const handleClick = isSelectable && !disabled ? (e) => {
4080
- onSelectedChange?.(!selected);
4081
- onClick?.(e);
4082
- } : onClick;
4083
- const handleKeyDown = isSelectable && !disabled ? (e) => {
4084
- if (e.key === "Enter" || e.key === " ") {
4085
- e.preventDefault();
4086
- onSelectedChange?.(!selected);
5105
+ insertMention(filtered[activeIndex]);
5106
+ } else if (e.key === "Escape") {
5107
+ setShowPopup(false);
4087
5108
  }
4088
- } : void 0;
4089
- const handleCheckableClick = (e) => {
4090
- e.stopPropagation();
4091
- onSelectedChange?.(!selected);
4092
5109
  };
4093
- const role = selectType === "radio" ? "radio" : selectType === "checkbox" ? "checkbox" : selectType === "toggle" ? "switch" : isSelectable ? "button" : void 0;
4094
- const ariaAttr = selectType === "radio" || selectType === "checkbox" || selectType === "toggle" ? { "aria-checked": !!selected } : isSelectable ? { "aria-pressed": !!selected } : {};
4095
- const showRing = isSelectable && !isToggle && !hasSelectType && selected;
4096
- const indicator = selectType === "radio" ? /* @__PURE__ */ jsx(RadioIndicator, { checked: !!selected, disabled }) : selectType === "checkbox" ? /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected, indeterminate, disabled }) : selectType === "toggle" ? /* @__PURE__ */ jsx(ToggleIndicator, { checked: !!selected, disabled }) : null;
4097
- const defaultCheckBadge = !hasSelectType && !checkable && selected && !loading ? /* @__PURE__ */ jsx("div", { className: "absolute top-ds-3 right-ds-3 w-5 h-5 rounded-[var(--ds-radius-full)] bg-[var(--ds-accent-primary)] flex items-center justify-center", children: /* @__PURE__ */ jsx(Icon, { name: "check", size: 12, className: "text-[var(--ds-text-on-primary)]" }) }) : null;
4098
- return /* @__PURE__ */ jsxs(
4099
- "div",
4100
- {
4101
- ref,
4102
- "data-card": "",
4103
- role,
4104
- tabIndex: isSelectable ? 0 : void 0,
4105
- "aria-disabled": isSelectable && disabled ? true : void 0,
4106
- ...name && selectType === "radio" ? { "data-radio-group": name } : {},
4107
- style: variant === "interactive" ? { ...INTERACTIVE_SCALE_CAP, ...style } : style,
4108
- className: cn(
4109
- "rounded-[var(--ds-radius-md)] flex flex-col relative",
4110
- variantStyles3[variant],
4111
- isSelectable && !disabled && "cursor-pointer select-none transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
4112
- isSelectable && !disabled && !selected && "hover:border-[var(--ds-accent-primary)]",
4113
- isSelectable && "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
4114
- (showRing || hasSelectType && selected) && ACTIVE_RING,
4115
- hasSelectType && selected && "bg-[var(--ds-accent-subtle)]",
4116
- disabled && "opacity-disabled cursor-not-allowed",
4117
- className
4118
- ),
4119
- onClick: handleClick,
4120
- onKeyDown: handleKeyDown,
4121
- ...ariaAttr,
4122
- ...props,
4123
- children: [
4124
- defaultCheckBadge,
4125
- indicator && /* @__PURE__ */ jsx("div", { className: "absolute top-ds-3 right-ds-3 z-[1]", children: indicator }),
4126
- checkable && /* @__PURE__ */ jsx(
4127
- "div",
4128
- {
4129
- className: "absolute top-ds-3 left-ds-3 z-[1] cursor-pointer",
4130
- onClick: handleCheckableClick,
4131
- role: "checkbox",
4132
- "aria-checked": !!selected,
4133
- tabIndex: 0,
4134
- onKeyDown: (e) => {
4135
- if (e.key === "Enter" || e.key === " ") {
4136
- e.preventDefault();
4137
- e.stopPropagation();
4138
- onSelectedChange?.(!selected);
4139
- }
4140
- },
4141
- children: /* @__PURE__ */ jsx(CheckboxIndicator, { checked: !!selected })
4142
- }
4143
- ),
4144
- /* @__PURE__ */ jsx(CardCtx, { value: checkable, children: loading ? /* @__PURE__ */ jsxs("div", { className: "space-y-ds-3", children: [
4145
- /* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-4 w-1/3" }),
4146
- /* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-full" }),
4147
- /* @__PURE__ */ jsx(Skeleton, { variant: "custom", className: "h-3 w-2/3" })
4148
- ] }) : children })
4149
- ]
4150
- }
4151
- );
4152
- });
4153
- var CardHeader = forwardRef(function CardHeader2({ className, children, actions, icon, menuItems, ...props }, ref) {
4154
- const isCheckable = useContext(CardCtx);
4155
- const hasActions = actions || menuItems;
4156
- const pl = isCheckable ? "pl-ds-10" : "pl-ds-5";
4157
- const actionsBlock = hasActions ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2 shrink-0", children: [
4158
- actions,
4159
- menuItems && /* @__PURE__ */ jsx(
4160
- DropdownMenu,
5110
+ useEffect(() => {
5111
+ if (!showPopup) return;
5112
+ const handler = (e) => {
5113
+ if (popupRef.current && !popupRef.current.contains(e.target) && inputRef.current && !inputRef.current.contains(e.target)) {
5114
+ setShowPopup(false);
5115
+ }
5116
+ };
5117
+ document.addEventListener("mousedown", handler);
5118
+ return () => document.removeEventListener("mousedown", handler);
5119
+ }, [showPopup]);
5120
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
5121
+ /* @__PURE__ */ jsx(
5122
+ "textarea",
4161
5123
  {
4162
- trigger: /* @__PURE__ */ jsx(
4163
- "button",
4164
- {
4165
- type: "button",
4166
- className: cn(
4167
- "inline-flex items-center justify-center h-8 w-8 rounded-[var(--ds-radius-md)]",
4168
- "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-bg-muted)]",
4169
- "transition-colors duration-[var(--ds-transition-speed)]"
4170
- ),
4171
- onClick: (e) => e.stopPropagation(),
4172
- children: /* @__PURE__ */ jsx(Icon, { name: "more-horizontal", size: 16 })
4173
- }
4174
- ),
4175
- items: menuItems
5124
+ ref: inputRef,
5125
+ value,
5126
+ onChange: handleInput,
5127
+ onKeyDown: handleKeyDown,
5128
+ placeholder,
5129
+ disabled,
5130
+ rows: 3,
5131
+ className: cn(
5132
+ "flex w-full px-ds-3 py-ds-2 text-sm resize-none",
5133
+ "bg-[var(--ds-input-bg)] text-[var(--ds-text-primary)]",
5134
+ "border-[length:var(--ds-border-width)] border-[var(--ds-input-border)]",
5135
+ "rounded-[var(--ds-radius-md)]",
5136
+ "shadow-[var(--ds-input-shadow)]",
5137
+ "placeholder:text-[var(--ds-text-muted)]",
5138
+ "hover:border-[var(--ds-input-border-hover)]",
5139
+ FOCUS_RING,
5140
+ "disabled:cursor-not-allowed disabled:opacity-disabled disabled:hover:border-[var(--ds-input-border)]",
5141
+ "transition-colors duration-[var(--ds-transition-speed)]"
5142
+ )
5143
+ }
5144
+ ),
5145
+ /* @__PURE__ */ jsx(
5146
+ "div",
5147
+ {
5148
+ ref: mirrorRef,
5149
+ "aria-hidden": true,
5150
+ className: "fixed top-0 left-0 -z-50 opacity-0 pointer-events-none"
4176
5151
  }
5152
+ ),
5153
+ showPopup && filtered.length > 0 && createPortal(
5154
+ /* @__PURE__ */ jsx(
5155
+ "div",
5156
+ {
5157
+ ref: popupRef,
5158
+ role: "listbox",
5159
+ className: cn(
5160
+ "fixed z-[var(--ds-z-popover)] min-w-[200px] max-h-[200px] overflow-y-auto",
5161
+ "bg-[var(--ds-bg-surface-elevated)]",
5162
+ "[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
5163
+ "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
5164
+ "rounded-[var(--ds-radius-md)] shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]",
5165
+ "py-ds-1"
5166
+ ),
5167
+ style: { top: popupPos.top, left: popupPos.left },
5168
+ children: filtered.map((s, i) => /* @__PURE__ */ jsxs(
5169
+ "button",
5170
+ {
5171
+ type: "button",
5172
+ role: "option",
5173
+ "aria-selected": i === activeIndex,
5174
+ className: cn(
5175
+ "flex items-center gap-ds-2.5 w-full px-ds-3 py-ds-1.5 text-left text-sm cursor-pointer",
5176
+ "transition-colors duration-[var(--ds-transition-speed)]",
5177
+ i === activeIndex ? "bg-[var(--ds-bg-muted)] text-[var(--ds-text-primary)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] hover:text-[var(--ds-text-primary)]"
5178
+ ),
5179
+ onMouseDown: (e) => {
5180
+ e.preventDefault();
5181
+ insertMention(s);
5182
+ },
5183
+ onMouseEnter: () => setActiveIndex(i),
5184
+ children: [
5185
+ /* @__PURE__ */ jsx(
5186
+ Avatar,
5187
+ {
5188
+ src: s.avatar,
5189
+ initials: s.label.charAt(0).toUpperCase(),
5190
+ alt: s.label,
5191
+ size: "sm",
5192
+ className: "!h-6 !w-6 !text-2xs"
5193
+ }
5194
+ ),
5195
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
5196
+ /* @__PURE__ */ jsx("div", { className: "font-medium text-[var(--ds-text-primary)] truncate", children: s.label }),
5197
+ s.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-[var(--ds-text-muted)] truncate", children: s.description })
5198
+ ] })
5199
+ ]
5200
+ },
5201
+ s.id
5202
+ ))
5203
+ }
5204
+ ),
5205
+ document.body
4177
5206
  )
4178
- ] }) : null;
4179
- const iconBlock = icon ? /* @__PURE__ */ jsx("span", { className: "shrink-0 h-10 w-10 rounded-[var(--ds-radius-md)] bg-[var(--ds-bg-muted)] flex items-center justify-center mb-ds-1", children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 20, className: "text-[var(--ds-text-secondary)]" }) }) : null;
4180
- if (hasActions) {
4181
- return /* @__PURE__ */ jsx("div", { ref, className: cn(pl, "pr-ds-5 pt-ds-4 last:pb-ds-4", className), ...props, children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-ds-4", children: [
4182
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col space-y-ds-1.5 min-w-0", children: [
4183
- iconBlock,
4184
- children
4185
- ] }),
4186
- actionsBlock
4187
- ] }) });
4188
- }
4189
- return /* @__PURE__ */ jsxs("div", { ref, className: cn("flex flex-col space-y-ds-1.5 pr-ds-5 pt-ds-4 last:pb-ds-4", pl, className), ...props, children: [
4190
- iconBlock,
4191
- children
4192
5207
  ] });
4193
- });
4194
- var CardTitle = forwardRef(function CardTitle2({ className, children, ...props }, forwardedRef) {
4195
- const { ref: overflowRef, isTruncated } = useTextOverflow({ lines: 1 });
4196
- const heading = /* @__PURE__ */ jsx(
4197
- "h3",
4198
- {
4199
- ref: (node) => {
4200
- overflowRef(node);
4201
- if (typeof forwardedRef === "function") forwardedRef(node);
4202
- else if (forwardedRef) forwardedRef.current = node;
4203
- },
4204
- className: cn("font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", className),
4205
- ...props,
4206
- children
4207
- }
4208
- );
4209
- if (!isTruncated) return heading;
4210
- return /* @__PURE__ */ jsx(Tooltip, { content: children, children: heading });
4211
- });
4212
- var cardLineClampClasses = {
4213
- 1: "truncate",
4214
- 2: "line-clamp-2",
4215
- 3: "line-clamp-3",
4216
- 4: "line-clamp-4",
4217
- 5: "line-clamp-5",
4218
- 6: "line-clamp-6"
4219
- };
4220
- var CardDescription = forwardRef(function CardDescription2({ className, children, lines = 2, ...props }, forwardedRef) {
4221
- const { ref: overflowRef, isTruncated } = useTextOverflow({ lines, disabled: lines === 0 });
4222
- const lineClampClass = lines > 0 ? cardLineClampClasses[lines] || `line-clamp-[${lines}]` : "";
4223
- const el = /* @__PURE__ */ jsx(
4224
- "p",
4225
- {
4226
- ref: (node) => {
4227
- if (lines > 0) overflowRef(node);
4228
- if (typeof forwardedRef === "function") forwardedRef(node);
4229
- else if (forwardedRef) forwardedRef.current = node;
4230
- },
4231
- className: cn("text-sm text-[var(--ds-text-muted)]", lines > 0 && lineClampClass, className),
4232
- ...props,
4233
- children
4234
- }
4235
- );
4236
- if (!isTruncated || lines === 0) return el;
4237
- return /* @__PURE__ */ jsx(Tooltip, { content: children, children: el });
4238
- });
4239
- var CardContent = forwardRef(function CardContent2({ className, children, ...props }, ref) {
4240
- const isCheckable = useContext(CardCtx);
4241
- return /* @__PURE__ */ jsx("div", { ref, className: cn("flex-1 pr-ds-5 py-ds-4", isCheckable ? "pl-ds-10" : "pl-ds-5", className), ...props, children });
4242
- });
4243
- var CardFooter = forwardRef(function CardFooter2({ className, children, ...props }, ref) {
4244
- const isCheckable = useContext(CardCtx);
4245
- return /* @__PURE__ */ jsx("div", { ref, className: cn("flex items-center pr-ds-5 pb-ds-4 pt-ds-2 mt-auto min-w-0", isCheckable ? "pl-ds-10" : "pl-ds-5", className), ...props, children });
4246
- });
5208
+ }
4247
5209
  function TruncLabel({ children }) {
4248
5210
  const { ref, isTruncated } = useTextOverflow({ lines: 1 });
4249
5211
  const el = /* @__PURE__ */ jsx("span", { ref, className: "text-xs font-medium text-[var(--ds-text-muted)] uppercase tracking-wider truncate min-w-0", children });
@@ -4305,10 +5267,12 @@ function StatsCard({ value, label, trend, icon, layout = "card", interactive, on
4305
5267
  }
4306
5268
  function TrendBadge({ trend }) {
4307
5269
  const colors = {
4308
- up: "text-[var(--ds-status-success)] bg-[var(--ds-status-success-bg)]",
4309
- down: "text-[var(--ds-status-error)] bg-[var(--ds-status-error-bg)]",
4310
- flat: "text-[var(--ds-text-muted)] bg-[var(--ds-bg-muted)]"
5270
+ positive: "text-[var(--ds-status-success)] bg-[var(--ds-status-success-bg)]",
5271
+ negative: "text-[var(--ds-status-error)] bg-[var(--ds-status-error-bg)]",
5272
+ neutral: "text-[var(--ds-text-muted)] bg-[var(--ds-bg-muted)]"
4311
5273
  };
5274
+ const defaultSentiment = { up: "positive", down: "negative", flat: "neutral" };
5275
+ const sentiment = trend.sentiment ?? defaultSentiment[trend.direction];
4312
5276
  const arrows = { up: "\u2191", down: "\u2193", flat: "\u2192" };
4313
5277
  const { ref, isTruncated } = useTextOverflow({ lines: 1, content: trend.value });
4314
5278
  const badge = /* @__PURE__ */ jsxs(
@@ -4316,7 +5280,7 @@ function TrendBadge({ trend }) {
4316
5280
  {
4317
5281
  className: cn(
4318
5282
  "inline-flex items-center gap-ds-0.5 text-xs font-medium rounded-[var(--ds-radius-sm)] px-ds-1.5 py-ds-0.5 min-w-0 max-w-full",
4319
- colors[trend.direction]
5283
+ colors[sentiment]
4320
5284
  ),
4321
5285
  children: [
4322
5286
  /* @__PURE__ */ jsx("span", { children: arrows[trend.direction] }),
@@ -4381,10 +5345,11 @@ var DescriptionList = forwardRef(function DescriptionList2({
4381
5345
  columns = 1,
4382
5346
  size = "md",
4383
5347
  dividers = false,
4384
- stackBelow,
5348
+ stackBelow: stackBelowProp,
4385
5349
  className
4386
5350
  }, ref) {
4387
5351
  const s = sizeStyles4[size];
5352
+ const stackBelow = stackBelowProp ?? (columns > 1 ? "sm" : void 0);
4388
5353
  if (orientation === "vertical") {
4389
5354
  return /* @__PURE__ */ jsx(
4390
5355
  "dl",
@@ -4394,7 +5359,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
4394
5359
  "grid",
4395
5360
  columnClasses[columns],
4396
5361
  "gap-x-ds-6 gap-y-ds-1",
4397
- stackBelow && stackBreakpoints[stackBelow],
5362
+ stackBelow && stackBelow !== "none" && stackBreakpoints[stackBelow],
4398
5363
  dividers && "divide-y-[length:var(--ds-border-width)] divide-[var(--ds-border-subtle)]",
4399
5364
  className
4400
5365
  ),
@@ -4436,7 +5401,7 @@ var DescriptionList = forwardRef(function DescriptionList2({
4436
5401
  "grid",
4437
5402
  columnClasses[columns],
4438
5403
  "gap-x-ds-6",
4439
- stackBelow && stackBreakpoints[stackBelow],
5404
+ stackBelow && stackBelow !== "none" && stackBreakpoints[stackBelow],
4440
5405
  dividers && "divide-y-[length:var(--ds-border-width)] divide-[var(--ds-border-subtle)]",
4441
5406
  className
4442
5407
  ),
@@ -4643,6 +5608,12 @@ function Table({
4643
5608
  return next;
4644
5609
  });
4645
5610
  };
5611
+ const columnKeys = useMemo(() => columns.map((c) => c.key), [columns]);
5612
+ const inferredKinds = useMemo(() => inferColumnKinds(data, columnKeys), [data, columnKeys]);
5613
+ const kindOf = useCallback(
5614
+ (col) => col.kind ?? inferredKinds.get(col.key),
5615
+ [inferredKinds]
5616
+ );
4646
5617
  const isMobile = useBreakpoint(mobileBreakpoint);
4647
5618
  if (isMobile) {
4648
5619
  if (loading) {
@@ -4675,8 +5646,8 @@ function Table({
4675
5646
  children: [
4676
5647
  selectable && /* @__PURE__ */ jsx(Checkbox, { checked: isSelected, onChange: () => toggleRow(originalIdx), label: "Select" }),
4677
5648
  columns.map((col) => /* @__PURE__ */ jsxs("div", { className: "flex justify-between gap-ds-2 text-sm", children: [
4678
- /* @__PURE__ */ jsx("span", { className: "text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider", children: col.header }),
4679
- /* @__PURE__ */ jsx("span", { className: "text-[var(--ds-text-primary)] text-right", children: row[col.key] })
5649
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[var(--ds-text-secondary)] font-medium text-xs uppercase tracking-wider", children: col.header }),
5650
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 text-[var(--ds-text-primary)] text-right [overflow-wrap:anywhere]", children: row[col.key] })
4680
5651
  ] }, col.key)),
4681
5652
  expandable && renderExpanded && /* @__PURE__ */ jsx("div", { className: "pt-ds-2 border-t-[length:var(--ds-divider-width)] border-[var(--ds-border-subtle)] text-sm text-[var(--ds-text-secondary)]", children: renderExpanded(row, i) })
4682
5653
  ]
@@ -4711,6 +5682,7 @@ function Table({
4711
5682
  columns.map((col) => {
4712
5683
  const isSortable = sortable || col.sortable;
4713
5684
  const isActiveSort = sortKey === col.key;
5685
+ const headerAlign = col.align ?? (kindOf(col) === "number" ? "right" : "left");
4714
5686
  return /* @__PURE__ */ jsx(
4715
5687
  "th",
4716
5688
  {
@@ -4718,7 +5690,7 @@ function Table({
4718
5690
  density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
4719
5691
  "font-[var(--ds-weight-heading)] text-[var(--ds-text-secondary)]",
4720
5692
  "text-xs uppercase tracking-wider",
4721
- col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left",
5693
+ headerAlign === "right" ? "text-right" : headerAlign === "center" ? "text-center" : "text-left",
4722
5694
  isSortable && "cursor-pointer select-none hover:text-[var(--ds-text-primary)]"
4723
5695
  ),
4724
5696
  style: col.maxWidth ? { maxWidth: col.maxWidth } : void 0,
@@ -4799,16 +5771,29 @@ function Table({
4799
5771
  ) }),
4800
5772
  columns.map((col) => {
4801
5773
  const truncLines = col.truncate === true ? 1 : col.truncate ? col.truncate.lines : 0;
5774
+ const kind = kindOf(col);
5775
+ const alignClass = col.align ? col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left" : kind === "number" ? "text-right" : "text-left";
5776
+ const cellContent = row[col.key];
5777
+ let inner;
5778
+ if (truncLines > 0) {
5779
+ inner = /* @__PURE__ */ jsx(TruncCell, { lines: truncLines, children: cellContent });
5780
+ } else if (kind === "email") {
5781
+ inner = /* @__PURE__ */ jsx("span", { className: "max-w-[200px] truncate inline-block", title: typeof cellContent === "string" ? cellContent : void 0, children: cellContent });
5782
+ } else if (kind === "date" || kind === "number") {
5783
+ inner = /* @__PURE__ */ jsx("span", { className: "whitespace-nowrap", children: cellContent });
5784
+ } else {
5785
+ inner = cellContent;
5786
+ }
4802
5787
  return /* @__PURE__ */ jsx(
4803
5788
  "td",
4804
5789
  {
4805
5790
  className: cn(
4806
5791
  density === "compact" ? "px-ds-3 py-ds-2" : "px-ds-4 py-ds-3",
4807
5792
  "text-[var(--ds-text-primary)]",
4808
- col.align === "right" ? "text-right" : col.align === "center" ? "text-center" : "text-left"
5793
+ alignClass
4809
5794
  ),
4810
5795
  style: col.maxWidth ? { maxWidth: col.maxWidth } : void 0,
4811
- children: truncLines > 0 ? /* @__PURE__ */ jsx(TruncCell, { lines: truncLines, children: row[col.key] }) : row[col.key]
5796
+ children: inner
4812
5797
  },
4813
5798
  col.key
4814
5799
  );
@@ -4831,10 +5816,10 @@ function Table({
4831
5816
  );
4832
5817
  }
4833
5818
  var sizes4 = {
4834
- xs: "text-xs h-5 px-ds-2",
4835
- sm: "text-xs h-7 px-ds-3",
4836
- md: "text-sm h-9 px-ds-3",
4837
- lg: "text-base h-11 px-ds-3"
5819
+ xs: "text-xs px-ds-2",
5820
+ sm: "text-xs px-ds-3",
5821
+ md: "text-sm px-ds-3",
5822
+ lg: "text-base px-ds-3"
4838
5823
  };
4839
5824
  var containerPadding = {
4840
5825
  xs: "p-[2px] gap-[2px]",
@@ -4843,22 +5828,26 @@ var containerPadding = {
4843
5828
  lg: "p-ds-1 gap-ds-0.5"
4844
5829
  };
4845
5830
  var indicatorInset = {
4846
- xs: { top: "2px", height: "calc(100% - 4px)" },
4847
- sm: { top: "4px", height: "calc(100% - 8px)" },
4848
- md: { top: "4px", height: "calc(100% - 8px)" },
4849
- lg: { top: "4px", height: "calc(100% - 8px)" }
5831
+ xs: "2px",
5832
+ sm: "4px",
5833
+ md: "4px",
5834
+ lg: "4px"
4850
5835
  };
4851
5836
  function SegmentedControl({
4852
5837
  value,
4853
5838
  onChange,
4854
5839
  options,
4855
- size = "md",
5840
+ size: sizeProp,
4856
5841
  variant = "default",
4857
5842
  fullWidth = false,
4858
5843
  onHoverChange,
4859
5844
  className,
4860
- "aria-label": ariaLabel
5845
+ "aria-label": ariaLabel,
5846
+ maxOptions = 6
4861
5847
  }) {
5848
+ const contextSize = useContext(ControlSizeContext);
5849
+ const size = sizeProp ?? contextSize ?? "md";
5850
+ const collapsed = options.length > maxOptions;
4862
5851
  const containerRef = useRef(null);
4863
5852
  const [indicator, setIndicator] = useState({ left: 0, width: 0 });
4864
5853
  const updateIndicator = useCallback(() => {
@@ -4876,12 +5865,12 @@ function SegmentedControl({
4876
5865
  updateIndicator();
4877
5866
  }, [value, optionsKey, updateIndicator]);
4878
5867
  useLayoutEffect(() => {
4879
- if (!containerRef.current || typeof ResizeObserver === "undefined") return;
5868
+ if (collapsed || !containerRef.current || typeof ResizeObserver === "undefined") return;
4880
5869
  const observer = new ResizeObserver(updateIndicator);
4881
5870
  observer.observe(containerRef.current);
4882
5871
  containerRef.current.querySelectorAll("button").forEach((b) => observer.observe(b));
4883
5872
  return () => observer.disconnect();
4884
- }, [updateIndicator, optionsKey]);
5873
+ }, [updateIndicator, optionsKey, collapsed]);
4885
5874
  const containerHeight = {
4886
5875
  xs: "h-ds-6",
4887
5876
  sm: "h-[var(--ds-control-height-sm)]",
@@ -4906,6 +5895,19 @@ function SegmentedControl({
4906
5895
  if (b.dataset.value === enabled[next].value) b.focus();
4907
5896
  });
4908
5897
  };
5898
+ if (collapsed) {
5899
+ return /* @__PURE__ */ jsx(
5900
+ Dropdown,
5901
+ {
5902
+ "aria-label": ariaLabel,
5903
+ size: size === "md" || size === "lg" ? "md" : "sm",
5904
+ options: options.filter((o) => !o.disabled).map((o) => ({ id: o.value, label: o.label })),
5905
+ value,
5906
+ onChange: (v) => onChange(v),
5907
+ className: cn("inline-block", fullWidth ? "w-full" : "w-auto", className)
5908
+ }
5909
+ );
5910
+ }
4909
5911
  return /* @__PURE__ */ jsxs(
4910
5912
  "div",
4911
5913
  {
@@ -4936,8 +5938,8 @@ function SegmentedControl({
4936
5938
  style: {
4937
5939
  left: indicator.left,
4938
5940
  width: indicator.width,
4939
- top: indicatorInset[size].top,
4940
- height: indicatorInset[size].height,
5941
+ top: indicatorInset[size],
5942
+ bottom: indicatorInset[size],
4941
5943
  transitionDuration: "var(--ds-transition-speed)",
4942
5944
  transitionTimingFunction: "var(--ds-transition-ease)"
4943
5945
  }
@@ -4957,7 +5959,7 @@ function SegmentedControl({
4957
5959
  onMouseEnter: onHoverChange && !opt.disabled ? () => onHoverChange(opt.value) : void 0,
4958
5960
  onMouseLeave: onHoverChange ? () => onHoverChange(null) : void 0,
4959
5961
  className: cn(
4960
- "relative z-10 inline-flex items-center justify-center font-medium whitespace-nowrap",
5962
+ "relative z-10 inline-flex items-center justify-center self-stretch font-medium whitespace-nowrap",
4961
5963
  fullWidth && "flex-1",
4962
5964
  "rounded-[var(--ds-radius-md)]",
4963
5965
  "transition-colors cursor-pointer",
@@ -6535,13 +7537,40 @@ function EmptyState({ icon, iconFrame = "circle", title, description, action, va
6535
7537
  ),
6536
7538
  children: [
6537
7539
  iconFrame === "none" && iconNode ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center mb-ds-4", children: iconNode }) : /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-[var(--ds-radius-full)] bg-[var(--ds-bg-emphasis)] flex items-center justify-center mb-ds-4", children: iconNode ?? /* @__PURE__ */ jsx("span", { className: "text-2xl text-[var(--ds-text-muted)]", children: defaultIcons[variant] }) }),
6538
- /* @__PURE__ */ jsx("h3", { className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
7540
+ /* @__PURE__ */ jsx("h3", { className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] text-center", children: title }),
6539
7541
  description && /* @__PURE__ */ jsx("p", { className: "mt-ds-1 text-sm text-[var(--ds-text-muted)] max-w-sm text-center", children: description }),
6540
7542
  action && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: action })
6541
7543
  ]
6542
7544
  }
6543
7545
  );
6544
7546
  }
7547
+ function EntityCell({ avatar, primary, secondary, size = "md", className }) {
7548
+ const isPhone = useBreakpoint("sm");
7549
+ const avatarElement = typeof avatar === "string" ? /* @__PURE__ */ jsx(Avatar, { src: avatar, alt: primary, size }) : avatar;
7550
+ return /* @__PURE__ */ jsxs(
7551
+ "div",
7552
+ {
7553
+ className: cn(
7554
+ "flex gap-ds-2",
7555
+ isPhone ? "flex-col items-center text-center" : "flex-row items-center",
7556
+ className
7557
+ ),
7558
+ children: [
7559
+ /* @__PURE__ */ jsx("div", { className: "shrink-0", children: avatarElement }),
7560
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
7561
+ /* @__PURE__ */ jsx("p", { className: cn(
7562
+ "font-medium text-[var(--ds-text-primary)] truncate",
7563
+ size === "sm" ? "text-xs" : "text-sm"
7564
+ ), children: primary }),
7565
+ secondary && /* @__PURE__ */ jsx("p", { className: cn(
7566
+ "text-[var(--ds-text-secondary)] truncate",
7567
+ size === "sm" ? "text-xs" : "text-sm"
7568
+ ), children: secondary })
7569
+ ] })
7570
+ ]
7571
+ }
7572
+ );
7573
+ }
6545
7574
  function SkipLink({ href = "#main", children = "Skip to content", className }) {
6546
7575
  return /* @__PURE__ */ jsx(
6547
7576
  "a",
@@ -6559,11 +7588,16 @@ function SkipLink({ href = "#main", children = "Skip to content", className }) {
6559
7588
  );
6560
7589
  }
6561
7590
  function useCompact(ref, breakpoint) {
6562
- const [compact, setCompact] = useState(false);
7591
+ const px = typeof breakpoint === "number" ? breakpoint : readBreakpointPx(breakpoint);
7592
+ const width = useElementWidth(ref);
7593
+ return width > 0 && width < px;
7594
+ }
7595
+ function useElementWidth(ref) {
7596
+ const [width, setWidth] = useState(0);
6563
7597
  const check = useCallback(() => {
6564
- const width = ref.current?.offsetWidth ?? 0;
6565
- if (width > 0) setCompact(width < breakpoint);
6566
- }, [ref, breakpoint]);
7598
+ const next = ref.current?.offsetWidth ?? 0;
7599
+ if (next > 0) setWidth(next);
7600
+ }, [ref]);
6567
7601
  useLayoutEffect(() => {
6568
7602
  check();
6569
7603
  if (!ref.current || typeof ResizeObserver === "undefined") return;
@@ -6571,7 +7605,7 @@ function useCompact(ref, breakpoint) {
6571
7605
  observer.observe(ref.current);
6572
7606
  return () => observer.disconnect();
6573
7607
  }, [check, ref]);
6574
- return compact;
7608
+ return width;
6575
7609
  }
6576
7610
  function TableToolbar({
6577
7611
  search,
@@ -6601,7 +7635,7 @@ function TableToolbar({
6601
7635
  const iconSize = size === "sm" ? 14 : 16;
6602
7636
  const count = activeFilterCount ?? activeFilters?.length ?? 0;
6603
7637
  const hasChips = !!activeFilters?.length;
6604
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-3 min-w-0", className), "data-table-toolbar": "", children: [
7638
+ return /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: size, children: /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-ds-3 min-w-0", className), "data-table-toolbar": "", children: [
6605
7639
  /* @__PURE__ */ jsxs("div", { ref: rowRef, className: "flex items-center gap-ds-2 flex-wrap", children: [
6606
7640
  search && /* @__PURE__ */ jsx(
6607
7641
  Input,
@@ -6664,7 +7698,7 @@ function TableToolbar({
6664
7698
  activeFilters?.map((f) => /* @__PURE__ */ jsx(Tag, { size: "sm", variant: "subtle", onRemove: f.onRemove, children: f.label }, f.id)),
6665
7699
  hasChips && onClearAll && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: onClearAll, children: "Clear all" })
6666
7700
  ] })
6667
- ] });
7701
+ ] }) });
6668
7702
  }
6669
7703
  var dotVariant = {
6670
7704
  default: "bg-[var(--ds-accent-primary)] shadow-[0_0_0_3px_var(--ds-accent-primary)]/20",
@@ -6699,11 +7733,11 @@ function ExpandableDescription({ children, className }) {
6699
7733
  }
6700
7734
  );
6701
7735
  }
6702
- function HorizontalLayout({ items, className }) {
6703
- return /* @__PURE__ */ jsx("div", { className: cn("flex items-start", className), children: items.map((item, i) => {
7736
+ function HorizontalLayout({ items, minItemWidth, className }) {
7737
+ return /* @__PURE__ */ jsx("div", { "data-timeline-row": "", className: cn("flex items-start overflow-x-auto snap-x", className), children: items.map((item, i) => {
6704
7738
  const isFirst = i === 0;
6705
7739
  const isLast = i === items.length - 1;
6706
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col items-center min-w-[100px]", children: [
7740
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-1 shrink-0 flex-col items-center snap-start", style: { minWidth: minItemWidth }, children: [
6707
7741
  /* @__PURE__ */ jsxs("div", { className: "flex items-center w-full", children: [
6708
7742
  /* @__PURE__ */ jsx(
6709
7743
  "div",
@@ -6762,17 +7796,17 @@ function VerticalLayout({ items, className }) {
6762
7796
  ] })
6763
7797
  ] }, i)) });
6764
7798
  }
6765
- function Timeline({ items, orientation = "vertical", className, ref }) {
6766
- if (orientation === "horizontal") {
6767
- return /* @__PURE__ */ jsx("div", { ref, className, children: /* @__PURE__ */ jsx(HorizontalLayout, { items }) });
6768
- }
6769
- if (orientation === "responsive") {
6770
- return /* @__PURE__ */ jsxs("div", { ref, className, children: [
6771
- /* @__PURE__ */ jsx("div", { className: "hidden md:block", children: /* @__PURE__ */ jsx(HorizontalLayout, { items }) }),
6772
- /* @__PURE__ */ jsx("div", { className: "md:hidden", children: /* @__PURE__ */ jsx(VerticalLayout, { items }) })
6773
- ] });
6774
- }
6775
- return /* @__PURE__ */ jsx("div", { ref, className, children: /* @__PURE__ */ jsx(VerticalLayout, { items }) });
7799
+ function Timeline({ items, orientation = "vertical", minItemWidth = 200, className, ref }) {
7800
+ const measureRef = useRef(null);
7801
+ const width = useElementWidth(measureRef);
7802
+ const setRefs = useCallback((node) => {
7803
+ measureRef.current = node;
7804
+ if (typeof ref === "function") ref(node);
7805
+ else if (ref) ref.current = node;
7806
+ }, [ref]);
7807
+ const fits = width === 0 || width >= items.length * minItemWidth;
7808
+ const horizontal = orientation === "horizontal" || orientation === "responsive" && fits;
7809
+ return /* @__PURE__ */ jsx("div", { ref: setRefs, "data-timeline-orientation": horizontal ? "horizontal" : "vertical", className, children: horizontal ? /* @__PURE__ */ jsx(HorizontalLayout, { items, minItemWidth }) : /* @__PURE__ */ jsx(VerticalLayout, { items }) });
6776
7810
  }
6777
7811
  var CollapsibleContext = createContext(null);
6778
7812
  function useCollapsible() {
@@ -7282,147 +8316,6 @@ function Carousel({
7282
8316
  }
7283
8317
  );
7284
8318
  }
7285
- var variantStyles4 = {
7286
- info: "border-[var(--ds-accent-primary)] bg-[var(--ds-accent-subtle)]",
7287
- success: "border-[var(--ds-status-success)] bg-[var(--ds-status-success-bg)]",
7288
- warning: "border-[var(--ds-status-warning)] bg-[var(--ds-status-warning-bg)]",
7289
- error: "border-[var(--ds-status-error)] bg-[var(--ds-status-error-bg)]"
7290
- };
7291
- var indicators = {
7292
- info: "bg-[var(--ds-accent-primary)]",
7293
- success: "bg-[var(--ds-status-success)]",
7294
- warning: "bg-[var(--ds-status-warning)]",
7295
- error: "bg-[var(--ds-status-error)]"
7296
- };
7297
- var actionColorsByVariant = {
7298
- info: "text-[var(--ds-accent-primary)] hover:bg-[var(--ds-accent-muted)]",
7299
- success: "text-[var(--ds-status-success)] hover:bg-[color-mix(in_srgb,var(--ds-status-success)_12%,transparent)]",
7300
- warning: "text-[var(--ds-status-warning)] hover:bg-[color-mix(in_srgb,var(--ds-status-warning)_15%,transparent)]",
7301
- error: "text-[var(--ds-status-error)] hover:bg-[color-mix(in_srgb,var(--ds-status-error)_12%,transparent)]"
7302
- };
7303
- var Alert = forwardRef(function Alert2({
7304
- variant,
7305
- title,
7306
- children,
7307
- dismissible,
7308
- onDismiss,
7309
- action,
7310
- actions,
7311
- placement = "inline",
7312
- expandableContent,
7313
- className
7314
- }, ref) {
7315
- const [detailsExpanded, setDetailsExpanded] = useState(false);
7316
- const isMobile = useBreakpoint("sm");
7317
- const resolvedActions = actions ?? (action ? [action] : []);
7318
- const shouldCollapseActions = isMobile && resolvedActions.length > 1;
7319
- const placementClasses = placement === "page-top" ? "sticky top-0 z-[var(--ds-z-sticky)] rounded-none" : placement === "section-top" ? "rounded-[var(--ds-radius-md)] my-ds-4" : "rounded-[var(--ds-radius-md)]";
7320
- return /* @__PURE__ */ jsxs(
7321
- "div",
7322
- {
7323
- ref,
7324
- role: "alert",
7325
- className: cn(
7326
- "flex items-start gap-ds-3 p-ds-4",
7327
- "border-[length:var(--ds-border-width)]",
7328
- "shadow-[var(--ds-shadow-sm)]",
7329
- "text-sm text-[var(--ds-text-primary)]",
7330
- variantStyles4[variant],
7331
- placementClasses,
7332
- className
7333
- ),
7334
- children: [
7335
- /* @__PURE__ */ jsx("div", { className: cn("mt-[0.3125em] w-3 h-3 shrink-0 rounded-[var(--ds-radius-sm)]", indicators[variant]) }),
7336
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
7337
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-3", children: [
7338
- /* @__PURE__ */ jsx("p", { className: "text-sm font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
7339
- resolvedActions.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: shouldCollapseActions ? /* @__PURE__ */ jsx(
7340
- DropdownMenu,
7341
- {
7342
- trigger: /* @__PURE__ */ jsx(
7343
- "button",
7344
- {
7345
- className: cn(
7346
- "shrink-0 text-xs font-medium px-ds-2.5 py-ds-1 rounded-[var(--ds-radius-sm)]",
7347
- "transition-colors cursor-pointer",
7348
- "border-[length:var(--ds-border-width)] border-current",
7349
- actionColorsByVariant[variant]
7350
- ),
7351
- children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-ds-1", children: [
7352
- /* @__PURE__ */ jsx(Icon, { name: "more-vertical", size: 12 }),
7353
- "Actions"
7354
- ] })
7355
- }
7356
- ),
7357
- items: resolvedActions.map((a) => ({
7358
- label: a.label,
7359
- onClick: a.onClick
7360
- })),
7361
- align: "end"
7362
- }
7363
- ) : resolvedActions.map((a, i) => {
7364
- const effectiveVariant = a.variant ?? (i === 0 ? "secondary" : "outline");
7365
- const isAccent = effectiveVariant === "secondary";
7366
- return /* @__PURE__ */ jsxs(
7367
- "button",
7368
- {
7369
- onClick: a.onClick,
7370
- className: cn(
7371
- "shrink-0 text-xs font-medium px-ds-2.5 py-ds-1 rounded-[var(--ds-radius-sm)]",
7372
- "transition-colors cursor-pointer",
7373
- isAccent ? cn("border-[length:var(--ds-border-width)] border-current", actionColorsByVariant[variant]) : cn("border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]", "text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)] hover:bg-[var(--ds-tab-hover-bg)]")
7374
- ),
7375
- children: [
7376
- a.iconLeft && /* @__PURE__ */ jsx("span", { className: "inline-flex mr-ds-1", children: a.iconLeft }),
7377
- a.label
7378
- ]
7379
- },
7380
- i
7381
- );
7382
- }) })
7383
- ] }),
7384
- children && /* @__PURE__ */ jsx("div", { className: "mt-ds-1 text-xs text-[var(--ds-text-secondary)]", children }),
7385
- expandableContent && /* @__PURE__ */ jsxs("div", { className: "mt-ds-2", children: [
7386
- /* @__PURE__ */ jsxs(
7387
- "button",
7388
- {
7389
- onClick: () => setDetailsExpanded(!detailsExpanded),
7390
- "aria-expanded": detailsExpanded,
7391
- className: cn(
7392
- "inline-flex items-center gap-ds-1 text-xs font-medium cursor-pointer",
7393
- "transition-colors duration-[var(--ds-transition-speed)]",
7394
- actionColorsByVariant[variant],
7395
- "rounded-[var(--ds-radius-sm)] px-ds-1.5 py-ds-0.5"
7396
- ),
7397
- children: [
7398
- /* @__PURE__ */ jsx(
7399
- Icon,
7400
- {
7401
- name: "chevron-right",
7402
- size: 12,
7403
- className: cn("transition-transform duration-[var(--ds-transition-speed)]", detailsExpanded && "rotate-90")
7404
- }
7405
- ),
7406
- detailsExpanded ? "Hide details" : "Show details"
7407
- ]
7408
- }
7409
- ),
7410
- detailsExpanded && /* @__PURE__ */ jsx("div", { className: "mt-ds-2 text-xs text-[var(--ds-text-secondary)] border-l-2 border-current/20 pl-ds-3", children: expandableContent })
7411
- ] })
7412
- ] }),
7413
- dismissible && /* @__PURE__ */ jsx(
7414
- "button",
7415
- {
7416
- onClick: onDismiss,
7417
- className: "shrink-0 text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
7418
- "aria-label": "Dismiss",
7419
- children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 })
7420
- }
7421
- )
7422
- ]
7423
- }
7424
- );
7425
- });
7426
8319
  function formatTime2(d) {
7427
8320
  return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
7428
8321
  }
@@ -7782,95 +8675,50 @@ function ChatPanel({
7782
8675
  return /* @__PURE__ */ jsxs("div", { id: panelId, "data-chat-panel": "", className: cn("flex h-full min-h-0 flex-col bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]", className), children: [
7783
8676
  /* @__PURE__ */ jsxs(
7784
8677
  "header",
7785
- {
7786
- className: "flex shrink-0 items-center gap-ds-3 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
7787
- style: { padding: "var(--ds-space-3) var(--ds-space-4)" },
7788
- children: [
7789
- typeof icon === "string" ? /* @__PURE__ */ jsx("span", { className: "inline-flex h-ds-8 w-ds-8 shrink-0 items-center justify-center rounded-[var(--ds-radius-md)] bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)]", children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 18 }) }) : (
7790
- // An element (an Avatar, a logo) brings its own shape — no tinted box around it.
7791
- /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center justify-center", children: icon })
7792
- ),
7793
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
7794
- /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-ds-2", children: [
7795
- isTruncated ? /* @__PURE__ */ jsx(Tooltip, { content: title, children: heading }) : heading,
7796
- status && /* @__PURE__ */ jsx(StatusDot, { variant: STATUS_VARIANT[status.tone ?? "success"], label: status.label })
7797
- ] }),
7798
- description && /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-[var(--ds-text-muted)]", children: description })
7799
- ] }),
7800
- /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-ds-1", children: [
7801
- actions,
7802
- onNewConversation && /* @__PURE__ */ jsx(Tooltip, { content: "New conversation", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "New conversation", onClick: onNewConversation, children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 16 }) }) }),
7803
- onExpandedChange && /* @__PURE__ */ jsx(Tooltip, { content: expanded ? "Collapse" : "Expand", children: /* @__PURE__ */ jsx(
7804
- Button,
7805
- {
7806
- variant: "ghost",
7807
- size: "icon-sm",
7808
- "aria-label": expanded ? "Collapse" : "Expand",
7809
- "aria-pressed": expanded,
7810
- onClick: () => onExpandedChange(!expanded),
7811
- children: /* @__PURE__ */ jsx(Icon, { name: expanded ? "minimize-2" : "maximize-2", size: 16 })
7812
- }
7813
- ) }),
7814
- /* @__PURE__ */ jsx(Tooltip, { content: "Close", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Close", onClick: onClose, ...{ [OVERLAY_CLOSE_ATTR]: "" }, children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 }) }) })
7815
- ] })
7816
- ]
7817
- }
7818
- ),
7819
- /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col", children }),
7820
- footer && /* @__PURE__ */ jsx(
7821
- "div",
7822
- {
7823
- className: "shrink-0 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-bg-muted)] text-center text-2xs text-[var(--ds-text-muted)]",
7824
- style: { padding: "var(--ds-space-2) var(--ds-space-4)" },
7825
- children: footer
7826
- }
7827
- )
7828
- ] });
7829
- }
7830
- function transitionMs(el) {
7831
- const cs = getComputedStyle(el);
7832
- const parse = (list) => list.split(",").map((raw) => {
7833
- const s = raw.trim();
7834
- if (!s) return 0;
7835
- const n = parseFloat(s);
7836
- if (Number.isNaN(n)) return 0;
7837
- return s.endsWith("ms") ? n : n * 1e3;
7838
- });
7839
- const durations = parse(cs.transitionDuration || "0s");
7840
- const delays = parse(cs.transitionDelay || "0s");
7841
- let max = 0;
7842
- durations.forEach((d, i) => {
7843
- const total = d + (delays[i] ?? delays[0] ?? 0);
7844
- if (total > max) max = total;
7845
- });
7846
- return max;
7847
- }
7848
- function useCloseSettle(open, elRef, onSettled) {
7849
- const cb = useLatest(onSettled);
7850
- useEffect(() => {
7851
- if (open) return;
7852
- const el = elRef.current;
7853
- const ms = el ? transitionMs(el) : 0;
7854
- let done = false;
7855
- const finish = () => {
7856
- if (done) return;
7857
- done = true;
7858
- cb.current();
7859
- };
7860
- if (!el || ms === 0) {
7861
- const t2 = setTimeout(finish, 0);
7862
- return () => clearTimeout(t2);
7863
- }
7864
- const onEnd = (e) => {
7865
- if (e.target === el) finish();
7866
- };
7867
- el.addEventListener("transitionend", onEnd);
7868
- const t = setTimeout(finish, ms + 50);
7869
- return () => {
7870
- el.removeEventListener("transitionend", onEnd);
7871
- clearTimeout(t);
7872
- };
7873
- }, [open, elRef, cb]);
8678
+ {
8679
+ className: "flex shrink-0 items-center gap-ds-3 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
8680
+ style: { padding: "var(--ds-space-3) var(--ds-space-4)" },
8681
+ children: [
8682
+ typeof icon === "string" ? /* @__PURE__ */ jsx("span", { className: "inline-flex h-ds-8 w-ds-8 shrink-0 items-center justify-center rounded-[var(--ds-radius-md)] bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)]", children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 18 }) }) : (
8683
+ // An element (an Avatar, a logo) brings its own shape — no tinted box around it.
8684
+ /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0 items-center justify-center", children: icon })
8685
+ ),
8686
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
8687
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-ds-2", children: [
8688
+ isTruncated ? /* @__PURE__ */ jsx(Tooltip, { content: title, children: heading }) : heading,
8689
+ status && /* @__PURE__ */ jsx(StatusDot, { variant: STATUS_VARIANT[status.tone ?? "success"], label: status.label })
8690
+ ] }),
8691
+ description && /* @__PURE__ */ jsx("p", { className: "truncate text-xs text-[var(--ds-text-muted)]", children: description })
8692
+ ] }),
8693
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-ds-1", children: [
8694
+ actions,
8695
+ onNewConversation && /* @__PURE__ */ jsx(Tooltip, { content: "New conversation", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "New conversation", onClick: onNewConversation, children: /* @__PURE__ */ jsx(Icon, { name: "plus", size: 16 }) }) }),
8696
+ onExpandedChange && /* @__PURE__ */ jsx(Tooltip, { content: expanded ? "Collapse" : "Expand", children: /* @__PURE__ */ jsx(
8697
+ Button,
8698
+ {
8699
+ variant: "ghost",
8700
+ size: "icon-sm",
8701
+ "aria-label": expanded ? "Collapse" : "Expand",
8702
+ "aria-pressed": expanded,
8703
+ onClick: () => onExpandedChange(!expanded),
8704
+ children: /* @__PURE__ */ jsx(Icon, { name: expanded ? "minimize-2" : "maximize-2", size: 16 })
8705
+ }
8706
+ ) }),
8707
+ /* @__PURE__ */ jsx(Tooltip, { content: "Close", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Close", onClick: onClose, ...{ [OVERLAY_CLOSE_ATTR]: "" }, children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 16 }) }) })
8708
+ ] })
8709
+ ]
8710
+ }
8711
+ ),
8712
+ /* @__PURE__ */ jsx("div", { className: "flex min-h-0 flex-1 flex-col", children }),
8713
+ footer && /* @__PURE__ */ jsx(
8714
+ "div",
8715
+ {
8716
+ className: "shrink-0 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-bg-muted)] text-center text-2xs text-[var(--ds-text-muted)]",
8717
+ style: { padding: "var(--ds-space-2) var(--ds-space-4)" },
8718
+ children: footer
8719
+ }
8720
+ )
8721
+ ] });
7874
8722
  }
7875
8723
  var TOAST_INSET_VARS = {
7876
8724
  "bottom-right": "--ds-toast-inset-bottom-right",
@@ -7895,219 +8743,32 @@ function winner(claims) {
7895
8743
  for (const c of claims) {
7896
8744
  if (!best || c.priority > best.priority || c.priority === best.priority && c.seq > best.seq) best = c;
7897
8745
  }
7898
- return best;
7899
- }
7900
- function apply(target, corner) {
7901
- const style = target.style;
7902
- if (!style) return;
7903
- const best = winner(claimsFor(target)[corner]);
7904
- if (best) style.setProperty(TOAST_INSET_VARS[corner], best.inset);
7905
- else style.removeProperty(TOAST_INSET_VARS[corner]);
7906
- }
7907
- function claimCornerInset(corner, inset, priority, target) {
7908
- const claim = { inset, priority, seq: ++seq };
7909
- const list = claimsFor(target)[corner];
7910
- list.push(claim);
7911
- apply(target, corner);
7912
- return () => {
7913
- const i = list.indexOf(claim);
7914
- if (i >= 0) list.splice(i, 1);
7915
- apply(target, corner);
7916
- };
7917
- }
7918
- function useCornerInset(corner, inset, priority, target) {
7919
- useEffect(() => {
7920
- if (!corner || !inset) return;
7921
- const el = target ?? document.documentElement;
7922
- return claimCornerInset(corner, inset, priority, el);
7923
- }, [corner, inset, priority, target]);
7924
- }
7925
- function Sheet({ open, onClose, title, children, footer, snapPoints = [0.5, 0.92], container, flush, keepMounted = false, id, labelledBy }) {
7926
- const titleId = useId();
7927
- const panelRef = useRef(null);
7928
- const [mounted, setMounted] = useState(open);
7929
- const [hidden, setHidden] = useState(!open);
7930
- const [snapIdx, setSnapIdx] = useState(0);
7931
- const [dragOffset, setDragOffset] = useState(0);
7932
- const [dragging, setDragging] = useState(false);
7933
- const dragStartY = useRef(0);
7934
- const startHeight = useRef(0);
7935
- const onCloseRef = useLatest(onClose);
7936
- const [prevOpen, setPrevOpen] = useState(open);
7937
- if (open !== prevOpen) {
7938
- setPrevOpen(open);
7939
- if (open) {
7940
- setMounted(true);
7941
- setHidden(false);
7942
- setSnapIdx(0);
7943
- setDragOffset(0);
7944
- }
7945
- }
7946
- const viewportHeight = useCallback(
7947
- () => container instanceof HTMLElement ? container.clientHeight : window.innerHeight,
7948
- [container]
7949
- );
7950
- useCloseSettle(open, panelRef, () => {
7951
- if (keepMounted) setHidden(true);
7952
- else setMounted(false);
7953
- });
7954
- useReturnFocus(open);
7955
- useEffect(() => {
7956
- if (!open || !mounted) return;
7957
- const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
7958
- return () => cancelAnimationFrame(raf);
7959
- }, [open, mounted]);
7960
- const isTopLayer = useOverlayLayer(open);
7961
- useFocusTrap(panelRef, open, isTopLayer);
7962
- useEffect(() => {
7963
- if (!open) return;
7964
- const onKeyDown = (e) => {
7965
- if (e.key === "Escape" && isTopLayer()) onCloseRef.current();
7966
- };
7967
- document.addEventListener("keydown", onKeyDown);
7968
- if (!container) lockBodyScroll();
7969
- return () => {
7970
- document.removeEventListener("keydown", onKeyDown);
7971
- if (!container) unlockBodyScroll();
7972
- };
7973
- }, [open, container, onCloseRef, isTopLayer]);
7974
- const handlePointerDown = useCallback((e) => {
7975
- setDragging(true);
7976
- dragStartY.current = e.clientY;
7977
- startHeight.current = (snapPoints[snapIdx] ?? snapPoints[0]) * viewportHeight();
7978
- setDragOffset(0);
7979
- e.target.setPointerCapture(e.pointerId);
7980
- }, [snapIdx, snapPoints, viewportHeight]);
7981
- const handlePointerMove = useCallback((e) => {
7982
- if (!dragging) return;
7983
- const delta = dragStartY.current - e.clientY;
7984
- setDragOffset(delta);
7985
- }, [dragging]);
7986
- const handlePointerUp = useCallback(() => {
7987
- if (!dragging) return;
7988
- setDragging(false);
7989
- const currentHeightPx = startHeight.current + dragOffset;
7990
- const currentFraction = currentHeightPx / viewportHeight();
7991
- if (currentFraction < snapPoints[0] * 0.6) {
7992
- onClose();
7993
- setDragOffset(0);
7994
- return;
7995
- }
7996
- let bestIdx = 0;
7997
- let bestDist = Math.abs(currentFraction - snapPoints[0]);
7998
- for (let i = 1; i < snapPoints.length; i++) {
7999
- const dist = Math.abs(currentFraction - snapPoints[i]);
8000
- if (dist < bestDist) {
8001
- bestDist = dist;
8002
- bestIdx = i;
8003
- }
8004
- }
8005
- setSnapIdx(bestIdx);
8006
- setDragOffset(0);
8007
- }, [dragging, dragOffset, snapPoints, onClose, viewportHeight]);
8008
- if (!mounted) return null;
8009
- const baseHeight = (snapPoints[snapIdx] ?? snapPoints[0]) * 100;
8010
- const heightUnit = container ? "%" : "vh";
8011
- const dragPx = dragging ? dragOffset : 0;
8012
- const positionClass = container ? "absolute" : "fixed";
8013
- return createPortal(
8014
- /* @__PURE__ */ jsxs(
8015
- "div",
8016
- {
8017
- hidden: keepMounted && hidden ? true : void 0,
8018
- className: cn(
8019
- `${positionClass} inset-0 z-[var(--ds-z-modal)] transition-opacity duration-[var(--ds-transition-speed)]`,
8020
- open ? "pointer-events-auto" : "pointer-events-none"
8021
- ),
8022
- children: [
8023
- /* @__PURE__ */ jsx(
8024
- "div",
8025
- {
8026
- className: cn(
8027
- "absolute inset-0 bg-black/50 transition-opacity duration-[var(--ds-transition-speed)]",
8028
- open ? "opacity-100" : "opacity-0"
8029
- ),
8030
- onClick: onClose
8031
- }
8032
- ),
8033
- /* @__PURE__ */ jsxs(
8034
- "div",
8035
- {
8036
- ref: panelRef,
8037
- id,
8038
- role: "dialog",
8039
- "aria-modal": "true",
8040
- "aria-labelledby": title ? titleId : labelledBy,
8041
- "data-ds-sheet": "",
8042
- className: cn(
8043
- `${positionClass} bottom-0 left-0 right-0 z-10 flex flex-col`,
8044
- "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
8045
- GLASS_OVERLAY,
8046
- "border-t-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
8047
- "rounded-t-[var(--ds-radius-xl)]",
8048
- !dragging && "transition-[transform,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
8049
- open ? "translate-y-0" : "translate-y-full"
8050
- ),
8051
- style: {
8052
- containerType: "inline-size",
8053
- height: dragPx ? `calc(${baseHeight}${heightUnit} + ${dragPx}px)` : `${baseHeight}${heightUnit}`
8054
- },
8055
- children: [
8056
- /* @__PURE__ */ jsx(
8057
- "div",
8058
- {
8059
- className: "flex justify-center pt-ds-2 pb-ds-1 cursor-grab active:cursor-grabbing touch-none",
8060
- onPointerDown: handlePointerDown,
8061
- onPointerMove: handlePointerMove,
8062
- onPointerUp: handlePointerUp,
8063
- onPointerCancel: handlePointerUp,
8064
- children: /* @__PURE__ */ jsx("div", { className: "w-10 h-1 rounded-[var(--ds-radius-full)] bg-[var(--ds-border-default)]" })
8065
- }
8066
- ),
8067
- title && /* @__PURE__ */ jsxs(
8068
- "div",
8069
- {
8070
- className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
8071
- style: { padding: "var(--ds-space-2) var(--ds-space-5)" },
8072
- children: [
8073
- /* @__PURE__ */ jsx("h2", { id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
8074
- /* @__PURE__ */ jsx(
8075
- "button",
8076
- {
8077
- onClick: onClose,
8078
- ...{ [OVERLAY_CLOSE_ATTR]: "" },
8079
- className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
8080
- "aria-label": "Close",
8081
- children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
8082
- }
8083
- )
8084
- ]
8085
- }
8086
- ),
8087
- /* @__PURE__ */ jsx(
8088
- "div",
8089
- {
8090
- className: "flex-1 overflow-y-auto",
8091
- style: flush ? void 0 : { padding: "var(--ds-space-5)" },
8092
- children
8093
- }
8094
- ),
8095
- footer && /* @__PURE__ */ jsx(
8096
- "div",
8097
- {
8098
- className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
8099
- style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
8100
- children: footer
8101
- }
8102
- )
8103
- ]
8104
- }
8105
- )
8106
- ]
8107
- }
8108
- ),
8109
- container ?? document.body
8110
- );
8746
+ return best;
8747
+ }
8748
+ function apply(target, corner) {
8749
+ const style = target.style;
8750
+ if (!style) return;
8751
+ const best = winner(claimsFor(target)[corner]);
8752
+ if (best) style.setProperty(TOAST_INSET_VARS[corner], best.inset);
8753
+ else style.removeProperty(TOAST_INSET_VARS[corner]);
8754
+ }
8755
+ function claimCornerInset(corner, inset, priority, target) {
8756
+ const claim = { inset, priority, seq: ++seq };
8757
+ const list = claimsFor(target)[corner];
8758
+ list.push(claim);
8759
+ apply(target, corner);
8760
+ return () => {
8761
+ const i = list.indexOf(claim);
8762
+ if (i >= 0) list.splice(i, 1);
8763
+ apply(target, corner);
8764
+ };
8765
+ }
8766
+ function useCornerInset(corner, inset, priority, target) {
8767
+ useEffect(() => {
8768
+ if (!corner || !inset) return;
8769
+ const el = target ?? document.documentElement;
8770
+ return claimCornerInset(corner, inset, priority, el);
8771
+ }, [corner, inset, priority, target]);
8111
8772
  }
8112
8773
  var DEFAULT_OFFSET = "var(--ds-space-4)";
8113
8774
  var CORNER_PANEL_ANCHOR_INSET = "calc(var(--ds-space-12) + var(--ds-space-3))";
@@ -8148,388 +8809,74 @@ function CornerPanel({
8148
8809
  labelledBy,
8149
8810
  keepMounted,
8150
8811
  container,
8151
- className,
8152
- children
8153
- }
8154
- );
8155
- }
8156
- var RIBBON_INSET = "calc(var(--ds-space-8) + var(--ds-space-3))";
8157
- function CornerWindow({ open, onClose, edge, align, width, height, offset, anchorInset, expanded, id, labelledBy, keepMounted, container, children, className }) {
8158
- const panelRef = useRef(null);
8159
- const [mounted, setMounted] = useState(open);
8160
- const [hidden, setHidden] = useState(!open);
8161
- if (open && !mounted) setMounted(true);
8162
- if (open && hidden) setHidden(false);
8163
- const side = edge.endsWith("left") ? "left" : "right";
8164
- const vertical = edge.startsWith("bottom") ? "bottom" : edge.startsWith("top") ? "top" : "side";
8165
- const x = offset?.x ?? (vertical === "side" ? RIBBON_INSET : DEFAULT_OFFSET);
8166
- const y = offset?.y ?? DEFAULT_OFFSET;
8167
- const bottom = vertical === "bottom" ? `calc(${y} + ${anchorInset})` : y;
8168
- const isTopLayer = useOverlayLayer(open);
8169
- useNonModalDialog(panelRef, open && mounted, onClose, isTopLayer);
8170
- useCloseSettle(open, panelRef, () => {
8171
- if (keepMounted) setHidden(true);
8172
- else setMounted(false);
8173
- });
8174
- const claim = vertical === "bottom" ? side === "right" ? "bottom-right" : "bottom-left" : side;
8175
- const containerEl = container instanceof Element ? container : null;
8176
- useCornerInset(
8177
- open && mounted && !expanded ? claim : null,
8178
- vertical === "bottom" ? `calc(${bottom} + ${height} + var(--ds-space-3))` : `calc(${x} + ${width} + var(--ds-space-3))`,
8179
- PANEL_INSET_PRIORITY,
8180
- containerEl
8181
- );
8182
- if (!mounted) return null;
8183
- const positionClass = container ? "absolute" : "fixed";
8184
- const viewport = container ? "100%" : "100dvh";
8185
- const style = expanded ? { top: y, bottom: vertical === "top" ? DEFAULT_OFFSET : y, left: vertical === "side" ? DEFAULT_OFFSET : x, right: vertical === "side" ? DEFAULT_OFFSET : x } : {
8186
- ...vertical === "bottom" ? { bottom: `calc(${bottom} + env(safe-area-inset-bottom))`, maxHeight: `calc(${viewport} - ${bottom} - ${y})` } : vertical === "top" ? { top: `calc(${y} + env(safe-area-inset-top))`, maxHeight: `calc(${viewport} - ${y} - ${DEFAULT_OFFSET})` } : align === "center" ? { top: `max(${y}, calc(50% - ${height} / 2))`, maxHeight: `calc(${viewport} - ${y} * 2)` } : { bottom: `calc(${y} + env(safe-area-inset-bottom))`, maxHeight: `calc(${viewport} - ${y} * 2)` },
8187
- [side]: `calc(${x} + env(safe-area-inset-${side}))`,
8188
- width,
8189
- height,
8190
- maxWidth: `calc(100% - ${x} - ${DEFAULT_OFFSET})`
8191
- };
8192
- return createPortal(
8193
- /* @__PURE__ */ jsx(
8194
- "div",
8195
- {
8196
- ref: panelRef,
8197
- id,
8198
- role: "dialog",
8199
- "aria-labelledby": labelledBy,
8200
- hidden: keepMounted && hidden ? true : void 0,
8201
- "data-corner-panel": "",
8202
- "data-edge": edge,
8203
- "data-expanded": expanded || void 0,
8204
- style,
8205
- className: cn(
8206
- positionClass,
8207
- "z-[var(--ds-z-overlay)] flex flex-col overflow-hidden",
8208
- "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
8209
- // The dropdown grade, like Popover and NotificationCenter: it floats over a
8210
- // live page with no backdrop, so the modal shadow reads far too heavy.
8211
- GLASS_DROPDOWN,
8212
- "rounded-[var(--ds-radius-lg)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
8213
- "transition-[opacity,transform,inset,width,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
8214
- vertical === "bottom" ? side === "right" ? "origin-bottom-right" : "origin-bottom-left" : vertical === "top" ? side === "right" ? "origin-top-right" : "origin-top-left" : side === "right" ? "origin-right" : "origin-left",
8215
- open ? "opacity-100 translate-y-0 scale-100" : vertical === "top" ? "opacity-0 -translate-y-ds-2 scale-95" : "opacity-0 translate-y-ds-2 scale-95",
8216
- className
8217
- ),
8218
- children
8219
- }
8220
- ),
8221
- container ?? document.body
8222
- );
8223
- }
8224
- var STEP = 16;
8225
- var BIG_STEP = 64;
8226
- function clamp(v, min, max) {
8227
- return Math.min(Math.max(v, min), max);
8228
- }
8229
- function ResizeEdge({ edge, width, min, max, defaultWidth, onResize, label, onDraggingChange, className }) {
8230
- const [dragging, setDragging] = useState(false);
8231
- const start = useRef(null);
8232
- const latestOnResize = useLatest(onResize);
8233
- const direction = edge === "left" ? -1 : 1;
8234
- const onPointerDown = useCallback(
8235
- (e) => {
8236
- if (e.button !== 0) return;
8237
- e.preventDefault();
8238
- start.current = { x: e.clientX, width };
8239
- setDragging(true);
8240
- e.currentTarget.setPointerCapture(e.pointerId);
8241
- },
8242
- [width]
8243
- );
8244
- const onPointerMove = useCallback(
8245
- (e) => {
8246
- if (!start.current) return;
8247
- const next = clamp(start.current.width + direction * (e.clientX - start.current.x), min, max());
8248
- latestOnResize.current(next);
8249
- },
8250
- [direction, min, max, latestOnResize]
8251
- );
8252
- const endDrag = useCallback(() => {
8253
- start.current = null;
8254
- setDragging(false);
8255
- }, []);
8256
- const latestOnDraggingChange = useLatest(onDraggingChange);
8257
- useEffect(() => {
8258
- latestOnDraggingChange.current?.(dragging);
8259
- }, [dragging, latestOnDraggingChange]);
8260
- useEffect(() => {
8261
- if (!dragging) return;
8262
- const onKey = (e) => {
8263
- if (e.key !== "Escape" || !start.current) return;
8264
- latestOnResize.current(start.current.width);
8265
- endDrag();
8266
- };
8267
- document.addEventListener("keydown", onKey);
8268
- return () => document.removeEventListener("keydown", onKey);
8269
- }, [dragging, endDrag, latestOnResize]);
8270
- const onKeyDown = (e) => {
8271
- const step = e.shiftKey ? BIG_STEP : STEP;
8272
- let next = null;
8273
- if (e.key === "ArrowLeft") next = width - direction * step;
8274
- else if (e.key === "ArrowRight") next = width + direction * step;
8275
- else if (e.key === "Home") next = min;
8276
- else if (e.key === "End") next = max();
8277
- else if (e.key === "Enter") next = defaultWidth;
8278
- if (next === null) return;
8279
- e.preventDefault();
8280
- onResize(clamp(next, min, max()));
8281
- };
8282
- return /* @__PURE__ */ jsx(
8283
- "div",
8284
- {
8285
- role: "separator",
8286
- tabIndex: 0,
8287
- "aria-orientation": "vertical",
8288
- "aria-label": label,
8289
- "aria-valuemin": min,
8290
- "aria-valuemax": max(),
8291
- "aria-valuenow": Math.round(width),
8292
- "data-resize-edge": edge,
8293
- "data-dragging": dragging || void 0,
8294
- onPointerDown,
8295
- onPointerMove,
8296
- onPointerUp: endDrag,
8297
- onPointerCancel: endDrag,
8298
- onDoubleClick: () => onResize(clamp(defaultWidth, min, max())),
8299
- onKeyDown,
8300
- className: cn(
8301
- // A narrow absolutely-positioned strip over the edge — never a flex child that takes width.
8302
- "group/edge absolute top-0 bottom-0 z-10 w-ds-2 cursor-col-resize touch-none select-none outline-none",
8303
- edge === "left" ? "-left-ds-1" : "-right-ds-1",
8304
- className
8305
- ),
8306
- children: /* @__PURE__ */ jsx(
8307
- "div",
8308
- {
8309
- "aria-hidden": "true",
8310
- className: cn(
8311
- "absolute top-0 bottom-0 left-1/2 w-px -translate-x-1/2 transition-[width,background-color] duration-[var(--ds-transition-speed)]",
8312
- "group-hover/edge:w-[3px] group-hover/edge:bg-[var(--ds-accent-primary)]",
8313
- "group-focus-visible/edge:w-[3px] group-focus-visible/edge:bg-[var(--ds-accent-primary)]",
8314
- dragging && "w-[3px] bg-[var(--ds-accent-primary)]"
8315
- )
8316
- }
8317
- )
8318
- }
8319
- );
8320
- }
8321
- var remembered = /* @__PURE__ */ new Map();
8322
- function useRememberedWidth(key) {
8323
- const [width, setWidth] = useState(() => key ? remembered.get(key) ?? null : null);
8324
- const remember = useCallback(
8325
- (w) => {
8326
- setWidth(w);
8327
- if (!key) return;
8328
- if (w === null) remembered.delete(key);
8329
- else remembered.set(key, w);
8330
- },
8331
- [key]
8332
- );
8333
- return [width, remember];
8334
- }
8335
- function pxOf(length) {
8336
- if (!length) return null;
8337
- const m = /^(\d+(?:\.\d+)?)px$/.exec(length.trim());
8338
- return m ? parseFloat(m[1]) : null;
8339
- }
8340
- function defaultMaxWidth(container) {
8341
- const base = container instanceof HTMLElement ? container.clientWidth : typeof window !== "undefined" ? window.innerWidth : 1200;
8342
- return Math.round(base * 0.6);
8343
- }
8344
- var slideClasses = {
8345
- right: {
8346
- panel: "top-0 right-0 h-full",
8347
- open: "translate-x-0",
8348
- closed: "translate-x-full"
8349
- },
8350
- left: {
8351
- panel: "top-0 left-0 h-full",
8352
- open: "translate-x-0",
8353
- closed: "-translate-x-full"
8354
- },
8355
- bottom: {
8356
- panel: "bottom-0 left-0 right-0",
8357
- open: "translate-y-0",
8358
- closed: "translate-y-full"
8359
- }
8360
- };
8361
- var borderByPosition = {
8362
- right: "border-l-[length:var(--ds-border-width)] border-l-[var(--ds-border-default)]",
8363
- left: "border-r-[length:var(--ds-border-width)] border-r-[var(--ds-border-default)]",
8364
- bottom: "border-t-[length:var(--ds-border-width)] border-t-[var(--ds-border-default)]"
8365
- };
8366
- function Drawer(props) {
8367
- const { position = "right", mobile, snapPoints, open, onClose, title, children, footer, container, flush, keepMounted, id, labelledBy } = props;
8368
- const isPhone = useBreakpoint("sm");
8369
- const mobileMode = mobile ?? (position === "left" ? "panel" : "sheet");
8370
- if (isPhone && mobileMode === "sheet") {
8371
- return /* @__PURE__ */ jsx(Sheet, { open, onClose, title, footer, container, flush, snapPoints, keepMounted, id, labelledBy, children });
8372
- }
8373
- return /* @__PURE__ */ jsx(DrawerPanel, { ...props });
8374
- }
8375
- function DrawerPanel({ open, onClose, position = "right", width = "400px", title, children, footer, container, flush, lightBackdrop, topOffset, modal = true, keepMounted = false, id, labelledBy, resizable = false, maxWidth }) {
8376
- const nonModal = !modal;
8377
- const [chosen, remember] = useRememberedWidth(id ?? labelledBy);
8378
- const canResize = nonModal && resizable && position !== "bottom";
8379
- const effectiveWidth = canResize && chosen !== null ? `${chosen}px` : width;
8380
- const minPx = pxOf(width) ?? 320;
8381
- const maxPx = () => pxOf(maxWidth) ?? defaultMaxWidth(container instanceof Element ? container : null);
8382
- const titleId = useId();
8383
- const { ref: titleOverflowRef, isTruncated: titleTruncated } = useTextOverflow({ lines: 1 });
8384
- const isMobile = useBreakpoint("sm");
8812
+ className,
8813
+ children
8814
+ }
8815
+ );
8816
+ }
8817
+ var RIBBON_INSET = "calc(var(--ds-space-8) + var(--ds-space-3))";
8818
+ function CornerWindow({ open, onClose, edge, align, width, height, offset, anchorInset, expanded, id, labelledBy, keepMounted, container, children, className }) {
8385
8819
  const panelRef = useRef(null);
8386
8820
  const [mounted, setMounted] = useState(open);
8387
8821
  const [hidden, setHidden] = useState(!open);
8388
- const onCloseRef = useLatest(onClose);
8389
8822
  if (open && !mounted) setMounted(true);
8390
8823
  if (open && hidden) setHidden(false);
8824
+ const side = edge.endsWith("left") ? "left" : "right";
8825
+ const vertical = edge.startsWith("bottom") ? "bottom" : edge.startsWith("top") ? "top" : "side";
8826
+ const x = offset?.x ?? (vertical === "side" ? RIBBON_INSET : DEFAULT_OFFSET);
8827
+ const y = offset?.y ?? DEFAULT_OFFSET;
8828
+ const bottom = vertical === "bottom" ? `calc(${y} + ${anchorInset})` : y;
8391
8829
  const isTopLayer = useOverlayLayer(open);
8392
- useEffect(() => {
8393
- if (!open || nonModal) return;
8394
- const onKeyDown = (e) => {
8395
- if (e.key === "Escape" && isTopLayer()) onCloseRef.current();
8396
- };
8397
- document.addEventListener("keydown", onKeyDown);
8398
- if (!container) lockBodyScroll();
8399
- return () => {
8400
- document.removeEventListener("keydown", onKeyDown);
8401
- if (!container) unlockBodyScroll();
8402
- };
8403
- }, [open, nonModal, container, onCloseRef, isTopLayer]);
8404
- useReturnFocus(open && !nonModal);
8405
- useFocusTrap(panelRef, open && !topOffset && !nonModal, isTopLayer);
8406
- useEffect(() => {
8407
- if (!open || !mounted || nonModal) return;
8408
- const raf = requestAnimationFrame(() => focusInitial(panelRef.current));
8409
- return () => cancelAnimationFrame(raf);
8410
- }, [open, mounted, nonModal]);
8411
- useNonModalDialog(panelRef, open && mounted && nonModal, onClose, isTopLayer);
8830
+ useNonModalDialog(panelRef, open && mounted, onClose, isTopLayer);
8412
8831
  useCloseSettle(open, panelRef, () => {
8413
8832
  if (keepMounted) setHidden(true);
8414
8833
  else setMounted(false);
8415
8834
  });
8835
+ const claim = vertical === "bottom" ? side === "right" ? "bottom-right" : "bottom-left" : side;
8836
+ const containerEl = container instanceof Element ? container : null;
8837
+ useCornerInset(
8838
+ open && mounted && !expanded ? claim : null,
8839
+ vertical === "bottom" ? `calc(${bottom} + ${height} + var(--ds-space-3))` : `calc(${x} + ${width} + var(--ds-space-3))`,
8840
+ PANEL_INSET_PRIORITY,
8841
+ containerEl
8842
+ );
8416
8843
  if (!mounted) return null;
8417
- const slide = slideClasses[position];
8418
- const isHorizontal = position === "left" || position === "right";
8419
8844
  const positionClass = container ? "absolute" : "fixed";
8845
+ const viewport = container ? "100%" : "100dvh";
8846
+ const style = expanded ? { top: y, bottom: vertical === "top" ? DEFAULT_OFFSET : y, left: vertical === "side" ? DEFAULT_OFFSET : x, right: vertical === "side" ? DEFAULT_OFFSET : x } : {
8847
+ ...vertical === "bottom" ? { bottom: `calc(${bottom} + env(safe-area-inset-bottom))`, maxHeight: `calc(${viewport} - ${bottom} - ${y})` } : vertical === "top" ? { top: `calc(${y} + env(safe-area-inset-top))`, maxHeight: `calc(${viewport} - ${y} - ${DEFAULT_OFFSET})` } : align === "center" ? { top: `max(${y}, calc(50% - ${height} / 2))`, maxHeight: `calc(${viewport} - ${y} * 2)` } : { bottom: `calc(${y} + env(safe-area-inset-bottom))`, maxHeight: `calc(${viewport} - ${y} * 2)` },
8848
+ [side]: `calc(${x} + env(safe-area-inset-${side}))`,
8849
+ width,
8850
+ height,
8851
+ maxWidth: `calc(100% - ${x} - ${DEFAULT_OFFSET})`
8852
+ };
8420
8853
  return createPortal(
8421
- /* @__PURE__ */ jsxs(
8854
+ /* @__PURE__ */ jsx(
8422
8855
  "div",
8423
8856
  {
8857
+ ref: panelRef,
8858
+ id,
8859
+ role: "dialog",
8860
+ "aria-labelledby": labelledBy,
8424
8861
  hidden: keepMounted && hidden ? true : void 0,
8862
+ "data-corner-panel": "",
8863
+ "data-edge": edge,
8864
+ "data-expanded": expanded || void 0,
8865
+ style,
8425
8866
  className: cn(
8426
- `${positionClass} transition-opacity duration-[var(--ds-transition-speed)]`,
8427
- // A non-modal panel never intercepts the page: the wrapper is inert to the
8428
- // pointer and only the panel itself accepts events.
8429
- nonModal ? "z-[var(--ds-z-overlay)] pointer-events-none" : cn("z-[var(--ds-z-modal)]", open ? "pointer-events-auto" : "pointer-events-none"),
8430
- topOffset ? "left-0 right-0 bottom-0" : "inset-0"
8867
+ positionClass,
8868
+ "z-[var(--ds-z-overlay)] flex flex-col overflow-hidden",
8869
+ "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
8870
+ // The dropdown grade, like Popover and NotificationCenter: it floats over a
8871
+ // live page with no backdrop, so the modal shadow reads far too heavy.
8872
+ GLASS_DROPDOWN,
8873
+ "rounded-[var(--ds-radius-lg)] border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
8874
+ "transition-[opacity,transform,inset,width,height] duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
8875
+ vertical === "bottom" ? side === "right" ? "origin-bottom-right" : "origin-bottom-left" : vertical === "top" ? side === "right" ? "origin-top-right" : "origin-top-left" : side === "right" ? "origin-right" : "origin-left",
8876
+ open ? "opacity-100 translate-y-0 scale-100" : vertical === "top" ? "opacity-0 -translate-y-ds-2 scale-95" : "opacity-0 translate-y-ds-2 scale-95",
8877
+ className
8431
8878
  ),
8432
- style: topOffset ? { top: topOffset } : void 0,
8433
- children: [
8434
- !nonModal && /* @__PURE__ */ jsx(
8435
- "div",
8436
- {
8437
- className: cn(
8438
- "absolute inset-0 transition-opacity duration-[var(--ds-transition-speed)]",
8439
- lightBackdrop ? "bg-black/15" : cn("bg-black/50", "[backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))] [-webkit-backdrop-filter:blur(calc(var(--ds-glass-blur)*0.3))]"),
8440
- open ? "opacity-100" : "opacity-0"
8441
- ),
8442
- onClick: onClose
8443
- }
8444
- ),
8445
- /* @__PURE__ */ jsxs(
8446
- "div",
8447
- {
8448
- ref: panelRef,
8449
- id,
8450
- role: "dialog",
8451
- "aria-modal": nonModal ? void 0 : "true",
8452
- "aria-labelledby": title ? titleId : labelledBy,
8453
- style: {
8454
- containerType: "inline-size",
8455
- width: isHorizontal ? effectiveWidth : void 0,
8456
- maxWidth: isHorizontal ? "100%" : void 0,
8457
- height: isMobile ? "100%" : void 0,
8458
- maxHeight: !isMobile && !isHorizontal ? "80vh" : void 0
8459
- },
8460
- className: cn(
8461
- `${positionClass} z-10 flex flex-col`,
8462
- nonModal && "pointer-events-auto",
8463
- "bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]",
8464
- GLASS_OVERLAY,
8465
- // flush drops the edge border for children that draw their own (the mobile
8466
- // menu's Sidebar); a non-modal panel has no backdrop to separate it from
8467
- // the page, so it always keeps the border.
8468
- (!flush || nonModal) && borderByPosition[position],
8469
- "transition-transform duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
8470
- isHorizontal && position === "left" && "rounded-r-[var(--ds-radius-lg)] overflow-hidden",
8471
- isHorizontal && position === "right" && "rounded-l-[var(--ds-radius-lg)] overflow-hidden",
8472
- !isHorizontal && "rounded-t-[var(--ds-radius-lg)] overflow-hidden",
8473
- (lightBackdrop || nonModal) && "shadow-[var(--ds-shadow-overlay)]",
8474
- slide.panel,
8475
- open ? slide.open : slide.closed
8476
- ),
8477
- children: [
8478
- canResize && open && /* @__PURE__ */ jsx(
8479
- ResizeEdge,
8480
- {
8481
- edge: position === "right" ? "left" : "right",
8482
- width: chosen ?? minPx,
8483
- min: minPx,
8484
- max: maxPx,
8485
- defaultWidth: minPx,
8486
- onResize: (w) => remember(w === minPx ? null : w),
8487
- label: "Resize panel"
8488
- }
8489
- ),
8490
- title && /* @__PURE__ */ jsxs(
8491
- "div",
8492
- {
8493
- className: "flex items-center justify-between shrink-0 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
8494
- style: {
8495
- padding: "var(--ds-space-3) var(--ds-space-6)",
8496
- minHeight: "calc(var(--ds-space-unit) * 6 + 1.75rem + 2px + var(--ds-border-width))"
8497
- },
8498
- children: [
8499
- titleTruncated ? /* @__PURE__ */ jsx(Tooltip, { content: title, children: /* @__PURE__ */ jsx("h2", { ref: titleOverflowRef, id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }) }) : /* @__PURE__ */ jsx("h2", { ref: titleOverflowRef, id: titleId, className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
8500
- /* @__PURE__ */ jsx(
8501
- "button",
8502
- {
8503
- onClick: onClose,
8504
- ...{ [OVERLAY_CLOSE_ATTR]: "" },
8505
- className: "text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] transition-colors cursor-pointer",
8506
- "aria-label": "Close",
8507
- children: /* @__PURE__ */ jsx(Icon, { name: "close", size: 18 })
8508
- }
8509
- )
8510
- ]
8511
- }
8512
- ),
8513
- /* @__PURE__ */ jsx(
8514
- "div",
8515
- {
8516
- className: "flex-1 overflow-y-auto",
8517
- style: flush ? void 0 : { padding: "var(--ds-space-5)" },
8518
- children
8519
- }
8520
- ),
8521
- footer && /* @__PURE__ */ jsx(
8522
- "div",
8523
- {
8524
- className: "shrink-0 flex items-center justify-end gap-ds-2 border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
8525
- style: { padding: "var(--ds-space-3) var(--ds-space-5)" },
8526
- children: footer
8527
- }
8528
- )
8529
- ]
8530
- }
8531
- )
8532
- ]
8879
+ children
8533
8880
  }
8534
8881
  ),
8535
8882
  container ?? document.body
@@ -8588,10 +8935,28 @@ var AppShell = forwardRef(function AppShell2({
8588
8935
  const navbarFloating = (chrome.navbar ?? theme?.navbarPosition) === "floating";
8589
8936
  const sidebarFloating = hasSidebar && !isMobile && (chrome.sidebar ?? theme?.sidebarPosition) === "floating";
8590
8937
  const isHome = currentPath != null && currentPath === homePath;
8938
+ const hasFooter = footer != null && scrollable;
8939
+ const mainRef = useRef(null);
8940
+ useEffect(() => {
8941
+ const main = mainRef.current;
8942
+ if (!hasFooter || !shellEl || !main || typeof ResizeObserver === "undefined") {
8943
+ shellEl?.style.removeProperty("--ds-main-height");
8944
+ return;
8945
+ }
8946
+ const ro = new ResizeObserver(() => shellEl.style.setProperty("--ds-main-height", `${main.clientHeight}px`));
8947
+ ro.observe(main);
8948
+ return () => {
8949
+ ro.disconnect();
8950
+ shellEl.style.removeProperty("--ds-main-height");
8951
+ };
8952
+ }, [hasFooter, shellEl]);
8953
+ const hasLauncher = !!launcher && !isSmallMobile;
8954
+ const launcherProps = isValidElement(launcher) ? launcher.props : null;
8955
+ const launcherCorner = !hasLauncher ? null : launcherProps?.variant === "ribbon" ? null : launcherProps?.edge === "bottom-left" ? "bottom-left" : launcherProps?.edge === "right" || launcherProps?.edge === "left" || launcherProps?.edge === "bottom" ? null : "bottom-right";
8591
8956
  return /* @__PURE__ */ jsx(
8592
8957
  AppShellContext,
8593
8958
  {
8594
- value: { hasSidebar, hasMobileMenu, hasMobileNav, sidebarOpen, setSidebarOpen, isMobile, isTablet, sidebarCollapsed, setSidebarCollapsed: setUserCollapsed, asideOpen, setAsideOpen, asideSide, asideFloating, setAsideFloating, container: shellEl, theme: theme ?? null, isHome, navbarFloating, sidebarFloating, registerChrome },
8959
+ value: { hasSidebar, hasMobileMenu, hasMobileNav, sidebarOpen, setSidebarOpen, isMobile, isTablet, sidebarCollapsed, setSidebarCollapsed: setUserCollapsed, asideOpen, setAsideOpen, asideSide, asideFloating, setAsideFloating, container: shellEl, theme: theme ?? null, isHome, navbarFloating, sidebarFloating, registerChrome, hasLauncher, launcherCorner, hasFooter },
8595
8960
  children: /* @__PURE__ */ jsxs("div", { ref: (el) => {
8596
8961
  setShellEl(el);
8597
8962
  if (typeof ref === "function") ref(el);
@@ -8609,6 +8974,7 @@ var AppShell = forwardRef(function AppShell2({
8609
8974
  /* @__PURE__ */ jsx(
8610
8975
  "main",
8611
8976
  {
8977
+ ref: mainRef,
8612
8978
  id: mainId,
8613
8979
  tabIndex: -1,
8614
8980
  className: cn(
@@ -8812,8 +9178,10 @@ var StackedList = forwardRef(function StackedList2({
8812
9178
  divided = true,
8813
9179
  flush = false,
8814
9180
  selectedId,
9181
+ hover = "tint",
8815
9182
  className
8816
9183
  }, ref) {
9184
+ const isPhone = useBreakpoint("sm");
8817
9185
  return /* @__PURE__ */ jsx(
8818
9186
  "ul",
8819
9187
  {
@@ -8859,7 +9227,7 @@ var StackedList = forwardRef(function StackedList2({
8859
9227
  // (1.5× the tab rail; still 0 under tint and pill). Every row carries
8860
9228
  // the rail width as a transparent placeholder so content never shifts.
8861
9229
  "border-l-[length:calc(var(--ds-nav-v-active-rail)*1.5)]",
8862
- isSelected ? "bg-[var(--ds-nav-v-active-bg)] text-[var(--ds-nav-v-active-text)] border-[var(--ds-accent-primary)]" : cn("border-transparent", interactive && "hover:bg-[var(--ds-tab-hover-bg)]")
9230
+ isSelected ? "bg-[var(--ds-nav-v-active-bg)] text-[var(--ds-nav-v-active-text)] border-[var(--ds-accent-primary)]" : cn("border-transparent", interactive && hover === "tint" && "hover:bg-[var(--ds-tab-hover-bg)]", interactive && hover === "title" && "group/row")
8863
9231
  ),
8864
9232
  onClick: item.onClick,
8865
9233
  role: interactive ? "button" : void 0,
@@ -8874,23 +9242,25 @@ var StackedList = forwardRef(function StackedList2({
8874
9242
  children: [
8875
9243
  item.leading && /* @__PURE__ */ jsx("div", { className: cn("shrink-0", multiline && "mt-ds-0.5"), children: item.leading }),
8876
9244
  /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
8877
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-ds-2", children: [
9245
+ /* @__PURE__ */ jsxs("div", { className: cn("flex gap-ds-2", isPhone ? "flex-col" : "items-center justify-between"), children: [
8878
9246
  /* @__PURE__ */ jsx(
8879
9247
  TruncText,
8880
9248
  {
8881
9249
  className: cn(
8882
9250
  "text-sm",
8883
- isSelected ? "font-medium text-[var(--ds-nav-v-active-text)]" : hasEmphasis && !item.unread ? "text-[var(--ds-text-secondary)]" : "font-medium text-[var(--ds-text-primary)]"
9251
+ isSelected ? "font-medium text-[var(--ds-nav-v-active-text)]" : hasEmphasis && !item.unread ? "text-[var(--ds-text-secondary)]" : "font-medium text-[var(--ds-text-primary)]",
9252
+ // hover="title": the title answers the pointer (accent, underline) instead of the row's background
9253
+ interactive && hover === "title" && !isSelected && "transition-colors group-hover/row:text-[var(--ds-accent-primary)] group-hover/row:underline underline-offset-2"
8884
9254
  ),
8885
9255
  children: item.title
8886
9256
  }
8887
9257
  ),
8888
- multiline && trailing
9258
+ (multiline || isPhone) && trailing
8889
9259
  ] }),
8890
9260
  item.subtitle && /* @__PURE__ */ jsx(TruncText, { className: cn("text-sm", isSelected ? "text-[var(--ds-nav-v-active-muted)]" : "text-[var(--ds-text-secondary)]"), children: item.subtitle }),
8891
9261
  item.description && /* @__PURE__ */ jsx(TruncText, { className: cn("text-xs", isSelected ? "text-[var(--ds-nav-v-active-muted)]" : "text-[var(--ds-text-muted)]"), children: item.description })
8892
9262
  ] }),
8893
- !multiline && trailing,
9263
+ !multiline && !isPhone && trailing,
8894
9264
  item.actions && /* @__PURE__ */ jsx(
8895
9265
  "div",
8896
9266
  {
@@ -9471,6 +9841,109 @@ var Tabs = Object.assign(TabsRoot, {
9471
9841
  Trigger: TabsTrigger,
9472
9842
  Content: TabsContent
9473
9843
  });
9844
+ var MIN_PANEL_WIDTH = 480;
9845
+ function SettingsLayout({
9846
+ sections,
9847
+ value,
9848
+ onChange,
9849
+ layout: layoutProp,
9850
+ railWidth = 220,
9851
+ collapseBelow = railWidth + MIN_PANEL_WIDTH,
9852
+ "aria-label": ariaLabel = "Settings sections",
9853
+ children,
9854
+ className
9855
+ }) {
9856
+ const shell = useAppShell();
9857
+ const layout = layoutProp ?? shell?.theme?.settingsLayout ?? "sidebar";
9858
+ const rootRef = useRef(null);
9859
+ const compact = useCompact(rootRef, collapseBelow);
9860
+ const tabs = sections.map((s) => ({ id: s.id, label: s.label, icon: s.icon, group: s.group, disabled: s.disabled }));
9861
+ const stickyTop = shell ? "var(--ds-sticky-offset, 0px)" : "calc(var(--ds-navbar-height) + var(--ds-sticky-offset, 0px))";
9862
+ if (layout === "tabs") {
9863
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "tabs", className: cn("flex flex-col gap-ds-6", className), children: [
9864
+ /* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, children: /* @__PURE__ */ jsx(Tabs, { orientation: "horizontal", mobile: "dropdown", tabs, activeTab: value, onTabChange: onChange }) }),
9865
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children })
9866
+ ] });
9867
+ }
9868
+ if (compact) {
9869
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "sidebar", "data-collapsed": "true", className: cn("flex flex-col gap-ds-6", className), children: [
9870
+ /* @__PURE__ */ jsx(
9871
+ Dropdown,
9872
+ {
9873
+ "aria-label": ariaLabel,
9874
+ options: sections.filter((s) => !s.disabled).map((s) => ({ id: s.id, label: s.label, group: s.group })),
9875
+ value,
9876
+ onChange: (v) => onChange(v)
9877
+ }
9878
+ ),
9879
+ /* @__PURE__ */ jsx("div", { className: "min-w-0", children })
9880
+ ] });
9881
+ }
9882
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-settings-layout": "sidebar", className: cn("flex flex-row items-start gap-ds-8", className), children: [
9883
+ /* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel, className: "sticky self-start shrink-0", style: { width: `${railWidth}px`, top: stickyTop }, children: /* @__PURE__ */ jsx(Tabs, { orientation: "vertical", tabs, activeTab: value, onTabChange: onChange, className: "w-full" }) }),
9884
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children })
9885
+ ] });
9886
+ }
9887
+ function SplitView({
9888
+ list,
9889
+ detail,
9890
+ aside,
9891
+ asideTitle = "Details",
9892
+ detailOpen = false,
9893
+ onDetailClose,
9894
+ detailMode = "stack",
9895
+ backLabel = "Back",
9896
+ listWidth = 35,
9897
+ listMinWidth = 25,
9898
+ asideWidth = 25,
9899
+ collapseBelow = 768,
9900
+ asideCollapseBelow = 1024,
9901
+ bordered = false,
9902
+ frame = "page",
9903
+ "aria-label": ariaLabel,
9904
+ className
9905
+ }) {
9906
+ const rootRef = useRef(null);
9907
+ const compact = useCompact(rootRef, collapseBelow);
9908
+ const asideCollapsed = useCompact(rootRef, asideCollapseBelow);
9909
+ const [asideOpen, setAsideOpen] = useState(false);
9910
+ useEffect(() => {
9911
+ if (!asideCollapsed) setAsideOpen(false);
9912
+ }, [asideCollapsed]);
9913
+ const region = ariaLabel ? { role: "region", "aria-label": ariaLabel } : {};
9914
+ const isFill = frame === "fill";
9915
+ const shell = useAppShell();
9916
+ const fillStyle = isFill && shell?.hasFooter ? { height: "var(--ds-main-height, 100%)" } : void 0;
9917
+ const surface = cn(
9918
+ "h-full min-h-0 w-full bg-[var(--ds-bg-surface)]",
9919
+ isFill && "rounded-none border-0",
9920
+ bordered && !isFill && "border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] rounded-[var(--ds-radius-md)] overflow-hidden",
9921
+ className
9922
+ );
9923
+ if (compact) {
9924
+ const showDetail = detailMode === "stack" && detailOpen;
9925
+ return /* @__PURE__ */ jsx("div", { ref: rootRef, "data-split-view": showDetail ? "detail" : "list", "data-frame": frame, ...region, className: cn(surface, "flex flex-col"), style: fillStyle, children: showDetail ? /* @__PURE__ */ jsxs(Fragment, { children: [
9926
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 px-ds-3 py-ds-2 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", iconLeft: /* @__PURE__ */ jsx(Icon, { name: "arrow-left", size: 14 }), onClick: onDetailClose, children: backLabel }) }),
9927
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-y-auto", children: detail })
9928
+ ] }) : /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-y-auto", children: list }) });
9929
+ }
9930
+ const asideToggle = aside && asideCollapsed ? /* @__PURE__ */ jsx("div", { className: "shrink-0 flex justify-end px-ds-3 py-ds-2 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]", children: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", iconLeft: /* @__PURE__ */ jsx(Icon, { name: "info", size: 14 }), onClick: () => setAsideOpen(true), "aria-expanded": asideOpen, children: asideTitle }) }) : null;
9931
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, "data-split-view": "split", "data-frame": frame, ...region, className: surface, style: fillStyle, children: [
9932
+ /* @__PURE__ */ jsxs(ResizablePanelGroup, { direction: "horizontal", stackOnMobile: false, className: "h-full", children: [
9933
+ /* @__PURE__ */ jsx(ResizablePanel, { id: "list", defaultSize: `${listWidth}%`, minSize: `${listMinWidth}%`, children: /* @__PURE__ */ jsx("div", { "data-pane": "list", className: "h-full min-h-0 overflow-y-auto", children: list }) }),
9934
+ /* @__PURE__ */ jsx(ResizableHandle, { withHandle: true }),
9935
+ /* @__PURE__ */ jsx(ResizablePanel, { id: "detail", minSize: "30%", children: /* @__PURE__ */ jsxs("div", { "data-pane": "detail", className: "h-full min-h-0 flex flex-col", children: [
9936
+ asideToggle,
9937
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-y-auto", children: detail })
9938
+ ] }) }),
9939
+ aside && !asideCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
9940
+ /* @__PURE__ */ jsx(ResizableHandle, { withHandle: true }),
9941
+ /* @__PURE__ */ jsx(ResizablePanel, { id: "aside", defaultSize: `${asideWidth}%`, minSize: "15%", children: /* @__PURE__ */ jsx("div", { "data-pane": "aside", className: "h-full min-h-0 overflow-y-auto", children: aside }) })
9942
+ ] })
9943
+ ] }),
9944
+ aside && asideCollapsed && /* @__PURE__ */ jsx(Drawer, { open: asideOpen, onClose: () => setAsideOpen(false), title: asideTitle, position: "right", children: aside })
9945
+ ] });
9946
+ }
9474
9947
  function SeparatorIcon({ type, size }) {
9475
9948
  const iconSize = size === "sm" ? 10 : 12;
9476
9949
  if (type === "chevron") return /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: iconSize });
@@ -9881,7 +10354,7 @@ function EllipsisJumper({ totalPages, onPageChange }) {
9881
10354
  type: "button",
9882
10355
  onClick: handleGo,
9883
10356
  className: cn(
9884
- "px-ds-2.5 h-8 text-xs font-medium cursor-pointer",
10357
+ "px-ds-2.5 h-[var(--ds-control-height-sm)] text-xs font-medium cursor-pointer",
9885
10358
  "rounded-[var(--ds-radius-md)]",
9886
10359
  "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)]",
9887
10360
  "transition-colors duration-[var(--ds-transition-speed)]",
@@ -10317,9 +10790,11 @@ var Sidebar = forwardRef(function Sidebar2({
10317
10790
  }
10318
10791
  return /* @__PURE__ */ jsx(SidebarContext, { value: { collapsed, onCollapsedChange: handleCollapsedChange, portalContainer: portalEl, type, position: "flush", navbarFloating: !!navbarFloating, navSize }, children: aside });
10319
10792
  });
10320
- function TruncLabel3({ children, className, side = "right", container }) {
10321
- const { ref, isTruncated } = useTextOverflow({ lines: 1 });
10322
- const label = /* @__PURE__ */ jsx("span", { ref, className: cn("truncate", className), children });
10793
+ function TruncLabel3({ children, className, side = "right", container, lines = 1 }) {
10794
+ const { ref, isTruncated } = useTextOverflow({ lines });
10795
+ const clampMap = { 2: "line-clamp-2", 3: "line-clamp-3" };
10796
+ const clampClass = lines <= 1 ? "truncate" : clampMap[lines] ?? "truncate";
10797
+ const label = /* @__PURE__ */ jsx("span", { ref, className: cn(clampClass, className), children });
10323
10798
  if (!isTruncated) return label;
10324
10799
  return /* @__PURE__ */ jsx(Tooltip, { content: children, side, delay: 200, container, children: label });
10325
10800
  }
@@ -10792,7 +11267,7 @@ function CompactNavItem({
10792
11267
  className: cn((item.active || childActive) && "text-[var(--ds-sidebar-active-accent)]")
10793
11268
  }
10794
11269
  ),
10795
- /* @__PURE__ */ jsx(TruncLabel3, { className: "text-[clamp(9px,var(--ds-font-size-2xs),12px)] leading-tight max-w-full", side: "right", container: portalContainer ?? void 0, children: item.label }),
11270
+ /* @__PURE__ */ jsx(TruncLabel3, { className: "text-[clamp(9px,var(--ds-font-size-2xs),12px)] leading-tight max-w-full text-center", lines: 2, side: "right", container: portalContainer ?? void 0, children: item.label }),
10796
11271
  mobile && hasChildren && /* @__PURE__ */ jsx(
10797
11272
  Icon,
10798
11273
  {
@@ -10966,7 +11441,8 @@ function resolvePageHeader(theme, props, facts) {
10966
11441
  breadcrumbSeparator: props.breadcrumbSeparator ?? b.separator ?? "chevron",
10967
11442
  navbarFloating,
10968
11443
  sidebarFloating,
10969
- outside: variant === "colourful" || behavior === "snapping" || position === "floating"
11444
+ outside: variant === "colourful" || behavior === "snapping" || position === "floating",
11445
+ overlap: variant === "colourful" && (t.overlap ?? false)
10970
11446
  };
10971
11447
  }
10972
11448
  var maxWidthValues = {
@@ -10996,6 +11472,11 @@ var bottomPaddingClasses = {
10996
11472
  default: "pb-ds-12",
10997
11473
  spacious: "pb-ds-16"
10998
11474
  };
11475
+ var bottomPaddingValues = {
11476
+ none: "0px",
11477
+ default: "var(--ds-space-12)",
11478
+ spacious: "var(--ds-space-16)"
11479
+ };
10999
11480
  var FLOATING_BLOCK = cn(
11000
11481
  "rounded-[var(--ds-radius-md)]",
11001
11482
  "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
@@ -11011,6 +11492,14 @@ function isPageHeaderElement(node) {
11011
11492
  const type = node.type;
11012
11493
  return !!type && typeof type !== "string" && type[PAGE_HEADER_MARK] === true;
11013
11494
  }
11495
+ var OVERLAP_MIN = 24;
11496
+ var OVERLAP_MAX = 64;
11497
+ function overlapTarget(column) {
11498
+ const first = column?.firstElementChild ?? null;
11499
+ if (!first) return null;
11500
+ const bare = first.tagName === "DIV" && !first.getAttribute("style") && !(first.getAttribute("class") ?? "").split(/\s+/).some((c) => /^(?:p[xytblr]?-|m[xytblr]?-|bg-|border|rounded|shadow|grid|@)/.test(c));
11501
+ return bare && first.firstElementChild ? first.firstElementChild : first;
11502
+ }
11014
11503
  function floatingBlockPadding(navbarFloating, sidebarFloating, overlap) {
11015
11504
  return {
11016
11505
  paddingTop: navbarFloating ? 0 : "var(--ds-space-3)",
@@ -11031,11 +11520,63 @@ var PageContainer = forwardRef(function PageContainer2({
11031
11520
  renderHeader
11032
11521
  }, ref) {
11033
11522
  const shell = useAppShell();
11523
+ const rootRef = useRef(null);
11524
+ const setRoot = useCallback((node) => {
11525
+ rootRef.current = node;
11526
+ if (typeof ref === "function") ref(node);
11527
+ else if (ref) ref.current = node;
11528
+ }, [ref]);
11529
+ const setPinnedHeight = useCallback((px) => {
11530
+ if (px) rootRef.current?.style.setProperty("--ds-sticky-offset", `${px}px`);
11531
+ else rootRef.current?.style.removeProperty("--ds-sticky-offset");
11532
+ }, []);
11034
11533
  const resolvedMaxWidth = width ? widthToMaxWidth[width] : maxWidth;
11035
11534
  const maxWidthValue = maxWidthValues[resolvedMaxWidth];
11036
11535
  const kids = Children.toArray(children);
11037
11536
  const headerIdx = kids.findIndex(isPageHeaderElement);
11038
- if (headerIdx === -1) {
11537
+ const launcherCorner = shell?.launcherCorner ?? null;
11538
+ const vPad = verticalPadding ?? "default";
11539
+ const launcherPadding = launcherCorner ? { paddingBottom: `max(${bottomPaddingValues[vPad]}, var(--ds-toast-inset-${launcherCorner}, 0px))` } : {};
11540
+ const headerEl = headerIdx === -1 ? null : kids[headerIdx];
11541
+ const r = headerEl ? resolvePageHeader(shell?.theme, headerEl.props, {
11542
+ isHome: shell?.isHome ?? false,
11543
+ isMobile: shell?.isMobile ?? false,
11544
+ navbarFloating: shell?.navbarFloating ?? false,
11545
+ sidebarFloating: shell?.sidebarFloating ?? false
11546
+ }) : null;
11547
+ const overlapActive = !!r && r.variant === "colourful" && r.overlap;
11548
+ const columnRef = useRef(null);
11549
+ const observedRef = useRef(null);
11550
+ useEffect(() => {
11551
+ const stop = () => {
11552
+ observedRef.current?.ro.disconnect();
11553
+ observedRef.current = null;
11554
+ };
11555
+ if (!overlapActive) {
11556
+ stop();
11557
+ rootRef.current?.style.removeProperty("--ds-overlap");
11558
+ return;
11559
+ }
11560
+ const target = overlapTarget(columnRef.current);
11561
+ if (!target) {
11562
+ stop();
11563
+ return;
11564
+ }
11565
+ if (observedRef.current?.target === target) return;
11566
+ stop();
11567
+ if (typeof ResizeObserver === "undefined") return;
11568
+ const ro = new ResizeObserver(([entry]) => {
11569
+ const h = entry.contentRect.height;
11570
+ rootRef.current?.style.setProperty("--ds-overlap", `${Math.min(OVERLAP_MAX, Math.max(OVERLAP_MIN, Math.round(h / 2)))}px`);
11571
+ });
11572
+ ro.observe(target);
11573
+ observedRef.current = { target, ro };
11574
+ });
11575
+ useEffect(() => () => {
11576
+ observedRef.current?.ro.disconnect();
11577
+ observedRef.current = null;
11578
+ }, []);
11579
+ if (headerIdx === -1 || !headerEl || !r) {
11039
11580
  return /* @__PURE__ */ jsx(
11040
11581
  "div",
11041
11582
  {
@@ -11043,23 +11584,16 @@ var PageContainer = forwardRef(function PageContainer2({
11043
11584
  className: cn(
11044
11585
  "w-full",
11045
11586
  paddingClasses[padding],
11046
- verticalPaddingClasses[verticalPadding ?? "default"],
11587
+ verticalPaddingClasses[vPad],
11047
11588
  centered && "mx-auto",
11048
11589
  className
11049
11590
  ),
11050
- style: { maxWidth: maxWidthValue, containerType: "inline-size" },
11591
+ style: { maxWidth: maxWidthValue, containerType: "inline-size", ...launcherPadding },
11051
11592
  children
11052
11593
  }
11053
11594
  );
11054
11595
  }
11055
- const headerEl = kids[headerIdx];
11056
11596
  const rest = kids.filter((_, i) => i !== headerIdx);
11057
- const r = resolvePageHeader(shell?.theme, headerEl.props, {
11058
- isHome: shell?.isHome ?? false,
11059
- isMobile: shell?.isMobile ?? false,
11060
- navbarFloating: shell?.navbarFloating ?? false,
11061
- sidebarFloating: shell?.sidebarFloating ?? false
11062
- });
11063
11597
  const snapping = r.behavior === "snapping";
11064
11598
  const floatingHeader = r.position === "floating";
11065
11599
  const colourful = r.variant === "colourful";
@@ -11068,22 +11602,18 @@ var PageContainer = forwardRef(function PageContainer2({
11068
11602
  const block = floatingHeader && contained && !snapping;
11069
11603
  const placement = block ? "block" : r.outside ? "outside" : "inside";
11070
11604
  const breadcrumbsInsideHeader = snapping && floatingHeader && contained;
11071
- const overlap = colourful && typeof headerEl.props.overlapHeight === "number" && headerEl.props.overlapHeight > 0 ? headerEl.props.overlapHeight : 0;
11072
- const strip = contained && !breadcrumbsInsideHeader && crumbs ? (
11073
- // The strip is the whole trail: the path, then this page as the current item (Breadcrumbs renders the last item as text).
11074
- /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth: maxWidthValue, separator: r.breadcrumbSeparator, items: headerEl.props.title ? [...crumbs, { label: headerEl.props.title }] : crumbs })
11075
- ) : null;
11605
+ const strip = contained && !breadcrumbsInsideHeader && crumbs ? /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth: maxWidthValue, separator: r.breadcrumbSeparator, items: headerEl.props.title ? [...crumbs, { label: headerEl.props.title }] : crumbs }) : null;
11076
11606
  const columnClass = (pad2) => cn("w-full", paddingClasses[pad2], centered && "mx-auto");
11077
11607
  const columnStyle = { maxWidth: maxWidthValue, containerType: "inline-size" };
11078
- const header = /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement, containedBreadcrumbs: contained, breadcrumbsInsideHeader, noBottomMargin: block }, children: renderHeader ? renderHeader(headerEl) : headerEl });
11608
+ const header = /* @__PURE__ */ jsx(PageContainerContext, { value: { contentMaxWidth: maxWidthValue, placement, containedBreadcrumbs: contained, breadcrumbsInsideHeader, noBottomMargin: block, overlap: overlapActive, setPinnedHeight }, children: renderHeader ? renderHeader(headerEl) : headerEl });
11079
11609
  const contentPadding = floatingHeader && shell?.isMobile ? "none" : padding;
11080
- const wrapperStyle = floatingHeader || overlap ? {
11610
+ const wrapperStyle = floatingHeader || overlapActive ? {
11081
11611
  ...floatingHeader ? { paddingRight: "var(--ds-space-3)", paddingLeft: r.sidebarFloating ? 0 : "var(--ds-space-3)" } : {},
11082
- ...overlap ? { marginTop: -overlap, position: "relative", zIndex: 1 } : {}
11612
+ ...overlapActive ? { marginTop: "calc(-1 * var(--ds-overlap, 0px))", position: "relative", zIndex: 1 } : {}
11083
11613
  } : void 0;
11084
- const column = /* @__PURE__ */ jsx("div", { className: cn(columnClass(contentPadding), bottomPaddingClasses[verticalPadding ?? "default"], className), style: columnStyle, children: rest });
11085
- return /* @__PURE__ */ jsxs("div", { ref, "data-page-container": "", className: "w-full", children: [
11086
- placement === "block" ? /* @__PURE__ */ jsx("div", { style: floatingBlockPadding(r.navbarFloating, r.sidebarFloating, overlap > 0), children: /* @__PURE__ */ jsxs("div", { className: FLOATING_BLOCK, children: [
11614
+ const column = /* @__PURE__ */ jsx("div", { ref: columnRef, className: cn(columnClass(contentPadding), bottomPaddingClasses[vPad], className), style: { ...columnStyle, ...launcherPadding }, children: rest });
11615
+ return /* @__PURE__ */ jsxs("div", { ref: setRoot, "data-page-container": "", className: "w-full", children: [
11616
+ placement === "block" ? /* @__PURE__ */ jsx("div", { style: floatingBlockPadding(r.navbarFloating, r.sidebarFloating, overlapActive), children: /* @__PURE__ */ jsxs("div", { className: FLOATING_BLOCK, children: [
11087
11617
  strip,
11088
11618
  colourful ? header : /* @__PURE__ */ jsx("div", { className: columnClass(padding), style: columnStyle, children: header })
11089
11619
  ] }) }) : placement === "outside" ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -11224,7 +11754,6 @@ var PageHeader = forwardRef(function PageHeader2({
11224
11754
  behavior: behaviorProp,
11225
11755
  intensity: intensityProp,
11226
11756
  backgroundImage,
11227
- overlapHeight,
11228
11757
  expandedContent,
11229
11758
  collapseOffset = 100,
11230
11759
  pinned = true,
@@ -11263,6 +11792,7 @@ var PageHeader = forwardRef(function PageHeader2({
11263
11792
  const hideExpandedBreadcrumbs = hideExpandedBreadcrumbsProp ?? (!!container?.containedBreadcrumbs && snapping);
11264
11793
  const containedBreadcrumbs = containedBreadcrumbsProp ?? (container?.breadcrumbsInsideHeader && breadcrumbs?.length ? /* @__PURE__ */ jsx(Breadcrumbs, { variant: "contained", itemVariant: r.breadcrumbStyle, bleed: true, contentMaxWidth, separator: bcSep, items: [...breadcrumbs, { label: title }] }) : void 0);
11265
11794
  const noBottomMargin = noBottomMarginProp ?? container?.noBottomMargin;
11795
+ const overlapActive = container?.overlap ?? false;
11266
11796
  if (behavior === "snapping") {
11267
11797
  return /* @__PURE__ */ jsx(
11268
11798
  SnappingHeader,
@@ -11282,7 +11812,7 @@ var PageHeader = forwardRef(function PageHeader2({
11282
11812
  variant,
11283
11813
  intensity,
11284
11814
  backgroundImage,
11285
- overlapHeight,
11815
+ overlapActive,
11286
11816
  tabs,
11287
11817
  breadcrumbPill: bcPill,
11288
11818
  breadcrumbSeparator: bcSep,
@@ -11336,7 +11866,7 @@ var PageHeader = forwardRef(function PageHeader2({
11336
11866
  filters,
11337
11867
  intensity,
11338
11868
  backgroundImage,
11339
- overlapHeight,
11869
+ overlapActive,
11340
11870
  contentMaxWidth,
11341
11871
  breadcrumbPill: bcPill,
11342
11872
  breadcrumbSeparator: bcSep,
@@ -11371,7 +11901,6 @@ var PageHeader = forwardRef(function PageHeader2({
11371
11901
  );
11372
11902
  }
11373
11903
  if (isFloating) {
11374
- const overlapActive = variant === "colourful" && !!overlapHeight;
11375
11904
  return /* @__PURE__ */ jsx(
11376
11905
  "div",
11377
11906
  {
@@ -11452,7 +11981,7 @@ function DefaultHeader({
11452
11981
  ] }),
11453
11982
  actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions })
11454
11983
  ] }),
11455
- filters && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-3 mt-ds-4", children: filters })
11984
+ filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) })
11456
11985
  ] })
11457
11986
  ]
11458
11987
  }
@@ -11480,7 +12009,7 @@ function MinimalHeader({
11480
12009
  /* @__PURE__ */ jsx(TruncHeading, { as: Heading, lines: 1, className: "font-[family-name:var(--ds-font-display)] text-xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
11481
12010
  badge
11482
12011
  ] }),
11483
- actions && /* @__PURE__ */ jsx(ButtonSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
12012
+ actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
11484
12013
  ] })
11485
12014
  ] }) });
11486
12015
  }
@@ -11495,7 +12024,7 @@ function ColourfulHeader({
11495
12024
  filters,
11496
12025
  intensity = "bold",
11497
12026
  backgroundImage,
11498
- overlapHeight,
12027
+ overlapActive,
11499
12028
  contentMaxWidth,
11500
12029
  breadcrumbPill,
11501
12030
  breadcrumbSeparator,
@@ -11513,7 +12042,7 @@ function ColourfulHeader({
11513
12042
  ref: headerRef,
11514
12043
  className: cn(
11515
12044
  "relative overflow-hidden w-full",
11516
- !isFloating && !overlapHeight && !noBottomMargin && "mb-ds-6",
12045
+ !isFloating && !overlapActive && !noBottomMargin && "mb-ds-6",
11517
12046
  isBold ? "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box]" : "bg-[var(--ds-tint-base)]",
11518
12047
  isFloating ? cn(
11519
12048
  "rounded-[var(--ds-radius-md)]",
@@ -11548,7 +12077,7 @@ function ColourfulHeader({
11548
12077
  style: {
11549
12078
  maxWidth: contentMaxWidth ?? "var(--ds-bp-xl)",
11550
12079
  containerType: "inline-size",
11551
- ...overlapHeight ? { paddingBottom: `calc(var(--ds-space-6) + ${overlapHeight}px)` } : {}
12080
+ ...overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px))` } : {}
11552
12081
  },
11553
12082
  children: [
11554
12083
  hasBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, onLight: isBold, onTint: !isBold, pill: breadcrumbPill, separator: breadcrumbSeparator }),
@@ -11575,7 +12104,7 @@ function ColourfulHeader({
11575
12104
  ] }),
11576
12105
  actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions })
11577
12106
  ] }),
11578
- filters && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-3 mt-ds-4", children: filters })
12107
+ filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) })
11579
12108
  ]
11580
12109
  }
11581
12110
  )
@@ -11599,7 +12128,7 @@ function SnappingHeader({
11599
12128
  variant = "default",
11600
12129
  intensity = "bold",
11601
12130
  backgroundImage,
11602
- overlapHeight,
12131
+ overlapActive,
11603
12132
  tabs,
11604
12133
  breadcrumbPill,
11605
12134
  breadcrumbSeparator,
@@ -11614,6 +12143,31 @@ function SnappingHeader({
11614
12143
  stickyTop = "top-[var(--ds-navbar-height)]"
11615
12144
  }) {
11616
12145
  const [collapsed, setCollapsed] = useState(false);
12146
+ const container = usePageContainer();
12147
+ const stickyRef = useRef(null);
12148
+ const setStickyRef = useCallback((node) => {
12149
+ stickyRef.current = node;
12150
+ if (typeof headerRef === "function") headerRef(node);
12151
+ else if (headerRef) headerRef.current = node;
12152
+ }, [headerRef]);
12153
+ useLayoutEffect(() => {
12154
+ const report = container?.setPinnedHeight;
12155
+ if (!report) return;
12156
+ const el = stickyRef.current;
12157
+ if (!(pinned && collapsed) || !el) {
12158
+ report(null);
12159
+ return;
12160
+ }
12161
+ const sync = () => report(el.offsetHeight);
12162
+ sync();
12163
+ if (typeof ResizeObserver === "undefined") return () => report(null);
12164
+ const obs = new ResizeObserver(sync);
12165
+ obs.observe(el);
12166
+ return () => {
12167
+ obs.disconnect();
12168
+ report(null);
12169
+ };
12170
+ }, [container?.setPinnedHeight, pinned, collapsed]);
11617
12171
  const sentinelRef = useRef(null);
11618
12172
  const collapsedRef = useRef(false);
11619
12173
  const rafRef = useRef(0);
@@ -11682,7 +12236,7 @@ function SnappingHeader({
11682
12236
  const headerEl = /* @__PURE__ */ jsxs(
11683
12237
  "header",
11684
12238
  {
11685
- ref: !isFloating ? headerRef : void 0,
12239
+ ref: !isFloating ? setStickyRef : void 0,
11686
12240
  className: cn(
11687
12241
  "transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
11688
12242
  !isFloating && pinned && collapsed && cn("sticky", stickyTop, "z-[calc(var(--ds-z-sticky,40)-1)]"),
@@ -11694,7 +12248,7 @@ function SnappingHeader({
11694
12248
  isBoldColourful ? "border-[color-mix(in_srgb,var(--ds-accent-primary)_70%,black)] bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box]" : cn("border-[var(--ds-border-subtle)] bg-[var(--ds-tint-base)]", GLASS_SURFACE)
11695
12249
  ] : [
11696
12250
  "relative overflow-hidden",
11697
- !overlapHeight && !wrapperHasCard && "mb-ds-6",
12251
+ !overlapActive && !wrapperHasCard && "mb-ds-6",
11698
12252
  isBoldColourful ? "bg-[var(--ds-accent-primary)] [background-image:var(--ds-gradient)] [background-origin:border-box] border-b-[2px] border-[color-mix(in_srgb,var(--ds-accent-primary)_70%,black)]" : "bg-[var(--ds-tint-base)] border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]"
11699
12253
  ]),
11700
12254
  !collapsed && !isColourful && isFloating && !wrapperHasCard && FLOATING_HEADER,
@@ -11724,9 +12278,9 @@ function SnappingHeader({
11724
12278
  /* @__PURE__ */ jsx(TruncHeading, { as: Heading, className: "font-[family-name:var(--ds-font-display)] text-xl font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)]", children: title }),
11725
12279
  badge
11726
12280
  ] }),
11727
- actions && /* @__PURE__ */ jsx(ButtonSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
12281
+ actions && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) })
11728
12282
  ] }),
11729
- filters && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-3 mt-ds-3", children: filters }),
12283
+ filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-3", children: filters }) }),
11730
12284
  expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-3", children: expandedContent }),
11731
12285
  tabs && /* @__PURE__ */ jsx("div", { className: "mt-ds-3 -mx-ds-1", children: tabs })
11732
12286
  ] }) : /* @__PURE__ */ jsxs(
@@ -11736,11 +12290,11 @@ function SnappingHeader({
11736
12290
  "transition-all duration-[var(--ds-transition-speed)] ease-[var(--ds-transition-ease)]",
11737
12291
  isColourful && !collapsed && "relative z-10",
11738
12292
  collapsed ? cn("flex items-center justify-between gap-ds-4 py-ds-2", !effectiveMaxWidth && "px-ds-4") : [
11739
- (!isColourful || !overlapHeight) && "pb-ds-6",
12293
+ (!isColourful || !overlapActive) && "pb-ds-6",
11740
12294
  hasBreadcrumbs && !hideExpandedBreadcrumbs ? "pt-ds-3" : "pt-ds-6"
11741
12295
  ]
11742
12296
  ),
11743
- style: !collapsed && isColourful && overlapHeight ? { paddingBottom: `calc(var(--ds-space-6) + ${overlapHeight}px)` } : void 0,
12297
+ style: !collapsed && isColourful && overlapActive ? { paddingBottom: `calc(var(--ds-space-6) + var(--ds-overlap, 0px))` } : void 0,
11744
12298
  children: [
11745
12299
  !collapsed && hasBreadcrumbs && !hideExpandedBreadcrumbs && /* @__PURE__ */ jsx(Breadcrumbs3, { items: breadcrumbs, onLight, onTint, pill: breadcrumbPill, separator: breadcrumbSeparator }),
11746
12300
  /* @__PURE__ */ jsxs("div", { className: cn(
@@ -11791,9 +12345,9 @@ function SnappingHeader({
11791
12345
  ), children: description })
11792
12346
  ] })
11793
12347
  ] }),
11794
- actions && (collapsed ? /* @__PURE__ */ jsx(ButtonSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) }) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }))
12348
+ actions && (collapsed ? /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }) }) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-2 shrink-0", children: actions }))
11795
12349
  ] }),
11796
- !collapsed && filters && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-ds-3 mt-ds-4", children: filters }),
12350
+ !collapsed && filters && /* @__PURE__ */ jsx(ControlSizeContext.Provider, { value: "sm", children: /* @__PURE__ */ jsx("div", { className: "flex items-center flex-wrap gap-ds-3 mt-ds-4", children: filters }) }),
11797
12351
  !collapsed && expandedContent && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children: expandedContent }),
11798
12352
  !collapsed && tabs && /* @__PURE__ */ jsx("div", { className: "mt-ds-4 -mx-ds-1", children: tabs })
11799
12353
  ]
@@ -11808,7 +12362,6 @@ function SnappingHeader({
11808
12362
  }
11809
12363
  );
11810
12364
  if (isFloating) {
11811
- const overlapActive = !collapsed && isColourful && !!overlapHeight;
11812
12365
  const floatingStyle = collapsed ? {
11813
12366
  paddingTop: navbarFloating ? 0 : "var(--ds-space-3)",
11814
12367
  paddingRight: "var(--ds-space-3)",
@@ -11820,7 +12373,7 @@ function SnappingHeader({
11820
12373
  /* @__PURE__ */ jsx(
11821
12374
  "div",
11822
12375
  {
11823
- ref: headerRef,
12376
+ ref: setStickyRef,
11824
12377
  className: cn(
11825
12378
  pinned && collapsed && "sticky z-[calc(var(--ds-z-sticky,40)-1)]",
11826
12379
  pinned && collapsed && "top-0"
@@ -12533,7 +13086,9 @@ var sizeClasses = {
12533
13086
  xl: "max-w-4xl",
12534
13087
  full: "max-w-[calc(100vw-2rem)]"
12535
13088
  };
12536
- function Dialog({ open, onClose, title, description, children, footer, variant = "default", size = "md", alert = false, container, onSubmit }) {
13089
+ function Dialog({ open, onClose: onCloseProp, title, description, children, footer, variant = "default", size = "md", alert = false, container, onSubmit, dirty, onDiscard }) {
13090
+ const guard = useDirtyGuard(dirty, onCloseProp, onDiscard);
13091
+ const onClose = guard.requestClose;
12537
13092
  const titleId = useId();
12538
13093
  const descriptionId = useId();
12539
13094
  const isMobile = useBreakpoint("sm");
@@ -12660,6 +13215,7 @@ function Dialog({ open, onClose, title, description, children, footer, variant =
12660
13215
  children && /* @__PURE__ */ jsx("div", { className: "mt-ds-4", children })
12661
13216
  ] })
12662
13217
  ] }) }),
13218
+ /* @__PURE__ */ jsx(DiscardConfirm, { open: guard.confirming, onKeep: guard.keep, onDiscard: guard.discard }),
12663
13219
  footer && /* @__PURE__ */ jsx("div", { className: cn(
12664
13220
  "flex justify-end gap-ds-2 p-ds-4",
12665
13221
  "border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]",
@@ -13728,16 +14284,21 @@ var SectionHeading = forwardRef(function SectionHeading2({
13728
14284
  bordered = false,
13729
14285
  className
13730
14286
  }, ref) {
14287
+ const isPhone = useBreakpoint("sm");
13731
14288
  return /* @__PURE__ */ jsxs(
13732
14289
  "div",
13733
14290
  {
13734
14291
  ref,
13735
14292
  className: cn(
14293
+ "mb-[var(--ds-heading-gap)]",
13736
14294
  bordered && "border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] pb-ds-4",
13737
14295
  className
13738
14296
  ),
13739
14297
  children: [
13740
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-ds-4", children: [
14298
+ /* @__PURE__ */ jsxs("div", { className: cn(
14299
+ "flex gap-ds-4",
14300
+ isPhone && actions ? "flex-col" : "items-start justify-between"
14301
+ ), children: [
13741
14302
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
13742
14303
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-ds-2", children: [
13743
14304
  /* @__PURE__ */ jsx("h2", { className: "font-[family-name:var(--ds-font-display)] text-lg font-[var(--ds-weight-heading)] text-[var(--ds-text-primary)] truncate", children: title }),
@@ -13846,6 +14407,6 @@ var TextOverflow = forwardRef(function TextOverflow2({
13846
14407
  return /* @__PURE__ */ jsx(Tooltip, { content: resolvedTooltipContent, children: content });
13847
14408
  });
13848
14409
 
13849
- export { Accordion, ActionPanel, ActionPanelGroup, Alert, AppShell, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, BulkActionBar, Button, ButtonSizeContext, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, Drawer, Dropdown, DropdownMenu, EmptyState, Field, FileUpload, FormWrapper, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, Sheet, Sidebar, SidebarNav, SkipLink, SliderRange, Spinner, StackedList, StatsCard, StatusDot, Stepper, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimePicker, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, useAppShell, useFormContext, useSidebar, useToast };
14410
+ export { Accordion, ActionPanel, ActionPanelGroup, Alert, AppShell, AsidePanel, Avatar, AvatarGroup, BottomNav, Breadcrumbs, BulkActionBar, Button, ButtonSizeContext, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Carousel, ChatMessageList, ChatPanel, Checkbox, CheckboxGroup, CheckboxGroupItem, Collapsible, ColorPicker, Combobox, CommandPalette, ContextMenu, ControlSizeContext, CornerPanel, DEFAULT_DATE_RANGE_PRESETS, DataList, DatePicker, DateRangePicker, DescriptionList, Dialog, Dock, Drawer, Dropdown, DropdownMenu, EmptyState, EntityCell, Field, FileUpload, FormWrapper, HoverCard, InlineFieldError, Input, Kbd, Label, Launcher, MentionInput, MobileHeaderMenu, NavItem, NavMenu, Navbar, NotificationCenter, NumberInput, PageContainer, PageHeader, Pagination, PinInput, Popover, Progress, RadioGroup, Rating, ScrollArea, SectionHeading, SegmentedControl, SettingsLayout, Sheet, Sidebar, SidebarNav, SkipLink, SliderRange, Spinner, SplitView, StackedList, StatsCard, StatusDot, Stepper, Table, TableToolbar, Tabs, Tag, TagInput, TextOverflow, Textarea, TimePicker, Timeline, Toast, ToastProvider, Toggle, Tour, TransferList, TreeView, useAppShell, useFormContext, useSidebar, useToast };
13850
14411
  //# sourceMappingURL=index.js.map
13851
14412
  //# sourceMappingURL=index.js.map