@proyecto-viviana/solid-stately 0.3.0 → 0.4.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.
Files changed (77) hide show
  1. package/dist/calendar/IncompleteDate.d.ts +61 -0
  2. package/dist/calendar/createCalendarState.d.ts +20 -10
  3. package/dist/calendar/createDateFieldState.d.ts +65 -20
  4. package/dist/calendar/createRangeCalendarState.d.ts +20 -2
  5. package/dist/calendar/createTimeFieldState.d.ts +38 -67
  6. package/dist/calendar/index.d.ts +1 -1
  7. package/dist/calendar/intl/index.d.ts +10 -0
  8. package/dist/collections/ListCollection.d.ts +8 -0
  9. package/dist/collections/createListState.d.ts +16 -1
  10. package/dist/collections/createSelectionState.d.ts +17 -5
  11. package/dist/collections/getChildNodes.d.ts +19 -0
  12. package/dist/collections/index.d.ts +3 -2
  13. package/dist/collections/types.d.ts +9 -0
  14. package/dist/color/intl/index.d.ts +14 -0
  15. package/dist/combobox/createComboBoxState.d.ts +7 -0
  16. package/dist/dnd/createDroppableCollectionState.d.ts +17 -2
  17. package/dist/dnd/index.d.ts +1 -1
  18. package/dist/dnd/types.d.ts +3 -1
  19. package/dist/grid/types.d.ts +17 -3
  20. package/dist/index.d.ts +6 -6
  21. package/dist/index.js +4372 -1087
  22. package/dist/index.js.map +1 -1
  23. package/dist/select/createSelectState.d.ts +6 -0
  24. package/dist/selection/Selection.d.ts +16 -0
  25. package/dist/selection/SelectionManager.d.ts +119 -0
  26. package/dist/selection/createMultipleSelectionState.d.ts +59 -0
  27. package/dist/selection/index.d.ts +1 -0
  28. package/dist/table/TableCollection.d.ts +30 -0
  29. package/dist/table/createTreeGridState.d.ts +15 -0
  30. package/dist/table/index.d.ts +2 -1
  31. package/dist/table/types.d.ts +58 -0
  32. package/dist/toast/createToastState.d.ts +16 -0
  33. package/dist/toast/index.d.ts +1 -1
  34. package/dist/tree/types.d.ts +14 -6
  35. package/package.json +1 -1
  36. package/src/calendar/IncompleteDate.ts +430 -0
  37. package/src/calendar/createCalendarState.ts +129 -40
  38. package/src/calendar/createDateFieldState.ts +633 -477
  39. package/src/calendar/createRangeCalendarState.ts +343 -30
  40. package/src/calendar/createTimeFieldState.ts +179 -467
  41. package/src/calendar/index.ts +2 -0
  42. package/src/calendar/intl/index.ts +364 -0
  43. package/src/collections/ListCollection.ts +31 -0
  44. package/src/collections/createListState.ts +139 -17
  45. package/src/collections/createMenuState.ts +3 -0
  46. package/src/collections/createSelectionState.ts +38 -28
  47. package/src/collections/getChildNodes.ts +129 -0
  48. package/src/collections/index.ts +12 -0
  49. package/src/collections/types.ts +10 -0
  50. package/src/color/Color.ts +104 -133
  51. package/src/color/intl/index.ts +1409 -0
  52. package/src/combobox/createComboBoxState.ts +38 -13
  53. package/src/dnd/createDroppableCollectionState.ts +125 -6
  54. package/src/dnd/index.d.ts +1 -0
  55. package/src/dnd/index.ts +1 -0
  56. package/src/dnd/types.d.ts +3 -1
  57. package/src/dnd/types.ts +4 -1
  58. package/src/grid/createGridState.ts +36 -2
  59. package/src/grid/types.ts +17 -3
  60. package/src/index.d.ts +1 -0
  61. package/src/index.ts +14 -0
  62. package/src/select/createSelectState.ts +15 -2
  63. package/src/selection/Selection.ts +28 -0
  64. package/src/selection/SelectionManager.ts +541 -0
  65. package/src/selection/createMultipleSelectionState.ts +247 -0
  66. package/src/selection/index.ts +6 -0
  67. package/src/steplist/createStepListState.ts +27 -4
  68. package/src/table/TableCollection.ts +213 -43
  69. package/src/table/createTableState.ts +20 -0
  70. package/src/table/createTreeGridState.ts +146 -0
  71. package/src/table/index.ts +3 -0
  72. package/src/table/types.ts +66 -0
  73. package/src/tabs/createTabListState.ts +11 -9
  74. package/src/toast/createToastState.ts +43 -10
  75. package/src/toast/index.ts +1 -0
  76. package/src/tree/createTreeState.ts +37 -6
  77. package/src/tree/types.ts +14 -6
