@codeandfunction/callaloo 4.7.6 → 4.8.0
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/callaloo.global.js +1 -1
- package/dist/chunks/CLModal.vue_vue_type_style_index_0_lang-BDyONfaQ.js +176 -0
- package/dist/chunks/_plugin-vue_export-helper-CHgC5LLL.js +9 -0
- package/dist/components/Containers/CLCarousel/CLCarousel.js +144 -148
- package/dist/components/Modals/CLModal/CLModal.js +3 -174
- package/dist/components/Modals/CLModalDatePicker/CLModalDatePicker.css +1 -0
- package/dist/components/Modals/CLModalDatePicker/CLModalDatePicker.js +267 -0
- package/dist/components/Modals/CLModalDatePicker/CLModalDatePicker.vue.d.ts +77 -0
- package/dist/components/Modals/CLModalDatePicker/index.d.ts +4 -0
- package/dist/components/Modals/index.d.ts +2 -1
- package/dist/components/Popups/CLDropdownMenu/CLDropdownMenu.js +438 -425
- package/dist/components/Popups/CLDropdownMenu/CLDropdownMenu.vue.d.ts +9 -2
- package/dist/composables/useDatePicker.d.ts +39 -0
- package/dist/composables/useDatePicker.js +136 -0
- package/dist/composables/useDatePicker.spec.js +232 -0
- package/dist/composables/useDropdown.d.ts +1 -1
- package/dist/composables/useDropdown.js +16 -16
- package/package.json +5 -1
|
@@ -4,8 +4,12 @@ export interface CLDropdownMenuProps {
|
|
|
4
4
|
buttonAriaLabel: string;
|
|
5
5
|
/** Set the border radius size on the anchor button. The property can be one of `CLBorderRadius`, e.g. `CLBorderRadius.Medium`. */
|
|
6
6
|
buttonBorderRadius?: CLBorderRadius;
|
|
7
|
+
/** A `boolean` value which dictates the busy state of the button */
|
|
8
|
+
buttonBusy?: boolean;
|
|
7
9
|
/** Sets the color of the anchor button. The property can be one of `CLColors`, e.g. `CLColors.Primary`. */
|
|
8
10
|
buttonColor?: CLColors;
|
|
11
|
+
/** Sets the disabled state of the anchor button. */
|
|
12
|
+
buttonDisabled?: boolean;
|
|
9
13
|
/** Sets the height of the anchor button, its default value is `auto`. */
|
|
10
14
|
buttonHeight?: string;
|
|
11
15
|
/** Sets the anchor button size. The property can be one of `CLSizes`, e.g. `CLSizes.Medium`. */
|
|
@@ -47,16 +51,19 @@ export interface CLDropdownMenuProps {
|
|
|
47
51
|
/** Sets the z-index of the content container. */
|
|
48
52
|
zIndex?: number | string;
|
|
49
53
|
}
|
|
50
|
-
declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<CLDropdownMenuProps, {
|
|
54
|
+
declare const _default: __VLS_WithTemplateSlots<import('vue').DefineComponent<CLDropdownMenuProps, {
|
|
55
|
+
close: () => void;
|
|
56
|
+
open: () => void;
|
|
57
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<CLDropdownMenuProps> & Readonly<{}>, {
|
|
51
58
|
testId: string;
|
|
52
59
|
iconAfter: CLIconNames;
|
|
53
60
|
iconSize: CLIconSizes;
|
|
54
61
|
isOpen: boolean;
|
|
55
62
|
zIndex: number | string;
|
|
56
63
|
buttonColor: CLColors;
|
|
57
|
-
buttonHeight: string;
|
|
58
64
|
buttonSize: CLSizes;
|
|
59
65
|
buttonVariant: CLColorVariants;
|
|
66
|
+
buttonHeight: string;
|
|
60
67
|
buttonWidth: string;
|
|
61
68
|
containerBordered: boolean;
|
|
62
69
|
containerElevated: boolean;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ComputedRef, Ref } from 'vue';
|
|
2
|
+
export type ISODate = string;
|
|
3
|
+
export interface CalendarCell {
|
|
4
|
+
date: ISODate | null;
|
|
5
|
+
day: number | null;
|
|
6
|
+
isOutsideMonth: boolean;
|
|
7
|
+
}
|
|
8
|
+
interface Input {
|
|
9
|
+
appliedEnd?: Ref<ISODate | null>;
|
|
10
|
+
appliedStart?: Ref<ISODate | null>;
|
|
11
|
+
}
|
|
12
|
+
interface Return {
|
|
13
|
+
calendarGrid: ComputedRef<CalendarCell[]>;
|
|
14
|
+
cancelDraft: () => void;
|
|
15
|
+
clearDraft: () => void;
|
|
16
|
+
currentDate: Ref<Date>;
|
|
17
|
+
currentMonthLabel: ComputedRef<string>;
|
|
18
|
+
draftEnd: Ref<ISODate | null>;
|
|
19
|
+
draftStart: Ref<ISODate | null>;
|
|
20
|
+
formatDateToISO: (date: Date) => ISODate;
|
|
21
|
+
formatHumanDate: (iso: ISODate) => string;
|
|
22
|
+
formatLongDate: (iso: ISODate) => string;
|
|
23
|
+
formatShortNoYear: (iso: ISODate) => string;
|
|
24
|
+
formatShortWithYear: (iso: ISODate) => string;
|
|
25
|
+
getDayAriaLabel: (iso: ISODate) => string;
|
|
26
|
+
handleNextMonth: () => void;
|
|
27
|
+
handlePrevMonth: () => void;
|
|
28
|
+
initializeDraft: () => void;
|
|
29
|
+
isDraftEnd: (iso: ISODate) => boolean;
|
|
30
|
+
isDraftStart: (iso: ISODate) => boolean;
|
|
31
|
+
isInDraftRange: (iso: ISODate) => boolean;
|
|
32
|
+
isoToLocalDate: (iso: ISODate) => Date;
|
|
33
|
+
onDayClick: (iso: ISODate | null) => void;
|
|
34
|
+
rangeLabel: ComputedRef<string | undefined>;
|
|
35
|
+
setCalendarMonthToAppliedOrToday: () => void;
|
|
36
|
+
weekDays: string[];
|
|
37
|
+
}
|
|
38
|
+
export declare const useDatePicker: ({ appliedEnd, appliedStart }?: Input) => Return;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import '../assets/core.css';
|
|
2
|
+
import { i as M } from "../chunks/helper-qUkciePY.js";
|
|
3
|
+
import { ref as $, computed as w } from "vue";
|
|
4
|
+
const j = ({
|
|
5
|
+
appliedEnd: v,
|
|
6
|
+
appliedStart: s
|
|
7
|
+
} = {}) => {
|
|
8
|
+
const a = $(/* @__PURE__ */ new Date()), r = $(null), n = $(null), T = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], i = (t) => {
|
|
9
|
+
const e = t.getFullYear(), l = String(t.getMonth() + 1).padStart(2, "0"), o = String(t.getDate()).padStart(2, "0");
|
|
10
|
+
return `${e}-${l}-${o}`;
|
|
11
|
+
}, c = (t) => /* @__PURE__ */ new Date(`${t}T00:00:00`), k = (t) => M ? c(t).toLocaleDateString("default", {
|
|
12
|
+
day: "numeric",
|
|
13
|
+
month: "short",
|
|
14
|
+
year: "numeric"
|
|
15
|
+
}) : t, f = (t) => M ? c(t).toLocaleDateString("default", {
|
|
16
|
+
day: "numeric",
|
|
17
|
+
month: "long",
|
|
18
|
+
weekday: "long",
|
|
19
|
+
year: "numeric"
|
|
20
|
+
}) : t, d = (t) => {
|
|
21
|
+
const e = c(t), l = e.getMonth() + 1, o = String(e.getDate());
|
|
22
|
+
return `${l}/${o}`;
|
|
23
|
+
}, h = (t) => {
|
|
24
|
+
const e = c(t), l = e.getMonth() + 1, o = String(e.getDate()), y = String(e.getFullYear()).slice(-2);
|
|
25
|
+
return `${l}/${o}/${y}`;
|
|
26
|
+
}, Y = () => {
|
|
27
|
+
const t = s?.value ? c(s.value) : /* @__PURE__ */ new Date();
|
|
28
|
+
a.value = new Date(
|
|
29
|
+
t.getFullYear(),
|
|
30
|
+
t.getMonth(),
|
|
31
|
+
1
|
|
32
|
+
);
|
|
33
|
+
}, b = () => {
|
|
34
|
+
Y(), n.value = s?.value ?? null, r.value = v?.value ?? null;
|
|
35
|
+
}, I = () => {
|
|
36
|
+
s && (s.value = null), v && (v.value = null), n.value = null, r.value = null;
|
|
37
|
+
}, x = () => {
|
|
38
|
+
n.value = s?.value ?? null, r.value = v?.value ?? null;
|
|
39
|
+
}, P = w(() => {
|
|
40
|
+
if (!M) {
|
|
41
|
+
const t = a.value.getMonth() + 1, e = a.value.getFullYear();
|
|
42
|
+
return `${t}/${e}`;
|
|
43
|
+
}
|
|
44
|
+
return a.value.toLocaleString("default", {
|
|
45
|
+
month: "long",
|
|
46
|
+
year: "numeric"
|
|
47
|
+
});
|
|
48
|
+
}), W = w(() => {
|
|
49
|
+
const t = s?.value ?? null, e = v?.value ?? null;
|
|
50
|
+
if (!t) return;
|
|
51
|
+
if (!e) return h(t);
|
|
52
|
+
const l = c(t).getFullYear(), o = c(e).getFullYear();
|
|
53
|
+
return l !== o ? `${h(t)} - ${h(e)}` : `${d(t)} - ${d(e)}`;
|
|
54
|
+
}), S = (t) => n.value === t, F = (t) => r.value === t, L = (t) => n.value ? r.value ? t >= n.value && t <= r.value : t === n.value : !1, A = (t) => S(t) ? `${f(t)} (start date)` : F(t) ? `${f(t)} (end date)` : L(t) ? `${f(t)} (in range)` : f(t), C = (t) => {
|
|
55
|
+
if (t) {
|
|
56
|
+
if (!n.value || n.value && r.value) {
|
|
57
|
+
n.value = t, r.value = null;
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (t < n.value) {
|
|
61
|
+
r.value = n.value, n.value = t;
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
r.value = t;
|
|
65
|
+
}
|
|
66
|
+
}, G = () => {
|
|
67
|
+
a.value = new Date(
|
|
68
|
+
a.value.getFullYear(),
|
|
69
|
+
a.value.getMonth() - 1,
|
|
70
|
+
1
|
|
71
|
+
);
|
|
72
|
+
}, N = () => {
|
|
73
|
+
a.value = new Date(
|
|
74
|
+
a.value.getFullYear(),
|
|
75
|
+
a.value.getMonth() + 1,
|
|
76
|
+
1
|
|
77
|
+
);
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
calendarGrid: w(() => {
|
|
81
|
+
const t = a.value.getFullYear(), e = a.value.getMonth(), l = new Date(t, e, 1), o = new Date(t, e + 1, 0).getDate(), y = new Date(t, e, 0).getDate(), O = l.getDay(), g = [];
|
|
82
|
+
for (let u = 0; u < O; u++) {
|
|
83
|
+
const D = y - (O - 1 - u), z = i(new Date(t, e - 1, D));
|
|
84
|
+
g.push({
|
|
85
|
+
day: D,
|
|
86
|
+
date: z,
|
|
87
|
+
isOutsideMonth: !0
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
for (let u = 1; u <= o; u++) {
|
|
91
|
+
const D = i(new Date(t, e, u));
|
|
92
|
+
g.push({
|
|
93
|
+
day: u,
|
|
94
|
+
date: D,
|
|
95
|
+
isOutsideMonth: !1
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
let m = 1;
|
|
99
|
+
for (; g.length < 42; ) {
|
|
100
|
+
const u = i(new Date(t, e + 1, m));
|
|
101
|
+
g.push({
|
|
102
|
+
day: m,
|
|
103
|
+
date: u,
|
|
104
|
+
isOutsideMonth: !0
|
|
105
|
+
}), m++;
|
|
106
|
+
}
|
|
107
|
+
return g;
|
|
108
|
+
}),
|
|
109
|
+
cancelDraft: x,
|
|
110
|
+
clearDraft: I,
|
|
111
|
+
currentDate: a,
|
|
112
|
+
currentMonthLabel: P,
|
|
113
|
+
draftEnd: r,
|
|
114
|
+
draftStart: n,
|
|
115
|
+
formatDateToISO: i,
|
|
116
|
+
formatHumanDate: k,
|
|
117
|
+
formatLongDate: f,
|
|
118
|
+
formatShortNoYear: d,
|
|
119
|
+
formatShortWithYear: h,
|
|
120
|
+
getDayAriaLabel: A,
|
|
121
|
+
handleNextMonth: N,
|
|
122
|
+
handlePrevMonth: G,
|
|
123
|
+
initializeDraft: b,
|
|
124
|
+
isDraftEnd: F,
|
|
125
|
+
isDraftStart: S,
|
|
126
|
+
isInDraftRange: L,
|
|
127
|
+
isoToLocalDate: c,
|
|
128
|
+
onDayClick: C,
|
|
129
|
+
rangeLabel: W,
|
|
130
|
+
setCalendarMonthToAppliedOrToday: Y,
|
|
131
|
+
weekDays: T
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
export {
|
|
135
|
+
j as useDatePicker
|
|
136
|
+
};
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import '../assets/core.css';
|
|
2
|
+
import { nextTick as g, defineComponent as B, h as y, ref as D } from "vue";
|
|
3
|
+
import { d as s, b as f, a as m, i as n, m as c, g as e } from "../chunks/vue-test-utils.esm-bundler-BeQTU4qG.js";
|
|
4
|
+
import { useDatePicker as p } from "./useDatePicker.js";
|
|
5
|
+
s("useDatePicker", () => {
|
|
6
|
+
let u, t, l, d;
|
|
7
|
+
const i = (a, o) => B({
|
|
8
|
+
setup() {
|
|
9
|
+
return t = p({
|
|
10
|
+
appliedStart: a,
|
|
11
|
+
appliedEnd: o
|
|
12
|
+
}), () => y("div");
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
f(() => {
|
|
16
|
+
l = D(null), d = D(null);
|
|
17
|
+
}), m(() => {
|
|
18
|
+
u?.unmount();
|
|
19
|
+
}), s("weekDays", () => {
|
|
20
|
+
n("should return correct week day abbreviations", () => {
|
|
21
|
+
u = c(i()), e(t.weekDays).toEqual([
|
|
22
|
+
"Su",
|
|
23
|
+
"Mo",
|
|
24
|
+
"Tu",
|
|
25
|
+
"We",
|
|
26
|
+
"Th",
|
|
27
|
+
"Fr",
|
|
28
|
+
"Sa"
|
|
29
|
+
]);
|
|
30
|
+
});
|
|
31
|
+
}), s("date formatting functions", () => {
|
|
32
|
+
f(() => {
|
|
33
|
+
u = c(i());
|
|
34
|
+
}), s("formatDateToISO", () => {
|
|
35
|
+
n("should convert Date to ISO string (YYYY-MM-DD)", () => {
|
|
36
|
+
const a = new Date(2026, 0, 26), o = t.formatDateToISO(a);
|
|
37
|
+
e(o).toBe("2026-01-26");
|
|
38
|
+
}), n("should pad month and day with zeros", () => {
|
|
39
|
+
const a = new Date(2026, 0, 5), o = t.formatDateToISO(a);
|
|
40
|
+
e(o).toBe("2026-01-05");
|
|
41
|
+
}), n("should handle December correctly", () => {
|
|
42
|
+
const a = new Date(2026, 11, 31), o = t.formatDateToISO(a);
|
|
43
|
+
e(o).toBe("2026-12-31");
|
|
44
|
+
});
|
|
45
|
+
}), s("isoToLocalDate", () => {
|
|
46
|
+
n("should convert ISO string to Date", () => {
|
|
47
|
+
const o = t.isoToLocalDate("2026-01-26");
|
|
48
|
+
e(o).toBeInstanceOf(Date), e(o.getFullYear()).toBe(2026), e(o.getMonth()).toBe(0), e(o.getDate()).toBe(26);
|
|
49
|
+
});
|
|
50
|
+
}), s("formatHumanDate", () => {
|
|
51
|
+
n("should format to human-readable date", () => {
|
|
52
|
+
const o = t.formatHumanDate("2026-01-26");
|
|
53
|
+
e(o).toContain("Jan"), e(o).toContain("26"), e(o).toContain("2026");
|
|
54
|
+
});
|
|
55
|
+
}), s("formatLongDate", () => {
|
|
56
|
+
n("should format to long date with weekday", () => {
|
|
57
|
+
const o = t.formatLongDate("2026-01-26");
|
|
58
|
+
e(o).toContain("January"), e(o).toContain("26"), e(o).toContain("2026");
|
|
59
|
+
});
|
|
60
|
+
}), s("formatShortNoYear", () => {
|
|
61
|
+
n("should format to M/D format", () => {
|
|
62
|
+
const o = t.formatShortNoYear("2026-01-26");
|
|
63
|
+
e(o).toBe("1/26");
|
|
64
|
+
}), n("should handle double-digit months and days", () => {
|
|
65
|
+
const o = t.formatShortNoYear("2026-12-31");
|
|
66
|
+
e(o).toBe("12/31");
|
|
67
|
+
});
|
|
68
|
+
}), s("formatShortWithYear", () => {
|
|
69
|
+
n("should format to M/D/YY format", () => {
|
|
70
|
+
const o = t.formatShortWithYear("2026-01-26");
|
|
71
|
+
e(o).toBe("1/26/26");
|
|
72
|
+
}), n("should handle double-digit months and days", () => {
|
|
73
|
+
const o = t.formatShortWithYear("2026-12-31");
|
|
74
|
+
e(o).toBe("12/31/26");
|
|
75
|
+
}), n("should use last two digits of year", () => {
|
|
76
|
+
const o = t.formatShortWithYear("2025-01-26");
|
|
77
|
+
e(o).toBe("1/26/25");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
}), s("calendar grid generation", () => {
|
|
81
|
+
f(() => {
|
|
82
|
+
u = c(i());
|
|
83
|
+
}), n("should generate correct 42-cell grid (6 weeks × 7 days)", () => {
|
|
84
|
+
const a = t.calendarGrid.value;
|
|
85
|
+
e(a).toHaveLength(42);
|
|
86
|
+
}), n("should correctly mark cells as isOutsideMonth", () => {
|
|
87
|
+
const a = t.calendarGrid.value, o = (/* @__PURE__ */ new Date()).getMonth(), r = (/* @__PURE__ */ new Date()).getFullYear(), h = a.find((v) => !v.isOutsideMonth);
|
|
88
|
+
if (e(h).toBeDefined(), h && h.date) {
|
|
89
|
+
const v = t.isoToLocalDate(h.date);
|
|
90
|
+
e(v.getMonth()).toBe(o), e(v.getFullYear()).toBe(r);
|
|
91
|
+
}
|
|
92
|
+
}), n("should include padding days from previous month", () => {
|
|
93
|
+
const o = t.calendarGrid.value[0];
|
|
94
|
+
o.isOutsideMonth && (e(o.day).toBeGreaterThan(0), e(o.date).toBeTruthy());
|
|
95
|
+
}), n("should include padding days from next month", () => {
|
|
96
|
+
const a = t.calendarGrid.value, o = a[a.length - 1];
|
|
97
|
+
o.isOutsideMonth && (e(o.day).toBeGreaterThan(0), e(o.date).toBeTruthy());
|
|
98
|
+
}), n("should handle month boundaries correctly", () => {
|
|
99
|
+
t.currentDate.value = new Date(2026, 0, 1);
|
|
100
|
+
const o = t.calendarGrid.value.filter(
|
|
101
|
+
(r) => !r.isOutsideMonth && r.date
|
|
102
|
+
);
|
|
103
|
+
e(o.length).toBe(31), o.forEach((r) => {
|
|
104
|
+
r.date && e(r.date).toMatch(/^2026-01-/);
|
|
105
|
+
});
|
|
106
|
+
}), n("should handle February in leap year correctly", () => {
|
|
107
|
+
t.currentDate.value = new Date(2024, 1, 1);
|
|
108
|
+
const o = t.calendarGrid.value.filter(
|
|
109
|
+
(r) => !r.isOutsideMonth && r.date
|
|
110
|
+
);
|
|
111
|
+
e(o.length).toBe(29);
|
|
112
|
+
}), n("should handle February in non-leap year correctly", () => {
|
|
113
|
+
t.currentDate.value = new Date(2025, 1, 1);
|
|
114
|
+
const o = t.calendarGrid.value.filter(
|
|
115
|
+
(r) => !r.isOutsideMonth && r.date
|
|
116
|
+
);
|
|
117
|
+
e(o.length).toBe(28);
|
|
118
|
+
});
|
|
119
|
+
}), s("month navigation", () => {
|
|
120
|
+
f(() => {
|
|
121
|
+
u = c(i());
|
|
122
|
+
}), n("handleNextMonth should advance to next month", () => {
|
|
123
|
+
const a = t.currentDate.value.getMonth(), o = t.currentDate.value.getFullYear();
|
|
124
|
+
t.handleNextMonth();
|
|
125
|
+
const r = t.currentDate.value.getMonth(), h = t.currentDate.value.getFullYear();
|
|
126
|
+
a === 11 ? (e(r).toBe(0), e(h).toBe(o + 1)) : (e(r).toBe(a + 1), e(h).toBe(o));
|
|
127
|
+
}), n("handlePrevMonth should go back to previous month", () => {
|
|
128
|
+
const a = t.currentDate.value.getMonth(), o = t.currentDate.value.getFullYear();
|
|
129
|
+
t.handlePrevMonth();
|
|
130
|
+
const r = t.currentDate.value.getMonth(), h = t.currentDate.value.getFullYear();
|
|
131
|
+
a === 0 ? (e(r).toBe(11), e(h).toBe(o - 1)) : (e(r).toBe(a - 1), e(h).toBe(o));
|
|
132
|
+
}), n("currentMonthLabel should update correctly after navigation", async () => {
|
|
133
|
+
const a = t.currentMonthLabel.value;
|
|
134
|
+
t.handleNextMonth(), await g();
|
|
135
|
+
const o = t.currentMonthLabel.value;
|
|
136
|
+
e(o).not.toBe(a), e(o).toContain(
|
|
137
|
+
t.currentDate.value.getFullYear().toString()
|
|
138
|
+
);
|
|
139
|
+
}), n("setCalendarMonthToAppliedOrToday should set to applied start date", () => {
|
|
140
|
+
l.value = "2026-06-15", u = c(i(l, d)), t.setCalendarMonthToAppliedOrToday();
|
|
141
|
+
const a = t.currentDate.value;
|
|
142
|
+
e(a.getFullYear()).toBe(2026), e(a.getMonth()).toBe(5), e(a.getDate()).toBe(1);
|
|
143
|
+
}), n("setCalendarMonthToAppliedOrToday should set to today when no applied start date", () => {
|
|
144
|
+
u = c(i());
|
|
145
|
+
const a = /* @__PURE__ */ new Date();
|
|
146
|
+
t.setCalendarMonthToAppliedOrToday();
|
|
147
|
+
const o = t.currentDate.value;
|
|
148
|
+
e(o.getFullYear()).toBe(a.getFullYear()), e(o.getMonth()).toBe(a.getMonth()), e(o.getDate()).toBe(1);
|
|
149
|
+
});
|
|
150
|
+
}), s("range selection logic", () => {
|
|
151
|
+
f(() => {
|
|
152
|
+
u = c(i(l, d));
|
|
153
|
+
}), n("initializeDraft should initialize draft from applied values", () => {
|
|
154
|
+
l.value = "2026-01-15", d.value = "2026-01-20", t.initializeDraft(), e(t.draftStart.value).toBe("2026-01-15"), e(t.draftEnd.value).toBe("2026-01-20");
|
|
155
|
+
}), n("initializeDraft should handle null applied values", () => {
|
|
156
|
+
l.value = null, d.value = null, t.initializeDraft(), e(t.draftStart.value).toBeNull(), e(t.draftEnd.value).toBeNull();
|
|
157
|
+
}), n("onDayClick should handle single date selection (sets start)", () => {
|
|
158
|
+
t.onDayClick("2026-01-15"), e(t.draftStart.value).toBe("2026-01-15"), e(t.draftEnd.value).toBeNull();
|
|
159
|
+
}), n("onDayClick should handle range selection (sets end after start)", () => {
|
|
160
|
+
t.onDayClick("2026-01-15"), t.onDayClick("2026-01-20"), e(t.draftStart.value).toBe("2026-01-15"), e(t.draftEnd.value).toBe("2026-01-20");
|
|
161
|
+
}), n("onDayClick should handle reverse selection (end before start swaps them)", () => {
|
|
162
|
+
t.onDayClick("2026-01-20"), t.onDayClick("2026-01-15"), e(t.draftStart.value).toBe("2026-01-15"), e(t.draftEnd.value).toBe("2026-01-20");
|
|
163
|
+
}), n("onDayClick should reset when both dates are set and new date clicked", () => {
|
|
164
|
+
t.onDayClick("2026-01-15"), t.onDayClick("2026-01-20"), t.onDayClick("2026-02-10"), e(t.draftStart.value).toBe("2026-02-10"), e(t.draftEnd.value).toBeNull();
|
|
165
|
+
}), n("onDayClick should do nothing when null is passed", () => {
|
|
166
|
+
const a = t.draftStart.value, o = t.draftEnd.value;
|
|
167
|
+
t.onDayClick(null), e(t.draftStart.value).toBe(a), e(t.draftEnd.value).toBe(o);
|
|
168
|
+
}), n("isDraftStart should correctly identify start date", () => {
|
|
169
|
+
t.draftStart.value = "2026-01-15", e(t.isDraftStart("2026-01-15")).toBe(!0), e(t.isDraftStart("2026-01-20")).toBe(!1);
|
|
170
|
+
}), n("isDraftEnd should correctly identify end date", () => {
|
|
171
|
+
t.draftEnd.value = "2026-01-20", e(t.isDraftEnd("2026-01-20")).toBe(!0), e(t.isDraftEnd("2026-01-15")).toBe(!1);
|
|
172
|
+
}), n("isInDraftRange should correctly identify dates in range", () => {
|
|
173
|
+
t.draftStart.value = "2026-01-15", t.draftEnd.value = "2026-01-20", e(t.isInDraftRange("2026-01-15")).toBe(!0), e(t.isInDraftRange("2026-01-18")).toBe(!0), e(t.isInDraftRange("2026-01-20")).toBe(!0), e(t.isInDraftRange("2026-01-14")).toBe(!1), e(t.isInDraftRange("2026-01-21")).toBe(!1);
|
|
174
|
+
}), n("isInDraftRange should return true only for start when no end date", () => {
|
|
175
|
+
t.draftStart.value = "2026-01-15", t.draftEnd.value = null, e(t.isInDraftRange("2026-01-15")).toBe(!0), e(t.isInDraftRange("2026-01-16")).toBe(!1);
|
|
176
|
+
}), n("isInDraftRange should return false when no start date", () => {
|
|
177
|
+
t.draftStart.value = null, t.draftEnd.value = "2026-01-20", e(t.isInDraftRange("2026-01-20")).toBe(!1);
|
|
178
|
+
});
|
|
179
|
+
}), s("draft management", () => {
|
|
180
|
+
f(() => {
|
|
181
|
+
u = c(i(l, d));
|
|
182
|
+
}), n("cancelDraft should revert draft to applied values", () => {
|
|
183
|
+
l.value = "2026-01-15", d.value = "2026-01-20", t.initializeDraft(), t.draftStart.value = "2026-02-10", t.draftEnd.value = "2026-02-15", t.cancelDraft(), e(t.draftStart.value).toBe("2026-01-15"), e(t.draftEnd.value).toBe("2026-01-20");
|
|
184
|
+
}), n("cancelDraft should handle null applied values", () => {
|
|
185
|
+
l.value = null, d.value = null, t.draftStart.value = "2026-01-15", t.draftEnd.value = "2026-01-20", t.cancelDraft(), e(t.draftStart.value).toBeNull(), e(t.draftEnd.value).toBeNull();
|
|
186
|
+
}), n("clearDraft should clear both draft and applied values", () => {
|
|
187
|
+
l.value = "2026-01-15", d.value = "2026-01-20", t.clearDraft(), e(t.draftStart.value).toBeNull(), e(t.draftEnd.value).toBeNull(), e(l.value).toBeNull(), e(d.value).toBeNull();
|
|
188
|
+
}), n("clearDraft should handle when applied refs are not provided", () => {
|
|
189
|
+
u = c(i()), t.draftStart.value = "2026-01-15", t.draftEnd.value = "2026-01-20", t.clearDraft(), e(t.draftStart.value).toBeNull(), e(t.draftEnd.value).toBeNull();
|
|
190
|
+
});
|
|
191
|
+
}), s("range label", () => {
|
|
192
|
+
f(() => {
|
|
193
|
+
u = c(i(l, d));
|
|
194
|
+
}), n("should show single date when only start date", () => {
|
|
195
|
+
l.value = "2026-01-15", d.value = null;
|
|
196
|
+
const a = t.rangeLabel.value;
|
|
197
|
+
e(a).toContain("1/15/26"), e(a).not.toContain(" - ");
|
|
198
|
+
}), n("should show range with year when different years", () => {
|
|
199
|
+
l.value = "2025-12-15", d.value = "2026-01-20";
|
|
200
|
+
const a = t.rangeLabel.value;
|
|
201
|
+
e(a).toContain("12/15/25"), e(a).toContain("1/20/26"), e(a).toContain(" - ");
|
|
202
|
+
}), n("should show range without year when same year", () => {
|
|
203
|
+
l.value = "2026-01-15", d.value = "2026-01-20";
|
|
204
|
+
const a = t.rangeLabel.value;
|
|
205
|
+
e(a).toContain("1/15"), e(a).toContain("1/20"), e(a).not.toContain("/26"), e(a).toContain(" - ");
|
|
206
|
+
}), n("should show range without year when same year but different months", () => {
|
|
207
|
+
l.value = "2026-01-15", d.value = "2026-02-20";
|
|
208
|
+
const a = t.rangeLabel.value;
|
|
209
|
+
e(a).toContain("1/15"), e(a).toContain("2/20"), e(a).not.toContain("/26"), e(a).toContain(" - ");
|
|
210
|
+
});
|
|
211
|
+
}), s("ARIA labels", () => {
|
|
212
|
+
f(() => {
|
|
213
|
+
u = c(i(l, d));
|
|
214
|
+
}), n('getDayAriaLabel should include "(start date)" for start', () => {
|
|
215
|
+
t.draftStart.value = "2026-01-15";
|
|
216
|
+
const a = t.getDayAriaLabel("2026-01-15");
|
|
217
|
+
e(a).toContain("(start date)");
|
|
218
|
+
}), n('getDayAriaLabel should include "(end date)" for end', () => {
|
|
219
|
+
t.draftStart.value = "2026-01-15", t.draftEnd.value = "2026-01-20";
|
|
220
|
+
const a = t.getDayAriaLabel("2026-01-20");
|
|
221
|
+
e(a).toContain("(end date)");
|
|
222
|
+
}), n('getDayAriaLabel should include "(in range)" for dates in range', () => {
|
|
223
|
+
t.draftStart.value = "2026-01-15", t.draftEnd.value = "2026-01-20";
|
|
224
|
+
const a = t.getDayAriaLabel("2026-01-18");
|
|
225
|
+
e(a).toContain("(in range)");
|
|
226
|
+
}), n("getDayAriaLabel should return plain date when not in range", () => {
|
|
227
|
+
t.draftStart.value = "2026-01-15", t.draftEnd.value = "2026-01-20";
|
|
228
|
+
const a = t.getDayAriaLabel("2026-01-25");
|
|
229
|
+
e(a).not.toContain("(start date)"), e(a).not.toContain("(end date)"), e(a).not.toContain("(in range)"), e(a).toBeTruthy();
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
});
|
|
@@ -7,7 +7,7 @@ interface Props {
|
|
|
7
7
|
}
|
|
8
8
|
export declare const useDropdown: ({ triggerElem, dropdownRef, openDropdownHandler, closeDropdownHandler }: Props) => {
|
|
9
9
|
open: Ref<boolean, boolean>;
|
|
10
|
-
|
|
10
|
+
openDropdown: () => void;
|
|
11
11
|
closeDropdown: () => void;
|
|
12
12
|
clearEventListeners: () => void;
|
|
13
13
|
};
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import '../assets/core.css';
|
|
2
|
-
import { ref as
|
|
3
|
-
import { i as
|
|
2
|
+
import { ref as w } from "vue";
|
|
3
|
+
import { i as o } from "../chunks/helper-qUkciePY.js";
|
|
4
4
|
const E = ({
|
|
5
|
-
triggerElem:
|
|
6
|
-
dropdownRef:
|
|
5
|
+
triggerElem: v,
|
|
6
|
+
dropdownRef: a,
|
|
7
7
|
openDropdownHandler: u,
|
|
8
8
|
closeDropdownHandler: s
|
|
9
9
|
}) => {
|
|
10
|
-
const t =
|
|
10
|
+
const t = w(!1), i = w(), d = () => {
|
|
11
11
|
try {
|
|
12
|
-
t.value = !
|
|
12
|
+
t.value = !0, o && (i.value = window.setTimeout(() => {
|
|
13
13
|
window.removeEventListener("click", e), window.removeEventListener("keyup", e), window.addEventListener("click", e), window.addEventListener("keyup", e);
|
|
14
14
|
}, 100)), u?.();
|
|
15
15
|
} catch (r) {
|
|
@@ -17,31 +17,31 @@ const E = ({
|
|
|
17
17
|
}
|
|
18
18
|
}, m = (r) => {
|
|
19
19
|
try {
|
|
20
|
-
const
|
|
21
|
-
return
|
|
22
|
-
} catch (
|
|
23
|
-
console.error(
|
|
20
|
+
const n = r?.target, c = v?.value, l = a?.value;
|
|
21
|
+
return o && c && l && !c.contains(n) && !l.contains(n) ? !0 : void 0;
|
|
22
|
+
} catch (n) {
|
|
23
|
+
console.error(n);
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
26
|
}, e = (r) => {
|
|
27
27
|
try {
|
|
28
|
-
m(r) && (
|
|
29
|
-
} catch (
|
|
30
|
-
console.error(
|
|
28
|
+
m(r) && (o && (window.removeEventListener("click", e), window.removeEventListener("keyup", e)), t.value = !1, s?.());
|
|
29
|
+
} catch (n) {
|
|
30
|
+
console.error(n);
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
return {
|
|
34
34
|
open: t,
|
|
35
|
-
|
|
35
|
+
openDropdown: d,
|
|
36
36
|
closeDropdown: () => {
|
|
37
37
|
try {
|
|
38
|
-
|
|
38
|
+
o && (window.removeEventListener("click", e), window.removeEventListener("keyup", e)), t.value = !1, s?.();
|
|
39
39
|
} catch (r) {
|
|
40
40
|
console.error(r);
|
|
41
41
|
}
|
|
42
42
|
},
|
|
43
43
|
clearEventListeners: () => {
|
|
44
|
-
|
|
44
|
+
o && (i.value && window.clearTimeout(i.value), window.removeEventListener("click", e), window.removeEventListener("keyup", e));
|
|
45
45
|
}
|
|
46
46
|
};
|
|
47
47
|
};
|
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"ui components",
|
|
18
18
|
"vuejs"
|
|
19
19
|
],
|
|
20
|
-
"version": "4.
|
|
20
|
+
"version": "4.8.0",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"type": "module",
|
|
23
23
|
"unpkg": "dist/callaloo.global.js",
|
|
@@ -135,6 +135,10 @@
|
|
|
135
135
|
"types": "./dist/components/Modals/CLModal/CLModal.vue.d.ts",
|
|
136
136
|
"import": "./dist/components/Modals/CLModal/CLModal.js"
|
|
137
137
|
},
|
|
138
|
+
"./CLModalDatePicker": {
|
|
139
|
+
"types": "./dist/components/Modals/CLModalDatePicker/CLModalDatePicker.vue.d.ts",
|
|
140
|
+
"import": "./dist/components/Modals/CLModalDatePicker/CLModalDatePicker.js"
|
|
141
|
+
},
|
|
138
142
|
"./CLLink": {
|
|
139
143
|
"types": "./dist/components/Navigation/CLLink/CLLink.vue.d.ts",
|
|
140
144
|
"import": "./dist/components/Navigation/CLLink/CLLink.js"
|