@sit-onyx/headless 0.1.1-dev-20250922084911 → 0.2.0-dev-20251014161744
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/dist/composables/calendar/createCalendar.d.ts +71 -0
- package/dist/composables/calendar/createCalendar.spec.d.ts +1 -0
- package/dist/composables/comboBox/SelectOnlyCombobox.d.vue.ts +15 -4
- package/dist/composables/comboBox/TestCombobox.d.vue.ts +15 -4
- package/dist/composables/comboBox/createComboBox.d.ts +15 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +299 -1
- package/dist/utils/dates.d.ts +15 -0
- package/package.json +5 -5
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { MaybeRefOrGetter, Ref } from 'vue';
|
|
2
|
+
import { DateRange, DateValue, Weekday } from '../../utils/dates.js';
|
|
3
|
+
import { Nullable } from '../../utils/types.js';
|
|
4
|
+
export type SelectionMode = "single" | "multiple" | "range";
|
|
5
|
+
export type CalendarSize = "small" | "big";
|
|
6
|
+
export type CreateCalendarOptions = {
|
|
7
|
+
locale: MaybeRefOrGetter<string>;
|
|
8
|
+
calendarSize: MaybeRefOrGetter<CalendarSize>;
|
|
9
|
+
weekStartDay: MaybeRefOrGetter<Weekday>;
|
|
10
|
+
viewMonth: Ref<DateValue>;
|
|
11
|
+
modelValue?: Ref<Nullable<DateValue | DateValue[] | DateRange>>;
|
|
12
|
+
disabled?: MaybeRefOrGetter<boolean>;
|
|
13
|
+
min?: MaybeRefOrGetter<Nullable<DateValue>>;
|
|
14
|
+
max?: MaybeRefOrGetter<Nullable<DateValue>>;
|
|
15
|
+
showCalendarWeeks?: MaybeRefOrGetter<boolean>;
|
|
16
|
+
selectionMode?: MaybeRefOrGetter<SelectionMode>;
|
|
17
|
+
onUpdateViewMonth?: (date: Date) => unknown;
|
|
18
|
+
onUpdateModelValue?: (newValue: Date | Date[] | DateRange) => unknown;
|
|
19
|
+
};
|
|
20
|
+
export type RenderWeek = {
|
|
21
|
+
weekNumber: number;
|
|
22
|
+
days: RenderDay[];
|
|
23
|
+
};
|
|
24
|
+
export type RenderDay = {
|
|
25
|
+
date: Date;
|
|
26
|
+
isCurrentMonth: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* @experimental
|
|
30
|
+
* @deprecated This component is still under active development and its API might change in patch releases.
|
|
31
|
+
*/
|
|
32
|
+
export declare const _unstableCreateCalendar: (options: CreateCalendarOptions) => import('../../utils/builder.js').HeadlessComposable<{
|
|
33
|
+
table: {
|
|
34
|
+
role: string;
|
|
35
|
+
onKeydown: (event: KeyboardEvent) => Promise<void>;
|
|
36
|
+
ref: import('../../utils/builder.js').HeadlessElRef<HTMLElement>;
|
|
37
|
+
};
|
|
38
|
+
cell: import('vue').ComputedRef<(cell: {
|
|
39
|
+
date: Date;
|
|
40
|
+
}) => {
|
|
41
|
+
role: string;
|
|
42
|
+
"aria-selected": boolean;
|
|
43
|
+
"aria-disabled": boolean;
|
|
44
|
+
}>;
|
|
45
|
+
button: import('vue').ComputedRef<(button: {
|
|
46
|
+
date: Date;
|
|
47
|
+
}) => {
|
|
48
|
+
"aria-label": string;
|
|
49
|
+
"data-date": string;
|
|
50
|
+
} | {
|
|
51
|
+
tabindex: string;
|
|
52
|
+
disabled: boolean;
|
|
53
|
+
onClick: (() => void) | undefined;
|
|
54
|
+
"aria-label": string;
|
|
55
|
+
"data-date": string;
|
|
56
|
+
}>;
|
|
57
|
+
}, {
|
|
58
|
+
weekdayNames: import('vue').ComputedRef<string[]>;
|
|
59
|
+
weeksToRender: import('vue').ComputedRef<RenderWeek[]>;
|
|
60
|
+
focusedDate: Ref<Date, Date>;
|
|
61
|
+
viewMonth: import('vue').WritableComputedRef<Date, Date>;
|
|
62
|
+
}, {
|
|
63
|
+
goToMonthByOffset: (offset: number) => void;
|
|
64
|
+
goToToday: () => void;
|
|
65
|
+
isSelected: import('vue').ComputedRef<(date: Date) => boolean>;
|
|
66
|
+
isToday: (date: Date) => boolean;
|
|
67
|
+
getRangeType: import('vue').ComputedRef<(date: Date, range?: DateRange) => "start" | "middle" | "end" | undefined>;
|
|
68
|
+
isDisabled: import('vue').ComputedRef<(date: Date) => boolean>;
|
|
69
|
+
goToDate: (date: Date, preventSelectionUpdate?: boolean) => void;
|
|
70
|
+
isFocused: import('vue').ComputedRef<(date: Date) => boolean>;
|
|
71
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -132,18 +132,18 @@ declare const _default: import('vue').DefineComponent<{}, {
|
|
|
132
132
|
onBlur?: ((payload: FocusEvent) => void) | undefined;
|
|
133
133
|
onChange?: ((payload: Event) => void) | undefined;
|
|
134
134
|
onBeforeinput?: ((payload: InputEvent) => void) | undefined;
|
|
135
|
-
|
|
135
|
+
onFormdata?: ((payload: FormDataEvent) => void) | undefined;
|
|
136
|
+
onInput?: ((payload: InputEvent) => void) | undefined;
|
|
136
137
|
onReset?: ((payload: Event) => void) | undefined;
|
|
137
138
|
onSubmit?: ((payload: SubmitEvent) => void) | undefined;
|
|
138
139
|
onInvalid?: ((payload: Event) => void) | undefined;
|
|
140
|
+
onFullscreenchange?: ((payload: Event) => void) | undefined;
|
|
141
|
+
onFullscreenerror?: ((payload: Event) => void) | undefined;
|
|
139
142
|
onLoad?: ((payload: Event) => void) | undefined;
|
|
140
143
|
onError?: ((payload: Event) => void) | undefined;
|
|
141
144
|
onKeydown?: ((payload: KeyboardEvent) => void) | undefined;
|
|
142
145
|
onKeypress?: ((payload: KeyboardEvent) => void) | undefined;
|
|
143
146
|
onKeyup?: ((payload: KeyboardEvent) => void) | undefined;
|
|
144
|
-
onAuxclick?: ((payload: PointerEvent) => void) | undefined;
|
|
145
|
-
onClick?: ((payload: PointerEvent) => void) | undefined;
|
|
146
|
-
onContextmenu?: ((payload: PointerEvent) => void) | undefined;
|
|
147
147
|
onDblclick?: ((payload: MouseEvent) => void) | undefined;
|
|
148
148
|
onMouseenter?: ((payload: MouseEvent) => void) | undefined;
|
|
149
149
|
onMouseleave?: ((payload: MouseEvent) => void) | undefined;
|
|
@@ -180,6 +180,11 @@ declare const _default: import('vue').DefineComponent<{}, {
|
|
|
180
180
|
onTouchend?: ((payload: TouchEvent) => void) | undefined;
|
|
181
181
|
onTouchmove?: ((payload: TouchEvent) => void) | undefined;
|
|
182
182
|
onTouchstart?: ((payload: TouchEvent) => void) | undefined;
|
|
183
|
+
onAuxclick?: ((payload: PointerEvent) => void) | undefined;
|
|
184
|
+
onClick?: ((payload: PointerEvent) => void) | undefined;
|
|
185
|
+
onContextmenu?: ((payload: PointerEvent) => void) | undefined;
|
|
186
|
+
onGotpointercapture?: ((payload: PointerEvent) => void) | undefined;
|
|
187
|
+
onLostpointercapture?: ((payload: PointerEvent) => void) | undefined;
|
|
183
188
|
onPointerdown?: ((payload: PointerEvent) => void) | undefined;
|
|
184
189
|
onPointermove?: ((payload: PointerEvent) => void) | undefined;
|
|
185
190
|
onPointerup?: ((payload: PointerEvent) => void) | undefined;
|
|
@@ -188,11 +193,17 @@ declare const _default: import('vue').DefineComponent<{}, {
|
|
|
188
193
|
onPointerleave?: ((payload: PointerEvent) => void) | undefined;
|
|
189
194
|
onPointerover?: ((payload: PointerEvent) => void) | undefined;
|
|
190
195
|
onPointerout?: ((payload: PointerEvent) => void) | undefined;
|
|
196
|
+
onBeforetoggle?: ((payload: ToggleEvent) => void) | undefined;
|
|
197
|
+
onToggle?: ((payload: ToggleEvent) => void) | undefined;
|
|
191
198
|
onWheel?: ((payload: WheelEvent) => void) | undefined;
|
|
199
|
+
onAnimationcancel?: ((payload: AnimationEvent) => void) | undefined;
|
|
192
200
|
onAnimationstart?: ((payload: AnimationEvent) => void) | undefined;
|
|
193
201
|
onAnimationend?: ((payload: AnimationEvent) => void) | undefined;
|
|
194
202
|
onAnimationiteration?: ((payload: AnimationEvent) => void) | undefined;
|
|
203
|
+
onSecuritypolicyviolation?: ((payload: SecurityPolicyViolationEvent) => void) | undefined;
|
|
204
|
+
onTransitioncancel?: ((payload: TransitionEvent) => void) | undefined;
|
|
195
205
|
onTransitionend?: ((payload: TransitionEvent) => void) | undefined;
|
|
206
|
+
onTransitionrun?: ((payload: TransitionEvent) => void) | undefined;
|
|
196
207
|
onTransitionstart?: ((payload: TransitionEvent) => void) | undefined;
|
|
197
208
|
ref?: import('vue').Ref<Element | ({
|
|
198
209
|
$: import('vue').ComponentInternalInstance;
|
|
@@ -132,18 +132,18 @@ declare const _default: import('vue').DefineComponent<{}, {
|
|
|
132
132
|
onBlur?: ((payload: FocusEvent) => void) | undefined;
|
|
133
133
|
onChange?: ((payload: Event) => void) | undefined;
|
|
134
134
|
onBeforeinput?: ((payload: InputEvent) => void) | undefined;
|
|
135
|
-
|
|
135
|
+
onFormdata?: ((payload: FormDataEvent) => void) | undefined;
|
|
136
|
+
onInput?: ((payload: InputEvent) => void) | undefined;
|
|
136
137
|
onReset?: ((payload: Event) => void) | undefined;
|
|
137
138
|
onSubmit?: ((payload: SubmitEvent) => void) | undefined;
|
|
138
139
|
onInvalid?: ((payload: Event) => void) | undefined;
|
|
140
|
+
onFullscreenchange?: ((payload: Event) => void) | undefined;
|
|
141
|
+
onFullscreenerror?: ((payload: Event) => void) | undefined;
|
|
139
142
|
onLoad?: ((payload: Event) => void) | undefined;
|
|
140
143
|
onError?: ((payload: Event) => void) | undefined;
|
|
141
144
|
onKeydown?: ((payload: KeyboardEvent) => void) | undefined;
|
|
142
145
|
onKeypress?: ((payload: KeyboardEvent) => void) | undefined;
|
|
143
146
|
onKeyup?: ((payload: KeyboardEvent) => void) | undefined;
|
|
144
|
-
onAuxclick?: ((payload: PointerEvent) => void) | undefined;
|
|
145
|
-
onClick?: ((payload: PointerEvent) => void) | undefined;
|
|
146
|
-
onContextmenu?: ((payload: PointerEvent) => void) | undefined;
|
|
147
147
|
onDblclick?: ((payload: MouseEvent) => void) | undefined;
|
|
148
148
|
onMouseenter?: ((payload: MouseEvent) => void) | undefined;
|
|
149
149
|
onMouseleave?: ((payload: MouseEvent) => void) | undefined;
|
|
@@ -180,6 +180,11 @@ declare const _default: import('vue').DefineComponent<{}, {
|
|
|
180
180
|
onTouchend?: ((payload: TouchEvent) => void) | undefined;
|
|
181
181
|
onTouchmove?: ((payload: TouchEvent) => void) | undefined;
|
|
182
182
|
onTouchstart?: ((payload: TouchEvent) => void) | undefined;
|
|
183
|
+
onAuxclick?: ((payload: PointerEvent) => void) | undefined;
|
|
184
|
+
onClick?: ((payload: PointerEvent) => void) | undefined;
|
|
185
|
+
onContextmenu?: ((payload: PointerEvent) => void) | undefined;
|
|
186
|
+
onGotpointercapture?: ((payload: PointerEvent) => void) | undefined;
|
|
187
|
+
onLostpointercapture?: ((payload: PointerEvent) => void) | undefined;
|
|
183
188
|
onPointerdown?: ((payload: PointerEvent) => void) | undefined;
|
|
184
189
|
onPointermove?: ((payload: PointerEvent) => void) | undefined;
|
|
185
190
|
onPointerup?: ((payload: PointerEvent) => void) | undefined;
|
|
@@ -188,11 +193,17 @@ declare const _default: import('vue').DefineComponent<{}, {
|
|
|
188
193
|
onPointerleave?: ((payload: PointerEvent) => void) | undefined;
|
|
189
194
|
onPointerover?: ((payload: PointerEvent) => void) | undefined;
|
|
190
195
|
onPointerout?: ((payload: PointerEvent) => void) | undefined;
|
|
196
|
+
onBeforetoggle?: ((payload: ToggleEvent) => void) | undefined;
|
|
197
|
+
onToggle?: ((payload: ToggleEvent) => void) | undefined;
|
|
191
198
|
onWheel?: ((payload: WheelEvent) => void) | undefined;
|
|
199
|
+
onAnimationcancel?: ((payload: AnimationEvent) => void) | undefined;
|
|
192
200
|
onAnimationstart?: ((payload: AnimationEvent) => void) | undefined;
|
|
193
201
|
onAnimationend?: ((payload: AnimationEvent) => void) | undefined;
|
|
194
202
|
onAnimationiteration?: ((payload: AnimationEvent) => void) | undefined;
|
|
203
|
+
onSecuritypolicyviolation?: ((payload: SecurityPolicyViolationEvent) => void) | undefined;
|
|
204
|
+
onTransitioncancel?: ((payload: TransitionEvent) => void) | undefined;
|
|
195
205
|
onTransitionend?: ((payload: TransitionEvent) => void) | undefined;
|
|
206
|
+
onTransitionrun?: ((payload: TransitionEvent) => void) | undefined;
|
|
196
207
|
onTransitionstart?: ((payload: TransitionEvent) => void) | undefined;
|
|
197
208
|
ref?: import('vue').Ref<Element | ({
|
|
198
209
|
$: import('vue').ComponentInternalInstance;
|
|
@@ -200,18 +200,18 @@ export declare const createComboBox: <TValue extends ListboxValue, TAutoComplete
|
|
|
200
200
|
onBlur?: ((payload: FocusEvent) => void) | undefined;
|
|
201
201
|
onChange?: ((payload: Event) => void) | undefined;
|
|
202
202
|
onBeforeinput?: ((payload: InputEvent) => void) | undefined;
|
|
203
|
-
|
|
203
|
+
onFormdata?: ((payload: FormDataEvent) => void) | undefined;
|
|
204
|
+
onInput?: ((payload: InputEvent) => void) | undefined;
|
|
204
205
|
onReset?: ((payload: Event) => void) | undefined;
|
|
205
206
|
onSubmit?: ((payload: SubmitEvent) => void) | undefined;
|
|
206
207
|
onInvalid?: ((payload: Event) => void) | undefined;
|
|
208
|
+
onFullscreenchange?: ((payload: Event) => void) | undefined;
|
|
209
|
+
onFullscreenerror?: ((payload: Event) => void) | undefined;
|
|
207
210
|
onLoad?: ((payload: Event) => void) | undefined;
|
|
208
211
|
onError?: ((payload: Event) => void) | undefined;
|
|
209
212
|
onKeydown?: ((payload: KeyboardEvent) => void) | undefined;
|
|
210
213
|
onKeypress?: ((payload: KeyboardEvent) => void) | undefined;
|
|
211
214
|
onKeyup?: ((payload: KeyboardEvent) => void) | undefined;
|
|
212
|
-
onAuxclick?: ((payload: PointerEvent) => void) | undefined;
|
|
213
|
-
onClick?: ((payload: PointerEvent) => void) | undefined;
|
|
214
|
-
onContextmenu?: ((payload: PointerEvent) => void) | undefined;
|
|
215
215
|
onDblclick?: ((payload: MouseEvent) => void) | undefined;
|
|
216
216
|
onMouseenter?: ((payload: MouseEvent) => void) | undefined;
|
|
217
217
|
onMouseleave?: ((payload: MouseEvent) => void) | undefined;
|
|
@@ -248,6 +248,11 @@ export declare const createComboBox: <TValue extends ListboxValue, TAutoComplete
|
|
|
248
248
|
onTouchend?: ((payload: TouchEvent) => void) | undefined;
|
|
249
249
|
onTouchmove?: ((payload: TouchEvent) => void) | undefined;
|
|
250
250
|
onTouchstart?: ((payload: TouchEvent) => void) | undefined;
|
|
251
|
+
onAuxclick?: ((payload: PointerEvent) => void) | undefined;
|
|
252
|
+
onClick?: ((payload: PointerEvent) => void) | undefined;
|
|
253
|
+
onContextmenu?: ((payload: PointerEvent) => void) | undefined;
|
|
254
|
+
onGotpointercapture?: ((payload: PointerEvent) => void) | undefined;
|
|
255
|
+
onLostpointercapture?: ((payload: PointerEvent) => void) | undefined;
|
|
251
256
|
onPointerdown?: ((payload: PointerEvent) => void) | undefined;
|
|
252
257
|
onPointermove?: ((payload: PointerEvent) => void) | undefined;
|
|
253
258
|
onPointerup?: ((payload: PointerEvent) => void) | undefined;
|
|
@@ -256,11 +261,17 @@ export declare const createComboBox: <TValue extends ListboxValue, TAutoComplete
|
|
|
256
261
|
onPointerleave?: ((payload: PointerEvent) => void) | undefined;
|
|
257
262
|
onPointerover?: ((payload: PointerEvent) => void) | undefined;
|
|
258
263
|
onPointerout?: ((payload: PointerEvent) => void) | undefined;
|
|
264
|
+
onBeforetoggle?: ((payload: ToggleEvent) => void) | undefined;
|
|
265
|
+
onToggle?: ((payload: ToggleEvent) => void) | undefined;
|
|
259
266
|
onWheel?: ((payload: WheelEvent) => void) | undefined;
|
|
267
|
+
onAnimationcancel?: ((payload: AnimationEvent) => void) | undefined;
|
|
260
268
|
onAnimationstart?: ((payload: AnimationEvent) => void) | undefined;
|
|
261
269
|
onAnimationend?: ((payload: AnimationEvent) => void) | undefined;
|
|
262
270
|
onAnimationiteration?: ((payload: AnimationEvent) => void) | undefined;
|
|
271
|
+
onSecuritypolicyviolation?: ((payload: SecurityPolicyViolationEvent) => void) | undefined;
|
|
272
|
+
onTransitioncancel?: ((payload: TransitionEvent) => void) | undefined;
|
|
263
273
|
onTransitionend?: ((payload: TransitionEvent) => void) | undefined;
|
|
274
|
+
onTransitionrun?: ((payload: TransitionEvent) => void) | undefined;
|
|
264
275
|
onTransitionstart?: ((payload: TransitionEvent) => void) | undefined;
|
|
265
276
|
ref?: Ref<Element | ({
|
|
266
277
|
$: import('vue').ComponentInternalInstance;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { shallowRef, computed,
|
|
1
|
+
import { shallowRef, computed, toValue, ref, watch, nextTick, reactive, onBeforeMount, watchEffect, onBeforeUnmount, unref, useId, toRef } from "vue";
|
|
2
2
|
const createBuilder = (builder) => builder;
|
|
3
3
|
function createElRef() {
|
|
4
4
|
const elementRef = shallowRef();
|
|
@@ -9,6 +9,303 @@ function createElRef() {
|
|
|
9
9
|
get: () => elementRef.value
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
|
+
function getISOWeekNumber(date) {
|
|
13
|
+
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
|
14
|
+
const dayNum = d.getUTCDay() || 7;
|
|
15
|
+
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
|
16
|
+
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
|
17
|
+
const weekNo = Math.ceil(((d.getTime() - yearStart.getTime()) / 864e5 + 1) / 7);
|
|
18
|
+
return weekNo;
|
|
19
|
+
}
|
|
20
|
+
function isInDateRange(date, start, end) {
|
|
21
|
+
start = new Date(start);
|
|
22
|
+
start.setHours(0, 0, 0, 0);
|
|
23
|
+
end = new Date(end);
|
|
24
|
+
end.setHours(23, 59, 59, 999);
|
|
25
|
+
const time = date.getTime();
|
|
26
|
+
return time >= start.getTime() && time <= end.getTime();
|
|
27
|
+
}
|
|
28
|
+
function getNormalizedDayIndex(date, weekStartDay) {
|
|
29
|
+
const day = date.getDay();
|
|
30
|
+
const start = WEEKDAYS.indexOf(weekStartDay);
|
|
31
|
+
const normalizedDay = day === 0 ? 6 : day - 1;
|
|
32
|
+
return (normalizedDay - start + 7) % 7;
|
|
33
|
+
}
|
|
34
|
+
const WEEKDAYS = [
|
|
35
|
+
"Monday",
|
|
36
|
+
"Tuesday",
|
|
37
|
+
"Wednesday",
|
|
38
|
+
"Thursday",
|
|
39
|
+
"Friday",
|
|
40
|
+
"Saturday",
|
|
41
|
+
"Sunday"
|
|
42
|
+
];
|
|
43
|
+
function sortDateRange(range) {
|
|
44
|
+
const start = new Date(range.start);
|
|
45
|
+
const end = range.end ? new Date(range.end) : void 0;
|
|
46
|
+
if (end && end.getTime() < start.getTime()) {
|
|
47
|
+
return { start: end, end: start };
|
|
48
|
+
}
|
|
49
|
+
return { start, end };
|
|
50
|
+
}
|
|
51
|
+
const _unstableCreateCalendar = createBuilder((options) => {
|
|
52
|
+
const viewMonth = computed({
|
|
53
|
+
get: () => {
|
|
54
|
+
const date = toValue(options.viewMonth);
|
|
55
|
+
return date ? new Date(date) : /* @__PURE__ */ new Date();
|
|
56
|
+
},
|
|
57
|
+
set: (newValue) => options.onUpdateViewMonth?.(new Date(newValue))
|
|
58
|
+
});
|
|
59
|
+
const weekdayNames = computed(() => {
|
|
60
|
+
const formatter = new Intl.DateTimeFormat(toValue(options.locale), {
|
|
61
|
+
weekday: toValue(options.calendarSize) === "big" ? "long" : "short"
|
|
62
|
+
});
|
|
63
|
+
const names = Array.from({ length: 7 }, (_, i) => new Date(2024, 0, 1 + i)).map(
|
|
64
|
+
(day) => formatter.format(day)
|
|
65
|
+
);
|
|
66
|
+
const weekStartDay = toValue(options.weekStartDay);
|
|
67
|
+
const index = WEEKDAYS.indexOf(weekStartDay);
|
|
68
|
+
return names.slice(index).concat(names.slice(0, index));
|
|
69
|
+
});
|
|
70
|
+
const focusedDate = ref(/* @__PURE__ */ new Date());
|
|
71
|
+
watch(
|
|
72
|
+
() => toValue(options.modelValue),
|
|
73
|
+
(newValue) => {
|
|
74
|
+
if (!newValue) return;
|
|
75
|
+
let newFocusDate;
|
|
76
|
+
if (Array.isArray(newValue)) {
|
|
77
|
+
newFocusDate = newValue.length ? new Date(newValue[0]) : void 0;
|
|
78
|
+
} else if (typeof newValue === "object" && !(newValue instanceof Date)) {
|
|
79
|
+
newFocusDate = new Date(newValue.start);
|
|
80
|
+
} else {
|
|
81
|
+
newFocusDate = new Date(newValue);
|
|
82
|
+
}
|
|
83
|
+
if (newFocusDate) focusedDate.value = newFocusDate;
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
const isToday = (date) => {
|
|
87
|
+
return date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
|
|
88
|
+
};
|
|
89
|
+
const isSelected = computed(() => {
|
|
90
|
+
return (date) => {
|
|
91
|
+
const value = toValue(options.modelValue);
|
|
92
|
+
if (!value) return false;
|
|
93
|
+
if (Array.isArray(value)) {
|
|
94
|
+
const values = value.map((i) => new Date(i));
|
|
95
|
+
return values.some((d) => d.toDateString() === date.toDateString());
|
|
96
|
+
}
|
|
97
|
+
if (typeof value === "object" && !(value instanceof Date)) {
|
|
98
|
+
const start = new Date(value.start);
|
|
99
|
+
const end = value.end ? new Date(value.end) : void 0;
|
|
100
|
+
return start.toDateString() === date.toDateString() || end?.toDateString() === date.toDateString();
|
|
101
|
+
}
|
|
102
|
+
return new Date(value).toDateString() === date.toDateString();
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
const isFocused = computed(() => {
|
|
106
|
+
return (date) => {
|
|
107
|
+
return focusedDate.value?.toDateString() === date.toDateString();
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
const isDisabled = computed(() => {
|
|
111
|
+
return (date) => {
|
|
112
|
+
if (toValue(options.disabled)) return true;
|
|
113
|
+
const min = toValue(options.min);
|
|
114
|
+
const minDate = min ? new Date(min) : void 0;
|
|
115
|
+
minDate?.setHours(0, 0, 0, 0);
|
|
116
|
+
const max = toValue(options.max);
|
|
117
|
+
const maxDate = max ? new Date(max) : void 0;
|
|
118
|
+
maxDate?.setHours(23, 59, 59, 999);
|
|
119
|
+
if (minDate && maxDate) return !isInDateRange(date, minDate, maxDate);
|
|
120
|
+
if (minDate) return date.getTime() < minDate.getTime();
|
|
121
|
+
if (maxDate) return date.getTime() > maxDate.getTime();
|
|
122
|
+
return false;
|
|
123
|
+
};
|
|
124
|
+
});
|
|
125
|
+
const weeksToRender = computed(() => {
|
|
126
|
+
const weekStartDay = toValue(options.weekStartDay);
|
|
127
|
+
const firstDayInViewMonth = new Date(
|
|
128
|
+
viewMonth.value.getFullYear(),
|
|
129
|
+
viewMonth.value.getMonth(),
|
|
130
|
+
1
|
|
131
|
+
);
|
|
132
|
+
const startOffset = (firstDayInViewMonth.getDay() + 6) % 7;
|
|
133
|
+
const daysBeforeStart = (startOffset - WEEKDAYS.indexOf(weekStartDay) + 7) % 7;
|
|
134
|
+
const weeksToRender2 = 6;
|
|
135
|
+
const weeks = [];
|
|
136
|
+
for (let weekIndex = 0; weekIndex < weeksToRender2; weekIndex++) {
|
|
137
|
+
const weekStartDate = new Date(firstDayInViewMonth);
|
|
138
|
+
weekStartDate.setDate(weekStartDate.getDate() - daysBeforeStart + weekIndex * 7);
|
|
139
|
+
const days = Array.from({ length: 7 }, (_, dayIndex) => {
|
|
140
|
+
const date = new Date(weekStartDate);
|
|
141
|
+
date.setDate(date.getDate() + dayIndex);
|
|
142
|
+
return {
|
|
143
|
+
date,
|
|
144
|
+
isCurrentMonth: date.getMonth() === viewMonth.value.getMonth()
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
weeks.push({
|
|
148
|
+
weekNumber: getISOWeekNumber(weekStartDate),
|
|
149
|
+
days
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return weeks;
|
|
153
|
+
});
|
|
154
|
+
const goToDate = (date, preventSelectionUpdate) => {
|
|
155
|
+
focusedDate.value = new Date(date);
|
|
156
|
+
if (focusedDate.value.getFullYear() !== viewMonth.value.getFullYear() || focusedDate.value.getMonth() !== viewMonth.value.getMonth()) {
|
|
157
|
+
viewMonth.value = new Date(focusedDate.value);
|
|
158
|
+
}
|
|
159
|
+
const selectionMode = toValue(options.selectionMode);
|
|
160
|
+
if (!selectionMode || preventSelectionUpdate) return;
|
|
161
|
+
const selection = toValue(options.modelValue);
|
|
162
|
+
switch (selectionMode) {
|
|
163
|
+
case "single":
|
|
164
|
+
options.onUpdateModelValue?.(new Date(date));
|
|
165
|
+
break;
|
|
166
|
+
case "multiple": {
|
|
167
|
+
let values = Array.isArray(selection) ? selection.map((d) => new Date(d)) : [];
|
|
168
|
+
if (isSelected.value(date)) {
|
|
169
|
+
values = values.filter((d) => d.toDateString() !== date.toDateString());
|
|
170
|
+
} else {
|
|
171
|
+
values.push(new Date(date));
|
|
172
|
+
}
|
|
173
|
+
options.onUpdateModelValue?.(values);
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case "range": {
|
|
177
|
+
const currentRange = typeof selection === "object" && !(selection instanceof Date) && !Array.isArray(selection) ? selection : void 0;
|
|
178
|
+
let newRange;
|
|
179
|
+
if (currentRange?.start && currentRange.end) {
|
|
180
|
+
newRange = { start: new Date(date) };
|
|
181
|
+
} else {
|
|
182
|
+
newRange = {
|
|
183
|
+
start: currentRange?.start ? new Date(currentRange.start) : new Date(date),
|
|
184
|
+
end: currentRange?.start ? new Date(date) : void 0
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
newRange = sortDateRange(newRange);
|
|
188
|
+
options.onUpdateModelValue?.(newRange);
|
|
189
|
+
break;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
const handleKeyNavigation = async (event) => {
|
|
194
|
+
let newDate;
|
|
195
|
+
const getNewFocusDateByDiff = (diff, type = "days") => {
|
|
196
|
+
const date = new Date(focusedDate.value);
|
|
197
|
+
if (type === "month") date.setMonth(date.getMonth() + diff);
|
|
198
|
+
else date.setDate(date.getDate() + diff);
|
|
199
|
+
return date;
|
|
200
|
+
};
|
|
201
|
+
switch (event.key) {
|
|
202
|
+
case "ArrowUp":
|
|
203
|
+
newDate = getNewFocusDateByDiff(-7);
|
|
204
|
+
break;
|
|
205
|
+
case "ArrowDown":
|
|
206
|
+
newDate = getNewFocusDateByDiff(7);
|
|
207
|
+
break;
|
|
208
|
+
case "ArrowLeft":
|
|
209
|
+
newDate = getNewFocusDateByDiff(-1);
|
|
210
|
+
break;
|
|
211
|
+
case "ArrowRight":
|
|
212
|
+
newDate = getNewFocusDateByDiff(1);
|
|
213
|
+
break;
|
|
214
|
+
case "Home": {
|
|
215
|
+
const idx = getNormalizedDayIndex(focusedDate.value, toValue(options.weekStartDay));
|
|
216
|
+
newDate = getNewFocusDateByDiff(-idx);
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
case "End": {
|
|
220
|
+
const idx = getNormalizedDayIndex(focusedDate.value, toValue(options.weekStartDay));
|
|
221
|
+
newDate = getNewFocusDateByDiff(6 - idx);
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
case "PageUp":
|
|
225
|
+
newDate = getNewFocusDateByDiff(-(event.shiftKey ? 12 : 1), "month");
|
|
226
|
+
break;
|
|
227
|
+
case "PageDown":
|
|
228
|
+
newDate = getNewFocusDateByDiff(event.shiftKey ? 12 : 1, "month");
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
if (!newDate || isDisabled.value(newDate)) return;
|
|
232
|
+
event.preventDefault();
|
|
233
|
+
goToDate(newDate, true);
|
|
234
|
+
await nextTick();
|
|
235
|
+
tableRef.value?.querySelector(`[data-date="${focusedDate.value.toDateString()}"]`)?.focus();
|
|
236
|
+
};
|
|
237
|
+
const getRangeType = computed(() => {
|
|
238
|
+
return (date, range) => {
|
|
239
|
+
const selection = range ?? toValue(options.modelValue);
|
|
240
|
+
if (!selection || typeof selection !== "object" || Array.isArray(selection) || selection instanceof Date) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const sortedRange = sortDateRange(selection);
|
|
244
|
+
const start = new Date(sortedRange.start);
|
|
245
|
+
start.setHours(0, 0, 0, 0);
|
|
246
|
+
const end = sortedRange.end ? new Date(sortedRange.end) : void 0;
|
|
247
|
+
end?.setHours(23, 59, 59, 999);
|
|
248
|
+
if (date.toDateString() === start.toDateString()) return "start";
|
|
249
|
+
if (date.toDateString() === end?.toDateString()) return "end";
|
|
250
|
+
if (end && isInDateRange(date, start, end)) return "middle";
|
|
251
|
+
};
|
|
252
|
+
});
|
|
253
|
+
const goToMonthByOffset = (offset) => {
|
|
254
|
+
const date = new Date(viewMonth.value);
|
|
255
|
+
date.setMonth(date.getMonth() + offset, 1);
|
|
256
|
+
viewMonth.value = date;
|
|
257
|
+
};
|
|
258
|
+
const goToToday = () => {
|
|
259
|
+
viewMonth.value = /* @__PURE__ */ new Date();
|
|
260
|
+
};
|
|
261
|
+
const tableRef = createElRef();
|
|
262
|
+
return {
|
|
263
|
+
state: {
|
|
264
|
+
weekdayNames,
|
|
265
|
+
weeksToRender,
|
|
266
|
+
focusedDate,
|
|
267
|
+
viewMonth
|
|
268
|
+
},
|
|
269
|
+
elements: {
|
|
270
|
+
table: {
|
|
271
|
+
role: "grid",
|
|
272
|
+
onKeydown: handleKeyNavigation,
|
|
273
|
+
ref: tableRef
|
|
274
|
+
},
|
|
275
|
+
cell: computed(() => (cell) => ({
|
|
276
|
+
role: "gridcell",
|
|
277
|
+
"aria-selected": isSelected.value(cell.date),
|
|
278
|
+
"aria-disabled": isDisabled.value(cell.date)
|
|
279
|
+
})),
|
|
280
|
+
button: computed(() => (button) => {
|
|
281
|
+
const formatter = new Intl.DateTimeFormat(toValue(options.locale), { dateStyle: "full" });
|
|
282
|
+
const attributes = {
|
|
283
|
+
"aria-label": formatter.format(button.date),
|
|
284
|
+
"data-date": button.date.toDateString()
|
|
285
|
+
};
|
|
286
|
+
const selection = toValue(options.selectionMode);
|
|
287
|
+
if (!selection) return attributes;
|
|
288
|
+
const disabled = isDisabled.value(button.date);
|
|
289
|
+
return {
|
|
290
|
+
...attributes,
|
|
291
|
+
tabindex: isFocused.value(button.date) && !disabled ? "0" : "-1",
|
|
292
|
+
disabled,
|
|
293
|
+
onClick: disabled ? void 0 : () => goToDate(button.date)
|
|
294
|
+
};
|
|
295
|
+
})
|
|
296
|
+
},
|
|
297
|
+
internals: {
|
|
298
|
+
goToMonthByOffset,
|
|
299
|
+
goToToday,
|
|
300
|
+
isSelected,
|
|
301
|
+
isToday,
|
|
302
|
+
getRangeType,
|
|
303
|
+
isDisabled,
|
|
304
|
+
goToDate,
|
|
305
|
+
isFocused
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
});
|
|
12
309
|
const isSubsetMatching = (subset, target) => Object.entries(subset).every(
|
|
13
310
|
([key, value]) => target[key] === value
|
|
14
311
|
);
|
|
@@ -762,6 +1059,7 @@ const createTooltip = createBuilder(({ debounce: debounce2, isVisible }) => {
|
|
|
762
1059
|
export {
|
|
763
1060
|
CLOSING_KEYS,
|
|
764
1061
|
OPENING_KEYS,
|
|
1062
|
+
_unstableCreateCalendar,
|
|
765
1063
|
createBuilder,
|
|
766
1064
|
createComboBox,
|
|
767
1065
|
createElRef,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Nullable } from './types.js';
|
|
2
|
+
export declare function getISOWeekNumber(date: Date): number;
|
|
3
|
+
/**
|
|
4
|
+
* Checks whether the given date is in between the given start and end date.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isInDateRange(date: Date, start: Date, end: Date): boolean;
|
|
7
|
+
export declare function getNormalizedDayIndex(date: Date, weekStartDay: Weekday): number;
|
|
8
|
+
export declare const WEEKDAYS: readonly ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
9
|
+
export type Weekday = (typeof WEEKDAYS)[number];
|
|
10
|
+
export type DateValue = Date | string | number;
|
|
11
|
+
export type DateRange<T extends DateValue = DateValue> = {
|
|
12
|
+
start: T;
|
|
13
|
+
end?: Nullable<T>;
|
|
14
|
+
};
|
|
15
|
+
export declare function sortDateRange(range: DateRange): DateRange<Date>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sit-onyx/headless",
|
|
3
3
|
"description": "Headless composables for Vue",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.2.0-dev-20251014161744",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Schwarz IT KG",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"url": "https://github.com/SchwarzIT/onyx/issues"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
|
-
"@playwright/experimental-ct-vue": "1.
|
|
36
|
-
"@playwright/test": "1.
|
|
35
|
+
"@playwright/experimental-ct-vue": "1.56.0",
|
|
36
|
+
"@playwright/test": "1.56.0",
|
|
37
37
|
"typescript": ">= 5",
|
|
38
38
|
"vue": ">= 3.5.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@vue/compiler-dom": "3.5.
|
|
42
|
-
"vue": "3.5.
|
|
41
|
+
"@vue/compiler-dom": "3.5.22",
|
|
42
|
+
"vue": "3.5.22",
|
|
43
43
|
"@sit-onyx/shared": "^0.1.0"
|
|
44
44
|
},
|
|
45
45
|
"scripts": {
|