@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,91 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+ import { ref, watch } from 'vue'
3
+
4
+ import SelectMenu from './select-menu.vue'
5
+
6
+ const meta: Meta<typeof SelectMenu> = {
7
+ title: 'Core/SelectMenu',
8
+ component: SelectMenu,
9
+ parameters: {
10
+ layout: 'centered',
11
+ docs: {
12
+ description: {
13
+ component: 'A customizable select/dropdown menu component built on top of reka-ui. Provides a flexible dropdown interface with support for icons, descriptions, tooltips, and custom styling. Supports v-model binding and emits selection, focus, and blur events.',
14
+ },
15
+ },
16
+ },
17
+ argTypes: {
18
+ modelValue: {
19
+ control: 'text',
20
+ description: 'The currently selected value (v-model)',
21
+ },
22
+ options: {
23
+ control: false,
24
+ description: 'Array of options to display in the select menu. Each option should have at least `value` and `label` properties. Supports optional `icon`, `description`, `externalIconSrc`, and `tooltipContent` properties.',
25
+ },
26
+ triggerClass: {
27
+ control: 'text',
28
+ description: 'Custom CSS classes to apply to the trigger element',
29
+ },
30
+ contentClass: {
31
+ control: 'text',
32
+ description: 'Custom CSS classes to apply to the content/dropdown container',
33
+ },
34
+ groupClass: {
35
+ control: 'text',
36
+ description: 'Custom CSS classes to apply to the group container',
37
+ },
38
+ itemClass: {
39
+ control: 'text',
40
+ description: 'Custom CSS classes to apply to each menu item',
41
+ },
42
+ placeholder: {
43
+ control: 'text',
44
+ description: 'Placeholder text to display when no value is selected',
45
+ },
46
+ triggerIconSize: {
47
+ control: 'text',
48
+ description: 'Size of the trigger icon',
49
+ },
50
+ disabled: {
51
+ control: 'boolean',
52
+ description: 'Whether the select menu is disabled',
53
+ },
54
+ iconWithBackground: {
55
+ control: false,
56
+ description: 'Configuration for icons with background styling. Should include `size` ("xs" | "sm" | "md") and `backgroundClass` (CSS class string).',
57
+ },
58
+ enablePortal: {
59
+ control: 'boolean',
60
+ description: 'Whether to render the dropdown content in a portal (useful for z-index issues)',
61
+ },
62
+ },
63
+ }
64
+
65
+ export default meta
66
+
67
+ type Story = StoryObj<typeof meta>
68
+
69
+ export const Default: Story = {
70
+ args: {
71
+ options: [
72
+ { value: 'item-1', label: 'Item 1' },
73
+ { value: 'item-2', label: 'Item 2' },
74
+ { value: 'item-3', label: 'Item 3' },
75
+ { value: 'item-4', label: 'Item 4' },
76
+ ],
77
+ modelValue: 'item-1',
78
+ enablePortal: true,
79
+ },
80
+ render: args => ({
81
+ components: { SelectMenu },
82
+ setup() {
83
+ const modelValue = ref(args.modelValue)
84
+ watch(() => args.modelValue, (newValue) => {
85
+ modelValue.value = newValue
86
+ })
87
+ return { args, modelValue }
88
+ },
89
+ template: '<SelectMenu v-model="modelValue" :options="args.options" :enable-portal="args.enablePortal" />',
90
+ }),
91
+ }
@@ -0,0 +1,165 @@
1
+ <script setup lang="ts">
2
+ import type { ComponentPublicInstance, HTMLAttributes } from 'vue'
3
+ import type { AcceptableValue } from 'reka-ui'
4
+
5
+ import SelectMenuRoot from './select-menu-root.vue'
6
+ import SelectMenuTrigger from './select-menu-trigger.vue'
7
+ import SelectMenuValue from './select-menu-value.vue'
8
+ import SelectMenuContent from './select-menu-content.vue'
9
+ import SelectMenuGroup from './select-menu-group.vue'
10
+ import SelectMenuItem from './select-menu-item.vue'
11
+
12
+ const props = defineProps<{
13
+ modelValue?: string
14
+ options: SelectMenuOptions
15
+ triggerClass?: HTMLAttributes['class']
16
+ contentClass?: HTMLAttributes['class']
17
+ groupClass?: HTMLAttributes['class']
18
+ itemClass?: HTMLAttributes['class']
19
+ placeholder?: string
20
+ triggerIconSize?: string
21
+ disabled?: boolean
22
+ iconWithBackground?: {
23
+ size: 'xs' | 'sm' | 'md'
24
+ backgroundClass: string
25
+ }
26
+ enablePortal?: boolean
27
+ }>()
28
+
29
+ const emit = defineEmits<{
30
+ 'update:modelValue': [value: string]
31
+ 'select': [value: string]
32
+ 'blur': []
33
+ 'focus': []
34
+ }>()
35
+
36
+ const isOpen = ref(false)
37
+ const testId = ref('')
38
+ const container = ref<HTMLElement>()
39
+ const triggerElementRef = ref<HTMLElement | ComponentPublicInstance | null>(null)
40
+
41
+ onMounted(() => {
42
+ if (container.value?.attributes && container.value?.attributes.getNamedItem('data-testid')) {
43
+ testId.value = container.value?.attributes.getNamedItem('data-testid')?.value as string
44
+
45
+ container.value?.removeAttribute('data-testid')
46
+
47
+ const triggerElement = (triggerElementRef.value as any)?.$el || triggerElementRef.value
48
+ if (triggerElement instanceof HTMLElement) {
49
+ triggerElement.setAttribute('data-testid', testId.value)
50
+ }
51
+ }
52
+ })
53
+
54
+ const currentOption = computed(() => {
55
+ if (!props.modelValue && props.placeholder) {
56
+ return { label: props.placeholder, value: '' }
57
+ }
58
+
59
+ return props.options.find(option => option.value === props.modelValue) ?? props.options[0]
60
+ })
61
+
62
+ function handleValueChange(value: AcceptableValue) {
63
+ if (value !== null) {
64
+ const stringValue = String(value)
65
+
66
+ emit('update:modelValue', stringValue)
67
+ emit('select', stringValue)
68
+ }
69
+ }
70
+
71
+ function handleEscKey(event: KeyboardEvent) {
72
+ if (event.key === 'Escape') {
73
+ isOpen.value = false
74
+
75
+ emit('blur')
76
+ event.stopPropagation()
77
+ }
78
+ }
79
+
80
+ function handleOpenChange(open: boolean) {
81
+ isOpen.value = open
82
+
83
+ if (open) {
84
+ emit('focus')
85
+ }
86
+ else {
87
+ emit('blur')
88
+ }
89
+ }
90
+ </script>
91
+
92
+ <template>
93
+ <div
94
+ v-bind="$attrs"
95
+ ref="container"
96
+ @keydown.esc.stop="handleEscKey($event)"
97
+ >
98
+ <SelectMenuRoot :model-value="modelValue" :open="isOpen" :disabled="disabled" @update:model-value="handleValueChange" @update:open="handleOpenChange">
99
+ <slot
100
+ v-bind="{ currentOption }"
101
+ name="trigger"
102
+ >
103
+ <SelectMenuTrigger
104
+ ref="triggerElementRef"
105
+ :class="cn('w-[180px]', triggerClass)"
106
+ :trigger-icon-size="triggerIconSize"
107
+ >
108
+ <div v-if="currentOption" flex items-center w-full gap-8px>
109
+ <div
110
+ v-if="currentOption?.icon && !(currentOption.value === '')"
111
+ rounded-4px flex items-center justify-center
112
+ >
113
+ <Icon v-if="typeof currentOption.icon === 'string'" :name="currentOption.icon" />
114
+ <Component :is="currentOption.icon" v-else />
115
+ </div>
116
+ <div v-if="!currentOption?.icon && currentOption?.externalIconSrc" mr-4px rounded-4px w-16px h-20px flex items-center justify-center>
117
+ <img :src="currentOption.externalIconSrc" alt="" w-16px h-16px>
118
+ </div>
119
+ <span
120
+ text-left flex-auto
121
+ >
122
+ {{ currentOption?.label }}
123
+ </span>
124
+ </div>
125
+ <SelectMenuValue v-else :placeholder="placeholder" />
126
+ </SelectMenuTrigger>
127
+ </slot>
128
+
129
+ <SelectMenuContent :class="cn(contentClass)" :enable-portal="enablePortal">
130
+ <SelectMenuGroup :class="cn(groupClass)">
131
+ <SelectMenuItem v-for="option in options" :key="option.value" v-test="testId ? `${testId}:option:${option.value}` : undefined" :value="option.value" :class="cn(itemClass)" :trigger-icon-size="triggerIconSize">
132
+ <TelaTooltip
133
+ side="right"
134
+ :disabled="!option.tooltipContent"
135
+ :delay-duration="200"
136
+ >
137
+ <template #content>
138
+ <component :is="option.tooltipContent" />
139
+ </template>
140
+ <div
141
+ v-if="option.icon" mr-12px rounded-4px w-40px h-40px flex items-center justify-center
142
+ b="0.5px gray-200"
143
+ text="gray-900"
144
+ bg-white flex-none
145
+ >
146
+ <TelaIcon v-if="iconWithBackground" :name="option.icon" :size="iconWithBackground?.size" :background-class="iconWithBackground?.backgroundClass" />
147
+ <TelaIcon v-else-if="typeof option.icon === 'string'" size="sm" :name="option.icon" />
148
+ <Component :is="option.icon" v-else class="!w-24px !h-24px" />
149
+ </div>
150
+ <div v-if="!option.icon && option?.externalIconSrc" mr-12px rounded-4px w-16px h-36px flex items-center justify-center>
151
+ <img :src="option.externalIconSrc" alt="" w-18px h-18px>
152
+ </div>
153
+ <div flex="~ col" text-start>
154
+ {{ option.label }}
155
+ <span v-if="option.description" text="gray-700" body-12-regular text-start>
156
+ {{ option.description }}
157
+ </span>
158
+ </div>
159
+ </TelaTooltip>
160
+ </SelectMenuItem>
161
+ </SelectMenuGroup>
162
+ </SelectMenuContent>
163
+ </SelectMenuRoot>
164
+ </div>
165
+ </template>
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ icon?: string
4
+ selected?: boolean
5
+ disabled?: boolean
6
+ }>()
7
+
8
+ const emit = defineEmits<{
9
+ click: []
10
+ }>()
11
+
12
+ const containerEl = ref<HTMLElement | null>(null)
13
+ const hovered = useElementHover(containerEl)
14
+ </script>
15
+
16
+ <template>
17
+ <button
18
+ h-32px pl-10px h-34px py-8px flex="~ items-center" rounded-8px
19
+ b="0.5px transparent"
20
+ :class="[
21
+ disabled ? 'text-gray-400! cursor-not-allowed' : 'hover:bg-gray-100',
22
+ ]"
23
+ :text="selected ? 'gray-900' : 'gray-700'"
24
+ :cursor="disabled ? 'not-allowed' : 'pointer'"
25
+ @click="!disabled && emit('click')"
26
+ >
27
+ <div v-if="icon" flex>
28
+ <img v-if="icon.endsWith('.svg')" :src="icon" w-16px h-12px max-w="initial">
29
+ <TelaIcon v-else :name="icon" size="16px" :text="selected ? 'gray-950' : 'gray-600'" />
30
+ </div>
31
+ <span
32
+ body-14-medium
33
+ :class="[
34
+ icon && 'ml-10px',
35
+ ]"
36
+ truncate
37
+ text-ellipsis
38
+ >
39
+ <slot />
40
+ </span>
41
+ <div flex-auto />
42
+
43
+ <div class="pr-1">
44
+ <slot v-if="hovered" name="trailing" />
45
+ </div>
46
+ </button>
47
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import { DialogClose } from 'reka-ui'
3
+ import type { DialogCloseProps } from 'reka-ui'
4
+
5
+ const props = defineProps<DialogCloseProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <DialogClose v-bind="props">
10
+ <slot />
11
+ </DialogClose>
12
+ </template>
@@ -0,0 +1,57 @@
1
+ <script setup lang="ts">
2
+ import { X } from 'lucide-vue-next'
3
+ import {
4
+ DialogClose,
5
+ DialogContent,
6
+
7
+ DialogOverlay,
8
+ DialogPortal,
9
+ useForwardPropsEmits,
10
+ } from 'reka-ui'
11
+ import type { DialogContentEmits, DialogContentProps } from 'reka-ui'
12
+ import { computed } from 'vue'
13
+ import type { HTMLAttributes } from 'vue'
14
+ import { sheetVariants } from './variants'
15
+ import type { SheetVariants } from './variants'
16
+
17
+ interface SheetContentProps extends DialogContentProps {
18
+ class?: HTMLAttributes['class']
19
+ side?: SheetVariants['side']
20
+ }
21
+
22
+ defineOptions({
23
+ inheritAttrs: false,
24
+ })
25
+
26
+ const props = defineProps<SheetContentProps>()
27
+
28
+ const emits = defineEmits<DialogContentEmits>()
29
+
30
+ const delegatedProps = computed(() => {
31
+ const { class: _, side, ...delegated } = props
32
+
33
+ return delegated
34
+ })
35
+
36
+ const forwarded = useForwardPropsEmits(delegatedProps, emits)
37
+ </script>
38
+
39
+ <template>
40
+ <DialogPortal>
41
+ <DialogOverlay
42
+ class="fixed inset-0 z-999 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0"
43
+ />
44
+ <DialogContent
45
+ :class="cn(sheetVariants({ side }), props.class)"
46
+ v-bind="{ ...forwarded, ...$attrs }"
47
+ >
48
+ <slot />
49
+
50
+ <DialogClose
51
+ class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-gray-800"
52
+ >
53
+ <X class="w-4 h-4 text-muted-foreground" />
54
+ </DialogClose>
55
+ </DialogContent>
56
+ </DialogPortal>
57
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { DialogDescription } from 'reka-ui'
3
+ import type { DialogDescriptionProps } from 'reka-ui'
4
+ import { computed } from 'vue'
5
+ import type { HTMLAttributes } from 'vue'
6
+
7
+ const props = defineProps<DialogDescriptionProps & { class?: HTMLAttributes['class'] }>()
8
+
9
+ const delegatedProps = computed(() => {
10
+ const { class: _, ...delegated } = props
11
+
12
+ return delegated
13
+ })
14
+ </script>
15
+
16
+ <template>
17
+ <DialogDescription
18
+ :class="cn('text-sm text-muted-foreground', props.class)"
19
+ v-bind="delegatedProps"
20
+ >
21
+ <slot />
22
+ </DialogDescription>
23
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+
4
+ const props = defineProps<{ class?: HTMLAttributes['class'] }>()
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ :class="
10
+ cn(
11
+ 'flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-x-2',
12
+ props.class,
13
+ )
14
+ "
15
+ >
16
+ <slot />
17
+ </div>
18
+ </template>
@@ -0,0 +1,15 @@
1
+ <script setup lang="ts">
2
+ import type { HTMLAttributes } from 'vue'
3
+
4
+ const props = defineProps<{ class?: HTMLAttributes['class'] }>()
5
+ </script>
6
+
7
+ <template>
8
+ <div
9
+ :class="
10
+ cn('flex flex-col gap-y-2 text-center sm:text-left', props.class)
11
+ "
12
+ >
13
+ <slot />
14
+ </div>
15
+ </template>
@@ -0,0 +1,18 @@
1
+ <script setup lang="ts">
2
+ import { DialogRoot, useForwardPropsEmits } from 'reka-ui'
3
+ import type { DialogRootEmits, DialogRootProps } from 'reka-ui'
4
+
5
+ const props = defineProps<DialogRootProps>()
6
+ const emits = defineEmits<DialogRootEmits>()
7
+
8
+ const forwarded = useForwardPropsEmits(props, emits)
9
+ </script>
10
+
11
+ <template>
12
+ <DialogRoot v-bind="forwarded">
13
+ <template #actions>
14
+ <slot name="actions" />
15
+ </template>
16
+ <slot />
17
+ </DialogRoot>
18
+ </template>
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { DialogTitle } from 'reka-ui'
3
+ import type { DialogTitleProps } from 'reka-ui'
4
+ import { computed } from 'vue'
5
+ import type { HTMLAttributes } from 'vue'
6
+
7
+ const props = defineProps<DialogTitleProps & { class?: HTMLAttributes['class'] }>()
8
+
9
+ const delegatedProps = computed(() => {
10
+ const { class: _, ...delegated } = props
11
+
12
+ return delegated
13
+ })
14
+ </script>
15
+
16
+ <template>
17
+ <DialogTitle
18
+ :class="cn('text-lg font-semibold text-foreground', props.class)"
19
+ v-bind="delegatedProps"
20
+ >
21
+ <slot />
22
+ </DialogTitle>
23
+ </template>
@@ -0,0 +1,12 @@
1
+ <script setup lang="ts">
2
+ import { DialogTrigger } from 'reka-ui'
3
+ import type { DialogTriggerProps } from 'reka-ui'
4
+
5
+ const props = defineProps<DialogTriggerProps>()
6
+ </script>
7
+
8
+ <template>
9
+ <DialogTrigger v-bind="props">
10
+ <slot />
11
+ </DialogTrigger>
12
+ </template>
@@ -0,0 +1,150 @@
1
+ <script setup lang="ts">
2
+ import { computed, useAttrs, watch } from 'vue'
3
+
4
+ import {
5
+ DialogClose,
6
+ DialogContent,
7
+ DialogOverlay,
8
+ DialogPortal,
9
+ DialogRoot,
10
+ VisuallyHidden,
11
+ DialogTitle,
12
+ DialogDescription,
13
+ } from 'radix-vue'
14
+
15
+ defineOptions({
16
+ inheritAttrs: false,
17
+ })
18
+
19
+ const props = defineProps<{
20
+ title?: string,
21
+ modalWidth?: 'md' | 'lg'
22
+ compact?: boolean
23
+ fullscreen?: boolean
24
+ hideDividers?: boolean
25
+ overlayClass?: string
26
+ hideCloseButton?: boolean
27
+ }>()
28
+
29
+ const emit = defineEmits<{
30
+ close: []
31
+ }>()
32
+
33
+ const attrs = useAttrs()
34
+
35
+ const forwardedAttrs = computed(() => {
36
+ const { onPointerDownOutside, ...rest } = attrs as Record<string, unknown>
37
+ return rest
38
+ })
39
+
40
+ const open = defineModel<boolean>()
41
+
42
+ watch(open, (value) => {
43
+ if (!value)
44
+ emit('close')
45
+ })
46
+
47
+ function handlePointerDownOutside(event: any) {
48
+ const target = event?.detail?.originalEvent?.target ?? event?.target
49
+
50
+ if (target instanceof Element && target.closest('[data-sonner-toast]'))
51
+ event.preventDefault()
52
+
53
+ const listener = (attrs as Record<string, unknown>).onPointerDownOutside
54
+ if (Array.isArray(listener)) {
55
+ listener.forEach((handler) => {
56
+ if (typeof handler === 'function')
57
+ handler(event)
58
+ })
59
+ }
60
+ else if (typeof listener === 'function') {
61
+ listener(event)
62
+ }
63
+ }
64
+ </script>
65
+
66
+ <template>
67
+ <DialogRoot v-model:open="open">
68
+ <DialogPortal>
69
+ <DialogOverlay class="DialogOverlay" :class="overlayClass" bg="gray-700/70" z-600>
70
+ <DialogContent
71
+ z-101
72
+ relative w-full flex="~ col"
73
+ class="DialogContent !w-screen !rounded-t-40px p-0px!"
74
+ :class="[
75
+ fullscreen ? 'h-full w-100dvw' : 'h-98dvh !w-98dvw rounded-t-16px',
76
+ ]"
77
+ bg-white
78
+ v-bind="forwardedAttrs"
79
+ @pointer-down-outside="handlePointerDownOutside"
80
+ >
81
+ <VisuallyHidden>
82
+ <DialogTitle />
83
+ <DialogDescription />
84
+ </VisuallyHidden>
85
+ <DialogClose v-if="!hideCloseButton" as-child>
86
+ <TelaIconButton absolute right-32px top-32px icon="i-ph-x" size="md" color="secondary" text-18px outline-none rounded-full border="1 bordercolor/80" />
87
+ </DialogClose>
88
+
89
+ <slot />
90
+
91
+ <div
92
+ v-if="$slots.footer" mt-24px :b-t="!props.hideDividers && '0.5px gray-200'"
93
+ py-24px flex px-32px
94
+ >
95
+ <slot name="footer" />
96
+ </div>
97
+ </DialogContent>
98
+ </DialogOverlay>
99
+ </DialogPortal>
100
+ </DialogRoot>
101
+ </template>
102
+
103
+ <style lang="css" scoped>
104
+ .DialogOverlay {
105
+ position: fixed;
106
+ inset: 0;
107
+ animation: overlayShow 150ms cubic-bezier(0.16, 1, 0.3, 1);
108
+ backdrop-filter: blur(4px);
109
+ }
110
+
111
+ .DialogContent {
112
+ box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
113
+ position: fixed;
114
+ bottom: 0;
115
+ left: 50%;
116
+ transform: translate(-50%, 0%);
117
+ animation: contentShow 250ms cubic-bezier(0.16, 1, 0.3, 1);
118
+ }
119
+
120
+ .DialogContent:focus {
121
+ outline: none;
122
+ }
123
+
124
+ .DialogDescription {
125
+ margin: 10px 0 20px;
126
+ color: var(--mauve-11);
127
+ font-size: 15px;
128
+ line-height: 1.5;
129
+ }
130
+
131
+ @keyframes overlayShow {
132
+ from {
133
+ opacity: 0;
134
+ }
135
+ to {
136
+ opacity: 1;
137
+ }
138
+ }
139
+
140
+ @keyframes contentShow {
141
+ from {
142
+ opacity: 0;
143
+ transform: translate(-50%, 10%) scale(0.96);
144
+ }
145
+ to {
146
+ opacity: 1;
147
+ transform: translate(-50%, 0%) scale(1);
148
+ }
149
+ }
150
+ </style>