@meistrari/tela-build 1.0.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 +75 -0
- package/app.config.ts +73 -0
- package/components/tela/animated/animated-calculating-number.vue +16 -0
- package/components/tela/animated/animated-number.mdx +248 -0
- package/components/tela/animated/animated-number.stories.ts +52 -0
- package/components/tela/animated/animated-number.vue +23 -0
- package/components/tela/animated/animated-text.vue +124 -0
- package/components/tela/animated/animated-value.vue +68 -0
- package/components/tela/avatar/avatar.mdx +117 -0
- package/components/tela/avatar/avatar.stories.ts +62 -0
- package/components/tela/avatar/avatar.vue +71 -0
- package/components/tela/avatar/group/avatar-group.stories.ts +78 -0
- package/components/tela/avatar/group/avatar-group.vue +46 -0
- package/components/tela/badge/badge.mdx +154 -0
- package/components/tela/badge/badge.stories.ts +82 -0
- package/components/tela/badge/badge.vue +41 -0
- package/components/tela/button/button.mdx +155 -0
- package/components/tela/button/button.stories.ts +202 -0
- package/components/tela/button/button.vue +107 -0
- package/components/tela/card.vue +30 -0
- package/components/tela/chart/chart-bar.vue +58 -0
- package/components/tela/chat/chat.mdx +268 -0
- package/components/tela/chat/chat.stories.ts +253 -0
- package/components/tela/chat/command/index.vue +41 -0
- package/components/tela/chat/command/mention/index.vue +138 -0
- package/components/tela/chat/index.vue +112 -0
- package/components/tela/chat/pure-text-input/chat-text-input.vue +190 -0
- package/components/tela/chat/text-input/chat-text-input.stories.ts +128 -0
- package/components/tela/chat/text-input/index.vue +217 -0
- package/components/tela/chat/text-message/chat-text-message.stories.ts +138 -0
- package/components/tela/chat/text-message/index.vue +355 -0
- package/components/tela/chat/types.ts +19 -0
- package/components/tela/checkbox/checkbox-card.vue +30 -0
- package/components/tela/checkbox/checkbox.mdx +164 -0
- package/components/tela/checkbox/checkbox.stories.ts +104 -0
- package/components/tela/checkbox/checkbox.vue +43 -0
- package/components/tela/collapsible/Collapsible.vue +15 -0
- package/components/tela/collapsible/CollapsibleContent.vue +59 -0
- package/components/tela/collapsible/CollapsibleTrigger.vue +12 -0
- package/components/tela/collapsible/collapsible.mdx +157 -0
- package/components/tela/collapsible-section/collapsible-section.mdx +180 -0
- package/components/tela/collapsible-section/collapsible-section.stories.ts +53 -0
- package/components/tela/collapsible-section/collapsible-section.vue +51 -0
- package/components/tela/collapsible-section-with-actions.vue +98 -0
- package/components/tela/combobox/combobox-anchor.vue +24 -0
- package/components/tela/combobox/combobox-empty.vue +19 -0
- package/components/tela/combobox/combobox-group.vue +24 -0
- package/components/tela/combobox/combobox-indicator.vue +22 -0
- package/components/tela/combobox/combobox-input.vue +31 -0
- package/components/tela/combobox/combobox-item.vue +28 -0
- package/components/tela/combobox/combobox-label.vue +24 -0
- package/components/tela/combobox/combobox-list.vue +90 -0
- package/components/tela/combobox/combobox-module-selector.vue +366 -0
- package/components/tela/combobox/combobox-root.vue +15 -0
- package/components/tela/combobox/combobox-trigger.vue +12 -0
- package/components/tela/combobox/combobox.mdx +285 -0
- package/components/tela/combobox/combobox.stories.ts +232 -0
- package/components/tela/combobox/combobox.vue +497 -0
- package/components/tela/command/command-dialog.vue +22 -0
- package/components/tela/command/command-empty.vue +25 -0
- package/components/tela/command/command-group.vue +46 -0
- package/components/tela/command/command-input.vue +38 -0
- package/components/tela/command/command-item.vue +78 -0
- package/components/tela/command/command-list.vue +78 -0
- package/components/tela/command/command-separator.vue +23 -0
- package/components/tela/command/command-shortcut.vue +13 -0
- package/components/tela/command/command.vue +88 -0
- package/components/tela/command/dialog-base.vue +15 -0
- package/components/tela/command/dialog-content.vue +50 -0
- package/components/tela/command/utils.ts +15 -0
- package/components/tela/complex-table/complex-table-cell.stories.ts +145 -0
- package/components/tela/complex-table/complex-table-cell.vue +45 -0
- package/components/tela/complex-table/complex-table-header-cell.stories.ts +103 -0
- package/components/tela/complex-table/complex-table-header-cell.vue +48 -0
- package/components/tela/complex-table/complex-table-header.stories.ts +89 -0
- package/components/tela/complex-table/complex-table-header.vue +70 -0
- package/components/tela/complex-table/complex-table-row.vue +199 -0
- package/components/tela/complex-table/complex-table-virtualized.vue +326 -0
- package/components/tela/complex-table/complex-table.stories.ts +358 -0
- package/components/tela/complex-table/complex-table.vue +237 -0
- package/components/tela/complex-table/composables/table-common.ts +93 -0
- package/components/tela/complex-table/composables/table-selection.ts +87 -0
- package/components/tela/complex-table/composables/virtual-scroll.ts +252 -0
- package/components/tela/complex-table/styles/table-shared.css +170 -0
- package/components/tela/complex-table/types.ts +63 -0
- package/components/tela/complex-table/utils.ts +35 -0
- package/components/tela/confirm-button/confirm-button.vue +137 -0
- package/components/tela/confirmation-modal/confirmation-modal.vue +72 -0
- package/components/tela/copy-button.vue +86 -0
- package/components/tela/date-range-picker.vue +221 -0
- package/components/tela/dialog/dialog.mdx +170 -0
- package/components/tela/dialog/dialog.vue +182 -0
- package/components/tela/disabled-area.vue +16 -0
- package/components/tela/disclaimer/disclaimer.mdx +238 -0
- package/components/tela/disclaimer/disclaimer.stories.ts +196 -0
- package/components/tela/disclaimer/disclaimer.vue +125 -0
- package/components/tela/dropdown-menu/DropdownMenu.vue +121 -0
- package/components/tela/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
- package/components/tela/dropdown-menu/DropdownMenuContent.vue +75 -0
- package/components/tela/dropdown-menu/DropdownMenuGroup.vue +12 -0
- package/components/tela/dropdown-menu/DropdownMenuItem.vue +137 -0
- package/components/tela/dropdown-menu/DropdownMenuLabel.vue +26 -0
- package/components/tela/dropdown-menu/DropdownMenuRadioGroup.vue +18 -0
- package/components/tela/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
- package/components/tela/dropdown-menu/DropdownMenuRoot.vue +15 -0
- package/components/tela/dropdown-menu/DropdownMenuSeparator.vue +21 -0
- package/components/tela/dropdown-menu/DropdownMenuShortcut.vue +14 -0
- package/components/tela/dropdown-menu/DropdownMenuSub.vue +18 -0
- package/components/tela/dropdown-menu/DropdownMenuSubContent.vue +30 -0
- package/components/tela/dropdown-menu/DropdownMenuSubTrigger.vue +35 -0
- package/components/tela/dropdown-menu/DropdownMenuTrigger.vue +14 -0
- package/components/tela/dropdown-menu/dropdown-menu.mdx +265 -0
- package/components/tela/dropdown-menu/dropdown-menu.stories.ts +156 -0
- package/components/tela/expandable-input.vue +96 -0
- package/components/tela/file-drop.vue +37 -0
- package/components/tela/file-upload/file-upload.mdx +189 -0
- package/components/tela/file-upload/file-upload.stories.ts +48 -0
- package/components/tela/file-upload/file-upload.vue +205 -0
- package/components/tela/filters/checkbox-filter.stories.ts +218 -0
- package/components/tela/filters/checkbox-filter.vue +165 -0
- package/components/tela/filters/date-filter.stories.ts +258 -0
- package/components/tela/filters/date-filter.vue +200 -0
- package/components/tela/filters/user-filter.stories.ts +344 -0
- package/components/tela/filters/user-filter.vue +271 -0
- package/components/tela/hover-card/hover-card.mdx +221 -0
- package/components/tela/hover-card/hover-card.stories.ts +87 -0
- package/components/tela/hover-card/hover-card.vue +61 -0
- package/components/tela/icon/custom.vue +319 -0
- package/components/tela/icon/spinner.vue +12 -0
- package/components/tela/icon-button/icon-button.vue +114 -0
- package/components/tela/icon.vue +37 -0
- package/components/tela/initials.vue +28 -0
- package/components/tela/inline-input.vue +77 -0
- package/components/tela/input/input.mdx +182 -0
- package/components/tela/input/input.stories.ts +153 -0
- package/components/tela/input/tela-input.vue +240 -0
- package/components/tela/kbd/kbd-return.vue +6 -0
- package/components/tela/kbd/kbd.mdx +238 -0
- package/components/tela/kbd/kbd.vue +18 -0
- package/components/tela/label/label.mdx +121 -0
- package/components/tela/label/label.stories.ts +37 -0
- package/components/tela/label/label.vue +25 -0
- package/components/tela/link-decoration/link-decoration.vue +19 -0
- package/components/tela/live-label.vue +32 -0
- package/components/tela/long-press-button.vue +98 -0
- package/components/tela/menubar/menubar-content.vue +77 -0
- package/components/tela/menubar/menubar-item.vue +32 -0
- package/components/tela/menubar/menubar-label.vue +14 -0
- package/components/tela/menubar/menubar-menu.vue +12 -0
- package/components/tela/menubar/menubar-root.vue +30 -0
- package/components/tela/menubar/menubar-separator.vue +17 -0
- package/components/tela/menubar/menubar-shortcut.vue +14 -0
- package/components/tela/menubar/menubar-sub-content.vue +36 -0
- package/components/tela/menubar/menubar-sub-trigger.vue +28 -0
- package/components/tela/menubar/menubar-sub.vue +20 -0
- package/components/tela/menubar/menubar-trigger.vue +27 -0
- package/components/tela/menubar/menubar.vue +298 -0
- package/components/tela/modal/modal.mdx +145 -0
- package/components/tela/modal/modal.vue +242 -0
- package/components/tela/multiple-select/multiple-select.mdx +274 -0
- package/components/tela/multiple-select/multiple-select.stories.ts +325 -0
- package/components/tela/multiple-select/multiple-select.vue +666 -0
- package/components/tela/pane.vue +110 -0
- package/components/tela/popover/popover-content.vue +48 -0
- package/components/tela/popover/popover-trigger.vue +12 -0
- package/components/tela/popover/popover.mdx +239 -0
- package/components/tela/popover/popover.stories.ts +150 -0
- package/components/tela/popover/popover.vue +15 -0
- package/components/tela/popover-list/popover-list-nested.vue +104 -0
- package/components/tela/popover-list/popover-list.stories.ts +330 -0
- package/components/tela/popover-list/popover-list.vue +191 -0
- package/components/tela/radio-button.vue +66 -0
- package/components/tela/radio-group/radio-group-item.vue +40 -0
- package/components/tela/radio-group/radio-group-root.vue +26 -0
- package/components/tela/radio-group/radio-group.mdx +78 -0
- package/components/tela/radio-group/radio-group.stories.ts +106 -0
- package/components/tela/radio-group/radio-group.vue +23 -0
- package/components/tela/range-calendar.stories.ts +110 -0
- package/components/tela/range-calendar.vue +109 -0
- package/components/tela/scroll-area/scroll-area.mdx +183 -0
- package/components/tela/scroll-area/scroll-area.vue +30 -0
- package/components/tela/scroll-area/scroll-bar.vue +31 -0
- package/components/tela/segment-toggle.stories.ts +114 -0
- package/components/tela/segment-toggle.vue +66 -0
- package/components/tela/select-menu/select-menu-content.vue +106 -0
- package/components/tela/select-menu/select-menu-down-button.vue +20 -0
- package/components/tela/select-menu/select-menu-group.vue +16 -0
- package/components/tela/select-menu/select-menu-item.vue +40 -0
- package/components/tela/select-menu/select-menu-root.vue +15 -0
- package/components/tela/select-menu/select-menu-trigger.vue +34 -0
- package/components/tela/select-menu/select-menu-up-button.vue +20 -0
- package/components/tela/select-menu/select-menu-value.vue +12 -0
- package/components/tela/select-menu/select-menu.mdx +221 -0
- package/components/tela/select-menu/select-menu.stories.ts +91 -0
- package/components/tela/select-menu/select-menu.vue +165 -0
- package/components/tela/selector/selector.vue +47 -0
- package/components/tela/sheet/sheet-close.vue +12 -0
- package/components/tela/sheet/sheet-content.vue +57 -0
- package/components/tela/sheet/sheet-description.vue +23 -0
- package/components/tela/sheet/sheet-footer.vue +18 -0
- package/components/tela/sheet/sheet-header.vue +15 -0
- package/components/tela/sheet/sheet-root.vue +18 -0
- package/components/tela/sheet/sheet-title.vue +23 -0
- package/components/tela/sheet/sheet-trigger.vue +12 -0
- package/components/tela/sheet/sheet.client.vue +150 -0
- package/components/tela/sheet/sheet.mdx +176 -0
- package/components/tela/sheet/sheet.stories.ts +201 -0
- package/components/tela/sheet/variants.ts +22 -0
- package/components/tela/side-sheet/side-sheet.mdx +131 -0
- package/components/tela/side-sheet/side-sheet.stories.ts +134 -0
- package/components/tela/side-sheet/side-sheet.vue +106 -0
- package/components/tela/skeleton/skeleton.mdx +165 -0
- package/components/tela/skeleton/skeleton.stories.ts +35 -0
- package/components/tela/skeleton/skeleton.vue +45 -0
- package/components/tela/skeleton-icon.vue +24 -0
- package/components/tela/span.vue +24 -0
- package/components/tela/star-button.vue +70 -0
- package/components/tela/status/status-lean.vue +30 -0
- package/components/tela/status/status.mdx +187 -0
- package/components/tela/status/status.stories.ts +160 -0
- package/components/tela/status/status.vue +420 -0
- package/components/tela/status-bar/status-bar.mdx +178 -0
- package/components/tela/status-bar/status-bar.stories.ts +64 -0
- package/components/tela/status-bar/status-bar.vue +56 -0
- package/components/tela/status-bar/types.ts +5 -0
- package/components/tela/switch/switch.mdx +118 -0
- package/components/tela/switch/switch.stories.ts +80 -0
- package/components/tela/switch/switch.vue +56 -0
- package/components/tela/table/table-body.vue +13 -0
- package/components/tela/table/table-caption.vue +13 -0
- package/components/tela/table/table-cell.vue +20 -0
- package/components/tela/table/table-empty.vue +37 -0
- package/components/tela/table/table-footer.vue +13 -0
- package/components/tela/table/table-head.vue +13 -0
- package/components/tela/table/table-header.vue +13 -0
- package/components/tela/table/table-row.vue +13 -0
- package/components/tela/table/table.mdx +230 -0
- package/components/tela/table/table.stories.ts +384 -0
- package/components/tela/table/table.vue +15 -0
- package/components/tela/tabs/tabs-content.vue +20 -0
- package/components/tela/tabs/tabs-indicator.vue +22 -0
- package/components/tela/tabs/tabs-list.vue +23 -0
- package/components/tela/tabs/tabs-root.vue +15 -0
- package/components/tela/tabs/tabs-trigger.vue +27 -0
- package/components/tela/tabs/tabs.mdx +138 -0
- package/components/tela/tabs/tabs.stories.ts +72 -0
- package/components/tela/tabs/tabs.vue +61 -0
- package/components/tela/tags/tags-select.mdx +318 -0
- package/components/tela/tags/tags-select.stories.ts +47 -0
- package/components/tela/tags/tags-select.vue +637 -0
- package/components/tela/tags/tags.mdx +151 -0
- package/components/tela/tags/tags.stories.ts +118 -0
- package/components/tela/tags/tags.vue +112 -0
- package/components/tela/textarea/textarea.mdx +102 -0
- package/components/tela/textarea/textarea.stories.ts +50 -0
- package/components/tela/textarea/textarea.vue +34 -0
- package/components/tela/toggle-group.vue +91 -0
- package/components/tela/tooltip/tooltip-content.vue +45 -0
- package/components/tela/tooltip/tooltip-provider.vue +12 -0
- package/components/tela/tooltip/tooltip-root.vue +15 -0
- package/components/tela/tooltip/tooltip-trigger.vue +12 -0
- package/components/tela/tooltip/tooltip.mdx +196 -0
- package/components/tela/tooltip/tooltip.stories.ts +200 -0
- package/components/tela/tooltip/tooltip.vue +91 -0
- package/components/tela/tooltip-group/tooltip-group-trigger.vue +92 -0
- package/components/tela/tooltip-group/tooltip-group.mdx +236 -0
- package/components/tela/tooltip-group/tooltip-group.stories.ts +465 -0
- package/components/tela/tooltip-group/tooltip-group.vue +35 -0
- package/components/tela/transparent-input.vue +151 -0
- package/components/tela/variable-icon.vue +28 -0
- package/components/tela/variable-input.vue +77 -0
- package/components/tela/wide-button/wide-button.vue +40 -0
- package/components.json +18 -0
- package/composables/status-toast.ts +67 -0
- package/css/reset.css +386 -0
- package/css/text.css +22 -0
- package/lib/doc-generator.ts +903 -0
- package/lib/extractors/volar-extract.ts +186 -0
- package/lib/type-resolver.ts +402 -0
- package/lib/utils.ts +6 -0
- package/modules/tela-build-docs/index.ts +139 -0
- package/nuxt.config.ts +80 -0
- package/package.json +84 -0
- package/plugins/test-id.ts +7 -0
- package/tsconfig.json +7 -0
- package/types/custom-icon.ts +1 -0
- package/types/index.ts +2 -0
- package/types/status.ts +1 -0
- package/unocss.config.ts +89 -0
- package/utils/component-utils.ts +30 -0
- package/utils/design-tokens.ts +431 -0
- package/utils/fold.ts +8 -0
- package/utils/select-menu.ts +10 -0
- package/utils/status.ts +1 -0
- package/utils/without-keys.ts +34 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Pane } from 'splitpanes'
|
|
3
|
+
|
|
4
|
+
const props = defineProps<{
|
|
5
|
+
title?: string
|
|
6
|
+
subtitle?: string
|
|
7
|
+
size?: number
|
|
8
|
+
minSize?: number
|
|
9
|
+
icon?: string
|
|
10
|
+
iconUrl?: string
|
|
11
|
+
collapsible?: boolean
|
|
12
|
+
collapseThreshold?: number
|
|
13
|
+
collapsedSize?: number
|
|
14
|
+
collapsedIcon?: string
|
|
15
|
+
startCollapsed?: boolean
|
|
16
|
+
disableSplit?: boolean
|
|
17
|
+
}>()
|
|
18
|
+
|
|
19
|
+
const emit = defineEmits<{
|
|
20
|
+
'update:collapse': [size: number]
|
|
21
|
+
}>()
|
|
22
|
+
|
|
23
|
+
const size = ref(props.size)
|
|
24
|
+
const collapsedSize = ref(props.collapsedSize ?? 7)
|
|
25
|
+
const sizeBeforeCollapse = ref(props.size)
|
|
26
|
+
const isCollapsed = ref(Boolean(props.startCollapsed))
|
|
27
|
+
|
|
28
|
+
watch(() => props.size, (newValue) => {
|
|
29
|
+
size.value = newValue
|
|
30
|
+
|
|
31
|
+
if (isCollapsed.value && newValue !== collapsedSize.value)
|
|
32
|
+
isCollapsed.value = false
|
|
33
|
+
|
|
34
|
+
if (!isCollapsed.value && newValue && newValue <= collapsedSize.value + (props.collapseThreshold ?? 0)) {
|
|
35
|
+
isCollapsed.value = true
|
|
36
|
+
emit('update:collapse', collapsedSize.value)
|
|
37
|
+
}
|
|
38
|
+
}, { immediate: true })
|
|
39
|
+
|
|
40
|
+
function toggleCollapse() {
|
|
41
|
+
if (isCollapsed.value) {
|
|
42
|
+
isCollapsed.value = false
|
|
43
|
+
emit('update:collapse', Math.max(sizeBeforeCollapse.value ?? 0, props.minSize ?? 0, collapsedSize.value + 8))
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
isCollapsed.value = true
|
|
47
|
+
sizeBeforeCollapse.value = size.value
|
|
48
|
+
emit('update:collapse', collapsedSize.value)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
<template>
|
|
54
|
+
<component
|
|
55
|
+
:is="disableSplit ? 'div' : Pane"
|
|
56
|
+
:size="disableSplit ? undefined : size"
|
|
57
|
+
:min-size="minSize"
|
|
58
|
+
>
|
|
59
|
+
<div v-if="title || $slots.actions" flex items-center w-full justify-between relative h-72px z-1>
|
|
60
|
+
<Transition name="fade">
|
|
61
|
+
<div v-if="title && !isCollapsed" flex flex-col p-24px>
|
|
62
|
+
<div flex>
|
|
63
|
+
<img v-if="iconUrl" :src="iconUrl" w-24px>
|
|
64
|
+
<TelaIcon v-else-if="icon" :name="icon" w-24px />
|
|
65
|
+
<div :m="(iconUrl || icon) ? 'l-16px' : 'l-8px'" font-semibold text="14px textcolor">
|
|
66
|
+
{{ title }}
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
<div v-if="subtitle" :m="(iconUrl || icon) ? 'l-16px' : 'l-8px'" font-regular text="13px gray-800">
|
|
70
|
+
{{ subtitle }}
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</Transition>
|
|
74
|
+
<div absolute top-16px right-32px flex items-center gap-8px>
|
|
75
|
+
<slot name="actions" />
|
|
76
|
+
|
|
77
|
+
<TelaButton
|
|
78
|
+
v-if="collapsible"
|
|
79
|
+
transition ease-in-out
|
|
80
|
+
ml-12px
|
|
81
|
+
icon="i-ph-arrow-left"
|
|
82
|
+
size="sm"
|
|
83
|
+
color="primary"
|
|
84
|
+
variant="ghost"
|
|
85
|
+
:class="{
|
|
86
|
+
'rotate-180': !isCollapsed,
|
|
87
|
+
}"
|
|
88
|
+
@click="toggleCollapse"
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<slot v-if="!isCollapsed" />
|
|
94
|
+
</component>
|
|
95
|
+
</template>
|
|
96
|
+
|
|
97
|
+
<style scoped>
|
|
98
|
+
.fade-enter-active {
|
|
99
|
+
transition: opacity 0.6s cubic-bezier(1, 0, 0, 1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.fade-leave-active {
|
|
103
|
+
transition: opacity 0.6s cubic-bezier(1, 0, 0, 1);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.fade-enter-from,
|
|
107
|
+
.fade-leave-to {
|
|
108
|
+
opacity: 0;
|
|
109
|
+
}
|
|
110
|
+
</style>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
PopoverContent,
|
|
4
|
+
PopoverPortal,
|
|
5
|
+
useForwardPropsEmits,
|
|
6
|
+
} from 'reka-ui'
|
|
7
|
+
import type { PopoverContentEmits, PopoverContentProps } from 'reka-ui'
|
|
8
|
+
import { computed } from 'vue'
|
|
9
|
+
import type { HTMLAttributes } from 'vue'
|
|
10
|
+
|
|
11
|
+
defineOptions({
|
|
12
|
+
inheritAttrs: false,
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const props = withDefaults(
|
|
16
|
+
defineProps<PopoverContentProps & { class?: HTMLAttributes['class'] }>(),
|
|
17
|
+
{
|
|
18
|
+
align: 'center',
|
|
19
|
+
sideOffset: 4,
|
|
20
|
+
},
|
|
21
|
+
)
|
|
22
|
+
const emits = defineEmits<PopoverContentEmits>()
|
|
23
|
+
|
|
24
|
+
const delegatedProps = computed(() => {
|
|
25
|
+
const { class: _, ...delegated } = props
|
|
26
|
+
|
|
27
|
+
return delegated
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const forwarded = useForwardPropsEmits(delegatedProps, emits)
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<PopoverPortal>
|
|
35
|
+
<PopoverContent
|
|
36
|
+
v-bind="{ ...forwarded, ...$attrs }"
|
|
37
|
+
:class="
|
|
38
|
+
cn(
|
|
39
|
+
'w-72 rounded-md border-[1px] bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
40
|
+
props.class,
|
|
41
|
+
)
|
|
42
|
+
"
|
|
43
|
+
z-700
|
|
44
|
+
>
|
|
45
|
+
<slot />
|
|
46
|
+
</PopoverContent>
|
|
47
|
+
</PopoverPortal>
|
|
48
|
+
</template>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { PopoverTrigger } from 'reka-ui'
|
|
3
|
+
import type { PopoverTriggerProps } from 'reka-ui'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<PopoverTriggerProps>()
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<PopoverTrigger v-bind="props">
|
|
10
|
+
<slot />
|
|
11
|
+
</PopoverTrigger>
|
|
12
|
+
</template>
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as PopoverStories from './popover.stories.ts';
|
|
3
|
+
|
|
4
|
+
<Meta of={PopoverStories} />
|
|
5
|
+
|
|
6
|
+
# TelaPopover
|
|
7
|
+
|
|
8
|
+
A popover component that displays content in a floating panel. Supports positioning on all sides (top, right, bottom, left) with different alignments (start, center, end). Built with composable subcomponents for flexible usage.
|
|
9
|
+
|
|
10
|
+
## Examples
|
|
11
|
+
|
|
12
|
+
### With Custom Content
|
|
13
|
+
|
|
14
|
+
<Canvas of={PopoverStories.WithCustomContent} />
|
|
15
|
+
|
|
16
|
+
### Different Positions
|
|
17
|
+
|
|
18
|
+
<Canvas of={PopoverStories.WithDifferentPositions} />
|
|
19
|
+
|
|
20
|
+
### Different Alignments
|
|
21
|
+
|
|
22
|
+
<Canvas of={PopoverStories.WithDifferentAlignments} />
|
|
23
|
+
|
|
24
|
+
### Basic Usage
|
|
25
|
+
|
|
26
|
+
```vue
|
|
27
|
+
<script setup>
|
|
28
|
+
import { ref } from 'vue'
|
|
29
|
+
|
|
30
|
+
const isOpen = ref(false)
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<TelaPopover v-model:open="isOpen">
|
|
35
|
+
<TelaPopoverTrigger>
|
|
36
|
+
<TelaButton>Open Popover</TelaButton>
|
|
37
|
+
</TelaPopoverTrigger>
|
|
38
|
+
<TelaPopoverContent>
|
|
39
|
+
<div class="p-4">
|
|
40
|
+
<h3>Popover Content</h3>
|
|
41
|
+
<p>This is the popover content</p>
|
|
42
|
+
</div>
|
|
43
|
+
</TelaPopoverContent>
|
|
44
|
+
</TelaPopover>
|
|
45
|
+
</template>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### With Custom Content Code
|
|
49
|
+
|
|
50
|
+
```vue
|
|
51
|
+
<TelaPopover v-model:open="isOpen">
|
|
52
|
+
<TelaPopoverTrigger>
|
|
53
|
+
<TelaButton>Options</TelaButton>
|
|
54
|
+
</TelaPopoverTrigger>
|
|
55
|
+
<TelaPopoverContent>
|
|
56
|
+
<div class="flex flex-col gap-2 p-2">
|
|
57
|
+
<button class="p-2 hover:bg-gray-100 rounded">
|
|
58
|
+
Option 1
|
|
59
|
+
</button>
|
|
60
|
+
<button class="p-2 hover:bg-gray-100 rounded">
|
|
61
|
+
Option 2
|
|
62
|
+
</button>
|
|
63
|
+
<button class="p-2 hover:bg-gray-100 rounded">
|
|
64
|
+
Option 3
|
|
65
|
+
</button>
|
|
66
|
+
</div>
|
|
67
|
+
</TelaPopoverContent>
|
|
68
|
+
</TelaPopover>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Different Positions Code
|
|
72
|
+
|
|
73
|
+
```vue
|
|
74
|
+
<!-- Top -->
|
|
75
|
+
<TelaPopover>
|
|
76
|
+
<TelaPopoverTrigger>
|
|
77
|
+
<TelaButton>Top</TelaButton>
|
|
78
|
+
</TelaPopoverTrigger>
|
|
79
|
+
<TelaPopoverContent side="top">
|
|
80
|
+
Popover on top
|
|
81
|
+
</TelaPopoverContent>
|
|
82
|
+
</TelaPopover>
|
|
83
|
+
|
|
84
|
+
<!-- Right -->
|
|
85
|
+
<TelaPopover>
|
|
86
|
+
<TelaPopoverTrigger>
|
|
87
|
+
<TelaButton>Right</TelaButton>
|
|
88
|
+
</TelaPopoverTrigger>
|
|
89
|
+
<TelaPopoverContent side="right">
|
|
90
|
+
Popover on right
|
|
91
|
+
</TelaPopoverContent>
|
|
92
|
+
</TelaPopover>
|
|
93
|
+
|
|
94
|
+
<!-- Bottom (default) -->
|
|
95
|
+
<TelaPopover>
|
|
96
|
+
<TelaPopoverTrigger>
|
|
97
|
+
<TelaButton>Bottom</TelaButton>
|
|
98
|
+
</TelaPopoverTrigger>
|
|
99
|
+
<TelaPopoverContent side="bottom">
|
|
100
|
+
Popover on bottom
|
|
101
|
+
</TelaPopoverContent>
|
|
102
|
+
</TelaPopover>
|
|
103
|
+
|
|
104
|
+
<!-- Left -->
|
|
105
|
+
<TelaPopover>
|
|
106
|
+
<TelaPopoverTrigger>
|
|
107
|
+
<TelaButton>Left</TelaButton>
|
|
108
|
+
</TelaPopoverTrigger>
|
|
109
|
+
<TelaPopoverContent side="left">
|
|
110
|
+
Popover on left
|
|
111
|
+
</TelaPopoverContent>
|
|
112
|
+
</TelaPopover>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
```vue
|
|
116
|
+
<!-- Align Start -->
|
|
117
|
+
<TelaPopover>
|
|
118
|
+
<TelaPopoverTrigger>
|
|
119
|
+
<TelaButton>Start</TelaButton>
|
|
120
|
+
</TelaPopoverTrigger>
|
|
121
|
+
<TelaPopoverContent align="start">
|
|
122
|
+
Aligned to start
|
|
123
|
+
</TelaPopoverContent>
|
|
124
|
+
</TelaPopover>
|
|
125
|
+
|
|
126
|
+
<!-- Align Center (default) -->
|
|
127
|
+
<TelaPopover>
|
|
128
|
+
<TelaPopoverTrigger>
|
|
129
|
+
<TelaButton>Center</TelaButton>
|
|
130
|
+
</TelaPopoverTrigger>
|
|
131
|
+
<TelaPopoverContent align="center">
|
|
132
|
+
Aligned to center
|
|
133
|
+
</TelaPopoverContent>
|
|
134
|
+
</TelaPopover>
|
|
135
|
+
|
|
136
|
+
<!-- Align End -->
|
|
137
|
+
<TelaPopover>
|
|
138
|
+
<TelaPopoverTrigger>
|
|
139
|
+
<TelaButton>End</TelaButton>
|
|
140
|
+
</TelaPopoverTrigger>
|
|
141
|
+
<TelaPopoverContent align="end">
|
|
142
|
+
Aligned to end
|
|
143
|
+
</TelaPopoverContent>
|
|
144
|
+
</TelaPopover>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### With Side Offset
|
|
148
|
+
|
|
149
|
+
```vue
|
|
150
|
+
<TelaPopover>
|
|
151
|
+
<TelaPopoverTrigger>
|
|
152
|
+
<TelaButton>With Offset</TelaButton>
|
|
153
|
+
</TelaPopoverTrigger>
|
|
154
|
+
<TelaPopoverContent :side-offset="20">
|
|
155
|
+
Popover with 20px offset
|
|
156
|
+
</TelaPopoverContent>
|
|
157
|
+
</TelaPopover>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Form in Popover
|
|
161
|
+
|
|
162
|
+
```vue
|
|
163
|
+
<TelaPopover v-model:open="isOpen">
|
|
164
|
+
<TelaPopoverTrigger>
|
|
165
|
+
<TelaButton>Add Item</TelaButton>
|
|
166
|
+
</TelaPopoverTrigger>
|
|
167
|
+
<TelaPopoverContent>
|
|
168
|
+
<form @submit.prevent="onSubmit" class="p-4 w-300px">
|
|
169
|
+
<h3 class="text-lg font-medium mb-4">Add New Item</h3>
|
|
170
|
+
<TelaInput label="Name" v-model="name" class="mb-3" />
|
|
171
|
+
<TelaTextarea label="Description" v-model="description" class="mb-4" />
|
|
172
|
+
<div class="flex gap-2 justify-end">
|
|
173
|
+
<TelaButton variant="secondary" @click="isOpen = false">
|
|
174
|
+
Cancel
|
|
175
|
+
</TelaButton>
|
|
176
|
+
<TelaButton type="submit" variant="primary">
|
|
177
|
+
Add
|
|
178
|
+
</TelaButton>
|
|
179
|
+
</div>
|
|
180
|
+
</form>
|
|
181
|
+
</TelaPopoverContent>
|
|
182
|
+
</TelaPopover>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Props
|
|
186
|
+
|
|
187
|
+
<ArgTypes />
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
type PopoverSide = 'top' | 'right' | 'bottom' | 'left'
|
|
191
|
+
type PopoverAlign = 'start' | 'center' | 'end'
|
|
192
|
+
|
|
193
|
+
type PopoverProps = {
|
|
194
|
+
open?: boolean
|
|
195
|
+
side?: PopoverSide
|
|
196
|
+
align?: PopoverAlign
|
|
197
|
+
sideOffset?: number
|
|
198
|
+
ariaLabel?: string
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## Components
|
|
203
|
+
|
|
204
|
+
- `TelaPopover` - Root popover container
|
|
205
|
+
- `TelaPopoverTrigger` - Trigger button/element
|
|
206
|
+
- `TelaPopoverContent` - Content panel
|
|
207
|
+
|
|
208
|
+
## Features
|
|
209
|
+
|
|
210
|
+
- **Flexible Positioning**: All sides and alignments
|
|
211
|
+
- **Click to Open**: Opens on click (vs hover for tooltip)
|
|
212
|
+
- **Click Outside to Close**: Closes when clicking outside
|
|
213
|
+
- **Escape Key**: Press Escape to close
|
|
214
|
+
- **Custom Content**: Full control over popover content
|
|
215
|
+
- **Side Offset**: Control distance from trigger
|
|
216
|
+
- **Accessible**: Built on reka-ui with proper ARIA
|
|
217
|
+
- **Portal Rendering**: Renders in portal to avoid z-index issues
|
|
218
|
+
|
|
219
|
+
## Popover vs Tooltip
|
|
220
|
+
|
|
221
|
+
- **Popover**: Click to open, rich interactive content
|
|
222
|
+
- **Tooltip**: Hover to show, brief informational text
|
|
223
|
+
|
|
224
|
+
## Best Practices
|
|
225
|
+
|
|
226
|
+
1. **Use for Actions**: Popovers are for interactive content
|
|
227
|
+
2. **Keep Content Focused**: Don't overload with too much content
|
|
228
|
+
3. **Provide Close Option**: Ensure users can close easily
|
|
229
|
+
4. **Position Wisely**: Ensure popover doesn't cover important UI
|
|
230
|
+
5. **Mobile Friendly**: Popovers work better than tooltips on touch
|
|
231
|
+
|
|
232
|
+
## Accessibility
|
|
233
|
+
|
|
234
|
+
- Built on reka-ui primitives
|
|
235
|
+
- Proper ARIA attributes (role="dialog")
|
|
236
|
+
- Keyboard navigation (Escape to close)
|
|
237
|
+
- Focus management
|
|
238
|
+
- Click outside to close
|
|
239
|
+
- Screen reader support
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import { fn } from '@storybook/test'
|
|
3
|
+
import Popover from './popover.vue'
|
|
4
|
+
import PopoverTrigger from './popover-trigger.vue'
|
|
5
|
+
import PopoverContent from './popover-content.vue'
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof Popover> = {
|
|
8
|
+
title: 'Core/Popover',
|
|
9
|
+
component: Popover,
|
|
10
|
+
subcomponents: { PopoverTrigger, PopoverContent },
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'centered',
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component: 'A popover component that displays content in a floating panel. Supports positioning on all sides (top, right, bottom, left) with different alignments (start, center, end). Built with composable subcomponents for flexible usage.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
argTypes: {
|
|
20
|
+
open: {
|
|
21
|
+
control: 'boolean',
|
|
22
|
+
description: 'Controls the open state of the popover. Use v-model:open for two-way binding.',
|
|
23
|
+
},
|
|
24
|
+
side: {
|
|
25
|
+
control: 'select',
|
|
26
|
+
options: ['top', 'right', 'bottom', 'left'],
|
|
27
|
+
description: 'Side of the trigger element where the popover should appear.',
|
|
28
|
+
},
|
|
29
|
+
align: {
|
|
30
|
+
control: 'select',
|
|
31
|
+
options: ['start', 'center', 'end'],
|
|
32
|
+
description: 'Alignment of the popover content relative to the trigger element.',
|
|
33
|
+
},
|
|
34
|
+
sideOffset: {
|
|
35
|
+
control: 'number',
|
|
36
|
+
description: 'Distance in pixels from the trigger element to the popover content.',
|
|
37
|
+
},
|
|
38
|
+
ariaLabel: {
|
|
39
|
+
control: 'text',
|
|
40
|
+
description: 'Accessibility label for the popover trigger element.',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
args: {
|
|
44
|
+
'onUpdate:open': fn(),
|
|
45
|
+
'side': 'bottom',
|
|
46
|
+
'align': 'center',
|
|
47
|
+
'ariaLabel': 'Popover trigger',
|
|
48
|
+
} as any,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default meta
|
|
52
|
+
|
|
53
|
+
type Story = StoryObj<typeof meta>
|
|
54
|
+
|
|
55
|
+
export const Default: Story = {
|
|
56
|
+
render: args => ({
|
|
57
|
+
components: { Popover, PopoverTrigger, PopoverContent },
|
|
58
|
+
setup() {
|
|
59
|
+
const isOpen = ref(false)
|
|
60
|
+
return { args, isOpen }
|
|
61
|
+
},
|
|
62
|
+
template: `
|
|
63
|
+
<div style="padding: 100px; display: flex; justify-content: center;">
|
|
64
|
+
<Popover v-model:open="isOpen" v-bind="args">
|
|
65
|
+
<PopoverTrigger>
|
|
66
|
+
<button>Click me</button>
|
|
67
|
+
</PopoverTrigger>
|
|
68
|
+
<PopoverContent>
|
|
69
|
+
<h3 class="text-lg font-medium">Popover Content</h3>
|
|
70
|
+
<p class="mt-2">This is the content of the popover.</p>
|
|
71
|
+
</PopoverContent>
|
|
72
|
+
</Popover>
|
|
73
|
+
</div>
|
|
74
|
+
`,
|
|
75
|
+
}),
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const WithCustomContent: Story = {
|
|
79
|
+
render: args => ({
|
|
80
|
+
components: { Popover, PopoverTrigger, PopoverContent },
|
|
81
|
+
setup() {
|
|
82
|
+
const isOpen = ref(false)
|
|
83
|
+
return { args, isOpen }
|
|
84
|
+
},
|
|
85
|
+
template: `
|
|
86
|
+
<div style="padding: 100px; display: flex; justify-content: center;">
|
|
87
|
+
<Popover v-model:open="isOpen" v-bind="args">
|
|
88
|
+
<PopoverTrigger>
|
|
89
|
+
<button class="px-4 py-2 bg-blue-500 text-white rounded">
|
|
90
|
+
Hover me
|
|
91
|
+
</button>
|
|
92
|
+
</PopoverTrigger>
|
|
93
|
+
<PopoverContent>
|
|
94
|
+
<div class="flex flex-col gap-2">
|
|
95
|
+
<button class="p-2 hover:bg-gray-100 rounded">Option 1</button>
|
|
96
|
+
<button class="p-2 hover:bg-gray-100 rounded">Option 2</button>
|
|
97
|
+
<button class="p-2 hover:bg-gray-100 rounded">Option 3</button>
|
|
98
|
+
</div>
|
|
99
|
+
</PopoverContent>
|
|
100
|
+
</Popover>
|
|
101
|
+
</div>
|
|
102
|
+
`,
|
|
103
|
+
}),
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const WithDifferentPositions: Story = {
|
|
107
|
+
render: args => ({
|
|
108
|
+
components: { Popover, PopoverTrigger, PopoverContent },
|
|
109
|
+
setup() {
|
|
110
|
+
return { args }
|
|
111
|
+
},
|
|
112
|
+
template: `
|
|
113
|
+
<div style="padding: 100px; display: flex; gap: 100px; justify-content: center; flex-wrap: wrap;">
|
|
114
|
+
<Popover v-for="side in ['top', 'right', 'bottom', 'left']" :key="side" v-bind="args">
|
|
115
|
+
<PopoverTrigger>
|
|
116
|
+
<button class="px-4 py-2 bg-gray-200 rounded">
|
|
117
|
+
{{ side }}
|
|
118
|
+
</button>
|
|
119
|
+
</PopoverTrigger>
|
|
120
|
+
<PopoverContent :side="side">
|
|
121
|
+
Popover on {{ side }}
|
|
122
|
+
</PopoverContent>
|
|
123
|
+
</Popover>
|
|
124
|
+
</div>
|
|
125
|
+
`,
|
|
126
|
+
}),
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export const WithDifferentAlignments: Story = {
|
|
130
|
+
render: args => ({
|
|
131
|
+
components: { Popover, PopoverTrigger, PopoverContent },
|
|
132
|
+
setup() {
|
|
133
|
+
return { args }
|
|
134
|
+
},
|
|
135
|
+
template: `
|
|
136
|
+
<div style="padding: 100px; display: flex; gap: 100px; justify-content: center; flex-wrap: wrap;">
|
|
137
|
+
<Popover v-for="align in ['start', 'center', 'end']" :key="align" v-bind="args">
|
|
138
|
+
<PopoverTrigger>
|
|
139
|
+
<button class="px-4 py-2 bg-gray-200 rounded">
|
|
140
|
+
{{ align }}
|
|
141
|
+
</button>
|
|
142
|
+
</PopoverTrigger>
|
|
143
|
+
<PopoverContent :align="align">
|
|
144
|
+
Popover on {{ align }}
|
|
145
|
+
</PopoverContent>
|
|
146
|
+
</Popover>
|
|
147
|
+
</div>
|
|
148
|
+
`,
|
|
149
|
+
}),
|
|
150
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { PopoverRootEmits, PopoverRootProps } from 'reka-ui'
|
|
3
|
+
import { PopoverRoot, useForwardPropsEmits } from 'reka-ui'
|
|
4
|
+
|
|
5
|
+
const props = defineProps<PopoverRootProps>()
|
|
6
|
+
const emits = defineEmits<PopoverRootEmits>()
|
|
7
|
+
|
|
8
|
+
const forwarded = useForwardPropsEmits(props, emits)
|
|
9
|
+
</script>
|
|
10
|
+
|
|
11
|
+
<template>
|
|
12
|
+
<PopoverRoot v-bind="forwarded">
|
|
13
|
+
<slot />
|
|
14
|
+
</PopoverRoot>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
<script setup lang="ts" generic="T">
|
|
2
|
+
interface PopoverListNestedProps<T> {
|
|
3
|
+
items: T[]
|
|
4
|
+
depth?: number
|
|
5
|
+
variant?: 'attributes' | 'detailed'
|
|
6
|
+
hasChildrenFn: (item: T) => boolean
|
|
7
|
+
getChildrenFn: (item: T) => T[]
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const props = defineProps<PopoverListNestedProps<T>>()
|
|
11
|
+
|
|
12
|
+
function getNestedItemName(item: T): string {
|
|
13
|
+
if (typeof item === 'object' && item !== null) {
|
|
14
|
+
const obj = item as any
|
|
15
|
+
return obj.name || obj.id || 'Item'
|
|
16
|
+
}
|
|
17
|
+
return String(item)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getNestedItemValue(item: T): any {
|
|
21
|
+
if (typeof item === 'object' && item !== null) {
|
|
22
|
+
const obj = item as any
|
|
23
|
+
const value = obj.value !== undefined ? obj.value : item
|
|
24
|
+
|
|
25
|
+
// Se o valor é um objeto complexo, não exibir no modo detailed
|
|
26
|
+
if (typeof value === 'object' && value !== null) {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return value
|
|
31
|
+
}
|
|
32
|
+
return item
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function shouldShowValue(item: T): boolean {
|
|
36
|
+
const value = getNestedItemValue(item)
|
|
37
|
+
return value !== null && value !== undefined
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const textStyle = computed(() => props.depth
|
|
41
|
+
? 'text-gray-300 text-[11px] tracking-[-0.022px]'
|
|
42
|
+
: 'text-[#EFF1F3] text-[12px] tracking-[-0.024px]')
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<template>
|
|
46
|
+
<div v-for="(item, index) in items" :key="`${getNestedItemName(item)}-${index}`">
|
|
47
|
+
<!-- Detailed variant -->
|
|
48
|
+
<div v-if="getNestedItemName(item) && variant === 'detailed'" class="flex flex-col items-start self-stretch pb-8px rounded-md p-1">
|
|
49
|
+
<span class="text-white text-[12px] font-semibold">
|
|
50
|
+
<slot name="item" :item="item" :index="index" :depth="depth">
|
|
51
|
+
{{ getNestedItemName(item) }}
|
|
52
|
+
</slot>
|
|
53
|
+
</span>
|
|
54
|
+
<span v-if="shouldShowValue(item)" class="text-[#BDC4CC] text-[12px]">
|
|
55
|
+
{{ getNestedItemValue(item) }}
|
|
56
|
+
</span>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<!-- Detailed variant without name -->
|
|
60
|
+
<div v-else-if="variant === 'detailed' && !getNestedItemName(item)" class="flex flex-col items-start self-stretch pb-8px rounded-md p-1">
|
|
61
|
+
<span v-if="shouldShowValue(item)" class="text-[#BDC4CC] text-[12px]">
|
|
62
|
+
<slot name="item" :item="item" :index="index" :depth="depth">
|
|
63
|
+
{{ getNestedItemValue(item) }}
|
|
64
|
+
</slot>
|
|
65
|
+
</span>
|
|
66
|
+
<span v-else class="text-[#BDC4CC] text-[12px]">
|
|
67
|
+
No value yet
|
|
68
|
+
</span>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<!-- Attributes variant -->
|
|
72
|
+
<div v-if="getNestedItemName(item) && variant === 'attributes'" class="flex items-center gap-4px self-stretch py-2px rounded-md px-1">
|
|
73
|
+
<div class="w-2 h-2 rounded-full flex py-[2px] items-center gap-4px self-stretch">
|
|
74
|
+
<svg width="6" height="8" viewBox="0 0 6 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
75
|
+
<g id="ColorArea">
|
|
76
|
+
<circle id="Color" cx="2" cy="5" r="2" fill="#8BA5FF" />
|
|
77
|
+
</g>
|
|
78
|
+
</svg>
|
|
79
|
+
</div>
|
|
80
|
+
<p class="text-justify font-inter font-medium leading-[12px] max-w-[150px] truncate text-ellipsis" :class="[textStyle]">
|
|
81
|
+
<slot name="item" :item="item" :index="index" :depth="depth">
|
|
82
|
+
{{ getNestedItemName(item) }}
|
|
83
|
+
</slot>
|
|
84
|
+
</p>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<!-- Nested children -->
|
|
88
|
+
<template v-if="hasChildrenFn(item)">
|
|
89
|
+
<div class="pl-4">
|
|
90
|
+
<PopoverListNested
|
|
91
|
+
:items="getChildrenFn(item)"
|
|
92
|
+
:depth="(depth ?? 0) + 1"
|
|
93
|
+
:variant="variant"
|
|
94
|
+
:has-children-fn="hasChildrenFn"
|
|
95
|
+
:get-children-fn="getChildrenFn"
|
|
96
|
+
>
|
|
97
|
+
<template #item="slotProps: any">
|
|
98
|
+
<slot name="item" v-bind="slotProps" />
|
|
99
|
+
</template>
|
|
100
|
+
</PopoverListNested>
|
|
101
|
+
</div>
|
|
102
|
+
</template>
|
|
103
|
+
</div>
|
|
104
|
+
</template>
|