@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 CHANGED
@@ -1,185 +1,203 @@
1
1
  import { jsx as k } from "react/jsx-runtime";
2
- import { createContext as W, useMemo as v, use as F } from "react";
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((n) => n.charAt(0).toUpperCase() + n.slice(1).toLowerCase()).join("") : "";
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 n = t.replace(/\D/g, "").length;
10
+ const e = t.replace(/\D/g, "").length;
11
11
  return Math.max(
12
12
  R,
13
- N - n * w
13
+ N - e * w
14
14
  );
15
15
  }
16
- function C(t, n = !0) {
16
+ function C(t, e = !0) {
17
17
  if (!t) return "";
18
- const i = t.includes("."), [l, o] = t.split("."), u = l.replace(/\B(?=(\d{3})+(?!\d))/g, " ");
19
- return i && n ? o ? `${u}.${o}` : `${u}.` : u;
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, n = {}) {
21
+ function H(t, e = {}) {
22
22
  const {
23
- allowDecimals: i = !0,
24
- thousandsSeparator: l = !0,
25
- maxIntegerLength: o = 9,
23
+ allowDecimals: o = !0,
24
+ thousandsSeparator: c = !0,
25
+ maxIntegerLength: r = 9,
26
26
  maxDecimalLength: u = 9
27
- } = n, r = t.replace(",", ".").replace(/[^\d.]/g, "");
28
- let e = r;
29
- if (e = e.replace(/^0+(?=\d)/, ""), !i)
30
- return e = e.replace(/\D/g, ""), o > 0 && e.length > o && (e = e.slice(0, o)), l ? C(e) : e;
31
- e === "." && (e = "0.");
32
- const a = e.indexOf(".");
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 c = e.slice(0, a), f = e.slice(a + 1).replace(/\./g, "");
35
- o > 0 && c.length > o && (c = c.slice(0, o)), f = f.slice(0, u), c === "" && (c = "0");
36
- const p = r.endsWith(".") || e.endsWith(".");
37
- e = f.length > 0 ? `${c}.${f}` : p ? `${c}.` : c;
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
- o > 0 && e.length > o && (e = e.slice(0, o));
40
- return l ? C(e) : e;
39
+ r > 0 && n.length > r && (n = n.slice(0, r));
40
+ return c ? C(n) : n;
41
41
  }
42
- function J(t, n) {
43
- const i = W(n), l = ({ children: u, value: r }) => {
44
- const e = v(
45
- () => r,
46
- Object.values(r ?? {})
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(i, { value: e, children: u });
48
+ return /* @__PURE__ */ k(o.Provider, { value: n, children: u });
49
49
  };
50
- l.displayName = t + "Provider";
51
- function o({
50
+ c.displayName = t + "Provider";
51
+ function r({
52
52
  consumerName: u,
53
- contextRequired: r
53
+ contextRequired: i
54
54
  }) {
55
- const e = F(i);
56
- if (e)
57
- return e;
58
- if (r)
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 n || {};
62
+ return e || {};
63
63
  }
64
- return [l, o];
64
+ return [c, r];
65
65
  }
66
66
  function K(...t) {
67
67
  return j(_(t));
68
68
  }
69
- const I = (t) => typeof t == "string" || typeof t == "number", Q = (t) => Array.isArray(t) ? t.every(I) : I(t);
70
- function S(t, n) {
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(n);
73
- typeof t == "object" && t !== null && "current" in t && (t.current = n);
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 n = /* @__PURE__ */ new Map();
77
- return (i) => {
78
- if (i === null) {
79
- t.forEach((l) => {
80
- const o = n.get(l);
81
- typeof o == "function" && o(), S(l, null);
82
- }), n.clear();
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((l) => {
86
- const o = S(l, i);
87
- typeof o == "function" && n.set(l, o);
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 v(() => z(...t), t);
92
+ return D(() => z(...t), t);
93
93
  }
94
- const tt = (t, n) => {
95
- let i = t;
96
- for (const l of n) {
97
- if (i == null)
94
+ const tt = (t, e) => {
95
+ let o = t;
96
+ for (const c of e) {
97
+ if (o == null)
98
98
  return;
99
- i = i[l];
99
+ o = o[c];
100
100
  }
101
- return i;
102
- }, nt = ({
101
+ return o;
102
+ }, et = ({
103
103
  currentStep: t,
104
- totalSteps: n,
105
- size: i,
106
- label: l,
107
- strokeWidth: o = 4,
104
+ totalSteps: e,
105
+ size: o,
106
+ label: c,
107
+ strokeWidth: r = 4,
108
108
  arcPercentage: u = 0.75
109
109
  }) => {
110
- const r = Math.min(Math.max(t, 0), n), e = l ?? `${r}/${n}`, a = n <= 0 ? 0 : r / n, c = (i - o) / 2, f = i / 2, p = i / 2, m = 2 * Math.PI * c, d = m * u, y = d * (1 - a), h = r <= 0, $ = `${d} ${m}`, D = h ? d - 2 : y;
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: e,
112
+ displayLabel: n,
113
113
  progress: a,
114
- r: c,
114
+ r: s,
115
115
  cx: f,
116
- cy: p,
116
+ cy: h,
117
117
  circumference: m,
118
- trackArcLength: d,
119
- trackDashArray: `${d} ${m}`,
120
- progressDashArray: $,
121
- progressDashOffset: D,
122
- showMinimalDot: h
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, n, i = {}) {
126
- const { leading: l = !1, trailing: o = !0, maxWait: u } = i;
127
- let r = null, e = null, a = null, c = 0, f = null, p = null, m;
128
- const d = u !== void 0, y = d ? Math.max(u, n) : 0, h = (s) => {
129
- c = s;
130
- const g = f, T = p;
131
- return f = null, p = null, m = t.apply(T, g), m;
132
- }, $ = (s) => {
133
- const g = a ? s - a : 0;
134
- return n - g;
135
- }, D = (s) => {
136
- const g = a ? s - a : n, T = s - c;
137
- return a === null || g >= n || g < 0 || d && T >= y;
138
- }, A = (s) => (r = null, o && f ? h(s) : (f = null, p = null, m)), x = () => {
139
- const s = Date.now();
140
- if (D(s)) {
141
- A(s);
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
- r = setTimeout(x, $(s));
145
- }, E = () => {
146
- const s = Date.now();
147
- e = null, f && (h(s), r !== null && (clearTimeout(r), r = setTimeout(x, n)));
148
- }, P = (s) => (c = s, r = setTimeout(x, n), d && (e = setTimeout(E, y)), l ? h(s) : m), b = () => {
149
- r !== null && clearTimeout(r), e !== null && clearTimeout(e), c = 0, f = null, p = null, a = null, r = null, e = null;
150
- }, L = () => r === null && e === null ? m : A(Date.now()), O = () => r !== null || e !== null, M = function(...s) {
151
- const g = Date.now(), T = D(g);
152
- if (f = s, p = this, a = g, T) {
153
- if (r === null)
154
- return P(g);
155
- if (d)
156
- return clearTimeout(r), r = setTimeout(x, n), h(g);
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 r === null && (r = setTimeout(x, n)), m;
174
+ return i === null && (i = setTimeout(x, e)), m;
159
175
  };
160
- return M.cancel = b, M.flush = L, M.pending = O, M;
176
+ return P.cancel = E, P.flush = L, P.pending = O, P;
161
177
  }
162
- function et(t, n, i = {}) {
163
- const { leading: l = !0, trailing: o = !0 } = i;
164
- return V(t, n, {
165
- leading: l,
166
- trailing: o,
167
- maxWait: n
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
- S as assignRef,
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
- nt as getStepperCalculations,
195
+ et as getStepperCalculations,
179
196
  Q as isTextChildren,
180
197
  z as mergeRefs,
181
198
  H as textFormatter,
182
- et as throttle,
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,3 @@
1
+ import { FormattedValue } from './types';
2
+ export declare const buildAriaLabel: (parts: FormattedValue, hidden: boolean, hiddenLabel: string) => string;
3
+ //# sourceMappingURL=buildAriaLabel.d.ts.map
@@ -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,4 @@
1
+ export { useSplitText } from './useSplitText';
2
+ export { buildAriaLabel } from './buildAriaLabel';
3
+ export type { FormattedValue, SplitChar } from './types';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -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,6 @@
1
+ import { FormattedValue, SplitChar } from './types';
2
+ export declare const useSplitText: (value: FormattedValue) => {
3
+ integerPart: SplitChar[];
4
+ decimalPart: SplitChar[];
5
+ };
6
+ //# sourceMappingURL=useSplitText.d.ts.map
@@ -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,2 +1,3 @@
1
1
  export * from './getStepperCalculations';
2
+ export * from './amountDisplayHelpers';
2
3
  //# sourceMappingURL=index.d.ts.map
@@ -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,EAAgB,MAAM,OAAO,CAAC;AAEnE,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"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ledgerhq/lumen-utils-shared",
3
- "version": "0.0.20",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -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,3 @@
1
+ export { useSplitText } from './useSplitText';
2
+ export { buildAriaLabel } from './buildAriaLabel';
3
+ export type { FormattedValue, SplitChar } from './types';
@@ -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 +1,2 @@
1
1
  export * from './getStepperCalculations';
2
+ export * from './amountDisplayHelpers';
@@ -1,4 +1,4 @@
1
- import { createContext, FC, ReactNode, use, useMemo } from 'react';
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 = use(Context);
31
+ const context = useContext(Context);
32
32
 
33
33
  if (context) {
34
34
  return context;