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