@kenos-ui/react-datepicker 0.4.1 → 0.4.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @kenos-ui/react-datepicker
2
2
 
3
+ ## 0.4.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 3222bd8: Sync controlled single `value` into reducer state via a new `SET_SELECTED_DATE` action, keeping the segmented input and calendar focused month in sync when the prop changes externally.
8
+
3
9
  ## 0.4.1
4
10
 
5
11
  ### Minor Changes
@@ -9,18 +15,21 @@
9
15
  Headless date & scheduling primitives for React 19+, fully unstyled and composition-first.
10
16
 
11
17
  **Selection API**
18
+
12
19
  - Unified `DatePicker.Root` with `mode`: `"single"` | `"range"` | `"multiple"`
13
20
  - Controlled / uncontrolled `value`, `open`, and `onValueChange` / `onOpenChange`
14
21
  - Range mode with live hover preview between `rangeStart` and `rangeEnd`
15
22
  - `minDate`, `maxDate`, `disabled` (boolean or per-date function), `readOnly`, `closeOnSelect`
16
23
 
17
24
  **Segmented input (timescape)**
25
+
18
26
  - First-class `<DatePicker.Input />` — locale-aware month / day / year segments
19
27
  - Dual inputs for range (`index={0}` / `index={1}`)
20
28
  - Bidirectional sync: type in segments or pick from calendar
21
29
  - Custom `segmentLabels` for screen readers
22
30
 
23
31
  **Compound calendar parts**
32
+
24
33
  - `Label`, `Trigger`, `Content`, `Calendar` (shorthand composition)
25
34
  - `ViewControl`, `PrevTrigger`, `NextTrigger`, `ViewTrigger`
26
35
  - `View` with `day` / `month` / `year` drill-down
@@ -29,25 +38,30 @@
29
38
  - `useDatePickerContext()` for custom layouts
30
39
 
31
40
  **Positioning & popup policy**
41
+
32
42
  - Floating UI via `Content`: `side`, `align`, `sideOffset`, `avoidCollisions`, `portal`
33
43
  - `forceMount` for enter/exit animations (`data-state`)
34
44
  - `modal` prop (default `false`) — opt-in focus trap + `aria-modal`; popup-policy friendly
35
45
  - Focus restore to trigger / input on close; dialog-interop (`Escape` does not bubble)
36
46
 
37
47
  **State & i18n**
48
+
38
49
  - Reducer-driven state machine (`OPEN`, `SELECT_DATE`, `NAV_PREV`/`NAV_NEXT`, `SET_VIEW`, `COMMIT_INPUT`, …)
39
50
  - `Intl`-based locale: week start, month/year labels, segment order & separators
40
51
  - `weekStartsOn` override
41
52
 
42
53
  **Accessibility & quality**
54
+
43
55
  - WAI-ARIA: `role="dialog"`, `grid` / `gridcell`, labelled inputs, keyboard roving tabindex
44
56
  - Test suite: reducer, calendar grid, date utils, ARIA, keyboard nav, dialog interop, axe (vitest-axe)
45
57
  - Storybook: Single, Range, Multiple, Locales
46
58
 
47
59
  **Docs**
60
+
48
61
  - README with quick start, range / multiple examples, full composition, localization, and `Content` props
49
62
 
50
63
  **Packaging**
64
+
51
65
  - Add `license: MIT` to `package.json` (fixes npm registry showing "no license")
52
66
 
53
67
  ## 0.4.0
@@ -59,18 +73,21 @@
59
73
  Headless date & scheduling primitives for React 19+, fully unstyled and composition-first.
60
74
 
61
75
  **Selection API**
76
+
62
77
  - Unified `DatePicker.Root` with `mode`: `"single"` | `"range"` | `"multiple"`
63
78
  - Controlled / uncontrolled `value`, `open`, and `onValueChange` / `onOpenChange`
64
79
  - Range mode with live hover preview between `rangeStart` and `rangeEnd`
65
80
  - `minDate`, `maxDate`, `disabled` (boolean or per-date function), `readOnly`, `closeOnSelect`
66
81
 
67
82
  **Segmented input (timescape)**
83
+
68
84
  - First-class `<DatePicker.Input />` — locale-aware month / day / year segments
69
85
  - Dual inputs for range (`index={0}` / `index={1}`)
70
86
  - Bidirectional sync: type in segments or pick from calendar
71
87
  - Custom `segmentLabels` for screen readers
72
88
 
73
89
  **Compound calendar parts**
