@saasmakers/ui 2.0.51 → 2.0.53
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/assets/styles/base.css +26 -14
- package/app/components/bases/BaseTag.vue +11 -186
- package/app/types/bases.d.ts +10 -41
- package/app/types/global.d.ts +1 -1
- package/package.json +1 -1
- package/uno.config.ts +1 -1
- package/app/components/bases/BaseTags.vue +0 -289
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
/* Document */
|
|
2
|
+
|
|
1
3
|
html,
|
|
2
4
|
body {
|
|
3
5
|
scrollbar-gutter: stable;
|
|
4
6
|
touch-action: manipulation;
|
|
5
7
|
}
|
|
6
8
|
|
|
9
|
+
/* Theme backgrounds */
|
|
10
|
+
|
|
7
11
|
html.light body {
|
|
8
12
|
background-color: var(--gray-100);
|
|
9
13
|
}
|
|
@@ -12,23 +16,31 @@ html.dark body {
|
|
|
12
16
|
background-color: var(--gray-900);
|
|
13
17
|
}
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
input[type='datetime-local']::-webkit-date-and-time-value {
|
|
17
|
-
text-align: inherit;
|
|
18
|
-
}
|
|
19
|
+
/* Temporal inputs — native picker icon and popup follow app theme, not OS preference */
|
|
19
20
|
|
|
20
|
-
html.light
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
html.light :is(
|
|
22
|
+
input[type='date'],
|
|
23
|
+
input[type='datetime-local'],
|
|
24
|
+
input[type='month'],
|
|
25
|
+
input[type='week'],
|
|
26
|
+
input[type='time']
|
|
27
|
+
) {
|
|
25
28
|
color-scheme: light;
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
html.dark
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
html.dark :is(
|
|
32
|
+
input[type='date'],
|
|
33
|
+
input[type='datetime-local'],
|
|
34
|
+
input[type='month'],
|
|
35
|
+
input[type='week'],
|
|
36
|
+
input[type='time']
|
|
37
|
+
) {
|
|
33
38
|
color-scheme: dark;
|
|
34
39
|
}
|
|
40
|
+
|
|
41
|
+
:is(
|
|
42
|
+
input[type='date'],
|
|
43
|
+
input[type='datetime-local']
|
|
44
|
+
)::-webkit-date-and-time-value {
|
|
45
|
+
text-align: inherit;
|
|
46
|
+
}
|
|
@@ -1,199 +1,24 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { NuxtLinkLocale } from '#components'
|
|
3
2
|
import type { BaseTag } from '../../types/bases'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
avatar: '',
|
|
8
|
-
circle: '',
|
|
9
|
-
clickable: true,
|
|
10
|
-
color: 'black',
|
|
11
|
-
draggable: false,
|
|
12
|
-
editable: false,
|
|
13
|
-
icon: undefined,
|
|
14
|
-
iconSize: undefined,
|
|
15
|
-
id: undefined,
|
|
16
|
-
isCreation: false,
|
|
17
|
-
light: true,
|
|
18
|
-
removable: false,
|
|
19
|
-
rounded: false,
|
|
4
|
+
withDefaults(defineProps<BaseTag>(), {
|
|
5
|
+
color: 'gray',
|
|
20
6
|
size: 'base',
|
|
21
7
|
text: '',
|
|
22
|
-
to: undefined,
|
|
23
|
-
truncate: false,
|
|
24
8
|
})
|
|
25
|
-
|
|
26
|
-
const emit = defineEmits<{
|
|
27
|
-
click: [event: MouseEvent, id?: number | string]
|
|
28
|
-
close: [event: MouseEvent, id?: number | string]
|
|
29
|
-
inputBlur: [event: FocusEvent, name: string, id?: number | string]
|
|
30
|
-
inputSubmit: [event: KeyboardEvent, name: string, id?: number | string]
|
|
31
|
-
remove: [event: MouseEvent, id?: number | string]
|
|
32
|
-
}>()
|
|
33
|
-
|
|
34
|
-
defineSlots<{
|
|
35
|
-
default?: () => VNode[]
|
|
36
|
-
}>()
|
|
37
|
-
|
|
38
|
-
const hovered = ref(false)
|
|
39
|
-
const form = reactive({ name: '' })
|
|
40
|
-
|
|
41
|
-
onBeforeMount(() => {
|
|
42
|
-
if (!props.isCreation) {
|
|
43
|
-
initializeFormForExistingTag()
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
function initializeFormForExistingTag() {
|
|
48
|
-
form.name = String(props.text)?.slice(1)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function onBlur() {
|
|
52
|
-
hovered.value = false
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function onClick(event: MouseEvent) {
|
|
56
|
-
if (!props.removable) {
|
|
57
|
-
emit('click', event, props.id)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function onFocus() {
|
|
62
|
-
hovered.value = true
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function onInputBlur(event: FocusEvent) {
|
|
66
|
-
emit('inputBlur', event, form.name.trim(), props.id)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function onInputSubmit(event: KeyboardEvent) {
|
|
70
|
-
emit('inputSubmit', event, form.name.trim(), props.id)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function onKeyDown(event: KeyboardEvent) {
|
|
74
|
-
if (props.clickable) {
|
|
75
|
-
(event.currentTarget as HTMLElement).click()
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function onMouseEnter() {
|
|
80
|
-
hovered.value = true
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function onMouseLeave() {
|
|
84
|
-
hovered.value = false
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function onRemove(event: MouseEvent) {
|
|
88
|
-
emit('remove', event, props.id)
|
|
89
|
-
}
|
|
90
9
|
</script>
|
|
91
10
|
|
|
92
11
|
<template>
|
|
93
12
|
<span
|
|
94
|
-
class="flex
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
@mouseleave="onMouseLeave"
|
|
103
|
-
@focusin="onFocus"
|
|
104
|
-
@focusout="onBlur"
|
|
13
|
+
class="pointer-events-none inline-flex rounded font-medium tracking-tight"
|
|
14
|
+
:class="{
|
|
15
|
+
'px-0.5 py-px text-3xs': size === 'xs',
|
|
16
|
+
'px-1 py-px text-3xs': size === 'sm',
|
|
17
|
+
'px-1.5 py-0.5 text-2xs': size === 'base',
|
|
18
|
+
'bg-orange-100 text-orange-700 dark:bg-orange-950 dark:text-orange-300': color === 'orange',
|
|
19
|
+
'bg-gray-200 text-gray-600 dark:bg-gray-800 dark:text-gray-400': color === 'gray',
|
|
20
|
+
}"
|
|
105
21
|
>
|
|
106
|
-
<
|
|
107
|
-
:is="to ? NuxtLinkLocale : 'span'"
|
|
108
|
-
class="inline-flex items-center border font-medium"
|
|
109
|
-
:class="{
|
|
110
|
-
'cursor-pointer': clickable,
|
|
111
|
-
'rounded-md': !rounded,
|
|
112
|
-
'rounded-full': rounded,
|
|
113
|
-
'border-gray-200 dark:border-gray-800 bg-gray-200 dark:bg-gray-800 text-gray-800 dark:text-gray-200': (color === 'black' && light && !active) || removable,
|
|
114
|
-
'border-gray-900 dark:border-gray-100 bg-gray-900 dark:bg-gray-100 text-white dark:text-black': color === 'black' && (!light || active),
|
|
115
|
-
'border-gray-700 dark:border-gray-300 bg-gray-100 dark:bg-gray-900 text-gray-700 dark:text-gray-300': color === 'gray' && light && !active,
|
|
116
|
-
'border-gray-800 dark:border-gray-200 bg-gray-800 dark:bg-gray-200 text-white dark:text-black': color === 'gray' && (!light || active),
|
|
117
|
-
'border-green-700 dark:border-green-300 bg-green-100 dark:bg-green-900 text-green-700 dark:text-green-300': color === 'green' && light && !active,
|
|
118
|
-
'border-green-800 dark:border-green-200 bg-green-800 dark:bg-green-200 text-white dark:text-black': color === 'green' && (!light || active),
|
|
119
|
-
'border-indigo-700 dark:border-indigo-300 bg-indigo-100 dark:bg-indigo-900 text-indigo-700 dark:text-indigo-300': color === 'indigo' && light && !active,
|
|
120
|
-
'border-indigo-800 dark:border-indigo-200 bg-indigo-800 dark:bg-indigo-200 text-white dark:text-black': color === 'indigo' && (!light || active),
|
|
121
|
-
'border-orange-700 dark:border-orange-300 bg-white dark:bg-gray-900 text-orange-700 dark:text-orange-300': color === 'orange' && light && !active,
|
|
122
|
-
'border-orange-800 dark:border-orange-200 bg-orange-800 dark:bg-orange-200 text-white dark:text-black': color === 'orange' && (!light || active),
|
|
123
|
-
'border-red-700 dark:border-red-300 bg-white dark:bg-gray-900 text-red-700 dark:text-red-300': color === 'red' && light && !active,
|
|
124
|
-
'border-red-800 dark:border-red-200 bg-red-800 dark:bg-red-200 text-white dark:text-black': color === 'red' && (!light || active),
|
|
125
|
-
'border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200': color === 'white' && light && !active,
|
|
126
|
-
'border-white dark:border-gray-900 text-white dark:text-black': color === 'white' && (!light || active),
|
|
127
|
-
'border-dashed border-gray-400 dark:border-gray-600 bg-white dark:bg-gray-900 text-gray-800 dark:text-gray-200': color === 'white' && light && !active,
|
|
128
|
-
'py-0.5 px-1.5': size === 'xs',
|
|
129
|
-
'py-1.5 px-2.5': size === 'sm',
|
|
130
|
-
'py-2 px-3': size === 'base',
|
|
131
|
-
}"
|
|
132
|
-
:to="to"
|
|
133
|
-
>
|
|
134
|
-
<BaseIcon
|
|
135
|
-
v-if="draggable"
|
|
136
|
-
class="js-drag-handle mr-2 cursor-move"
|
|
137
|
-
clickable
|
|
138
|
-
color="gray"
|
|
139
|
-
:icon="getLayerIcon('drag')"
|
|
140
|
-
/>
|
|
141
|
-
|
|
142
|
-
<span
|
|
143
|
-
v-if="avatar || circle || icon"
|
|
144
|
-
class="mr-1 flex items-center text-center"
|
|
145
|
-
:class="{
|
|
146
|
-
'h-2.5 w-2.5': size === 'xs' || size === 'sm' || iconSize === 2.5,
|
|
147
|
-
'h-3 w-3': size === 'base' || iconSize === 3,
|
|
148
|
-
'h-3.5 w-3.5': iconSize === 3.5,
|
|
149
|
-
'h-4 w-4': iconSize === 4,
|
|
150
|
-
}"
|
|
151
|
-
>
|
|
152
|
-
<BaseAvatar
|
|
153
|
-
v-if="avatar"
|
|
154
|
-
class="h-full w-full"
|
|
155
|
-
:shadow="false"
|
|
156
|
-
:src="avatar"
|
|
157
|
-
/>
|
|
158
|
-
|
|
159
|
-
<BaseIcon
|
|
160
|
-
v-else-if="icon"
|
|
161
|
-
class="h-full w-full"
|
|
162
|
-
:icon="icon"
|
|
163
|
-
/>
|
|
164
|
-
</span>
|
|
165
|
-
|
|
166
|
-
<span
|
|
167
|
-
v-if="$slots.default"
|
|
168
|
-
class="mr-1"
|
|
169
|
-
>
|
|
170
|
-
<slot />
|
|
171
|
-
</span>
|
|
172
|
-
|
|
173
|
-
<BaseText
|
|
174
|
-
v-if="!editable"
|
|
175
|
-
class="whitespace-nowrap outline-none"
|
|
176
|
-
:class="{ truncate }"
|
|
177
|
-
:size="size === 'xs' ? '3xs' : size === 'sm' ? '2xs' : 'xs'"
|
|
178
|
-
:text="text"
|
|
179
|
-
/>
|
|
180
|
-
|
|
181
|
-
<FieldInput
|
|
182
|
-
v-else
|
|
183
|
-
v-model="form.name"
|
|
184
|
-
border="none"
|
|
185
|
-
class="w-16"
|
|
186
|
-
size="sm"
|
|
187
|
-
@blur="onInputBlur"
|
|
188
|
-
@submit="onInputSubmit"
|
|
189
|
-
/>
|
|
190
|
-
|
|
191
|
-
<BaseIcon
|
|
192
|
-
v-if="removable"
|
|
193
|
-
class="ml-1.5 text-red-700 dark:text-red-300 hover:text-black dark:hover:text-white"
|
|
194
|
-
:icon="getLayerIcon('closeCircle')"
|
|
195
|
-
@click.prevent.stop="onRemove"
|
|
196
|
-
/>
|
|
197
|
-
</component>
|
|
22
|
+
<slot>{{ text }}</slot>
|
|
198
23
|
</span>
|
|
199
24
|
</template>
|
package/app/types/bases.d.ts
CHANGED
|
@@ -127,6 +127,16 @@ export interface BaseCircle {
|
|
|
127
127
|
|
|
128
128
|
export type BaseCircleColor = 'amber' | 'green' | 'indigo' | 'red'
|
|
129
129
|
|
|
130
|
+
export interface BaseTag {
|
|
131
|
+
color?: BaseTagColor
|
|
132
|
+
size?: BaseTagSize
|
|
133
|
+
text?: BaseTextText
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export type BaseTagColor = 'gray' | 'orange'
|
|
137
|
+
|
|
138
|
+
export type BaseTagSize = 'base' | 'sm' | 'xs'
|
|
139
|
+
|
|
130
140
|
export type BaseColor
|
|
131
141
|
= | 'black'
|
|
132
142
|
| 'gray'
|
|
@@ -327,47 +337,6 @@ export interface BaseSpinner {
|
|
|
327
337
|
|
|
328
338
|
export type BaseStatus = | 'error' | 'info' | 'success' | 'warning'
|
|
329
339
|
|
|
330
|
-
export interface BaseTag {
|
|
331
|
-
active?: boolean
|
|
332
|
-
avatar?: string
|
|
333
|
-
circle?: string
|
|
334
|
-
clickable?: boolean
|
|
335
|
-
color?: BaseColor
|
|
336
|
-
draggable?: boolean
|
|
337
|
-
editable?: boolean
|
|
338
|
-
icon?: string
|
|
339
|
-
iconSize?: number
|
|
340
|
-
id?: number
|
|
341
|
-
isCreation?: boolean
|
|
342
|
-
light?: boolean
|
|
343
|
-
order?: number
|
|
344
|
-
removable?: boolean
|
|
345
|
-
rounded?: boolean
|
|
346
|
-
size?: BaseTagSize
|
|
347
|
-
text: BaseTextText
|
|
348
|
-
to?: RouteLocationNamedI18n
|
|
349
|
-
truncate?: boolean
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
export interface BaseTags {
|
|
353
|
-
active?: boolean
|
|
354
|
-
clickable?: boolean
|
|
355
|
-
draggable?: boolean
|
|
356
|
-
editable?: boolean
|
|
357
|
-
hasBack?: boolean
|
|
358
|
-
hasCreation?: boolean
|
|
359
|
-
maxTags?: number
|
|
360
|
-
modelValue: (number | string)[]
|
|
361
|
-
removable?: boolean
|
|
362
|
-
selectable?: boolean
|
|
363
|
-
selectableUnique?: boolean
|
|
364
|
-
size?: BaseTagSize
|
|
365
|
-
tags: BaseTag[]
|
|
366
|
-
wrap?: boolean
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
export type BaseTagSize = 'base' | 'sm' | 'xs'
|
|
370
|
-
|
|
371
340
|
export interface BaseText {
|
|
372
341
|
alignment?: BaseAlignment
|
|
373
342
|
background?: BaseBackground
|
package/app/types/global.d.ts
CHANGED
|
@@ -69,7 +69,7 @@ declare global {
|
|
|
69
69
|
type BaseSpinner = import('./bases').BaseSpinner
|
|
70
70
|
type BaseStatus = import('./bases').BaseStatus
|
|
71
71
|
type BaseTag = import('./bases').BaseTag
|
|
72
|
-
type
|
|
72
|
+
type BaseTagColor = import('./bases').BaseTagColor
|
|
73
73
|
type BaseTagSize = import('./bases').BaseTagSize
|
|
74
74
|
type BaseText = import('./bases').BaseText
|
|
75
75
|
type BaseTextText = import('./bases').BaseTextText
|
package/package.json
CHANGED
package/uno.config.ts
CHANGED
|
@@ -36,7 +36,7 @@ export const shortcuts: Record<string, string> = {
|
|
|
36
36
|
'base-border-interactive-focus-within': 'hover:border-gray-300 focus-within:border-gray-400 dark:hover:border-gray-700 dark:focus-within:border-gray-600',
|
|
37
37
|
'base-bg': 'bg-white dark:bg-gray-900',
|
|
38
38
|
'base-box': 'border shadow-sm base-border rounded-lg',
|
|
39
|
-
'base-highlight-indigo': 'border border-indigo-600/35 bg-indigo-600/[0.08] dark:border-indigo-400/35 dark:bg-indigo-400/[0.08]',
|
|
39
|
+
'base-highlight-indigo': 'border border-indigo-600/35 bg-indigo-600/[0.08] shadow-indigo-600/15 dark:border-indigo-400/35 dark:bg-indigo-400/[0.08] dark:shadow-indigo-400/15',
|
|
40
40
|
'base-surface': 'border base-border base-bg shadow-sm',
|
|
41
41
|
'field-disabled': 'opacity-50 cursor-not-allowed',
|
|
42
42
|
'scroll-y-stable': 'overflow-y-auto [scrollbar-gutter:stable]',
|
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
<script lang="ts" setup>
|
|
2
|
-
import type { BaseTags } from '../../types/bases'
|
|
3
|
-
|
|
4
|
-
const props = withDefaults(defineProps<Omit<BaseTags, 'modelValue'>>(), {
|
|
5
|
-
active: false,
|
|
6
|
-
clickable: true,
|
|
7
|
-
draggable: false,
|
|
8
|
-
editable: false,
|
|
9
|
-
hasBack: false,
|
|
10
|
-
hasCreation: false,
|
|
11
|
-
maxTags: Number.POSITIVE_INFINITY,
|
|
12
|
-
removable: false,
|
|
13
|
-
selectable: false,
|
|
14
|
-
selectableUnique: false,
|
|
15
|
-
size: 'base',
|
|
16
|
-
tags: () => [],
|
|
17
|
-
wrap: false,
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
const emit = defineEmits<{
|
|
21
|
-
attach: [event: MouseEvent, tagId?: number | string]
|
|
22
|
-
back: [event: MouseEvent]
|
|
23
|
-
click: [event: MouseEvent]
|
|
24
|
-
create: [event: FocusEvent | KeyboardEvent, name: string]
|
|
25
|
-
detach: [event: MouseEvent, tagId?: number | string]
|
|
26
|
-
remove: [event: MouseEvent, tagId?: number | string]
|
|
27
|
-
update: [event: FocusEvent | KeyboardEvent, name: string, tagId?: number | string]
|
|
28
|
-
}>()
|
|
29
|
-
|
|
30
|
-
const modelValue = defineModel<BaseTags['modelValue']>({ default: () => [] })
|
|
31
|
-
const keyForTagCreation = ref(Date.now())
|
|
32
|
-
const keyForTagUpdate = ref(Date.now())
|
|
33
|
-
const root = ref<HTMLDivElement>()
|
|
34
|
-
const showingAllTags = ref(false)
|
|
35
|
-
const showingTagCreationField = ref(false)
|
|
36
|
-
const { t } = useI18n()
|
|
37
|
-
|
|
38
|
-
const sortedTags = computed({
|
|
39
|
-
get() {
|
|
40
|
-
return [...props.tags]
|
|
41
|
-
.filter((_tag, tagIndex) => tagIndex < props.maxTags || showingAllTags.value)
|
|
42
|
-
.toSorted((tagA, tagB) => {
|
|
43
|
-
return (tagA.order ?? 0) < (tagB.order ?? 0) ? -1 : 0
|
|
44
|
-
})
|
|
45
|
-
},
|
|
46
|
-
|
|
47
|
-
set(tags) {
|
|
48
|
-
const suiteForTags = tags
|
|
49
|
-
.map((tag, order) => ({
|
|
50
|
-
id: tag.id,
|
|
51
|
-
order,
|
|
52
|
-
}))
|
|
53
|
-
.map(tag => ({
|
|
54
|
-
id: tag.id,
|
|
55
|
-
order: tag.order,
|
|
56
|
-
}))
|
|
57
|
-
|
|
58
|
-
return suiteForTags
|
|
59
|
-
},
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
function onCreateTag(event: FocusEvent | KeyboardEvent, name: string) {
|
|
63
|
-
showingTagCreationField.value = false
|
|
64
|
-
keyForTagCreation.value = Date.now()
|
|
65
|
-
|
|
66
|
-
emit('create', event, name)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function onGoBack(event: MouseEvent) {
|
|
70
|
-
emit('back', event)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function onRemoveTag(event: MouseEvent, tagId?: number | string) {
|
|
74
|
-
emit('remove', event, tagId)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function onShowAllTags() {
|
|
78
|
-
showingAllTags.value = true
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function onShowTagField() {
|
|
82
|
-
if (!showingTagCreationField.value) {
|
|
83
|
-
showingTagCreationField.value = true
|
|
84
|
-
|
|
85
|
-
nextTick(() => {
|
|
86
|
-
const element = root.value?.querySelector<HTMLInputElement>('input[type="text"]')
|
|
87
|
-
|
|
88
|
-
element?.focus()
|
|
89
|
-
})
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
function onTagClick(event: MouseEvent, tagId?: number | string) {
|
|
94
|
-
if (props.selectable && tagId) {
|
|
95
|
-
let value = [...modelValue.value]
|
|
96
|
-
|
|
97
|
-
if (value.includes(tagId)) {
|
|
98
|
-
value.splice(value.indexOf(tagId), 1)
|
|
99
|
-
emit('detach', event, tagId)
|
|
100
|
-
}
|
|
101
|
-
else if (props.selectableUnique) {
|
|
102
|
-
value = [tagId]
|
|
103
|
-
|
|
104
|
-
emit('attach', event, tagId)
|
|
105
|
-
}
|
|
106
|
-
else {
|
|
107
|
-
value.push(tagId)
|
|
108
|
-
emit('attach', event, tagId)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
modelValue.value = value
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function onUpdateTag(event: FocusEvent | KeyboardEvent, name: string, tagId?: number | string) {
|
|
116
|
-
if (name) {
|
|
117
|
-
emit('update', event, name, tagId)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
else {
|
|
121
|
-
keyForTagUpdate.value = Date.now()
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
</script>
|
|
125
|
-
|
|
126
|
-
<template>
|
|
127
|
-
<div
|
|
128
|
-
ref="root"
|
|
129
|
-
class="flex items-center"
|
|
130
|
-
:class="{
|
|
131
|
-
'flex-wrap': wrap,
|
|
132
|
-
'w-full overflow-x-auto': !wrap,
|
|
133
|
-
'-mt-0.75 -ml-0.75': size === 'sm',
|
|
134
|
-
'-mt-1 -ml-1': size === 'base',
|
|
135
|
-
}"
|
|
136
|
-
>
|
|
137
|
-
<BaseTag
|
|
138
|
-
v-if="hasBack"
|
|
139
|
-
key="BaseTagToGoBack"
|
|
140
|
-
:class="{
|
|
141
|
-
'm-0.75': size === 'sm',
|
|
142
|
-
'm-1': size === 'base',
|
|
143
|
-
}"
|
|
144
|
-
color="indigo"
|
|
145
|
-
:icon="getLayerIcon('back')"
|
|
146
|
-
:size="size"
|
|
147
|
-
:text="t('cancel')"
|
|
148
|
-
@click="onGoBack"
|
|
149
|
-
/>
|
|
150
|
-
|
|
151
|
-
<BaseTag
|
|
152
|
-
v-if="hasCreation"
|
|
153
|
-
:key="keyForTagCreation"
|
|
154
|
-
:class="{
|
|
155
|
-
'm-0.75': size === 'sm',
|
|
156
|
-
'm-1': size === 'base',
|
|
157
|
-
}"
|
|
158
|
-
color="indigo"
|
|
159
|
-
:editable="showingTagCreationField"
|
|
160
|
-
:icon="showingTagCreationField ? getLayerIcon('tags') : getLayerIcon('plus')"
|
|
161
|
-
is-creation
|
|
162
|
-
:light="false"
|
|
163
|
-
:size="size"
|
|
164
|
-
:text="showingTagCreationField ? '' : t('newTag')"
|
|
165
|
-
@click="onShowTagField"
|
|
166
|
-
@input-blur="onCreateTag"
|
|
167
|
-
@input-submit="onCreateTag"
|
|
168
|
-
/>
|
|
169
|
-
|
|
170
|
-
<div class="flex items-center">
|
|
171
|
-
<span
|
|
172
|
-
v-for="(tag, tagIndex) in sortedTags"
|
|
173
|
-
:key="tag.id ? `${tag.id}_${tag.order}_${keyForTagUpdate}` : tagIndex"
|
|
174
|
-
class="flex flex-wrap items-center"
|
|
175
|
-
:class="{
|
|
176
|
-
'm-0.75': size === 'sm',
|
|
177
|
-
'm-1': size === 'base',
|
|
178
|
-
}"
|
|
179
|
-
>
|
|
180
|
-
<template v-if="tag">
|
|
181
|
-
<BaseTag
|
|
182
|
-
:id="tag.id || tagIndex"
|
|
183
|
-
:key="`${tag.id}_${tagIndex}`"
|
|
184
|
-
:active="tag.id && modelValue.includes(tag.id) || tag.active"
|
|
185
|
-
:avatar="tag.avatar"
|
|
186
|
-
:circle="tag.circle"
|
|
187
|
-
:clickable="clickable"
|
|
188
|
-
:color="tag.color"
|
|
189
|
-
:draggable="draggable"
|
|
190
|
-
:editable="editable"
|
|
191
|
-
:icon="tag.icon"
|
|
192
|
-
:icon-size="tag.iconSize"
|
|
193
|
-
:light="tag.light"
|
|
194
|
-
:removable="removable"
|
|
195
|
-
:size="size"
|
|
196
|
-
:text="tag.text"
|
|
197
|
-
:to="tag.to"
|
|
198
|
-
@click="onTagClick"
|
|
199
|
-
@input-blur="onUpdateTag"
|
|
200
|
-
@input-submit="onUpdateTag"
|
|
201
|
-
@remove="onRemoveTag"
|
|
202
|
-
/>
|
|
203
|
-
</template>
|
|
204
|
-
</span>
|
|
205
|
-
</div>
|
|
206
|
-
|
|
207
|
-
<BaseTag
|
|
208
|
-
v-if="tags.length > maxTags && !showingAllTags"
|
|
209
|
-
key="showMore"
|
|
210
|
-
:class="{
|
|
211
|
-
'm-0.75': size === 'sm',
|
|
212
|
-
'm-1': size === 'base',
|
|
213
|
-
}"
|
|
214
|
-
:size="size"
|
|
215
|
-
:text="t('showMore', { value: tags.length - maxTags })"
|
|
216
|
-
@click="onShowAllTags"
|
|
217
|
-
/>
|
|
218
|
-
</div>
|
|
219
|
-
</template>
|
|
220
|
-
|
|
221
|
-
<i18n lang="json">
|
|
222
|
-
{
|
|
223
|
-
"de": {
|
|
224
|
-
"cancel": "Abbrechen",
|
|
225
|
-
"newTag": "Neues Tag",
|
|
226
|
-
"showMore": "& {value} weiteres | & {value} weitere"
|
|
227
|
-
},
|
|
228
|
-
"en": {
|
|
229
|
-
"cancel": "Cancel",
|
|
230
|
-
"newTag": "New tag",
|
|
231
|
-
"showMore": "& {value} other | & {value} others"
|
|
232
|
-
},
|
|
233
|
-
"es": {
|
|
234
|
-
"cancel": "Cancelar",
|
|
235
|
-
"newTag": "Nueva etiqueta",
|
|
236
|
-
"showMore": "& {value} otro | & {value} otros"
|
|
237
|
-
},
|
|
238
|
-
"fr": {
|
|
239
|
-
"cancel": "Annuler",
|
|
240
|
-
"newTag": "Nouveau tag",
|
|
241
|
-
"showMore": "& {value} autre | & {value} autres"
|
|
242
|
-
},
|
|
243
|
-
"id": {
|
|
244
|
-
"cancel": "Batal",
|
|
245
|
-
"newTag": "Tag baru",
|
|
246
|
-
"showMore": "& {value} lainnya | & {value} lainnya"
|
|
247
|
-
},
|
|
248
|
-
"it": {
|
|
249
|
-
"cancel": "Annulla",
|
|
250
|
-
"newTag": "Nuovo tag",
|
|
251
|
-
"showMore": "& {value} altro | & {value} altri"
|
|
252
|
-
},
|
|
253
|
-
"ja": {
|
|
254
|
-
"cancel": "キャンセル",
|
|
255
|
-
"newTag": "新しいタグ",
|
|
256
|
-
"showMore": "& {value} その他 | & {value} その他"
|
|
257
|
-
},
|
|
258
|
-
"ko": {
|
|
259
|
-
"cancel": "취소",
|
|
260
|
-
"newTag": "새 태그",
|
|
261
|
-
"showMore": "& {value}개 더 | & {value}개 더"
|
|
262
|
-
},
|
|
263
|
-
"nl": {
|
|
264
|
-
"cancel": "Annuleren",
|
|
265
|
-
"newTag": "Nieuwe tag",
|
|
266
|
-
"showMore": "& {value} andere | & {value} anderen"
|
|
267
|
-
},
|
|
268
|
-
"pl": {
|
|
269
|
-
"cancel": "Anuluj",
|
|
270
|
-
"newTag": "Nowy tag",
|
|
271
|
-
"showMore": "& {value} inny | & {value} innych"
|
|
272
|
-
},
|
|
273
|
-
"pt": {
|
|
274
|
-
"cancel": "Cancelar",
|
|
275
|
-
"newTag": "Nova etiqueta",
|
|
276
|
-
"showMore": "& {value} outro | & {value} outros"
|
|
277
|
-
},
|
|
278
|
-
"pt-BR": {
|
|
279
|
-
"cancel": "Cancelar",
|
|
280
|
-
"newTag": "Nova tag",
|
|
281
|
-
"showMore": "& {value} outro | & {value} outros"
|
|
282
|
-
},
|
|
283
|
-
"vi": {
|
|
284
|
-
"cancel": "Hủy",
|
|
285
|
-
"newTag": "Thẻ mới",
|
|
286
|
-
"showMore": "& {value} mục khác | & {value} mục khác"
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
</i18n>
|