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.
Files changed (55) hide show
  1. package/adapter.locale/vue-i18n.ts +3 -2
  2. package/adapter.locale/vueless.ts +2 -23
  3. package/composables/tests/useUI.test.ts +28 -13
  4. package/composables/useComponentLocaleMassages.ts +6 -3
  5. package/composables/useLocale.ts +2 -2
  6. package/constants.js +2 -5
  7. package/directives/tooltip/storybook/docs.mdx +37 -0
  8. package/directives/tooltip/storybook/stories.ts +11 -8
  9. package/directives/tooltip/vTooltip.ts +1 -2
  10. package/icons/storybook/contact_mail.svg +1 -0
  11. package/icons/storybook/vpn_key.svg +1 -0
  12. package/icons/storybook/web_traffic.svg +1 -0
  13. package/index.d.ts +2 -1
  14. package/index.ts +2 -1
  15. package/package.json +2 -3
  16. package/plugin-vite.js +1 -8
  17. package/tailwind.css +25 -0
  18. package/types.ts +21 -1
  19. package/ui.boilerplate/tests/UBoilerplate.test.ts +2 -24
  20. package/ui.container-accordion/UAccordion.vue +15 -2
  21. package/ui.container-accordion/config.ts +1 -0
  22. package/ui.container-accordion/storybook/stories.ts +28 -1
  23. package/ui.container-accordion/tests/UAccordion.test.ts +46 -0
  24. package/ui.data-list/UDataList.vue +2 -0
  25. package/ui.data-table/UTable.vue +19 -13
  26. package/ui.data-table/storybook/stories.ts +11 -0
  27. package/ui.data-table/tests/UTable.test.ts +18 -0
  28. package/ui.dropdown-button/UDropdownButton.vue +1 -0
  29. package/ui.dropdown-button/config.ts +9 -1
  30. package/ui.dropdown-button/storybook/stories.ts +1 -1
  31. package/ui.dropdown-button/tests/UDropdownButton.test.ts +17 -1
  32. package/ui.dropdown-button/types.ts +5 -0
  33. package/ui.form-calendar/UCalendar.vue +9 -7
  34. package/ui.form-input/tests/UInput.test.ts +1 -1
  35. package/ui.form-input-counter/tests/UInputCounter.test.ts +1 -1
  36. package/ui.form-input-file/tests/UInputFile.test.ts +1 -1
  37. package/ui.form-input-password/tests/UInputPassword.test.ts +3 -3
  38. package/ui.form-input-rating/tests/UInputRating.test.ts +2 -2
  39. package/ui.form-input-search/tests/UInputSearch.test.ts +2 -2
  40. package/ui.form-listbox/UListbox.vue +1 -1
  41. package/ui.form-listbox/storybook/stories.ts +5 -5
  42. package/ui.form-select/config.ts +1 -1
  43. package/ui.form-select/storybook/stories.ts +5 -5
  44. package/ui.image-icon/tests/UIcon.test.ts +2 -2
  45. package/ui.navigation-pagination/UPagination.vue +2 -7
  46. package/ui.navigation-pagination/config.ts +1 -0
  47. package/ui.navigation-pagination/tests/UPagination.test.ts +1 -1
  48. package/ui.navigation-pagination/types.ts +1 -1
  49. package/ui.text-notify/tests/UNotify.test.ts +1 -1
  50. package/utils/node/dynamicProps.js +17 -8
  51. package/utils/node/helper.js +11 -1
  52. package/utils/node/storybook.js +52 -0
  53. package/utils/node/vuelessConfig.js +18 -8
  54. package/utils/theme.ts +13 -11
  55. 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 default function createVueI18nAdapter(i18n: I18n) {
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 default function createVuelessAdapter(options?: LocaleOptions): LocaleInstance {
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
- // Return a spy function that can be called and tracked
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 (value && variants[value]) {
22
- classes += ` ${variants[value]}`;
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(locale, () => {
21
- globalComponentMassages.value = recursiveRt(tm(componentName) as VueMessageType);
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,
@@ -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}/.cache/vueless`;
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, UAlert, ULink, UText },
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="{ content: '<b>Tooltip</b>', placement: 'bottom', allowHTML: true }"
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 story demonstrates how to pass custom options to the v-tooltip directive,
64
- including HTML content and tooltip placement. For more settings,
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: "light",
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 { default as createVueI18nAdapter } from "./adapter.locale/vue-i18n.ts";
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 { default as createVueI18nAdapter } from "./adapter.locale/vue-i18n.ts";
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.2",
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.2",
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
- // DataTest prop
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
- // Config prop
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 :id="`description-${elementId}`" v-bind="descriptionAttrs" v-text="description" />
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" />
@@ -24,6 +24,7 @@ export default /*tw*/ {
24
24
  },
25
25
  },
26
26
  },
27
+ content: "pt-3",
27
28
  toggleIcon: {
28
29
  base: "{UIcon} transition duration-300",
29
30
  variants: {
@@ -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: `