@galyan/ui 0.0.1

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.
Files changed (95) hide show
  1. package/.turbo/turbo-build.log +20 -0
  2. package/dist/index.cjs +2291 -0
  3. package/dist/index.css +2558 -0
  4. package/dist/index.d.cts +498 -0
  5. package/dist/index.d.ts +498 -0
  6. package/dist/index.js +2235 -0
  7. package/eslint.config.mjs +4 -0
  8. package/package.json +43 -0
  9. package/src/accordion/Accordion.tsx +88 -0
  10. package/src/accordion/accordion.css +78 -0
  11. package/src/accordion/index.ts +2 -0
  12. package/src/animatednumber/AnimatedNumber.tsx +71 -0
  13. package/src/animatednumber/index.ts +2 -0
  14. package/src/banner/Banner.tsx +84 -0
  15. package/src/banner/banner.css +56 -0
  16. package/src/banner/index.ts +2 -0
  17. package/src/breadcrumb/Breadcrumb.tsx +94 -0
  18. package/src/breadcrumb/breadcrumb.css +58 -0
  19. package/src/breadcrumb/index.ts +2 -0
  20. package/src/button/Button.tsx +98 -0
  21. package/src/button/button.css +190 -0
  22. package/src/button/index.ts +2 -0
  23. package/src/button.tsx +20 -0
  24. package/src/calendar/Calendar.tsx +190 -0
  25. package/src/calendar/calendar.css +142 -0
  26. package/src/calendar/index.ts +2 -0
  27. package/src/card/Card.tsx +88 -0
  28. package/src/card/card.css +115 -0
  29. package/src/card/index.ts +2 -0
  30. package/src/card.tsx +27 -0
  31. package/src/chart/Chart.tsx +186 -0
  32. package/src/chart/index.ts +2 -0
  33. package/src/checkbox/Checkbox.tsx +101 -0
  34. package/src/checkbox/checkbox.css +76 -0
  35. package/src/checkbox/index.ts +2 -0
  36. package/src/chips/Chips.tsx +146 -0
  37. package/src/chips/chips.css +90 -0
  38. package/src/chips/index.ts +2 -0
  39. package/src/code.tsx +11 -0
  40. package/src/datepicker/DatePicker.tsx +104 -0
  41. package/src/datepicker/datepicker.css +22 -0
  42. package/src/datepicker/index.ts +2 -0
  43. package/src/dragdrop/DragDrop.tsx +168 -0
  44. package/src/dragdrop/dragdrop.css +122 -0
  45. package/src/dragdrop/index.ts +2 -0
  46. package/src/dropdown/Dropdown.tsx +176 -0
  47. package/src/dropdown/dropdown.css +118 -0
  48. package/src/dropdown/index.ts +2 -0
  49. package/src/fileupload/FileUpload.tsx +144 -0
  50. package/src/fileupload/fileupload.css +118 -0
  51. package/src/fileupload/index.ts +2 -0
  52. package/src/index.ts +28 -0
  53. package/src/input/Input.tsx +121 -0
  54. package/src/input/index.ts +2 -0
  55. package/src/input/input.css +120 -0
  56. package/src/menu/Menu.tsx +118 -0
  57. package/src/menu/index.ts +2 -0
  58. package/src/menu/menu.css +117 -0
  59. package/src/modal/Modal.tsx +103 -0
  60. package/src/modal/index.ts +2 -0
  61. package/src/modal/modal.css +79 -0
  62. package/src/progressbar/ProgressBar.tsx +68 -0
  63. package/src/progressbar/index.ts +2 -0
  64. package/src/progressbar/progressbar.css +73 -0
  65. package/src/radiogroup/RadioGroup.tsx +73 -0
  66. package/src/radiogroup/index.ts +2 -0
  67. package/src/radiogroup/radiogroup.css +80 -0
  68. package/src/skeleton/Skeleton.tsx +61 -0
  69. package/src/skeleton/index.ts +2 -0
  70. package/src/skeleton/skeleton.css +46 -0
  71. package/src/spinner/Spinner.tsx +29 -0
  72. package/src/spinner/index.ts +2 -0
  73. package/src/spinner/spinner.css +39 -0
  74. package/src/stepper/Stepper.tsx +127 -0
  75. package/src/stepper/index.ts +2 -0
  76. package/src/stepper/stepper.css +141 -0
  77. package/src/tab/Tabs.tsx +71 -0
  78. package/src/tab/index.ts +2 -0
  79. package/src/tab/tab.css +92 -0
  80. package/src/table/Table.tsx +205 -0
  81. package/src/table/index.ts +2 -0
  82. package/src/table/table.css +119 -0
  83. package/src/textarea/Textarea.tsx +102 -0
  84. package/src/textarea/index.ts +2 -0
  85. package/src/textarea/textarea.css +85 -0
  86. package/src/toaster/Toaster.tsx +108 -0
  87. package/src/toaster/index.ts +2 -0
  88. package/src/toaster/toaster.css +113 -0
  89. package/src/toggle/Toggle.tsx +88 -0
  90. package/src/toggle/index.ts +2 -0
  91. package/src/toggle/toggle.css +63 -0
  92. package/src/typography/Typography.tsx +58 -0
  93. package/src/typography/index.ts +2 -0
  94. package/src/typography/typography.css +102 -0
  95. package/tsconfig.json +13 -0
