@coinbase/cdp-react 0.0.21 → 0.0.22

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.
Files changed (31) hide show
  1. package/dist/assets/AmountInput.css +1 -0
  2. package/dist/assets/ExchangeAmountInput.css +1 -0
  3. package/dist/components/forms/AmountInput/index.d.ts +3 -0
  4. package/dist/components/forms/AmountInput/index.js +92 -0
  5. package/dist/components/forms/AmountInput/types.d.ts +19 -0
  6. package/dist/components/forms/AmountInput/types.js +1 -0
  7. package/dist/components/forms/AmountInput/useAmountInput.d.ts +2 -0
  8. package/dist/components/forms/AmountInput/useAmountInput.js +113 -0
  9. package/dist/components/forms/AmountInput/useInputScale.d.ts +13 -0
  10. package/dist/components/forms/AmountInput/useInputScale.js +35 -0
  11. package/dist/components/forms/AmountInput/useNumberParseAndFormat.d.ts +11 -0
  12. package/dist/components/forms/AmountInput/useNumberParseAndFormat.js +22 -0
  13. package/dist/components/forms/ExchangeAmountInput/index.d.ts +3 -0
  14. package/dist/components/forms/ExchangeAmountInput/index.js +87 -0
  15. package/dist/components/forms/ExchangeAmountInput/types.d.ts +30 -0
  16. package/dist/components/forms/ExchangeAmountInput/types.js +1 -0
  17. package/dist/components/forms/ExchangeAmountInput/useExchangeAmountInput.d.ts +2 -0
  18. package/dist/components/forms/ExchangeAmountInput/useExchangeAmountInput.js +102 -0
  19. package/dist/components/forms/OTPForm/index.js +8 -7
  20. package/dist/data/locale.d.ts +1 -0
  21. package/dist/data/locale.js +4 -0
  22. package/dist/icons/IconArrowsUpDown.d.ts +2 -0
  23. package/dist/icons/IconArrowsUpDown.js +14 -0
  24. package/dist/icons/index.d.ts +1 -0
  25. package/dist/icons/index.js +14 -12
  26. package/dist/index.js +58 -52
  27. package/dist/utils/clamp.d.ts +1 -0
  28. package/dist/utils/clamp.js +4 -0
  29. package/dist/utils/index.d.ts +2 -0
  30. package/dist/utils/index.js +10 -6
  31. package/package.json +10 -7
