Skip to content

Commit e366ee7

Browse files
authored
feat(format): Support passing locale as part of config object (#82)
1 parent d7e5094 commit e366ee7

File tree

4 files changed

+80
-37
lines changed

4 files changed

+80
-37
lines changed

.changeset/open-schools-spend.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@layerstack/utils': patch
3+
---
4+
5+
feat(format): Support passing `locale` as part of config object

packages/utils/src/lib/format.test.ts

Lines changed: 43 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,29 @@ describe('format()', () => {
1616
expect(actual).equal('');
1717
});
1818

19+
describe('format based on value type', () => {
20+
it('integer', () => {
21+
const actual = format(1234);
22+
expect(actual).equal('1,234');
23+
});
24+
it('decimal', () => {
25+
const actual = format(1234.5678);
26+
expect(actual).equal('1,234.57');
27+
});
28+
it('date string', () => {
29+
const actual = format(testDateStr);
30+
expect(actual).equal('11/21/2023');
31+
});
32+
it('date', () => {
33+
const actual = format(parseDate(testDateStr));
34+
expect(actual).equal('11/21/2023');
35+
});
36+
it('string', () => {
37+
const actual = format('hello');
38+
expect(actual).equal('hello');
39+
});
40+
});
41+
1942
describe('formats number', () => {
2043
// See `number.test.ts` for more number tests
2144
it('returns original value as string for style "none"', () => {
@@ -46,6 +69,16 @@ describe('format()', () => {
4669
expect(actual).equal('1,234.57');
4770
});
4871

72+
it('formats with "decimal" config with locale (es)', () => {
73+
const actual = format(1234.5678, { type: 'decimal', locale: 'es' });
74+
expect(actual).equal('1234,57');
75+
});
76+
77+
it('formats with "decimal" config with locale (de)', () => {
78+
const actual = format(1234.5678, { type: 'decimal', locale: 'de' });
79+
expect(actual).equal('1.234,57');
80+
});
81+
4982
it('formats with "decimal" config with extra options', () => {
5083
const actual = format(1234.5678, { type: 'decimal', options: { fractionDigits: 3 } });
5184
expect(actual).equal('1,234.568');
@@ -100,32 +133,19 @@ describe('format()', () => {
100133
expect(actual).equal('11/21/2023');
101134
});
102135

103-
it('formats date with config with extra options', () => {
104-
const actual = format(testDate, { type: 'day', options: { variant: 'short' } });
105-
expect(actual).equal('11/21');
136+
it('formats date with config with locale', () => {
137+
const actual = format(testDate, { type: 'day', locale: 'es' });
138+
expect(actual).equal('21/11/2023');
106139
});
107-
});
108140

109-
describe('format based on value type', () => {
110-
it('format based on value type (integer)', () => {
111-
const actual = format(1234);
112-
expect(actual).equal('1,234');
113-
});
114-
it('format based on value type (decimal)', () => {
115-
const actual = format(1234.5678);
116-
expect(actual).equal('1,234.57');
117-
});
118-
it('format based on value type (date string)', () => {
119-
const actual = format(testDateStr);
120-
expect(actual).equal('11/21/2023');
121-
});
122-
it('format based on value type (date)', () => {
123-
const actual = format(parseDate(testDateStr));
124-
expect(actual).equal('11/21/2023');
141+
it('formats date with config with locale', () => {
142+
const actual = format(testDate, { type: 'day', locale: 'de' });
143+
expect(actual).equal('21.11.2023');
125144
});
126-
it('format based on value type (string)', () => {
127-
const actual = format('hello');
128-
expect(actual).equal('hello');
145+
146+
it('formats date with config with extra options', () => {
147+
const actual = format(testDate, { type: 'day', options: { variant: 'short' } });
148+
expect(actual).equal('11/21');
129149
});
130150
});
131151
});

packages/utils/src/lib/format.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from './date.js';
88
import { formatNumberWithLocale } from './number.js';
99
import type { FormatNumberOptions, FormatNumberStyle } from './number.js';
10-
import { defaultLocale, type LocaleSettings } from './locale.js';
10+
import { createLocaleSettings, defaultLocale, type LocaleSettings } from './locale.js';
1111
import {
1212
PeriodType,
1313
type FormatDateOptions,
@@ -29,33 +29,51 @@ export type { FormatNumberStyle, PeriodType, PeriodTypeCode };
2929
*/
3030
export function format(value: null | undefined, format?: FormatType): string;
3131
export function format(value: null | undefined, config: { type: FormatType }): string;
32+
33+
// number
3234
export function format(
3335
value: number,
3436
format?: FormatNumberStyle | CustomFormatter,
35-
options?: FormatNumberOptions
37+
options?: FormatNumberOptions,
38+
locale?: string
3639
): string;
3740
export function format(
3841
value: number,
39-
config: { type: FormatNumberStyle | CustomFormatter; options?: FormatNumberOptions }
42+
config: {
43+
type: FormatNumberStyle | CustomFormatter;
44+
options?: FormatNumberOptions;
45+
locale?: string;
46+
}
4047
): string;
48+
49+
// Date
4150
export function format(
4251
value: string | Date,
4352
format?: PeriodType | PeriodTypeCode | CustomFormatter,
44-
options?: FormatDateOptions
53+
options?: FormatDateOptions,
54+
locale?: string
4555
): string;
4656
export function format(
4757
value: string | Date,
48-
config: { type: PeriodType | PeriodTypeCode | CustomFormatter; options?: FormatDateOptions }
58+
config: {
59+
type: PeriodType | PeriodTypeCode | CustomFormatter;
60+
options?: FormatDateOptions;
61+
locale?: string;
62+
}
4963
): string;
64+
5065
export function format(
5166
value: any,
5267
formatOrConfig?:
5368
| FormatType
54-
| { type: FormatType; options?: FormatNumberOptions | FormatDateOptions },
69+
| { type: FormatType; options?: FormatNumberOptions | FormatDateOptions; locale?: string },
5570
options?: FormatNumberOptions | FormatDateOptions
5671
): any {
57-
if (formatOrConfig && typeof formatOrConfig === 'object' && 'type' in formatOrConfig) {
58-
return formatWithLocale(defaultLocale, value, formatOrConfig.type, formatOrConfig.options);
72+
if (typeof formatOrConfig === 'object') {
73+
const locale = formatOrConfig.locale
74+
? createLocaleSettings({ locale: formatOrConfig.locale })
75+
: defaultLocale;
76+
return formatWithLocale(locale, value, formatOrConfig.type, formatOrConfig.options);
5977
}
6078
return formatWithLocale(defaultLocale, value, formatOrConfig as FormatType, options);
6179
}

sites/docs/src/routes/docs/utils/format/+page.svelte

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import Code from '$docs/Code.svelte';
1212
1313
let value = 1234.56;
14-
let style: FormatNumberStyle = 'decimal';
14+
let numberType: FormatNumberStyle = 'decimal';
1515
let currency: Intl.NumberFormatOptions['currency'] | undefined = 'USD';
1616
let notation: Intl.NumberFormatOptions['notation'] = 'standard';
1717
@@ -50,8 +50,8 @@
5050
<TextField label="value" bind:value type="decimal" />
5151

5252
<MenuField
53-
label="style"
54-
bind:value={style}
53+
label="type"
54+
bind:value={numberType}
5555
options={[
5656
'integer',
5757
'decimal',
@@ -72,7 +72,7 @@
7272
value,
7373
}))}
7474
stepper
75-
disabled={style !== 'currency' && style !== 'currencyRound'}
75+
disabled={numberType !== 'currency' && numberType !== 'currencyRound'}
7676
/>
7777

7878
<MenuField
@@ -94,7 +94,7 @@
9494
</div>
9595

9696
<Preview>
97-
<div>{format(value, style, { currency, notation })}</div>
97+
<div>{format(value, { type: numberType, locale, options: { currency, notation } })}</div>
9898
</Preview>
9999

100100
<h2>Playground dates</h2>
@@ -118,7 +118,7 @@
118118
</div>
119119

120120
<Preview>
121-
<div>{format(myDate, periodType)}</div>
121+
<div>{format(myDate, { type: periodType, locale })}</div>
122122
</Preview>
123123

124124
<h1>Numbers</h1>

0 commit comments

Comments
 (0)