@antify/ui 3.1.27 → 3.2.3

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,162 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ getMonth,
4
+ format,
5
+ addDays,
6
+ subDays,
7
+ } from 'date-fns';
8
+ import {
9
+ computed,
10
+ defineEmits, ref, watch,
11
+ } from 'vue';
12
+ import AntDateSwitcher from './AntDateSwitcher.vue';
13
+ import AntButton from '../AntButton.vue';
14
+
15
+ const props = withDefaults(defineProps<{
16
+ /**
17
+ * The date which should be visible when the date picker is opened
18
+ * as timestamp.
19
+ */
20
+ modelValue: number;
21
+ showWeekend?: boolean;
22
+ showTodayButton?: boolean;
23
+ }>(), {
24
+ showWeekend: false,
25
+ showTodayButton: true,
26
+ });
27
+ const emit = defineEmits([
28
+ 'select',
29
+ 'update:modelValue',
30
+ ]);
31
+
32
+ const COUNT_ROWS = 6;
33
+ const COUNT_COLUMNS = 7;
34
+ const currentMonthIndex = ref(new Date(props.modelValue).getMonth());
35
+ const currentYear = ref(new Date(props.modelValue).getFullYear());
36
+ const matrix = computed(() => {
37
+ /**
38
+ * The picker always starts with Monday.
39
+ * So if the first day of the current month is for example a wednesday,
40
+ * the first two days (Monday and Tuesday) should be from the previous month.
41
+ * Also, the last days of the matrix should be filled with the next month's days.
42
+ */
43
+ const firstDateOfMonth = new Date(currentYear.value, currentMonthIndex.value, 1);
44
+ const _matrix = Array.from({
45
+ length: COUNT_ROWS,
46
+ }, () => Array(COUNT_COLUMNS).fill(null));
47
+
48
+ // Emit on which weekday the first day of the month is.
49
+ const weekdayIndexOfFirstDay = (firstDateOfMonth.getDay() - 1); // 0 is Monday, 6 is Sunday
50
+
51
+ // Subtract the gap from the currentDate
52
+ let currentDate = subDays(firstDateOfMonth, weekdayIndexOfFirstDay);
53
+
54
+ for (let weekIndex = 0; weekIndex < _matrix.length; weekIndex++) {
55
+ for (let weekdayIndex = 0; weekdayIndex < COUNT_COLUMNS; weekdayIndex++) {
56
+ const date = format(currentDate, 'yyyy-MM-dd');
57
+ const isCurrentMonth = getMonth(currentDate) === currentMonthIndex.value;
58
+
59
+ _matrix[weekIndex][weekdayIndex] = {
60
+ date,
61
+ label: format(currentDate, 'd'),
62
+ month: getMonth(currentDate),
63
+ isCurrentMonth,
64
+ isWeekend: weekdayIndex === 5 || weekdayIndex === 6,
65
+ isToday: date === format(Date.now(), 'yyyy-MM-dd') && isCurrentMonth,
66
+ };
67
+
68
+ currentDate = addDays(currentDate, 1);
69
+ }
70
+ }
71
+
72
+ if (props.showWeekend) {
73
+ return _matrix;
74
+ }
75
+
76
+ // Filter out weekends
77
+ return _matrix.map(week => week.filter(day => !day.isWeekend));
78
+ });
79
+ const weekDays = computed(() => {
80
+ // TODO:: Add translation support
81
+ return props.showWeekend
82
+ ? [
83
+ 'M',
84
+ 'D',
85
+ 'M',
86
+ 'D',
87
+ 'F',
88
+ 'S',
89
+ 'S',
90
+ ]
91
+ : [
92
+ 'M',
93
+ 'D',
94
+ 'M',
95
+ 'D',
96
+ 'F',
97
+ ];
98
+ });
99
+
100
+ watch(() => props.modelValue, (val) => {
101
+ const date = new Date(val);
102
+ currentMonthIndex.value = date.getMonth();
103
+ currentYear.value = date.getFullYear();
104
+ });
105
+ </script>
106
+
107
+ <template>
108
+ <div>
109
+ <AntDateSwitcher
110
+ v-model:month="currentMonthIndex"
111
+ v-model:year="currentYear"
112
+ />
113
+
114
+ <div
115
+ class="grid gap-1 p-px"
116
+ :class="{
117
+ 'grid-cols-7': showWeekend,
118
+ 'grid-cols-5': !showWeekend,
119
+ }"
120
+ >
121
+ <div
122
+ v-for="day in weekDays"
123
+ :key="day"
124
+ class="text-for-white-bg-font text-center p-2"
125
+ >
126
+ {{ day }}
127
+ </div>
128
+
129
+ <template
130
+ v-for="week in matrix"
131
+ :key="week"
132
+ >
133
+ <div
134
+ v-for="day in week"
135
+ :key="day.date"
136
+ class="rounded-md flex items-center justify-center p-2 font-semibold cursor-pointer transition-colors"
137
+ :class="{
138
+ 'text-base-400': !day.isCurrentMonth,
139
+ 'text-for-white-bg-font': day.isCurrentMonth,
140
+ 'outline outline-primary-500': day.isToday,
141
+ 'hover:bg-base-200 hover:text-base-200-font': day.date !== format(modelValue, 'yyyy-MM-dd'),
142
+ 'bg-primary-500 text-primary-500-font hover:bg-primary-300 hover:text-primary-300-font': day.date === format(modelValue, 'yyyy-MM-dd'),
143
+ }"
144
+ @click="() => $emit('update:modelValue', new Date(day.date).getTime())"
145
+ >
146
+ {{ day.label }}
147
+ </div>
148
+ </template>
149
+ </div>
150
+
151
+ <div
152
+ v-if="showTodayButton"
153
+ class="flex items-center justify-center p-2"
154
+ >
155
+ <AntButton
156
+ @click="() => $emit('update:modelValue', Date.now())"
157
+ >
158
+ Heute
159
+ </AntButton>
160
+ </div>
161
+ </div>
162
+ </template>
@@ -0,0 +1,148 @@
1
+ <script lang="ts" setup>
2
+ import AntButton from '../AntButton.vue';
3
+ import {
4
+ faChevronLeft,
5
+ faChevronRight,
6
+ } from '@fortawesome/free-solid-svg-icons';
7
+ import {
8
+ Grouped,
9
+ } from '../../enums';
10
+ import AntDropdown from '../AntDropdown.vue';
11
+ import {
12
+ nextTick,
13
+ ref, watch,
14
+ } from 'vue';
15
+ import AntMonthPicker from './AntMonthPicker.vue';
16
+ import AntYearPicker from './AntYearPicker.vue';
17
+
18
+ const props = defineProps<{
19
+ /**
20
+ * Selected month index (0-11).
21
+ */
22
+ month: number;
23
+ year: number;
24
+ }>();
25
+ const emit = defineEmits([
26
+ 'update:month',
27
+ 'update:year',
28
+ ]);
29
+ // TODO:: add translation support
30
+ const options = [
31
+ 'Januar',
32
+ 'Februar',
33
+ 'März',
34
+ 'April',
35
+ 'Mai',
36
+ 'Juni',
37
+ 'Juli',
38
+ 'August',
39
+ 'September',
40
+ 'Oktober',
41
+ 'November',
42
+ 'Dezember',
43
+ ];
44
+ const showMonthDropdown = ref(false);
45
+ const showYearDropdown = ref(false);
46
+ const currentYear = new Date().getFullYear();
47
+ const yearPickerRef = ref<InstanceType<typeof AntYearPicker> | null>(null);
48
+
49
+ watch(showYearDropdown, (val) => {
50
+ if (val) {
51
+ setTimeout(() => {
52
+ yearPickerRef.value?.scrollToYear();
53
+ }, 50);
54
+ }
55
+ });
56
+
57
+ function onSelectYear(year: number) {
58
+ showYearDropdown.value = false;
59
+ emit('update:year', year);
60
+ }
61
+
62
+ function onClickPrevious() {
63
+ if (props.month === 0) {
64
+ emit('update:month', 11);
65
+ nextTick(() => {
66
+ emit('update:year', props.year - 1);
67
+ });
68
+ } else {
69
+ emit('update:month', props.month - 1);
70
+ }
71
+ }
72
+
73
+ function onClickNext() {
74
+ if (props.month === 11) {
75
+ emit('update:month', 0);
76
+ nextTick(() => {
77
+ emit('update:year', props.year + 1);
78
+ });
79
+ } else {
80
+ emit('update:month', props.month + 1);
81
+ }
82
+ }
83
+ </script>
84
+
85
+ <template>
86
+ <div class="flex">
87
+ <AntButton
88
+ :icon-left="faChevronLeft"
89
+ :grouped="Grouped.left"
90
+ @click="onClickPrevious"
91
+ />
92
+ <AntDropdown
93
+ v-model:show-dropdown="showMonthDropdown"
94
+ expanded
95
+ class="-ml-px"
96
+ >
97
+ <AntButton
98
+ :grouped="Grouped.center"
99
+ expanded
100
+ @click="showMonthDropdown = !showMonthDropdown"
101
+ >
102
+ {{ options[month] }}
103
+ </AntButton>
104
+
105
+ <template #content>
106
+ <AntMonthPicker
107
+ :value="month"
108
+ :highlight-current-month="year === currentYear"
109
+ @select="(m) => { emit('update:month', m); showMonthDropdown = false; }"
110
+ />
111
+ </template>
112
+ </AntDropdown>
113
+
114
+ <AntDropdown
115
+ v-model:show-dropdown="showYearDropdown"
116
+ :content-padding="false"
117
+ expanded
118
+ class="-ml-px"
119
+ >
120
+ <AntButton
121
+ :grouped="Grouped.center"
122
+ expanded
123
+ @click="showYearDropdown = !showYearDropdown"
124
+ >
125
+ {{ year }}
126
+ </AntButton>
127
+
128
+ <template #content>
129
+ <AntYearPicker
130
+ ref="yearPickerRef"
131
+ :value="year"
132
+ :highlight-current-month="year === currentYear"
133
+ @select="onSelectYear"
134
+ />
135
+ </template>
136
+ </AntDropdown>
137
+
138
+ <div
139
+ class="-ml-px"
140
+ >
141
+ <AntButton
142
+ :icon-left="faChevronRight"
143
+ :grouped="Grouped.right"
144
+ @click="onClickNext"
145
+ />
146
+ </div>
147
+ </div>
148
+ </template>
@@ -0,0 +1,51 @@
1
+ <script lang="ts" setup>
2
+ withDefaults(
3
+ defineProps<{
4
+ /**
5
+ * Selected month index (0-11).
6
+ */
7
+ value: number;
8
+ highlightCurrentMonth?: boolean;
9
+ }>(),
10
+ {
11
+ highlightCurrentMonth: true,
12
+ },
13
+ );
14
+ defineEmits([
15
+ 'select',
16
+ ]);
17
+
18
+ const months = [
19
+ 'Januar',
20
+ 'Februar',
21
+ 'März',
22
+ 'April',
23
+ 'Mai',
24
+ 'Juni',
25
+ 'Juli',
26
+ 'August',
27
+ 'September',
28
+ 'Oktober',
29
+ 'November',
30
+ 'Dezember',
31
+ ];
32
+ const currentMonthIndex = new Date().getMonth();
33
+ </script>
34
+
35
+ <template>
36
+ <div class="grid grid-cols-3 gap-2">
37
+ <div
38
+ v-for="(month, index) in months"
39
+ :key="index"
40
+ class="p-2 text-center text-for-white-bg-font cursor-pointer rounded-md transition-colors"
41
+ :class="{
42
+ 'outline outline-primary-500': highlightCurrentMonth && index === currentMonthIndex,
43
+ 'bg-primary-500 text-info-500-font hover:bg-primary-300 hover:text-info-300-font': index === value,
44
+ 'hover:bg-base-200 hover:text-base-200-font': index !== value,
45
+ }"
46
+ @click="$emit('select', index)"
47
+ >
48
+ {{ month }}
49
+ </div>
50
+ </div>
51
+ </template>
@@ -0,0 +1,69 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ onMounted, ref,
4
+ } from 'vue';
5
+ import AntButton from '../AntButton.vue';
6
+
7
+ const props = defineProps<{
8
+ value: number;
9
+ }>();
10
+ defineEmits([
11
+ 'select',
12
+ ]);
13
+
14
+ const currentYear = new Date().getFullYear();
15
+ const years = Array.from({
16
+ length: 41,
17
+ }, (_, i) => currentYear + 20 - i);
18
+ const yearListRef = ref<HTMLDivElement | null>(null);
19
+
20
+ /**
21
+ * Scroll to the selected year.
22
+ */
23
+ function scrollToYear() {
24
+ const currentYearElement = yearListRef.value?.querySelector(`[data-year="${props.value}"]`);
25
+
26
+ currentYearElement?.scrollIntoView({
27
+ block: 'center',
28
+ });
29
+ }
30
+
31
+ onMounted(scrollToYear);
32
+
33
+ defineExpose({
34
+ scrollToYear,
35
+ });
36
+ </script>
37
+
38
+ <template>
39
+ <div class="flex flex-col">
40
+ <div
41
+ ref="yearListRef"
42
+ class="h-64 overflow-y-auto flex flex-col gap-2 p-2 border-b border-base-300"
43
+ >
44
+ <div
45
+ v-for="year in years"
46
+ :key="year"
47
+ :data-year="year"
48
+ class="p-2 text-center text-for-white-bg-font cursor-pointer rounded-md transition-colors"
49
+ :class="{
50
+ 'bg-primary-500 text-info-500-font hover:bg-primary-300 hover:text-info-300-font': year === value,
51
+ 'hover:bg-base-200 hover:text-base-200-font': year !== value,
52
+ 'outline outline-primary-500': year === currentYear,
53
+ }"
54
+ @click="$emit('select', year)"
55
+ >
56
+ {{ year }}
57
+ </div>
58
+ </div>
59
+
60
+ <div class="p-2 flex justify-center">
61
+ <AntButton
62
+ expanded
63
+ @click="$emit('select', currentYear)"
64
+ >
65
+ {{ currentYear }}
66
+ </AntButton>
67
+ </div>
68
+ </div>
69
+ </template>
@@ -0,0 +1,6 @@
1
+ import AntCalendar from '../AntDatePicker.vue';
2
+ import { type Meta, type StoryObj } from '@storybook/vue3';
3
+ declare const meta: Meta<typeof AntCalendar>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof AntCalendar>;
6
+ export declare const Docs: Story;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ module.exports = exports.Docs = void 0;
7
+ var _AntDatePicker = _interopRequireDefault(require("../AntDatePicker.vue"));
8
+ var _AntDateSwitcher = _interopRequireDefault(require("../AntDateSwitcher.vue"));
9
+ var _vue = require("vue");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ const meta = {
12
+ title: "Components/DatePicker",
13
+ component: _AntDatePicker.default,
14
+ parameters: {
15
+ controls: {
16
+ sort: "requiredFirst"
17
+ }
18
+ },
19
+ subcomponents: {
20
+ AntDateSwitcher: _AntDateSwitcher.default
21
+ },
22
+ argTypes: {
23
+ onSelect: {
24
+ action: "select"
25
+ }
26
+ }
27
+ };
28
+ module.exports = meta;
29
+ const Docs = exports.Docs = {
30
+ parameters: {
31
+ chromatic: {
32
+ // disableSnapshot: false,
33
+ }
34
+ },
35
+ render: args => ({
36
+ components: {
37
+ AntCalendar: _AntDatePicker.default
38
+ },
39
+ setup() {
40
+ const value = (0, _vue.ref)(Date.now());
41
+ return {
42
+ value,
43
+ args
44
+ };
45
+ },
46
+ template: `
47
+ <div class="p-4">
48
+ <div class="dashed w-64">
49
+ <AntCalendar
50
+ v-bind="args"
51
+ v-model="value"
52
+ />
53
+ </div>
54
+ </div>`
55
+ }),
56
+ args: {}
57
+ };
@@ -0,0 +1,52 @@
1
+ import AntCalendar from "../AntDatePicker.vue";
2
+ import AntDateSwitcher from "../AntDateSwitcher.vue";
3
+ import {
4
+ ref
5
+ } from "vue";
6
+ const meta = {
7
+ title: "Components/DatePicker",
8
+ component: AntCalendar,
9
+ parameters: {
10
+ controls: {
11
+ sort: "requiredFirst"
12
+ }
13
+ },
14
+ subcomponents: {
15
+ AntDateSwitcher
16
+ },
17
+ argTypes: {
18
+ onSelect: {
19
+ action: "select"
20
+ }
21
+ }
22
+ };
23
+ export default meta;
24
+ export const Docs = {
25
+ parameters: {
26
+ chromatic: {
27
+ // disableSnapshot: false,
28
+ }
29
+ },
30
+ render: (args) => ({
31
+ components: {
32
+ AntCalendar
33
+ },
34
+ setup() {
35
+ const value = ref(Date.now());
36
+ return {
37
+ value,
38
+ args
39
+ };
40
+ },
41
+ template: `
42
+ <div class="p-4">
43
+ <div class="dashed w-64">
44
+ <AntCalendar
45
+ v-bind="args"
46
+ v-model="value"
47
+ />
48
+ </div>
49
+ </div>`
50
+ }),
51
+ args: {}
52
+ };
@@ -38,6 +38,7 @@ import AntAccordionItem from './AntAccordionItem.vue';
38
38
  import AntAlert from './AntAlert.vue';
