vueless 0.0.487 → 0.0.489

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.
@@ -4,7 +4,7 @@ import inputFileConfig from "../../ui.form-input-file/config.js";
4
4
  import dropdownListConfig from "../../ui.dropdown-list/config.js";
5
5
  import modalConfirmConfig from "../../ui.container-modal-confirm/config.js";
6
6
  import tableConfig from "../../ui.data-table/config.js";
7
- import calendarConfig from "../../ui.form-calendar/config.js";
7
+ import calendarConfig from "../../ui.form-calendar/config.ts";
8
8
  import datepickerConfig from "../../ui.form-date-picker/config.js";
9
9
  import datepickerRangeConfig from "../../ui.form-date-picker-range/config.js";
10
10
  import dataListConfig from "../../ui.data-list/config.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.487",
3
+ "version": "0.0.489",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
package/types.ts CHANGED
@@ -5,6 +5,7 @@ import UTextDefaultConfig from "./ui.text-block/config.ts";
5
5
  import UButtonDefaultConfig from "./ui.button/config.ts";
6
6
  import UBadgeDefaultConfig from "./ui.text-badge/config.ts";
7
7
  import UCalendarDefaultConfig from "./ui.form-calendar/config.ts";
8
+ import UDatePickerConfig from "./ui.form-date-picker/config.ts";
8
9
 
9
10
  import type { ComputedRef, MaybeRef, Ref } from "vue";
10
11
  import type { Props } from "tippy.js";
@@ -115,6 +116,7 @@ export interface Components {
115
116
  UButton?: Partial<typeof UButtonDefaultConfig>;
116
117
  UBadge?: Partial<typeof UBadgeDefaultConfig>;
117
118
  UCalendar?: Partial<typeof UCalendarDefaultConfig>;
119
+ UDatePicker?: Partial<typeof UDatePickerConfig>;
118
120
  }
119
121
 
