@dolanske/vui 0.3.4 → 0.5.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.
Files changed (114) hide show
  1. package/LICENSE +673 -673
  2. package/README.md +41 -40
  3. package/dist/components/Dropdown/DropdownItem.vue.d.ts +1 -0
  4. package/dist/components/Flex/Flex.vue.d.ts +3 -1
  5. package/dist/components/Grid/Grid.vue.d.ts +3 -1
  6. package/dist/components/Tabs/Tabs.vue.d.ts +4 -0
  7. package/dist/style.css +1 -1
  8. package/dist/vui.js +1547 -1534
  9. package/package.json +68 -68
  10. package/src/App.vue +176 -175
  11. package/src/components/Accordion/Accordion.vue +91 -91
  12. package/src/components/Accordion/AccordionGroup.vue +43 -43
  13. package/src/components/Accordion/accordion.scss +81 -80
  14. package/src/components/Alert/Alert.vue +53 -53
  15. package/src/components/Alert/alert.scss +80 -80
  16. package/src/components/Avatar/Avatar.vue +50 -50
  17. package/src/components/Avatar/avatar.scss +52 -52
  18. package/src/components/Badge/Badge.vue +21 -21
  19. package/src/components/Badge/badge.scss +89 -89
  20. package/src/components/Breadcrumbs/BreadcrumbItem.vue +26 -26
  21. package/src/components/Breadcrumbs/Breadcrumbs.vue +33 -33
  22. package/src/components/Breadcrumbs/breadcrumbs.scss +30 -30
  23. package/src/components/Button/Button.vue +90 -90
  24. package/src/components/Button/button.scss +178 -176
  25. package/src/components/ButtonGroup/ButtonGroup.vue +25 -25
  26. package/src/components/ButtonGroup/button-group.scss +51 -51
  27. package/src/components/Calendar/Calendar.vue +63 -60
  28. package/src/components/Calendar/calendar.scss +60 -56
  29. package/src/components/Card/Card.vue +48 -48
  30. package/src/components/Card/card.scss +53 -53
  31. package/src/components/Checkbox/Checkbox.vue +51 -52
  32. package/src/components/Checkbox/checkbox.scss +75 -66
  33. package/src/components/CopyClipboard/CopyClipboard.vue +82 -82
  34. package/src/components/CopyClipboard/copy-clipboard.scss +17 -17
  35. package/src/components/Divider/Divider.vue +44 -44
  36. package/src/components/Divider/divider.scss +35 -35
  37. package/src/components/Drawer/Drawer.vue +97 -97
  38. package/src/components/Drawer/drawer.scss +36 -36
  39. package/src/components/Dropdown/Dropdown.vue +111 -111
  40. package/src/components/Dropdown/DropdownItem.vue +33 -29
  41. package/src/components/Dropdown/DropdownTitle.vue +8 -8
  42. package/src/components/Dropdown/dropdown-item.scss +77 -0
  43. package/src/components/Dropdown/dropdown.scss +39 -117
  44. package/src/components/Flex/Flex.vue +113 -106
  45. package/src/components/Grid/Grid.vue +60 -54
  46. package/src/components/Input/Counter.vue +70 -70
  47. package/src/components/Input/Dropzone.vue +65 -65
  48. package/src/components/Input/File.vue +15 -15
  49. package/src/components/Input/Input.vue +121 -121
  50. package/src/components/Input/Password.vue +47 -47
  51. package/src/components/Input/Textarea.vue +76 -76
  52. package/src/components/Input/input.scss +208 -208
  53. package/src/components/Kbd/Kbd.vue +48 -48
  54. package/src/components/Kbd/KbdGroup.vue +31 -31
  55. package/src/components/Kbd/kbd.scss +18 -18
  56. package/src/components/Modal/Confirm.vue +56 -56
  57. package/src/components/Modal/Modal.vue +91 -91
  58. package/src/components/Modal/modal.scss +49 -49
  59. package/src/components/OTP/OTP.vue +133 -133
  60. package/src/components/OTP/OTPItem.vue +37 -37
  61. package/src/components/OTP/otp.scss +83 -83
  62. package/src/components/Pagination/Pagination.vue +74 -74
  63. package/src/components/Pagination/pagination.ts +78 -78
  64. package/src/components/Popout/Popout.vue +42 -42
  65. package/src/components/Popout/popout.scss +8 -8
  66. package/src/components/Progress/Progress.vue +90 -90
  67. package/src/components/Progress/progress.scss +41 -41
  68. package/src/components/Radio/Radio.vue +36 -36
  69. package/src/components/Radio/RadioGroup.vue +40 -40
  70. package/src/components/Radio/radio.scss +68 -59
  71. package/src/components/Select/Select.vue +180 -180
  72. package/src/components/Select/select.scss +44 -44
  73. package/src/components/Sheet/Sheet.vue +92 -92
  74. package/src/components/Sheet/sheet.scss +60 -60
  75. package/src/components/Sidebar/Sidebar.vue +102 -0
  76. package/src/components/Sidebar/sidebar.scss +123 -0
  77. package/src/components/Skeleton/Skeleton.vue +43 -43
  78. package/src/components/Skeleton/skeleton.scss +14 -14
  79. package/src/components/Spinner/Spinner.vue +42 -42
  80. package/src/components/Spinner/spinner.scss +46 -46
  81. package/src/components/Switch/Switch.vue +30 -30
  82. package/src/components/Switch/switch.scss +60 -52
  83. package/src/components/Table/Cell.vue +23 -23
  84. package/src/components/Table/Header.vue +59 -59
  85. package/src/components/Table/Row.vue +9 -9
  86. package/src/components/Table/SelectAll.vue +23 -23
  87. package/src/components/Table/SelectRow.vue +29 -29
  88. package/src/components/Table/Table.vue +66 -66
  89. package/src/components/Table/table.scss +134 -134
  90. package/src/components/Table/table.ts +244 -244
  91. package/src/components/Tabs/Tab.vue +27 -27
  92. package/src/components/Tabs/Tabs.vue +89 -82
  93. package/src/components/Tabs/tabs.scss +80 -79
  94. package/src/components/Toast/Toasts.vue +47 -47
  95. package/src/components/Toast/toast.scss +41 -41
  96. package/src/components/Toast/toast.ts +68 -68
  97. package/src/components/Tooltip/Tooltip.vue +86 -86
  98. package/src/components/Tooltip/tooltip.scss +4 -4
  99. package/src/index.scss +1 -1
  100. package/src/index.ts +119 -119
  101. package/src/internal/Backdrop/Backdrop.vue +22 -22
  102. package/src/internal/Backdrop/backdrop.scss +28 -28
  103. package/src/main.ts +5 -5
  104. package/src/shared/helpers.ts +74 -74
  105. package/src/shared/types.ts +29 -29
  106. package/src/style/animation.scss +21 -21
  107. package/src/style/core.scss +150 -148
  108. package/src/style/layout.scss +168 -136
  109. package/src/style/media-query.scss +29 -29
  110. package/src/style/reset.scss +135 -135
  111. package/src/style/{fonts.scss → text.scss} +74 -53
  112. package/src/style/tooltip.scss +128 -128
  113. package/src/style/typography.scss +338 -338
  114. package/src/style/utils.scss +36 -36
