@rupe/v-datepicker 1.0.0-alpha.2 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -40,6 +40,8 @@ export declare const DatePicker: {
40
40
  readonly: boolean;
41
41
  isDateDisabled: Matcher;
42
42
  isDateUnavailable: Matcher;
43
+ minYear: number;
44
+ maxYear: number;
43
45
  closeOnSelect: boolean;
44
46
  }, false, {}, {}, GlobalComponents, GlobalDirectives, string, {}, any, ComponentProvideOptions, {
45
47
  P: {};
@@ -68,6 +70,8 @@ export declare const DatePicker: {
68
70
  readonly: boolean;
69
71
  isDateDisabled: Matcher;
70
72
  isDateUnavailable: Matcher;
73
+ minYear: number;
74
+ maxYear: number;
71
75
  closeOnSelect: boolean;
72
76
  }>;
73
77
  __isFragment?: never;
@@ -97,6 +101,8 @@ export declare const DatePicker: {
97
101
  readonly: boolean;
98
102
  isDateDisabled: Matcher;
99
103
  isDateUnavailable: Matcher;
104
+ minYear: number;
105
+ maxYear: number;
100
106
  closeOnSelect: boolean;
101
107
  }, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & VNodeProps & AllowedComponentProps & ComponentCustomProps & (new () => {
102
108
  $slots: {
@@ -527,10 +533,10 @@ export declare const DatePicker: {
527
533
  } & ComponentOptionsBase<Readonly< CalendarMonthYearOverlayProps> & Readonly<{}>, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, {}, {}, string, {}, GlobalComponents, GlobalDirectives, string, ComponentProvideOptions> & VNodeProps & AllowedComponentProps & ComponentCustomProps & (new () => {
528
534
  $slots: {
529
535
  default?(_: {
530
- months: MonthNameDateValue[];
536
+ months: MonthNameDateValue[][];
531
537
  years: {
532
538
  year: number;
533
- }[];
539
+ }[][];
534
540
  }): any;
535
541
  };
536
542
  });
package/dist/index.mjs CHANGED
@@ -6,6 +6,12 @@ import { defu } from "defu";
6
6
  import { unrefElement, computedEager, useVModel, defaultWindow, onKeyStroke, createGlobalState, useMounted } from "@vueuse/core";
7
7
  import { isClient, reactiveOmit } from "@vueuse/shared";
8
8
  import { offset, flip, shift, size, arrow, hide, limitShift, useFloating, autoUpdate } from "@floating-ui/vue";
9
+ function chunk$1(arr, size2) {
10
+ const result = [];
11
+ for (let i = 0; i < arr.length; i += size2)
12
+ result.push(arr.slice(i, i + size2));
13
+ return result;
14
+ }
9
15
  function createContext(providerComponentName, contextName) {
10
16
  const symbolDescription = typeof providerComponentName === "string" && !contextName ? `${providerComponentName}Context` : contextName;
11
17
  const injectionKey = Symbol(symbolDescription);
@@ -3177,6 +3183,9 @@ function handlePrevPage(date, prevPageFunc) {
3177
3183
  }
3178
3184
  function useCalendar(props) {
3179
3185
  const formatter = useDateFormatter(props.locale.value);
3186
+ watch(props.locale, (newLocale) => {
3187
+ formatter.setLocale(newLocale);
3188
+ });
3180
3189
  const headingFormatOptions = computed(() => {
3181
3190
  const options = {
3182
3191
  calendar: props.placeholder.value.calendar.identifier
@@ -3343,15 +3352,14 @@ function useCalendar(props) {
3343
3352
  }
3344
3353
  );
3345
3354
  const headingValue = computed(() => {
3346
- if (!grid.value.length) return "";
3347
- if (props.locale.value !== formatter.getLocale())
3348
- formatter.setLocale(props.locale.value);
3355
+ if (!grid.value.length || !grid.value[0]) return "";
3349
3356
  if (grid.value.length === 1) {
3350
3357
  const month = grid.value[0].value;
3351
3358
  return `${formatter.fullMonthAndYear(toDate(month), headingFormatOptions.value)}`;
3352
3359
  }
3353
3360
  const startMonth = toDate(grid.value[0].value);
3354
- const endMonth = toDate(grid.value[grid.value.length - 1].value);
3361
+ const lastMonth = grid.value[grid.value.length - 1];
3362
+ const endMonth = toDate(lastMonth ? lastMonth.value : grid.value[0].value);
3355
3363
  const startMonthName = formatter.fullMonth(
3356
3364
  startMonth,
3357
3365
  headingFormatOptions.value
@@ -3371,26 +3379,18 @@ function useCalendar(props) {
3371
3379
  const content = startMonthYear === endMonthYear ? `${startMonthName} - ${endMonthName} ${endMonthYear}` : `${startMonthName} ${startMonthYear} - ${endMonthName} ${endMonthYear}`;
3372
3380
  return content;
3373
3381
  });
3374
- const currentMonth = computed(() => {
3375
- if (!grid.value.length) return "";
3376
- if (props.locale.value !== formatter.getLocale())
3377
- formatter.setLocale(props.locale.value);
3378
- const date = grid.value[0]?.value;
3379
- if (date) {
3380
- return `${formatter.fullMonth(toDate(date), headingFormatOptions.value)}`;
3381
- }
3382
- return "";
3383
- });
3384
- const currentYear = computed(() => {
3382
+ function formatGridDate(fn) {
3385
3383
  if (!grid.value.length) return "";
3386
- if (props.locale.value !== formatter.getLocale())
3387
- formatter.setLocale(props.locale.value);
3388
3384
  const date = grid.value[0]?.value;
3389
- if (date) {
3390
- return `${formatter.fullYear(toDate(date), headingFormatOptions.value)}`;
3391
- }
3392
- return "";
3393
- });
3385
+ if (!date) return "";
3386
+ return fn(toDate(date));
3387
+ }
3388
+ const currentMonth = computed(
3389
+ () => formatGridDate((d) => formatter.fullMonth(d, headingFormatOptions.value))
3390
+ );
3391
+ const currentYear = computed(
3392
+ () => formatGridDate((d) => formatter.fullYear(d, headingFormatOptions.value))
3393
+ );
3394
3394
  const months = computed(() => {
3395
3395
  const startDate = props.placeholder.value.set({ month: 1 });
3396
3396
  const monthsArray = createMonths({
@@ -3407,8 +3407,8 @@ function useCalendar(props) {
3407
3407
  });
3408
3408
  });
3409
3409
  const years = computed(() => {
3410
- const startDate = props.placeholder.value.set({ year: 1875 });
3411
- const endDate = props.placeholder.value.set({ year: 2100 });
3410
+ const startDate = props.placeholder.value.set({ year: props.minYear.value });
3411
+ const endDate = props.placeholder.value.set({ year: props.maxYear.value });
3412
3412
  return createYearRange({ start: startDate, end: endDate });
3413
3413
  });
3414
3414
  const fullCalendarLabel = computed(
@@ -3467,6 +3467,8 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
3467
3467
  modelValue: {},
3468
3468
  multiple: { type: Boolean, default: false },
3469
3469
  disableDaysOutsideCurrentView: { type: Boolean, default: false },
3470
+ minYear: { default: 1900 },
3471
+ maxYear: { default: 2100 },
3470
3472
  asChild: { type: Boolean },
3471
3473
  as: { default: "div" }
3472
3474
  },
@@ -3495,7 +3497,9 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
3495
3497
  prevPage: propsPrevPage,
3496
3498
  dir: propDir,
3497
3499
  locale: propLocale,
3498
- disableDaysOutsideCurrentView
3500
+ disableDaysOutsideCurrentView,
3501
+ minYear,
3502
+ maxYear
3499
3503
  } = toRefs(props);
3500
3504
  const { primitiveElement, currentElement: parentElement } = usePrimitiveElement();
3501
3505
  const locale = useLocale(propLocale);
@@ -3549,7 +3553,9 @@ const _sfc_main$E = /* @__PURE__ */ defineComponent({
3549
3553
  isDateUnavailable: propsIsDateUnavailable.value,
3550
3554
  calendarLabel,
3551
3555
  nextPage: propsNextPage,
3552
- prevPage: propsPrevPage
3556
+ prevPage: propsPrevPage,
3557
+ minYear,
3558
+ maxYear
3553
3559
  });
3554
3560
  const { isInvalid, isDateSelected } = useCalendarState({
3555
3561
  date: modelValue,
@@ -4139,6 +4145,10 @@ const _sfc_main$r = /* @__PURE__ */ defineComponent({
4139
4145
  };
4140
4146
  }
4141
4147
  });
4148
+ const [
4149
+ injectCalendarMonthYearOverlayContext,
4150
+ provideCalendarMonthYearOverlayContext
4151
+ ] = createContext("CalendarMonthYearOverlay");
4142
4152
  const _sfc_main$q = /* @__PURE__ */ defineComponent({
4143
4153
  ...{
4144
4154
  inheritAttrs: false
@@ -4146,20 +4156,27 @@ const _sfc_main$q = /* @__PURE__ */ defineComponent({
4146
4156
  __name: "CalendarMonthYearOverlay",
4147
4157
  props: {
4148
4158
  type: {},
4159
+ itemsPerRow: { default: 4 },
4149
4160
  asChild: { type: Boolean },
4150
4161
  as: {}
4151
4162
  },
4152
4163
  setup(__props) {
4153
4164
  const props = __props;
4165
+ const itemsPerRow = computed(() => props.itemsPerRow);
4154
4166
  const rootContext = injectCalendarRootContext();
4155
- const months = computed(() => rootContext.months.value);
4156
- const years = computed(() => rootContext.years.value);
4167
+ const months = computed(
4168
+ () => chunk$1(rootContext.months.value, props.itemsPerRow)
4169
+ );
4170
+ const years = computed(() => chunk$1(rootContext.years.value, props.itemsPerRow));
4157
4171
  const isOpen = computed(
4158
4172
  () => rootContext.monthYearOverlayState.value === props.type
4159
4173
  );
4160
4174
  function onEscapeKeyDown() {
4161
4175
  rootContext.monthYearOverlayState.value = false;
4162
4176
  }
4177
+ provideCalendarMonthYearOverlayContext({
4178
+ itemsPerRow
4179
+ });
4163
4180
  return (_ctx, _cache) => {
4164
4181
  return isOpen.value ? (openBlock(), createBlock(_sfc_main$O, {
4165
4182
  key: 0,
@@ -4176,8 +4193,7 @@ const _sfc_main$q = /* @__PURE__ */ defineComponent({
4176
4193
  left: "0",
4177
4194
  zIndex: "1000"
4178
4195
  },
4179
- role: "dialog",
4180
- tabindex: "0"
4196
+ role: "dialog"
4181
4197
  }), {
4182
4198
  default: withCtx(() => [
4183
4199
  renderSlot(_ctx.$slots, "default", {
@@ -4230,6 +4246,8 @@ const _sfc_main$p = /* @__PURE__ */ defineComponent({
4230
4246
  fixedWeeks: { type: Boolean, default: false },
4231
4247
  numberOfMonths: { default: 1 },
4232
4248
  preventDeselect: { type: Boolean, default: false },
4249
+ minYear: { default: 1900 },
4250
+ maxYear: { default: 2100 },
4233
4251
  closeOnSelect: { type: Boolean, default: false }
4234
4252
  },
4235
4253
  emits: ["update:modelValue", "update:placeholder", "update:open"],
@@ -4260,7 +4278,9 @@ const _sfc_main$p = /* @__PURE__ */ defineComponent({
4260
4278
  defaultValue,
4261
4279
  dir: propDir,
4262
4280
  step,
4263
- closeOnSelect
4281
+ closeOnSelect,
4282
+ minYear,
4283
+ maxYear
4264
4284
  } = toRefs(props);
4265
4285
  const dir = useDirection(propDir);
4266
4286
  const modelValue = useVModel(props, "modelValue", emits, {
@@ -4331,7 +4351,9 @@ const _sfc_main$p = /* @__PURE__ */ defineComponent({
4331
4351
  onPlaceholderChange(date) {
4332
4352
  placeholder.value = date.copy();
4333
4353
  },
4334
- closeOnSelect
4354
+ closeOnSelect,
4355
+ minYear,
4356
+ maxYear
4335
4357
  });
4336
4358
  return (_ctx, _cache) => {
4337
4359
  return openBlock(), createBlock(unref(_sfc_main$S), {
@@ -4366,7 +4388,9 @@ const _sfc_main$o = /* @__PURE__ */ defineComponent({
4366
4388
  numberOfMonths: unref(rootContext).numberOfMonths.value,
4367
4389
  readonly: unref(rootContext).readonly.value,
4368
4390
  preventDeselect: unref(rootContext).preventDeselect.value,
4369
- dir: unref(rootContext).dir.value
4391
+ dir: unref(rootContext).dir.value,
4392
+ minYear: unref(rootContext).minYear.value,
4393
+ maxYear: unref(rootContext).maxYear.value
4370
4394
  }, {
4371
4395
  "model-value": unref(rootContext).modelValue.value,
4372
4396
  placeholder: unref(rootContext).placeholder.value,
@@ -5125,6 +5149,7 @@ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
5125
5149
  __name: "DatePickerMonthYearOverlay",
5126
5150
  props: {
5127
5151
  type: {},
5152
+ itemsPerRow: {},
5128
5153
  asChild: { type: Boolean },
5129
5154
  as: {}
5130
5155
  },
@@ -5147,25 +5172,125 @@ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
5147
5172
  __name: "CalendarOverlayItem",
5148
5173
  props: {
5149
5174
  date: {},
5175
+ disabled: { type: Boolean },
5176
+ type: {},
5150
5177
  asChild: { type: Boolean },
5151
- as: { default: "button" }
5178
+ as: { default: "div" }
5152
5179
  },
5153
5180
  setup(__props) {
5154
5181
  const props = __props;
5155
5182
  const rootContext = injectCalendarRootContext();
5183
+ const years = computed(() => rootContext.years.value);
5184
+ const overlayContext = injectCalendarMonthYearOverlayContext();
5185
+ const dataValue = computed(() => `${props.type}-${props.date[props.type]}`);
5186
+ const { primitiveElement, currentElement } = usePrimitiveElement();
5187
+ const isFocusedDate = computed(() => {
5188
+ if (props.type === "month")
5189
+ return rootContext.currentMonth.value === props.date.monthName;
5190
+ return rootContext.currentYear.value === props.date.year.toString();
5191
+ });
5192
+ const ariaLabel = computed(() => {
5193
+ if (props.type === "month") return props.date.monthName;
5194
+ return props.date.year.toString();
5195
+ });
5196
+ onMounted(() => {
5197
+ if (isFocusedDate.value) {
5198
+ nextTick(() => {
5199
+ currentElement.value?.focus();
5200
+ currentElement.value?.scrollIntoView({ block: "nearest" });
5201
+ });
5202
+ }
5203
+ });
5204
+ function isDateSelectable(date) {
5205
+ return !rootContext.isDateDisabled(date) && !rootContext.isDateUnavailable?.(date);
5206
+ }
5207
+ function closeOverlay() {
5208
+ rootContext.monthYearOverlayState.value = false;
5209
+ }
5156
5210
  function handleClick() {
5157
- if (rootContext.isDateDisabled(props.date) || rootContext.isDateUnavailable?.(props.date))
5158
- return;
5211
+ if (!isDateSelectable(props.date)) return;
5159
5212
  rootContext.onDateChange(props.date);
5160
- rootContext.monthYearOverlayState.value = false;
5213
+ closeOverlay();
5214
+ }
5215
+ const kbd = useKbd();
5216
+ function handleKeydown(e) {
5217
+ if (props.disabled) return;
5218
+ e.preventDefault();
5219
+ e.stopPropagation();
5220
+ const parentElement = rootContext.parentElement.value;
5221
+ const itemsPerRow = overlayContext.itemsPerRow.value;
5222
+ const sign = rootContext.dir.value === "rtl" ? -1 : 1;
5223
+ const currentValue = props.date[props.type];
5224
+ function focusItem(value) {
5225
+ const candidate = parentElement.querySelector(
5226
+ `[data-value='${props.type}-${value}']`
5227
+ );
5228
+ candidate?.focus();
5229
+ candidate?.scrollIntoView({ block: "nearest" });
5230
+ }
5231
+ function shiftFocus(add) {
5232
+ let nextValue = currentValue + add;
5233
+ if (props.type === "month") {
5234
+ nextValue = (nextValue - 1 + 12) % 12 + 1;
5235
+ } else {
5236
+ const minYear = years.value[0].year;
5237
+ const maxYear = years.value[years.value.length - 1].year;
5238
+ nextValue = Math.max(minYear, Math.min(nextValue, maxYear));
5239
+ }
5240
+ focusItem(nextValue);
5241
+ }
5242
+ switch (e.code) {
5243
+ case kbd.ARROW_RIGHT:
5244
+ shiftFocus(sign);
5245
+ break;
5246
+ case kbd.ARROW_LEFT:
5247
+ shiftFocus(-sign);
5248
+ break;
5249
+ case kbd.ARROW_UP:
5250
+ shiftFocus(-itemsPerRow);
5251
+ break;
5252
+ case kbd.ARROW_DOWN:
5253
+ shiftFocus(itemsPerRow);
5254
+ break;
5255
+ case kbd.HOME: {
5256
+ const firstValue = props.type === "month" ? 1 : years.value[0].year;
5257
+ focusItem(firstValue);
5258
+ break;
5259
+ }
5260
+ case kbd.END: {
5261
+ const lastValue = props.type === "month" ? 12 : years.value[years.value.length - 1].year;
5262
+ focusItem(lastValue);
5263
+ break;
5264
+ }
5265
+ case kbd.ENTER:
5266
+ case kbd.SPACE_CODE:
5267
+ if (isDateSelectable(props.date)) {
5268
+ rootContext.onDateChange(props.date);
5269
+ closeOverlay();
5270
+ }
5271
+ }
5161
5272
  }
5162
5273
  return (_ctx, _cache) => {
5163
- return openBlock(), createBlock(unref(Primitive), mergeProps(props, { onClick: handleClick }), {
5274
+ return openBlock(), createBlock(unref(Primitive), mergeProps(props, {
5275
+ onClick: handleClick,
5276
+ ref_key: "primitiveElement",
5277
+ ref: primitiveElement,
5278
+ role: "button",
5279
+ "aria-label": ariaLabel.value,
5280
+ "aria-disabled": __props.disabled,
5281
+ "data-value": dataValue.value,
5282
+ onKeydown: [
5283
+ withKeys(handleKeydown, ["up", "down", "left", "right", "space", "enter", "home", "end"]),
5284
+ _cache[0] || (_cache[0] = withKeys(withModifiers(() => {
5285
+ }, ["prevent"]), ["enter"]))
5286
+ ],
5287
+ tabindex: isFocusedDate.value ? 0 : -1
5288
+ }), {
5164
5289
  default: withCtx(() => [
5165
5290
  renderSlot(_ctx.$slots, "default")
5166
5291
  ]),
5167
5292
  _: 3
5168
- }, 16);
5293
+ }, 16, ["aria-label", "aria-disabled", "data-value", "tabindex"]);
5169
5294
  };
5170
5295
  }
5171
5296
  });
@@ -5173,6 +5298,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
5173
5298
  __name: "DatePickerOverlayItem",
5174
5299
  props: {
5175
5300
  date: {},
5301
+ disabled: { type: Boolean },
5302
+ type: {},
5176
5303
  asChild: { type: Boolean },
5177
5304
  as: {}
5178
5305
  },