@rotki/ui-library 2.12.2 → 2.13.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 (277) hide show
  1. package/dist/components/accordions/accordion/RuiAccordion.vue.d.ts +6 -14
  2. package/dist/components/accordions/accordion/RuiAccordion.vue.js +3 -4
  3. package/dist/components/accordions/accordion/RuiAccordion.vue.js.map +1 -1
  4. package/dist/components/accordions/accordions/RuiAccordions.vue.d.ts +10 -9
  5. package/dist/components/accordions/accordions/RuiAccordions.vue.js +27 -26
  6. package/dist/components/accordions/accordions/RuiAccordions.vue.js.map +1 -1
  7. package/dist/components/alerts/RuiAlert.vue.d.ts +5 -15
  8. package/dist/components/alerts/RuiAlert.vue2.js +8 -16
  9. package/dist/components/alerts/RuiAlert.vue2.js.map +1 -1
  10. package/dist/components/buttons/button/RuiButton.vue.d.ts +5 -7
  11. package/dist/components/buttons/button/RuiButton.vue2.js +19 -20
  12. package/dist/components/buttons/button/RuiButton.vue2.js.map +1 -1
  13. package/dist/components/buttons/button-group/RuiButtonGroup.vue.d.ts +6 -5
  14. package/dist/components/buttons/button-group/RuiButtonGroup.vue2.js +42 -41
  15. package/dist/components/buttons/button-group/RuiButtonGroup.vue2.js.map +1 -1
  16. package/dist/components/calendar/RuiCalendar.vue.d.ts +1 -6
  17. package/dist/components/calendar/RuiCalendar.vue.js +6 -7
  18. package/dist/components/calendar/RuiCalendar.vue.js.map +1 -1
  19. package/dist/components/calendar/RuiCalendarGrid.vue.js +1 -1
  20. package/dist/components/calendar/RuiCalendarGrid.vue2.js +19 -17
  21. package/dist/components/calendar/RuiCalendarGrid.vue2.js.map +1 -1
  22. package/dist/components/calendar/RuiCalendarHeader.vue.js +1 -1
  23. package/dist/components/calendar/RuiCalendarHeader.vue2.js +2 -3
  24. package/dist/components/calendar/RuiCalendarHeader.vue2.js.map +1 -1
  25. package/dist/components/calendar/RuiCalendarMenu.vue.js +1 -1
  26. package/dist/components/calendar/RuiCalendarMenu.vue2.js +47 -39
  27. package/dist/components/calendar/RuiCalendarMenu.vue2.js.map +1 -1
  28. package/dist/components/cards/RuiCard.vue.d.ts +9 -24
  29. package/dist/components/cards/RuiCard.vue2.js +7 -7
  30. package/dist/components/cards/RuiCard.vue2.js.map +1 -1
  31. package/dist/components/cards/RuiCardHeader.vue.d.ts +5 -10
  32. package/dist/components/cards/RuiCardHeader.vue2.js.map +1 -1
  33. package/dist/components/chips/RuiChip.vue.d.ts +7 -21
  34. package/dist/components/chips/RuiChip.vue2.js +16 -21
  35. package/dist/components/chips/RuiChip.vue2.js.map +1 -1
  36. package/dist/components/color-picker/RuiColorBoard.vue.d.ts +1 -1
  37. package/dist/components/color-picker/RuiColorBoard.vue2.js +14 -18
  38. package/dist/components/color-picker/RuiColorBoard.vue2.js.map +1 -1
  39. package/dist/components/color-picker/RuiColorDisplay.vue.js +3 -5
  40. package/dist/components/color-picker/RuiColorDisplay.vue.js.map +1 -1
  41. package/dist/components/color-picker/RuiColorHue.vue2.js +10 -13
  42. package/dist/components/color-picker/RuiColorHue.vue2.js.map +1 -1
  43. package/dist/components/color-picker/RuiColorInput.vue.js +8 -6
  44. package/dist/components/color-picker/RuiColorInput.vue.js.map +1 -1
  45. package/dist/components/color-picker/RuiColorPicker.vue.d.ts +7 -9
  46. package/dist/components/color-picker/RuiColorPicker.vue.js +18 -13
  47. package/dist/components/color-picker/RuiColorPicker.vue.js.map +1 -1
  48. package/dist/components/color-picker/utils.js +22 -5
  49. package/dist/components/color-picker/utils.js.map +1 -1
  50. package/dist/components/date-time-picker/RuiDateTimePicker.vue.d.ts +2 -44
  51. package/dist/components/date-time-picker/RuiDateTimePicker.vue2.js +73 -77
  52. package/dist/components/date-time-picker/RuiDateTimePicker.vue2.js.map +1 -1
  53. package/dist/components/date-time-picker/dayjs-setup.d.ts +1 -0
  54. package/dist/components/date-time-picker/dayjs-setup.js +8 -0
  55. package/dist/components/date-time-picker/dayjs-setup.js.map +1 -0
  56. package/dist/components/date-time-picker/segment-config.d.ts +14 -0
  57. package/dist/components/date-time-picker/segment-config.js +23 -0
  58. package/dist/components/date-time-picker/segment-config.js.map +1 -0
  59. package/dist/components/date-time-picker/segment-utils.d.ts +5 -0
  60. package/dist/components/date-time-picker/segment-utils.js +36 -0
  61. package/dist/components/date-time-picker/segment-utils.js.map +1 -0
  62. package/dist/components/date-time-picker/use-date-time-selection.d.ts +1 -0
  63. package/dist/components/date-time-picker/use-date-time-selection.js +1 -0
  64. package/dist/components/date-time-picker/use-date-time-selection.js.map +1 -1
  65. package/dist/components/date-time-picker/use-keyboard-handler.d.ts +4 -8
  66. package/dist/components/date-time-picker/use-keyboard-handler.js +9 -54
  67. package/dist/components/date-time-picker/use-keyboard-handler.js.map +1 -1
  68. package/dist/components/date-time-picker/utils.d.ts +1 -0
  69. package/dist/components/date-time-picker/utils.js +1 -0
  70. package/dist/components/date-time-picker/utils.js.map +1 -1
  71. package/dist/components/divider/RuiDivider.vue.d.ts +1 -3
  72. package/dist/components/divider/RuiDivider.vue.js.map +1 -1
  73. package/dist/components/forms/auto-complete/RuiAutoComplete.vue.d.ts +9 -1120
  74. package/dist/components/forms/auto-complete/RuiAutoComplete.vue2.js +144 -160
  75. package/dist/components/forms/auto-complete/RuiAutoComplete.vue2.js.map +1 -1
  76. package/dist/components/forms/checkbox/RuiCheckbox.vue.d.ts +15 -24
  77. package/dist/components/forms/checkbox/RuiCheckbox.vue2.js +31 -31
  78. package/dist/components/forms/checkbox/RuiCheckbox.vue2.js.map +1 -1
  79. package/dist/components/forms/radio-button/radio/RuiRadio.vue.d.ts +1 -1
  80. package/dist/components/forms/radio-button/radio/RuiRadio.vue2.js +18 -21
  81. package/dist/components/forms/radio-button/radio/RuiRadio.vue2.js.map +1 -1
  82. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue.d.ts +3 -1
  83. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue2.js +12 -15
  84. package/dist/components/forms/radio-button/radio-group/RuiRadioGroup.vue2.js.map +1 -1
  85. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue.d.ts +5 -11
  86. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue.js +6 -7
  87. package/dist/components/forms/revealable-text-field/RuiRevealableTextField.vue.js.map +1 -1
  88. package/dist/components/forms/select/RuiMenuSelect.vue.d.ts +9 -784
  89. package/dist/components/forms/select/RuiMenuSelect.vue2.js +48 -51
  90. package/dist/components/forms/select/RuiMenuSelect.vue2.js.map +1 -1
  91. package/dist/components/forms/select/RuiSimpleSelect.vue.d.ts +10 -11
  92. package/dist/components/forms/select/RuiSimpleSelect.vue2.js +15 -24
  93. package/dist/components/forms/select/RuiSimpleSelect.vue2.js.map +1 -1
  94. package/dist/components/forms/slider/RuiSlider.vue.d.ts +10 -26
  95. package/dist/components/forms/slider/RuiSlider.vue2.js +41 -46
  96. package/dist/components/forms/slider/RuiSlider.vue2.js.map +1 -1
  97. package/dist/components/forms/switch/RuiSwitch.vue.d.ts +12 -20
  98. package/dist/components/forms/switch/RuiSwitch.vue2.js +21 -20
  99. package/dist/components/forms/switch/RuiSwitch.vue2.js.map +1 -1
  100. package/dist/components/forms/text-area/RuiTextArea.vue.d.ts +5 -30
  101. package/dist/components/forms/text-area/RuiTextArea.vue2.js +43 -79
  102. package/dist/components/forms/text-area/RuiTextArea.vue2.js.map +1 -1
  103. package/dist/components/forms/text-field/RuiTextField.vue.d.ts +7 -27
  104. package/dist/components/forms/text-field/RuiTextField.vue2.js +35 -66
  105. package/dist/components/forms/text-field/RuiTextField.vue2.js.map +1 -1
  106. package/dist/components/helpers/RuiFormTextDetail.vue.d.ts +1 -5
  107. package/dist/components/helpers/RuiFormTextDetail.vue.js +5 -9
  108. package/dist/components/helpers/RuiFormTextDetail.vue.js.map +1 -1
  109. package/dist/components/icons/LazyIcon.vue.d.ts +1 -3
  110. package/dist/components/icons/RuiIcon.vue.d.ts +1 -4
  111. package/dist/components/icons/RuiIcon.vue2.js +8 -8
  112. package/dist/components/icons/RuiIcon.vue2.js.map +1 -1
  113. package/dist/components/index.d.ts +3 -3
  114. package/dist/components/loaders/RuiSkeletonBase.vue.d.ts +1 -3
  115. package/dist/components/loaders/RuiSkeletonBase.vue2.js +1 -1
  116. package/dist/components/loaders/RuiSkeletonBase.vue2.js.map +1 -1
  117. package/dist/components/loaders/RuiSkeletonLoader.vue.d.ts +1 -4
  118. package/dist/components/loaders/RuiSkeletonLoader.vue2.js +1 -1
  119. package/dist/components/loaders/RuiSkeletonLoader.vue2.js.map +1 -1
  120. package/dist/components/logos/RuiLogo.vue.d.ts +1 -7
  121. package/dist/components/logos/RuiLogo.vue.js +11 -13
  122. package/dist/components/logos/RuiLogo.vue.js.map +1 -1
  123. package/dist/components/overlays/badge/RuiBadge.vue.d.ts +5 -20
  124. package/dist/components/overlays/badge/RuiBadge.vue2.js +11 -13
  125. package/dist/components/overlays/badge/RuiBadge.vue2.js.map +1 -1
  126. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue.d.ts +10 -5
  127. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue.js +18 -7
  128. package/dist/components/overlays/bottom-sheet/RuiBottomSheet.vue.js.map +1 -1
  129. package/dist/components/overlays/dialog/RuiDialog.vue.d.ts +21 -27
  130. package/dist/components/overlays/dialog/RuiDialog.vue2.js +80 -63
  131. package/dist/components/overlays/dialog/RuiDialog.vue2.js.map +1 -1
  132. package/dist/components/overlays/menu/RuiMenu.vue.d.ts +24 -35
  133. package/dist/components/overlays/menu/RuiMenu.vue2.js +67 -76
  134. package/dist/components/overlays/menu/RuiMenu.vue2.js.map +1 -1
  135. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue.d.ts +22 -30
  136. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue2.js +71 -47
  137. package/dist/components/overlays/navigation-drawer/RuiNavigationDrawer.vue2.js.map +1 -1
  138. package/dist/components/overlays/notification/RuiNotification.vue.d.ts +12 -12
  139. package/dist/components/overlays/notification/RuiNotification.vue.js +25 -22
  140. package/dist/components/overlays/notification/RuiNotification.vue.js.map +1 -1
  141. package/dist/components/overlays/tooltip/RuiTooltip.vue.d.ts +7 -18
  142. package/dist/components/overlays/tooltip/RuiTooltip.vue2.js +11 -8
  143. package/dist/components/overlays/tooltip/RuiTooltip.vue2.js.map +1 -1
  144. package/dist/components/progress/RuiProgress.vue.d.ts +8 -10
  145. package/dist/components/progress/RuiProgress.vue2.js +18 -24
  146. package/dist/components/progress/RuiProgress.vue2.js.map +1 -1
  147. package/dist/components/steppers/RuiFooterStepper.vue.d.ts +10 -11
  148. package/dist/components/steppers/RuiFooterStepper.vue2.js +21 -21
  149. package/dist/components/steppers/RuiFooterStepper.vue2.js.map +1 -1
  150. package/dist/components/steppers/RuiStepper.vue.d.ts +6 -15
  151. package/dist/components/steppers/RuiStepper.vue2.js +31 -33
  152. package/dist/components/steppers/RuiStepper.vue2.js.map +1 -1
  153. package/dist/components/steppers/RuiStepperCustomIcon.vue.d.ts +1 -3
  154. package/dist/components/steppers/RuiStepperCustomIcon.vue2.js +1 -1
  155. package/dist/components/steppers/RuiStepperCustomIcon.vue2.js.map +1 -1
  156. package/dist/components/steppers/RuiStepperIcon.vue.d.ts +1 -3
  157. package/dist/components/steppers/RuiStepperIcon.vue2.js +1 -1
  158. package/dist/components/steppers/RuiStepperIcon.vue2.js.map +1 -1
  159. package/dist/components/tables/RuiDataTable.vue.d.ts +29 -81
  160. package/dist/components/tables/RuiDataTable.vue2.js +173 -582
  161. package/dist/components/tables/RuiDataTable.vue2.js.map +1 -1
  162. package/dist/components/tables/RuiDataTable.vue3.js +24 -27
  163. package/dist/components/tables/RuiDataTable.vue3.js.map +1 -1
  164. package/dist/components/tables/RuiExpandButton.vue.d.ts +3 -6
  165. package/dist/components/tables/RuiExpandButton.vue2.js +1 -0
  166. package/dist/components/tables/RuiExpandButton.vue2.js.map +1 -1
  167. package/dist/components/tables/RuiTableHead.vue.d.ts +4 -7
  168. package/dist/components/tables/RuiTableHead.vue2.js +19 -19
  169. package/dist/components/tables/RuiTableHead.vue2.js.map +1 -1
  170. package/dist/components/tables/RuiTablePagination.vue.d.ts +10 -10
  171. package/dist/components/tables/RuiTablePagination.vue2.js +17 -16
  172. package/dist/components/tables/RuiTablePagination.vue2.js.map +1 -1
  173. package/dist/components/tabs/tab/RuiTab.vue.d.ts +3 -18
  174. package/dist/components/tabs/tab/RuiTab.vue2.js +80 -51
  175. package/dist/components/tabs/tab/RuiTab.vue2.js.map +1 -1
  176. package/dist/components/tabs/tab-item/RuiTabItem.vue.d.ts +3 -11
  177. package/dist/components/tabs/tab-item/RuiTabItem.vue2.js +1 -1
  178. package/dist/components/tabs/tab-item/RuiTabItem.vue2.js.map +1 -1
  179. package/dist/components/tabs/tab-items/RuiTabItems.vue.d.ts +1 -4
  180. package/dist/components/tabs/tab-items/RuiTabItems.vue2.js +18 -18
  181. package/dist/components/tabs/tab-items/RuiTabItems.vue2.js.map +1 -1
  182. package/dist/components/tabs/tabs/RuiTabs.vue.d.ts +10 -14
  183. package/dist/components/tabs/tabs/RuiTabs.vue2.js +101 -94
  184. package/dist/components/tabs/tabs/RuiTabs.vue2.js.map +1 -1
  185. package/dist/components/time-picker/RuiTimePicker.vue.d.ts +1 -4
  186. package/dist/components/time-picker/RuiTimePicker.vue2.js +68 -35
  187. package/dist/components/time-picker/RuiTimePicker.vue2.js.map +1 -1
  188. package/dist/composables/breakpoint.js +8 -13
  189. package/dist/composables/breakpoint.js.map +1 -1
  190. package/dist/composables/dropdown-menu.d.ts +7 -4
  191. package/dist/composables/dropdown-menu.js +73 -50
  192. package/dist/composables/dropdown-menu.js.map +1 -1
  193. package/dist/composables/forms/auto-complete/focus.d.ts +7 -5
  194. package/dist/composables/forms/auto-complete/focus.js +28 -17
  195. package/dist/composables/forms/auto-complete/focus.js.map +1 -1
  196. package/dist/composables/forms/auto-complete/index.d.ts +0 -9
  197. package/dist/composables/forms/auto-complete/keyboard-navigation.d.ts +8 -3
  198. package/dist/composables/forms/auto-complete/keyboard-navigation.js +11 -5
  199. package/dist/composables/forms/auto-complete/keyboard-navigation.js.map +1 -1
  200. package/dist/composables/forms/auto-complete/search.d.ts +7 -0
  201. package/dist/composables/forms/auto-complete/search.js +10 -8
  202. package/dist/composables/forms/auto-complete/search.js.map +1 -1
  203. package/dist/composables/forms/auto-complete/value.d.ts +4 -0
  204. package/dist/composables/forms/auto-complete/value.js +24 -42
  205. package/dist/composables/forms/auto-complete/value.js.map +1 -1
  206. package/dist/composables/forms/use-label-with-quote.d.ts +2 -0
  207. package/dist/composables/forms/use-label-with-quote.js +14 -0
  208. package/dist/composables/forms/use-label-with-quote.js.map +1 -0
  209. package/dist/composables/forms/use-prepend-append-width.d.ts +6 -0
  210. package/dist/composables/forms/use-prepend-append-width.js +25 -0
  211. package/dist/composables/forms/use-prepend-append-width.js.map +1 -0
  212. package/dist/composables/popper.js +60 -46
  213. package/dist/composables/popper.js.map +1 -1
  214. package/dist/composables/sticky-header.d.ts +7 -5
  215. package/dist/composables/sticky-header.js +51 -41
  216. package/dist/composables/sticky-header.js.map +1 -1
  217. package/dist/composables/tables/data-table/columns.d.ts +25 -0
  218. package/dist/composables/tables/data-table/columns.js +54 -0
  219. package/dist/composables/tables/data-table/columns.js.map +1 -0
  220. package/dist/composables/tables/data-table/expansion.d.ts +17 -0
  221. package/dist/composables/tables/data-table/expansion.js +38 -0
  222. package/dist/composables/tables/data-table/expansion.js.map +1 -0
  223. package/dist/composables/tables/data-table/grouping.d.ts +29 -0
  224. package/dist/composables/tables/data-table/grouping.js +136 -0
  225. package/dist/composables/tables/data-table/grouping.js.map +1 -0
  226. package/dist/composables/tables/data-table/pagination.d.ts +33 -0
  227. package/dist/composables/tables/data-table/pagination.js +119 -0
  228. package/dist/composables/tables/data-table/pagination.js.map +1 -0
  229. package/dist/composables/tables/data-table/selection.d.ts +29 -0
  230. package/dist/composables/tables/data-table/selection.js +164 -0
  231. package/dist/composables/tables/data-table/selection.js.map +1 -0
  232. package/dist/composables/tables/data-table/sort.d.ts +32 -0
  233. package/dist/composables/tables/data-table/sort.js +136 -0
  234. package/dist/composables/tables/data-table/sort.js.map +1 -0
  235. package/dist/composables/tables/data-table/types.d.ts +14 -0
  236. package/dist/composables/tables/data-table/types.js +11 -0
  237. package/dist/composables/tables/data-table/types.js.map +1 -0
  238. package/dist/composables/theme.js +1 -20
  239. package/dist/composables/theme.js.map +1 -1
  240. package/dist/composables/timeout-manager.d.ts +4 -2
  241. package/dist/composables/timeout-manager.js +2 -1
  242. package/dist/composables/timeout-manager.js.map +1 -1
  243. package/dist/icons/icons_1.js +28 -28
  244. package/dist/icons/icons_1.js.map +1 -1
  245. package/dist/icons/icons_2.d.ts +8 -8
  246. package/dist/icons/icons_2.js +52 -52
  247. package/dist/icons/icons_2.js.map +1 -1
  248. package/dist/icons/icons_3.d.ts +18 -18
  249. package/dist/icons/icons_3.js +108 -108
  250. package/dist/icons/icons_3.js.map +1 -1
  251. package/dist/icons/icons_4.d.ts +35 -0
  252. package/dist/icons/icons_4.js +176 -1
  253. package/dist/icons/icons_4.js.map +1 -1
  254. package/dist/icons/index.d.ts +1 -1
  255. package/dist/icons/index.js +1 -1
  256. package/dist/icons/index.js.map +1 -1
  257. package/dist/index.js +43 -15
  258. package/dist/index.js.map +1 -1
  259. package/dist/style.css +189 -162
  260. package/dist/theme/index.js +15 -1
  261. package/dist/theme/index.js.map +1 -1
  262. package/dist/utils/assert.d.ts +1 -1
  263. package/dist/utils/assert.js.map +1 -1
  264. package/dist/utils/form-text-detail.d.ts +9 -8
  265. package/dist/utils/form-text-detail.js +1 -2
  266. package/dist/utils/form-text-detail.js.map +1 -1
  267. package/dist/utils/helpers.d.ts +4 -32
  268. package/dist/utils/helpers.js +8 -9
  269. package/dist/utils/helpers.js.map +1 -1
  270. package/dist/utils/is-equal.d.ts +1 -1
  271. package/dist/utils/is-equal.js +5 -3
  272. package/dist/utils/is-equal.js.map +1 -1
  273. package/dist/web-types.json +359 -359
  274. package/package.json +44 -35
  275. package/dist/utils/generate-id.d.ts +0 -5
  276. package/dist/utils/generate-id.js +0 -21
  277. package/dist/utils/generate-id.js.map +0 -1
