vueless 0.0.568 → 0.0.570

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.
Files changed (90) hide show
  1. package/package.json +1 -1
  2. package/types.ts +14 -0
  3. package/ui.container-accordion/UAccordion.vue +2 -2
  4. package/ui.container-accordion/types.ts +1 -0
  5. package/ui.container-modal/UModal.vue +15 -8
  6. package/ui.container-page/UPage.vue +10 -6
  7. package/ui.form-calendar/UCalendar.vue +14 -25
  8. package/ui.form-calendar/config.ts +3 -0
  9. package/ui.form-calendar/constants.ts +0 -2
  10. package/ui.form-calendar/useAttrs.ts +1 -1
  11. package/ui.form-calendar/utilCalendar.ts +16 -9
  12. package/ui.form-calendar/utilFormatting.ts +63 -11
  13. package/ui.form-checkbox/types.ts +7 -0
  14. package/ui.form-checkbox-group/UCheckboxGroup.vue +1 -1
  15. package/ui.form-checkbox-multi-state/UCheckboxMultiState.vue +4 -1
  16. package/ui.form-color-picker/UColorPicker.vue +67 -147
  17. package/ui.form-color-picker/storybook/Docs.mdx +2 -2
  18. package/ui.form-color-picker/storybook/{stories.js → stories.ts} +13 -5
  19. package/ui.form-color-picker/types.ts +64 -0
  20. package/ui.form-color-picker/useAttrs.ts +15 -0
  21. package/ui.form-date-picker/UDatePicker.vue +109 -43
  22. package/ui.form-date-picker/config.ts +5 -5
  23. package/ui.form-date-picker-range/useAttrs.ts +1 -1
  24. package/ui.form-date-picker-range/useLocale.ts +1 -1
  25. package/ui.form-input/UInput.vue +162 -301
  26. package/ui.form-input/{config.js → config.ts} +3 -0
  27. package/ui.form-input/storybook/Docs.mdx +2 -2
  28. package/ui.form-input/storybook/{stories.js → stories.ts} +14 -6
  29. package/ui.form-input/types.ts +103 -0
  30. package/ui.form-input/useAttrs.ts +31 -0
  31. package/ui.form-input-file/UInputFile.vue +188 -245
  32. package/ui.form-input-file/storybook/Docs.mdx +2 -2
  33. package/ui.form-input-file/storybook/{stories.js → stories.ts} +13 -5
  34. package/ui.form-input-file/types.ts +72 -0
  35. package/ui.form-input-file/useAttrs.ts +21 -0
  36. package/ui.form-input-file/{utilFileForm.js → utilFileForm.ts} +1 -1
  37. package/ui.form-input-money/UInputMoney.vue +76 -223
  38. package/ui.form-input-money/storybook/Docs.mdx +2 -2
  39. package/ui.form-input-money/storybook/{stories.js → stories.ts} +14 -6
  40. package/ui.form-input-money/types.ts +118 -0
  41. package/ui.form-input-money/useAttrs.ts +15 -0
  42. package/ui.form-input-money/{useFormatCurrency.js → useFormatCurrency.ts} +28 -17
  43. package/ui.form-input-money/utilFormat.ts +83 -0
  44. package/ui.form-input-number/UInputNumber.vue +69 -156
  45. package/ui.form-input-number/storybook/Docs.mdx +2 -2
  46. package/ui.form-input-number/storybook/{stories.js → stories.ts} +17 -9
  47. package/ui.form-input-number/types.ts +65 -0
  48. package/ui.form-input-number/useAttrs.ts +15 -0
  49. package/ui.form-input-rating/UInputRating.vue +70 -158
  50. package/ui.form-input-rating/storybook/Docs.mdx +2 -2
  51. package/ui.form-input-rating/storybook/{stories.js → stories.ts} +14 -6
  52. package/ui.form-input-rating/types.ts +67 -0
  53. package/ui.form-input-rating/useAttrs.ts +14 -0
  54. package/ui.form-input-search/UInputSearch.vue +97 -224
  55. package/ui.form-input-search/storybook/Docs.mdx +2 -2
  56. package/ui.form-input-search/storybook/{stories.js → stories.ts} +13 -5
  57. package/ui.form-input-search/types.ts +93 -0
  58. package/ui.form-input-search/useAttrs.ts +15 -0
  59. package/ui.form-radio/URadio.vue +1 -1
  60. package/ui.form-radio-group/URadioGroup.vue +1 -1
  61. package/ui.navigation-pagination/UPagination.vue +15 -15
  62. package/ui.navigation-pagination/types.ts +3 -0
  63. package/ui.navigation-progress/UProgress.vue +16 -2
  64. package/ui.navigation-progress/types.ts +2 -0
  65. package/ui.text-files/UFiles.vue +20 -16
  66. package/ui.text-files/types.ts +1 -1
  67. package/ui.text-notify/UNotify.vue +38 -48
  68. package/ui.text-notify/types.ts +24 -0
  69. package/web-types.json +229 -132
  70. package/ui.form-color-picker/useAttrs.js +0 -9
  71. package/ui.form-input/useAttrs.js +0 -15
  72. package/ui.form-input-file/useAttrs.js +0 -15
  73. package/ui.form-input-money/useAttrs.js +0 -9
  74. package/ui.form-input-money/utilFormat.js +0 -75
  75. package/ui.form-input-number/useAttrs.js +0 -9
  76. package/ui.form-input-rating/useAttrs.js +0 -8
  77. package/ui.form-input-search/useAttrs.js +0 -9
  78. /package/ui.form-color-picker/{config.js → config.ts} +0 -0
  79. /package/ui.form-color-picker/{constants.js → constants.ts} +0 -0
  80. /package/ui.form-input/{constants.js → constants.ts} +0 -0
  81. /package/ui.form-input-file/{config.js → config.ts} +0 -0
  82. /package/ui.form-input-file/{constants.js → constants.ts} +0 -0
  83. /package/ui.form-input-money/{config.js → config.ts} +0 -0
  84. /package/ui.form-input-money/{constants.js → constants.ts} +0 -0
  85. /package/ui.form-input-number/{config.js → config.ts} +0 -0
  86. /package/ui.form-input-number/{constants.js → constants.ts} +0 -0
  87. /package/ui.form-input-rating/{config.js → config.ts} +0 -0
  88. /package/ui.form-input-rating/{constants.js → constants.ts} +0 -0
  89. /package/ui.form-input-search/{config.js → config.ts} +0 -0
  90. /package/ui.form-input-search/{constants.js → constants.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.568",
3
+ "version": "0.0.570",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
package/types.ts CHANGED
@@ -46,6 +46,13 @@ import URadioGroupConfig from "./ui.form-radio-group/config.ts";
46
46
  import USwitchConfig from "./ui.form-switch/config.ts";
47
47
  import UTextareaConfig from "./ui.form-textarea/config.ts";
48
48
  import ULabelConfig from "./ui.form-label/config.ts";
49
+ import UColorPickerConfig from "./ui.form-color-picker/config.ts";
50
+ import UInputConfig from "./ui.form-input/config.ts";
51
+ import UInputNumberConfig from "./ui.form-input-number/config.ts";
52
+ import UInputRatingConfig from "./ui.form-input-rating/config.ts";
53
+ import UInputSearchConfig from "./ui.form-input-search/config.ts";
54
+ import UInputFileConfig from "./ui.form-input-file/config.ts";
55
+ import UInputMoneyConfig from "./ui.form-input-money/config.ts";
49
56
  import UDataListConfig from "./ui.data-list/config.ts";
50
57
 
51
58
  import type { ComputedRef, MaybeRef, Ref, UnwrapRef } from "vue";
@@ -209,6 +216,13 @@ export interface Components {
209
216
  USwitch?: Partial<typeof USwitchConfig>;
210
217
  UTextarea?: Partial<typeof UTextareaConfig>;
211
218
  ULabel?: Partial<typeof ULabelConfig>;
219
+ UColorPicker?: Partial<typeof UColorPickerConfig>;
220
+ UInput?: Partial<typeof UInputConfig>;
221
+ UInputNumber?: Partial<typeof UInputNumberConfig>;
222
+ UInputRating?: Partial<typeof UInputRatingConfig>;
223
+ UInputSearch?: Partial<typeof UInputSearchConfig>;
224
+ UInputFile?: Partial<typeof UInputFileConfig>;
225
+ UInputMoney?: Partial<typeof UInputMoneyConfig>;
212
226
  UDataList?: Partial<typeof UDataListConfig>;
213
227
  }
214
228
 
@@ -9,7 +9,7 @@ import { UAccordion } from "./constants.ts";
9
9
  import defaultConfig from "./config.ts";
10
10
  import useAttrs from "./useAttrs.ts";
11
11
 
12
- import type { UAccordionProps } from "./types.ts";
12
+ import type { UAccordionProps, DividerSize } from "./types.ts";
13
13
 
14
14
  defineOptions({ inheritAttrs: false });
15
15
 
@@ -52,7 +52,7 @@ const dividerSize = computed(() => {
52
52
  lg: "xl",
53
53
  };
54
54
 
55
- return sizes[props.size];
55
+ return sizes[props.size] as DividerSize;
56
56
  });
