@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.
Files changed (295) hide show
  1. package/README.md +75 -0
  2. package/app.config.ts +73 -0
  3. package/components/tela/animated/animated-calculating-number.vue +16 -0
  4. package/components/tela/animated/animated-number.mdx +248 -0
  5. package/components/tela/animated/animated-number.stories.ts +52 -0
  6. package/components/tela/animated/animated-number.vue +23 -0
  7. package/components/tela/animated/animated-text.vue +124 -0
  8. package/components/tela/animated/animated-value.vue +68 -0
  9. package/components/tela/avatar/avatar.mdx +117 -0
  10. package/components/tela/avatar/avatar.stories.ts +62 -0
  11. package/components/tela/avatar/avatar.vue +71 -0
  12. package/components/tela/avatar/group/avatar-group.stories.ts +78 -0
  13. package/components/tela/avatar/group/avatar-group.vue +46 -0
  14. package/components/tela/badge/badge.mdx +154 -0
  15. package/components/tela/badge/badge.stories.ts +82 -0
  16. package/components/tela/badge/badge.vue +41 -0
  17. package/components/tela/button/button.mdx +155 -0
  18. package/components/tela/button/button.stories.ts +202 -0
  19. package/components/tela/button/button.vue +107 -0
  20. package/components/tela/card.vue +30 -0
  21. package/components/tela/chart/chart-bar.vue +58 -0
  22. package/components/tela/chat/chat.mdx +268 -0
  23. package/components/tela/chat/chat.stories.ts +253 -0
  24. package/components/tela/chat/command/index.vue +41 -0
  25. package/components/tela/chat/command/mention/index.vue +138 -0
  26. package/components/tela/chat/index.vue +112 -0
  27. package/components/tela/chat/pure-text-input/chat-text-input.vue +190 -0
  28. package/components/tela/chat/text-input/chat-text-input.stories.ts +128 -0
  29. package/components/tela/chat/text-input/index.vue +217 -0
  30. package/components/tela/chat/text-message/chat-text-message.stories.ts +138 -0
  31. package/components/tela/chat/text-message/index.vue +355 -0
  32. package/components/tela/chat/types.ts +19 -0
  33. package/components/tela/checkbox/checkbox-card.vue +30 -0
  34. package/components/tela/checkbox/checkbox.mdx +164 -0
  35. package/components/tela/checkbox/checkbox.stories.ts +104 -0
  36. package/components/tela/checkbox/checkbox.vue +43 -0
  37. package/components/tela/collapsible/Collapsible.vue +15 -0
  38. package/components/tela/collapsible/CollapsibleContent.vue +59 -0
  39. package/components/tela/collapsible/CollapsibleTrigger.vue +12 -0
  40. package/components/tela/collapsible/collapsible.mdx +157 -0
  41. package/components/tela/collapsible-section/collapsible-section.mdx +180 -0
  42. package/components/tela/collapsible-section/collapsible-section.stories.ts +53 -0
  43. package/components/tela/collapsible-section/collapsible-section.vue +51 -0
  44. package/components/tela/collapsible-section-with-actions.vue +98 -0
  45. package/components/tela/combobox/combobox-anchor.vue +24 -0
  46. package/components/tela/combobox/combobox-empty.vue +19 -0
  47. package/components/tela/combobox/combobox-group.vue +24 -0
  48. package/components/tela/combobox/combobox-indicator.vue +22 -0
  49. package/components/tela/combobox/combobox-input.vue +31 -0
  50. package/components/tela/combobox/combobox-item.vue +28 -0
  51. package/components/tela/combobox/combobox-label.vue +24 -0
  52. package/components/tela/combobox/combobox-list.vue +90 -0
  53. package/components/tela/combobox/combobox-module-selector.vue +366 -0
  54. package/components/tela/combobox/combobox-root.vue +15 -0
  55. package/components/tela/combobox/combobox-trigger.vue +12 -0
  56. package/components/tela/combobox/combobox.mdx +285 -0
  57. package/components/tela/combobox/combobox.stories.ts +232 -0
  58. package/components/tela/combobox/combobox.vue +497 -0
  59. package/components/tela/command/command-dialog.vue +22 -0
  60. package/components/tela/command/command-empty.vue +25 -0
  61. package/components/tela/command/command-group.vue +46 -0
  62. package/components/tela/command/command-input.vue +38 -0
  63. package/components/tela/command/command-item.vue +78 -0
  64. package/components/tela/command/command-list.vue +78 -0
  65. package/components/tela/command/command-separator.vue +23 -0
  66. package/components/tela/command/command-shortcut.vue +13 -0
  67. package/components/tela/command/command.vue +88 -0
  68. package/components/tela/command/dialog-base.vue +15 -0
  69. package/components/tela/command/dialog-content.vue +50 -0
  70. package/components/tela/command/utils.ts +15 -0
  71. package/components/tela/complex-table/complex-table-cell.stories.ts +145 -0
  72. package/components/tela/complex-table/complex-table-cell.vue +45 -0
  73. package/components/tela/complex-table/complex-table-header-cell.stories.ts +103 -0
  74. package/components/tela/complex-table/complex-table-header-cell.vue +48 -0
  75. package/components/tela/complex-table/complex-table-header.stories.ts +89 -0
  76. package/components/tela/complex-table/complex-table-header.vue +70 -0
  77. package/components/tela/complex-table/complex-table-row.vue +199 -0
  78. package/components/tela/complex-table/complex-table-virtualized.vue +326 -0
  79. package/components/tela/complex-table/complex-table.stories.ts +358 -0
  80. package/components/tela/complex-table/complex-table.vue +237 -0
  81. package/components/tela/complex-table/composables/table-common.ts +93 -0
  82. package/components/tela/complex-table/composables/table-selection.ts +87 -0
  83. package/components/tela/complex-table/composables/virtual-scroll.ts +252 -0
  84. package/components/tela/complex-table/styles/table-shared.css +170 -0
  85. package/components/tela/complex-table/types.ts +63 -0
  86. package/components/tela/complex-table/utils.ts +35 -0
  87. package/components/tela/confirm-button/confirm-button.vue +137 -0
  88. package/components/tela/confirmation-modal/confirmation-modal.vue +72 -0
  89. package/components/tela/copy-button.vue +86 -0
  90. package/components/tela/date-range-picker.vue +221 -0
  91. package/components/tela/dialog/dialog.mdx +170 -0
  92. package/components/tela/dialog/dialog.vue +182 -0
  93. package/components/tela/disabled-area.vue +16 -0
  94. package/components/tela/disclaimer/disclaimer.mdx +238 -0
  95. package/components/tela/disclaimer/disclaimer.stories.ts +196 -0
  96. package/components/tela/disclaimer/disclaimer.vue +125 -0
  97. package/components/tela/dropdown-menu/DropdownMenu.vue +121 -0
  98. package/components/tela/dropdown-menu/DropdownMenuCheckboxItem.vue +40 -0
  99. package/components/tela/dropdown-menu/DropdownMenuContent.vue +75 -0
  100. package/components/tela/dropdown-menu/DropdownMenuGroup.vue +12 -0
  101. package/components/tela/dropdown-menu/DropdownMenuItem.vue +137 -0
  102. package/components/tela/dropdown-menu/DropdownMenuLabel.vue +26 -0
  103. package/components/tela/dropdown-menu/DropdownMenuRadioGroup.vue +18 -0
  104. package/components/tela/dropdown-menu/DropdownMenuRadioItem.vue +40 -0
  105. package/components/tela/dropdown-menu/DropdownMenuRoot.vue +15 -0
  106. package/components/tela/dropdown-menu/DropdownMenuSeparator.vue +21 -0
  107. package/components/tela/dropdown-menu/DropdownMenuShortcut.vue +14 -0
  108. package/components/tela/dropdown-menu/DropdownMenuSub.vue +18 -0
  109. package/components/tela/dropdown-menu/DropdownMenuSubContent.vue +30 -0
  110. package/components/tela/dropdown-menu/DropdownMenuSubTrigger.vue +35 -0
  111. package/components/tela/dropdown-menu/DropdownMenuTrigger.vue +14 -0
  112. package/components/tela/dropdown-menu/dropdown-menu.mdx +265 -0
  113. package/components/tela/dropdown-menu/dropdown-menu.stories.ts +156 -0
  114. package/components/tela/expandable-input.vue +96 -0
  115. package/components/tela/file-drop.vue +37 -0
  116. package/components/tela/file-upload/file-upload.mdx +189 -0
  117. package/components/tela/file-upload/file-upload.stories.ts +48 -0
  118. package/components/tela/file-upload/file-upload.vue +205 -0
  119. package/components/tela/filters/checkbox-filter.stories.ts +218 -0
  120. package/components/tela/filters/checkbox-filter.vue +165 -0
  121. package/components/tela/filters/date-filter.stories.ts +258 -0
  122. package/components/tela/filters/date-filter.vue +200 -0
  123. package/components/tela/filters/user-filter.stories.ts +344 -0
  124. package/components/tela/filters/user-filter.vue +271 -0
  125. package/components/tela/hover-card/hover-card.mdx +221 -0
  126. package/components/tela/hover-card/hover-card.stories.ts +87 -0
  127. package/components/tela/hover-card/hover-card.vue +61 -0
  128. package/components/tela/icon/custom.vue +319 -0
  129. package/components/tela/icon/spinner.vue +12 -0
  130. package/components/tela/icon-button/icon-button.vue +114 -0
  131. package/components/tela/icon.vue +37 -0
  132. package/components/tela/initials.vue +28 -0
  133. package/components/tela/inline-input.vue +77 -0
  134. package/components/tela/input/input.mdx +182 -0
  135. package/components/tela/input/input.stories.ts +153 -0
  136. package/components/tela/input/tela-input.vue +240 -0
  137. package/components/tela/kbd/kbd-return.vue +6 -0
  138. package/components/tela/kbd/kbd.mdx +238 -0
  139. package/components/tela/kbd/kbd.vue +18 -0
  140. package/components/tela/label/label.mdx +121 -0
  141. package/components/tela/label/label.stories.ts +37 -0
  142. package/components/tela/label/label.vue +25 -0
  143. package/components/tela/link-decoration/link-decoration.vue +19 -0
  144. package/components/tela/live-label.vue +32 -0
  145. package/components/tela/long-press-button.vue +98 -0
  146. package/components/tela/menubar/menubar-content.vue +77 -0
  147. package/components/tela/menubar/menubar-item.vue +32 -0
  148. package/components/tela/menubar/menubar-label.vue +14 -0
  149. package/components/tela/menubar/menubar-menu.vue +12 -0
  150. package/components/tela/menubar/menubar-root.vue +30 -0
  151. package/components/tela/menubar/menubar-separator.vue +17 -0
  152. package/components/tela/menubar/menubar-shortcut.vue +14 -0
  153. package/components/tela/menubar/menubar-sub-content.vue +36 -0
  154. package/components/tela/menubar/menubar-sub-trigger.vue +28 -0
  155. package/components/tela/menubar/menubar-sub.vue +20 -0
  156. package/components/tela/menubar/menubar-trigger.vue +27 -0
  157. package/components/tela/menubar/menubar.vue +298 -0
  158. package/components/tela/modal/modal.mdx +145 -0
  159. package/components/tela/modal/modal.vue +242 -0
  160. package/components/tela/multiple-select/multiple-select.mdx +274 -0
  161. package/components/tela/multiple-select/multiple-select.stories.ts +325 -0
  162. package/components/tela/multiple-select/multiple-select.vue +666 -0
  163. package/components/tela/pane.vue +110 -0
  164. package/components/tela/popover/popover-content.vue +48 -0
  165. package/components/tela/popover/popover-trigger.vue +12 -0
  166. package/components/tela/popover/popover.mdx +239 -0
  167. package/components/tela/popover/popover.stories.ts +150 -0
  168. package/components/tela/popover/popover.vue +15 -0
  169. package/components/tela/popover-list/popover-list-nested.vue +104 -0
  170. package/components/tela/popover-list/popover-list.stories.ts +330 -0
  171. package/components/tela/popover-list/popover-list.vue +191 -0
  172. package/components/tela/radio-button.vue +66 -0
  173. package/components/tela/radio-group/radio-group-item.vue +40 -0
  174. package/components/tela/radio-group/radio-group-root.vue +26 -0
  175. package/components/tela/radio-group/radio-group.mdx +78 -0
  176. package/components/tela/radio-group/radio-group.stories.ts +106 -0
  177. package/components/tela/radio-group/radio-group.vue +23 -0
  178. package/components/tela/range-calendar.stories.ts +110 -0
  179. package/components/tela/range-calendar.vue +109 -0
  180. package/components/tela/scroll-area/scroll-area.mdx +183 -0
  181. package/components/tela/scroll-area/scroll-area.vue +30 -0
  182. package/components/tela/scroll-area/scroll-bar.vue +31 -0
  183. package/components/tela/segment-toggle.stories.ts +114 -0
  184. package/components/tela/segment-toggle.vue +66 -0
  185. package/components/tela/select-menu/select-menu-content.vue +106 -0
  186. package/components/tela/select-menu/select-menu-down-button.vue +20 -0
  187. package/components/tela/select-menu/select-menu-group.vue +16 -0
  188. package/components/tela/select-menu/select-menu-item.vue +40 -0
  189. package/components/tela/select-menu/select-menu-root.vue +15 -0
  190. package/components/tela/select-menu/select-menu-trigger.vue +34 -0
  191. package/components/tela/select-menu/select-menu-up-button.vue +20 -0
  192. package/components/tela/select-menu/select-menu-value.vue +12 -0
  193. package/components/tela/select-menu/select-menu.mdx +221 -0
  194. package/components/tela/select-menu/select-menu.stories.ts +91 -0
  195. package/components/tela/select-menu/select-menu.vue +165 -0
  196. package/components/tela/selector/selector.vue +47 -0
  197. package/components/tela/sheet/sheet-close.vue +12 -0
  198. package/components/tela/sheet/sheet-content.vue +57 -0
  199. package/components/tela/sheet/sheet-description.vue +23 -0
  200. package/components/tela/sheet/sheet-footer.vue +18 -0
  201. package/components/tela/sheet/sheet-header.vue +15 -0
  202. package/components/tela/sheet/sheet-root.vue +18 -0
  203. package/components/tela/sheet/sheet-title.vue +23 -0
  204. package/components/tela/sheet/sheet-trigger.vue +12 -0
  205. package/components/tela/sheet/sheet.client.vue +150 -0
  206. package/components/tela/sheet/sheet.mdx +176 -0
  207. package/components/tela/sheet/sheet.stories.ts +201 -0
  208. package/components/tela/sheet/variants.ts +22 -0
  209. package/components/tela/side-sheet/side-sheet.mdx +131 -0
  210. package/components/tela/side-sheet/side-sheet.stories.ts +134 -0
  211. package/components/tela/side-sheet/side-sheet.vue +106 -0
  212. package/components/tela/skeleton/skeleton.mdx +165 -0
  213. package/components/tela/skeleton/skeleton.stories.ts +35 -0
  214. package/components/tela/skeleton/skeleton.vue +45 -0
  215. package/components/tela/skeleton-icon.vue +24 -0
  216. package/components/tela/span.vue +24 -0
  217. package/components/tela/star-button.vue +70 -0
  218. package/components/tela/status/status-lean.vue +30 -0
  219. package/components/tela/status/status.mdx +187 -0
  220. package/components/tela/status/status.stories.ts +160 -0
  221. package/components/tela/status/status.vue +420 -0
  222. package/components/tela/status-bar/status-bar.mdx +178 -0
  223. package/components/tela/status-bar/status-bar.stories.ts +64 -0
  224. package/components/tela/status-bar/status-bar.vue +56 -0
  225. package/components/tela/status-bar/types.ts +5 -0
  226. package/components/tela/switch/switch.mdx +118 -0
  227. package/components/tela/switch/switch.stories.ts +80 -0
  228. package/components/tela/switch/switch.vue +56 -0
  229. package/components/tela/table/table-body.vue +13 -0
  230. package/components/tela/table/table-caption.vue +13 -0
  231. package/components/tela/table/table-cell.vue +20 -0
  232. package/components/tela/table/table-empty.vue +37 -0
  233. package/components/tela/table/table-footer.vue +13 -0
  234. package/components/tela/table/table-head.vue +13 -0
  235. package/components/tela/table/table-header.vue +13 -0
  236. package/components/tela/table/table-row.vue +13 -0
  237. package/components/tela/table/table.mdx +230 -0
  238. package/components/tela/table/table.stories.ts +384 -0
  239. package/components/tela/table/table.vue +15 -0
  240. package/components/tela/tabs/tabs-content.vue +20 -0
  241. package/components/tela/tabs/tabs-indicator.vue +22 -0
  242. package/components/tela/tabs/tabs-list.vue +23 -0
  243. package/components/tela/tabs/tabs-root.vue +15 -0
  244. package/components/tela/tabs/tabs-trigger.vue +27 -0
  245. package/components/tela/tabs/tabs.mdx +138 -0
  246. package/components/tela/tabs/tabs.stories.ts +72 -0
  247. package/components/tela/tabs/tabs.vue +61 -0
  248. package/components/tela/tags/tags-select.mdx +318 -0
  249. package/components/tela/tags/tags-select.stories.ts +47 -0
  250. package/components/tela/tags/tags-select.vue +637 -0
  251. package/components/tela/tags/tags.mdx +151 -0
  252. package/components/tela/tags/tags.stories.ts +118 -0
  253. package/components/tela/tags/tags.vue +112 -0
  254. package/components/tela/textarea/textarea.mdx +102 -0
  255. package/components/tela/textarea/textarea.stories.ts +50 -0
  256. package/components/tela/textarea/textarea.vue +34 -0
  257. package/components/tela/toggle-group.vue +91 -0
  258. package/components/tela/tooltip/tooltip-content.vue +45 -0
  259. package/components/tela/tooltip/tooltip-provider.vue +12 -0
  260. package/components/tela/tooltip/tooltip-root.vue +15 -0
  261. package/components/tela/tooltip/tooltip-trigger.vue +12 -0
  262. package/components/tela/tooltip/tooltip.mdx +196 -0
  263. package/components/tela/tooltip/tooltip.stories.ts +200 -0
  264. package/components/tela/tooltip/tooltip.vue +91 -0
  265. package/components/tela/tooltip-group/tooltip-group-trigger.vue +92 -0
  266. package/components/tela/tooltip-group/tooltip-group.mdx +236 -0
  267. package/components/tela/tooltip-group/tooltip-group.stories.ts +465 -0
  268. package/components/tela/tooltip-group/tooltip-group.vue +35 -0
  269. package/components/tela/transparent-input.vue +151 -0
  270. package/components/tela/variable-icon.vue +28 -0
  271. package/components/tela/variable-input.vue +77 -0
  272. package/components/tela/wide-button/wide-button.vue +40 -0
  273. package/components.json +18 -0
  274. package/composables/status-toast.ts +67 -0
  275. package/css/reset.css +386 -0
  276. package/css/text.css +22 -0
  277. package/lib/doc-generator.ts +903 -0
  278. package/lib/extractors/volar-extract.ts +186 -0
  279. package/lib/type-resolver.ts +402 -0
  280. package/lib/utils.ts +6 -0
  281. package/modules/tela-build-docs/index.ts +139 -0
  282. package/nuxt.config.ts +80 -0
  283. package/package.json +84 -0
  284. package/plugins/test-id.ts +7 -0
  285. package/tsconfig.json +7 -0
  286. package/types/custom-icon.ts +1 -0
  287. package/types/index.ts +2 -0
  288. package/types/status.ts +1 -0
  289. package/unocss.config.ts +89 -0
  290. package/utils/component-utils.ts +30 -0
  291. package/utils/design-tokens.ts +431 -0
  292. package/utils/fold.ts +8 -0
  293. package/utils/select-menu.ts +10 -0
  294. package/utils/status.ts +1 -0
  295. package/utils/without-keys.ts +34 -0
