sangam-ui 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,2890 @@
1
+ // src/primitives/button.tsx
2
+ import * as React2 from "react";
3
+ import { Slot } from "@radix-ui/react-slot";
4
+ import { cva as cva2 } from "class-variance-authority";
5
+ import { cn as cn2 } from "@esds-sangam/utils";
6
+ import { semanticColorsResolved } from "@esds-sangam/tokens";
7
+
8
+ // src/primitives/loader.tsx
9
+ import * as React from "react";
10
+ import { cva } from "class-variance-authority";
11
+ import { cn } from "@esds-sangam/utils";
12
+ import { jsx } from "react/jsx-runtime";
13
+ var LOADER_COLOR = "#111111";
14
+ var LOADER_COLOR_TRANSPARENT = "#11111100";
15
+ var loaderVariants = cva(
16
+ [
17
+ "rounded-full shrink-0",
18
+ "animate-spin [animation-duration:600ms] [animation-delay:1s] [animation-timing-function:linear]",
19
+ // Ring shape via radial mask; inner % = hole, rest = visible ring (thicker for visibility, especially extra small)
20
+ "[mask:radial-gradient(circle,transparent_50%,black_50%)] [-webkit-mask:radial-gradient(circle,transparent_50%,black_50%)]"
21
+ ],
22
+ {
23
+ variants: {
24
+ size: {
25
+ big: "h-10 w-10",
26
+ // 40×40
27
+ medium: "h-8 w-8",
28
+ // 32×32
29
+ small: "h-6 w-6",
30
+ // 24×24
31
+ extraSmall: "h-4 w-4"
32
+ // 16×16
33
+ }
34
+ },
35
+ defaultVariants: {
36
+ size: "big"
37
+ }
38
+ }
39
+ );
40
+ var Loader = React.forwardRef(
41
+ ({ className, size, "aria-label": ariaLabel, color, colorTransparent, style, ...props }, ref) => {
42
+ const gradientColor = color ?? LOADER_COLOR;
43
+ const gradientTransparent = colorTransparent ?? (color ? `${color}00` : LOADER_COLOR_TRANSPARENT);
44
+ return /* @__PURE__ */ jsx(
45
+ "div",
46
+ {
47
+ ref,
48
+ role: "status",
49
+ "aria-label": ariaLabel ?? "Loading",
50
+ "aria-live": "polite",
51
+ className: cn(loaderVariants({ size }), className),
52
+ style: {
53
+ background: `conic-gradient(from 0deg, ${gradientColor}, ${gradientTransparent})`,
54
+ ...style
55
+ },
56
+ ...props
57
+ }
58
+ );
59
+ }
60
+ );
61
+ Loader.displayName = "Loader";
62
+
63
+ // src/primitives/button.tsx
64
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
65
+ var buttonVariants = cva2(
66
+ // Base styles - applied to ALL buttons
67
+ [
68
+ "inline-flex items-center justify-center gap-2",
69
+ "font-medium",
70
+ "transition-colors duration-200 ease-out",
71
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
72
+ "whitespace-nowrap",
73
+ "rounded-sm"
74
+ ],
75
+ {
76
+ variants: {
77
+ // Variant: Visual style per Figma design
78
+ variant: {
79
+ // Primary: semantic background/text (neutral inverse primary)
80
+ primary: [
81
+ "bg-semantic-background-neutralInverse-primary text-semantic-text-neutralInverse-primary",
82
+ "hover:bg-semantic-background-neutralInverse-secondary",
83
+ "focus-visible:ring-semantic-border-neutral-primary focus-visible:ring-offset-0",
84
+ "disabled:bg-semantic-background-neutral-disabled disabled:text-semantic-text-neutral-disabled disabled:pointer-events-none",
85
+ "data-[loading=true]:!bg-semantic-background-neutralInverse-primary data-[loading=true]:!text-semantic-text-neutralInverse-primary"
86
+ ],
87
+ // Secondary: border #111111 (semantic border neutralInverse tertiary), hover: border removed, bg #EBEBEB (semantic background neutral tertiary)
88
+ secondary: [
89
+ "bg-semantic-background-neutral-primary border border-semantic-border-neutralInverse-tertiary text-semantic-text-neutral-primary",
90
+ "hover:border-transparent hover:bg-semantic-background-neutral-tertiary",
91
+ "focus-visible:border-2 focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:border-semantic-border-neutralInverse-tertiary focus-visible:-m-px",
92
+ "disabled:bg-semantic-background-neutral-disabled disabled:text-semantic-text-neutral-disabled disabled:border-semantic-border-neutral-disabled disabled:pointer-events-none"
93
+ ],
94
+ // Danger: semantic error default/hover
95
+ danger: [
96
+ "bg-semantic-background-semantic-error-default text-semantic-text-semantic-error-default",
97
+ "hover:bg-semantic-background-semantic-error-hover",
98
+ "focus-visible:ring-semantic-border-semantic-error-default",
99
+ "disabled:bg-semantic-background-neutral-disabled disabled:text-semantic-text-neutral-disabled disabled:pointer-events-none",
100
+ "data-[loading=true]:!bg-semantic-background-semantic-error-default data-[loading=true]:!text-semantic-text-semantic-error-default"
101
+ ],
102
+ // Link: semantic info default text
103
+ link: [
104
+ "bg-transparent text-semantic-background-semantic-info-default underline-offset-4",
105
+ "hover:underline",
106
+ "focus-visible:ring-semantic-border-semantic-info-default",
107
+ "disabled:text-semantic-text-neutral-disabled disabled:pointer-events-none"
108
+ ]
109
+ },
110
+ // Size: Height, padding, font size (from Figma specs)
111
+ size: {
112
+ // Small: 32px height
113
+ small: [
114
+ "h-8",
115
+ // 32px height
116
+ "px-3 py-1.5",
117
+ // padding: 12px horizontal, 6px vertical
118
+ "text-sm"
119
+ // 14px font size
120
+ ],
121
+ // Big: 40px height
122
+ big: [
123
+ "h-10",
124
+ // 40px height
125
+ "px-4 py-2",
126
+ // padding: 16px horizontal, 8px vertical
127
+ "text-base"
128
+ // 16px font size
129
+ ]
130
+ },
131
+ /**
132
+ * Icon-only: Circular button controlled by boolean prop
133
+ * - When true, button becomes fully rounded.
134
+ * - Height is still driven by `size` (small/big).
135
+ * - Width is applied via compoundVariants below:
136
+ * - size="small" → w-8 (32px)
137
+ * - size="big" → w-10 (40px)
138
+ */
139
+ iconOnly: {
140
+ false: "",
141
+ true: "rounded-full"
142
+ }
143
+ },
144
+ defaultVariants: {
145
+ variant: "primary",
146
+ size: "big"
147
+ },
148
+ compoundVariants: [
149
+ {
150
+ iconOnly: true,
151
+ size: "big",
152
+ class: "w-10"
153
+ },
154
+ {
155
+ iconOnly: true,
156
+ size: "small",
157
+ class: "w-8"
158
+ }
159
+ ]
160
+ }
161
+ );
162
+ var BUTTON_LOADER_COLOR = semanticColorsResolved.text.neutralInverse.primary;
163
+ var BUTTON_LOADER_COLOR_TRANSPARENT = `${BUTTON_LOADER_COLOR}00`;
164
+ var Button = React2.forwardRef(
165
+ ({
166
+ className,
167
+ variant,
168
+ size,
169
+ iconOnly = false,
170
+ asChild = false,
171
+ icon,
172
+ leadingIcon = false,
173
+ trailingIcon = false,
174
+ children,
175
+ loading = false,
176
+ disabled,
177
+ "aria-busy": ariaBusy,
178
+ "aria-disabled": ariaDisabled,
179
+ ...props
180
+ }, ref) => {
181
+ const isDisabled = disabled ?? loading;
182
+ const showLoader = loading && !asChild;
183
+ const loaderSize = size === "small" ? "extraSmall" : "small";
184
+ const iconPixelSize = size === "small" ? 16 : 20;
185
+ const iconSizeClass = size === "small" ? "h-4 w-4" : "h-5 w-5";
186
+ const loaderColor = variant === "primary" || variant === "danger" ? { color: BUTTON_LOADER_COLOR, colorTransparent: BUTTON_LOADER_COLOR_TRANSPARENT } : void 0;
187
+ const Comp = asChild && !showLoader ? Slot : "button";
188
+ const hasIcon = !!icon;
189
+ const showIconOnly = iconOnly && hasIcon;
190
+ const showLeadingIcon = !showIconOnly && hasIcon && leadingIcon;
191
+ const showTrailingIcon = !showIconOnly && hasIcon && !leadingIcon && trailingIcon;
192
+ let renderIcon = icon;
193
+ if (React2.isValidElement(icon)) {
194
+ const isDomElement = typeof icon.type === "string";
195
+ const existingClassName = icon.props.className;
196
+ const mergedClassName = cn2(iconSizeClass, existingClassName);
197
+ renderIcon = React2.cloneElement(
198
+ icon,
199
+ isDomElement ? { className: mergedClassName } : { size: iconPixelSize, className: mergedClassName }
200
+ );
201
+ }
202
+ return /* @__PURE__ */ jsx2(
203
+ Comp,
204
+ {
205
+ className: cn2(buttonVariants({ variant, size, iconOnly, className })),
206
+ ref,
207
+ disabled: isDisabled,
208
+ "data-loading": showLoader ? true : void 0,
209
+ "aria-busy": showLoader ? true : ariaBusy,
210
+ "aria-disabled": showLoader ? true : ariaDisabled,
211
+ ...props,
212
+ children: showLoader ? /* @__PURE__ */ jsx2(
213
+ Loader,
214
+ {
215
+ size: loaderSize,
216
+ "aria-label": "Loading",
217
+ className: "shrink-0",
218
+ ...loaderColor ?? {}
219
+ }
220
+ ) : showIconOnly ? /* @__PURE__ */ jsx2("span", { className: "inline-flex shrink-0", children: renderIcon }) : /* @__PURE__ */ jsxs(Fragment, { children: [
221
+ showLeadingIcon && /* @__PURE__ */ jsx2("span", { className: "inline-flex shrink-0", children: renderIcon }),
222
+ children,
223
+ showTrailingIcon && /* @__PURE__ */ jsx2("span", { className: "inline-flex shrink-0", children: renderIcon })
224
+ ] })
225
+ }
226
+ );
227
+ }
228
+ );
229
+ Button.displayName = "Button";
230
+
231
+ // src/primitives/toggle.tsx
232
+ import * as React3 from "react";
233
+ import * as SwitchPrimitives from "@radix-ui/react-switch";
234
+ import { cva as cva3 } from "class-variance-authority";
235
+ import { cn as cn3 } from "@esds-sangam/utils";
236
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
237
+ var toggleVariants = cva3(
238
+ [
239
+ "peer inline-flex shrink-0 cursor-pointer items-center rounded-full",
240
+ "transition-all duration-200 ease-out",
241
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-800 focus-visible:ring-offset-2",
242
+ "disabled:cursor-not-allowed disabled:opacity-100",
243
+ // Default unchecked state
244
+ "bg-neutral-400",
245
+ // Hover effect for unchecked state (border appears on hover)
246
+ "border-1 border-transparent hover:border-neutral-700",
247
+ // Checked state
248
+ "data-[state=checked]:bg-neutral-1100",
249
+ // Remove hover border when checked
250
+ "data-[state=checked]:hover:border-1 data-[state=checked]:hover:border-neutral-1100",
251
+ // Disabled states - MUST come after checked to override
252
+ "disabled:bg-neutral-200",
253
+ "disabled:hover:border-1 disabled:hover:border-neutral-200",
254
+ // Force disabled color even when checked
255
+ "disabled:data-[state=checked]:bg-neutral-200",
256
+ "disabled:data-[state=checked]:border-1 disabled:data-[state=checked]:border-neutral-200"
257
+ ],
258
+ {
259
+ variants: {
260
+ size: {
261
+ big: "h-7 w-14",
262
+ // 28px height, 56px width
263
+ small: "h-6 w-11"
264
+ // 24px height, 44px width
265
+ }
266
+ },
267
+ defaultVariants: {
268
+ size: "big"
269
+ }
270
+ }
271
+ );
272
+ var toggleThumbVariants = cva3(
273
+ [
274
+ "pointer-events-none block rounded-full bg-white shadow-sm",
275
+ "transition-transform duration-200 ease-out",
276
+ // Disabled state
277
+ "data-[disabled]:bg-neutral-500"
278
+ ],
279
+ {
280
+ variants: {
281
+ size: {
282
+ big: [
283
+ "h-5 w-5",
284
+ // 20px circle
285
+ "data-[state=unchecked]:translate-x-1",
286
+ // 4px from left
287
+ "data-[state=checked]:translate-x-8"
288
+ // 32px from left (56-20-4=32)
289
+ ],
290
+ small: [
291
+ "h-4 w-4",
292
+ // 16px circle
293
+ "data-[state=unchecked]:translate-x-1",
294
+ // 4px from left
295
+ "data-[state=checked]:translate-x-6"
296
+ // 24px from left (44-16-4=24)
297
+ ]
298
+ }
299
+ },
300
+ defaultVariants: {
301
+ size: "big"
302
+ }
303
+ }
304
+ );
305
+ var Toggle = React3.forwardRef(
306
+ ({ className, size = "big", title, subtext, ...props }, ref) => {
307
+ const hasLabel = title != null || subtext != null;
308
+ const switchEl = /* @__PURE__ */ jsx3(
309
+ SwitchPrimitives.Root,
310
+ {
311
+ className: cn3(toggleVariants({ size }), !hasLabel && className),
312
+ ...props,
313
+ ref,
314
+ children: /* @__PURE__ */ jsx3(
315
+ SwitchPrimitives.Thumb,
316
+ {
317
+ className: cn3(toggleThumbVariants({ size })),
318
+ "data-disabled": props.disabled ? "" : void 0
319
+ }
320
+ )
321
+ }
322
+ );
323
+ if (!hasLabel) return switchEl;
324
+ return /* @__PURE__ */ jsxs2("label", { className: cn3("inline-flex cursor-pointer items-center gap-3", className), children: [
325
+ switchEl,
326
+ /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-0", children: [
327
+ title != null && /* @__PURE__ */ jsx3("span", { className: "text-sm font-medium leading-6 text-neutral-1100", children: title }),
328
+ subtext != null && /* @__PURE__ */ jsx3("span", { className: "text-xs font-normal leading-4 text-neutral-600", children: subtext })
329
+ ] })
330
+ ] });
331
+ }
332
+ );
333
+ Toggle.displayName = "Toggle";
334
+
335
+ // src/primitives/checkbox.tsx
336
+ import * as React4 from "react";
337
+ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
338
+ import { Check } from "lucide-react";
339
+ import { cva as cva4 } from "class-variance-authority";
340
+ import { cn as cn4 } from "@esds-sangam/utils";
341
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
342
+ var checkboxRootVariants = cva4(
343
+ [
344
+ "peer group flex shrink-0 items-center justify-center",
345
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-800 focus-visible:ring-offset-2",
346
+ "disabled:cursor-not-allowed"
347
+ ],
348
+ {
349
+ variants: {
350
+ size: {
351
+ big: "h-6 w-6",
352
+ // 24px outer
353
+ small: "h-5 w-5"
354
+ // 20px outer
355
+ }
356
+ },
357
+ defaultVariants: {
358
+ size: "big"
359
+ }
360
+ }
361
+ );
362
+ var checkboxInnerVariants = cva4(
363
+ [
364
+ "flex shrink-0 items-center justify-center rounded-xs border transition-all duration-200 ease-out",
365
+ // Default unchecked
366
+ "border-neutral-400 bg-transparent",
367
+ "group-hover:border-neutral-700",
368
+ "group-data-[state=checked]:bg-neutral-1100 group-data-[state=checked]:border-neutral-1100",
369
+ "group-data-[state=checked]:group-hover:border-neutral-1100",
370
+ "group-disabled:border-neutral-200 group-disabled:group-hover:border-neutral-200",
371
+ "group-disabled:group-data-[state=checked]:bg-neutral-200 group-disabled:group-data-[state=checked]:border-neutral-200"
372
+ ],
373
+ {
374
+ variants: {
375
+ size: {
376
+ big: "h-5 w-5",
377
+ // 20px inner (2px gap inside 24px)
378
+ small: "h-4 w-4"
379
+ // 16px inner (2px gap inside 20px)
380
+ }
381
+ },
382
+ defaultVariants: {
383
+ size: "big"
384
+ }
385
+ }
386
+ );
387
+ var checkboxIndicatorVariants = cva4(
388
+ ["flex items-center justify-center text-current transition-colors duration-200 ease-out"],
389
+ {
390
+ variants: {
391
+ size: {
392
+ big: "h-5 w-5",
393
+ small: "h-4 w-4"
394
+ }
395
+ },
396
+ defaultVariants: {
397
+ size: "big"
398
+ }
399
+ }
400
+ );
401
+ var Checkbox = React4.forwardRef(
402
+ ({ className, size = "big", disabled, title, subtext, ...props }, ref) => {
403
+ const hasLabel = title != null || subtext != null;
404
+ const checkboxEl = /* @__PURE__ */ jsx4(
405
+ CheckboxPrimitive.Root,
406
+ {
407
+ ref,
408
+ className: cn4(checkboxRootVariants({ size }), !hasLabel && className),
409
+ disabled,
410
+ ...props,
411
+ children: /* @__PURE__ */ jsx4("div", { className: cn4(checkboxInnerVariants({ size })), "aria-hidden": true, children: /* @__PURE__ */ jsx4(CheckboxPrimitive.Indicator, { className: cn4(checkboxIndicatorVariants({ size })), children: /* @__PURE__ */ jsx4(
412
+ Check,
413
+ {
414
+ className: cn4(
415
+ size === "big" ? "h-4 w-4" : "h-3 w-3",
416
+ "text-white",
417
+ disabled && "text-neutral-500"
418
+ ),
419
+ strokeWidth: 3
420
+ }
421
+ ) }) })
422
+ }
423
+ );
424
+ if (!hasLabel) return checkboxEl;
425
+ return /* @__PURE__ */ jsxs3("label", { className: cn4("inline-flex cursor-pointer items-center gap-3", className), children: [
426
+ checkboxEl,
427
+ /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-0", children: [
428
+ title != null && /* @__PURE__ */ jsx4("span", { className: "text-sm font-medium leading-6 text-neutral-1100", children: title }),
429
+ subtext != null && /* @__PURE__ */ jsx4("span", { className: "text-xs font-normal leading-4 text-neutral-600", children: subtext })
430
+ ] })
431
+ ] });
432
+ }
433
+ );
434
+ Checkbox.displayName = "Checkbox";
435
+
436
+ // src/primitives/radio.tsx
437
+ import * as React5 from "react";
438
+ import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
439
+ import { cva as cva5 } from "class-variance-authority";
440
+ import { cn as cn5 } from "@esds-sangam/utils";
441
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
442
+ var radioVariants = cva5(
443
+ [
444
+ "aspect-square shrink-0 rounded-full border transition-all duration-200 ease-out flex items-center justify-center",
445
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-800 focus-visible:ring-offset-2",
446
+ "disabled:cursor-not-allowed",
447
+ // Default unchecked state (not selected)
448
+ "border-neutral-400 bg-transparent",
449
+ // Hover effect for unchecked state
450
+ "hover:border-neutral-700",
451
+ // Checked state (selected)
452
+ "data-[state=checked]:border-neutral-1100",
453
+ // No border change on hover when checked
454
+ "data-[state=checked]:hover:border-neutral-1100",
455
+ // Disabled states
456
+ "disabled:border-neutral-200",
457
+ "disabled:hover:border-neutral-200",
458
+ // Disabled + checked state
459
+ "disabled:data-[state=checked]:border-neutral-200"
460
+ ],
461
+ {
462
+ variants: {
463
+ size: {
464
+ big: "h-6 w-6",
465
+ // 24px
466
+ small: "h-5 w-5"
467
+ // 20px
468
+ }
469
+ },
470
+ defaultVariants: {
471
+ size: "big"
472
+ }
473
+ }
474
+ );
475
+ var radioIndicatorVariants = cva5(["flex items-center justify-center"], {
476
+ variants: {
477
+ size: {
478
+ big: "h-6 w-6",
479
+ // 24px container
480
+ small: "h-5 w-5"
481
+ // 20px container
482
+ }
483
+ },
484
+ defaultVariants: {
485
+ size: "big"
486
+ }
487
+ });
488
+ var radioDotVariants = cva5(
489
+ [
490
+ "rounded-full transition-colors duration-200 ease-out flex items-center justify-center",
491
+ // Default selected state - black dot
492
+ "bg-neutral-1100"
493
+ ],
494
+ {
495
+ variants: {
496
+ size: {
497
+ big: "h-2.5 w-2.5",
498
+ // 12px inner dot for 24px radio
499
+ small: "h-[9px] w-[9px]"
500
+ // 10px inner dot for 20px radio
501
+ },
502
+ disabled: {
503
+ true: "bg-neutral-500",
504
+ // Gray dot when disabled
505
+ false: "bg-neutral-1100"
506
+ // Black dot when enabled
507
+ }
508
+ },
509
+ defaultVariants: {
510
+ size: "big",
511
+ disabled: false
512
+ }
513
+ }
514
+ );
515
+ var RadioGroup = React5.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx5(RadioGroupPrimitive.Root, { className: cn5("grid gap-2", className), ...props, ref }));
516
+ RadioGroup.displayName = "RadioGroup";
517
+ var Radio = React5.forwardRef(
518
+ ({ className, size = "big", disabled, title, subtext, ...props }, ref) => {
519
+ const hasLabel = title != null || subtext != null;
520
+ const radioEl = /* @__PURE__ */ jsx5(
521
+ RadioGroupPrimitive.Item,
522
+ {
523
+ ref,
524
+ className: cn5(radioVariants({ size }), !hasLabel && className),
525
+ disabled,
526
+ ...props,
527
+ children: /* @__PURE__ */ jsx5(RadioGroupPrimitive.Indicator, { className: cn5(radioIndicatorVariants({ size })), children: /* @__PURE__ */ jsx5("span", { className: cn5(radioDotVariants({ size, disabled: !!disabled })) }) })
528
+ }
529
+ );
530
+ if (!hasLabel) return radioEl;
531
+ return /* @__PURE__ */ jsxs4("label", { className: cn5("inline-flex cursor-pointer items-center gap-3", className), children: [
532
+ radioEl,
533
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-0", children: [
534
+ title != null && /* @__PURE__ */ jsx5("span", { className: "text-sm font-medium leading-6 text-neutral-1100", children: title }),
535
+ subtext != null && /* @__PURE__ */ jsx5("span", { className: "text-xs font-normal leading-4 text-neutral-600", children: subtext })
536
+ ] })
537
+ ] });
538
+ }
539
+ );
540
+ Radio.displayName = "Radio";
541
+
542
+ // src/primitives/input.tsx
543
+ import * as React6 from "react";
544
+ import { cva as cva6 } from "class-variance-authority";
545
+ import { cn as cn6 } from "@esds-sangam/utils";
546
+ import { Info, TickmarkFilled, WarningFilled } from "@esds-sangam/icons";
547
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
548
+ var inputVariants = cva6(
549
+ [
550
+ // Base styles
551
+ "w-full rounded-sm border transition-all duration-200 ease-out",
552
+ "font-sans text-sm leading-6 font-normal h-8",
553
+ // 14px font, 24px line-height, 400 weight
554
+ "px-3 py-1",
555
+ // 12px horizontal, 4px vertical
556
+ "outline-none",
557
+ // Default state
558
+ "bg-white border-neutral-400 text-neutral-600",
559
+ // Placeholder
560
+ "placeholder:text-sm",
561
+ // 14px font
562
+ "placeholder:leading-6",
563
+ // 24px line-height
564
+ // Hover state
565
+ "hover:border-neutral-700",
566
+ // Focus (Active/Typing) state
567
+ "focus:border-neutral-700 focus:text-neutral-1100",
568
+ // Caret (cursor) color
569
+ "caret-neutral-1100",
570
+ // Disabled state
571
+ "disabled:bg-neutral-200 disabled:border-neutral-200 disabled:text-neutral-500",
572
+ "disabled:cursor-not-allowed",
573
+ // Remove default focus ring
574
+ "focus-visible:outline-none"
575
+ ],
576
+ {
577
+ variants: {
578
+ variant: {
579
+ default: "",
580
+ error: ["border-red-800 focus:border-red-800", "text-neutral-1100 focus:text-neutral-1100"],
581
+ success: [
582
+ "border-green-800 focus:border-green-800",
583
+ "text-neutral-1100 focus:text-neutral-1100"
584
+ ]
585
+ },
586
+ // Filled state (when input has value); filled disabled keeps text #111111
587
+ filled: {
588
+ true: "text-neutral-1100 disabled:text-neutral-1100",
589
+ false: ""
590
+ }
591
+ },
592
+ defaultVariants: {
593
+ variant: "default",
594
+ filled: false
595
+ }
596
+ }
597
+ );
598
+ var labelVariants = cva6([
599
+ // Base label styles matching Figma specs
600
+ "block text-xs font-medium leading-4 tracking-normal",
601
+ "text-neutral-1100 font-sans mb-2"
602
+ ]);
603
+ var Label = React6.forwardRef(
604
+ ({ children, required, className, endAdornment, ...props }, ref) => /* @__PURE__ */ jsxs5(
605
+ "label",
606
+ {
607
+ ref,
608
+ className: cn6(labelVariants(), "flex items-center gap-1", className),
609
+ ...props,
610
+ children: [
611
+ children,
612
+ required && /* @__PURE__ */ jsx6("span", { className: "text-red-700 ml-0.5", children: "*" }),
613
+ endAdornment
614
+ ]
615
+ }
616
+ )
617
+ );
618
+ Label.displayName = "Label";
619
+ var Input = React6.forwardRef(
620
+ ({
621
+ className,
622
+ type = "text",
623
+ label,
624
+ required,
625
+ error,
626
+ success,
627
+ helperText,
628
+ helperError,
629
+ disabled,
630
+ value,
631
+ showLabelIcon = false,
632
+ showHelperIcon = false,
633
+ trailingIcon,
634
+ ctaLabel,
635
+ onCtaClick,
636
+ ...props
637
+ }, ref) => {
638
+ const variant = error ? "error" : success ? "success" : "default";
639
+ const isFilled = !!value && value.toString().length > 0;
640
+ const inputId = props.id || `input-${React6.useId()}`;
641
+ const helperTextId = helperText ? `${inputId}-helper` : void 0;
642
+ const helperTextColor = error ? "text-red-800" : success ? "text-green-800" : "text-neutral-600";
643
+ const HelperIcon = error ? WarningFilled : success ? TickmarkFilled : showHelperIcon ? Info : null;
644
+ const hasTrailing = Boolean(trailingIcon);
645
+ const hasCta = Boolean(ctaLabel);
646
+ const inputElement = /* @__PURE__ */ jsx6(
647
+ "input",
648
+ {
649
+ id: inputId,
650
+ ref,
651
+ type,
652
+ disabled,
653
+ value,
654
+ "aria-describedby": helperTextId,
655
+ "aria-invalid": error ? "true" : void 0,
656
+ className: cn6(
657
+ inputVariants({ variant, filled: isFilled }),
658
+ (hasTrailing || hasCta) && "min-w-0 flex-1 w-auto border-0 rounded-none focus:ring-0",
659
+ hasTrailing && "pr-2",
660
+ hasCta && "pr-2",
661
+ !hasTrailing && !hasCta && className
662
+ ),
663
+ ...props
664
+ }
665
+ );
666
+ return /* @__PURE__ */ jsxs5("div", { className: "w-full", children: [
667
+ label && /* @__PURE__ */ jsx6(
668
+ Label,
669
+ {
670
+ htmlFor: inputId,
671
+ required,
672
+ endAdornment: showLabelIcon ? /* @__PURE__ */ jsx6(Info, { size: 16, className: "!text-neutral-600 shrink-0", "aria-hidden": "true" }) : void 0,
673
+ children: label
674
+ }
675
+ ),
676
+ hasTrailing ? /* @__PURE__ */ jsxs5(
677
+ "div",
678
+ {
679
+ className: cn6(
680
+ "flex items-center w-full overflow-hidden rounded-sm border transition-all duration-200 ease-out",
681
+ "bg-white font-sans text-sm leading-6 font-normal",
682
+ "border-neutral-400 hover:border-neutral-700",
683
+ "focus-within:border-neutral-700",
684
+ error && "border-red-800 hover:border-red-800 focus-within:border-red-800",
685
+ success && "border-green-800 hover:border-green-800 focus-within:border-green-800",
686
+ disabled && "bg-neutral-200 border-neutral-200",
687
+ className
688
+ ),
689
+ children: [
690
+ inputElement,
691
+ /* @__PURE__ */ jsx6(
692
+ "div",
693
+ {
694
+ className: cn6(
695
+ "flex items-center justify-center shrink-0 pl-1 pr-3 py-1 min-h-[32px]",
696
+ "text-neutral-1100",
697
+ disabled && "text-neutral-500"
698
+ ),
699
+ "aria-hidden": "true",
700
+ children: trailingIcon
701
+ }
702
+ )
703
+ ]
704
+ }
705
+ ) : hasCta ? /* @__PURE__ */ jsxs5(
706
+ "div",
707
+ {
708
+ className: cn6(
709
+ "flex items-center w-full overflow-hidden rounded-sm border transition-all duration-200 ease-out",
710
+ "bg-white font-sans text-sm leading-6 font-normal",
711
+ "border-neutral-400 hover:border-neutral-700",
712
+ "focus-within:border-neutral-700",
713
+ error && "border-red-800 hover:border-red-800 focus-within:border-red-800",
714
+ success && "border-green-800 hover:border-green-800 focus-within:border-green-800",
715
+ disabled && "bg-neutral-200 border-neutral-200",
716
+ className
717
+ ),
718
+ children: [
719
+ inputElement,
720
+ /* @__PURE__ */ jsx6(
721
+ "button",
722
+ {
723
+ type: "button",
724
+ onClick: onCtaClick,
725
+ disabled,
726
+ className: "shrink-0 text-blue-600 text-sm font-normal hover:underline pl-2 pr-3 py-1 focus:outline-none focus-visible:ring-0 rounded",
727
+ children: ctaLabel
728
+ }
729
+ )
730
+ ]
731
+ }
732
+ ) : inputElement,
733
+ helperText && /* @__PURE__ */ jsxs5(
734
+ "p",
735
+ {
736
+ id: helperTextId,
737
+ className: cn6(
738
+ "mt-2 flex items-center gap-1 text-xs leading-4 font-normal",
739
+ helperTextColor
740
+ ),
741
+ children: [
742
+ HelperIcon && /* @__PURE__ */ jsx6(
743
+ HelperIcon,
744
+ {
745
+ size: 16,
746
+ className: cn6(
747
+ error ? "text-red-800" : success ? "text-green-800" : "text-neutral-600"
748
+ ),
749
+ "aria-hidden": "true"
750
+ }
751
+ ),
752
+ helperText
753
+ ]
754
+ }
755
+ )
756
+ ] });
757
+ }
758
+ );
759
+ Input.displayName = "Input";
760
+
761
+ // src/primitives/dropdown.tsx
762
+ import * as React7 from "react";
763
+ import * as SelectPrimitive from "@radix-ui/react-select";
764
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
765
+ import { cva as cva7 } from "class-variance-authority";
766
+ import { cn as cn7 } from "@esds-sangam/utils";
767
+ import {
768
+ ChevronDown,
769
+ ChevronUp,
770
+ Close,
771
+ Tickmark,
772
+ Info as Info2,
773
+ InfoFilled as InfoFilled2,
774
+ WarningFilled as WarningFilled2
775
+ } from "@esds-sangam/icons";
776
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
777
+ var DROPDOWN_TRIGGER_HEIGHT = 32;
778
+ var DROPDOWN_TRIGGER_MIN_WIDTH = 264;
779
+ var dropdownTriggerVariants = cva7(
780
+ [
781
+ "flex items-center justify-between w-full rounded-sm border transition-all duration-200 ease-out outline-none",
782
+ "font-sans text-sm leading-6 font-normal",
783
+ "px-3 py-1 min-h-[32px] h-8",
784
+ "bg-white border-neutral-400 text-neutral-1100",
785
+ "hover:border-neutral-700",
786
+ "focus:border-neutral-700",
787
+ "data-[placeholder]:text-neutral-600",
788
+ "data-[state=open]:border-neutral-700 data-[state=open]:text-neutral-600",
789
+ "disabled:bg-neutral-200 disabled:border-neutral-200 disabled:text-neutral-500 disabled:cursor-not-allowed",
790
+ "focus-visible:outline-none"
791
+ ],
792
+ {
793
+ variants: {
794
+ error: {
795
+ true: "border-red-800 hover:border-red-800 focus:border-red-800 data-[state=open]:border-red-800",
796
+ false: ""
797
+ }
798
+ },
799
+ defaultVariants: {
800
+ error: false
801
+ }
802
+ }
803
+ );
804
+ var dropdownContentVariants = cva7([
805
+ "z-50 overflow-hidden rounded-sm border bg-white p-2",
806
+ "border-neutral-200 shadow-elevation-bottom-sm",
807
+ "text-neutral-1100 text-sm font-normal leading-6",
808
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
809
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
810
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
811
+ "data-[side=bottom]:slide-in-from-top-2"
812
+ ]);
813
+ var dropdownItemVariants = cva7([
814
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-2 pl-3 pr-8 text-sm font-normal leading-6 outline-none",
815
+ "text-neutral-1100",
816
+ "data-[highlighted]:bg-neutral-100",
817
+ "data-[disabled]:pointer-events-none data-[disabled]:text-neutral-500"
818
+ ]);
819
+ var Dropdown = React7.forwardRef(
820
+ ({
821
+ label,
822
+ required,
823
+ placeholder = "Input",
824
+ options,
825
+ width,
826
+ error = false,
827
+ disabled,
828
+ showLabelIcon = false,
829
+ helperText,
830
+ showHelperIcon = false,
831
+ ...rootProps
832
+ }, ref) => {
833
+ const triggerId = React7.useId();
834
+ const isDisabled = disabled ?? false;
835
+ const helperTextId = helperText ? `${triggerId}-helper` : void 0;
836
+ const helperTextColor = error ? "text-red-800" : "text-neutral-500";
837
+ const HelperIcon = error ? WarningFilled2 : showHelperIcon ? Info2 : null;
838
+ return /* @__PURE__ */ jsxs6("div", { className: "w-full flex flex-col gap-2", children: [
839
+ label && /* @__PURE__ */ jsx7(
840
+ Label,
841
+ {
842
+ htmlFor: triggerId,
843
+ required,
844
+ endAdornment: showLabelIcon ? /* @__PURE__ */ jsx7(Info2, { size: 16, className: "shrink-0 !text-neutral-600", "aria-hidden": "true" }) : void 0,
845
+ className: "!m-0",
846
+ children: label
847
+ }
848
+ ),
849
+ /* @__PURE__ */ jsxs6(SelectPrimitive.Root, { ...rootProps, disabled: isDisabled, required, children: [
850
+ /* @__PURE__ */ jsxs6(
851
+ SelectPrimitive.Trigger,
852
+ {
853
+ ref,
854
+ id: triggerId,
855
+ className: cn7("group", dropdownTriggerVariants({ error })),
856
+ style: {
857
+ width: width ?? "100%",
858
+ minWidth: DROPDOWN_TRIGGER_MIN_WIDTH,
859
+ minHeight: DROPDOWN_TRIGGER_HEIGHT
860
+ },
861
+ children: [
862
+ /* @__PURE__ */ jsx7(SelectPrimitive.Value, { placeholder }),
863
+ /* @__PURE__ */ jsx7(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsxs6(Fragment2, { children: [
864
+ /* @__PURE__ */ jsx7(ChevronDown, { size: 16, className: "shrink-0 group-data-[state=open]:hidden" }),
865
+ /* @__PURE__ */ jsx7(ChevronUp, { size: 16, className: "hidden shrink-0 group-data-[state=open]:block" })
866
+ ] }) })
867
+ ]
868
+ }
869
+ ),
870
+ /* @__PURE__ */ jsx7(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx7(
871
+ SelectPrimitive.Content,
872
+ {
873
+ className: cn7(
874
+ dropdownContentVariants(),
875
+ "min-w-[var(--radix-select-trigger-width)] flex flex-col gap-2"
876
+ ),
877
+ position: "popper",
878
+ side: "bottom",
879
+ sideOffset: 4,
880
+ avoidCollisions: false,
881
+ children: /* @__PURE__ */ jsx7(SelectPrimitive.Viewport, { className: "flex flex-col gap-2", children: options.map((opt) => /* @__PURE__ */ jsxs6(
882
+ SelectPrimitive.Item,
883
+ {
884
+ value: opt.value,
885
+ disabled: opt.disabled,
886
+ className: dropdownItemVariants(),
887
+ textValue: opt.label,
888
+ children: [
889
+ /* @__PURE__ */ jsx7(SelectPrimitive.ItemText, { children: opt.label }),
890
+ /* @__PURE__ */ jsx7(SelectPrimitive.ItemIndicator, { className: "absolute right-2 flex h-4 w-4 items-center justify-center", children: /* @__PURE__ */ jsx7(Tickmark, { size: 16, color: "var(--color-neutral-1100)" }) })
891
+ ]
892
+ },
893
+ opt.value
894
+ )) })
895
+ }
896
+ ) })
897
+ ] }),
898
+ helperText && /* @__PURE__ */ jsxs6(
899
+ "p",
900
+ {
901
+ id: helperTextId,
902
+ className: cn7("flex items-center gap-1 text-xs leading-4 font-normal", helperTextColor),
903
+ children: [
904
+ HelperIcon && /* @__PURE__ */ jsx7(
905
+ HelperIcon,
906
+ {
907
+ size: 16,
908
+ className: cn7(error ? "text-red-800" : "text-neutral-1100", "shrink-0"),
909
+ "aria-hidden": "true"
910
+ }
911
+ ),
912
+ helperText
913
+ ]
914
+ }
915
+ )
916
+ ] });
917
+ }
918
+ );
919
+ Dropdown.displayName = "Dropdown";
920
+ var multiSelectContentVariants = cva7([
921
+ "z-50 min-w-[var(--radix-dropdown-menu-trigger-width)] overflow-hidden rounded-sm border bg-white p-2 flex flex-col gap-2",
922
+ "border-neutral-200 shadow-elevation-bottom-sm",
923
+ "text-neutral-1100 text-sm font-normal leading-6",
924
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
925
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
926
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
927
+ "data-[side=bottom]:slide-in-from-top-2"
928
+ ]);
929
+ var multiSelectCheckboxItemVariants = cva7([
930
+ "group relative flex cursor-default select-none items-center gap-1.5 rounded-[4px] px-2 py-1 text-sm font-normal leading-6 outline-none",
931
+ "text-neutral-1100",
932
+ "data-[highlighted]:bg-neutral-200",
933
+ "data-[disabled]:pointer-events-none data-[disabled]:opacity-50"
934
+ ]);
935
+ var multiSelectCheckboxBox = "flex h-4 w-4 shrink-0 p-[3px] items-center justify-center rounded-[4px] border border-neutral-400 group-data-[state=checked]:border-neutral-1100 group-data-[state=checked]:bg-neutral-1100";
936
+ var DropdownMulti = React7.forwardRef(
937
+ ({
938
+ label,
939
+ required,
940
+ placeholder = "Input",
941
+ options,
942
+ value = [],
943
+ onValueChange,
944
+ width,
945
+ error = false,
946
+ disabled,
947
+ selectAllLabel = "Select all",
948
+ showLabelIcon = false,
949
+ helperText,
950
+ showHelperIcon = false
951
+ }, ref) => {
952
+ const triggerId = React7.useId();
953
+ const [open, setOpen] = React7.useState(false);
954
+ const helperTextId = helperText ? `${triggerId}-helper` : void 0;
955
+ const helperTextColor = error ? "text-red-800" : "text-neutral-600";
956
+ const HelperIcon = error ? InfoFilled2 : showHelperIcon ? Info2 : null;
957
+ const allSelected = options.length > 0 && value.length === options.length;
958
+ const handleCheckedChange = (optValue, checked) => {
959
+ if (checked) {
960
+ onValueChange([...value, optValue]);
961
+ } else {
962
+ onValueChange(value.filter((v) => v !== optValue));
963
+ }
964
+ };
965
+ const handleSelectAllChange = (checked) => {
966
+ if (checked) {
967
+ onValueChange(options.map((o) => o.value));
968
+ } else {
969
+ onValueChange([]);
970
+ }
971
+ };
972
+ const removeOption = (e, optValue) => {
973
+ e.stopPropagation();
974
+ onValueChange(value.filter((v) => v !== optValue));
975
+ };
976
+ const selectedLabels = value.map((v) => options.find((o) => o.value === v)?.label).filter(Boolean);
977
+ return /* @__PURE__ */ jsxs6("div", { className: "w-full", children: [
978
+ label && /* @__PURE__ */ jsx7(
979
+ Label,
980
+ {
981
+ htmlFor: triggerId,
982
+ required,
983
+ endAdornment: showLabelIcon ? /* @__PURE__ */ jsx7(Info2, { size: 16, className: "!text-neutral-600 shrink-0", "aria-hidden": "true" }) : void 0,
984
+ children: label
985
+ }
986
+ ),
987
+ /* @__PURE__ */ jsxs6(DropdownMenuPrimitive.Root, { open, onOpenChange: setOpen, children: [
988
+ /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs6(
989
+ "button",
990
+ {
991
+ ref,
992
+ type: "button",
993
+ id: triggerId,
994
+ disabled,
995
+ "aria-haspopup": "listbox",
996
+ "aria-expanded": open,
997
+ "data-state": open ? "open" : "closed",
998
+ className: cn7(
999
+ "group flex min-h-8 h-8 w-full flex-wrap items-center gap-1 rounded-sm bg-white px-3 py-1 text-left font-sans text-sm leading-6 font-normal outline-none transition-all duration-200 ease-out",
1000
+ error ? "border border-red-800 hover:border-red-800 focus:border-red-800" : "border border-neutral-400 hover:border-neutral-700 focus:border-neutral-700",
1001
+ "focus-visible:outline-none",
1002
+ "disabled:cursor-not-allowed disabled:bg-neutral-200 disabled:border-neutral-200 disabled:text-neutral-500"
1003
+ ),
1004
+ style: {
1005
+ width: width ?? "100%",
1006
+ minWidth: DROPDOWN_TRIGGER_MIN_WIDTH,
1007
+ minHeight: DROPDOWN_TRIGGER_HEIGHT
1008
+ },
1009
+ children: [
1010
+ selectedLabels.length === 0 ? /* @__PURE__ */ jsx7("span", { className: "text-neutral-600", children: placeholder }) : value.map((optValue, i) => {
1011
+ const labelText = options.find((o) => o.value === optValue)?.label ?? selectedLabels[i];
1012
+ return /* @__PURE__ */ jsxs6(
1013
+ "span",
1014
+ {
1015
+ className: "inline-flex items-center gap-1 rounded-full border border-neutral-400 bg-neutral-200 px-2 py-[1.5px] !text-xs text-neutral-1100 font-medium",
1016
+ children: [
1017
+ labelText,
1018
+ /* @__PURE__ */ jsx7(
1019
+ "button",
1020
+ {
1021
+ type: "button",
1022
+ onClick: (e) => removeOption(e, optValue),
1023
+ className: "flex cursor-pointer items-center justify-center rounded hover:opacity-80",
1024
+ "aria-label": `Remove ${labelText}`,
1025
+ children: /* @__PURE__ */ jsx7(Close, { size: 12, className: "shrink-0 text-neutral-1100", "aria-hidden": true })
1026
+ }
1027
+ )
1028
+ ]
1029
+ },
1030
+ optValue
1031
+ );
1032
+ }),
1033
+ /* @__PURE__ */ jsxs6(
1034
+ "span",
1035
+ {
1036
+ className: "ml-auto flex shrink-0 items-center justify-center pl-1 text-neutral-1100",
1037
+ "aria-hidden": true,
1038
+ children: [
1039
+ /* @__PURE__ */ jsx7(ChevronDown, { size: 16, className: "shrink-0 group-data-[state=open]:hidden" }),
1040
+ /* @__PURE__ */ jsx7(ChevronUp, { size: 16, className: "hidden shrink-0 group-data-[state=open]:block" })
1041
+ ]
1042
+ }
1043
+ )
1044
+ ]
1045
+ }
1046
+ ) }),
1047
+ /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsxs6(
1048
+ DropdownMenuPrimitive.Content,
1049
+ {
1050
+ className: multiSelectContentVariants(),
1051
+ align: "start",
1052
+ side: "bottom",
1053
+ sideOffset: 4,
1054
+ avoidCollisions: false,
1055
+ onCloseAutoFocus: (e) => e.preventDefault(),
1056
+ children: [
1057
+ selectAllLabel ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
1058
+ /* @__PURE__ */ jsxs6(
1059
+ DropdownMenuPrimitive.CheckboxItem,
1060
+ {
1061
+ checked: allSelected,
1062
+ onCheckedChange: handleSelectAllChange,
1063
+ className: multiSelectCheckboxItemVariants(),
1064
+ onSelect: (e) => e.preventDefault(),
1065
+ children: [
1066
+ /* @__PURE__ */ jsx7("span", { className: cn7(multiSelectCheckboxBox), children: /* @__PURE__ */ jsx7(
1067
+ Tickmark,
1068
+ {
1069
+ size: 12,
1070
+ className: "opacity-0 !text-white group-data-[state=checked]:opacity-100"
1071
+ }
1072
+ ) }),
1073
+ selectAllLabel
1074
+ ]
1075
+ }
1076
+ ),
1077
+ /* @__PURE__ */ jsx7(DropdownMenuPrimitive.Separator, { className: "border-b border-neutral-200 my-0" })
1078
+ ] }) : null,
1079
+ options.map((opt) => /* @__PURE__ */ jsxs6(
1080
+ DropdownMenuPrimitive.CheckboxItem,
1081
+ {
1082
+ checked: value.includes(opt.value),
1083
+ onCheckedChange: (checked) => handleCheckedChange(opt.value, checked),
1084
+ disabled: opt.disabled,
1085
+ className: multiSelectCheckboxItemVariants(),
1086
+ onSelect: (e) => e.preventDefault(),
1087
+ children: [
1088
+ /* @__PURE__ */ jsx7("span", { className: cn7(multiSelectCheckboxBox), children: /* @__PURE__ */ jsx7(
1089
+ Tickmark,
1090
+ {
1091
+ size: 12,
1092
+ className: "opacity-0 !text-white group-data-[state=checked]:opacity-100"
1093
+ }
1094
+ ) }),
1095
+ opt.label
1096
+ ]
1097
+ },
1098
+ opt.value
1099
+ ))
1100
+ ]
1101
+ }
1102
+ ) })
1103
+ ] }),
1104
+ helperText && /* @__PURE__ */ jsxs6(
1105
+ "p",
1106
+ {
1107
+ id: helperTextId,
1108
+ className: cn7(
1109
+ "mt-1 flex items-center gap-1.5 text-xs leading-4 font-normal",
1110
+ helperTextColor
1111
+ ),
1112
+ children: [
1113
+ HelperIcon && /* @__PURE__ */ jsx7(
1114
+ HelperIcon,
1115
+ {
1116
+ size: 16,
1117
+ className: cn7(error ? "text-red-800" : "text-neutral-1100", "shrink-0"),
1118
+ "aria-hidden": "true"
1119
+ }
1120
+ ),
1121
+ helperText
1122
+ ]
1123
+ }
1124
+ )
1125
+ ] });
1126
+ }
1127
+ );
1128
+ DropdownMulti.displayName = "DropdownMulti";
1129
+
1130
+ // src/primitives/search-field.tsx
1131
+ import * as React8 from "react";
1132
+ import { cva as cva8 } from "class-variance-authority";
1133
+ import { cn as cn8 } from "@esds-sangam/utils";
1134
+ import { Search, Close as Close2 } from "@esds-sangam/icons";
1135
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1136
+ var searchFieldVariants = cva8(
1137
+ [
1138
+ // Base styles
1139
+ "relative w-[400px] flex items-center gap-2",
1140
+ "rounded-sm border transition-all duration-200 ease-out",
1141
+ // rounded-sm = 8px from radius tokens
1142
+ "font-sans text-sm leading-6 font-normal",
1143
+ // 14px font, 24px line-height
1144
+ "px-3 py-1",
1145
+ // 12px horizontal, 4px vertical
1146
+ // Default state
1147
+ "bg-white border-neutral-400",
1148
+ // Hover state
1149
+ "hover:border-neutral-700",
1150
+ // Focus-within (Active/Typing) state
1151
+ "focus-within:border-neutral-700",
1152
+ // Disabled state
1153
+ "has-[:disabled]:bg-neutral-200 has-[:disabled]:border-neutral-200",
1154
+ "has-[:disabled]:cursor-not-allowed",
1155
+ "h-8 w-full min-w-[296px]"
1156
+ ],
1157
+ {
1158
+ variants: {},
1159
+ defaultVariants: {}
1160
+ }
1161
+ );
1162
+ var searchInputVariants = cva8([
1163
+ // Base input styles
1164
+ "flex-1 bg-transparent border-none outline-none",
1165
+ "text-neutral-1100 placeholder:text-neutral-600",
1166
+ "focus:text-neutral-1100",
1167
+ // Caret (cursor) color
1168
+ "caret-neutral-1100",
1169
+ // Disabled state
1170
+ "disabled:text-neutral-500 disabled:cursor-not-allowed",
1171
+ // Remove default input styling
1172
+ "appearance-none"
1173
+ ]);
1174
+ var DEFAULT_WIDTH = "100%";
1175
+ var SearchField = React8.forwardRef(
1176
+ ({
1177
+ width = DEFAULT_WIDTH,
1178
+ className,
1179
+ value,
1180
+ onChange,
1181
+ onClear,
1182
+ showClearButton = true,
1183
+ disabled,
1184
+ placeholder = "Search",
1185
+ ...props
1186
+ }, ref) => {
1187
+ const hasValue = !!value && value.toString().length > 0;
1188
+ const handleClear = () => {
1189
+ if (onClear) {
1190
+ onClear();
1191
+ } else if (onChange) {
1192
+ const syntheticEvent = {
1193
+ target: { value: "" }
1194
+ };
1195
+ onChange(syntheticEvent);
1196
+ }
1197
+ };
1198
+ return /* @__PURE__ */ jsxs7("div", { className: cn8(searchFieldVariants(), className), style: { width }, children: [
1199
+ /* @__PURE__ */ jsx8(
1200
+ Search,
1201
+ {
1202
+ size: 16,
1203
+ className: cn8(
1204
+ "shrink-0 transition-colors duration-200",
1205
+ disabled ? "!text-neutral-500" : "!text-neutral-600"
1206
+ )
1207
+ }
1208
+ ),
1209
+ /* @__PURE__ */ jsx8(
1210
+ "input",
1211
+ {
1212
+ ref,
1213
+ type: "text",
1214
+ value,
1215
+ onChange,
1216
+ disabled,
1217
+ placeholder,
1218
+ className: searchInputVariants(),
1219
+ ...props
1220
+ }
1221
+ ),
1222
+ hasValue && showClearButton && !disabled && /* @__PURE__ */ jsx8(
1223
+ "button",
1224
+ {
1225
+ type: "button",
1226
+ onClick: handleClear,
1227
+ className: cn8(
1228
+ "shrink-0 flex items-center justify-center",
1229
+ "text-neutral-900 hover:text-neutral-1100",
1230
+ "transition-colors duration-200 ease-out",
1231
+ "focus:outline-none focus-visible:ring-2 focus-visible:ring-neutral-800 focus-visible:ring-offset-2 rounded-sm"
1232
+ ),
1233
+ "aria-label": "Clear search",
1234
+ tabIndex: 0,
1235
+ children: /* @__PURE__ */ jsx8(Close2, { size: 16 })
1236
+ }
1237
+ )
1238
+ ] });
1239
+ }
1240
+ );
1241
+ SearchField.displayName = "SearchField";
1242
+
1243
+ // src/primitives/textarea.tsx
1244
+ import * as React9 from "react";
1245
+ import { cva as cva9 } from "class-variance-authority";
1246
+ import { cn as cn9 } from "@esds-sangam/utils";
1247
+ import { Info as Info3, TickmarkFilled as TickmarkFilled2, InfoFilled as InfoFilled3 } from "@esds-sangam/icons";
1248
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1249
+ var textareaVariants = cva9(
1250
+ [
1251
+ // Base styles
1252
+ "w-[450px] h-24 rounded-sm border transition-all duration-200 ease-out",
1253
+ "font-sans text-sm leading-6 font-normal",
1254
+ // 14px font, 24px line-height, 400 weight
1255
+ "px-3 py-1",
1256
+ // 12px horizontal, 4px vertical
1257
+ "outline-none resize-none",
1258
+ // Fixed height, no resize
1259
+ // Default state
1260
+ "bg-white border-neutral-400 text-neutral-600 placeholder:text-neutral-600",
1261
+ // Hover state
1262
+ "hover:border-neutral-700",
1263
+ // Focus (Active/Typing) state
1264
+ "focus:border-neutral-700 focus:text-neutral-1100",
1265
+ // Caret (cursor) color
1266
+ "caret-neutral-1100",
1267
+ // Disabled state
1268
+ "disabled:bg-neutral-200 disabled:border-neutral-200 disabled:text-neutral-500",
1269
+ "disabled:cursor-not-allowed",
1270
+ // Remove default focus ring
1271
+ "focus-visible:outline-none"
1272
+ ],
1273
+ {
1274
+ variants: {
1275
+ variant: {
1276
+ default: "",
1277
+ error: ["border-red-800 focus:border-red-800", "text-neutral-1100 focus:text-neutral-1100"],
1278
+ success: [
1279
+ "border-green-800 focus:border-green-800",
1280
+ "text-neutral-1100 focus:text-neutral-1100"
1281
+ ]
1282
+ },
1283
+ // Filled state (when textarea has value)
1284
+ filled: {
1285
+ true: "text-neutral-1100",
1286
+ false: ""
1287
+ }
1288
+ },
1289
+ defaultVariants: {
1290
+ variant: "default",
1291
+ filled: false
1292
+ }
1293
+ }
1294
+ );
1295
+ var Textarea = React9.forwardRef(
1296
+ ({
1297
+ className,
1298
+ label,
1299
+ required,
1300
+ error,
1301
+ success,
1302
+ helperText,
1303
+ helperError,
1304
+ disabled,
1305
+ value,
1306
+ rows = 3,
1307
+ maxLength = 250,
1308
+ showCounter = true,
1309
+ showLabelIcon = false,
1310
+ showHelperIcon = false,
1311
+ ...props
1312
+ }, ref) => {
1313
+ const variant = error ? "error" : success ? "success" : "default";
1314
+ const isFilled = !!value && value.toString().length > 0;
1315
+ const currentLength = value ? value.toString().length : 0;
1316
+ const textareaId = props.id || `textarea-${React9.useId()}`;
1317
+ const helperTextId = helperText ? `${textareaId}-helper` : void 0;
1318
+ const helperTextColor = error ? "text-red-800" : success ? "text-green-800" : "text-neutral-600";
1319
+ const HelperIcon = error ? InfoFilled3 : success ? TickmarkFilled2 : showHelperIcon ? Info3 : null;
1320
+ return /* @__PURE__ */ jsxs8("div", { className: "w-full", children: [
1321
+ label && /* @__PURE__ */ jsx9(
1322
+ Label,
1323
+ {
1324
+ htmlFor: textareaId,
1325
+ required,
1326
+ endAdornment: showLabelIcon ? /* @__PURE__ */ jsx9(Info3, { size: 16, className: "text-neutral-1100 shrink-0", "aria-hidden": "true" }) : void 0,
1327
+ children: label
1328
+ }
1329
+ ),
1330
+ /* @__PURE__ */ jsx9(
1331
+ "textarea",
1332
+ {
1333
+ id: textareaId,
1334
+ ref,
1335
+ disabled,
1336
+ value,
1337
+ rows,
1338
+ maxLength,
1339
+ "aria-describedby": helperTextId,
1340
+ "aria-invalid": error ? "true" : void 0,
1341
+ className: cn9(textareaVariants({ variant, filled: isFilled }), className),
1342
+ ...props
1343
+ }
1344
+ ),
1345
+ (helperText || showCounter) && /* @__PURE__ */ jsxs8("div", { className: "mt-1 flex items-center justify-between gap-2", children: [
1346
+ helperText && /* @__PURE__ */ jsxs8(
1347
+ "p",
1348
+ {
1349
+ id: helperTextId,
1350
+ className: cn9(
1351
+ "flex items-center gap-1.5 text-xs leading-4 font-normal",
1352
+ // 12px, 400 weight, 16px line-height; color from tokens
1353
+ helperTextColor
1354
+ ),
1355
+ children: [
1356
+ HelperIcon && /* @__PURE__ */ jsx9(
1357
+ HelperIcon,
1358
+ {
1359
+ size: 16,
1360
+ className: cn9(
1361
+ error ? "text-red-800" : success ? "text-green-800" : "text-neutral-1100"
1362
+ ),
1363
+ "aria-hidden": "true"
1364
+ }
1365
+ ),
1366
+ helperText
1367
+ ]
1368
+ }
1369
+ ),
1370
+ showCounter && /* @__PURE__ */ jsxs8(
1371
+ "div",
1372
+ {
1373
+ className: cn9(
1374
+ "text-xs leading-4 select-none",
1375
+ // 12px font, 16px line-height
1376
+ disabled ? "text-neutral-500" : "text-neutral-600",
1377
+ helperText ? "" : "ml-auto"
1378
+ // Push to right if no helper text
1379
+ ),
1380
+ "aria-live": "polite",
1381
+ "aria-atomic": "true",
1382
+ children: [
1383
+ currentLength,
1384
+ "/",
1385
+ maxLength
1386
+ ]
1387
+ }
1388
+ )
1389
+ ] })
1390
+ ] });
1391
+ }
1392
+ );
1393
+ Textarea.displayName = "Textarea";
1394
+
1395
+ // src/primitives/tooltip.tsx
1396
+ import * as React10 from "react";
1397
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
1398
+ import { cva as cva10 } from "class-variance-authority";
1399
+ import { cn as cn10 } from "@esds-sangam/utils";
1400
+ import { CaretDown, CaretUp, CaretLeft, CaretRight, Close as Close3 } from "@esds-sangam/icons";
1401
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1402
+ var tooltipContentVariants = cva10(
1403
+ [
1404
+ // Base styles
1405
+ "z-50 rounded-sm",
1406
+ // Removed overflow-hidden to allow arrows to show
1407
+ "bg-neutral-1100 text-white",
1408
+ "px-4 py-1",
1409
+ // 16px horizontal, 4px vertical
1410
+ "text-xs font-medium leading-4",
1411
+ // 12px, 500 weight, 16px line-height
1412
+ "shadow-md",
1413
+ // Fixed width (rem for accessibility - scales with user font size)
1414
+ "w-30",
1415
+ // 7.5rem = 120px at default (16px base)
1416
+ // Animation
1417
+ "animate-in fade-in-0 zoom-in-95",
1418
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1419
+ "data-[side=bottom]:slide-in-from-top-2",
1420
+ "data-[side=left]:slide-in-from-right-2",
1421
+ "data-[side=right]:slide-in-from-left-2",
1422
+ "data-[side=top]:slide-in-from-bottom-2"
1423
+ ],
1424
+ {
1425
+ variants: {
1426
+ variant: {
1427
+ default: "h-8 flex items-center justify-center",
1428
+ // 2rem = 32px, centered content
1429
+ withDescription: "h-[3.25rem] flex flex-col items-start justify-center gap-1"
1430
+ // 3.25rem = 52px, stacked content
1431
+ }
1432
+ },
1433
+ defaultVariants: {
1434
+ variant: "default"
1435
+ }
1436
+ }
1437
+ );
1438
+ var TooltipProvider = TooltipPrimitive.Provider;
1439
+ var Tooltip = TooltipPrimitive.Root;
1440
+ var TooltipTrigger = TooltipPrimitive.Trigger;
1441
+ var TooltipContent = React10.forwardRef(
1442
+ ({
1443
+ className,
1444
+ variant,
1445
+ sideOffset = 12,
1446
+ side = "bottom",
1447
+ align = "center",
1448
+ showArrow = true,
1449
+ title,
1450
+ description,
1451
+ showCloseIcon = false,
1452
+ onClose,
1453
+ children,
1454
+ ...props
1455
+ }, ref) => {
1456
+ const computedVariant = description || showCloseIcon ? "withDescription" : "default";
1457
+ const finalVariant = variant || computedVariant;
1458
+ const CaretComponent = {
1459
+ bottom: CaretUp,
1460
+ // Tooltip at bottom, arrow at top pointing up
1461
+ top: CaretDown,
1462
+ // Tooltip at top, arrow at bottom pointing down
1463
+ left: CaretRight,
1464
+ // Tooltip at left, arrow at right pointing right
1465
+ right: CaretLeft
1466
+ // Tooltip at right, arrow at left pointing left
1467
+ }[side];
1468
+ const getCaretPosition = () => {
1469
+ if (side === "bottom" || side === "top") {
1470
+ const baseClasses = "absolute left-1/2 -translate-x-1/2";
1471
+ const sideClass = side === "bottom" ? "-top-[8px]" : "-bottom-[8px]";
1472
+ let alignClass = "";
1473
+ if (align === "start") {
1474
+ alignClass = "!left-4 !translate-x-0";
1475
+ } else if (align === "end") {
1476
+ alignClass = "!left-auto !right-4 !translate-x-0";
1477
+ }
1478
+ return `${baseClasses} ${sideClass} ${alignClass}`;
1479
+ }
1480
+ if (side === "left" || side === "right") {
1481
+ const baseClasses = "absolute top-1/2 -translate-y-1/2";
1482
+ const sideClass = side === "left" ? "-right-[8px]" : "-left-[8px]";
1483
+ let alignClass = "";
1484
+ if (align === "start") {
1485
+ alignClass = "!top-auto !bottom-4 !translate-y-0";
1486
+ } else if (align === "end") {
1487
+ alignClass = "!top-4 !translate-y-0";
1488
+ }
1489
+ return `${baseClasses} ${sideClass} ${alignClass}`;
1490
+ }
1491
+ return "";
1492
+ };
1493
+ return /* @__PURE__ */ jsx10(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs9(
1494
+ TooltipPrimitive.Content,
1495
+ {
1496
+ ref,
1497
+ side,
1498
+ align,
1499
+ sideOffset,
1500
+ className: cn10(tooltipContentVariants({ variant: finalVariant }), "relative", className),
1501
+ ...props,
1502
+ children: [
1503
+ /* @__PURE__ */ jsxs9("div", { className: "w-full relative", children: [
1504
+ /* @__PURE__ */ jsx10("div", { className: "text-xs font-medium leading-4 text-white", children: title }),
1505
+ description && /* @__PURE__ */ jsx10("div", { className: "text-xs font-normal leading-4 text-white opacity-90 mt-1", children: description }),
1506
+ showCloseIcon && /* @__PURE__ */ jsx10(
1507
+ "button",
1508
+ {
1509
+ onClick: onClose,
1510
+ className: "absolute top-0 right-0 text-white hover:opacity-80 transition-opacity",
1511
+ "aria-label": "Close tooltip",
1512
+ type: "button",
1513
+ children: /* @__PURE__ */ jsx10(Close3, { size: 16 })
1514
+ }
1515
+ )
1516
+ ] }),
1517
+ !title && children,
1518
+ showArrow && /* @__PURE__ */ jsx10("div", { className: cn10(getCaretPosition(), "pointer-events-none"), children: /* @__PURE__ */ jsx10(CaretComponent, { className: "text-neutral-1100" }) })
1519
+ ]
1520
+ }
1521
+ ) });
1522
+ }
1523
+ );
1524
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
1525
+
1526
+ // src/primitives/progress-bar.tsx
1527
+ import * as React11 from "react";
1528
+ import { cn as cn11 } from "@esds-sangam/utils";
1529
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1530
+ var TRACK_HEIGHT_PX = 6;
1531
+ var TRACK_WIDTH_PX = 476;
1532
+ var labelClassName = "text-xs font-medium leading-4 text-neutral-1100 shrink-0 min-w-[2.5rem]";
1533
+ var ProgressBar = React11.forwardRef(
1534
+ ({
1535
+ className,
1536
+ value,
1537
+ max = 100,
1538
+ showLabel = "both",
1539
+ width = TRACK_WIDTH_PX,
1540
+ height = TRACK_HEIGHT_PX,
1541
+ fluid = false,
1542
+ "aria-label": ariaLabel,
1543
+ ...props
1544
+ }, ref) => {
1545
+ const clamped = Math.min(max, Math.max(0, value));
1546
+ const percentage = max === 0 ? 0 : Math.round(clamped / max * 100);
1547
+ const displayLabel = `${percentage}%`;
1548
+ const showLeft = showLabel === "left" || showLabel === "both";
1549
+ const showRight = showLabel === "right" || showLabel === "both";
1550
+ const trackStyle = fluid ? { height } : { width, height };
1551
+ return /* @__PURE__ */ jsxs10(
1552
+ "div",
1553
+ {
1554
+ ref,
1555
+ className: cn11("flex items-center gap-3 w-full", className),
1556
+ role: "progressbar",
1557
+ "aria-valuenow": clamped,
1558
+ "aria-valuemin": 0,
1559
+ "aria-valuemax": max,
1560
+ "aria-label": ariaLabel ?? (showLabel === "none" ? "Progress" : void 0),
1561
+ ...props,
1562
+ children: [
1563
+ showLeft && /* @__PURE__ */ jsx11("span", { className: labelClassName, "aria-hidden": true, children: displayLabel }),
1564
+ /* @__PURE__ */ jsx11(
1565
+ "div",
1566
+ {
1567
+ className: cn11(
1568
+ "rounded-full overflow-hidden bg-neutral-200 transition-colors shrink-0",
1569
+ fluid && "w-full"
1570
+ ),
1571
+ style: trackStyle,
1572
+ children: /* @__PURE__ */ jsx11(
1573
+ "div",
1574
+ {
1575
+ className: "h-full rounded-full bg-neutral-1100 transition-all duration-200 ease-out",
1576
+ style: {
1577
+ width: `${percentage}%`,
1578
+ // At 0%, show a short visible segment at the left (min ~8px)
1579
+ minWidth: percentage === 0 ? 8 : void 0
1580
+ }
1581
+ }
1582
+ )
1583
+ }
1584
+ ),
1585
+ showRight && /* @__PURE__ */ jsx11("span", { className: cn11(labelClassName, "text-right"), "aria-hidden": true, children: displayLabel })
1586
+ ]
1587
+ }
1588
+ );
1589
+ }
1590
+ );
1591
+ ProgressBar.displayName = "ProgressBar";
1592
+
1593
+ // src/primitives/skeleton.tsx
1594
+ import * as React12 from "react";
1595
+ import { cva as cva11 } from "class-variance-authority";
1596
+ import { cn as cn12 } from "@esds-sangam/utils";
1597
+ import { jsx as jsx12 } from "react/jsx-runtime";
1598
+ var skeletonVariants = cva11(
1599
+ [
1600
+ "relative overflow-hidden",
1601
+ "rounded-sm",
1602
+ // tokens radius.sm = 8px
1603
+ "bg-neutral-200",
1604
+ // from colors.json
1605
+ // Use Tailwind's built-in pulse animation for loading state
1606
+ "animate-pulse"
1607
+ ],
1608
+ {
1609
+ variants: {
1610
+ variant: {
1611
+ rectangular: ""
1612
+ }
1613
+ },
1614
+ defaultVariants: {
1615
+ variant: "rectangular"
1616
+ }
1617
+ }
1618
+ );
1619
+ var Skeleton = React12.forwardRef(
1620
+ ({ className, variant, style, "aria-label": ariaLabel, ...props }, ref) => {
1621
+ const accessibleProps = ariaLabel != null ? {
1622
+ role: "status",
1623
+ "aria-label": ariaLabel,
1624
+ "aria-busy": true
1625
+ } : {
1626
+ "aria-hidden": true
1627
+ };
1628
+ return /* @__PURE__ */ jsx12(
1629
+ "div",
1630
+ {
1631
+ ref,
1632
+ className: cn12(skeletonVariants({ variant, className })),
1633
+ style,
1634
+ ...accessibleProps,
1635
+ ...props
1636
+ }
1637
+ );
1638
+ }
1639
+ );
1640
+ Skeleton.displayName = "Skeleton";
1641
+
1642
+ // src/primitives/tabs.tsx
1643
+ import * as React13 from "react";
1644
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
1645
+ import { cva as cva12 } from "class-variance-authority";
1646
+ import { cn as cn13 } from "@esds-sangam/utils";
1647
+ import { Tickmark as Tickmark2 } from "@esds-sangam/icons";
1648
+ import { jsx as jsx13 } from "react/jsx-runtime";
1649
+ var tabsListVariants = cva12("inline-flex items-center", {
1650
+ variants: {
1651
+ type: {
1652
+ container: "gap-0 rounded-xs p-0.5 bg-neutral-200",
1653
+ underline: "gap-0 border-b border-neutral-200",
1654
+ iconOnly: "gap-0 rounded-xs p-0.5 bg-neutral-200"
1655
+ }
1656
+ },
1657
+ defaultVariants: {
1658
+ type: "container"
1659
+ }
1660
+ });
1661
+ var tabsTriggerVariants = cva12(
1662
+ [
1663
+ "inline-flex items-center justify-center transition-colors duration-200 ease-out",
1664
+ "text-sm font-medium leading-6",
1665
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-neutral-400",
1666
+ "disabled:pointer-events-none disabled:cursor-not-allowed"
1667
+ ],
1668
+ {
1669
+ variants: {
1670
+ type: {
1671
+ container: [
1672
+ "min-w-[178px] h-8 px-4 rounded-xs",
1673
+ "text-neutral-600 hover:text-neutral-1100",
1674
+ "data-[state=active]:bg-white data-[state=active]:text-neutral-1100 data-[state=active]:shadow-elevation-bottom-sm",
1675
+ "disabled:text-neutral-500"
1676
+ ],
1677
+ underline: [
1678
+ "px-3 py-1 border-b-2 -mb-[1px] border-transparent",
1679
+ "text-neutral-600 hover:text-neutral-1100",
1680
+ "data-[state=active]:text-neutral-1100 data-[state=active]:border-blue-600 data-[state=active]:border-b-2",
1681
+ "disabled:text-neutral-500"
1682
+ ],
1683
+ iconOnly: [
1684
+ "w-6 h-6 rounded-xs p-1",
1685
+ "text-neutral-600 hover:text-neutral-1100",
1686
+ "data-[state=active]:bg-white data-[state=active]:text-neutral-1100 data-[state=active]:shadow-elevation-bottom-sm",
1687
+ "disabled:text-neutral-500"
1688
+ ]
1689
+ }
1690
+ },
1691
+ defaultVariants: {
1692
+ type: "container"
1693
+ }
1694
+ }
1695
+ );
1696
+ var TabsContext = React13.createContext(null);
1697
+ function useTabsType() {
1698
+ const ctx = React13.useContext(TabsContext);
1699
+ return ctx?.tabType ?? "container";
1700
+ }
1701
+ var TabsRoot = React13.forwardRef(
1702
+ ({ type = "container", className, ...props }, ref) => /* @__PURE__ */ jsx13(TabsContext.Provider, { value: { tabType: type }, children: /* @__PURE__ */ jsx13(TabsPrimitive.Root, { ref, className: cn13(className), ...props }) })
1703
+ );
1704
+ TabsRoot.displayName = "Tabs";
1705
+ var TabsList = React13.forwardRef(({ className, type, ...props }, ref) => {
1706
+ const resolvedType = type ?? useTabsType();
1707
+ return /* @__PURE__ */ jsx13(
1708
+ TabsPrimitive.List,
1709
+ {
1710
+ ref,
1711
+ className: cn13(tabsListVariants({ type: resolvedType }), className),
1712
+ ...props
1713
+ }
1714
+ );
1715
+ });
1716
+ TabsList.displayName = "TabsList";
1717
+ var TabsTrigger = React13.forwardRef(({ className, type, icon, children, ...props }, ref) => {
1718
+ const resolvedType = type ?? useTabsType();
1719
+ const iconContent = icon ?? (resolvedType === "iconOnly" ? /* @__PURE__ */ jsx13(Tickmark2, { size: 16, className: "shrink-0" }) : null);
1720
+ return /* @__PURE__ */ jsx13(
1721
+ TabsPrimitive.Trigger,
1722
+ {
1723
+ ref,
1724
+ className: cn13(tabsTriggerVariants({ type: resolvedType }), className),
1725
+ ...props,
1726
+ children: resolvedType === "iconOnly" ? iconContent : children ?? "Label"
1727
+ }
1728
+ );
1729
+ });
1730
+ TabsTrigger.displayName = "TabsTrigger";
1731
+ var TabsContent = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx13(
1732
+ TabsPrimitive.Content,
1733
+ {
1734
+ ref,
1735
+ className: cn13("mt-4 focus-visible:outline-none", className),
1736
+ ...props
1737
+ }
1738
+ ));
1739
+ TabsContent.displayName = "TabsContent";
1740
+ var Tabs = Object.assign(TabsRoot, {
1741
+ List: TabsList,
1742
+ Trigger: TabsTrigger,
1743
+ Content: TabsContent
1744
+ });
1745
+
1746
+ // src/primitives/avatar.tsx
1747
+ import * as React14 from "react";
1748
+ import { cva as cva13 } from "class-variance-authority";
1749
+ import { cn as cn14 } from "@esds-sangam/utils";
1750
+ import { AvatarPlaceholder } from "@esds-sangam/icons";
1751
+ import { jsx as jsx14 } from "react/jsx-runtime";
1752
+ var avatarVariants = cva13(
1753
+ [
1754
+ "inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full",
1755
+ "bg-neutral-200"
1756
+ // tokens colors.json neutral.200
1757
+ ],
1758
+ {
1759
+ variants: {
1760
+ size: {
1761
+ large: "h-8 w-8",
1762
+ // 32×32 (Big)
1763
+ medium: "h-6 w-6",
1764
+ // 24×24 (Medium)
1765
+ small: "h-5 w-5"
1766
+ // 20×20 (Small)
1767
+ }
1768
+ },
1769
+ defaultVariants: {
1770
+ size: "large"
1771
+ }
1772
+ }
1773
+ );
1774
+ var letterTextClassBySize = {
1775
+ large: "text-base font-medium leading-6 text-neutral-600",
1776
+ // tokens base = 16px
1777
+ medium: "text-3xs font-medium leading-4 text-neutral-600",
1778
+ // tokens 3xs = 10px
1779
+ small: "text-3xs font-medium leading-4 text-neutral-600"
1780
+ // tokens 3xs = 10px
1781
+ };
1782
+ var Avatar = React14.forwardRef(
1783
+ ({ className, size = "large", variant = "image", src, alt = "", children, ...props }, ref) => {
1784
+ const [imgFailed, setImgFailed] = React14.useState(false);
1785
+ const showImg = variant === "image" && src && !imgFailed;
1786
+ const showLetter = variant === "letter" || variant === "image" && !showImg && children;
1787
+ const sizePx = size === "large" ? 32 : size === "medium" ? 24 : 20;
1788
+ return /* @__PURE__ */ jsx14(
1789
+ "span",
1790
+ {
1791
+ ref,
1792
+ role: "img",
1793
+ "aria-label": alt || (typeof children === "string" ? children : void 0),
1794
+ className: cn14(avatarVariants({ size }), className),
1795
+ ...props,
1796
+ children: showImg ? /* @__PURE__ */ jsx14(
1797
+ "img",
1798
+ {
1799
+ src,
1800
+ alt,
1801
+ width: sizePx,
1802
+ height: sizePx,
1803
+ className: "h-full w-full object-cover",
1804
+ onError: () => setImgFailed(true)
1805
+ }
1806
+ ) : showLetter && children ? /* @__PURE__ */ jsx14(
1807
+ "span",
1808
+ {
1809
+ className: cn14(
1810
+ "flex h-full w-full items-center justify-center",
1811
+ letterTextClassBySize[size ?? "large"]
1812
+ ),
1813
+ children
1814
+ }
1815
+ ) : /* @__PURE__ */ jsx14(AvatarPlaceholder, { size: sizePx, className: "shrink-0" })
1816
+ }
1817
+ );
1818
+ }
1819
+ );
1820
+ Avatar.displayName = "Avatar";
1821
+
1822
+ // src/components/badge.tsx
1823
+ import * as React15 from "react";
1824
+ import { cva as cva14 } from "class-variance-authority";
1825
+ import { cn as cn15 } from "@esds-sangam/utils";
1826
+ import { ChevronDown as ChevronDown2, Close as Close4, InfoFilled as InfoFilled4, TickmarkFilled as TickmarkFilled3, WarningFilled as WarningFilled3 } from "@esds-sangam/icons";
1827
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1828
+ var badgeVariants = cva14(
1829
+ [
1830
+ "inline-flex items-center justify-center gap-1 transition-colors",
1831
+ "border box-border",
1832
+ "text-xs font-medium leading-4"
1833
+ // Label: 12px, weight 500, line-height 16px (both big & small)
1834
+ ],
1835
+ {
1836
+ variants: {
1837
+ size: {
1838
+ big: "",
1839
+ small: ""
1840
+ },
1841
+ variant: {
1842
+ rounded: "rounded-sm",
1843
+ // 8px border radius (tokens radius.sm = 0.5rem)
1844
+ pill: "rounded-full",
1845
+ notification: "rounded-full"
1846
+ },
1847
+ state: {
1848
+ info: "",
1849
+ success: "",
1850
+ warning: "",
1851
+ error: "",
1852
+ neutral: "",
1853
+ process: "",
1854
+ action: ""
1855
+ },
1856
+ appearance: {
1857
+ outlined: "border",
1858
+ solid: "border-transparent"
1859
+ }
1860
+ },
1861
+ compoundVariants: [
1862
+ // Big: rounded/pill 48×24, notification 24×24
1863
+ { size: "big", variant: "rounded", class: "h-6 min-w-12 py-1 px-2" },
1864
+ { size: "big", variant: "pill", class: "h-6 min-w-12 py-1 px-2" },
1865
+ { size: "big", variant: "notification", class: "h-6 w-6 p-0" },
1866
+ // Small: rounded/pill 48×20, notification 20×20; padding top=2 bottom=2 left=8 right=8
1867
+ { size: "small", variant: "rounded", class: "h-5 min-w-12 py-0.5 px-2" },
1868
+ { size: "small", variant: "pill", class: "h-5 min-w-12 py-0.5 px-2" },
1869
+ { size: "small", variant: "notification", class: "h-5 w-5 p-0" },
1870
+ // Info (subtle/solid from semantic tokens)
1871
+ {
1872
+ state: "info",
1873
+ appearance: "outlined",
1874
+ class: "bg-semantic-background-semantic-info-subtle border-semantic-border-semantic-info-subtle text-semantic-text-neutral-primary"
1875
+ },
1876
+ {
1877
+ state: "info",
1878
+ appearance: "solid",
1879
+ class: "bg-semantic-background-semantic-info-default text-semantic-text-semantic-info-default"
1880
+ },
1881
+ // Success
1882
+ {
1883
+ state: "success",
1884
+ appearance: "outlined",
1885
+ class: "bg-semantic-background-semantic-success-subtle border-semantic-border-semantic-success-subtle text-semantic-text-neutral-primary"
1886
+ },
1887
+ {
1888
+ state: "success",
1889
+ appearance: "solid",
1890
+ class: "bg-semantic-background-semantic-success-default text-semantic-text-semantic-success-default"
1891
+ },
1892
+ // Warning
1893
+ {
1894
+ state: "warning",
1895
+ appearance: "outlined",
1896
+ class: "bg-semantic-background-semantic-warning-subtle border-semantic-border-semantic-warning-subtle text-semantic-text-neutral-primary"
1897
+ },
1898
+ {
1899
+ state: "warning",
1900
+ appearance: "solid",
1901
+ class: "bg-semantic-background-semantic-warning-default text-semantic-text-semantic-warning-default"
1902
+ },
1903
+ // Error
1904
+ {
1905
+ state: "error",
1906
+ appearance: "outlined",
1907
+ class: "bg-semantic-background-semantic-error-subtle border-semantic-border-semantic-error-subtle text-semantic-text-neutral-primary"
1908
+ },
1909
+ {
1910
+ state: "error",
1911
+ appearance: "solid",
1912
+ class: "bg-semantic-background-semantic-error-default text-semantic-text-semantic-error-default"
1913
+ },
1914
+ // Neutral
1915
+ {
1916
+ state: "neutral",
1917
+ appearance: "outlined",
1918
+ class: "bg-semantic-background-neutral-tertiary border-semantic-border-neutral-primary text-semantic-text-neutral-primary"
1919
+ },
1920
+ {
1921
+ state: "neutral",
1922
+ appearance: "solid",
1923
+ class: "bg-neutral-400 text-neutral-1100"
1924
+ },
1925
+ // Process (purple: outlined = bg purple-200, border purple-700, text neutral-1100; solid = bg purple-700, text white)
1926
+ {
1927
+ state: "process",
1928
+ appearance: "outlined",
1929
+ class: "bg-purple-200 border-purple-700 text-neutral-1100"
1930
+ },
1931
+ {
1932
+ state: "process",
1933
+ appearance: "solid",
1934
+ class: "bg-purple-700 text-white"
1935
+ },
1936
+ {
1937
+ state: "action",
1938
+ appearance: "outlined",
1939
+ class: "bg-semantic-background-semantic-action-subtle border-neutral-400 text-semantic-text-neutral-primary"
1940
+ }
1941
+ ],
1942
+ defaultVariants: {
1943
+ size: "big",
1944
+ variant: "rounded",
1945
+ state: "neutral",
1946
+ appearance: "outlined"
1947
+ }
1948
+ }
1949
+ );
1950
+ var leadingIconMap = {
1951
+ info: InfoFilled4,
1952
+ success: TickmarkFilled3,
1953
+ warning: WarningFilled3,
1954
+ error: WarningFilled3,
1955
+ neutral: InfoFilled4,
1956
+ process: InfoFilled4,
1957
+ action: InfoFilled4
1958
+ };
1959
+ var Badge = React15.forwardRef(
1960
+ ({
1961
+ className,
1962
+ size,
1963
+ variant,
1964
+ state,
1965
+ appearance,
1966
+ children,
1967
+ isSolid = false,
1968
+ leadingIcon = false,
1969
+ dropdownIcon = false,
1970
+ closable = false,
1971
+ onClose,
1972
+ ...props
1973
+ }, ref) => {
1974
+ const resolvedAppearance = isSolid ? "solid" : appearance;
1975
+ const resolvedState = state ?? "neutral";
1976
+ const LeadingIcon = leadingIconMap[resolvedState];
1977
+ const showLeadingIcon = leadingIcon && !!LeadingIcon;
1978
+ const onCloseClick = (event) => {
1979
+ event.stopPropagation();
1980
+ onClose?.();
1981
+ };
1982
+ const leadingIconSize = size === "small" ? 12 : 16;
1983
+ const dropdownChevronSize = size === "small" ? 12 : 16;
1984
+ const closeIconSize = size === "small" ? 10 : 12;
1985
+ return /* @__PURE__ */ jsxs11(
1986
+ "span",
1987
+ {
1988
+ ref,
1989
+ className: cn15(
1990
+ badgeVariants({ size, variant, state: resolvedState, appearance: resolvedAppearance }),
1991
+ className
1992
+ ),
1993
+ ...props,
1994
+ children: [
1995
+ showLeadingIcon && /* @__PURE__ */ jsx15(
1996
+ LeadingIcon,
1997
+ {
1998
+ size: leadingIconSize,
1999
+ className: cn15(
2000
+ "shrink-0",
2001
+ resolvedAppearance === "solid" ? "text-neutral-50" : "text-neutral-1100"
2002
+ ),
2003
+ "aria-hidden": "true"
2004
+ }
2005
+ ),
2006
+ children,
2007
+ dropdownIcon && /* @__PURE__ */ jsx15(
2008
+ ChevronDown2,
2009
+ {
2010
+ size: dropdownChevronSize,
2011
+ className: cn15(
2012
+ "shrink-0",
2013
+ resolvedAppearance === "solid" ? "text-neutral-50" : "text-neutral-1100"
2014
+ ),
2015
+ "aria-hidden": "true"
2016
+ }
2017
+ ),
2018
+ closable && /* @__PURE__ */ jsx15(
2019
+ "button",
2020
+ {
2021
+ type: "button",
2022
+ onClick: onCloseClick,
2023
+ className: cn15(
2024
+ "shrink-0 p-0 border-0 bg-transparent cursor-pointer rounded inline-flex items-center justify-center",
2025
+ resolvedAppearance === "solid" ? "text-neutral-50" : "text-neutral-1100"
2026
+ ),
2027
+ "aria-label": "Dismiss",
2028
+ children: /* @__PURE__ */ jsx15(Close4, { size: closeIconSize, "aria-hidden": true })
2029
+ }
2030
+ )
2031
+ ]
2032
+ }
2033
+ );
2034
+ }
2035
+ );
2036
+ Badge.displayName = "Badge";
2037
+
2038
+ // src/components/chips.tsx
2039
+ import * as React16 from "react";
2040
+ import { cva as cva15 } from "class-variance-authority";
2041
+ import { cn as cn16 } from "@esds-sangam/utils";
2042
+ import { Close as Close5, TickmarkFilled as TickmarkFilled4 } from "@esds-sangam/icons";
2043
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
2044
+ var chipVariants = cva15(
2045
+ [
2046
+ "inline-flex items-center justify-center gap-1.5 rounded-full border transition-colors duration-200 ease-out",
2047
+ "font-sans font-normal leading-5",
2048
+ // Default: 1px border
2049
+ "bg-white border border-neutral-400 text-neutral-1100",
2050
+ // Hover
2051
+ "hover:bg-neutral-200 hover:border-transparent",
2052
+ // Focused: 2px border neutral-700 so clearly distinct from default
2053
+ "focus-within:border-2 focus-within:border-neutral-700 focus-within:bg-white focus-within:text-neutral-1100",
2054
+ "focus-within:outline-none"
2055
+ ],
2056
+ {
2057
+ variants: {
2058
+ size: {
2059
+ large: "h-8 min-w-[75px] py-1 px-3 gap-1.5 text-sm",
2060
+ small: "h-6 min-w-[67px] py-1 px-3 gap-1 text-xs"
2061
+ },
2062
+ selected: {
2063
+ true: "bg-neutral-1100 text-white border-transparent hover:bg-neutral-1100",
2064
+ false: ""
2065
+ },
2066
+ disabled: {
2067
+ true: "bg-neutral-200 text-neutral-500 border-transparent hover:bg-neutral-200 cursor-not-allowed pointer-events-none",
2068
+ false: ""
2069
+ }
2070
+ },
2071
+ compoundVariants: [
2072
+ { selected: true, disabled: true, class: "bg-neutral-200 text-neutral-500" },
2073
+ {
2074
+ selected: true,
2075
+ disabled: false,
2076
+ class: "focus-within:border-2 focus-within:bg-neutral-1100 focus-within:text-white focus-within:border-neutral-700"
2077
+ }
2078
+ ],
2079
+ defaultVariants: {
2080
+ size: "large",
2081
+ selected: false,
2082
+ disabled: false
2083
+ }
2084
+ }
2085
+ );
2086
+ var Chip = React16.forwardRef(
2087
+ ({
2088
+ className,
2089
+ size = "large",
2090
+ selected = false,
2091
+ disabled = false,
2092
+ onDismiss,
2093
+ showLeadingIcon = false,
2094
+ children,
2095
+ ...props
2096
+ }, ref) => {
2097
+ const iconSize = size === "large" ? 16 : 12;
2098
+ return /* @__PURE__ */ jsxs12(
2099
+ "div",
2100
+ {
2101
+ ref,
2102
+ role: "group",
2103
+ className: cn16(chipVariants({ size, selected, disabled }), className),
2104
+ "aria-disabled": disabled,
2105
+ "aria-pressed": selected,
2106
+ "data-state": selected ? "selected" : void 0,
2107
+ ...props,
2108
+ children: [
2109
+ showLeadingIcon && /* @__PURE__ */ jsx16(
2110
+ "span",
2111
+ {
2112
+ className: "shrink-0 inline-flex items-center justify-center text-inherit",
2113
+ "aria-hidden": true,
2114
+ children: /* @__PURE__ */ jsx16(TickmarkFilled4, { size: iconSize, className: "text-inherit" })
2115
+ }
2116
+ ),
2117
+ /* @__PURE__ */ jsx16("span", { className: "truncate", children }),
2118
+ onDismiss != null && /* @__PURE__ */ jsx16(
2119
+ "button",
2120
+ {
2121
+ type: "button",
2122
+ onClick: (e) => {
2123
+ e.stopPropagation();
2124
+ if (!disabled) onDismiss();
2125
+ },
2126
+ disabled,
2127
+ className: "shrink-0 p-0 border-0 bg-transparent cursor-pointer rounded-full inline-flex items-center justify-center text-inherit focus:outline-none focus-visible:ring-0 disabled:pointer-events-none",
2128
+ "aria-label": "Remove",
2129
+ children: /* @__PURE__ */ jsx16(Close5, { size: iconSize, className: "text-inherit", "aria-hidden": true })
2130
+ }
2131
+ )
2132
+ ]
2133
+ }
2134
+ );
2135
+ }
2136
+ );
2137
+ Chip.displayName = "Chip";
2138
+
2139
+ // src/components/toast.tsx
2140
+ import * as React17 from "react";
2141
+ import { cva as cva16 } from "class-variance-authority";
2142
+ import { cn as cn17 } from "@esds-sangam/utils";
2143
+ import { Close as Close6, InfoFilled as InfoFilled5, TickmarkFilled as TickmarkFilled5, WarningFilled as WarningFilled4 } from "@esds-sangam/icons";
2144
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
2145
+ var toastVariants = cva16(
2146
+ [
2147
+ // Base styles
2148
+ "flex gap-2",
2149
+ "w-[420px]",
2150
+ // 384px fixed width
2151
+ "rounded-sm",
2152
+ // 8px = tokens radius.lg
2153
+ "bg-white",
2154
+ "p-4",
2155
+ // 16px padding
2156
+ "border-l-[3px]",
2157
+ // 3px left border
2158
+ "shadow-md"
2159
+ // tokens.shadows.md = 0 4px 10px 0 rgba(0,0,0,0.1)
2160
+ ],
2161
+ {
2162
+ variants: {
2163
+ variant: {
2164
+ info: "border-l-blue-600 bg-blue-200",
2165
+ success: "border-l-green-800 bg-green-200",
2166
+ warning: "border-l-orange-700 bg-orange-200",
2167
+ error: "border-l-red-800 bg-red-200"
2168
+ },
2169
+ layout: {
2170
+ default: "h-14 items-center",
2171
+ // 56px, centered vertically
2172
+ withDescription: "h-21 items-start"
2173
+ // 84px, top aligned
2174
+ }
2175
+ },
2176
+ defaultVariants: {
2177
+ variant: "info",
2178
+ layout: "default"
2179
+ }
2180
+ }
2181
+ );
2182
+ var Toast = React17.forwardRef(
2183
+ ({
2184
+ className,
2185
+ variant = "info",
2186
+ title,
2187
+ description,
2188
+ showClose = true,
2189
+ onClose,
2190
+ ctaText,
2191
+ onCtaClick,
2192
+ ...props
2193
+ }, ref) => {
2194
+ const hasCTA = Boolean(ctaText);
2195
+ const shouldShowClose = showClose && !hasCTA;
2196
+ const hasExtendedContent = Boolean(hasCTA || description);
2197
+ const layout = hasExtendedContent ? "withDescription" : "default";
2198
+ const shouldShowDescription = description && !hasCTA;
2199
+ const IconComponent = {
2200
+ info: InfoFilled5,
2201
+ success: TickmarkFilled5,
2202
+ warning: WarningFilled4,
2203
+ error: WarningFilled4
2204
+ }[variant];
2205
+ const iconClassName = {
2206
+ info: "!text-blue-600",
2207
+ success: "!text-green-800",
2208
+ warning: "!text-orange-700",
2209
+ error: "!text-red-800"
2210
+ }[variant];
2211
+ return /* @__PURE__ */ jsxs13(
2212
+ "div",
2213
+ {
2214
+ ref,
2215
+ role: "alert",
2216
+ className: cn17(toastVariants({ variant, layout }), className),
2217
+ ...props,
2218
+ children: [
2219
+ /* @__PURE__ */ jsx17("div", { className: "flex-shrink-0 mt-0.5", children: /* @__PURE__ */ jsx17(IconComponent, { size: 20, className: iconClassName, "aria-hidden": "true" }) }),
2220
+ /* @__PURE__ */ jsxs13("div", { className: "flex-1 min-w-0 flex flex-col gap-4", children: [
2221
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2", children: [
2222
+ /* @__PURE__ */ jsx17("p", { className: "text-base font-medium leading-6 text-neutral-1100", children: title }),
2223
+ shouldShowDescription && /* @__PURE__ */ jsx17("p", { className: "text-sm font-normal leading-6 text-neutral-600", children: description })
2224
+ ] }),
2225
+ hasCTA && /* @__PURE__ */ jsx17(
2226
+ Button,
2227
+ {
2228
+ onClick: onCtaClick,
2229
+ size: "small",
2230
+ variant: "primary",
2231
+ className: "w-auto self-start mt-",
2232
+ children: ctaText
2233
+ }
2234
+ )
2235
+ ] }),
2236
+ shouldShowClose && /* @__PURE__ */ jsx17(
2237
+ "button",
2238
+ {
2239
+ onClick: onClose,
2240
+ className: "flex-shrink-0 self-start text-neutral-1100 hover:opacity-70 transition-opacity",
2241
+ "aria-label": "Close notification",
2242
+ type: "button",
2243
+ children: /* @__PURE__ */ jsx17(Close6, { size: 16 })
2244
+ }
2245
+ )
2246
+ ]
2247
+ }
2248
+ );
2249
+ }
2250
+ );
2251
+ Toast.displayName = "Toast";
2252
+
2253
+ // src/patterns/PageHeader.tsx
2254
+ import * as React18 from "react";
2255
+ import { cva as cva17 } from "class-variance-authority";
2256
+ import { cn as cn18 } from "@esds-sangam/utils";
2257
+ import { ArrowLeft, Close as Close7 } from "@esds-sangam/icons";
2258
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
2259
+ var pageHeaderVariants = cva17("w-full", {
2260
+ variants: {
2261
+ variant: {
2262
+ withTitle: "border-b border-neutral-200",
2263
+ withTabs: "border-b border-neutral-200",
2264
+ titleTabs: "border-b border-neutral-200"
2265
+ }
2266
+ },
2267
+ defaultVariants: {
2268
+ variant: "withTitle"
2269
+ }
2270
+ });
2271
+ var PageHeader = React18.forwardRef(
2272
+ ({
2273
+ className,
2274
+ variant = "withTitle",
2275
+ title,
2276
+ tabs = [],
2277
+ defaultTab,
2278
+ tab,
2279
+ onTabChange,
2280
+ titleClassName,
2281
+ tabsClassName,
2282
+ backIcon,
2283
+ onBackClick,
2284
+ showTitle = true,
2285
+ badgeLabel,
2286
+ showSubtext,
2287
+ subtext,
2288
+ primaryAction,
2289
+ secondaryAction,
2290
+ tertiaryAction,
2291
+ closeIcon,
2292
+ onCloseClick,
2293
+ ...props
2294
+ }, ref) => {
2295
+ const isControlled = tab !== void 0;
2296
+ const tabsValue = isControlled ? tab : defaultTab ?? tabs[0]?.value;
2297
+ const hasTabs = tabs.length > 0;
2298
+ const hasActions = !!primaryAction || !!secondaryAction || !!tertiaryAction || !!closeIcon;
2299
+ const renderActions = () => {
2300
+ if (!hasActions) return null;
2301
+ const actions = [];
2302
+ if (tertiaryAction) actions.push(tertiaryAction);
2303
+ if (secondaryAction) actions.push(secondaryAction);
2304
+ if (primaryAction) actions.push(primaryAction);
2305
+ return /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
2306
+ actions.map((action, index) => {
2307
+ const { label, onClick, variant: actionVariant, icon, iconPosition } = action;
2308
+ const leadingIcon = !!icon && (iconPosition ?? "leading") === "leading";
2309
+ const trailingIcon = !!icon && (iconPosition ?? "leading") === "trailing";
2310
+ return /* @__PURE__ */ jsx18(
2311
+ Button,
2312
+ {
2313
+ size: "small",
2314
+ variant: actionVariant ?? "primary",
2315
+ icon,
2316
+ leadingIcon,
2317
+ trailingIcon,
2318
+ onClick,
2319
+ children: label
2320
+ },
2321
+ `${label}-${index}`
2322
+ );
2323
+ }),
2324
+ closeIcon && /* @__PURE__ */ jsx18(Close7, { size: 16, className: "cursor-pointer", "aria-label": "Close", onClick: onCloseClick })
2325
+ ] });
2326
+ };
2327
+ const showTitleSection = variant === "withTitle" || variant === "titleTabs";
2328
+ const showTabsSection = variant === "withTabs" || variant === "titleTabs";
2329
+ return /* @__PURE__ */ jsxs14(
2330
+ "header",
2331
+ {
2332
+ ref,
2333
+ className: cn18(pageHeaderVariants({ variant }), className),
2334
+ ...props,
2335
+ children: [
2336
+ showTitleSection && /* @__PURE__ */ jsxs14("div", { className: "flex flex-col gap-1 px-4 py-3", children: [
2337
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-4", children: [
2338
+ /* @__PURE__ */ jsxs14("div", { className: "flex min-w-0 items-center gap-3", children: [
2339
+ backIcon && /* @__PURE__ */ jsx18(
2340
+ ArrowLeft,
2341
+ {
2342
+ size: 16,
2343
+ "aria-label": "Back",
2344
+ className: "cursor-pointer",
2345
+ onClick: onBackClick
2346
+ }
2347
+ ),
2348
+ showTitle && /* @__PURE__ */ jsx18(
2349
+ "h2",
2350
+ {
2351
+ className: cn18(
2352
+ "truncate text-xl font-semibold leading-7 text-neutral-1100",
2353
+ titleClassName
2354
+ ),
2355
+ children: title
2356
+ }
2357
+ ),
2358
+ badgeLabel && /* @__PURE__ */ jsx18(Badge, { size: "big", variant: "rounded", state: "info", children: badgeLabel })
2359
+ ] }),
2360
+ renderActions()
2361
+ ] }),
2362
+ showSubtext && subtext && /* @__PURE__ */ jsx18("p", { className: "px-[2px] text-sm leading-6 text-neutral-600", children: subtext })
2363
+ ] }),
2364
+ showTabsSection && hasTabs && /* @__PURE__ */ jsx18("div", { className: cn18("", tabsClassName), children: variant === "withTabs" ? /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-4", children: [
2365
+ /* @__PURE__ */ jsxs14(
2366
+ Tabs,
2367
+ {
2368
+ type: "underline",
2369
+ ...isControlled ? { value: tabsValue, onValueChange: onTabChange } : {
2370
+ defaultValue: defaultTab ?? tabs[0]?.value,
2371
+ onValueChange: onTabChange
2372
+ },
2373
+ className: "flex-1 pt-5",
2374
+ children: [
2375
+ /* @__PURE__ */ jsx18(Tabs.List, { children: tabs.map((t) => /* @__PURE__ */ jsx18(Tabs.Trigger, { value: t.value, children: t.label }, t.value)) }),
2376
+ tabs.map((t) => /* @__PURE__ */ jsx18(Tabs.Content, { value: t.value, className: "hidden" }, t.value))
2377
+ ]
2378
+ }
2379
+ ),
2380
+ renderActions()
2381
+ ] }) : /* @__PURE__ */ jsxs14(
2382
+ Tabs,
2383
+ {
2384
+ type: "underline",
2385
+ ...isControlled ? { value: tabsValue, onValueChange: onTabChange } : {
2386
+ defaultValue: defaultTab ?? tabs[0]?.value,
2387
+ onValueChange: onTabChange
2388
+ },
2389
+ className: "-mb-px mt-0 px-5",
2390
+ children: [
2391
+ /* @__PURE__ */ jsx18(Tabs.List, { className: "mt-0", children: tabs.map((t) => /* @__PURE__ */ jsx18(Tabs.Trigger, { value: t.value, children: t.label }, t.value)) }),
2392
+ tabs.map((t) => /* @__PURE__ */ jsx18(Tabs.Content, { value: t.value, className: "hidden" }, t.value))
2393
+ ]
2394
+ }
2395
+ ) })
2396
+ ]
2397
+ }
2398
+ );
2399
+ }
2400
+ );
2401
+ PageHeader.displayName = "PageHeader";
2402
+
2403
+ // src/patterns/PageFooter.tsx
2404
+ import * as React19 from "react";
2405
+ import { cn as cn19 } from "@esds-sangam/utils";
2406
+ import { jsx as jsx19 } from "react/jsx-runtime";
2407
+ var PAGE_FOOTER_WIDTH = 532;
2408
+ var PageFooter = React19.forwardRef(
2409
+ ({ className, children, width = PAGE_FOOTER_WIDTH, contentClassName, ...props }, ref) => {
2410
+ return /* @__PURE__ */ jsx19(
2411
+ "footer",
2412
+ {
2413
+ ref,
2414
+ className: cn19(
2415
+ "flex h-16 items-center gap-2 bg-white p-4 shadow-elevation-top-sm",
2416
+ className
2417
+ ),
2418
+ style: { width },
2419
+ ...props,
2420
+ children: /* @__PURE__ */ jsx19("div", { className: cn19("flex flex-1 items-center justify-end gap-2", contentClassName), children: children ?? /* @__PURE__ */ jsx19(Button, { variant: "primary", size: "small", children: "Convert" }) })
2421
+ }
2422
+ );
2423
+ }
2424
+ );
2425
+ PageFooter.displayName = "PageFooter";
2426
+
2427
+ // src/patterns/SideMenu.tsx
2428
+ import * as React20 from "react";
2429
+ import { cva as cva18 } from "class-variance-authority";
2430
+ import { cn as cn20 } from "@esds-sangam/utils";
2431
+ import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
2432
+ var sideMenuVariants = cva18(
2433
+ "flex flex-col self-start transition-[width] duration-200 ease-out",
2434
+ {
2435
+ variants: {
2436
+ variant: {
2437
+ default: "h-[1024px] w-[48px] rounded-r-lg bg-neutral-200 py-4 px-1.5",
2438
+ hover: "h-[1024px] w-[132px] rounded-r-lg bg-white border-l border-neutral-200 shadow-elevation-right-sm py-4 pl-3 pr-3",
2439
+ selected: "h-[1024px] w-[132px] rounded-r-lg bg-white border-l border-neutral-200 shadow-elevation-right-sm py-4 pl-3 pr-3"
2440
+ }
2441
+ },
2442
+ defaultVariants: {
2443
+ variant: "default"
2444
+ }
2445
+ }
2446
+ );
2447
+ var MENU_TEXT_STYLES = "text-xs font-medium leading-4 text-neutral-1100";
2448
+ var SideMenu = React20.forwardRef(
2449
+ ({
2450
+ className,
2451
+ variant = "default",
2452
+ logo,
2453
+ topItems,
2454
+ bottomItems,
2455
+ selectedId: selectedIdProp,
2456
+ defaultSelectedId,
2457
+ expanded: expandedProp,
2458
+ onItemClick,
2459
+ onMouseEnter,
2460
+ onMouseLeave,
2461
+ ...props
2462
+ }, ref) => {
2463
+ const [internalSelected, setInternalSelected] = React20.useState(
2464
+ defaultSelectedId ?? null
2465
+ );
2466
+ const selectedId = selectedIdProp !== void 0 ? selectedIdProp : internalSelected;
2467
+ const isControlled = selectedIdProp !== void 0;
2468
+ const [hoverExpanded, setHoverExpanded] = React20.useState(false);
2469
+ const isUncontrolledDefault = variant === "default" && expandedProp === void 0;
2470
+ const isExpandedByHover = isUncontrolledDefault && hoverExpanded;
2471
+ const effectiveExpanded = variant === "hover" || variant === "selected" || isExpandedByHover;
2472
+ const isCollapsed = !effectiveExpanded;
2473
+ const handleMouseEnter = (e) => {
2474
+ if (isUncontrolledDefault) setHoverExpanded(true);
2475
+ onMouseEnter?.(e);
2476
+ };
2477
+ const handleMouseLeave = (e) => {
2478
+ if (isUncontrolledDefault) setHoverExpanded(false);
2479
+ onMouseLeave?.(e);
2480
+ };
2481
+ const handleItemClick = (id) => {
2482
+ if (!isControlled) setInternalSelected(id);
2483
+ onItemClick?.(id);
2484
+ };
2485
+ return /* @__PURE__ */ jsx20(
2486
+ "div",
2487
+ {
2488
+ className: cn20("relative w-12 shrink-0 overflow-visible", className),
2489
+ ...props,
2490
+ children: /* @__PURE__ */ jsx20(
2491
+ "div",
2492
+ {
2493
+ className: "absolute left-0 top-0",
2494
+ onMouseEnter: handleMouseEnter,
2495
+ onMouseLeave: handleMouseLeave,
2496
+ children: /* @__PURE__ */ jsxs15(
2497
+ "nav",
2498
+ {
2499
+ ref,
2500
+ role: "navigation",
2501
+ "aria-label": "Side menu",
2502
+ "aria-expanded": isUncontrolledDefault ? isExpandedByHover : void 0,
2503
+ className: sideMenuVariants({
2504
+ variant: isExpandedByHover && selectedId ? "selected" : isExpandedByHover ? "hover" : variant
2505
+ }),
2506
+ children: [
2507
+ /* @__PURE__ */ jsx20(
2508
+ "div",
2509
+ {
2510
+ className: cn20(
2511
+ "mb-4 shrink-0 flex items-center",
2512
+ isCollapsed ? "justify-center" : "justify-start"
2513
+ ),
2514
+ children: logo
2515
+ }
2516
+ ),
2517
+ /* @__PURE__ */ jsx20("div", { className: "flex flex-1 flex-col gap-2", children: topItems.map((item) => {
2518
+ const isSelected = selectedId === item.id;
2519
+ const itemIcon = isCollapsed && !isSelected ? item.icon : item.iconExpanded ?? item.icon;
2520
+ return /* @__PURE__ */ jsx20(
2521
+ "button",
2522
+ {
2523
+ type: "button",
2524
+ onClick: () => handleItemClick(item.id),
2525
+ className: cn20(
2526
+ "inline-flex w-full items-center outline-none focus-visible:ring-2 focus-visible:ring-primary-600 focus-visible:ring-offset-2",
2527
+ isCollapsed ? "justify-center" : "justify-start"
2528
+ ),
2529
+ children: isCollapsed ? /* @__PURE__ */ jsx20(
2530
+ "span",
2531
+ {
2532
+ className: cn20(
2533
+ "flex h-9 w-9 items-center justify-center rounded-sm [&>svg]:size-5",
2534
+ isSelected && "border border-neutral-300 bg-white shadow-elevation-bottom-sm"
2535
+ ),
2536
+ children: itemIcon
2537
+ }
2538
+ ) : /* @__PURE__ */ jsxs15(
2539
+ "span",
2540
+ {
2541
+ className: cn20(
2542
+ "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-sm px-2",
2543
+ isSelected ? "mx-1 my-0.5 border border-neutral-300 bg-white shadow-elevation-bottom-sm" : "hover:bg-neutral-200/60"
2544
+ ),
2545
+ children: [
2546
+ /* @__PURE__ */ jsx20("span", { className: "shrink-0 [&>svg]:size-5", children: itemIcon }),
2547
+ /* @__PURE__ */ jsx20("span", { className: cn20(MENU_TEXT_STYLES, "truncate"), children: item.label })
2548
+ ]
2549
+ }
2550
+ )
2551
+ },
2552
+ item.id
2553
+ );
2554
+ }) }),
2555
+ /* @__PURE__ */ jsx20("div", { className: "flex flex-col gap-2 pt-4", children: bottomItems.map((item) => {
2556
+ const isSelected = selectedId === item.id;
2557
+ const itemIcon = isCollapsed && !isSelected ? item.icon : item.iconExpanded ?? item.icon;
2558
+ return /* @__PURE__ */ jsx20(
2559
+ "button",
2560
+ {
2561
+ type: "button",
2562
+ onClick: () => handleItemClick(item.id),
2563
+ className: cn20(
2564
+ "inline-flex w-full items-center outline-none focus-visible:ring-2 focus-visible:ring-primary-600 focus-visible:ring-offset-2",
2565
+ isCollapsed ? "justify-center" : "justify-start"
2566
+ ),
2567
+ children: isCollapsed ? /* @__PURE__ */ jsx20(
2568
+ "span",
2569
+ {
2570
+ className: cn20(
2571
+ "flex h-9 w-9 items-center justify-center rounded-sm [&>svg]:size-5",
2572
+ isSelected && "border border-neutral-300 bg-white shadow-elevation-bottom-sm"
2573
+ ),
2574
+ children: itemIcon
2575
+ }
2576
+ ) : /* @__PURE__ */ jsxs15(
2577
+ "span",
2578
+ {
2579
+ className: cn20(
2580
+ "flex h-9 min-w-0 flex-1 items-center gap-2 rounded-sm px-2",
2581
+ isSelected ? "mx-1 my-0.5 border border-neutral-300 bg-white shadow-elevation-bottom-sm" : "hover:bg-neutral-200/60"
2582
+ ),
2583
+ children: [
2584
+ /* @__PURE__ */ jsx20("span", { className: "shrink-0 [&>svg]:size-5", children: itemIcon }),
2585
+ /* @__PURE__ */ jsx20("span", { className: cn20(MENU_TEXT_STYLES, "truncate"), children: item.label })
2586
+ ]
2587
+ }
2588
+ )
2589
+ },
2590
+ item.id
2591
+ );
2592
+ }) })
2593
+ ]
2594
+ }
2595
+ )
2596
+ }
2597
+ )
2598
+ }
2599
+ );
2600
+ }
2601
+ );
2602
+ SideMenu.displayName = "SideMenu";
2603
+
2604
+ // src/patterns/Upload.tsx
2605
+ import * as React21 from "react";
2606
+ import { cva as cva19 } from "class-variance-authority";
2607
+ import { colors } from "@esds-sangam/tokens";
2608
+ import { cn as cn21 } from "@esds-sangam/utils";
2609
+ import { CloudUpload, DocumentPdf, Close as Close8, Delete, Retry, TickmarkFilled as TickmarkFilled6 } from "@esds-sangam/icons";
2610
+ import { Fragment as Fragment3, jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
2611
+ var uploadBoxVariants = cva19([
2612
+ "relative flex flex-col items-center justify-center w-full",
2613
+ "rounded-sm border border-dashed border-neutral-400 hover:border-neutral-700",
2614
+ "bg-white",
2615
+ "transition-colors duration-200 ease-out",
2616
+ "cursor-pointer"
2617
+ ]);
2618
+ var Upload = React21.forwardRef(
2619
+ ({
2620
+ className,
2621
+ label,
2622
+ required,
2623
+ accept,
2624
+ multiple,
2625
+ onFilesSelected,
2626
+ helperText = "PNG, JPG, PDF, EXCEL (max size)",
2627
+ ...props
2628
+ }, ref) => {
2629
+ const inputRef = React21.useRef(null);
2630
+ const handleClick = () => {
2631
+ inputRef.current?.click();
2632
+ };
2633
+ const handleFiles = (fileList) => {
2634
+ if (!fileList || !onFilesSelected) return;
2635
+ const files = Array.from(fileList);
2636
+ if (files.length) onFilesSelected(files);
2637
+ };
2638
+ const handleInputChange = (event) => {
2639
+ handleFiles(event.target.files);
2640
+ event.target.value = "";
2641
+ };
2642
+ const handleDrop = (event) => {
2643
+ event.preventDefault();
2644
+ handleFiles(event.dataTransfer.files);
2645
+ };
2646
+ const handleDragOver = (event) => {
2647
+ event.preventDefault();
2648
+ };
2649
+ return /* @__PURE__ */ jsxs16(
2650
+ "div",
2651
+ {
2652
+ ref,
2653
+ className: cn21("flex w-full min-w-[328px] flex-col gap-2", className),
2654
+ ...props,
2655
+ children: [
2656
+ /* @__PURE__ */ jsxs16("label", { className: "text-xs font-medium leading-4 text-neutral-1100", children: [
2657
+ label,
2658
+ required && /* @__PURE__ */ jsx21("span", { className: "text-red-800 ml-0.5", children: "*" })
2659
+ ] }),
2660
+ /* @__PURE__ */ jsx21(
2661
+ "input",
2662
+ {
2663
+ ref: inputRef,
2664
+ type: "file",
2665
+ accept,
2666
+ multiple,
2667
+ className: "hidden",
2668
+ onChange: handleInputChange
2669
+ }
2670
+ ),
2671
+ /* @__PURE__ */ jsx21(
2672
+ "div",
2673
+ {
2674
+ role: "button",
2675
+ tabIndex: 0,
2676
+ "aria-label": label,
2677
+ onClick: handleClick,
2678
+ onKeyDown: (e) => {
2679
+ if (e.key === "Enter" || e.key === " ") {
2680
+ e.preventDefault();
2681
+ handleClick();
2682
+ }
2683
+ },
2684
+ onDrop: handleDrop,
2685
+ onDragOver: handleDragOver,
2686
+ className: cn21(
2687
+ uploadBoxVariants(),
2688
+ // Padding: top/bottom 20px (py-5), left/right 12px (px-3)
2689
+ "py-5 px-3"
2690
+ ),
2691
+ children: /* @__PURE__ */ jsxs16("div", { className: "flex flex-col items-center gap-2 text-center", children: [
2692
+ /* @__PURE__ */ jsx21("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-blue-200 text-blue-600", children: /* @__PURE__ */ jsx21(CloudUpload, { size: 20, color: colors.blue["600"], "aria-hidden": "true" }) }),
2693
+ /* @__PURE__ */ jsxs16("div", { className: "flex flex-col gap-1", children: [
2694
+ /* @__PURE__ */ jsxs16("p", { className: "text-sm leading-6 text-neutral-1100", children: [
2695
+ /* @__PURE__ */ jsx21("span", { className: "font-normal", children: "Drop your files here or " }),
2696
+ /* @__PURE__ */ jsx21(
2697
+ "button",
2698
+ {
2699
+ type: "button",
2700
+ className: "font-medium text-blue-600 underline-offset-4 hover:underline",
2701
+ onClick: (e) => {
2702
+ e.stopPropagation();
2703
+ handleClick();
2704
+ },
2705
+ children: "Click to upload"
2706
+ }
2707
+ )
2708
+ ] }),
2709
+ /* @__PURE__ */ jsx21("p", { className: "text-xs font-normal leading-4 text-neutral-600", children: helperText })
2710
+ ] })
2711
+ ] })
2712
+ }
2713
+ )
2714
+ ]
2715
+ }
2716
+ );
2717
+ }
2718
+ );
2719
+ Upload.displayName = "Upload";
2720
+ var uploadFileItemBoxVariants = cva19(
2721
+ ["flex flex-col gap-2 rounded-md bg-white border p-4", "w-full min-w-[328px] min-h-[76px]"],
2722
+ {
2723
+ variants: {
2724
+ status: {
2725
+ uploading: "border-neutral-300",
2726
+ complete: "border-neutral-300",
2727
+ failed: "border-red-800"
2728
+ }
2729
+ },
2730
+ defaultVariants: {
2731
+ status: "uploading"
2732
+ }
2733
+ }
2734
+ );
2735
+ var UploadFileItem = React21.forwardRef(
2736
+ ({
2737
+ className,
2738
+ status = "uploading",
2739
+ fileName,
2740
+ fileSize,
2741
+ progress = 0,
2742
+ onCancel,
2743
+ onRetry,
2744
+ onDelete,
2745
+ ...props
2746
+ }, ref) => {
2747
+ const progressValue = Math.min(100, Math.max(0, progress));
2748
+ const showProgress = status !== "failed";
2749
+ return /* @__PURE__ */ jsxs16(
2750
+ "div",
2751
+ {
2752
+ ref,
2753
+ role: "listitem",
2754
+ className: cn21(uploadFileItemBoxVariants({ status }), className),
2755
+ ...props,
2756
+ children: [
2757
+ /* @__PURE__ */ jsxs16("div", { className: "flex min-w-0 flex-1 gap-3", children: [
2758
+ /* @__PURE__ */ jsxs16("div", { className: "flex flex-1 min-w-0 gap-2", children: [
2759
+ /* @__PURE__ */ jsx21(DocumentPdf, { size: 24, className: "shrink-0 text-neutral-1100", "aria-hidden": true }),
2760
+ /* @__PURE__ */ jsxs16("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
2761
+ /* @__PURE__ */ jsx21("p", { className: "truncate text-sm font-medium leading-6 text-neutral-1100", children: fileName }),
2762
+ status === "failed" ? /* @__PURE__ */ jsx21("p", { className: "text-xs font-normal leading-4 text-red-800", children: "Upload failed" }) : fileSize ? /* @__PURE__ */ jsx21("p", { className: "text-xs font-normal leading-4 text-neutral-600", children: fileSize }) : null
2763
+ ] })
2764
+ ] }),
2765
+ /* @__PURE__ */ jsxs16("div", { className: "flex shrink-0 flex-col items-end justify-center", children: [
2766
+ status === "uploading" && /* @__PURE__ */ jsx21(
2767
+ "button",
2768
+ {
2769
+ type: "button",
2770
+ onClick: onCancel,
2771
+ className: "inline-flex items-center justify-center rounded p-0 text-neutral-1100 hover:opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-neutral-700 focus-visible:ring-offset-1",
2772
+ "aria-label": "Cancel upload",
2773
+ children: /* @__PURE__ */ jsx21(Close8, { size: 20, "aria-hidden": true })
2774
+ }
2775
+ ),
2776
+ status === "complete" && /* @__PURE__ */ jsx21(Fragment3, { children: /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-4", children: [
2777
+ /* @__PURE__ */ jsx21(TickmarkFilled6, { size: 20, className: "!text-green-800 shrink-0", "aria-hidden": true }),
2778
+ /* @__PURE__ */ jsx21(
2779
+ "button",
2780
+ {
2781
+ type: "button",
2782
+ onClick: onDelete,
2783
+ className: "inline-flex items-center justify-center rounded p-0 text-neutral-1100 hover:opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-neutral-700 focus-visible:ring-offset-1",
2784
+ "aria-label": "Delete file",
2785
+ children: /* @__PURE__ */ jsx21(Delete, { size: 20, "aria-hidden": true })
2786
+ }
2787
+ )
2788
+ ] }) }),
2789
+ status === "failed" && /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-4", children: [
2790
+ /* @__PURE__ */ jsx21(
2791
+ "button",
2792
+ {
2793
+ type: "button",
2794
+ onClick: onRetry,
2795
+ className: "inline-flex items-center justify-center rounded p-0 text-neutral-1100 hover:opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-neutral-700 focus-visible:ring-offset-1",
2796
+ "aria-label": "Retry upload",
2797
+ children: /* @__PURE__ */ jsx21(Retry, { size: 20, "aria-hidden": true })
2798
+ }
2799
+ ),
2800
+ /* @__PURE__ */ jsx21(
2801
+ "button",
2802
+ {
2803
+ type: "button",
2804
+ onClick: onDelete,
2805
+ className: "inline-flex items-center justify-center rounded p-0 text-neutral-1100 hover:opacity-80 focus:outline-none focus-visible:ring-2 focus-visible:ring-neutral-700 focus-visible:ring-offset-1",
2806
+ "aria-label": "Delete file",
2807
+ children: /* @__PURE__ */ jsx21(Delete, { size: 20, "aria-hidden": true })
2808
+ }
2809
+ )
2810
+ ] })
2811
+ ] })
2812
+ ] }),
2813
+ showProgress && /* @__PURE__ */ jsxs16("div", { className: "flex w-full items-center gap-sm", children: [
2814
+ /* @__PURE__ */ jsx21(
2815
+ ProgressBar,
2816
+ {
2817
+ value: progressValue,
2818
+ showLabel: "none",
2819
+ fluid: true,
2820
+ "aria-label": `Upload progress ${progressValue}%`
2821
+ }
2822
+ ),
2823
+ /* @__PURE__ */ jsxs16("span", { className: "text-xs font-normal leading-4 text-neutral-600 shrink-0 text-right", children: [
2824
+ progressValue,
2825
+ "%"
2826
+ ] })
2827
+ ] })
2828
+ ]
2829
+ }
2830
+ );
2831
+ }
2832
+ );
2833
+ UploadFileItem.displayName = "UploadFileItem";
2834
+ export {
2835
+ Avatar,
2836
+ Badge,
2837
+ Button,
2838
+ Checkbox,
2839
+ Chip,
2840
+ Dropdown,
2841
+ DropdownMulti,
2842
+ Input,
2843
+ Label,
2844
+ Loader,
2845
+ PageFooter,
2846
+ PageHeader,
2847
+ ProgressBar,
2848
+ Radio,
2849
+ RadioGroup,
2850
+ SearchField,
2851
+ SideMenu,
2852
+ Skeleton,
2853
+ Tabs,
2854
+ TabsContent,
2855
+ TabsList,
2856
+ TabsRoot,
2857
+ TabsTrigger,
2858
+ Textarea,
2859
+ Toast,
2860
+ Toggle,
2861
+ Tooltip,
2862
+ TooltipContent,
2863
+ TooltipProvider,
2864
+ TooltipTrigger,
2865
+ Upload,
2866
+ UploadFileItem,
2867
+ avatarVariants,
2868
+ badgeVariants,
2869
+ buttonVariants,
2870
+ checkboxRootVariants as checkboxVariants,
2871
+ chipVariants,
2872
+ dropdownContentVariants,
2873
+ dropdownItemVariants,
2874
+ dropdownTriggerVariants,
2875
+ inputVariants,
2876
+ loaderVariants,
2877
+ pageHeaderVariants,
2878
+ radioVariants,
2879
+ searchFieldVariants,
2880
+ sideMenuVariants,
2881
+ skeletonVariants,
2882
+ tabsListVariants,
2883
+ tabsTriggerVariants,
2884
+ textareaVariants,
2885
+ toastVariants,
2886
+ toggleVariants,
2887
+ tooltipContentVariants,
2888
+ uploadBoxVariants,
2889
+ uploadFileItemBoxVariants
2890
+ };