@charlite/react-temporal 0.0.0-stage → 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.
Files changed (49) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/LICENSE +21 -0
  3. package/README.md +178 -2
  4. package/dist/hooks/useTemporalAdd.d.ts +7 -0
  5. package/dist/hooks/useTemporalCalendar.d.ts +4 -0
  6. package/dist/hooks/useTemporalClock.d.ts +5 -0
  7. package/dist/hooks/useTemporalCompare.d.ts +7 -0
  8. package/dist/hooks/useTemporalCountdown.d.ts +5 -0
  9. package/dist/hooks/useTemporalCountdownStatus.d.ts +11 -0
  10. package/dist/hooks/useTemporalDiff.d.ts +5 -0
  11. package/dist/hooks/useTemporalDuration.d.ts +5 -0
  12. package/dist/hooks/useTemporalElapsed.d.ts +5 -0
  13. package/dist/hooks/useTemporalFormat.d.ts +7 -0
  14. package/dist/hooks/useTemporalFrom.d.ts +5 -0
  15. package/dist/hooks/useTemporalInterval.d.ts +6 -0
  16. package/dist/hooks/useTemporalLocalDate.d.ts +5 -0
  17. package/dist/hooks/useTemporalMonth.d.ts +5 -0
  18. package/dist/hooks/useTemporalNow.d.ts +6 -0
  19. package/dist/hooks/useTemporalParse.d.ts +3 -0
  20. package/dist/hooks/useTemporalRange.d.ts +5 -0
  21. package/dist/hooks/useTemporalRelative.d.ts +6 -0
  22. package/dist/hooks/useTemporalSafeParse.d.ts +5 -0
  23. package/dist/hooks/useTemporalSchedule.d.ts +9 -0
  24. package/dist/hooks/useTemporalStopwatch.d.ts +11 -0
  25. package/dist/hooks/useTemporalTimeZone.d.ts +4 -0
  26. package/dist/hooks/useTemporalWeek.d.ts +5 -0
  27. package/dist/hooks/useTemporalWithin.d.ts +5 -0
  28. package/dist/hooks/useTemporalYear.d.ts +5 -0
  29. package/dist/hooks/useTemporalZonedNow.d.ts +6 -0
  30. package/dist/index.cjs +507 -0
  31. package/dist/index.cjs.map +1 -0
  32. package/dist/index.d.ts +29 -0
  33. package/dist/index.esm.js +477 -0
  34. package/dist/index.esm.js.map +1 -0
  35. package/dist/internal/durationKey.d.ts +5 -0
  36. package/dist/internal/useLatest.d.ts +2 -0
  37. package/dist/internal/useTemporalTicker.d.ts +11 -0
  38. package/dist/temporal.d.ts +20 -0
  39. package/dist/types.d.ts +35 -0
  40. package/dist/utils/formatRelative.d.ts +6 -0
  41. package/dist/utils/parseTemporal.d.ts +2 -0
  42. package/docs/README.md +53 -0
  43. package/docs/api-reference.md +331 -0
  44. package/docs/getting-started.md +111 -0
  45. package/docs/installation.md +87 -0
  46. package/docs/migration.md +143 -0
  47. package/docs/polyfill.md +89 -0
  48. package/docs/typescript.md +86 -0
  49. package/package.json +117 -4
