@bloomkit/react 0.2.11 → 0.2.13

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.js CHANGED
@@ -1499,16 +1499,345 @@ var SelectSeparator = forwardRef14(
1499
1499
  );
1500
1500
  SelectSeparator.displayName = "SelectSeparator";
1501
1501
 
1502
+ // src/components/otp-input/otp-input.tsx
1503
+ import { forwardRef as forwardRef15, useRef, useCallback as useCallback2, useState as useState5, useEffect as useEffect3 } from "react";
1504
+ import { jsx as jsx20 } from "react/jsx-runtime";
1505
+ var OTPInput = forwardRef15(
1506
+ ({ length = 6, value = "", onChange, onComplete, disabled = false, className, autoFocus = false }, ref) => {
1507
+ const [digits, setDigits] = useState5(() => {
1508
+ const arr = new Array(length).fill("");
1509
+ value.split("").forEach((char, i) => {
1510
+ if (i < length) arr[i] = char;
1511
+ });
1512
+ return arr;
1513
+ });
1514
+ const inputRefs = useRef([]);
1515
+ useEffect3(() => {
1516
+ const arr = new Array(length).fill("");
1517
+ value.split("").forEach((char, i) => {
1518
+ if (i < length) arr[i] = char;
1519
+ });
1520
+ setDigits(arr);
1521
+ }, [value, length]);
1522
+ const updateDigits = useCallback2(
1523
+ (newDigits) => {
1524
+ setDigits(newDigits);
1525
+ const joined = newDigits.join("");
1526
+ onChange?.(joined);
1527
+ if (joined.length === length && newDigits.every((d) => d !== "")) {
1528
+ onComplete?.(joined);
1529
+ }
1530
+ },
1531
+ [length, onChange, onComplete]
1532
+ );
1533
+ const handleInput = useCallback2(
1534
+ (index, char) => {
1535
+ if (!/^\d$/.test(char)) return;
1536
+ const newDigits = [...digits];
1537
+ newDigits[index] = char;
1538
+ updateDigits(newDigits);
1539
+ if (index < length - 1) {
1540
+ inputRefs.current[index + 1]?.focus();
1541
+ }
1542
+ },
1543
+ [digits, length, updateDigits]
1544
+ );
1545
+ const handleKeyDown = useCallback2(
1546
+ (index, e) => {
1547
+ if (e.key === "Backspace") {
1548
+ e.preventDefault();
1549
+ const newDigits = [...digits];
1550
+ if (digits[index]) {
1551
+ newDigits[index] = "";
1552
+ updateDigits(newDigits);
1553
+ } else if (index > 0) {
1554
+ newDigits[index - 1] = "";
1555
+ updateDigits(newDigits);
1556
+ inputRefs.current[index - 1]?.focus();
1557
+ }
1558
+ } else if (e.key === "ArrowLeft" && index > 0) {
1559
+ inputRefs.current[index - 1]?.focus();
1560
+ } else if (e.key === "ArrowRight" && index < length - 1) {
1561
+ inputRefs.current[index + 1]?.focus();
1562
+ }
1563
+ },
1564
+ [digits, length, updateDigits]
1565
+ );
1566
+ const handlePaste = useCallback2(
1567
+ (e) => {
1568
+ e.preventDefault();
1569
+ const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
1570
+ if (!pasted) return;
1571
+ const newDigits = new Array(length).fill("");
1572
+ pasted.split("").forEach((char, i) => {
1573
+ newDigits[i] = char;
1574
+ });
1575
+ updateDigits(newDigits);
1576
+ const focusIndex = Math.min(pasted.length, length - 1);
1577
+ inputRefs.current[focusIndex]?.focus();
1578
+ },
1579
+ [length, updateDigits]
1580
+ );
1581
+ return /* @__PURE__ */ jsx20("div", { ref, className: cn("flex items-center gap-[var(--space-sm)]", className), children: digits.map((digit, index) => /* @__PURE__ */ jsx20(
1582
+ "input",
1583
+ {
1584
+ ref: (el) => {
1585
+ inputRefs.current[index] = el;
1586
+ },
1587
+ type: "text",
1588
+ inputMode: "numeric",
1589
+ autoComplete: "one-time-code",
1590
+ maxLength: 1,
1591
+ value: digit,
1592
+ disabled,
1593
+ autoFocus: autoFocus && index === 0,
1594
+ onChange: (e) => {
1595
+ const char = e.target.value.slice(-1);
1596
+ handleInput(index, char);
1597
+ },
1598
+ onKeyDown: (e) => handleKeyDown(index, e),
1599
+ onPaste: handlePaste,
1600
+ onFocus: (e) => e.target.select(),
1601
+ className: cn(
1602
+ inputVariants(),
1603
+ "h-[52px] w-[44px] text-center",
1604
+ "text-[length:var(--bloom-text-heading)]",
1605
+ "px-0"
1606
+ )
1607
+ },
1608
+ index
1609
+ )) });
1610
+ }
1611
+ );
1612
+ OTPInput.displayName = "OTPInput";
1613
+
1614
+ // src/components/drawer/drawer.tsx
1615
+ import * as DialogPrimitive2 from "@radix-ui/react-dialog";
1616
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1617
+ var slideIn = {
1618
+ right: "data-[state=open]:slide-in-from-right",
1619
+ left: "data-[state=open]:slide-in-from-left",
1620
+ top: "data-[state=open]:slide-in-from-top",
1621
+ bottom: "data-[state=open]:slide-in-from-bottom"
1622
+ };
1623
+ var slideOut = {
1624
+ right: "data-[state=closed]:slide-out-to-right",
1625
+ left: "data-[state=closed]:slide-out-to-left",
1626
+ top: "data-[state=closed]:slide-out-to-top",
1627
+ bottom: "data-[state=closed]:slide-out-to-bottom"
1628
+ };
1629
+ var sidePosition = {
1630
+ right: "inset-y-0 right-0",
1631
+ left: "inset-y-0 left-0",
1632
+ top: "inset-x-0 top-0",
1633
+ bottom: "inset-x-0 bottom-0"
1634
+ };
1635
+ var sideSize = {
1636
+ right: "h-full w-full max-w-[400px]",
1637
+ left: "h-full w-full max-w-[400px]",
1638
+ top: "w-full",
1639
+ bottom: "w-full"
1640
+ };
1641
+ function Drawer({
1642
+ open,
1643
+ onOpenChange,
1644
+ title,
1645
+ description,
1646
+ children,
1647
+ side = "right",
1648
+ className
1649
+ }) {
1650
+ return /* @__PURE__ */ jsx21(DialogPrimitive2.Root, { open, onOpenChange, children: /* @__PURE__ */ jsxs15(DialogPrimitive2.Portal, { children: [
1651
+ /* @__PURE__ */ jsx21(
1652
+ DialogPrimitive2.Overlay,
1653
+ {
1654
+ className: cn(
1655
+ "fixed inset-0 z-50 bg-black/40 backdrop-blur-sm",
1656
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0",
1657
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0"
1658
+ )
1659
+ }
1660
+ ),
1661
+ /* @__PURE__ */ jsxs15(
1662
+ DialogPrimitive2.Content,
1663
+ {
1664
+ className: cn(
1665
+ "bloom fixed z-50",
1666
+ sidePosition[side],
1667
+ sideSize[side],
1668
+ "bg-[var(--bloom-surface)] p-[var(--space-xl)]",
1669
+ "shadow-[var(--bloom-shadow-hover)]",
1670
+ "border-[var(--bloom-surface2)]",
1671
+ side === "right" && "border-l",
1672
+ side === "left" && "border-r",
1673
+ side === "top" && "border-b",
1674
+ side === "bottom" && "border-t",
1675
+ "data-[state=open]:animate-in data-[state=open]:duration-300",
1676
+ "data-[state=closed]:animate-out data-[state=closed]:duration-200",
1677
+ slideIn[side],
1678
+ slideOut[side],
1679
+ "focus:outline-none",
1680
+ className
1681
+ ),
1682
+ children: [
1683
+ title && /* @__PURE__ */ jsx21(DialogPrimitive2.Title, { className: "font-[family-name:var(--bloom-font-display)] text-[length:var(--bloom-text-heading)] font-medium color-[var(--bloom-text)] mb-[var(--space-sm)]", children: title }),
1684
+ description && /* @__PURE__ */ jsx21(DialogPrimitive2.Description, { className: "text-[length:var(--bloom-text-body)] color-[var(--bloom-text-secondary)] mb-[var(--space-lg)]", children: description }),
1685
+ children,
1686
+ /* @__PURE__ */ jsx21(
1687
+ DialogPrimitive2.Close,
1688
+ {
1689
+ className: cn(
1690
+ "absolute top-[var(--space-lg)] right-[var(--space-lg)]",
1691
+ "inline-flex items-center justify-center",
1692
+ "h-[32px] w-[32px] rounded-full",
1693
+ "color-[var(--bloom-text-secondary)] hover:color-[var(--bloom-text)]",
1694
+ "hover:bg-[var(--bloom-surface2)]",
1695
+ "transition-colors duration-[var(--bloom-duration-fast)]",
1696
+ "focus-visible:outline-none focus-visible:ring-[4px] focus-visible:ring-[var(--bloom-accent1)]/30"
1697
+ ),
1698
+ "aria-label": "Close",
1699
+ children: /* @__PURE__ */ jsx21("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx21("path", { d: "M12 4L4 12M4 4l8 8", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }) })
1700
+ }
1701
+ )
1702
+ ]
1703
+ }
1704
+ )
1705
+ ] }) });
1706
+ }
1707
+
1708
+ // src/components/popover/popover.tsx
1709
+ import * as PopoverPrimitive from "@radix-ui/react-popover";
1710
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
1711
+ function Popover2({
1712
+ trigger,
1713
+ children,
1714
+ side = "bottom",
1715
+ align = "center",
1716
+ className,
1717
+ open,
1718
+ onOpenChange
1719
+ }) {
1720
+ return /* @__PURE__ */ jsxs16(PopoverPrimitive.Root, { open, onOpenChange, children: [
1721
+ /* @__PURE__ */ jsx22(PopoverPrimitive.Trigger, { asChild: true, children: trigger }),
1722
+ /* @__PURE__ */ jsx22(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx22(
1723
+ PopoverPrimitive.Content,
1724
+ {
1725
+ side,
1726
+ align,
1727
+ sideOffset: 8,
1728
+ className: cn(
1729
+ "bloom z-50 w-[320px] overflow-hidden",
1730
+ "rounded-[var(--bloom-radius)]",
1731
+ "bg-[var(--bloom-surface)] p-[var(--space-lg)]",
1732
+ "shadow-[var(--bloom-shadow-hover)]",
1733
+ "border border-[var(--bloom-surface2)]",
1734
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
1735
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
1736
+ "focus:outline-none",
1737
+ className
1738
+ ),
1739
+ children
1740
+ }
1741
+ ) })
1742
+ ] });
1743
+ }
1744
+
1745
+ // src/components/accordion/accordion.tsx
1746
+ import { forwardRef as forwardRef16 } from "react";
1747
+ import * as AccordionPrimitive from "@radix-ui/react-accordion";
1748
+ import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
1749
+ var Accordion = forwardRef16(
1750
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
1751
+ AccordionPrimitive.Root,
1752
+ {
1753
+ ref,
1754
+ className: cn("w-full", className),
1755
+ ...props
1756
+ }
1757
+ )
1758
+ );
1759
+ Accordion.displayName = "Accordion";
1760
+ var AccordionItem = forwardRef16(
1761
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
1762
+ AccordionPrimitive.Item,
1763
+ {
1764
+ ref,
1765
+ className: cn(
1766
+ "border-b border-[var(--bloom-surface2)]",
1767
+ className
1768
+ ),
1769
+ ...props
1770
+ }
1771
+ )
1772
+ );
1773
+ AccordionItem.displayName = "AccordionItem";
1774
+ var AccordionTrigger = forwardRef16(
1775
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx23(AccordionPrimitive.Header, { className: "flex", children: /* @__PURE__ */ jsxs17(
1776
+ AccordionPrimitive.Trigger,
1777
+ {
1778
+ ref,
1779
+ className: cn(
1780
+ "flex flex-1 items-center justify-between",
1781
+ "py-[var(--space-lg)]",
1782
+ "text-[length:var(--bloom-text-body)] font-[family-name:var(--bloom-font)] font-medium color-[var(--bloom-text)]",
1783
+ "cursor-pointer",
1784
+ "transition-all duration-[var(--bloom-duration-fast)]",
1785
+ "hover:color-[var(--bloom-accent1-deep)]",
1786
+ "[&[data-state=open]>svg]:rotate-180",
1787
+ className
1788
+ ),
1789
+ ...props,
1790
+ children: [
1791
+ children,
1792
+ /* @__PURE__ */ jsx23(
1793
+ "svg",
1794
+ {
1795
+ width: "16",
1796
+ height: "16",
1797
+ viewBox: "0 0 16 16",
1798
+ fill: "none",
1799
+ stroke: "currentColor",
1800
+ strokeWidth: "1.5",
1801
+ strokeLinecap: "round",
1802
+ strokeLinejoin: "round",
1803
+ className: "shrink-0 transition-transform duration-[var(--bloom-duration-fast)]",
1804
+ children: /* @__PURE__ */ jsx23("path", { d: "M4 6l4 4 4-4" })
1805
+ }
1806
+ )
1807
+ ]
1808
+ }
1809
+ ) })
1810
+ );
1811
+ AccordionTrigger.displayName = "AccordionTrigger";
1812
+ var AccordionContent = forwardRef16(
1813
+ ({ className, children, ...props }, ref) => /* @__PURE__ */ jsx23(
1814
+ AccordionPrimitive.Content,
1815
+ {
1816
+ ref,
1817
+ className: cn(
1818
+ "overflow-hidden",
1819
+ "text-[length:var(--bloom-text-body)] font-[family-name:var(--bloom-font)] color-[var(--bloom-text-secondary)]",
1820
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0",
1821
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
1822
+ className
1823
+ ),
1824
+ ...props,
1825
+ children: /* @__PURE__ */ jsx23("div", { className: "pb-[var(--space-lg)]", children })
1826
+ }
1827
+ )
1828
+ );
1829
+ AccordionContent.displayName = "AccordionContent";
1830
+
1502
1831
  // src/components/theme/theme.tsx
