vueless 0.0.319 → 0.0.321

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.319",
3
+ "version": "0.0.321",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless Component Framework.",
6
6
  "homepage": "https://vueless.com",
@@ -99,9 +99,6 @@ const {
99
99
  currentDayAttrs,
100
100
  anotherMonthDayAttrs,
101
101
  dayAttrs,
102
- inRangeFirstDayAttrs,
103
- inRangeLastDayAttrs,
104
- inRangeDayAttrs,
105
102
  } = useAttrs(props);
106
103
 
107
104
  const localSelectedDate = computed(() => {
@@ -227,25 +224,27 @@ function getDayClasses(day) {
227
224
  (!isSelectedDay(day) && !isSelectedToDay(day)) || props.selectedDate === null;
228
225
 
229
226
  if (isToday(day) && isNotSelectedDate) {
230
- return cx([isDayInRange && inRangeDayAttrs.value.class, currentDayAttrs.value.class]);
227
+ return cx([isDayInRange && props.config.inRangeDate, currentDayAttrs.value.class]);
231
228
  }
232
229
 
233
230
  if (props.range && isSelectedDay(day)) {
234
231
  return cx([
235
232
  isAnotherMothDay(day, activeMonthDate.value) && anotherMonthDayAttrs.value.class,
236
- inRangeFirstDayAttrs.value.class,
233
+ props.config.inRangeEdgeDate,
234
+ props.config.inRangeFirstDate,
237
235
  ]);
238
236
  }
239
237
 
240
238
  if (props.range && isSelectedToDay(day)) {
241
239
  return cx([
242
240
  isAnotherMothDay(day, activeMonthDate.value) && anotherMonthDayAttrs.value.class,
243
- inRangeLastDayAttrs.value.class,
241
+ props.config.inRangeEdgeDate,
242
+ props.config.inRangeLastDate,
244
243
  ]);
245
244
  }
246
245
 
247
246
  if (isDayInRange) {
248
- return inRangeDayAttrs.value.class;
247
+ return props.config.inRangeDate;
249
248
  }
250
249
 
251
250
  if (isSelectedDay(day)) {
@@ -17,8 +17,10 @@
17
17
 
18
18
  <script setup>
19
19
  import { computed } from "vue";
20
+
20
21
  import { formatDate, dateIsOutOfRange } from "../services/calendar.service";
21
22
  import { isSameMonth, getDateWithoutTime, isCurrentMoth } from "../services/date.service";
23
+ import { cx } from "../../service.ui";
22
24
 
23
25
  import useAttrs from "../composables/attrs.composable";
24
26
 
@@ -32,6 +34,11 @@ const props = defineProps({
32
34
  required: true,
33
35
  },
34
36
 
37
+ selectedDateTo: {
38
+ type: [Date, null],
39
+ default: undefined,
40
+ },
41
+
35
42
  activeDate: {
36
43
  type: [Date, null],
37
44
  required: true,
@@ -49,7 +56,12 @@ const props = defineProps({
49
56
 
50
57
  dateFormat: {
51
58
  type: String,
52
- required: true,
59
+ default: undefined,
60
+ },
61
+
62
+ range: {
63
+ type: Boolean,
64
+ default: false,
53
65
  },
54
66
 
55
67
  maxDate: {
@@ -101,26 +113,69 @@ function getMonth(monthNumber) {
101
113
  }
102
114
 
103
115
  function getMonthClasses(month) {
116
+ const isMonthInRange =
117
+ props.range &&
118
+ localSelectedDate.value &&
119
+ props.selectedDateTo &&
120
+ !dateIsOutOfRange(
121
+ month,
122
+ props.selectedDate,
123
+ props.selectedDateTo,
124
+ props.locale,
125
+ props.dateFormat,
126
+ );
127
+
104
128
  const isNotSelectedDate =
105
129
  (!isSelectedMonth(month) && !isSelectedMonth(month)) || props.selectedDate === null;
106
130
 
131
+ const isMoreThenOneMonthRange =
132
+ props.selectedDateTo && isMoreThanOneMonthDiff(props.selectedDate, props.selectedDateTo);
133
+
107
134
  if (isCurrentMoth(month) && isNotSelectedDate) {
108
- return [currentMothAttrs.value.class];
135
+ return cx([currentMothAttrs.value.class, isMonthInRange && props.config.inRangeDate]);
136
+ }
137
+
138
+ if (props.range && isSelectedMonth(month) && isMoreThenOneMonthRange) {
139
+ return cx([props.config.inRangeEdgeDate, props.config.inRangeFirstDate]);
140
+ }
141
+
142
+ if (props.range && isSelectedToMonth(month) && isMoreThenOneMonthRange) {
143
+ return cx([props.config.inRangeEdgeDate, props.config.inRangeLastDate]);
144
+ }
145
+
146
+ if (props.range && isSelectedMonth(month) && !isMoreThenOneMonthRange) {
147
+ return cx([props.config.inRangeDate, "rounded-dynamic"]);
148
+ }
149
+
150
+ if (isMonthInRange) {
151
+ return props.config.inRangeDate;
109
152
  }
110
153
 
111
154
  if (isSelectedMonth(month)) {
112
- return [selectedMonthAttrs.value.class];
155
+ return selectedMonthAttrs.value.class;
113
156
  }
114
157
 
115
- if (isSameMonth(props.activeMonth, month)) {
116
- return [activeMonthAttrs.value.class];
158
+ if (isSameMonth(props.activeMonth, month) && !props.range) {
159
+ return activeMonthAttrs.value.class;
117
160
  }
118
161
  }
119
162
 
163
+ function isMoreThanOneMonthDiff(date, dateTo) {
164
+ const yearDiff = Math.abs(dateTo.getFullYear() - date.getFullYear());
165
+ const monthDiff = Math.abs(dateTo.getMonth() - date.getMonth());
166
+ const dayDiff = Math.abs(dateTo.getDate() - date.getDate());
167
+
168
+ return yearDiff > 0 || monthDiff > 1 || (monthDiff === 1 && dayDiff > 0);
169
+ }
170
+
120
171
  function isSelectedMonth(month) {
121
172
  return isSameMonth(month, localSelectedDate.value);
122
173
  }
123
174
 
175
+ function isSelectedToMonth(month) {
176
+ return isSameMonth(month, props.selectedDateTo);
177
+ }
178
+
124
179
  function onClickMonth(month) {
125
180
  emit("input", month);
126
181
  }
@@ -17,8 +17,10 @@
17
17
 
18
18
  <script setup>
19
19
  import { computed } from "vue";
20
+
20
21
  import { formatDate, getYearsRange, dateIsOutOfRange } from "../services/calendar.service";
21
22
  import { isSameMonth, getDateWithoutTime, isCurrentYear } from "../services/date.service";
23
+ import { cx } from "../../service.ui";
22
24
 
23
25
  import useAttrs from "../composables/attrs.composable";
24
26
 
@@ -32,6 +34,11 @@ const props = defineProps({
32
34
  required: true,
33
35
  },
34
36
 
37
+ selectedDateTo: {
38
+ type: [Date, null],
39
+ default: undefined,
40
+ },
41
+
35
42
  activeDate: {
36
43
  type: [Date, null],
37
44
  required: true,
@@ -49,7 +56,12 @@ const props = defineProps({
49
56
 
50
57
  dateFormat: {
51
58
  type: String,
52
- required: true,
59
+ default: undefined,
60
+ },
61
+
62
+ range: {
63
+ type: Boolean,
64
+ default: false,
53
65
  },
54
66
 
55
67
  maxDate: {
@@ -105,19 +117,55 @@ function getYear(year) {
105
117
  }
106
118
 
107
119
  function getYearClasses(year) {
120
+ const isYearInRange =
121
+ props.range &&
122
+ localSelectedDate.value &&
123
+ props.selectedDateTo &&
124
+ !dateIsOutOfRange(
125
+ year,
126
+ props.selectedDate,
127
+ props.selectedDateTo,
128
+ props.locale,
129
+ props.dateFormat,
130
+ );
131
+
108
132
  const isNotSelectedDate =
109
133
  (!isSelectedMonth(year) && !isSelectedMonth(year)) || props.selectedDate === null;
110
134
 
135
+ const isMoreThanOneYearRange =
136
+ props.selectedDateTo &&
137
+ props.selectedDateTo.getFullYear() - props.selectedDate.getFullYear() > 1;
138
+
139
+ const isFirstYear = year.getFullYear() === props.selectedDate.getFullYear();
140
+ const isLastYear =
141
+ props.selectedDateTo && year.getFullYear() === props.selectedDateTo.getFullYear();
142
+
111
143
  if (isCurrentYear(year) && isNotSelectedDate) {
112
- return [currentYearAttrs.value.class];
144
+ return cx([currentYearAttrs.value.class, isYearInRange && props.config.inRangeDate]);
145
+ }
146
+
147
+ if (props.range && isFirstYear && isMoreThanOneYearRange) {
148
+ return cx([props.config.inRangeEdgeDate, props.config.inRangeFirstDate]);
149
+ }
150
+
151
+ if (props.range && isLastYear && isMoreThanOneYearRange) {
152
+ return cx([props.config.inRangeEdgeDate, props.config.inRangeLastDate]);
153
+ }
154
+
155
+ if (props.range && isFirstYear && !isMoreThanOneYearRange) {
156
+ return cx([props.config.inRangeDate, "rounded-dynamic"]);
157
+ }
158
+
159
+ if (isYearInRange) {
160
+ return props.config.inRangeDate;
113
161
  }
114
162
 
115
163
  if (isSelectedMonth(year)) {
116
- return [selectedYearAttrs.value.class];
164
+ return selectedYearAttrs.value.class;
117
165
  }
118
166
 
119
- if (isSameMonth(props.activeMonth, year)) {
120
- return [activeYearAttrs.value.class];
167
+ if (isSameMonth(props.activeMonth, year) && !props.range) {
168
+ return activeYearAttrs.value.class;
121
169
  }
122
170
  }
123
171
 
@@ -17,15 +17,16 @@ export default /*tw*/ {
17
17
  days: "grid grid-cols-7",
18
18
  day: "mx-auto size-8 rounded-dynamic text-sm hover:bg-brand-100 hover:text-brand-600 disabled:opacity-50 disabled:cursor-not-allowed",
19
19
  activeDay: "bg-brand-100 hover:bg-brand-100",
20
- inRangeFirstDay: "rounded-dynamic rounded-r-none bg-brand-200 text-brand-900 hover:bg-brand-200",
21
- inRangeLastDay: "rounded-dynamic rounded-l-none bg-brand-200 text-brand-900 hover:bg-brand-200",
22
- inRangeDay: "bg-brand-100 text-brand-900 hover:!bg-brand-200 rounded-none",
20
+ inRangeDate: "bg-brand-100 text-brand-900 hover:!bg-brand-200 rounded-none",
21
+ inRangeEdgeDate: "rounded-dynamic bg-brand-200 text-brand-900 hover:bg-brand-200",
22
+ inRangeFirstDate: "rounded-r-none",
23
+ inRangeLastDate: "rounded-l-none",
23
24
  selectedDay: "bg-brand-600 text-white hover:bg-brand-600 hover:text-white",
24
25
  currentDay: "hover:bg-brand-100 border-2 border-brand-600",
25
26
  anotherMonthDay: "hover:bg-brand-100 text-gray-400",
26
27
  monthView: "grid grid-cols-4 items-center justify-center",
27
28
  month: "{UButton} mx-auto flex h-12 w-full rounded-dynamic",
28
- selectedMonth: "bg-brand-900 hover:bg-brand-900 text-white",
29
+ selectedMonth: "bg-brand-600 hover:bg-brand-900 text-white",
29
30
  activeMonth: "bg-brand-100",
30
31
  currentMoth: "border-2 border-brand-900",
31
32
  yearView: "grid grid-cols-4 items-center justify-center",
@@ -119,10 +120,12 @@ export default /*tw*/ {
119
120
  okLabel: "Ok",
120
121
  },
121
122
  defaults: {
122
- userFormat: "j F, Y",
123
+ userDateFormat: "j F, Y",
124
+ userDateTimeFormat: "j F, Y - H:i:S",
123
125
  range: false,
124
126
  timepicker: false,
125
127
  dateFormat: undefined,
128
+ dateTimeFormat: undefined,
126
129
  maxDate: undefined,
127
130
  minDate: undefined,
128
131
  /* icons */
@@ -68,4 +68,4 @@ MinMax.args = {
68
68
  };
69
69
 
70
70
  export const DateFormat = DefaultTemplate.bind({});
71
- DateFormat.args = { dateFormat: "d.m.Y", userFormat: "d.m.Y", value: "28.06.2024" };
71
+ DateFormat.args = { dateFormat: "d.m.Y", userDateFormat: "d.m.Y", value: "28.06.2024" };
@@ -11,7 +11,7 @@
11
11
  no-ring
12
12
  size="sm"
13
13
  variant="thirdary"
14
- :right-icon="isCurrentView.day && config.defaults.viewSwitchIcon"
14
+ :right-icon="isCurrentView.day ? config.defaults.viewSwitchIcon : undefined"
15
15
  v-bind="viewSwitchButtonAttrs"
16
16
  @mousedown.prevent.capture
17
17
  @click="onClickViewSwitch"
@@ -60,7 +60,7 @@
60
60
  :active-date="activeDate"
61
61
  :min-date="minDate"
62
62
  :max-date="maxDate"
63
- :date-format="dateFormat"
63
+ :date-format="actualDateFormat"
64
64
  :locale="locale"
65
65
  :config="config"
66
66
  @input="onInputDate"
@@ -69,11 +69,13 @@
69
69
  <MonthView
70
70
  v-if="isCurrentView.month"
71
71
  :selected-date="selectedDate"
72
+ :selected-date-to="selectedDateTo"
73
+ :range="range"
72
74
  :active-month="activeMonth"
73
75
  :active-date="activeDate"
74
76
  :min-date="minDate"
75
77
  :max-date="maxDate"
76
- :date-format="dateFormat"
78
+ :date-format="actualDateFormat"
77
79
  :locale="locale"
78
80
  :config="config"
79
81
  @input="onInput"
@@ -82,11 +84,13 @@
82
84
  <YearView
83
85
  v-if="isCurrentView.year"
84
86
  :selected-date="selectedDate"
87
+ :selected-date-to="selectedDateTo"
88
+ :range="range"
85
89
  :active-month="activeMonth"
86
90
  :active-date="activeDate"
87
91
  :min-date="minDate"
88
92
  :max-date="maxDate"
89
- :date-format="dateFormat"
93
+ :date-format="actualDateFormat"
90
94
  :locale="locale"
91
95
  :config="config"
92
96
  @input="onInput"
@@ -231,12 +235,28 @@ const props = defineProps({
231
235
  default: getDefault(defaultConfig, UCalendar).dateFormat,
232
236
  },
233
237
 
238
+ /**
239
+ * Same as date format, but used when timepicker is enabled.
240
+ */
241
+ dateTimeFormat: {
242
+ type: String,
243
+ default: getDefault(defaultConfig, UCalendar).dateTimeFormat,
244
+ },
245
+
234
246
  /**
235
247
  * User friendly date format.
236
248
  */
237
- userFormat: {
249
+ userDateFormat: {
238
250
  type: String,
239
- default: getDefault(defaultConfig, UCalendar).userFormat,
251
+ default: getDefault(defaultConfig, UCalendar).userDateFormat,
252
+ },
253
+
254
+ /**
255
+ * Same as user format, but used when timepicker is enabled.
256
+ */
257
+ userDateTimeFormat: {
258
+ type: String,
259
+ default: getDefault(defaultConfig, UCalendar).userDateTimeFormat,
240
260
  },
241
261
 
242
262
  /**
@@ -386,6 +406,18 @@ const locale = computed(() => {
386
406
  };
387
407
  });
388
408
 
409
+ const isTimepickerEnabled = computed(() => {
410
+ return props.timepicker && !props.range;
411
+ });
412
+
413
+ const actualDateFormat = computed(() => {
414
+ return isTimepickerEnabled.value ? props.dateTimeFormat : props.dateFormat;
415
+ });
416
+
417
+ const actualUserFormat = computed(() => {
418
+ return isTimepickerEnabled.value ? props.userDateTimeFormat : props.userDateFormat;
419
+ });
420
+
389
421
  const userFormatLocale = computed(() => {
390
422
  const { months, weekdays } = currentLocale.value;
391
423
 
@@ -413,10 +445,6 @@ const userFormatLocale = computed(() => {
413
445
  };
414
446
  });
415
447
 
416
- const isTimepickerEnabled = computed(() => {
417
- return props.timepicker && !props.range;
418
- });
419
-
420
448
  const isModelRangeType = computed(() => {
421
449
  return (
422
450
  props.modelValue !== null &&
@@ -433,22 +461,26 @@ const localValue = computed({
433
461
  const to = isModelRangeType.value ? props.modelValue.to : null;
434
462
 
435
463
  return {
436
- from: parseDate(from || null, props.dateFormat, locale.value),
437
- to: parseDate(to || null, props.dateFormat, locale.value),
464
+ from: parseDate(from || null, actualDateFormat.value, locale.value),
465
+ to: parseDate(to || null, actualDateFormat.value, locale.value),
438
466
  };
439
467
  }
440
468
 
441
469
  return isModelRangeType.value
442
- ? parseDate(props.modelValue.from || null, props.dateFormat, locale.value)
443
- : parseDate(props.modelValue || null, props.dateFormat, locale.value);
470
+ ? parseDate(props.modelValue.from || null, actualDateFormat.value, locale.value)
471
+ : parseDate(props.modelValue || null, actualDateFormat.value, locale.value);
444
472
  },
445
473
  set(value) {
446
474
  value = getCurrentValueType(value);
447
475
 
448
- const parsedDate = parseDate(props.range ? value.from : value, props.dateFormat, locale.value);
476
+ const parsedDate = parseDate(
477
+ props.range ? value.from : value,
478
+ actualDateFormat.value,
479
+ locale.value,
480
+ );
449
481
  const parsedDateTo =
450
482
  isModelRangeType.value && props.range
451
- ? parseDate(value.to, props.dateFormat, locale.value)
483
+ ? parseDate(value.to, actualDateFormat.value, locale.value)
452
484
  : undefined;
453
485
 
454
486
  if (parsedDate && isTimepickerEnabled.value) {
@@ -462,19 +494,19 @@ const localValue = computed({
462
494
  props.minDate,
463
495
  props.maxDate,
464
496
  locale.value,
465
- props.dateFormat,
497
+ actualDateFormat.value,
466
498
  );
467
499
 
468
500
  if (isOutOfRange) {
469
501
  return;
470
502
  }
471
503
 
472
- const newDate = props.dateFormat
473
- ? formatDate(parsedDate || null, props.dateFormat, locale.value)
504
+ const newDate = actualDateFormat.value
505
+ ? formatDate(parsedDate || null, actualDateFormat.value, locale.value)
474
506
  : parsedDate;
475
507
 
476
- const newDateTo = props.dateFormat
477
- ? formatDate(parsedDateTo || null, props.dateFormat, locale.value)
508
+ const newDateTo = actualDateFormat.value
509
+ ? formatDate(parsedDateTo || null, actualDateFormat.value, locale.value)
478
510
  : parsedDateTo;
479
511
 
480
512
  emit("update:modelValue", props.range ? { from: newDate, to: newDateTo } : newDate);
@@ -492,23 +524,25 @@ const localValue = computed({
492
524
  const selectedDate = computed(() => {
493
525
  return parseDate(
494
526
  props.range ? localValue.value.from : localValue.value,
495
- props.dateFormat,
527
+ actualDateFormat.value,
496
528
  locale.value,
497
529
  );
498
530
  });
499
531
 
500
532
  const selectedDateTo = computed(() => {
501
- return props.range ? parseDate(localValue.value.to, props.dateFormat, locale.value) : undefined;
533
+ return props.range
534
+ ? parseDate(localValue.value.to, actualDateFormat.value, locale.value)
535
+ : undefined;
502
536
  });
503
537
 
504
538
  const formattedDate = computed(() => {
505
- return formatDate(selectedDate.value, props.dateFormat, locale.value);
539
+ return formatDate(selectedDate.value, actualDateFormat.value, locale.value);
506
540
  });
507
541
 
508
542
  const userFormattedDate = computed(() => {
509
- const date = formatDate(selectedDate.value, props.userFormat, userFormatLocale.value);
543
+ const date = formatDate(selectedDate.value, actualUserFormat.value, userFormatLocale.value);
510
544
  const dateTo = props.range
511
- ? formatDate(selectedDateTo.value, props.userFormat, userFormatLocale.value)
545
+ ? formatDate(selectedDateTo.value, actualUserFormat.value, userFormatLocale.value)
512
546
  : undefined;
513
547
 
514
548
  return props.range ? `${date} ${SEPARATOR} ${dateTo}` : date;
@@ -699,7 +733,7 @@ function arrowKeyHandler(event) {
699
733
  props.minDate,
700
734
  props.maxDate,
701
735
  locale.value,
702
- props.dateFormat,
736
+ actualDateFormat.value,
703
737
  );
704
738
 
705
739
  if (newActiveDate && !isOutOfRange) {
@@ -108,7 +108,8 @@ export default /*tw*/ {
108
108
  okLabel: "Ok",
109
109
  },
110
110
  defaults: {
111
- userFormat: "j F, Y",
111
+ userDateFormat: "j F, Y",
112
+ userDateTimeFormat: "j F, Y - H:i:S",
112
113
  size: "md",
113
114
  openDirectionX: "auto",
114
115
  openDirectionY: "auto",
@@ -116,6 +117,7 @@ export default /*tw*/ {
116
117
  timepicker: false,
117
118
  disabled: false,
118
119
  dateFormat: undefined,
120
+ dateTimeFormat: undefined,
119
121
  maxDate: undefined,
120
122
  minDate: undefined,
121
123
  },
@@ -133,13 +133,13 @@ export const placeholder = DefaultTemplate.bind({});
133
133
  placeholder.args = { placeholder: "some placeholder" };
134
134
 
135
135
  export const DateFormat = DefaultTemplate.bind({});
136
- DateFormat.args = { dateFormat: "d.m.Y", userFormat: "d.m.Y", modelValue: "28.06.2024" };
136
+ DateFormat.args = { dateFormat: "d.m.Y", userDateFormat: "d.m.Y", modelValue: "28.06.2024" };
137
137
 
138
138
  export const Timepicker = DefaultTemplate.bind({});
139
139
  Timepicker.args = {
140
140
  timepicker: true,
141
141
  modelValue: new Date(2024, 2, 14, 12, 24, 14),
142
- userFormat: "j F, Y - H:i:S",
142
+ userDateFormat: "j F, Y - H:i:S",
143
143
  };
144
144
 
145
145
  export const MinMax = DefaultTemplate.bind({});
@@ -47,7 +47,9 @@
47
47
  tabindex="-1"
48
48
  :timepicker="timepicker"
49
49
  :date-format="dateFormat"
50
- :user-format="userFormat"
50
+ :date-time-format="dateTimeFormat"
51
+ :user-date-format="userFormat"
52
+ :user-date-time-format="userDateTimeFormat"
51
53
  :max-date="maxDate"
52
54
  :min-date="minDate"
53
55
  v-bind="calendarAttrs"
@@ -217,12 +219,28 @@ const props = defineProps({
217
219
  default: getDefault(defaultConfig, UDatePicker).dateFormat,
218
220
  },
219
221
 
222
+ /**
223
+ * Same as date format, but used when timepicker is enabled.
224
+ */
225
+ dateTimeFormat: {
226
+ type: String,
227
+ default: getDefault(defaultConfig, UCalendar).dateTimeFormat,
228
+ },
229
+
220
230
  /**
221
231
  * User friendly date format.
222
232
  */
223
- userFormat: {
233
+ userDateFormat: {
234
+ type: String,
235
+ default: getDefault(defaultConfig, UDatePicker).userDateFormat,
236
+ },
237
+
238
+ /**
239
+ * Same as user format, but used when timepicker is enabled.
240
+ */
241
+ userDateTimeFormat: {
224
242
  type: String,
225
- default: getDefault(defaultConfig, UDatePicker).userFormat,
243
+ default: getDefault(defaultConfig, UCalendar).userDateTimeFormat,
226
244
  },
227
245
 
228
246
  /**
@@ -341,7 +359,7 @@ function onBlur(event) {
341
359
  }
342
360
 
343
361
  function formatUserDate(data) {
344
- if (props.userFormat !== STANDARD_USER_FORMAT) return data;
362
+ if (props.userFormat !== STANDARD_USER_FORMAT || props.timepicker) return data;
345
363
 
346
364
  let prefix = "";
347
365
  const formattedDate = data.charAt(0).toUpperCase() + data.toLowerCase().slice(1);
@@ -44,20 +44,28 @@ export default /*tw*/ {
44
44
  periodDateYearList: "grid grid-cols-3 grid-rows-1 gap-0.5",
45
45
  periodDateQuarterList: "",
46
46
  periodDate: "w-full",
47
+ periodDateInRange: "bg-brand-100 text-brand-900 hover:!bg-brand-200 rounded-none",
48
+ edgePeriodDate: "rounded-dynamic bg-brand-200 text-brand-900 hover:bg-brand-200",
49
+ firstPeriodGridDate: "rounded-r-none",
50
+ lastPeriodGridDate: "rounded-l-none",
51
+ firstPeriodListDate: "rounded-b-none",
52
+ lastPeriodListDate: "rounded-t-none",
47
53
  periodDateActive: "bg-gray-100",
48
- rangeInputWrapper: "flex mt-4 -space-x-px",
54
+ rangeInputWrapper: "flex mt-4 -space-x-px group/range-input-wrapper",
55
+ rangeInputFirst: "group/range-input-first",
56
+ rangeInputLast: "group/range-input-last",
49
57
  rangeInput: {
50
58
  component: "{UInput}",
51
59
  label: {
52
60
  component: "{ULabel}",
53
- wrapper: "group/range-input-wrapper w-full hover:z-10 focus:z-10",
61
+ wrapper: "w-full hover:z-10 focus:z-10",
54
62
  description: "hidden",
55
63
  },
56
64
  block: `
57
65
  focus-within:z-10 focus-within:ring-0
58
- group-first/range-input-wrapper:rounded-r-none group-last/range-input-wrapper:rounded-l-none
66
+ group-[]/range-input-first:rounded-r-none group-[]/range-input-last:rounded-l-none
59
67
  `,
60
- input: "group-first/range-input-wrapper:rounded-r-none group-last/range-input-wrapper:rounded-l-none",
68
+ input: "group-[]/range-input-first:rounded-r-none group-[]/range-input-last:rounded-l-none",
61
69
  },
62
70
  inputRangeError: "text-xs font-normal leading-none mt-2 text-center text-red-500",
63
71
  calendar: {
@@ -150,7 +150,7 @@ MinMax.args = {
150
150
  export const DateFormat = DefaultTemplate.bind({});
151
151
  DateFormat.args = {
152
152
  dateFormat: "d.m.Y",
153
- userFormat: "d.m.Y",
153
+ userDateFormat: "d.m.Y",
154
154
  value: { from: "28.06.2024", to: "30.06.2024" },
155
155
  };
156
156
 
@@ -163,13 +163,13 @@
163
163
 
164
164
  <div v-bind="periodDateListAttrs(getPeriodDateListClasses())">
165
165
  <UButton
166
- v-for="date in periodDateList"
166
+ v-for="(date, index) in periodDateList"
167
167
  :key="date.title"
168
168
  no-ring
169
169
  size="sm"
170
170
  variant="thirdary"
171
171
  :disabled="isDatePeriodOutOfRange(date)"
172
- v-bind="periodDateAttrs(getPeriodDateClasses(date))"
172
+ v-bind="periodDateAttrs(getPeriodDateClasses(date, index))"
173
173
  :label="String(date.title)"
174
174
  @click="selectDate(date), toggleMenu()"
175
175
  />
@@ -183,6 +183,7 @@
183
183
  :error="inputRangeFromError"
184
184
  size="md"
185
185
  v-bind="rangeInputAttrs"
186
+ :class="cx([rangeInputAttrs.class, config.rangeInputFirst])"
186
187
  :name="rangeInputName"
187
188
  @input="onInputRangeInput($event, INPUT_RANGE_TYPE.start)"
188
189
  />
@@ -193,6 +194,7 @@
193
194
  :error="inputRangeToError"
194
195
  size="md"
195
196
  v-bind="rangeInputAttrs"
197
+ :class="cx([rangeInputAttrs.class, config.rangeInputLast])"
196
198
  :name="rangeInputName"
197
199
  @input="onInputRangeInput($event, INPUT_RANGE_TYPE.end)"
198
200
  />
@@ -229,7 +231,7 @@ import { LOCALE_TYPE } from "../ui.form-calendar/constants";
229
231
 
230
232
  import vClickOutside from "../directive.clickOutside";
231
233
 
232
- import { getRandomId, getDefault } from "../service.ui";
234
+ import { getRandomId, getDefault, cx } from "../service.ui";
233
235
 
234
236
  import {
235
237
  addDays,
@@ -811,8 +813,6 @@ function onClickPeriodButton(periodName) {
811
813
 
812
814
  period.value = PERIOD.year;
813
815
  }
814
-
815
- selectDate(periodDateList.value.at(0));
816
816
  }
817
817
 
818
818
  function onClickOwnRange() {
@@ -862,7 +862,7 @@ function onClickShiftDatesList(action) {
862
862
 
863
863
  if (isPeriod.value.week) {
864
864
  activeDate.value = addMonths(activeDate.value, defaultRange);
865
- periodDateList.value = getWeekDateList(activeDate.value, config.value.i18n.months.shorthand);
865
+ periodDateList.value = getWeekDateList(activeDate.value, locale.value.months.shorthand);
866
866
  }
867
867
 
868
868
  if (isPeriod.value.month) {
@@ -885,7 +885,64 @@ function getPeriodButtonsClasses(periodName) {
885
885
  return period.value === periodName ? config.value.periodButtonActive : "";
886
886
  }
887
887
 
888
- function getPeriodDateClasses(date) {
888
+ function getPeriodDateClasses(date, index) {
889
+ const localStart = new Date(localValue.value.from);
890
+ const localEnd = new Date(localValue.value.to);
891
+ const isListType = isPeriod.value.quarter || isPeriod.value.week;
892
+ const firstInRangeClasses = cx([
893
+ config.value.edgePeriodDate,
894
+ isListType ? config.value.firstPeriodListDate : config.value.firstPeriodGridDate,
895
+ ]);
896
+ const lastInRangeClasses = cx([
897
+ config.value.edgePeriodDate,
898
+ isListType ? config.value.lastPeriodListDate : config.value.lastPeriodGridDate,
899
+ ]);
900
+
901
+ if (isPeriod.value.year) {
902
+ localStart.setMonth(0, 1);
903
+ localEnd.setMonth(11, 31);
904
+ }
905
+
906
+ localStart.setHours(0, 0, 0, 0);
907
+ localEnd.setHours(23, 59, 59, 999);
908
+
909
+ const startDateInRangeIndex = periodDateList.value.findIndex((periodDate) => {
910
+ return localStart <= periodDate.endRange && localStart >= periodDate.startRange;
911
+ });
912
+
913
+ const endDateInRangeIndex = periodDateList.value.findIndex((periodDate) => {
914
+ return localEnd >= periodDate.startRange && localEnd <= periodDate.endRange;
915
+ });
916
+
917
+ let isInRange = index >= startDateInRangeIndex && index <= endDateInRangeIndex;
918
+
919
+ if (!~startDateInRangeIndex || !~endDateInRangeIndex) {
920
+ isInRange =
921
+ (index >= startDateInRangeIndex && startDateInRangeIndex > -1) ||
922
+ (index <= endDateInRangeIndex && endDateInRangeIndex > -1);
923
+ }
924
+
925
+ if (
926
+ !~startDateInRangeIndex &&
927
+ periodDateList.value.at(0).startRange > localStart &&
928
+ !~endDateInRangeIndex &&
929
+ periodDateList.value.at(0).endRange < localEnd
930
+ ) {
931
+ isInRange = true;
932
+ }
933
+
934
+ const isSingleItem =
935
+ startDateInRangeIndex === endDateInRangeIndex && ~endDateInRangeIndex && ~startDateInRangeIndex;
936
+
937
+ if (isInRange) {
938
+ return cx([
939
+ config.value.periodDateInRange,
940
+ startDateInRangeIndex === index && firstInRangeClasses,
941
+ endDateInRangeIndex === index && lastInRangeClasses,
942
+ isSingleItem && "rounded-dynamic",
943
+ ]);
944
+ }
945
+
889
946
  return localValue.value.from === date.startRange ? config.value.periodDateActive : "";
890
947
  }
891
948
 
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "framework": "vue",
3
3
  "name": "vueless",
4
- "version": "0.0.319",
4
+ "version": "0.0.321",
5
5
  "contributions": {
6
6
  "html": {
7
7
  "description-markup": "markdown",
@@ -114,6 +114,14 @@
114
114
  "type": "date|null"
115
115
  }
116
116
  },
117
+ {
118
+ "name": "selectedDateTo",
119
+ "value": {
120
+ "kind": "expression",
121
+ "type": "date|null"
122
+ },
123
+ "default": "undefined"
124
+ },
117
125
  {
118
126
  "name": "activeDate",
119
127
  "required": true,
@@ -140,11 +148,19 @@
140
148
  },
141
149
  {
142
150
  "name": "dateFormat",
143
- "required": true,
144
151
  "value": {
145
152
  "kind": "expression",
146
153
  "type": "string"
147
- }
154
+ },
155
+ "default": "undefined"
156
+ },
157
+ {
158
+ "name": "range",
159
+ "value": {
160
+ "kind": "expression",
161
+ "type": "boolean"
162
+ },
163
+ "default": "false"
148
164
  },
149
165
  {
150
166
  "name": "maxDate",
@@ -1204,7 +1220,15 @@
1204
1220
  }
1205
1221
  },
1206
1222
  {
1207
- "name": "userFormat",
1223
+ "name": "dateTimeFormat",
1224
+ "description": "Same as date format, but used when timepicker is enabled.",
1225
+ "value": {
1226
+ "kind": "expression",
1227
+ "type": "string"
1228
+ }
1229
+ },
1230
+ {
1231
+ "name": "userDateFormat",
1208
1232
  "description": "User friendly date format.",
1209
1233
  "value": {
1210
1234
  "kind": "expression",
@@ -1212,6 +1236,15 @@
1212
1236
  },
1213
1237
  "default": "j F, Y"
1214
1238
  },
1239
+ {
1240
+ "name": "userDateTimeFormat",
1241
+ "description": "Same as user format, but used when timepicker is enabled.",
1242
+ "value": {
1243
+ "kind": "expression",
1244
+ "type": "string"
1245
+ },
1246
+ "default": "j F, Y - H:i:S"
1247
+ },
1215
1248
  {
1216
1249
  "name": "minDate",
1217
1250
  "description": "Min date in JS Date Object or Date String formatted in provided props.dateFormat.",
@@ -2423,7 +2456,15 @@
2423
2456
  }
2424
2457
  },
2425
2458
  {
2426
- "name": "userFormat",
2459
+ "name": "dateTimeFormat",
2460
+ "description": "Same as date format, but used when timepicker is enabled.",
2461
+ "value": {
2462
+ "kind": "expression",
2463
+ "type": "string"
2464
+ }
2465
+ },
2466
+ {
2467
+ "name": "userDateFormat",
2427
2468
  "description": "User friendly date format.",
2428
2469
  "value": {
2429
2470
  "kind": "expression",
@@ -2431,6 +2472,15 @@
2431
2472
  },
2432
2473
  "default": "j F, Y"
2433
2474
  },
2475
+ {
2476
+ "name": "userDateTimeFormat",
2477
+ "description": "Same as user format, but used when timepicker is enabled.",
2478
+ "value": {
2479
+ "kind": "expression",
2480
+ "type": "string"
2481
+ },
2482
+ "default": "j F, Y - H:i:S"
2483
+ },
2434
2484
  {
2435
2485
  "name": "id",
2436
2486
  "description": "@ignore: Unique element id.",
@@ -8757,6 +8807,14 @@
8757
8807
  "type": "date|null"
8758
8808
  }
8759
8809
  },
8810
+ {
8811
+ "name": "selectedDateTo",
8812
+ "value": {
8813
+ "kind": "expression",
8814
+ "type": "date|null"
8815
+ },
8816
+ "default": "undefined"
8817
+ },
8760
8818
  {
8761
8819
  "name": "activeDate",
8762
8820
  "required": true,
@@ -8783,11 +8841,19 @@
8783
8841
  },
8784
8842
  {
8785
8843
  "name": "dateFormat",
8786
- "required": true,
8787
8844
  "value": {
8788
8845
  "kind": "expression",
8789
8846
  "type": "string"
8790
- }
8847
+ },
8848
+ "default": "undefined"
8849
+ },
8850
+ {
8851
+ "name": "range",
8852
+ "value": {
8853
+ "kind": "expression",
8854
+ "type": "boolean"
8855
+ },
8856
+ "default": "false"
8791
8857
  },
8792
8858
  {
8793
8859
  "name": "maxDate",