@@ -0,0 +1 @@
1
+ .AmountInput-module__amount-input___24NlC{--cdp-web-amount-input-text-size: 3.75em;--cdp-web-amount-input-scale: 1;--cdp-web-amount-input-width: 1em;box-sizing:border-box;color:var(--cdp-web-colors-page-text-default);font-family:var(--cdp-web-font-family-sans);font-size:var(--cdp-web-font-size-base);line-height:1.2;display:flex;align-items:center;justify-content:flex-start;gap:.25rem;overflow:hidden;position:relative;width:100%}.AmountInput-module__input___Af-R1{appearance:textfield;background-color:transparent;color:var(--cdp-web-colors-page-text-default);border:0;font-weight:600;margin:0;outline:0;padding:0;width:var(--cdp-web-amount-input-width)}.AmountInput-module__input___Af-R1::placeholder{color:var(--cdp-web-colors-page-text-muted)}.AmountInput-module__amount-unit___48d60{font-size:var(--cdp-web-amount-input-text-size);font-weight:600;display:flex;align-items:center;justify-content:flex-start}.AmountInput-module__amount-unit___48d60.AmountInput-module__visible___qmvT0{cursor:text;transform:scale(var(--cdp-web-amount-input-scale));transform-origin:left center}.AmountInput-module__hidden___cO0sQ{visibility:hidden;position:absolute;pointer-events:none}.AmountInput-module__unit___-zmGz{color:var(--cdp-web-colors-page-text-muted)}
@@ -0,0 +1 @@
1
+ .ExchangeAmountInput-module__flex-row___ZKB-Q{display:flex;flex-direction:row;font-size:var(--cdp-web-font-size-base);align-items:center;justify-content:flex-start}.ExchangeAmountInput-module__gap-1___vuNQW{gap:.5em}.ExchangeAmountInput-module__gap-2___4-s-b{gap:.25em}.ExchangeAmountInput-module__swap-button___i9lSz{background-color:transparent;border:none;display:flex;align-items:center;justify-content:center;padding:0;margin:0;cursor:pointer}.ExchangeAmountInput-module__icon___b5JpF{width:auto;height:1.25em}
@@ -0,0 +1,3 @@
1
+ import { InputHTMLAttributes } from 'react';
2
+ import { AmountInputProps } from './types';
3
+ export declare const AmountInput: import('react').ForwardRefExoticComponent<AmountInputProps & Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "type" | "inputMode" | "onChange" | "max" | "min"> & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,92 @@
1
+ import { jsxs as s, jsx as a } from "react/jsx-runtime";
2
+ import { forwardRef as g, useRef as u, useCallback as j, useEffect as f } from "react";
3
+ import { useAmountInput as q } from "./useAmountInput.js";
4
+ import { useInputScale as z } from "./useInputScale.js";
5
+ import '../../../assets/AmountInput.css';const w = "AmountInput-module__input___Af-R1", E = "AmountInput-module__visible___qmvT0", G = "AmountInput-module__hidden___cO0sQ", M = "AmountInput-module__unit___-zmGz", n = {
6
+ "amount-input": "AmountInput-module__amount-input___24NlC",
7
+ input: w,
8
+ "amount-unit": "AmountInput-module__amount-unit___48d60",
9
+ visible: E,
10
+ hidden: G,
11
+ unit: M
12
+ }, O = g(
13
+ ({
14
+ amount: h,
15
+ className: I = "",
16
+ unit: t,
17
+ decimalPlaces: p = 2,
18
+ locale: A,
19
+ max: R,
20
+ min: v,
21
+ setAmount: N,
22
+ onBlur: y,
23
+ onPaste: C,
24
+ placeholder: r = "0",
25
+ ...$
26
+ }, e) => {
27
+ const o = u(null), l = u(null), c = u(null), m = u(null), d = u(null), { handleBlur: b, handleChange: x, handleBeforeInput: B, handlePaste: k, inputValue: i } = q(
28
+ {
29
+ amount: h,
30
+ decimalPlaces: p,
31
+ locale: A,
32
+ max: R,
33
+ min: v,
34
+ setAmount: N,
35
+ onBlur: y,
36
+ onPaste: C
37
+ }
38
+ ), { updateScale: _ } = z({
39
+ containerRef: l,
40
+ measureRef: c,
41
+ valueRef: m,
42
+ inputRef: o,
43
+ scaleWrapperRef: d
44
+ }), S = j(() => {
45
+ l.current?.querySelector("input[type='text']")?.focus();
46
+ }, []);
47
+ return f(() => {
48
+ _();
49
+ }, [i, t, p, _]), f(() => {
50
+ e && (typeof e == "function" ? e(o.current) : e.current = o.current);
51
+ }, [e]), /* @__PURE__ */ s("span", { ref: l, className: n["amount-input"], children: [
52
+ /* @__PURE__ */ s("span", { ref: d, className: `${n["amount-unit"]} ${n.visible}`, children: [
53
+ /* @__PURE__ */ a(
54
+ "input",
55
+ {
56
+ className: `${n.input} ${I}`,
57
+ inputMode: "decimal",
58
+ onBlur: b,
59
+ onChange: x,
60
+ onBeforeInput: B,
61
+ onPaste: k,
62
+ placeholder: r,
63
+ ref: o,
64
+ type: "text",
65
+ value: i,
66
+ ...$
67
+ }
68
+ ),
69
+ t && /* @__PURE__ */ a("span", { className: n.unit, onClick: S, children: t })
70
+ ] }),
71
+ /* @__PURE__ */ s(
72
+ "span",
73
+ {
74
+ ref: c,
75
+ "aria-hidden": "true",
76
+ className: `${n["amount-unit"]} ${n.hidden}`,
77
+ children: [
78
+ /* @__PURE__ */ s("span", { ref: m, children: [
79
+ i || r,
80
+ " "
81
+ ] }),
82
+ t && /* @__PURE__ */ a("span", { children: t })
83
+ ]
84
+ }
85
+ )
86
+ ] });
87
+ }
88
+ );
89
+ O.displayName = "AmountInput";
90
+ export {
91
+ O as AmountInput
92
+ };
@@ -0,0 +1,19 @@
1
+ import { ChangeEvent, ClipboardEvent, FocusEvent, InputEvent, InputHTMLAttributes } from 'react';
2
+ export interface AmountInputProps {
3
+ amount: number | undefined;
4
+ unit?: string;
5
+ decimalPlaces?: number;
6
+ locale?: string;
7
+ max?: number;
8
+ min?: number;
9
+ setAmount: (amount: number) => void;
10
+ }
11
+ export type UseAmoutInputParams = Pick<AmountInputProps, "amount" | "decimalPlaces" | "locale" | "max" | "min" | "setAmount"> & Pick<InputHTMLAttributes<HTMLInputElement>, "onBlur" | "onPaste">;
12
+ export interface UseAmoutInputReturn {
13
+ handleBeforeInput: (e: InputEvent<HTMLInputElement>) => void;
14
+ handleBlur: (e: FocusEvent<HTMLInputElement>) => void;
15
+ handleChange: (e: ChangeEvent<HTMLInputElement>) => void;
16
+ handlePaste: (e: ClipboardEvent<HTMLInputElement>) => void;
17
+ inputValue: string;
18
+ numberValue: number;
19
+ }
@@ -0,0 +1 @@
1
+ import "react";
@@ -0,0 +1,2 @@
1
+ import { UseAmoutInputParams, UseAmoutInputReturn } from './types';
2
+ export declare const useAmountInput: ({ amount, decimalPlaces, locale, max, min, setAmount, onBlur, onPaste, }: UseAmoutInputParams) => UseAmoutInputReturn;
@@ -0,0 +1,113 @@
1
+ import { NumberFormatter as k } from "@internationalized/number";
2
+ import { useState as L, useCallback as n, useEffect as w, useMemo as S } from "react";
3
+ import { DEFAULT_LOCALE as T } from "../../../data/locale.js";
4
+ import { clamp as z } from "../../../utils/clamp.js";
5
+ import { useNumberParseAndFormat as B } from "./useNumberParseAndFormat.js";
6
+ const j = ({
7
+ amount: i,
8
+ decimalPlaces: p,
9
+ locale: b = T,
10
+ max: a,
11
+ min: r,
12
+ setAmount: g,
13
+ onBlur: D,
14
+ onPaste: F
15
+ }) => {
16
+ const [s, m] = L(
17
+ i === void 0 || isNaN(i) ? NaN : +i
18
+ ), d = n(
19
+ (t) => {
20
+ m(t), g(t);
21
+ },
22
+ [g]
23
+ ), [u, c] = L(
24
+ () => isNaN(s) ? "" : new k(b, {
25
+ maximumFractionDigits: p,
26
+ minimumFractionDigits: 0
27
+ }).format(s)
28
+ ), v = n(
29
+ (t) => r !== void 0 && a !== void 0 ? z(t, r, a) : r !== void 0 && a === void 0 ? Math.max(t, r) : r === void 0 && a !== void 0 ? Math.min(t, a) : t,
30
+ [r, a]
31
+ ), { parser: o, formatter: f } = B({
32
+ inputValue: u,
33
+ locale: b,
34
+ options: {
35
+ maximumFractionDigits: p,
36
+ minimumFractionDigits: 0
37
+ }
38
+ }), l = n(
39
+ (t) => {
40
+ if (o.isValidPartialNumber(t, r, a)) {
41
+ const e = o.parse(t);
42
+ d(e), c(t);
43
+ }
44
+ },
45
+ [a, r, o, d]
46
+ ), h = n(
47
+ (t) => {
48
+ l(t.target.value);
49
+ },
50
+ [l]
51
+ ), C = n(
52
+ (t) => {
53
+ const e = t.currentTarget;
54
+ if ("data" in t) {
55
+ if (!t.data) return;
56
+ if (t.data === " ") {
57
+ t.preventDefault();
58
+ return;
59
+ }
60
+ const V = e.selectionStart || 0, N = e.selectionEnd || 0, A = e.value, M = A.slice(0, V) + t.data + A.slice(N);
61
+ o.isValidPartialNumber(M, r, a) || t.preventDefault();
62
+ }
63
+ },
64
+ [o, r, a]
65
+ ), E = n(
66
+ (t) => {
67
+ if (D?.(t), !u.length) {
68
+ d(NaN), c("");
69
+ return;
70
+ }
71
+ const e = o.parse(u);
72
+ if (isNaN(e)) {
73
+ c(f.format(s));
74
+ return;
75
+ }
76
+ const V = v(e), N = Number(V.toFixed(p));
77
+ d(N), c(f.format(N));
78
+ },
79
+ [
80
+ p,
81
+ v,
82
+ u,
83
+ f,
84
+ o,
85
+ s,
86
+ D,
87
+ d
88
+ ]
89
+ ), I = n(
90
+ (t) => {
91
+ F?.(t);
92
+ let e = t.clipboardData?.getData("text").replace(/\s/g, "");
93
+ r !== void 0 && r >= 0 && (e = e.replace(/-/g, "")), l(e), t.preventDefault();
94
+ },
95
+ [r, F, l]
96
+ );
97
+ return w(() => {
98
+ (i === void 0 || isNaN(i)) && isNaN(s) || i === s || (i === void 0 || isNaN(i) ? (m(NaN), c("")) : (m(i), c(f.format(i))));
99
+ }, [i, f, s]), S(
100
+ () => ({
101
+ numberValue: s,
102
+ inputValue: u,
103
+ handleBlur: E,
104
+ handleChange: h,
105
+ handleBeforeInput: C,
106
+ handlePaste: I
107
+ }),
108
+ [E, h, C, I, u, s]
109
+ );
110
+ };
111
+ export {
112
+ j as useAmountInput
113
+ };
@@ -0,0 +1,13 @@
1
+ import { RefObject } from 'react';
2
+ interface UseInputScaleParams {
3
+ minScale?: number;
4
+ containerRef: RefObject<HTMLElement | null>;
5
+ valueRef: RefObject<HTMLElement | null>;
6
+ measureRef: RefObject<HTMLElement | null>;
7
+ inputRef: RefObject<HTMLInputElement | null>;
8
+ scaleWrapperRef: RefObject<HTMLElement | null>;
9
+ }
10
+ export declare const useInputScale: ({ minScale, containerRef, measureRef, inputRef, scaleWrapperRef, valueRef, }: UseInputScaleParams) => {
11
+ updateScale: () => void;
12
+ };
13
+ export {};
@@ -0,0 +1,35 @@
1
+ import { useCallback as W, useEffect as m } from "react";
2
+ const x = ({
3
+ minScale: c = 0.1,
4
+ containerRef: r,
5
+ measureRef: o,
6
+ inputRef: i,
7
+ scaleWrapperRef: l,
8
+ valueRef: u
9
+ }) => {
10
+ const n = W(() => {
11
+ const t = r.current, e = i.current, a = o.current, d = u.current, s = l.current;
12
+ if (!t || !a || !d || !e || !s)
13
+ return;
14
+ const h = a.clientWidth, b = t.clientWidth;
15
+ if (e.style.width = `${d.clientWidth}px`, h > b) {
16
+ const p = b / h;
17
+ s.style.transform = `scale(${Math.max(p, c)})`;
18
+ } else
19
+ s.style.transform = "scale(1)";
20
+ }, [c, r, o, u, i, l]);
21
+ return m(() => {
22
+ const t = r.current;
23
+ if (!t)
24
+ return;
25
+ const e = new ResizeObserver(n);
26
+ return e.observe(t), () => {
27
+ e.disconnect();
28
+ };
29
+ }, [r, n]), {
30
+ updateScale: n
31
+ };
32
+ };
33
+ export {
34
+ x as useInputScale
35
+ };
@@ -0,0 +1,11 @@
1
+ import { NumberParser, NumberFormatter } from '@internationalized/number';
2
+ export interface UseNumberParseAndFormatParams {
3
+ inputValue?: string;
4
+ locale?: string;
5
+ options?: Intl.NumberFormatOptions;
6
+ }
7
+ export interface UseNumberParseAndFormatReturn {
8
+ parser: NumberParser;
9
+ formatter: NumberFormatter;
10
+ }
11
+ export declare const useNumberParseAndFormat: (params?: UseNumberParseAndFormatParams) => UseNumberParseAndFormatReturn;
@@ -0,0 +1,22 @@
1
+ import { NumberParser as a, NumberFormatter as i } from "@internationalized/number";
2
+ import { useMemo as o } from "react";
3
+ import { DEFAULT_LOCALE as p } from "../../../data/locale.js";
4
+ const N = (u) => {
5
+ const { inputValue: m, locale: r = p, options: e } = u || {}, t = o(() => new a(r, e), [r, e]), n = o(
6
+ () => t.getNumberingSystem(m || ""),
7
+ [t, m]
8
+ ), s = o(
9
+ () => new i(r, { ...e, numberingSystem: n }),
10
+ [r, n, e]
11
+ );
12
+ return o(
13
+ () => ({
14
+ formatter: s,
15
+ parser: t
16
+ }),
17
+ [s, t]
18
+ );
19
+ };
20
+ export {
21
+ N as useNumberParseAndFormat
22
+ };
@@ -0,0 +1,3 @@
1
+ import { InputHTMLAttributes } from 'react';
2
+ import { ExchangeAmountInputProps } from './types';
3
+ export declare const ExchangeAmountInput: import('react').ForwardRefExoticComponent<ExchangeAmountInputProps & Omit<InputHTMLAttributes<HTMLInputElement>, "value" | "type" | "inputMode" | "onChange" | "max" | "min"> & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,87 @@
1
+ import { jsxs as o, Fragment as C, jsx as n } from "react/jsx-runtime";
2
+ import { forwardRef as L, useCallback as z } from "react";
3
+ import { AmountInput as D } from "../AmountInput/index.js";
4
+ import { DEFAULT_LOCALE as F } from "../../../data/locale.js";
5
+ import { IconArrowsUpDown as V } from "../../../icons/IconArrowsUpDown.js";
6
+ import { useExchangeAmountInput as j } from "./useExchangeAmountInput.js";
7
+ import '../../../assets/ExchangeAmountInput.css';const k = "ExchangeAmountInput-module__icon___b5JpF", t = {
8
+ "flex-row": "ExchangeAmountInput-module__flex-row___ZKB-Q",
9
+ "gap-1": "ExchangeAmountInput-module__gap-1___vuNQW",
10
+ "gap-2": "ExchangeAmountInput-module__gap-2___4-s-b",
11
+ "swap-button": "ExchangeAmountInput-module__swap-button___i9lSz",
12
+ icon: k
13
+ }, v = L(
14
+ ({
15
+ cryptoAmount: c,
16
+ cryptoCurrency: u,
17
+ cryptoDecimalPlaces: s,
18
+ fiatAmount: l,
19
+ fiatCurrency: e,
20
+ fiatDecimalPlaces: r,
21
+ exchangeRate: i,
22
+ inputType: a,
23
+ locale: p = F,
24
+ setCryptoAmount: _,
25
+ setFiatAmount: d,
26
+ setInputType: m,
27
+ ...g
28
+ }, h) => {
29
+ const f = a === "fiat" ? `switch input to ${u}` : `switch input to ${e}`, {
30
+ inputValue: x,
31
+ inputCurrency: w,
32
+ inputDecimalPlaces: A,
33
+ formatOutputValue: b,
34
+ outputValue: E,
35
+ outputCurrency: I,
36
+ handleChange: N
37
+ } = j({
38
+ cryptoAmount: c,
39
+ cryptoCurrency: u,
40
+ cryptoDecimalPlaces: s,
41
+ exchangeRate: i,
42
+ fiatAmount: l,
43
+ fiatCurrency: e,
44
+ fiatDecimalPlaces: r,
45
+ inputType: a,
46
+ locale: p,
47
+ setCryptoAmount: _,
48
+ setFiatAmount: d
49
+ }), $ = z(() => {
50
+ m(a === "fiat" ? "crypto" : "fiat");
51
+ }, [a, m]);
52
+ return /* @__PURE__ */ o(C, { children: [
53
+ /* @__PURE__ */ n(
54
+ D,
55
+ {
56
+ ref: h,
57
+ amount: x,
58
+ unit: w,
59
+ decimalPlaces: A,
60
+ locale: p,
61
+ setAmount: N,
62
+ ...g
63
+ }
64
+ ),
65
+ /* @__PURE__ */ o("span", { className: `${t["flex-row"]} ${t["gap-1"]}`, children: [
66
+ /* @__PURE__ */ n(
67
+ "button",
68
+ {
69
+ "aria-label": f,
70
+ className: t["swap-button"],
71
+ onClick: $,
72
+ type: "button",
73
+ children: /* @__PURE__ */ n(V, { className: t.icon })
74
+ }
75
+ ),
76
+ /* @__PURE__ */ o("span", { className: `${t["flex-row"]} ${t["gap-2"]}`, children: [
77
+ /* @__PURE__ */ n("span", { "data-part": "amount-input-unsized-value", children: b(E ?? 0) }),
78
+ /* @__PURE__ */ n("span", { "data-part": "amount-input-unsized-currency", children: I })
79
+ ] })
80
+ ] })
81
+ ] });
82
+ }
83
+ );
84
+ v.displayName = "ExchangeAmountInput";
85
+ export {
86
+ v as ExchangeAmountInput
87
+ };
@@ -0,0 +1,30 @@
1
+ import { AmountInputProps } from '../AmountInput/types';
2
+ export type InputType = "crypto" | "fiat";
3
+ export type ExchangeAmountInputProps = {
4
+ cryptoAmount: AmountInputProps["amount"];
5
+ cryptoDecimalPlaces?: AmountInputProps["decimalPlaces"];
6
+ cryptoCurrency: NonNullable<AmountInputProps["unit"]>;
7
+ exchangeRate: string;
8
+ fiatAmount: AmountInputProps["amount"];
9
+ fiatCurrency: NonNullable<AmountInputProps["unit"]>;
10
+ fiatDecimalPlaces?: AmountInputProps["decimalPlaces"];
11
+ inputType: InputType;
12
+ locale?: string;
13
+ max?: number;
14
+ min?: number;
15
+ setCryptoAmount: AmountInputProps["setAmount"];
16
+ setFiatAmount: AmountInputProps["setAmount"];
17
+ setInputType: (inputType: InputType) => void;
18
+ };
19
+ export type UseExchangeAmountInputParams = Omit<ExchangeAmountInputProps, "max" | "min" | "setInputType">;
20
+ export interface UseExchangeAmountInputReturn {
21
+ formatInputValue: (value: number) => string;
22
+ formatOutputValue: (value: number) => string;
23
+ handleChange: (value: number, onChange?: (value: number) => void) => void;
24
+ inputCurrency: string;
25
+ inputDecimalPlaces: number;
26
+ inputValue: AmountInputProps["amount"];
27
+ outputCurrency: string;
28
+ outputDecimalPlaces: number;
29
+ outputValue: AmountInputProps["amount"];
30
+ }
@@ -0,0 +1 @@
1
+ import "react";
@@ -0,0 +1,2 @@
1
+ import { UseExchangeAmountInputParams, UseExchangeAmountInputReturn } from './types';
2
+ export declare const useExchangeAmountInput: ({ cryptoAmount, cryptoCurrency, cryptoDecimalPlaces, exchangeRate, fiatAmount, fiatCurrency, fiatDecimalPlaces, inputType, locale, setFiatAmount, setCryptoAmount, }: UseExchangeAmountInputParams) => UseExchangeAmountInputReturn;
@@ -0,0 +1,102 @@
1
+ import { Big as h } from "big.js";
2
+ import { useCallback as u, useMemo as _ } from "react";
3
+ import { useNumberParseAndFormat as I } from "../AmountInput/useNumberParseAndFormat.js";
4
+ import { DEFAULT_LOCALE as k } from "../../../data/locale.js";
5
+ const O = (f) => {
6
+ try {
7
+ return h(f);
8
+ } catch {
9
+ return null;
10
+ }
11
+ }, z = ({
12
+ cryptoAmount: f,
13
+ cryptoCurrency: F,
14
+ cryptoDecimalPlaces: n = 8,
15
+ exchangeRate: a,
16
+ fiatAmount: N,
17
+ fiatCurrency: V,
18
+ fiatDecimalPlaces: i = 2,
19
+ inputType: o,
20
+ locale: E = k,
21
+ setFiatAmount: m,
22
+ setCryptoAmount: d
23
+ }) => {
24
+ const x = u(
25
+ (r) => {
26
+ m(r);
27
+ const t = O(r);
28
+ if (r === 0 || isNaN(r) || t === null) {
29
+ d(0);
30
+ return;
31
+ }
32
+ const s = t.times(a).round(n, h.roundDown);
33
+ d(s.eq(0) ? 0 : +s.toFixed());
34
+ },
35
+ [a, m, d, n]
36
+ ), L = u(
37
+ (r) => {
38
+ d(r);
39
+ const t = O(r);
40
+ if (r === 0 || isNaN(r) || t === null) {
41
+ m(0);
42
+ return;
43
+ }
44
+ const s = t.div(a).round(i, h.roundDown);
45
+ m(s.eq(0) ? 0 : +s.toFixed());
46
+ },
47
+ [a, m, d, i]
48
+ ), b = u(
49
+ (r, t) => {
50
+ o === "fiat" ? x(r) : L(r), t?.(r);
51
+ },
52
+ [x, L, o]
53
+ ), { formatter: g } = I({
54
+ inputValue: "",
55
+ locale: E,
56
+ options: {
57
+ maximumFractionDigits: i,
58
+ minimumFractionDigits: 0
59
+ }
60
+ }), { formatter: B } = I({
61
+ inputValue: "",
62
+ locale: E,
63
+ options: {
64
+ maximumFractionDigits: n,
65
+ minimumFractionDigits: 0
66
+ }
67
+ }), q = u(
68
+ (r) => o === "fiat" ? g.format(r) : B.format(r),
69
+ [B, g, o]
70
+ ), w = u(
71
+ (r) => o === "fiat" ? B.format(r) : g.format(r),
72
+ [B, g, o]
73
+ );
74
+ return _(
75
+ () => ({
76
+ inputCurrency: o === "fiat" ? V : F,
77
+ inputDecimalPlaces: o === "fiat" ? i : n,
78
+ inputValue: o === "fiat" ? N : f,
79
+ formatInputValue: q,
80
+ formatOutputValue: w,
81
+ handleChange: b,
82
+ outputCurrency: o === "fiat" ? F : V,
83
+ outputDecimalPlaces: o === "fiat" ? n : i,
84
+ outputValue: o === "fiat" ? f : N
85
+ }),
86
+ [
87
+ f,
88
+ F,
89
+ n,
90
+ N,
91
+ V,
92
+ i,
93
+ q,
94
+ w,
95
+ b,
96
+ o
97
+ ]
98
+ );
99
+ };
100
+ export {
101
+ z as useExchangeAmountInput
102
+ };
@@ -7,6 +7,7 @@ import { Button as F } from "../../ui/Button/index.js";
7
7
  import { LoadingSpinner as N } from "../../ui/LoadingSpinner/index.js";
