next-formatter 2.0.0 → 2.0.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 +39 -26
- package/dist/cjs/index.js +0 -12
- package/dist/cjs/server.js +9 -1
- package/dist/esm/index.mjs +0 -11
- package/dist/esm/server.mjs +9 -2
- package/dist/types/index.d.ts +1 -58
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/server.d.ts +75 -3
- package/dist/types/server.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
# next-formatter
|
|
2
2
|
|
|
3
3
|
Universal number, currency, date, and relative time formatter for Next.js App Router — works in both **Server Components** and **Client Components** with zero hydration mismatches.
|
|
4
4
|
|
|
5
|
-
[→ View Full Documentation
|
|
6
|
-
|
|
7
|
-
### Installation
|
|
5
|
+
[→ View Full Documentation](https://gauravgorade.github.io/next-formatter/)
|
|
8
6
|
|
|
7
|
+
## Installation
|
|
9
8
|
```bash
|
|
10
9
|
npm install next-formatter
|
|
11
10
|
```
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
## Recommended Setup
|
|
14
13
|
|
|
15
|
-
Define your configuration once in a shared
|
|
14
|
+
Define your configuration once in a shared file to keep locale and currency consistent across server and client.
|
|
16
15
|
|
|
17
16
|
**lib/formatter.ts**
|
|
18
|
-
|
|
19
17
|
```typescript
|
|
20
18
|
import { getFormatter as _getFormatter } from "next-formatter/server";
|
|
21
|
-
import { useFormatter } from "next-formatter/client";
|
|
22
19
|
import type { NextFormatterConfig } from "next-formatter";
|
|
23
20
|
|
|
24
21
|
const config: NextFormatterConfig = {
|
|
@@ -31,46 +28,45 @@ const config: NextFormatterConfig = {
|
|
|
31
28
|
|
|
32
29
|
export const formatterConfig = config;
|
|
33
30
|
export const getFormatter = () => _getFormatter(config);
|
|
34
|
-
export { useFormatter };
|
|
35
31
|
```
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
## 1. Add the Provider
|
|
38
34
|
|
|
39
|
-
Add
|
|
35
|
+
Add `NextFormatterProvider` to your root layout.
|
|
40
36
|
|
|
41
37
|
**app/layout.tsx**
|
|
42
|
-
|
|
43
38
|
```tsx
|
|
44
|
-
import { NextFormatterProvider } from "next-formatter";
|
|
39
|
+
import { NextFormatterProvider } from "next-formatter/server";
|
|
45
40
|
import { formatterConfig } from "@/lib/formatter";
|
|
46
41
|
|
|
47
42
|
export default async function RootLayout({ children }) {
|
|
48
43
|
return (
|
|
49
44
|
<html lang="en">
|
|
50
45
|
<body>
|
|
51
|
-
<NextFormatterProvider config={formatterConfig}>
|
|
46
|
+
<NextFormatterProvider config={formatterConfig}>
|
|
47
|
+
{children}
|
|
48
|
+
</NextFormatterProvider>
|
|
52
49
|
</body>
|
|
53
50
|
</html>
|
|
54
51
|
);
|
|
55
52
|
}
|
|
56
53
|
```
|
|
57
54
|
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
## 2. Server Components
|
|
60
56
|
```tsx
|
|
61
57
|
import { getFormatter } from "@/lib/formatter";
|
|
62
58
|
|
|
63
59
|
export default async function Page() {
|
|
64
60
|
const fmt = await getFormatter();
|
|
61
|
+
|
|
65
62
|
return <h1>{fmt.currency(49.99)}</h1>;
|
|
66
63
|
}
|
|
67
64
|
```
|
|
68
65
|
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
## 3. Client Components
|
|
71
67
|
```tsx
|
|
72
68
|
"use client";
|
|
73
|
-
import { useFormatter } from "
|
|
69
|
+
import { useFormatter } from "next-formatter/client";
|
|
74
70
|
|
|
75
71
|
export function Price({ value }) {
|
|
76
72
|
const { currency } = useFormatter();
|
|
@@ -78,14 +74,31 @@ export function Price({ value }) {
|
|
|
78
74
|
}
|
|
79
75
|
```
|
|
80
76
|
|
|
81
|
-
|
|
77
|
+
## Dynamic Locale & Currency
|
|
78
|
+
|
|
79
|
+
Resolve locale and currency per request from session, cookies, or headers.
|
|
80
|
+
```typescript
|
|
81
|
+
import type { NextFormatterConfig } from "next-formatter";
|
|
82
|
+
|
|
83
|
+
export const formatterConfig: NextFormatterConfig = {
|
|
84
|
+
getLocale: async () => {
|
|
85
|
+
const session = await auth();
|
|
86
|
+
return session?.user?.locale;
|
|
87
|
+
},
|
|
88
|
+
getCurrency: async () => {
|
|
89
|
+
const session = await auth();
|
|
90
|
+
return session?.user?.currency;
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
```
|
|
82
94
|
|
|
83
|
-
|
|
84
|
-
- **Dynamic Resolvers**: Detect locale from cookies, headers, or your database.
|
|
85
|
-
- **Micro-Bundle**: Optimized for the App Router with negligible client-side impact.
|
|
95
|
+
## Why next-formatter?
|
|
86
96
|
|
|
87
|
-
|
|
97
|
+
- **Zero hydration mismatches** — ICU spacing and fraction digits are normalized between server and client.
|
|
98
|
+
- **Dynamic resolvers** — detect locale and currency from cookies, headers, or your database per request.
|
|
99
|
+
- **Tiny client bundle** — server resolution means minimal JavaScript shipped to the browser.
|
|
100
|
+
- **Drop-in** — no global state, no providers required for server-only usage.
|
|
88
101
|
|
|
89
|
-
|
|
102
|
+
## License
|
|
90
103
|
|
|
91
|
-
MIT © [gauravgorade](https://github.com/gauravgorade)
|
|
104
|
+
MIT © [gauravgorade](https://github.com/gauravgorade)
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var client = require('./client');
|
|
4
|
-
var create = require('./create');
|
|
5
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
-
|
|
7
|
-
// src/index.tsx
|
|
8
|
-
async function NextFormatterProvider({ config = {}, children }) {
|
|
9
|
-
const locale = await create.resolveLocale(config.getLocale, config.locale);
|
|
10
|
-
const currency = await create.resolveCurrency(config.getCurrency, config.currency);
|
|
11
|
-
return /* @__PURE__ */ jsxRuntime.jsx(client.FormattersProvider, { config: { locale, currency, fallback: config.fallback, rules: config.rules }, children });
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
exports.NextFormatterProvider = NextFormatterProvider;
|
package/dist/cjs/server.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var client = require('./client');
|
|
3
4
|
var core = require('./core');
|
|
4
5
|
var create = require('./create');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
7
|
|
|
6
|
-
// src/server.
|
|
8
|
+
// src/server.tsx
|
|
9
|
+
async function NextFormatterProvider({ config = {}, children }) {
|
|
10
|
+
const locale = await create.resolveLocale(config.getLocale, config.locale);
|
|
11
|
+
const currency = await create.resolveCurrency(config.getCurrency, config.currency);
|
|
12
|
+
return /* @__PURE__ */ jsxRuntime.jsx(client.FormattersProvider, { config: { locale, currency, fallback: config.fallback, rules: config.rules }, children });
|
|
13
|
+
}
|
|
7
14
|
async function getFormatter(config = {}) {
|
|
8
15
|
const locale = await create.resolveLocale(config.getLocale, config.locale);
|
|
9
16
|
const currency = await create.resolveCurrency(config.getCurrency, config.currency);
|
|
@@ -15,4 +22,5 @@ async function getFormatter(config = {}) {
|
|
|
15
22
|
});
|
|
16
23
|
}
|
|
17
24
|
|
|
25
|
+
exports.NextFormatterProvider = NextFormatterProvider;
|
|
18
26
|
exports.getFormatter = getFormatter;
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,12 +1 @@
|
|
|
1
|
-
import { FormattersProvider } from './client';
|
|
2
|
-
import { resolveLocale, resolveCurrency } from './create';
|
|
3
|
-
import { jsx } from 'react/jsx-runtime';
|
|
4
1
|
|
|
5
|
-
// src/index.tsx
|
|
6
|
-
async function NextFormatterProvider({ config = {}, children }) {
|
|
7
|
-
const locale = await resolveLocale(config.getLocale, config.locale);
|
|
8
|
-
const currency = await resolveCurrency(config.getCurrency, config.currency);
|
|
9
|
-
return /* @__PURE__ */ jsx(FormattersProvider, { config: { locale, currency, fallback: config.fallback, rules: config.rules }, children });
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export { NextFormatterProvider };
|
package/dist/esm/server.mjs
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
import { FormattersProvider } from './client';
|
|
1
2
|
import { createFormatters } from './core';
|
|
2
3
|
import { resolveLocale, resolveCurrency } from './create';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
5
|
|
|
4
|
-
// src/server.
|
|
6
|
+
// src/server.tsx
|
|
7
|
+
async function NextFormatterProvider({ config = {}, children }) {
|
|
8
|
+
const locale = await resolveLocale(config.getLocale, config.locale);
|
|
9
|
+
const currency = await resolveCurrency(config.getCurrency, config.currency);
|
|
10
|
+
return /* @__PURE__ */ jsx(FormattersProvider, { config: { locale, currency, fallback: config.fallback, rules: config.rules }, children });
|
|
11
|
+
}
|
|
5
12
|
async function getFormatter(config = {}) {
|
|
6
13
|
const locale = await resolveLocale(config.getLocale, config.locale);
|
|
7
14
|
const currency = await resolveCurrency(config.getCurrency, config.currency);
|
|
@@ -13,4 +20,4 @@ async function getFormatter(config = {}) {
|
|
|
13
20
|
});
|
|
14
21
|
}
|
|
15
22
|
|
|
16
|
-
export { getFormatter };
|
|
23
|
+
export { NextFormatterProvider, getFormatter };
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,60 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import { type NextFormatterConfig } from "./create";
|
|
3
|
-
/**
|
|
4
|
-
* Root provider for Next.js App Router. Place in `app/layout.tsx`.
|
|
5
|
-
*
|
|
6
|
-
* Async Server Component — resolves locale and currency server-side per request,
|
|
7
|
-
* then passes the resolved config to the client-side context. Zero client bundle cost.
|
|
8
|
-
*
|
|
9
|
-
* Resolution order for locale:
|
|
10
|
-
* 1. `getLocale()` resolver (session, db, cookie)
|
|
11
|
-
* 2. `locale` static value
|
|
12
|
-
* 3. `accept-language` request header
|
|
13
|
-
* 4. `"en-US"` default
|
|
14
|
-
*
|
|
15
|
-
* Resolution order for currency:
|
|
16
|
-
* 1. `getCurrency()` resolver (session, db, cookie)
|
|
17
|
-
* 2. `currency` static value
|
|
18
|
-
* 3. `"USD"` default
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* // Zero config — locale auto-detected from accept-language header
|
|
22
|
-
* <NextFormatterProvider>{children}</NextFormatterProvider>
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* // Static locale and currency
|
|
26
|
-
* <NextFormatterProvider config={{ locale: "de-DE", currency: "EUR" }}>
|
|
27
|
-
* {children}
|
|
28
|
-
* </NextFormatterProvider>
|
|
29
|
-
*
|
|
30
|
-
* @example
|
|
31
|
-
* // Dynamic locale and currency from session
|
|
32
|
-
* <NextFormatterProvider
|
|
33
|
-
* config={{
|
|
34
|
-
* getLocale: async () => (await auth())?.user?.locale,
|
|
35
|
-
* getCurrency: async () => (await auth())?.user?.currency,
|
|
36
|
-
* fallback: "N/A",
|
|
37
|
-
* rules: {
|
|
38
|
-
* compactThreshold: 50_000,
|
|
39
|
-
* currencyDisplay: "symbol",
|
|
40
|
-
* dateFormat: { year: "numeric", month: "long", day: "2-digit" },
|
|
41
|
-
* },
|
|
42
|
-
* }}
|
|
43
|
-
* >
|
|
44
|
-
* {children}
|
|
45
|
-
* </NextFormatterProvider>
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* // Recommended — define config once in lib/formatter.ts, import everywhere
|
|
49
|
-
* import { formatterConfig } from "@/lib/formatter";
|
|
50
|
-
*
|
|
51
|
-
* <NextFormatterProvider config={formatterConfig}>
|
|
52
|
-
* {children}
|
|
53
|
-
* </NextFormatterProvider>
|
|
54
|
-
*/
|
|
55
|
-
export declare function NextFormatterProvider({ config, children }: PropsWithChildren<{
|
|
56
|
-
config?: NextFormatterConfig;
|
|
57
|
-
}>): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
58
|
-
export type { FormatterConfig, Formatter, FormatterRules, NumericInput, DateInput } from "./core";
|
|
1
|
+
export type { FormatterConfig, Formatter, FormatterRules, NumericInput, DateInput, NumberOptions, CurrencyOptions, PercentageOptions, DateOptions, DateTimeOptions } from "./core";
|
|
59
2
|
export type { NextFormatterConfig } from "./create";
|
|
60
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,cAAc,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AACnL,YAAY,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/types/server.d.ts
CHANGED
|
@@ -1,22 +1,94 @@
|
|
|
1
|
+
import { type PropsWithChildren } from "react";
|
|
1
2
|
import { type Formatter } from "./core";
|
|
2
3
|
import { type NextFormatterConfig } from "./create";
|
|
4
|
+
/**
|
|
5
|
+
* Root provider for Next.js App Router. Place in `app/layout.tsx`.
|
|
6
|
+
*
|
|
7
|
+
* Async Server Component — resolves locale and currency server-side per request,
|
|
8
|
+
* then passes the resolved config to the client-side context. Zero client bundle cost.
|
|
9
|
+
*
|
|
10
|
+
* Resolution order for locale:
|
|
11
|
+
* 1. `getLocale()` resolver (session, db, cookie)
|
|
12
|
+
* 2. `locale` static value
|
|
13
|
+
* 3. `accept-language` request header
|
|
14
|
+
* 4. `"en-US"` default
|
|
15
|
+
*
|
|
16
|
+
* Resolution order for currency:
|
|
17
|
+
* 1. `getCurrency()` resolver (session, db, cookie)
|
|
18
|
+
* 2. `currency` static value
|
|
19
|
+
* 3. `"USD"` default
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Zero config — locale auto-detected from accept-language header
|
|
23
|
+
* <NextFormatterProvider>{children}</NextFormatterProvider>
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Static locale and currency
|
|
27
|
+
* <NextFormatterProvider config={{ locale: "de-DE", currency: "EUR" }}>
|
|
28
|
+
* {children}
|
|
29
|
+
* </NextFormatterProvider>
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // Dynamic locale and currency from session
|
|
33
|
+
* <NextFormatterProvider
|
|
34
|
+
* config={{
|
|
35
|
+
* getLocale: async () => (await auth())?.user?.locale,
|
|
36
|
+
* getCurrency: async () => (await auth())?.user?.currency,
|
|
37
|
+
* fallback: "N/A",
|
|
38
|
+
* rules: {
|
|
39
|
+
* compactThreshold: 50_000,
|
|
40
|
+
* currencyDisplay: "symbol",
|
|
41
|
+
* dateFormat: { year: "numeric", month: "long", day: "2-digit" },
|
|
42
|
+
* },
|
|
43
|
+
* }}
|
|
44
|
+
* >
|
|
45
|
+
* {children}
|
|
46
|
+
* </NextFormatterProvider>
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* // Recommended — define config once in lib/formatter.ts, import everywhere
|
|
50
|
+
* import { formatterConfig } from "@/lib/formatter";
|
|
51
|
+
*
|
|
52
|
+
* <NextFormatterProvider config={formatterConfig}>
|
|
53
|
+
* {children}
|
|
54
|
+
* </NextFormatterProvider>
|
|
55
|
+
*/
|
|
56
|
+
export declare function NextFormatterProvider({ config, children }: PropsWithChildren<{
|
|
57
|
+
config?: NextFormatterConfig;
|
|
58
|
+
}>): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
3
59
|
/**
|
|
4
60
|
* Use in Server Components or Server Actions.
|
|
5
61
|
* Locale is auto-detected from request headers — pass config only to override.
|
|
6
62
|
*
|
|
7
63
|
* @example
|
|
8
|
-
* // Zero config
|
|
64
|
+
* // Zero config — locale and currency auto-detected
|
|
9
65
|
* const fmt = await getFormatter();
|
|
66
|
+
* fmt.currency(1234); // "$1,234"
|
|
10
67
|
*
|
|
11
68
|
* @example
|
|
12
|
-
* //
|
|
13
|
-
* const fmt = await getFormatter({ currency: "EUR" });
|
|
69
|
+
* // Static overrides
|
|
70
|
+
* const fmt = await getFormatter({ locale: "de-DE", currency: "EUR" });
|
|
71
|
+
* fmt.currency(1234); // "1.234 €"
|
|
14
72
|
*
|
|
15
73
|
* @example
|
|
16
74
|
* // Dynamic currency from session
|
|
17
75
|
* const fmt = await getFormatter({
|
|
18
76
|
* getCurrency: async () => (await auth())?.user?.currency,
|
|
19
77
|
* });
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* // With custom rules
|
|
81
|
+
* const fmt = await getFormatter({
|
|
82
|
+
* rules: {
|
|
83
|
+
* compactThreshold: 50_000,
|
|
84
|
+
* currencyDisplay: "symbol",
|
|
85
|
+
* },
|
|
86
|
+
* });
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* // Recommended — define config once in lib/formatter.ts, import everywhere
|
|
90
|
+
* import { formatterConfig } from "@/lib/formatter";
|
|
91
|
+
* const fmt = await getFormatter(formatterConfig);
|
|
20
92
|
*/
|
|
21
93
|
export declare function getFormatter(config?: NextFormatterConfig): Promise<Formatter>;
|
|
22
94
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAAoB,KAAK,SAAS,EAAE,MAAM,QAAQ,CAAC;AAC1D,OAAO,EAAkC,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,wBAAsB,qBAAqB,CAAC,EAAE,MAAW,EAAE,QAAQ,EAAE,EAAE,iBAAiB,CAAC;IAAE,MAAM,CAAC,EAAE,mBAAmB,CAAA;CAAE,CAAC,oDAKzH;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,YAAY,CAAC,MAAM,GAAE,mBAAwB,GAAG,OAAO,CAAC,SAAS,CAAC,CAUvF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-formatter",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "A universal formatter for numbers, currency, dates, and relative time — built for Next.js App Router, supporting server components, client components, and Node.js backends.",
|
|
5
5
|
"author": "gauravgorade",
|
|
6
6
|
"license": "MIT",
|