@pichetch08/trip-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/README.md +46 -0
  2. package/dist/accordion.d.ts +18 -0
  3. package/dist/accordion.js +76 -0
  4. package/dist/agreement-modal.d.ts +16 -0
  5. package/dist/agreement-modal.js +67 -0
  6. package/dist/alert.d.ts +13 -0
  7. package/dist/alert.js +47 -0
  8. package/dist/auth-hero.d.ts +7 -0
  9. package/dist/auth-hero.js +63 -0
  10. package/dist/avatar.d.ts +21 -0
  11. package/dist/avatar.js +114 -0
  12. package/dist/badge.d.ts +13 -0
  13. package/dist/badge.js +36 -0
  14. package/dist/banner.d.ts +14 -0
  15. package/dist/banner.js +57 -0
  16. package/dist/breadcrumb.d.ts +15 -0
  17. package/dist/breadcrumb.js +37 -0
  18. package/dist/button.d.ts +15 -0
  19. package/dist/button.js +81 -0
  20. package/dist/card.d.ts +30 -0
  21. package/dist/card.js +66 -0
  22. package/dist/change-summary-modal.d.ts +35 -0
  23. package/dist/change-summary-modal.js +128 -0
  24. package/dist/channel-badge.d.ts +8 -0
  25. package/dist/channel-badge.js +17 -0
  26. package/dist/checkbox.d.ts +28 -0
  27. package/dist/checkbox.js +108 -0
  28. package/dist/chunk-ORMEWXMH.js +37 -0
  29. package/dist/color-picker.d.ts +15 -0
  30. package/dist/color-picker.js +159 -0
  31. package/dist/confirm-dialog.d.ts +23 -0
  32. package/dist/confirm-dialog.js +108 -0
  33. package/dist/copy-button.d.ts +13 -0
  34. package/dist/copy-button.js +69 -0
  35. package/dist/dashed-add-button.d.ts +8 -0
  36. package/dist/dashed-add-button.js +24 -0
  37. package/dist/data-table.d.ts +27 -0
  38. package/dist/data-table.js +152 -0
  39. package/dist/date-picker.d.ts +19 -0
  40. package/dist/date-picker.js +234 -0
  41. package/dist/date-range-picker.d.ts +25 -0
  42. package/dist/date-range-picker.js +456 -0
  43. package/dist/dev-auto-fill.d.ts +12 -0
  44. package/dist/dev-auto-fill.js +22 -0
  45. package/dist/divider.d.ts +10 -0
  46. package/dist/divider.js +44 -0
  47. package/dist/drawer.d.ts +16 -0
  48. package/dist/drawer.js +111 -0
  49. package/dist/dropdown-menu.d.ts +20 -0
  50. package/dist/dropdown-menu.js +94 -0
  51. package/dist/empty-state.d.ts +13 -0
  52. package/dist/empty-state.js +24 -0
  53. package/dist/file-upload.d.ts +32 -0
  54. package/dist/file-upload.js +212 -0
  55. package/dist/filter-tabs.d.ts +16 -0
  56. package/dist/filter-tabs.js +30 -0
  57. package/dist/footer-action-bar.d.ts +21 -0
  58. package/dist/footer-action-bar.js +95 -0
  59. package/dist/form-input.d.ts +16 -0
  60. package/dist/form-input.js +58 -0
  61. package/dist/form-textarea.d.ts +13 -0
  62. package/dist/form-textarea.js +41 -0
  63. package/dist/icon-button.d.ts +12 -0
  64. package/dist/icon-button.js +54 -0
  65. package/dist/icon-picker.d.ts +15 -0
  66. package/dist/icon-picker.js +311 -0
  67. package/dist/icon-wrapper.d.ts +15 -0
  68. package/dist/icon-wrapper.js +52 -0
  69. package/dist/image-upload.d.ts +24 -0
  70. package/dist/image-upload.js +122 -0
  71. package/dist/index.d.ts +71 -0
  72. package/dist/index.js +155 -0
  73. package/dist/kbd.d.ts +15 -0
  74. package/dist/kbd.js +27 -0
  75. package/dist/mobile-preview.d.ts +36 -0
  76. package/dist/mobile-preview.js +167 -0
  77. package/dist/modal.d.ts +19 -0
  78. package/dist/modal.js +110 -0
  79. package/dist/multi-select.d.ts +30 -0
  80. package/dist/multi-select.js +261 -0
  81. package/dist/number-input.d.ts +21 -0
  82. package/dist/number-input.js +129 -0
  83. package/dist/otp-input.d.ts +13 -0
  84. package/dist/otp-input.js +114 -0
  85. package/dist/page-header.d.ts +15 -0
  86. package/dist/page-header.js +43 -0
  87. package/dist/page-state.d.ts +14 -0
  88. package/dist/page-state.js +29 -0
  89. package/dist/pagination.d.ts +20 -0
  90. package/dist/pagination.js +87 -0
  91. package/dist/popover.d.ts +11 -0
  92. package/dist/popover.js +70 -0
  93. package/dist/preview-drawer.d.ts +33 -0
  94. package/dist/preview-drawer.js +74 -0
  95. package/dist/progress-bar.d.ts +15 -0
  96. package/dist/progress-bar.js +56 -0
  97. package/dist/qr-code-display.d.ts +10 -0
  98. package/dist/qr-code-display.js +43 -0
  99. package/dist/radio-group.d.ts +19 -0
  100. package/dist/radio-group.js +78 -0
  101. package/dist/rating.d.ts +12 -0
  102. package/dist/rating.js +123 -0
  103. package/dist/rich-editor.d.ts +13 -0
  104. package/dist/rich-editor.js +97 -0
  105. package/dist/search-bar.d.ts +14 -0
  106. package/dist/search-bar.js +64 -0
  107. package/dist/section-header.d.ts +12 -0
  108. package/dist/section-header.js +41 -0
  109. package/dist/segmented-control.d.ts +24 -0
  110. package/dist/segmented-control.js +38 -0
  111. package/dist/select-picker.d.ts +24 -0
  112. package/dist/select-picker.js +157 -0
  113. package/dist/skeleton.d.ts +14 -0
  114. package/dist/skeleton.js +53 -0
  115. package/dist/slider.d.ts +17 -0
  116. package/dist/slider.js +151 -0
  117. package/dist/spinner.d.ts +13 -0
  118. package/dist/spinner.js +38 -0
  119. package/dist/stat-card.d.ts +20 -0
  120. package/dist/stat-card.js +87 -0
  121. package/dist/stats-summary.d.ts +13 -0
  122. package/dist/stats-summary.js +28 -0
  123. package/dist/status-badge.d.ts +19 -0
  124. package/dist/status-badge.js +41 -0
  125. package/dist/stepper.d.ts +12 -0
  126. package/dist/stepper.js +89 -0
  127. package/dist/tabs.d.ts +18 -0
  128. package/dist/tabs.js +70 -0
  129. package/dist/tag.d.ts +23 -0
  130. package/dist/tag.js +158 -0
  131. package/dist/time-picker.d.ts +19 -0
  132. package/dist/time-picker.js +222 -0
  133. package/dist/timeline.d.ts +15 -0
  134. package/dist/timeline.js +49 -0
  135. package/dist/toast.d.ts +18 -0
  136. package/dist/toast.js +108 -0
  137. package/dist/toggle-switch.d.ts +12 -0
  138. package/dist/toggle-switch.js +34 -0
  139. package/dist/tooltip.d.ts +9 -0
  140. package/dist/tooltip.js +69 -0
  141. package/dist/trip-day-map-lazy.d.ts +15 -0
  142. package/dist/trip-day-map-lazy.js +16 -0
  143. package/dist/trip-day-map.d.ts +15 -0
  144. package/dist/trip-day-map.js +62 -0
  145. package/package.json +73 -0
