@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.
- package/dist/component/FluxButtonStack.vue.d.ts +1 -1
- package/dist/component/FluxCalendar.vue.d.ts +63 -2
- package/dist/component/{FluxCalendarEvent.vue.d.ts → FluxCalendarItem.vue.d.ts} +9 -7
- package/dist/component/FluxClickablePane.vue.d.ts +1 -1
- package/dist/component/FluxDivider.vue.d.ts +1 -1
- package/dist/component/FluxFilter.vue.d.ts +1 -1
- package/dist/component/FluxFilterBar.vue.d.ts +1 -1
- package/dist/component/FluxFormInput.vue.d.ts +2 -2
- package/dist/component/FluxFormInputAddition.vue.d.ts +1 -1
- package/dist/component/FluxFormTreeViewSelect.vue.d.ts +3 -3
- package/dist/component/FluxGallery.vue.d.ts +1 -1
- package/dist/component/FluxInfo.vue.d.ts +1 -1
- package/dist/component/FluxKanbanColumn.vue.d.ts +2 -2
- package/dist/component/{FluxKanbanCard.vue.d.ts → FluxKanbanItem.vue.d.ts} +1 -1
- package/dist/component/FluxMenuItem.vue.d.ts +1 -1
- package/dist/component/FluxNotice.vue.d.ts +1 -1
- package/dist/component/FluxPaneHeader.vue.d.ts +1 -1
- package/dist/component/FluxPressable.vue.d.ts +1 -1
- package/dist/component/FluxPrompt.vue.d.ts +3 -3
- package/dist/component/FluxSplitButton.vue.d.ts +1 -1
- package/dist/component/FluxStack.vue.d.ts +1 -1
- package/dist/component/FluxTab.vue.d.ts +1 -1
- package/dist/component/FluxTabBar.vue.d.ts +4 -1
- package/dist/component/FluxTabs.vue.d.ts +4 -1
- package/dist/component/FluxTimelineItem.vue.d.ts +1 -1
- package/dist/component/calendar/FluxCalendarItemDisplay.vue.d.ts +9 -0
- package/dist/component/calendar/FluxCalendarMonthView.vue.d.ts +19 -0
- package/dist/component/calendar/FluxCalendarTimeGridView.vue.d.ts +36 -0
- package/dist/component/calendar/index.d.ts +3 -0
- package/dist/component/index.d.ts +2 -2
- package/dist/component/primitive/DialogLayout.vue.d.ts +1 -1
- package/dist/component/primitive/SelectBase.vue.d.ts +3 -3
- package/dist/composable/index.d.ts +3 -0
- package/dist/composable/private/index.d.ts +5 -8
- package/dist/composable/private/useKanban.d.ts +2 -2
- package/dist/composable/private/useKanbanAutoScroll.d.ts +13 -0
- package/dist/composable/useCalendarInjection.d.ts +2 -0
- package/dist/composable/useKanbanInjection.d.ts +2 -0
- package/dist/composable/useTabBarInjection.d.ts +2 -0
- package/dist/data/di.d.ts +54 -12
- package/dist/data/i18n.d.ts +4 -0
- package/dist/index.css +1500 -1221
- package/dist/index.js +9339 -8216
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
- package/src/component/FluxAction.vue +1 -1
- package/src/component/FluxActionBar.vue +2 -2
- package/src/component/FluxActionPane.vue +1 -1
- package/src/component/FluxAdaptiveGroup.vue +2 -2
- package/src/component/FluxAdaptiveSlot.vue +2 -2
- package/src/component/FluxAlert.vue +1 -1
- package/src/component/FluxAnimatedColors.vue +1 -1
- package/src/component/FluxAspectRatio.vue +1 -1
- package/src/component/FluxAvatar.vue +2 -2
- package/src/component/FluxBadge.vue +2 -2
- package/src/component/FluxBorderShine.vue +1 -1
- package/src/component/FluxBoxedIcon.vue +1 -1
- package/src/component/FluxButton.vue +2 -2
- package/src/component/FluxButtonGroup.vue +1 -1
- package/src/component/FluxButtonStack.vue +1 -1
- package/src/component/FluxCalendar.vue +588 -179
- package/src/component/FluxCalendarItem.vue +79 -0
- package/src/component/FluxCheckbox.vue +2 -2
- package/src/component/FluxChip.vue +2 -2
- package/src/component/FluxClickablePane.vue +2 -2
- package/src/component/FluxColorPicker.vue +2 -2
- package/src/component/FluxColorSelect.vue +3 -3
- package/src/component/FluxColumn.vue +1 -1
- package/src/component/FluxCommandPalette.vue +4 -4
- package/src/component/FluxCommandPaletteGroup.vue +1 -1
- package/src/component/FluxCommandPaletteItem.vue +1 -1
- package/src/component/FluxComment.vue +2 -2
- package/src/component/FluxConfirm.vue +1 -1
- package/src/component/FluxContainer.vue +1 -1
- package/src/component/FluxDataTable.vue +1 -2
- package/src/component/FluxDatePicker.vue +3 -3
- package/src/component/FluxDestructiveButton.vue +1 -1
- package/src/component/FluxDisabled.vue +1 -1
- package/src/component/FluxDivider.vue +2 -2
- package/src/component/FluxDotPattern.vue +1 -1
- package/src/component/FluxDropZone.vue +4 -4
- package/src/component/FluxExpandable.vue +3 -3
- package/src/component/FluxExpandableGroup.vue +2 -2
- package/src/component/FluxFader.vue +1 -1
- package/src/component/FluxFaderItem.vue +1 -1
- package/src/component/FluxFilter.vue +2 -2
- package/src/component/FluxFilterBar.vue +5 -6
- package/src/component/FluxFilterBase.vue +2 -2
- package/src/component/FluxFilterDate.vue +2 -2
- package/src/component/FluxFilterDateRange.vue +2 -2
- package/src/component/FluxFilterOption.vue +2 -2
- package/src/component/FluxFilterOptionAsync.vue +1 -1
- package/src/component/FluxFilterOptions.vue +2 -2
- package/src/component/FluxFilterOptionsAsync.vue +1 -1
- package/src/component/FluxFilterRange.vue +2 -2
- package/src/component/FluxFilterWindow.vue +3 -3
- package/src/component/FluxFlickeringGrid.vue +1 -1
- package/src/component/FluxFlyout.vue +2 -2
- package/src/component/FluxFocalPointEditor.vue +3 -3
- package/src/component/FluxFocalPointImage.vue +1 -1
- package/src/component/FluxForm.vue +1 -1
- package/src/component/FluxFormColumn.vue +1 -1
- package/src/component/FluxFormDateInput.vue +3 -3
- package/src/component/FluxFormDateRangeInput.vue +4 -4
- package/src/component/FluxFormDateTimeInput.vue +3 -3
- package/src/component/FluxFormField.vue +3 -3
- package/src/component/FluxFormFieldAddition.vue +1 -1
- package/src/component/FluxFormGrid.vue +1 -1
- package/src/component/FluxFormInput.vue +3 -3
- package/src/component/FluxFormInputAddition.vue +2 -2
- package/src/component/FluxFormInputGroup.vue +2 -2
- package/src/component/FluxFormPinInput.vue +3 -3
- package/src/component/FluxFormRangeSlider.vue +3 -3
- package/src/component/FluxFormRow.vue +1 -1
- package/src/component/FluxFormSection.vue +1 -1
- package/src/component/FluxFormSelect.vue +4 -4
- package/src/component/FluxFormSelectAsync.vue +6 -6
- package/src/component/FluxFormSlider.vue +2 -2
- package/src/component/FluxFormTextArea.vue +2 -2
- package/src/component/FluxFormTimeZonePicker.vue +4 -4
- package/src/component/FluxFormTreeViewSelect.vue +9 -12
- package/src/component/FluxGallery.vue +3 -3
- package/src/component/FluxGalleryItem.vue +1 -1
- package/src/component/FluxGrid.vue +1 -1
- package/src/component/FluxGridColumn.vue +1 -1
- package/src/component/FluxGridPattern.vue +1 -1
- package/src/component/FluxIcon.vue +2 -2
- package/src/component/FluxInfo.vue +2 -2
- package/src/component/FluxItem.vue +1 -1
- package/src/component/FluxItemActions.vue +1 -1
- package/src/component/FluxItemContent.vue +1 -1
- package/src/component/FluxItemMedia.vue +1 -1
- package/src/component/FluxItemStack.vue +1 -1
- package/src/component/FluxKanban.vue +6 -13
- package/src/component/FluxKanbanColumn.vue +42 -36
- package/src/component/FluxKanbanItem.vue +162 -0
- package/src/component/FluxLayerPane.vue +1 -1
- package/src/component/FluxLayerPaneSecondary.vue +1 -1
- package/src/component/FluxLegend.vue +1 -1
- package/src/component/FluxLink.vue +1 -1
- package/src/component/FluxMenu.vue +1 -1
- package/src/component/FluxMenuCollapsible.vue +3 -3
- package/src/component/FluxMenuGroup.vue +1 -1
- package/src/component/FluxMenuItem.vue +2 -2
- package/src/component/FluxMenuSubHeader.vue +1 -1
- package/src/component/FluxMenuTitle.vue +1 -1
- package/src/component/FluxNotice.vue +3 -3
- package/src/component/FluxOverflowBar.vue +1 -1
- package/src/component/FluxOverlay.vue +3 -3
- package/src/component/FluxOverlayProvider.vue +2 -2
- package/src/component/FluxPagination.vue +3 -3
- package/src/component/FluxPaginationBar.vue +2 -2
- package/src/component/FluxPaginationButton.vue +1 -1
- package/src/component/FluxPane.vue +1 -1
- package/src/component/FluxPaneBody.vue +1 -1
- package/src/component/FluxPaneFooter.vue +1 -1
- package/src/component/FluxPaneGroup.vue +1 -1
- package/src/component/FluxPaneHeader.vue +2 -2
- package/src/component/FluxPaneIllustration.vue +1 -1
- package/src/component/FluxPaneMedia.vue +1 -1
- package/src/component/FluxPercentageBar.vue +1 -1
- package/src/component/FluxPersona.vue +1 -1
- package/src/component/FluxPlaceholder.vue +1 -1
- package/src/component/FluxPressable.vue +1 -1
- package/src/component/FluxPrimaryButton.vue +1 -1
- package/src/component/FluxPrimaryLinkButton.vue +1 -1
- package/src/component/FluxProgressBar.vue +2 -2
- package/src/component/FluxPrompt.vue +1 -1
- package/src/component/FluxPublishButton.vue +1 -1
- package/src/component/FluxQuantitySelector.vue +2 -2
- package/src/component/FluxRemove.vue +2 -2
- package/src/component/FluxRoot.vue +2 -2
- package/src/component/FluxRow.vue +1 -1
- package/src/component/FluxSecondaryButton.vue +1 -1
- package/src/component/FluxSecondaryLinkButton.vue +1 -1
- package/src/component/FluxSegmentedControl.vue +1 -1
- package/src/component/FluxSeparator.vue +1 -1
- package/src/component/FluxSlideOver.vue +3 -3
- package/src/component/FluxSnackbar.vue +2 -2
- package/src/component/FluxSnackbarProvider.vue +2 -2
- package/src/component/FluxSpacer.vue +1 -1
- package/src/component/FluxSpinner.vue +1 -1
- package/src/component/FluxSplitButton.vue +2 -2
- package/src/component/FluxStack.vue +2 -2
- package/src/component/FluxStatistic.vue +2 -2
- package/src/component/FluxStepper.vue +1 -1
- package/src/component/FluxStepperStep.vue +1 -1
- package/src/component/FluxStepperSteps.vue +2 -2
- package/src/component/FluxTab.vue +2 -2
- package/src/component/FluxTabBar.vue +75 -7
- package/src/component/FluxTabBarItem.vue +35 -4
- package/src/component/FluxTable.vue +3 -4
- package/src/component/FluxTableActions.vue +1 -1
- package/src/component/FluxTableBar.vue +3 -3
- package/src/component/FluxTableCell.vue +3 -3
- package/src/component/FluxTableHeader.vue +3 -3
- package/src/component/FluxTableRow.vue +1 -1
- package/src/component/FluxTabs.vue +10 -4
- package/src/component/FluxTag.vue +2 -2
- package/src/component/FluxTicks.vue +1 -1
- package/src/component/FluxTimeline.vue +1 -1
- package/src/component/FluxTimelineItem.vue +2 -2
- package/src/component/FluxToggle.vue +2 -2
- package/src/component/FluxToolbar.vue +2 -2
- package/src/component/FluxTooltip.vue +1 -1
- package/src/component/FluxTooltipProvider.vue +3 -3
- package/src/component/FluxTreeView.vue +3 -4
- package/src/component/FluxWindow.vue +1 -1
- package/src/component/calendar/FluxCalendarItemDisplay.vue +117 -0
- package/src/component/calendar/FluxCalendarMonthView.vue +134 -0
- package/src/component/calendar/FluxCalendarTimeGridView.vue +550 -0
- package/src/component/calendar/index.ts +3 -0
- package/src/component/index.ts +2 -2
- package/src/component/primitive/CoordinatePicker.vue +2 -2
- package/src/component/primitive/CoordinatePickerThumb.vue +2 -2
- package/src/component/primitive/DialogLayout.vue +1 -1
- package/src/component/primitive/FilterBadge.vue +2 -2
- package/src/component/primitive/FilterItem.vue +1 -1
- package/src/component/primitive/FilterMenuRenderer.ts +2 -2
- package/src/component/primitive/FilterOptionBase.vue +6 -6
- package/src/component/primitive/SelectBase.vue +13 -13
- package/src/component/primitive/SliderBase.vue +3 -3
- package/src/component/primitive/SliderThumb.vue +2 -2
- package/src/component/primitive/SliderTrack.vue +1 -1
- package/src/component/primitive/TreeNodeRenderer.vue +3 -4
- package/src/component/primitive/VNodeRenderer.ts +1 -2
- package/src/composable/index.ts +3 -0
- package/src/composable/private/index.ts +5 -8
- package/src/composable/private/useAsyncFilterOptions.ts +2 -2
- package/src/composable/private/useCommandPalette.ts +2 -2
- package/src/composable/private/useDateFlyout.ts +1 -1
- package/src/composable/private/useDropdownPopup.ts +1 -1
- package/src/composable/private/useFilterOption.ts +2 -2
- package/src/composable/private/useFormSelect.ts +2 -3
- package/src/composable/private/useKanban.ts +167 -244
- package/src/composable/private/useKanbanAutoScroll.ts +95 -0
- package/src/composable/private/useTranslate.ts +1 -2
- package/src/composable/private/useTreeView.ts +1 -1
- package/src/composable/useAdaptiveGroupInjection.ts +1 -1
- package/src/composable/useBreakpoints.ts +1 -2
- package/src/composable/useCalendarInjection.ts +6 -0
- package/src/composable/useDisabled.ts +1 -2
- package/src/composable/useDisabledInjection.ts +1 -1
- package/src/composable/useExpandableGroupInjection.ts +1 -1
- package/src/composable/useFilterInjection.ts +1 -1
- package/src/composable/useFlyoutInjection.ts +1 -1
- package/src/composable/useFormFieldInjection.ts +1 -1
- package/src/composable/useKanbanInjection.ts +12 -0
- package/src/composable/useTabBarInjection.ts +10 -0
- package/src/composable/useTableInjection.ts +1 -1
- package/src/composable/useTooltipInjection.ts +1 -1
- package/src/css/component/Action.module.scss +1 -1
- package/src/css/component/AdaptiveSlot.module.scss +5 -7
- package/src/css/component/Avatar.module.scss +1 -1
- package/src/css/component/Badge.module.scss +1 -1
- package/src/css/component/Button.module.scss +1 -1
- package/src/css/component/Calendar.module.scss +274 -44
- package/src/css/component/Chip.module.scss +1 -1
- package/src/css/component/Color.module.scss +1 -1
- package/src/css/component/CommandPalette.module.scss +1 -1
- package/src/css/component/DatePicker.module.scss +1 -1
- package/src/css/component/Expandable.module.scss +1 -1
- package/src/css/component/Form.module.scss +1 -1
- package/src/css/component/Gallery.module.scss +1 -1
- package/src/css/component/Grid.module.scss +1 -1
- package/src/css/component/Item.module.scss +1 -1
- package/src/css/component/{FluxKanban.module.scss → Kanban.module.scss} +56 -79
- package/src/css/component/Layout.module.scss +1 -1
- package/src/css/component/Menu.module.scss +1 -1
- package/src/css/component/Notice.module.scss +1 -1
- package/src/css/component/Overlay.module.scss +4 -4
- package/src/css/component/Pagination.module.scss +1 -1
- package/src/css/component/Pane.module.scss +2 -1
- package/src/css/component/Placeholder.module.scss +1 -1
- package/src/css/component/Remove.module.scss +1 -1
- package/src/css/component/SegmentedControl.module.scss +1 -1
- package/src/css/component/Snackbar.module.scss +1 -1
- package/src/css/component/Tab.module.scss +138 -34
- package/src/css/component/Table.module.scss +1 -1
- package/src/css/component/TreeView.module.scss +1 -1
- package/src/css/component/TreeViewSelect.module.scss +1 -1
- package/src/css/component/base/Button.module.scss +1 -1
- package/src/css/component/primitive/Slider.module.scss +1 -1
- package/src/css/component/primitive/TreeNode.module.scss +1 -1
- package/src/css/variables.scss +2 -2
- package/src/data/di.ts +64 -11
- package/src/data/filter.ts +3 -3
- package/src/data/i18n.ts +4 -0
- package/src/data/store.ts +1 -2
- package/src/transition/FluxBreakthroughTransition.vue +1 -1
- package/src/transition/FluxFadeTransition.vue +1 -1
- package/src/transition/FluxOverlayTransition.vue +1 -1
- package/src/transition/FluxRouteTransition.vue +1 -1
- package/src/transition/FluxSlideOverTransition.vue +1 -1
- package/src/transition/FluxTooltipTransition.vue +1 -1
- package/src/transition/FluxVerticalWindowTransition.vue +1 -1
- package/src/transition/FluxWindowTransition.vue +1 -1
- package/src/util/createDialogRenderer.ts +3 -4
- package/src/util/createLabelForDateRange.ts +1 -1
- package/src/component/FluxCalendarEvent.vue +0 -42
- package/src/component/FluxKanbanCard.vue +0 -199
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FluxKanbanMoveColumnEvent, FluxKanbanMoveEvent } from '@flux-ui/types';
|
|
2
|
-
import type
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
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
|
|
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
|
|
29
|
-
const
|
|
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
|
-
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
51
|
-
return true;
|
|
52
|
-
}
|
|
53
|
+
const currentMoveEvent = computed<FluxKanbanMoveEvent | null>(() => tryBuildMoveEvent(unref(dragState)));
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
const isDropAllowed = computed(() => {
|
|
56
|
+
const event = unref(currentMoveEvent);
|
|
57
|
+
return event === null || validateMove(event);
|
|
55
58
|
});
|
|
56
59
|
|
|
57
|
-
function
|
|
60
|
+
function tryBuildMoveEvent(state: FluxKanbanDragState | null): FluxKanbanMoveEvent | null {
|
|
61
|
+
if (!state || state.dropColumnId === null) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
58
65
|
return {
|
|
59
|
-
|
|
66
|
+
itemId: state.itemId,
|
|
60
67
|
fromColumnId: state.fromColumnId,
|
|
61
|
-
toColumnId: state.dropColumnId
|
|
62
|
-
|
|
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
|
-
|
|
75
|
-
|
|
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
|
|
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 =>
|
|
118
|
+
.map(child => itemRegistry.get(child)?.itemId)
|
|
132
119
|
.filter((id): id is string | number => id !== undefined);
|
|
133
120
|
}
|
|
134
121
|
|
|
135
|
-
function
|
|
136
|
-
|
|
137
|
-
|
|
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
|
|
141
|
-
const info =
|
|
127
|
+
function unregisterItem(element: Element): void {
|
|
128
|
+
const info = itemRegistry.get(element);
|
|
142
129
|
|
|
143
130
|
if (info) {
|
|
144
|
-
|
|
131
|
+
itemElementsById.delete(info.itemId);
|
|
145
132
|
}
|
|
146
133
|
|
|
147
|
-
|
|
134
|
+
itemRegistry.delete(element);
|
|
148
135
|
}
|
|
149
136
|
|
|
150
|
-
function
|
|
151
|
-
return
|
|
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
|
|
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 = {
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
230
|
-
|
|
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
|
-
|
|
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(`
|
|
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(
|
|
275
|
+
function findCurrentColumnId(itemId: string | number): string | number | null {
|
|
259
276
|
for (const columnId of columnElementsById.keys()) {
|
|
260
|
-
if (
|
|
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
|
|
269
|
-
const
|
|
270
|
-
const idx =
|
|
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
|
|
293
|
+
return items[idx + 1] ?? null;
|
|
277
294
|
}
|
|
278
295
|
|
|
279
|
-
function
|
|
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
|
-
|
|
305
|
+
itemId,
|
|
289
306
|
fromColumnId,
|
|
290
307
|
dropColumnId: null,
|
|
291
|
-
|
|
292
|
-
|
|
308
|
+
beforeItemId: null,
|
|
309
|
+
originBeforeItemId: findCurrentBeforeItemId(itemId, fromColumnId)
|
|
293
310
|
};
|
|
294
|
-
options.onAnnounce('
|
|
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
|
|
305
|
-
const currentColumnId = findCurrentColumnId(
|
|
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(
|
|
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
|
-
|
|
337
|
+
itemId,
|
|
321
338
|
fromColumnId: currentColumnId,
|
|
322
339
|
toColumnId: target.columnId,
|
|
323
|
-
|
|
340
|
+
beforeItemId: target.beforeItemId ?? undefined
|
|
324
341
|
};
|
|
325
342
|
|
|
326
|
-
|
|
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
|
-
|
|
350
|
+
restoreItemFocus(itemId);
|
|
336
351
|
}
|
|
337
352
|
|
|
338
|
-
function
|
|
353
|
+
function restoreItemFocus(itemId: string | number): void {
|
|
339
354
|
requestAnimationFrame(() => {
|
|
340
|
-
const elm =
|
|
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
|
-
|
|
364
|
+
itemId: string | number,
|
|
350
365
|
columnId: string | number,
|
|
351
366
|
direction: 'up' | 'down'
|
|
352
|
-
): { columnId: string | number;
|
|
353
|
-
const
|
|
354
|
-
const idx =
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
379
|
-
announcement: `Position ${
|
|
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;
|
|
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
|
|
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
|
|
407
|
+
const targetItems = getItemsInColumn(nextColumn.columnId);
|
|
401
408
|
|
|
402
409
|
return {
|
|
403
410
|
columnId: nextColumn.columnId,
|
|
404
|
-
|
|
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.
|
|
423
|
+
const currentColumnId = findCurrentColumnId(state.itemId);
|
|
417
424
|
dragState.value = null;
|
|
418
425
|
|
|
419
426
|
if (currentColumnId !== null) {
|
|
420
|
-
options.onAnnounce(`
|
|
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
|
|
432
|
-
const currentColumnId = findCurrentColumnId(
|
|
433
|
-
const
|
|
434
|
-
?
|
|
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
|
-
&&
|
|
445
|
+
&& currentBeforeItemId === (state.originBeforeItemId ?? null);
|
|
439
446
|
|
|
440
447
|
if (!isAtOrigin && currentColumnId !== null) {
|
|
441
448
|
options.onMove({
|
|
442
|
-
|
|
449
|
+
itemId,
|
|
443
450
|
fromColumnId: currentColumnId,
|
|
444
451
|
toColumnId: state.fromColumnId,
|
|
445
|
-
|
|
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
|
|
460
|
+
function isItemGrabbed(itemId: string | number): boolean {
|
|
454
461
|
const state = unref(dragState);
|
|
455
|
-
return state !== null && state.mode === 'keyboard' && state.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
625
|
-
|
|
626
|
-
|
|
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
|
-
|
|
559
|
+
grabItem,
|
|
638
560
|
moveKeyboard,
|
|
639
561
|
commitKeyboardDrop,
|
|
640
562
|
cancelKeyboardDrop,
|
|
641
|
-
|
|
563
|
+
isItemGrabbed,
|
|
642
564
|
startColumnDrag,
|
|
643
565
|
endColumnDrag,
|
|
644
566
|
updateColumnDropTarget,
|
|
645
567
|
commitColumnDrop,
|
|
568
|
+
cancelAll,
|
|
646
569
|
onPointerMove
|
|
647
570
|
};
|
|
648
571
|
}
|