@nepdatejs/react 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +74 -2
- package/dist/date-text-BX3Uag0O.cjs +84 -0
- package/dist/date-text-BX3Uag0O.cjs.map +1 -0
- package/dist/date-text-DLwhBmYj.js +61 -0
- package/dist/date-text-DLwhBmYj.js.map +1 -0
- package/dist/date-text-Dipetpbp.d.cts +37 -0
- package/dist/date-text-Dipetpbp.d.ts +37 -0
- package/dist/headless-AEI6dxTJ.cjs +619 -0
- package/dist/headless-AEI6dxTJ.cjs.map +1 -0
- package/dist/headless-CVj0DhD4.js +560 -0
- package/dist/headless-CVj0DhD4.js.map +1 -0
- package/dist/headless-ChE3zuYj.d.ts +195 -0
- package/dist/headless-CrIIPnOF.d.cts +195 -0
- package/dist/headless.cjs +11 -0
- package/dist/headless.d.cts +2 -0
- package/dist/headless.d.ts +2 -0
- package/dist/headless.js +2 -0
- package/dist/index.cjs +915 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +245 -0
- package/dist/index.d.ts +245 -0
- package/dist/index.js +895 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +6 -0
- package/dist/server.d.cts +2 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +1 -0
- package/package.json +110 -3
- package/src/bindings.ts +247 -0
- package/src/calendar-body.tsx +133 -0
- package/src/calendar.tsx +34 -0
- package/src/date-picker.tsx +343 -0
- package/src/date-range-picker.tsx +225 -0
- package/src/date-text.tsx +110 -0
- package/src/date-time-picker.tsx +289 -0
- package/src/headless.ts +21 -0
- package/src/hooks.ts +476 -0
- package/src/icons.tsx +35 -0
- package/src/index.ts +21 -0
- package/src/multi-date-picker.tsx +245 -0
- package/src/page-locale.ts +23 -0
- package/src/panel.ts +67 -0
- package/src/presets.tsx +44 -0
- package/src/server.ts +8 -0
- package/src/time-columns.tsx +60 -0
- package/src/use-store.ts +196 -0
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
let react = require("react");
|
|
2
|
+
let _nepdatejs_core = require("@nepdatejs/core");
|
|
3
|
+
let _nepdatejs_calendar = require("@nepdatejs/calendar");
|
|
4
|
+
let _nepdatejs_datepicker = require("@nepdatejs/datepicker");
|
|
5
|
+
//#region src/bindings.ts
|
|
6
|
+
const FOCUS_KEYS = /* @__PURE__ */ new Set([
|
|
7
|
+
"ArrowLeft",
|
|
8
|
+
"ArrowRight",
|
|
9
|
+
"ArrowUp",
|
|
10
|
+
"ArrowDown",
|
|
11
|
+
"Home",
|
|
12
|
+
"End",
|
|
13
|
+
"PageUp",
|
|
14
|
+
"PageDown"
|
|
15
|
+
]);
|
|
16
|
+
function useCalendarBindings(state, actions, locale, options) {
|
|
17
|
+
const { getSnapshot, onDayActivate } = options;
|
|
18
|
+
const grid = (0, react.useRef)(null);
|
|
19
|
+
const root = (0, react.useRef)(null);
|
|
20
|
+
const focusRequested = (0, react.useRef)(false);
|
|
21
|
+
const labels = (0, _nepdatejs_core.getLocale)(locale).labels;
|
|
22
|
+
const focusGrid = (0, react.useCallback)(() => {
|
|
23
|
+
(grid.current?.closest(".ndp-calendar") ?? grid.current ?? root.current)?.querySelector(".ndp-day[tabindex=\"0\"], .ndp-option[tabindex=\"0\"]")?.focus();
|
|
24
|
+
}, []);
|
|
25
|
+
(0, react.useEffect)(() => {
|
|
26
|
+
if (focusRequested.current) {
|
|
27
|
+
focusRequested.current = false;
|
|
28
|
+
focusGrid();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
const requestFocus = () => {
|
|
32
|
+
focusRequested.current = true;
|
|
33
|
+
};
|
|
34
|
+
const activate = onDayActivate ?? ((date) => actions.select(date));
|
|
35
|
+
const [monthName, yearText] = splitTitle(state.title);
|
|
36
|
+
const focusIndex = (tiles) => {
|
|
37
|
+
const selected = tiles.findIndex((tile) => tile.isSelected);
|
|
38
|
+
const current = tiles.findIndex((tile) => tile.isCurrent);
|
|
39
|
+
return Math.max(0, selected === -1 ? current : selected);
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
state,
|
|
43
|
+
actions,
|
|
44
|
+
focusGrid,
|
|
45
|
+
getGridProps: () => ({
|
|
46
|
+
role: "grid",
|
|
47
|
+
"aria-label": state.title,
|
|
48
|
+
ref: (node) => {
|
|
49
|
+
grid.current = node;
|
|
50
|
+
},
|
|
51
|
+
onKeyDown: (event) => {
|
|
52
|
+
if (!FOCUS_KEYS.has(event.key)) return;
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
requestFocus();
|
|
55
|
+
actions.moveFocus(event.key, { shift: event.shiftKey });
|
|
56
|
+
if (getSnapshot() === state) {
|
|
57
|
+
focusRequested.current = false;
|
|
58
|
+
focusGrid();
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
onMouseLeave: () => {
|
|
62
|
+
if (state.selectionMode === "range") actions.hover(null);
|
|
63
|
+
}
|
|
64
|
+
}),
|
|
65
|
+
getDayProps: (cell) => ({
|
|
66
|
+
type: "button",
|
|
67
|
+
tabIndex: cell.isFocusTarget ? 0 : -1,
|
|
68
|
+
disabled: cell.isDisabled,
|
|
69
|
+
"aria-pressed": cell.isSelected,
|
|
70
|
+
...cell.isToday ? { "aria-current": "date" } : {},
|
|
71
|
+
"data-state": cell.state,
|
|
72
|
+
"data-weekend": cell.isWeekend || void 0,
|
|
73
|
+
"data-preview": cell.isInRangePreview && !cell.isSelected || void 0,
|
|
74
|
+
"data-outside": cell.isOutside || void 0,
|
|
75
|
+
onClick: () => {
|
|
76
|
+
if (!cell.isDisabled) activate(cell.date);
|
|
77
|
+
},
|
|
78
|
+
onFocus: () => {
|
|
79
|
+
if (!cell.isFocusTarget) actions.focus(cell.date);
|
|
80
|
+
},
|
|
81
|
+
onMouseEnter: () => {
|
|
82
|
+
if (state.selectionMode === "range") actions.hover(cell.isDisabled ? null : cell.date);
|
|
83
|
+
}
|
|
84
|
+
}),
|
|
85
|
+
getPrevProps: () => ({
|
|
86
|
+
type: "button",
|
|
87
|
+
disabled: !state.canPrev,
|
|
88
|
+
"aria-label": state.view === "day" ? labels.previousMonth : labels.previousYear,
|
|
89
|
+
onClick: () => {
|
|
90
|
+
actions.prev();
|
|
91
|
+
}
|
|
92
|
+
}),
|
|
93
|
+
getNextProps: () => ({
|
|
94
|
+
type: "button",
|
|
95
|
+
disabled: !state.canNext,
|
|
96
|
+
"aria-label": state.view === "day" ? labels.nextMonth : labels.nextYear,
|
|
97
|
+
onClick: () => {
|
|
98
|
+
actions.next();
|
|
99
|
+
}
|
|
100
|
+
}),
|
|
101
|
+
getTitleButtons: () => state.view === "day" ? [{
|
|
102
|
+
key: "month",
|
|
103
|
+
label: monthName,
|
|
104
|
+
props: {
|
|
105
|
+
type: "button",
|
|
106
|
+
"aria-label": `${labels.month}: ${monthName}`,
|
|
107
|
+
onClick: () => {
|
|
108
|
+
requestFocus();
|
|
109
|
+
actions.setView("month");
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}, {
|
|
113
|
+
key: "year",
|
|
114
|
+
label: yearText,
|
|
115
|
+
props: {
|
|
116
|
+
type: "button",
|
|
117
|
+
"aria-label": `${labels.year}: ${yearText}`,
|
|
118
|
+
onClick: () => {
|
|
119
|
+
requestFocus();
|
|
120
|
+
actions.setView("year");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}] : [{
|
|
124
|
+
key: "up",
|
|
125
|
+
label: state.title,
|
|
126
|
+
props: {
|
|
127
|
+
type: "button",
|
|
128
|
+
"aria-label": state.view === "fiscal" ? state.title : `${labels.year}: ${state.title}`,
|
|
129
|
+
onClick: () => {
|
|
130
|
+
requestFocus();
|
|
131
|
+
actions.setView(state.view === "month" ? "year" : "day");
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}],
|
|
135
|
+
getOptionProps: (tile, index, tiles) => ({
|
|
136
|
+
type: "button",
|
|
137
|
+
tabIndex: index === focusIndex(tiles) ? 0 : -1,
|
|
138
|
+
disabled: tile.isDisabled,
|
|
139
|
+
"aria-pressed": tile.isSelected,
|
|
140
|
+
"data-state": tile.isSelected ? "selected" : tile.isCurrent ? "current" : "default",
|
|
141
|
+
onClick: () => {
|
|
142
|
+
requestFocus();
|
|
143
|
+
if (state.view === "month") actions.chooseMonth(tile.value);
|
|
144
|
+
else if (state.view === "year") actions.chooseYear(tile.value);
|
|
145
|
+
else actions.chooseFiscalYear(tile.value);
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/** "Kartik 2083" → ["Kartik", "2083"]. */
|
|
151
|
+
function splitTitle(title) {
|
|
152
|
+
const space = title.lastIndexOf(" ");
|
|
153
|
+
return space === -1 ? [title, ""] : [title.slice(0, space), title.slice(space + 1)];
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/use-store.ts
|
|
157
|
+
/** Function options whose answers decide how the calendar's days look. */
|
|
158
|
+
const DAY_FUNCTIONS = [
|
|
159
|
+
"isDateDisabled",
|
|
160
|
+
"holidays",
|
|
161
|
+
"events"
|
|
162
|
+
];
|
|
163
|
+
/** useLayoutEffect in the browser, useEffect on the server (no warning). */
|
|
164
|
+
const useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
|
|
165
|
+
/**
|
|
166
|
+
* Create a store once and keep its options in step with props, without
|
|
167
|
+
* loops: functions are wrapped once so their identity never changes, and data
|
|
168
|
+
* options are compared by value, so inline objects and arrays are fine.
|
|
169
|
+
*/
|
|
170
|
+
function useStore(create, options) {
|
|
171
|
+
const latest = (0, react.useRef)(options);
|
|
172
|
+
latest.current = options;
|
|
173
|
+
const wrappers = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
174
|
+
const prepare = (input) => {
|
|
175
|
+
const out = {};
|
|
176
|
+
for (const [key, value] of Object.entries(input)) if (typeof value === "function") {
|
|
177
|
+
let wrapper = wrappers.current.get(key);
|
|
178
|
+
if (!wrapper) {
|
|
179
|
+
wrapper = (...args) => latest.current[key]?.(...args);
|
|
180
|
+
wrappers.current.set(key, wrapper);
|
|
181
|
+
}
|
|
182
|
+
out[key] = wrapper;
|
|
183
|
+
} else out[key] = value;
|
|
184
|
+
return out;
|
|
185
|
+
};
|
|
186
|
+
const [store] = (0, react.useState)(() => create(prepare(options)));
|
|
187
|
+
const previous = (0, react.useRef)(prepare(options));
|
|
188
|
+
const dayAnswers = (0, react.useRef)(null);
|
|
189
|
+
const storeValue = (0, react.useRef)(valueOf(store.getState()));
|
|
190
|
+
useIsomorphicLayoutEffect(() => {
|
|
191
|
+
const next = prepare(options);
|
|
192
|
+
const before = previous.current;
|
|
193
|
+
const changes = {};
|
|
194
|
+
for (const key of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(next)])) if (!deepEqual(before[key], next[key])) changes[key] = next[key];
|
|
195
|
+
previous.current = next;
|
|
196
|
+
const current = askDayFunctions(options, store.getState());
|
|
197
|
+
const asked = dayAnswers.current;
|
|
198
|
+
dayAnswers.current = current;
|
|
199
|
+
if (asked?.days === current?.days && asked?.answers !== current?.answers) {
|
|
200
|
+
for (const key of DAY_FUNCTIONS) if (key in next) changes[key] = next[key];
|
|
201
|
+
}
|
|
202
|
+
if (Object.keys(changes).length > 0) store.setOptions(changes);
|
|
203
|
+
const value = valueOf(store.getState());
|
|
204
|
+
const changedByUser = !deepEqual(value, storeValue.current) && !("value" in changes);
|
|
205
|
+
storeValue.current = value;
|
|
206
|
+
const held = next["value"];
|
|
207
|
+
if (changedByUser && held !== void 0 && isChosen(value) && !deepEqual(value, held)) {
|
|
208
|
+
store.actions?.setValue?.(held);
|
|
209
|
+
storeValue.current = valueOf(store.getState());
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
store,
|
|
214
|
+
state: (0, react.useSyncExternalStore)((listener) => store.subscribe(listener), () => store.getState(), () => store.getState())
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
function valueOf(state) {
|
|
218
|
+
return state.value;
|
|
219
|
+
}
|
|
220
|
+
/** A finished value: not empty, half typed, or a range with one end still to pick. */
|
|
221
|
+
function isChosen(value) {
|
|
222
|
+
if (Array.isArray(value)) return value.length > 0;
|
|
223
|
+
if (typeof value === "object" && value !== null) return Object.values(value).every((part) => part !== "");
|
|
224
|
+
return value !== "" && value !== void 0;
|
|
225
|
+
}
|
|
226
|
+
/** What the day functions say about the days on screen, or null when there are none. */
|
|
227
|
+
function askDayFunctions(options, state) {
|
|
228
|
+
const given = DAY_FUNCTIONS.flatMap((key) => {
|
|
229
|
+
const option = options[key];
|
|
230
|
+
return typeof option === "function" ? [option] : [];
|
|
231
|
+
});
|
|
232
|
+
if (given.length === 0) return null;
|
|
233
|
+
const { weeks, calendarState } = state;
|
|
234
|
+
const dates = (weeks ?? calendarState?.weeks ?? []).flat().flatMap((cell) => cell ? [cell.date] : []);
|
|
235
|
+
return {
|
|
236
|
+
days: JSON.stringify(dates),
|
|
237
|
+
answers: JSON.stringify(dates.map((date) => given.map((ask) => ask(date))))
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
/** Structural equality for plain data (dates, ranges, lists); identity for everything else. */
|
|
241
|
+
function deepEqual(a, b) {
|
|
242
|
+
if (Object.is(a, b)) return true;
|
|
243
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
244
|
+
if (Array.isArray(a) || Array.isArray(b)) return Array.isArray(a) && Array.isArray(b) && a.length === b.length && a.every((item, index) => deepEqual(item, b[index]));
|
|
245
|
+
if (Object.getPrototypeOf(a) !== Object.prototype || Object.getPrototypeOf(b) !== Object.prototype) return false;
|
|
246
|
+
const keysA = Object.keys(a);
|
|
247
|
+
const keysB = Object.keys(b);
|
|
248
|
+
return keysA.length === keysB.length && keysA.every((key) => deepEqual(a[key], b[key]));
|
|
249
|
+
}
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/hooks.ts
|
|
252
|
+
/** A standalone calendar: state, actions and prop getters. */
|
|
253
|
+
function useCalendar(options = {}) {
|
|
254
|
+
const { store, state } = useStore(_nepdatejs_calendar.createCalendar, options);
|
|
255
|
+
return {
|
|
256
|
+
...useCalendarBindings(state, store.actions, options.locale, { getSnapshot: () => store.getState() }),
|
|
257
|
+
store
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
/** A BS/AD date picker without markup: wire the getters to your own elements. */
|
|
261
|
+
function useDatePicker(options = {}) {
|
|
262
|
+
const { id: givenId, ...storeOptions } = options;
|
|
263
|
+
const { store, state } = useStore(_nepdatejs_datepicker.createDatePicker, storeOptions);
|
|
264
|
+
const generated = (0, react.useId)();
|
|
265
|
+
const input = givenId ?? `ndp${generated.replace(/:/g, "")}`;
|
|
266
|
+
const ids = {
|
|
267
|
+
input,
|
|
268
|
+
panel: `${input}-panel`,
|
|
269
|
+
hint: `${input}-hint`
|
|
270
|
+
};
|
|
271
|
+
const labels = (0, _nepdatejs_core.getLocale)(options.locale);
|
|
272
|
+
const calendar = useCalendarBindings(state.calendarState, store.calendar.actions, options.locale, {
|
|
273
|
+
getSnapshot: () => store.calendar.getState(),
|
|
274
|
+
onDayActivate: (date) => {
|
|
275
|
+
store.actions.select(date);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
const hasHint = state.error !== null || state.equivalentText !== null;
|
|
279
|
+
return {
|
|
280
|
+
state,
|
|
281
|
+
actions: store.actions,
|
|
282
|
+
store,
|
|
283
|
+
calendar,
|
|
284
|
+
ids,
|
|
285
|
+
getInputProps: () => ({
|
|
286
|
+
id: ids.input,
|
|
287
|
+
...popupProps(state),
|
|
288
|
+
type: "text",
|
|
289
|
+
inputMode: "numeric",
|
|
290
|
+
autoComplete: "off",
|
|
291
|
+
value: state.text,
|
|
292
|
+
placeholder: state.placeholder,
|
|
293
|
+
"aria-controls": ids.panel,
|
|
294
|
+
...state.error ? { "aria-invalid": true } : {},
|
|
295
|
+
...hasHint ? { "aria-describedby": ids.hint } : {},
|
|
296
|
+
onChange: (event) => {
|
|
297
|
+
store.actions.type(event.target.value);
|
|
298
|
+
},
|
|
299
|
+
onBlur: () => {
|
|
300
|
+
store.actions.blur();
|
|
301
|
+
},
|
|
302
|
+
onKeyDown: (event) => {
|
|
303
|
+
if (event.key === "ArrowDown" && (event.altKey || state.text === "")) {
|
|
304
|
+
event.preventDefault();
|
|
305
|
+
store.actions.open();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}),
|
|
309
|
+
getToggleProps: () => ({
|
|
310
|
+
type: "button",
|
|
311
|
+
"aria-label": labels.labels.openCalendar,
|
|
312
|
+
"aria-expanded": state.open,
|
|
313
|
+
"aria-controls": ids.panel,
|
|
314
|
+
onClick: () => {
|
|
315
|
+
store.actions.toggle();
|
|
316
|
+
}
|
|
317
|
+
}),
|
|
318
|
+
getClearProps: () => ({
|
|
319
|
+
type: "button",
|
|
320
|
+
"aria-label": labels.labels.clear,
|
|
321
|
+
onClick: () => {
|
|
322
|
+
store.actions.clear();
|
|
323
|
+
}
|
|
324
|
+
}),
|
|
325
|
+
getSwitchProps: () => {
|
|
326
|
+
const other = state.calendar === "BS" ? "AD" : "BS";
|
|
327
|
+
return {
|
|
328
|
+
type: "button",
|
|
329
|
+
"aria-label": `${labels.labels.calendar}: ${labels.calendarNames[state.calendar]} → ${labels.calendarNames[other]}`,
|
|
330
|
+
onClick: () => {
|
|
331
|
+
store.actions.switchCalendar(other);
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
},
|
|
335
|
+
getCalendarOptionProps: (option) => ({
|
|
336
|
+
type: "button",
|
|
337
|
+
"aria-pressed": state.calendar === option,
|
|
338
|
+
onClick: () => {
|
|
339
|
+
store.actions.switchCalendar(option);
|
|
340
|
+
}
|
|
341
|
+
}),
|
|
342
|
+
getTodayProps: () => ({
|
|
343
|
+
type: "button",
|
|
344
|
+
onClick: () => {
|
|
345
|
+
store.actions.selectToday();
|
|
346
|
+
}
|
|
347
|
+
}),
|
|
348
|
+
getPanelProps: () => ({
|
|
349
|
+
id: ids.panel,
|
|
350
|
+
role: state.inline ? "group" : "dialog",
|
|
351
|
+
"aria-label": labels.labels.chooseDate
|
|
352
|
+
}),
|
|
353
|
+
getPresetProps: (preset) => presetProps(preset, (id) => store.actions.applyPreset(id))
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
/** Combobox ARIA for a popup picker; an inline picker's input is a plain text field. */
|
|
357
|
+
function popupProps(state) {
|
|
358
|
+
return state.inline ? {} : {
|
|
359
|
+
role: "combobox",
|
|
360
|
+
"aria-haspopup": "dialog",
|
|
361
|
+
"aria-expanded": state.open
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function presetProps(preset, apply) {
|
|
365
|
+
return {
|
|
366
|
+
type: "button",
|
|
367
|
+
"aria-pressed": preset.isActive,
|
|
368
|
+
disabled: preset.isDisabled,
|
|
369
|
+
onClick: () => {
|
|
370
|
+
apply(preset.id);
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
/** A BS/AD date range picker without markup. */
|
|
375
|
+
function useDateRangePicker(options = {}) {
|
|
376
|
+
const { store, state } = useStore(_nepdatejs_datepicker.createDateRangePicker, options);
|
|
377
|
+
const base = `ndp${(0, react.useId)().replace(/:/g, "")}`;
|
|
378
|
+
const ids = {
|
|
379
|
+
start: `${base}-start`,
|
|
380
|
+
end: `${base}-end`,
|
|
381
|
+
panel: `${base}-panel`,
|
|
382
|
+
hint: `${base}-hint`
|
|
383
|
+
};
|
|
384
|
+
const labels = (0, _nepdatejs_core.getLocale)(options.locale);
|
|
385
|
+
const calendar = useCalendarBindings(state.calendarState, store.calendar.actions, options.locale, {
|
|
386
|
+
getSnapshot: () => store.calendar.getState(),
|
|
387
|
+
onDayActivate: (date) => {
|
|
388
|
+
store.actions.select(date);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
const texts = {
|
|
392
|
+
start: state.startText,
|
|
393
|
+
end: state.endText
|
|
394
|
+
};
|
|
395
|
+
return {
|
|
396
|
+
state,
|
|
397
|
+
actions: store.actions,
|
|
398
|
+
store,
|
|
399
|
+
calendar,
|
|
400
|
+
ids,
|
|
401
|
+
getInputProps: (field) => {
|
|
402
|
+
const invalid = state.error !== null && (state.error.field === field || state.error.field === "range");
|
|
403
|
+
return {
|
|
404
|
+
id: ids[field],
|
|
405
|
+
...popupProps(state),
|
|
406
|
+
type: "text",
|
|
407
|
+
inputMode: "numeric",
|
|
408
|
+
autoComplete: "off",
|
|
409
|
+
value: texts[field],
|
|
410
|
+
placeholder: state.placeholder,
|
|
411
|
+
"aria-controls": ids.panel,
|
|
412
|
+
...invalid ? { "aria-invalid": true } : {},
|
|
413
|
+
...state.error ? { "aria-describedby": ids.hint } : {},
|
|
414
|
+
onChange: (event) => {
|
|
415
|
+
store.actions.type(field, event.target.value);
|
|
416
|
+
},
|
|
417
|
+
onBlur: () => {
|
|
418
|
+
store.actions.blur(field);
|
|
419
|
+
},
|
|
420
|
+
onKeyDown: (event) => {
|
|
421
|
+
if (event.key === "ArrowDown" && (event.altKey || texts[field] === "")) {
|
|
422
|
+
event.preventDefault();
|
|
423
|
+
store.actions.open();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
},
|
|
428
|
+
getToggleProps: () => ({
|
|
429
|
+
type: "button",
|
|
430
|
+
"aria-label": labels.labels.openCalendar,
|
|
431
|
+
"aria-expanded": state.open,
|
|
432
|
+
"aria-controls": ids.panel,
|
|
433
|
+
onClick: () => {
|
|
434
|
+
store.actions.toggle();
|
|
435
|
+
}
|
|
436
|
+
}),
|
|
437
|
+
getCalendarOptionProps: (option) => ({
|
|
438
|
+
type: "button",
|
|
439
|
+
"aria-pressed": state.calendar === option,
|
|
440
|
+
onClick: () => {
|
|
441
|
+
store.actions.switchCalendar(option);
|
|
442
|
+
}
|
|
443
|
+
}),
|
|
444
|
+
getPanelProps: () => ({
|
|
445
|
+
id: ids.panel,
|
|
446
|
+
role: state.inline ? "group" : "dialog",
|
|
447
|
+
"aria-label": labels.labels.chooseDate
|
|
448
|
+
}),
|
|
449
|
+
getPresetProps: (preset) => presetProps(preset, (id) => store.actions.applyPreset(id))
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
/** A BS/AD date + time picker without markup. The value is a zoned ISO timestamp. */
|
|
453
|
+
function useDateTimePicker(options = {}) {
|
|
454
|
+
const { id: givenId, ...storeOptions } = options;
|
|
455
|
+
const { store, state } = useStore(_nepdatejs_datepicker.createDateTimePicker, storeOptions);
|
|
456
|
+
const generated = (0, react.useId)();
|
|
457
|
+
const base = givenId ?? `ndp${generated.replace(/:/g, "")}`;
|
|
458
|
+
const calendar = useCalendarBindings(state.calendarState, store.calendar.actions, options.locale, {
|
|
459
|
+
getSnapshot: () => store.calendar.getState(),
|
|
460
|
+
onDayActivate: (date) => {
|
|
461
|
+
store.actions.selectDate(date);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
return {
|
|
465
|
+
state,
|
|
466
|
+
actions: store.actions,
|
|
467
|
+
store,
|
|
468
|
+
calendar,
|
|
469
|
+
ids: {
|
|
470
|
+
date: base,
|
|
471
|
+
time: `${base}-time`,
|
|
472
|
+
panel: `${base}-panel`,
|
|
473
|
+
hint: `${base}-hint`
|
|
474
|
+
}
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
/** A picker for several separate BS/AD days, without markup (PICK-001). */
|
|
478
|
+
function useMultiDatePicker(options = {}) {
|
|
479
|
+
const { id: givenId, ...storeOptions } = options;
|
|
480
|
+
const { store, state } = useStore(_nepdatejs_datepicker.createMultiDatePicker, storeOptions);
|
|
481
|
+
const generated = (0, react.useId)();
|
|
482
|
+
const input = givenId ?? `ndp${generated.replace(/:/g, "")}`;
|
|
483
|
+
const ids = {
|
|
484
|
+
input,
|
|
485
|
+
panel: `${input}-panel`,
|
|
486
|
+
hint: `${input}-hint`
|
|
487
|
+
};
|
|
488
|
+
const labels = (0, _nepdatejs_core.getLocale)(options.locale);
|
|
489
|
+
const calendar = useCalendarBindings(state.calendarState, store.calendar.actions, options.locale, {
|
|
490
|
+
getSnapshot: () => store.calendar.getState(),
|
|
491
|
+
onDayActivate: (date) => {
|
|
492
|
+
store.actions.select(date);
|
|
493
|
+
}
|
|
494
|
+
});
|
|
495
|
+
return {
|
|
496
|
+
state,
|
|
497
|
+
actions: store.actions,
|
|
498
|
+
store,
|
|
499
|
+
calendar,
|
|
500
|
+
ids,
|
|
501
|
+
getInputProps: () => ({
|
|
502
|
+
id: ids.input,
|
|
503
|
+
...popupProps(state),
|
|
504
|
+
type: "text",
|
|
505
|
+
inputMode: "numeric",
|
|
506
|
+
autoComplete: "off",
|
|
507
|
+
value: state.text,
|
|
508
|
+
placeholder: state.placeholder,
|
|
509
|
+
"aria-controls": ids.panel,
|
|
510
|
+
...state.error ? {
|
|
511
|
+
"aria-invalid": true,
|
|
512
|
+
"aria-describedby": ids.hint
|
|
513
|
+
} : {},
|
|
514
|
+
onChange: (event) => {
|
|
515
|
+
store.actions.type(event.target.value);
|
|
516
|
+
},
|
|
517
|
+
onBlur: () => {
|
|
518
|
+
store.actions.blur();
|
|
519
|
+
},
|
|
520
|
+
onKeyDown: (event) => {
|
|
521
|
+
if (event.key === "ArrowDown" && (event.altKey || state.text === "")) {
|
|
522
|
+
event.preventDefault();
|
|
523
|
+
store.actions.open();
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}),
|
|
527
|
+
getToggleProps: () => ({
|
|
528
|
+
type: "button",
|
|
529
|
+
"aria-label": labels.labels.openCalendar,
|
|
530
|
+
"aria-expanded": state.open,
|
|
531
|
+
"aria-controls": ids.panel,
|
|
532
|
+
onClick: () => {
|
|
533
|
+
store.actions.toggle();
|
|
534
|
+
}
|
|
535
|
+
}),
|
|
536
|
+
getClearProps: () => ({
|
|
537
|
+
type: "button",
|
|
538
|
+
"aria-label": labels.labels.clear,
|
|
539
|
+
onClick: () => {
|
|
540
|
+
store.actions.clear();
|
|
541
|
+
}
|
|
542
|
+
}),
|
|
543
|
+
getCalendarOptionProps: (option) => ({
|
|
544
|
+
type: "button",
|
|
545
|
+
"aria-pressed": state.calendar === option,
|
|
546
|
+
onClick: () => {
|
|
547
|
+
store.actions.switchCalendar(option);
|
|
548
|
+
}
|
|
549
|
+
}),
|
|
550
|
+
getPanelProps: () => ({
|
|
551
|
+
id: ids.panel,
|
|
552
|
+
role: state.inline ? "group" : "dialog",
|
|
553
|
+
"aria-label": labels.labels.chooseDate
|
|
554
|
+
})
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
//#endregion
|
|
558
|
+
Object.defineProperty(exports, "deepEqual", {
|
|
559
|
+
enumerable: true,
|
|
560
|
+
get: function() {
|
|
561
|
+
return deepEqual;
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
Object.defineProperty(exports, "popupProps", {
|
|
565
|
+
enumerable: true,
|
|
566
|
+
get: function() {
|
|
567
|
+
return popupProps;
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
Object.defineProperty(exports, "useCalendar", {
|
|
571
|
+
enumerable: true,
|
|
572
|
+
get: function() {
|
|
573
|
+
return useCalendar;
|
|
574
|
+
}
|
|
575
|
+
});
|
|
576
|
+
Object.defineProperty(exports, "useCalendarBindings", {
|
|
577
|
+
enumerable: true,
|
|
578
|
+
get: function() {
|
|
579
|
+
return useCalendarBindings;
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
Object.defineProperty(exports, "useDatePicker", {
|
|
583
|
+
enumerable: true,
|
|
584
|
+
get: function() {
|
|
585
|
+
return useDatePicker;
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
Object.defineProperty(exports, "useDateRangePicker", {
|
|
589
|
+
enumerable: true,
|
|
590
|
+
get: function() {
|
|
591
|
+
return useDateRangePicker;
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
Object.defineProperty(exports, "useDateTimePicker", {
|
|
595
|
+
enumerable: true,
|
|
596
|
+
get: function() {
|
|
597
|
+
return useDateTimePicker;
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
Object.defineProperty(exports, "useIsomorphicLayoutEffect", {
|
|
601
|
+
enumerable: true,
|
|
602
|
+
get: function() {
|
|
603
|
+
return useIsomorphicLayoutEffect;
|
|
604
|
+
}
|
|
605
|
+
});
|
|
606
|
+
Object.defineProperty(exports, "useMultiDatePicker", {
|
|
607
|
+
enumerable: true,
|
|
608
|
+
get: function() {
|
|
609
|
+
return useMultiDatePicker;
|
|
610
|
+
}
|
|
611
|
+
});
|
|
612
|
+
Object.defineProperty(exports, "useStore", {
|
|
613
|
+
enumerable: true,
|
|
614
|
+
get: function() {
|
|
615
|
+
return useStore;
|
|
616
|
+
}
|
|
617
|
+
});
|
|
618
|
+
|
|
619
|
+
//# sourceMappingURL=headless-AEI6dxTJ.cjs.map
|