@@ -0,0 +1,159 @@
1
+ "use client";
2
+ import {
3
+ __spreadProps,
4
+ __spreadValues
5
+ } from "./chunk-ORMEWXMH.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useState, useRef } from "react";
8
+ const DEFAULT_PRESETS = [
9
+ "#ef4444",
10
+ "#f97316",
11
+ "#eab308",
12
+ "#22c55e",
13
+ "#14b8a6",
14
+ "#3b82f6",
15
+ "#8b5cf6",
16
+ "#ec4899",
17
+ "#64748b",
18
+ "#000000",
19
+ "#ffffff",
20
+ "#f1f5f9"
21
+ ];
22
+ function isValidHex(value) {
23
+ return /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value);
24
+ }
25
+ function ColorPicker({
26
+ label,
27
+ value,
28
+ onChange,
29
+ presets = DEFAULT_PRESETS,
30
+ showHexInput = true,
31
+ showPalette = true,
32
+ error,
33
+ required,
34
+ hexErrorText = "\u0E01\u0E23\u0E38\u0E13\u0E32\u0E01\u0E23\u0E2D\u0E01 hex color \u0E17\u0E35\u0E48\u0E16\u0E39\u0E01\u0E15\u0E49\u0E2D\u0E07 \u0E40\u0E0A\u0E48\u0E19 #3b82f6",
35
+ paletteLabel = "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E08\u0E32\u0E19\u0E2A\u0E35"
36
+ }) {
37
+ const [inputValue, setInputValue] = useState(value);
38
+ const [inputError, setInputError] = useState(null);
39
+ const inputRef = useRef(null);
40
+ const nativePickerRef = useRef(null);
41
+ const applyColor = (hex) => {
42
+ setInputValue(hex);
43
+ setInputError(null);
44
+ onChange(hex);
45
+ };
46
+ const handleInputChange = (e) => {
47
+ const raw = e.target.value;
48
+ setInputValue(raw);
49
+ const normalized = raw.startsWith("#") ? raw : `#${raw}`;
50
+ if (isValidHex(normalized)) {
51
+ setInputError(null);
52
+ onChange(normalized);
53
+ }
54
+ };
55
+ const handleInputBlur = () => {
56
+ const normalized = inputValue.startsWith("#") ? inputValue : `#${inputValue}`;
57
+ if (!isValidHex(normalized)) {
58
+ setInputError(hexErrorText);
59
+ setInputValue(value);
60
+ } else {
61
+ setInputError(null);
62
+ onChange(normalized);
63
+ }
64
+ };
65
+ const displayError = error != null ? error : inputError;
66
+ const inputId = label ? `colorpicker-${label.replace(/\s+/g, "-").toLowerCase()}` : void 0;
67
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
68
+ label && /* @__PURE__ */ jsxs("label", { htmlFor: inputId, className: "text-sm font-medium text-on-surface", children: [
69
+ label,
70
+ required && /* @__PURE__ */ jsx("span", { className: "text-red-500 ml-1", children: "*" })
71
+ ] }),
72
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-6 gap-2", children: presets.map((hex) => {
73
+ const isSelected = value.toLowerCase() === hex.toLowerCase();
74
+ return /* @__PURE__ */ jsx(
75
+ "button",
76
+ {
77
+ type: "button",
78
+ "aria-label": hex,
79
+ onClick: () => applyColor(hex),
80
+ className: [
81
+ "w-8 h-8 rounded-full cursor-pointer border-2 transition-all hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 active:scale-95",
82
+ isSelected ? "border-primary ring-2 ring-primary/30 scale-110" : "border-transparent hover:border-outline-variant"
83
+ ].join(" "),
84
+ style: { backgroundColor: hex }
85
+ },
86
+ hex
87
+ );
88
+ }) }),
89
+ showHexInput && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
90
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
91
+ /* @__PURE__ */ jsx(
92
+ "div",
93
+ {
94
+ className: "w-10 h-10 rounded-xl border border-outline-variant/30 shadow-sm shrink-0 cursor-pointer hover:ring-2 hover:ring-primary/30 transition-all",
95
+ style: { backgroundColor: isValidHex(value) ? value : "#ffffff" },
96
+ "aria-hidden": "true",
97
+ onClick: () => {
98
+ var _a;
99
+ return showPalette && ((_a = nativePickerRef.current) == null ? void 0 : _a.click());
100
+ },
101
+ title: showPalette ? paletteLabel : void 0
102
+ }
103
+ ),
104
+ showPalette && /* @__PURE__ */ jsx(
105
+ "input",
106
+ {
107
+ ref: nativePickerRef,
108
+ type: "color",
109
+ value: isValidHex(value) ? value : "#3b82f6",
110
+ onChange: (e) => applyColor(e.target.value),
111
+ className: "absolute inset-0 opacity-0 w-full h-full cursor-pointer",
112
+ tabIndex: -1,
113
+ "aria-label": paletteLabel
114
+ }
115
+ )
116
+ ] }),
117
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 relative", children: [
118
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center border border-outline-variant/40 rounded-xl overflow-hidden bg-surface-container-low focus-within:ring-2 focus-within:ring-primary/30 focus-within:border-primary", children: [
119
+ /* @__PURE__ */ jsx("span", { className: "pl-3 pr-1 text-sm font-mono text-on-surface-variant select-none", children: "#" }),
120
+ /* @__PURE__ */ jsx(
121
+ "input",
122
+ {
123
+ ref: inputRef,
124
+ id: inputId,
125
+ type: "text",
126
+ value: inputValue.startsWith("#") ? inputValue.slice(1) : inputValue,
127
+ onChange: (e) => handleInputChange(__spreadProps(__spreadValues({}, e), {
128
+ target: __spreadProps(__spreadValues({}, e.target), { value: `#${e.target.value}` })
129
+ })),
130
+ onBlur: handleInputBlur,
131
+ placeholder: "3b82f6",
132
+ maxLength: 7,
133
+ className: "flex-1 py-2 pr-3 text-sm font-mono bg-transparent outline-none text-on-surface placeholder:text-on-surface-variant/40",
134
+ "aria-invalid": !!displayError
135
+ }
136
+ )
137
+ ] }),
138
+ displayError && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-red-500", children: displayError })
139
+ ] }),
140
+ showPalette && /* @__PURE__ */ jsx(
141
+ "button",
142
+ {
143
+ type: "button",
144
+ onClick: () => {
145
+ var _a;
146
+ return (_a = nativePickerRef.current) == null ? void 0 : _a.click();
147
+ },
148
+ className: "w-10 h-10 rounded-xl flex items-center justify-center bg-surface-container-low border border-outline-variant/40 text-on-surface-variant hover:bg-surface-container hover:text-on-surface transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 shrink-0",
149
+ "aria-label": paletteLabel,
150
+ title: paletteLabel,
151
+ children: /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined", style: { fontSize: "20px" }, children: "palette" })
152
+ }
153
+ )
154
+ ] })
155
+ ] });
156
+ }
157
+ export {
158
+ ColorPicker
159
+ };
@@ -0,0 +1,23 @@
1
+ interface ConfirmDialogProps {
2
+ open: boolean;
3
+ /** Called when dialog should close. Accepts both staff's onOpenChange and admin's onClose patterns. */
4
+ onOpenChange?: (open: boolean) => void;
5
+ onClose?: () => void;
6
+ onConfirm: () => void;
7
+ title: string;
8
+ description?: string;
9
+ confirmLabel?: string;
10
+ /** Alias for confirmLabel (backward compat). */
11
+ confirmText?: string;
12
+ cancelLabel?: string;
13
+ /** Alias for cancelLabel (backward compat). */
14
+ cancelText?: string;
15
+ /** "danger" maps to isDangerous=true. */
16
+ variant?: "danger" | "default";
17
+ /** Alias for variant="danger" (backward compat). */
18
+ isDangerous?: boolean;
19
+ isLoading?: boolean;
20
+ }
21
+ declare function ConfirmDialog({ open, onOpenChange, onClose, onConfirm, title, description, confirmLabel, confirmText, cancelLabel, cancelText, variant, isDangerous, isLoading, }: ConfirmDialogProps): React.ReactNode;
22
+
23
+ export { ConfirmDialog };
@@ -0,0 +1,108 @@
1
+ "use client";
2
+ import "./chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useEffect, useRef } from "react";
5
+ import { Button } from "./button";
6
+ function ConfirmDialog({
7
+ open,
8
+ onOpenChange,
9
+ onClose,
10
+ onConfirm,
11
+ title,
12
+ description,
13
+ confirmLabel,
14
+ confirmText = "\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19",
15
+ cancelLabel,
16
+ cancelText = "\u0E22\u0E01\u0E40\u0E25\u0E34\u0E01",
17
+ variant = "default",
18
+ isDangerous = false,
19
+ isLoading = false
20
+ }) {
21
+ const dialogRef = useRef(null);
22
+ const cancelRef = useRef(null);
23
+ const confirmBtn = confirmLabel != null ? confirmLabel : confirmText;
24
+ const cancelBtn = cancelLabel != null ? cancelLabel : cancelText;
25
+ const isDanger = isDangerous || variant === "danger";
26
+ const handleClose = () => {
27
+ onOpenChange == null ? void 0 : onOpenChange(false);
28
+ onClose == null ? void 0 : onClose();
29
+ };
30
+ useEffect(() => {
31
+ var _a;
32
+ if (!open) return;
33
+ (_a = cancelRef.current) == null ? void 0 : _a.focus();
34
+ const onKey = (e) => {
35
+ if (e.key === "Escape") {
36
+ e.preventDefault();
37
+ handleClose();
38
+ return;
39
+ }
40
+ if (e.key !== "Tab" || !dialogRef.current) return;
41
+ const els = Array.from(
42
+ dialogRef.current.querySelectorAll(
43
+ 'button:not([disabled]), [tabindex]:not([tabindex="-1"])'
44
+ )
45
+ );
46
+ if (els.length === 0) return;
47
+ const first = els[0], last = els[els.length - 1];
48
+ if (e.shiftKey && document.activeElement === first) {
49
+ e.preventDefault();
50
+ last.focus();
51
+ } else if (!e.shiftKey && document.activeElement === last) {
52
+ e.preventDefault();
53
+ first.focus();
54
+ }
55
+ };
56
+ window.addEventListener("keydown", onKey);
57
+ return () => window.removeEventListener("keydown", onKey);
58
+ }, [open]);
59
+ if (!open) return null;
60
+ return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-100 flex items-center justify-center p-4", children: [
61
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/50 cursor-pointer", onClick: handleClose }),
62
+ /* @__PURE__ */ jsxs(
63
+ "div",
64
+ {
65
+ ref: dialogRef,
66
+ role: "alertdialog",
67
+ "aria-modal": "true",
68
+ "aria-labelledby": "confirm-dialog-title",
69
+ "aria-describedby": description ? "confirm-dialog-desc" : void 0,
70
+ className: "relative bg-surface rounded-2xl shadow-2xl w-full max-w-sm p-6 space-y-4",
71
+ children: [
72
+ /* @__PURE__ */ jsx("h3", { id: "confirm-dialog-title", className: "text-lg font-bold text-on-surface", children: title }),
73
+ description && /* @__PURE__ */ jsx("p", { id: "confirm-dialog-desc", className: "text-sm text-on-surface-variant whitespace-pre-line", children: description }),
74
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-3 pt-2", children: [
75
+ /* @__PURE__ */ jsx(
76
+ Button,
77
+ {
78
+ ref: cancelRef,
79
+ variant: "outline",
80
+ className: "flex-1",
81
+ onClick: handleClose,
82
+ disabled: isLoading,
83
+ children: cancelBtn
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsx(
87
+ Button,
88
+ {
89
+ variant: isDanger ? "danger" : "primary",
90
+ className: "flex-1",
91
+ onClick: () => {
92
+ onConfirm();
93
+ handleClose();
94
+ },
95
+ disabled: isLoading,
96
+ loading: isLoading,
97
+ children: confirmBtn
98
+ }
99
+ )
100
+ ] })
101
+ ]
102
+ }
103
+ )
104
+ ] });
105
+ }
106
+ export {
107
+ ConfirmDialog
108
+ };
@@ -0,0 +1,13 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface CopyButtonProps {
4
+ text: string;
5
+ label?: string;
6
+ copiedLabel?: string;
7
+ variant?: "button" | "icon";
8
+ size?: "sm" | "md";
9
+ className?: string;
10
+ }
11
+ declare function CopyButton({ text, label, copiedLabel, variant, size, className, }: CopyButtonProps): react_jsx_runtime.JSX.Element;
12
+
13
+ export { CopyButton };
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import "./chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useState, useRef } from "react";
5
+ function CopyButton({
6
+ text,
7
+ label = "\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01",
8
+ copiedLabel = "\u0E04\u0E31\u0E14\u0E25\u0E2D\u0E01\u0E41\u0E25\u0E49\u0E27!",
9
+ variant = "button",
10
+ size = "md",
11
+ className = ""
12
+ }) {
13
+ const [copied, setCopied] = useState(false);
14
+ const timeoutRef = useRef(null);
15
+ const handleCopy = async () => {
16
+ try {
17
+ await navigator.clipboard.writeText(text);
18
+ setCopied(true);
19
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
20
+ timeoutRef.current = setTimeout(() => setCopied(false), 2e3);
21
+ } catch (e) {
22
+ }
23
+ };
24
+ if (variant === "icon") {
25
+ return /* @__PURE__ */ jsx(
26
+ "button",
27
+ {
28
+ type: "button",
29
+ onClick: handleCopy,
30
+ "aria-label": copied ? copiedLabel : label,
31
+ className: [
32
+ "p-2 rounded-lg transition-colors active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
33
+ copied ? "text-emerald-600 bg-emerald-100" : "text-on-surface-variant hover:text-on-surface hover:bg-surface-container",
34
+ className
35
+ ].filter(Boolean).join(" "),
36
+ children: /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined", style: { fontSize: "20px" }, "aria-hidden": "true", children: copied ? "check" : "content_copy" })
37
+ }
38
+ );
39
+ }
40
+ const sizeClasses = size === "sm" ? "px-3 py-1.5 text-xs rounded-lg" : "px-4 py-2 text-sm rounded-xl";
41
+ return /* @__PURE__ */ jsxs(
42
+ "button",
43
+ {
44
+ type: "button",
45
+ onClick: handleCopy,
46
+ className: [
47
+ "inline-flex items-center gap-1.5 font-medium transition-colors active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
48
+ sizeClasses,
49
+ copied ? "bg-emerald-100 text-emerald-700" : "bg-surface-container text-on-surface-variant hover:bg-surface-container-high",
50
+ className
51
+ ].filter(Boolean).join(" "),
52
+ children: [
53
+ /* @__PURE__ */ jsx(
54
+ "span",
55
+ {
56
+ className: "material-symbols-outlined",
57
+ style: { fontSize: size === "sm" ? "14px" : "16px" },
58
+ "aria-hidden": "true",
59
+ children: copied ? "check" : "content_copy"
60
+ }
61
+ ),
62
+ copied ? copiedLabel : label
63
+ ]
64
+ }
65
+ );
66
+ }
67
+ export {
68
+ CopyButton
69
+ };
@@ -0,0 +1,8 @@
1
+ interface DashedAddButtonProps {
2
+ children: React.ReactNode;
3
+ onClick?: () => void;
4
+ className?: string;
5
+ }
6
+ declare function DashedAddButton({ children, onClick, className, }: DashedAddButtonProps): React.ReactNode;
7
+
8
+ export { DashedAddButton };
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import "./chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ function DashedAddButton({
5
+ children,
6
+ onClick,
7
+ className = ""
8
+ }) {
9
+ return /* @__PURE__ */ jsxs(
10
+ "button",
11
+ {
12
+ type: "button",
13
+ onClick,
14
+ className: `w-full py-4 border-2 border-dashed border-primary/30 rounded-xl text-xs font-bold text-primary uppercase tracking-widest hover:bg-primary/5 transition-colors flex items-center justify-center gap-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary ${className}`,
15
+ children: [
16
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm", "aria-hidden": "true", children: "add_circle" }),
17
+ children
18
+ ]
19
+ }
20
+ );
21
+ }
22
+ export {
23
+ DashedAddButton
24
+ };
@@ -0,0 +1,27 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface Column<T> {
4
+ key: keyof T;
5
+ label: string;
6
+ render?: (value: any, item: T) => React.ReactNode;
7
+ sortable?: boolean;
8
+ width?: string;
9
+ }
10
+ interface DataTableProps<T> {
11
+ columns: Column<T>[];
12
+ data: T[];
13
+ rowKey: keyof T;
14
+ onRowClick?: (item: T) => void;
15
+ actions?: (item: T) => React.ReactNode;
16
+ isLoading?: boolean;
17
+ emptyMessage?: string;
18
+ loadingText?: string;
19
+ actionsLabel?: string;
20
+ selectAllLabel?: string;
21
+ selectRowLabel?: (key: string) => string;
22
+ selectable?: boolean;
23
+ onSelectionChange?: (selected: any[]) => void;
24
+ }
25
+ declare function DataTable<T>({ columns, data, rowKey, onRowClick, actions, isLoading, emptyMessage, loadingText, actionsLabel, selectAllLabel, selectRowLabel, selectable, onSelectionChange, }: DataTableProps<T>): react_jsx_runtime.JSX.Element;
26
+
27
+ export { type Column, DataTable };
@@ -0,0 +1,152 @@
1
+ "use client";
2
+ import {
3
+ __spreadProps,
4
+ __spreadValues
5
+ } from "./chunk-ORMEWXMH.js";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { useState } from "react";
8
+ function DataTable({
9
+ columns,
10
+ data,
11
+ rowKey,
12
+ onRowClick,
13
+ actions,
14
+ isLoading = false,
15
+ emptyMessage = "\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25",
16
+ loadingText = "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14...",
17
+ actionsLabel = "\u0E08\u0E31\u0E14\u0E01\u0E32\u0E23",
18
+ selectAllLabel = "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14",
19
+ selectRowLabel = (key) => `\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E41\u0E16\u0E27\u0E17\u0E35\u0E48 ${key}`,
20
+ selectable = false,
21
+ onSelectionChange
22
+ }) {
23
+ const [sortKey, setSortKey] = useState(null);
24
+ const [sortDirection, setSortDirection] = useState("asc");
25
+ const [selectedRows, setSelectedRows] = useState(/* @__PURE__ */ new Set());
26
+ const handleSort = (key) => {
27
+ if (sortKey === key) {
28
+ setSortDirection(sortDirection === "asc" ? "desc" : "asc");
29
+ } else {
30
+ setSortKey(key);
31
+ setSortDirection("asc");
32
+ }
33
+ };
34
+ const handleSelectAll = () => {
35
+ if (selectedRows.size === data.length) {
36
+ setSelectedRows(/* @__PURE__ */ new Set());
37
+ onSelectionChange == null ? void 0 : onSelectionChange([]);
38
+ } else {
39
+ const newSelected = new Set(data.map((item) => item[rowKey]));
40
+ setSelectedRows(newSelected);
41
+ onSelectionChange == null ? void 0 : onSelectionChange(Array.from(newSelected));
42
+ }
43
+ };
44
+ const handleSelectRow = (item) => {
45
+ const key = item[rowKey];
46
+ const newSelected = new Set(selectedRows);
47
+ if (newSelected.has(key)) {
48
+ newSelected.delete(key);
49
+ } else {
50
+ newSelected.add(key);
51
+ }
52
+ setSelectedRows(newSelected);
53
+ onSelectionChange == null ? void 0 : onSelectionChange(Array.from(newSelected));
54
+ };
55
+ const normalizedColumns = columns.map((col) => {
56
+ var _a;
57
+ return __spreadProps(__spreadValues({}, col), {
58
+ sortable: (_a = col.sortable) != null ? _a : true
59
+ });
60
+ });
61
+ const sortedData = sortKey ? [...data].sort((a, b) => {
62
+ const aVal = a[sortKey];
63
+ const bVal = b[sortKey];
64
+ if (aVal < bVal) return sortDirection === "asc" ? -1 : 1;
65
+ if (aVal > bVal) return sortDirection === "asc" ? 1 : -1;
66
+ return 0;
67
+ }) : data;
68
+ if (isLoading) {
69
+ return /* @__PURE__ */ jsxs("div", { className: "w-full p-8 text-center", role: "status", "aria-live": "polite", "aria-label": loadingText, children: [
70
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined animate-spin inline-block", "aria-hidden": "true", children: "progress_activity" }),
71
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-on-surface-variant", children: loadingText })
72
+ ] });
73
+ }
74
+ if (!data || data.length === 0) {
75
+ return /* @__PURE__ */ jsxs("div", { className: "w-full p-8 text-center", children: [
76
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-4xl text-outline mb-2 block", "aria-hidden": "true", children: "inbox" }),
77
+ /* @__PURE__ */ jsx("p", { className: "text-on-surface-variant", children: emptyMessage })
78
+ ] });
79
+ }
80
+ const colCount = columns.length + (selectable ? 1 : 0) + (actions ? 1 : 0);
81
+ return /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-left text-sm", "aria-colcount": colCount, children: [
82
+ /* @__PURE__ */ jsx("thead", { className: "bg-surface-container-low text-xs uppercase tracking-wider text-on-surface-variant font-bold", children: /* @__PURE__ */ jsxs("tr", { children: [
83
+ selectable && /* @__PURE__ */ jsx("th", { className: "px-6 py-4 w-12", scope: "col", children: /* @__PURE__ */ jsx(
84
+ "input",
85
+ {
86
+ type: "checkbox",
87
+ checked: selectedRows.size === data.length,
88
+ onChange: handleSelectAll,
89
+ "aria-label": selectAllLabel,
90
+ className: "w-4 h-4 rounded border-outline-variant text-primary accent-primary cursor-pointer"
91
+ }
92
+ ) }),
93
+ normalizedColumns.map((col) => /* @__PURE__ */ jsx(
94
+ "th",
95
+ {
96
+ scope: "col",
97
+ "aria-sort": col.sortable ? sortKey === col.key ? sortDirection === "asc" ? "ascending" : "descending" : "none" : void 0,
98
+ className: `px-6 py-4 ${col.width || ""} ${col.sortable ? "cursor-pointer hover:bg-surface-container" : ""}`,
99
+ onClick: () => col.sortable && handleSort(col.key),
100
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
101
+ col.label,
102
+ col.sortable && sortKey === col.key && /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-xs leading-none", "aria-hidden": "true", children: sortDirection === "asc" ? "arrow_upward" : "arrow_downward" })
103
+ ] })
104
+ },
105
+ String(col.key)
106
+ )),
107
+ actions && /* @__PURE__ */ jsx("th", { className: "px-6 py-4 text-right", scope: "col", children: actionsLabel })
108
+ ] }) }),
109
+ /* @__PURE__ */ jsx("tbody", { children: sortedData.map((item) => /* @__PURE__ */ jsxs(
110
+ "tr",
111
+ {
112
+ className: "border-t border-outline-variant/20 hover:bg-surface-container-lowest transition-colors cursor-pointer",
113
+ onClick: () => onRowClick == null ? void 0 : onRowClick(item),
114
+ children: [
115
+ selectable && /* @__PURE__ */ jsx(
116
+ "td",
117
+ {
118
+ className: "px-6 py-4",
119
+ onClick: (e) => {
120
+ e.stopPropagation();
121
+ handleSelectRow(item);
122
+ },
123
+ children: /* @__PURE__ */ jsx(
124
+ "input",
125
+ {
126
+ type: "checkbox",
127
+ checked: selectedRows.has(item[rowKey]),
128
+ onChange: () => handleSelectRow(item),
129
+ "aria-label": selectRowLabel(String(item[rowKey])),
130
+ className: "w-4 h-4 rounded border-outline-variant text-primary accent-primary cursor-pointer"
131
+ }
132
+ )
133
+ }
134
+ ),
135
+ normalizedColumns.map((col) => /* @__PURE__ */ jsx("td", { className: "px-6 py-4", children: col.render ? col.render(item[col.key], item) : String(item[col.key]) }, String(col.key))),
136
+ actions && /* @__PURE__ */ jsx(
137
+ "td",
138
+ {
139
+ className: "px-6 py-4 text-right",
140
+ onClick: (e) => e.stopPropagation(),
141
+ children: actions(item)
142
+ }
143
+ )
144
+ ]
145
+ },
146
+ String(item[rowKey])
147
+ )) })
148
+ ] }) });
149
+ }
150
+ export {
151
+ DataTable
152
+ };
@@ -0,0 +1,19 @@
1
+ interface DatePickerProps {
2
+ label?: string;
3
+ value: string;
4
+ onChange: (value: string) => void;
5
+ placeholder?: string;
6
+ todayLabel?: string;
7
+ clearLabel?: string;
8
+ min?: string;
9
+ max?: string;
10
+ required?: boolean;
11
+ error?: string;
12
+ icon?: string;
13
+ name?: string;
14
+ dayNames?: string[];
15
+ monthNames?: string[];
16
+ }
17
+ declare function DatePicker({ label, value, onChange, placeholder, todayLabel, clearLabel, min, max, required, error, icon, name, dayNames, monthNames, }: DatePickerProps): React.ReactNode;
18
+
19
+ export { DatePicker };