@meistrari/tela-build 1.51.0 → 1.52.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/tela/avatar/label/avatar-label.stories.ts +0 -1
- package/components/tela/confirmation-modal/confirmation-modal.vue +5 -23
- package/components/tela/drag-zone.vue +49 -0
- package/components/tela/dropdown-menu/DropdownMenu.vue +17 -2
- package/components/tela/dropdown-menu/DropdownMenuItem.vue +5 -2
- package/components/tela/dropdown-menu/dropdown-menu.stories.ts +7 -0
- package/components/tela/filter/filter.stories.ts +0 -1
- package/components/tela/link-decoration/link-decoration.vue +3 -6
- package/components/tela/multiple-select/multiple-select.vue +128 -175
- package/components/tela/scroll-area/scroll-area.vue +1 -1
- package/components/tela/select-menu/select-menu.vue +6 -1
- package/components/tela/tags/tags.vue +3 -2
- package/components/tela/uploader/uploader-drop-zone.vue +76 -0
- package/components/tela/uploader/uploader-file-list.vue +166 -0
- package/components/tela/uploader/uploader-mappings.test.ts +184 -0
- package/components/tela/uploader/uploader-mappings.ts +186 -0
- package/components/tela/uploader/uploader-preview.vue +98 -0
- package/components/tela/uploader/uploader-variable-assignment.vue +234 -0
- package/components/tela/uploader/uploader.mdx +666 -0
- package/components/tela/uploader/uploader.stories.ts +396 -0
- package/components/tela/uploader/uploader.vue +1108 -0
- package/modules/tela-build-docs/__tests__/ensure-claude-symlink.test.ts +53 -4
- package/modules/tela-build-docs/index.ts +56 -4
- package/nuxt.config.ts +10 -0
- package/package.json +2 -1
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { DialogClose } from 'radix-vue'
|
|
3
2
|
import TelaModal from '../modal/modal.vue'
|
|
4
3
|
import TelaButton from '../button/button.vue'
|
|
5
4
|
|
|
@@ -20,11 +19,6 @@ const emit = defineEmits<{
|
|
|
20
19
|
|
|
21
20
|
const open = defineModel<boolean>('open')
|
|
22
21
|
|
|
23
|
-
function handleCloseClick() {
|
|
24
|
-
emit('cancel')
|
|
25
|
-
open.value = false
|
|
26
|
-
}
|
|
27
|
-
|
|
28
22
|
const confirmButtonVariant = computed(() => {
|
|
29
23
|
return props.variant === 'danger' ? 'danger' : 'primary'
|
|
30
24
|
})
|
|
@@ -35,36 +29,24 @@ const confirmButtonVariant = computed(() => {
|
|
|
35
29
|
v-model:model-value="open"
|
|
36
30
|
:compact="props.compact ?? true"
|
|
37
31
|
hide-dividers
|
|
32
|
+
:is-close-icon="false"
|
|
33
|
+
:style="{ paddingBlock: '20px' }"
|
|
38
34
|
@close="emit('cancel')"
|
|
39
35
|
>
|
|
40
|
-
<template #actions>
|
|
41
|
-
<DialogClose as-child>
|
|
42
|
-
<TelaIconButton
|
|
43
|
-
absolute
|
|
44
|
-
top-8px
|
|
45
|
-
right-8px
|
|
46
|
-
icon="i-ph-x"
|
|
47
|
-
size="md"
|
|
48
|
-
color="secondary"
|
|
49
|
-
outline-none
|
|
50
|
-
@click="handleCloseClick"
|
|
51
|
-
/>
|
|
52
|
-
</DialogClose>
|
|
53
|
-
</template>
|
|
54
36
|
<div flex="~ col" w-400px>
|
|
55
37
|
<h6 body-20-semibold text-gray-900>
|
|
56
38
|
{{ props.title }}
|
|
57
39
|
</h6>
|
|
58
|
-
<div body-16-regular text-gray-700 mt-
|
|
40
|
+
<div body-16-regular text-gray-700 mt-4px>
|
|
59
41
|
<slot />
|
|
60
42
|
</div>
|
|
61
43
|
</div>
|
|
62
44
|
<template #footer>
|
|
63
45
|
<div flex="~" gap-8px w-full justify-between>
|
|
64
|
-
<TelaButton :disabled="props.loading" size="lg" variant="secondary" @click="emit('cancel')">
|
|
46
|
+
<TelaButton :disabled="props.loading" size="lg" variant="secondary" flex-1 whitespace-nowrap @click="emit('cancel')">
|
|
65
47
|
{{ props.cancelButtonText ?? 'Cancel' }}
|
|
66
48
|
</TelaButton>
|
|
67
|
-
<TelaButton :loading="props.loading" size="lg" :variant="confirmButtonVariant" :data-testid="props.confirmButtonTestId" @click="emit('confirm')">
|
|
49
|
+
<TelaButton :loading="props.loading" size="lg" :variant="confirmButtonVariant" :data-testid="props.confirmButtonTestId" flex-1 whitespace-nowrap @click="emit('confirm')">
|
|
68
50
|
{{ props.confirmButtonText ?? 'Confirm' }}
|
|
69
51
|
</TelaButton>
|
|
70
52
|
</div>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const props = defineProps<{
|
|
3
|
+
disabled?: boolean
|
|
4
|
+
}>()
|
|
5
|
+
|
|
6
|
+
const emit = defineEmits<{
|
|
7
|
+
filesDropped: [list: File[]]
|
|
8
|
+
}>()
|
|
9
|
+
|
|
10
|
+
const active = ref(false)
|
|
11
|
+
let inActiveTimeout: ReturnType<typeof setTimeout> | null = null
|
|
12
|
+
|
|
13
|
+
// setActive and setInactive use timeouts, so that when you drag an item over a child element,
|
|
14
|
+
// the dragleave event that is fired won't cause a flicker. A few ms should be plenty of
|
|
15
|
+
// time to wait for the next dragenter event to clear the timeout and set it back to active.
|
|
16
|
+
function setActive() {
|
|
17
|
+
if (props.disabled)
|
|
18
|
+
return
|
|
19
|
+
active.value = true
|
|
20
|
+
if (inActiveTimeout)
|
|
21
|
+
clearTimeout(inActiveTimeout)
|
|
22
|
+
}
|
|
23
|
+
function setInactive() {
|
|
24
|
+
inActiveTimeout = setTimeout(() => {
|
|
25
|
+
active.value = false
|
|
26
|
+
}, 50)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function onDrop(e: DragEvent) {
|
|
30
|
+
setInactive()
|
|
31
|
+
if (props.disabled)
|
|
32
|
+
return
|
|
33
|
+
if (!e.dataTransfer?.files)
|
|
34
|
+
return
|
|
35
|
+
emit('filesDropped', [...e.dataTransfer.files])
|
|
36
|
+
}
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div
|
|
41
|
+
:data-active="active"
|
|
42
|
+
@dragenter.prevent.stop="setActive"
|
|
43
|
+
@dragover.prevent.stop="setActive"
|
|
44
|
+
@dragleave.prevent.stop="setInactive"
|
|
45
|
+
@drop.prevent.stop="onDrop"
|
|
46
|
+
>
|
|
47
|
+
<slot :drop-zone-active="active" />
|
|
48
|
+
</div>
|
|
49
|
+
</template>
|
|
@@ -16,10 +16,12 @@ const props = withDefaults(defineProps<{
|
|
|
16
16
|
label: string
|
|
17
17
|
icon?: string
|
|
18
18
|
iconSide?: 'left' | 'right'
|
|
19
|
+
trailingIcon?: string
|
|
19
20
|
group?: string
|
|
20
21
|
color?: 'positive' | 'caution' | 'negative'
|
|
21
22
|
click: () => void
|
|
22
23
|
disabled?: boolean
|
|
24
|
+
preventClose?: boolean
|
|
23
25
|
checkbox?: {
|
|
24
26
|
modelValue: boolean
|
|
25
27
|
onChange: (value: boolean) => void
|
|
@@ -34,6 +36,8 @@ const props = withDefaults(defineProps<{
|
|
|
34
36
|
triggerClass?: HTMLAttributes['class']
|
|
35
37
|
contentClass?: HTMLAttributes['class']
|
|
36
38
|
align?: 'start' | 'end' | 'center'
|
|
39
|
+
labelClass?: string
|
|
40
|
+
defaultOpen?: boolean
|
|
37
41
|
}>(), {
|
|
38
42
|
align: 'start',
|
|
39
43
|
iconSide: 'left',
|
|
@@ -70,7 +74,7 @@ function onToggle(open: boolean) {
|
|
|
70
74
|
|
|
71
75
|
<template>
|
|
72
76
|
<div data-allow-mismatch @click.stop>
|
|
73
|
-
<DropdownMenuRoot :modal="shouldBeModal" :default-open="
|
|
77
|
+
<DropdownMenuRoot :modal="shouldBeModal" :default-open="defaultOpen" @update:open="onToggle">
|
|
74
78
|
<DropdownMenuTrigger as-child :class="cn('data-[state=open]:bg-muted', triggerClass)" @click.prevent.stop>
|
|
75
79
|
<slot />
|
|
76
80
|
<VisuallyHidden v-if="isStorybook" as-child>
|
|
@@ -83,6 +87,8 @@ function onToggle(open: boolean) {
|
|
|
83
87
|
:side-offset="sideOffset"
|
|
84
88
|
:class="cn('min-w-128px! z-605!', contentClass)"
|
|
85
89
|
>
|
|
90
|
+
<slot name="header" />
|
|
91
|
+
|
|
86
92
|
<div v-if="allowSearch" flex="~" items-center px-8px py-6px>
|
|
87
93
|
<TelaIcon name="i-ph-magnifying-glass-bold" text-gray-800 mr-6px />
|
|
88
94
|
<input
|
|
@@ -111,16 +117,25 @@ function onToggle(open: boolean) {
|
|
|
111
117
|
:disabled="item.disabled"
|
|
112
118
|
:icon="item.icon"
|
|
113
119
|
:icon-side="item.iconSide"
|
|
120
|
+
:trailing-icon="item.trailingIcon"
|
|
114
121
|
:color="item.color"
|
|
115
122
|
:checkbox="item.checkbox"
|
|
116
123
|
:tooltip="item.tooltip"
|
|
117
124
|
:data-testid="item.testId"
|
|
125
|
+
:label-class="labelClass"
|
|
126
|
+
@select="(event: Event) => {
|
|
127
|
+
if (item.preventClose) {
|
|
128
|
+
event.preventDefault()
|
|
129
|
+
}
|
|
130
|
+
}"
|
|
118
131
|
@click="item.click"
|
|
119
132
|
>
|
|
120
|
-
|
|
133
|
+
{{ item.label }}
|
|
121
134
|
</DropdownMenuItem>
|
|
122
135
|
</DropdownMenuGroup>
|
|
123
136
|
</template>
|
|
137
|
+
|
|
138
|
+
<slot name="footer" />
|
|
124
139
|
</DropdownMenuContent>
|
|
125
140
|
</DropdownMenuRoot>
|
|
126
141
|
</div>
|
|
@@ -7,9 +7,11 @@ import type { TooltipProps } from '../tooltip/tooltip.vue'
|
|
|
7
7
|
|
|
8
8
|
const props = defineProps<DropdownMenuItemProps & {
|
|
9
9
|
class?: HTMLAttributes['class']
|
|
10
|
+
labelClass?: HTMLAttributes['class']
|
|
10
11
|
inset?: boolean
|
|
11
12
|
icon?: string
|
|
12
13
|
iconSide?: 'left' | 'right'
|
|
14
|
+
trailingIcon?: string
|
|
13
15
|
iconWithBackground?: {
|
|
14
16
|
name: string
|
|
15
17
|
size?: string
|
|
@@ -105,7 +107,7 @@ const isIconImage = computed(() => {
|
|
|
105
107
|
<TelaIcon v-else-if="icon" :name="icon" :class="getIconClasses(props.color)" />
|
|
106
108
|
<TelaIcon v-else-if="iconWithBackground" :name="iconWithBackground.name" :size="iconWithBackground.size" :background-class="iconWithBackground.backgroundClass" :class="getIconClasses(props.color)" />
|
|
107
109
|
<TelaCheckbox v-else-if="checkbox" :model-value="checkbox?.modelValue" @update:model-value="(value) => checkbox?.onChange(value === true)" />
|
|
108
|
-
<span text-body-14-medium font-460 :class="getItemClasses(props.color)">
|
|
110
|
+
<span text-body-14-medium font-460 :class="cn(getItemClasses(props.color), labelClass)">
|
|
109
111
|
<slot />
|
|
110
112
|
</span>
|
|
111
113
|
</DropdownMenuItem>
|
|
@@ -127,10 +129,11 @@ const isIconImage = computed(() => {
|
|
|
127
129
|
<TelaIcon v-else-if="icon && (!iconSide || iconSide === 'left')" :name="icon" :class="getIconClasses(props.color)" />
|
|
128
130
|
<TelaIcon v-else-if="iconWithBackground" :name="iconWithBackground.name" :size="iconWithBackground.size" :background-class="iconWithBackground.backgroundClass" :class="getIconClasses(props.color)" />
|
|
129
131
|
<TelaCheckbox v-else-if="checkbox" :model-value="checkbox?.modelValue" @update:model-value="(value) => checkbox?.onChange(value === true)" />
|
|
130
|
-
<span text-body-14-medium font-460 :class="getItemClasses(props.color)">
|
|
132
|
+
<span text-body-14-medium font-460 :class="cn(getItemClasses(props.color), labelClass)">
|
|
131
133
|
<slot />
|
|
132
134
|
</span>
|
|
133
135
|
<img v-if="icon && iconSide === 'right' && isIconImage" :src="icon" :class="cn('size-16px')">
|
|
134
136
|
<TelaIcon v-else-if="icon && iconSide === 'right'" :name="icon" />
|
|
137
|
+
<TelaIcon v-else-if="trailingIcon" :name="trailingIcon" color="gray-400" size="14px" ml-auto />
|
|
135
138
|
</DropdownMenuItem>
|
|
136
139
|
</template>
|
|
@@ -44,6 +44,13 @@ const meta: Meta<typeof DropdownMenu> = {
|
|
|
44
44
|
options: ['start', 'end', 'center'],
|
|
45
45
|
description: 'Alignment of the dropdown menu relative to the trigger element.',
|
|
46
46
|
},
|
|
47
|
+
defaultOpen: {
|
|
48
|
+
control: 'boolean',
|
|
49
|
+
description: 'Whether the dropdown menu starts open when mounted.',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
args: {
|
|
53
|
+
defaultOpen: true,
|
|
47
54
|
},
|
|
48
55
|
}
|
|
49
56
|
|
|
@@ -6,14 +6,11 @@ const props = defineProps<{
|
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<template>
|
|
9
|
-
<
|
|
10
|
-
|
|
9
|
+
<component
|
|
10
|
+
:is="props.href ? 'a' : 'span'"
|
|
11
11
|
:href="props.href"
|
|
12
12
|
:class="cn('text-gray-900 underline underline-offset-3px', props.class)"
|
|
13
13
|
>
|
|
14
14
|
<slot />
|
|
15
|
-
</
|
|
16
|
-
<span v-else :class="cn('text-gray-900 underline underline-offset-3px', props.class)">
|
|
17
|
-
<slot />
|
|
18
|
-
</span>
|
|
15
|
+
</component>
|
|
19
16
|
</template>
|