@neoptocom/neopto-ui 1.5.4 → 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(() => {
@@ -297,7 +297,7 @@ function Icon({
297
297
  }
298
298
  );
299
299
  }
300
- var Input = React3__namespace.forwardRef(
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 = React3__namespace.forwardRef(
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" ? React3__namespace.useLayoutEffect : React3__namespace.useEffect;
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] = React3__namespace.useState(false);
435
- const [isDark, setIsDark] = React3__namespace.useState(false);
436
- React3__namespace.useEffect(() => {
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
- React3__namespace.useEffect(() => {
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] = React3.useState(false);
583
- const initials = React3.useMemo(() => getInitials(name), [name]);
584
- const computedStyle = React3.useMemo(() => {
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 = React3__namespace.Children.toArray(children);
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 = React3__namespace.forwardRef(
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 ?? React3.useId();
734
+ const inputId = id ?? React11.useId();
735
735
  const listboxId = `${inputId}-listbox`;
736
- const [searchQuery, setSearchQuery] = React3.useState("");
737
- const [open, setOpen] = React3.useState(false);
738
- const [activeIndex, setActiveIndex] = React3.useState(-1);
739
- const rootRef = React3.useRef(null);
740
- const listRef = React3.useRef(null);
741
- 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(() => {
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 = React3.useMemo(() => {
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 = React3.useMemo(
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-13",
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(" "),
@@ -969,27 +969,27 @@ function Search({
969
969
  children,
970
970
  ...props
971
971
  }) {
972
- const inputId = id ?? React3.useId();
972
+ const inputId = id ?? React11.useId();
973
973
  const listboxId = `${inputId}-listbox`;
974
- const [searchQuery, setSearchQuery] = React3.useState("");
975
- const [open, setOpen] = React3.useState(false);
976
- const [activeIndex, setActiveIndex] = React3.useState(-1);
977
- const [filtersExpanded, setFiltersExpanded] = React3.useState(false);
978
- const rootRef = React3.useRef(null);
979
- const listRef = React3.useRef(null);
980
- const searchTimeoutRef = React3.useRef(null);
981
- 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(() => {
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
- React3.useMemo(
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 = React3.useCallback(
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
- React3__namespace.useEffect(() => {
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 = React3__namespace.forwardRef(
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] = React3__namespace.useState(value);
1241
- React3__namespace.useEffect(() => {
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 = React3.useMemo(() => Math.random().toString(36).substr(2, 9), []);
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 = React3.useMemo(() => Math.random().toString(36).substr(2, 9), []);
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] = React3.useState(false);
1366
- const [delayedHasNotification, setDelayedHasNotification] = React3.useState(false);
1367
- const [isMounted, setIsMounted] = React3.useState(false);
1368
- 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(() => {
1369
1369
  const timer = setTimeout(() => setIsMounted(true), 250);
1370
1370
  return () => clearTimeout(timer);
1371
1371
  }, []);
1372
- React3.useEffect(() => {
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 = React3__namespace.forwardRef(
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,305 @@ var Breadcrumb = ({
1549
1549
  ] }, index);
1550
1550
  }) }) });
1551
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";
1552
1851
 
1553
1852
  exports.AgentButton = AgentButton_default;
1554
1853
  exports.AnimatedBgCircle = AnimatedBgCircle_default;
@@ -1560,9 +1859,11 @@ exports.AvatarGroup = AvatarGroup;
1560
1859
  exports.BackgroundBlur = BackgroundBlur;
1561
1860
  exports.Breadcrumb = Breadcrumb;
1562
1861
  exports.Button = Button;
1862
+ exports.Calendar = Calendar;
1563
1863
  exports.Card = Card;
1564
1864
  exports.Chip = Chip;
1565
1865
  exports.Counter = Counter;
1866
+ exports.DateInput = DateInput;
1566
1867
  exports.Icon = Icon;
1567
1868
  exports.IconButton = IconButton;
1568
1869
  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
- 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, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, 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 };
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 };