@jsenv/dom 0.10.3 → 0.10.5
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 +365 -269
- package/package.json +1 -1
package/dist/jsenv_dom.js
CHANGED
|
@@ -5419,6 +5419,31 @@ const getScrollContainerSet = (element) => {
|
|
|
5419
5419
|
return scrollContainerSet;
|
|
5420
5420
|
};
|
|
5421
5421
|
|
|
5422
|
+
/**
|
|
5423
|
+
* Rounds a CSS pixel value to the nearest physical pixel boundary for the current display.
|
|
5424
|
+
*
|
|
5425
|
+
* At zoom levels other than 100%, `devicePixelRatio` is not an integer (e.g. 1.25, 1.5),
|
|
5426
|
+
* so fractional CSS pixel values from `getBoundingClientRect()` may not align to the physical
|
|
5427
|
+
* pixel grid. Setting `top`/`left` to such values causes the browser to interpolate across
|
|
5428
|
+
* pixels, resulting in blurry rendering or misalignment with adjacent elements.
|
|
5429
|
+
*
|
|
5430
|
+
* Snapping to the physical grid ensures the value falls exactly on a pixel boundary.
|
|
5431
|
+
*
|
|
5432
|
+
* @param {number} value - A CSS pixel value (e.g. from getBoundingClientRect or scroll offset).
|
|
5433
|
+
* @returns {number} The nearest physical-pixel-aligned CSS pixel value.
|
|
5434
|
+
* @example
|
|
5435
|
+
* // At devicePixelRatio 1.25, snapToPixel(154.4) → 154.4 (already on grid)
|
|
5436
|
+
* // At devicePixelRatio 1.25, snapToPixel(154.3) → 154.4
|
|
5437
|
+
*/
|
|
5438
|
+
const snapToPixel = (value) => {
|
|
5439
|
+
return Math.round(value * devicePixelRatio) / devicePixelRatio;
|
|
5440
|
+
};
|
|
5441
|
+
|
|
5442
|
+
// Round a CSS-pixel value to the nearest physical pixel boundary.
|
|
5443
|
+
// At zoom levels other than 100%, devicePixelRatio is not an integer (e.g. 1.25, 1.5),
|
|
5444
|
+
// so CSS pixels don't align 1:1 with physical pixels. Rounding to the physical grid
|
|
5445
|
+
// ensures the browser can render the element without sub-pixel blurring.
|
|
5446
|
+
|
|
5422
5447
|
const getBorderSizes = (element) => {
|
|
5423
5448
|
const {
|
|
5424
5449
|
borderLeftWidth,
|
|
@@ -5426,11 +5451,12 @@ const getBorderSizes = (element) => {
|
|
|
5426
5451
|
borderTopWidth,
|
|
5427
5452
|
borderBottomWidth,
|
|
5428
5453
|
} = window.getComputedStyle(element, null);
|
|
5454
|
+
|
|
5429
5455
|
return {
|
|
5430
|
-
left: parseFloat(borderLeftWidth),
|
|
5431
|
-
right: parseFloat(borderRightWidth),
|
|
5432
|
-
top: parseFloat(borderTopWidth),
|
|
5433
|
-
bottom: parseFloat(borderBottomWidth),
|
|
5456
|
+
left: snapToPixel(parseFloat(borderLeftWidth)),
|
|
5457
|
+
right: snapToPixel(parseFloat(borderRightWidth)),
|
|
5458
|
+
top: snapToPixel(parseFloat(borderTopWidth)),
|
|
5459
|
+
bottom: snapToPixel(parseFloat(borderBottomWidth)),
|
|
5434
5460
|
};
|
|
5435
5461
|
};
|
|
5436
5462
|
|
|
@@ -5782,8 +5808,8 @@ const measureScrollbar = (scrollableElement) => {
|
|
|
5782
5808
|
const scrollbarHeight = scrollDiv.offsetHeight - scrollDiv.clientHeight;
|
|
5783
5809
|
scrollableElement.removeChild(scrollDiv);
|
|
5784
5810
|
return [
|
|
5785
|
-
hasXScrollbar ? scrollbarWidth : 0,
|
|
5786
|
-
hasYScrollbar ? scrollbarHeight : 0,
|
|
5811
|
+
hasXScrollbar ? snapToPixel(scrollbarWidth) : 0,
|
|
5812
|
+
hasYScrollbar ? snapToPixel(scrollbarHeight) : 0,
|
|
5787
5813
|
];
|
|
5788
5814
|
};
|
|
5789
5815
|
|
|
@@ -6096,6 +6122,18 @@ const scrollIntoViewWithStickyAwareness = (
|
|
|
6096
6122
|
}
|
|
6097
6123
|
};
|
|
6098
6124
|
|
|
6125
|
+
const getPaddingSizes = (element) => {
|
|
6126
|
+
const { paddingLeft, paddingRight, paddingTop, paddingBottom } =
|
|
6127
|
+
window.getComputedStyle(element, null);
|
|
6128
|
+
|
|
6129
|
+
return {
|
|
6130
|
+
left: snapToPixel(parseFloat(paddingLeft)),
|
|
6131
|
+
right: snapToPixel(parseFloat(paddingRight)),
|
|
6132
|
+
top: snapToPixel(parseFloat(paddingTop)),
|
|
6133
|
+
bottom: snapToPixel(parseFloat(paddingBottom)),
|
|
6134
|
+
};
|
|
6135
|
+
};
|
|
6136
|
+
|
|
6099
6137
|
/**
|
|
6100
6138
|
* Prevents scrolling on all scrollable containers that are ancestors of (or
|
|
6101
6139
|
* siblings preceding) `element`. Used when an overlay (popover, dialog) is
|
|
@@ -6132,11 +6170,10 @@ const trapScrollInside = (element) => {
|
|
|
6132
6170
|
return;
|
|
6133
6171
|
}
|
|
6134
6172
|
const [scrollbarWidth, scrollbarHeight] = measureScrollbar(el);
|
|
6135
|
-
const
|
|
6136
|
-
const paddingBottom = parseInt(getStyle(el, "padding-bottom"), 0);
|
|
6173
|
+
const { right, bottom } = getPaddingSizes(el);
|
|
6137
6174
|
const removeScrollLockStyles = setStyles(el, {
|
|
6138
|
-
"padding-right": `${
|
|
6139
|
-
"padding-bottom": `${
|
|
6175
|
+
"padding-right": `${right + scrollbarWidth}px`,
|
|
6176
|
+
"padding-bottom": `${bottom + scrollbarHeight}px`,
|
|
6140
6177
|
"overflow": "hidden",
|
|
6141
6178
|
});
|
|
6142
6179
|
cleanupCallbackSet.add(removeScrollLockStyles);
|
|
@@ -6919,6 +6956,13 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
6919
6956
|
* donc juste x/y ca seras surement mieux
|
|
6920
6957
|
*
|
|
6921
6958
|
*/
|
|
6959
|
+
const css$3 = /* css */`
|
|
6960
|
+
.navi_drag_gesture_backdrop {
|
|
6961
|
+
position: fixed;
|
|
6962
|
+
inset: 0;
|
|
6963
|
+
user-select: none;
|
|
6964
|
+
}
|
|
6965
|
+
`;
|
|
6922
6966
|
const createDragGestureController = (options = {}) => {
|
|
6923
6967
|
const {
|
|
6924
6968
|
name,
|
|
@@ -7065,6 +7109,7 @@ const createDragGestureController = (options = {}) => {
|
|
|
7065
7109
|
|
|
7066
7110
|
// 2. VISUAL CONTROL: Backdrop for consistent cursor and pointer event blocking
|
|
7067
7111
|
if (backdrop) {
|
|
7112
|
+
import.meta.css = [css$3, "@jsenv/dom/src/interaction/drag/drag_gesture.js"];
|
|
7068
7113
|
const backdropElement = document.createElement("div");
|
|
7069
7114
|
backdropElement.className = "navi_drag_gesture_backdrop";
|
|
7070
7115
|
backdropElement.ariaHidden = "true";
|
|
@@ -7421,15 +7466,24 @@ const definePropertyAsReadOnly = (object, propertyName) => {
|
|
|
7421
7466
|
value: object[propertyName]
|
|
7422
7467
|
});
|
|
7423
7468
|
};
|
|
7424
|
-
|
|
7425
|
-
|
|
7469
|
+
|
|
7470
|
+
installImportMetaCssBuild(import.meta);const css$2 = /* css */`
|
|
7471
|
+
.navi_constraint_feedback_line {
|
|
7426
7472
|
position: fixed;
|
|
7427
|
-
|
|
7428
|
-
|
|
7473
|
+
z-index: 9998;
|
|
7474
|
+
border-top: 2px dotted rgba(59, 130, 246, 0.7);
|
|
7475
|
+
visibility: hidden;
|
|
7476
|
+
transform-origin: left center;
|
|
7477
|
+
transition: opacity 0.15s ease;
|
|
7478
|
+
pointer-events: none;
|
|
7429
7479
|
}
|
|
7430
|
-
`, "@jsenv/dom/src/interaction/drag/drag_gesture.js"];
|
|
7431
7480
|
|
|
7432
|
-
|
|
7481
|
+
.navi_constraint_feedback_line[data-visible] {
|
|
7482
|
+
visibility: visible;
|
|
7483
|
+
}
|
|
7484
|
+
`;
|
|
7485
|
+
const setupConstraintFeedbackLine = () => {
|
|
7486
|
+
import.meta.css = [css$2, "@jsenv/dom/src/interaction/drag/constraint_feedback_line.js"];
|
|
7433
7487
|
const constraintFeedbackLine = createConstraintFeedbackLine();
|
|
7434
7488
|
|
|
7435
7489
|
// Track last known mouse position for constraint feedback line during scroll
|
|
@@ -7502,21 +7556,6 @@ const createConstraintFeedbackLine = () => {
|
|
|
7502
7556
|
document.body.appendChild(line);
|
|
7503
7557
|
return line;
|
|
7504
7558
|
};
|
|
7505
|
-
import.meta.css = [/* css */`
|
|
7506
|
-
.navi_constraint_feedback_line {
|
|
7507
|
-
position: fixed;
|
|
7508
|
-
z-index: 9998;
|
|
7509
|
-
border-top: 2px dotted rgba(59, 130, 246, 0.7);
|
|
7510
|
-
visibility: hidden;
|
|
7511
|
-
transform-origin: left center;
|
|
7512
|
-
transition: opacity 0.15s ease;
|
|
7513
|
-
pointer-events: none;
|
|
7514
|
-
}
|
|
7515
|
-
|
|
7516
|
-
.navi_constraint_feedback_line[data-visible] {
|
|
7517
|
-
visibility: visible;
|
|
7518
|
-
}
|
|
7519
|
-
`, "@jsenv/dom/src/interaction/drag/constraint_feedback_line.js"];
|
|
7520
7559
|
|
|
7521
7560
|
installImportMetaCssBuild(import.meta);// Keep visual markers (debug markers, obstacle markers, constraint feedback line) in DOM after drag ends
|
|
7522
7561
|
const MARKER_SIZE = 12;
|
|
@@ -7524,9 +7563,197 @@ let currentDebugMarkers = [];
|
|
|
7524
7563
|
let currentConstraintMarkers = [];
|
|
7525
7564
|
let currentReferenceElementMarker = null;
|
|
7526
7565
|
let currentElementMarker = null;
|
|
7566
|
+
const css$1 = /* css */`
|
|
7567
|
+
.navi_debug_markers_container {
|
|
7568
|
+
position: fixed;
|
|
7569
|
+
top: 0;
|
|
7570
|
+
left: 0;
|
|
7571
|
+
z-index: 999998;
|
|
7572
|
+
width: 100vw;
|
|
7573
|
+
height: 100vh;
|
|
7574
|
+
pointer-events: none;
|
|
7575
|
+
overflow: hidden;
|
|
7576
|
+
--marker-size: ${MARKER_SIZE}px;
|
|
7577
|
+
}
|
|
7578
|
+
|
|
7579
|
+
.navi_debug_marker {
|
|
7580
|
+
position: absolute;
|
|
7581
|
+
pointer-events: none;
|
|
7582
|
+
}
|
|
7583
|
+
|
|
7584
|
+
/* Markers based on side rather than orientation */
|
|
7585
|
+
.navi_debug_marker[data-left],
|
|
7586
|
+
.navi_debug_marker[data-right] {
|
|
7587
|
+
width: var(--marker-size);
|
|
7588
|
+
height: 100vh;
|
|
7589
|
+
}
|
|
7590
|
+
|
|
7591
|
+
.navi_debug_marker[data-top],
|
|
7592
|
+
.navi_debug_marker[data-bottom] {
|
|
7593
|
+
width: 100vw;
|
|
7594
|
+
height: var(--marker-size);
|
|
7595
|
+
}
|
|
7596
|
+
|
|
7597
|
+
/* Gradient directions based on side, using CSS custom properties for color */
|
|
7598
|
+
.navi_debug_marker[data-left] {
|
|
7599
|
+
background: linear-gradient(
|
|
7600
|
+
to right,
|
|
7601
|
+
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7602
|
+
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7603
|
+
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7604
|
+
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7605
|
+
);
|
|
7606
|
+
}
|
|
7607
|
+
|
|
7608
|
+
.navi_debug_marker[data-right] {
|
|
7609
|
+
background: linear-gradient(
|
|
7610
|
+
to left,
|
|
7611
|
+
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7612
|
+
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7613
|
+
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7614
|
+
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7615
|
+
);
|
|
7616
|
+
}
|
|
7617
|
+
|
|
7618
|
+
.navi_debug_marker[data-top] {
|
|
7619
|
+
background: linear-gradient(
|
|
7620
|
+
to bottom,
|
|
7621
|
+
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7622
|
+
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7623
|
+
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7624
|
+
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7625
|
+
);
|
|
7626
|
+
}
|
|
7627
|
+
|
|
7628
|
+
.navi_debug_marker[data-bottom] {
|
|
7629
|
+
background: linear-gradient(
|
|
7630
|
+
to top,
|
|
7631
|
+
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7632
|
+
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7633
|
+
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7634
|
+
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7635
|
+
);
|
|
7636
|
+
}
|
|
7637
|
+
|
|
7638
|
+
.navi_debug_marker_label {
|
|
7639
|
+
position: absolute;
|
|
7640
|
+
padding: 2px 6px;
|
|
7641
|
+
color: rgb(from var(--marker-color) r g b / 1);
|
|
7642
|
+
font-weight: bold;
|
|
7643
|
+
font-size: 12px;
|
|
7644
|
+
white-space: nowrap;
|
|
7645
|
+
background: rgba(255, 255, 255, 0.9);
|
|
7646
|
+
border: 1px solid;
|
|
7647
|
+
border-color: rgb(from var(--marker-color) r g b / 1);
|
|
7648
|
+
border-radius: 3px;
|
|
7649
|
+
pointer-events: none;
|
|
7650
|
+
}
|
|
7651
|
+
|
|
7652
|
+
/* Label positioning based on side data attributes */
|
|
7653
|
+
|
|
7654
|
+
/* Left side markers - vertical with 90° rotation */
|
|
7655
|
+
.navi_debug_marker[data-left] .navi_debug_marker_label {
|
|
7656
|
+
top: 20px;
|
|
7657
|
+
left: 10px;
|
|
7658
|
+
transform: rotate(90deg);
|
|
7659
|
+
transform-origin: left center;
|
|
7660
|
+
}
|
|
7661
|
+
|
|
7662
|
+
/* Right side markers - vertical with -90° rotation */
|
|
7663
|
+
.navi_debug_marker[data-right] .navi_debug_marker_label {
|
|
7664
|
+
top: 20px;
|
|
7665
|
+
right: 10px;
|
|
7666
|
+
left: auto;
|
|
7667
|
+
transform: rotate(-90deg);
|
|
7668
|
+
transform-origin: right center;
|
|
7669
|
+
}
|
|
7670
|
+
|
|
7671
|
+
/* Top side markers - horizontal, label on the line */
|
|
7672
|
+
.navi_debug_marker[data-top] .navi_debug_marker_label {
|
|
7673
|
+
top: 0px;
|
|
7674
|
+
left: 20px;
|
|
7675
|
+
}
|
|
7676
|
+
|
|
7677
|
+
/* Bottom side markers - horizontal, label on the line */
|
|
7678
|
+
.navi_debug_marker[data-bottom] .navi_debug_marker_label {
|
|
7679
|
+
top: auto;
|
|
7680
|
+
bottom: 0px;
|
|
7681
|
+
left: 20px;
|
|
7682
|
+
}
|
|
7683
|
+
|
|
7684
|
+
.navi_obstacle_marker {
|
|
7685
|
+
position: absolute;
|
|
7686
|
+
z-index: 9999;
|
|
7687
|
+
background-color: orange;
|
|
7688
|
+
opacity: 0.6;
|
|
7689
|
+
pointer-events: none;
|
|
7690
|
+
}
|
|
7691
|
+
|
|
7692
|
+
.navi_obstacle_marker_label {
|
|
7693
|
+
position: absolute;
|
|
7694
|
+
top: 50%;
|
|
7695
|
+
left: 50%;
|
|
7696
|
+
color: white;
|
|
7697
|
+
font-weight: bold;
|
|
7698
|
+
font-size: 12px;
|
|
7699
|
+
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
|
|
7700
|
+
transform: translate(-50%, -50%);
|
|
7701
|
+
pointer-events: none;
|
|
7702
|
+
}
|
|
7703
|
+
|
|
7704
|
+
.navi_element_marker {
|
|
7705
|
+
position: absolute;
|
|
7706
|
+
z-index: 9997;
|
|
7707
|
+
background-color: var(--element-color-alpha, rgba(255, 0, 150, 0.3));
|
|
7708
|
+
border: 2px solid var(--element-color, rgb(255, 0, 150));
|
|
7709
|
+
opacity: 0.9;
|
|
7710
|
+
pointer-events: none;
|
|
7711
|
+
}
|
|
7712
|
+
|
|
7713
|
+
.navi_element_marker_label {
|
|
7714
|
+
position: absolute;
|
|
7715
|
+
top: -25px;
|
|
7716
|
+
right: 0;
|
|
7717
|
+
padding: 2px 6px;
|
|
7718
|
+
color: var(--element-color, rgb(255, 0, 150));
|
|
7719
|
+
font-weight: bold;
|
|
7720
|
+
font-size: 11px;
|
|
7721
|
+
white-space: nowrap;
|
|
7722
|
+
background: rgba(255, 255, 255, 0.9);
|
|
7723
|
+
border: 1px solid var(--element-color, rgb(255, 0, 150));
|
|
7724
|
+
border-radius: 3px;
|
|
7725
|
+
pointer-events: none;
|
|
7726
|
+
}
|
|
7727
|
+
|
|
7728
|
+
.navi_reference_element_marker {
|
|
7729
|
+
position: absolute;
|
|
7730
|
+
z-index: 9998;
|
|
7731
|
+
background-color: rgba(0, 150, 255, 0.3);
|
|
7732
|
+
border: 2px dashed rgba(0, 150, 255, 0.7);
|
|
7733
|
+
opacity: 0.8;
|
|
7734
|
+
pointer-events: none;
|
|
7735
|
+
}
|
|
7736
|
+
|
|
7737
|
+
.navi_reference_element_marker_label {
|
|
7738
|
+
position: absolute;
|
|
7739
|
+
top: -25px;
|
|
7740
|
+
left: 0;
|
|
7741
|
+
padding: 2px 6px;
|
|
7742
|
+
color: rgba(0, 150, 255, 1);
|
|
7743
|
+
font-weight: bold;
|
|
7744
|
+
font-size: 11px;
|
|
7745
|
+
white-space: nowrap;
|
|
7746
|
+
background: rgba(255, 255, 255, 0.9);
|
|
7747
|
+
border: 1px solid rgba(0, 150, 255, 0.7);
|
|
7748
|
+
border-radius: 3px;
|
|
7749
|
+
pointer-events: none;
|
|
7750
|
+
}
|
|
7751
|
+
`;
|
|
7527
7752
|
const setupDragDebugMarkers = (dragGesture, {
|
|
7528
7753
|
referenceElement
|
|
7529
7754
|
}) => {
|
|
7755
|
+
import.meta.css = [css$1, "@jsenv/dom/src/interaction/drag/drag_debug_markers.js"];
|
|
7756
|
+
|
|
7530
7757
|
// Clean up any existing persistent markers from previous drag gestures
|
|
7531
7758
|
{
|
|
7532
7759
|
// Remove any existing markers from previous gestures
|
|
@@ -7913,192 +8140,6 @@ const createReferenceElementMarker = ({
|
|
|
7913
8140
|
container.appendChild(marker);
|
|
7914
8141
|
return marker;
|
|
7915
8142
|
};
|
|
7916
|
-
import.meta.css = [/* css */`
|
|
7917
|
-
.navi_debug_markers_container {
|
|
7918
|
-
position: fixed;
|
|
7919
|
-
top: 0;
|
|
7920
|
-
left: 0;
|
|
7921
|
-
z-index: 999998;
|
|
7922
|
-
width: 100vw;
|
|
7923
|
-
height: 100vh;
|
|
7924
|
-
pointer-events: none;
|
|
7925
|
-
overflow: hidden;
|
|
7926
|
-
--marker-size: ${MARKER_SIZE}px;
|
|
7927
|
-
}
|
|
7928
|
-
|
|
7929
|
-
.navi_debug_marker {
|
|
7930
|
-
position: absolute;
|
|
7931
|
-
pointer-events: none;
|
|
7932
|
-
}
|
|
7933
|
-
|
|
7934
|
-
/* Markers based on side rather than orientation */
|
|
7935
|
-
.navi_debug_marker[data-left],
|
|
7936
|
-
.navi_debug_marker[data-right] {
|
|
7937
|
-
width: var(--marker-size);
|
|
7938
|
-
height: 100vh;
|
|
7939
|
-
}
|
|
7940
|
-
|
|
7941
|
-
.navi_debug_marker[data-top],
|
|
7942
|
-
.navi_debug_marker[data-bottom] {
|
|
7943
|
-
width: 100vw;
|
|
7944
|
-
height: var(--marker-size);
|
|
7945
|
-
}
|
|
7946
|
-
|
|
7947
|
-
/* Gradient directions based on side, using CSS custom properties for color */
|
|
7948
|
-
.navi_debug_marker[data-left] {
|
|
7949
|
-
background: linear-gradient(
|
|
7950
|
-
to right,
|
|
7951
|
-
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7952
|
-
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7953
|
-
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7954
|
-
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7955
|
-
);
|
|
7956
|
-
}
|
|
7957
|
-
|
|
7958
|
-
.navi_debug_marker[data-right] {
|
|
7959
|
-
background: linear-gradient(
|
|
7960
|
-
to left,
|
|
7961
|
-
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7962
|
-
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7963
|
-
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7964
|
-
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7965
|
-
);
|
|
7966
|
-
}
|
|
7967
|
-
|
|
7968
|
-
.navi_debug_marker[data-top] {
|
|
7969
|
-
background: linear-gradient(
|
|
7970
|
-
to bottom,
|
|
7971
|
-
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7972
|
-
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7973
|
-
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7974
|
-
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7975
|
-
);
|
|
7976
|
-
}
|
|
7977
|
-
|
|
7978
|
-
.navi_debug_marker[data-bottom] {
|
|
7979
|
-
background: linear-gradient(
|
|
7980
|
-
to top,
|
|
7981
|
-
rgba(from var(--marker-color) r g b / 0.9) 0%,
|
|
7982
|
-
rgba(from var(--marker-color) r g b / 0.7) 30%,
|
|
7983
|
-
rgba(from var(--marker-color) r g b / 0.3) 70%,
|
|
7984
|
-
rgba(from var(--marker-color) r g b / 0) 100%
|
|
7985
|
-
);
|
|
7986
|
-
}
|
|
7987
|
-
|
|
7988
|
-
.navi_debug_marker_label {
|
|
7989
|
-
position: absolute;
|
|
7990
|
-
padding: 2px 6px;
|
|
7991
|
-
color: rgb(from var(--marker-color) r g b / 1);
|
|
7992
|
-
font-weight: bold;
|
|
7993
|
-
font-size: 12px;
|
|
7994
|
-
white-space: nowrap;
|
|
7995
|
-
background: rgba(255, 255, 255, 0.9);
|
|
7996
|
-
border: 1px solid;
|
|
7997
|
-
border-color: rgb(from var(--marker-color) r g b / 1);
|
|
7998
|
-
border-radius: 3px;
|
|
7999
|
-
pointer-events: none;
|
|
8000
|
-
}
|
|
8001
|
-
|
|
8002
|
-
/* Label positioning based on side data attributes */
|
|
8003
|
-
|
|
8004
|
-
/* Left side markers - vertical with 90° rotation */
|
|
8005
|
-
.navi_debug_marker[data-left] .navi_debug_marker_label {
|
|
8006
|
-
top: 20px;
|
|
8007
|
-
left: 10px;
|
|
8008
|
-
transform: rotate(90deg);
|
|
8009
|
-
transform-origin: left center;
|
|
8010
|
-
}
|
|
8011
|
-
|
|
8012
|
-
/* Right side markers - vertical with -90° rotation */
|
|
8013
|
-
.navi_debug_marker[data-right] .navi_debug_marker_label {
|
|
8014
|
-
top: 20px;
|
|
8015
|
-
right: 10px;
|
|
8016
|
-
left: auto;
|
|
8017
|
-
transform: rotate(-90deg);
|
|
8018
|
-
transform-origin: right center;
|
|
8019
|
-
}
|
|
8020
|
-
|
|
8021
|
-
/* Top side markers - horizontal, label on the line */
|
|
8022
|
-
.navi_debug_marker[data-top] .navi_debug_marker_label {
|
|
8023
|
-
top: 0px;
|
|
8024
|
-
left: 20px;
|
|
8025
|
-
}
|
|
8026
|
-
|
|
8027
|
-
/* Bottom side markers - horizontal, label on the line */
|
|
8028
|
-
.navi_debug_marker[data-bottom] .navi_debug_marker_label {
|
|
8029
|
-
top: auto;
|
|
8030
|
-
bottom: 0px;
|
|
8031
|
-
left: 20px;
|
|
8032
|
-
}
|
|
8033
|
-
|
|
8034
|
-
.navi_obstacle_marker {
|
|
8035
|
-
position: absolute;
|
|
8036
|
-
z-index: 9999;
|
|
8037
|
-
background-color: orange;
|
|
8038
|
-
opacity: 0.6;
|
|
8039
|
-
pointer-events: none;
|
|
8040
|
-
}
|
|
8041
|
-
|
|
8042
|
-
.navi_obstacle_marker_label {
|
|
8043
|
-
position: absolute;
|
|
8044
|
-
top: 50%;
|
|
8045
|
-
left: 50%;
|
|
8046
|
-
color: white;
|
|
8047
|
-
font-weight: bold;
|
|
8048
|
-
font-size: 12px;
|
|
8049
|
-
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
|
|
8050
|
-
transform: translate(-50%, -50%);
|
|
8051
|
-
pointer-events: none;
|
|
8052
|
-
}
|
|
8053
|
-
|
|
8054
|
-
.navi_element_marker {
|
|
8055
|
-
position: absolute;
|
|
8056
|
-
z-index: 9997;
|
|
8057
|
-
background-color: var(--element-color-alpha, rgba(255, 0, 150, 0.3));
|
|
8058
|
-
border: 2px solid var(--element-color, rgb(255, 0, 150));
|
|
8059
|
-
opacity: 0.9;
|
|
8060
|
-
pointer-events: none;
|
|
8061
|
-
}
|
|
8062
|
-
|
|
8063
|
-
.navi_element_marker_label {
|
|
8064
|
-
position: absolute;
|
|
8065
|
-
top: -25px;
|
|
8066
|
-
right: 0;
|
|
8067
|
-
padding: 2px 6px;
|
|
8068
|
-
color: var(--element-color, rgb(255, 0, 150));
|
|
8069
|
-
font-weight: bold;
|
|
8070
|
-
font-size: 11px;
|
|
8071
|
-
white-space: nowrap;
|
|
8072
|
-
background: rgba(255, 255, 255, 0.9);
|
|
8073
|
-
border: 1px solid var(--element-color, rgb(255, 0, 150));
|
|
8074
|
-
border-radius: 3px;
|
|
8075
|
-
pointer-events: none;
|
|
8076
|
-
}
|
|
8077
|
-
|
|
8078
|
-
.navi_reference_element_marker {
|
|
8079
|
-
position: absolute;
|
|
8080
|
-
z-index: 9998;
|
|
8081
|
-
background-color: rgba(0, 150, 255, 0.3);
|
|
8082
|
-
border: 2px dashed rgba(0, 150, 255, 0.7);
|
|
8083
|
-
opacity: 0.8;
|
|
8084
|
-
pointer-events: none;
|
|
8085
|
-
}
|
|
8086
|
-
|
|
8087
|
-
.navi_reference_element_marker_label {
|
|
8088
|
-
position: absolute;
|
|
8089
|
-
top: -25px;
|
|
8090
|
-
left: 0;
|
|
8091
|
-
padding: 2px 6px;
|
|
8092
|
-
color: rgba(0, 150, 255, 1);
|
|
8093
|
-
font-weight: bold;
|
|
8094
|
-
font-size: 11px;
|
|
8095
|
-
white-space: nowrap;
|
|
8096
|
-
background: rgba(255, 255, 255, 0.9);
|
|
8097
|
-
border: 1px solid rgba(0, 150, 255, 0.7);
|
|
8098
|
-
border-radius: 3px;
|
|
8099
|
-
pointer-events: none;
|
|
8100
|
-
}
|
|
8101
|
-
`, "@jsenv/dom/src/interaction/drag/drag_debug_markers.js"];
|
|
8102
8143
|
|
|
8103
8144
|
const initDragConstraints = (
|
|
8104
8145
|
dragGesture,
|
|
@@ -8730,6 +8771,7 @@ const createStickyFrontierOnAxis = (
|
|
|
8730
8771
|
const dragStyleController = createStyleController("drag_to_move");
|
|
8731
8772
|
|
|
8732
8773
|
const createDragToMoveGestureController = ({
|
|
8774
|
+
cloneOnDrag = false,
|
|
8733
8775
|
stickyFrontiers = true,
|
|
8734
8776
|
// Padding to reduce the area used to autoscroll by this amount (applied after sticky frontiers)
|
|
8735
8777
|
// This creates an invisible space around the area where elements cannot be dragged
|
|
@@ -8743,8 +8785,8 @@ const createDragToMoveGestureController = ({
|
|
|
8743
8785
|
// position due to obstacles, boundaries, or other constraints. The line originates from where the mouse
|
|
8744
8786
|
// initially grabbed the element, but moves with the element to show the current anchor position.
|
|
8745
8787
|
// It becomes visible when there's a significant distance between mouse and grab point.
|
|
8746
|
-
showConstraintFeedbackLine =
|
|
8747
|
-
showDebugMarkers =
|
|
8788
|
+
showConstraintFeedbackLine = false,
|
|
8789
|
+
showDebugMarkers = false,
|
|
8748
8790
|
resetPositionAfterRelease = false,
|
|
8749
8791
|
...options
|
|
8750
8792
|
} = {}) => {
|
|
@@ -8752,6 +8794,18 @@ const createDragToMoveGestureController = ({
|
|
|
8752
8794
|
dragGesture,
|
|
8753
8795
|
{ element, referenceElement, elementToMove, convertScrollablePosition },
|
|
8754
8796
|
) => {
|
|
8797
|
+
if (cloneOnDrag) {
|
|
8798
|
+
const { grabEvent } = dragGesture.gestureInfo;
|
|
8799
|
+
const ghostData = createDragGhost(element, {
|
|
8800
|
+
clientX: grabEvent.clientX,
|
|
8801
|
+
clientY: grabEvent.clientY,
|
|
8802
|
+
});
|
|
8803
|
+
elementToMove = ghostData.ghostWrapper;
|
|
8804
|
+
dragGesture.gestureInfo.elementImpacted = ghostData.ghostWrapper;
|
|
8805
|
+
dragGesture.addReleaseCallback(() => {
|
|
8806
|
+
ghostData.remove();
|
|
8807
|
+
});
|
|
8808
|
+
}
|
|
8755
8809
|
const direction = dragGesture.gestureInfo.direction;
|
|
8756
8810
|
// const dragGestureName = dragGesture.gestureInfo.name;
|
|
8757
8811
|
const scrollContainer = dragGesture.gestureInfo.scrollContainer;
|
|
@@ -9021,6 +9075,31 @@ const createDragToMoveGestureController = ({
|
|
|
9021
9075
|
return dragGestureController;
|
|
9022
9076
|
};
|
|
9023
9077
|
|
|
9078
|
+
const createDragGhost = (element, pointerEvent) => {
|
|
9079
|
+
const rect = element.getBoundingClientRect();
|
|
9080
|
+
|
|
9081
|
+
const ghost = element.cloneNode(true);
|
|
9082
|
+
ghost.dataset.dragging = "";
|
|
9083
|
+
ghost.style.pointerEvents = "none";
|
|
9084
|
+
// transform-origin set to pointer position within the element for natural scale expansion
|
|
9085
|
+
const originX = pointerEvent.clientX - rect.left;
|
|
9086
|
+
const originY = pointerEvent.clientY - rect.top;
|
|
9087
|
+
ghost.style.transformOrigin = `${originX}px ${originY}px`;
|
|
9088
|
+
|
|
9089
|
+
const ghostWrapper = document.createElement("div");
|
|
9090
|
+
ghostWrapper.style.cssText = `position: absolute; pointer-events: none; z-index: 9999; top: ${rect.top + window.scrollY}px; left: ${rect.left + window.scrollX}px; width: ${rect.width}px;`;
|
|
9091
|
+
ghostWrapper.appendChild(ghost);
|
|
9092
|
+
document.body.appendChild(ghostWrapper);
|
|
9093
|
+
|
|
9094
|
+
return {
|
|
9095
|
+
ghost,
|
|
9096
|
+
ghostWrapper,
|
|
9097
|
+
remove: () => {
|
|
9098
|
+
ghostWrapper.remove();
|
|
9099
|
+
},
|
|
9100
|
+
};
|
|
9101
|
+
};
|
|
9102
|
+
|
|
9024
9103
|
const startDragToResizeGesture = (
|
|
9025
9104
|
pointerdownEvent,
|
|
9026
9105
|
{ onDragStart, onDrag, onRelease, ...options },
|
|
@@ -9096,7 +9175,7 @@ const getResizeDirection = (element) => {
|
|
|
9096
9175
|
* @returns {Object|null} Drop target info with elementSide or null if no valid target found
|
|
9097
9176
|
*/
|
|
9098
9177
|
const getDropTargetInfo = (gestureInfo, targetElements) => {
|
|
9099
|
-
const dragElement = gestureInfo.element;
|
|
9178
|
+
const dragElement = gestureInfo.elementImpacted || gestureInfo.element;
|
|
9100
9179
|
const dragElementRect = dragElement.getBoundingClientRect();
|
|
9101
9180
|
const intersectingTargets = [];
|
|
9102
9181
|
let someTargetIsCol;
|
|
@@ -9141,12 +9220,13 @@ const getDropTargetInfo = (gestureInfo, targetElements) => {
|
|
|
9141
9220
|
const elementsUnderDragElement = document.elementsFromPoint(clientX, clientY);
|
|
9142
9221
|
let targetElement = null;
|
|
9143
9222
|
let targetIndex = -1;
|
|
9223
|
+
let intersectingIndex = -1;
|
|
9144
9224
|
for (const element of elementsUnderDragElement) {
|
|
9145
9225
|
// First, check if the element itself is a target
|
|
9146
9226
|
const directIndex = intersectingTargets.indexOf(element);
|
|
9147
9227
|
if (directIndex !== -1) {
|
|
9148
9228
|
targetElement = element;
|
|
9149
|
-
|
|
9229
|
+
intersectingIndex = directIndex;
|
|
9150
9230
|
break;
|
|
9151
9231
|
}
|
|
9152
9232
|
// Special case: if element is <td> or <th> and not in targets,
|
|
@@ -9167,7 +9247,7 @@ const getDropTargetInfo = (gestureInfo, targetElements) => {
|
|
|
9167
9247
|
break try_col;
|
|
9168
9248
|
}
|
|
9169
9249
|
targetElement = tableCellCol;
|
|
9170
|
-
|
|
9250
|
+
intersectingIndex = colIndex;
|
|
9171
9251
|
break;
|
|
9172
9252
|
}
|
|
9173
9253
|
try_tr: {
|
|
@@ -9180,26 +9260,31 @@ const getDropTargetInfo = (gestureInfo, targetElements) => {
|
|
|
9180
9260
|
break try_tr;
|
|
9181
9261
|
}
|
|
9182
9262
|
targetElement = tableRow;
|
|
9183
|
-
|
|
9263
|
+
intersectingIndex = intersectingTargets.indexOf(tableRow);
|
|
9184
9264
|
break;
|
|
9185
9265
|
}
|
|
9186
9266
|
}
|
|
9187
9267
|
if (!targetElement) {
|
|
9188
9268
|
targetElement = intersectingTargets[0];
|
|
9189
|
-
|
|
9269
|
+
intersectingIndex = 0;
|
|
9190
9270
|
}
|
|
9271
|
+
targetIndex = targetElements.indexOf(targetElement);
|
|
9191
9272
|
|
|
9192
9273
|
// Determine position within the target for both axes
|
|
9193
9274
|
const targetRect = targetElement.getBoundingClientRect();
|
|
9194
9275
|
const targetCenterX = targetRect.left + targetRect.width / 2;
|
|
9195
9276
|
const targetCenterY = targetRect.top + targetRect.height / 2;
|
|
9196
9277
|
const result = {
|
|
9278
|
+
// Index of the target element within the original targetElements array
|
|
9197
9279
|
index: targetIndex,
|
|
9198
9280
|
element: targetElement,
|
|
9199
9281
|
elementSide: {
|
|
9200
9282
|
x: dragElementRect.left < targetCenterX ? "start" : "end",
|
|
9201
9283
|
y: dragElementRect.top < targetCenterY ? "start" : "end",
|
|
9202
9284
|
},
|
|
9285
|
+
// Index within the intersecting subset — could be useful to know how many
|
|
9286
|
+
// elements were overlapping, but rarely needed in practice
|
|
9287
|
+
intersectingIndex,
|
|
9203
9288
|
intersecting: intersectingTargets,
|
|
9204
9289
|
};
|
|
9205
9290
|
return result;
|
|
@@ -9284,15 +9369,16 @@ installImportMetaCssBuild(import.meta);/**
|
|
|
9284
9369
|
*
|
|
9285
9370
|
* The element should have a CSS "top" value specified (e.g., top: 10px).
|
|
9286
9371
|
*/
|
|
9287
|
-
|
|
9372
|
+
const css = /* css */`
|
|
9288
9373
|
[data-position-sticky-placeholder] {
|
|
9289
9374
|
position: static !important;
|
|
9290
9375
|
width: auto !important;
|
|
9291
9376
|
height: auto !important;
|
|
9292
9377
|
opacity: 0 !important;
|
|
9293
9378
|
}
|
|
9294
|
-
|
|
9379
|
+
`;
|
|
9295
9380
|
const initPositionSticky = element => {
|
|
9381
|
+
import.meta.css = [css, "@jsenv/dom/src/position/position_sticky.js"];
|
|
9296
9382
|
const computedStyle = getComputedStyle(element);
|
|
9297
9383
|
const topCssValue = computedStyle.top;
|
|
9298
9384
|
const top = parseFloat(topCssValue);
|
|
@@ -9930,6 +10016,8 @@ const pickPositionRelativeTo = (
|
|
|
9930
10016
|
positionYFixed,
|
|
9931
10017
|
alignToViewportEdgeWhenAnchorNearEdge = 0,
|
|
9932
10018
|
minLeft = 0,
|
|
10019
|
+
spacing = 0,
|
|
10020
|
+
viewportSpacing = 0,
|
|
9933
10021
|
} = {},
|
|
9934
10022
|
) => {
|
|
9935
10023
|
|
|
@@ -9944,12 +10032,10 @@ const pickPositionRelativeTo = (
|
|
|
9944
10032
|
top: elementTop,
|
|
9945
10033
|
bottom: elementBottom,
|
|
9946
10034
|
} = elementRect;
|
|
9947
|
-
const
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
bottom: anchorBottom,
|
|
9952
|
-
} = anchorRect;
|
|
10035
|
+
const anchorLeft = snapToPixel(anchorRect.left);
|
|
10036
|
+
const anchorTop = snapToPixel(anchorRect.top);
|
|
10037
|
+
const anchorRight = snapToPixel(anchorRect.right);
|
|
10038
|
+
const anchorBottom = snapToPixel(anchorRect.bottom);
|
|
9953
10039
|
const elementWidth = elementRight - elementLeft;
|
|
9954
10040
|
const elementHeight = elementBottom - elementTop;
|
|
9955
10041
|
const anchorWidth = anchorRight - anchorLeft;
|
|
@@ -9992,16 +10078,16 @@ const pickPositionRelativeTo = (
|
|
|
9992
10078
|
// Compute effective space for a given Y value
|
|
9993
10079
|
const spaceFor = (y) => {
|
|
9994
10080
|
if (y === "above") {
|
|
9995
|
-
return spaceAbove;
|
|
10081
|
+
return spaceAbove - spacing - viewportSpacing;
|
|
9996
10082
|
}
|
|
9997
10083
|
if (y === "above-overlap") {
|
|
9998
|
-
return spaceAbove + anchorHeight;
|
|
10084
|
+
return spaceAbove + anchorHeight - viewportSpacing;
|
|
9999
10085
|
}
|
|
10000
10086
|
if (y === "below") {
|
|
10001
|
-
return spaceBelow;
|
|
10087
|
+
return spaceBelow - spacing - viewportSpacing;
|
|
10002
10088
|
}
|
|
10003
10089
|
if (y === "below-overlap") {
|
|
10004
|
-
return spaceBelow + anchorHeight;
|
|
10090
|
+
return spaceBelow + anchorHeight - viewportSpacing;
|
|
10005
10091
|
}
|
|
10006
10092
|
return Infinity; // center
|
|
10007
10093
|
};
|
|
@@ -10049,16 +10135,16 @@ const pickPositionRelativeTo = (
|
|
|
10049
10135
|
// Compute effective space for a given X value
|
|
10050
10136
|
const spaceFor = (x) => {
|
|
10051
10137
|
if (x === "to-the-left") {
|
|
10052
|
-
return spaceLeft;
|
|
10138
|
+
return spaceLeft - spacing - viewportSpacing;
|
|
10053
10139
|
}
|
|
10054
10140
|
if (x === "left-aligned") {
|
|
10055
|
-
return viewportWidth - anchorLeft;
|
|
10141
|
+
return viewportWidth - anchorLeft - viewportSpacing;
|
|
10056
10142
|
}
|
|
10057
10143
|
if (x === "right-aligned") {
|
|
10058
|
-
return anchorRight;
|
|
10144
|
+
return anchorRight - viewportSpacing;
|
|
10059
10145
|
}
|
|
10060
10146
|
if (x === "to-the-right") {
|
|
10061
|
-
return spaceRight;
|
|
10147
|
+
return spaceRight - spacing - viewportSpacing;
|
|
10062
10148
|
}
|
|
10063
10149
|
return Infinity; // center
|
|
10064
10150
|
};
|
|
@@ -10095,7 +10181,7 @@ const pickPositionRelativeTo = (
|
|
|
10095
10181
|
let elementPositionLeft;
|
|
10096
10182
|
{
|
|
10097
10183
|
if (finalX === "to-the-left") {
|
|
10098
|
-
elementPositionLeft = anchorLeft - elementWidth;
|
|
10184
|
+
elementPositionLeft = anchorLeft - elementWidth - spacing;
|
|
10099
10185
|
} else if (finalX === "left-aligned") {
|
|
10100
10186
|
elementPositionLeft = anchorLeft;
|
|
10101
10187
|
} else if (finalX === "center") {
|
|
@@ -10132,13 +10218,16 @@ const pickPositionRelativeTo = (
|
|
|
10132
10218
|
elementPositionLeft = anchorRight - elementWidth;
|
|
10133
10219
|
} else {
|
|
10134
10220
|
// "to-the-right"
|
|
10135
|
-
elementPositionLeft = anchorRight;
|
|
10221
|
+
elementPositionLeft = anchorRight + spacing;
|
|
10136
10222
|
}
|
|
10137
|
-
// Constrain horizontal position to viewport boundaries
|
|
10138
|
-
if (elementPositionLeft <
|
|
10139
|
-
elementPositionLeft =
|
|
10140
|
-
} else if (
|
|
10141
|
-
elementPositionLeft
|
|
10223
|
+
// Constrain horizontal position to viewport boundaries (with viewportSpacing margin)
|
|
10224
|
+
if (elementPositionLeft < viewportSpacing) {
|
|
10225
|
+
elementPositionLeft = viewportSpacing;
|
|
10226
|
+
} else if (
|
|
10227
|
+
elementPositionLeft + elementWidth >
|
|
10228
|
+
viewportWidth - viewportSpacing
|
|
10229
|
+
) {
|
|
10230
|
+
elementPositionLeft = viewportWidth - viewportSpacing - elementWidth;
|
|
10142
10231
|
}
|
|
10143
10232
|
}
|
|
10144
10233
|
|
|
@@ -10146,11 +10235,14 @@ const pickPositionRelativeTo = (
|
|
|
10146
10235
|
let elementPositionTop;
|
|
10147
10236
|
{
|
|
10148
10237
|
if (finalY === "above") {
|
|
10149
|
-
|
|
10150
|
-
|
|
10238
|
+
// top is always anchorTop - elementHeight - spacing — max-height truncates if needed.
|
|
10239
|
+
const idealTop = anchorTop - elementHeight - spacing;
|
|
10240
|
+
elementPositionTop =
|
|
10241
|
+
idealTop < viewportSpacing ? viewportSpacing : idealTop;
|
|
10151
10242
|
} else if (finalY === "above-overlap") {
|
|
10152
10243
|
const idealTop = anchorBottom - elementHeight;
|
|
10153
|
-
elementPositionTop =
|
|
10244
|
+
elementPositionTop =
|
|
10245
|
+
idealTop < viewportSpacing ? viewportSpacing : idealTop;
|
|
10154
10246
|
} else if (finalY === "center") {
|
|
10155
10247
|
elementPositionTop = anchorTop + anchorHeight / 2 - elementHeight / 2;
|
|
10156
10248
|
} else if (finalY === "below-overlap") {
|
|
@@ -10159,7 +10251,9 @@ const pickPositionRelativeTo = (
|
|
|
10159
10251
|
idealTop % 1 === 0 ? idealTop : Math.floor(idealTop) + 1;
|
|
10160
10252
|
} else {
|
|
10161
10253
|
// "below"
|
|
10162
|
-
|
|
10254
|
+
// top is always anchorBottom + spacing — max-height (via --space-available) truncates
|
|
10255
|
+
// the element height so it doesn't overflow the viewport bottom.
|
|
10256
|
+
const idealTop = anchorBottom + spacing;
|
|
10163
10257
|
elementPositionTop =
|
|
10164
10258
|
idealTop % 1 === 0 ? idealTop : Math.floor(idealTop) + 1;
|
|
10165
10259
|
}
|
|
@@ -10176,13 +10270,26 @@ const pickPositionRelativeTo = (
|
|
|
10176
10270
|
|
|
10177
10271
|
// Get document scroll for final coordinate conversion
|
|
10178
10272
|
const { scrollLeft, scrollTop } = document.documentElement;
|
|
10179
|
-
const elementDocumentLeft = elementPositionLeft + scrollLeft;
|
|
10180
|
-
const elementDocumentTop = elementPositionTop + scrollTop;
|
|
10273
|
+
const elementDocumentLeft = snapToPixel(elementPositionLeft + scrollLeft);
|
|
10274
|
+
const elementDocumentTop = snapToPixel(elementPositionTop + scrollTop);
|
|
10181
10275
|
const anchorDocumentLeft = anchorLeft + scrollLeft;
|
|
10182
10276
|
const anchorDocumentTop = anchorTop + scrollTop;
|
|
10183
10277
|
const anchorDocumentRight = anchorRight + scrollLeft;
|
|
10184
10278
|
const anchorDocumentBottom = anchorBottom + scrollTop;
|
|
10185
10279
|
|
|
10280
|
+
// For overlap variants the element starts at the anchor edge (not past it),
|
|
10281
|
+
// so the usable space includes the anchor dimension.
|
|
10282
|
+
// spacing (gap between anchor and element) and viewportSpacing are subtracted
|
|
10283
|
+
// so callers get the net usable space directly.
|
|
10284
|
+
const effectiveSpaceAbove =
|
|
10285
|
+
(finalY === "above-overlap" ? spaceAbove + anchorHeight : spaceAbove) -
|
|
10286
|
+
(finalY === "above" ? spacing : 0) -
|
|
10287
|
+
viewportSpacing;
|
|
10288
|
+
const effectiveSpaceBelow =
|
|
10289
|
+
(finalY === "below-overlap" ? spaceBelow + anchorHeight : spaceBelow) -
|
|
10290
|
+
(finalY === "below" ? spacing : 0) -
|
|
10291
|
+
viewportSpacing;
|
|
10292
|
+
|
|
10186
10293
|
return {
|
|
10187
10294
|
positionX: finalX,
|
|
10188
10295
|
positionY: finalY,
|
|
@@ -10194,10 +10301,10 @@ const pickPositionRelativeTo = (
|
|
|
10194
10301
|
anchorTop: anchorDocumentTop,
|
|
10195
10302
|
anchorRight: anchorDocumentRight,
|
|
10196
10303
|
anchorBottom: anchorDocumentBottom,
|
|
10197
|
-
spaceLeft,
|
|
10198
|
-
spaceRight,
|
|
10199
|
-
spaceAbove,
|
|
10200
|
-
spaceBelow,
|
|
10304
|
+
spaceLeft: spaceLeft - viewportSpacing,
|
|
10305
|
+
spaceRight: spaceRight - viewportSpacing,
|
|
10306
|
+
spaceAbove: effectiveSpaceAbove,
|
|
10307
|
+
spaceBelow: effectiveSpaceBelow,
|
|
10201
10308
|
};
|
|
10202
10309
|
};
|
|
10203
10310
|
|
|
@@ -11973,17 +12080,6 @@ const getWidthWithoutTransition = (element) =>
|
|
|
11973
12080
|
const getHeightWithoutTransition = (element) =>
|
|
11974
12081
|
getHeight$1(element, transitionStyleController);
|
|
11975
12082
|
|
|
11976
|
-
const getPaddingSizes = (element) => {
|
|
11977
|
-
const { paddingLeft, paddingRight, paddingTop, paddingBottom } =
|
|
11978
|
-
window.getComputedStyle(element, null);
|
|
11979
|
-
return {
|
|
11980
|
-
left: parseFloat(paddingLeft),
|
|
11981
|
-
right: parseFloat(paddingRight),
|
|
11982
|
-
top: parseFloat(paddingTop),
|
|
11983
|
-
bottom: parseFloat(paddingBottom),
|
|
11984
|
-
};
|
|
11985
|
-
};
|
|
11986
|
-
|
|
11987
12083
|
const getInnerHeight = (element) => {
|
|
11988
12084
|
// Always subtract paddings and borders to get the content height
|
|
11989
12085
|
const paddingSizes = getPaddingSizes(element);
|
|
@@ -13324,4 +13420,4 @@ const useResizeStatus = (elementRef, { as = "number" } = {}) => {
|
|
|
13324
13420
|
};
|
|
13325
13421
|
};
|
|
13326
13422
|
|
|
13327
|
-
export { EASING, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, canInterceptKeys, captureScrollState, contrastColor, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dragAfterThreshold, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findFocusable, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isSameColor, isScrollable, measureScrollbar, mergeOneStyle, mergeTwoStyles, normalizeStyles, parseStyle, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, resolveCSSColor, resolveCSSSize, resolveColorLuminance, resolveOklchLightness, scrollIntoViewScoped, scrollIntoViewWithStickyAwareness, setAttribute, setAttributes, setStyles, startDragToResizeGesture, stickyAsRelativeCoords, stringifyStyle, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect };
|
|
13423
|
+
export { EASING, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, canInterceptKeys, captureScrollState, contrastColor, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dragAfterThreshold, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findFocusable, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isSameColor, isScrollable, measureScrollbar, mergeOneStyle, mergeTwoStyles, normalizeStyle, normalizeStyles, parseStyle, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, resolveCSSColor, resolveCSSSize, resolveColorLuminance, resolveOklchLightness, scrollIntoViewScoped, scrollIntoViewWithStickyAwareness, setAttribute, setAttributes, setStyles, snapToPixel, startDragToResizeGesture, stickyAsRelativeCoords, stringifyStyle, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect };
|