@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/README.md CHANGED
@@ -97,7 +97,9 @@ import { DatePicker } from '@rupe/v-datepicker'
97
97
 
98
98
  ## Playground
99
99
 
100
- The repository includes a playground project built with **Nuxt** and **Tailwind CSS** to test the library locally.
100
+ You can check out the package in action on [StackBlitz](https://stackblitz.com/edit/nuxt-starter-tjmzbch9?file=package.json).
101
+
102
+ The repository also includes a playground project built with **Nuxt** and **Tailwind CSS** to test the library locally.
101
103
 
102
104
  ### Running the Playground
103
105
 
@@ -1,26 +1,25 @@
1
+ import { ComputedRef, DefineComponent, ComponentOptionsMixin, PublicProps, ComponentProvideOptions, Ref } from 'vue';
1
2
  import { PrimitiveProps } from '../Primitive';
2
3
  import { MonthNameDateValue } from './CalendarRoot.vue';
3
- import { Ref, DefineComponent, ComponentOptionsMixin, PublicProps, ComponentProvideOptions } from 'vue';
4
4
  export interface CalendarMonthYearOverlayProps extends PrimitiveProps {
5
5
  type: "month" | "year";
6
+ itemsPerRow?: number;
6
7
  }
7
- declare function __VLS_template(): {
8
- attrs: Partial<{}>;
9
- slots: {
10
- default?(_: {
11
- months: MonthNameDateValue[];
12
- years: {
13
- year: number;
14
- }[];
15
- state: Ref<false | "month" | "year", false | "month" | "year">;
16
- }): any;
17
- };
18
- refs: {};
19
- rootEl: any;
8
+ type CalendarMonthYearOverlayContext = {
9
+ itemsPerRow: ComputedRef<number>;
20
10
  };
21
- type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
22
- declare const __VLS_component: DefineComponent<CalendarMonthYearOverlayProps, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<CalendarMonthYearOverlayProps> & Readonly<{}>, {}, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
23
- declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
11
+ export declare const injectCalendarMonthYearOverlayContext: <T extends CalendarMonthYearOverlayContext | null | undefined = CalendarMonthYearOverlayContext>(fallback?: T | undefined) => T extends null ? CalendarMonthYearOverlayContext | null : CalendarMonthYearOverlayContext, provideCalendarMonthYearOverlayContext: (contextValue: CalendarMonthYearOverlayContext) => CalendarMonthYearOverlayContext;
12
+ declare const _default: __VLS_WithTemplateSlots< DefineComponent<CalendarMonthYearOverlayProps, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<CalendarMonthYearOverlayProps> & Readonly<{}>, {
13
+ itemsPerRow: number;
14
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>, {
15
+ default?(_: {
16
+ months: MonthNameDateValue[][];
17
+ years: {
18
+ year: number;
19
+ }[][];
20
+ state: Ref<false | "month" | "year", false | "month" | "year">;
21
+ }): any;
22
+ }>;
24
23
  export default _default;
25
24
  type __VLS_WithTemplateSlots<T, S> = T & {
26
25
  new (): {
@@ -1,21 +1,99 @@
1
1
  import { DateValue } from '@internationalized/date';
2
2
  import { PrimitiveProps, AsTag } from '../Primitive';
3
- import { DefineComponent, ComponentOptionsMixin, PublicProps, Component, ComponentProvideOptions } from 'vue';
3
+ import { CreateComponentPublicInstanceWithMixins, ExtractPropTypes, PropType, Component, VNode, RendererNode, RendererElement, ComponentOptionsMixin, PublicProps, GlobalComponents, GlobalDirectives, ComponentProvideOptions, DefineComponent } from 'vue';
4
4
  export interface CalendarOverlayItemProps extends PrimitiveProps {
5
- date: DateValue;
5
+ date: DateValue & {
6
+ monthName: string;
7
+ };
8
+ disabled?: boolean;
9
+ type: "month" | "year";
6
10
  }
7
11
  declare function __VLS_template(): {
8
12
  attrs: Partial<{}>;
9
13
  slots: {
10
14
  default?(_: {}): any;
11
15
  };
12
- refs: {};
16
+ refs: {
17
+ primitiveElement: CreateComponentPublicInstanceWithMixins<Readonly< ExtractPropTypes<{
18
+ asChild: {
19
+ type: BooleanConstructor;
20
+ default: boolean;
21
+ };
22
+ as: {
23
+ type: PropType< AsTag | Component>;
24
+ default: string;
25
+ };
26
+ }>> & Readonly<{}>, () => VNode<RendererNode, RendererElement, {
27
+ [key: string]: any;
28
+ }>, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, PublicProps, {
29
+ asChild: boolean;
30
+ as: AsTag | Component;
31
+ }, true, {}, {}, GlobalComponents, GlobalDirectives, string, {}, any, ComponentProvideOptions, {
32
+ P: {};
33
+ B: {};
34
+ D: {};
35
+ C: {};
36
+ M: {};
37
+ Defaults: {};
38
+ }, Readonly< ExtractPropTypes<{
39
+ asChild: {
40
+ type: BooleanConstructor;
41
+ default: boolean;
42
+ };
43
+ as: {
44
+ type: PropType< AsTag | Component>;
45
+ default: string;
46
+ };
47
+ }>> & Readonly<{}>, () => VNode<RendererNode, RendererElement, {
48
+ [key: string]: any;
49
+ }>, {}, {}, {}, {
50
+ asChild: boolean;
51
+ as: AsTag | Component;
52
+ }> | null;
53
+ };
13
54
  rootEl: any;
14
55
  };
15
56
  type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
16
57
  declare const __VLS_component: DefineComponent<CalendarOverlayItemProps, {}, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, string, PublicProps, Readonly<CalendarOverlayItemProps> & Readonly<{}>, {
17
58
  as: AsTag | Component;
18
- }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>;
59
+ }, {}, {}, {}, string, ComponentProvideOptions, false, {
60
+ primitiveElement: CreateComponentPublicInstanceWithMixins<Readonly< ExtractPropTypes<{
61
+ asChild: {
62
+ type: BooleanConstructor;
63
+ default: boolean;
64
+ };
65
+ as: {
66
+ type: PropType< AsTag | Component>;
67
+ default: string;
68
+ };
69
+ }>> & Readonly<{}>, () => VNode<RendererNode, RendererElement, {
70
+ [key: string]: any;
71
+ }>, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, {}, PublicProps, {
72
+ asChild: boolean;
73
+ as: AsTag | Component;
74
+ }, true, {}, {}, GlobalComponents, GlobalDirectives, string, {}, any, ComponentProvideOptions, {
75
+ P: {};
76
+ B: {};
77
+ D: {};
78
+ C: {};
79
+ M: {};
80
+ Defaults: {};
81
+ }, Readonly< ExtractPropTypes<{
82
+ asChild: {
83
+ type: BooleanConstructor;
84
+ default: boolean;
85
+ };
86
+ as: {
87
+ type: PropType< AsTag | Component>;
88
+ default: string;
89
+ };
90
+ }>> & Readonly<{}>, () => VNode<RendererNode, RendererElement, {
91
+ [key: string]: any;
92
+ }>, {}, {}, {}, {
93
+ asChild: boolean;
94
+ as: AsTag | Component;
95
+ }> | null;
96
+ }, any>;
19
97
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
20
98
  export default _default;
21
99
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -99,6 +99,10 @@ export interface CalendarRootProps extends PrimitiveProps {
99
99
  multiple?: boolean;
100
100
  /** Whether or not to disable days outside the current view. */
101
101
  disableDaysOutsideCurrentView?: boolean;
102
+ /** The minimum year displayed in the year overlay */
103
+ minYear?: number;
104
+ /** The maximum year displayed in the year overlay */
105
+ maxYear?: number;
102
106
  }
103
107
  export type CalendarRootEmits = {
104
108
  /** Event handler called whenever the model value changes */
@@ -130,6 +134,8 @@ declare const _default: __VLS_WithTemplateSlots< DefineComponent<CalendarRootPro
130
134
  isDateDisabled: Matcher;
131
135
  isDateUnavailable: Matcher;
132
136
  disableDaysOutsideCurrentView: boolean;
137
+ minYear: number;
138
+ maxYear: number;
133
139
  }, {}, {}, {}, string, ComponentProvideOptions, false, {
134
140
  primitiveElement: CreateComponentPublicInstanceWithMixins<Readonly< ExtractPropTypes<{
135
141
  asChild: {
@@ -18,6 +18,8 @@ export type UseCalendarProps = {
18
18
  calendarLabel: Ref<string | undefined>;
19
19
  nextPage: Ref<((placeholder: DateValue) => DateValue) | undefined>;
20
20
  prevPage: Ref<((placeholder: DateValue) => DateValue) | undefined>;
21
+ minYear: Ref<number>;
22
+ maxYear: Ref<number>;
21
23
  };
22
24
  export type UseCalendarStateProps = {
23
25
  isDateDisabled: Matcher;
@@ -6,10 +6,10 @@ declare function __VLS_template(): {
6
6
  attrs: Partial<{}>;
7
7
  slots: {
8
8
  default?(_: {
9
- months: MonthNameDateValue[];
9
+ months: MonthNameDateValue[][];
10
10
  years: {
11
11
  year: number;
12
- }[];
12
+ }[][];
13
13
  }): any;
14
14
  };
15
15
  refs: {};
@@ -36,8 +36,10 @@ type DatePickerRootContext = {
36
36
  dir: Ref<Direction>;
37
37
  step: Ref<DateStep | undefined>;
38
38
  closeOnSelect: Ref<boolean>;
39
+ minYear: Ref<number>;
40
+ maxYear: Ref<number>;
39
41
  };
40
- export type DatePickerRootProps = DateFieldRootProps & PopoverRootProps & Pick<CalendarRootProps, "isDateDisabled" | "pagedNavigation" | "weekStartsOn" | "weekdayFormat" | "fixedWeeks" | "numberOfMonths" | "preventDeselect"> & {
42
+ export type DatePickerRootProps = DateFieldRootProps & PopoverRootProps & Pick<CalendarRootProps, "isDateDisabled" | "pagedNavigation" | "weekStartsOn" | "weekdayFormat" | "fixedWeeks" | "numberOfMonths" | "preventDeselect" | "minYear" | "maxYear"> & {
41
43
  /** Whether or not to close the popover on date select */
42
44
  closeOnSelect?: boolean;
43
45
  };
@@ -72,6 +74,8 @@ declare const _default: __VLS_WithTemplateSlots< DefineComponent<DatePickerRootP
72
74
  readonly: boolean;
73
75
  isDateDisabled: Matcher;
74
76
  isDateUnavailable: Matcher;
77
+ minYear: number;
78
+ maxYear: number;
75
79
  closeOnSelect: boolean;
76
80
  }, {}, {}, {}, string, ComponentProvideOptions, false, {}, any>, {
77
81
  default?(_: {}): any;
package/dist/index.cjs CHANGED
@@ -24,6 +24,12 @@ function _interopNamespaceDefault(e) {
24
24
  return Object.freeze(n);
25
25
  }
26
26
  const vue__namespace = /* @__PURE__ */ _interopNamespaceDefault(vue);
27
+ function chunk$1(arr, size) {
28
+ const result = [];
29
+ for (let i = 0; i < arr.length; i += size)
30
+ result.push(arr.slice(i, i + size));
31
+ return result;
32
+ }
27
33
  function createContext(providerComponentName, contextName) {
28
34
  const symbolDescription = typeof providerComponentName === "string" && !contextName ? `${providerComponentName}Context` : contextName;
29
35
  const injectionKey = Symbol(symbolDescription);
@@ -3195,6 +3201,9 @@ function handlePrevPage(date2, prevPageFunc) {
3195
3201
  }
3196
3202
  function useCalendar(props) {
3197
3203
  const formatter = useDateFormatter(props.locale.value);
3204
+ vue.watch(props.locale, (newLocale) => {
3205
+ formatter.setLocale(newLocale);
3206
+ });
3198
3207
  const headingFormatOptions = vue.computed(() => {
3199
3208
  const options = {
3200
3209
  calendar: props.placeholder.value.calendar.identifier
@@ -3361,15 +3370,14 @@ function useCalendar(props) {
3361
3370
  }
3362
3371
  );
3363
3372
  const headingValue = vue.computed(() => {
3364
- if (!grid.value.length) return "";
3365
- if (props.locale.value !== formatter.getLocale())
3366
- formatter.setLocale(props.locale.value);
3373
+ if (!grid.value.length || !grid.value[0]) return "";
3367
3374
  if (grid.value.length === 1) {
3368
3375
  const month = grid.value[0].value;
3369
3376
  return `${formatter.fullMonthAndYear(toDate(month), headingFormatOptions.value)}`;
3370
3377
  }
3371
3378
  const startMonth = toDate(grid.value[0].value);
3372
- const endMonth = toDate(grid.value[grid.value.length - 1].value);
3379
+ const lastMonth = grid.value[grid.value.length - 1];
3380
+ const endMonth = toDate(lastMonth ? lastMonth.value : grid.value[0].value);
3373
3381
  const startMonthName = formatter.fullMonth(
3374
3382
  startMonth,
3375
3383
  headingFormatOptions.value
@@ -3389,26 +3397,18 @@ function useCalendar(props) {
3389
3397
  const content = startMonthYear === endMonthYear ? `${startMonthName} - ${endMonthName} ${endMonthYear}` : `${startMonthName} ${startMonthYear} - ${endMonthName} ${endMonthYear}`;
3390
3398
  return content;
3391
3399
  });
3392
- const currentMonth = vue.computed(() => {
3393
- if (!grid.value.length) return "";
3394
- if (props.locale.value !== formatter.getLocale())
3395
- formatter.setLocale(props.locale.value);
3396
- const date2 = grid.value[0]?.value;
3397
- if (date2) {
3398
- return `${formatter.fullMonth(toDate(date2), headingFormatOptions.value)}`;
3399
- }
3400
- return "";
3401
- });
3402
- const currentYear = vue.computed(() => {
3400
+ function formatGridDate(fn) {
3403
3401
  if (!grid.value.length) return "";
3404
- if (props.locale.value !== formatter.getLocale())
3405
- formatter.setLocale(props.locale.value);
3406
3402
  const date2 = grid.value[0]?.value;
3407
- if (date2) {
3408
- return `${formatter.fullYear(toDate(date2), headingFormatOptions.value)}`;
3409
- }
3410
- return "";
3411
- });
3403
+ if (!date2) return "";
3404
+ return fn(toDate(date2));
3405
+ }
3406
+ const currentMonth = vue.computed(
3407
+ () => formatGridDate((d) => formatter.fullMonth(d, headingFormatOptions.value))
3408
+ );
3409
+ const currentYear = vue.computed(
3410
+ () => formatGridDate((d) => formatter.fullYear(d, headingFormatOptions.value))
3411
+ );
3412
3412
  const months = vue.computed(() => {
3413
3413
  const startDate = props.placeholder.value.set({ month: 1 });
3414
3414
  const monthsArray = createMonths({
@@ -3425,8 +3425,8 @@ function useCalendar(props) {
3425
3425
  });
3426
3426
  });
3427
3427
  const years = vue.computed(() => {
3428
- const startDate = props.placeholder.value.set({ year: 1875 });
3429
- const endDate = props.placeholder.value.set({ year: 2100 });
3428
+ const startDate = props.placeholder.value.set({ year: props.minYear.value });
3429
+ const endDate = props.placeholder.value.set({ year: props.maxYear.value });
3430
3430
  return createYearRange({ start: startDate, end: endDate });
3431
3431
  });
3432
3432
  const fullCalendarLabel = vue.computed(
@@ -3485,6 +3485,8 @@ const _sfc_main$E = /* @__PURE__ */ vue.defineComponent({
3485
3485
  modelValue: {},
3486
3486
  multiple: { type: Boolean, default: false },
3487
3487
  disableDaysOutsideCurrentView: { type: Boolean, default: false },
3488
+ minYear: { default: 1900 },
3489
+ maxYear: { default: 2100 },
3488
3490
  asChild: { type: Boolean },
3489
3491
  as: { default: "div" }
3490
3492
  },
@@ -3513,7 +3515,9 @@ const _sfc_main$E = /* @__PURE__ */ vue.defineComponent({
3513
3515
  prevPage: propsPrevPage,
3514
3516
  dir: propDir,
3515
3517
  locale: propLocale,
3516
- disableDaysOutsideCurrentView
3518
+ disableDaysOutsideCurrentView,
3519
+ minYear,
3520
+ maxYear
3517
3521
  } = vue.toRefs(props);
3518
3522
  const { primitiveElement, currentElement: parentElement } = usePrimitiveElement();
3519
3523
  const locale = useLocale(propLocale);
@@ -3567,7 +3571,9 @@ const _sfc_main$E = /* @__PURE__ */ vue.defineComponent({
3567
3571
  isDateUnavailable: propsIsDateUnavailable.value,
3568
3572
  calendarLabel,
3569
3573
  nextPage: propsNextPage,
3570
- prevPage: propsPrevPage
3574
+ prevPage: propsPrevPage,
3575
+ minYear,
3576
+ maxYear
3571
3577
  });
3572
3578
  const { isInvalid, isDateSelected } = useCalendarState({
3573
3579
  date: modelValue,
@@ -4157,6 +4163,10 @@ const _sfc_main$r = /* @__PURE__ */ vue.defineComponent({
4157
4163
  };
4158
4164
  }
4159
4165
  });
4166
+ const [
4167
+ injectCalendarMonthYearOverlayContext,
4168
+ provideCalendarMonthYearOverlayContext
4169
+ ] = createContext("CalendarMonthYearOverlay");
4160
4170
  const _sfc_main$q = /* @__PURE__ */ vue.defineComponent({
4161
4171
  ...{
4162
4172
  inheritAttrs: false
@@ -4164,20 +4174,27 @@ const _sfc_main$q = /* @__PURE__ */ vue.defineComponent({
4164
4174
  __name: "CalendarMonthYearOverlay",
4165
4175
  props: {
4166
4176
  type: {},
4177
+ itemsPerRow: { default: 4 },
4167
4178
  asChild: { type: Boolean },
4168
4179
  as: {}
4169
4180
  },
4170
4181
  setup(__props) {
4171
4182
  const props = __props;
4183
+ const itemsPerRow = vue.computed(() => props.itemsPerRow);
4172
4184
  const rootContext = injectCalendarRootContext();
4173
- const months = vue.computed(() => rootContext.months.value);
4174
- const years = vue.computed(() => rootContext.years.value);
4185
+ const months = vue.computed(
4186
+ () => chunk$1(rootContext.months.value, props.itemsPerRow)
4187
+ );
4188
+ const years = vue.computed(() => chunk$1(rootContext.years.value, props.itemsPerRow));
4175
4189
  const isOpen = vue.computed(
4176
4190
  () => rootContext.monthYearOverlayState.value === props.type
4177
4191
  );
4178
4192
  function onEscapeKeyDown() {
4179
4193
  rootContext.monthYearOverlayState.value = false;
4180
4194
  }
4195
+ provideCalendarMonthYearOverlayContext({
4196
+ itemsPerRow
4197
+ });
4181
4198
  return (_ctx, _cache) => {
4182
4199
  return isOpen.value ? (vue.openBlock(), vue.createBlock(_sfc_main$O, {
4183
4200
  key: 0,
@@ -4194,8 +4211,7 @@ const _sfc_main$q = /* @__PURE__ */ vue.defineComponent({
4194
4211
  left: "0",
4195
4212
  zIndex: "1000"
4196
4213
  },
4197
- role: "dialog",
4198
- tabindex: "0"
4214
+ role: "dialog"
4199
4215
  }), {
4200
4216
  default: vue.withCtx(() => [
4201
4217
  vue.renderSlot(_ctx.$slots, "default", {
@@ -4248,6 +4264,8 @@ const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
4248
4264
  fixedWeeks: { type: Boolean, default: false },
4249
4265
  numberOfMonths: { default: 1 },
4250
4266
  preventDeselect: { type: Boolean, default: false },
4267
+ minYear: { default: 1900 },
4268
+ maxYear: { default: 2100 },
4251
4269
  closeOnSelect: { type: Boolean, default: false }
4252
4270
  },
4253
4271
  emits: ["update:modelValue", "update:placeholder", "update:open"],
@@ -4278,7 +4296,9 @@ const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
4278
4296
  defaultValue,
4279
4297
  dir: propDir,
4280
4298
  step,
4281
- closeOnSelect
4299
+ closeOnSelect,
4300
+ minYear,
4301
+ maxYear
4282
4302
  } = vue.toRefs(props);
4283
4303
  const dir = useDirection(propDir);
4284
4304
  const modelValue = core.useVModel(props, "modelValue", emits, {
@@ -4349,7 +4369,9 @@ const _sfc_main$p = /* @__PURE__ */ vue.defineComponent({
4349
4369
  onPlaceholderChange(date2) {
4350
4370
  placeholder.value = date2.copy();
4351
4371
  },
4352
- closeOnSelect
4372
+ closeOnSelect,
4373
+ minYear,
4374
+ maxYear
4353
4375
  });
4354
4376
  return (_ctx, _cache) => {
4355
4377
  return vue.openBlock(), vue.createBlock(vue.unref(_sfc_main$S), {
@@ -4384,7 +4406,9 @@ const _sfc_main$o = /* @__PURE__ */ vue.defineComponent({
4384
4406
  numberOfMonths: vue.unref(rootContext).numberOfMonths.value,
4385
4407
  readonly: vue.unref(rootContext).readonly.value,
4386
4408
  preventDeselect: vue.unref(rootContext).preventDeselect.value,
4387
- dir: vue.unref(rootContext).dir.value
4409
+ dir: vue.unref(rootContext).dir.value,
4410
+ minYear: vue.unref(rootContext).minYear.value,
4411
+ maxYear: vue.unref(rootContext).maxYear.value
4388
4412
  }, {
4389
4413
  "model-value": vue.unref(rootContext).modelValue.value,
4390
4414
  placeholder: vue.unref(rootContext).placeholder.value,
@@ -5143,6 +5167,7 @@ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
5143
5167
  __name: "DatePickerMonthYearOverlay",
5144
5168
  props: {
5145
5169
  type: {},
5170
+ itemsPerRow: {},
5146
5171
  asChild: { type: Boolean },
5147
5172
  as: {}
5148
5173
  },
@@ -5165,25 +5190,125 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
5165
5190
  __name: "CalendarOverlayItem",
5166
5191
  props: {
5167
5192
  date: {},
5193
+ disabled: { type: Boolean },
5194
+ type: {},
5168
5195
  asChild: { type: Boolean },
5169
- as: { default: "button" }
5196
+ as: { default: "div" }
5170
5197
  },
5171
5198
  setup(__props) {
5172
5199
  const props = __props;
5173
5200
  const rootContext = injectCalendarRootContext();
5201
+ const years = vue.computed(() => rootContext.years.value);
5202
+ const overlayContext = injectCalendarMonthYearOverlayContext();
5203
+ const dataValue = vue.computed(() => `${props.type}-${props.date[props.type]}`);
5204
+ const { primitiveElement, currentElement } = usePrimitiveElement();
5205
+ const isFocusedDate = vue.computed(() => {
5206
+ if (props.type === "month")
5207
+ return rootContext.currentMonth.value === props.date.monthName;
5208
+ return rootContext.currentYear.value === props.date.year.toString();
5209
+ });
5210
+ const ariaLabel = vue.computed(() => {
5211
+ if (props.type === "month") return props.date.monthName;
5212
+ return props.date.year.toString();
5213
+ });
5214
+ vue.onMounted(() => {
5215
+ if (isFocusedDate.value) {
5216
+ vue.nextTick(() => {
5217
+ currentElement.value?.focus();
5218
+ currentElement.value?.scrollIntoView({ block: "nearest" });
5219
+ });
5220
+ }
5221
+ });
5222
+ function isDateSelectable(date2) {
5223
+ return !rootContext.isDateDisabled(date2) && !rootContext.isDateUnavailable?.(date2);
5224
+ }
5225
+ function closeOverlay() {
5226
+ rootContext.monthYearOverlayState.value = false;
5227
+ }
5174
5228
  function handleClick() {
5175
- if (rootContext.isDateDisabled(props.date) || rootContext.isDateUnavailable?.(props.date))
5176
- return;
5229
+ if (!isDateSelectable(props.date)) return;
5177
5230
  rootContext.onDateChange(props.date);
5178
- rootContext.monthYearOverlayState.value = false;
5231
+ closeOverlay();
5232
+ }
5233
+ const kbd = useKbd();
5234
+ function handleKeydown(e) {
5235
+ if (props.disabled) return;
5236
+ e.preventDefault();
5237
+ e.stopPropagation();
5238
+ const parentElement = rootContext.parentElement.value;
5239
+ const itemsPerRow = overlayContext.itemsPerRow.value;
5240
+ const sign = rootContext.dir.value === "rtl" ? -1 : 1;
5241
+ const currentValue = props.date[props.type];
5242
+ function focusItem(value) {
5243
+ const candidate = parentElement.querySelector(
5244
+ `[data-value='${props.type}-${value}']`
5245
+ );
5246
+ candidate?.focus();
5247
+ candidate?.scrollIntoView({ block: "nearest" });
5248
+ }
5249
+ function shiftFocus(add) {
5250
+ let nextValue = currentValue + add;
5251
+ if (props.type === "month") {
5252
+ nextValue = (nextValue - 1 + 12) % 12 + 1;
5253
+ } else {
5254
+ const minYear = years.value[0].year;
5255
+ const maxYear = years.value[years.value.length - 1].year;
5256
+ nextValue = Math.max(minYear, Math.min(nextValue, maxYear));
5257
+ }
5258
+ focusItem(nextValue);
5259
+ }
5260
+ switch (e.code) {
5261
+ case kbd.ARROW_RIGHT:
5262
+ shiftFocus(sign);
5263
+ break;
5264
+ case kbd.ARROW_LEFT:
5265
+ shiftFocus(-sign);
5266
+ break;
5267
+ case kbd.ARROW_UP:
5268
+ shiftFocus(-itemsPerRow);
5269
+ break;
5270
+ case kbd.ARROW_DOWN:
5271
+ shiftFocus(itemsPerRow);
5272
+ break;
5273
+ case kbd.HOME: {
5274
+ const firstValue = props.type === "month" ? 1 : years.value[0].year;
5275
+ focusItem(firstValue);
5276
+ break;
5277
+ }
5278
+ case kbd.END: {
5279
+ const lastValue = props.type === "month" ? 12 : years.value[years.value.length - 1].year;
5280
+ focusItem(lastValue);
5281
+ break;
5282
+ }
5283
+ case kbd.ENTER:
5284
+ case kbd.SPACE_CODE:
5285
+ if (isDateSelectable(props.date)) {
5286
+ rootContext.onDateChange(props.date);
5287
+ closeOverlay();
5288
+ }
5289
+ }
5179
5290
  }
5180
5291
  return (_ctx, _cache) => {
5181
- return vue.openBlock(), vue.createBlock(vue.unref(Primitive), vue.mergeProps(props, { onClick: handleClick }), {
5292
+ return vue.openBlock(), vue.createBlock(vue.unref(Primitive), vue.mergeProps(props, {
5293
+ onClick: handleClick,
5294
+ ref_key: "primitiveElement",
5295
+ ref: primitiveElement,
5296
+ role: "button",
5297
+ "aria-label": ariaLabel.value,
5298
+ "aria-disabled": __props.disabled,
5299
+ "data-value": dataValue.value,
5300
+ onKeydown: [
5301
+ vue.withKeys(handleKeydown, ["up", "down", "left", "right", "space", "enter", "home", "end"]),
5302
+ _cache[0] || (_cache[0] = vue.withKeys(vue.withModifiers(() => {
5303
+ }, ["prevent"]), ["enter"]))
5304
+ ],
5305
+ tabindex: isFocusedDate.value ? 0 : -1
5306
+ }), {
5182
5307
  default: vue.withCtx(() => [
5183
5308
  vue.renderSlot(_ctx.$slots, "default")
5184
5309
  ]),
5185
5310
  _: 3
5186
- }, 16);
5311
+ }, 16, ["aria-label", "aria-disabled", "data-value", "tabindex"]);
5187
5312
  };
5188
5313
  }
5189
5314
  });
@@ -5191,6 +5316,8 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
5191
5316
  __name: "DatePickerOverlayItem",
5192
5317
  props: {
5193
5318
  date: {},
5319
+ disabled: { type: Boolean },
5320
+ type: {},
5194
5321
  asChild: { type: Boolean },
5195
5322
  as: {}
5196
5323
  },