package/dist/index.cjs ADDED
@@ -0,0 +1,2291 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ Accordion: () => Accordion,
34
+ AnimatedNumber: () => AnimatedNumber,
35
+ Banner: () => Banner,
36
+ Breadcrumb: () => Breadcrumb,
37
+ Button: () => Button,
38
+ Calendar: () => Calendar,
39
+ Card: () => Card,
40
+ CardBody: () => CardBody,
41
+ CardFooter: () => CardFooter,
42
+ CardHeader: () => CardHeader,
43
+ CardInfo: () => CardInfo,
44
+ Chart: () => Chart,
45
+ Checkbox: () => Checkbox,
46
+ Chip: () => Chip,
47
+ ChipsInput: () => ChipsInput,
48
+ DatePicker: () => DatePicker,
49
+ Dropdown: () => Dropdown,
50
+ FileUpload: () => FileUpload,
51
+ Input: () => Input,
52
+ KanbanBoard: () => KanbanBoard,
53
+ Menu: () => Menu,
54
+ Modal: () => Modal,
55
+ ProgressBar: () => ProgressBar,
56
+ RadioGroup: () => RadioGroup,
57
+ ReorderList: () => ReorderList,
58
+ Skeleton: () => Skeleton,
59
+ Spinner: () => Spinner,
60
+ Stepper: () => Stepper,
61
+ Table: () => Table,
62
+ Tabs: () => Tabs,
63
+ Textarea: () => Textarea,
64
+ ToasterProvider: () => ToasterProvider,
65
+ Toggle: () => Toggle,
66
+ Tooltip: () => Tooltip,
67
+ Typography: () => Typography,
68
+ useToast: () => useToast
69
+ });
70
+ module.exports = __toCommonJS(index_exports);
71
+
72
+ // src/button/Button.tsx
73
+ var import_react = require("react");
74
+ var import_jsx_runtime = require("react/jsx-runtime");
75
+ var Button = (0, import_react.forwardRef)(function Button2({
76
+ variant = "solid",
77
+ size = "md",
78
+ loading = false,
79
+ fullWidth = false,
80
+ leftIcon,
81
+ rightIcon,
82
+ disabled,
83
+ children,
84
+ className = "",
85
+ onClick,
86
+ as: Component = "button",
87
+ ...rest
88
+ }, ref) {
89
+ const rippleRef = (0, import_react.useRef)(null);
90
+ const handleClick = (0, import_react.useCallback)(
91
+ (e) => {
92
+ const btn = e.currentTarget;
93
+ const rect = btn.getBoundingClientRect();
94
+ const size2 = Math.max(rect.width, rect.height);
95
+ const x = e.clientX - rect.left - size2 / 2;
96
+ const y = e.clientY - rect.top - size2 / 2;
97
+ const ripple = document.createElement("span");
98
+ ripple.className = "gy-btn__ripple";
99
+ ripple.style.width = ripple.style.height = `${size2}px`;
100
+ ripple.style.left = `${x}px`;
101
+ ripple.style.top = `${y}px`;
102
+ btn.appendChild(ripple);
103
+ setTimeout(() => ripple.remove(), 600);
104
+ onClick?.(e);
105
+ },
106
+ [onClick]
107
+ );
108
+ const isDisabled = disabled || loading;
109
+ const iconOnly = !children && (leftIcon || rightIcon);
110
+ const classes = [
111
+ "gy-btn",
112
+ `gy-btn--${variant}`,
113
+ `gy-btn--${size}`,
114
+ fullWidth ? "gy-btn--full" : "",
115
+ loading ? "gy-btn--loading" : "",
116
+ iconOnly ? "gy-btn--icon-only" : "",
117
+ isDisabled ? "gy-btn--disabled" : "",
118
+ className
119
+ ].filter(Boolean).join(" ");
120
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
121
+ Component,
122
+ {
123
+ ref,
124
+ className: classes,
125
+ disabled: isDisabled,
126
+ onClick: handleClick,
127
+ "aria-busy": loading,
128
+ ...rest,
129
+ children: [
130
+ loading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gy-btn__spinner", "aria-hidden": "true" }) : leftIcon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gy-btn__icon gy-btn__icon--left", "aria-hidden": "true", children: leftIcon }),
131
+ children && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children }),
132
+ !loading && rightIcon && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "gy-btn__icon gy-btn__icon--right", "aria-hidden": "true", children: rightIcon })
133
+ ]
134
+ }
135
+ );
136
+ });
137
+
138
+ // src/typography/Typography.tsx
139
+ var import_jsx_runtime2 = require("react/jsx-runtime");
140
+ var variantTagMap = {
141
+ h1: "h1",
142
+ h2: "h2",
143
+ h3: "h3",
144
+ h4: "h4",
145
+ h5: "h5",
146
+ h6: "h6",
147
+ "body-xl": "p",
148
+ "body-lg": "p",
149
+ "body-md": "p",
150
+ "body-sm": "p",
151
+ "body-xs": "p",
152
+ "caption-lg": "span",
153
+ "caption-md": "span",
154
+ label: "label",
155
+ code: "code"
156
+ };
157
+ function Typography({
158
+ variant = "body-md",
159
+ color = "default",
160
+ as,
161
+ truncate = false,
162
+ className = "",
163
+ children,
164
+ ...rest
165
+ }) {
166
+ const Tag = as ?? variantTagMap[variant];
167
+ const classes = [
168
+ "gy-text",
169
+ `gy-text--${variant}`,
170
+ `gy-text--color-${color}`,
171
+ truncate ? "gy-text--truncate" : "",
172
+ className
173
+ ].filter(Boolean).join(" ");
174
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Tag, { className: classes, ...rest, children });
175
+ }
176
+
177
+ // src/input/Input.tsx
178
+ var import_react2 = require("react");
179
+ var import_jsx_runtime3 = require("react/jsx-runtime");
180
+ var Input = (0, import_react2.forwardRef)(function Input2({
181
+ label,
182
+ size = "md",
183
+ error,
184
+ helperText,
185
+ leftIcon,
186
+ rightIcon,
187
+ clearable,
188
+ onClear,
189
+ required,
190
+ fullWidth = true,
191
+ disabled,
192
+ className = "",
193
+ id,
194
+ value,
195
+ onChange,
196
+ ...rest
197
+ }, ref) {
198
+ const uid = (0, import_react2.useId)();
199
+ const inputId = id ?? uid;
200
+ const wrapperClasses = [
201
+ "gy-input-wrapper",
202
+ `gy-input-wrapper--${size}`,
203
+ error ? "gy-input-wrapper--error" : "",
204
+ disabled ? "gy-input-wrapper--disabled" : ""
205
+ ].filter(Boolean).join(" ");
206
+ const showClear = clearable && value && !disabled;
207
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `gy-input-root ${fullWidth ? "" : "gy-input-root--inline"} ${className}`, children: [
208
+ label && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
209
+ "label",
210
+ {
211
+ className: `gy-input-label ${required ? "gy-input-label--required" : ""}`,
212
+ htmlFor: inputId,
213
+ children: label
214
+ }
215
+ ),
216
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: wrapperClasses, children: [
217
+ leftIcon && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "gy-input-addon gy-input-addon--left", "aria-hidden": "true", children: leftIcon }),
218
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
219
+ "input",
220
+ {
221
+ ref,
222
+ id: inputId,
223
+ className: "gy-input",
224
+ disabled,
225
+ required,
226
+ "aria-invalid": !!error,
227
+ "aria-describedby": error ? `${inputId}-error` : helperText ? `${inputId}-helper` : void 0,
228
+ value,
229
+ onChange,
230
+ ...rest
231
+ }
232
+ ),
233
+ showClear && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
234
+ "button",
235
+ {
236
+ type: "button",
237
+ className: "gy-input-clear",
238
+ onClick: onClear,
239
+ "aria-label": "Clear input",
240
+ tabIndex: -1,
241
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
242
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "1", y1: "1", x2: "13", y2: "13" }),
243
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "13", y1: "1", x2: "1", y2: "13" })
244
+ ] })
245
+ }
246
+ ),
247
+ rightIcon && !showClear && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "gy-input-addon gy-input-addon--right", "aria-hidden": "true", children: rightIcon })
248
+ ] }),
249
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { id: `${inputId}-error`, className: "gy-input-helper gy-input-helper--error", role: "alert", children: error }),
250
+ !error && helperText && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { id: `${inputId}-helper`, className: "gy-input-helper", children: helperText })
251
+ ] });
252
+ });
253
+
254
+ // src/textarea/Textarea.tsx
255
+ var import_react3 = require("react");
256
+ var import_jsx_runtime4 = require("react/jsx-runtime");
257
+ var Textarea = (0, import_react3.forwardRef)(function Textarea2({
258
+ label,
259
+ error,
260
+ helperText,
261
+ maxCharCount,
262
+ autoResize = false,
263
+ required,
264
+ disabled,
265
+ value,
266
+ onChange,
267
+ className = "",
268
+ id,
269
+ ...rest
270
+ }, ref) {
271
+ const uid = (0, import_react3.useId)();
272
+ const inputId = id ?? uid;
273
+ const innerRef = (0, import_react3.useRef)(null);
274
+ const textareaRef = ref ?? innerRef;
275
+ const charCount = typeof value === "string" ? value.length : 0;
276
+ const isOver = maxCharCount ? charCount > maxCharCount : false;
277
+ const adjustHeight = (0, import_react3.useCallback)(() => {
278
+ const el = textareaRef.current;
279
+ if (!el || !autoResize) return;
280
+ el.style.height = "auto";
281
+ el.style.height = `${el.scrollHeight}px`;
282
+ }, [autoResize, textareaRef]);
283
+ (0, import_react3.useEffect)(() => {
284
+ adjustHeight();
285
+ }, [value, adjustHeight]);
286
+ const handleChange = (e) => {
287
+ adjustHeight();
288
+ onChange?.(e);
289
+ };
290
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `gy-textarea-root ${className}`, children: [
291
+ label && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
292
+ "label",
293
+ {
294
+ className: `gy-textarea-label ${required ? "gy-textarea-label--required" : ""}`,
295
+ htmlFor: inputId,
296
+ children: label
297
+ }
298
+ ),
299
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
300
+ "textarea",
301
+ {
302
+ ref: textareaRef,
303
+ id: inputId,
304
+ className: [
305
+ "gy-textarea",
306
+ error ? "gy-textarea--error" : "",
307
+ autoResize ? "gy-textarea--auto-resize" : ""
308
+ ].filter(Boolean).join(" "),
309
+ disabled,
310
+ required,
311
+ "aria-invalid": !!error,
312
+ value,
313
+ onChange: handleChange,
314
+ ...rest
315
+ }
316
+ ),
317
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "gy-textarea-footer", children: [
318
+ error ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "gy-textarea-helper gy-textarea-helper--error", role: "alert", children: error }) : helperText ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "gy-textarea-helper", children: helperText }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", {}),
319
+ maxCharCount !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: `gy-textarea-count ${isOver ? "gy-textarea-count--over" : ""}`, children: [
320
+ charCount,
321
+ "/",
322
+ maxCharCount
323
+ ] })
324
+ ] })
325
+ ] });
326
+ });
327
+
328
+ // src/checkbox/Checkbox.tsx
329
+ var import_react4 = require("react");
330
+ var import_jsx_runtime5 = require("react/jsx-runtime");
331
+ var Checkbox = (0, import_react4.forwardRef)(function Checkbox2({
332
+ checked,
333
+ defaultChecked,
334
+ indeterminate = false,
335
+ onChange,
336
+ disabled = false,
337
+ label,
338
+ description,
339
+ size = "md",
340
+ id,
341
+ name,
342
+ value,
343
+ className = ""
344
+ }, ref) {
345
+ const uid = (0, import_react4.useId)();
346
+ const inputId = id ?? uid;
347
+ const isChecked = checked ?? defaultChecked ?? false;
348
+ const boxClasses = [
349
+ "gy-checkbox-box",
350
+ `gy-checkbox-box--${size}`,
351
+ isChecked ? "gy-checkbox-box--checked" : "",
352
+ indeterminate ? "gy-checkbox-box--indeterminate" : ""
353
+ ].filter(Boolean).join(" ");
354
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
355
+ "label",
356
+ {
357
+ className: [
358
+ "gy-checkbox-root",
359
+ disabled ? "gy-checkbox-root--disabled" : "",
360
+ className
361
+ ].filter(Boolean).join(" "),
362
+ htmlFor: inputId,
363
+ children: [
364
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
365
+ "input",
366
+ {
367
+ ref,
368
+ type: "checkbox",
369
+ id: inputId,
370
+ name,
371
+ value,
372
+ checked,
373
+ defaultChecked,
374
+ disabled,
375
+ className: "gy-checkbox-input",
376
+ onChange: (e) => onChange?.(e.target.checked),
377
+ "aria-checked": indeterminate ? "mixed" : checked
378
+ }
379
+ ),
380
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: boxClasses, "aria-hidden": "true", children: (isChecked || indeterminate) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "gy-checkbox-icon", children: indeterminate ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "10", height: "2", viewBox: "0 0 10 2", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("rect", { x: "0", y: "0", width: "10", height: "2", rx: "1" }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "10", height: "8", viewBox: "0 0 10 8", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("polyline", { points: "1,4 4,7 9,1" }) }) }) }),
381
+ (label || description) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "gy-checkbox-content", children: [
382
+ label && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "gy-checkbox-label", children: label }),
383
+ description && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "gy-checkbox-description", children: description })
384
+ ] })
385
+ ]
386
+ }
387
+ );
388
+ });
389
+
390
+ // src/radiogroup/RadioGroup.tsx
391
+ var import_react5 = require("react");
392
+ var import_jsx_runtime6 = require("react/jsx-runtime");
393
+ function RadioGroup({
394
+ options,
395
+ value,
396
+ defaultValue,
397
+ onChange,
398
+ orientation = "vertical",
399
+ groupLabel,
400
+ name,
401
+ disabled = false,
402
+ className = ""
403
+ }) {
404
+ const uid = (0, import_react5.useId)();
405
+ const groupName = name ?? uid;
406
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
407
+ "div",
408
+ {
409
+ role: "radiogroup",
410
+ "aria-label": typeof groupLabel === "string" ? groupLabel : void 0,
411
+ className: `gy-radio-group ${orientation === "horizontal" ? "gy-radio-group--horizontal" : ""} ${className}`,
412
+ children: [
413
+ groupLabel && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "gy-radio-group-label", children: groupLabel }),
414
+ options.map((opt) => {
415
+ const isChecked = value !== void 0 ? value === opt.value : void 0;
416
+ const isDisabled = disabled || opt.disabled;
417
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
418
+ "label",
419
+ {
420
+ className: `gy-radio ${isDisabled ? "gy-radio--disabled" : ""}`,
421
+ children: [
422
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
423
+ "input",
424
+ {
425
+ type: "radio",
426
+ name: groupName,
427
+ value: opt.value,
428
+ checked: isChecked,
429
+ defaultChecked: defaultValue === opt.value,
430
+ disabled: isDisabled,
431
+ className: "gy-radio-input",
432
+ onChange: () => onChange?.(opt.value)
433
+ }
434
+ ),
435
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: `gy-radio-circle ${isChecked ? "gy-radio-circle--checked" : ""}`, children: isChecked && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "gy-radio-dot" }) }),
436
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "gy-radio-label", children: opt.label })
437
+ ]
438
+ },
439
+ opt.value
440
+ );
441
+ })
442
+ ]
443
+ }
444
+ );
445
+ }
446
+
447
+ // src/toggle/Toggle.tsx
448
+ var import_react6 = require("react");
449
+ var import_jsx_runtime7 = require("react/jsx-runtime");
450
+ var Toggle = (0, import_react6.forwardRef)(function Toggle2({
451
+ checked,
452
+ defaultChecked,
453
+ onChange,
454
+ disabled = false,
455
+ label,
456
+ labelPosition = "right",
457
+ size = "md",
458
+ id,
459
+ name,
460
+ className = ""
461
+ }, ref) {
462
+ const uid = (0, import_react6.useId)();
463
+ const inputId = id ?? uid;
464
+ const isChecked = checked ?? defaultChecked ?? false;
465
+ const track = /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
466
+ "span",
467
+ {
468
+ className: [
469
+ "gy-toggle-track",
470
+ `gy-toggle-track--${size}`,
471
+ isChecked ? "gy-toggle-track--checked" : ""
472
+ ].filter(Boolean).join(" "),
473
+ "aria-hidden": "true",
474
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "gy-toggle-thumb" })
475
+ }
476
+ );
477
+ const labelEl = label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "gy-toggle-label", children: label });
478
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
479
+ "label",
480
+ {
481
+ htmlFor: inputId,
482
+ className: [
483
+ "gy-toggle-root",
484
+ disabled ? "gy-toggle-root--disabled" : "",
485
+ className
486
+ ].filter(Boolean).join(" "),
487
+ children: [
488
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
489
+ "input",
490
+ {
491
+ ref,
492
+ id: inputId,
493
+ type: "checkbox",
494
+ role: "switch",
495
+ name,
496
+ checked,
497
+ defaultChecked,
498
+ disabled,
499
+ className: "gy-toggle-input",
500
+ "aria-checked": isChecked,
501
+ onChange: (e) => onChange?.(e.target.checked)
502
+ }
503
+ ),
504
+ labelPosition === "left" && labelEl,
505
+ track,
506
+ labelPosition === "right" && labelEl
507
+ ]
508
+ }
509
+ );
510
+ });
511
+
512
+ // src/chips/Chips.tsx
513
+ var import_react7 = require("react");
514
+ var import_jsx_runtime8 = require("react/jsx-runtime");
515
+ function Chip({
516
+ children,
517
+ variant = "soft",
518
+ size = "md",
519
+ removable = false,
520
+ onRemove,
521
+ clickable = false,
522
+ selected = false,
523
+ onClick,
524
+ icon,
525
+ className = ""
526
+ }) {
527
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
528
+ "span",
529
+ {
530
+ className: [
531
+ "gy-chip",
532
+ `gy-chip--${variant}`,
533
+ `gy-chip--${size}`,
534
+ clickable ? "gy-chip--clickable" : "",
535
+ selected ? "gy-chip--selected" : "",
536
+ className
537
+ ].filter(Boolean).join(" "),
538
+ role: clickable ? "button" : void 0,
539
+ tabIndex: clickable ? 0 : void 0,
540
+ onClick: clickable ? onClick : void 0,
541
+ onKeyDown: clickable ? (e) => {
542
+ if (e.key === "Enter" || e.key === " ") onClick?.();
543
+ } : void 0,
544
+ children: [
545
+ icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": "true", children: icon }),
546
+ children,
547
+ removable && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
548
+ "button",
549
+ {
550
+ type: "button",
551
+ className: "gy-chip__remove",
552
+ onClick: (e) => {
553
+ e.stopPropagation();
554
+ onRemove?.();
555
+ },
556
+ "aria-label": "Remove",
557
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("svg", { width: "8", height: "8", viewBox: "0 0 8 8", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", children: [
558
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "1", y1: "1", x2: "7", y2: "7" }),
559
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("line", { x1: "7", y1: "1", x2: "1", y2: "7" })
560
+ ] })
561
+ }
562
+ )
563
+ ]
564
+ }
565
+ );
566
+ }
567
+ function ChipsInput({
568
+ values,
569
+ onChange,
570
+ placeholder = "Add a tag...",
571
+ disabled = false,
572
+ maxItems,
573
+ chipVariant = "soft",
574
+ className = ""
575
+ }) {
576
+ const [input, setInput] = (0, import_react7.useState)("");
577
+ const inputRef = (0, import_react7.useRef)(null);
578
+ const addChip = (val) => {
579
+ const trimmed = val.trim();
580
+ if (!trimmed || values.includes(trimmed)) return;
581
+ if (maxItems && values.length >= maxItems) return;
582
+ onChange([...values, trimmed]);
583
+ setInput("");
584
+ };
585
+ const removeChip = (idx) => {
586
+ onChange(values.filter((_, i) => i !== idx));
587
+ };
588
+ const handleKeyDown = (e) => {
589
+ if (e.key === "Enter" || e.key === ",") {
590
+ e.preventDefault();
591
+ addChip(input);
592
+ }
593
+ if (e.key === "Backspace" && !input && values.length > 0) {
594
+ removeChip(values.length - 1);
595
+ }
596
+ };
597
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
598
+ "div",
599
+ {
600
+ className: `gy-chips-input ${className}`,
601
+ onClick: () => inputRef.current?.focus(),
602
+ children: [
603
+ values.map((val, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
604
+ Chip,
605
+ {
606
+ variant: chipVariant,
607
+ size: "sm",
608
+ removable: !disabled,
609
+ onRemove: () => removeChip(i),
610
+ children: val
611
+ },
612
+ i
613
+ )),
614
+ (!maxItems || values.length < maxItems) && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
615
+ "input",
616
+ {
617
+ ref: inputRef,
618
+ className: "gy-chips-input__field",
619
+ value: input,
620
+ onChange: (e) => setInput(e.target.value),
621
+ onKeyDown: handleKeyDown,
622
+ onBlur: () => addChip(input),
623
+ placeholder: values.length === 0 ? placeholder : "",
624
+ disabled,
625
+ "aria-label": placeholder
626
+ }
627
+ )
628
+ ]
629
+ }
630
+ );
631
+ }
632
+
633
+ // src/card/Card.tsx
634
+ var import_jsx_runtime9 = require("react/jsx-runtime");
635
+ function Card({ variant = "default", size = "md", hoverable = false, className = "", children, onClick, style }) {
636
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
637
+ "div",
638
+ {
639
+ className: [
640
+ "gy-card",
641
+ variant !== "default" ? `gy-card--${variant}` : "",
642
+ size !== "md" ? `gy-card--${size}` : "",
643
+ hoverable ? "gy-card--hoverable" : "",
644
+ className
645
+ ].filter(Boolean).join(" "),
646
+ onClick,
647
+ style,
648
+ role: onClick ? "button" : void 0,
649
+ tabIndex: onClick ? 0 : void 0,
650
+ children
651
+ }
652
+ );
653
+ }
654
+ function CardHeader({ children, className = "" }) {
655
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `gy-card-header ${className}`, children });
656
+ }
657
+ function CardBody({ children, size, className = "" }) {
658
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: ["gy-card-body", size ? `gy-card-body--${size}` : "", className].filter(Boolean).join(" "), children });
659
+ }
660
+ function CardFooter({ children, className = "" }) {
661
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: `gy-card-footer ${className}`, children });
662
+ }
663
+ function CardInfo({ title, value, icon, trend, footer, className = "" }) {
664
+ const isUp = trend ? trend.value >= 0 : null;
665
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: `gy-card-info ${className}`, children: [
666
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "gy-card-info__header", children: [
667
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "gy-card-info__title", children: title }),
668
+ icon && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "gy-card-info__icon", children: icon })
669
+ ] }),
670
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gy-card-info__value", children: value }),
671
+ trend && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { className: `gy-card-info__trend gy-card-info__trend--${isUp ? "up" : "down"}`, children: [
672
+ isUp ? "\u2191" : "\u2193",
673
+ " ",
674
+ Math.abs(trend.value),
675
+ "%",
676
+ trend.label && ` ${trend.label}`
677
+ ] }) }),
678
+ footer && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "gy-card-info__footer", children: footer })
679
+ ] });
680
+ }
681
+
682
+ // src/spinner/Spinner.tsx
683
+ var import_jsx_runtime10 = require("react/jsx-runtime");
684
+ function Spinner({ size = "md", color = "primary", label, className = "" }) {
685
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: `gy-spinner-container ${className}`, children: [
686
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
687
+ "span",
688
+ {
689
+ className: `gy-spinner gy-spinner--${size} gy-spinner--${color}`,
690
+ role: "status",
691
+ "aria-label": label ?? "Loading...",
692
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "gy-spinner__circle", "aria-hidden": "true" })
693
+ }
694
+ ),
695
+ label && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "gy-spinner__label", children: label })
696
+ ] });
697
+ }
698
+
699
+ // src/progressbar/ProgressBar.tsx
700
+ var import_jsx_runtime11 = require("react/jsx-runtime");
701
+ function ProgressBar({
702
+ value = 0,
703
+ max = 100,
704
+ size = "md",
705
+ color = "primary",
706
+ label,
707
+ showValue = false,
708
+ striped = false,
709
+ indeterminate = false,
710
+ className = ""
711
+ }) {
712
+ const pct = Math.min(Math.max(value / max * 100, 0), 100);
713
+ const fillClasses = [
714
+ "gy-progress-fill",
715
+ color !== "primary" ? `gy-progress-fill--${color}` : "",
716
+ striped ? "gy-progress-fill--striped" : "",
717
+ indeterminate ? "gy-progress-fill--indeterminate" : ""
718
+ ].filter(Boolean).join(" ");
719
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `gy-progress ${className}`, children: [
720
+ (label || showValue) && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "gy-progress-header", children: [
721
+ label && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "gy-progress-label", children: label }),
722
+ showValue && !indeterminate && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "gy-progress-value", children: [
723
+ Math.round(pct),
724
+ "%"
725
+ ] })
726
+ ] }),
727
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
728
+ "div",
729
+ {
730
+ className: `gy-progress-track gy-progress-track--${size}`,
731
+ role: "progressbar",
732
+ "aria-valuenow": indeterminate ? void 0 : value,
733
+ "aria-valuemin": 0,
734
+ "aria-valuemax": max,
735
+ "aria-label": label ?? "Progress",
736
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
737
+ "div",
738
+ {
739
+ className: fillClasses,
740
+ style: { width: indeterminate ? void 0 : `${pct}%` }
741
+ }
742
+ )
743
+ }
744
+ )
745
+ ] });
746
+ }
747
+
748
+ // src/skeleton/Skeleton.tsx
749
+ var import_jsx_runtime12 = require("react/jsx-runtime");
750
+ function Skeleton({
751
+ shape = "rect",
752
+ animation = "wave",
753
+ width,
754
+ height,
755
+ className = "",
756
+ lines,
757
+ gap = "0.5rem"
758
+ }) {
759
+ const classes = [
760
+ "gy-skeleton",
761
+ `gy-skeleton--${shape}`,
762
+ animation !== "none" ? `gy-skeleton--${animation}` : "",
763
+ !width ? "gy-skeleton--w-full" : "",
764
+ className
765
+ ].filter(Boolean).join(" ");
766
+ const style = {
767
+ width,
768
+ height
769
+ };
770
+ if (lines) {
771
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { display: "flex", flexDirection: "column", gap }, children: Array.from({ length: lines }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
772
+ "div",
773
+ {
774
+ className: `gy-skeleton gy-skeleton--text ${animation !== "none" ? `gy-skeleton--${animation}` : ""} ${i === lines - 1 ? "gy-skeleton--w-3-4" : "gy-skeleton--w-full"}`,
775
+ style: { height: height ?? "1em" },
776
+ "aria-hidden": "true"
777
+ },
778
+ i
779
+ )) });
780
+ }
781
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: classes, style, "aria-hidden": "true" });
782
+ }
783
+
784
+ // src/banner/Banner.tsx
785
+ var import_react8 = require("react");
786
+ var import_jsx_runtime13 = require("react/jsx-runtime");
787
+ var icons = {
788
+ info: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M8 1a7 7 0 100 14A7 7 0 008 1zm0 3a1 1 0 110 2 1 1 0 010-2zm0 3a.75.75 0 01.75.75v3.5a.75.75 0 01-1.5 0v-3.5A.75.75 0 018 7z" }) }),
789
+ success: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M8 1a7 7 0 100 14A7 7 0 008 1zm3.78 5.78a.75.75 0 00-1.06-1.06L7 9.44 5.28 7.72a.75.75 0 00-1.06 1.06l2.25 2.25a.75.75 0 001.06 0l4.25-4.25z" }) }),
790
+ warning: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M8 1.5a.75.75 0 01.65.375l6 10.5A.75.75 0 0114 13.5H2a.75.75 0 01-.65-1.125l6-10.5A.75.75 0 018 1.5zm0 4a.75.75 0 01.75.75v3a.75.75 0 01-1.5 0v-3A.75.75 0 018 5.5zm0 6.5a1 1 0 110-2 1 1 0 010 2z" }) }),
791
+ danger: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M8 1a7 7 0 100 14A7 7 0 008 1zm0 3a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 018 4zm0 7.5a1 1 0 110-2 1 1 0 010 2z" }) }),
792
+ neutral: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("path", { d: "M8 1a7 7 0 100 14A7 7 0 008 1zm0 3a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 018 4zm0 7.5a1 1 0 110-2 1 1 0 010 2z" }) })
793
+ };
794
+ function Banner({
795
+ variant = "info",
796
+ layout = "inline",
797
+ title,
798
+ description,
799
+ icon,
800
+ dismissible = false,
801
+ onDismiss,
802
+ className = ""
803
+ }) {
804
+ const [dismissed, setDismissed] = (0, import_react8.useState)(false);
805
+ if (dismissed) return null;
806
+ const handleDismiss = () => {
807
+ setDismissed(true);
808
+ onDismiss?.();
809
+ };
810
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
811
+ "div",
812
+ {
813
+ className: [
814
+ "gy-banner",
815
+ `gy-banner--${variant}`,
816
+ `gy-banner--${layout}`,
817
+ className
818
+ ].filter(Boolean).join(" "),
819
+ role: "alert",
820
+ children: [
821
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "gy-banner__icon", children: icon ?? icons[variant] }),
822
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "gy-banner__content", children: [
823
+ title && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gy-banner__title", children: title }),
824
+ description && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "gy-banner__description", children: description })
825
+ ] }),
826
+ dismissible && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("button", { className: "gy-banner__close", onClick: handleDismiss, "aria-label": "Dismiss", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
827
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("line", { x1: "1", y1: "1", x2: "11", y2: "11" }),
828
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("line", { x1: "11", y1: "1", x2: "1", y2: "11" })
829
+ ] }) })
830
+ ]
831
+ }
832
+ );
833
+ }
834
+
835
+ // src/breadcrumb/Breadcrumb.tsx
836
+ var import_react9 = require("react");
837
+ var import_jsx_runtime14 = require("react/jsx-runtime");
838
+ var DefaultSeparator = () => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("polyline", { points: "4,2 8,6 4,10" }) });
839
+ function Breadcrumb({
840
+ items,
841
+ separator = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(DefaultSeparator, {}),
842
+ maxItems,
843
+ className = ""
844
+ }) {
845
+ const [expanded, setExpanded] = (0, import_react9.useState)(false);
846
+ const shouldCollapse = maxItems && items.length > maxItems + 1 && !expanded;
847
+ const displayed = [];
848
+ if (shouldCollapse) {
849
+ const first = items[0];
850
+ const last = items[items.length - 1];
851
+ displayed.push(renderItem(first, false, separator));
852
+ displayed.push(
853
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { className: "gy-breadcrumb-item", children: [
854
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "gy-breadcrumb-separator", children: separator }),
855
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
856
+ "button",
857
+ {
858
+ className: "gy-breadcrumb-ellipsis",
859
+ onClick: () => setExpanded(true),
860
+ "aria-label": "Show more breadcrumbs",
861
+ children: "\u2022\u2022\u2022"
862
+ }
863
+ )
864
+ ] }, "ellipsis")
865
+ );
866
+ displayed.push(renderItem(last, true, separator));
867
+ } else {
868
+ items.forEach((item, i) => {
869
+ displayed.push(renderItem(item, i === items.length - 1, separator, i));
870
+ });
871
+ }
872
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("nav", { "aria-label": "Breadcrumb", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ol", { className: `gy-breadcrumb ${className}`, children: displayed }) });
873
+ }
874
+ function renderItem(item, isCurrent, separator, key) {
875
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { className: "gy-breadcrumb-item", children: [
876
+ key !== 0 && key !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "gy-breadcrumb-separator", "aria-hidden": "true", children: separator }),
877
+ isCurrent ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "gy-breadcrumb-current", "aria-current": "page", children: item.label }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
878
+ "a",
879
+ {
880
+ className: "gy-breadcrumb-link",
881
+ href: item.href ?? "#",
882
+ onClick: item.onClick ? (e) => {
883
+ e.preventDefault();
884
+ item.onClick?.();
885
+ } : void 0,
886
+ children: item.label
887
+ }
888
+ )
889
+ ] }, key ?? item.label);
890
+ }
891
+
892
+ // src/animatednumber/AnimatedNumber.tsx
893
+ var import_react10 = require("react");
894
+ var import_jsx_runtime15 = require("react/jsx-runtime");
895
+ function easeOut(t) {
896
+ return 1 - Math.pow(1 - t, 3);
897
+ }
898
+ function easeInOut(t) {
899
+ return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
900
+ }
901
+ function AnimatedNumber({
902
+ value,
903
+ duration = 1e3,
904
+ format,
905
+ className = "",
906
+ prefix = "",
907
+ suffix = "",
908
+ decimals = 0,
909
+ easing = "easeOut"
910
+ }) {
911
+ const [displayed, setDisplayed] = (0, import_react10.useState)(0);
912
+ const startRef = (0, import_react10.useRef)(0);
913
+ const startTimeRef = (0, import_react10.useRef)(null);
914
+ const rafRef = (0, import_react10.useRef)(0);
915
+ const prevValueRef = (0, import_react10.useRef)(0);
916
+ (0, import_react10.useEffect)(() => {
917
+ startRef.current = prevValueRef.current;
918
+ startTimeRef.current = null;
919
+ const easeFn = easing === "linear" ? (t) => t : easing === "easeOut" ? easeOut : easeInOut;
920
+ const animate = (time) => {
921
+ if (!startTimeRef.current) startTimeRef.current = time;
922
+ const elapsed = time - startTimeRef.current;
923
+ const t = Math.min(elapsed / duration, 1);
924
+ const eased = easeFn(t);
925
+ const current = startRef.current + (value - startRef.current) * eased;
926
+ setDisplayed(current);
927
+ if (t < 1) {
928
+ rafRef.current = requestAnimationFrame(animate);
929
+ } else {
930
+ prevValueRef.current = value;
931
+ }
932
+ };
933
+ cancelAnimationFrame(rafRef.current);
934
+ rafRef.current = requestAnimationFrame(animate);
935
+ return () => cancelAnimationFrame(rafRef.current);
936
+ }, [value, duration, easing]);
937
+ const formatted = format ? format(displayed) : displayed.toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
938
+ return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: `gy-animated-number ${className}`, "aria-live": "polite", "aria-atomic": "true", children: [
939
+ prefix,
940
+ formatted,
941
+ suffix
942
+ ] });
943
+ }
944
+
945
+ // src/accordion/Accordion.tsx
946
+ var import_react11 = require("react");
947
+ var import_jsx_runtime16 = require("react/jsx-runtime");
948
+ function AccordionPanel({ open, children }) {
949
+ const ref = (0, import_react11.useRef)(null);
950
+ const height = open ? ref.current?.scrollHeight ?? 0 : 0;
951
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
952
+ "div",
953
+ {
954
+ className: "gy-accordion-panel",
955
+ style: { height, transition: `height 250ms cubic-bezier(0.4, 0, 0.2, 1)`, overflow: "hidden" },
956
+ "aria-hidden": !open,
957
+ children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { ref, className: "gy-accordion-panel-inner", children })
958
+ }
959
+ );
960
+ }
961
+ function Accordion({ items, type = "single", defaultOpen, flush = false, className = "" }) {
962
+ const initOpen = defaultOpen ? Array.isArray(defaultOpen) ? defaultOpen : [defaultOpen] : [];
963
+ const [openIds, setOpenIds] = (0, import_react11.useState)(new Set(initOpen));
964
+ const toggle = (id) => {
965
+ setOpenIds((prev) => {
966
+ const next = new Set(prev);
967
+ if (next.has(id)) {
968
+ next.delete(id);
969
+ } else {
970
+ if (type === "single") next.clear();
971
+ next.add(id);
972
+ }
973
+ return next;
974
+ });
975
+ };
976
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: `gy-accordion ${className}`, children: items.map((item) => {
977
+ const isOpen = openIds.has(item.id);
978
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
979
+ "div",
980
+ {
981
+ className: `gy-accordion-item ${flush ? "gy-accordion-item--flush" : ""}`,
982
+ children: [
983
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
984
+ "button",
985
+ {
986
+ type: "button",
987
+ className: `gy-accordion-trigger ${isOpen ? "gy-accordion-trigger--open" : ""}`,
988
+ onClick: () => !item.disabled && toggle(item.id),
989
+ "aria-expanded": isOpen,
990
+ disabled: item.disabled,
991
+ children: [
992
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "gy-accordion-title", children: item.title }),
993
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: `gy-accordion-icon ${isOpen ? "gy-accordion-icon--open" : ""}`, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("polyline", { points: "4,6 8,10 12,6" }) }) })
994
+ ]
995
+ }
996
+ ),
997
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(AccordionPanel, { open: isOpen, children: item.content })
998
+ ]
999
+ },
1000
+ item.id
1001
+ );
1002
+ }) });
1003
+ }
1004
+
1005
+ // src/tab/Tabs.tsx
1006
+ var import_react12 = require("react");
1007
+ var import_jsx_runtime17 = require("react/jsx-runtime");
1008
+ function Tabs({ items, defaultTab, activeTab, onChange, orientation = "horizontal", className = "" }) {
1009
+ const [internalActive, setInternalActive] = (0, import_react12.useState)(defaultTab ?? items[0]?.id ?? "");
1010
+ const current = activeTab ?? internalActive;
1011
+ const handleSelect = (id) => {
1012
+ setInternalActive(id);
1013
+ onChange?.(id);
1014
+ };
1015
+ const activeItem = items.find((i) => i.id === current);
1016
+ return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: `gy-tabs ${orientation === "vertical" ? "gy-tabs--vertical" : ""} ${className}`, children: [
1017
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "gy-tabs-list", role: "tablist", "aria-orientation": orientation, children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
1018
+ "button",
1019
+ {
1020
+ role: "tab",
1021
+ id: `gy-tab-${item.id}`,
1022
+ "aria-controls": `gy-panel-${item.id}`,
1023
+ "aria-selected": current === item.id,
1024
+ disabled: item.disabled,
1025
+ className: `gy-tabs-trigger ${current === item.id ? "gy-tabs-trigger--active" : ""}`,
1026
+ onClick: () => !item.disabled && handleSelect(item.id),
1027
+ children: [
1028
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { "aria-hidden": "true", children: item.icon }),
1029
+ item.label,
1030
+ item.badge !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "gy-tabs-trigger-badge", children: item.badge })
1031
+ ]
1032
+ },
1033
+ item.id
1034
+ )) }),
1035
+ activeItem && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1036
+ "div",
1037
+ {
1038
+ id: `gy-panel-${current}`,
1039
+ role: "tabpanel",
1040
+ "aria-labelledby": `gy-tab-${current}`,
1041
+ className: "gy-tabs-panel",
1042
+ children: activeItem.content
1043
+ },
1044
+ current
1045
+ )
1046
+ ] });
1047
+ }
1048
+
1049
+ // src/modal/Modal.tsx
1050
+ var import_react13 = require("react");
1051
+ var import_react_dom = require("react-dom");
1052
+ var import_jsx_runtime18 = require("react/jsx-runtime");
1053
+ function Modal({
1054
+ open,
1055
+ onClose,
1056
+ title,
1057
+ size = "md",
1058
+ children,
1059
+ footer,
1060
+ closeOnBackdrop = true,
1061
+ closeOnEscape = true,
1062
+ className = ""
1063
+ }) {
1064
+ const dialogRef = (0, import_react13.useRef)(null);
1065
+ (0, import_react13.useEffect)(() => {
1066
+ if (!open) return;
1067
+ const previous = document.activeElement;
1068
+ dialogRef.current?.focus();
1069
+ const handleKey = (e) => {
1070
+ if (e.key === "Escape" && closeOnEscape) onClose();
1071
+ if (e.key === "Tab") {
1072
+ const focusable = dialogRef.current?.querySelectorAll(
1073
+ 'a, button:not(:disabled), textarea, input, select, [tabindex]:not([tabindex="-1"])'
1074
+ );
1075
+ if (!focusable?.length) return;
1076
+ const first = focusable[0];
1077
+ const last = focusable[focusable.length - 1];
1078
+ if (e.shiftKey && document.activeElement === first) {
1079
+ e.preventDefault();
1080
+ last.focus();
1081
+ } else if (!e.shiftKey && document.activeElement === last) {
1082
+ e.preventDefault();
1083
+ first.focus();
1084
+ }
1085
+ }
1086
+ };
1087
+ document.addEventListener("keydown", handleKey);
1088
+ document.body.style.overflow = "hidden";
1089
+ return () => {
1090
+ document.removeEventListener("keydown", handleKey);
1091
+ document.body.style.overflow = "";
1092
+ previous?.focus();
1093
+ };
1094
+ }, [open, onClose, closeOnEscape]);
1095
+ if (!open) return null;
1096
+ const content = /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
1097
+ "div",
1098
+ {
1099
+ className: "gy-modal-backdrop",
1100
+ onClick: closeOnBackdrop ? (e) => {
1101
+ if (e.target === e.currentTarget) onClose();
1102
+ } : void 0,
1103
+ "aria-modal": "true",
1104
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
1105
+ "div",
1106
+ {
1107
+ ref: dialogRef,
1108
+ role: "dialog",
1109
+ "aria-labelledby": title ? "gy-modal-title" : void 0,
1110
+ className: `gy-modal gy-modal--${size} ${className}`,
1111
+ tabIndex: -1,
1112
+ children: [
1113
+ title && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "gy-modal-header", children: [
1114
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h2", { id: "gy-modal-title", className: "gy-modal-title", children: title }),
1115
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("button", { className: "gy-modal-close", onClick: onClose, "aria-label": "Close dialog", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
1116
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("line", { x1: "1", y1: "1", x2: "15", y2: "15" }),
1117
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("line", { x1: "15", y1: "1", x2: "1", y2: "15" })
1118
+ ] }) })
1119
+ ] }),
1120
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "gy-modal-body", children }),
1121
+ footer && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "gy-modal-footer", children: footer })
1122
+ ]
1123
+ }
1124
+ )
1125
+ }
1126
+ );
1127
+ return (0, import_react_dom.createPortal)(content, document.body);
1128
+ }
1129
+
1130
+ // src/dropdown/Dropdown.tsx
1131
+ var import_react14 = require("react");
1132
+ var import_jsx_runtime19 = require("react/jsx-runtime");
1133
+ function Dropdown({
1134
+ options,
1135
+ value,
1136
+ onChange,
1137
+ placeholder = "Select an option",
1138
+ searchable = false,
1139
+ disabled = false,
1140
+ label,
1141
+ error,
1142
+ className = "",
1143
+ id
1144
+ }) {
1145
+ const uid = (0, import_react14.useId)();
1146
+ const inputId = id ?? uid;
1147
+ const [open, setOpen] = (0, import_react14.useState)(false);
1148
+ const [search, setSearch] = (0, import_react14.useState)("");
1149
+ const [focused, setFocused] = (0, import_react14.useState)(0);
1150
+ const rootRef = (0, import_react14.useRef)(null);
1151
+ const searchRef = (0, import_react14.useRef)(null);
1152
+ const selected = options.find((o) => o.value === value);
1153
+ const filtered = searchable && search ? options.filter((o) => String(o.label).toLowerCase().includes(search.toLowerCase())) : options;
1154
+ const groups = filtered.reduce((acc, opt) => {
1155
+ const g = opt.group ?? "__default__";
1156
+ acc[g] = [...acc[g] ?? [], opt];
1157
+ return acc;
1158
+ }, {});
1159
+ (0, import_react14.useEffect)(() => {
1160
+ if (!open) {
1161
+ setSearch("");
1162
+ setFocused(0);
1163
+ return;
1164
+ }
1165
+ if (searchable) setTimeout(() => searchRef.current?.focus(), 50);
1166
+ }, [open, searchable]);
1167
+ (0, import_react14.useEffect)(() => {
1168
+ const handler = (e) => {
1169
+ if (!rootRef.current?.contains(e.target)) setOpen(false);
1170
+ };
1171
+ document.addEventListener("mousedown", handler);
1172
+ return () => document.removeEventListener("mousedown", handler);
1173
+ }, []);
1174
+ const handleSelect = (opt) => {
1175
+ if (opt.disabled) return;
1176
+ onChange?.(opt.value);
1177
+ setOpen(false);
1178
+ };
1179
+ const handleKeyDown = (e) => {
1180
+ const flat = filtered.filter((o) => !o.disabled);
1181
+ if (e.key === "ArrowDown") {
1182
+ e.preventDefault();
1183
+ setFocused((f) => Math.min(f + 1, flat.length - 1));
1184
+ }
1185
+ if (e.key === "ArrowUp") {
1186
+ e.preventDefault();
1187
+ setFocused((f) => Math.max(f - 1, 0));
1188
+ }
1189
+ if (e.key === "Enter" && open) {
1190
+ e.preventDefault();
1191
+ const opt = flat[focused];
1192
+ if (opt) handleSelect(opt);
1193
+ }
1194
+ if (e.key === "Escape") setOpen(false);
1195
+ if (!open && (e.key === "Enter" || e.key === " ")) {
1196
+ e.preventDefault();
1197
+ setOpen(true);
1198
+ }
1199
+ };
1200
+ return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { ref: rootRef, className: `gy-dropdown-root ${className}`, onKeyDown: handleKeyDown, children: [
1201
+ label && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("label", { className: "gy-input-label", htmlFor: inputId, children: label }),
1202
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1203
+ "button",
1204
+ {
1205
+ id: inputId,
1206
+ type: "button",
1207
+ className: [
1208
+ "gy-dropdown-trigger",
1209
+ open ? "gy-dropdown-trigger--open" : "",
1210
+ disabled ? "gy-dropdown-trigger--disabled" : "",
1211
+ !selected ? "gy-dropdown-trigger--placeholder" : ""
1212
+ ].filter(Boolean).join(" "),
1213
+ onClick: () => !disabled && setOpen((o) => !o),
1214
+ disabled,
1215
+ "aria-expanded": open,
1216
+ "aria-haspopup": "listbox",
1217
+ children: [
1218
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { children: selected ? selected.label : placeholder }),
1219
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: `gy-dropdown-chevron ${open ? "gy-dropdown-chevron--open" : ""}`, "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("polyline", { points: "3,5 7,9 11,5" }) }) })
1220
+ ]
1221
+ }
1222
+ ),
1223
+ open && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "gy-dropdown-menu", role: "listbox", children: [
1224
+ searchable && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "gy-dropdown-search", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
1225
+ "input",
1226
+ {
1227
+ ref: searchRef,
1228
+ className: "gy-dropdown-search-input",
1229
+ value: search,
1230
+ onChange: (e) => {
1231
+ setSearch(e.target.value);
1232
+ setFocused(0);
1233
+ },
1234
+ placeholder: "Search...",
1235
+ "aria-label": "Search options"
1236
+ }
1237
+ ) }),
1238
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "gy-dropdown-options", children: filtered.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "gy-dropdown-empty", children: "No options found" }) : Object.entries(groups).map(([group, opts]) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
1239
+ group !== "__default__" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "gy-dropdown-group-label", children: group }),
1240
+ opts.map((opt, i) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
1241
+ "div",
1242
+ {
1243
+ className: [
1244
+ "gy-dropdown-option",
1245
+ opt.value === value ? "gy-dropdown-option--selected" : "",
1246
+ focused === i ? "gy-dropdown-option--focused" : "",
1247
+ opt.disabled ? "gy-dropdown-option--disabled" : ""
1248
+ ].filter(Boolean).join(" "),
1249
+ role: "option",
1250
+ "aria-selected": opt.value === value,
1251
+ onClick: () => handleSelect(opt),
1252
+ children: [
1253
+ opt.icon && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { "aria-hidden": "true", children: opt.icon }),
1254
+ opt.label,
1255
+ opt.value === value && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "gy-dropdown-check", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: "14", height: "11", viewBox: "0 0 14 11", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("polyline", { points: "1,5 5,9 13,1" }) }) })
1256
+ ]
1257
+ },
1258
+ opt.value
1259
+ ))
1260
+ ] }, group)) })
1261
+ ] }),
1262
+ error && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "gy-input-helper gy-input-helper--error", role: "alert", children: error })
1263
+ ] });
1264
+ }
1265
+
1266
+ // src/menu/Menu.tsx
1267
+ var import_react15 = __toESM(require("react"), 1);
1268
+ var import_jsx_runtime20 = require("react/jsx-runtime");
1269
+ function Tooltip({ content, children, position = "top", delay = 300, disabled = false }) {
1270
+ const [visible, setVisible] = (0, import_react15.useState)(false);
1271
+ const timerRef = (0, import_react15.useRef)(void 0);
1272
+ const show = () => {
1273
+ timerRef.current = setTimeout(() => setVisible(true), delay);
1274
+ };
1275
+ const hide = () => {
1276
+ clearTimeout(timerRef.current);
1277
+ setVisible(false);
1278
+ };
1279
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "gy-tooltip-wrapper", onMouseEnter: show, onMouseLeave: hide, onFocus: show, onBlur: hide, children: [
1280
+ children,
1281
+ visible && !disabled && content && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: `gy-tooltip gy-tooltip--${position}`, role: "tooltip", children: content })
1282
+ ] });
1283
+ }
1284
+ var posStyle = {
1285
+ "bottom-left": { top: "calc(100% + 4px)", left: 0 },
1286
+ "bottom-right": { top: "calc(100% + 4px)", right: 0 },
1287
+ "top-left": { bottom: "calc(100% + 4px)", left: 0 },
1288
+ "top-right": { bottom: "calc(100% + 4px)", right: 0 }
1289
+ };
1290
+ function Menu({ items, trigger, position = "bottom-left", className = "" }) {
1291
+ const [open, setOpen] = (0, import_react15.useState)(false);
1292
+ const rootRef = (0, import_react15.useRef)(null);
1293
+ (0, import_react15.useEffect)(() => {
1294
+ const handler = (e) => {
1295
+ if (!rootRef.current?.contains(e.target)) setOpen(false);
1296
+ };
1297
+ document.addEventListener("mousedown", handler);
1298
+ return () => document.removeEventListener("mousedown", handler);
1299
+ }, []);
1300
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { ref: rootRef, className: "gy-menu-trigger", style: { position: "relative" }, children: [
1301
+ import_react15.default.cloneElement(trigger, { onClick: () => setOpen((o) => !o) }),
1302
+ open && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: `gy-menu gy-menu--absolute ${className}`, style: posStyle[position], role: "menu", children: items.map((entry) => {
1303
+ if ("separator" in entry && entry.separator) {
1304
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "gy-menu-separator", role: "separator" }, entry.id);
1305
+ }
1306
+ if ("groupLabel" in entry && entry.groupLabel) {
1307
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "gy-menu-group-label", children: entry.groupLabel }, entry.id);
1308
+ }
1309
+ const item = entry;
1310
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1311
+ "button",
1312
+ {
1313
+ type: "button",
1314
+ className: [
1315
+ "gy-menu-item",
1316
+ item.danger ? "gy-menu-item--danger" : "",
1317
+ item.disabled ? "gy-menu-item--disabled" : ""
1318
+ ].filter(Boolean).join(" "),
1319
+ role: "menuitem",
1320
+ disabled: item.disabled,
1321
+ onClick: () => {
1322
+ item.onClick?.();
1323
+ setOpen(false);
1324
+ },
1325
+ children: [
1326
+ item.icon && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "gy-menu-item__icon", "aria-hidden": "true", children: item.icon }),
1327
+ item.label,
1328
+ item.badge && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "gy-menu-item__badge", children: item.badge })
1329
+ ]
1330
+ },
1331
+ item.id
1332
+ );
1333
+ }) })
1334
+ ] });
1335
+ }
1336
+
1337
+ // src/toaster/Toaster.tsx
1338
+ var import_react16 = require("react");
1339
+ var import_react_dom2 = require("react-dom");
1340
+ var import_jsx_runtime21 = require("react/jsx-runtime");
1341
+ var ToastContext = (0, import_react16.createContext)(null);
1342
+ var icons2 = {
1343
+ success: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "#10b981", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1344
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "8", r: "7" }),
1345
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("polyline", { points: "5,8 7,10 11,6" })
1346
+ ] }),
1347
+ error: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "#ef4444", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1348
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "8", r: "7" }),
1349
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "8", y1: "5", x2: "8", y2: "9" }),
1350
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "11.5", r: "0.5", fill: "#ef4444" })
1351
+ ] }),
1352
+ warning: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "#f59e0b", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { d: "M8 2L1 14h14L8 2zm0 4v4m0 2v.01", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round" }) }),
1353
+ info: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", stroke: "#0ea5e9", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1354
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "8", r: "7" }),
1355
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "8", y1: "8", x2: "8", y2: "12" }),
1356
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("circle", { cx: "8", cy: "5", r: "0.5", fill: "#0ea5e9" })
1357
+ ] }),
1358
+ loading: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Spinner, { size: "xs" })
1359
+ };
1360
+ function ToasterProvider({ children, position = "top-right" }) {
1361
+ const [toasts, setToasts] = (0, import_react16.useState)([]);
1362
+ const dismiss = (0, import_react16.useCallback)((id) => {
1363
+ setToasts((prev) => prev.filter((t) => t.id !== id));
1364
+ }, []);
1365
+ const dismissAll = (0, import_react16.useCallback)(() => setToasts([]), []);
1366
+ const toast = (0, import_react16.useCallback)((data) => {
1367
+ const id = Math.random().toString(36).slice(2);
1368
+ const duration = data.duration ?? (data.variant === "loading" ? 0 : 4e3);
1369
+ const newToast = { ...data, id, duration };
1370
+ setToasts((prev) => [...prev, newToast]);
1371
+ if (duration > 0) {
1372
+ setTimeout(() => dismiss(id), duration);
1373
+ }
1374
+ return id;
1375
+ }, [dismiss]);
1376
+ const isLeft = position.includes("left");
1377
+ const toasterNode = /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: `gy-toaster gy-toaster--${position}`, children: toasts.map((t) => /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
1378
+ "div",
1379
+ {
1380
+ className: `gy-toast gy-toast--${t.variant ?? "info"} ${isLeft ? "gy-toast--left" : ""}`,
1381
+ role: "alert",
1382
+ "aria-live": "polite",
1383
+ children: [
1384
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "gy-toast-accent" }),
1385
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "gy-toast-icon", children: icons2[t.variant ?? "info"] }),
1386
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "gy-toast-content", children: [
1387
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "gy-toast-title", children: t.title }),
1388
+ t.description && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "gy-toast-description", children: t.description })
1389
+ ] }),
1390
+ (t.dismissible ?? true) && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { className: "gy-toast-close", onClick: () => dismiss(t.id), "aria-label": "Dismiss", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
1391
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "1", y1: "1", x2: "11", y2: "11" }),
1392
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("line", { x1: "11", y1: "1", x2: "1", y2: "11" })
1393
+ ] }) }),
1394
+ t.duration && t.duration > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "gy-toast-progress", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "gy-toast-progress-bar", style: { animationDuration: `${t.duration}ms` } }) })
1395
+ ]
1396
+ },
1397
+ t.id
1398
+ )) });
1399
+ return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(ToastContext.Provider, { value: { toasts, toast, dismiss, dismissAll }, children: [
1400
+ children,
1401
+ typeof document !== "undefined" && (0, import_react_dom2.createPortal)(toasterNode, document.body)
1402
+ ] });
1403
+ }
1404
+ function useToast() {
1405
+ const ctx = (0, import_react16.useContext)(ToastContext);
1406
+ if (!ctx) throw new Error("useToast must be used inside ToasterProvider");
1407
+ return ctx;
1408
+ }
1409
+
1410
+ // src/stepper/Stepper.tsx
1411
+ var import_react17 = __toESM(require("react"), 1);
1412
+ var import_jsx_runtime22 = require("react/jsx-runtime");
1413
+ var CheckIcon = () => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("svg", { width: "14", height: "11", viewBox: "0 0 14 11", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("polyline", { points: "1,5 5,9 13,1" }) });
1414
+ var ErrorIcon = () => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
1415
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("line", { x1: "2", y1: "2", x2: "10", y2: "10" }),
1416
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("line", { x1: "10", y1: "2", x2: "2", y2: "10" })
1417
+ ] });
1418
+ function Stepper({
1419
+ steps,
1420
+ activeStep: controlledStep,
1421
+ defaultStep = 0,
1422
+ variant = "linear",
1423
+ orientation = "horizontal",
1424
+ onStepChange,
1425
+ onComplete,
1426
+ className = ""
1427
+ }) {
1428
+ const [internalStep, setInternalStep] = (0, import_react17.useState)(defaultStep);
1429
+ const current = controlledStep ?? internalStep;
1430
+ const goTo = (idx) => {
1431
+ if (variant === "linear" && idx > current + 1) return;
1432
+ if (idx < 0 || idx >= steps.length) return;
1433
+ setInternalStep(idx);
1434
+ onStepChange?.(idx);
1435
+ };
1436
+ const next = () => {
1437
+ if (current === steps.length - 1) {
1438
+ onComplete?.();
1439
+ } else {
1440
+ goTo(current + 1);
1441
+ }
1442
+ };
1443
+ const prev = () => goTo(current - 1);
1444
+ const getStatus = (idx) => {
1445
+ if (idx < current) return "completed";
1446
+ if (idx === current) return "active";
1447
+ return "upcoming";
1448
+ };
1449
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: `gy-stepper ${orientation === "vertical" ? "gy-stepper--vertical" : ""} ${className}`, children: [
1450
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: `gy-stepper ${orientation === "vertical" ? "gy-stepper--vertical" : ""}`, style: { width: "100%" }, children: steps.map((step, idx) => {
1451
+ const status = getStatus(idx);
1452
+ const isClickable = variant === "free" || idx <= current;
1453
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_react17.default.Fragment, { children: [
1454
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "gy-stepper-item", children: [
1455
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
1456
+ "span",
1457
+ {
1458
+ className: [
1459
+ "gy-stepper-indicator",
1460
+ `gy-stepper-indicator--${status}`,
1461
+ isClickable ? "gy-stepper-indicator--clickable" : ""
1462
+ ].filter(Boolean).join(" "),
1463
+ onClick: () => isClickable && goTo(idx),
1464
+ role: isClickable ? "button" : void 0,
1465
+ tabIndex: isClickable ? 0 : void 0,
1466
+ onKeyDown: isClickable ? (e) => {
1467
+ if (e.key === "Enter") goTo(idx);
1468
+ } : void 0,
1469
+ "aria-label": `Step ${idx + 1}: ${step.label}`,
1470
+ "aria-current": status === "active" ? "step" : void 0,
1471
+ children: status === "completed" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CheckIcon, {}) : status === "error" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ErrorIcon, {}) : idx + 1
1472
+ }
1473
+ ),
1474
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
1475
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: `gy-stepper-label gy-stepper-label--${status}`, children: step.label }),
1476
+ step.optional && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "gy-stepper-description", children: "Optional" }),
1477
+ step.description && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "gy-stepper-description", children: step.description })
1478
+ ] })
1479
+ ] }),
1480
+ idx < steps.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: `gy-stepper-connector ${idx < current ? "gy-stepper-connector--completed" : ""}` })
1481
+ ] }, step.id);
1482
+ }) }),
1483
+ steps[current]?.content && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "gy-stepper-panel", children: steps[current].content }, current)
1484
+ ] });
1485
+ }
1486
+
1487
+ // src/table/Table.tsx
1488
+ var import_react18 = __toESM(require("react"), 1);
1489
+ var import_jsx_runtime23 = require("react/jsx-runtime");
1490
+ function SortIcon({ dir }) {
1491
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "currentColor", className: `gy-table-sort-icon ${dir ? "gy-table-sort-icon--active" : ""}`, children: dir === "asc" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M6 2L10 8H2L6 2z" }) : dir === "desc" ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M6 10L2 4H10L6 10z" }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
1492
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M6 1L9 5H3L6 1z", opacity: ".5" }),
1493
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M6 11L3 7H9L6 11z", opacity: ".5" })
1494
+ ] }) });
1495
+ }
1496
+ function Table({
1497
+ columns,
1498
+ data,
1499
+ rowKey,
1500
+ selectable = false,
1501
+ selectedRows = [],
1502
+ onSelectionChange,
1503
+ pageSize = 10,
1504
+ emptyMessage = "No data available",
1505
+ className = "",
1506
+ stickyHeader = false
1507
+ }) {
1508
+ const [sortKey, setSortKey] = (0, import_react18.useState)(null);
1509
+ const [sortDir, setSortDir] = (0, import_react18.useState)("asc");
1510
+ const [page, setPage] = (0, import_react18.useState)(1);
1511
+ const sortedData = (0, import_react18.useMemo)(() => {
1512
+ if (!sortKey) return data;
1513
+ const col = columns.find((c) => c.key === sortKey);
1514
+ if (!col) return data;
1515
+ return [...data].sort((a, b) => {
1516
+ const av = String(col.accessor(a) ?? "");
1517
+ const bv = String(col.accessor(b) ?? "");
1518
+ const cmp = av.localeCompare(bv, void 0, { numeric: true });
1519
+ return sortDir === "asc" ? cmp : -cmp;
1520
+ });
1521
+ }, [data, sortKey, sortDir, columns]);
1522
+ const totalPages = Math.max(1, Math.ceil(sortedData.length / pageSize));
1523
+ const paged = sortedData.slice((page - 1) * pageSize, page * pageSize);
1524
+ const allSelected = paged.length > 0 && paged.every((r) => selectedRows.includes(rowKey(r)));
1525
+ const someSelected = paged.some((r) => selectedRows.includes(rowKey(r)));
1526
+ const toggleSort = (key) => {
1527
+ if (sortKey === key) {
1528
+ setSortDir((d) => d === "asc" ? "desc" : "asc");
1529
+ } else {
1530
+ setSortKey(key);
1531
+ setSortDir("asc");
1532
+ }
1533
+ setPage(1);
1534
+ };
1535
+ const toggleRow = (key) => {
1536
+ const next = selectedRows.includes(key) ? selectedRows.filter((k) => k !== key) : [...selectedRows, key];
1537
+ onSelectionChange?.(next);
1538
+ };
1539
+ const toggleAll = () => {
1540
+ const pageKeys = paged.map(rowKey);
1541
+ if (allSelected) {
1542
+ onSelectionChange?.(selectedRows.filter((k) => !pageKeys.includes(k)));
1543
+ } else {
1544
+ const combined = [.../* @__PURE__ */ new Set([...selectedRows, ...pageKeys])];
1545
+ onSelectionChange?.(combined);
1546
+ }
1547
+ };
1548
+ const pageNums = Array.from({ length: totalPages }, (_, i) => i + 1);
1549
+ const visiblePages = pageNums.filter(
1550
+ (p) => p === 1 || p === totalPages || Math.abs(p - page) <= 1
1551
+ );
1552
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: `gy-table-wrapper ${className}`, children: [
1553
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("table", { className: "gy-table", "aria-label": "Data table", children: [
1554
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("thead", { className: "gy-table-header", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("tr", { children: [
1555
+ selectable && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("th", { className: "gy-table-th gy-table-th--checkbox", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1556
+ Checkbox,
1557
+ {
1558
+ checked: allSelected,
1559
+ indeterminate: !allSelected && someSelected,
1560
+ onChange: toggleAll,
1561
+ size: "sm"
1562
+ }
1563
+ ) }),
1564
+ columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1565
+ "th",
1566
+ {
1567
+ className: `gy-table-th ${col.sortable ? "gy-table-th--sortable" : ""}`,
1568
+ style: { width: col.width, textAlign: col.align },
1569
+ onClick: col.sortable ? () => toggleSort(col.key) : void 0,
1570
+ "aria-sort": sortKey === col.key ? sortDir === "asc" ? "ascending" : "descending" : void 0,
1571
+ children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "gy-table-th-inner", children: [
1572
+ col.header,
1573
+ col.sortable && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SortIcon, { dir: sortKey === col.key ? sortDir : void 0 })
1574
+ ] })
1575
+ },
1576
+ col.key
1577
+ ))
1578
+ ] }) }),
1579
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("tbody", { children: paged.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { colSpan: columns.length + (selectable ? 1 : 0), className: "gy-table-empty", children: emptyMessage }) }) : paged.map((row) => {
1580
+ const key = rowKey(row);
1581
+ const isSelected = selectedRows.includes(key);
1582
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
1583
+ "tr",
1584
+ {
1585
+ className: `gy-table-tr ${isSelected ? "gy-table-tr--selected" : ""}`,
1586
+ "aria-selected": selectable ? isSelected : void 0,
1587
+ children: [
1588
+ selectable && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "gy-table-td gy-table-td--checkbox", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Checkbox, { checked: isSelected, onChange: () => toggleRow(key), size: "sm" }) }),
1589
+ columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("td", { className: "gy-table-td", style: { textAlign: col.align }, children: col.accessor(row) }, col.key))
1590
+ ]
1591
+ },
1592
+ key
1593
+ );
1594
+ }) })
1595
+ ] }),
1596
+ totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "gy-table-pagination", children: [
1597
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { className: "gy-table-pagination-info", children: [
1598
+ "Showing ",
1599
+ (page - 1) * pageSize + 1,
1600
+ "\u2013",
1601
+ Math.min(page * pageSize, sortedData.length),
1602
+ " of ",
1603
+ sortedData.length
1604
+ ] }),
1605
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "gy-table-pagination-controls", children: [
1606
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "gy-table-pagination-btn", onClick: () => setPage((p) => p - 1), disabled: page === 1, "aria-label": "Previous page", children: "\u2039" }),
1607
+ visiblePages.map((p, i, arr) => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_react18.default.Fragment, { children: [
1608
+ i > 0 && arr[i - 1] !== p - 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { style: { padding: "0 4px", color: "var(--gy-text-subtle)" }, children: "\u2026" }),
1609
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
1610
+ "button",
1611
+ {
1612
+ className: `gy-table-pagination-btn ${page === p ? "gy-table-pagination-btn--active" : ""}`,
1613
+ onClick: () => setPage(p),
1614
+ "aria-label": `Page ${p}`,
1615
+ "aria-current": page === p ? "page" : void 0,
1616
+ children: p
1617
+ }
1618
+ )
1619
+ ] }, p)),
1620
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { className: "gy-table-pagination-btn", onClick: () => setPage((p) => p + 1), disabled: page === totalPages, "aria-label": "Next page", children: "\u203A" })
1621
+ ] })
1622
+ ] })
1623
+ ] });
1624
+ }
1625
+
1626
+ // src/dragdrop/DragDrop.tsx
1627
+ var import_react19 = require("react");
1628
+ var import_jsx_runtime24 = require("react/jsx-runtime");
1629
+ function ReorderList({ items, onReorder, keyExtractor, renderItem: renderItem2, className = "" }) {
1630
+ const [draggedIdx, setDraggedIdx] = (0, import_react19.useState)(null);
1631
+ const [dragOverIdx, setDragOverIdx] = (0, import_react19.useState)(null);
1632
+ const handleDragStart = (idx, e) => {
1633
+ setDraggedIdx(idx);
1634
+ e.dataTransfer.effectAllowed = "move";
1635
+ e.dataTransfer.setData("text/plain", idx.toString());
1636
+ };
1637
+ const handleDragOver = (idx, e) => {
1638
+ e.preventDefault();
1639
+ e.dataTransfer.dropEffect = "move";
1640
+ if (idx !== dragOverIdx) setDragOverIdx(idx);
1641
+ };
1642
+ const handleDrop = (idx, e) => {
1643
+ e.preventDefault();
1644
+ const fromIdx = Number(e.dataTransfer.getData("text/plain"));
1645
+ if (fromIdx !== idx) {
1646
+ const next = [...items];
1647
+ const [moved] = next.splice(fromIdx, 1);
1648
+ if (moved !== void 0) {
1649
+ next.splice(idx, 0, moved);
1650
+ onReorder(next);
1651
+ }
1652
+ }
1653
+ setDraggedIdx(null);
1654
+ setDragOverIdx(null);
1655
+ };
1656
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: `gy-dnd-list ${className}`, children: items.map((item, idx) => {
1657
+ const isDragging = draggedIdx === idx;
1658
+ const isOver = dragOverIdx === idx;
1659
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
1660
+ "div",
1661
+ {
1662
+ className: [
1663
+ "gy-dnd-item",
1664
+ isDragging ? "gy-dnd-item--dragging" : "",
1665
+ isOver && !isDragging ? "gy-dnd-item--drag-over" : ""
1666
+ ].filter(Boolean).join(" "),
1667
+ draggable: true,
1668
+ onDragStart: (e) => handleDragStart(idx, e),
1669
+ onDragOver: (e) => handleDragOver(idx, e),
1670
+ onDragLeave: () => setDragOverIdx(null),
1671
+ onDrop: (e) => handleDrop(idx, e),
1672
+ onDragEnd: () => {
1673
+ setDraggedIdx(null);
1674
+ setDragOverIdx(null);
1675
+ },
1676
+ children: [
1677
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "gy-dnd-handle", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("svg", { width: "12", height: "16", viewBox: "0 0 12 16", fill: "currentColor", children: [
1678
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { cx: "4", cy: "4", r: "1.5" }),
1679
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { cx: "8", cy: "4", r: "1.5" }),
1680
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { cx: "4", cy: "8", r: "1.5" }),
1681
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { cx: "8", cy: "8", r: "1.5" }),
1682
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { cx: "4", cy: "12", r: "1.5" }),
1683
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("circle", { cx: "8", cy: "12", r: "1.5" })
1684
+ ] }) }),
1685
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "gy-dnd-item-content", children: renderItem2(item, isDragging) })
1686
+ ]
1687
+ },
1688
+ keyExtractor(item)
1689
+ );
1690
+ }) });
1691
+ }
1692
+ function KanbanBoard({ columns, onMove, keyExtractor, renderCard, className = "" }) {
1693
+ const [dragged, setDragged] = (0, import_react19.useState)(null);
1694
+ const [overCol, setOverCol] = (0, import_react19.useState)(null);
1695
+ const handleDragStart = (e, key, colId, idx) => {
1696
+ setDragged({ key, colId, idx });
1697
+ e.dataTransfer.effectAllowed = "move";
1698
+ e.dataTransfer.setData("application/json", JSON.stringify({ key, colId }));
1699
+ };
1700
+ const handleDragOver = (e, colId) => {
1701
+ e.preventDefault();
1702
+ e.dataTransfer.dropEffect = "move";
1703
+ if (overCol !== colId) setOverCol(colId);
1704
+ };
1705
+ const handleDrop = (e, toCol, toIndex) => {
1706
+ e.preventDefault();
1707
+ setOverCol(null);
1708
+ try {
1709
+ const data = JSON.parse(e.dataTransfer.getData("application/json"));
1710
+ if (data.colId === toCol && data.key === dragged?.key && toIndex === dragged?.idx) {
1711
+ return;
1712
+ }
1713
+ onMove(data.key, data.colId, toCol, toIndex);
1714
+ } catch (err) {
1715
+ }
1716
+ setDragged(null);
1717
+ };
1718
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: `gy-kanban ${className}`, children: columns.map((col) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "gy-kanban-column", children: [
1719
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "gy-kanban-column-header", children: [
1720
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "gy-kanban-column-title", children: col.title }),
1721
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "gy-kanban-column-count", children: col.items.length })
1722
+ ] }),
1723
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1724
+ "div",
1725
+ {
1726
+ className: `gy-kanban-drop-zone ${overCol === col.id ? "gy-kanban-drop-zone--over" : ""}`,
1727
+ onDragOver: (e) => handleDragOver(e, col.id),
1728
+ onDragLeave: () => setOverCol(null),
1729
+ onDrop: (e) => handleDrop(e, col.id, col.items.length),
1730
+ children: col.items.map((item, idx) => {
1731
+ const key = keyExtractor(item);
1732
+ const isDragging = dragged?.key === key;
1733
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
1734
+ "div",
1735
+ {
1736
+ className: `gy-kanban-card ${isDragging ? "gy-kanban-card--dragging" : ""}`,
1737
+ draggable: true,
1738
+ onDragStart: (e) => handleDragStart(e, key, col.id, idx),
1739
+ onDragEnd: () => {
1740
+ setDragged(null);
1741
+ setOverCol(null);
1742
+ },
1743
+ onDrop: (e) => {
1744
+ e.stopPropagation();
1745
+ handleDrop(e, col.id, idx);
1746
+ },
1747
+ children: renderCard(item, isDragging)
1748
+ },
1749
+ key
1750
+ );
1751
+ })
1752
+ }
1753
+ )
1754
+ ] }, col.id)) });
1755
+ }
1756
+
1757
+ // src/fileupload/FileUpload.tsx
1758
+ var import_react20 = require("react");
1759
+ var import_jsx_runtime25 = require("react/jsx-runtime");
1760
+ var formatSize = (bytes) => {
1761
+ if (bytes === 0) return "0 B";
1762
+ const k = 1024;
1763
+ const sizes = ["B", "KB", "MB", "GB"];
1764
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
1765
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + " " + sizes[i];
1766
+ };
1767
+ function FileUpload({
1768
+ onFilesSelected,
1769
+ multiple = false,
1770
+ accept,
1771
+ maxSize,
1772
+ maxFiles,
1773
+ disabled = false,
1774
+ label = "Click or drag files to upload",
1775
+ helperText,
1776
+ className = ""
1777
+ }) {
1778
+ const [dragActive, setDragActive] = (0, import_react20.useState)(false);
1779
+ const [selectedFiles, setSelectedFiles] = (0, import_react20.useState)([]);
1780
+ const inputRef = (0, import_react20.useRef)(null);
1781
+ const handleFiles = (files) => {
1782
+ if (!files) return;
1783
+ const valid = Array.from(files).filter((f) => !maxSize || f.size <= maxSize);
1784
+ const newFiles = multiple ? [...selectedFiles, ...valid] : valid;
1785
+ const limited = maxFiles ? newFiles.slice(0, maxFiles) : newFiles;
1786
+ if (!multiple) limited.splice(1);
1787
+ setSelectedFiles(limited);
1788
+ onFilesSelected?.(limited);
1789
+ };
1790
+ const handleDrag = (e) => {
1791
+ e.preventDefault();
1792
+ e.stopPropagation();
1793
+ if (disabled) return;
1794
+ if (e.type === "dragenter" || e.type === "dragover") setDragActive(true);
1795
+ else if (e.type === "dragleave") setDragActive(false);
1796
+ };
1797
+ const handleDrop = (e) => {
1798
+ e.preventDefault();
1799
+ e.stopPropagation();
1800
+ setDragActive(false);
1801
+ if (disabled) return;
1802
+ handleFiles(e.dataTransfer.files);
1803
+ };
1804
+ const removeFile = (idx) => {
1805
+ const updated = selectedFiles.filter((_, i) => i !== idx);
1806
+ setSelectedFiles(updated);
1807
+ onFilesSelected?.(updated);
1808
+ };
1809
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: `gy-fileupload ${className}`, children: [
1810
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
1811
+ "div",
1812
+ {
1813
+ className: [
1814
+ "gy-fileupload-zone",
1815
+ dragActive ? "gy-fileupload-zone--drag-active" : "",
1816
+ disabled ? "gy-fileupload-zone--disabled" : ""
1817
+ ].filter(Boolean).join(" "),
1818
+ onClick: () => !disabled && inputRef.current?.click(),
1819
+ onDragEnter: handleDrag,
1820
+ onDragLeave: handleDrag,
1821
+ onDragOver: handleDrag,
1822
+ onDrop: handleDrop,
1823
+ children: [
1824
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1825
+ "input",
1826
+ {
1827
+ ref: inputRef,
1828
+ type: "file",
1829
+ className: "gy-fileupload-input",
1830
+ multiple,
1831
+ accept,
1832
+ disabled,
1833
+ onChange: (e) => handleFiles(e.target.files)
1834
+ }
1835
+ ),
1836
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { className: "gy-fileupload-icon", width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1837
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1838
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("polyline", { points: "17 8 12 3 7 8" }),
1839
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "12", y1: "3", x2: "12", y2: "15" })
1840
+ ] }),
1841
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "gy-fileupload-text", children: label }),
1842
+ (helperText || maxSize) && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "gy-fileupload-subtext", children: [
1843
+ helperText,
1844
+ " ",
1845
+ maxSize && `(Max ${formatSize(maxSize)})`
1846
+ ] })
1847
+ ]
1848
+ }
1849
+ ),
1850
+ selectedFiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "gy-fileupload-list", children: selectedFiles.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "gy-fileupload-item", children: [
1851
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "gy-fileupload-item-icon", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1852
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("path", { d: "M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" }),
1853
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("polyline", { points: "13 2 13 9 20 9" })
1854
+ ] }) }),
1855
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "gy-fileupload-item-info", children: [
1856
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "gy-fileupload-item-name", title: f.name, children: f.name }),
1857
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { className: "gy-fileupload-item-size", children: formatSize(f.size) })
1858
+ ] }),
1859
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
1860
+ "button",
1861
+ {
1862
+ type: "button",
1863
+ className: "gy-fileupload-item-remove",
1864
+ onClick: (e) => {
1865
+ e.stopPropagation();
1866
+ removeFile(i);
1867
+ },
1868
+ "aria-label": "Remove file",
1869
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1870
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1871
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1872
+ ] })
1873
+ }
1874
+ )
1875
+ ] }, `${f.name}-${i}`)) })
1876
+ ] });
1877
+ }
1878
+
1879
+ // src/calendar/Calendar.tsx
1880
+ var import_react21 = require("react");
1881
+ var import_jsx_runtime26 = require("react/jsx-runtime");
1882
+ var getDaysInMonth = (year, month) => new Date(year, month + 1, 0).getDate();
1883
+ var getFirstDay = (year, month) => new Date(year, month, 1).getDay();
1884
+ var isSameDay = (d1, d2) => {
1885
+ if (!d1 || !d2) return false;
1886
+ return d1.getFullYear() === d2.getFullYear() && d1.getMonth() === d2.getMonth() && d1.getDate() === d2.getDate();
1887
+ };
1888
+ var isBetween = (d, start, end) => {
1889
+ if (!start || !end) return false;
1890
+ return d > start && d < end;
1891
+ };
1892
+ function Calendar({ mode = "single", value, onChange, minDate, maxDate, className = "", style }) {
1893
+ const [view, setView] = (0, import_react21.useState)("days");
1894
+ const [current, setCurrent] = (0, import_react21.useState)(() => {
1895
+ if (Array.isArray(value)) return value[0] ?? /* @__PURE__ */ new Date();
1896
+ return value ?? /* @__PURE__ */ new Date();
1897
+ });
1898
+ const [hoverDate, setHoverDate] = (0, import_react21.useState)(null);
1899
+ const [selStart, selEnd] = Array.isArray(value) ? value : [value, void 0];
1900
+ const y = current.getFullYear();
1901
+ const m = current.getMonth();
1902
+ const prevMonth = () => setCurrent(new Date(y, m - 1, 1));
1903
+ const nextMonth = () => setCurrent(new Date(y, m + 1, 1));
1904
+ const prevYear = () => setCurrent(new Date(y - 1, m, 1));
1905
+ const nextYear = () => setCurrent(new Date(y + 1, m, 1));
1906
+ const prevDecade = () => setCurrent(new Date(y - 10, m, 1));
1907
+ const nextDecade = () => setCurrent(new Date(y + 10, m, 1));
1908
+ const daysInMonth = getDaysInMonth(y, m);
1909
+ const firstDay = getFirstDay(y, m);
1910
+ const daysInPrev = getDaysInMonth(y, m - 1);
1911
+ const handleSelectDay = (date) => {
1912
+ if (mode === "single") {
1913
+ onChange?.(date);
1914
+ } else {
1915
+ if (!selStart || selStart && selEnd) {
1916
+ onChange?.([date, date]);
1917
+ } else {
1918
+ const start = date < selStart ? date : selStart;
1919
+ const end = date < selStart ? selStart : date;
1920
+ onChange?.([start, end]);
1921
+ }
1922
+ }
1923
+ };
1924
+ const renderDays = () => {
1925
+ const days = [];
1926
+ const today = /* @__PURE__ */ new Date();
1927
+ for (let i = firstDay - 1; i >= 0; i--) {
1928
+ const d = new Date(y, m - 1, daysInPrev - i);
1929
+ days.push(/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Day, { date: d, outside: true }, `prev-${i}`));
1930
+ }
1931
+ for (let i = 1; i <= daysInMonth; i++) {
1932
+ const d = new Date(y, m, i);
1933
+ days.push(/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Day, { date: d, isToday: isSameDay(d, today) }, `curr-${i}`));
1934
+ }
1935
+ const total = days.length;
1936
+ for (let i = 1; i <= 42 - total; i++) {
1937
+ const d = new Date(y, m + 1, i);
1938
+ days.push(/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(Day, { date: d, outside: true }, `next-${i}`));
1939
+ }
1940
+ return days;
1941
+ };
1942
+ const Day = ({ date, outside, isToday }) => {
1943
+ const disabled = minDate && date < minDate || maxDate && date > maxDate;
1944
+ const selected = isSameDay(date, selStart) || isSameDay(date, selEnd);
1945
+ const inRange = mode === "range" && isBetween(date, selStart, selEnd ?? hoverDate ?? void 0);
1946
+ const isStart = mode === "range" && isSameDay(date, selStart);
1947
+ const isEnd = mode === "range" && isSameDay(date, selEnd ?? hoverDate ?? void 0) && date > selStart;
1948
+ const cls = [
1949
+ "gy-calendar-day",
1950
+ outside ? "gy-calendar-day--outside" : "",
1951
+ isToday ? "gy-calendar-day--today" : "",
1952
+ selected ? "gy-calendar-day--selected" : "",
1953
+ inRange ? "gy-calendar-day--range-in" : "",
1954
+ isStart && (selEnd ?? hoverDate) ? "gy-calendar-day--range-start" : "",
1955
+ isEnd ? "gy-calendar-day--range-end" : "",
1956
+ disabled ? "gy-calendar-day--disabled" : ""
1957
+ ].filter(Boolean).join(" ");
1958
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1959
+ "button",
1960
+ {
1961
+ type: "button",
1962
+ className: cls,
1963
+ disabled,
1964
+ onClick: () => handleSelectDay(date),
1965
+ onMouseEnter: () => mode === "range" && selStart && !selEnd ? setHoverDate(date) : null,
1966
+ children: date.getDate()
1967
+ }
1968
+ );
1969
+ };
1970
+ const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
1971
+ const monthName = current.toLocaleString("default", { month: "long" });
1972
+ return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: `gy-calendar ${className}`, style, children: [
1973
+ view === "days" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
1974
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "gy-calendar-header", children: [
1975
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { className: "gy-calendar-nav", onClick: prevMonth, children: "\u2039" }),
1976
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "gy-calendar-title", onClick: () => setView("months"), children: [
1977
+ monthName,
1978
+ " ",
1979
+ y
1980
+ ] }),
1981
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { className: "gy-calendar-nav", onClick: nextMonth, children: "\u203A" })
1982
+ ] }),
1983
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "gy-calendar-grid", children: [
1984
+ ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"].map((d) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "gy-calendar-weekday", children: d }, d)),
1985
+ renderDays()
1986
+ ] })
1987
+ ] }),
1988
+ view === "months" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
1989
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "gy-calendar-header", children: [
1990
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { className: "gy-calendar-nav", onClick: prevYear, children: "\u2039" }),
1991
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "gy-calendar-title", onClick: () => setView("years"), children: y }),
1992
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { className: "gy-calendar-nav", onClick: nextYear, children: "\u203A" })
1993
+ ] }),
1994
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "gy-calendar-picker-grid", children: months.map((mon, i) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
1995
+ "button",
1996
+ {
1997
+ className: `gy-calendar-picker-item ${m === i ? "gy-calendar-picker-item--selected" : ""}`,
1998
+ onClick: () => {
1999
+ setCurrent(new Date(y, i, 1));
2000
+ setView("days");
2001
+ },
2002
+ children: mon
2003
+ },
2004
+ mon
2005
+ )) })
2006
+ ] }),
2007
+ view === "years" && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
2008
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "gy-calendar-header", children: [
2009
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { className: "gy-calendar-nav", onClick: prevDecade, children: "\u2039" }),
2010
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "gy-calendar-title", children: [
2011
+ y - y % 10,
2012
+ " - ",
2013
+ y - y % 10 + 9
2014
+ ] }),
2015
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { className: "gy-calendar-nav", onClick: nextDecade, children: "\u203A" })
2016
+ ] }),
2017
+ /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "gy-calendar-picker-grid", children: Array.from({ length: 12 }, (_, i) => y - y % 10 - 1 + i).map((year) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
2018
+ "button",
2019
+ {
2020
+ className: `gy-calendar-picker-item ${y === year ? "gy-calendar-picker-item--selected" : ""}`,
2021
+ onClick: () => {
2022
+ setCurrent(new Date(year, m, 1));
2023
+ setView("months");
2024
+ },
2025
+ children: year
2026
+ },
2027
+ year
2028
+ )) })
2029
+ ] })
2030
+ ] });
2031
+ }
2032
+
2033
+ // src/datepicker/DatePicker.tsx
2034
+ var import_react22 = require("react");
2035
+ var import_jsx_runtime27 = require("react/jsx-runtime");
2036
+ var formatDate = (date) => {
2037
+ return date.toLocaleDateString(void 0, {
2038
+ year: "numeric",
2039
+ month: "short",
2040
+ day: "numeric"
2041
+ });
2042
+ };
2043
+ function DatePicker({
2044
+ mode = "single",
2045
+ value,
2046
+ onChange,
2047
+ minDate,
2048
+ maxDate,
2049
+ label,
2050
+ placeholder = "Select date",
2051
+ disabled,
2052
+ error,
2053
+ helperText,
2054
+ className = ""
2055
+ }) {
2056
+ const uid = (0, import_react22.useId)();
2057
+ const [open, setOpen] = (0, import_react22.useState)(false);
2058
+ const rootRef = (0, import_react22.useRef)(null);
2059
+ (0, import_react22.useEffect)(() => {
2060
+ const handler = (e) => {
2061
+ if (!rootRef.current?.contains(e.target)) setOpen(false);
2062
+ };
2063
+ document.addEventListener("mousedown", handler);
2064
+ return () => document.removeEventListener("mousedown", handler);
2065
+ }, []);
2066
+ let displayValue = "";
2067
+ if (Array.isArray(value)) {
2068
+ if (value[0] && value[1]) displayValue = `${formatDate(value[0])} - ${formatDate(value[1])}`;
2069
+ else if (value[0]) displayValue = formatDate(value[0]);
2070
+ } else if (value) {
2071
+ displayValue = formatDate(value);
2072
+ }
2073
+ const handleChange = (val) => {
2074
+ onChange?.(val);
2075
+ if (mode === "single" || Array.isArray(val) && val[0] && val[1]) {
2076
+ setOpen(false);
2077
+ }
2078
+ };
2079
+ return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { ref: rootRef, className: `gy-datepicker ${className}`, children: [
2080
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { onClick: () => !disabled && setOpen((o) => !o), style: { cursor: disabled ? "not-allowed" : "pointer" }, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2081
+ Input,
2082
+ {
2083
+ id: `gy-datepicker-${uid}`,
2084
+ label,
2085
+ placeholder,
2086
+ value: displayValue,
2087
+ readOnly: true,
2088
+ disabled,
2089
+ error,
2090
+ helperText,
2091
+ style: { cursor: disabled ? "not-allowed" : "pointer", pointerEvents: "none" },
2092
+ rightIcon: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2093
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2", ry: "2" }),
2094
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("line", { x1: "16", y1: "2", x2: "16", y2: "6" }),
2095
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("line", { x1: "8", y1: "2", x2: "8", y2: "6" }),
2096
+ /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("line", { x1: "3", y1: "10", x2: "21", y2: "10" })
2097
+ ] })
2098
+ }
2099
+ ) }),
2100
+ open && !disabled && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "gy-datepicker-popover", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
2101
+ Calendar,
2102
+ {
2103
+ mode,
2104
+ value,
2105
+ onChange: handleChange,
2106
+ minDate,
2107
+ maxDate,
2108
+ className: "gy-calendar--popover",
2109
+ style: { border: "none", borderRadius: 0 }
2110
+ }
2111
+ ) })
2112
+ ] });
2113
+ }
2114
+
2115
+ // src/chart/Chart.tsx
2116
+ var import_recharts = require("recharts");
2117
+ var import_jsx_runtime28 = require("react/jsx-runtime");
2118
+ var DEFAULT_COLORS = [
2119
+ "var(--gy-primary)",
2120
+ "var(--gy-success)",
2121
+ "var(--gy-warning)",
2122
+ "var(--gy-danger)",
2123
+ "var(--gy-info)",
2124
+ "#8b5cf6",
2125
+ "#ec4899"
2126
+ ];
2127
+ function Chart({
2128
+ type,
2129
+ data,
2130
+ xAxisKey,
2131
+ series = [],
2132
+ nameKey,
2133
+ valueKey,
2134
+ height = 300,
2135
+ showGrid = true,
2136
+ showLegend = true,
2137
+ className = ""
2138
+ }) {
2139
+ const commonAxisProps = {
2140
+ stroke: "var(--gy-border-strong)",
2141
+ tick: { fill: "var(--gy-text-subtle)", fontSize: 12 },
2142
+ tickLine: { stroke: "var(--gy-border)" }
2143
+ };
2144
+ const commonTooltipProps = {
2145
+ contentStyle: {
2146
+ backgroundColor: "var(--gy-surface)",
2147
+ borderColor: "var(--gy-border)",
2148
+ borderRadius: "var(--gy-radius-lg)",
2149
+ boxShadow: "var(--gy-shadow-md)",
2150
+ color: "var(--gy-text)",
2151
+ fontSize: 13
2152
+ },
2153
+ itemStyle: { color: "var(--gy-text)" }
2154
+ };
2155
+ const renderContent = () => {
2156
+ switch (type) {
2157
+ case "line":
2158
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_recharts.LineChart, { data, children: [
2159
+ showGrid && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3", stroke: "var(--gy-border)", vertical: false }),
2160
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.XAxis, { dataKey: xAxisKey, ...commonAxisProps }),
2161
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.YAxis, { ...commonAxisProps }),
2162
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Tooltip, { ...commonTooltipProps }),
2163
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }),
2164
+ series.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2165
+ import_recharts.Line,
2166
+ {
2167
+ type: "monotone",
2168
+ dataKey: s.key,
2169
+ name: s.name ?? s.key,
2170
+ stroke: s.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length],
2171
+ strokeWidth: 2,
2172
+ dot: { r: 4, strokeWidth: 2, fill: "var(--gy-surface)" },
2173
+ activeDot: { r: 6, strokeWidth: 0 }
2174
+ },
2175
+ s.key
2176
+ ))
2177
+ ] });
2178
+ case "bar":
2179
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_recharts.BarChart, { data, children: [
2180
+ showGrid && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3", stroke: "var(--gy-border)", vertical: false }),
2181
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.XAxis, { dataKey: xAxisKey, ...commonAxisProps }),
2182
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.YAxis, { ...commonAxisProps }),
2183
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Tooltip, { ...commonTooltipProps, cursor: { fill: "var(--gy-background-muted)" } }),
2184
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }),
2185
+ series.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2186
+ import_recharts.Bar,
2187
+ {
2188
+ dataKey: s.key,
2189
+ name: s.name ?? s.key,
2190
+ fill: s.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length],
2191
+ radius: [4, 4, 0, 0]
2192
+ },
2193
+ s.key
2194
+ ))
2195
+ ] });
2196
+ case "area":
2197
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_recharts.AreaChart, { data, children: [
2198
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("defs", { children: series.map((s, i) => {
2199
+ const color = s.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length];
2200
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("linearGradient", { id: `grad-${s.key}`, x1: "0", y1: "0", x2: "0", y2: "1", children: [
2201
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("stop", { offset: "5%", stopColor: color, stopOpacity: 0.3 }),
2202
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("stop", { offset: "95%", stopColor: color, stopOpacity: 0 })
2203
+ ] }, `grad-${s.key}`);
2204
+ }) }),
2205
+ showGrid && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3", stroke: "var(--gy-border)", vertical: false }),
2206
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.XAxis, { dataKey: xAxisKey, ...commonAxisProps }),
2207
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.YAxis, { ...commonAxisProps }),
2208
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Tooltip, { ...commonTooltipProps }),
2209
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }),
2210
+ series.map((s, i) => {
2211
+ const color = s.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length];
2212
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2213
+ import_recharts.Area,
2214
+ {
2215
+ type: "monotone",
2216
+ dataKey: s.key,
2217
+ name: s.name ?? s.key,
2218
+ stroke: color,
2219
+ strokeWidth: 2,
2220
+ fillOpacity: 1,
2221
+ fill: `url(#grad-${s.key})`
2222
+ },
2223
+ s.key
2224
+ );
2225
+ })
2226
+ ] });
2227
+ case "pie":
2228
+ case "donut":
2229
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_recharts.PieChart, { children: [
2230
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Tooltip, { ...commonTooltipProps }),
2231
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }),
2232
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
2233
+ import_recharts.Pie,
2234
+ {
2235
+ data,
2236
+ dataKey: valueKey,
2237
+ nameKey,
2238
+ cx: "50%",
2239
+ cy: "50%",
2240
+ innerRadius: type === "donut" ? "60%" : 0,
2241
+ outerRadius: "80%",
2242
+ stroke: "var(--gy-surface)",
2243
+ strokeWidth: 2,
2244
+ paddingAngle: type === "donut" ? 2 : 0,
2245
+ children: data.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.Cell, { fill: entry.color ?? DEFAULT_COLORS[index % DEFAULT_COLORS.length] }, `cell-${index}`))
2246
+ }
2247
+ )
2248
+ ] });
2249
+ }
2250
+ };
2251
+ return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: `gy-chart ${className}`, style: { width: "100%", height }, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_recharts.ResponsiveContainer, { width: "100%", height: "100%", children: renderContent() }) });
2252
+ }
2253
+ // Annotate the CommonJS export names for ESM import in node:
2254
+ 0 && (module.exports = {
2255
+ Accordion,
2256
+ AnimatedNumber,
2257
+ Banner,
2258
+ Breadcrumb,
2259
+ Button,
2260
+ Calendar,
2261
+ Card,
2262
+ CardBody,
2263
+ CardFooter,
2264
+ CardHeader,
2265
+ CardInfo,
2266
+ Chart,
2267
+ Checkbox,
2268
+ Chip,
2269
+ ChipsInput,
2270
+ DatePicker,
2271
+ Dropdown,
2272
+ FileUpload,
2273
+ Input,
2274
+ KanbanBoard,
2275
+ Menu,
2276
+ Modal,
2277
+ ProgressBar,
2278
+ RadioGroup,
2279
+ ReorderList,
2280
+ Skeleton,
2281
+ Spinner,
2282
+ Stepper,
2283
+ Table,
2284
+ Tabs,
2285
+ Textarea,
2286
+ ToasterProvider,
2287
+ Toggle,
2288
+ Tooltip,
2289
+ Typography,
2290
+ useToast
2291
+ });