120
122
  export interface Directives {
@@ -110,7 +110,7 @@ const {
110
110
  timepickerSubmitButtonAttrs,
111
111
  } = useAttrs(props);
112
112
 
113
- const wrapperRef = useTemplateRef<HTMLInputElement>("wrapper");
113
+ const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
114
114
  const hoursRef = useTemplateRef<HTMLInputElement>("hours-input");
115
115
  const minutesRef = useTemplateRef<HTMLInputElement>("minutes-input");
116
116
  const secondsRef = useTemplateRef<HTMLInputElement>("seconds-input");
@@ -55,12 +55,6 @@ export const LOCALE_TYPE = {
55
55
  month: "month",
56
56
  };
57
57
 
58
- export const VIEW = {
59
- day: "day",
60
- month: "month",
61
- year: "year",
62
- };
63
-
64
58
  export const ARROW_KEYS: string[] = [
65
59
  KeyCode.ArrowLeft,
66
60
  KeyCode.ArrowUp,
@@ -1,90 +1,16 @@
1
- <template>
2
- <div v-bind="wrapperAttrs" ref="wrapperRef">
3
- <UInput
4
- :id="elementId"
5
- :key="isShownCalendar"
6
- v-model="userFormatDate"
7
- :label-align="labelAlign"
8
- :label="label"
9
- :placeholder="placeholder"
10
- :error="error"
11
- :description="description"
12
- readonly
13
- :disabled="disabled"
14
- :size="size"
15
- :left-icon="leftIcon"
16
- :right-icon="rightIcon"
17
- v-bind="isShownCalendar ? activeInputAttrs : inputAttrs"
18
- @focus="activate"
19
- >
20
- <template #left>
21
- <!-- @slot Use it add something before the date. -->
22
- <slot name="left" />
23
- </template>
24
-
25
- <template #left-icon="{ iconName, iconSize }">
26
- <!--
27
- @slot Use it add an icon before the date.
28
- @binding {string} icon-name
29
- @binding {string} icon-nize
30
- -->
31
- <slot name="left-icon" :icon-name="iconName" :icon-size="iconSize" />
32
- </template>
33
-
34
- <template #right-icon="{ iconName, iconSize }">
35
- <!--
36
- @slot Use it add an icon after the date.
37
- @binding {string} icon-name
38
- @binding {string} icon-size
39
- -->
40
- <slot name="right-icon" :icon-name="iconName" :icon-size="iconSize">
41
- <UIcon :name="iconName" :size="iconSize" color="gray" />
42
- </slot>
43
- </template>
44
-
45
- <template #right>
46
- <!-- @slot Use it add something after the date. -->
47
- <slot name="right" />
48
- </template>
49
- </UInput>
50
-
51
- <Transition v-bind="config.calendarTransition">
52
- <UCalendar
53
- v-show="isShownCalendar"
54
- ref="calendarRef"
55
- v-model="localValue"
56
- v-model:view="customView"
57
- tabindex="-1"
58
- :timepicker="timepicker"
59
- :date-format="dateFormat"
60
- :date-time-format="dateTimeFormat"
61
- :user-date-format="userDateFormat"
62
- :user-date-time-format="userDateTimeFormat"
63
- :max-date="maxDate"
64
- :min-date="minDate"
65
- v-bind="calendarAttrs"
66
- @keydown.esc="deactivate"
67
- @user-date-change="onUserFormatDateChange"
68
- @input="onInput"
69
- @blur="onBlur"
70
- @submit="onSubmit"
71
- />
72
- </Transition>
73
- </div>
74
- </template>
75
-
76
- <script setup>
77
- import { computed, nextTick, ref, useId } from "vue";
1
+ <script setup lang="ts">
2
+ import { computed, nextTick, ref, useId, useTemplateRef } from "vue";
78
3
  import { merge } from "lodash-es";
79
4
 
80
5
  import UIcon from "../ui.image-icon/UIcon.vue";
81
6
  import UInput from "../ui.form-input/UInput.vue";
82
7
  import UCalendar from "../ui.form-calendar/UCalendar.vue";
83
- import { VIEW, STANDARD_USER_FORMAT } from "../ui.form-calendar/constants.js";
8
+ import { View, STANDARD_USER_FORMAT } from "../ui.form-calendar/constants.js";
84
9
 
85
10
  import { getDefault } from "../utils/ui.ts";
86
11
 
87
- import { addDays, isSameDay } from "../ui.form-calendar/utilDate.ts";
12
+ import { addDays, isSameDay } from "../ui.form-calendar/utilDate.js";
13
+ import { parseDate } from "../ui.form-calendar/utilCalendar.ts";
88
14
 
89
15
  import useAttrs from "./useAttrs.js";
90
16
  import { useLocale } from "../composables/useLocale.ts";
@@ -93,188 +19,25 @@ import { useAutoPosition } from "../composables/useAutoPosition.ts";
93
19
  import defaultConfig from "./config.js";
94
20
  import { UDatePicker } from "./constants.js";
95
21
 
96
- defineOptions({ inheritAttrs: false });
97
-
98
- const props = defineProps({
99
- /**
100
- * Datepicker value (JavaScript Date object or string formatted in given `dateFormat`).
101
- */
102
- modelValue: {
103
- type: [Date, String],
104
- default: null,
105
- },
106
-
107
- /**
108
- * Datepicker label.
109
- */
110
- label: {
111
- type: String,
112
- default: "",
113
- },
114
-
115
- /**
116
- * Datepicker label placement.
117
- * @values top, topInside, topWithDesc, left, right
118
- */
119
- labelAlign: {
120
- type: String,
121
- default: getDefault(defaultConfig, UDatePicker).labelAlign,
122
- },
123
-
124
- /**
125
- * Datepicker placeholder.
126
- */
127
- placeholder: {
128
- type: String,
129
- default: "",
130
- },
131
-
132
- /**
133
- * Datepicker description.
134
- */
135
- description: {
136
- type: String,
137
- default: "",
138
- },
139
-
140
- /**
141
- * Datepicker error message.
142
- */
143
- error: {
144
- type: String,
145
- default: "",
146
- },
147
-
148
- /**
149
- * Datepicker size.
150
- * @values sm, md, lg
151
- */
152
- size: {
153
- type: String,
154
- default: getDefault(defaultConfig, UDatePicker).size,
155
- },
156
-
157
- /**
158
- * Datepicker open direction on x-axis.
159
- * @values auto, left, right
160
- */
161
- openDirectionX: {
162
- type: String,
163
- default: getDefault(defaultConfig, UDatePicker).openDirectionX,
164
- },
165
-
166
- /**
167
- * Datepicker open direction on y-axis.
168
- * @values auto, top, bottom
169
- */
170
- openDirectionY: {
171
- type: String,
172
- default: getDefault(defaultConfig, UDatePicker).openDirectionY,
173
- },
174
-
175
- /**
176
- * Min date (JavaScript Date object or string formatted in given `dateFormat`).
177
- */
178
- minDate: {
179
- type: [Date, String],
180
- default: getDefault(defaultConfig, UDatePicker).minDate,
181
- },
182
-
183
- /**
184
- * Max date (JavaScript Date object or string formatted in given `dateFormat`).
185
- */
186
- maxDate: {
187
- type: [Date, String],
188
- default: getDefault(defaultConfig, UDatePicker).maxDate,
189
- },
190
-
191
- /**
192
- * Date string format.
193
- */
194
- dateFormat: {
195
- type: String,
196
- default: getDefault(defaultConfig, UDatePicker).dateFormat,
197
- },
198
-
199
- /**
200
- * Same as date format, but used when timepicker is enabled.
201
- */
202
- dateTimeFormat: {
203
- type: String,
204
- default: getDefault(defaultConfig, UDatePicker).dateTimeFormat,
205
- },
206
-
207
- /**
208
- * User-friendly date format (it will be shown in UI).
209
- */
210
- userDateFormat: {
211
- type: String,
212
- default: getDefault(defaultConfig, UDatePicker).userDateFormat,
213
- },
22
+ import type { UDatePickerProps } from "./types.ts";
214
23
 
215
- /**
216
- * Same as user format, but used when timepicker is enabled.
217
- */
218
- userDateTimeFormat: {
219
- type: String,
220
- default: getDefault(defaultConfig, UDatePicker).userDateTimeFormat,
221
- },
222
-
223
- /**
224
- * Left icon name.
225
- */
226
- leftIcon: {
227
- type: String,
228
- default: "",
229
- },
230
-
231
- /**
232
- * Right icon name.
233
- */
234
- rightIcon: {
235
- type: String,
236
- default: getDefault(defaultConfig, UDatePicker).rightIcon,
237
- },
238
-
239
- /**
240
- * Make datepicker disabled.
241
- */
242
- disabled: {
243
- type: Boolean,
244
- default: getDefault(defaultConfig, UDatePicker).disabled,
245
- },
246
-
247
- /**
248
- * Show timepicker.
249
- */
250
- timepicker: {
251
- type: Boolean,
252
- default: getDefault(defaultConfig, UDatePicker).timepicker,
253
- },
254
-
255
- /**
256
- * Unique element id.
257
- */
258
- id: {
259
- type: String,
260
- default: "",
261
- },
262
-
263
- /**
264
- * Component config object.
265
- */
266
- config: {
267
- type: Object,
268
- default: () => ({}),
269
- },
24
+ defineOptions({ inheritAttrs: false });
270
25
 
271
- /**
272
- * Data-test attribute for automated testing.
273
- */
274
- dataTest: {
275
- type: String,
276
- default: "",
277
- },
26
+ const props = withDefaults(defineProps<UDatePickerProps>(), {
27
+ labelAlign: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).labelAlign,
28
+ size: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).size,
29
+ openDirectionX: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).openDirectionX,
30
+ openDirectionY: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).openDirectionY,
31
+ timepicker: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).timepicker,
32
+ dateFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).dateFormat,
33
+ dateTimeFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).dateTimeFormat,
34
+ userDateFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).userDateFormat,
35
+ userDateTimeFormat: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).userDateTimeFormat,
36
+ leftIcon: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).leftIcon,
37
+ rightIcon: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).rightIcon,
38
+ disabled: getDefault<UDatePickerProps>(defaultConfig, UDatePicker).disabled,
39
+ dataTest: "",
40
+ config: () => ({}),
278
41
  });