57
57
 
58
58
  function onClickItem() {
@@ -2,6 +2,7 @@ import defaultConfig from "./config.ts";
2
2
 
3
3
  export type Config = Partial<typeof defaultConfig>;
4
4
 
5
+ export type DividerSize = "md" | "lg" | "xl";
5
6
  export interface UAccordionProps {
6
7
  /**
7
8
  * Accordion title.
@@ -16,9 +16,6 @@ import useAttrs from "./useAttrs.ts";
16
16
  import type { UModalProps } from "./types.ts";
17
17
 
18
18
  defineOptions({ inheritAttrs: false });
19
- const slots = useSlots();
20
-
21
- const wrapperRef = ref(null);
22
19
 
23
20
  const props = withDefaults(defineProps<UModalProps>(), {
24
21
  size: getDefault<UModalProps>(defaultConfig, UModal).size,
@@ -29,6 +26,7 @@ const props = withDefaults(defineProps<UModalProps>(), {
29
26
  noDivider: getDefault<UModalProps>(defaultConfig, UModal).noDivider,
30
27
  mobileStickBottom: getDefault<UModalProps>(defaultConfig, UModal).mobileStickBottom,
31
28
  dataTest: "",
29
+ config: () => ({}),
32
30
  });
33
31
 
34
32
  const emit = defineEmits([
@@ -69,6 +67,10 @@ const {
69
67
  footerRightAttrs,
70
68
  } = useAttrs(props);
71
69
 
70
+ const slots = useSlots();
71
+
72
+ const wrapperRef = ref<HTMLElement | null>(null);
73
+
72
74
  const isShownModal = computed({
73
75
  get: () => props.modelValue,
74
76
  set: (value) => emit("update:modelValue", value),
@@ -94,14 +96,19 @@ const isExistFooter = computed(() => {
94
96
 
95
97
  watch(() => isShownModal.value, preventOverlayFromScrolling);
96
98
 
97
- function preventOverlayFromScrolling(newValue) {
99
+ function preventOverlayFromScrolling(newValue: boolean) {
98
100
  // focus wrapper to be able to close modal on esc
99
101
  setTimeout(() => wrapperRef.value?.focus(), 0);
100
102
 
101
103
  if (newValue) {
102
104
  document.body.style.overflow = "hidden";
103
105
  } else {
104
- document.getElementById(`${elementId}`).style.overflow = "hidden";
106
+ const element = document.getElementById(`${elementId}`);
107
+
108
+ if (element) {
109
+ element.style.overflow = "hidden";
110
+ }
111
+
105
112
  document.body.style.overflow = "auto";
106
113
  }
107
114
  }
@@ -166,7 +173,7 @@ function closeModal() {
166
173
  internal
167
174
  size="xs"
168
175
  color="gray"
169
- :name="config.defaults.backIcon"
176
+ :name="config.defaults?.backIcon"
170
177
  v-bind="backLinkIconAttrs"
171
178
  />
172
179
  </template>
@@ -191,12 +198,12 @@ function closeModal() {
191
198
  @slot Use it to add something instead of the close button.
192
199
  @binding {string} icon-name
193
200
  -->
194
- <slot name="close-button" :icon-name="config.defaults.closeIcon">
201
+ <slot name="close-button" :icon-name="config.defaults?.closeIcon">
195
202
  <UIcon
196
203
  internal
197
204
  interactive
198
205
  size="sm"
199
- :name="config.defaults.closeIcon"
206
+ :name="config.defaults?.closeIcon"
200
207
  v-bind="closeIconAttrs"
201
208
  :data-test="`${dataTest}-close`"
202
209
  @click="onClickCloseModal"
@@ -25,6 +25,7 @@ const props = withDefaults(defineProps<UPageProps>(), {
25
25
  gray: getDefault<UPageProps>(defaultConfig, UPage).gray,
26
26
  fixedRounding: getDefault<UPageProps>(defaultConfig, UPage).fixedRounding,
27
27
  dataTest: "",
28
+ config: () => ({}),
28
29
  });
29
30
 
30
31
  const { isMobileBreakpoint } = useBreakpoint();
@@ -68,11 +69,14 @@ const isShownArrowButton = computed(() => {
68
69
  });
69
70
 
70
71
  onMounted(() => {
71
- const classes = props.gray
72
- ? config.value.htmlBody.split(" ").filter((item) => Boolean(item))
73
- : [];
74
-
75
- document.querySelector("body").classList.add(...classes);
72
+ const classes =
73
+ props.gray && config.value?.htmlBody
74
+ ? config.value.htmlBody.split(" ").filter((item) => Boolean(item))
75
+ : "";
76
+
77
+ if (document.body) {
78
+ document.body.classList.add(...classes);
79
+ }
76
80
  });
77
81
  </script>
78
82
 
@@ -104,7 +108,7 @@ onMounted(() => {
104
108
  internal
105
109
  size="2xs"
106
110
  color="gray"
107
- :name="config.defaults.backIcon"
111
+ :name="config.defaults?.backIcon"
108
112
  v-bind="backLinkIconAttrs"
109
113
  />
110
114
  </template>
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts" generic="TModelValue extends DateValue">
2
- import { computed, ref, watch, useTemplateRef } from "vue";
2
+ import { computed, ref, watch, useTemplateRef, onMounted } from "vue";
3
3
  import { merge } from "lodash-es";
4
4
 
5
5
  import UButton from "../ui.button/UButton.vue";
@@ -195,7 +195,7 @@ const userFormatLocale = computed(() => {
195
195
 
196
196
  // formatted locale
197
197
  return {
198
- ...currentLocale,
198
+ ...currentLocale.value,
199
199
  months: {
200
200
  shorthand: getSortedLocale(months.shorthand, LocaleType.Month),
201
201
  longhand: getSortedLocale(monthsLonghand, LocaleType.Month),
@@ -333,31 +333,19 @@ watch(
333
333
  },
334
334
  );
335
335
 
336
- let isInit = false;
337
-
338
- const unwatchInit = watch(
339
- () => selectedDate.value,
340
- () => {
341
- if (isInit) unwatchInit();
342
-
343
- if (selectedDate.value && isTimepickerEnabled.value && isInputRefs.value && props.timepicker) {
344
- hoursRef.value!.value = String(selectedDate.value.getHours()).padStart(2, "0");
345
- minutesRef.value!.value = String(selectedDate.value.getMinutes()).padStart(2, "0");
346
- secondsRef.value!.value = String(selectedDate.value.getSeconds()).padStart(2, "0");
336
+ onMounted(() => {
337
+ if (selectedDate.value && isTimepickerEnabled.value && isInputRefs.value && props.timepicker) {
338
+ hoursRef.value!.value = String(selectedDate.value.getHours()).padStart(2, "0");
339
+ minutesRef.value!.value = String(selectedDate.value.getMinutes()).padStart(2, "0");
340
+ secondsRef.value!.value = String(selectedDate.value.getSeconds()).padStart(2, "0");
347
341
 
348
- emit("userDateChange", userFormattedDate.value);
349
-
350
- isInit = true;
351
- }
352
-
353
- if (selectedDate.value) {
354
- emit("userDateChange", userFormattedDate.value);
342
+ emit("userDateChange", userFormattedDate.value);
343
+ }
355
344
 
356
- isInit = true;
357
- }
358
- },
359
- { deep: true, immediate: true },
360
- );
345
+ if (selectedDate.value) {
346
+ emit("userDateChange", userFormattedDate.value);
347
+ }
348
+ });
361
349
 
362
350
  function getCurrentValueType(value: DateValue): DateValue {
363
351
  if (props.range && value === null) {
@@ -543,6 +531,7 @@ function enterKeyHandler() {
543
531
  activeMonth.value = null;
544
532
 
545
533
  emit("input", localValue.value);
534
+ emit("submit");
546
535
  }
547
536
 
548
537
  if (isCurrentView.value.month) currentView.value = View.Day;
@@ -70,6 +70,9 @@ export default /*tw*/ {
70
70
  timepickerInputSeconds: "{>timepickerInput} rounded-r-dynamic",
71
71
  timepickerSubmitButton: "{UButton} py-2 border-0",
72
72
  i18n: {
73
+ today: "Today,",
74
+ yesterday: "Yesterday,",
75
+ tomorrow: "Tomorrow,",
73
76
  weekdays: {
74
77
  shorthand: {
75
78
  sunday: "Sun",
@@ -4,8 +4,6 @@
4
4
  */
5
5
  export const UCalendar = "UCalendar";
6
6
 
7
- export const STANDARD_USER_FORMAT = "j F, Y";
8
-
9
7
  export const YEARS_PER_VIEW = 12;
10
8
  export const MONTHS_PER_VIEW = 12;
11
9
  export const START_WEEK = 1;
@@ -1,6 +1,6 @@
1
1
  import useUI from "../composables/useUI.ts";
2
2
 
3
- import defaultConfig from "./config.js";
3
+ import defaultConfig from "./config.ts";
4
4
 
5
5
  import type { UseAttrs } from "../types.ts";
6
6
  import type { UCalendarProps, Config } from "./types.ts";
@@ -49,7 +49,7 @@ export function isNumeric(char: string | number) {
49
49
  return /^\d+$/.test(String(char));
50
50
  }
51
51
 
52
- export function parseDate<TLocale>(
52
+ export function parseDate<TLocale extends DateLocale>(
53
53
  date: Date | string | null,
54
54
  format: string = "Y-m-d H:i:S",
55
55
  locale: TLocale,
@@ -96,7 +96,7 @@ export function parseDate<TLocale>(
96
96
  return parsedDate;
97
97
  }
98
98
 
99
- export function parseStringDate<TLocale>(
99
+ export function parseStringDate<TLocale extends DateLocale>(
100
100
  dateString: string,
101
101
  format = "Y-m-d H:i:S",
102
102
  locale: TLocale,
@@ -108,6 +108,14 @@ export function parseStringDate<TLocale>(
108
108
  } else {
109
109
  let parsedDate = new Date(new Date().getFullYear(), 0, 1, 0, 0, 0, 0);
110
110
 
111
+ const isRelativeDay = [locale.tomorrow, locale.today, locale.tomorrow].some((word) => {
112
+ return dateString.toLowerCase().includes(word.toLowerCase());
113
+ });
114
+
115
+ if (!isRelativeDay) {
116
+ format = format.replaceAll("r", "").trim();
117
+ }
118
+
111
119
  let matched;
112
120
  const operations: Operation[] = [];
113
121
 
@@ -130,20 +138,19 @@ export function parseStringDate<TLocale>(
130
138
  } else if (!isBackSlash) {
131
139
  regexStr += ".";
132
140
  }
141
+ }
133
142
 
134
- operations.forEach((op) => {
135
- const { fn } = op;
136
- const { val } = op;
143
+ operations.forEach((operation) => {
144
+ const { fn, val } = operation;
137
145
 
138
- parsedDate = (fn(parsedDate, String(val), locale as DateLocale) || parsedDate) as Date;
139
- });
140
- }
146
+ parsedDate = (fn(parsedDate, String(val), locale as DateLocale) || parsedDate) as Date;
147
+ });
141
148
 
142
149
  return matched ? parsedDate : undefined;
143
150
  }
144
151
  }
145
152
 
146
- export function dateIsOutOfRange<TLocale>(
153
+ export function dateIsOutOfRange<TLocale extends DateLocale>(
147
154
  date: Date,
148
155
  min: Date | string | undefined,
149
156
  max: Date | string | undefined,
@@ -1,3 +1,5 @@
1
+ import { addDays, isSameDay } from "./utilDate";
2
+
1
3
  export interface DateLocale {
2
4
  weekdays: {
3
5
  shorthand: string[];
@@ -9,6 +11,9 @@ export interface DateLocale {
9
11
  longhand: string[];
10
12
  userFormat?: unknown;
11
13
  };
14
+ today: string;
15
+ tomorrow: string;
16
+ yesterday: string;
12
17
  }
13
18
 
14
19
  const pad = (number: number, length = 2) => `000${number}`.slice(length * -1);
@@ -21,27 +26,41 @@ export const monthToStr = (monthNumber: number, shorthand: boolean, locale: Date
21
26
 
22
27
  export const revFormat = {
23
28
  D: doNothing,
24
- F(dateObj: Date, monthName: string, locale: DateLocale) {
25
- dateObj.setMonth(locale.months.longhand.indexOf(monthName));
29
+
30
+ F: (dateObj: Date, monthName: string, locale: DateLocale) => {
31
+ const monthIndex = locale.months.longhand.findIndex((longMonth) => {
32
+ return longMonth.toLowerCase().trim() === monthName.toLowerCase().trim();
33
+ });
34
+
35
+ dateObj.setMonth(monthIndex);
26
36
  },
37
+
27
38
  G: (dateObj: Date, hour: number | string) => {
28
39
  dateObj.setHours(parseFloat(String(hour)));
29
40
  },
41
+
30
42
  H: (dateObj: Date, hour: number | string) => {
31
43
  dateObj.setHours(parseFloat(String(hour)));
32
44
  },
45
+
33
46
  J: (dateObj: Date, day: number | string) => {
34
47
  dateObj.setDate(parseFloat(String(day)));
35
48
  },
36
- M(dateObj: Date, shortMonth: string, locale: DateLocale) {
37
- dateObj.setMonth(locale.months.shorthand.indexOf(shortMonth));
49
+
50
+ M: (dateObj: Date, monthName: string, locale: DateLocale) => {
51
+ const monthIndex = locale.months.shorthand.findIndex((shortMonth) => {
52
+ return shortMonth.toLowerCase().trim() === monthName.toLowerCase().trim();
53
+ });
54
+
55
+ dateObj.setMonth(monthIndex);
38
56
  },
39
57
  S: (dateObj: Date, seconds: number | string) => {
40
58
  dateObj.setSeconds(parseFloat(String(seconds)));
41
59
  },
60
+
42
61
  U: (_: unknown, unixSeconds: string | number) => new Date(parseFloat(String(unixSeconds)) * 1000),
43
62
 
44
- W(dateObj: Date, weekNum: number | string) {
63
+ W: (dateObj: Date, weekNum: number | string) => {
45
64
  const weekNumber = parseInt(String(weekNum), 10);
46
65
  const date = new Date(dateObj.getFullYear(), 0, 2 + (weekNumber - 1) * 7, 0, 0, 0, 0);
47
66
 
@@ -49,6 +68,7 @@ export const revFormat = {
49
68
 
50
69
  return date;
51
70
  },
71
+
52
72
  Y: (dateObj: Date, year: number | string) => {
53
73
  dateObj.setFullYear(parseFloat(String(year)));
54
74
  },
@@ -57,31 +77,42 @@ export const revFormat = {
57
77
  d: (dateObj: Date, day: number | string) => {
58
78
  dateObj.setDate(parseFloat(String(day)));
59
79
  },
80
+
60
81
  h: (dateObj: Date, hour: number | string) => {
61
82
  dateObj.setHours(parseFloat(String(hour)));
62
83
  },
84
+
63
85
  i: (dateObj: Date, minutes: number | string) => {
64
86
  dateObj.setMinutes(parseFloat(String(minutes)));
65
87
  },
88
+
66
89
  j: (dateObj: Date, day: number | string) => {
67
90
  dateObj.setDate(parseFloat(String(day)));
68
91
  },
92
+
69
93
  l: doNothing,
94
+
70
95
  m: (dateObj: Date, month: number | string) => {
71
96
  dateObj.setMonth(parseFloat(String(month)) - 1);
72
97
  },
98
+
73
99
  n: (dateObj: Date, month: number | string) => {
74
100
  dateObj.setMonth(parseFloat(String(month)) - 1);
75
101
  },
102
+
76
103
  s: (dateObj: Date, seconds: number | string) => {
77
104
  dateObj.setSeconds(parseFloat(String(seconds)));
78
105
  },
106
+
79
107
  u: (_: unknown, unixMillSeconds: number | string) =>
80
108
  new Date(parseFloat(String(unixMillSeconds))),
81
109
  w: doNothing,
110
+
82
111
  y: (dateObj: Date, year: number | string) => {
83
112
  dateObj.setFullYear(2000 + parseFloat(String(year)));
84
113
  },
114
+
115
+ r: doNothing,
85
116
  };
86
117
 
87
118
  export const formats = {
@@ -89,17 +120,17 @@ export const formats = {
89
120
  Z: (date: Date) => date.toISOString(),
90
121
 
91
122
  // weekday name, short, e.g. Thu
92
- D(date: Date, locale: DateLocale) {
123
+ D: (date: Date, locale: DateLocale) => {
93
124
  return locale.weekdays.shorthand[formats.w(date)];
94
125
  },
95
126
 
96
127
  // full month name e.g. January
97
- F(date: Date, locale: DateLocale) {
128
+ F: (date: Date, locale: DateLocale) => {
98
129
  return monthToStr(formats.n(date) - 1, false, locale);
99
130
  },
100
131
 
101
132
  // padded hour 1-12
102
- G(date: Date) {
133
+ G: (date: Date) => {
103
134
  return pad(formats.h(date));
104
135
  },
105
136
 
@@ -107,7 +138,7 @@ export const formats = {
107
138
  H: (date: Date) => pad(date.getHours()),
108
139
 
109
140
  // shorthand month e.g. Jan, Sep, Oct, etc
110
- M(date: Date, locale: DateLocale) {
141
+ M: (date: Date, locale: DateLocale) => {
111
142
  return monthToStr(date.getMonth(), true, locale);
112
143
  },
113
144
 
@@ -117,7 +148,7 @@ export const formats = {
117
148
  // unix timestamp
118
149
  U: (date: Date) => date.getTime() / 1000,
119
150
 
120
- W(date: Date) {
151
+ W: (date: Date) => {
121
152
  // return options.getWeek(date);
122
153
  const localDate = new Date(date.getTime());
123
154
 
@@ -154,7 +185,7 @@ export const formats = {
154
185
  j: (date: Date) => date.getDate(),
155
186
 
156
187
  // weekday name, full, e.g. Thursday
157
- l(date: Date, locale: DateLocale) {
188
+ l: (date: Date, locale: DateLocale) => {
158
189
  return locale.weekdays.longhand[date.getDay()];
159
190
  },
160
191
 
@@ -175,4 +206,25 @@ export const formats = {
175
206
 
176
207
  // last two digits of year e.g. 16 for 2016
177
208
  y: (date: Date) => String(date.getFullYear()).substring(2),
209
+
210
+ r: (date: Date, locale: DateLocale) => {
211
+ const today = new Date();
212
+ const isToday = isSameDay(today, date);
213
+ const isYesterday = isSameDay(addDays(today, -1), date);
214
+ const isTomorrow = isSameDay(addDays(today, 1), date);
215
+
216
+ if (isToday) {
217
+ return `${locale.today}`;
218
+ }
219
+
220
+ if (isYesterday) {
221
+ return `${locale.yesterday}`;
222
+ }
223
+
224
+ if (isTomorrow) {
225
+ return `${locale.tomorrow}`;
226
+ }
227
+
228
+ return "";
229
+ },
178
230
  };
@@ -6,6 +6,13 @@ export type Config = Partial<typeof defaultConfig>;
6
6
 
7
7
  export type IconSize = "2xs" | "xs" | "sm";
8
8
 
9
+ export interface UCheckboxOption {
10
+ value?: unknown;
11
+ label?: string;
12
+ icon?: string;
13
+ description?: string;
14
+ }
15
+
9
16
  export interface UCheckboxProps {
10
17
  /**
11
18
  * Checkbox value.
@@ -79,7 +79,7 @@ function onChangeCheckedItems() {
79
79
  <slot>
80
80
  <UCheckbox
81
81
  v-for="(option, index) in options"
82
- :key="option.value"
82
+ :key="option.id"
83
83
  :model-value="modelValue"
84
84
  :value="option.value"
85
85
  :true-value="option.trueValue"
@@ -9,6 +9,7 @@ import { UCheckboxMultiState } from "./constants.ts";
9
9
  import useAttrs from "./useAttrs.ts";
10
10
 
11
11
  import type { UCheckboxMultiStateProps } from "./types.ts";
12
+ import type { UCheckboxOption } from "../ui.form-checkbox/types.ts";
12
13
 
13
14
  defineOptions({ inheritAttrs: false });
14
15
 
@@ -31,7 +32,9 @@ const emit = defineEmits([
31
32
  const index = ref(0);
32
33
  const isChecked = ref(false);
33
34
 
34
- const selected = computed(() => props?.options?.[index.value] || { icon: undefined });
35
+ const selected = computed<UCheckboxOption>(() => {
36
+ return props.options?.[index.value] || { icon: undefined };
37
+ });
35
38
 
36
39
  const { multiStateCheckboxAttrs } = useAttrs(props, { selected });
37
40