@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.
- package/LICENSE +673 -673
- package/README.md +41 -40
- package/dist/components/Dropdown/DropdownItem.vue.d.ts +1 -0
- package/dist/components/Flex/Flex.vue.d.ts +3 -1
- package/dist/components/Grid/Grid.vue.d.ts +3 -1
- package/dist/components/Tabs/Tabs.vue.d.ts +4 -0
- package/dist/style.css +1 -1
- package/dist/vui.js +1547 -1534
- package/package.json +68 -68
- package/src/App.vue +176 -175
- package/src/components/Accordion/Accordion.vue +91 -91
- package/src/components/Accordion/AccordionGroup.vue +43 -43
- package/src/components/Accordion/accordion.scss +81 -80
- package/src/components/Alert/Alert.vue +53 -53
- package/src/components/Alert/alert.scss +80 -80
- package/src/components/Avatar/Avatar.vue +50 -50
- package/src/components/Avatar/avatar.scss +52 -52
- package/src/components/Badge/Badge.vue +21 -21
- package/src/components/Badge/badge.scss +89 -89
- package/src/components/Breadcrumbs/BreadcrumbItem.vue +26 -26
- package/src/components/Breadcrumbs/Breadcrumbs.vue +33 -33
- package/src/components/Breadcrumbs/breadcrumbs.scss +30 -30
- package/src/components/Button/Button.vue +90 -90
- package/src/components/Button/button.scss +178 -176
- package/src/components/ButtonGroup/ButtonGroup.vue +25 -25
- package/src/components/ButtonGroup/button-group.scss +51 -51
- package/src/components/Calendar/Calendar.vue +63 -60
- package/src/components/Calendar/calendar.scss +60 -56
- package/src/components/Card/Card.vue +48 -48
- package/src/components/Card/card.scss +53 -53
- package/src/components/Checkbox/Checkbox.vue +51 -52
- package/src/components/Checkbox/checkbox.scss +75 -66
- package/src/components/CopyClipboard/CopyClipboard.vue +82 -82
- package/src/components/CopyClipboard/copy-clipboard.scss +17 -17
- package/src/components/Divider/Divider.vue +44 -44
- package/src/components/Divider/divider.scss +35 -35
- package/src/components/Drawer/Drawer.vue +97 -97
- package/src/components/Drawer/drawer.scss +36 -36
- package/src/components/Dropdown/Dropdown.vue +111 -111
- package/src/components/Dropdown/DropdownItem.vue +33 -29
- package/src/components/Dropdown/DropdownTitle.vue +8 -8
- package/src/components/Dropdown/dropdown-item.scss +77 -0
- package/src/components/Dropdown/dropdown.scss +39 -117
- package/src/components/Flex/Flex.vue +113 -106
- package/src/components/Grid/Grid.vue +60 -54
- package/src/components/Input/Counter.vue +70 -70
- package/src/components/Input/Dropzone.vue +65 -65
- package/src/components/Input/File.vue +15 -15
- package/src/components/Input/Input.vue +121 -121
- package/src/components/Input/Password.vue +47 -47
- package/src/components/Input/Textarea.vue +76 -76
- package/src/components/Input/input.scss +208 -208
- package/src/components/Kbd/Kbd.vue +48 -48
- package/src/components/Kbd/KbdGroup.vue +31 -31
- package/src/components/Kbd/kbd.scss +18 -18
- package/src/components/Modal/Confirm.vue +56 -56
- package/src/components/Modal/Modal.vue +91 -91
- package/src/components/Modal/modal.scss +49 -49
- package/src/components/OTP/OTP.vue +133 -133
- package/src/components/OTP/OTPItem.vue +37 -37
- package/src/components/OTP/otp.scss +83 -83
- package/src/components/Pagination/Pagination.vue +74 -74
- package/src/components/Pagination/pagination.ts +78 -78
- package/src/components/Popout/Popout.vue +42 -42
- package/src/components/Popout/popout.scss +8 -8
- package/src/components/Progress/Progress.vue +90 -90
- package/src/components/Progress/progress.scss +41 -41
- package/src/components/Radio/Radio.vue +36 -36
- package/src/components/Radio/RadioGroup.vue +40 -40
- package/src/components/Radio/radio.scss +68 -59
- package/src/components/Select/Select.vue +180 -180
- package/src/components/Select/select.scss +44 -44
- package/src/components/Sheet/Sheet.vue +92 -92
- package/src/components/Sheet/sheet.scss +60 -60
- package/src/components/Sidebar/Sidebar.vue +102 -0
- package/src/components/Sidebar/sidebar.scss +123 -0
- package/src/components/Skeleton/Skeleton.vue +43 -43
- package/src/components/Skeleton/skeleton.scss +14 -14
- package/src/components/Spinner/Spinner.vue +42 -42
- package/src/components/Spinner/spinner.scss +46 -46
- package/src/components/Switch/Switch.vue +30 -30
- package/src/components/Switch/switch.scss +60 -52
- package/src/components/Table/Cell.vue +23 -23
- package/src/components/Table/Header.vue +59 -59
- package/src/components/Table/Row.vue +9 -9
- package/src/components/Table/SelectAll.vue +23 -23
- package/src/components/Table/SelectRow.vue +29 -29
- package/src/components/Table/Table.vue +66 -66
- package/src/components/Table/table.scss +134 -134
- package/src/components/Table/table.ts +244 -244
- package/src/components/Tabs/Tab.vue +27 -27
- package/src/components/Tabs/Tabs.vue +89 -82
- package/src/components/Tabs/tabs.scss +80 -79
- package/src/components/Toast/Toasts.vue +47 -47
- package/src/components/Toast/toast.scss +41 -41
- package/src/components/Toast/toast.ts +68 -68
- package/src/components/Tooltip/Tooltip.vue +86 -86
- package/src/components/Tooltip/tooltip.scss +4 -4
- package/src/index.scss +1 -1
- package/src/index.ts +119 -119
- package/src/internal/Backdrop/Backdrop.vue +22 -22
- package/src/internal/Backdrop/backdrop.scss +28 -28
- package/src/main.ts +5 -5
- package/src/shared/helpers.ts +74 -74
- package/src/shared/types.ts +29 -29
- package/src/style/animation.scss +21 -21
- package/src/style/core.scss +150 -148
- package/src/style/layout.scss +168 -136
- package/src/style/media-query.scss +29 -29
- package/src/style/reset.scss +135 -135
- package/src/style/{fonts.scss → text.scss} +74 -53
- package/src/style/tooltip.scss +128 -128
- package/src/style/typography.scss +338 -338
- package/src/style/utils.scss +36 -36
|
@@ -1,180 +1,180 @@
|
|
|
1
|
-
<!-- eslint-disable ts/consistent-type-definitions -->
|
|
2
|
-
<script setup lang='ts' generic="T">
|
|
3
|
-
import { Icon } from '@iconify/vue'
|
|
4
|
-
import { computed, onMounted, ref, useTemplateRef } from 'vue'
|
|
5
|
-
import { searchString } from '../../shared/helpers'
|
|
6
|
-
import Button from '../Button/Button.vue'
|
|
7
|
-
import Dropdown from '../Dropdown/Dropdown.vue'
|
|
8
|
-
import DropdownItem from '../Dropdown/DropdownItem.vue'
|
|
9
|
-
import DropdownTitle from '../Dropdown/DropdownTitle.vue'
|
|
10
|
-
import Input from '../Input/Input.vue'
|
|
11
|
-
import '../Input/input.scss'
|
|
12
|
-
import './select.scss'
|
|
13
|
-
|
|
14
|
-
export type SelectOption = {
|
|
15
|
-
value: any
|
|
16
|
-
label: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
type Props = {
|
|
20
|
-
single?: boolean
|
|
21
|
-
readonly?: boolean
|
|
22
|
-
options: SelectOption[]
|
|
23
|
-
label?: string
|
|
24
|
-
placeholder?: string
|
|
25
|
-
required?: boolean
|
|
26
|
-
expand?: boolean
|
|
27
|
-
hint?: string
|
|
28
|
-
search?: boolean
|
|
29
|
-
maxActiveOptions?: number
|
|
30
|
-
showClear?: boolean
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const {
|
|
34
|
-
expand,
|
|
35
|
-
readonly,
|
|
36
|
-
required,
|
|
37
|
-
hint,
|
|
38
|
-
placeholder,
|
|
39
|
-
options,
|
|
40
|
-
single = true,
|
|
41
|
-
search,
|
|
42
|
-
maxActiveOptions = 3,
|
|
43
|
-
showClear,
|
|
44
|
-
} = defineProps<Props>()
|
|
45
|
-
|
|
46
|
-
const selected = defineModel<SelectOption[] | undefined>()
|
|
47
|
-
|
|
48
|
-
//
|
|
49
|
-
function setValue(option: SelectOption) {
|
|
50
|
-
if (single) {
|
|
51
|
-
// Single
|
|
52
|
-
if (selected.value?.some(o => o.value === option.value) && !required) {
|
|
53
|
-
selected.value = undefined
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
selected.value = [option]
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
if (selected.value && selected.value?.some(o => o.value === option.value)) {
|
|
61
|
-
const values = selected.value.filter(o => o.value !== option.value)
|
|
62
|
-
// Cant remove the last value if it's required
|
|
63
|
-
if ((required && values.length > 0) || !required) {
|
|
64
|
-
selected.value = values.length > 0 ? values : undefined
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
if (!selected.value) {
|
|
69
|
-
selected.value = [option]
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
selected.value?.push(option)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
// Search
|
|
79
|
-
const searchStr = ref()
|
|
80
|
-
const filteredOptions = computed(() => {
|
|
81
|
-
if (!searchStr.value || searchStr.value.length === 0)
|
|
82
|
-
return options
|
|
83
|
-
|
|
84
|
-
return options.filter((option) => {
|
|
85
|
-
return searchString(option.label, searchStr.value)
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
// Render text inside the button
|
|
90
|
-
const renderPlaceholder = computed(() => {
|
|
91
|
-
// Render placeholder or a default select option
|
|
92
|
-
if (!selected.value || selected.value.length === 0)
|
|
93
|
-
return placeholder ?? 'Select an option'
|
|
94
|
-
|
|
95
|
-
// Selected values
|
|
96
|
-
if (single)
|
|
97
|
-
return selected.value[0].label
|
|
98
|
-
|
|
99
|
-
// If amount of selected exceeds the active capacity
|
|
100
|
-
if (selected.value.length > maxActiveOptions) {
|
|
101
|
-
return `${selected.value.length} selected`
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Just list ALL selected optionsx
|
|
105
|
-
return selected.value.map(o => o.label).join(', ')
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
onMounted(() => {
|
|
109
|
-
if (readonly && showClear) {
|
|
110
|
-
console.warn('[Select] readonly and showClear are mutually exclusive props. The clear button will not show up if required is present.')
|
|
111
|
-
}
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
const dropdownRef = useTemplateRef('dropdown')
|
|
115
|
-
|
|
116
|
-
function clearValue() {
|
|
117
|
-
selected.value = undefined
|
|
118
|
-
dropdownRef.value?.close()
|
|
119
|
-
}
|
|
120
|
-
</script>
|
|
121
|
-
|
|
122
|
-
<template>
|
|
123
|
-
<div class="vui-input-container vui-select" :class="{ expand, required, readonly }">
|
|
124
|
-
<Dropdown ref="dropdown" :expand>
|
|
125
|
-
<template #trigger="{ toggle, isOpen }">
|
|
126
|
-
<div class="vui-input vui-select-trigger-content">
|
|
127
|
-
<label v-if="label" for="id">{{ label }}</label>
|
|
128
|
-
<p v-if="hint" class="vui-input-hint">
|
|
129
|
-
{{ hint }}
|
|
130
|
-
</p>
|
|
131
|
-
|
|
132
|
-
<button class="vui-input-style vui-select-trigger-container" @click="toggle">
|
|
133
|
-
<span>
|
|
134
|
-
{{ renderPlaceholder }}
|
|
135
|
-
</span>
|
|
136
|
-
<Button
|
|
137
|
-
v-if="showClear && !required && selected"
|
|
138
|
-
plain
|
|
139
|
-
icon="ph:x"
|
|
140
|
-
square
|
|
141
|
-
size="s"
|
|
142
|
-
@click.stop="clearValue"
|
|
143
|
-
/>
|
|
144
|
-
<Icon :icon="isOpen ? 'ph:caret-up' : 'ph:caret-down'" />
|
|
145
|
-
</button>
|
|
146
|
-
</div>
|
|
147
|
-
</template>
|
|
148
|
-
|
|
149
|
-
<template #default="{ close, isOpen }">
|
|
150
|
-
<DropdownTitle v-if="search">
|
|
151
|
-
<Input
|
|
152
|
-
v-model="searchStr"
|
|
153
|
-
placeholder="Search..."
|
|
154
|
-
:focus="isOpen"
|
|
155
|
-
/>
|
|
156
|
-
</DropdownTitle>
|
|
157
|
-
|
|
158
|
-
<p v-if="filteredOptions.length === 0" class="vue-select-no-results">
|
|
159
|
-
No results...
|
|
160
|
-
</p>
|
|
161
|
-
|
|
162
|
-
<DropdownItem
|
|
163
|
-
v-for="option in filteredOptions"
|
|
164
|
-
:key="option.value"
|
|
165
|
-
:class="{ selected: selected?.find(v => v.value === option.value) }"
|
|
166
|
-
:icon="selected?.find(v => v.value === option.value) ? 'ph:check-bold' : ''"
|
|
167
|
-
@click="() => {
|
|
168
|
-
setValue(option)
|
|
169
|
-
// In single mode, close modal after clicking
|
|
170
|
-
if (single && !(required && selected && selected[0].value === option.value)) {
|
|
171
|
-
close()
|
|
172
|
-
}
|
|
173
|
-
}"
|
|
174
|
-
>
|
|
175
|
-
{{ option.label }}
|
|
176
|
-
</DropdownItem>
|
|
177
|
-
</template>
|
|
178
|
-
</Dropdown>
|
|
179
|
-
</div>
|
|
180
|
-
</template>
|
|
1
|
+
<!-- eslint-disable ts/consistent-type-definitions -->
|
|
2
|
+
<script setup lang='ts' generic="T">
|
|
3
|
+
import { Icon } from '@iconify/vue'
|
|
4
|
+
import { computed, onMounted, ref, useTemplateRef } from 'vue'
|
|
5
|
+
import { searchString } from '../../shared/helpers'
|
|
6
|
+
import Button from '../Button/Button.vue'
|
|
7
|
+
import Dropdown from '../Dropdown/Dropdown.vue'
|
|
8
|
+
import DropdownItem from '../Dropdown/DropdownItem.vue'
|
|
9
|
+
import DropdownTitle from '../Dropdown/DropdownTitle.vue'
|
|
10
|
+
import Input from '../Input/Input.vue'
|
|
11
|
+
import '../Input/input.scss'
|
|
12
|
+
import './select.scss'
|
|
13
|
+
|
|
14
|
+
export type SelectOption = {
|
|
15
|
+
value: any
|
|
16
|
+
label: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type Props = {
|
|
20
|
+
single?: boolean
|
|
21
|
+
readonly?: boolean
|
|
22
|
+
options: SelectOption[]
|
|
23
|
+
label?: string
|
|
24
|
+
placeholder?: string
|
|
25
|
+
required?: boolean
|
|
26
|
+
expand?: boolean
|
|
27
|
+
hint?: string
|
|
28
|
+
search?: boolean
|
|
29
|
+
maxActiveOptions?: number
|
|
30
|
+
showClear?: boolean
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const {
|
|
34
|
+
expand,
|
|
35
|
+
readonly,
|
|
36
|
+
required,
|
|
37
|
+
hint,
|
|
38
|
+
placeholder,
|
|
39
|
+
options,
|
|
40
|
+
single = true,
|
|
41
|
+
search,
|
|
42
|
+
maxActiveOptions = 3,
|
|
43
|
+
showClear,
|
|
44
|
+
} = defineProps<Props>()
|
|
45
|
+
|
|
46
|
+
const selected = defineModel<SelectOption[] | undefined>()
|
|
47
|
+
|
|
48
|
+
//
|
|
49
|
+
function setValue(option: SelectOption) {
|
|
50
|
+
if (single) {
|
|
51
|
+
// Single
|
|
52
|
+
if (selected.value?.some(o => o.value === option.value) && !required) {
|
|
53
|
+
selected.value = undefined
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
selected.value = [option]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
if (selected.value && selected.value?.some(o => o.value === option.value)) {
|
|
61
|
+
const values = selected.value.filter(o => o.value !== option.value)
|
|
62
|
+
// Cant remove the last value if it's required
|
|
63
|
+
if ((required && values.length > 0) || !required) {
|
|
64
|
+
selected.value = values.length > 0 ? values : undefined
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
if (!selected.value) {
|
|
69
|
+
selected.value = [option]
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
selected.value?.push(option)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Search
|
|
79
|
+
const searchStr = ref()
|
|
80
|
+
const filteredOptions = computed(() => {
|
|
81
|
+
if (!searchStr.value || searchStr.value.length === 0)
|
|
82
|
+
return options
|
|
83
|
+
|
|
84
|
+
return options.filter((option) => {
|
|
85
|
+
return searchString(option.label, searchStr.value)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Render text inside the button
|
|
90
|
+
const renderPlaceholder = computed(() => {
|
|
91
|
+
// Render placeholder or a default select option
|
|
92
|
+
if (!selected.value || selected.value.length === 0)
|
|
93
|
+
return placeholder ?? 'Select an option'
|
|
94
|
+
|
|
95
|
+
// Selected values
|
|
96
|
+
if (single)
|
|
97
|
+
return selected.value[0].label
|
|
98
|
+
|
|
99
|
+
// If amount of selected exceeds the active capacity
|
|
100
|
+
if (selected.value.length > maxActiveOptions) {
|
|
101
|
+
return `${selected.value.length} selected`
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Just list ALL selected optionsx
|
|
105
|
+
return selected.value.map(o => o.label).join(', ')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
onMounted(() => {
|
|
109
|
+
if (readonly && showClear) {
|
|
110
|
+
console.warn('[Select] readonly and showClear are mutually exclusive props. The clear button will not show up if required is present.')
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
const dropdownRef = useTemplateRef('dropdown')
|
|
115
|
+
|
|
116
|
+
function clearValue() {
|
|
117
|
+
selected.value = undefined
|
|
118
|
+
dropdownRef.value?.close()
|
|
119
|
+
}
|
|
120
|
+
</script>
|
|
121
|
+
|
|
122
|
+
<template>
|
|
123
|
+
<div class="vui-input-container vui-select" :class="{ expand, required, readonly }">
|
|
124
|
+
<Dropdown ref="dropdown" :expand>
|
|
125
|
+
<template #trigger="{ toggle, isOpen }">
|
|
126
|
+
<div class="vui-input vui-select-trigger-content">
|
|
127
|
+
<label v-if="label" for="id">{{ label }}</label>
|
|
128
|
+
<p v-if="hint" class="vui-input-hint">
|
|
129
|
+
{{ hint }}
|
|
130
|
+
</p>
|
|
131
|
+
|
|
132
|
+
<button class="vui-input-style vui-select-trigger-container" @click="toggle">
|
|
133
|
+
<span>
|
|
134
|
+
{{ renderPlaceholder }}
|
|
135
|
+
</span>
|
|
136
|
+
<Button
|
|
137
|
+
v-if="showClear && !required && selected"
|
|
138
|
+
plain
|
|
139
|
+
icon="ph:x"
|
|
140
|
+
square
|
|
141
|
+
size="s"
|
|
142
|
+
@click.stop="clearValue"
|
|
143
|
+
/>
|
|
144
|
+
<Icon :icon="isOpen ? 'ph:caret-up' : 'ph:caret-down'" />
|
|
145
|
+
</button>
|
|
146
|
+
</div>
|
|
147
|
+
</template>
|
|
148
|
+
|
|
149
|
+
<template #default="{ close, isOpen }">
|
|
150
|
+
<DropdownTitle v-if="search">
|
|
151
|
+
<Input
|
|
152
|
+
v-model="searchStr"
|
|
153
|
+
placeholder="Search..."
|
|
154
|
+
:focus="isOpen"
|
|
155
|
+
/>
|
|
156
|
+
</DropdownTitle>
|
|
157
|
+
|
|
158
|
+
<p v-if="filteredOptions.length === 0" class="vue-select-no-results">
|
|
159
|
+
No results...
|
|
160
|
+
</p>
|
|
161
|
+
|
|
162
|
+
<DropdownItem
|
|
163
|
+
v-for="option in filteredOptions"
|
|
164
|
+
:key="option.value"
|
|
165
|
+
:class="{ selected: selected?.find(v => v.value === option.value) }"
|
|
166
|
+
:icon="selected?.find(v => v.value === option.value) ? 'ph:check-bold' : ''"
|
|
167
|
+
@click="() => {
|
|
168
|
+
setValue(option)
|
|
169
|
+
// In single mode, close modal after clicking
|
|
170
|
+
if (single && !(required && selected && selected[0].value === option.value)) {
|
|
171
|
+
close()
|
|
172
|
+
}
|
|
173
|
+
}"
|
|
174
|
+
>
|
|
175
|
+
{{ option.label }}
|
|
176
|
+
</DropdownItem>
|
|
177
|
+
</template>
|
|
178
|
+
</Dropdown>
|
|
179
|
+
</div>
|
|
180
|
+
</template>
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
.vui-input-container {
|
|
2
|
-
&.vui-select {
|
|
3
|
-
&.expand {
|
|
4
|
-
.vui-dropdown-trigger-wrap,
|
|
5
|
-
.vui-dropdown-trigger-content {
|
|
6
|
-
width: 100%;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
.vui-select-trigger-container {
|
|
11
|
-
span {
|
|
12
|
-
white-space: nowrap;
|
|
13
|
-
text-overflow: ellipsis;
|
|
14
|
-
overflow-x: hidden;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
.vue-select-no-results {
|
|
19
|
-
text-align: center;
|
|
20
|
-
padding-block: var(--space-xs);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
.vui-input-style {
|
|
24
|
-
display: flex;
|
|
25
|
-
align-items: center;
|
|
26
|
-
justify-content: space-between;
|
|
27
|
-
gap: var(--space-s);
|
|
28
|
-
|
|
29
|
-
& > button {
|
|
30
|
-
margin-right: -6px;
|
|
31
|
-
|
|
32
|
-
.vui-button-slot svg {
|
|
33
|
-
width: 14px;
|
|
34
|
-
height: 14px;
|
|
35
|
-
color: var(--color-text-light);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
&:hover {
|
|
40
|
-
border-color: var(--color-border-strong);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
1
|
+
.vui-input-container {
|
|
2
|
+
&.vui-select {
|
|
3
|
+
&.expand {
|
|
4
|
+
.vui-dropdown-trigger-wrap,
|
|
5
|
+
.vui-dropdown-trigger-content {
|
|
6
|
+
width: 100%;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.vui-select-trigger-container {
|
|
11
|
+
span {
|
|
12
|
+
white-space: nowrap;
|
|
13
|
+
text-overflow: ellipsis;
|
|
14
|
+
overflow-x: hidden;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.vue-select-no-results {
|
|
19
|
+
text-align: center;
|
|
20
|
+
padding-block: var(--space-xs);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.vui-input-style {
|
|
24
|
+
display: flex;
|
|
25
|
+
align-items: center;
|
|
26
|
+
justify-content: space-between;
|
|
27
|
+
gap: var(--space-s);
|
|
28
|
+
|
|
29
|
+
& > button {
|
|
30
|
+
margin-right: -6px;
|
|
31
|
+
|
|
32
|
+
.vui-button-slot svg {
|
|
33
|
+
width: 14px;
|
|
34
|
+
height: 14px;
|
|
35
|
+
color: var(--color-text-light);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&:hover {
|
|
40
|
+
border-color: var(--color-border-strong);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -1,92 +1,92 @@
|
|
|
1
|
-
<script setup lang='ts'>
|
|
2
|
-
import { computed } from 'vue'
|
|
3
|
-
import Backdrop from '../../internal/Backdrop/Backdrop.vue'
|
|
4
|
-
import { formatUnitValue } from '../../shared/helpers'
|
|
5
|
-
import Button from '../Button/Button.vue'
|
|
6
|
-
import Divider from '../Divider/Divider.vue'
|
|
7
|
-
import './sheet.scss'
|
|
8
|
-
|
|
9
|
-
interface Props {
|
|
10
|
-
position?: 'left' | 'right' | 'top' | 'bottom'
|
|
11
|
-
size?: number | string
|
|
12
|
-
separator?: boolean
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
position = 'right',
|
|
17
|
-
size = 398,
|
|
18
|
-
separator,
|
|
19
|
-
} = defineProps<Props>()
|
|
20
|
-
|
|
21
|
-
const TRANSITION_OFFSET = 16
|
|
22
|
-
|
|
23
|
-
const open = defineModel<boolean>()
|
|
24
|
-
|
|
25
|
-
function close() {
|
|
26
|
-
open.value = false
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const style = computed(() => {
|
|
30
|
-
if (position === 'left' || position === 'right') {
|
|
31
|
-
return { width: formatUnitValue(size) }
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return undefined
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
// Used to compute base location so that sheet appears to animate form the edge of the screen
|
|
38
|
-
const baseTransform = computed(() => {
|
|
39
|
-
switch (position) {
|
|
40
|
-
case 'left': return `translate(-${TRANSITION_OFFSET}px, 0)`
|
|
41
|
-
case 'top': return `translate(0, -${TRANSITION_OFFSET}px)`
|
|
42
|
-
case 'bottom': return `translate(0, ${TRANSITION_OFFSET}px)`
|
|
43
|
-
case 'right':
|
|
44
|
-
default: return `translate(${TRANSITION_OFFSET}px, 0)`
|
|
45
|
-
}
|
|
46
|
-
})
|
|
47
|
-
</script>
|
|
48
|
-
|
|
49
|
-
<template>
|
|
50
|
-
<Teleport to="body">
|
|
51
|
-
<Transition appear name="sheet">
|
|
52
|
-
<Backdrop v-if="open" @close="open = false">
|
|
53
|
-
<div v-if="open" class="vui-sheet" :class="[`vui-sheet-position-${position}`]" :style>
|
|
54
|
-
<div class="vui-sheet-header">
|
|
55
|
-
<div class="flex-1">
|
|
56
|
-
<slot name="header" :close />
|
|
57
|
-
</div>
|
|
58
|
-
<Button square icon="ph:x" @click="open = false" />
|
|
59
|
-
</div>
|
|
60
|
-
|
|
61
|
-
<Divider v-if="separator && $slots.header" :space="1" />
|
|
62
|
-
|
|
63
|
-
<div v-if="$slots.default" class="vui-sheet-content">
|
|
64
|
-
<slot :close />
|
|
65
|
-
</div>
|
|
66
|
-
</div>
|
|
67
|
-
</Backdrop>
|
|
68
|
-
</Transition>
|
|
69
|
-
</Teleport>
|
|
70
|
-
</template>
|
|
71
|
-
|
|
72
|
-
<style scoped lang="scss">
|
|
73
|
-
.vui-backdrop {
|
|
74
|
-
padding: 0;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.sheet-enter-active,
|
|
78
|
-
.sheet-leave-active {
|
|
79
|
-
transition: var(--transition);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
.sheet-enter-to,
|
|
83
|
-
.sheet-leave-from {
|
|
84
|
-
transform: translate(0, 0);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.sheet-enter-from,
|
|
88
|
-
.sheet-leave-to {
|
|
89
|
-
opacity: 0;
|
|
90
|
-
transform: v-bind(baseTransform);
|
|
91
|
-
}
|
|
92
|
-
</style>
|
|
1
|
+
<script setup lang='ts'>
|
|
2
|
+
import { computed } from 'vue'
|
|
3
|
+
import Backdrop from '../../internal/Backdrop/Backdrop.vue'
|
|
4
|
+
import { formatUnitValue } from '../../shared/helpers'
|
|
5
|
+
import Button from '../Button/Button.vue'
|
|
6
|
+
import Divider from '../Divider/Divider.vue'
|
|
7
|
+
import './sheet.scss'
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
position?: 'left' | 'right' | 'top' | 'bottom'
|
|
11
|
+
size?: number | string
|
|
12
|
+
separator?: boolean
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
position = 'right',
|
|
17
|
+
size = 398,
|
|
18
|
+
separator,
|
|
19
|
+
} = defineProps<Props>()
|
|
20
|
+
|
|
21
|
+
const TRANSITION_OFFSET = 16
|
|
22
|
+
|
|
23
|
+
const open = defineModel<boolean>()
|
|
24
|
+
|
|
25
|
+
function close() {
|
|
26
|
+
open.value = false
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const style = computed(() => {
|
|
30
|
+
if (position === 'left' || position === 'right') {
|
|
31
|
+
return { width: formatUnitValue(size) }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return undefined
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
// Used to compute base location so that sheet appears to animate form the edge of the screen
|
|
38
|
+
const baseTransform = computed(() => {
|
|
39
|
+
switch (position) {
|
|
40
|
+
case 'left': return `translate(-${TRANSITION_OFFSET}px, 0)`
|
|
41
|
+
case 'top': return `translate(0, -${TRANSITION_OFFSET}px)`
|
|
42
|
+
case 'bottom': return `translate(0, ${TRANSITION_OFFSET}px)`
|
|
43
|
+
case 'right':
|
|
44
|
+
default: return `translate(${TRANSITION_OFFSET}px, 0)`
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template>
|
|
50
|
+
<Teleport to="body">
|
|
51
|
+
<Transition appear name="sheet">
|
|
52
|
+
<Backdrop v-if="open" @close="open = false">
|
|
53
|
+
<div v-if="open" class="vui-sheet" :class="[`vui-sheet-position-${position}`]" :style>
|
|
54
|
+
<div class="vui-sheet-header">
|
|
55
|
+
<div class="flex-1">
|
|
56
|
+
<slot name="header" :close />
|
|
57
|
+
</div>
|
|
58
|
+
<Button square icon="ph:x" @click="open = false" />
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<Divider v-if="separator && $slots.header" :space="1" />
|
|
62
|
+
|
|
63
|
+
<div v-if="$slots.default" class="vui-sheet-content">
|
|
64
|
+
<slot :close />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</Backdrop>
|
|
68
|
+
</Transition>
|
|
69
|
+
</Teleport>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<style scoped lang="scss">
|
|
73
|
+
.vui-backdrop {
|
|
74
|
+
padding: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.sheet-enter-active,
|
|
78
|
+
.sheet-leave-active {
|
|
79
|
+
transition: var(--transition);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.sheet-enter-to,
|
|
83
|
+
.sheet-leave-from {
|
|
84
|
+
transform: translate(0, 0);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.sheet-enter-from,
|
|
88
|
+
.sheet-leave-to {
|
|
89
|
+
opacity: 0;
|
|
90
|
+
transform: v-bind(baseTransform);
|
|
91
|
+
}
|
|
92
|
+
</style>
|