@saasmakers/ui 0.1.107 → 0.1.108
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/app/components/bases/BaseAlert.vue +13 -10
- package/app/components/bases/BaseAvatar.vue +27 -2
- package/app/components/bases/BaseCharacter.vue +8 -7
- package/app/components/bases/BaseChart.vue +21 -19
- package/app/components/bases/BaseEmoji.vue +11 -2
- package/app/components/bases/BaseHeading.stories.ts +1 -1
- package/app/components/bases/BaseHeading.vue +7 -1
- package/app/components/bases/BaseIcon.vue +41 -25
- package/app/components/bases/BaseMessage.vue +4 -6
- package/app/components/bases/BaseMetric.vue +9 -8
- package/app/components/bases/BaseOverlay.vue +17 -3
- package/app/components/bases/BaseParagraph.stories.ts +1 -1
- package/app/components/bases/BaseParagraph.vue +7 -1
- package/app/components/bases/BaseQuote.stories.ts +1 -1
- package/app/components/bases/BaseQuote.vue +19 -17
- package/app/components/bases/BaseSpinner.vue +10 -1
- package/app/components/bases/BaseTag.vue +21 -1
- package/app/components/bases/BaseTags.vue +3 -4
- package/app/components/bases/BaseToast.vue +10 -1
- package/app/components/fields/FieldDays.vue +2 -1
- package/app/components/fields/FieldEmojis.vue +3 -3
- package/app/components/fields/FieldLabel.vue +24 -8
- package/app/components/fields/FieldMessage.vue +60 -92
- package/app/components/fields/FieldSelect.vue +33 -8
- package/app/components/fields/FieldTime.vue +12 -1
- package/app/composables/useChartist.ts +1 -1
- package/app/composables/useDevice.ts +1 -0
- package/app/composables/useLayerUtils.ts +16 -16
- package/app/composables/useToasts.ts +1 -1
- package/app/composables/useTranslation.ts +1 -1
- package/app/types/bases.d.ts +2 -0
- package/nuxt.config.ts +6 -6
- package/package.json +17 -13
|
@@ -25,17 +25,20 @@ const { getIcon } = useLayerIcons()
|
|
|
25
25
|
const isClosed = ref(false)
|
|
26
26
|
|
|
27
27
|
const buttonColor = computed<BaseColor>(() => {
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
switch (props.status) {
|
|
29
|
+
case 'error': {
|
|
30
|
+
return 'red'
|
|
31
|
+
}
|
|
32
|
+
case 'success': {
|
|
33
|
+
return 'green'
|
|
34
|
+
}
|
|
35
|
+
case 'warning': {
|
|
36
|
+
return 'orange'
|
|
37
|
+
}
|
|
38
|
+
default: {
|
|
39
|
+
return 'indigo'
|
|
40
|
+
}
|
|
30
41
|
}
|
|
31
|
-
else if (props.status === 'success') {
|
|
32
|
-
return 'green'
|
|
33
|
-
}
|
|
34
|
-
else if (props.status === 'warning') {
|
|
35
|
-
return 'orange'
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return 'indigo'
|
|
39
42
|
})
|
|
40
43
|
|
|
41
44
|
onBeforeMount(async () => {
|
|
@@ -31,6 +31,10 @@ const loaded = ref(false)
|
|
|
31
31
|
|
|
32
32
|
const { t } = useI18n()
|
|
33
33
|
|
|
34
|
+
const isClickable = computed(() => {
|
|
35
|
+
return props.to || props.editable
|
|
36
|
+
})
|
|
37
|
+
|
|
34
38
|
function onAvatarSelected(event: Event) {
|
|
35
39
|
const file = (event.target as HTMLInputElement).files?.[0]
|
|
36
40
|
|
|
@@ -43,6 +47,10 @@ function onAvatarSelected(event: Event) {
|
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
49
|
|
|
50
|
+
function onBlur() {
|
|
51
|
+
hovered.value = false
|
|
52
|
+
}
|
|
53
|
+
|
|
46
54
|
function onClick(event: MouseEvent) {
|
|
47
55
|
emit('click', event)
|
|
48
56
|
|
|
@@ -56,6 +64,16 @@ function onError() {
|
|
|
56
64
|
loaded.value = true
|
|
57
65
|
}
|
|
58
66
|
|
|
67
|
+
function onFocus() {
|
|
68
|
+
hovered.value = true
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function onKeydown(event: KeyboardEvent) {
|
|
72
|
+
if ((event.key === 'Enter' || event.key === ' ') && isClickable.value) {
|
|
73
|
+
onClick(event as unknown as MouseEvent)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
59
77
|
function onLoad() {
|
|
60
78
|
loaded.value = true
|
|
61
79
|
}
|
|
@@ -76,6 +94,8 @@ function onMouseLeave() {
|
|
|
76
94
|
:to="to"
|
|
77
95
|
@mouseenter="onMouseEnter"
|
|
78
96
|
@mouseleave="onMouseLeave"
|
|
97
|
+
@focusin="onFocus"
|
|
98
|
+
@focusout="onBlur"
|
|
79
99
|
>
|
|
80
100
|
<div
|
|
81
101
|
:aria-label="editable ? t('edit') : undefined"
|
|
@@ -83,10 +103,13 @@ function onMouseLeave() {
|
|
|
83
103
|
:class="{
|
|
84
104
|
'rounded-full': circular,
|
|
85
105
|
'shadow': shadow,
|
|
86
|
-
'cursor-pointer':
|
|
106
|
+
'cursor-pointer': isClickable,
|
|
87
107
|
}"
|
|
88
|
-
|
|
108
|
+
role="button"
|
|
109
|
+
:aria-disabled="!isClickable"
|
|
110
|
+
tabindex="0"
|
|
89
111
|
@click="onClick"
|
|
112
|
+
@keydown.prevent="onKeydown"
|
|
90
113
|
>
|
|
91
114
|
<img
|
|
92
115
|
class="h-full w-full object-cover drag-none"
|
|
@@ -97,6 +120,7 @@ function onMouseLeave() {
|
|
|
97
120
|
'border-3': borderWidth === 3,
|
|
98
121
|
'border-4': borderWidth === 4,
|
|
99
122
|
}"
|
|
123
|
+
:alt="editable ? t('edit') : ''"
|
|
100
124
|
loading="lazy"
|
|
101
125
|
:src="!error && src ? src : '/images/bases/BaseAvatar/default.svg'"
|
|
102
126
|
@error="onError"
|
|
@@ -114,6 +138,7 @@ function onMouseLeave() {
|
|
|
114
138
|
v-if="editable"
|
|
115
139
|
ref="fileInput"
|
|
116
140
|
accept="image/*"
|
|
141
|
+
:aria-label="t('edit')"
|
|
117
142
|
class="hidden"
|
|
118
143
|
type="file"
|
|
119
144
|
@change="onAvatarSelected"
|
|
@@ -15,17 +15,18 @@ const width = computed(() => {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
switch (props.character) {
|
|
18
|
-
case 'nada':
|
|
18
|
+
case 'nada': {
|
|
19
19
|
return size[props.size] + 4
|
|
20
|
-
|
|
21
|
-
case 'power':
|
|
20
|
+
}
|
|
21
|
+
case 'power': {
|
|
22
22
|
return size[props.size] + 3
|
|
23
|
-
|
|
24
|
-
case 'yoda':
|
|
23
|
+
}
|
|
24
|
+
case 'yoda': {
|
|
25
25
|
return size[props.size] + 8
|
|
26
|
-
|
|
27
|
-
default:
|
|
26
|
+
}
|
|
27
|
+
default: {
|
|
28
28
|
return size[props.size]
|
|
29
|
+
}
|
|
29
30
|
}
|
|
30
31
|
})
|
|
31
32
|
</script>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { BarChart, LineChart, PieChart } from 'chartist'
|
|
3
3
|
import type { BaseChart } from '../../types/bases'
|
|
4
4
|
|
|
5
|
-
const
|
|
5
|
+
const properties = withDefaults(defineProps<BaseChart>(), {
|
|
6
6
|
data: () => ({
|
|
7
7
|
labels: [],
|
|
8
8
|
series: [],
|
|
@@ -16,18 +16,12 @@ const chart = ref()
|
|
|
16
16
|
const root = ref<HTMLDivElement>()
|
|
17
17
|
|
|
18
18
|
watch(
|
|
19
|
-
() =>
|
|
19
|
+
() => properties.data,
|
|
20
20
|
() => {
|
|
21
21
|
if (chart.value) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
else if (props.type === 'bar') {
|
|
26
|
-
chart.value.update((props.data as ChartistBarChartData), props.options)
|
|
27
|
-
}
|
|
28
|
-
else if (props.type === 'pie') {
|
|
29
|
-
chart.value.update((props.data as ChartistPieChartData), props.options)
|
|
30
|
-
}
|
|
22
|
+
const data = properties.data
|
|
23
|
+
|
|
24
|
+
return chart.value.update(data, properties.options)
|
|
31
25
|
}
|
|
32
26
|
},
|
|
33
27
|
{ deep: true },
|
|
@@ -35,14 +29,22 @@ watch(
|
|
|
35
29
|
|
|
36
30
|
onMounted(() => {
|
|
37
31
|
if (root.value) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
switch (properties.type) {
|
|
33
|
+
case 'bar': {
|
|
34
|
+
chart.value = new BarChart(root.value, (properties.data as ChartistBarChartData), properties.options)
|
|
35
|
+
|
|
36
|
+
break
|
|
37
|
+
}
|
|
38
|
+
case 'line': {
|
|
39
|
+
chart.value = new LineChart(root.value, (properties.data as ChartistLineChartData), properties.options)
|
|
40
|
+
|
|
41
|
+
break
|
|
42
|
+
}
|
|
43
|
+
case 'pie': {
|
|
44
|
+
chart.value = new PieChart(root.value, (properties.data as ChartistPieChartData), properties.options)
|
|
45
|
+
|
|
46
|
+
break
|
|
47
|
+
}
|
|
46
48
|
}
|
|
47
49
|
}
|
|
48
50
|
})
|
|
@@ -21,6 +21,12 @@ const { urls } = useAppConfig()
|
|
|
21
21
|
function onClick(event: MouseEvent) {
|
|
22
22
|
emit('click', event, props.emoji)
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
function onKeydown(event: KeyboardEvent) {
|
|
26
|
+
if ((event.key === 'Enter' || event.key === ' ') && props.clickable) {
|
|
27
|
+
onClick(event as unknown as MouseEvent)
|
|
28
|
+
}
|
|
29
|
+
}
|
|
24
30
|
</script>
|
|
25
31
|
|
|
26
32
|
<template>
|
|
@@ -43,11 +49,14 @@ function onClick(event: MouseEvent) {
|
|
|
43
49
|
'h-16 w-16': size === '3xl' && hasBox,
|
|
44
50
|
'h-18 w-18': size === '4xl' && hasBox,
|
|
45
51
|
}"
|
|
52
|
+
role="button"
|
|
53
|
+
tabindex="0"
|
|
46
54
|
@click="onClick"
|
|
55
|
+
@keydown.prevent="onKeydown"
|
|
47
56
|
>
|
|
48
57
|
<img
|
|
49
58
|
v-if="emoji"
|
|
50
|
-
class="flex"
|
|
59
|
+
class="pointer-events-none flex"
|
|
51
60
|
:class="{
|
|
52
61
|
'h-2.5 w-2.5': size === '3xs',
|
|
53
62
|
'h-3 w-3': size === '2xs',
|
|
@@ -60,9 +69,9 @@ function onClick(event: MouseEvent) {
|
|
|
60
69
|
'h-10 w-10': size === '3xl',
|
|
61
70
|
'h-12 w-12': size === '4xl',
|
|
62
71
|
}"
|
|
72
|
+
:alt="emoji"
|
|
63
73
|
loading="lazy"
|
|
64
74
|
:src="`${urls.storage}/images/emojis/${emoji}.svg`"
|
|
65
|
-
@click.stop="onClick"
|
|
66
75
|
>
|
|
67
76
|
|
|
68
77
|
<slot />
|
|
@@ -5,6 +5,7 @@ withDefaults(defineProps<BaseHeading>(), {
|
|
|
5
5
|
alignment: 'left',
|
|
6
6
|
size: 'base',
|
|
7
7
|
tag: 'h1',
|
|
8
|
+
text: '',
|
|
8
9
|
})
|
|
9
10
|
|
|
10
11
|
defineSlots<{
|
|
@@ -27,6 +28,11 @@ defineSlots<{
|
|
|
27
28
|
'text-2xl sm:text-4xl': size === 'lg',
|
|
28
29
|
}"
|
|
29
30
|
>
|
|
30
|
-
<
|
|
31
|
+
<BaseText
|
|
32
|
+
v-if="text"
|
|
33
|
+
:text="text"
|
|
34
|
+
/>
|
|
35
|
+
|
|
36
|
+
<slot v-else />
|
|
31
37
|
</component>
|
|
32
38
|
</template>
|
|
@@ -29,40 +29,47 @@ const confirming = ref(false)
|
|
|
29
29
|
const { t } = useI18n()
|
|
30
30
|
const { getIcon } = useLayerIcons()
|
|
31
31
|
|
|
32
|
+
const isClickable = computed(() => {
|
|
33
|
+
return props.clickable || props.to
|
|
34
|
+
})
|
|
35
|
+
|
|
32
36
|
const statusIcon = computed<string | undefined>(() => {
|
|
33
37
|
switch (props.status) {
|
|
34
|
-
case 'error':
|
|
38
|
+
case 'error': {
|
|
35
39
|
return getIcon('closeCircle')
|
|
36
|
-
|
|
37
|
-
case 'info':
|
|
40
|
+
}
|
|
41
|
+
case 'info': {
|
|
38
42
|
return getIcon('infoCircle')
|
|
39
|
-
|
|
40
|
-
case 'success':
|
|
43
|
+
}
|
|
44
|
+
case 'success': {
|
|
41
45
|
return getIcon('checkCircle')
|
|
42
|
-
|
|
43
|
-
case 'warning':
|
|
46
|
+
}
|
|
47
|
+
case 'warning': {
|
|
44
48
|
return getIcon('exclamationCircle')
|
|
45
|
-
|
|
46
|
-
default:
|
|
47
|
-
return
|
|
49
|
+
}
|
|
50
|
+
default: {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
48
53
|
}
|
|
49
54
|
})
|
|
50
55
|
|
|
51
56
|
const statusColor = computed<BaseColor | undefined>(() => {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
switch (props.status) {
|
|
58
|
+
case 'error': {
|
|
59
|
+
return 'red'
|
|
60
|
+
}
|
|
61
|
+
case 'info': {
|
|
62
|
+
return 'indigo'
|
|
63
|
+
}
|
|
64
|
+
case 'success': {
|
|
65
|
+
return 'green'
|
|
66
|
+
}
|
|
67
|
+
case 'warning': {
|
|
68
|
+
return 'orange'
|
|
69
|
+
}
|
|
70
|
+
default: {
|
|
71
|
+
return
|
|
72
|
+
}
|
|
66
73
|
}
|
|
67
74
|
})
|
|
68
75
|
|
|
@@ -91,17 +98,26 @@ function onClick(event: MouseEvent) {
|
|
|
91
98
|
|
|
92
99
|
emit('click', event)
|
|
93
100
|
}
|
|
101
|
+
|
|
102
|
+
function onKeydown(event: KeyboardEvent) {
|
|
103
|
+
if ((event.key === 'Enter' || event.key === ' ') && isClickable.value) {
|
|
104
|
+
onClick(event as unknown as MouseEvent)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
94
107
|
</script>
|
|
95
108
|
|
|
96
109
|
<template>
|
|
97
110
|
<div
|
|
98
111
|
class="flex items-center"
|
|
99
112
|
:class="{
|
|
100
|
-
'cursor-pointer hover:underline hover:text-gray-900 dark:hover:text-gray-100':
|
|
113
|
+
'cursor-pointer hover:underline hover:text-gray-900 dark:hover:text-gray-100': isClickable,
|
|
101
114
|
'flex-row': !reverse,
|
|
102
115
|
'flex-row-reverse': reverse,
|
|
103
116
|
}"
|
|
117
|
+
role="button"
|
|
118
|
+
tabindex="0"
|
|
104
119
|
@click="onClick"
|
|
120
|
+
@keydown.prevent="onKeydown"
|
|
105
121
|
>
|
|
106
122
|
<component
|
|
107
123
|
:is="to ? NuxtLinkLocale : 'span'"
|
|
@@ -32,17 +32,15 @@ defineSlots<{
|
|
|
32
32
|
alignment="center"
|
|
33
33
|
size="sm"
|
|
34
34
|
tag="h1"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
</BaseHeading>
|
|
35
|
+
:text="title"
|
|
36
|
+
/>
|
|
38
37
|
|
|
39
38
|
<BaseParagraph
|
|
40
39
|
v-if="description"
|
|
41
40
|
alignment="center"
|
|
42
41
|
class="mt-2"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
</BaseParagraph>
|
|
42
|
+
:text="description"
|
|
43
|
+
/>
|
|
46
44
|
|
|
47
45
|
<div
|
|
48
46
|
v-if="$slots.default"
|
|
@@ -14,17 +14,18 @@ const { getIcon } = useLayerIcons()
|
|
|
14
14
|
|
|
15
15
|
const performanceIcon = computed<string | undefined>(() => {
|
|
16
16
|
switch (props.performance) {
|
|
17
|
-
case 'down':
|
|
17
|
+
case 'down': {
|
|
18
18
|
return getIcon('arrowDown')
|
|
19
|
-
|
|
20
|
-
case 'equal':
|
|
19
|
+
}
|
|
20
|
+
case 'equal': {
|
|
21
21
|
return getIcon('arrowRight')
|
|
22
|
-
|
|
23
|
-
case 'up':
|
|
22
|
+
}
|
|
23
|
+
case 'up': {
|
|
24
24
|
return getIcon('arrowUp')
|
|
25
|
-
|
|
26
|
-
default:
|
|
27
|
-
return
|
|
25
|
+
}
|
|
26
|
+
default: {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
28
29
|
}
|
|
29
30
|
})
|
|
30
31
|
</script>
|
|
@@ -4,7 +4,7 @@ import { Motion } from 'motion-v'
|
|
|
4
4
|
import type { BaseOverlay } from '../../types/bases'
|
|
5
5
|
import useMotion from '../../composables/useMotion'
|
|
6
6
|
|
|
7
|
-
withDefaults(defineProps<BaseOverlay>(), {
|
|
7
|
+
const props = withDefaults(defineProps<BaseOverlay>(), {
|
|
8
8
|
active: true,
|
|
9
9
|
clickable: true,
|
|
10
10
|
fixed: true,
|
|
@@ -25,6 +25,10 @@ defineSlots<{
|
|
|
25
25
|
const { getIcon } = useLayerIcons()
|
|
26
26
|
const { fadeIn } = useMotion()
|
|
27
27
|
|
|
28
|
+
const isClickable = computed(() => {
|
|
29
|
+
return props.clickable || props.hasClose
|
|
30
|
+
})
|
|
31
|
+
|
|
28
32
|
function onClick(event: MouseEvent) {
|
|
29
33
|
emit('click', event)
|
|
30
34
|
}
|
|
@@ -33,6 +37,12 @@ function onClose(event: KeyboardEvent | MouseEvent) {
|
|
|
33
37
|
emit('close', event)
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
function onKeydown(event: KeyboardEvent) {
|
|
41
|
+
if ((event.key === 'Enter' || event.key === ' ') && isClickable.value) {
|
|
42
|
+
onClick(event as unknown as MouseEvent)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
onKeyStroke('Escape', (event) => {
|
|
37
47
|
event.preventDefault()
|
|
38
48
|
|
|
@@ -44,13 +54,17 @@ onKeyStroke('Escape', (event) => {
|
|
|
44
54
|
<div
|
|
45
55
|
:class="{
|
|
46
56
|
'fixed inset-0': fixed,
|
|
47
|
-
'cursor-pointer':
|
|
57
|
+
'cursor-pointer': isClickable,
|
|
48
58
|
}"
|
|
59
|
+
role="button"
|
|
60
|
+
tabindex="0"
|
|
49
61
|
@click="onClick"
|
|
62
|
+
@keydown.prevent="onKeydown"
|
|
50
63
|
>
|
|
51
64
|
<BaseIcon
|
|
52
65
|
v-if="hasClose"
|
|
53
|
-
class="absolute right-4 top-4 z-50 text-gray-200 dark:text-gray-800"
|
|
66
|
+
class="pointer-events-auto absolute right-4 top-4 z-50 text-gray-200 dark:text-gray-800"
|
|
67
|
+
clickable
|
|
54
68
|
:icon="getIcon('close')"
|
|
55
69
|
@click="onClose"
|
|
56
70
|
/>
|
|
@@ -4,6 +4,7 @@ import type { BaseParagraph } from '../../types/bases'
|
|
|
4
4
|
withDefaults(defineProps<BaseParagraph>(), {
|
|
5
5
|
alignment: 'left',
|
|
6
6
|
size: 'base',
|
|
7
|
+
text: '',
|
|
7
8
|
})
|
|
8
9
|
|
|
9
10
|
defineSlots<{
|
|
@@ -23,6 +24,11 @@ defineSlots<{
|
|
|
23
24
|
'text-lg sm:text-xl': size === 'lg',
|
|
24
25
|
}"
|
|
25
26
|
>
|
|
26
|
-
<
|
|
27
|
+
<BaseText
|
|
28
|
+
v-if="text"
|
|
29
|
+
:text="text"
|
|
30
|
+
/>
|
|
31
|
+
|
|
32
|
+
<slot v-else />
|
|
27
33
|
</p>
|
|
28
34
|
</template>
|
|
@@ -34,31 +34,30 @@ const { getIcon } = useLayerIcons()
|
|
|
34
34
|
const closed = ref(false)
|
|
35
35
|
|
|
36
36
|
const finalBackground = computed(() => {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return props.background
|
|
42
|
-
}
|
|
37
|
+
const isBackgroundGray = props.background === 'gray'
|
|
38
|
+
const isReverseWithNonGrayLight = props.reverse && props.background !== 'gray-light'
|
|
39
|
+
|
|
40
|
+
return (isBackgroundGray || isReverseWithNonGrayLight) ? 'gray' : props.background
|
|
43
41
|
})
|
|
44
42
|
|
|
45
43
|
const finalReverse = computed(() => {
|
|
46
|
-
return props.reverse
|
|
44
|
+
return props.reverse === null ? props.character !== 'julien' : props.reverse
|
|
47
45
|
})
|
|
48
46
|
|
|
49
47
|
onMounted(() => {
|
|
50
|
-
|
|
51
|
-
closed.value = localStorage.getItem(props.closingId) === 'true'
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
closed.value = false
|
|
55
|
-
}
|
|
48
|
+
closed.value = props.hasClose && props.closingId ? localStorage.getItem(props.closingId) === 'true' : false
|
|
56
49
|
})
|
|
57
50
|
|
|
58
51
|
function onBubbleClick(event: MouseEvent) {
|
|
59
52
|
emit('click', event)
|
|
60
53
|
}
|
|
61
54
|
|
|
55
|
+
function onBubbleKeydown(event: KeyboardEvent) {
|
|
56
|
+
if ((event.key === 'Enter' || event.key === ' ') && props.clickable) {
|
|
57
|
+
onBubbleClick(event as unknown as MouseEvent)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
62
61
|
function onClose(event: MouseEvent) {
|
|
63
62
|
if (props.closingId) {
|
|
64
63
|
localStorage.setItem(props.closingId, 'true')
|
|
@@ -108,7 +107,11 @@ function onClose(event: MouseEvent) {
|
|
|
108
107
|
'border-green-600 dark:border-green-400 text-green-600 dark:text-green-400': status === 'success',
|
|
109
108
|
'border-orange-600 dark:border-orange-400 text-orange-600 dark:text-orange-400': status === 'warning',
|
|
110
109
|
}"
|
|
110
|
+
role="button"
|
|
111
|
+
:aria-disabled="!clickable"
|
|
112
|
+
tabindex="0"
|
|
111
113
|
@click="onBubbleClick"
|
|
114
|
+
@keydown.prevent="onBubbleKeydown"
|
|
112
115
|
>
|
|
113
116
|
<div class="flex items-center">
|
|
114
117
|
<div
|
|
@@ -119,10 +122,9 @@ function onClose(event: MouseEvent) {
|
|
|
119
122
|
</div>
|
|
120
123
|
|
|
121
124
|
<div class="flex-1">
|
|
122
|
-
<p
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
/>
|
|
125
|
+
<p v-if="!forceSlot">
|
|
126
|
+
{{ translatedContent }}
|
|
127
|
+
</p>
|
|
126
128
|
|
|
127
129
|
<slot v-else />
|
|
128
130
|
</div>
|
|
@@ -18,6 +18,12 @@ const emit = defineEmits<{
|
|
|
18
18
|
function onClick(event: MouseEvent) {
|
|
19
19
|
emit('click', event, props.id)
|
|
20
20
|
}
|
|
21
|
+
|
|
22
|
+
function onKeydown(event: KeyboardEvent) {
|
|
23
|
+
if ((event.key === 'Enter' || event.key === ' ') && props.clickable) {
|
|
24
|
+
onClick(event as unknown as MouseEvent)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
21
27
|
</script>
|
|
22
28
|
|
|
23
29
|
<template>
|
|
@@ -28,7 +34,11 @@ function onClick(event: MouseEvent) {
|
|
|
28
34
|
'flex-row': !reverse,
|
|
29
35
|
'flex-row-reverse': reverse,
|
|
30
36
|
}"
|
|
37
|
+
role="button"
|
|
38
|
+
:aria-disabled="!clickable"
|
|
39
|
+
tabindex="0"
|
|
31
40
|
@click="onClick"
|
|
41
|
+
@keydown.prevent="onKeydown"
|
|
32
42
|
>
|
|
33
43
|
<div
|
|
34
44
|
class="relative inline-block cursor-wait flex-initial"
|
|
@@ -44,7 +54,6 @@ function onClick(event: MouseEvent) {
|
|
|
44
54
|
'h-10 w-10': size === '3xl',
|
|
45
55
|
'h-12 w-12': size === '4xl',
|
|
46
56
|
}"
|
|
47
|
-
@click="onClick"
|
|
48
57
|
>
|
|
49
58
|
<div
|
|
50
59
|
v-for="wave in 2"
|
|
@@ -49,7 +49,11 @@ onBeforeMount(() => {
|
|
|
49
49
|
})
|
|
50
50
|
|
|
51
51
|
function initializeFormForExistingTag() {
|
|
52
|
-
form.name = String(props.text)?.
|
|
52
|
+
form.name = String(props.text)?.slice(1)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function onBlur() {
|
|
56
|
+
hovered.value = false
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
function onClick(event: MouseEvent) {
|
|
@@ -58,6 +62,10 @@ function onClick(event: MouseEvent) {
|
|
|
58
62
|
}
|
|
59
63
|
}
|
|
60
64
|
|
|
65
|
+
function onFocus() {
|
|
66
|
+
hovered.value = true
|
|
67
|
+
}
|
|
68
|
+
|
|
61
69
|
function onInputBlur(event: FocusEvent) {
|
|
62
70
|
emit('inputBlur', event, form.name.trim(), props.id)
|
|
63
71
|
}
|
|
@@ -66,6 +74,12 @@ function onInputSubmit(event: KeyboardEvent) {
|
|
|
66
74
|
emit('inputSubmit', event, form.name.trim(), props.id)
|
|
67
75
|
}
|
|
68
76
|
|
|
77
|
+
function onKeydown(event: KeyboardEvent) {
|
|
78
|
+
if ((event.key === 'Enter' || event.key === ' ') && props.clickable) {
|
|
79
|
+
onClick(event as unknown as MouseEvent)
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
69
83
|
function onMouseEnter() {
|
|
70
84
|
hovered.value = true
|
|
71
85
|
}
|
|
@@ -82,9 +96,15 @@ function onRemove(event: MouseEvent) {
|
|
|
82
96
|
<template>
|
|
83
97
|
<span
|
|
84
98
|
class="flex select-none"
|
|
99
|
+
role="button"
|
|
100
|
+
:aria-disabled="!clickable"
|
|
101
|
+
tabindex="0"
|
|
85
102
|
@click.stop="onClick"
|
|
103
|
+
@keydown.prevent="onKeydown"
|
|
86
104
|
@mouseenter="onMouseEnter"
|
|
87
105
|
@mouseleave="onMouseLeave"
|
|
106
|
+
@focusin="onFocus"
|
|
107
|
+
@focusout="onBlur"
|
|
88
108
|
>
|
|
89
109
|
<component
|
|
90
110
|
:is="to ? NuxtLinkLocale : 'span'"
|