@@ -1,20 +1,25 @@
1
- import type { MaybeRef, Ref } from 'vue';
1
+ import type { MaybeRef, Ref, TemplateRef } from 'vue';
2
2
  export interface UseAutoCompleteKeyboardNavigationOptions {
3
+ /** Whether multiple items can be selected. */
3
4
  multiple: MaybeRef<boolean>;
5
+ /** Whether custom (free-text) values are allowed. */
4
6
  customValue: MaybeRef<boolean>;
7
+ /** Whether selected values are displayed as chips. */
8
+ chips: MaybeRef<boolean>;
5
9
  }
6
10
  export interface UseAutoCompleteKeyboardNavigationDeps<TItem> {
7
11
  internalSearch: Ref<string>;
8
12
  value: Ref<TItem[]>;
9
13
  filteredOptions: Ref<TItem[]>;
10
- options: Ref<TItem[]>;
11
14
  isOpen: Ref<boolean>;
12
15
  highlightedIndex: Ref<number>;
13
16
  searchInputFocused: Ref<boolean>;
14
17
  applyHighlighted: () => void;
15
18
  clear: () => void;
19
+ removeValue: (item: TItem) => void;
16
20
  setSearchAsValue: () => void;
17
- activator: Ref<HTMLElement | undefined>;
21
+ getText: (item: TItem) => string | undefined;
22
+ activator: Ref<HTMLElement | undefined> | TemplateRef<HTMLElement>;
18
23
  }
