@canutin/svelte-currency-input 1.0.0 → 1.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/README.md CHANGED
@@ -18,6 +18,7 @@ A fully-featured currency input component for Svelte 5 that handles formatting,
18
18
  - [Examples](#examples)
19
19
  - [Styling](#styling)
20
20
  - [Exported utilities](#exported-utilities)
21
+ - [formatValue options](#formatvalue-options)
21
22
  - [Svelte 4 / migration guide](#svelte-4)
22
23
  - [Contributing](#contributing)
23
24
 
@@ -274,6 +275,51 @@ const expanded = parseAbbrValue('2.5m', 'en-US');
274
275
  // → "2500000"
275
276
  ```
276
277
 
278
+ ### formatValue options
279
+
280
+ | Option | Type | Default | Description |
281
+ | ------------------------ | ------------ | ----------- | --------------------------------------------- |
282
+ | `value` | `string` | — | The value to format |
283
+ | `intlConfig` | `IntlConfig` | `undefined` | Locale and currency configuration |
284
+ | `decimalScale` | `number` | `undefined` | Number of decimal places |
285
+ | `decimalSeparator` | `string` | From locale | Override the decimal separator |
286
+ | `groupSeparator` | `string` | From locale | Override the grouping separator |
287
+ | `disableGroupSeparators` | `boolean` | `false` | Disable thousand separators |
288
+ | `prefix` | `string` | From locale | Override the currency prefix |
289
+ | `suffix` | `string` | `''` | Override the currency suffix |
290
+ | `roundValue` | `boolean` | `false` | Round to `decimalScale` instead of truncating |
291
+
292
+ By default, `formatValue` truncates decimals to `decimalScale`. Set `roundValue: true` to round instead, which is useful when formatting computed values with floating-point precision artifacts:
293
+
294
+ ```typescript
295
+ // Default: truncates
296
+ formatValue({
297
+ value: '87.5',
298
+ intlConfig: { locale: 'en-US', currency: 'USD' },
299
+ decimalScale: 0
300
+ });
301
+ // → "$87"
302
+
303
+ // With roundValue: rounds
304
+ formatValue({
305
+ value: '87.5',
306
+ intlConfig: { locale: 'en-US', currency: 'USD' },
307
+ decimalScale: 0,
308
+ roundValue: true
309
+ });
310
+ // → "$88"
311
+
312
+ // Useful for computed values with floating-point issues
313
+ const sum = 500.75 + 300.5 - 200.25 - 150.33; // = 450.66999999999996
314
+ formatValue({
315
+ value: String(sum),
316
+ intlConfig: { locale: 'en-US', currency: 'USD' },
317
+ decimalScale: 2,
318
+ roundValue: true
319
+ });
320
+ // → "$450.67" (without roundValue, would be "$450.66")
321
+ ```
322
+
277
323
  ## Svelte 4
278
324
 
279
325
  For Svelte 4 support, use the [0.x version](https://github.com/fmaclen/svelte-currency-input/tree/v0.13.0):
package/dist/types.d.ts CHANGED
@@ -22,6 +22,7 @@ export type FormatValueOptions = {
22
22
  decimalScale?: number;
23
23
  prefix?: string;
24
24
  suffix?: string;
25
+ roundValue?: boolean;
25
26
  };
26
27
  export type CleanValueOptions = {
27
28
  value: string;
@@ -1,7 +1,7 @@
1
1
  import { escapeRegExp } from './escapeRegExp';
2
2
  import { getSuffix } from './getSuffix';
3
3
  export const formatValue = (options) => {
4
- const { value: _value, decimalSeparator, intlConfig, decimalScale, prefix = '', suffix = '' } = options;
4
+ const { value: _value, decimalSeparator, intlConfig, decimalScale, prefix = '', suffix = '', roundValue = false } = options;
5
5
  if (_value === '' || _value === undefined) {
6
6
  return '';
7
7
  }
@@ -19,7 +19,7 @@ export const formatValue = (options) => {
19
19
  const defaultNumberFormatOptions = {
20
20
  ...formatOptions,
21
21
  minimumFractionDigits: decimalScale || 0,
22
- maximumFractionDigits: 20
22
+ maximumFractionDigits: roundValue && decimalScale !== undefined ? decimalScale : 20
23
23
  };
24
24
  const numberFormatter = intlConfig
25
25
  ? new Intl.NumberFormat(locale, {
@@ -66,7 +66,7 @@ const replaceDecimalSeparator = (value, decimalSeparator, isNegative) => {
66
66
  }
67
67
  return newValue;
68
68
  };
69
- const replaceParts = (parts, { prefix, groupSeparator, decimalSeparator, decimalScale, disableGroupSeparators = false }) => {
69
+ const replaceParts = (parts, { prefix, groupSeparator, decimalSeparator, decimalScale, disableGroupSeparators = false, roundValue = false }) => {
70
70
  return parts
71
71
  .reduce((prev, { type, value }, i) => {
72
72
  if (i === 0 && prefix) {
@@ -93,6 +93,9 @@ const replaceParts = (parts, { prefix, groupSeparator, decimalSeparator, decimal
93
93
  return [...prev, decimalSeparator !== undefined ? decimalSeparator : value];
94
94
  }
95
95
  if (type === 'fraction') {
96
+ if (roundValue) {
97
+ return [...prev, value];
98
+ }
96
99
  return [...prev, decimalScale !== undefined ? value.slice(0, decimalScale) : value];
97
100
  }
98
101
  return [...prev, value];
@@ -17,7 +17,16 @@ export const parseAbbrValue = (value, decimalSeparator = '.') => {
17
17
  if (match) {
18
18
  const [, digits, , abbr] = match;
19
19
  const multiplier = abbrMap[abbr.toLowerCase()];
20
- return Number(digits.replace(decimalSeparator, '.')) * multiplier;
20
+ const result = Number(digits.replace(decimalSeparator, '.')) * multiplier;
21
+ // Round based on input precision to avoid floating-point errors
22
+ // e.g. 4.1 * 1000000 = 4099999.9999999995 should become 4100000
23
+ // but 1.12345678 * 1000 = 1123.45678 should preserve all decimals
24
+ const decimalPart = digits.split(decimalSeparator)[1] || '';
25
+ const inputDecimals = decimalPart.length;
26
+ const multiplierZeros = Math.log10(multiplier);
27
+ const resultDecimals = Math.max(0, inputDecimals - multiplierZeros);
28
+ const precision = Math.pow(10, resultDecimals);
29
+ return Math.round(result * precision) / precision;
21
30
  }
22
31
  return undefined;
23
32
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canutin/svelte-currency-input",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "engines": {
5
5
  "node": ">=22"
6
6
  },