@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,182 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as InputStories from './input.stories.ts';
3
+
4
+ <Meta of={InputStories} />
5
+
6
+ # TelaInput
7
+
8
+ A flexible input component that supports both text input and textarea modes. Includes features like labels, error states, icons, clear buttons, and validation feedback. Supports v-model binding for two-way data binding.
9
+
10
+ ## Examples
11
+
12
+ ### With Clear Button
13
+
14
+ <Canvas of={InputStories.ClearButton} />
15
+
16
+ ### With Icon
17
+
18
+ <Canvas of={InputStories.WithIcon} />
19
+
20
+ ### With Error
21
+
22
+ <Canvas of={InputStories.WithError} />
23
+
24
+ ### Disabled
25
+
26
+ <Canvas of={InputStories.Disabled} />
27
+
28
+ ### Textarea
29
+
30
+ <Canvas of={InputStories.Textarea} />
31
+
32
+ ### Basic Usage
33
+
34
+ ```vue
35
+ <script setup>
36
+ import { ref } from 'vue'
37
+
38
+ const value = ref('')
39
+ </script>
40
+
41
+ <template>
42
+ <TelaInput
43
+ v-model="value"
44
+ label="Username"
45
+ placeholder="Enter your username"
46
+ />
47
+ </template>
48
+ ```
49
+
50
+ ### With Clear Button Code
51
+
52
+ ```vue
53
+ <TelaInput
54
+ v-model="value"
55
+ label="Email"
56
+ placeholder="you@example.com"
57
+ show-clear-button
58
+ />
59
+ ```
60
+
61
+ ### With Icon Code
62
+
63
+ ```vue
64
+ <TelaInput
65
+ v-model="searchQuery"
66
+ label="Search"
67
+ icon="i-ph-magnifying-glass"
68
+ placeholder="Search..."
69
+ />
70
+ ```
71
+
72
+ ### With Error Code
73
+
74
+ ```vue
75
+ <TelaInput
76
+ v-model="email"
77
+ label="Email"
78
+ placeholder="you@example.com"
79
+ error="Please enter a valid email address"
80
+ />
81
+ ```
82
+
83
+ ### Disabled Code
84
+
85
+ ```vue
86
+ <TelaInput
87
+ label="Disabled Input"
88
+ placeholder="Cannot edit"
89
+ disabled
90
+ model-value="Read only value"
91
+ />
92
+ ```
93
+
94
+ ```vue
95
+ <TelaInput
96
+ v-model="message"
97
+ type="textarea"
98
+ label="Message"
99
+ placeholder="Enter your message..."
100
+ />
101
+ ```
102
+
103
+ ### Custom Styling
104
+
105
+ ```vue
106
+ <TelaInput
107
+ v-model="value"
108
+ label="Custom Input"
109
+ label-class="text-blue-600 font-bold"
110
+ input-class="border-blue-400"
111
+ input-font-class="font-mono"
112
+ />
113
+ ```
114
+
115
+ ### With Maxlength
116
+
117
+ ```vue
118
+ <TelaInput
119
+ v-model="bio"
120
+ label="Bio"
121
+ placeholder="Tell us about yourself"
122
+ :maxlength="100"
123
+ />
124
+ ```
125
+
126
+ ## Props
127
+
128
+ <ArgTypes />
129
+
130
+ ```typescript
131
+ type InputSize = 'sm' | 'md'
132
+
133
+ type InputProps = {
134
+ id?: string
135
+ modelValue?: string | number
136
+ label?: string
137
+ placeholder?: string
138
+ hideLabel?: boolean
139
+ disabled?: boolean
140
+ size?: InputSize
141
+ error?: string | false
142
+ showClearButton?: boolean
143
+ tabindex?: number
144
+ autofocus?: boolean
145
+ autocomplete?: 'on' | 'off'
146
+ type?: string
147
+ labelClass?: string
148
+ inputFontClass?: string
149
+ inputClass?: string
150
+ icon?: string
151
+ showDescription?: boolean
152
+ maxlength?: number
153
+ }
154
+ ```
155
+
156
+ ## Features
157
+
158
+ - **Flexible Input Types**: Supports text, email, password, number, textarea, and more
159
+ - **Label Support**: Built-in label with hide option for accessibility
160
+ - **Error Handling**: Display validation errors with styling
161
+ - **Icon Integration**: Add icons inside the input field
162
+ - **Clear Button**: Quick clear functionality with show/hide control
163
+ - **Auto-focus**: Automatically focus on mount
164
+ - **Disabled State**: Proper disabled styling and behavior
165
+ - **Character Limit**: Maxlength support with counter
166
+ - **Custom Classes**: Granular control over label, input, and font styling
167
+ - **Two-way Binding**: Full v-model support
168
+ - **Textarea Mode**: Multi-line input support
169
+
170
+ ## Sizes
171
+
172
+ - **sm**: Small input with compact padding
173
+ - **md**: Medium input (default) with comfortable spacing
174
+
175
+ ## Accessibility
176
+
177
+ - Proper label-input association with `for` and `id` attributes
178
+ - Hidden label option maintains accessibility
179
+ - Error messages properly associated with input
180
+ - Keyboard navigation support
181
+ - Focus visible states
182
+ - Disabled state properly conveyed to screen readers
@@ -0,0 +1,153 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3'
2
+
3
+ import { fn } from '@storybook/test'
4
+
5
+ import Input from './tela-input.vue'
6
+
7
+ const meta: Meta<typeof Input> = {
8
+ title: 'Core/Input',
9
+ component: Input,
10
+ parameters: {
11
+ layout: 'centered',
12
+ docs: {
13
+ description: {
14
+ component: 'A flexible input component that supports both text input and textarea modes. Includes features like labels, error states, icons, clear buttons, and validation feedback. Supports v-model binding for two-way data binding.',
15
+ },
16
+ },
17
+ },
18
+ argTypes: {
19
+ id: {
20
+ control: 'text',
21
+ description: 'Unique identifier for the input element. Used for accessibility and form association.',
22
+ },
23
+ modelValue: {
24
+ control: 'text',
25
+ description: 'The input value (v-model). Supports string or number types.',
26
+ },
27
+ label: {
28
+ control: 'text',
29
+ description: 'Label text displayed above or alongside the input field.',
30
+ },
31
+ placeholder: {
32
+ control: 'text',
33
+ description: 'Placeholder text shown when the input is empty.',
34
+ },
35
+ hideLabel: {
36
+ control: 'boolean',
37
+ description: 'Hide the label visually while keeping it accessible for screen readers.',
38
+ },
39
+ disabled: {
40
+ control: 'boolean',
41
+ description: 'Disable the input, preventing user interaction.',
42
+ },
43
+ size: {
44
+ control: 'select',
45
+ options: ['sm', 'md'],
46
+ description: 'Size of the input field. Controls height and padding.',
47
+ },
48
+ error: {
49
+ control: 'text',
50
+ description: 'Error message to display below the input. Set to false to hide error state.',
51
+ },
52
+ showClearButton: {
53
+ control: 'boolean',
54
+ description: 'Show a clear button (X icon) that allows users to quickly clear the input value.',
55
+ },
56
+ tabindex: {
57
+ control: 'number',
58
+ description: 'Tab order of the input element. Use -1 to remove from tab sequence.',
59
+ },
60
+ autofocus: {
61
+ control: 'boolean',
62
+ description: 'Automatically focus the input when the component mounts.',
63
+ },
64
+ autocomplete: {
65
+ control: 'select',
66
+ options: ['off', 'on'],
67
+ description: 'HTML autocomplete attribute value. Controls browser autocomplete behavior.',
68
+ },
69
+ type: {
70
+ control: 'text',
71
+ description: 'Input type. Can be any HTML input type or "textarea" for multiline input.',
72
+ },
73
+ labelClass: {
74
+ control: 'text',
75
+ description: 'Custom CSS classes to apply to the label element.',
76
+ },
77
+ inputFontClass: {
78
+ control: 'text',
79
+ description: 'Custom CSS classes to apply to the input font styling.',
80
+ },
81
+ inputClass: {
82
+ control: 'text',
83
+ description: 'Custom CSS classes to apply to the input element.',
84
+ },
85
+ icon: {
86
+ control: 'text',
87
+ description: 'Icon name or class to display inside the input (typically on the left side).',
88
+ },
89
+ showDescription: {
90
+ control: 'boolean',
91
+ description: 'Show description text below the input field.',
92
+ },
93
+ maxlength: {
94
+ control: 'number',
95
+ description: 'Maximum number of characters allowed in the input.',
96
+ },
97
+ },
98
+ args: {
99
+ 'onUpdate:modelValue': fn(),
100
+ },
101
+ }
102
+
103
+ export default meta
104
+
105
+ type Story = StoryObj<typeof meta>
106
+
107
+ export const TextInput: Story = {
108
+ args: {
109
+ label: 'Label',
110
+ placeholder: 'Enter text',
111
+ autofocus: true,
112
+ modelValue: 'Hello',
113
+ },
114
+ }
115
+
116
+ export const ClearButton: Story = {
117
+ args: {
118
+ ...TextInput.args,
119
+ showClearButton: true,
120
+ },
121
+ }
122
+
123
+ export const WithIcon: Story = {
124
+ args: {
125
+ ...TextInput.args,
126
+ modelValue: 'Search...',
127
+ icon: 'i-ph-magnifying-glass',
128
+ },
129
+ }
130
+
131
+ export const WithError: Story = {
132
+ args: {
133
+ ...TextInput.args,
134
+ modelValue: 'Invalid value',
135
+ error: 'This is an error',
136
+ },
137
+ }
138
+
139
+ export const Disabled: Story = {
140
+ args: {
141
+ ...TextInput.args,
142
+ disabled: true,
143
+ },
144
+ }
145
+
146
+ export const Textarea: Story = {
147
+ args: {
148
+ ...TextInput.args,
149
+ type: 'textarea',
150
+ placeholder: 'Enter text',
151
+ modelValue: 'In the quiet of the night,\nStars above shining bright,\nWhispers of the moonlight,\nGuide my dreams till morning light.',
152
+ },
153
+ }
@@ -0,0 +1,240 @@
1
+ <script setup lang="ts">
2
+ import type { InputTypeHTMLAttribute } from 'vue'
3
+
4
+ const props = defineProps<{
5
+ id?: string
6
+ modelValue: string | number | undefined
7
+ label?: string
8
+ placeholder?: string
9
+ hideLabel?: boolean
10
+ disabled?: boolean
11
+ size?: 'sm' | 'md'
12
+ error?: string | false
13
+ showClearButton?: boolean
14
+ tabindex?: number
15
+ autofocus?: boolean
16
+ autocomplete?: 'off' | 'on'
17
+ type?: InputTypeHTMLAttribute | 'textarea'
18
+ labelClass?: string
19
+ inputFontClass?: string
20
+ inputClass?: string
21
+ icon?: string
22
+ showDescription?: boolean
23
+ maxlength?: number
24
+ }>()
25
+
26
+ const emit = defineEmits<{
27
+ 'focus': []
28
+ 'update:modelValue': [string]
29
+ 'blur': [string]
30
+ }>()
31
+
32
+ const isTextarea = computed(() => props.type === 'textarea')
33
+ const attributes = computed(() => ({
34
+ size: isTextarea.value ? 'md' : undefined,
35
+ type: isTextarea.value ? undefined : props.type,
36
+ modelValue: props.modelValue,
37
+ value: props.modelValue,
38
+ maxlength: props.maxlength,
39
+ }))
40
+
41
+ function handleInput(data: Event | string) {
42
+ if (isTextarea.value)
43
+ emit('update:modelValue', ((data as Event).target as HTMLInputElement).value)
44
+ else
45
+ emit('update:modelValue', ((data as Event).target as HTMLInputElement).value)
46
+ }
47
+
48
+ function handleBlur(data: Event | string) {
49
+ if (isTextarea.value)
50
+ emit('blur', data as string)
51
+ else
52
+ emit('blur', ((data as Event).target as HTMLInputElement).value)
53
+ }
54
+
55
+ function clearContent() {
56
+ emit('update:modelValue', '')
57
+ }
58
+
59
+ const container = ref<HTMLElement>()
60
+ const { textarea: inputRef, input: textareaInput } = useTextareaAutosize({ styleProp: 'minHeight' })
61
+
62
+ function focusInput() {
63
+ if (container.value) {
64
+ setTimeout(() => container.value!.querySelector(isTextarea.value ? 'textarea' : 'input')?.focus(), 100)
65
+ }
66
+ }
67
+
68
+ onMounted(() => {
69
+ if (container.value && container.value.attributes.getNamedItem('data-testid')) {
70
+ const testId = container.value.attributes.getNamedItem('data-testid')?.value as string
71
+
72
+ // Remove the data-testid attribute from the container element
73
+ container.value.removeAttribute('data-testid')
74
+
75
+ // Add the data-testid attribute to the input element
76
+ inputRef.value?.setAttribute('data-testid', testId)
77
+ }
78
+
79
+ if (props.autofocus) {
80
+ focusInput()
81
+ }
82
+ })
83
+
84
+ const trailingContent = useTemplateRef('trailing-content')
85
+ const { width: trailingWidth } = useElementBounding(trailingContent)
86
+
87
+ const errorContainerRef = ref<HTMLElement>()
88
+ const isErrorTruncated = ref(false)
89
+
90
+ function checkTruncation() {
91
+ if (!errorContainerRef.value)
92
+ return
93
+
94
+ const span = errorContainerRef.value.querySelector('span')
95
+ if (span) {
96
+ isErrorTruncated.value = span.scrollWidth > span.clientWidth
97
+ }
98
+ }
99
+
100
+ watch(() => props.error, async () => {
101
+ if (props.error) {
102
+ await nextTick()
103
+ checkTruncation()
104
+ }
105
+ else {
106
+ isErrorTruncated.value = false
107
+ }
108
+ }, { immediate: true })
109
+
110
+ useResizeObserver(errorContainerRef, () => {
111
+ checkTruncation()
112
+ })
113
+
114
+ defineExpose({
115
+ focusInput,
116
+ })
117
+ </script>
118
+
119
+ <template>
120
+ <div ref="container" flex="~ col" relative>
121
+ <div
122
+ relative
123
+ transition
124
+ cursor-text
125
+ overflow-hidden
126
+ px-3 py-8px
127
+ b="0.5px gray-300"
128
+ rounded-10px bg-white
129
+ class="focus-within-b-gray-400 focus-within-ring-2 focus-within-ring-gray-100"
130
+ :class="[
131
+ size === 'sm' && 'py-7px !px-12px',
132
+ disabled && '!bg-gray-50 cursor-not-allowed color-gray-600',
133
+ $attrs.class,
134
+ error && '!border-red-900 !text-red-900 !bg-[#FFDBDB66]',
135
+ props.inputClass,
136
+ ]"
137
+ flex items-center
138
+ @click="$el.querySelector(isTextarea ? 'textarea' : 'input')?.focus()"
139
+ >
140
+ <div v-if="icon" flex mr-6px>
141
+ <TelaIcon :name="icon" size="sm" text="gray-600" />
142
+ </div>
143
+ <div
144
+ flex="~ col" grow align-center h-full
145
+ :style="{
146
+ marginRight: `${trailingWidth - 0}px`,
147
+ }"
148
+ >
149
+ <label
150
+ v-if="label"
151
+ :for="id"
152
+ text="12px #68787A"
153
+ leading-20px
154
+ flex
155
+ align-center
156
+ :class="[disabled && 'cursor-not-allowed', props.labelClass]"
157
+ >
158
+
159
+ <slot name="label-leading" />
160
+ {{ label }}
161
+ </label>
162
+ <component
163
+ :is="isTextarea ? 'textarea' : 'input'"
164
+ :id="id"
165
+ ref="inputRef"
166
+ v-bind="attributes"
167
+ v-model="textareaInput"
168
+ :name="placeholder"
169
+ variant="none"
170
+ :autocomplete="autocomplete"
171
+ :placeholder="placeholder"
172
+ :rows="1"
173
+ autoresize
174
+ w-full
175
+ bg-transparent
176
+ z-0
177
+ h-full
178
+ class="placeholder-gray-300 focus-visible:outline-none! leading-170% tracking-.01em"
179
+ resize-none
180
+ :disabled="disabled"
181
+ :tabindex="tabindex"
182
+ :class="[
183
+ disabled && 'cursor-not-allowed',
184
+ size === 'sm' && 'leading-20px body-14-regular placeholder:body-14-regular',
185
+ props.inputFontClass ? props.inputFontClass : 'text-14px',
186
+ !isTextarea && '!h-1.7em',
187
+ ]"
188
+ @input="handleInput"
189
+ @update:model-value="handleInput"
190
+ @blur="handleBlur"
191
+ @focus="emit('focus')"
192
+ />
193
+ </div>
194
+
195
+ <div v-if="!showClearButton" ref="trailing-content" absolute top-0 right-0 :bg="error ? '' : 'bg-inherit'" h-full flex="~ col" px-8px>
196
+ <div flex-auto />
197
+ <slot name="trailing" />
198
+ <div flex-auto />
199
+ </div>
200
+
201
+ <div v-if="showDescription" class="body-12-regular text-gray-500">
202
+ <slot name="description" />
203
+ </div>
204
+
205
+ <div v-if="showClearButton && modelValue" class="top-60% -translate-y-60%" right-1 absolute>
206
+ <TelaTooltip
207
+ :content="$t('common.clear')"
208
+ >
209
+ <button
210
+ hover:bg="#EBEFF199"
211
+ transition
212
+ p-4px rounded-full
213
+ class="group"
214
+ tabindex="-1"
215
+ @click="clearContent"
216
+ >
217
+ <TelaIcon name="i-ph-x-circle-light" text="#031E22" op-40 group-hover:op-100 transition />
218
+ </button>
219
+ </TelaTooltip>
220
+ </div>
221
+ </div>
222
+ <TelaTooltip
223
+ v-if="error"
224
+ :content="error"
225
+ :disabled="!isErrorTruncated"
226
+ content-class="max-w-300px break-words z-[12000]"
227
+ >
228
+ <div
229
+ ref="errorContainerRef"
230
+ absolute bottom--14px left-0 right-0
231
+ body-10-medium text-red-900 flex items-center gap-3px
232
+ overflow-hidden text-ellipsis whitespace-nowrap
233
+ pr-2
234
+ >
235
+ <TelaIcon name="i-ph-warning-bold" size="sm" text="red-900" text-16px flex-shrink-0 />
236
+ <span class="overflow-hidden text-ellipsis">{{ error }}</span>
237
+ </div>
238
+ </TelaTooltip>
239
+ </div>
240
+ </template>
@@ -0,0 +1,6 @@
1
+ <template>
2
+ <div h-20px w-20px bg="#EFF0F3" rounded-4px relative>
3
+ <div h-10px w-12px bg="#60798F" rounded-4px absolute class="top-50% translate-y--50% left-50% translate-x--50%" />
4
+ <TelaIcon name="i-ph-key-return-fill" class="h-20px! w-20px!" color="#EFF0F3" absolute top-0px left-0px />
5
+ </div>
6
+ </template>