1503
1832
  import {
1504
1833
  createContext as createContext2,
1505
1834
  useContext as useContext2,
1506
- useState as useState5,
1507
- useEffect as useEffect3,
1508
- useCallback as useCallback2,
1509
- useRef
1835
+ useState as useState6,
1836
+ useEffect as useEffect4,
1837
+ useCallback as useCallback3,
1838
+ useRef as useRef2
1510
1839
  } from "react";
1511
- import { jsx as jsx20 } from "react/jsx-runtime";
1840
+ import { jsx as jsx24 } from "react/jsx-runtime";
1512
1841
  var ThemeContext = createContext2(null);
1513
1842
  function useTheme() {
1514
1843
  const ctx = useContext2(ThemeContext);
@@ -1530,35 +1859,35 @@ function ThemeProvider({
1530
1859
  palettes = [],
1531
1860
  storageKey = "bloom-theme"
1532
1861
  }) {
1533
- const paletteMap = useRef(
1862
+ const paletteMap = useRef2(
1534
1863
  new Map([
1535
1864
  ["bloom", { name: "bloom" }],
1536
1865
  ...palettes.map((p) => [p.name, p])
1537
1866
  ])
1538
1867
  );
1539
- const [colorMode, setColorModeState] = useState5(() => {
1868
+ const [colorMode, setColorModeState] = useState6(() => {
1540
1869
  if (typeof window === "undefined") return defaultColorMode;
1541
1870
  const stored = localStorage.getItem(`${storageKey}-mode`);
1542
1871
  if (stored === "light" || stored === "dark" || stored === "system") return stored;
1543
1872
  return defaultColorMode;
1544
1873
  });
1545
- const [palette, setPaletteState] = useState5(() => {
1874
+ const [palette, setPaletteState] = useState6(() => {
1546
1875
  if (typeof window === "undefined") return defaultPalette;
1547
1876
  const stored = localStorage.getItem(`${storageKey}-palette`);
1548
1877
  if (stored && paletteMap.current.has(stored)) return stored;
1549
1878
  return defaultPalette;
1550
1879
  });
1551
- const [resolvedMode, setResolvedMode] = useState5(
1880
+ const [resolvedMode, setResolvedMode] = useState6(
1552
1881
  () => resolveMode(colorMode)
1553
1882
  );
1554
- const setColorMode = useCallback2(
1883
+ const setColorMode = useCallback3(
1555
1884
  (mode) => {
1556
1885
  setColorModeState(mode);
1557
1886
  localStorage.setItem(`${storageKey}-mode`, mode);
1558
1887
  },
1559
1888
  [storageKey]
1560
1889
  );
1561
- const setPalette = useCallback2(
1890
+ const setPalette = useCallback3(
1562
1891
  (name) => {
1563
1892
  if (!paletteMap.current.has(name)) return;
1564
1893
  setPaletteState(name);
@@ -1566,10 +1895,10 @@ function ThemeProvider({
1566
1895
  },
1567
1896
  [storageKey]
1568
1897
  );
1569
- const toggleColorMode = useCallback2(() => {
1898
+ const toggleColorMode = useCallback3(() => {
1570
1899
  setColorMode(resolvedMode === "light" ? "dark" : "light");
1571
1900
  }, [resolvedMode, setColorMode]);
1572
- useEffect3(() => {
1901
+ useEffect4(() => {
1573
1902
  const root = document.documentElement;
1574
1903
  const resolved = resolveMode(colorMode);
1575
1904
  setResolvedMode(resolved);
@@ -1591,7 +1920,7 @@ function ThemeProvider({
1591
1920
  }
1592
1921
  }
1593
1922
  }, [colorMode, palette]);
1594
- useEffect3(() => {
1923
+ useEffect4(() => {
1595
1924
  if (colorMode !== "system") return;
1596
1925
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
1597
1926
  const handler = () => {
@@ -1620,7 +1949,7 @@ function ThemeProvider({
1620
1949
  return () => mq.removeEventListener("change", handler);
1621
1950
  }, [colorMode, palette]);
1622
1951
  const paletteNames = Array.from(paletteMap.current.keys());
1623
- return /* @__PURE__ */ jsx20(
1952
+ return /* @__PURE__ */ jsx24(
1624
1953
  ThemeContext.Provider,
1625
1954
  {
1626
1955
  value: {
@@ -1787,6 +2116,10 @@ var oceanMist = {
1787
2116
  };
1788
2117
  var builtInPalettes = [midnightGarden, desertRose, oceanMist];
1789
2118
  export {
2119
+ Accordion,
2120
+ AccordionContent,
2121
+ AccordionItem,
2122
+ AccordionTrigger,
1790
2123
  Alert,
1791
2124
  AlertDescription,
1792
2125
  AlertTitle,
@@ -1802,11 +2135,14 @@ export {
1802
2135
  CardTitle,
1803
2136
  Checkbox,
1804
2137
  DatePicker,
2138
+ Drawer,
1805
2139
  Dropdown,
1806
2140
  DropdownItem,
1807
2141
  DropdownSeparator,
1808
2142
  Input,
1809
2143
  Modal,
2144
+ OTPInput,
2145
+ Popover2 as Popover,
1810
2146
  Progress,
1811
2147
  ProgressCircular,
1812
2148
  RadioGroup,