v-calendar-3 1.0.1 → 1.1.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 +10 -2
- package/dist/cjs/index.css +11 -5
- package/dist/cjs/index.js +64 -22
- package/dist/cjs/index.js.map +1 -1
- package/dist/es/index.js +64 -22
- package/dist/es/index.js.map +1 -1
- package/dist/es/style.css +11 -5
- package/dist/iife/index.js +1 -1
- package/dist/iife/index.js.map +1 -1
- package/dist/mjs/index.mjs +64 -22
- package/dist/mjs/index.mjs.map +1 -1
- package/dist/mjs/style.css +11 -5
- package/dist/style.css +11 -5
- package/dist/types/components/Calendar/Calendar.vue.d.ts +9 -0
- package/dist/types/components/Calendar/CalendarHeader.vue.d.ts +1 -0
- package/dist/types/components/DatePicker/DatePicker.vue.d.ts +48 -0
- package/dist/types/components/DatePicker/TimePicker.vue.d.ts +32 -0
- package/dist/types/index.d.cts +128 -0
- package/dist/types/index.d.mts +128 -0
- package/dist/types/index.d.ts +128 -0
- package/dist/types/use/calendar.d.ts +7 -0
- package/dist/types/use/calendarGrid.d.ts +14 -0
- package/dist/types/use/datePicker.d.ts +64 -0
- package/dist/types/use/timePicker.d.ts +32 -0
- package/package.json +1 -1
- package/src/components/Calendar/Calendar.vue +2 -2
- package/src/components/Calendar/CalendarDay.vue +4 -5
- package/src/components/Calendar/CalendarHeader.vue +37 -8
- package/src/components/Calendar/CalendarPage.vue +7 -2
- package/src/styles/theme.css +1 -0
- package/src/use/calendar.ts +42 -8
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ A maintained Vue 3 calendar and date picker with TypeScript declarations,
|
|
|
4
4
|
timezone support, keyboard navigation, touch interaction, and responsive theme
|
|
5
5
|
handling.
|
|
6
6
|
|
|
7
|
-
Current version: `1.0
|
|
7
|
+
Current version: `1.1.0`
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
@@ -112,7 +112,7 @@ const attributes = [
|
|
|
112
112
|
<template>
|
|
113
113
|
<Calendar :attributes="attributes" />
|
|
114
114
|
<DatePicker v-model="selectedDate" />
|
|
115
|
-
<DatePicker v-model.range="range" />
|
|
115
|
+
<DatePicker v-model.range="range" :rows="2" />
|
|
116
116
|
</template>
|
|
117
117
|
```
|
|
118
118
|
|
|
@@ -139,6 +139,13 @@ ranges and the `mode` prop when time selection is required.
|
|
|
139
139
|
<DatePicker v-model="time" mode="time" is24hr />
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
+
`rows="2"` with the default `columns="1"` is the two-month period layout. It
|
|
143
|
+
renders both months horizontally with a complete navigation header and a
|
|
144
|
+
month/year picker on each pane. The displayed months remain consecutive, and
|
|
145
|
+
each pane includes muted leading and trailing dates from adjacent months so its
|
|
146
|
+
week rows are complete. With `trim-weeks`, both period panes are balanced to the
|
|
147
|
+
larger visible week count.
|
|
148
|
+
|
|
142
149
|
The `string` and `number` model modifiers are also supported. Numeric values use
|
|
143
150
|
JavaScript timestamp milliseconds.
|
|
144
151
|
|
|
@@ -234,6 +241,7 @@ styles to internal selectors.
|
|
|
234
241
|
--vc-day-min-height: 1.75rem;
|
|
235
242
|
--vc-day-content-width: 1.75rem;
|
|
236
243
|
--vc-day-content-height: 1.75rem;
|
|
244
|
+
--vc-day-content-outside-month-opacity: 0.6;
|
|
237
245
|
--vc-highlight-width: 1.75rem;
|
|
238
246
|
--vc-highlight-height: 1.75rem;
|
|
239
247
|
--vc-header-margin-top: 0;
|
package/dist/cjs/index.css
CHANGED
|
@@ -163,6 +163,8 @@
|
|
|
163
163
|
|
|
164
164
|
.vc-header {
|
|
165
165
|
display: grid;
|
|
166
|
+
width: 100%;
|
|
167
|
+
min-width: 0;
|
|
166
168
|
grid-gap: var(--vc-header-gap);
|
|
167
169
|
align-items: center;
|
|
168
170
|
height: var(--vc-header-height);
|
|
@@ -181,6 +183,8 @@
|
|
|
181
183
|
.vc-header .vc-title-wrapper {
|
|
182
184
|
grid-row: 1;
|
|
183
185
|
grid-column: title;
|
|
186
|
+
min-width: 0;
|
|
187
|
+
justify-self: center;
|
|
184
188
|
}
|
|
185
189
|
.vc-header .vc-prev {
|
|
186
190
|
grid-row: 1;
|
|
@@ -208,6 +212,9 @@
|
|
|
208
212
|
font-weight: var(--vc-font-semibold);
|
|
209
213
|
text-transform: var(--vc-header-title-text-transform);
|
|
210
214
|
white-space: nowrap;
|
|
215
|
+
max-width: 100%;
|
|
216
|
+
overflow: hidden;
|
|
217
|
+
text-overflow: ellipsis;
|
|
211
218
|
padding: var(--vc-header-title-padding);
|
|
212
219
|
margin: 0;
|
|
213
220
|
line-height: var(--vc-header-title-line-height);
|
|
@@ -303,15 +310,13 @@
|
|
|
303
310
|
position: relative;
|
|
304
311
|
min-height: var(--vc-day-min-height);
|
|
305
312
|
z-index: 1;
|
|
306
|
-
/* &.is-not-in-month * {
|
|
307
|
-
opacity: 0;
|
|
308
|
-
pointer-events: none;
|
|
309
|
-
} */
|
|
310
313
|
}
|
|
311
314
|
.vc-monthly .is-not-in-month * {
|
|
312
|
-
opacity: 0;
|
|
313
315
|
pointer-events: none;
|
|
314
316
|
}
|
|
317
|
+
.vc-monthly .is-not-in-month .vc-day-content {
|
|
318
|
+
opacity: var(--vc-day-content-outside-month-opacity);
|
|
319
|
+
}
|
|
315
320
|
.vc-day-layer {
|
|
316
321
|
position: absolute;
|
|
317
322
|
left: 0;
|
|
@@ -855,6 +860,7 @@
|
|
|
855
860
|
--vc-day-content-width: 28px;
|
|
856
861
|
--vc-day-content-height: 28px;
|
|
857
862
|
--vc-day-content-line-height: 28px;
|
|
863
|
+
--vc-day-content-outside-month-opacity: 0.6;
|
|
858
864
|
--vc-highlight-width: var(--vc-day-content-width);
|
|
859
865
|
--vc-highlight-height: var(--vc-day-content-height);
|
|
860
866
|
|
package/dist/cjs/index.js
CHANGED
|
@@ -8007,6 +8007,9 @@ function createCalendar(props, { slots, emit }) {
|
|
|
8007
8007
|
provideSlots(slots);
|
|
8008
8008
|
const { theme, color, displayMode, locale, masks, minDate, maxDate, normalizedMinDate, normalizedMaxDate, disabledAttribute, disabledDates } = useOrCreateBase(props);
|
|
8009
8009
|
const count = (0, vue.computed)(() => props.rows * props.columns);
|
|
8010
|
+
const isPeriodLayout = (0, vue.computed)(() => props.rows === 2 && props.columns === 1);
|
|
8011
|
+
const layoutRows = (0, vue.computed)(() => isPeriodLayout.value ? 1 : props.rows);
|
|
8012
|
+
const layoutColumns = (0, vue.computed)(() => isPeriodLayout.value ? 2 : props.columns);
|
|
8010
8013
|
const step = (0, vue.computed)(() => props.step || count.value);
|
|
8011
8014
|
const firstPage = (0, vue.computed)(() => (0, import_head.default)(_pages.value) ?? null);
|
|
8012
8015
|
const lastPage = (0, vue.computed)(() => (0, import_last.default)(_pages.value) ?? null);
|
|
@@ -8139,10 +8142,10 @@ function createCalendar(props, { slots, emit }) {
|
|
|
8139
8142
|
for (let i = 0; i < count.value; i++) {
|
|
8140
8143
|
const newPage = addPages$1(fromPage, i);
|
|
8141
8144
|
const position = i + 1;
|
|
8142
|
-
const row = Math.ceil(position /
|
|
8143
|
-
const rowFromEnd =
|
|
8144
|
-
const column = position %
|
|
8145
|
-
const columnFromEnd =
|
|
8145
|
+
const row = Math.ceil(position / layoutColumns.value);
|
|
8146
|
+
const rowFromEnd = layoutRows.value - row + 1;
|
|
8147
|
+
const column = position % layoutColumns.value || layoutColumns.value;
|
|
8148
|
+
const columnFromEnd = layoutColumns.value - column + 1;
|
|
8146
8149
|
const weeknumberPosition = getWeeknumberPosition(column, columnFromEnd);
|
|
8147
8150
|
pages.push(locale.value.getPage({
|
|
8148
8151
|
...newPage,
|
|
@@ -8159,6 +8162,12 @@ function createCalendar(props, { slots, emit }) {
|
|
|
8159
8162
|
weeknumberPosition
|
|
8160
8163
|
}));
|
|
8161
8164
|
}
|
|
8165
|
+
if (isPeriodLayout.value && isMonthly.value) {
|
|
8166
|
+
const weekCount = Math.max(...pages.map((currentPage) => currentPage.viewWeeks.length));
|
|
8167
|
+
pages.forEach((currentPage) => {
|
|
8168
|
+
currentPage.viewWeeks = currentPage.weeks.slice(0, weekCount);
|
|
8169
|
+
});
|
|
8170
|
+
}
|
|
8162
8171
|
transitionName.value = getPageTransition(_pages.value[0], pages[0], transition);
|
|
8163
8172
|
_pages.value = pages;
|
|
8164
8173
|
if (transitionName.value && transitionName.value !== "none") transitionPromise = {
|
|
@@ -8216,6 +8225,14 @@ function createCalendar(props, { slots, emit }) {
|
|
|
8216
8225
|
const moveNext = () => {
|
|
8217
8226
|
return moveBy(step.value);
|
|
8218
8227
|
};
|
|
8228
|
+
const canMovePeriodPrev = (0, vue.computed)(() => canMoveBy(-1));
|
|
8229
|
+
const canMovePeriodNext = (0, vue.computed)(() => canMoveBy(1));
|
|
8230
|
+
const movePeriodPrev = () => {
|
|
8231
|
+
return moveBy(-1);
|
|
8232
|
+
};
|
|
8233
|
+
const movePeriodNext = () => {
|
|
8234
|
+
return moveBy(1);
|
|
8235
|
+
};
|
|
8219
8236
|
const tryFocusDate = (date) => {
|
|
8220
8237
|
const inMonth = isMonthly.value ? ".in-month" : "";
|
|
8221
8238
|
const daySelector = `.id-${locale.value.getDayId(date)}${inMonth}`;
|
|
@@ -8317,7 +8334,11 @@ function createCalendar(props, { slots, emit }) {
|
|
|
8317
8334
|
(0, vue.watch)(() => locale.value, () => {
|
|
8318
8335
|
refreshPages();
|
|
8319
8336
|
});
|
|
8320
|
-
(0, vue.watch)(
|
|
8337
|
+
(0, vue.watch)([
|
|
8338
|
+
count,
|
|
8339
|
+
layoutRows,
|
|
8340
|
+
layoutColumns
|
|
8341
|
+
], () => refreshPages());
|
|
8321
8342
|
(0, vue.watch)(() => props.view, () => _view.value = props.view);
|
|
8322
8343
|
(0, vue.watch)(() => _view.value, () => {
|
|
8323
8344
|
handleWatcher("view", () => {
|
|
@@ -8358,6 +8379,9 @@ function createCalendar(props, { slots, emit }) {
|
|
|
8358
8379
|
dayCells,
|
|
8359
8380
|
count,
|
|
8360
8381
|
step,
|
|
8382
|
+
isPeriodLayout,
|
|
8383
|
+
layoutRows,
|
|
8384
|
+
layoutColumns,
|
|
8361
8385
|
firstPage,
|
|
8362
8386
|
lastPage,
|
|
8363
8387
|
canMovePrev,
|
|
@@ -8377,6 +8401,10 @@ function createCalendar(props, { slots, emit }) {
|
|
|
8377
8401
|
moveBy,
|
|
8378
8402
|
movePrev,
|
|
8379
8403
|
moveNext,
|
|
8404
|
+
canMovePeriodPrev,
|
|
8405
|
+
canMovePeriodNext,
|
|
8406
|
+
movePeriodPrev,
|
|
8407
|
+
movePeriodNext,
|
|
8380
8408
|
onTransitionBeforeEnter,
|
|
8381
8409
|
onTransitionAfterEnter,
|
|
8382
8410
|
tryFocusDate,
|
|
@@ -8940,11 +8968,16 @@ var CalendarHeader_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
8940
8968
|
isXl: { type: Boolean },
|
|
8941
8969
|
is2xl: { type: Boolean },
|
|
8942
8970
|
hideTitle: { type: Boolean },
|
|
8943
|
-
hideArrows: { type: Boolean }
|
|
8971
|
+
hideArrows: { type: Boolean },
|
|
8972
|
+
periodNavigation: { type: Boolean }
|
|
8944
8973
|
},
|
|
8945
8974
|
setup(__props) {
|
|
8946
8975
|
const props = __props;
|
|
8947
|
-
const { navPopoverId, navVisibility, canMovePrev, movePrev, canMoveNext, moveNext } = useCalendar();
|
|
8976
|
+
const { navPopoverId, navVisibility, canMovePrev, movePrev, canMoveNext, moveNext, canMovePeriodPrev, canMovePeriodNext, movePeriodPrev, movePeriodNext } = useCalendar();
|
|
8977
|
+
const canMovePrev_ = (0, vue.computed)(() => props.periodNavigation ? canMovePeriodPrev.value : canMovePrev.value);
|
|
8978
|
+
const canMoveNext_ = (0, vue.computed)(() => props.periodNavigation ? canMovePeriodNext.value : canMoveNext.value);
|
|
8979
|
+
const movePrev_ = () => props.periodNavigation ? movePeriodPrev() : movePrev();
|
|
8980
|
+
const moveNext_ = () => props.periodNavigation ? movePeriodNext() : moveNext();
|
|
8948
8981
|
const navPlacement = (0, vue.computed)(() => {
|
|
8949
8982
|
switch (props.page.titlePosition) {
|
|
8950
8983
|
case "left": return "bottom-start";
|
|
@@ -8982,6 +9015,7 @@ var CalendarHeader_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
8982
9015
|
};
|
|
8983
9016
|
});
|
|
8984
9017
|
const gridStyle = (0, vue.computed)(() => {
|
|
9018
|
+
if (props.periodNavigation && !props.layout) return { gridTemplateColumns: "[prev] auto [title] minmax(0, 1fr) [next] auto" };
|
|
8985
9019
|
return { gridTemplateColumns: layout_.value.split("").map((l) => {
|
|
8986
9020
|
switch (l) {
|
|
8987
9021
|
case "p": return "[prev] auto";
|
|
@@ -9005,12 +9039,12 @@ var CalendarHeader_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
9005
9039
|
key: 0,
|
|
9006
9040
|
type: "button",
|
|
9007
9041
|
class: "vc-arrow vc-prev vc-focus",
|
|
9008
|
-
disabled: !
|
|
9009
|
-
onClick:
|
|
9010
|
-
onKeydown:
|
|
9042
|
+
disabled: !canMovePrev_.value,
|
|
9043
|
+
onClick: movePrev_,
|
|
9044
|
+
onKeydown: (0, vue.withKeys)(movePrev_, ["space", "enter"])
|
|
9011
9045
|
}, [(0, vue.createVNode)(CalendarSlot_default, {
|
|
9012
9046
|
name: "header-prev-button",
|
|
9013
|
-
disabled: !
|
|
9047
|
+
disabled: !canMovePrev_.value
|
|
9014
9048
|
}, {
|
|
9015
9049
|
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BaseIcon_default, {
|
|
9016
9050
|
name: "ChevronLeft",
|
|
@@ -9032,12 +9066,12 @@ var CalendarHeader_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
9032
9066
|
key: 2,
|
|
9033
9067
|
type: "button",
|
|
9034
9068
|
class: "vc-arrow vc-next vc-focus",
|
|
9035
|
-
disabled: !
|
|
9036
|
-
onClick:
|
|
9037
|
-
onKeydown:
|
|
9069
|
+
disabled: !canMoveNext_.value,
|
|
9070
|
+
onClick: moveNext_,
|
|
9071
|
+
onKeydown: (0, vue.withKeys)(moveNext_, ["space", "enter"])
|
|
9038
9072
|
}, [(0, vue.createVNode)(CalendarSlot_default, {
|
|
9039
9073
|
name: "header-next-button",
|
|
9040
|
-
disabled: !
|
|
9074
|
+
disabled: !canMoveNext_.value
|
|
9041
9075
|
}, {
|
|
9042
9076
|
default: (0, vue.withCtx)(() => [(0, vue.createVNode)(BaseIcon_default, {
|
|
9043
9077
|
name: "ChevronRight",
|
|
@@ -9524,7 +9558,7 @@ var CalendarPage_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
9524
9558
|
__name: "CalendarPage",
|
|
9525
9559
|
setup(__props) {
|
|
9526
9560
|
const { page } = usePage();
|
|
9527
|
-
const { onWeeknumberClick } = useCalendar();
|
|
9561
|
+
const { isPeriodLayout, onWeeknumberClick } = useCalendar();
|
|
9528
9562
|
return (_ctx, _cache) => {
|
|
9529
9563
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
9530
9564
|
class: (0, vue.normalizeClass)([
|
|
@@ -9538,8 +9572,13 @@ var CalendarPage_default = /* @__PURE__ */ (0, vue.defineComponent)({
|
|
|
9538
9572
|
}, [(0, vue.createVNode)(CalendarHeader_default, {
|
|
9539
9573
|
page: (0, vue.unref)(page),
|
|
9540
9574
|
"is-lg": "",
|
|
9541
|
-
"hide-arrows":
|
|
9542
|
-
|
|
9575
|
+
"hide-arrows": !(0, vue.unref)(isPeriodLayout),
|
|
9576
|
+
"period-navigation": (0, vue.unref)(isPeriodLayout)
|
|
9577
|
+
}, null, 8, [
|
|
9578
|
+
"page",
|
|
9579
|
+
"hide-arrows",
|
|
9580
|
+
"period-navigation"
|
|
9581
|
+
]), (0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["vc-weeks", { [`vc-show-weeknumbers-${(0, vue.unref)(page).weeknumberPosition}`]: (0, vue.unref)(page).weeknumberPosition }]) }, [(0, vue.createElementVNode)("div", _hoisted_1$3, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)((0, vue.unref)(page).weekdays, ({ weekday, label }, i) => {
|
|
9543
9582
|
return (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
9544
9583
|
key: i,
|
|
9545
9584
|
class: (0, vue.normalizeClass)(`vc-weekday vc-weekday-${weekday}`)
|
|
@@ -9586,7 +9625,10 @@ var Calendar_vue_vue_type_script_lang_default = (0, vue.defineComponent)({
|
|
|
9586
9625
|
});
|
|
9587
9626
|
//#endregion
|
|
9588
9627
|
//#region src/components/Calendar/Calendar.vue
|
|
9589
|
-
var _hoisted_1$2 = {
|
|
9628
|
+
var _hoisted_1$2 = {
|
|
9629
|
+
key: 0,
|
|
9630
|
+
class: "vc-pane-header-wrapper"
|
|
9631
|
+
};
|
|
9590
9632
|
function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
9591
9633
|
const _component_CalendarHeader = (0, vue.resolveComponent)("CalendarHeader");
|
|
9592
9634
|
const _component_CalendarPage = (0, vue.resolveComponent)("CalendarPage");
|
|
@@ -9610,12 +9652,12 @@ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
9610
9652
|
onMouseup: _cache[0] || (_cache[0] = (0, vue.withModifiers)(() => {}, ["prevent"])),
|
|
9611
9653
|
ref: "containerRef"
|
|
9612
9654
|
}), [(0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(["vc-pane-container", { "in-transition": _ctx.inTransition }]) }, [
|
|
9613
|
-
(0, vue.
|
|
9655
|
+
!_ctx.isPeriodLayout ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_1$2, [_ctx.firstPage ? ((0, vue.openBlock)(), (0, vue.createBlock)(_component_CalendarHeader, {
|
|
9614
9656
|
key: 0,
|
|
9615
9657
|
page: _ctx.firstPage,
|
|
9616
9658
|
"is-lg": "",
|
|
9617
9659
|
"hide-title": ""
|
|
9618
|
-
}, null, 8, ["page"])) : (0, vue.createCommentVNode)("", true)]),
|
|
9660
|
+
}, null, 8, ["page"])) : (0, vue.createCommentVNode)("", true)])) : (0, vue.createCommentVNode)("", true),
|
|
9619
9661
|
(0, vue.createVNode)(vue.Transition, {
|
|
9620
9662
|
name: `vc-${_ctx.transitionName}`,
|
|
9621
9663
|
onBeforeEnter: _ctx.onTransitionBeforeEnter,
|
|
@@ -9624,7 +9666,7 @@ function _sfc_render$1(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
9624
9666
|
default: (0, vue.withCtx)(() => [((0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
|
|
9625
9667
|
key: _ctx.pages[0].id,
|
|
9626
9668
|
class: "vc-pane-layout",
|
|
9627
|
-
style: (0, vue.normalizeStyle)({ gridTemplateColumns: `repeat(${_ctx.
|
|
9669
|
+
style: (0, vue.normalizeStyle)({ gridTemplateColumns: `repeat(${_ctx.layoutColumns}, 1fr)` })
|
|
9628
9670
|
}, [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(_ctx.pages, (page) => {
|
|
9629
9671
|
return (0, vue.openBlock)(), (0, vue.createBlock)(_component_CalendarPageProvider, {
|
|
9630
9672
|
key: page.id,
|