@jsenv/dom 0.6.0 → 0.7.0
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/jsenv_dom.js +262 -330
- package/package.json +2 -4
- package/index.js +0 -124
- package/src/attr/add_attribute_effect.js +0 -93
- package/src/attr/attributes.js +0 -32
- package/src/color/color_constrast.js +0 -69
- package/src/color/color_parsing.js +0 -319
- package/src/color/color_scheme.js +0 -28
- package/src/color/pick_light_or_dark.js +0 -34
- package/src/color/resolve_css_color.js +0 -60
- package/src/demos/3_columns_resize_demo.html +0 -84
- package/src/demos/3_rows_resize_demo.html +0 -89
- package/src/demos/aside_and_main_demo.html +0 -93
- package/src/demos/coordinates_demo.html +0 -450
- package/src/demos/document_autoscroll_demo.html +0 -517
- package/src/demos/drag_gesture_constraints_demo.html +0 -701
- package/src/demos/drag_gesture_demo.html +0 -1047
- package/src/demos/drag_gesture_element_to_impact_demo.html +0 -445
- package/src/demos/drag_reference_element_demo.html +0 -480
- package/src/demos/flex_details_set_demo.html +0 -302
- package/src/demos/flex_details_set_demo_2.html +0 -315
- package/src/demos/visible_rect_demo.html +0 -525
- package/src/element_signature.js +0 -100
- package/src/interaction/drag/constraint_feedback_line.js +0 -92
- package/src/interaction/drag/drag_constraint.js +0 -659
- package/src/interaction/drag/drag_debug_markers.js +0 -635
- package/src/interaction/drag/drag_element_positioner.js +0 -382
- package/src/interaction/drag/drag_gesture.js +0 -566
- package/src/interaction/drag/drag_resize_demo.html +0 -571
- package/src/interaction/drag/drag_to_move.js +0 -301
- package/src/interaction/drag/drag_to_resize_gesture.js +0 -68
- package/src/interaction/drag/drop_target_detection.js +0 -148
- package/src/interaction/drag/sticky_frontiers.js +0 -160
- package/src/interaction/event_marker.js +0 -14
- package/src/interaction/focus/active_element.js +0 -33
- package/src/interaction/focus/arrow_navigation.js +0 -599
- package/src/interaction/focus/element_is_focusable.js +0 -57
- package/src/interaction/focus/element_visibility.js +0 -111
- package/src/interaction/focus/find_focusable.js +0 -21
- package/src/interaction/focus/focus_group.js +0 -91
- package/src/interaction/focus/focus_group_registry.js +0 -12
- package/src/interaction/focus/focus_nav.js +0 -12
- package/src/interaction/focus/focus_nav_event_marker.js +0 -14
- package/src/interaction/focus/focus_trap.js +0 -105
- package/src/interaction/focus/tab_navigation.js +0 -128
- package/src/interaction/focus/tests/focus_group_skip_tab_test.html +0 -206
- package/src/interaction/focus/tests/tree_focus_test.html +0 -304
- package/src/interaction/focus/tests/tree_focus_test.jsx +0 -261
- package/src/interaction/focus/tests/tree_focus_test_preact.html +0 -13
- package/src/interaction/isolate_interactions.js +0 -161
- package/src/interaction/keyboard.js +0 -26
- package/src/interaction/scroll/capture_scroll.js +0 -47
- package/src/interaction/scroll/is_scrollable.js +0 -159
- package/src/interaction/scroll/scroll_container.js +0 -110
- package/src/interaction/scroll/scroll_trap.js +0 -44
- package/src/interaction/scroll/scrollbar_size.js +0 -20
- package/src/interaction/scroll/wheel_through.js +0 -138
- package/src/iterable_weak_set.js +0 -66
- package/src/position/dom_coords.js +0 -340
- package/src/position/offset_parent.js +0 -15
- package/src/position/position_fixed.js +0 -15
- package/src/position/position_sticky.js +0 -213
- package/src/position/sticky_rect.js +0 -79
- package/src/position/visible_rect.js +0 -486
- package/src/pub_sub.js +0 -31
- package/src/size/can_take_size.js +0 -11
- package/src/size/details_content_full_height.js +0 -63
- package/src/size/flex_details_set.js +0 -974
- package/src/size/get_available_height.js +0 -22
- package/src/size/get_available_width.js +0 -22
- package/src/size/get_border_sizes.js +0 -14
- package/src/size/get_height.js +0 -4
- package/src/size/get_inner_height.js +0 -15
- package/src/size/get_inner_width.js +0 -15
- package/src/size/get_margin_sizes.js +0 -10
- package/src/size/get_max_height.js +0 -57
- package/src/size/get_max_width.js +0 -47
- package/src/size/get_min_height.js +0 -14
- package/src/size/get_min_width.js +0 -14
- package/src/size/get_padding_sizes.js +0 -10
- package/src/size/get_width.js +0 -4
- package/src/size/hooks/use_available_height.js +0 -27
- package/src/size/hooks/use_available_width.js +0 -27
- package/src/size/hooks/use_max_height.js +0 -10
- package/src/size/hooks/use_max_width.js +0 -10
- package/src/size/hooks/use_resize_status.js +0 -62
- package/src/size/resize.js +0 -695
- package/src/size/resolve_css_size.js +0 -32
- package/src/style/dom_styles.js +0 -97
- package/src/style/style_composition.js +0 -121
- package/src/style/style_controller.js +0 -345
- package/src/style/style_default.js +0 -153
- package/src/style/style_default_demo.html +0 -128
- package/src/style/style_parsing.js +0 -375
- package/src/transition/demos/animation_resumption_test.xhtml +0 -500
- package/src/transition/demos/height_toggle_test.xhtml +0 -515
- package/src/transition/dom_transition.js +0 -254
- package/src/transition/easing.js +0 -48
- package/src/transition/group_transition.js +0 -261
- package/src/transition/transform_style_parser.js +0 -32
- package/src/transition/transition_playback.js +0 -366
- package/src/transition/transition_timeline.js +0 -79
- package/src/traversal.js +0 -247
- package/src/ui_transition/demos/content_states_transition_demo.html +0 -628
- package/src/ui_transition/demos/smooth_height_transition_demo.html +0 -149
- package/src/ui_transition/demos/transition_testing.html +0 -354
- package/src/ui_transition/ui_transition.js +0 -1491
- package/src/utils.js +0 -69
- package/src/value_effect.js +0 -35
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
import { getScrollBox, getScrollport } from "../../position/dom_coords.js";
|
|
2
|
-
import { createStyleController } from "../../style/style_controller.js";
|
|
3
|
-
import { getScrollContainer } from "../scroll/scroll_container.js";
|
|
4
|
-
import { initDragConstraints } from "./drag_constraint.js";
|
|
5
|
-
import { createDragElementPositioner } from "./drag_element_positioner.js";
|
|
6
|
-
import { createDragGestureController } from "./drag_gesture.js";
|
|
7
|
-
import { applyStickyFrontiersToAutoScrollArea } from "./sticky_frontiers.js";
|
|
8
|
-
|
|
9
|
-
const dragStyleController = createStyleController("drag_to_move");
|
|
10
|
-
|
|
11
|
-
export const createDragToMoveGestureController = ({
|
|
12
|
-
stickyFrontiers = true,
|
|
13
|
-
// Padding to reduce the area used to autoscroll by this amount (applied after sticky frontiers)
|
|
14
|
-
// This creates an invisible space around the area where elements cannot be dragged
|
|
15
|
-
autoScrollAreaPadding = 0,
|
|
16
|
-
// constraints,
|
|
17
|
-
areaConstraint = "scroll", // "scroll" | "scrollport" | "none" | {left,top,right,bottom} | function
|
|
18
|
-
obstaclesContainer,
|
|
19
|
-
obstacleAttributeName = "data-drag-obstacle",
|
|
20
|
-
// Visual feedback line connecting mouse cursor to the moving grab point when constraints prevent following
|
|
21
|
-
// This provides intuitive feedback during drag operations when the element cannot reach the mouse
|
|
22
|
-
// position due to obstacles, boundaries, or other constraints. The line originates from where the mouse
|
|
23
|
-
// initially grabbed the element, but moves with the element to show the current anchor position.
|
|
24
|
-
// It becomes visible when there's a significant distance between mouse and grab point.
|
|
25
|
-
showConstraintFeedbackLine = true,
|
|
26
|
-
showDebugMarkers = true,
|
|
27
|
-
resetPositionAfterRelease = false,
|
|
28
|
-
...options
|
|
29
|
-
} = {}) => {
|
|
30
|
-
const initGrabToMoveElement = (
|
|
31
|
-
dragGesture,
|
|
32
|
-
{ element, referenceElement, elementToMove, convertScrollablePosition },
|
|
33
|
-
) => {
|
|
34
|
-
const direction = dragGesture.gestureInfo.direction;
|
|
35
|
-
const dragGestureName = dragGesture.gestureInfo.name;
|
|
36
|
-
const scrollContainer = dragGesture.gestureInfo.scrollContainer;
|
|
37
|
-
const elementImpacted = elementToMove || element;
|
|
38
|
-
const translateXAtGrab = dragStyleController.getUnderlyingValue(
|
|
39
|
-
elementImpacted,
|
|
40
|
-
"transform.translateX",
|
|
41
|
-
);
|
|
42
|
-
const translateYAtGrab = dragStyleController.getUnderlyingValue(
|
|
43
|
-
elementImpacted,
|
|
44
|
-
"transform.translateY",
|
|
45
|
-
);
|
|
46
|
-
dragGesture.addReleaseCallback(() => {
|
|
47
|
-
if (resetPositionAfterRelease) {
|
|
48
|
-
dragStyleController.clear(elementImpacted);
|
|
49
|
-
} else {
|
|
50
|
-
dragStyleController.commit(elementImpacted);
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
let elementWidth;
|
|
55
|
-
let elementHeight;
|
|
56
|
-
{
|
|
57
|
-
const updateElementDimension = () => {
|
|
58
|
-
const elementRect = element.getBoundingClientRect();
|
|
59
|
-
elementWidth = elementRect.width;
|
|
60
|
-
elementHeight = elementRect.height;
|
|
61
|
-
};
|
|
62
|
-
updateElementDimension();
|
|
63
|
-
dragGesture.addBeforeDragCallback(updateElementDimension);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
let scrollArea;
|
|
67
|
-
{
|
|
68
|
-
// computed at start so that scrollWidth/scrollHeight are fixed
|
|
69
|
-
// even if the dragging side effects increases them afterwards
|
|
70
|
-
scrollArea = {
|
|
71
|
-
left: 0,
|
|
72
|
-
top: 0,
|
|
73
|
-
right: scrollContainer.scrollWidth,
|
|
74
|
-
bottom: scrollContainer.scrollHeight,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let scrollport;
|
|
79
|
-
let autoScrollArea;
|
|
80
|
-
{
|
|
81
|
-
// for visible are we also want to snapshot the widht/height
|
|
82
|
-
// and we'll add scrollContainer container scrolls during drag (getScrollport does that)
|
|
83
|
-
const scrollBox = getScrollBox(scrollContainer);
|
|
84
|
-
const updateScrollportAndAutoScrollArea = () => {
|
|
85
|
-
scrollport = getScrollport(scrollBox, scrollContainer);
|
|
86
|
-
autoScrollArea = scrollport;
|
|
87
|
-
if (stickyFrontiers) {
|
|
88
|
-
autoScrollArea = applyStickyFrontiersToAutoScrollArea(
|
|
89
|
-
autoScrollArea,
|
|
90
|
-
{
|
|
91
|
-
scrollContainer,
|
|
92
|
-
direction,
|
|
93
|
-
dragGestureName,
|
|
94
|
-
},
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
if (autoScrollAreaPadding > 0) {
|
|
98
|
-
autoScrollArea = {
|
|
99
|
-
paddingLeft: autoScrollAreaPadding,
|
|
100
|
-
paddingTop: autoScrollAreaPadding,
|
|
101
|
-
paddingRight: autoScrollAreaPadding,
|
|
102
|
-
paddingBottom: autoScrollAreaPadding,
|
|
103
|
-
left: autoScrollArea.left + autoScrollAreaPadding,
|
|
104
|
-
top: autoScrollArea.top + autoScrollAreaPadding,
|
|
105
|
-
right: autoScrollArea.right - autoScrollAreaPadding,
|
|
106
|
-
bottom: autoScrollArea.bottom - autoScrollAreaPadding,
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
updateScrollportAndAutoScrollArea();
|
|
111
|
-
dragGesture.addBeforeDragCallback(updateScrollportAndAutoScrollArea);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Set up dragging attribute
|
|
115
|
-
element.setAttribute("data-grabbed", "");
|
|
116
|
-
dragGesture.addReleaseCallback(() => {
|
|
117
|
-
element.removeAttribute("data-grabbed");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
// Will be used for dynamic constraints on sticky elements
|
|
121
|
-
let hasCrossedScrollportLeftOnce = false;
|
|
122
|
-
let hasCrossedScrollportTopOnce = false;
|
|
123
|
-
const dragConstraints = initDragConstraints(dragGesture, {
|
|
124
|
-
areaConstraint,
|
|
125
|
-
obstaclesContainer: obstaclesContainer || scrollContainer,
|
|
126
|
-
obstacleAttributeName,
|
|
127
|
-
showConstraintFeedbackLine,
|
|
128
|
-
showDebugMarkers,
|
|
129
|
-
referenceElement,
|
|
130
|
-
});
|
|
131
|
-
dragGesture.addBeforeDragCallback(
|
|
132
|
-
(layoutRequested, currentLayout, limitLayout, { dragEvent }) => {
|
|
133
|
-
dragConstraints.applyConstraints(
|
|
134
|
-
layoutRequested,
|
|
135
|
-
currentLayout,
|
|
136
|
-
limitLayout,
|
|
137
|
-
{
|
|
138
|
-
elementWidth,
|
|
139
|
-
elementHeight,
|
|
140
|
-
scrollArea,
|
|
141
|
-
scrollport,
|
|
142
|
-
hasCrossedScrollportLeftOnce,
|
|
143
|
-
hasCrossedScrollportTopOnce,
|
|
144
|
-
autoScrollArea,
|
|
145
|
-
dragEvent,
|
|
146
|
-
},
|
|
147
|
-
);
|
|
148
|
-
},
|
|
149
|
-
);
|
|
150
|
-
|
|
151
|
-
const dragToMove = (gestureInfo) => {
|
|
152
|
-
const { isGoingDown, isGoingUp, isGoingLeft, isGoingRight, layout } =
|
|
153
|
-
gestureInfo;
|
|
154
|
-
const left = layout.left;
|
|
155
|
-
const top = layout.top;
|
|
156
|
-
const right = left + elementWidth;
|
|
157
|
-
const bottom = top + elementHeight;
|
|
158
|
-
|
|
159
|
-
auto_scroll: {
|
|
160
|
-
hasCrossedScrollportLeftOnce =
|
|
161
|
-
hasCrossedScrollportLeftOnce || left < scrollport.left;
|
|
162
|
-
hasCrossedScrollportTopOnce =
|
|
163
|
-
hasCrossedScrollportTopOnce || top < scrollport.top;
|
|
164
|
-
|
|
165
|
-
const getScrollMove = (axis) => {
|
|
166
|
-
const isGoingPositive = axis === "x" ? isGoingRight : isGoingDown;
|
|
167
|
-
if (isGoingPositive) {
|
|
168
|
-
const elementEnd = axis === "x" ? right : bottom;
|
|
169
|
-
const autoScrollAreaEnd =
|
|
170
|
-
axis === "x" ? autoScrollArea.right : autoScrollArea.bottom;
|
|
171
|
-
|
|
172
|
-
if (elementEnd <= autoScrollAreaEnd) {
|
|
173
|
-
return 0;
|
|
174
|
-
}
|
|
175
|
-
const scrollAmountNeeded = elementEnd - autoScrollAreaEnd;
|
|
176
|
-
return scrollAmountNeeded;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const isGoingNegative = axis === "x" ? isGoingLeft : isGoingUp;
|
|
180
|
-
if (!isGoingNegative) {
|
|
181
|
-
return 0;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const referenceOrEl = referenceElement || element;
|
|
185
|
-
const canAutoScrollNegative =
|
|
186
|
-
axis === "x"
|
|
187
|
-
? !referenceOrEl.hasAttribute("data-sticky-left") ||
|
|
188
|
-
hasCrossedScrollportLeftOnce
|
|
189
|
-
: !referenceOrEl.hasAttribute("data-sticky-top") ||
|
|
190
|
-
hasCrossedScrollportTopOnce;
|
|
191
|
-
if (!canAutoScrollNegative) {
|
|
192
|
-
return 0;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const elementStart = axis === "x" ? left : top;
|
|
196
|
-
const autoScrollAreaStart =
|
|
197
|
-
axis === "x" ? autoScrollArea.left : autoScrollArea.top;
|
|
198
|
-
if (elementStart >= autoScrollAreaStart) {
|
|
199
|
-
return 0;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const scrollAmountNeeded = autoScrollAreaStart - elementStart;
|
|
203
|
-
return -scrollAmountNeeded;
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
let scrollLeftTarget;
|
|
207
|
-
let scrollTopTarget;
|
|
208
|
-
if (direction.x) {
|
|
209
|
-
const containerScrollLeftMove = getScrollMove("x");
|
|
210
|
-
if (containerScrollLeftMove) {
|
|
211
|
-
scrollLeftTarget =
|
|
212
|
-
scrollContainer.scrollLeft + containerScrollLeftMove;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
if (direction.y) {
|
|
216
|
-
const containerScrollTopMove = getScrollMove("y");
|
|
217
|
-
if (containerScrollTopMove) {
|
|
218
|
-
scrollTopTarget =
|
|
219
|
-
scrollContainer.scrollTop + containerScrollTopMove;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
// now we know what to do, do it
|
|
223
|
-
if (scrollLeftTarget !== undefined) {
|
|
224
|
-
scrollContainer.scrollLeft = scrollLeftTarget;
|
|
225
|
-
}
|
|
226
|
-
if (scrollTopTarget !== undefined) {
|
|
227
|
-
scrollContainer.scrollTop = scrollTopTarget;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
move: {
|
|
232
|
-
const { scrollableLeft, scrollableTop } = layout;
|
|
233
|
-
const [positionedLeft, positionedTop] = convertScrollablePosition(
|
|
234
|
-
scrollableLeft,
|
|
235
|
-
scrollableTop,
|
|
236
|
-
);
|
|
237
|
-
const transform = {};
|
|
238
|
-
if (direction.x) {
|
|
239
|
-
const leftTarget = positionedLeft;
|
|
240
|
-
const leftAtGrab = dragGesture.gestureInfo.leftAtGrab;
|
|
241
|
-
const leftDelta = leftTarget - leftAtGrab;
|
|
242
|
-
const translateX = translateXAtGrab
|
|
243
|
-
? translateXAtGrab + leftDelta
|
|
244
|
-
: leftDelta;
|
|
245
|
-
transform.translateX = translateX;
|
|
246
|
-
// console.log({
|
|
247
|
-
// leftAtGrab,
|
|
248
|
-
// scrollableLeft,
|
|
249
|
-
// left,
|
|
250
|
-
// leftTarget,
|
|
251
|
-
// });
|
|
252
|
-
}
|
|
253
|
-
if (direction.y) {
|
|
254
|
-
const topTarget = positionedTop;
|
|
255
|
-
const topAtGrab = dragGesture.gestureInfo.topAtGrab;
|
|
256
|
-
const topDelta = topTarget - topAtGrab;
|
|
257
|
-
const translateY = translateYAtGrab
|
|
258
|
-
? translateYAtGrab + topDelta
|
|
259
|
-
: topDelta;
|
|
260
|
-
transform.translateY = translateY;
|
|
261
|
-
}
|
|
262
|
-
dragStyleController.set(elementImpacted, {
|
|
263
|
-
transform,
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
dragGesture.addDragCallback(dragToMove);
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
const dragGestureController = createDragGestureController(options);
|
|
271
|
-
const grab = dragGestureController.grab;
|
|
272
|
-
dragGestureController.grab = ({
|
|
273
|
-
element,
|
|
274
|
-
referenceElement,
|
|
275
|
-
elementToMove,
|
|
276
|
-
...rest
|
|
277
|
-
} = {}) => {
|
|
278
|
-
const scrollContainer = getScrollContainer(referenceElement || element);
|
|
279
|
-
const [
|
|
280
|
-
elementScrollableLeft,
|
|
281
|
-
elementScrollableTop,
|
|
282
|
-
convertScrollablePosition,
|
|
283
|
-
] = createDragElementPositioner(element, referenceElement, elementToMove);
|
|
284
|
-
const dragGesture = grab({
|
|
285
|
-
element,
|
|
286
|
-
scrollContainer,
|
|
287
|
-
layoutScrollableLeft: elementScrollableLeft,
|
|
288
|
-
layoutScrollableTop: elementScrollableTop,
|
|
289
|
-
...rest,
|
|
290
|
-
});
|
|
291
|
-
initGrabToMoveElement(dragGesture, {
|
|
292
|
-
element,
|
|
293
|
-
referenceElement,
|
|
294
|
-
elementToMove,
|
|
295
|
-
convertScrollablePosition,
|
|
296
|
-
});
|
|
297
|
-
return dragGesture;
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
return dragGestureController;
|
|
301
|
-
};
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { createDragGestureController } from "./drag_gesture.js";
|
|
2
|
-
|
|
3
|
-
export const startDragToResizeGesture = (
|
|
4
|
-
pointerdownEvent,
|
|
5
|
-
{ onDragStart, onDrag, onRelease, ...options },
|
|
6
|
-
) => {
|
|
7
|
-
const target = pointerdownEvent.target;
|
|
8
|
-
if (!target.closest) {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
const elementWithDataResizeHandle = target.closest("[data-resize-handle]");
|
|
12
|
-
if (!elementWithDataResizeHandle) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
let elementToResize;
|
|
16
|
-
const dataResizeHandle =
|
|
17
|
-
elementWithDataResizeHandle.getAttribute("data-resize-handle");
|
|
18
|
-
if (!dataResizeHandle || dataResizeHandle === "true") {
|
|
19
|
-
elementToResize = elementWithDataResizeHandle.closest("[data-resize]");
|
|
20
|
-
} else {
|
|
21
|
-
elementToResize = document.querySelector(`#${dataResizeHandle}`);
|
|
22
|
-
}
|
|
23
|
-
if (!elementToResize) {
|
|
24
|
-
console.warn("No element to resize found");
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
// inspired by https://developer.mozilla.org/en-US/docs/Web/CSS/resize
|
|
28
|
-
// "horizontal", "vertical", "both"
|
|
29
|
-
const resizeDirection = getResizeDirection(elementToResize);
|
|
30
|
-
if (!resizeDirection.x && !resizeDirection.y) {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const dragToResizeGestureController = createDragGestureController({
|
|
35
|
-
gestureAttribute: "data-resizing",
|
|
36
|
-
onDragStart: (...args) => {
|
|
37
|
-
onDragStart?.(...args);
|
|
38
|
-
},
|
|
39
|
-
onDrag,
|
|
40
|
-
onRelease: (...args) => {
|
|
41
|
-
elementWithDataResizeHandle.removeAttribute("data-active");
|
|
42
|
-
onRelease?.(...args);
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
elementWithDataResizeHandle.setAttribute("data-active", "");
|
|
46
|
-
const dragToResizeGesture = dragToResizeGestureController.grabViaPointer(
|
|
47
|
-
pointerdownEvent,
|
|
48
|
-
{
|
|
49
|
-
element: elementToResize,
|
|
50
|
-
direction: resizeDirection,
|
|
51
|
-
cursor:
|
|
52
|
-
resizeDirection.x && resizeDirection.y
|
|
53
|
-
? "nwse-resize"
|
|
54
|
-
: resizeDirection.x
|
|
55
|
-
? "ew-resize"
|
|
56
|
-
: "ns-resize",
|
|
57
|
-
...options,
|
|
58
|
-
},
|
|
59
|
-
);
|
|
60
|
-
return dragToResizeGesture;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
const getResizeDirection = (element) => {
|
|
64
|
-
const direction = element.getAttribute("data-resize");
|
|
65
|
-
const x = direction === "horizontal" || direction === "both";
|
|
66
|
-
const y = direction === "vertical" || direction === "both";
|
|
67
|
-
return { x, y };
|
|
68
|
-
};
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Detects the drop target based on what element is actually under the mouse cursor.
|
|
3
|
-
* Uses document.elementsFromPoint() to respect visual stacking order naturally.
|
|
4
|
-
*
|
|
5
|
-
* @param {Object} gestureInfo - Gesture information
|
|
6
|
-
* @param {Element[]} targetElements - Array of potential drop target elements
|
|
7
|
-
* @returns {Object|null} Drop target info with elementSide or null if no valid target found
|
|
8
|
-
*/
|
|
9
|
-
export const getDropTargetInfo = (gestureInfo, targetElements) => {
|
|
10
|
-
const dragElement = gestureInfo.element;
|
|
11
|
-
const dragElementRect = dragElement.getBoundingClientRect();
|
|
12
|
-
const intersectingTargets = [];
|
|
13
|
-
let someTargetIsCol;
|
|
14
|
-
let someTargetIsTr;
|
|
15
|
-
for (const targetElement of targetElements) {
|
|
16
|
-
const targetRect = targetElement.getBoundingClientRect();
|
|
17
|
-
if (!rectangleAreIntersecting(dragElementRect, targetRect)) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
if (!someTargetIsCol && targetElement.tagName === "COL") {
|
|
21
|
-
someTargetIsCol = true;
|
|
22
|
-
}
|
|
23
|
-
if (!someTargetIsTr && targetElement.tagName === "TR") {
|
|
24
|
-
someTargetIsTr = true;
|
|
25
|
-
}
|
|
26
|
-
intersectingTargets.push(targetElement);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (intersectingTargets.length === 0) {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const dragElementCenterX = dragElementRect.left + dragElementRect.width / 2;
|
|
34
|
-
const dragElementCenterY = dragElementRect.top + dragElementRect.height / 2;
|
|
35
|
-
// Clamp coordinates to viewport to avoid issues with elementsFromPoint
|
|
36
|
-
const viewportWidth = document.documentElement.clientWidth;
|
|
37
|
-
const viewportHeight = document.documentElement.clientHeight;
|
|
38
|
-
const clientX =
|
|
39
|
-
dragElementCenterX < 0
|
|
40
|
-
? 0
|
|
41
|
-
: dragElementCenterX > viewportWidth
|
|
42
|
-
? viewportWidth - 1
|
|
43
|
-
: dragElementCenterX;
|
|
44
|
-
const clientY =
|
|
45
|
-
dragElementCenterY < 0
|
|
46
|
-
? 0
|
|
47
|
-
: dragElementCenterY > viewportHeight
|
|
48
|
-
? viewportHeight - 1
|
|
49
|
-
: dragElementCenterY;
|
|
50
|
-
|
|
51
|
-
// Find the first target element in the stack (topmost visible target)
|
|
52
|
-
const elementsUnderDragElement = document.elementsFromPoint(clientX, clientY);
|
|
53
|
-
let targetElement = null;
|
|
54
|
-
let targetIndex = -1;
|
|
55
|
-
for (const element of elementsUnderDragElement) {
|
|
56
|
-
// First, check if the element itself is a target
|
|
57
|
-
const directIndex = intersectingTargets.indexOf(element);
|
|
58
|
-
if (directIndex !== -1) {
|
|
59
|
-
targetElement = element;
|
|
60
|
-
targetIndex = directIndex;
|
|
61
|
-
break;
|
|
62
|
-
}
|
|
63
|
-
// Special case: if element is <td> or <th> and not in targets,
|
|
64
|
-
// try to find its corresponding <col> element
|
|
65
|
-
if (!isTableCell(element)) {
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
try_col: {
|
|
69
|
-
if (!someTargetIsCol) {
|
|
70
|
-
break try_col;
|
|
71
|
-
}
|
|
72
|
-
const tableCellCol = findTableCellCol(element);
|
|
73
|
-
if (!tableCellCol) {
|
|
74
|
-
break try_col;
|
|
75
|
-
}
|
|
76
|
-
const colIndex = intersectingTargets.indexOf(tableCellCol);
|
|
77
|
-
if (colIndex === -1) {
|
|
78
|
-
break try_col;
|
|
79
|
-
}
|
|
80
|
-
targetElement = tableCellCol;
|
|
81
|
-
targetIndex = colIndex;
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
try_tr: {
|
|
85
|
-
if (!someTargetIsTr) {
|
|
86
|
-
break try_tr;
|
|
87
|
-
}
|
|
88
|
-
const tableRow = element.closest("tr");
|
|
89
|
-
const rowIndex = targetElements.indexOf(tableRow);
|
|
90
|
-
if (rowIndex === -1) {
|
|
91
|
-
break try_tr;
|
|
92
|
-
}
|
|
93
|
-
targetElement = tableRow;
|
|
94
|
-
targetIndex = rowIndex;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (!targetElement) {
|
|
99
|
-
targetElement = intersectingTargets[0];
|
|
100
|
-
targetIndex = 0;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Determine position within the target for both axes
|
|
104
|
-
const targetRect = targetElement.getBoundingClientRect();
|
|
105
|
-
const targetCenterX = targetRect.left + targetRect.width / 2;
|
|
106
|
-
const targetCenterY = targetRect.top + targetRect.height / 2;
|
|
107
|
-
const result = {
|
|
108
|
-
index: targetIndex,
|
|
109
|
-
element: targetElement,
|
|
110
|
-
elementSide: {
|
|
111
|
-
x: dragElementRect.left < targetCenterX ? "start" : "end",
|
|
112
|
-
y: dragElementRect.top < targetCenterY ? "start" : "end",
|
|
113
|
-
},
|
|
114
|
-
intersecting: intersectingTargets,
|
|
115
|
-
};
|
|
116
|
-
return result;
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
const rectangleAreIntersecting = (r1, r2) => {
|
|
120
|
-
return !(
|
|
121
|
-
r2.left > r1.right ||
|
|
122
|
-
r2.right < r1.left ||
|
|
123
|
-
r2.top > r1.bottom ||
|
|
124
|
-
r2.bottom < r1.top
|
|
125
|
-
);
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const isTableCell = (el) => {
|
|
129
|
-
return el.tagName === "TD" || el.tagName === "TH";
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Find the corresponding <col> element for a given <td> or <th> cell
|
|
134
|
-
* @param {Element} cellElement - The <td> or <th> element
|
|
135
|
-
* @param {Element[]} targetColElements - Array of <col> elements to search in
|
|
136
|
-
* @returns {Element|null} The corresponding <col> element or null if not found
|
|
137
|
-
*/
|
|
138
|
-
const findTableCellCol = (cellElement) => {
|
|
139
|
-
const table = cellElement.closest("table");
|
|
140
|
-
const colgroup = table.querySelector("colgroup");
|
|
141
|
-
if (!colgroup) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
const cols = colgroup.querySelectorAll("col");
|
|
145
|
-
const columnIndex = cellElement.cellIndex;
|
|
146
|
-
const correspondingCol = cols[columnIndex];
|
|
147
|
-
return correspondingCol;
|
|
148
|
-
};
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { getElementSignature } from "../../element_signature.js";
|
|
2
|
-
import { getScrollRelativeRect } from "../../position/dom_coords.js";
|
|
3
|
-
|
|
4
|
-
export const applyStickyFrontiersToAutoScrollArea = (
|
|
5
|
-
autoScrollArea,
|
|
6
|
-
{ direction, scrollContainer, dragName },
|
|
7
|
-
) => {
|
|
8
|
-
let { left, right, top, bottom } = autoScrollArea;
|
|
9
|
-
|
|
10
|
-
if (direction.x) {
|
|
11
|
-
const horizontalStickyFrontiers = createStickyFrontierOnAxis(
|
|
12
|
-
scrollContainer,
|
|
13
|
-
{
|
|
14
|
-
name: dragName,
|
|
15
|
-
scrollContainer,
|
|
16
|
-
primarySide: "left",
|
|
17
|
-
oppositeSide: "right",
|
|
18
|
-
},
|
|
19
|
-
);
|
|
20
|
-
for (const horizontalStickyFrontier of horizontalStickyFrontiers) {
|
|
21
|
-
const { side, bounds, element } = horizontalStickyFrontier;
|
|
22
|
-
if (side === "left") {
|
|
23
|
-
if (bounds.right <= left) {
|
|
24
|
-
continue;
|
|
25
|
-
}
|
|
26
|
-
left = bounds.right;
|
|
27
|
-
if (import.meta.dev && left > right) {
|
|
28
|
-
console.warn(
|
|
29
|
-
`Sticky frontier created invalid horizontal visible area: left (${left}) > right (${right}). Original: left=${bounds.right}, right=${right}`,
|
|
30
|
-
{
|
|
31
|
-
frontierElement: element,
|
|
32
|
-
frontierBounds: bounds,
|
|
33
|
-
dragName,
|
|
34
|
-
},
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
// right
|
|
40
|
-
if (bounds.left >= right) {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
right = bounds.left;
|
|
44
|
-
if (import.meta.dev && left > right) {
|
|
45
|
-
console.warn(
|
|
46
|
-
`Sticky frontier created invalid horizontal visible area: left (${left}) > right (${right}). Original: left=${left}, right=${bounds.left}`,
|
|
47
|
-
{
|
|
48
|
-
frontierElement: element,
|
|
49
|
-
frontierBounds: bounds,
|
|
50
|
-
dragName,
|
|
51
|
-
},
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
if (direction.y) {
|
|
59
|
-
const verticalStickyFrontiers = createStickyFrontierOnAxis(
|
|
60
|
-
scrollContainer,
|
|
61
|
-
{
|
|
62
|
-
name: dragName,
|
|
63
|
-
scrollContainer,
|
|
64
|
-
primarySide: "top",
|
|
65
|
-
oppositeSide: "bottom",
|
|
66
|
-
},
|
|
67
|
-
);
|
|
68
|
-
for (const verticalStickyFrontier of verticalStickyFrontiers) {
|
|
69
|
-
const { side, bounds, element } = verticalStickyFrontier;
|
|
70
|
-
|
|
71
|
-
// Frontier acts as a top barrier - constrains from the bottom edge of the frontier
|
|
72
|
-
if (side === "top") {
|
|
73
|
-
if (bounds.bottom <= top) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
top = bounds.bottom;
|
|
77
|
-
if (import.meta.dev && top > bottom) {
|
|
78
|
-
console.warn(
|
|
79
|
-
`Sticky frontier created invalid vertical visible area: top (${top}) > bottom (${bottom}). Original: top=${bounds.bottom}, bottom=${bottom}`,
|
|
80
|
-
{
|
|
81
|
-
frontierElement: element,
|
|
82
|
-
frontierBounds: bounds,
|
|
83
|
-
dragName,
|
|
84
|
-
},
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Frontier acts as a bottom barrier - constrains from the top edge of the frontier
|
|
91
|
-
if (bounds.top >= bottom) {
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
bottom = bounds.top;
|
|
95
|
-
if (import.meta.dev && top > bottom) {
|
|
96
|
-
console.warn(
|
|
97
|
-
`Sticky frontier created invalid vertical visible area: top (${top}) > bottom (${bottom}). Original: top=${top}, bottom=${bounds.top}`,
|
|
98
|
-
{
|
|
99
|
-
frontierElement: element,
|
|
100
|
-
frontierBounds: bounds,
|
|
101
|
-
dragName,
|
|
102
|
-
},
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
continue;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return { left, right, top, bottom };
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const createStickyFrontierOnAxis = (
|
|
113
|
-
element,
|
|
114
|
-
{ name, scrollContainer, primarySide, oppositeSide },
|
|
115
|
-
) => {
|
|
116
|
-
const primaryAttrName = `data-drag-sticky-${primarySide}-frontier`;
|
|
117
|
-
const oppositeAttrName = `data-drag-sticky-${oppositeSide}-frontier`;
|
|
118
|
-
const frontiers = element.querySelectorAll(
|
|
119
|
-
`[${primaryAttrName}], [${oppositeAttrName}]`,
|
|
120
|
-
);
|
|
121
|
-
const matchingStickyFrontiers = [];
|
|
122
|
-
for (const frontier of frontiers) {
|
|
123
|
-
if (frontier.closest("[data-drag-ignore]")) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
const hasPrimary = frontier.hasAttribute(primaryAttrName);
|
|
127
|
-
const hasOpposite = frontier.hasAttribute(oppositeAttrName);
|
|
128
|
-
// Check if element has both sides (invalid)
|
|
129
|
-
if (hasPrimary && hasOpposite) {
|
|
130
|
-
const elementSignature = getElementSignature(frontier);
|
|
131
|
-
console.warn(
|
|
132
|
-
`Sticky frontier element (${elementSignature}) has both ${primarySide} and ${oppositeSide} attributes.
|
|
133
|
-
A sticky frontier should only have one side attribute.`,
|
|
134
|
-
);
|
|
135
|
-
continue;
|
|
136
|
-
}
|
|
137
|
-
const attrName = hasPrimary ? primaryAttrName : oppositeAttrName;
|
|
138
|
-
const attributeValue = frontier.getAttribute(attrName);
|
|
139
|
-
if (attributeValue && name) {
|
|
140
|
-
const frontierNames = attributeValue.split(",");
|
|
141
|
-
const isMatching = frontierNames.some(
|
|
142
|
-
(frontierName) =>
|
|
143
|
-
frontierName.trim().toLowerCase() === name.toLowerCase(),
|
|
144
|
-
);
|
|
145
|
-
if (!isMatching) {
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const frontierBounds = getScrollRelativeRect(frontier, scrollContainer);
|
|
150
|
-
const stickyFrontierObject = {
|
|
151
|
-
type: "sticky-frontier",
|
|
152
|
-
element: frontier,
|
|
153
|
-
side: hasPrimary ? primarySide : oppositeSide,
|
|
154
|
-
bounds: frontierBounds,
|
|
155
|
-
name: `sticky_frontier_${hasPrimary ? primarySide : oppositeSide} (${getElementSignature(frontier)})`,
|
|
156
|
-
};
|
|
157
|
-
matchingStickyFrontiers.push(stickyFrontierObject);
|
|
158
|
-
}
|
|
159
|
-
return matchingStickyFrontiers;
|
|
160
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export const createEventMarker = (symbolName) => {
|
|
2
|
-
const symbol = Symbol.for(symbolName);
|
|
3
|
-
|
|
4
|
-
const isMarked = (event) => {
|
|
5
|
-
return Boolean(event[symbol]);
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
return {
|
|
9
|
-
mark: (event) => {
|
|
10
|
-
event[symbol] = true;
|
|
11
|
-
},
|
|
12
|
-
isMarked,
|
|
13
|
-
};
|
|
14
|
-
};
|