8
8
  import { VisuallyHidden as g } from "../../ui/VisuallyHidden/index.js";
9
9
  import { isApiError as b } from "../../../utils/isApiError.js";
10
+ import "libphonenumber-js";
10
11
  import '../../../assets/OTPForm.css';const o = {
11
12
  "otp-form": "OTPForm-module__otp-form___G1-63",
12
13
  "form-footer": "OTPForm-module__form-footer___ybmdd",
@@ -14,10 +15,10 @@ import '../../../assets/OTPForm.css';const o = {
14
15
  "loading-spinner": "OTPForm-module__loading-spinner___8N9XU",
15
16
  "resend-wrapper": "OTPForm-module__resend-wrapper___aZUAz",
16
17
  "reset-timer": "OTPForm-module__reset-timer___7ElWj"
17
- }, S = ({
18
+ }, A = ({
18
19
  canResetOTP: m,
19
- error: a,
20
- isPending: t,
20
+ error: t,
21
+ isPending: a,
21
22
  onOTPChange: s,
22
23
  onResendOTP: l,
23
24
  otp: p,
@@ -36,7 +37,7 @@ import '../../../assets/OTPForm.css';const o = {
36
37
  autoSubmit: !0,
37
38
  passwordLength: n || 6,
38
39
  value: p,
39
- error: b(a) ? a.message : a,
40
+ error: b(t) ? t.message : t,
40
41
  onChange: (f) => f.preventDefault(),
41
42
  onValueChange: s,
42
43
  className: o["otp-form"],
@@ -44,14 +45,14 @@ import '../../../assets/OTPForm.css';const o = {
44
45
  }
45
46
  ),
46
47
  /* @__PURE__ */ r("div", { className: o["form-footer"], children: [
47
- t && !m && /* @__PURE__ */ e("div", { className: o["server-state-wrapper"], children: t && !m && /* @__PURE__ */ e(N, { className: o["loading-spinner"] }) }),
48
+ a && !m && /* @__PURE__ */ e("div", { className: o["server-state-wrapper"], children: a && !m && /* @__PURE__ */ e(N, { className: o["loading-spinner"] }) }),
48
49
  /* @__PURE__ */ r("div", { className: o["resend-wrapper"], children: [
49
50
  m && /* @__PURE__ */ e(h, { asChild: !0, children: /* @__PURE__ */ e(
50
51
  F,
51
52
  {
52
53
  type: "button",
53
54
  onClick: l,
54
- isPending: t,
55
+ isPending: a,
55
56
  variant: "linkPrimary",
56
57
  children: "Resend code"
57
58
  }
@@ -72,5 +73,5 @@ import '../../../assets/OTPForm.css';const o = {
72
73
  ] })
73
74
  ] });
74
75
  export {
75
- S as OTPForm
76
+ A as OTPForm
76
77
  };
@@ -0,0 +1 @@
1
+ export declare const DEFAULT_LOCALE = "en-US";
@@ -0,0 +1,4 @@
1
+ const L = "en-US";
2
+ export {
3
+ L as DEFAULT_LOCALE
4
+ };
@@ -0,0 +1,2 @@
1
+ import { SVGProps } from 'react';
2
+ export declare const IconArrowsUpDown: (props: Omit<SVGProps<SVGSVGElement>, "viewBox">) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,14 @@
1
+ import { jsx as l } from "react/jsx-runtime";
2
+ import "react";
3
+ import { SvgIcon as r } from "./SvgIcon.js";
4
+ const t = (o) => /* @__PURE__ */ l(r, { viewBox: "0 0 20 20", fill: "currentColor", width: 20, height: 20, ...o, children: /* @__PURE__ */ l(
5
+ "path",
6
+ {
7
+ fillRule: "evenodd",
8
+ d: "M2.24 6.8a.75.75 0 0 0 1.06-.04l1.95-2.1v8.59a.75.75 0 0 0 1.5 0V4.66l1.95 2.1a.75.75 0 1 0 1.1-1.02l-3.25-3.5a.75.75 0 0 0-1.1 0L2.2 5.74a.75.75 0 0 0 .04 1.06Zm8 6.4a.75.75 0 0 0-.04 1.06l3.25 3.5a.75.75 0 0 0 1.1 0l3.25-3.5a.75.75 0 1 0-1.1-1.02l-1.95 2.1V6.75a.75.75 0 0 0-1.5 0v8.59l-1.95-2.1a.75.75 0 0 0-1.06-.04Z",
9
+ clipRule: "evenodd"
10
+ }
11
+ ) });
12
+ export {
13
+ t as IconArrowsUpDown
14
+ };
@@ -1,4 +1,5 @@
1
1
  export * from './IconArrowLeft';
2
+ export * from './IconArrowsUpDown';
2
3
  export * from './IconCheckCircle';
3
4
  export * from './IconEnvelope';
4
5
  export * from './IconExclamationCircle';
@@ -1,16 +1,18 @@
1
1
  import { IconArrowLeft as e } from "./IconArrowLeft.js";
2
- import { IconCheckCircle as n } from "./IconCheckCircle.js";
3
- import { IconEnvelope as f } from "./IconEnvelope.js";
4
- import { IconExclamationCircle as p } from "./IconExclamationCircle.js";
5
- import { IconLock as I } from "./IconLock.js";
6
- import { IconPhone as a } from "./IconPhone.js";
7
- import { IconXMark as k } from "./IconXMark.js";
2
+ import { IconArrowsUpDown as n } from "./IconArrowsUpDown.js";
3
+ import { IconCheckCircle as t } from "./IconCheckCircle.js";
4
+ import { IconEnvelope as m } from "./IconEnvelope.js";
5
+ import { IconExclamationCircle as I } from "./IconExclamationCircle.js";
6
+ import { IconLock as a } from "./IconLock.js";
7
+ import { IconPhone as k } from "./IconPhone.js";
8
+ import { IconXMark as C } from "./IconXMark.js";
8
9
  export {
9
10
  e as IconArrowLeft,
10
- n as IconCheckCircle,
11
- f as IconEnvelope,
12
- p as IconExclamationCircle,
13
- I as IconLock,
14
- a as IconPhone,
15
- k as IconXMark
11
+ n as IconArrowsUpDown,
12
+ t as IconCheckCircle,
13
+ m as IconEnvelope,
14
+ I as IconExclamationCircle,
15
+ a as IconLock,
16
+ k as IconPhone,
17
+ C as IconXMark
16
18
  };
package/dist/index.js CHANGED
@@ -2,70 +2,76 @@ import { AUTH_METHODS as e, CDPReactProvider as t, useAppConfig as n } from "./c
2
2
  import { AuthButton as p } from "./components/AuthButton/index.js";
3
3
  import { SendTransactionButton as x } from "./components/SendTransactionButton/index.js";
4
4
  import { SignIn as s } from "./components/SignIn/index.js";
5
- import { useSignInReducer as I } from "./components/SignIn/useSignInReducer.js";
6
- import { SignOutButton as g } from "./components/SignOutButton/index.js";
7
- import { SignInModal as S } from "./components/SignInModal/index.js";
5
+ import { useSignInReducer as a } from "./components/SignIn/useSignInReducer.js";
6
+ import { SignOutButton as l } from "./components/SignOutButton/index.js";
7
+ import { SignInModal as u } from "./components/SignInModal/index.js";
8
8
  import { ThemeProvider as h, useTheme as C } from "./components/ThemeProvider/index.js";
9
9
  import { cssVariables as d } from "./theme/cssVariables.js";
10
- import { theme as B } from "./theme/theme.js";
11
- import { colors as E, colorsBase as M, colorsComponents as v, colorsSemantic as P, font as b, tokens as D } from "./theme/tokens.js";
12
- import { flattenTokensObject as O, themeToCssVariables as w } from "./theme/utils.js";
13
- import { IconArrowLeft as L } from "./icons/IconArrowLeft.js";
14
- import { IconCheckCircle as U } from "./icons/IconCheckCircle.js";
15
- import { IconEnvelope as j } from "./icons/IconEnvelope.js";
16
- import { IconExclamationCircle as _ } from "./icons/IconExclamationCircle.js";
17
- import { IconLock as y } from "./icons/IconLock.js";
18
- import { IconPhone as G } from "./icons/IconPhone.js";
19
- import { IconXMark as K } from "./icons/IconXMark.js";
20
- import { getMessageFromUnknownError as Q } from "./utils/getMessageFromUnknownError.js";
21
- import { isApiError as Y } from "./utils/isApiError.js";
22
- import { isEmailInvalid as $ } from "./utils/isEmailInvalid.js";
23
- import { SignInAuthMethodButtons as ro } from "./components/SignIn/SignInAuthMethodButtons.js";
24
- import { SignInBackButton as to } from "./components/SignIn/SignInBackButton.js";
25
- import { SignInDescription as mo } from "./components/SignIn/SignInDescription.js";
26
- import { SignInFooter as fo } from "./components/SignIn/SignInFooter.js";
27
- import { SignInForm as io } from "./components/SignIn/SignInForm.js";
28
- import { SignInImage as co } from "./components/SignIn/SignInImage.js";
29
- import { SignInTitle as ao } from "./components/SignIn/SignInTitle.js";
30
- import { useSignInContext as lo } from "./components/SignIn/SignInProvider.js";
10
+ import { theme as A } from "./theme/theme.js";
11
+ import { colors as E, colorsBase as M, colorsComponents as P, colorsSemantic as b, font as v, tokens as w } from "./theme/tokens.js";
12
+ import { flattenTokensObject as F, themeToCssVariables as O } from "./theme/utils.js";
13
+ import { IconArrowLeft as V } from "./icons/IconArrowLeft.js";
14
+ import { IconArrowsUpDown as L } from "./icons/IconArrowsUpDown.js";
15
+ import { IconCheckCircle as j } from "./icons/IconCheckCircle.js";
16
+ import { IconEnvelope as X } from "./icons/IconEnvelope.js";
17
+ import { IconExclamationCircle as q } from "./icons/IconExclamationCircle.js";
18
+ import { IconLock as z } from "./icons/IconLock.js";
19
+ import { IconPhone as J } from "./icons/IconPhone.js";
20
+ import { IconXMark as Q } from "./icons/IconXMark.js";
21
+ import { clamp as Y } from "./utils/clamp.js";
22
+ import { getMessageFromUnknownError as $ } from "./utils/getMessageFromUnknownError.js";
23
+ import { isApiError as ro } from "./utils/isApiError.js";
24
+ import { isEmailInvalid as to } from "./utils/isEmailInvalid.js";
25
+ import { parseValuesFromPhoneNumber as mo } from "./utils/parseValuesFromPhoneNumber.js";
26
+ import { SignInAuthMethodButtons as fo } from "./components/SignIn/SignInAuthMethodButtons.js";
27
+ import { SignInBackButton as io } from "./components/SignIn/SignInBackButton.js";
28
+ import { SignInDescription as co } from "./components/SignIn/SignInDescription.js";
29
+ import { SignInFooter as Io } from "./components/SignIn/SignInFooter.js";
30
+ import { SignInForm as go } from "./components/SignIn/SignInForm.js";
31
+ import { SignInImage as So } from "./components/SignIn/SignInImage.js";
32
+ import { SignInTitle as Co } from "./components/SignIn/SignInTitle.js";
33
+ import { useSignInContext as ko } from "./components/SignIn/SignInProvider.js";
31
34
  export {
32
35
  e as AUTH_METHODS,
33
36
  p as AuthButton,
34
37
  t as CDPReactProvider,
35
- L as IconArrowLeft,
36
- U as IconCheckCircle,
37
- j as IconEnvelope,
38
- _ as IconExclamationCircle,
39
- y as IconLock,
40
- G as IconPhone,
41
- K as IconXMark,
38
+ V as IconArrowLeft,
39
+ L as IconArrowsUpDown,
40
+ j as IconCheckCircle,
41
+ X as IconEnvelope,
42
+ q as IconExclamationCircle,
43
+ z as IconLock,
44
+ J as IconPhone,
45
+ Q as IconXMark,
42
46
  x as SendTransactionButton,
43
47
  s as SignIn,
44
- ro as SignInAuthMethodButtons,
45
- to as SignInBackButton,
46
- mo as SignInDescription,
47
- fo as SignInFooter,
48
- io as SignInForm,
49
- co as SignInImage,
50
- S as SignInModal,
51
- ao as SignInTitle,
52
- g as SignOutButton,
48
+ fo as SignInAuthMethodButtons,
49
+ io as SignInBackButton,
50
+ co as SignInDescription,
51
+ Io as SignInFooter,
52
+ go as SignInForm,
53
+ So as SignInImage,
54
+ u as SignInModal,
55
+ Co as SignInTitle,
56
+ l as SignOutButton,
53
57
  h as ThemeProvider,
58
+ Y as clamp,
54
59
  E as colors,
55
60
  M as colorsBase,
56
- v as colorsComponents,
57
- P as colorsSemantic,
61
+ P as colorsComponents,
62
+ b as colorsSemantic,
58
63
  d as cssVariables,
59
- O as flattenTokensObject,
60
- b as font,
61
- Q as getMessageFromUnknownError,
62
- Y as isApiError,
63
- $ as isEmailInvalid,
64
- B as theme,
65
- w as themeToCssVariables,
66
- D as tokens,
64
+ F as flattenTokensObject,
65
+ v as font,
66
+ $ as getMessageFromUnknownError,
67
+ ro as isApiError,
68
+ to as isEmailInvalid,
69
+ mo as parseValuesFromPhoneNumber,
70
+ A as theme,
71
+ O as themeToCssVariables,
72
+ w as tokens,
67
73
  n as useAppConfig,
68
- lo as useSignInContext,
69
- I as useSignInReducer,
74
+ ko as useSignInContext,
75
+ a as useSignInReducer,
70
76
  C as useTheme
71
77
  };
@@ -0,0 +1 @@
1
+ export declare const clamp: (value: number, min: number, max: number) => number;
@@ -0,0 +1,4 @@
1
+ const n = (t, a, m) => Math.min(Math.max(t, a), m);
2
+ export {
3
+ n as clamp
4
+ };
@@ -1,3 +1,5 @@
1
+ export * from './clamp';
1
2
  export * from './getMessageFromUnknownError';
2
3
  export * from './isApiError';
3
4
  export * from './isEmailInvalid';
5
+ export * from './parseValuesFromPhoneNumber';
@@ -1,8 +1,12 @@
1
- import { getMessageFromUnknownError as e } from "./getMessageFromUnknownError.js";
2
- import { isApiError as m } from "./isApiError.js";
3
- import { isEmailInvalid as p } from "./isEmailInvalid.js";
1
+ import { clamp as e } from "./clamp.js";
2
+ import { getMessageFromUnknownError as p } from "./getMessageFromUnknownError.js";
3
+ import { isApiError as s } from "./isApiError.js";
4
+ import { isEmailInvalid as f } from "./isEmailInvalid.js";
5
+ import { parseValuesFromPhoneNumber as n } from "./parseValuesFromPhoneNumber.js";
4
6
  export {
5
- e as getMessageFromUnknownError,
6
- m as isApiError,
7
- p as isEmailInvalid
7
+ e as clamp,
8
+ p as getMessageFromUnknownError,
9
+ s as isApiError,
10
+ f as isEmailInvalid,
11
+ n as parseValuesFromPhoneNumber
8
12
  };
package/package.json CHANGED
@@ -1,18 +1,20 @@
1
1
  {
2
2
  "name": "@coinbase/cdp-react",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "dependencies": {
6
+ "@internationalized/number": "3.6.4",
6
7
  "@radix-ui/react-dialog": "^1.1.14",
7
8
  "@radix-ui/react-form": "^0.1.7",
8
9
  "@radix-ui/react-one-time-password-field": "^0.1.7",
9
- "react-transition-state": "2.3.0",
10
- "libphonenumber-js": "^1.12.10"
10
+ "big.js": "7.0.1",
11
+ "libphonenumber-js": "^1.12.10",
12
+ "react-transition-state": "2.3.0"
11
13
  },
12
14
  "peerDependencies": {
13
15
  "react": ">=18.2.0",
14
- "@coinbase/cdp-core": "^0.0.21",
15
- "@coinbase/cdp-hooks": "^0.0.21"
16
+ "@coinbase/cdp-core": "^0.0.22",
17
+ "@coinbase/cdp-hooks": "^0.0.22"
16
18
  },
17
19
  "devDependencies": {
18
20
  "@size-limit/preset-big-lib": "^11.2.0",
@@ -23,6 +25,7 @@
23
25
  "@testing-library/jest-dom": "^6.6.3",
24
26
  "@testing-library/react": "^16.3.0",
25
27
  "@testing-library/user-event": "^14.6.1",
28
+ "@types/big.js": "6.2.2",
26
29
  "@types/glob": "^9.0.0",
27
30
  "@types/react": "^19.1.0",
28
31
  "@types/react-dom": "^19.1.0",
@@ -41,8 +44,8 @@
41
44
  "vite": "^7.0.4",
42
45
  "vite-plugin-dts": "^4.5.4",
43
46
  "vite-plugin-lib-inject-css": "^2.2.2",
44
- "@coinbase/cdp-core": "^0.0.21",
45
- "@coinbase/cdp-hooks": "^0.0.21"
47
+ "@coinbase/cdp-core": "^0.0.22",
48
+ "@coinbase/cdp-hooks": "^0.0.22"
46
49
  },
47
50
  "size-limit": [
48
51
  {