@dolanske/vui 0.1.0 → 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/README.md +7 -0
- package/dist/components/Accordion/Accordion.vue.d.ts +45 -0
- package/dist/components/Accordion/AccordionGroup.vue.d.ts +32 -0
- package/dist/components/Alert/Alert.vue.d.ts +29 -0
- package/dist/components/Avatar/Avatar.vue.d.ts +9 -0
- package/dist/components/Badge/Badge.vue.d.ts +21 -0
- package/dist/components/Breadcrumbs/BreadcrumbItem.vue.d.ts +21 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.vue.d.ts +27 -0
- package/dist/components/Button/Button.vue.d.ts +41 -0
- package/dist/components/ButtonGroup/ButtonGroup.vue.d.ts +19 -0
- package/dist/components/Calendar/Calendar.vue.d.ts +27 -0
- package/dist/components/Card/Card.vue.d.ts +25 -0
- package/dist/components/Checkbox/Checkbox.vue.d.ts +31 -0
- package/dist/components/CopyClipboard/CopyClipboard.vue.d.ts +40 -0
- package/dist/components/Divider/Divider.vue.d.ts +24 -0
- package/dist/components/Drawer/Drawer.vue.d.ts +52 -0
- package/dist/components/Dropdown/DropdownItem.vue.d.ts +21 -0
- package/dist/components/Dropdown/DropdownTitle.vue.d.ts +17 -0
- package/dist/components/Flex/Flex.vue.d.ts +38 -0
- package/dist/components/Grid/Grid.vue.d.ts +27 -0
- package/dist/components/Input/Counter.vue.d.ts +19 -0
- package/dist/components/Input/Dropzone.vue.d.ts +107 -0
- package/dist/components/Input/File.vue.d.ts +7 -0
- package/dist/components/Input/Input.vue.d.ts +54 -0
- package/dist/components/Input/Password.vue.d.ts +6 -0
- package/dist/components/Input/Textarea.vue.d.ts +30 -0
- package/dist/components/Kbd/Kbd.vue.d.ts +23 -0
- package/dist/components/Kbd/KbdGroup.vue.d.ts +31 -0
- package/dist/components/Modal/Confirm.vue.d.ts +45 -0
- package/dist/components/Modal/Modal.vue.d.ts +55 -0
- package/dist/components/Pagination/Pagination.vue.d.ts +42 -0
- package/dist/components/Pagination/pagination.d.ts +12 -0
- package/dist/components/Popout/Popout.vue.d.ts +34 -0
- package/dist/components/Progress/Progress.vue.d.ts +31 -0
- package/dist/components/Radio/Radio.vue.d.ts +27 -0
- package/dist/components/Radio/RadioGroup.vue.d.ts +40 -0
- package/dist/components/Select/Select.vue.d.ts +37 -0
- package/dist/components/Sheet/Sheet.vue.d.ts +35 -0
- package/dist/components/Skeleton/Skeleton.vue.d.ts +8 -0
- package/dist/components/Spinner/Spinner.vue.d.ts +6 -0
- package/dist/components/Switch/Switch.vue.d.ts +26 -0
- package/dist/components/Table/Cell.vue.d.ts +19 -0
- package/dist/components/Table/Header.vue.d.ts +29 -0
- package/dist/components/Table/Row.vue.d.ts +16 -0
- package/dist/components/Table/SelectAll.vue.d.ts +2 -0
- package/dist/components/Table/SelectRow.vue.d.ts +6 -0
- package/dist/components/Table/Table.vue.d.ts +40 -0
- package/dist/components/Table/table.d.ts +68 -0
- package/dist/components/Tabs/Tab.vue.d.ts +8 -0
- package/dist/components/Tabs/Tabs.vue.d.ts +43 -0
- package/dist/components/Toast/Toasts.vue.d.ts +2 -0
- package/dist/components/Toast/toast.d.ts +42 -0
- package/dist/components/Tooltip/Tooltip.vue.d.ts +32 -0
- package/dist/index.d.ts +54 -1
- package/dist/internal/Backdrop/Backdrop.vue.d.ts +20 -0
- package/dist/shared/composables.d.ts +3 -0
- package/dist/shared/helpers.d.ts +16 -0
- package/dist/shared/types.d.ts +10 -0
- package/dist/style.css +1 -1
- package/package.json +11 -9
- package/src/App.vue +158 -0
- package/src/components/Accordion/Accordion.vue +75 -0
- package/src/components/Accordion/AccordionGroup.vue +43 -0
- package/src/components/Accordion/accordion.scss +44 -0
- package/src/components/Alert/Alert.vue +53 -0
- package/src/components/Alert/alert.scss +80 -0
- package/src/components/Avatar/Avatar.vue +36 -0
- package/src/components/Avatar/avatar.scss +46 -0
- package/src/components/Badge/Badge.vue +21 -0
- package/src/components/Badge/badge.scss +89 -0
- package/src/components/Breadcrumbs/BreadcrumbItem.vue +26 -0
- package/src/components/Breadcrumbs/Breadcrumbs.vue +33 -0
- package/src/components/Breadcrumbs/breadcrumbs.scss +30 -0
- package/src/components/Button/Button.vue +90 -0
- package/src/components/Button/button.scss +176 -0
- package/src/components/ButtonGroup/ButtonGroup.vue +25 -0
- package/src/components/ButtonGroup/button-group.scss +51 -0
- package/src/components/Calendar/Calendar.vue +58 -0
- package/src/components/Calendar/calendar.scss +56 -0
- package/src/components/Card/Card.vue +48 -0
- package/src/components/Card/card.scss +53 -0
- package/src/components/Checkbox/Checkbox.vue +49 -0
- package/src/components/Checkbox/checkbox.scss +60 -0
- package/src/components/CopyClipboard/CopyClipboard.vue +82 -0
- package/src/components/CopyClipboard/copy-clipboard.scss +17 -0
- package/src/components/Divider/Divider.vue +34 -0
- package/src/components/Divider/divider.scss +35 -0
- package/src/components/Drawer/Drawer.vue +93 -0
- package/src/components/Drawer/drawer.scss +49 -0
- package/src/components/Dropdown/Dropdown.vue +100 -0
- package/src/components/Dropdown/DropdownItem.vue +29 -0
- package/src/components/Dropdown/DropdownTitle.vue +8 -0
- package/src/components/Dropdown/dropdown.scss +112 -0
- package/src/components/Flex/Flex.vue +109 -0
- package/src/components/Grid/Grid.vue +59 -0
- package/src/components/Input/Counter.vue +70 -0
- package/src/components/Input/Dropzone.vue +63 -0
- package/src/components/Input/File.vue +15 -0
- package/src/components/Input/Input.vue +118 -0
- package/src/components/Input/Password.vue +47 -0
- package/src/components/Input/Textarea.vue +73 -0
- package/src/components/Input/input.scss +199 -0
- package/src/components/Kbd/Kbd.vue +48 -0
- package/src/components/Kbd/KbdGroup.vue +31 -0
- package/src/components/Kbd/kbd.scss +18 -0
- package/src/components/Modal/Confirm.vue +56 -0
- package/src/components/Modal/Modal.vue +91 -0
- package/src/components/Modal/modal.scss +49 -0
- package/src/components/Pagination/Pagination.vue +74 -0
- package/src/components/Pagination/pagination.ts +78 -0
- package/src/components/Popout/Popout.vue +39 -0
- package/src/components/Popout/popout.scss +7 -0
- package/src/components/Progress/Progress.vue +84 -0
- package/src/components/Progress/progress.scss +41 -0
- package/src/components/Radio/Radio.vue +36 -0
- package/src/components/Radio/RadioGroup.vue +35 -0
- package/src/components/Radio/radio.scss +59 -0
- package/src/components/Select/Select.vue +180 -0
- package/src/components/Select/select.scss +43 -0
- package/src/components/Sheet/Sheet.vue +91 -0
- package/src/components/Sheet/sheet.scss +56 -0
- package/src/components/Skeleton/Skeleton.vue +46 -0
- package/src/components/Skeleton/skeleton.scss +14 -0
- package/src/components/Spinner/Spinner.vue +44 -0
- package/src/components/Spinner/spinner.scss +46 -0
- package/src/components/Switch/Switch.vue +30 -0
- package/src/components/Switch/switch.scss +52 -0
- package/src/components/Table/Cell.vue +23 -0
- package/src/components/Table/Header.vue +59 -0
- package/src/components/Table/Row.vue +9 -0
- package/src/components/Table/SelectAll.vue +23 -0
- package/src/components/Table/SelectRow.vue +29 -0
- package/src/components/Table/Table.vue +66 -0
- package/src/components/Table/table.scss +134 -0
- package/src/components/Table/table.ts +243 -0
- package/src/components/Tabs/Tab.vue +21 -0
- package/src/components/Tabs/Tabs.vue +76 -0
- package/src/components/Tabs/tabs.scss +78 -0
- package/src/components/Toast/Toasts.vue +47 -0
- package/src/components/Toast/toast.scss +41 -0
- package/src/components/Toast/toast.ts +92 -0
- package/src/components/Tooltip/Tooltip.vue +80 -0
- package/src/components/Tooltip/tooltip.scss +4 -0
- package/src/index.scss +1 -0
- package/src/index.ts +111 -0
- package/src/internal/Backdrop/Backdrop.vue +22 -0
- package/src/internal/Backdrop/backdrop.scss +28 -0
- package/src/main.ts +5 -0
- package/src/shared/composables.ts +18 -0
- package/src/shared/helpers.ts +53 -0
- package/src/shared/types.ts +11 -0
- package/src/style/animation.scss +21 -0
- package/src/style/core.scss +128 -0
- package/src/style/fonts.scss +0 -0
- package/src/style/layout.scss +9 -0
- package/src/style/media-query.scss +29 -0
- package/src/style/reset.scss +135 -0
- package/src/style/tooltip.scss +128 -0
- package/src/style/typography.scss +339 -0
- package/src/style/utils.scss +22 -0
- package/src/vite-env.d.ts +1 -0
|
@@ -0,0 +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>
|
|
@@ -0,0 +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
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// share some tiny global state
|
|
2
|
+
|
|
3
|
+
import { ref } from 'vue'
|
|
4
|
+
|
|
5
|
+
interface ToastAction {
|
|
6
|
+
label: string
|
|
7
|
+
handler: (toastId: number) => void
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface ToastOptions {
|
|
11
|
+
persist?: boolean
|
|
12
|
+
timeout?: number
|
|
13
|
+
action?: ToastAction
|
|
14
|
+
description?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface Toast {
|
|
18
|
+
id: number
|
|
19
|
+
// type: ToastType
|
|
20
|
+
title: string
|
|
21
|
+
action?: ToastAction
|
|
22
|
+
createdAt: number
|
|
23
|
+
expiresAt: number
|
|
24
|
+
description?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Store in a ref so the toast component can import it
|
|
28
|
+
export const toasts = ref(new Map<number, Toast>())
|
|
29
|
+
|
|
30
|
+
// Simple incremental id system
|
|
31
|
+
let id = 0
|
|
32
|
+
|
|
33
|
+
// function toast(type: ToastType, title: string, options?: ToastOptions): Toast {
|
|
34
|
+
export function pushToast(title: string, options?: ToastOptions): Toast {
|
|
35
|
+
const parsedOptions = Object.assign({
|
|
36
|
+
persist: false,
|
|
37
|
+
timeout: 7000,
|
|
38
|
+
}, options)
|
|
39
|
+
|
|
40
|
+
const newToast = {
|
|
41
|
+
id,
|
|
42
|
+
// type,
|
|
43
|
+
title,
|
|
44
|
+
persist: parsedOptions.persist,
|
|
45
|
+
description: parsedOptions.description,
|
|
46
|
+
action: parsedOptions.action,
|
|
47
|
+
createdAt: Date.now(),
|
|
48
|
+
expiresAt: Date.now() + parsedOptions.timeout,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
toasts.value.set(id, newToast)
|
|
52
|
+
|
|
53
|
+
// If options include timeout (by default) remove the toast after timeout
|
|
54
|
+
// passes
|
|
55
|
+
if (!parsedOptions.persist) {
|
|
56
|
+
setTimeout((_id: number) => {
|
|
57
|
+
toasts.value.delete(_id)
|
|
58
|
+
// Pass Id as an optional argument, becasue by the time it is executed the
|
|
59
|
+
// Id will have been increased
|
|
60
|
+
}, parsedOptions.timeout, id)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
id++
|
|
64
|
+
|
|
65
|
+
return newToast
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function removeToast(id: number): void {
|
|
69
|
+
toasts.value.delete(id)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
//////
|
|
73
|
+
|
|
74
|
+
// export const toastError: NewToastFn = (title, options) => {
|
|
75
|
+
// return pushToast('error', title, options)
|
|
76
|
+
// }
|
|
77
|
+
|
|
78
|
+
// export const toastSuccess: NewToastFn = (title, options) => {
|
|
79
|
+
// return pushToast('success', title, options)
|
|
80
|
+
// }
|
|
81
|
+
|
|
82
|
+
// export const toastInfo: NewToastFn = (title, options) => {
|
|
83
|
+
// return pushToast('info', title, options)
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
// export const toastNeutral: NewToastFn = (title, options) => {
|
|
87
|
+
// return pushToast('neutral', title, options)
|
|
88
|
+
// }
|
|
89
|
+
|
|
90
|
+
// export const toastWarning: NewToastFn = (title, options) => {
|
|
91
|
+
// return pushToast('warning', title, options)
|
|
92
|
+
// }
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
<script setup lang='ts'>
|
|
2
|
+
import type { Placement } from '@floating-ui/vue'
|
|
3
|
+
import { ref, useTemplateRef, watch } from 'vue'
|
|
4
|
+
import Popout from '../Popout/Popout.vue'
|
|
5
|
+
import './tooltip.scss'
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
/**
|
|
9
|
+
* Tooltip placement related to the anchor
|
|
10
|
+
*/
|
|
11
|
+
placement?: Placement
|
|
12
|
+
/**
|
|
13
|
+
* Amount of time user should hover the anchor until the tooltip shows up
|
|
14
|
+
*/
|
|
15
|
+
delay?: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const {
|
|
19
|
+
placement = 'bottom',
|
|
20
|
+
delay = 0,
|
|
21
|
+
} = defineProps<Props>()
|
|
22
|
+
|
|
23
|
+
const popoutAnchor = useTemplateRef('popoutAnchor')
|
|
24
|
+
// Track if user is hovering the anchor
|
|
25
|
+
const hoverAnchor = ref(false)
|
|
26
|
+
|
|
27
|
+
// Display tooltip
|
|
28
|
+
const showTooltip = ref(false)
|
|
29
|
+
|
|
30
|
+
let timeoutId: NodeJS.Timeout
|
|
31
|
+
watch(hoverAnchor, (isHovering) => {
|
|
32
|
+
if (isHovering) {
|
|
33
|
+
if (!delay || delay <= 0) {
|
|
34
|
+
showTooltip.value = true
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
clearTimeout(timeoutId)
|
|
39
|
+
|
|
40
|
+
timeoutId = setTimeout(() => {
|
|
41
|
+
// Need to reference the ref itself as this will execute without the
|
|
42
|
+
// outside scope (as far as I know tbh)
|
|
43
|
+
if (hoverAnchor.value) {
|
|
44
|
+
showTooltip.value = true
|
|
45
|
+
}
|
|
46
|
+
}, delay)
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
clearTimeout(timeoutId)
|
|
50
|
+
showTooltip.value = false
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template>
|
|
56
|
+
<div
|
|
57
|
+
ref="popoutAnchor"
|
|
58
|
+
@mouseenter="hoverAnchor = true"
|
|
59
|
+
@mouseleave="hoverAnchor = false"
|
|
60
|
+
>
|
|
61
|
+
<slot />
|
|
62
|
+
</div>
|
|
63
|
+
<Transition appear name="tooltip">
|
|
64
|
+
<Popout v-if="showTooltip" :anchor="popoutAnchor" class="vui-tooltip" :placement>
|
|
65
|
+
<slot name="tooltip" />
|
|
66
|
+
</Popout>
|
|
67
|
+
</Transition>
|
|
68
|
+
</template>
|
|
69
|
+
|
|
70
|
+
<style scoped>
|
|
71
|
+
.tooltip-enter-active,
|
|
72
|
+
.tooltip-leave-active {
|
|
73
|
+
transition: 0.1s opacity ease-in-out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.tooltip-enter-from,
|
|
77
|
+
.tooltip-leave-to {
|
|
78
|
+
opacity: 0;
|
|
79
|
+
}
|
|
80
|
+
</style>
|
package/src/index.scss
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import url(./style/core.scss);
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import Accordion from './components/Accordion/Accordion.vue'
|
|
2
|
+
import AccordionGroup from './components/Accordion/AccordionGroup.vue'
|
|
3
|
+
import Alert from './components/Alert/Alert.vue'
|
|
4
|
+
import Avatar from './components/Avatar/Avatar.vue'
|
|
5
|
+
import Badge from './components/Badge/Badge.vue'
|
|
6
|
+
import BreadcrumbItem from './components/Breadcrumbs/BreadcrumbItem.vue'
|
|
7
|
+
import Breadcrumbs from './components/Breadcrumbs/Breadcrumbs.vue'
|
|
8
|
+
import Button from './components/Button/Button.vue'
|
|
9
|
+
import ButtonGroup from './components/ButtonGroup/ButtonGroup.vue'
|
|
10
|
+
import Calendar from './components/Calendar/Calendar.vue'
|
|
11
|
+
import Card from './components/Card/Card.vue'
|
|
12
|
+
import Checkbox from './components/Checkbox/Checkbox.vue'
|
|
13
|
+
import CopyClipboard from './components/CopyClipboard/CopyClipboard.vue'
|
|
14
|
+
import Divider from './components/Divider/Divider.vue'
|
|
15
|
+
import Drawer from './components/Drawer/Drawer.vue'
|
|
16
|
+
import Dropdown from './components/Dropdown/Dropdown.vue'
|
|
17
|
+
import DropdownItem from './components/Dropdown/DropdownItem.vue'
|
|
18
|
+
import DropdownTitle from './components/Dropdown/DropdownTitle.vue'
|
|
19
|
+
import Flex from './components/Flex/Flex.vue'
|
|
20
|
+
import Grid from './components/Grid/Grid.vue'
|
|
21
|
+
import Counter from './components/Input/Counter.vue'
|
|
22
|
+
import Dropzone from './components/Input/Dropzone.vue'
|
|
23
|
+
import File from './components/Input/File.vue'
|
|
24
|
+
import Input from './components/Input/Input.vue'
|
|
25
|
+
import Password from './components/Input/Password.vue'
|
|
26
|
+
import Textarea from './components/Input/Textarea.vue'
|
|
27
|
+
import Kbd from './components/Kbd/Kbd.vue'
|
|
28
|
+
import KbdGroup from './components/Kbd/KbdGroup.vue'
|
|
29
|
+
import Confirm from './components/Modal/Confirm.vue'
|
|
30
|
+
import Modal from './components/Modal/Modal.vue'
|
|
31
|
+
import Pagination from './components/Pagination/Pagination.vue'
|
|
32
|
+
import Popout from './components/Popout/Popout.vue'
|
|
33
|
+
import Progress from './components/Progress/Progress.vue'
|
|
34
|
+
import Radio from './components/Radio/Radio.vue'
|
|
35
|
+
import RadioGroup from './components/Radio/RadioGroup.vue'
|
|
36
|
+
import Select from './components/Select/Select.vue'
|
|
37
|
+
import Sheet from './components/Sheet/Sheet.vue'
|
|
38
|
+
import Skeleton from './components/Skeleton/Skeleton.vue'
|
|
39
|
+
import Spinner from './components/Spinner/Spinner.vue'
|
|
40
|
+
import Switch from './components/Switch/Switch.vue'
|
|
41
|
+
import Cell from './components/Table/Cell.vue'
|
|
42
|
+
import Header from './components/Table/Header.vue'
|
|
43
|
+
import Row from './components/Table/Row.vue'
|
|
44
|
+
import SelectAll from './components/Table/SelectAll.vue'
|
|
45
|
+
import SelectRow from './components/Table/SelectRow.vue'
|
|
46
|
+
import Table from './components/Table/Table.vue'
|
|
47
|
+
import Tab from './components/Tabs/Tab.vue'
|
|
48
|
+
import Tabs from './components/Tabs/Tabs.vue'
|
|
49
|
+
import { pushToast, removeToast } from './components/Toast/toast'
|
|
50
|
+
import Toasts from './components/Toast/Toasts.vue'
|
|
51
|
+
import Tooltip from './components/Tooltip/Tooltip.vue'
|
|
52
|
+
import Backdrop from './internal/Backdrop/Backdrop.vue'
|
|
53
|
+
import { searchString } from './shared/helpers'
|
|
54
|
+
import './index.scss'
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
Accordion,
|
|
58
|
+
AccordionGroup,
|
|
59
|
+
Alert,
|
|
60
|
+
Avatar,
|
|
61
|
+
Backdrop,
|
|
62
|
+
Badge,
|
|
63
|
+
BreadcrumbItem,
|
|
64
|
+
Breadcrumbs,
|
|
65
|
+
Button,
|
|
66
|
+
ButtonGroup,
|
|
67
|
+
Calendar,
|
|
68
|
+
Card,
|
|
69
|
+
Cell,
|
|
70
|
+
Checkbox,
|
|
71
|
+
Confirm,
|
|
72
|
+
CopyClipboard,
|
|
73
|
+
Counter,
|
|
74
|
+
Divider,
|
|
75
|
+
Drawer,
|
|
76
|
+
Dropdown,
|
|
77
|
+
DropdownItem,
|
|
78
|
+
DropdownTitle,
|
|
79
|
+
Dropzone,
|
|
80
|
+
File,
|
|
81
|
+
Flex,
|
|
82
|
+
Grid,
|
|
83
|
+
Header,
|
|
84
|
+
Input,
|
|
85
|
+
Kbd,
|
|
86
|
+
KbdGroup,
|
|
87
|
+
Modal,
|
|
88
|
+
Pagination,
|
|
89
|
+
Password,
|
|
90
|
+
Popout,
|
|
91
|
+
Progress,
|
|
92
|
+
pushToast,
|
|
93
|
+
Radio,
|
|
94
|
+
RadioGroup,
|
|
95
|
+
removeToast,
|
|
96
|
+
Row,
|
|
97
|
+
searchString,
|
|
98
|
+
Select,
|
|
99
|
+
SelectAll,
|
|
100
|
+
SelectRow,
|
|
101
|
+
Sheet,
|
|
102
|
+
Skeleton,
|
|
103
|
+
Spinner,
|
|
104
|
+
Switch,
|
|
105
|
+
Tab,
|
|
106
|
+
Table,
|
|
107
|
+
Tabs,
|
|
108
|
+
Textarea,
|
|
109
|
+
Toasts,
|
|
110
|
+
Tooltip,
|
|
111
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { onMounted } from 'vue'
|
|
3
|
+
import './backdrop.scss'
|
|
4
|
+
|
|
5
|
+
const emits = defineEmits<{
|
|
6
|
+
(e: 'close'): void
|
|
7
|
+
}>()
|
|
8
|
+
|
|
9
|
+
onMounted(() => {
|
|
10
|
+
window.addEventListener('keydown', (e) => {
|
|
11
|
+
if (e.key === 'Escape') {
|
|
12
|
+
emits('close')
|
|
13
|
+
}
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<div class="vui-backdrop" @click.self="emits('close')">
|
|
20
|
+
<slot />
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--backdrop-offset: 64px;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.vui-backdrop {
|
|
6
|
+
z-index: 1000;
|
|
7
|
+
position: fixed;
|
|
8
|
+
display: block;
|
|
9
|
+
width: 100dvw;
|
|
10
|
+
height: 100dvh;
|
|
11
|
+
top: 0;
|
|
12
|
+
left: 0;
|
|
13
|
+
padding: var(--backdrop-offset);
|
|
14
|
+
overflow-y: auto;
|
|
15
|
+
|
|
16
|
+
&:after {
|
|
17
|
+
content: '';
|
|
18
|
+
position: fixed;
|
|
19
|
+
z-index: -1;
|
|
20
|
+
inset: 0;
|
|
21
|
+
background-color: var(--color-bg-lowered);
|
|
22
|
+
opacity: 0.9;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
html:has(.vui-backdrop) {
|
|
27
|
+
overflow: hidden;
|
|
28
|
+
}
|
package/src/main.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ComputedRef } from 'vue'
|
|
2
|
+
import type { Sizes } from './types'
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import { Size } from './types'
|
|
5
|
+
|
|
6
|
+
// Some files may share the same properties
|
|
7
|
+
export function useActualGap(gap?: Sizes | number): ComputedRef<string> {
|
|
8
|
+
return computed(() => {
|
|
9
|
+
if (typeof gap === 'number')
|
|
10
|
+
return `${gap}px`
|
|
11
|
+
switch (gap) {
|
|
12
|
+
case Size.s: return '4px'
|
|
13
|
+
case Size.l: return '16px'
|
|
14
|
+
case Size.m:
|
|
15
|
+
default: return '8px'
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export function createArray(length: number, startOffset: number = 0): number[] {
|
|
2
|
+
return Array
|
|
3
|
+
.from({ length })
|
|
4
|
+
.map((_, index) => startOffset + index)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// Searches through the input and checkes wether it contains match
|
|
8
|
+
// It searches the input by splitting it by whitespace and matching each
|
|
9
|
+
// word against the string
|
|
10
|
+
export function searchString(match: string | string[], input: string): boolean {
|
|
11
|
+
if (!match)
|
|
12
|
+
return false
|
|
13
|
+
|
|
14
|
+
const joint: string = Array.isArray(match) ? match.join(' ') : match
|
|
15
|
+
|
|
16
|
+
const split = input.trim().split(/\s+/)
|
|
17
|
+
return split.every(s => joint.toLowerCase().includes(s.toLowerCase()))
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getMaybeRefLength(value: string | number): number {
|
|
21
|
+
return typeof value === 'number' ? value : value.length
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function isNil(value: any): value is undefined {
|
|
25
|
+
return value === undefined || value === null
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Checks wether a color is light or dark, depending on
|
|
30
|
+
*/
|
|
31
|
+
export function calculateColorLightness(r: number, g: number, b: number): 'dark' | 'light' {
|
|
32
|
+
const yiq = (r * 299 + g * 587 + b * 114) / 1000
|
|
33
|
+
return yiq >= 128 ? 'light' : 'dark'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Convert a CSS rgb string to a tuple of actual r,g,b values
|
|
38
|
+
*
|
|
39
|
+
* 'rgb(12,16,24)' --> [12, 16, 24]
|
|
40
|
+
*/
|
|
41
|
+
export function stringRgbToValues(rgbString: string): [number, number, number] {
|
|
42
|
+
return rgbString.match(/\d+/g)!.map(Number) as any as [number, number, number]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function randomMinMax(min: number, max: number): number {
|
|
46
|
+
min = Math.ceil(min)
|
|
47
|
+
max = Math.floor(max)
|
|
48
|
+
return Math.floor(Math.random() * (max - min + 1)) + min
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function delay(amount: number): Promise<any> {
|
|
52
|
+
return new Promise(r => setTimeout(r, amount))
|
|
53
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export enum Size {
|
|
2
|
+
s = 's',
|
|
3
|
+
m = 'm',
|
|
4
|
+
l = 'l',
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type Sizes = 's' | 'm' | 'l'
|
|
8
|
+
|
|
9
|
+
export type DeepRequired<T> = { [K in keyof T]: DeepRequired<T[K]> } & Required<T>
|
|
10
|
+
|
|
11
|
+
export type VueClass = string | Record<string, | boolean> | Array<string | Record<string, string | boolean>>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.fade-enter-active,
|
|
2
|
+
.fade-leave-active {
|
|
3
|
+
transition: var(--transition);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.fade-enter-from,
|
|
7
|
+
.fade-leave-to {
|
|
8
|
+
opacity: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.fade-up-enter-active,
|
|
12
|
+
.fade-up-leave-active {
|
|
13
|
+
transition: var(--transition);
|
|
14
|
+
transition-property: transform, opacity;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.fade-up-enter-from,
|
|
18
|
+
.fade-up-leave-to {
|
|
19
|
+
opacity: 0;
|
|
20
|
+
transform: translateY(8px);
|
|
21
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Core of the UI library, it should only contain styles which are relevant to
|
|
2
|
+
// the library and each component should import it
|
|
3
|
+
|
|
4
|
+
// To overwrite any of these styles, simply create a style file and import it
|
|
5
|
+
// after this one
|
|
6
|
+
@use './reset.scss';
|
|
7
|
+
@use './fonts.scss';
|
|
8
|
+
|
|
9
|
+
:root {
|
|
10
|
+
--container-s: 498px;
|
|
11
|
+
--container-m: 856px;
|
|
12
|
+
--container-l: 1140px;
|
|
13
|
+
--container-xl: 1540px;
|
|
14
|
+
|
|
15
|
+
--border-radius-xs: 2px;
|
|
16
|
+
--border-radius-s: 4px;
|
|
17
|
+
--border-radius-m: 8px;
|
|
18
|
+
--border-radius-l: 12px;
|
|
19
|
+
|
|
20
|
+
--font-size-xs: 1.15rem;
|
|
21
|
+
--font-size-s: 1.3rem;
|
|
22
|
+
--font-size-ms: 1.45rem;
|
|
23
|
+
--font-size-m: 1.6rem;
|
|
24
|
+
--font-size-l: 1.65rem;
|
|
25
|
+
|
|
26
|
+
--space-xs: 8px;
|
|
27
|
+
--space-s: 12px;
|
|
28
|
+
--space-m: 18px;
|
|
29
|
+
--space-l: 26px;
|
|
30
|
+
--space-xl: 40px;
|
|
31
|
+
--space-xxl: 52px;
|
|
32
|
+
|
|
33
|
+
--transition-quick: 0.08s all ease-in-out;
|
|
34
|
+
--transition: 0.1s all ease-in-out;
|
|
35
|
+
--transition-slow: 0.3s all ease-in-out;
|
|
36
|
+
|
|
37
|
+
--color-bg: rgb(18, 18, 18);
|
|
38
|
+
--color-bg-raised: rgb(28, 28, 28);
|
|
39
|
+
--color-bg-lowered: rgb(14, 14, 14);
|
|
40
|
+
|
|
41
|
+
--color-text: rgb(231, 231, 231);
|
|
42
|
+
--color-text-light: rgb(158, 158, 158);
|
|
43
|
+
--color-text-lighter: rgb(100, 100, 100);
|
|
44
|
+
--color-text-invert: rgb(17, 17, 17);
|
|
45
|
+
|
|
46
|
+
--color-button-gray: rgb(28, 28, 28);
|
|
47
|
+
--color-button-gray-hover: rgb(38, 38, 38);
|
|
48
|
+
|
|
49
|
+
--color-text-red: rgb(243, 78, 70);
|
|
50
|
+
--color-bg-red-lowered: rgb(66, 22, 20);
|
|
51
|
+
--color-bg-red-raised: rgb(119, 31, 26);
|
|
52
|
+
--color-border-red: rgb(94, 23, 19);
|
|
53
|
+
|
|
54
|
+
--color-text-green: rgb(44, 214, 52);
|
|
55
|
+
--color-text-green-disabled: rgb(109, 193, 113);
|
|
56
|
+
--color-bg-green-lowered: rgb(19, 46, 9);
|
|
57
|
+
--color-bg-green-raised: rgb(48, 122, 22);
|
|
58
|
+
--color-border-green: rgb(27, 70, 12);
|
|
59
|
+
|
|
60
|
+
--color-text-yellow: rgb(243, 231, 70);
|
|
61
|
+
--color-bg-yellow-lowered: rgb(59, 46, 10);
|
|
62
|
+
--color-bg-yellow-raised: rgb(119, 82, 26);
|
|
63
|
+
--color-border-yellow: rgb(99, 97, 16);
|
|
64
|
+
|
|
65
|
+
--color-text-blue: rgb(85, 141, 245);
|
|
66
|
+
--color-bg-blue-lowered: rgb(10, 25, 59);
|
|
67
|
+
--color-bg-blue-raised: rgb(26, 59, 119);
|
|
68
|
+
--color-border-blue: rgb(20, 45, 112);
|
|
69
|
+
|
|
70
|
+
--color-border: rgb(38, 38, 38);
|
|
71
|
+
--color-border-strong: rgb(54, 54, 54);
|
|
72
|
+
--color-border-weak: rgb(36, 36, 36);
|
|
73
|
+
|
|
74
|
+
--color-accent: rgb(56, 214, 219);
|
|
75
|
+
--color-accent-disabled: hsl(from var(--color-accent) calc(h) calc(s * 0.5) calc(l));
|
|
76
|
+
--color-bg-accent-lowered: hsl(from var(--color-accent) calc(h) s calc(l * 0.2));
|
|
77
|
+
--color-bg-accent-raised: hsl(from var(--color-accent) calc(h) s calc(l * 0.6));
|
|
78
|
+
--color-border-accent: hsl(from var(--color-accent) calc(h) s calc(l * 0.5));
|
|
79
|
+
|
|
80
|
+
--box-shadow: 0 2px 12px rgba(8, 8, 8, 0.2);
|
|
81
|
+
--box-shadow-strong: 0 4px 15px rgba(8, 8, 8, 0.4);
|
|
82
|
+
|
|
83
|
+
--global-font: Geist, sans-serif;
|
|
84
|
+
--global-font-mono: 'Geist Mono', 'Courier New', Courier, monospace;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
:root {
|
|
88
|
+
font-family: var(--global-font);
|
|
89
|
+
font-size: 63.5%;
|
|
90
|
+
// TODO remove
|
|
91
|
+
position: relative;
|
|
92
|
+
background-color: var(--color-bg);
|
|
93
|
+
|
|
94
|
+
overflow-x: hidden;
|
|
95
|
+
width: 100%;
|
|
96
|
+
|
|
97
|
+
font-feature-settings: normal;
|
|
98
|
+
font-variation-settings: normal;
|
|
99
|
+
|
|
100
|
+
font-synthesis: none;
|
|
101
|
+
text-rendering: optimizeLegibility;
|
|
102
|
+
-webkit-font-smoothing: antialiased;
|
|
103
|
+
-moz-osx-font-smoothing: grayscale;
|
|
104
|
+
// TODO end remove
|
|
105
|
+
|
|
106
|
+
* {
|
|
107
|
+
-webkit-box-sizing: border-box;
|
|
108
|
+
-moz-box-sizing: border-box;
|
|
109
|
+
box-sizing: border-box;
|
|
110
|
+
outline: none;
|
|
111
|
+
|
|
112
|
+
&:focus-visible {
|
|
113
|
+
outline: 2px solid var(--color-text);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
body {
|
|
119
|
+
color: var(--color-text);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@import './typography.scss';
|
|
123
|
+
@import './layout.scss';
|
|
124
|
+
@import './animation.scss';
|
|
125
|
+
@import './tooltip.scss';
|
|
126
|
+
@import './utils.scss';
|
|
127
|
+
|
|
128
|
+
@import './media-query.scss';
|
|
File without changes
|