@archpublicwebsite/rangepicker 1.0.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.
@@ -0,0 +1,986 @@
1
+ import { defineComponent, computed, ref, watch, onMounted, onUnmounted, createBlock, openBlock, Teleport, createVNode, Transition, withCtx, createElementBlock, createCommentVNode, createElementVNode, normalizeStyle, normalizeClass, toDisplayString, Fragment, renderList, nextTick } from "vue";
2
+ import { useBreakpoints, breakpointsTailwind, useWindowSize, onClickOutside } from "@vueuse/core";
3
+ import dayjs from "dayjs";
4
+ function getDefaultExportFromCjs(x) {
5
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
6
+ }
7
+ var isBetween$2 = { exports: {} };
8
+ var isBetween$1 = isBetween$2.exports;
9
+ var hasRequiredIsBetween;
10
+ function requireIsBetween() {
11
+ if (hasRequiredIsBetween) return isBetween$2.exports;
12
+ hasRequiredIsBetween = 1;
13
+ (function(module, exports$1) {
14
+ !(function(e, i) {
15
+ module.exports = i();
16
+ })(isBetween$1, (function() {
17
+ return function(e, i, t) {
18
+ i.prototype.isBetween = function(e2, i2, s, f) {
19
+ var n = t(e2), o = t(i2), r = "(" === (f = f || "()")[0], u = ")" === f[1];
20
+ return (r ? this.isAfter(n, s) : !this.isBefore(n, s)) && (u ? this.isBefore(o, s) : !this.isAfter(o, s)) || (r ? this.isBefore(n, s) : !this.isAfter(n, s)) && (u ? this.isAfter(o, s) : !this.isBefore(o, s));
21
+ };
22
+ };
23
+ }));
24
+ })(isBetween$2);
25
+ return isBetween$2.exports;
26
+ }
27
+ var isBetweenExports = requireIsBetween();
28
+ const isBetween = /* @__PURE__ */ getDefaultExportFromCjs(isBetweenExports);
29
+ var isSameOrAfter$2 = { exports: {} };
30
+ var isSameOrAfter$1 = isSameOrAfter$2.exports;
31
+ var hasRequiredIsSameOrAfter;
32
+ function requireIsSameOrAfter() {
33
+ if (hasRequiredIsSameOrAfter) return isSameOrAfter$2.exports;
34
+ hasRequiredIsSameOrAfter = 1;
35
+ (function(module, exports$1) {
36
+ !(function(e, t) {
37
+ module.exports = t();
38
+ })(isSameOrAfter$1, (function() {
39
+ return function(e, t) {
40
+ t.prototype.isSameOrAfter = function(e2, t2) {
41
+ return this.isSame(e2, t2) || this.isAfter(e2, t2);
42
+ };
43
+ };
44
+ }));
45
+ })(isSameOrAfter$2);
46
+ return isSameOrAfter$2.exports;
47
+ }
48
+ var isSameOrAfterExports = requireIsSameOrAfter();
49
+ const isSameOrAfter = /* @__PURE__ */ getDefaultExportFromCjs(isSameOrAfterExports);
50
+ var isSameOrBefore$2 = { exports: {} };
51
+ var isSameOrBefore$1 = isSameOrBefore$2.exports;
52
+ var hasRequiredIsSameOrBefore;
53
+ function requireIsSameOrBefore() {
54
+ if (hasRequiredIsSameOrBefore) return isSameOrBefore$2.exports;
55
+ hasRequiredIsSameOrBefore = 1;
56
+ (function(module, exports$1) {
57
+ !(function(e, i) {
58
+ module.exports = i();
59
+ })(isSameOrBefore$1, (function() {
60
+ return function(e, i) {
61
+ i.prototype.isSameOrBefore = function(e2, i2) {
62
+ return this.isSame(e2, i2) || this.isBefore(e2, i2);
63
+ };
64
+ };
65
+ }));
66
+ })(isSameOrBefore$2);
67
+ return isSameOrBefore$2.exports;
68
+ }
69
+ var isSameOrBeforeExports = requireIsSameOrBefore();
70
+ const isSameOrBefore = /* @__PURE__ */ getDefaultExportFromCjs(isSameOrBeforeExports);
71
+ var customParseFormat$2 = { exports: {} };
72
+ var customParseFormat$1 = customParseFormat$2.exports;
73
+ var hasRequiredCustomParseFormat;
74
+ function requireCustomParseFormat() {
75
+ if (hasRequiredCustomParseFormat) return customParseFormat$2.exports;
76
+ hasRequiredCustomParseFormat = 1;
77
+ (function(module, exports$1) {
78
+ !(function(e, t) {
79
+ module.exports = t();
80
+ })(customParseFormat$1, (function() {
81
+ var e = { LTS: "h:mm:ss A", LT: "h:mm A", L: "MM/DD/YYYY", LL: "MMMM D, YYYY", LLL: "MMMM D, YYYY h:mm A", LLLL: "dddd, MMMM D, YYYY h:mm A" }, t = /(\[[^[]*\])|([-_:/.,()\s]+)|(A|a|Q|YYYY|YY?|ww?|MM?M?M?|Do|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g, n = /\d/, r = /\d\d/, i = /\d\d?/, o = /\d*[^-_:/,()\s\d]+/, s = {}, a = function(e2) {
82
+ return (e2 = +e2) + (e2 > 68 ? 1900 : 2e3);
83
+ };
84
+ var f = function(e2) {
85
+ return function(t2) {
86
+ this[e2] = +t2;
87
+ };
88
+ }, h = [/[+-]\d\d:?(\d\d)?|Z/, function(e2) {
89
+ (this.zone || (this.zone = {})).offset = (function(e3) {
90
+ if (!e3) return 0;
91
+ if ("Z" === e3) return 0;
92
+ var t2 = e3.match(/([+-]|\d\d)/g), n2 = 60 * t2[1] + (+t2[2] || 0);
93
+ return 0 === n2 ? 0 : "+" === t2[0] ? -n2 : n2;
94
+ })(e2);
95
+ }], u = function(e2) {
96
+ var t2 = s[e2];
97
+ return t2 && (t2.indexOf ? t2 : t2.s.concat(t2.f));
98
+ }, d = function(e2, t2) {
99
+ var n2, r2 = s.meridiem;
100
+ if (r2) {
101
+ for (var i2 = 1; i2 <= 24; i2 += 1) if (e2.indexOf(r2(i2, 0, t2)) > -1) {
102
+ n2 = i2 > 12;
103
+ break;
104
+ }
105
+ } else n2 = e2 === (t2 ? "pm" : "PM");
106
+ return n2;
107
+ }, c = { A: [o, function(e2) {
108
+ this.afternoon = d(e2, false);
109
+ }], a: [o, function(e2) {
110
+ this.afternoon = d(e2, true);
111
+ }], Q: [n, function(e2) {
112
+ this.month = 3 * (e2 - 1) + 1;
113
+ }], S: [n, function(e2) {
114
+ this.milliseconds = 100 * +e2;
115
+ }], SS: [r, function(e2) {
116
+ this.milliseconds = 10 * +e2;
117
+ }], SSS: [/\d{3}/, function(e2) {
118
+ this.milliseconds = +e2;
119
+ }], s: [i, f("seconds")], ss: [i, f("seconds")], m: [i, f("minutes")], mm: [i, f("minutes")], H: [i, f("hours")], h: [i, f("hours")], HH: [i, f("hours")], hh: [i, f("hours")], D: [i, f("day")], DD: [r, f("day")], Do: [o, function(e2) {
120
+ var t2 = s.ordinal, n2 = e2.match(/\d+/);
121
+ if (this.day = n2[0], t2) for (var r2 = 1; r2 <= 31; r2 += 1) t2(r2).replace(/\[|\]/g, "") === e2 && (this.day = r2);
122
+ }], w: [i, f("week")], ww: [r, f("week")], M: [i, f("month")], MM: [r, f("month")], MMM: [o, function(e2) {
123
+ var t2 = u("months"), n2 = (u("monthsShort") || t2.map((function(e3) {
124
+ return e3.slice(0, 3);
125
+ }))).indexOf(e2) + 1;
126
+ if (n2 < 1) throw new Error();
127
+ this.month = n2 % 12 || n2;
128
+ }], MMMM: [o, function(e2) {
129
+ var t2 = u("months").indexOf(e2) + 1;
130
+ if (t2 < 1) throw new Error();
131
+ this.month = t2 % 12 || t2;
132
+ }], Y: [/[+-]?\d+/, f("year")], YY: [r, function(e2) {
133
+ this.year = a(e2);
134
+ }], YYYY: [/\d{4}/, f("year")], Z: h, ZZ: h };
135
+ function l(n2) {
136
+ var r2, i2;
137
+ r2 = n2, i2 = s && s.formats;
138
+ for (var o2 = (n2 = r2.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g, (function(t2, n3, r3) {
139
+ var o3 = r3 && r3.toUpperCase();
140
+ return n3 || i2[r3] || e[r3] || i2[o3].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g, (function(e2, t3, n4) {
141
+ return t3 || n4.slice(1);
142
+ }));
143
+ }))).match(t), a2 = o2.length, f2 = 0; f2 < a2; f2 += 1) {
144
+ var h2 = o2[f2], u2 = c[h2], d2 = u2 && u2[0], l2 = u2 && u2[1];
145
+ o2[f2] = l2 ? { regex: d2, parser: l2 } : h2.replace(/^\[|\]$/g, "");
146
+ }
147
+ return function(e2) {
148
+ for (var t2 = {}, n3 = 0, r3 = 0; n3 < a2; n3 += 1) {
149
+ var i3 = o2[n3];
150
+ if ("string" == typeof i3) r3 += i3.length;
151
+ else {
152
+ var s2 = i3.regex, f3 = i3.parser, h3 = e2.slice(r3), u3 = s2.exec(h3)[0];
153
+ f3.call(t2, u3), e2 = e2.replace(u3, "");
154
+ }
155
+ }
156
+ return (function(e3) {
157
+ var t3 = e3.afternoon;
158
+ if (void 0 !== t3) {
159
+ var n4 = e3.hours;
160
+ t3 ? n4 < 12 && (e3.hours += 12) : 12 === n4 && (e3.hours = 0), delete e3.afternoon;
161
+ }
162
+ })(t2), t2;
163
+ };
164
+ }
165
+ return function(e2, t2, n2) {
166
+ n2.p.customParseFormat = true, e2 && e2.parseTwoDigitYear && (a = e2.parseTwoDigitYear);
167
+ var r2 = t2.prototype, i2 = r2.parse;
168
+ r2.parse = function(e3) {
169
+ var t3 = e3.date, r3 = e3.utc, o2 = e3.args;
170
+ this.$u = r3;
171
+ var a2 = o2[1];
172
+ if ("string" == typeof a2) {
173
+ var f2 = true === o2[2], h2 = true === o2[3], u2 = f2 || h2, d2 = o2[2];
174
+ h2 && (d2 = o2[2]), s = this.$locale(), !f2 && d2 && (s = n2.Ls[d2]), this.$d = (function(e4, t4, n3, r4) {
175
+ try {
176
+ if (["x", "X"].indexOf(t4) > -1) return new Date(("X" === t4 ? 1e3 : 1) * e4);
177
+ var i3 = l(t4)(e4), o3 = i3.year, s2 = i3.month, a3 = i3.day, f3 = i3.hours, h3 = i3.minutes, u3 = i3.seconds, d3 = i3.milliseconds, c3 = i3.zone, m2 = i3.week, M2 = /* @__PURE__ */ new Date(), Y = a3 || (o3 || s2 ? 1 : M2.getDate()), p = o3 || M2.getFullYear(), v = 0;
178
+ o3 && !s2 || (v = s2 > 0 ? s2 - 1 : M2.getMonth());
179
+ var D, w = f3 || 0, g = h3 || 0, y = u3 || 0, L = d3 || 0;
180
+ return c3 ? new Date(Date.UTC(p, v, Y, w, g, y, L + 60 * c3.offset * 1e3)) : n3 ? new Date(Date.UTC(p, v, Y, w, g, y, L)) : (D = new Date(p, v, Y, w, g, y, L), m2 && (D = r4(D).week(m2).toDate()), D);
181
+ } catch (e5) {
182
+ return /* @__PURE__ */ new Date("");
183
+ }
184
+ })(t3, a2, r3, n2), this.init(), d2 && true !== d2 && (this.$L = this.locale(d2).$L), u2 && t3 != this.format(a2) && (this.$d = /* @__PURE__ */ new Date("")), s = {};
185
+ } else if (a2 instanceof Array) for (var c2 = a2.length, m = 1; m <= c2; m += 1) {
186
+ o2[1] = a2[m - 1];
187
+ var M = n2.apply(this, o2);
188
+ if (M.isValid()) {
189
+ this.$d = M.$d, this.$L = M.$L, this.init();
190
+ break;
191
+ }
192
+ m === c2 && (this.$d = /* @__PURE__ */ new Date(""));
193
+ }
194
+ else i2.call(this, e3);
195
+ };
196
+ };
197
+ }));
198
+ })(customParseFormat$2);
199
+ return customParseFormat$2.exports;
200
+ }
201
+ var customParseFormatExports = requireCustomParseFormat();
202
+ const customParseFormat = /* @__PURE__ */ getDefaultExportFromCjs(customParseFormatExports);
203
+ dayjs.extend(isBetween);
204
+ dayjs.extend(isSameOrAfter);
205
+ dayjs.extend(isSameOrBefore);
206
+ dayjs.extend(customParseFormat);
207
+ function getMonthDays(monthOffset, currentDate = dayjs()) {
208
+ const month = currentDate.add(monthOffset, "month").startOf("month");
209
+ const firstDayOfMonth = month.day();
210
+ const daysInMonth = month.daysInMonth();
211
+ const daysInPrevMonth = month.subtract(1, "month").daysInMonth();
212
+ const days = [];
213
+ for (let i = firstDayOfMonth - 1; i >= 0; i--) {
214
+ const date = month.subtract(1, "month").date(daysInPrevMonth - i);
215
+ days.push({
216
+ date,
217
+ isPrevMonth: true,
218
+ isCurrentMonth: false,
219
+ isNextMonth: false
220
+ });
221
+ }
222
+ for (let i = 1; i <= daysInMonth; i++) {
223
+ const date = month.date(i);
224
+ days.push({
225
+ date,
226
+ isPrevMonth: false,
227
+ isCurrentMonth: true,
228
+ isNextMonth: false
229
+ });
230
+ }
231
+ const remainingDays = 42 - days.length;
232
+ for (let i = 1; i <= remainingDays; i++) {
233
+ const date = month.add(1, "month").date(i);
234
+ days.push({
235
+ date,
236
+ isPrevMonth: false,
237
+ isCurrentMonth: false,
238
+ isNextMonth: true
239
+ });
240
+ }
241
+ return { month, days };
242
+ }
243
+ function createCalendarDay(date, isPrevMonth, isCurrentMonth, isNextMonth, options = {}) {
244
+ const {
245
+ startDate = null,
246
+ endDate = null,
247
+ minDate = null,
248
+ maxDate = null,
249
+ disabledDates = [],
250
+ holidays = []
251
+ } = options;
252
+ const isDisabled = minDate && date.isBefore(minDate, "day") || maxDate && date.isAfter(maxDate, "day") || disabledDates.some((d) => d.isSame(date, "day"));
253
+ const isHoliday = holidays.some((h) => h.isSame(date, "day"));
254
+ const isSelected = startDate && date.isSame(startDate, "day") || endDate && date.isSame(endDate, "day");
255
+ const isInRange = startDate && endDate && date.isAfter(startDate, "day") && date.isBefore(endDate, "day");
256
+ const isToday = date.isSame(dayjs(), "day");
257
+ const isWeekend = date.day() === 0 || date.day() === 6;
258
+ return {
259
+ date,
260
+ isPrevMonth,
261
+ isCurrentMonth,
262
+ isNextMonth,
263
+ isDisabled,
264
+ isHoliday,
265
+ isWeekend,
266
+ isSelected,
267
+ isInRange,
268
+ isToday
269
+ };
270
+ }
271
+ function generateCalendarMonths(numberOfMonths, startOffset = 0, options = {}) {
272
+ const months = [];
273
+ for (let i = 0; i < numberOfMonths; i++) {
274
+ const { month, days } = getMonthDays(startOffset + i);
275
+ const calendarDays = days.map(
276
+ (day) => createCalendarDay(
277
+ day.date,
278
+ day.isPrevMonth,
279
+ day.isCurrentMonth,
280
+ day.isNextMonth,
281
+ options
282
+ )
283
+ );
284
+ months.push({
285
+ month,
286
+ days: calendarDays
287
+ });
288
+ }
289
+ return months;
290
+ }
291
+ function getWeekDays(locale = "en", format = "short") {
292
+ const weekStart = dayjs().startOf("week");
293
+ const days = [];
294
+ for (let i = 0; i < 7; i++) {
295
+ const day = weekStart.add(i, "day");
296
+ days.push(format === "short" ? day.format("ddd") : day.format("dd"));
297
+ }
298
+ return days;
299
+ }
300
+ function calculatePosition(triggerElement, calendarElement, preferredPosition = "auto") {
301
+ if (!triggerElement || !calendarElement)
302
+ return { left: 0 };
303
+ const triggerRect = triggerElement.getBoundingClientRect();
304
+ const calendarRect = calendarElement.getBoundingClientRect();
305
+ const viewportHeight = window.innerHeight;
306
+ const viewportWidth = window.innerWidth;
307
+ const spaceAbove = triggerRect.top;
308
+ const spaceBelow = viewportHeight - triggerRect.bottom;
309
+ const position = { left: triggerRect.left };
310
+ if (preferredPosition === "auto") {
311
+ if (spaceBelow >= calendarRect.height || spaceBelow > spaceAbove) {
312
+ position.top = triggerRect.bottom + 8;
313
+ } else {
314
+ position.bottom = viewportHeight - triggerRect.top + 8;
315
+ }
316
+ } else if (preferredPosition === "top") {
317
+ position.bottom = viewportHeight - triggerRect.top + 8;
318
+ } else {
319
+ position.top = triggerRect.bottom + 8;
320
+ }
321
+ if (position.left + calendarRect.width > viewportWidth)
322
+ position.left = viewportWidth - calendarRect.width - 16;
323
+ if (position.left < 16)
324
+ position.left = 16;
325
+ return position;
326
+ }
327
+ const _hoisted_1$1 = {
328
+ key: 0,
329
+ class: "rangepicker-overlay"
330
+ };
331
+ const _hoisted_2 = { class: "rangepicker-header" };
332
+ const _hoisted_3 = { class: "flex items-center justify-between" };
333
+ const _hoisted_4 = {
334
+ key: 0,
335
+ class: "text-xs font-medium text-gray-500 mb-1 font-secondary"
336
+ };
337
+ const _hoisted_5 = { class: "text-sm font-semibold text-gray-900 font-secondary" };
338
+ const _hoisted_6 = {
339
+ key: 0,
340
+ class: "text-xs text-gray-500 mt-1 font-secondary"
341
+ };
342
+ const _hoisted_7 = { class: "rangepicker-body" };
343
+ const _hoisted_8 = { class: "rangepicker-month-header" };
344
+ const _hoisted_9 = ["disabled"];
345
+ const _hoisted_10 = {
346
+ key: 1,
347
+ class: "w-8"
348
+ };
349
+ const _hoisted_11 = { class: "rangepicker-month-title font-secondary" };
350
+ const _hoisted_12 = ["disabled"];
351
+ const _hoisted_13 = {
352
+ key: 3,
353
+ class: "w-8"
354
+ };
355
+ const _hoisted_14 = { class: "rangepicker-weekdays" };
356
+ const _hoisted_15 = { class: "rangepicker-grid" };
357
+ const _hoisted_16 = ["disabled", "aria-label", "onClick", "onMouseenter"];
358
+ const _hoisted_17 = { class: "font-secondary" };
359
+ const _hoisted_18 = {
360
+ key: 0,
361
+ class: "mt-4 flex items-center justify-end gap-2 border-t border-gray-200 pt-4"
362
+ };
363
+ const _hoisted_19 = ["disabled"];
364
+ const _hoisted_20 = { class: "flex items-center gap-1" };
365
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
366
+ __name: "Rangepicker",
367
+ props: {
368
+ modelValue: {},
369
+ isOpen: { type: Boolean, default: false },
370
+ variant: { default: "desktop" },
371
+ minDate: {},
372
+ maxDate: {},
373
+ minDays: {},
374
+ maxDays: {},
375
+ close: { type: Boolean },
376
+ valueOfMonths: { default: 2 },
377
+ valueOfColumns: { default: 2 },
378
+ disabledDates: {},
379
+ holidays: {},
380
+ format: { default: "YYYY-MM-DD" },
381
+ delimiter: { default: " - " },
382
+ placeholder: {},
383
+ label: {},
384
+ showTooltip: { type: Boolean, default: true },
385
+ autoApply: { type: Boolean, default: false },
386
+ position: { default: "auto" },
387
+ triggerElement: {},
388
+ colorStyles: {}
389
+ },
390
+ emits: ["update:modelValue", "update:isOpen", "dateSelected", "rangeSelected"],
391
+ setup(__props, { emit: __emit }) {
392
+ const props = __props;
393
+ const emit = __emit;
394
+ const breakpoints = useBreakpoints(breakpointsTailwind);
395
+ const isMobile = breakpoints.smallerOrEqual("lg");
396
+ const numberOfMonths = computed(
397
+ () => isMobile.value ? 1 : props.valueOfMonths
398
+ );
399
+ const numberOfColumns = computed(
400
+ () => isMobile.value ? 1 : props.valueOfColumns
401
+ );
402
+ const calendarRef = ref(null);
403
+ const isFadingOut = ref(false);
404
+ const hoveredDay = ref(null);
405
+ const monthOffset = ref(0);
406
+ const localIsOpen = ref(props.isOpen);
407
+ const localStartDate = ref(null);
408
+ const localEndDate = ref(null);
409
+ const parsedMinDate = computed(
410
+ () => props.minDate ? dayjs(props.minDate) : null
411
+ );
412
+ const parsedMaxDate = computed(
413
+ () => props.maxDate ? dayjs(props.maxDate) : null
414
+ );
415
+ const parsedDisabledDates = computed(
416
+ () => {
417
+ var _a;
418
+ return ((_a = props.disabledDates) == null ? void 0 : _a.map((d) => dayjs(d))) || [];
419
+ }
420
+ );
421
+ const parsedHolidays = computed(
422
+ () => {
423
+ var _a;
424
+ return ((_a = props.holidays) == null ? void 0 : _a.map((h) => dayjs(h))) || [];
425
+ }
426
+ );
427
+ const weekdays = computed(() => getWeekDays("en", "narrow"));
428
+ const effectiveNumberOfMonths = computed(
429
+ () => props.variant === "mobile" ? 1 : numberOfMonths.value
430
+ );
431
+ const calendarMonths = computed(
432
+ () => generateCalendarMonths(effectiveNumberOfMonths.value, monthOffset.value, {
433
+ startDate: localStartDate.value,
434
+ endDate: localEndDate.value,
435
+ minDate: parsedMinDate.value,
436
+ maxDate: parsedMaxDate.value,
437
+ disabledDates: parsedDisabledDates.value,
438
+ holidays: parsedHolidays.value
439
+ })
440
+ );
441
+ const nightCount = computed(() => {
442
+ if (!localStartDate.value || !localEndDate.value)
443
+ return 0;
444
+ return localEndDate.value.diff(localStartDate.value, "day");
445
+ });
446
+ const formattedDateRange = computed(() => {
447
+ if (!localStartDate.value && !localEndDate.value)
448
+ return "";
449
+ else if (localStartDate.value && !localEndDate.value)
450
+ return localStartDate.value.format(props.format);
451
+ else if (localStartDate.value && localEndDate.value)
452
+ return `${localStartDate.value.format(props.format)}${props.delimiter}${localEndDate.value.format(props.format)}`;
453
+ else
454
+ return "";
455
+ });
456
+ const canNavigatePrevious = computed(() => {
457
+ if (!parsedMinDate.value)
458
+ return true;
459
+ const firstMonth = dayjs().add(monthOffset.value, "month").startOf("month");
460
+ return firstMonth.isAfter(parsedMinDate.value, "month");
461
+ });
462
+ const canNavigateNext = computed(() => {
463
+ if (!parsedMaxDate.value)
464
+ return true;
465
+ const lastMonth = dayjs().add(monthOffset.value + effectiveNumberOfMonths.value - 1, "month").endOf("month");
466
+ return lastMonth.isBefore(parsedMaxDate.value, "month");
467
+ });
468
+ const { width: windowWidth } = useWindowSize();
469
+ const calendarStyle = ref({});
470
+ function updatePosition() {
471
+ if (props.variant === "mobile")
472
+ return;
473
+ nextTick(() => {
474
+ const position = calculatePosition(
475
+ props.triggerElement,
476
+ calendarRef.value,
477
+ props.position
478
+ );
479
+ calendarStyle.value = {
480
+ left: `${position.left}px`,
481
+ ...position.top !== void 0 && { top: `${position.top}px` },
482
+ ...position.bottom !== void 0 && { bottom: `${position.bottom}px` },
483
+ ...position.transform && { transform: position.transform }
484
+ };
485
+ });
486
+ }
487
+ const tooltipStyle = ref({});
488
+ const tooltipText = computed(() => {
489
+ if (!hoveredDay.value || !localStartDate.value)
490
+ return "";
491
+ const nights = hoveredDay.value.date.diff(localStartDate.value, "day");
492
+ if (nights <= 0)
493
+ return "";
494
+ return `${nights} ${nights === 1 ? "night" : "nights"}`;
495
+ });
496
+ const showTooltipComputed = computed(() => {
497
+ return props.showTooltip && hoveredDay.value && localStartDate.value && !localEndDate.value && hoveredDay.value.date.isAfter(localStartDate.value, "day");
498
+ });
499
+ function getDayClasses(day) {
500
+ const classes = ["rangepicker-day"];
501
+ if (!day.isCurrentMonth)
502
+ classes.push("rangepicker-day-other-month");
503
+ if (day.isDisabled)
504
+ classes.push("rangepicker-day-disabled");
505
+ if (day.isToday)
506
+ classes.push("rangepicker-day-today");
507
+ if (day.isWeekend && !day.isSelected)
508
+ classes.push("rangepicker-day-weekend");
509
+ if (day.isHoliday)
510
+ classes.push("rangepicker-day-holiday");
511
+ if (day.isSelected) {
512
+ if (localStartDate.value && localEndDate.value && day.date.isSame(localStartDate.value, "day") && day.date.isSame(localEndDate.value, "day"))
513
+ classes.push("rangepicker-day-selected-single");
514
+ else if (localStartDate.value && day.date.isSame(localStartDate.value, "day"))
515
+ classes.push("rangepicker-day-selected-start");
516
+ else if (localEndDate.value && day.date.isSame(localEndDate.value, "day"))
517
+ classes.push("rangepicker-day-selected-end");
518
+ else
519
+ classes.push("rangepicker-day-selected");
520
+ }
521
+ if (day.isInRange)
522
+ classes.push("rangepicker-day-in-range");
523
+ if (localStartDate.value && !localEndDate.value && hoveredDay.value) {
524
+ const start = localStartDate.value;
525
+ const hovered = hoveredDay.value.date;
526
+ if (day.date.isAfter(start, "day") && day.date.isBefore(hovered, "day"))
527
+ classes.push("rangepicker-day-hover-range");
528
+ else if (day.date.isSame(hovered, "day") && hovered.isAfter(start, "day"))
529
+ classes.push("rangepicker-day-hover-end");
530
+ }
531
+ return classes;
532
+ }
533
+ function selectDate(day) {
534
+ if (day.isDisabled)
535
+ return;
536
+ emit("dateSelected", day.date);
537
+ if (!localStartDate.value || localStartDate.value && localEndDate.value) {
538
+ localStartDate.value = day.date;
539
+ localEndDate.value = null;
540
+ } else {
541
+ if (day.date.isBefore(localStartDate.value, "day")) {
542
+ localEndDate.value = localStartDate.value;
543
+ localStartDate.value = day.date;
544
+ } else {
545
+ localEndDate.value = day.date;
546
+ }
547
+ if (props.minDays) {
548
+ const days = localEndDate.value.diff(localStartDate.value, "day");
549
+ if (days < props.minDays) {
550
+ localStartDate.value = day.date;
551
+ localEndDate.value = null;
552
+ return;
553
+ }
554
+ }
555
+ if (props.maxDays) {
556
+ const days = localEndDate.value.diff(localStartDate.value, "day");
557
+ if (days > props.maxDays) {
558
+ localStartDate.value = day.date;
559
+ localEndDate.value = null;
560
+ return;
561
+ }
562
+ }
563
+ emit("rangeSelected", localStartDate.value, localEndDate.value);
564
+ if (props.autoApply)
565
+ apply();
566
+ }
567
+ }
568
+ function handleDayHover(day, event) {
569
+ hoveredDay.value = day;
570
+ if (props.showTooltip && localStartDate.value && !localEndDate.value)
571
+ updateTooltipPosition(event);
572
+ }
573
+ function updateTooltipPosition(event) {
574
+ const rect = event.target.getBoundingClientRect();
575
+ tooltipStyle.value = {
576
+ left: `${rect.left + rect.width / 2}px`,
577
+ top: `${rect.top - 10}px`,
578
+ transform: "translateX(-50%) translateY(-100%)"
579
+ };
580
+ }
581
+ function handleDayLeave() {
582
+ hoveredDay.value = null;
583
+ }
584
+ function previousMonth() {
585
+ if (canNavigatePrevious.value)
586
+ monthOffset.value--;
587
+ }
588
+ function nextMonth() {
589
+ if (canNavigateNext.value)
590
+ monthOffset.value++;
591
+ }
592
+ function close() {
593
+ if (isFadingOut.value)
594
+ return;
595
+ isFadingOut.value = true;
596
+ setTimeout(() => {
597
+ localIsOpen.value = false;
598
+ emit("update:isOpen", false);
599
+ isFadingOut.value = false;
600
+ }, 200);
601
+ }
602
+ function apply() {
603
+ if (localStartDate.value && localEndDate.value) {
604
+ emit("update:modelValue", {
605
+ startDate: localStartDate.value.format(props.format),
606
+ endDate: localEndDate.value.format(props.format)
607
+ });
608
+ }
609
+ close();
610
+ }
611
+ function cancel() {
612
+ var _a, _b;
613
+ if ((_a = props.modelValue) == null ? void 0 : _a.startDate)
614
+ localStartDate.value = dayjs(props.modelValue.startDate);
615
+ else
616
+ localStartDate.value = null;
617
+ if ((_b = props.modelValue) == null ? void 0 : _b.endDate)
618
+ localEndDate.value = dayjs(props.modelValue.endDate);
619
+ else
620
+ localEndDate.value = null;
621
+ close();
622
+ }
623
+ watch(
624
+ () => props.isOpen,
625
+ (newVal) => {
626
+ localIsOpen.value = newVal;
627
+ if (newVal)
628
+ updatePosition();
629
+ }
630
+ );
631
+ watch(
632
+ () => props.close,
633
+ (newVal) => {
634
+ if (newVal)
635
+ close();
636
+ }
637
+ );
638
+ watch(
639
+ () => props.modelValue,
640
+ (newVal) => {
641
+ if (newVal == null ? void 0 : newVal.startDate)
642
+ localStartDate.value = dayjs(newVal.startDate);
643
+ else
644
+ localStartDate.value = null;
645
+ if (newVal == null ? void 0 : newVal.endDate)
646
+ localEndDate.value = dayjs(newVal.endDate);
647
+ else
648
+ localEndDate.value = null;
649
+ },
650
+ { immediate: true, deep: true }
651
+ );
652
+ watch([windowWidth, localIsOpen], () => {
653
+ if (localIsOpen.value)
654
+ updatePosition();
655
+ });
656
+ onClickOutside(calendarRef, () => {
657
+ if (localIsOpen.value && props.variant !== "mobile")
658
+ close();
659
+ });
660
+ function handleKeydown(e) {
661
+ if (!localIsOpen.value)
662
+ return;
663
+ if (e.key === "Escape")
664
+ close();
665
+ }
666
+ onMounted(() => {
667
+ document.addEventListener("keydown", handleKeydown);
668
+ if (props.isOpen)
669
+ updatePosition();
670
+ });
671
+ onUnmounted(() => {
672
+ document.removeEventListener("keydown", handleKeydown);
673
+ });
674
+ return (_ctx, _cache) => {
675
+ return openBlock(), createBlock(Teleport, { to: "body" }, [
676
+ createVNode(Transition, {
677
+ name: __props.variant === "mobile" ? "slide-up" : "fade"
678
+ }, {
679
+ default: withCtx(() => [
680
+ localIsOpen.value || isFadingOut.value ? (openBlock(), createElementBlock("div", _hoisted_1$1, [
681
+ createElementVNode("div", {
682
+ class: "rangepicker-backdrop",
683
+ onClick: close
684
+ }),
685
+ createElementVNode("div", {
686
+ ref_key: "calendarRef",
687
+ ref: calendarRef,
688
+ class: normalizeClass(["rangepicker-container", [
689
+ __props.variant === "mobile" ? "rangepicker-mobile" : ""
690
+ ]]),
691
+ style: normalizeStyle({ ...calendarStyle.value, ...__props.colorStyles })
692
+ }, [
693
+ createElementVNode("div", _hoisted_2, [
694
+ createElementVNode("div", _hoisted_3, [
695
+ createElementVNode("div", null, [
696
+ __props.label ? (openBlock(), createElementBlock("p", _hoisted_4, toDisplayString(__props.label), 1)) : createCommentVNode("", true),
697
+ createElementVNode("p", _hoisted_5, toDisplayString(formattedDateRange.value || __props.placeholder || "Select dates"), 1)
698
+ ]),
699
+ nightCount.value > 0 ? (openBlock(), createElementBlock("p", _hoisted_6, toDisplayString(nightCount.value) + " " + toDisplayString(nightCount.value === 1 ? "night" : "nights"), 1)) : createCommentVNode("", true)
700
+ ])
701
+ ]),
702
+ createElementVNode("div", _hoisted_7, [
703
+ createElementVNode("div", {
704
+ class: normalizeClass(["rangepicker-month-grid", [
705
+ __props.variant === "mobile" ? "grid-cols-1" : `lg:grid-cols-${numberOfColumns.value}`
706
+ ]])
707
+ }, [
708
+ (openBlock(true), createElementBlock(Fragment, null, renderList(calendarMonths.value, (monthData, index) => {
709
+ return openBlock(), createElementBlock("div", {
710
+ key: monthData.month.format("YYYY-MM"),
711
+ class: "rangepicker-month"
712
+ }, [
713
+ createElementVNode("div", _hoisted_8, [
714
+ __props.variant === "mobile" || index === 0 ? (openBlock(), createElementBlock("button", {
715
+ key: 0,
716
+ class: "rangepicker-nav-button",
717
+ disabled: !canNavigatePrevious.value,
718
+ "aria-label": "Previous month",
719
+ onClick: previousMonth
720
+ }, [..._cache[0] || (_cache[0] = [
721
+ createElementVNode("svg", {
722
+ xmlns: "http://www.w3.org/2000/svg",
723
+ class: "h-5 w-5",
724
+ viewBox: "0 0 20 20",
725
+ fill: "currentColor"
726
+ }, [
727
+ createElementVNode("path", {
728
+ "fill-rule": "evenodd",
729
+ d: "M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z",
730
+ "clip-rule": "evenodd"
731
+ })
732
+ ], -1)
733
+ ])], 8, _hoisted_9)) : (openBlock(), createElementBlock("div", _hoisted_10)),
734
+ createElementVNode("h3", _hoisted_11, toDisplayString(monthData.month.format("MMMM YYYY")), 1),
735
+ __props.variant === "mobile" || index === calendarMonths.value.length - 1 ? (openBlock(), createElementBlock("button", {
736
+ key: 2,
737
+ class: "rangepicker-nav-button",
738
+ disabled: !canNavigateNext.value,
739
+ "aria-label": "Next month",
740
+ onClick: nextMonth
741
+ }, [..._cache[1] || (_cache[1] = [
742
+ createElementVNode("svg", {
743
+ xmlns: "http://www.w3.org/2000/svg",
744
+ class: "h-5 w-5",
745
+ viewBox: "0 0 20 20",
746
+ fill: "currentColor"
747
+ }, [
748
+ createElementVNode("path", {
749
+ "fill-rule": "evenodd",
750
+ d: "M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z",
751
+ "clip-rule": "evenodd"
752
+ })
753
+ ], -1)
754
+ ])], 8, _hoisted_12)) : (openBlock(), createElementBlock("div", _hoisted_13))
755
+ ]),
756
+ createElementVNode("div", _hoisted_14, [
757
+ (openBlock(true), createElementBlock(Fragment, null, renderList(weekdays.value, (weekday) => {
758
+ return openBlock(), createElementBlock("div", {
759
+ key: weekday,
760
+ class: "rangepicker-weekday font-secondary"
761
+ }, toDisplayString(weekday), 1);
762
+ }), 128))
763
+ ]),
764
+ createElementVNode("div", _hoisted_15, [
765
+ (openBlock(true), createElementBlock(Fragment, null, renderList(monthData.days, (day) => {
766
+ return openBlock(), createElementBlock("button", {
767
+ key: day.date.unix(),
768
+ class: normalizeClass(getDayClasses(day)),
769
+ disabled: day.isDisabled,
770
+ "aria-label": day.date.format("MMMM D, YYYY"),
771
+ onClick: ($event) => selectDate(day),
772
+ onMouseenter: (e) => handleDayHover(day, e),
773
+ onMouseleave: handleDayLeave
774
+ }, [
775
+ createElementVNode("span", _hoisted_17, toDisplayString(day.date.date()), 1)
776
+ ], 42, _hoisted_16);
777
+ }), 128))
778
+ ])
779
+ ]);
780
+ }), 128))
781
+ ], 2),
782
+ !__props.autoApply ? (openBlock(), createElementBlock("div", _hoisted_18, [
783
+ createElementVNode("button", {
784
+ class: "px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 rounded-lg transition-colors font-secondary",
785
+ onClick: cancel
786
+ }, " Cancel "),
787
+ createElementVNode("button", {
788
+ class: "px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed font-secondary",
789
+ disabled: !localStartDate.value || !localEndDate.value,
790
+ onClick: apply
791
+ }, " Apply ", 8, _hoisted_19)
792
+ ])) : createCommentVNode("", true)
793
+ ]),
794
+ showTooltipComputed.value ? (openBlock(), createElementBlock("div", {
795
+ key: 0,
796
+ class: "rangepicker-tooltip",
797
+ style: normalizeStyle(tooltipStyle.value)
798
+ }, [
799
+ createElementVNode("div", _hoisted_20, toDisplayString(tooltipText.value), 1)
800
+ ], 4)) : createCommentVNode("", true)
801
+ ], 6)
802
+ ])) : createCommentVNode("", true)
803
+ ]),
804
+ _: 1
805
+ }, 8, ["name"])
806
+ ]);
807
+ };
808
+ }
809
+ });
810
+ const _export_sfc = (sfc, props) => {
811
+ const target = sfc.__vccOpts || sfc;
812
+ for (const [key, val] of props) {
813
+ target[key] = val;
814
+ }
815
+ return target;
816
+ };
817
+ const Rangepicker = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-540ea16c"]]);
818
+ const _hoisted_1 = ["id", "value", "placeholder", "readonly", "name"];
819
+ const _sfc_main = /* @__PURE__ */ defineComponent({
820
+ __name: "RangepickerInput",
821
+ props: {
822
+ id: {},
823
+ close: { type: Boolean },
824
+ modelValue: {},
825
+ name: {},
826
+ placeholder: { default: "Select dates" },
827
+ readonly: { type: Boolean, default: true },
828
+ class: {},
829
+ options: {},
830
+ variant: { default: "desktop" },
831
+ primaryColor: {},
832
+ secondaryColor: {}
833
+ },
834
+ emits: ["update:modelValue", "focusin"],
835
+ setup(__props, { emit: __emit }) {
836
+ function hexToRgb(hex) {
837
+ hex = hex.replace(/^#/, "");
838
+ if (hex.length === 3) {
839
+ hex = hex.split("").map((char) => char + char).join("");
840
+ }
841
+ if (hex.length !== 6) {
842
+ console.warn(`[Rangepicker] Invalid hex color: ${hex}`);
843
+ return null;
844
+ }
845
+ const r = parseInt(hex.substring(0, 2), 16);
846
+ const g = parseInt(hex.substring(2, 4), 16);
847
+ const b = parseInt(hex.substring(4, 6), 16);
848
+ if (isNaN(r) || isNaN(g) || isNaN(b)) {
849
+ return null;
850
+ }
851
+ return `${r} ${g} ${b}`;
852
+ }
853
+ const props = __props;
854
+ const emit = __emit;
855
+ const inputRef = ref(null);
856
+ const wrapperRef = ref(null);
857
+ const isOpen = ref(false);
858
+ function parseValue(value) {
859
+ if (!value)
860
+ return { startDate: "", endDate: "" };
861
+ const parts = value.split(" - ");
862
+ if (parts.length === 2) {
863
+ return {
864
+ startDate: parts[0].trim(),
865
+ endDate: parts[1].trim()
866
+ };
867
+ }
868
+ return { startDate: "", endDate: "" };
869
+ }
870
+ watch(() => props == null ? void 0 : props.close, (cur) => {
871
+ if (cur)
872
+ inputRef.value.blur();
873
+ });
874
+ const localValue = ref(parseValue(props.modelValue));
875
+ const displayValue = computed(() => {
876
+ return props.modelValue || "";
877
+ });
878
+ const inputClass = computed(() => {
879
+ return props.class || "form-control";
880
+ });
881
+ function openPicker() {
882
+ isOpen.value = true;
883
+ }
884
+ function onFocus() {
885
+ emit("focusin");
886
+ openPicker();
887
+ }
888
+ function handleUpdate(value) {
889
+ localValue.value = value;
890
+ const formatted = `${value.startDate} - ${value.endDate}`;
891
+ emit("update:modelValue", formatted);
892
+ }
893
+ watch(() => props.modelValue, (newVal) => {
894
+ localValue.value = parseValue(newVal);
895
+ });
896
+ const colorStyles = computed(() => {
897
+ const styles = {};
898
+ if (props.primaryColor) {
899
+ const rgb = hexToRgb(props.primaryColor);
900
+ if (rgb) {
901
+ styles["--color-primary"] = rgb;
902
+ }
903
+ }
904
+ if (props.secondaryColor) {
905
+ const rgb = hexToRgb(props.secondaryColor);
906
+ if (rgb) {
907
+ styles["--color-secondary"] = rgb;
908
+ }
909
+ }
910
+ return styles;
911
+ });
912
+ return (_ctx, _cache) => {
913
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
914
+ return openBlock(), createElementBlock("div", {
915
+ ref_key: "wrapperRef",
916
+ ref: wrapperRef,
917
+ class: "rangepicker-input-wrapper"
918
+ }, [
919
+ createElementVNode("input", {
920
+ id: __props.id,
921
+ ref_key: "inputRef",
922
+ ref: inputRef,
923
+ type: "text",
924
+ value: displayValue.value,
925
+ placeholder: __props.placeholder,
926
+ readonly: __props.readonly,
927
+ name: __props.name,
928
+ class: normalizeClass(inputClass.value),
929
+ onClick: openPicker,
930
+ onFocus
931
+ }, null, 42, _hoisted_1),
932
+ createVNode(Rangepicker, {
933
+ modelValue: localValue.value,
934
+ "onUpdate:modelValue": [
935
+ _cache[0] || (_cache[0] = ($event) => localValue.value = $event),
936
+ handleUpdate
937
+ ],
938
+ "is-open": isOpen.value,
939
+ "onUpdate:isOpen": _cache[1] || (_cache[1] = ($event) => isOpen.value = $event),
940
+ "trigger-element": inputRef.value,
941
+ "min-date": (_a = __props.options) == null ? void 0 : _a.minDate,
942
+ "max-date": (_b = __props.options) == null ? void 0 : _b.maxDate,
943
+ "min-days": (_c = __props.options) == null ? void 0 : _c.minDays,
944
+ "max-days": (_d = __props.options) == null ? void 0 : _d.maxDays,
945
+ "value-of-months": ((_e = __props.options) == null ? void 0 : _e.numberOfMonths) || 2,
946
+ "value-of-columns": ((_f = __props.options) == null ? void 0 : _f.numberOfColumns) || 2,
947
+ format: ((_g = __props.options) == null ? void 0 : _g.format) || "DD MMM YYYY",
948
+ "auto-apply": ((_h = __props.options) == null ? void 0 : _h.autoApply) !== false,
949
+ "show-tooltip": ((_i = __props.options) == null ? void 0 : _i.showTooltip) !== false,
950
+ variant: __props.variant,
951
+ close: props.close,
952
+ "color-styles": colorStyles.value
953
+ }, null, 8, ["modelValue", "is-open", "trigger-element", "min-date", "max-date", "min-days", "max-days", "value-of-months", "value-of-columns", "format", "auto-apply", "show-tooltip", "variant", "close", "color-styles"])
954
+ ], 512);
955
+ };
956
+ }
957
+ });
958
+ const RangepickerInput = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-25bfff76"]]);
959
+ function useRangepicker(triggerRef, options = {}) {
960
+ const isOpen = ref(false);
961
+ const dateRange = ref({ startDate: "", endDate: "" });
962
+ const open = () => {
963
+ isOpen.value = true;
964
+ };
965
+ const close = () => {
966
+ isOpen.value = false;
967
+ };
968
+ const toggle = () => {
969
+ isOpen.value = !isOpen.value;
970
+ };
971
+ return {
972
+ isOpen,
973
+ dateRange,
974
+ open,
975
+ close,
976
+ toggle,
977
+ options
978
+ };
979
+ }
980
+ export {
981
+ Rangepicker,
982
+ RangepickerInput,
983
+ RangepickerInput as default,
984
+ useRangepicker
985
+ };
986
+ //# sourceMappingURL=rangepicker.js.map