chrona-react 0.3.5 → 0.3.6
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/AGENTS.md +47 -10
- package/README.md +8 -2
- package/dist/date-field.d.ts +2 -2
- package/dist/date-picker.d.ts +1 -1
- package/dist/time-field.d.ts +2 -2
- package/package.json +2 -2
package/AGENTS.md
CHANGED
|
@@ -11,10 +11,11 @@ https://github.com/devlinduldulao/chrona#readme
|
|
|
11
11
|
`temporal-spec/global`, so `Temporal.PlainDate` resolves as an ambient global
|
|
12
12
|
in any file that imports from Chrona. A file that uses Temporal types without
|
|
13
13
|
importing Chrona needs `import "temporal-spec/global"` of its own.
|
|
14
|
-
3. **Server Components.**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
3. **Server Components.** The package carries a `"use client"` directive, so
|
|
15
|
+
*importing* it from a Server Component is safe; the module that **renders**
|
|
16
|
+
it still has to be a client module. The polyfill import is a side effect and
|
|
17
|
+
must reach the client bundle — put it at the top of a `"use client"` module
|
|
18
|
+
that always loads (a providers file), not in a Server Component.
|
|
18
19
|
4. **SSR module init.** The providers import does not order Node module
|
|
19
20
|
evaluation. If another `"use client"` file reads `Temporal` at module scope
|
|
20
21
|
(`const reference = Temporal.PlainDate.from(...)` at the top of `page.tsx`),
|
|
@@ -49,17 +50,53 @@ what the field and calendar open on before a value exists.
|
|
|
49
50
|
- Typed digits are literal, stepping clamps. 29 February is reachable before the
|
|
50
51
|
year is typed; a finished date that cannot exist reports
|
|
51
52
|
`onInvalid("nonexistent")` rather than clamping to the 28th.
|
|
52
|
-
-
|
|
53
|
-
|
|
53
|
+
- A segment is a draft until its last digit lands, and a draft reports nothing:
|
|
54
|
+
typing `2026` calls `onChange` once with that year, not four times through
|
|
55
|
+
2, 20 and 202. Blur settles a draft literally — `20` becomes the year 20.
|
|
54
56
|
- Empty fields are `null`. Partial drafts stay internal; `onChange` only sees
|
|
55
57
|
complete, valid values.
|
|
58
|
+
- Segments accept input from soft keyboards, which send no usable `key` and
|
|
59
|
+
often arrive as a composition. The AM/PM segment also accepts its locale's own
|
|
60
|
+
label, so it can be set without a hardware keyboard — but it has no pointer
|
|
61
|
+
affordance, so leave readers a keyboard path to it.
|
|
62
|
+
- A segment announces `aria-valuemin`/`aria-valuemax` narrowed to
|
|
63
|
+
`minValue`/`maxValue` where that is certain, while still accepting
|
|
64
|
+
out-of-range input so it can be reported rather than silently refused.
|
|
56
65
|
|
|
57
66
|
## SSR determinism
|
|
58
67
|
|
|
59
|
-
Pass the same reference date, value, locale
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
68
|
+
Pass the same reference date, value, locale and `timeZone` on server and client.
|
|
69
|
+
|
|
70
|
+
**`today` is resolved on the client, not at render time.** A server cannot know
|
|
71
|
+
the reader's day — it may be in another zone, and a prerendered page can be
|
|
72
|
+
served days after it was built — so `data-today` and `aria-current="date"` are
|
|
73
|
+
absent from the server HTML and appear just after hydration. Pass `today`
|
|
74
|
+
yourself to put the marker in the server HTML.
|
|
75
|
+
|
|
76
|
+
**Give every server-rendered calendar a reference date.** With no `value`,
|
|
77
|
+
`defaultValue`, `focusedValue`, `defaultFocusedValue` or `placeholderValue`, a
|
|
78
|
+
calendar opens on whichever day the renderer thinks it is, and React will not
|
|
79
|
+
patch up the mismatch that follows. A development build warns once about this
|
|
80
|
+
from the server render.
|
|
81
|
+
|
|
82
|
+
**Keep values in `iso8601` unless the server is known to manage more.** Node's
|
|
83
|
+
native Temporal cannot do arithmetic on other calendars — `gregory` included —
|
|
84
|
+
so `calendar="gregory"`, or a value carrying that calendar, renders in the
|
|
85
|
+
browser and raises `CALENDAR_UNSUPPORTED` during SSR.
|
|
86
|
+
|
|
87
|
+
Segment literals are normalized (U+202F and U+00A0 collapse to a plain space),
|
|
88
|
+
so a 12-hour `TimeField` hydrates cleanly across differing ICU versions;
|
|
89
|
+
`hourCycle="h23"` is not a requirement. Two things that normalization cannot
|
|
90
|
+
cover: dates before 1582, which ICU renders through the Julian calendar and
|
|
91
|
+
runtimes disagree about, and `dateStyle` in `ja-JP`/`zh-CN`, where V8 and
|
|
92
|
+
`temporal-polyfill` differ — which only shows when the two sides of a page run
|
|
93
|
+
different implementations.
|
|
94
|
+
|
|
95
|
+
## Styling
|
|
96
|
+
|
|
97
|
+
No CSS ships. Style through `data-scope`, `data-part` and state attributes.
|
|
98
|
+
`docs/starter.css` in the repository is a copy-and-edit stylesheet covering every
|
|
99
|
+
part these components emit.
|
|
63
100
|
|
|
64
101
|
## Not implemented
|
|
65
102
|
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@ values, no free-form date parsing, and no CSS — you own every pixel.
|
|
|
6
6
|
Part of [Chrona](https://github.com/devlinduldulao/chrona). Built on
|
|
7
7
|
[`chrona-core`](https://www.npmjs.com/package/chrona-core).
|
|
8
8
|
|
|
9
|
-
> **Status: experimental 0.3.
|
|
9
|
+
> **Status: experimental 0.3.6.** Public APIs and styling attributes are not
|
|
10
10
|
> frozen for v1. 0.3.0 changes when a field reports a value and leaves `today`
|
|
11
11
|
> to the client; 0.2.0 changed the Calendar cell anatomy. See the
|
|
12
12
|
> [changelog](./CHANGELOG.md). Automated axe checks pass, but no screen-reader
|
|
@@ -120,7 +120,7 @@ return focus to the trigger.
|
|
|
120
120
|
| `DateField` | `chrona-react/date-field` | Locale-ordered segments; ISO/Gregorian years 1–9999 |
|
|
121
121
|
| `TimeField` | `chrona-react/time-field` | `hourCycle` h11/h12/h23/h24, minute or second granularity |
|
|
122
122
|
| `DatePicker` | `chrona-react/date-picker` | Field plus calendar in a native dialog |
|
|
123
|
-
| `ChronaProvider` | — | Ambient `locale` and `
|
|
123
|
+
| `ChronaProvider` | — | Ambient `locale`, `timeZone`, `dir` and `translations` |
|
|
124
124
|
|
|
125
125
|
A barrel export is also available. Matching hooks — `useCalendar`,
|
|
126
126
|
`useRangeCalendar`, `useDateField`, `useTimeField`, `useDatePicker` — expose
|
|
@@ -154,6 +154,12 @@ Hidden inputs serialize with `.toString()` and are never read back.
|
|
|
154
154
|
inputs do not take part in browser constraint validation — validate required,
|
|
155
155
|
incomplete, or invalid values in your form layer before submission.
|
|
156
156
|
|
|
157
|
+
Every failure is a `ChronaError` carrying a stable `code`, listed in
|
|
158
|
+
[`chrona-core`'s README](https://www.npmjs.com/package/chrona-core#errors).
|
|
159
|
+
`TEMPORAL_MISSING`, `TEMPORAL_MISMATCH` and `CALENDAR_UNSUPPORTED` are the three
|
|
160
|
+
worth handling: each means the page's Temporal runtime is not what the component
|
|
161
|
+
needs, and each usually shows up only on the server.
|
|
162
|
+
|
|
157
163
|
## With shadcn/ui
|
|
158
164
|
|
|
159
165
|
Chrona does not replace shadcn. Keep `Button`, `Popover`, `Label`, and `cn`.
|
package/dist/date-field.d.ts
CHANGED
|
@@ -5,14 +5,14 @@ import { F as FieldProps } from './field-DayikvR6.js';
|
|
|
5
5
|
|
|
6
6
|
type DateFieldProps = FieldProps<"date">;
|
|
7
7
|
declare const DateField: {
|
|
8
|
-
Root: ({ children, asChild, className, style, ...props }: FieldProps<"date"> & Pick<PartProps, "
|
|
8
|
+
Root: ({ children, asChild, className, style, ...props }: FieldProps<"date"> & Pick<PartProps, "className" | "style" | "children" | "asChild">) => React.JSX.Element;
|
|
9
9
|
Label: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
|
|
10
10
|
asChild?: boolean;
|
|
11
11
|
} & React.RefAttributes<HTMLElement>>;
|
|
12
12
|
Field: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
|
|
13
13
|
asChild?: boolean;
|
|
14
14
|
} & React.RefAttributes<HTMLElement>>;
|
|
15
|
-
Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "
|
|
15
|
+
Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultValue" | "children" | "onChange" | "type" | "value"> & {
|
|
16
16
|
type: chrona_core.SegmentType;
|
|
17
17
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
18
18
|
HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
|
package/dist/date-picker.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ declare const DatePicker: {
|
|
|
47
47
|
Field: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
|
|
48
48
|
asChild?: boolean;
|
|
49
49
|
} & React.RefAttributes<HTMLElement>>;
|
|
50
|
-
Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "
|
|
50
|
+
Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultValue" | "children" | "onChange" | "type" | "value"> & {
|
|
51
51
|
type: chrona_core.SegmentType;
|
|
52
52
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
53
53
|
HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
|
package/dist/time-field.d.ts
CHANGED
|
@@ -5,14 +5,14 @@ import { F as FieldProps } from './field-DayikvR6.js';
|
|
|
5
5
|
|
|
6
6
|
type TimeFieldProps = FieldProps<"time">;
|
|
7
7
|
declare const TimeField: {
|
|
8
|
-
Root: ({ children, asChild, className, style, ...props }: FieldProps<"time"> & Pick<PartProps, "
|
|
8
|
+
Root: ({ children, asChild, className, style, ...props }: FieldProps<"time"> & Pick<PartProps, "className" | "style" | "children" | "asChild">) => React.JSX.Element;
|
|
9
9
|
Label: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
|
|
10
10
|
asChild?: boolean;
|
|
11
11
|
} & React.RefAttributes<HTMLElement>>;
|
|
12
12
|
Field: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
|
|
13
13
|
asChild?: boolean;
|
|
14
14
|
} & React.RefAttributes<HTMLElement>>;
|
|
15
|
-
Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "
|
|
15
|
+
Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultValue" | "children" | "onChange" | "type" | "value"> & {
|
|
16
16
|
type: chrona_core.SegmentType;
|
|
17
17
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
18
18
|
HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrona-react",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Headless Temporal-native React date and time primitives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
}
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
|
-
"chrona-core": "^0.3.
|
|
64
|
+
"chrona-core": "^0.3.6"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
67
|
"react": ">=18.0.0",
|