vueless 0.0.603 → 0.0.605

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.
@@ -53,11 +53,12 @@ export default function useUI<T>(
53
53
  : (STRATEGY_TYPE.merge as Strategies);
54
54
 
55
55
  const firstClassKey = Object.keys(defaultConfig || {})[0];
56
- const propsConfig = props.config as ComponentConfig<T>;
57
56
  const config = ref({}) as Ref<ComponentConfig<T>>;
58
57
  const attrs = useAttrs();
59
58
 
60
59
  watchEffect(() => {
60
+ const propsConfig = props.config as ComponentConfig<T>;
61
+
61
62
  config.value = getMergedConfig({
62
63
  defaultConfig,
63
64
  globalConfig,
@@ -93,6 +94,8 @@ export default function useUI<T>(
93
94
  classes = cx([classes, attrs.class]);
94
95
  }
95
96
 
97
+ classes = classes.replaceAll(EXTENDS_PATTERN_REG_EXP, "");
98
+
96
99
  return color ? setColor(classes, color) : classes;
97
100
  });
98
101
  }
@@ -118,12 +121,12 @@ export default function useUI<T>(
118
121
  * Get an element attributes for a given key.
119
122
  */
120
123
  function getAttrs(configKey: string, classes: ComputedRef<string>) {
121
- const nestedComponent = getNestedComponent(config.value[configKey] || "");
124
+ const vuelessAttrs = ref({});
122
125
 
123
126
  const attrs = useAttrs() as KeyAttrs;
124
127
  const isDev = isCSR && import.meta.env?.DEV;
125
- const vuelessAttrs = ref({});
126
128
  const isTopLevelKey = (topLevelClassKey || firstClassKey) === configKey;
129
+ const nestedComponent = getNestedComponent(config.value[configKey] || "");
127
130
 
128
131
  const commonAttrs: KeyAttrs = {
129
132
  ...(isTopLevelKey ? attrs : {}),
@@ -137,34 +140,25 @@ export default function useUI<T>(
137
140
  /* Delete value key to prevent v-model overwrite. */
138
141
  delete commonAttrs.value;
139
142
 
140
- watch(config, updateVuelessAttrs, { immediate: true });
141
- watch(props, updateVuelessAttrs);
142
-
143
- if (classes?.value) {
144
- watch(classes, updateVuelessAttrs);
145
- }
143
+ watch([config, props, classes], updateVuelessAttrs, { immediate: true });
146
144
 
145
+ /**
146
+ * Updating Vueless attributes.
147
+ */
147
148
  function updateVuelessAttrs() {
148
149
  let configAttr: NestedComponent = {};
149
- let extendsConfigAttr: NestedComponent = {};
150
- let extendsClasses: string[] = [];
151
-
152
- const baseClasses = getBaseClasses(config.value[configKey]);
153
- const extendsKeys = getExtendsKeys(baseClasses);
154
150
 
155
151
  if (typeof config.value[configKey] === "object") {
156
152
  configAttr = config.value[configKey] as NestedComponent;
157
153
  }
158
154
 
159
- if (extendsKeys.length) {
160
- extendsClasses = extendsKeys.map((key) => toValue(getClasses(key, mutatedProps)));
161
- extendsConfigAttr = getExtendsConfig(extendsKeys);
162
- }
155
+ const extendsClasses = getExtendsClasses(configKey);
156
+ const extendsConfigAttr = getExtendsConfigAttr(configKey);
163
157
 
164
158
  vuelessAttrs.value = {
165
159
  ...commonAttrs,
166
- class: cx([...extendsClasses, toValue(classes).replaceAll(EXTENDS_PATTERN_REG_EXP, "")]),
167
- config: merge(configAttr, extendsConfigAttr),
160
+ class: cx([...extendsClasses, toValue(classes)]),
161
+ config: merge({}, configAttr, extendsConfigAttr),
168
162
  ...getDefaults({
169
163
  ...(configAttr.defaults || {}),
170
164
  ...(extendsConfigAttr.defaults || {}),
@@ -172,21 +166,54 @@ export default function useUI<T>(
172
166
  };
173
167
  }
174
168
 
169
+ /**
170
+ * Recursively get extends classes.
171
+ */
172
+ function getExtendsClasses(configKey: string) {
173
+ let extendsClasses: string[] = [];
174
+
175
+ const extendsKeys = getExtendsKeys(config.value[configKey]);
176
+
177
+ if (extendsKeys.length) {
178
+ extendsKeys.forEach((key) => {
179
+ if (key === configKey) return;
180
+
181
+ extendsClasses = [
182
+ ...extendsClasses,
183
+ ...getExtendsClasses(key),
184
+ toValue(getClasses(key, mutatedProps)),
185
+ ];
186
+ });
187
+ }
188
+
189
+ return extendsClasses;
190
+ }
191
+
175
192
  /**
176
193
  * Merge extends nested component configs.
177
194
  * TODO: Add ability to merge multiple keys in one (now works for merging only 1 first key).
178
195
  */
179
- function getExtendsConfig(extendsKeys: string[]) {
180
- const [firstKey] = extendsKeys;
181
-
182
- return getMergedConfig({
183
- defaultConfig: config.value[firstKey],
184
- globalConfig: globalConfig[firstKey],
185
- propsConfig: propsConfig[firstKey],
186
- }) as NestedComponent;
196
+ function getExtendsConfigAttr(configKey: string) {
197
+ let extendsConfigAttr: NestedComponent = {};
198
+
199
+ const propsConfig = props.config as ComponentConfig<T>;
200
+ const extendsKeys = getExtendsKeys(config.value[configKey]);
201
+
202
+ if (extendsKeys.length) {
203
+ const [firstKey] = extendsKeys;
204
+
205
+ extendsConfigAttr = getMergedConfig({
206
+ defaultConfig: config.value[firstKey],
207
+ globalConfig: globalConfig[firstKey],
208
+ propsConfig: propsConfig[firstKey],
209
+ }) as NestedComponent;
210
+ }
211
+
212
+ return extendsConfigAttr;
187
213
  }
188
214
 
189
215
  /**
216
+ * Get component prop default value.
190
217
  * Conditionally set props default value for nested components based on parent component prop value.
191
218
  * For example, set icon size for the nested component based on the size of the parent component.
192
219
  * Use an object where key = parent component prop value, value = nested component prop value.
@@ -221,7 +248,8 @@ function getBaseClasses(value: string | CVA | undefined) {
221
248
  * Retrieves extends keys from patterns:
222
249
  * Example: `{>someKey} {>someOtherKey}` >>> `["someKey", "someOtherKey"]`.
223
250
  */
224
- function getExtendsKeys(values: string = ""): string[] {
251
+ function getExtendsKeys(configItemValue?: CVA | string): string[] {
252
+ const values = getBaseClasses(configItemValue);
225
253
  const matches = values.match(EXTENDS_PATTERN_REG_EXP);
226
254
 
227
255
  return matches ? matches?.map((pattern) => pattern.slice(2, -1)) : [];
@@ -249,7 +277,11 @@ function isSystemKey(key: string): boolean {
249
277
  /**
250
278
  * Check is config contains default CVA keys.
251
279
  */
252
- function isCVA(config: UnknownObject): boolean {
280
+ function isCVA(config?: UnknownObject | string): boolean {
281
+ if (typeof config !== "object") {
282
+ return false;
283
+ }
284
+
253
285
  return Object.values(CVA_CONFIG_KEY).some((value) =>
254
286
  Object.keys(config).some((key) => key === value),
255
287
  );
@@ -24,7 +24,6 @@ if (isCSR) {
24
24
  animation: "shift-away",
25
25
  };
26
26
 
27
- settings = merge(defaultSettings, {});
28
27
  settings = merge(defaultSettings, vuelessConfig.directive?.tooltip || {}) as DefaultProps;
29
28
  tippy.setDefaultProps(settings);
30
29
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.603",
3
+ "version": "0.0.605",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
@@ -119,9 +119,9 @@ const { buttonAttrs, loaderAttrs, leftIconAttrs, rightIconAttrs, centerIconAttrs
119
119
  <slot name="right" :icon-name="rightIcon">
120
120
  <UIcon
121
121
  v-if="rightIcon"
122
- internal
123
- color="inherit"
124
122
  :name="rightIcon"
123
+ color="inherit"
124
+ internal
125
125
  v-bind="rightIconAttrs"
126
126
  />
127
127
  </slot>
@@ -49,7 +49,9 @@ const isShownModal = computed({
49
49
  });
50
50
 
51
51
  const i18nGlobal = tm(UModalConfirm);
52
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props?.config?.i18n));
52
+ const currentLocale = computed(() =>
53
+ merge({}, defaultConfig.i18n, i18nGlobal, props?.config?.i18n),
54
+ );
53
55
 
54
56
  function closeModal() {
55
57
  isShownModal.value = false;
@@ -48,7 +48,7 @@ const emit = defineEmits([
48
48
  const { tm } = useLocale();
49
49
 
50
50
  const i18nGlobal = tm(UDataListName);
51
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
51
+ const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
52
52
 
53
53
  const iconSize = computed(() => {
54
54
  const sizes = {
@@ -96,7 +96,7 @@ const stickyActionHeaderRowRef = useTemplateRef<HTMLDivElement>("sticky-action-h
96
96
  const actionHeaderRowRef = useTemplateRef<HTMLDivElement>("action-header-row");
97
97
 
98
98
  const i18nGlobal = tm(UTable);
99
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
99
+ const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
100
100
 
101
101
  const sortedRows: ComputedRef<Row[]> = computed(() => {
102
102
  const headerKeys = props.columns.map((column) =>
@@ -40,14 +40,7 @@ export default /*tw*/ {
40
40
  },
41
41
  headerCellCheckbox: "{>headerCellBase} w-10 pr-2",
42
42
  headerCheckbox: "{UCheckbox}",
43
- headerCounter: {
44
- base: "{>headerCounterBase} absolute top-4 mt-px left-11 ml-px",
45
- variants: {
46
- compact: {
47
- true: "top-3",
48
- },
49
- },
50
- },
43
+ headerCounter: "{>stickyHeaderCounter} mt-px ml-px",
51
44
  headerLoader: "{ULoaderProgress} absolute !top-auto",
52
45
  body: "group/body divide-none",
53
46
  bodyRow: "hover:bg-gray-50",
@@ -108,7 +101,6 @@ export default /*tw*/ {
108
101
  },
109
102
  defaults: {
110
103
  emptyCellLabel: "—",
111
- nesting: false,
112
104
  compact: false,
113
105
  selectable: false,
114
106
  dateDivider: false,
@@ -39,12 +39,12 @@ export default {
39
39
  argTypes: {
40
40
  ...getArgTypes(UTable.__name),
41
41
  row: {
42
- description:
43
- "The row of the table. It's not a prop (it created for ease of work with storybook).",
42
+ table: {
43
+ disable: true,
44
+ },
44
45
  },
45
46
  numberOfRows: {
46
- description:
47
- "The number of table rows. It's not a prop (it created for ease of work with storybook).",
47
+ description: "The number of table rows (not a component prop).",
48
48
  },
49
49
  },
50
50
  args: {
@@ -5,16 +5,7 @@ import type { ComponentConfig, UnknownObject } from "../types.ts";
5
5
 
6
6
  export type Config = typeof defaultConfig;
7
7
 
8
- type RowKeys =
9
- | number
10
- | string
11
- | boolean
12
- | undefined
13
- | Date
14
- | Row
15
- | Row[]
16
- | string
17
- | ((row: Row) => string);
8
+ type RowKeys = number | string | boolean | undefined | Date | Row | Row[] | ((row: Row) => string);
18
9
 
19
10
  export interface CellObject {
20
11
  contentClasses?: string | ((value: unknown | string, row: Row) => string);
@@ -102,7 +102,7 @@ const { config, wrapperAttrs, dropdownBadgeAttrs, dropdownListAttrs, dropdownIco
102
102
  <slot :label="label" :opened="isShownOptions" />
103
103
  </template>
104
104
 
105
- <template #right="{ iconColor }">
105
+ <template #right="{ iconSize }">
106
106
  <!--
107
107
  @slot Use it to add something after the label.
108
108
  @binding {boolean} opened
@@ -111,8 +111,8 @@ const { config, wrapperAttrs, dropdownBadgeAttrs, dropdownListAttrs, dropdownIco
111
111
  <UIcon
112
112
  v-if="!noIcon"
113
113
  internal
114
- :color="iconColor"
115
- :size="size"
114
+ color="inherit"
115
+ :size="iconSize"
116
116
  :name="config.defaults.dropdownIcon"
117
117
  v-bind="dropdownIconAttrs"
118
118
  :data-test="`${dataTest}-dropdown`"
@@ -1,11 +1,10 @@
1
1
  export default /*tw*/ {
2
2
  wrapper: "relative inline-block",
3
3
  dropdownButton: {
4
- base: "{UButton}",
4
+ base: "{UButton} transition",
5
5
  variants: {
6
6
  opened: {
7
7
  true: "group ring-dynamic ring-offset-dynamic ring-{color}-700/15",
8
- false: "reactive-fix", // todo: remove it later
9
8
  },
10
9
  },
11
10
  compoundVariants: [{ opened: true, color: ["grayscale", "white"], class: "ring-gray-700/15" }],
@@ -54,7 +54,7 @@ const elementId = props.id || useId();
54
54
  const { tm } = useLocale();
55
55
 
56
56
  const i18nGlobal = tm(UDropdownList);
57
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
57
+ const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
58
58
 
59
59
  const addOptionKeyCombination = computed(() => {
60
60
  return isMac ? "(⌘ + Enter)" : "(Ctrl + Enter)";
@@ -129,7 +129,7 @@ const isCurrentView = computed(() => ({
129
129
  const i18nGlobal = tm<DefaultLocale>(UCalendar);
130
130
 
131
131
  const currentLocale: ComputedRef<Locale> = computed(() =>
132
- merge(defaultConfig.i18n, i18nGlobal, props.config?.i18n),
132
+ merge({}, defaultConfig.i18n, i18nGlobal, props.config?.i18n),
133
133
  );
134
134
 
135
135
  const locale = computed(() => {
@@ -63,7 +63,9 @@ const userFormatDate = ref("");
63
63
  const formattedDate = ref("");
64
64
  const customView = ref(View.Day);
65
65
 
66
- const datepickerInputRef = useTemplateRef<typeof UInput>("input");
66
+ type UInputRef = InstanceType<typeof UInput>;
67
+
68
+ const datepickerInputRef = useTemplateRef<UInputRef>("input");
67
69
  const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
68
70
  const calendarRef = useTemplateRef<ComponentExposed<typeof UCalendar>>("calendar");
69
71
 
@@ -82,7 +84,7 @@ const localValue = computed({
82
84
  });
83
85
 
84
86
  const currentLocale: ComputedRef<Locale> = computed(() =>
85
- merge(defaultConfig.i18n, i18nGlobal, props.config.i18n),
87
+ merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n),
86
88
  );
87
89
 
88
90
  const clickOutsideOptions = computed(() => ({ ignore: [datepickerInputRef.value?.inputRef] }));
@@ -258,6 +260,7 @@ const mutatedProps = computed(() => ({
258
260
  const {
259
261
  config,
260
262
  wrapperAttrs,
263
+ rightIconAttrs,
261
264
  datepickerInputAttrs,
262
265
  datepickerInputActiveAttrs,
263
266
  datepickerCalendarAttrs,
@@ -268,7 +271,7 @@ watchEffect(() => {
268
271
  const calendarConfig = datepickerCalendarAttrs.value.config as unknown as UCalendarConfig;
269
272
 
270
273
  if (!calendarConfig?.i18n || props.config?.i18n) {
271
- calendarConfig.i18n = merge(calendarConfig.i18n, config.value.i18n);
274
+ calendarConfig.i18n = merge({}, calendarConfig.i18n, config.value.i18n);
272
275
  }
273
276
  });
274
277
  </script>
@@ -318,7 +321,7 @@ watchEffect(() => {
318
321
  @binding {string} icon-size
319
322
  -->
320
323
  <slot name="right-icon" :icon-name="iconName" :icon-size="iconSize">
321
- <UIcon :name="iconName" :size="iconSize" color="gray" />
324
+ <UIcon :name="iconName" :size="iconSize" color="gray" v-bind="rightIconAttrs" />
322
325
  </slot>
323
326
  </template>
324
327
 
@@ -12,6 +12,7 @@ export default /*tw*/ {
12
12
  },
13
13
  },
14
14
  },
15
+ rightIcon: "{UIcon}",
15
16
  datepickerCalendar: {
16
17
  base: "{UCalendar} absolute mb-3 z-40",
17
18
  variants: {
@@ -543,6 +543,7 @@ const mutatedProps = computed(() => ({
543
543
  const {
544
544
  config,
545
545
  wrapperAttrs,
546
+ rightIconAttrs,
546
547
  datepickerCalendarAttrs,
547
548
  datepickerInputAttrs,
548
549
  menuAttrs,
@@ -551,7 +552,7 @@ const {
551
552
  shiftRangeButtonAttrs,
552
553
  rangeInputWrapperAttrs,
553
554
  rangeInputErrorAttrs,
554
- datepickerActiveInputAttrs,
555
+ datepickerInputActiveAttrs,
555
556
  rangeInputFirstAttrs,
556
557
  rangeInputLastAttrs,
557
558
  periodRowAttrs,
@@ -573,7 +574,7 @@ watchEffect(() => {
573
574
  const calendarConfig = datepickerCalendarAttrs.value.config as unknown as UCalendarConfig;
574
575
 
575
576
  if (!calendarConfig.i18n || props.config?.i18n) {
576
- calendarConfig.i18n = merge(calendarConfig.i18n, config.value.i18n);
577
+ calendarConfig.i18n = merge({}, calendarConfig.i18n, config.value.i18n);
577
578
  }
578
579
  });
579
580
  </script>
@@ -595,8 +596,9 @@ watchEffect(() => {
595
596
  readonly
596
597
  :left-icon="leftIcon"
597
598
  :right-icon="rightIcon || config.defaults.calendarIcon"
598
- v-bind="isShownMenu ? datepickerActiveInputAttrs : datepickerInputAttrs"
599
+ v-bind="isShownMenu ? datepickerInputActiveAttrs : datepickerInputAttrs"
599
600
  @focus="activate"
601
+ @keydown.esc="deactivate"
600
602
  >
601
603
  <template #left>
602
604
  <!-- @slot Use it to add something before the date. -->
@@ -608,14 +610,14 @@ watchEffect(() => {
608
610
  <slot name="left-icon" />
609
611
  </template>
610
612
 
611
- <template #right-icon>
613
+ <template #right-icon="{ iconName, iconSize }">
612
614
  <!--
613
615
  @slot Use it add an icon after the date.
614
616
  @binding {string} icon-name
615
617
  @binding {string} icon-size
616
618
  -->
617
- <slot name="right-icon" :icon-name="rightIcon" :icon-size="size">
618
- <UIcon :name="rightIcon" :size="size" color="gray" />
619
+ <slot name="right-icon" :icon-name="iconName" :icon-size="size">
620
+ <UIcon :name="iconName" :size="iconSize" color="gray" v-bind="rightIconAttrs" />
619
621
  </slot>
620
622
  </template>
621
623
 
@@ -12,6 +12,7 @@ export default /*tw*/ {
12
12
  },
13
13
  },
14
14
  },
15
+ rightIcon: "{UIcon}",
15
16
  buttonWrapper: {
16
17
  base: `
17
18
  flex rounded-dynamic max-md:justify-between
@@ -211,7 +212,6 @@ export default /*tw*/ {
211
212
  labelAlign: "topInside",
212
213
  openDirectionX: "auto",
213
214
  openDirectionY: "auto",
214
- timepicker: false,
215
215
  disabled: false,
216
216
  dateFormat: undefined,
217
217
  maxDate: undefined,
@@ -31,6 +31,7 @@ export default {
31
31
  title: "Form Inputs & Controls / Date Picker Range",
32
32
  component: UDatePickerRange,
33
33
  args: {
34
+ label: "Datepicker range",
34
35
  modelValue: {
35
36
  from: new Date(2022, 1, 14),
36
37
  to: new Date(2022, 2, 20),
@@ -41,15 +42,11 @@ export default {
41
42
  },
42
43
  parameters: {
43
44
  docs: {
45
+ ...getDocsDescription(UDatePickerRangeName),
44
46
  story: {
45
47
  height: "620px",
46
48
  },
47
49
  },
48
- parameters: {
49
- docs: {
50
- ...getDocsDescription(UDatePickerRangeName),
51
- },
52
- },
53
50
  },
54
51
  } as Meta;
55
52
 
@@ -124,11 +124,6 @@ export interface UDatePickerRangeProps<TModelValue> {
124
124
  */
125
125
  dateFormat?: string;
126
126
 
127
- /**
128
- * Same as date format, but used when timepicker is enabled.
129
- */
130
- dateTimeFormat?: string;
131
-
132
127
  /**
133
128
  * User-friendly date format (it will be shown in UI).
134
129
  */
@@ -15,7 +15,9 @@ export function useLocale(props: UDatePickerRangeProps<unknown>) {
15
15
 
16
16
  const i18nGlobal = tm<Locale>(UDatePickerRange);
17
17
 
18
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config?.i18n));
18
+ const currentLocale = computed(() =>
19
+ merge({}, defaultConfig.i18n, i18nGlobal, props.config?.i18n),
20
+ );
19
21
 
20
22
  const locale = computed(() => {
21
23
  const { months, weekdays } = currentLocale.value;
@@ -50,7 +50,7 @@ const fileInputRef = ref<HTMLInputElement | null>(null);
50
50
  const elementId = props.id || useId();
51
51
 
52
52
  const i18nGlobal = tm(UInputFile);
53
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
53
+ const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
54
54
 
55
55
  const currentFiles = computed<File | File[] | null>({
56
56
  get: () => props.modelValue,
@@ -97,7 +97,7 @@ const innerWrapperRef = ref<HTMLDivElement | null>(null);
97
97
  const elementId = props.id || useId();
98
98
 
99
99
  const i18nGlobal = tm(USelect);
100
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
100
+ const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
101
101
 
102
102
  const isTop = computed(() => {
103
103
  if (props.openDirection === DIRECTION.top) return true;
@@ -33,7 +33,7 @@ const emit = defineEmits([
33
33
  const { tm } = useLocale();
34
34
 
35
35
  const i18nGlobal = tm(USwitch);
36
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config?.i18n));
36
+ const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config?.i18n));
37
37
 
38
38
  const checkedValue = computed({
39
39
  get: () => props.modelValue,
@@ -213,6 +213,6 @@ const { stripeAttrs } = useUI<Config>(defaultConfig);
213
213
 
214
214
  <template>
215
215
  <Transition :css="false" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter">
216
- <div v-if="show" v-bind="stripeAttrs" :style="barStyle" />
216
+ <div v-if="show" v-bind="stripeAttrs" :data-test="dataTest" :style="barStyle" />
217
217
  </Transition>
218
218
  </template>
@@ -49,4 +49,9 @@ export interface Props {
49
49
  * Component config object.
50
50
  */
51
51
  config?: ComponentConfig<Config>;
52
+
53
+ /**
54
+ * Data-test attribute for automated testing.
55
+ */
56
+ dataTest?: string;
52
57
  }
@@ -59,7 +59,6 @@ export default /*tw*/ {
59
59
  decimalSeparator: ",",
60
60
  thousandsSeparator: " ",
61
61
  planned: false,
62
- integer: false,
63
62
  symbolDivided: true,
64
63
  },
65
64
  };
@@ -27,7 +27,7 @@ const notifyPositionStyles = ref({});
27
27
  const notificationsWrapperRef = ref<NotificationsWrapperRef | null>(null);
28
28
 
29
29
  const i18nGlobal = tm(UNotify);
30
- const currentLocale = computed(() => merge(defaultConfig.i18n, i18nGlobal, props.config.i18n));
30
+ const currentLocale = computed(() => merge({}, defaultConfig.i18n, i18nGlobal, props.config.i18n));
31
31
 
32
32
  onMounted(() => {
33
33
  window.addEventListener("resize", setPosition, { passive: true });
@@ -311,5 +311,5 @@ async function getDefaults() {
311
311
  const defaultConfigPath = path.join(cwd, defaultIconsDir, COMPONENTS[U_ICON], "config.ts");
312
312
  const uIconDefaultConfig = await getComponentDefaultConfig(U_ICON, defaultConfigPath);
313
313
 
314
- return merge(uIconDefaultConfig?.defaults, vuelessConfig?.component?.[U_ICON]?.defaults);
314
+ return merge({}, uIconDefaultConfig?.defaults, vuelessConfig?.component?.[U_ICON]?.defaults);
315
315
  }
package/utils/ui.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { merge } from "lodash-es";
2
2
  import { defineConfig } from "cva";
3
3
  import { extendTailwindMerge } from "tailwind-merge";
4
- import { cloneDeep, isCSR, isSSR } from "./helper.ts";
4
+ import { isCSR, isSSR } from "./helper.ts";
5
5
  import { createGetMergedConfig } from "./node/mergeConfigs.js";
6
6
  import { UIcon } from "../ui.image-icon/constants.ts";
7
7
  import {
@@ -99,10 +99,10 @@ export const cva = ({ base = "", variants = {}, compoundVariants = [], defaultVa
99
99
  * Return default values for component props, icons, etc..
100
100
  */
101
101
  export function getDefaults<Props, Config>(defaultConfig: Config, name: ComponentNames) {
102
- const componentDefaults = cloneDeep((defaultConfig as UnknownObject).defaults) || {};
103
- const globalDefaults = cloneDeep(vuelessConfig.component?.[name]?.defaults) || {};
102
+ const componentDefaults = (defaultConfig as UnknownObject).defaults || {};
103
+ const globalDefaults = vuelessConfig.component?.[name]?.defaults || {};
104
104
 
105
- const defaults = merge(componentDefaults, globalDefaults) as Props & Defaults;
105
+ const defaults = merge({}, componentDefaults, globalDefaults) as Props & Defaults;
106
106
 
107
107
  if (defaults.color) {
108
108
  defaults.color = getColor(defaults.color as BrandColors);
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "framework": "vue",
3
3
  "name": "vueless",
4
- "version": "0.0.603",
4
+ "version": "0.0.605",
5
5
  "contributions": {
6
6
  "html": {
7
7
  "description-markup": "markdown",
@@ -3282,15 +3282,6 @@
3282
3282
  "type": "string"
3283
3283
  }
3284
3284
  },
3285
- {
3286
- "name": "dateTimeFormat",
3287
- "required": false,
3288
- "description": "Same as date format, but used when timepicker is enabled.",
3289
- "value": {
3290
- "kind": "expression",
3291
- "type": "string"
3292
- }
3293
- },
3294
3285
  {
3295
3286
  "name": "userDateFormat",
3296
3287
  "required": false,
@@ -7858,6 +7849,15 @@
7858
7849
  "kind": "expression",
7859
7850
  "type": "ComponentConfig"
7860
7851
  }
7852
+ },
7853
+ {
7854
+ "name": "dataTest",
7855
+ "required": false,
7856
+ "description": "Data-test attribute for automated testing.",
7857
+ "value": {
7858
+ "kind": "expression",
7859
+ "type": "string"
7860
+ }
7861
7861
  }
7862
7862
  ],
7863
7863
  "source": {