@rupe/v-datepicker 1.0.0-alpha.1 → 1.0.0-beta.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/README.md +124 -0
- package/dist/components/Calendar/CalendarMonthYearOverlay.vue.d.ts +16 -17
- package/dist/components/Calendar/CalendarOverlayItem.vue.d.ts +82 -4
- package/dist/components/DatePicker/DatePickerMonthYearOverlay.vue.d.ts +2 -2
- package/dist/index.cjs +102 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +102 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/Calendar/CalendarMonthYearOverlay.vue +41 -12
- package/src/components/Calendar/CalendarOverlayItem.vue +92 -5
- package/src/components/Calendar/useCalendar.ts +3 -5
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# v-datepicker
|
|
2
|
+
|
|
3
|
+
A flexible and accessible Vue 3 datepicker component library.
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
`v-datepicker` is a highly customizable datepicker package built for the Vue 3 ecosystem. It is primarily based on the robust implementation of [reka-ui](https://github.com/reka-ui/reka-ui) (formerly radix-vue) to ensure top-tier accessibility and performance.
|
|
8
|
+
|
|
9
|
+
This package is further enriched with advanced features like the **Month and Year Overlay**, inspired by the popular [vue-datepicker](https://github.com/Vuepic/vue-datepicker), providing a more intuitive navigation experience for users.
|
|
10
|
+
|
|
11
|
+
> **Note:** This is a **headless** library. No styling is included out of the box. You have full control over the look and feel, and are responsible for applying all styles (e.g., using Tailwind CSS).
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **Headless & Accessible**: Built on top of Reka UI's accessible primitives.
|
|
16
|
+
- **Customizable**: Full control over the rendering of every part of the datepicker.
|
|
17
|
+
- **Tree-shakable**: Built using modern ES modules.
|
|
18
|
+
- **Month & Year Overlays**: Quick navigation inspired by Vue Datepicker.
|
|
19
|
+
- **TypeScript Ready**: Full type support for a better developer experience.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# pnpm
|
|
25
|
+
pnpm add @rupe/v-datepicker
|
|
26
|
+
|
|
27
|
+
# npm
|
|
28
|
+
npm install @rupe/v-datepicker
|
|
29
|
+
|
|
30
|
+
# yarn
|
|
31
|
+
yarn add @rupe/v-datepicker
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Basic Usage (Tailwind CSS)
|
|
35
|
+
|
|
36
|
+
Since the library is headless, you'll need to apply your own styles. Here's an example using Tailwind CSS:
|
|
37
|
+
|
|
38
|
+
```vue
|
|
39
|
+
<script setup lang="ts">
|
|
40
|
+
import { DatePicker } from '@rupe/v-datepicker'
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<DatePicker.Root class="relative">
|
|
45
|
+
<DatePicker.Field v-slot="{ segments }" class="flex items-center gap-1 border border-gray-300 rounded px-3 py-2 bg-white focus-within:ring-2 focus:ring-blue-500">
|
|
46
|
+
<div class="flex items-center">
|
|
47
|
+
<template v-for="item in segments" :key="item.part">
|
|
48
|
+
<DatePicker.Input
|
|
49
|
+
:part="item.part"
|
|
50
|
+
class="px-0.5 rounded focus:bg-blue-100 focus:outline-none data-[placeholder]:text-gray-400"
|
|
51
|
+
>
|
|
52
|
+
{{ item.value }}
|
|
53
|
+
</DatePicker.Input>
|
|
54
|
+
</template>
|
|
55
|
+
</div>
|
|
56
|
+
<DatePicker.Trigger class="ml-auto text-gray-500 hover:text-gray-700">
|
|
57
|
+
📅
|
|
58
|
+
</DatePicker.Trigger>
|
|
59
|
+
</DatePicker.Field>
|
|
60
|
+
|
|
61
|
+
<DatePicker.Content class="absolute z-10 mt-2 bg-white border border-gray-200 rounded-lg shadow-xl p-4">
|
|
62
|
+
<DatePicker.Calendar v-slot="{ weekDays, grid }">
|
|
63
|
+
<DatePicker.Header class="flex items-center justify-between mb-4">
|
|
64
|
+
<DatePicker.Prev class="p-1 hover:bg-gray-100 rounded">⬅️</DatePicker.Prev>
|
|
65
|
+
<DatePicker.Heading class="font-bold flex gap-1">
|
|
66
|
+
<DatePicker.MonthHeading />
|
|
67
|
+
<DatePicker.YearHeading />
|
|
68
|
+
</DatePicker.Heading>
|
|
69
|
+
<DatePicker.Next class="p-1 hover:bg-gray-100 rounded">➡️</DatePicker.Next>
|
|
70
|
+
</DatePicker.Header>
|
|
71
|
+
|
|
72
|
+
<DatePicker.Grid v-for="month in grid" :key="month.value.toString()" class="w-full">
|
|
73
|
+
<DatePicker.GridHead>
|
|
74
|
+
<DatePicker.GridRow class="flex justify-between">
|
|
75
|
+
<DatePicker.HeadCell v-for="day in weekDays" :key="day" class="w-8 text-center text-xs text-gray-500 font-medium">
|
|
76
|
+
{{ day }}
|
|
77
|
+
</DatePicker.HeadCell>
|
|
78
|
+
</DatePicker.GridRow>
|
|
79
|
+
</DatePicker.GridHead>
|
|
80
|
+
<DatePicker.GridBody>
|
|
81
|
+
<DatePicker.GridRow v-for="(weekDates, index) in month.rows" :key="index" class="flex justify-between mt-1">
|
|
82
|
+
<DatePicker.Cell v-for="weekDate in weekDates" :key="weekDate.toString()" :date="weekDate">
|
|
83
|
+
<DatePicker.CellTrigger
|
|
84
|
+
:day="weekDate"
|
|
85
|
+
:month="month.value"
|
|
86
|
+
class="w-8 h-8 flex items-center justify-center rounded-full text-sm hover:bg-blue-50 data-[selected]:bg-blue-600 data-[selected]:text-white data-[outside-view]:text-gray-300"
|
|
87
|
+
/>
|
|
88
|
+
</DatePicker.Cell>
|
|
89
|
+
</DatePicker.GridRow>
|
|
90
|
+
</DatePicker.GridBody>
|
|
91
|
+
</DatePicker.Grid>
|
|
92
|
+
</DatePicker.Calendar>
|
|
93
|
+
</DatePicker.Content>
|
|
94
|
+
</DatePicker.Root>
|
|
95
|
+
</template>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Playground
|
|
99
|
+
|
|
100
|
+
The repository includes a playground project built with **Nuxt** and **Tailwind CSS** to test the library locally.
|
|
101
|
+
|
|
102
|
+
### Running the Playground
|
|
103
|
+
|
|
104
|
+
1. **Clone the repository**
|
|
105
|
+
2. **Install dependencies**:
|
|
106
|
+
```bash
|
|
107
|
+
pnpm install
|
|
108
|
+
```
|
|
109
|
+
3. **Start the playground**:
|
|
110
|
+
```bash
|
|
111
|
+
pnpm dev
|
|
112
|
+
```
|
|
113
|
+
This will start the Nuxt dev server for the `playground` folder. Any changes made in the `src/` directory will be reflected instantly via HMR.
|
|
114
|
+
|
|
115
|
+
## Credits
|
|
116
|
+
|
|
117
|
+
Special thanks to the following projects that made this package possible:
|
|
118
|
+
|
|
119
|
+
- **[reka-ui](https://reka-ui.com/)**: For the incredible foundation of accessible headless components.
|
|
120
|
+
- **[vue-datepicker](https://vue3-datepicker.com/)**: For the inspiration behind the intuitive month and year overlay navigation.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -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
|
-
|
|
8
|
-
|
|
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
|
-
|
|
22
|
-
declare const
|
|
23
|
-
|
|
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 {
|
|
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, {
|
|
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 & {
|
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);
|
|
@@ -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,25 +4174,35 @@ 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(
|
|
4174
|
-
|
|
4175
|
-
|
|
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));
|
|
4189
|
+
const isOpen = vue.computed(
|
|
4190
|
+
() => rootContext.monthYearOverlayState.value === props.type
|
|
4191
|
+
);
|
|
4176
4192
|
function onEscapeKeyDown() {
|
|
4177
4193
|
rootContext.monthYearOverlayState.value = false;
|
|
4178
4194
|
}
|
|
4195
|
+
provideCalendarMonthYearOverlayContext({
|
|
4196
|
+
itemsPerRow
|
|
4197
|
+
});
|
|
4179
4198
|
return (_ctx, _cache) => {
|
|
4180
|
-
return vue.openBlock(), vue.createBlock(_sfc_main$O, {
|
|
4199
|
+
return isOpen.value ? (vue.openBlock(), vue.createBlock(_sfc_main$O, {
|
|
4200
|
+
key: 0,
|
|
4181
4201
|
"as-child": "",
|
|
4182
4202
|
onEscapeKeyDown
|
|
4183
4203
|
}, {
|
|
4184
4204
|
default: vue.withCtx(() => [
|
|
4185
|
-
|
|
4205
|
+
vue.createVNode(vue.unref(Primitive), vue.mergeProps({ ...props, ..._ctx.$attrs }, {
|
|
4186
4206
|
style: {
|
|
4187
4207
|
position: "absolute",
|
|
4188
4208
|
height: "100%",
|
|
@@ -4202,10 +4222,10 @@ const _sfc_main$q = /* @__PURE__ */ vue.defineComponent({
|
|
|
4202
4222
|
})
|
|
4203
4223
|
]),
|
|
4204
4224
|
_: 3
|
|
4205
|
-
}, 16)
|
|
4225
|
+
}, 16)
|
|
4206
4226
|
]),
|
|
4207
4227
|
_: 3
|
|
4208
|
-
});
|
|
4228
|
+
})) : vue.createCommentVNode("", true);
|
|
4209
4229
|
};
|
|
4210
4230
|
}
|
|
4211
4231
|
});
|
|
@@ -5140,6 +5160,7 @@ const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
|
|
|
5140
5160
|
__name: "DatePickerMonthYearOverlay",
|
|
5141
5161
|
props: {
|
|
5142
5162
|
type: {},
|
|
5163
|
+
itemsPerRow: {},
|
|
5143
5164
|
asChild: { type: Boolean },
|
|
5144
5165
|
as: {}
|
|
5145
5166
|
},
|
|
@@ -5162,25 +5183,93 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
|
|
|
5162
5183
|
__name: "CalendarOverlayItem",
|
|
5163
5184
|
props: {
|
|
5164
5185
|
date: {},
|
|
5186
|
+
disabled: { type: Boolean },
|
|
5187
|
+
type: {},
|
|
5165
5188
|
asChild: { type: Boolean },
|
|
5166
|
-
as: { default: "
|
|
5189
|
+
as: { default: "div" }
|
|
5167
5190
|
},
|
|
5168
5191
|
setup(__props) {
|
|
5169
5192
|
const props = __props;
|
|
5170
5193
|
const rootContext = injectCalendarRootContext();
|
|
5194
|
+
const years = vue.computed(() => rootContext.years.value);
|
|
5195
|
+
const maxValue = vue.computed(
|
|
5196
|
+
() => props.type === "month" ? 12 : years.value.length
|
|
5197
|
+
);
|
|
5198
|
+
const overlayContext = injectCalendarMonthYearOverlayContext();
|
|
5199
|
+
const dataValue = vue.computed(() => `${props.type}-${props.date[props.type]}`);
|
|
5200
|
+
const isFocusedDate = vue.computed(() => {
|
|
5201
|
+
if (props.type === "month")
|
|
5202
|
+
return rootContext.currentMonth.value === props.date.monthName;
|
|
5203
|
+
return rootContext.currentYear.value === props.date.year.toString();
|
|
5204
|
+
});
|
|
5205
|
+
function closeOverlay() {
|
|
5206
|
+
rootContext.monthYearOverlayState.value = false;
|
|
5207
|
+
}
|
|
5171
5208
|
function handleClick() {
|
|
5172
5209
|
if (rootContext.isDateDisabled(props.date) || rootContext.isDateUnavailable?.(props.date))
|
|
5173
5210
|
return;
|
|
5174
5211
|
rootContext.onDateChange(props.date);
|
|
5175
|
-
|
|
5212
|
+
closeOverlay();
|
|
5213
|
+
}
|
|
5214
|
+
const kbd = useKbd();
|
|
5215
|
+
function handleArrowKey(e) {
|
|
5216
|
+
if (props.disabled) return;
|
|
5217
|
+
e.preventDefault();
|
|
5218
|
+
e.stopPropagation();
|
|
5219
|
+
const parentElement = rootContext.parentElement.value;
|
|
5220
|
+
const indexIncrementation = overlayContext.itemsPerRow.value;
|
|
5221
|
+
const sign = rootContext.dir.value === "rtl" ? -1 : 1;
|
|
5222
|
+
switch (e.code) {
|
|
5223
|
+
case kbd.ARROW_RIGHT:
|
|
5224
|
+
shiftFocus(props.date, sign);
|
|
5225
|
+
break;
|
|
5226
|
+
case kbd.ARROW_LEFT:
|
|
5227
|
+
shiftFocus(props.date, -sign);
|
|
5228
|
+
break;
|
|
5229
|
+
case kbd.ARROW_UP:
|
|
5230
|
+
shiftFocus(props.date, -indexIncrementation);
|
|
5231
|
+
break;
|
|
5232
|
+
case kbd.ARROW_DOWN:
|
|
5233
|
+
shiftFocus(props.date, indexIncrementation);
|
|
5234
|
+
break;
|
|
5235
|
+
case kbd.ENTER:
|
|
5236
|
+
case kbd.SPACE_CODE:
|
|
5237
|
+
rootContext.onDateChange(props.date);
|
|
5238
|
+
closeOverlay();
|
|
5239
|
+
}
|
|
5240
|
+
function shiftFocus(date2, add) {
|
|
5241
|
+
let nextDate = date2[props.type] + add;
|
|
5242
|
+
if (nextDate <= 0) {
|
|
5243
|
+
nextDate = maxValue.value + nextDate;
|
|
5244
|
+
}
|
|
5245
|
+
if (nextDate > years.value[maxValue.value - 1].year) {
|
|
5246
|
+
nextDate = nextDate - maxValue.value;
|
|
5247
|
+
}
|
|
5248
|
+
const candidateDay = parentElement.querySelector(
|
|
5249
|
+
`[data-value='${props.type}-${nextDate}']`
|
|
5250
|
+
);
|
|
5251
|
+
candidateDay?.focus();
|
|
5252
|
+
}
|
|
5176
5253
|
}
|
|
5177
5254
|
return (_ctx, _cache) => {
|
|
5178
|
-
return vue.openBlock(), vue.createBlock(vue.unref(Primitive), vue.mergeProps(props, {
|
|
5255
|
+
return vue.openBlock(), vue.createBlock(vue.unref(Primitive), vue.mergeProps(props, {
|
|
5256
|
+
onClick: handleClick,
|
|
5257
|
+
ref: "primitiveElement",
|
|
5258
|
+
role: "button",
|
|
5259
|
+
"aria-disabled": __props.disabled,
|
|
5260
|
+
"data-value": dataValue.value,
|
|
5261
|
+
onKeydown: [
|
|
5262
|
+
vue.withKeys(handleArrowKey, ["up", "down", "left", "right", "space", "enter"]),
|
|
5263
|
+
_cache[0] || (_cache[0] = vue.withKeys(vue.withModifiers(() => {
|
|
5264
|
+
}, ["prevent"]), ["enter"]))
|
|
5265
|
+
],
|
|
5266
|
+
tabindex: isFocusedDate.value ? 0 : -1
|
|
5267
|
+
}), {
|
|
5179
5268
|
default: vue.withCtx(() => [
|
|
5180
5269
|
vue.renderSlot(_ctx.$slots, "default")
|
|
5181
5270
|
]),
|
|
5182
5271
|
_: 3
|
|
5183
|
-
}, 16);
|
|
5272
|
+
}, 16, ["aria-disabled", "data-value", "tabindex"]);
|
|
5184
5273
|
};
|
|
5185
5274
|
}
|
|
5186
5275
|
});
|
|
@@ -5188,6 +5277,8 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
5188
5277
|
__name: "DatePickerOverlayItem",
|
|
5189
5278
|
props: {
|
|
5190
5279
|
date: {},
|
|
5280
|
+
disabled: { type: Boolean },
|
|
5281
|
+
type: {},
|
|
5191
5282
|
asChild: { type: Boolean },
|
|
5192
5283
|
as: {}
|
|
5193
5284
|
},
|