@ledgerhq/lumen-utils-shared 0.0.20 → 0.1.1
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 +133 -115
- package/dist/lib/components/amountDisplayHelpers/buildAriaLabel.d.ts +3 -0
- package/dist/lib/components/amountDisplayHelpers/buildAriaLabel.d.ts.map +1 -0
- package/dist/lib/components/amountDisplayHelpers/index.d.ts +4 -0
- package/dist/lib/components/amountDisplayHelpers/index.d.ts.map +1 -0
- package/dist/lib/components/amountDisplayHelpers/types.d.ts +30 -0
- package/dist/lib/components/amountDisplayHelpers/types.d.ts.map +1 -0
- package/dist/lib/components/amountDisplayHelpers/useSplitText.d.ts +6 -0
- package/dist/lib/components/amountDisplayHelpers/useSplitText.d.ts.map +1 -0
- package/dist/lib/components/index.d.ts +1 -0
- package/dist/lib/components/index.d.ts.map +1 -1
- package/dist/lib/createSafeContext/createSafeContext.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/lib/components/amountDisplayHelpers/buildAriaLabel.ts +20 -0
- package/src/lib/components/amountDisplayHelpers/index.ts +3 -0
- package/src/lib/components/amountDisplayHelpers/types.ts +30 -0
- package/src/lib/components/amountDisplayHelpers/useSplitText.test.ts +101 -0
- package/src/lib/components/amountDisplayHelpers/useSplitText.ts +25 -0
- package/src/lib/components/index.ts +1 -0
- package/src/lib/createSafeContext/createSafeContext.tsx +3 -3
package/dist/index.js
CHANGED
|
@@ -1,185 +1,203 @@
|
|
|
1
1
|
import { jsx as k } from "react/jsx-runtime";
|
|
2
|
-
import { createContext as W, useMemo as
|
|
2
|
+
import { createContext as W, useMemo as D, useContext as F } from "react";
|
|
3
3
|
import { clsx as _ } from "clsx";
|
|
4
4
|
import { twMerge as j } from "tailwind-merge";
|
|
5
5
|
function q(t) {
|
|
6
|
-
return t ? t.split(/[-_ ]+/).map((
|
|
6
|
+
return t ? t.split(/[-_ ]+/).map((e) => e.charAt(0).toUpperCase() + e.slice(1).toLowerCase()).join("") : "";
|
|
7
7
|
}
|
|
8
8
|
const N = 48, R = 17, w = 2;
|
|
9
9
|
function G(t) {
|
|
10
|
-
const
|
|
10
|
+
const e = t.replace(/\D/g, "").length;
|
|
11
11
|
return Math.max(
|
|
12
12
|
R,
|
|
13
|
-
N -
|
|
13
|
+
N - e * w
|
|
14
14
|
);
|
|
15
15
|
}
|
|
16
|
-
function C(t,
|
|
16
|
+
function C(t, e = !0) {
|
|
17
17
|
if (!t) return "";
|
|
18
|
-
const
|
|
19
|
-
return
|
|
18
|
+
const o = t.includes("."), [c, r] = t.split("."), u = c.replace(/\B(?=(\d{3})+(?!\d))/g, " ");
|
|
19
|
+
return o && e ? r ? `${u}.${r}` : `${u}.` : u;
|
|
20
20
|
}
|
|
21
|
-
function H(t,
|
|
21
|
+
function H(t, e = {}) {
|
|
22
22
|
const {
|
|
23
|
-
allowDecimals:
|
|
24
|
-
thousandsSeparator:
|
|
25
|
-
maxIntegerLength:
|
|
23
|
+
allowDecimals: o = !0,
|
|
24
|
+
thousandsSeparator: c = !0,
|
|
25
|
+
maxIntegerLength: r = 9,
|
|
26
26
|
maxDecimalLength: u = 9
|
|
27
|
-
} =
|
|
28
|
-
let
|
|
29
|
-
if (
|
|
30
|
-
return
|
|
31
|
-
|
|
32
|
-
const a =
|
|
27
|
+
} = e, i = t.replace(",", ".").replace(/[^\d.]/g, "");
|
|
28
|
+
let n = i;
|
|
29
|
+
if (n = n.replace(/^0+(?=\d)/, ""), !o)
|
|
30
|
+
return n = n.replace(/\D/g, ""), r > 0 && n.length > r && (n = n.slice(0, r)), c ? C(n) : n;
|
|
31
|
+
n === "." && (n = "0.");
|
|
32
|
+
const a = n.indexOf(".");
|
|
33
33
|
if (a !== -1) {
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
|
|
34
|
+
let s = n.slice(0, a), f = n.slice(a + 1).replace(/\./g, "");
|
|
35
|
+
r > 0 && s.length > r && (s = s.slice(0, r)), f = f.slice(0, u), s === "" && (s = "0");
|
|
36
|
+
const h = i.endsWith(".") || n.endsWith(".");
|
|
37
|
+
n = f.length > 0 ? `${s}.${f}` : h ? `${s}.` : s;
|
|
38
38
|
} else
|
|
39
|
-
|
|
40
|
-
return
|
|
39
|
+
r > 0 && n.length > r && (n = n.slice(0, r));
|
|
40
|
+
return c ? C(n) : n;
|
|
41
41
|
}
|
|
42
|
-
function J(t,
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
() =>
|
|
46
|
-
Object.values(
|
|
42
|
+
function J(t, e) {
|
|
43
|
+
const o = W(e), c = ({ children: u, value: i }) => {
|
|
44
|
+
const n = D(
|
|
45
|
+
() => i,
|
|
46
|
+
Object.values(i ?? {})
|
|
47
47
|
);
|
|
48
|
-
return /* @__PURE__ */ k(
|
|
48
|
+
return /* @__PURE__ */ k(o.Provider, { value: n, children: u });
|
|
49
49
|
};
|
|
50
|
-
|
|
51
|
-
function
|
|
50
|
+
c.displayName = t + "Provider";
|
|
51
|
+
function r({
|
|
52
52
|
consumerName: u,
|
|
53
|
-
contextRequired:
|
|
53
|
+
contextRequired: i
|
|
54
54
|
}) {
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
return
|
|
58
|
-
if (
|
|
55
|
+
const n = F(o);
|
|
56
|
+
if (n)
|
|
57
|
+
return n;
|
|
58
|
+
if (i)
|
|
59
59
|
throw new Error(
|
|
60
60
|
`${u} must be used within ${t}`
|
|
61
61
|
);
|
|
62
|
-
return
|
|
62
|
+
return e || {};
|
|
63
63
|
}
|
|
64
|
-
return [
|
|
64
|
+
return [c, r];
|
|
65
65
|
}
|
|
66
66
|
function K(...t) {
|
|
67
67
|
return j(_(t));
|
|
68
68
|
}
|
|
69
|
-
const
|
|
70
|
-
function
|
|
69
|
+
const S = (t) => typeof t == "string" || typeof t == "number", Q = (t) => Array.isArray(t) ? t.every(S) : S(t);
|
|
70
|
+
function I(t, e) {
|
|
71
71
|
if (typeof t == "function")
|
|
72
|
-
return t(
|
|
73
|
-
typeof t == "object" && t !== null && "current" in t && (t.current =
|
|
72
|
+
return t(e);
|
|
73
|
+
typeof t == "object" && t !== null && "current" in t && (t.current = e);
|
|
74
74
|
}
|
|
75
75
|
function z(...t) {
|
|
76
|
-
const
|
|
77
|
-
return (
|
|
78
|
-
if (
|
|
79
|
-
t.forEach((
|
|
80
|
-
const
|
|
81
|
-
typeof
|
|
82
|
-
}),
|
|
76
|
+
const e = /* @__PURE__ */ new Map();
|
|
77
|
+
return (o) => {
|
|
78
|
+
if (o === null) {
|
|
79
|
+
t.forEach((c) => {
|
|
80
|
+
const r = e.get(c);
|
|
81
|
+
typeof r == "function" && r(), I(c, null);
|
|
82
|
+
}), e.clear();
|
|
83
83
|
return;
|
|
84
84
|
}
|
|
85
|
-
t.forEach((
|
|
86
|
-
const
|
|
87
|
-
typeof
|
|
85
|
+
t.forEach((c) => {
|
|
86
|
+
const r = I(c, o);
|
|
87
|
+
typeof r == "function" && e.set(c, r);
|
|
88
88
|
});
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
function Y(...t) {
|
|
92
|
-
return
|
|
92
|
+
return D(() => z(...t), t);
|
|
93
93
|
}
|
|
94
|
-
const tt = (t,
|
|
95
|
-
let
|
|
96
|
-
for (const
|
|
97
|
-
if (
|
|
94
|
+
const tt = (t, e) => {
|
|
95
|
+
let o = t;
|
|
96
|
+
for (const c of e) {
|
|
97
|
+
if (o == null)
|
|
98
98
|
return;
|
|
99
|
-
|
|
99
|
+
o = o[c];
|
|
100
100
|
}
|
|
101
|
-
return
|
|
102
|
-
},
|
|
101
|
+
return o;
|
|
102
|
+
}, et = ({
|
|
103
103
|
currentStep: t,
|
|
104
|
-
totalSteps:
|
|
105
|
-
size:
|
|
106
|
-
label:
|
|
107
|
-
strokeWidth:
|
|
104
|
+
totalSteps: e,
|
|
105
|
+
size: o,
|
|
106
|
+
label: c,
|
|
107
|
+
strokeWidth: r = 4,
|
|
108
108
|
arcPercentage: u = 0.75
|
|
109
109
|
}) => {
|
|
110
|
-
const
|
|
110
|
+
const i = Math.min(Math.max(t, 0), e), n = c ?? `${i}/${e}`, a = e <= 0 ? 0 : i / e, s = (o - r) / 2, f = o / 2, h = o / 2, m = 2 * Math.PI * s, g = m * u, T = g * (1 - a), p = i <= 0, A = `${g} ${m}`, $ = p ? g - 2 : T;
|
|
111
111
|
return {
|
|
112
|
-
displayLabel:
|
|
112
|
+
displayLabel: n,
|
|
113
113
|
progress: a,
|
|
114
|
-
r:
|
|
114
|
+
r: s,
|
|
115
115
|
cx: f,
|
|
116
|
-
cy:
|
|
116
|
+
cy: h,
|
|
117
117
|
circumference: m,
|
|
118
|
-
trackArcLength:
|
|
119
|
-
trackDashArray: `${
|
|
120
|
-
progressDashArray:
|
|
121
|
-
progressDashOffset:
|
|
122
|
-
showMinimalDot:
|
|
118
|
+
trackArcLength: g,
|
|
119
|
+
trackDashArray: `${g} ${m}`,
|
|
120
|
+
progressDashArray: A,
|
|
121
|
+
progressDashOffset: $,
|
|
122
|
+
showMinimalDot: p
|
|
123
123
|
};
|
|
124
|
+
}, nt = (t) => D(
|
|
125
|
+
() => ({
|
|
126
|
+
integerPart: Array.from(t.integerPart, (e) => ({
|
|
127
|
+
value: e,
|
|
128
|
+
type: e.match(/^\d$/) ? "digit" : "separator"
|
|
129
|
+
})),
|
|
130
|
+
decimalPart: t.decimalPart ? Array.from(t.decimalPart, (e) => ({
|
|
131
|
+
value: e,
|
|
132
|
+
type: "digit"
|
|
133
|
+
})) : []
|
|
134
|
+
}),
|
|
135
|
+
[t.integerPart, t.decimalPart]
|
|
136
|
+
), rt = (t, e, o) => {
|
|
137
|
+
if (e) return o;
|
|
138
|
+
const c = t.decimalPart ? `${t.decimalSeparator}${t.decimalPart}` : "", r = `${t.integerPart}${c}`;
|
|
139
|
+
return t.currencyPosition === "end" ? `${r} ${t.currencyText}` : `${t.currencyText} ${r}`;
|
|
124
140
|
};
|
|
125
|
-
function V(t,
|
|
126
|
-
const { leading:
|
|
127
|
-
let
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
return f = null,
|
|
132
|
-
},
|
|
133
|
-
const
|
|
134
|
-
return
|
|
135
|
-
},
|
|
136
|
-
const
|
|
137
|
-
return a === null ||
|
|
138
|
-
},
|
|
139
|
-
const
|
|
140
|
-
if (
|
|
141
|
-
|
|
141
|
+
function V(t, e, o = {}) {
|
|
142
|
+
const { leading: c = !1, trailing: r = !0, maxWait: u } = o;
|
|
143
|
+
let i = null, n = null, a = null, s = 0, f = null, h = null, m;
|
|
144
|
+
const g = u !== void 0, T = g ? Math.max(u, e) : 0, p = (l) => {
|
|
145
|
+
s = l;
|
|
146
|
+
const d = f, y = h;
|
|
147
|
+
return f = null, h = null, m = t.apply(y, d), m;
|
|
148
|
+
}, A = (l) => {
|
|
149
|
+
const d = a ? l - a : 0;
|
|
150
|
+
return e - d;
|
|
151
|
+
}, $ = (l) => {
|
|
152
|
+
const d = a ? l - a : e, y = l - s;
|
|
153
|
+
return a === null || d >= e || d < 0 || g && y >= T;
|
|
154
|
+
}, M = (l) => (i = null, r && f ? p(l) : (f = null, h = null, m)), x = () => {
|
|
155
|
+
const l = Date.now();
|
|
156
|
+
if ($(l)) {
|
|
157
|
+
M(l);
|
|
142
158
|
return;
|
|
143
159
|
}
|
|
144
|
-
|
|
145
|
-
},
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
},
|
|
149
|
-
|
|
150
|
-
}, L = () =>
|
|
151
|
-
const
|
|
152
|
-
if (f =
|
|
153
|
-
if (
|
|
154
|
-
return
|
|
155
|
-
if (
|
|
156
|
-
return clearTimeout(
|
|
160
|
+
i = setTimeout(x, A(l));
|
|
161
|
+
}, b = () => {
|
|
162
|
+
const l = Date.now();
|
|
163
|
+
n = null, f && (p(l), i !== null && (clearTimeout(i), i = setTimeout(x, e)));
|
|
164
|
+
}, v = (l) => (s = l, i = setTimeout(x, e), g && (n = setTimeout(b, T)), c ? p(l) : m), E = () => {
|
|
165
|
+
i !== null && clearTimeout(i), n !== null && clearTimeout(n), s = 0, f = null, h = null, a = null, i = null, n = null;
|
|
166
|
+
}, L = () => i === null && n === null ? m : M(Date.now()), O = () => i !== null || n !== null, P = function(...l) {
|
|
167
|
+
const d = Date.now(), y = $(d);
|
|
168
|
+
if (f = l, h = this, a = d, y) {
|
|
169
|
+
if (i === null)
|
|
170
|
+
return v(d);
|
|
171
|
+
if (g)
|
|
172
|
+
return clearTimeout(i), i = setTimeout(x, e), p(d);
|
|
157
173
|
}
|
|
158
|
-
return
|
|
174
|
+
return i === null && (i = setTimeout(x, e)), m;
|
|
159
175
|
};
|
|
160
|
-
return
|
|
176
|
+
return P.cancel = E, P.flush = L, P.pending = O, P;
|
|
161
177
|
}
|
|
162
|
-
function
|
|
163
|
-
const { leading:
|
|
164
|
-
return V(t,
|
|
165
|
-
leading:
|
|
166
|
-
trailing:
|
|
167
|
-
maxWait:
|
|
178
|
+
function it(t, e, o = {}) {
|
|
179
|
+
const { leading: c = !0, trailing: r = !0 } = o;
|
|
180
|
+
return V(t, e, {
|
|
181
|
+
leading: c,
|
|
182
|
+
trailing: r,
|
|
183
|
+
maxWait: e
|
|
168
184
|
});
|
|
169
185
|
}
|
|
170
186
|
export {
|
|
171
|
-
|
|
187
|
+
I as assignRef,
|
|
188
|
+
rt as buildAriaLabel,
|
|
172
189
|
K as cn,
|
|
173
190
|
J as createSafeContext,
|
|
174
191
|
V as debounce,
|
|
175
192
|
C as formatThousands,
|
|
176
193
|
G as getFontSize,
|
|
177
194
|
tt as getObjectPath,
|
|
178
|
-
|
|
195
|
+
et as getStepperCalculations,
|
|
179
196
|
Q as isTextChildren,
|
|
180
197
|
z as mergeRefs,
|
|
181
198
|
H as textFormatter,
|
|
182
|
-
|
|
199
|
+
it as throttle,
|
|
183
200
|
q as toPascalCase,
|
|
184
|
-
Y as useMergedRef
|
|
201
|
+
Y as useMergedRef,
|
|
202
|
+
nt as useSplitText
|
|
185
203
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildAriaLabel.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/amountDisplayHelpers/buildAriaLabel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,eAAO,MAAM,cAAc,UAClB,cAAc,UACb,OAAO,eACF,MAAM,KAClB,MAaF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/amountDisplayHelpers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type SplitChar = {
|
|
2
|
+
value: string;
|
|
3
|
+
type: 'digit' | 'separator';
|
|
4
|
+
};
|
|
5
|
+
export type FormattedValue = {
|
|
6
|
+
/**
|
|
7
|
+
* The whole number portion of the amount (e.g., "1234" from 1234.56)
|
|
8
|
+
*/
|
|
9
|
+
integerPart: string;
|
|
10
|
+
/**
|
|
11
|
+
* The fractional portion of the amount without the separator (e.g., "56" from 1234.56)
|
|
12
|
+
* @optional
|
|
13
|
+
*/
|
|
14
|
+
decimalPart?: string;
|
|
15
|
+
/**
|
|
16
|
+
* The currency text or symbol (e.g., "$", "USD", "€", "BTC")
|
|
17
|
+
*/
|
|
18
|
+
currencyText: string;
|
|
19
|
+
/**
|
|
20
|
+
* The character which separates integer and fractional parts.
|
|
21
|
+
*/
|
|
22
|
+
decimalSeparator: '.' | ',';
|
|
23
|
+
/**
|
|
24
|
+
* Position of the currency text relative to the amount.
|
|
25
|
+
* @optional
|
|
26
|
+
* @default 'start'
|
|
27
|
+
*/
|
|
28
|
+
currencyPosition?: 'start' | 'end';
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/amountDisplayHelpers/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,WAAW,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,gBAAgB,EAAE,GAAG,GAAG,GAAG,CAAC;IAC5B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;CACpC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSplitText.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/amountDisplayHelpers/useSplitText.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEpD,eAAO,MAAM,YAAY,UAChB,cAAc,KACpB;IACD,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,WAAW,EAAE,SAAS,EAAE,CAAC;CAiB1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createSafeContext.d.ts","sourceRoot":"","sources":["../../../src/lib/createSafeContext/createSafeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,EAAE,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"createSafeContext.d.ts","sourceRoot":"","sources":["../../../src/lib/createSafeContext/createSafeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,EAAE,EAAE,SAAS,EAAuB,MAAM,OAAO,CAAC;AAE1E,wBAAgB,iBAAiB,CAAC,YAAY,SAAS,MAAM,EAC3D,iBAAiB,EAAE,MAAM,EACzB,cAAc,CAAC,EAAE,YAAY;cAKjB,SAAS;WACZ,YAAY;KAaG,eAAe,SAAS,OAAO,gDAGpD;IACD,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;CAClC,KAAG,eAAe,SAAS,IAAI,GAAG,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,EAgBxE"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { FormattedValue } from './types';
|
|
2
|
+
|
|
3
|
+
export const buildAriaLabel = (
|
|
4
|
+
parts: FormattedValue,
|
|
5
|
+
hidden: boolean,
|
|
6
|
+
hiddenLabel: string,
|
|
7
|
+
): string => {
|
|
8
|
+
if (hidden) return hiddenLabel;
|
|
9
|
+
|
|
10
|
+
const decimal = parts.decimalPart
|
|
11
|
+
? `${parts.decimalSeparator}${parts.decimalPart}`
|
|
12
|
+
: '';
|
|
13
|
+
const amount = `${parts.integerPart}${decimal}`;
|
|
14
|
+
|
|
15
|
+
if (parts.currencyPosition === 'end') {
|
|
16
|
+
return `${amount} ${parts.currencyText}`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return `${parts.currencyText} ${amount}`;
|
|
20
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export type SplitChar = {
|
|
2
|
+
value: string;
|
|
3
|
+
type: 'digit' | 'separator';
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type FormattedValue = {
|
|
7
|
+
/**
|
|
8
|
+
* The whole number portion of the amount (e.g., "1234" from 1234.56)
|
|
9
|
+
*/
|
|
10
|
+
integerPart: string;
|
|
11
|
+
/**
|
|
12
|
+
* The fractional portion of the amount without the separator (e.g., "56" from 1234.56)
|
|
13
|
+
* @optional
|
|
14
|
+
*/
|
|
15
|
+
decimalPart?: string;
|
|
16
|
+
/**
|
|
17
|
+
* The currency text or symbol (e.g., "$", "USD", "€", "BTC")
|
|
18
|
+
*/
|
|
19
|
+
currencyText: string;
|
|
20
|
+
/**
|
|
21
|
+
* The character which separates integer and fractional parts.
|
|
22
|
+
*/
|
|
23
|
+
decimalSeparator: '.' | ',';
|
|
24
|
+
/**
|
|
25
|
+
* Position of the currency text relative to the amount.
|
|
26
|
+
* @optional
|
|
27
|
+
* @default 'start'
|
|
28
|
+
*/
|
|
29
|
+
currencyPosition?: 'start' | 'end';
|
|
30
|
+
};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { renderHook } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { FormattedValue } from './types';
|
|
5
|
+
import { useSplitText } from './useSplitText';
|
|
6
|
+
|
|
7
|
+
const createValue = (
|
|
8
|
+
overrides: Partial<FormattedValue> = {},
|
|
9
|
+
): FormattedValue => ({
|
|
10
|
+
integerPart: '1234',
|
|
11
|
+
decimalPart: '56',
|
|
12
|
+
currencyText: 'USD',
|
|
13
|
+
decimalSeparator: '.',
|
|
14
|
+
currencyPosition: 'start',
|
|
15
|
+
...overrides,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
describe('useSplitText', () => {
|
|
19
|
+
it('splits integer part into individual digit characters', () => {
|
|
20
|
+
const { result } = renderHook(() => useSplitText(createValue()));
|
|
21
|
+
|
|
22
|
+
expect(result.current.integerPart).toEqual([
|
|
23
|
+
{ value: '1', type: 'digit' },
|
|
24
|
+
{ value: '2', type: 'digit' },
|
|
25
|
+
{ value: '3', type: 'digit' },
|
|
26
|
+
{ value: '4', type: 'digit' },
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('splits decimal part into individual digit characters', () => {
|
|
31
|
+
const { result } = renderHook(() => useSplitText(createValue()));
|
|
32
|
+
|
|
33
|
+
expect(result.current.decimalPart).toEqual([
|
|
34
|
+
{ value: '5', type: 'digit' },
|
|
35
|
+
{ value: '6', type: 'digit' },
|
|
36
|
+
]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('returns empty decimal part when decimalPart is undefined', () => {
|
|
40
|
+
const { result } = renderHook(() =>
|
|
41
|
+
useSplitText(createValue({ decimalPart: undefined })),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(result.current.decimalPart).toEqual([]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('classifies group separators in integer part', () => {
|
|
48
|
+
const { result } = renderHook(() =>
|
|
49
|
+
useSplitText(createValue({ integerPart: '1,234,567' })),
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
expect(result.current.integerPart).toEqual([
|
|
53
|
+
{ value: '1', type: 'digit' },
|
|
54
|
+
{ value: ',', type: 'separator' },
|
|
55
|
+
{ value: '2', type: 'digit' },
|
|
56
|
+
{ value: '3', type: 'digit' },
|
|
57
|
+
{ value: '4', type: 'digit' },
|
|
58
|
+
{ value: ',', type: 'separator' },
|
|
59
|
+
{ value: '5', type: 'digit' },
|
|
60
|
+
{ value: '6', type: 'digit' },
|
|
61
|
+
{ value: '7', type: 'digit' },
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('classifies space separators in integer part', () => {
|
|
66
|
+
const { result } = renderHook(() =>
|
|
67
|
+
useSplitText(createValue({ integerPart: '1 234 567' })),
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
expect(result.current.integerPart).toEqual([
|
|
71
|
+
{ value: '1', type: 'digit' },
|
|
72
|
+
{ value: ' ', type: 'separator' },
|
|
73
|
+
{ value: '2', type: 'digit' },
|
|
74
|
+
{ value: '3', type: 'digit' },
|
|
75
|
+
{ value: '4', type: 'digit' },
|
|
76
|
+
{ value: ' ', type: 'separator' },
|
|
77
|
+
{ value: '5', type: 'digit' },
|
|
78
|
+
{ value: '6', type: 'digit' },
|
|
79
|
+
{ value: '7', type: 'digit' },
|
|
80
|
+
]);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('handles single digit integer part', () => {
|
|
84
|
+
const { result } = renderHook(() =>
|
|
85
|
+
useSplitText(createValue({ integerPart: '0' })),
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
expect(result.current.integerPart).toEqual([{ value: '0', type: 'digit' }]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('handles long decimal part', () => {
|
|
92
|
+
const { result } = renderHook(() =>
|
|
93
|
+
useSplitText(createValue({ decimalPart: '00123456' })),
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
expect(result.current.decimalPart).toHaveLength(8);
|
|
97
|
+
expect(result.current.decimalPart.every((c) => c.type === 'digit')).toBe(
|
|
98
|
+
true,
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { FormattedValue, SplitChar } from './types';
|
|
3
|
+
|
|
4
|
+
export const useSplitText = (
|
|
5
|
+
value: FormattedValue,
|
|
6
|
+
): {
|
|
7
|
+
integerPart: SplitChar[];
|
|
8
|
+
decimalPart: SplitChar[];
|
|
9
|
+
} => {
|
|
10
|
+
return useMemo(
|
|
11
|
+
() => ({
|
|
12
|
+
integerPart: Array.from(value.integerPart, (digit) => ({
|
|
13
|
+
value: digit,
|
|
14
|
+
type: digit.match(/^\d$/) ? 'digit' : 'separator',
|
|
15
|
+
})),
|
|
16
|
+
decimalPart: value.decimalPart
|
|
17
|
+
? Array.from(value.decimalPart, (digit) => ({
|
|
18
|
+
value: digit,
|
|
19
|
+
type: 'digit',
|
|
20
|
+
}))
|
|
21
|
+
: [],
|
|
22
|
+
}),
|
|
23
|
+
[value.integerPart, value.decimalPart],
|
|
24
|
+
);
|
|
25
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, FC, ReactNode,
|
|
1
|
+
import { createContext, FC, ReactNode, useContext, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
export function createSafeContext<ContextValue extends object>(
|
|
4
4
|
rootComponentName: string,
|
|
@@ -16,7 +16,7 @@ export function createSafeContext<ContextValue extends object>(
|
|
|
16
16
|
Object.values(context ?? {}),
|
|
17
17
|
) as ContextValue;
|
|
18
18
|
|
|
19
|
-
return <Context value={memoValue}>{children}</Context>;
|
|
19
|
+
return <Context.Provider value={memoValue}>{children}</Context.Provider>;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
Provider.displayName = rootComponentName + 'Provider';
|
|
@@ -28,7 +28,7 @@ export function createSafeContext<ContextValue extends object>(
|
|
|
28
28
|
consumerName: string;
|
|
29
29
|
contextRequired: ContextRequired;
|
|
30
30
|
}): ContextRequired extends true ? ContextValue : Partial<ContextValue> {
|
|
31
|
-
const context =
|
|
31
|
+
const context = useContext(Context);
|
|
32
32
|
|
|
33
33
|
if (context) {
|
|
34
34
|
return context;
|