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