@marcoschwartz/lite-ui 0.7.0 → 0.8.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 +36 -7
- package/dist/index.d.ts +36 -7
- package/dist/index.js +938 -225
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +938 -226
- 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
|
|
|
@@ -927,7 +936,8 @@ TextInput.displayName = "TextInput";
|
|
|
927
936
|
|
|
928
937
|
// src/components/ActionMenu.tsx
|
|
929
938
|
import { useState as useState5, useRef as useRef2, useEffect as useEffect5 } from "react";
|
|
930
|
-
import {
|
|
939
|
+
import { createPortal } from "react-dom";
|
|
940
|
+
import { Fragment as Fragment6, jsx as jsx41, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
931
941
|
var ActionMenu = ({
|
|
932
942
|
items,
|
|
933
943
|
trigger,
|
|
@@ -935,10 +945,16 @@ var ActionMenu = ({
|
|
|
935
945
|
}) => {
|
|
936
946
|
const { themeName } = useTheme();
|
|
937
947
|
const [isOpen, setIsOpen] = useState5(false);
|
|
948
|
+
const [menuPosition, setMenuPosition] = useState5(null);
|
|
949
|
+
const [mounted, setMounted] = useState5(false);
|
|
938
950
|
const menuRef = useRef2(null);
|
|
951
|
+
const triggerRef = useRef2(null);
|
|
952
|
+
useEffect5(() => {
|
|
953
|
+
setMounted(true);
|
|
954
|
+
}, []);
|
|
939
955
|
useEffect5(() => {
|
|
940
956
|
const handleClickOutside = (event) => {
|
|
941
|
-
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
957
|
+
if (menuRef.current && !menuRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
|
|
942
958
|
setIsOpen(false);
|
|
943
959
|
}
|
|
944
960
|
};
|
|
@@ -947,7 +963,20 @@ var ActionMenu = ({
|
|
|
947
963
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
948
964
|
}
|
|
949
965
|
}, [isOpen]);
|
|
966
|
+
useEffect5(() => {
|
|
967
|
+
if (isOpen && triggerRef.current) {
|
|
968
|
+
const rect = triggerRef.current.getBoundingClientRect();
|
|
969
|
+
const menuWidth = 224;
|
|
970
|
+
setMenuPosition({
|
|
971
|
+
top: rect.bottom + 8,
|
|
972
|
+
left: position === "left" ? rect.left : rect.right - menuWidth
|
|
973
|
+
});
|
|
974
|
+
} else {
|
|
975
|
+
setMenuPosition(null);
|
|
976
|
+
}
|
|
977
|
+
}, [isOpen, position]);
|
|
950
978
|
const handleItemClick = (item) => {
|
|
979
|
+
if (item.type === "divider") return;
|
|
951
980
|
if (!item.disabled) {
|
|
952
981
|
item.onClick();
|
|
953
982
|
setIsOpen(false);
|
|
@@ -963,15 +992,27 @@ var ActionMenu = ({
|
|
|
963
992
|
);
|
|
964
993
|
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";
|
|
965
994
|
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";
|
|
966
|
-
const
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
{
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
995
|
+
const menu = isOpen && mounted && menuPosition ? /* @__PURE__ */ jsx41(
|
|
996
|
+
"div",
|
|
997
|
+
{
|
|
998
|
+
ref: menuRef,
|
|
999
|
+
className: `fixed w-56 rounded-lg ${menuBaseStyles} z-[9999] max-h-[80vh] overflow-auto`,
|
|
1000
|
+
style: {
|
|
1001
|
+
minWidth: "14rem",
|
|
1002
|
+
top: `${menuPosition.top}px`,
|
|
1003
|
+
left: `${menuPosition.left}px`
|
|
1004
|
+
},
|
|
1005
|
+
children: items.map((item, index) => {
|
|
1006
|
+
if (item.type === "divider") {
|
|
1007
|
+
return /* @__PURE__ */ jsx41(
|
|
1008
|
+
"div",
|
|
1009
|
+
{
|
|
1010
|
+
className: "my-1 border-t border-gray-200 dark:border-gray-700"
|
|
1011
|
+
},
|
|
1012
|
+
index
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
1015
|
+
return /* @__PURE__ */ jsxs10(
|
|
975
1016
|
"button",
|
|
976
1017
|
{
|
|
977
1018
|
onClick: () => handleItemClick(item),
|
|
@@ -983,9 +1024,13 @@ var ActionMenu = ({
|
|
|
983
1024
|
]
|
|
984
1025
|
},
|
|
985
1026
|
index
|
|
986
|
-
)
|
|
987
|
-
}
|
|
988
|
-
|
|
1027
|
+
);
|
|
1028
|
+
})
|
|
1029
|
+
}
|
|
1030
|
+
) : null;
|
|
1031
|
+
return /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
1032
|
+
/* @__PURE__ */ jsx41("div", { className: "relative inline-block", ref: triggerRef, children: /* @__PURE__ */ jsx41("div", { onClick: () => setIsOpen(!isOpen), children: trigger || defaultTrigger }) }),
|
|
1033
|
+
mounted && createPortal(menu, document.body)
|
|
989
1034
|
] });
|
|
990
1035
|
};
|
|
991
1036
|
|
|
@@ -1245,33 +1290,42 @@ function Table({
|
|
|
1245
1290
|
const { theme } = useTheme();
|
|
1246
1291
|
return /* @__PURE__ */ jsxs15("div", { className: `overflow-x-auto ${className}`, children: [
|
|
1247
1292
|
/* @__PURE__ */ jsxs15("table", { className: "w-full text-left", children: [
|
|
1248
|
-
/* @__PURE__ */ jsx49("thead", { className: "bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx49("tr", { children: columns.map((column) =>
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1293
|
+
/* @__PURE__ */ jsx49("thead", { className: "bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700", children: /* @__PURE__ */ jsx49("tr", { children: columns.map((column, colIndex) => {
|
|
1294
|
+
const isLast = colIndex === columns.length - 1;
|
|
1295
|
+
return /* @__PURE__ */ jsx49(
|
|
1296
|
+
"th",
|
|
1297
|
+
{
|
|
1298
|
+
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",
|
|
1299
|
+
style: { width: column.width },
|
|
1300
|
+
children: column.title
|
|
1301
|
+
},
|
|
1302
|
+
column.key
|
|
1303
|
+
);
|
|
1304
|
+
}) }) }),
|
|
1305
|
+
/* @__PURE__ */ jsx49("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children: data.map((row, rowIndex) => {
|
|
1306
|
+
const rowClasses = [
|
|
1307
|
+
striped && rowIndex % 2 === 1 ? "bg-gray-50 dark:bg-gray-800/50" : "",
|
|
1308
|
+
hoverable ? "hover:bg-gray-100 dark:hover:bg-gray-800 transition-colors" : ""
|
|
1309
|
+
].filter(Boolean).join(" ");
|
|
1310
|
+
return /* @__PURE__ */ jsx49(
|
|
1311
|
+
"tr",
|
|
1312
|
+
{
|
|
1313
|
+
className: rowClasses,
|
|
1314
|
+
children: columns.map((column, colIndex) => {
|
|
1315
|
+
const isLast = colIndex === columns.length - 1;
|
|
1316
|
+
return /* @__PURE__ */ jsx49(
|
|
1317
|
+
"td",
|
|
1318
|
+
{
|
|
1319
|
+
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",
|
|
1320
|
+
children: column.render ? column.render(row[column.key], row, rowIndex) : row[column.key]
|
|
1321
|
+
},
|
|
1322
|
+
column.key
|
|
1323
|
+
);
|
|
1324
|
+
})
|
|
1325
|
+
},
|
|
1326
|
+
row[keyField] || rowIndex
|
|
1327
|
+
);
|
|
1328
|
+
}) })
|
|
1275
1329
|
] }),
|
|
1276
1330
|
data.length === 0 && /* @__PURE__ */ jsx49("div", { className: "text-center py-8 text-gray-500 dark:text-gray-400", children: "No data available" })
|
|
1277
1331
|
] });
|
|
@@ -1367,37 +1421,227 @@ var Pagination = ({
|
|
|
1367
1421
|
};
|
|
1368
1422
|
|
|
1369
1423
|
// src/components/DatePicker.tsx
|
|
1370
|
-
import {
|
|
1424
|
+
import { useState as useState7, useRef as useRef3, useEffect as useEffect6 } from "react";
|
|
1425
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1371
1426
|
import { jsx as jsx51, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1372
|
-
var
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1427
|
+
var DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1428
|
+
var MONTHS = [
|
|
1429
|
+
"January",
|
|
1430
|
+
"February",
|
|
1431
|
+
"March",
|
|
1432
|
+
"April",
|
|
1433
|
+
"May",
|
|
1434
|
+
"June",
|
|
1435
|
+
"July",
|
|
1436
|
+
"August",
|
|
1437
|
+
"September",
|
|
1438
|
+
"October",
|
|
1439
|
+
"November",
|
|
1440
|
+
"December"
|
|
1441
|
+
];
|
|
1442
|
+
var DatePicker = ({
|
|
1443
|
+
label,
|
|
1444
|
+
error,
|
|
1445
|
+
helperText,
|
|
1446
|
+
value,
|
|
1447
|
+
onChange,
|
|
1448
|
+
minDate,
|
|
1449
|
+
maxDate,
|
|
1450
|
+
disabled,
|
|
1451
|
+
className = "",
|
|
1452
|
+
placeholder = "Select date..."
|
|
1453
|
+
}) => {
|
|
1454
|
+
const { theme } = useTheme();
|
|
1455
|
+
const [isOpen, setIsOpen] = useState7(false);
|
|
1456
|
+
const [viewDate, setViewDate] = useState7(value || /* @__PURE__ */ new Date());
|
|
1457
|
+
const [mounted, setMounted] = useState7(false);
|
|
1458
|
+
const [calendarPosition, setCalendarPosition] = useState7(null);
|
|
1459
|
+
const inputRef = useRef3(null);
|
|
1460
|
+
const calendarRef = useRef3(null);
|
|
1461
|
+
useEffect6(() => {
|
|
1462
|
+
setMounted(true);
|
|
1463
|
+
}, []);
|
|
1464
|
+
useEffect6(() => {
|
|
1465
|
+
const handleClickOutside = (event) => {
|
|
1466
|
+
if (calendarRef.current && !calendarRef.current.contains(event.target) && inputRef.current && !inputRef.current.contains(event.target)) {
|
|
1467
|
+
setIsOpen(false);
|
|
1468
|
+
}
|
|
1469
|
+
};
|
|
1470
|
+
if (isOpen) {
|
|
1471
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1472
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1473
|
+
}
|
|
1474
|
+
}, [isOpen]);
|
|
1475
|
+
useEffect6(() => {
|
|
1476
|
+
if (isOpen && inputRef.current) {
|
|
1477
|
+
const rect = inputRef.current.getBoundingClientRect();
|
|
1478
|
+
setCalendarPosition({
|
|
1479
|
+
top: rect.bottom + 8,
|
|
1480
|
+
left: rect.left
|
|
1481
|
+
});
|
|
1482
|
+
} else {
|
|
1483
|
+
setCalendarPosition(null);
|
|
1484
|
+
}
|
|
1485
|
+
}, [isOpen]);
|
|
1486
|
+
const year = viewDate.getFullYear();
|
|
1487
|
+
const month = viewDate.getMonth();
|
|
1488
|
+
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
1489
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
1490
|
+
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
1491
|
+
const calendarDays = [];
|
|
1492
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
1493
|
+
calendarDays.push(new Date(year, month - 1, daysInPrevMonth - i));
|
|
1393
1494
|
}
|
|
1394
|
-
)
|
|
1495
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
1496
|
+
calendarDays.push(new Date(year, month, i));
|
|
1497
|
+
}
|
|
1498
|
+
const remainingDays = 42 - calendarDays.length;
|
|
1499
|
+
for (let i = 1; i <= remainingDays; i++) {
|
|
1500
|
+
calendarDays.push(new Date(year, month + 1, i));
|
|
1501
|
+
}
|
|
1502
|
+
const isSameDay = (date1, date2) => {
|
|
1503
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1504
|
+
};
|
|
1505
|
+
const isToday = (date) => {
|
|
1506
|
+
return isSameDay(date, /* @__PURE__ */ new Date());
|
|
1507
|
+
};
|
|
1508
|
+
const isSelected = (date) => {
|
|
1509
|
+
return value && isSameDay(date, value);
|
|
1510
|
+
};
|
|
1511
|
+
const isCurrentMonth = (date) => {
|
|
1512
|
+
return date.getMonth() === month;
|
|
1513
|
+
};
|
|
1514
|
+
const isDisabled = (date) => {
|
|
1515
|
+
if (minDate && date < minDate) return true;
|
|
1516
|
+
if (maxDate && date > maxDate) return true;
|
|
1517
|
+
return false;
|
|
1518
|
+
};
|
|
1519
|
+
const handleDateClick = (date) => {
|
|
1520
|
+
if (isDisabled(date)) return;
|
|
1521
|
+
onChange?.(date);
|
|
1522
|
+
setIsOpen(false);
|
|
1523
|
+
};
|
|
1524
|
+
const handlePrevMonth = () => {
|
|
1525
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
1526
|
+
};
|
|
1527
|
+
const handleNextMonth = () => {
|
|
1528
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
1529
|
+
};
|
|
1530
|
+
const handleToday = () => {
|
|
1531
|
+
const today = /* @__PURE__ */ new Date();
|
|
1532
|
+
setViewDate(today);
|
|
1533
|
+
onChange?.(today);
|
|
1534
|
+
setIsOpen(false);
|
|
1535
|
+
};
|
|
1536
|
+
const formatDate = (date) => {
|
|
1537
|
+
if (!date) return "";
|
|
1538
|
+
return date.toLocaleDateString("en-US", {
|
|
1539
|
+
month: "short",
|
|
1540
|
+
day: "numeric",
|
|
1541
|
+
year: "numeric"
|
|
1542
|
+
});
|
|
1543
|
+
};
|
|
1544
|
+
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";
|
|
1545
|
+
const errorStyles = error ? "border-red-500 focus:ring-red-500 dark:border-red-500" : "";
|
|
1546
|
+
const disabledStyles = disabled ? "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900" : "";
|
|
1547
|
+
const calendar = isOpen && mounted && calendarPosition ? /* @__PURE__ */ jsxs17(
|
|
1548
|
+
"div",
|
|
1549
|
+
{
|
|
1550
|
+
ref: calendarRef,
|
|
1551
|
+
className: "fixed z-[9999] bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4",
|
|
1552
|
+
style: {
|
|
1553
|
+
top: `${calendarPosition.top}px`,
|
|
1554
|
+
left: `${calendarPosition.left}px`,
|
|
1555
|
+
minWidth: "320px"
|
|
1556
|
+
},
|
|
1557
|
+
children: [
|
|
1558
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center justify-between mb-4", children: [
|
|
1559
|
+
/* @__PURE__ */ jsx51(
|
|
1560
|
+
"button",
|
|
1561
|
+
{
|
|
1562
|
+
onClick: handlePrevMonth,
|
|
1563
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
1564
|
+
"aria-label": "Previous month",
|
|
1565
|
+
children: /* @__PURE__ */ jsx51("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx51("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
1566
|
+
}
|
|
1567
|
+
),
|
|
1568
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
1569
|
+
/* @__PURE__ */ jsxs17("h2", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: [
|
|
1570
|
+
MONTHS[month],
|
|
1571
|
+
" ",
|
|
1572
|
+
year
|
|
1573
|
+
] }),
|
|
1574
|
+
/* @__PURE__ */ jsx51(
|
|
1575
|
+
"button",
|
|
1576
|
+
{
|
|
1577
|
+
onClick: handleToday,
|
|
1578
|
+
className: "px-2 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors",
|
|
1579
|
+
children: "Today"
|
|
1580
|
+
}
|
|
1581
|
+
)
|
|
1582
|
+
] }),
|
|
1583
|
+
/* @__PURE__ */ jsx51(
|
|
1584
|
+
"button",
|
|
1585
|
+
{
|
|
1586
|
+
onClick: handleNextMonth,
|
|
1587
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
1588
|
+
"aria-label": "Next month",
|
|
1589
|
+
children: /* @__PURE__ */ jsx51("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx51("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
1590
|
+
}
|
|
1591
|
+
)
|
|
1592
|
+
] }),
|
|
1593
|
+
/* @__PURE__ */ jsx51("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS.map((day) => /* @__PURE__ */ jsx51("div", { className: "text-center text-xs font-semibold text-gray-600 dark:text-gray-400 py-1", children: day }, day)) }),
|
|
1594
|
+
/* @__PURE__ */ jsx51("div", { className: "grid grid-cols-7 gap-1", children: calendarDays.map((date, index) => {
|
|
1595
|
+
const isCurrentMonthDay = isCurrentMonth(date);
|
|
1596
|
+
const isTodayDay = isToday(date);
|
|
1597
|
+
const isSelectedDay = isSelected(date);
|
|
1598
|
+
const isDisabledDay = isDisabled(date);
|
|
1599
|
+
return /* @__PURE__ */ jsx51(
|
|
1600
|
+
"button",
|
|
1601
|
+
{
|
|
1602
|
+
onClick: () => handleDateClick(date),
|
|
1603
|
+
disabled: isDisabledDay,
|
|
1604
|
+
className: `
|
|
1605
|
+
aspect-square p-1 rounded-lg text-sm font-medium transition-all
|
|
1606
|
+
${!isCurrentMonthDay ? "text-gray-400 dark:text-gray-600" : "text-gray-900 dark:text-gray-100"}
|
|
1607
|
+
${isTodayDay && !isSelectedDay ? "bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-bold" : ""}
|
|
1608
|
+
${isSelectedDay ? "bg-blue-600 text-white hover:bg-blue-700" : ""}
|
|
1609
|
+
${!isSelectedDay && !isDisabledDay ? "hover:bg-gray-100 dark:hover:bg-gray-700" : ""}
|
|
1610
|
+
${isDisabledDay ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}
|
|
1611
|
+
`,
|
|
1612
|
+
children: date.getDate()
|
|
1613
|
+
},
|
|
1614
|
+
index
|
|
1615
|
+
);
|
|
1616
|
+
}) })
|
|
1617
|
+
]
|
|
1618
|
+
}
|
|
1619
|
+
) : null;
|
|
1620
|
+
return /* @__PURE__ */ jsxs17("div", { className, children: [
|
|
1621
|
+
label && /* @__PURE__ */ jsx51("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
1622
|
+
/* @__PURE__ */ jsxs17(
|
|
1623
|
+
"div",
|
|
1624
|
+
{
|
|
1625
|
+
ref: inputRef,
|
|
1626
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
1627
|
+
className: `${baseStyles} ${errorStyles} ${disabledStyles} flex items-center justify-between`.trim(),
|
|
1628
|
+
children: [
|
|
1629
|
+
/* @__PURE__ */ jsx51("span", { className: !value ? "text-gray-500 dark:text-gray-400" : "", children: value ? formatDate(value) : placeholder }),
|
|
1630
|
+
/* @__PURE__ */ jsx51("svg", { className: "w-5 h-5 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx51("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" }) })
|
|
1631
|
+
]
|
|
1632
|
+
}
|
|
1633
|
+
),
|
|
1634
|
+
error && /* @__PURE__ */ jsx51("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
1635
|
+
helperText && !error && /* @__PURE__ */ jsx51("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText }),
|
|
1636
|
+
mounted && createPortal2(calendar, document.body)
|
|
1637
|
+
] });
|
|
1638
|
+
};
|
|
1395
1639
|
DatePicker.displayName = "DatePicker";
|
|
1396
1640
|
|
|
1397
1641
|
// src/components/TimePicker.tsx
|
|
1398
|
-
import { forwardRef as
|
|
1642
|
+
import { forwardRef as forwardRef4 } from "react";
|
|
1399
1643
|
import { jsx as jsx52, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1400
|
-
var TimePicker =
|
|
1644
|
+
var TimePicker = forwardRef4(
|
|
1401
1645
|
({ label, error, helperText, className = "", disabled, ...props }, ref) => {
|
|
1402
1646
|
const { theme } = useTheme();
|
|
1403
1647
|
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";
|
|
@@ -1423,36 +1667,503 @@ var TimePicker = forwardRef5(
|
|
|
1423
1667
|
TimePicker.displayName = "TimePicker";
|
|
1424
1668
|
|
|
1425
1669
|
// src/components/DateTimePicker.tsx
|
|
1426
|
-
import {
|
|
1670
|
+
import { useState as useState8, useRef as useRef4, useEffect as useEffect7 } from "react";
|
|
1671
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
1427
1672
|
import { jsx as jsx53, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1428
|
-
var
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1673
|
+
var DAYS2 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1674
|
+
var MONTHS2 = [
|
|
1675
|
+
"January",
|
|
1676
|
+
"February",
|
|
1677
|
+
"March",
|
|
1678
|
+
"April",
|
|
1679
|
+
"May",
|
|
1680
|
+
"June",
|
|
1681
|
+
"July",
|
|
1682
|
+
"August",
|
|
1683
|
+
"September",
|
|
1684
|
+
"October",
|
|
1685
|
+
"November",
|
|
1686
|
+
"December"
|
|
1687
|
+
];
|
|
1688
|
+
var DateTimePicker = ({
|
|
1689
|
+
label,
|
|
1690
|
+
error,
|
|
1691
|
+
helperText,
|
|
1692
|
+
value,
|
|
1693
|
+
onChange,
|
|
1694
|
+
minDate,
|
|
1695
|
+
maxDate,
|
|
1696
|
+
disabled,
|
|
1697
|
+
className = "",
|
|
1698
|
+
placeholder = "Select date and time..."
|
|
1699
|
+
}) => {
|
|
1700
|
+
const { theme } = useTheme();
|
|
1701
|
+
const [isOpen, setIsOpen] = useState8(false);
|
|
1702
|
+
const [viewDate, setViewDate] = useState8(value || /* @__PURE__ */ new Date());
|
|
1703
|
+
const [selectedTime, setSelectedTime] = useState8(
|
|
1704
|
+
value ? { hours: value.getHours(), minutes: value.getMinutes() } : { hours: 12, minutes: 0 }
|
|
1705
|
+
);
|
|
1706
|
+
const [mounted, setMounted] = useState8(false);
|
|
1707
|
+
const [pickerPosition, setPickerPosition] = useState8(null);
|
|
1708
|
+
const inputRef = useRef4(null);
|
|
1709
|
+
const pickerRef = useRef4(null);
|
|
1710
|
+
useEffect7(() => {
|
|
1711
|
+
setMounted(true);
|
|
1712
|
+
}, []);
|
|
1713
|
+
useEffect7(() => {
|
|
1714
|
+
const handleClickOutside = (event) => {
|
|
1715
|
+
if (pickerRef.current && !pickerRef.current.contains(event.target) && inputRef.current && !inputRef.current.contains(event.target)) {
|
|
1716
|
+
setIsOpen(false);
|
|
1717
|
+
}
|
|
1718
|
+
};
|
|
1719
|
+
if (isOpen) {
|
|
1720
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1721
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1722
|
+
}
|
|
1723
|
+
}, [isOpen]);
|
|
1724
|
+
useEffect7(() => {
|
|
1725
|
+
if (isOpen && inputRef.current) {
|
|
1726
|
+
const rect = inputRef.current.getBoundingClientRect();
|
|
1727
|
+
setPickerPosition({
|
|
1728
|
+
top: rect.bottom + 8,
|
|
1729
|
+
left: rect.left
|
|
1730
|
+
});
|
|
1731
|
+
} else {
|
|
1732
|
+
setPickerPosition(null);
|
|
1733
|
+
}
|
|
1734
|
+
}, [isOpen]);
|
|
1735
|
+
const year = viewDate.getFullYear();
|
|
1736
|
+
const month = viewDate.getMonth();
|
|
1737
|
+
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
1738
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
1739
|
+
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
1740
|
+
const calendarDays = [];
|
|
1741
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
1742
|
+
calendarDays.push(new Date(year, month - 1, daysInPrevMonth - i));
|
|
1743
|
+
}
|
|
1744
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
1745
|
+
calendarDays.push(new Date(year, month, i));
|
|
1746
|
+
}
|
|
1747
|
+
const remainingDays = 42 - calendarDays.length;
|
|
1748
|
+
for (let i = 1; i <= remainingDays; i++) {
|
|
1749
|
+
calendarDays.push(new Date(year, month + 1, i));
|
|
1750
|
+
}
|
|
1751
|
+
const isSameDay = (date1, date2) => {
|
|
1752
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1753
|
+
};
|
|
1754
|
+
const isToday = (date) => {
|
|
1755
|
+
return isSameDay(date, /* @__PURE__ */ new Date());
|
|
1756
|
+
};
|
|
1757
|
+
const isSelected = (date) => {
|
|
1758
|
+
return value && isSameDay(date, value);
|
|
1759
|
+
};
|
|
1760
|
+
const isCurrentMonth = (date) => {
|
|
1761
|
+
return date.getMonth() === month;
|
|
1762
|
+
};
|
|
1763
|
+
const isDisabled = (date) => {
|
|
1764
|
+
if (minDate && date < minDate) return true;
|
|
1765
|
+
if (maxDate && date > maxDate) return true;
|
|
1766
|
+
return false;
|
|
1767
|
+
};
|
|
1768
|
+
const handleDateClick = (date) => {
|
|
1769
|
+
if (isDisabled(date)) return;
|
|
1770
|
+
const newDateTime = new Date(
|
|
1771
|
+
date.getFullYear(),
|
|
1772
|
+
date.getMonth(),
|
|
1773
|
+
date.getDate(),
|
|
1774
|
+
selectedTime.hours,
|
|
1775
|
+
selectedTime.minutes
|
|
1776
|
+
);
|
|
1777
|
+
onChange?.(newDateTime);
|
|
1778
|
+
};
|
|
1779
|
+
const handleTimeChange = (hours, minutes) => {
|
|
1780
|
+
setSelectedTime({ hours, minutes });
|
|
1781
|
+
if (value) {
|
|
1782
|
+
const newDateTime = new Date(
|
|
1783
|
+
value.getFullYear(),
|
|
1784
|
+
value.getMonth(),
|
|
1785
|
+
value.getDate(),
|
|
1786
|
+
hours,
|
|
1787
|
+
minutes
|
|
1788
|
+
);
|
|
1789
|
+
onChange?.(newDateTime);
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
const handleDone = () => {
|
|
1793
|
+
if (value) {
|
|
1794
|
+
setIsOpen(false);
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
const handlePrevMonth = () => {
|
|
1798
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
1799
|
+
};
|
|
1800
|
+
const handleNextMonth = () => {
|
|
1801
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
1802
|
+
};
|
|
1803
|
+
const handleToday = () => {
|
|
1804
|
+
const now = /* @__PURE__ */ new Date();
|
|
1805
|
+
setViewDate(now);
|
|
1806
|
+
setSelectedTime({ hours: now.getHours(), minutes: now.getMinutes() });
|
|
1807
|
+
onChange?.(now);
|
|
1808
|
+
};
|
|
1809
|
+
const formatDateTime = (date) => {
|
|
1810
|
+
if (!date) return "";
|
|
1811
|
+
return date.toLocaleString("en-US", {
|
|
1812
|
+
month: "short",
|
|
1813
|
+
day: "numeric",
|
|
1814
|
+
year: "numeric",
|
|
1815
|
+
hour: "numeric",
|
|
1816
|
+
minute: "2-digit",
|
|
1817
|
+
hour12: true
|
|
1818
|
+
});
|
|
1819
|
+
};
|
|
1820
|
+
const formatTime = (hours, minutes) => {
|
|
1821
|
+
const period = hours >= 12 ? "PM" : "AM";
|
|
1822
|
+
const displayHours = hours % 12 || 12;
|
|
1823
|
+
const displayMinutes = minutes.toString().padStart(2, "0");
|
|
1824
|
+
return `${displayHours}:${displayMinutes} ${period}`;
|
|
1825
|
+
};
|
|
1826
|
+
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";
|
|
1827
|
+
const errorStyles = error ? "border-red-500 focus:ring-red-500 dark:border-red-500" : "";
|
|
1828
|
+
const disabledStyles = disabled ? "opacity-50 cursor-not-allowed bg-gray-50 dark:bg-gray-900" : "";
|
|
1829
|
+
const picker = isOpen && mounted && pickerPosition ? /* @__PURE__ */ jsxs19(
|
|
1830
|
+
"div",
|
|
1831
|
+
{
|
|
1832
|
+
ref: pickerRef,
|
|
1833
|
+
className: "fixed z-[9999] bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 shadow-xl p-4",
|
|
1834
|
+
style: {
|
|
1835
|
+
top: `${pickerPosition.top}px`,
|
|
1836
|
+
left: `${pickerPosition.left}px`,
|
|
1837
|
+
minWidth: "360px"
|
|
1838
|
+
},
|
|
1839
|
+
children: [
|
|
1840
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between mb-4", children: [
|
|
1841
|
+
/* @__PURE__ */ jsx53(
|
|
1842
|
+
"button",
|
|
1843
|
+
{
|
|
1844
|
+
onClick: handlePrevMonth,
|
|
1845
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
1846
|
+
"aria-label": "Previous month",
|
|
1847
|
+
children: /* @__PURE__ */ jsx53("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx53("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
|
|
1848
|
+
}
|
|
1849
|
+
),
|
|
1850
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2", children: [
|
|
1851
|
+
/* @__PURE__ */ jsxs19("h2", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: [
|
|
1852
|
+
MONTHS2[month],
|
|
1853
|
+
" ",
|
|
1854
|
+
year
|
|
1855
|
+
] }),
|
|
1856
|
+
/* @__PURE__ */ jsx53(
|
|
1857
|
+
"button",
|
|
1858
|
+
{
|
|
1859
|
+
onClick: handleToday,
|
|
1860
|
+
className: "px-2 py-1 text-xs bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors",
|
|
1861
|
+
children: "Now"
|
|
1862
|
+
}
|
|
1863
|
+
)
|
|
1864
|
+
] }),
|
|
1865
|
+
/* @__PURE__ */ jsx53(
|
|
1866
|
+
"button",
|
|
1867
|
+
{
|
|
1868
|
+
onClick: handleNextMonth,
|
|
1869
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
1870
|
+
"aria-label": "Next month",
|
|
1871
|
+
children: /* @__PURE__ */ jsx53("svg", { className: "w-5 h-5 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx53("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) })
|
|
1872
|
+
}
|
|
1873
|
+
)
|
|
1874
|
+
] }),
|
|
1875
|
+
/* @__PURE__ */ jsx53("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS2.map((day) => /* @__PURE__ */ jsx53("div", { className: "text-center text-xs font-semibold text-gray-600 dark:text-gray-400 py-1", children: day }, day)) }),
|
|
1876
|
+
/* @__PURE__ */ jsx53("div", { className: "grid grid-cols-7 gap-1 mb-4", children: calendarDays.map((date, index) => {
|
|
1877
|
+
const isCurrentMonthDay = isCurrentMonth(date);
|
|
1878
|
+
const isTodayDay = isToday(date);
|
|
1879
|
+
const isSelectedDay = isSelected(date);
|
|
1880
|
+
const isDisabledDay = isDisabled(date);
|
|
1881
|
+
return /* @__PURE__ */ jsx53(
|
|
1882
|
+
"button",
|
|
1883
|
+
{
|
|
1884
|
+
onClick: () => handleDateClick(date),
|
|
1885
|
+
disabled: isDisabledDay,
|
|
1886
|
+
className: `
|
|
1887
|
+
aspect-square p-1 rounded-lg text-sm font-medium transition-all
|
|
1888
|
+
${!isCurrentMonthDay ? "text-gray-400 dark:text-gray-600" : "text-gray-900 dark:text-gray-100"}
|
|
1889
|
+
${isTodayDay && !isSelectedDay ? "bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-bold" : ""}
|
|
1890
|
+
${isSelectedDay ? "bg-blue-600 text-white hover:bg-blue-700" : ""}
|
|
1891
|
+
${!isSelectedDay && !isDisabledDay ? "hover:bg-gray-100 dark:hover:bg-gray-700" : ""}
|
|
1892
|
+
${isDisabledDay ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}
|
|
1893
|
+
`,
|
|
1894
|
+
children: date.getDate()
|
|
1895
|
+
},
|
|
1896
|
+
index
|
|
1897
|
+
);
|
|
1898
|
+
}) }),
|
|
1899
|
+
/* @__PURE__ */ jsxs19("div", { className: "border-t border-gray-200 dark:border-gray-700 pt-4", children: [
|
|
1900
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-center gap-4 mb-4", children: [
|
|
1901
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col items-center", children: [
|
|
1902
|
+
/* @__PURE__ */ jsx53("label", { className: "text-xs font-semibold text-gray-600 dark:text-gray-400 mb-2", children: "Hour" }),
|
|
1903
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col items-center gap-1", children: [
|
|
1904
|
+
/* @__PURE__ */ jsx53(
|
|
1905
|
+
"button",
|
|
1906
|
+
{
|
|
1907
|
+
type: "button",
|
|
1908
|
+
onClick: () => handleTimeChange((selectedTime.hours + 1) % 24, selectedTime.minutes),
|
|
1909
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
1910
|
+
children: /* @__PURE__ */ jsx53("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx53("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) })
|
|
1911
|
+
}
|
|
1912
|
+
),
|
|
1913
|
+
/* @__PURE__ */ jsx53(
|
|
1914
|
+
"input",
|
|
1915
|
+
{
|
|
1916
|
+
type: "number",
|
|
1917
|
+
min: "0",
|
|
1918
|
+
max: "23",
|
|
1919
|
+
value: selectedTime.hours,
|
|
1920
|
+
onChange: (e) => {
|
|
1921
|
+
const val = parseInt(e.target.value);
|
|
1922
|
+
if (!isNaN(val) && val >= 0 && val <= 23) {
|
|
1923
|
+
handleTimeChange(val, selectedTime.minutes);
|
|
1924
|
+
}
|
|
1925
|
+
},
|
|
1926
|
+
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"
|
|
1927
|
+
}
|
|
1928
|
+
),
|
|
1929
|
+
/* @__PURE__ */ jsx53(
|
|
1930
|
+
"button",
|
|
1931
|
+
{
|
|
1932
|
+
type: "button",
|
|
1933
|
+
onClick: () => handleTimeChange((selectedTime.hours - 1 + 24) % 24, selectedTime.minutes),
|
|
1934
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
1935
|
+
children: /* @__PURE__ */ jsx53("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx53("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
|
|
1936
|
+
}
|
|
1937
|
+
)
|
|
1938
|
+
] })
|
|
1939
|
+
] }),
|
|
1940
|
+
/* @__PURE__ */ jsx53("span", { className: "text-2xl font-bold text-gray-600 dark:text-gray-400 mt-8", children: ":" }),
|
|
1941
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col items-center", children: [
|
|
1942
|
+
/* @__PURE__ */ jsx53("label", { className: "text-xs font-semibold text-gray-600 dark:text-gray-400 mb-2", children: "Minute" }),
|
|
1943
|
+
/* @__PURE__ */ jsxs19("div", { className: "flex flex-col items-center gap-1", children: [
|
|
1944
|
+
/* @__PURE__ */ jsx53(
|
|
1945
|
+
"button",
|
|
1946
|
+
{
|
|
1947
|
+
type: "button",
|
|
1948
|
+
onClick: () => handleTimeChange(selectedTime.hours, (selectedTime.minutes + 1) % 60),
|
|
1949
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
1950
|
+
children: /* @__PURE__ */ jsx53("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx53("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 15l7-7 7 7" }) })
|
|
1951
|
+
}
|
|
1952
|
+
),
|
|
1953
|
+
/* @__PURE__ */ jsx53(
|
|
1954
|
+
"input",
|
|
1955
|
+
{
|
|
1956
|
+
type: "number",
|
|
1957
|
+
min: "0",
|
|
1958
|
+
max: "59",
|
|
1959
|
+
value: selectedTime.minutes,
|
|
1960
|
+
onChange: (e) => {
|
|
1961
|
+
const val = parseInt(e.target.value);
|
|
1962
|
+
if (!isNaN(val) && val >= 0 && val <= 59) {
|
|
1963
|
+
handleTimeChange(selectedTime.hours, val);
|
|
1964
|
+
}
|
|
1965
|
+
},
|
|
1966
|
+
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"
|
|
1967
|
+
}
|
|
1968
|
+
),
|
|
1969
|
+
/* @__PURE__ */ jsx53(
|
|
1970
|
+
"button",
|
|
1971
|
+
{
|
|
1972
|
+
type: "button",
|
|
1973
|
+
onClick: () => handleTimeChange(selectedTime.hours, (selectedTime.minutes - 1 + 60) % 60),
|
|
1974
|
+
className: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded transition-colors",
|
|
1975
|
+
children: /* @__PURE__ */ jsx53("svg", { className: "w-4 h-4 text-gray-600 dark:text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx53("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })
|
|
1976
|
+
}
|
|
1977
|
+
)
|
|
1978
|
+
] })
|
|
1979
|
+
] })
|
|
1980
|
+
] }),
|
|
1981
|
+
/* @__PURE__ */ jsx53("div", { className: "text-center text-sm text-gray-600 dark:text-gray-400 mb-4", children: formatTime(selectedTime.hours, selectedTime.minutes) }),
|
|
1982
|
+
/* @__PURE__ */ jsx53(
|
|
1983
|
+
"button",
|
|
1984
|
+
{
|
|
1985
|
+
onClick: handleDone,
|
|
1986
|
+
className: "w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium",
|
|
1987
|
+
children: "Done"
|
|
1988
|
+
}
|
|
1989
|
+
)
|
|
1990
|
+
] })
|
|
1991
|
+
]
|
|
1992
|
+
}
|
|
1993
|
+
) : null;
|
|
1994
|
+
return /* @__PURE__ */ jsxs19("div", { className, children: [
|
|
1995
|
+
label && /* @__PURE__ */ jsx53("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
1996
|
+
/* @__PURE__ */ jsxs19(
|
|
1997
|
+
"div",
|
|
1998
|
+
{
|
|
1999
|
+
ref: inputRef,
|
|
2000
|
+
onClick: () => !disabled && setIsOpen(!isOpen),
|
|
2001
|
+
className: `${baseStyles} ${errorStyles} ${disabledStyles} flex items-center justify-between`.trim(),
|
|
2002
|
+
children: [
|
|
2003
|
+
/* @__PURE__ */ jsx53("span", { className: !value ? "text-gray-500 dark:text-gray-400" : "", children: value ? formatDateTime(value) : placeholder }),
|
|
2004
|
+
/* @__PURE__ */ jsx53("svg", { className: "w-5 h-5 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx53("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" }) })
|
|
2005
|
+
]
|
|
2006
|
+
}
|
|
2007
|
+
),
|
|
2008
|
+
error && /* @__PURE__ */ jsx53("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
2009
|
+
helperText && !error && /* @__PURE__ */ jsx53("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText }),
|
|
2010
|
+
mounted && createPortal3(picker, document.body)
|
|
2011
|
+
] });
|
|
2012
|
+
};
|
|
2013
|
+
DateTimePicker.displayName = "DateTimePicker";
|
|
2014
|
+
|
|
2015
|
+
// src/components/Calendar.tsx
|
|
2016
|
+
import { useState as useState9 } from "react";
|
|
2017
|
+
import { jsx as jsx54, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
2018
|
+
var DAYS3 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
2019
|
+
var MONTHS3 = [
|
|
2020
|
+
"January",
|
|
2021
|
+
"February",
|
|
2022
|
+
"March",
|
|
2023
|
+
"April",
|
|
2024
|
+
"May",
|
|
2025
|
+
"June",
|
|
2026
|
+
"July",
|
|
2027
|
+
"August",
|
|
2028
|
+
"September",
|
|
2029
|
+
"October",
|
|
2030
|
+
"November",
|
|
2031
|
+
"December"
|
|
2032
|
+
];
|
|
2033
|
+
var Calendar = ({
|
|
2034
|
+
value,
|
|
2035
|
+
onChange,
|
|
2036
|
+
minDate,
|
|
2037
|
+
maxDate,
|
|
2038
|
+
className = ""
|
|
2039
|
+
}) => {
|
|
2040
|
+
const { theme } = useTheme();
|
|
2041
|
+
const [currentDate, setCurrentDate] = useState9(value || /* @__PURE__ */ new Date());
|
|
2042
|
+
const [viewDate, setViewDate] = useState9(value || /* @__PURE__ */ new Date());
|
|
2043
|
+
const year = viewDate.getFullYear();
|
|
2044
|
+
const month = viewDate.getMonth();
|
|
2045
|
+
const firstDayOfMonth = new Date(year, month, 1).getDay();
|
|
2046
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
2047
|
+
const daysInPrevMonth = new Date(year, month, 0).getDate();
|
|
2048
|
+
const calendarDays = [];
|
|
2049
|
+
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
|
2050
|
+
calendarDays.push(new Date(year, month - 1, daysInPrevMonth - i));
|
|
2051
|
+
}
|
|
2052
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
2053
|
+
calendarDays.push(new Date(year, month, i));
|
|
2054
|
+
}
|
|
2055
|
+
const remainingDays = 42 - calendarDays.length;
|
|
2056
|
+
for (let i = 1; i <= remainingDays; i++) {
|
|
2057
|
+
calendarDays.push(new Date(year, month + 1, i));
|
|
2058
|
+
}
|
|
2059
|
+
const isSameDay = (date1, date2) => {
|
|
2060
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
2061
|
+
};
|
|
2062
|
+
const isToday = (date) => {
|
|
2063
|
+
return isSameDay(date, /* @__PURE__ */ new Date());
|
|
2064
|
+
};
|
|
2065
|
+
const isSelected = (date) => {
|
|
2066
|
+
return value && isSameDay(date, value);
|
|
2067
|
+
};
|
|
2068
|
+
const isCurrentMonth = (date) => {
|
|
2069
|
+
return date.getMonth() === month;
|
|
2070
|
+
};
|
|
2071
|
+
const isDisabled = (date) => {
|
|
2072
|
+
if (minDate && date < minDate) return true;
|
|
2073
|
+
if (maxDate && date > maxDate) return true;
|
|
2074
|
+
return false;
|
|
2075
|
+
};
|
|
2076
|
+
const handleDateClick = (date) => {
|
|
2077
|
+
if (isDisabled(date)) return;
|
|
2078
|
+
setCurrentDate(date);
|
|
2079
|
+
onChange?.(date);
|
|
2080
|
+
};
|
|
2081
|
+
const handlePrevMonth = () => {
|
|
2082
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
2083
|
+
};
|
|
2084
|
+
const handleNextMonth = () => {
|
|
2085
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
2086
|
+
};
|
|
2087
|
+
const handleToday = () => {
|
|
2088
|
+
const today = /* @__PURE__ */ new Date();
|
|
2089
|
+
setViewDate(today);
|
|
2090
|
+
setCurrentDate(today);
|
|
2091
|
+
onChange?.(today);
|
|
2092
|
+
};
|
|
2093
|
+
return /* @__PURE__ */ jsxs20("div", { className: `bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4 ${className}`, children: [
|
|
2094
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center justify-between mb-4", children: [
|
|
2095
|
+
/* @__PURE__ */ jsx54(
|
|
2096
|
+
"button",
|
|
1438
2097
|
{
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
className:
|
|
1443
|
-
...props
|
|
2098
|
+
onClick: handlePrevMonth,
|
|
2099
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
2100
|
+
"aria-label": "Previous month",
|
|
2101
|
+
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" }) })
|
|
1444
2102
|
}
|
|
1445
2103
|
),
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
2104
|
+
/* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-2", children: [
|
|
2105
|
+
/* @__PURE__ */ jsxs20("h2", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: [
|
|
2106
|
+
MONTHS3[month],
|
|
2107
|
+
" ",
|
|
2108
|
+
year
|
|
2109
|
+
] }),
|
|
2110
|
+
/* @__PURE__ */ jsx54(
|
|
2111
|
+
"button",
|
|
2112
|
+
{
|
|
2113
|
+
onClick: handleToday,
|
|
2114
|
+
className: "px-3 py-1 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors",
|
|
2115
|
+
children: "Today"
|
|
2116
|
+
}
|
|
2117
|
+
)
|
|
2118
|
+
] }),
|
|
2119
|
+
/* @__PURE__ */ jsx54(
|
|
2120
|
+
"button",
|
|
2121
|
+
{
|
|
2122
|
+
onClick: handleNextMonth,
|
|
2123
|
+
className: "p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors",
|
|
2124
|
+
"aria-label": "Next month",
|
|
2125
|
+
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" }) })
|
|
2126
|
+
}
|
|
2127
|
+
)
|
|
2128
|
+
] }),
|
|
2129
|
+
/* @__PURE__ */ jsx54("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS3.map((day) => /* @__PURE__ */ jsx54(
|
|
2130
|
+
"div",
|
|
2131
|
+
{
|
|
2132
|
+
className: "text-center text-xs font-semibold text-gray-600 dark:text-gray-400 py-2",
|
|
2133
|
+
children: day
|
|
2134
|
+
},
|
|
2135
|
+
day
|
|
2136
|
+
)) }),
|
|
2137
|
+
/* @__PURE__ */ jsx54("div", { className: "grid grid-cols-7 gap-1", children: calendarDays.map((date, index) => {
|
|
2138
|
+
if (!date) return /* @__PURE__ */ jsx54("div", {}, index);
|
|
2139
|
+
const isCurrentMonthDay = isCurrentMonth(date);
|
|
2140
|
+
const isTodayDay = isToday(date);
|
|
2141
|
+
const isSelectedDay = isSelected(date);
|
|
2142
|
+
const isDisabledDay = isDisabled(date);
|
|
2143
|
+
return /* @__PURE__ */ jsx54(
|
|
2144
|
+
"button",
|
|
2145
|
+
{
|
|
2146
|
+
onClick: () => handleDateClick(date),
|
|
2147
|
+
disabled: isDisabledDay,
|
|
2148
|
+
className: `
|
|
2149
|
+
aspect-square p-2 rounded-lg text-sm font-medium transition-all
|
|
2150
|
+
${!isCurrentMonthDay ? "text-gray-400 dark:text-gray-600" : "text-gray-900 dark:text-gray-100"}
|
|
2151
|
+
${isTodayDay && !isSelectedDay ? "bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400 font-bold" : ""}
|
|
2152
|
+
${isSelectedDay ? "bg-blue-600 text-white hover:bg-blue-700" : ""}
|
|
2153
|
+
${!isSelectedDay && !isDisabledDay ? "hover:bg-gray-100 dark:hover:bg-gray-700" : ""}
|
|
2154
|
+
${isDisabledDay ? "opacity-30 cursor-not-allowed" : "cursor-pointer"}
|
|
2155
|
+
`,
|
|
2156
|
+
children: date.getDate()
|
|
2157
|
+
},
|
|
2158
|
+
index
|
|
2159
|
+
);
|
|
2160
|
+
}) })
|
|
2161
|
+
] });
|
|
2162
|
+
};
|
|
1452
2163
|
|
|
1453
2164
|
// src/components/Radio.tsx
|
|
1454
|
-
import
|
|
1455
|
-
import { jsx as
|
|
2165
|
+
import React16 from "react";
|
|
2166
|
+
import { jsx as jsx55, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1456
2167
|
var Radio = ({
|
|
1457
2168
|
name,
|
|
1458
2169
|
options,
|
|
@@ -1463,7 +2174,7 @@ var Radio = ({
|
|
|
1463
2174
|
orientation = "vertical",
|
|
1464
2175
|
className = ""
|
|
1465
2176
|
}) => {
|
|
1466
|
-
const [internalValue, setInternalValue] =
|
|
2177
|
+
const [internalValue, setInternalValue] = React16.useState(defaultValue || "");
|
|
1467
2178
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
1468
2179
|
const handleChange = (optionValue) => {
|
|
1469
2180
|
if (disabled) return;
|
|
@@ -1471,17 +2182,17 @@ var Radio = ({
|
|
|
1471
2182
|
onChange?.(optionValue);
|
|
1472
2183
|
};
|
|
1473
2184
|
const containerClass = orientation === "horizontal" ? "flex flex-wrap gap-4" : "flex flex-col gap-2";
|
|
1474
|
-
return /* @__PURE__ */
|
|
2185
|
+
return /* @__PURE__ */ jsx55("div", { className: `${containerClass} ${className}`, role: "radiogroup", children: options.map((option) => {
|
|
1475
2186
|
const isDisabled = disabled || option.disabled;
|
|
1476
2187
|
const isChecked = value === option.value;
|
|
1477
2188
|
const id = `${name}-${option.value}`;
|
|
1478
|
-
return /* @__PURE__ */
|
|
2189
|
+
return /* @__PURE__ */ jsxs21(
|
|
1479
2190
|
"label",
|
|
1480
2191
|
{
|
|
1481
2192
|
htmlFor: id,
|
|
1482
2193
|
className: `flex items-center gap-2 cursor-pointer ${isDisabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
1483
2194
|
children: [
|
|
1484
|
-
/* @__PURE__ */
|
|
2195
|
+
/* @__PURE__ */ jsx55(
|
|
1485
2196
|
"input",
|
|
1486
2197
|
{
|
|
1487
2198
|
type: "radio",
|
|
@@ -1494,7 +2205,7 @@ var Radio = ({
|
|
|
1494
2205
|
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"
|
|
1495
2206
|
}
|
|
1496
2207
|
),
|
|
1497
|
-
/* @__PURE__ */
|
|
2208
|
+
/* @__PURE__ */ jsx55("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-300", children: option.label })
|
|
1498
2209
|
]
|
|
1499
2210
|
},
|
|
1500
2211
|
option.value
|
|
@@ -1503,7 +2214,7 @@ var Radio = ({
|
|
|
1503
2214
|
};
|
|
1504
2215
|
|
|
1505
2216
|
// src/components/ProgressBar.tsx
|
|
1506
|
-
import { jsx as
|
|
2217
|
+
import { jsx as jsx56, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1507
2218
|
var ProgressBar = ({
|
|
1508
2219
|
value,
|
|
1509
2220
|
max = 100,
|
|
@@ -1525,15 +2236,15 @@ var ProgressBar = ({
|
|
|
1525
2236
|
warning: "bg-yellow-500 dark:bg-yellow-400",
|
|
1526
2237
|
danger: "bg-red-600 dark:bg-red-500"
|
|
1527
2238
|
};
|
|
1528
|
-
return /* @__PURE__ */
|
|
1529
|
-
(showLabel || label) && /* @__PURE__ */
|
|
1530
|
-
label && /* @__PURE__ */
|
|
1531
|
-
showLabel && /* @__PURE__ */
|
|
2239
|
+
return /* @__PURE__ */ jsxs22("div", { className: `w-full ${className}`, children: [
|
|
2240
|
+
(showLabel || label) && /* @__PURE__ */ jsxs22("div", { className: "flex justify-between items-center mb-1", children: [
|
|
2241
|
+
label && /* @__PURE__ */ jsx56("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: label }),
|
|
2242
|
+
showLabel && /* @__PURE__ */ jsxs22("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: [
|
|
1532
2243
|
Math.round(percentage),
|
|
1533
2244
|
"%"
|
|
1534
2245
|
] })
|
|
1535
2246
|
] }),
|
|
1536
|
-
/* @__PURE__ */
|
|
2247
|
+
/* @__PURE__ */ jsx56(
|
|
1537
2248
|
"div",
|
|
1538
2249
|
{
|
|
1539
2250
|
className: `w-full bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden ${sizeClasses6[size]}`,
|
|
@@ -1541,7 +2252,7 @@ var ProgressBar = ({
|
|
|
1541
2252
|
"aria-valuenow": value,
|
|
1542
2253
|
"aria-valuemin": 0,
|
|
1543
2254
|
"aria-valuemax": max,
|
|
1544
|
-
children: /* @__PURE__ */
|
|
2255
|
+
children: /* @__PURE__ */ jsx56(
|
|
1545
2256
|
"div",
|
|
1546
2257
|
{
|
|
1547
2258
|
className: `${sizeClasses6[size]} ${variantClasses[variant]} rounded-full transition-all duration-300 ease-out`,
|
|
@@ -1554,8 +2265,8 @@ var ProgressBar = ({
|
|
|
1554
2265
|
};
|
|
1555
2266
|
|
|
1556
2267
|
// src/components/Slider.tsx
|
|
1557
|
-
import
|
|
1558
|
-
import { jsx as
|
|
2268
|
+
import React17 from "react";
|
|
2269
|
+
import { jsx as jsx57, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1559
2270
|
var Slider = ({
|
|
1560
2271
|
value: controlledValue,
|
|
1561
2272
|
defaultValue = 50,
|
|
@@ -1568,7 +2279,7 @@ var Slider = ({
|
|
|
1568
2279
|
label,
|
|
1569
2280
|
className = ""
|
|
1570
2281
|
}) => {
|
|
1571
|
-
const [internalValue, setInternalValue] =
|
|
2282
|
+
const [internalValue, setInternalValue] = React17.useState(defaultValue);
|
|
1572
2283
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
1573
2284
|
const handleChange = (e) => {
|
|
1574
2285
|
const newValue = Number(e.target.value);
|
|
@@ -1576,21 +2287,21 @@ var Slider = ({
|
|
|
1576
2287
|
onChange?.(newValue);
|
|
1577
2288
|
};
|
|
1578
2289
|
const percentage = (value - min) / (max - min) * 100;
|
|
1579
|
-
return /* @__PURE__ */
|
|
1580
|
-
(label || showValue) && /* @__PURE__ */
|
|
1581
|
-
label && /* @__PURE__ */
|
|
1582
|
-
showValue && /* @__PURE__ */
|
|
2290
|
+
return /* @__PURE__ */ jsxs23("div", { className: `w-full ${className}`, children: [
|
|
2291
|
+
(label || showValue) && /* @__PURE__ */ jsxs23("div", { className: "flex justify-between items-center mb-2", children: [
|
|
2292
|
+
label && /* @__PURE__ */ jsx57("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: label }),
|
|
2293
|
+
showValue && /* @__PURE__ */ jsx57("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: value })
|
|
1583
2294
|
] }),
|
|
1584
|
-
/* @__PURE__ */
|
|
1585
|
-
/* @__PURE__ */
|
|
1586
|
-
/* @__PURE__ */
|
|
2295
|
+
/* @__PURE__ */ jsxs23("div", { className: "relative", children: [
|
|
2296
|
+
/* @__PURE__ */ jsx57("div", { className: "absolute inset-0 h-2 bg-gray-200 dark:bg-gray-700 rounded-full top-1/2 -translate-y-1/2" }),
|
|
2297
|
+
/* @__PURE__ */ jsx57(
|
|
1587
2298
|
"div",
|
|
1588
2299
|
{
|
|
1589
2300
|
className: "absolute h-2 bg-blue-600 dark:bg-blue-500 rounded-full top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1590
2301
|
style: { width: `${percentage}%` }
|
|
1591
2302
|
}
|
|
1592
2303
|
),
|
|
1593
|
-
/* @__PURE__ */
|
|
2304
|
+
/* @__PURE__ */ jsx57(
|
|
1594
2305
|
"input",
|
|
1595
2306
|
{
|
|
1596
2307
|
type: "range",
|
|
@@ -1612,8 +2323,8 @@ var Slider = ({
|
|
|
1612
2323
|
};
|
|
1613
2324
|
|
|
1614
2325
|
// src/components/Avatar.tsx
|
|
1615
|
-
import
|
|
1616
|
-
import { jsx as
|
|
2326
|
+
import React18 from "react";
|
|
2327
|
+
import { jsx as jsx58 } from "react/jsx-runtime";
|
|
1617
2328
|
var Avatar = ({
|
|
1618
2329
|
src,
|
|
1619
2330
|
alt,
|
|
@@ -1623,7 +2334,7 @@ var Avatar = ({
|
|
|
1623
2334
|
className = "",
|
|
1624
2335
|
fallbackColor = "bg-blue-600"
|
|
1625
2336
|
}) => {
|
|
1626
|
-
const [imageError, setImageError] =
|
|
2337
|
+
const [imageError, setImageError] = React18.useState(false);
|
|
1627
2338
|
const sizeClasses6 = {
|
|
1628
2339
|
xs: "w-6 h-6 text-xs",
|
|
1629
2340
|
sm: "w-8 h-8 text-sm",
|
|
@@ -1641,11 +2352,11 @@ var Avatar = ({
|
|
|
1641
2352
|
};
|
|
1642
2353
|
const showImage = src && !imageError;
|
|
1643
2354
|
const showInitials = !showImage && name;
|
|
1644
|
-
return /* @__PURE__ */
|
|
2355
|
+
return /* @__PURE__ */ jsx58(
|
|
1645
2356
|
"div",
|
|
1646
2357
|
{
|
|
1647
2358
|
className: `${sizeClasses6[size]} ${shapeClass} flex items-center justify-center overflow-hidden ${showImage ? "bg-gray-200 dark:bg-gray-700" : `${fallbackColor} text-white`} ${className}`,
|
|
1648
|
-
children: showImage ? /* @__PURE__ */
|
|
2359
|
+
children: showImage ? /* @__PURE__ */ jsx58(
|
|
1649
2360
|
"img",
|
|
1650
2361
|
{
|
|
1651
2362
|
src,
|
|
@@ -1653,13 +2364,13 @@ var Avatar = ({
|
|
|
1653
2364
|
className: "w-full h-full object-cover",
|
|
1654
2365
|
onError: () => setImageError(true)
|
|
1655
2366
|
}
|
|
1656
|
-
) : showInitials ? /* @__PURE__ */
|
|
2367
|
+
) : showInitials ? /* @__PURE__ */ jsx58("span", { className: "font-semibold select-none", children: getInitials(name) }) : /* @__PURE__ */ jsx58(
|
|
1657
2368
|
"svg",
|
|
1658
2369
|
{
|
|
1659
2370
|
className: "w-full h-full text-gray-400 dark:text-gray-600",
|
|
1660
2371
|
fill: "currentColor",
|
|
1661
2372
|
viewBox: "0 0 24 24",
|
|
1662
|
-
children: /* @__PURE__ */
|
|
2373
|
+
children: /* @__PURE__ */ jsx58("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" })
|
|
1663
2374
|
}
|
|
1664
2375
|
)
|
|
1665
2376
|
}
|
|
@@ -1667,7 +2378,7 @@ var Avatar = ({
|
|
|
1667
2378
|
};
|
|
1668
2379
|
|
|
1669
2380
|
// src/components/Textarea.tsx
|
|
1670
|
-
import { jsx as
|
|
2381
|
+
import { jsx as jsx59, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1671
2382
|
var Textarea = ({
|
|
1672
2383
|
label,
|
|
1673
2384
|
error,
|
|
@@ -1694,9 +2405,9 @@ var Textarea = ({
|
|
|
1694
2405
|
bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100
|
|
1695
2406
|
placeholder:text-gray-500 dark:placeholder:text-gray-400
|
|
1696
2407
|
disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-gray-50 dark:disabled:bg-gray-900`;
|
|
1697
|
-
return /* @__PURE__ */
|
|
1698
|
-
label && /* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
2408
|
+
return /* @__PURE__ */ jsxs24("div", { className: `w-full ${className}`, children: [
|
|
2409
|
+
label && /* @__PURE__ */ jsx59("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1", children: label }),
|
|
2410
|
+
/* @__PURE__ */ jsx59(
|
|
1700
2411
|
"textarea",
|
|
1701
2412
|
{
|
|
1702
2413
|
className: `${baseClasses} ${sizeClasses6[size]} ${resizeClasses[resize]}`,
|
|
@@ -1704,14 +2415,14 @@ var Textarea = ({
|
|
|
1704
2415
|
...props
|
|
1705
2416
|
}
|
|
1706
2417
|
),
|
|
1707
|
-
error && /* @__PURE__ */
|
|
1708
|
-
helperText && !error && /* @__PURE__ */
|
|
2418
|
+
error && /* @__PURE__ */ jsx59("p", { className: "mt-1 text-sm text-red-600 dark:text-red-400", children: error }),
|
|
2419
|
+
helperText && !error && /* @__PURE__ */ jsx59("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: helperText })
|
|
1709
2420
|
] });
|
|
1710
2421
|
};
|
|
1711
2422
|
|
|
1712
2423
|
// src/components/Toast.tsx
|
|
1713
|
-
import { createContext as createContext3, useContext as useContext3, useState as
|
|
1714
|
-
import { jsx as
|
|
2424
|
+
import { createContext as createContext3, useContext as useContext3, useState as useState10, useCallback } from "react";
|
|
2425
|
+
import { jsx as jsx60, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
1715
2426
|
var ToastContext = createContext3(void 0);
|
|
1716
2427
|
var useToast = () => {
|
|
1717
2428
|
const context = useContext3(ToastContext);
|
|
@@ -1721,7 +2432,7 @@ var useToast = () => {
|
|
|
1721
2432
|
return context;
|
|
1722
2433
|
};
|
|
1723
2434
|
var ToastProvider = ({ children, position = "top-right" }) => {
|
|
1724
|
-
const [toasts, setToasts] =
|
|
2435
|
+
const [toasts, setToasts] = useState10([]);
|
|
1725
2436
|
const addToast = useCallback((toast2) => {
|
|
1726
2437
|
const id = Math.random().toString(36).substring(7);
|
|
1727
2438
|
const newToast = { ...toast2, id };
|
|
@@ -1742,9 +2453,9 @@ var ToastProvider = ({ children, position = "top-right" }) => {
|
|
|
1742
2453
|
"top-center": "top-4 left-1/2 -translate-x-1/2",
|
|
1743
2454
|
"bottom-center": "bottom-4 left-1/2 -translate-x-1/2"
|
|
1744
2455
|
};
|
|
1745
|
-
return /* @__PURE__ */
|
|
2456
|
+
return /* @__PURE__ */ jsxs25(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
|
|
1746
2457
|
children,
|
|
1747
|
-
/* @__PURE__ */
|
|
2458
|
+
/* @__PURE__ */ jsx60("div", { className: `fixed ${positionClasses2[position]} z-50 flex flex-col gap-2 max-w-md`, children: toasts.map((toast2) => /* @__PURE__ */ jsx60(ToastItem, { toast: toast2, onClose: () => removeToast(toast2.id) }, toast2.id)) })
|
|
1748
2459
|
] });
|
|
1749
2460
|
};
|
|
1750
2461
|
var ToastItem = ({ toast: toast2, onClose }) => {
|
|
@@ -1755,27 +2466,27 @@ var ToastItem = ({ toast: toast2, onClose }) => {
|
|
|
1755
2466
|
info: "bg-blue-50 dark:bg-blue-900/30 border-blue-500 text-blue-800 dark:text-blue-200"
|
|
1756
2467
|
};
|
|
1757
2468
|
const typeIcons = {
|
|
1758
|
-
success: /* @__PURE__ */
|
|
1759
|
-
error: /* @__PURE__ */
|
|
1760
|
-
warning: /* @__PURE__ */
|
|
1761
|
-
info: /* @__PURE__ */
|
|
2469
|
+
success: /* @__PURE__ */ jsx60(CheckIcon, { size: "sm", className: "text-green-600 dark:text-green-400" }),
|
|
2470
|
+
error: /* @__PURE__ */ jsx60(CloseIcon, { size: "sm", className: "text-red-600 dark:text-red-400" }),
|
|
2471
|
+
warning: /* @__PURE__ */ jsx60("svg", { className: "w-4 h-4 text-yellow-600 dark:text-yellow-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx60("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" }) }),
|
|
2472
|
+
info: /* @__PURE__ */ jsx60("svg", { className: "w-4 h-4 text-blue-600 dark:text-blue-400", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx60("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" }) })
|
|
1762
2473
|
};
|
|
1763
2474
|
const type = toast2.type || "info";
|
|
1764
|
-
return /* @__PURE__ */
|
|
2475
|
+
return /* @__PURE__ */ jsxs25(
|
|
1765
2476
|
"div",
|
|
1766
2477
|
{
|
|
1767
2478
|
className: `flex items-start gap-3 p-4 rounded-lg border-l-4 shadow-lg backdrop-blur-sm ${typeStyles[type]} animate-slide-in`,
|
|
1768
2479
|
role: "alert",
|
|
1769
2480
|
children: [
|
|
1770
|
-
/* @__PURE__ */
|
|
1771
|
-
/* @__PURE__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
2481
|
+
/* @__PURE__ */ jsx60("div", { className: "flex-shrink-0 mt-0.5", children: typeIcons[type] }),
|
|
2482
|
+
/* @__PURE__ */ jsx60("p", { className: "flex-1 text-sm font-medium", children: toast2.message }),
|
|
2483
|
+
/* @__PURE__ */ jsx60(
|
|
1773
2484
|
"button",
|
|
1774
2485
|
{
|
|
1775
2486
|
onClick: onClose,
|
|
1776
2487
|
className: "flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-colors",
|
|
1777
2488
|
"aria-label": "Close",
|
|
1778
|
-
children: /* @__PURE__ */
|
|
2489
|
+
children: /* @__PURE__ */ jsx60(CloseIcon, { size: "sm" })
|
|
1779
2490
|
}
|
|
1780
2491
|
)
|
|
1781
2492
|
]
|
|
@@ -1806,8 +2517,8 @@ var toast = {
|
|
|
1806
2517
|
};
|
|
1807
2518
|
|
|
1808
2519
|
// src/components/Stepper.tsx
|
|
1809
|
-
import
|
|
1810
|
-
import { jsx as
|
|
2520
|
+
import React20 from "react";
|
|
2521
|
+
import { jsx as jsx61, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1811
2522
|
var Stepper = ({
|
|
1812
2523
|
steps,
|
|
1813
2524
|
currentStep,
|
|
@@ -1815,18 +2526,18 @@ var Stepper = ({
|
|
|
1815
2526
|
className = ""
|
|
1816
2527
|
}) => {
|
|
1817
2528
|
const isHorizontal = orientation === "horizontal";
|
|
1818
|
-
return /* @__PURE__ */
|
|
2529
|
+
return /* @__PURE__ */ jsx61("div", { className: `${isHorizontal ? "flex items-center" : "flex flex-col"} ${className}`, children: steps.map((step, index) => {
|
|
1819
2530
|
const stepNumber = index + 1;
|
|
1820
2531
|
const isActive = stepNumber === currentStep;
|
|
1821
2532
|
const isCompleted = stepNumber < currentStep;
|
|
1822
2533
|
const isLast = index === steps.length - 1;
|
|
1823
|
-
return /* @__PURE__ */
|
|
1824
|
-
/* @__PURE__ */
|
|
1825
|
-
/* @__PURE__ */
|
|
2534
|
+
return /* @__PURE__ */ jsxs26(React20.Fragment, { children: [
|
|
2535
|
+
/* @__PURE__ */ jsxs26("div", { className: `flex ${isHorizontal ? "flex-col items-center" : "flex-row items-start"} ${isHorizontal ? "" : "flex-1"}`, children: [
|
|
2536
|
+
/* @__PURE__ */ jsx61("div", { className: "flex items-center", children: /* @__PURE__ */ jsx61(
|
|
1826
2537
|
"div",
|
|
1827
2538
|
{
|
|
1828
2539
|
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"}`,
|
|
1829
|
-
children: isCompleted ? /* @__PURE__ */
|
|
2540
|
+
children: isCompleted ? /* @__PURE__ */ jsx61(CheckIcon, { size: "sm", className: "text-white" }) : /* @__PURE__ */ jsx61(
|
|
1830
2541
|
"span",
|
|
1831
2542
|
{
|
|
1832
2543
|
className: `text-sm font-semibold ${isActive ? "text-blue-600 dark:text-blue-400" : "text-gray-500 dark:text-gray-400"}`,
|
|
@@ -1835,18 +2546,18 @@ var Stepper = ({
|
|
|
1835
2546
|
)
|
|
1836
2547
|
}
|
|
1837
2548
|
) }),
|
|
1838
|
-
/* @__PURE__ */
|
|
1839
|
-
/* @__PURE__ */
|
|
2549
|
+
/* @__PURE__ */ jsxs26("div", { className: `${isHorizontal ? "mt-2 text-center" : "ml-4 pb-8"} ${isLast && !isHorizontal ? "pb-0" : ""}`, children: [
|
|
2550
|
+
/* @__PURE__ */ jsx61(
|
|
1840
2551
|
"p",
|
|
1841
2552
|
{
|
|
1842
2553
|
className: `text-sm font-medium ${isActive || isCompleted ? "text-gray-900 dark:text-gray-100" : "text-gray-500 dark:text-gray-400"}`,
|
|
1843
2554
|
children: step.label
|
|
1844
2555
|
}
|
|
1845
2556
|
),
|
|
1846
|
-
step.description && /* @__PURE__ */
|
|
2557
|
+
step.description && /* @__PURE__ */ jsx61("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: step.description })
|
|
1847
2558
|
] })
|
|
1848
2559
|
] }),
|
|
1849
|
-
!isLast && /* @__PURE__ */
|
|
2560
|
+
!isLast && /* @__PURE__ */ jsx61(
|
|
1850
2561
|
"div",
|
|
1851
2562
|
{
|
|
1852
2563
|
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"}`
|
|
@@ -1857,7 +2568,7 @@ var Stepper = ({
|
|
|
1857
2568
|
};
|
|
1858
2569
|
|
|
1859
2570
|
// src/components/Divider.tsx
|
|
1860
|
-
import { jsx as
|
|
2571
|
+
import { jsx as jsx62, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1861
2572
|
var Divider = ({
|
|
1862
2573
|
orientation = "horizontal",
|
|
1863
2574
|
variant = "solid",
|
|
@@ -1876,14 +2587,14 @@ var Divider = ({
|
|
|
1876
2587
|
center: "justify-center",
|
|
1877
2588
|
right: "justify-end"
|
|
1878
2589
|
};
|
|
1879
|
-
return /* @__PURE__ */
|
|
1880
|
-
labelPosition !== "left" && /* @__PURE__ */
|
|
1881
|
-
/* @__PURE__ */
|
|
1882
|
-
labelPosition !== "right" && /* @__PURE__ */
|
|
2590
|
+
return /* @__PURE__ */ jsxs27("div", { className: `flex items-center ${alignmentClasses[labelPosition]} ${className}`, role: "separator", children: [
|
|
2591
|
+
labelPosition !== "left" && /* @__PURE__ */ jsx62("div", { className: `flex-1 border-t ${variantClasses[variant]} border-gray-300 dark:border-gray-600` }),
|
|
2592
|
+
/* @__PURE__ */ jsx62("span", { className: "px-4 text-sm text-gray-500 dark:text-gray-400", children: label }),
|
|
2593
|
+
labelPosition !== "right" && /* @__PURE__ */ jsx62("div", { className: `flex-1 border-t ${variantClasses[variant]} border-gray-300 dark:border-gray-600` })
|
|
1883
2594
|
] });
|
|
1884
2595
|
}
|
|
1885
2596
|
if (orientation === "vertical") {
|
|
1886
|
-
return /* @__PURE__ */
|
|
2597
|
+
return /* @__PURE__ */ jsx62(
|
|
1887
2598
|
"div",
|
|
1888
2599
|
{
|
|
1889
2600
|
className: `inline-block h-full border-l ${variantClasses[variant]} border-gray-300 dark:border-gray-600 ${className}`,
|
|
@@ -1892,7 +2603,7 @@ var Divider = ({
|
|
|
1892
2603
|
}
|
|
1893
2604
|
);
|
|
1894
2605
|
}
|
|
1895
|
-
return /* @__PURE__ */
|
|
2606
|
+
return /* @__PURE__ */ jsx62(
|
|
1896
2607
|
"hr",
|
|
1897
2608
|
{
|
|
1898
2609
|
className: `border-t ${variantClasses[variant]} border-gray-300 dark:border-gray-600 ${className}`,
|
|
@@ -1902,8 +2613,8 @@ var Divider = ({
|
|
|
1902
2613
|
};
|
|
1903
2614
|
|
|
1904
2615
|
// src/components/FileUpload.tsx
|
|
1905
|
-
import { useRef as
|
|
1906
|
-
import { jsx as
|
|
2616
|
+
import { useRef as useRef5, useState as useState11 } from "react";
|
|
2617
|
+
import { jsx as jsx63, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
1907
2618
|
var FileUpload = ({
|
|
1908
2619
|
accept,
|
|
1909
2620
|
multiple = false,
|
|
@@ -1916,9 +2627,9 @@ var FileUpload = ({
|
|
|
1916
2627
|
label,
|
|
1917
2628
|
helperText
|
|
1918
2629
|
}) => {
|
|
1919
|
-
const [files, setFiles] =
|
|
1920
|
-
const [isDragging, setIsDragging] =
|
|
1921
|
-
const fileInputRef =
|
|
2630
|
+
const [files, setFiles] = useState11([]);
|
|
2631
|
+
const [isDragging, setIsDragging] = useState11(false);
|
|
2632
|
+
const fileInputRef = useRef5(null);
|
|
1922
2633
|
const formatFileSize = (bytes) => {
|
|
1923
2634
|
if (bytes === 0) return "0 Bytes";
|
|
1924
2635
|
const k = 1024;
|
|
@@ -1976,9 +2687,9 @@ var FileUpload = ({
|
|
|
1976
2687
|
setFiles(newFiles);
|
|
1977
2688
|
onChange?.(newFiles);
|
|
1978
2689
|
};
|
|
1979
|
-
return /* @__PURE__ */
|
|
1980
|
-
label && /* @__PURE__ */
|
|
1981
|
-
/* @__PURE__ */
|
|
2690
|
+
return /* @__PURE__ */ jsxs28("div", { className: `w-full ${className}`, children: [
|
|
2691
|
+
label && /* @__PURE__ */ jsx63("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2", children: label }),
|
|
2692
|
+
/* @__PURE__ */ jsxs28(
|
|
1982
2693
|
"div",
|
|
1983
2694
|
{
|
|
1984
2695
|
onDrop: handleDrop,
|
|
@@ -1987,7 +2698,7 @@ var FileUpload = ({
|
|
|
1987
2698
|
onClick: handleClick,
|
|
1988
2699
|
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" : ""}`,
|
|
1989
2700
|
children: [
|
|
1990
|
-
/* @__PURE__ */
|
|
2701
|
+
/* @__PURE__ */ jsx63(
|
|
1991
2702
|
"input",
|
|
1992
2703
|
{
|
|
1993
2704
|
ref: fileInputRef,
|
|
@@ -1999,14 +2710,14 @@ var FileUpload = ({
|
|
|
1999
2710
|
className: "hidden"
|
|
2000
2711
|
}
|
|
2001
2712
|
),
|
|
2002
|
-
/* @__PURE__ */
|
|
2003
|
-
/* @__PURE__ */
|
|
2004
|
-
/* @__PURE__ */
|
|
2005
|
-
/* @__PURE__ */
|
|
2006
|
-
/* @__PURE__ */
|
|
2713
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex flex-col items-center gap-2", children: [
|
|
2714
|
+
/* @__PURE__ */ jsx63("div", { className: "w-12 h-12 rounded-full bg-gray-100 dark:bg-gray-800 flex items-center justify-center", children: /* @__PURE__ */ jsx63(UploadIcon, { size: "lg", className: "text-gray-400 dark:text-gray-500" }) }),
|
|
2715
|
+
/* @__PURE__ */ jsxs28("div", { children: [
|
|
2716
|
+
/* @__PURE__ */ jsxs28("p", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: [
|
|
2717
|
+
/* @__PURE__ */ jsx63("span", { className: "text-blue-600 dark:text-blue-400", children: "Click to upload" }),
|
|
2007
2718
|
" or drag and drop"
|
|
2008
2719
|
] }),
|
|
2009
|
-
/* @__PURE__ */
|
|
2720
|
+
/* @__PURE__ */ jsxs28("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: [
|
|
2010
2721
|
accept ? `Accepted: ${accept}` : "Any file type",
|
|
2011
2722
|
maxSize && ` \u2022 Max size: ${formatFileSize(maxSize)}`
|
|
2012
2723
|
] })
|
|
@@ -2015,17 +2726,17 @@ var FileUpload = ({
|
|
|
2015
2726
|
]
|
|
2016
2727
|
}
|
|
2017
2728
|
),
|
|
2018
|
-
helperText && /* @__PURE__ */
|
|
2019
|
-
files.length > 0 && /* @__PURE__ */
|
|
2729
|
+
helperText && /* @__PURE__ */ jsx63("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: helperText }),
|
|
2730
|
+
files.length > 0 && /* @__PURE__ */ jsx63("div", { className: "mt-4 space-y-2", children: files.map((file, index) => /* @__PURE__ */ jsxs28(
|
|
2020
2731
|
"div",
|
|
2021
2732
|
{
|
|
2022
2733
|
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",
|
|
2023
2734
|
children: [
|
|
2024
|
-
/* @__PURE__ */
|
|
2025
|
-
/* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
2735
|
+
/* @__PURE__ */ jsxs28("div", { className: "flex-1 min-w-0", children: [
|
|
2736
|
+
/* @__PURE__ */ jsx63("p", { className: "text-sm font-medium text-gray-900 dark:text-gray-100 truncate", children: file.name }),
|
|
2737
|
+
/* @__PURE__ */ jsx63("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: formatFileSize(file.size) })
|
|
2027
2738
|
] }),
|
|
2028
|
-
/* @__PURE__ */
|
|
2739
|
+
/* @__PURE__ */ jsx63(
|
|
2029
2740
|
"button",
|
|
2030
2741
|
{
|
|
2031
2742
|
onClick: (e) => {
|
|
@@ -2034,7 +2745,7 @@ var FileUpload = ({
|
|
|
2034
2745
|
},
|
|
2035
2746
|
className: "ml-4 text-gray-400 hover:text-red-600 dark:hover:text-red-400 transition-colors",
|
|
2036
2747
|
"aria-label": "Remove file",
|
|
2037
|
-
children: /* @__PURE__ */
|
|
2748
|
+
children: /* @__PURE__ */ jsx63(CloseIcon, { size: "sm" })
|
|
2038
2749
|
}
|
|
2039
2750
|
)
|
|
2040
2751
|
]
|
|
@@ -2085,6 +2796,7 @@ export {
|
|
|
2085
2796
|
Badge,
|
|
2086
2797
|
BellIcon,
|
|
2087
2798
|
Button,
|
|
2799
|
+
Calendar,
|
|
2088
2800
|
CalendarIcon,
|
|
2089
2801
|
CameraIcon,
|
|
2090
2802
|
Card,
|