@planetaexo/design-system 0.9.3 → 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
@@ -3894,8 +3894,11 @@ function BookingConfirmationEmail({
3894
3894
  );
3895
3895
  }
3896
3896
  function BookingOtpEmail({
3897
- bodyMessage,
3897
+ greeting,
3898
+ intro,
3899
+ code,
3898
3900
  expiryMessage,
3901
+ teamSignature,
3899
3902
  logoUrl,
3900
3903
  className
3901
3904
  }) {
@@ -3915,15 +3918,44 @@ function BookingOtpEmail({
3915
3918
  className,
3916
3919
  children: [
3917
3920
  /* @__PURE__ */ jsxRuntime.jsx(EmailLogo, { src: logoUrl }),
3921
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "16px", lineHeight: "1.5", margin: "0 0 12px" }, children: greeting }),
3922
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "15px", lineHeight: "1.5", margin: "0 0 24px" }, children: intro }),
3918
3923
  /* @__PURE__ */ jsxRuntime.jsx(
3919
- "p",
3924
+ "table",
3920
3925
  {
3921
- style: {
3922
- fontSize: "16px",
3923
- lineHeight: "1.6",
3924
- margin: "0 0 16px"
3925
- },
3926
- children: bodyMessage
3926
+ role: "presentation",
3927
+ cellPadding: 0,
3928
+ cellSpacing: 0,
3929
+ border: 0,
3930
+ style: { width: "100%", borderCollapse: "collapse", margin: "0 0 24px" },
3931
+ children: /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
3932
+ "td",
3933
+ {
3934
+ align: "center",
3935
+ style: {
3936
+ backgroundColor: emailTokens.primaryLight,
3937
+ border: `1px solid ${emailTokens.border}`,
3938
+ borderRadius: "12px",
3939
+ padding: "24px 16px"
3940
+ },
3941
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3942
+ "div",
3943
+ {
3944
+ style: {
3945
+ fontFamily: emailTokens.fontFamily,
3946
+ fontSize: "36px",
3947
+ fontWeight: 700,
3948
+ letterSpacing: "0.3em",
3949
+ color: emailTokens.foreground,
3950
+ lineHeight: 1,
3951
+ // Padding esquerdo compensa letter-spacing final, mantendo visualmente centralizado.
3952
+ paddingLeft: "0.3em"
3953
+ },
3954
+ children: code
3955
+ }
3956
+ )
3957
+ }
3958
+ ) }) })
3927
3959
  }
3928
3960
  ),
3929
3961
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -3933,11 +3965,12 @@ function BookingOtpEmail({
3933
3965
  color: emailTokens.mutedForeground,
3934
3966
  fontSize: "14px",
3935
3967
  lineHeight: "1.5",
3936
- margin: "0"
3968
+ margin: "0 0 24px"
3937
3969
  },
3938
3970
  children: expiryMessage
3939
3971
  }
3940
- )
3972
+ ),
3973
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "14px", lineHeight: "1.5", margin: "0" }, children: teamSignature })
3941
3974
  ]
3942
3975
  }
3943
3976
  );
