vueless 1.2.3-beta.10 → 1.2.3-beta.12
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/constants.d.ts +1 -0
- package/constants.js +1 -0
- package/index.d.ts +1 -0
- package/index.ts +1 -0
- package/package.json +1 -1
- package/types.ts +2 -0
- package/ui.container-accordion/UAccordion.vue +69 -74
- package/ui.container-accordion/config.ts +4 -46
- package/ui.container-accordion/storybook/stories.ts +51 -90
- package/ui.container-accordion/tests/UAccordion.test.ts +44 -239
- package/ui.container-accordion/types.ts +20 -6
- package/ui.container-accordion-item/UAccordionItem.vue +158 -0
- package/ui.container-accordion-item/config.ts +52 -0
- package/ui.container-accordion-item/constants.ts +5 -0
- package/ui.container-accordion-item/storybook/docs.mdx +16 -0
- package/ui.container-accordion-item/storybook/stories.ts +113 -0
- package/ui.container-accordion-item/tests/UAccordionItem.test.ts +296 -0
- package/ui.container-accordion-item/types.ts +56 -0
package/constants.d.ts
CHANGED
package/constants.js
CHANGED
|
@@ -287,6 +287,7 @@ export const COMPONENTS = {
|
|
|
287
287
|
UGroup: "ui.container-group",
|
|
288
288
|
UGroups: "ui.container-groups",
|
|
289
289
|
UAccordion: "ui.container-accordion",
|
|
290
|
+
UAccordionItem: "ui.container-accordion-item",
|
|
290
291
|
UCard: "ui.container-card",
|
|
291
292
|
UModal: "ui.container-modal",
|
|
292
293
|
UModalConfirm: "ui.container-modal-confirm",
|
package/index.d.ts
CHANGED
|
@@ -94,6 +94,7 @@ export { default as URow } from "./ui.container-row/URow.vue";
|
|
|
94
94
|
export { default as UGroup } from "./ui.container-group/UGroup.vue";
|
|
95
95
|
export { default as UGroups } from "./ui.container-groups/UGroups.vue";
|
|
96
96
|
export { default as UAccordion } from "./ui.container-accordion/UAccordion.vue";
|
|
97
|
+
export { default as UAccordionItem } from "./ui.container-accordion-item/UAccordionItem.vue";
|
|
97
98
|
export { default as UCard } from "./ui.container-card/UCard.vue";
|
|
98
99
|
export { default as UModal } from "./ui.container-modal/UModal.vue";
|
|
99
100
|
export { default as UModalConfirm } from "./ui.container-modal-confirm/UModalConfirm.vue";
|
package/index.ts
CHANGED
|
@@ -100,6 +100,7 @@ export { default as URow } from "./ui.container-row/URow.vue";
|
|
|
100
100
|
export { default as UGroup } from "./ui.container-group/UGroup.vue";
|
|
101
101
|
export { default as UGroups } from "./ui.container-groups/UGroups.vue";
|
|
102
102
|
export { default as UAccordion } from "./ui.container-accordion/UAccordion.vue";
|
|
103
|
+
export { default as UAccordionItem } from "./ui.container-accordion-item/UAccordionItem.vue";
|
|
103
104
|
export { default as UCard } from "./ui.container-card/UCard.vue";
|
|
104
105
|
export { default as UModal } from "./ui.container-modal/UModal.vue";
|
|
105
106
|
export { default as UModalConfirm } from "./ui.container-modal-confirm/UModalConfirm.vue";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vueless",
|
|
3
|
-
"version": "1.2.3-beta.
|
|
3
|
+
"version": "1.2.3-beta.12",
|
|
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",
|
package/types.ts
CHANGED
|
@@ -20,6 +20,7 @@ import UDropdownBadgeConfig from "./ui.dropdown-badge/config";
|
|
|
20
20
|
import UDropdownButtonConfig from "./ui.dropdown-button/config";
|
|
21
21
|
import UDropdownLinkConfig from "./ui.dropdown-link/config";
|
|
22
22
|
import UAccordionConfig from "./ui.container-accordion/config";
|
|
23
|
+
import UAccordionItemConfig from "./ui.container-accordion-item/config";
|
|
23
24
|
import UCardConfig from "./ui.container-card/config";
|
|
24
25
|
import UColConfig from "./ui.container-col/config";
|
|
25
26
|
import UDividerConfig from "./ui.container-divider/config";
|
|
@@ -252,6 +253,7 @@ export interface Components {
|
|
|
252
253
|
UDropdownLink: Partial<typeof UDropdownLinkConfig>;
|
|
253
254
|
UListbox: Partial<typeof UListboxConfig>;
|
|
254
255
|
UAccordion: Partial<typeof UAccordionConfig>;
|
|
256
|
+
UAccordionItem: Partial<typeof UAccordionItemConfig>;
|
|
255
257
|
UCard: Partial<typeof UCardConfig>;
|
|
256
258
|
UCol: Partial<typeof UColConfig>;
|
|
257
259
|
UDivider: Partial<typeof UDividerConfig>;
|
|
@@ -1,119 +1,114 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed,
|
|
2
|
+
import { computed, provide, useTemplateRef, ref, watch } from "vue";
|
|
3
3
|
|
|
4
4
|
import useUI from "../composables/useUI";
|
|
5
5
|
import { getDefaults } from "../utils/ui";
|
|
6
|
-
import { hasSlotContent } from "../utils/helper";
|
|
7
6
|
|
|
8
|
-
import
|
|
9
|
-
import UDivider from "../ui.container-divider/UDivider.vue";
|
|
7
|
+
import UAccordionItem from "../ui.container-accordion-item/UAccordionItem.vue";
|
|
10
8
|
|
|
11
9
|
import { COMPONENT_NAME } from "./constants";
|
|
12
10
|
import defaultConfig from "./config";
|
|
13
11
|
|
|
14
|
-
import type { Props, Config } from "./types";
|
|
12
|
+
import type { Props, Config, SetAccordionSelectedItem } from "./types";
|
|
15
13
|
|
|
16
14
|
defineOptions({ inheritAttrs: false });
|
|
17
15
|
|
|
18
16
|
const props = withDefaults(defineProps<Props>(), {
|
|
19
17
|
...getDefaults<Props, Config>(defaultConfig, COMPONENT_NAME),
|
|
18
|
+
modelValue: undefined,
|
|
19
|
+
options: () => [],
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
const emit = defineEmits([
|
|
23
23
|
/**
|
|
24
|
-
* Triggers when the
|
|
25
|
-
* @property {string}
|
|
26
|
-
* @property {boolean} isOpened
|
|
24
|
+
* Triggers when the value attribute changes.
|
|
25
|
+
* @property {string} value
|
|
27
26
|
*/
|
|
28
|
-
"
|
|
27
|
+
"update:modelValue",
|
|
29
28
|
]);
|
|
30
29
|
|
|
31
|
-
const
|
|
32
|
-
const contentRef = useTemplateRef<HTMLDivElement>("content");
|
|
30
|
+
const accordionRef = useTemplateRef<HTMLDivElement>("accordion");
|
|
33
31
|
|
|
34
|
-
const
|
|
32
|
+
const internalValue = ref<string | string[] | null>(props.multiple ? [] : null);
|
|
35
33
|
|
|
36
|
-
const
|
|
37
|
-
const elementId = props.id || useId();
|
|
34
|
+
const isControlled = computed(() => props.modelValue !== undefined);
|
|
38
35
|
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
36
|
+
const selectedItem = computed({
|
|
37
|
+
get: () => (isControlled.value ? props.modelValue! : internalValue.value),
|
|
38
|
+
set: (value) => {
|
|
39
|
+
if (!isControlled.value) internalValue.value = value;
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
emit("update:modelValue", value);
|
|
42
|
+
},
|
|
45
43
|
});
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
if (
|
|
45
|
+
provide<SetAccordionSelectedItem>("setAccordionSelectedItem", (value, opened) => {
|
|
46
|
+
if (props.multiple) {
|
|
47
|
+
let current: string[] = [];
|
|
48
|
+
|
|
49
|
+
if (selectedItem.value) {
|
|
50
|
+
current = Array.isArray(selectedItem.value) ? [...selectedItem.value] : [selectedItem.value];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (opened && !current.includes(value)) {
|
|
54
|
+
current.push(value);
|
|
55
|
+
} else {
|
|
56
|
+
const index = current.indexOf(value);
|
|
57
|
+
|
|
58
|
+
if (index !== -1) {
|
|
59
|
+
current.splice(index, 1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
selectedItem.value = current;
|
|
64
|
+
|
|
49
65
|
return;
|
|
50
66
|
}
|
|
51
67
|
|
|
52
|
-
|
|
68
|
+
selectedItem.value = opened ? value : null;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
provide("getAccordionSelectedItem", () => selectedItem.value ?? null);
|
|
72
|
+
provide("getAccordionSize", () => props.size);
|
|
73
|
+
provide("getAccordionDisabled", () => props.disabled);
|
|
53
74
|
|
|
54
|
-
|
|
55
|
-
|
|
75
|
+
watch(
|
|
76
|
+
() => props.multiple,
|
|
77
|
+
(isMultiple) => {
|
|
78
|
+
if (!isControlled.value) {
|
|
79
|
+
internalValue.value = isMultiple ? [] : null;
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
);
|
|
56
83
|
|
|
57
84
|
defineExpose({
|
|
58
85
|
/**
|
|
59
86
|
* A reference to the component's wrapper element for direct DOM manipulation.
|
|
60
87
|
* @property {HTMLDivElement}
|
|
61
88
|
*/
|
|
62
|
-
|
|
89
|
+
accordionRef,
|
|
63
90
|
});
|
|
64
91
|
|
|
65
|
-
const
|
|
66
|
-
/* component state, not a props */
|
|
67
|
-
opened: isOpened.value,
|
|
68
|
-
}));
|
|
69
|
-
|
|
70
|
-
const {
|
|
71
|
-
getDataTest,
|
|
72
|
-
config,
|
|
73
|
-
wrapperAttrs,
|
|
74
|
-
descriptionAttrs,
|
|
75
|
-
bodyAttrs,
|
|
76
|
-
titleAttrs,
|
|
77
|
-
contentAttrs,
|
|
78
|
-
toggleIconAttrs,
|
|
79
|
-
accordionDividerAttrs,
|
|
80
|
-
} = useUI<Config>(defaultConfig, mutatedProps);
|
|
92
|
+
const { getDataTest, accordionItemAttrs, accordionAttrs } = useUI<Config>(defaultConfig);
|
|
81
93
|
</script>
|
|
82
94
|
|
|
83
95
|
<template>
|
|
84
|
-
<div ref="
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
v-bind="toggleIconAttrs"
|
|
100
|
-
/>
|
|
101
|
-
</slot>
|
|
102
|
-
</div>
|
|
103
|
-
|
|
104
|
-
<div
|
|
105
|
-
v-if="description"
|
|
106
|
-
:id="`description-${elementId}`"
|
|
107
|
-
v-bind="descriptionAttrs"
|
|
108
|
-
v-text="description"
|
|
96
|
+
<div ref="accordion" v-bind="accordionAttrs" :data-test="getDataTest()">
|
|
97
|
+
<!-- @slot Use it to add UAccordionItem directly. -->
|
|
98
|
+
<slot>
|
|
99
|
+
<UAccordionItem
|
|
100
|
+
v-for="(option, index) in options"
|
|
101
|
+
:key="index"
|
|
102
|
+
:model-value="selectedItem"
|
|
103
|
+
:value="option.value"
|
|
104
|
+
:opened="option.opened"
|
|
105
|
+
:title="option.title"
|
|
106
|
+
:description="option.description"
|
|
107
|
+
:size="size"
|
|
108
|
+
:disabled="disabled"
|
|
109
|
+
v-bind="accordionItemAttrs"
|
|
110
|
+
:data-test="getDataTest(`item-${index}`)"
|
|
109
111
|
/>
|
|
110
|
-
|
|
111
|
-
<div v-if="isOpened && hasSlotContent(slots['default'])" ref="content" v-bind="contentAttrs">
|
|
112
|
-
<!-- @slot Use it to add accordion content. -->
|
|
113
|
-
<slot />
|
|
114
|
-
</div>
|
|
115
|
-
</div>
|
|
116
|
-
|
|
117
|
-
<UDivider v-bind="accordionDividerAttrs" />
|
|
112
|
+
</slot>
|
|
118
113
|
</div>
|
|
119
114
|
</template>
|
|
@@ -1,51 +1,9 @@
|
|
|
1
1
|
export default /*tw*/ {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
title: {
|
|
5
|
-
base: "flex items-center justify-between font-medium",
|
|
6
|
-
variants: {
|
|
7
|
-
size: {
|
|
8
|
-
sm: "text-small",
|
|
9
|
-
md: "text-medium",
|
|
10
|
-
lg: "text-large",
|
|
11
|
-
},
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
description: {
|
|
15
|
-
base: "text-accented h-0 opacity-0 transition-all",
|
|
16
|
-
variants: {
|
|
17
|
-
size: {
|
|
18
|
-
sm: "text-tiny",
|
|
19
|
-
md: "text-small",
|
|
20
|
-
lg: "text-medium",
|
|
21
|
-
},
|
|
22
|
-
opened: {
|
|
23
|
-
true: "pt-2 h-fit opacity-100",
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
content: "pt-3 cursor-default",
|
|
28
|
-
toggleIcon: {
|
|
29
|
-
base: "{UIcon} transition duration-300",
|
|
30
|
-
variants: {
|
|
31
|
-
opened: {
|
|
32
|
-
true: "group-[*]:rotate-180",
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
accordionDivider: {
|
|
37
|
-
base: "{UDivider} group-last:hidden",
|
|
38
|
-
variants: {
|
|
39
|
-
size: {
|
|
40
|
-
sm: "py-4",
|
|
41
|
-
md: "py-5",
|
|
42
|
-
lg: "py-6",
|
|
43
|
-
},
|
|
44
|
-
},
|
|
45
|
-
},
|
|
2
|
+
accordion: "flex flex-col w-full divide-y divide-muted",
|
|
3
|
+
accordionItem: "{UAccordionItem} py-5 first:pt-0 last:pb-0",
|
|
46
4
|
defaults: {
|
|
47
5
|
size: "md",
|
|
48
|
-
|
|
49
|
-
|
|
6
|
+
disabled: false,
|
|
7
|
+
multiple: false,
|
|
50
8
|
},
|
|
51
9
|
};
|
|
@@ -20,18 +20,41 @@ import type { Props } from "../types";
|
|
|
20
20
|
interface UAccordionArgs extends Props {
|
|
21
21
|
slotTemplate?: string;
|
|
22
22
|
enum: "size";
|
|
23
|
+
class?: string;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export default {
|
|
26
|
-
id: "
|
|
27
|
+
id: "5040",
|
|
27
28
|
title: "Containers / Accordion",
|
|
28
29
|
component: UAccordion,
|
|
29
30
|
args: {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
modelValue: "2",
|
|
32
|
+
options: [
|
|
33
|
+
{
|
|
34
|
+
value: "1",
|
|
35
|
+
title: "Committed to Quality and Performance",
|
|
36
|
+
description:
|
|
37
|
+
trimText(`We take pride in delivering high-quality solutions tailored to your needs.
|
|
38
|
+
Our expertise ensures that your project is built with efficiency, scalability, and reliability in mind.
|
|
39
|
+
`),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
value: "2",
|
|
43
|
+
title: "Pioneering Cutting-Edge Solutions",
|
|
44
|
+
description:
|
|
45
|
+
trimText(`Our team stays ahead of the curve, integrating the latest technologies
|
|
46
|
+
and best practices to drive innovation and create future-ready applications for your business.
|
|
47
|
+
`),
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
value: "3",
|
|
51
|
+
title: "Building Together for Long-Term Success",
|
|
52
|
+
description:
|
|
53
|
+
trimText(`We work closely with you to understand your goals, ensuring seamless communication
|
|
54
|
+
and a collaborative approach that leads to sustainable, impactful results.
|
|
55
|
+
`),
|
|
56
|
+
},
|
|
57
|
+
],
|
|
35
58
|
},
|
|
36
59
|
argTypes: {
|
|
37
60
|
...getArgTypes(UAccordion.__name),
|
|
@@ -47,104 +70,42 @@ const DefaultTemplate: StoryFn<UAccordionArgs> = (args: UAccordionArgs) => ({
|
|
|
47
70
|
components: { UAccordion, ULink, UButton, UCol, URow, UIcon },
|
|
48
71
|
setup: () => ({ args, slots: getSlotNames(UAccordion.__name) }),
|
|
49
72
|
template: `
|
|
50
|
-
<UAccordion v-bind="args">
|
|
51
|
-
${args.slotTemplate || getSlotsFragment("")}
|
|
52
|
-
</UAccordion>
|
|
53
|
-
`,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
const AccordionsTemplate: StoryFn<UAccordionArgs> = (args: UAccordionArgs) => ({
|
|
57
|
-
components: { UAccordion, UButton },
|
|
58
|
-
setup() {
|
|
59
|
-
const slots = getSlotNames(UAccordion.__name);
|
|
60
|
-
|
|
61
|
-
const accordions = [
|
|
62
|
-
{
|
|
63
|
-
title: "Committed to Quality and Performance",
|
|
64
|
-
description: `
|
|
65
|
-
We take pride in delivering high-quality solutions tailored to your needs.
|
|
66
|
-
Our expertise ensures that your project is built with efficiency, scalability, and reliability in mind.
|
|
67
|
-
`,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
title: "Pioneering Cutting-Edge Solutions",
|
|
71
|
-
description: `
|
|
72
|
-
Our team stays ahead of the curve, integrating the latest technologies and best practices
|
|
73
|
-
to drive innovation and create future-ready applications for your business.
|
|
74
|
-
`,
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
title: "Building Together for Long-Term Success",
|
|
78
|
-
description: `
|
|
79
|
-
We work closely with you to understand your goals, ensuring seamless communication
|
|
80
|
-
and a collaborative approach that leads to sustainable, impactful results.
|
|
81
|
-
`,
|
|
82
|
-
},
|
|
83
|
-
];
|
|
84
|
-
|
|
85
|
-
return { args, slots, accordions };
|
|
86
|
-
},
|
|
87
|
-
template: `
|
|
88
|
-
<UAccordion
|
|
89
|
-
v-for="(accordion, index) in accordions"
|
|
90
|
-
:key="index"
|
|
91
|
-
v-bind="accordion"
|
|
92
|
-
>
|
|
73
|
+
<UAccordion v-bind="args" v-model="args.modelValue">
|
|
93
74
|
${args.slotTemplate || getSlotsFragment("")}
|
|
94
75
|
</UAccordion>
|
|
95
76
|
`,
|
|
96
77
|
});
|
|
97
78
|
|
|
98
79
|
const EnumTemplate: StoryFn<UAccordionArgs> = (args: UAccordionArgs, { argTypes }) => ({
|
|
99
|
-
components: { UAccordion },
|
|
80
|
+
components: { UAccordion, UCol },
|
|
100
81
|
setup: () => ({ args, argTypes, getArgs }),
|
|
101
82
|
template: `
|
|
102
|
-
<
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
83
|
+
<UCol gap="xl" block>
|
|
84
|
+
<UAccordion
|
|
85
|
+
v-for="option in argTypes?.[args.enum]?.options"
|
|
86
|
+
v-bind="getArgs(args, option)"
|
|
87
|
+
v-model="args.modelValue"
|
|
88
|
+
:key="option"
|
|
89
|
+
/>
|
|
90
|
+
</UCol>
|
|
107
91
|
`,
|
|
108
92
|
});
|
|
109
93
|
|
|
110
94
|
export const Default = DefaultTemplate.bind({});
|
|
111
95
|
Default.args = {};
|
|
112
96
|
|
|
113
|
-
export const
|
|
114
|
-
|
|
97
|
+
export const Disabled = DefaultTemplate.bind({});
|
|
98
|
+
Disabled.args = { disabled: true };
|
|
115
99
|
|
|
116
100
|
export const Sizes = EnumTemplate.bind({});
|
|
117
|
-
Sizes.args = {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
143
|
-
export const ToggleSlot = DefaultTemplate.bind({});
|
|
144
|
-
ToggleSlot.args = {
|
|
145
|
-
slotTemplate: `
|
|
146
|
-
<template #toggle="{ opened }">
|
|
147
|
-
<ULink :label="opened ? 'Collapse' : 'Expand'" color="grayscale" />
|
|
148
|
-
</template>
|
|
149
|
-
`,
|
|
101
|
+
Sizes.args = {
|
|
102
|
+
enum: "size",
|
|
103
|
+
class: "w-full",
|
|
104
|
+
options: [
|
|
105
|
+
{
|
|
106
|
+
value: "1",
|
|
107
|
+
title: "Committed to Quality and Performance",
|
|
108
|
+
description: "{enumValue}",
|
|
109
|
+
},
|
|
110
|
+
],
|
|
150
111
|
};
|