@vue-skuilder/common-ui 0.1.1
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/assets/index.css +10 -0
- package/dist/common-ui.es.js +16404 -0
- package/dist/common-ui.es.js.map +1 -0
- package/dist/common-ui.umd.js +9 -0
- package/dist/common-ui.umd.js.map +1 -0
- package/dist/components/HeatMap.types.d.ts +13 -0
- package/dist/components/PaginatingToolbar.types.d.ts +40 -0
- package/dist/components/SkMouseTrap.types.d.ts +3 -0
- package/dist/components/SkMouseTrapToolTip.types.d.ts +35 -0
- package/dist/components/SnackbarService.d.ts +11 -0
- package/dist/components/StudySession.types.d.ts +6 -0
- package/dist/components/auth/index.d.ts +4 -0
- package/dist/components/cardRendering/MarkdownRendererHelpers.d.ts +22 -0
- package/dist/components/studentInputs/BaseUserInput.d.ts +16 -0
- package/dist/components/studentInputs/RadioMultipleChoice.types.d.ts +5 -0
- package/dist/composables/CompositionViewable.d.ts +33 -0
- package/dist/composables/Displayable.d.ts +47 -0
- package/dist/composables/index.d.ts +2 -0
- package/dist/index.d.ts +36 -0
- package/dist/plugins/pinia.d.ts +5 -0
- package/dist/stores/useAuthStore.d.ts +225 -0
- package/dist/stores/useCardPreviewModeStore.d.ts +8 -0
- package/dist/stores/useConfigStore.d.ts +11 -0
- package/dist/utils/SkldrMouseTrap.d.ts +32 -0
- package/package.json +67 -0
- package/src/components/HeatMap.types.ts +15 -0
- package/src/components/HeatMap.vue +354 -0
- package/src/components/PaginatingToolbar.types.ts +48 -0
- package/src/components/PaginatingToolbar.vue +75 -0
- package/src/components/SkMouseTrap.types.ts +3 -0
- package/src/components/SkMouseTrap.vue +70 -0
- package/src/components/SkMouseTrapToolTip.types.ts +41 -0
- package/src/components/SkMouseTrapToolTip.vue +316 -0
- package/src/components/SnackbarService.ts +39 -0
- package/src/components/SnackbarService.vue +71 -0
- package/src/components/StudySession.types.ts +6 -0
- package/src/components/StudySession.vue +670 -0
- package/src/components/StudySessionTimer.vue +121 -0
- package/src/components/auth/UserChip.vue +106 -0
- package/src/components/auth/UserLogin.vue +141 -0
- package/src/components/auth/UserLoginAndRegistrationContainer.vue +85 -0
- package/src/components/auth/UserRegistration.vue +181 -0
- package/src/components/auth/index.ts +4 -0
- package/src/components/cardRendering/AudioAutoPlayer.vue +131 -0
- package/src/components/cardRendering/CardLoader.vue +123 -0
- package/src/components/cardRendering/CardViewer.vue +101 -0
- package/src/components/cardRendering/CodeBlockRenderer.vue +81 -0
- package/src/components/cardRendering/MarkdownRenderer.vue +46 -0
- package/src/components/cardRendering/MarkdownRendererHelpers.ts +114 -0
- package/src/components/cardRendering/MdTokenRenderer.vue +244 -0
- package/src/components/studentInputs/BaseUserInput.ts +71 -0
- package/src/components/studentInputs/MultipleChoiceOption.vue +127 -0
- package/src/components/studentInputs/RadioMultipleChoice.types.ts +6 -0
- package/src/components/studentInputs/RadioMultipleChoice.vue +168 -0
- package/src/components/studentInputs/TrueFalse.vue +27 -0
- package/src/components/studentInputs/UserInputNumber.vue +63 -0
- package/src/components/studentInputs/UserInputString.vue +89 -0
- package/src/components/studentInputs/fillInInput.vue +71 -0
- package/src/composables/CompositionViewable.ts +180 -0
- package/src/composables/Displayable.ts +133 -0
- package/src/composables/index.ts +2 -0
- package/src/index.ts +79 -0
- package/src/plugins/pinia.ts +24 -0
- package/src/stores/useAuthStore.ts +92 -0
- package/src/stores/useCardPreviewModeStore.ts +32 -0
- package/src/stores/useConfigStore.ts +60 -0
- package/src/utils/SkldrMouseTrap.ts +141 -0
- package/src/vue-shims.d.ts +5 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
class="sk-mousetrap-tooltip-wrapper"
|
|
4
|
+
ref="wrapperElement"
|
|
5
|
+
:class="[
|
|
6
|
+
isControlKeyPressed && !disabled && highlightEffect !== 'none' ? `sk-mousetrap-highlight-${highlightEffect}` : '',
|
|
7
|
+
]"
|
|
8
|
+
>
|
|
9
|
+
<slot></slot>
|
|
10
|
+
<transition name="fade">
|
|
11
|
+
<div
|
|
12
|
+
v-if="showTooltip && isControlKeyPressed && !disabled"
|
|
13
|
+
class="sk-mousetrap-tooltip"
|
|
14
|
+
:class="{
|
|
15
|
+
'sk-mt-tooltip-top': position === 'top',
|
|
16
|
+
'sk-mt-tooltip-bottom': position === 'bottom',
|
|
17
|
+
'sk-mt-tooltip-left': position === 'left',
|
|
18
|
+
'sk-mt-tooltip-right': position === 'right',
|
|
19
|
+
}"
|
|
20
|
+
>
|
|
21
|
+
{{ formattedHotkey }}
|
|
22
|
+
</div>
|
|
23
|
+
</transition>
|
|
24
|
+
</div>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script lang="ts">
|
|
28
|
+
import { defineComponent, PropType, ref, onMounted, onBeforeUnmount, computed, watch } from 'vue';
|
|
29
|
+
import { SkldrMouseTrap, HotKeyMetaData } from '../utils/SkldrMouseTrap';
|
|
30
|
+
|
|
31
|
+
export default defineComponent({
|
|
32
|
+
name: 'SkMouseTrapToolTip',
|
|
33
|
+
|
|
34
|
+
props: {
|
|
35
|
+
hotkey: {
|
|
36
|
+
type: [String, Array] as PropType<string | string[]>,
|
|
37
|
+
required: true,
|
|
38
|
+
},
|
|
39
|
+
command: {
|
|
40
|
+
type: String,
|
|
41
|
+
required: true,
|
|
42
|
+
},
|
|
43
|
+
disabled: {
|
|
44
|
+
type: Boolean,
|
|
45
|
+
default: false,
|
|
46
|
+
},
|
|
47
|
+
position: {
|
|
48
|
+
type: String as PropType<'top' | 'bottom' | 'left' | 'right'>,
|
|
49
|
+
default: 'top',
|
|
50
|
+
},
|
|
51
|
+
showTooltip: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: true,
|
|
54
|
+
},
|
|
55
|
+
highlightEffect: {
|
|
56
|
+
type: String as PropType<'glow' | 'scale' | 'border' | 'none'>,
|
|
57
|
+
default: 'glow',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
emits: ['hotkey-triggered'],
|
|
62
|
+
|
|
63
|
+
setup(props, { emit }) {
|
|
64
|
+
const wrapperElement = ref<HTMLElement | null>(null);
|
|
65
|
+
const isControlKeyPressed = ref(false);
|
|
66
|
+
const hotkeyId = ref(`hotkey-${Math.random().toString(36).substring(2, 15)}`);
|
|
67
|
+
|
|
68
|
+
// Format hotkey for display
|
|
69
|
+
const formattedHotkey = computed(() => {
|
|
70
|
+
const hotkey = Array.isArray(props.hotkey) ? props.hotkey[0] : props.hotkey;
|
|
71
|
+
// Check if this is a sequence (has spaces) or a combination (has +)
|
|
72
|
+
if (hotkey.includes(' ')) {
|
|
73
|
+
// For sequences like "g h", display as "g, h"
|
|
74
|
+
return hotkey
|
|
75
|
+
.toLowerCase()
|
|
76
|
+
.split(' ')
|
|
77
|
+
.map((part) => part.charAt(0) + part.slice(1))
|
|
78
|
+
.join(', ');
|
|
79
|
+
} else {
|
|
80
|
+
// For combinations like "ctrl+s", display as "Ctrl + S"
|
|
81
|
+
return hotkey
|
|
82
|
+
.toLowerCase()
|
|
83
|
+
.split('+')
|
|
84
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
85
|
+
.join(' + ');
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Apply highlight effect to the actual button/control when Ctrl is pressed
|
|
90
|
+
watch(
|
|
91
|
+
() => isControlKeyPressed.value,
|
|
92
|
+
(pressed) => {
|
|
93
|
+
if (!wrapperElement.value || props.disabled) return;
|
|
94
|
+
|
|
95
|
+
const clickableElement = wrapperElement.value.querySelector(
|
|
96
|
+
'button, a, input[type="button"], [role="button"]'
|
|
97
|
+
) as HTMLElement;
|
|
98
|
+
|
|
99
|
+
if (clickableElement) {
|
|
100
|
+
clickableElement.style.transition = 'all 250ms ease';
|
|
101
|
+
|
|
102
|
+
if (pressed && props.highlightEffect !== 'none') {
|
|
103
|
+
// Add slight brightness increase to the inner element
|
|
104
|
+
clickableElement.style.filter = 'brightness(1.1)';
|
|
105
|
+
} else {
|
|
106
|
+
clickableElement.style.filter = '';
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
// Handle Ctrl key detection
|
|
113
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
114
|
+
if (e.key === 'Control') {
|
|
115
|
+
isControlKeyPressed.value = true;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const handleKeyUp = (e: KeyboardEvent) => {
|
|
120
|
+
if (e.key === 'Control') {
|
|
121
|
+
isControlKeyPressed.value = false;
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Handle clicking the element when hotkey is pressed
|
|
126
|
+
const handleHotkeyPress = () => {
|
|
127
|
+
if (props.disabled || !wrapperElement.value) return;
|
|
128
|
+
|
|
129
|
+
// Try finding a clickable element within our wrapper
|
|
130
|
+
let clickableElement = wrapperElement.value.querySelector(
|
|
131
|
+
'button, a, input[type="button"], [role="button"]'
|
|
132
|
+
) as HTMLElement;
|
|
133
|
+
|
|
134
|
+
// If no standard clickable element found, try to find navigation or list items
|
|
135
|
+
if (!clickableElement) {
|
|
136
|
+
clickableElement = wrapperElement.value.querySelector(
|
|
137
|
+
'v-list-item, .v-list-item, router-link, .router-link, a, [to]'
|
|
138
|
+
) as HTMLElement;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// If still no element found, try the wrapper itself - it might be clickable
|
|
142
|
+
if (
|
|
143
|
+
!clickableElement &&
|
|
144
|
+
(wrapperElement.value.hasAttribute('to') ||
|
|
145
|
+
wrapperElement.value.tagName === 'A' ||
|
|
146
|
+
wrapperElement.value.classList.contains('v-list-item'))
|
|
147
|
+
) {
|
|
148
|
+
clickableElement = wrapperElement.value;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Get closest parent list item or router link if we found a title/content element
|
|
152
|
+
if (!clickableElement) {
|
|
153
|
+
const closestClickableParent = wrapperElement.value.closest('v-list-item, .v-list-item, a, [to]');
|
|
154
|
+
if (closestClickableParent) {
|
|
155
|
+
clickableElement = closestClickableParent as HTMLElement;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (clickableElement) {
|
|
160
|
+
if (clickableElement.hasAttribute('to')) {
|
|
161
|
+
// Handle router-link style navigation
|
|
162
|
+
const routePath = clickableElement.getAttribute('to');
|
|
163
|
+
if (routePath && window.location.pathname !== routePath) {
|
|
164
|
+
// Use parent router if available (Vue component)
|
|
165
|
+
const router = (window as any).$nuxt?.$router || (window as any).$router;
|
|
166
|
+
if (router && typeof router.push === 'function') {
|
|
167
|
+
router.push(routePath);
|
|
168
|
+
} else {
|
|
169
|
+
// Fallback to regular navigation
|
|
170
|
+
window.location.pathname = routePath;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
emit('hotkey-triggered', props.hotkey);
|
|
174
|
+
} else {
|
|
175
|
+
// Regular click for standard elements
|
|
176
|
+
clickableElement.click();
|
|
177
|
+
emit('hotkey-triggered', props.hotkey);
|
|
178
|
+
}
|
|
179
|
+
} else {
|
|
180
|
+
// If no clickable element found, emit the event for parent handling
|
|
181
|
+
console.log('No clickable element found for hotkey', props.hotkey);
|
|
182
|
+
emit('hotkey-triggered', props.hotkey);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Register/unregister the hotkey binding
|
|
187
|
+
const registerHotkey = () => {
|
|
188
|
+
if (!props.disabled) {
|
|
189
|
+
SkldrMouseTrap.addBinding({
|
|
190
|
+
hotkey: props.hotkey,
|
|
191
|
+
command: props.command,
|
|
192
|
+
callback: handleHotkeyPress,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const unregisterHotkey = () => {
|
|
198
|
+
if (!props.disabled) {
|
|
199
|
+
SkldrMouseTrap.removeBinding(props.hotkey);
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Watch for changes to the disabled prop
|
|
204
|
+
watch(
|
|
205
|
+
() => props.disabled,
|
|
206
|
+
(newValue) => {
|
|
207
|
+
if (newValue) {
|
|
208
|
+
unregisterHotkey();
|
|
209
|
+
} else {
|
|
210
|
+
registerHotkey();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
onMounted(() => {
|
|
216
|
+
// Register global keyboard listeners for the Ctrl key
|
|
217
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
218
|
+
document.addEventListener('keyup', handleKeyUp);
|
|
219
|
+
|
|
220
|
+
// Register the hotkey
|
|
221
|
+
registerHotkey();
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
onBeforeUnmount(() => {
|
|
225
|
+
// Clean up event listeners
|
|
226
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
227
|
+
document.removeEventListener('keyup', handleKeyUp);
|
|
228
|
+
|
|
229
|
+
// Unregister the hotkey
|
|
230
|
+
unregisterHotkey();
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
wrapperElement,
|
|
235
|
+
isControlKeyPressed,
|
|
236
|
+
formattedHotkey,
|
|
237
|
+
};
|
|
238
|
+
},
|
|
239
|
+
});
|
|
240
|
+
</script>
|
|
241
|
+
|
|
242
|
+
<style scoped>
|
|
243
|
+
.sk-mousetrap-tooltip-wrapper {
|
|
244
|
+
display: inline-block;
|
|
245
|
+
position: relative;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.sk-mousetrap-tooltip {
|
|
249
|
+
position: absolute;
|
|
250
|
+
background-color: rgba(0, 0, 0, 0.8);
|
|
251
|
+
color: white;
|
|
252
|
+
padding: 2px 6px;
|
|
253
|
+
border-radius: 4px;
|
|
254
|
+
font-size: 12px;
|
|
255
|
+
white-space: nowrap;
|
|
256
|
+
pointer-events: none;
|
|
257
|
+
z-index: 9999;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.sk-mt-tooltip-top {
|
|
261
|
+
bottom: 100%;
|
|
262
|
+
margin-bottom: 5px;
|
|
263
|
+
left: 50%;
|
|
264
|
+
transform: translateX(-50%);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.sk-mt-tooltip-bottom {
|
|
268
|
+
top: 100%;
|
|
269
|
+
margin-top: 5px;
|
|
270
|
+
left: 50%;
|
|
271
|
+
transform: translateX(-50%);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.sk-mt-tooltip-left {
|
|
275
|
+
right: 100%;
|
|
276
|
+
margin-right: 5px;
|
|
277
|
+
top: 50%;
|
|
278
|
+
transform: translateY(-50%);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.sk-mt-tooltip-right {
|
|
282
|
+
left: 100%;
|
|
283
|
+
margin-left: 5px;
|
|
284
|
+
top: 50%;
|
|
285
|
+
transform: translateY(-50%);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/* Highlight effects when Ctrl is pressed */
|
|
289
|
+
.sk-mousetrap-highlight-glow {
|
|
290
|
+
box-shadow: 0 0 8px 2px rgba(25, 118, 210, 0.6);
|
|
291
|
+
transition: box-shadow 250ms ease;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.sk-mousetrap-highlight-scale {
|
|
295
|
+
transform: scale(1.03);
|
|
296
|
+
transition: transform 250ms ease;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.sk-mousetrap-highlight-border {
|
|
300
|
+
outline: 2px solid rgba(25, 118, 210, 0.8);
|
|
301
|
+
outline-offset: 2px;
|
|
302
|
+
border-radius: 4px;
|
|
303
|
+
transition: outline 250ms ease, outline-offset 250ms ease;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* Fade transition */
|
|
307
|
+
.fade-enter-active,
|
|
308
|
+
.fade-leave-active {
|
|
309
|
+
transition: opacity 250ms ease;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.fade-enter-from,
|
|
313
|
+
.fade-leave-to {
|
|
314
|
+
opacity: 0;
|
|
315
|
+
}
|
|
316
|
+
</style>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// common-ui/src/components/SnackbarService.ts
|
|
2
|
+
import { Status } from '@vue-skuilder/common';
|
|
3
|
+
|
|
4
|
+
export interface SnackbarOptions {
|
|
5
|
+
text: string;
|
|
6
|
+
status: Status;
|
|
7
|
+
timeout?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Module for managing the snackbar service
|
|
11
|
+
const SnackbarServiceModule = (() => {
|
|
12
|
+
// Private variable to hold the instance
|
|
13
|
+
let _instance: { addSnack: (snack: SnackbarOptions) => void } | null = null;
|
|
14
|
+
|
|
15
|
+
return {
|
|
16
|
+
// Register the instance
|
|
17
|
+
setInstance(instance: { addSnack: (snack: SnackbarOptions) => void }): void {
|
|
18
|
+
_instance = instance;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
// Get the current instance
|
|
22
|
+
getInstance(): { addSnack: (snack: SnackbarOptions) => void } | null {
|
|
23
|
+
return _instance;
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
// Alert user function
|
|
27
|
+
alertUser(msg: SnackbarOptions): void {
|
|
28
|
+
// Try getting the instance
|
|
29
|
+
const snackBarService = _instance;
|
|
30
|
+
if (snackBarService) {
|
|
31
|
+
snackBarService.addSnack(msg);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
console.error('SnackbarService not found');
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
|
|
39
|
+
export const { setInstance, getInstance, alertUser } = SnackbarServiceModule;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<v-snackbar
|
|
4
|
+
v-for="snack in snacks"
|
|
5
|
+
:key="snacks.indexOf(snack)"
|
|
6
|
+
v-model="show[snacks.indexOf(snack)]"
|
|
7
|
+
:timeout="snack.timeout"
|
|
8
|
+
location="bottom right"
|
|
9
|
+
:color="getColor(snack)"
|
|
10
|
+
>
|
|
11
|
+
<div class="d-flex align-center justify-space-between w-100">
|
|
12
|
+
<span>{{ snack.text }}</span>
|
|
13
|
+
<v-btn icon variant="text" @click="close()">
|
|
14
|
+
<v-icon>mdi-close</v-icon>
|
|
15
|
+
</v-btn>
|
|
16
|
+
</div>
|
|
17
|
+
</v-snackbar>
|
|
18
|
+
</div>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<script lang="ts">
|
|
22
|
+
import { defineComponent } from 'vue';
|
|
23
|
+
import { Status } from '@vue-skuilder/common';
|
|
24
|
+
import { SnackbarOptions, setInstance } from './SnackbarService';
|
|
25
|
+
|
|
26
|
+
const SnackbarService = defineComponent({
|
|
27
|
+
name: 'SnackbarService',
|
|
28
|
+
|
|
29
|
+
data() {
|
|
30
|
+
return {
|
|
31
|
+
/**
|
|
32
|
+
* A history of snacks served in this session.
|
|
33
|
+
*
|
|
34
|
+
* Possible future work: write these to localstorage/pouchdb
|
|
35
|
+
* for persistance
|
|
36
|
+
*/
|
|
37
|
+
snacks: [] as SnackbarOptions[],
|
|
38
|
+
show: [] as boolean[],
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
mounted() {
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
43
|
+
setInstance(this);
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
methods: {
|
|
47
|
+
addSnack(snack: SnackbarOptions): void {
|
|
48
|
+
this.snacks.push(snack);
|
|
49
|
+
this.show.push(true);
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
close(): void {
|
|
53
|
+
this.show.pop();
|
|
54
|
+
this.show.push(false);
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
getColor(snack: SnackbarOptions): string | undefined {
|
|
58
|
+
if (snack.status === Status.ok) {
|
|
59
|
+
return 'success';
|
|
60
|
+
} else if (snack.status === Status.error) {
|
|
61
|
+
return 'error';
|
|
62
|
+
} else if (snack.status === Status.warning) {
|
|
63
|
+
return 'yellow';
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export default SnackbarService;
|
|
71
|
+
</script>
|