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/README.md +603 -0
- package/assets/ESDS logo.png +0 -0
- package/dist/index.d.ts +1434 -0
- package/dist/index.js +2890 -0
- package/package.json +78 -0
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
|
+
};
|