@ptx-showcase/utils 0.4.0 → 0.6.0
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/README.md +78 -0
- package/dist/chunks/currency-symbol-CBowgXv-.es +26 -0
- package/dist/chunks/currency-symbol-gb63Q_9Q.cjs +1 -0
- package/dist/chunks/truncate-decimals-BFMoEzul.es +7 -0
- package/dist/chunks/truncate-decimals-CArL-IeO.cjs +1 -0
- package/dist/currency-symbol/constants/currency-symbol.constant.d.ts +6 -0
- package/dist/currency-symbol/index.cjs +1 -0
- package/dist/currency-symbol/index.d.ts +23 -0
- package/dist/currency-symbol/index.js +2 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +6 -4
- package/dist/truncate-decimals/constants/truncate-decimals.constant.d.ts +1 -0
- package/dist/truncate-decimals/index.cjs +1 -0
- package/dist/truncate-decimals/index.d.ts +32 -0
- package/dist/truncate-decimals/index.js +2 -0
- package/package.json +18 -8
package/README.md
CHANGED
|
@@ -126,6 +126,30 @@ await downloadBlob(blob, { hash: 12345 })
|
|
|
126
126
|
|
|
127
127
|
---
|
|
128
128
|
|
|
129
|
+
### getCurrencySymbol
|
|
130
|
+
|
|
131
|
+
Resolves the symbol for an ISO 4217 currency code via `Intl`. A handful of currencies (`AUD`, `CAD`, `NZD`, `CHF`, etc.) are overridden where the `Intl` narrow symbol would be ambiguous.
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// from root
|
|
135
|
+
import { getCurrencySymbol } from '@ptx-showcase/utils'
|
|
136
|
+
|
|
137
|
+
// from subpath
|
|
138
|
+
import { getCurrencySymbol } from '@ptx-showcase/utils/currency-symbol'
|
|
139
|
+
|
|
140
|
+
getCurrencySymbol('EUR') // → '€'
|
|
141
|
+
getCurrencySymbol('USD') // → '$'
|
|
142
|
+
getCurrencySymbol('AUD') // → 'A$' (override)
|
|
143
|
+
getCurrencySymbol('CHF') // → '₣' (override)
|
|
144
|
+
getCurrencySymbol('ZZZ') // → 'ZZZ' (well-formed but unknown code)
|
|
145
|
+
getCurrencySymbol('EURO') // → 'N/A' (not a 3-letter code)
|
|
146
|
+
|
|
147
|
+
// custom locale
|
|
148
|
+
getCurrencySymbol('EUR', 'de-DE') // → '€'
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
129
153
|
### handleApiError
|
|
130
154
|
|
|
131
155
|
Parses backend error responses (including `ky`'s `HTTPError`) and reports human-readable messages through whatever notification system your project uses (`vue-sonner`, `react-hot-toast`, `console.error`, etc).
|
|
@@ -159,6 +183,57 @@ try {
|
|
|
159
183
|
|
|
160
184
|
---
|
|
161
185
|
|
|
186
|
+
### normalizeDecimalInput / normalizePhoneNumberInput
|
|
187
|
+
|
|
188
|
+
In-place `input`/`change` event handlers that sanitize a text input's value as the user types.
|
|
189
|
+
|
|
190
|
+
- `normalizeDecimalInput` — keeps only digits and a single dot, converts a comma to a dot, prefixes a leading dot with `0`, and truncates the decimal part to `decimals` digits (default `2`).
|
|
191
|
+
- `normalizePhoneNumberInput` — keeps only digits, truncates to `maxDigits` (default `15`, the E.164 limit), and prefixes the result with `+`.
|
|
192
|
+
|
|
193
|
+
```ts
|
|
194
|
+
// from root
|
|
195
|
+
import { normalizeDecimalInput, normalizePhoneNumberInput } from '@ptx-showcase/utils'
|
|
196
|
+
|
|
197
|
+
// from subpath
|
|
198
|
+
import { normalizeDecimalInput, normalizePhoneNumberInput } from '@ptx-showcase/utils/normalize-input'
|
|
199
|
+
|
|
200
|
+
// Vue
|
|
201
|
+
<input type="text" inputmode="decimal" @input="normalizeDecimalInput" />
|
|
202
|
+
<input type="text" inputmode="tel" @input="normalizePhoneNumberInput" />
|
|
203
|
+
|
|
204
|
+
// React (wrap to access the native event)
|
|
205
|
+
<input type="text" inputMode="decimal" onChange={(e) => normalizeDecimalInput(e.nativeEvent, 4)} />
|
|
206
|
+
<input type="text" inputMode="tel" onChange={(e) => normalizePhoneNumberInput(e.nativeEvent, 11)} />
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
### truncateDecimals
|
|
212
|
+
|
|
213
|
+
Formats a number (or numeric string) to a fixed number of decimal places by cutting the extra digits off, **without rounding**. Accepts a string too, so values more precise than a JS `number` can hold (e.g. amounts from an API) can be truncated without a lossy float conversion first. Returns `'N/A'` for anything that isn't a finite number or a well-formed numeric string.
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
// from root
|
|
217
|
+
import { truncateDecimals } from '@ptx-showcase/utils'
|
|
218
|
+
|
|
219
|
+
// from subpath
|
|
220
|
+
import { truncateDecimals } from '@ptx-showcase/utils/truncate-decimals'
|
|
221
|
+
|
|
222
|
+
truncateDecimals(4.21312312) // → '4.21'
|
|
223
|
+
truncateDecimals(4.995) // → '4.99' (not rounded to 5.00)
|
|
224
|
+
truncateDecimals(4.2) // → '4.2' (fewer decimals than requested — left untouched)
|
|
225
|
+
truncateDecimals(4.219, 0) // → '4'
|
|
226
|
+
|
|
227
|
+
// numeric string input — no float precision loss
|
|
228
|
+
truncateDecimals('4.219999999999999999999999', 2) // → '4.21'
|
|
229
|
+
|
|
230
|
+
// invalid input
|
|
231
|
+
truncateDecimals('not a number') // → 'N/A'
|
|
232
|
+
truncateDecimals(undefined) // → 'N/A'
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
162
237
|
## Available modules
|
|
163
238
|
|
|
164
239
|
| Subpath | Exports |
|
|
@@ -167,8 +242,11 @@ try {
|
|
|
167
242
|
| `@ptx-showcase/utils/build-query-params` | `buildQueryParams` |
|
|
168
243
|
| `@ptx-showcase/utils/build-sort-param` | `buildSortParam` |
|
|
169
244
|
| `@ptx-showcase/utils/cookies` | `setCookie`, `getCookie`, `deleteCookie`, `defaultCookieOptions` |
|
|
245
|
+
| `@ptx-showcase/utils/currency-symbol` | `getCurrencySymbol` |
|
|
170
246
|
| `@ptx-showcase/utils/download-file` | `downloadBlob` |
|
|
171
247
|
| `@ptx-showcase/utils/handle-api-error` | `handleApiError`, `initHandleApiError` |
|
|
248
|
+
| `@ptx-showcase/utils/normalize-input` | `normalizeDecimalInput`, `normalizePhoneNumberInput` |
|
|
249
|
+
| `@ptx-showcase/utils/truncate-decimals` | `truncateDecimals` |
|
|
172
250
|
| `@ptx-showcase/utils/types` | `TableColumnConfig`, `PaginatedList` |
|
|
173
251
|
|
|
174
252
|
---
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/currency-symbol/constants/currency-symbol.constant.ts
|
|
2
|
+
var e = {
|
|
3
|
+
CHF: "₣",
|
|
4
|
+
AUD: "A$",
|
|
5
|
+
CAD: "CA$",
|
|
6
|
+
NZD: "NZ$",
|
|
7
|
+
HKD: "HK$",
|
|
8
|
+
MXN: "MX$",
|
|
9
|
+
SGD: "S$"
|
|
10
|
+
}, t = (t, n = "en-US") => {
|
|
11
|
+
if (typeof t != "string" || t == null || t === "" || t === " " || t.length !== 3) return "N/A";
|
|
12
|
+
let r = e[t.toUpperCase()];
|
|
13
|
+
if (r !== void 0) return r;
|
|
14
|
+
try {
|
|
15
|
+
let e = new Intl.NumberFormat(n, {
|
|
16
|
+
style: "currency",
|
|
17
|
+
currency: t,
|
|
18
|
+
currencyDisplay: "narrowSymbol"
|
|
19
|
+
}).formatToParts(0).find((e) => e.type === "currency");
|
|
20
|
+
return e === void 0 ? t : e.value;
|
|
21
|
+
} catch {
|
|
22
|
+
return t;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
//#endregion
|
|
26
|
+
export { t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e={CHF:`₣`,AUD:`A$`,CAD:`CA$`,NZD:`NZ$`,HKD:`HK$`,MXN:`MX$`,SGD:`S$`},t=(t,n=`en-US`)=>{if(typeof t!=`string`||t==null||t===``||t===` `||t.length!==3)return`N/A`;let r=e[t.toUpperCase()];if(r!==void 0)return r;try{let e=new Intl.NumberFormat(n,{style:`currency`,currency:t,currencyDisplay:`narrowSymbol`}).formatToParts(0).find(e=>e.type===`currency`);return e===void 0?t:e.value}catch{return t}};Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return t}});
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
//#region src/truncate-decimals/constants/truncate-decimals.constant.ts
|
|
2
|
+
var e = /^-?\d+(\.\d+)?$/, t = (t, r = 2) => typeof t == "number" ? Number.isFinite(t) ? n(String(t), r) : "N/A" : typeof t == "string" && e.test(t.trim()) ? n(t.trim(), r) : "N/A", n = (e, t) => {
|
|
3
|
+
let [n, r] = e.split(".");
|
|
4
|
+
return r === void 0 ? e : t > 0 ? `${n}.${r.slice(0, t)}` : n;
|
|
5
|
+
};
|
|
6
|
+
//#endregion
|
|
7
|
+
export { t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=/^-?\d+(\.\d+)?$/,t=(t,r=2)=>typeof t==`number`?Number.isFinite(t)?n(String(t),r):`N/A`:typeof t==`string`&&e.test(t.trim())?n(t.trim(),r):`N/A`,n=(e,t)=>{let[n,r]=e.split(`.`);return r===void 0?e:t>0?`${n}.${r.slice(0,t)}`:n};Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return t}});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Explicit code → symbol overrides, checked before falling back to `Intl`.
|
|
3
|
+
* Use this for symbols `Intl` doesn't resolve the way you want (missing,
|
|
4
|
+
* wrong, or just not the convention your product uses).
|
|
5
|
+
*/
|
|
6
|
+
export declare const CURRENCY_SYMBOL_OVERRIDES: Record<string, string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../chunks/currency-symbol-gb63Q_9Q.cjs");exports.getCurrencySymbol=e.t;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the symbol for a given ISO 4217 currency code.
|
|
3
|
+
*
|
|
4
|
+
* Codes listed in `CURRENCY_SYMBOL_OVERRIDES` are returned as-is — this
|
|
5
|
+
* covers currencies whose `Intl` narrow symbol is ambiguous (e.g. `AUD`,
|
|
6
|
+
* `CAD`, `NZD` all narrow to a plain `$`) or otherwise not what the product
|
|
7
|
+
* wants. Everything else is resolved via the runtime's `Intl` data, so all
|
|
8
|
+
* other currencies are supported without a hardcoded map.
|
|
9
|
+
*
|
|
10
|
+
* @param code - ISO 4217 currency code (e.g. `"EUR"`)
|
|
11
|
+
* @param locale - Locale used to resolve the symbol. Defaults to `"en-US"`.
|
|
12
|
+
* @returns The currency symbol; `code` itself if it's well-formed but not a
|
|
13
|
+
* recognized currency; `"N/A"` if `code` isn't a 3-letter string
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* getCurrencySymbol('EUR') // => '€'
|
|
18
|
+
* getCurrencySymbol('USD') // => '$'
|
|
19
|
+
* getCurrencySymbol('AUD') // => 'A$' (override)
|
|
20
|
+
* getCurrencySymbol('CHF') // => '₣' (override)
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare const getCurrencySymbol: (code: string, locale?: string) => string;
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./build-query-params/index.cjs"),t=require("./clean-object/index.cjs"),n=require("./cookies/index.cjs"),r=require("./build-sort-param/index.cjs"),i=require("./download-file/index.cjs"),
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./build-query-params/index.cjs"),t=require("./clean-object/index.cjs"),n=require("./cookies/index.cjs"),r=require("./build-sort-param/index.cjs"),i=require("./chunks/currency-symbol-gb63Q_9Q.cjs"),a=require("./download-file/index.cjs"),o=require("./chunks/handle-api-error-D714W9rp.cjs"),s=require("./normalize-input/index.cjs"),c=require("./chunks/truncate-decimals-CArL-IeO.cjs");exports.buildQueryParams=e.buildQueryParams,exports.buildSortParam=r.buildSortParam,exports.cleanObject=t.cleanObject,exports.defaultCookieOptions=n.defaultCookieOptions,exports.deleteCookie=n.deleteCookie,exports.downloadBlob=a.downloadBlob,exports.getCookie=n.getCookie,exports.getCurrencySymbol=i.t,exports.handleApiError=o.t,exports.initHandleApiError=o.n,exports.normalizeDecimalInput=s.normalizeDecimalInput,exports.normalizePhoneNumberInput=s.normalizePhoneNumberInput,exports.setCookie=n.setCookie,exports.truncateDecimals=c.t;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ export * from './clean-object';
|
|
|
3
3
|
export * from './cookies';
|
|
4
4
|
export type * from './types';
|
|
5
5
|
export * from './build-sort-param';
|
|
6
|
+
export * from './currency-symbol';
|
|
6
7
|
export * from './download-file';
|
|
7
8
|
export * from './handle-api-error';
|
|
8
9
|
export * from './normalize-input';
|
|
10
|
+
export * from './truncate-decimals';
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,9 @@ import { buildQueryParams as e } from "./build-query-params/index.js";
|
|
|
2
2
|
import { cleanObject as t } from "./clean-object/index.js";
|
|
3
3
|
import { defaultCookieOptions as n, deleteCookie as r, getCookie as i, setCookie as a } from "./cookies/index.js";
|
|
4
4
|
import { buildSortParam as o } from "./build-sort-param/index.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
5
|
+
import { t as s } from "./chunks/currency-symbol-CBowgXv-.es";
|
|
6
|
+
import { downloadBlob as c } from "./download-file/index.js";
|
|
7
|
+
import { n as l, t as u } from "./chunks/handle-api-error-CMd_LxPS.es";
|
|
8
|
+
import { normalizeDecimalInput as d, normalizePhoneNumberInput as f } from "./normalize-input/index.js";
|
|
9
|
+
import { t as p } from "./chunks/truncate-decimals-BFMoEzul.es";
|
|
10
|
+
export { e as buildQueryParams, o as buildSortParam, t as cleanObject, n as defaultCookieOptions, r as deleteCookie, c as downloadBlob, i as getCookie, s as getCurrencySymbol, u as handleApiError, l as initHandleApiError, d as normalizeDecimalInput, f as normalizePhoneNumberInput, a as setCookie, p as truncateDecimals };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const NUMERIC_STRING_PATTERN: RegExp;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../chunks/truncate-decimals-CArL-IeO.cjs");exports.truncateDecimals=e.t;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Formats a number (or numeric string) to a fixed number of decimal places
|
|
3
|
+
* by cutting the extra digits off, without rounding.
|
|
4
|
+
*
|
|
5
|
+
* Unlike `toFixed`, `4.21312312` truncated to 2 decimals stays `4.21`
|
|
6
|
+
* instead of being rounded to `4.21`/`4.22` depending on the digits that follow.
|
|
7
|
+
*
|
|
8
|
+
* Accepts a string as well as a number so that values with more precision
|
|
9
|
+
* than a JS `number` can hold safely (e.g. amounts coming from an API as
|
|
10
|
+
* strings) can be truncated without going through a lossy float conversion first.
|
|
11
|
+
*
|
|
12
|
+
* Numbers large/small enough to be stringified in exponential notation
|
|
13
|
+
* (e.g. `1e+21`, `1e-7`) are returned as-is, since there's no decimal part to cut.
|
|
14
|
+
*
|
|
15
|
+
* @param value - The number (or numeric string) to truncate
|
|
16
|
+
* @param decimals - Number of digits to keep after the decimal point.
|
|
17
|
+
* Pass `0` to drop the decimal part entirely. Defaults to `2`.
|
|
18
|
+
* @returns The truncated value as a string; `'N/A'` if `value` isn't a finite
|
|
19
|
+
* number or a well-formed numeric string (e.g. `undefined`, `null`, `NaN`,
|
|
20
|
+
* `{}`, `[]`, `'not a number'`)
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```ts
|
|
24
|
+
* truncateDecimals(4.21312312) // => '4.21'
|
|
25
|
+
* truncateDecimals(4.2) // => '4.2' (fewer decimals than requested — left untouched)
|
|
26
|
+
* truncateDecimals(4.219, 0) // => '4'
|
|
27
|
+
* truncateDecimals('4.219999999999999999999999', 2) // => '4.21' (string input, no float precision loss)
|
|
28
|
+
* truncateDecimals('not a number') // => 'N/A'
|
|
29
|
+
* truncateDecimals(undefined as unknown as number) // => 'N/A'
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare const truncateDecimals: (value: number | string, decimals?: number) => string;
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@ptx-showcase/utils",
|
|
3
3
|
"author": "ptx-showcase",
|
|
4
4
|
"description": "Shared utilities for PTX Showcase projects",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.6.0",
|
|
6
6
|
"private": false,
|
|
7
7
|
"type": "module",
|
|
8
8
|
"license": "MIT",
|
|
@@ -51,6 +51,11 @@
|
|
|
51
51
|
"require": "./dist/clean-object/index.cjs",
|
|
52
52
|
"types": "./dist/clean-object/index.d.ts"
|
|
53
53
|
},
|
|
54
|
+
"./currency-symbol": {
|
|
55
|
+
"import": "./dist/currency-symbol/index.js",
|
|
56
|
+
"require": "./dist/currency-symbol/index.cjs",
|
|
57
|
+
"types": "./dist/currency-symbol/index.d.ts"
|
|
58
|
+
},
|
|
54
59
|
"./download-file": {
|
|
55
60
|
"import": "./dist/download-file/index.js",
|
|
56
61
|
"require": "./dist/download-file/index.cjs",
|
|
@@ -66,6 +71,11 @@
|
|
|
66
71
|
"require": "./dist/normalize-input/index.cjs",
|
|
67
72
|
"types": "./dist/normalize-input/index.d.ts"
|
|
68
73
|
},
|
|
74
|
+
"./truncate-decimals": {
|
|
75
|
+
"import": "./dist/truncate-decimals/index.js",
|
|
76
|
+
"require": "./dist/truncate-decimals/index.cjs",
|
|
77
|
+
"types": "./dist/truncate-decimals/index.d.ts"
|
|
78
|
+
},
|
|
69
79
|
"./types": {
|
|
70
80
|
"import": "./dist/types/index.js",
|
|
71
81
|
"require": "./dist/types/index.cjs",
|
|
@@ -87,20 +97,20 @@
|
|
|
87
97
|
"access": "public"
|
|
88
98
|
},
|
|
89
99
|
"devDependencies": {
|
|
90
|
-
"@types/node": "^26.
|
|
91
|
-
"bumpp": "^12.2.
|
|
92
|
-
"oxfmt": "^0.
|
|
93
|
-
"oxlint": "^1.
|
|
100
|
+
"@types/node": "^26.4.0",
|
|
101
|
+
"bumpp": "^12.2.2",
|
|
102
|
+
"oxfmt": "^0.65.0",
|
|
103
|
+
"oxlint": "^1.80.0",
|
|
94
104
|
"typescript": "~6.0.3",
|
|
95
|
-
"vite": "^8.2.
|
|
105
|
+
"vite": "^8.2.2",
|
|
96
106
|
"vite-plugin-dts": "^5.0.3",
|
|
97
|
-
"vitest": "^4.1.
|
|
107
|
+
"vitest": "^4.1.11"
|
|
98
108
|
},
|
|
99
109
|
"dependencies": {
|
|
100
110
|
"@types/file-saver": "^2.0.7",
|
|
101
111
|
"@types/js-cookie": "^3.0.6",
|
|
102
112
|
"file-saver": "^2.0.5",
|
|
103
113
|
"js-cookie": "^3.0.8",
|
|
104
|
-
"ky": "^2.0
|
|
114
|
+
"ky": "^2.1.0"
|
|
105
115
|
}
|
|
106
116
|
}
|