@flux-ui/components 3.0.0-next.58 → 3.0.0-next.59

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 (301) hide show
  1. package/dist/component/FluxButtonStack.vue.d.ts +1 -1
  2. package/dist/component/FluxCalendar.vue.d.ts +63 -2
  3. package/dist/component/{FluxCalendarEvent.vue.d.ts → FluxCalendarItem.vue.d.ts} +9 -7
  4. package/dist/component/FluxClickablePane.vue.d.ts +1 -1
  5. package/dist/component/FluxDivider.vue.d.ts +1 -1
  6. package/dist/component/FluxFilter.vue.d.ts +1 -1
  7. package/dist/component/FluxFilterBar.vue.d.ts +1 -1
  8. package/dist/component/FluxFormInput.vue.d.ts +2 -2
  9. package/dist/component/FluxFormInputAddition.vue.d.ts +1 -1
  10. package/dist/component/FluxFormTreeViewSelect.vue.d.ts +3 -3
  11. package/dist/component/FluxGallery.vue.d.ts +1 -1
  12. package/dist/component/FluxInfo.vue.d.ts +1 -1
  13. package/dist/component/FluxKanbanColumn.vue.d.ts +2 -2
  14. package/dist/component/{FluxKanbanCard.vue.d.ts → FluxKanbanItem.vue.d.ts} +1 -1
  15. package/dist/component/FluxMenuItem.vue.d.ts +1 -1
  16. package/dist/component/FluxNotice.vue.d.ts +1 -1
  17. package/dist/component/FluxPaneHeader.vue.d.ts +1 -1
  18. package/dist/component/FluxPressable.vue.d.ts +1 -1
  19. package/dist/component/FluxPrompt.vue.d.ts +3 -3
  20. package/dist/component/FluxSplitButton.vue.d.ts +1 -1
  21. package/dist/component/FluxStack.vue.d.ts +1 -1
  22. package/dist/component/FluxTab.vue.d.ts +1 -1
  23. package/dist/component/FluxTabBar.vue.d.ts +4 -1
  24. package/dist/component/FluxTabs.vue.d.ts +4 -1
  25. package/dist/component/FluxTimelineItem.vue.d.ts +1 -1
  26. package/dist/component/calendar/FluxCalendarItemDisplay.vue.d.ts +9 -0
  27. package/dist/component/calendar/FluxCalendarMonthView.vue.d.ts +19 -0
  28. package/dist/component/calendar/FluxCalendarTimeGridView.vue.d.ts +36 -0
  29. package/dist/component/calendar/index.d.ts +3 -0
  30. package/dist/component/index.d.ts +2 -2
  31. package/dist/component/primitive/DialogLayout.vue.d.ts +1 -1
  32. package/dist/component/primitive/SelectBase.vue.d.ts +3 -3
  33. package/dist/composable/index.d.ts +3 -0
  34. package/dist/composable/private/index.d.ts +5 -8
  35. package/dist/composable/private/useKanban.d.ts +2 -2
  36. package/dist/composable/private/useKanbanAutoScroll.d.ts +13 -0
  37. package/dist/composable/useCalendarInjection.d.ts +2 -0
  38. package/dist/composable/useKanbanInjection.d.ts +2 -0
  39. package/dist/composable/useTabBarInjection.d.ts +2 -0
  40. package/dist/data/di.d.ts +54 -12
  41. package/dist/data/i18n.d.ts +4 -0
  42. package/dist/index.css +1500 -1221
  43. package/dist/index.js +9339 -8216
  44. package/dist/index.js.map +1 -1
  45. package/package.json +6 -6
  46. package/src/component/FluxAction.vue +1 -1
  47. package/src/component/FluxActionBar.vue +2 -2
  48. package/src/component/FluxActionPane.vue +1 -1
  49. package/src/component/FluxAdaptiveGroup.vue +2 -2
  50. package/src/component/FluxAdaptiveSlot.vue +2 -2
  51. package/src/component/FluxAlert.vue +1 -1
  52. package/src/component/FluxAnimatedColors.vue +1 -1
  53. package/src/component/FluxAspectRatio.vue +1 -1
  54. package/src/component/FluxAvatar.vue +2 -2
  55. package/src/component/FluxBadge.vue +2 -2
  56. package/src/component/FluxBorderShine.vue +1 -1
  57. package/src/component/FluxBoxedIcon.vue +1 -1
  58. package/src/component/FluxButton.vue +2 -2
  59. package/src/component/FluxButtonGroup.vue +1 -1
  60. package/src/component/FluxButtonStack.vue +1 -1
  61. package/src/component/FluxCalendar.vue +588 -179
  62. package/src/component/FluxCalendarItem.vue +79 -0
  63. package/src/component/FluxCheckbox.vue +2 -2
  64. package/src/component/FluxChip.vue +2 -2
  65. package/src/component/FluxClickablePane.vue +2 -2
  66. package/src/component/FluxColorPicker.vue +2 -2
  67. package/src/component/FluxColorSelect.vue +3 -3
  68. package/src/component/FluxColumn.vue +1 -1
  69. package/src/component/FluxCommandPalette.vue +4 -4
  70. package/src/component/FluxCommandPaletteGroup.vue +1 -1
  71. package/src/component/FluxCommandPaletteItem.vue +1 -1
  72. package/src/component/FluxComment.vue +2 -2
  73. package/src/component/FluxConfirm.vue +1 -1
  74. package/src/component/FluxContainer.vue +1 -1
  75. package/src/component/FluxDataTable.vue +1 -2
  76. package/src/component/FluxDatePicker.vue +3 -3
  77. package/src/component/FluxDestructiveButton.vue +1 -1
  78. package/src/component/FluxDisabled.vue +1 -1
  79. package/src/component/FluxDivider.vue +2 -2
  80. package/src/component/FluxDotPattern.vue +1 -1
  81. package/src/component/FluxDropZone.vue +4 -4
  82. package/src/component/FluxExpandable.vue +3 -3
  83. package/src/component/FluxExpandableGroup.vue +2 -2
  84. package/src/component/FluxFader.vue +1 -1
  85. package/src/component/FluxFaderItem.vue +1 -1
  86. package/src/component/FluxFilter.vue +2 -2
  87. package/src/component/FluxFilterBar.vue +5 -6
  88. package/src/component/FluxFilterBase.vue +2 -2
  89. package/src/component/FluxFilterDate.vue +2 -2
  90. package/src/component/FluxFilterDateRange.vue +2 -2
  91. package/src/component/FluxFilterOption.vue +2 -2
  92. package/src/component/FluxFilterOptionAsync.vue +1 -1
  93. package/src/component/FluxFilterOptions.vue +2 -2
  94. package/src/component/FluxFilterOptionsAsync.vue +1 -1
  95. package/src/component/FluxFilterRange.vue +2 -2
  96. package/src/component/FluxFilterWindow.vue +3 -3
  97. package/src/component/FluxFlickeringGrid.vue +1 -1
  98. package/src/component/FluxFlyout.vue +2 -2
  99. package/src/component/FluxFocalPointEditor.vue +3 -3
  100. package/src/component/FluxFocalPointImage.vue +1 -1
  101. package/src/component/FluxForm.vue +1 -1
  102. package/src/component/FluxFormColumn.vue +1 -1
  103. package/src/component/FluxFormDateInput.vue +3 -3
  104. package/src/component/FluxFormDateRangeInput.vue +4 -4
  105. package/src/component/FluxFormDateTimeInput.vue +3 -3
  106. package/src/component/FluxFormField.vue +3 -3
  107. package/src/component/FluxFormFieldAddition.vue +1 -1
  108. package/src/component/FluxFormGrid.vue +1 -1
  109. package/src/component/FluxFormInput.vue +3 -3
  110. package/src/component/FluxFormInputAddition.vue +2 -2
  111. package/src/component/FluxFormInputGroup.vue +2 -2
  112. package/src/component/FluxFormPinInput.vue +3 -3
  113. package/src/component/FluxFormRangeSlider.vue +3 -3
  114. package/src/component/FluxFormRow.vue +1 -1
  115. package/src/component/FluxFormSection.vue +1 -1
  116. package/src/component/FluxFormSelect.vue +4 -4
  117. package/src/component/FluxFormSelectAsync.vue +6 -6
  118. package/src/component/FluxFormSlider.vue +2 -2
  119. package/src/component/FluxFormTextArea.vue +2 -2
  120. package/src/component/FluxFormTimeZonePicker.vue +4 -4
  121. package/src/component/FluxFormTreeViewSelect.vue +9 -12
  122. package/src/component/FluxGallery.vue +3 -3
  123. package/src/component/FluxGalleryItem.vue +1 -1
  124. package/src/component/FluxGrid.vue +1 -1
  125. package/src/component/FluxGridColumn.vue +1 -1
  126. package/src/component/FluxGridPattern.vue +1 -1
  127. package/src/component/FluxIcon.vue +2 -2
  128. package/src/component/FluxInfo.vue +2 -2
  129. package/src/component/FluxItem.vue +1 -1
  130. package/src/component/FluxItemActions.vue +1 -1
  131. package/src/component/FluxItemContent.vue +1 -1
  132. package/src/component/FluxItemMedia.vue +1 -1
  133. package/src/component/FluxItemStack.vue +1 -1
  134. package/src/component/FluxKanban.vue +6 -13
  135. package/src/component/FluxKanbanColumn.vue +42 -36
  136. package/src/component/FluxKanbanItem.vue +162 -0
  137. package/src/component/FluxLayerPane.vue +1 -1
  138. package/src/component/FluxLayerPaneSecondary.vue +1 -1
  139. package/src/component/FluxLegend.vue +1 -1
  140. package/src/component/FluxLink.vue +1 -1
  141. package/src/component/FluxMenu.vue +1 -1
  142. package/src/component/FluxMenuCollapsible.vue +3 -3
  143. package/src/component/FluxMenuGroup.vue +1 -1
  144. package/src/component/FluxMenuItem.vue +2 -2
  145. package/src/component/FluxMenuSubHeader.vue +1 -1
  146. package/src/component/FluxMenuTitle.vue +1 -1
  147. package/src/component/FluxNotice.vue +3 -3
  148. package/src/component/FluxOverflowBar.vue +1 -1
  149. package/src/component/FluxOverlay.vue +3 -3
  150. package/src/component/FluxOverlayProvider.vue +2 -2
  151. package/src/component/FluxPagination.vue +3 -3
  152. package/src/component/FluxPaginationBar.vue +2 -2
  153. package/src/component/FluxPaginationButton.vue +1 -1
  154. package/src/component/FluxPane.vue +1 -1
  155. package/src/component/FluxPaneBody.vue +1 -1
  156. package/src/component/FluxPaneFooter.vue +1 -1
  157. package/src/component/FluxPaneGroup.vue +1 -1
  158. package/src/component/FluxPaneHeader.vue +2 -2
  159. package/src/component/FluxPaneIllustration.vue +1 -1
  160. package/src/component/FluxPaneMedia.vue +1 -1
  161. package/src/component/FluxPercentageBar.vue +1 -1
  162. package/src/component/FluxPersona.vue +1 -1
  163. package/src/component/FluxPlaceholder.vue +1 -1
  164. package/src/component/FluxPressable.vue +1 -1
  165. package/src/component/FluxPrimaryButton.vue +1 -1
  166. package/src/component/FluxPrimaryLinkButton.vue +1 -1
  167. package/src/component/FluxProgressBar.vue +2 -2
  168. package/src/component/FluxPrompt.vue +1 -1
  169. package/src/component/FluxPublishButton.vue +1 -1
  170. package/src/component/FluxQuantitySelector.vue +2 -2
  171. package/src/component/FluxRemove.vue +2 -2
  172. package/src/component/FluxRoot.vue +2 -2
  173. package/src/component/FluxRow.vue +1 -1
  174. package/src/component/FluxSecondaryButton.vue +1 -1
  175. package/src/component/FluxSecondaryLinkButton.vue +1 -1
  176. package/src/component/FluxSegmentedControl.vue +1 -1
  177. package/src/component/FluxSeparator.vue +1 -1
  178. package/src/component/FluxSlideOver.vue +3 -3
  179. package/src/component/FluxSnackbar.vue +2 -2
  180. package/src/component/FluxSnackbarProvider.vue +2 -2
  181. package/src/component/FluxSpacer.vue +1 -1
  182. package/src/component/FluxSpinner.vue +1 -1
  183. package/src/component/FluxSplitButton.vue +2 -2
  184. package/src/component/FluxStack.vue +2 -2
  185. package/src/component/FluxStatistic.vue +2 -2
  186. package/src/component/FluxStepper.vue +1 -1
  187. package/src/component/FluxStepperStep.vue +1 -1
  188. package/src/component/FluxStepperSteps.vue +2 -2
  189. package/src/component/FluxTab.vue +2 -2
  190. package/src/component/FluxTabBar.vue +75 -7
  191. package/src/component/FluxTabBarItem.vue +35 -4
  192. package/src/component/FluxTable.vue +3 -4
  193. package/src/component/FluxTableActions.vue +1 -1
  194. package/src/component/FluxTableBar.vue +3 -3
  195. package/src/component/FluxTableCell.vue +3 -3
  196. package/src/component/FluxTableHeader.vue +3 -3
  197. package/src/component/FluxTableRow.vue +1 -1
  198. package/src/component/FluxTabs.vue +10 -4
  199. package/src/component/FluxTag.vue +2 -2
  200. package/src/component/FluxTicks.vue +1 -1
  201. package/src/component/FluxTimeline.vue +1 -1
  202. package/src/component/FluxTimelineItem.vue +2 -2
  203. package/src/component/FluxToggle.vue +2 -2
  204. package/src/component/FluxToolbar.vue +2 -2
  205. package/src/component/FluxTooltip.vue +1 -1
  206. package/src/component/FluxTooltipProvider.vue +3 -3
  207. package/src/component/FluxTreeView.vue +3 -4
  208. package/src/component/FluxWindow.vue +1 -1
  209. package/src/component/calendar/FluxCalendarItemDisplay.vue +117 -0
  210. package/src/component/calendar/FluxCalendarMonthView.vue +134 -0
  211. package/src/component/calendar/FluxCalendarTimeGridView.vue +550 -0
  212. package/src/component/calendar/index.ts +3 -0
  213. package/src/component/index.ts +2 -2
  214. package/src/component/primitive/CoordinatePicker.vue +2 -2
  215. package/src/component/primitive/CoordinatePickerThumb.vue +2 -2
  216. package/src/component/primitive/DialogLayout.vue +1 -1
  217. package/src/component/primitive/FilterBadge.vue +2 -2
  218. package/src/component/primitive/FilterItem.vue +1 -1
  219. package/src/component/primitive/FilterMenuRenderer.ts +2 -2
  220. package/src/component/primitive/FilterOptionBase.vue +6 -6
  221. package/src/component/primitive/SelectBase.vue +13 -13
  222. package/src/component/primitive/SliderBase.vue +3 -3
  223. package/src/component/primitive/SliderThumb.vue +2 -2
  224. package/src/component/primitive/SliderTrack.vue +1 -1
  225. package/src/component/primitive/TreeNodeRenderer.vue +3 -4
  226. package/src/component/primitive/VNodeRenderer.ts +1 -2
  227. package/src/composable/index.ts +3 -0
  228. package/src/composable/private/index.ts +5 -8
  229. package/src/composable/private/useAsyncFilterOptions.ts +2 -2
  230. package/src/composable/private/useCommandPalette.ts +2 -2
  231. package/src/composable/private/useDateFlyout.ts +1 -1
  232. package/src/composable/private/useDropdownPopup.ts +1 -1
  233. package/src/composable/private/useFilterOption.ts +2 -2
  234. package/src/composable/private/useFormSelect.ts +2 -3
  235. package/src/composable/private/useKanban.ts +167 -244
  236. package/src/composable/private/useKanbanAutoScroll.ts +95 -0
  237. package/src/composable/private/useTranslate.ts +1 -2
  238. package/src/composable/private/useTreeView.ts +1 -1
  239. package/src/composable/useAdaptiveGroupInjection.ts +1 -1
  240. package/src/composable/useBreakpoints.ts +1 -2
  241. package/src/composable/useCalendarInjection.ts +6 -0
  242. package/src/composable/useDisabled.ts +1 -2
  243. package/src/composable/useDisabledInjection.ts +1 -1
  244. package/src/composable/useExpandableGroupInjection.ts +1 -1
  245. package/src/composable/useFilterInjection.ts +1 -1
  246. package/src/composable/useFlyoutInjection.ts +1 -1
  247. package/src/composable/useFormFieldInjection.ts +1 -1
  248. package/src/composable/useKanbanInjection.ts +12 -0
  249. package/src/composable/useTabBarInjection.ts +10 -0
  250. package/src/composable/useTableInjection.ts +1 -1
  251. package/src/composable/useTooltipInjection.ts +1 -1
  252. package/src/css/component/Action.module.scss +1 -1
  253. package/src/css/component/AdaptiveSlot.module.scss +5 -7
  254. package/src/css/component/Avatar.module.scss +1 -1
  255. package/src/css/component/Badge.module.scss +1 -1
  256. package/src/css/component/Button.module.scss +1 -1
  257. package/src/css/component/Calendar.module.scss +274 -44
  258. package/src/css/component/Chip.module.scss +1 -1
  259. package/src/css/component/Color.module.scss +1 -1
  260. package/src/css/component/CommandPalette.module.scss +1 -1
  261. package/src/css/component/DatePicker.module.scss +1 -1
  262. package/src/css/component/Expandable.module.scss +1 -1
  263. package/src/css/component/Form.module.scss +1 -1
  264. package/src/css/component/Gallery.module.scss +1 -1
  265. package/src/css/component/Grid.module.scss +1 -1
  266. package/src/css/component/Item.module.scss +1 -1
  267. package/src/css/component/{FluxKanban.module.scss → Kanban.module.scss} +56 -79
  268. package/src/css/component/Layout.module.scss +1 -1
  269. package/src/css/component/Menu.module.scss +1 -1
  270. package/src/css/component/Notice.module.scss +1 -1
  271. package/src/css/component/Overlay.module.scss +4 -4
  272. package/src/css/component/Pagination.module.scss +1 -1
  273. package/src/css/component/Pane.module.scss +2 -1
  274. package/src/css/component/Placeholder.module.scss +1 -1
  275. package/src/css/component/Remove.module.scss +1 -1
  276. package/src/css/component/SegmentedControl.module.scss +1 -1
  277. package/src/css/component/Snackbar.module.scss +1 -1
  278. package/src/css/component/Tab.module.scss +138 -34
  279. package/src/css/component/Table.module.scss +1 -1
  280. package/src/css/component/TreeView.module.scss +1 -1
  281. package/src/css/component/TreeViewSelect.module.scss +1 -1
  282. package/src/css/component/base/Button.module.scss +1 -1
  283. package/src/css/component/primitive/Slider.module.scss +1 -1
  284. package/src/css/component/primitive/TreeNode.module.scss +1 -1
  285. package/src/css/variables.scss +2 -2
  286. package/src/data/di.ts +64 -11
  287. package/src/data/filter.ts +3 -3
  288. package/src/data/i18n.ts +4 -0
  289. package/src/data/store.ts +1 -2
  290. package/src/transition/FluxBreakthroughTransition.vue +1 -1
  291. package/src/transition/FluxFadeTransition.vue +1 -1
  292. package/src/transition/FluxOverlayTransition.vue +1 -1
  293. package/src/transition/FluxRouteTransition.vue +1 -1
  294. package/src/transition/FluxSlideOverTransition.vue +1 -1
  295. package/src/transition/FluxTooltipTransition.vue +1 -1
  296. package/src/transition/FluxVerticalWindowTransition.vue +1 -1
  297. package/src/transition/FluxWindowTransition.vue +1 -1
  298. package/src/util/createDialogRenderer.ts +3 -4
  299. package/src/util/createLabelForDateRange.ts +1 -1
  300. package/src/component/FluxCalendarEvent.vue +0 -42
  301. package/src/component/FluxKanbanCard.vue +0 -199
