@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.
- package/CHANGELOG.md +106 -0
- package/LICENSE +21 -0
- package/README.md +178 -2
- package/dist/hooks/useTemporalAdd.d.ts +7 -0
- package/dist/hooks/useTemporalCalendar.d.ts +4 -0
- package/dist/hooks/useTemporalClock.d.ts +5 -0
- package/dist/hooks/useTemporalCompare.d.ts +7 -0
- package/dist/hooks/useTemporalCountdown.d.ts +5 -0
- package/dist/hooks/useTemporalCountdownStatus.d.ts +11 -0
- package/dist/hooks/useTemporalDiff.d.ts +5 -0
- package/dist/hooks/useTemporalDuration.d.ts +5 -0
- package/dist/hooks/useTemporalElapsed.d.ts +5 -0
- package/dist/hooks/useTemporalFormat.d.ts +7 -0
- package/dist/hooks/useTemporalFrom.d.ts +5 -0
- package/dist/hooks/useTemporalInterval.d.ts +6 -0
- package/dist/hooks/useTemporalLocalDate.d.ts +5 -0
- package/dist/hooks/useTemporalMonth.d.ts +5 -0
- package/dist/hooks/useTemporalNow.d.ts +6 -0
- package/dist/hooks/useTemporalParse.d.ts +3 -0
- package/dist/hooks/useTemporalRange.d.ts +5 -0
- package/dist/hooks/useTemporalRelative.d.ts +6 -0
- package/dist/hooks/useTemporalSafeParse.d.ts +5 -0
- package/dist/hooks/useTemporalSchedule.d.ts +9 -0
- package/dist/hooks/useTemporalStopwatch.d.ts +11 -0
- package/dist/hooks/useTemporalTimeZone.d.ts +4 -0
- package/dist/hooks/useTemporalWeek.d.ts +5 -0
- package/dist/hooks/useTemporalWithin.d.ts +5 -0
- package/dist/hooks/useTemporalYear.d.ts +5 -0
- package/dist/hooks/useTemporalZonedNow.d.ts +6 -0
- package/dist/index.cjs +507 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.esm.js +477 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/internal/durationKey.d.ts +5 -0
- package/dist/internal/useLatest.d.ts +2 -0
- package/dist/internal/useTemporalTicker.d.ts +11 -0
- package/dist/temporal.d.ts +20 -0
- package/dist/types.d.ts +35 -0
- package/dist/utils/formatRelative.d.ts +6 -0
- package/dist/utils/parseTemporal.d.ts +2 -0
- package/docs/README.md +53 -0
- package/docs/api-reference.md +331 -0
- package/docs/getting-started.md +111 -0
- package/docs/installation.md +87 -0
- package/docs/migration.md +143 -0
- package/docs/polyfill.md +89 -0
- package/docs/typescript.md +86 -0
- package/package.json +117 -4
package/docs/polyfill.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Polyfill guide
|
|
2
|
+
|
|
3
|
+
**react-temporal** uses native `Temporal` when available and falls back to a polyfill automatically.
|
|
4
|
+
|
|
5
|
+
## How runtime resolution works
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { getTemporal, Temporal } from '@charlite/react-temporal';
|
|
9
|
+
|
|
10
|
+
// getTemporal() checks globalThis.Temporal first, then falls back to temporal-polyfill
|
|
11
|
+
const T = getTemporal();
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Resolution order:
|
|
15
|
+
|
|
16
|
+
1. **`globalThis.Temporal`** — used when the host provides native Temporal
|
|
17
|
+
2. **`temporal-polyfill`** — loaded when native Temporal is unavailable (optional dependency)
|
|
18
|
+
|
|
19
|
+
You rarely need to call `getTemporal()` directly; hooks use it internally.
|
|
20
|
+
|
|
21
|
+
## Browser support (2026)
|
|
22
|
+
|
|
23
|
+
| Browser | Native Temporal | Action |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| Chrome 144+ | Yes | No polyfill needed |
|
|
26
|
+
| Firefox 139+ | Yes | No polyfill needed |
|
|
27
|
+
| Edge 144+ | Yes | No polyfill needed |
|
|
28
|
+
| Safari | Partial / preview | Use a polyfill |
|
|
29
|
+
| Older browsers | No | Use a polyfill |
|
|
30
|
+
|
|
31
|
+
## Node.js
|
|
32
|
+
|
|
33
|
+
**Node.js 26+** ships Temporal by default in current releases. Older Node versions and some test environments (for example jsdom) still need a polyfill for SSR and unit tests:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install temporal-polyfill
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import 'temporal-polyfill/global';
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Choosing a polyfill
|
|
44
|
+
|
|
45
|
+
### temporal-polyfill (recommended)
|
|
46
|
+
|
|
47
|
+
- Smaller bundle (~20 KB gzip)
|
|
48
|
+
- Maintained by the FullCalendar team
|
|
49
|
+
- Near-perfect TC39 spec compliance
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import 'temporal-polyfill/global';
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### @js-temporal/polyfill
|
|
56
|
+
|
|
57
|
+
- Official reference implementation from Temporal proposal champions
|
|
58
|
+
- Larger (~44 KB gzip)
|
|
59
|
+
- Installed automatically as an optional dependency of `@charlite/react-temporal`
|
|
60
|
+
|
|
61
|
+
No global import is required — the package loads it when native Temporal is missing.
|
|
62
|
+
|
|
63
|
+
## SSR checklist
|
|
64
|
+
|
|
65
|
+
1. Install `temporal-polyfill` or ensure `@js-temporal/polyfill` is available
|
|
66
|
+
2. Import the polyfill at the server entry point **before** any hook runs
|
|
67
|
+
3. Verify your SSR bundle does not tree-shake away the polyfill import
|
|
68
|
+
|
|
69
|
+
## Testing
|
|
70
|
+
|
|
71
|
+
In **Vitest** with `jsdom`, native Temporal is typically unavailable. This library imports `temporal-polyfill` inside `src/temporal.ts`, so tests do not need to assign `globalThis.Temporal` unless your app code reads the global directly.
|
|
72
|
+
|
|
73
|
+
## FAQ
|
|
74
|
+
|
|
75
|
+
**Do I need to import Temporal separately?**
|
|
76
|
+
|
|
77
|
+
No. Import `Temporal` from `@charlite/react-temporal`:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { Temporal } from '@charlite/react-temporal';
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Can I use only native Temporal and skip the polyfill?**
|
|
84
|
+
|
|
85
|
+
Yes, if you only support browsers with native Temporal and run Node.js 26+ on the server. Remove optional polyfill dependencies and ensure your build does not resolve `@js-temporal/polyfill`.
|
|
86
|
+
|
|
87
|
+
**Does the polyfill get bundled into my app?**
|
|
88
|
+
|
|
89
|
+
No. The polyfill is an external dependency — your bundler includes it only if you import it (or if the fallback path resolves at runtime in Node).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# TypeScript
|
|
2
|
+
|
|
3
|
+
**react-temporal** is written in TypeScript and ships `.d.ts` declarations with the package.
|
|
4
|
+
|
|
5
|
+
## Importing types
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import type {
|
|
9
|
+
TemporalInstant,
|
|
10
|
+
TemporalPlainDate,
|
|
11
|
+
TemporalPlainDateTime,
|
|
12
|
+
TemporalZonedDateTime,
|
|
13
|
+
TemporalDuration,
|
|
14
|
+
TemporalDurationLike,
|
|
15
|
+
UseTemporalNowOptions,
|
|
16
|
+
UseTemporalClockOptions,
|
|
17
|
+
TemporalNamespace,
|
|
18
|
+
} from '@charlite/react-temporal';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Importing values and types together
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { Temporal, useTemporalNow } from '@charlite/react-temporal';
|
|
25
|
+
import type { TemporalInstant } from '@charlite/react-temporal';
|
|
26
|
+
|
|
27
|
+
function logInstant(instant: TemporalInstant) {
|
|
28
|
+
console.log(instant.toString());
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Hook return types
|
|
33
|
+
|
|
34
|
+
| Hook | Return type |
|
|
35
|
+
| --- | --- |
|
|
36
|
+
| `useTemporalNow()` | `TemporalInstant` |
|
|
37
|
+
| `useTemporalNow({ timeZone })` | `TemporalZonedDateTime` |
|
|
38
|
+
| `useTemporalClock()` | `TemporalInstant` |
|
|
39
|
+
| `useTemporalZonedNow(tz)` | `TemporalZonedDateTime` |
|
|
40
|
+
| `useTemporalDuration(a, b)` | `TemporalDuration` |
|
|
41
|
+
| `useTemporalDiff(a, b)` | `TemporalDuration` |
|
|
42
|
+
| `useTemporalParse(iso)` | `TemporalInstant` |
|
|
43
|
+
| `useTemporalCountdown(target)` | `number` |
|
|
44
|
+
| `useTemporalRelative(...)` | `string` |
|
|
45
|
+
| `useTemporalFormat(obj, ...)` | `string` |
|
|
46
|
+
| `useTemporalCalendar(id)` | `string` |
|
|
47
|
+
| `useTemporalTimeZone(id)` | `string` |
|
|
48
|
+
| `useTemporalRange(start, end)` | `TemporalPlainDate[]` |
|
|
49
|
+
| `useTemporalWeek(date)` | `TemporalPlainDate[]` |
|
|
50
|
+
| `useTemporalMonth(date)` | `TemporalPlainDate[]` |
|
|
51
|
+
| `useTemporalYear(date)` | `TemporalPlainDate[]` |
|
|
52
|
+
|
|
53
|
+
## Typing component props
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import type { TemporalInstant, TemporalPlainDate } from '@charlite/react-temporal';
|
|
57
|
+
|
|
58
|
+
interface EventCardProps {
|
|
59
|
+
startsAt: TemporalInstant;
|
|
60
|
+
date: TemporalPlainDate;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function EventCard({ startsAt, date }: EventCardProps) {
|
|
64
|
+
// ...
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## `TemporalNamespace`
|
|
69
|
+
|
|
70
|
+
Use this when you need the type of the full `Temporal` namespace:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import type { TemporalNamespace } from '@charlite/react-temporal';
|
|
74
|
+
|
|
75
|
+
function useTemporalSafe(): TemporalNamespace {
|
|
76
|
+
return getTemporal();
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Strict mode
|
|
81
|
+
|
|
82
|
+
The package is built with `strict: true`. All hooks use explicit parameter and return types.
|
|
83
|
+
|
|
84
|
+
## Source of Temporal types
|
|
85
|
+
|
|
86
|
+
Runtime types are sourced from `temporal-polyfill`, which tracks the TC39 Temporal specification. Native `Temporal` in modern browsers is structurally compatible at runtime.
|
package/package.json
CHANGED
|
@@ -1,6 +1,119 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@charlite/react-temporal",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.1.1",
|
|
4
|
+
"description": "React hooks for date and time using the JavaScript Temporal API — native in modern browsers and Node.js 26+, polyfill-ready elsewhere.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "dist/index.cjs",
|
|
8
|
+
"module": "dist/index.esm.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.esm.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"docs",
|
|
20
|
+
"README.md",
|
|
21
|
+
"LICENSE",
|
|
22
|
+
"CHANGELOG.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "rollup -c",
|
|
26
|
+
"test": "vitest run",
|
|
27
|
+
"test:watch": "vitest",
|
|
28
|
+
"test:coverage": "vitest run --coverage",
|
|
29
|
+
"lint": "eslint \"src/**/*.{ts,tsx}\"",
|
|
30
|
+
"lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
|
|
31
|
+
"format": "prettier --write \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
32
|
+
"format:check": "prettier --check \"src/**/*.{ts,tsx,js,jsx,json,md}\"",
|
|
33
|
+
"typecheck": "tsc --noEmit",
|
|
34
|
+
"dev": "pwsh -ExecutionPolicy Bypass -File scripts/dev.ps1",
|
|
35
|
+
"dev:test": "pwsh -ExecutionPolicy Bypass -File scripts/dev.ps1 -Task test",
|
|
36
|
+
"dev:build": "pwsh -ExecutionPolicy Bypass -File scripts/dev.ps1 -Task build",
|
|
37
|
+
"dev:lint": "pwsh -ExecutionPolicy Bypass -File scripts/dev.ps1 -Task lint",
|
|
38
|
+
"dev:typecheck": "pwsh -ExecutionPolicy Bypass -File scripts/dev.ps1 -Task typecheck",
|
|
39
|
+
"prepublishOnly": "npm run build && npm run test && npm run lint && npm run typecheck",
|
|
40
|
+
"setup": "node scripts/setup.js",
|
|
41
|
+
"setup:ps": "pwsh -ExecutionPolicy Bypass -File scripts/setup.ps1",
|
|
42
|
+
"release": "node scripts/release.js patch",
|
|
43
|
+
"release:minor": "node scripts/release.js minor",
|
|
44
|
+
"release:major": "node scripts/release.js major",
|
|
45
|
+
"release:ps": "pwsh -ExecutionPolicy Bypass -File scripts/release.ps1",
|
|
46
|
+
"release:ps:minor": "pwsh -ExecutionPolicy Bypass -File scripts/release.ps1 -VersionType minor",
|
|
47
|
+
"release:ps:major": "pwsh -ExecutionPolicy Bypass -File scripts/release.ps1 -VersionType major"
|
|
48
|
+
},
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/charlite/react-temporal.git"
|
|
52
|
+
},
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/charlite/react-temporal#readme",
|
|
57
|
+
"bugs": {
|
|
58
|
+
"url": "https://github.com/charlite/react-temporal/issues"
|
|
59
|
+
},
|
|
60
|
+
"keywords": [
|
|
61
|
+
"react",
|
|
62
|
+
"react-hooks",
|
|
63
|
+
"temporal",
|
|
64
|
+
"temporal-api",
|
|
65
|
+
"date",
|
|
66
|
+
"time",
|
|
67
|
+
"calendar",
|
|
68
|
+
"timezone",
|
|
69
|
+
"hooks",
|
|
70
|
+
"datetime",
|
|
71
|
+
"javascript",
|
|
72
|
+
"intl",
|
|
73
|
+
"polyfill",
|
|
74
|
+
"okf"
|
|
75
|
+
],
|
|
76
|
+
"author": {
|
|
77
|
+
"name": "charlite",
|
|
78
|
+
"email": "38315638+charlite@users.noreply.github.com",
|
|
79
|
+
"url": "https://github.com/charlite"
|
|
80
|
+
},
|
|
81
|
+
"license": "MIT",
|
|
82
|
+
"engines": {
|
|
83
|
+
"node": ">=26.0.0"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@eslint/js": "^10.0.1",
|
|
87
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
88
|
+
"@testing-library/react": "^16.3.0",
|
|
89
|
+
"@types/react": "^19.2.0",
|
|
90
|
+
"@types/react-dom": "^19.2.0",
|
|
91
|
+
"@vitest/coverage-v8": "^5.0.3",
|
|
92
|
+
"eslint": "^10.12.0",
|
|
93
|
+
"jsdom": "^27.0.0",
|
|
94
|
+
"prettier": "^3.6.2",
|
|
95
|
+
"react": "^19.2.0",
|
|
96
|
+
"react-dom": "^19.2.0",
|
|
97
|
+
"rollup": "^4.52.0",
|
|
98
|
+
"tslib": "^2.8.1",
|
|
99
|
+
"typescript": "^5.9.3",
|
|
100
|
+
"temporal-polyfill": "^1.0.5",
|
|
101
|
+
"typescript-eslint": "^8.46.0",
|
|
102
|
+
"vitest": "^5.0.3"
|
|
103
|
+
},
|
|
104
|
+
"peerDependencies": {
|
|
105
|
+
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
106
|
+
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
|
|
107
|
+
},
|
|
108
|
+
"peerDependenciesMeta": {
|
|
109
|
+
"@js-temporal/polyfill": {
|
|
110
|
+
"optional": true
|
|
111
|
+
},
|
|
112
|
+
"temporal-polyfill": {
|
|
113
|
+
"optional": true
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
"optionalDependencies": {
|
|
117
|
+
"temporal-polyfill": "^1.0.5"
|
|
118
|
+
}
|
|
119
|
+
}
|