@@ -0,0 +1,61 @@
1
+ /**
2
+ * IncompleteDate for Solid-Stately
3
+ *
4
+ * Represents a date that is incomplete or otherwise invalid as a result of user
5
+ * editing (for example February 31st, if the day is edited before the month).
6
+ * This lets a date field hold an invalid intermediate value while typing and
7
+ * only constrain it on blur, matching upstream behavior.
8
+ *
9
+ * Based on @react-stately/datepicker IncompleteDate
10
+ */
11
+ import { type AnyDateTime, type Calendar, type DateValue } from "@internationalized/date";
12
+ import type { DateSegmentType } from "./createDateFieldState";
13
+ type HourCycle = "h12" | "h11" | "h23" | "h24";
14
+ /**
15
+ * This class represents a date that is incomplete or otherwise invalid as a result of user editing.
16
+ * For example, it can represent temporary dates such as February 31st if the user edits the day
17
+ * before the month. Times are represented according to an hour cycle rather than always in 24 hour
18
+ * time. This enables the user to adjust the day period (e.g. am/pm) independently from the hour.
19
+ */
20
+ export declare class IncompleteDate {
21
+ calendar: Calendar;
22
+ era: string | null;
23
+ year: number | null;
24
+ month: number | null;
25
+ day: number | null;
26
+ hour: number | null;
27
+ hourCycle: HourCycle;
28
+ dayPeriod: number | null;
29
+ minute: number | null;
30
+ second: number | null;
31
+ millisecond: number | null;
32
+ offset: number | null;
33
+ constructor(calendar: Calendar, hourCycle: HourCycle, dateValue?: Partial<Omit<AnyDateTime, "copy">> | null);
34
+ copy(): IncompleteDate;
35
+ /** Checks whether all the specified segments have a value. */
36
+ isComplete(segments: DateSegmentType[]): boolean;
37
+ /** Checks whether the given date value matches this value for the specified segments. */
38
+ validate(dt: DateValue, segments: DateSegmentType[]): boolean;
39
+ /** Checks if the date is empty (i.e. all specified segments are null). */
40
+ isCleared(segments: DateSegmentType[]): boolean;
41
+ /** Sets the given field. */
42
+ set(field: DateSegmentType, value: number | string, placeholder: DateValue): IncompleteDate;
43
+ /** Sets the given field to null. */
44
+ clear(field: DateSegmentType): IncompleteDate;
45
+ /**
46
+ * Increments or decrements the given field. If it is null, then it is set to the placeholder
47
+ * value.
48
+ */
49
+ cycle(field: DateSegmentType, amount: number, placeholder: DateValue, displaySegments: DateSegmentType[]): IncompleteDate;
50
+ /**
51
+ * Converts the incomplete date to a full date value, using the provided value for any unset
52
+ * fields.
53
+ */
54
+ toValue(value: DateValue): DateValue;
55
+ getSegmentLimits(type: string): {
56
+ value: number | null;
57
+ minValue: number;
58
+ maxValue: number;
59
+ } | undefined;
60
+ }
61
+ export {};
@@ -11,13 +11,17 @@ export type ValidationState = "valid" | "invalid";
11
11
  export type CalendarPageBehavior = "single" | "visible";
12
12
  export type CalendarSelectionAlignment = "start" | "center" | "end";
13
13
  export type CalendarDayOfWeek = "sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat";