@@ -0,0 +1,331 @@
1
+ # API reference
2
+
3
+ All exports from `@charlite/react-temporal`.
4
+
5
+ ## Utilities
6
+
7
+ ### `Temporal`
8
+
9
+ Re-exported Temporal namespace (native or polyfill).
10
+
11
+ ```ts
12
+ import { Temporal } from '@charlite/react-temporal';
13
+
14
+ const date = Temporal.PlainDate.from('2026-07-05');
15
+ const now = Temporal.Now.instant();
16
+ ```
17
+
18
+ ### `getTemporal()`
19
+
20
+ Returns the resolved Temporal namespace. Prefer using `Temporal` directly.
21
+
22
+ ```ts
23
+ import { getTemporal } from '@charlite/react-temporal';
24
+
25
+ const T = getTemporal();
26
+ ```
27
+
28
+ ### `hasNativeTemporal()`
29
+
30
+ Returns `true` when `globalThis.Temporal` is defined.
31
+
32
+ ---
33
+
34
+ ## Parsing
35
+
36
+ ### `useTemporalFrom(kind, input)`
37
+
38
+ Parses an ISO string into the requested Temporal type.
39
+
40
+ **Kinds:** `'instant' | 'plainDate' | 'plainTime' | 'plainDateTime' | 'zonedDateTime'`
41
+
42
+ ### `useTemporalSafeParse(kind, input)`
43
+
44
+ Same as `useTemporalFrom`, but returns `{ value, error }` instead of throwing.
45
+
46
+ ---
47
+
48
+ ## Clock hooks
49
+
50
+ ### `useTemporalNow(options?)`
51
+
52
+ Returns the current time, updating at a configurable interval.
53
+
54
+ | Option | Type | Default | Description |
55
+ | --- | --- | --- | --- |
56
+ | `intervalMs` | `number` | `1000` | Tick interval in milliseconds |
57
+ | `timeZone` | `string` | — | IANA time zone; when set, returns `ZonedDateTime` |
58
+ | `pauseWhenHidden` | `boolean` | `false` | Skip ticks while the document is hidden |
59
+
60
+ **Returns:** `Temporal.Instant` or `Temporal.ZonedDateTime`
61
+
62
+ ```tsx
63
+ const now = useTemporalNow();
64
+ const madrid = useTemporalNow({ timeZone: 'Europe/Madrid', intervalMs: 5000 });
65
+ ```
66
+
67
+ ---
68
+
69
+ ### `useTemporalClock(options?)`
70
+
71
+ Live clock returning `Temporal.Instant`. Simpler alternative to `useTemporalNow` without time zone support.
72
+
73
+ | Option | Type | Default | Description |
74
+ | --- | --- | --- | --- |
75
+ | `intervalMs` | `number` | `1000` | Tick interval in milliseconds |
76
+
77
+ **Returns:** `Temporal.Instant`
78
+
79
+ ```tsx
80
+ const now = useTemporalClock({ intervalMs: 100 });
81
+ ```
82
+
83
+ ---
84
+
85
+ ### `useTemporalZonedNow(timeZone, options?)`
86
+
87
+ Live clock for a specific IANA time zone.
88
+
89
+ | Parameter | Type | Description |
90
+ | --- | --- | --- |
91
+ | `timeZone` | `string` | IANA time zone identifier (e.g. `'Asia/Tokyo'`) |
92
+ | `options.intervalMs` | `number` | Tick interval (default `1000`) |
93
+
94
+ **Returns:** `Temporal.ZonedDateTime`
95
+
96
+ ```tsx
97
+ const tokyo = useTemporalZonedNow('Asia/Tokyo');
98
+ ```
99
+
100
+ ---
101
+
102
+ ## Duration and difference
103
+
104
+ ### `useTemporalDuration(start, end)`
105
+
106
+ Returns the duration from `start` to `end` using `start.until(end)`.
107
+
108
+ **Returns:** `Temporal.Duration`
109
+
110
+ ```tsx
111
+ const duration = useTemporalDuration(startInstant, endInstant);
112
+ duration.total('minutes'); // 90
113
+ ```
114
+
115
+ ---
116
+
117
+ ### `useTemporalDiff(a, b)`
118
+
119
+ Alias-style hook returning `a.until(b)`.
120
+
121
+ **Returns:** `Temporal.Duration`
122
+
123
+ ```tsx
124
+ const diff = useTemporalDiff(earlier, later);
125
+ diff.total('hours');
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Formatting and parsing
131
+
132
+ ### `useTemporalFormat(temporalObj, locales?, options?)`
133
+
134
+ Formats a Temporal value using `toLocaleString`.
135
+
136
+ **Accepts:** `Instant`, `PlainDate`, `PlainTime`, `PlainDateTime`, `ZonedDateTime`
137
+
138
+ **Returns:** `string`
139
+
140
+ ```tsx
141
+ const formatted = useTemporalFormat(
142
+ Temporal.PlainDateTime.from('2026-07-05T14:30:00'),
143
+ 'en-US',
144
+ { dateStyle: 'full', timeStyle: 'short' },
145
+ );
146
+ ```
147
+
148
+ ---
149
+
150
+ ### `useTemporalParse(isoString)`
151
+
152
+ Parses an ISO 8601 string to `Temporal.Instant`. Memoized on `isoString`.
153
+
154
+ **Returns:** `Temporal.Instant`
155
+
156
+ ```tsx
157
+ const instant = useTemporalParse('2026-07-05T12:00:00Z');
158
+ ```
159
+
160
+ ---
161
+
162
+ ### `useTemporalRelative(from, to, locales?, options?)`
163
+
164
+ Locale-aware relative time via `Intl.RelativeTimeFormat`.
165
+
166
+ **Returns:** `string` (e.g. `"in 3 hours"`, `"2 days ago"`)
167
+
168
+ ```tsx
169
+ const label = useTemporalRelative(past, future, 'en', { numeric: 'auto' });
170
+ ```
171
+
172
+ ---
173
+
174
+ ## Calendar and ranges
175
+
176
+ ### `useTemporalRange(start, end)`
177
+
178
+ Inclusive array of `PlainDate` from `start` to `end`.
179
+
180
+ **Returns:** `Temporal.PlainDate[]`
181
+
182
+ ```tsx
183
+ const dates = useTemporalRange(
184
+ Temporal.PlainDate.from('2026-07-01'),
185
+ Temporal.PlainDate.from('2026-07-07'),
186
+ );
187
+ ```
188
+
189
+ ---
190
+
191
+ ### `useTemporalWeek(date)`
192
+
193
+ All dates in the ISO week (Monday–Sunday) containing `date`.
194
+
195
+ **Returns:** `Temporal.PlainDate[]` (7 items)
196
+
197
+ ```tsx
198
+ const week = useTemporalWeek(Temporal.PlainDate.from('2026-07-05'));
199
+ ```
200
+
201
+ ---
202
+
203
+ ### `useTemporalMonth(date)`
204
+
205
+ All dates in the month of `date`.
206
+
207
+ **Returns:** `Temporal.PlainDate[]`
208
+
209
+ ```tsx
210
+ const days = useTemporalMonth(Temporal.PlainDate.from('2026-07-15'));
211
+ ```
212
+
213
+ ---
214
+
215
+ ### `useTemporalYear(date)`
216
+
217
+ First day of each month in the year of `date`.
218
+
219
+ **Returns:** `Temporal.PlainDate[]` (12 items)
220
+
221
+ ```tsx
222
+ const months = useTemporalYear(Temporal.PlainDate.from('2026-07-05'));
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Validation
228
+
229
+ ### `useTemporalCalendar(id)`
230
+
231
+ Validates a calendar identifier and returns the resolved calendar ID.
232
+
233
+ **Returns:** `string`
234
+
235
+ ```tsx
236
+ const id = useTemporalCalendar('iso8601'); // 'iso8601'
237
+ ```
238
+
239
+ ---
240
+
241
+ ### `useTemporalTimeZone(id)`
242
+
243
+ Validates an IANA time zone and returns the resolved time zone ID.
244
+
245
+ **Returns:** `string`
246
+
247
+ ```tsx
248
+ const id = useTemporalTimeZone('Europe/Madrid'); // 'Europe/Madrid'
249
+ ```
250
+
251
+ ---
252
+
253
+ ## Timers and scheduling
254
+
255
+ ### `useTemporalInterval(callback, duration)`
256
+
257
+ Runs `callback` repeatedly at the given `Temporal.DurationLike` interval. Uses a ref for the callback to avoid stale closures.
258
+
259
+ ```tsx
260
+ useTemporalInterval(() => refresh(), { seconds: 30 });
261
+ ```
262
+
263
+ ---
264
+
265
+ ### `useTemporalCountdown(target, options?)`
266
+
267
+ Seconds remaining until `target`. Returns `0` after the target passes.
268
+
269
+ | Option | Description |
270
+ | --- | --- |
271
+ | `intervalMs` | Tick interval (default `1000`) |
272
+ | `onComplete` | Called once when countdown reaches zero |
273
+
274
+ ### `useTemporalCountdownStatus(target, options?)`
275
+
276
+ Same as countdown but returns `{ seconds, isComplete }`.
277
+
278
+ ### `useTemporalElapsed(since, options?)`
279
+
280
+ Live seconds elapsed since `since` (0 if `since` is in the future).
281
+
282
+ ### `useTemporalStopwatch(start, options?)`
283
+
284
+ Returns `{ elapsed: Duration, seconds }` updating from `start`.
285
+
286
+ ### `useTemporalLocalDate(timeZone, options?)`
287
+
288
+ Today's `PlainDate` in the given IANA zone (default tick: 60s).
289
+
290
+ ---
291
+
292
+ ### `useTemporalSchedule(callback, instant, options?)`
293
+
294
+ Schedules `callback` once at `instant`. Runs immediately when already past unless `runIfPast: false`.
295
+
296
+ ```tsx
297
+ useTemporalSchedule(() => alert('Done!'), Temporal.Now.instant().add({ minutes: 5 }));
298
+ ```
299
+
300
+ ---
301
+
302
+ ### `useTemporalCompare(a, b)`
303
+
304
+ Memoized `Temporal.Instant.compare` or `PlainDate.compare`.
305
+
306
+ ### `useTemporalWithin(value, start, end)`
307
+
308
+ Inclusive range check (matching `Instant` or `PlainDate` operands).
309
+
310
+ ### `useTemporalAdd(value, duration)`
311
+
312
+ Memoized `.add(duration)` for `Instant` or `PlainDate`.
313
+
314
+ ---
315
+
316
+ ## Type exports
317
+
318
+ | Export | Description |
319
+ | --- | --- |
320
+ | `TemporalInstant` | `Temporal.Instant` |
321
+ | `TemporalPlainDate` | `Temporal.PlainDate` |
322
+ | `TemporalPlainTime` | `Temporal.PlainTime` |
323
+ | `TemporalPlainDateTime` | `Temporal.PlainDateTime` |
324
+ | `TemporalZonedDateTime` | `Temporal.ZonedDateTime` |
325
+ | `TemporalDuration` | `Temporal.Duration` |
326
+ | `TemporalDurationLike` | `Temporal.DurationLike` |
327
+ | `TemporalNamespace` | `typeof Temporal` |
328
+ | `UseTemporalNowOptions` | Options for `useTemporalNow` |
329
+ | `UseTemporalClockOptions` | Options for `useTemporalClock` / `useTemporalZonedNow` |
330
+
331
+ See [TypeScript](./typescript.md) for usage examples.
@@ -0,0 +1,111 @@
1
+ # Getting started
2
+
3
+ This guide walks you through installing **react-temporal** and using it in a React app.
4
+
5
+ ## Prerequisites
6
+
7
+ - Node.js **26** or later (for local development of this repo)
8
+ - React **17**, **18**, or **19**
9
+ - A bundler that supports ES modules (Vite, Next.js, Webpack 5, etc.)
10
+
11
+ ## 1. Install the package
12
+
13
+ ```bash
14
+ npm install @charlite/react-temporal
15
+ ```
16
+
17
+ ## 2. Add a polyfill (if needed)
18
+
19
+ Skip this step if you only target browsers with native Temporal (Chrome 144+, Firefox 139+, Edge 144+) **and** run Node.js 26+ on the server without needing a fallback.
20
+
21
+ For **Safari**, **Node.js < 26**, or mixed environments:
22
+
23
+ ```bash
24
+ # Recommended — smaller bundle (~20 KB gzip)
25
+ npm install temporal-polyfill
26
+
27
+ # Or the official reference implementation
28
+ npm install @js-temporal/polyfill
29
+ ```
30
+
31
+ Add the polyfill once at your app entry point:
32
+
33
+ ```ts
34
+ // main.tsx or _app.tsx
35
+ import 'temporal-polyfill/global';
36
+ ```
37
+
38
+ See the [Polyfill guide](./polyfill.md) for details.
39
+
40
+ ## 3. Use a hook
41
+
42
+ ```tsx
43
+ import { useTemporalNow } from '@charlite/react-temporal';
44
+
45
+ export function Clock() {
46
+ const now = useTemporalNow();
47
+ return <time dateTime={now.toString()}>{now.toLocaleString()}</time>;
48
+ }
49
+ ```
50
+
51
+ ## 4. Import Temporal types
52
+
53
+ You do not need a separate polyfill import for types or values — the package re-exports `Temporal`:
54
+
55
+ ```tsx
56
+ import { Temporal, useTemporalMonth } from '@charlite/react-temporal';
57
+
58
+ export function JulyCalendar() {
59
+ const dates = useTemporalMonth(Temporal.PlainDate.from('2026-07-01'));
60
+
61
+ return (
62
+ <ul>
63
+ {dates.map((date) => (
64
+ <li key={date.toString()}>{date.day}</li>
65
+ ))}
66
+ </ul>
67
+ );
68
+ }
69
+ ```
70
+
71
+ ## Common patterns
72
+
73
+ ### Live clock with time zone
74
+
75
+ ```tsx
76
+ import { useTemporalZonedNow } from '@charlite/react-temporal';
77
+
78
+ export function LocalClock({ timeZone }: { timeZone: string }) {
79
+ const now = useTemporalZonedNow(timeZone, { intervalMs: 1000 });
80
+ return <span>{now.toLocaleString()}</span>;
81
+ }
82
+ ```
83
+
84
+ ### Countdown timer
85
+
86
+ ```tsx
87
+ import { useTemporalCountdown, Temporal } from '@charlite/react-temporal';
88
+
89
+ export function Countdown({ iso }: { iso: string }) {
90
+ const target = Temporal.Instant.from(iso);
91
+ const seconds = useTemporalCountdown(target);
92
+ return <span>{seconds}s remaining</span>;
93
+ }
94
+ ```
95
+
96
+ ### Relative time label
97
+
98
+ ```tsx
99
+ import { useTemporalRelative, Temporal } from '@charlite/react-temporal';
100
+
101
+ export function RelativeLabel({ instant }: { instant: Temporal.Instant }) {
102
+ const label = useTemporalRelative(Temporal.Now.instant(), instant, 'en');
103
+ return <span>{label}</span>;
104
+ }
105
+ ```
106
+
107
+ ## Next steps
108
+
109
+ - [API reference](./api-reference.md) — full hook documentation
110
+ - [TypeScript](./typescript.md) — type exports and annotations
111
+ - [Examples](../examples/README.md) — one example per hook
@@ -0,0 +1,87 @@
1
+ # Installation
2
+
3
+ ## npm
4
+
5
+ ```bash
6
+ npm install @charlite/react-temporal
7
+ ```
8
+
9
+ ## yarn
10
+
11
+ ```bash
12
+ yarn add @charlite/react-temporal
13
+ ```
14
+
15
+ ## pnpm
16
+
17
+ ```bash
18
+ pnpm add @charlite/react-temporal
19
+ ```
20
+
21
+ ## Peer dependencies
22
+
23
+ `@charlite/react-temporal` expects React to already be installed in your project:
24
+
25
+ | Package | Supported versions |
26
+ | --- | --- |
27
+ | `react` | `^17.0.0 \|\| ^18.0.0 \|\| ^19.0.0` |
28
+ | `react-dom` | `^17.0.0 \|\| ^18.0.0 \|\| ^19.0.0` |
29
+
30
+ If npm warns about missing peers, install React explicitly:
31
+
32
+ ```bash
33
+ npm install react react-dom
34
+ ```
35
+
36
+ ## Optional polyfill dependencies
37
+
38
+ For environments without native Temporal, install **one** of:
39
+
40
+ | Package | Size (gzip) | Notes |
41
+ | --- | --- | --- |
42
+ | [`temporal-polyfill`](https://www.npmjs.com/package/temporal-polyfill) | ~20 KB | Recommended; installed automatically with `@charlite/react-temporal` |
43
+ | [`@js-temporal/polyfill`](https://www.npmjs.com/package/@js-temporal/polyfill) | ~44 KB | Official reference implementation (install manually if needed) |
44
+
45
+ ```bash
46
+ npm install temporal-polyfill
47
+ # or
48
+ npm install @js-temporal/polyfill
49
+ ```
50
+
51
+ ## Node.js version
52
+
53
+ Development and CI for this package require **Node.js 26+**. Your end-user app can run on older Node versions if you install a Temporal polyfill when native Temporal is missing.
54
+
55
+ ## Package exports
56
+
57
+ The package ships ESM and CommonJS builds:
58
+
59
+ ```json
60
+ {
61
+ "import": "./dist/index.esm.js",
62
+ "require": "./dist/index.cjs",
63
+ "types": "./dist/index.d.ts"
64
+ }
65
+ ```
66
+
67
+ Tree-shaking is supported (`"sideEffects": false`).
68
+
69
+ ## Bundler notes
70
+
71
+ ### Vite / CRA / Webpack
72
+
73
+ No special configuration required. Install a polyfill for SSR or test environments running in Node.js without native Temporal.
74
+
75
+ ### Next.js
76
+
77
+ Add the polyfill import in `instrumentation.ts` or your root layout for server components that use Temporal hooks on the server:
78
+
79
+ ```ts
80
+ import 'temporal-polyfill/global';
81
+ ```
82
+
83
+ Client components can use hooks normally.
84
+
85
+ ### Vitest
86
+
87
+ Ensure the test environment loads a polyfill before tests run (see root `vitest.setup.ts` in this repository).
@@ -0,0 +1,143 @@
1
+ # Migration guide
2
+
3
+ ## Upgrading to 1.1.0 from 1.0.0
4
+
5
+ ### Polyfill default
6
+
7
+ The built-in fallback is now **`temporal-polyfill`** instead of `@js-temporal/polyfill`. No app changes are required unless you relied on `@js-temporal/polyfill` being installed automatically — add it explicitly if you still need it for code outside `@charlite/react-temporal`.
8
+
9
+ ### New hooks (optional)
10
+
11
+ See [API reference](./api-reference.md) for `useTemporalFrom`, `useTemporalElapsed`, `useTemporalStopwatch`, `useTemporalLocalDate`, and related utilities.
12
+
13
+ ### Schedule behavior
14
+
15
+ `useTemporalSchedule` now invokes the callback immediately when the target instant is in the past (use `{ runIfPast: false }` to restore the old no-op behavior).
16
+
17
+ ---
18
+
19
+ ## Upgrading to 1.0.0 from 0.0.3
20
+
21
+ Version **1.0.0** aligns the repo with the 2026 Temporal ecosystem and modern tooling. Library APIs are unchanged; development and CI requirements changed.
22
+
23
+ ### Node.js
24
+
25
+ **Before:** Node.js 22+
26
+
27
+ **After:** Node.js **26+** (native Temporal in supported releases)
28
+
29
+ ```bash
30
+ nvm install 26
31
+ nvm use 26
32
+ ```
33
+
34
+ Update GitHub Actions / CI images to Node 26. End-user apps on older Node versions can still use **@charlite/react-temporal** with a Temporal polyfill.
35
+
36
+ ### Testing (contributors)
37
+
38
+ **Before:** Jest + `jest.config.json`
39
+
40
+ **After:** Vitest + `vitest.config.ts`
41
+
42
+ ```bash
43
+ npm test # vitest run
44
+ npm run test:watch
45
+ npm run test:coverage
46
+ ```
47
+
48
+ Timer mocks use `vi` instead of `jest`:
49
+
50
+ ```diff
51
+ - jest.useFakeTimers();
52
+ + vi.useFakeTimers();
53
+ ```
54
+
55
+ ### Linting (contributors)
56
+
57
+ **Before:** `.eslintrc.json`
58
+
59
+ **After:** `eslint.config.js` (ESLint 10 flat config)
60
+
61
+ ### Agent / knowledge layout
62
+
63
+ New OKF v0.2 bundle at [`knowledge/`](../knowledge/index.md) and [`AGENTS.md`](../AGENTS.md). No runtime impact on published npm code.
64
+
65
+ ---
66
+
67
+ ## Upgrading to 0.0.3 from 0.0.1 / 0.0.2
68
+
69
+ Version **0.0.3** modernizes the library for 2026 Temporal adoption. Most changes are additive; a few APIs changed behavior.
70
+
71
+ ### Install / dependency changes
72
+
73
+ **Before (0.0.2):**
74
+
75
+ ```bash
76
+ npm install @charlite/react-temporal
77
+ # react and react-dom were bundled as direct dependencies
78
+ # polyfill was bundled inside the package
79
+ ```
80
+
81
+ **After (0.0.3):**
82
+
83
+ ```bash
84
+ npm install @charlite/react-temporal
85
+ npm install temporal-polyfill # recommended for SSR / Safari / Node
86
+ ```
87
+
88
+ Ensure `react` and `react-dom` are in your app's `package.json` (peer dependencies).
89
+
90
+ ### Import changes
91
+
92
+ You can now import `Temporal` from the package instead of `@js-temporal/polyfill`:
93
+
94
+ ```diff
95
+ - import { useTemporalMonth } from '@charlite/react-temporal';
96
+ - import { Temporal } from '@js-temporal/polyfill';
97
+ + import { useTemporalMonth, Temporal } from '@charlite/react-temporal';
98
+ ```
99
+
100
+ ### `useTemporalFormat`
101
+
102
+ Signature changed to match `toLocaleString`:
103
+
104
+ ```diff
105
+ - useTemporalFormat(date, { dateStyle: 'full' })
106
+ + useTemporalFormat(date, undefined, { dateStyle: 'full' })
107
+ + useTemporalFormat(date, 'en-US', { dateStyle: 'full' })
108
+ ```
109
+
110
+ ### `useTemporalRelative`
111
+
112
+ Output format changed from manual strings (`"10 seconds ago"`) to `Intl.RelativeTimeFormat` (`"in 10 seconds"`). Pass a locale as the third argument:
113
+
114
+ ```diff
115
+ - useTemporalRelative(from, to)
116
+ + useTemporalRelative(from, to, 'en')
117
+ ```
118
+
119
+ ### `useTemporalDuration` / `useTemporalDiff`
120
+
121
+ These now use `until()` internally. Access total units with `.total()`:
122
+
123
+ ```diff
124
+ - diff.hours
125
+ + diff.total('hours')
126
+ ```
127
+
128
+ ### New hooks (optional adoption)
129
+
130
+ - `useTemporalClock({ intervalMs })` — configurable live clock
131
+ - `useTemporalZonedNow(timeZone, { intervalMs })` — zoned live clock
132
+ - `useTemporalNow({ intervalMs, timeZone })` — extended options
133
+
134
+ ### No action needed
135
+
136
+ These hooks work the same way, with improved internals:
137
+
138
+ - `useTemporalParse`
139
+ - `useTemporalRange`
140
+ - `useTemporalWeek` / `useTemporalMonth` / `useTemporalYear`
141
+ - `useTemporalCalendar` / `useTemporalTimeZone`
142
+ - `useTemporalInterval`
143
+ - `useTemporalSchedule`