19
24
  export interface UseAutoCompleteKeyboardNavigationReturn {
20
25
  focusedValueIndex: Ref<number>;
@@ -42,8 +42,7 @@ function useAutoCompleteKeyboardNavigation(options, deps) {
42
42
  if (typeof highlightedOption === "string") {
43
43
  hasExactMatch = highlightedOption === internalSearch;
44
44
  } else if (highlightedOption && typeof highlightedOption === "object") {
45
- const label = highlightedOption.label || highlightedOption.value || "";
46
- hasExactMatch = label === internalSearch;
45
+ hasExactMatch = (deps.getText(highlightedOption) ?? "") === internalSearch;
47
46
  }
48
47
  }
49
48
  if (!hasExactMatch) {
@@ -89,10 +88,17 @@ function useAutoCompleteKeyboardNavigation(options, deps) {
89
88
  const total = value.length;
90
89
  const multiple = get(options.multiple);
91
90
  if (!internalSearch && total > 0) {
92
- if (multiple)
93
- set(focusedValueIndex, total - 1);
94
- else
91
+ if (multiple) {
92
+ if (get(options.chips)) {
93
+ set(focusedValueIndex, total - 1);
94
+ } else {
95
+ const lastItem = value[total - 1];
96
+ if (lastItem !== void 0)
97
+ deps.removeValue(lastItem);
98
+ }
99
+ } else {
95
100
  deps.clear();
101
+ }
96
102
  }
97
103
  }
98
104
  watch(deps.value, () => {
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard-navigation.js","sources":["../../../../src/composables/forms/auto-complete/keyboard-navigation.ts"],"sourcesContent":["import type { MaybeRef, Ref } from 'vue';\nimport { get, set } from '@vueuse/shared';\n\nexport interface UseAutoCompleteKeyboardNavigationOptions {\n multiple: MaybeRef<boolean>;\n customValue: MaybeRef<boolean>;\n}\n\nexport interface UseAutoCompleteKeyboardNavigationDeps<TItem> {\n internalSearch: Ref<string>;\n value: Ref<TItem[]>;\n filteredOptions: Ref<TItem[]>;\n options: Ref<TItem[]>;\n isOpen: Ref<boolean>;\n highlightedIndex: Ref<number>;\n searchInputFocused: Ref<boolean>;\n applyHighlighted: () => void;\n clear: () => void;\n setSearchAsValue: () => void;\n activator: Ref<HTMLElement | undefined>;\n}\n\nexport interface UseAutoCompleteKeyboardNavigationReturn {\n focusedValueIndex: Ref<number>;\n moveSelectedValueHighlight: (event: KeyboardEvent, next: boolean) => void;\n onEnter: (event: KeyboardEvent) => void;\n onTab: (event: KeyboardEvent) => void;\n onInputDeletePressed: () => void;\n setValueFocus: (index: number) => void;\n}\n\nexport function useAutoCompleteKeyboardNavigation<TItem>(\n options: UseAutoCompleteKeyboardNavigationOptions,\n deps: UseAutoCompleteKeyboardNavigationDeps<TItem>,\n): UseAutoCompleteKeyboardNavigationReturn {\n const focusedValueIndex = ref<number>(-1);\n const chipElementsCache = ref<Map<number, HTMLElement>>(new Map());\n\n function setValueFocus(index: number): void {\n set(focusedValueIndex, index);\n }\n\n function moveSelectedValueHighlight(event: KeyboardEvent, next: boolean): void {\n const multiple = get(options.multiple);\n const internalSearchValue = get(deps.internalSearch);\n\n if (!multiple || internalSearchValue.length > 0)\n return;\n\n event.preventDefault();\n const total = get(deps.value).length;\n\n let current = get(focusedValueIndex);\n\n if (current === -1) {\n set(focusedValueIndex, next ? 0 : total - 1);\n return;\n }\n\n const move = next ? 1 : -1;\n current += move;\n\n if (current < 0 || current >= total) {\n set(focusedValueIndex, -1);\n set(deps.searchInputFocused, true);\n }\n else {\n set(focusedValueIndex, current);\n }\n }\n\n function onEnter(event: KeyboardEvent): void {\n const filteredOptions = get(deps.filteredOptions);\n const highlightedIndex = get(deps.highlightedIndex);\n const isOpen = get(deps.isOpen);\n const customValue = get(options.customValue);\n const multiple = get(options.multiple);\n const value = get(deps.value);\n const internalSearch = get(deps.internalSearch);\n\n // Check if we should use custom value\n if (customValue && internalSearch && isOpen) {\n // Check if any option exactly matches the search term\n let hasExactMatch = false;\n\n if (highlightedIndex > -1 && highlightedIndex < filteredOptions.length) {\n const highlightedOption = filteredOptions[highlightedIndex];\n if (typeof highlightedOption === 'string') {\n hasExactMatch = highlightedOption === internalSearch;\n }\n else if (highlightedOption && typeof highlightedOption === 'object') {\n const label = (highlightedOption as any).label || (highlightedOption as any).value || '';\n hasExactMatch = label === internalSearch;\n }\n }\n\n // If no exact match with highlighted option, use custom value\n if (!hasExactMatch) {\n deps.setSearchAsValue();\n if (!multiple)\n set(deps.isOpen, false);\n event.preventDefault();\n return;\n }\n }\n\n if (filteredOptions.length > 0 && highlightedIndex > -1 && isOpen) {\n deps.applyHighlighted();\n event.preventDefault();\n }\n else if (filteredOptions.length === 0 && customValue && internalSearch) {\n deps.setSearchAsValue();\n if (!multiple)\n set(deps.isOpen, false);\n event.preventDefault();\n }\n else if (!isOpen && value.length === 0) {\n set(deps.isOpen, true);\n event.preventDefault();\n }\n else {\n const activator = get(deps.activator);\n const form = activator?.closest('form');\n if (form) {\n form.dispatchEvent(new Event('submit'));\n }\n }\n }\n\n function onTab(event: KeyboardEvent): void {\n const isOpen = get(deps.isOpen);\n const filteredOptions = get(deps.filteredOptions);\n const highlightedIndex = get(deps.highlightedIndex);\n const multiple = get(options.multiple);\n\n if (isOpen && filteredOptions.length > 0 && highlightedIndex > -1 && !multiple) {\n deps.applyHighlighted();\n event.preventDefault();\n }\n }\n\n function onInputDeletePressed(): void {\n const internalSearch = get(deps.internalSearch);\n const value = get(deps.value);\n const total = value.length;\n const multiple = get(options.multiple);\n\n if (!internalSearch && total > 0) {\n if (multiple)\n set(focusedValueIndex, total - 1);\n else\n deps.clear();\n }\n }\n\n // Watch value changes to reset focused index and clear cache\n watch(deps.value, () => {\n setValueFocus(-1);\n get(chipElementsCache).clear();\n });\n\n // Watch focused value index to handle chip focus\n watch(focusedValueIndex, async (index) => {\n const multiple = get(options.multiple);\n if (index === -1 || !multiple)\n return;\n\n await nextTick(() => {\n const cache = get(chipElementsCache);\n let activeChip = cache.get(index);\n\n if (!activeChip) {\n const activator = get(deps.activator);\n const element = activator?.querySelector(`[data-index=\"${index}\"]`) as HTMLElement | null;\n if (element) {\n activeChip = element;\n cache.set(index, element);\n }\n }\n\n if (activeChip && 'focus' in activeChip && typeof activeChip.focus === 'function')\n activeChip.focus();\n });\n });\n\n return {\n focusedValueIndex,\n moveSelectedValueHighlight,\n onEnter,\n onInputDeletePressed,\n onTab,\n setValueFocus,\n };\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keyboard-navigation.js","sources":["../../../../src/composables/forms/auto-complete/keyboard-navigation.ts"],"sourcesContent":["import type { MaybeRef, Ref, TemplateRef } from 'vue';\nimport { get, set } from '@vueuse/shared';\n\nexport interface UseAutoCompleteKeyboardNavigationOptions {\n /** Whether multiple items can be selected. */\n multiple: MaybeRef<boolean>;\n /** Whether custom (free-text) values are allowed. */\n customValue: MaybeRef<boolean>;\n /** Whether selected values are displayed as chips. */\n chips: MaybeRef<boolean>;\n}\n\nexport interface UseAutoCompleteKeyboardNavigationDeps<TItem> {\n internalSearch: Ref<string>;\n value: Ref<TItem[]>;\n filteredOptions: Ref<TItem[]>;\n isOpen: Ref<boolean>;\n highlightedIndex: Ref<number>;\n searchInputFocused: Ref<boolean>;\n applyHighlighted: () => void;\n clear: () => void;\n removeValue: (item: TItem) => void;\n setSearchAsValue: () => void;\n getText: (item: TItem) => string | undefined;\n activator: Ref<HTMLElement | undefined> | TemplateRef<HTMLElement>;\n}\n\nexport interface UseAutoCompleteKeyboardNavigationReturn {\n focusedValueIndex: Ref<number>;\n moveSelectedValueHighlight: (event: KeyboardEvent, next: boolean) => void;\n onEnter: (event: KeyboardEvent) => void;\n onTab: (event: KeyboardEvent) => void;\n onInputDeletePressed: () => void;\n setValueFocus: (index: number) => void;\n}\n\nexport function useAutoCompleteKeyboardNavigation<TItem>(\n options: UseAutoCompleteKeyboardNavigationOptions,\n deps: UseAutoCompleteKeyboardNavigationDeps<TItem>,\n): UseAutoCompleteKeyboardNavigationReturn {\n const focusedValueIndex = ref<number>(-1);\n const chipElementsCache = ref<Map<number, HTMLElement>>(new Map());\n\n function setValueFocus(index: number): void {\n set(focusedValueIndex, index);\n }\n\n function moveSelectedValueHighlight(event: KeyboardEvent, next: boolean): void {\n const multiple = get(options.multiple);\n const internalSearchValue = get(deps.internalSearch);\n\n if (!multiple || internalSearchValue.length > 0)\n return;\n\n event.preventDefault();\n const total = get(deps.value).length;\n\n let current = get(focusedValueIndex);\n\n if (current === -1) {\n set(focusedValueIndex, next ? 0 : total - 1);\n return;\n }\n\n const move = next ? 1 : -1;\n current += move;\n\n if (current < 0 || current >= total) {\n set(focusedValueIndex, -1);\n set(deps.searchInputFocused, true);\n }\n else {\n set(focusedValueIndex, current);\n }\n }\n\n function onEnter(event: KeyboardEvent): void {\n const filteredOptions = get(deps.filteredOptions);\n const highlightedIndex = get(deps.highlightedIndex);\n const isOpen = get(deps.isOpen);\n const customValue = get(options.customValue);\n const multiple = get(options.multiple);\n const value = get(deps.value);\n const internalSearch = get(deps.internalSearch);\n\n // Check if we should use custom value\n if (customValue && internalSearch && isOpen) {\n // Check if any option exactly matches the search term\n let hasExactMatch = false;\n\n if (highlightedIndex > -1 && highlightedIndex < filteredOptions.length) {\n const highlightedOption = filteredOptions[highlightedIndex];\n if (typeof highlightedOption === 'string') {\n hasExactMatch = highlightedOption === internalSearch;\n }\n else if (highlightedOption && typeof highlightedOption === 'object') {\n hasExactMatch = (deps.getText(highlightedOption) ?? '') === internalSearch;\n }\n }\n\n // If no exact match with highlighted option, use custom value\n if (!hasExactMatch) {\n deps.setSearchAsValue();\n if (!multiple)\n set(deps.isOpen, false);\n event.preventDefault();\n return;\n }\n }\n\n if (filteredOptions.length > 0 && highlightedIndex > -1 && isOpen) {\n deps.applyHighlighted();\n event.preventDefault();\n }\n else if (filteredOptions.length === 0 && customValue && internalSearch) {\n deps.setSearchAsValue();\n if (!multiple)\n set(deps.isOpen, false);\n event.preventDefault();\n }\n else if (!isOpen && value.length === 0) {\n set(deps.isOpen, true);\n event.preventDefault();\n }\n else {\n const activator = get(deps.activator);\n const form = activator?.closest('form');\n if (form) {\n form.dispatchEvent(new Event('submit'));\n }\n }\n }\n\n function onTab(event: KeyboardEvent): void {\n const isOpen = get(deps.isOpen);\n const filteredOptions = get(deps.filteredOptions);\n const highlightedIndex = get(deps.highlightedIndex);\n const multiple = get(options.multiple);\n\n if (isOpen && filteredOptions.length > 0 && highlightedIndex > -1 && !multiple) {\n deps.applyHighlighted();\n event.preventDefault();\n }\n }\n\n function onInputDeletePressed(): void {\n const internalSearch = get(deps.internalSearch);\n const value = get(deps.value);\n const total = value.length;\n const multiple = get(options.multiple);\n\n if (!internalSearch && total > 0) {\n if (multiple) {\n if (get(options.chips)) {\n set(focusedValueIndex, total - 1);\n }\n else {\n const lastItem = value[total - 1];\n if (lastItem !== undefined)\n deps.removeValue(lastItem);\n }\n }\n else {\n deps.clear();\n }\n }\n }\n\n // Watch value changes to reset focused index and clear cache\n watch(deps.value, () => {\n setValueFocus(-1);\n get(chipElementsCache).clear();\n });\n\n // Watch focused value index to handle chip focus\n watch(focusedValueIndex, async (index) => {\n const multiple = get(options.multiple);\n if (index === -1 || !multiple)\n return;\n\n await nextTick(() => {\n const cache = get(chipElementsCache);\n let activeChip = cache.get(index);\n\n if (!activeChip) {\n const activator = get(deps.activator);\n const element = activator?.querySelector(`[data-index=\"${index}\"]`) as HTMLElement | null;\n if (element) {\n activeChip = element;\n cache.set(index, element);\n }\n }\n\n if (activeChip && 'focus' in activeChip && typeof activeChip.focus === 'function')\n activeChip.focus();\n });\n });\n\n return {\n focusedValueIndex,\n moveSelectedValueHighlight,\n onEnter,\n onInputDeletePressed,\n onTab,\n setValueFocus,\n };\n}\n"],"names":[],"mappings":"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"}
@@ -1,11 +1,18 @@
1
1
  import type { MaybeRef, Ref } from 'vue';
2
2
  export interface UseAutoCompleteSearchOptions<TItem> {
3
+ /** The property used as the unique identifier for each item. */
3
4
  keyAttr?: MaybeRef<keyof TItem | undefined>;
5
+ /** The property used to display text for each item. */
4
6
  textAttr?: MaybeRef<keyof TItem | undefined>;
7
+ /** Whether to disable client-side filtering of options. */
5
8
  noFilter?: MaybeRef<boolean>;
9
+ /** Custom filter function to match items against the search query. */
6
10
  filter?: MaybeRef<((item: TItem, queryText: string) => boolean) | undefined>;
11
+ /** Whether custom (free-text) values are allowed. */
7
12
  customValue?: MaybeRef<boolean>;
13
+ /** Whether to hide the custom value option from the dropdown. */
8
14
  hideCustomValue?: MaybeRef<boolean>;
15
+ /** Whether to return the full item object instead of just the key. */
9
16
  returnObject?: MaybeRef<boolean>;
10
17
  }
11
18
  export interface UseAutoCompleteSearchReturn<TItem> {
@@ -1,16 +1,18 @@
1
1
  import { get, set } from "@vueuse/shared";
2
2
  import { getTextToken } from "../../../utils/helpers.js";
3
- import { ref, computed, watch, onUnmounted } from "vue";
3
+ import { shallowRef, computed, watch, onUnmounted } from "vue";
4
4
  import { refDebounced } from "@vueuse/core";
5
5
  function useAutoCompleteSearch(options, searchModel, opts) {
6
- const internalSearch = ref("");
6
+ const internalSearch = shallowRef("");
7
7
  const debouncedInternalSearch = refDebounced(internalSearch, 50);
8
- const justOpened = ref(false);
8
+ const justOpened = shallowRef(false);
9
+ const MAX_CACHE_SIZE = 500;
9
10
  const tokenCache = /* @__PURE__ */ new Map();
10
11
  const getCachedTextToken = (text) => {
11
- if (tokenCache.has(text)) {
12
+ if (tokenCache.has(text))
12
13
  return tokenCache.get(text);
13
- }
14
+ if (tokenCache.size >= MAX_CACHE_SIZE)
15
+ tokenCache.clear();
14
16
  const token = getTextToken(text);
15
17
  tokenCache.set(text, token);
16
18
  return token;
@@ -28,10 +30,10 @@ function useAutoCompleteSearch(options, searchModel, opts) {
28
30
  const usedFilter = filter || ((item) => {
29
31
  if (!item)
30
32
  return false;
31
- const keywords = [keyAttr ? getCachedTextToken(item[keyAttr]) : item.toString()];
33
+ const keywords = [getCachedTextToken(keyAttr ? String(item[keyAttr]) : item.toString())];
32
34
  if (textAttr && typeof item === "object")
33
- keywords.push(getCachedTextToken(item[textAttr]));
34
- return keywords.some((keyword) => getCachedTextToken(keyword).includes(searchToken));
35
+ keywords.push(getCachedTextToken(String(item[textAttr])));
36
+ return keywords.some((keyword) => keyword.includes(searchToken));
35
37
  });
36
38
  const filtered = optionsValue.filter((item) => usedFilter(item, search));
37
39
  const customValue = get(opts.customValue);
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","sources":["../../../../src/composables/forms/auto-complete/search.ts"],"sourcesContent":["import type { MaybeRef, Ref } from 'vue';\nimport { get, set } from '@vueuse/shared';\nimport { getTextToken } from '@/utils/helpers';\n\nexport interface UseAutoCompleteSearchOptions<TItem> {\n keyAttr?: MaybeRef<keyof TItem | undefined>;\n textAttr?: MaybeRef<keyof TItem | undefined>;\n noFilter?: MaybeRef<boolean>;\n filter?: MaybeRef<((item: TItem, queryText: string) => boolean) | undefined>;\n customValue?: MaybeRef<boolean>;\n hideCustomValue?: MaybeRef<boolean>;\n returnObject?: MaybeRef<boolean>;\n}\n\nexport interface UseAutoCompleteSearchReturn<TItem> {\n internalSearch: Ref<string>;\n debouncedInternalSearch: Readonly<Ref<string>>;\n filteredOptions: Readonly<Ref<TItem[]>>;\n justOpened: Ref<boolean>;\n updateInternalSearch: (value?: string) => void;\n textValueToProperValue: (val: any, returnObject?: boolean) => TItem;\n}\n\nexport function useAutoCompleteSearch<TItem>(\n options: MaybeRef<TItem[]>,\n searchModel: Ref<string>,\n opts: UseAutoCompleteSearchOptions<TItem>,\n): UseAutoCompleteSearchReturn<TItem> {\n const internalSearch = ref<string>('');\n const debouncedInternalSearch = refDebounced(internalSearch, 50);\n const justOpened = ref<boolean>(false);\n\n // Memoize token computation to avoid repeated string processing\n const tokenCache = new Map<string, string>();\n const getCachedTextToken = (text: string): string => {\n if (tokenCache.has(text)) {\n return tokenCache.get(text)!;\n }\n const token = getTextToken(text);\n tokenCache.set(text, token);\n return token;\n };\n\n const filteredOptions = computed<TItem[]>(() => {\n const search = get(debouncedInternalSearch);\n const optionsValue = get(options);\n\n const noFilter = get(opts.noFilter);\n if (noFilter || !search || get(justOpened))\n return optionsValue;\n\n const keyAttr = get(opts.keyAttr);\n const textAttr = get(opts.textAttr);\n const filter = get(opts.filter);\n\n // Cache the search token once\n const searchToken = getCachedTextToken(search);\n\n const usedFilter = filter || ((item) => {\n if (!item)\n return false;\n\n const keywords: string[] = [keyAttr ? getCachedTextToken((item as any)[keyAttr]) : item.toString()];\n\n if (textAttr && typeof item === 'object')\n keywords.push(getCachedTextToken((item as any)[textAttr]));\n\n return keywords.some(keyword => getCachedTextToken(keyword).includes(searchToken));\n });\n\n const filtered = optionsValue.filter(item => usedFilter(item, search));\n\n const customValue = get(opts.customValue);\n const hideCustomValue = get(opts.hideCustomValue);\n if (!customValue || hideCustomValue || !search) {\n return filtered;\n }\n\n // Use a more efficient check for custom value inclusion\n const isCustomValueIncluded = filtered.some((item) => {\n if (!item) {\n return false;\n }\n\n const val = textAttr ? (item as any)[textAttr] : item.toString();\n return val === search;\n });\n\n if (isCustomValueIncluded) {\n return filtered;\n }\n\n return [textValueToProperValue(search, {\n keyAttr,\n returnObject: get(opts.returnObject),\n textAttr,\n }), ...filtered];\n });\n\n function textValueToProperValue(val: any, options: { keyAttr?: keyof TItem; textAttr?: keyof TItem; returnObject?: boolean }): TItem {\n const { keyAttr, returnObject, textAttr } = options;\n if (!keyAttr || returnObject)\n return val;\n\n return {\n [keyAttr]: val,\n ...(\n textAttr\n ? { [textAttr]: val }\n : {}\n ),\n } as TItem;\n }\n\n function updateInternalSearch(value: string = ''): void {\n set(searchModel, value);\n set(internalSearch, value);\n }\n\n watch(searchModel, (search) => {\n set(internalSearch, search);\n }, { immediate: true });\n\n // Clear token cache when component unmounts to prevent memory leaks\n onUnmounted(() => {\n tokenCache.clear();\n });\n\n return {\n debouncedInternalSearch,\n filteredOptions,\n internalSearch,\n justOpened,\n textValueToProperValue: (val: any, returnObjectOverride: boolean = false) => textValueToProperValue(val, {\n keyAttr: get(opts.keyAttr),\n returnObject: returnObjectOverride || get(opts.returnObject),\n textAttr: get(opts.textAttr),\n }),\n updateInternalSearch,\n };\n}\n"],"names":["options"],"mappings":"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"}
1
+ {"version":3,"file":"search.js","sources":["../../../../src/composables/forms/auto-complete/search.ts"],"sourcesContent":["import type { MaybeRef, Ref } from 'vue';\nimport { get, set } from '@vueuse/shared';\nimport { getTextToken } from '@/utils/helpers';\n\nexport interface UseAutoCompleteSearchOptions<TItem> {\n /** The property used as the unique identifier for each item. */\n keyAttr?: MaybeRef<keyof TItem | undefined>;\n /** The property used to display text for each item. */\n textAttr?: MaybeRef<keyof TItem | undefined>;\n /** Whether to disable client-side filtering of options. */\n noFilter?: MaybeRef<boolean>;\n /** Custom filter function to match items against the search query. */\n filter?: MaybeRef<((item: TItem, queryText: string) => boolean) | undefined>;\n /** Whether custom (free-text) values are allowed. */\n customValue?: MaybeRef<boolean>;\n /** Whether to hide the custom value option from the dropdown. */\n hideCustomValue?: MaybeRef<boolean>;\n /** Whether to return the full item object instead of just the key. */\n returnObject?: MaybeRef<boolean>;\n}\n\nexport interface UseAutoCompleteSearchReturn<TItem> {\n internalSearch: Ref<string>;\n debouncedInternalSearch: Readonly<Ref<string>>;\n filteredOptions: Readonly<Ref<TItem[]>>;\n justOpened: Ref<boolean>;\n updateInternalSearch: (value?: string) => void;\n textValueToProperValue: (val: any, returnObject?: boolean) => TItem;\n}\n\nexport function useAutoCompleteSearch<TItem>(\n options: MaybeRef<TItem[]>,\n searchModel: Ref<string>,\n opts: UseAutoCompleteSearchOptions<TItem>,\n): UseAutoCompleteSearchReturn<TItem> {\n const internalSearch = shallowRef<string>('');\n const debouncedInternalSearch = refDebounced(internalSearch, 50);\n const justOpened = shallowRef<boolean>(false);\n\n // Memoize token computation to avoid repeated string processing\n const MAX_CACHE_SIZE = 500;\n const tokenCache = new Map<string, string>();\n const getCachedTextToken = (text: string): string => {\n if (tokenCache.has(text))\n return tokenCache.get(text)!;\n\n if (tokenCache.size >= MAX_CACHE_SIZE)\n tokenCache.clear();\n\n const token = getTextToken(text);\n tokenCache.set(text, token);\n return token;\n };\n\n const filteredOptions = computed<TItem[]>(() => {\n const search = get(debouncedInternalSearch);\n const optionsValue = get(options);\n\n const noFilter = get(opts.noFilter);\n if (noFilter || !search || get(justOpened))\n return optionsValue;\n\n const keyAttr = get(opts.keyAttr);\n const textAttr = get(opts.textAttr);\n const filter = get(opts.filter);\n\n // Cache the search token once\n const searchToken = getCachedTextToken(search);\n\n const usedFilter = filter || ((item) => {\n if (!item)\n return false;\n\n const keywords: string[] = [getCachedTextToken(keyAttr ? String((item as any)[keyAttr]) : item.toString())];\n\n if (textAttr && typeof item === 'object')\n keywords.push(getCachedTextToken(String((item as any)[textAttr])));\n\n return keywords.some(keyword => keyword.includes(searchToken));\n });\n\n const filtered = optionsValue.filter(item => usedFilter(item, search));\n\n const customValue = get(opts.customValue);\n const hideCustomValue = get(opts.hideCustomValue);\n if (!customValue || hideCustomValue || !search) {\n return filtered;\n }\n\n // Use a more efficient check for custom value inclusion\n const isCustomValueIncluded = filtered.some((item) => {\n if (!item) {\n return false;\n }\n\n const val = textAttr ? (item as any)[textAttr] : item.toString();\n return val === search;\n });\n\n if (isCustomValueIncluded) {\n return filtered;\n }\n\n return [textValueToProperValue(search, {\n keyAttr,\n returnObject: get(opts.returnObject),\n textAttr,\n }), ...filtered];\n });\n\n function textValueToProperValue(val: any, options: { keyAttr?: keyof TItem; textAttr?: keyof TItem; returnObject?: boolean }): TItem {\n const { keyAttr, returnObject, textAttr } = options;\n if (!keyAttr || returnObject)\n return val;\n\n return {\n [keyAttr]: val,\n ...(\n textAttr\n ? { [textAttr]: val }\n : {}\n ),\n } as TItem;\n }\n\n function updateInternalSearch(value: string = ''): void {\n set(searchModel, value);\n set(internalSearch, value);\n }\n\n watch(searchModel, (search) => {\n set(internalSearch, search);\n }, { immediate: true });\n\n // Clear token cache when component unmounts to prevent memory leaks\n onUnmounted(() => {\n tokenCache.clear();\n });\n\n return {\n debouncedInternalSearch,\n filteredOptions,\n internalSearch,\n justOpened,\n textValueToProperValue: (val: any, returnObjectOverride: boolean = false) => textValueToProperValue(val, {\n keyAttr: get(opts.keyAttr),\n returnObject: returnObjectOverride || get(opts.returnObject),\n textAttr: get(opts.textAttr),\n }),\n updateInternalSearch,\n };\n}\n"],"names":["options"],"mappings":"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"}
@@ -1,7 +1,10 @@
1
1
  import type { ComputedRef, MaybeRef, Ref } from 'vue';
2
2
  export interface UseAutoCompleteValueOptions<TItem> {
3
+ /** The property used as the unique identifier for each item. */
3
4
  keyAttr?: MaybeRef<keyof TItem | undefined>;
5
+ /** Whether to return the full item object instead of just the key. */
4
6
  returnObject?: MaybeRef<boolean>;
7
+ /** Whether custom (free-text) values are allowed. */
5
8
  customValue?: MaybeRef<boolean>;
6
9
  }
7
10
  export interface UseAutoCompleteValueReturn<TItem> {
@@ -14,6 +17,7 @@ export interface UseAutoCompleteValueDeps<TItem> {
14
17
  textValueToProperValue: (val: any, returnObject?: boolean) => TItem;
15
18
  shouldApplyValueAsSearch: MaybeRef<boolean>;
16
19
  isOpen: MaybeRef<boolean>;
20
+ multiple: MaybeRef<boolean>;
17
21
  updateInternalSearch: (value?: string) => void;
18
22
  }
19
23
  export declare function useAutoCompleteValue<TValue, TItem>(modelValue: Ref<TValue | undefined>, options: MaybeRef<TItem[]>, opts: UseAutoCompleteValueOptions<TItem>, deps: UseAutoCompleteValueDeps<TItem>): UseAutoCompleteValueReturn<TItem>;
@@ -1,8 +1,7 @@
1
1
  import { get, set } from "@vueuse/shared";
2
2
  import { assert } from "../../../utils/assert.js";
3
- import { computed } from "vue";
3
+ import { computed, watch } from "vue";
4
4
  function useAutoCompleteValue(modelValue, options, opts, deps) {
5
- const multiple = computed(() => Array.isArray(get(modelValue)));
6
5
  const optionsMap = computed(() => {
7
6
  const map = /* @__PURE__ */ new Map();
8
7
  const optionsData = get(options);
@@ -12,7 +11,7 @@ function useAutoCompleteValue(modelValue, options, opts, deps) {
12
11
  return map;
13
12
  });
14
13
  function convertModelValueToArray(modelValueData) {
15
- if (!modelValueData)
14
+ if (modelValueData === null || modelValueData === void 0)
16
15
  return [];
17
16
  return Array.isArray(modelValueData) ? modelValueData : [modelValueData];
18
17
  }
@@ -23,7 +22,7 @@ function useAutoCompleteValue(modelValue, options, opts, deps) {
23
22
  for (const val of valueArray) {
24
23
  const identifier = deps.getIdentifier(val);
25
24
  const inOptions = optionsMapData.get(identifier);
26
- if (inOptions) {
25
+ if (inOptions !== void 0) {
27
26
  filtered[index++] = inOptions;
28
27
  } else if (customValue) {
29
28
  filtered[index++] = deps.textValueToProperValue(val, returnObject);
@@ -38,7 +37,7 @@ function useAutoCompleteValue(modelValue, options, opts, deps) {
38
37
  let index = 0;
39
38
  for (const val of valueArray) {
40
39
  const inOptions = optionsMapData.get(val);
41
- if (inOptions) {
40
+ if (inOptions !== void 0) {
42
41
  filtered[index++] = inOptions;
43
42
  } else if (customValue) {
44
43
  filtered[index++] = deps.textValueToProperValue(val, returnObject);
@@ -47,34 +46,19 @@ function useAutoCompleteValue(modelValue, options, opts, deps) {
47
46
  filtered.length = index;
48
47
  return filtered;
49
48
  }
50
- function processReturnObjectValue(modelValueData, optionsMapData, returnObject, customValue, shouldUpdateInternalSearch) {
49
+ function processReturnObjectValue(modelValueData, optionsMapData, returnObject, customValue) {
51
50
  const multipleValue = Array.isArray(modelValueData);
52
51
  const valueArray = convertModelValueToArray(modelValueData);
53
52
  const filtered = filterValuesByOptions(valueArray, optionsMapData, customValue, returnObject);
54
- if (multipleValue || filtered.length === 0) {
55
- if (shouldUpdateInternalSearch)
56
- deps.updateInternalSearch();
53
+ if (multipleValue || filtered.length === 0)
57
54
  return filtered;
58
- }
59
55
  const val = filtered[0];
60
56
  assert(val);
61
- if (shouldUpdateInternalSearch)
62
- deps.updateInternalSearch(deps.getText(val));
63
57
  return [val];
64
58
  }
65
- function processStandardValue(modelValueData, optionsMapData, returnObject, customValue, shouldUpdateInternalSearch) {
59
+ function processStandardValue(modelValueData, optionsMapData, returnObject, customValue) {
66
60
  const valueArray = convertModelValueToArray(modelValueData);
67
- const filtered = filterValuesByIdentifier(valueArray, optionsMapData, customValue, returnObject);
68
- if (shouldUpdateInternalSearch) {
69
- if (filtered.length > 0) {
70
- const firstItem = filtered[0];
71
- assert(firstItem);
72
- deps.updateInternalSearch(deps.getText(firstItem));
73
- } else {
74
- deps.updateInternalSearch();
75
- }
76
- }
77
- return filtered;
61
+ return filterValuesByIdentifier(valueArray, optionsMapData, customValue, returnObject);
78
62
  }
79
63
  function onUpdateModelValue(value2) {
80
64
  set(modelValue, value2);
@@ -83,7 +67,7 @@ function useAutoCompleteValue(modelValue, options, opts, deps) {
83
67
  const keyAttr = get(opts.keyAttr);
84
68
  const returnObject = get(opts.returnObject);
85
69
  const selection = keyAttr && !returnObject ? selected.map((item) => item[keyAttr]) : selected;
86
- if (get(multiple))
70
+ if (get(deps.multiple))
87
71
  return onUpdateModelValue(selection);
88
72
  if (selection.length === 0)
89
73
  return onUpdateModelValue(void 0);
@@ -96,28 +80,26 @@ function useAutoCompleteValue(modelValue, options, opts, deps) {
96
80
  const returnObject = get(opts.returnObject) ?? false;
97
81
  const customValue = get(opts.customValue) ?? false;
98
82
  const optionsMapData = get(optionsMap);
99
- const shouldUpdateInternalSearch = get(deps.shouldApplyValueAsSearch) && !get(deps.isOpen);
100
- if (keyAttr && returnObject) {
101
- return processReturnObjectValue(
102
- modelValueData,
103
- optionsMapData,
104
- returnObject,
105
- customValue,
106
- shouldUpdateInternalSearch
107
- );
108
- }
109
- return processStandardValue(
110
- modelValueData,
111
- optionsMapData,
112
- returnObject,
113
- customValue,
114
- shouldUpdateInternalSearch
115
- );
83
+ if (keyAttr && returnObject)
84
+ return processReturnObjectValue(modelValueData, optionsMapData, returnObject, customValue);
85
+ return processStandardValue(modelValueData, optionsMapData, returnObject, customValue);
116
86
  },
117
87
  set: (selected) => {
118
88
  setSelected(selected);
119
89
  }
120
90
  });
91
+ watch([modelValue, () => get(deps.isOpen)], () => {
92
+ if (get(deps.isOpen) || !get(deps.shouldApplyValueAsSearch))
93
+ return;
94
+ const currentValue = get(value);
95
+ if (get(deps.multiple) || currentValue.length === 0) {
96
+ deps.updateInternalSearch();
97
+ } else {
98
+ const firstItem = currentValue[0];
99
+ assert(firstItem);
100
+ deps.updateInternalSearch(deps.getText(firstItem));
101
+ }
102
+ }, { immediate: true });
121
103
  return {
122
104
  setSelected,
123
105
  value
@@ -1 +1 @@
1
- {"version":3,"file":"value.js","sources":["../../../../src/composables/forms/auto-complete/value.ts"],"sourcesContent":["import type { ComputedRef, MaybeRef, Ref } from 'vue';\nimport { get, set } from '@vueuse/shared';\nimport { assert } from '@/utils/assert';\n\nexport interface UseAutoCompleteValueOptions<TItem> {\n keyAttr?: MaybeRef<keyof TItem | undefined>;\n returnObject?: MaybeRef<boolean>;\n customValue?: MaybeRef<boolean>;\n}\n\nexport interface UseAutoCompleteValueReturn<TItem> {\n value: ComputedRef<TItem[]>;\n setSelected: (selected: TItem[]) => void;\n}\n\nexport interface UseAutoCompleteValueDeps<TItem> {\n getIdentifier: (item: TItem) => any;\n getText: (item: TItem) => string | undefined;\n textValueToProperValue: (val: any, returnObject?: boolean) => TItem;\n shouldApplyValueAsSearch: MaybeRef<boolean>;\n isOpen: MaybeRef<boolean>;\n updateInternalSearch: (value?: string) => void;\n}\n\nexport function useAutoCompleteValue<TValue, TItem>(\n modelValue: Ref<TValue | undefined>,\n options: MaybeRef<TItem[]>,\n opts: UseAutoCompleteValueOptions<TItem>,\n deps: UseAutoCompleteValueDeps<TItem>,\n): UseAutoCompleteValueReturn<TItem> {\n const multiple = computed<boolean>(() => Array.isArray(get(modelValue)));\n\n // Create maps for O(1) lookup performance\n const optionsMap = computed<Map<any, TItem>>(() => {\n const map = new Map<any, TItem>();\n const optionsData = get(options);\n for (const item of optionsData) {\n map.set(deps.getIdentifier(item), item);\n }\n return map;\n });\n\n function convertModelValueToArray(modelValueData: TValue | undefined): any[] {\n if (!modelValueData)\n return [];\n return Array.isArray(modelValueData) ? modelValueData : [modelValueData];\n }\n\n function filterValuesByOptions(\n valueArray: any[],\n optionsMapData: Map<any, TItem>,\n customValue: boolean,\n returnObject: boolean,\n ): TItem[] {\n const filtered: TItem[] = [];\n filtered.length = valueArray.length; // Pre-allocate array size\n let index = 0;\n\n for (const val of valueArray) {\n const identifier = deps.getIdentifier(val);\n const inOptions = optionsMapData.get(identifier);\n\n if (inOptions) {\n filtered[index++] = inOptions;\n }\n else if (customValue) {\n filtered[index++] = deps.textValueToProperValue(val, returnObject);\n }\n }\n\n filtered.length = index; // Trim to actual size\n return filtered;\n }\n\n function filterValuesByIdentifier(\n valueArray: any[],\n optionsMapData: Map<any, TItem>,\n customValue: boolean,\n returnObject: boolean,\n ): TItem[] {\n const filtered: TItem[] = [];\n filtered.length = valueArray.length; // Pre-allocate array size\n let index = 0;\n\n for (const val of valueArray) {\n const inOptions = optionsMapData.get(val);\n\n if (inOptions) {\n filtered[index++] = inOptions;\n }\n else if (customValue) {\n filtered[index++] = deps.textValueToProperValue(val, returnObject);\n }\n }\n\n filtered.length = index; // Trim to actual size\n return filtered;\n }\n\n function processReturnObjectValue(\n modelValueData: TValue | undefined,\n optionsMapData: Map<any, TItem>,\n returnObject: boolean,\n customValue: boolean,\n shouldUpdateInternalSearch: boolean,\n ): TItem[] {\n const multipleValue = Array.isArray(modelValueData);\n const valueArray = convertModelValueToArray(modelValueData);\n const filtered = filterValuesByOptions(valueArray, optionsMapData, customValue, returnObject);\n\n if (multipleValue || filtered.length === 0) {\n if (shouldUpdateInternalSearch)\n deps.updateInternalSearch();\n return filtered;\n }\n\n const val = filtered[0];\n assert(val);\n if (shouldUpdateInternalSearch)\n deps.updateInternalSearch(deps.getText(val));\n return [val];\n }\n\n function processStandardValue(\n modelValueData: TValue | undefined,\n optionsMapData: Map<any, TItem>,\n returnObject: boolean,\n customValue: boolean,\n shouldUpdateInternalSearch: boolean,\n ): TItem[] {\n const valueArray = convertModelValueToArray(modelValueData);\n const filtered = filterValuesByIdentifier(valueArray, optionsMapData, customValue, returnObject);\n\n if (shouldUpdateInternalSearch) {\n if (filtered.length > 0) {\n const firstItem = filtered[0];\n assert(firstItem);\n deps.updateInternalSearch(deps.getText(firstItem));\n }\n else {\n deps.updateInternalSearch();\n }\n }\n\n return filtered;\n }\n\n function onUpdateModelValue(value: TValue | undefined): void {\n set(modelValue, value);\n }\n\n function setSelected(selected: TItem[]): void {\n const keyAttr = get(opts.keyAttr);\n const returnObject = get(opts.returnObject);\n const selection = keyAttr && !returnObject ? selected.map(item => item[keyAttr]) : selected;\n\n if (get(multiple))\n return onUpdateModelValue(selection as TValue);\n\n if (selection.length === 0)\n return onUpdateModelValue(undefined);\n\n return onUpdateModelValue(selection[0] as TValue);\n }\n\n const value = computed<TItem[]>({\n get: () => {\n const modelValueData = get(modelValue);\n const keyAttr = get(opts.keyAttr);\n const returnObject = get(opts.returnObject) ?? false;\n const customValue = get(opts.customValue) ?? false;\n const optionsMapData = get(optionsMap);\n const shouldUpdateInternalSearch = get(deps.shouldApplyValueAsSearch) && !get(deps.isOpen);\n\n if (keyAttr && returnObject) {\n return processReturnObjectValue(\n modelValueData,\n optionsMapData,\n returnObject,\n customValue,\n shouldUpdateInternalSearch,\n );\n }\n\n return processStandardValue(\n modelValueData,\n optionsMapData,\n returnObject,\n customValue,\n shouldUpdateInternalSearch,\n );\n },\n set: (selected: TItem[]): void => {\n setSelected(selected);\n },\n });\n\n return {\n setSelected,\n value,\n };\n}\n"],"names":["value"],"mappings":"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"}
1
+ {"version":3,"file":"value.js","sources":["../../../../src/composables/forms/auto-complete/value.ts"],"sourcesContent":["import type { ComputedRef, MaybeRef, Ref } from 'vue';\nimport { get, set } from '@vueuse/shared';\nimport { assert } from '@/utils/assert';\n\nexport interface UseAutoCompleteValueOptions<TItem> {\n /** The property used as the unique identifier for each item. */\n keyAttr?: MaybeRef<keyof TItem | undefined>;\n /** Whether to return the full item object instead of just the key. */\n returnObject?: MaybeRef<boolean>;\n /** Whether custom (free-text) values are allowed. */\n customValue?: MaybeRef<boolean>;\n}\n\nexport interface UseAutoCompleteValueReturn<TItem> {\n value: ComputedRef<TItem[]>;\n setSelected: (selected: TItem[]) => void;\n}\n\nexport interface UseAutoCompleteValueDeps<TItem> {\n getIdentifier: (item: TItem) => any;\n getText: (item: TItem) => string | undefined;\n textValueToProperValue: (val: any, returnObject?: boolean) => TItem;\n shouldApplyValueAsSearch: MaybeRef<boolean>;\n isOpen: MaybeRef<boolean>;\n multiple: MaybeRef<boolean>;\n updateInternalSearch: (value?: string) => void;\n}\n\nexport function useAutoCompleteValue<TValue, TItem>(\n modelValue: Ref<TValue | undefined>,\n options: MaybeRef<TItem[]>,\n opts: UseAutoCompleteValueOptions<TItem>,\n deps: UseAutoCompleteValueDeps<TItem>,\n): UseAutoCompleteValueReturn<TItem> {\n // Create maps for O(1) lookup performance\n const optionsMap = computed<Map<any, TItem>>(() => {\n const map = new Map<any, TItem>();\n const optionsData = get(options);\n for (const item of optionsData) {\n map.set(deps.getIdentifier(item), item);\n }\n return map;\n });\n\n function convertModelValueToArray(modelValueData: TValue | undefined): any[] {\n if (modelValueData === null || modelValueData === undefined)\n return [];\n return Array.isArray(modelValueData) ? modelValueData : [modelValueData];\n }\n\n function filterValuesByOptions(\n valueArray: any[],\n optionsMapData: Map<any, TItem>,\n customValue: boolean,\n returnObject: boolean,\n ): TItem[] {\n const filtered: TItem[] = [];\n filtered.length = valueArray.length; // Pre-allocate array size\n let index = 0;\n\n for (const val of valueArray) {\n const identifier = deps.getIdentifier(val);\n const inOptions = optionsMapData.get(identifier);\n\n if (inOptions !== undefined) {\n filtered[index++] = inOptions;\n }\n else if (customValue) {\n filtered[index++] = deps.textValueToProperValue(val, returnObject);\n }\n }\n\n filtered.length = index; // Trim to actual size\n return filtered;\n }\n\n function filterValuesByIdentifier(\n valueArray: any[],\n optionsMapData: Map<any, TItem>,\n customValue: boolean,\n returnObject: boolean,\n ): TItem[] {\n const filtered: TItem[] = [];\n filtered.length = valueArray.length; // Pre-allocate array size\n let index = 0;\n\n for (const val of valueArray) {\n const inOptions = optionsMapData.get(val);\n\n if (inOptions !== undefined) {\n filtered[index++] = inOptions;\n }\n else if (customValue) {\n filtered[index++] = deps.textValueToProperValue(val, returnObject);\n }\n }\n\n filtered.length = index; // Trim to actual size\n return filtered;\n }\n\n function processReturnObjectValue(\n modelValueData: TValue | undefined,\n optionsMapData: Map<any, TItem>,\n returnObject: boolean,\n customValue: boolean,\n ): TItem[] {\n const multipleValue = Array.isArray(modelValueData);\n const valueArray = convertModelValueToArray(modelValueData);\n const filtered = filterValuesByOptions(valueArray, optionsMapData, customValue, returnObject);\n\n if (multipleValue || filtered.length === 0)\n return filtered;\n\n const val = filtered[0];\n assert(val);\n return [val];\n }\n\n function processStandardValue(\n modelValueData: TValue | undefined,\n optionsMapData: Map<any, TItem>,\n returnObject: boolean,\n customValue: boolean,\n ): TItem[] {\n const valueArray = convertModelValueToArray(modelValueData);\n return filterValuesByIdentifier(valueArray, optionsMapData, customValue, returnObject);\n }\n\n function onUpdateModelValue(value: TValue | undefined): void {\n set(modelValue, value);\n }\n\n function setSelected(selected: TItem[]): void {\n const keyAttr = get(opts.keyAttr);\n const returnObject = get(opts.returnObject);\n const selection = keyAttr && !returnObject ? selected.map(item => item[keyAttr]) : selected;\n\n if (get(deps.multiple))\n return onUpdateModelValue(selection as TValue);\n\n if (selection.length === 0)\n return onUpdateModelValue(undefined);\n\n return onUpdateModelValue(selection[0] as TValue);\n }\n\n const value = computed<TItem[]>({\n get: () => {\n const modelValueData = get(modelValue);\n const keyAttr = get(opts.keyAttr);\n const returnObject = get(opts.returnObject) ?? false;\n const customValue = get(opts.customValue) ?? false;\n const optionsMapData = get(optionsMap);\n\n if (keyAttr && returnObject)\n return processReturnObjectValue(modelValueData, optionsMapData, returnObject, customValue);\n\n return processStandardValue(modelValueData, optionsMapData, returnObject, customValue);\n },\n set: (selected: TItem[]): void => {\n setSelected(selected);\n },\n });\n\n // Sync search text when menu is closed and value changes\n watch([modelValue, () => get(deps.isOpen)], () => {\n if (get(deps.isOpen) || !get(deps.shouldApplyValueAsSearch))\n return;\n\n const currentValue = get(value);\n if (get(deps.multiple) || currentValue.length === 0) {\n deps.updateInternalSearch();\n }\n else {\n const firstItem = currentValue[0];\n assert(firstItem);\n deps.updateInternalSearch(deps.getText(firstItem));\n }\n }, { immediate: true });\n\n return {\n setSelected,\n value,\n };\n}\n"],"names":["value"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { ComputedRef } from 'vue';
2
+ export declare function useLabelWithQuote(label: () => string, required: () => boolean): ComputedRef<string>;
@@ -0,0 +1,14 @@
1
+ import { computed } from "vue";
2
+ function useLabelWithQuote(label, required) {
3
+ return computed(() => {
4
+ const labelVal = label();
5
+ if (!labelVal)
6
+ return '"\\200B"';
7
+ const asterisk = required() ? "﹡" : "";
8
+ return `' ${labelVal}${asterisk} '`;
9
+ });
10
+ }
11
+ export {
12
+ useLabelWithQuote
13
+ };
14
+ //# sourceMappingURL=use-label-with-quote.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-label-with-quote.js","sources":["../../../src/composables/forms/use-label-with-quote.ts"],"sourcesContent":["import type { ComputedRef } from 'vue';\n\nexport function useLabelWithQuote(\n label: () => string,\n required: () => boolean,\n): ComputedRef<string> {\n return computed<string>(() => {\n const labelVal = label();\n if (!labelVal)\n return '\"\\\\200B\"';\n\n const asterisk = required() ? '﹡' : '';\n return `' ${labelVal}${asterisk} '`;\n });\n}\n"],"names":[],"mappings":";AAEO,SAAS,kBACd,OACA,UACqB;AACrB,SAAO,SAAiB,MAAM;AAC5B,UAAM,WAAW,MAAA;AACjB,QAAI,CAAC;AACH,aAAO;AAET,UAAM,WAAW,aAAa,MAAM;AACpC,WAAO,MAAM,QAAQ,GAAG,QAAQ;AAAA,EAClC,CAAC;AACH;"}
@@ -0,0 +1,6 @@
1
+ import type { Ref, ShallowRef } from 'vue';
2
+ export interface PrependAppendWidth {
3
+ prependWidth: Ref<string>;
4
+ appendWidth: Ref<string>;
5
+ }
6
+ export declare function usePrependAppendWidth(prepend: Readonly<ShallowRef<HTMLDivElement | null>>, append: Readonly<ShallowRef<HTMLDivElement | null>>, offset?: number): PrependAppendWidth;
@@ -0,0 +1,25 @@
1
+ import { assert } from "../../utils/assert.js";
2
+ import { shallowRef } from "vue";
3
+ import { useResizeObserver } from "@vueuse/core";
4
+ import { set } from "@vueuse/shared";
5
+ function usePrependAppendWidth(prepend, append, offset = 0) {
6
+ const prependWidth = shallowRef("0px");
7
+ const appendWidth = shallowRef("0px");
8
+ useResizeObserver(prepend, (entries) => {
9
+ const [entry] = entries;
10
+ assert(entry);
11
+ const { width, left } = entry.contentRect;
12
+ set(prependWidth, `${width + left + offset}px`);
13
+ });
14
+ useResizeObserver(append, (entries) => {
15
+ const [entry] = entries;
16
+ assert(entry);
17
+ const { width, right } = entry.contentRect;
18
+ set(appendWidth, `${width + right + offset}px`);
19
+ });
20
+ return { prependWidth, appendWidth };
21
+ }
22
+ export {
23
+ usePrependAppendWidth
24
+ };
25
+ //# sourceMappingURL=use-prepend-append-width.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-prepend-append-width.js","sources":["../../../src/composables/forms/use-prepend-append-width.ts"],"sourcesContent":["import type { Ref, ShallowRef } from 'vue';\nimport { assert } from '@/utils/assert';\n\nexport interface PrependAppendWidth {\n prependWidth: Ref<string>;\n appendWidth: Ref<string>;\n}\n\nexport function usePrependAppendWidth(\n prepend: Readonly<ShallowRef<HTMLDivElement | null>>,\n append: Readonly<ShallowRef<HTMLDivElement | null>>,\n offset: number = 0,\n): PrependAppendWidth {\n const prependWidth = shallowRef<string>('0px');\n const appendWidth = shallowRef<string>('0px');\n\n useResizeObserver(prepend, (entries) => {\n const [entry] = entries;\n assert(entry);\n const { width, left } = entry.contentRect;\n set(prependWidth, `${width + left + offset}px`);\n });\n\n useResizeObserver(append, (entries) => {\n const [entry] = entries;\n assert(entry);\n const { width, right } = entry.contentRect;\n set(appendWidth, `${width + right + offset}px`);\n });\n\n return { prependWidth, appendWidth };\n}\n"],"names":[],"mappings":";;;;AAQO,SAAS,sBACd,SACA,QACA,SAAiB,GACG;AACpB,QAAM,eAAe,WAAmB,KAAK;AAC7C,QAAM,cAAc,WAAmB,KAAK;AAE5C,oBAAkB,SAAS,CAAC,YAAY;AACtC,UAAM,CAAC,KAAK,IAAI;AAChB,WAAO,KAAK;AACZ,UAAM,EAAE,OAAO,KAAA,IAAS,MAAM;AAC9B,QAAI,cAAc,GAAG,QAAQ,OAAO,MAAM,IAAI;AAAA,EAChD,CAAC;AAED,oBAAkB,QAAQ,CAAC,YAAY;AACrC,UAAM,CAAC,KAAK,IAAI;AAChB,WAAO,KAAK;AACZ,UAAM,EAAE,OAAO,MAAA,IAAU,MAAM;AAC/B,QAAI,aAAa,GAAG,QAAQ,QAAQ,MAAM,IAAI;AAAA,EAChD,CAAC;AAED,SAAO,EAAE,cAAc,YAAA;AACzB;"}
@@ -1,6 +1,6 @@
1
1
  import { createPopper } from "@popperjs/core";
2
2
  import { useResizeObserver, isDefined, unrefElement } from "@vueuse/core";
3
- import { ref, computed, onMounted, watchEffect } from "vue";
3
+ import { ref, shallowRef, computed, onMounted, watchEffect } from "vue";
4
4
  import { useTimeoutManager } from "./timeout-manager.js";
5
5
  import { get, set } from "@vueuse/shared";
6
6
  const DEFAULT_POPPER_OPTIONS = {
@@ -15,13 +15,13 @@ const DEFAULT_POPPER_OPTIONS = {
15
15
  scroll: true,
16
16
  strategy: "absolute"
17
17
  };
18
- function usePopper(options, disabled = ref(false), openDelay = ref(0), closeDelay = ref(0), virtualReference) {
18
+ function usePopper(options, disabled = shallowRef(false), openDelay = shallowRef(0), closeDelay = shallowRef(0), virtualReference) {
19
19
  const reference = ref();
20
20
  const popper = ref();
21
21
  const instance = ref();
22
- const open = ref(false);
23
- const popperEnter = ref(false);
24
- const leavePending = ref(false);
22
+ const open = shallowRef(false);
23
+ const popperEnter = shallowRef(false);
24
+ const leavePending = shallowRef(false);
25
25
  const openTimeoutManager = useTimeoutManager();
26
26
  const closeTimeoutManager = useTimeoutManager();
27
27
  const onPopperLeave = () => {
@@ -37,9 +37,12 @@ function usePopper(options, disabled = ref(false), openDelay = ref(0), closeDela
37
37
  set(leavePending, false);
38
38
  if (!openTimeoutManager.isActive()) {
39
39
  set(popperEnter, true);
40
- openTimeoutManager.create(() => {
41
- set(open, true);
42
- }, immediate ? 0 : get(openDelay));
40
+ openTimeoutManager.create(
41
+ () => {
42
+ set(open, true);
43
+ },
44
+ immediate ? 0 : get(openDelay)
45
+ );
43
46
  }
44
47
  };
45
48
  const onClose = (immediate = false) => {
@@ -47,11 +50,14 @@ function usePopper(options, disabled = ref(false), openDelay = ref(0), closeDela
47
50
  return;
48
51
  openTimeoutManager.clear();
49
52
  if (!closeTimeoutManager.isActive()) {
50
- closeTimeoutManager.create(() => {
51
- if (!get(open))
52
- onPopperLeave();
53
- set(open, false);
54
- }, immediate ? 0 : get(closeDelay));
53
+ closeTimeoutManager.create(
54
+ () => {
55
+ if (!get(open))
56
+ onPopperLeave();
57
+ set(open, false);
58
+ },
59
+ immediate ? 0 : get(closeDelay)
60
+ );
55
61
  }
56
62
  };
57
63
  const onLeavePending = () => {
@@ -68,40 +74,48 @@ function usePopper(options, disabled = ref(false), openDelay = ref(0), closeDela
68
74
  resize = DEFAULT_POPPER_OPTIONS.resize,
69
75
  scroll = DEFAULT_POPPER_OPTIONS.scroll
70
76
  } = get(options);
71
- return [{
72
- enabled: false,
73
- name: "hide"
74
- }, {
75
- enabled: !locked,
76
- name: "flip"
77
- }, {
78
- name: "preventOverflow",
79
- options: {
80
- padding: overflowPadding
77
+ return [
78
+ {
79
+ enabled: false,
80
+ name: "hide"
81
+ },
82
+ {
83
+ enabled: !locked,
84
+ name: "flip"
85
+ },
86
+ {
87
+ name: "preventOverflow",
88
+ options: {
89
+ padding: overflowPadding
90
+ }
91
+ },
92
+ {
93
+ name: "offset",
94
+ options: {
95
+ offset: [offsetSkid, offsetDistance]
96
+ }
97
+ },
98
+ {
99
+ name: "computeStyles",
100
+ options: {
101
+ adaptive,
102
+ gpuAcceleration
103
+ }
104
+ },
105
+ {
106
+ name: "eventListeners",
107
+ options: {
108
+ resize,
109
+ scroll
110
+ }
111
+ },
112
+ {
113
+ name: "arrow",
114
+ options: {
115
+ padding: 4
116
+ }
81
117
  }
82
- }, {
83
- name: "offset",
84
- options: {
85
- offset: [offsetSkid, offsetDistance]
86
- }
87
- }, {
88
- name: "computeStyles",
89
- options: {
90
- adaptive,
91
- gpuAcceleration
92
- }
93
- }, {
94
- name: "eventListeners",
95
- options: {
96
- resize,
97
- scroll
98
- }
99
- }, {
100
- name: "arrow",
101
- options: {
102
- padding: 4
103
- }
104
- }];
118
+ ];
105
119
  });
106
120
  const popperConfig = computed(() => {
107
121
  const {