vueless 0.0.554 → 0.0.556

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 (105) hide show
  1. package/composables/useUI.ts +28 -64
  2. package/constants.js +21 -2
  3. package/index.d.ts +8 -1
  4. package/index.ts +1 -1
  5. package/package.json +1 -1
  6. package/types.ts +4 -10
  7. package/ui.button/UButton.vue +21 -7
  8. package/ui.button-link/ULink.vue +14 -2
  9. package/ui.button-link/config.ts +6 -1
  10. package/ui.button-link/useAttrs.ts +8 -39
  11. package/ui.button-toggle/useAttrs.ts +2 -8
  12. package/ui.button-toggle-item/config.ts +9 -11
  13. package/ui.button-toggle-item/useAttrs.ts +4 -18
  14. package/ui.container-accordion/config.ts +3 -1
  15. package/ui.container-accordion/useAttrs.ts +6 -17
  16. package/ui.container-card/UCard.vue +2 -1
  17. package/ui.container-card/useAttrs.ts +2 -8
  18. package/ui.container-col/useAttrs.ts +2 -8
  19. package/ui.container-divider/useAttrs.ts +2 -8
  20. package/ui.container-group/useAttrs.ts +2 -8
  21. package/ui.container-groups/useAttrs.ts +2 -8
  22. package/ui.container-modal/UModal.vue +1 -1
  23. package/ui.container-modal/useAttrs.ts +2 -12
  24. package/ui.container-modal-confirm/UModalConfirm.vue +3 -7
  25. package/ui.container-modal-confirm/useAttrs.ts +2 -8
  26. package/ui.container-page/UPage.vue +4 -5
  27. package/ui.container-page/useAttrs.ts +3 -32
  28. package/ui.container-row/useAttrs.ts +2 -8
  29. package/ui.data-list/UDataList.vue +3 -2
  30. package/ui.data-list/config.js +1 -1
  31. package/ui.data-list/useAttrs.js +2 -18
  32. package/ui.data-table/UTable.vue +6 -6
  33. package/ui.data-table/UTableRow.vue +1 -5
  34. package/ui.data-table/config.ts +28 -13
  35. package/ui.data-table/useAttrs.ts +10 -75
  36. package/ui.dropdown-badge/config.ts +10 -2
  37. package/ui.dropdown-badge/useAttrs.ts +8 -21
  38. package/ui.dropdown-button/config.ts +6 -6
  39. package/ui.dropdown-button/useAttrs.ts +6 -19
  40. package/ui.dropdown-link/config.ts +8 -2
  41. package/ui.dropdown-link/useAttrs.ts +10 -20
  42. package/ui.dropdown-list/config.ts +3 -2
  43. package/ui.dropdown-list/useAttrs.ts +2 -25
  44. package/ui.form-calendar/config.ts +36 -36
  45. package/ui.form-calendar/useAttrs.ts +2 -264
  46. package/ui.form-checkbox/useAttrs.ts +2 -8
  47. package/ui.form-checkbox-group/useAttrs.ts +2 -8
  48. package/ui.form-checkbox-multi-state/useAttrs.ts +2 -6
  49. package/ui.form-color-picker/useAttrs.js +2 -8
  50. package/ui.form-date-picker/useAttrs.ts +2 -6
  51. package/ui.form-date-picker-range/UDatePickerRange.vue +28 -28
  52. package/ui.form-date-picker-range/config.ts +30 -16
  53. package/ui.form-date-picker-range/useAttrs.ts +9 -70
  54. package/ui.form-input/UInput.vue +1 -1
  55. package/ui.form-input/useAttrs.js +2 -8
  56. package/ui.form-input-file/UInputFile.vue +3 -4
  57. package/ui.form-input-file/useAttrs.js +2 -8
  58. package/ui.form-input-money/useAttrs.js +2 -8
  59. package/ui.form-input-number/useAttrs.js +2 -8
  60. package/ui.form-input-rating/UInputRating.vue +5 -11
  61. package/ui.form-input-rating/useAttrs.js +2 -8
  62. package/ui.form-input-search/useAttrs.js +2 -8
  63. package/ui.form-label/useAttrs.js +2 -8
  64. package/ui.form-radio/useAttrs.ts +2 -8
  65. package/ui.form-radio-group/useAttrs.ts +2 -8
  66. package/ui.form-select/USelect.vue +37 -38
  67. package/ui.form-select/config.js +30 -11
  68. package/ui.form-select/useAttrs.js +6 -50
  69. package/ui.form-switch/useAttrs.js +2 -8
  70. package/ui.form-textarea/UTextarea.vue +5 -9
  71. package/ui.form-textarea/useAttrs.js +2 -8
  72. package/ui.image-avatar/useAttrs.ts +2 -8
  73. package/ui.image-icon/useAttrs.ts +2 -8
  74. package/ui.loader/config.ts +4 -1
  75. package/ui.loader/useAttrs.ts +2 -17
  76. package/ui.loader-overlay/useAttrs.ts +2 -12
  77. package/ui.loader-progress/ULoaderProgress.vue +2 -2
  78. package/ui.loader-progress/config.ts +8 -2
  79. package/ui.loader-progress/types.ts +5 -0
  80. package/ui.loader-progress/useAttrs.ts +3 -27
  81. package/ui.navigation-pagination/config.ts +6 -6
  82. package/ui.navigation-pagination/useAttrs.ts +2 -34
  83. package/ui.navigation-progress/config.ts +3 -1
  84. package/ui.navigation-progress/useAttrs.ts +5 -17
  85. package/ui.navigation-tab/config.ts +3 -1
  86. package/ui.navigation-tab/useAttrs.ts +4 -18
  87. package/ui.navigation-tabs/useAttrs.ts +2 -8
  88. package/ui.other-dot/useAttrs.ts +2 -8
  89. package/ui.text-alert/UAlert.vue +2 -1
  90. package/ui.text-alert/useAttrs.ts +2 -8
  91. package/ui.text-badge/useAttrs.ts +3 -8
  92. package/ui.text-block/UText.vue +2 -1
  93. package/ui.text-block/useAttrs.ts +2 -8
  94. package/ui.text-empty/useAttrs.ts +2 -8
  95. package/ui.text-file/useAttrs.ts +2 -8
  96. package/ui.text-files/useAttrs.ts +2 -8
  97. package/ui.text-header/useAttrs.ts +2 -8
  98. package/ui.text-money/UMoney.vue +1 -1
  99. package/ui.text-money/useAttrs.ts +2 -8
  100. package/ui.text-notify/useAttrs.ts +2 -8
  101. package/utils/helper.ts +29 -0
  102. package/utils/node/tailwindSafelist.js +2 -2
  103. package/utils/ui.ts +3 -4
  104. package/web-types.json +17 -1
  105. package/ui.button/useAttrs.ts +0 -26
