@neoptocom/neopto-ui 1.5.3 → 1.6.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.cjs +398 -85
- package/dist/index.d.cts +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +363 -52
- package/package.json +1 -1
- package/src/components/Autocomplete.tsx +1 -1
- package/src/components/Calendar.tsx +217 -0
- package/src/components/DateInput.tsx +225 -0
- package/src/components/Input.tsx +28 -2
- package/src/index.ts +5 -1
- package/src/stories/DateInput.stories.tsx +136 -0
- package/src/stories/Input.stories.tsx +11 -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(() => {
|
|
@@ -264,7 +264,40 @@ function Card({
|
|
|
264
264
|
}
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
|
-
var
|
|
267
|
+
var sizeMap = {
|
|
268
|
+
sm: 16,
|
|
269
|
+
md: 24,
|
|
270
|
+
lg: 36
|
|
271
|
+
};
|
|
272
|
+
function Icon({
|
|
273
|
+
name,
|
|
274
|
+
className = "",
|
|
275
|
+
title,
|
|
276
|
+
size = "md",
|
|
277
|
+
fill = 0
|
|
278
|
+
}) {
|
|
279
|
+
const fontSize = sizeMap[size] ?? sizeMap.md;
|
|
280
|
+
const hasColorClass = /\b(?:text-|fill-|stroke-)\S+/.test(className);
|
|
281
|
+
const style = {
|
|
282
|
+
fontVariationSettings: `'FILL' ${fill}, 'wght' 300, 'GRAD' 0, 'opsz' ${fontSize}`,
|
|
283
|
+
fontSize,
|
|
284
|
+
lineHeight: 1,
|
|
285
|
+
display: "inline-block",
|
|
286
|
+
verticalAlign: "middle",
|
|
287
|
+
...hasColorClass ? {} : { color: "inherit" }
|
|
288
|
+
};
|
|
289
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
290
|
+
"span",
|
|
291
|
+
{
|
|
292
|
+
className: `material-symbols-rounded rounded ${className}`,
|
|
293
|
+
style,
|
|
294
|
+
"aria-hidden": title ? void 0 : true,
|
|
295
|
+
title,
|
|
296
|
+
children: name
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
var Input = React11__namespace.forwardRef(
|
|
268
301
|
({
|
|
269
302
|
className,
|
|
270
303
|
disabled,
|
|
@@ -273,14 +306,17 @@ var Input = React3__namespace.forwardRef(
|
|
|
273
306
|
fieldsetProps,
|
|
274
307
|
legendProps,
|
|
275
308
|
error = false,
|
|
309
|
+
icon,
|
|
276
310
|
...props
|
|
277
311
|
}, ref) => {
|
|
278
312
|
const isInlineVariant = variant === "inline";
|
|
279
313
|
const shouldUseInlineStyles = isInlineVariant || Boolean(label);
|
|
280
314
|
const isError = error && !disabled;
|
|
315
|
+
const hasIcon = Boolean(icon);
|
|
281
316
|
const inputClasses = [
|
|
282
317
|
"w-full bg-transparent outline-none transition-colors",
|
|
283
|
-
shouldUseInlineStyles ? "h-9" : "h-12
|
|
318
|
+
shouldUseInlineStyles ? "h-9" : "h-12 rounded-full",
|
|
319
|
+
shouldUseInlineStyles ? hasIcon ? "pr-8" : "" : hasIcon ? "px-4 pr-10" : "px-4",
|
|
284
320
|
"font-['Poppins'] text-sm placeholder:text-[var(--muted-fg)]"
|
|
285
321
|
];
|
|
286
322
|
if (!shouldUseInlineStyles) {
|
|
@@ -307,6 +343,12 @@ var Input = React3__namespace.forwardRef(
|
|
|
307
343
|
const inputClassName = inputClasses.join(" ");
|
|
308
344
|
const inputElement = /* @__PURE__ */ jsxRuntime.jsx("input", { ref, disabled, className: inputClassName, ...props });
|
|
309
345
|
if (!label) {
|
|
346
|
+
if (hasIcon) {
|
|
347
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
348
|
+
inputElement,
|
|
349
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-4 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: "text-[var(--muted-fg)] opacity-50" }) })
|
|
350
|
+
] });
|
|
351
|
+
}
|
|
310
352
|
return inputElement;
|
|
311
353
|
}
|
|
312
354
|
const { className: fieldsetClassNameProp = "", ...restFieldsetProps } = fieldsetProps ?? {};
|
|
@@ -338,14 +380,17 @@ var Input = React3__namespace.forwardRef(
|
|
|
338
380
|
children: label
|
|
339
381
|
}
|
|
340
382
|
),
|
|
341
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex pl-5 pr-3 pb-1 h-full", children: /* @__PURE__ */ jsxRuntime.
|
|
383
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex pl-5 pr-3 pb-1 h-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full relative", children: [
|
|
384
|
+
inputElement,
|
|
385
|
+
hasIcon && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-1 top-1/2 -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: icon, className: "text-[var(--muted-fg)] opacity-50" }) })
|
|
386
|
+
] }) })
|
|
342
387
|
]
|
|
343
388
|
}
|
|
344
389
|
);
|
|
345
390
|
}
|
|
346
391
|
);
|
|
347
392
|
Input.displayName = "Input";
|
|
348
|
-
var Textarea =
|
|
393
|
+
var Textarea = React11__namespace.forwardRef(
|
|
349
394
|
({ className, disabled, variant = "default", ...props }, ref) => {
|
|
350
395
|
const isInline = variant === "inline";
|
|
351
396
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -374,7 +419,7 @@ var Textarea = React3__namespace.forwardRef(
|
|
|
374
419
|
);
|
|
375
420
|
Textarea.displayName = "Textarea";
|
|
376
421
|
function useIsomorphicLayoutEffect(effect, deps) {
|
|
377
|
-
const useEffectHook = typeof window !== "undefined" ?
|
|
422
|
+
const useEffectHook = typeof window !== "undefined" ? React11__namespace.useLayoutEffect : React11__namespace.useEffect;
|
|
378
423
|
useEffectHook(effect, deps);
|
|
379
424
|
}
|
|
380
425
|
function Modal({
|
|
@@ -386,9 +431,9 @@ function Modal({
|
|
|
386
431
|
zIndex = 50,
|
|
387
432
|
showDecorations = true
|
|
388
433
|
}) {
|
|
389
|
-
const [mounted, setMounted] =
|
|
390
|
-
const [isDark, setIsDark] =
|
|
391
|
-
|
|
434
|
+
const [mounted, setMounted] = React11__namespace.useState(false);
|
|
435
|
+
const [isDark, setIsDark] = React11__namespace.useState(false);
|
|
436
|
+
React11__namespace.useEffect(() => {
|
|
392
437
|
const checkDarkMode = () => {
|
|
393
438
|
const hasDarkClass = document.documentElement.classList.contains("dark") || document.body.classList.contains("dark") || document.querySelector(".dark") !== null;
|
|
394
439
|
setIsDark(hasDarkClass);
|
|
@@ -411,7 +456,7 @@ function Modal({
|
|
|
411
456
|
document.body.style.overflow = original;
|
|
412
457
|
};
|
|
413
458
|
}, [open]);
|
|
414
|
-
|
|
459
|
+
React11__namespace.useEffect(() => {
|
|
415
460
|
if (!open) return;
|
|
416
461
|
const onKey = (e) => {
|
|
417
462
|
if (e.key === "Escape") onClose?.();
|
|
@@ -534,9 +579,9 @@ function Avatar({
|
|
|
534
579
|
style,
|
|
535
580
|
...props
|
|
536
581
|
}) {
|
|
537
|
-
const [imgError, setImgError] =
|
|
538
|
-
const initials =
|
|
539
|
-
const computedStyle =
|
|
582
|
+
const [imgError, setImgError] = React11.useState(false);
|
|
583
|
+
const initials = React11.useMemo(() => getInitials(name), [name]);
|
|
584
|
+
const computedStyle = React11.useMemo(() => {
|
|
540
585
|
const s = { ...style };
|
|
541
586
|
if (color) s.backgroundColor = color;
|
|
542
587
|
return s;
|
|
@@ -571,7 +616,7 @@ function AvatarGroup({
|
|
|
571
616
|
overlapPx = 8,
|
|
572
617
|
withRings = true
|
|
573
618
|
}) {
|
|
574
|
-
const avatars =
|
|
619
|
+
const avatars = React11__namespace.Children.toArray(children);
|
|
575
620
|
const displayAvatars = typeof max === "number" ? avatars.slice(0, max) : avatars;
|
|
576
621
|
const extraCount = typeof max === "number" && avatars.length > max ? avatars.length - max : 0;
|
|
577
622
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["flex items-center", className].filter(Boolean).join(" "), children: [
|
|
@@ -625,39 +670,6 @@ function Skeleton({ className = "", rounded = "md", ...props }) {
|
|
|
625
670
|
}
|
|
626
671
|
);
|
|
627
672
|
}
|
|
628
|
-
var sizeMap = {
|
|
629
|
-
sm: 16,
|
|
630
|
-
md: 24,
|
|
631
|
-
lg: 36
|
|
632
|
-
};
|
|
633
|
-
function Icon({
|
|
634
|
-
name,
|
|
635
|
-
className = "",
|
|
636
|
-
title,
|
|
637
|
-
size = "md",
|
|
638
|
-
fill = 0
|
|
639
|
-
}) {
|
|
640
|
-
const fontSize = sizeMap[size] ?? sizeMap.md;
|
|
641
|
-
const hasColorClass = /\b(?:text-|fill-|stroke-)\S+/.test(className);
|
|
642
|
-
const style = {
|
|
643
|
-
fontVariationSettings: `'FILL' ${fill}, 'wght' 300, 'GRAD' 0, 'opsz' ${fontSize}`,
|
|
644
|
-
fontSize,
|
|
645
|
-
lineHeight: 1,
|
|
646
|
-
display: "inline-block",
|
|
647
|
-
verticalAlign: "middle",
|
|
648
|
-
...hasColorClass ? {} : { color: "inherit" }
|
|
649
|
-
};
|
|
650
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
651
|
-
"span",
|
|
652
|
-
{
|
|
653
|
-
className: `material-symbols-rounded rounded ${className}`,
|
|
654
|
-
style,
|
|
655
|
-
"aria-hidden": title ? void 0 : true,
|
|
656
|
-
title,
|
|
657
|
-
children: name
|
|
658
|
-
}
|
|
659
|
-
);
|
|
660
|
-
}
|
|
661
673
|
function getIconButtonClasses(variant = "ghost", size = "md", className) {
|
|
662
674
|
const base = "cursor-pointer flex items-center justify-center rounded-full flex-shrink-0 transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-cyan-500/40 disabled:cursor-not-allowed disabled:opacity-50";
|
|
663
675
|
const variants = {
|
|
@@ -672,7 +684,7 @@ function getIconButtonClasses(variant = "ghost", size = "md", className) {
|
|
|
672
684
|
};
|
|
673
685
|
return [base, variants[variant], sizes[size], className].filter(Boolean).join(" ");
|
|
674
686
|
}
|
|
675
|
-
var IconButton =
|
|
687
|
+
var IconButton = React11__namespace.forwardRef(
|
|
676
688
|
({
|
|
677
689
|
variant,
|
|
678
690
|
size,
|
|
@@ -719,14 +731,14 @@ function Autocomplete({
|
|
|
719
731
|
id,
|
|
720
732
|
...props
|
|
721
733
|
}) {
|
|
722
|
-
const inputId = id ??
|
|
734
|
+
const inputId = id ?? React11.useId();
|
|
723
735
|
const listboxId = `${inputId}-listbox`;
|
|
724
|
-
const [searchQuery, setSearchQuery] =
|
|
725
|
-
const [open, setOpen] =
|
|
726
|
-
const [activeIndex, setActiveIndex] =
|
|
727
|
-
const rootRef =
|
|
728
|
-
const listRef =
|
|
729
|
-
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(() => {
|
|
730
742
|
if (Array.isArray(options) && typeof options[0] === "string") {
|
|
731
743
|
return options.map((str) => ({
|
|
732
744
|
name: str,
|
|
@@ -743,7 +755,7 @@ function Autocomplete({
|
|
|
743
755
|
};
|
|
744
756
|
});
|
|
745
757
|
}, [options]);
|
|
746
|
-
const filtered =
|
|
758
|
+
const filtered = React11.useMemo(() => {
|
|
747
759
|
const q = searchQuery.trim().toLowerCase();
|
|
748
760
|
if (!q) return normalizedOptions;
|
|
749
761
|
return normalizedOptions.filter((o) => {
|
|
@@ -752,7 +764,7 @@ function Autocomplete({
|
|
|
752
764
|
return name.includes(q) || label.includes(q);
|
|
753
765
|
});
|
|
754
766
|
}, [normalizedOptions, searchQuery]);
|
|
755
|
-
const anyOptionHasImage =
|
|
767
|
+
const anyOptionHasImage = React11.useMemo(
|
|
756
768
|
() => normalizedOptions.some((o) => !!o.image),
|
|
757
769
|
[normalizedOptions]
|
|
758
770
|
);
|
|
@@ -831,7 +843,7 @@ function Autocomplete({
|
|
|
831
843
|
"fieldset",
|
|
832
844
|
{
|
|
833
845
|
className: [
|
|
834
|
-
"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",
|
|
835
847
|
"border-[var(--border)] focus-within:border-[var(--color-brand)]",
|
|
836
848
|
disabled ? "opacity-60 cursor-not-allowed" : ""
|
|
837
849
|
].join(" "),
|
|
@@ -957,27 +969,27 @@ function Search({
|
|
|
957
969
|
children,
|
|
958
970
|
...props
|
|
959
971
|
}) {
|
|
960
|
-
const inputId = id ??
|
|
972
|
+
const inputId = id ?? React11.useId();
|
|
961
973
|
const listboxId = `${inputId}-listbox`;
|
|
962
|
-
const [searchQuery, setSearchQuery] =
|
|
963
|
-
const [open, setOpen] =
|
|
964
|
-
const [activeIndex, setActiveIndex] =
|
|
965
|
-
const [filtersExpanded, setFiltersExpanded] =
|
|
966
|
-
const rootRef =
|
|
967
|
-
const listRef =
|
|
968
|
-
const searchTimeoutRef =
|
|
969
|
-
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(() => {
|
|
970
982
|
if (Array.isArray(options) && typeof options[0] === "string") {
|
|
971
983
|
return options.map((str) => ({ label: str, value: str }));
|
|
972
984
|
}
|
|
973
985
|
return options;
|
|
974
986
|
}, [options]);
|
|
975
|
-
|
|
987
|
+
React11.useMemo(
|
|
976
988
|
() => normalizedOptions.some((o) => !!o.image),
|
|
977
989
|
[normalizedOptions]
|
|
978
990
|
);
|
|
979
991
|
const displayValue = selectedOption != null ? typeof selectedOption === "string" ? selectedOption : selectedOption.label : searchQuery;
|
|
980
|
-
const debouncedSearch =
|
|
992
|
+
const debouncedSearch = React11.useCallback(
|
|
981
993
|
(query) => {
|
|
982
994
|
if (searchTimeoutRef.current) {
|
|
983
995
|
clearTimeout(searchTimeoutRef.current);
|
|
@@ -1046,7 +1058,7 @@ function Search({
|
|
|
1046
1058
|
const el = list.children[idx];
|
|
1047
1059
|
el?.scrollIntoView({ block: "nearest" });
|
|
1048
1060
|
}
|
|
1049
|
-
|
|
1061
|
+
React11__namespace.useEffect(() => {
|
|
1050
1062
|
return () => {
|
|
1051
1063
|
if (searchTimeoutRef.current) {
|
|
1052
1064
|
clearTimeout(searchTimeoutRef.current);
|
|
@@ -1153,7 +1165,7 @@ function getButtonClasses(variant = "primary", size = "md", fullWidth, className
|
|
|
1153
1165
|
className
|
|
1154
1166
|
].filter(Boolean).join(" ");
|
|
1155
1167
|
}
|
|
1156
|
-
var Button =
|
|
1168
|
+
var Button = React11__namespace.forwardRef(
|
|
1157
1169
|
({ variant, size, fullWidth, className, children, icon, ...props }, ref) => {
|
|
1158
1170
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1159
1171
|
"button",
|
|
@@ -1225,8 +1237,8 @@ function Counter({
|
|
|
1225
1237
|
className = "",
|
|
1226
1238
|
...props
|
|
1227
1239
|
}) {
|
|
1228
|
-
const [count, setCount] =
|
|
1229
|
-
|
|
1240
|
+
const [count, setCount] = React11__namespace.useState(value);
|
|
1241
|
+
React11__namespace.useEffect(() => {
|
|
1230
1242
|
setCount(value);
|
|
1231
1243
|
}, [value]);
|
|
1232
1244
|
const handleIncrement = () => {
|
|
@@ -1269,7 +1281,7 @@ function Counter({
|
|
|
1269
1281
|
] });
|
|
1270
1282
|
}
|
|
1271
1283
|
var AnimatedBgCircle = ({ colors, delay = 0 }) => {
|
|
1272
|
-
const uniqueId =
|
|
1284
|
+
const uniqueId = React11.useMemo(() => Math.random().toString(36).substr(2, 9), []);
|
|
1273
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: [
|
|
1274
1286
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
1275
1287
|
@keyframes colorCycle-${uniqueId} {
|
|
@@ -1301,7 +1313,7 @@ var AnimatedBgCircle = ({ colors, delay = 0 }) => {
|
|
|
1301
1313
|
};
|
|
1302
1314
|
var AnimatedBgCircle_default = AnimatedBgCircle;
|
|
1303
1315
|
var AnimatedBgRectangle = ({ colors, delay = 0 }) => {
|
|
1304
|
-
const uniqueId =
|
|
1316
|
+
const uniqueId = React11.useMemo(() => Math.random().toString(36).substr(2, 9), []);
|
|
1305
1317
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1306
1318
|
"svg",
|
|
1307
1319
|
{
|
|
@@ -1350,14 +1362,14 @@ var AgentButton = ({
|
|
|
1350
1362
|
animationColors = ["#7DADB9", "#3864F5", "#55468D", "#479A8D"],
|
|
1351
1363
|
disabled = false
|
|
1352
1364
|
}) => {
|
|
1353
|
-
const [showText, setShowText] =
|
|
1354
|
-
const [delayedHasNotification, setDelayedHasNotification] =
|
|
1355
|
-
const [isMounted, setIsMounted] =
|
|
1356
|
-
|
|
1365
|
+
const [showText, setShowText] = React11.useState(false);
|
|
1366
|
+
const [delayedHasNotification, setDelayedHasNotification] = React11.useState(false);
|
|
1367
|
+
const [isMounted, setIsMounted] = React11.useState(false);
|
|
1368
|
+
React11.useEffect(() => {
|
|
1357
1369
|
const timer = setTimeout(() => setIsMounted(true), 250);
|
|
1358
1370
|
return () => clearTimeout(timer);
|
|
1359
1371
|
}, []);
|
|
1360
|
-
|
|
1372
|
+
React11.useEffect(() => {
|
|
1361
1373
|
if (hasNotification) {
|
|
1362
1374
|
const textTimer = setTimeout(() => setShowText(true), 500);
|
|
1363
1375
|
setDelayedHasNotification(true);
|
|
@@ -1459,7 +1471,7 @@ var AgentButton = ({
|
|
|
1459
1471
|
);
|
|
1460
1472
|
};
|
|
1461
1473
|
var AgentButton_default = AgentButton;
|
|
1462
|
-
var MessageBubble =
|
|
1474
|
+
var MessageBubble = React11__namespace.forwardRef(
|
|
1463
1475
|
({ direction, color, children, className, ...props }, ref) => {
|
|
1464
1476
|
const borderRadiusClass = direction === "left" ? "[border-radius:16px_16px_16px_2px]" : direction === "right" ? "[border-radius:16px_16px_2px_16px]" : "rounded-2xl";
|
|
1465
1477
|
const backgroundColor = color || "var(--muted)";
|
|
@@ -1537,6 +1549,305 @@ var Breadcrumb = ({
|
|
|
1537
1549
|
] }, index);
|
|
1538
1550
|
}) }) });
|
|
1539
1551
|
};
|
|
1552
|
+
var DAYS_OF_WEEK = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
1553
|
+
var MONTHS = [
|
|
1554
|
+
"January",
|
|
1555
|
+
"February",
|
|
1556
|
+
"March",
|
|
1557
|
+
"April",
|
|
1558
|
+
"May",
|
|
1559
|
+
"June",
|
|
1560
|
+
"July",
|
|
1561
|
+
"August",
|
|
1562
|
+
"September",
|
|
1563
|
+
"October",
|
|
1564
|
+
"November",
|
|
1565
|
+
"December"
|
|
1566
|
+
];
|
|
1567
|
+
function isSameDay(date1, date2) {
|
|
1568
|
+
return date1.getDate() === date2.getDate() && date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1569
|
+
}
|
|
1570
|
+
function isSameMonth(date1, date2) {
|
|
1571
|
+
return date1.getMonth() === date2.getMonth() && date1.getFullYear() === date2.getFullYear();
|
|
1572
|
+
}
|
|
1573
|
+
function startOfDay(date) {
|
|
1574
|
+
const d = new Date(date);
|
|
1575
|
+
d.setHours(0, 0, 0, 0);
|
|
1576
|
+
return d;
|
|
1577
|
+
}
|
|
1578
|
+
function Calendar({
|
|
1579
|
+
selectedDate,
|
|
1580
|
+
onDateSelect,
|
|
1581
|
+
today = /* @__PURE__ */ new Date(),
|
|
1582
|
+
minDate,
|
|
1583
|
+
maxDate
|
|
1584
|
+
}) {
|
|
1585
|
+
const [currentMonth, setCurrentMonth] = React11__namespace.useState(
|
|
1586
|
+
selectedDate || /* @__PURE__ */ new Date()
|
|
1587
|
+
);
|
|
1588
|
+
const todayStart = startOfDay(today);
|
|
1589
|
+
const selectedDateStart = selectedDate ? startOfDay(selectedDate) : null;
|
|
1590
|
+
const firstDayOfMonth = new Date(
|
|
1591
|
+
currentMonth.getFullYear(),
|
|
1592
|
+
currentMonth.getMonth(),
|
|
1593
|
+
1
|
|
1594
|
+
);
|
|
1595
|
+
const lastDayOfMonth = new Date(
|
|
1596
|
+
currentMonth.getFullYear(),
|
|
1597
|
+
currentMonth.getMonth() + 1,
|
|
1598
|
+
0
|
|
1599
|
+
);
|
|
1600
|
+
const daysInMonth = lastDayOfMonth.getDate();
|
|
1601
|
+
const startingDayOfWeek = firstDayOfMonth.getDay();
|
|
1602
|
+
const prevMonth = () => {
|
|
1603
|
+
setCurrentMonth(
|
|
1604
|
+
new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1)
|
|
1605
|
+
);
|
|
1606
|
+
};
|
|
1607
|
+
const nextMonth = () => {
|
|
1608
|
+
setCurrentMonth(
|
|
1609
|
+
new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)
|
|
1610
|
+
);
|
|
1611
|
+
};
|
|
1612
|
+
const handleDateClick = (day) => {
|
|
1613
|
+
const date = new Date(
|
|
1614
|
+
currentMonth.getFullYear(),
|
|
1615
|
+
currentMonth.getMonth(),
|
|
1616
|
+
day
|
|
1617
|
+
);
|
|
1618
|
+
const dateStart = startOfDay(date);
|
|
1619
|
+
if (minDate && dateStart < startOfDay(minDate)) return;
|
|
1620
|
+
if (maxDate && dateStart > startOfDay(maxDate)) return;
|
|
1621
|
+
onDateSelect(date);
|
|
1622
|
+
};
|
|
1623
|
+
const isDateDisabled = (day) => {
|
|
1624
|
+
const date = new Date(
|
|
1625
|
+
currentMonth.getFullYear(),
|
|
1626
|
+
currentMonth.getMonth(),
|
|
1627
|
+
day
|
|
1628
|
+
);
|
|
1629
|
+
const dateStart = startOfDay(date);
|
|
1630
|
+
if (minDate && dateStart < startOfDay(minDate)) return true;
|
|
1631
|
+
if (maxDate && dateStart > startOfDay(maxDate)) return true;
|
|
1632
|
+
return false;
|
|
1633
|
+
};
|
|
1634
|
+
const days = [];
|
|
1635
|
+
for (let i = 0; i < startingDayOfWeek; i++) {
|
|
1636
|
+
days.push(null);
|
|
1637
|
+
}
|
|
1638
|
+
for (let day = 1; day <= daysInMonth; day++) {
|
|
1639
|
+
days.push(day);
|
|
1640
|
+
}
|
|
1641
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
|
|
1642
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
1643
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1644
|
+
"button",
|
|
1645
|
+
{
|
|
1646
|
+
type: "button",
|
|
1647
|
+
onClick: prevMonth,
|
|
1648
|
+
className: "p-2 rounded-full hover:bg-[var(--muted)] transition-colors",
|
|
1649
|
+
"aria-label": "Previous month",
|
|
1650
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "material-symbols-rounded text-[var(--fg)]", children: "chevron_left" })
|
|
1651
|
+
}
|
|
1652
|
+
),
|
|
1653
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-sm font-medium text-[var(--fg)]", children: [
|
|
1654
|
+
MONTHS[currentMonth.getMonth()],
|
|
1655
|
+
" ",
|
|
1656
|
+
currentMonth.getFullYear()
|
|
1657
|
+
] }),
|
|
1658
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1659
|
+
"button",
|
|
1660
|
+
{
|
|
1661
|
+
type: "button",
|
|
1662
|
+
onClick: nextMonth,
|
|
1663
|
+
className: "p-2 rounded-full hover:bg-[var(--muted)] transition-colors",
|
|
1664
|
+
"aria-label": "Next month",
|
|
1665
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "material-symbols-rounded text-[var(--fg)]", children: "chevron_right" })
|
|
1666
|
+
}
|
|
1667
|
+
)
|
|
1668
|
+
] }),
|
|
1669
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-1 mb-2", children: DAYS_OF_WEEK.map((day) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1670
|
+
"div",
|
|
1671
|
+
{
|
|
1672
|
+
className: "text-xs text-center text-[var(--muted-fg)] font-medium py-1",
|
|
1673
|
+
children: day
|
|
1674
|
+
},
|
|
1675
|
+
day
|
|
1676
|
+
)) }),
|
|
1677
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((day, idx) => {
|
|
1678
|
+
if (day === null) {
|
|
1679
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-square" }, `empty-${idx}`);
|
|
1680
|
+
}
|
|
1681
|
+
const date = new Date(
|
|
1682
|
+
currentMonth.getFullYear(),
|
|
1683
|
+
currentMonth.getMonth(),
|
|
1684
|
+
day
|
|
1685
|
+
);
|
|
1686
|
+
const dateStart = startOfDay(date);
|
|
1687
|
+
const isSelected = selectedDateStart && isSameDay(dateStart, selectedDateStart);
|
|
1688
|
+
const isToday = isSameDay(dateStart, todayStart);
|
|
1689
|
+
const isDisabled = isDateDisabled(day);
|
|
1690
|
+
const isCurrentMonth = isSameMonth(dateStart, currentMonth);
|
|
1691
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1692
|
+
"button",
|
|
1693
|
+
{
|
|
1694
|
+
type: "button",
|
|
1695
|
+
onClick: () => handleDateClick(day),
|
|
1696
|
+
disabled: isDisabled,
|
|
1697
|
+
className: [
|
|
1698
|
+
"aspect-square rounded-lg text-sm transition-colors",
|
|
1699
|
+
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)]",
|
|
1700
|
+
isDisabled ? "opacity-30 cursor-not-allowed" : "cursor-pointer",
|
|
1701
|
+
!isCurrentMonth ? "opacity-50" : ""
|
|
1702
|
+
].filter(Boolean).join(" "),
|
|
1703
|
+
children: day
|
|
1704
|
+
},
|
|
1705
|
+
day
|
|
1706
|
+
);
|
|
1707
|
+
}) })
|
|
1708
|
+
] });
|
|
1709
|
+
}
|
|
1710
|
+
function formatDate(date) {
|
|
1711
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
1712
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
1713
|
+
const year = date.getFullYear();
|
|
1714
|
+
return `${day}/${month}/${year}`;
|
|
1715
|
+
}
|
|
1716
|
+
function parseDate(dateString) {
|
|
1717
|
+
const parts = dateString.split("/");
|
|
1718
|
+
if (parts.length !== 3) return null;
|
|
1719
|
+
const day = parseInt(parts[0], 10);
|
|
1720
|
+
const month = parseInt(parts[1], 10) - 1;
|
|
1721
|
+
const year = parseInt(parts[2], 10);
|
|
1722
|
+
if (isNaN(day) || isNaN(month) || isNaN(year)) return null;
|
|
1723
|
+
const date = new Date(year, month, day);
|
|
1724
|
+
if (date.getDate() !== day || date.getMonth() !== month || date.getFullYear() !== year) {
|
|
1725
|
+
return null;
|
|
1726
|
+
}
|
|
1727
|
+
return date;
|
|
1728
|
+
}
|
|
1729
|
+
function isValidDate(date) {
|
|
1730
|
+
return date instanceof Date && !isNaN(date.getTime());
|
|
1731
|
+
}
|
|
1732
|
+
function startOfDay2(date) {
|
|
1733
|
+
const d = new Date(date);
|
|
1734
|
+
d.setHours(0, 0, 0, 0);
|
|
1735
|
+
return d;
|
|
1736
|
+
}
|
|
1737
|
+
var DateInput = React11__namespace.forwardRef(
|
|
1738
|
+
({
|
|
1739
|
+
label,
|
|
1740
|
+
value,
|
|
1741
|
+
onChange,
|
|
1742
|
+
error = false,
|
|
1743
|
+
disabled = false,
|
|
1744
|
+
minDate,
|
|
1745
|
+
maxDate,
|
|
1746
|
+
placeholder = "00/00/0000",
|
|
1747
|
+
className = "",
|
|
1748
|
+
...props
|
|
1749
|
+
}, ref) => {
|
|
1750
|
+
const [inputValue, setInputValue] = React11__namespace.useState(
|
|
1751
|
+
value && isValidDate(value) ? formatDate(value) : placeholder
|
|
1752
|
+
);
|
|
1753
|
+
const [isFocused, setIsFocused] = React11__namespace.useState(false);
|
|
1754
|
+
const [showCalendar, setShowCalendar] = React11__namespace.useState(false);
|
|
1755
|
+
const [initialDateSet, setInitialDateSet] = React11__namespace.useState(true);
|
|
1756
|
+
const containerRef = React11__namespace.useRef(null);
|
|
1757
|
+
React11__namespace.useEffect(() => {
|
|
1758
|
+
if (value && isValidDate(value)) {
|
|
1759
|
+
setInputValue(formatDate(value));
|
|
1760
|
+
} else {
|
|
1761
|
+
setInputValue(placeholder);
|
|
1762
|
+
}
|
|
1763
|
+
}, [value, placeholder]);
|
|
1764
|
+
React11__namespace.useEffect(() => {
|
|
1765
|
+
if (showCalendar && initialDateSet) {
|
|
1766
|
+
const today = /* @__PURE__ */ new Date();
|
|
1767
|
+
onChange(today);
|
|
1768
|
+
setInputValue(formatDate(today));
|
|
1769
|
+
setInitialDateSet(false);
|
|
1770
|
+
}
|
|
1771
|
+
}, [showCalendar, initialDateSet, onChange]);
|
|
1772
|
+
React11__namespace.useEffect(() => {
|
|
1773
|
+
const handleClickOutside = (event) => {
|
|
1774
|
+
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
1775
|
+
setShowCalendar(false);
|
|
1776
|
+
setInitialDateSet(false);
|
|
1777
|
+
}
|
|
1778
|
+
};
|
|
1779
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1780
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
1781
|
+
}, []);
|
|
1782
|
+
const handleInputChange = (e) => {
|
|
1783
|
+
let rawValue = e.target.value;
|
|
1784
|
+
rawValue = rawValue.replace(/\D/g, "").replace(/^(\d{2})/, "$1/").replace(/^(\d{2}\/\d{2})/, "$1/").slice(0, 10);
|
|
1785
|
+
setInputValue(rawValue);
|
|
1786
|
+
if (rawValue.length === 10) {
|
|
1787
|
+
const parsedDate = parseDate(rawValue);
|
|
1788
|
+
if (parsedDate && isValidDate(parsedDate)) {
|
|
1789
|
+
onChange(parsedDate);
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
};
|
|
1793
|
+
const handleCalendarSelect = (date) => {
|
|
1794
|
+
const selectedDate = parseDate(inputValue);
|
|
1795
|
+
const sameDay = selectedDate && isValidDate(selectedDate) && selectedDate.getDate() === date.getDate() && selectedDate.getMonth() === date.getMonth() && selectedDate.getFullYear() === date.getFullYear();
|
|
1796
|
+
if (!sameDay) {
|
|
1797
|
+
onChange(date);
|
|
1798
|
+
setInputValue(formatDate(date));
|
|
1799
|
+
}
|
|
1800
|
+
setInitialDateSet(false);
|
|
1801
|
+
setShowCalendar(false);
|
|
1802
|
+
};
|
|
1803
|
+
const handleInputFocus = () => {
|
|
1804
|
+
setIsFocused(true);
|
|
1805
|
+
setShowCalendar(true);
|
|
1806
|
+
};
|
|
1807
|
+
const handleInputBlur = () => {
|
|
1808
|
+
setIsFocused(false);
|
|
1809
|
+
const parsed = parseDate(inputValue);
|
|
1810
|
+
if (!parsed || !isValidDate(parsed)) {
|
|
1811
|
+
const today = /* @__PURE__ */ new Date();
|
|
1812
|
+
onChange(today);
|
|
1813
|
+
setInputValue(formatDate(today));
|
|
1814
|
+
}
|
|
1815
|
+
};
|
|
1816
|
+
const isEmpty = inputValue === placeholder;
|
|
1817
|
+
const textColorClass = isEmpty ? "text-[var(--muted-fg)]" : "";
|
|
1818
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["relative w-full", className].join(" "), ref: containerRef, children: [
|
|
1819
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1820
|
+
Input,
|
|
1821
|
+
{
|
|
1822
|
+
ref,
|
|
1823
|
+
label,
|
|
1824
|
+
type: "text",
|
|
1825
|
+
value: inputValue,
|
|
1826
|
+
onChange: handleInputChange,
|
|
1827
|
+
onFocus: handleInputFocus,
|
|
1828
|
+
onBlur: handleInputBlur,
|
|
1829
|
+
onClick: () => !disabled && setShowCalendar(true),
|
|
1830
|
+
disabled,
|
|
1831
|
+
error,
|
|
1832
|
+
icon: "calendar_today",
|
|
1833
|
+
className: textColorClass,
|
|
1834
|
+
...props
|
|
1835
|
+
}
|
|
1836
|
+
),
|
|
1837
|
+
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(
|
|
1838
|
+
Calendar,
|
|
1839
|
+
{
|
|
1840
|
+
selectedDate: inputValue !== placeholder && parseDate(inputValue) && isValidDate(parseDate(inputValue)) ? parseDate(inputValue) : /* @__PURE__ */ new Date(),
|
|
1841
|
+
onDateSelect: handleCalendarSelect,
|
|
1842
|
+
today: startOfDay2(/* @__PURE__ */ new Date()),
|
|
1843
|
+
minDate,
|
|
1844
|
+
maxDate
|
|
1845
|
+
}
|
|
1846
|
+
) }) })
|
|
1847
|
+
] });
|
|
1848
|
+
}
|
|
1849
|
+
);
|
|
1850
|
+
DateInput.displayName = "DateInput";
|
|
1540
1851
|
|
|
1541
1852
|
exports.AgentButton = AgentButton_default;
|
|
1542
1853
|
exports.AnimatedBgCircle = AnimatedBgCircle_default;
|
|
@@ -1548,9 +1859,11 @@ exports.AvatarGroup = AvatarGroup;
|
|
|
1548
1859
|
exports.BackgroundBlur = BackgroundBlur;
|
|
1549
1860
|
exports.Breadcrumb = Breadcrumb;
|
|
1550
1861
|
exports.Button = Button;
|
|
1862
|
+
exports.Calendar = Calendar;
|
|
1551
1863
|
exports.Card = Card;
|
|
1552
1864
|
exports.Chip = Chip;
|
|
1553
1865
|
exports.Counter = Counter;
|
|
1866
|
+
exports.DateInput = DateInput;
|
|
1554
1867
|
exports.Icon = Icon;
|
|
1555
1868
|
exports.IconButton = IconButton;
|
|
1556
1869
|
exports.Input = Input;
|