vueless 0.0.555 → 0.0.557

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 (103) hide show
  1. package/composables/useUI.ts +15 -80
  2. package/constants.js +19 -1
  3. package/index.d.ts +8 -1
  4. package/index.ts +1 -1
  5. package/package.json +1 -1
  6. package/types.ts +17 -10
  7. package/ui.button/UButton.vue +23 -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/useAttrs.ts +2 -8
  45. package/ui.form-checkbox/useAttrs.ts +2 -8
  46. package/ui.form-checkbox-group/useAttrs.ts +2 -8
  47. package/ui.form-checkbox-multi-state/useAttrs.ts +2 -6
  48. package/ui.form-color-picker/useAttrs.js +2 -8
  49. package/ui.form-date-picker/useAttrs.ts +2 -6
  50. package/ui.form-date-picker-range/UDatePickerRange.vue +28 -28
  51. package/ui.form-date-picker-range/config.ts +30 -16
  52. package/ui.form-date-picker-range/useAttrs.ts +9 -70
  53. package/ui.form-input/UInput.vue +1 -1
  54. package/ui.form-input/useAttrs.js +2 -8
  55. package/ui.form-input-file/UInputFile.vue +3 -4
  56. package/ui.form-input-file/useAttrs.js +2 -8
  57. package/ui.form-input-money/useAttrs.js +2 -8
  58. package/ui.form-input-number/useAttrs.js +2 -8
  59. package/ui.form-input-rating/UInputRating.vue +5 -11
  60. package/ui.form-input-rating/useAttrs.js +2 -8
  61. package/ui.form-input-search/useAttrs.js +2 -8
  62. package/ui.form-label/useAttrs.js +2 -8
  63. package/ui.form-radio/useAttrs.ts +2 -8
  64. package/ui.form-radio-group/useAttrs.ts +2 -8
  65. package/ui.form-select/USelect.vue +37 -38
  66. package/ui.form-select/config.js +30 -11
  67. package/ui.form-select/useAttrs.js +6 -50
  68. package/ui.form-switch/useAttrs.js +2 -8
  69. package/ui.form-textarea/UTextarea.vue +5 -9
  70. package/ui.form-textarea/useAttrs.js +2 -8
  71. package/ui.image-avatar/useAttrs.ts +2 -8
  72. package/ui.image-icon/useAttrs.ts +2 -8
  73. package/ui.loader/config.ts +4 -1
  74. package/ui.loader/useAttrs.ts +2 -17
  75. package/ui.loader-overlay/useAttrs.ts +2 -12
  76. package/ui.loader-progress/ULoaderProgress.vue +2 -2
  77. package/ui.loader-progress/config.ts +8 -2
  78. package/ui.loader-progress/types.ts +5 -0
  79. package/ui.loader-progress/useAttrs.ts +3 -27
  80. package/ui.navigation-pagination/config.ts +6 -6
  81. package/ui.navigation-pagination/useAttrs.ts +2 -34
  82. package/ui.navigation-progress/config.ts +3 -1
  83. package/ui.navigation-progress/useAttrs.ts +5 -17
  84. package/ui.navigation-tab/config.ts +3 -1
  85. package/ui.navigation-tab/useAttrs.ts +4 -18
  86. package/ui.navigation-tabs/useAttrs.ts +2 -8
  87. package/ui.other-dot/useAttrs.ts +2 -8
  88. package/ui.text-alert/UAlert.vue +2 -1
  89. package/ui.text-alert/useAttrs.ts +2 -8
  90. package/ui.text-badge/useAttrs.ts +3 -8
  91. package/ui.text-block/UText.vue +2 -1
  92. package/ui.text-block/useAttrs.ts +2 -8
  93. package/ui.text-empty/useAttrs.ts +2 -8
  94. package/ui.text-file/useAttrs.ts +2 -8
  95. package/ui.text-files/useAttrs.ts +2 -8
  96. package/ui.text-header/useAttrs.ts +2 -8
  97. package/ui.text-money/UMoney.vue +1 -1
  98. package/ui.text-money/useAttrs.ts +2 -8
  99. package/ui.text-notify/useAttrs.ts +2 -8
  100. package/utils/helper.ts +29 -0
  101. package/utils/ui.ts +0 -2
  102. package/web-types.json +17 -1
  103. 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";
@@ -21,7 +10,7 @@ import {
21
10
  EXTENDS_PATTERN_REG_EXP,
22
11
  } from "../constants.js";
23
12
 
