@charlite/react-temporal 0.0.0-stage → 1.1.0

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 +94 -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 -3
@@ -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 '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 `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 `react-temporal`:
78
+
79
+ ```ts
80
+ import { Temporal } from '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 'react-temporal';
19
+ ```
20
+
21
+ ## Importing values and types together
22
+
23
+ ```ts
24
+ import { Temporal, useTemporalNow } from 'react-temporal';
25
+ import type { TemporalInstant } from '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 '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 '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,120 @@
1
1
  {
2
2
  "name": "@charlite/react-temporal",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.1.0",
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
+ "registry": "https://registry.npmjs.org"
56
+ },
57
+ "homepage": "https://github.com/charlite/react-temporal#readme",
58
+ "bugs": {
59
+ "url": "https://github.com/charlite/react-temporal/issues"
60
+ },
61
+ "keywords": [
62
+ "react",
63
+ "react-hooks",
64
+ "temporal",
65
+ "temporal-api",
66
+ "date",
67
+ "time",
68
+ "calendar",
69
+ "timezone",
70
+ "hooks",
71
+ "datetime",
72
+ "javascript",
73
+ "intl",
74
+ "polyfill",
75
+ "okf"
76
+ ],
77
+ "author": {
78
+ "name": "charlite",
79
+ "email": "38315638+charlite@users.noreply.github.com",
80
+ "url": "https://github.com/charlite"
81
+ },
82
+ "license": "MIT",
83
+ "engines": {
84
+ "node": ">=26.0.0"
85
+ },
86
+ "devDependencies": {
87
+ "@eslint/js": "^10.0.1",
88
+ "@rollup/plugin-typescript": "^12.3.0",
89
+ "@testing-library/react": "^16.3.0",
90
+ "@types/react": "^19.2.0",
91
+ "@types/react-dom": "^19.2.0",
92
+ "@vitest/coverage-v8": "^5.0.3",
93
+ "eslint": "^10.12.0",
94
+ "jsdom": "^27.0.0",
95
+ "prettier": "^3.6.2",
96
+ "react": "^19.2.0",
97
+ "react-dom": "^19.2.0",
98
+ "rollup": "^4.52.0",
99
+ "tslib": "^2.8.1",
100
+ "typescript": "^5.9.3",
101
+ "temporal-polyfill": "^1.0.5",
102
+ "typescript-eslint": "^8.46.0",
103
+ "vitest": "^5.0.3"
104
+ },
105
+ "peerDependencies": {
106
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0",
107
+ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
108
+ },
109
+ "peerDependenciesMeta": {
110
+ "@js-temporal/polyfill": {
111
+ "optional": true
112
+ },
113
+ "temporal-polyfill": {
114
+ "optional": true
115
+ }
116
+ },
117
+ "optionalDependencies": {
118
+ "temporal-polyfill": "^1.0.5"
119
+ }
6
120
  }