@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var React3 = require('react');
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 React3__namespace = /*#__PURE__*/_interopNamespace(React3);
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] = React3.useState(false);
111
- const [isVisible, setIsVisible] = React3.useState(false);
112
- React3.useEffect(() => {
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 Input = React3__namespace.forwardRef(
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 px-4 rounded-full",
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.jsx("div", { className: "flex w-full", children: inputElement }) })
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 = React3__namespace.forwardRef(
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" ? React3__namespace.useLayoutEffect : React3__namespace.useEffect;
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] = React3__namespace.useState(false);
390
- const [isDark, setIsDark] = React3__namespace.useState(false);
391
- React3__namespace.useEffect(() => {
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
- React3__namespace.useEffect(() => {
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] = React3.useState(false);
538
- const initials = React3.useMemo(() => getInitials(name), [name]);
539
- const computedStyle = React3.useMemo(() => {
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 = React3__namespace.Children.toArray(children);
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 = React3__namespace.forwardRef(
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 ?? React3.useId();
734
+ const inputId = id ?? React11.useId();
723
735
  const listboxId = `${inputId}-listbox`;
724
- const [searchQuery, setSearchQuery] = React3.useState("");
725
- const [open, setOpen] = React3.useState(false);
726
- const [activeIndex, setActiveIndex] = React3.useState(-1);
727
- const rootRef = React3.useRef(null);
728
- const listRef = React3.useRef(null);
729
- const normalizedOptions = React3.useMemo(() => {
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 = React3.useMemo(() => {
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 = React3.useMemo(
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-13",
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 ?? React3.useId();
972
+ const inputId = id ?? React11.useId();
961
973
  const listboxId = `${inputId}-listbox`;
962
- const [searchQuery, setSearchQuery] = React3.useState("");
963
- const [open, setOpen] = React3.useState(false);
964
- const [activeIndex, setActiveIndex] = React3.useState(-1);
965
- const [filtersExpanded, setFiltersExpanded] = React3.useState(false);
966
- const rootRef = React3.useRef(null);
967
- const listRef = React3.useRef(null);
968
- const searchTimeoutRef = React3.useRef(null);
969
- const normalizedOptions = React3.useMemo(() => {
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
- React3.useMemo(
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 = React3.useCallback(
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
- React3__namespace.useEffect(() => {
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 = React3__namespace.forwardRef(
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] = React3__namespace.useState(value);
1229
- React3__namespace.useEffect(() => {
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 = React3.useMemo(() => Math.random().toString(36).substr(2, 9), []);
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 = React3.useMemo(() => Math.random().toString(36).substr(2, 9), []);
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] = React3.useState(false);
1354
- const [delayedHasNotification, setDelayedHasNotification] = React3.useState(false);
1355
- const [isMounted, setIsMounted] = React3.useState(false);
1356
- React3.useEffect(() => {
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
- React3.useEffect(() => {
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 = React3__namespace.forwardRef(
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;