@planetaexo/design-system 0.9.4 → 0.9.5

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
@@ -5696,74 +5696,19 @@ var OTPCodeInput = ({
5696
5696
  required
5697
5697
  }) => {
5698
5698
  const baseId = id != null ? id : React22__namespace.useId();
5699
- const inputRefs = React22__namespace.useRef([]);
5699
+ const inputRef = React22__namespace.useRef(null);
5700
+ const [focused, setFocused] = React22__namespace.useState(false);
5700
5701
  const digits = React22__namespace.useMemo(() => {
5701
5702
  const arr = value.split("").slice(0, length);
5702
5703
  while (arr.length < length) arr.push("");
5703
5704
  return arr;
5704
5705
  }, [value, length]);
5705
- const updateValue = (newDigits) => {
5706
- onChange(newDigits.join(""));
5707
- };
5708
- const focusedIndexRef = React22__namespace.useRef(0);
5709
- const focusSlot = (index) => {
5710
- var _a;
5711
- if (index >= 0 && index < length) {
5712
- (_a = inputRefs.current[index]) == null ? void 0 : _a.focus();
5713
- }
5714
- };
5715
- const handleChange = (index, raw) => {
5716
- const numeric = raw.replace(/\D/g, "");
5717
- if (!numeric) return;
5718
- const newDigits = [...digits];
5719
- if (numeric.length === 1) {
5720
- newDigits[index] = numeric;
5721
- updateValue(newDigits);
5722
- if (index < length - 1) focusSlot(index + 1);
5723
- return;
5724
- }
5725
- const toPaste = numeric.slice(0, length - index);
5726
- for (let i = 0; i < toPaste.length; i++) {
5727
- newDigits[index + i] = toPaste[i];
5728
- }
5729
- updateValue(newDigits);
5730
- const lastFilled = Math.min(index + toPaste.length, length) - 1;
5731
- focusSlot(lastFilled < length - 1 ? lastFilled + 1 : lastFilled);
5732
- };
5733
- const handleKeyDown = (index, e) => {
5734
- if (e.key === "Backspace") {
5735
- e.preventDefault();
5736
- const newDigits = [...digits];
5737
- if (newDigits[index]) {
5738
- newDigits[index] = "";
5739
- updateValue(newDigits);
5740
- } else if (index > 0) {
5741
- newDigits[index - 1] = "";
5742
- updateValue(newDigits);
5743
- focusSlot(index - 1);
5744
- }
5745
- } else if (e.key === "ArrowLeft") {
5746
- e.preventDefault();
5747
- focusSlot(index - 1);
5748
- } else if (e.key === "ArrowRight") {
5749
- e.preventDefault();
5750
- focusSlot(index + 1);
5751
- } else if (e.key === "Tab") ; else if (!/^\d$/.test(e.key) && e.key.length === 1) {
5752
- e.preventDefault();
5753
- }
5754
- };
5755
- const handlePaste = (e, startIndex) => {
5756
- e.preventDefault();
5757
- const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
5758
- if (!pasted) return;
5759
- const newDigits = [...digits];
5760
- for (let i = 0; i < pasted.length && startIndex + i < length; i++) {
5761
- newDigits[startIndex + i] = pasted[i];
5762
- }
5763
- updateValue(newDigits);
5764
- const lastFilled = Math.min(startIndex + pasted.length, length) - 1;
5765
- focusSlot(lastFilled < length - 1 ? lastFilled + 1 : lastFilled);
5706
+ const handleChange = (e) => {
5707
+ const numeric = e.target.value.replace(/\D/g, "").slice(0, length);
5708
+ onChange(numeric);
5766
5709
  };
5710
+ const activeIndex = Math.min(value.length, length - 1);
5711
+ const errorId = error ? `${baseId}-error` : void 0;
5767
5712
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center", className), children: [
5768
5713
  /* @__PURE__ */ jsxRuntime.jsx(
5769
5714
  "label",
@@ -5776,50 +5721,71 @@ var OTPCodeInput = ({
5776
5721
  children: label
5777
5722
  }
5778
5723
  ),
5779
- /* @__PURE__ */ jsxRuntime.jsx(
5724
+ /* @__PURE__ */ jsxRuntime.jsxs(
5780
5725
  "div",
5781
5726
  {
5782
5727
  className: cn(
5783
- "flex justify-center gap-2",
5728
+ "relative",
5784
5729
  disabled && "opacity-50 pointer-events-none"
5785
5730
  ),
5786
- role: "group",
5787
- "aria-label": label,
5788
- children: digits.map((digit, index) => /* @__PURE__ */ jsxRuntime.jsx(
5789
- "input",
5790
- {
5791
- ref: (el) => {
5792
- inputRefs.current[index] = el;
5793
- },
5794
- id: index === 0 ? baseId : `${baseId}-${index}`,
5795
- type: "text",
5796
- inputMode: "numeric",
5797
- pattern: "\\d*",
5798
- maxLength: 1,
5799
- value: digit,
5800
- autoComplete: index === 0 ? "one-time-code" : "off",
5801
- "aria-label": `${label} d\xEDgito ${index + 1} de ${length}`,
5802
- disabled,
5803
- onChange: (e) => handleChange(index, e.target.value),
5804
- onKeyDown: (e) => handleKeyDown(index, e),
5805
- onPaste: (e) => handlePaste(e, index),
5806
- onFocus: (e) => {
5807
- focusedIndexRef.current = index;
5808
- e.target.select();
5809
- },
5810
- className: cn(
5811
- "w-11 h-14 text-center text-lg rounded-lg border font-ui",
5812
- "bg-background text-foreground border-border",
5813
- "transition-colors",
5814
- "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary",
5815
- error && "border-destructive focus:border-destructive focus:ring-destructive"
5816
- )
5817
- },
5818
- index
5819
- ))
5731
+ children: [
5732
+ /* @__PURE__ */ jsxRuntime.jsx(
5733
+ "input",
5734
+ {
5735
+ ref: inputRef,
5736
+ id: baseId,
5737
+ type: "text",
5738
+ inputMode: "numeric",
5739
+ pattern: "\\d*",
5740
+ maxLength: length,
5741
+ value,
5742
+ autoComplete: "one-time-code",
5743
+ "aria-label": label,
5744
+ "aria-describedby": errorId,
5745
+ "aria-invalid": !!error,
5746
+ disabled,
5747
+ required,
5748
+ onChange: handleChange,
5749
+ onFocus: () => setFocused(true),
5750
+ onBlur: () => setFocused(false),
5751
+ className: "absolute inset-0 w-full h-full opacity-0 cursor-text outline-none"
5752
+ }
5753
+ ),
5754
+ /* @__PURE__ */ jsxRuntime.jsx(
5755
+ "div",
5756
+ {
5757
+ className: "flex justify-center gap-2 pointer-events-none",
5758
+ role: "group",
5759
+ "aria-hidden": "true",
5760
+ children: digits.map((digit, i) => {
5761
+ const isActive = focused && i === activeIndex;
5762
+ return /* @__PURE__ */ jsxRuntime.jsx(
5763
+ "div",
5764
+ {
5765
+ className: cn(
5766
+ "w-11 h-14 flex items-center justify-center text-lg rounded-lg border font-ui",
5767
+ "bg-background text-foreground border-border transition-colors",
5768
+ isActive && "border-primary ring-1 ring-primary",
5769
+ error && "border-destructive"
5770
+ ),
5771
+ children: digit
5772
+ },
5773
+ i
5774
+ );
5775
+ })
5776
+ }
5777
+ )
5778
+ ]
5820
5779
  }
5821
5780
  ),
5822
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-destructive font-ui self-start", children: error })
5781
+ error && /* @__PURE__ */ jsxRuntime.jsx(
5782
+ "p",
5783
+ {
5784
+ id: errorId,
5785
+ className: "mt-1 text-xs text-destructive font-ui self-start",
5786
+ children: error
5787
+ }
5788
+ )
5823
5789
  ] });
5824
5790
  };
5825
5791
  OTPCodeInput.displayName = "OTPCodeInput";