@baklavue/ui 1.0.0 → 1.0.2-preview.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/dist/accordion/Accordion.vue.d.ts +51 -0
  2. package/dist/accordion/Accordion.vue.d.ts.map +1 -0
  3. package/dist/accordion/accordion.types.d.ts +97 -0
  4. package/dist/accordion/accordion.types.d.ts.map +1 -0
  5. package/dist/accordion/index.d.ts +3 -0
  6. package/dist/accordion/index.d.ts.map +1 -0
  7. package/dist/alert/Alert.vue.d.ts +49 -0
  8. package/dist/alert/Alert.vue.d.ts.map +1 -0
  9. package/dist/alert/alert.types.d.ts +52 -0
  10. package/dist/alert/alert.types.d.ts.map +1 -0
  11. package/dist/alert/index.d.ts +3 -0
  12. package/dist/alert/index.d.ts.map +1 -0
  13. package/dist/badge/Badge.vue.d.ts +22 -0
  14. package/dist/badge/Badge.vue.d.ts.map +1 -0
  15. package/dist/badge/badge.types.d.ts +7 -0
  16. package/dist/badge/badge.types.d.ts.map +1 -0
  17. package/dist/badge/index.d.ts +3 -0
  18. package/dist/badge/index.d.ts.map +1 -0
  19. package/dist/banner/Banner.vue.d.ts +36 -0
  20. package/dist/banner/Banner.vue.d.ts.map +1 -0
  21. package/dist/banner/banner.types.d.ts +70 -0
  22. package/dist/banner/banner.types.d.ts.map +1 -0
  23. package/dist/banner/index.d.ts +3 -0
  24. package/dist/banner/index.d.ts.map +1 -0
  25. package/dist/button/Button.vue.d.ts +36 -0
  26. package/dist/button/Button.vue.d.ts.map +1 -0
  27. package/dist/button/button.types.d.ts +24 -0
  28. package/dist/button/button.types.d.ts.map +1 -0
  29. package/dist/button/index.d.ts +3 -0
  30. package/dist/button/index.d.ts.map +1 -0
  31. package/dist/checkbox/Checkbox.vue.d.ts +39 -0
  32. package/dist/checkbox/Checkbox.vue.d.ts.map +1 -0
  33. package/dist/checkbox/checkbox.types.d.ts +95 -0
  34. package/dist/checkbox/checkbox.types.d.ts.map +1 -0
  35. package/dist/checkbox/index.d.ts +3 -0
  36. package/dist/checkbox/index.d.ts.map +1 -0
  37. package/dist/chip/Chip.vue.d.ts +29 -0
  38. package/dist/chip/Chip.vue.d.ts.map +1 -0
  39. package/dist/chip/chip.types.d.ts +59 -0
  40. package/dist/chip/chip.types.d.ts.map +1 -0
  41. package/dist/chip/index.d.ts +3 -0
  42. package/dist/chip/index.d.ts.map +1 -0
  43. package/dist/datepicker/Datepicker.vue.d.ts +41 -0
  44. package/dist/datepicker/Datepicker.vue.d.ts.map +1 -0
  45. package/dist/datepicker/datepicker.types.d.ts +38 -0
  46. package/dist/datepicker/datepicker.types.d.ts.map +1 -0
  47. package/dist/datepicker/index.d.ts +3 -0
  48. package/dist/datepicker/index.d.ts.map +1 -0
  49. package/dist/dialog/Dialog.vue.d.ts +44 -0
  50. package/dist/dialog/Dialog.vue.d.ts.map +1 -0
  51. package/dist/dialog/dialog.types.d.ts +18 -0
  52. package/dist/dialog/dialog.types.d.ts.map +1 -0
  53. package/dist/dialog/index.d.ts +3 -0
  54. package/dist/dialog/index.d.ts.map +1 -0
  55. package/dist/drawer/Drawer.vue.d.ts +42 -0
  56. package/dist/drawer/Drawer.vue.d.ts.map +1 -0
  57. package/dist/drawer/drawer.types.d.ts +18 -0
  58. package/dist/drawer/drawer.types.d.ts.map +1 -0
  59. package/dist/drawer/index.d.ts +3 -0
  60. package/dist/drawer/index.d.ts.map +1 -0
  61. package/dist/dropdown/Dropdown.vue.d.ts +59 -0
  62. package/dist/dropdown/Dropdown.vue.d.ts.map +1 -0
  63. package/dist/dropdown/dropdown.types.d.ts +92 -0
  64. package/dist/dropdown/dropdown.types.d.ts.map +1 -0
  65. package/dist/dropdown/index.d.ts +3 -0
  66. package/dist/dropdown/index.d.ts.map +1 -0
  67. package/dist/file-upload/FileUpload.vue.d.ts +44 -0
  68. package/dist/file-upload/FileUpload.vue.d.ts.map +1 -0
  69. package/dist/file-upload/file-upload.types.d.ts +76 -0
  70. package/dist/file-upload/file-upload.types.d.ts.map +1 -0
  71. package/dist/file-upload/index.d.ts +3 -0
  72. package/dist/file-upload/index.d.ts.map +1 -0
  73. package/dist/icon/Icon.vue.d.ts +29 -0
  74. package/dist/icon/Icon.vue.d.ts.map +1 -0
  75. package/dist/icon/icon.types.d.ts +23 -0
  76. package/dist/icon/icon.types.d.ts.map +1 -0
  77. package/dist/icon/index.d.ts +3 -0
  78. package/dist/icon/index.d.ts.map +1 -0
  79. package/dist/image/Image.vue.d.ts +30 -0
  80. package/dist/image/Image.vue.d.ts.map +1 -0
  81. package/dist/image/image.types.d.ts +48 -0
  82. package/dist/image/image.types.d.ts.map +1 -0
  83. package/dist/image/index.d.ts +3 -0
  84. package/dist/image/index.d.ts.map +1 -0
  85. package/dist/index.css +474 -0
  86. package/dist/index.d.ts +42 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +2424 -0
  89. package/dist/index.js.map +1 -0
  90. package/dist/input/Input.vue.d.ts +39 -0
  91. package/dist/input/Input.vue.d.ts.map +1 -0
  92. package/dist/input/index.d.ts +3 -0
  93. package/dist/input/index.d.ts.map +1 -0
  94. package/dist/input/input.types.d.ts +122 -0
  95. package/dist/input/input.types.d.ts.map +1 -0
  96. package/dist/link/Link.vue.d.ts +38 -0
  97. package/dist/link/Link.vue.d.ts.map +1 -0
  98. package/dist/link/index.d.ts +3 -0
  99. package/dist/link/index.d.ts.map +1 -0
  100. package/dist/link/link.types.d.ts +40 -0
  101. package/dist/link/link.types.d.ts.map +1 -0
  102. package/dist/notification/Notification.vue.d.ts +7 -0
  103. package/dist/notification/Notification.vue.d.ts.map +1 -0
  104. package/dist/notification/index.d.ts +3 -0
  105. package/dist/notification/index.d.ts.map +1 -0
  106. package/dist/notification/notification.types.d.ts +25 -0
  107. package/dist/notification/notification.types.d.ts.map +1 -0
  108. package/dist/pagination/Pagination.vue.d.ts +34 -0
  109. package/dist/pagination/Pagination.vue.d.ts.map +1 -0
  110. package/dist/pagination/index.d.ts +3 -0
  111. package/dist/pagination/index.d.ts.map +1 -0
  112. package/dist/pagination/pagination.types.d.ts +54 -0
  113. package/dist/pagination/pagination.types.d.ts.map +1 -0
  114. package/dist/radio/Radio.vue.d.ts +42 -0
  115. package/dist/radio/Radio.vue.d.ts.map +1 -0
  116. package/dist/radio/index.d.ts +3 -0
  117. package/dist/radio/index.d.ts.map +1 -0
  118. package/dist/radio/radio.types.d.ts +84 -0
  119. package/dist/radio/radio.types.d.ts.map +1 -0
  120. package/dist/scroll-to-top/ScrollToTop.vue.d.ts +14 -0
  121. package/dist/scroll-to-top/ScrollToTop.vue.d.ts.map +1 -0
  122. package/dist/scroll-to-top/index.d.ts +3 -0
  123. package/dist/scroll-to-top/index.d.ts.map +1 -0
  124. package/dist/scroll-to-top/scroll-to-top.types.d.ts +33 -0
  125. package/dist/scroll-to-top/scroll-to-top.types.d.ts.map +1 -0
  126. package/dist/select/Select.vue.d.ts +42 -0
  127. package/dist/select/Select.vue.d.ts.map +1 -0
  128. package/dist/select/index.d.ts +3 -0
  129. package/dist/select/index.d.ts.map +1 -0
  130. package/dist/select/select.types.d.ts +52 -0
  131. package/dist/select/select.types.d.ts.map +1 -0
  132. package/dist/skeleton/Skeleton.vue.d.ts +9 -0
  133. package/dist/skeleton/Skeleton.vue.d.ts.map +1 -0
  134. package/dist/skeleton/index.d.ts +3 -0
  135. package/dist/skeleton/index.d.ts.map +1 -0
  136. package/dist/skeleton/skeleton.types.d.ts +30 -0
  137. package/dist/skeleton/skeleton.types.d.ts.map +1 -0
  138. package/dist/spinner/Spinner.vue.d.ts +8 -0
  139. package/dist/spinner/Spinner.vue.d.ts.map +1 -0
  140. package/dist/spinner/index.d.ts +3 -0
  141. package/dist/spinner/index.d.ts.map +1 -0
  142. package/dist/spinner/spinner.types.d.ts +12 -0
  143. package/dist/spinner/spinner.types.d.ts.map +1 -0
  144. package/dist/split-button/SplitButton.vue.d.ts +25 -0
  145. package/dist/split-button/SplitButton.vue.d.ts.map +1 -0
  146. package/dist/split-button/index.d.ts +3 -0
  147. package/dist/split-button/index.d.ts.map +1 -0
  148. package/dist/split-button/split-button.types.d.ts +19 -0
  149. package/dist/split-button/split-button.types.d.ts.map +1 -0
  150. package/dist/stepper/Stepper.vue.d.ts +30 -0
  151. package/dist/stepper/Stepper.vue.d.ts.map +1 -0
  152. package/dist/stepper/index.d.ts +3 -0
  153. package/dist/stepper/index.d.ts.map +1 -0
  154. package/dist/stepper/stepper.types.d.ts +29 -0
  155. package/dist/stepper/stepper.types.d.ts.map +1 -0
  156. package/dist/switch/Switch.vue.d.ts +32 -0
  157. package/dist/switch/Switch.vue.d.ts.map +1 -0
  158. package/dist/switch/index.d.ts +3 -0
  159. package/dist/switch/index.d.ts.map +1 -0
  160. package/dist/switch/switch.types.d.ts +14 -0
  161. package/dist/switch/switch.types.d.ts.map +1 -0
  162. package/dist/tab/Tab.vue.d.ts +31 -0
  163. package/dist/tab/Tab.vue.d.ts.map +1 -0
  164. package/dist/tab/index.d.ts +3 -0
  165. package/dist/tab/index.d.ts.map +1 -0
  166. package/dist/tab/tab.types.d.ts +17 -0
  167. package/dist/tab/tab.types.d.ts.map +1 -0
  168. package/dist/table/Table.vue.d.ts +185 -0
  169. package/dist/table/Table.vue.d.ts.map +1 -0
  170. package/dist/table/index.d.ts +3 -0
  171. package/dist/table/index.d.ts.map +1 -0
  172. package/dist/table/table.types.d.ts +61 -0
  173. package/dist/table/table.types.d.ts.map +1 -0
  174. package/dist/tag/Tag.vue.d.ts +31 -0
  175. package/dist/tag/Tag.vue.d.ts.map +1 -0
  176. package/dist/tag/index.d.ts +3 -0
  177. package/dist/tag/index.d.ts.map +1 -0
  178. package/dist/tag/tag.types.d.ts +22 -0
  179. package/dist/tag/tag.types.d.ts.map +1 -0
  180. package/dist/textarea/Textarea.vue.d.ts +35 -0
  181. package/dist/textarea/Textarea.vue.d.ts.map +1 -0
  182. package/dist/textarea/index.d.ts +3 -0
  183. package/dist/textarea/index.d.ts.map +1 -0
  184. package/dist/textarea/textarea.types.d.ts +37 -0
  185. package/dist/textarea/textarea.types.d.ts.map +1 -0
  186. package/dist/tooltip/Tooltip.vue.d.ts +33 -0
  187. package/dist/tooltip/Tooltip.vue.d.ts.map +1 -0
  188. package/dist/tooltip/index.d.ts +3 -0
  189. package/dist/tooltip/index.d.ts.map +1 -0
  190. package/dist/tooltip/tooltip.types.d.ts +17 -0
  191. package/dist/tooltip/tooltip.types.d.ts.map +1 -0
  192. package/dist/utils/loadBaklavaResources.d.ts +2 -0
  193. package/dist/utils/loadBaklavaResources.d.ts.map +1 -0
  194. package/package.json +18 -2
  195. package/.releaserc.json +0 -14
  196. package/CHANGELOG.md +0 -88
  197. package/env.d.ts +0 -5
  198. package/index.ts +0 -1
  199. package/src/accordion/Accordion.spec.ts +0 -75
  200. package/src/accordion/Accordion.vue +0 -206
  201. package/src/accordion/accordion.types.ts +0 -109
  202. package/src/accordion/index.ts +0 -3
  203. package/src/alert/Alert.spec.ts +0 -38
  204. package/src/alert/Alert.vue +0 -199
  205. package/src/alert/alert.types.ts +0 -58
  206. package/src/alert/index.ts +0 -2
  207. package/src/badge/Badge.spec.ts +0 -28
  208. package/src/badge/Badge.vue +0 -20
  209. package/src/badge/badge.types.ts +0 -7
  210. package/src/badge/index.ts +0 -2
  211. package/src/banner/Banner.spec.ts +0 -111
  212. package/src/banner/Banner.vue +0 -265
  213. package/src/banner/banner.types.ts +0 -86
  214. package/src/banner/index.ts +0 -2
  215. package/src/button/Button.spec.ts +0 -51
  216. package/src/button/Button.vue +0 -45
  217. package/src/button/button.types.ts +0 -30
  218. package/src/button/index.ts +0 -3
  219. package/src/checkbox/Checkbox.spec.ts +0 -216
  220. package/src/checkbox/Checkbox.vue +0 -148
  221. package/src/checkbox/checkbox.types.ts +0 -108
  222. package/src/checkbox/index.ts +0 -2
  223. package/src/chip/Chip.spec.ts +0 -49
  224. package/src/chip/Chip.vue +0 -237
  225. package/src/chip/chip.types.ts +0 -77
  226. package/src/chip/index.ts +0 -2
  227. package/src/datepicker/Datepicker.spec.ts +0 -129
  228. package/src/datepicker/Datepicker.vue +0 -172
  229. package/src/datepicker/datepicker.types.ts +0 -39
  230. package/src/datepicker/index.ts +0 -2
  231. package/src/dialog/Dialog.spec.ts +0 -111
  232. package/src/dialog/Dialog.vue +0 -178
  233. package/src/dialog/dialog.types.ts +0 -17
  234. package/src/dialog/index.ts +0 -2
  235. package/src/drawer/Drawer.spec.ts +0 -102
  236. package/src/drawer/Drawer.vue +0 -162
  237. package/src/drawer/drawer.types.ts +0 -17
  238. package/src/drawer/index.ts +0 -2
  239. package/src/dropdown/Dropdown.spec.ts +0 -207
  240. package/src/dropdown/Dropdown.vue +0 -231
  241. package/src/dropdown/dropdown.types.ts +0 -110
  242. package/src/dropdown/index.ts +0 -2
  243. package/src/file-upload/FileUpload.spec.ts +0 -359
  244. package/src/file-upload/FileUpload.vue +0 -440
  245. package/src/file-upload/file-upload.types.ts +0 -89
  246. package/src/file-upload/index.ts +0 -7
  247. package/src/icon/Icon.spec.ts +0 -40
  248. package/src/icon/Icon.vue +0 -102
  249. package/src/icon/icon.types.ts +0 -25
  250. package/src/icon/index.ts +0 -2
  251. package/src/image/Image.spec.ts +0 -23
  252. package/src/image/Image.vue +0 -144
  253. package/src/image/image.types.ts +0 -57
  254. package/src/image/index.ts +0 -3
  255. package/src/index.ts +0 -43
  256. package/src/input/Input.spec.ts +0 -69
  257. package/src/input/Input.vue +0 -148
  258. package/src/input/index.ts +0 -3
  259. package/src/input/input.types.ts +0 -156
  260. package/src/link/Link.spec.ts +0 -69
  261. package/src/link/Link.vue +0 -133
  262. package/src/link/index.ts +0 -2
  263. package/src/link/link.types.ts +0 -42
  264. package/src/notification/Notification.spec.ts +0 -18
  265. package/src/notification/Notification.vue +0 -57
  266. package/src/notification/index.ts +0 -2
  267. package/src/notification/notification.types.ts +0 -25
  268. package/src/pagination/Pagination.spec.ts +0 -39
  269. package/src/pagination/Pagination.vue +0 -137
  270. package/src/pagination/index.ts +0 -2
  271. package/src/pagination/pagination.types.ts +0 -61
  272. package/src/radio/Radio.spec.ts +0 -149
  273. package/src/radio/Radio.vue +0 -205
  274. package/src/radio/index.ts +0 -2
  275. package/src/radio/radio.types.ts +0 -95
  276. package/src/scroll-to-top/ScrollToTop.spec.ts +0 -119
  277. package/src/scroll-to-top/ScrollToTop.vue +0 -130
  278. package/src/scroll-to-top/index.ts +0 -2
  279. package/src/scroll-to-top/scroll-to-top.types.ts +0 -42
  280. package/src/select/Select.spec.ts +0 -47
  281. package/src/select/Select.vue +0 -147
  282. package/src/select/index.ts +0 -2
  283. package/src/select/select.types.ts +0 -53
  284. package/src/skeleton/Skeleton.spec.ts +0 -28
  285. package/src/skeleton/Skeleton.vue +0 -115
  286. package/src/skeleton/index.ts +0 -2
  287. package/src/skeleton/skeleton.types.ts +0 -33
  288. package/src/spinner/Spinner.spec.ts +0 -28
  289. package/src/spinner/Spinner.vue +0 -49
  290. package/src/spinner/index.ts +0 -2
  291. package/src/spinner/spinner.types.ts +0 -11
  292. package/src/split-button/SplitButton.spec.ts +0 -24
  293. package/src/split-button/SplitButton.vue +0 -73
  294. package/src/split-button/index.ts +0 -2
  295. package/src/split-button/split-button.types.ts +0 -19
  296. package/src/stepper/Stepper.spec.ts +0 -37
  297. package/src/stepper/Stepper.vue +0 -100
  298. package/src/stepper/index.ts +0 -2
  299. package/src/stepper/stepper.types.ts +0 -29
  300. package/src/switch/Switch.spec.ts +0 -30
  301. package/src/switch/Switch.vue +0 -80
  302. package/src/switch/index.ts +0 -2
  303. package/src/switch/switch.types.ts +0 -13
  304. package/src/tab/Tab.spec.ts +0 -87
  305. package/src/tab/Tab.vue +0 -99
  306. package/src/tab/index.ts +0 -2
  307. package/src/tab/tab.types.ts +0 -17
  308. package/src/table/Table.spec.ts +0 -185
  309. package/src/table/Table.vue +0 -264
  310. package/src/table/index.ts +0 -7
  311. package/src/table/table.types.ts +0 -62
  312. package/src/tag/Tag.spec.ts +0 -84
  313. package/src/tag/Tag.vue +0 -83
  314. package/src/tag/index.ts +0 -2
  315. package/src/tag/tag.types.ts +0 -24
  316. package/src/textarea/Textarea.spec.ts +0 -105
  317. package/src/textarea/Textarea.vue +0 -84
  318. package/src/textarea/index.ts +0 -2
  319. package/src/textarea/textarea.types.ts +0 -37
  320. package/src/tooltip/Tooltip.spec.ts +0 -46
  321. package/src/tooltip/Tooltip.vue +0 -81
  322. package/src/tooltip/index.ts +0 -3
  323. package/src/tooltip/tooltip.types.ts +0 -29
  324. package/src/utils/loadBaklavaResources.ts +0 -24
  325. package/tests/setup.ts +0 -352
  326. package/tsconfig.json +0 -29
  327. package/vitest.config.ts +0 -32
