@dolanske/vui 0.1.5 → 0.3.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/README.md +29 -98
- package/dist/components/Accordion/Accordion.vue.d.ts +1 -0
- package/dist/components/Avatar/Avatar.vue.d.ts +1 -1
- package/dist/components/Calendar/Calendar.vue.d.ts +1 -1
- package/dist/components/Divider/Divider.vue.d.ts +2 -4
- package/dist/components/Dropdown/Dropdown.vue.d.ts +105 -0
- package/dist/components/Flex/Flex.vue.d.ts +2 -2
- package/dist/components/Grid/Grid.vue.d.ts +2 -2
- package/dist/components/Input/Dropzone.vue.d.ts +1 -0
- package/dist/components/Input/Input.vue.d.ts +1 -0
- package/dist/components/Popout/Popout.vue.d.ts +3 -3
- package/dist/components/Radio/Radio.vue.d.ts +1 -1
- package/dist/components/Radio/RadioGroup.vue.d.ts +3 -12
- package/dist/components/Tooltip/Tooltip.vue.d.ts +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/shared/helpers.d.ts +6 -0
- package/dist/shared/types.d.ts +14 -0
- package/dist/style.css +1 -1
- package/dist/vui.js +4617 -4470
- package/package.json +6 -2
- package/src/App.vue +24 -16
- package/src/components/Accordion/Accordion.vue +8 -4
- package/src/components/Accordion/accordion.scss +38 -2
- package/src/components/Alert/alert.scss +1 -1
- package/src/components/Avatar/Avatar.vue +10 -3
- package/src/components/Avatar/avatar.scss +5 -5
- package/src/components/Button/Button.vue +6 -9
- package/src/components/Calendar/Calendar.vue +10 -8
- package/src/components/Card/Card.vue +2 -2
- package/src/components/Checkbox/Checkbox.vue +4 -1
- package/src/components/Checkbox/checkbox.scss +12 -6
- package/src/components/Divider/Divider.vue +18 -8
- package/src/components/Drawer/Drawer.vue +14 -10
- package/src/components/Drawer/drawer.scss +1 -14
- package/src/components/Dropdown/Dropdown.vue +14 -9
- package/src/components/Dropdown/dropdown.scss +4 -0
- package/src/components/Flex/Flex.vue +14 -17
- package/src/components/Grid/Grid.vue +9 -14
- package/src/components/Input/Input.vue +4 -1
- package/src/components/Input/Textarea.vue +7 -4
- package/src/components/Input/input.scss +13 -4
- package/src/components/OTP/otp.scss +1 -2
- package/src/components/Popout/Popout.vue +3 -3
- package/src/components/Progress/Progress.vue +13 -7
- package/src/components/Progress/progress.scss +1 -1
- package/src/components/Radio/Radio.vue +1 -1
- package/src/components/Radio/RadioGroup.vue +10 -5
- package/src/components/Sheet/Sheet.vue +16 -15
- package/src/components/Sheet/sheet.scss +4 -0
- package/src/components/Skeleton/Skeleton.vue +13 -16
- package/src/components/Spinner/Spinner.vue +9 -11
- package/src/components/Table/table.scss +1 -1
- package/src/components/Table/table.ts +2 -1
- package/src/components/Tabs/Tab.vue +1 -1
- package/src/components/Tabs/Tabs.vue +1 -0
- package/src/components/Toast/toast.ts +0 -24
- package/src/components/Tooltip/Tooltip.vue +6 -3
- package/src/index.ts +4 -0
- package/src/shared/helpers.ts +15 -0
- package/src/shared/types.ts +18 -0
- package/src/style/core.scss +28 -15
- package/src/style/fonts.scss +23 -0
- package/src/style/layout.scss +133 -1
- package/src/style/typography.scss +9 -9
- package/src/style/utils.scss +13 -0
- package/dist/shared/composables.d.ts +0 -3
- package/src/shared/composables.ts +0 -18
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type {
|
|
2
|
+
import type { Space } from '../../shared/types'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
|
-
import { useActualGap } from '../../shared/composables'
|
|
5
4
|
|
|
6
5
|
export interface FlexProps {
|
|
7
6
|
inline?: boolean
|
|
@@ -13,7 +12,7 @@ export interface FlexProps {
|
|
|
13
12
|
rowReverse?: boolean
|
|
14
13
|
columnReverse?: boolean
|
|
15
14
|
|
|
16
|
-
gap?:
|
|
15
|
+
gap?: Space | number
|
|
17
16
|
|
|
18
17
|
// NOTE: Add more if needed
|
|
19
18
|
justifyStart?: boolean
|
|
@@ -35,7 +34,7 @@ export interface FlexProps {
|
|
|
35
34
|
const props = defineProps<FlexProps>()
|
|
36
35
|
|
|
37
36
|
// Flex gap
|
|
38
|
-
const ag =
|
|
37
|
+
const ag = computed(() => `var(--space-${props.gap})`)
|
|
39
38
|
|
|
40
39
|
// Flex direction
|
|
41
40
|
const ad = computed(() => {
|
|
@@ -91,19 +90,17 @@ const aH = computed(() => props.expand ? '100%' : 'auto')
|
|
|
91
90
|
</script>
|
|
92
91
|
|
|
93
92
|
<template>
|
|
94
|
-
<div
|
|
93
|
+
<div
|
|
94
|
+
class="vui-flex" :style="{
|
|
95
|
+
display: aY,
|
|
96
|
+
flexWrap: aW,
|
|
97
|
+
flexDirection: ad,
|
|
98
|
+
justifyContent: aj,
|
|
99
|
+
gap: ag,
|
|
100
|
+
alignItems: aA,
|
|
101
|
+
width: aH,
|
|
102
|
+
}"
|
|
103
|
+
>
|
|
95
104
|
<slot />
|
|
96
105
|
</div>
|
|
97
106
|
</template>
|
|
98
|
-
|
|
99
|
-
<style scoped lang="scss">
|
|
100
|
-
.vui-flex {
|
|
101
|
-
display: v-bind(aY);
|
|
102
|
-
flex-wrap: v-bind(aW);
|
|
103
|
-
flex-direction: v-bind(ad);
|
|
104
|
-
justify-content: v-bind(aj);
|
|
105
|
-
gap: v-bind(ag);
|
|
106
|
-
align-items: v-bind(aA);
|
|
107
|
-
width: v-bind(aH);
|
|
108
|
-
}
|
|
109
|
-
</style>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import type {
|
|
2
|
+
import type { Space } from '../../shared/types'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
|
-
import { useActualGap } from '../../shared/composables'
|
|
5
4
|
import { createArray } from '../../shared/helpers'
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -10,7 +9,7 @@ import { createArray } from '../../shared/helpers'
|
|
|
10
9
|
|
|
11
10
|
interface Props {
|
|
12
11
|
inline?: boolean
|
|
13
|
-
gap?:
|
|
12
|
+
gap?: Space | number
|
|
14
13
|
rows?: number | string
|
|
15
14
|
columns?: number | string
|
|
16
15
|
areas?: string[]
|
|
@@ -18,7 +17,7 @@ interface Props {
|
|
|
18
17
|
|
|
19
18
|
const props = defineProps<Props>()
|
|
20
19
|
|
|
21
|
-
const
|
|
20
|
+
const ag = computed(() => `var(--space-${props.gap})`)
|
|
22
21
|
|
|
23
22
|
const aTC = computed(() => {
|
|
24
23
|
if (typeof props.columns === 'number') {
|
|
@@ -43,17 +42,13 @@ const aD = computed(() => props.inline ? 'inline-grid' : 'grid')
|
|
|
43
42
|
|
|
44
43
|
<template>
|
|
45
44
|
<div
|
|
46
|
-
class="vui-grid"
|
|
45
|
+
class="vui-grid" :style="{
|
|
46
|
+
display: aD,
|
|
47
|
+
gap: ag,
|
|
48
|
+
gridTemplateColumns: aTC,
|
|
49
|
+
gridTemplateRows: aTR,
|
|
50
|
+
}"
|
|
47
51
|
>
|
|
48
52
|
<slot />
|
|
49
53
|
</div>
|
|
50
54
|
</template>
|
|
51
|
-
|
|
52
|
-
<style scoped lang="scss">
|
|
53
|
-
.vui-grid {
|
|
54
|
-
display: v-bind(aD);
|
|
55
|
-
gap: v-bind(aG);
|
|
56
|
-
grid-template-columns: v-bind(aTC);
|
|
57
|
-
grid-template-rows: v-bind(aTR);
|
|
58
|
-
}
|
|
59
|
-
</style>
|
|
@@ -23,6 +23,7 @@ export interface InputProps {
|
|
|
23
23
|
multiple?: boolean
|
|
24
24
|
min?: number
|
|
25
25
|
max?: number
|
|
26
|
+
disabled?: boolean
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const {
|
|
@@ -40,6 +41,7 @@ const {
|
|
|
40
41
|
min,
|
|
41
42
|
max,
|
|
42
43
|
errors = [] as string[],
|
|
44
|
+
disabled,
|
|
43
45
|
} = defineProps<InputProps>()
|
|
44
46
|
|
|
45
47
|
const model = defineModel<string | number>({
|
|
@@ -76,7 +78,7 @@ const renderLimit = computed(() => {
|
|
|
76
78
|
</script>
|
|
77
79
|
|
|
78
80
|
<template>
|
|
79
|
-
<div class="vui-input-container" :class="{ expand, required, readonly, 'has-errors': errors.length > 0 }">
|
|
81
|
+
<div class="vui-input-container" :class="{ expand, disabled, required, readonly, 'has-errors': errors.length > 0 }">
|
|
80
82
|
<slot name="before" />
|
|
81
83
|
<div class="vui-input">
|
|
82
84
|
<label v-if="label" for="id">{{ label }}</label>
|
|
@@ -100,6 +102,7 @@ const renderLimit = computed(() => {
|
|
|
100
102
|
:accept
|
|
101
103
|
:multiple
|
|
102
104
|
:min
|
|
105
|
+
:disabled
|
|
103
106
|
>
|
|
104
107
|
<slot name="end" />
|
|
105
108
|
</Flex>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { InputProps } from './Input.vue'
|
|
3
|
-
import { useId } from 'vue'
|
|
3
|
+
import { computed, useId } from 'vue'
|
|
4
4
|
import '../Input/input.scss'
|
|
5
5
|
|
|
6
6
|
type Props = Omit<InputProps, 'type'> & {
|
|
@@ -35,6 +35,9 @@ const model = defineModel<string>({
|
|
|
35
35
|
},
|
|
36
36
|
})
|
|
37
37
|
const id = useId()
|
|
38
|
+
|
|
39
|
+
const r = computed(() => resize === true ? 'both' : (resize || 'initial'))
|
|
40
|
+
const fS = computed(() => autoResize ? 'content' : 'auto')
|
|
38
41
|
</script>
|
|
39
42
|
|
|
40
43
|
<template>
|
|
@@ -54,9 +57,9 @@ const id = useId()
|
|
|
54
57
|
:required
|
|
55
58
|
:max="limit"
|
|
56
59
|
:style="{
|
|
57
|
-
|
|
58
|
-
// @ts-expect-error
|
|
59
|
-
|
|
60
|
+
resize: r,
|
|
61
|
+
// @ts-expect-error Early-adoption CSS attribute
|
|
62
|
+
fieldSizing: fS,
|
|
60
63
|
}"
|
|
61
64
|
/>
|
|
62
65
|
</div>
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
|
|
18
18
|
width: 224px;
|
|
19
19
|
|
|
20
|
+
&.disabled input,
|
|
21
|
+
&.disabled textarea {
|
|
22
|
+
cursor: not-allowed;
|
|
23
|
+
}
|
|
24
|
+
|
|
20
25
|
&.expand {
|
|
21
26
|
width: 100%;
|
|
22
27
|
}
|
|
@@ -26,10 +31,14 @@
|
|
|
26
31
|
color: var(--input-color-text-red);
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
&.readonly .vui-input
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
&.readonly .vui-input {
|
|
35
|
+
input,
|
|
36
|
+
textarea,
|
|
37
|
+
.vui-input-style {
|
|
38
|
+
pointer-events: none;
|
|
39
|
+
color: var(--input-color-text-light);
|
|
40
|
+
border-color: var(--input-color-border-weak);
|
|
41
|
+
}
|
|
33
42
|
}
|
|
34
43
|
|
|
35
44
|
&.has-errors {
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
border: 1px solid var(--color-border-strong);
|
|
16
16
|
color: var(--color-text);
|
|
17
17
|
z-index: 1;
|
|
18
|
-
font-size: var(--font-size-
|
|
18
|
+
font-size: var(--font-size-m);
|
|
19
19
|
outline: 0 solid var(--color-text-light);
|
|
20
20
|
transition: var(--transition);
|
|
21
21
|
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
// TODO: animate blinking cursor
|
|
51
50
|
&.active {
|
|
52
51
|
z-index: 2;
|
|
53
52
|
outline-width: 2px;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
|
-
import type {
|
|
2
|
+
import type { Placement, PopoutMaybeElement } from '../../shared/types'
|
|
3
3
|
import { autoPlacement, offset, useFloating } from '@floating-ui/vue'
|
|
4
4
|
import { toRef, useTemplateRef } from 'vue'
|
|
5
5
|
import './popout.scss'
|
|
6
6
|
|
|
7
|
-
interface Props {
|
|
8
|
-
anchor:
|
|
7
|
+
export interface Props {
|
|
8
|
+
anchor: PopoutMaybeElement<HTMLElement>
|
|
9
9
|
/**
|
|
10
10
|
* Override the autoPlacement option
|
|
11
11
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
|
-
import { onMounted, useTemplateRef, watchEffect } from 'vue'
|
|
3
|
-
import { delay, isNil, randomMinMax } from '../../shared/helpers'
|
|
2
|
+
import { computed, onMounted, useTemplateRef, watchEffect } from 'vue'
|
|
3
|
+
import { delay, formatUnitValue, isNil, randomMinMax } from '../../shared/helpers'
|
|
4
4
|
import './progress.scss'
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
@@ -42,16 +42,19 @@ const progressRef = useTemplateRef('progress')
|
|
|
42
42
|
|
|
43
43
|
watchEffect(() => {
|
|
44
44
|
if (progressRef.value && !isNil(height)) {
|
|
45
|
-
progressRef.value.style.setProperty(
|
|
45
|
+
progressRef.value.style.setProperty(
|
|
46
|
+
'--vui-progress-height',
|
|
47
|
+
formatUnitValue(height),
|
|
48
|
+
)
|
|
46
49
|
}
|
|
47
50
|
})
|
|
48
51
|
|
|
49
52
|
// Automatically / randomly increment but never reach 100% until
|
|
50
53
|
async function fakeIncrement() {
|
|
51
54
|
if (fake && progressAmount.value < 100) {
|
|
52
|
-
if (progressAmount.value >
|
|
55
|
+
if (progressAmount.value > 90) {
|
|
53
56
|
// Only in crement by the fraction of the remaining amount
|
|
54
|
-
progressAmount.value += (100 - progressAmount.value) * 0.
|
|
57
|
+
progressAmount.value += (100 - progressAmount.value) * 0.05
|
|
55
58
|
await delay(randomMinMax(500, 3000))
|
|
56
59
|
}
|
|
57
60
|
else {
|
|
@@ -63,6 +66,9 @@ async function fakeIncrement() {
|
|
|
63
66
|
}
|
|
64
67
|
|
|
65
68
|
onMounted(fakeIncrement)
|
|
69
|
+
|
|
70
|
+
const w = computed(() => `${progressAmount.value}%`)
|
|
71
|
+
const bC = computed(() => color)
|
|
66
72
|
</script>
|
|
67
73
|
|
|
68
74
|
<template>
|
|
@@ -76,8 +82,8 @@ onMounted(fakeIncrement)
|
|
|
76
82
|
>
|
|
77
83
|
<div
|
|
78
84
|
class="vui-progress-indicator" :style="{
|
|
79
|
-
width:
|
|
80
|
-
backgroundColor:
|
|
85
|
+
width: w,
|
|
86
|
+
backgroundColor: bC,
|
|
81
87
|
}"
|
|
82
88
|
/>
|
|
83
89
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
.vui-progress {
|
|
2
2
|
--vui-progress-height: 3px;
|
|
3
|
+
|
|
3
4
|
display: block;
|
|
4
5
|
width: 100%;
|
|
5
6
|
position: relative;
|
|
@@ -18,7 +19,6 @@
|
|
|
18
19
|
border-radius: none !important;
|
|
19
20
|
|
|
20
21
|
&.fixed-active {
|
|
21
|
-
// Some arbitrary value which should never happen to people with
|
|
22
22
|
height: var(--vui-progress-height);
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
|
-
import type { VNode } from 'vue'
|
|
3
2
|
import type { FlexProps } from '../Flex/Flex.vue'
|
|
4
|
-
import type
|
|
3
|
+
import type Radio from './Radio.vue'
|
|
4
|
+
import { watchEffect } from 'vue'
|
|
5
5
|
import Flex from '../Flex/Flex.vue'
|
|
6
6
|
|
|
7
7
|
interface Props extends FlexProps {
|
|
@@ -14,22 +14,27 @@ const {
|
|
|
14
14
|
} = defineProps<Props>()
|
|
15
15
|
|
|
16
16
|
const slots = defineSlots<{
|
|
17
|
-
default: () =>
|
|
17
|
+
default: () => Array<typeof Radio>
|
|
18
18
|
}>()
|
|
19
19
|
|
|
20
20
|
const checked = defineModel()
|
|
21
|
+
|
|
22
|
+
watchEffect(() => {
|
|
23
|
+
if (slots.default().some(s => s.type.__name !== 'Radio')) {
|
|
24
|
+
console.error('You can only pass `<Radio />` components as children.')
|
|
25
|
+
}
|
|
26
|
+
})
|
|
21
27
|
</script>
|
|
22
28
|
|
|
23
29
|
<template>
|
|
24
30
|
<Flex v-bind="flexProps">
|
|
25
31
|
<Component
|
|
26
32
|
:is="vnode"
|
|
27
|
-
v-for="vnode of slots.default()
|
|
33
|
+
v-for="vnode of slots.default()"
|
|
28
34
|
:key="vnode.props.value"
|
|
29
35
|
v-bind="vnode.props"
|
|
30
36
|
v-model="checked"
|
|
31
37
|
:class="{ disabled: disabled || vnode.props.disabled }"
|
|
32
38
|
/>
|
|
33
39
|
</Flex>
|
|
34
|
-
<!-- <div class="vui-radio-group" /> -->
|
|
35
40
|
</template>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import Backdrop from '../../internal/Backdrop/Backdrop.vue'
|
|
4
|
+
import { formatUnitValue } from '../../shared/helpers'
|
|
4
5
|
import Button from '../Button/Button.vue'
|
|
5
6
|
import Divider from '../Divider/Divider.vue'
|
|
6
7
|
import './sheet.scss'
|
|
@@ -17,6 +18,8 @@ const {
|
|
|
17
18
|
separator,
|
|
18
19
|
} = defineProps<Props>()
|
|
19
20
|
|
|
21
|
+
const TRANSITION_OFFSET = 16
|
|
22
|
+
|
|
20
23
|
const open = defineModel<boolean>()
|
|
21
24
|
|
|
22
25
|
function close() {
|
|
@@ -24,27 +27,21 @@ function close() {
|
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
const style = computed(() => {
|
|
27
|
-
const formattedSizeValue = typeof size === 'number' ? `${size}px` : size
|
|
28
|
-
let style
|
|
29
|
-
|
|
30
30
|
if (position === 'left' || position === 'right') {
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
style = { minHeight: formattedSizeValue }
|
|
31
|
+
return { width: formatUnitValue(size) }
|
|
35
32
|
}
|
|
36
33
|
|
|
37
|
-
return
|
|
34
|
+
return undefined
|
|
38
35
|
})
|
|
39
36
|
|
|
40
37
|
// Used to compute base location so that sheet appears to animate form the edge of the screen
|
|
41
38
|
const baseTransform = computed(() => {
|
|
42
39
|
switch (position) {
|
|
43
|
-
case 'left': return `translate(
|
|
44
|
-
case 'top': return `translate(0,
|
|
45
|
-
case 'bottom': return `translate(0,
|
|
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)`
|
|
46
43
|
case 'right':
|
|
47
|
-
default: return `translate(
|
|
44
|
+
default: return `translate(${TRANSITION_OFFSET}px, 0)`
|
|
48
45
|
}
|
|
49
46
|
})
|
|
50
47
|
</script>
|
|
@@ -52,16 +49,16 @@ const baseTransform = computed(() => {
|
|
|
52
49
|
<template>
|
|
53
50
|
<Teleport to="body">
|
|
54
51
|
<Transition appear name="sheet">
|
|
55
|
-
<Backdrop v-if="open"
|
|
52
|
+
<Backdrop v-if="open" @close="open = false">
|
|
56
53
|
<div v-if="open" class="vui-sheet" :class="[`vui-sheet-position-${position}`]" :style>
|
|
57
54
|
<div class="vui-sheet-header">
|
|
58
|
-
<div
|
|
55
|
+
<div class="flex-1">
|
|
59
56
|
<slot name="header" :close />
|
|
60
57
|
</div>
|
|
61
58
|
<Button square icon="ph:x" @click="open = false" />
|
|
62
59
|
</div>
|
|
63
60
|
|
|
64
|
-
<Divider v-if="separator && $slots.header" :
|
|
61
|
+
<Divider v-if="separator && $slots.header" :space="1" />
|
|
65
62
|
|
|
66
63
|
<div v-if="$slots.default" class="vui-sheet-content">
|
|
67
64
|
<slot :close />
|
|
@@ -73,6 +70,10 @@ const baseTransform = computed(() => {
|
|
|
73
70
|
</template>
|
|
74
71
|
|
|
75
72
|
<style scoped lang="scss">
|
|
73
|
+
.vui-backdrop {
|
|
74
|
+
padding: 0;
|
|
75
|
+
}
|
|
76
|
+
|
|
76
77
|
.sheet-enter-active,
|
|
77
78
|
.sheet-leave-active {
|
|
78
79
|
transition: var(--transition);
|
|
@@ -9,20 +9,24 @@
|
|
|
9
9
|
&.vui-sheet-position-top {
|
|
10
10
|
top: 0;
|
|
11
11
|
border-bottom: 1px solid var(--color-border);
|
|
12
|
+
height: auto;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
&.vui-sheet-position-bottom {
|
|
15
16
|
bottom: 0;
|
|
16
17
|
border-top: 1px solid var(--color-border);
|
|
18
|
+
height: auto;
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
&.vui-sheet-position-right {
|
|
20
22
|
right: 0;
|
|
23
|
+
top: 0;
|
|
21
24
|
border-left: 1px solid var(--color-border);
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
&.vui-sheet-position-left {
|
|
25
28
|
left: 0;
|
|
29
|
+
top: 0;
|
|
26
30
|
border-right: 1px solid var(--color-border);
|
|
27
31
|
}
|
|
28
32
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<!-- eslint-disable ts/no-use-before-define -->
|
|
2
2
|
<script setup lang='ts'>
|
|
3
|
+
import { computed } from 'vue'
|
|
4
|
+
import { formatUnitValue } from '../../shared/helpers'
|
|
3
5
|
import './skeleton.scss'
|
|
4
6
|
|
|
5
7
|
interface Props {
|
|
@@ -20,27 +22,22 @@ const {
|
|
|
20
22
|
|
|
21
23
|
const DEFAULT_RADIUS = 'var(--border-radius-s)'
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
25
|
+
// Give priority to radius, if it is NOT set to default
|
|
26
|
+
const bR = computed(() => formatUnitValue(circle && radius === DEFAULT_RADIUS ? 9999 : radius))
|
|
27
|
+
|
|
28
|
+
// When using `circle` prop, we want to use the same
|
|
29
|
+
// value for both height and width, but we can't
|
|
30
|
+
// know which one will be defined
|
|
31
|
+
const w = computed(() => formatUnitValue(circle ? (width || height) : width))
|
|
32
|
+
const h = computed(() => formatUnitValue(circle ? (width || height) : height))
|
|
32
33
|
</script>
|
|
33
34
|
|
|
34
35
|
<template>
|
|
35
36
|
<div
|
|
36
37
|
class="vui-skeleton" :style="{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
// value for both height and width, but we can't
|
|
41
|
-
// know which one will be defined
|
|
42
|
-
width: valueToPixels(circle ? (width || height) : width),
|
|
43
|
-
height: valueToPixels(circle ? (width || height) : height),
|
|
38
|
+
borderRadius: bR,
|
|
39
|
+
width: w,
|
|
40
|
+
height: h,
|
|
44
41
|
}"
|
|
45
42
|
/>
|
|
46
43
|
</template>
|
|
@@ -12,7 +12,7 @@ const {
|
|
|
12
12
|
size = 's',
|
|
13
13
|
} = defineProps<Props>()
|
|
14
14
|
|
|
15
|
-
const
|
|
15
|
+
const w = computed(() => {
|
|
16
16
|
switch (size) {
|
|
17
17
|
case Size.s: return '16px'
|
|
18
18
|
case Size.l: return '38px'
|
|
@@ -21,7 +21,7 @@ const actualSize = computed(() => {
|
|
|
21
21
|
}
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const bW = computed(() => {
|
|
25
25
|
switch (size) {
|
|
26
26
|
case Size.s: return '3px'
|
|
27
27
|
case Size.l: return '5px'
|
|
@@ -32,13 +32,11 @@ const actualBorderWidth = computed(() => {
|
|
|
32
32
|
</script>
|
|
33
33
|
|
|
34
34
|
<template>
|
|
35
|
-
<div
|
|
35
|
+
<div
|
|
36
|
+
:class="{ size }" class="vui-spinner" :style="{
|
|
37
|
+
width: w,
|
|
38
|
+
height: w,
|
|
39
|
+
borderWidth: bW,
|
|
40
|
+
}"
|
|
41
|
+
/>
|
|
36
42
|
</template>
|
|
37
|
-
|
|
38
|
-
<style lang="scss">
|
|
39
|
-
.vui-spinner {
|
|
40
|
-
width: v-bind(actualSize);
|
|
41
|
-
height: v-bind(actualSize);
|
|
42
|
-
border-width: v-bind(actualBorderWidth);
|
|
43
|
-
}
|
|
44
|
-
</style>
|
|
@@ -125,7 +125,8 @@ export function defineTable<const Dataset extends Array<BaseRow>>(
|
|
|
125
125
|
const key = sorting.value.key
|
|
126
126
|
|
|
127
127
|
if (key) {
|
|
128
|
-
|
|
128
|
+
// FIXME: change to `toSorted` when typescript is ok
|
|
129
|
+
final = [...final].sort((a: Dataset[number], b: Dataset[number]) => {
|
|
129
130
|
const aValue = a[key]
|
|
130
131
|
const bValue = b[key]
|
|
131
132
|
return sorting.value.type === 'asc'
|
|
@@ -14,7 +14,7 @@ const id = computed(() => props.id ?? props.label)
|
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
<template>
|
|
17
|
-
<button class="vui-tab" :data-tab-id="id" :class="{ disabled: props.disabled }">
|
|
17
|
+
<button class="vui-tab" :data-tab-id="id" :class="{ disabled: props.disabled }" role="tab">
|
|
18
18
|
<Icon v-if="props.icon" :icon="props.icon" />
|
|
19
19
|
{{ props.label }}
|
|
20
20
|
</button>
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// share some tiny global state
|
|
2
|
-
|
|
3
1
|
import { ref } from 'vue'
|
|
4
2
|
|
|
5
3
|
interface ToastAction {
|
|
@@ -68,25 +66,3 @@ export function pushToast(title: string, options?: ToastOptions): Toast {
|
|
|
68
66
|
export function removeToast(id: number): void {
|
|
69
67
|
toasts.value.delete(id)
|
|
70
68
|
}
|
|
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
|
-
// }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
|
-
import type { Placement } from '
|
|
3
|
-
import { ref, useTemplateRef, watch } from 'vue'
|
|
2
|
+
import type { Placement } from '../../shared/types'
|
|
3
|
+
import { ref, useId, useTemplateRef, watch } from 'vue'
|
|
4
4
|
import Popout from '../Popout/Popout.vue'
|
|
5
5
|
import './tooltip.scss'
|
|
6
6
|
|
|
@@ -50,18 +50,21 @@ watch(hoverAnchor, (isHovering) => {
|
|
|
50
50
|
showTooltip.value = false
|
|
51
51
|
}
|
|
52
52
|
})
|
|
53
|
+
|
|
54
|
+
const id = useId()
|
|
53
55
|
</script>
|
|
54
56
|
|
|
55
57
|
<template>
|
|
56
58
|
<div
|
|
57
59
|
ref="popoutAnchor"
|
|
60
|
+
:aria-describedby="id"
|
|
58
61
|
@mouseenter="hoverAnchor = true"
|
|
59
62
|
@mouseleave="hoverAnchor = false"
|
|
60
63
|
>
|
|
61
64
|
<slot />
|
|
62
65
|
</div>
|
|
63
66
|
<Transition appear name="tooltip">
|
|
64
|
-
<Popout v-if="showTooltip" :anchor="popoutAnchorRef" class="vui-tooltip" :placement>
|
|
67
|
+
<Popout v-if="showTooltip" :id :anchor="popoutAnchorRef" class="vui-tooltip" :placement name="tooltip">
|
|
65
68
|
<slot name="tooltip" />
|
|
66
69
|
</Popout>
|
|
67
70
|
</Transition>
|