@platned/ui 0.1.3 → 0.3.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,34 +1,34 @@
1
- // src/index.tsx
2
- import clsx20 from "clsx";
3
-
4
- // src/components/button.tsx
1
+ // src/components/forms/button.tsx
5
2
  import clsx from "clsx";
6
3
  import { jsx, jsxs } from "react/jsx-runtime";
7
4
  var variantStyles = {
8
5
  primary: clsx(
9
- "bg-background-brand border border-border-brand text-text-brand-on-brand",
10
- "hover:bg-background-brand-hover",
11
- "disabled:bg-background-disabled disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
6
+ "bg-brand border border-brand text-brand-on-brand",
7
+ "hover:bg-brand-hover",
8
+ "disabled:bg-disabled disabled:border-disabled disabled:text-disabled-on-disabled"
12
9
  ),
13
10
  neutral: clsx(
14
- "bg-background-default border border-border-default text-text-default",
15
- "hover:bg-background-default-hover",
16
- "disabled:bg-background-disabled disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
11
+ "bg-default border border-default text-default",
12
+ "hover:bg-default-hover hover:text-brand",
13
+ "disabled:bg-disabled disabled:border-disabled disabled:text-disabled-on-disabled"
17
14
  ),
18
15
  subtle: clsx(
19
- "bg-transparent text-text-neutral",
20
- "hover:bg-background-neutral-tertiary",
21
- "disabled:bg-background-disabled disabled:border disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
16
+ // border-transparent holds space so hover border doesn't shift layout
17
+ "bg-transparent border border-transparent text-neutral",
18
+ "hover:border-default hover:text-brand",
19
+ "disabled:bg-disabled disabled:border-disabled disabled:text-disabled-on-disabled"
22
20
  ),
23
21
  danger: clsx(
24
- "bg-background-danger border border-border-danger-secondary text-text-danger-on-danger",
25
- "hover:bg-background-danger-hover",
26
- "disabled:bg-background-disabled disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
22
+ "bg-danger border border-danger-secondary text-danger-on-danger",
23
+ // border shifts from danger-secondary → danger-default on hover (Figma spec)
24
+ "hover:bg-danger-hover hover:border-danger",
25
+ "disabled:bg-disabled disabled:border-disabled disabled:text-disabled-on-disabled"
27
26
  ),
28
27
  "danger-subtle": clsx(
29
- "bg-transparent text-text-danger",
30
- "hover:bg-background-danger-tertiary",
31
- "disabled:bg-background-disabled disabled:border disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
28
+ // border-transparent base avoids layout shift when hover border appears
29
+ "bg-transparent border border-transparent text-danger",
30
+ "hover:bg-danger-tertiary-hover hover:border-danger",
31
+ "disabled:bg-disabled disabled:border-disabled disabled:text-disabled-on-disabled"
32
32
  )
33
33
  };