@@ -1,231 +0,0 @@
1
- <script setup lang="ts">
2
- /**
3
- * Dropdown Component
4
- *
5
- * A Vue UI kit component for Baklava's `bl-dropdown`, `bl-dropdown-group`, and `bl-dropdown-item`
6
- * web components. Can be used in two modes: slot mode (custom content via slots) or items
7
- * mode (declarative menu items with optional grouping).
8
- *
9
- * @component
10
- * @example
11
- * ```vue
12
- * <!-- Basic usage with label and items -->
13
- * <template>
14
- * <BvDropdown label="Actions" :items="menuItems">
15
- * <template #item="{ item }">
16
- * {{ item.caption }}
17
- * </template>
18
- * </BvDropdown>
19
- * </template>
20
- * ```
21
- *
22
- * @example
23
- * ```vue
24
- * <!-- Items mode with groups -->
25
- * <template>
26
- * <BvDropdown label="Menu" :items="groupedItems">
27
- * <template #item="{ item }">
28
- * {{ item.caption }}
29
- * </template>
30
- * </BvDropdown>
31
- * </template>
32
- * ```
33
- *
34
- * @example
35
- * ```vue
36
- * <!-- Programmatic control via ref -->
37
- * <template>
38
- * <BvButton @click="dropdownRef?.open()">Open</BvButton>
39
- * <BvButton @click="dropdownRef?.close()">Close</BvButton>
40
- * <BvDropdown ref="dropdownRef" label="Menu" :items="items">
41
- * <template #item="{ item }">{{ item.caption }}</template>
42
- * </BvDropdown>
43
- * </template>
44
- * ```
45
- */
46
- import { computed, onMounted, ref, watch } from "vue";
47
- import { loadBaklavaResources } from "../utils/loadBaklavaResources";
48
- import type { DropdownItem, DropdownProps } from "./dropdown.types";
49
-
50
- const props = withDefaults(defineProps<DropdownProps>(), {
51
- open: false,
52
- placement: undefined,
53
- disabled: false,
54
- trigger: undefined,
55
- label: "Menu",
56
- variant: undefined,
57
- kind: undefined,
58
- size: undefined,
59
- icon: undefined,
60
- items: undefined,
61
- });
62
-
63
- const emit = defineEmits<{
64
- /** Emitted when visibility changes. Use for two-way binding. */
65
- "update:open": [open: boolean];
66
- /** Emitted when the dropdown is opened. */
67
- open: [];
68
- /** Emitted when the dropdown is closed. */
69
- close: [];
70
- /** Emitted when a dropdown item is clicked (from bl-dropdown-item-click). */
71
- select: [event: CustomEvent];
72
- }>();
73
-
74
- /** Reference to the underlying bl-dropdown element. */
75
- const dropdownRef = ref<HTMLElement | null>(null);
76
-
77
- /** Determines if the component is in items mode (using items prop). */
78
- const isItemsMode = computed(
79
- () => Array.isArray(props.items) && props.items.length > 0,
80
- );
81
-
82
- /** Groups items by groupCaption for rendering bl-dropdown-group. */
83
- const groupedItems = computed(() => {
84
- if (!props.items) return [];
85
- const groups = new Map<
86
- string | undefined,
87
- { item: DropdownItem; index: number }[]
88
- >();
89
- props.items.forEach((item, index) => {
90
- const key = item.groupCaption ?? undefined;
91
- const list = groups.get(key) ?? [];
92
- list.push({ item, index });
93
- groups.set(key, list);
94
- });
95
- return Array.from(groups.entries()).map(([groupCaption, entries]) => ({
96
- groupCaption: groupCaption || undefined,
97
- entries,
98
- }));
99
- });
100
-
101
- /** Handles bl-dropdown-open event. Syncs state and emits. */
102
- const handleOpen = () => {
103
- emit("update:open", true);
104
- emit("open");
105
- };
106
-
107
- /** Handles bl-dropdown-close event. Syncs state and emits. */
108
- const handleClose = () => {
109
- emit("update:open", false);
110
- emit("close");
111
- };
112
-
113
- /** Handles bl-dropdown-item-click from items. Bubbles as select event. */
114
- const handleItemClick = (event: CustomEvent) => {
115
- emit("select", event);
116
- };
117
-
118
- type BlDropdownElement = {
119
- opened?: boolean;
120
- open: () => void;
121
- close: () => void;
122
- };
123
-
124
- function getBlDropdown(el: HTMLElement | null): BlDropdownElement | null {
125
- return el as unknown as BlDropdownElement | null;
126
- }
127
-
128
- /** Syncs props.open to the bl-dropdown element. */
129
- watch(
130
- () => props.open,
131
- (newValue) => {
132
- const blDropdown = getBlDropdown(dropdownRef.value);
133
- if (blDropdown) {
134
- if (newValue && !blDropdown.opened) {
135
- blDropdown.open();
136
- } else if (!newValue && blDropdown.opened) {
137
- blDropdown.close();
138
- }
139
- }
140
- },
141
- { immediate: true },
142
- );
143
-
144
- onMounted(() => {
145
- loadBaklavaResources();
146
-
147
- const blDropdown = getBlDropdown(dropdownRef.value);
148
- if (blDropdown && blDropdown.opened !== props.open) {
149
- if (props.open) {
150
- blDropdown.open();
151
- } else {
152
- blDropdown.close();
153
- }
154
- }
155
- });
156
-
157
- defineExpose({
158
- /** Opens the dropdown programmatically. */
159
- open: () => {
160
- getBlDropdown(dropdownRef.value)?.open();
161
- },
162
- /** Closes the dropdown programmatically. */
163
- close: () => {
164
- getBlDropdown(dropdownRef.value)?.close();
165
- },
166
- /** Toggles the dropdown open/closed state. */
167
- toggle: () => {
168
- const blDropdown = getBlDropdown(dropdownRef.value);
169
- if (blDropdown) {
170
- if (blDropdown.opened) {
171
- blDropdown.close();
172
- } else {
173
- blDropdown.open();
174
- }
175
- }
176
- },
177
- });
178
- </script>
179
-
180
- <template>
181
- <bl-dropdown
182
- ref="dropdownRef"
183
- v-bind="{
184
- label: props.label,
185
- variant: props.variant,
186
- kind: props.kind,
187
- size: props.size,
188
- icon: props.icon,
189
- disabled: props.disabled === true ? true : undefined,
190
- }"
191
- @bl-dropdown-open="handleOpen"
192
- @bl-dropdown-close="handleClose"
193
- >
194
- <!-- Items mode: render bl-dropdown-group and bl-dropdown-item -->
195
- <template v-if="isItemsMode">
196
- <template v-for="(group, gi) in groupedItems" :key="gi">
197
- <bl-dropdown-group
198
- v-if="group.groupCaption"
199
- :caption="group.groupCaption"
200
- >
201
- <bl-dropdown-item
202
- v-for="(entry, ii) in group.entries"
203
- :key="`${gi}-${ii}`"
204
- :icon="entry.item.icon"
205
- :disabled="entry.item.disabled === true"
206
- @bl-dropdown-item-click="handleItemClick"
207
- >
208
- <slot name="item" :item="entry.item" :index="entry.index">
209
- {{ entry.item.caption }}
210
- </slot>
211
- </bl-dropdown-item>
212
- </bl-dropdown-group>
213
- <template v-else>
214
- <bl-dropdown-item
215
- v-for="(entry, ii) in group.entries"
216
- :key="`${gi}-${ii}`"
217
- :icon="entry.item.icon"
218
- :disabled="entry.item.disabled === true"
219
- @bl-dropdown-item-click="handleItemClick"
220
- >
221
- <slot name="item" :item="entry.item" :index="entry.index">
222
- {{ entry.item.caption }}
223
- </slot>
224
- </bl-dropdown-item>
225
- </template>
226
- </template>
227
- </template>
228
- <!-- Slot mode: default slot for custom content -->
229
- <slot v-else />
230
- </bl-dropdown>
231
- </template>
@@ -1,110 +0,0 @@
1
- import type { BaklavaIcon } from "@trendyol/baklava-icons";
2
- import type {
3
- ButtonKind,
4
- ButtonSize,
5
- ButtonVariant,
6
- } from "@trendyol/baklava/dist/components/button/bl-button";
7
-
8
- /**
9
- * Properties for a dropdown item when used in items mode.
10
- *
11
- * @interface DropdownItem
12
- */
13
- export interface DropdownItem {
14
- /**
15
- * The caption text displayed for the item.
16
- */
17
- caption?: string;
18
-
19
- /**
20
- * Icon name for the item. Shows icon with bl-icon component.
21
- */
22
- icon?: BaklavaIcon;
23
-
24
- /**
25
- * Whether the item is disabled.
26
- *
27
- * @default false
28
- */
29
- disabled?: boolean;
30
-
31
- /**
32
- * Optional group caption. Items with the same groupCaption are rendered
33
- * inside a bl-dropdown-group with that caption.
34
- */
35
- groupCaption?: string;
36
-
37
- /**
38
- * Additional custom data for use in the #item scoped slot.
39
- */
40
- [key: string]: unknown;
41
- }
42
-
43
- /**
44
- * Props for the Dropdown component.
45
- *
46
- * When `items` prop is provided, the component acts in items mode using
47
- * bl-dropdown-group and bl-dropdown-item. Otherwise, it uses slots for
48
- * trigger and content.
49
- *
50
- * @interface DropdownProps
51
- */
52
- export interface DropdownProps {
53
- /**
54
- * Whether the dropdown is open.
55
- *
56
- * @default false
57
- */
58
- open?: boolean;
59
-
60
- /**
61
- * Placement of the dropdown popover relative to the trigger.
62
- * Maps to bl-popover placement.
63
- */
64
- placement?: string;
65
-
66
- /**
67
- * Whether the dropdown trigger is disabled.
68
- *
69
- * @default false
70
- */
71
- disabled?: boolean;
72
-
73
- /**
74
- * Reserved for custom trigger configuration.
75
- */
76
- trigger?: string;
77
-
78
- /**
79
- * Label for the built-in dropdown button.
80
- * Used when in items mode or when not using trigger slot.
81
- */
82
- label?: string;
83
-
84
- /**
85
- * Button variant for the built-in dropdown button.
86
- */
87
- variant?: ButtonVariant;
88
-
89
- /**
90
- * Button kind for the built-in dropdown button.
91
- */
92
- kind?: ButtonKind;
93
-
94
- /**
95
- * Button size for the built-in dropdown button.
96
- */
97
- size?: ButtonSize;
98
-
99
- /**
100
- * Icon name for the built-in dropdown button.
101
- */
102
- icon?: string;
103
-
104
- /**
105
- * Array of dropdown items to render when in items mode.
106
- * Each item will be rendered as a bl-dropdown-item (optionally grouped
107
- * via bl-dropdown-group). Content for each item is provided via the #item slot.
108
- */
109
- items?: DropdownItem[];
110
- }
@@ -1,2 +0,0 @@
1
- export { default as BvDropdown } from "./Dropdown.vue";
2
- export type { DropdownProps, DropdownItem } from "./dropdown.types";
@@ -1,359 +0,0 @@
1
- import { mount } from "@vue/test-utils";
2
- import { describe, expect, it, vi } from "vitest";
3
- import type { FileUploadInvalidEntry } from "./file-upload.types";
4
- import BvFileUpload from "./FileUpload.vue";
5
-
6
- function createFile(
7
- name: string,
8
- size: number,
9
- type = "application/octet-stream",
10
- ): File {
11
- return new File([new Blob(["x".repeat(size)])], name, { type });
12
- }
13
-
14
- function createImageFile(name: string, size: number): File {
15
- return new File([new Blob(["x".repeat(size)])], name, {
16
- type: "image/png",
17
- });
18
- }
19
-
20
- describe("BvFileUpload", () => {
21
- it("renders with label", () => {
22
- const wrapper = mount(BvFileUpload, {
23
- props: { label: "Upload file" },
24
- });
25
- expect(wrapper.text()).toContain("Upload file");
26
- });
27
-
28
- it("renders drop zone", () => {
29
- const wrapper = mount(BvFileUpload);
30
- expect(wrapper.find(".file-upload-zone").exists()).toBe(true);
31
- });
32
-
33
- it("displays help text when provided and no error", () => {
34
- const wrapper = mount(BvFileUpload, {
35
- props: { helpText: "Max 5MB" },
36
- });
37
- expect(wrapper.text()).toContain("Max 5MB");
38
- });
39
-
40
- it("displays invalid text when provided", () => {
41
- const wrapper = mount(BvFileUpload, {
42
- props: { invalidText: "File too large" },
43
- });
44
- expect(wrapper.text()).toContain("File too large");
45
- });
46
-
47
- it("hides help text when invalidText is set", () => {
48
- const wrapper = mount(BvFileUpload, {
49
- props: { helpText: "Help", invalidText: "Error" },
50
- });
51
- expect(wrapper.find(".file-upload-help").exists()).toBe(false);
52
- expect(wrapper.find(".file-upload-invalid").exists()).toBe(true);
53
- });
54
-
55
- it("applies size class to zone", () => {
56
- const small = mount(BvFileUpload, { props: { size: "small" } });
57
- const large = mount(BvFileUpload, { props: { size: "large" } });
58
- expect(small.find(".file-upload-zone").classes()).toContain(
59
- "file-upload-zone--small",
60
- );
61
- expect(large.find(".file-upload-zone").classes()).toContain(
62
- "file-upload-zone--large",
63
- );
64
- });
65
-
66
- it("processes files via input change and emits update:modelValue", async () => {
67
- const wrapper = mount(BvFileUpload);
68
- const file = createFile("doc.pdf", 100);
69
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
70
-
71
- Object.defineProperty(input, "files", {
72
- value: [file],
73
- writable: false,
74
- });
75
- wrapper.find('input[type="file"]').trigger("change");
76
-
77
- await wrapper.vm.$nextTick();
78
- expect(wrapper.emitted("update:modelValue")).toBeDefined();
79
- expect(wrapper.emitted("update:modelValue")![0][0]).toBe(file);
80
- expect(wrapper.emitted("change")).toBeDefined();
81
- expect(wrapper.emitted("change")![0][0]).toEqual([file]);
82
- });
83
-
84
- it("processes multiple files when multiple prop is true", async () => {
85
- const wrapper = mount(BvFileUpload, { props: { multiple: true } });
86
- const file1 = createFile("a.pdf", 100);
87
- const file2 = createFile("b.pdf", 200);
88
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
89
-
90
- Object.defineProperty(input, "files", {
91
- value: [file1, file2],
92
- writable: false,
93
- });
94
- wrapper.find('input[type="file"]').trigger("change");
95
-
96
- await wrapper.vm.$nextTick();
97
- expect(wrapper.emitted("update:modelValue")).toBeDefined();
98
- expect(wrapper.emitted("update:modelValue")![0][0]).toEqual([file1, file2]);
99
- expect(wrapper.emitted("change")![0][0]).toEqual([file1, file2]);
100
- });
101
-
102
- it("appends to existing files when multiple and modelValue has files", async () => {
103
- const existing = createFile("existing.pdf", 50);
104
- const wrapper = mount(BvFileUpload, {
105
- props: { modelValue: existing, multiple: true },
106
- });
107
- const newFile = createFile("new.pdf", 100);
108
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
109
-
110
- Object.defineProperty(input, "files", {
111
- value: [newFile],
112
- writable: false,
113
- });
114
- wrapper.find('input[type="file"]').trigger("change");
115
-
116
- await wrapper.vm.$nextTick();
117
- const emitted = wrapper.emitted("update:modelValue")![0][0] as File[];
118
- expect(Array.isArray(emitted)).toBe(true);
119
- expect(emitted).toHaveLength(2);
120
- expect(emitted[0].name).toBe("existing.pdf");
121
- expect(emitted[1].name).toBe("new.pdf");
122
- });
123
-
124
- it("emits invalid when file exceeds maxSize", async () => {
125
- const wrapper = mount(BvFileUpload, { props: { maxSize: 50 } });
126
- const file = createFile("large.pdf", 1000);
127
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
128
-
129
- Object.defineProperty(input, "files", {
130
- value: [file],
131
- writable: false,
132
- });
133
- wrapper.find('input[type="file"]').trigger("change");
134
-
135
- await wrapper.vm.$nextTick();
136
- expect(wrapper.emitted("invalid")).toBeDefined();
137
- expect(wrapper.emitted("invalid")![0][0]).toHaveLength(1);
138
- expect((wrapper.emitted("invalid")![0][0] as FileUploadInvalidEntry[])[0].reason).toBe("size");
139
- expect(wrapper.emitted("update:modelValue")).toBeUndefined();
140
- });
141
-
142
- it("emits invalid when file is below minSize", async () => {
143
- const wrapper = mount(BvFileUpload, { props: { minSize: 100 } });
144
- const file = createFile("tiny.pdf", 10);
145
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
146
-
147
- Object.defineProperty(input, "files", {
148
- value: [file],
149
- writable: false,
150
- });
151
- wrapper.find('input[type="file"]').trigger("change");
152
-
153
- await wrapper.vm.$nextTick();
154
- expect(wrapper.emitted("invalid")).toBeDefined();
155
- expect((wrapper.emitted("invalid")![0][0] as FileUploadInvalidEntry[])[0].reason).toBe("size");
156
- });
157
-
158
- it("emits invalid when file type does not match accept", async () => {
159
- const wrapper = mount(BvFileUpload, { props: { accept: "image/*" } });
160
- const file = createFile("doc.pdf", 100, "application/pdf");
161
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
162
-
163
- Object.defineProperty(input, "files", {
164
- value: [file],
165
- writable: false,
166
- });
167
- wrapper.find('input[type="file"]').trigger("change");
168
-
169
- await wrapper.vm.$nextTick();
170
- expect(wrapper.emitted("invalid")).toBeDefined();
171
- expect((wrapper.emitted("invalid")![0][0] as FileUploadInvalidEntry[])[0].reason).toBe("type");
172
- });
173
-
174
- it("accepts image when accept is image/*", async () => {
175
- const wrapper = mount(BvFileUpload, { props: { accept: "image/*" } });
176
- const file = createImageFile("img.png", 100);
177
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
178
-
179
- Object.defineProperty(input, "files", {
180
- value: [file],
181
- writable: false,
182
- });
183
- wrapper.find('input[type="file"]').trigger("change");
184
-
185
- await wrapper.vm.$nextTick();
186
- expect(wrapper.emitted("update:modelValue")).toEqual([[file]]);
187
- });
188
-
189
- it("accepts file when accept matches extension", async () => {
190
- const wrapper = mount(BvFileUpload, { props: { accept: ".pdf" } });
191
- const file = createFile("doc.pdf", 100, "application/pdf");
192
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
193
-
194
- Object.defineProperty(input, "files", {
195
- value: [file],
196
- writable: false,
197
- });
198
- wrapper.find('input[type="file"]').trigger("change");
199
-
200
- await wrapper.vm.$nextTick();
201
- expect(wrapper.emitted("update:modelValue")).toEqual([[file]]);
202
- });
203
-
204
- it("emits invalid when exceeding maxFiles in multiple mode", async () => {
205
- const existing = createFile("a.pdf", 50);
206
- const wrapper = mount(BvFileUpload, {
207
- props: { modelValue: [existing], multiple: true, maxFiles: 1 },
208
- });
209
- const newFile = createFile("b.pdf", 50);
210
- const input = wrapper.find('input[type="file"]').element as HTMLInputElement;
211
-
212
- Object.defineProperty(input, "files", {
213
- value: [newFile],
214
- writable: false,
215
- });
216
- wrapper.find('input[type="file"]').trigger("change");
217
-
218
- await wrapper.vm.$nextTick();
219
- expect(wrapper.emitted("invalid")).toBeDefined();
220
- expect((wrapper.emitted("invalid")![0][0] as FileUploadInvalidEntry[])[0].reason).toBe("count");
221
- });
222
-
223
- it("processes files via drop", async () => {
224
- const wrapper = mount(BvFileUpload);
225
- const file = createFile("dropped.pdf", 100);
226
- const dataTransfer = { files: [file] } as unknown as DataTransfer;
227
-
228
- const dropEvent = new DragEvent("drop", {
229
- bubbles: true,
230
- dataTransfer,
231
- });
232
- Object.defineProperty(dropEvent, "dataTransfer", { value: dataTransfer });
233
-
234
- wrapper.find(".file-upload-zone").element.dispatchEvent(dropEvent);
235
- await wrapper.vm.$nextTick();
236
- expect(wrapper.emitted("update:modelValue")).toEqual([[file]]);
237
- });
238
-
239
- it("does not process drop when disabled", async () => {
240
- const wrapper = mount(BvFileUpload, { props: { disabled: true } });
241
- const file = createFile("dropped.pdf", 100);
242
- const dataTransfer = { files: [file] } as unknown as DataTransfer;
243
-
244
- const dropEvent = new DragEvent("drop", {
245
- bubbles: true,
246
- dataTransfer,
247
- });
248
- Object.defineProperty(dropEvent, "dataTransfer", { value: dataTransfer });
249
-
250
- wrapper.find(".file-upload-zone").element.dispatchEvent(dropEvent);
251
- await wrapper.vm.$nextTick();
252
- expect(wrapper.emitted("update:modelValue")).toBeUndefined();
253
- });
254
-
255
- it("sets dragging state on dragover and clears on dragleave", async () => {
256
- const wrapper = mount(BvFileUpload);
257
- const zone = wrapper.find(".file-upload-zone");
258
-
259
- const dragover = new DragEvent("dragover", { bubbles: true });
260
- zone.element.dispatchEvent(dragover);
261
- await wrapper.vm.$nextTick();
262
- expect(zone.classes()).toContain("file-upload-zone--dragging");
263
-
264
- zone.element.dispatchEvent(new DragEvent("dragleave", { bubbles: true }));
265
- await wrapper.vm.$nextTick();
266
- expect(zone.classes()).not.toContain("file-upload-zone--dragging");
267
- });
268
-
269
- it("does not set dragging when disabled", async () => {
270
- const wrapper = mount(BvFileUpload, { props: { disabled: true } });
271
- const zone = wrapper.find(".file-upload-zone");
272
- zone.element.dispatchEvent(
273
- new DragEvent("dragover", { bubbles: true, dataTransfer: {} as unknown as DataTransfer }),
274
- );
275
- await wrapper.vm.$nextTick();
276
- expect(zone.classes()).not.toContain("file-upload-zone--dragging");
277
- });
278
-
279
- it("opens file picker on zone click when not disabled", async () => {
280
- const wrapper = mount(BvFileUpload);
281
- const clickSpy = vi.spyOn(HTMLInputElement.prototype, "click");
282
- wrapper.find(".file-upload-zone").trigger("click");
283
- await wrapper.vm.$nextTick();
284
- expect(clickSpy).toHaveBeenCalled();
285
- clickSpy.mockRestore();
286
- });
287
-
288
- it("does not open file picker when disabled", async () => {
289
- const wrapper = mount(BvFileUpload, { props: { disabled: true } });
290
- const clickSpy = vi.spyOn(HTMLInputElement.prototype, "click");
291
- wrapper.find(".file-upload-zone").trigger("click");
292
- await wrapper.vm.$nextTick();
293
- expect(clickSpy).not.toHaveBeenCalled();
294
- clickSpy.mockRestore();
295
- });
296
-
297
- it("displays file list when modelValue has files", () => {
298
- const file = createFile("doc.pdf", 1024);
299
- const wrapper = mount(BvFileUpload, { props: { modelValue: file } });
300
- expect(wrapper.find(".file-upload-list").exists()).toBe(true);
301
- expect(wrapper.text()).toContain("doc.pdf");
302
- expect(wrapper.text()).toContain("1.0 KB");
303
- });
304
-
305
- it("removes file when tag close is clicked", async () => {
306
- const file = createFile("doc.pdf", 100);
307
- const wrapper = mount(BvFileUpload, { props: { modelValue: file } });
308
- wrapper.find("bl-tag").element.dispatchEvent(
309
- new CustomEvent("bl-tag-click", {
310
- bubbles: true,
311
- detail: { value: null, selected: true },
312
- }),
313
- );
314
- await wrapper.vm.$nextTick();
315
- expect(wrapper.emitted("update:modelValue")).toEqual([[null]]);
316
- expect(wrapper.emitted("change")![0][0]).toEqual([]);
317
- });
318
-
319
- it("removes file at index in multiple mode", async () => {
320
- const file1 = createFile("a.pdf", 50);
321
- const file2 = createFile("b.pdf", 100);
322
- const wrapper = mount(BvFileUpload, {
323
- props: { modelValue: [file1, file2], multiple: true },
324
- });
325
- const tags = wrapper.findAll("bl-tag");
326
- tags[1].element.dispatchEvent(
327
- new CustomEvent("bl-tag-click", {
328
- bubbles: true,
329
- detail: { value: null, selected: true },
330
- }),
331
- );
332
- await wrapper.vm.$nextTick();
333
- expect(wrapper.emitted("update:modelValue")![0][0]).toEqual([file1]);
334
- });
335
-
336
- it("shows preview for image files when showPreview is true", () => {
337
- const file = createImageFile("img.png", 100);
338
- const wrapper = mount(BvFileUpload, {
339
- props: { modelValue: file, showPreview: true },
340
- });
341
- expect(wrapper.find(".file-upload-preview").exists()).toBe(true);
342
- expect(wrapper.find("img.file-upload-thumb").exists()).toBe(true);
343
- });
344
-
345
- it("does not show preview for non-image files", () => {
346
- const file = createFile("doc.pdf", 100);
347
- const wrapper = mount(BvFileUpload, {
348
- props: { modelValue: file, showPreview: true },
349
- });
350
- expect(wrapper.find(".file-upload-preview").exists()).toBe(false);
351
- });
352
-
353
- it("renders hint slot", () => {
354
- const wrapper = mount(BvFileUpload, {
355
- slots: { hint: "Drag and drop or click" },
356
- });
357
- expect(wrapper.text()).toContain("Drag and drop or click");
358
- });
359
- });