@neoptocom/neopto-ui 1.5.4 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +340 -51
- package/dist/index.d.cts +48 -1
- package/dist/index.d.ts +48 -1
- package/dist/index.js +305 -18
- package/package.json +1 -1
- package/src/components/Autocomplete.tsx +2 -2
- package/src/components/Calendar.tsx +212 -0
- package/src/components/DateInput.tsx +225 -0
- package/src/index.ts +5 -1
- package/src/stories/DateInput.stories.tsx +136 -0
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var
|
|
4
|
+
var React11 = require('react');
|
|
5
5
|
var reactDom = require('react-dom');
|
|
6
6
|
|
|
7
7
|
function _interopNamespace(e) {
|
|
@@ -22,7 +22,7 @@ function _interopNamespace(e) {
|
|
|
22
22
|
return Object.freeze(n);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
var
|
|
25
|
+
var React11__namespace = /*#__PURE__*/_interopNamespace(React11);
|
|
26
26
|
|
|
27
27
|
var __defProp = Object.defineProperty;
|
|
28
28
|
var __export = (target, all) => {
|
|
@@ -107,9 +107,9 @@ function BackgroundBlur({
|
|
|
107
107
|
zIndex = 40,
|
|
108
108
|
className = ""
|
|
109
109
|
}) {
|
|
110
|
-
const [shouldRender, setShouldRender] =
|
|
111
|
-
const [isVisible, setIsVisible] =
|
|
112
|
-
|
|
110
|
+
const [shouldRender, setShouldRender] = React11.useState(false);
|
|
111
|
+
const [isVisible, setIsVisible] = React11.useState(false);
|
|
112
|
+
React11.useEffect(() => {
|
|
113
113
|
if (open) {
|
|
114
114
|
setShouldRender(true);
|
|
115
115
|
requestAnimationFrame(() => {
|
|
@@ -297,7 +297,7 @@ function Icon({
|
|
|
297
297
|
}
|
|
298
298
|
);
|
|
299
299
|
}
|
|
300
|
-
var Input =
|
|
300
|
+
var Input = React11__namespace.forwardRef(
|
|
301
301
|
({
|
|
302
302
|
className,
|
|
303
303
|
disabled,
|
|
@@ -390,7 +390,7 @@ var Input = React3__namespace.forwardRef(
|
|
|
390
390
|
}
|
|
391
391
|
);
|
|
392
392
|
Input.displayName = "Input";
|
|
393
|
-
var Textarea =
|
|
393
|
+
var Textarea = React11__namespace.forwardRef(
|
|
394
394
|
({ className, disabled, variant = "default", ...props }, ref) => {
|
|
395
395
|
const isInline = variant === "inline";
|
|
396
396
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -419,7 +419,7 @@ var Textarea = React3__namespace.forwardRef(
|
|
|
419
419
|
);
|
|
420
420
|
Textarea.displayName = "Textarea";
|
|
421
421
|
function useIsomorphicLayoutEffect(effect, deps) {
|
|
422
|
-
const useEffectHook = typeof window !== "undefined" ?
|
|
422
|
+
const useEffectHook = typeof window !== "undefined" ? React11__namespace.useLayoutEffect : React11__namespace.useEffect;
|
|
423
423
|
useEffectHook(effect, deps);
|
|
424
424
|
}
|
|
425
425
|
function Modal({
|
|
@@ -431,9 +431,9 @@ function Modal({
|
|
|
431
431
|
zIndex = 50,
|
|
432
432
|
showDecorations = true
|
|
433
433
|
}) {
|
|
434
|
-
const [mounted, setMounted] =
|
|
435
|
-
const [isDark, setIsDark] =
|
|
436
|
-
|
|
434
|
+
const [mounted, setMounted] = React11__namespace.useState(false);
|
|
435
|
+
const [isDark, setIsDark] = React11__namespace.useState(false);
|
|
436
|
+
React11__namespace.useEffect(() => {
|
|
437
437
|
const checkDarkMode = () => {
|
|
438
438
|
const hasDarkClass = document.documentElement.classList.contains("dark") || document.body.classList.contains("dark") || document.querySelector(".dark") !== null;
|
|
439
439
|
setIsDark(hasDarkClass);
|
|
@@ -456,7 +456,7 @@ function Modal({
|
|
|
456
456
|
document.body.style.overflow = original;
|
|
457
457
|
};
|
|
458
458
|
}, [open]);
|
|
459
|
-
|
|
459
|
+
React11__namespace.useEffect(() => {
|
|
460
460
|
if (!open) return;
|
|
461
461
|
const onKey = (e) => {
|
|
462
462
|
if (e.key === "Escape") onClose?.();
|
|
@@ -579,9 +579,9 @@ function Avatar({
|
|
|
579
579
|
style,
|
|
580
580
|
...props
|
|
581
581
|
}) {
|
|
582
|
-
const [imgError, setImgError] =
|
|
583
|
-
const initials =
|
|
584
|
-
const computedStyle =
|
|
582
|
+
const [imgError, setImgError] = React11.useState(false);
|
|
583
|
+
const initials = React11.useMemo(() => getInitials(name), [name]);
|
|
584
|
+
const computedStyle = React11.useMemo(() => {
|
|
585
585
|
const s = { ...style };
|
|
586
586
|
if (color) s.backgroundColor = color;
|
|
587
587
|
return s;
|
|
@@ -616,7 +616,7 @@ function AvatarGroup({
|
|
|
616
616
|
overlapPx = 8,
|
|
617
617
|
withRings = true
|
|
618
618
|
}) {
|
|
619
|
-
const avatars =
|
|
619
|
+
const avatars = React11__namespace.Children.toArray(children);
|
|
620
620
|
const displayAvatars = typeof max === "number" ? avatars.slice(0, max) : avatars;
|
|
621
621
|
const extraCount = typeof max === "number" && avatars.length > max ? avatars.length - max : 0;
|
|
622
622
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["flex items-center", className].filter(Boolean).join(" "), children: [
|
|
@@ -684,7 +684,7 @@ function getIconButtonClasses(variant = "ghost", size = "md", className) {
|
|
|
684
684
|
};
|
|
685
685
|
return [base, variants[variant], sizes[size], className].filter(Boolean).join(" ");
|
|
686
686
|
}
|
|
687
|
-
var IconButton =
|
|
687
|
+
var IconButton = React11__namespace.forwardRef(
|
|
688
688
|
({
|
|
689
689
|
variant,
|
|
690
690
|
size,
|
|
@@ -731,14 +731,14 @@ function Autocomplete({
|
|
|
731
731
|
id,
|
|
732
732
|
...props
|
|
733
733
|
}) {
|
|
734
|
-
const inputId = id ??
|
|
734
|
+
const inputId = id ?? React11.useId();
|
|
735
735
|
const listboxId = `${inputId}-listbox`;
|
|
736
|
-
const [searchQuery, setSearchQuery] =
|
|
737
|
-
const [open, setOpen] =
|
|
738
|
-
const [activeIndex, setActiveIndex] =
|
|
739
|
-
const rootRef =
|
|
740
|
-
const listRef =
|
|
741
|
-
const normalizedOptions =
|
|
736
|
+
const [searchQuery, setSearchQuery] = React11.useState("");
|
|
737
|
+
const [open, setOpen] = React11.useState(false);
|
|
738
|
+
const [activeIndex, setActiveIndex] = React11.useState(-1);
|
|
739
|
+
const rootRef = React11.useRef(null);
|
|
740
|
+
const listRef = React11.useRef(null);
|
|
741
|
+
const normalizedOptions = React11.useMemo(() => {
|
|
742
742
|
if (Array.isArray(options) && typeof options[0] === "string") {
|
|
743
743
|
return options.map((str) => ({
|
|
744
744
|
name: str,
|
|
@@ -755,7 +755,7 @@ function Autocomplete({
|
|
|
755
755
|
};
|
|
756
756
|
});
|
|
757
757
|
}, [options]);
|
|
758
|
-
const filtered =
|
|
758
|
+
const filtered = React11.useMemo(() => {
|
|
759
759
|
const q = searchQuery.trim().toLowerCase();
|
|
760
760
|
if (!q) return normalizedOptions;
|
|
761
761
|
return normalizedOptions.filter((o) => {
|
|
@@ -764,7 +764,7 @@ function Autocomplete({
|
|
|
764
764
|
return name.includes(q) || label.includes(q);
|
|
765
765
|
});
|
|
766
766
|
}, [normalizedOptions, searchQuery]);
|
|
767
|
-
const anyOptionHasImage =
|
|
767
|
+
const anyOptionHasImage = React11.useMemo(
|
|
768
768
|
() => normalizedOptions.some((o) => !!o.image),
|
|
769
769
|
[normalizedOptions]
|
|
770
770
|
);
|
|
@@ -843,7 +843,7 @@ function Autocomplete({
|
|
|
843
843
|
"fieldset",
|
|
844
844
|
{
|
|
845
845
|
className: [
|
|
846
|
-
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors h-
|
|
846
|
+
"w-full min-w-0 rounded-full border bg-[var(--surface)] transition-colors h-14",
|
|
847
847
|
"border-[var(--border)] focus-within:border-[var(--color-brand)]",
|
|
848
848
|
disabled ? "opacity-60 cursor-not-allowed" : ""
|
|
849
849
|
].join(" "),
|
|
@@ -897,7 +897,7 @@ function Autocomplete({
|
|
|
897
897
|
onClick: selectedOption && !open ? handleClear : () => setOpen((s) => !s),
|
|
898
898
|
disabled,
|
|
899
899
|
"aria-label": selectedOption && !open ? "Clear" : open ? "Collapse" : "Expand",
|
|
900
|
-
className: "absolute right-
|
|
900
|
+
className: "absolute right-1 top-[-20%]",
|
|
901
901
|
iconClassName: [
|
|
902
902
|
"transition-transform duration-300 text-[var(--muted-fg)]",
|
|
903
903
|
open ? "rotate-180 text-[var(--color-brand)]" : ""
|
|
@@ -969,27 +969,27 @@ function Search({
|
|
|
969
969
|
children,
|
|
970
970
|
...props
|
|
971
971
|
}) {
|
|
972
|
-
const inputId = id ??
|
|
972
|
+
const inputId = id ?? React11.useId();
|
|
973
973
|
const listboxId = `${inputId}-listbox`;
|
|
974
|
-
const [searchQuery, setSearchQuery] =
|
|
975
|
-
const [open, setOpen] =
|
|
976
|
-
const [activeIndex, setActiveIndex] =
|
|
977
|
-
const [filtersExpanded, setFiltersExpanded] =
|
|
978
|
-
const rootRef =
|
|
979
|
-
const listRef =
|
|
980
|
-
const searchTimeoutRef =
|
|
981
|
-
const normalizedOptions =
|
|
974
|
+
const [searchQuery, setSearchQuery] = React11.useState("");
|
|
975
|
+
const [open, setOpen] = React11.useState(false);
|
|
976
|
+
const [activeIndex, setActiveIndex] = React11.useState(-1);
|
|
977
|
+
const [filtersExpanded, setFiltersExpanded] = React11.useState(false);
|
|
978
|
+
const rootRef = React11.useRef(null);
|
|
979
|
+
const listRef = React11.useRef(null);
|
|
980
|
+
const searchTimeoutRef = React11.useRef(null);
|
|
981
|
+
const normalizedOptions = React11.useMemo(() => {
|
|
982
982
|
if (Array.isArray(options) && typeof options[0] === "string") {
|
|
983
983
|
return options.map((str) => ({ label: str, value: str }));
|
|
984
984
|
}
|
|
985
985
|
return options;
|
|
986
986
|
}, [options]);
|
|
987
|
-
|
|
987
|
+
React11.useMemo(
|
|
988
988
|
() => normalizedOptions.some((o) => !!o.image),
|
|
989
989
|
[normalizedOptions]
|
|
990
990
|
);
|
|
991
991
|
const displayValue = selectedOption != null ? typeof selectedOption === "string" ? selectedOption : selectedOption.label : searchQuery;
|
|
992
|
-
const debouncedSearch =
|
|
992
|
+
const debouncedSearch = React11.useCallback(
|
|
993
993
|
(query) => {
|
|
994
994
|
if (searchTimeoutRef.current) {
|
|
995
995
|
clearTimeout(searchTimeoutRef.current);
|
|
@@ -1058,7 +1058,7 @@ function Search({
|
|
|
1058
1058
|
const el = list.children[idx];
|
|
1059
1059
|
el?.scrollIntoView({ block: "nearest" });
|
|
1060
1060
|
}
|
|
1061
|
-
|
|
1061
|
+
React11__namespace.useEffect(() => {
|
|
1062
1062
|
return () => {
|
|
1063
1063
|
if (searchTimeoutRef.current) {
|
|
1064
1064
|
clearTimeout(searchTimeoutRef.current);
|
|
@@ -1165,7 +1165,7 @@ function getButtonClasses(variant = "primary", size = "md", fullWidth, className
|
|
|
1165
1165
|
className
|
|
1166
1166
|
].filter(Boolean).join(" ");
|
|
1167
1167
|
}
|
|
1168
|
-
var Button =
|
|
1168
|
+
var Button = React11__namespace.forwardRef(
|
|
1169
1169
|
({ variant, size, fullWidth, className, children, icon, ...props }, ref) => {
|
|
1170
1170
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1171
1171
|
"button",
|
|
@@ -1237,8 +1237,8 @@ function Counter({
|
|
|
1237
1237
|
className = "",
|
|
1238
1238
|
...props
|
|
1239
1239
|
}) {
|
|
1240
|
-
const [count, setCount] =
|
|
1241
|
-
|
|
1240
|
+
const [count, setCount] = React11__namespace.useState(value);
|
|
1241
|
+
React11__namespace.useEffect(() => {
|
|
1242
1242
|
setCount(value);
|
|
1243
1243
|
}, [value]);
|
|
1244
1244
|
const handleIncrement = () => {
|
|
@@ -1281,7 +1281,7 @@ function Counter({
|
|
|
1281
1281
|
] });
|
|
1282
1282
|
}
|
|
1283
1283
|
var AnimatedBgCircle = ({ colors, delay = 0 }) => {
|
|
1284
|
-
const uniqueId =
|
|
1284
|
+
const uniqueId = React11.useMemo(() => Math.random().toString(36).substr(2, 9), []);
|
|
1285
1285
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 64 64", fill: "none", className: "h-full transition-all duration-500 ease-in-out w-full", children: [
|
|
1286
1286
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
1287
1287
|
@keyframes colorCycle-${uniqueId} {
|
|
@@ -1313,7 +1313,7 @@ var AnimatedBgCircle = ({ colors, delay = 0 }) => {
|
|
|
1313
1313
|
};
|
|
1314
1314
|
var AnimatedBgCircle_default = AnimatedBgCircle;
|
|
1315
1315
|
var AnimatedBgRectangle = ({ colors, delay = 0 }) => {
|
|
1316
|
-
const uniqueId =
|
|
1316
|
+
const uniqueId = React11.useMemo(() => Math.random().toString(36).substr(2, 9), []);
|
|
1317
1317
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1318
1318
|
"svg",
|
|
1319
1319
|
{
|
|
@@ -1362,14 +1362,14 @@ var AgentButton = ({
|
|
|
1362
1362
|
animationColors = ["#7DADB9", "#3864F5", "#55468D", "#479A8D"],
|
|
1363
1363
|
disabled = false
|
|
1364
1364
|
}) => {
|
|
1365
|
-
const [showText, setShowText] =
|
|
1366
|
-
const [delayedHasNotification, setDelayedHasNotification] =
|
|
1367
|
-
const [isMounted, setIsMounted] =
|
|
1368
|
-
|
|
1365
|
+
const [showText, setShowText] = React11.useState(false);
|
|
1366
|
+
const [delayedHasNotification, setDelayedHasNotification] = React11.useState(false);
|
|
1367
|
+
const [isMounted, setIsMounted] = React11.useState(false);
|
|
1368
|
+
React11.useEffect(() => {
|
|
1369
1369
|
const timer = setTimeout(() => setIsMounted(true), 250);
|
|
1370
1370
|
return () => clearTimeout(timer);
|
|
1371
1371
|
}, []);
|
|
1372
|
-
|
|
1372
|
+
React11.useEffect(() => {
|
|
1373
1373
|
if (hasNotification) {
|
|
1374
1374
|
const textTimer = setTimeout(() => setShowText(true), 500);
|
|
1375
1375
|
setDelayedHasNotification(true);
|
|
@@ -1471,7 +1471,7 @@ var AgentButton = ({
|
|
|
1471
1471
|
);
|
|
1472
1472
|
};
|
|
1473
1473
|
var AgentButton_default = AgentButton;
|
|
1474
|
-
var MessageBubble =
|
|
1474
|
+
var MessageBubble = React11__namespace.forwardRef(
|
|
1475
1475
|
({ direction, color, children, className, ...props }, ref) => {
|
|
1476
1476
|
const borderRadiusClass = direction === "left" ? "[border-radius:16px_16px_16px_2px]" : direction === "right" ? "[border-radius:16px_16px_2px_16px]" : "rounded-2xl";
|
|
1477
1477
|
const backgroundColor = color || "var(--muted)";
|
|
@@ -1549,6 +1549,293 @@ var Breadcrumb = ({
|
|
|
1549
1549
|
] }, index);
|
|
1550
1550
|
}) }) });
|
|
1551
1551
|
};
|
|
1552
|
+
var DAYS_OF_WEEK = ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "S\xE1b"];
|
|
1553
|
+
var MONTHS = ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"];
|
|
1554
|
+
function isSameDay(date1, date2) {
|
|
1555
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1556
|
+
}
|
|
1557
|
+
function isSameMonth(date1, date2) {
|
|
1558
|
+
return date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1559
|
+
}
|
|
1560
|
+
function startOfDay(date) {
|
|
1561
|
+
const d = new Date(date);
|
|
1562
|
+
d.setHours(0, 0, 0, 0);
|
|
1563
|
+
return d;
|
|
1564
|
+
}
|
|
1565
|
+
function Calendar({
|
|
1566
|
+
selectedDate,
|
|
1567
|
+
onDateSelect,
|
|
1568
|
+
today = /* @__PURE__ */ new Date(),
|
|
1569
|
+
minDate,
|
|
1570
|
+
maxDate
|
|
1571
|
+
}) {
|
|
1572
|
+
const [currentMonth, setCurrentMonth] = React11__namespace.useState(
|
|
1573
|
+
selectedDate || /* @__PURE__ */ new Date()
|
|
1574
|
+
);
|
|
1575
|
+
const todayStart = startOfDay(today);
|
|
1576
|
+
const selectedDateStart = selectedDate ? startOfDay(selectedDate) : null;
|
|
1577
|
+
const firstDayOfMonth = new Date(
|
|
1578
|
+
currentMonth.getFullYear(),
|
|
1579
|
+
currentMonth.getMonth(),
|
|
1580
|
+
1
|
|
1581
|
+
);
|
|
1582
|
+
const lastDayOfMonth = new Date(
|
|
1583
|
+
currentMonth.getFullYear(),
|
|
1584
|
+
currentMonth.getMonth() + 1,
|
|
1585
|
+
0
|
|
1586
|
+
);
|
|
1587
|
+
const daysInMonth = lastDayOfMonth.getDate();
|
|
1588
|
+
const startingDayOfWeek = firstDayOfMonth.getDay();
|
|
1589
|
+
const prevMonth = () => {
|
|
1590
|
+
setCurrentMonth(
|
|
1591
|
+
new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1)
|
|
1592
|
+
);
|
|
1593
|
+
};
|
|
1594
|
+
const nextMonth = () => {
|
|
1595
|
+
setCurrentMonth(
|
|
1596
|
+
new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)
|
|
1597
|
+
);
|
|
1598
|
+
};
|
|
1599
|
+
const handleDateClick = (day) => {
|
|
1600
|
+
const date = new Date(
|
|
1601
|
+
currentMonth.getFullYear(),
|
|
1602
|
+
currentMonth.getMonth(),
|
|
1603
|
+
day
|
|
1604
|
+
);
|
|
1605
|
+
const dateStart = startOfDay(date);
|
|
1606
|
+
if (minDate && dateStart < startOfDay(minDate)) return;
|
|
1607
|
+
if (maxDate && dateStart > startOfDay(maxDate)) return;
|
|
1608
|
+
onDateSelect(date);
|
|
1609
|
+
};
|
|
1610
|
+
const isDateDisabled = (day) => {
|
|
1611
|
+
const date = new Date(
|
|
1612
|
+
currentMonth.getFullYear(),
|
|
1613
|
+
currentMonth.getMonth(),
|
|
1614
|
+
day
|
|
1615
|
+
);
|
|
1616
|
+
const dateStart = startOfDay(date);
|
|
1617
|
+
if (minDate && dateStart < startOfDay(minDate)) return true;
|
|
1618
|
+
if (maxDate && dateStart > startOfDay(maxDate)) return true;
|
|
1619
|
+
return false;
|
|
1620
|
+
};
|
|
1621
|
+
const days = [];
|
|
1622
|
+
for (let i = 0; i < startingDayOfWeek; i++) {
|
|
1623
|
+
days.push(null);
|
|
1624
|
+
}
|
|
1625
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
1626
|
+
days.push(day);
|
|
1627
|
+
}
|
|
1628
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
|
|
1629
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
1630
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1631
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typo, { variant: "title-md", bold: "medium", className: "text-[var(--fg)]", children: MONTHS[currentMonth.getMonth()] }),
|
|
1632
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typo, { variant: "title-md", bold: "medium", className: "text-cyan-500", children: currentMonth.getFullYear() })
|
|
1633
|
+
] }),
|
|
1634
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1635
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1636
|
+
"button",
|
|
1637
|
+
{
|
|
1638
|
+
type: "button",
|
|
1639
|
+
onClick: prevMonth,
|
|
1640
|
+
className: "p-2 rounded-full hover:bg-[var(--muted)] transition-colors",
|
|
1641
|
+
"aria-label": "Previous month",
|
|
1642
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "material-symbols-rounded text-[var(--fg)]", children: "chevron_left" })
|
|
1643
|
+
}
|
|
1644
|
+
),
|
|
1645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1646
|
+
"button",
|
|
1647
|
+
{
|
|
1648
|
+
type: "button",
|
|
1649
|
+
onClick: nextMonth,
|
|
1650
|
+
className: "p-2 rounded-full hover:bg-[var(--muted)] transition-colors",
|
|
1651
|
+
"aria-label": "Next month",
|
|
1652
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "material-symbols-rounded text-[var(--fg)]", children: "chevron_right" })
|
|
1653
|
+
}
|
|
1654
|
+
)
|
|
1655
|
+
] })
|
|
1656
|
+
] }),
|
|
1657
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS_OF_WEEK.map((day) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1658
|
+
"div",
|
|
1659
|
+
{
|
|
1660
|
+
className: "text-xs text-center text-[var(--muted-fg)] font-medium py-1",
|
|
1661
|
+
children: day
|
|
1662
|
+
},
|
|
1663
|
+
day
|
|
1664
|
+
)) }),
|
|
1665
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((day, idx) => {
|
|
1666
|
+
if (day === null) {
|
|
1667
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-square" }, `empty-${idx}`);
|
|
1668
|
+
}
|
|
1669
|
+
const date = new Date(
|
|
1670
|
+
currentMonth.getFullYear(),
|
|
1671
|
+
currentMonth.getMonth(),
|
|
1672
|
+
day
|
|
1673
|
+
);
|
|
1674
|
+
const dateStart = startOfDay(date);
|
|
1675
|
+
const isSelected = selectedDateStart && isSameDay(dateStart, selectedDateStart);
|
|
1676
|
+
const isToday = isSameDay(dateStart, todayStart);
|
|
1677
|
+
const isDisabled = isDateDisabled(day);
|
|
1678
|
+
const isCurrentMonth = isSameMonth(dateStart, currentMonth);
|
|
1679
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1680
|
+
"button",
|
|
1681
|
+
{
|
|
1682
|
+
type: "button",
|
|
1683
|
+
onClick: () => handleDateClick(day),
|
|
1684
|
+
disabled: isDisabled,
|
|
1685
|
+
className: [
|
|
1686
|
+
"aspect-square rounded-lg text-sm transition-colors",
|
|
1687
|
+
isSelected ? "bg-[var(--color-brand)] text-white font-medium" : isToday ? "bg-[var(--muted)] text-[var(--fg)] font-medium border border-[var(--color-brand)]" : "text-[var(--fg)] hover:bg-[var(--muted)]",
|
|
1688
|
+
isDisabled ? "opacity-30 cursor-not-allowed" : "cursor-pointer",
|
|
1689
|
+
!isCurrentMonth ? "opacity-50" : ""
|
|
1690
|
+
].filter(Boolean).join(" "),
|
|
1691
|
+
children: day
|
|
1692
|
+
},
|
|
1693
|
+
day
|
|
1694
|
+
);
|
|
1695
|
+
}) })
|
|
1696
|
+
] });
|
|
1697
|
+
}
|
|
1698
|
+
function formatDate(date) {
|
|
1699
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1700
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1701
|
+
const year = date.getFullYear();
|
|
1702
|
+
return `${day}/${month}/${year}`;
|
|
1703
|
+
}
|
|
1704
|
+
function parseDate(dateString) {
|
|
1705
|
+
const parts = dateString.split("/");
|
|
1706
|
+
if (parts.length !== 3) return null;
|
|
1707
|
+
const day = parseInt(parts[0], 10);
|
|
1708
|
+
const month = parseInt(parts[1], 10) - 1;
|
|
1709
|
+
const year = parseInt(parts[2], 10);
|
|
1710
|
+
if (isNaN(day) || isNaN(month) || isNaN(year)) return null;
|
|
1711
|
+
const date = new Date(year, month, day);
|
|
1712
|
+
if (date.getDate() !== day || date.getMonth() !== month || date.getFullYear() !== year) {
|
|
1713
|
+
return null;
|
|
1714
|
+
}
|
|
1715
|
+
return date;
|
|
1716
|
+
}
|
|
1717
|
+
function isValidDate(date) {
|
|
1718
|
+
return date instanceof Date && !isNaN(date.getTime());
|
|
1719
|
+
}
|
|
1720
|
+
function startOfDay2(date) {
|
|
1721
|
+
const d = new Date(date);
|
|
1722
|
+
d.setHours(0, 0, 0, 0);
|
|
1723
|
+
return d;
|
|
1724
|
+
}
|
|
1725
|
+
var DateInput = React11__namespace.forwardRef(
|
|
1726
|
+
({
|
|
1727
|
+
label,
|
|
1728
|
+
value,
|
|
1729
|
+
onChange,
|
|
1730
|
+
error = false,
|
|
1731
|
+
disabled = false,
|
|
1732
|
+
minDate,
|
|
1733
|
+
maxDate,
|
|
1734
|
+
placeholder = "00/00/0000",
|
|
1735
|
+
className = "",
|
|
1736
|
+
...props
|
|
1737
|
+
}, ref) => {
|
|
1738
|
+
const [inputValue, setInputValue] = React11__namespace.useState(
|
|
1739
|
+
value && isValidDate(value) ? formatDate(value) : placeholder
|
|
1740
|
+
);
|
|
1741
|
+
const [isFocused, setIsFocused] = React11__namespace.useState(false);
|
|
1742
|
+
const [showCalendar, setShowCalendar] = React11__namespace.useState(false);
|
|
1743
|
+
const [initialDateSet, setInitialDateSet] = React11__namespace.useState(true);
|
|
1744
|
+
const containerRef = React11__namespace.useRef(null);
|
|
1745
|
+
React11__namespace.useEffect(() => {
|
|
1746
|
+
if (value && isValidDate(value)) {
|
|
1747
|
+
setInputValue(formatDate(value));
|
|
1748
|
+
} else {
|
|
1749
|
+
setInputValue(placeholder);
|
|
1750
|
+
}
|
|
1751
|
+
}, [value, placeholder]);
|
|
1752
|
+
React11__namespace.useEffect(() => {
|
|
1753
|
+
if (showCalendar && initialDateSet) {
|
|
1754
|
+
const today = /* @__PURE__ */ new Date();
|
|
1755
|
+
onChange(today);
|
|
1756
|
+
setInputValue(formatDate(today));
|
|
1757
|
+
setInitialDateSet(false);
|
|
1758
|
+
}
|
|
1759
|
+
}, [showCalendar, initialDateSet, onChange]);
|
|
1760
|
+
React11__namespace.useEffect(() => {
|
|
1761
|
+
const handleClickOutside = (event) => {
|
|
1762
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1763
|
+
setShowCalendar(false);
|
|
1764
|
+
setInitialDateSet(false);
|
|
1765
|
+
}
|
|
1766
|
+
};
|
|
1767
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1768
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1769
|
+
}, []);
|
|
1770
|
+
const handleInputChange = (e) => {
|
|
1771
|
+
let rawValue = e.target.value;
|
|
1772
|
+
rawValue = rawValue.replace(/\D/g, "").replace(/^(\d{2})/, "$1/").replace(/^(\d{2}\/\d{2})/, "$1/").slice(0, 10);
|
|
1773
|
+
setInputValue(rawValue);
|
|
1774
|
+
if (rawValue.length === 10) {
|
|
1775
|
+
const parsedDate = parseDate(rawValue);
|
|
1776
|
+
if (parsedDate && isValidDate(parsedDate)) {
|
|
1777
|
+
onChange(parsedDate);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
const handleCalendarSelect = (date) => {
|
|
1782
|
+
const selectedDate = parseDate(inputValue);
|
|
1783
|
+
const sameDay = selectedDate && isValidDate(selectedDate) && selectedDate.getDate() === date.getDate() && selectedDate.getMonth() === date.getMonth() && selectedDate.getFullYear() === date.getFullYear();
|
|
1784
|
+
if (!sameDay) {
|
|
1785
|
+
onChange(date);
|
|
1786
|
+
setInputValue(formatDate(date));
|
|
1787
|
+
}
|
|
1788
|
+
setInitialDateSet(false);
|
|
1789
|
+
setShowCalendar(false);
|
|
1790
|
+
};
|
|
1791
|
+
const handleInputFocus = () => {
|
|
1792
|
+
setIsFocused(true);
|
|
1793
|
+
setShowCalendar(true);
|
|
1794
|
+
};
|
|
1795
|
+
const handleInputBlur = () => {
|
|
1796
|
+
setIsFocused(false);
|
|
1797
|
+
const parsed = parseDate(inputValue);
|
|
1798
|
+
if (!parsed || !isValidDate(parsed)) {
|
|
1799
|
+
const today = /* @__PURE__ */ new Date();
|
|
1800
|
+
onChange(today);
|
|
1801
|
+
setInputValue(formatDate(today));
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
const isEmpty = inputValue === placeholder;
|
|
1805
|
+
const textColorClass = isEmpty ? "text-[var(--muted-fg)]" : "";
|
|
1806
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["relative w-full", className].join(" "), ref: containerRef, children: [
|
|
1807
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1808
|
+
Input,
|
|
1809
|
+
{
|
|
1810
|
+
ref,
|
|
1811
|
+
label,
|
|
1812
|
+
type: "text",
|
|
1813
|
+
value: inputValue,
|
|
1814
|
+
onChange: handleInputChange,
|
|
1815
|
+
onFocus: handleInputFocus,
|
|
1816
|
+
onBlur: handleInputBlur,
|
|
1817
|
+
onClick: () => !disabled && setShowCalendar(true),
|
|
1818
|
+
disabled,
|
|
1819
|
+
error,
|
|
1820
|
+
icon: "calendar_today",
|
|
1821
|
+
className: textColorClass,
|
|
1822
|
+
...props
|
|
1823
|
+
}
|
|
1824
|
+
),
|
|
1825
|
+
showCalendar && !disabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute z-20 mt-2 w-full max-w-sm", children: /* @__PURE__ */ jsxRuntime.jsx(Card, { className: "p-4", showDecorations: false, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1826
|
+
Calendar,
|
|
1827
|
+
{
|
|
1828
|
+
selectedDate: inputValue !== placeholder && parseDate(inputValue) && isValidDate(parseDate(inputValue)) ? parseDate(inputValue) : /* @__PURE__ */ new Date(),
|
|
1829
|
+
onDateSelect: handleCalendarSelect,
|
|
1830
|
+
today: startOfDay2(/* @__PURE__ */ new Date()),
|
|
1831
|
+
minDate,
|
|
1832
|
+
maxDate
|
|
1833
|
+
}
|
|
1834
|
+
) }) })
|
|
1835
|
+
] });
|
|
1836
|
+
}
|
|
1837
|
+
);
|
|
1838
|
+
DateInput.displayName = "DateInput";
|
|
1552
1839
|
|
|
1553
1840
|
exports.AgentButton = AgentButton_default;
|
|
1554
1841
|
exports.AnimatedBgCircle = AnimatedBgCircle_default;
|
|
@@ -1560,9 +1847,11 @@ exports.AvatarGroup = AvatarGroup;
|
|
|
1560
1847
|
exports.BackgroundBlur = BackgroundBlur;
|
|
1561
1848
|
exports.Breadcrumb = Breadcrumb;
|
|
1562
1849
|
exports.Button = Button;
|
|
1850
|
+
exports.Calendar = Calendar;
|
|
1563
1851
|
exports.Card = Card;
|
|
1564
1852
|
exports.Chip = Chip;
|
|
1565
1853
|
exports.Counter = Counter;
|
|
1854
|
+
exports.DateInput = DateInput;
|
|
1566
1855
|
exports.Icon = Icon;
|
|
1567
1856
|
exports.IconButton = IconButton;
|
|
1568
1857
|
exports.Input = Input;
|
package/dist/index.d.cts
CHANGED
|
@@ -392,4 +392,51 @@ interface BreadcrumbProps {
|
|
|
392
392
|
*/
|
|
393
393
|
declare const Breadcrumb: React__default.FC<BreadcrumbProps>;
|
|
394
394
|
|
|
395
|
-
|
|
395
|
+
type DateInputProps = Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange" | "type"> & {
|
|
396
|
+
/** Label text displayed above the input */
|
|
397
|
+
label?: string;
|
|
398
|
+
/** Current date value */
|
|
399
|
+
value?: Date | null;
|
|
400
|
+
/** Callback when date changes */
|
|
401
|
+
onChange: (date: Date) => void;
|
|
402
|
+
/** Flag to visually mark the input as errored */
|
|
403
|
+
error?: boolean;
|
|
404
|
+
/** Minimum selectable date */
|
|
405
|
+
minDate?: Date;
|
|
406
|
+
/** Maximum selectable date */
|
|
407
|
+
maxDate?: Date;
|
|
408
|
+
/** Placeholder text (default: "00/00/0000") */
|
|
409
|
+
placeholder?: string;
|
|
410
|
+
};
|
|
411
|
+
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "type" | "value"> & {
|
|
412
|
+
/** Label text displayed above the input */
|
|
413
|
+
label?: string;
|
|
414
|
+
/** Current date value */
|
|
415
|
+
value?: Date | null;
|
|
416
|
+
/** Callback when date changes */
|
|
417
|
+
onChange: (date: Date) => void;
|
|
418
|
+
/** Flag to visually mark the input as errored */
|
|
419
|
+
error?: boolean;
|
|
420
|
+
/** Minimum selectable date */
|
|
421
|
+
minDate?: Date;
|
|
422
|
+
/** Maximum selectable date */
|
|
423
|
+
maxDate?: Date;
|
|
424
|
+
/** Placeholder text (default: "00/00/0000") */
|
|
425
|
+
placeholder?: string;
|
|
426
|
+
} & React.RefAttributes<HTMLInputElement>>;
|
|
427
|
+
|
|
428
|
+
type CalendarProps = {
|
|
429
|
+
/** Currently selected date */
|
|
430
|
+
selectedDate?: Date;
|
|
431
|
+
/** Callback when a date is selected */
|
|
432
|
+
onDateSelect: (date: Date) => void;
|
|
433
|
+
/** Today's date (for highlighting) */
|
|
434
|
+
today?: Date;
|
|
435
|
+
/** Minimum selectable date */
|
|
436
|
+
minDate?: Date;
|
|
437
|
+
/** Maximum selectable date */
|
|
438
|
+
maxDate?: Date;
|
|
439
|
+
};
|
|
440
|
+
declare function Calendar({ selectedDate, onDateSelect, today, minDate, maxDate, }: CalendarProps): react_jsx_runtime.JSX.Element;
|
|
441
|
+
|
|
442
|
+
export { AgentButton, type AgentButtonProps, AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Calendar, type CalendarProps, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, DateInput, type DateInputProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, MessageBubble, type MessageBubbleProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Separator, type SeparatorProps, Skeleton, type SkeletonProps, Textarea, type TextareaProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
|