14
- export interface CalendarStateProps<T extends DateValue = DateValue> {
14
+ export type CalendarSelectionMode = "single" | "multiple";
15
+ export type CalendarValueType<T, M extends CalendarSelectionMode> = M extends "single" ? T : readonly T[];
16
+ export interface CalendarStateProps<T extends DateValue = DateValue, M extends CalendarSelectionMode = "single"> {
15
17
  /** The current value (controlled). */
16
- value?: MaybeAccessor<T | null>;
18
+ value?: MaybeAccessor<CalendarValueType<T | null, M> | undefined>;
17
19
  /** The default value (uncontrolled). */
18
- defaultValue?: T | null;
20
+ defaultValue?: CalendarValueType<T | null, M> | null;
19
21
  /** Handler called when the value changes. */
20
- onChange?: (value: T | null) => void;
22
+ onChange?: (value: CalendarValueType<T | null, M>) => void;
23
+ /** Whether single or multiple date selection is enabled. */
24
+ selectionMode?: MaybeAccessor<M>;
21
25
  /** The minimum allowed date. */
22
26
  minValue?: MaybeAccessor<DateValue | undefined>;
23
27
  /** The maximum allowed date. */
@@ -57,15 +61,21 @@ export interface CalendarStateProps<T extends DateValue = DateValue> {
57
61
  /** The first day of the week (0 = Sunday, 1 = Monday, etc.). */
58
62
  firstDayOfWeek?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
59
63
  }
60
- export interface CalendarState<T extends DateValue = DateValue> {
61
- /** The currently selected date. */
62
- value: Accessor<T | null>;
63
- /** Sets the selected date. */
64
- setValue: (value: T | null) => void;
64
+ export interface CalendarState<T extends DateValue = DateValue, M extends CalendarSelectionMode = "single"> {
65
+ /** Whether single or multiple selection is enabled. */
66
+ selectionMode: Accessor<CalendarSelectionMode>;
67
+ /** The currently selected date(s). */
68
+ value: Accessor<CalendarValueType<T | null, M>>;
69
+ /** Sets the selected date(s). */
70
+ setValue: (value: CalendarValueType<T | null, M>) => void;
65
71
  /** The currently focused date. */
66
72
  focusedDate: Accessor<CalendarDate>;
67
73
  /** Sets the focused date. */
68
74
  setFocusedDate: (date: CalendarDate) => void;
75
+ /** The minimum allowed date that a user may select. */
76
+ minValue: Accessor<DateValue | null>;
77
+ /** The maximum allowed date that a user may select. */
78
+ maxValue: Accessor<DateValue | null>;
69
79
  /** Whether the calendar is disabled. */
70
80
  isDisabled: Accessor<boolean>;
71
81
  /** Whether the calendar is read-only. */
@@ -141,4 +151,4 @@ export interface CalendarState<T extends DateValue = DateValue> {
141
151
  /**
142
152
  * Provides state management for a calendar component.
143
153
  */
144
- export declare function createCalendarState<T extends DateValue = CalendarDate>(props?: CalendarStateProps<T>): CalendarState<T>;
154
+ export declare function createCalendarState<T extends DateValue = CalendarDate, M extends CalendarSelectionMode = "single">(props?: CalendarStateProps<T, M>): CalendarState<T, M>;
@@ -2,21 +2,34 @@
2
2
  * DateFieldState for Solid-Stately
3
3
  *
4
4
  * Provides state management for date field components with segment-based editing.
5
- * Based on @react-stately/datepicker useDateFieldState
5
+ * Faithful port of @react-stately/datepicker useDateFieldState.
6
+ *
7
+ * Editing is modeled with an {@link IncompleteDate} display value so that invalid
8
+ * intermediate dates (e.g. February 31st, produced by editing the day before the
9
+ * month) are held as-typed while the field is focused and only constrained on blur
10
+ * via `confirmPlaceholder`, matching upstream behavior. Out-of-range values are
11
+ * never snapped to `minValue`/`maxValue`; they are kept and reported as invalid.
12
+ *
13
+ * The upstream "derived state during render" resync (which re-mints the display
14
+ * value when the committed value / calendar / hour cycle changes) is ported to a
15
+ * Solid `createComputed` so it runs synchronously before render effects — mirroring
16
+ * React's render-phase setState rather than a post-render `createEffect`.
6
17
  */
7
18
  import { type Accessor } from "solid-js";
8
- import { CalendarDate, type DateValue } from "@internationalized/date";
19
+ import { type Calendar, type CalendarDateTime, type CalendarIdentifier, type DateValue, DateFormatter, Time } from "@internationalized/date";
9
20
  import { type MaybeAccessor } from "../utils";
10
21
  import type { ValidationState } from "./createCalendarState";
11
22
  import { type ValidationBehavior, type ValidationFunction, type ValidationResult } from "../form";
12
23
  export type DateSegmentType = "year" | "month" | "day" | "hour" | "minute" | "second" | "dayPeriod" | "era" | "timeZoneName" | "literal";
24
+ type Granularity = "year" | "month" | "day" | "hour" | "minute" | "second";
25
+ type FieldGranularity = "day" | "hour" | "minute" | "second";
13
26
  export interface DateSegment {
14
27
  /** The type of segment. */
15
28
  type: DateSegmentType;
16
29
  /** The text content of the segment. */
17
30
  text: string;
18
31
  /** The numeric value of the segment (if applicable). */
19
- value?: number;
32
+ value?: number | null;
20
33
  /** The minimum value for the segment. */
21
34
  minValue?: number;
22
35
  /** The maximum value for the segment. */
@@ -50,7 +63,9 @@ export interface DateFieldStateProps<T extends DateValue = DateValue> {
50
63
  /** The locale to use for formatting. */
51
64
  locale?: string;
52
65
  /** The granularity of the date/time (day, hour, minute, second). */
53
- granularity?: "day" | "hour" | "minute" | "second";
66
+ granularity?: FieldGranularity;
67
+ /** The maximum granularity (largest editable unit). Defaults to `year`. */
68
+ maxGranularity?: "year" | "month" | "day" | "hour" | "minute";
54
69
  /** Whether to show the hour in 12 or 24 hour format. */
55
70
  hourCycle?: 12 | 24;
56
71
  /** Whether to hide the time zone. */
@@ -71,28 +86,42 @@ export interface DateFieldStateProps<T extends DateValue = DateValue> {
71
86
  errorMessage?: string;
72
87
  /** Whether dates outside the min/max range are allowed. */
73
88
  allowsNonContiguousRanges?: boolean;
74
- /** Whether to create a date or datetime. */
75
- createCalendar?: (name: string) => unknown;
89
+ /** Resolves a calendar system by its Unicode identifier. */
90
+ createCalendar?: (name: CalendarIdentifier) => Calendar;
76
91
  /** Whether a date is unavailable. */
77
92
  isDateUnavailable?: (date: DateValue) => boolean;
78
93
  }
79
94
  export interface DateFieldState<T extends DateValue = DateValue> {
80
- /** The current value. */
81
- value: Accessor<T | null>;
82
- /** The date value (may be partial during editing). */
83
- dateValue: Accessor<DateValue | null>;
95
+ /** The current value, converted to the display calendar. */
96
+ value: Accessor<DateValue | null>;
97
+ /** The current value as a native JavaScript Date (may be partial during editing). */
98
+ dateValue: Accessor<Date>;
99
+ /** The display calendar system. */
100
+ readonly calendar: Calendar;
84
101
  /** Sets the date value. */
85
102
  setValue: (value: T | null) => void;
86
103
  /** The segments that make up the date. */
87
104
  segments: Accessor<DateSegment[]>;
88
- /** The format string. */
105
+ /** The formatter used to render the field. */
106
+ readonly dateFormatter: DateFormatter;
107
+ /** Formats the current value with the given field options. */
89
108
  formatValue: (fieldOptions?: Intl.DateTimeFormatOptions) => string;
109
+ /** Returns a formatter with the field's resolved options merged with the given ones. */
110
+ getDateFormatter: (locale: string, formatOptions: FormatterOptions) => DateFormatter;
90
111
  /** Sets a segment value. */
91
112
  setSegment: (type: DateSegmentType, value: number) => void;
92
- /** Increments a segment. */
93
- incrementSegment: (type: DateSegmentType) => void;
94
- /** Decrements a segment. */
95
- decrementSegment: (type: DateSegmentType) => void;
113
+ /** Increments a segment by one. */
114
+ increment: (type: DateSegmentType) => void;
115
+ /** Decrements a segment by one. */
116
+ decrement: (type: DateSegmentType) => void;
117
+ /** Increments a segment by a larger page step. */
118
+ incrementPage: (type: DateSegmentType) => void;
119
+ /** Decrements a segment by a larger page step. */
120
+ decrementPage: (type: DateSegmentType) => void;
121
+ /** Sets a segment to its maximum value. */
122
+ incrementToMax: (type: DateSegmentType) => void;
123
+ /** Sets a segment to its minimum value. */
124
+ decrementToMin: (type: DateSegmentType) => void;
96
125
  /** Clears a segment. */
97
126
  clearSegment: (type: DateSegmentType) => void;
98
127
  /** Confirms the value (after typing). */
@@ -106,7 +135,9 @@ export interface DateFieldState<T extends DateValue = DateValue> {
106
135
  /** The validation state. */
107
136
  validationState: Accessor<ValidationState | undefined>;
108
137
  /** The granularity. */
109
- granularity: "day" | "hour" | "minute" | "second";
138
+ readonly granularity: FieldGranularity;
139
+ /** The maximum granularity. */
140
+ readonly maxGranularity: "year" | "month" | "day" | "hour" | "minute";
110
141
  /** Whether the value is invalid. */
111
142
  isInvalid: Accessor<boolean>;
112
143
  /** Realtime validation results, including native and custom constraints. */
@@ -120,13 +151,27 @@ export interface DateFieldState<T extends DateValue = DateValue> {
120
151
  /** Commits realtime validation to displayed validation. */
121
152
  commitValidation: () => void;
122
153
  /** The locale. */
123
- locale: string;
154
+ readonly locale: string;
124
155
  /** The time zone. */
125
- timeZone: string;
156
+ readonly timeZone: string;
126
157
  /** The default value. */
127
- defaultValue: T | null;
158
+ defaultValue: DateValue | null;
128
159
  }
129
160
  /**
130
161
  * Provides state management for a date field component.
131
162
  */
132
- export declare function createDateFieldState<T extends DateValue = CalendarDate>(props?: DateFieldStateProps<T>): DateFieldState<T>;
163
+ export declare function createDateFieldState<T extends DateValue = DateValue>(props?: DateFieldStateProps<T>): DateFieldState<T>;
164
+ interface FormatterOptions {
165
+ timeZone?: string;
166
+ hideTimeZone?: boolean;
167
+ granularity?: Granularity;
168
+ maxGranularity?: "year" | "month" | "day" | "hour" | "minute";
169
+ hourCycle?: 12 | 24;
170
+ showEra?: boolean;
171
+ shouldForceLeadingZeros?: boolean;
172
+ }
173
+ export declare function getFormatOptions(fieldOptions: Intl.DateTimeFormatOptions | undefined, options: FormatterOptions): Intl.DateTimeFormatOptions;
174
+ /** The placeholder time, used by time-only fields. */
175
+ export declare function getPlaceholderTime(placeholderValue?: DateValue): Time | DateValue;
176
+ export declare function getValidationResult(value: DateValue | null, minValue: DateValue | undefined, maxValue: DateValue | undefined, isDateUnavailable: ((date: DateValue) => boolean) | undefined, options: FormatterOptions): ValidationResult;
177
+ export type { CalendarDateTime };
@@ -43,8 +43,12 @@ export interface RangeCalendarStateProps<T extends DateValue = DateValue> {
43
43
  locale?: MaybeAccessor<string | undefined>;
44
44
  /** Creates a calendar object for a locale calendar identifier. */
45
45
  createCalendar?: (identifier: CalendarIdentifier) => InternationalizedCalendar;
46
- /** Callback to determine if a date is unavailable. */
47
- isDateUnavailable?: (date: DateValue) => boolean;
46
+ /**
47
+ * Callback that determines if a date is unavailable. The second argument is the
48
+ * current selection anchor (the first selected date), so availability can be
49
+ * derived from it. Mirrors @react-stately/calendar 1.18.
50
+ */
51
+ isDateUnavailable?: (date: DateValue, anchorDate: CalendarDate | null) => boolean;
48
52
  /** The number of months to display at once. */
49
53
  visibleMonths?: MaybeAccessor<number | undefined>;
50
54
  /** Controls how the initial visible months are aligned around the current value. */
@@ -69,6 +73,10 @@ export interface RangeCalendarState<T extends DateValue = DateValue> {
69
73
  focusedDate: Accessor<CalendarDate>;
70
74
  /** Sets the focused date. */
71
75
  setFocusedDate: (date: CalendarDate) => void;
76
+ /** The minimum allowed date that a user may select. */
77
+ minValue: Accessor<DateValue | null>;
78
+ /** The maximum allowed date that a user may select. */
79
+ maxValue: Accessor<DateValue | null>;
72
80
  /** The anchor date when selecting a range (first click). */
73
81
  anchorDate: Accessor<CalendarDate | null>;
74
82
  /** Sets the anchor date. */
@@ -156,6 +164,16 @@ export interface RangeCalendarState<T extends DateValue = DateValue> {
156
164
  isDragging: Accessor<boolean>;
157
165
  /** Sets whether the user is dragging to select. */
158
166
  setDragging: (dragging: boolean) => void;
167
+ /**
168
+ * Formats the selected range as a `{ start, end }` pair of localized strings,
169
+ * or `null` when the range is incomplete. Mirrors upstream
170
+ * `DateRangePickerState.formatValue` — the port collapses that state into the
171
+ * range calendar state, so the range picker reads its SR description from here.
172
+ */
173
+ formatValue: (locale: string, fieldOptions: Intl.DateTimeFormatOptions) => {
174
+ start: string;
175
+ end: string;
176
+ } | null;
159
177
  }
160
178
  /**
161
179
  * Provides state management for a range calendar component.
@@ -1,34 +1,37 @@
1
1
  /**
2
2
  * TimeFieldState for Solid-Stately
3
3
  *
4
- * Provides state management for time field components with segment-based editing.
5
- * Based on @react-stately/datepicker useTimeFieldState
4
+ * Faithful port of `@react-stately/datepicker` `useTimeFieldState`, which is a
5
+ * thin wrapper over `useDateFieldState`: a time-only `Time` value is converted
6
+ * to a `CalendarDateTime` (anchored on today's date, or a zoned date when the
7
+ * value/default carries a time zone) and fed to the date-field state machine
8
+ * with `maxGranularity: 'hour'` so the date segments drop away and only
9
+ * hour/minute[/second]/dayPeriod remain. The returned state IS the
10
+ * `DateFieldState`, plus a `timeValue` accessor holding the value back in the
11
+ * `Time` domain. This means TimeField reuses the certified DateField segment
12
+ * stack (`createDateSegment`, `DateInput`, `DateSegment`) exactly as RAC's
13
+ * TimeField reuses `DateInput`/`DateSegment` — there is no parallel time
14
+ * primitive.
15
+ *
16
+ * The `timeValue` is layered on with a Proxy rather than an object spread
17
+ * because `DateFieldState`'s `calendar`/`dateFormatter`/`granularity`/
18
+ * `maxGranularity`/`locale`/`timeZone` members are getters — spreading would
19
+ * invoke and freeze them, breaking reactivity.
6
20
  */
7
21
  import { type Accessor } from "solid-js";
8
- import { type Time, type CalendarDateTime, type ZonedDateTime, type DateValue } from "@internationalized/date";
22
+ import { Time, type CalendarDateTime, type ZonedDateTime, type DateValue } from "@internationalized/date";
9
23
  import { type MaybeAccessor } from "../utils";
10
24
  import type { ValidationState } from "./createCalendarState";
11
- import { type ValidationBehavior, type ValidationFunction, type ValidationResult } from "../form";
25
+ import type { ValidationBehavior, ValidationFunction } from "../form";
26
+ import { type DateFieldState, type DateSegment as DateSegmentInternal, type DateSegmentType as DateSegmentTypeInternal } from "./createDateFieldState";
12
27
  export type TimeValue = Time | CalendarDateTime | ZonedDateTime;
13
- export type TimeSegmentType = "hour" | "minute" | "second" | "dayPeriod" | "literal";
14
- export interface TimeSegment {
15
- /** The type of segment. */
16
- type: TimeSegmentType;
17
- /** The text content of the segment. */
18
- text: string;
19
- /** The numeric value of the segment (if applicable). */
20
- value?: number;
21
- /** The minimum value for the segment. */
22
- minValue?: number;
23
- /** The maximum value for the segment. */
24
- maxValue?: number;
25
- /** Whether this segment is editable. */
26
- isEditable: boolean;
27
- /** Whether this segment is a placeholder. */
28
- isPlaceholder: boolean;
29
- /** A placeholder string for the segment. */
30
- placeholder: string;
31
- }
28
+ /**
29
+ * TimeField reuses the DateField segment vocabulary (RAC TimeField reuses
30
+ * `DateInput`/`DateSegment`); the legacy `TimeSegment`/`TimeSegmentType` names
31
+ * are kept as aliases of the shared date-segment types.
32
+ */
33
+ export type TimeSegmentType = DateSegmentTypeInternal;
34
+ export type TimeSegment = DateSegmentInternal;
32
35
  export interface TimeFieldStateProps<T extends TimeValue = Time> {
33
36
  /** The current value (controlled). */
34
37
  value?: MaybeAccessor<T | null>;
@@ -54,6 +57,8 @@ export interface TimeFieldStateProps<T extends TimeValue = Time> {
54
57
  granularity?: "hour" | "minute" | "second";
55
58
  /** Whether to show 12 or 24 hour format. */
56
59
  hourCycle?: 12 | 24;
60
+ /** Whether to hide the time zone. */
61
+ hideTimeZone?: boolean;
57
62
  /** Whether to force leading zeroes in the hour segment. */
58
63
  shouldForceLeadingZeros?: boolean;
59
64
  /** Validation state. */
@@ -61,7 +66,7 @@ export interface TimeFieldStateProps<T extends TimeValue = Time> {
61
66
  /** Validation behavior mode. */
62
67
  validationBehavior?: ValidationBehavior;
63
68
  /** Custom validation function. */
64
- validate?: ValidationFunction<T>;
69
+ validate?: ValidationFunction<T | null>;
65
70
  /** Description text. */
66
71
  description?: string;
67
72
  /** Error message. */
@@ -71,49 +76,15 @@ export interface TimeFieldStateProps<T extends TimeValue = Time> {
71
76
  /** Whether dates outside the min/max range are unavailable. Added for API consistency. */
72
77
  isDateUnavailable?: (date: DateValue) => boolean;
73
78
  }
74
- export interface TimeFieldState<T extends TimeValue = Time> {
75
- /** The current value. */
76
- value: Accessor<T | null>;
77
- /** The default value. */
78
- defaultValue: T | null;
79
- /** Sets the value. */
80
- setValue: (value: T | null) => void;
81
- /** The segments that make up the time. */
82
- segments: Accessor<TimeSegment[]>;
83
- /** Sets a segment value. */
84
- setSegment: (type: TimeSegmentType, value: number) => void;
85
- /** Increments a segment. */
86
- incrementSegment: (type: TimeSegmentType) => void;
87
- /** Decrements a segment. */
88
- decrementSegment: (type: TimeSegmentType) => void;
89
- /** Clears a segment. */
90
- clearSegment: (type: TimeSegmentType) => void;
91
- /** Whether the field is disabled. */
92
- isDisabled: Accessor<boolean>;
93
- /** Whether the field is read-only. */
94
- isReadOnly: Accessor<boolean>;
95
- /** Whether the field is required. */
96
- isRequired: Accessor<boolean>;
97
- /** The validation state. */
98
- validationState: Accessor<ValidationState | undefined>;
99
- /** The granularity. */
100
- granularity: "hour" | "minute" | "second";
101
- /** Whether the value is invalid. */
102
- isInvalid: Accessor<boolean>;
103
- /** Realtime validation results, including native and custom constraints. */
104
- realtimeValidation: Accessor<ValidationResult>;
105
- /** Currently displayed validation results. */
106
- displayValidation: Accessor<ValidationResult>;
107
- /** Updates the current validation result. */
108
- updateValidation: (result: ValidationResult) => void;
109
- /** Resets displayed validation to valid. */
110
- resetValidation: () => void;
111
- /** Commits realtime validation to displayed validation. */
112
- commitValidation: () => void;
113
- /** The locale. */
114
- locale: string;
115
- /** The hour cycle. */
116
- hourCycle: 12 | 24;
79
+ /**
80
+ * The TimeField state IS the certified DateField state (segments, validation,
81
+ * increment/decrement, formatter, etc.) with a `timeValue` accessor added. The
82
+ * `T` generic is retained for API back-compat with existing `TimeFieldState<T>`
83
+ * consumers.
84
+ */
85
+ export interface TimeFieldState<T extends TimeValue = Time> extends DateFieldState {
86
+ /** The current value in the `Time`/`CalendarDateTime`/`ZonedDateTime` domain. */
87
+ timeValue: Accessor<TimeValue | null>;
117
88
  }
118
89
  /**
119
90
  * Provides state management for a time field component.
@@ -1,4 +1,4 @@
1
- export { createCalendarState, type CalendarStateProps, type CalendarState, type ValidationState, type CalendarPageBehavior, type CalendarSelectionAlignment, type CalendarDayOfWeek, } from "./createCalendarState";
1
+ export { createCalendarState, type CalendarStateProps, type CalendarState, type CalendarSelectionMode, type CalendarValueType, type ValidationState, type CalendarPageBehavior, type CalendarSelectionAlignment, type CalendarDayOfWeek, } from "./createCalendarState";
2
2
  export { createRangeCalendarState, type RangeCalendarStateProps, type RangeCalendarState, type DateRange, type RangeValue, } from "./createRangeCalendarState";
3
3
  export { createDateFieldState, type DateFieldStateProps, type DateFieldState, type DateSegment, type DateSegmentType, } from "./createDateFieldState";
4
4
  export { createTimeFieldState, type TimeFieldStateProps, type TimeFieldState, type TimeSegment, type TimeSegmentType, type TimeValue, } from "./createTimeFieldState";
@@ -0,0 +1,10 @@
1
+ export type DateFieldErrorKey = "rangeUnderflow" | "rangeOverflow" | "rangeReversed" | "unavailableDate";
2
+ type DateFieldErrorArgs = {
3
+ minValue?: string;
4
+ maxValue?: string;
5
+ };
6
+ /** Mirrors LocalizedStringFormatter.format for the datepicker validation messages. */
7
+ export declare function formatDateFieldError(locale: string, key: DateFieldErrorKey, args?: DateFieldErrorArgs): string;
8
+ /** Mirrors @react-stately/datepicker getPlaceholder. */
9
+ export declare function getPlaceholder(field: string, value: string, locale: string): string;
10
+ export {};
@@ -21,6 +21,14 @@ export declare class ListCollection<T = unknown> implements Collection<T> {
21
21
  getLastKey(): Key | null;
22
22
  getChildren(key: Key): Iterable<CollectionNode<T>>;
23
23
  getTextValue(key: Key): string;
24
+ /**
25
+ * Filter the collection, returning a new `ListCollection` containing only the
26
+ * item nodes for which `filterFn(node.textValue, node)` returns true. Sections
27
+ * whose children are all filtered out are dropped; surviving sections are
28
+ * rebuilt with their filtered children. Node order is preserved. Mirrors the
29
+ * behaviour of @react-aria/collections `BaseCollection.filter`.
30
+ */
31
+ filter(filterFn: (nodeValue: string, node: CollectionNode<T>) => boolean): ListCollection<T>;
24
32
  /**
25
33
  * Get all items (excluding sections, including items within sections).
26
34
  */
@@ -5,7 +5,8 @@
5
5
  */
6
6
  import { type Accessor } from "solid-js";
7
7
  import { type MaybeAccessor } from "../utils";
8
- import { type SelectionState } from "./createSelectionState";
8
+ import type { SelectionState } from "./createSelectionState";
9
+ import { SelectionManager } from "../selection/SelectionManager";
9
10
  import type { Collection, CollectionNode, DisabledBehavior, FocusStrategy, Key, SelectionBehavior, SelectionMode } from "./types";
10
11
  export interface ListStateProps<T = unknown> {
11
12
  /** The items in the list (for dynamic rendering). */
@@ -38,6 +39,8 @@ export interface ListStateProps<T = unknown> {
38
39
  export interface ListState<T = unknown> extends SelectionState {
39
40
  /** The collection of items. */
40
41
  readonly collection: Accessor<Collection<T>>;
42
+ /** The collection-aware selection manager (single source of truth for selection). */
43
+ readonly selectionManager: SelectionManager<T>;
41
44
  /** Whether the collection is focused. */
42
45
  readonly isFocused: Accessor<boolean>;
43
46
  /** Set the focused state. */
@@ -53,6 +56,18 @@ export interface ListState<T = unknown> extends SelectionState {
53
56
  * Creates state for a list component with selection.
54
57
  */
55
58
  export declare function createListState<T = unknown>(props: MaybeAccessor<ListStateProps<T>>): ListState<T>;
59
+ /** A collection filter predicate: `(nodeTextValue, node) => keep`. */
60
+ export type ListFilterFn<T = unknown> = (nodeValue: string, node: CollectionNode<T>) => boolean;
61
+ /**
62
+ * Wraps a {@link ListState} so its collection is filtered by `filterFn`, returning
63
+ * a new (reactive) ListState. Mirrors @react-stately's `UNSTABLE_useFilteredListState`
64
+ * (used by Autocomplete): the filter re-runs as the predicate — which typically
65
+ * closes over the current input value — or the base collection changes; a single
66
+ * stable, collection-aware manager reads the narrowed collection live and shares
67
+ * the base selection/focus state; and the focused key is reset to the nearest
68
+ * surviving item when the current one is filtered out.
69
+ */
70
+ export declare function createFilteredListState<T = unknown>(state: ListState<T>, filterFn: Accessor<ListFilterFn<T> | null | undefined>): ListState<T>;
56
71
  /**
57
72
  * Props for single selection list state.
58
73
  */
@@ -63,11 +63,23 @@ export interface SelectionState {
63
63
  /** Extend selection to a key (for shift-click). */
64
64
  extendSelection(toKey: Key, collection: Collection): void;
65
65
  /** Select a key based on interaction. */
66
- select(key: Key, e?: {
67
- shiftKey?: boolean;
68
- ctrlKey?: boolean;
69
- metaKey?: boolean;
70
- }, collection?: Collection): void;
66
+ select(key: Key, e?: SelectionPressEvent): void;
67
+ }
68
+ /**
69
+ * The press/pointer interaction consulted by {@link SelectionState.select}.
70
+ * Mirrors react-stately's `SelectionManager.select(e)`: only `pointerType` is
71
+ * read here (touch / virtual force toggle, since those devices have no modifier
72
+ * keys). Modifier keys (ctrl / meta / shift) are resolved one layer up in the
73
+ * aria-layer `onSelect` (solidaria `selectItem`), matching upstream's split
74
+ * between react-stately and react-aria. The modifier fields are accepted so a
75
+ * full press/pointer event is assignable, but they are not read here.
76
+ */
77
+ export interface SelectionPressEvent {
78
+ pointerType?: "mouse" | "pen" | "touch" | "keyboard" | "virtual";
79
+ shiftKey?: boolean;
80
+ ctrlKey?: boolean;
81
+ metaKey?: boolean;
82
+ altKey?: boolean;
71
83
  }
72
84
  /**
73
85
  * Creates selection state for a collection.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Helpers for traversing collection nodes and comparing their document order.
3
+ *
4
+ * Based on @react-stately/collections.
5
+ */
6
+ import type { Collection, CollectionNode } from "./types";
7
+ export declare function getChildNodes<T>(node: CollectionNode<T>, collection: Collection<T>): Iterable<CollectionNode<T>>;
8
+ export declare function getFirstItem<T>(iterable: Iterable<T>): T | undefined;
9
+ export declare function getNthItem<T>(iterable: Iterable<T>, index: number): T | undefined;
10
+ export declare function getLastItem<T>(iterable: Iterable<T>): T | undefined;
11
+ /**
12
+ * Counts the item nodes (recursing into sections, ignoring section headers and
13
+ * other non-item nodes) in a collection. Faithful port of
14
+ * @react-stately/collections `getItemCount`; used by createOption to populate
15
+ * `aria-setsize` when the listbox is virtualized. Cached per (immutable)
16
+ * collection identity, exactly like upstream.
17
+ */
18
+ export declare function getItemCount<T>(collection: Collection<T>): number;
19
+ export declare function compareNodeOrder<T>(collection: Collection<T>, a: CollectionNode<T>, b: CollectionNode<T>): number;
@@ -1,5 +1,6 @@
1
1
  export type { Key, SelectionMode, SelectionBehavior, Selection, FocusStrategy, DisabledBehavior, CollectionNode, Collection, ItemProps, SectionProps, CollectionBase, SingleSelection, MultipleSelection, } from "./types";
2
2
  export { ListCollection, createListCollection } from "./ListCollection";
3
- export { createSelectionState, type SelectionStateProps, type SelectionState, } from "./createSelectionState";
4
- export { createListState, createSingleSelectListState, type ListStateProps, type ListState, type SingleSelectListStateProps, type SingleSelectListState, } from "./createListState";
3
+ export { getChildNodes, getFirstItem, getNthItem, getLastItem, getItemCount, compareNodeOrder, } from "./getChildNodes";
4
+ export { createSelectionState, type SelectionStateProps, type SelectionState, type SelectionPressEvent, } from "./createSelectionState";
5
+ export { createListState, createFilteredListState, createSingleSelectListState, type ListStateProps, type ListState, type ListFilterFn, type SingleSelectListStateProps, type SingleSelectListState, } from "./createListState";
5
6
  export { createMenuState, createMenuTriggerState, type MenuStateProps, type MenuState, type MenuTriggerStateProps, type MenuTriggerState, } from "./createMenuState";
@@ -70,6 +70,15 @@ export interface Collection<T = unknown> extends Iterable<CollectionNode<T>> {
70
70
  getChildren(key: Key): Iterable<CollectionNode<T>>;
71
71
  /** Get the text value for a key. */
72
72
  getTextValue(key: Key): string;
73
+ /**
74
+ * Filter the collection, returning a new collection containing only the item
75
+ * nodes for which `filterFn` returns true. Sections whose children are all
76
+ * filtered out are dropped. Mirrors @react-aria/collections
77
+ * `BaseCollection.filter` (and the optional `Collection.filter` in
78
+ * @react-types/shared). Used by Autocomplete to narrow the collection as the
79
+ * user types.
80
+ */
81
+ filter?(filterFn: (nodeValue: string, node: CollectionNode<T>) => boolean): Collection<T>;
73
82
  }
74
83
  /**
75
84
  * Structural shape expected when inferring collection item properties
@@ -0,0 +1,14 @@
1
+ export type ColorStringKey = "hue" | "saturation" | "lightness" | "brightness" | "red" | "green" | "blue" | "alpha" | "colorName" | "transparentColorName" | "very dark" | "dark" | "light" | "very light" | "pale" | "grayish" | "vibrant" | "black" | "white" | "gray" | "pink" | "pink red" | "red orange" | "brown" | "orange" | "orange yellow" | "brown yellow" | "yellow" | "yellow green" | "green cyan" | "cyan" | "cyan blue" | "blue purple" | "purple" | "purple magenta" | "magenta" | "magenta pink";
2
+ export declare const colorStrings: Record<string, Record<ColorStringKey, string>>;
3
+ /**
4
+ * Mirrors LocalizedStringDictionary.getStringForLocale: exact-locale match,
5
+ * then language-only match (e.g. "ar" for "ar-AE"), then the en-US fallback.
6
+ * Ported so solid-stately's Color needs no @internationalized/string dependency.
7
+ */
8
+ export declare function getColorStringForLocale(key: ColorStringKey, locale: string): string;
9
+ /**
10
+ * Mirrors LocalizedStringFormatter.format for the plain `{variable}` messages
11
+ * used by color names (colorName / transparentColorName). Substitutes each
12
+ * `{name}` token with the matching variable's string value.
13
+ */
14
+ export declare function formatColorMessage(key: ColorStringKey, locale: string, variables: Record<string, string>): string;
@@ -8,6 +8,7 @@
8
8
  import { type Accessor } from "solid-js";
9
9
  import { type MaybeAccessor } from "../utils";
10
10
  import type { Key, CollectionNode, Collection, FocusStrategy } from "../collections/types";
11
+ import type { SelectionManager } from "../selection/SelectionManager";
11
12
  export type MenuTriggerAction = "focus" | "input" | "manual";
12
13
  export type { FocusStrategy } from "../collections/types";
13
14
  export type FilterFn = (textValue: string, inputValue: string) => boolean;
@@ -70,6 +71,12 @@ export interface ComboBoxStateProps<T = unknown> {
70
71
  export interface ComboBoxState<T = unknown> {
71
72
  /** The collection of items (may be filtered). */
72
73
  readonly collection: Accessor<Collection<T>>;
74
+ /**
75
+ * The collection-aware selection manager. Mirrors upstream `useComboBoxState`,
76
+ * which returns the `useListState` selection manager bound to the unfiltered
77
+ * collection (selection spans all items; filtering is display-only).
78
+ */
79
+ readonly selectionManager: SelectionManager<T>;
73
80
  /** Whether the combobox dropdown is open. */
74
81
  readonly isOpen: Accessor<boolean>;
75
82
  /** Open the combobox dropdown. */