34
34
  var sizeStyles = {
@@ -50,7 +50,7 @@ function Button({
50
50
  {
51
51
  className: clsx(
52
52
  "inline-flex items-center justify-center whitespace-nowrap transition-colors",
53
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-1",
53
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1",
54
54
  "disabled:cursor-not-allowed",
55
55
  variantStyles[variant],
56
56
  sizeStyles[size],
@@ -66,25 +66,28 @@ function Button({
66
66
  );
67
67
  }
68
68
 
69
- // src/components/icon-button.tsx
69
+ // src/components/forms/icon-button.tsx
70
70
  import clsx2 from "clsx";
71
71
  import { jsx as jsx2 } from "react/jsx-runtime";
72
72
  var variantStyles2 = {
73
73
  primary: clsx2(
74
- "bg-background-brand border border-border-brand text-text-brand-on-brand",
75
- "hover:bg-background-brand-hover",
76
- "disabled:bg-background-disabled disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
74
+ "bg-brand border border-brand text-brand-on-brand",
75
+ "hover:bg-brand-hover",
76
+ "disabled:bg-disabled disabled:border-disabled disabled:text-disabled-on-disabled"
77
77
  ),
78
78
  // Neutral uses secondary background (light gray) for visual weight without a text label
79
79
  neutral: clsx2(
80
- "bg-background-default-secondary border border-border-default text-text-default",
81
- "hover:bg-background-default-secondary-hover",
82
- "disabled:bg-background-disabled disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
80
+ "bg-default-secondary border border-default text-default",
81
+ // icon turns brand blue on hover (Figma spec)
82
+ "hover:bg-default-secondary-hover hover:text-brand",
83
+ "disabled:bg-disabled disabled:border-disabled disabled:text-disabled-on-disabled"
83
84
  ),
84
85
  subtle: clsx2(
85
- "bg-transparent text-text-neutral",
86
- "hover:bg-background-neutral-tertiary",
87
- "disabled:bg-background-disabled disabled:border disabled:border-border-disabled disabled:text-text-disabled-on-disabled"
86
+ "bg-transparent text-neutral",
87
+ // hover uses background-default-default-hover (#f5f5f5), icon turns brand blue (Figma spec)
88
+ "hover:bg-default-hover hover:text-brand",
89
+ // disabled needs explicit border since there is no base border
90
+ "disabled:bg-disabled disabled:border disabled:border-disabled disabled:text-disabled-on-disabled"
88
91
  )
89
92
  };
90
93
  var sizeStyles2 = {
@@ -95,7 +98,7 @@ var sizeStyles2 = {
95
98
  function IconButton({
96
99
  variant = "primary",
97
100
  size = "md",
98
- icon,
101
+ children,
99
102
  className,
100
103
  ...props
101
104
  }) {
@@ -104,44 +107,44 @@ function IconButton({
104
107
  {
105
108
  className: clsx2(
106
109
  "inline-flex shrink-0 items-center justify-center transition-colors",
107
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-1",
110
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1",
108
111
  "disabled:cursor-not-allowed",
109
112
  variantStyles2[variant],
110
113
  sizeStyles2[size],
111
114
  className
112
115
  ),
113
116
  ...props,
114
- children: icon
117
+ children
115
118
  }
116
119
  );
117
120
  }
118
121
 
119
- // src/components/button-group.tsx
122
+ // src/components/forms/button-group.tsx
120
123
  import clsx3 from "clsx";
121
124
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
122
125
  var containerStyles = {
123
- primary: "bg-background-neutral-tertiary p-1 rounded-2xl",
124
- neutral: "bg-background-neutral-tertiary p-1 rounded-2xl",
125
- filter: "bg-background-default border border-border-default p-1 rounded-xl"
126
+ primary: "bg-neutral-tertiary p-1 rounded-2xl",
127
+ neutral: "bg-neutral-tertiary p-1 rounded-2xl",
128
+ filter: "bg-default border border-default p-1 rounded-xl"
126
129
  };
127
130
  var selectedStyles = {
128
131
  primary: clsx3(
129
- "bg-background-brand border border-border-brand text-text-brand-on-brand",
130
- "hover:bg-background-brand-hover"
132
+ "bg-brand border border-brand text-brand-on-brand",
133
+ "hover:bg-brand-hover"
131
134
  ),
132
135
  neutral: clsx3(
133
- "bg-background-default border border-border-default text-text-default",
134
- "hover:bg-background-default-hover"
136
+ "bg-default border border-default text-default",
137
+ "hover:bg-default-hover"
135
138
  ),
136
139
  filter: clsx3(
137
- "bg-background-brand text-text-brand-on-brand",
138
- "hover:bg-background-brand-hover"
140
+ "bg-brand text-brand-on-brand",
141
+ "hover:bg-brand-hover"
139
142
  )
140
143
  };
141
144
  var unselectedStyles = {
142
- primary: clsx3("bg-transparent text-text-neutral", "hover:bg-background-neutral-tertiary-hover"),
143
- neutral: clsx3("bg-transparent text-text-neutral", "hover:bg-background-neutral-tertiary-hover"),
144
- filter: clsx3("text-text-default-secondary", "hover:text-text-default")
145
+ primary: clsx3("bg-transparent text-neutral", "hover:bg-neutral-tertiary-hover"),
146
+ neutral: clsx3("bg-transparent text-neutral", "hover:bg-neutral-tertiary-hover"),
147
+ filter: clsx3("text-default-secondary", "hover:text-default")
145
148
  };
146
149
  var itemSizeStyles = {
147
150
  lg: "h-12 px-3 gap-1 rounded-2xl text-body font-semibold [&_svg]:size-5",
@@ -192,8 +195,8 @@ function ButtonGroup({
192
195
  onClick: () => onChange(item.value),
193
196
  className: clsx3(
194
197
  "inline-flex items-center justify-center whitespace-nowrap transition-colors",
195
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-1",
196
- "disabled:cursor-not-allowed disabled:text-text-disabled",
198
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1",
199
+ "disabled:cursor-not-allowed disabled:text-disabled",
197
200
  (isJustify || isStack) && "w-full",
198
201
  itemSizeStyles[size],
199
202
  isSelected ? selectedStyles[variant] : unselectedStyles[variant]
@@ -213,7 +216,7 @@ function ButtonGroup({
213
216
  );
214
217
  }
215
218
 
216
- // src/components/avatar.tsx
219
+ // src/components/avatar/avatar.tsx
217
220
  import clsx4 from "clsx";
218
221
  import { jsx as jsx4 } from "react/jsx-runtime";
219
222
  var sizeStyles3 = {
@@ -226,16 +229,16 @@ var initialTextStyles = {
226
229
  md: "text-body-xs font-semibold",
227
230
  sm: "text-body-tiny font-semibold"
228
231
  };
229
- var shapeStyles = {
230
- circle: "rounded-full",
231
- square: "rounded-lg"
232
- };
232
+ function getShapeClass(shape, size) {
233
+ if (shape === "circle") return "rounded-full";
234
+ return size === "sm" ? "rounded" : "rounded-lg";
235
+ }
233
236
  function Avatar(props) {
234
237
  const { size = "lg", shape = "circle", className } = props;
235
238
  const base = clsx4(
236
239
  "shrink-0 overflow-hidden",
237
240
  sizeStyles3[size],
238
- shapeStyles[shape],
241
+ getShapeClass(shape, size),
239
242
  className
240
243
  );
241
244
  if (props.type === "image") {
@@ -259,7 +262,7 @@ function Avatar(props) {
259
262
  "span",
260
263
  {
261
264
  className: clsx4(
262
- "select-none leading-none text-text-brand-on-brand",
265
+ "select-none leading-none text-brand-on-brand",
263
266
  initialTextStyles[size]
264
267
  ),
265
268
  children: props.initial.charAt(0).toUpperCase()
@@ -269,7 +272,7 @@ function Avatar(props) {
269
272
  );
270
273
  }
271
274
 
272
- // src/components/avatar-group.tsx
275
+ // src/components/avatar/avatar-group.tsx
273
276
  import clsx5 from "clsx";
274
277
  import { jsxs as jsxs3 } from "react/jsx-runtime";
275
278
  function AvatarGroup({
@@ -294,7 +297,7 @@ function AvatarGroup({
294
297
  className: clsx5(
295
298
  "flex items-center justify-center",
296
299
  "min-w-6 h-6 px-1 rounded-lg",
297
- "bg-background-default-secondary text-text-default-secondary text-body-sm",
300
+ "bg-default-secondary text-default-secondary text-body-sm",
298
301
  spacing === "overlap" && "drop-shadow-sm"
299
302
  ),
300
303
  children: [
@@ -308,39 +311,20 @@ function AvatarGroup({
308
311
  );
309
312
  }
310
313
 
311
- // src/components/nav-item.tsx
314
+ // src/components/avatar/avatar-block.tsx
312
315
  import clsx6 from "clsx";
313
316
  import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
314
- function NavItem({
315
- icon,
316
- label,
317
- isActive = false,
318
- indicator = false,
319
- collapsed = false,
320
- className
321
- }) {
322
- return /* @__PURE__ */ jsxs4(
323
- "span",
324
- {
325
- className: clsx6(
326
- "relative flex h-11 w-full items-center gap-3 rounded-xl px-3.5 py-2.5 transition-colors",
327
- collapsed && "justify-center",
328
- isActive ? "bg-background-brand text-text-brand-on-brand" : [
329
- "border border-border-default bg-background-default text-text-default-secondary",
330
- "hover:bg-background-brand-tertiary-hover hover:border-border-brand-tertiary hover:text-text-brand"
331
- ],
332
- className
333
- ),
334
- children: [
335
- icon !== void 0 && /* @__PURE__ */ jsx5("span", { className: "shrink-0 [&_svg]:size-4", children: icon }),
336
- !collapsed && /* @__PURE__ */ jsx5("span", { className: "flex-1 min-w-0 truncate text-body-sm font-regular leading-snug", children: label }),
337
- indicator && /* @__PURE__ */ jsx5("span", { className: "absolute -right-px -top-px size-2 rounded-full bg-background-danger" })
338
- ]
339
- }
340
- );
317
+ function AvatarBlock({ children, title, description, className }) {
318
+ return /* @__PURE__ */ jsxs4("div", { className: clsx6("flex items-start gap-3", className), children: [
319
+ /* @__PURE__ */ jsx5("div", { className: "shrink-0", children }),
320
+ /* @__PURE__ */ jsxs4("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
321
+ /* @__PURE__ */ jsx5("span", { className: "text-body font-semibold text-default-secondary", children: title }),
322
+ description && /* @__PURE__ */ jsx5("span", { className: "text-body text-default-tertiary", children: description })
323
+ ] })
324
+ ] });
341
325
  }
342
326
 
343
- // src/components/input.tsx
327
+ // src/components/forms/input.tsx
344
328
  import { forwardRef } from "react";
345
329
  import clsx7 from "clsx";
346
330
  import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
@@ -358,17 +342,17 @@ var labelText = {
358
342
  sm: "text-body-tiny"
359
343
  };
360
344
  var inputBase = {
361
- lg: "h-12 px-4 py-3.5 text-body",
362
- md: "h-9 px-3 py-2.5 text-body-sm",
363
- sm: "h-6 px-2 py-[5px] text-body-tiny"
345
+ lg: "h-12 px-5 py-3.5 text-body",
346
+ md: "h-9 px-4 py-2.5 text-body-sm",
347
+ sm: "h-6 px-3 py-[5px] text-body-tiny"
364
348
  };
365
349
  var leadingPad = {
366
- lg: "pl-10",
350
+ lg: "pl-12",
367
351
  md: "pl-8",
368
352
  sm: "pl-6"
369
353
  };
370
354
  var trailingPad = {
371
- lg: "pr-10",
355
+ lg: "pr-12",
372
356
  md: "pr-8",
373
357
  sm: "pr-6"
374
358
  };
@@ -377,7 +361,7 @@ var iconWrap = {
377
361
  md: { left: "left-3", right: "right-3", size: "size-4" },
378
362
  sm: { left: "left-2", right: "right-2", size: "size-3" }
379
363
  };
380
- var Input = forwardRef(function Input2({ label, description, error, hint, size = "md", leadingIcon, trailingIcon, className, disabled, id, ...props }, ref) {
364
+ var Input = forwardRef(function Input2({ label, description, error, hint, size = "md", leadingIcon, trailingIcon, trailingAction, className, disabled, id, ...props }, ref) {
381
365
  const hasError = !!error;
382
366
  const iw = iconWrap[size];
383
367
  return /* @__PURE__ */ jsxs5("div", { className: clsx7("flex flex-col", wrapGap[size], className), children: [
@@ -385,11 +369,11 @@ var Input = forwardRef(function Input2({ label, description, error, hint, size =
385
369
  "label",
386
370
  {
387
371
  htmlFor: id,
388
- className: clsx7(labelText[size], disabled ? "text-text-disabled" : "text-text-default"),
372
+ className: clsx7(labelText[size], disabled ? "text-disabled" : "text-default"),
389
373
  children: label
390
374
  }
391
375
  ),
392
- description && /* @__PURE__ */ jsx6("p", { className: clsx7(labelText[size], disabled ? "text-text-disabled" : "text-text-default-secondary"), children: description }),
376
+ description && /* @__PURE__ */ jsx6("p", { className: clsx7(labelText[size], disabled ? "text-disabled" : "text-default-secondary"), children: description }),
393
377
  /* @__PURE__ */ jsxs5("div", { className: "relative flex items-center", children: [
394
378
  leadingIcon && /* @__PURE__ */ jsx6("span", { className: clsx7("pointer-events-none absolute", iw.left, iw.size, "flex items-center justify-center text-icon-default-secondary"), children: leadingIcon }),
395
379
  /* @__PURE__ */ jsx6(
@@ -400,24 +384,25 @@ var Input = forwardRef(function Input2({ label, description, error, hint, size =
400
384
  disabled,
401
385
  className: clsx7(
402
386
  "w-full rounded-lg border outline-none transition-colors",
403
- "bg-background-default text-text-default",
404
- "placeholder:text-text-default-tertiary",
387
+ "bg-default text-default",
388
+ "placeholder:text-default-tertiary",
405
389
  inputBase[size],
406
390
  leadingIcon && leadingPad[size],
407
- trailingIcon && trailingPad[size],
408
- disabled ? "cursor-not-allowed bg-background-disabled border-border-disabled text-text-disabled placeholder:text-text-disabled" : hasError ? "border-border-danger-secondary focus:border-border-danger-secondary focus:ring-1 focus:ring-border-danger-secondary" : "border-border-default focus:border-border-brand-tertiary focus:ring-1 focus:ring-border-brand-tertiary"
391
+ (trailingIcon || trailingAction) && trailingPad[size],
392
+ disabled ? "cursor-not-allowed bg-disabled border-disabled text-disabled placeholder:text-disabled" : hasError ? "border-danger-secondary focus:border-danger-secondary focus:ring-1 focus:ring-danger-secondary" : "border-default focus:border-brand-secondary focus:ring-1 focus:ring-brand-secondary"
409
393
  ),
410
394
  ...props
411
395
  }
412
396
  ),
413
- trailingIcon && /* @__PURE__ */ jsx6("span", { className: clsx7("pointer-events-none absolute", iw.right, iw.size, "flex items-center justify-center text-icon-default-secondary"), children: trailingIcon })
397
+ trailingIcon && !trailingAction && /* @__PURE__ */ jsx6("span", { className: clsx7("pointer-events-none absolute", iw.right, iw.size, "flex items-center justify-center text-icon-default-secondary"), children: trailingIcon }),
398
+ trailingAction && /* @__PURE__ */ jsx6("span", { className: clsx7("absolute", iw.right, "flex items-center justify-center text-icon-default-secondary"), children: trailingAction })
414
399
  ] }),
415
- hasError && /* @__PURE__ */ jsx6("p", { className: clsx7(labelText[size], "text-text-danger"), children: error }),
416
- !hasError && hint && /* @__PURE__ */ jsx6("p", { className: clsx7(labelText[size], "text-text-default-secondary"), children: hint })
400
+ hasError && /* @__PURE__ */ jsx6("p", { className: clsx7(labelText[size], "text-danger"), children: error }),
401
+ !hasError && hint && /* @__PURE__ */ jsx6("p", { className: clsx7(labelText[size], "text-default"), children: hint })
417
402
  ] });
418
403
  });
419
404
 
420
- // src/components/textarea.tsx
405
+ // src/components/forms/textarea.tsx
421
406
  import { forwardRef as forwardRef2 } from "react";
422
407
  import clsx8 from "clsx";
423
408
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
@@ -443,11 +428,11 @@ var Textarea = forwardRef2(function Textarea2({ label, description, error, hint,
443
428
  "label",
444
429
  {
445
430
  htmlFor: id,
446
- className: clsx8(labelText2[size], disabled ? "text-text-disabled" : "text-text-default"),
431
+ className: clsx8(labelText2[size], disabled ? "text-disabled" : "text-default"),
447
432
  children: label
448
433
  }
449
434
  ),
450
- description && /* @__PURE__ */ jsx7("p", { className: clsx8(labelText2[size], disabled ? "text-text-disabled" : "text-text-default-secondary"), children: description }),
435
+ description && /* @__PURE__ */ jsx7("p", { className: clsx8(labelText2[size], disabled ? "text-disabled" : "text-default-secondary"), children: description }),
451
436
  /* @__PURE__ */ jsx7(
452
437
  "textarea",
453
438
  {
@@ -456,20 +441,20 @@ var Textarea = forwardRef2(function Textarea2({ label, description, error, hint,
456
441
  disabled,
457
442
  className: clsx8(
458
443
  "w-full rounded-lg border outline-none transition-colors resize-y",
459
- "bg-background-default text-text-default",
460
- "placeholder:text-text-default-tertiary",
444
+ "bg-default text-default",
445
+ "placeholder:text-default-tertiary",
461
446
  textareaBase[size],
462
- disabled ? "cursor-not-allowed bg-background-disabled border-border-disabled text-text-disabled placeholder:text-text-disabled resize-none" : hasError ? "border-border-danger-secondary focus:border-border-danger-secondary focus:ring-1 focus:ring-border-danger-secondary" : "border-border-default focus:border-border-brand-tertiary focus:ring-1 focus:ring-border-brand-tertiary"
447
+ disabled ? "cursor-not-allowed bg-disabled border-disabled text-disabled placeholder:text-disabled resize-none" : hasError ? "border-danger-secondary focus:border-danger-secondary focus:ring-1 focus:ring-danger-secondary" : "border-default focus:border-brand-secondary focus:ring-1 focus:ring-brand-secondary"
463
448
  ),
464
449
  ...props
465
450
  }
466
451
  ),
467
- hasError && /* @__PURE__ */ jsx7("p", { className: clsx8(labelText2[size], "text-text-danger"), children: error }),
468
- !hasError && hint && /* @__PURE__ */ jsx7("p", { className: clsx8(labelText2[size], "text-text-default-secondary"), children: hint })
452
+ hasError && /* @__PURE__ */ jsx7("p", { className: clsx8(labelText2[size], "text-danger"), children: error }),
453
+ !hasError && hint && /* @__PURE__ */ jsx7("p", { className: clsx8(labelText2[size], "text-default-secondary"), children: hint })
469
454
  ] });
470
455
  });
471
456
 
472
- // src/components/select.tsx
457
+ // src/components/forms/select.tsx
473
458
  import { forwardRef as forwardRef3 } from "react";
474
459
  import clsx9 from "clsx";
475
460
  import { LuChevronDown } from "react-icons/lu";
@@ -505,11 +490,11 @@ var Select = forwardRef3(function Select2({ label, description, error, hint, siz
505
490
  "label",
506
491
  {
507
492
  htmlFor: id,
508
- className: clsx9(labelText3[size], disabled ? "text-text-disabled" : "text-text-default"),
493
+ className: clsx9(labelText3[size], disabled ? "text-disabled" : "text-default"),
509
494
  children: label
510
495
  }
511
496
  ),
512
- description && /* @__PURE__ */ jsx8("p", { className: clsx9(labelText3[size], disabled ? "text-text-disabled" : "text-text-default-secondary"), children: description }),
497
+ description && /* @__PURE__ */ jsx8("p", { className: clsx9(labelText3[size], disabled ? "text-disabled" : "text-default-secondary"), children: description }),
513
498
  /* @__PURE__ */ jsxs7("div", { className: "relative flex items-center", children: [
514
499
  /* @__PURE__ */ jsxs7(
515
500
  "select",
@@ -519,9 +504,9 @@ var Select = forwardRef3(function Select2({ label, description, error, hint, siz
519
504
  disabled,
520
505
  className: clsx9(
521
506
  "w-full appearance-none rounded-lg border outline-none transition-colors pt-0.5",
522
- "bg-background-default text-text-default",
507
+ "bg-default text-default",
523
508
  selectBase[size],
524
- disabled ? "cursor-not-allowed bg-background-disabled border-border-disabled text-text-disabled" : hasError ? "border-border-danger-secondary focus:border-border-danger-secondary focus:ring-1 focus:ring-border-danger-secondary" : "border-border-default focus:border-border-brand-tertiary focus:ring-1 focus:ring-border-brand-tertiary"
509
+ disabled ? "cursor-not-allowed bg-disabled border-disabled text-disabled" : hasError ? "border-danger-secondary focus:border-danger-secondary focus:ring-1 focus:ring-danger-secondary" : "border-default focus:border-brand-secondary focus:ring-1 focus:ring-brand-secondary"
525
510
  ),
526
511
  ...props,
527
512
  children: [
@@ -544,49 +529,129 @@ var Select = forwardRef3(function Select2({ label, description, error, hint, siz
544
529
  }
545
530
  )
546
531
  ] }),
547
- hasError && /* @__PURE__ */ jsx8("p", { className: clsx9(labelText3[size], "text-text-danger"), children: error }),
548
- !hasError && hint && /* @__PURE__ */ jsx8("p", { className: clsx9(labelText3[size], "text-text-default-secondary"), children: hint })
532
+ hasError && /* @__PURE__ */ jsx8("p", { className: clsx9(labelText3[size], "text-danger"), children: error }),
533
+ !hasError && hint && /* @__PURE__ */ jsx8("p", { className: clsx9(labelText3[size], "text-default-secondary"), children: hint })
549
534
  ] });
550
535
  });
551
536
 
552
- // src/components/stepper.tsx
537
+ // src/components/forms/date-picker.tsx
538
+ import { forwardRef as forwardRef4 } from "react";
553
539
  import clsx10 from "clsx";
554
- import { LuCheck, LuChevronRight } from "react-icons/lu";
540
+ import { LuCalendar } from "react-icons/lu";
555
541
  import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
542
+ var wrapGap4 = {
543
+ lg: "gap-2",
544
+ md: "gap-1",
545
+ sm: "gap-0.5"
546
+ };
547
+ var labelText4 = {
548
+ lg: "text-body",
549
+ md: "text-body-sm",
550
+ sm: "text-body-tiny"
551
+ };
552
+ var inputBase2 = {
553
+ lg: "h-12 px-5 py-3.5 pr-12 text-body",
554
+ md: "h-9 px-4 py-2.5 pr-8 text-body-sm",
555
+ sm: "h-6 px-3 py-[5px] pr-6 text-body-tiny"
556
+ };
557
+ var iconWrap2 = {
558
+ lg: { right: "right-4", size: "size-5" },
559
+ md: { right: "right-3", size: "size-4" },
560
+ sm: { right: "right-2", size: "size-3" }
561
+ };
562
+ var DatePicker = forwardRef4(function DatePicker2({ label, description, error, hint, size = "md", className, disabled, id, ...props }, ref) {
563
+ const hasError = !!error;
564
+ const iw = iconWrap2[size];
565
+ return /* @__PURE__ */ jsxs8("div", { className: clsx10("flex flex-col", wrapGap4[size], className), children: [
566
+ label && /* @__PURE__ */ jsx9(
567
+ "label",
568
+ {
569
+ htmlFor: id,
570
+ className: clsx10(labelText4[size], disabled ? "text-disabled" : "text-default"),
571
+ children: label
572
+ }
573
+ ),
574
+ description && /* @__PURE__ */ jsx9("p", { className: clsx10(labelText4[size], disabled ? "text-disabled" : "text-default-secondary"), children: description }),
575
+ /* @__PURE__ */ jsxs8("div", { className: "relative flex items-center", children: [
576
+ /* @__PURE__ */ jsx9(
577
+ "input",
578
+ {
579
+ ref,
580
+ id,
581
+ type: "date",
582
+ disabled,
583
+ className: clsx10(
584
+ "w-full rounded-lg border outline-none transition-colors",
585
+ "bg-default text-default",
586
+ "[&::-webkit-calendar-picker-indicator]:opacity-0",
587
+ "[&::-webkit-calendar-picker-indicator]:absolute",
588
+ "[&::-webkit-calendar-picker-indicator]:right-0",
589
+ "[&::-webkit-calendar-picker-indicator]:h-full",
590
+ "[&::-webkit-calendar-picker-indicator]:w-10",
591
+ "[&::-webkit-calendar-picker-indicator]:cursor-pointer",
592
+ inputBase2[size],
593
+ disabled ? "cursor-not-allowed bg-disabled border-disabled text-disabled" : hasError ? "border-danger-secondary focus:border-danger-secondary focus:ring-1 focus:ring-danger-secondary" : "border-default focus:border-brand-secondary focus:ring-1 focus:ring-brand-secondary"
594
+ ),
595
+ ...props
596
+ }
597
+ ),
598
+ /* @__PURE__ */ jsx9(
599
+ "span",
600
+ {
601
+ className: clsx10(
602
+ "pointer-events-none absolute",
603
+ iw.right,
604
+ iw.size,
605
+ "flex items-center justify-center",
606
+ disabled ? "text-icon-disabled" : "text-icon-default-secondary"
607
+ ),
608
+ children: /* @__PURE__ */ jsx9(LuCalendar, { className: "size-full" })
609
+ }
610
+ )
611
+ ] }),
612
+ hasError && /* @__PURE__ */ jsx9("p", { className: clsx10(labelText4[size], "text-danger"), children: error }),
613
+ !hasError && hint && /* @__PURE__ */ jsx9("p", { className: clsx10(labelText4[size], "text-default"), children: hint })
614
+ ] });
615
+ });
616
+
617
+ // src/components/forms/stepper.tsx
618
+ import clsx11 from "clsx";
619
+ import { LuCheck, LuChevronRight } from "react-icons/lu";
620
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
556
621
  function StepIndicator({ status }) {
557
622
  if (status === "complete") {
558
- return /* @__PURE__ */ jsx9("span", { className: "flex size-5 shrink-0 items-center justify-center rounded-full bg-background-brand text-white", children: /* @__PURE__ */ jsx9(LuCheck, { size: 11, "aria-hidden": true }) });
623
+ return /* @__PURE__ */ jsx10("span", { className: "flex size-5 shrink-0 items-center justify-center rounded-full bg-brand text-white", children: /* @__PURE__ */ jsx10(LuCheck, { size: 11, "aria-hidden": true }) });
559
624
  }
560
625
  if (status === "active") {
561
- return /* @__PURE__ */ jsx9("span", { className: "flex size-5 shrink-0 items-center justify-center rounded-full border-2 border-background-brand", children: /* @__PURE__ */ jsx9("span", { className: "size-2.5 rounded-full bg-background-brand" }) });
626
+ return /* @__PURE__ */ jsx10("span", { className: "flex size-5 shrink-0 items-center justify-center rounded-full border-2 border-brand-emphasis", children: /* @__PURE__ */ jsx10("span", { className: "size-2.5 rounded-full bg-brand" }) });
562
627
  }
563
- return /* @__PURE__ */ jsx9("span", { className: "size-5 shrink-0 rounded-full border-2 border-border-disabled", "aria-hidden": "true" });
628
+ return /* @__PURE__ */ jsx10("span", { className: "size-5 shrink-0 rounded-full border-2 border-disabled", "aria-hidden": "true" });
564
629
  }
565
630
  function ChevronSeparator() {
566
- return /* @__PURE__ */ jsx9(LuChevronRight, { className: "mx-1 size-4 shrink-0 text-text-default-tertiary", "aria-hidden": true });
631
+ return /* @__PURE__ */ jsx10(LuChevronRight, { className: "mx-1 size-4 shrink-0 text-default-tertiary", "aria-hidden": true });
567
632
  }
568
633
  var labelClass = {
569
- complete: "text-text-brand font-semibold",
570
- active: "text-text-brand font-semibold",
571
- upcoming: "text-text-disabled font-regular"
634
+ complete: "text-brand font-semibold",
635
+ active: "text-brand font-semibold",
636
+ upcoming: "text-disabled font-regular"
572
637
  };
573
638
  function Stepper({ steps, className }) {
574
- return /* @__PURE__ */ jsx9(
639
+ return /* @__PURE__ */ jsx10(
575
640
  "ol",
576
641
  {
577
- className: clsx10("flex items-center overflow-x-auto", className),
642
+ className: clsx11("flex items-center overflow-x-auto", className),
578
643
  "aria-label": "Progress",
579
- children: steps.map((step, i) => /* @__PURE__ */ jsxs8(
644
+ children: steps.map((step, i) => /* @__PURE__ */ jsxs9(
580
645
  "li",
581
646
  {
582
647
  className: "flex items-center",
583
648
  "aria-current": step.status === "active" ? "step" : void 0,
584
649
  children: [
585
- /* @__PURE__ */ jsxs8("span", { className: "flex items-center gap-1.5", children: [
586
- /* @__PURE__ */ jsx9(StepIndicator, { status: step.status }),
587
- /* @__PURE__ */ jsx9("span", { className: clsx10("text-body-xs whitespace-nowrap", labelClass[step.status]), children: step.label })
650
+ /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-1.5", children: [
651
+ /* @__PURE__ */ jsx10(StepIndicator, { status: step.status }),
652
+ /* @__PURE__ */ jsx10("span", { className: clsx11("text-body-xs whitespace-nowrap", labelClass[step.status]), children: step.label })
588
653
  ] }),
589
- i < steps.length - 1 && /* @__PURE__ */ jsx9(ChevronSeparator, {})
654
+ i < steps.length - 1 && /* @__PURE__ */ jsx10(ChevronSeparator, {})
590
655
  ]
591
656
  },
592
657
  i
@@ -595,9 +660,10 @@ function Stepper({ steps, className }) {
595
660
  );
596
661
  }
597
662
 
598
- // src/components/multiselect-card.tsx
599
- import clsx11 from "clsx";
600
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
663
+ // src/components/forms/multiselect-card.tsx
664
+ import clsx12 from "clsx";
665
+ import { LuCheck as LuCheck2 } from "react-icons/lu";
666
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
601
667
  function MultiSelectCard({
602
668
  icon,
603
669
  title,
@@ -606,299 +672,245 @@ function MultiSelectCard({
606
672
  onToggle,
607
673
  className
608
674
  }) {
609
- return /* @__PURE__ */ jsxs9(
675
+ return /* @__PURE__ */ jsxs10(
610
676
  "button",
611
677
  {
612
678
  type: "button",
613
679
  role: "checkbox",
614
680
  "aria-checked": selected,
615
681
  onClick: onToggle,
616
- className: clsx11(
682
+ className: clsx12(
617
683
  "relative w-full rounded-2xl border-2 p-4 text-left transition-all",
618
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-1",
619
- selected ? "border-border-brand bg-background-brand-tertiary" : "border-border-default bg-background-default hover:border-border-default-secondary",
684
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1",
685
+ selected ? "border-brand bg-brand-tertiary" : "border-default bg-default hover:border-default-secondary",
620
686
  className
621
687
  ),
622
688
  children: [
623
- /* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between gap-2", children: [
624
- /* @__PURE__ */ jsx10(
689
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-start justify-between gap-2", children: [
690
+ /* @__PURE__ */ jsx11(
625
691
  "span",
626
692
  {
627
- className: clsx11(
693
+ className: clsx12(
628
694
  "flex size-10 shrink-0 items-center justify-center rounded-xl",
629
- selected ? "bg-background-brand" : "bg-background-brand-tertiary"
695
+ selected ? "bg-brand" : "bg-brand-tertiary"
630
696
  ),
631
- children: /* @__PURE__ */ jsx10("span", { className: clsx11("size-5", selected ? "text-icon-brand-on-brand" : "text-icon-brand"), children: icon })
697
+ children: /* @__PURE__ */ jsx11("span", { className: clsx12("size-5", selected ? "text-icon-brand-on-brand" : "text-icon-brand"), children: icon })
632
698
  }
633
699
  ),
634
- selected ? /* @__PURE__ */ jsx10("span", { className: "flex size-5 shrink-0 items-center justify-center rounded-full bg-background-brand", children: /* @__PURE__ */ jsx10("svg", { width: "11", height: "8", viewBox: "0 0 11 8", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ jsx10(
635
- "path",
636
- {
637
- d: "M1 4L3.9 7L10 1",
638
- stroke: "white",
639
- strokeWidth: "1.5",
640
- strokeLinecap: "round",
641
- strokeLinejoin: "round"
642
- }
643
- ) }) }) : /* @__PURE__ */ jsx10(
700
+ selected ? /* @__PURE__ */ jsx11("span", { className: "flex size-5 shrink-0 items-center justify-center rounded-full bg-brand text-icon-brand-on-brand", children: /* @__PURE__ */ jsx11(LuCheck2, { className: "size-3", strokeWidth: 2.5, "aria-hidden": true }) }) : /* @__PURE__ */ jsx11(
644
701
  "span",
645
702
  {
646
- className: "size-5 shrink-0 rounded-full border-2 border-border-default",
703
+ className: "size-5 shrink-0 rounded-full border-2 border-default",
647
704
  "aria-hidden": "true"
648
705
  }
649
706
  )
650
707
  ] }),
651
- /* @__PURE__ */ jsxs9("div", { className: "mt-3", children: [
652
- /* @__PURE__ */ jsx10(
708
+ /* @__PURE__ */ jsxs10("div", { className: "mt-3", children: [
709
+ /* @__PURE__ */ jsx11(
653
710
  "p",
654
711
  {
655
- className: clsx11(
712
+ className: clsx12(
656
713
  "text-body-sm font-semibold",
657
- selected ? "text-text-brand" : "text-text-default"
714
+ selected ? "text-brand" : "text-default"
658
715
  ),
659
716
  children: title
660
717
  }
661
718
  ),
662
- description && /* @__PURE__ */ jsx10("p", { className: "mt-0.5 text-body-xs text-text-default-secondary", children: description })
719
+ description && /* @__PURE__ */ jsx11("p", { className: "mt-0.5 text-body-xs text-default-secondary", children: description })
663
720
  ] })
664
721
  ]
665
722
  }
666
723
  );
667
724
  }
668
725
 
669
- // src/components/data-table.tsx
670
- import clsx12 from "clsx";
671
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
672
- function DataTable({
673
- columns,
674
- rows,
675
- getRowKey,
676
- className,
677
- onRowClick
678
- }) {
679
- return /* @__PURE__ */ jsxs10(
680
- "div",
681
- {
682
- className: clsx12(
683
- "overflow-hidden rounded-xl border border-border-default bg-background-default",
684
- className
685
- ),
686
- children: [
687
- /* @__PURE__ */ jsx11("div", { className: "flex items-center bg-background-default-secondary px-4 py-3", children: columns.map((col) => /* @__PURE__ */ jsx11("div", { className: clsx12("overflow-hidden", col.grow ? "flex-1 min-w-0" : "shrink-0"), style: col.grow ? { minWidth: col.width } : { width: col.width }, children: /* @__PURE__ */ jsx11("span", { className: "text-body-xs font-medium text-text-default-secondary whitespace-nowrap", children: col.header }) }, col.key)) }),
688
- /* @__PURE__ */ jsx11("div", { children: rows.map((row, i) => /* @__PURE__ */ jsx11(
689
- "div",
690
- {
691
- className: clsx12(
692
- "flex items-center px-4 py-[14px] transition-colors hover:bg-background-default-secondary/50",
693
- i > 0 && "border-t border-[#ececec]",
694
- onRowClick && "cursor-pointer"
695
- ),
696
- onClick: onRowClick ? () => onRowClick(row) : void 0,
697
- children: columns.map((col) => /* @__PURE__ */ jsx11("div", { className: clsx12("overflow-hidden", col.grow ? "flex-1 min-w-0" : "shrink-0"), style: col.grow ? { minWidth: col.width } : { width: col.width }, children: col.render(row) }, col.key))
698
- },
699
- getRowKey(row, i)
700
- )) })
701
- ]
702
- }
703
- );
704
- }
705
- function TableCellLeadText({
706
- primary,
707
- secondary
708
- }) {
709
- return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-0.5", children: [
710
- /* @__PURE__ */ jsx11("span", { className: "text-body-sm font-medium text-text-default leading-snug", children: primary }),
711
- secondary && /* @__PURE__ */ jsx11("span", { className: "text-body-xs font-normal text-text-default-secondary leading-tight", children: secondary })
712
- ] });
713
- }
714
- function TableCellText({
715
- children,
716
- muted = true
717
- }) {
718
- return /* @__PURE__ */ jsx11(
719
- "span",
720
- {
721
- className: clsx12(
722
- "text-body-xs font-normal leading-snug whitespace-nowrap",
723
- muted ? "text-text-default-secondary" : "text-text-default"
724
- ),
725
- children
726
- }
727
- );
728
- }
729
- function TableCellBadge({ label }) {
730
- return /* @__PURE__ */ jsx11("span", { className: "inline-flex items-center rounded-md border border-border-default bg-background-default-secondary px-2 py-0.5 text-body-tiny font-medium text-text-default-secondary whitespace-nowrap", children: label });
731
- }
732
- function TableCellStatusPill({
733
- label,
734
- dotColor,
735
- backgroundColor,
736
- textColor
737
- }) {
738
- return /* @__PURE__ */ jsxs10(
739
- "span",
740
- {
741
- className: "inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-body-xs font-medium leading-tight whitespace-nowrap",
742
- style: { backgroundColor, color: textColor },
743
- children: [
744
- /* @__PURE__ */ jsx11("span", { className: "size-1.5 shrink-0 rounded-full", style: { backgroundColor: dotColor } }),
745
- label
746
- ]
747
- }
748
- );
749
- }
750
- function TableCellProgress({
751
- percent,
752
- barColor
753
- }) {
754
- const color = barColor ?? "#0c2d58";
755
- const clamped = Math.min(100, Math.max(0, percent));
756
- return /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-1", children: [
757
- /* @__PURE__ */ jsx11("div", { className: "h-1.5 w-16 overflow-hidden rounded-full bg-background-default-secondary", children: /* @__PURE__ */ jsx11(
758
- "div",
759
- {
760
- className: "h-full rounded-full transition-all",
761
- style: { width: `${clamped}%`, backgroundColor: color }
762
- }
763
- ) }),
764
- /* @__PURE__ */ jsxs10("span", { className: "text-body-tiny text-text-default-secondary leading-none", children: [
765
- percent,
766
- "%"
767
- ] })
768
- ] });
769
- }
770
-
771
- // src/components/stat-tile.tsx
726
+ // src/components/forms/toggle.tsx
772
727
  import clsx13 from "clsx";
773
728
  import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
774
- function StatTile({ label, value, dotColor, className }) {
729
+ var SIZE = {
730
+ sm: { track: "h-5 w-9", knob: "size-4", translate: "translate-x-4" },
731
+ md: { track: "h-6 w-11", knob: "size-5", translate: "translate-x-5" }
732
+ };
733
+ function Toggle({
734
+ checked,
735
+ onChange,
736
+ label,
737
+ size = "md",
738
+ disabled = false,
739
+ id,
740
+ "aria-label": ariaLabel,
741
+ "aria-labelledby": ariaLabelledBy,
742
+ className
743
+ }) {
744
+ const s = SIZE[size];
775
745
  return /* @__PURE__ */ jsxs11(
776
- "div",
777
- {
778
- className: clsx13(
779
- "flex flex-col gap-2 rounded-xl border border-border-default bg-background-default p-4",
780
- className
781
- ),
782
- children: [
783
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1.5", children: [
784
- dotColor && /* @__PURE__ */ jsx12("span", { className: "size-2 shrink-0 rounded-full", style: { backgroundColor: dotColor } }),
785
- /* @__PURE__ */ jsx12("span", { className: "text-body-xs font-medium text-text-default-secondary whitespace-nowrap", children: label })
786
- ] }),
787
- /* @__PURE__ */ jsx12("span", { className: "text-heading font-semibold text-text-default leading-none", children: value })
788
- ]
789
- }
790
- );
791
- }
792
-
793
- // src/components/toggle.tsx
794
- import clsx14 from "clsx";
795
- import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
796
- function Toggle({ checked, onChange, label, disabled = false }) {
797
- return /* @__PURE__ */ jsxs12(
798
746
  "button",
799
747
  {
800
748
  type: "button",
801
749
  role: "switch",
750
+ id,
802
751
  "aria-checked": checked,
752
+ "aria-label": label ? void 0 : ariaLabel,
753
+ "aria-labelledby": ariaLabelledBy,
803
754
  disabled,
804
755
  onClick: () => onChange(!checked),
805
- className: clsx14(
806
- "flex items-center gap-2",
807
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-1",
808
- disabled && "cursor-not-allowed opacity-50"
756
+ className: clsx13(
757
+ "group flex items-center gap-2",
758
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1",
759
+ disabled && "cursor-not-allowed opacity-50",
760
+ className
809
761
  ),
810
762
  children: [
811
- /* @__PURE__ */ jsx13(
763
+ /* @__PURE__ */ jsx12(
812
764
  "span",
813
765
  {
814
- className: clsx14(
815
- "relative inline-flex h-6 w-10 shrink-0 rounded-full transition-colors",
816
- checked ? "bg-background-brand" : "border border-border-default bg-background-neutral-tertiary"
766
+ className: clsx13(
767
+ "relative inline-flex shrink-0 rounded-full transition-colors",
768
+ s.track,
769
+ // The unchecked track is borderless per the spec. A border here would also
770
+ // shift the knob's rendered inset by 1px between states, since the knob is
771
+ // positioned against the padding box.
772
+ disabled ? "bg-disabled" : checked ? "bg-brand group-hover:bg-brand-hover" : "bg-default-secondary group-hover:bg-default-secondary-hover"
817
773
  ),
818
- children: /* @__PURE__ */ jsx13(
774
+ children: /* @__PURE__ */ jsx12(
819
775
  "span",
820
776
  {
821
- className: clsx14(
822
- "absolute left-0.5 top-0.5 size-5 rounded-full bg-white shadow-sm transition-transform",
823
- checked ? "translate-x-4" : "translate-x-0"
777
+ className: clsx13(
778
+ "absolute left-0.5 top-0.5 rounded-full bg-default shadow-sm transition-transform",
779
+ s.knob,
780
+ checked ? s.translate : "translate-x-0"
824
781
  )
825
782
  }
826
783
  )
827
784
  }
828
785
  ),
829
- label && /* @__PURE__ */ jsx13("span", { className: "text-body-xs text-text-default", children: label })
786
+ label && /* @__PURE__ */ jsx12("span", { className: "text-body-xs text-default", children: label })
830
787
  ]
831
788
  }
832
789
  );
833
790
  }
834
791
 
835
- // src/components/file-drop-zone.tsx
792
+ // src/components/forms/file-drop-zone.tsx
836
793
  import { useRef, useState } from "react";
837
- import clsx15 from "clsx";
794
+ import clsx14 from "clsx";
838
795
  import { LuUpload } from "react-icons/lu";
839
- import { Fragment, jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
840
- function FileDropZone({ className }) {
796
+ import { Fragment, jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
797
+ var DEFAULT_ACCEPT = ".pdf,.jpg,.jpeg,.png";
798
+ var DEFAULT_MAX_SIZE_BYTES = 10 * 1024 * 1024;
799
+ function formatSize(bytes) {
800
+ const mb = bytes / (1024 * 1024);
801
+ return `${Number.isInteger(mb) ? mb : mb.toFixed(1)} MB`;
802
+ }
803
+ function matchesAccept(file, accept) {
804
+ const extensions = accept.split(",").map((part) => part.trim().toLowerCase()).filter((part) => part.startsWith("."));
805
+ if (extensions.length === 0) {
806
+ return true;
807
+ }
808
+ return extensions.some((extension) => file.name.toLowerCase().endsWith(extension));
809
+ }
810
+ function FileDropZone({
811
+ className,
812
+ description = "Drag & drop or browse \xB7 PDF, JPG, PNG \xB7 up to 10 MB",
813
+ accept = DEFAULT_ACCEPT,
814
+ maxSizeBytes = DEFAULT_MAX_SIZE_BYTES,
815
+ onFileSelected,
816
+ disabled = false
817
+ }) {
841
818
  const inputRef = useRef(null);
842
819
  const [isDragging, setIsDragging] = useState(false);
843
- return /* @__PURE__ */ jsxs13(Fragment, { children: [
844
- /* @__PURE__ */ jsx14(
820
+ const [error, setError] = useState(null);
821
+ function handleFiles(files) {
822
+ const file = files?.[0];
823
+ if (!file) {
824
+ return;
825
+ }
826
+ if (!matchesAccept(file, accept)) {
827
+ setError(`Unsupported file type. Allowed: ${accept}.`);
828
+ return;
829
+ }
830
+ if (file.size > maxSizeBytes) {
831
+ setError(`That file is ${formatSize(file.size)}. The limit is ${formatSize(maxSizeBytes)}.`);
832
+ return;
833
+ }
834
+ setError(null);
835
+ onFileSelected?.(file);
836
+ }
837
+ return /* @__PURE__ */ jsxs12(Fragment, { children: [
838
+ /* @__PURE__ */ jsx13(
845
839
  "input",
846
840
  {
847
841
  ref: inputRef,
848
842
  type: "file",
849
- accept: ".pdf,.jpg,.jpeg,.png",
843
+ accept,
850
844
  className: "sr-only",
851
- tabIndex: -1
845
+ tabIndex: -1,
846
+ disabled,
847
+ onChange: (e) => {
848
+ handleFiles(e.target.files);
849
+ e.target.value = "";
850
+ }
852
851
  }
853
852
  ),
854
- /* @__PURE__ */ jsxs13(
853
+ /* @__PURE__ */ jsxs12(
855
854
  "div",
856
855
  {
857
856
  role: "button",
858
- tabIndex: 0,
859
- onClick: () => inputRef.current?.click(),
860
- onKeyDown: (e) => (e.key === "Enter" || e.key === " ") && inputRef.current?.click(),
857
+ tabIndex: disabled ? -1 : 0,
858
+ "aria-disabled": disabled,
859
+ onClick: () => {
860
+ if (!disabled) inputRef.current?.click();
861
+ },
862
+ onKeyDown: (e) => {
863
+ if (!disabled && (e.key === "Enter" || e.key === " ")) {
864
+ e.preventDefault();
865
+ inputRef.current?.click();
866
+ }
867
+ },
861
868
  onDragOver: (e) => {
862
869
  e.preventDefault();
863
- setIsDragging(true);
870
+ if (!disabled) setIsDragging(true);
864
871
  },
865
872
  onDragEnter: (e) => {
866
873
  e.preventDefault();
867
- setIsDragging(true);
874
+ if (!disabled) setIsDragging(true);
868
875
  },
869
876
  onDragLeave: () => setIsDragging(false),
870
877
  onDrop: (e) => {
871
878
  e.preventDefault();
872
879
  setIsDragging(false);
880
+ if (!disabled) handleFiles(e.dataTransfer.files);
873
881
  },
874
- className: clsx15(
875
- "flex flex-col items-center justify-center gap-1 rounded-lg border-2 border-dashed py-4 px-4 cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-1",
876
- isDragging ? "border-border-brand bg-background-brand-tertiary" : "border-border-default bg-background-default-secondary hover:border-border-brand hover:bg-background-brand-tertiary",
882
+ className: clsx14(
883
+ "flex flex-col items-center justify-center gap-1 rounded-lg border-2 border-dashed py-4 px-4 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1",
884
+ disabled ? "cursor-not-allowed border-disabled bg-disabled" : clsx14(
885
+ "cursor-pointer",
886
+ isDragging ? "border-brand bg-brand-tertiary" : "border-default bg-default-secondary hover:border-brand hover:bg-brand-tertiary"
887
+ ),
877
888
  className
878
889
  ),
879
890
  children: [
880
- /* @__PURE__ */ jsx14("span", { className: isDragging ? "text-text-brand" : "text-text-default-secondary", children: /* @__PURE__ */ jsx14(LuUpload, { size: 20 }) }),
881
- /* @__PURE__ */ jsx14("span", { className: "text-body-sm font-medium text-text-default", children: "Upload file" }),
882
- /* @__PURE__ */ jsx14("span", { className: "text-body-xs text-text-default-secondary text-center", children: "Drag & drop or browse \xB7 PDF, JPG, PNG \xB7 up to 10 MB" })
891
+ /* @__PURE__ */ jsx13("span", { className: disabled ? "text-disabled" : isDragging ? "text-brand" : "text-default-secondary", children: /* @__PURE__ */ jsx13(LuUpload, { className: "size-5" }) }),
892
+ /* @__PURE__ */ jsx13("span", { className: clsx14("text-body-sm font-medium", disabled ? "text-disabled" : "text-default"), children: "Upload file" }),
893
+ /* @__PURE__ */ jsx13("span", { className: "text-body-xs text-default-secondary text-center", children: description })
883
894
  ]
884
895
  }
885
- )
896
+ ),
897
+ error && /* @__PURE__ */ jsx13("span", { role: "alert", className: "text-body-xs text-danger", children: error })
886
898
  ] });
887
899
  }
888
900
 
889
- // src/components/form-card.tsx
890
- import clsx16 from "clsx";
901
+ // src/components/forms/form-card.tsx
902
+ import clsx15 from "clsx";
891
903
  import { LuArrowLeft, LuArrowRight } from "react-icons/lu";
892
- import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
904
+ import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
893
905
  function FormCard({
894
906
  children,
895
907
  className
896
908
  }) {
897
- return /* @__PURE__ */ jsx15(
909
+ return /* @__PURE__ */ jsx14(
898
910
  "div",
899
911
  {
900
- className: clsx16(
901
- "overflow-hidden rounded-xl border border-border-default bg-background-default",
912
+ className: clsx15(
913
+ "overflow-hidden rounded-xl border border-default bg-default",
902
914
  className
903
915
  ),
904
916
  children
@@ -906,9 +918,9 @@ function FormCard({
906
918
  );
907
919
  }
908
920
  function FormCardHeader({ title, subtitle }) {
909
- return /* @__PURE__ */ jsxs14("div", { className: "border-b border-border-default px-7 py-6", children: [
910
- /* @__PURE__ */ jsx15("h2", { className: "text-heading-sm font-semibold text-text-default leading-snug", children: title }),
911
- subtitle && /* @__PURE__ */ jsx15("p", { className: "mt-1 text-body-xs text-text-default-secondary", children: subtitle })
921
+ return /* @__PURE__ */ jsxs13("div", { className: "border-b border-default px-7 py-6", children: [
922
+ /* @__PURE__ */ jsx14("h2", { className: "text-heading-sm font-semibold text-default leading-snug", children: title }),
923
+ subtitle && /* @__PURE__ */ jsx14("p", { className: "mt-1 text-body-xs text-default-secondary", children: subtitle })
912
924
  ] });
913
925
  }
914
926
  function FormCardFooter({
@@ -916,131 +928,104 @@ function FormCardFooter({
916
928
  onBack,
917
929
  onContinue,
918
930
  continueLabel = "Continue",
919
- backDisabled = false
931
+ backDisabled = false,
932
+ continueDisabled = false
920
933
  }) {
921
- return /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between border-t border-border-default px-7 py-5", children: [
922
- /* @__PURE__ */ jsx15(Button, { variant: "neutral", size: "md", onClick: onSaveDraft, children: "Save as draft" }),
923
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
924
- !backDisabled && /* @__PURE__ */ jsx15(Button, { variant: "neutral", size: "md", leadingIcon: /* @__PURE__ */ jsx15(LuArrowLeft, { size: 16 }), onClick: onBack, children: "Back" }),
925
- /* @__PURE__ */ jsx15(Button, { variant: "primary", size: "md", trailingIcon: /* @__PURE__ */ jsx15(LuArrowRight, { size: 16 }), onClick: onContinue, children: continueLabel })
934
+ return /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between border-t border-default px-7 py-5", children: [
935
+ /* @__PURE__ */ jsx14(Button, { variant: "neutral", size: "md", onClick: onSaveDraft, disabled: !onSaveDraft, children: "Save as draft" }),
936
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
937
+ !backDisabled && /* @__PURE__ */ jsx14(Button, { variant: "neutral", size: "md", leadingIcon: /* @__PURE__ */ jsx14(LuArrowLeft, { size: 16 }), onClick: onBack, children: "Back" }),
938
+ /* @__PURE__ */ jsx14(Button, { variant: "primary", size: "md", trailingIcon: /* @__PURE__ */ jsx14(LuArrowRight, { size: 16 }), onClick: onContinue, disabled: continueDisabled, children: continueLabel })
926
939
  ] })
927
940
  ] });
928
941
  }
929
942
 
930
- // src/components/document-row.tsx
931
- import clsx17 from "clsx";
932
- import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
933
- var STATUS_CONFIG = {
934
- uploaded: { label: "\u2713 Uploaded", style: "bg-[#e6f4ea] text-[#1f7a3d]" },
935
- "under-review": { label: "\u25CF Under review", style: "bg-[#fbe6cf] text-[#9a6206]" },
936
- processing: { label: "\u25CF Processing", style: "bg-[#e9eff7] text-[#0c2d58]" },
937
- missing: { label: "Missing", style: "bg-[#fee2e2] text-[#b91c1c]" },
938
- "not-provided": { label: "Not provided", style: "bg-background-default-secondary text-text-default-secondary" }
943
+ // src/components/status/badge.tsx
944
+ import clsx16 from "clsx";
945
+ import { LuX } from "react-icons/lu";
946
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
947
+ var defaultClasses = {
948
+ gray: "bg-badge-gray text-badge-gray",
949
+ red: "bg-badge-red text-badge-red",
950
+ yellow: "bg-badge-yellow text-badge-yellow",
951
+ lime: "bg-badge-lime text-badge-lime",
952
+ green: "bg-badge-green text-badge-green",
953
+ teal: "bg-badge-teal text-badge-teal",
954
+ blue: "bg-badge-blue text-badge-blue",
955
+ pink: "bg-badge-pink text-badge-pink",
956
+ slate: "bg-badge-slate text-badge-slate"
939
957
  };
940
- function FileTypeBadge({ type }) {
941
- return /* @__PURE__ */ jsx16("div", { className: "flex h-[34px] w-[34px] shrink-0 items-center justify-center rounded-md bg-background-brand-tertiary", children: /* @__PURE__ */ jsx16("span", { className: "text-body-tiny font-semibold text-text-brand", children: type }) });
942
- }
943
- function DocumentRow({
944
- title,
945
- required,
946
- description,
947
- status,
948
- fileName,
949
- fileSize,
950
- fileType = "PDF"
958
+ var subtleClasses = {
959
+ gray: "border border-badge-gray text-default-secondary",
960
+ red: "border border-badge-red text-default-secondary",
961
+ yellow: "border border-badge-yellow text-default-secondary",
962
+ lime: "border border-badge-lime text-default-secondary",
963
+ green: "border border-badge-green text-default-secondary",
964
+ teal: "border border-badge-teal text-default-secondary",
965
+ blue: "border border-badge-blue text-default-secondary",
966
+ pink: "border border-badge-pink text-default-secondary",
967
+ slate: "border border-badge-slate text-default-secondary"
968
+ };
969
+ function Badge({
970
+ label,
971
+ color = "gray",
972
+ size = "sm",
973
+ variant = "default",
974
+ indicator = false,
975
+ onClose,
976
+ className
951
977
  }) {
952
- const hasFile = (status === "uploaded" || status === "under-review" || status === "processing") && !!fileName;
953
- const cfg = STATUS_CONFIG[status];
954
- return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-3 py-4", children: [
955
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between gap-2", children: [
956
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 min-w-0", children: [
957
- /* @__PURE__ */ jsx16("span", { className: "text-body-sm font-semibold text-text-default truncate", children: title }),
958
- /* @__PURE__ */ jsx16("span", { className: "shrink-0 rounded-md border border-border-default bg-background-default-secondary px-2 py-0.5 text-body-tiny font-medium text-text-default-secondary", children: required ? "Required" : "Optional" })
959
- ] }),
960
- /* @__PURE__ */ jsx16(
961
- "span",
962
- {
963
- className: clsx17(
964
- "shrink-0 rounded-full px-2.5 py-0.5 text-body-tiny font-medium whitespace-nowrap",
965
- cfg.style
966
- ),
967
- children: cfg.label
968
- }
969
- )
970
- ] }),
971
- /* @__PURE__ */ jsx16("p", { className: "text-body-xs text-text-default-secondary", children: description }),
972
- hasFile ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-3 rounded-lg border border-border-default bg-background-default px-3 py-2.5", children: [
973
- /* @__PURE__ */ jsx16(FileTypeBadge, { type: fileType }),
974
- /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
975
- /* @__PURE__ */ jsx16("span", { className: "truncate text-body-sm font-medium text-text-default", children: fileName }),
976
- fileSize && /* @__PURE__ */ jsx16("span", { className: "text-body-xs text-text-default-secondary", children: fileSize })
977
- ] }),
978
- /* @__PURE__ */ jsxs15("div", { className: "flex shrink-0 items-center gap-4", children: [
979
- /* @__PURE__ */ jsx16(
980
- "button",
978
+ const isDefault = variant === "default";
979
+ return /* @__PURE__ */ jsxs14(
980
+ "span",
981
+ {
982
+ className: clsx16(
983
+ "inline-flex items-center rounded-full px-2 py-0.5",
984
+ size === "sm" ? "gap-1" : "gap-1.5",
985
+ isDefault ? defaultClasses[color] : subtleClasses[color],
986
+ className
987
+ ),
988
+ children: [
989
+ indicator && /* @__PURE__ */ jsx15(
990
+ "span",
981
991
  {
982
- type: "button",
983
- className: "text-body-xs font-medium text-text-brand hover:underline",
984
- children: "Replace"
992
+ className: clsx16(
993
+ "shrink-0 rounded-full bg-current",
994
+ size === "sm" ? "h-1.5 w-1.5" : "h-2 w-2"
995
+ )
996
+ }
997
+ ),
998
+ /* @__PURE__ */ jsx15(
999
+ "span",
1000
+ {
1001
+ className: clsx16(
1002
+ "whitespace-nowrap",
1003
+ size === "sm" ? clsx16("text-body-tiny", isDefault && "font-semibold") : "text-body-xs"
1004
+ ),
1005
+ children: label
985
1006
  }
986
1007
  ),
987
- /* @__PURE__ */ jsx16(
1008
+ onClose && /* @__PURE__ */ jsx15(
988
1009
  "button",
989
1010
  {
990
1011
  type: "button",
991
- className: "text-body-xs font-medium text-text-danger hover:underline",
992
- children: "Remove"
1012
+ onClick: onClose,
1013
+ className: clsx16(
1014
+ "inline-flex shrink-0 items-center justify-center rounded-full opacity-60 transition-opacity hover:opacity-100",
1015
+ size === "sm" ? "h-3 w-3" : "h-4 w-4"
1016
+ ),
1017
+ "aria-label": "Remove",
1018
+ children: /* @__PURE__ */ jsx15(LuX, { className: "h-full w-full", strokeWidth: 2.5, "aria-hidden": true })
993
1019
  }
994
1020
  )
995
- ] })
996
- ] }) : /* @__PURE__ */ jsx16(FileDropZone, {})
997
- ] });
998
- }
999
-
1000
- // src/components/modal.tsx
1001
- import clsx18 from "clsx";
1002
- import { LuX } from "react-icons/lu";
1003
- import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
1004
- function Modal({ isOpen, onClose, title, subtitle, children, footer, maxWidth = "max-w-[540px]" }) {
1005
- if (!isOpen) return null;
1006
- return /* @__PURE__ */ jsx17(
1007
- "div",
1008
- {
1009
- className: "fixed inset-0 z-50 flex items-center justify-center bg-black/80",
1010
- onClick: (e) => {
1011
- if (e.target === e.currentTarget) onClose();
1012
- },
1013
- children: /* @__PURE__ */ jsxs16("div", { className: clsx18("w-full mx-4 rounded-2xl bg-white shadow-xl", maxWidth), children: [
1014
- /* @__PURE__ */ jsxs16("div", { className: "flex items-start justify-between px-6 py-5", children: [
1015
- /* @__PURE__ */ jsxs16("div", { children: [
1016
- /* @__PURE__ */ jsx17("h2", { className: "text-heading-sm font-semibold text-text-default", children: title }),
1017
- subtitle && /* @__PURE__ */ jsx17("p", { className: "mt-0.5 text-body-xs text-text-default-secondary", children: subtitle })
1018
- ] }),
1019
- /* @__PURE__ */ jsx17(
1020
- IconButton,
1021
- {
1022
- variant: "subtle",
1023
- size: "sm",
1024
- "aria-label": "Close dialog",
1025
- icon: /* @__PURE__ */ jsx17(LuX, { size: 16 }),
1026
- onClick: onClose
1027
- }
1028
- )
1029
- ] }),
1030
- /* @__PURE__ */ jsx17("hr", { className: "border-border-default" }),
1031
- /* @__PURE__ */ jsx17("div", { className: "px-6 py-5", children }),
1032
- footer && /* @__PURE__ */ jsxs16(Fragment2, { children: [
1033
- /* @__PURE__ */ jsx17("hr", { className: "border-border-default" }),
1034
- /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-end gap-2 px-6 py-4", children: footer })
1035
- ] })
1036
- ] })
1021
+ ]
1037
1022
  }
1038
1023
  );
1039
1024
  }
1040
1025
 
1041
- // src/components/role-badge.tsx
1042
- import clsx19 from "clsx";
1043
- import { jsx as jsx18 } from "react/jsx-runtime";
1026
+ // src/components/status/role-badge.tsx
1027
+ import clsx17 from "clsx";
1028
+ import { jsx as jsx16 } from "react/jsx-runtime";
1044
1029
  var ROLE_COLORS = {
1045
1030
  "Super Admin": { bg: "#e9eff7", text: "#0c2d58" },
1046
1031
  "Admin": { bg: "#e9eff7", text: "#0c2d58" },
@@ -1054,12 +1039,19 @@ var ROLE_COLORS = {
1054
1039
  "User": { bg: "#e9eff7", text: "#0c2d58" }
1055
1040
  };
1056
1041
  var FALLBACK = { bg: "#f5f5f5", text: "#757575" };
1057
- function RoleBadge({ role, size = "sm" }) {
1058
- const colors = ROLE_COLORS[role] ?? FALLBACK;
1059
- return /* @__PURE__ */ jsx18(
1042
+ var HEX6 = /^#[0-9a-fA-F]{6}$/;
1043
+ function resolveColors(role, color) {
1044
+ if (color && HEX6.test(color)) {
1045
+ return { bg: `${color}1F`, text: color };
1046
+ }
1047
+ return ROLE_COLORS[role] ?? FALLBACK;
1048
+ }
1049
+ function RoleBadge({ role, size = "sm", color }) {
1050
+ const colors = resolveColors(role, color);
1051
+ return /* @__PURE__ */ jsx16(
1060
1052
  "span",
1061
1053
  {
1062
- className: clsx19(
1054
+ className: clsx17(
1063
1055
  "inline-flex items-center rounded-full font-medium whitespace-nowrap",
1064
1056
  size === "sm" ? "px-2 py-0.5 text-body-tiny" : "px-3 py-1 text-body-xs"
1065
1057
  ),
@@ -1069,10 +1061,10 @@ function RoleBadge({ role, size = "sm" }) {
1069
1061
  );
1070
1062
  }
1071
1063
 
1072
- // src/components/role-combo-box.tsx
1064
+ // src/components/forms/role-combo-box.tsx
1073
1065
  import { useEffect, useRef as useRef2, useState as useState2 } from "react";
1074
1066
  import { LuChevronDown as LuChevronDown2 } from "react-icons/lu";
1075
- import { Fragment as Fragment3, jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
1067
+ import { Fragment as Fragment2, jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
1076
1068
  var ROLE_COMBO_OPTIONS = [
1077
1069
  { role: "Reviewer", description: "Reviews onboarding requests" },
1078
1070
  { role: "Admin", description: "Full org control" },
@@ -1111,21 +1103,32 @@ function RoleComboBox({ value, onChange, options = ROLE_COMBO_OPTIONS }) {
1111
1103
  const otherOptions = options.filter(
1112
1104
  (o) => o.role !== value && o.role.toLowerCase().includes(query.toLowerCase())
1113
1105
  );
1114
- return /* @__PURE__ */ jsxs17("div", { className: "relative", ref: containerRef, children: [
1115
- /* @__PURE__ */ jsxs17(
1106
+ return /* @__PURE__ */ jsxs15("div", { className: "relative", ref: containerRef, children: [
1107
+ /* @__PURE__ */ jsxs15(
1116
1108
  "div",
1117
1109
  {
1118
1110
  role: "combobox",
1119
1111
  "aria-expanded": open,
1120
1112
  "aria-haspopup": "listbox",
1121
1113
  onClick: openDropdown,
1122
- className: `flex h-11 cursor-pointer items-center gap-2 rounded-lg border-[1.5px] pl-2.5 pr-3 transition-colors ${open ? "border-blue-500" : "border-border-default hover:border-border-brand-tertiary"}`,
1114
+ tabIndex: 0,
1115
+ onKeyDown: (e) => {
1116
+ if (e.key === "Enter" || e.key === " ") {
1117
+ e.preventDefault();
1118
+ openDropdown();
1119
+ }
1120
+ if (e.key === "Escape") {
1121
+ setOpen(false);
1122
+ setQuery("");
1123
+ }
1124
+ },
1125
+ className: `flex h-11 cursor-pointer items-center gap-2 rounded-lg border-[1.5px] pl-2.5 pr-3 transition-colors ${open ? "border-blue-500" : "border-default hover:border-brand-tertiary"}`,
1123
1126
  children: [
1124
- /* @__PURE__ */ jsxs17("div", { className: "flex flex-1 min-w-0 items-center gap-1.5 overflow-hidden", children: [
1125
- /* @__PURE__ */ jsx19(RoleBadge, { role: value, size: "sm" }),
1126
- value === "User" && !open && /* @__PURE__ */ jsx19("span", { className: "rounded border border-border-default bg-background-default-secondary px-1.5 py-0.5 text-body-tiny font-medium text-text-default-secondary", children: "DEFAULT" }),
1127
- open && /* @__PURE__ */ jsxs17(Fragment3, { children: [
1128
- /* @__PURE__ */ jsx19(
1127
+ /* @__PURE__ */ jsxs15("div", { className: "flex flex-1 min-w-0 items-center gap-1.5 overflow-hidden", children: [
1128
+ /* @__PURE__ */ jsx17(RoleBadge, { role: value, size: "sm" }),
1129
+ value === "User" && !open && /* @__PURE__ */ jsx17("span", { className: "rounded border border-default bg-default-secondary px-1.5 py-0.5 text-body-tiny font-medium text-default-secondary", children: "DEFAULT" }),
1130
+ open && /* @__PURE__ */ jsxs15(Fragment2, { children: [
1131
+ /* @__PURE__ */ jsx17(
1129
1132
  "input",
1130
1133
  {
1131
1134
  ref: inputRef,
@@ -1133,24 +1136,24 @@ function RoleComboBox({ value, onChange, options = ROLE_COMBO_OPTIONS }) {
1133
1136
  value: query,
1134
1137
  onChange: (e) => setQuery(e.target.value),
1135
1138
  onClick: (e) => e.stopPropagation(),
1136
- className: "min-w-0 flex-1 bg-transparent text-body-xs text-text-default outline-none",
1139
+ className: "min-w-0 flex-1 bg-transparent text-body-xs text-default outline-none",
1137
1140
  "aria-label": "Search roles"
1138
1141
  }
1139
1142
  ),
1140
- /* @__PURE__ */ jsx19("span", { className: "mx-0.5 h-[18px] w-px shrink-0 bg-text-default", "aria-hidden": true })
1143
+ /* @__PURE__ */ jsx17("span", { className: "mx-0.5 h-[18px] w-px shrink-0 bg-divider", "aria-hidden": true })
1141
1144
  ] })
1142
1145
  ] }),
1143
- /* @__PURE__ */ jsx19("span", { className: "shrink-0 text-text-default-secondary", children: /* @__PURE__ */ jsx19(LuChevronDown2, { size: 14 }) })
1146
+ /* @__PURE__ */ jsx17("span", { className: "shrink-0 text-default-secondary", children: /* @__PURE__ */ jsx17(LuChevronDown2, { size: 14 }) })
1144
1147
  ]
1145
1148
  }
1146
1149
  ),
1147
- open && /* @__PURE__ */ jsxs17(
1150
+ open && /* @__PURE__ */ jsxs15(
1148
1151
  "div",
1149
1152
  {
1150
1153
  role: "listbox",
1151
- className: "absolute left-0 right-0 top-full z-20 mt-1 flex max-h-64 flex-col gap-0.5 overflow-y-auto rounded-xl border border-border-default bg-white p-1.5 shadow-lg",
1154
+ className: "absolute left-0 right-0 top-full z-20 mt-1 flex max-h-64 flex-col gap-0.5 overflow-y-auto rounded-xl border border-default bg-white p-1.5 shadow-lg",
1152
1155
  children: [
1153
- selectedEntry && /* @__PURE__ */ jsxs17(
1156
+ selectedEntry && /* @__PURE__ */ jsxs15(
1154
1157
  "div",
1155
1158
  {
1156
1159
  role: "option",
@@ -1158,31 +1161,38 @@ function RoleComboBox({ value, onChange, options = ROLE_COMBO_OPTIONS }) {
1158
1161
  className: "flex cursor-pointer items-center gap-2.5 rounded-md bg-blue-50 px-2.5 py-2",
1159
1162
  onClick: () => select(selectedEntry.role),
1160
1163
  children: [
1161
- /* @__PURE__ */ jsx19(RoleBadge, { role: selectedEntry.role, size: "sm" }),
1162
- /* @__PURE__ */ jsx19("span", { className: "flex-1 text-body-xs text-text-default-secondary", children: selectedEntry.description }),
1163
- /* @__PURE__ */ jsx19("span", { className: "shrink-0 text-sm font-bold text-blue-600", children: "\u2713" })
1164
+ /* @__PURE__ */ jsx17(RoleBadge, { role: selectedEntry.role, size: "sm" }),
1165
+ /* @__PURE__ */ jsx17("span", { className: "flex-1 text-body-xs text-default-secondary", children: selectedEntry.description }),
1166
+ /* @__PURE__ */ jsx17("span", { className: "shrink-0 text-sm font-bold text-blue-600", children: "\u2713" })
1164
1167
  ]
1165
1168
  }
1166
1169
  ),
1167
- /* @__PURE__ */ jsx19("div", { className: "h-px bg-border-default" }),
1168
- otherOptions.length > 0 && /* @__PURE__ */ jsxs17(Fragment3, { children: [
1169
- /* @__PURE__ */ jsx19("div", { className: "px-2.5 pb-1 pt-1.5", children: /* @__PURE__ */ jsx19("span", { className: "text-body-tiny font-semibold uppercase tracking-wide text-text-default-secondary", children: "Other roles" }) }),
1170
- otherOptions.map((opt) => /* @__PURE__ */ jsxs17(
1170
+ /* @__PURE__ */ jsx17("div", { className: "h-px bg-divider" }),
1171
+ otherOptions.length > 0 && /* @__PURE__ */ jsxs15(Fragment2, { children: [
1172
+ /* @__PURE__ */ jsx17("div", { className: "px-2.5 pb-1 pt-1.5", children: /* @__PURE__ */ jsx17("span", { className: "text-body-tiny font-semibold uppercase tracking-wide text-default-secondary", children: "Other roles" }) }),
1173
+ otherOptions.map((opt) => /* @__PURE__ */ jsxs15(
1171
1174
  "div",
1172
1175
  {
1173
1176
  role: "option",
1174
1177
  "aria-selected": false,
1175
- className: "flex cursor-pointer items-center gap-2.5 rounded-md px-2.5 py-2 hover:bg-background-default-secondary",
1178
+ className: "flex cursor-pointer items-center gap-2.5 rounded-md px-2.5 py-2 hover:bg-default-secondary",
1176
1179
  onClick: () => select(opt.role),
1180
+ tabIndex: 0,
1181
+ onKeyDown: (e) => {
1182
+ if (e.key === "Enter" || e.key === " ") {
1183
+ e.preventDefault();
1184
+ select(opt.role);
1185
+ }
1186
+ },
1177
1187
  children: [
1178
- /* @__PURE__ */ jsx19(RoleBadge, { role: opt.role, size: "sm" }),
1179
- /* @__PURE__ */ jsx19("span", { className: "text-body-xs text-text-default-secondary", children: opt.description })
1188
+ /* @__PURE__ */ jsx17(RoleBadge, { role: opt.role, size: "sm" }),
1189
+ /* @__PURE__ */ jsx17("span", { className: "text-body-xs text-default-secondary", children: opt.description })
1180
1190
  ]
1181
1191
  },
1182
1192
  opt.role
1183
1193
  ))
1184
1194
  ] }),
1185
- otherOptions.length === 0 && query && /* @__PURE__ */ jsxs17("p", { className: "px-2.5 py-2 text-body-xs text-text-default-secondary", children: [
1195
+ otherOptions.length === 0 && query && /* @__PURE__ */ jsxs15("p", { className: "px-2.5 py-2 text-body-xs text-default-secondary", children: [
1186
1196
  'No roles match "',
1187
1197
  query,
1188
1198
  '"'
@@ -1193,92 +1203,2754 @@ function RoleComboBox({ value, onChange, options = ROLE_COMBO_OPTIONS }) {
1193
1203
  ] });
1194
1204
  }
1195
1205
 
1196
- // src/index.tsx
1197
- import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
1198
- function Panel({
1199
- children,
1200
- className
1206
+ // src/components/status/status-badge.tsx
1207
+ import clsx18 from "clsx";
1208
+ import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
1209
+ var TONE_STYLES = {
1210
+ neutral: "bg-status-neutral text-status-neutral",
1211
+ info: "bg-status-info text-status-info",
1212
+ warning: "bg-status-warning text-status-warning",
1213
+ caution: "bg-status-caution text-status-caution",
1214
+ accent: "bg-status-accent text-status-accent",
1215
+ positive: "bg-status-positive text-status-positive",
1216
+ danger: "bg-status-danger text-status-danger"
1217
+ };
1218
+ var DOT_STYLES = {
1219
+ neutral: "bg-status-dot-neutral",
1220
+ info: "bg-status-dot-info",
1221
+ warning: "bg-status-dot-warning",
1222
+ caution: "bg-status-dot-caution",
1223
+ accent: "bg-status-dot-accent",
1224
+ positive: "bg-status-dot-positive",
1225
+ danger: "bg-status-dot-danger"
1226
+ };
1227
+ var SIZE_STYLES = {
1228
+ sm: "px-2 py-0.5 text-body-tiny",
1229
+ md: "px-2.5 py-1 text-body-xs"
1230
+ };
1231
+ function StatusBadge({
1232
+ label,
1233
+ tone = "neutral",
1234
+ size = "md",
1235
+ dot = true,
1236
+ icon,
1237
+ className
1238
+ }) {
1239
+ return /* @__PURE__ */ jsxs16(
1240
+ "span",
1241
+ {
1242
+ className: clsx18(
1243
+ "inline-flex items-center gap-1.5 rounded-full font-medium leading-tight whitespace-nowrap",
1244
+ SIZE_STYLES[size],
1245
+ TONE_STYLES[tone],
1246
+ className
1247
+ ),
1248
+ children: [
1249
+ icon ? /* @__PURE__ */ jsx18("span", { className: "shrink-0", children: icon }) : dot && /* @__PURE__ */ jsx18("span", { className: clsx18("size-1.5 shrink-0 rounded-full", DOT_STYLES[tone]) }),
1250
+ label
1251
+ ]
1252
+ }
1253
+ );
1254
+ }
1255
+
1256
+ // src/components/status/status-dot.tsx
1257
+ import clsx19 from "clsx";
1258
+ import { jsx as jsx19 } from "react/jsx-runtime";
1259
+ var dotTones = {
1260
+ brand: "bg-brand",
1261
+ positive: "bg-positive",
1262
+ warning: "bg-warning",
1263
+ danger: "bg-danger",
1264
+ neutral: "bg-neutral",
1265
+ default: "bg-default-tertiary"
1266
+ };
1267
+ function StatusDot({ tone = "default", color, className }) {
1268
+ return /* @__PURE__ */ jsx19(
1269
+ "span",
1270
+ {
1271
+ className: clsx19("inline-block size-1.5 shrink-0 rounded-full", !color && dotTones[tone], className),
1272
+ style: color ? { backgroundColor: color } : void 0
1273
+ }
1274
+ );
1275
+ }
1276
+
1277
+ // src/components/status/status-chip.tsx
1278
+ import clsx20 from "clsx";
1279
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
1280
+ function StatusChip({ label, count, tone = "default", dotColor, bg, className }) {
1281
+ return /* @__PURE__ */ jsxs17(
1282
+ "span",
1283
+ {
1284
+ className: clsx20(
1285
+ "inline-flex items-center gap-1.5 rounded-full px-2.5 py-1",
1286
+ !bg && "bg-default-secondary",
1287
+ className
1288
+ ),
1289
+ style: bg ? { backgroundColor: bg } : void 0,
1290
+ children: [
1291
+ /* @__PURE__ */ jsx20(StatusDot, { tone, color: dotColor }),
1292
+ /* @__PURE__ */ jsx20("span", { className: "text-body-xs font-medium text-default", children: count }),
1293
+ /* @__PURE__ */ jsx20("span", { className: "text-body-xs text-default-secondary", children: label })
1294
+ ]
1295
+ }
1296
+ );
1297
+ }
1298
+
1299
+ // src/components/status/count-badge.tsx
1300
+ import clsx21 from "clsx";
1301
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
1302
+ function CountBadge({ count, label, tone = "positive", className }) {
1303
+ return /* @__PURE__ */ jsxs18(
1304
+ "span",
1305
+ {
1306
+ className: clsx21(
1307
+ "inline-flex items-center gap-1.5 rounded-full border border-default px-2.5 py-1 text-body-xs font-medium text-default",
1308
+ className
1309
+ ),
1310
+ children: [
1311
+ /* @__PURE__ */ jsx21(StatusDot, { tone }),
1312
+ count,
1313
+ label && /* @__PURE__ */ jsx21("span", { className: "text-default-secondary", children: label })
1314
+ ]
1315
+ }
1316
+ );
1317
+ }
1318
+
1319
+ // src/components/status/tag-pill.tsx
1320
+ import clsx22 from "clsx";
1321
+ import { jsx as jsx22 } from "react/jsx-runtime";
1322
+ var toneStyles = {
1323
+ default: "bg-default-secondary text-default-secondary",
1324
+ brand: "bg-brand-tertiary text-brand",
1325
+ positive: "bg-positive-tertiary text-positive",
1326
+ warning: "bg-warning-tertiary text-warning",
1327
+ danger: "bg-danger-tertiary text-danger"
1328
+ };
1329
+ function TagPill({ label, tone = "default", bg, color, className }) {
1330
+ return /* @__PURE__ */ jsx22(
1331
+ "span",
1332
+ {
1333
+ className: clsx22(
1334
+ "inline-flex items-center rounded-full px-2 py-0.5 text-body-xs font-medium",
1335
+ !bg && !color && toneStyles[tone],
1336
+ className
1337
+ ),
1338
+ style: {
1339
+ ...bg ? { backgroundColor: bg } : void 0,
1340
+ ...color ? { color } : void 0
1341
+ },
1342
+ children: label
1343
+ }
1344
+ );
1345
+ }
1346
+
1347
+ // src/components/status/trail-chip.tsx
1348
+ import clsx23 from "clsx";
1349
+ import { jsx as jsx23, jsxs as jsxs19 } from "react/jsx-runtime";
1350
+ var DOT = {
1351
+ neutral: "bg-status-dot-neutral",
1352
+ info: "bg-status-dot-info",
1353
+ warning: "bg-status-dot-warning",
1354
+ caution: "bg-status-dot-caution",
1355
+ accent: "bg-status-dot-accent",
1356
+ positive: "bg-status-dot-positive",
1357
+ danger: "bg-status-dot-danger"
1358
+ };
1359
+ function TrailChip({ label, value, tone = "info", dotColor, className }) {
1360
+ return /* @__PURE__ */ jsxs19(
1361
+ "div",
1362
+ {
1363
+ className: clsx23(
1364
+ "flex items-center gap-2 rounded-full border border-default bg-default px-3 py-1.5",
1365
+ className
1366
+ ),
1367
+ children: [
1368
+ /* @__PURE__ */ jsx23(
1369
+ "span",
1370
+ {
1371
+ className: clsx23("size-1.5 shrink-0 rounded-full", !dotColor && DOT[tone]),
1372
+ style: dotColor ? { backgroundColor: dotColor } : void 0
1373
+ }
1374
+ ),
1375
+ /* @__PURE__ */ jsx23("span", { className: "text-body-tiny font-semibold uppercase tracking-wide text-default-secondary", children: label }),
1376
+ /* @__PURE__ */ jsx23("span", { className: "text-body-xs font-medium text-default", children: value })
1377
+ ]
1378
+ }
1379
+ );
1380
+ }
1381
+
1382
+ // src/components/status/user-status-pill.tsx
1383
+ import { jsx as jsx24 } from "react/jsx-runtime";
1384
+ var STATUS_META = {
1385
+ active: { label: "Active", tone: "positive" },
1386
+ // `caution` (pale yellow), not `warning` (orange) — Pending is one step below a
1387
+ // warning on the severity ramp, and reads as waiting rather than at risk.
1388
+ pending: { label: "Pending", tone: "caution" },
1389
+ deactivated: { label: "Deactivated", tone: "danger" }
1390
+ };
1391
+ function UserStatusPill({ status }) {
1392
+ const { label, tone } = STATUS_META[status];
1393
+ return /* @__PURE__ */ jsx24(StatusBadge, { label, tone });
1394
+ }
1395
+
1396
+ // src/components/status/check-indicator.tsx
1397
+ import clsx24 from "clsx";
1398
+ import { LuCheck as LuCheck3, LuCircleAlert, LuLoaderCircle, LuMinus, LuX as LuX2 } from "react-icons/lu";
1399
+ import { jsx as jsx25 } from "react/jsx-runtime";
1400
+ var STATUS_STYLES = {
1401
+ passed: "bg-status-check-passed border-status-check-passed text-status-check-passed",
1402
+ in_progress: "bg-status-check-progress border-status-check-progress text-status-check-progress",
1403
+ action_required: "bg-status-check-failed border-status-check-failed text-status-check-failed",
1404
+ failed: "bg-status-check-failed border-status-check-failed text-status-check-failed",
1405
+ pending: "bg-status-check-pending border-status-check-pending text-status-check-pending",
1406
+ waived: "bg-status-check-pending border-status-check-pending text-status-check-pending"
1407
+ };
1408
+ function StatusGlyph({ status }) {
1409
+ switch (status) {
1410
+ case "passed":
1411
+ return /* @__PURE__ */ jsx25(LuCheck3, { className: "size-3", strokeWidth: 3, "aria-hidden": true });
1412
+ case "failed":
1413
+ return /* @__PURE__ */ jsx25(LuX2, { className: "size-3", strokeWidth: 3, "aria-hidden": true });
1414
+ case "waived":
1415
+ return /* @__PURE__ */ jsx25(LuMinus, { className: "size-3", strokeWidth: 3, "aria-hidden": true });
1416
+ case "in_progress":
1417
+ return /* @__PURE__ */ jsx25(LuLoaderCircle, { className: "size-3", strokeWidth: 3, "aria-hidden": true });
1418
+ case "action_required":
1419
+ return /* @__PURE__ */ jsx25(LuCircleAlert, { className: "size-3.5", strokeWidth: 2.5, "aria-hidden": true });
1420
+ case "pending":
1421
+ return null;
1422
+ }
1423
+ }
1424
+ function CheckIndicator({ status, label, className }) {
1425
+ return /* @__PURE__ */ jsx25(
1426
+ "div",
1427
+ {
1428
+ className: clsx24(
1429
+ "flex size-[22px] shrink-0 items-center justify-center rounded-full border-[1.5px]",
1430
+ STATUS_STYLES[status],
1431
+ className
1432
+ ),
1433
+ role: label ? "img" : void 0,
1434
+ "aria-label": label,
1435
+ "aria-hidden": label ? void 0 : true,
1436
+ children: /* @__PURE__ */ jsx25(StatusGlyph, { status })
1437
+ }
1438
+ );
1439
+ }
1440
+
1441
+ // src/components/status/entity-icon-badge.tsx
1442
+ import clsx25 from "clsx";
1443
+ import { jsx as jsx26 } from "react/jsx-runtime";
1444
+ var sizeStyles4 = {
1445
+ sm: "size-8",
1446
+ md: "size-10"
1447
+ };
1448
+ var shapeStyles = {
1449
+ square: { sm: "rounded-lg", md: "rounded-xl" },
1450
+ circle: { sm: "rounded-full", md: "rounded-full" }
1451
+ };
1452
+ var toneStyles2 = {
1453
+ default: "bg-default-secondary text-icon-default",
1454
+ brand: "bg-brand-tertiary text-icon-brand",
1455
+ positive: "bg-positive-tertiary text-icon-positive",
1456
+ warning: "bg-warning-tertiary text-icon-warning",
1457
+ danger: "bg-danger-tertiary text-icon-danger",
1458
+ neutral: "bg-neutral-tertiary text-icon-neutral"
1459
+ };
1460
+ function EntityIconBadge({ size = "sm", tone = "default", shape = "square", bg, iconColor, children, className }) {
1461
+ return /* @__PURE__ */ jsx26(
1462
+ "span",
1463
+ {
1464
+ className: clsx25(
1465
+ "inline-flex shrink-0 items-center justify-center",
1466
+ sizeStyles4[size],
1467
+ shapeStyles[shape][size],
1468
+ !bg && !iconColor && toneStyles2[tone],
1469
+ className
1470
+ ),
1471
+ style: {
1472
+ ...bg ? { backgroundColor: bg } : void 0,
1473
+ ...iconColor ? { color: iconColor } : void 0
1474
+ },
1475
+ children
1476
+ }
1477
+ );
1478
+ }
1479
+
1480
+ // src/components/forms/checkbox.tsx
1481
+ import { useEffect as useEffect2, useRef as useRef3 } from "react";
1482
+ import clsx26 from "clsx";
1483
+ import { LuCheck as LuCheck4, LuMinus as LuMinus2 } from "react-icons/lu";
1484
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
1485
+ function Checkbox({
1486
+ checked,
1487
+ onChange,
1488
+ label,
1489
+ disabled = false,
1490
+ indeterminate = false,
1491
+ className
1492
+ }) {
1493
+ const inputRef = useRef3(null);
1494
+ useEffect2(() => {
1495
+ if (inputRef.current) inputRef.current.indeterminate = indeterminate;
1496
+ }, [indeterminate]);
1497
+ return /* @__PURE__ */ jsxs20(
1498
+ "label",
1499
+ {
1500
+ className: clsx26(
1501
+ "group inline-flex items-start gap-2.5",
1502
+ disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer",
1503
+ className
1504
+ ),
1505
+ children: [
1506
+ /* @__PURE__ */ jsx27(
1507
+ "input",
1508
+ {
1509
+ ref: inputRef,
1510
+ type: "checkbox",
1511
+ checked,
1512
+ disabled,
1513
+ onChange: (e) => onChange(e.target.checked),
1514
+ className: "peer sr-only"
1515
+ }
1516
+ ),
1517
+ /* @__PURE__ */ jsx27(
1518
+ "span",
1519
+ {
1520
+ "aria-hidden": true,
1521
+ className: clsx26(
1522
+ "mt-px flex size-[18px] shrink-0 items-center justify-center rounded-[4px] border-[1.5px] transition-colors",
1523
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-brand peer-focus-visible:ring-offset-1",
1524
+ checked || indeterminate ? "border-brand-emphasis bg-brand text-brand-on-brand" : "border-default-secondary bg-default"
1525
+ ),
1526
+ children: indeterminate ? /* @__PURE__ */ jsx27(LuMinus2, { className: "size-3", strokeWidth: 3 }) : checked ? /* @__PURE__ */ jsx27(LuCheck4, { className: "size-3", strokeWidth: 3 }) : null
1527
+ }
1528
+ ),
1529
+ label && /* @__PURE__ */ jsx27("span", { className: "text-body-xs text-default", children: label })
1530
+ ]
1531
+ }
1532
+ );
1533
+ }
1534
+
1535
+ // src/components/forms/segmented-control.tsx
1536
+ import clsx27 from "clsx";
1537
+ import { jsx as jsx28 } from "react/jsx-runtime";
1538
+ function SegmentedControl({ options, value, onChange, className }) {
1539
+ return /* @__PURE__ */ jsx28(
1540
+ "div",
1541
+ {
1542
+ className: clsx27(
1543
+ "inline-flex items-center rounded-xl border border-default bg-default-secondary p-0.5",
1544
+ className
1545
+ ),
1546
+ children: options.map((opt) => /* @__PURE__ */ jsx28(
1547
+ "button",
1548
+ {
1549
+ type: "button",
1550
+ onClick: () => onChange?.(opt.value),
1551
+ className: clsx27(
1552
+ "rounded-lg px-3.5 py-1.5 text-body-xs font-medium transition-colors",
1553
+ opt.value === value ? "bg-default shadow-panel text-default" : "text-default-secondary hover:text-default"
1554
+ ),
1555
+ children: opt.label
1556
+ },
1557
+ opt.value
1558
+ ))
1559
+ }
1560
+ );
1561
+ }
1562
+
1563
+ // src/components/overlays/modal.tsx
1564
+ import { useRef as useRef4 } from "react";
1565
+ import { LuCircleCheckBig, LuInfo, LuOctagonAlert, LuTriangleAlert, LuX as LuX3 } from "react-icons/lu";
1566
+
1567
+ // src/lib/cn.ts
1568
+ import { clsx as clsx28 } from "clsx";
1569
+ import { twMerge } from "tailwind-merge";
1570
+ function cn(...inputs) {
1571
+ return twMerge(clsx28(inputs));
1572
+ }
1573
+
1574
+ // src/components/overlays/overlay.ts
1575
+ import { useEffect as useEffect3 } from "react";
1576
+ var OVERLAY_SCRIM = "bg-overlay";
1577
+ var FOCUSABLE = [
1578
+ "a[href]",
1579
+ "button:not([disabled])",
1580
+ "input:not([disabled])",
1581
+ "select:not([disabled])",
1582
+ "textarea:not([disabled])",
1583
+ '[tabindex]:not([tabindex="-1"])'
1584
+ ].join(",");
1585
+ function focusableWithin(root) {
1586
+ return Array.from(root.querySelectorAll(FOCUSABLE)).filter(
1587
+ (el) => el.offsetParent !== null || el === root
1588
+ );
1589
+ }
1590
+ function useOverlayDismiss(onClose, panelRef) {
1591
+ useEffect3(() => {
1592
+ function onKeyDown(e) {
1593
+ const panel = panelRef.current;
1594
+ if (e.key === "Escape") {
1595
+ e.stopPropagation();
1596
+ onClose();
1597
+ return;
1598
+ }
1599
+ if (e.key !== "Tab" || !panel) return;
1600
+ const items = focusableWithin(panel);
1601
+ if (items.length === 0) return;
1602
+ const first = items[0];
1603
+ const last = items[items.length - 1];
1604
+ const active = document.activeElement;
1605
+ if (e.shiftKey && (active === first || !panel.contains(active))) {
1606
+ e.preventDefault();
1607
+ last.focus();
1608
+ } else if (!e.shiftKey && active === last) {
1609
+ e.preventDefault();
1610
+ first.focus();
1611
+ }
1612
+ }
1613
+ document.addEventListener("keydown", onKeyDown);
1614
+ return () => document.removeEventListener("keydown", onKeyDown);
1615
+ }, [onClose, panelRef]);
1616
+ useEffect3(() => {
1617
+ const previouslyFocused = document.activeElement;
1618
+ const panel = panelRef.current;
1619
+ if (panel) {
1620
+ const target = focusableWithin(panel)[0] ?? panel;
1621
+ target.focus({ preventScroll: true });
1622
+ }
1623
+ return () => previouslyFocused?.focus?.({ preventScroll: true });
1624
+ }, [panelRef]);
1625
+ }
1626
+
1627
+ // src/components/overlays/modal.tsx
1628
+ import { jsx as jsx29, jsxs as jsxs21 } from "react/jsx-runtime";
1629
+ var SIZE2 = {
1630
+ sm: "sm:max-w-[420px]",
1631
+ md: "sm:max-w-[540px]",
1632
+ lg: "sm:max-w-[640px]",
1633
+ xl: "sm:max-w-[800px]"
1634
+ };
1635
+ var TONE_ICON = {
1636
+ info: /* @__PURE__ */ jsx29(LuInfo, { className: "size-5" }),
1637
+ positive: /* @__PURE__ */ jsx29(LuCircleCheckBig, { className: "size-5" }),
1638
+ warning: /* @__PURE__ */ jsx29(LuTriangleAlert, { className: "size-5" }),
1639
+ danger: /* @__PURE__ */ jsx29(LuOctagonAlert, { className: "size-5" })
1640
+ };
1641
+ var TONE_BADGE = {
1642
+ info: "brand",
1643
+ positive: "positive",
1644
+ warning: "warning",
1645
+ danger: "danger"
1646
+ };
1647
+ var FOOTER_ALIGN = {
1648
+ start: "justify-start",
1649
+ between: "justify-between",
1650
+ end: "justify-end"
1651
+ };
1652
+ function Modal(props) {
1653
+ if (!props.isOpen) return null;
1654
+ return /* @__PURE__ */ jsx29(ModalShell, { ...props });
1655
+ }
1656
+ function ModalShell({
1657
+ onClose,
1658
+ label,
1659
+ children,
1660
+ size = "md",
1661
+ showClose = true,
1662
+ className
1663
+ }) {
1664
+ const panelRef = useRef4(null);
1665
+ useOverlayDismiss(onClose, panelRef);
1666
+ return /* @__PURE__ */ jsx29(
1667
+ "div",
1668
+ {
1669
+ className: cn("fixed inset-0 z-50 flex items-end justify-center sm:items-center", OVERLAY_SCRIM),
1670
+ onClick: (e) => {
1671
+ if (e.target === e.currentTarget) onClose();
1672
+ },
1673
+ children: /* @__PURE__ */ jsxs21(
1674
+ "div",
1675
+ {
1676
+ ref: panelRef,
1677
+ role: "dialog",
1678
+ "aria-modal": "true",
1679
+ "aria-label": label,
1680
+ className: cn(
1681
+ "relative max-h-[92dvh] w-full overflow-y-auto bg-default shadow-xl",
1682
+ "rounded-t-2xl pb-[env(safe-area-inset-bottom)] sm:mx-4 sm:rounded-2xl sm:pb-0",
1683
+ SIZE2[size],
1684
+ className
1685
+ ),
1686
+ children: [
1687
+ showClose && /* @__PURE__ */ jsx29(
1688
+ IconButton,
1689
+ {
1690
+ variant: "subtle",
1691
+ size: "sm",
1692
+ "aria-label": "Close dialog",
1693
+ onClick: onClose,
1694
+ className: "absolute right-6 top-5 z-10",
1695
+ children: /* @__PURE__ */ jsx29(LuX3, { size: 16 })
1696
+ }
1697
+ ),
1698
+ children
1699
+ ]
1700
+ }
1701
+ )
1702
+ }
1703
+ );
1704
+ }
1705
+ function ModalHeader({
1706
+ children,
1707
+ tone = "default",
1708
+ divider = true,
1709
+ className,
1710
+ ...rest
1711
+ }) {
1712
+ return /* @__PURE__ */ jsxs21(
1713
+ "div",
1714
+ {
1715
+ className: cn(
1716
+ // pr-14 reserves the floating close button's column (24px gutter + 24px
1717
+ // button + gap), which the old flex-between header used to hold open.
1718
+ "flex items-start gap-3 px-6 py-5 pr-14",
1719
+ divider && "border-b border-default",
1720
+ className
1721
+ ),
1722
+ ...rest,
1723
+ children: [
1724
+ tone !== "default" && /* @__PURE__ */ jsx29(EntityIconBadge, { size: "md", shape: "circle", tone: TONE_BADGE[tone], children: TONE_ICON[tone] }),
1725
+ /* @__PURE__ */ jsx29("div", { className: "min-w-0 flex-1", children })
1726
+ ]
1727
+ }
1728
+ );
1729
+ }
1730
+ function ModalTitle({ children, className, ...rest }) {
1731
+ return /* @__PURE__ */ jsx29("h2", { className: cn("text-heading-sm font-semibold text-default", className), ...rest, children });
1732
+ }
1733
+ function ModalDescription({ children, className, ...rest }) {
1734
+ return /* @__PURE__ */ jsx29("p", { className: cn("mt-0.5 text-body-xs text-default-secondary", className), ...rest, children });
1735
+ }
1736
+ function ModalBody({ children, className, ...rest }) {
1737
+ return /* @__PURE__ */ jsx29("div", { className: cn("px-6 py-5", className), ...rest, children });
1738
+ }
1739
+ function ModalFooter({
1740
+ children,
1741
+ align = "end",
1742
+ divider = true,
1743
+ className,
1744
+ ...rest
1745
+ }) {
1746
+ return /* @__PURE__ */ jsx29(
1747
+ "div",
1748
+ {
1749
+ className: cn(
1750
+ "flex items-center gap-2 px-6 py-4",
1751
+ FOOTER_ALIGN[align],
1752
+ divider && "border-t border-default",
1753
+ className
1754
+ ),
1755
+ ...rest,
1756
+ children
1757
+ }
1758
+ );
1759
+ }
1760
+
1761
+ // src/components/overlays/drawer.tsx
1762
+ import { useRef as useRef5 } from "react";
1763
+ import clsx29 from "clsx";
1764
+ import { LuX as LuX4 } from "react-icons/lu";
1765
+ import { jsx as jsx30, jsxs as jsxs22 } from "react/jsx-runtime";
1766
+ function Drawer(props) {
1767
+ if (!props.isOpen) return null;
1768
+ return /* @__PURE__ */ jsx30(DrawerShell, { ...props });
1769
+ }
1770
+ function DrawerShell({
1771
+ onClose,
1772
+ header,
1773
+ children,
1774
+ footer,
1775
+ footerAlign = "end",
1776
+ width = "w-[440px] max-w-[90vw]",
1777
+ label,
1778
+ className
1779
+ }) {
1780
+ const panelRef = useRef5(null);
1781
+ useOverlayDismiss(onClose, panelRef);
1782
+ return /* @__PURE__ */ jsx30(
1783
+ "div",
1784
+ {
1785
+ className: clsx29("fixed inset-0 z-50 flex justify-end", OVERLAY_SCRIM),
1786
+ onClick: (e) => {
1787
+ if (e.target === e.currentTarget) onClose();
1788
+ },
1789
+ children: /* @__PURE__ */ jsxs22(
1790
+ "aside",
1791
+ {
1792
+ ref: panelRef,
1793
+ role: "dialog",
1794
+ "aria-modal": "true",
1795
+ "aria-label": label,
1796
+ className: clsx29("relative flex h-full flex-col bg-default shadow-2xl", width, className),
1797
+ children: [
1798
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-start justify-between gap-3 border-b border-default p-6", children: [
1799
+ /* @__PURE__ */ jsx30("div", { className: "min-w-0", children: header }),
1800
+ /* @__PURE__ */ jsx30(IconButton, { variant: "subtle", size: "sm", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx30(LuX4, { size: 18 }) })
1801
+ ] }),
1802
+ /* @__PURE__ */ jsx30("div", { className: "flex-1 space-y-6 overflow-y-auto p-6", children }),
1803
+ footer && /* @__PURE__ */ jsx30(
1804
+ "div",
1805
+ {
1806
+ className: clsx29(
1807
+ "flex items-center gap-2 border-t border-default px-6 py-4",
1808
+ footerAlign === "between" ? "justify-between" : "justify-end"
1809
+ ),
1810
+ children: footer
1811
+ }
1812
+ )
1813
+ ]
1814
+ }
1815
+ )
1816
+ }
1817
+ );
1818
+ }
1819
+
1820
+ // src/components/overlays/confirm-dialog.tsx
1821
+ import { jsx as jsx31, jsxs as jsxs23 } from "react/jsx-runtime";
1822
+ function ConfirmDialog({
1823
+ isOpen,
1824
+ title,
1825
+ subtitle,
1826
+ tone = "default",
1827
+ size = "md",
1828
+ confirmLabel = "Confirm",
1829
+ cancelLabel = "Cancel",
1830
+ confirmVariant = "primary",
1831
+ isConfirming = false,
1832
+ confirmingLabel = "Working\u2026",
1833
+ children,
1834
+ className,
1835
+ onConfirm,
1836
+ onClose
1837
+ }) {
1838
+ return /* @__PURE__ */ jsxs23(Modal, { isOpen, onClose, label: title, size, className, children: [
1839
+ /* @__PURE__ */ jsxs23(ModalHeader, { tone, divider: Boolean(children), children: [
1840
+ /* @__PURE__ */ jsx31(ModalTitle, { children: title }),
1841
+ subtitle && /* @__PURE__ */ jsx31(ModalDescription, { children: subtitle })
1842
+ ] }),
1843
+ children && /* @__PURE__ */ jsx31(ModalBody, { children }),
1844
+ /* @__PURE__ */ jsxs23(ModalFooter, { children: [
1845
+ /* @__PURE__ */ jsx31(Button, { variant: "neutral", size: "md", onClick: onClose, children: cancelLabel }),
1846
+ /* @__PURE__ */ jsx31(Button, { variant: confirmVariant, size: "md", disabled: isConfirming, onClick: onConfirm, children: isConfirming ? confirmingLabel : confirmLabel })
1847
+ ] })
1848
+ ] });
1849
+ }
1850
+
1851
+ // src/components/overlays/note-confirm-modal.tsx
1852
+ import { useState as useState3 } from "react";
1853
+ import { jsx as jsx32, jsxs as jsxs24 } from "react/jsx-runtime";
1854
+ function NoteConfirmModal({ isOpen, ...rest }) {
1855
+ if (!isOpen) return null;
1856
+ return /* @__PURE__ */ jsx32(NoteConfirmModalShell, { ...rest });
1857
+ }
1858
+ function NoteConfirmModalShell({
1859
+ title,
1860
+ subtitle,
1861
+ tone = "default",
1862
+ size = "md",
1863
+ confirmLabel,
1864
+ cancelLabel = "Cancel",
1865
+ confirmVariant = "primary",
1866
+ requireNote = false,
1867
+ notePlaceholder = "Add a note\u2026",
1868
+ submittingLabel = "Saving\u2026",
1869
+ isSubmitting = false,
1870
+ className,
1871
+ onClose,
1872
+ onConfirm
1873
+ }) {
1874
+ const [note, setNote] = useState3("");
1875
+ const disabled = isSubmitting || requireNote && !note.trim();
1876
+ return /* @__PURE__ */ jsxs24(Modal, { isOpen: true, onClose, label: title, size, className, children: [
1877
+ /* @__PURE__ */ jsxs24(ModalHeader, { tone, children: [
1878
+ /* @__PURE__ */ jsx32(ModalTitle, { children: title }),
1879
+ subtitle && /* @__PURE__ */ jsx32(ModalDescription, { children: subtitle })
1880
+ ] }),
1881
+ /* @__PURE__ */ jsx32(ModalBody, { children: /* @__PURE__ */ jsx32(
1882
+ Textarea,
1883
+ {
1884
+ value: note,
1885
+ onChange: (e) => setNote(e.target.value),
1886
+ placeholder: notePlaceholder,
1887
+ rows: 4
1888
+ }
1889
+ ) }),
1890
+ /* @__PURE__ */ jsxs24(ModalFooter, { children: [
1891
+ /* @__PURE__ */ jsx32(Button, { variant: "neutral", size: "md", onClick: onClose, children: cancelLabel }),
1892
+ /* @__PURE__ */ jsx32(Button, { variant: confirmVariant, size: "md", disabled, onClick: () => onConfirm(note.trim()), children: isSubmitting ? submittingLabel : confirmLabel })
1893
+ ] })
1894
+ ] });
1895
+ }
1896
+
1897
+ // src/components/overlays/dropdown-menu.tsx
1898
+ import { useEffect as useEffect4, useRef as useRef6, useState as useState4 } from "react";
1899
+ import clsx30 from "clsx";
1900
+ import { LuEllipsis } from "react-icons/lu";
1901
+ import { jsx as jsx33, jsxs as jsxs25 } from "react/jsx-runtime";
1902
+ function DropdownMenu({
1903
+ items,
1904
+ trigger,
1905
+ label,
1906
+ align = "right",
1907
+ className
1908
+ }) {
1909
+ const [open, setOpen] = useState4(false);
1910
+ const rootRef = useRef6(null);
1911
+ useEffect4(() => {
1912
+ if (!open) return;
1913
+ function handleOutside(e) {
1914
+ const root = rootRef.current;
1915
+ if (root && !root.contains(e.target)) setOpen(false);
1916
+ }
1917
+ function handleKey(e) {
1918
+ if (e.key === "Escape") setOpen(false);
1919
+ }
1920
+ document.addEventListener("mousedown", handleOutside);
1921
+ document.addEventListener("keydown", handleKey);
1922
+ return () => {
1923
+ document.removeEventListener("mousedown", handleOutside);
1924
+ document.removeEventListener("keydown", handleKey);
1925
+ };
1926
+ }, [open]);
1927
+ const visible = items.filter((item) => item.label);
1928
+ return /* @__PURE__ */ jsxs25(
1929
+ "div",
1930
+ {
1931
+ ref: rootRef,
1932
+ className: clsx30("relative", className),
1933
+ onMouseDown: (e) => e.stopPropagation(),
1934
+ children: [
1935
+ /* @__PURE__ */ jsx33(
1936
+ "button",
1937
+ {
1938
+ type: "button",
1939
+ "aria-label": label,
1940
+ "aria-haspopup": "menu",
1941
+ "aria-expanded": open,
1942
+ onClick: (e) => {
1943
+ e.stopPropagation();
1944
+ setOpen((v) => !v);
1945
+ },
1946
+ className: clsx30(
1947
+ "rounded-md border border-default bg-default text-body-xs font-medium leading-none text-default transition-colors hover:bg-default-secondary",
1948
+ trigger ? "p-1.5" : "px-2.5 py-1.5"
1949
+ ),
1950
+ children: trigger ?? /* @__PURE__ */ jsx33(LuEllipsis, { className: "size-4" })
1951
+ }
1952
+ ),
1953
+ open && /* @__PURE__ */ jsx33(
1954
+ "div",
1955
+ {
1956
+ role: "menu",
1957
+ className: clsx30(
1958
+ "absolute top-full z-20 mt-1 min-w-[148px] rounded-lg border border-default bg-default py-1 shadow-lg",
1959
+ align === "right" ? "right-0" : "left-0"
1960
+ ),
1961
+ children: visible.map((item, i) => /* @__PURE__ */ jsxs25("div", { children: [
1962
+ item.separatorBefore && i > 0 && /* @__PURE__ */ jsx33("div", { className: "my-1 h-px bg-divider" }),
1963
+ /* @__PURE__ */ jsx33(
1964
+ "button",
1965
+ {
1966
+ type: "button",
1967
+ role: "menuitem",
1968
+ disabled: item.disabled,
1969
+ className: clsx30(
1970
+ "flex w-full items-center px-3 py-2 text-left text-body-sm transition-colors",
1971
+ item.disabled && "cursor-not-allowed opacity-50",
1972
+ item.tone === "danger" ? "text-danger hover:bg-danger-tertiary" : "text-default hover:bg-default-secondary"
1973
+ ),
1974
+ onClick: (e) => {
1975
+ e.stopPropagation();
1976
+ setOpen(false);
1977
+ item.onSelect();
1978
+ },
1979
+ children: item.label
1980
+ }
1981
+ )
1982
+ ] }, item.label))
1983
+ }
1984
+ )
1985
+ ]
1986
+ }
1987
+ );
1988
+ }
1989
+
1990
+ // src/components/cards/card.tsx
1991
+ import { jsx as jsx34 } from "react/jsx-runtime";
1992
+ var RADIUS = {
1993
+ lg: "rounded-lg",
1994
+ xl: "rounded-xl",
1995
+ "2xl": "rounded-2xl"
1996
+ };
1997
+ var TONE = {
1998
+ default: "border-default bg-default",
1999
+ brand: "border-brand-tertiary bg-brand-tertiary",
2000
+ positive: "border-positive-tertiary bg-positive-tertiary",
2001
+ warning: "border-warning-tertiary bg-warning-tertiary",
2002
+ // The one asymmetry: danger keeps the strong `border-danger` rather than the
2003
+ // tertiary border, because it is the only tone that has to read as an alarm from
2004
+ // across a dashboard. Byte-identical to the deleted AlertCard's danger surface.
2005
+ danger: "border-danger bg-danger-tertiary"
2006
+ };
2007
+ var BOX = {
2008
+ sm: "px-3 py-2",
2009
+ md: "px-4 py-3",
2010
+ lg: "px-5 py-4"
2011
+ };
2012
+ var BODY_BOX = {
2013
+ sm: "gap-3 p-3",
2014
+ md: "gap-4 p-4",
2015
+ lg: "gap-5 p-5"
2016
+ };
2017
+ var TITLE_SIZE = {
2018
+ sm: "text-body-xs",
2019
+ md: "text-body-sm",
2020
+ lg: "text-subheading-sm"
2021
+ };
2022
+ var FOOTER_ALIGN2 = {
2023
+ start: "justify-start",
2024
+ between: "justify-between",
2025
+ end: "justify-end"
2026
+ };
2027
+ function Card({ children, radius = "2xl", tone = "default", className, ...rest }) {
2028
+ return /* @__PURE__ */ jsx34(
2029
+ "div",
2030
+ {
2031
+ "data-slot": "card",
2032
+ className: cn("flex flex-col overflow-hidden border", RADIUS[radius], TONE[tone], className),
2033
+ ...rest,
2034
+ children
2035
+ }
2036
+ );
2037
+ }
2038
+ function CardHeader({
2039
+ children,
2040
+ size = "md",
2041
+ divider = true,
2042
+ className,
2043
+ ...rest
2044
+ }) {
2045
+ return /* @__PURE__ */ jsx34(
2046
+ "div",
2047
+ {
2048
+ "data-slot": "card-header",
2049
+ className: cn(
2050
+ "grid auto-rows-min items-center gap-x-3 gap-y-0.5",
2051
+ "has-[[data-slot=card-action]]:grid-cols-[1fr_auto]",
2052
+ BOX[size],
2053
+ divider && "border-b border-default",
2054
+ className
2055
+ ),
2056
+ ...rest,
2057
+ children
2058
+ }
2059
+ );
2060
+ }
2061
+ function CardTitle({ children, size = "md", as: Tag = "p", className, ...rest }) {
2062
+ return /* @__PURE__ */ jsx34(
2063
+ Tag,
2064
+ {
2065
+ "data-slot": "card-title",
2066
+ className: cn("min-w-0 font-semibold text-default", TITLE_SIZE[size], className),
2067
+ ...rest,
2068
+ children
2069
+ }
2070
+ );
2071
+ }
2072
+ function CardDescription({ children, className, ...rest }) {
2073
+ return /* @__PURE__ */ jsx34(
2074
+ "p",
2075
+ {
2076
+ "data-slot": "card-description",
2077
+ className: cn("min-w-0 text-body-tiny text-default-secondary", className),
2078
+ ...rest,
2079
+ children
2080
+ }
2081
+ );
2082
+ }
2083
+ function CardAction({ children, className, ...rest }) {
2084
+ return /* @__PURE__ */ jsx34(
2085
+ "div",
2086
+ {
2087
+ "data-slot": "card-action",
2088
+ className: cn("col-start-2 row-span-2 row-start-1 shrink-0 self-center justify-self-end", className),
2089
+ ...rest,
2090
+ children
2091
+ }
2092
+ );
2093
+ }
2094
+ function CardBody({ children, size = "md", className, ...rest }) {
2095
+ return /* @__PURE__ */ jsx34("div", { "data-slot": "card-body", className: cn("flex flex-col", BODY_BOX[size], className), ...rest, children });
2096
+ }
2097
+ function CardFooter({
2098
+ children,
2099
+ size = "md",
2100
+ divider = true,
2101
+ align = "end",
2102
+ className,
2103
+ ...rest
2104
+ }) {
2105
+ return /* @__PURE__ */ jsx34(
2106
+ "div",
2107
+ {
2108
+ "data-slot": "card-footer",
2109
+ className: cn(
2110
+ "flex items-center gap-2",
2111
+ BOX[size],
2112
+ FOOTER_ALIGN2[align],
2113
+ divider && "border-t border-default",
2114
+ className
2115
+ ),
2116
+ ...rest,
2117
+ children
2118
+ }
2119
+ );
2120
+ }
2121
+
2122
+ // src/components/chrome/page-heading.tsx
2123
+ import clsx31 from "clsx";
2124
+ import { jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
2125
+ var TITLE = {
2126
+ page: "text-2xl font-semibold text-default",
2127
+ toolbar: "text-heading-sm font-semibold leading-snug text-default",
2128
+ section: "text-lg font-semibold text-default"
2129
+ };
2130
+ var SUBTITLE = {
2131
+ page: "mt-1 text-body-sm text-default-secondary",
2132
+ toolbar: "text-body-xs text-default-secondary",
2133
+ section: "mt-1 text-body-sm text-default-secondary"
2134
+ };
2135
+ function PageHeading({
2136
+ title,
2137
+ subtitle,
2138
+ size = "page",
2139
+ as,
2140
+ actions,
2141
+ truncateTitle,
2142
+ className
2143
+ }) {
2144
+ const Tag = as ?? (size === "section" ? "h2" : "h1");
2145
+ const heading = /* @__PURE__ */ jsxs26("div", { className: "flex min-w-0 flex-col gap-0.5", children: [
2146
+ /* @__PURE__ */ jsx35(Tag, { className: clsx31(TITLE[size], truncateTitle && "truncate"), children: title }),
2147
+ subtitle && /* @__PURE__ */ jsx35("p", { className: SUBTITLE[size], children: subtitle })
2148
+ ] });
2149
+ if (!actions) return className ? /* @__PURE__ */ jsx35("div", { className, children: heading }) : heading;
2150
+ return /* @__PURE__ */ jsxs26("div", { className: clsx31("flex items-start justify-between gap-4", className), children: [
2151
+ heading,
2152
+ /* @__PURE__ */ jsx35("div", { className: "flex shrink-0 items-center gap-2", children: actions })
2153
+ ] });
2154
+ }
2155
+
2156
+ // src/components/chrome/page-toolbar.tsx
2157
+ import clsx32 from "clsx";
2158
+ import { jsx as jsx36 } from "react/jsx-runtime";
2159
+ var SIZE3 = {
2160
+ sm: "min-h-[56px] px-4 py-2.5 md:px-7",
2161
+ md: "min-h-[72px] px-4 py-4 md:px-7"
2162
+ };
2163
+ function PageToolbar({ children, wrap, size = "md", className }) {
2164
+ return /* @__PURE__ */ jsx36(
2165
+ "div",
2166
+ {
2167
+ className: clsx32(
2168
+ "flex shrink-0 items-center justify-between gap-4 border-b border-default bg-default",
2169
+ SIZE3[size],
2170
+ wrap && "flex-wrap gap-2",
2171
+ className
2172
+ ),
2173
+ children
2174
+ }
2175
+ );
2176
+ }
2177
+
2178
+ // src/components/chrome/filter-bar.tsx
2179
+ import clsx33 from "clsx";
2180
+ import { jsx as jsx37, jsxs as jsxs27 } from "react/jsx-runtime";
2181
+ var GAP = {
2182
+ sm: "gap-2",
2183
+ md: "gap-3"
2184
+ };
2185
+ function FilterBar({ children, trailing, size = "md", className }) {
2186
+ return /* @__PURE__ */ jsxs27("div", { className: clsx33("flex flex-wrap items-center", GAP[size], className), children: [
2187
+ children,
2188
+ trailing && /* @__PURE__ */ jsx37("div", { className: "ml-auto flex items-center gap-2", children: trailing })
2189
+ ] });
2190
+ }
2191
+
2192
+ // src/components/chrome/tabs.tsx
2193
+ import clsx34 from "clsx";
2194
+ import { jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
2195
+ var SIZE4 = {
2196
+ underline: {
2197
+ sm: { strip: "gap-4", tab: "px-0.5 py-1.5 text-body-xs" },
2198
+ md: { strip: "gap-6", tab: "px-0.5 py-2.5 text-body-sm" }
2199
+ },
2200
+ pill: {
2201
+ sm: { strip: "gap-1", tab: "rounded-md px-2.5 py-1.5 text-body-tiny" },
2202
+ md: { strip: "gap-1.5", tab: "rounded-lg px-3.5 py-2 text-body-xs" }
2203
+ }
2204
+ };
2205
+ function Tabs({
2206
+ items,
2207
+ value,
2208
+ onChange,
2209
+ variant = "underline",
2210
+ size = "md",
2211
+ className
2212
+ }) {
2213
+ const isPill = variant === "pill";
2214
+ const s = SIZE4[variant][size];
2215
+ return /* @__PURE__ */ jsx38(
2216
+ "div",
2217
+ {
2218
+ role: "tablist",
2219
+ className: clsx34(
2220
+ "flex shrink-0 overflow-x-auto",
2221
+ s.strip,
2222
+ !isPill && "border-b border-default",
2223
+ className
2224
+ ),
2225
+ children: items.map((tab) => {
2226
+ const active = tab.key === value;
2227
+ return /* @__PURE__ */ jsxs28(
2228
+ "button",
2229
+ {
2230
+ type: "button",
2231
+ role: "tab",
2232
+ "aria-selected": active,
2233
+ onClick: () => onChange(tab.key),
2234
+ className: clsx34(
2235
+ "flex shrink-0 items-center gap-1.5 whitespace-nowrap transition-colors",
2236
+ s.tab,
2237
+ isPill ? clsx34(
2238
+ "font-medium",
2239
+ active ? "bg-brand text-brand-on-brand" : "text-default-secondary hover:bg-default-secondary"
2240
+ ) : clsx34(
2241
+ "leading-snug",
2242
+ active ? "border-b-2 border-brand-emphasis font-semibold text-brand-emphasis" : "font-normal text-default-secondary hover:text-default"
2243
+ )
2244
+ ),
2245
+ children: [
2246
+ tab.label,
2247
+ tab.count !== void 0 && /* @__PURE__ */ jsx38(
2248
+ "span",
2249
+ {
2250
+ className: clsx34(
2251
+ "rounded-md px-1.5 py-px text-body-tiny font-medium leading-snug",
2252
+ active && isPill ? "bg-brand-hover text-brand-on-brand" : "bg-default-secondary text-default-secondary"
2253
+ ),
2254
+ children: tab.count
2255
+ }
2256
+ )
2257
+ ]
2258
+ },
2259
+ tab.key
2260
+ );
2261
+ })
2262
+ }
2263
+ );
2264
+ }
2265
+
2266
+ // src/components/chrome/nav-item.tsx
2267
+ import clsx35 from "clsx";
2268
+ import { jsx as jsx39, jsxs as jsxs29 } from "react/jsx-runtime";
2269
+ var SIZE5 = {
2270
+ sm: { box: "h-9 gap-2 rounded-lg px-2.5 py-1.5", label: "text-body-xs" },
2271
+ md: { box: "h-11 gap-3 rounded-xl px-3.5 py-2.5", label: "text-body-sm" }
2272
+ };
2273
+ function NavItem({
2274
+ icon,
2275
+ label,
2276
+ isActive = false,
2277
+ indicator = false,
2278
+ collapsed = false,
2279
+ size = "md",
2280
+ className
2281
+ }) {
2282
+ const s = SIZE5[size];
2283
+ return /* @__PURE__ */ jsxs29(
2284
+ "span",
2285
+ {
2286
+ className: clsx35(
2287
+ "relative flex w-full items-center transition-colors",
2288
+ s.box,
2289
+ collapsed && "justify-center",
2290
+ isActive ? "bg-brand text-brand-on-brand" : [
2291
+ "border border-default bg-default text-default-secondary",
2292
+ "hover:bg-brand-tertiary-hover hover:border-brand-tertiary hover:text-brand"
2293
+ ],
2294
+ className
2295
+ ),
2296
+ children: [
2297
+ icon !== void 0 && /* @__PURE__ */ jsx39("span", { className: "shrink-0 [&_svg]:size-4", children: icon }),
2298
+ !collapsed && /* @__PURE__ */ jsx39("span", { className: clsx35("min-w-0 flex-1 truncate font-regular leading-snug", s.label), children: label }),
2299
+ indicator && /* @__PURE__ */ jsx39("span", { className: "absolute -right-px -top-px size-2 rounded-full bg-danger" })
2300
+ ]
2301
+ }
2302
+ );
2303
+ }
2304
+
2305
+ // src/components/chrome/eyebrow-label.tsx
2306
+ import clsx36 from "clsx";
2307
+ import { jsx as jsx40 } from "react/jsx-runtime";
2308
+ function EyebrowLabel({ children, variant = "uppercase", className }) {
2309
+ return /* @__PURE__ */ jsx40(
2310
+ "p",
2311
+ {
2312
+ className: clsx36(
2313
+ "text-body-tiny font-semibold tracking-wide text-default-secondary",
2314
+ variant === "uppercase" && "uppercase",
2315
+ className
2316
+ ),
2317
+ children
2318
+ }
2319
+ );
2320
+ }
2321
+
2322
+ // src/components/widgets/widget-header.tsx
2323
+ import clsx38 from "clsx";
2324
+
2325
+ // src/components/widgets/widget-title.tsx
2326
+ import clsx37 from "clsx";
2327
+ import { jsx as jsx41 } from "react/jsx-runtime";
2328
+ var sizeStyles5 = {
2329
+ sm: "text-subheading-sm font-semibold leading-none",
2330
+ md: "text-[18px] font-bold leading-normal",
2331
+ lg: "text-subheading font-semibold leading-[1.2]"
2332
+ };
2333
+ function WidgetTitle({ children, size = "sm", className }) {
2334
+ return /* @__PURE__ */ jsx41("h3", { className: clsx37(sizeStyles5[size], "text-default", className), children });
2335
+ }
2336
+
2337
+ // src/components/widgets/widget-header.tsx
2338
+ import { jsx as jsx42, jsxs as jsxs30 } from "react/jsx-runtime";
2339
+ var eyebrowStyles = {
2340
+ uppercase: "text-body-tiny font-medium uppercase tracking-[0.66px] text-default-secondary",
2341
+ plain: "text-body-xs leading-[1.4] text-default-secondary"
2342
+ };
2343
+ function WidgetHeader({
2344
+ eyebrow,
2345
+ eyebrowVariant = "uppercase",
2346
+ title,
2347
+ titleSize,
2348
+ subtitle,
2349
+ badge,
2350
+ action,
2351
+ className
2352
+ }) {
2353
+ return /* @__PURE__ */ jsxs30("div", { className: clsx38("flex items-start justify-between gap-2", className), children: [
2354
+ /* @__PURE__ */ jsxs30("div", { className: "min-w-0 flex-1", children: [
2355
+ eyebrow && /* @__PURE__ */ jsx42("p", { className: eyebrowStyles[eyebrowVariant], children: eyebrow }),
2356
+ /* @__PURE__ */ jsx42(WidgetTitle, { size: titleSize, children: title }),
2357
+ subtitle && /* @__PURE__ */ jsx42("p", { className: "mt-1 text-body-xs text-default-secondary leading-snug", children: subtitle })
2358
+ ] }),
2359
+ /* @__PURE__ */ jsxs30("div", { className: "flex shrink-0 items-center gap-2", children: [
2360
+ badge,
2361
+ action
2362
+ ] })
2363
+ ] });
2364
+ }
2365
+
2366
+ // src/components/widgets/widget-footer.tsx
2367
+ import clsx39 from "clsx";
2368
+ import { jsx as jsx43, jsxs as jsxs31 } from "react/jsx-runtime";
2369
+ function WidgetFooter({ caption, subcaption, action, className }) {
2370
+ return /* @__PURE__ */ jsxs31("div", { className: clsx39("flex items-center gap-3", className), children: [
2371
+ caption && /* @__PURE__ */ jsxs31("div", { className: "flex items-stretch gap-3 flex-1 min-w-0", children: [
2372
+ /* @__PURE__ */ jsx43("div", { className: "w-0.5 shrink-0 self-stretch rounded-full bg-brand" }),
2373
+ /* @__PURE__ */ jsxs31("div", { className: "min-w-0", children: [
2374
+ /* @__PURE__ */ jsx43("p", { className: "text-body-sm font-medium text-default leading-snug", children: caption }),
2375
+ subcaption && /* @__PURE__ */ jsx43("p", { className: "mt-0.5 text-body-xs text-default-secondary", children: subcaption })
2376
+ ] })
2377
+ ] }),
2378
+ action && /* @__PURE__ */ jsx43("div", { className: "ml-auto shrink-0", children: action })
2379
+ ] });
2380
+ }
2381
+
2382
+ // src/components/stats/stat-tile.tsx
2383
+ import clsx40 from "clsx";
2384
+ import { jsx as jsx44, jsxs as jsxs32 } from "react/jsx-runtime";
2385
+ var DOT_TONE = {
2386
+ neutral: "bg-status-dot-neutral",
2387
+ info: "bg-status-dot-info",
2388
+ warning: "bg-status-dot-warning",
2389
+ caution: "bg-status-dot-caution",
2390
+ accent: "bg-status-dot-accent",
2391
+ positive: "bg-status-dot-positive",
2392
+ danger: "bg-status-dot-danger"
2393
+ };
2394
+ function StatTile({ label, value, tone, dotColor, className }) {
2395
+ const showDot = Boolean(tone || dotColor);
2396
+ return /* @__PURE__ */ jsxs32(
2397
+ "div",
2398
+ {
2399
+ className: clsx40(
2400
+ "flex flex-col gap-2 rounded-xl border border-default bg-default p-4",
2401
+ className
2402
+ ),
2403
+ children: [
2404
+ /* @__PURE__ */ jsxs32("div", { className: "flex items-center gap-1.5", children: [
2405
+ showDot && /* @__PURE__ */ jsx44(
2406
+ "span",
2407
+ {
2408
+ className: clsx40("size-2 shrink-0 rounded-full", tone && DOT_TONE[tone]),
2409
+ style: tone ? void 0 : { backgroundColor: dotColor }
2410
+ }
2411
+ ),
2412
+ /* @__PURE__ */ jsx44("span", { className: "text-body-xs font-medium text-default-secondary whitespace-nowrap", children: label })
2413
+ ] }),
2414
+ /* @__PURE__ */ jsx44("span", { className: "text-heading font-semibold text-default leading-none", children: value })
2415
+ ]
2416
+ }
2417
+ );
2418
+ }
2419
+
2420
+ // src/components/stats/stat-number.tsx
2421
+ import clsx41 from "clsx";
2422
+ import { jsx as jsx45, jsxs as jsxs33 } from "react/jsx-runtime";
2423
+ var sizeStyles6 = {
2424
+ sm: "text-subtitle",
2425
+ md: "text-subtitle-lg",
2426
+ lg: "text-title"
2427
+ };
2428
+ var weightStyles = {
2429
+ medium: "font-medium",
2430
+ bold: "font-bold"
2431
+ };
2432
+ function StatNumber({ value, unit, size = "md", weight = "bold", color, className }) {
2433
+ return /* @__PURE__ */ jsxs33(
2434
+ "p",
2435
+ {
2436
+ className: clsx41(sizeStyles6[size], weightStyles[weight], "leading-none", !color && "text-default", className),
2437
+ style: color ? { color } : void 0,
2438
+ children: [
2439
+ value,
2440
+ unit && /* @__PURE__ */ jsx45("span", { className: "ml-1 text-subheading font-medium text-default-secondary", children: unit })
2441
+ ]
2442
+ }
2443
+ );
2444
+ }
2445
+
2446
+ // src/components/stats/score-value.tsx
2447
+ import clsx42 from "clsx";
2448
+ import { jsx as jsx46, jsxs as jsxs34 } from "react/jsx-runtime";
2449
+ var DEFAULT_SCORE_THRESHOLDS = { danger: 80, warning: 65, neutral: 50 };
2450
+ function getScoreTone(score, {
2451
+ direction = "higher-is-worse",
2452
+ thresholds = DEFAULT_SCORE_THRESHOLDS
2453
+ } = {}) {
2454
+ const v = direction === "higher-is-better" ? 100 - score : score;
2455
+ if (v >= thresholds.danger) return "danger";
2456
+ if (v >= thresholds.warning) return "warning";
2457
+ if (v >= thresholds.neutral) return "neutral";
2458
+ return "positive";
2459
+ }
2460
+ var SIZE6 = {
2461
+ sm: "text-body-xs",
2462
+ md: "text-body-sm",
2463
+ lg: "text-subheading-sm",
2464
+ xl: "text-subheading",
2465
+ "2xl": "text-subtitle"
2466
+ };
2467
+ var WEIGHT = {
2468
+ normal: "font-normal",
2469
+ semibold: "font-semibold",
2470
+ bold: "font-bold"
2471
+ };
2472
+ var TONE2 = {
2473
+ brand: "text-brand",
2474
+ positive: "text-positive",
2475
+ warning: "text-warning",
2476
+ danger: "text-danger",
2477
+ neutral: "text-default-secondary",
2478
+ default: "text-default"
2479
+ };
2480
+ function ScoreValue({
2481
+ value,
2482
+ label,
2483
+ size = "md",
2484
+ weight = "bold",
2485
+ tone = "auto",
2486
+ direction = "higher-is-worse",
2487
+ thresholds = DEFAULT_SCORE_THRESHOLDS,
2488
+ className
2489
+ }) {
2490
+ const numeric = typeof value === "number" ? value : Number(value);
2491
+ const resolved = tone === "auto" ? Number.isFinite(numeric) ? getScoreTone(numeric, { direction, thresholds }) : "default" : tone;
2492
+ return /* @__PURE__ */ jsxs34("span", { className: clsx42("inline-flex items-baseline gap-1", className), children: [
2493
+ /* @__PURE__ */ jsx46("span", { className: clsx42(SIZE6[size], WEIGHT[weight], TONE2[resolved]), children: value }),
2494
+ label && /* @__PURE__ */ jsx46("span", { className: "text-body-xs text-default-secondary whitespace-nowrap", children: label })
2495
+ ] });
2496
+ }
2497
+
2498
+ // src/components/stats/tile-grid.tsx
2499
+ import clsx43 from "clsx";
2500
+ import { jsx as jsx47 } from "react/jsx-runtime";
2501
+ var COLUMNS = {
2502
+ sm: {
2503
+ 2: "grid-cols-2",
2504
+ 3: "grid-cols-2 sm:grid-cols-3",
2505
+ 4: "grid-cols-2 sm:grid-cols-4",
2506
+ 5: "grid-cols-2 sm:grid-cols-5",
2507
+ 6: "grid-cols-2 sm:grid-cols-6"
2508
+ },
2509
+ md: {
2510
+ 2: "grid-cols-2",
2511
+ 3: "grid-cols-2 md:grid-cols-3",
2512
+ 4: "grid-cols-2 md:grid-cols-4",
2513
+ 5: "grid-cols-2 md:grid-cols-5",
2514
+ 6: "grid-cols-2 sm:grid-cols-3 md:grid-cols-6"
2515
+ },
2516
+ lg: {
2517
+ 2: "grid-cols-2",
2518
+ 3: "grid-cols-2 lg:grid-cols-3",
2519
+ 4: "grid-cols-2 lg:grid-cols-4",
2520
+ 5: "grid-cols-2 lg:grid-cols-5",
2521
+ 6: "grid-cols-2 sm:grid-cols-3 lg:grid-cols-6"
2522
+ }
2523
+ };
2524
+ function TileGrid({
2525
+ children,
2526
+ columns = 4,
2527
+ at = "lg",
2528
+ className
2529
+ }) {
2530
+ return /* @__PURE__ */ jsx47("div", { className: clsx43("grid gap-3", COLUMNS[at][columns], className), children });
2531
+ }
2532
+
2533
+ // src/components/charts/chart-tone.ts
2534
+ var CHART_TONE = {
2535
+ brand: "var(--color-background-brand-default)",
2536
+ info: "var(--status-info-dot)",
2537
+ positive: "var(--color-background-positive-default)",
2538
+ warning: "var(--color-background-warning-default)",
2539
+ danger: "var(--color-background-danger-default)",
2540
+ neutral: "var(--color-background-neutral-default)"
2541
+ };
2542
+ var CHART_TRACK = "var(--color-background-default-tertiary)";
2543
+ var CHART_SEQUENCE = ["brand", "info", "positive", "warning", "danger", "neutral"];
2544
+ function resolveChartColor(color, tone, index = 0) {
2545
+ if (color) return color;
2546
+ if (tone) return CHART_TONE[tone];
2547
+ return CHART_TONE[CHART_SEQUENCE[index % CHART_SEQUENCE.length]];
2548
+ }
2549
+
2550
+ // src/components/charts/bar-chart.tsx
2551
+ import clsx44 from "clsx";
2552
+ import { jsx as jsx48, jsxs as jsxs35 } from "react/jsx-runtime";
2553
+ var SIZE7 = {
2554
+ sm: { band: 14, gap: 6, label: "text-body-tiny" },
2555
+ md: { band: 20, gap: 8, label: "text-body-xs" },
2556
+ lg: { band: 28, gap: 10, label: "text-body-xs" }
2557
+ };
2558
+ function BarChart({
2559
+ categories,
2560
+ series,
2561
+ orientation = "horizontal",
2562
+ stacked = false,
2563
+ size = "md",
2564
+ length = 240,
2565
+ showLabels = true,
2566
+ showValues = false,
2567
+ radius = 3,
2568
+ label,
2569
+ className
2570
+ }) {
2571
+ const { band, gap, label: labelClass2 } = SIZE7[size];
2572
+ if (categories.length === 0 || series.length === 0) return null;
2573
+ const perCategory = stacked ? band : band * series.length + gap * (series.length - 1);
2574
+ const categoryTotals = categories.map(
2575
+ (_, ci) => stacked ? series.reduce((sum, s) => sum + Math.max(0, s.values[ci] ?? 0), 0) : Math.max(...series.map((s) => Math.max(0, s.values[ci] ?? 0)))
2576
+ );
2577
+ const max = Math.max(...categoryTotals, 1);
2578
+ const horizontal = orientation === "horizontal";
2579
+ return /* @__PURE__ */ jsx48(
2580
+ "div",
2581
+ {
2582
+ className: clsx44("flex w-full min-w-0", horizontal ? "flex-col gap-2" : "flex-row items-end gap-3", className),
2583
+ role: label ? "img" : void 0,
2584
+ "aria-label": label,
2585
+ children: categories.map((category, ci) => {
2586
+ const bars = series.map((s, si) => ({
2587
+ key: s.label,
2588
+ value: Math.max(0, s.values[ci] ?? 0),
2589
+ color: resolveChartColor(s.color, s.tone, si)
2590
+ }));
2591
+ return /* @__PURE__ */ jsxs35(
2592
+ "div",
2593
+ {
2594
+ className: clsx44("flex min-w-0", horizontal ? "flex-col gap-1" : "h-full flex-col justify-end gap-1.5"),
2595
+ style: horizontal ? void 0 : { width: perCategory },
2596
+ children: [
2597
+ showLabels && horizontal && /* @__PURE__ */ jsx48("span", { className: clsx44("truncate text-default-secondary", labelClass2), children: category }),
2598
+ /* @__PURE__ */ jsxs35(
2599
+ "div",
2600
+ {
2601
+ className: clsx44("flex", horizontal ? "items-center gap-2" : "w-full flex-1 items-end justify-center"),
2602
+ style: horizontal ? void 0 : { height: length },
2603
+ children: [
2604
+ /* @__PURE__ */ jsx48(
2605
+ "div",
2606
+ {
2607
+ className: clsx44("flex min-w-0", stacked ? "gap-0" : ""),
2608
+ style: horizontal ? { width: length, flexDirection: stacked ? "row" : "column", gap: stacked ? 0 : gap } : {
2609
+ height: "100%",
2610
+ width: perCategory,
2611
+ flexDirection: stacked ? "column-reverse" : "row",
2612
+ alignItems: "flex-end",
2613
+ gap: stacked ? 0 : gap
2614
+ },
2615
+ children: bars.map((bar) => {
2616
+ const extent = `${bar.value / max * 100}%`;
2617
+ return /* @__PURE__ */ jsx48(
2618
+ "div",
2619
+ {
2620
+ title: `${category} \xB7 ${bar.key}: ${bar.value}`,
2621
+ className: "transition-all",
2622
+ style: {
2623
+ backgroundColor: bar.color,
2624
+ borderRadius: radius,
2625
+ ...horizontal ? { width: extent, height: stacked ? band : band } : { height: extent, width: stacked ? perCategory : band }
2626
+ }
2627
+ },
2628
+ bar.key
2629
+ );
2630
+ })
2631
+ }
2632
+ ),
2633
+ showValues && horizontal && /* @__PURE__ */ jsx48("span", { className: clsx44("shrink-0 tabular-nums text-default-secondary", labelClass2), children: categoryTotals[ci] })
2634
+ ]
2635
+ }
2636
+ ),
2637
+ showLabels && !horizontal && /* @__PURE__ */ jsx48("span", { className: clsx44("truncate text-center text-default-secondary", labelClass2), children: category })
2638
+ ]
2639
+ },
2640
+ category
2641
+ );
2642
+ })
2643
+ }
2644
+ );
2645
+ }
2646
+
2647
+ // src/components/charts/donut-chart.tsx
2648
+ import clsx45 from "clsx";
2649
+ import { jsx as jsx49, jsxs as jsxs36 } from "react/jsx-runtime";
2650
+ var SIZE8 = {
2651
+ sm: { box: 88, thickness: 10 },
2652
+ md: { box: 128, thickness: 14 },
2653
+ lg: { box: 180, thickness: 20 }
2654
+ };
2655
+ function DonutChart({
2656
+ segments,
2657
+ size = "md",
2658
+ thickness,
2659
+ centerValue,
2660
+ centerLabel,
2661
+ gap = 2,
2662
+ label,
2663
+ className
2664
+ }) {
2665
+ const { box, thickness: presetThickness } = SIZE8[size];
2666
+ const ring = thickness ?? presetThickness;
2667
+ const radius = (box - ring) / 2;
2668
+ const circumference = 2 * Math.PI * radius;
2669
+ const total = segments.reduce((sum, s) => sum + Math.max(0, s.value), 0);
2670
+ const visible = segments.filter((s) => s.value > 0);
2671
+ const gapLength = visible.length > 1 ? gap / 360 * circumference : 0;
2672
+ let offset = 0;
2673
+ return /* @__PURE__ */ jsxs36("div", { className: clsx45("relative inline-flex shrink-0 items-center justify-center", className), children: [
2674
+ /* @__PURE__ */ jsxs36(
2675
+ "svg",
2676
+ {
2677
+ width: box,
2678
+ height: box,
2679
+ viewBox: `0 0 ${box} ${box}`,
2680
+ role: label ? "img" : void 0,
2681
+ "aria-label": label,
2682
+ "aria-hidden": label ? void 0 : true,
2683
+ className: "block -rotate-90",
2684
+ children: [
2685
+ /* @__PURE__ */ jsx49("circle", { cx: box / 2, cy: box / 2, r: radius, fill: "none", stroke: CHART_TRACK, strokeWidth: ring }),
2686
+ total > 0 && segments.map((segment, i) => {
2687
+ const fraction = Math.max(0, segment.value) / total;
2688
+ const length = Math.max(0, fraction * circumference - gapLength);
2689
+ const dash = `${length} ${circumference - length}`;
2690
+ const thisOffset = offset;
2691
+ offset += fraction * circumference;
2692
+ if (segment.value <= 0) return null;
2693
+ return /* @__PURE__ */ jsx49(
2694
+ "circle",
2695
+ {
2696
+ cx: box / 2,
2697
+ cy: box / 2,
2698
+ r: radius,
2699
+ fill: "none",
2700
+ stroke: resolveChartColor(segment.color, segment.tone, i),
2701
+ strokeWidth: ring,
2702
+ strokeDasharray: dash,
2703
+ strokeDashoffset: -thisOffset,
2704
+ strokeLinecap: "butt"
2705
+ },
2706
+ segment.label
2707
+ );
2708
+ })
2709
+ ]
2710
+ }
2711
+ ),
2712
+ (centerValue != null || centerLabel != null) && /* @__PURE__ */ jsxs36("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-center", children: [
2713
+ centerValue != null && /* @__PURE__ */ jsx49("span", { className: "text-subheading-sm font-bold leading-none text-default", children: centerValue }),
2714
+ centerLabel != null && /* @__PURE__ */ jsx49("span", { className: "mt-0.5 text-body-tiny text-default-secondary", children: centerLabel })
2715
+ ] })
2716
+ ] });
2717
+ }
2718
+
2719
+ // src/components/charts/radial-gauge.tsx
2720
+ import clsx46 from "clsx";
2721
+ import { jsx as jsx50, jsxs as jsxs37 } from "react/jsx-runtime";
2722
+ var SIZE9 = {
2723
+ sm: { box: 72, thickness: 8, value: "text-body-sm" },
2724
+ md: { box: 104, thickness: 11, value: "text-subheading-sm" },
2725
+ lg: { box: 148, thickness: 15, value: "text-subheading" }
2726
+ };
2727
+ function RadialGauge({
2728
+ value,
2729
+ max = 100,
2730
+ size = "md",
2731
+ tone = "brand",
2732
+ color,
2733
+ thickness,
2734
+ sweep = 270,
2735
+ children,
2736
+ centerLabel,
2737
+ label,
2738
+ className
2739
+ }) {
2740
+ const preset = SIZE9[size];
2741
+ const box = preset.box;
2742
+ const ring = thickness ?? preset.thickness;
2743
+ const radius = (box - ring) / 2;
2744
+ const circumference = 2 * Math.PI * radius;
2745
+ const clampedSweep = Math.min(360, Math.max(1, sweep));
2746
+ const arc = clampedSweep / 360 * circumference;
2747
+ const fraction = max > 0 ? Math.min(1, Math.max(0, value / max)) : 0;
2748
+ const stroke = resolveChartColor(color, tone);
2749
+ const rotation = -90 + (360 - clampedSweep) / 2;
2750
+ return /* @__PURE__ */ jsxs37("div", { className: clsx46("relative inline-flex shrink-0 items-center justify-center", className), children: [
2751
+ /* @__PURE__ */ jsxs37(
2752
+ "svg",
2753
+ {
2754
+ width: box,
2755
+ height: box,
2756
+ viewBox: `0 0 ${box} ${box}`,
2757
+ role: label ? "img" : void 0,
2758
+ "aria-label": label,
2759
+ "aria-hidden": label ? void 0 : true,
2760
+ className: "block",
2761
+ style: { transform: `rotate(${rotation}deg)` },
2762
+ children: [
2763
+ /* @__PURE__ */ jsx50(
2764
+ "circle",
2765
+ {
2766
+ cx: box / 2,
2767
+ cy: box / 2,
2768
+ r: radius,
2769
+ fill: "none",
2770
+ stroke: CHART_TRACK,
2771
+ strokeWidth: ring,
2772
+ strokeDasharray: `${arc} ${circumference - arc}`,
2773
+ strokeLinecap: "round"
2774
+ }
2775
+ ),
2776
+ /* @__PURE__ */ jsx50(
2777
+ "circle",
2778
+ {
2779
+ cx: box / 2,
2780
+ cy: box / 2,
2781
+ r: radius,
2782
+ fill: "none",
2783
+ stroke,
2784
+ strokeWidth: ring,
2785
+ strokeDasharray: `${arc * fraction} ${circumference - arc * fraction}`,
2786
+ strokeLinecap: "round",
2787
+ className: "transition-all"
2788
+ }
2789
+ )
2790
+ ]
2791
+ }
2792
+ ),
2793
+ /* @__PURE__ */ jsxs37("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-center", children: [
2794
+ children === void 0 ? /* @__PURE__ */ jsx50("span", { className: clsx46("font-bold leading-none text-default", preset.value), children: value }) : children,
2795
+ centerLabel != null && /* @__PURE__ */ jsx50("span", { className: "mt-0.5 text-body-tiny text-default-secondary", children: centerLabel })
2796
+ ] })
2797
+ ] });
2798
+ }
2799
+
2800
+ // src/components/charts/sparkline.tsx
2801
+ import { useId } from "react";
2802
+ import clsx47 from "clsx";
2803
+ import { Fragment as Fragment3, jsx as jsx51, jsxs as jsxs38 } from "react/jsx-runtime";
2804
+ var SIZE10 = {
2805
+ sm: { width: 80, height: 24 },
2806
+ md: { width: 120, height: 36 },
2807
+ lg: { width: 200, height: 56 }
2808
+ };
2809
+ function Sparkline({
2810
+ data,
2811
+ variant = "line",
2812
+ tone = "brand",
2813
+ color,
2814
+ size = "md",
2815
+ width,
2816
+ height,
2817
+ strokeWidth = 1.5,
2818
+ showEndDot = false,
2819
+ label,
2820
+ className
2821
+ }) {
2822
+ const gradientId = useId();
2823
+ if (data.length < 2) return null;
2824
+ const w = width ?? SIZE10[size].width;
2825
+ const h = height ?? SIZE10[size].height;
2826
+ const stroke = resolveChartColor(color, tone);
2827
+ const min = Math.min(...data);
2828
+ const max = Math.max(...data);
2829
+ const range = max - min || 1;
2830
+ const pad = strokeWidth;
2831
+ const innerH = h - pad * 2;
2832
+ const innerW = w - pad * 2;
2833
+ const coords = data.map((v, i) => ({
2834
+ x: pad + i / (data.length - 1) * innerW,
2835
+ y: pad + innerH - (v - min) / range * innerH
2836
+ }));
2837
+ const points = coords.map((p) => `${p.x.toFixed(2)},${p.y.toFixed(2)}`).join(" ");
2838
+ const areaPath = `M ${points.split(" ").join(" L ")} L ${coords[coords.length - 1].x.toFixed(2)},${h} L ${coords[0].x.toFixed(2)},${h} Z`;
2839
+ const last = coords[coords.length - 1];
2840
+ return /* @__PURE__ */ jsxs38(
2841
+ "svg",
2842
+ {
2843
+ width: w,
2844
+ height: h,
2845
+ viewBox: `0 0 ${w} ${h}`,
2846
+ fill: "none",
2847
+ role: label ? "img" : void 0,
2848
+ "aria-label": label,
2849
+ "aria-hidden": label ? void 0 : true,
2850
+ className: clsx47("block shrink-0", className),
2851
+ children: [
2852
+ variant === "area" && /* @__PURE__ */ jsxs38(Fragment3, { children: [
2853
+ /* @__PURE__ */ jsx51("defs", { children: /* @__PURE__ */ jsxs38("linearGradient", { id: gradientId, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2854
+ /* @__PURE__ */ jsx51("stop", { offset: "0%", stopColor: stroke, stopOpacity: 0.24 }),
2855
+ /* @__PURE__ */ jsx51("stop", { offset: "100%", stopColor: stroke, stopOpacity: 0 })
2856
+ ] }) }),
2857
+ /* @__PURE__ */ jsx51("path", { d: areaPath, fill: `url(#${gradientId})` })
2858
+ ] }),
2859
+ /* @__PURE__ */ jsx51(
2860
+ "polyline",
2861
+ {
2862
+ points,
2863
+ stroke,
2864
+ strokeWidth,
2865
+ strokeLinecap: "round",
2866
+ strokeLinejoin: "round",
2867
+ fill: "none"
2868
+ }
2869
+ ),
2870
+ showEndDot && /* @__PURE__ */ jsx51("circle", { cx: last.x, cy: last.y, r: strokeWidth * 1.6, fill: stroke, stroke: CHART_TONE.neutral, strokeWidth: 0 })
2871
+ ]
2872
+ }
2873
+ );
2874
+ }
2875
+
2876
+ // src/components/charts/mini-bar-chart.tsx
2877
+ import clsx48 from "clsx";
2878
+ import { jsx as jsx52 } from "react/jsx-runtime";
2879
+ var SIZE11 = {
2880
+ sm: { width: 80, height: 32, gap: 2 },
2881
+ md: { width: 120, height: 48, gap: 3 },
2882
+ lg: { width: 200, height: 72, gap: 4 }
2883
+ };
2884
+ function MiniBarChart({
2885
+ bars,
2886
+ tone = "brand",
2887
+ color,
2888
+ restColor = CHART_TRACK,
2889
+ highlight = -1,
2890
+ size = "md",
2891
+ width,
2892
+ height,
2893
+ gap,
2894
+ orientation = "vertical",
2895
+ radius = 2,
2896
+ label,
2897
+ className
2898
+ }) {
2899
+ if (bars.length === 0) return null;
2900
+ const preset = SIZE11[size];
2901
+ const w = width ?? preset.width;
2902
+ const h = height ?? preset.height;
2903
+ const g = gap ?? preset.gap;
2904
+ const fill = resolveChartColor(color, tone);
2905
+ const highlighted = new Set(
2906
+ (Array.isArray(highlight) ? highlight : [highlight]).map((i) => i < 0 ? bars.length + i : i)
2907
+ );
2908
+ const max = Math.max(...bars) || 1;
2909
+ const vertical = orientation === "vertical";
2910
+ const span = vertical ? w : h;
2911
+ const extent = vertical ? h : w;
2912
+ const barThickness = (span - g * (bars.length - 1)) / bars.length;
2913
+ return /* @__PURE__ */ jsx52(
2914
+ "svg",
2915
+ {
2916
+ width: w,
2917
+ height: h,
2918
+ viewBox: `0 0 ${w} ${h}`,
2919
+ fill: "none",
2920
+ role: label ? "img" : void 0,
2921
+ "aria-label": label,
2922
+ "aria-hidden": label ? void 0 : true,
2923
+ className: clsx48("block shrink-0", className),
2924
+ children: bars.map((v, i) => {
2925
+ const magnitude = Math.max(2, v / max * extent);
2926
+ const offset = i * (barThickness + g);
2927
+ return /* @__PURE__ */ jsx52(
2928
+ "rect",
2929
+ {
2930
+ x: (vertical ? offset : 0).toFixed(2),
2931
+ y: (vertical ? extent - magnitude : offset).toFixed(2),
2932
+ width: (vertical ? barThickness : magnitude).toFixed(2),
2933
+ height: (vertical ? magnitude : barThickness).toFixed(2),
2934
+ fill: highlighted.has(i) ? fill : restColor,
2935
+ rx: radius
2936
+ },
2937
+ i
2938
+ );
2939
+ })
2940
+ }
2941
+ );
2942
+ }
2943
+
2944
+ // src/components/charts/chart-legend.tsx
2945
+ import clsx50 from "clsx";
2946
+
2947
+ // src/components/charts/legend-dot.tsx
2948
+ import clsx49 from "clsx";
2949
+ import { jsx as jsx53 } from "react/jsx-runtime";
2950
+ var SHAPE = {
2951
+ dot: { sm: "size-1.5 rounded-full", md: "size-2 rounded-full" },
2952
+ square: { sm: "size-1.5 rounded-[2px]", md: "size-2 rounded-[3px]" },
2953
+ line: { sm: "h-0.5 w-3 rounded-full", md: "h-0.5 w-4 rounded-full" }
2954
+ };
2955
+ function LegendDot({ tone, color, size = "md", shape = "dot", className }) {
2956
+ return /* @__PURE__ */ jsx53(
2957
+ "span",
2958
+ {
2959
+ className: clsx49("inline-block shrink-0", SHAPE[shape][size], className),
2960
+ style: { backgroundColor: resolveChartColor(color, tone) },
2961
+ "aria-hidden": true
2962
+ }
2963
+ );
2964
+ }
2965
+
2966
+ // src/components/charts/chart-legend.tsx
2967
+ import { jsx as jsx54, jsxs as jsxs39 } from "react/jsx-runtime";
2968
+ function ChartLegend({
2969
+ items,
2970
+ orientation = "vertical",
2971
+ size = "md",
2972
+ shape = "dot",
2973
+ className
2974
+ }) {
2975
+ const horizontal = orientation === "horizontal";
2976
+ return /* @__PURE__ */ jsx54(
2977
+ "div",
2978
+ {
2979
+ className: clsx50(
2980
+ horizontal ? "flex flex-wrap items-center gap-x-4 gap-y-2" : "flex flex-col gap-3",
2981
+ className
2982
+ ),
2983
+ children: items.map((item, i) => /* @__PURE__ */ jsxs39(
2984
+ "div",
2985
+ {
2986
+ className: clsx50("flex items-center gap-2", horizontal ? "min-w-0" : "justify-between"),
2987
+ children: [
2988
+ /* @__PURE__ */ jsxs39("div", { className: "flex min-w-0 items-center gap-2", children: [
2989
+ /* @__PURE__ */ jsx54(LegendDot, { color: resolveChartColor(item.color, item.tone, i), size, shape }),
2990
+ /* @__PURE__ */ jsx54("span", { className: "truncate text-body-xs text-default-secondary", children: item.label })
2991
+ ] }),
2992
+ item.count != null && /* @__PURE__ */ jsx54("span", { className: "shrink-0 text-body-xs font-semibold tabular-nums text-default", children: item.count })
2993
+ ]
2994
+ },
2995
+ item.label
2996
+ ))
2997
+ }
2998
+ );
2999
+ }
3000
+
3001
+ // src/components/charts/trend-label.tsx
3002
+ import clsx51 from "clsx";
3003
+ import { LuTrendingDown, LuTrendingUp } from "react-icons/lu";
3004
+ import { jsx as jsx55, jsxs as jsxs40 } from "react/jsx-runtime";
3005
+ var SIZE12 = {
3006
+ sm: "text-body-xs",
3007
+ md: "text-body-sm",
3008
+ lg: "text-subheading-sm"
3009
+ };
3010
+ var ICON_SIZE = {
3011
+ sm: "size-3",
3012
+ md: "size-3.5",
3013
+ lg: "size-4"
3014
+ };
3015
+ var weightBySize = {
3016
+ sm: "semibold",
3017
+ md: "semibold",
3018
+ lg: "bold"
3019
+ };
3020
+ var WEIGHT2 = {
3021
+ semibold: "font-semibold",
3022
+ bold: "font-bold"
3023
+ };
3024
+ function TrendLabel({
3025
+ value,
3026
+ suffix = "%",
3027
+ size = "md",
3028
+ weight,
3029
+ direction = "up-is-good",
3030
+ showArrow = true,
3031
+ color,
3032
+ className
3033
+ }) {
3034
+ const rising = value > 0;
3035
+ const flat = value === 0;
3036
+ const good = direction === "up-is-good" ? rising : !rising;
3037
+ const Arrow = rising ? LuTrendingUp : LuTrendingDown;
3038
+ return /* @__PURE__ */ jsxs40(
3039
+ "span",
3040
+ {
3041
+ className: clsx51(
3042
+ "inline-flex items-center gap-1 whitespace-nowrap",
3043
+ SIZE12[size],
3044
+ WEIGHT2[weight ?? weightBySize[size]],
3045
+ !color && (flat ? "text-default-secondary" : good ? "text-positive" : "text-danger"),
3046
+ className
3047
+ ),
3048
+ style: color ? { color } : void 0,
3049
+ children: [
3050
+ showArrow && !flat && /* @__PURE__ */ jsx55(Arrow, { className: clsx51("shrink-0", ICON_SIZE[size]), "aria-hidden": true }),
3051
+ rising ? "+" : "",
3052
+ value,
3053
+ suffix
3054
+ ]
3055
+ }
3056
+ );
3057
+ }
3058
+
3059
+ // src/components/lists/list-row.tsx
3060
+ import clsx52 from "clsx";
3061
+ import { jsx as jsx56, jsxs as jsxs41 } from "react/jsx-runtime";
3062
+ var DENSITY = {
3063
+ default: {
3064
+ pad: "py-4",
3065
+ gap: "gap-3",
3066
+ title: "text-body-sm font-semibold text-default",
3067
+ description: "text-body-xs text-default-secondary"
3068
+ },
3069
+ compact: {
3070
+ pad: "py-2.5",
3071
+ gap: "gap-2",
3072
+ title: "text-body-xs font-semibold text-default",
3073
+ description: "text-body-tiny text-default-secondary"
3074
+ }
3075
+ };
3076
+ var DIVIDER = {
3077
+ none: "",
3078
+ top: "border-t border-default",
3079
+ bottom: "border-b border-default"
3080
+ };
3081
+ function ListRow({
3082
+ leading,
3083
+ title,
3084
+ titleMeta,
3085
+ description,
3086
+ meta,
3087
+ trailing,
3088
+ footer,
3089
+ density = "default",
3090
+ divider = "none",
3091
+ as: Tag = "div",
3092
+ onClick,
3093
+ className
3094
+ }) {
3095
+ const d = DENSITY[density];
3096
+ const hasTitleLine = Boolean(leading || title != null || titleMeta || meta);
3097
+ return /* @__PURE__ */ jsxs41(
3098
+ Tag,
3099
+ {
3100
+ className: clsx52(
3101
+ "flex w-full items-start",
3102
+ d.pad,
3103
+ DIVIDER[divider],
3104
+ onClick && "cursor-pointer rounded-lg transition-colors hover:bg-default-secondary/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand",
3105
+ className
3106
+ ),
3107
+ onClick,
3108
+ role: onClick ? "button" : void 0,
3109
+ tabIndex: onClick ? 0 : void 0,
3110
+ onKeyDown: onClick ? (e) => {
3111
+ if (e.key === "Enter" || e.key === " ") {
3112
+ e.preventDefault();
3113
+ onClick();
3114
+ }
3115
+ } : void 0,
3116
+ children: [
3117
+ /* @__PURE__ */ jsxs41("div", { className: clsx52("flex min-w-0 flex-1 flex-col", d.gap), children: [
3118
+ hasTitleLine && /* @__PURE__ */ jsxs41("div", { className: "flex items-center justify-between gap-2", children: [
3119
+ /* @__PURE__ */ jsxs41("div", { className: "flex min-w-0 items-center gap-2", children: [
3120
+ leading,
3121
+ title != null && /* @__PURE__ */ jsx56("span", { className: clsx52("truncate", d.title), children: title }),
3122
+ titleMeta && /* @__PURE__ */ jsx56("span", { className: "shrink-0", children: titleMeta })
3123
+ ] }),
3124
+ meta && /* @__PURE__ */ jsx56("span", { className: "shrink-0", children: meta })
3125
+ ] }),
3126
+ description && /* @__PURE__ */ jsx56("p", { className: d.description, children: description }),
3127
+ footer
3128
+ ] }),
3129
+ trailing && /* @__PURE__ */ jsx56("div", { className: "ml-3 flex shrink-0 items-center self-center", children: trailing })
3130
+ ]
3131
+ }
3132
+ );
3133
+ }
3134
+
3135
+ // src/components/lists/file-row.tsx
3136
+ import clsx53 from "clsx";
3137
+ import { jsx as jsx57, jsxs as jsxs42 } from "react/jsx-runtime";
3138
+ function FileTypeBadge({ type }) {
3139
+ return /* @__PURE__ */ jsx57("span", { className: "flex size-[34px] shrink-0 items-center justify-center rounded-md bg-brand-tertiary text-body-tiny font-semibold text-brand", children: type });
3140
+ }
3141
+ function FileRow({
3142
+ name,
3143
+ detail,
3144
+ fileType,
3145
+ leading,
3146
+ onDownload,
3147
+ downloadLabel = "Download",
3148
+ actions,
3149
+ className
3150
+ }) {
3151
+ const lead = leading ?? (fileType ? /* @__PURE__ */ jsx57(FileTypeBadge, { type: fileType }) : null);
3152
+ return /* @__PURE__ */ jsxs42(
3153
+ "div",
3154
+ {
3155
+ className: clsx53(
3156
+ "flex items-center gap-3 rounded-lg border border-default bg-default px-3 py-2.5",
3157
+ className
3158
+ ),
3159
+ children: [
3160
+ lead,
3161
+ /* @__PURE__ */ jsxs42("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
3162
+ /* @__PURE__ */ jsx57("span", { className: "truncate text-body-sm font-medium text-default", children: name }),
3163
+ detail && /* @__PURE__ */ jsx57("span", { className: "text-body-xs text-default-secondary", children: detail })
3164
+ ] }),
3165
+ (onDownload || actions) && /* @__PURE__ */ jsxs42("div", { className: "flex shrink-0 items-center gap-3", children: [
3166
+ onDownload && /* @__PURE__ */ jsx57(
3167
+ "button",
3168
+ {
3169
+ type: "button",
3170
+ onClick: onDownload,
3171
+ className: "text-body-xs font-medium text-brand hover:underline",
3172
+ children: downloadLabel
3173
+ }
3174
+ ),
3175
+ actions
3176
+ ] })
3177
+ ]
3178
+ }
3179
+ );
3180
+ }
3181
+
3182
+ // src/components/lists/scored-row.tsx
3183
+ import clsx54 from "clsx";
3184
+ import { jsx as jsx58, jsxs as jsxs43 } from "react/jsx-runtime";
3185
+ var GAP2 = {
3186
+ sm: "gap-2",
3187
+ md: "gap-3",
3188
+ lg: "gap-5",
3189
+ xl: "gap-12"
3190
+ };
3191
+ var ALIGN = {
3192
+ center: "items-center",
3193
+ end: "items-end"
3194
+ };
3195
+ function ScoredRow({
3196
+ leading,
3197
+ title,
3198
+ subtitle,
3199
+ aside,
3200
+ meter,
3201
+ trailing,
3202
+ titleWidth,
3203
+ asideWidth,
3204
+ meterWidth,
3205
+ trailingWidth,
3206
+ gap = "md",
3207
+ leadingGap,
3208
+ align = "center",
3209
+ className
3210
+ }) {
3211
+ return /* @__PURE__ */ jsxs43("div", { className: clsx54("flex w-full", ALIGN[align], GAP2[gap], className), children: [
3212
+ /* @__PURE__ */ jsxs43(
3213
+ "div",
3214
+ {
3215
+ className: clsx54(
3216
+ "flex min-w-0",
3217
+ ALIGN[align],
3218
+ GAP2[leadingGap ?? gap],
3219
+ titleWidth ? "shrink-0" : "flex-1"
3220
+ ),
3221
+ style: titleWidth ? { width: titleWidth } : void 0,
3222
+ children: [
3223
+ leading,
3224
+ /* @__PURE__ */ jsxs43("div", { className: "min-w-0 flex-1", children: [
3225
+ /* @__PURE__ */ jsx58("p", { className: "truncate text-body-sm font-medium leading-none text-default", children: title }),
3226
+ subtitle && /* @__PURE__ */ jsx58("p", { className: "mt-0.5 truncate text-body-xs text-default-secondary", children: subtitle })
3227
+ ] })
3228
+ ]
3229
+ }
3230
+ ),
3231
+ aside && /* @__PURE__ */ jsx58(
3232
+ "div",
3233
+ {
3234
+ className: clsx54("min-w-0", asideWidth ? "shrink-0" : "flex-1"),
3235
+ style: asideWidth ? { width: asideWidth } : void 0,
3236
+ children: aside
3237
+ }
3238
+ ),
3239
+ meter && /* @__PURE__ */ jsx58(
3240
+ "div",
3241
+ {
3242
+ className: clsx54("min-w-0", meterWidth ? "shrink-0" : "flex-1"),
3243
+ style: meterWidth ? { width: meterWidth } : void 0,
3244
+ children: meter
3245
+ }
3246
+ ),
3247
+ trailing && /* @__PURE__ */ jsx58("div", { className: "shrink-0 text-right", style: trailingWidth ? { width: trailingWidth } : void 0, children: trailing })
3248
+ ] });
3249
+ }
3250
+
3251
+ // src/components/lists/ranked-row.tsx
3252
+ import clsx55 from "clsx";
3253
+
3254
+ // src/components/feedback/progress-bar.tsx
3255
+ import { jsx as jsx59, jsxs as jsxs44 } from "react/jsx-runtime";
3256
+ var SIZE13 = {
3257
+ xs: "h-1",
3258
+ sm: "h-1.5",
3259
+ md: "h-2",
3260
+ lg: "h-3"
3261
+ };
3262
+ var FILL = {
3263
+ brand: "bg-brand",
3264
+ positive: "bg-positive",
3265
+ warning: "bg-warning",
3266
+ danger: "bg-danger",
3267
+ neutral: "bg-neutral"
3268
+ };
3269
+ function ProgressBar({
3270
+ value,
3271
+ tone = "brand",
3272
+ size = "sm",
3273
+ label,
3274
+ showValue = false,
3275
+ radius,
3276
+ "aria-label": ariaLabel,
3277
+ className
3278
+ }) {
3279
+ const clamped = Math.min(100, Math.max(0, value));
3280
+ const rounded = radius ? void 0 : "rounded-full";
3281
+ const track = /* @__PURE__ */ jsx59(
3282
+ "div",
3283
+ {
3284
+ role: "progressbar",
3285
+ "aria-valuenow": clamped,
3286
+ "aria-valuemin": 0,
3287
+ "aria-valuemax": 100,
3288
+ "aria-label": label ? void 0 : ariaLabel,
3289
+ className: cn("w-full overflow-hidden bg-default-tertiary", SIZE13[size], rounded, className),
3290
+ style: radius ? { borderRadius: radius } : void 0,
3291
+ children: /* @__PURE__ */ jsx59(
3292
+ "div",
3293
+ {
3294
+ className: cn("h-full transition-all", rounded, FILL[tone]),
3295
+ style: { width: `${clamped}%`, ...radius ? { borderRadius: radius } : void 0 }
3296
+ }
3297
+ )
3298
+ }
3299
+ );
3300
+ if (!label && !showValue) return track;
3301
+ return /* @__PURE__ */ jsxs44("div", { children: [
3302
+ /* @__PURE__ */ jsxs44("div", { className: "mb-1.5 flex items-center justify-between gap-2", children: [
3303
+ label && /* @__PURE__ */ jsx59("span", { className: "text-body-xs text-default-secondary", children: label }),
3304
+ showValue && /* @__PURE__ */ jsxs44("span", { className: "ml-auto text-body-xs font-medium tabular-nums text-default", children: [
3305
+ Math.round(clamped),
3306
+ "%"
3307
+ ] })
3308
+ ] }),
3309
+ track
3310
+ ] });
3311
+ }
3312
+
3313
+ // src/components/lists/ranked-row.tsx
3314
+ import { jsx as jsx60, jsxs as jsxs45 } from "react/jsx-runtime";
3315
+ function RankedRow({
3316
+ rank,
3317
+ name,
3318
+ sublabel,
3319
+ score,
3320
+ tone = "auto",
3321
+ direction = "higher-is-worse",
3322
+ scoreSize = "md",
3323
+ scoreWeight = "bold",
3324
+ className
1201
3325
  }) {
1202
- return /* @__PURE__ */ jsx20("section", { className: clsx20("rounded-3xl border border-white/70 bg-white/90 p-6 shadow-panel backdrop-blur", className), children });
3326
+ const resolved = tone === "auto" ? getScoreTone(score, { direction }) : tone;
3327
+ return /* @__PURE__ */ jsxs45("div", { className: clsx55("flex w-full shrink-0 flex-col gap-1.5", className), children: [
3328
+ /* @__PURE__ */ jsxs45("div", { className: "flex w-full items-center justify-between", children: [
3329
+ /* @__PURE__ */ jsxs45("div", { className: "flex min-w-0 items-center gap-2.5", children: [
3330
+ rank !== void 0 && /* @__PURE__ */ jsx60("p", { className: "w-[14px] shrink-0 text-body-xs font-bold text-default-secondary", children: rank }),
3331
+ /* @__PURE__ */ jsxs45("div", { className: "flex min-w-0 flex-col gap-px", children: [
3332
+ /* @__PURE__ */ jsx60("p", { className: "truncate text-body-sm font-medium leading-none text-default", children: name }),
3333
+ sublabel && /* @__PURE__ */ jsx60("p", { className: "text-body-tiny text-default-tertiary", children: sublabel })
3334
+ ] })
3335
+ ] }),
3336
+ /* @__PURE__ */ jsx60(
3337
+ ScoreValue,
3338
+ {
3339
+ value: score,
3340
+ size: scoreSize,
3341
+ weight: scoreWeight,
3342
+ tone: resolved,
3343
+ className: "ml-2 shrink-0"
3344
+ }
3345
+ )
3346
+ ] }),
3347
+ /* @__PURE__ */ jsx60(ProgressBar, { value: score, tone: resolved, "aria-label": `${name} score` })
3348
+ ] });
3349
+ }
3350
+
3351
+ // src/components/lists/icon-text-row.tsx
3352
+ import clsx56 from "clsx";
3353
+ import { jsx as jsx61, jsxs as jsxs46 } from "react/jsx-runtime";
3354
+ function IconTextRow({ icon, title, detail, className }) {
3355
+ return /* @__PURE__ */ jsxs46("div", { className: clsx56("flex items-start gap-3", className), children: [
3356
+ /* @__PURE__ */ jsx61("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-full bg-brand-tertiary text-brand", children: icon }),
3357
+ /* @__PURE__ */ jsxs46("div", { className: "min-w-0", children: [
3358
+ /* @__PURE__ */ jsx61("p", { className: "text-body-sm font-semibold text-default", children: title }),
3359
+ /* @__PURE__ */ jsx61("p", { className: "mt-0.5 text-body-xs text-default-secondary", children: detail })
3360
+ ] })
3361
+ ] });
3362
+ }
3363
+
3364
+ // src/components/lists/checklist-row.tsx
3365
+ import clsx57 from "clsx";
3366
+ import { LuCheck as LuCheck5 } from "react-icons/lu";
3367
+ import { jsx as jsx62, jsxs as jsxs47 } from "react/jsx-runtime";
3368
+ function ChecklistRow({ label, state, className }) {
3369
+ return /* @__PURE__ */ jsxs47("li", { className: clsx57("flex items-center gap-3", className), children: [
3370
+ /* @__PURE__ */ jsx62("span", { className: "flex size-5 shrink-0 items-center justify-center", children: state === "done" ? /* @__PURE__ */ jsx62(LuCheck5, { className: "size-4 text-positive", strokeWidth: 2.5, "aria-hidden": true }) : /* @__PURE__ */ jsx62(
3371
+ "span",
3372
+ {
3373
+ className: clsx57(
3374
+ "size-3.5 rounded-full border-2",
3375
+ state === "active" ? "animate-pulse border-brand-emphasis border-t-transparent" : "border-disabled"
3376
+ )
3377
+ }
3378
+ ) }),
3379
+ /* @__PURE__ */ jsx62(
3380
+ "span",
3381
+ {
3382
+ className: clsx57(
3383
+ "text-body-sm",
3384
+ state === "pending" ? "text-default-tertiary" : "font-semibold text-default"
3385
+ ),
3386
+ children: label
3387
+ }
3388
+ )
3389
+ ] });
3390
+ }
3391
+
3392
+ // src/components/lists/numbered-steps-list.tsx
3393
+ import clsx58 from "clsx";
3394
+ import { jsx as jsx63, jsxs as jsxs48 } from "react/jsx-runtime";
3395
+ function NumberedStepsList({ steps, className }) {
3396
+ return /* @__PURE__ */ jsx63("ol", { className: clsx58("flex flex-col gap-1.5", className), children: steps.map((step, i) => /* @__PURE__ */ jsxs48("li", { className: "flex items-start gap-2 text-[12px] text-default", children: [
3397
+ /* @__PURE__ */ jsx63("span", { className: "mt-0.5 flex size-4 shrink-0 items-center justify-center rounded-full bg-brand-tertiary text-[9px] font-bold text-brand", children: i + 1 }),
3398
+ step
3399
+ ] }, i)) });
1203
3400
  }
1204
- function MetricCard({
3401
+
3402
+ // src/components/lists/meta-field.tsx
3403
+ import clsx59 from "clsx";
3404
+ import { jsx as jsx64, jsxs as jsxs49 } from "react/jsx-runtime";
3405
+ function MetaField({
1205
3406
  label,
1206
3407
  value,
1207
- tone = "default"
3408
+ detail,
3409
+ layout = "stacked",
3410
+ className
1208
3411
  }) {
1209
- const tones = {
1210
- default: "from-white to-slate-50 text-text-default",
1211
- signal: "from-background-brand-tertiary to-cyan-50 text-text-brand",
1212
- ember: "from-amber-50 to-orange-50 text-text-danger",
1213
- moss: "from-emerald-50 to-lime-50 text-text-positive"
1214
- };
1215
- return /* @__PURE__ */ jsxs18(Panel, { className: clsx20("bg-gradient-to-br", tones[tone]), children: [
1216
- /* @__PURE__ */ jsx20("p", { className: "text-sm uppercase tracking-[0.2em] text-slate-500", children: label }),
1217
- /* @__PURE__ */ jsx20("p", { className: "mt-3 text-3xl font-semibold", children: value })
3412
+ const shown = value === null || value === void 0 || value === "" ? "\u2014" : value;
3413
+ if (layout === "inline") {
3414
+ return /* @__PURE__ */ jsxs49("div", { className: clsx59("flex gap-3 text-body-xs", className), children: [
3415
+ /* @__PURE__ */ jsx64("span", { className: "w-[120px] shrink-0 text-default-secondary", children: label }),
3416
+ /* @__PURE__ */ jsx64("span", { className: "min-w-0 flex-1 text-default", children: shown })
3417
+ ] });
3418
+ }
3419
+ return /* @__PURE__ */ jsxs49("div", { className: clsx59("flex flex-col gap-0.5", className), children: [
3420
+ /* @__PURE__ */ jsx64("p", { className: "text-body-tiny font-medium text-default-secondary", children: label }),
3421
+ /* @__PURE__ */ jsx64("p", { className: "text-body-sm font-medium text-default", children: shown }),
3422
+ detail && /* @__PURE__ */ jsx64("p", { className: "text-body-xs text-default-secondary", children: detail })
1218
3423
  ] });
1219
3424
  }
1220
- function SeverityBadge({ severity }) {
1221
- const styles = {
1222
- critical: "bg-red-100 text-red-700",
1223
- high: "bg-orange-100 text-orange-700",
1224
- medium: "bg-amber-100 text-amber-700",
1225
- low: "bg-slate-100 text-slate-700"
1226
- };
1227
- return /* @__PURE__ */ jsx20("span", { className: clsx20("inline-flex rounded-full px-3 py-1 text-xs font-semibold uppercase tracking-wide", styles[severity ?? "low"]), children: severity ?? "unknown" });
1228
- }
1229
- function SentimentBadge({ sentiment }) {
1230
- const styles = {
1231
- positive: "bg-emerald-100 text-emerald-700",
1232
- neutral: "bg-slate-100 text-slate-700",
1233
- negative: "bg-rose-100 text-rose-700",
1234
- concerning: "bg-amber-100 text-amber-700"
1235
- };
1236
- return /* @__PURE__ */ jsx20("span", { className: clsx20("inline-flex rounded-full px-3 py-1 text-xs font-semibold capitalize", styles[sentiment ?? "neutral"] ?? styles.neutral), children: sentiment ?? "unknown" });
1237
- }
1238
- function SectionHeading({
1239
- eyebrow,
1240
- title,
1241
- detail
3425
+ function MetaFieldGrid({ children, className }) {
3426
+ return /* @__PURE__ */ jsx64("div", { className: clsx59("flex flex-wrap gap-x-4 gap-y-3.5", className), children });
3427
+ }
3428
+
3429
+ // src/components/lists/checked-group-list.tsx
3430
+ import clsx60 from "clsx";
3431
+ import { LuCheck as LuCheck6 } from "react-icons/lu";
3432
+ import { jsx as jsx65, jsxs as jsxs50 } from "react/jsx-runtime";
3433
+ var COLUMNS2 = {
3434
+ 1: "columns-1",
3435
+ 2: "columns-2",
3436
+ 3: "columns-3"
3437
+ };
3438
+ function CheckedGroupList({
3439
+ groups,
3440
+ columns = 2,
3441
+ icon,
3442
+ emptyLabel = "None.",
3443
+ className
3444
+ }) {
3445
+ if (groups.length === 0) {
3446
+ return /* @__PURE__ */ jsx65("p", { className: clsx60("text-body-xs text-default-secondary", className), children: emptyLabel });
3447
+ }
3448
+ const glyph = icon === void 0 ? /* @__PURE__ */ jsx65(LuCheck6, { className: "size-3.5", strokeWidth: 2.5, "aria-hidden": true }) : icon;
3449
+ return /* @__PURE__ */ jsx65("div", { className: clsx60(COLUMNS2[columns], "gap-x-6", className), children: groups.map((group) => /* @__PURE__ */ jsxs50("div", { className: "mb-5 break-inside-avoid last:mb-0", children: [
3450
+ /* @__PURE__ */ jsx65("p", { className: "mb-2 text-body-tiny font-semibold uppercase tracking-wide text-default-secondary", children: group.label }),
3451
+ /* @__PURE__ */ jsx65("ul", { className: "space-y-1.5", children: group.items.map((item) => /* @__PURE__ */ jsxs50("li", { className: "flex items-center gap-2 text-body-xs text-default", children: [
3452
+ glyph && /* @__PURE__ */ jsx65("span", { className: "shrink-0", children: glyph }),
3453
+ item
3454
+ ] }, item)) })
3455
+ ] }, group.label)) });
3456
+ }
3457
+
3458
+ // src/components/lists/data-table.tsx
3459
+ import clsx61 from "clsx";
3460
+ import { jsx as jsx66, jsxs as jsxs51 } from "react/jsx-runtime";
3461
+ var DENSITY2 = {
3462
+ default: {
3463
+ headerCell: "px-4 py-3",
3464
+ headerText: "text-body-xs font-medium text-default-secondary whitespace-nowrap",
3465
+ bodyCell: "px-4 py-[14px]"
3466
+ },
3467
+ compact: {
3468
+ headerCell: "px-3 py-2",
3469
+ headerText: "text-body-tiny font-semibold uppercase tracking-[0.4px] text-default-secondary whitespace-nowrap",
3470
+ bodyCell: "px-3 py-2 text-body-xs text-default"
3471
+ }
3472
+ };
3473
+ var ALIGN2 = {
3474
+ center: "align-middle",
3475
+ top: "align-top"
3476
+ };
3477
+ function DataTable({
3478
+ columns,
3479
+ rows,
3480
+ getRowKey,
3481
+ density = "default",
3482
+ align = "center",
3483
+ onRowClick,
3484
+ emptyLabel,
3485
+ className
3486
+ }) {
3487
+ const d = DENSITY2[density];
3488
+ const minWidth = columns.length ? `calc(${columns.map((c) => c.width).join(" + ")})` : void 0;
3489
+ return /* @__PURE__ */ jsx66("div", { className: clsx61("overflow-x-auto rounded-xl border border-default bg-default", className), children: /* @__PURE__ */ jsxs51("table", { className: "w-full table-fixed border-collapse text-left", style: { minWidth }, children: [
3490
+ /* @__PURE__ */ jsx66("colgroup", { children: columns.map((col) => (
3491
+ // A grow column gets no width, so table-fixed hands it the leftover space.
3492
+ // Its floor is already counted in the table's min-width.
3493
+ /* @__PURE__ */ jsx66("col", { style: col.grow ? void 0 : { width: col.width } }, col.key)
3494
+ )) }),
3495
+ /* @__PURE__ */ jsx66("thead", { children: /* @__PURE__ */ jsx66("tr", { className: "bg-default-secondary", children: columns.map((col) => /* @__PURE__ */ jsx66("th", { scope: "col", className: clsx61("overflow-hidden", d.headerCell, d.headerText), children: col.header }, col.key)) }) }),
3496
+ /* @__PURE__ */ jsx66("tbody", { children: rows.length === 0 ? emptyLabel && /* @__PURE__ */ jsx66("tr", { children: /* @__PURE__ */ jsx66(
3497
+ "td",
3498
+ {
3499
+ colSpan: columns.length,
3500
+ className: clsx61(d.bodyCell, "text-center text-body-sm text-default-secondary"),
3501
+ children: emptyLabel
3502
+ }
3503
+ ) }) : rows.map((row, i) => /* @__PURE__ */ jsx66(
3504
+ "tr",
3505
+ {
3506
+ className: clsx61(
3507
+ "transition-colors hover:bg-default-secondary/50",
3508
+ i > 0 && "border-t border-default",
3509
+ // outline, not ring: `ring-*` compiles to box-shadow, which browsers
3510
+ // do not paint on a <tr> under border-collapse: collapse.
3511
+ onRowClick && "cursor-pointer outline-none focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-brand"
3512
+ ),
3513
+ tabIndex: onRowClick ? 0 : void 0,
3514
+ onClick: onRowClick ? () => onRowClick(row) : void 0,
3515
+ onKeyDown: onRowClick ? (e) => {
3516
+ if (e.key === "Enter" || e.key === " ") {
3517
+ e.preventDefault();
3518
+ onRowClick(row);
3519
+ }
3520
+ } : void 0,
3521
+ children: columns.map((col) => /* @__PURE__ */ jsx66("td", { className: clsx61("overflow-hidden", d.bodyCell, ALIGN2[align]), children: col.render(row) }, col.key))
3522
+ },
3523
+ getRowKey(row, i)
3524
+ )) })
3525
+ ] }) });
3526
+ }
3527
+ function TableCellLeadText({ primary, secondary, size = "md", className }) {
3528
+ return /* @__PURE__ */ jsxs51("div", { className: clsx61("flex flex-col gap-0.5", className), children: [
3529
+ /* @__PURE__ */ jsx66(
3530
+ "span",
3531
+ {
3532
+ className: clsx61(
3533
+ "font-medium leading-snug text-default",
3534
+ size === "sm" ? "text-body-xs" : "text-body-sm"
3535
+ ),
3536
+ children: primary
3537
+ }
3538
+ ),
3539
+ secondary && /* @__PURE__ */ jsx66(
3540
+ "span",
3541
+ {
3542
+ className: clsx61(
3543
+ "font-normal leading-tight text-default-secondary",
3544
+ size === "sm" ? "text-body-tiny" : "text-body-xs"
3545
+ ),
3546
+ children: secondary
3547
+ }
3548
+ )
3549
+ ] });
3550
+ }
3551
+ function TableCellText({
3552
+ children,
3553
+ muted = true,
3554
+ size = "md",
3555
+ truncate = false,
3556
+ className
3557
+ }) {
3558
+ return /* @__PURE__ */ jsx66(
3559
+ "span",
3560
+ {
3561
+ className: clsx61(
3562
+ "font-normal leading-snug",
3563
+ size === "sm" ? "text-body-tiny" : "text-body-xs",
3564
+ truncate ? "block truncate" : "whitespace-nowrap",
3565
+ muted ? "text-default-secondary" : "text-default",
3566
+ className
3567
+ ),
3568
+ children
3569
+ }
3570
+ );
3571
+ }
3572
+ function TableCellBadge({ label, className }) {
3573
+ return /* @__PURE__ */ jsx66(
3574
+ "span",
3575
+ {
3576
+ className: clsx61(
3577
+ "inline-flex items-center rounded-md border border-default bg-default-secondary px-2 py-0.5 text-body-tiny font-medium text-default-secondary whitespace-nowrap",
3578
+ className
3579
+ ),
3580
+ children: label
3581
+ }
3582
+ );
3583
+ }
3584
+ function TableCellProgress({
3585
+ percent,
3586
+ tone = "brand",
3587
+ size = "md",
3588
+ className
3589
+ }) {
3590
+ const clamped = Math.min(100, Math.max(0, percent));
3591
+ return /* @__PURE__ */ jsxs51("div", { className: clsx61("flex flex-col gap-1", className), children: [
3592
+ /* @__PURE__ */ jsx66(ProgressBar, { value: clamped, tone, size: "sm", className: "w-16", "aria-label": `${clamped}%` }),
3593
+ /* @__PURE__ */ jsxs51(
3594
+ "span",
3595
+ {
3596
+ className: clsx61(
3597
+ "leading-none text-default-secondary",
3598
+ size === "sm" ? "text-[10px]" : "text-body-tiny"
3599
+ ),
3600
+ children: [
3601
+ percent,
3602
+ "%"
3603
+ ]
3604
+ }
3605
+ )
3606
+ ] });
3607
+ }
3608
+
3609
+ // src/components/feedback/inline-alert.tsx
3610
+ import clsx62 from "clsx";
3611
+ import { LuCircleCheckBig as LuCircleCheckBig2, LuInfo as LuInfo2, LuTriangleAlert as LuTriangleAlert2 } from "react-icons/lu";
3612
+ import { jsx as jsx67, jsxs as jsxs52 } from "react/jsx-runtime";
3613
+ var toneStyles3 = {
3614
+ info: "border-brand-tertiary bg-brand-tertiary text-brand",
3615
+ warning: "border-warning-tertiary bg-warning-tertiary text-warning",
3616
+ danger: "border-danger-tertiary bg-danger-tertiary text-danger",
3617
+ positive: "border-positive-tertiary bg-positive-tertiary text-positive"
3618
+ };
3619
+ var toneIcons = {
3620
+ info: /* @__PURE__ */ jsx67(LuInfo2, { className: "size-4" }),
3621
+ warning: /* @__PURE__ */ jsx67(LuTriangleAlert2, { className: "size-4" }),
3622
+ danger: /* @__PURE__ */ jsx67(LuTriangleAlert2, { className: "size-4" }),
3623
+ positive: /* @__PURE__ */ jsx67(LuCircleCheckBig2, { className: "size-4" })
3624
+ };
3625
+ function InlineAlert({ tone, children, icon, className }) {
3626
+ const glyph = icon === void 0 ? toneIcons[tone] : icon;
3627
+ return /* @__PURE__ */ jsxs52(
3628
+ "div",
3629
+ {
3630
+ role: tone === "danger" ? "alert" : "status",
3631
+ className: clsx62(
3632
+ "flex items-start gap-2.5 rounded-xl border p-3.5 text-body-xs",
3633
+ toneStyles3[tone],
3634
+ className
3635
+ ),
3636
+ children: [
3637
+ glyph && /* @__PURE__ */ jsx67("span", { className: "mt-px shrink-0", children: glyph }),
3638
+ /* @__PURE__ */ jsx67("div", { className: "min-w-0", children })
3639
+ ]
3640
+ }
3641
+ );
3642
+ }
3643
+
3644
+ // src/components/feedback/empty-state.tsx
3645
+ import clsx63 from "clsx";
3646
+ import { jsx as jsx68, jsxs as jsxs53 } from "react/jsx-runtime";
3647
+ var SIZES = {
3648
+ sm: "py-8",
3649
+ md: "py-12",
3650
+ lg: "py-16"
3651
+ };
3652
+ var TONES = {
3653
+ empty: "text-default-secondary",
3654
+ loading: "text-default-secondary",
3655
+ error: "text-danger"
3656
+ };
3657
+ function EmptyState({
3658
+ message,
3659
+ variant = "empty",
3660
+ size = "sm",
3661
+ icon,
3662
+ action,
3663
+ className
3664
+ }) {
3665
+ return /* @__PURE__ */ jsxs53(
3666
+ "div",
3667
+ {
3668
+ className: clsx63(
3669
+ "flex flex-col items-center justify-center gap-2 px-4 text-center text-body-sm",
3670
+ SIZES[size],
3671
+ TONES[variant],
3672
+ className
3673
+ ),
3674
+ "aria-live": variant === "empty" ? void 0 : "polite",
3675
+ children: [
3676
+ icon && /* @__PURE__ */ jsx68("span", { className: "text-default-tertiary", children: icon }),
3677
+ /* @__PURE__ */ jsx68("p", { children: message }),
3678
+ action
3679
+ ]
3680
+ }
3681
+ );
3682
+ }
3683
+
3684
+ // src/components/forms/password-input.tsx
3685
+ import { forwardRef as forwardRef5, useState as useState5 } from "react";
3686
+ import { LuEye, LuEyeOff } from "react-icons/lu";
3687
+ import { jsx as jsx69 } from "react/jsx-runtime";
3688
+ var PasswordInput = forwardRef5(function PasswordInput2(props, ref) {
3689
+ const [visible, setVisible] = useState5(false);
3690
+ return /* @__PURE__ */ jsx69(
3691
+ Input,
3692
+ {
3693
+ ref,
3694
+ ...props,
3695
+ type: visible ? "text" : "password",
3696
+ trailingAction: /* @__PURE__ */ jsx69(
3697
+ "button",
3698
+ {
3699
+ type: "button",
3700
+ "aria-label": visible ? "Hide password" : "Show password",
3701
+ onClick: () => setVisible((v) => !v),
3702
+ className: "flex items-center justify-center rounded transition-colors hover:text-default focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand",
3703
+ children: visible ? /* @__PURE__ */ jsx69(LuEyeOff, { className: "size-4" }) : /* @__PURE__ */ jsx69(LuEye, { className: "size-4" })
3704
+ }
3705
+ )
3706
+ }
3707
+ );
3708
+ });
3709
+
3710
+ // src/components/ai/ai-chat-bar.tsx
3711
+ import clsx64 from "clsx";
3712
+ import { LuArrowRight as LuArrowRight2, LuSearch } from "react-icons/lu";
3713
+ import { jsx as jsx70, jsxs as jsxs54 } from "react/jsx-runtime";
3714
+ function AIChatBar({
3715
+ placeholder = "Ask Intelligence about any entity, supplier, or risk\u2026",
3716
+ className
1242
3717
  }) {
1243
- return /* @__PURE__ */ jsxs18("div", { children: [
1244
- /* @__PURE__ */ jsx20("p", { className: "text-xs uppercase tracking-[0.25em] text-text-brand", children: eyebrow }),
1245
- /* @__PURE__ */ jsx20("h2", { className: "mt-2 text-2xl font-semibold text-text-default", children: title }),
1246
- detail ? /* @__PURE__ */ jsx20("p", { className: "mt-2 max-w-2xl text-sm text-slate-600", children: detail }) : null
3718
+ return /* @__PURE__ */ jsxs54(
3719
+ "div",
3720
+ {
3721
+ className: clsx64(
3722
+ "flex h-16 items-center gap-3 rounded-2xl border border-default bg-default px-6 shadow-panel",
3723
+ className
3724
+ ),
3725
+ children: [
3726
+ /* @__PURE__ */ jsx70("span", { className: "shrink-0 text-icon-default-secondary", children: /* @__PURE__ */ jsx70(LuSearch, { className: "size-4" }) }),
3727
+ /* @__PURE__ */ jsx70("p", { className: "flex-1 text-body-sm text-default-tertiary truncate", children: placeholder }),
3728
+ /* @__PURE__ */ jsxs54(
3729
+ "button",
3730
+ {
3731
+ type: "button",
3732
+ className: "inline-flex shrink-0 items-center gap-2 rounded-xl bg-brand px-4 py-3 text-body-sm font-semibold text-brand-on-brand hover:bg-brand-hover transition-colors",
3733
+ children: [
3734
+ "Ask",
3735
+ /* @__PURE__ */ jsx70(LuArrowRight2, { className: "size-4" })
3736
+ ]
3737
+ }
3738
+ )
3739
+ ]
3740
+ }
3741
+ );
3742
+ }
3743
+
3744
+ // src/components/ai/ai-suggestion-chip.tsx
3745
+ import clsx65 from "clsx";
3746
+ import { LuArrowRight as LuArrowRight3, LuCpu } from "react-icons/lu";
3747
+ import { jsx as jsx71, jsxs as jsxs55 } from "react/jsx-runtime";
3748
+ function AISuggestionChip({ prompt, onClick, className }) {
3749
+ return /* @__PURE__ */ jsxs55(
3750
+ "button",
3751
+ {
3752
+ type: "button",
3753
+ onClick,
3754
+ className: clsx65(
3755
+ "flex h-12 w-full items-center gap-3 rounded-xl border border-default bg-default px-3 text-left hover:bg-default-hover transition-colors",
3756
+ className
3757
+ ),
3758
+ children: [
3759
+ /* @__PURE__ */ jsx71("span", { className: "shrink-0 text-icon-brand", children: /* @__PURE__ */ jsx71(LuCpu, { className: "size-4" }) }),
3760
+ /* @__PURE__ */ jsx71("span", { className: "flex-1 text-body-sm text-default truncate", children: prompt }),
3761
+ /* @__PURE__ */ jsx71("span", { className: "shrink-0 text-icon-default-secondary", children: /* @__PURE__ */ jsx71(LuArrowRight3, { className: "size-3.5", strokeWidth: 2.5 }) })
3762
+ ]
3763
+ }
3764
+ );
3765
+ }
3766
+
3767
+ // src/components/ai/quick-actions-bar.tsx
3768
+ import clsx66 from "clsx";
3769
+ import { jsx as jsx72 } from "react/jsx-runtime";
3770
+ function QuickActionsBar({ actions, active, onSelect, className }) {
3771
+ return /* @__PURE__ */ jsx72("div", { className: clsx66("flex items-center gap-3 flex-wrap", className), children: actions.map((action) => /* @__PURE__ */ jsx72(
3772
+ "button",
3773
+ {
3774
+ type: "button",
3775
+ onClick: () => onSelect?.(action.value),
3776
+ className: "focus:outline-none",
3777
+ children: /* @__PURE__ */ jsx72(
3778
+ TagPill,
3779
+ {
3780
+ label: action.label,
3781
+ tone: active === action.value ? "brand" : "default"
3782
+ }
3783
+ )
3784
+ },
3785
+ action.value
3786
+ )) });
3787
+ }
3788
+
3789
+ // src/components/decorative/aurora-backdrop.tsx
3790
+ import { jsx as jsx73, jsxs as jsxs56 } from "react/jsx-runtime";
3791
+ function AuroraBackdrop() {
3792
+ return /* @__PURE__ */ jsxs56("div", { className: "pointer-events-none absolute inset-0", "aria-hidden": true, children: [
3793
+ /* @__PURE__ */ jsx73("div", { className: "absolute -left-24 -top-28", style: { width: 380, height: 380, background: "radial-gradient(ellipse, rgba(249,133,133,0.45) 0%, transparent 70%)" } }),
3794
+ /* @__PURE__ */ jsx73("div", { className: "absolute -top-24 right-[-4%]", style: { width: 320, height: 320, background: "radial-gradient(ellipse, rgba(254,160,160,0.4) 0%, transparent 70%)" } }),
3795
+ /* @__PURE__ */ jsx73("div", { className: "absolute bottom-[-10%] right-[14%]", style: { width: 420, height: 420, background: "radial-gradient(ellipse, rgba(196,181,253,0.3) 0%, transparent 70%)" } }),
3796
+ /* @__PURE__ */ jsx73("div", { className: "absolute bottom-[-6%] left-[4%]", style: { width: 280, height: 280, background: "radial-gradient(ellipse, rgba(147,197,253,0.25) 0%, transparent 70%)" } }),
3797
+ /* @__PURE__ */ jsx73("div", { className: "absolute left-[20%] top-[30%]", style: { width: 240, height: 240, background: "radial-gradient(ellipse, rgba(173,216,255,0.18) 0%, transparent 70%)" } })
1247
3798
  ] });
1248
3799
  }
3800
+
3801
+ // src/components/icons/solid.tsx
3802
+ import { jsx as jsx74 } from "react/jsx-runtime";
3803
+ function solid(path, displayName) {
3804
+ const Component = ({ className }) => /* @__PURE__ */ jsx74("svg", { viewBox: "0 0 20 20", fill: "currentColor", className, "aria-hidden": "true", children: /* @__PURE__ */ jsx74("path", { fillRule: "evenodd", d: path, clipRule: "evenodd" }) });
3805
+ Component.displayName = displayName;
3806
+ return Component;
3807
+ }
3808
+ var SolidAlertTriangle = solid(
3809
+ "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
3810
+ "SolidAlertTriangle"
3811
+ );
3812
+ var SolidShieldCheck = solid(
3813
+ "M10 1.944A11.954 11.954 0 012.166 5C2.056 5.649 2 6.319 2 7c0 5.225 3.34 9.67 8 11.317C14.66 16.67 18 12.225 18 7c0-.682-.057-1.35-.166-2.001A11.954 11.954 0 0110 1.944zm1.414 7.349a1 1 0 00-1.414-1.414L8.5 9.379l-.793-.793a1 1 0 00-1.414 1.414l1.5 1.5a1 1 0 001.414 0l2.207-2.207z",
3814
+ "SolidShieldCheck"
3815
+ );
3816
+ var SolidGlobe = solid(
3817
+ "M10 18a8 8 0 100-16 8 8 0 000 16zM4.332 8.027a6.012 6.012 0 011.912-2.706C6.512 5.73 6.974 6 7.5 6A1.5 1.5 0 019 7.5V8a2 2 0 004 0 2 2 0 011.523-1.943A5.977 5.977 0 0116 10c0 .34-.028.675-.083 1H15a2 2 0 00-2 2v2.197A5.973 5.973 0 0110 16v-2a2 2 0 00-2-2 2 2 0 01-2-2 2 2 0 00-1.668-1.973z",
3818
+ "SolidGlobe"
3819
+ );
3820
+ var SolidMapPin = solid(
3821
+ "M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z",
3822
+ "SolidMapPin"
3823
+ );
3824
+ var SolidClock = solid(
3825
+ "M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z",
3826
+ "SolidClock"
3827
+ );
3828
+ var SolidArrowRight = solid(
3829
+ "M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z",
3830
+ "SolidArrowRight"
3831
+ );
3832
+ var SolidInfoCircle = solid(
3833
+ "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z",
3834
+ "SolidInfoCircle"
3835
+ );
3836
+ var SolidCheck = solid(
3837
+ "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
3838
+ "SolidCheck"
3839
+ );
3840
+ function SolidChartBar({ className }) {
3841
+ return /* @__PURE__ */ jsx74("svg", { viewBox: "0 0 20 20", fill: "currentColor", className, "aria-hidden": "true", children: /* @__PURE__ */ jsx74("path", { d: "M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z" }) });
3842
+ }
1249
3843
  export {
3844
+ AIChatBar,
3845
+ AISuggestionChip,
3846
+ AuroraBackdrop,
1250
3847
  Avatar,
3848
+ AvatarBlock,
1251
3849
  AvatarGroup,
3850
+ Badge,
3851
+ BarChart,
1252
3852
  Button,
1253
3853
  ButtonGroup,
3854
+ CHART_SEQUENCE,
3855
+ CHART_TONE,
3856
+ CHART_TRACK,
3857
+ Card,
3858
+ CardAction,
3859
+ CardBody,
3860
+ CardDescription,
3861
+ CardFooter,
3862
+ CardHeader,
3863
+ CardTitle,
3864
+ ChartLegend,
3865
+ CheckIndicator,
3866
+ Checkbox,
3867
+ CheckedGroupList,
3868
+ ChecklistRow,
3869
+ ConfirmDialog,
3870
+ CountBadge,
3871
+ DEFAULT_SCORE_THRESHOLDS,
1254
3872
  DataTable,
1255
- DocumentRow,
3873
+ DatePicker,
3874
+ DonutChart,
3875
+ Drawer,
3876
+ DropdownMenu,
3877
+ EmptyState,
3878
+ EntityIconBadge,
3879
+ EyebrowLabel,
1256
3880
  FileDropZone,
3881
+ FileRow,
3882
+ FilterBar,
1257
3883
  FormCard,
1258
3884
  FormCardFooter,
1259
3885
  FormCardHeader,
1260
3886
  IconButton,
3887
+ IconTextRow,
3888
+ InlineAlert,
1261
3889
  Input,
1262
- MetricCard,
3890
+ LegendDot,
3891
+ ListRow,
3892
+ MetaField,
3893
+ MetaFieldGrid,
3894
+ MiniBarChart,
1263
3895
  Modal,
3896
+ ModalBody,
3897
+ ModalDescription,
3898
+ ModalFooter,
3899
+ ModalHeader,
3900
+ ModalTitle,
1264
3901
  MultiSelectCard,
1265
3902
  NavItem,
1266
- Panel,
3903
+ NoteConfirmModal,
3904
+ NumberedStepsList,
3905
+ OVERLAY_SCRIM,
3906
+ PageHeading,
3907
+ PageToolbar,
3908
+ PasswordInput,
3909
+ ProgressBar,
3910
+ QuickActionsBar,
1267
3911
  ROLE_COMBO_OPTIONS,
3912
+ RadialGauge,
3913
+ RankedRow,
1268
3914
  RoleBadge,
1269
3915
  RoleComboBox,
1270
- SectionHeading,
3916
+ ScoreValue,
3917
+ ScoredRow,
3918
+ SegmentedControl,
1271
3919
  Select,
1272
- SentimentBadge,
1273
- SeverityBadge,
3920
+ SolidAlertTriangle,
3921
+ SolidArrowRight,
3922
+ SolidChartBar,
3923
+ SolidCheck,
3924
+ SolidClock,
3925
+ SolidGlobe,
3926
+ SolidInfoCircle,
3927
+ SolidMapPin,
3928
+ SolidShieldCheck,
3929
+ Sparkline,
3930
+ StatNumber,
1274
3931
  StatTile,
3932
+ StatusBadge,
3933
+ StatusChip,
3934
+ StatusDot,
1275
3935
  Stepper,
1276
3936
  TableCellBadge,
1277
3937
  TableCellLeadText,
1278
3938
  TableCellProgress,
1279
- TableCellStatusPill,
1280
3939
  TableCellText,
3940
+ Tabs,
3941
+ TagPill,
1281
3942
  Textarea,
1282
- Toggle
3943
+ TileGrid,
3944
+ Toggle,
3945
+ TrailChip,
3946
+ TrendLabel,
3947
+ UserStatusPill,
3948
+ WidgetFooter,
3949
+ WidgetHeader,
3950
+ WidgetTitle,
3951
+ cn,
3952
+ getScoreTone,
3953
+ resolveChartColor,
3954
+ useOverlayDismiss
1283
3955
  };
1284
3956
  //# sourceMappingURL=index.js.map