@dolanske/vui 0.5.0 → 1.0.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 +5 -4
- package/dist/components/Accordion/Accordion.vue.d.ts +3 -2
- package/dist/components/Accordion/AccordionGroup.vue.d.ts +5 -2
- package/dist/components/Alert/Alert.vue.d.ts +10 -3
- package/dist/components/Avatar/Avatar.vue.d.ts +16 -1
- package/dist/components/Badge/Badge.vue.d.ts +4 -3
- package/dist/components/Breadcrumbs/BreadcrumbItem.vue.d.ts +4 -3
- package/dist/components/Breadcrumbs/Breadcrumbs.vue.d.ts +3 -2
- package/dist/components/Button/Button.vue.d.ts +8 -17
- package/dist/components/ButtonGroup/ButtonGroup.vue.d.ts +5 -2
- package/dist/components/Calendar/Calendar.vue.d.ts +7 -7
- package/dist/components/Card/Card.vue.d.ts +4 -3
- package/dist/components/Checkbox/Checkbox.vue.d.ts +8 -6
- package/dist/components/CopyClipboard/CopyClipboard.vue.d.ts +2 -1
- package/dist/components/Divider/Divider.vue.d.ts +3 -2
- package/dist/components/Drawer/Drawer.vue.d.ts +6 -5
- package/dist/components/Dropdown/Dropdown.vue.d.ts +84 -6
- package/dist/components/Dropdown/DropdownItem.vue.d.ts +3 -2
- package/dist/components/Dropdown/DropdownTitle.vue.d.ts +6 -2
- package/dist/components/Flex/Flex.vue.d.ts +3 -2
- package/dist/components/Grid/Grid.vue.d.ts +7 -3
- package/dist/components/Input/Color.vue.d.ts +11 -0
- package/dist/components/Input/Counter.vue.d.ts +5 -5
- package/dist/components/Input/Dropzone.vue.d.ts +96 -11
- package/dist/components/Input/File.vue.d.ts +4 -3
- package/dist/components/Input/Input.vue.d.ts +9 -8
- package/dist/components/Input/Password.vue.d.ts +1 -1
- package/dist/components/Input/Textarea.vue.d.ts +7 -6
- package/dist/components/Kbd/Kbd.vue.d.ts +1 -1
- package/dist/components/Kbd/KbdGroup.vue.d.ts +5 -12
- package/dist/components/Modal/Confirm.vue.d.ts +7 -6
- package/dist/components/Modal/Modal.vue.d.ts +7 -6
- package/dist/components/OTP/OTP.vue.d.ts +7 -6
- package/dist/components/OTP/OTPItem.vue.d.ts +1 -1
- package/dist/components/Pagination/Pagination.vue.d.ts +6 -2
- package/dist/components/Popout/Popout.vue.d.ts +11 -3
- package/dist/components/Progress/Progress.vue.d.ts +7 -5
- package/dist/components/Radio/Radio.vue.d.ts +8 -6
- package/dist/components/Radio/RadioGroup.vue.d.ts +7 -6
- package/dist/components/Select/Select.vue.d.ts +6 -8
- package/dist/components/Sheet/Sheet.vue.d.ts +9 -5
- package/dist/components/Sidebar/Sidebar.vue.d.ts +70 -0
- package/dist/components/Skeleton/Skeleton.vue.d.ts +1 -1
- package/dist/components/Spinner/Spinner.vue.d.ts +1 -1
- package/dist/components/Switch/Switch.vue.d.ts +8 -6
- package/dist/components/Table/Cell.vue.d.ts +5 -2
- package/dist/components/Table/{Header.vue.d.ts → Head.vue.d.ts} +3 -2
- package/dist/components/Table/{Table.vue.d.ts → Root.vue.d.ts} +3 -2
- package/dist/components/Table/index.d.ts +6 -0
- package/dist/components/Table/table.d.ts +3 -3
- package/dist/components/Tabs/Tab.vue.d.ts +17 -3
- package/dist/components/Tabs/Tabs.vue.d.ts +8 -7
- package/dist/components/Toast/toast.d.ts +245 -0
- package/dist/components/Tooltip/Tooltip.vue.d.ts +2 -1
- package/dist/index.d.ts +5 -7
- package/dist/internal/Backdrop/Backdrop.vue.d.ts +3 -2
- package/dist/shared/helpers.d.ts +9 -0
- package/dist/shared/theme.d.ts +3 -0
- package/dist/vui.css +1 -0
- package/dist/vui.js +7160 -6355
- package/package.json +22 -18
- package/src/App.vue +90 -171
- package/src/components/Accordion/accordion.scss +1 -0
- package/src/components/Alert/Alert.vue +11 -5
- package/src/components/Alert/alert.scss +104 -23
- package/src/components/Avatar/Avatar.vue +4 -1
- package/src/components/Avatar/avatar.scss +1 -1
- package/src/components/Badge/Badge.vue +1 -1
- package/src/components/Badge/badge.scss +134 -17
- package/src/components/Breadcrumbs/BreadcrumbItem.vue +2 -2
- package/src/components/Breadcrumbs/Breadcrumbs.vue +1 -2
- package/src/components/Breadcrumbs/breadcrumbs.scss +2 -1
- package/src/components/Button/Button.vue +15 -20
- package/src/components/Button/button.scss +156 -55
- package/src/components/ButtonGroup/ButtonGroup.vue +4 -1
- package/src/components/ButtonGroup/button-group.scss +2 -2
- package/src/components/Calendar/Calendar.vue +4 -1
- package/src/components/Calendar/calendar.scss +25 -2
- package/src/components/Card/Card.vue +2 -2
- package/src/components/Card/card.scss +4 -4
- package/src/components/Checkbox/Checkbox.vue +4 -1
- package/src/components/Checkbox/checkbox.scss +17 -12
- package/src/components/CopyClipboard/CopyClipboard.vue +15 -6
- package/src/components/CopyClipboard/copy-clipboard.scss +10 -2
- package/src/components/Drawer/Drawer.vue +4 -4
- package/src/components/Drawer/drawer.scss +1 -0
- package/src/components/Dropdown/Dropdown.vue +44 -20
- package/src/components/Dropdown/DropdownItem.vue +4 -4
- package/src/components/Dropdown/DropdownTitle.vue +7 -1
- package/src/components/Dropdown/dropdown-item.scss +9 -2
- package/src/components/Dropdown/dropdown.scss +21 -7
- package/src/components/Grid/Grid.vue +21 -1
- package/src/components/Input/Color.vue +26 -0
- package/src/components/Input/Counter.vue +12 -16
- package/src/components/Input/Dropzone.vue +1 -1
- package/src/components/Input/File.vue +1 -1
- package/src/components/Input/Input.vue +8 -6
- package/src/components/Input/Password.vue +1 -13
- package/src/components/Input/Textarea.vue +4 -2
- package/src/components/Input/input.scss +110 -16
- package/src/components/Kbd/KbdGroup.vue +2 -6
- package/src/components/Kbd/kbd.scss +6 -5
- package/src/components/Modal/Confirm.vue +1 -1
- package/src/components/Modal/Modal.vue +23 -15
- package/src/components/Modal/modal.scss +11 -6
- package/src/components/OTP/otp.scss +8 -7
- package/src/components/Pagination/Pagination.vue +6 -3
- package/src/components/Popout/Popout.vue +15 -5
- package/src/components/Popout/popout.scss +8 -1
- package/src/components/Progress/Progress.vue +18 -5
- package/src/components/Progress/progress.scss +7 -1
- package/src/components/Radio/Radio.vue +4 -2
- package/src/components/Radio/radio.scss +18 -8
- package/src/components/Select/Select.vue +49 -18
- package/src/components/Select/select.scss +35 -2
- package/src/components/Sheet/Sheet.vue +8 -2
- package/src/components/Sheet/sheet.scss +9 -0
- package/src/components/Sidebar/Sidebar.vue +24 -11
- package/src/components/Sidebar/sidebar.scss +6 -5
- package/src/components/Spinner/spinner.scss +2 -1
- package/src/components/Switch/Switch.vue +4 -3
- package/src/components/Switch/switch.scss +39 -6
- package/src/components/Table/{Header.vue → Head.vue} +5 -5
- package/src/components/Table/{Table.vue → Root.vue} +2 -2
- package/src/components/Table/SelectRow.vue +2 -1
- package/src/components/Table/index.ts +7 -0
- package/src/components/Table/table.scss +25 -5
- package/src/components/Table/table.ts +7 -3
- package/src/components/Tabs/Tab.vue +7 -9
- package/src/components/Tabs/Tabs.vue +5 -4
- package/src/components/Tabs/tabs.scss +10 -3
- package/src/components/Toast/Toasts.vue +5 -0
- package/src/components/Toast/toast.scss +6 -2
- package/src/components/Toast/toast.ts +7 -0
- package/src/components/Tooltip/Tooltip.vue +9 -9
- package/src/components/Tooltip/tooltip.scss +4 -0
- package/src/examples/ExampleAccordions.vue +58 -0
- package/src/examples/ExampleAlerts.vue +78 -0
- package/src/examples/ExampleAvatars.vue +44 -0
- package/src/examples/ExampleBadges.vue +48 -0
- package/src/examples/ExampleBreadcrumbs.vue +46 -0
- package/src/examples/ExampleButtons.vue +140 -0
- package/src/examples/ExampleCalendars.vue +40 -0
- package/src/examples/ExampleCards.vue +94 -0
- package/src/examples/ExampleCheckboxes.vue +123 -0
- package/src/examples/ExampleCopyClipboard.vue +47 -0
- package/src/examples/ExampleDividers.vue +39 -0
- package/src/examples/ExampleDrawers.vue +67 -0
- package/src/examples/ExampleDropdowns.vue +114 -0
- package/src/examples/ExampleFlexGrid.vue +122 -0
- package/src/examples/ExampleInputs.vue +234 -0
- package/src/examples/ExampleKBD.vue +65 -0
- package/src/examples/ExampleModals.vue +143 -0
- package/src/examples/ExamplePalette.vue +159 -0
- package/src/examples/ExamplePopouts.vue +41 -0
- package/src/examples/ExampleSheets.vue +77 -0
- package/src/examples/ExampleSidebars.vue +270 -0
- package/src/examples/ExampleSkeletons.vue +26 -0
- package/src/examples/ExampleSpinners.vue +78 -0
- package/src/examples/ExampleTables.vue +195 -0
- package/src/examples/ExampleTabs.vue +119 -0
- package/src/examples/ExampleToasts.vue +96 -0
- package/src/examples/ExampleTooltips.vue +70 -0
- package/src/examples/shared/ExampleColor.vue +28 -0
- package/src/index.ts +8 -11
- package/src/internal/Backdrop/backdrop.scss +7 -1
- package/src/shared/helpers.ts +43 -0
- package/src/shared/theme.ts +22 -0
- package/src/style/animation.scss +1 -0
- package/src/style/core.scss +30 -55
- package/src/style/layout.scss +74 -9
- package/src/style/text.scss +18 -0
- package/src/style/theme.scss +195 -0
- package/src/style/tooltip.scss +22 -4
- package/src/style/typography.scss +95 -18
- package/dist/components/Table/Row.vue.d.ts +0 -16
- package/dist/style.css +0 -1
- package/src/components/Table/Row.vue +0 -9
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { whenever } from '@vueuse/core'
|
|
3
|
+
import { computed, onMounted, useTemplateRef, watch, watchEffect } from 'vue'
|
|
4
|
+
import { clamp, delay, formatUnitValue, isNil, randomMinMax } from '../../shared/helpers'
|
|
4
5
|
import './progress.scss'
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
@@ -30,10 +31,14 @@ const {
|
|
|
30
31
|
height,
|
|
31
32
|
} = defineProps<Props>()
|
|
32
33
|
|
|
34
|
+
const emit = defineEmits<{
|
|
35
|
+
done: []
|
|
36
|
+
}>()
|
|
37
|
+
|
|
33
38
|
const progressAmount = defineModel<number>({
|
|
34
39
|
default: 0,
|
|
35
40
|
set(value) {
|
|
36
|
-
return
|
|
41
|
+
return clamp(0, 100, value)
|
|
37
42
|
},
|
|
38
43
|
})
|
|
39
44
|
|
|
@@ -49,6 +54,8 @@ watchEffect(() => {
|
|
|
49
54
|
}
|
|
50
55
|
})
|
|
51
56
|
|
|
57
|
+
whenever(() => fake, fakeIncrement)
|
|
58
|
+
|
|
52
59
|
// Automatically / randomly increment but never reach 100% until
|
|
53
60
|
async function fakeIncrement() {
|
|
54
61
|
if (fake && progressAmount.value < 100) {
|
|
@@ -59,15 +66,21 @@ async function fakeIncrement() {
|
|
|
59
66
|
}
|
|
60
67
|
else {
|
|
61
68
|
progressAmount.value += randomMinMax(1, 10)
|
|
62
|
-
await delay(randomMinMax(200,
|
|
69
|
+
await delay(randomMinMax(200, 12000))
|
|
63
70
|
}
|
|
64
71
|
fakeIncrement()
|
|
65
72
|
}
|
|
66
73
|
}
|
|
67
74
|
|
|
75
|
+
watch(progressAmount, (v) => {
|
|
76
|
+
if (v >= 100) {
|
|
77
|
+
emit('done')
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
|
|
68
81
|
onMounted(fakeIncrement)
|
|
69
82
|
|
|
70
|
-
const w = computed(() => `${progressAmount.value}%`)
|
|
83
|
+
const w = computed(() => `${clamp(0, 100, progressAmount.value)}%`)
|
|
71
84
|
const bC = computed(() => color)
|
|
72
85
|
</script>
|
|
73
86
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
width: 100%;
|
|
6
6
|
position: relative;
|
|
7
7
|
border-radius: 999px;
|
|
8
|
-
background-color: var(--color-bg-
|
|
8
|
+
background-color: var(--color-bg-raised);
|
|
9
9
|
overflow: hidden;
|
|
10
10
|
height: var(--vui-progress-height);
|
|
11
11
|
|
|
@@ -39,3 +39,9 @@
|
|
|
39
39
|
transition: var(--transition-slow);
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
:root.light {
|
|
44
|
+
.vui-progress-indicator {
|
|
45
|
+
background-color: var(--);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -7,12 +7,14 @@ export interface RadioProps {
|
|
|
7
7
|
label?: string
|
|
8
8
|
disabled?: boolean
|
|
9
9
|
value: any
|
|
10
|
+
accent?: boolean
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const {
|
|
13
14
|
label,
|
|
14
15
|
disabled,
|
|
15
16
|
value,
|
|
17
|
+
accent,
|
|
16
18
|
} = defineProps<RadioProps>()
|
|
17
19
|
const slots = defineSlots()
|
|
18
20
|
const checked = defineModel()
|
|
@@ -21,8 +23,8 @@ const isChecked = computed(() => value === checked.value)
|
|
|
21
23
|
</script>
|
|
22
24
|
|
|
23
25
|
<template>
|
|
24
|
-
<div class="vui-radio" :class="{ disabled: !!disabled, checked: isChecked }">
|
|
25
|
-
<input :id v-model="checked" type="radio" :value :checked="isChecked">
|
|
26
|
+
<div class="vui-radio" :class="{ disabled: !!disabled, checked: isChecked, accent }">
|
|
27
|
+
<input :id v-model="checked" type="radio" :value :checked="isChecked" :disabled>
|
|
26
28
|
<label :for="id">
|
|
27
29
|
<span class="vui-radio-icon">
|
|
28
30
|
<Icon :icon="isChecked ? 'ph:radio-button-fill' : 'ph:circle'" />
|
|
@@ -5,18 +5,21 @@
|
|
|
5
5
|
.vui-radio-icon svg {
|
|
6
6
|
color: var(--color-text);
|
|
7
7
|
}
|
|
8
|
+
|
|
9
|
+
&.accent .vui-radio-icon svg {
|
|
10
|
+
color: var(--color-accent);
|
|
11
|
+
}
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
&.disabled {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.vui-radio-icon svg path {
|
|
15
|
-
color: var(--color-text-lighter) !important;
|
|
15
|
+
.vui-radio-icon {
|
|
16
|
+
opacity: 0.25;
|
|
17
|
+
cursor: not-allowed;
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
input + label
|
|
19
|
-
|
|
20
|
+
input + label .vui-radio-content {
|
|
21
|
+
opacity: 0.4;
|
|
22
|
+
cursor: not-allowed;
|
|
20
23
|
}
|
|
21
24
|
}
|
|
22
25
|
|
|
@@ -38,6 +41,7 @@
|
|
|
38
41
|
position: absolute;
|
|
39
42
|
overflow: hidden;
|
|
40
43
|
outline: none !important;
|
|
44
|
+
opacity: 0;
|
|
41
45
|
|
|
42
46
|
&:focus-visible + label .vui-radio-icon {
|
|
43
47
|
outline: 2px solid var(--color-text);
|
|
@@ -59,10 +63,16 @@
|
|
|
59
63
|
display: flex;
|
|
60
64
|
align-items: center;
|
|
61
65
|
min-height: var(--radio-size);
|
|
62
|
-
font-size: var(--font-size-
|
|
66
|
+
font-size: var(--font-size-m);
|
|
63
67
|
// line-height: var(--radio-size);
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
}
|
|
73
|
+
|
|
74
|
+
:root.light {
|
|
75
|
+
.vui-radio.checked.accent .vui-radio-icon svg {
|
|
76
|
+
color: var(--color-accent);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- eslint-disable ts/consistent-type-definitions -->
|
|
2
2
|
<script setup lang='ts' generic="T">
|
|
3
3
|
import { Icon } from '@iconify/vue'
|
|
4
|
-
import { computed, onMounted, ref, useTemplateRef } from 'vue'
|
|
4
|
+
import { computed, onMounted, ref, useId, useTemplateRef } from 'vue'
|
|
5
5
|
import { searchString } from '../../shared/helpers'
|
|
6
6
|
import Button from '../Button/Button.vue'
|
|
7
7
|
import Dropdown from '../Dropdown/Dropdown.vue'
|
|
@@ -28,6 +28,8 @@ type Props = {
|
|
|
28
28
|
search?: boolean
|
|
29
29
|
maxActiveOptions?: number
|
|
30
30
|
showClear?: boolean
|
|
31
|
+
disabled?: boolean
|
|
32
|
+
errors?: string[]
|
|
31
33
|
}
|
|
32
34
|
|
|
33
35
|
const {
|
|
@@ -39,11 +41,14 @@ const {
|
|
|
39
41
|
options,
|
|
40
42
|
single = true,
|
|
41
43
|
search,
|
|
42
|
-
maxActiveOptions
|
|
44
|
+
maxActiveOptions,
|
|
43
45
|
showClear,
|
|
46
|
+
disabled,
|
|
47
|
+
errors = [] as string[],
|
|
44
48
|
} = defineProps<Props>()
|
|
45
49
|
|
|
46
50
|
const selected = defineModel<SelectOption[] | undefined>()
|
|
51
|
+
const trigger = useTemplateRef('trigger')
|
|
47
52
|
|
|
48
53
|
//
|
|
49
54
|
function setValue(option: SelectOption) {
|
|
@@ -68,7 +73,7 @@ function setValue(option: SelectOption) {
|
|
|
68
73
|
if (!selected.value) {
|
|
69
74
|
selected.value = [option]
|
|
70
75
|
}
|
|
71
|
-
else {
|
|
76
|
+
else if (!maxActiveOptions || (selected.value.length < maxActiveOptions)) {
|
|
72
77
|
selected.value?.push(option)
|
|
73
78
|
}
|
|
74
79
|
}
|
|
@@ -97,7 +102,7 @@ const renderPlaceholder = computed(() => {
|
|
|
97
102
|
return selected.value[0].label
|
|
98
103
|
|
|
99
104
|
// If amount of selected exceeds the active capacity
|
|
100
|
-
if (selected.value.length >
|
|
105
|
+
if (selected.value.length > 3) {
|
|
101
106
|
return `${selected.value.length} selected`
|
|
102
107
|
}
|
|
103
108
|
|
|
@@ -117,42 +122,59 @@ function clearValue() {
|
|
|
117
122
|
selected.value = undefined
|
|
118
123
|
dropdownRef.value?.close()
|
|
119
124
|
}
|
|
125
|
+
|
|
126
|
+
const id = useId()
|
|
120
127
|
</script>
|
|
121
128
|
|
|
122
129
|
<template>
|
|
123
|
-
<div class="vui-input-container vui-select" :class="{ expand, required, readonly }">
|
|
124
|
-
<Dropdown ref="dropdown" :expand>
|
|
130
|
+
<div class="vui-input-container vui-select" :class="{ expand, required, readonly, disabled, 'has-errors': errors.length > 0 }">
|
|
131
|
+
<Dropdown ref="dropdown" :expand @close="trigger?.focus({ preventScroll: true })">
|
|
125
132
|
<template #trigger="{ toggle, isOpen }">
|
|
126
133
|
<div class="vui-input vui-select-trigger-content">
|
|
127
|
-
<label v-if="label" for="id">{{ label }}</label>
|
|
134
|
+
<label v-if="label" :for="id">{{ label }}</label>
|
|
128
135
|
<p v-if="hint" class="vui-input-hint">
|
|
129
136
|
{{ hint }}
|
|
130
137
|
</p>
|
|
131
138
|
|
|
132
|
-
<button
|
|
139
|
+
<button
|
|
140
|
+
:id
|
|
141
|
+
ref="trigger"
|
|
142
|
+
class="vui-input-style vui-select-trigger-container"
|
|
143
|
+
:class="{ 'has-value': selected && selected.length > 0 }"
|
|
144
|
+
:disabled
|
|
145
|
+
@click="toggle"
|
|
146
|
+
>
|
|
133
147
|
<span>
|
|
134
148
|
{{ renderPlaceholder }}
|
|
135
149
|
</span>
|
|
136
|
-
<
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
150
|
+
<template v-if="showClear && !required && selected">
|
|
151
|
+
<div class="flex-1" />
|
|
152
|
+
<Button
|
|
153
|
+
plain
|
|
154
|
+
icon="ph:x"
|
|
155
|
+
square
|
|
156
|
+
size="s"
|
|
157
|
+
|
|
158
|
+
@click.stop="clearValue"
|
|
159
|
+
/>
|
|
160
|
+
</template>
|
|
144
161
|
<Icon :icon="isOpen ? 'ph:caret-up' : 'ph:caret-down'" />
|
|
145
162
|
</button>
|
|
146
163
|
</div>
|
|
147
164
|
</template>
|
|
148
165
|
|
|
149
166
|
<template #default="{ close, isOpen }">
|
|
150
|
-
<DropdownTitle v-if="search">
|
|
167
|
+
<DropdownTitle v-if="search" sticky>
|
|
151
168
|
<Input
|
|
152
169
|
v-model="searchStr"
|
|
153
170
|
placeholder="Search..."
|
|
154
171
|
:focus="isOpen"
|
|
155
|
-
|
|
172
|
+
expand
|
|
173
|
+
>
|
|
174
|
+
<template #start>
|
|
175
|
+
<Icon icon="ph:magnifying-glass" />
|
|
176
|
+
</template>
|
|
177
|
+
</Input>
|
|
156
178
|
</DropdownTitle>
|
|
157
179
|
|
|
158
180
|
<p v-if="filteredOptions.length === 0" class="vue-select-no-results">
|
|
@@ -176,5 +198,14 @@ function clearValue() {
|
|
|
176
198
|
</DropdownItem>
|
|
177
199
|
</template>
|
|
178
200
|
</Dropdown>
|
|
201
|
+
|
|
202
|
+
<p v-if="maxActiveOptions && !single" class="vui-input-limit">
|
|
203
|
+
{{ `${selected ? selected.length : 0}/${maxActiveOptions}` }}
|
|
204
|
+
</p>
|
|
205
|
+
<ul v-if="errors.length > 0" class="vui-input-errors">
|
|
206
|
+
<li v-for="err in errors" :key="err">
|
|
207
|
+
{{ err }}
|
|
208
|
+
</li>
|
|
209
|
+
</ul>
|
|
179
210
|
</div>
|
|
180
211
|
</template>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
.vui-input-container {
|
|
2
2
|
&.vui-select {
|
|
3
|
+
width: auto;
|
|
4
|
+
|
|
3
5
|
&.expand {
|
|
4
6
|
.vui-dropdown-trigger-wrap,
|
|
5
7
|
.vui-dropdown-trigger-content {
|
|
@@ -7,7 +9,22 @@
|
|
|
7
9
|
}
|
|
8
10
|
}
|
|
9
11
|
|
|
12
|
+
&.disabled {
|
|
13
|
+
.vui-input-style {
|
|
14
|
+
cursor: not-allowed;
|
|
15
|
+
|
|
16
|
+
&:hover {
|
|
17
|
+
border-color: var(--color-border);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
10
22
|
.vui-select-trigger-container {
|
|
23
|
+
&.has-value span {
|
|
24
|
+
color: var(--color-text);
|
|
25
|
+
font-weight: var(--font-weight-medium);
|
|
26
|
+
}
|
|
27
|
+
|
|
11
28
|
span {
|
|
12
29
|
white-space: nowrap;
|
|
13
30
|
text-overflow: ellipsis;
|
|
@@ -30,8 +47,6 @@
|
|
|
30
47
|
margin-right: -6px;
|
|
31
48
|
|
|
32
49
|
.vui-button-slot svg {
|
|
33
|
-
width: 14px;
|
|
34
|
-
height: 14px;
|
|
35
50
|
color: var(--color-text-light);
|
|
36
51
|
}
|
|
37
52
|
}
|
|
@@ -42,3 +57,21 @@
|
|
|
42
57
|
}
|
|
43
58
|
}
|
|
44
59
|
}
|
|
60
|
+
|
|
61
|
+
select {
|
|
62
|
+
display: block;
|
|
63
|
+
height: var(--interactive-el-height);
|
|
64
|
+
line-height: var(--interactive-el-height);
|
|
65
|
+
background-color: var(--color-bg);
|
|
66
|
+
border: 1px solid var(--color-border);
|
|
67
|
+
border-radius: var(--border-radius-s);
|
|
68
|
+
padding-inline: var(--space-xs);
|
|
69
|
+
transition: var(--transition-fast);
|
|
70
|
+
z-index: 1;
|
|
71
|
+
font-size: var(--font-size-m);
|
|
72
|
+
color: var(--color-text);
|
|
73
|
+
|
|
74
|
+
&:hover {
|
|
75
|
+
border-color: var(--color-border-strong);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -55,14 +55,20 @@ const baseTransform = computed(() => {
|
|
|
55
55
|
<div class="flex-1">
|
|
56
56
|
<slot name="header" :close />
|
|
57
57
|
</div>
|
|
58
|
-
<Button square icon="ph:x" @click="open = false" />
|
|
58
|
+
<Button plain square icon="ph:x" @click="open = false" />
|
|
59
59
|
</div>
|
|
60
60
|
|
|
61
|
-
<Divider v-if="separator && $slots.header" :
|
|
61
|
+
<Divider v-if="separator && $slots.header" :size="1" />
|
|
62
62
|
|
|
63
63
|
<div v-if="$slots.default" class="vui-sheet-content">
|
|
64
64
|
<slot :close />
|
|
65
65
|
</div>
|
|
66
|
+
|
|
67
|
+
<Divider v-if="separator && $slots.footer" :size="1" />
|
|
68
|
+
|
|
69
|
+
<div class="vui-sheet-footer">
|
|
70
|
+
<slot name="footer" :close />
|
|
71
|
+
</div>
|
|
66
72
|
</div>
|
|
67
73
|
</Backdrop>
|
|
68
74
|
</Transition>
|
|
@@ -10,24 +10,32 @@
|
|
|
10
10
|
top: 0;
|
|
11
11
|
border-bottom: 1px solid var(--color-border);
|
|
12
12
|
height: auto;
|
|
13
|
+
border-bottom-right-radius: var(--border-radius-l);
|
|
14
|
+
border-bottom-left-radius: var(--border-radius-l);
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
&.vui-sheet-position-bottom {
|
|
16
18
|
bottom: 0;
|
|
17
19
|
border-top: 1px solid var(--color-border);
|
|
18
20
|
height: auto;
|
|
21
|
+
border-top-right-radius: var(--border-radius-l);
|
|
22
|
+
border-top-left-radius: var(--border-radius-l);
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
&.vui-sheet-position-right {
|
|
22
26
|
right: 0;
|
|
23
27
|
top: 0;
|
|
24
28
|
border-left: 1px solid var(--color-border);
|
|
29
|
+
border-top-left-radius: var(--border-radius-l);
|
|
30
|
+
border-bottom-left-radius: var(--border-radius-l);
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
&.vui-sheet-position-left {
|
|
28
34
|
left: 0;
|
|
29
35
|
top: 0;
|
|
30
36
|
border-right: 1px solid var(--color-border);
|
|
37
|
+
border-top-right-radius: var(--border-radius-l);
|
|
38
|
+
border-bottom-right-radius: var(--border-radius-l);
|
|
31
39
|
}
|
|
32
40
|
|
|
33
41
|
&.vui-sheet-position-top,
|
|
@@ -36,6 +44,7 @@
|
|
|
36
44
|
width: 100%;
|
|
37
45
|
}
|
|
38
46
|
|
|
47
|
+
.vui-sheet-footer,
|
|
39
48
|
.vui-sheet-header,
|
|
40
49
|
.vui-sheet-content {
|
|
41
50
|
width: 100%;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
|
-
import { useCssVar,
|
|
3
|
-
import { computed, useSlots, useTemplateRef } from 'vue'
|
|
2
|
+
import { useCssVar, useMouseInElement, useTimeoutFn, watchThrottled } from '@vueuse/core'
|
|
3
|
+
import { computed, onMounted, useSlots, useTemplateRef } from 'vue'
|
|
4
4
|
import { isNil } from '../../shared/helpers'
|
|
5
5
|
import './sidebar.scss'
|
|
6
6
|
|
|
@@ -27,18 +27,21 @@ interface Props {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const sidebar = useTemplateRef('sidebar')
|
|
30
|
-
const open = defineModel<boolean>(
|
|
30
|
+
const open = defineModel<boolean>({
|
|
31
|
+
default: true,
|
|
32
|
+
})
|
|
31
33
|
const slots = useSlots()
|
|
32
34
|
const offset = useCssVar('--vui-sidebar-float-offset', sidebar, {
|
|
33
35
|
initialValue: '8px',
|
|
34
36
|
})
|
|
35
37
|
|
|
36
38
|
const width = computed(() => {
|
|
37
|
-
if (props.mini)
|
|
38
|
-
return `65px`
|
|
39
|
+
if (props.mini) {
|
|
40
|
+
return props.floaty ? '73px' : `65px`
|
|
41
|
+
}
|
|
39
42
|
if (!props.floaty)
|
|
40
43
|
return `${props.width}px`
|
|
41
|
-
return `calc(${props.width}px
|
|
44
|
+
return `calc(${props.width}px + ${offset.value})`
|
|
42
45
|
})
|
|
43
46
|
|
|
44
47
|
const slotProps = computed(() => ({
|
|
@@ -46,19 +49,29 @@ const slotProps = computed(() => ({
|
|
|
46
49
|
floaty: props.floaty,
|
|
47
50
|
width: props.width,
|
|
48
51
|
open,
|
|
52
|
+
close: () => open.value = false,
|
|
49
53
|
}))
|
|
50
54
|
|
|
51
55
|
// Sidebar `appear` implementation
|
|
52
56
|
const { start, stop, isPending } = useTimeoutFn(() => {
|
|
53
|
-
|
|
57
|
+
if (props.appear) {
|
|
58
|
+
open.value = true
|
|
59
|
+
}
|
|
54
60
|
}, 250)
|
|
55
61
|
|
|
56
62
|
const APPEAR_OFFSET = 32
|
|
57
63
|
|
|
58
|
-
const
|
|
64
|
+
const wrap = useTemplateRef('wrap')
|
|
65
|
+
const { elementX } = useMouseInElement(wrap)
|
|
66
|
+
|
|
67
|
+
onMounted(() => {
|
|
68
|
+
if (props.appear && open.value) {
|
|
69
|
+
open.value = false
|
|
70
|
+
}
|
|
71
|
+
})
|
|
59
72
|
|
|
60
|
-
watchThrottled(
|
|
61
|
-
if (!props.appear)
|
|
73
|
+
watchThrottled(elementX, (pos) => {
|
|
74
|
+
if (!props.appear || (pos <= APPEAR_OFFSET && pos >= 0 && isPending.value))
|
|
62
75
|
return
|
|
63
76
|
|
|
64
77
|
if (pos <= APPEAR_OFFSET && pos >= 0 && !open.value && !isPending.value) {
|
|
@@ -83,7 +96,7 @@ watchThrottled(x, (pos) => {
|
|
|
83
96
|
</script>
|
|
84
97
|
|
|
85
98
|
<template>
|
|
86
|
-
<div class="vui-sidebar-outer" :style="{ width }" :class="{ open }">
|
|
99
|
+
<div ref="wrap" class="vui-sidebar-outer" :style="{ width }" :class="{ open }">
|
|
87
100
|
<aside ref="sidebar" class="vui-sidebar" :class="{ open, floaty: props.floaty, mini: props.mini }" :style="{ width: `${props.mini ? 65 : props.width}px` }">
|
|
88
101
|
<div v-if="slots.header" class="vui-sidebar-header">
|
|
89
102
|
<slot name="header" v-bind="slotProps" />
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
.vui-sidebar-layout {
|
|
3
3
|
display: flex;
|
|
4
4
|
flex-wrap: nowrap;
|
|
5
|
-
gap:
|
|
5
|
+
gap: 0;
|
|
6
|
+
height: 100vh;
|
|
6
7
|
position: relative;
|
|
7
8
|
|
|
8
9
|
main {
|
|
9
10
|
flex: 1;
|
|
10
|
-
padding: 2rem;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.vui-sidebar-outer {
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
.vui-sidebar {
|
|
23
23
|
--vui-sidebar-float-offset: 8px;
|
|
24
24
|
display: flex;
|
|
25
|
+
height: 100%;
|
|
25
26
|
flex-direction: column;
|
|
26
27
|
gap: var(--space-sm);
|
|
27
|
-
height: 100vh;
|
|
28
28
|
width: 224px;
|
|
29
|
-
position:
|
|
29
|
+
position: absolute;
|
|
30
30
|
top: 0;
|
|
31
31
|
z-index: 50;
|
|
32
32
|
background-color: var(--color-bg);
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
top: var(--vui-sidebar-float-offset);
|
|
48
48
|
left: var(--vui-sidebar-float-offset);
|
|
49
49
|
bottom: var(--vui-sidebar-float-offset);
|
|
50
|
-
height: calc(
|
|
50
|
+
height: calc(100% - calc(var(--vui-sidebar-float-offset) * 2));
|
|
51
51
|
border-radius: var(--border-radius-m);
|
|
52
52
|
border: 1px solid var(--color-border);
|
|
53
53
|
transform: translateX(calc(-100% - calc(var(--vui-sidebar-float-offset) * 2)));
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
position: absolute;
|
|
77
77
|
inset: 0;
|
|
78
78
|
overflow-y: auto;
|
|
79
|
+
overflow-x: hidden;
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
|
|
@@ -5,17 +5,18 @@ import './switch.scss'
|
|
|
5
5
|
interface Props {
|
|
6
6
|
label?: string
|
|
7
7
|
disabled?: boolean
|
|
8
|
+
accent?: boolean
|
|
8
9
|
}
|
|
9
10
|
|
|
10
|
-
const { label, disabled } = defineProps<Props>()
|
|
11
|
+
const { label, disabled, accent } = defineProps<Props>()
|
|
11
12
|
const slots = defineSlots()
|
|
12
13
|
const checked = defineModel<boolean>()
|
|
13
14
|
const id = useId()
|
|
14
15
|
</script>
|
|
15
16
|
|
|
16
17
|
<template>
|
|
17
|
-
<div class="vui-switch" :class="{ disabled, checked }">
|
|
18
|
-
<input :id v-model="checked" type="checkbox">
|
|
18
|
+
<div class="vui-switch" :class="{ disabled, checked, accent }">
|
|
19
|
+
<input :id v-model="checked" type="checkbox" :disabled>
|
|
19
20
|
<label :for="id">
|
|
20
21
|
<div class="vui-switch-icon">
|
|
21
22
|
<span class="vui-switch-indicator" />
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
.vui-switch {
|
|
2
2
|
--switch-size: 24px;
|
|
3
3
|
|
|
4
|
-
&.checked
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
&.checked {
|
|
5
|
+
.vui-switch-icon .vui-switch-indicator {
|
|
6
|
+
left: calc(100% - 24px);
|
|
7
|
+
background-color: var(--color-text);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&.accent .vui-switch-icon .vui-switch-indicator {
|
|
11
|
+
background-color: var(--color-accent);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
&.disabled {
|
|
16
|
+
.vui-switch-icon {
|
|
17
|
+
opacity: 0.5;
|
|
18
|
+
cursor: not-allowed;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
input + label .vui-switch-content {
|
|
22
|
+
opacity: 0.5;
|
|
23
|
+
cursor: not-allowed;
|
|
24
|
+
}
|
|
7
25
|
}
|
|
8
26
|
|
|
9
27
|
.vui-switch-icon {
|
|
@@ -12,7 +30,7 @@
|
|
|
12
30
|
border-radius: 22px;
|
|
13
31
|
background-color: var(--color-bg-raised);
|
|
14
32
|
position: relative;
|
|
15
|
-
cursor:
|
|
33
|
+
cursor: default;
|
|
16
34
|
|
|
17
35
|
.vui-switch-indicator {
|
|
18
36
|
display: block;
|
|
@@ -22,7 +40,7 @@
|
|
|
22
40
|
width: 20px;
|
|
23
41
|
height: 20px;
|
|
24
42
|
border-radius: 100%;
|
|
25
|
-
background-color: var(--color-
|
|
43
|
+
background-color: var(--color-text-lighter);
|
|
26
44
|
transition: var(--transition);
|
|
27
45
|
}
|
|
28
46
|
}
|
|
@@ -33,6 +51,7 @@
|
|
|
33
51
|
position: absolute;
|
|
34
52
|
overflow: hidden;
|
|
35
53
|
outline: none !important;
|
|
54
|
+
opacity: 0;
|
|
36
55
|
|
|
37
56
|
&:focus-visible + label .vui-switch-icon {
|
|
38
57
|
outline: 2px solid var(--color-text);
|
|
@@ -52,9 +71,23 @@
|
|
|
52
71
|
&:is(p) {
|
|
53
72
|
height: var(--switch-size);
|
|
54
73
|
line-height: var(--switch-size);
|
|
55
|
-
font-size: var(--font-size-
|
|
74
|
+
font-size: var(--font-size-m);
|
|
56
75
|
}
|
|
57
76
|
}
|
|
58
77
|
}
|
|
59
78
|
}
|
|
60
79
|
}
|
|
80
|
+
|
|
81
|
+
:root.light {
|
|
82
|
+
.vui-switch .vui-switch-icon .vui-switch-indicator {
|
|
83
|
+
background-color: var(--color-bg-lowered);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.vui-switch.checked.accent .vui-switch-icon .vui-switch-indicator {
|
|
87
|
+
background-color: var(--color-accent);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.vui-switch.checked .vui-switch-icon .vui-switch-indicator {
|
|
91
|
+
background-color: var(--color-text);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -40,18 +40,18 @@ const sortStateBind = computed(() => {
|
|
|
40
40
|
|
|
41
41
|
<template>
|
|
42
42
|
<th>
|
|
43
|
-
<div v-if="props.header" class="vui-table-th-content">
|
|
43
|
+
<div v-if="props.header || $slots.default" class="vui-table-th-content">
|
|
44
44
|
<slot>
|
|
45
|
-
{{ props.header
|
|
45
|
+
{{ props.header?.label }}
|
|
46
46
|
</slot>
|
|
47
47
|
<Button
|
|
48
|
-
v-if="props.sort"
|
|
48
|
+
v-if="props.sort && props.header"
|
|
49
49
|
class="vui-table-sort-button"
|
|
50
50
|
v-bind="sortStateBind"
|
|
51
|
-
:class="{ active: !!props.header.sortKey }"
|
|
52
51
|
size="s"
|
|
53
|
-
plain
|
|
52
|
+
:plain="!!!props.header.sortKey"
|
|
54
53
|
square
|
|
54
|
+
variant="gray"
|
|
55
55
|
@click="props.header.sortToggle"
|
|
56
56
|
/>
|
|
57
57
|
</div>
|