39
39
  import AntCard from './AntCard.vue';
40
40
  import AntContent from './AntContent.vue';
41
+ import AntDatePicker from './calendar/AntDatePicker.vue';
41
42
  import AntDropdown from './AntDropdown.vue';
42
43
  import AntIcon from './AntIcon.vue';
43
44
  import AntKeycap from './AntKeycap.vue';
@@ -52,4 +53,4 @@ import AntTag from './AntTag.vue';
52
53
  import AntToast from './AntToast.vue';
53
54
  import AntToaster from './AntToaster.vue';
54
55
  import AntTooltip from './AntTooltip.vue';
55
- export { AntButton, AntDialog, AntField, AntFormGroup, AntFormGroupLabel, AntBaseInput, AntSelectMenu, AntInputDescription, AntInputLabel, AntInputLimiter, AntCheckbox, AntCheckboxGroup, AntDateInput, AntNumberInput, AntPasswordInput, AntRadio, AntRadioGroup, AntRangeSlider, AntSearch, AntSelect, AntSwitch, AntSwitcher, AntTagInput, AntTextarea, AntTextInput, AntUnitInput, AntImageInput, AntNavLeftLayout, AntNavbar, AntNavbarItem, AntTable, AntTabs, AntTransitionCollapseHeight, AntAccordion, AntAccordionItem, AntAlert, AntCard, AntContent, AntDropdown, AntIcon, AntKeycap, AntListGroup, AntListGroupItem, AntModal, AntPagination, AntPopover, AntSkeleton, AntSpinner, AntTag, AntToast, AntToaster, AntTooltip, AntColorInput, AntMultiSelect, };
56
+ export { AntButton, AntDatePicker, AntDialog, AntField, AntFormGroup, AntFormGroupLabel, AntBaseInput, AntSelectMenu, AntInputDescription, AntInputLabel, AntInputLimiter, AntCheckbox, AntCheckboxGroup, AntDateInput, AntNumberInput, AntPasswordInput, AntRadio, AntRadioGroup, AntRangeSlider, AntSearch, AntSelect, AntSwitch, AntSwitcher, AntTagInput, AntTextarea, AntTextInput, AntUnitInput, AntImageInput, AntNavLeftLayout, AntNavbar, AntNavbarItem, AntTable, AntTabs, AntTransitionCollapseHeight, AntAccordion, AntAccordionItem, AntAlert, AntCard, AntContent, AntDropdown, AntIcon, AntKeycap, AntListGroup, AntListGroupItem, AntModal, AntPagination, AntPopover, AntSkeleton, AntSpinner, AntTag, AntToast, AntToaster, AntTooltip, AntColorInput, AntMultiSelect, };
@@ -69,6 +69,12 @@ Object.defineProperty(exports, "AntDateInput", {
69
69
  return _AntDateInput.default;
70
70
  }
71
71
  });
