chrona-react 0.1.0 → 0.2.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/AGENTS.md +68 -0
- package/README.md +78 -6
- package/dist/calendar.d.ts +21 -5
- package/dist/calendar.js +1 -1
- package/dist/{chunk-ZN4FZDUQ.js → chunk-2GZMCFFY.js} +2 -2
- package/dist/{chunk-VSD2IX3U.js → chunk-JNQXKZO3.js} +3 -2
- package/dist/chunk-JNQXKZO3.js.map +1 -0
- package/dist/{chunk-XNVORQQ5.js → chunk-QQANBK5G.js} +8 -4
- package/dist/chunk-QQANBK5G.js.map +1 -0
- package/dist/{chunk-EFN32TNK.js → chunk-RCWVBOO6.js} +22 -13
- package/dist/chunk-RCWVBOO6.js.map +1 -0
- package/dist/{chunk-6QRNDYNF.js → chunk-ROJQDSGQ.js} +2 -2
- package/dist/{chunk-5426MN2K.js → chunk-U4LLSRIH.js} +16 -8
- package/dist/chunk-U4LLSRIH.js.map +1 -0
- package/dist/date-field.d.ts +2 -2
- package/dist/date-field.js +2 -2
- package/dist/date-picker.d.ts +2 -2
- package/dist/date-picker.js +4 -4
- package/dist/{field-CQjoX8QG.d.ts → field-DayikvR6.d.ts} +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/range-calendar.d.ts +50 -11
- package/dist/range-calendar.js +2 -2
- package/dist/time-field.d.ts +2 -2
- package/dist/time-field.js +2 -2
- package/package.json +3 -2
- package/dist/chunk-5426MN2K.js.map +0 -1
- package/dist/chunk-EFN32TNK.js.map +0 -1
- package/dist/chunk-VSD2IX3U.js.map +0 -1
- package/dist/chunk-XNVORQQ5.js.map +0 -1
- /package/dist/{chunk-ZN4FZDUQ.js.map → chunk-2GZMCFFY.js.map} +0 -0
- /package/dist/{chunk-6QRNDYNF.js.map → chunk-ROJQDSGQ.js.map} +0 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# chrona-react for agents
|
|
2
|
+
|
|
3
|
+
Headless React date/time primitives over the Temporal proposal. Full docs:
|
|
4
|
+
https://github.com/devlinduldulao/chrona#readme
|
|
5
|
+
|
|
6
|
+
## Setup that is easy to get wrong
|
|
7
|
+
|
|
8
|
+
1. **Runtime.** Chrona reads `globalThis.Temporal` and never installs it. Where
|
|
9
|
+
Temporal is not native, `import "temporal-polyfill/global"` before rendering.
|
|
10
|
+
2. **Types.** No extra import is needed. `chrona-core`'s declarations reference
|
|
11
|
+
`temporal-spec/global`, so `Temporal.PlainDate` resolves as an ambient global
|
|
12
|
+
in any file that imports from Chrona. A file that uses Temporal types without
|
|
13
|
+
importing Chrona needs `import "temporal-spec/global"` of its own.
|
|
14
|
+
3. **Server Components.** These components hold state: mark their module
|
|
15
|
+
`"use client"`. The polyfill import is a side effect, so it must reach the
|
|
16
|
+
client bundle — put it at the top of a `"use client"` module that always
|
|
17
|
+
loads (a providers file), not in a Server Component. That covers hydration.
|
|
18
|
+
4. **SSR module init.** The providers import does not order Node module
|
|
19
|
+
evaluation. If another `"use client"` file reads `Temporal` at module scope
|
|
20
|
+
(`const reference = Temporal.PlainDate.from(...)` at the top of `page.tsx`),
|
|
21
|
+
Next.js may evaluate that file during SSR before `providers.tsx` has run and
|
|
22
|
+
throw `ReferenceError: Temporal is not defined`. Import the polyfill at the
|
|
23
|
+
top of *that* file too, or move the call inside the component body.
|
|
24
|
+
5. **Values are Temporal objects.** Strings and `Date` are rejected with a
|
|
25
|
+
`ChronaError`; there is no parsing layer.
|
|
26
|
+
|
|
27
|
+
## Anatomy
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<Calendar.Root value={value} onChange={setValue} placeholderValue={reference}>
|
|
31
|
+
<Calendar.Header><Calendar.PrevButton /><Calendar.Heading /><Calendar.NextButton /></Calendar.Header>
|
|
32
|
+
<Calendar.Grid><Calendar.GridHeader /><Calendar.GridBody /></Calendar.Grid>
|
|
33
|
+
</Calendar.Root>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`Calendar.Cell` is the `role="gridcell"` wrapper and `Calendar.CellTrigger` the
|
|
37
|
+
button inside it; a cell with no children renders its trigger. Style the
|
|
38
|
+
interactive element as `[data-part="cell-trigger"]`. Paging buttons render a
|
|
39
|
+
default chevron when given no children, and `DatePicker.Trigger` a calendar
|
|
40
|
+
glyph.
|
|
41
|
+
|
|
42
|
+
`DatePicker` takes every `DateField` prop, `placeholderValue` included — it is
|
|
43
|
+
what the field and calendar open on before a value exists.
|
|
44
|
+
|
|
45
|
+
## Field behavior
|
|
46
|
+
|
|
47
|
+
- Blank segments read `mm/dd/yyyy` and `hh:mm`; filled numeric segments other
|
|
48
|
+
than the year are zero-padded.
|
|
49
|
+
- Typed digits are literal, stepping clamps. 29 February is reachable before the
|
|
50
|
+
year is typed; a finished date that cannot exist reports
|
|
51
|
+
`onInvalid("nonexistent")` rather than clamping to the 28th.
|
|
52
|
+
- Validation waits for a segment to finish. A half-typed year emits nothing
|
|
53
|
+
until it is complete or the field blurs.
|
|
54
|
+
- Empty fields are `null`. Partial drafts stay internal; `onChange` only sees
|
|
55
|
+
complete, valid values.
|
|
56
|
+
|
|
57
|
+
## SSR determinism
|
|
58
|
+
|
|
59
|
+
Pass the same reference date, value, locale, and `timeZone` on server and
|
|
60
|
+
client — today is resolved at render time. Segment literals are normalized
|
|
61
|
+
(U+202F and U+00A0 collapse to a plain space), so a 12-hour `TimeField` hydrates
|
|
62
|
+
cleanly across differing ICU versions; `hourCycle="h23"` is not a requirement.
|
|
63
|
+
|
|
64
|
+
## Not implemented
|
|
65
|
+
|
|
66
|
+
MonthPicker/YearPicker, DateTimeField, DateTimePicker, TimePicker,
|
|
67
|
+
DateRangePicker, zoned fields/pickers, TimeZoneSelect. Public APIs are
|
|
68
|
+
experimental at 0.x and not frozen for v1.
|
package/README.md
CHANGED
|
@@ -6,9 +6,10 @@ 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.1
|
|
10
|
-
> frozen for v1.
|
|
11
|
-
>
|
|
9
|
+
> **Status: experimental 0.2.1.** Public APIs and styling attributes are not
|
|
10
|
+
> frozen for v1; 0.2.0 changes the Calendar cell anatomy. See the
|
|
11
|
+
> [changelog](./CHANGELOG.md). Automated axe checks pass, but no screen-reader
|
|
12
|
+
> compatibility certification is claimed.
|
|
12
13
|
|
|
13
14
|
## Install
|
|
14
15
|
|
|
@@ -27,6 +28,10 @@ it is not native, load a polyfill before rendering:
|
|
|
27
28
|
import "temporal-polyfill/global";
|
|
28
29
|
```
|
|
29
30
|
|
|
31
|
+
The TypeScript types come along for free: `chrona-core`'s declarations reference
|
|
32
|
+
`temporal-spec/global`, so importing anything from this package puts the ambient
|
|
33
|
+
`Temporal` namespace in scope, exactly as the examples below assume.
|
|
34
|
+
|
|
30
35
|
## Calendar
|
|
31
36
|
|
|
32
37
|
```tsx
|
|
@@ -64,6 +69,14 @@ covers arrows, Home/End, PageUp/PageDown, Shift+PageUp/PageDown, and
|
|
|
64
69
|
Enter/Space, with RTL and locale week starts. Unavailable dates stay focusable
|
|
65
70
|
but unselectable; hard-disabled dates are not interactive.
|
|
66
71
|
|
|
72
|
+
`Calendar.Cell` renders the `role="gridcell"` wrapper and `Calendar.CellTrigger`
|
|
73
|
+
the button inside it, so the control keeps its button role in the accessibility
|
|
74
|
+
tree; a cell given no children renders its trigger for you. Style the
|
|
75
|
+
interactive element as `[data-part="cell-trigger"]`. `PrevButton` and
|
|
76
|
+
`NextButton` render a default chevron, pointing the way they page in the
|
|
77
|
+
resolved reading direction, when you give them no children; `DatePicker.Trigger`
|
|
78
|
+
does the same with a calendar glyph.
|
|
79
|
+
|
|
67
80
|
## DatePicker
|
|
68
81
|
|
|
69
82
|
```tsx
|
|
@@ -78,6 +91,11 @@ but unselectable; hard-disabled dates are not interactive.
|
|
|
78
91
|
</DatePicker.Root>
|
|
79
92
|
```
|
|
80
93
|
|
|
94
|
+
`DatePicker` accepts every `DateField` prop. `placeholderValue` is one of them,
|
|
95
|
+
and it decides the reference date the segments and the calendar open on before a
|
|
96
|
+
value exists — supply it (or `value`/`defaultValue`) rather than falling back to
|
|
97
|
+
today.
|
|
98
|
+
|
|
81
99
|
The popover is a native `<dialog>`, modal by default. It anchors to its trigger,
|
|
82
100
|
flips above when that fits, shifts to stay in the viewport, and scrolls
|
|
83
101
|
internally when oversized. Escape, outside pointer dismissal, and selection all
|
|
@@ -105,6 +123,11 @@ Style via `data-scope`, `data-part`, and state attributes: `data-selected`,
|
|
|
105
123
|
`data-outside-month`, `data-in-range`, `data-range-start`, `data-range-end`,
|
|
106
124
|
`data-preview`, `data-invalid`, `data-placeholder`.
|
|
107
125
|
|
|
126
|
+
Date cells are two parts: `cell` is the `role="gridcell"` wrapper, `cell-trigger`
|
|
127
|
+
is the button that takes focus, hover, and the click. Both carry the state
|
|
128
|
+
attributes. The default icons are `data-part="chevron"` on the paging buttons
|
|
129
|
+
and `data-part="trigger-icon"` on the picker trigger.
|
|
130
|
+
|
|
108
131
|
Layout and button parts accept `asChild` with event and ref composition. Input
|
|
109
132
|
segments, hidden inputs, and the dialog keep their HTML elements.
|
|
110
133
|
|
|
@@ -119,12 +142,61 @@ incomplete, or invalid values in your form layer before submission.
|
|
|
119
142
|
|
|
120
143
|
- ESM with declarations and source maps, targeting ES2022.
|
|
121
144
|
- Size budgets, minified + gzip, excluding React: Calendar 6 kB, DatePicker 12 kB.
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
145
|
+
- Blank segments read `mm/dd/yyyy` and `hh:mm`; filled numeric segments except
|
|
146
|
+
the year are zero-padded, so a field keeps one width as it fills.
|
|
147
|
+
- Typed digits are literal and stepping clamps: 29 February is reachable before
|
|
148
|
+
the year is typed, and a finished date the calendar cannot hold reports
|
|
149
|
+
`onInvalid("nonexistent")` instead of sliding to the 28th. Validation waits for
|
|
150
|
+
a segment to finish, so a half-typed year raises nothing until blur.
|
|
125
151
|
- Use `value`/`onChange` or `defaultValue`/`onChange` — do not switch modes
|
|
126
152
|
during a component's lifetime.
|
|
127
153
|
|
|
154
|
+
## Server Rendering
|
|
155
|
+
|
|
156
|
+
These are client components: mark the module that renders them `"use client"`.
|
|
157
|
+
|
|
158
|
+
The polyfill import is a side effect, so it has to reach the *client* bundle.
|
|
159
|
+
Importing `temporal-polyfill/global` from a Server Component file installs
|
|
160
|
+
Temporal on the server only. Put it at the top of a `"use client"` module that
|
|
161
|
+
always loads — a providers file, for example — so it runs before hydration:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
// app/providers.tsx
|
|
165
|
+
"use client";
|
|
166
|
+
|
|
167
|
+
import "temporal-polyfill/global";
|
|
168
|
+
import { ChronaProvider } from "chrona-react";
|
|
169
|
+
|
|
170
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
171
|
+
return <ChronaProvider locale="en-US" timeZone="Europe/Copenhagen">{children}</ChronaProvider>;
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
That covers the client bundle before hydration. It does not order Node module
|
|
176
|
+
evaluation. If another `"use client"` file reads `Temporal` at module scope
|
|
177
|
+
(`const reference = Temporal.PlainDate.from(...)` at the top of `page.tsx`),
|
|
178
|
+
Next.js may evaluate that file during SSR before `providers.tsx` has run and
|
|
179
|
+
throw `ReferenceError: Temporal is not defined`. Import the polyfill at the top
|
|
180
|
+
of that file too, or move the call inside the component body:
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
"use client";
|
|
184
|
+
|
|
185
|
+
import "temporal-polyfill/global";
|
|
186
|
+
import { Calendar } from "chrona-react";
|
|
187
|
+
|
|
188
|
+
const REFERENCE = Temporal.PlainDate.from({ year: 2026, month: 9, day: 16 });
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Pass the same reference date, value, locale, and time zone on server and client.
|
|
192
|
+
`timeZone` matters because today is resolved at render time, and a server in
|
|
193
|
+
another zone marks a different cell.
|
|
194
|
+
|
|
195
|
+
Segment literals are normalized before they reach the DOM: `Intl` emits U+202F
|
|
196
|
+
before AM/PM on newer ICU data and a plain space on older data, and Node and the
|
|
197
|
+
browser rarely ship the same ICU. Chrona collapses both to a plain space, so a
|
|
198
|
+
12-hour `TimeField` hydrates cleanly without forcing `hourCycle="h23"`.
|
|
199
|
+
|
|
128
200
|
Full documentation lives in the [repository README](https://github.com/devlinduldulao/chrona#readme).
|
|
129
201
|
|
|
130
202
|
## License
|
package/dist/calendar.d.ts
CHANGED
|
@@ -35,13 +35,20 @@ declare function useCalendar(props?: CalendarProps): {
|
|
|
35
35
|
"data-part": string;
|
|
36
36
|
};
|
|
37
37
|
getCellProps: (date: PlainDate, month?: temporal_spec.Temporal.PlainDate) => {
|
|
38
|
-
|
|
38
|
+
"data-date": string;
|
|
39
|
+
"data-selected": string | undefined;
|
|
40
|
+
"data-focused": string | undefined;
|
|
41
|
+
"data-disabled": string | undefined;
|
|
42
|
+
"data-unavailable": string | undefined;
|
|
43
|
+
"data-outside-month": string | undefined;
|
|
44
|
+
"data-today": string | undefined;
|
|
39
45
|
role: "gridcell";
|
|
40
|
-
tabIndex: number;
|
|
41
|
-
"aria-label": string;
|
|
42
46
|
"aria-selected": boolean;
|
|
43
47
|
"aria-disabled": true | undefined;
|
|
44
|
-
"
|
|
48
|
+
"data-scope": string;
|
|
49
|
+
"data-part": string;
|
|
50
|
+
};
|
|
51
|
+
getCellTriggerProps: (date: PlainDate, month?: temporal_spec.Temporal.PlainDate) => {
|
|
45
52
|
"data-date": string;
|
|
46
53
|
"data-selected": string | undefined;
|
|
47
54
|
"data-focused": string | undefined;
|
|
@@ -49,6 +56,12 @@ declare function useCalendar(props?: CalendarProps): {
|
|
|
49
56
|
"data-unavailable": string | undefined;
|
|
50
57
|
"data-outside-month": string | undefined;
|
|
51
58
|
"data-today": string | undefined;
|
|
59
|
+
id: string;
|
|
60
|
+
type: "button";
|
|
61
|
+
tabIndex: number;
|
|
62
|
+
"aria-label": string;
|
|
63
|
+
"aria-disabled": true | undefined;
|
|
64
|
+
"aria-current": "date" | undefined;
|
|
52
65
|
"data-scope": string;
|
|
53
66
|
"data-part": string;
|
|
54
67
|
};
|
|
@@ -109,11 +122,14 @@ declare const Calendar: {
|
|
|
109
122
|
GridBody: React.ForwardRefExoticComponent<Omit<PartProps, "children"> & {
|
|
110
123
|
children?: (date: PlainDate) => React.ReactNode;
|
|
111
124
|
} & React.RefAttributes<HTMLElement>>;
|
|
112
|
-
Cell: React.ForwardRefExoticComponent<
|
|
125
|
+
Cell: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
|
|
113
126
|
asChild?: boolean;
|
|
114
127
|
} & {
|
|
115
128
|
date: PlainDate;
|
|
116
129
|
} & React.RefAttributes<HTMLElement>>;
|
|
130
|
+
CellTrigger: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
|
|
131
|
+
asChild?: boolean;
|
|
132
|
+
} & React.RefAttributes<HTMLElement>>;
|
|
117
133
|
LiveRegion: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
|
|
118
134
|
asChild?: boolean;
|
|
119
135
|
} & React.RefAttributes<HTMLElement>>;
|
package/dist/calendar.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createFieldComponents,
|
|
3
3
|
useField
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JNQXKZO3.js";
|
|
5
5
|
|
|
6
6
|
// src/date-field.tsx
|
|
7
7
|
var DateField = createFieldComponents("date");
|
|
@@ -13,4 +13,4 @@ export {
|
|
|
13
13
|
DateField,
|
|
14
14
|
useDateField
|
|
15
15
|
};
|
|
16
|
-
//# sourceMappingURL=chunk-
|
|
16
|
+
//# sourceMappingURL=chunk-2GZMCFFY.js.map
|
|
@@ -34,7 +34,8 @@ function useField(kind, props) {
|
|
|
34
34
|
}, [configuration, state, store]);
|
|
35
35
|
const groupRef = React.useRef(null);
|
|
36
36
|
const [invalidReason, setInvalidReason] = React.useState(null);
|
|
37
|
-
const
|
|
37
|
+
const announcementKey = { range: "invalidRange", unavailable: "unavailable", nonexistent: "nonexistentDate" };
|
|
38
|
+
const announcement = invalidReason === null ? "" : options.translations?.[announcementKey[invalidReason]] ?? translations[announcementKey[invalidReason]];
|
|
38
39
|
function moveFocus(segment, offset) {
|
|
39
40
|
const elements = Array.from(groupRef.current?.querySelectorAll("input[data-segment]") ?? []);
|
|
40
41
|
const index = elements.findIndex((element) => element.dataset.segment === segment);
|
|
@@ -180,4 +181,4 @@ export {
|
|
|
180
181
|
useField,
|
|
181
182
|
createFieldComponents
|
|
182
183
|
};
|
|
183
|
-
//# sourceMappingURL=chunk-
|
|
184
|
+
//# sourceMappingURL=chunk-JNQXKZO3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/field.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { connectField, createField, createStore, digitValue, fieldHourCycle, transitionField, translations, type FieldEvent, type FieldInvalidReason, type FieldKind, type FieldOptions, type FieldValue, type SegmentType } from \"chrona-core\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useChronaConfig } from \"./provider\";\nimport { useFormReset, type HiddenInputProps } from \"./form\";\n\nexport interface FieldProps<Kind extends FieldKind> extends FieldOptions<Kind> {\n defaultValue?: FieldValue<Kind> | null;\n onChange?: (value: FieldValue<Kind> | null) => void;\n onInvalid?: (reason: FieldInvalidReason) => void;\n id?: string;\n describedBy?: string;\n}\n\nfunction equalValues(first: { equals: (other: never) => boolean } | null, second: { equals: (other: never) => boolean } | null) {\n return first === null || second === null ? first === second : first.equals(second as never);\n}\n\nexport function useField<Kind extends FieldKind>(kind: Kind, props: FieldProps<Kind>) {\n const options = useChronaConfig(props);\n const generatedId = React.useId();\n const id = props.id ?? generatedId;\n const [store] = React.useState(() => createStore(createField(kind, { ...options, value: props.value !== undefined ? props.value : props.defaultValue })));\n const snapshot = React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);\n const value = props.value !== undefined ? props.value : snapshot.value;\n const placeholderValue = options.placeholderValue ?? snapshot.reference;\n const { minValue, maxValue, locale, hourCycle, granularity } = options;\n const configured = React.useMemo(() => createField(kind, { value, placeholderValue, minValue, maxValue, locale, hourCycle, granularity }), [kind, value, placeholderValue, minValue, maxValue, locale, hourCycle, granularity]);\n const cycle = fieldHourCycle(options);\n const configuration = `${cycle}:${props.granularity ?? \"minute\"}`;\n const previousConfiguration = React.useRef(configuration);\n const state = props.value !== undefined && !equalValues(snapshot.value, props.value)\n ? configured\n : kind === \"time\" && configuration !== previousConfiguration.current\n ? configured\n : snapshot;\n React.useEffect(() => {\n if (previousConfiguration.current !== configuration) {\n previousConfiguration.current = configuration;\n store.setState(state);\n }\n }, [configuration, state, store]);\n const groupRef = React.useRef<HTMLElement | null>(null);\n const [invalidReason, setInvalidReason] = React.useState<FieldInvalidReason | null>(null);\n const announcementKey = { range: \"invalidRange\", unavailable: \"unavailable\", nonexistent: \"nonexistentDate\" } as const;\n const announcement = invalidReason === null ? \"\" : options.translations?.[announcementKey[invalidReason]] ?? translations[announcementKey[invalidReason]];\n\n function moveFocus(segment: SegmentType, offset: number) {\n const elements = Array.from(groupRef.current?.querySelectorAll<HTMLInputElement>(\"input[data-segment]\") ?? []);\n const index = elements.findIndex((element) => element.dataset.segment === segment);\n elements[index + offset]?.focus();\n }\n\n function send(event: FieldEvent) {\n const result = transitionField(state, event, options);\n store.setState(result.state);\n if (!result.state.invalid) setInvalidReason(null);\n for (const effect of result.effects) {\n if (effect.type === \"change\") props.onChange?.(effect.value);\n if (effect.type === \"invalid\") { setInvalidReason(effect.reason); props.onInvalid?.(effect.reason); }\n if (effect.type === \"advance\") queueMicrotask(() => moveFocus(effect.segment, 1));\n }\n }\n\n function reset() {\n setInvalidReason(null);\n const value = props.defaultValue ?? null;\n store.setState(createField(kind, { ...options, value }));\n if (!equalValues(state.value, value)) props.onChange?.(value);\n }\n\n const [labelled, setLabelled] = React.useState(false);\n return { id, state, options, send, reset, moveFocus, groupRef, announcement, registerLabel: setLabelled, api: connectField(state, { ...options, id, labelId: labelled ? `${id}-label` : undefined }) };\n}\n\nexport function createFieldComponents<Kind extends FieldKind>(kind: Kind) {\n const Context = React.createContext<ReturnType<typeof useField<Kind>> | null>(null);\n function useContext() {\n const context = React.useContext(Context);\n if (!context) throw new Error(`${kind === \"date\" ? \"DateField\" : \"TimeField\"} parts must be inside their Root.`);\n return context;\n }\n\n function Root({ children, asChild, className, style, ...props }: FieldProps<Kind> & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const context = useField(kind, props);\n return <Context.Provider value={context}><Part asChild={asChild} className={className} style={style} id={props.id} dir={context.options.dir} data-scope={`${kind}-field`} data-part=\"root\">{children}</Part></Context.Provider>;\n }\n\n const Label = React.forwardRef<HTMLElement, PartProps>(function Label(props, ref) {\n const { id, registerLabel } = useContext();\n React.useEffect(() => {\n registerLabel(true);\n return () => registerLabel(false);\n }, [registerLabel]);\n return <Part as=\"span\" {...props} ref={ref} id={`${id}-label`} data-scope={`${kind}-field`} data-part=\"label\" />;\n });\n\n const Segment = React.forwardRef<HTMLInputElement, Omit<React.ComponentPropsWithoutRef<\"input\">, \"type\" | \"value\" | \"defaultValue\" | \"onChange\" | \"children\"> & { type: SegmentType }>(function Segment({ type, onKeyDown, onFocus, onBlur, onPaste, onDrop, ...props }, ref) {\n const { state, api, options, send, moveFocus, groupRef } = useContext();\n if (!(type in state.parts)) throw new Error(`The ${type} segment is not enabled in this field.`);\n const { display, ...segmentProps } = api.getSegmentProps(type);\n return <input {...props} {...segmentProps} ref={ref} type=\"text\" inputMode={type === \"dayPeriod\" ? \"text\" : \"numeric\"} autoComplete=\"off\" spellCheck={false} value={display} disabled={options.disabled} readOnly={options.readOnly}\n onFocus={composeEvent(onFocus, (event) => { event.currentTarget.select(); })}\n onBlur={composeEvent(onBlur, () => send({ type: \"BLUR\" }))}\n onPaste={composeEvent(onPaste, (event) => event.preventDefault())}\n onDrop={composeEvent(onDrop, (event) => event.preventDefault())}\n onChange={(event) => {\n const native = event.nativeEvent as InputEvent;\n const digit = digitValue(native.data ?? \"\", options.locale);\n event.currentTarget.value = display;\n if (native.inputType === \"insertText\" && digit !== null) send({ type: \"DIGIT\", segment: type, digit });\n else if (native.inputType === \"deleteContentBackward\" || native.inputType === \"deleteContentForward\") send({ type: \"CLEAR\", segment: type });\n }}\n onKeyDown={composeEvent(onKeyDown, (event) => {\n if (event.altKey || event.ctrlKey || event.metaKey || event.nativeEvent.isComposing) return;\n const digit = digitValue(event.key, options.locale);\n const dir = options.dir ?? (groupRef.current?.closest(\"[dir]\")?.getAttribute(\"dir\") === \"rtl\" ? \"rtl\" : \"ltr\");\n if (digit !== null) { event.preventDefault(); send({ type: \"DIGIT\", segment: type, digit }); return; }\n switch (event.key) {\n case \"ArrowUp\": case \"ArrowDown\": event.preventDefault(); send({ type: \"STEP\", segment: type, direction: event.key === \"ArrowUp\" ? 1 : -1 }); break;\n case \"Home\": case \"End\": event.preventDefault(); send({ type: \"EDGE\", segment: type, edge: event.key === \"Home\" ? \"min\" : \"max\" }); break;\n case \"Backspace\": case \"Delete\": event.preventDefault(); send({ type: \"CLEAR\", segment: type }); break;\n case \"ArrowLeft\": case \"ArrowRight\": event.preventDefault(); moveFocus(type, (event.key === \"ArrowRight\" ? 1 : -1) * (dir === \"rtl\" ? -1 : 1)); break;\n default:\n if (type === \"dayPeriod\" && [\"a\", \"p\"].includes(event.key.toLowerCase())) {\n event.preventDefault(); send({ type: \"PERIOD\", value: event.key.toLowerCase() === \"a\" ? 0 : 1 });\n }\n }\n })} />;\n });\n\n const Field = React.forwardRef<HTMLElement, PartProps>(function Field({ children, ...props }, ref) {\n const { api, groupRef } = useContext();\n return <Part {...props} {...api.getGroupProps()} ref={(node) => {\n groupRef.current = node;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }}>{children ?? api.segments.map((segment, index) => segment.type === \"literal\" ? <span key={index} aria-hidden=\"true\" data-scope={`${kind}-field`} data-part=\"literal\">{segment.value}</span> : <Segment key={segment.type} type={segment.type} />)}</Part>;\n });\n\n function HiddenInput(props: HiddenInputProps) {\n const { state, options, reset } = useContext();\n const input = React.useRef<HTMLInputElement>(null);\n useFormReset(input, props.form, reset);\n return <input {...props} ref={input} type=\"hidden\" value={state.value?.toString() ?? \"\"} disabled={options.disabled || props.disabled} data-scope={`${kind}-field`} data-part=\"hidden-input\" />;\n }\n\n const ClearButton = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<\"button\"> & { asChild?: boolean }>(function ClearButton({ onClick, ...props }, ref) {\n const { options, send } = useContext();\n return <Part as=\"button\" {...props} ref={ref} type=\"button\" aria-label={options.translations?.clear ?? translations.clear} disabled={options.disabled || options.readOnly} data-scope={`${kind}-field`} data-part=\"clear-button\" onClick={composeEvent(onClick, () => send({ type: \"CLEAR\" }))} />;\n });\n\n const LiveRegion = React.forwardRef<HTMLElement, PartProps>(function LiveRegion(props, ref) {\n const { announcement } = useContext();\n return <Part {...props} ref={ref} role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" data-scope={`${kind}-field`} data-part=\"live-region\">{announcement}</Part>;\n });\n\n return { Root, Label, Field, Segment, HiddenInput, ClearButton, LiveRegion };\n}"],"mappings":"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","names":["value","useContext","Label","Segment","Field","ClearButton","LiveRegion"]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
Calendar,
|
|
3
3
|
CalendarSurface,
|
|
4
4
|
useCalendar
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RCWVBOO6.js";
|
|
6
6
|
import {
|
|
7
7
|
Part,
|
|
8
8
|
composeEvent,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
|
|
13
13
|
// src/range-calendar.tsx
|
|
14
14
|
import * as React from "react";
|
|
15
|
-
import { createRange, createStore, formatDate, getRangeCellProps, transitionRange, translations, validateRange } from "chrona-core";
|
|
15
|
+
import { createRange, createStore, formatDate, getRangeCellProps, getRangeCellTriggerProps, transitionRange, translations, validateRange } from "chrona-core";
|
|
16
16
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
17
17
|
function useRangeCalendar(input = {}) {
|
|
18
18
|
const props = useChronaConfig(input);
|
|
@@ -46,7 +46,11 @@ function useRangeCalendar(input = {}) {
|
|
|
46
46
|
if (state.anchor) send({ type: "PREVIEW", date });
|
|
47
47
|
} });
|
|
48
48
|
const baseApi = calendar.api;
|
|
49
|
-
const api = {
|
|
49
|
+
const api = {
|
|
50
|
+
...baseApi,
|
|
51
|
+
getCellProps: (date, month) => ({ ...baseApi.getCellProps(date, month), ...getRangeCellProps(state, date) }),
|
|
52
|
+
getCellTriggerProps: (date, month) => ({ ...baseApi.getCellTriggerProps(date, month), ...getRangeCellTriggerProps(state, date) })
|
|
53
|
+
};
|
|
50
54
|
return {
|
|
51
55
|
state,
|
|
52
56
|
send,
|
|
@@ -109,4 +113,4 @@ export {
|
|
|
109
113
|
useRangeCalendar,
|
|
110
114
|
RangeCalendar
|
|
111
115
|
};
|
|
112
|
-
//# sourceMappingURL=chunk-
|
|
116
|
+
//# sourceMappingURL=chunk-QQANBK5G.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/range-calendar.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { createRange, createStore, formatDate, getRangeCellProps, getRangeCellTriggerProps, transitionRange, translations, validateRange, type DateRange, type PlainDate, type RangeEvent } from \"chrona-core\";\nimport { Calendar, CalendarSurface, useCalendar, type CalendarProps } from \"./calendar\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useFormReset, type HiddenInputProps } from \"./form\";\nimport { useChronaConfig } from \"./provider\";\n\nexport interface RangeCalendarProps extends Omit<CalendarProps, \"value\" | \"defaultValue\" | \"onChange\"> {\n value?: DateRange | null;\n defaultValue?: DateRange | null;\n onChange?: (value: DateRange | null) => void;\n onRangeStartChange?: (value: PlainDate | null) => void;\n onInvalid?: () => void;\n}\n\nexport function useRangeCalendar(input: RangeCalendarProps = {}) {\n const props = useChronaConfig(input);\n const [store] = React.useState(() => createStore(createRange(props.value !== undefined ? props.value : props.defaultValue)));\n const snapshot = React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);\n if (props.value) validateRange(props.value);\n const state = { ...snapshot, value: props.value === undefined ? snapshot.value : props.value };\n const [announcement, setAnnouncement] = React.useState(\"\");\n function send(event: RangeEvent) {\n const result = transitionRange(state, event, props);\n store.setState(result.state);\n for (const effect of result.effects) {\n if (effect.type === \"change\") {\n props.onChange?.(effect.value);\n setAnnouncement(effect.value ? [effect.value.start, effect.value.end].map((date) => formatDate(date, props.locale, { dateStyle: \"long\" })).join(props.translations?.rangeSeparator ?? translations.rangeSeparator) : \"\");\n }\n if (effect.type === \"rangeStart\") {\n props.onRangeStartChange?.(effect.value);\n if (effect.value) setAnnouncement(formatDate(effect.value, props.locale, { dateStyle: \"long\" }));\n }\n if (effect.type === \"invalid\") { props.onInvalid?.(); setAnnouncement(props.translations?.unavailable ?? translations.unavailable); }\n }\n }\n const calendar = useCalendar({ ...props, value: null, defaultValue: null, placeholderValue: props.placeholderValue ?? state.value?.start, onChange: (date) => { if (date) send({ type: \"SELECT\", date }); }, onFocusedValueChange: (date) => { props.onFocusedValueChange?.(date); if (state.anchor) send({ type: \"PREVIEW\", date }); } });\n const baseApi = calendar.api;\n const api = {\n ...baseApi,\n getCellProps: (date: PlainDate, month?: PlainDate) => ({ ...baseApi.getCellProps(date, month), ...getRangeCellProps(state, date) }),\n getCellTriggerProps: (date: PlainDate, month?: PlainDate) => ({ ...baseApi.getCellTriggerProps(date, month), ...getRangeCellTriggerProps(state, date) }),\n };\n return {\n state, send, announcement, props, options: props, api, rootRef: calendar.rootRef, months: calendar.months,\n reset() { const value = props.defaultValue ?? null; store.setState(createRange(value)); props.onChange?.(value); },\n calendar: { ...calendar, api },\n };\n}\n\nconst Context = React.createContext<ReturnType<typeof useRangeCalendar> | null>(null);\nfunction useContext() {\n const value = React.useContext(Context);\n if (!value) throw new Error(\"RangeCalendar parts must be inside RangeCalendar.Root.\");\n return value;\n}\n\nfunction Root({ children, asChild, className, style, ...props }: RangeCalendarProps & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const context = useRangeCalendar(props);\n return <Context.Provider value={context}><CalendarSurface calendar={context.calendar} asChild={asChild} className={className} style={style} data-scope=\"range-calendar\" onKeyDown={(event) => { if (event.key === \"Escape\" && context.state.anchor) { event.preventDefault(); context.send({ type: \"CANCEL\" }); } }}>{children}</CalendarSurface></Context.Provider>;\n}\n\nconst Cell = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<typeof Calendar.Cell>>(function Cell({ date, onPointerEnter, ...props }, ref) {\n const { send } = useContext();\n return <Calendar.Cell {...props} ref={ref} date={date} onPointerEnter={composeEvent(onPointerEnter, () => send({ type: \"PREVIEW\", date }))} />;\n});\n\nconst GridBody = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<typeof Calendar.GridBody>>(function GridBody({ children, ...props }, ref) {\n return <Calendar.GridBody {...props} ref={ref}>{children ?? ((date) => <Cell date={date} />)}</Calendar.GridBody>;\n});\n\nconst LiveRegion = React.forwardRef<HTMLElement, PartProps>(function LiveRegion(props, ref) {\n const { announcement } = useContext();\n return <Part {...props} ref={ref} role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" data-scope=\"range-calendar\" data-part=\"live-region\">{announcement}</Part>;\n});\n\nconst ClearButton = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<typeof Calendar.ClearButton>>(function ClearButton({ onClick, ...props }, ref) {\n const { send, props: options } = useContext();\n return <Part as=\"button\" {...props} ref={ref} type=\"button\" disabled={options.disabled || options.readOnly} aria-label={options.translations?.clear ?? translations.clear} data-scope=\"range-calendar\" data-part=\"clear-button\" onClick={composeEvent(onClick, () => send({ type: \"CLEAR\" }))} />;\n});\n\nfunction HiddenInput({ name, form, id, disabled, ...inputProps }: HiddenInputProps & { name: string }) {\n const { state, props, reset } = useContext();\n const input = React.useRef<HTMLInputElement>(null);\n useFormReset(input, form, reset);\n return <><input {...inputProps} id={id ? `${id}-start` : undefined} ref={input} type=\"hidden\" name={`${name}.start`} form={form} value={state.value?.start.toString() ?? \"\"} disabled={props.disabled || disabled} data-scope=\"range-calendar\" data-part=\"hidden-input\" /><input {...inputProps} id={id ? `${id}-end` : undefined} type=\"hidden\" name={`${name}.end`} form={form} value={state.value?.end.toString() ?? \"\"} disabled={props.disabled || disabled} data-scope=\"range-calendar\" data-part=\"hidden-input\" /></>;\n}\n\nexport const RangeCalendar = { ...Calendar, Root, Cell, GridBody, LiveRegion, ClearButton, HiddenInput };"],"mappings":"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","names":["useContext","Cell","GridBody","LiveRegion","ClearButton"]}
|
|
@@ -25,7 +25,7 @@ function useCalendar(props = {}) {
|
|
|
25
25
|
React.useEffect(() => {
|
|
26
26
|
if (pendingFocus.current) {
|
|
27
27
|
pendingFocus.current = false;
|
|
28
|
-
rootRef.current?.querySelector('[data-part="cell"][tabindex="0"]')?.focus();
|
|
28
|
+
rootRef.current?.querySelector('[data-part="cell-trigger"][tabindex="0"]')?.focus();
|
|
29
29
|
}
|
|
30
30
|
});
|
|
31
31
|
function send(event) {
|
|
@@ -76,13 +76,17 @@ var Heading = React.forwardRef(function Heading2({ children, ...props }, ref) {
|
|
|
76
76
|
const month = React.useContext(MonthContext);
|
|
77
77
|
return /* @__PURE__ */ jsx(Part, { as: "h2", ...props, ref, "data-scope": "calendar", "data-part": "heading", "aria-live": "polite", "aria-atomic": "true", children: children ?? (month ? [month] : months).map((date) => formatDate(date, options.locale, { month: "long", year: "numeric" })).join(options.translations?.rangeSeparator ?? translations.rangeSeparator) });
|
|
78
78
|
});
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
return /* @__PURE__ */ jsx(
|
|
79
|
+
function Chevron({ towards }) {
|
|
80
|
+
const points = towards === "start" ? "15 4 7 12 15 20" : "9 4 17 12 9 20";
|
|
81
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", focusable: "false", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "data-scope": "calendar", "data-part": "chevron", children: /* @__PURE__ */ jsx("polyline", { points }) });
|
|
82
|
+
}
|
|
83
|
+
var PrevButton = React.forwardRef(function PrevButton2({ onClick, children, ...props }, ref) {
|
|
84
|
+
const { api, send, options } = useContext2();
|
|
85
|
+
return /* @__PURE__ */ jsx(Part, { as: "button", ...props, ...api.getPrevButtonProps(), ref, onClick: composeEvent(onClick, () => send({ type: "PAGE", direction: -1 })), children: children ?? /* @__PURE__ */ jsx(Chevron, { towards: options.dir === "rtl" ? "end" : "start" }) });
|
|
82
86
|
});
|
|
83
|
-
var NextButton = React.forwardRef(function NextButton2({ onClick, ...props }, ref) {
|
|
84
|
-
const { api, send } = useContext2();
|
|
85
|
-
return /* @__PURE__ */ jsx(Part, { as: "button", ...props, ...api.getNextButtonProps(), ref, onClick: composeEvent(onClick, () => send({ type: "PAGE", direction: 1 })) });
|
|
87
|
+
var NextButton = React.forwardRef(function NextButton2({ onClick, children, ...props }, ref) {
|
|
88
|
+
const { api, send, options } = useContext2();
|
|
89
|
+
return /* @__PURE__ */ jsx(Part, { as: "button", ...props, ...api.getNextButtonProps(), ref, onClick: composeEvent(onClick, () => send({ type: "PAGE", direction: 1 })), children: children ?? /* @__PURE__ */ jsx(Chevron, { towards: options.dir === "rtl" ? "start" : "end" }) });
|
|
86
90
|
});
|
|
87
91
|
var Grid = React.forwardRef(function Grid2({ monthIndex = 0, children, ...props }, ref) {
|
|
88
92
|
const { api, months } = useContext2();
|
|
@@ -110,16 +114,17 @@ var GridBody = React.forwardRef(function GridBody2({ children, ...props }, ref)
|
|
|
110
114
|
const { weeks } = useMonth();
|
|
111
115
|
return /* @__PURE__ */ jsx(Part, { ...props, ref, role: "rowgroup", "data-scope": "calendar", "data-part": "grid-body", children: weeks.map((week) => /* @__PURE__ */ jsx("div", { role: "row", "data-scope": "calendar", "data-part": "row", children: week.map((date) => /* @__PURE__ */ jsx(React.Fragment, { children: children ? children(date) : /* @__PURE__ */ jsx(Cell, { date }) }, date.toString())) }, week[0].toString())) });
|
|
112
116
|
});
|
|
113
|
-
var
|
|
117
|
+
var CellContext = React.createContext(null);
|
|
118
|
+
var CellTrigger = React.forwardRef(function CellTrigger2({ children, onClick, onKeyDown, onFocus, ...props }, ref) {
|
|
114
119
|
const { api, send, month, options } = useMonth();
|
|
115
|
-
const
|
|
120
|
+
const date = React.useContext(CellContext);
|
|
121
|
+
if (!date) throw new Error("Calendar.CellTrigger must be inside Calendar.Cell.");
|
|
116
122
|
return /* @__PURE__ */ jsx(
|
|
117
123
|
Part,
|
|
118
124
|
{
|
|
119
125
|
as: "button",
|
|
120
126
|
...props,
|
|
121
|
-
...
|
|
122
|
-
type: "button",
|
|
127
|
+
...api.getCellTriggerProps(date, month),
|
|
123
128
|
ref,
|
|
124
129
|
onFocus: composeEvent(onFocus, () => {
|
|
125
130
|
if (!options.disabled) send({ type: "FOCUS", date });
|
|
@@ -134,6 +139,10 @@ var Cell = React.forwardRef(function Cell2({ date, children, onClick, onKeyDown,
|
|
|
134
139
|
}
|
|
135
140
|
);
|
|
136
141
|
});
|
|
142
|
+
var Cell = React.forwardRef(function Cell2({ date, children, ...props }, ref) {
|
|
143
|
+
const { api, month } = useMonth();
|
|
144
|
+
return /* @__PURE__ */ jsx(CellContext.Provider, { value: date, children: /* @__PURE__ */ jsx(Part, { ...props, ...api.getCellProps(date, month), ref, children: children ?? /* @__PURE__ */ jsx(CellTrigger, {}) }) });
|
|
145
|
+
});
|
|
137
146
|
var LiveRegion = React.forwardRef(function LiveRegion2(props, ref) {
|
|
138
147
|
const { announcement } = useContext2();
|
|
139
148
|
return /* @__PURE__ */ jsx(Part, { ...props, ref, role: "status", "aria-live": "polite", "aria-atomic": "true", "data-scope": "calendar", "data-part": "live-region", children: announcement });
|
|
@@ -148,7 +157,7 @@ function HiddenInput(props) {
|
|
|
148
157
|
useFormReset(input, props.form, () => send({ type: "RESET", value: options.defaultValue ?? null }));
|
|
149
158
|
return /* @__PURE__ */ jsx("input", { ...props, ref: input, type: "hidden", disabled: options.disabled || props.disabled, value: state.value?.toString() ?? "", "data-scope": "calendar", "data-part": "hidden-input" });
|
|
150
159
|
}
|
|
151
|
-
var Calendar = { Root: CalendarRoot, Header, Heading, PrevButton, NextButton, Grid, GridHeader, HeaderCell, GridBody, Cell, LiveRegion, ClearButton, HiddenInput };
|
|
160
|
+
var Calendar = { Root: CalendarRoot, Header, Heading, PrevButton, NextButton, Grid, GridHeader, HeaderCell, GridBody, Cell, CellTrigger, LiveRegion, ClearButton, HiddenInput };
|
|
152
161
|
|
|
153
162
|
export {
|
|
154
163
|
useCalendar,
|
|
@@ -156,4 +165,4 @@ export {
|
|
|
156
165
|
CalendarSurface,
|
|
157
166
|
Calendar
|
|
158
167
|
};
|
|
159
|
-
//# sourceMappingURL=chunk-
|
|
168
|
+
//# sourceMappingURL=chunk-RCWVBOO6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/calendar.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { calendarKeys, connectCalendar, createCalendar, createStore, formatDate, getNumberFormatter, resolveWeekStart, sameDate, syncCalendar, temporal, transitionCalendar, translations, weeksInMonthView, type CalendarEvent, type CalendarOptions, type PlainDate } from \"chrona-core\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useChronaConfig } from \"./provider\";\nimport { useFormReset, type HiddenInputProps } from \"./form\";\n\nexport interface CalendarProps extends CalendarOptions {\n defaultValue?: PlainDate | null;\n defaultFocusedValue?: PlainDate;\n onChange?: (value: PlainDate | null) => void;\n onSelect?: (value: PlainDate) => void;\n onFocusedValueChange?: (value: PlainDate) => void;\n id?: string;\n}\n\nexport function useCalendar(props: CalendarProps = {}) {\n const options = useChronaConfig(props);\n const generatedId = React.useId();\n const id = props.id ?? generatedId;\n const [store] = React.useState(() => createStore(createCalendar({ ...options, value: props.value !== undefined ? props.value : props.defaultValue, focusedValue: props.focusedValue ?? props.defaultFocusedValue })));\n const snapshot = React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);\n // The store is the single source of truth; controlled props are reconciled into it by syncCalendar.\n const state = syncCalendar(snapshot, { ...options, value: props.value, focusedValue: props.focusedValue });\n React.useEffect(() => { store.setState(state); });\n const rootRef = React.useRef<HTMLElement | null>(null);\n const pendingFocus = React.useRef(false);\n const [announcement, setAnnouncement] = React.useState(\"\");\n\n React.useEffect(() => {\n if (pendingFocus.current) {\n pendingFocus.current = false;\n rootRef.current?.querySelector<HTMLElement>('[data-part=\"cell-trigger\"][tabindex=\"0\"]')?.focus();\n }\n });\n\n function send(event: CalendarEvent) {\n const dir = options.dir ?? (rootRef.current?.closest(\"[dir]\")?.getAttribute(\"dir\") === \"rtl\" ? \"rtl\" : \"ltr\");\n const result = transitionCalendar(state, event, { ...options, dir });\n store.setState(result.state);\n for (const effect of result.effects) {\n if (effect.type === \"focus\") {\n pendingFocus.current = true;\n if (!sameDate(effect.value, state.focusedValue)) props.onFocusedValueChange?.(effect.value);\n } else if (effect.type === \"change\") {\n props.onChange?.(effect.value);\n setAnnouncement(effect.value ? (options.translations?.selected ?? translations.selected)(formatDate(effect.value, options.locale, { dateStyle: \"full\" })) : \"\");\n } else {\n props.onSelect?.(effect.value);\n }\n }\n }\n\n return {\n state, options, send, rootRef, announcement,\n api: connectCalendar(state, { ...options, id, today: temporal().Now.plainDateISO(options.timeZone) }),\n months: Array.from({ length: options.numberOfMonths ?? 1 }, (_, index) => state.visibleMonth.add({ months: index })),\n };\n}\n\ntype CalendarContextValue = ReturnType<typeof useCalendar>;\nconst Context = React.createContext<CalendarContextValue | null>(null);\nconst MonthContext = React.createContext<PlainDate | null>(null);\n\nfunction useContext() {\n const value = React.useContext(Context);\n if (!value) throw new Error(\"Calendar parts must be inside Calendar.Root.\");\n return value;\n}\n\nexport function CalendarRoot({ children, asChild, className, style, ...props }: CalendarProps & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const calendar = useCalendar(props);\n return <CalendarSurface calendar={calendar} id={props.id} asChild={asChild} className={className} style={style}>{children}</CalendarSurface>;\n}\n\nexport function CalendarSurface({ calendar, ...props }: PartProps & { calendar: CalendarContextValue }) {\n return <Context.Provider value={calendar}><Part {...calendar.api.getRootProps()} {...props} ref={calendar.rootRef} /></Context.Provider>;\n}\n\nconst Header = React.forwardRef<HTMLElement, PartProps>(function Header(props, ref) {\n return <Part {...props} ref={ref} data-scope=\"calendar\" data-part=\"header\" />;\n});\n\nconst Heading = React.forwardRef<HTMLElement, PartProps>(function Heading({ children, ...props }, ref) {\n const { months, options } = useContext();\n const month = React.useContext(MonthContext);\n return <Part as=\"h2\" {...props} ref={ref} data-scope=\"calendar\" data-part=\"heading\" aria-live=\"polite\" aria-atomic=\"true\">{children ?? (month ? [month] : months).map((date) => formatDate(date, options.locale, { month: \"long\", year: \"numeric\" })).join(options.translations?.rangeSeparator ?? translations.rangeSeparator)}</Part>;\n});\n\ntype ButtonProps = React.ComponentPropsWithoutRef<\"button\"> & { asChild?: boolean };\n\n/**\n * Paging buttons carry an `aria-label` but no text, so without a default they render as blank\n * chrome for sighted users. The arrow points the way the button pages in the resolved direction.\n */\nfunction Chevron({ towards }: { towards: \"start\" | \"end\" }) {\n const points = towards === \"start\" ? \"15 4 7 12 15 20\" : \"9 4 17 12 9 20\";\n return <svg aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" data-scope=\"calendar\" data-part=\"chevron\"><polyline points={points} /></svg>;\n}\n\nconst PrevButton = React.forwardRef<HTMLElement, ButtonProps>(function PrevButton({ onClick, children, ...props }, ref) {\n const { api, send, options } = useContext();\n return <Part as=\"button\" {...props} {...api.getPrevButtonProps()} ref={ref} onClick={composeEvent(onClick, () => send({ type: \"PAGE\", direction: -1 }))}>{children ?? <Chevron towards={options.dir === \"rtl\" ? \"end\" : \"start\"} />}</Part>;\n});\n\nconst NextButton = React.forwardRef<HTMLElement, ButtonProps>(function NextButton({ onClick, children, ...props }, ref) {\n const { api, send, options } = useContext();\n return <Part as=\"button\" {...props} {...api.getNextButtonProps()} ref={ref} onClick={composeEvent(onClick, () => send({ type: \"PAGE\", direction: 1 }))}>{children ?? <Chevron towards={options.dir === \"rtl\" ? \"start\" : \"end\"} />}</Part>;\n});\n\nconst Grid = React.forwardRef<HTMLElement, PartProps & { monthIndex?: number }>(function Grid({ monthIndex = 0, children, ...props }, ref) {\n const { api, months } = useContext();\n const month = months[monthIndex];\n if (!month) throw new Error(\"Calendar.Grid monthIndex is outside numberOfMonths.\");\n return <MonthContext.Provider value={month}><Part {...props} {...api.getGridProps(month)} ref={ref}>{children}</Part></MonthContext.Provider>;\n});\n\nfunction useMonth() {\n const context = useContext();\n const month = React.useContext(MonthContext) ?? context.state.visibleMonth;\n return { ...context, month, weeks: weeksInMonthView(month.toPlainYearMonth(), resolveWeekStart(context.options.locale, context.options.firstDayOfWeek), context.options.fixedWeeks) };\n}\n\nexport interface Weekday { date: PlainDate; label: string }\n\nconst GridHeader = React.forwardRef<HTMLElement, Omit<PartProps, \"children\"> & { children?: (day: Weekday) => React.ReactNode }>(function GridHeader({ children, ...props }, ref) {\n const { weeks, options } = useMonth();\n return <Part {...props} ref={ref} role=\"row\" data-scope=\"calendar\" data-part=\"grid-header\">{weeks[0]!.map((date) => {\n const day = { date, label: formatDate(date, options.locale, { weekday: \"short\" }) };\n return <React.Fragment key={date.toString()}>{children ? children(day) : <HeaderCell day={day} />}</React.Fragment>;\n })}</Part>;\n});\n\nconst HeaderCell = React.forwardRef<HTMLElement, PartProps & { day: Weekday }>(function HeaderCell({ day, children, ...props }, ref) {\n const { options } = useContext();\n return <Part {...props} ref={ref} role=\"columnheader\" aria-label={formatDate(day.date, options.locale, { weekday: \"long\" })} data-scope=\"calendar\" data-part=\"header-cell\">{children ?? day.label}</Part>;\n});\n\nconst GridBody = React.forwardRef<HTMLElement, Omit<PartProps, \"children\"> & { children?: (date: PlainDate) => React.ReactNode }>(function GridBody({ children, ...props }, ref) {\n const { weeks } = useMonth();\n return <Part {...props} ref={ref} role=\"rowgroup\" data-scope=\"calendar\" data-part=\"grid-body\">{weeks.map((week) => <div key={week[0]!.toString()} role=\"row\" data-scope=\"calendar\" data-part=\"row\">{week.map((date) => <React.Fragment key={date.toString()}>{children ? children(date) : <Cell date={date} />}</React.Fragment>)}</div>)}</Part>;\n});\n\nconst CellContext = React.createContext<PlainDate | null>(null);\n\nconst CellTrigger = React.forwardRef<HTMLElement, ButtonProps>(function CellTrigger({ children, onClick, onKeyDown, onFocus, ...props }, ref) {\n const { api, send, month, options } = useMonth();\n const date = React.useContext(CellContext);\n if (!date) throw new Error(\"Calendar.CellTrigger must be inside Calendar.Cell.\");\n // aria-disabled instead of native disabled keeps out-of-range dates discoverable by screen readers.\n return <Part as=\"button\" {...props} {...api.getCellTriggerProps(date, month)} ref={ref}\n onFocus={composeEvent(onFocus, () => { if (!options.disabled) send({ type: \"FOCUS\", date }); })}\n onClick={composeEvent(onClick, () => send({ type: \"SELECT\", date }))}\n onKeyDown={composeEvent(onKeyDown, (event) => {\n if (!calendarKeys.has(event.key) || event.altKey || event.ctrlKey || event.metaKey) return;\n event.preventDefault();\n send({ type: \"KEY_DOWN\", key: event.key, shiftKey: event.shiftKey });\n })}>{children ?? getNumberFormatter(options.locale, { useGrouping: false }).format(date.day)}</Part>;\n});\n\n/** The grid semantics live on the cell; the button inside it stays a button. */\nconst Cell = React.forwardRef<HTMLElement, PartProps & { date: PlainDate }>(function Cell({ date, children, ...props }, ref) {\n const { api, month } = useMonth();\n return <CellContext.Provider value={date}><Part {...props} {...api.getCellProps(date, month)} ref={ref}>{children ?? <CellTrigger />}</Part></CellContext.Provider>;\n});\n\nconst LiveRegion = React.forwardRef<HTMLElement, PartProps>(function LiveRegion(props, ref) {\n const { announcement } = useContext();\n return <Part {...props} ref={ref} role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" data-scope=\"calendar\" data-part=\"live-region\">{announcement}</Part>;\n});\n\nconst ClearButton = React.forwardRef<HTMLElement, ButtonProps>(function ClearButton({ onClick, ...props }, ref) {\n const { options, send, state } = useContext();\n return <Part as=\"button\" {...props} ref={ref} type=\"button\" data-scope=\"calendar\" data-part=\"clear-button\" aria-label={options.translations?.clear ?? translations.clear} disabled={options.disabled || options.readOnly || state.value === null} onClick={composeEvent(onClick, () => send({ type: \"CLEAR\" }))} />;\n});\n\nfunction HiddenInput(props: HiddenInputProps) {\n const { state, options, send } = useContext();\n const input = React.useRef<HTMLInputElement>(null);\n useFormReset(input, props.form, () => send({ type: \"RESET\", value: options.defaultValue ?? null }));\n return <input {...props} ref={input} type=\"hidden\" disabled={options.disabled || props.disabled} value={state.value?.toString() ?? \"\"} data-scope=\"calendar\" data-part=\"hidden-input\" />;\n}\n\nexport const Calendar = { Root: CalendarRoot, Header, Heading, PrevButton, NextButton, Grid, GridHeader, HeaderCell, GridBody, Cell, CellTrigger, LiveRegion, ClearButton, HiddenInput };"],"mappings":"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","names":["useContext","Header","Heading","PrevButton","NextButton","Grid","GridHeader","HeaderCell","GridBody","CellTrigger","Cell","LiveRegion","ClearButton"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createFieldComponents,
|
|
3
3
|
useField
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-JNQXKZO3.js";
|
|
5
5
|
|
|
6
6
|
// src/time-field.tsx
|
|
7
7
|
var TimeField = createFieldComponents("time");
|
|
@@ -13,4 +13,4 @@ export {
|
|
|
13
13
|
TimeField,
|
|
14
14
|
useTimeField
|
|
15
15
|
};
|
|
16
|
-
//# sourceMappingURL=chunk-
|
|
16
|
+
//# sourceMappingURL=chunk-ROJQDSGQ.js.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DateField
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2GZMCFFY.js";
|
|
4
4
|
import {
|
|
5
5
|
Calendar
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RCWVBOO6.js";
|
|
7
7
|
import {
|
|
8
8
|
Part,
|
|
9
9
|
composeEvent,
|
|
@@ -55,13 +55,19 @@ var Label = React.forwardRef(function Label2(props, ref) {
|
|
|
55
55
|
}, [registerLabel]);
|
|
56
56
|
return /* @__PURE__ */ jsx(DateField.Label, { ...props, ref });
|
|
57
57
|
});
|
|
58
|
-
|
|
58
|
+
function CalendarGlyph() {
|
|
59
|
+
return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", focusable: "false", viewBox: "0 0 24 24", width: "1em", height: "1em", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "data-scope": "date-picker", "data-part": "trigger-icon", children: [
|
|
60
|
+
/* @__PURE__ */ jsx("rect", { x: "3", y: "5", width: "18", height: "16", rx: "2" }),
|
|
61
|
+
/* @__PURE__ */ jsx("path", { d: "M3 10h18M8 3v4M16 3v4" })
|
|
62
|
+
] });
|
|
63
|
+
}
|
|
64
|
+
var Trigger = React.forwardRef(function Trigger2({ onClick, children, ...props }, ref) {
|
|
59
65
|
const picker = usePicker();
|
|
60
66
|
return /* @__PURE__ */ jsx(Part, { as: "button", ...props, type: "button", ref: (node) => {
|
|
61
67
|
picker.trigger.current = node;
|
|
62
68
|
if (typeof ref === "function") ref(node);
|
|
63
69
|
else if (ref) ref.current = node;
|
|
64
|
-
}, "aria-label": props["aria-label"] ?? picker.props.translations?.chooseDate ?? translations.chooseDate, "aria-haspopup": "dialog", "aria-expanded": picker.open, "aria-controls": `${picker.id}-dialog`, disabled: picker.props.disabled, "data-scope": "date-picker", "data-part": "trigger", onClick: composeEvent(onClick, () => picker.send({ type: "TOGGLE" })) });
|
|
70
|
+
}, "aria-label": props["aria-label"] ?? picker.props.translations?.chooseDate ?? translations.chooseDate, "aria-haspopup": "dialog", "aria-expanded": picker.open, "aria-controls": `${picker.id}-dialog`, disabled: picker.props.disabled, "data-scope": "date-picker", "data-part": "trigger", onClick: composeEvent(onClick, () => picker.send({ type: "TOGGLE" })), children: children ?? /* @__PURE__ */ jsx(CalendarGlyph, {}) });
|
|
65
71
|
});
|
|
66
72
|
var Popover = React.forwardRef(function Popover2({ children, anchored = true, onCancel, onClose, onKeyDown, ...props }, ref) {
|
|
67
73
|
const picker = usePicker();
|
|
@@ -74,7 +80,7 @@ var Popover = React.forwardRef(function Popover2({ children, anchored = true, on
|
|
|
74
80
|
if (picker.open && !element.open) {
|
|
75
81
|
if (picker.props.modal === false) element.show();
|
|
76
82
|
else element.showModal();
|
|
77
|
-
element.querySelector('[data-part="cell"][tabindex="0"]')?.focus();
|
|
83
|
+
element.querySelector('[data-part="cell-trigger"][tabindex="0"]')?.focus();
|
|
78
84
|
} else if (!picker.open && element.open) {
|
|
79
85
|
element.close();
|
|
80
86
|
picker.trigger.current?.focus();
|
|
@@ -157,6 +163,8 @@ var Popover = React.forwardRef(function Popover2({ children, anchored = true, on
|
|
|
157
163
|
element.ownerDocument.addEventListener("pointerdown", dismiss);
|
|
158
164
|
return () => element.ownerDocument.removeEventListener("pointerdown", dismiss);
|
|
159
165
|
}, [picker.open]);
|
|
166
|
+
const labelledBy = props["aria-labelledby"] ?? (props["aria-label"] || !picker.labelled ? void 0 : `${picker.id}-field-label`);
|
|
167
|
+
const label = props["aria-label"] ?? (labelledBy === void 0 ? picker.props.translations?.chooseDate ?? translations.chooseDate : void 0);
|
|
160
168
|
return /* @__PURE__ */ jsx(
|
|
161
169
|
"dialog",
|
|
162
170
|
{
|
|
@@ -167,8 +175,8 @@ var Popover = React.forwardRef(function Popover2({ children, anchored = true, on
|
|
|
167
175
|
else if (ref) ref.current = node;
|
|
168
176
|
},
|
|
169
177
|
id: `${picker.id}-dialog`,
|
|
170
|
-
"aria-label":
|
|
171
|
-
"aria-labelledby":
|
|
178
|
+
"aria-label": label,
|
|
179
|
+
"aria-labelledby": labelledBy,
|
|
172
180
|
"aria-modal": picker.props.modal !== false || void 0,
|
|
173
181
|
"data-scope": "date-picker",
|
|
174
182
|
"data-part": "popover",
|
|
@@ -208,4 +216,4 @@ export {
|
|
|
208
216
|
useDatePicker,
|
|
209
217
|
DatePicker
|
|
210
218
|
};
|
|
211
|
-
//# sourceMappingURL=chunk-
|
|
219
|
+
//# sourceMappingURL=chunk-U4LLSRIH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/date-picker.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { computeAnchorPosition, containTabFocus, transitionPicker, translations, type PlainDate, type PickerEvent } from \"chrona-core\";\nimport { Calendar, type CalendarProps } from \"./calendar\";\nimport { DateField, type DateFieldProps } from \"./date-field\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useChronaConfig } from \"./provider\";\n\nexport interface DatePickerProps extends DateFieldProps {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n modal?: boolean;\n timeZone?: string;\n firstDayOfWeek?: number;\n fixedWeeks?: boolean;\n numberOfMonths?: number;\n pagedNavigation?: boolean;\n}\n\ninterface PickerContext {\n props: DatePickerProps;\n options: DatePickerProps;\n state: { value: PlainDate | null; open: boolean };\n id: string;\n value: PlainDate | null;\n change: (value: PlainDate | null) => void;\n open: boolean;\n send: (event: PickerEvent) => void;\n trigger: { current: HTMLElement | null };\n labelled: boolean;\n registerLabel: (present: boolean) => void;\n}\n\nconst Context = React.createContext<PickerContext | null>(null);\nfunction usePicker() {\n const value = React.useContext(Context);\n if (!value) throw new Error(\"DatePicker parts must be inside DatePicker.Root.\");\n return value;\n}\n\nfunction Root({ children, asChild, className, style, ...input }: DatePickerProps & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const picker = useDatePicker(input);\n return <Context.Provider value={picker}><Part asChild={asChild} className={className} style={style} dir={picker.props.dir} data-scope=\"date-picker\" data-part=\"root\"><DateField.Root {...picker.props} id={`${picker.id}-field`} value={picker.value} onChange={picker.change}>{children}</DateField.Root></Part></Context.Provider>;\n}\n\nexport function useDatePicker(input: DatePickerProps = {}): PickerContext {\n const props = useChronaConfig(input);\n const generatedId = React.useId();\n const id = props.id ?? generatedId;\n const [uncontrolledValue, setValue] = React.useState(props.defaultValue ?? null);\n const [uncontrolledOpen, setOpen] = React.useState(props.defaultOpen ?? false);\n const value = props.value === undefined ? uncontrolledValue : props.value;\n const open = props.open ?? uncontrolledOpen;\n const trigger = React.useRef<HTMLElement | null>(null);\n const [labelled, registerLabel] = React.useState(false);\n function change(next: PlainDate | null) {\n if (props.value === undefined) setValue(next);\n props.onChange?.(next);\n }\n function send(event: PickerEvent) {\n const result = transitionPicker({ open }, event, props);\n for (const effect of result.effects) if (effect.type === \"openChange\") {\n if (props.open === undefined) setOpen(effect.open);\n props.onOpenChange?.(effect.open);\n }\n }\n return { props, options: props, state: { value, open }, id, value, change, open, send, trigger, labelled, registerLabel };\n}\n\nconst Label = React.forwardRef<HTMLElement, PartProps>(function Label(props, ref) {\n const { registerLabel } = usePicker();\n React.useEffect(() => {\n registerLabel(true);\n return () => registerLabel(false);\n }, [registerLabel]);\n return <DateField.Label {...props} ref={ref} />;\n});\n\n/** Like the paging buttons, the trigger is labelled but has no text of its own to show. */\nfunction CalendarGlyph() {\n return <svg aria-hidden=\"true\" focusable=\"false\" viewBox=\"0 0 24 24\" width=\"1em\" height=\"1em\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" data-scope=\"date-picker\" data-part=\"trigger-icon\"><rect x=\"3\" y=\"5\" width=\"18\" height=\"16\" rx=\"2\" /><path d=\"M3 10h18M8 3v4M16 3v4\" /></svg>;\n}\n\nconst Trigger = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<\"button\"> & { asChild?: boolean }>(function Trigger({ onClick, children, ...props }, ref) {\n const picker = usePicker();\n return <Part as=\"button\" {...props} type=\"button\" ref={(node) => {\n picker.trigger.current = node;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }} aria-label={props[\"aria-label\"] ?? picker.props.translations?.chooseDate ?? translations.chooseDate} aria-haspopup=\"dialog\" aria-expanded={picker.open} aria-controls={`${picker.id}-dialog`} disabled={picker.props.disabled} data-scope=\"date-picker\" data-part=\"trigger\" onClick={composeEvent(onClick, () => picker.send({ type: \"TOGGLE\" }))}>{children ?? <CalendarGlyph />}</Part>;\n});\n\nconst Popover = React.forwardRef<HTMLDialogElement, Omit<React.ComponentPropsWithoutRef<\"dialog\">, \"open\"> & { anchored?: boolean }>(function Popover({ children, anchored = true, onCancel, onClose, onKeyDown, ...props }, ref) {\n const picker = usePicker();\n const dialog = React.useRef<HTMLDialogElement | null>(null);\n const latest = React.useRef(picker);\n latest.current = picker;\n\n React.useEffect(() => {\n const element = dialog.current;\n if (!element) return;\n if (picker.open && !element.open) {\n if (picker.props.modal === false) element.show(); else element.showModal();\n element.querySelector<HTMLElement>('[data-part=\"cell-trigger\"][tabindex=\"0\"]')?.focus();\n } else if (!picker.open && element.open) {\n element.close();\n picker.trigger.current?.focus();\n }\n }, [picker.open, picker.props.modal, picker.trigger]);\n\n React.useEffect(() => {\n if (!picker.open || !anchored) return;\n const element = dialog.current;\n const anchor = picker.trigger.current;\n const window = element?.ownerDocument.defaultView;\n if (!element || !anchor || !window) return;\n const properties = [\"position\", \"margin\", \"top\", \"left\", \"max-width\", \"max-height\", \"min-width\", \"min-height\", \"box-sizing\", \"overflow\"];\n const original = properties.map((property) => ({ property, value: element.style.getPropertyValue(property), priority: element.style.getPropertyPriority(property) }));\n const originalPlacement = element.getAttribute(\"data-placement\");\n const position = () => {\n const viewport = window.visualViewport;\n const width = viewport?.width ?? element.ownerDocument.documentElement.clientWidth;\n const height = viewport?.height ?? element.ownerDocument.documentElement.clientHeight;\n const offsetTop = viewport?.offsetTop ?? 0;\n const offsetLeft = viewport?.offsetLeft ?? 0;\n Object.assign(element.style, {\n position: \"fixed\", margin: \"0\", boxSizing: \"border-box\", overflow: \"auto\",\n minWidth: \"0\", minHeight: \"0\", maxWidth: `${Math.max(0, width - 8)}px`, maxHeight: `${Math.max(0, height - 8)}px`,\n });\n const rect = anchor.getBoundingClientRect();\n const { top, left, placement } = computeAnchorPosition(\n { top: rect.top - offsetTop, left: rect.left - offsetLeft, width: rect.width, height: rect.height },\n { width: element.offsetWidth, height: element.offsetHeight }, { width, height },\n );\n Object.assign(element.style, { top: `${top + offsetTop}px`, left: `${left + offsetLeft}px` });\n element.setAttribute(\"data-placement\", placement);\n };\n position();\n let frame: number | undefined;\n const schedulePosition = () => {\n if (frame !== undefined) return;\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n position();\n });\n };\n const observer = window.ResizeObserver ? new window.ResizeObserver(schedulePosition) : undefined;\n observer?.observe(element);\n observer?.observe(anchor);\n window.addEventListener(\"resize\", schedulePosition);\n window.addEventListener(\"scroll\", schedulePosition, true);\n window.visualViewport?.addEventListener(\"resize\", schedulePosition);\n window.visualViewport?.addEventListener(\"scroll\", schedulePosition);\n return () => {\n if (frame !== undefined) window.cancelAnimationFrame(frame);\n observer?.disconnect();\n window.removeEventListener(\"resize\", schedulePosition);\n window.removeEventListener(\"scroll\", schedulePosition, true);\n window.visualViewport?.removeEventListener(\"resize\", schedulePosition);\n window.visualViewport?.removeEventListener(\"scroll\", schedulePosition);\n for (const { property, value, priority } of original) {\n if (value) element.style.setProperty(property, value, priority);\n else element.style.removeProperty(property);\n }\n if (originalPlacement === null) element.removeAttribute(\"data-placement\");\n else element.setAttribute(\"data-placement\", originalPlacement);\n };\n }, [picker.open, anchored, picker.trigger]);\n\n React.useEffect(() => {\n const element = dialog.current;\n if (!picker.open || !element) return;\n const dismiss = (event: PointerEvent) => {\n if (!(event.target instanceof Node) || latest.current.trigger.current?.contains(event.target)) return;\n const rect = element.getBoundingClientRect();\n const onBackdrop = event.target === element && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom);\n if (!element.contains(event.target) || onBackdrop) latest.current.send({ type: \"CLOSE\" });\n };\n element.ownerDocument.addEventListener(\"pointerdown\", dismiss);\n return () => element.ownerDocument.removeEventListener(\"pointerdown\", dismiss);\n }, [picker.open]);\n\n // aria-labelledby wins wherever both are present, so the fallback name is only applied when\n // nothing else names the dialog.\n const labelledBy = props[\"aria-labelledby\"] ?? (props[\"aria-label\"] || !picker.labelled ? undefined : `${picker.id}-field-label`);\n const label = props[\"aria-label\"] ?? (labelledBy === undefined ? picker.props.translations?.chooseDate ?? translations.chooseDate : undefined);\n\n return <dialog {...props} ref={(node) => {\n dialog.current = node;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }} id={`${picker.id}-dialog`} aria-label={label} aria-labelledby={labelledBy} aria-modal={picker.props.modal !== false || undefined} data-scope=\"date-picker\" data-part=\"popover\"\n onKeyDown={composeEvent(onKeyDown, (event) => { if (picker.props.modal !== false) containTabFocus(event.currentTarget, event); })}\n onCancel={(event) => { onCancel?.(event); const canceled = event.defaultPrevented; event.preventDefault(); if (!canceled) picker.send({ type: \"CLOSE\" }); }}\n onClose={composeEvent(onClose, () => { if (picker.open) picker.send({ type: \"CLOSE\" }); })}>{picker.open ? children : null}</dialog>;\n});\n\nfunction PickerCalendar({ children, ...props }: Omit<CalendarProps, \"value\" | \"defaultValue\" | \"onChange\"> & Pick<PartProps, \"children\" | \"className\" | \"style\">) {\n const picker = usePicker();\n return <Calendar.Root {...picker.props} {...props} value={picker.value} onChange={picker.change} onSelect={() => picker.send({ type: \"SELECT\" })}>{children ?? <><Calendar.Header><Calendar.PrevButton /><Calendar.Heading /><Calendar.NextButton /></Calendar.Header><Calendar.Grid><Calendar.GridHeader /><Calendar.GridBody /></Calendar.Grid></>}</Calendar.Root>;\n}\n\nexport const DatePicker = { Root, Label, Field: DateField.Field, Segment: DateField.Segment, HiddenInput: DateField.HiddenInput, ClearButton: DateField.ClearButton, LiveRegion: DateField.LiveRegion, Trigger, Popover, Calendar: PickerCalendar };"],"mappings":"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","names":["Label","Trigger","Popover"]}
|
package/dist/date-field.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { P as PartProps, H as HiddenInputProps, C as ChronaConfig } from './form-BCAGbNh-.js';
|
|
2
2
|
import * as chrona_core from 'chrona-core';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import { F as FieldProps } from './field-
|
|
4
|
+
import { F as FieldProps } from './field-DayikvR6.js';
|
|
5
5
|
|
|
6
6
|
type DateFieldProps = FieldProps<"date">;
|
|
7
7
|
declare const DateField: {
|
|
@@ -12,7 +12,7 @@ declare const DateField: {
|
|
|
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">, "children" | "defaultValue" | "onChange" | "value" | "type"> & {
|
|
16
16
|
type: chrona_core.SegmentType;
|
|
17
17
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
18
18
|
HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
|
package/dist/date-field.js
CHANGED
package/dist/date-picker.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import * as React from 'react';
|
|
|
5
5
|
import { CalendarProps } from './calendar.js';
|
|
6
6
|
import { DateFieldProps } from './date-field.js';
|
|
7
7
|
import 'temporal-spec';
|
|
8
|
-
import './field-
|
|
8
|
+
import './field-DayikvR6.js';
|
|
9
9
|
|
|
10
10
|
interface DatePickerProps extends DateFieldProps {
|
|
11
11
|
open?: boolean;
|
|
@@ -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">, "children" | "defaultValue" | "onChange" | "value" | "type"> & {
|
|
51
51
|
type: chrona_core.SegmentType;
|
|
52
52
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
53
53
|
HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
|
package/dist/date-picker.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DatePicker,
|
|
3
3
|
useDatePicker
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-U4LLSRIH.js";
|
|
5
|
+
import "./chunk-2GZMCFFY.js";
|
|
6
|
+
import "./chunk-RCWVBOO6.js";
|
|
7
|
+
import "./chunk-JNQXKZO3.js";
|
|
8
8
|
import "./chunk-GN2YCKFZ.js";
|
|
9
9
|
export {
|
|
10
10
|
DatePicker,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { FieldKind, FieldOptions, FieldValue } from 'chrona-core';
|
|
1
|
+
import { FieldKind, FieldOptions, FieldValue, FieldInvalidReason } from 'chrona-core';
|
|
2
2
|
|
|
3
3
|
interface FieldProps<Kind extends FieldKind> extends FieldOptions<Kind> {
|
|
4
4
|
defaultValue?: FieldValue<Kind> | null;
|
|
5
5
|
onChange?: (value: FieldValue<Kind> | null) => void;
|
|
6
|
-
onInvalid?: (reason:
|
|
6
|
+
onInvalid?: (reason: FieldInvalidReason) => void;
|
|
7
7
|
id?: string;
|
|
8
8
|
describedBy?: string;
|
|
9
9
|
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DatePicker,
|
|
3
3
|
useDatePicker
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-U4LLSRIH.js";
|
|
5
5
|
import {
|
|
6
6
|
DateField,
|
|
7
7
|
useDateField
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2GZMCFFY.js";
|
|
9
9
|
import {
|
|
10
10
|
RangeCalendar,
|
|
11
11
|
useRangeCalendar
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-QQANBK5G.js";
|
|
13
13
|
import {
|
|
14
14
|
Calendar,
|
|
15
15
|
CalendarRoot,
|
|
16
16
|
useCalendar
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-RCWVBOO6.js";
|
|
18
18
|
import {
|
|
19
19
|
TimeField,
|
|
20
20
|
useTimeField
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import "./chunk-
|
|
21
|
+
} from "./chunk-ROJQDSGQ.js";
|
|
22
|
+
import "./chunk-JNQXKZO3.js";
|
|
23
23
|
import {
|
|
24
24
|
ChronaProvider
|
|
25
25
|
} from "./chunk-GN2YCKFZ.js";
|
package/dist/range-calendar.d.ts
CHANGED
|
@@ -26,25 +26,43 @@ declare function useRangeCalendar(input?: RangeCalendarProps): {
|
|
|
26
26
|
api: {
|
|
27
27
|
getCellProps: (date: PlainDate, month?: PlainDate) => {
|
|
28
28
|
"data-scope": string;
|
|
29
|
-
"aria-selected": boolean;
|
|
30
29
|
"data-selected": string | undefined;
|
|
31
30
|
"data-in-range": string | undefined;
|
|
32
31
|
"data-range-start": string | undefined;
|
|
33
32
|
"data-range-end": string | undefined;
|
|
34
33
|
"data-preview": string | undefined;
|
|
35
34
|
"data-invalid": string | undefined;
|
|
36
|
-
|
|
35
|
+
"aria-selected": boolean;
|
|
36
|
+
"data-date": string;
|
|
37
|
+
"data-focused": string | undefined;
|
|
38
|
+
"data-disabled": string | undefined;
|
|
39
|
+
"data-unavailable": string | undefined;
|
|
40
|
+
"data-outside-month": string | undefined;
|
|
41
|
+
"data-today": string | undefined;
|
|
37
42
|
role: "gridcell";
|
|
38
|
-
tabIndex: number;
|
|
39
|
-
"aria-label": string;
|
|
40
43
|
"aria-disabled": true | undefined;
|
|
41
|
-
"
|
|
44
|
+
"data-part": string;
|
|
45
|
+
};
|
|
46
|
+
getCellTriggerProps: (date: PlainDate, month?: PlainDate) => {
|
|
47
|
+
"data-scope": string;
|
|
48
|
+
"data-selected": string | undefined;
|
|
49
|
+
"data-in-range": string | undefined;
|
|
50
|
+
"data-range-start": string | undefined;
|
|
51
|
+
"data-range-end": string | undefined;
|
|
52
|
+
"data-preview": string | undefined;
|
|
53
|
+
"data-invalid": string | undefined;
|
|
42
54
|
"data-date": string;
|
|
43
55
|
"data-focused": string | undefined;
|
|
44
56
|
"data-disabled": string | undefined;
|
|
45
57
|
"data-unavailable": string | undefined;
|
|
46
58
|
"data-outside-month": string | undefined;
|
|
47
59
|
"data-today": string | undefined;
|
|
60
|
+
id: string;
|
|
61
|
+
type: "button";
|
|
62
|
+
tabIndex: number;
|
|
63
|
+
"aria-label": string;
|
|
64
|
+
"aria-disabled": true | undefined;
|
|
65
|
+
"aria-current": "date" | undefined;
|
|
48
66
|
"data-part": string;
|
|
49
67
|
};
|
|
50
68
|
getRootProps: () => {
|
|
@@ -84,25 +102,43 @@ declare function useRangeCalendar(input?: RangeCalendarProps): {
|
|
|
84
102
|
api: {
|
|
85
103
|
getCellProps: (date: PlainDate, month?: PlainDate) => {
|
|
86
104
|
"data-scope": string;
|
|
87
|
-
"aria-selected": boolean;
|
|
88
105
|
"data-selected": string | undefined;
|
|
89
106
|
"data-in-range": string | undefined;
|
|
90
107
|
"data-range-start": string | undefined;
|
|
91
108
|
"data-range-end": string | undefined;
|
|
92
109
|
"data-preview": string | undefined;
|
|
93
110
|
"data-invalid": string | undefined;
|
|
94
|
-
|
|
111
|
+
"aria-selected": boolean;
|
|
112
|
+
"data-date": string;
|
|
113
|
+
"data-focused": string | undefined;
|
|
114
|
+
"data-disabled": string | undefined;
|
|
115
|
+
"data-unavailable": string | undefined;
|
|
116
|
+
"data-outside-month": string | undefined;
|
|
117
|
+
"data-today": string | undefined;
|
|
95
118
|
role: "gridcell";
|
|
96
|
-
tabIndex: number;
|
|
97
|
-
"aria-label": string;
|
|
98
119
|
"aria-disabled": true | undefined;
|
|
99
|
-
"
|
|
120
|
+
"data-part": string;
|
|
121
|
+
};
|
|
122
|
+
getCellTriggerProps: (date: PlainDate, month?: PlainDate) => {
|
|
123
|
+
"data-scope": string;
|
|
124
|
+
"data-selected": string | undefined;
|
|
125
|
+
"data-in-range": string | undefined;
|
|
126
|
+
"data-range-start": string | undefined;
|
|
127
|
+
"data-range-end": string | undefined;
|
|
128
|
+
"data-preview": string | undefined;
|
|
129
|
+
"data-invalid": string | undefined;
|
|
100
130
|
"data-date": string;
|
|
101
131
|
"data-focused": string | undefined;
|
|
102
132
|
"data-disabled": string | undefined;
|
|
103
133
|
"data-unavailable": string | undefined;
|
|
104
134
|
"data-outside-month": string | undefined;
|
|
105
135
|
"data-today": string | undefined;
|
|
136
|
+
id: string;
|
|
137
|
+
type: "button";
|
|
138
|
+
tabIndex: number;
|
|
139
|
+
"aria-label": string;
|
|
140
|
+
"aria-disabled": true | undefined;
|
|
141
|
+
"aria-current": "date" | undefined;
|
|
106
142
|
"data-part": string;
|
|
107
143
|
};
|
|
108
144
|
getRootProps: () => {
|
|
@@ -149,7 +185,7 @@ declare function HiddenInput({ name, form, id, disabled, ...inputProps }: Hidden
|
|
|
149
185
|
}): React.JSX.Element;
|
|
150
186
|
declare const RangeCalendar: {
|
|
151
187
|
Root: typeof Root;
|
|
152
|
-
Cell: React.ForwardRefExoticComponent<Omit<
|
|
188
|
+
Cell: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLElement> & {
|
|
153
189
|
asChild?: boolean;
|
|
154
190
|
} & {
|
|
155
191
|
date: PlainDate;
|
|
@@ -189,6 +225,9 @@ declare const RangeCalendar: {
|
|
|
189
225
|
} & {
|
|
190
226
|
day: Weekday;
|
|
191
227
|
} & React.RefAttributes<HTMLElement>>;
|
|
228
|
+
CellTrigger: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
|
|
229
|
+
asChild?: boolean;
|
|
230
|
+
} & React.RefAttributes<HTMLElement>>;
|
|
192
231
|
};
|
|
193
232
|
|
|
194
233
|
export { RangeCalendar, type RangeCalendarProps, useRangeCalendar };
|
package/dist/range-calendar.js
CHANGED
package/dist/time-field.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { P as PartProps, H as HiddenInputProps, C as ChronaConfig } from './form-BCAGbNh-.js';
|
|
2
2
|
import * as chrona_core from 'chrona-core';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import { F as FieldProps } from './field-
|
|
4
|
+
import { F as FieldProps } from './field-DayikvR6.js';
|
|
5
5
|
|
|
6
6
|
type TimeFieldProps = FieldProps<"time">;
|
|
7
7
|
declare const TimeField: {
|
|
@@ -12,7 +12,7 @@ declare const TimeField: {
|
|
|
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">, "children" | "defaultValue" | "onChange" | "value" | "type"> & {
|
|
16
16
|
type: chrona_core.SegmentType;
|
|
17
17
|
} & React.RefAttributes<HTMLInputElement>>;
|
|
18
18
|
HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
|
package/dist/time-field.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chrona-react",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Headless Temporal-native React date and time primitives",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"sideEffects": false,
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|
|
34
|
+
"AGENTS.md",
|
|
34
35
|
"LICENSE"
|
|
35
36
|
],
|
|
36
37
|
"exports": {
|
|
@@ -60,7 +61,7 @@
|
|
|
60
61
|
}
|
|
61
62
|
},
|
|
62
63
|
"dependencies": {
|
|
63
|
-
"chrona-core": "^0.1
|
|
64
|
+
"chrona-core": "^0.2.1"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
67
|
"react": ">=18.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/date-picker.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { computeAnchorPosition, containTabFocus, transitionPicker, translations, type PlainDate, type PickerEvent } from \"chrona-core\";\nimport { Calendar, type CalendarProps } from \"./calendar\";\nimport { DateField, type DateFieldProps } from \"./date-field\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useChronaConfig } from \"./provider\";\n\nexport interface DatePickerProps extends DateFieldProps {\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n modal?: boolean;\n timeZone?: string;\n firstDayOfWeek?: number;\n fixedWeeks?: boolean;\n numberOfMonths?: number;\n pagedNavigation?: boolean;\n}\n\ninterface PickerContext {\n props: DatePickerProps;\n options: DatePickerProps;\n state: { value: PlainDate | null; open: boolean };\n id: string;\n value: PlainDate | null;\n change: (value: PlainDate | null) => void;\n open: boolean;\n send: (event: PickerEvent) => void;\n trigger: { current: HTMLElement | null };\n labelled: boolean;\n registerLabel: (present: boolean) => void;\n}\n\nconst Context = React.createContext<PickerContext | null>(null);\nfunction usePicker() {\n const value = React.useContext(Context);\n if (!value) throw new Error(\"DatePicker parts must be inside DatePicker.Root.\");\n return value;\n}\n\nfunction Root({ children, asChild, className, style, ...input }: DatePickerProps & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const picker = useDatePicker(input);\n return <Context.Provider value={picker}><Part asChild={asChild} className={className} style={style} dir={picker.props.dir} data-scope=\"date-picker\" data-part=\"root\"><DateField.Root {...picker.props} id={`${picker.id}-field`} value={picker.value} onChange={picker.change}>{children}</DateField.Root></Part></Context.Provider>;\n}\n\nexport function useDatePicker(input: DatePickerProps = {}): PickerContext {\n const props = useChronaConfig(input);\n const generatedId = React.useId();\n const id = props.id ?? generatedId;\n const [uncontrolledValue, setValue] = React.useState(props.defaultValue ?? null);\n const [uncontrolledOpen, setOpen] = React.useState(props.defaultOpen ?? false);\n const value = props.value === undefined ? uncontrolledValue : props.value;\n const open = props.open ?? uncontrolledOpen;\n const trigger = React.useRef<HTMLElement | null>(null);\n const [labelled, registerLabel] = React.useState(false);\n function change(next: PlainDate | null) {\n if (props.value === undefined) setValue(next);\n props.onChange?.(next);\n }\n function send(event: PickerEvent) {\n const result = transitionPicker({ open }, event, props);\n for (const effect of result.effects) if (effect.type === \"openChange\") {\n if (props.open === undefined) setOpen(effect.open);\n props.onOpenChange?.(effect.open);\n }\n }\n return { props, options: props, state: { value, open }, id, value, change, open, send, trigger, labelled, registerLabel };\n}\n\nconst Label = React.forwardRef<HTMLElement, PartProps>(function Label(props, ref) {\n const { registerLabel } = usePicker();\n React.useEffect(() => {\n registerLabel(true);\n return () => registerLabel(false);\n }, [registerLabel]);\n return <DateField.Label {...props} ref={ref} />;\n});\n\nconst Trigger = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<\"button\"> & { asChild?: boolean }>(function Trigger({ onClick, ...props }, ref) {\n const picker = usePicker();\n return <Part as=\"button\" {...props} type=\"button\" ref={(node) => {\n picker.trigger.current = node;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }} aria-label={props[\"aria-label\"] ?? picker.props.translations?.chooseDate ?? translations.chooseDate} aria-haspopup=\"dialog\" aria-expanded={picker.open} aria-controls={`${picker.id}-dialog`} disabled={picker.props.disabled} data-scope=\"date-picker\" data-part=\"trigger\" onClick={composeEvent(onClick, () => picker.send({ type: \"TOGGLE\" }))} />;\n});\n\nconst Popover = React.forwardRef<HTMLDialogElement, Omit<React.ComponentPropsWithoutRef<\"dialog\">, \"open\"> & { anchored?: boolean }>(function Popover({ children, anchored = true, onCancel, onClose, onKeyDown, ...props }, ref) {\n const picker = usePicker();\n const dialog = React.useRef<HTMLDialogElement | null>(null);\n const latest = React.useRef(picker);\n latest.current = picker;\n\n React.useEffect(() => {\n const element = dialog.current;\n if (!element) return;\n if (picker.open && !element.open) {\n if (picker.props.modal === false) element.show(); else element.showModal();\n element.querySelector<HTMLElement>('[data-part=\"cell\"][tabindex=\"0\"]')?.focus();\n } else if (!picker.open && element.open) {\n element.close();\n picker.trigger.current?.focus();\n }\n }, [picker.open, picker.props.modal, picker.trigger]);\n\n React.useEffect(() => {\n if (!picker.open || !anchored) return;\n const element = dialog.current;\n const anchor = picker.trigger.current;\n const window = element?.ownerDocument.defaultView;\n if (!element || !anchor || !window) return;\n const properties = [\"position\", \"margin\", \"top\", \"left\", \"max-width\", \"max-height\", \"min-width\", \"min-height\", \"box-sizing\", \"overflow\"];\n const original = properties.map((property) => ({ property, value: element.style.getPropertyValue(property), priority: element.style.getPropertyPriority(property) }));\n const originalPlacement = element.getAttribute(\"data-placement\");\n const position = () => {\n const viewport = window.visualViewport;\n const width = viewport?.width ?? element.ownerDocument.documentElement.clientWidth;\n const height = viewport?.height ?? element.ownerDocument.documentElement.clientHeight;\n const offsetTop = viewport?.offsetTop ?? 0;\n const offsetLeft = viewport?.offsetLeft ?? 0;\n Object.assign(element.style, {\n position: \"fixed\", margin: \"0\", boxSizing: \"border-box\", overflow: \"auto\",\n minWidth: \"0\", minHeight: \"0\", maxWidth: `${Math.max(0, width - 8)}px`, maxHeight: `${Math.max(0, height - 8)}px`,\n });\n const rect = anchor.getBoundingClientRect();\n const { top, left, placement } = computeAnchorPosition(\n { top: rect.top - offsetTop, left: rect.left - offsetLeft, width: rect.width, height: rect.height },\n { width: element.offsetWidth, height: element.offsetHeight }, { width, height },\n );\n Object.assign(element.style, { top: `${top + offsetTop}px`, left: `${left + offsetLeft}px` });\n element.setAttribute(\"data-placement\", placement);\n };\n position();\n let frame: number | undefined;\n const schedulePosition = () => {\n if (frame !== undefined) return;\n frame = window.requestAnimationFrame(() => {\n frame = undefined;\n position();\n });\n };\n const observer = window.ResizeObserver ? new window.ResizeObserver(schedulePosition) : undefined;\n observer?.observe(element);\n observer?.observe(anchor);\n window.addEventListener(\"resize\", schedulePosition);\n window.addEventListener(\"scroll\", schedulePosition, true);\n window.visualViewport?.addEventListener(\"resize\", schedulePosition);\n window.visualViewport?.addEventListener(\"scroll\", schedulePosition);\n return () => {\n if (frame !== undefined) window.cancelAnimationFrame(frame);\n observer?.disconnect();\n window.removeEventListener(\"resize\", schedulePosition);\n window.removeEventListener(\"scroll\", schedulePosition, true);\n window.visualViewport?.removeEventListener(\"resize\", schedulePosition);\n window.visualViewport?.removeEventListener(\"scroll\", schedulePosition);\n for (const { property, value, priority } of original) {\n if (value) element.style.setProperty(property, value, priority);\n else element.style.removeProperty(property);\n }\n if (originalPlacement === null) element.removeAttribute(\"data-placement\");\n else element.setAttribute(\"data-placement\", originalPlacement);\n };\n }, [picker.open, anchored, picker.trigger]);\n\n React.useEffect(() => {\n const element = dialog.current;\n if (!picker.open || !element) return;\n const dismiss = (event: PointerEvent) => {\n if (!(event.target instanceof Node) || latest.current.trigger.current?.contains(event.target)) return;\n const rect = element.getBoundingClientRect();\n const onBackdrop = event.target === element && (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom);\n if (!element.contains(event.target) || onBackdrop) latest.current.send({ type: \"CLOSE\" });\n };\n element.ownerDocument.addEventListener(\"pointerdown\", dismiss);\n return () => element.ownerDocument.removeEventListener(\"pointerdown\", dismiss);\n }, [picker.open]);\n\n return <dialog {...props} ref={(node) => {\n dialog.current = node;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }} id={`${picker.id}-dialog`} aria-label={props[\"aria-label\"] ?? picker.props.translations?.chooseDate ?? translations.chooseDate} aria-labelledby={props[\"aria-labelledby\"] ?? (props[\"aria-label\"] || !picker.labelled ? undefined : `${picker.id}-field-label`)} aria-modal={picker.props.modal !== false || undefined} data-scope=\"date-picker\" data-part=\"popover\"\n onKeyDown={composeEvent(onKeyDown, (event) => { if (picker.props.modal !== false) containTabFocus(event.currentTarget, event); })}\n onCancel={(event) => { onCancel?.(event); const canceled = event.defaultPrevented; event.preventDefault(); if (!canceled) picker.send({ type: \"CLOSE\" }); }}\n onClose={composeEvent(onClose, () => { if (picker.open) picker.send({ type: \"CLOSE\" }); })}>{picker.open ? children : null}</dialog>;\n});\n\nfunction PickerCalendar({ children, ...props }: Omit<CalendarProps, \"value\" | \"defaultValue\" | \"onChange\"> & Pick<PartProps, \"children\" | \"className\" | \"style\">) {\n const picker = usePicker();\n return <Calendar.Root {...picker.props} {...props} value={picker.value} onChange={picker.change} onSelect={() => picker.send({ type: \"SELECT\" })}>{children ?? <><Calendar.Header><Calendar.PrevButton /><Calendar.Heading /><Calendar.NextButton /></Calendar.Header><Calendar.Grid><Calendar.GridHeader /><Calendar.GridBody /></Calendar.Grid></>}</Calendar.Root>;\n}\n\nexport const DatePicker = { Root, Label, Field: DateField.Field, Segment: DateField.Segment, HiddenInput: DateField.HiddenInput, ClearButton: DateField.ClearButton, LiveRegion: DateField.LiveRegion, Trigger, Popover, Calendar: PickerCalendar };"],"mappings":"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","names":["Label","Trigger","Popover"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/calendar.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { calendarKeys, connectCalendar, createCalendar, createStore, formatDate, getNumberFormatter, resolveWeekStart, sameDate, syncCalendar, temporal, transitionCalendar, translations, weeksInMonthView, type CalendarEvent, type CalendarOptions, type PlainDate } from \"chrona-core\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useChronaConfig } from \"./provider\";\nimport { useFormReset, type HiddenInputProps } from \"./form\";\n\nexport interface CalendarProps extends CalendarOptions {\n defaultValue?: PlainDate | null;\n defaultFocusedValue?: PlainDate;\n onChange?: (value: PlainDate | null) => void;\n onSelect?: (value: PlainDate) => void;\n onFocusedValueChange?: (value: PlainDate) => void;\n id?: string;\n}\n\nexport function useCalendar(props: CalendarProps = {}) {\n const options = useChronaConfig(props);\n const generatedId = React.useId();\n const id = props.id ?? generatedId;\n const [store] = React.useState(() => createStore(createCalendar({ ...options, value: props.value !== undefined ? props.value : props.defaultValue, focusedValue: props.focusedValue ?? props.defaultFocusedValue })));\n const snapshot = React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);\n // The store is the single source of truth; controlled props are reconciled into it by syncCalendar.\n const state = syncCalendar(snapshot, { ...options, value: props.value, focusedValue: props.focusedValue });\n React.useEffect(() => { store.setState(state); });\n const rootRef = React.useRef<HTMLElement | null>(null);\n const pendingFocus = React.useRef(false);\n const [announcement, setAnnouncement] = React.useState(\"\");\n\n React.useEffect(() => {\n if (pendingFocus.current) {\n pendingFocus.current = false;\n rootRef.current?.querySelector<HTMLElement>('[data-part=\"cell\"][tabindex=\"0\"]')?.focus();\n }\n });\n\n function send(event: CalendarEvent) {\n const dir = options.dir ?? (rootRef.current?.closest(\"[dir]\")?.getAttribute(\"dir\") === \"rtl\" ? \"rtl\" : \"ltr\");\n const result = transitionCalendar(state, event, { ...options, dir });\n store.setState(result.state);\n for (const effect of result.effects) {\n if (effect.type === \"focus\") {\n pendingFocus.current = true;\n if (!sameDate(effect.value, state.focusedValue)) props.onFocusedValueChange?.(effect.value);\n } else if (effect.type === \"change\") {\n props.onChange?.(effect.value);\n setAnnouncement(effect.value ? (options.translations?.selected ?? translations.selected)(formatDate(effect.value, options.locale, { dateStyle: \"full\" })) : \"\");\n } else {\n props.onSelect?.(effect.value);\n }\n }\n }\n\n return {\n state, options, send, rootRef, announcement,\n api: connectCalendar(state, { ...options, id, today: temporal().Now.plainDateISO(options.timeZone) }),\n months: Array.from({ length: options.numberOfMonths ?? 1 }, (_, index) => state.visibleMonth.add({ months: index })),\n };\n}\n\ntype CalendarContextValue = ReturnType<typeof useCalendar>;\nconst Context = React.createContext<CalendarContextValue | null>(null);\nconst MonthContext = React.createContext<PlainDate | null>(null);\n\nfunction useContext() {\n const value = React.useContext(Context);\n if (!value) throw new Error(\"Calendar parts must be inside Calendar.Root.\");\n return value;\n}\n\nexport function CalendarRoot({ children, asChild, className, style, ...props }: CalendarProps & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const calendar = useCalendar(props);\n return <CalendarSurface calendar={calendar} id={props.id} asChild={asChild} className={className} style={style}>{children}</CalendarSurface>;\n}\n\nexport function CalendarSurface({ calendar, ...props }: PartProps & { calendar: CalendarContextValue }) {\n return <Context.Provider value={calendar}><Part {...calendar.api.getRootProps()} {...props} ref={calendar.rootRef} /></Context.Provider>;\n}\n\nconst Header = React.forwardRef<HTMLElement, PartProps>(function Header(props, ref) {\n return <Part {...props} ref={ref} data-scope=\"calendar\" data-part=\"header\" />;\n});\n\nconst Heading = React.forwardRef<HTMLElement, PartProps>(function Heading({ children, ...props }, ref) {\n const { months, options } = useContext();\n const month = React.useContext(MonthContext);\n return <Part as=\"h2\" {...props} ref={ref} data-scope=\"calendar\" data-part=\"heading\" aria-live=\"polite\" aria-atomic=\"true\">{children ?? (month ? [month] : months).map((date) => formatDate(date, options.locale, { month: \"long\", year: \"numeric\" })).join(options.translations?.rangeSeparator ?? translations.rangeSeparator)}</Part>;\n});\n\ntype ButtonProps = React.ComponentPropsWithoutRef<\"button\"> & { asChild?: boolean };\n\nconst PrevButton = React.forwardRef<HTMLElement, ButtonProps>(function PrevButton({ onClick, ...props }, ref) {\n const { api, send } = useContext();\n return <Part as=\"button\" {...props} {...api.getPrevButtonProps()} ref={ref} onClick={composeEvent(onClick, () => send({ type: \"PAGE\", direction: -1 }))} />;\n});\n\nconst NextButton = React.forwardRef<HTMLElement, ButtonProps>(function NextButton({ onClick, ...props }, ref) {\n const { api, send } = useContext();\n return <Part as=\"button\" {...props} {...api.getNextButtonProps()} ref={ref} onClick={composeEvent(onClick, () => send({ type: \"PAGE\", direction: 1 }))} />;\n});\n\nconst Grid = React.forwardRef<HTMLElement, PartProps & { monthIndex?: number }>(function Grid({ monthIndex = 0, children, ...props }, ref) {\n const { api, months } = useContext();\n const month = months[monthIndex];\n if (!month) throw new Error(\"Calendar.Grid monthIndex is outside numberOfMonths.\");\n return <MonthContext.Provider value={month}><Part {...props} {...api.getGridProps(month)} ref={ref}>{children}</Part></MonthContext.Provider>;\n});\n\nfunction useMonth() {\n const context = useContext();\n const month = React.useContext(MonthContext) ?? context.state.visibleMonth;\n return { ...context, month, weeks: weeksInMonthView(month.toPlainYearMonth(), resolveWeekStart(context.options.locale, context.options.firstDayOfWeek), context.options.fixedWeeks) };\n}\n\nexport interface Weekday { date: PlainDate; label: string }\n\nconst GridHeader = React.forwardRef<HTMLElement, Omit<PartProps, \"children\"> & { children?: (day: Weekday) => React.ReactNode }>(function GridHeader({ children, ...props }, ref) {\n const { weeks, options } = useMonth();\n return <Part {...props} ref={ref} role=\"row\" data-scope=\"calendar\" data-part=\"grid-header\">{weeks[0]!.map((date) => {\n const day = { date, label: formatDate(date, options.locale, { weekday: \"short\" }) };\n return <React.Fragment key={date.toString()}>{children ? children(day) : <HeaderCell day={day} />}</React.Fragment>;\n })}</Part>;\n});\n\nconst HeaderCell = React.forwardRef<HTMLElement, PartProps & { day: Weekday }>(function HeaderCell({ day, children, ...props }, ref) {\n const { options } = useContext();\n return <Part {...props} ref={ref} role=\"columnheader\" aria-label={formatDate(day.date, options.locale, { weekday: \"long\" })} data-scope=\"calendar\" data-part=\"header-cell\">{children ?? day.label}</Part>;\n});\n\nconst GridBody = React.forwardRef<HTMLElement, Omit<PartProps, \"children\"> & { children?: (date: PlainDate) => React.ReactNode }>(function GridBody({ children, ...props }, ref) {\n const { weeks } = useMonth();\n return <Part {...props} ref={ref} role=\"rowgroup\" data-scope=\"calendar\" data-part=\"grid-body\">{weeks.map((week) => <div key={week[0]!.toString()} role=\"row\" data-scope=\"calendar\" data-part=\"row\">{week.map((date) => <React.Fragment key={date.toString()}>{children ? children(date) : <Cell date={date} />}</React.Fragment>)}</div>)}</Part>;\n});\n\nconst Cell = React.forwardRef<HTMLElement, ButtonProps & { date: PlainDate }>(function Cell({ date, children, onClick, onKeyDown, onFocus, ...props }, ref) {\n const { api, send, month, options } = useMonth();\n const cellProps = api.getCellProps(date, month);\n // aria-disabled instead of native disabled keeps out-of-range cells discoverable by screen readers.\n return <Part as=\"button\" {...props} {...cellProps} type=\"button\" ref={ref}\n onFocus={composeEvent(onFocus, () => { if (!options.disabled) send({ type: \"FOCUS\", date }); })}\n onClick={composeEvent(onClick, () => send({ type: \"SELECT\", date }))}\n onKeyDown={composeEvent(onKeyDown, (event) => {\n if (!calendarKeys.has(event.key) || event.altKey || event.ctrlKey || event.metaKey) return;\n event.preventDefault();\n send({ type: \"KEY_DOWN\", key: event.key, shiftKey: event.shiftKey });\n })}>{children ?? getNumberFormatter(options.locale, { useGrouping: false }).format(date.day)}</Part>;\n});\n\nconst LiveRegion = React.forwardRef<HTMLElement, PartProps>(function LiveRegion(props, ref) {\n const { announcement } = useContext();\n return <Part {...props} ref={ref} role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" data-scope=\"calendar\" data-part=\"live-region\">{announcement}</Part>;\n});\n\nconst ClearButton = React.forwardRef<HTMLElement, ButtonProps>(function ClearButton({ onClick, ...props }, ref) {\n const { options, send, state } = useContext();\n return <Part as=\"button\" {...props} ref={ref} type=\"button\" data-scope=\"calendar\" data-part=\"clear-button\" aria-label={options.translations?.clear ?? translations.clear} disabled={options.disabled || options.readOnly || state.value === null} onClick={composeEvent(onClick, () => send({ type: \"CLEAR\" }))} />;\n});\n\nfunction HiddenInput(props: HiddenInputProps) {\n const { state, options, send } = useContext();\n const input = React.useRef<HTMLInputElement>(null);\n useFormReset(input, props.form, () => send({ type: \"RESET\", value: options.defaultValue ?? null }));\n return <input {...props} ref={input} type=\"hidden\" disabled={options.disabled || props.disabled} value={state.value?.toString() ?? \"\"} data-scope=\"calendar\" data-part=\"hidden-input\" />;\n}\n\nexport const Calendar = { Root: CalendarRoot, Header, Heading, PrevButton, NextButton, Grid, GridHeader, HeaderCell, GridBody, Cell, LiveRegion, ClearButton, HiddenInput };"],"mappings":"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","names":["useContext","Header","Heading","PrevButton","NextButton","Grid","GridHeader","HeaderCell","GridBody","Cell","LiveRegion","ClearButton"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/field.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { connectField, createField, createStore, digitValue, fieldHourCycle, transitionField, translations, type FieldEvent, type FieldKind, type FieldOptions, type FieldValue, type SegmentType } from \"chrona-core\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useChronaConfig } from \"./provider\";\nimport { useFormReset, type HiddenInputProps } from \"./form\";\n\nexport interface FieldProps<Kind extends FieldKind> extends FieldOptions<Kind> {\n defaultValue?: FieldValue<Kind> | null;\n onChange?: (value: FieldValue<Kind> | null) => void;\n onInvalid?: (reason: \"range\" | \"unavailable\") => void;\n id?: string;\n describedBy?: string;\n}\n\nfunction equalValues(first: { equals: (other: never) => boolean } | null, second: { equals: (other: never) => boolean } | null) {\n return first === null || second === null ? first === second : first.equals(second as never);\n}\n\nexport function useField<Kind extends FieldKind>(kind: Kind, props: FieldProps<Kind>) {\n const options = useChronaConfig(props);\n const generatedId = React.useId();\n const id = props.id ?? generatedId;\n const [store] = React.useState(() => createStore(createField(kind, { ...options, value: props.value !== undefined ? props.value : props.defaultValue })));\n const snapshot = React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);\n const value = props.value !== undefined ? props.value : snapshot.value;\n const placeholderValue = options.placeholderValue ?? snapshot.reference;\n const { minValue, maxValue, locale, hourCycle, granularity } = options;\n const configured = React.useMemo(() => createField(kind, { value, placeholderValue, minValue, maxValue, locale, hourCycle, granularity }), [kind, value, placeholderValue, minValue, maxValue, locale, hourCycle, granularity]);\n const cycle = fieldHourCycle(options);\n const configuration = `${cycle}:${props.granularity ?? \"minute\"}`;\n const previousConfiguration = React.useRef(configuration);\n const state = props.value !== undefined && !equalValues(snapshot.value, props.value)\n ? configured\n : kind === \"time\" && configuration !== previousConfiguration.current\n ? configured\n : snapshot;\n React.useEffect(() => {\n if (previousConfiguration.current !== configuration) {\n previousConfiguration.current = configuration;\n store.setState(state);\n }\n }, [configuration, state, store]);\n const groupRef = React.useRef<HTMLElement | null>(null);\n const [invalidReason, setInvalidReason] = React.useState<\"range\" | \"unavailable\" | null>(null);\n const announcement = invalidReason === null ? \"\" : invalidReason === \"range\"\n ? options.translations?.invalidRange ?? translations.invalidRange\n : options.translations?.unavailable ?? translations.unavailable;\n\n function moveFocus(segment: SegmentType, offset: number) {\n const elements = Array.from(groupRef.current?.querySelectorAll<HTMLInputElement>(\"input[data-segment]\") ?? []);\n const index = elements.findIndex((element) => element.dataset.segment === segment);\n elements[index + offset]?.focus();\n }\n\n function send(event: FieldEvent) {\n const result = transitionField(state, event, options);\n store.setState(result.state);\n if (!result.state.invalid) setInvalidReason(null);\n for (const effect of result.effects) {\n if (effect.type === \"change\") props.onChange?.(effect.value);\n if (effect.type === \"invalid\") { setInvalidReason(effect.reason); props.onInvalid?.(effect.reason); }\n if (effect.type === \"advance\") queueMicrotask(() => moveFocus(effect.segment, 1));\n }\n }\n\n function reset() {\n setInvalidReason(null);\n const value = props.defaultValue ?? null;\n store.setState(createField(kind, { ...options, value }));\n if (!equalValues(state.value, value)) props.onChange?.(value);\n }\n\n const [labelled, setLabelled] = React.useState(false);\n return { id, state, options, send, reset, moveFocus, groupRef, announcement, registerLabel: setLabelled, api: connectField(state, { ...options, id, labelId: labelled ? `${id}-label` : undefined }) };\n}\n\nexport function createFieldComponents<Kind extends FieldKind>(kind: Kind) {\n const Context = React.createContext<ReturnType<typeof useField<Kind>> | null>(null);\n function useContext() {\n const context = React.useContext(Context);\n if (!context) throw new Error(`${kind === \"date\" ? \"DateField\" : \"TimeField\"} parts must be inside their Root.`);\n return context;\n }\n\n function Root({ children, asChild, className, style, ...props }: FieldProps<Kind> & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const context = useField(kind, props);\n return <Context.Provider value={context}><Part asChild={asChild} className={className} style={style} id={props.id} dir={context.options.dir} data-scope={`${kind}-field`} data-part=\"root\">{children}</Part></Context.Provider>;\n }\n\n const Label = React.forwardRef<HTMLElement, PartProps>(function Label(props, ref) {\n const { id, registerLabel } = useContext();\n React.useEffect(() => {\n registerLabel(true);\n return () => registerLabel(false);\n }, [registerLabel]);\n return <Part as=\"span\" {...props} ref={ref} id={`${id}-label`} data-scope={`${kind}-field`} data-part=\"label\" />;\n });\n\n const Segment = React.forwardRef<HTMLInputElement, Omit<React.ComponentPropsWithoutRef<\"input\">, \"type\" | \"value\" | \"defaultValue\" | \"onChange\" | \"children\"> & { type: SegmentType }>(function Segment({ type, onKeyDown, onFocus, onBlur, onPaste, onDrop, ...props }, ref) {\n const { state, api, options, send, moveFocus, groupRef } = useContext();\n if (!(type in state.parts)) throw new Error(`The ${type} segment is not enabled in this field.`);\n const { display, ...segmentProps } = api.getSegmentProps(type);\n return <input {...props} {...segmentProps} ref={ref} type=\"text\" inputMode={type === \"dayPeriod\" ? \"text\" : \"numeric\"} autoComplete=\"off\" spellCheck={false} value={display} disabled={options.disabled} readOnly={options.readOnly}\n onFocus={composeEvent(onFocus, (event) => { event.currentTarget.select(); })}\n onBlur={composeEvent(onBlur, () => send({ type: \"BLUR\" }))}\n onPaste={composeEvent(onPaste, (event) => event.preventDefault())}\n onDrop={composeEvent(onDrop, (event) => event.preventDefault())}\n onChange={(event) => {\n const native = event.nativeEvent as InputEvent;\n const digit = digitValue(native.data ?? \"\", options.locale);\n event.currentTarget.value = display;\n if (native.inputType === \"insertText\" && digit !== null) send({ type: \"DIGIT\", segment: type, digit });\n else if (native.inputType === \"deleteContentBackward\" || native.inputType === \"deleteContentForward\") send({ type: \"CLEAR\", segment: type });\n }}\n onKeyDown={composeEvent(onKeyDown, (event) => {\n if (event.altKey || event.ctrlKey || event.metaKey || event.nativeEvent.isComposing) return;\n const digit = digitValue(event.key, options.locale);\n const dir = options.dir ?? (groupRef.current?.closest(\"[dir]\")?.getAttribute(\"dir\") === \"rtl\" ? \"rtl\" : \"ltr\");\n if (digit !== null) { event.preventDefault(); send({ type: \"DIGIT\", segment: type, digit }); return; }\n switch (event.key) {\n case \"ArrowUp\": case \"ArrowDown\": event.preventDefault(); send({ type: \"STEP\", segment: type, direction: event.key === \"ArrowUp\" ? 1 : -1 }); break;\n case \"Home\": case \"End\": event.preventDefault(); send({ type: \"EDGE\", segment: type, edge: event.key === \"Home\" ? \"min\" : \"max\" }); break;\n case \"Backspace\": case \"Delete\": event.preventDefault(); send({ type: \"CLEAR\", segment: type }); break;\n case \"ArrowLeft\": case \"ArrowRight\": event.preventDefault(); moveFocus(type, (event.key === \"ArrowRight\" ? 1 : -1) * (dir === \"rtl\" ? -1 : 1)); break;\n default:\n if (type === \"dayPeriod\" && [\"a\", \"p\"].includes(event.key.toLowerCase())) {\n event.preventDefault(); send({ type: \"PERIOD\", value: event.key.toLowerCase() === \"a\" ? 0 : 1 });\n }\n }\n })} />;\n });\n\n const Field = React.forwardRef<HTMLElement, PartProps>(function Field({ children, ...props }, ref) {\n const { api, groupRef } = useContext();\n return <Part {...props} {...api.getGroupProps()} ref={(node) => {\n groupRef.current = node;\n if (typeof ref === \"function\") ref(node); else if (ref) ref.current = node;\n }}>{children ?? api.segments.map((segment, index) => segment.type === \"literal\" ? <span key={index} aria-hidden=\"true\" data-scope={`${kind}-field`} data-part=\"literal\">{segment.value}</span> : <Segment key={segment.type} type={segment.type} />)}</Part>;\n });\n\n function HiddenInput(props: HiddenInputProps) {\n const { state, options, reset } = useContext();\n const input = React.useRef<HTMLInputElement>(null);\n useFormReset(input, props.form, reset);\n return <input {...props} ref={input} type=\"hidden\" value={state.value?.toString() ?? \"\"} disabled={options.disabled || props.disabled} data-scope={`${kind}-field`} data-part=\"hidden-input\" />;\n }\n\n const ClearButton = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<\"button\"> & { asChild?: boolean }>(function ClearButton({ onClick, ...props }, ref) {\n const { options, send } = useContext();\n return <Part as=\"button\" {...props} ref={ref} type=\"button\" aria-label={options.translations?.clear ?? translations.clear} disabled={options.disabled || options.readOnly} data-scope={`${kind}-field`} data-part=\"clear-button\" onClick={composeEvent(onClick, () => send({ type: \"CLEAR\" }))} />;\n });\n\n const LiveRegion = React.forwardRef<HTMLElement, PartProps>(function LiveRegion(props, ref) {\n const { announcement } = useContext();\n return <Part {...props} ref={ref} role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" data-scope={`${kind}-field`} data-part=\"live-region\">{announcement}</Part>;\n });\n\n return { Root, Label, Field, Segment, HiddenInput, ClearButton, LiveRegion };\n}"],"mappings":"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","names":["value","useContext","Label","Segment","Field","ClearButton","LiveRegion"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/range-calendar.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { createRange, createStore, formatDate, getRangeCellProps, transitionRange, translations, validateRange, type DateRange, type PlainDate, type RangeEvent } from \"chrona-core\";\nimport { Calendar, CalendarSurface, useCalendar, type CalendarProps } from \"./calendar\";\nimport { Part, composeEvent, type PartProps } from \"./part\";\nimport { useFormReset, type HiddenInputProps } from \"./form\";\nimport { useChronaConfig } from \"./provider\";\n\nexport interface RangeCalendarProps extends Omit<CalendarProps, \"value\" | \"defaultValue\" | \"onChange\"> {\n value?: DateRange | null;\n defaultValue?: DateRange | null;\n onChange?: (value: DateRange | null) => void;\n onRangeStartChange?: (value: PlainDate | null) => void;\n onInvalid?: () => void;\n}\n\nexport function useRangeCalendar(input: RangeCalendarProps = {}) {\n const props = useChronaConfig(input);\n const [store] = React.useState(() => createStore(createRange(props.value !== undefined ? props.value : props.defaultValue)));\n const snapshot = React.useSyncExternalStore(store.subscribe, store.getSnapshot, store.getServerSnapshot);\n if (props.value) validateRange(props.value);\n const state = { ...snapshot, value: props.value === undefined ? snapshot.value : props.value };\n const [announcement, setAnnouncement] = React.useState(\"\");\n function send(event: RangeEvent) {\n const result = transitionRange(state, event, props);\n store.setState(result.state);\n for (const effect of result.effects) {\n if (effect.type === \"change\") {\n props.onChange?.(effect.value);\n setAnnouncement(effect.value ? [effect.value.start, effect.value.end].map((date) => formatDate(date, props.locale, { dateStyle: \"long\" })).join(props.translations?.rangeSeparator ?? translations.rangeSeparator) : \"\");\n }\n if (effect.type === \"rangeStart\") {\n props.onRangeStartChange?.(effect.value);\n if (effect.value) setAnnouncement(formatDate(effect.value, props.locale, { dateStyle: \"long\" }));\n }\n if (effect.type === \"invalid\") { props.onInvalid?.(); setAnnouncement(props.translations?.unavailable ?? translations.unavailable); }\n }\n }\n const calendar = useCalendar({ ...props, value: null, defaultValue: null, placeholderValue: props.placeholderValue ?? state.value?.start, onChange: (date) => { if (date) send({ type: \"SELECT\", date }); }, onFocusedValueChange: (date) => { props.onFocusedValueChange?.(date); if (state.anchor) send({ type: \"PREVIEW\", date }); } });\n const baseApi = calendar.api;\n const api = { ...baseApi, getCellProps: (date: PlainDate, month?: PlainDate) => ({ ...baseApi.getCellProps(date, month), ...getRangeCellProps(state, date) }) };\n return {\n state, send, announcement, props, options: props, api, rootRef: calendar.rootRef, months: calendar.months,\n reset() { const value = props.defaultValue ?? null; store.setState(createRange(value)); props.onChange?.(value); },\n calendar: { ...calendar, api },\n };\n}\n\nconst Context = React.createContext<ReturnType<typeof useRangeCalendar> | null>(null);\nfunction useContext() {\n const value = React.useContext(Context);\n if (!value) throw new Error(\"RangeCalendar parts must be inside RangeCalendar.Root.\");\n return value;\n}\n\nfunction Root({ children, asChild, className, style, ...props }: RangeCalendarProps & Pick<PartProps, \"children\" | \"asChild\" | \"className\" | \"style\">) {\n const context = useRangeCalendar(props);\n return <Context.Provider value={context}><CalendarSurface calendar={context.calendar} asChild={asChild} className={className} style={style} data-scope=\"range-calendar\" onKeyDown={(event) => { if (event.key === \"Escape\" && context.state.anchor) { event.preventDefault(); context.send({ type: \"CANCEL\" }); } }}>{children}</CalendarSurface></Context.Provider>;\n}\n\nconst Cell = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<typeof Calendar.Cell>>(function Cell({ date, onPointerEnter, ...props }, ref) {\n const { send } = useContext();\n return <Calendar.Cell {...props} ref={ref} date={date} onPointerEnter={composeEvent(onPointerEnter, () => send({ type: \"PREVIEW\", date }))} />;\n});\n\nconst GridBody = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<typeof Calendar.GridBody>>(function GridBody({ children, ...props }, ref) {\n return <Calendar.GridBody {...props} ref={ref}>{children ?? ((date) => <Cell date={date} />)}</Calendar.GridBody>;\n});\n\nconst LiveRegion = React.forwardRef<HTMLElement, PartProps>(function LiveRegion(props, ref) {\n const { announcement } = useContext();\n return <Part {...props} ref={ref} role=\"status\" aria-live=\"polite\" aria-atomic=\"true\" data-scope=\"range-calendar\" data-part=\"live-region\">{announcement}</Part>;\n});\n\nconst ClearButton = React.forwardRef<HTMLElement, React.ComponentPropsWithoutRef<typeof Calendar.ClearButton>>(function ClearButton({ onClick, ...props }, ref) {\n const { send, props: options } = useContext();\n return <Part as=\"button\" {...props} ref={ref} type=\"button\" disabled={options.disabled || options.readOnly} aria-label={options.translations?.clear ?? translations.clear} data-scope=\"range-calendar\" data-part=\"clear-button\" onClick={composeEvent(onClick, () => send({ type: \"CLEAR\" }))} />;\n});\n\nfunction HiddenInput({ name, form, id, disabled, ...inputProps }: HiddenInputProps & { name: string }) {\n const { state, props, reset } = useContext();\n const input = React.useRef<HTMLInputElement>(null);\n useFormReset(input, form, reset);\n return <><input {...inputProps} id={id ? `${id}-start` : undefined} ref={input} type=\"hidden\" name={`${name}.start`} form={form} value={state.value?.start.toString() ?? \"\"} disabled={props.disabled || disabled} data-scope=\"range-calendar\" data-part=\"hidden-input\" /><input {...inputProps} id={id ? `${id}-end` : undefined} type=\"hidden\" name={`${name}.end`} form={form} value={state.value?.end.toString() ?? \"\"} disabled={props.disabled || disabled} data-scope=\"range-calendar\" data-part=\"hidden-input\" /></>;\n}\n\nexport const RangeCalendar = { ...Calendar, Root, Cell, GridBody, LiveRegion, ClearButton, HiddenInput };"],"mappings":"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","names":["useContext","Cell","GridBody","LiveRegion","ClearButton"]}
|
|
File without changes
|
|
File without changes
|