24
- import type { ComponentInternalInstance, Slot, VNode, ComputedRef } from "vue";
13
+ import type { ComponentInternalInstance, ComputedRef } from "vue";
25
14
  import type {
26
15
  BrandColors,
27
16
  Strategies,
@@ -30,8 +19,9 @@ import type {
30
19
  NestedComponent,
31
20
  ComponentNames,
32
21
  CVA,
22
+ UseUI,
33
23
  KeyAttrs,
34
- KeysToExtend,
24
+ KeysAttrs,
35
25
  ExtendedKeyClasses,
36
26
  } from "../types.ts";
37
27
 
@@ -46,7 +36,8 @@ export default function useUI<T>(
46
36
  defaultConfig: T & Component,
47
37
  propsConfigGetter?: () => (T & Component) | undefined,
48
38
  topLevelClassKey?: string,
49
- ) {
39
+ mutatedProps?: ComputedRef,
40
+ ): UseUI<T> {
50
41
  const { type, props } = getCurrentInstance() as ComponentInternalInstance;
51
42
  const componentName = type.__name as ComponentNames;
52
43
  const globalConfig = vuelessConfig?.component?.[componentName] || {};
@@ -59,7 +50,7 @@ export default function useUI<T>(
59
50
  : (STRATEGY_TYPE.merge as Strategies);
60
51
 
61
52
  const firstClassKey = defaultConfig ? Object.keys(defaultConfig)[0] : "";
62
- const config = ref({} as T);
53
+ const config = ref({} as T & Component);
63
54
  const attrs = useAttrs();
64
55
 
65
56
  watchEffect(() => {
@@ -78,6 +69,7 @@ export default function useUI<T>(
78
69
  */
79
70
  function getClasses(key: string, mutatedProps: UnknownObject): ComputedRef<string> {
80
71
  return computed(() => {
72
+ const mutatedPropsValue = toValue(mutatedProps);
81
73
  const color = (toValue(mutatedProps)?.color as BrandColors) || props?.color;
82
74
  const value = config.value[key] as (CVA & NestedComponent) | string;
83
75
 
@@ -86,7 +78,7 @@ export default function useUI<T>(
86
78
  if (typeof value === "object" && isCVA(value)) {
87
79
  classes = cva(value)({
88
80
  ...props,
89
- ...toValue(mutatedProps),
81
+ ...mutatedPropsValue,
90
82
  ...(color ? { color: getColor(color) } : {}),
91
83
  });
92
84
  }
@@ -119,49 +111,22 @@ export default function useUI<T>(
119
111
  }
120
112
 
121
113
  /**
122
- * Get an object where:
114
+ * Returns an object where:
123
115
  * – key: elementKey
124
116
  * – value: reactive object of string element attributes (with classes).
125
117
  */
126
- function getKeysAttrs(
127
- mutatedProps = {},
128
- extendingKeys: string[] = [],
129
- keysToExtendConfig: Record<string, KeysToExtend> = {},
130
- ) {
131
- const keysAttrs: UnknownObject = {};
132
-
133
- // TODO: should be removed after migration of all components to the new api.
134
- for (const key in config.value) {
135
- if (isSystemKey(key) || extendingKeys.includes(key)) continue;
136
-
137
- keysAttrs[`${key}Attrs`] = getAttrs(key, getClasses(key, mutatedProps));
138
-
139
- const keysToExtend = Object.keys(keysToExtendConfig);
140
-
141
- if (keysToExtend.includes(key)) {
142
- const { base, extend } = keysToExtendConfig[key];
143
- const keyAttrs = keysAttrs[`${key}Attrs`] as ComputedRef<KeyAttrs>;
144
-
145
- keysAttrs[`${key}Attrs`] = computed(() => ({
146
- ...keyAttrs.value,
147
- class: cx([
148
- ...(Array.isArray(base) ? toValue(base) : [toValue(base)]),
149
- keyAttrs.value.class,
150
- ...(Array.isArray(extend) ? toValue(extend) : [toValue(extend)]),
151
- ]),
152
- }));
153
- }
154
- }
118
+ function getKeysAttrs(mutatedProps = {}): KeysAttrs {
119
+ const keysAttrs: KeysAttrs = {};
155
120
 
156
121
  for (const key in config.value) {
157
122
  if (isSystemKey(key)) continue;
158
123
 
124
+ keysAttrs[`${key}Attrs`] = getAttrs(key, getClasses(key, mutatedProps));
125
+
159
126
  const baseClasses = getBaseClasses(config.value[key]);
160
127
  const extendsMatches = baseClasses.match(EXTENDS_PATTERN_REG_EXP);
161
128
 
162
129
  if (extendsMatches) {
163
- keysAttrs[`${key}Attrs`] = getAttrs(key, getClasses(key, mutatedProps));
164
-
165
130
  // retrieves extends keys from patterns:
166
131
  // Example: `{>someKey} {>someOtherKey}` >>> `["someKey", "someOtherKey"]`.
167
132
  const extendsKeys = extendsMatches.map((pattern) => pattern.slice(2, -1));
@@ -228,12 +193,7 @@ export default function useUI<T>(
228
193
  return vuelessAttrs;
229
194
  }
230
195
 
231
- return {
232
- config,
233
- getKeysAttrs,
234
- getExtendingKeysClasses,
235
- hasSlotContent,
236
- };
196
+ return { config, getKeysAttrs, ...getKeysAttrs(mutatedProps) };
237
197
  }
238
198
 
239
199
  /**
@@ -274,28 +234,3 @@ function isCVA(config: UnknownObject): boolean {
274
234
  Object.keys(config).some((key) => key === value),
275
235
  );
276
236
  }
277
-
278
- /**
279
- * Check if slot defined, and have a content.
280
- */
281
- export function hasSlotContent(slot: Slot | undefined | null, props = {}): boolean {
282
- type Args = VNode | VNode[] | undefined | null;
283
-
284
- const asArray = (arg: Args) => {
285
- return Array.isArray(arg) ? arg : arg != null ? [arg] : [];
286
- };
287
-
288
- const isVNodeEmpty = (vnode: Args) => {
289
- return (
290
- !vnode ||
291
- asArray(vnode).every(
292
- (vnode) =>
293
- vnode.type === Comment ||
294
- (vnode.type === Text && !vnode.children?.length) ||
295
- (vnode.type === Fragment && !vnode.children?.length),
296
- )
297
- );
298
- };
299
-
300
- return !isVNodeEmpty(slot?.(props));
301
- }
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
  };
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.555",
3
+ "version": "0.0.557",
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 { ComputedRef, MaybeRef, Ref, UnwrapRef } from "vue";
50
48
  import type { Props } from "tippy.js";
51
49
  import type { LocaleOptions } from "./adatper.locale/vueless.ts";
52
50
 
@@ -229,6 +227,19 @@ export interface NestedComponent {
229
227
  [key: string]: Record<string, string | object> | string;
230
228
  }
231
229
 
230
+ export type ComponentConfig<T> = [T & Component] extends [Ref]
231
+ ? Ref<T & Component>
232
+ : Ref<UnwrapRef<T & Component>, T & Component>;
233
+
234
+ export interface UseUI<T> {
235
+ config: ComponentConfig<T>;
236
+ getKeysAttrs: (mutatedProps?: ComputedRef) => KeysAttrs;
237
+ [key: string]:
238
+ | ComputedRef<KeyAttrs>
239
+ | ComponentConfig<T>
240
+ | ((mutatedProps?: ComputedRef) => KeysAttrs);
241
+ }
242
+
232
243
  export interface Transition {
233
244
  enterFromClass?: string;
234
245
  enterActiveClass?: string;
@@ -256,10 +267,11 @@ export interface VueAttrs {
256
267
  value?: string;
257
268
  }
258
269
 
270
+ export type KeysAttrs = Record<string, Ref<UnknownObject | undefined>>;
271
+
259
272
  export interface UseAttrs<TConfig> {
260
- hasSlotContent: typeof hasSlotContent;
261
273
  config: Ref<TConfig | undefined>;
262
- [key: string]: Ref<TConfig | undefined> | typeof hasSlotContent;
274
+ [key: string]: Ref<TConfig | undefined>;
263
275
  }
264
276
 
265
277
  export interface KeyAttrs extends VueAttrs {
@@ -271,11 +283,6 @@ export interface KeyAttrs extends VueAttrs {
271
283
  [key: string]: string | UnknownObject | undefined | null;
272
284
  }
273
285
 
274
- export interface KeysToExtend {
275
- base?: ComputedRef;
276
- extend?: ComputedRef;
277
- }
278
-
279
286
  export interface CreateVuelessOptions {
280
287
  i18n?: LocaleOptions;
281
288
  }
@@ -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,23 @@ 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 mutatedProps = computed(() => ({
110
+ leftIcon: Boolean(props.leftIcon) || hasSlotContent(slots["left"]),
111
+ rightIcon: Boolean(props.rightIcon) || hasSlotContent(slots["right"]),
112
+ label: Boolean(props.label),
113
+ }));
114
+
115
+ const { buttonAttrs, loaderAttrs, leftIconAttrs, rightIconAttrs, centerIconAttrs } = useUI<Config>(
116
+ defaultConfig,
117
+ () => props.config,
118
+ "",
119
+ mutatedProps,
120
+ );
105
121
  </script>
106
122
 
107
123
  <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
  }