@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,25 @@
1
+ const css = `
2
+ .saltDatePickerPanel {
3
+ background: var(--salt-container-primary-background);
4
+ border: var(--salt-size-border) var(--salt-selectable-borderStyle-selected) var(--salt-selectable-borderColor-selected);
5
+ z-index: var(--salt-zIndex-flyover);
6
+ box-shadow: var(--salt-overlayable-shadow-popout);
7
+ box-sizing: border-box;
8
+ border-radius: var(--salt-palette-corner, 0);
9
+ display: flex;
10
+ position: relative;
11
+ overflow: hidden auto;
12
+ }
13
+
14
+ .saltDatePickerPanel-container {
15
+ gap: 1px;
16
+ width: min-content;
17
+ }
18
+
19
+ .saltDatePickerPanel-header {
20
+ padding: var(--salt-spacing-100);
21
+ }
22
+
23
+
24
+ `;
25
+ export default css;
@@ -0,0 +1,124 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { endOfMonth, startOfMonth } from "@internationalized/date";
3
+ import { FlexItem, FlexLayout, FormFieldContext, FormFieldHelperText, StackLayout, makePrefixer, useFloatingComponent, useFormFieldProps } from "@salt-ds/core";
4
+ import { useComponentCssInjection } from "@salt-ds/styles";
5
+ import { useWindow } from "@salt-ds/window";
6
+ import { clsx } from "clsx";
7
+ import { forwardRef, useEffect, useState } from "react";
8
+ import { Calendar, isRangeOrOffsetSelectionWithStartDate } from "../calendar/index.js";
9
+ import { useDatePickerContext } from "./DatePickerContext.js";
10
+ import DatePickerPanel_0 from "./DatePickerPanel.css";
11
+ const withBaseName = makePrefixer("saltDatePickerPanel");
12
+ function getHoveredDate(date, compact, hoveredDate) {
13
+ return date && !compact && hoveredDate && hoveredDate.compare(endOfMonth(date)) > 0 ? endOfMonth(date) : hoveredDate;
14
+ }
15
+ const DatePickerPanel_DatePickerPanel = /*#__PURE__*/ forwardRef(function(props, ref) {
16
+ const { className, onSelect, helperText, CalendarProps, visibleMonths, ...rest } = props;
17
+ const targetWindow = useWindow();
18
+ useComponentCssInjection({
19
+ testId: "salt-date-picker-panel",
20
+ css: DatePickerPanel_0,
21
+ window: targetWindow
22
+ });
23
+ const { Component: FloatingComponent } = useFloatingComponent();
24
+ const [hoveredDate, setHoveredDate] = useState(null);
25
+ const { openState, selectedDate, setSelectedDate, startVisibleMonth, setStartVisibleMonth, endVisibleMonth, setEndVisibleMonth, setOpen, context, getPanelPosition, selectionVariant } = useDatePickerContext();
26
+ const { a11yProps } = useFormFieldProps();
27
+ const isRangePicker = isRangeOrOffsetSelectionWithStartDate(selectedDate) || "range" === selectionVariant && void 0 === selectedDate;
28
+ const compact = 1 === visibleMonths;
29
+ const setRangeDate = (event, newDate)=>{
30
+ setSelectedDate(newDate);
31
+ onSelect?.(event, newDate);
32
+ if (newDate.startDate && newDate.endDate) setOpen(false);
33
+ };
34
+ const setSingleDate = (event, newDate)=>{
35
+ setSelectedDate(newDate);
36
+ onSelect?.(event, newDate);
37
+ setOpen(false);
38
+ };
39
+ const handleHoveredDateChange = (_, newHoveredDate)=>{
40
+ setHoveredDate(newHoveredDate);
41
+ };
42
+ useEffect(()=>{
43
+ if (isRangePicker) {
44
+ if (selectedDate?.startDate) {
45
+ setStartVisibleMonth(selectedDate.startDate);
46
+ setEndVisibleMonth(selectedDate.startDate.add({
47
+ months: 1
48
+ }));
49
+ }
50
+ } else setStartVisibleMonth(selectedDate);
51
+ }, [
52
+ isRangePicker,
53
+ selectedDate,
54
+ setEndVisibleMonth,
55
+ setStartVisibleMonth
56
+ ]);
57
+ const firstCalendarProps = isRangePicker ? {
58
+ selectionVariant: "range",
59
+ hoveredDate: getHoveredDate(selectedDate?.startDate, compact, hoveredDate),
60
+ onHoveredDateChange: handleHoveredDateChange,
61
+ selectedDate: selectedDate,
62
+ onSelectedDateChange: setRangeDate,
63
+ maxDate: !compact && selectedDate?.startDate ? endOfMonth(selectedDate?.startDate) : void 0,
64
+ hideOutOfRangeDates: true
65
+ } : {
66
+ selectionVariant: "default",
67
+ selectedDate: selectedDate,
68
+ onSelectedDateChange: setSingleDate
69
+ };
70
+ return /*#__PURE__*/ jsx(FloatingComponent, {
71
+ open: openState,
72
+ className: clsx(withBaseName(), className),
73
+ "aria-modal": "true",
74
+ ref: ref,
75
+ focusManagerProps: context ? {
76
+ context: context,
77
+ initialFocus: 4
78
+ } : void 0,
79
+ ...getPanelPosition(),
80
+ ...a11yProps,
81
+ ...rest,
82
+ children: /*#__PURE__*/ jsxs(StackLayout, {
83
+ separators: true,
84
+ gap: 0,
85
+ className: withBaseName("container"),
86
+ children: [
87
+ helperText && /*#__PURE__*/ jsx(FlexItem, {
88
+ className: withBaseName("header"),
89
+ children: /*#__PURE__*/ jsx(FormFieldHelperText, {
90
+ children: helperText
91
+ })
92
+ }),
93
+ /*#__PURE__*/ jsx(FlexLayout, {
94
+ children: /*#__PURE__*/ jsxs(FormFieldContext.Provider, {
95
+ value: {},
96
+ children: [
97
+ /*#__PURE__*/ jsx(Calendar, {
98
+ visibleMonth: startVisibleMonth,
99
+ onVisibleMonthChange: (_, month)=>setStartVisibleMonth(month),
100
+ ...firstCalendarProps,
101
+ ...CalendarProps
102
+ }),
103
+ isRangePicker && !compact && /*#__PURE__*/ jsx(Calendar, {
104
+ selectionVariant: "range",
105
+ hoveredDate: hoveredDate,
106
+ onHoveredDateChange: handleHoveredDateChange,
107
+ selectedDate: selectedDate,
108
+ onSelectedDateChange: setRangeDate,
109
+ visibleMonth: endVisibleMonth,
110
+ onVisibleMonthChange: (_, month)=>setEndVisibleMonth(month),
111
+ hideOutOfRangeDates: true,
112
+ minDate: selectedDate?.startDate ? startOfMonth(selectedDate?.startDate)?.add({
113
+ months: 1
114
+ }) : void 0,
115
+ ...CalendarProps
116
+ })
117
+ ]
118
+ })
119
+ })
120
+ ]
121
+ })
122
+ });
123
+ });
124
+ export { DatePickerPanel_DatePickerPanel as DatePickerPanel };
@@ -0,0 +1 @@
1
+ export * from "./DatePicker.js";
@@ -0,0 +1,123 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { createContext, useCallback, useContext, useMemo } from "react";
3
+ import { useGlobalDragDrop } from "./useGlobalDragDrop.js";
4
+ const NO_DRAG_CONTEXT = {
5
+ isDragSource: void 0,
6
+ isDropTarget: void 0,
7
+ register: ()=>void 0
8
+ };
9
+ const unconfiguredRegistrationCall = ()=>console.log("have you forgotten to provide a DragDrop Provider ?");
10
+ const DragDropContext = /*#__PURE__*/ createContext({
11
+ registerDragDropParty: unconfiguredRegistrationCall
12
+ });
13
+ const measureDropTargets = (dropTargetIds = [])=>dropTargetIds.reduce((map, id)=>{
14
+ const el = document.getElementById(id);
15
+ if (el) {
16
+ const { top, right, bottom, left } = el.getBoundingClientRect();
17
+ map[id] = {
18
+ top,
19
+ right,
20
+ bottom,
21
+ left
22
+ };
23
+ }
24
+ return map;
25
+ }, {});
26
+ const DragDropProvider = ({ children, dragSources: dragSourcesProp })=>{
27
+ const resumeDragHandlers = useMemo(()=>new Map(), []);
28
+ const dropHandlers = useMemo(()=>new Map(), []);
29
+ const handleDragOverDropTarget = useCallback((dropTargetId, dragDropState)=>{
30
+ const resumeDrag = resumeDragHandlers.get(dropTargetId);
31
+ if (resumeDrag) return resumeDrag(dragDropState);
32
+ return false;
33
+ }, [
34
+ resumeDragHandlers
35
+ ]);
36
+ const handleDrop = useCallback((dropTargetId, dragDropState)=>{
37
+ const handleDrop = dropHandlers.get(dropTargetId);
38
+ if (handleDrop) handleDrop(dragDropState);
39
+ }, [
40
+ dropHandlers
41
+ ]);
42
+ const { measuredDropTargetsRef, resumeDrag } = useGlobalDragDrop({
43
+ onDragOverDropTarget: handleDragOverDropTarget,
44
+ onDrop: handleDrop
45
+ });
46
+ const [dragSources, dropTargets] = useMemo(()=>{
47
+ const sources = new Map();
48
+ const targets = new Map();
49
+ for (const [sourceId, { dropTargets }] of Object.entries(dragSourcesProp)){
50
+ const sourceEntry = sources.get(sourceId);
51
+ const targetIds = Array.isArray(dropTargets) ? dropTargets : [
52
+ dropTargets
53
+ ];
54
+ if (sourceEntry) sourceEntry.push(...targetIds);
55
+ else sources.set(sourceId, targetIds);
56
+ for (const targetId of targetIds){
57
+ const targetEntry = targets.get(targetId);
58
+ if (targetEntry) targetEntry.push(sourceId);
59
+ else targets.set(targetId, [
60
+ sourceId
61
+ ]);
62
+ }
63
+ }
64
+ return [
65
+ sources,
66
+ targets
67
+ ];
68
+ }, [
69
+ dragSourcesProp
70
+ ]);
71
+ const onDragOut = useCallback((id, dragDropState)=>{
72
+ measuredDropTargetsRef.current = measureDropTargets(dragSources.get(id));
73
+ resumeDrag(dragDropState);
74
+ return true;
75
+ }, [
76
+ dragSources,
77
+ measuredDropTargetsRef,
78
+ resumeDrag
79
+ ]);
80
+ const onEndOfDragOperation = useCallback((id)=>{
81
+ console.log(`end of drag operation, id= ${id}`);
82
+ }, []);
83
+ const registerDragDropParty = useCallback((id, resumeDrag, onDrop)=>{
84
+ if (resumeDrag) resumeDragHandlers.set(id, resumeDrag);
85
+ else if (onDrop) dropHandlers.set(id, onDrop);
86
+ }, [
87
+ dropHandlers,
88
+ resumeDragHandlers
89
+ ]);
90
+ const contextValue = useMemo(()=>({
91
+ dragSources,
92
+ dropTargets,
93
+ onDragOut,
94
+ onEndOfDragOperation,
95
+ registerDragDropParty
96
+ }), [
97
+ dragSources,
98
+ dropTargets,
99
+ onDragOut,
100
+ onEndOfDragOperation,
101
+ registerDragDropParty
102
+ ]);
103
+ return /*#__PURE__*/ jsx(DragDropContext.Provider, {
104
+ value: contextValue,
105
+ children: children
106
+ });
107
+ };
108
+ const useDragDropProvider = (id)=>{
109
+ const { dragSources, dropTargets, onDragOut, onEndOfDragOperation, registerDragDropParty } = useContext(DragDropContext);
110
+ if (!id || !dragSources && !dropTargets) return NO_DRAG_CONTEXT;
111
+ {
112
+ const isDragSource = dragSources?.has(id) ?? false;
113
+ const isDropTarget = dropTargets?.has(id) ?? false;
114
+ return {
115
+ isDragSource,
116
+ isDropTarget,
117
+ onDragOut,
118
+ onEndOfDragOperation,
119
+ register: registerDragDropParty
120
+ };
121
+ }
122
+ };
123
+ export { DragDropProvider, useDragDropProvider };
@@ -0,0 +1,25 @@
1
+ class DragDropState {
2
+ mouseOffset;
3
+ initialDragElement;
4
+ draggableElement = null;
5
+ payload = null;
6
+ constructor(mousePosition, dragElement){
7
+ this.initialDragElement = dragElement;
8
+ this.mouseOffset = this.getMouseOffset(mousePosition, dragElement);
9
+ }
10
+ setDraggable = (el)=>{
11
+ this.draggableElement = el;
12
+ };
13
+ setPayload(payload) {
14
+ this.payload = payload;
15
+ }
16
+ getMouseOffset(mousePosition, dragElement) {
17
+ const { clientX, clientY } = mousePosition;
18
+ const draggableRect = dragElement.getBoundingClientRect();
19
+ return {
20
+ x: clientX - draggableRect.left,
21
+ y: clientY - draggableRect.top
22
+ };
23
+ }
24
+ }
25
+ export { DragDropState };
@@ -0,0 +1,57 @@
1
+ const css = `
2
+ .vuuDraggable {
3
+ box-shadow: var(--salt-overlayable-shadow-drag);
4
+ cursor: var(--salt-draggable-grab-cursor-active);
5
+ opacity: .95;
6
+ z-index: 2000;
7
+ background: none;
8
+ position: absolute;
9
+ }
10
+
11
+ .vuuDraggable-spacer {
12
+ display: var(--vuuDraggable-display, inline-block);
13
+ height: var(--vuuDraggable-spacer-height, var(--tabstrip-height));
14
+ transition: var(--vuuDraggable-transitionProp, width) .3s ease;
15
+ width: var(--vuuDraggable-spacer-width, 0);
16
+ }
17
+
18
+ .vuuDraggable-dropIndicatorPosition {
19
+ display: var(--saltDraggable-display, inline-block);
20
+ width: 100%;
21
+ height: 0;
22
+ }
23
+
24
+ .vuuDraggable-dropIndicatorContainer {
25
+ transition: var(--vuuDraggable-transitionProp, top) .2s ease;
26
+ }
27
+
28
+ .vuuDraggable-dropIndicator {
29
+ background-color: var(--salt-palette-accent-background);
30
+ width: 100%;
31
+ height: 2px;
32
+ }
33
+
34
+ .vuuDraggable-dropIndicator:before {
35
+ content: "";
36
+ background-color: var(--salt-palette-accent-background);
37
+ border-radius: 3px;
38
+ width: 6px;
39
+ height: 6px;
40
+ position: absolute;
41
+ top: -2px;
42
+ left: -3px;
43
+ }
44
+
45
+ .vuuDraggable-settling {
46
+ transition-property: left, top;
47
+ transition-duration: .15s;
48
+ transition-timing-function: ease-out;
49
+ }
50
+
51
+ .vuuDraggable-spacer {
52
+ order: 1;
53
+ }
54
+
55
+
56
+ `;
57
+ export default css;
@@ -0,0 +1,77 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useForkRef } from "@salt-ds/core";
3
+ import clsx from "clsx";
4
+ import { useComponentCssInjection } from "@salt-ds/styles";
5
+ import { useWindow } from "@salt-ds/window";
6
+ import { forwardRef, useCallback, useMemo } from "react";
7
+ import { PopupComponent, Portal } from "@vuu-ui/vuu-popups";
8
+ import Draggable_0 from "./Draggable.css";
9
+ const makeClassNames = (classNames)=>classNames.split(" ").map((className)=>`vuuDraggable-${className}`);
10
+ const Draggable_Draggable = /*#__PURE__*/ forwardRef(function({ wrapperClassName, element, onDropped, onTransitionEnd, style, scale = 1 }, forwardedRef) {
11
+ const targetWindow = useWindow();
12
+ useComponentCssInjection({
13
+ testId: "vuu-draggable",
14
+ css: Draggable_0,
15
+ window: targetWindow
16
+ });
17
+ const handleVuuDrop = useCallback(()=>{
18
+ onDropped?.();
19
+ }, [
20
+ onDropped
21
+ ]);
22
+ const callbackRef = useCallback((el)=>{
23
+ if (el) {
24
+ el.innerHTML = "";
25
+ el.appendChild(element);
26
+ if (1 !== scale) el.style.transform = `scale(${scale},${scale})`;
27
+ el.addEventListener("vuu-dropped", handleVuuDrop);
28
+ }
29
+ }, [
30
+ element,
31
+ handleVuuDrop,
32
+ scale
33
+ ]);
34
+ const forkedRef = useForkRef(forwardedRef, callbackRef);
35
+ const position = useMemo(()=>({
36
+ left: 0,
37
+ top: 0
38
+ }), []);
39
+ return /*#__PURE__*/ jsx(Portal, {
40
+ children: /*#__PURE__*/ jsx(PopupComponent, {
41
+ anchorElement: {
42
+ current: document.body
43
+ },
44
+ className: "vuuPopup",
45
+ placement: "absolute",
46
+ position: position,
47
+ children: /*#__PURE__*/ jsx("div", {
48
+ className: clsx("vuuDraggable", ...makeClassNames(wrapperClassName)),
49
+ ref: forkedRef,
50
+ onTransitionEnd: onTransitionEnd,
51
+ style: style
52
+ })
53
+ })
54
+ });
55
+ });
56
+ const createDragSpacer = (transitioning)=>{
57
+ const spacer = document.createElement("div");
58
+ spacer.className = "vuuDraggable-spacer";
59
+ if (transitioning) spacer.addEventListener("transitionend", ()=>{
60
+ transitioning.current = false;
61
+ });
62
+ return spacer;
63
+ };
64
+ const createDropIndicatorPosition = ()=>{
65
+ const spacer = document.createElement("div");
66
+ spacer.className = "vuuDraggable-dropIndicatorPosition";
67
+ return spacer;
68
+ };
69
+ const createDropIndicator = (transitioning)=>{
70
+ const spacer = document.createElement("div");
71
+ spacer.className = "vuuDraggable-dropIndicator";
72
+ if (transitioning) spacer.addEventListener("transitionend", ()=>{
73
+ transitioning.current = false;
74
+ });
75
+ return spacer;
76
+ };
77
+ export { Draggable_Draggable as Draggable, createDragSpacer, createDropIndicator, createDropIndicatorPosition };
@@ -0,0 +1,11 @@
1
+ const css = `
2
+ .vuuDropIndicator {
3
+ background: var(--salt-accent-background);
4
+ cursor: move;
5
+ position: absolute;
6
+ transform: translate(-4px);
7
+ }
8
+
9
+
10
+ `;
11
+ export default css;
@@ -0,0 +1,28 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { Portal } from "@vuu-ui/vuu-popups";
3
+ import { useComponentCssInjection } from "@salt-ds/styles";
4
+ import { useWindow } from "@salt-ds/window";
5
+ import { forwardRef } from "react";
6
+ import DropIndicator_0 from "./DropIndicator.css";
7
+ const DropIndicator_DropIndicator = /*#__PURE__*/ forwardRef(function({ rect }, forwardedRef) {
8
+ const targetWindow = useWindow();
9
+ useComponentCssInjection({
10
+ testId: "vuu-drop-indicator",
11
+ css: DropIndicator_0,
12
+ window: targetWindow
13
+ });
14
+ const { left, top, width, height } = rect;
15
+ return /*#__PURE__*/ jsx(Portal, {
16
+ children: /*#__PURE__*/ jsx("div", {
17
+ className: "vuuDropIndicator",
18
+ ref: forwardedRef,
19
+ style: {
20
+ left,
21
+ top,
22
+ width,
23
+ height
24
+ }
25
+ })
26
+ });
27
+ });
28
+ export { DropIndicator_DropIndicator as DropIndicator };
@@ -0,0 +1,3 @@
1
+ const FWD = "fwd";
2
+ const BWD = "bwd";
3
+ export { BWD, FWD };
@@ -0,0 +1,199 @@
1
+ const LEFT_RIGHT = [
2
+ "left",
3
+ "right"
4
+ ];
5
+ const TOP_BOTTOM = [
6
+ "top",
7
+ "bottom"
8
+ ];
9
+ const NOT_OVERFLOWED = ":not(.wrapped)";
10
+ const NOT_HIDDEN = ':not([aria-hidden="true"])';
11
+ const cloneElement = (element)=>{
12
+ const dolly = element.cloneNode(true);
13
+ dolly.removeAttribute("id");
14
+ dolly.dataset.index = "-1";
15
+ return dolly;
16
+ };
17
+ const measureElementSizeAndPosition = (element, dimension = "width", includeAutoMargin = false)=>{
18
+ const pos = "width" === dimension ? "left" : "top";
19
+ const { [dimension]: size, [pos]: position } = element.getBoundingClientRect();
20
+ const { padEnd = false, padStart = false } = element.dataset;
21
+ const style = getComputedStyle(element);
22
+ const [start, end] = "width" === dimension ? LEFT_RIGHT : TOP_BOTTOM;
23
+ const marginStart = padStart && !includeAutoMargin ? 0 : parseInt(style.getPropertyValue(`margin-${start}`), 10);
24
+ const marginEnd = padEnd && !includeAutoMargin ? 0 : parseInt(style.getPropertyValue(`margin-${end}`), 10);
25
+ let minWidth = size;
26
+ const flexShrink = parseInt(style.getPropertyValue("flex-shrink"), 10);
27
+ if (flexShrink > 0) {
28
+ const flexBasis = parseInt(style.getPropertyValue("flex-basis"), 10);
29
+ if (!isNaN(flexBasis) && flexBasis > 0) minWidth = flexBasis;
30
+ }
31
+ return [
32
+ position,
33
+ marginStart + minWidth + marginEnd
34
+ ];
35
+ };
36
+ const DIMENSIONS = {
37
+ horizontal: {
38
+ CLIENT_POS: "clientX",
39
+ CLIENT_SIZE: "clientWidth",
40
+ CONTRA: "top",
41
+ CONTRA_CLIENT_POS: "clientY",
42
+ CONTRA_END: "bottom",
43
+ CONTRA_POS: "y",
44
+ DIMENSION: "width",
45
+ END: "right",
46
+ POS: "x",
47
+ SCROLL_POS: "scrollLeft",
48
+ SCROLL_SIZE: "scrollWidth",
49
+ START: "left"
50
+ },
51
+ vertical: {
52
+ CLIENT_POS: "clientY",
53
+ CLIENT_SIZE: "clientHeight",
54
+ CONTRA: "left",
55
+ CONTRA_CLIENT_POS: "clientX",
56
+ CONTRA_END: "right",
57
+ CONTRA_POS: "x",
58
+ DIMENSION: "height",
59
+ END: "bottom",
60
+ POS: "y",
61
+ SCROLL_POS: "scrollTop",
62
+ SCROLL_SIZE: "scrollHeight",
63
+ START: "top"
64
+ }
65
+ };
66
+ const dimensions = (orientation)=>DIMENSIONS[orientation];
67
+ const getItemById = (measuredItems, id)=>{
68
+ const result = measuredItems.find((item)=>item.id === id);
69
+ if (result) return result;
70
+ };
71
+ const removeDraggedItem = (measuredItems, index)=>{
72
+ measuredItems.splice(index, 1);
73
+ for(let i = index; i < measuredItems.length; i++)measuredItems[i].currentIndex -= 1;
74
+ };
75
+ const measureDropTargets = (container, orientation, itemQuery, viewportRange, draggedItemId)=>{
76
+ const dragThresholds = [];
77
+ const { DIMENSION } = dimensions(orientation);
78
+ const children = Array.from(itemQuery ? container.querySelectorAll(itemQuery) : container.children);
79
+ const itemCount = children.length;
80
+ const start = "number" == typeof viewportRange?.from ? viewportRange.atEnd ? Math.max(0, viewportRange.from - 1) : viewportRange.from : 0;
81
+ const end = "number" == typeof viewportRange?.to ? Math.min(viewportRange.to + 2, itemCount - 1) : itemCount - 1;
82
+ for(let index = start; index <= end; index++){
83
+ const element = children[index];
84
+ const [start, size] = measureElementSizeAndPosition(element, DIMENSION);
85
+ const isLast = index === itemCount - 1;
86
+ const id = element.id;
87
+ dragThresholds.push({
88
+ currentIndex: index,
89
+ id,
90
+ index,
91
+ isDraggedItem: draggedItemId === id,
92
+ isLast,
93
+ isOverflowIndicator: "overflow" === element.dataset.index,
94
+ element: element,
95
+ start,
96
+ end: start + size,
97
+ size,
98
+ mid: start + size / 2
99
+ });
100
+ }
101
+ return dragThresholds;
102
+ };
103
+ const getIndexOfDraggedItem = (dropTargets)=>dropTargets.findIndex((d)=>d.isDraggedItem);
104
+ const mutateDropTargetsSwitchDropTargetPosition = (dropTargets, direction)=>{
105
+ const indexOfDraggedItem = getIndexOfDraggedItem(dropTargets);
106
+ const indexOfTarget = "fwd" === direction ? indexOfDraggedItem + 1 : indexOfDraggedItem - 1;
107
+ if (indexOfTarget < 0 || indexOfTarget >= dropTargets.length) throw Error("switchDropTargetPosition index out of range");
108
+ const draggedItem = dropTargets.at(indexOfDraggedItem);
109
+ const targetItem = dropTargets.at(indexOfTarget);
110
+ const diff = targetItem.size - draggedItem.size;
111
+ if ("fwd" === direction) {
112
+ const draggedStart = targetItem.start + diff;
113
+ const draggedEnd = targetItem.end;
114
+ const newDraggedItem = {
115
+ ...draggedItem,
116
+ start: draggedStart,
117
+ mid: Math.floor(draggedStart + (draggedEnd - draggedStart) / 2),
118
+ end: draggedEnd
119
+ };
120
+ const targetStart = draggedItem.start;
121
+ const targetEnd = draggedItem.end + diff;
122
+ const newTargetItem = {
123
+ ...targetItem,
124
+ start: targetStart,
125
+ mid: Math.floor(targetStart + (targetEnd - targetStart) / 2),
126
+ end: targetEnd
127
+ };
128
+ dropTargets.splice(indexOfDraggedItem, 2, newTargetItem, newDraggedItem);
129
+ } else {
130
+ const draggedStart = targetItem.start;
131
+ const draggedEnd = targetItem.end - diff;
132
+ const newDraggedItem = {
133
+ ...draggedItem,
134
+ start: draggedStart,
135
+ mid: Math.floor(draggedStart + (draggedEnd - draggedStart) / 2),
136
+ end: draggedEnd
137
+ };
138
+ const targetStart = draggedItem.start - diff;
139
+ const targetEnd = draggedItem.end;
140
+ const newTargetItem = {
141
+ ...targetItem,
142
+ start: targetStart,
143
+ mid: Math.floor(targetStart + (targetEnd - targetStart) / 2),
144
+ end: targetEnd
145
+ };
146
+ dropTargets.splice(indexOfTarget, 2, newDraggedItem, newTargetItem);
147
+ }
148
+ };
149
+ const getNextDropTarget = (dropTargets, pos, draggedItemSize, mouseMoveDirection)=>{
150
+ const len = dropTargets.length;
151
+ const indexOfDraggedItem = getIndexOfDraggedItem(dropTargets);
152
+ const draggedItem = dropTargets[indexOfDraggedItem];
153
+ if ("fwd" === mouseMoveDirection) {
154
+ const leadingEdge = Math.round(pos + draggedItemSize);
155
+ for(let index = len - 1; index >= 0; index--){
156
+ const dropTarget = dropTargets[index];
157
+ if (leadingEdge > dropTarget.mid) if (draggedItem && index < indexOfDraggedItem) return draggedItem;
158
+ else return dropTarget;
159
+ }
160
+ } else {
161
+ const leadingEdge = Math.round(pos);
162
+ for(let index = 0; index < len; index++){
163
+ const dropTarget = dropTargets[index];
164
+ if (leadingEdge < dropTarget.mid) if (index > indexOfDraggedItem) return draggedItem;
165
+ else return dropTarget;
166
+ }
167
+ }
168
+ throw Error("no dropTarget identified");
169
+ };
170
+ function constrainRect(targetRect, constraintRect) {
171
+ const { height, left, top, width } = targetRect;
172
+ const { height: constrainedHeight, width: constrainedWidth } = constraintRect;
173
+ return {
174
+ height: Math.min(height, constrainedHeight),
175
+ left,
176
+ top,
177
+ width: Math.min(width, constrainedWidth)
178
+ };
179
+ }
180
+ const dropTargetsDebugString = (dropTargets)=>dropTargets.map((d, i)=>`\n${d.isDraggedItem ? "*" : " "}[${i}] width : ${Math.floor(d.size)} ${Math.floor(d.start)} - ${Math.floor(d.end)} (mid ${Math.floor(d.mid)}) ${d.element?.textContent} `).join("");
181
+ const getItemParentContainer = (container, itemQuery)=>{
182
+ const firstItem = container?.querySelector(`${itemQuery}:not([aria-hidden="true"])`);
183
+ if (firstItem) return firstItem.parentElement;
184
+ return null;
185
+ };
186
+ const getScrollableContainer = (container, itemQuery)=>{
187
+ const immediateParent = getItemParentContainer(container, itemQuery);
188
+ if (immediateParent === container) return container;
189
+ return immediateParent?.parentElement;
190
+ };
191
+ const isContainerScrollable = (scrollableContainer, orientation)=>{
192
+ if (null === scrollableContainer) return false;
193
+ {
194
+ const { SCROLL_SIZE, CLIENT_SIZE } = dimensions(orientation);
195
+ const { [SCROLL_SIZE]: scrollSize, [CLIENT_SIZE]: clientSize } = scrollableContainer;
196
+ return scrollSize > clientSize;
197
+ }
198
+ };
199
+ export { NOT_HIDDEN, NOT_OVERFLOWED, cloneElement, constrainRect, dimensions, dropTargetsDebugString, getIndexOfDraggedItem, getItemById, getItemParentContainer, getNextDropTarget, getScrollableContainer, isContainerScrollable, measureDropTargets, measureElementSizeAndPosition, mutateDropTargetsSwitchDropTargetPosition, removeDraggedItem };