@citizenplane/pimp 9.16.2 → 10.0.0
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/pimp.es.js +5419 -7042
- package/dist/pimp.umd.js +44 -44
- package/dist/style.css +1 -1
- package/package.json +1 -2
- package/src/components/CpSelectMenu.vue +1 -13
- package/src/components/CpToast.vue +27 -0
- package/src/components/index.ts +1 -10
- package/src/components/CpToaster.vue +0 -382
- package/src/plugins/toaster.ts +0 -71
- package/src/stories/CpToaster.stories.ts +0 -188
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@citizenplane/pimp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"dev": "storybook dev -p 8080",
|
|
6
6
|
"build-storybook": "storybook build --output-dir ./docs",
|
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
"./*.css": "./dist/*.css"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"animejs": "^4.2.2",
|
|
37
36
|
"feather-icons": "^4.29.2",
|
|
38
37
|
"floating-vue": "^5.2.2",
|
|
39
38
|
"luxon": "^3.7.2",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
type="chevron-down"
|
|
9
9
|
/>
|
|
10
10
|
</button>
|
|
11
|
-
<transition
|
|
11
|
+
<transition mode="out-in" name="scale-elastic">
|
|
12
12
|
<div v-if="isDropdownOpen" ref="dropdownRef" class="cpSelectMenu__dropdown dropdown">
|
|
13
13
|
<p v-if="dropdownTitle" class="dropdown__title">
|
|
14
14
|
{{ dropdownTitle }}
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
</template>
|
|
48
48
|
|
|
49
49
|
<script setup lang="ts">
|
|
50
|
-
import { animate, cubicBezier } from 'animejs'
|
|
51
50
|
import { ref, computed, nextTick } from 'vue'
|
|
52
51
|
|
|
53
52
|
interface SelectValue {
|
|
@@ -92,17 +91,6 @@ const inputType = computed(() => {
|
|
|
92
91
|
return props.isMultiSelect ? 'checkbox' : 'radio'
|
|
93
92
|
})
|
|
94
93
|
|
|
95
|
-
const enter = (): void => {
|
|
96
|
-
if (dropdownRef.value) {
|
|
97
|
-
animate(dropdownRef.value, {
|
|
98
|
-
scale: [0.8, 1],
|
|
99
|
-
opacity: [0, 1],
|
|
100
|
-
duration: 200,
|
|
101
|
-
ease: cubicBezier(0.175, 0.885, 0.32, 1.175),
|
|
102
|
-
})
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
94
|
const toggleDropdown = (): void => {
|
|
107
95
|
isDropdownOpen.value = !isDropdownOpen.value
|
|
108
96
|
|
|
@@ -151,8 +151,14 @@ const handleActionClick = (onClick: VoidFunction, closeCallback: VoidFunction) =
|
|
|
151
151
|
z-index: -1;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
+
.cpToasts {
|
|
155
|
+
pointer-events: none;
|
|
156
|
+
}
|
|
157
|
+
|
|
154
158
|
.cpToasts .p-toast-message-leave-active:not(:only-child) {
|
|
155
159
|
position: absolute;
|
|
160
|
+
left: 0;
|
|
161
|
+
right: 0;
|
|
156
162
|
}
|
|
157
163
|
|
|
158
164
|
.cpToasts[data-p$='center'] {
|
|
@@ -169,6 +175,7 @@ const handleActionClick = (onClick: VoidFunction, closeCallback: VoidFunction) =
|
|
|
169
175
|
.cpToasts > div {
|
|
170
176
|
display: flex;
|
|
171
177
|
flex-direction: column;
|
|
178
|
+
pointer-events: auto;
|
|
172
179
|
gap: sp.$space;
|
|
173
180
|
}
|
|
174
181
|
|
|
@@ -180,6 +187,7 @@ const handleActionClick = (onClick: VoidFunction, closeCallback: VoidFunction) =
|
|
|
180
187
|
overflow: hidden;
|
|
181
188
|
position: relative;
|
|
182
189
|
flex-direction: column;
|
|
190
|
+
max-width: fn.px-to-rem(400);
|
|
183
191
|
padding: sp.$space-md;
|
|
184
192
|
border-radius: fn.px-to-rem(8);
|
|
185
193
|
box-shadow: var(--toaster-shadow);
|
|
@@ -216,6 +224,10 @@ const handleActionClick = (onClick: VoidFunction, closeCallback: VoidFunction) =
|
|
|
216
224
|
&__summary {
|
|
217
225
|
font-weight: 600;
|
|
218
226
|
color: fn.v(text-accent-primary);
|
|
227
|
+
|
|
228
|
+
&:first-letter {
|
|
229
|
+
text-transform: capitalize;
|
|
230
|
+
}
|
|
219
231
|
}
|
|
220
232
|
|
|
221
233
|
&__detail {
|
|
@@ -345,4 +357,19 @@ const handleActionClick = (onClick: VoidFunction, closeCallback: VoidFunction) =
|
|
|
345
357
|
}
|
|
346
358
|
}
|
|
347
359
|
}
|
|
360
|
+
|
|
361
|
+
@media (max-width: 451px) {
|
|
362
|
+
.cpToasts {
|
|
363
|
+
max-width: calc(100% - #{fn.v(spacing-2xl)});
|
|
364
|
+
right: 0 !important;
|
|
365
|
+
left: 0;
|
|
366
|
+
margin: 0 auto;
|
|
367
|
+
text-align: center;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.cpToast {
|
|
371
|
+
max-width: 100%;
|
|
372
|
+
min-width: 100%;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
348
375
|
</style>
|
package/src/components/index.ts
CHANGED
|
@@ -43,7 +43,6 @@ import CpTabs from './CpTabs.vue'
|
|
|
43
43
|
import CpTelInput from './CpTelInput.vue'
|
|
44
44
|
import CpTextarea from './CpTextarea.vue'
|
|
45
45
|
import CpToast from './CpToast.vue'
|
|
46
|
-
import CpToaster from './CpToaster.vue'
|
|
47
46
|
import CpTooltip from './CpTooltip.vue'
|
|
48
47
|
import CpTransitionDialog from './CpTransitionDialog.vue'
|
|
49
48
|
import IconAirline from './icons/IconAirline.vue'
|
|
@@ -56,10 +55,8 @@ import IconSupplier from './icons/IconSupplier.vue'
|
|
|
56
55
|
import IconThirdParty from './icons/IconThirdParty.vue'
|
|
57
56
|
import IconTooltip from './icons/IconTooltip.vue'
|
|
58
57
|
import TransitionExpand from './TransitionExpand.vue'
|
|
59
|
-
import createToaster from '@/plugins/toaster'
|
|
60
58
|
|
|
61
59
|
const Components = {
|
|
62
|
-
CpToaster,
|
|
63
60
|
CpToast,
|
|
64
61
|
CpBadge,
|
|
65
62
|
CpTabs,
|
|
@@ -105,7 +102,7 @@ const Components = {
|
|
|
105
102
|
}
|
|
106
103
|
|
|
107
104
|
const Pimp = {
|
|
108
|
-
install(app: App
|
|
105
|
+
install(app: App) {
|
|
109
106
|
app.use(PrimeVue, { unstyled: true })
|
|
110
107
|
app.use(VueTelInput)
|
|
111
108
|
app.use(ToastService)
|
|
@@ -119,12 +116,6 @@ const Pimp = {
|
|
|
119
116
|
app.directive('bind-once', BindOnceDirective)
|
|
120
117
|
app.directive('maska', vMaska)
|
|
121
118
|
app.directive('tooltip', vTooltip)
|
|
122
|
-
|
|
123
|
-
// CpToaster
|
|
124
|
-
const methods = createToaster(options)
|
|
125
|
-
// @ts-expect-error <comment on type error>
|
|
126
|
-
app.$toaster = methods
|
|
127
|
-
app.config.globalProperties.$toaster = methods
|
|
128
119
|
},
|
|
129
120
|
}
|
|
130
121
|
|
|
@@ -1,382 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<transition @enter="enter" @leave="leave">
|
|
3
|
-
<div
|
|
4
|
-
v-show="isOpen"
|
|
5
|
-
:id="toasterId"
|
|
6
|
-
:key="toasterId"
|
|
7
|
-
class="cpToaster"
|
|
8
|
-
:class="dynamicClass"
|
|
9
|
-
role="alert"
|
|
10
|
-
@mouseenter="setHoverState()"
|
|
11
|
-
@mouseleave="setHoverState(false)"
|
|
12
|
-
>
|
|
13
|
-
<div class="cpToaster__content">
|
|
14
|
-
<cp-icon class="cpToaster__icon" :type="toasterIcon" />
|
|
15
|
-
<div class="cpToaster__body">
|
|
16
|
-
<cp-heading class="cpToaster__title" :heading-level="HeadingLevels.H4" :size="400">{{ title }}</cp-heading>
|
|
17
|
-
<p v-if="description" class="cpToaster__description">{{ description }}</p>
|
|
18
|
-
</div>
|
|
19
|
-
</div>
|
|
20
|
-
<button class="cpToaster__close" type="button" @click="closeToaster">
|
|
21
|
-
<cp-icon type="x" />
|
|
22
|
-
</button>
|
|
23
|
-
<div v-if="actionLabel" class="cpToaster__footer">
|
|
24
|
-
<button v-if="actionIsButton" class="cpToaster__button" type="button" @click="handleActionMethod">
|
|
25
|
-
{{ actionLabel }}
|
|
26
|
-
</button>
|
|
27
|
-
<a v-else class="cpToaster__button" v-bind="actionLinkProperties">
|
|
28
|
-
{{ actionLabel }}
|
|
29
|
-
</a>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
32
|
-
</transition>
|
|
33
|
-
</template>
|
|
34
|
-
|
|
35
|
-
<script setup lang="ts">
|
|
36
|
-
import { animate, cubicBezier } from 'animejs'
|
|
37
|
-
import { ref, computed, watch, onBeforeMount, onMounted, nextTick, getCurrentInstance, useId } from 'vue'
|
|
38
|
-
|
|
39
|
-
import CpHeading from '@/components/CpHeading.vue'
|
|
40
|
-
import CpIcon from '@/components/CpIcon.vue'
|
|
41
|
-
|
|
42
|
-
import { HeadingLevels, Intent } from '@/constants'
|
|
43
|
-
|
|
44
|
-
interface Props {
|
|
45
|
-
actionAs?: 'link' | 'button'
|
|
46
|
-
actionLabel?: string
|
|
47
|
-
actionLinkProperties?: Record<string, unknown>
|
|
48
|
-
actionMethod?: (vmProperties: Record<string, unknown>) => void
|
|
49
|
-
delayBeforeCloseInMs?: number
|
|
50
|
-
description?: string
|
|
51
|
-
isUnique?: boolean
|
|
52
|
-
title: string
|
|
53
|
-
type?: string
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
interface PublicMethods {
|
|
57
|
-
closeToaster: () => void
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
61
|
-
description: '',
|
|
62
|
-
type: 'info',
|
|
63
|
-
delayBeforeCloseInMs: 5000,
|
|
64
|
-
actionLabel: '',
|
|
65
|
-
actionLinkProperties: () => ({}),
|
|
66
|
-
actionAs: 'button',
|
|
67
|
-
actionMethod: () => {},
|
|
68
|
-
isUnique: false,
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const validateType = (value: string): boolean => {
|
|
72
|
-
const intentValues = Object.values(Intent).map((item) => item.value)
|
|
73
|
-
return intentValues.includes(value)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
if (!validateType(props.type)) {
|
|
77
|
-
console.warn(`Type de toaster invalide: ${props.type}`)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const toasterId = useId()
|
|
81
|
-
const toastersContainer = ref<HTMLElement | null>(null)
|
|
82
|
-
const isOpen = ref<boolean>(false)
|
|
83
|
-
const isHovered = ref<boolean>(false)
|
|
84
|
-
const deleteCountDown = ref<number>(props.delayBeforeCloseInMs)
|
|
85
|
-
const timeoutID = ref<ReturnType<typeof setTimeout>>()
|
|
86
|
-
const countDownInterval = ref<ReturnType<typeof setInterval>>()
|
|
87
|
-
|
|
88
|
-
const instance = getCurrentInstance()
|
|
89
|
-
|
|
90
|
-
const actionIsButton = computed(() => props.actionAs === 'button')
|
|
91
|
-
|
|
92
|
-
const toasterIcon = computed(() => {
|
|
93
|
-
const intentValues = Object.values(Intent)
|
|
94
|
-
const intent = intentValues.find((intentItem) => intentItem.value === props.type)
|
|
95
|
-
return intent ? intent.icon : Intent.INFO.icon
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
const dynamicClass = computed(() => {
|
|
99
|
-
return `cpToaster--${props.type || Intent.INFO.value}`
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
watch(isHovered, (newValue: boolean) => {
|
|
103
|
-
if (!newValue) {
|
|
104
|
-
handleDeleteEvent()
|
|
105
|
-
} else {
|
|
106
|
-
cancelDelete()
|
|
107
|
-
}
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
const createContainer = (): void => {
|
|
111
|
-
toastersContainer.value = document.querySelector('.cpToaster__container')
|
|
112
|
-
|
|
113
|
-
if (toastersContainer.value) return
|
|
114
|
-
|
|
115
|
-
if (!toastersContainer.value) {
|
|
116
|
-
toastersContainer.value = document.createElement('section')
|
|
117
|
-
toastersContainer.value.className = 'cpToaster__container'
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const setupContainer = (): void => {
|
|
122
|
-
if (toastersContainer.value) {
|
|
123
|
-
document.body.appendChild(toastersContainer.value)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
const removeSiblings = (): void => {
|
|
128
|
-
if (!props.isUnique) return
|
|
129
|
-
|
|
130
|
-
const siblings = document.querySelectorAll('.cpToaster')
|
|
131
|
-
siblings.forEach(removeElement)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const showToaster = (): void => {
|
|
135
|
-
isOpen.value = true
|
|
136
|
-
|
|
137
|
-
nextTick(() => {
|
|
138
|
-
if (toastersContainer.value && instance?.proxy?.$el) {
|
|
139
|
-
toastersContainer.value.insertAdjacentElement('afterbegin', instance.proxy.$el)
|
|
140
|
-
}
|
|
141
|
-
})
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const setHoverState = (state: boolean = true): void => {
|
|
145
|
-
isHovered.value = state
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const handleDeleteEvent = (): void => {
|
|
149
|
-
startCountDown()
|
|
150
|
-
|
|
151
|
-
timeoutID.value = setTimeout(() => {
|
|
152
|
-
closeToaster()
|
|
153
|
-
}, props.delayBeforeCloseInMs)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const cancelDelete = (): void => {
|
|
157
|
-
if (timeoutID.value) {
|
|
158
|
-
clearTimeout(timeoutID.value)
|
|
159
|
-
}
|
|
160
|
-
if (countDownInterval.value) {
|
|
161
|
-
clearInterval(countDownInterval.value)
|
|
162
|
-
}
|
|
163
|
-
resetCountDown()
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const startCountDown = (): void => {
|
|
167
|
-
countDownInterval.value = setInterval(() => {
|
|
168
|
-
deleteCountDown.value -= 1000
|
|
169
|
-
if (deleteCountDown.value <= 0 && countDownInterval.value) {
|
|
170
|
-
clearInterval(countDownInterval.value)
|
|
171
|
-
}
|
|
172
|
-
}, 1000)
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const resetCountDown = (): void => {
|
|
176
|
-
deleteCountDown.value = props.delayBeforeCloseInMs
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const handleActionMethod = (): void => {
|
|
180
|
-
const vmProperties: Record<string, unknown> = {
|
|
181
|
-
closeToaster,
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return props.actionMethod(vmProperties)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const closeToaster = (): void => {
|
|
188
|
-
cancelDelete()
|
|
189
|
-
isOpen.value = false
|
|
190
|
-
|
|
191
|
-
setTimeout(() => {
|
|
192
|
-
if (instance?.proxy?.$el) {
|
|
193
|
-
removeElement(instance.proxy.$el)
|
|
194
|
-
}
|
|
195
|
-
}, 240)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const removeElement = (el: Element): void => {
|
|
199
|
-
if (typeof el.remove !== 'undefined') {
|
|
200
|
-
el.remove()
|
|
201
|
-
} else if (el.parentNode) {
|
|
202
|
-
el.parentNode.removeChild(el)
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
const enter = async (el: Element, done: () => void): Promise<void> => {
|
|
207
|
-
animate(el, {
|
|
208
|
-
translateY: [-60, 0],
|
|
209
|
-
opacity: [0, 1],
|
|
210
|
-
duration: 240,
|
|
211
|
-
ease: cubicBezier(0.175, 0.885, 0.32, 1.175),
|
|
212
|
-
complete: function () {
|
|
213
|
-
done()
|
|
214
|
-
},
|
|
215
|
-
})
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const leave = async (el: Element, done: () => void): Promise<void> => {
|
|
219
|
-
animate(el, {
|
|
220
|
-
scale: [1, 0.8],
|
|
221
|
-
opacity: [1, 0],
|
|
222
|
-
duration: 240,
|
|
223
|
-
ease: cubicBezier(0.0, 0.0, 0.2, 1),
|
|
224
|
-
complete: function () {
|
|
225
|
-
done()
|
|
226
|
-
},
|
|
227
|
-
})
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
onBeforeMount(() => {
|
|
231
|
-
createContainer()
|
|
232
|
-
setupContainer()
|
|
233
|
-
removeSiblings()
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
onMounted(() => {
|
|
237
|
-
showToaster()
|
|
238
|
-
handleDeleteEvent()
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
defineExpose<PublicMethods>({
|
|
242
|
-
closeToaster,
|
|
243
|
-
})
|
|
244
|
-
</script>
|
|
245
|
-
|
|
246
|
-
<style lang="scss">
|
|
247
|
-
@mixin cp-toaster-style($color, $className) {
|
|
248
|
-
&--#{$className} &__icon {
|
|
249
|
-
color: $color;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
&--#{$className}:before {
|
|
253
|
-
background-color: $color;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
.cpToaster {
|
|
258
|
-
position: relative;
|
|
259
|
-
box-shadow:
|
|
260
|
-
rgba(67, 90, 111, 0.3) 0 0 1px,
|
|
261
|
-
rgba(67, 90, 111, 0.47) 0 8px 10px -4px;
|
|
262
|
-
background: colors.$neutral-light;
|
|
263
|
-
padding: sp.$space-md;
|
|
264
|
-
overflow: hidden;
|
|
265
|
-
width: max-content;
|
|
266
|
-
max-width: 100%;
|
|
267
|
-
margin: auto;
|
|
268
|
-
pointer-events: auto;
|
|
269
|
-
font-size: fn.px-to-rem(14);
|
|
270
|
-
|
|
271
|
-
@media (min-width: 769px) {
|
|
272
|
-
border-radius: fn.px-to-rem(8);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
@media (max-width: 768px) {
|
|
276
|
-
min-width: 100%;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
&:before {
|
|
280
|
-
content: '';
|
|
281
|
-
position: absolute;
|
|
282
|
-
top: 0;
|
|
283
|
-
left: 0;
|
|
284
|
-
width: fn.px-to-rem(3);
|
|
285
|
-
height: 100%;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
&__container {
|
|
289
|
-
position: fixed;
|
|
290
|
-
z-index: 9999;
|
|
291
|
-
top: 0;
|
|
292
|
-
left: 0;
|
|
293
|
-
right: 0;
|
|
294
|
-
margin: auto;
|
|
295
|
-
padding: sp.$space-lg;
|
|
296
|
-
max-width: fn.px-to-rem(400);
|
|
297
|
-
pointer-events: none;
|
|
298
|
-
|
|
299
|
-
& > *:not(:last-child) {
|
|
300
|
-
margin-bottom: sp.$space;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
@media (max-width: 768px) {
|
|
304
|
-
max-width: 100%;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
&__content {
|
|
309
|
-
display: flex;
|
|
310
|
-
align-items: flex-start;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
&__body {
|
|
314
|
-
flex: 1;
|
|
315
|
-
margin-left: sp.$space;
|
|
316
|
-
padding-right: calc(sp.$space-lg + sp.$space-lg);
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
&__icon {
|
|
320
|
-
flex-shrink: 0;
|
|
321
|
-
height: fn.px-to-rem(16);
|
|
322
|
-
width: fn.px-to-rem(16);
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
&__content,
|
|
326
|
-
&__title {
|
|
327
|
-
line-height: fn.px-to-rem(16);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
&__title {
|
|
331
|
-
font-weight: 600;
|
|
332
|
-
|
|
333
|
-
&:not(:only-child) {
|
|
334
|
-
margin-bottom: sp.$space-sm;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
&__description {
|
|
339
|
-
font-size: fn.px-to-rem(14);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
&__close {
|
|
343
|
-
position: absolute;
|
|
344
|
-
right: sp.$space;
|
|
345
|
-
top: sp.$space;
|
|
346
|
-
display: flex;
|
|
347
|
-
border-radius: fn.px-to-rem(4);
|
|
348
|
-
padding: sp.$space-sm;
|
|
349
|
-
color: colors.$neutral-dark-1;
|
|
350
|
-
|
|
351
|
-
svg {
|
|
352
|
-
margin: 0;
|
|
353
|
-
width: fn.px-to-rem(18);
|
|
354
|
-
height: fn.px-to-rem(18);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
&:hover {
|
|
358
|
-
background-color: rgba(colors.$neutral-dark-1, 0.1);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
&__footer {
|
|
363
|
-
display: flex;
|
|
364
|
-
justify-content: flex-end;
|
|
365
|
-
margin-top: sp.$space-lg;
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
&__button {
|
|
369
|
-
font-size: fn.px-to-rem(12);
|
|
370
|
-
color: colors.$secondary-color;
|
|
371
|
-
|
|
372
|
-
&:not(:hover) {
|
|
373
|
-
text-decoration: underline;
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
@include cp-toaster-style(colors.$secondary-color, 'info');
|
|
378
|
-
@include cp-toaster-style(colors.$warning-color, 'warning');
|
|
379
|
-
@include cp-toaster-style(colors.$success-color, 'success');
|
|
380
|
-
@include cp-toaster-style(colors.$error-color, 'critical');
|
|
381
|
-
}
|
|
382
|
-
</style>
|
package/src/plugins/toaster.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { App, h, render, VNode } from 'vue'
|
|
2
|
-
|
|
3
|
-
import CpToaster from '@/components/CpToaster.vue'
|
|
4
|
-
|
|
5
|
-
import { Intent } from '@/constants'
|
|
6
|
-
|
|
7
|
-
type MountOptions = {
|
|
8
|
-
app?: App | null
|
|
9
|
-
children?: unknown
|
|
10
|
-
element?: HTMLElement | null
|
|
11
|
-
props?: Record<string, unknown>
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const createElement = () => (typeof document !== 'undefined' ? document.createElement('div') : null)
|
|
15
|
-
|
|
16
|
-
const mount = (component: unknown, { props, children, element, app }: MountOptions = {}) => {
|
|
17
|
-
let el: HTMLElement | null = element ? element : createElement()
|
|
18
|
-
|
|
19
|
-
// @ts-expect-error <comment on type error>
|
|
20
|
-
let vNode: VNode = h(component, props, children)
|
|
21
|
-
if (app && app._context) {
|
|
22
|
-
vNode.appContext = app._context
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
render(vNode, el as HTMLElement)
|
|
26
|
-
|
|
27
|
-
const destroy = () => {
|
|
28
|
-
if (el) {
|
|
29
|
-
render(null, el)
|
|
30
|
-
}
|
|
31
|
-
el = null
|
|
32
|
-
// @ts-expect-error explicit nulling for GC
|
|
33
|
-
vNode = null
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return { vNode, destroy, el }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const createToaster = (globalOptions: Record<string, unknown> = {}) => {
|
|
40
|
-
return {
|
|
41
|
-
show(options: Record<string, unknown> = {}) {
|
|
42
|
-
const localOptions = { ...options }
|
|
43
|
-
|
|
44
|
-
mount(CpToaster, {
|
|
45
|
-
props: { ...globalOptions, ...localOptions },
|
|
46
|
-
})
|
|
47
|
-
},
|
|
48
|
-
unique(options: Record<string, unknown> = {}) {
|
|
49
|
-
options.isUnique = true
|
|
50
|
-
return this.show(options)
|
|
51
|
-
},
|
|
52
|
-
success(options: Record<string, unknown> = {}) {
|
|
53
|
-
options.type = Intent.SUCCESS.value
|
|
54
|
-
return this.show(options)
|
|
55
|
-
},
|
|
56
|
-
critical(options: Record<string, unknown> = {}) {
|
|
57
|
-
options.type = Intent.CRITICAL.value
|
|
58
|
-
return this.show(options)
|
|
59
|
-
},
|
|
60
|
-
info(options: Record<string, unknown> = {}) {
|
|
61
|
-
options.type = Intent.INFO.value
|
|
62
|
-
return this.show(options)
|
|
63
|
-
},
|
|
64
|
-
warning(options: Record<string, unknown> = {}) {
|
|
65
|
-
options.type = Intent.WARNING.value
|
|
66
|
-
return this.show(options)
|
|
67
|
-
},
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
export default createToaster
|