chrona-react 0.3.0 → 0.3.2

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/README.md CHANGED
@@ -6,7 +6,7 @@ values, no free-form date parsing, and no CSS — you own every pixel.
6
6
  Part of [Chrona](https://github.com/devlinduldulao/chrona). Built on
7
7
  [`chrona-core`](https://www.npmjs.com/package/chrona-core).
8
8
 
9
- > **Status: experimental 0.3.0.** Public APIs and styling attributes are not
9
+ > **Status: experimental 0.3.2.** Public APIs and styling attributes are not
10
10
  > frozen for v1. 0.3.0 changes when a field reports a value and leaves `today`
11
11
  > to the client; 0.2.0 changed the Calendar cell anatomy. See the
12
12
  > [changelog](./CHANGELOG.md). Automated axe checks pass, but no screen-reader
@@ -308,17 +308,11 @@ import { DatePicker } from "chrona-react";
308
308
  so it can be set from a touch keyboard; it has no pointer affordance of its
309
309
  own, so give readers a keyboard path to it.
310
310
 
311
- ## Server Rendering
311
+ ## Next.js App Router
312
312
 
313
- These components use state and context, so they carry a `"use client"`
314
- directive. Importing them from a Server Component is safe the framework moves
315
- the import across the boundary — but the module that *renders* them still has to
316
- be a client module, so mark it `"use client"` as usual.
317
-
318
- The polyfill import is a side effect, so it has to reach the *client* bundle.
319
- Importing `temporal-polyfill/global` from a Server Component file installs
320
- Temporal on the server only. Put it at the top of a `"use client"` module that
321
- always loads — a providers file, for example — so it runs before hydration:
313
+ Two files. Both need `"use client"`, and both need the polyfill import that
314
+ second one is the part people lose an afternoon to, so it is explained under
315
+ the code.
322
316
 
323
317
  ```tsx
324
318
  // app/providers.tsx
@@ -328,26 +322,72 @@ import "temporal-polyfill/global";
328
322
  import { ChronaProvider } from "chrona-react";
329
323
 
330
324
  export function Providers({ children }: { children: React.ReactNode }) {
331
- return <ChronaProvider locale="en-US" timeZone="Europe/Copenhagen">{children}</ChronaProvider>;
325
+ return (
326
+ <ChronaProvider locale="en-US" timeZone="Europe/Copenhagen">
327
+ {children}
328
+ </ChronaProvider>
329
+ );
332
330
  }
333
331
  ```
334
332
 
335
- That covers the client bundle before hydration. It does not order Node module
336
- evaluation. If another `"use client"` file reads `Temporal` at module scope
337
- (`const reference = Temporal.PlainDate.from(...)` at the top of `page.tsx`),
338
- Next.js may evaluate that file during SSR before `providers.tsx` has run and
339
- throw `ReferenceError: Temporal is not defined`. Import the polyfill at the top
340
- of that file too, or move the call inside the component body:
333
+ Render that from `app/layout.tsx` which stays a Server Component wrapping
334
+ `{children}`.
341
335
 
342
336
  ```tsx
337
+ // app/booking-form.tsx
343
338
  "use client";
344
339
 
340
+ // Needed here as well as in providers.tsx: this module reads Temporal at module
341
+ // scope, and Next.js does not promise providers.tsx has been evaluated first.
345
342
  import "temporal-polyfill/global";
343
+
344
+ import { useState } from "react";
346
345
  import { Calendar } from "chrona-react";
347
346
 
348
347
  const REFERENCE = Temporal.PlainDate.from({ year: 2026, month: 9, day: 16 });
348
+
349
+ export function BookingForm() {
350
+ const [value, setValue] = useState<Temporal.PlainDate | null>(null);
351
+
352
+ return (
353
+ <Calendar.Root value={value} onChange={setValue} placeholderValue={REFERENCE} fixedWeeks>
354
+ <Calendar.Header>
355
+ <Calendar.PrevButton />
356
+ <Calendar.Heading />
357
+ <Calendar.NextButton />
358
+ </Calendar.Header>
359
+ <Calendar.Grid>
360
+ <Calendar.GridHeader />
361
+ <Calendar.GridBody />
362
+ </Calendar.Grid>
363
+ <Calendar.HiddenInput name="bookingDate" />
364
+ </Calendar.Root>
365
+ );
366
+ }
349
367
  ```
350
368
 
369
+ Why the polyfill appears twice: importing it is a side effect, so it has to
370
+ reach the *client* bundle — importing it from a Server Component installs
371
+ Temporal on the server only. `providers.tsx` covers the client before
372
+ hydration, but it does not order Node's module evaluation during SSR. A
373
+ `"use client"` file that reads `Temporal` at module scope can be evaluated
374
+ before `providers.tsx` and throw `ReferenceError: Temporal is not defined`.
375
+ Import it at the top of that file too, or move the call inside the component.
376
+
377
+ `placeholderValue` is not decoration: it is what a server-rendered calendar
378
+ opens on. See [Give every calendar a reference date](#give-every-calendar-a-reference-date).
379
+
380
+ `chrona-react` also ships an `AGENTS.md`, written for coding agents and short
381
+ enough to be worth reading yourself — it lists the SSR pitfalls, the part
382
+ anatomy, field draft behaviour, and what is deliberately not implemented.
383
+
384
+ ## Server Rendering
385
+
386
+ These components use state and context, so they carry a `"use client"`
387
+ directive. Importing them from a Server Component is safe — the framework moves
388
+ the import across the boundary — but the module that *renders* them still has to
389
+ be a client module.
390
+
351
391
  Pass the same reference date, value, locale, and time zone on server and client.
352
392
 
353
393
  ### Today
@@ -0,0 +1,142 @@
1
+ import * as temporal_spec from 'temporal-spec';
2
+ import { P as PartProps, H as HiddenInputProps, C as ChronaConfig } from './form-BCAGbNh-.js';
3
+ import * as chrona_core from 'chrona-core';
4
+ import { CalendarOptions, PlainDate, CalendarEvent } from 'chrona-core';
5
+ import * as React from 'react';
6
+
7
+ interface CalendarProps extends CalendarOptions {
8
+ defaultValue?: PlainDate | null;
9
+ defaultFocusedValue?: PlainDate;
10
+ onChange?: (value: PlainDate | null) => void;
11
+ onSelect?: (value: PlainDate) => void;
12
+ onFocusedValueChange?: (value: PlainDate) => void;
13
+ id?: string;
14
+ }
15
+ declare function useCalendar(props?: CalendarProps): {
16
+ state: chrona_core.CalendarState;
17
+ options: CalendarProps & ChronaConfig;
18
+ send: (event: CalendarEvent) => void;
19
+ rootRef: React.RefObject<HTMLElement | null>;
20
+ announcement: string;
21
+ api: {
22
+ getRootProps: () => {
23
+ dir: "ltr" | "rtl" | undefined;
24
+ "data-disabled": string | undefined;
25
+ "data-readonly": string | undefined;
26
+ "data-scope": string;
27
+ "data-part": string;
28
+ };
29
+ getGridProps: (month?: temporal_spec.Temporal.PlainDate) => {
30
+ role: "grid";
31
+ "aria-label": string;
32
+ "aria-readonly": true | undefined;
33
+ "aria-disabled": true | undefined;
34
+ "data-scope": string;
35
+ "data-part": string;
36
+ };
37
+ getCellProps: (date: PlainDate, month?: temporal_spec.Temporal.PlainDate) => {
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;
45
+ role: "gridcell";
46
+ "aria-selected": boolean;
47
+ "aria-disabled": true | undefined;
48
+ "data-scope": string;
49
+ "data-part": string;
50
+ };
51
+ getCellTriggerProps: (date: PlainDate, month?: temporal_spec.Temporal.PlainDate) => {
52
+ "data-date": string;
53
+ "data-selected": string | undefined;
54
+ "data-focused": string | undefined;
55
+ "data-disabled": string | undefined;
56
+ "data-unavailable": string | undefined;
57
+ "data-outside-month": string | undefined;
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;
65
+ "data-scope": string;
66
+ "data-part": string;
67
+ };
68
+ getPrevButtonProps: () => {
69
+ type: "button";
70
+ "aria-label": string;
71
+ disabled: boolean;
72
+ "data-scope": string;
73
+ "data-part": string;
74
+ };
75
+ getNextButtonProps: () => {
76
+ type: "button";
77
+ "aria-label": string;
78
+ disabled: boolean;
79
+ "data-scope": string;
80
+ "data-part": string;
81
+ };
82
+ };
83
+ months: temporal_spec.Temporal.PlainDate[];
84
+ };
85
+ type CalendarContextValue = ReturnType<typeof useCalendar>;
86
+ declare function CalendarRoot({ children, asChild, className, style, ...props }: CalendarProps & Pick<PartProps, "children" | "asChild" | "className" | "style">): React.JSX.Element;
87
+ declare function CalendarSurface({ calendar, ...props }: PartProps & {
88
+ calendar: CalendarContextValue;
89
+ }): React.JSX.Element;
90
+ interface Weekday {
91
+ date: PlainDate;
92
+ label: string;
93
+ }
94
+ declare function HiddenInput(props: HiddenInputProps): React.JSX.Element;
95
+ declare const Calendar: {
96
+ Root: typeof CalendarRoot;
97
+ Header: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
98
+ asChild?: boolean;
99
+ } & React.RefAttributes<HTMLElement>>;
100
+ Heading: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
101
+ asChild?: boolean;
102
+ } & React.RefAttributes<HTMLElement>>;
103
+ PrevButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
104
+ asChild?: boolean;
105
+ } & React.RefAttributes<HTMLElement>>;
106
+ NextButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
107
+ asChild?: boolean;
108
+ } & React.RefAttributes<HTMLElement>>;
109
+ Grid: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
110
+ asChild?: boolean;
111
+ } & {
112
+ monthIndex?: number;
113
+ } & React.RefAttributes<HTMLElement>>;
114
+ GridHeader: React.ForwardRefExoticComponent<Omit<PartProps, "children"> & {
115
+ children?: (day: Weekday) => React.ReactNode;
116
+ } & React.RefAttributes<HTMLElement>>;
117
+ HeaderCell: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
118
+ asChild?: boolean;
119
+ } & {
120
+ day: Weekday;
121
+ } & React.RefAttributes<HTMLElement>>;
122
+ GridBody: React.ForwardRefExoticComponent<Omit<PartProps, "children"> & {
123
+ children?: (date: PlainDate) => React.ReactNode;
124
+ } & React.RefAttributes<HTMLElement>>;
125
+ Cell: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
126
+ asChild?: boolean;
127
+ } & {
128
+ date: PlainDate;
129
+ } & React.RefAttributes<HTMLElement>>;
130
+ CellTrigger: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
131
+ asChild?: boolean;
132
+ } & React.RefAttributes<HTMLElement>>;
133
+ LiveRegion: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
134
+ asChild?: boolean;
135
+ } & React.RefAttributes<HTMLElement>>;
136
+ ClearButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
137
+ asChild?: boolean;
138
+ } & React.RefAttributes<HTMLElement>>;
139
+ HiddenInput: typeof HiddenInput;
140
+ };
141
+
142
+ export { Calendar, type CalendarProps, CalendarRoot, CalendarSurface, type Weekday, useCalendar };
@@ -0,0 +1,74 @@
1
+ import { P as PartProps, H as HiddenInputProps, C as ChronaConfig } from './form-BCAGbNh-.js';
2
+ import * as chrona_core from 'chrona-core';
3
+ import * as React from 'react';
4
+ import { F as FieldProps } from './field-DayikvR6.js';
5
+
6
+ type DateFieldProps = FieldProps<"date">;
7
+ declare const DateField: {
8
+ Root: ({ children, asChild, className, style, ...props }: FieldProps<"date"> & Pick<PartProps, "className" | "style" | "children" | "asChild">) => React.JSX.Element;
9
+ Label: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
10
+ asChild?: boolean;
11
+ } & React.RefAttributes<HTMLElement>>;
12
+ Field: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
13
+ asChild?: boolean;
14
+ } & React.RefAttributes<HTMLElement>>;
15
+ Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultValue" | "children" | "onChange" | "type" | "value"> & {
16
+ type: chrona_core.SegmentType;
17
+ } & React.RefAttributes<HTMLInputElement>>;
18
+ HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
19
+ ClearButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
20
+ asChild?: boolean;
21
+ } & React.RefAttributes<HTMLElement>>;
22
+ LiveRegion: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
23
+ asChild?: boolean;
24
+ } & React.RefAttributes<HTMLElement>>;
25
+ };
26
+ declare function useDateField(props?: DateFieldProps): {
27
+ id: string;
28
+ state: chrona_core.FieldState<"date">;
29
+ options: FieldProps<"date"> & ChronaConfig;
30
+ send: (event: chrona_core.FieldEvent) => void;
31
+ reset: () => void;
32
+ moveFocus: (segment: chrona_core.SegmentType, offset: number) => void;
33
+ groupRef: React.RefObject<HTMLElement | null>;
34
+ announcement: string;
35
+ registerLabel: React.Dispatch<React.SetStateAction<boolean>>;
36
+ api: {
37
+ segments: {
38
+ type: chrona_core.SegmentType | "literal";
39
+ value: string;
40
+ }[];
41
+ getGroupProps: () => {
42
+ role: "group";
43
+ "aria-labelledby": string | undefined;
44
+ "aria-describedby": string | undefined;
45
+ "aria-invalid": true | undefined;
46
+ "data-scope": string;
47
+ "data-part": string;
48
+ "data-invalid": string | undefined;
49
+ "data-disabled": string | undefined;
50
+ "data-readonly": string | undefined;
51
+ dir: "ltr" | "rtl" | undefined;
52
+ };
53
+ getSegmentProps: (segment: chrona_core.SegmentType) => {
54
+ role: "spinbutton";
55
+ "aria-label": string;
56
+ "aria-valuemin": number;
57
+ "aria-valuemax": number;
58
+ "aria-valuenow": number | undefined;
59
+ "aria-valuetext": string;
60
+ "aria-required": true | undefined;
61
+ "aria-invalid": true | undefined;
62
+ "aria-describedby": string | undefined;
63
+ "aria-readonly": true | undefined;
64
+ "data-scope": string;
65
+ "data-part": string;
66
+ "data-segment": chrona_core.SegmentName;
67
+ "data-placeholder": string | undefined;
68
+ "data-invalid": string | undefined;
69
+ display: string;
70
+ };
71
+ };
72
+ };
73
+
74
+ export { DateField, type DateFieldProps, useDateField };
@@ -0,0 +1,69 @@
1
+ import { P as PartProps, H as HiddenInputProps } from './form-BCAGbNh-.js';
2
+ import * as chrona_core from 'chrona-core';
3
+ import { PlainDate, PickerEvent } from 'chrona-core';
4
+ import * as React from 'react';
5
+ import { CalendarProps } from './calendar.js';
6
+ import { DateFieldProps } from './date-field.js';
7
+ import 'temporal-spec';
8
+ import './field-DayikvR6.js';
9
+
10
+ interface DatePickerProps extends DateFieldProps {
11
+ open?: boolean;
12
+ defaultOpen?: boolean;
13
+ onOpenChange?: (open: boolean) => void;
14
+ modal?: boolean;
15
+ timeZone?: string;
16
+ firstDayOfWeek?: number;
17
+ fixedWeeks?: boolean;
18
+ numberOfMonths?: number;
19
+ pagedNavigation?: boolean;
20
+ }
21
+ interface PickerContext {
22
+ props: DatePickerProps;
23
+ options: DatePickerProps;
24
+ state: {
25
+ value: PlainDate | null;
26
+ open: boolean;
27
+ };
28
+ id: string;
29
+ value: PlainDate | null;
30
+ change: (value: PlainDate | null) => void;
31
+ open: boolean;
32
+ send: (event: PickerEvent) => void;
33
+ trigger: {
34
+ current: HTMLElement | null;
35
+ };
36
+ labelled: boolean;
37
+ registerLabel: (present: boolean) => void;
38
+ }
39
+ declare function Root({ children, asChild, className, style, ...input }: DatePickerProps & Pick<PartProps, "children" | "asChild" | "className" | "style">): React.JSX.Element;
40
+ declare function useDatePicker(input?: DatePickerProps): PickerContext;
41
+ declare function PickerCalendar({ children, ...props }: Omit<CalendarProps, "value" | "defaultValue" | "onChange"> & Pick<PartProps, "children" | "className" | "style">): React.JSX.Element;
42
+ declare const DatePicker: {
43
+ Root: typeof Root;
44
+ Label: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
45
+ asChild?: boolean;
46
+ } & React.RefAttributes<HTMLElement>>;
47
+ Field: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
48
+ asChild?: boolean;
49
+ } & React.RefAttributes<HTMLElement>>;
50
+ Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultValue" | "children" | "onChange" | "type" | "value"> & {
51
+ type: chrona_core.SegmentType;
52
+ } & React.RefAttributes<HTMLInputElement>>;
53
+ HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
54
+ ClearButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
55
+ asChild?: boolean;
56
+ } & React.RefAttributes<HTMLElement>>;
57
+ LiveRegion: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
58
+ asChild?: boolean;
59
+ } & React.RefAttributes<HTMLElement>>;
60
+ Trigger: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
61
+ asChild?: boolean;
62
+ } & React.RefAttributes<HTMLElement>>;
63
+ Popover: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.DialogHTMLAttributes<HTMLDialogElement>, HTMLDialogElement>, "ref">, "open"> & {
64
+ anchored?: boolean;
65
+ } & React.RefAttributes<HTMLDialogElement>>;
66
+ Calendar: typeof PickerCalendar;
67
+ };
68
+
69
+ export { DatePicker, type DatePickerProps, useDatePicker };
@@ -0,0 +1,11 @@
1
+ import { FieldKind, FieldOptions, FieldValue, FieldInvalidReason } from 'chrona-core';
2
+
3
+ interface FieldProps<Kind extends FieldKind> extends FieldOptions<Kind> {
4
+ defaultValue?: FieldValue<Kind> | null;
5
+ onChange?: (value: FieldValue<Kind> | null) => void;
6
+ onInvalid?: (reason: FieldInvalidReason) => void;
7
+ id?: string;
8
+ describedBy?: string;
9
+ }
10
+
11
+ export type { FieldProps as F };
@@ -0,0 +1,20 @@
1
+ import * as React from 'react';
2
+ import { Translations } from 'chrona-core';
3
+
4
+ interface ChronaConfig {
5
+ locale?: string;
6
+ timeZone?: string;
7
+ dir?: "ltr" | "rtl";
8
+ translations?: Partial<Translations>;
9
+ }
10
+ declare function ChronaProvider({ children, ...config }: ChronaConfig & {
11
+ children: React.ReactNode;
12
+ }): React.JSX.Element;
13
+
14
+ type PartProps = React.HTMLAttributes<HTMLElement> & {
15
+ asChild?: boolean;
16
+ };
17
+
18
+ type HiddenInputProps = Omit<React.ComponentPropsWithoutRef<"input">, "type" | "value" | "defaultValue" | "onChange">;
19
+
20
+ export { type ChronaConfig as C, type HiddenInputProps as H, type PartProps as P, ChronaProvider as a };
@@ -0,0 +1,10 @@
1
+ export { Calendar, CalendarProps, CalendarRoot, Weekday, useCalendar } from './calendar.js';
2
+ export { C as ChronaConfig, a as ChronaProvider } from './form-BCAGbNh-.js';
3
+ export { DateField, DateFieldProps, useDateField } from './date-field.js';
4
+ export { TimeField, TimeFieldProps, useTimeField } from './time-field.js';
5
+ export { DatePicker, DatePickerProps, useDatePicker } from './date-picker.js';
6
+ export { RangeCalendar, RangeCalendarProps, useRangeCalendar } from './range-calendar.js';
7
+ import 'temporal-spec';
8
+ import 'chrona-core';
9
+ import 'react';
10
+ import './field-DayikvR6.js';
@@ -0,0 +1,233 @@
1
+ import { CalendarProps, Weekday } from './calendar.js';
2
+ import * as chrona_core from 'chrona-core';
3
+ import { DateRange, PlainDate, RangeEvent } from 'chrona-core';
4
+ import * as temporal_spec from 'temporal-spec';
5
+ import { P as PartProps, H as HiddenInputProps, C as ChronaConfig } from './form-BCAGbNh-.js';
6
+ import * as React from 'react';
7
+
8
+ interface RangeCalendarProps extends Omit<CalendarProps, "value" | "defaultValue" | "onChange"> {
9
+ value?: DateRange | null;
10
+ defaultValue?: DateRange | null;
11
+ onChange?: (value: DateRange | null) => void;
12
+ onRangeStartChange?: (value: PlainDate | null) => void;
13
+ onInvalid?: () => void;
14
+ }
15
+ declare function useRangeCalendar(input?: RangeCalendarProps): {
16
+ state: {
17
+ value: DateRange | null;
18
+ anchor: PlainDate | null;
19
+ preview: PlainDate | null;
20
+ invalid: boolean;
21
+ };
22
+ send: (event: RangeEvent) => void;
23
+ announcement: string;
24
+ props: RangeCalendarProps & ChronaConfig;
25
+ options: RangeCalendarProps & ChronaConfig;
26
+ api: {
27
+ getCellProps: (date: PlainDate, month?: PlainDate) => {
28
+ "data-scope": string;
29
+ "data-selected": string | undefined;
30
+ "data-in-range": string | undefined;
31
+ "data-range-start": string | undefined;
32
+ "data-range-end": string | undefined;
33
+ "data-preview": string | undefined;
34
+ "data-invalid": string | undefined;
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;
42
+ role: "gridcell";
43
+ "aria-disabled": true | undefined;
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;
54
+ "data-date": string;
55
+ "data-focused": string | undefined;
56
+ "data-disabled": string | undefined;
57
+ "data-unavailable": string | undefined;
58
+ "data-outside-month": string | undefined;
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;
66
+ "data-part": string;
67
+ };
68
+ getRootProps: () => {
69
+ dir: "ltr" | "rtl" | undefined;
70
+ "data-disabled": string | undefined;
71
+ "data-readonly": string | undefined;
72
+ "data-scope": string;
73
+ "data-part": string;
74
+ };
75
+ getGridProps: (month?: temporal_spec.Temporal.PlainDate) => {
76
+ role: "grid";
77
+ "aria-label": string;
78
+ "aria-readonly": true | undefined;
79
+ "aria-disabled": true | undefined;
80
+ "data-scope": string;
81
+ "data-part": string;
82
+ };
83
+ getPrevButtonProps: () => {
84
+ type: "button";
85
+ "aria-label": string;
86
+ disabled: boolean;
87
+ "data-scope": string;
88
+ "data-part": string;
89
+ };
90
+ getNextButtonProps: () => {
91
+ type: "button";
92
+ "aria-label": string;
93
+ disabled: boolean;
94
+ "data-scope": string;
95
+ "data-part": string;
96
+ };
97
+ };
98
+ rootRef: React.RefObject<HTMLElement | null>;
99
+ months: temporal_spec.Temporal.PlainDate[];
100
+ reset(): void;
101
+ calendar: {
102
+ api: {
103
+ getCellProps: (date: PlainDate, month?: PlainDate) => {
104
+ "data-scope": string;
105
+ "data-selected": string | undefined;
106
+ "data-in-range": string | undefined;
107
+ "data-range-start": string | undefined;
108
+ "data-range-end": string | undefined;
109
+ "data-preview": string | undefined;
110
+ "data-invalid": string | undefined;
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;
118
+ role: "gridcell";
119
+ "aria-disabled": true | undefined;
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;
130
+ "data-date": string;
131
+ "data-focused": string | undefined;
132
+ "data-disabled": string | undefined;
133
+ "data-unavailable": string | undefined;
134
+ "data-outside-month": string | undefined;
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;
142
+ "data-part": string;
143
+ };
144
+ getRootProps: () => {
145
+ dir: "ltr" | "rtl" | undefined;
146
+ "data-disabled": string | undefined;
147
+ "data-readonly": string | undefined;
148
+ "data-scope": string;
149
+ "data-part": string;
150
+ };
151
+ getGridProps: (month?: temporal_spec.Temporal.PlainDate) => {
152
+ role: "grid";
153
+ "aria-label": string;
154
+ "aria-readonly": true | undefined;
155
+ "aria-disabled": true | undefined;
156
+ "data-scope": string;
157
+ "data-part": string;
158
+ };
159
+ getPrevButtonProps: () => {
160
+ type: "button";
161
+ "aria-label": string;
162
+ disabled: boolean;
163
+ "data-scope": string;
164
+ "data-part": string;
165
+ };
166
+ getNextButtonProps: () => {
167
+ type: "button";
168
+ "aria-label": string;
169
+ disabled: boolean;
170
+ "data-scope": string;
171
+ "data-part": string;
172
+ };
173
+ };
174
+ state: chrona_core.CalendarState;
175
+ options: CalendarProps & ChronaConfig;
176
+ send: (event: chrona_core.CalendarEvent) => void;
177
+ rootRef: React.RefObject<HTMLElement | null>;
178
+ announcement: string;
179
+ months: temporal_spec.Temporal.PlainDate[];
180
+ };
181
+ };
182
+ declare function Root({ children, asChild, className, style, ...props }: RangeCalendarProps & Pick<PartProps, "children" | "asChild" | "className" | "style">): React.JSX.Element;
183
+ declare function HiddenInput({ name, form, id, disabled, ...inputProps }: HiddenInputProps & {
184
+ name: string;
185
+ }): React.JSX.Element;
186
+ declare const RangeCalendar: {
187
+ Root: typeof Root;
188
+ Cell: React.ForwardRefExoticComponent<Omit<React.HTMLAttributes<HTMLElement> & {
189
+ asChild?: boolean;
190
+ } & {
191
+ date: PlainDate;
192
+ } & React.RefAttributes<HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>;
193
+ GridBody: React.ForwardRefExoticComponent<Omit<Omit<PartProps, "children"> & {
194
+ children?: (date: PlainDate) => React.ReactNode;
195
+ } & React.RefAttributes<HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>;
196
+ LiveRegion: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
197
+ asChild?: boolean;
198
+ } & React.RefAttributes<HTMLElement>>;
199
+ ClearButton: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
200
+ asChild?: boolean;
201
+ } & React.RefAttributes<HTMLElement>, "ref"> & React.RefAttributes<HTMLElement>>;
202
+ HiddenInput: typeof HiddenInput;
203
+ Header: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
204
+ asChild?: boolean;
205
+ } & React.RefAttributes<HTMLElement>>;
206
+ Heading: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
207
+ asChild?: boolean;
208
+ } & React.RefAttributes<HTMLElement>>;
209
+ PrevButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
210
+ asChild?: boolean;
211
+ } & React.RefAttributes<HTMLElement>>;
212
+ NextButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
213
+ asChild?: boolean;
214
+ } & React.RefAttributes<HTMLElement>>;
215
+ Grid: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
216
+ asChild?: boolean;
217
+ } & {
218
+ monthIndex?: number;
219
+ } & React.RefAttributes<HTMLElement>>;
220
+ GridHeader: React.ForwardRefExoticComponent<Omit<PartProps, "children"> & {
221
+ children?: (day: Weekday) => React.ReactNode;
222
+ } & React.RefAttributes<HTMLElement>>;
223
+ HeaderCell: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
224
+ asChild?: boolean;
225
+ } & {
226
+ day: Weekday;
227
+ } & React.RefAttributes<HTMLElement>>;
228
+ CellTrigger: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
229
+ asChild?: boolean;
230
+ } & React.RefAttributes<HTMLElement>>;
231
+ };
232
+
233
+ export { RangeCalendar, type RangeCalendarProps, useRangeCalendar };
@@ -0,0 +1,74 @@
1
+ import { P as PartProps, H as HiddenInputProps, C as ChronaConfig } from './form-BCAGbNh-.js';
2
+ import * as chrona_core from 'chrona-core';
3
+ import * as React from 'react';
4
+ import { F as FieldProps } from './field-DayikvR6.js';
5
+
6
+ type TimeFieldProps = FieldProps<"time">;
7
+ declare const TimeField: {
8
+ Root: ({ children, asChild, className, style, ...props }: FieldProps<"time"> & Pick<PartProps, "className" | "style" | "children" | "asChild">) => React.JSX.Element;
9
+ Label: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
10
+ asChild?: boolean;
11
+ } & React.RefAttributes<HTMLElement>>;
12
+ Field: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
13
+ asChild?: boolean;
14
+ } & React.RefAttributes<HTMLElement>>;
15
+ Segment: React.ForwardRefExoticComponent<Omit<Omit<React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref">, "defaultValue" | "children" | "onChange" | "type" | "value"> & {
16
+ type: chrona_core.SegmentType;
17
+ } & React.RefAttributes<HTMLInputElement>>;
18
+ HiddenInput: (props: HiddenInputProps) => React.JSX.Element;
19
+ ClearButton: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "ref"> & {
20
+ asChild?: boolean;
21
+ } & React.RefAttributes<HTMLElement>>;
22
+ LiveRegion: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLElement> & {
23
+ asChild?: boolean;
24
+ } & React.RefAttributes<HTMLElement>>;
25
+ };
26
+ declare function useTimeField(props?: TimeFieldProps): {
27
+ id: string;
28
+ state: chrona_core.FieldState<"time">;
29
+ options: FieldProps<"time"> & ChronaConfig;
30
+ send: (event: chrona_core.FieldEvent) => void;
31
+ reset: () => void;
32
+ moveFocus: (segment: chrona_core.SegmentType, offset: number) => void;
33
+ groupRef: React.RefObject<HTMLElement | null>;
34
+ announcement: string;
35
+ registerLabel: React.Dispatch<React.SetStateAction<boolean>>;
36
+ api: {
37
+ segments: {
38
+ type: chrona_core.SegmentType | "literal";
39
+ value: string;
40
+ }[];
41
+ getGroupProps: () => {
42
+ role: "group";
43
+ "aria-labelledby": string | undefined;
44
+ "aria-describedby": string | undefined;
45
+ "aria-invalid": true | undefined;
46
+ "data-scope": string;
47
+ "data-part": string;
48
+ "data-invalid": string | undefined;
49
+ "data-disabled": string | undefined;
50
+ "data-readonly": string | undefined;
51
+ dir: "ltr" | "rtl" | undefined;
52
+ };
53
+ getSegmentProps: (segment: chrona_core.SegmentType) => {
54
+ role: "spinbutton";
55
+ "aria-label": string;
56
+ "aria-valuemin": number;
57
+ "aria-valuemax": number;
58
+ "aria-valuenow": number | undefined;
59
+ "aria-valuetext": string;
60
+ "aria-required": true | undefined;
61
+ "aria-invalid": true | undefined;
62
+ "aria-describedby": string | undefined;
63
+ "aria-readonly": true | undefined;
64
+ "data-scope": string;
65
+ "data-part": string;
66
+ "data-segment": chrona_core.SegmentName;
67
+ "data-placeholder": string | undefined;
68
+ "data-invalid": string | undefined;
69
+ display: string;
70
+ };
71
+ };
72
+ };
73
+
74
+ export { TimeField, type TimeFieldProps, useTimeField };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chrona-react",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Headless Temporal-native React date and time primitives",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -61,7 +61,7 @@
61
61
  }
62
62
  },
63
63
  "dependencies": {
64
- "chrona-core": "^0.3.0"
64
+ "chrona-core": "^0.3.2"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "react": ">=18.0.0",