@volverjs/ui-vue 0.0.9-beta.3 → 0.0.9-beta.5
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/README.md +2 -2
- package/auto-imports.d.ts +2 -0
- package/dist/components/VvCombobox/VvCombobox.es.js +1 -1
- package/dist/components/VvCombobox/VvCombobox.umd.js +1 -1
- package/dist/components/VvDialog/VvDialog.es.js +15 -15
- package/dist/components/VvDialog/VvDialog.umd.js +1 -1
- package/dist/components/VvDropdown/VvDropdown.es.js +1 -1
- package/dist/components/VvDropdown/VvDropdown.umd.js +1 -1
- package/dist/components/index.es.js +15 -15
- package/dist/components/index.umd.js +1 -1
- package/dist/composables/alert/useAlert.d.ts +27 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/composables/index.es.js +81 -0
- package/dist/composables/index.umd.js +1 -0
- package/dist/constants.d.ts +10 -0
- package/dist/icons.es.js +3 -3
- package/dist/icons.umd.js +1 -1
- package/dist/stories/AlertGroup/AlertGroupSlots.stories.d.ts +2 -2
- package/dist/stories/AlertGroup/AlertGroupWithComposable.stories.d.ts +6 -0
- package/package.json +9 -1
- package/src/assets/icons/detailed.json +1 -1
- package/src/assets/icons/normal.json +1 -1
- package/src/assets/icons/simple.json +1 -1
- package/src/components/VvDialog/VvDialog.vue +14 -14
- package/src/components/VvDropdown/VvDropdown.vue +1 -1
- package/src/composables/alert/useAlert.ts +103 -0
- package/src/composables/index.ts +3 -0
- package/src/constants.ts +21 -0
- package/src/stories/AlertGroup/AlertGroup.test.ts +13 -0
- package/src/stories/AlertGroup/AlertGroupSlots.stories.ts +3 -3
- package/src/stories/AlertGroup/AlertGroupWithComposable.stories.ts +118 -0
- package/src/types/alert.d.ts +20 -0
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
const dialogEl: Ref<HTMLDialogElement | undefined> = ref()
|
|
16
16
|
|
|
17
17
|
// data
|
|
18
|
+
const modelValue = useVModel(props, 'modelValue', emit)
|
|
18
19
|
const localModelValue = ref(false)
|
|
19
|
-
const
|
|
20
|
-
get()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
localModelValue.value = value
|
|
20
|
+
const opened = computed({
|
|
21
|
+
get: () => modelValue.value ?? localModelValue.value,
|
|
22
|
+
set: (newValue) => {
|
|
23
|
+
if (modelValue.value === undefined) {
|
|
24
|
+
localModelValue.value = newValue
|
|
25
|
+
return
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
modelValue.value = newValue
|
|
28
28
|
},
|
|
29
29
|
})
|
|
30
30
|
|
|
@@ -80,24 +80,24 @@
|
|
|
80
80
|
|
|
81
81
|
// methods
|
|
82
82
|
onClickOutside(modalWrapper, () => {
|
|
83
|
-
if (!props.keepOpen) {
|
|
84
|
-
|
|
83
|
+
if (!props.keepOpen && opened.value) {
|
|
84
|
+
opened.value = false
|
|
85
85
|
}
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
function close() {
|
|
89
|
-
|
|
89
|
+
opened.value = false
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
function open() {
|
|
93
|
-
|
|
93
|
+
opened.value = true
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
defineExpose({ close, open })
|
|
97
97
|
|
|
98
98
|
// keyboard
|
|
99
99
|
onKeyStroke('Escape', (e) => {
|
|
100
|
-
if (
|
|
100
|
+
if (opened.value) {
|
|
101
101
|
e.preventDefault()
|
|
102
102
|
close()
|
|
103
103
|
}
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
<template>
|
|
108
108
|
<Transition :name="transitioName" v-on="dialogTransitionHandlers">
|
|
109
109
|
<dialog
|
|
110
|
-
v-show="
|
|
110
|
+
v-show="opened"
|
|
111
111
|
v-bind="dialogAttrs"
|
|
112
112
|
ref="dialogEl"
|
|
113
113
|
:class="dialogClass"
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_ALERT_AUTO_CLOSE,
|
|
3
|
+
DEFAULT_ALERT_DISMISSABLE,
|
|
4
|
+
DEFAULT_ALERT_GROUP,
|
|
5
|
+
DEFAULT_ALERT_MODIFIERS,
|
|
6
|
+
DEFAULT_ALERT_INFO_ICON,
|
|
7
|
+
DefaultAlertIconMap,
|
|
8
|
+
} from '@/constants'
|
|
9
|
+
import type { Alert, AlertModifiers } from '@/types/alert'
|
|
10
|
+
|
|
11
|
+
const groups = reactive(
|
|
12
|
+
new Map<string, Map<string, Alert>>([
|
|
13
|
+
[DEFAULT_ALERT_GROUP, new Map<string, Alert>()],
|
|
14
|
+
]),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @description Composable to access alert groups, alerts and functions to add, remove and get alerts by group.
|
|
19
|
+
* @example
|
|
20
|
+
* const { groups, alerts, addAlert, removeAlert, getAlerts } = useAlert()
|
|
21
|
+
* addAlert({
|
|
22
|
+
* title: 'Success!',
|
|
23
|
+
* modifiers: 'success',
|
|
24
|
+
* })
|
|
25
|
+
*
|
|
26
|
+
* `<vv-alert-group :items="alerts" :onClose="removeAlert" />`
|
|
27
|
+
*
|
|
28
|
+
* @returns {
|
|
29
|
+
* alerts: ComputedRef<Alert[]> reactive list of alerts default group,
|
|
30
|
+
* groups: ReactiveRef<Map<string, Map<string, Alert>>>,
|
|
31
|
+
* addAlert: Function to add alert,
|
|
32
|
+
* removeAlert: Function to remove alert,
|
|
33
|
+
* getAlerts: Function to get alerts by group
|
|
34
|
+
* }
|
|
35
|
+
*/
|
|
36
|
+
export const useAlert = () => {
|
|
37
|
+
const addAlert = (
|
|
38
|
+
{
|
|
39
|
+
id = crypto.randomUUID(),
|
|
40
|
+
group = DEFAULT_ALERT_GROUP,
|
|
41
|
+
title,
|
|
42
|
+
icon = DEFAULT_ALERT_INFO_ICON,
|
|
43
|
+
content,
|
|
44
|
+
footer,
|
|
45
|
+
modifiers = DEFAULT_ALERT_MODIFIERS,
|
|
46
|
+
dismissable = DEFAULT_ALERT_DISMISSABLE,
|
|
47
|
+
autoClose = DEFAULT_ALERT_AUTO_CLOSE,
|
|
48
|
+
} = {} as Partial<Alert>,
|
|
49
|
+
) => {
|
|
50
|
+
if (!groups.has(group)) {
|
|
51
|
+
groups.set(group, new Map<string, Alert>())
|
|
52
|
+
}
|
|
53
|
+
const groupMap = groups.get(group)
|
|
54
|
+
const normalizedModifiers =
|
|
55
|
+
typeof modifiers === 'string' ? modifiers.split(' ') : modifiers
|
|
56
|
+
|
|
57
|
+
if (!icon) {
|
|
58
|
+
const alertModifier = normalizedModifiers.find((modifier) =>
|
|
59
|
+
DefaultAlertIconMap.has(modifier as AlertModifiers),
|
|
60
|
+
) as AlertModifiers | undefined
|
|
61
|
+
|
|
62
|
+
if (alertModifier) {
|
|
63
|
+
icon = DefaultAlertIconMap.get(alertModifier) as string
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
groupMap?.set(id.toString(), {
|
|
67
|
+
id,
|
|
68
|
+
group,
|
|
69
|
+
title,
|
|
70
|
+
icon,
|
|
71
|
+
content,
|
|
72
|
+
footer,
|
|
73
|
+
modifiers,
|
|
74
|
+
dismissable,
|
|
75
|
+
autoClose,
|
|
76
|
+
timestamp: Date.now(),
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const removeAlert = (id: string | number, group = DEFAULT_ALERT_GROUP) => {
|
|
81
|
+
const groupMap = groups.get(group)
|
|
82
|
+
groupMap?.delete(id.toString())
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const getAlerts = (group = DEFAULT_ALERT_GROUP) => {
|
|
86
|
+
return computed(() => {
|
|
87
|
+
const groupMap = groups.get(group)
|
|
88
|
+
return groupMap && groupMap instanceof Map
|
|
89
|
+
? Array.from(groupMap?.values()).sort(
|
|
90
|
+
(a, b) => a.timestamp - b.timestamp,
|
|
91
|
+
)
|
|
92
|
+
: []
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
groups,
|
|
98
|
+
alerts: getAlerts(),
|
|
99
|
+
addAlert,
|
|
100
|
+
removeAlert,
|
|
101
|
+
getAlerts,
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { InjectionKey, Ref } from 'vue'
|
|
2
2
|
import type { Emitter } from 'mitt'
|
|
3
3
|
import type { Volver } from './Volver'
|
|
4
|
+
import type { AlertModifiers } from './types/alert'
|
|
4
5
|
|
|
5
6
|
export const DEFAULT_ICONIFY_PROVIDER = 'vv'
|
|
6
7
|
|
|
@@ -110,3 +111,23 @@ export const INJECTION_KEY_ALERT_GROUP = Symbol.for(
|
|
|
110
111
|
name?: Ref<string | undefined>
|
|
111
112
|
bus?: Emitter<{ close: string }>
|
|
112
113
|
}>
|
|
114
|
+
export const DEFAULT_ALERT_AUTO_CLOSE = 10000
|
|
115
|
+
export const DEFAULT_ALERT_MODIFIERS = 'info'
|
|
116
|
+
export const DEFAULT_ALERT_DISMISSABLE = true
|
|
117
|
+
export const DEFAULT_ALERT_GROUP = 'default'
|
|
118
|
+
export const DEFAULT_ALERT_INFO_ICON = 'information'
|
|
119
|
+
export const DEFAULT_ALERT_SUCCESS_ICON = 'check-circle'
|
|
120
|
+
export const DEFAULT_ALERT_WARNING_ICON = 'warning'
|
|
121
|
+
export const DEFAULT_ALERT_DANGER_ICON = 'error'
|
|
122
|
+
export const DefaultAlertIconMap = new Map<AlertModifiers, string>([
|
|
123
|
+
['success', DEFAULT_ALERT_SUCCESS_ICON],
|
|
124
|
+
['info', DEFAULT_ALERT_INFO_ICON],
|
|
125
|
+
['warning', DEFAULT_ALERT_WARNING_ICON],
|
|
126
|
+
['danger', DEFAULT_ALERT_DANGER_ICON],
|
|
127
|
+
])
|
|
128
|
+
// {
|
|
129
|
+
// success: DEFAULT_ALERT_SUCCESS_ICON,
|
|
130
|
+
// info: DEFAULT_ALERT_INFO_ICON,
|
|
131
|
+
// warning: DEFAULT_ALERT_WARNING_ICON,
|
|
132
|
+
// danger: DEFAULT_ALERT_DANGER_ICON,
|
|
133
|
+
// }
|
|
@@ -6,6 +6,8 @@ export async function defaultTest({ canvasElement, args }: PlayAttributes) {
|
|
|
6
6
|
const element = (await within(canvasElement).findByTestId(
|
|
7
7
|
'element',
|
|
8
8
|
)) as HTMLElement
|
|
9
|
+
const buttons =
|
|
10
|
+
canvasElement.getElementsByClassName('buttons-container')?.[0]
|
|
9
11
|
|
|
10
12
|
expect(element).toHaveClass('vv-alert-group')
|
|
11
13
|
|
|
@@ -71,6 +73,17 @@ export async function defaultTest({ canvasElement, args }: PlayAttributes) {
|
|
|
71
73
|
expect(element.lastElementChild?.innerHTML).toEqual(div.innerHTML)
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
if (buttons) {
|
|
77
|
+
// click every button child and expect to have alert with correct css class
|
|
78
|
+
for (let i = 0; i < buttons.children.length; i++) {
|
|
79
|
+
const button = buttons.children[i] as HTMLElement
|
|
80
|
+
await button.click()
|
|
81
|
+
expect(alertGroupList.lastElementChild).toHaveClass(
|
|
82
|
+
`vv-alert--${button.id}`,
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
74
87
|
// check accessibility
|
|
75
88
|
await expect(element).toHaveNoViolations()
|
|
76
89
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Meta } from '@storybook/vue3'
|
|
2
|
-
import
|
|
2
|
+
import VvAlertGroup from '@/components/VvAlertGroup/VvAlertGroup.vue'
|
|
3
3
|
import { defaultArgs, argTypes } from './AlertGroup.settings'
|
|
4
4
|
import { Default as DefaultStory, type Story } from './AlertGroup.stories'
|
|
5
5
|
|
|
6
|
-
const meta: Meta<typeof
|
|
6
|
+
const meta: Meta<typeof VvAlertGroup> = {
|
|
7
7
|
title: 'Components/AlertGroup/Slots',
|
|
8
|
-
component:
|
|
8
|
+
component: VvAlertGroup,
|
|
9
9
|
args: defaultArgs,
|
|
10
10
|
argTypes,
|
|
11
11
|
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/vue3'
|
|
2
|
+
import VvAlertGroup from '@/components/VvAlertGroup/VvAlertGroup.vue'
|
|
3
|
+
import VvButton from '@/components/VvButton/VvButton.vue'
|
|
4
|
+
import { defaultArgs, argTypes } from './AlertGroup.settings'
|
|
5
|
+
import { Default as DefaultStory, type Story } from './AlertGroup.stories'
|
|
6
|
+
import { useAlert } from '@/composables/alert/useAlert'
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof VvAlertGroup> = {
|
|
9
|
+
title: 'Components/AlertGroup/UseComposable',
|
|
10
|
+
component: VvAlertGroup,
|
|
11
|
+
args: defaultArgs,
|
|
12
|
+
argTypes,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export default meta
|
|
17
|
+
|
|
18
|
+
export const UseComposable: Story = {
|
|
19
|
+
...DefaultStory,
|
|
20
|
+
parameters: {
|
|
21
|
+
docs: {
|
|
22
|
+
source: {
|
|
23
|
+
type: 'code',
|
|
24
|
+
language: 'html',
|
|
25
|
+
code: /* html */ `
|
|
26
|
+
<div class="flex gap-md">
|
|
27
|
+
<vv-button label="Show success" modifiers="secondary" @click="showSuccess" class="mb-lg" />
|
|
28
|
+
<vv-button label="Show danger" modifiers="secondary" @click="showDanger" class="mb-lg" />
|
|
29
|
+
<vv-button label="Show warning" modifiers="secondary" @click="showWarning" class="mb-lg" />
|
|
30
|
+
<vv-button label="Show info" modifiers="secondary" @click="showInfo" class="mb-lg" />
|
|
31
|
+
</div>
|
|
32
|
+
<vv-alert-group v-bind="args" :items="alerts" :onClose="removeAlert" data-testId="element" />
|
|
33
|
+
|
|
34
|
+
<script setup lang='ts'>
|
|
35
|
+
import { useAlert } from '@volverjs/ui-vue/composables'
|
|
36
|
+
|
|
37
|
+
const { addAlert, removeAlert, alerts } = useAlert()
|
|
38
|
+
|
|
39
|
+
function showSuccess() {
|
|
40
|
+
addAlert({
|
|
41
|
+
title: 'Success!',
|
|
42
|
+
modifiers: 'success',
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
function showDanger() {
|
|
46
|
+
addAlert({
|
|
47
|
+
title: 'Danger!',
|
|
48
|
+
modifiers: 'danger',
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
function showWarning() {
|
|
52
|
+
addAlert({
|
|
53
|
+
title: 'Warning!',
|
|
54
|
+
modifiers: 'warning',
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
function showInfo() {
|
|
58
|
+
addAlert({
|
|
59
|
+
title: 'Info!',
|
|
60
|
+
modifiers: 'info',
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
64
|
+
`,
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
render: (args) => ({
|
|
69
|
+
components: { VvAlertGroup, VvButton },
|
|
70
|
+
setup() {
|
|
71
|
+
const { addAlert, removeAlert, alerts } = useAlert()
|
|
72
|
+
|
|
73
|
+
function showSuccess() {
|
|
74
|
+
addAlert({
|
|
75
|
+
title: 'Success!',
|
|
76
|
+
modifiers: 'success',
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
function showDanger() {
|
|
80
|
+
addAlert({
|
|
81
|
+
title: 'Danger!',
|
|
82
|
+
modifiers: 'danger',
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
function showWarning() {
|
|
86
|
+
addAlert({
|
|
87
|
+
title: 'Warning!',
|
|
88
|
+
modifiers: 'warning',
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
function showInfo() {
|
|
92
|
+
addAlert({
|
|
93
|
+
title: 'Info!',
|
|
94
|
+
modifiers: 'info',
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
args,
|
|
100
|
+
alerts,
|
|
101
|
+
removeAlert,
|
|
102
|
+
showSuccess,
|
|
103
|
+
showDanger,
|
|
104
|
+
showWarning,
|
|
105
|
+
showInfo,
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
template: /* html */ `
|
|
109
|
+
<div class="buttons-container flex gap-md" >
|
|
110
|
+
<vv-button id="success" label="Show success" modifiers="secondary" @click="showSuccess" class="mb-lg" />
|
|
111
|
+
<vv-button id="danger" label="Show danger" modifiers="secondary" @click="showDanger" class="mb-lg" />
|
|
112
|
+
<vv-button id="warning" label="Show warning" modifiers="secondary" @click="showWarning" class="mb-lg" />
|
|
113
|
+
<vv-button id="info" label="Show info" modifiers="secondary" @click="showInfo" class="mb-lg" />
|
|
114
|
+
</div>
|
|
115
|
+
<vv-alert-group v-bind="args" :items="alerts" :onClose="removeAlert" data-testId="element" />
|
|
116
|
+
`,
|
|
117
|
+
}),
|
|
118
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type AlertModifiers =
|
|
2
|
+
| 'success'
|
|
3
|
+
| 'info'
|
|
4
|
+
| 'warning'
|
|
5
|
+
| 'danger'
|
|
6
|
+
| 'brand'
|
|
7
|
+
| 'accent'
|
|
8
|
+
|
|
9
|
+
export type Alert = {
|
|
10
|
+
id: string | number
|
|
11
|
+
group: string
|
|
12
|
+
title?: string
|
|
13
|
+
icon: string | Record<string, unknown>
|
|
14
|
+
content?: string
|
|
15
|
+
footer?: string
|
|
16
|
+
modifiers: AlertModifiers
|
|
17
|
+
dismissable: boolean
|
|
18
|
+
autoClose: number
|
|
19
|
+
timestamp: number
|
|
20
|
+
}
|