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