@@ -1,15 +1,4 @@
1
- import {
2
- ref,
3
- watch,
4
- watchEffect,
5
- getCurrentInstance,
6
- toValue,
7
- useAttrs,
8
- Comment,
9
- Text,
10
- Fragment,
11
- computed,
12
- } from "vue";
1
+ import { ref, watch, watchEffect, getCurrentInstance, toValue, useAttrs, computed } from "vue";
13
2
 
14
3
  import { cx, cva, setColor, getColor, vuelessConfig, getMergedConfig } from "../utils/ui.ts";
15
4
  import { isCSR } from "../utils/helper.ts";
@@ -17,10 +6,11 @@ import {
17
6
  STRATEGY_TYPE,
18
7
  CVA_CONFIG_KEY,
19
8
  SYSTEM_CONFIG_KEY,
20
- NESTED_COMPONENT_REG_EXP,
9
+ NESTED_COMPONENT_PATTERN_REG_EXP,
10
+ EXTENDS_PATTERN_REG_EXP,
21
11
  } from "../constants.js";
22
12
 
23
- import type { ComponentInternalInstance, Slot, VNode, ComputedRef } from "vue";
13
+ import type { ComponentInternalInstance, ComputedRef } from "vue";
24
14
  import type {
25
15
  BrandColors,
26
16
  Strategies,
@@ -30,8 +20,8 @@ import type {
30
20
  ComponentNames,
31
21
  CVA,
32
22
  KeyAttrs,
33
- KeysToExtend,
34
23
  ExtendedKeyClasses,
24
+ KeysAttrs,
35
25
  } from "../types.ts";
36
26
 
37
27
  /**
@@ -77,6 +67,7 @@ export default function useUI<T>(
77
67
  */
78
68
  function getClasses(key: string, mutatedProps: UnknownObject): ComputedRef<string> {
79
69
  return computed(() => {
70
+ const mutatedPropsValue = toValue(mutatedProps);
80
71
  const color = (toValue(mutatedProps)?.color as BrandColors) || props?.color;
81
72
  const value = config.value[key] as (CVA & NestedComponent) | string;
82
73
 
@@ -85,7 +76,7 @@ export default function useUI<T>(
85
76
  if (typeof value === "object" && isCVA(value)) {
86
77
  classes = cva(value)({
87
78
  ...props,
88
- ...toValue(mutatedProps),
79
+ ...mutatedPropsValue,
89
80
  ...(color ? { color: getColor(color) } : {}),
90
81
  });
91
82
  }
@@ -118,33 +109,35 @@ export default function useUI<T>(
118
109
  }
119
110
 
120
111
  /**
121
- * Get an object where:
112
+ * Returns an object where:
122
113
  * – key: elementKey
123
114
  * – value: reactive object of string element attributes (with classes).
124
115
  */
125
- function getKeysAttrs(
126
- mutatedProps = {},
127
- extendingKeys: string[] = [],
128
- keysToExtendConfig: Record<string, KeysToExtend> = {},
129
- ) {
130
- const keysToExtend = Object.keys(keysToExtendConfig);
131
- const keysAttrs: UnknownObject = {};
116
+ function getKeysAttrs(mutatedProps = {}): KeysAttrs {
117
+ const keysAttrs: KeysAttrs = {};
132
118
 
133
- for (const key in defaultConfig) {
134
- if (isSystemKey(key) || extendingKeys.includes(key)) continue;
119
+ for (const key in config.value) {
120
+ if (isSystemKey(key)) continue;
135
121
 
136
122
  keysAttrs[`${key}Attrs`] = getAttrs(key, getClasses(key, mutatedProps));
137
123
 
138
- if (keysToExtend.includes(key)) {
139
- const { base, extend } = keysToExtendConfig[key];
124
+ const baseClasses = getBaseClasses(config.value[key]);
125
+ const extendsMatches = baseClasses.match(EXTENDS_PATTERN_REG_EXP);
126
+
127
+ if (extendsMatches) {
128
+ // retrieves extends keys from patterns:
129
+ // Example: `{>someKey} {>someOtherKey}` >>> `["someKey", "someOtherKey"]`.
130
+ const extendsKeys = extendsMatches.map((pattern) => pattern.slice(2, -1));
131
+ const classes = getExtendingKeysClasses(extendsKeys, mutatedProps);
132
+ const extendsClasses = Object.values(classes).map((item) => toValue(item));
133
+
140
134
  const keyAttrs = keysAttrs[`${key}Attrs`] as ComputedRef<KeyAttrs>;
141
135
 
142
136
  keysAttrs[`${key}Attrs`] = computed(() => ({
143
137
  ...keyAttrs.value,
144
138
  class: cx([
145
- ...(Array.isArray(base) ? toValue(base) : [toValue(base)]),
146
- keyAttrs.value.class,
147
- ...(Array.isArray(extend) ? toValue(extend) : [toValue(extend)]),
139
+ ...extendsClasses,
140
+ keyAttrs.value.class?.replaceAll(EXTENDS_PATTERN_REG_EXP, ""),
148
141
  ]),
149
142
  }));
150
143
  }
@@ -157,7 +150,7 @@ export default function useUI<T>(
157
150
  * Get an element attributes for a given key.
158
151
  */
159
152
  function getAttrs(configKey: string, classes: ComputedRef) {
160
- const nestedComponent = getNestedComponent(defaultConfig[configKey] || "");
153
+ const nestedComponent = getNestedComponent(config.value[configKey] || "");
161
154
 
162
155
  const attrs = useAttrs();
163
156
  const isDev = isCSR && import.meta.env?.DEV;
@@ -198,12 +191,7 @@ export default function useUI<T>(
198
191
  return vuelessAttrs;
199
192
  }
200
193
 
201
- return {
202
- config,
203
- getKeysAttrs,
204
- getExtendingKeysClasses,
205
- hasSlotContent,
206
- };
194
+ return { config, getKeysAttrs };
207
195
  }
208
196
 
209
197
  /**
@@ -221,7 +209,8 @@ function getNestedComponent(value: string | NestedComponent | CVA) {
221
209
  const component = (value as NestedComponent)?.component as ComponentNames;
222
210
 
223
211
  const match =
224
- classes.match(NESTED_COMPONENT_REG_EXP) || component?.match(NESTED_COMPONENT_REG_EXP);
212
+ classes.match(NESTED_COMPONENT_PATTERN_REG_EXP) ||
213
+ component?.match(NESTED_COMPONENT_PATTERN_REG_EXP);
225
214
 
226
215
  return match ? match[1] : "";
227
216
  }
@@ -243,28 +232,3 @@ function isCVA(config: UnknownObject): boolean {
243
232
  Object.keys(config).some((key) => key === value),
244
233
  );
245
234
  }
246
-
247
- /**
248
- * Check if slot defined, and have a content.
249
- */
250
- export function hasSlotContent(slot: Slot | undefined | null, props = {}): boolean {
251
- type Args = VNode | VNode[] | undefined | null;
252
-
253
- const asArray = (arg: Args) => {
254
- return Array.isArray(arg) ? arg : arg != null ? [arg] : [];
255
- };
256
-
257
- const isVNodeEmpty = (vnode: Args) => {
258
- return (
259
- !vnode ||
260
- asArray(vnode).every(
261
- (vnode) =>
262
- vnode.type === Comment ||
263
- (vnode.type === Text && !vnode.children?.length) ||
264
- (vnode.type === Fragment && !vnode.children?.length),
265
- )
266
- );
267
- };
268
-
269
- return !isVNodeEmpty(slot?.(props));
270
- }
package/constants.js CHANGED
@@ -154,7 +154,11 @@ export const COMPONENTS = {
154
154
  UDot: "ui.other-dot",
155
155
  };
156
156
 
157
- /* Extending Tailwind Merge by vueless custom tailwind classes. */
157
+ /**
158
+ * Extending Tailwind Merge by vueless custom tailwind classes.
159
+ * All lists of rules available here:
160
+ * https://github.com/dcastil/tailwind-merge/blob/v2.3.0/src/lib/default-config.ts
161
+ */
158
162
  export const TAILWIND_MERGE_EXTENSION = {
159
163
  extend: {
160
164
  theme: {
@@ -166,6 +170,20 @@ export const TAILWIND_MERGE_EXTENSION = {
166
170
  "ring-offset-color": [{ "ring-offset": ["color-dynamic"] }],
167
171
  "font-size": [{ text: ["2xs"] }],
168
172
  rounded: [{ rounded: ["dynamic"] }],
173
+ "rounded-s": [{ "rounded-s": ["dynamic"] }],
174
+ "rounded-e": [{ "rounded-e": ["dynamic"] }],
175
+ "rounded-t": [{ "rounded-t": ["dynamic"] }],
176
+ "rounded-r": [{ "rounded-r": ["dynamic"] }],
177
+ "rounded-b": [{ "rounded-b": ["dynamic"] }],
178
+ "rounded-l": [{ "rounded-l": ["dynamic"] }],
179
+ "rounded-ss": [{ "rounded-ss": ["dynamic"] }],
180
+ "rounded-se": [{ "rounded-se": ["dynamic"] }],
181
+ "rounded-ee": [{ "rounded-ee": ["dynamic"] }],
182
+ "rounded-es": [{ "rounded-es": ["dynamic"] }],
183
+ "rounded-tl": [{ "rounded-tl": ["dynamic"] }],
184
+ "rounded-tr": [{ "rounded-tr": ["dynamic"] }],
185
+ "rounded-br": [{ "rounded-br": ["dynamic"] }],
186
+ "rounded-bl": [{ "rounded-bl": ["dynamic"] }],
169
187
  },
170
188
  },
171
189
  };
@@ -200,7 +218,8 @@ export const VUELESS_ICONS_CACHED_DIR = `${VUELESS_CACHE_DIR}/${ICONS_DIR}`;
200
218
 
201
219
  /* Other */
202
220
  export const PX_IN_REM = 16;
203
- export const NESTED_COMPONENT_REG_EXP = /\{U[^}]*}/g;
221
+ export const NESTED_COMPONENT_PATTERN_REG_EXP = /\{U[^}]*}/g;
222
+ export const EXTENDS_PATTERN_REG_EXP = /\{>[^}]*}/g;
204
223
  export const DYNAMIC_COLOR_PATTERN = "{color}";
205
224
  export const TAILWIND_COLOR_OPACITY_DELIMITER = "/";
206
225
  export const TAILWIND_VARIANT_DELIMITER = ":";
package/index.d.ts CHANGED
@@ -2,7 +2,14 @@ import type { App } from "vue";
2
2
  import type { CreateVuelessOptions } from "./types.ts";
3
3
  export { setTheme } from "./utils/theme.ts";
4
4
  export { cx, cva, compose } from "./utils/ui.ts";
5
- export { isSSR, isCSR, getRandomId, setTitle, createDebounce } from "./utils/helper.ts";
5
+ export {
6
+ isSSR,
7
+ isCSR,
8
+ getRandomId,
9
+ setTitle,
10
+ createDebounce,
11
+ hasSlotContent,
12
+ } from "./utils/helper.ts";
6
13
  export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform.ts";
7
14
  export { default as createVueI18nAdapter } from "./adatper.locale/vue-i18n.js";
8
15
  export { default as defaultEnLocale } from "./adatper.locale/locales/en.js";
package/index.ts CHANGED
@@ -9,7 +9,7 @@ import type { CreateVuelessOptions } from './types.ts'
9
9
 
10
10
  export { setTheme } from "./utils/theme.ts";
11
11
  export { cx, cva, compose } from "./utils/ui.ts";
12
- export { isSSR, isCSR, getRandomId, setTitle, createDebounce } from "./utils/helper.ts";
12
+ export { isSSR, isCSR, getRandomId, setTitle, createDebounce, hasSlotContent } from "./utils/helper.ts";
13
13
  export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform.ts";
14
14
  export { default as createVueI18nAdapter } from "./adatper.locale/vue-i18n.js";
15
15
  export { default as defaultEnLocale } from "./adatper.locale/locales/en.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vueless",
3
- "version": "0.0.554",
3
+ "version": "0.0.556",
4
4
  "license": "MIT",
5
5
  "description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
6
6
  "keywords": [
package/types.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { hasSlotContent } from "./composables/useUI.ts";
2
-
3
1
  import UTextDefaultConfig from "./ui.text-block/config.ts";
4
2
  import UAlertDefaultConfig from "./ui.text-alert/config.ts";
5
3
  import UEmptyDefaultConfig from "./ui.text-empty/config.ts";
@@ -46,7 +44,7 @@ import UCheckboxMultiStateConfig from "./ui.form-checkbox-multi-state/config.ts"
46
44
  import URadioConfig from "./ui.form-radio/config.ts";
47
45
  import URadioGroupConfig from "./ui.form-radio-group/config.ts";
48
46
 
49
- import type { ComputedRef, MaybeRef, Ref } from "vue";
47
+ import type { MaybeRef, Ref } from "vue";
50
48
  import type { Props } from "tippy.js";
51
49
  import type { LocaleOptions } from "./adatper.locale/vueless.ts";
52
50
 
@@ -256,10 +254,11 @@ export interface VueAttrs {
256
254
  value?: string;
257
255
  }
258
256
 
257
+ export type KeysAttrs = Record<string, Ref<UnknownObject | undefined>>;
258
+
259
259
  export interface UseAttrs<TConfig> {
260
- hasSlotContent: typeof hasSlotContent;
261
260
  config: Ref<TConfig | undefined>;
262
- [key: string]: Ref<TConfig | undefined> | typeof hasSlotContent;
261
+ [key: string]: Ref<TConfig | undefined>;
263
262
  }
264
263
 
265
264
  export interface KeyAttrs extends VueAttrs {
@@ -271,11 +270,6 @@ export interface KeyAttrs extends VueAttrs {
271
270
  [key: string]: string | UnknownObject | undefined | null;
272
271
  }
273
272
 
274
- export interface KeysToExtend {
275
- base?: ComputedRef;
276
- extend?: ComputedRef;
277
- }
278
-
279
273
  export interface CreateVuelessOptions {
280
274
  i18n?: LocaleOptions;
281
275
  }
@@ -1,16 +1,18 @@
1
1
  <script setup lang="ts">
2
- import { computed, ref, watchEffect, useId, watch } from "vue";
2
+ import { computed, ref, watchEffect, useId, watch, useSlots } from "vue";
3
3
 
4
+ import useUI from "../composables/useUI.ts";
4
5
  import { useDarkMode } from "../composables/useDarkMode.ts";
6
+ import { hasSlotContent } from "../utils/helper.ts";
5
7
  import { getDefault } from "../utils/ui.ts";
8
+
6
9
  import ULoader from "../ui.loader/ULoader.vue";
7
10
  import UIcon from "../ui.image-icon/UIcon.vue";
8
11
 
9
12
  import defaultConfig from "./config.ts";
10
- import useAttrs from "./useAttrs.ts";
11
13
  import { UButton } from "./constants.ts";
12
14
 
13
- import type { UButtonProps, LoaderSize, IconSize } from "./types.ts";
15
+ import type { UButtonProps, LoaderSize, IconSize, Config } from "./types.ts";
14
16
 
15
17
  defineOptions({ inheritAttrs: false });
16
18
 
@@ -30,13 +32,10 @@ const props = withDefaults(defineProps<UButtonProps>(), {
30
32
  dataTest: "",
31
33
  });
32
34
 
35
+ const slots = useSlots();
33
36
  const elementId = props.id || useId();
34
-
35
37
  const { isDarkMode } = useDarkMode();
36
38
 
37
- const { buttonAttrs, loaderAttrs, leftIconAttrs, rightIconAttrs, centerIconAttrs } =
38
- useAttrs(props);
39
-
40
39
  const buttonRef = ref<HTMLElement | null>(null);
41
40
  const buttonStyle = ref({});
42
41
  const buttonWidth = ref(0);
@@ -102,6 +101,21 @@ defineExpose({
102
101
  */
103
102
  buttonRef,
104
103
  });
104
+
105
+ /**
106
+ * Get element / nested component attributes for each config token ✨
107
+ * Applies: `class`, `config`, redefined default `props` and dev `vl-...` attributes.
108
+ */
109
+ const { getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
110
+
111
+ const mutatedProps = computed(() => ({
112
+ leftIcon: Boolean(props.leftIcon) || hasSlotContent(slots["left"]),
113
+ rightIcon: Boolean(props.rightIcon) || hasSlotContent(slots["right"]),
114
+ label: Boolean(props.label),
115
+ }));
116
+
117
+ const { buttonAttrs, loaderAttrs, leftIconAttrs, rightIconAttrs, centerIconAttrs } =
118
+ getKeysAttrs(mutatedProps);
105
119
  </script>
106
120
 
107
121
  <template>
@@ -83,7 +83,17 @@ const { route, isActive, isExactActive } = useLink(useLinkOptions);
83
83
 
84
84
  const wrapperRef = ref(null);
85
85
 
86
- const { wrapperAttrs, linkAttrs } = useAttrs(props, { isActive, isExactActive });
86
+ const { wrapperAttrs, linkAttrs } = useAttrs(props);
87
+
88
+ const wrapperActiveClasses = computed(() => [
89
+ isActive.value && props.wrapperActiveClass,
90
+ isExactActive.value && props.wrapperExactActiveClass,
91
+ ]);
92
+
93
+ const linkActiveClasses = computed(() => [
94
+ isActive.value && props.activeClass,
95
+ isExactActive.value && props.exactActiveClass,
96
+ ]);
87
97
 
88
98
  const targetValue = computed(() => {
89
99
  return props.targetBlank ? "_blank" : "_self";
@@ -129,7 +139,7 @@ defineExpose({
129
139
  </script>
130
140
 
131
141
  <template>
132
- <div v-bind="wrapperAttrs" ref="wrapperRef" tabindex="-1">
142
+ <div v-bind="wrapperAttrs" ref="wrapperRef" :class="wrapperActiveClasses" tabindex="-1">
133
143
  <!-- @slot Use it to add something before the label. -->
134
144
  <slot name="left" />
135
145
 
@@ -138,6 +148,7 @@ defineExpose({
138
148
  :to="route"
139
149
  :target="targetValue"
140
150
  v-bind="linkAttrs"
151
+ :class="linkActiveClasses"
141
152
  :data-test="dataTest"
142
153
  tabindex="0"
143
154
  @blur="onBlur"
@@ -157,6 +168,7 @@ defineExpose({
157
168
  :href="prefixedHref"
158
169
  :target="targetValue"
159
170
  v-bind="linkAttrs"
171
+ :class="linkActiveClasses"
160
172
  :data-test="dataTest"
161
173
  tabindex="0"
162
174
  @blur="onBlur"
@@ -17,6 +17,9 @@ export default /*tw*/ {
17
17
  disabled: {
18
18
  true: "!ring-0 !ring-offset-0 cursor-not-allowed",
19
19
  },
20
+ defaultSlot: {
21
+ true: "flex items-center focus-within:ring-0 focus-within:ring-offset-0",
22
+ },
20
23
  noRing: {
21
24
  true: "!ring-0 !ring-offset-0",
22
25
  },
@@ -59,9 +62,11 @@ export default /*tw*/ {
59
62
  disabled: {
60
63
  true: "text-gray-400 pointer-events-none",
61
64
  },
65
+ defaultSlot: {
66
+ true: "flex items-center no-underline hover:no-underline",
67
+ },
62
68
  },
63
69
  },
64
- linkWithChild: "flex items-center no-underline hover:no-underline focus-within:ring-0 focus-within:ring-offset-0",
65
70
  defaults: {
66
71
  color: "brand",
67
72
  type: "link",
@@ -1,51 +1,20 @@
1
1
  import { computed, useSlots } from "vue";
2
2
  import useUI from "../composables/useUI.ts";
3
+ import { hasSlotContent } from "../utils/helper.ts";
3
4
 
4
5
  import defaultConfig from "./config.ts";
5
6
 
6
- import type { Ref } from "vue";
7
7
  import type { UseAttrs } from "../types.ts";
8
8
  import type { ULinkProps, Config } from "./types.ts";
9
9
 
10
- type ComponentState = {
11
- isActive: Ref<boolean>;
12
- isExactActive: Ref<boolean>;
13
- };
14
-
15
- export default function useAttrs(
16
- props: ULinkProps,
17
- { isActive, isExactActive }: ComponentState,
18
- ): UseAttrs<Config> {
19
- const { config, getKeysAttrs, hasSlotContent, getExtendingKeysClasses } = useUI<Config>(
20
- defaultConfig,
21
- () => props.config,
22
- "link",
23
- );
10
+ export default function useAttrs(props: ULinkProps): UseAttrs<Config> {
11
+ const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config, "link");
24
12
  const slots = useSlots();
25
13
 
26
- const extendingKeys = ["linkWithChild"];
27
- const extendingKeysClasses = getExtendingKeysClasses(extendingKeys);
28
-
29
- const keysAttrs = getKeysAttrs({}, extendingKeys, {
30
- wrapper: {
31
- extend: computed(() => [
32
- hasSlotContent(slots["default"]) && extendingKeysClasses.linkWithChild.value,
33
- isActive.value && props.wrapperActiveClass,
34
- isExactActive.value && props.wrapperExactActiveClass,
35
- ]),
36
- },
37
- link: {
38
- extend: computed(() => [
39
- hasSlotContent(slots["default"]) && extendingKeysClasses.linkWithChild.value,
40
- isActive.value && props.activeClass,
41
- isExactActive.value && props.exactActiveClass,
42
- ]),
43
- },
44
- });
14
+ const mutatedProps = computed(() => ({
15
+ /* component state, not a props */
16
+ defaultSlot: hasSlotContent(slots["default"]),
17
+ }));
45
18
 
46
- return {
47
- config,
48
- ...keysAttrs,
49
- hasSlotContent,
50
- };
19
+ return { config, ...getKeysAttrs(mutatedProps) };
51
20
  }
@@ -6,13 +6,7 @@ import type { UseAttrs } from "../types.ts";
6
6
  import type { UToggleProps, Config } from "./types.ts";
7
7
 
8
8
  export default function useAttrs(props: UToggleProps): UseAttrs<Config> {
9
- const { config, getKeysAttrs, hasSlotContent } = useUI<Config>(defaultConfig, () => props.config);
9
+ const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
10
10
 
11
- const keysAttrs = getKeysAttrs();
12
-
13
- return {
14
- config,
15
- ...keysAttrs,
16
- hasSlotContent,
17
- };
11
+ return { config, ...getKeysAttrs() };
18
12
  }
@@ -10,7 +10,10 @@ export default /*tw*/ {
10
10
  `,
11
11
  variants: {
12
12
  separated: {
13
- false: "rounded-none",
13
+ false: "rounded-none focus:ring-0",
14
+ },
15
+ selected: {
16
+ false: "relative disabled:z-10",
14
17
  },
15
18
  variant: {
16
19
  thirdary: `
@@ -19,16 +22,11 @@ export default /*tw*/ {
19
22
  `,
20
23
  },
21
24
  },
22
- },
23
- toggleButtonActive: {
24
- base: "relative disabled:z-10",
25
- variants: {
26
- variant: {
27
- primary: "!text-white bg-brand-600 border-brand-600",
28
- secondary: "text-brand-600 border-brand-600 bg-brand-600/10",
29
- thirdary: "!bg-brand-600/20",
30
- },
31
- },
25
+ compoundVariants: [
26
+ { selected: true, variant: "primary", class: "!text-white bg-brand-600 !border-brand-600" },
27
+ { selected: true, variant: "secondary", class: "text-brand-600 border-brand-600 bg-brand-600/10" },
28
+ { selected: true, variant: "thirdary", class: "!bg-brand-600/20" },
29
+ ],
32
30
  },
33
31
  toggleInput: "p-0 m-0 size-0 invisible absolute",
34
32
  defaults: {
@@ -16,28 +16,14 @@ export default function useAttrs(
16
16
  props: UToggleItemProps,
17
17
  { isSelected, separated, variant }: itemState,
18
18
  ): UseAttrs<Config> {
19
- const { config, getKeysAttrs, hasSlotContent, getExtendingKeysClasses } = useUI<Config>(
20
- defaultConfig,
21
- () => props.config,
22
- );
19
+ const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
23
20
 
24
21
  const mutatedProps = computed(() => ({
25
22
  variant: toValue(variant),
26
23
  separated: toValue(separated),
24
+ /* component state, not a props */
25
+ selected: isSelected.value,
27
26
  }));
28
27
 
29
- const extendingKeys = ["toggleButtonActive"];
30
- const extendingKeysClasses = getExtendingKeysClasses(extendingKeys, mutatedProps);
31
-
32
- const keysAttrs = getKeysAttrs(mutatedProps, extendingKeys, {
33
- toggleButton: {
34
- extend: computed(() => [isSelected.value && extendingKeysClasses.toggleButtonActive.value]),
35
- },
36
- });
37
-
38
- return {
39
- config,
40
- ...keysAttrs,
41
- hasSlotContent,
42
- };
28
+ return { config, ...getKeysAttrs(mutatedProps) };
43
29
  }
@@ -19,9 +19,11 @@ export default /*tw*/ {
19
19
  md: "text-sm",
20
20
  lg: "text-base",
21
21
  },
22
+ opened: {
23
+ true: "pt-2 h-fit opacity-100",
24
+ },
22
25
  },
23
26
  },
24
- descriptionShown: "pt-2 h-fit opacity-100",
25
27
  toggleIcon: "{UIcon}",
26
28
  divider: "{UDivider} group-last:hidden",
27
29
  defaults: {
@@ -15,23 +15,12 @@ export default function useAttrs(
15
15
  props: UAccordionProps,
16
16
  { isOpened }: ComponentState,
17
17
  ): UseAttrs<Config> {
18
- const { config, getKeysAttrs, hasSlotContent, getExtendingKeysClasses } = useUI<Config>(
19
- defaultConfig,
20
- () => props.config,
21
- );
18
+ const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
22
19
 
23
- const extendingKeys = ["descriptionShown"];
24
- const extendingKeysClasses = getExtendingKeysClasses(extendingKeys);
20
+ const mutatedProps = computed(() => ({
21
+ /* component state, not a props */
22
+ opened: isOpened.value,
23
+ }));
25
24
 
26
- const keysAttrs = getKeysAttrs({}, extendingKeys, {
27
- description: {
28
- extend: computed(() => [isOpened.value && extendingKeysClasses.descriptionShown.value]),
29
- },
30
- });
31
-
32
- return {
33
- config,
34
- ...keysAttrs,
35
- hasSlotContent,
36
- };
25
+ return { config, ...getKeysAttrs(mutatedProps) };
37
26
  }
@@ -1,6 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, useSlots } from "vue";
3
3
 
4
+ import { hasSlotContent } from "../utils/helper.ts";
5
+
4
6
  import UHeader from "../ui.text-header/UHeader.vue";
5
7
  import UDivider from "../ui.container-divider/UDivider.vue";
6
8
 
@@ -28,7 +30,6 @@ const isShownFooter = computed(() => {
28
30
  });
29
31
 
30
32
  const {
31
- hasSlotContent,
32
33
  wrapperAttrs,
33
34
  titleAttrs,
34
35
  dividerAttrs,
@@ -6,13 +6,7 @@ import type { UseAttrs } from "../types.ts";
6
6
  import type { UCardProps, Config } from "./types.ts";
7
7
 
8
8
  export default function useAttrs(props: UCardProps): UseAttrs<Config> {
9
- const { config, getKeysAttrs, hasSlotContent } = useUI<Config>(defaultConfig, () => props.config);
9
+ const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
10
10
 
11
- const keysAttrs = getKeysAttrs();
12
-
13
- return {
14
- config,
15
- ...keysAttrs,
16
- hasSlotContent,
17
- };
11
+ return { config, ...getKeysAttrs() };
18
12
  }
@@ -6,13 +6,7 @@ import type { UseAttrs } from "../types.ts";
6
6
  import type { UColProps, Config } from "./types.ts";
7
7
 
8
8
  export default function useAttrs(props: UColProps): UseAttrs<Config> {
9
- const { config, getKeysAttrs, hasSlotContent } = useUI<Config>(defaultConfig, () => props.config);
9
+ const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
10
10
 
11
- const keysAttrs = getKeysAttrs();
12
-
13
- return {
14
- config,
15
- ...keysAttrs,
16
- hasSlotContent,
17
- };
11
+ return { config, ...getKeysAttrs() };
18
12
  }