@@ -1,7 +1,7 @@
1
1
  import type { FluxKanbanMoveColumnEvent, FluxKanbanMoveEvent } from '@flux-ui/types';
2
- import type { Ref } from 'vue';
3
- import { computed, ref, unref } from 'vue';
4
- import type { FluxKanbanColumnDragState, FluxKanbanDragState, FluxKanbanInjection, FluxKanbanKeyboardDirection } from '$flux/data/di';
2
+ import { computed, ref, unref, type Ref } from 'vue';
3
+ import type { FluxKanbanColumnDragState, FluxKanbanDragState, FluxKanbanInjection, FluxKanbanKeyboardDirection } from '~flux/components/data';
4
+ import { useKanbanAutoScroll } from './useKanbanAutoScroll';
5
5
 
6
6
  export type UseKanbanOptions = {
7
7
  readonly disabled: Ref<boolean>;
@@ -12,57 +12,69 @@ export type UseKanbanOptions = {
12
12
  readonly onAnnounce: (message: string) => void;
13
13
  };
14
14
 
15
- const AUTOSCROLL_ZONE = 40;
16
- const AUTOSCROLL_MAX_SPEED = 12;
17
15
  const DRAG_LEAVE_GRACE_MS = 50;
18
16
 
17
+ const WITHIN_COLUMN_DELTA: Record<'up' | 'down', -1 | 1> = {up: -1, down: 1};
18
+ const ACROSS_COLUMN_DELTA: Record<'left' | 'right', -1 | 1> = {left: -1, right: 1};
19
+
19
20
  /**
20
21
  * Internal composable for managing kanban drag-and-drop state.
21
- * Provides card registration, drag tracking, drop target management,
22
+ * Provides item registration, drag tracking, drop target management,
22
23
  * keyboard drag-and-drop, column reordering, drop validation and auto-scroll.
23
24
  */
24
25
  export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
25
26
  const dragState = ref<FluxKanbanDragState | null>(null);
26
27
  const columnDragState = ref<FluxKanbanColumnDragState | null>(null);
28
+ const isOverColumnId = ref<string | number | null>(null);
27
29
 
28
- const cardRegistry = new WeakMap<Element, { readonly cardId: string | number }>();
29
- const cardElementsById = new Map<string | number, Element>();
30
+ const itemRegistry = new WeakMap<Element, { readonly itemId: string | number }>();
31
+ const itemElementsById = new Map<string | number, Element>();
30
32
  const columnRegistry = new WeakMap<Element, { readonly columnId: string | number }>();
31
33
  const columnElementsById = new Map<string | number, Element>();
32
34
  const columnBodyById = new Map<string | number, Element>();
35
+ const dragEnterCounts = new Map<string | number, number>();
33
36
 
34
37
  let boardElement: Element | null = null;
35
38
  let clearTimer: ReturnType<typeof setTimeout> | null = null;
36
- let autoScrollFrame: number | null = null;
37
- let autoScrollX = 0;
38
- let autoScrollY = 0;
39
- let autoScrollVerticalTarget: Element | null = null;
40
-
41
- const isDropAllowed = computed(() => {
42
- const state = unref(dragState);
43
39
 
44
- if (!state || state.dropColumnId === null) {
45
- return true;
40
+ const autoScroll = useKanbanAutoScroll({
41
+ getBoardElement: () => boardElement,
42
+ getVerticalTarget: () => {
43
+ const state = unref(dragState);
44
+ return state && state.dropColumnId !== null ? columnBodyById.get(state.dropColumnId) ?? null : null;
46
45
  }
46
+ });
47
47
 
48
- const validate = unref(options.canMove);
48
+ const grabbedId = computed<string | number | null>(() => {
49
+ const state = unref(dragState);
50
+ return state !== null && state.mode === 'keyboard' ? state.itemId : null;
51
+ });
49
52
 
50
- if (!validate) {
51
- return true;
52
- }
53
+ const currentMoveEvent = computed<FluxKanbanMoveEvent | null>(() => tryBuildMoveEvent(unref(dragState)));
53
54
 
54
- return validate(buildMoveEvent(state));
55
+ const isDropAllowed = computed(() => {
56
+ const event = unref(currentMoveEvent);
57
+ return event === null || validateMove(event);
55
58
  });
56
59
 
57
- function buildMoveEvent(state: FluxKanbanDragState): FluxKanbanMoveEvent {
60
+ function tryBuildMoveEvent(state: FluxKanbanDragState | null): FluxKanbanMoveEvent | null {
61
+ if (!state || state.dropColumnId === null) {
62
+ return null;
63
+ }
64
+
58
65
  return {
59
- cardId: state.cardId,
66
+ itemId: state.itemId,
60
67
  fromColumnId: state.fromColumnId,
61
- toColumnId: state.dropColumnId as string | number,
62
- beforeCardId: state.beforeCardId ?? undefined
68
+ toColumnId: state.dropColumnId,
69
+ beforeItemId: state.beforeItemId ?? undefined
63
70
  };
64
71
  }
65
72
 
73
+ function validateMove(event: FluxKanbanMoveEvent): boolean {
74
+ const validate = unref(options.canMove);
75
+ return validate ? validate(event) : true;
76
+ }
77
+
66
78
  function clearTimerIfAny(): void {
67
79
  if (clearTimer !== null) {
68
80
  clearTimeout(clearTimer);
@@ -71,33 +83,8 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
71
83
  }
72
84
 
73
85
  function isSelfDrop(state: FluxKanbanDragState): boolean {
74
- if (state.dropColumnId !== state.fromColumnId) {
75
- return false;
76
- }
77
-
78
- if (state.beforeCardId === state.cardId) {
79
- return true;
80
- }
81
-
82
- const fromBody = columnBodyById.get(state.fromColumnId);
83
-
84
- if (!fromBody) {
85
- return false;
86
- }
87
-
88
- const cards = Array.from(fromBody.children).filter(child => cardRegistry.has(child));
89
- const draggedIndex = cards.findIndex(elm => cardRegistry.get(elm)?.cardId === state.cardId);
90
-
91
- if (draggedIndex === -1) {
92
- return false;
93
- }
94
-
95
- if (state.beforeCardId === null) {
96
- return draggedIndex === cards.length - 1;
97
- }
98
-
99
- const beforeIndex = cards.findIndex(elm => cardRegistry.get(elm)?.cardId === state.beforeCardId);
100
- return beforeIndex !== -1 && beforeIndex === draggedIndex + 1;
86
+ return state.fromColumnId === state.dropColumnId
87
+ && state.beforeItemId === (state.originBeforeItemId ?? null);
101
88
  }
102
89
 
103
90
  function getColumnIndex(columnId: string | number): number {
@@ -120,7 +107,7 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
120
107
  return elm ? columnRegistry.get(elm)! : null;
121
108
  }
122
109
 
123
- function getCardsInColumn(columnId: string | number): (string | number)[] {
110
+ function getItemsInColumn(columnId: string | number): (string | number)[] {
124
111
  const body = columnBodyById.get(columnId);
125
112
 
126
113
  if (!body) {
@@ -128,27 +115,27 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
128
115
  }
129
116
 
130
117
  return Array.from(body.children)
131
- .map(child => cardRegistry.get(child)?.cardId)
118
+ .map(child => itemRegistry.get(child)?.itemId)
132
119
  .filter((id): id is string | number => id !== undefined);
133
120
  }
134
121
 
135
- function registerCard(element: Element, cardId: string | number): void {
136
- cardRegistry.set(element, {cardId});
137
- cardElementsById.set(cardId, element);
122
+ function registerItem(element: Element, itemId: string | number): void {
123
+ itemRegistry.set(element, {itemId});
124
+ itemElementsById.set(itemId, element);
138
125
  }
139
126
 
140
- function unregisterCard(element: Element): void {
141
- const info = cardRegistry.get(element);
127
+ function unregisterItem(element: Element): void {
128
+ const info = itemRegistry.get(element);
142
129
 
143
130
  if (info) {
144
- cardElementsById.delete(info.cardId);
131
+ itemElementsById.delete(info.itemId);
145
132
  }
146
133
 
147
- cardRegistry.delete(element);
134
+ itemRegistry.delete(element);
148
135
  }
149
136
 
150
- function getCardInfo(element: Element): { readonly cardId: string | number } | undefined {
151
- return cardRegistry.get(element);
137
+ function getItemInfo(element: Element): { readonly itemId: string | number } | undefined {
138
+ return itemRegistry.get(element);
152
139
  }
153
140
 
154
141
  function registerColumn(element: Element, columnId: string | number): void {
@@ -162,6 +149,11 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
162
149
  if (info) {
163
150
  columnElementsById.delete(info.columnId);
164
151
  columnBodyById.delete(info.columnId);
152
+ dragEnterCounts.delete(info.columnId);
153
+
154
+ if (isOverColumnId.value === info.columnId) {
155
+ isOverColumnId.value = null;
156
+ }
165
157
  }
166
158
 
167
159
  columnRegistry.delete(element);
@@ -183,28 +175,64 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
183
175
  }
184
176
  }
185
177
 
186
- function startDrag(cardId: string | number, fromColumnId: string | number): void {
178
+ function enterColumn(columnId: string | number): void {
179
+ if (unref(options.disabled)) {
180
+ return;
181
+ }
182
+
183
+ const count = (dragEnterCounts.get(columnId) ?? 0) + 1;
184
+ dragEnterCounts.set(columnId, count);
185
+ isOverColumnId.value = columnId;
186
+ }
187
+
188
+ function leaveColumn(columnId: string | number): void {
189
+ const next = (dragEnterCounts.get(columnId) ?? 0) - 1;
190
+
191
+ if (next > 0) {
192
+ dragEnterCounts.set(columnId, next);
193
+ return;
194
+ }
195
+
196
+ dragEnterCounts.delete(columnId);
197
+
198
+ if (isOverColumnId.value === columnId) {
199
+ isOverColumnId.value = null;
200
+ }
201
+
202
+ clearDropTarget();
203
+ }
204
+
205
+ function startDrag(itemId: string | number, fromColumnId: string | number): void {
187
206
  if (unref(options.disabled)) {
188
207
  return;
189
208
  }
190
209
 
191
210
  clearTimerIfAny();
192
- dragState.value = {mode: 'pointer', cardId, fromColumnId, dropColumnId: null, beforeCardId: null};
211
+ dragState.value = {
212
+ mode: 'pointer',
213
+ itemId,
214
+ fromColumnId,
215
+ dropColumnId: null,
216
+ beforeItemId: null,
217
+ originBeforeItemId: findCurrentBeforeItemId(itemId, fromColumnId)
218
+ };
193
219
  }
194
220
 
195
221
  function endDrag(): void {
196
222
  clearTimerIfAny();
197
- stopAutoScroll();
223
+ autoScroll.stop();
198
224
  dragState.value = null;
225
+ isOverColumnId.value = null;
226
+ dragEnterCounts.clear();
199
227
  }
200
228
 
201
- function updateDropTarget(columnId: string | number, beforeCardId: string | number | null): void {
229
+ function updateDropTarget(columnId: string | number, beforeItemId: string | number | null): void {
202
230
  if (!dragState.value) {
203
231
  return;
204
232
  }
205
233
 
206
234
  clearTimerIfAny();
207
- dragState.value = {...dragState.value, dropColumnId: columnId, beforeCardId};
235
+ dragState.value = {...dragState.value, dropColumnId: columnId, beforeItemId};
208
236
  }
209
237
 
210
238
  function clearDropTarget(): void {
@@ -220,44 +248,33 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
220
248
  return;
221
249
  }
222
250
 
223
- dragState.value = {...dragState.value, dropColumnId: null, beforeCardId: null};
251
+ dragState.value = {...dragState.value, dropColumnId: null, beforeItemId: null};
224
252
  }, DRAG_LEAVE_GRACE_MS);
225
253
  }
226
254
 
227
255
  function commitDrop(): void {
228
256
  const state = dragState.value;
229
- clearTimerIfAny();
230
- stopAutoScroll();
231
-
232
- if (!state || state.dropColumnId === null) {
233
- dragState.value = null;
234
- return;
235
- }
257
+ const event = tryBuildMoveEvent(state);
258
+ endDrag();
236
259
 
237
- if (isSelfDrop(state)) {
238
- dragState.value = null;
260
+ if (!event || !state || isSelfDrop(state)) {
239
261
  return;
240
262
  }
241
263
 
242
- const event = buildMoveEvent(state);
243
- const validate = unref(options.canMove);
244
-
245
- if (validate && !validate(event)) {
264
+ if (!validateMove(event)) {
246
265
  options.onAnnounce('Drop not allowed.');
247
- dragState.value = null;
248
266
  return;
249
267
  }
250
268
 
251
269
  options.onMove(event);
252
- options.onAnnounce(`Card moved to ${String(state.dropColumnId)}.`);
253
- dragState.value = null;
270
+ options.onAnnounce(`Item moved to ${String(event.toColumnId)}.`);
254
271
  }
255
272
 
256
273
  /* region keyboard */
257
274
 
258
- function findCurrentColumnId(cardId: string | number): string | number | null {
275
+ function findCurrentColumnId(itemId: string | number): string | number | null {
259
276
  for (const columnId of columnElementsById.keys()) {
260
- if (getCardsInColumn(columnId).includes(cardId)) {
277
+ if (getItemsInColumn(columnId).includes(itemId)) {
261
278
  return columnId;
262
279
  }
263
280
  }
@@ -265,18 +282,18 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
265
282
  return null;
266
283
  }
267
284
 
268
- function findCurrentBeforeCardId(cardId: string | number, columnId: string | number): string | number | null {
269
- const cards = getCardsInColumn(columnId);
270
- const idx = cards.indexOf(cardId);
285
+ function findCurrentBeforeItemId(itemId: string | number, columnId: string | number): string | number | null {
286
+ const items = getItemsInColumn(columnId);
287
+ const idx = items.indexOf(itemId);
271
288
 
272
289
  if (idx === -1) {
273
290
  return null;
274
291
  }
275
292
 
276
- return cards[idx + 1] ?? null;
293
+ return items[idx + 1] ?? null;
277
294
  }
278
295
 
279
- function grabCard(cardId: string | number, fromColumnId: string | number): void {
296
+ function grabItem(itemId: string | number, fromColumnId: string | number): void {
280
297
  if (unref(options.disabled)) {
281
298
  return;
282
299
  }
@@ -285,13 +302,13 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
285
302
 
286
303
  dragState.value = {
287
304
  mode: 'keyboard',
288
- cardId,
305
+ itemId,
289
306
  fromColumnId,
290
307
  dropColumnId: null,
291
- beforeCardId: null,
292
- originBeforeCardId: findCurrentBeforeCardId(cardId, fromColumnId)
308
+ beforeItemId: null,
309
+ originBeforeItemId: findCurrentBeforeItemId(itemId, fromColumnId)
293
310
  };
294
- options.onAnnounce('Card grabbed. Use arrow keys to move, Enter to drop, Escape to cancel.');
311
+ options.onAnnounce('Item grabbed. Use arrow keys to move, Enter to drop, Escape to cancel.');
295
312
  }
296
313
 
297
314
  function moveKeyboard(direction: FluxKanbanKeyboardDirection): void {
@@ -301,15 +318,15 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
301
318
  return;
302
319
  }
303
320
 
304
- const cardId = state.cardId;
305
- const currentColumnId = findCurrentColumnId(cardId);
321
+ const itemId = state.itemId;
322
+ const currentColumnId = findCurrentColumnId(itemId);
306
323
 
307
324
  if (currentColumnId === null) {
308
325
  return;
309
326
  }
310
327
 
311
328
  const target = direction === 'up' || direction === 'down'
312
- ? computeWithinColumnTarget(cardId, currentColumnId, direction)
329
+ ? computeWithinColumnTarget(itemId, currentColumnId, direction)
313
330
  : computeAcrossColumnTarget(currentColumnId, direction);
314
331
 
315
332
  if (!target) {
@@ -317,27 +334,25 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
317
334
  }
318
335
 
319
336
  const event: FluxKanbanMoveEvent = {
320
- cardId,
337
+ itemId,
321
338
  fromColumnId: currentColumnId,
322
339
  toColumnId: target.columnId,
323
- beforeCardId: target.beforeCardId ?? undefined
340
+ beforeItemId: target.beforeItemId ?? undefined
324
341
  };
325
342
 
326
- const validate = unref(options.canMove);
327
-
328
- if (validate && !validate(event)) {
343
+ if (!validateMove(event)) {
329
344
  options.onAnnounce('Move not allowed.');
330
345
  return;
331
346
  }
332
347
 
333
348
  options.onMove(event);
334
349
  options.onAnnounce(target.announcement);
335
- restoreCardFocus(cardId);
350
+ restoreItemFocus(itemId);
336
351
  }
337
352
 
338
- function restoreCardFocus(cardId: string | number): void {
353
+ function restoreItemFocus(itemId: string | number): void {
339
354
  requestAnimationFrame(() => {
340
- const elm = cardElementsById.get(cardId);
355
+ const elm = itemElementsById.get(itemId);
341
356
 
342
357
  if (elm instanceof HTMLElement) {
343
358
  elm.focus();
@@ -346,62 +361,54 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
346
361
  }
347
362
 
348
363
  function computeWithinColumnTarget(
349
- cardId: string | number,
364
+ itemId: string | number,
350
365
  columnId: string | number,
351
366
  direction: 'up' | 'down'
352
- ): { columnId: string | number; beforeCardId: string | number | null; announcement: string } | null {
353
- const cards = getCardsInColumn(columnId);
354
- const idx = cards.indexOf(cardId);
367
+ ): { columnId: string | number; beforeItemId: string | number | null; announcement: string } | null {
368
+ const items = getItemsInColumn(columnId);
369
+ const idx = items.indexOf(itemId);
355
370
 
356
371
  if (idx === -1) {
357
372
  return null;
358
373
  }
359
374
 
360
- if (direction === 'up') {
361
- if (idx === 0) {
362
- return null;
363
- }
364
-
365
- return {
366
- columnId,
367
- beforeCardId: cards[idx - 1],
368
- announcement: `Position ${idx} of ${cards.length}.`
369
- };
370
- }
375
+ const targetIdx = idx + WITHIN_COLUMN_DELTA[direction];
371
376
 
372
- if (idx === cards.length - 1) {
377
+ if (targetIdx < 0 || targetIdx >= items.length) {
373
378
  return null;
374
379
  }
375
380
 
381
+ // For "down" we want the item to land after items[targetIdx], so beforeItemId is items[targetIdx + 1]; for "up" it's items[targetIdx].
382
+ const beforeItemId = direction === 'up' ? items[targetIdx] : items[targetIdx + 1] ?? null;
383
+
376
384
  return {
377
385
  columnId,
378
- beforeCardId: cards[idx + 2] ?? null,
379
- announcement: `Position ${idx + 2} of ${cards.length}.`
386
+ beforeItemId,
387
+ announcement: `Position ${targetIdx + 1} of ${items.length}.`
380
388
  };
381
389
  }
382
390
 
383
391
  function computeAcrossColumnTarget(
384
392
  currentColumnId: string | number,
385
393
  direction: 'left' | 'right'
386
- ): { columnId: string | number; beforeCardId: string | number | null; announcement: string } | null {
394
+ ): { columnId: string | number; beforeItemId: string | number | null; announcement: string } | null {
387
395
  const currentIdx = getColumnIndex(currentColumnId);
388
396
 
389
397
  if (currentIdx === -1) {
390
398
  return null;
391
399
  }
392
400
 
393
- const nextIdx = direction === 'left' ? currentIdx - 1 : currentIdx + 1;
394
- const nextColumn = getColumnByIndex(nextIdx);
401
+ const nextColumn = getColumnByIndex(currentIdx + ACROSS_COLUMN_DELTA[direction]);
395
402
 
396
403
  if (!nextColumn) {
397
404
  return null;
398
405
  }
399
406
 
400
- const targetCards = getCardsInColumn(nextColumn.columnId);
407
+ const targetItems = getItemsInColumn(nextColumn.columnId);
401
408
 
402
409
  return {
403
410
  columnId: nextColumn.columnId,
404
- beforeCardId: targetCards[0] ?? null,
411
+ beforeItemId: targetItems[0] ?? null,
405
412
  announcement: `Moved to column ${String(nextColumn.columnId)}.`
406
413
  };
407
414
  }
@@ -413,11 +420,11 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
413
420
  return;
414
421
  }
415
422
 
416
- const currentColumnId = findCurrentColumnId(state.cardId);
423
+ const currentColumnId = findCurrentColumnId(state.itemId);
417
424
  dragState.value = null;
418
425
 
419
426
  if (currentColumnId !== null) {
420
- options.onAnnounce(`Card dropped in ${String(currentColumnId)}.`);
427
+ options.onAnnounce(`Item dropped in ${String(currentColumnId)}.`);
421
428
  }
422
429
  }
423
430
 
@@ -428,21 +435,21 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
428
435
  return;
429
436
  }
430
437
 
431
- const cardId = state.cardId;
432
- const currentColumnId = findCurrentColumnId(cardId);
433
- const currentBeforeCardId = currentColumnId !== null
434
- ? findCurrentBeforeCardId(cardId, currentColumnId)
438
+ const itemId = state.itemId;
439
+ const currentColumnId = findCurrentColumnId(itemId);
440
+ const currentBeforeItemId = currentColumnId !== null
441
+ ? findCurrentBeforeItemId(itemId, currentColumnId)
435
442
  : null;
436
443
 
437
444
  const isAtOrigin = currentColumnId === state.fromColumnId
438
- && currentBeforeCardId === (state.originBeforeCardId ?? null);
445
+ && currentBeforeItemId === (state.originBeforeItemId ?? null);
439
446
 
440
447
  if (!isAtOrigin && currentColumnId !== null) {
441
448
  options.onMove({
442
- cardId,
449
+ itemId,
443
450
  fromColumnId: currentColumnId,
444
451
  toColumnId: state.fromColumnId,
445
- beforeCardId: state.originBeforeCardId ?? undefined
452
+ beforeItemId: state.originBeforeItemId ?? undefined
446
453
  });
447
454
  }
448
455
 
@@ -450,9 +457,9 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
450
457
  options.onAnnounce('Drop cancelled.');
451
458
  }
452
459
 
453
- function isCardGrabbed(cardId: string | number): boolean {
460
+ function isItemGrabbed(itemId: string | number): boolean {
454
461
  const state = unref(dragState);
455
- return state !== null && state.mode === 'keyboard' && state.cardId === cardId;
462
+ return state !== null && state.mode === 'keyboard' && state.itemId === itemId;
456
463
  }
457
464
 
458
465
  /* endregion */
@@ -468,7 +475,7 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
468
475
  }
469
476
 
470
477
  function endColumnDrag(): void {
471
- stopAutoScroll();
478
+ autoScroll.stop();
472
479
  columnDragState.value = null;
473
480
  }
474
481
 
@@ -482,7 +489,7 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
482
489
 
483
490
  function commitColumnDrop(): void {
484
491
  const state = columnDragState.value;
485
- stopAutoScroll();
492
+ autoScroll.stop();
486
493
 
487
494
  if (!state) {
488
495
  return;
@@ -512,137 +519,53 @@ export function useKanban(options: UseKanbanOptions): FluxKanbanInjection {
512
519
 
513
520
  /* endregion */
514
521
 
515
- /* region auto-scroll */
522
+ function cancelAll(): void {
523
+ endDrag();
524
+ endColumnDrag();
525
+ cancelKeyboardDrop();
526
+ }
516
527
 
517
528
  function onPointerMove(clientX: number, clientY: number): void {
518
529
  if (!unref(dragState) && !unref(columnDragState)) {
519
530
  return;
520
531
  }
521
532
 
522
- autoScrollX = computeHorizontalScrollDelta(clientX);
523
- autoScrollY = 0;
524
- autoScrollVerticalTarget = null;
525
-
526
- const state = unref(dragState);
527
-
528
- if (state && state.dropColumnId !== null) {
529
- const body = columnBodyById.get(state.dropColumnId);
530
-
531
- if (body) {
532
- autoScrollY = computeVerticalScrollDelta(body, clientY);
533
- autoScrollVerticalTarget = body;
534
- }
535
- }
536
-
537
- if (autoScrollX !== 0 || autoScrollY !== 0) {
538
- startAutoScroll();
539
- } else {
540
- stopAutoScroll();
541
- }
542
- }
543
-
544
- function computeHorizontalScrollDelta(clientX: number): number {
545
- if (!boardElement) {
546
- return 0;
547
- }
548
-
549
- const rect = boardElement.getBoundingClientRect();
550
-
551
- if (clientX < rect.left + AUTOSCROLL_ZONE) {
552
- const distance = Math.max(0, clientX - rect.left);
553
- return -Math.round(((AUTOSCROLL_ZONE - distance) / AUTOSCROLL_ZONE) * AUTOSCROLL_MAX_SPEED);
554
- }
555
-
556
- if (clientX > rect.right - AUTOSCROLL_ZONE) {
557
- const distance = Math.max(0, rect.right - clientX);
558
- return Math.round(((AUTOSCROLL_ZONE - distance) / AUTOSCROLL_ZONE) * AUTOSCROLL_MAX_SPEED);
559
- }
560
-
561
- return 0;
562
- }
563
-
564
- function computeVerticalScrollDelta(target: Element, clientY: number): number {
565
- const rect = target.getBoundingClientRect();
566
-
567
- if (clientY < rect.top + AUTOSCROLL_ZONE) {
568
- const distance = Math.max(0, clientY - rect.top);
569
- return -Math.round(((AUTOSCROLL_ZONE - distance) / AUTOSCROLL_ZONE) * AUTOSCROLL_MAX_SPEED);
570
- }
571
-
572
- if (clientY > rect.bottom - AUTOSCROLL_ZONE) {
573
- const distance = Math.max(0, rect.bottom - clientY);
574
- return Math.round(((AUTOSCROLL_ZONE - distance) / AUTOSCROLL_ZONE) * AUTOSCROLL_MAX_SPEED);
575
- }
576
-
577
- return 0;
578
- }
579
-
580
- function startAutoScroll(): void {
581
- if (autoScrollFrame !== null) {
582
- return;
583
- }
584
-
585
- const tick = () => {
586
- if (autoScrollX !== 0 && boardElement) {
587
- boardElement.scrollLeft += autoScrollX;
588
- }
589
-
590
- if (autoScrollY !== 0 && autoScrollVerticalTarget) {
591
- autoScrollVerticalTarget.scrollTop += autoScrollY;
592
- }
593
-
594
- if (autoScrollX === 0 && autoScrollY === 0) {
595
- autoScrollFrame = null;
596
- return;
597
- }
598
-
599
- autoScrollFrame = requestAnimationFrame(tick);
600
- };
601
-
602
- autoScrollFrame = requestAnimationFrame(tick);
603
- }
604
-
605
- function stopAutoScroll(): void {
606
- if (autoScrollFrame !== null) {
607
- cancelAnimationFrame(autoScrollFrame);
608
- autoScrollFrame = null;
609
- }
610
-
611
- autoScrollX = 0;
612
- autoScrollY = 0;
613
- autoScrollVerticalTarget = null;
533
+ autoScroll.onPointerMove(clientX, clientY);
614
534
  }
615
535
 
616
- /* endregion */
617
-
618
536
  return {
619
537
  disabled: options.disabled,
620
538
  reorderableColumns: options.reorderableColumns,
621
539
  dragState,
622
540
  columnDragState,
541
+ grabbedId,
542
+ isOverColumnId,
623
543
  isDropAllowed,
624
- registerCard,
625
- unregisterCard,
626
- getCardInfo,
544
+ registerItem,
545
+ unregisterItem,
546
+ getItemInfo,
627
547
  registerColumn,
628
548
  unregisterColumn,
629
549
  getColumnInfo,
630
550
  setBoardElement,
631
551
  setColumnBodyElement,
552
+ enterColumn,
553
+ leaveColumn,
632
554
  startDrag,
633
555
  endDrag,
634
556
  updateDropTarget,
635
557
  clearDropTarget,
636
558
  commitDrop,
637
- grabCard,
559
+ grabItem,
638
560
  moveKeyboard,
639
561
  commitKeyboardDrop,
640
562
  cancelKeyboardDrop,
641
- isCardGrabbed,
563
+ isItemGrabbed,
642
564
  startColumnDrag,
643
565
  endColumnDrag,
644
566
  updateColumnDropTarget,
645
567
  commitColumnDrop,
568
+ cancelAll,
646
569
  onPointerMove
647
570
  };
648
571
  }