72
+ Object.defineProperty(exports, "AntDatePicker", {
73
+ enumerable: true,
74
+ get: function () {
75
+ return _AntDatePicker.default;
76
+ }
77
+ });
72
78
  Object.defineProperty(exports, "AntDialog", {
73
79
  enumerable: true,
74
80
  get: function () {
@@ -367,6 +373,7 @@ var _AntAccordionItem = _interopRequireDefault(require("./AntAccordionItem.vue")
367
373
  var _AntAlert = _interopRequireDefault(require("./AntAlert.vue"));
368
374
  var _AntCard = _interopRequireDefault(require("./AntCard.vue"));
369
375
  var _AntContent = _interopRequireDefault(require("./AntContent.vue"));
376
+ var _AntDatePicker = _interopRequireDefault(require("./calendar/AntDatePicker.vue"));
370
377
  var _AntDropdown = _interopRequireDefault(require("./AntDropdown.vue"));
371
378
  var _AntIcon = _interopRequireDefault(require("./AntIcon.vue"));
372
379
  var _AntKeycap = _interopRequireDefault(require("./AntKeycap.vue"));
@@ -38,6 +38,7 @@ import AntAccordionItem from "./AntAccordionItem.vue";
38
38
  import AntAlert from "./AntAlert.vue";
39
39
  import AntCard from "./AntCard.vue";
40
40
  import AntContent from "./AntContent.vue";
41
+ import AntDatePicker from "./calendar/AntDatePicker.vue";
41
42
  import AntDropdown from "./AntDropdown.vue";
42
43
  import AntIcon from "./AntIcon.vue";
43
44
  import AntKeycap from "./AntKeycap.vue";
@@ -54,6 +55,7 @@ import AntToaster from "./AntToaster.vue";
54
55
  import AntTooltip from "./AntTooltip.vue";
55
56
  export {
56
57
  AntButton,
58
+ AntDatePicker,
57
59
  AntDialog,
58
60
  AntField,
59
61
  AntFormGroup,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antify/ui",
3
- "version": "3.1.27",
3
+ "version": "3.2.3",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {