@vuu-ui/vuu-ui-controls 2.1.19-beta.1 → 2.1.19-beta.2

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 (180) hide show
  1. package/package.json +12 -13
  2. package/src/calendar/Calendar.css.js +10 -0
  3. package/src/calendar/Calendar.js +70 -0
  4. package/src/calendar/index.js +4 -0
  5. package/src/calendar/internal/CalendarCarousel.css.js +19 -0
  6. package/src/calendar/internal/CalendarCarousel.js +73 -0
  7. package/src/calendar/internal/CalendarContext.js +9 -0
  8. package/src/calendar/internal/CalendarDay.css.js +116 -0
  9. package/src/calendar/internal/CalendarDay.js +64 -0
  10. package/src/calendar/internal/CalendarMonth.css.js +13 -0
  11. package/src/calendar/internal/CalendarMonth.js +43 -0
  12. package/src/calendar/internal/CalendarNavigation.css.js +24 -0
  13. package/src/calendar/internal/CalendarNavigation.js +185 -0
  14. package/src/calendar/internal/CalendarWeekHeader.css.js +23 -0
  15. package/src/calendar/internal/CalendarWeekHeader.js +31 -0
  16. package/src/calendar/internal/useFocusManagement.js +66 -0
  17. package/src/calendar/internal/utils.js +57 -0
  18. package/src/calendar/useCalendar.js +116 -0
  19. package/src/calendar/useCalendarDay.js +74 -0
  20. package/src/calendar/useSelection.js +202 -0
  21. package/src/column-picker/ColumnPicker.css.js +8 -0
  22. package/src/column-picker/ColumnPicker.js +108 -0
  23. package/src/column-picker/ColumnSearch.css.js +61 -0
  24. package/src/column-picker/ColumnSearch.js +66 -0
  25. package/src/column-picker/index.js +2 -0
  26. package/src/column-picker/moving-window.js +49 -0
  27. package/src/common-hooks/index.js +3 -0
  28. package/src/common-hooks/selectionTypes.js +8 -0
  29. package/src/common-hooks/use-resize-observer.js +122 -0
  30. package/src/common-hooks/useControlled.js +45 -0
  31. package/src/context-panel-provider/ContextPanelProvider.js +80 -0
  32. package/src/cycle-state-button/CycleStateButton.js +30 -0
  33. package/src/cycle-state-button/index.js +1 -0
  34. package/src/date-input/DateInput.css.js +195 -0
  35. package/src/date-input/DateInput.js +210 -0
  36. package/src/date-input/index.js +1 -0
  37. package/src/date-picker/DatePicker.js +137 -0
  38. package/src/date-picker/DatePickerContext.js +20 -0
  39. package/src/date-picker/DatePickerPanel.css.js +25 -0
  40. package/src/date-picker/DatePickerPanel.js +124 -0
  41. package/src/date-picker/index.js +1 -0
  42. package/src/drag-drop/DragDropProvider.js +123 -0
  43. package/src/drag-drop/DragDropState.js +25 -0
  44. package/src/drag-drop/Draggable.css.js +57 -0
  45. package/src/drag-drop/Draggable.js +77 -0
  46. package/src/drag-drop/DropIndicator.css.js +11 -0
  47. package/src/drag-drop/DropIndicator.js +28 -0
  48. package/src/drag-drop/dragDropTypes.js +3 -0
  49. package/src/drag-drop/drop-target-utils.js +199 -0
  50. package/src/drag-drop/index.js +6 -0
  51. package/src/drag-drop/useAutoScroll.js +53 -0
  52. package/src/drag-drop/useDragDisplacers.js +126 -0
  53. package/src/drag-drop/useDragDrop.js +435 -0
  54. package/src/drag-drop/useDragDropCopy.js +22 -0
  55. package/src/drag-drop/useDragDropIndicator.js +182 -0
  56. package/src/drag-drop/useDragDropNaturalMovement.js +205 -0
  57. package/src/drag-drop/useDropIndicator.js +21 -0
  58. package/src/drag-drop/useGlobalDragDrop.js +67 -0
  59. package/src/drag-drop/useTransition.js +11 -0
  60. package/src/editable/index.js +1 -0
  61. package/src/editable/useEditableText.js +199 -0
  62. package/src/editable-label/EditableLabel.css.js +81 -0
  63. package/src/editable-label/EditableLabel.js +125 -0
  64. package/src/editable-label/index.js +1 -0
  65. package/src/expando-input/ExpandoInput.css.js +67 -0
  66. package/src/expando-input/ExpandoInput.js +40 -0
  67. package/src/expando-input/index.js +1 -0
  68. package/src/highlighter/Highlighter.css.js +8 -0
  69. package/src/highlighter/Highlighter.js +27 -0
  70. package/src/highlighter/index.js +1 -0
  71. package/src/hover-overlay/HoverOverlay.js +92 -0
  72. package/src/icon-button/Icon.css.js +8 -0
  73. package/src/icon-button/Icon.js +26 -0
  74. package/src/icon-button/IconButton.css.js +10 -0
  75. package/src/icon-button/IconButton.js +28 -0
  76. package/src/icon-button/ToggleIconButton.css.js +47 -0
  77. package/src/icon-button/ToggleIconButton.js +26 -0
  78. package/src/icon-button/index.js +3 -0
  79. package/src/index.js +31 -0
  80. package/src/instrument-picker/SearchCell.css.js +17 -0
  81. package/src/instrument-picker/SearchCell.js +29 -0
  82. package/src/instrument-picker/TablePicker.css.js +23 -0
  83. package/src/instrument-picker/TablePicker.js +89 -0
  84. package/src/instrument-picker/index.js +1 -0
  85. package/src/instrument-picker/moving-window.js +49 -0
  86. package/src/instrument-picker/useDataSource.js +38 -0
  87. package/src/instrument-picker/useTablePicker.js +136 -0
  88. package/src/measured-container/MeasuredContainer.css.js +11 -0
  89. package/src/measured-container/MeasuredContainer.js +50 -0
  90. package/src/measured-container/index.js +2 -0
  91. package/src/measured-container/useMeasuredContainer.js +156 -0
  92. package/src/modal-provider/ModalProvider.js +147 -0
  93. package/src/overflow-container/OverflowContainer.css.js +135 -0
  94. package/src/overflow-container/OverflowContainer.js +87 -0
  95. package/src/overflow-container/index.js +2 -0
  96. package/src/overflow-container/overflow-utils.js +211 -0
  97. package/src/overflow-container/useOverflowContainer.js +108 -0
  98. package/src/price-ticker/PriceTicker.css.js +32 -0
  99. package/src/price-ticker/PriceTicker.js +51 -0
  100. package/src/price-ticker/index.js +1 -0
  101. package/src/prompt/Prompt.css.js +48 -0
  102. package/src/prompt/Prompt.js +112 -0
  103. package/src/sortable-list/SortableList.js +39 -0
  104. package/src/split-button/SplitButton.css.js +117 -0
  105. package/src/split-button/SplitButton.js +60 -0
  106. package/src/split-button/SplitStateButton.css.js +66 -0
  107. package/src/split-button/SplitStateButton.js +23 -0
  108. package/src/split-button/index.js +2 -0
  109. package/src/split-button/useSplitButton.js +61 -0
  110. package/src/table-search/SearchCell.css.js +20 -0
  111. package/src/table-search/SearchCell.js +26 -0
  112. package/src/table-search/TableSearch.css.js +27 -0
  113. package/src/table-search/TableSearch.js +81 -0
  114. package/src/table-search/index.js +1 -0
  115. package/src/table-search/moving-window.js +49 -0
  116. package/src/table-search/useTableSearch.js +30 -0
  117. package/src/tabs-next/TabBar.css.js +26 -0
  118. package/src/tabs-next/TabBar.js +27 -0
  119. package/src/tabs-next/TabListNext.css.js +36 -0
  120. package/src/tabs-next/TabListNext.js +94 -0
  121. package/src/tabs-next/TabNext.css.js +76 -0
  122. package/src/tabs-next/TabNext.js +91 -0
  123. package/src/tabs-next/TabNextAction.js +26 -0
  124. package/src/tabs-next/TabNextContext.js +14 -0
  125. package/src/tabs-next/TabNextPanel.css.js +17 -0
  126. package/src/tabs-next/TabNextPanel.js +69 -0
  127. package/src/tabs-next/TabNextTrigger.css.js +22 -0
  128. package/src/tabs-next/TabNextTrigger.js +66 -0
  129. package/src/tabs-next/TabOverflowList.css.js +77 -0
  130. package/src/tabs-next/TabOverflowList.js +115 -0
  131. package/src/tabs-next/TabsNext.js +149 -0
  132. package/src/tabs-next/TabsNextContext.js +28 -0
  133. package/src/tabs-next/hooks/useCollection.js +80 -0
  134. package/src/tabs-next/hooks/useFocusOutside.js +23 -0
  135. package/src/tabs-next/hooks/useOverflow.js +118 -0
  136. package/src/tabs-next/index.js +7 -0
  137. package/src/tabstrip/Tab.css.js +148 -0
  138. package/src/tabstrip/Tab.js +107 -0
  139. package/src/tabstrip/TabMenu.css.js +8 -0
  140. package/src/tabstrip/TabMenu.js +48 -0
  141. package/src/tabstrip/TabMenuOptions.js +14 -0
  142. package/src/tabstrip/TabsTypes.js +0 -0
  143. package/src/tabstrip/Tabstrip.css.js +121 -0
  144. package/src/tabstrip/Tabstrip.js +106 -0
  145. package/src/tabstrip/ThemeTabstrip.css.js +20 -0
  146. package/src/tabstrip/index.js +4 -0
  147. package/src/tabstrip/tabstrip-dom-utils.js +11 -0
  148. package/src/tabstrip/useAnimatedSelectionThumb.js +68 -0
  149. package/src/tabstrip/useKeyboardNavigation.js +191 -0
  150. package/src/tabstrip/useSelection.js +50 -0
  151. package/src/tabstrip/useTabstrip.js +181 -0
  152. package/src/time-input/MaskedInput.js +285 -0
  153. package/src/time-input/TimeInput.css.js +39 -0
  154. package/src/time-input/TimeInput.js +37 -0
  155. package/src/time-input/useTimeInput.js +82 -0
  156. package/src/toolbar/Toolbar.css.js +46 -0
  157. package/src/toolbar/Toolbar.js +62 -0
  158. package/src/toolbar/index.js +1 -0
  159. package/src/toolbar/toolbar-dom-utils.js +11 -0
  160. package/src/toolbar/useKeyboardNavigation.js +240 -0
  161. package/src/toolbar/useSelection.js +82 -0
  162. package/src/toolbar/useToolbar.js +73 -0
  163. package/src/utils/deprecated-types.js +0 -0
  164. package/src/utils/escapeRegExp.js +5 -0
  165. package/src/utils/forwardCallbackProps.js +15 -0
  166. package/src/utils/index.js +5 -0
  167. package/src/utils/isOverflowElement.js +2 -0
  168. package/src/utils/isPlainObject.js +2 -0
  169. package/src/vuu-date-picker/VuuDatePicker.js +92 -0
  170. package/src/vuu-date-picker/index.js +1 -0
  171. package/src/vuu-input/VuuInput.css.js +13 -0
  172. package/src/vuu-input/VuuInput.js +85 -0
  173. package/src/vuu-input/index.js +1 -0
  174. package/src/vuu-time-picker/TimeRangePicker.js +0 -0
  175. package/src/vuu-time-picker/VuuTimePicker.css.js +14 -0
  176. package/src/vuu-time-picker/VuuTimePicker.js +26 -0
  177. package/src/vuu-typeahead-input/VuuTypeaheadInput.css.js +49 -0
  178. package/src/vuu-typeahead-input/VuuTypeaheadInput.js +46 -0
  179. package/src/vuu-typeahead-input/index.js +1 -0
  180. package/src/vuu-typeahead-input/useVuuTypeaheadInput.js +140 -0
@@ -0,0 +1,6 @@
1
+ export * from "./dragDropTypes.js";
2
+ export * from "./DragDropProvider.js";
3
+ export * from "./DragDropState.js";
4
+ export * from "./useDragDrop.js";
5
+ export * from "./drop-target-utils.js";
6
+ export * from "./useGlobalDragDrop.js";
@@ -0,0 +1,53 @@
1
+ import { useCallback, useRef } from "react";
2
+ import { dimensions } from "./drop-target-utils.js";
3
+ const useAutoScroll = ({ containerRef, onScrollingStopped, orientation = "vertical" })=>{
4
+ const scrollTimer = useRef(null);
5
+ const isScrolling = useRef(false);
6
+ const scrollPosRef = useRef(0);
7
+ const lastScrollDirectionRef = useRef("fwd");
8
+ const stopScrolling = useCallback((atEnd = false)=>{
9
+ if (null !== scrollTimer.current) {
10
+ clearTimeout(scrollTimer.current);
11
+ scrollTimer.current = null;
12
+ }
13
+ isScrolling.current = false;
14
+ onScrollingStopped?.(lastScrollDirectionRef.current, scrollPosRef.current, atEnd);
15
+ }, [
16
+ onScrollingStopped
17
+ ]);
18
+ const startScrolling = useCallback((direction, scrollRate, scrollUnit = 100)=>{
19
+ const { current: container } = containerRef;
20
+ if (container) {
21
+ const { SCROLL_POS, SCROLL_SIZE, CLIENT_SIZE } = dimensions(orientation);
22
+ const { [SCROLL_POS]: scrollPos, [SCROLL_SIZE]: scrollSize, [CLIENT_SIZE]: clientSize } = container;
23
+ const maxScroll = "fwd" === direction ? scrollSize - clientSize - scrollPos : scrollPos;
24
+ const nextScroll = Math.min(maxScroll, scrollUnit);
25
+ if ("fwd" === direction) {
26
+ lastScrollDirectionRef.current = "fwd";
27
+ container[SCROLL_POS] = scrollPosRef.current = scrollPos + nextScroll;
28
+ } else {
29
+ lastScrollDirectionRef.current = "bwd";
30
+ container[SCROLL_POS] = scrollPosRef.current = scrollPos - nextScroll;
31
+ }
32
+ if (nextScroll === maxScroll) requestAnimationFrame(()=>{
33
+ stopScrolling(true);
34
+ });
35
+ else {
36
+ isScrolling.current = true;
37
+ scrollTimer.current = window.setTimeout(()=>{
38
+ startScrolling(direction, scrollRate, scrollUnit);
39
+ }, 100);
40
+ }
41
+ }
42
+ }, [
43
+ containerRef,
44
+ orientation,
45
+ stopScrolling
46
+ ]);
47
+ return {
48
+ isScrolling,
49
+ startScrolling,
50
+ stopScrolling
51
+ };
52
+ };
53
+ export { useAutoScroll };
@@ -0,0 +1,126 @@
1
+ import { useCallback, useMemo, useRef } from "react";
2
+ import { createDragSpacer } from "./Draggable.js";
3
+ import { mutateDropTargetsSwitchDropTargetPosition } from "./drop-target-utils.js";
4
+ const useDragDisplacers = (orientation = "horizontal")=>{
5
+ const animationFrame = useRef(0);
6
+ const transitioning = useRef(false);
7
+ const spacers = useMemo(()=>[
8
+ createDragSpacer(transitioning),
9
+ createDragSpacer()
10
+ ], []);
11
+ const animateTransition = useCallback((size, propertyName = "width")=>{
12
+ const [spacer1, spacer2] = spacers;
13
+ animationFrame.current = requestAnimationFrame(()=>{
14
+ transitioning.current = true;
15
+ spacer1.style.cssText = `${propertyName}: 0px`;
16
+ spacer2.style.cssText = `${propertyName}: ${size}px`;
17
+ spacers[0] = spacer2;
18
+ spacers[1] = spacer1;
19
+ });
20
+ }, [
21
+ spacers
22
+ ]);
23
+ const clearSpacers = useCallback((useTransition = false)=>{
24
+ if (true === useTransition) {
25
+ const [spacer] = spacers;
26
+ const cleanup = ()=>{
27
+ spacer.removeEventListener("transitionend", cleanup);
28
+ clearSpacers();
29
+ };
30
+ const propertyName = "horizontal" === orientation ? "width" : "height";
31
+ spacer.addEventListener("transitionend", cleanup);
32
+ animateTransition(0, propertyName);
33
+ } else spacers.forEach((spacer)=>spacer.remove());
34
+ }, [
35
+ animateTransition,
36
+ orientation,
37
+ spacers
38
+ ]);
39
+ const setTerminalSpacer = useCallback((container, position, size)=>{
40
+ clearSpacers();
41
+ const propertyName = "horizontal" === orientation ? "width" : "height";
42
+ const [spacer] = spacers;
43
+ spacer.style.cssText = `${propertyName}: ${size}px`;
44
+ if ("start" === position) container.firstChild?.before(spacer);
45
+ else container.lastChild?.after(spacer);
46
+ }, [
47
+ clearSpacers,
48
+ orientation,
49
+ spacers
50
+ ]);
51
+ const cancelAnyPendingAnimation = useCallback(()=>{
52
+ if (animationFrame.current) {
53
+ cancelAnimationFrame(animationFrame.current);
54
+ animationFrame.current = 0;
55
+ }
56
+ }, []);
57
+ const displaceItem = useCallback((dropTargets, dropTarget, size, useTransition = false, direction = "static")=>{
58
+ if (dropTarget) {
59
+ const propertyName = "horizontal" === orientation ? "width" : "height";
60
+ const [spacer1, spacer2] = spacers;
61
+ cancelAnyPendingAnimation();
62
+ if (useTransition) {
63
+ if (transitioning.current) {
64
+ clearSpacers();
65
+ spacer1.style.cssText = `${propertyName}: ${size}px`;
66
+ spacer2.style.cssText = `${propertyName}: 0px`;
67
+ if ("fwd" === direction) {
68
+ dropTarget.element.before(spacer1);
69
+ dropTarget.element.after(spacer2);
70
+ } else {
71
+ dropTarget.element.after(spacer1);
72
+ dropTarget.element.before(spacer2);
73
+ }
74
+ } else if ("fwd" === direction) dropTarget.element.after(spacer2);
75
+ else dropTarget.element.before(spacer2);
76
+ animateTransition(size, propertyName);
77
+ } else if ("static" === direction) {
78
+ spacer1.style.cssText = `${propertyName}: ${size}px`;
79
+ dropTarget.element.before(spacer1);
80
+ } else throw Error("useDragDisplacers currently only supports noTransition for static displacement");
81
+ if ("static" !== direction) mutateDropTargetsSwitchDropTargetPosition(dropTargets, direction);
82
+ return "bwd" === direction ? dropTarget.index : dropTarget.index + 1;
83
+ }
84
+ return -1;
85
+ }, [
86
+ animateTransition,
87
+ cancelAnyPendingAnimation,
88
+ clearSpacers,
89
+ orientation,
90
+ spacers
91
+ ]);
92
+ const displaceLastItem = useCallback((dropTargets, dropTarget, size, useTransition = false, direction = "static")=>{
93
+ const propertyName = "horizontal" === orientation ? "width" : "height";
94
+ const [spacer1, spacer2] = spacers;
95
+ cancelAnyPendingAnimation();
96
+ if (useTransition) {
97
+ if (transitioning.current) {
98
+ clearSpacers();
99
+ spacer1.style.cssText = `${propertyName}: ${size}px`;
100
+ spacer2.style.cssText = `${propertyName}: 0px`;
101
+ dropTarget.element.before(spacer1);
102
+ dropTarget.element.after(spacer2);
103
+ } else if ("fwd" === direction) dropTarget.element.after(spacer2);
104
+ else dropTarget.element.before(spacer2);
105
+ animateTransition(size, propertyName);
106
+ } else {
107
+ spacer1.style.cssText = `${propertyName}: ${size}px`;
108
+ dropTarget.element.after(spacer1);
109
+ }
110
+ if ("static" !== direction) mutateDropTargetsSwitchDropTargetPosition(dropTargets, direction);
111
+ return dropTarget.index;
112
+ }, [
113
+ animateTransition,
114
+ cancelAnyPendingAnimation,
115
+ clearSpacers,
116
+ orientation,
117
+ spacers
118
+ ]);
119
+ return {
120
+ displaceItem,
121
+ displaceLastItem,
122
+ clearSpacers,
123
+ setTerminalSpacer
124
+ };
125
+ };
126
+ export { useDragDisplacers };
@@ -0,0 +1,435 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { dispatchCustomEvent } from "@vuu-ui/vuu-utils";
3
+ import { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
4
+ import { useDragDropProvider } from "./DragDropProvider.js";
5
+ import { DragDropState } from "./DragDropState.js";
6
+ import { Draggable } from "./Draggable.js";
7
+ import { NOT_OVERFLOWED, cloneElement, constrainRect, dimensions, getScrollableContainer, isContainerScrollable } from "./drop-target-utils.js";
8
+ import { useAutoScroll } from "./useAutoScroll.js";
9
+ import { NULL_DROP_OPTIONS, useDragDropCopy } from "./useDragDropCopy.js";
10
+ import { useDragDropIndicator } from "./useDragDropIndicator.js";
11
+ import { useDragDropNaturalMovement } from "./useDragDropNaturalMovement.js";
12
+ import { isOverflowElement } from "../utils/index.js";
13
+ const NULL_DRAG_DROP_RESULT = {
14
+ beginDrag: ()=>void 0,
15
+ drag: ()=>void 0,
16
+ draggableRef: {
17
+ current: null
18
+ },
19
+ drop: ()=>NULL_DROP_OPTIONS,
20
+ isDragging: false,
21
+ isScrolling: false,
22
+ handleScrollStart: ()=>void 0,
23
+ handleScrollStop: ()=>void 0,
24
+ revealOverflowedItems: false
25
+ };
26
+ const UNBOUNDED = {
27
+ start: 0,
28
+ end: 1000,
29
+ contraStart: 0,
30
+ contraEnd: 1000
31
+ };
32
+ const noDragDrop = ()=>NULL_DRAG_DROP_RESULT;
33
+ const dragThreshold = 3;
34
+ const getDraggableElement = (el, query)=>el?.closest(query);
35
+ const getLastElement = (container, itemQuery)=>{
36
+ const fullItemQuery = `:is(${itemQuery}${NOT_OVERFLOWED},.vuuOverflowContainer-OverflowIndicator)`;
37
+ const childElements = Array.from(container.querySelectorAll(fullItemQuery));
38
+ const lastElement = childElements.pop();
39
+ return [
40
+ lastElement,
41
+ isOverflowElement(lastElement)
42
+ ];
43
+ };
44
+ const useDragDrop = ({ allowDragDrop, containerRef, draggableClassName, getDragPayload, id, itemQuery = "*", onDragStart, onDrop, onDropSettle, orientation, scrollingContainerRef, ...dragDropProps })=>{
45
+ const dragBoundaries = useRef({
46
+ start: 0,
47
+ end: 0,
48
+ contraStart: 0,
49
+ contraEnd: 0
50
+ });
51
+ const [draggableStatus, setDraggableStatus] = useState({
52
+ draggable: void 0,
53
+ draggedItemIndex: -1,
54
+ isDragging: false
55
+ });
56
+ const dragDropStateRef = useRef(null);
57
+ const mouseDownTimer = useRef(null);
58
+ const isScrollableRef = useRef(false);
59
+ const mousedownElementRef = useRef(null);
60
+ const mousePosRef = useRef({
61
+ x: 0,
62
+ y: 0
63
+ });
64
+ const startPosRef = useRef({
65
+ x: 0,
66
+ y: 0
67
+ });
68
+ const settlingItemRef = useRef(null);
69
+ const scrollableContainerRef = useRef(null);
70
+ const dropPosRef = useRef(-1);
71
+ const dropIndexRef = useRef(-1);
72
+ const handleScrollStopRef = useRef(void 0);
73
+ const { isDragSource, isDropTarget, onDragOut, onEndOfDragOperation, register } = useDragDropProvider(id);
74
+ const dragMouseMoveHandlerRef = useRef(void 0);
75
+ const dragMouseUpHandlerRef = useRef(void 0);
76
+ const attachDragHandlers = useCallback(()=>{
77
+ const { current: dragMove } = dragMouseMoveHandlerRef;
78
+ const { current: dragUp } = dragMouseUpHandlerRef;
79
+ if (dragMove && dragUp) {
80
+ document.addEventListener("mousemove", dragMove, false);
81
+ document.addEventListener("mouseup", dragUp, false);
82
+ }
83
+ }, []);
84
+ const removeDragHandlers = useCallback(()=>{
85
+ const { current: dragMove } = dragMouseMoveHandlerRef;
86
+ const { current: dragUp } = dragMouseUpHandlerRef;
87
+ if (dragMove && dragUp) {
88
+ document.removeEventListener("mousemove", dragMove, false);
89
+ document.removeEventListener("mouseup", dragUp, false);
90
+ }
91
+ }, []);
92
+ const setDragBoundaries = useCallback((containerRect, draggableRect)=>{
93
+ const { current: container } = containerRef;
94
+ if (container) {
95
+ const [lastElement, lastItemIsOverflowIndicator] = getLastElement(container, itemQuery);
96
+ const { CONTRA, CONTRA_END, DIMENSION, END, START } = dimensions(orientation);
97
+ const draggableSize = draggableRect[DIMENSION];
98
+ const { [START]: lastItemStart, [END]: lastItemEnd } = lastElement.getBoundingClientRect();
99
+ dragBoundaries.current.start = containerRect[START];
100
+ dragBoundaries.current.end = lastItemIsOverflowIndicator ? Math.max(lastItemStart, containerRect.right - draggableSize) : isScrollableRef.current ? containerRect[START] + containerRect[DIMENSION] - draggableSize : lastItemEnd - draggableSize;
101
+ dragBoundaries.current.contraStart = containerRect[CONTRA];
102
+ dragBoundaries.current.contraEnd = containerRect[CONTRA_END];
103
+ }
104
+ }, [
105
+ containerRef,
106
+ itemQuery,
107
+ orientation
108
+ ]);
109
+ const terminateDrag = useCallback(()=>{
110
+ const { current: settlingItem } = settlingItemRef;
111
+ settlingItemRef.current = null;
112
+ const { current: toIndex } = dropIndexRef;
113
+ const droppedItem = containerRef.current?.querySelector(`${itemQuery}[data-index="${toIndex}"]`);
114
+ if (droppedItem) droppedItem.classList.remove("vuuDropTarget-settling");
115
+ dropIndexRef.current = -1;
116
+ onDropSettle?.(toIndex);
117
+ setDraggableStatus((status)=>({
118
+ ...status,
119
+ draggable: void 0
120
+ }));
121
+ if (settlingItem) dispatchCustomEvent(settlingItem, "vuu-dropped");
122
+ }, [
123
+ containerRef,
124
+ itemQuery,
125
+ onDropSettle
126
+ ]);
127
+ const getScrollDirection = useCallback((mousePos)=>{
128
+ if (scrollableContainerRef.current && dragDropStateRef.current) {
129
+ const { mouseOffset } = dragDropStateRef.current;
130
+ const { POS, SCROLL_POS, SCROLL_SIZE, CLIENT_SIZE } = dimensions(orientation);
131
+ const { [SCROLL_POS]: scrollPos, [SCROLL_SIZE]: scrollSize, [CLIENT_SIZE]: clientSize } = scrollableContainerRef.current;
132
+ const maxScroll = scrollSize - clientSize;
133
+ const canScrollFwd = scrollPos < maxScroll;
134
+ const viewportEnd = dragBoundaries.current.end;
135
+ const bwd = scrollPos > 0 && mousePos - mouseOffset[POS] <= dragBoundaries.current.start;
136
+ const fwd = canScrollFwd && mousePos - mouseOffset[POS] >= viewportEnd;
137
+ return bwd ? "bwd" : fwd ? "fwd" : "";
138
+ }
139
+ }, [
140
+ scrollableContainerRef,
141
+ orientation
142
+ ]);
143
+ const useDragDropHook = true === allowDragDrop || "natural-movement" === allowDragDrop ? useDragDropNaturalMovement : "drop-indicator" === allowDragDrop ? useDragDropIndicator : "drag-copy" === allowDragDrop ? useDragDropCopy : noDragDrop;
144
+ const onScrollingStopped = useCallback((scrollDirection, scrollPos, atEnd)=>{
145
+ handleScrollStopRef.current?.(scrollDirection, scrollPos, atEnd);
146
+ }, []);
147
+ const { isScrolling, startScrolling, stopScrolling } = useAutoScroll({
148
+ containerRef: scrollableContainerRef,
149
+ onScrollingStopped,
150
+ orientation
151
+ });
152
+ const handleDrop = useCallback((options)=>{
153
+ dropPosRef.current = options.toIndex;
154
+ if (options.isExternal) onDrop?.({
155
+ ...options,
156
+ payload: dragDropStateRef.current?.payload
157
+ });
158
+ else onDrop?.(options);
159
+ dropIndexRef.current = options.toIndex;
160
+ if (id) onEndOfDragOperation?.(id);
161
+ dragDropStateRef.current = null;
162
+ }, [
163
+ id,
164
+ onDrop,
165
+ onEndOfDragOperation
166
+ ]);
167
+ const { beginDrag, drag, drop, handleScrollStart, handleScrollStop, releaseDrag, ...dragResult } = useDragDropHook({
168
+ ...dragDropProps,
169
+ containerRef,
170
+ isDragSource,
171
+ isDropTarget,
172
+ itemQuery,
173
+ orientation
174
+ });
175
+ handleScrollStopRef.current = handleScrollStop;
176
+ const dragHandedOvertoProvider = useCallback((dragDistance, clientContraPos)=>{
177
+ const { CONTRA_POS } = dimensions(orientation);
178
+ const lastClientContraPos = mousePosRef.current[CONTRA_POS];
179
+ const dragOutDistance = isDragSource ? Math.abs(lastClientContraPos - clientContraPos) : 0;
180
+ if (true === allowDragDrop && !isDragSource && !isDropTarget) return false;
181
+ const handoverToProvider = false === isDropTarget || dragOutDistance - dragDistance > 5;
182
+ if (dragDropStateRef.current && handoverToProvider) {
183
+ if (onDragOut?.(id, dragDropStateRef.current)) {
184
+ removeDragHandlers();
185
+ releaseDrag?.();
186
+ dragDropStateRef.current = null;
187
+ }
188
+ dragBoundaries.current = UNBOUNDED;
189
+ return true;
190
+ }
191
+ }, [
192
+ allowDragDrop,
193
+ id,
194
+ isDragSource,
195
+ isDropTarget,
196
+ onDragOut,
197
+ orientation,
198
+ releaseDrag,
199
+ removeDragHandlers
200
+ ]);
201
+ const dragMouseMoveHandler = useCallback((evt)=>{
202
+ const { CLIENT_POS, CONTRA_CLIENT_POS, POS } = dimensions(orientation);
203
+ const { clientX, clientY } = evt;
204
+ const { [CLIENT_POS]: clientPos, [CONTRA_CLIENT_POS]: clientContraPos } = evt;
205
+ const lastClientPos = mousePosRef.current[POS];
206
+ const dragDistance = Math.abs(lastClientPos - clientPos);
207
+ const { current: dragDropState } = dragDropStateRef;
208
+ const { current: boundary } = dragBoundaries;
209
+ if (dragHandedOvertoProvider(dragDistance, clientContraPos)) return;
210
+ mousePosRef.current.x = clientX;
211
+ mousePosRef.current.y = clientY;
212
+ if (dragDropState) {
213
+ const { draggableElement, mouseOffset } = dragDropState;
214
+ if (dragBoundaries.current === UNBOUNDED && draggableElement) {
215
+ const dragPosX = mousePosRef.current.x - mouseOffset.x;
216
+ const dragPosY = mousePosRef.current.y - mouseOffset.y;
217
+ draggableElement.style.top = `${dragPosY}px`;
218
+ draggableElement.style.left = `${dragPosX}px`;
219
+ } else if (dragDistance > 0 && draggableElement) {
220
+ const mouseMoveDirection = lastClientPos < clientPos ? "fwd" : "bwd";
221
+ const scrollDirection = getScrollDirection(clientPos);
222
+ const dragPos = mousePosRef.current[POS] - mouseOffset[POS];
223
+ const START = "horizontal" === orientation ? "left" : "top";
224
+ if (scrollDirection && isScrollableRef.current && !isScrolling.current) {
225
+ handleScrollStart?.(scrollDirection);
226
+ startScrolling(scrollDirection, 1);
227
+ if ("fwd" === scrollDirection) draggableElement.style[START] = `${boundary.end}px`;
228
+ else draggableElement.style[START] = `${boundary.start}px`;
229
+ } else if (!scrollDirection && isScrolling.current) stopScrolling();
230
+ if (!isScrolling.current) {
231
+ const renderDragPos = Math.round(Math.max(boundary.start, Math.min(boundary.end, dragPos)));
232
+ draggableElement.style[START] = `${renderDragPos}px`;
233
+ drag(renderDragPos, mouseMoveDirection);
234
+ }
235
+ }
236
+ }
237
+ }, [
238
+ drag,
239
+ dragHandedOvertoProvider,
240
+ getScrollDirection,
241
+ handleScrollStart,
242
+ isScrolling,
243
+ orientation,
244
+ startScrolling,
245
+ stopScrolling
246
+ ]);
247
+ const dragMouseUpHandler = useCallback(()=>{
248
+ removeDragHandlers();
249
+ if (dragDropStateRef.current) settlingItemRef.current = dragDropStateRef.current.draggableElement;
250
+ const dropOptions = drop();
251
+ handleDrop(dropOptions);
252
+ setDraggableStatus((status)=>({
253
+ ...status,
254
+ draggedItemIndex: -1,
255
+ isDragging: false
256
+ }));
257
+ }, [
258
+ drop,
259
+ handleDrop,
260
+ removeDragHandlers
261
+ ]);
262
+ dragMouseMoveHandlerRef.current = dragMouseMoveHandler;
263
+ dragMouseUpHandlerRef.current = dragMouseUpHandler;
264
+ const resumeDrag = useCallback((dragDropState)=>{
265
+ dragDropStateRef.current = dragDropState;
266
+ const { draggableElement, mouseOffset } = dragDropState;
267
+ const { current: container } = containerRef;
268
+ if (!container || !draggableElement) return false;
269
+ {
270
+ const containerRect = container.getBoundingClientRect();
271
+ const draggableRect = draggableElement.getBoundingClientRect();
272
+ setDragBoundaries(containerRect, draggableRect);
273
+ mousePosRef.current.x = draggableRect.left + mouseOffset.x;
274
+ mousePosRef.current.y = draggableRect.top + mouseOffset.y;
275
+ beginDrag(draggableElement);
276
+ attachDragHandlers();
277
+ return true;
278
+ }
279
+ }, [
280
+ attachDragHandlers,
281
+ beginDrag,
282
+ containerRef,
283
+ setDragBoundaries
284
+ ]);
285
+ const dragStart = useCallback((mousePosition)=>{
286
+ const { current: container } = containerRef;
287
+ const { current: target } = mousedownElementRef;
288
+ const dragElement = getDraggableElement(target, itemQuery);
289
+ const scrollableContainer = scrollingContainerRef?.current ?? getScrollableContainer(container, itemQuery);
290
+ if (container && scrollableContainer && dragElement) {
291
+ isScrollableRef.current = isContainerScrollable(scrollableContainer, orientation);
292
+ scrollableContainerRef.current = scrollableContainer;
293
+ const containerRect = scrollableContainer.getBoundingClientRect();
294
+ const draggableRect = dragElement.getBoundingClientRect();
295
+ const dragDropState = dragDropStateRef.current = new DragDropState(mousePosition, dragElement);
296
+ setDragBoundaries(containerRect, draggableRect);
297
+ beginDrag(dragElement);
298
+ const { dataset: { index = "-1" } } = dragElement;
299
+ setDraggableStatus({
300
+ isDragging: true,
301
+ draggable: /*#__PURE__*/ jsx(Draggable, {
302
+ element: cloneElement(dragElement),
303
+ onDropped: terminateDrag,
304
+ onTransitionEnd: terminateDrag,
305
+ ref: dragDropState.setDraggable,
306
+ style: constrainRect(draggableRect, containerRect),
307
+ wrapperClassName: draggableClassName
308
+ }),
309
+ draggedItemIndex: parseInt(index)
310
+ });
311
+ onDragStart?.(dragDropState);
312
+ attachDragHandlers();
313
+ mousedownElementRef.current = null;
314
+ }
315
+ }, [
316
+ attachDragHandlers,
317
+ beginDrag,
318
+ containerRef,
319
+ draggableClassName,
320
+ itemQuery,
321
+ onDragStart,
322
+ orientation,
323
+ scrollingContainerRef,
324
+ setDragBoundaries,
325
+ terminateDrag
326
+ ]);
327
+ const preDragMouseMoveHandler = useCallback((evt)=>{
328
+ const { current: mouseDownPosition } = startPosRef;
329
+ const { CLIENT_POS, POS } = dimensions(orientation);
330
+ const { [CLIENT_POS]: clientPos } = evt;
331
+ const mouseMoveDistance = Math.abs(clientPos - mouseDownPosition[POS]);
332
+ if (mouseMoveDistance > dragThreshold && containerRef.current) {
333
+ if (mouseDownTimer.current) {
334
+ window.clearTimeout(mouseDownTimer.current);
335
+ mouseDownTimer.current = null;
336
+ }
337
+ document.removeEventListener("mousemove", preDragMouseMoveHandler);
338
+ document.removeEventListener("mouseup", preDragMouseUpHandler, false);
339
+ const mousePosition = {
340
+ clientX: mouseDownPosition.x,
341
+ clientY: mouseDownPosition.y
342
+ };
343
+ dragStart(mousePosition);
344
+ }
345
+ }, [
346
+ containerRef,
347
+ beginDrag,
348
+ orientation
349
+ ]);
350
+ const preDragMouseUpHandler = useCallback(()=>{
351
+ if (mouseDownTimer.current) {
352
+ window.clearTimeout(mouseDownTimer.current);
353
+ mouseDownTimer.current = null;
354
+ }
355
+ document.removeEventListener("mousemove", preDragMouseMoveHandler, false);
356
+ document.removeEventListener("mouseup", preDragMouseUpHandler, false);
357
+ }, [
358
+ preDragMouseMoveHandler
359
+ ]);
360
+ const mouseDownHandler = useCallback((evt)=>{
361
+ if (0 !== evt.button) return;
362
+ const { current: container } = containerRef;
363
+ evt.stopPropagation();
364
+ if (container && !evt.defaultPrevented) {
365
+ const { clientX, clientY } = evt;
366
+ mousePosRef.current.x = startPosRef.current.x = clientX;
367
+ mousePosRef.current.y = startPosRef.current.y = clientY;
368
+ mousedownElementRef.current = evt.target;
369
+ const mousePosition = {
370
+ clientX,
371
+ clientY
372
+ };
373
+ document.addEventListener("mousemove", preDragMouseMoveHandler, false);
374
+ document.addEventListener("mouseup", preDragMouseUpHandler, false);
375
+ evt.persist();
376
+ mouseDownTimer.current = window.setTimeout(()=>{
377
+ document.removeEventListener("mousemove", preDragMouseMoveHandler, false);
378
+ document.removeEventListener("mouseup", preDragMouseUpHandler, false);
379
+ dragStart(mousePosition);
380
+ }, 500);
381
+ }
382
+ }, [
383
+ containerRef,
384
+ dragStart,
385
+ preDragMouseMoveHandler,
386
+ preDragMouseUpHandler
387
+ ]);
388
+ const { current: settlingItem } = settlingItemRef;
389
+ useLayoutEffect(()=>{
390
+ if (settlingItem && containerRef.current) {
391
+ const dropPos = dropPosRef.current;
392
+ const droppedItem = containerRef.current.querySelector(`${itemQuery}[data-index="${dropPos}"]`);
393
+ if (droppedItem) {
394
+ droppedItem.classList.add("vuuDropTarget-settling");
395
+ requestAnimationFrame(()=>{
396
+ const { top: targetTop, left: targetLeft } = droppedItem.getBoundingClientRect();
397
+ const style = getComputedStyle(settlingItem);
398
+ const currentLeft = parseInt(style.getPropertyValue("left"));
399
+ const currentTop = parseInt(style.getPropertyValue("top"));
400
+ if (currentLeft !== targetLeft || currentTop !== targetTop) {
401
+ settlingItem.classList.add("vuuDraggable-settling");
402
+ settlingItem.style.top = `${targetTop}px`;
403
+ settlingItem.style.left = `${targetLeft}px`;
404
+ } else terminateDrag();
405
+ });
406
+ } else setDraggableStatus((status)=>({
407
+ ...status,
408
+ draggable: void 0
409
+ }));
410
+ }
411
+ }, [
412
+ containerRef,
413
+ itemQuery,
414
+ settlingItem,
415
+ terminateDrag
416
+ ]);
417
+ useEffect(()=>{
418
+ if (id && (isDragSource || isDropTarget)) register(id, "drop-only" === allowDragDrop ? false : resumeDrag, onDrop);
419
+ }, [
420
+ allowDragDrop,
421
+ id,
422
+ isDragSource,
423
+ isDropTarget,
424
+ onDrop,
425
+ register,
426
+ resumeDrag
427
+ ]);
428
+ return {
429
+ ...dragResult,
430
+ ...draggableStatus,
431
+ isScrolling,
432
+ onMouseDown: allowDragDrop && "drop-only" !== allowDragDrop ? mouseDownHandler : void 0
433
+ };
434
+ };
435
+ export { useDragDrop };
@@ -0,0 +1,22 @@
1
+ import { useCallback, useRef } from "react";
2
+ const NULL_DROP_OPTIONS = {
3
+ fromIndex: -1,
4
+ toIndex: -1
5
+ };
6
+ const useDragDropCopy = ({ selected, viewportRange })=>{
7
+ const rangeRef = useRef(void 0);
8
+ rangeRef.current = viewportRange;
9
+ const beginDrag = useCallback((dragElement)=>{
10
+ if (dragElement.ariaSelected && Array.isArray(selected) && selected.length > 1) console.log("its a selected element, and we have a multi select");
11
+ }, [
12
+ selected
13
+ ]);
14
+ const drag = useCallback(()=>void 0, []);
15
+ const drop = useCallback(()=>NULL_DROP_OPTIONS, []);
16
+ return {
17
+ beginDrag,
18
+ drag,
19
+ drop
20
+ };
21
+ };
22
+ export { NULL_DROP_OPTIONS, useDragDropCopy };