@marcoschwartz/lite-ui 0.7.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +51 -5
- package/dist/index.d.ts +51 -5
- package/dist/index.js +1127 -282
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1115 -272
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -198,6 +198,9 @@ var Select = ({
|
|
|
198
198
|
value: controlledValue,
|
|
199
199
|
defaultValue,
|
|
200
200
|
onChange,
|
|
201
|
+
label,
|
|
202
|
+
error,
|
|
203
|
+
helperText,
|
|
201
204
|
...props
|
|
202
205
|
}) => {
|
|
203
206
|
const { theme, themeName } = useTheme();
|
|
@@ -232,7 +235,8 @@ var Select = ({
|
|
|
232
235
|
const baseStyles = theme.select.base;
|
|
233
236
|
const sizeStyles2 = theme.select.sizes[size];
|
|
234
237
|
const disabledStyles = disabled ? theme.select.disabled : "";
|
|
235
|
-
const
|
|
238
|
+
const errorStyles = error ? "border-red-500 focus:ring-red-500 dark:border-red-500" : "";
|
|
239
|
+
const buttonClasses = `${baseStyles} ${sizeStyles2} ${disabledStyles} ${errorStyles}`.trim();
|
|
236
240
|
const iconColor = themeName === "minimalistic" ? disabled ? "text-gray-600" : "text-white" : disabled ? "text-gray-400" : "text-gray-500";
|
|
237
241
|
const dropdownBaseStyles = themeName === "minimalistic" ? "bg-black border-2 border-white" : "bg-white border border-gray-300 shadow-lg dark:bg-gray-800 dark:border-gray-600";
|
|
238
242
|
const optionBaseStyles = themeName === "minimalistic" ? "text-white hover:bg-white hover:text-black transition-colors duration-200" : "text-gray-900 hover:bg-blue-50 transition-colors duration-150 dark:text-gray-100 dark:hover:bg-gray-700";
|
|
@@ -242,51 +246,56 @@ var Select = ({
|
|
|
242
246
|
lg: "px-4 py-3 text-lg",
|
|
243
247
|
xl: "px-5 py-4 text-xl"
|
|
244
248
|
}[size];
|
|
245
|
-
return /* @__PURE__ */ jsxs2("div", { className:
|
|
246
|
-
/* @__PURE__ */ jsx3(
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
{
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
"
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
"
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
249
|
+
return /* @__PURE__ */ jsxs2("div", { className: `w-full ${className}`, children: [
|
|
250
|
+
label && /* @__PURE__ */ jsx3("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
251
|
+
/* @__PURE__ */ jsxs2("div", { className: "relative inline-block w-full", ref: dropdownRef, ...props, children: [
|
|
252
|
+
/* @__PURE__ */ jsx3(
|
|
253
|
+
"button",
|
|
254
|
+
{
|
|
255
|
+
type: "button",
|
|
256
|
+
className: buttonClasses,
|
|
257
|
+
onClick: handleToggle,
|
|
258
|
+
disabled,
|
|
259
|
+
children: /* @__PURE__ */ jsx3("span", { className: !selectedOption && placeholder ? "opacity-50" : "", children: displayText })
|
|
260
|
+
}
|
|
261
|
+
),
|
|
262
|
+
/* @__PURE__ */ jsx3("div", { className: "pointer-events-none absolute inset-y-0 right-0 flex items-center pr-4", children: /* @__PURE__ */ jsx3(
|
|
263
|
+
"svg",
|
|
264
|
+
{
|
|
265
|
+
className: `h-5 w-5 transition-transform duration-200 ${iconColor} ${isOpen ? "rotate-180" : ""}`,
|
|
266
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
267
|
+
viewBox: "0 0 20 20",
|
|
268
|
+
fill: "currentColor",
|
|
269
|
+
"aria-hidden": "true",
|
|
270
|
+
children: /* @__PURE__ */ jsx3(
|
|
271
|
+
"path",
|
|
272
|
+
{
|
|
273
|
+
fillRule: "evenodd",
|
|
274
|
+
d: "M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z",
|
|
275
|
+
clipRule: "evenodd"
|
|
276
|
+
}
|
|
277
|
+
)
|
|
278
|
+
}
|
|
279
|
+
) }),
|
|
280
|
+
isOpen && !disabled && /* @__PURE__ */ jsx3(
|
|
281
|
+
"div",
|
|
282
|
+
{
|
|
283
|
+
className: `absolute z-50 w-full mt-1 ${dropdownBaseStyles} rounded-lg overflow-hidden`,
|
|
284
|
+
style: { maxHeight: "300px", overflowY: "auto" },
|
|
285
|
+
children: options.map((option) => /* @__PURE__ */ jsx3(
|
|
286
|
+
"div",
|
|
287
|
+
{
|
|
288
|
+
className: `${optionBaseStyles} ${optionSizeStyles} cursor-pointer ${value === option.value ? themeName === "minimalistic" ? "bg-white text-black" : "bg-blue-50 dark:bg-gray-700" : ""}`,
|
|
289
|
+
onClick: () => handleSelect(option.value),
|
|
290
|
+
children: option.label
|
|
291
|
+
},
|
|
292
|
+
option.value
|
|
293
|
+
))
|
|
294
|
+
}
|
|
295
|
+
)
|
|
296
|
+
] }),
|
|
297
|
+
error && /* @__PURE__ */ jsx3("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
298
|
+
helperText && !error && /* @__PURE__ */ jsx3("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText })
|
|
290
299
|
] });
|
|
291
300
|
};
|
|
292
301
|
|
|
@@ -706,6 +715,7 @@ var AppShell = ({
|
|
|
706
715
|
const [isMobileNavbarOpen, setIsMobileNavbarOpen] = useState4(defaultNavbarOpen);
|
|
707
716
|
const navbarWidth = navbar?.width || "md";
|
|
708
717
|
const navbarBreakpoint = navbar?.breakpoint || "md";
|
|
718
|
+
const navbarPosition = navbar?.position || "side";
|
|
709
719
|
const widthClass = widthClasses2[navbarWidth];
|
|
710
720
|
const breakpoint = breakpointClasses[navbarBreakpoint];
|
|
711
721
|
if (!responsive && navbar) {
|
|
@@ -723,6 +733,51 @@ var AppShell = ({
|
|
|
723
733
|
/* @__PURE__ */ jsx38("main", { className: "flex-1 overflow-y-auto", children })
|
|
724
734
|
] });
|
|
725
735
|
}
|
|
736
|
+
if (navbar && navbarPosition === "top") {
|
|
737
|
+
const mobileMenuClass = navbarBreakpoint === "sm" ? "sm:hidden" : navbarBreakpoint === "md" ? "md:hidden" : navbarBreakpoint === "lg" ? "lg:hidden" : "xl:hidden";
|
|
738
|
+
const desktopNavClass = navbarBreakpoint === "sm" ? "sm:flex" : navbarBreakpoint === "md" ? "md:flex" : navbarBreakpoint === "lg" ? "lg:flex" : "xl:flex";
|
|
739
|
+
return /* @__PURE__ */ jsxs7("div", { className: `min-h-screen flex flex-col bg-gray-50 dark:bg-gray-900 ${className}`, children: [
|
|
740
|
+
/* @__PURE__ */ jsx38("nav", { className: "sticky top-0 z-30 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx38("div", { className: "max-w-7xl mx-auto px-4 sm:px-6 lg:px-8", children: /* @__PURE__ */ jsxs7("div", { className: "flex justify-between items-center h-16", children: [
|
|
741
|
+
/* @__PURE__ */ jsx38("div", { className: "flex items-center", children: navbarLogo ? /* @__PURE__ */ jsx38("div", { children: navbarLogo }) : navbarTitle ? /* @__PURE__ */ jsx38("span", { className: "text-xl font-bold text-gray-900 dark:text-gray-100", children: navbarTitle }) : null }),
|
|
742
|
+
/* @__PURE__ */ jsx38("div", { className: `hidden ${desktopNavClass} items-center gap-6`, children: navbar.content }),
|
|
743
|
+
/* @__PURE__ */ jsx38(
|
|
744
|
+
"button",
|
|
745
|
+
{
|
|
746
|
+
className: `${mobileMenuClass} p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors`,
|
|
747
|
+
onClick: () => setIsMobileNavbarOpen(!isMobileNavbarOpen),
|
|
748
|
+
"aria-label": "Toggle menu",
|
|
749
|
+
children: /* @__PURE__ */ jsx38(MenuIcon, { size: "md" })
|
|
750
|
+
}
|
|
751
|
+
)
|
|
752
|
+
] }) }) }),
|
|
753
|
+
header && /* @__PURE__ */ jsx38("div", { className: "w-full", children: header }),
|
|
754
|
+
isMobileNavbarOpen && /* @__PURE__ */ jsxs7(Fragment4, { children: [
|
|
755
|
+
/* @__PURE__ */ jsx38(
|
|
756
|
+
"div",
|
|
757
|
+
{
|
|
758
|
+
className: `${mobileMenuClass} fixed inset-0 z-40 bg-black/60 backdrop-blur-sm animate-in fade-in duration-200`,
|
|
759
|
+
onClick: () => setIsMobileNavbarOpen(false)
|
|
760
|
+
}
|
|
761
|
+
),
|
|
762
|
+
/* @__PURE__ */ jsxs7("div", { className: `${mobileMenuClass} fixed left-0 top-0 bottom-0 z-50 w-64 bg-white dark:bg-gray-800 shadow-2xl animate-in slide-in-from-left duration-300`, children: [
|
|
763
|
+
/* @__PURE__ */ jsxs7("div", { className: "p-4 border-b border-gray-200 dark:border-gray-700 flex items-center justify-between", children: [
|
|
764
|
+
navbarLogo ? /* @__PURE__ */ jsx38("div", { children: navbarLogo }) : navbarTitle ? /* @__PURE__ */ jsx38("span", { className: "text-xl font-bold text-gray-900 dark:text-gray-100", children: navbarTitle }) : null,
|
|
765
|
+
/* @__PURE__ */ jsx38(
|
|
766
|
+
"button",
|
|
767
|
+
{
|
|
768
|
+
className: "p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",
|
|
769
|
+
onClick: () => setIsMobileNavbarOpen(false),
|
|
770
|
+
"aria-label": "Close menu",
|
|
771
|
+
children: /* @__PURE__ */ jsx38("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx38("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
772
|
+
}
|
|
773
|
+
)
|
|
774
|
+
] }),
|
|
775
|
+
/* @__PURE__ */ jsx38("div", { className: "p-4 flex flex-col gap-4", children: navbar.content })
|
|
776
|
+
] })
|
|
777
|
+
] }),
|
|
778
|
+
/* @__PURE__ */ jsx38("main", { className: "flex-1 overflow-y-auto", children })
|
|
779
|
+
] });
|
|
780
|
+
}
|
|
726
781
|
if (navbar) {
|
|
727
782
|
const mobileHeaderClass = navbarBreakpoint === "sm" ? "sm:hidden" : navbarBreakpoint === "md" ? "md:hidden" : navbarBreakpoint === "lg" ? "lg:hidden" : "xl:hidden";
|
|
728
783
|
const desktopNavbarClass = navbarBreakpoint === "sm" ? "sm:block" : navbarBreakpoint === "md" ? "md:block" : navbarBreakpoint === "lg" ? "lg:block" : "xl:block";
|
|
@@ -925,21 +980,150 @@ var TextInput = forwardRef(
|
|
|
925
980
|
);
|
|
926
981
|
TextInput.displayName = "TextInput";
|
|
927
982
|
|
|
983
|
+
// src/components/NumberInput.tsx
|
|
984
|
+
import { useState as useState5, useRef as useRef2 } from "react";
|
|
985
|
+
import { jsx as jsx41, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
986
|
+
var sizeClasses5 = {
|
|
987
|
+
sm: "px-3 py-1.5 text-sm",
|
|
988
|
+
md: "px-4 py-2.5 text-base",
|
|
989
|
+
lg: "px-4 py-3 text-lg"
|
|
990
|
+
};
|
|
991
|
+
var NumberInput = ({
|
|
992
|
+
label,
|
|
993
|
+
error,
|
|
994
|
+
helperText,
|
|
995
|
+
value,
|
|
996
|
+
onChange,
|
|
997
|
+
min,
|
|
998
|
+
max,
|
|
999
|
+
step = 1,
|
|
1000
|
+
precision,
|
|
1001
|
+
disabled = false,
|
|
1002
|
+
hideControls = false,
|
|
1003
|
+
size = "md",
|
|
1004
|
+
fullWidth = false,
|
|
1005
|
+
placeholder,
|
|
1006
|
+
className = ""
|
|
1007
|
+
}) => {
|
|
1008
|
+
const { theme } = useTheme();
|
|
1009
|
+
const inputRef = useRef2(null);
|
|
1010
|
+
const [isFocused, setIsFocused] = useState5(false);
|
|
1011
|
+
const clampValue = (val) => {
|
|
1012
|
+
let clamped = val;
|
|
1013
|
+
if (min !== void 0 && clamped < min) clamped = min;
|
|
1014
|
+
if (max !== void 0 && clamped > max) clamped = max;
|
|
1015
|
+
if (precision !== void 0) {
|
|
1016
|
+
clamped = parseFloat(clamped.toFixed(precision));
|
|
1017
|
+
}
|
|
1018
|
+
return clamped;
|
|
1019
|
+
};
|
|
1020
|
+
const handleIncrement = () => {
|
|
1021
|
+
if (disabled) return;
|
|
1022
|
+
const currentValue = value ?? 0;
|
|
1023
|
+
const newValue = clampValue(currentValue + step);
|
|
1024
|
+
onChange?.(newValue);
|
|
1025
|
+
};
|
|
1026
|
+
const handleDecrement = () => {
|
|
1027
|
+
if (disabled) return;
|
|
1028
|
+
const currentValue = value ?? 0;
|
|
1029
|
+
const newValue = clampValue(currentValue - step);
|
|
1030
|
+
onChange?.(newValue);
|
|
1031
|
+
};
|
|
1032
|
+
const handleInputChange = (e) => {
|
|
1033
|
+
const inputValue = e.target.value;
|
|
1034
|
+
if (inputValue === "" || inputValue === "-") {
|
|
1035
|
+
onChange?.(void 0);
|
|
1036
|
+
return;
|
|
1037
|
+
}
|
|
1038
|
+
const numValue = parseFloat(inputValue);
|
|
1039
|
+
if (!isNaN(numValue)) {
|
|
1040
|
+
const clamped = clampValue(numValue);
|
|
1041
|
+
onChange?.(clamped);
|
|
1042
|
+
}
|
|
1043
|
+
};
|
|
1044
|
+
const handleKeyDown = (e) => {
|
|
1045
|
+
if (e.key === "ArrowUp") {
|
|
1046
|
+
e.preventDefault();
|
|
1047
|
+
handleIncrement();
|
|
1048
|
+
} else if (e.key === "ArrowDown") {
|
|
1049
|
+
e.preventDefault();
|
|
1050
|
+
handleDecrement();
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
const baseStyles = "w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500";
|
|
1054
|
+
const sizeStyle = sizeClasses5[size];
|
|
1055
|
+
const errorStyles = error ? "border-red-500 focus:ring-red-500 dark:border-red-500" : "";
|
|
1056
|
+
const disabledStyles = disabled ? "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900" : "";
|
|
1057
|
+
const widthStyle = fullWidth ? "w-full" : "";
|
|
1058
|
+
const paddingWithControls = !hideControls ? "pr-8" : "";
|
|
1059
|
+
const displayValue = value !== void 0 ? value.toString() : "";
|
|
1060
|
+
return /* @__PURE__ */ jsxs10("div", { className: `${widthStyle} ${className}`, children: [
|
|
1061
|
+
label && /* @__PURE__ */ jsx41("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
1062
|
+
/* @__PURE__ */ jsxs10("div", { className: "relative", children: [
|
|
1063
|
+
/* @__PURE__ */ jsx41(
|
|
1064
|
+
"input",
|
|
1065
|
+
{
|
|
1066
|
+
ref: inputRef,
|
|
1067
|
+
type: "number",
|
|
1068
|
+
value: displayValue,
|
|
1069
|
+
onChange: handleInputChange,
|
|
1070
|
+
onKeyDown: handleKeyDown,
|
|
1071
|
+
onFocus: () => setIsFocused(true),
|
|
1072
|
+
onBlur: () => setIsFocused(false),
|
|
1073
|
+
disabled,
|
|
1074
|
+
placeholder,
|
|
1075
|
+
min,
|
|
1076
|
+
max,
|
|
1077
|
+
step,
|
|
1078
|
+
className: `${baseStyles} ${sizeStyle} ${errorStyles} ${disabledStyles} ${paddingWithControls} [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none`.trim()
|
|
1079
|
+
}
|
|
1080
|
+
),
|
|
1081
|
+
!hideControls && /* @__PURE__ */ jsxs10("div", { className: "absolute right-1 top-1/2 -translate-y-1/2 flex flex-col", children: [
|
|
1082
|
+
/* @__PURE__ */ jsx41(
|
|
1083
|
+
"button",
|
|
1084
|
+
{
|
|
1085
|
+
type: "button",
|
|
1086
|
+
onClick: handleIncrement,
|
|
1087
|
+
disabled: disabled || max !== void 0 && value !== void 0 && value >= max,
|
|
1088
|
+
className: "px-2 py-0.5 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
1089
|
+
tabIndex: -1,
|
|
1090
|
+
children: /* @__PURE__ */ jsx41("svg", { className: "w-3 h-3 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx41("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 3, d: "M5 15l7-7 7 7" }) })
|
|
1091
|
+
}
|
|
1092
|
+
),
|
|
1093
|
+
/* @__PURE__ */ jsx41(
|
|
1094
|
+
"button",
|
|
1095
|
+
{
|
|
1096
|
+
type: "button",
|
|
1097
|
+
onClick: handleDecrement,
|
|
1098
|
+
disabled: disabled || min !== void 0 && value !== void 0 && value <= min,
|
|
1099
|
+
className: "px-2 py-0.5 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors disabled:opacity-30 disabled:cursor-not-allowed",
|
|
1100
|
+
tabIndex: -1,
|
|
1101
|
+
children: /* @__PURE__ */ jsx41("svg", { className: "w-3 h-3 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx41("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 3, d: "M19 9l-7 7-7-7" }) })
|
|
1102
|
+
}
|
|
1103
|
+
)
|
|
1104
|
+
] })
|
|
1105
|
+
] }),
|
|
1106
|
+
error && /* @__PURE__ */ jsx41("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
1107
|
+
helperText && !error && /* @__PURE__ */ jsx41("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText })
|
|
1108
|
+
] });
|
|
1109
|
+
};
|
|
1110
|
+
NumberInput.displayName = "NumberInput";
|
|
1111
|
+
|
|
928
1112
|
// src/components/ActionMenu.tsx
|
|
929
|
-
import { useState as
|
|
1113
|
+
import { useState as useState6, useRef as useRef3, useEffect as useEffect5 } from "react";
|
|
930
1114
|
import { createPortal } from "react-dom";
|
|
931
|
-
import { Fragment as Fragment6, jsx as
|
|
1115
|
+
import { Fragment as Fragment6, jsx as jsx42, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
932
1116
|
var ActionMenu = ({
|
|
933
1117
|
items,
|
|
934
1118
|
trigger,
|
|
935
1119
|
position = "right"
|
|
936
1120
|
}) => {
|
|
937
1121
|
const { themeName } = useTheme();
|
|
938
|
-
const [isOpen, setIsOpen] =
|
|
939
|
-
const [menuPosition, setMenuPosition] =
|
|
940
|
-
const [mounted, setMounted] =
|
|
941
|
-
const menuRef =
|
|
942
|
-
const triggerRef =
|
|
1122
|
+
const [isOpen, setIsOpen] = useState6(false);
|
|
1123
|
+
const [menuPosition, setMenuPosition] = useState6(null);
|
|
1124
|
+
const [mounted, setMounted] = useState6(false);
|
|
1125
|
+
const menuRef = useRef3(null);
|
|
1126
|
+
const triggerRef = useRef3(null);
|
|
943
1127
|
useEffect5(() => {
|
|
944
1128
|
setMounted(true);
|
|
945
1129
|
}, []);
|
|
@@ -973,17 +1157,17 @@ var ActionMenu = ({
|
|
|
973
1157
|
setIsOpen(false);
|
|
974
1158
|
}
|
|
975
1159
|
};
|
|
976
|
-
const defaultTrigger = /* @__PURE__ */
|
|
1160
|
+
const defaultTrigger = /* @__PURE__ */ jsx42(
|
|
977
1161
|
"button",
|
|
978
1162
|
{
|
|
979
1163
|
className: "p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors",
|
|
980
1164
|
"aria-label": "Open menu",
|
|
981
|
-
children: /* @__PURE__ */
|
|
1165
|
+
children: /* @__PURE__ */ jsx42("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx42("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z" }) })
|
|
982
1166
|
}
|
|
983
1167
|
);
|
|
984
1168
|
const menuBaseStyles = themeName === "minimalistic" ? "bg-black border-2 border-white" : "bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow-lg";
|
|
985
1169
|
const itemBaseStyles = themeName === "minimalistic" ? "text-white hover:bg-white hover:text-black transition-colors duration-200" : "text-gray-700 dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors";
|
|
986
|
-
const menu = isOpen && mounted && menuPosition ? /* @__PURE__ */
|
|
1170
|
+
const menu = isOpen && mounted && menuPosition ? /* @__PURE__ */ jsx42(
|
|
987
1171
|
"div",
|
|
988
1172
|
{
|
|
989
1173
|
ref: menuRef,
|
|
@@ -995,7 +1179,7 @@ var ActionMenu = ({
|
|
|
995
1179
|
},
|
|
996
1180
|
children: items.map((item, index) => {
|
|
997
1181
|
if (item.type === "divider") {
|
|
998
|
-
return /* @__PURE__ */
|
|
1182
|
+
return /* @__PURE__ */ jsx42(
|
|
999
1183
|
"div",
|
|
1000
1184
|
{
|
|
1001
1185
|
className: "my-1 border-t border-gray-200 dark:border-gray-700"
|
|
@@ -1003,15 +1187,15 @@ var ActionMenu = ({
|
|
|
1003
1187
|
index
|
|
1004
1188
|
);
|
|
1005
1189
|
}
|
|
1006
|
-
return /* @__PURE__ */
|
|
1190
|
+
return /* @__PURE__ */ jsxs11(
|
|
1007
1191
|
"button",
|
|
1008
1192
|
{
|
|
1009
1193
|
onClick: () => handleItemClick(item),
|
|
1010
1194
|
disabled: item.disabled,
|
|
1011
1195
|
className: `w-full text-left px-4 py-3 flex items-center gap-3 ${itemBaseStyles} ${item.disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"} ${item.variant === "danger" ? "text-red-600 dark:text-red-400 hover:bg-red-50 dark:hover:bg-red-900/20" : ""}`,
|
|
1012
1196
|
children: [
|
|
1013
|
-
item.icon && /* @__PURE__ */
|
|
1014
|
-
/* @__PURE__ */
|
|
1197
|
+
item.icon && /* @__PURE__ */ jsx42("span", { className: "flex-shrink-0", children: item.icon }),
|
|
1198
|
+
/* @__PURE__ */ jsx42("span", { className: "flex-1", children: item.label })
|
|
1015
1199
|
]
|
|
1016
1200
|
},
|
|
1017
1201
|
index
|
|
@@ -1019,14 +1203,14 @@ var ActionMenu = ({
|
|
|
1019
1203
|
})
|
|
1020
1204
|
}
|
|
1021
1205
|
) : null;
|
|
1022
|
-
return /* @__PURE__ */
|
|
1023
|
-
/* @__PURE__ */
|
|
1206
|
+
return /* @__PURE__ */ jsxs11(Fragment6, { children: [
|
|
1207
|
+
/* @__PURE__ */ jsx42("div", { className: "relative inline-block", ref: triggerRef, children: /* @__PURE__ */ jsx42("div", { onClick: () => setIsOpen(!isOpen), children: trigger || defaultTrigger }) }),
|
|
1024
1208
|
mounted && createPortal(menu, document.body)
|
|
1025
1209
|
] });
|
|
1026
1210
|
};
|
|
1027
1211
|
|
|
1028
1212
|
// src/components/Card.tsx
|
|
1029
|
-
import { jsx as
|
|
1213
|
+
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
1030
1214
|
var paddingClasses = {
|
|
1031
1215
|
none: "",
|
|
1032
1216
|
sm: "p-4",
|
|
@@ -1041,8 +1225,8 @@ var Card = ({
|
|
|
1041
1225
|
}) => {
|
|
1042
1226
|
const { theme } = useTheme();
|
|
1043
1227
|
const paddingClass = paddingClasses[padding];
|
|
1044
|
-
const hoverClass = hover ? "hover:shadow-
|
|
1045
|
-
return /* @__PURE__ */
|
|
1228
|
+
const hoverClass = hover ? "hover:shadow-xl hover:scale-[1.02] hover:border-blue-400 dark:hover:border-blue-500 cursor-pointer transition-all duration-200 ease-in-out" : "";
|
|
1229
|
+
return /* @__PURE__ */ jsx43(
|
|
1046
1230
|
"div",
|
|
1047
1231
|
{
|
|
1048
1232
|
className: `bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 ${paddingClass} ${hoverClass} ${className}`,
|
|
@@ -1052,7 +1236,7 @@ var Card = ({
|
|
|
1052
1236
|
};
|
|
1053
1237
|
|
|
1054
1238
|
// src/components/Alert.tsx
|
|
1055
|
-
import { jsx as
|
|
1239
|
+
import { jsx as jsx44, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1056
1240
|
var variantStyles = {
|
|
1057
1241
|
info: "bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800 text-blue-900 dark:text-blue-100",
|
|
1058
1242
|
success: "bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800 text-green-900 dark:text-green-100",
|
|
@@ -1075,24 +1259,24 @@ var Alert = ({
|
|
|
1075
1259
|
const { theme } = useTheme();
|
|
1076
1260
|
const variantClass = variantStyles[variant];
|
|
1077
1261
|
const iconClass = iconStyles[variant];
|
|
1078
|
-
return /* @__PURE__ */
|
|
1079
|
-
/* @__PURE__ */
|
|
1080
|
-
variant === "info" && /* @__PURE__ */
|
|
1081
|
-
variant === "success" && /* @__PURE__ */
|
|
1082
|
-
variant === "warning" && /* @__PURE__ */
|
|
1083
|
-
variant === "error" && /* @__PURE__ */
|
|
1262
|
+
return /* @__PURE__ */ jsx44("div", { className: `rounded-lg border p-4 ${variantClass} ${className}`, role: "alert", children: /* @__PURE__ */ jsxs12("div", { className: "flex items-start gap-3", children: [
|
|
1263
|
+
/* @__PURE__ */ jsxs12("div", { className: `flex-shrink-0 ${iconClass}`, children: [
|
|
1264
|
+
variant === "info" && /* @__PURE__ */ jsx44("svg", { className: "w-5 h-5", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx44("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }),
|
|
1265
|
+
variant === "success" && /* @__PURE__ */ jsx44("svg", { className: "w-5 h-5", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx44("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z", clipRule: "evenodd" }) }),
|
|
1266
|
+
variant === "warning" && /* @__PURE__ */ jsx44("svg", { className: "w-5 h-5", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx44("path", { fillRule: "evenodd", d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }),
|
|
1267
|
+
variant === "error" && /* @__PURE__ */ jsx44("svg", { className: "w-5 h-5", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx44("path", { fillRule: "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z", clipRule: "evenodd" }) })
|
|
1084
1268
|
] }),
|
|
1085
|
-
/* @__PURE__ */
|
|
1086
|
-
title && /* @__PURE__ */
|
|
1087
|
-
/* @__PURE__ */
|
|
1269
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex-1", children: [
|
|
1270
|
+
title && /* @__PURE__ */ jsx44("h3", { className: "font-semibold mb-1", children: title }),
|
|
1271
|
+
/* @__PURE__ */ jsx44("div", { className: "text-sm", children })
|
|
1088
1272
|
] }),
|
|
1089
|
-
onClose && /* @__PURE__ */
|
|
1273
|
+
onClose && /* @__PURE__ */ jsx44(
|
|
1090
1274
|
"button",
|
|
1091
1275
|
{
|
|
1092
1276
|
onClick: onClose,
|
|
1093
1277
|
className: `flex-shrink-0 ${iconClass} hover:opacity-70 transition-opacity`,
|
|
1094
1278
|
"aria-label": "Close alert",
|
|
1095
|
-
children: /* @__PURE__ */
|
|
1279
|
+
children: /* @__PURE__ */ jsx44("svg", { className: "w-5 h-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx44("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })
|
|
1096
1280
|
}
|
|
1097
1281
|
)
|
|
1098
1282
|
] }) });
|
|
@@ -1100,13 +1284,13 @@ var Alert = ({
|
|
|
1100
1284
|
|
|
1101
1285
|
// src/components/Checkbox.tsx
|
|
1102
1286
|
import { forwardRef as forwardRef2 } from "react";
|
|
1103
|
-
import { jsx as
|
|
1287
|
+
import { jsx as jsx45, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1104
1288
|
var Checkbox = forwardRef2(
|
|
1105
1289
|
({ label, error, className = "", disabled, ...props }, ref) => {
|
|
1106
1290
|
const { theme } = useTheme();
|
|
1107
|
-
return /* @__PURE__ */
|
|
1108
|
-
/* @__PURE__ */
|
|
1109
|
-
/* @__PURE__ */
|
|
1291
|
+
return /* @__PURE__ */ jsxs13("div", { className, children: [
|
|
1292
|
+
/* @__PURE__ */ jsxs13("label", { className: "flex items-center gap-2 cursor-pointer group", children: [
|
|
1293
|
+
/* @__PURE__ */ jsx45(
|
|
1110
1294
|
"input",
|
|
1111
1295
|
{
|
|
1112
1296
|
ref,
|
|
@@ -1116,9 +1300,9 @@ var Checkbox = forwardRef2(
|
|
|
1116
1300
|
...props
|
|
1117
1301
|
}
|
|
1118
1302
|
),
|
|
1119
|
-
label && /* @__PURE__ */
|
|
1303
|
+
label && /* @__PURE__ */ jsx45("span", { className: `text-sm text-gray-700 dark:text-gray-300 ${disabled ? "opacity-50 cursor-not-allowed" : "group-hover:text-gray-900 dark:group-hover:text-gray-100"}`, children: label })
|
|
1120
1304
|
] }),
|
|
1121
|
-
error && /* @__PURE__ */
|
|
1305
|
+
error && /* @__PURE__ */ jsx45("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error })
|
|
1122
1306
|
] });
|
|
1123
1307
|
}
|
|
1124
1308
|
);
|
|
@@ -1126,7 +1310,7 @@ Checkbox.displayName = "Checkbox";
|
|
|
1126
1310
|
|
|
1127
1311
|
// src/components/Toggle.tsx
|
|
1128
1312
|
import { forwardRef as forwardRef3 } from "react";
|
|
1129
|
-
import { jsx as
|
|
1313
|
+
import { jsx as jsx46, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1130
1314
|
var Toggle = forwardRef3(
|
|
1131
1315
|
({ label, size = "md", className = "", disabled, checked, ...props }, ref) => {
|
|
1132
1316
|
const { theme } = useTheme();
|
|
@@ -1145,9 +1329,9 @@ var Toggle = forwardRef3(
|
|
|
1145
1329
|
}
|
|
1146
1330
|
};
|
|
1147
1331
|
const currentSize = toggleClasses[size];
|
|
1148
|
-
return /* @__PURE__ */
|
|
1149
|
-
/* @__PURE__ */
|
|
1150
|
-
/* @__PURE__ */
|
|
1332
|
+
return /* @__PURE__ */ jsxs14("label", { className: `inline-flex items-center gap-3 cursor-pointer ${disabled ? "opacity-50 cursor-not-allowed" : ""} ${className}`, children: [
|
|
1333
|
+
/* @__PURE__ */ jsxs14("div", { className: "relative", children: [
|
|
1334
|
+
/* @__PURE__ */ jsx46(
|
|
1151
1335
|
"input",
|
|
1152
1336
|
{
|
|
1153
1337
|
ref,
|
|
@@ -1158,27 +1342,27 @@ var Toggle = forwardRef3(
|
|
|
1158
1342
|
...props
|
|
1159
1343
|
}
|
|
1160
1344
|
),
|
|
1161
|
-
/* @__PURE__ */
|
|
1345
|
+
/* @__PURE__ */ jsx46(
|
|
1162
1346
|
"div",
|
|
1163
1347
|
{
|
|
1164
1348
|
className: `${currentSize.switch} bg-gray-300 dark:bg-gray-700 peer-focus:ring-2 peer-focus:ring-blue-500 rounded-full peer peer-checked:bg-blue-600 dark:peer-checked:bg-blue-500 transition-colors`
|
|
1165
1349
|
}
|
|
1166
1350
|
),
|
|
1167
|
-
/* @__PURE__ */
|
|
1351
|
+
/* @__PURE__ */ jsx46(
|
|
1168
1352
|
"div",
|
|
1169
1353
|
{
|
|
1170
1354
|
className: `${currentSize.thumb} bg-white rounded-full shadow-md absolute top-0.5 left-0.5 transition-transform`
|
|
1171
1355
|
}
|
|
1172
1356
|
)
|
|
1173
1357
|
] }),
|
|
1174
|
-
label && /* @__PURE__ */
|
|
1358
|
+
label && /* @__PURE__ */ jsx46("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: label })
|
|
1175
1359
|
] });
|
|
1176
1360
|
}
|
|
1177
1361
|
);
|
|
1178
1362
|
Toggle.displayName = "Toggle";
|
|
1179
1363
|
|
|
1180
1364
|
// src/components/Badge.tsx
|
|
1181
|
-
import { jsx as
|
|
1365
|
+
import { jsx as jsx47 } from "react/jsx-runtime";
|
|
1182
1366
|
var variantStyles2 = {
|
|
1183
1367
|
default: "bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200",
|
|
1184
1368
|
primary: "bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-200",
|
|
@@ -1201,12 +1385,12 @@ var Badge = ({
|
|
|
1201
1385
|
const { theme } = useTheme();
|
|
1202
1386
|
const variantClass = variantStyles2[variant];
|
|
1203
1387
|
const sizeClass = sizeStyles[size];
|
|
1204
|
-
return /* @__PURE__ */
|
|
1388
|
+
return /* @__PURE__ */ jsx47("span", { className: `inline-flex items-center font-medium rounded-full ${variantClass} ${sizeClass} ${className}`, children });
|
|
1205
1389
|
};
|
|
1206
1390
|
|
|
1207
1391
|
// src/components/Spinner.tsx
|
|
1208
|
-
import { jsx as
|
|
1209
|
-
var
|
|
1392
|
+
import { jsx as jsx48 } from "react/jsx-runtime";
|
|
1393
|
+
var sizeClasses6 = {
|
|
1210
1394
|
sm: "w-4 h-4 border-2",
|
|
1211
1395
|
md: "w-8 h-8 border-2",
|
|
1212
1396
|
lg: "w-12 h-12 border-3",
|
|
@@ -1223,22 +1407,22 @@ var Spinner = ({
|
|
|
1223
1407
|
className = ""
|
|
1224
1408
|
}) => {
|
|
1225
1409
|
const { theme } = useTheme();
|
|
1226
|
-
const sizeClass =
|
|
1410
|
+
const sizeClass = sizeClasses6[size];
|
|
1227
1411
|
const colorClass = colorClasses[color];
|
|
1228
|
-
return /* @__PURE__ */
|
|
1412
|
+
return /* @__PURE__ */ jsx48(
|
|
1229
1413
|
"div",
|
|
1230
1414
|
{
|
|
1231
1415
|
className: `inline-block rounded-full animate-spin ${sizeClass} ${colorClass} ${className}`,
|
|
1232
1416
|
role: "status",
|
|
1233
1417
|
"aria-label": "Loading",
|
|
1234
|
-
children: /* @__PURE__ */
|
|
1418
|
+
children: /* @__PURE__ */ jsx48("span", { className: "sr-only", children: "Loading..." })
|
|
1235
1419
|
}
|
|
1236
1420
|
);
|
|
1237
1421
|
};
|
|
1238
1422
|
|
|
1239
1423
|
// src/components/Tabs.tsx
|
|
1240
|
-
import { useState as
|
|
1241
|
-
import { jsx as
|
|
1424
|
+
import { useState as useState7 } from "react";
|
|
1425
|
+
import { jsx as jsx49, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1242
1426
|
var Tabs = ({
|
|
1243
1427
|
tabs,
|
|
1244
1428
|
defaultIndex = 0,
|
|
@@ -1246,14 +1430,14 @@ var Tabs = ({
|
|
|
1246
1430
|
className = ""
|
|
1247
1431
|
}) => {
|
|
1248
1432
|
const { theme } = useTheme();
|
|
1249
|
-
const [activeIndex, setActiveIndex] =
|
|
1433
|
+
const [activeIndex, setActiveIndex] = useState7(defaultIndex);
|
|
1250
1434
|
const handleTabClick = (index) => {
|
|
1251
1435
|
if (tabs[index].disabled) return;
|
|
1252
1436
|
setActiveIndex(index);
|
|
1253
1437
|
onChange?.(index);
|
|
1254
1438
|
};
|
|
1255
|
-
return /* @__PURE__ */
|
|
1256
|
-
/* @__PURE__ */
|
|
1439
|
+
return /* @__PURE__ */ jsxs15("div", { className, children: [
|
|
1440
|
+
/* @__PURE__ */ jsx49("div", { className: "border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx49("nav", { className: "flex gap-8 px-6", "aria-label": "Tabs", children: tabs.map((tab, index) => /* @__PURE__ */ jsx49(
|
|
1257
1441
|
"button",
|
|
1258
1442
|
{
|
|
1259
1443
|
onClick: () => handleTabClick(index),
|
|
@@ -1264,12 +1448,12 @@ var Tabs = ({
|
|
|
1264
1448
|
},
|
|
1265
1449
|
index
|
|
1266
1450
|
)) }) }),
|
|
1267
|
-
/* @__PURE__ */
|
|
1451
|
+
/* @__PURE__ */ jsx49("div", { children: tabs[activeIndex]?.content })
|
|
1268
1452
|
] });
|
|
1269
1453
|
};
|
|
1270
1454
|
|
|
1271
1455
|
// src/components/Table.tsx
|
|
1272
|
-
import { jsx as
|
|
1456
|
+
import { jsx as jsx50, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1273
1457
|
function Table({
|
|
1274
1458
|
columns,
|
|
1275
1459
|
data,
|
|
@@ -1279,11 +1463,11 @@ function Table({
|
|
|
1279
1463
|
className = ""
|
|
1280
1464
|
}) {
|
|
1281
1465
|
const { theme } = useTheme();
|
|
1282
|
-
return /* @__PURE__ */
|
|
1283
|
-
/* @__PURE__ */
|
|
1284
|
-
/* @__PURE__ */
|
|
1466
|
+
return /* @__PURE__ */ jsxs16("div", { className: `overflow-x-auto ${className}`, children: [
|
|
1467
|
+
/* @__PURE__ */ jsxs16("table", { className: "w-full text-left", children: [
|
|
1468
|
+
/* @__PURE__ */ jsx50("thead", { className: "bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx50("tr", { children: columns.map((column, colIndex) => {
|
|
1285
1469
|
const isLast = colIndex === columns.length - 1;
|
|
1286
|
-
return /* @__PURE__ */
|
|
1470
|
+
return /* @__PURE__ */ jsx50(
|
|
1287
1471
|
"th",
|
|
1288
1472
|
{
|
|
1289
1473
|
className: isLast ? "px-6 py-3 text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider relative" : "px-6 py-3 text-xs font-medium text-gray-700 dark:text-gray-300 uppercase tracking-wider",
|
|
@@ -1293,18 +1477,18 @@ function Table({
|
|
|
1293
1477
|
column.key
|
|
1294
1478
|
);
|
|
1295
1479
|
}) }) }),
|
|
1296
|
-
/* @__PURE__ */
|
|
1480
|
+
/* @__PURE__ */ jsx50("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children: data.map((row, rowIndex) => {
|
|
1297
1481
|
const rowClasses = [
|
|
1298
1482
|
striped && rowIndex % 2 === 1 ? "bg-gray-50 dark:bg-gray-800/50" : "",
|
|
1299
1483
|
hoverable ? "hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors" : ""
|
|
1300
1484
|
].filter(Boolean).join(" ");
|
|
1301
|
-
return /* @__PURE__ */
|
|
1485
|
+
return /* @__PURE__ */ jsx50(
|
|
1302
1486
|
"tr",
|
|
1303
1487
|
{
|
|
1304
1488
|
className: rowClasses,
|
|
1305
1489
|
children: columns.map((column, colIndex) => {
|
|
1306
1490
|
const isLast = colIndex === columns.length - 1;
|
|
1307
|
-
return /* @__PURE__ */
|
|
1491
|
+
return /* @__PURE__ */ jsx50(
|
|
1308
1492
|
"td",
|
|
1309
1493
|
{
|
|
1310
1494
|
className: isLast ? "px-6 py-4 text-sm text-gray-900 dark:text-gray-100 overflow-visible" : "px-6 py-4 text-sm text-gray-900 dark:text-gray-100",
|
|
@@ -1318,12 +1502,12 @@ function Table({
|
|
|
1318
1502
|
);
|
|
1319
1503
|
}) })
|
|
1320
1504
|
] }),
|
|
1321
|
-
data.length === 0 && /* @__PURE__ */
|
|
1505
|
+
data.length === 0 && /* @__PURE__ */ jsx50("div", { className: "text-center py-8 text-gray-500 dark:text-gray-400", children: "No data available" })
|
|
1322
1506
|
] });
|
|
1323
1507
|
}
|
|
1324
1508
|
|
|
1325
1509
|
// src/components/Pagination.tsx
|
|
1326
|
-
import { jsx as
|
|
1510
|
+
import { jsx as jsx51, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1327
1511
|
var Pagination = ({
|
|
1328
1512
|
currentPage,
|
|
1329
1513
|
totalPages,
|
|
@@ -1364,8 +1548,8 @@ var Pagination = ({
|
|
|
1364
1548
|
return range(1, totalPages);
|
|
1365
1549
|
};
|
|
1366
1550
|
const pages = paginationRange();
|
|
1367
|
-
return /* @__PURE__ */
|
|
1368
|
-
/* @__PURE__ */
|
|
1551
|
+
return /* @__PURE__ */ jsxs17("nav", { className: `flex items-center gap-1 ${className}`, "aria-label": "Pagination", children: [
|
|
1552
|
+
/* @__PURE__ */ jsx51(
|
|
1369
1553
|
"button",
|
|
1370
1554
|
{
|
|
1371
1555
|
onClick: () => onPageChange(currentPage - 1),
|
|
@@ -1377,7 +1561,7 @@ var Pagination = ({
|
|
|
1377
1561
|
),
|
|
1378
1562
|
pages.map((page, index) => {
|
|
1379
1563
|
if (page === "...") {
|
|
1380
|
-
return /* @__PURE__ */
|
|
1564
|
+
return /* @__PURE__ */ jsx51(
|
|
1381
1565
|
"span",
|
|
1382
1566
|
{
|
|
1383
1567
|
className: "px-3 py-2 text-gray-700 dark:text-gray-300",
|
|
@@ -1386,7 +1570,7 @@ var Pagination = ({
|
|
|
1386
1570
|
`dots-${index}`
|
|
1387
1571
|
);
|
|
1388
1572
|
}
|
|
1389
|
-
return /* @__PURE__ */
|
|
1573
|
+
return /* @__PURE__ */ jsx51(
|
|
1390
1574
|
"button",
|
|
1391
1575
|
{
|
|
1392
1576
|
onClick: () => onPageChange(page),
|
|
@@ -1398,7 +1582,7 @@ var Pagination = ({
|
|
|
1398
1582
|
page
|
|
1399
1583
|
);
|
|
1400
1584
|
}),
|
|
1401
|
-
/* @__PURE__ */
|
|
1585
|
+
/* @__PURE__ */ jsx51(
|
|
1402
1586
|
"button",
|
|
1403
1587
|
{
|
|
1404
1588
|
onClick: () => onPageChange(currentPage + 1),
|
|
@@ -1412,65 +1596,227 @@ var Pagination = ({
|
|
|
1412
1596
|
};
|
|
1413
1597
|
|
|
1414
1598
|
// src/components/DatePicker.tsx
|
|
1415
|
-
import {
|
|
1416
|
-
import {
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1599
|
+
import { useState as useState8, useRef as useRef4, useEffect as useEffect6 } from "react";
|
|
1600
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1601
|
+
import { jsx as jsx52, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1602
|
+
var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1603
|
+
var MONTHS = [
|
|
1604
|
+
"January",
|
|
1605
|
+
"February",
|
|
1606
|
+
"March",
|
|
1607
|
+
"April",
|
|
1608
|
+
"May",
|
|
1609
|
+
"June",
|
|
1610
|
+
"July",
|
|
1611
|
+
"August",
|
|
1612
|
+
"September",
|
|
1613
|
+
"October",
|
|
1614
|
+
"November",
|
|
1615
|
+
"December"
|
|
1616
|
+
];
|
|
1617
|
+
var DatePicker = ({
|
|
1618
|
+
label,
|
|
1619
|
+
error,
|
|
1620
|
+
helperText,
|
|
1621
|
+
value,
|
|
1622
|
+
onChange,
|
|
1623
|
+
minDate,
|
|
1624
|
+
maxDate,
|
|
1625
|
+
disabled,
|
|
1626
|
+
className = "",
|
|
1627
|
+
placeholder = "Select date..."
|
|
1628
|
+
}) => {
|
|
1629
|
+
const { theme } = useTheme();
|
|
1630
|
+
const [isOpen, setIsOpen] = useState8(false);
|
|
1631
|
+
const [viewDate, setViewDate] = useState8(value || /* @__PURE__ */ new Date());
|
|
1632
|
+
const [mounted, setMounted] = useState8(false);
|
|
1633
|
+
const [calendarPosition, setCalendarPosition] = useState8(null);
|
|
1634
|
+
const inputRef = useRef4(null);
|
|
1635
|
+
const calendarRef = useRef4(null);
|
|
1636
|
+
useEffect6(() => {
|
|
1637
|
+
setMounted(true);
|
|
1638
|
+
}, []);
|
|
1639
|
+
useEffect6(() => {
|
|
1640
|
+
const handleClickOutside = (event) => {
|
|
1641
|
+
if (calendarRef.current && !calendarRef.current.contains(event.target) && inputRef.current && !inputRef.current.contains(event.target)) {
|
|
1642
|
+
setIsOpen(false);
|
|
1643
|
+
}
|
|
1644
|
+
};
|
|
1645
|
+
if (isOpen) {
|
|
1646
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1647
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1648
|
+
}
|
|
1649
|
+
}, [isOpen]);
|
|
1650
|
+
useEffect6(() => {
|
|
1651
|
+
if (isOpen && inputRef.current) {
|
|
1652
|
+
const rect = inputRef.current.getBoundingClientRect();
|
|
1653
|
+
setCalendarPosition({
|
|
1654
|
+
top: rect.bottom + 8,
|
|
1655
|
+
left: rect.left
|
|
1656
|
+
});
|
|
1657
|
+
} else {
|
|
1658
|
+
setCalendarPosition(null);
|
|
1659
|
+
}
|
|
1660
|
+
}, [isOpen]);
|
|
1661
|
+
const year = viewDate.getFullYear();
|
|
1662
|
+
const month = viewDate.getMonth();
|
|
1663
|
+
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
1664
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
1665
|
+
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
1666
|
+
const calendarDays = [];
|
|
1667
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
1668
|
+
calendarDays.push(new Date(year, month - 1, daysInPrevMonth - i));
|
|
1438
1669
|
}
|
|
1439
|
-
)
|
|
1670
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
1671
|
+
calendarDays.push(new Date(year, month, i));
|
|
1672
|
+
}
|
|
1673
|
+
const remainingDays = 42 - calendarDays.length;
|
|
1674
|
+
for (let i = 1; i <= remainingDays; i++) {
|
|
1675
|
+
calendarDays.push(new Date(year, month + 1, i));
|
|
1676
|
+
}
|
|
1677
|
+
const isSameDay = (date1, date2) => {
|
|
1678
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1679
|
+
};
|
|
1680
|
+
const isToday = (date) => {
|
|
1681
|
+
return isSameDay(date, /* @__PURE__ */ new Date());
|
|
1682
|
+
};
|
|
1683
|
+
const isSelected = (date) => {
|
|
1684
|
+
return value && isSameDay(date, value);
|
|
1685
|
+
};
|
|
1686
|
+
const isCurrentMonth = (date) => {
|
|
1687
|
+
return date.getMonth() === month;
|
|
1688
|
+
};
|
|
1689
|
+
const isDisabled = (date) => {
|
|
1690
|
+
if (minDate && date < minDate) return true;
|
|
1691
|
+
if (maxDate && date > maxDate) return true;
|
|
1692
|
+
return false;
|
|
1693
|
+
};
|
|
1694
|
+
const handleDateClick = (date) => {
|
|
1695
|
+
if (isDisabled(date)) return;
|
|
1696
|
+
onChange?.(date);
|
|
1697
|
+
setIsOpen(false);
|
|
1698
|
+
};
|
|
1699
|
+
const handlePrevMonth = () => {
|
|
1700
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
1701
|
+
};
|
|
1702
|
+
const handleNextMonth = () => {
|
|
1703
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
1704
|
+
};
|
|
1705
|
+
const handleToday = () => {
|
|
1706
|
+
const today = /* @__PURE__ */ new Date();
|
|
1707
|
+
setViewDate(today);
|
|
1708
|
+
onChange?.(today);
|
|
1709
|
+
setIsOpen(false);
|
|
1710
|
+
};
|
|
1711
|
+
const formatDate = (date) => {
|
|
1712
|
+
if (!date) return "";
|
|
1713
|
+
return date.toLocaleDateString("en-US", {
|
|
1714
|
+
month: "short",
|
|
1715
|
+
day: "numeric",
|
|
1716
|
+
year: "numeric"
|
|
1717
|
+
});
|
|
1718
|
+
};
|
|
1719
|
+
const baseStyles = "w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 px-4 py-2.5 text-base transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500 cursor-pointer";
|
|
1720
|
+
const errorStyles = error ? "border-red-500 focus:ring-red-500 dark:border-red-500" : "";
|
|
1721
|
+
const disabledStyles = disabled ? "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900" : "";
|
|
1722
|
+
const calendar = isOpen && mounted && calendarPosition ? /* @__PURE__ */ jsxs18(
|
|
1723
|
+
"div",
|
|
1724
|
+
{
|
|
1725
|
+
ref: calendarRef,
|
|
1726
|
+
className: "fixed z-[9999] bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4",
|
|
1727
|
+
style: {
|
|
1728
|
+
top: `${calendarPosition.top}px`,
|
|
1729
|
+
left: `${calendarPosition.left}px`,
|
|
1730
|
+
minWidth: "320px"
|
|
1731
|
+
},
|
|
1732
|
+
children: [
|
|
1733
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between mb-4", children: [
|
|
1734
|
+
/* @__PURE__ */ jsx52(
|
|
1735
|
+
"button",
|
|
1736
|
+
{
|
|
1737
|
+
onClick: handlePrevMonth,
|
|
1738
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
1739
|
+
"aria-label": "Previous month",
|
|
1740
|
+
children: /* @__PURE__ */ jsx52("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx52("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
1741
|
+
}
|
|
1742
|
+
),
|
|
1743
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2", children: [
|
|
1744
|
+
/* @__PURE__ */ jsxs18("h2", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: [
|
|
1745
|
+
MONTHS[month],
|
|
1746
|
+
" ",
|
|
1747
|
+
year
|
|
1748
|
+
] }),
|
|
1749
|
+
/* @__PURE__ */ jsx52(
|
|
1750
|
+
"button",
|
|
1751
|
+
{
|
|
1752
|
+
onClick: handleToday,
|
|
1753
|
+
className: "px-2 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors",
|
|
1754
|
+
children: "Today"
|
|
1755
|
+
}
|
|
1756
|
+
)
|
|
1757
|
+
] }),
|
|
1758
|
+
/* @__PURE__ */ jsx52(
|
|
1759
|
+
"button",
|
|
1760
|
+
{
|
|
1761
|
+
onClick: handleNextMonth,
|
|
1762
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
1763
|
+
"aria-label": "Next month",
|
|
1764
|
+
children: /* @__PURE__ */ jsx52("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx52("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
1765
|
+
}
|
|
1766
|
+
)
|
|
1767
|
+
] }),
|
|
1768
|
+
/* @__PURE__ */ jsx52("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS.map((day) => /* @__PURE__ */ jsx52("div", { className: "text-center text-xs font-semibold text-gray-600 dark:text-gray-400 py-1", children: day }, day)) }),
|
|
1769
|
+
/* @__PURE__ */ jsx52("div", { className: "grid grid-cols-7 gap-1", children: calendarDays.map((date, index) => {
|
|
1770
|
+
const isCurrentMonthDay = isCurrentMonth(date);
|
|
1771
|
+
const isTodayDay = isToday(date);
|
|
1772
|
+
const isSelectedDay = isSelected(date);
|
|
1773
|
+
const isDisabledDay = isDisabled(date);
|
|
1774
|
+
return /* @__PURE__ */ jsx52(
|
|
1775
|
+
"button",
|
|
1776
|
+
{
|
|
1777
|
+
onClick: () => handleDateClick(date),
|
|
1778
|
+
disabled: isDisabledDay,
|
|
1779
|
+
className: `
|
|
1780
|
+
aspect-square p-1 rounded-lg text-sm font-medium transition-all
|
|
1781
|
+
${!isCurrentMonthDay ? "text-gray-400 dark:text-gray-600" : "text-gray-900 dark:text-gray-100"}
|
|
1782
|
+
${isTodayDay && !isSelectedDay ? "bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-bold" : ""}
|
|
1783
|
+
${isSelectedDay ? "bg-blue-600 text-white hover:bg-blue-700" : ""}
|
|
1784
|
+
${!isSelectedDay && !isDisabledDay ? "hover:bg-gray-100 dark:hover:bg-gray-700" : ""}
|
|
1785
|
+
${isDisabledDay ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}
|
|
1786
|
+
`,
|
|
1787
|
+
children: date.getDate()
|
|
1788
|
+
},
|
|
1789
|
+
index
|
|
1790
|
+
);
|
|
1791
|
+
}) })
|
|
1792
|
+
]
|
|
1793
|
+
}
|
|
1794
|
+
) : null;
|
|
1795
|
+
return /* @__PURE__ */ jsxs18("div", { className, children: [
|
|
1796
|
+
label && /* @__PURE__ */ jsx52("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
1797
|
+
/* @__PURE__ */ jsxs18(
|
|
1798
|
+
"div",
|
|
1799
|
+
{
|
|
1800
|
+
ref: inputRef,
|
|
1801
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1802
|
+
className: `${baseStyles} ${errorStyles} ${disabledStyles} flex items-center justify-between`.trim(),
|
|
1803
|
+
children: [
|
|
1804
|
+
/* @__PURE__ */ jsx52("span", { className: !value ? "text-gray-500 dark:text-gray-400" : "", children: value ? formatDate(value) : placeholder }),
|
|
1805
|
+
/* @__PURE__ */ jsx52("svg", { className: "w-5 h-5 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx52("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) })
|
|
1806
|
+
]
|
|
1807
|
+
}
|
|
1808
|
+
),
|
|
1809
|
+
error && /* @__PURE__ */ jsx52("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
1810
|
+
helperText && !error && /* @__PURE__ */ jsx52("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText }),
|
|
1811
|
+
mounted && createPortal2(calendar, document.body)
|
|
1812
|
+
] });
|
|
1813
|
+
};
|
|
1440
1814
|
DatePicker.displayName = "DatePicker";
|
|
1441
1815
|
|
|
1442
1816
|
// src/components/TimePicker.tsx
|
|
1443
|
-
import { forwardRef as
|
|
1444
|
-
import { jsx as jsx52, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1445
|
-
var TimePicker = forwardRef5(
|
|
1446
|
-
({ label, error, helperText, className = "", disabled, ...props }, ref) => {
|
|
1447
|
-
const { theme } = useTheme();
|
|
1448
|
-
const baseStyles = "w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 px-4 py-2.5 text-base transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500";
|
|
1449
|
-
const errorStyles = error ? "border-red-500 focus:ring-red-500 dark:border-red-500" : "";
|
|
1450
|
-
const disabledStyles = disabled ? "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900" : "";
|
|
1451
|
-
return /* @__PURE__ */ jsxs18("div", { className, children: [
|
|
1452
|
-
label && /* @__PURE__ */ jsx52("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
1453
|
-
/* @__PURE__ */ jsx52(
|
|
1454
|
-
"input",
|
|
1455
|
-
{
|
|
1456
|
-
ref,
|
|
1457
|
-
type: "time",
|
|
1458
|
-
disabled,
|
|
1459
|
-
className: `${baseStyles} ${errorStyles} ${disabledStyles}`.trim(),
|
|
1460
|
-
...props
|
|
1461
|
-
}
|
|
1462
|
-
),
|
|
1463
|
-
error && /* @__PURE__ */ jsx52("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
1464
|
-
helperText && !error && /* @__PURE__ */ jsx52("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText })
|
|
1465
|
-
] });
|
|
1466
|
-
}
|
|
1467
|
-
);
|
|
1468
|
-
TimePicker.displayName = "TimePicker";
|
|
1469
|
-
|
|
1470
|
-
// src/components/DateTimePicker.tsx
|
|
1471
|
-
import { forwardRef as forwardRef6 } from "react";
|
|
1817
|
+
import { forwardRef as forwardRef4 } from "react";
|
|
1472
1818
|
import { jsx as jsx53, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1473
|
-
var
|
|
1819
|
+
var TimePicker = forwardRef4(
|
|
1474
1820
|
({ label, error, helperText, className = "", disabled, ...props }, ref) => {
|
|
1475
1821
|
const { theme } = useTheme();
|
|
1476
1822
|
const baseStyles = "w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 px-4 py-2.5 text-base transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500";
|
|
@@ -1482,7 +1828,7 @@ var DateTimePicker = forwardRef6(
|
|
|
1482
1828
|
"input",
|
|
1483
1829
|
{
|
|
1484
1830
|
ref,
|
|
1485
|
-
type: "
|
|
1831
|
+
type: "time",
|
|
1486
1832
|
disabled,
|
|
1487
1833
|
className: `${baseStyles} ${errorStyles} ${disabledStyles}`.trim(),
|
|
1488
1834
|
...props
|
|
@@ -1493,11 +1839,506 @@ var DateTimePicker = forwardRef6(
|
|
|
1493
1839
|
] });
|
|
1494
1840
|
}
|
|
1495
1841
|
);
|
|
1842
|
+
TimePicker.displayName = "TimePicker";
|
|
1843
|
+
|
|
1844
|
+
// src/components/DateTimePicker.tsx
|
|
1845
|
+
import { useState as useState9, useRef as useRef5, useEffect as useEffect7 } from "react";
|
|
1846
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
1847
|
+
import { jsx as jsx54, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1848
|
+
var DAYS2 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1849
|
+
var MONTHS2 = [
|
|
1850
|
+
"January",
|
|
1851
|
+
"February",
|
|
1852
|
+
"March",
|
|
1853
|
+
"April",
|
|
1854
|
+
"May",
|
|
1855
|
+
"June",
|
|
1856
|
+
"July",
|
|
1857
|
+
"August",
|
|
1858
|
+
"September",
|
|
1859
|
+
"October",
|
|
1860
|
+
"November",
|
|
1861
|
+
"December"
|
|
1862
|
+
];
|
|
1863
|
+
var DateTimePicker = ({
|
|
1864
|
+
label,
|
|
1865
|
+
error,
|
|
1866
|
+
helperText,
|
|
1867
|
+
value,
|
|
1868
|
+
onChange,
|
|
1869
|
+
minDate,
|
|
1870
|
+
maxDate,
|
|
1871
|
+
disabled,
|
|
1872
|
+
className = "",
|
|
1873
|
+
placeholder = "Select date and time..."
|
|
1874
|
+
}) => {
|
|
1875
|
+
const { theme } = useTheme();
|
|
1876
|
+
const [isOpen, setIsOpen] = useState9(false);
|
|
1877
|
+
const [viewDate, setViewDate] = useState9(value || /* @__PURE__ */ new Date());
|
|
1878
|
+
const [selectedTime, setSelectedTime] = useState9(
|
|
1879
|
+
value ? { hours: value.getHours(), minutes: value.getMinutes() } : { hours: 12, minutes: 0 }
|
|
1880
|
+
);
|
|
1881
|
+
const [mounted, setMounted] = useState9(false);
|
|
1882
|
+
const [pickerPosition, setPickerPosition] = useState9(null);
|
|
1883
|
+
const inputRef = useRef5(null);
|
|
1884
|
+
const pickerRef = useRef5(null);
|
|
1885
|
+
useEffect7(() => {
|
|
1886
|
+
setMounted(true);
|
|
1887
|
+
}, []);
|
|
1888
|
+
useEffect7(() => {
|
|
1889
|
+
const handleClickOutside = (event) => {
|
|
1890
|
+
if (pickerRef.current && !pickerRef.current.contains(event.target) && inputRef.current && !inputRef.current.contains(event.target)) {
|
|
1891
|
+
setIsOpen(false);
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1894
|
+
if (isOpen) {
|
|
1895
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1896
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1897
|
+
}
|
|
1898
|
+
}, [isOpen]);
|
|
1899
|
+
useEffect7(() => {
|
|
1900
|
+
if (isOpen && inputRef.current) {
|
|
1901
|
+
const rect = inputRef.current.getBoundingClientRect();
|
|
1902
|
+
setPickerPosition({
|
|
1903
|
+
top: rect.bottom + 8,
|
|
1904
|
+
left: rect.left
|
|
1905
|
+
});
|
|
1906
|
+
} else {
|
|
1907
|
+
setPickerPosition(null);
|
|
1908
|
+
}
|
|
1909
|
+
}, [isOpen]);
|
|
1910
|
+
const year = viewDate.getFullYear();
|
|
1911
|
+
const month = viewDate.getMonth();
|
|
1912
|
+
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
1913
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
1914
|
+
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
1915
|
+
const calendarDays = [];
|
|
1916
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
1917
|
+
calendarDays.push(new Date(year, month - 1, daysInPrevMonth - i));
|
|
1918
|
+
}
|
|
1919
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
1920
|
+
calendarDays.push(new Date(year, month, i));
|
|
1921
|
+
}
|
|
1922
|
+
const remainingDays = 42 - calendarDays.length;
|
|
1923
|
+
for (let i = 1; i <= remainingDays; i++) {
|
|
1924
|
+
calendarDays.push(new Date(year, month + 1, i));
|
|
1925
|
+
}
|
|
1926
|
+
const isSameDay = (date1, date2) => {
|
|
1927
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1928
|
+
};
|
|
1929
|
+
const isToday = (date) => {
|
|
1930
|
+
return isSameDay(date, /* @__PURE__ */ new Date());
|
|
1931
|
+
};
|
|
1932
|
+
const isSelected = (date) => {
|
|
1933
|
+
return value && isSameDay(date, value);
|
|
1934
|
+
};
|
|
1935
|
+
const isCurrentMonth = (date) => {
|
|
1936
|
+
return date.getMonth() === month;
|
|
1937
|
+
};
|
|
1938
|
+
const isDisabled = (date) => {
|
|
1939
|
+
if (minDate && date < minDate) return true;
|
|
1940
|
+
if (maxDate && date > maxDate) return true;
|
|
1941
|
+
return false;
|
|
1942
|
+
};
|
|
1943
|
+
const handleDateClick = (date) => {
|
|
1944
|
+
if (isDisabled(date)) return;
|
|
1945
|
+
const newDateTime = new Date(
|
|
1946
|
+
date.getFullYear(),
|
|
1947
|
+
date.getMonth(),
|
|
1948
|
+
date.getDate(),
|
|
1949
|
+
selectedTime.hours,
|
|
1950
|
+
selectedTime.minutes
|
|
1951
|
+
);
|
|
1952
|
+
onChange?.(newDateTime);
|
|
1953
|
+
};
|
|
1954
|
+
const handleTimeChange = (hours, minutes) => {
|
|
1955
|
+
setSelectedTime({ hours, minutes });
|
|
1956
|
+
if (value) {
|
|
1957
|
+
const newDateTime = new Date(
|
|
1958
|
+
value.getFullYear(),
|
|
1959
|
+
value.getMonth(),
|
|
1960
|
+
value.getDate(),
|
|
1961
|
+
hours,
|
|
1962
|
+
minutes
|
|
1963
|
+
);
|
|
1964
|
+
onChange?.(newDateTime);
|
|
1965
|
+
}
|
|
1966
|
+
};
|
|
1967
|
+
const handleDone = () => {
|
|
1968
|
+
if (value) {
|
|
1969
|
+
setIsOpen(false);
|
|
1970
|
+
}
|
|
1971
|
+
};
|
|
1972
|
+
const handlePrevMonth = () => {
|
|
1973
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
1974
|
+
};
|
|
1975
|
+
const handleNextMonth = () => {
|
|
1976
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
1977
|
+
};
|
|
1978
|
+
const handleToday = () => {
|
|
1979
|
+
const now = /* @__PURE__ */ new Date();
|
|
1980
|
+
setViewDate(now);
|
|
1981
|
+
setSelectedTime({ hours: now.getHours(), minutes: now.getMinutes() });
|
|
1982
|
+
onChange?.(now);
|
|
1983
|
+
};
|
|
1984
|
+
const formatDateTime = (date) => {
|
|
1985
|
+
if (!date) return "";
|
|
1986
|
+
return date.toLocaleString("en-US", {
|
|
1987
|
+
month: "short",
|
|
1988
|
+
day: "numeric",
|
|
1989
|
+
year: "numeric",
|
|
1990
|
+
hour: "numeric",
|
|
1991
|
+
minute: "2-digit",
|
|
1992
|
+
hour12: true
|
|
1993
|
+
});
|
|
1994
|
+
};
|
|
1995
|
+
const formatTime = (hours, minutes) => {
|
|
1996
|
+
const period = hours >= 12 ? "PM" : "AM";
|
|
1997
|
+
const displayHours = hours % 12 || 12;
|
|
1998
|
+
const displayMinutes = minutes.toString().padStart(2, "0");
|
|
1999
|
+
return `${displayHours}:${displayMinutes} ${period}`;
|
|
2000
|
+
};
|
|
2001
|
+
const baseStyles = "w-full appearance-none rounded-lg border border-gray-300 bg-white text-gray-900 px-4 py-2.5 text-base transition-all duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent shadow-sm hover:border-gray-400 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-100 dark:hover:border-gray-500 cursor-pointer";
|
|
2002
|
+
const errorStyles = error ? "border-red-500 focus:ring-red-500 dark:border-red-500" : "";
|
|
2003
|
+
const disabledStyles = disabled ? "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900" : "";
|
|
2004
|
+
const picker = isOpen && mounted && pickerPosition ? /* @__PURE__ */ jsxs20(
|
|
2005
|
+
"div",
|
|
2006
|
+
{
|
|
2007
|
+
ref: pickerRef,
|
|
2008
|
+
className: "fixed z-[9999] bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4",
|
|
2009
|
+
style: {
|
|
2010
|
+
top: `${pickerPosition.top}px`,
|
|
2011
|
+
left: `${pickerPosition.left}px`,
|
|
2012
|
+
minWidth: "360px"
|
|
2013
|
+
},
|
|
2014
|
+
children: [
|
|
2015
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between mb-4", children: [
|
|
2016
|
+
/* @__PURE__ */ jsx54(
|
|
2017
|
+
"button",
|
|
2018
|
+
{
|
|
2019
|
+
onClick: handlePrevMonth,
|
|
2020
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
2021
|
+
"aria-label": "Previous month",
|
|
2022
|
+
children: /* @__PURE__ */ jsx54("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx54("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
2023
|
+
}
|
|
2024
|
+
),
|
|
2025
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
|
|
2026
|
+
/* @__PURE__ */ jsxs20("h2", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: [
|
|
2027
|
+
MONTHS2[month],
|
|
2028
|
+
" ",
|
|
2029
|
+
year
|
|
2030
|
+
] }),
|
|
2031
|
+
/* @__PURE__ */ jsx54(
|
|
2032
|
+
"button",
|
|
2033
|
+
{
|
|
2034
|
+
onClick: handleToday,
|
|
2035
|
+
className: "px-2 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors",
|
|
2036
|
+
children: "Now"
|
|
2037
|
+
}
|
|
2038
|
+
)
|
|
2039
|
+
] }),
|
|
2040
|
+
/* @__PURE__ */ jsx54(
|
|
2041
|
+
"button",
|
|
2042
|
+
{
|
|
2043
|
+
onClick: handleNextMonth,
|
|
2044
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
2045
|
+
"aria-label": "Next month",
|
|
2046
|
+
children: /* @__PURE__ */ jsx54("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx54("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
2047
|
+
}
|
|
2048
|
+
)
|
|
2049
|
+
] }),
|
|
2050
|
+
/* @__PURE__ */ jsx54("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS2.map((day) => /* @__PURE__ */ jsx54("div", { className: "text-center text-xs font-semibold text-gray-600 dark:text-gray-400 py-1", children: day }, day)) }),
|
|
2051
|
+
/* @__PURE__ */ jsx54("div", { className: "grid grid-cols-7 gap-1 mb-4", children: calendarDays.map((date, index) => {
|
|
2052
|
+
const isCurrentMonthDay = isCurrentMonth(date);
|
|
2053
|
+
const isTodayDay = isToday(date);
|
|
2054
|
+
const isSelectedDay = isSelected(date);
|
|
2055
|
+
const isDisabledDay = isDisabled(date);
|
|
2056
|
+
return /* @__PURE__ */ jsx54(
|
|
2057
|
+
"button",
|
|
2058
|
+
{
|
|
2059
|
+
onClick: () => handleDateClick(date),
|
|
2060
|
+
disabled: isDisabledDay,
|
|
2061
|
+
className: `
|
|
2062
|
+
aspect-square p-1 rounded-lg text-sm font-medium transition-all
|
|
2063
|
+
${!isCurrentMonthDay ? "text-gray-400 dark:text-gray-600" : "text-gray-900 dark:text-gray-100"}
|
|
2064
|
+
${isTodayDay && !isSelectedDay ? "bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-bold" : ""}
|
|
2065
|
+
${isSelectedDay ? "bg-blue-600 text-white hover:bg-blue-700" : ""}
|
|
2066
|
+
${!isSelectedDay && !isDisabledDay ? "hover:bg-gray-100 dark:hover:bg-gray-700" : ""}
|
|
2067
|
+
${isDisabledDay ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}
|
|
2068
|
+
`,
|
|
2069
|
+
children: date.getDate()
|
|
2070
|
+
},
|
|
2071
|
+
index
|
|
2072
|
+
);
|
|
2073
|
+
}) }),
|
|
2074
|
+
/* @__PURE__ */ jsxs20("div", { className: "border-t border-gray-200 dark:border-gray-700 pt-4", children: [
|
|
2075
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-center gap-4 mb-4", children: [
|
|
2076
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-col items-center", children: [
|
|
2077
|
+
/* @__PURE__ */ jsx54("label", { className: "text-xs font-semibold text-gray-600 dark:text-gray-400 mb-2", children: "Hour" }),
|
|
2078
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-col items-center gap-1", children: [
|
|
2079
|
+
/* @__PURE__ */ jsx54(
|
|
2080
|
+
"button",
|
|
2081
|
+
{
|
|
2082
|
+
type: "button",
|
|
2083
|
+
onClick: () => handleTimeChange((selectedTime.hours + 1) % 24, selectedTime.minutes),
|
|
2084
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
2085
|
+
children: /* @__PURE__ */ jsx54("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx54("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) })
|
|
2086
|
+
}
|
|
2087
|
+
),
|
|
2088
|
+
/* @__PURE__ */ jsx54(
|
|
2089
|
+
"input",
|
|
2090
|
+
{
|
|
2091
|
+
type: "number",
|
|
2092
|
+
min: "0",
|
|
2093
|
+
max: "23",
|
|
2094
|
+
value: selectedTime.hours,
|
|
2095
|
+
onChange: (e) => {
|
|
2096
|
+
const val = parseInt(e.target.value);
|
|
2097
|
+
if (!isNaN(val) && val >= 0 && val <= 23) {
|
|
2098
|
+
handleTimeChange(val, selectedTime.minutes);
|
|
2099
|
+
}
|
|
2100
|
+
},
|
|
2101
|
+
className: "w-16 px-2 py-2 text-center border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg font-semibold [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
2102
|
+
}
|
|
2103
|
+
),
|
|
2104
|
+
/* @__PURE__ */ jsx54(
|
|
2105
|
+
"button",
|
|
2106
|
+
{
|
|
2107
|
+
type: "button",
|
|
2108
|
+
onClick: () => handleTimeChange((selectedTime.hours - 1 + 24) % 24, selectedTime.minutes),
|
|
2109
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
2110
|
+
children: /* @__PURE__ */ jsx54("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx54("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
|
|
2111
|
+
}
|
|
2112
|
+
)
|
|
2113
|
+
] })
|
|
2114
|
+
] }),
|
|
2115
|
+
/* @__PURE__ */ jsx54("span", { className: "text-2xl font-bold text-gray-600 dark:text-gray-400 mt-8", children: ":" }),
|
|
2116
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-col items-center", children: [
|
|
2117
|
+
/* @__PURE__ */ jsx54("label", { className: "text-xs font-semibold text-gray-600 dark:text-gray-400 mb-2", children: "Minute" }),
|
|
2118
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex flex-col items-center gap-1", children: [
|
|
2119
|
+
/* @__PURE__ */ jsx54(
|
|
2120
|
+
"button",
|
|
2121
|
+
{
|
|
2122
|
+
type: "button",
|
|
2123
|
+
onClick: () => handleTimeChange(selectedTime.hours, (selectedTime.minutes + 1) % 60),
|
|
2124
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
2125
|
+
children: /* @__PURE__ */ jsx54("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx54("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) })
|
|
2126
|
+
}
|
|
2127
|
+
),
|
|
2128
|
+
/* @__PURE__ */ jsx54(
|
|
2129
|
+
"input",
|
|
2130
|
+
{
|
|
2131
|
+
type: "number",
|
|
2132
|
+
min: "0",
|
|
2133
|
+
max: "59",
|
|
2134
|
+
value: selectedTime.minutes,
|
|
2135
|
+
onChange: (e) => {
|
|
2136
|
+
const val = parseInt(e.target.value);
|
|
2137
|
+
if (!isNaN(val) && val >= 0 && val <= 59) {
|
|
2138
|
+
handleTimeChange(selectedTime.hours, val);
|
|
2139
|
+
}
|
|
2140
|
+
},
|
|
2141
|
+
className: "w-16 px-2 py-2 text-center border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-lg font-semibold [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
|
2142
|
+
}
|
|
2143
|
+
),
|
|
2144
|
+
/* @__PURE__ */ jsx54(
|
|
2145
|
+
"button",
|
|
2146
|
+
{
|
|
2147
|
+
type: "button",
|
|
2148
|
+
onClick: () => handleTimeChange(selectedTime.hours, (selectedTime.minutes - 1 + 60) % 60),
|
|
2149
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
2150
|
+
children: /* @__PURE__ */ jsx54("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx54("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
|
|
2151
|
+
}
|
|
2152
|
+
)
|
|
2153
|
+
] })
|
|
2154
|
+
] })
|
|
2155
|
+
] }),
|
|
2156
|
+
/* @__PURE__ */ jsx54("div", { className: "text-center text-sm text-gray-600 dark:text-gray-400 mb-4", children: formatTime(selectedTime.hours, selectedTime.minutes) }),
|
|
2157
|
+
/* @__PURE__ */ jsx54(
|
|
2158
|
+
"button",
|
|
2159
|
+
{
|
|
2160
|
+
onClick: handleDone,
|
|
2161
|
+
className: "w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium",
|
|
2162
|
+
children: "Done"
|
|
2163
|
+
}
|
|
2164
|
+
)
|
|
2165
|
+
] })
|
|
2166
|
+
]
|
|
2167
|
+
}
|
|
2168
|
+
) : null;
|
|
2169
|
+
return /* @__PURE__ */ jsxs20("div", { className, children: [
|
|
2170
|
+
label && /* @__PURE__ */ jsx54("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
2171
|
+
/* @__PURE__ */ jsxs20(
|
|
2172
|
+
"div",
|
|
2173
|
+
{
|
|
2174
|
+
ref: inputRef,
|
|
2175
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
2176
|
+
className: `${baseStyles} ${errorStyles} ${disabledStyles} flex items-center justify-between`.trim(),
|
|
2177
|
+
children: [
|
|
2178
|
+
/* @__PURE__ */ jsx54("span", { className: !value ? "text-gray-500 dark:text-gray-400" : "", children: value ? formatDateTime(value) : placeholder }),
|
|
2179
|
+
/* @__PURE__ */ jsx54("svg", { className: "w-5 h-5 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx54("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) })
|
|
2180
|
+
]
|
|
2181
|
+
}
|
|
2182
|
+
),
|
|
2183
|
+
error && /* @__PURE__ */ jsx54("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
2184
|
+
helperText && !error && /* @__PURE__ */ jsx54("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText }),
|
|
2185
|
+
mounted && createPortal3(picker, document.body)
|
|
2186
|
+
] });
|
|
2187
|
+
};
|
|
1496
2188
|
DateTimePicker.displayName = "DateTimePicker";
|
|
1497
2189
|
|
|
2190
|
+
// src/components/Calendar.tsx
|
|
2191
|
+
import { useState as useState10 } from "react";
|
|
2192
|
+
import { jsx as jsx55, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
2193
|
+
var DAYS3 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
2194
|
+
var MONTHS3 = [
|
|
2195
|
+
"January",
|
|
2196
|
+
"February",
|
|
2197
|
+
"March",
|
|
2198
|
+
"April",
|
|
2199
|
+
"May",
|
|
2200
|
+
"June",
|
|
2201
|
+
"July",
|
|
2202
|
+
"August",
|
|
2203
|
+
"September",
|
|
2204
|
+
"October",
|
|
2205
|
+
"November",
|
|
2206
|
+
"December"
|
|
2207
|
+
];
|
|
2208
|
+
var Calendar = ({
|
|
2209
|
+
value,
|
|
2210
|
+
onChange,
|
|
2211
|
+
minDate,
|
|
2212
|
+
maxDate,
|
|
2213
|
+
className = ""
|
|
2214
|
+
}) => {
|
|
2215
|
+
const { theme } = useTheme();
|
|
2216
|
+
const [currentDate, setCurrentDate] = useState10(value || /* @__PURE__ */ new Date());
|
|
2217
|
+
const [viewDate, setViewDate] = useState10(value || /* @__PURE__ */ new Date());
|
|
2218
|
+
const year = viewDate.getFullYear();
|
|
2219
|
+
const month = viewDate.getMonth();
|
|
2220
|
+
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
2221
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
2222
|
+
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
2223
|
+
const calendarDays = [];
|
|
2224
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
2225
|
+
calendarDays.push(new Date(year, month - 1, daysInPrevMonth - i));
|
|
2226
|
+
}
|
|
2227
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
2228
|
+
calendarDays.push(new Date(year, month, i));
|
|
2229
|
+
}
|
|
2230
|
+
const remainingDays = 42 - calendarDays.length;
|
|
2231
|
+
for (let i = 1; i <= remainingDays; i++) {
|
|
2232
|
+
calendarDays.push(new Date(year, month + 1, i));
|
|
2233
|
+
}
|
|
2234
|
+
const isSameDay = (date1, date2) => {
|
|
2235
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
2236
|
+
};
|
|
2237
|
+
const isToday = (date) => {
|
|
2238
|
+
return isSameDay(date, /* @__PURE__ */ new Date());
|
|
2239
|
+
};
|
|
2240
|
+
const isSelected = (date) => {
|
|
2241
|
+
return value && isSameDay(date, value);
|
|
2242
|
+
};
|
|
2243
|
+
const isCurrentMonth = (date) => {
|
|
2244
|
+
return date.getMonth() === month;
|
|
2245
|
+
};
|
|
2246
|
+
const isDisabled = (date) => {
|
|
2247
|
+
if (minDate && date < minDate) return true;
|
|
2248
|
+
if (maxDate && date > maxDate) return true;
|
|
2249
|
+
return false;
|
|
2250
|
+
};
|
|
2251
|
+
const handleDateClick = (date) => {
|
|
2252
|
+
if (isDisabled(date)) return;
|
|
2253
|
+
setCurrentDate(date);
|
|
2254
|
+
onChange?.(date);
|
|
2255
|
+
};
|
|
2256
|
+
const handlePrevMonth = () => {
|
|
2257
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
2258
|
+
};
|
|
2259
|
+
const handleNextMonth = () => {
|
|
2260
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
2261
|
+
};
|
|
2262
|
+
const handleToday = () => {
|
|
2263
|
+
const today = /* @__PURE__ */ new Date();
|
|
2264
|
+
setViewDate(today);
|
|
2265
|
+
setCurrentDate(today);
|
|
2266
|
+
onChange?.(today);
|
|
2267
|
+
};
|
|
2268
|
+
return /* @__PURE__ */ jsxs21("div", { className: `bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4 ${className}`, children: [
|
|
2269
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center justify-between mb-4", children: [
|
|
2270
|
+
/* @__PURE__ */ jsx55(
|
|
2271
|
+
"button",
|
|
2272
|
+
{
|
|
2273
|
+
onClick: handlePrevMonth,
|
|
2274
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
2275
|
+
"aria-label": "Previous month",
|
|
2276
|
+
children: /* @__PURE__ */ jsx55("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx55("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
2277
|
+
}
|
|
2278
|
+
),
|
|
2279
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2", children: [
|
|
2280
|
+
/* @__PURE__ */ jsxs21("h2", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: [
|
|
2281
|
+
MONTHS3[month],
|
|
2282
|
+
" ",
|
|
2283
|
+
year
|
|
2284
|
+
] }),
|
|
2285
|
+
/* @__PURE__ */ jsx55(
|
|
2286
|
+
"button",
|
|
2287
|
+
{
|
|
2288
|
+
onClick: handleToday,
|
|
2289
|
+
className: "px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors",
|
|
2290
|
+
children: "Today"
|
|
2291
|
+
}
|
|
2292
|
+
)
|
|
2293
|
+
] }),
|
|
2294
|
+
/* @__PURE__ */ jsx55(
|
|
2295
|
+
"button",
|
|
2296
|
+
{
|
|
2297
|
+
onClick: handleNextMonth,
|
|
2298
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
2299
|
+
"aria-label": "Next month",
|
|
2300
|
+
children: /* @__PURE__ */ jsx55("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx55("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
2301
|
+
}
|
|
2302
|
+
)
|
|
2303
|
+
] }),
|
|
2304
|
+
/* @__PURE__ */ jsx55("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS3.map((day) => /* @__PURE__ */ jsx55(
|
|
2305
|
+
"div",
|
|
2306
|
+
{
|
|
2307
|
+
className: "text-center text-xs font-semibold text-gray-600 dark:text-gray-400 py-2",
|
|
2308
|
+
children: day
|
|
2309
|
+
},
|
|
2310
|
+
day
|
|
2311
|
+
)) }),
|
|
2312
|
+
/* @__PURE__ */ jsx55("div", { className: "grid grid-cols-7 gap-1", children: calendarDays.map((date, index) => {
|
|
2313
|
+
if (!date) return /* @__PURE__ */ jsx55("div", {}, index);
|
|
2314
|
+
const isCurrentMonthDay = isCurrentMonth(date);
|
|
2315
|
+
const isTodayDay = isToday(date);
|
|
2316
|
+
const isSelectedDay = isSelected(date);
|
|
2317
|
+
const isDisabledDay = isDisabled(date);
|
|
2318
|
+
return /* @__PURE__ */ jsx55(
|
|
2319
|
+
"button",
|
|
2320
|
+
{
|
|
2321
|
+
onClick: () => handleDateClick(date),
|
|
2322
|
+
disabled: isDisabledDay,
|
|
2323
|
+
className: `
|
|
2324
|
+
aspect-square p-2 rounded-lg text-sm font-medium transition-all
|
|
2325
|
+
${!isCurrentMonthDay ? "text-gray-400 dark:text-gray-600" : "text-gray-900 dark:text-gray-100"}
|
|
2326
|
+
${isTodayDay && !isSelectedDay ? "bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-bold" : ""}
|
|
2327
|
+
${isSelectedDay ? "bg-blue-600 text-white hover:bg-blue-700" : ""}
|
|
2328
|
+
${!isSelectedDay && !isDisabledDay ? "hover:bg-gray-100 dark:hover:bg-gray-700" : ""}
|
|
2329
|
+
${isDisabledDay ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}
|
|
2330
|
+
`,
|
|
2331
|
+
children: date.getDate()
|
|
2332
|
+
},
|
|
2333
|
+
index
|
|
2334
|
+
);
|
|
2335
|
+
}) })
|
|
2336
|
+
] });
|
|
2337
|
+
};
|
|
2338
|
+
|
|
1498
2339
|
// src/components/Radio.tsx
|
|
1499
|
-
import
|
|
1500
|
-
import { jsx as
|
|
2340
|
+
import React17 from "react";
|
|
2341
|
+
import { jsx as jsx56, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1501
2342
|
var Radio = ({
|
|
1502
2343
|
name,
|
|
1503
2344
|
options,
|
|
@@ -1508,7 +2349,7 @@ var Radio = ({
|
|
|
1508
2349
|
orientation = "vertical",
|
|
1509
2350
|
className = ""
|
|
1510
2351
|
}) => {
|
|
1511
|
-
const [internalValue, setInternalValue] =
|
|
2352
|
+
const [internalValue, setInternalValue] = React17.useState(defaultValue || "");
|
|
1512
2353
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
1513
2354
|
const handleChange = (optionValue) => {
|
|
1514
2355
|
if (disabled) return;
|
|
@@ -1516,17 +2357,17 @@ var Radio = ({
|
|
|
1516
2357
|
onChange?.(optionValue);
|
|
1517
2358
|
};
|
|
1518
2359
|
const containerClass = orientation === "horizontal" ? "flex flex-wrap gap-4" : "flex flex-col gap-2";
|
|
1519
|
-
return /* @__PURE__ */
|
|
2360
|
+
return /* @__PURE__ */ jsx56("div", { className: `${containerClass} ${className}`, role: "radiogroup", children: options.map((option) => {
|
|
1520
2361
|
const isDisabled = disabled || option.disabled;
|
|
1521
2362
|
const isChecked = value === option.value;
|
|
1522
2363
|
const id = `${name}-${option.value}`;
|
|
1523
|
-
return /* @__PURE__ */
|
|
2364
|
+
return /* @__PURE__ */ jsxs22(
|
|
1524
2365
|
"label",
|
|
1525
2366
|
{
|
|
1526
2367
|
htmlFor: id,
|
|
1527
2368
|
className: `flex items-center gap-2 cursor-pointer ${isDisabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
1528
2369
|
children: [
|
|
1529
|
-
/* @__PURE__ */
|
|
2370
|
+
/* @__PURE__ */ jsx56(
|
|
1530
2371
|
"input",
|
|
1531
2372
|
{
|
|
1532
2373
|
type: "radio",
|
|
@@ -1539,7 +2380,7 @@ var Radio = ({
|
|
|
1539
2380
|
className: "w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 cursor-pointer disabled:cursor-not-allowed"
|
|
1540
2381
|
}
|
|
1541
2382
|
),
|
|
1542
|
-
/* @__PURE__ */
|
|
2383
|
+
/* @__PURE__ */ jsx56("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-300", children: option.label })
|
|
1543
2384
|
]
|
|
1544
2385
|
},
|
|
1545
2386
|
option.value
|
|
@@ -1548,7 +2389,7 @@ var Radio = ({
|
|
|
1548
2389
|
};
|
|
1549
2390
|
|
|
1550
2391
|
// src/components/ProgressBar.tsx
|
|
1551
|
-
import { jsx as
|
|
2392
|
+
import { jsx as jsx57, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1552
2393
|
var ProgressBar = ({
|
|
1553
2394
|
value,
|
|
1554
2395
|
max = 100,
|
|
@@ -1559,7 +2400,7 @@ var ProgressBar = ({
|
|
|
1559
2400
|
className = ""
|
|
1560
2401
|
}) => {
|
|
1561
2402
|
const percentage = Math.min(Math.max(value / max * 100, 0), 100);
|
|
1562
|
-
const
|
|
2403
|
+
const sizeClasses7 = {
|
|
1563
2404
|
sm: "h-1",
|
|
1564
2405
|
md: "h-2",
|
|
1565
2406
|
lg: "h-3"
|
|
@@ -1570,26 +2411,26 @@ var ProgressBar = ({
|
|
|
1570
2411
|
warning: "bg-yellow-500 dark:bg-yellow-400",
|
|
1571
2412
|
danger: "bg-red-600 dark:bg-red-500"
|
|
1572
2413
|
};
|
|
1573
|
-
return /* @__PURE__ */
|
|
1574
|
-
(showLabel || label) && /* @__PURE__ */
|
|
1575
|
-
label && /* @__PURE__ */
|
|
1576
|
-
showLabel && /* @__PURE__ */
|
|
2414
|
+
return /* @__PURE__ */ jsxs23("div", { className: `w-full ${className}`, children: [
|
|
2415
|
+
(showLabel || label) && /* @__PURE__ */ jsxs23("div", { className: "flex justify-between items-center mb-1", children: [
|
|
2416
|
+
label && /* @__PURE__ */ jsx57("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: label }),
|
|
2417
|
+
showLabel && /* @__PURE__ */ jsxs23("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: [
|
|
1577
2418
|
Math.round(percentage),
|
|
1578
2419
|
"%"
|
|
1579
2420
|
] })
|
|
1580
2421
|
] }),
|
|
1581
|
-
/* @__PURE__ */
|
|
2422
|
+
/* @__PURE__ */ jsx57(
|
|
1582
2423
|
"div",
|
|
1583
2424
|
{
|
|
1584
|
-
className: `w-full bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden ${
|
|
2425
|
+
className: `w-full bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden ${sizeClasses7[size]}`,
|
|
1585
2426
|
role: "progressbar",
|
|
1586
2427
|
"aria-valuenow": value,
|
|
1587
2428
|
"aria-valuemin": 0,
|
|
1588
2429
|
"aria-valuemax": max,
|
|
1589
|
-
children: /* @__PURE__ */
|
|
2430
|
+
children: /* @__PURE__ */ jsx57(
|
|
1590
2431
|
"div",
|
|
1591
2432
|
{
|
|
1592
|
-
className: `${
|
|
2433
|
+
className: `${sizeClasses7[size]} ${variantClasses[variant]} rounded-full transition-all duration-300 ease-out`,
|
|
1593
2434
|
style: { width: `${percentage}%` }
|
|
1594
2435
|
}
|
|
1595
2436
|
)
|
|
@@ -1599,8 +2440,8 @@ var ProgressBar = ({
|
|
|
1599
2440
|
};
|
|
1600
2441
|
|
|
1601
2442
|
// src/components/Slider.tsx
|
|
1602
|
-
import
|
|
1603
|
-
import { jsx as
|
|
2443
|
+
import React18 from "react";
|
|
2444
|
+
import { jsx as jsx58, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1604
2445
|
var Slider = ({
|
|
1605
2446
|
value: controlledValue,
|
|
1606
2447
|
defaultValue = 50,
|
|
@@ -1613,7 +2454,7 @@ var Slider = ({
|
|
|
1613
2454
|
label,
|
|
1614
2455
|
className = ""
|
|
1615
2456
|
}) => {
|
|
1616
|
-
const [internalValue, setInternalValue] =
|
|
2457
|
+
const [internalValue, setInternalValue] = React18.useState(defaultValue);
|
|
1617
2458
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
1618
2459
|
const handleChange = (e) => {
|
|
1619
2460
|
const newValue = Number(e.target.value);
|
|
@@ -1621,21 +2462,21 @@ var Slider = ({
|
|
|
1621
2462
|
onChange?.(newValue);
|
|
1622
2463
|
};
|
|
1623
2464
|
const percentage = (value - min) / (max - min) * 100;
|
|
1624
|
-
return /* @__PURE__ */
|
|
1625
|
-
(label || showValue) && /* @__PURE__ */
|
|
1626
|
-
label && /* @__PURE__ */
|
|
1627
|
-
showValue && /* @__PURE__ */
|
|
2465
|
+
return /* @__PURE__ */ jsxs24("div", { className: `w-full ${className}`, children: [
|
|
2466
|
+
(label || showValue) && /* @__PURE__ */ jsxs24("div", { className: "flex justify-between items-center mb-2", children: [
|
|
2467
|
+
label && /* @__PURE__ */ jsx58("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: label }),
|
|
2468
|
+
showValue && /* @__PURE__ */ jsx58("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: value })
|
|
1628
2469
|
] }),
|
|
1629
|
-
/* @__PURE__ */
|
|
1630
|
-
/* @__PURE__ */
|
|
1631
|
-
/* @__PURE__ */
|
|
2470
|
+
/* @__PURE__ */ jsxs24("div", { className: "relative", children: [
|
|
2471
|
+
/* @__PURE__ */ jsx58("div", { className: "absolute inset-0 h-2 bg-gray-200 dark:bg-gray-700 rounded-full top-1/2 -translate-y-1/2" }),
|
|
2472
|
+
/* @__PURE__ */ jsx58(
|
|
1632
2473
|
"div",
|
|
1633
2474
|
{
|
|
1634
2475
|
className: "absolute h-2 bg-blue-600 dark:bg-blue-500 rounded-full top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1635
2476
|
style: { width: `${percentage}%` }
|
|
1636
2477
|
}
|
|
1637
2478
|
),
|
|
1638
|
-
/* @__PURE__ */
|
|
2479
|
+
/* @__PURE__ */ jsx58(
|
|
1639
2480
|
"input",
|
|
1640
2481
|
{
|
|
1641
2482
|
type: "range",
|
|
@@ -1657,8 +2498,8 @@ var Slider = ({
|
|
|
1657
2498
|
};
|
|
1658
2499
|
|
|
1659
2500
|
// src/components/Avatar.tsx
|
|
1660
|
-
import
|
|
1661
|
-
import { jsx as
|
|
2501
|
+
import React19 from "react";
|
|
2502
|
+
import { jsx as jsx59 } from "react/jsx-runtime";
|
|
1662
2503
|
var Avatar = ({
|
|
1663
2504
|
src,
|
|
1664
2505
|
alt,
|
|
@@ -1668,8 +2509,8 @@ var Avatar = ({
|
|
|
1668
2509
|
className = "",
|
|
1669
2510
|
fallbackColor = "bg-blue-600"
|
|
1670
2511
|
}) => {
|
|
1671
|
-
const [imageError, setImageError] =
|
|
1672
|
-
const
|
|
2512
|
+
const [imageError, setImageError] = React19.useState(false);
|
|
2513
|
+
const sizeClasses7 = {
|
|
1673
2514
|
xs: "w-6 h-6 text-xs",
|
|
1674
2515
|
sm: "w-8 h-8 text-sm",
|
|
1675
2516
|
md: "w-10 h-10 text-base",
|
|
@@ -1686,11 +2527,11 @@ var Avatar = ({
|
|
|
1686
2527
|
};
|
|
1687
2528
|
const showImage = src && !imageError;
|
|
1688
2529
|
const showInitials = !showImage && name;
|
|
1689
|
-
return /* @__PURE__ */
|
|
2530
|
+
return /* @__PURE__ */ jsx59(
|
|
1690
2531
|
"div",
|
|
1691
2532
|
{
|
|
1692
|
-
className: `${
|
|
1693
|
-
children: showImage ? /* @__PURE__ */
|
|
2533
|
+
className: `${sizeClasses7[size]} ${shapeClass} flex items-center justify-center overflow-hidden ${showImage ? "bg-gray-200 dark:bg-gray-700" : `${fallbackColor} text-white`} ${className}`,
|
|
2534
|
+
children: showImage ? /* @__PURE__ */ jsx59(
|
|
1694
2535
|
"img",
|
|
1695
2536
|
{
|
|
1696
2537
|
src,
|
|
@@ -1698,13 +2539,13 @@ var Avatar = ({
|
|
|
1698
2539
|
className: "w-full h-full object-cover",
|
|
1699
2540
|
onError: () => setImageError(true)
|
|
1700
2541
|
}
|
|
1701
|
-
) : showInitials ? /* @__PURE__ */
|
|
2542
|
+
) : showInitials ? /* @__PURE__ */ jsx59("span", { className: "font-semibold select-none", children: getInitials(name) }) : /* @__PURE__ */ jsx59(
|
|
1702
2543
|
"svg",
|
|
1703
2544
|
{
|
|
1704
2545
|
className: "w-full h-full text-gray-400 dark:text-gray-600",
|
|
1705
2546
|
fill: "currentColor",
|
|
1706
2547
|
viewBox: "0 0 24 24",
|
|
1707
|
-
children: /* @__PURE__ */
|
|
2548
|
+
children: /* @__PURE__ */ jsx59("path", { d: "M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" })
|
|
1708
2549
|
}
|
|
1709
2550
|
)
|
|
1710
2551
|
}
|
|
@@ -1712,7 +2553,7 @@ var Avatar = ({
|
|
|
1712
2553
|
};
|
|
1713
2554
|
|
|
1714
2555
|
// src/components/Textarea.tsx
|
|
1715
|
-
import { jsx as
|
|
2556
|
+
import { jsx as jsx60, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1716
2557
|
var Textarea = ({
|
|
1717
2558
|
label,
|
|
1718
2559
|
error,
|
|
@@ -1723,7 +2564,7 @@ var Textarea = ({
|
|
|
1723
2564
|
disabled,
|
|
1724
2565
|
...props
|
|
1725
2566
|
}) => {
|
|
1726
|
-
const
|
|
2567
|
+
const sizeClasses7 = {
|
|
1727
2568
|
sm: "px-3 py-1.5 text-sm min-h-[80px]",
|
|
1728
2569
|
md: "px-4 py-2 text-base min-h-[100px]",
|
|
1729
2570
|
lg: "px-4 py-3 text-lg min-h-[120px]"
|
|
@@ -1739,24 +2580,24 @@ var Textarea = ({
|
|
|
1739
2580
|
bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100
|
|
1740
2581
|
placeholder:text-gray-500 dark:placeholder:text-gray-400
|
|
1741
2582
|
disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-gray-50 dark:disabled:bg-gray-900`;
|
|
1742
|
-
return /* @__PURE__ */
|
|
1743
|
-
label && /* @__PURE__ */
|
|
1744
|
-
/* @__PURE__ */
|
|
2583
|
+
return /* @__PURE__ */ jsxs25("div", { className: `w-full ${className}`, children: [
|
|
2584
|
+
label && /* @__PURE__ */ jsx60("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
2585
|
+
/* @__PURE__ */ jsx60(
|
|
1745
2586
|
"textarea",
|
|
1746
2587
|
{
|
|
1747
|
-
className: `${baseClasses} ${
|
|
2588
|
+
className: `${baseClasses} ${sizeClasses7[size]} ${resizeClasses[resize]}`,
|
|
1748
2589
|
disabled,
|
|
1749
2590
|
...props
|
|
1750
2591
|
}
|
|
1751
2592
|
),
|
|
1752
|
-
error && /* @__PURE__ */
|
|
1753
|
-
helperText && !error && /* @__PURE__ */
|
|
2593
|
+
error && /* @__PURE__ */ jsx60("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
2594
|
+
helperText && !error && /* @__PURE__ */ jsx60("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText })
|
|
1754
2595
|
] });
|
|
1755
2596
|
};
|
|
1756
2597
|
|
|
1757
2598
|
// src/components/Toast.tsx
|
|
1758
|
-
import { createContext as createContext3, useContext as useContext3, useState as
|
|
1759
|
-
import { jsx as
|
|
2599
|
+
import { createContext as createContext3, useContext as useContext3, useState as useState11, useCallback } from "react";
|
|
2600
|
+
import { jsx as jsx61, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1760
2601
|
var ToastContext = createContext3(void 0);
|
|
1761
2602
|
var useToast = () => {
|
|
1762
2603
|
const context = useContext3(ToastContext);
|
|
@@ -1766,7 +2607,7 @@ var useToast = () => {
|
|
|
1766
2607
|
return context;
|
|
1767
2608
|
};
|
|
1768
2609
|
var ToastProvider = ({ children, position = "top-right" }) => {
|
|
1769
|
-
const [toasts, setToasts] =
|
|
2610
|
+
const [toasts, setToasts] = useState11([]);
|
|
1770
2611
|
const addToast = useCallback((toast2) => {
|
|
1771
2612
|
const id = Math.random().toString(36).substring(7);
|
|
1772
2613
|
const newToast = { ...toast2, id };
|
|
@@ -1787,9 +2628,9 @@ var ToastProvider = ({ children, position = "top-right" }) => {
|
|
|
1787
2628
|
"top-center": "top-4 left-1/2 -translate-x-1/2",
|
|
1788
2629
|
"bottom-center": "bottom-4 left-1/2 -translate-x-1/2"
|
|
1789
2630
|
};
|
|
1790
|
-
return /* @__PURE__ */
|
|
2631
|
+
return /* @__PURE__ */ jsxs26(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
|
|
1791
2632
|
children,
|
|
1792
|
-
/* @__PURE__ */
|
|
2633
|
+
/* @__PURE__ */ jsx61("div", { className: `fixed ${positionClasses2[position]} z-50 flex flex-col gap-2 max-w-md`, children: toasts.map((toast2) => /* @__PURE__ */ jsx61(ToastItem, { toast: toast2, onClose: () => removeToast(toast2.id) }, toast2.id)) })
|
|
1793
2634
|
] });
|
|
1794
2635
|
};
|
|
1795
2636
|
var ToastItem = ({ toast: toast2, onClose }) => {
|
|
@@ -1800,27 +2641,27 @@ var ToastItem = ({ toast: toast2, onClose }) => {
|
|
|
1800
2641
|
info: "bg-blue-50 dark:bg-blue-900/30 border-blue-500 text-blue-800 dark:text-blue-200"
|
|
1801
2642
|
};
|
|
1802
2643
|
const typeIcons = {
|
|
1803
|
-
success: /* @__PURE__ */
|
|
1804
|
-
error: /* @__PURE__ */
|
|
1805
|
-
warning: /* @__PURE__ */
|
|
1806
|
-
info: /* @__PURE__ */
|
|
2644
|
+
success: /* @__PURE__ */ jsx61(CheckIcon, { size: "sm", className: "text-green-600 dark:text-green-400" }),
|
|
2645
|
+
error: /* @__PURE__ */ jsx61(CloseIcon, { size: "sm", className: "text-red-600 dark:text-red-400" }),
|
|
2646
|
+
warning: /* @__PURE__ */ jsx61("svg", { className: "w-4 h-4 text-yellow-600 dark:text-yellow-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx61("path", { fillRule: "evenodd", d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }),
|
|
2647
|
+
info: /* @__PURE__ */ jsx61("svg", { className: "w-4 h-4 text-blue-600 dark:text-blue-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx61("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) })
|
|
1807
2648
|
};
|
|
1808
2649
|
const type = toast2.type || "info";
|
|
1809
|
-
return /* @__PURE__ */
|
|
2650
|
+
return /* @__PURE__ */ jsxs26(
|
|
1810
2651
|
"div",
|
|
1811
2652
|
{
|
|
1812
2653
|
className: `flex items-start gap-3 p-4 rounded-lg border-l-4 shadow-lg backdrop-blur-sm ${typeStyles[type]} animate-slide-in`,
|
|
1813
2654
|
role: "alert",
|
|
1814
2655
|
children: [
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
/* @__PURE__ */
|
|
2656
|
+
/* @__PURE__ */ jsx61("div", { className: "flex-shrink-0 mt-0.5", children: typeIcons[type] }),
|
|
2657
|
+
/* @__PURE__ */ jsx61("p", { className: "flex-1 text-sm font-medium", children: toast2.message }),
|
|
2658
|
+
/* @__PURE__ */ jsx61(
|
|
1818
2659
|
"button",
|
|
1819
2660
|
{
|
|
1820
2661
|
onClick: onClose,
|
|
1821
2662
|
className: "flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-colors",
|
|
1822
2663
|
"aria-label": "Close",
|
|
1823
|
-
children: /* @__PURE__ */
|
|
2664
|
+
children: /* @__PURE__ */ jsx61(CloseIcon, { size: "sm" })
|
|
1824
2665
|
}
|
|
1825
2666
|
)
|
|
1826
2667
|
]
|
|
@@ -1851,8 +2692,8 @@ var toast = {
|
|
|
1851
2692
|
};
|
|
1852
2693
|
|
|
1853
2694
|
// src/components/Stepper.tsx
|
|
1854
|
-
import
|
|
1855
|
-
import { jsx as
|
|
2695
|
+
import React21 from "react";
|
|
2696
|
+
import { jsx as jsx62, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1856
2697
|
var Stepper = ({
|
|
1857
2698
|
steps,
|
|
1858
2699
|
currentStep,
|
|
@@ -1860,18 +2701,18 @@ var Stepper = ({
|
|
|
1860
2701
|
className = ""
|
|
1861
2702
|
}) => {
|
|
1862
2703
|
const isHorizontal = orientation === "horizontal";
|
|
1863
|
-
return /* @__PURE__ */
|
|
2704
|
+
return /* @__PURE__ */ jsx62("div", { className: `${isHorizontal ? "flex items-center" : "flex flex-col"} ${className}`, children: steps.map((step, index) => {
|
|
1864
2705
|
const stepNumber = index + 1;
|
|
1865
2706
|
const isActive = stepNumber === currentStep;
|
|
1866
2707
|
const isCompleted = stepNumber < currentStep;
|
|
1867
2708
|
const isLast = index === steps.length - 1;
|
|
1868
|
-
return /* @__PURE__ */
|
|
1869
|
-
/* @__PURE__ */
|
|
1870
|
-
/* @__PURE__ */
|
|
2709
|
+
return /* @__PURE__ */ jsxs27(React21.Fragment, { children: [
|
|
2710
|
+
/* @__PURE__ */ jsxs27("div", { className: `flex ${isHorizontal ? "flex-col items-center" : "flex-row items-start"} ${isHorizontal ? "" : "flex-1"}`, children: [
|
|
2711
|
+
/* @__PURE__ */ jsx62("div", { className: "flex items-center", children: /* @__PURE__ */ jsx62(
|
|
1871
2712
|
"div",
|
|
1872
2713
|
{
|
|
1873
2714
|
className: `flex items-center justify-center w-10 h-10 rounded-full border-2 transition-all ${isCompleted ? "bg-blue-600 border-blue-600 dark:bg-blue-500 dark:border-blue-500" : isActive ? "border-blue-600 bg-white dark:border-blue-500 dark:bg-gray-800" : "border-gray-300 bg-white dark:border-gray-600 dark:bg-gray-800"}`,
|
|
1874
|
-
children: isCompleted ? /* @__PURE__ */
|
|
2715
|
+
children: isCompleted ? /* @__PURE__ */ jsx62(CheckIcon, { size: "sm", className: "text-white" }) : /* @__PURE__ */ jsx62(
|
|
1875
2716
|
"span",
|
|
1876
2717
|
{
|
|
1877
2718
|
className: `text-sm font-semibold ${isActive ? "text-blue-600 dark:text-blue-400" : "text-gray-500 dark:text-gray-400"}`,
|
|
@@ -1880,18 +2721,18 @@ var Stepper = ({
|
|
|
1880
2721
|
)
|
|
1881
2722
|
}
|
|
1882
2723
|
) }),
|
|
1883
|
-
/* @__PURE__ */
|
|
1884
|
-
/* @__PURE__ */
|
|
2724
|
+
/* @__PURE__ */ jsxs27("div", { className: `${isHorizontal ? "mt-2 text-center" : "ml-4 pb-8"} ${isLast && !isHorizontal ? "pb-0" : ""}`, children: [
|
|
2725
|
+
/* @__PURE__ */ jsx62(
|
|
1885
2726
|
"p",
|
|
1886
2727
|
{
|
|
1887
2728
|
className: `text-sm font-medium ${isActive || isCompleted ? "text-gray-900 dark:text-gray-100" : "text-gray-500 dark:text-gray-400"}`,
|
|
1888
2729
|
children: step.label
|
|
1889
2730
|
}
|
|
1890
2731
|
),
|
|
1891
|
-
step.description && /* @__PURE__ */
|
|
2732
|
+
step.description && /* @__PURE__ */ jsx62("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: step.description })
|
|
1892
2733
|
] })
|
|
1893
2734
|
] }),
|
|
1894
|
-
!isLast && /* @__PURE__ */
|
|
2735
|
+
!isLast && /* @__PURE__ */ jsx62(
|
|
1895
2736
|
"div",
|
|
1896
2737
|
{
|
|
1897
2738
|
className: `${isHorizontal ? "flex-1 h-0.5 mx-4" : "w-0.5 h-full ml-5 -mt-8"} ${isCompleted || isActive && stepNumber < currentStep ? "bg-blue-600 dark:bg-blue-500" : "bg-gray-300 dark:bg-gray-600"}`
|
|
@@ -1902,7 +2743,7 @@ var Stepper = ({
|
|
|
1902
2743
|
};
|
|
1903
2744
|
|
|
1904
2745
|
// src/components/Divider.tsx
|
|
1905
|
-
import { jsx as
|
|
2746
|
+
import { jsx as jsx63, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1906
2747
|
var Divider = ({
|
|
1907
2748
|
orientation = "horizontal",
|
|
1908
2749
|
variant = "solid",
|
|
@@ -1921,14 +2762,14 @@ var Divider = ({
|
|
|
1921
2762
|
center: "justify-center",
|
|
1922
2763
|
right: "justify-end"
|
|
1923
2764
|
};
|
|
1924
|
-
return /* @__PURE__ */
|
|
1925
|
-
labelPosition !== "left" && /* @__PURE__ */
|
|
1926
|
-
/* @__PURE__ */
|
|
1927
|
-
labelPosition !== "right" && /* @__PURE__ */
|
|
2765
|
+
return /* @__PURE__ */ jsxs28("div", { className: `flex items-center ${alignmentClasses[labelPosition]} ${className}`, role: "separator", children: [
|
|
2766
|
+
labelPosition !== "left" && /* @__PURE__ */ jsx63("div", { className: `flex-1 border-t ${variantClasses[variant]} border-gray-300 dark:border-gray-600` }),
|
|
2767
|
+
/* @__PURE__ */ jsx63("span", { className: "px-4 text-sm text-gray-500 dark:text-gray-400", children: label }),
|
|
2768
|
+
labelPosition !== "right" && /* @__PURE__ */ jsx63("div", { className: `flex-1 border-t ${variantClasses[variant]} border-gray-300 dark:border-gray-600` })
|
|
1928
2769
|
] });
|
|
1929
2770
|
}
|
|
1930
2771
|
if (orientation === "vertical") {
|
|
1931
|
-
return /* @__PURE__ */
|
|
2772
|
+
return /* @__PURE__ */ jsx63(
|
|
1932
2773
|
"div",
|
|
1933
2774
|
{
|
|
1934
2775
|
className: `inline-block h-full border-l ${variantClasses[variant]} border-gray-300 dark:border-gray-600 ${className}`,
|
|
@@ -1937,7 +2778,7 @@ var Divider = ({
|
|
|
1937
2778
|
}
|
|
1938
2779
|
);
|
|
1939
2780
|
}
|
|
1940
|
-
return /* @__PURE__ */
|
|
2781
|
+
return /* @__PURE__ */ jsx63(
|
|
1941
2782
|
"hr",
|
|
1942
2783
|
{
|
|
1943
2784
|
className: `border-t ${variantClasses[variant]} border-gray-300 dark:border-gray-600 ${className}`,
|
|
@@ -1947,8 +2788,8 @@ var Divider = ({
|
|
|
1947
2788
|
};
|
|
1948
2789
|
|
|
1949
2790
|
// src/components/FileUpload.tsx
|
|
1950
|
-
import { useRef as
|
|
1951
|
-
import { jsx as
|
|
2791
|
+
import { useRef as useRef6, useState as useState12 } from "react";
|
|
2792
|
+
import { jsx as jsx64, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
1952
2793
|
var FileUpload = ({
|
|
1953
2794
|
accept,
|
|
1954
2795
|
multiple = false,
|
|
@@ -1961,9 +2802,9 @@ var FileUpload = ({
|
|
|
1961
2802
|
label,
|
|
1962
2803
|
helperText
|
|
1963
2804
|
}) => {
|
|
1964
|
-
const [files, setFiles] =
|
|
1965
|
-
const [isDragging, setIsDragging] =
|
|
1966
|
-
const fileInputRef =
|
|
2805
|
+
const [files, setFiles] = useState12([]);
|
|
2806
|
+
const [isDragging, setIsDragging] = useState12(false);
|
|
2807
|
+
const fileInputRef = useRef6(null);
|
|
1967
2808
|
const formatFileSize = (bytes) => {
|
|
1968
2809
|
if (bytes === 0) return "0 Bytes";
|
|
1969
2810
|
const k = 1024;
|
|
@@ -2021,9 +2862,9 @@ var FileUpload = ({
|
|
|
2021
2862
|
setFiles(newFiles);
|
|
2022
2863
|
onChange?.(newFiles);
|
|
2023
2864
|
};
|
|
2024
|
-
return /* @__PURE__ */
|
|
2025
|
-
label && /* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
2865
|
+
return /* @__PURE__ */ jsxs29("div", { className: `w-full ${className}`, children: [
|
|
2866
|
+
label && /* @__PURE__ */ jsx64("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: label }),
|
|
2867
|
+
/* @__PURE__ */ jsxs29(
|
|
2027
2868
|
"div",
|
|
2028
2869
|
{
|
|
2029
2870
|
onDrop: handleDrop,
|
|
@@ -2032,7 +2873,7 @@ var FileUpload = ({
|
|
|
2032
2873
|
onClick: handleClick,
|
|
2033
2874
|
className: `relative border-2 border-dashed rounded-lg p-8 text-center cursor-pointer transition-all ${isDragging ? "border-blue-500 bg-blue-50 dark:bg-blue-900/20" : "border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500"} ${disabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
2034
2875
|
children: [
|
|
2035
|
-
/* @__PURE__ */
|
|
2876
|
+
/* @__PURE__ */ jsx64(
|
|
2036
2877
|
"input",
|
|
2037
2878
|
{
|
|
2038
2879
|
ref: fileInputRef,
|
|
@@ -2044,14 +2885,14 @@ var FileUpload = ({
|
|
|
2044
2885
|
className: "hidden"
|
|
2045
2886
|
}
|
|
2046
2887
|
),
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2049
|
-
/* @__PURE__ */
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
/* @__PURE__ */
|
|
2888
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex flex-col items-center gap-2", children: [
|
|
2889
|
+
/* @__PURE__ */ jsx64("div", { className: "w-12 h-12 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center", children: /* @__PURE__ */ jsx64(UploadIcon, { size: "lg", className: "text-gray-400 dark:text-gray-500" }) }),
|
|
2890
|
+
/* @__PURE__ */ jsxs29("div", { children: [
|
|
2891
|
+
/* @__PURE__ */ jsxs29("p", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: [
|
|
2892
|
+
/* @__PURE__ */ jsx64("span", { className: "text-blue-600 dark:text-blue-400", children: "Click to upload" }),
|
|
2052
2893
|
" or drag and drop"
|
|
2053
2894
|
] }),
|
|
2054
|
-
/* @__PURE__ */
|
|
2895
|
+
/* @__PURE__ */ jsxs29("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: [
|
|
2055
2896
|
accept ? `Accepted: ${accept}` : "Any file type",
|
|
2056
2897
|
maxSize && ` \u2022 Max size: ${formatFileSize(maxSize)}`
|
|
2057
2898
|
] })
|
|
@@ -2060,17 +2901,17 @@ var FileUpload = ({
|
|
|
2060
2901
|
]
|
|
2061
2902
|
}
|
|
2062
2903
|
),
|
|
2063
|
-
helperText && /* @__PURE__ */
|
|
2064
|
-
files.length > 0 && /* @__PURE__ */
|
|
2904
|
+
helperText && /* @__PURE__ */ jsx64("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: helperText }),
|
|
2905
|
+
files.length > 0 && /* @__PURE__ */ jsx64("div", { className: "mt-4 space-y-2", children: files.map((file, index) => /* @__PURE__ */ jsxs29(
|
|
2065
2906
|
"div",
|
|
2066
2907
|
{
|
|
2067
2908
|
className: "flex items-center justify-between p-3 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700",
|
|
2068
2909
|
children: [
|
|
2069
|
-
/* @__PURE__ */
|
|
2070
|
-
/* @__PURE__ */
|
|
2071
|
-
/* @__PURE__ */
|
|
2910
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex-1 min-w-0", children: [
|
|
2911
|
+
/* @__PURE__ */ jsx64("p", { className: "text-sm font-medium text-gray-900 dark:text-gray-100 truncate", children: file.name }),
|
|
2912
|
+
/* @__PURE__ */ jsx64("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: formatFileSize(file.size) })
|
|
2072
2913
|
] }),
|
|
2073
|
-
/* @__PURE__ */
|
|
2914
|
+
/* @__PURE__ */ jsx64(
|
|
2074
2915
|
"button",
|
|
2075
2916
|
{
|
|
2076
2917
|
onClick: (e) => {
|
|
@@ -2079,7 +2920,7 @@ var FileUpload = ({
|
|
|
2079
2920
|
},
|
|
2080
2921
|
className: "ml-4 text-gray-400 hover:text-red-600 dark:hover:text-red-400 transition-colors",
|
|
2081
2922
|
"aria-label": "Remove file",
|
|
2082
|
-
children: /* @__PURE__ */
|
|
2923
|
+
children: /* @__PURE__ */ jsx64(CloseIcon, { size: "sm" })
|
|
2083
2924
|
}
|
|
2084
2925
|
)
|
|
2085
2926
|
]
|
|
@@ -2130,6 +2971,7 @@ export {
|
|
|
2130
2971
|
Badge,
|
|
2131
2972
|
BellIcon,
|
|
2132
2973
|
Button,
|
|
2974
|
+
Calendar,
|
|
2133
2975
|
CalendarIcon,
|
|
2134
2976
|
CameraIcon,
|
|
2135
2977
|
Card,
|
|
@@ -2156,6 +2998,7 @@ export {
|
|
|
2156
2998
|
MenuIcon,
|
|
2157
2999
|
Modal,
|
|
2158
3000
|
Navbar,
|
|
3001
|
+
NumberInput,
|
|
2159
3002
|
Pagination,
|
|
2160
3003
|
PlusIcon,
|
|
2161
3004
|
ProgressBar,
|