@@ -5663,66 +5696,19 @@ var OTPCodeInput = ({
5663
5696
  required
5664
5697
  }) => {
5665
5698
  const baseId = id != null ? id : React22__namespace.useId();
5666
- const inputRefs = React22__namespace.useRef([]);
5699
+ const inputRef = React22__namespace.useRef(null);
5700
+ const [focused, setFocused] = React22__namespace.useState(false);
5667
5701
  const digits = React22__namespace.useMemo(() => {
5668
5702
  const arr = value.split("").slice(0, length);
5669
5703
  while (arr.length < length) arr.push("");
5670
5704
  return arr;
5671
5705
  }, [value, length]);
5672
- const updateValue = (newDigits) => {
5673
- onChange(newDigits.join(""));
5674
- };
5675
- const focusedIndexRef = React22__namespace.useRef(0);
5676
- const focusSlot = (index) => {
5677
- var _a;
5678
- if (index >= 0 && index < length) {
5679
- (_a = inputRefs.current[index]) == null ? void 0 : _a.focus();
5680
- }
5681
- };
5682
- const handleChange = (index, raw) => {
5683
- const numeric = raw.replace(/\D/g, "");
5684
- if (!numeric) return;
5685
- const newDigits = [...digits];
5686
- newDigits[index] = numeric[numeric.length - 1];
5687
- updateValue(newDigits);
5688
- if (index < length - 1) {
5689
- focusSlot(index + 1);
5690
- }
5691
- };
5692
- const handleKeyDown = (index, e) => {
5693
- if (e.key === "Backspace") {
5694
- e.preventDefault();
5695
- const newDigits = [...digits];
5696
- if (newDigits[index]) {
5697
- newDigits[index] = "";
5698
- updateValue(newDigits);
5699
- } else if (index > 0) {
5700
- newDigits[index - 1] = "";
5701
- updateValue(newDigits);
5702
- focusSlot(index - 1);
5703
- }
5704
- } else if (e.key === "ArrowLeft") {
5705
- e.preventDefault();
5706
- focusSlot(index - 1);
5707
- } else if (e.key === "ArrowRight") {
5708
- e.preventDefault();
5709
- focusSlot(index + 1);
5710
- } else if (e.key === "Tab") ; else if (!/^\d$/.test(e.key) && e.key.length === 1) {
5711
- e.preventDefault();
5712
- }
5713
- };
5714
- const handlePaste = (e, startIndex) => {
5715
- e.preventDefault();
5716
- const pasted = e.clipboardData.getData("text").replace(/\D/g, "").slice(0, length);
5717
- if (!pasted) return;
5718
- const newDigits = [...digits];
5719
- for (let i = 0; i < pasted.length && startIndex + i < length; i++) {
5720
- newDigits[startIndex + i] = pasted[i];
5721
- }
5722
- updateValue(newDigits);
5723
- const lastFilled = Math.min(startIndex + pasted.length, length) - 1;
5724
- 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);
5725
5709
  };
5710
+ const activeIndex = Math.min(value.length, length - 1);
5711
+ const errorId = error ? `${baseId}-error` : void 0;
5726
5712
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-col items-center", className), children: [
5727
5713
  /* @__PURE__ */ jsxRuntime.jsx(
5728
5714
  "label",
@@ -5735,50 +5721,71 @@ var OTPCodeInput = ({
5735
5721
  children: label
5736
5722
  }
5737
5723
  ),
5738
- /* @__PURE__ */ jsxRuntime.jsx(
5724
+ /* @__PURE__ */ jsxRuntime.jsxs(
5739
5725
  "div",
5740
5726
  {
5741
5727
  className: cn(
5742
- "flex justify-center gap-2",
5728
+ "relative",
5743
5729
  disabled && "opacity-50 pointer-events-none"
5744
5730
  ),
5745
- role: "group",
5746
- "aria-label": label,
5747
- children: digits.map((digit, index) => /* @__PURE__ */ jsxRuntime.jsx(
5748
- "input",
5749
- {
5750
- ref: (el) => {
5751
- inputRefs.current[index] = el;
5752
- },
5753
- id: index === 0 ? baseId : `${baseId}-${index}`,
5754
- type: "text",
5755
- inputMode: "numeric",
5756
- pattern: "\\d*",
5757
- maxLength: 1,
5758
- value: digit,
5759
- autoComplete: index === 0 ? "one-time-code" : "off",
5760
- "aria-label": `${label} d\xEDgito ${index + 1} de ${length}`,
5761
- disabled,
5762
- onChange: (e) => handleChange(index, e.target.value),
5763
- onKeyDown: (e) => handleKeyDown(index, e),
5764
- onPaste: (e) => handlePaste(e, index),
5765
- onFocus: (e) => {
5766
- focusedIndexRef.current = index;
5767
- e.target.select();
5768
- },
5769
- className: cn(
5770
- "w-11 h-14 text-center text-lg rounded-lg border font-ui",
5771
- "bg-background text-foreground border-border",
5772
- "transition-colors",
5773
- "focus:outline-none focus:border-primary focus:ring-1 focus:ring-primary",
5774
- error && "border-destructive focus:border-destructive focus:ring-destructive"
5775
- )
5776
- },
5777
- index
5778
- ))
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
+ ]
5779
5779
  }
5780
5780
  ),
5781
- 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
+ )
5782
5789
  ] });
5783
5790
  };
5784
5791
  OTPCodeInput.displayName = "OTPCodeInput";