90
+
74
91
  - `Label`, `Trigger`, `Content`, `Calendar` (shorthand composition)
75
92
  - `ViewControl`, `PrevTrigger`, `NextTrigger`, `ViewTrigger`
76
93
  - `View` with `day` / `month` / `year` drill-down
@@ -79,22 +96,26 @@
79
96
  - `useDatePickerContext()` for custom layouts
80
97
 
81
98
  **Positioning & popup policy**
99
+
82
100
  - Floating UI via `Content`: `side`, `align`, `sideOffset`, `avoidCollisions`, `portal`
83
101
  - `forceMount` for enter/exit animations (`data-state`)
84
102
  - `modal` prop (default `false`) — opt-in focus trap + `aria-modal`; popup-policy friendly
85
103
  - Focus restore to trigger / input on close; dialog-interop (`Escape` does not bubble)
86
104
 
87
105
  **State & i18n**
106
+
88
107
  - Reducer-driven state machine (`OPEN`, `SELECT_DATE`, `NAV_PREV`/`NAV_NEXT`, `SET_VIEW`, `COMMIT_INPUT`, …)
89
108
  - `Intl`-based locale: week start, month/year labels, segment order & separators
90
109
  - `weekStartsOn` override
91
110
 
92
111
  **Accessibility & quality**
112
+
93
113
  - WAI-ARIA: `role="dialog"`, `grid` / `gridcell`, labelled inputs, keyboard roving tabindex
94
114
  - Test suite: reducer, calendar grid, date utils, ARIA, keyboard nav, dialog interop, axe (vitest-axe)
95
115
  - Storybook: Single, Range, Multiple, Locales
96
116
 
97
117
  **Docs**
118
+
98
119
  - README with quick start, range / multiple examples, full composition, localization, and `Content` props
99
120
 
100
121
  ## 0.3.3
@@ -125,6 +146,7 @@
125
146
  ### Minor Changes
126
147
 
127
148
  - Axis lift-and-shift: publish DatePicker under `@at5/axis-datepicker`.
149
+
128
150
  - Add `@at5/axis-datepicker` — same DatePicker API and behavior as `@at5/kairo` (migrated from `packages/kairo` to `packages/datepicker`)
129
151
  - Add `@at5/axis` — aggregator re-exporting `DatePicker`
130
152
  - `@at5/kairo` — deprecated; thin re-export of `@at5/axis-datepicker` for transition
package/dist/index.cjs CHANGED
@@ -362,6 +362,20 @@ function datePickerReducer(state, action, config) {
362
362
  } : {}
363
363
  };
364
364
  }
365
+ case "SET_SELECTED_DATE": {
366
+ const d = action.date ? startOfDay(action.date) : null;
367
+ return {
368
+ ...state,
369
+ selectedDate: d,
370
+ inputValue: d ? formatDate(d, config.locale) : "",
371
+ ...d ? {
372
+ focusedDate: d,
373
+ focusedMonth: d.getMonth(),
374
+ focusedYear: d.getFullYear(),
375
+ yearPageStart: yearPageStart(d.getFullYear())
376
+ } : {}
377
+ };
378
+ }
365
379
  case "SET_INPUT":
366
380
  return { ...state, inputValue: action.value };
367
381
  case "COMMIT_INPUT": {
@@ -488,6 +502,17 @@ function useDatePicker(props) {
488
502
  prevSelectedRef.current = state.selectedDate;
489
503
  }
490
504
  }, [state.selectedDate]);
505
+ const controlledSingleValue = (!props.mode || props.mode === "single") && "value" in props && props.value !== void 0 ? props.value : void 0;
506
+ const propSelectedT = controlledSingleValue?.getTime() ?? null;
507
+ const lastSyncedPropSelectedRef = React.useRef(null);
508
+ React.useEffect(() => {
509
+ if (controlledSingleValue === void 0) return;
510
+ if (lastSyncedPropSelectedRef.current === propSelectedT) return;
511
+ lastSyncedPropSelectedRef.current = propSelectedT;
512
+ const stateT = state.selectedDate?.getTime() ?? null;
513
+ if (propSelectedT === stateT) return;
514
+ dispatch({ type: "SET_SELECTED_DATE", date: controlledSingleValue });
515
+ }, [propSelectedT, dispatch]);
491
516
  const controlledRangeValue = props.mode === "range" && "value" in props && props.value !== void 0 ? props.value : void 0;
492
517
  const lastSyncedPropRangeRef = React.useRef(
493
518
  null