edvoyui-component-library-test-flight 0.0.106 → 0.0.108
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/dist/alerts/EUIAlerts.vue.d.ts +4 -0
- package/dist/alerts/EUIAlerts.vue.d.ts.map +1 -0
- package/dist/library-vue-ts.cjs.js +28 -28
- package/dist/library-vue-ts.css +1 -1
- package/dist/library-vue-ts.es.js +4976 -4722
- package/dist/library-vue-ts.umd.js +24 -24
- package/dist/modal/EUIModal.vue.d.ts +1 -1
- package/dist/modal/EUIModal.vue.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/HelloWorld.vue +293 -167
- package/src/components/alerts/EUIAlerts.stories.ts +217 -0
- package/src/components/alerts/EUIAlerts.vue +194 -0
- package/src/components/dropdown/EUIMultiDropdown.vue +74 -39
- package/src/components/index.ts +1 -0
- package/src/components/modal/EUIModal.stories.ts +20 -0
- package/src/components/modal/EUIModal.vue +36 -8
- package/src/components/slideover/EUISlideover.stories.ts +1 -1
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/vue3";
|
|
2
|
+
import EUIAlerts from "./EUIAlerts.vue"; // Adjust the path if necessary
|
|
3
|
+
import { CalendarDaysIcon } from "@heroicons/vue/24/outline";
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: "Components/Alerts",
|
|
7
|
+
component: EUIAlerts,
|
|
8
|
+
tags: ["autodocs"],
|
|
9
|
+
argTypes: {
|
|
10
|
+
...{
|
|
11
|
+
showAlert: {
|
|
12
|
+
control: "boolean",
|
|
13
|
+
description: "Controls the visibility of the alert.",
|
|
14
|
+
defaultValue: true,
|
|
15
|
+
},
|
|
16
|
+
alertType: {
|
|
17
|
+
control: {
|
|
18
|
+
type: "select",
|
|
19
|
+
options: ["Default", "Warning", "Success", "Error"],
|
|
20
|
+
},
|
|
21
|
+
description:
|
|
22
|
+
'Determines the style and icon of the alert. Options are "Default", "Warning", "Success", and "Error".',
|
|
23
|
+
},
|
|
24
|
+
heading: {
|
|
25
|
+
control: "text",
|
|
26
|
+
description: "The title text displayed in the alert header.",
|
|
27
|
+
},
|
|
28
|
+
textMessage: {
|
|
29
|
+
control: "text",
|
|
30
|
+
description:
|
|
31
|
+
"Additional information about the alert. This text appears below the title.",
|
|
32
|
+
},
|
|
33
|
+
alertIcon: {
|
|
34
|
+
control: "text",
|
|
35
|
+
description:
|
|
36
|
+
"An optional custom icon to display. This can be a Vue component, a string, or a function.",
|
|
37
|
+
},
|
|
38
|
+
closeIcon: {
|
|
39
|
+
control: "boolean",
|
|
40
|
+
description:
|
|
41
|
+
"If set to true, shows a close icon to allow dismissing the alert.",
|
|
42
|
+
},
|
|
43
|
+
actionItems: {
|
|
44
|
+
control: "boolean",
|
|
45
|
+
description:
|
|
46
|
+
'If set to true, displays action buttons (e.g., "View status" and "Dismiss") within the alert.',
|
|
47
|
+
},
|
|
48
|
+
"update:showAlert": {
|
|
49
|
+
action: "update:showAlert",
|
|
50
|
+
description: "Emitted to update the visibility of the alert.",
|
|
51
|
+
},
|
|
52
|
+
alertAction: {
|
|
53
|
+
action: "alertAction",
|
|
54
|
+
description: "Emitted when the action button is clicked.",
|
|
55
|
+
},
|
|
56
|
+
alertDismiss: {
|
|
57
|
+
action: "alertDismiss",
|
|
58
|
+
description: "Emitted when the alert is dismissed.",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
parameters: {
|
|
63
|
+
docs: {
|
|
64
|
+
description: {
|
|
65
|
+
component:
|
|
66
|
+
"An alert component that displays messages with various styles (Default, Warning, Success, Error). It supports custom titles, descriptions, icons, and optional action buttons.",
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
} satisfies Meta<typeof EUIAlerts>;
|
|
71
|
+
|
|
72
|
+
export default meta;
|
|
73
|
+
type Story = StoryObj<typeof meta>;
|
|
74
|
+
|
|
75
|
+
// Default button story with default slot content
|
|
76
|
+
export const Default: Story = {
|
|
77
|
+
argTypes: {
|
|
78
|
+
alertType: {
|
|
79
|
+
control: "select",
|
|
80
|
+
options: ["Default", "Warning", "Success", "Error"],
|
|
81
|
+
},
|
|
82
|
+
alertIcon: {
|
|
83
|
+
control: "text",
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
args: {
|
|
87
|
+
alertType: "Default",
|
|
88
|
+
showAlert: true,
|
|
89
|
+
heading: "Default Alert",
|
|
90
|
+
textMessage: "This is a default alert message.",
|
|
91
|
+
},
|
|
92
|
+
render: (args) => ({
|
|
93
|
+
components: { EUIAlerts },
|
|
94
|
+
setup() {
|
|
95
|
+
return { args };
|
|
96
|
+
},
|
|
97
|
+
template: `<EUIAlerts v-bind="args"></EUIAlerts>`,
|
|
98
|
+
}),
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export const onlyTitle: Story = {
|
|
102
|
+
args: {
|
|
103
|
+
alertType: "Success",
|
|
104
|
+
heading: "Your account activated",
|
|
105
|
+
},
|
|
106
|
+
render: (args) => ({
|
|
107
|
+
components: { EUIAlerts },
|
|
108
|
+
setup() {
|
|
109
|
+
return { args };
|
|
110
|
+
},
|
|
111
|
+
template: `<EUIAlerts v-bind="args"></EUIAlerts>`,
|
|
112
|
+
}),
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
export const UseCustomIcon: Story = {
|
|
116
|
+
args: {
|
|
117
|
+
alertType: "Success",
|
|
118
|
+
heading: "Send Icon here",
|
|
119
|
+
alertIcon: CalendarDaysIcon,
|
|
120
|
+
},
|
|
121
|
+
render: (args) => ({
|
|
122
|
+
components: { EUIAlerts, CalendarDaysIcon },
|
|
123
|
+
setup() {
|
|
124
|
+
return { args };
|
|
125
|
+
},
|
|
126
|
+
template: `<EUIAlerts v-bind="args"></EUIAlerts>`,
|
|
127
|
+
}),
|
|
128
|
+
parameters: {
|
|
129
|
+
docs: {
|
|
130
|
+
source: {
|
|
131
|
+
code: `<template>
|
|
132
|
+
<EUIAlerts
|
|
133
|
+
alertType="Success"
|
|
134
|
+
heading="Send Icon here"
|
|
135
|
+
:alertIcon="CalendarDaysIcon"
|
|
136
|
+
>
|
|
137
|
+
</EUIAlerts>
|
|
138
|
+
</template>`,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const EnableClose: Story = {
|
|
145
|
+
args: {
|
|
146
|
+
alertType: "Default",
|
|
147
|
+
heading: "Close Icon Boolean enabled",
|
|
148
|
+
closeIcon: true,
|
|
149
|
+
},
|
|
150
|
+
render: (args) => ({
|
|
151
|
+
components: { EUIAlerts },
|
|
152
|
+
setup() {
|
|
153
|
+
return { args };
|
|
154
|
+
},
|
|
155
|
+
template: `<EUIAlerts v-bind="args"></EUIAlerts>`,
|
|
156
|
+
}),
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export const UseSlots: Story = {
|
|
160
|
+
args: {
|
|
161
|
+
alertType: "Warning",
|
|
162
|
+
alertIcon: CalendarDaysIcon,
|
|
163
|
+
},
|
|
164
|
+
render: (args) => ({
|
|
165
|
+
components: { EUIAlerts },
|
|
166
|
+
setup() {
|
|
167
|
+
return { args };
|
|
168
|
+
},
|
|
169
|
+
template: `<EUIAlerts v-bind="args">
|
|
170
|
+
<template #title> Custom Header here</template>
|
|
171
|
+
<template #content><p class="text-sm font-normal"> Custom message here Are you sure you want to deactivate your account?.</p></template>
|
|
172
|
+
<template #actionButtons>
|
|
173
|
+
<div class="mt-4">
|
|
174
|
+
<button type="button"
|
|
175
|
+
class="rounded-md px-3 py-1.5 text-sm font-medium bg-black text-white focus:outline-none focus:ring-2 focus:ring-offset-2"
|
|
176
|
+
>
|
|
177
|
+
View status
|
|
178
|
+
</button>
|
|
179
|
+
<button
|
|
180
|
+
type="button"
|
|
181
|
+
class="ml-3 rounded-md px-3 py-1.5 bg-white text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2"
|
|
182
|
+
>
|
|
183
|
+
Dismiss
|
|
184
|
+
</button>
|
|
185
|
+
</div>
|
|
186
|
+
</template>
|
|
187
|
+
</EUIAlerts>`,
|
|
188
|
+
}),
|
|
189
|
+
parameters: {
|
|
190
|
+
docs: {
|
|
191
|
+
source: {
|
|
192
|
+
code: `<template>
|
|
193
|
+
<EUIAlerts>
|
|
194
|
+
<template #icon> <CalendarDaysIcon class="text-current size-5" aria-hidden="true" /></template>
|
|
195
|
+
<template #title> Custom Header here</template>
|
|
196
|
+
<template #content><p class="text-sm font-normal"> Custom message here Are you sure you want to deactivate your account?.</p></template>
|
|
197
|
+
<template #actionButtons>
|
|
198
|
+
<div>
|
|
199
|
+
<button type="button"
|
|
200
|
+
class="rounded-md px-3 py-1.5 text-sm font-medium bg-black text-white focus:outline-none focus:ring-2 focus:ring-offset-2"
|
|
201
|
+
>
|
|
202
|
+
View status
|
|
203
|
+
</button>
|
|
204
|
+
<button
|
|
205
|
+
type="button"
|
|
206
|
+
class="ml-3 rounded-md px-3 py-1.5 bg-white text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2"
|
|
207
|
+
>
|
|
208
|
+
Dismiss
|
|
209
|
+
</button>
|
|
210
|
+
</div>
|
|
211
|
+
</template>
|
|
212
|
+
</EUIAlerts>
|
|
213
|
+
</template>`,
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
};
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<transition
|
|
3
|
+
enter-active-class="transition duration-300 ease-out transform"
|
|
4
|
+
enter-from-class="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
|
|
5
|
+
enter-to-class="translate-y-0 opacity-100 sm:translate-x-0"
|
|
6
|
+
leave-active-class="transition duration-100 ease-in"
|
|
7
|
+
leave-from-class="opacity-100"
|
|
8
|
+
leave-to-class="opacity-0"
|
|
9
|
+
>
|
|
10
|
+
<div v-if="showAlert" :class="['p-4 rounded-md', alertsClass.bgColor]">
|
|
11
|
+
<div
|
|
12
|
+
:class="[closeIcon && !textMessage ? 'items-center pr-2 flex' : 'flex']"
|
|
13
|
+
>
|
|
14
|
+
<div class="shrink-0">
|
|
15
|
+
<slot name="icon">
|
|
16
|
+
<component
|
|
17
|
+
:is="alertIcon || alertsClass.leftIcon?.icon"
|
|
18
|
+
:class="['size-5', alertsClass.leftIcon?.color]"
|
|
19
|
+
aria-hidden="true"
|
|
20
|
+
/>
|
|
21
|
+
</slot>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="ml-3">
|
|
24
|
+
<h3 :class="['text-sm font-medium', alertsClass.titleColor]">
|
|
25
|
+
<slot name="title">{{ heading || "Alert Title" }}</slot>
|
|
26
|
+
</h3>
|
|
27
|
+
|
|
28
|
+
<slot name="content">
|
|
29
|
+
<div v-if="textMessage" :class="['mt-2 text-sm', alertsClass.textColor]">
|
|
30
|
+
{{ textMessage || "your description here..." }}
|
|
31
|
+
</div>
|
|
32
|
+
</slot>
|
|
33
|
+
|
|
34
|
+
<slot name="actionButtons">
|
|
35
|
+
<div v-if="actionItems" class="mt-4">
|
|
36
|
+
<div class="-mx-2 -my-1.5 flex">
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
:class="[
|
|
40
|
+
'rounded-md px-3 py-1.5 text-sm font-medium text-white focus:outline-none focus:ring-2 focus:ring-offset-2',
|
|
41
|
+
alertsClass.btnPrimary,
|
|
42
|
+
]"
|
|
43
|
+
@click="onAction"
|
|
44
|
+
>
|
|
45
|
+
View status
|
|
46
|
+
</button>
|
|
47
|
+
<button
|
|
48
|
+
type="button"
|
|
49
|
+
:class="[
|
|
50
|
+
'ml-3 rounded-md px-3 py-1.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2',
|
|
51
|
+
alertsClass.btnTertiary,
|
|
52
|
+
]"
|
|
53
|
+
@click="onClose"
|
|
54
|
+
>
|
|
55
|
+
Dismiss
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</slot>
|
|
60
|
+
</div>
|
|
61
|
+
<div class="pl-3 ml-auto">
|
|
62
|
+
<slot name="xclose">
|
|
63
|
+
<div v-if="closeIcon" class="-mx-1.5 -my-1.5 pt-1">
|
|
64
|
+
<button
|
|
65
|
+
type="button"
|
|
66
|
+
:class="[
|
|
67
|
+
'inline-flex rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2',
|
|
68
|
+
alertsClass.btnClose,
|
|
69
|
+
]"
|
|
70
|
+
@click="onClose()"
|
|
71
|
+
>
|
|
72
|
+
<span class="sr-only">Dismiss</span>
|
|
73
|
+
<XMarkIcon class="size-5" aria-hidden="true" />
|
|
74
|
+
</button>
|
|
75
|
+
</div>
|
|
76
|
+
</slot>
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</transition>
|
|
81
|
+
</template>
|
|
82
|
+
|
|
83
|
+
<script setup lang="ts">
|
|
84
|
+
import { computed, toRefs, type PropType } from "vue";
|
|
85
|
+
import {
|
|
86
|
+
ExclamationTriangleIcon,
|
|
87
|
+
CheckCircleIcon,
|
|
88
|
+
XCircleIcon,
|
|
89
|
+
XMarkIcon,
|
|
90
|
+
} from "@heroicons/vue/24/solid";
|
|
91
|
+
|
|
92
|
+
const props = defineProps({
|
|
93
|
+
showAlert: {
|
|
94
|
+
type: Boolean,
|
|
95
|
+
default: true,
|
|
96
|
+
},
|
|
97
|
+
heading: {
|
|
98
|
+
type: String,
|
|
99
|
+
default: "",
|
|
100
|
+
},
|
|
101
|
+
textMessage: {
|
|
102
|
+
type: String,
|
|
103
|
+
default: "",
|
|
104
|
+
},
|
|
105
|
+
alertType: {
|
|
106
|
+
type: String as PropType<"Default" | "Warning" | "Success" | "Error">,
|
|
107
|
+
default: "Default",
|
|
108
|
+
},
|
|
109
|
+
alertIcon: {
|
|
110
|
+
type: [String, Object, Function],
|
|
111
|
+
default: "",
|
|
112
|
+
},
|
|
113
|
+
actionItems: Boolean,
|
|
114
|
+
closeIcon: Boolean,
|
|
115
|
+
});
|
|
116
|
+
const { showAlert } = toRefs(props);
|
|
117
|
+
const emits = defineEmits(["update:showAlert", "alertAction", "alertDismiss"]);
|
|
118
|
+
const onAction = () => {
|
|
119
|
+
emits("alertAction", true);
|
|
120
|
+
emits("update:showAlert", false);
|
|
121
|
+
};
|
|
122
|
+
const onClose = () => {
|
|
123
|
+
emits("alertDismiss", false);
|
|
124
|
+
emits("update:showAlert", false);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const alertsClass = computed(() => {
|
|
128
|
+
const iconClasses = {
|
|
129
|
+
Default: {
|
|
130
|
+
bgColor: "bg-blue-50",
|
|
131
|
+
leftIcon: {
|
|
132
|
+
icon: CheckCircleIcon,
|
|
133
|
+
color: "text-blue-400",
|
|
134
|
+
},
|
|
135
|
+
titleColor: "text-blue-800",
|
|
136
|
+
textColor: "text-blue-700",
|
|
137
|
+
btnPrimary:
|
|
138
|
+
"bg-blue-700 hover:bg-blue-800 focus:ring-blue-600 focus:ring-offset-blue-50",
|
|
139
|
+
btnTertiary:
|
|
140
|
+
"text-blue-500 bg-blue-50 hover:bg-blue-100 focus:ring-blue-600 focus:ring-offset-blue-50",
|
|
141
|
+
btnClose:
|
|
142
|
+
"bg-blue-50 text-blue-500 hover:bg-blue-100 focus:ring-blue-600 focus:ring-offset-blue-50",
|
|
143
|
+
},
|
|
144
|
+
Warning: {
|
|
145
|
+
bgColor: "bg-yellow-50",
|
|
146
|
+
leftIcon: {
|
|
147
|
+
icon: ExclamationTriangleIcon,
|
|
148
|
+
color: "text-yellow-400",
|
|
149
|
+
},
|
|
150
|
+
titleColor: "text-yellow-800",
|
|
151
|
+
textColor: "text-yellow-700",
|
|
152
|
+
btnPrimary:
|
|
153
|
+
"bg-yellow-700 hover:bg-yellow-800 focus:ring-yellow-600 focus:ring-offset-yellow-50",
|
|
154
|
+
btnTertiary:
|
|
155
|
+
"text-yellow-500 bg-yellow-50 hover:bg-yellow-100 focus:ring-yellow-600 focus:ring-offset-yellow-50",
|
|
156
|
+
btnClose:
|
|
157
|
+
"bg-yellow-50 text-yellow-500 hover:bg-yellow-100 focus:ring-yellow-600 focus:ring-offset-yellow-50",
|
|
158
|
+
},
|
|
159
|
+
Success: {
|
|
160
|
+
bgColor: "bg-green-50",
|
|
161
|
+
leftIcon: {
|
|
162
|
+
icon: CheckCircleIcon,
|
|
163
|
+
color: "text-green-400",
|
|
164
|
+
},
|
|
165
|
+
titleColor: "text-green-800",
|
|
166
|
+
textColor: "text-green-700",
|
|
167
|
+
btnPrimary:
|
|
168
|
+
"bg-green-700 hover:bg-green-800 focus:ring-green-600 focus:ring-offset-green-50",
|
|
169
|
+
btnTertiary:
|
|
170
|
+
"text-green-500 bg-green-50 hover:bg-green-100 focus:ring-green-600 focus:ring-offset-green-50",
|
|
171
|
+
btnClose:
|
|
172
|
+
"bg-green-50 text-green-500 hover:bg-green-100 focus:ring-green-600 focus:ring-offset-green-50",
|
|
173
|
+
},
|
|
174
|
+
Error: {
|
|
175
|
+
bgColor: "bg-red-50",
|
|
176
|
+
leftIcon: {
|
|
177
|
+
icon: XCircleIcon,
|
|
178
|
+
color: "text-red-400",
|
|
179
|
+
},
|
|
180
|
+
titleColor: "text-red-800",
|
|
181
|
+
textColor: "text-red-700",
|
|
182
|
+
btnPrimary:
|
|
183
|
+
"bg-red-700 hover:bg-red-800 focus:ring-red-600 focus:ring-offset-red-50",
|
|
184
|
+
btnTertiary:
|
|
185
|
+
"text-red-500 bg-red-50 hover:bg-red-100 focus:ring-red-600 focus:ring-offset-red-50",
|
|
186
|
+
btnClose:
|
|
187
|
+
"bg-red-50 text-red-500 hover:bg-red-100 focus:ring-red-600 focus:ring-offset-red-50",
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
return iconClasses[props.alertType] || "";
|
|
191
|
+
});
|
|
192
|
+
</script>
|
|
193
|
+
|
|
194
|
+
<style scoped></style>
|
|
@@ -4,20 +4,32 @@
|
|
|
4
4
|
<button
|
|
5
5
|
type="button"
|
|
6
6
|
ref="dropdownButton"
|
|
7
|
-
:class="[
|
|
7
|
+
:class="[
|
|
8
|
+
'inline-flex items-center text-sm font-semibold gap-x-2 capitalize outline-none focus:outline-none',
|
|
9
|
+
className,
|
|
10
|
+
]"
|
|
8
11
|
:disabled="disabled"
|
|
9
12
|
@click="toggleDropdown()"
|
|
10
13
|
>
|
|
11
14
|
<slot name="dropdownName" :open="isOpen">
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
{{ title }}
|
|
16
|
+
<ChevronDownStroke
|
|
17
|
+
:class="isOpen ? 'text-gray-900 rotate-180' : 'text-gray-500'"
|
|
18
|
+
class="transition duration-100 ease-in-out transform rotate-0 size-6 group-hover:text-opacity-80"
|
|
19
|
+
aria-hidden="true"
|
|
16
20
|
/>
|
|
17
21
|
</slot>
|
|
18
22
|
</button>
|
|
19
23
|
<!-- Menu lists -->
|
|
20
|
-
<div
|
|
24
|
+
<div
|
|
25
|
+
v-if="isOpen && menuItems.length"
|
|
26
|
+
:class="[
|
|
27
|
+
'absolute left-0 z-0 p-2 mt-1 transition-all duration-300 ease-in-out bg-white border border-gray-200 border-solid rounded-lg shadow-2xl shadow-gray-300 min-w-32 max-w-64 w-max',
|
|
28
|
+
placement === 'top' ? 'bottom-full' : 'top-full',
|
|
29
|
+
dropdownClass,
|
|
30
|
+
]"
|
|
31
|
+
@click.stop
|
|
32
|
+
>
|
|
21
33
|
<div
|
|
22
34
|
v-for="item in menuItems"
|
|
23
35
|
:key="item.text"
|
|
@@ -26,36 +38,55 @@
|
|
|
26
38
|
@mouseleave="clearActiveMenuItem"
|
|
27
39
|
@click.stop="$emit('menuItem', item)"
|
|
28
40
|
>
|
|
29
|
-
<div
|
|
41
|
+
<div
|
|
42
|
+
class="flex items-center justify-between w-full gap-2 text-sm font-medium text-gray-800 break-words hover:text-gray-900"
|
|
43
|
+
>
|
|
30
44
|
<slot name="menu" :menuitem="item">
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
45
|
+
{{ item.text }}
|
|
46
|
+
<ChevronDownStroke
|
|
47
|
+
v-if="item.subMenu"
|
|
48
|
+
:class="
|
|
49
|
+
activeMenuItem === item.text
|
|
50
|
+
? 'text-gray-900 -rotate-90'
|
|
51
|
+
: 'text-gray-500 rotate-0'
|
|
52
|
+
"
|
|
53
|
+
class="ml-auto transition duration-300 ease-in-out transform size-6 group-hover:text-opacity-80"
|
|
54
|
+
aria-hidden="true"
|
|
55
|
+
/>
|
|
35
56
|
</slot>
|
|
36
57
|
</div>
|
|
37
58
|
|
|
38
59
|
<!-- Sub-menu lists-->
|
|
39
|
-
<div
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
60
|
+
<div
|
|
61
|
+
v-if="item.subMenu && activeMenuItem === item.text"
|
|
62
|
+
class="absolute top-0 z-10 transition-all duration-300 ease-in-out left-full min-w-32 max-w-64 w-max"
|
|
63
|
+
>
|
|
64
|
+
<div
|
|
65
|
+
class="bg-white border border-gray-200 border-solid rounded-lg shadow-2xl ms-2 shadow-gray-300"
|
|
66
|
+
>
|
|
67
|
+
<div
|
|
68
|
+
v-if="item.enableAction"
|
|
69
|
+
class="flex items-center justify-center w-full gap-1 px-6 py-3 text-sm font-medium text-gray-900 bg-purple-100 rounded-t-md"
|
|
70
|
+
@click.prevent="$emit('actionItem', 'action')"
|
|
71
|
+
>
|
|
72
|
+
<slot name="actionName">{{ "+ Action Name" }}</slot>
|
|
73
|
+
</div>
|
|
74
|
+
<div
|
|
75
|
+
class="p-2 overflow-y-auto overscroll-auto max-h-[50svh] min-h-0 scrollbar--thin"
|
|
76
|
+
>
|
|
45
77
|
<div
|
|
46
78
|
v-for="subItem in item.subMenu"
|
|
47
79
|
:key="subItem.text"
|
|
48
80
|
class="flex items-center justify-between gap-2 px-3 py-2 text-sm font-medium text-gray-700 rounded-lg cursor-pointer hover:bg-gray-100 hover:text-gray-900"
|
|
49
81
|
@click.stop="$emit('subMenuItem', subItem)"
|
|
50
82
|
>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
83
|
+
<slot name="submenu" :subItem="subItem">
|
|
84
|
+
{{ subItem.text }}
|
|
85
|
+
</slot>
|
|
54
86
|
</div>
|
|
55
|
-
|
|
87
|
+
</div>
|
|
56
88
|
</div>
|
|
57
89
|
</div>
|
|
58
|
-
|
|
59
90
|
</div>
|
|
60
91
|
</div>
|
|
61
92
|
</div>
|
|
@@ -69,7 +100,7 @@ import ChevronDownStroke from "../../assets/svg/ChevronDownStroke.vue";
|
|
|
69
100
|
interface MenuItem {
|
|
70
101
|
text: string;
|
|
71
102
|
subMenu?: MenuItem[];
|
|
72
|
-
enableAction?:boolean;
|
|
103
|
+
enableAction?: boolean;
|
|
73
104
|
}
|
|
74
105
|
|
|
75
106
|
defineProps({
|
|
@@ -81,6 +112,10 @@ defineProps({
|
|
|
81
112
|
type: String,
|
|
82
113
|
required: false,
|
|
83
114
|
},
|
|
115
|
+
dropdownClass: {
|
|
116
|
+
type: String,
|
|
117
|
+
required: false,
|
|
118
|
+
},
|
|
84
119
|
menuItems: {
|
|
85
120
|
type: Array as PropType<MenuItem[]>,
|
|
86
121
|
default: () => [
|
|
@@ -93,44 +128,44 @@ defineProps({
|
|
|
93
128
|
{ text: "UKI Fair" },
|
|
94
129
|
{ text: "Germany Q4' 24" },
|
|
95
130
|
{ text: "Edvoy Express" },
|
|
96
|
-
{ text: "Q1 2025 Pipeline" }
|
|
97
|
-
]
|
|
131
|
+
{ text: "Q1 2025 Pipeline" },
|
|
132
|
+
],
|
|
98
133
|
},
|
|
99
134
|
{
|
|
100
135
|
text: "Custom Filter",
|
|
101
|
-
subMenu: [
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
enableAction: true
|
|
106
|
-
}
|
|
107
|
-
]
|
|
136
|
+
subMenu: [{ text: "Application Intakes" }, { text: "New Students" }],
|
|
137
|
+
enableAction: true,
|
|
138
|
+
},
|
|
139
|
+
],
|
|
108
140
|
},
|
|
109
141
|
disabled: Boolean,
|
|
142
|
+
placement: {
|
|
143
|
+
type: String as PropType<"top" | "bottom">,
|
|
144
|
+
default: "bottom",
|
|
145
|
+
},
|
|
110
146
|
});
|
|
111
147
|
|
|
112
148
|
const isOpen = ref(false);
|
|
113
149
|
const activeMenuItem = ref<string | null>(null);
|
|
114
150
|
const dropdownButton = ref<HTMLElement | null>(null);
|
|
115
151
|
|
|
116
|
-
defineEmits([
|
|
152
|
+
defineEmits(["subMenuItem", "menuItem", "actionItem"]);
|
|
117
153
|
|
|
118
154
|
const toggleDropdown = () => {
|
|
119
155
|
isOpen.value = !isOpen.value;
|
|
120
|
-
}
|
|
156
|
+
};
|
|
121
157
|
|
|
122
|
-
const setActiveMenuItem = (text:string) => {
|
|
158
|
+
const setActiveMenuItem = (text: string) => {
|
|
123
159
|
activeMenuItem.value = text;
|
|
124
|
-
}
|
|
160
|
+
};
|
|
125
161
|
|
|
126
162
|
const clearActiveMenuItem = () => {
|
|
127
163
|
activeMenuItem.value = null;
|
|
128
|
-
}
|
|
164
|
+
};
|
|
129
165
|
|
|
130
166
|
onClickOutside(dropdownButton, () => {
|
|
131
167
|
isOpen.value = false;
|
|
132
168
|
});
|
|
133
169
|
</script>
|
|
134
170
|
|
|
135
|
-
<style lang="scss" scoped>
|
|
136
|
-
</style>
|
|
171
|
+
<style lang="scss" scoped></style>
|
package/src/components/index.ts
CHANGED
|
@@ -50,3 +50,4 @@ export { default as EUISearchExpand } from "./searchexpand/EUISearchExpand.vue";
|
|
|
50
50
|
export { default as EUISearchToggle } from "./searchexpand/EUISearchToggle.vue";
|
|
51
51
|
|
|
52
52
|
export { default as EUIBreadcrumb } from "./breadcrumb/EUIBreadcrumb.vue";
|
|
53
|
+
export { default as EUIAlerts } from "./alerts/EUIAlerts.vue";
|
|
@@ -44,6 +44,17 @@ const meta: Meta<typeof EUIModal> = {
|
|
|
44
44
|
"Prevents the modal from being closed by clicking on the backdrop or pressing the Escape key.",
|
|
45
45
|
defaultValue: false,
|
|
46
46
|
},
|
|
47
|
+
size: {
|
|
48
|
+
control: {
|
|
49
|
+
type: "select",
|
|
50
|
+
options: ["xs", "sm", "md", "lg", "xl", "full"],
|
|
51
|
+
},
|
|
52
|
+
description: "Size of the slideover.",
|
|
53
|
+
defaultValue: "sm",
|
|
54
|
+
table: {
|
|
55
|
+
defaultValue: { summary: "sm" },
|
|
56
|
+
},
|
|
57
|
+
},
|
|
47
58
|
},
|
|
48
59
|
},
|
|
49
60
|
parameters: {
|
|
@@ -58,6 +69,15 @@ type Story = StoryObj<typeof meta>;
|
|
|
58
69
|
|
|
59
70
|
// Default EUIModal story with basic content
|
|
60
71
|
export const Default: Story = {
|
|
72
|
+
argTypes: {
|
|
73
|
+
size: {
|
|
74
|
+
control: "select",
|
|
75
|
+
options: ["xs", "sm", "md", "lg", "full"],
|
|
76
|
+
persistent: false,
|
|
77
|
+
slimHeader: false,
|
|
78
|
+
visibleClose: true,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
61
81
|
args: {
|
|
62
82
|
isVisible: false,
|
|
63
83
|
},
|