@@ -1,82 +1,89 @@
1
- <script setup lang="ts">
2
- import type { TabProps } from './Tab.vue'
3
- import { useEventListener } from '@vueuse/core'
4
- import { onMounted, useTemplateRef, type VNode, watch } from 'vue'
5
- import './tabs.scss'
6
-
7
- interface Props {
8
- variant?: 'default' | 'filled'
9
- expand?: boolean
10
- disabled?: boolean
11
- }
12
-
13
- const {
14
- expand,
15
- disabled,
16
- variant = 'default',
17
- } = defineProps<Props>()
18
-
19
- const slots = defineSlots<{
20
- default: () => Array<VNode & { props: TabProps }>
21
- }>()
22
-
23
- const active = defineModel()
24
-
25
- // Underline calculation
26
- const underlineRef = useTemplateRef('underline')
27
- const tabsRef = useTemplateRef('tabs')
28
-
29
- function computeUnderlinePosition() {
30
- if (!window)
31
- return
32
-
33
- if (tabsRef.value && underlineRef.value) {
34
- const activeBounds = tabsRef.value.querySelector('.vui-tab.active')?.getBoundingClientRect()
35
- const parentBounds = tabsRef.value.getBoundingClientRect()
36
- if (!activeBounds || !parentBounds)
37
- return
38
-
39
- underlineRef.value.style.width = `${activeBounds.width}px`
40
- underlineRef.value.style.left = `${activeBounds.left - parentBounds.left}px`
41
- }
42
- }
43
-
44
- onMounted(() => {
45
- useEventListener(window, 'resize', computeUnderlinePosition)
46
-
47
- watch(
48
- [active, () => expand],
49
- computeUnderlinePosition,
50
- {
51
- immediate: true,
52
- flush: 'post',
53
- },
54
- )
55
- })
56
- </script>
57
-
58
- <template>
59
- <div
60
- ref="tabs"
61
- class="vui-tabs"
62
- role="tablist"
63
- :class="[
64
- { expand, disabled },
65
- variant === 'default'
66
- ? ''
67
- : `vui-tabs-variant-${variant}`,
68
- ]"
69
- >
70
- <Component
71
- :is="vnode"
72
- v-for="vnode of slots.default()"
73
- :key="vnode.props.id"
74
- :class="{ active: vnode.props.id === active }"
75
- @click="active = vnode.props.id"
76
- />
77
-
78
- <Transition name="fade" appear>
79
- <div ref="underline" class="vui-tab-underline" />
80
- </Transition>
81
- </div>
82
- </template>
1
+ <script setup lang="ts">
2
+ import type { TabProps } from './Tab.vue'
3
+ import { useResizeObserver } from '@vueuse/core'
4
+ import { onMounted, useTemplateRef, type VNode, watch } from 'vue'
5
+ import './tabs.scss'
6
+
7
+ interface Props {
8
+ variant?: 'default' | 'filled'
9
+ expand?: boolean
10
+ disabled?: boolean
11
+ }
12
+
13
+ const {
14
+ expand,
15
+ disabled,
16
+ variant = 'default',
17
+ } = defineProps<Props>()
18
+
19
+ const slots = defineSlots<{
20
+ default: () => Array<VNode & { props: TabProps }>
21
+ start: unknown
22
+ end: unknown
23
+ }>()
24
+
25
+ const active = defineModel()
26
+
27
+ // Underline calculation
28
+ const underlineRef = useTemplateRef('underline')
29
+ const tabsRef = useTemplateRef('tabs')
30
+
31
+ function computeUnderlinePosition() {
32
+ if (!window)
33
+ return
34
+
35
+ if (tabsRef.value && underlineRef.value) {
36
+ const activeBounds = tabsRef.value.querySelector('.vui-tab.active')?.getBoundingClientRect()
37
+ const parentBounds = tabsRef.value.getBoundingClientRect()
38
+ if (!activeBounds || !parentBounds)
39
+ return
40
+
41
+ underlineRef.value.style.width = `${activeBounds.width}px`
42
+ underlineRef.value.style.left = `${activeBounds.left - parentBounds.left}px`
43
+ }
44
+ }
45
+
46
+ onMounted(() => {
47
+ useResizeObserver(tabsRef, computeUnderlinePosition)
48
+
49
+ watch(
50
+ [active, () => expand],
51
+ computeUnderlinePosition,
52
+ {
53
+ immediate: true,
54
+ flush: 'post',
55
+ },
56
+ )
57
+ })
58
+ </script>
59
+
60
+ <template>
61
+ <div
62
+ ref="tabs"
63
+ class="vui-tabs"
64
+ role="tablist"
65
+ :class="[
66
+ { expand, disabled },
67
+ variant === 'default'
68
+ ? ''
69
+ : `vui-tabs-variant-${variant}`,
70
+ ]"
71
+ >
72
+ <slot name="start" />
73
+ <Component
74
+ :is="vnode"
75
+ v-for="vnode of slots.default()"
76
+ :key="vnode.props.id"
77
+ :class="{ active: vnode.props.id === active }"
78
+ @click="active = vnode.props.id"
79
+ />
80
+ <template v-if="slots.end">
81
+ <div v-if="!!!expand" class="flex-1" />
82
+ <slot name="end" />
83
+ </template>
84
+
85
+ <Transition name="fade" appear>
86
+ <div ref="underline" class="vui-tab-underline" />
87
+ </Transition>
88
+ </div>
89
+ </template>
@@ -1,79 +1,80 @@
1
- .vui-tabs {
2
- display: flex;
3
- width: 100%;
4
- gap: 4px;
5
- border-bottom: 1px solid var(--color-border);
6
- position: relative;
7
-
8
- &.vui-tabs-variant-filled {
9
- background-color: var(--color-bg-raised);
10
- border-bottom: none;
11
- z-index: 1;
12
- border-radius: var(--border-radius-m);
13
- padding-inline: 4px;
14
-
15
- .vui-tab-underline {
16
- border-bottom: none;
17
- background-color: var(--color-bg-lowered);
18
- top: 4px;
19
- bottom: 4px;
20
- z-index: -1;
21
- border-radius: var(--border-radius-m);
22
- }
23
- }
24
-
25
- &.disabled .vui-tab,
26
- .vui-tab.disabled {
27
- pointer-events: none;
28
- color: var(--color-text-lighter);
29
-
30
- &.active {
31
- color: var(--color-text-lighter) !important;
32
- }
33
- }
34
-
35
- &.disabled {
36
- .vui-tab-underline {
37
- border-color: var(--color-text-lighter);
38
- }
39
- }
40
-
41
- &.expand .vui-tab {
42
- flex: 1;
43
- }
44
-
45
- .vui-tab {
46
- display: flex;
47
- height: 40px;
48
- // place-content: center;
49
- align-items: center;
50
- justify-content: center;
51
- padding: 0 10px;
52
- font-size: var(--font-size-ms);
53
- position: relative;
54
- color: var(--color-text-light);
55
- transition: var(--transition);
56
- cursor: default;
57
- gap: var(--space-xs);
58
- border-radius: var(--border-radius-m);
59
-
60
- svg {
61
- width: 20px;
62
- height: 20px;
63
- color: var(--color-text-light);
64
- }
65
-
66
- &:hover,
67
- &.active {
68
- color: var(--color-text);
69
- }
70
- }
71
-
72
- .vui-tab-underline {
73
- transition: var(--transition);
74
- display: block;
75
- border-bottom: 1px solid var(--color-text);
76
- position: absolute;
77
- bottom: 0;
78
- }
79
- }
1
+ .vui-tabs {
2
+ display: flex;
3
+ width: 100%;
4
+ gap: 4px;
5
+ align-items: center;
6
+ border-bottom: 1px solid var(--color-border);
7
+ position: relative;
8
+
9
+ &.vui-tabs-variant-filled {
10
+ background-color: var(--color-bg-raised);
11
+ border-bottom: none;
12
+ z-index: 1;
13
+ border-radius: var(--border-radius-m);
14
+ padding-inline: 4px;
15
+
16
+ .vui-tab-underline {
17
+ border-bottom: none;
18
+ background-color: var(--color-bg-lowered);
19
+ top: 4px;
20
+ bottom: 4px;
21
+ z-index: -1;
22
+ border-radius: var(--border-radius-m);
23
+ }
24
+ }
25
+
26
+ &.disabled .vui-tab,
27
+ .vui-tab.disabled {
28
+ pointer-events: none;
29
+ color: var(--color-text-lighter);
30
+
31
+ &.active {
32
+ color: var(--color-text-lighter) !important;
33
+ }
34
+ }
35
+
36
+ &.disabled {
37
+ .vui-tab-underline {
38
+ border-color: var(--color-text-lighter);
39
+ }
40
+ }
41
+
42
+ &.expand .vui-tab {
43
+ flex: 1;
44
+ }
45
+
46
+ .vui-tab {
47
+ display: flex;
48
+ height: 40px;
49
+ // place-content: center;
50
+ align-items: center;
51
+ justify-content: center;
52
+ padding: 0 10px;
53
+ font-size: var(--font-size-ms);
54
+ position: relative;
55
+ color: var(--color-text-light);
56
+ transition: var(--transition);
57
+ cursor: default;
58
+ gap: var(--space-xs);
59
+ border-radius: var(--border-radius-m);
60
+
61
+ svg {
62
+ width: 20px;
63
+ height: 20px;
64
+ color: var(--color-text-light);
65
+ }
66
+
67
+ &:hover,
68
+ &.active {
69
+ color: var(--color-text);
70
+ }
71
+ }
72
+
73
+ .vui-tab-underline {
74
+ transition: var(--transition);
75
+ display: block;
76
+ border-bottom: 1px solid var(--color-text);
77
+ position: absolute;
78
+ bottom: 0;
79
+ }
80
+ }
@@ -1,47 +1,47 @@
1
- <script setup lang="ts">
2
- import Button from '../Button/Button.vue'
3
- import { toasts } from './toast'
4
- import './toast.scss'
5
- </script>
6
-
7
- <template>
8
- <Teleport to="body">
9
- <div class="vui-toast-wrapper">
10
- <TransitionGroup name="toast" tag="ul" class="vui-toast-list">
11
- <li v-for="[toastId, toast] in toasts" :key="toastId" class="vui-toast-item">
12
- <div class="vui-toast-item-content">
13
- <strong>{{ toast.title }}</strong>
14
- <p v-if="toast.description">
15
- {{ toast.description }}
16
- </p>
17
- </div>
18
- <Button v-if="toast.action" @click="toast.action.handler(toast.id)">
19
- {{ toast.action.label }}
20
- </Button>
21
- </li>
22
- </TransitionGroup>
23
- </div>
24
- </Teleport>
25
- </template>
26
-
27
- <style scoped>
28
- .toast-move,
29
- .toast-enter-active,
30
- .toast-leave-active {
31
- transition: var(--transition);
32
- }
33
-
34
- .toast-enter-from {
35
- opacity: 0;
36
- transform: translateY(24px) scale(0.95);
37
- }
38
-
39
- .toast-leave-to {
40
- opacity: 0;
41
- transform: translateY(-24px) scale(0.95);
42
- }
43
-
44
- .toast-leave-active {
45
- position: absolute;
46
- }
47
- </style>
1
+ <script setup lang="ts">
2
+ import Button from '../Button/Button.vue'
3
+ import { toasts } from './toast'
4
+ import './toast.scss'
5
+ </script>
6
+
7
+ <template>
8
+ <Teleport to="body">
9
+ <div class="vui-toast-wrapper">
10
+ <TransitionGroup name="toast" tag="ul" class="vui-toast-list">
11
+ <li v-for="[toastId, toast] in toasts" :key="toastId" class="vui-toast-item">
12
+ <div class="vui-toast-item-content">
13
+ <strong>{{ toast.title }}</strong>
14
+ <p v-if="toast.description">
15
+ {{ toast.description }}
16
+ </p>
17
+ </div>
18
+ <Button v-if="toast.action" @click="toast.action.handler(toast.id)">
19
+ {{ toast.action.label }}
20
+ </Button>
21
+ </li>
22
+ </TransitionGroup>
23
+ </div>
24
+ </Teleport>
25
+ </template>
26
+
27
+ <style scoped>
28
+ .toast-move,
29
+ .toast-enter-active,
30
+ .toast-leave-active {
31
+ transition: var(--transition);
32
+ }
33
+
34
+ .toast-enter-from {
35
+ opacity: 0;
36
+ transform: translateY(24px) scale(0.95);
37
+ }
38
+
39
+ .toast-leave-to {
40
+ opacity: 0;
41
+ transform: translateY(-24px) scale(0.95);
42
+ }
43
+
44
+ .toast-leave-active {
45
+ position: absolute;
46
+ }
47
+ </style>
@@ -1,41 +1,41 @@
1
- .vui-toast-wrapper {
2
- position: fixed;
3
- bottom: 32px;
4
- right: 32px;
5
- width: 100%;
6
- max-width: 392px;
7
-
8
- .vui-toast-list {
9
- display: flex;
10
- flex-direction: column;
11
- gap: var(--space-xs);
12
-
13
- .vui-toast-item {
14
- display: flex;
15
- border: 1px solid var(--color-border);
16
- border-radius: var(--border-radius-m);
17
- padding: var(--space-m) var(--space-s);
18
- background-color: var(--color-bg);
19
- width: 100%;
20
- align-items: center;
21
- gap: var(--space-m);
22
- box-shadow: var(--box-shadow);
23
-
24
- .vui-toast-item-content {
25
- flex: 1;
26
-
27
- strong {
28
- color: var(--color-text);
29
- margin-bottom: var(--space-xs);
30
- display: block;
31
- font-size: var(--font-size-m);
32
- }
33
-
34
- p {
35
- color: var(--color-text-lighter);
36
- font-size: var(--font-size-s);
37
- }
38
- }
39
- }
40
- }
41
- }
1
+ .vui-toast-wrapper {
2
+ position: fixed;
3
+ bottom: 32px;
4
+ right: 32px;
5
+ width: 100%;
6
+ max-width: 392px;
7
+
8
+ .vui-toast-list {
9
+ display: flex;
10
+ flex-direction: column;
11
+ gap: var(--space-xs);
12
+
13
+ .vui-toast-item {
14
+ display: flex;
15
+ border: 1px solid var(--color-border);
16
+ border-radius: var(--border-radius-m);
17
+ padding: var(--space-m) var(--space-s);
18
+ background-color: var(--color-bg);
19
+ width: 100%;
20
+ align-items: center;
21
+ gap: var(--space-m);
22
+ box-shadow: var(--box-shadow);
23
+
24
+ .vui-toast-item-content {
25
+ flex: 1;
26
+
27
+ strong {
28
+ color: var(--color-text);
29
+ margin-bottom: var(--space-xs);
30
+ display: block;
31
+ font-size: var(--font-size-m);
32
+ }
33
+
34
+ p {
35
+ color: var(--color-text-lighter);
36
+ font-size: var(--font-size-s);
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
@@ -1,68 +1,68 @@
1
- import { ref } from 'vue'
2
-
3
- interface ToastAction {
4
- label: string
5
- handler: (toastId: number) => void
6
- }
7
-
8
- interface ToastOptions {
9
- persist?: boolean
10
- timeout?: number
11
- action?: ToastAction
12
- description?: string
13
- }
14
-
15
- interface Toast {
16
- id: number
17
- // type: ToastType
18
- title: string
19
- action?: ToastAction
20
- createdAt: number
21
- expiresAt: number
22
- description?: string
23
- }
24
-
25
- // Store in a ref so the toast component can import it
26
- export const toasts = ref(new Map<number, Toast>())
27
-
28
- // Simple incremental id system
29
- let id = 0
30
-
31
- // function toast(type: ToastType, title: string, options?: ToastOptions): Toast {
32
- export function pushToast(title: string, options?: ToastOptions): Toast {
33
- const parsedOptions = Object.assign({
34
- persist: false,
35
- timeout: 7000,
36
- }, options)
37
-
38
- const newToast = {
39
- id,
40
- // type,
41
- title,
42
- persist: parsedOptions.persist,
43
- description: parsedOptions.description,
44
- action: parsedOptions.action,
45
- createdAt: Date.now(),
46
- expiresAt: Date.now() + parsedOptions.timeout,
47
- }
48
-
49
- toasts.value.set(id, newToast)
50
-
51
- // If options include timeout (by default) remove the toast after timeout
52
- // passes
53
- if (!parsedOptions.persist) {
54
- setTimeout((_id: number) => {
55
- toasts.value.delete(_id)
56
- // Pass Id as an optional argument, becasue by the time it is executed the
57
- // Id will have been increased
58
- }, parsedOptions.timeout, id)
59
- }
60
-
61
- id++
62
-
63
- return newToast
64
- }
65
-
66
- export function removeToast(id: number): void {
67
- toasts.value.delete(id)
68
- }
1
+ import { ref } from 'vue'
2
+
3
+ interface ToastAction {
4
+ label: string
5
+ handler: (toastId: number) => void
6
+ }
7
+
8
+ interface ToastOptions {
9
+ persist?: boolean
10
+ timeout?: number
11
+ action?: ToastAction
12
+ description?: string
13
+ }
14
+
15
+ interface Toast {
16
+ id: number
17
+ // type: ToastType
18
+ title: string
19
+ action?: ToastAction
20
+ createdAt: number
21
+ expiresAt: number
22
+ description?: string
23
+ }
24
+
25
+ // Store in a ref so the toast component can import it
26
+ export const toasts = ref(new Map<number, Toast>())
27
+
28
+ // Simple incremental id system
29
+ let id = 0
30
+
31
+ // function toast(type: ToastType, title: string, options?: ToastOptions): Toast {
32
+ export function pushToast(title: string, options?: ToastOptions): Toast {
33
+ const parsedOptions = Object.assign({
34
+ persist: false,
35
+ timeout: 7000,
36
+ }, options)
37
+
38
+ const newToast = {
39
+ id,
40
+ // type,
41
+ title,
42
+ persist: parsedOptions.persist,
43
+ description: parsedOptions.description,
44
+ action: parsedOptions.action,
45
+ createdAt: Date.now(),
46
+ expiresAt: Date.now() + parsedOptions.timeout,
47
+ }
48
+
49
+ toasts.value.set(id, newToast)
50
+
51
+ // If options include timeout (by default) remove the toast after timeout
52
+ // passes
53
+ if (!parsedOptions.persist) {
54
+ setTimeout((_id: number) => {
55
+ toasts.value.delete(_id)
56
+ // Pass Id as an optional argument, becasue by the time it is executed the
57
+ // Id will have been increased
58
+ }, parsedOptions.timeout, id)
59
+ }
60
+
61
+ id++
62
+
63
+ return newToast
64
+ }
65
+
66
+ export function removeToast(id: number): void {
67
+ toasts.value.delete(id)
68
+ }