vueless 1.1.1-beta.2 → 1.1.1-beta.20
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/adapter.locale/vue-i18n.ts +3 -2
- package/adapter.locale/vueless.ts +2 -23
- package/composables/tests/useUI.test.ts +28 -13
- package/composables/useComponentLocaleMassages.ts +6 -3
- package/composables/useLocale.ts +2 -2
- package/constants.js +2 -5
- package/directives/tooltip/storybook/docs.mdx +37 -0
- package/directives/tooltip/storybook/stories.ts +11 -8
- package/directives/tooltip/vTooltip.ts +1 -2
- package/icons/storybook/contact_mail.svg +1 -0
- package/icons/storybook/vpn_key.svg +1 -0
- package/icons/storybook/web_traffic.svg +1 -0
- package/index.d.ts +2 -1
- package/index.ts +2 -1
- package/package.json +2 -3
- package/plugin-vite.js +1 -8
- package/tailwind.css +25 -0
- package/types.ts +21 -1
- package/ui.boilerplate/tests/UBoilerplate.test.ts +2 -24
- package/ui.container-accordion/UAccordion.vue +15 -2
- package/ui.container-accordion/config.ts +1 -0
- package/ui.container-accordion/storybook/stories.ts +28 -1
- package/ui.container-accordion/tests/UAccordion.test.ts +46 -0
- package/ui.data-list/UDataList.vue +2 -0
- package/ui.data-table/UTable.vue +19 -13
- package/ui.data-table/storybook/stories.ts +11 -0
- package/ui.data-table/tests/UTable.test.ts +18 -0
- package/ui.dropdown-button/UDropdownButton.vue +1 -0
- package/ui.dropdown-button/config.ts +9 -1
- package/ui.dropdown-button/storybook/stories.ts +1 -1
- package/ui.dropdown-button/tests/UDropdownButton.test.ts +17 -1
- package/ui.dropdown-button/types.ts +5 -0
- package/ui.form-calendar/UCalendar.vue +9 -7
- package/ui.form-input/tests/UInput.test.ts +1 -1
- package/ui.form-input-counter/tests/UInputCounter.test.ts +1 -1
- package/ui.form-input-file/tests/UInputFile.test.ts +1 -1
- package/ui.form-input-password/tests/UInputPassword.test.ts +3 -3
- package/ui.form-input-rating/tests/UInputRating.test.ts +2 -2
- package/ui.form-input-search/tests/UInputSearch.test.ts +2 -2
- package/ui.form-listbox/UListbox.vue +1 -1
- package/ui.form-listbox/storybook/stories.ts +5 -5
- package/ui.form-select/config.ts +1 -1
- package/ui.form-select/storybook/stories.ts +5 -5
- package/ui.image-icon/tests/UIcon.test.ts +2 -2
- package/ui.navigation-pagination/UPagination.vue +2 -7
- package/ui.navigation-pagination/config.ts +1 -0
- package/ui.navigation-pagination/tests/UPagination.test.ts +1 -1
- package/ui.navigation-pagination/types.ts +1 -1
- package/ui.text-notify/tests/UNotify.test.ts +1 -1
- package/utils/node/dynamicProps.js +17 -8
- package/utils/node/helper.js +11 -1
- package/utils/node/storybook.js +52 -0
- package/utils/node/vuelessConfig.js +18 -8
- package/utils/theme.ts +13 -11
- package/utils/node/dynamicStories.js +0 -62
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { I18n } from "vue-i18n";
|
|
2
|
+
import type { LocaleInstance } from "../types.ts";
|
|
2
3
|
|
|
3
|
-
export
|
|
4
|
+
export function createVueI18nAdapter(i18n: I18n): LocaleInstance {
|
|
4
5
|
return {
|
|
5
6
|
name: "vue-i18n",
|
|
6
7
|
locale: i18n.global.locale,
|
|
7
|
-
fallback: i18n.global.fallbackLocale,
|
|
8
|
+
fallback: i18n.global.fallbackLocale as string,
|
|
8
9
|
messages: i18n.global.messages,
|
|
9
10
|
// @ts-expect-error Type instantiation is excessively deep and possibly infinite
|
|
10
11
|
t: (key: string, ...params: unknown[]) => i18n.global.t(key, params),
|
|
@@ -4,33 +4,12 @@ import { merge } from "lodash-es";
|
|
|
4
4
|
import en from "./locales/en.ts";
|
|
5
5
|
|
|
6
6
|
import type { Ref } from "vue";
|
|
7
|
-
import type { UnknownObject } from "../types.ts";
|
|
8
7
|
import type { VueMessageType } from "vue-i18n";
|
|
9
|
-
|
|
10
|
-
export interface LocaleMessages {
|
|
11
|
-
[key: string]: LocaleMessages | string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface LocaleOptions {
|
|
15
|
-
messages?: LocaleMessages;
|
|
16
|
-
locale?: string;
|
|
17
|
-
fallback?: string;
|
|
18
|
-
adapter?: LocaleInstance;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface LocaleInstance {
|
|
22
|
-
name: string;
|
|
23
|
-
messages: Ref<LocaleMessages>;
|
|
24
|
-
locale: Ref<string>;
|
|
25
|
-
fallback: Ref<string>;
|
|
26
|
-
t: (key: string, ...params: unknown[]) => string;
|
|
27
|
-
n: (value: number) => string;
|
|
28
|
-
tm: <TMassages>(key: string) => Partial<TMassages>;
|
|
29
|
-
}
|
|
8
|
+
import type { UnknownObject, LocaleOptions, LocaleMessages, LocaleInstance } from "../types.ts";
|
|
30
9
|
|
|
31
10
|
const FALLBACK_LOCALE_CODE = "en";
|
|
32
11
|
|
|
33
|
-
export
|
|
12
|
+
export function createVuelessAdapter(options?: LocaleOptions): LocaleInstance {
|
|
34
13
|
const current = shallowRef(options?.locale ?? FALLBACK_LOCALE_CODE);
|
|
35
14
|
const fallback = shallowRef(options?.fallback ?? FALLBACK_LOCALE_CODE);
|
|
36
15
|
|
|
@@ -2,14 +2,15 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
|
2
2
|
import { computed, nextTick } from "vue";
|
|
3
3
|
import { mount } from "@vue/test-utils";
|
|
4
4
|
|
|
5
|
+
import type { ComponentInternalInstance } from "vue";
|
|
6
|
+
|
|
5
7
|
// TODO: Autogenerated, need to be reviewed
|
|
6
8
|
|
|
7
9
|
// Mock the ui utils
|
|
8
10
|
vi.mock("../../utils/ui.ts", () => ({
|
|
9
11
|
cx: vi.fn((classes) => (Array.isArray(classes) ? classes.filter(Boolean).join(" ") : classes)),
|
|
10
12
|
cva: vi.fn((config) => {
|
|
11
|
-
|
|
12
|
-
const cvaSpy = vi.fn((props) => {
|
|
13
|
+
return vi.fn((props) => {
|
|
13
14
|
if (!config.variants) return config.base || "";
|
|
14
15
|
|
|
15
16
|
let classes = config.base || "";
|
|
@@ -17,16 +18,15 @@ vi.mock("../../utils/ui.ts", () => ({
|
|
|
17
18
|
// Apply variants
|
|
18
19
|
Object.entries(config.variants).forEach(([key, variants]) => {
|
|
19
20
|
const value = props[key];
|
|
21
|
+
const variantsRecord = variants as UnknownObject;
|
|
20
22
|
|
|
21
|
-
if (
|
|
22
|
-
classes += ` ${
|
|
23
|
+
if (variantsRecord?.[value]) {
|
|
24
|
+
classes += ` ${variantsRecord[value]}`;
|
|
23
25
|
}
|
|
24
26
|
});
|
|
25
27
|
|
|
26
28
|
return classes.trim();
|
|
27
29
|
});
|
|
28
|
-
|
|
29
|
-
return cvaSpy;
|
|
30
30
|
}),
|
|
31
31
|
setColor: vi.fn((classes, color) => classes?.replace(/{color}/g, color)),
|
|
32
32
|
vuelessConfig: { components: {}, unstyled: false },
|
|
@@ -56,10 +56,25 @@ vi.mock("vue", async () => {
|
|
|
56
56
|
import useUI from "../useUI.ts";
|
|
57
57
|
import * as uiUtils from "../../utils/ui.ts";
|
|
58
58
|
import { getCurrentInstance, useAttrs } from "vue";
|
|
59
|
+
import type { UnknownObject } from "../../types.ts";
|
|
59
60
|
|
|
60
61
|
// Test component for integration testing
|
|
61
62
|
const TestComponent = {
|
|
62
63
|
template: '<div :data-test="getDataTest()" v-bind="bodyAttrs">Test</div>',
|
|
64
|
+
props: {
|
|
65
|
+
config: {
|
|
66
|
+
type: Object,
|
|
67
|
+
default: () => ({}),
|
|
68
|
+
},
|
|
69
|
+
dataTest: {
|
|
70
|
+
type: String,
|
|
71
|
+
default: null,
|
|
72
|
+
},
|
|
73
|
+
color: {
|
|
74
|
+
type: String,
|
|
75
|
+
default: "primary",
|
|
76
|
+
},
|
|
77
|
+
},
|
|
63
78
|
setup() {
|
|
64
79
|
const defaultConfig = {
|
|
65
80
|
body: {
|
|
@@ -97,7 +112,7 @@ describe("useUI", () => {
|
|
|
97
112
|
type: { __name: "TestComponent" },
|
|
98
113
|
props: { dataTest: "test", color: "primary", config: {} },
|
|
99
114
|
parent: null,
|
|
100
|
-
});
|
|
115
|
+
} as unknown as ComponentInternalInstance);
|
|
101
116
|
|
|
102
117
|
vi.mocked(useAttrs).mockReturnValue({
|
|
103
118
|
class: "",
|
|
@@ -148,7 +163,7 @@ describe("useUI", () => {
|
|
|
148
163
|
type: { __name: "TestComponent" },
|
|
149
164
|
props: { config: propsConfig, dataTest: "test" },
|
|
150
165
|
parent: null,
|
|
151
|
-
});
|
|
166
|
+
} as unknown as ComponentInternalInstance);
|
|
152
167
|
|
|
153
168
|
// Call useUI to trigger the config merging
|
|
154
169
|
useUI(defaultConfig);
|
|
@@ -201,7 +216,7 @@ describe("useUI", () => {
|
|
|
201
216
|
type: { __name: "TestComponent" },
|
|
202
217
|
props: { color: "blue", dataTest: "test" },
|
|
203
218
|
parent: null,
|
|
204
|
-
});
|
|
219
|
+
} as unknown as ComponentInternalInstance);
|
|
205
220
|
|
|
206
221
|
// Test the setColor function directly
|
|
207
222
|
expect(uiUtils.setColor).toBeDefined();
|
|
@@ -247,7 +262,7 @@ describe("useUI", () => {
|
|
|
247
262
|
type: { __name: "TestComponent" },
|
|
248
263
|
props: {},
|
|
249
264
|
parent: null,
|
|
250
|
-
});
|
|
265
|
+
} as unknown as ComponentInternalInstance);
|
|
251
266
|
|
|
252
267
|
const result = useUI({});
|
|
253
268
|
const dataTest = result.getDataTest();
|
|
@@ -336,7 +351,7 @@ describe("useUI", () => {
|
|
|
336
351
|
type: { __name: "UButton" },
|
|
337
352
|
props: { dataTest: "test" },
|
|
338
353
|
parent: null,
|
|
339
|
-
});
|
|
354
|
+
} as unknown as ComponentInternalInstance);
|
|
340
355
|
|
|
341
356
|
const result = useUI({});
|
|
342
357
|
|
|
@@ -349,8 +364,8 @@ describe("useUI", () => {
|
|
|
349
364
|
props: { dataTest: "test" },
|
|
350
365
|
parent: {
|
|
351
366
|
type: { __name: "UButton" },
|
|
352
|
-
},
|
|
353
|
-
});
|
|
367
|
+
} as UnknownObject,
|
|
368
|
+
} as unknown as ComponentInternalInstance);
|
|
354
369
|
|
|
355
370
|
const result = useUI({});
|
|
356
371
|
|
|
@@ -17,9 +17,12 @@ export function useComponentLocaleMessages<TLocale>(
|
|
|
17
17
|
|
|
18
18
|
const globalComponentMassages = ref(recursiveRt(tm(componentName) as VueMessageType));
|
|
19
19
|
|
|
20
|
-
watch(
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
watch(
|
|
21
|
+
() => locale,
|
|
22
|
+
() => {
|
|
23
|
+
globalComponentMassages.value = recursiveRt(tm(componentName) as VueMessageType);
|
|
24
|
+
},
|
|
25
|
+
);
|
|
23
26
|
|
|
24
27
|
const localeMessages = computed(
|
|
25
28
|
() => merge({}, defaultLocale, globalComponentMassages.value, propsLocale) as TLocale,
|
package/composables/useLocale.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { inject } from "vue";
|
|
2
|
-
import createVuelessAdapter from "../adapter.locale/vueless.ts";
|
|
2
|
+
import { createVuelessAdapter } from "../adapter.locale/vueless.ts";
|
|
3
3
|
|
|
4
|
-
import type { LocaleInstance, LocaleOptions } from "../adapter.locale/vueless.ts";
|
|
5
4
|
import type { InjectionKey } from "vue";
|
|
5
|
+
import type { LocaleInstance, LocaleOptions } from "../types.ts";
|
|
6
6
|
|
|
7
7
|
export const LocaleSymbol: InjectionKey<LocaleInstance> = Symbol.for("vueless:locale");
|
|
8
8
|
|
package/constants.js
CHANGED
|
@@ -368,10 +368,6 @@ export const DEFAULT_SVGO_CONFIG = {
|
|
|
368
368
|
},
|
|
369
369
|
},
|
|
370
370
|
},
|
|
371
|
-
{
|
|
372
|
-
name: "removeViewBox",
|
|
373
|
-
active: false,
|
|
374
|
-
},
|
|
375
371
|
],
|
|
376
372
|
};
|
|
377
373
|
|
|
@@ -384,9 +380,10 @@ export const VUELESS_LIBRARY = "vueless";
|
|
|
384
380
|
export const INTERNAL_ICONS_LIBRARY = "internal";
|
|
385
381
|
export const STORYBOOK_ICONS_LIBRARY = "storybook";
|
|
386
382
|
|
|
383
|
+
export const CACHE_DIR = ".cache";
|
|
387
384
|
export const NODE_MODULES_DIR = "node_modules";
|
|
388
385
|
export const VUELESS_PACKAGE_DIR = `${NODE_MODULES_DIR}/vueless`;
|
|
389
|
-
export const VUELESS_CACHE_DIR = `${NODE_MODULES_DIR}
|
|
386
|
+
export const VUELESS_CACHE_DIR = `${NODE_MODULES_DIR}/${CACHE_DIR}/vueless`;
|
|
390
387
|
export const VUELESS_LOCAL_DIR = "src";
|
|
391
388
|
export const ICONS_DIR = "icons";
|
|
392
389
|
export const ICONS_VUELESS_DIR = `${VUELESS_PACKAGE_DIR}/${ICONS_DIR}`;
|
|
@@ -8,3 +8,40 @@ import * as stories from "./stories.ts";
|
|
|
8
8
|
<Description of={stories} />
|
|
9
9
|
<Controls of={stories.Default} />
|
|
10
10
|
<Stories of={stories} />
|
|
11
|
+
|
|
12
|
+
## Theme Configuration
|
|
13
|
+
You can use the default `vueless` theme or create your own [custom one](https://atomiks.github.io/tippyjs/v6/themes/) via the global Vueless config:
|
|
14
|
+
|
|
15
|
+
<Source code={`
|
|
16
|
+
directives: {
|
|
17
|
+
tooltip: {
|
|
18
|
+
theme: "custom",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
`} language="jsx" dark />
|
|
22
|
+
|
|
23
|
+
## Customizing Styles
|
|
24
|
+
To customize the default `vueless` or your own custom theme, simply update your CSS as shown below:
|
|
25
|
+
|
|
26
|
+
<Source code={`
|
|
27
|
+
.tippy-box[data-theme~="custom"] {
|
|
28
|
+
background-color: var(--vl-neutral-accented);
|
|
29
|
+
color: var(--vl-text-inverted);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.tippy-box[data-theme~="custom"][data-placement^="top"] > .tippy-arrow:before {
|
|
33
|
+
border-top-color: var(--vl-neutral-accented);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.tippy-box[data-theme~="custom"][data-placement^="bottom"] > .tippy-arrow:before {
|
|
37
|
+
border-bottom-color: var(--vl-neutral-accented);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.tippy-box[data-theme~="custom"][data-placement^="left"] > .tippy-arrow:before {
|
|
41
|
+
border-left-color: var(--vl-neutral-accented);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.tippy-box[data-theme~="custom"][data-placement^="right"] > .tippy-arrow:before {
|
|
45
|
+
border-right-color: var(--vl-neutral-accented);
|
|
46
|
+
}
|
|
47
|
+
`} language="jsx" dark />
|
|
@@ -2,9 +2,6 @@ import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
|
2
2
|
|
|
3
3
|
import UIcon from "../../../ui.image-icon/UIcon.vue";
|
|
4
4
|
import UCol from "../../../ui.container-col/UCol.vue";
|
|
5
|
-
import UAlert from "../../../ui.text-alert/UAlert.vue";
|
|
6
|
-
import ULink from "../../../ui.button-link/ULink.vue";
|
|
7
|
-
import UText from "../../../ui.text-block/UText.vue";
|
|
8
5
|
import tooltip from "../vTooltip.ts";
|
|
9
6
|
|
|
10
7
|
import type { Props } from "tippy.js";
|
|
@@ -35,7 +32,7 @@ const DefaultTemplate: StoryFn<VTooltipArgs> = (args: VTooltipArgs) => ({
|
|
|
35
32
|
});
|
|
36
33
|
|
|
37
34
|
const TooltipSettingsTemplate: StoryFn<VTooltipArgs> = (args: VTooltipArgs) => ({
|
|
38
|
-
components: { UIcon, UCol
|
|
35
|
+
components: { UIcon, UCol },
|
|
39
36
|
directives: { tooltip },
|
|
40
37
|
setup() {
|
|
41
38
|
return { args };
|
|
@@ -45,7 +42,13 @@ const TooltipSettingsTemplate: StoryFn<VTooltipArgs> = (args: VTooltipArgs) => (
|
|
|
45
42
|
<UIcon
|
|
46
43
|
interactive
|
|
47
44
|
name="sentiment_satisfied"
|
|
48
|
-
v-tooltip="{
|
|
45
|
+
v-tooltip="{
|
|
46
|
+
content: '<b>Tooltip</b>',
|
|
47
|
+
placement: 'bottom',
|
|
48
|
+
allowHTML: true,
|
|
49
|
+
hideOnClick: true,
|
|
50
|
+
trigger: 'click'
|
|
51
|
+
}"
|
|
49
52
|
/>
|
|
50
53
|
</UCol>
|
|
51
54
|
`,
|
|
@@ -60,9 +63,9 @@ TooltipSettings.parameters = {
|
|
|
60
63
|
docs: {
|
|
61
64
|
description: {
|
|
62
65
|
story: `
|
|
63
|
-
This
|
|
64
|
-
including HTML content and
|
|
65
|
-
refer to the <a href="https://atomiks.github.io/tippyjs/v6/all-props/" target="_blank" class="!no-underline">Tippy.js documentation</a>.
|
|
66
|
+
This example shows how to configure the \`v-tooltip\` directive with custom options,
|
|
67
|
+
including HTML content, specific placement, click-triggered display, and persistent visibility after a click.
|
|
68
|
+
For a full list of available settings, refer to the <a href="https://atomiks.github.io/tippyjs/v6/all-props/" target="_blank" class="!no-underline">Tippy.js documentation</a>.
|
|
66
69
|
`,
|
|
67
70
|
},
|
|
68
71
|
},
|
|
@@ -15,12 +15,11 @@ let settings: Partial<DefaultProps> = {};
|
|
|
15
15
|
|
|
16
16
|
if (isCSR) {
|
|
17
17
|
import("tippy.js/dist/tippy.css");
|
|
18
|
-
import("tippy.js/themes/light.css");
|
|
19
18
|
import("tippy.js/animations/shift-away.css");
|
|
20
19
|
|
|
21
20
|
const defaultSettings = {
|
|
22
21
|
arrow: true,
|
|
23
|
-
theme: "
|
|
22
|
+
theme: "vueless",
|
|
24
23
|
animation: "shift-away",
|
|
25
24
|
};
|
|
26
25
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 -960 960 960"><path d="M561.76-524.48h264.17v-184.09H561.76v184.09Zm133.09-37L590.33-640v-40l103.52 78.52L797.37-680v40l-102.52 78.52ZM68.37-117.37q-27.7 0-48.03-20.27Q0-157.9 0-185.5v-589q0-27.6 20.34-47.86 20.33-20.27 48.03-20.27h823.5q27.35 0 47.74 20.27Q960-802.1 960-774.5v589q0 27.6-20.39 47.86-20.39 20.27-47.74 20.27H68.37Zm528.13-65.26h298v-594.74h-829v594.74h7q44-68.76 112.5-108.88 68.5-40.12 149.5-40.12 81.24 0 149.62 40.12 68.38 40.12 112.38 108.88Zm-262.48-218.8q50.76 0 85.98-35.36 35.22-35.36 35.22-85.96 0-50.6-35.21-85.96-35.21-35.36-85.96-35.36-50.75 0-86.1 35.34-35.36 35.34-35.36 86.1 0 50.48 35.34 85.84 35.33 35.36 86.09 35.36Zm-178.58 218.8h357.17q-34.91-39.6-81.43-61.67-46.53-22.07-97.15-22.07-50.62 0-97.08 22.07-46.47 22.06-81.51 61.67Zm178.58-281.44q-24.79 0-41.79-16.93-17.01-16.94-17.01-41.75 0-24.91 17-41.8 17.01-16.88 41.8-16.88 24.78 0 41.68 16.9 16.89 16.91 16.89 41.9 0 24.78-16.94 41.67t-41.63 16.89ZM480-480Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 -960 960 960"><path d="M280-234.5q-102.07 0-173.79-71.73Q34.5-377.96 34.5-480.06q0-102.09 71.71-173.77Q177.93-725.5 280-725.5q80.63 0 135.45 39.05 54.81 39.06 80.33 100.82H925.5v211.26h-106v137H628v-137H495.73q-25.47 61.76-80.28 100.82Q360.63-234.5 280-234.5Zm0-65.5q72.2 0 117.82-48.2 45.61-48.19 52.61-91.43H697.5v137H754v-137h106v-80.74H450.48q-7.05-43.24-52.66-91.43Q352.2-660 280-660q-75 0-127.5 52.5T100-480q0 75 52.5 127.5T280-300Zm-.06-109.37q30.26 0 50.47-20.28 20.22-20.27 20.22-50.29 0-30.26-20.16-50.47-20.16-20.22-50.41-20.22-30.02 0-50.35 20.16-20.34 20.16-20.34 50.41 0 30.02 20.28 50.35 20.27 20.34 50.29 20.34ZM280-480Z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 -960 960 960"><path d="M118.37-471.57v-62.86H247v62.86H118.37Zm115.2 232.68-41.68-41.68 89.68-89.91 41.91 41.91-89.91 89.68Zm48-399.63-89.68-89.91 41.68-41.92 89.91 89.92-41.91 41.91Zm469.19 494.11L559.17-335.76l-45.43 139.83-107.83-373.16 364.92 114.83L629-403.83l190.59 190.59-68.83 68.83ZM435.57-714v-128.63h62.86V-714h-62.86Zm216.86 75.48-41.91-41.91 89.91-89.92 41.92 41.92-89.92 89.91Z"/></svg>
|
package/index.d.ts
CHANGED
|
@@ -12,7 +12,8 @@ export {
|
|
|
12
12
|
} from "./utils/helper.ts";
|
|
13
13
|
export { getArgTypes, getSlotNames, getSlotsFragment, getSource } from "./utils/storybook.ts";
|
|
14
14
|
export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform.ts";
|
|
15
|
-
export {
|
|
15
|
+
export { createVueI18nAdapter } from "./adapter.locale/vue-i18n.ts";
|
|
16
|
+
export { createVuelessAdapter } from "./adapter.locale/vueless.ts";
|
|
16
17
|
export { default as defaultEnLocale } from "./adapter.locale/locales/en.ts";
|
|
17
18
|
export { default as useUI } from "./composables/useUI.ts";
|
|
18
19
|
export { useLocale } from "./composables/useLocale.ts";
|
package/index.ts
CHANGED
|
@@ -13,7 +13,8 @@ export { cx, cva, compose, getDefaults } from "./utils/ui.ts";
|
|
|
13
13
|
export { getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook.ts";
|
|
14
14
|
export { isSSR, isCSR, getRandomId, setTitle, createDebounce, hasSlotContent } from "./utils/helper.ts";
|
|
15
15
|
export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform.ts";
|
|
16
|
-
export {
|
|
16
|
+
export { createVueI18nAdapter } from "./adapter.locale/vue-i18n.ts";
|
|
17
|
+
export { createVuelessAdapter } from "./adapter.locale/vueless.ts";
|
|
17
18
|
export { default as defaultEnLocale } from "./adapter.locale/locales/en.ts";
|
|
18
19
|
export { default as useUI } from "./composables/useUI.ts";
|
|
19
20
|
export { useLocale } from "./composables/useLocale.ts";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vueless",
|
|
3
|
-
"version": "1.1.1-beta.
|
|
3
|
+
"version": "1.1.1-beta.20",
|
|
4
4
|
"description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
|
|
5
5
|
"author": "Johnny Grid <hello@vueless.com> (https://vueless.com)",
|
|
6
6
|
"homepage": "https://vueless.com",
|
|
@@ -45,7 +45,6 @@
|
|
|
45
45
|
"vuedraggable": "4.1.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@eslint/js": "^9.32.0",
|
|
49
48
|
"@material-symbols/svg-500": "^0.33.0",
|
|
50
49
|
"@release-it/bumper": "^7.0.5",
|
|
51
50
|
"@tsconfig/node20": "^20.1.6",
|
|
@@ -58,7 +57,7 @@
|
|
|
58
57
|
"@vue/eslint-config-typescript": "^14.6.0",
|
|
59
58
|
"@vue/test-utils": "^2.4.6",
|
|
60
59
|
"@vue/tsconfig": "^0.7.0",
|
|
61
|
-
"@vueless/storybook": "^1.1.
|
|
60
|
+
"@vueless/storybook": "^1.1.3",
|
|
62
61
|
"eslint": "^9.32.0",
|
|
63
62
|
"eslint-plugin-storybook": "^9.0.18",
|
|
64
63
|
"eslint-plugin-vue": "^10.3.0",
|
package/plugin-vite.js
CHANGED
|
@@ -20,7 +20,6 @@ import { createTailwindSafelist, clearTailwindSafelist } from "./utils/node/tail
|
|
|
20
20
|
import { componentResolver, directiveResolver } from "./utils/node/vuelessResolver.js";
|
|
21
21
|
import { setCustomPropTypes, removeCustomPropTypes } from "./utils/node/dynamicProps.js";
|
|
22
22
|
import { buildWebTypes } from "./utils/node/webTypes.js";
|
|
23
|
-
import { hideHiddenStories, showHiddenStories } from "./utils/node/dynamicStories.js";
|
|
24
23
|
import {
|
|
25
24
|
getNuxtDirs,
|
|
26
25
|
getVueDirs,
|
|
@@ -81,7 +80,6 @@ export const Vueless = function (options = {}) {
|
|
|
81
80
|
/* if server stopped by developer (Ctrl+C) */
|
|
82
81
|
process.on("SIGINT", async () => {
|
|
83
82
|
if (isInternalEnv || isStorybookEnv) {
|
|
84
|
-
await showHiddenStories(vuelessSrcDir);
|
|
85
83
|
await removeCustomPropTypes(vuelessSrcDir);
|
|
86
84
|
}
|
|
87
85
|
|
|
@@ -116,7 +114,7 @@ export const Vueless = function (options = {}) {
|
|
|
116
114
|
"process.env": {},
|
|
117
115
|
},
|
|
118
116
|
optimizeDeps: {
|
|
119
|
-
include: ["vueless/directives/**/*.ts"],
|
|
117
|
+
include: ["vueless/directives/**/*.ts", "vueless/constants.js"],
|
|
120
118
|
},
|
|
121
119
|
}),
|
|
122
120
|
|
|
@@ -133,11 +131,6 @@ export const Vueless = function (options = {}) {
|
|
|
133
131
|
await buildWebTypes(vuelessSrcDir);
|
|
134
132
|
await setCustomPropTypes(vuelessSrcDir);
|
|
135
133
|
|
|
136
|
-
if (isInternalEnv || isStorybookEnv) {
|
|
137
|
-
await showHiddenStories(vuelessSrcDir);
|
|
138
|
-
await hideHiddenStories(vuelessSrcDir);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
134
|
/* collect used in project colors for tailwind safelist */
|
|
142
135
|
await createTailwindSafelist({ env, srcDir: vuelessSrcDir, targetFiles, debug });
|
|
143
136
|
|
package/tailwind.css
CHANGED
|
@@ -131,3 +131,28 @@
|
|
|
131
131
|
outline-style: var(--tw-outline-style);
|
|
132
132
|
outline-width: var(--vl-outline-lg);
|
|
133
133
|
}
|
|
134
|
+
|
|
135
|
+
/* ------ Tippy.js Vueless default theme ------ */
|
|
136
|
+
.tippy-box[data-theme~="vueless"] {
|
|
137
|
+
background-color: var(--vl-bg-inverted);
|
|
138
|
+
color: var(--vl-text-inverted);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.tippy-box[data-theme~="vueless"][data-placement^="top"] > .tippy-arrow:before {
|
|
142
|
+
border-top-color: var(--vl-bg-inverted);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.tippy-box[data-theme~="vueless"][data-placement^="bottom"] > .tippy-arrow:before {
|
|
146
|
+
border-bottom-color: var(--vl-bg-inverted);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.tippy-box[data-theme~="vueless"][data-placement^="left"] > .tippy-arrow:before {
|
|
150
|
+
border-left-color: var(--vl-bg-inverted);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.tippy-box[data-theme~="vueless"][data-placement^="right"] > .tippy-arrow:before {
|
|
154
|
+
border-right-color: var(--vl-bg-inverted);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
|
package/types.ts
CHANGED
|
@@ -61,7 +61,6 @@ import UListboxConfig from "./ui.form-listbox/config.ts";
|
|
|
61
61
|
import type { Props } from "tippy.js";
|
|
62
62
|
import type { Config as TailwindConfig } from "tailwindcss";
|
|
63
63
|
import type { ComputedRef, Ref, ComponentInternalInstance } from "vue";
|
|
64
|
-
import type { LocaleOptions } from "./adapter.locale/vueless.ts";
|
|
65
64
|
|
|
66
65
|
export enum ColorMode {
|
|
67
66
|
Dark = "dark",
|
|
@@ -366,6 +365,27 @@ export interface CreateVuelessOptions extends Config {
|
|
|
366
365
|
config?: Config;
|
|
367
366
|
}
|
|
368
367
|
|
|
368
|
+
export interface LocaleOptions {
|
|
369
|
+
messages?: LocaleMessages;
|
|
370
|
+
locale?: string;
|
|
371
|
+
fallback?: string;
|
|
372
|
+
adapter?: LocaleInstance;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export interface LocaleInstance {
|
|
376
|
+
name: string;
|
|
377
|
+
messages: LocaleMessages | Ref<LocaleMessages>;
|
|
378
|
+
locale: string | Ref<string>;
|
|
379
|
+
fallback: string | Ref<string>;
|
|
380
|
+
t: (key: string, ...params: unknown[]) => string;
|
|
381
|
+
n: (value: number) => string;
|
|
382
|
+
tm: <TMassages>(key: string) => Partial<TMassages>;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export interface LocaleMessages {
|
|
386
|
+
[key: string]: LocaleMessages | string;
|
|
387
|
+
}
|
|
388
|
+
|
|
369
389
|
export interface VuelessCssVariables {
|
|
370
390
|
/* Outline size CSS variables */
|
|
371
391
|
"--vl-outline-sm": string;
|
|
@@ -5,10 +5,8 @@ import UBoilerplate from "../UBoilerplate.vue";
|
|
|
5
5
|
import defaultConfig from "../config.ts";
|
|
6
6
|
|
|
7
7
|
describe("UBoilerplate.vue", () => {
|
|
8
|
-
// Props tests
|
|
9
8
|
describe("Props", () => {
|
|
10
|
-
|
|
11
|
-
it("accepts the dataTest prop", () => {
|
|
9
|
+
it("Data Test – accepts the dataTest prop", () => {
|
|
12
10
|
const dataTest = "test-boilerplate";
|
|
13
11
|
|
|
14
12
|
const component = mount(UBoilerplate, {
|
|
@@ -20,8 +18,7 @@ describe("UBoilerplate.vue", () => {
|
|
|
20
18
|
expect(component.attributes("data-test")).toBe(dataTest);
|
|
21
19
|
});
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
it("applies custom config when provided", () => {
|
|
21
|
+
it("Config – applies custom config when provided", () => {
|
|
25
22
|
const customClass = "custom-class";
|
|
26
23
|
const config = {
|
|
27
24
|
wrapper: customClass,
|
|
@@ -38,23 +35,4 @@ describe("UBoilerplate.vue", () => {
|
|
|
38
35
|
expect(component.attributes("class")).toContain(defaultConfig.wrapper);
|
|
39
36
|
});
|
|
40
37
|
});
|
|
41
|
-
|
|
42
|
-
/*
|
|
43
|
-
// Slots tests
|
|
44
|
-
describe("Slots", () => {
|
|
45
|
-
// Default slot
|
|
46
|
-
it("renders content from default slot", () => {
|
|
47
|
-
const slotContent = "Custom Content";
|
|
48
|
-
|
|
49
|
-
const component = mount(UBoilerplate, {
|
|
50
|
-
slots: {
|
|
51
|
-
default: slotContent,
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
expect(component.text()).not.toBe("Boilerplate");
|
|
56
|
-
expect(component.text()).toBe(slotContent);
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
*/
|
|
60
38
|
});
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed, ref, useId, useTemplateRef } from "vue";
|
|
2
|
+
import { computed, ref, useId, useSlots, useTemplateRef } from "vue";
|
|
3
3
|
|
|
4
4
|
import useUI from "../composables/useUI.ts";
|
|
5
5
|
import { getDefaults } from "../utils/ui.ts";
|
|
6
|
+
import { hasSlotContent } from "../utils/helper.ts";
|
|
6
7
|
|
|
7
8
|
import UIcon from "../ui.image-icon/UIcon.vue";
|
|
8
9
|
import UDivider from "../ui.container-divider/UDivider.vue";
|
|
@@ -31,6 +32,7 @@ const wrapperRef = useTemplateRef<HTMLDivElement>("wrapper");
|
|
|
31
32
|
|
|
32
33
|
const isOpened = ref(false);
|
|
33
34
|
|
|
35
|
+
const slots = useSlots();
|
|
34
36
|
const elementId = props.id || useId();
|
|
35
37
|
|
|
36
38
|
const toggleIconName = computed(() => {
|
|
@@ -67,6 +69,7 @@ const {
|
|
|
67
69
|
descriptionAttrs,
|
|
68
70
|
bodyAttrs,
|
|
69
71
|
titleAttrs,
|
|
72
|
+
contentAttrs,
|
|
70
73
|
toggleIconAttrs,
|
|
71
74
|
accordionDividerAttrs,
|
|
72
75
|
} = useUI<Config>(defaultConfig, mutatedProps);
|
|
@@ -93,7 +96,17 @@ const {
|
|
|
93
96
|
</slot>
|
|
94
97
|
</div>
|
|
95
98
|
|
|
96
|
-
<div
|
|
99
|
+
<div
|
|
100
|
+
v-if="description"
|
|
101
|
+
:id="`description-${elementId}`"
|
|
102
|
+
v-bind="descriptionAttrs"
|
|
103
|
+
v-text="description"
|
|
104
|
+
/>
|
|
105
|
+
|
|
106
|
+
<div v-if="isOpened && hasSlotContent(slots['default'])" v-bind="contentAttrs">
|
|
107
|
+
<!-- @slot Use it to add accordion content. -->
|
|
108
|
+
<slot />
|
|
109
|
+
</div>
|
|
97
110
|
</div>
|
|
98
111
|
|
|
99
112
|
<UDivider v-bind="accordionDividerAttrs" />
|
|
@@ -10,6 +10,9 @@ import {
|
|
|
10
10
|
import UAccordion from "../../ui.container-accordion/UAccordion.vue";
|
|
11
11
|
import UButton from "../../ui.button/UButton.vue";
|
|
12
12
|
import ULink from "../../ui.button-link/ULink.vue";
|
|
13
|
+
import UCol from "../../ui.container-col/UCol.vue";
|
|
14
|
+
import URow from "../../ui.container-row/URow.vue";
|
|
15
|
+
import UIcon from "../../ui.image-icon/UIcon.vue";
|
|
13
16
|
|
|
14
17
|
import type { Meta, StoryFn } from "@storybook/vue3-vite";
|
|
15
18
|
import type { Props } from "../types.ts";
|
|
@@ -41,7 +44,7 @@ export default {
|
|
|
41
44
|
} as Meta;
|
|
42
45
|
|
|
43
46
|
const DefaultTemplate: StoryFn<UAccordionArgs> = (args: UAccordionArgs) => ({
|
|
44
|
-
components: { UAccordion, ULink },
|
|
47
|
+
components: { UAccordion, ULink, UButton, UCol, URow, UIcon },
|
|
45
48
|
setup: () => ({ args, slots: getSlotNames(UAccordion.__name) }),
|
|
46
49
|
template: `
|
|
47
50
|
<UAccordion v-bind="args">
|
|
@@ -113,6 +116,30 @@ Accordions.args = {};
|
|
|
113
116
|
export const Sizes = EnumTemplate.bind({});
|
|
114
117
|
Sizes.args = { enum: "size", description: "{enumValue}" };
|
|
115
118
|
|
|
119
|
+
export const DefaultSlot = DefaultTemplate.bind({});
|
|
120
|
+
DefaultSlot.args = {
|
|
121
|
+
slotTemplate: `
|
|
122
|
+
<template #default>
|
|
123
|
+
<UCol gap="sm">
|
|
124
|
+
<URow gap="xs" align="end">
|
|
125
|
+
<UIcon name="contact_mail" size="xs" color="primary" />
|
|
126
|
+
<ULink label="Email services" />
|
|
127
|
+
</URow>
|
|
128
|
+
|
|
129
|
+
<URow gap="xs" align="end">
|
|
130
|
+
<UIcon name="vpn_key" size="xs" color="primary" />
|
|
131
|
+
<ULink label="VPN" />
|
|
132
|
+
</URow>
|
|
133
|
+
|
|
134
|
+
<URow gap="xs" align="end">
|
|
135
|
+
<UIcon name="web_traffic" size="xs" color="primary" />
|
|
136
|
+
<ULink label="SEO Tools" />
|
|
137
|
+
</URow>
|
|
138
|
+
</UCol>
|
|
139
|
+
</template>
|
|
140
|
+
`,
|
|
141
|
+
};
|
|
142
|
+
|
|
116
143
|
export const ToggleSlot = DefaultTemplate.bind({});
|
|
117
144
|
ToggleSlot.args = {
|
|
118
145
|
slotTemplate: `
|