@marcoschwartz/lite-ui 0.7.1 → 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 +31 -5
- package/dist/index.d.ts +31 -5
- package/dist/index.js +853 -185
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +852 -185
- 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
|
|
|
@@ -1412,37 +1421,227 @@ var Pagination = ({
|
|
|
1412
1421
|
};
|
|
1413
1422
|
|
|
1414
1423
|
// src/components/DatePicker.tsx
|
|
1415
|
-
import {
|
|
1424
|
+
import { useState as useState7, useRef as useRef3, useEffect as useEffect6 } from "react";
|
|
1425
|
+
import { createPortal as createPortal2 } from "react-dom";
|
|
1416
1426
|
import { jsx as jsx51, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1417
|
-
var
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
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));
|
|
1438
1494
|
}
|
|
1439
|
-
)
|
|
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
|
+
};
|
|
1440
1639
|
DatePicker.displayName = "DatePicker";
|
|
1441
1640
|
|
|
1442
1641
|
// src/components/TimePicker.tsx
|
|
1443
|
-
import { forwardRef as
|
|
1642
|
+
import { forwardRef as forwardRef4 } from "react";
|
|
1444
1643
|
import { jsx as jsx52, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1445
|
-
var TimePicker =
|
|
1644
|
+
var TimePicker = forwardRef4(
|
|
1446
1645
|
({ label, error, helperText, className = "", disabled, ...props }, ref) => {
|
|
1447
1646
|
const { theme } = useTheme();
|
|
1448
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";
|
|
@@ -1468,36 +1667,503 @@ var TimePicker = forwardRef5(
|
|
|
1468
1667
|
TimePicker.displayName = "TimePicker";
|
|
1469
1668
|
|
|
1470
1669
|
// src/components/DateTimePicker.tsx
|
|
1471
|
-
import {
|
|
1670
|
+
import { useState as useState8, useRef as useRef4, useEffect as useEffect7 } from "react";
|
|
1671
|
+
import { createPortal as createPortal3 } from "react-dom";
|
|
1472
1672
|
import { jsx as jsx53, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1473
|
-
var
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
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",
|
|
1483
2097
|
{
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
className:
|
|
1488
|
-
...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" }) })
|
|
1489
2102
|
}
|
|
1490
2103
|
),
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
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
|
+
};
|
|
1497
2163
|
|
|
1498
2164
|
// src/components/Radio.tsx
|
|
1499
|
-
import
|
|
1500
|
-
import { jsx as
|
|
2165
|
+
import React16 from "react";
|
|
2166
|
+
import { jsx as jsx55, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1501
2167
|
var Radio = ({
|
|
1502
2168
|
name,
|
|
1503
2169
|
options,
|
|
@@ -1508,7 +2174,7 @@ var Radio = ({
|
|
|
1508
2174
|
orientation = "vertical",
|
|
1509
2175
|
className = ""
|
|
1510
2176
|
}) => {
|
|
1511
|
-
const [internalValue, setInternalValue] =
|
|
2177
|
+
const [internalValue, setInternalValue] = React16.useState(defaultValue || "");
|
|
1512
2178
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
1513
2179
|
const handleChange = (optionValue) => {
|
|
1514
2180
|
if (disabled) return;
|
|
@@ -1516,17 +2182,17 @@ var Radio = ({
|
|
|
1516
2182
|
onChange?.(optionValue);
|
|
1517
2183
|
};
|
|
1518
2184
|
const containerClass = orientation === "horizontal" ? "flex flex-wrap gap-4" : "flex flex-col gap-2";
|
|
1519
|
-
return /* @__PURE__ */
|
|
2185
|
+
return /* @__PURE__ */ jsx55("div", { className: `${containerClass} ${className}`, role: "radiogroup", children: options.map((option) => {
|
|
1520
2186
|
const isDisabled = disabled || option.disabled;
|
|
1521
2187
|
const isChecked = value === option.value;
|
|
1522
2188
|
const id = `${name}-${option.value}`;
|
|
1523
|
-
return /* @__PURE__ */
|
|
2189
|
+
return /* @__PURE__ */ jsxs21(
|
|
1524
2190
|
"label",
|
|
1525
2191
|
{
|
|
1526
2192
|
htmlFor: id,
|
|
1527
2193
|
className: `flex items-center gap-2 cursor-pointer ${isDisabled ? "opacity-50 cursor-not-allowed" : ""}`,
|
|
1528
2194
|
children: [
|
|
1529
|
-
/* @__PURE__ */
|
|
2195
|
+
/* @__PURE__ */ jsx55(
|
|
1530
2196
|
"input",
|
|
1531
2197
|
{
|
|
1532
2198
|
type: "radio",
|
|
@@ -1539,7 +2205,7 @@ var Radio = ({
|
|
|
1539
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"
|
|
1540
2206
|
}
|
|
1541
2207
|
),
|
|
1542
|
-
/* @__PURE__ */
|
|
2208
|
+
/* @__PURE__ */ jsx55("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-300", children: option.label })
|
|
1543
2209
|
]
|
|
1544
2210
|
},
|
|
1545
2211
|
option.value
|
|
@@ -1548,7 +2214,7 @@ var Radio = ({
|
|
|
1548
2214
|
};
|
|
1549
2215
|
|
|
1550
2216
|
// src/components/ProgressBar.tsx
|
|
1551
|
-
import { jsx as
|
|
2217
|
+
import { jsx as jsx56, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1552
2218
|
var ProgressBar = ({
|
|
1553
2219
|
value,
|
|
1554
2220
|
max = 100,
|
|
@@ -1570,15 +2236,15 @@ var ProgressBar = ({
|
|
|
1570
2236
|
warning: "bg-yellow-500 dark:bg-yellow-400",
|
|
1571
2237
|
danger: "bg-red-600 dark:bg-red-500"
|
|
1572
2238
|
};
|
|
1573
|
-
return /* @__PURE__ */
|
|
1574
|
-
(showLabel || label) && /* @__PURE__ */
|
|
1575
|
-
label && /* @__PURE__ */
|
|
1576
|
-
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: [
|
|
1577
2243
|
Math.round(percentage),
|
|
1578
2244
|
"%"
|
|
1579
2245
|
] })
|
|
1580
2246
|
] }),
|
|
1581
|
-
/* @__PURE__ */
|
|
2247
|
+
/* @__PURE__ */ jsx56(
|
|
1582
2248
|
"div",
|
|
1583
2249
|
{
|
|
1584
2250
|
className: `w-full bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden ${sizeClasses6[size]}`,
|
|
@@ -1586,7 +2252,7 @@ var ProgressBar = ({
|
|
|
1586
2252
|
"aria-valuenow": value,
|
|
1587
2253
|
"aria-valuemin": 0,
|
|
1588
2254
|
"aria-valuemax": max,
|
|
1589
|
-
children: /* @__PURE__ */
|
|
2255
|
+
children: /* @__PURE__ */ jsx56(
|
|
1590
2256
|
"div",
|
|
1591
2257
|
{
|
|
1592
2258
|
className: `${sizeClasses6[size]} ${variantClasses[variant]} rounded-full transition-all duration-300 ease-out`,
|
|
@@ -1599,8 +2265,8 @@ var ProgressBar = ({
|
|
|
1599
2265
|
};
|
|
1600
2266
|
|
|
1601
2267
|
// src/components/Slider.tsx
|
|
1602
|
-
import
|
|
1603
|
-
import { jsx as
|
|
2268
|
+
import React17 from "react";
|
|
2269
|
+
import { jsx as jsx57, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1604
2270
|
var Slider = ({
|
|
1605
2271
|
value: controlledValue,
|
|
1606
2272
|
defaultValue = 50,
|
|
@@ -1613,7 +2279,7 @@ var Slider = ({
|
|
|
1613
2279
|
label,
|
|
1614
2280
|
className = ""
|
|
1615
2281
|
}) => {
|
|
1616
|
-
const [internalValue, setInternalValue] =
|
|
2282
|
+
const [internalValue, setInternalValue] = React17.useState(defaultValue);
|
|
1617
2283
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
1618
2284
|
const handleChange = (e) => {
|
|
1619
2285
|
const newValue = Number(e.target.value);
|
|
@@ -1621,21 +2287,21 @@ var Slider = ({
|
|
|
1621
2287
|
onChange?.(newValue);
|
|
1622
2288
|
};
|
|
1623
2289
|
const percentage = (value - min) / (max - min) * 100;
|
|
1624
|
-
return /* @__PURE__ */
|
|
1625
|
-
(label || showValue) && /* @__PURE__ */
|
|
1626
|
-
label && /* @__PURE__ */
|
|
1627
|
-
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 })
|
|
1628
2294
|
] }),
|
|
1629
|
-
/* @__PURE__ */
|
|
1630
|
-
/* @__PURE__ */
|
|
1631
|
-
/* @__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(
|
|
1632
2298
|
"div",
|
|
1633
2299
|
{
|
|
1634
2300
|
className: "absolute h-2 bg-blue-600 dark:bg-blue-500 rounded-full top-1/2 -translate-y-1/2 pointer-events-none",
|
|
1635
2301
|
style: { width: `${percentage}%` }
|
|
1636
2302
|
}
|
|
1637
2303
|
),
|
|
1638
|
-
/* @__PURE__ */
|
|
2304
|
+
/* @__PURE__ */ jsx57(
|
|
1639
2305
|
"input",
|
|
1640
2306
|
{
|
|
1641
2307
|
type: "range",
|
|
@@ -1657,8 +2323,8 @@ var Slider = ({
|
|
|
1657
2323
|
};
|
|
1658
2324
|
|
|
1659
2325
|
// src/components/Avatar.tsx
|
|
1660
|
-
import
|
|
1661
|
-
import { jsx as
|
|
2326
|
+
import React18 from "react";
|
|
2327
|
+
import { jsx as jsx58 } from "react/jsx-runtime";
|
|
1662
2328
|
var Avatar = ({
|
|
1663
2329
|
src,
|
|
1664
2330
|
alt,
|
|
@@ -1668,7 +2334,7 @@ var Avatar = ({
|
|
|
1668
2334
|
className = "",
|
|
1669
2335
|
fallbackColor = "bg-blue-600"
|
|
1670
2336
|
}) => {
|
|
1671
|
-
const [imageError, setImageError] =
|
|
2337
|
+
const [imageError, setImageError] = React18.useState(false);
|
|
1672
2338
|
const sizeClasses6 = {
|
|
1673
2339
|
xs: "w-6 h-6 text-xs",
|
|
1674
2340
|
sm: "w-8 h-8 text-sm",
|
|
@@ -1686,11 +2352,11 @@ var Avatar = ({
|
|
|
1686
2352
|
};
|
|
1687
2353
|
const showImage = src && !imageError;
|
|
1688
2354
|
const showInitials = !showImage && name;
|
|
1689
|
-
return /* @__PURE__ */
|
|
2355
|
+
return /* @__PURE__ */ jsx58(
|
|
1690
2356
|
"div",
|
|
1691
2357
|
{
|
|
1692
2358
|
className: `${sizeClasses6[size]} ${shapeClass} flex items-center justify-center overflow-hidden ${showImage ? "bg-gray-200 dark:bg-gray-700" : `${fallbackColor} text-white`} ${className}`,
|
|
1693
|
-
children: showImage ? /* @__PURE__ */
|
|
2359
|
+
children: showImage ? /* @__PURE__ */ jsx58(
|
|
1694
2360
|
"img",
|
|
1695
2361
|
{
|
|
1696
2362
|
src,
|
|
@@ -1698,13 +2364,13 @@ var Avatar = ({
|
|
|
1698
2364
|
className: "w-full h-full object-cover",
|
|
1699
2365
|
onError: () => setImageError(true)
|
|
1700
2366
|
}
|
|
1701
|
-
) : showInitials ? /* @__PURE__ */
|
|
2367
|
+
) : showInitials ? /* @__PURE__ */ jsx58("span", { className: "font-semibold select-none", children: getInitials(name) }) : /* @__PURE__ */ jsx58(
|
|
1702
2368
|
"svg",
|
|
1703
2369
|
{
|
|
1704
2370
|
className: "w-full h-full text-gray-400 dark:text-gray-600",
|
|
1705
2371
|
fill: "currentColor",
|
|
1706
2372
|
viewBox: "0 0 24 24",
|
|
1707
|
-
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" })
|
|
1708
2374
|
}
|
|
1709
2375
|
)
|
|
1710
2376
|
}
|
|
@@ -1712,7 +2378,7 @@ var Avatar = ({
|
|
|
1712
2378
|
};
|
|
1713
2379
|
|
|
1714
2380
|
// src/components/Textarea.tsx
|
|
1715
|
-
import { jsx as
|
|
2381
|
+
import { jsx as jsx59, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
1716
2382
|
var Textarea = ({
|
|
1717
2383
|
label,
|
|
1718
2384
|
error,
|
|
@@ -1739,9 +2405,9 @@ var Textarea = ({
|
|
|
1739
2405
|
bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100
|
|
1740
2406
|
placeholder:text-gray-500 dark:placeholder:text-gray-400
|
|
1741
2407
|
disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-gray-50 dark:disabled:bg-gray-900`;
|
|
1742
|
-
return /* @__PURE__ */
|
|
1743
|
-
label && /* @__PURE__ */
|
|
1744
|
-
/* @__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(
|
|
1745
2411
|
"textarea",
|
|
1746
2412
|
{
|
|
1747
2413
|
className: `${baseClasses} ${sizeClasses6[size]} ${resizeClasses[resize]}`,
|
|
@@ -1749,14 +2415,14 @@ var Textarea = ({
|
|
|
1749
2415
|
...props
|
|
1750
2416
|
}
|
|
1751
2417
|
),
|
|
1752
|
-
error && /* @__PURE__ */
|
|
1753
|
-
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 })
|
|
1754
2420
|
] });
|
|
1755
2421
|
};
|
|
1756
2422
|
|
|
1757
2423
|
// src/components/Toast.tsx
|
|
1758
|
-
import { createContext as createContext3, useContext as useContext3, useState as
|
|
1759
|
-
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";
|
|
1760
2426
|
var ToastContext = createContext3(void 0);
|
|
1761
2427
|
var useToast = () => {
|
|
1762
2428
|
const context = useContext3(ToastContext);
|
|
@@ -1766,7 +2432,7 @@ var useToast = () => {
|
|
|
1766
2432
|
return context;
|
|
1767
2433
|
};
|
|
1768
2434
|
var ToastProvider = ({ children, position = "top-right" }) => {
|
|
1769
|
-
const [toasts, setToasts] =
|
|
2435
|
+
const [toasts, setToasts] = useState10([]);
|
|
1770
2436
|
const addToast = useCallback((toast2) => {
|
|
1771
2437
|
const id = Math.random().toString(36).substring(7);
|
|
1772
2438
|
const newToast = { ...toast2, id };
|
|
@@ -1787,9 +2453,9 @@ var ToastProvider = ({ children, position = "top-right" }) => {
|
|
|
1787
2453
|
"top-center": "top-4 left-1/2 -translate-x-1/2",
|
|
1788
2454
|
"bottom-center": "bottom-4 left-1/2 -translate-x-1/2"
|
|
1789
2455
|
};
|
|
1790
|
-
return /* @__PURE__ */
|
|
2456
|
+
return /* @__PURE__ */ jsxs25(ToastContext.Provider, { value: { toasts, addToast, removeToast }, children: [
|
|
1791
2457
|
children,
|
|
1792
|
-
/* @__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)) })
|
|
1793
2459
|
] });
|
|
1794
2460
|
};
|
|
1795
2461
|
var ToastItem = ({ toast: toast2, onClose }) => {
|
|
@@ -1800,27 +2466,27 @@ var ToastItem = ({ toast: toast2, onClose }) => {
|
|
|
1800
2466
|
info: "bg-blue-50 dark:bg-blue-900/30 border-blue-500 text-blue-800 dark:text-blue-200"
|
|
1801
2467
|
};
|
|
1802
2468
|
const typeIcons = {
|
|
1803
|
-
success: /* @__PURE__ */
|
|
1804
|
-
error: /* @__PURE__ */
|
|
1805
|
-
warning: /* @__PURE__ */
|
|
1806
|
-
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" }) })
|
|
1807
2473
|
};
|
|
1808
2474
|
const type = toast2.type || "info";
|
|
1809
|
-
return /* @__PURE__ */
|
|
2475
|
+
return /* @__PURE__ */ jsxs25(
|
|
1810
2476
|
"div",
|
|
1811
2477
|
{
|
|
1812
2478
|
className: `flex items-start gap-3 p-4 rounded-lg border-l-4 shadow-lg backdrop-blur-sm ${typeStyles[type]} animate-slide-in`,
|
|
1813
2479
|
role: "alert",
|
|
1814
2480
|
children: [
|
|
1815
|
-
/* @__PURE__ */
|
|
1816
|
-
/* @__PURE__ */
|
|
1817
|
-
/* @__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(
|
|
1818
2484
|
"button",
|
|
1819
2485
|
{
|
|
1820
2486
|
onClick: onClose,
|
|
1821
2487
|
className: "flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 transition-colors",
|
|
1822
2488
|
"aria-label": "Close",
|
|
1823
|
-
children: /* @__PURE__ */
|
|
2489
|
+
children: /* @__PURE__ */ jsx60(CloseIcon, { size: "sm" })
|
|
1824
2490
|
}
|
|
1825
2491
|
)
|
|
1826
2492
|
]
|
|
@@ -1851,8 +2517,8 @@ var toast = {
|
|
|
1851
2517
|
};
|
|
1852
2518
|
|
|
1853
2519
|
// src/components/Stepper.tsx
|
|
1854
|
-
import
|
|
1855
|
-
import { jsx as
|
|
2520
|
+
import React20 from "react";
|
|
2521
|
+
import { jsx as jsx61, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
1856
2522
|
var Stepper = ({
|
|
1857
2523
|
steps,
|
|
1858
2524
|
currentStep,
|
|
@@ -1860,18 +2526,18 @@ var Stepper = ({
|
|
|
1860
2526
|
className = ""
|
|
1861
2527
|
}) => {
|
|
1862
2528
|
const isHorizontal = orientation === "horizontal";
|
|
1863
|
-
return /* @__PURE__ */
|
|
2529
|
+
return /* @__PURE__ */ jsx61("div", { className: `${isHorizontal ? "flex items-center" : "flex flex-col"} ${className}`, children: steps.map((step, index) => {
|
|
1864
2530
|
const stepNumber = index + 1;
|
|
1865
2531
|
const isActive = stepNumber === currentStep;
|
|
1866
2532
|
const isCompleted = stepNumber < currentStep;
|
|
1867
2533
|
const isLast = index === steps.length - 1;
|
|
1868
|
-
return /* @__PURE__ */
|
|
1869
|
-
/* @__PURE__ */
|
|
1870
|
-
/* @__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(
|
|
1871
2537
|
"div",
|
|
1872
2538
|
{
|
|
1873
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"}`,
|
|
1874
|
-
children: isCompleted ? /* @__PURE__ */
|
|
2540
|
+
children: isCompleted ? /* @__PURE__ */ jsx61(CheckIcon, { size: "sm", className: "text-white" }) : /* @__PURE__ */ jsx61(
|
|
1875
2541
|
"span",
|
|
1876
2542
|
{
|
|
1877
2543
|
className: `text-sm font-semibold ${isActive ? "text-blue-600 dark:text-blue-400" : "text-gray-500 dark:text-gray-400"}`,
|
|
@@ -1880,18 +2546,18 @@ var Stepper = ({
|
|
|
1880
2546
|
)
|
|
1881
2547
|
}
|
|
1882
2548
|
) }),
|
|
1883
|
-
/* @__PURE__ */
|
|
1884
|
-
/* @__PURE__ */
|
|
2549
|
+
/* @__PURE__ */ jsxs26("div", { className: `${isHorizontal ? "mt-2 text-center" : "ml-4 pb-8"} ${isLast && !isHorizontal ? "pb-0" : ""}`, children: [
|
|
2550
|
+
/* @__PURE__ */ jsx61(
|
|
1885
2551
|
"p",
|
|
1886
2552
|
{
|
|
1887
2553
|
className: `text-sm font-medium ${isActive || isCompleted ? "text-gray-900 dark:text-gray-100" : "text-gray-500 dark:text-gray-400"}`,
|
|
1888
2554
|
children: step.label
|
|
1889
2555
|
}
|
|
1890
2556
|
),
|
|
1891
|
-
step.description && /* @__PURE__ */
|
|
2557
|
+
step.description && /* @__PURE__ */ jsx61("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: step.description })
|
|
1892
2558
|
] })
|
|
1893
2559
|
] }),
|
|
1894
|
-
!isLast && /* @__PURE__ */
|
|
2560
|
+
!isLast && /* @__PURE__ */ jsx61(
|
|
1895
2561
|
"div",
|
|
1896
2562
|
{
|
|
1897
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"}`
|
|
@@ -1902,7 +2568,7 @@ var Stepper = ({
|
|
|
1902
2568
|
};
|
|
1903
2569
|
|
|
1904
2570
|
// src/components/Divider.tsx
|
|
1905
|
-
import { jsx as
|
|
2571
|
+
import { jsx as jsx62, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
1906
2572
|
var Divider = ({
|
|
1907
2573
|
orientation = "horizontal",
|
|
1908
2574
|
variant = "solid",
|
|
@@ -1921,14 +2587,14 @@ var Divider = ({
|
|
|
1921
2587
|
center: "justify-center",
|
|
1922
2588
|
right: "justify-end"
|
|
1923
2589
|
};
|
|
1924
|
-
return /* @__PURE__ */
|
|
1925
|
-
labelPosition !== "left" && /* @__PURE__ */
|
|
1926
|
-
/* @__PURE__ */
|
|
1927
|
-
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` })
|
|
1928
2594
|
] });
|
|
1929
2595
|
}
|
|
1930
2596
|
if (orientation === "vertical") {
|
|
1931
|
-
return /* @__PURE__ */
|
|
2597
|
+
return /* @__PURE__ */ jsx62(
|
|
1932
2598
|
"div",
|
|
1933
2599
|
{
|
|
1934
2600
|
className: `inline-block h-full border-l ${variantClasses[variant]} border-gray-300 dark:border-gray-600 ${className}`,
|
|
@@ -1937,7 +2603,7 @@ var Divider = ({
|
|
|
1937
2603
|
}
|
|
1938
2604
|
);
|
|
1939
2605
|
}
|
|
1940
|
-
return /* @__PURE__ */
|
|
2606
|
+
return /* @__PURE__ */ jsx62(
|
|
1941
2607
|
"hr",
|
|
1942
2608
|
{
|
|
1943
2609
|
className: `border-t ${variantClasses[variant]} border-gray-300 dark:border-gray-600 ${className}`,
|
|
@@ -1947,8 +2613,8 @@ var Divider = ({
|
|
|
1947
2613
|
};
|
|
1948
2614
|
|
|
1949
2615
|
// src/components/FileUpload.tsx
|
|
1950
|
-
import { useRef as
|
|
1951
|
-
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";
|
|
1952
2618
|
var FileUpload = ({
|
|
1953
2619
|
accept,
|
|
1954
2620
|
multiple = false,
|
|
@@ -1961,9 +2627,9 @@ var FileUpload = ({
|
|
|
1961
2627
|
label,
|
|
1962
2628
|
helperText
|
|
1963
2629
|
}) => {
|
|
1964
|
-
const [files, setFiles] =
|
|
1965
|
-
const [isDragging, setIsDragging] =
|
|
1966
|
-
const fileInputRef =
|
|
2630
|
+
const [files, setFiles] = useState11([]);
|
|
2631
|
+
const [isDragging, setIsDragging] = useState11(false);
|
|
2632
|
+
const fileInputRef = useRef5(null);
|
|
1967
2633
|
const formatFileSize = (bytes) => {
|
|
1968
2634
|
if (bytes === 0) return "0 Bytes";
|
|
1969
2635
|
const k = 1024;
|
|
@@ -2021,9 +2687,9 @@ var FileUpload = ({
|
|
|
2021
2687
|
setFiles(newFiles);
|
|
2022
2688
|
onChange?.(newFiles);
|
|
2023
2689
|
};
|
|
2024
|
-
return /* @__PURE__ */
|
|
2025
|
-
label && /* @__PURE__ */
|
|
2026
|
-
/* @__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(
|
|
2027
2693
|
"div",
|
|
2028
2694
|
{
|
|
2029
2695
|
onDrop: handleDrop,
|
|
@@ -2032,7 +2698,7 @@ var FileUpload = ({
|
|
|
2032
2698
|
onClick: handleClick,
|
|
2033
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" : ""}`,
|
|
2034
2700
|
children: [
|
|
2035
|
-
/* @__PURE__ */
|
|
2701
|
+
/* @__PURE__ */ jsx63(
|
|
2036
2702
|
"input",
|
|
2037
2703
|
{
|
|
2038
2704
|
ref: fileInputRef,
|
|
@@ -2044,14 +2710,14 @@ var FileUpload = ({
|
|
|
2044
2710
|
className: "hidden"
|
|
2045
2711
|
}
|
|
2046
2712
|
),
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2049
|
-
/* @__PURE__ */
|
|
2050
|
-
/* @__PURE__ */
|
|
2051
|
-
/* @__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" }),
|
|
2052
2718
|
" or drag and drop"
|
|
2053
2719
|
] }),
|
|
2054
|
-
/* @__PURE__ */
|
|
2720
|
+
/* @__PURE__ */ jsxs28("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: [
|
|
2055
2721
|
accept ? `Accepted: ${accept}` : "Any file type",
|
|
2056
2722
|
maxSize && ` \u2022 Max size: ${formatFileSize(maxSize)}`
|
|
2057
2723
|
] })
|
|
@@ -2060,17 +2726,17 @@ var FileUpload = ({
|
|
|
2060
2726
|
]
|
|
2061
2727
|
}
|
|
2062
2728
|
),
|
|
2063
|
-
helperText && /* @__PURE__ */
|
|
2064
|
-
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(
|
|
2065
2731
|
"div",
|
|
2066
2732
|
{
|
|
2067
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",
|
|
2068
2734
|
children: [
|
|
2069
|
-
/* @__PURE__ */
|
|
2070
|
-
/* @__PURE__ */
|
|
2071
|
-
/* @__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) })
|
|
2072
2738
|
] }),
|
|
2073
|
-
/* @__PURE__ */
|
|
2739
|
+
/* @__PURE__ */ jsx63(
|
|
2074
2740
|
"button",
|
|
2075
2741
|
{
|
|
2076
2742
|
onClick: (e) => {
|
|
@@ -2079,7 +2745,7 @@ var FileUpload = ({
|
|
|
2079
2745
|
},
|
|
2080
2746
|
className: "ml-4 text-gray-400 hover:text-red-600 dark:hover:text-red-400 transition-colors",
|
|
2081
2747
|
"aria-label": "Remove file",
|
|
2082
|
-
children: /* @__PURE__ */
|
|
2748
|
+
children: /* @__PURE__ */ jsx63(CloseIcon, { size: "sm" })
|
|
2083
2749
|
}
|
|
2084
2750
|
)
|
|
2085
2751
|
]
|
|
@@ -2130,6 +2796,7 @@ export {
|
|
|
2130
2796
|
Badge,
|
|
2131
2797
|
BellIcon,
|
|
2132
2798
|
Button,
|
|
2799
|
+
Calendar,
|
|
2133
2800
|
CalendarIcon,
|
|
2134
2801
|
CameraIcon,
|
|
2135
2802
|
Card,
|