@@ -0,0 +1,366 @@
1
+ <script setup lang="ts">
2
+ import { ref, computed, watch } from 'vue'
3
+ import { useMagicKeys } from '@vueuse/core'
4
+ import { useI18n } from 'vue-i18n'
5
+
6
+ import { ComboboxRoot as Combobox, ComboboxTrigger } from 'reka-ui'
7
+ import type { AllActionsInfo } from 'tela-workflow/src/actions'
8
+
9
+ import ComboboxAnchor from './combobox-anchor.vue'
10
+ import ComboboxEmpty from './combobox-empty.vue'
11
+ import ComboboxGroup from './combobox-group.vue'
12
+ import ComboboxInput from './combobox-input.vue'
13
+ import ComboboxItem from './combobox-item.vue'
14
+ import ComboboxList from './combobox-list.vue'
15
+ import ComboboxLabel from './combobox-label.vue'
16
+
17
+ import Tabs from '../tabs/tabs-root.vue'
18
+ import TabsContent from '../tabs/tabs-content.vue'
19
+ import TabsList from '../tabs/tabs-list.vue'
20
+ import TabsIndicator from '../tabs/tabs-indicator.vue'
21
+ import TabsTrigger from '../tabs/tabs-trigger.vue'
22
+
23
+ export interface CombinedOption {
24
+ label: string
25
+ description?: string
26
+ value: AllActionsInfo['actionName']
27
+ icon: string
28
+ enabled?: () => boolean | undefined
29
+ tabs?: string[]
30
+ }
31
+
32
+ const props = withDefaults(defineProps<{
33
+ options: CombinedOption[]
34
+ comboSide?: 'top' | 'bottom'
35
+ listClass?: string
36
+ closeOnOutsideClick?: boolean
37
+ closeOnEscape?: boolean
38
+ priority?: 'low' | 'normal' | 'high'
39
+ inline?: boolean
40
+ to?: string | HTMLElement
41
+ }>(), {
42
+ closeOnOutsideClick: true,
43
+ closeOnEscape: true,
44
+ comboSide: 'top',
45
+ priority: 'normal',
46
+ inline: false,
47
+ })
48
+
49
+ const emit = defineEmits<{
50
+ 'update:modelValue': [value: string]
51
+ 'select': [value: string]
52
+ 'selectWorkflowModule': [value: string]
53
+ }>()
54
+
55
+ const { t } = useI18n()
56
+
57
+ const open = defineModel<boolean>('open')
58
+
59
+ const selectedTab = ref('everything')
60
+ const search = ref('')
61
+ const innerValue = ref<string>('')
62
+ const zIndexValue = computed(() => {
63
+ switch (props.priority) {
64
+ case 'low':
65
+ return 1
66
+ case 'high':
67
+ return 9999
68
+ case 'normal':
69
+ default:
70
+ return 999
71
+ }
72
+ })
73
+
74
+ const effectiveOptions = computed((): CombinedOption[] => {
75
+ return (props.options).map(option => ({
76
+ value: option.value,
77
+ label: option.label,
78
+ description: option.description,
79
+ icon: option.icon,
80
+ enabled: option.enabled,
81
+ tabs: option.tabs,
82
+ }))
83
+ })
84
+
85
+ const tabs = computed(() => {
86
+ const allTabs = effectiveOptions.value.reduce((acc, option) => {
87
+ if (option.tabs) {
88
+ option.tabs.forEach((tab) => {
89
+ if (!acc.find(t => t.tab === tab)) {
90
+ acc.push({ tab, label: tab.charAt(0).toUpperCase() + tab.slice(1) })
91
+ }
92
+ })
93
+ }
94
+ return acc
95
+ }, [] as Array<{ tab: string, label: string }>)
96
+
97
+ const hasAll = allTabs.find(t => t.tab === 'everything')
98
+
99
+ if (!hasAll) {
100
+ allTabs.unshift({ tab: 'everything', label: t('workflow.modules.everything') })
101
+ }
102
+
103
+ return allTabs
104
+ })
105
+
106
+ const groupedOptions = computed(() => {
107
+ let filteredOptions = effectiveOptions.value
108
+
109
+ if (selectedTab.value !== 'everything') {
110
+ filteredOptions = effectiveOptions.value.filter(option =>
111
+ option.tabs?.includes(selectedTab.value),
112
+ )
113
+ }
114
+
115
+ if (search.value.trim()) {
116
+ filteredOptions = filteredOptions.filter(option =>
117
+ option.label.toLowerCase().includes(search.value.toLowerCase())
118
+ || option.description?.toLowerCase().includes(search.value.toLowerCase()),
119
+ )
120
+
121
+ filteredOptions = filteredOptions.filter((item, idx, arr) =>
122
+ arr.findIndex(i => i.value === item.value) === idx,
123
+ )
124
+ }
125
+
126
+ if (selectedTab.value === 'everything') {
127
+ const categoryGroups: Record<string, typeof filteredOptions> = {}
128
+
129
+ filteredOptions.forEach((option) => {
130
+ if (option.tabs?.includes('modules')) {
131
+ const modulesLabel = t('workflow.modules.modules')
132
+ if (!categoryGroups[modulesLabel])
133
+ categoryGroups[modulesLabel] = []
134
+ categoryGroups[modulesLabel].push(option)
135
+ }
136
+ if (option.tabs?.includes('resources')) {
137
+ const resourcesLabel = t('workflow.modules.resources')
138
+ if (!categoryGroups[resourcesLabel])
139
+ categoryGroups[resourcesLabel] = []
140
+ categoryGroups[resourcesLabel].push(option)
141
+ }
142
+ if (option.tabs?.includes('actions')) {
143
+ const actionsLabel = t('workflow.modules.actions')
144
+ if (!categoryGroups[actionsLabel])
145
+ categoryGroups[actionsLabel] = []
146
+ categoryGroups[actionsLabel].push(option)
147
+ }
148
+ })
149
+
150
+ return Object.entries(categoryGroups).map(([heading, children]) => ({
151
+ heading,
152
+ children: children.filter((item, idx, arr) =>
153
+ arr.findIndex(i => i.value === item.value) === idx,
154
+ ),
155
+ })).filter(group => group.children.length > 0)
156
+ }
157
+
158
+ return [{
159
+ heading: selectedTab.value.charAt(0).toUpperCase() + selectedTab.value.slice(1),
160
+ children: filteredOptions,
161
+ }].filter(group => group.children.length > 0)
162
+ })
163
+
164
+ const handleDeleteSearchValue = () => search.value = ''
165
+
166
+ const keys = useMagicKeys()
167
+ const CmdBackspace = keys['Cmd+Backspace']
168
+
169
+ watch(CmdBackspace as Ref<boolean>, (v) => {
170
+ if (v)
171
+ handleDeleteSearchValue()
172
+ })
173
+
174
+ function handleSelect(option: any) {
175
+ emit('select', option.value)
176
+ emit('selectWorkflowModule', option.value)
177
+ emit('update:modelValue', option.value)
178
+ }
179
+
180
+ function getBackgroundColor(heading: string) {
181
+ switch (heading) {
182
+ case 'Modules':
183
+ return 'bg-[#E6ECFF] text-[#315FFF]'
184
+ case 'Resources':
185
+ return 'bg-[#EEE2FF] text-[#7114FF]'
186
+ case 'Stop':
187
+ return 'bg-[#FDE6EA] text-red'
188
+ default:
189
+ return 'bg-[#F1F1F4] text-[#315FFF]'
190
+ }
191
+ }
192
+
193
+ watch(innerValue, (value) => {
194
+ if (!value)
195
+ return
196
+
197
+ const option = effectiveOptions.value.find(option => option.value === value)
198
+
199
+ if (!option)
200
+ return
201
+
202
+ innerValue.value = ''
203
+
204
+ emit('select', value)
205
+ emit('selectWorkflowModule', value)
206
+ emit('update:modelValue', value)
207
+ })
208
+ </script>
209
+
210
+ <template>
211
+ <Combobox
212
+ v-model="innerValue" v-model:open="open" by="value"
213
+ @update:model-value="handleSelect"
214
+ >
215
+ <ComboboxAnchor>
216
+ <ComboboxTrigger
217
+ as="button"
218
+ class="group select-none flex items-center justify-center gap-3 rounded-full size-3.5 hover:size-6 bg-white border-[1.5px] border-gray-200 transition-[width,height] outline-none data-[state=open]:bg-gray-50 data-[state=open]:size-6"
219
+ >
220
+ <TelaIcon name="i-ph-plus-bold" size="14px" class="text-gray-400 group-hover:text-gray-400 opacity-0 duration-200 group-hover:opacity-100 group-data-[state=open]:rotate-45 group-data-[state=open]:text-gray-400 group-data-[state=open]:opacity-100" />
221
+ </ComboboxTrigger>
222
+ </ComboboxAnchor>
223
+ <ComboboxList
224
+ class="min-w-400px w-400px"
225
+ :style="{ zIndex: zIndexValue }"
226
+ align="center"
227
+ :side="comboSide"
228
+ :side-offset="8"
229
+ as-child
230
+ has-animate
231
+ :position="inline ? 'inline' : 'popper'"
232
+ :position-strategy="inline ? 'absolute' : 'fixed'"
233
+ :to="to"
234
+ @interact-outside="closeOnOutsideClick ? undefined : $event.preventDefault()"
235
+ @pointer-down-outside="closeOnOutsideClick ? undefined : $event.preventDefault()"
236
+ @escape-key-down="closeOnEscape ? undefined : $event.preventDefault()"
237
+ >
238
+ <div class="relative">
239
+ <span class="absolute inset-y-0 start-0 flex items-center justify-center px-2.5">
240
+ <TelaIcon name="i-ph-magnifying-glass" size="12px" class="text-gray-400" />
241
+ </span>
242
+ <ComboboxInput
243
+ v-model="search" class="pl-7 rounded-b-none"
244
+ :placeholder="t('models.labels.search')"
245
+ />
246
+ <div v-if="search.length > 0" class="absolute inset-y-0 end-0 flex items-center justify-center px-2.5">
247
+ <button class="flex items-center justify-center" @click="handleDeleteSearchValue">
248
+ <TelaIcon name="i-ph-x-circle" size="16px" class="text-gray-400" />
249
+ </button>
250
+ </div>
251
+ </div>
252
+ <Tabs v-model="selectedTab" :default-value="selectedTab">
253
+ <TabsList class="sticky z-10 top-0 shrink-0 flex gap-2 w-full">
254
+ <TabsIndicator />
255
+ <TabsTrigger v-for="tab in tabs" :key="tab.tab" :value="tab.tab">
256
+ {{ tab.label }}
257
+ </TabsTrigger>
258
+ </TabsList>
259
+ <TabsContent :value="selectedTab" class="max-h-262px overflow-y-auto no-scrollbar" :class="listClass">
260
+ <ComboboxEmpty
261
+ v-if="groupedOptions.length === 0 || groupedOptions.every(g => g.children.length === 0)"
262
+ class="flex flex-col items-center justify-center gap-5 px-7"
263
+ >
264
+ <div class="flex flex-col items-center justify-center gap-3">
265
+ <TelaIcon name="i-ph-smiley-sad" size="24px" class="text-gray-400" />
266
+ <span class="text-xl font-medium leading-none">
267
+ {{ $t('common.noItemsFound') }}{{ search.trim() ? ` with '${search}'` : '' }}
268
+ </span>
269
+ <span v-if="search.trim()" class="inline-flex gap-1.5 text-md text-gray-500">
270
+ {{ $t('common.press') }}
271
+ <div class="flex items-center gap-1">
272
+ <div class="p-2px bg-gray-200 rounded">
273
+ <TelaIcon name="i-ph-command" size="16px" />
274
+ </div>
275
+ <div class="p-2px bg-gray-200 rounded">
276
+ <TelaIcon name="i-ph-backspace" size="16px" />
277
+ </div>
278
+ </div>
279
+ {{ $t('common.toClear') }}
280
+ </span>
281
+ </div>
282
+ <TelaButton
283
+ v-if="search.trim()" variant="secondary" size="sm" class="rounded-lg"
284
+ @click="handleDeleteSearchValue"
285
+ >
286
+ {{ $t('common.clear') }}
287
+ </TelaButton>
288
+ </ComboboxEmpty>
289
+ <template v-for="group in groupedOptions" :key="group.heading">
290
+ <ComboboxGroup :heading="group.heading" class="py-2">
291
+ <ComboboxLabel v-if="!search.trim()" class="py-0 tracking-normal">
292
+ {{ group.heading }}
293
+ </ComboboxLabel>
294
+ <ComboboxItem
295
+ v-for="item in group.children"
296
+ :key="item.value"
297
+ :value="item"
298
+ :disabled="!item.enabled?.()"
299
+ class="group py-2"
300
+ >
301
+ <div class="flex items-center">
302
+ <div class="flex items-center gap-2">
303
+ <div :class="cn('w-6 h-6 shrink-0 flex items-center justify-center rounded-md', getBackgroundColor(item.label === 'Stop' ? item.label : group.heading))">
304
+ <TelaIcon
305
+ :name="item.icon"
306
+ size="15px"
307
+ />
308
+ </div>
309
+ <div class="flex flex-col w-full">
310
+ <div class="flex flex-col">
311
+ <div v-if="!item.enabled?.()" class="flex items-center gap-1">
312
+ <span class="font-medium truncate max-w-140px">{{ item.label }}</span>
313
+ <span
314
+ class="font-semibold uppercase text-9px tracking-wider text-gray-700 bg-gray-100 rounded leading-none py-2px px-1"
315
+ >{{ $t('common.comingSoon') }}</span>
316
+ </div>
317
+ <span v-else class="font-medium truncate max-w-140px">{{ item.label }}</span>
318
+ <span v-if="item.description" class="font-normal text-sm leading-none text-gray-500">
319
+ {{ item.description }}
320
+ </span>
321
+ </div>
322
+ </div>
323
+ </div>
324
+ </div>
325
+ </ComboboxItem>
326
+ </ComboboxGroup>
327
+ </template>
328
+ </TabsContent>
329
+ </Tabs>
330
+ </ComboboxList>
331
+ </Combobox>
332
+ </template>
333
+
334
+ <style scoped>
335
+ /* Force UnoCSS to include dynamic icons used in moduleOptions */
336
+ .dynamic-icons-safelist {
337
+ @apply i-ph-pencil-simple-bold;
338
+ @apply i-ph-arrow-square-in-bold;
339
+ @apply i-ph-code-bold;
340
+ @apply i-ph-arrows-split-bold;
341
+ @apply i-ph-arrows-out-line-horizontal-bold;
342
+ @apply i-ph-crop-bold;
343
+ @apply i-ph-map-trifold-bold;
344
+ @apply i-ph-arrow-bend-up-right;
345
+ @apply i-ph-arrow-bend-down-right;
346
+ @apply i-ph-checks;
347
+ @apply i-ph-record;
348
+ @apply i-ph-square-bold;
349
+ @apply i-ph-lightbulb-bold;
350
+
351
+ display: none;
352
+ }
353
+
354
+ .nuxt-icon {
355
+ margin-bottom: 0;
356
+ }
357
+
358
+ .no-scrollbar {
359
+ -ms-overflow-style: none;
360
+ scrollbar-width: none;
361
+
362
+ &::-webkit-scrollbar {
363
+ display: none;
364
+ }
365
+ }
366
+ </style>
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import { ComboboxRoot, useForwardPropsEmits } from 'reka-ui'
3
+ import type { ComboboxRootProps, ComboboxRootEmits } from 'reka-ui'
4
+
5
+ const props = defineProps<ComboboxRootProps>()
6
+ const emits = defineEmits<ComboboxRootEmits>()
7
+
8
+ const forwarded = useForwardPropsEmits(props, emits)
9
+ </script>
10
+
11
+ <template>
12
+ <ComboboxRoot v-bind="forwarded">
13
+ <slot />
14
+ </ComboboxRoot>
15
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import { ComboboxTrigger } from 'reka-ui'
3
+ import type { ComboboxTriggerProps } from 'reka-ui'
4
+
5
+ const props = defineProps<ComboboxTriggerProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <ComboboxTrigger v-bind="props">
10
+ <slot />
11
+ </ComboboxTrigger>
12
+ </template>
@@ -0,0 +1,285 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as ComboboxStories from './combobox.stories.ts';
3
+
4
+ <Meta of={ComboboxStories} />
5
+
6
+ # TelaCombobox
7
+
8
+ A searchable combobox component built on reka-ui. Allows users to search and select from a list of options. Supports filtering, icons, descriptions, grouping, tabs, token limits display, and custom styling. The component provides a searchable dropdown interface with keyboard navigation (Cmd+Backspace to clear search).
9
+
10
+ ## Examples
11
+
12
+ ### Basic Usage
13
+
14
+ ```vue
15
+ <script setup>
16
+ import { ref } from 'vue'
17
+
18
+ const selected = ref('')
19
+ const options = [
20
+ { value: 'bug', label: 'Bug' },
21
+ { value: 'feature', label: 'Feature Request' },
22
+ { value: 'improvement', label: 'Improvement' }
23
+ ]
24
+ </script>
25
+
26
+ <template>
27
+ <TelaCombobox
28
+ v-model="selected"
29
+ :options="options"
30
+ placeholder="Select an option"
31
+ input-placeholder="Search..."
32
+ />
33
+ </template>
34
+ ```
35
+
36
+ ### With Icons and Descriptions
37
+
38
+ ```vue
39
+ <TelaCombobox
40
+ v-model="selected"
41
+ :options="[
42
+ {
43
+ value: 'gpt4',
44
+ label: 'GPT-4',
45
+ icon: 'i-ph-brain',
46
+ description: 'Most capable model',
47
+ maxInputTokens: 8000,
48
+ maxOutputTokens: 4000
49
+ },
50
+ {
51
+ value: 'gpt3',
52
+ label: 'GPT-3.5',
53
+ icon: 'i-ph-lightning',
54
+ description: 'Fast and efficient',
55
+ maxInputTokens: 4000,
56
+ maxOutputTokens: 2000
57
+ }
58
+ ]"
59
+ />
60
+ ```
61
+
62
+ ### With Grouping
63
+
64
+ ```vue
65
+ <script setup>
66
+ import { ref } from 'vue'
67
+
68
+ const selected = ref('')
69
+ const options = [
70
+ { value: 'gpt4', label: 'GPT-4', group: 'OpenAI' },
71
+ { value: 'gpt3', label: 'GPT-3.5', group: 'OpenAI' },
72
+ { value: 'claude', label: 'Claude', group: 'Anthropic' },
73
+ { value: 'gemini', label: 'Gemini', group: 'Google' }
74
+ ]
75
+ </script>
76
+
77
+ <template>
78
+ <TelaCombobox
79
+ v-model="selected"
80
+ :options="options"
81
+ :has-grouping-labels="true"
82
+ />
83
+ </template>
84
+ ```
85
+
86
+ ### With Tabs
87
+
88
+ ```vue
89
+ <TelaCombobox
90
+ v-model="selected"
91
+ :options="[
92
+ {
93
+ value: 'gpt4',
94
+ label: 'GPT-4',
95
+ tabs: ['all', 'text']
96
+ },
97
+ {
98
+ value: 'gpt4v',
99
+ label: 'GPT-4 Vision',
100
+ tabs: ['all', 'multimodal'],
101
+ isMultiModal: true
102
+ },
103
+ {
104
+ value: 'claude',
105
+ label: 'Claude',
106
+ tabs: ['all', 'text']
107
+ }
108
+ ]"
109
+ />
110
+ ```
111
+
112
+ ### Compact vs Non-Compact
113
+
114
+ ```vue
115
+ <!-- Compact (default) -->
116
+ <TelaCombobox
117
+ v-model="selected"
118
+ :options="options"
119
+ :compact="true"
120
+ />
121
+
122
+ <!-- Non-compact with more spacing -->
123
+ <TelaCombobox
124
+ v-model="selected"
125
+ :options="options"
126
+ :compact="false"
127
+ />
128
+ ```
129
+
130
+ ### Custom Styling
131
+
132
+ ```vue
133
+ <TelaCombobox
134
+ v-model="selected"
135
+ :options="options"
136
+ trigger-class="w-400px"
137
+ content-class="max-h-500px"
138
+ label-class="text-blue-600"
139
+ description-class="text-gray-600"
140
+ />
141
+ ```
142
+
143
+ ### With Cost Indicator
144
+
145
+ ```vue
146
+ <TelaCombobox
147
+ v-model="selected"
148
+ :options="[
149
+ { value: 'gpt4', label: 'GPT-4', cost: 5 },
150
+ { value: 'claude', label: 'Claude', cost: 3 },
151
+ { value: 'gpt3', label: 'GPT-3.5', cost: 1 }
152
+ ]"
153
+ />
154
+ ```
155
+
156
+ ### Read-Only State
157
+
158
+ ```vue
159
+ <TelaCombobox
160
+ v-model="selected"
161
+ :options="options"
162
+ read-only
163
+ />
164
+ ```
165
+
166
+ ### Without Search Bar
167
+
168
+ ```vue
169
+ <TelaCombobox
170
+ v-model="selected"
171
+ :options="options"
172
+ :has-searchbar="false"
173
+ />
174
+ ```
175
+
176
+ ### Disable Portal
177
+
178
+ ```vue
179
+ <TelaCombobox
180
+ v-model="selected"
181
+ :options="options"
182
+ disable-portal
183
+ />
184
+ ```
185
+
186
+ ## Props
187
+
188
+ <ArgTypes />
189
+
190
+ ```typescript
191
+ interface ComboboxOption {
192
+ value: string
193
+ label: string
194
+ description?: string
195
+ icon?: string | Component
196
+ externalIconSrc?: string
197
+ maxInputTokens?: number
198
+ maxOutputTokens?: number
199
+ group?: string
200
+ badge?: string
201
+ tabs?: string[]
202
+ to?: string
203
+ isMultiModal?: boolean
204
+ features?: Array<{ text: string }>
205
+ cost?: number
206
+ }
207
+
208
+ type ComboboxProps = {
209
+ modelValue?: string
210
+ placeholder?: string
211
+ inputPlaceholder?: string
212
+ options: ComboboxOption[]
213
+ readOnly?: boolean
214
+ size?: 'xs' | 'sm' | 'md'
215
+ iconWithBackground?: {
216
+ size: 'xs' | 'sm' | 'md'
217
+ backgroundClass: string
218
+ }
219
+ compact?: boolean
220
+ hasGroupingLabels?: boolean
221
+ colorIcon?: string
222
+ disablePortal?: boolean
223
+ labelClass?: string
224
+ triggerClass?: string
225
+ iconClass?: string
226
+ contentClass?: string
227
+ labelItemClass?: string
228
+ labelIconVisible?: boolean
229
+ descriptionClass?: string
230
+ hasSearchbar?: boolean
231
+ }
232
+ ```
233
+
234
+ ## Slots
235
+
236
+ - `tags` - Custom tags/badges for each option (receives `option` as slot prop)
237
+
238
+ ## Components
239
+
240
+ The Combobox system consists of these sub-components:
241
+ - `TelaComboboxRoot` - Root container
242
+ - `TelaComboboxAnchor` - Anchor for positioning
243
+ - `TelaComboboxTrigger` - Trigger button
244
+ - `TelaComboboxInput` - Search input field
245
+ - `TelaComboboxList` - Dropdown list container
246
+ - `TelaComboboxEmpty` - Empty state when no results
247
+ - `TelaComboboxGroup` - Group container
248
+ - `TelaComboboxItem` - Individual item
249
+ - `TelaComboboxLabel` - Group label
250
+ - `TelaComboboxItemIndicator` - Selected indicator
251
+
252
+ ## Features
253
+
254
+ - **Searchable**: Filter options by typing
255
+ - **Keyboard Shortcuts**: Cmd+Backspace to clear search
256
+ - **Rich Options**: Icons, descriptions, badges, token limits
257
+ - **Grouping**: Organize options with labels
258
+ - **Tabs**: Filter options by category
259
+ - **Multi-modal Support**: Badge for multi-modal models
260
+ - **Cost Indicator**: Show relative cost with $ symbols
261
+ - **Empty State**: Custom message when no results
262
+ - **Compact Mode**: Dense or spacious layouts
263
+ - **Portal Rendering**: Control dropdown positioning
264
+ - **Icon Customization**: With or without backgrounds
265
+ - **Accessible**: Full keyboard navigation
266
+
267
+ ## Events
268
+
269
+ - `update:modelValue` - Emitted when selection changes with new value
270
+ - `select` - Emitted when an option is selected with the value
271
+
272
+ ## Keyboard Shortcuts
273
+
274
+ - `Cmd/Ctrl + Backspace` - Clear search input
275
+ - `Escape` - Close dropdown
276
+ - `Arrow Up/Down` - Navigate options
277
+ - `Enter` - Select highlighted option
278
+
279
+ ## Accessibility
280
+
281
+ - Built on reka-ui primitives
282
+ - Proper ARIA attributes
283
+ - Keyboard navigation
284
+ - Focus management
285
+ - Screen reader support