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.
- package/composables/useUI.ts +28 -64
- package/constants.js +21 -2
- package/index.d.ts +8 -1
- package/index.ts +1 -1
- package/package.json +1 -1
- package/types.ts +4 -10
- package/ui.button/UButton.vue +21 -7
- package/ui.button-link/ULink.vue +14 -2
- package/ui.button-link/config.ts +6 -1
- package/ui.button-link/useAttrs.ts +8 -39
- package/ui.button-toggle/useAttrs.ts +2 -8
- package/ui.button-toggle-item/config.ts +9 -11
- package/ui.button-toggle-item/useAttrs.ts +4 -18
- package/ui.container-accordion/config.ts +3 -1
- package/ui.container-accordion/useAttrs.ts +6 -17
- package/ui.container-card/UCard.vue +2 -1
- package/ui.container-card/useAttrs.ts +2 -8
- package/ui.container-col/useAttrs.ts +2 -8
- package/ui.container-divider/useAttrs.ts +2 -8
- package/ui.container-group/useAttrs.ts +2 -8
- package/ui.container-groups/useAttrs.ts +2 -8
- package/ui.container-modal/UModal.vue +1 -1
- package/ui.container-modal/useAttrs.ts +2 -12
- package/ui.container-modal-confirm/UModalConfirm.vue +3 -7
- package/ui.container-modal-confirm/useAttrs.ts +2 -8
- package/ui.container-page/UPage.vue +4 -5
- package/ui.container-page/useAttrs.ts +3 -32
- package/ui.container-row/useAttrs.ts +2 -8
- package/ui.data-list/UDataList.vue +3 -2
- package/ui.data-list/config.js +1 -1
- package/ui.data-list/useAttrs.js +2 -18
- package/ui.data-table/UTable.vue +6 -6
- package/ui.data-table/UTableRow.vue +1 -5
- package/ui.data-table/config.ts +28 -13
- package/ui.data-table/useAttrs.ts +10 -75
- package/ui.dropdown-badge/config.ts +10 -2
- package/ui.dropdown-badge/useAttrs.ts +8 -21
- package/ui.dropdown-button/config.ts +6 -6
- package/ui.dropdown-button/useAttrs.ts +6 -19
- package/ui.dropdown-link/config.ts +8 -2
- package/ui.dropdown-link/useAttrs.ts +10 -20
- package/ui.dropdown-list/config.ts +3 -2
- package/ui.dropdown-list/useAttrs.ts +2 -25
- package/ui.form-calendar/config.ts +36 -36
- package/ui.form-calendar/useAttrs.ts +2 -264
- package/ui.form-checkbox/useAttrs.ts +2 -8
- package/ui.form-checkbox-group/useAttrs.ts +2 -8
- package/ui.form-checkbox-multi-state/useAttrs.ts +2 -6
- package/ui.form-color-picker/useAttrs.js +2 -8
- package/ui.form-date-picker/useAttrs.ts +2 -6
- package/ui.form-date-picker-range/UDatePickerRange.vue +28 -28
- package/ui.form-date-picker-range/config.ts +30 -16
- package/ui.form-date-picker-range/useAttrs.ts +9 -70
- package/ui.form-input/UInput.vue +1 -1
- package/ui.form-input/useAttrs.js +2 -8
- package/ui.form-input-file/UInputFile.vue +3 -4
- package/ui.form-input-file/useAttrs.js +2 -8
- package/ui.form-input-money/useAttrs.js +2 -8
- package/ui.form-input-number/useAttrs.js +2 -8
- package/ui.form-input-rating/UInputRating.vue +5 -11
- package/ui.form-input-rating/useAttrs.js +2 -8
- package/ui.form-input-search/useAttrs.js +2 -8
- package/ui.form-label/useAttrs.js +2 -8
- package/ui.form-radio/useAttrs.ts +2 -8
- package/ui.form-radio-group/useAttrs.ts +2 -8
- package/ui.form-select/USelect.vue +37 -38
- package/ui.form-select/config.js +30 -11
- package/ui.form-select/useAttrs.js +6 -50
- package/ui.form-switch/useAttrs.js +2 -8
- package/ui.form-textarea/UTextarea.vue +5 -9
- package/ui.form-textarea/useAttrs.js +2 -8
- package/ui.image-avatar/useAttrs.ts +2 -8
- package/ui.image-icon/useAttrs.ts +2 -8
- package/ui.loader/config.ts +4 -1
- package/ui.loader/useAttrs.ts +2 -17
- package/ui.loader-overlay/useAttrs.ts +2 -12
- package/ui.loader-progress/ULoaderProgress.vue +2 -2
- package/ui.loader-progress/config.ts +8 -2
- package/ui.loader-progress/types.ts +5 -0
- package/ui.loader-progress/useAttrs.ts +3 -27
- package/ui.navigation-pagination/config.ts +6 -6
- package/ui.navigation-pagination/useAttrs.ts +2 -34
- package/ui.navigation-progress/config.ts +3 -1
- package/ui.navigation-progress/useAttrs.ts +5 -17
- package/ui.navigation-tab/config.ts +3 -1
- package/ui.navigation-tab/useAttrs.ts +4 -18
- package/ui.navigation-tabs/useAttrs.ts +2 -8
- package/ui.other-dot/useAttrs.ts +2 -8
- package/ui.text-alert/UAlert.vue +2 -1
- package/ui.text-alert/useAttrs.ts +2 -8
- package/ui.text-badge/useAttrs.ts +3 -8
- package/ui.text-block/UText.vue +2 -1
- package/ui.text-block/useAttrs.ts +2 -8
- package/ui.text-empty/useAttrs.ts +2 -8
- package/ui.text-file/useAttrs.ts +2 -8
- package/ui.text-files/useAttrs.ts +2 -8
- package/ui.text-header/useAttrs.ts +2 -8
- package/ui.text-money/UMoney.vue +1 -1
- package/ui.text-money/useAttrs.ts +2 -8
- package/ui.text-notify/useAttrs.ts +2 -8
- package/utils/helper.ts +29 -0
- package/utils/node/tailwindSafelist.js +2 -2
- package/utils/ui.ts +3 -4
- package/web-types.json +17 -1
- package/ui.button/useAttrs.ts +0 -26
package/composables/useUI.ts
CHANGED
|
@@ -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
|
-
|
|
9
|
+
NESTED_COMPONENT_PATTERN_REG_EXP,
|
|
10
|
+
EXTENDS_PATTERN_REG_EXP,
|
|
21
11
|
} from "../constants.js";
|
|
22
12
|
|
|
23
|
-
import type { ComponentInternalInstance,
|
|
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
|
-
...
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
|
134
|
-
if (isSystemKey(key)
|
|
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
|
-
|
|
139
|
-
|
|
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
|
-
...
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
|
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 {
|
|
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
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 {
|
|
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
|
|
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
|
}
|
package/ui.button/UButton.vue
CHANGED
|
@@ -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>
|
package/ui.button-link/ULink.vue
CHANGED
|
@@ -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
|
|
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"
|
package/ui.button-link/config.ts
CHANGED
|
@@ -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
|
-
|
|
11
|
-
|
|
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
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
|
9
|
+
const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
|
|
10
10
|
|
|
11
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
19
|
-
defaultConfig,
|
|
20
|
-
() => props.config,
|
|
21
|
-
);
|
|
18
|
+
const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
|
|
22
19
|
|
|
23
|
-
const
|
|
24
|
-
|
|
20
|
+
const mutatedProps = computed(() => ({
|
|
21
|
+
/* component state, not a props */
|
|
22
|
+
opened: isOpened.value,
|
|
23
|
+
}));
|
|
25
24
|
|
|
26
|
-
|
|
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
|
|
9
|
+
const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
|
|
10
10
|
|
|
11
|
-
|
|
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
|
|
9
|
+
const { config, getKeysAttrs } = useUI<Config>(defaultConfig, () => props.config);
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
config,
|
|
15
|
-
...keysAttrs,
|
|
16
|
-
hasSlotContent,
|
|
17
|
-
};
|
|
11
|
+
return { config, ...getKeysAttrs() };
|
|
18
12
|
}
|