279
42
 
280
43
  const emit = defineEmits([
@@ -298,12 +61,12 @@ const i18nGlobal = tm(UDatePicker);
298
61
  const isShownCalendar = ref(false);
299
62
  const userFormatDate = ref("");
300
63
  const formattedDate = ref("");
301
- const customView = ref(VIEW.day);
64
+ const customView = ref(View.Day);
302
65
 
303
- const wrapperRef = ref(null);
304
- const calendarRef = ref(null);
66
+ const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
67
+ const calendarRef = useTemplateRef<InstanceType<typeof UCalendar>>("calendar");
305
68
 
306
- const calendarWrapperRef = computed(() => calendarRef?.value?.wrapperRef);
69
+ const calendarWrapperRef = computed(() => calendarRef?.value?.wrapperRef || null);
307
70
 
308
71
  const { isTop, isRight, adjustPositionY, adjustPositionX } = useAutoPosition(
309
72
  wrapperRef,
@@ -322,7 +85,6 @@ const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props
322
85
  const elementId = props.id || useId();
323
86
 
324
87
  const { config, inputAttrs, activeInputAttrs, calendarAttrs, wrapperAttrs } = useAttrs(props, {
325
- isShownCalendar,
326
88
  isTop,
327
89
  isRight,
328
90
  });
@@ -334,17 +96,17 @@ function activate() {
334
96
  adjustPositionY();
335
97
  adjustPositionX();
336
98
 
337
- calendarRef.value.wrapperRef.focus();
99
+ calendarRef.value?.wrapperRef?.focus();
338
100
  });
339
101
  }
340
102
 
341
103
  function deactivate() {
342
104
  isShownCalendar.value = false;
343
105
 
344
- customView.value = VIEW.day;
106
+ customView.value = View.Day;
345
107
  }
346
108
 
347
- function onUserFormatDateChange(value) {
109
+ function onUserFormatDateChange(value: string) {
348
110
  userFormatDate.value = formatUserDate(value) || "";
349
111
  }
350
112
 
@@ -352,13 +114,13 @@ function onSubmit() {
352
114
  deactivate();
353
115
  }
354
116
 
355
- function onBlur(event) {
117
+ function onBlur(event: FocusEvent) {
356
118
  const { relatedTarget } = event;
357
119
 
358
- if (!calendarRef?.value?.wrapperRef?.contains(relatedTarget)) deactivate();
120
+ if (!calendarRef?.value?.wrapperRef?.contains(relatedTarget as HTMLElement)) deactivate();
359
121
  }
360
122
 
361
- function formatUserDate(data) {
123
+ function formatUserDate(data: string) {
362
124
  if (props.userDateFormat !== STANDARD_USER_FORMAT || props.timepicker) return data;
363
125
 
364
126
  let prefix = "";
@@ -367,9 +129,10 @@ function formatUserDate(data) {
367
129
 
368
130
  const today = new Date();
369
131
 
370
- const isToday = isSameDay(today, localValue.value);
371
- const isYesterday = isSameDay(addDays(today, -1), localValue.value);
372
- const isTomorrow = isSameDay(addDays(today, 1), localValue.value);
132
+ const parsedLocalDate = parseDate(localValue.value, props.dateFormat, currentLocale.value);
133
+ const isToday = parsedLocalDate && isSameDay(today, parsedLocalDate);
134
+ const isYesterday = parsedLocalDate && isSameDay(addDays(today, -1), parsedLocalDate);
135
+ const isTomorrow = parsedLocalDate && isSameDay(addDays(today, 1), parsedLocalDate);
373
136
 
374
137
  if (isToday) {
375
138
  prefix = currentLocale.value.today;
@@ -413,3 +176,78 @@ defineExpose({
413
176
  formattedDate,
414
177
  });
415
178
  </script>
179
+
180
+ <template>
181
+ <div v-bind="wrapperAttrs" ref="wrapper">
182
+ <UInput
183
+ :id="elementId"
184
+ :key="String(isShownCalendar)"
185
+ v-model="userFormatDate"
186
+ :label-align="labelAlign"
187
+ :label="label"
188
+ :placeholder="placeholder"
189
+ :error="error"
190
+ :description="description"
191
+ readonly
192
+ :disabled="disabled"
193
+ :size="size"
194
+ :left-icon="leftIcon"
195
+ :right-icon="rightIcon"
196
+ v-bind="isShownCalendar ? activeInputAttrs : inputAttrs"
197
+ @focus="activate"
198
+ >
199
+ <template #left>
200
+ <!-- @slot Use it add something before the date. -->
201
+ <slot name="left" />
202
+ </template>
203
+
204
+ <template #left-icon="{ iconName, iconSize }">
205
+ <!--
206
+ @slot Use it add an icon before the date.
207
+ @binding {string} icon-name
208
+ @binding {string} icon-nize
209
+ -->
210
+ <slot name="left-icon" :icon-name="iconName" :icon-size="iconSize" />
211
+ </template>
212
+
213
+ <template #right-icon="{ iconName, iconSize }">
214
+ <!--
215
+ @slot Use it add an icon after the date.
216
+ @binding {string} icon-name
217
+ @binding {string} icon-size
218
+ -->
219
+ <slot name="right-icon" :icon-name="iconName" :icon-size="iconSize">
220
+ <UIcon :name="iconName" :size="iconSize" color="gray" />
221
+ </slot>
222
+ </template>
223
+
224
+ <template #right>
225
+ <!-- @slot Use it add something after the date. -->
226
+ <slot name="right" />
227
+ </template>
228
+ </UInput>
229
+
230
+ <Transition v-bind="config.calendarTransition">
231
+ <UCalendar
232
+ v-show="isShownCalendar"
233
+ ref="calendarRef"
234
+ v-model="localValue"
235
+ v-model:view="customView"
236
+ tabindex="-1"
237
+ :timepicker="timepicker"
238
+ :date-format="dateFormat"
239
+ :date-time-format="dateTimeFormat"
240
+ :user-date-format="userDateFormat"
241
+ :user-date-time-format="userDateTimeFormat"
242
+ :max-date="maxDate"
243
+ :min-date="minDate"
244
+ v-bind="calendarAttrs"
245
+ @keydown.esc="deactivate"
246
+ @user-date-change="onUserFormatDateChange"
247
+ @input="onInput"
248
+ @blur="onBlur"
249
+ @submit="onSubmit"
250
+ />
251
+ </Transition>
252
+ </div>
253
+ </template>
@@ -0,0 +1,53 @@
1
+ import { Meta, Title, Subtitle, Description, Primary, Controls, Stories, Source, Markdown } from "@storybook/blocks";
2
+ import { getSource } from "../../utils/storybook.ts";
3
+
4
+ import * as stories from "./stories.ts";
5
+ import defaultConfig from "../config.ts?raw"
6
+
7
+ <Meta of={stories} />
8
+ <Title of={stories} />
9
+ <Subtitle of={stories} />
10
+ <Description of={stories} />
11
+ <Primary of={stories} />
12
+ <Controls of={stories.Default} />
13
+ <Stories of={stories} />
14
+
15
+ ## Default config
16
+ <Source code={getSource(defaultConfig)} language="jsx" dark />
17
+
18
+ ## Formatting tokens
19
+ Each character in the table below can be used in `dateFormat` / `dateTimeFormat` and `userDateFormat` / `userDateTimeFormat` options
20
+ to achieve the format you need.
21
+
22
+ <Markdown>
23
+ {`
24
+ | Token | Description | Example |
25
+ | ----- | --------------------------------------------------------- | ------------------------------------------------------------- |
26
+ | d | Day of the month, 2 digits with leading zeros | 01 to 31 |
27
+ | D | A textual representation of a day | Mon through Sun |
28
+ | l | A full textual representation of the day of the week | Sunday through Saturday |
29
+ | j | Day of the month without leading zeros | 1 to 31 |
30
+ | J | Day of the month without leading zeros and ordinal suffix | 1st, 2nd, to 31st |
31
+ | w | Numeric representation of the day of the week | 0 (for Sunday) through 6 (for Saturday) |
32
+ | W | Numeric representation of the week | 0 (first week of the year) through 52 (last week of the year) |
33
+ | F | A full textual representation of a month | January through December |
34
+ | m | Numeric representation of a month, with leading zero | 01 through 12 |
35
+ | n | Numeric representation of a month, without leading zeros | 1 through 12 |
36
+ | M | A short textual representation of a month | Jan through Dec |
37
+ | U | A short textual representation of a month | 1413704993 |
38
+ | y | A two-digit representation of a year | 99 or 03 |
39
+ | Y | A full numeric representation of a year, 4 digits | 1999 or 2003 |
40
+ | Z | ISO Date format | 2017-03-04T01:23:43.000Z |
41
+ | H | Hours (24 hours) | 00 to 23 |
42
+ | h | Hours | 1 to 12 |
43
+ | G | Hours, 2 digits with leading zeros | 1 to 12 |
44
+ | i | Minutes | 00 to 59 |
45
+ | S | Seconds, 2 digits | 00 to 59 |
46
+ | s | Seconds | 0, 1 to 59 |
47
+ `}
48
+ </Markdown>
49
+
50
+ ## Escaping Formatting Tokens
51
+ You may escape formatting tokens using `\\`.
52
+
53
+ <Source code={`dateFormat: "Y-m-d\\Z", // Displays: 2017-01-22Z`} language="jsx" dark />
@@ -0,0 +1,200 @@
1
+ import type { Meta, StoryFn } from "@storybook/vue3";
2
+ import { getArgTypes, getSlotNames, getSlotsFragment } from "../../utils/storybook.ts";
3
+
4
+ import UDatePicker from "../../ui.form-date-picker/UDatePicker.vue";
5
+ import UIcon from "../../ui.image-icon/UIcon.vue";
6
+ import URow from "../../ui.container-row/URow.vue";
7
+
8
+ import type { UDatePickerProps } from "../types.ts";
9
+
10
+ interface DefaultUDatePickerArgs extends UDatePickerProps {
11
+ slotTemplate?: string;
12
+ }
13
+
14
+ interface EnumUDatePickerArgs extends UDatePickerProps {
15
+ slotTemplate?: string;
16
+ enum: "size";
17
+ }
18
+
19
+ /**
20
+ * The `UDatePicker` component. | [View on GitHub](https://github.com/vuelessjs/vueless/tree/main/src/ui.form-date-picker)
21
+ */
22
+ export default {
23
+ id: "3170",
24
+ title: "Form Inputs & Controls / Date Picker",
25
+ component: UDatePicker,
26
+ args: {
27
+ label: "Label",
28
+ modelValue: null,
29
+ },
30
+ argTypes: {
31
+ ...getArgTypes(UDatePicker.__name),
32
+ },
33
+ parameters: {
34
+ docs: {
35
+ story: {
36
+ height: "480px",
37
+ },
38
+ },
39
+ },
40
+ } as Meta;
41
+
42
+ const DefaultTemplate: StoryFn<DefaultUDatePickerArgs> = (args: DefaultUDatePickerArgs) => ({
43
+ components: { UDatePicker, UIcon },
44
+ setup() {
45
+ const slots = getSlotNames(UDatePicker.__name);
46
+
47
+ return { args, slots };
48
+ },
49
+ template: `
50
+ <UDatePicker open-direction-y="bottom" v-bind="args" v-model="args.modelValue">
51
+ ${args.slotTemplate || getSlotsFragment("")}
52
+ </UDatePicker>
53
+
54
+ <div class="mt-4">
55
+ {{ args.modelValue }}
56
+ </div>
57
+ `,
58
+ });
59
+
60
+ const EnumVariantTemplate: StoryFn<EnumUDatePickerArgs> = (
61
+ args: EnumUDatePickerArgs,
62
+ { argTypes },
63
+ ) => ({
64
+ components: { UDatePicker, URow },
65
+ setup() {
66
+ return {
67
+ args,
68
+ options: argTypes?.[args.enum]?.options,
69
+ };
70
+ },
71
+ template: `
72
+ <URow>
73
+ <UDatePicker
74
+ v-for="(option, index) in options"
75
+ open-direction-y="bottom"
76
+ :key="index"
77
+ v-bind="args"
78
+ :[args.enum]="option"
79
+ :label="option"
80
+ />
81
+ </URow>
82
+ `,
83
+ });
84
+
85
+ const OpenDirectionTemplate: StoryFn<DefaultUDatePickerArgs> = (args: DefaultUDatePickerArgs) => ({
86
+ components: { UDatePicker, URow },
87
+ setup() {
88
+ return {
89
+ args,
90
+ };
91
+ },
92
+ template: `
93
+ <URow class="!flex-col">
94
+ <UDatePicker
95
+ class="w-full"
96
+ open-direction-y="top"
97
+ open-direction-x="left"
98
+ v-bind="args"
99
+ v-model="args.modelValue"
100
+ label="Top Left"
101
+ />
102
+ <UDatePicker
103
+ class="w-full"
104
+ open-direction-y="top"
105
+ open-direction-x="right"
106
+ v-bind="args"
107
+ v-model="args.modelValue"
108
+ label="Top Right"
109
+ />
110
+ <UDatePicker
111
+ class="w-full"
112
+ open-direction-y="bottom"
113
+ open-direction-x="left"
114
+ v-bind="args"
115
+ v-model="args.modelValue"
116
+ label="Bottom Left"
117
+ />
118
+ <UDatePicker
119
+ class="w-full"
120
+ open-direction-y="bottom"
121
+ open-direction-x="right"
122
+ v-bind="args"
123
+ v-model="args.modelValue"
124
+ label="Bottom Right"
125
+ />
126
+ </URow>
127
+ `,
128
+ });
129
+
130
+ export const Default = DefaultTemplate.bind({});
131
+ Default.args = { modelValue: new Date() };
132
+
133
+ export const Sizes = EnumVariantTemplate.bind({});
134
+ Sizes.args = { enum: "size", label: "" };
135
+
136
+ export const OpenDirection = OpenDirectionTemplate.bind({});
137
+ OpenDirection.args = {};
138
+
139
+ export const Description = DefaultTemplate.bind({});
140
+ Description.args = { description: "some description" };
141
+
142
+ export const Disabled = DefaultTemplate.bind({});
143
+ Disabled.args = { disabled: true };
144
+
145
+ export const Error = DefaultTemplate.bind({});
146
+ Error.args = { error: "some error" };
147
+
148
+ export const Placeholder = DefaultTemplate.bind({});
149
+ Placeholder.args = { placeholder: "some placeholder" };
150
+
151
+ export const DateFormat = DefaultTemplate.bind({});
152
+ DateFormat.args = { dateFormat: "d.m.Y", userDateFormat: "d.m.Y", modelValue: "28.06.2024" };
153
+
154
+ export const Timepicker = DefaultTemplate.bind({});
155
+ Timepicker.args = {
156
+ timepicker: true,
157
+ modelValue: new Date(2024, 2, 14, 12, 24, 14),
158
+ userDateFormat: "j F, Y - H:i:S",
159
+ };
160
+
161
+ export const MinMax = DefaultTemplate.bind({});
162
+ MinMax.args = {
163
+ minDate: new Date(2022, 2, 22),
164
+ maxDate: new Date(2022, 2, 26),
165
+ modelValue: new Date(2022, 2, 24),
166
+ };
167
+
168
+ export const LeftIcon = DefaultTemplate.bind({});
169
+ LeftIcon.args = {
170
+ leftIcon: "star",
171
+ };
172
+
173
+ export const RightIcon = DefaultTemplate.bind({});
174
+ RightIcon.args = {
175
+ rightIcon: "star",
176
+ };
177
+
178
+ export const LeftIconSlot = DefaultTemplate.bind({});
179
+ LeftIconSlot.args = {
180
+ slotTemplate: `
181
+ <template #left-icon>
182
+ <UIcon
183
+ name="archive"
184
+ color="red"
185
+ />
186
+ </template>
187
+ `,
188
+ };
189
+
190
+ export const RightIconSlot = DefaultTemplate.bind({});
191
+ RightIconSlot.args = {
192
+ slotTemplate: `
193
+ <template #right-icon>
194
+ <UIcon
195
+ name="archive"
196
+ color="red"
197
+ />
198
+ </template>
199
+ `,
200
+ };
@@ -0,0 +1,119 @@
1
+ import defaultConfig from "./config.ts";
2
+
3
+ export type Config = Partial<typeof defaultConfig>;
4
+
5
+ export interface UDatePickerProps {
6
+ /**
7
+ * Calendar value (JavaScript Date object or string formatted in given `dateFormat` or object when `range` enabled).
8
+ */
9
+ modelValue: Date | string;
10
+
11
+ /**
12
+ * Datepicker label.
13
+ */
14
+ label?: string;
15
+
16
+ /**
17
+ * Datepicker label placement.
18
+ * @values top, topInside, topWithDesc, left, right
19
+ */
20
+ labelAlign?: "top" | "topInside" | "topWithDesc" | "left" | "right";
21
+
22
+ /**
23
+ * Datepicker placeholder.
24
+ */
25
+ placeholder?: string;
26
+
27
+ /**
28
+ * Datepicker description.
29
+ */
30
+ description?: string;
31
+
32
+ /**
33
+ * Datepicker error message.
34
+ */
35
+ error?: string;
36
+
37
+ /**
38
+ * Datepicker size.
39
+ * @values sm, md, lg
40
+ */
41
+ size?: "sm" | "md" | "lg";
42
+
43
+ /**
44
+ * Datepicker open direction on x-axis.
45
+ * @values auto, left, right
46
+ */
47
+ openDirectionX?: "auto" | "left" | "right";
48
+
49
+ /**
50
+ * Datepicker open direction on y-axis.
51
+ * @values auto, top, bottom
52
+ */
53
+ openDirectionY?: "auto" | "top" | "bottom";
54
+
55
+ /**
56
+ * Show timepicker.
57
+ */
58
+ timepicker?: boolean;
59
+
60
+ /**
61
+ * Date string format.
62
+ */
63
+ dateFormat?: string | undefined;
64
+
65
+ /**
66
+ * Same as date format, but used when timepicker is enabled.
67
+ */
68
+ dateTimeFormat?: string;
69
+
70
+ /**
71
+ * User-friendly date format (it will be shown in UI).
72
+ */
73
+ userDateFormat?: string;
74
+
75
+ /**
76
+ * Same as user format, but used when timepicker is enabled.
77
+ */
78
+ userDateTimeFormat?: string;
79
+
80
+ /**
81
+ * Min date (JavaScript Date object or string formatted in given `dateFormat`).
82
+ */
83
+ minDate?: string | Date | undefined;
84
+
85
+ /**
86
+ * Max date (JavaScript Date object or string formatted in given `dateFormat`).
87
+ */
88
+ maxDate?: string | Date | undefined;
89
+
90
+ /**
91
+ * Left icon name.
92
+ */
93
+ leftIcon?: string;
94
+
95
+ /**
96
+ * Right icon name.
97
+ */
98
+ rightIcon?: string;
99
+
100
+ /**
101
+ * Make datepicker disabled.
102
+ */
103
+ disabled?: boolean;
104
+
105
+ /**
106
+ * Unique element id.
107
+ */
108
+ id?: string;
109
+
110
+ /**
111
+ * Component config object.
112
+ */
113
+ config?: Config;
114
+
115
+ /**
116
+ * Data-test attribute for automated testing.
117
+ */
118
+ dataTest?: string;
119
+ }
@@ -0,0 +1,47 @@
1
+ import { computed, watchEffect, type Ref } from "vue";
2
+ import { merge } from "lodash-es";
3
+ import useUI from "../composables/useUI.ts";
4
+
5
+ import defaultConfig from "./config.ts";
6
+ import { Direction } from "../composables/useAutoPosition.ts";
7
+
8
+ import type { UseAttrs } from "../types.ts";
9
+ import type { UDatePickerProps, Config } from "./types.ts";
10
+ import type { Config as UCalendarConfig } from "../ui.form-calendar/types.ts";
11
+
12
+ interface DatePickerState {
13
+ isTop: Ref<boolean>;
14
+ isRight: Ref<boolean>;
15
+ }
16
+
17
+ export default function useAttrs(
18
+ props: UDatePickerProps,
19
+ { isTop, isRight }: DatePickerState,
20
+ ): UseAttrs<Config> {
21
+ const { config, getKeysAttrs, hasSlotContent } = useUI(defaultConfig, () => props.config);
22
+
23
+ const mutatedProps = computed(() => ({
24
+ openDirectionY: isTop.value ? Direction.Top : Direction.Bottom,
25
+ openDirectionX: isRight.value ? Direction.Right : Direction.Left,
26
+ error: Boolean(props.error),
27
+ description: Boolean(props.description),
28
+ }));
29
+
30
+ const keysAttrs = getKeysAttrs(mutatedProps);
31
+
32
+ /* Merging DatePicker's i18n translations into Calendar's i18n translations. */
33
+ watchEffect(() => {
34
+ const calendarAttrs = keysAttrs.calendarAttrs as Ref<{ config: UCalendarConfig }>;
35
+ const calendarConfig = calendarAttrs.value.config || {};
36
+
37
+ if (!calendarConfig.i18n || props.config?.i18n) {
38
+ calendarAttrs.value.config.i18n = merge(calendarConfig.i18n, config.value.i18n);
39
+ }
40
+ });
41
+
42
+ return {
43
+ config,
44
+ ...keysAttrs,
45
+ hasSlotContent,
46
+ };
47
+ }
@@ -4,7 +4,7 @@ import { useLocale as useGlobalLocale } from "../composables/useLocale.ts";
4
4
  import { merge } from "lodash-es";
5
5
  import { getSortedLocale } from "../ui.form-calendar/utilDate.ts";
6
6
 
7
- import { LOCALE_TYPE } from "../ui.form-calendar/constants.js";
7
+ import { LOCALE_TYPE } from "../ui.form-calendar/constants.ts";
8
8
  import { UDatePickerRange } from "./constants.js";
9
9
  import defaultConfig from "./config.js";
10
10
 
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "framework": "vue",
3
3
  "name": "vueless",
4
- "version": "0.0.487",
4
+ "version": "0.0.489",
5
5
  "contributions": {
6
6
  "html": {
7
7
  "description-markup": "markdown",
@@ -2771,24 +2771,29 @@
2771
2771
  "attributes": [
2772
2772
  {
2773
2773
  "name": "modelValue",
2774
- "description": "Datepicker value (JavaScript Date object or string formatted in given `dateFormat`).",
2774
+ "required": true,
2775
+ "description": "Calendar value (JavaScript Date object or string formatted in given `dateFormat` or object when `range` enabled).",
2776
+ "enum": [
2777
+ "Date",
2778
+ "string"
2779
+ ],
2775
2780
  "value": {
2776
2781
  "kind": "expression",
2777
- "type": "date|string"
2778
- },
2779
- "default": "null"
2782
+ "type": "union"
2783
+ }
2780
2784
  },
2781
2785
  {
2782
2786
  "name": "label",
2787
+ "required": false,
2783
2788
  "description": "Datepicker label.",
2784
2789
  "value": {
2785
2790
  "kind": "expression",
2786
2791
  "type": "string"
2787
- },
2788
- "default": "\"\""
2792
+ }
2789
2793
  },
2790
2794
  {
2791
2795
  "name": "labelAlign",
2796
+ "required": false,
2792
2797
  "description": "Datepicker label placement.",
2793
2798
  "enum": [
2794
2799
  "top",
@@ -2799,39 +2804,40 @@
2799
2804
  ],
2800
2805
  "value": {
2801
2806
  "kind": "expression",
2802
- "type": "string"
2807
+ "type": "union"
2803
2808
  },
2804
2809
  "default": "topInside"
2805
2810
  },
2806
2811
  {
2807
2812
  "name": "placeholder",
2813
+ "required": false,
2808
2814
  "description": "Datepicker placeholder.",
2809
2815
  "value": {
2810
2816
  "kind": "expression",
2811
2817
  "type": "string"
2812
- },
2813
- "default": "\"\""
2818
+ }
2814
2819
  },
2815
2820
  {
2816
2821
  "name": "description",
2822
+ "required": false,
2817
2823
  "description": "Datepicker description.",
2818
2824
  "value": {
2819
2825
  "kind": "expression",
2820
2826
  "type": "string"
2821
- },
2822
- "default": "\"\""
2827
+ }
2823
2828
  },
2824
2829
  {
2825
2830
  "name": "error",
2831
+ "required": false,
2826
2832
  "description": "Datepicker error message.",
2827
2833
  "value": {
2828
2834
  "kind": "expression",
2829
2835
  "type": "string"
2830
- },
2831
- "default": "\"\""
2836
+ }
2832
2837
  },
2833
2838
  {
2834
2839
  "name": "size",
2840
+ "required": false,
2835
2841
  "description": "Datepicker size.",
2836
2842
  "enum": [
2837
2843
  "sm",
@@ -2840,12 +2846,13 @@
2840
2846
  ],
2841
2847
  "value": {
2842
2848
  "kind": "expression",
2843
- "type": "string"
2849
+ "type": "union"
2844
2850
  },
2845
2851
  "default": "md"
2846
2852
  },
2847
2853
  {
2848
2854
  "name": "openDirectionX",
2855
+ "required": false,
2849
2856
  "description": "Datepicker open direction on x-axis.",
2850
2857
  "enum": [
2851
2858
  "auto",
@@ -2854,12 +2861,13 @@
2854
2861
  ],
2855
2862
  "value": {
2856
2863
  "kind": "expression",
2857
- "type": "string"
2864
+ "type": "union"
2858
2865
  },
2859
2866
  "default": "auto"
2860
2867
  },
2861
2868
  {
2862
2869
  "name": "openDirectionY",
2870
+ "required": false,
2863
2871
  "description": "Datepicker open direction on y-axis.",
2864
2872
  "enum": [
2865
2873
  "auto",
@@ -2868,36 +2876,36 @@
2868
2876
  ],
2869
2877
  "value": {
2870
2878
  "kind": "expression",
2871
- "type": "string"
2879
+ "type": "union"
2872
2880
  },
2873
2881
  "default": "auto"
2874
2882
  },
2875
2883
  {
2876
- "name": "minDate",
2877
- "description": "Min date (JavaScript Date object or string formatted in given `dateFormat`).",
2878
- "value": {
2879
- "kind": "expression",
2880
- "type": "date|string"
2881
- }
2882
- },
2883
- {
2884
- "name": "maxDate",
2885
- "description": "Max date (JavaScript Date object or string formatted in given `dateFormat`).",
2884
+ "name": "timepicker",
2885
+ "required": false,
2886
+ "description": "Show timepicker.",
2886
2887
  "value": {
2887
2888
  "kind": "expression",
2888
- "type": "date|string"
2889
- }
2889
+ "type": "boolean"
2890
+ },
2891
+ "default": "false"
2890
2892
  },
2891
2893
  {
2892
2894
  "name": "dateFormat",
2895
+ "required": false,
2893
2896
  "description": "Date string format.",
2897
+ "enum": [
2898
+ "string",
2899
+ "undefined"
2900
+ ],
2894
2901
  "value": {
2895
2902
  "kind": "expression",
2896
- "type": "string"
2903
+ "type": "union"
2897
2904
  }
2898
2905
  },
2899
2906
  {
2900
2907
  "name": "dateTimeFormat",
2908
+ "required": false,
2901
2909
  "description": "Same as date format, but used when timepicker is enabled.",
2902
2910
  "value": {
2903
2911
  "kind": "expression",
@@ -2906,6 +2914,7 @@
2906
2914
  },
2907
2915
  {
2908
2916
  "name": "userDateFormat",
2917
+ "required": false,
2909
2918
  "description": "User-friendly date format (it will be shown in UI).",
2910
2919
  "value": {
2911
2920
  "kind": "expression",
@@ -2915,6 +2924,7 @@
2915
2924
  },
2916
2925
  {
2917
2926
  "name": "userDateTimeFormat",
2927
+ "required": false,
2918
2928
  "description": "Same as user format, but used when timepicker is enabled.",
2919
2929
  "value": {
2920
2930
  "kind": "expression",
@@ -2922,17 +2932,47 @@
2922
2932
  },
2923
2933
  "default": "j F, Y - H:i:S"
2924
2934
  },
2935
+ {
2936
+ "name": "minDate",
2937
+ "required": false,
2938
+ "description": "Min date (JavaScript Date object or string formatted in given `dateFormat`).",
2939
+ "enum": [
2940
+ "string",
2941
+ "Date",
2942
+ "undefined"
2943
+ ],
2944
+ "value": {
2945
+ "kind": "expression",
2946
+ "type": "union"
2947
+ }
2948
+ },
2949
+ {
2950
+ "name": "maxDate",
2951
+ "required": false,
2952
+ "description": "Max date (JavaScript Date object or string formatted in given `dateFormat`).",
2953
+ "enum": [
2954
+ "string",
2955
+ "Date",
2956
+ "undefined"
2957
+ ],
2958
+ "value": {
2959
+ "kind": "expression",
2960
+ "type": "union"
2961
+ }
2962
+ },
2925
2963
  {
2926
2964
  "name": "leftIcon",
2965
+ "required": false,
2927
2966
  "description": "Left icon name.",
2928
2967
  "value": {
2929
2968
  "kind": "expression",
2930
2969
  "type": "string"
2931
2970
  },
2932
- "default": "\"\""
2971
+ "default": "getDefault<UDatePickerProps>(defaultConfig, UDatePicker).leftIcon"
2933
2972
  },
2934
2973
  {
2935
2974
  "name": "rightIcon",
2975
+ "required": false,
2936
2976
  "description": "Right icon name.",
2937
2977
  "value": {
2938
2978
  "kind": "expression",
@@ -2942,6 +2982,7 @@
2942
2982
  },
2943
2983
  {
2944
2984
  "name": "disabled",
2985
+ "required": false,
2945
2986
  "description": "Make datepicker disabled.",
2946
2987
  "value": {
2947
2988
  "kind": "expression",
@@ -2949,35 +2990,28 @@
2949
2990
  },
2950
2991
  "default": "false"
2951
2992
  },
2952
- {
2953
- "name": "timepicker",
2954
- "description": "Show timepicker.",
2955
- "value": {
2956
- "kind": "expression",
2957
- "type": "boolean"
2958
- },
2959
- "default": "false"
2960
- },
2961
2993
  {
2962
2994
  "name": "id",
2995
+ "required": false,
2963
2996
  "description": "Unique element id.",
2964
2997
  "value": {
2965
2998
  "kind": "expression",
2966
2999
  "type": "string"
2967
- },
2968
- "default": "\"\""
3000
+ }
2969
3001
  },
2970
3002
  {
2971
3003
  "name": "config",
3004
+ "required": false,
2972
3005
  "description": "Component config object.",
2973
3006
  "value": {
2974
3007
  "kind": "expression",
2975
- "type": "object"
3008
+ "type": "Config"
2976
3009
  },
2977
- "default": "{}"
3010
+ "default": "() => ({})"
2978
3011
  },
2979
3012
  {
2980
3013
  "name": "dataTest",
3014
+ "required": false,
2981
3015
  "description": "Data-test attribute for automated testing.",
2982
3016
  "value": {
2983
3017
  "kind": "expression",
@@ -1,5 +0,0 @@
1
- /*
2
- This const is needed to prevent the issue in script setup:
3
- `defineProps` is referencing locally declared variables. (vue/valid-define-props)
4
- */
5
- export const UDatePicker = "UDatePicker";
@@ -1,34 +0,0 @@
1
- import { computed, watchEffect } from "vue";
2
- import { merge } from "lodash-es";
3
- import useUI from "../composables/useUI.ts";
4
-
5
- import defaultConfig from "./config.js";
6
- import { POSITION } from "../composables/useAutoPosition.ts";
7
-
8
- export default function useAttrs(props, { isTop, isRight }) {
9
- const { config, getKeysAttrs, hasSlotContent } = useUI(defaultConfig, () => props.config);
10
-
11
- const mutatedProps = computed(() => ({
12
- openDirectionY: isTop.value ? POSITION.top : POSITION.bottom,
13
- openDirectionX: isRight.value ? POSITION.right : POSITION.left,
14
- error: Boolean(props.error),
15
- description: Boolean(props.description),
16
- }));
17
-
18
- const keysAttrs = getKeysAttrs(mutatedProps);
19
-
20
- /* Merging DatePicker's i18n translations into Calendar's i18n translations. */
21
- watchEffect(() => {
22
- const calendarConfig = keysAttrs.calendarAttrs.value.config || {};
23
-
24
- if (!calendarConfig.i18n || props.config.i18n) {
25
- keysAttrs.calendarAttrs.value.config.i18n = merge(calendarConfig.i18n, config.value.i18n);
26
- }
27
- });
28
-
29
- return {
30
- config,
31
- ...keysAttrs,
32
- hasSlotContent,
33
- };
34
- }
File without changes