Drawing rail: fix phone layout, stray pointer, and make it movable
Three problems reported from a device after v15, two of them the same mistake. Phone layout filled the screen. The strip's rule and ol-ext's `.ol-control.ol-bar.ol-left` both weigh (0,3,0), so stylesheet order decided which won — and the built app loads them in the opposite order from the test harness, which is why this passed review and failed on the phone. With ol-ext winning, `top: 50%` survived next to `bottom: 12px` and the bar stretched between them. The rail's selectors now carry enough classes to win outright rather than by luck; both orders are verified. Stray dark shape beside the option bar was ol-ext's pointer triangle. Same cause: `.ol-editbar-rail .ol-option-bar::before` (0,2,1) never beat `.ol-control.ol-bar.ol-left .ol-option-bar:before` (0,4,1). The rail covered the settings toggle. `.offcanvas-toggle-left` sits at left:10px, vertically centred — precisely where ol-ext docks a left bar, so the rail landed on top of it. The rail now starts at left:66px, clear of the 44px toggle, and can be dragged anywhere by a grip at its top. The position is remembered in localStorage, clamped so the rail cannot be pushed off-map, and reset by double-clicking the grip. Dragging is limited to the grip so a mis-aimed tap moves nothing, and is off below the phone breakpoint where the bar is docked above the dock. Service Worker v15 -> v16. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e9bb4d81c9
commit
19dc000efe
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
dist/assets/index-4Lh4FMTD.js.map
vendored
Normal file
1
dist/assets/index-4Lh4FMTD.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/assets/index-9k1yuCxX.js.map
vendored
1
dist/assets/index-9k1yuCxX.js.map
vendored
File diff suppressed because one or more lines are too long
65
dist/index.html
vendored
65
dist/index.html
vendored
@ -1536,7 +1536,11 @@
|
|||||||
instead of dropping downwards. We keep that behaviour and override only
|
instead of dropping downwards. We keep that behaviour and override only
|
||||||
the layout.
|
the layout.
|
||||||
================================================================ */
|
================================================================ */
|
||||||
.ol-editbar.ol-editbar-rail {
|
.ol-control.ol-bar.ol-editbar.ol-editbar-rail {
|
||||||
|
/* Clear of the left off-canvas toggle, which sits at left:10px and is
|
||||||
|
44px wide, vertically centred — exactly where ol-ext docks a left bar.
|
||||||
|
Officers can drag the rail anywhere from here; see the grip below. */
|
||||||
|
left: 66px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 30px);
|
grid-template-columns: repeat(2, 30px);
|
||||||
gap: 3px;
|
gap: 3px;
|
||||||
@ -1564,6 +1568,51 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- drag grip ---------------------------------------------------
|
||||||
|
The rail can be moved: officers work at different zoom levels and on
|
||||||
|
different hands, and a fixed panel always covers something. Dragging is
|
||||||
|
deliberately restricted to this grip so a mis-aimed tap on a tool never
|
||||||
|
moves the palette instead of selecting.
|
||||||
|
---------------------------------------------------------------- */
|
||||||
|
.ol-editbar-rail .ol-rail-grip {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
height: 18px;
|
||||||
|
margin: -2px 0 2px;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
cursor: grab;
|
||||||
|
touch-action: none;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.ol-editbar-rail .ol-rail-grip:hover {
|
||||||
|
background: var(--muted);
|
||||||
|
color: var(--foreground);
|
||||||
|
}
|
||||||
|
.ol-editbar-rail .ol-rail-grip:active,
|
||||||
|
.ol-editbar-rail.is-dragging .ol-rail-grip {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
.ol-editbar-rail .ol-rail-grip::before {
|
||||||
|
content: "";
|
||||||
|
width: 22px;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: currentColor;
|
||||||
|
opacity: 0.45;
|
||||||
|
}
|
||||||
|
.ol-editbar-rail.is-dragging {
|
||||||
|
opacity: 0.9;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
/* No dragging on phones — the strip is docked above the dock bar. */
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.ol-editbar-rail .ol-rail-grip {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Group heading — spans both columns. */
|
/* Group heading — spans both columns. */
|
||||||
.ol-editbar-rail .ol-rail-label {
|
.ol-editbar-rail .ol-rail-label {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
@ -1680,8 +1729,14 @@
|
|||||||
margin: 0 0 0 8px !important;
|
margin: 0 0 0 8px !important;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.ol-editbar-rail .ol-option-bar::before {
|
/* ol-ext draws a little pointer triangle on the option bar. It reads as a
|
||||||
|
stray dark button next to the flyout, and it is declared at
|
||||||
|
`.ol-control.ol-bar.ol-left .ol-option-bar:before` (0,4,1) — so the
|
||||||
|
selector that hides it has to be at least as specific. */
|
||||||
|
.ol-control.ol-bar.ol-editbar-rail.ol-left .ol-option-bar::before,
|
||||||
|
.ol-control.ol-bar.ol-editbar-rail.ol-left .ol-option-bar::after {
|
||||||
display: none;
|
display: none;
|
||||||
|
content: none;
|
||||||
}
|
}
|
||||||
.ol-editbar-rail .ol-option-bar .ol-control {
|
.ol-editbar-rail .ol-option-bar .ol-control {
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
@ -1725,7 +1780,7 @@
|
|||||||
/* `.ol-left` is repeated here for specificity: ol-ext's own
|
/* `.ol-left` is repeated here for specificity: ol-ext's own
|
||||||
`.ol-control.ol-bar.ol-left` sets top/transform, and without matching
|
`.ol-control.ol-bar.ol-left` sets top/transform, and without matching
|
||||||
it the rail stays vertically centred and stretches to `bottom`. */
|
it the rail stays vertically centred and stretches to `bottom`. */
|
||||||
.ol-editbar.ol-editbar-rail.ol-left {
|
.ol-control.ol-bar.ol-editbar.ol-editbar-rail.ol-left {
|
||||||
/* NOTE: display must NOT be !important — ol-ext toggles the bar with an
|
/* NOTE: display must NOT be !important — ol-ext toggles the bar with an
|
||||||
inline display:none/'' (setVisible). An !important here would beat
|
inline display:none/'' (setVisible). An !important here would beat
|
||||||
that and keep the toolbar visible even when Draw mode is off. */
|
that and keep the toolbar visible even when Draw mode is off. */
|
||||||
@ -1748,7 +1803,7 @@
|
|||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
}
|
}
|
||||||
.ol-editbar.ol-editbar-rail.ol-left::-webkit-scrollbar {
|
.ol-control.ol-bar.ol-editbar.ol-editbar-rail.ol-left::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1820,7 +1875,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<script type="module" crossorigin src="/assets/index-9k1yuCxX.js"></script>
|
<script type="module" crossorigin src="/assets/index-4Lh4FMTD.js"></script>
|
||||||
<link rel="modulepreload" crossorigin href="/assets/openlayers-J9qS6Th1.js">
|
<link rel="modulepreload" crossorigin href="/assets/openlayers-J9qS6Th1.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/pako-Xa-UToif.js">
|
<link rel="modulepreload" crossorigin href="/assets/pako-Xa-UToif.js">
|
||||||
<link rel="modulepreload" crossorigin href="/assets/geotiff-BaoeLn6q.js">
|
<link rel="modulepreload" crossorigin href="/assets/geotiff-BaoeLn6q.js">
|
||||||
|
|||||||
11
dist/sw.js
vendored
11
dist/sw.js
vendored
@ -80,7 +80,16 @@
|
|||||||
// Icon. On phones it becomes a horizontally scrolling strip above the
|
// Icon. On phones it becomes a horizontally scrolling strip above the
|
||||||
// dock, which retires the previous two-row wrapping workaround.
|
// dock, which retires the previous two-row wrapping workaround.
|
||||||
// New hashed bundle + updated index.html shell.
|
// New hashed bundle + updated index.html shell.
|
||||||
const CACHE_VERSION = 'v15';
|
// v16: Three fixes to the v15 rail, all reported from the field. The phone
|
||||||
|
// layout stretched down the whole screen because its rule only tied with
|
||||||
|
// ol-ext's on specificity, so stylesheet order decided the winner and the
|
||||||
|
// built app ordered them the other way round from the test harness. A
|
||||||
|
// stray dark shape beside the option bar was ol-ext's pointer triangle,
|
||||||
|
// hidden by a selector that was likewise not specific enough. And the rail
|
||||||
|
// covered the left off-canvas toggle, which sits at exactly the position
|
||||||
|
// ol-ext docks a left bar to — so the rail now starts clear of it and can
|
||||||
|
// be dragged anywhere by its grip, with the position remembered.
|
||||||
|
const CACHE_VERSION = 'v16';
|
||||||
const SHELL_CACHE = `shell-${CACHE_VERSION}`;
|
const SHELL_CACHE = `shell-${CACHE_VERSION}`;
|
||||||
const MODULES_CACHE = `modules-${CACHE_VERSION}`;
|
const MODULES_CACHE = `modules-${CACHE_VERSION}`;
|
||||||
const API_CACHE = `api-${CACHE_VERSION}`;
|
const API_CACHE = `api-${CACHE_VERSION}`;
|
||||||
|
|||||||
63
index.html
63
index.html
@ -1536,7 +1536,11 @@
|
|||||||
instead of dropping downwards. We keep that behaviour and override only
|
instead of dropping downwards. We keep that behaviour and override only
|
||||||
the layout.
|
the layout.
|
||||||
================================================================ */
|
================================================================ */
|
||||||
.ol-editbar.ol-editbar-rail {
|
.ol-control.ol-bar.ol-editbar.ol-editbar-rail {
|
||||||
|
/* Clear of the left off-canvas toggle, which sits at left:10px and is
|
||||||
|
44px wide, vertically centred — exactly where ol-ext docks a left bar.
|
||||||
|
Officers can drag the rail anywhere from here; see the grip below. */
|
||||||
|
left: 66px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 30px);
|
grid-template-columns: repeat(2, 30px);
|
||||||
gap: 3px;
|
gap: 3px;
|
||||||
@ -1564,6 +1568,51 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- drag grip ---------------------------------------------------
|
||||||
|
The rail can be moved: officers work at different zoom levels and on
|
||||||
|
different hands, and a fixed panel always covers something. Dragging is
|
||||||
|
deliberately restricted to this grip so a mis-aimed tap on a tool never
|
||||||
|
moves the palette instead of selecting.
|
||||||
|
---------------------------------------------------------------- */
|
||||||
|
.ol-editbar-rail .ol-rail-grip {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
height: 18px;
|
||||||
|
margin: -2px 0 2px;
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--muted-foreground);
|
||||||
|
cursor: grab;
|
||||||
|
touch-action: none;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
}
|
||||||
|
.ol-editbar-rail .ol-rail-grip:hover {
|
||||||
|
background: var(--muted);
|
||||||
|
color: var(--foreground);
|
||||||
|
}
|
||||||
|
.ol-editbar-rail .ol-rail-grip:active,
|
||||||
|
.ol-editbar-rail.is-dragging .ol-rail-grip {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
.ol-editbar-rail .ol-rail-grip::before {
|
||||||
|
content: "";
|
||||||
|
width: 22px;
|
||||||
|
height: 4px;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: currentColor;
|
||||||
|
opacity: 0.45;
|
||||||
|
}
|
||||||
|
.ol-editbar-rail.is-dragging {
|
||||||
|
opacity: 0.9;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
/* No dragging on phones — the strip is docked above the dock bar. */
|
||||||
|
@media (max-width: 576px) {
|
||||||
|
.ol-editbar-rail .ol-rail-grip {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Group heading — spans both columns. */
|
/* Group heading — spans both columns. */
|
||||||
.ol-editbar-rail .ol-rail-label {
|
.ol-editbar-rail .ol-rail-label {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
@ -1680,8 +1729,14 @@
|
|||||||
margin: 0 0 0 8px !important;
|
margin: 0 0 0 8px !important;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.ol-editbar-rail .ol-option-bar::before {
|
/* ol-ext draws a little pointer triangle on the option bar. It reads as a
|
||||||
|
stray dark button next to the flyout, and it is declared at
|
||||||
|
`.ol-control.ol-bar.ol-left .ol-option-bar:before` (0,4,1) — so the
|
||||||
|
selector that hides it has to be at least as specific. */
|
||||||
|
.ol-control.ol-bar.ol-editbar-rail.ol-left .ol-option-bar::before,
|
||||||
|
.ol-control.ol-bar.ol-editbar-rail.ol-left .ol-option-bar::after {
|
||||||
display: none;
|
display: none;
|
||||||
|
content: none;
|
||||||
}
|
}
|
||||||
.ol-editbar-rail .ol-option-bar .ol-control {
|
.ol-editbar-rail .ol-option-bar .ol-control {
|
||||||
display: inline-block !important;
|
display: inline-block !important;
|
||||||
@ -1725,7 +1780,7 @@
|
|||||||
/* `.ol-left` is repeated here for specificity: ol-ext's own
|
/* `.ol-left` is repeated here for specificity: ol-ext's own
|
||||||
`.ol-control.ol-bar.ol-left` sets top/transform, and without matching
|
`.ol-control.ol-bar.ol-left` sets top/transform, and without matching
|
||||||
it the rail stays vertically centred and stretches to `bottom`. */
|
it the rail stays vertically centred and stretches to `bottom`. */
|
||||||
.ol-editbar.ol-editbar-rail.ol-left {
|
.ol-control.ol-bar.ol-editbar.ol-editbar-rail.ol-left {
|
||||||
/* NOTE: display must NOT be !important — ol-ext toggles the bar with an
|
/* NOTE: display must NOT be !important — ol-ext toggles the bar with an
|
||||||
inline display:none/'' (setVisible). An !important here would beat
|
inline display:none/'' (setVisible). An !important here would beat
|
||||||
that and keep the toolbar visible even when Draw mode is off. */
|
that and keep the toolbar visible even when Draw mode is off. */
|
||||||
@ -1748,7 +1803,7 @@
|
|||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
scrollbar-width: none;
|
scrollbar-width: none;
|
||||||
}
|
}
|
||||||
.ol-editbar.ol-editbar-rail.ol-left::-webkit-scrollbar {
|
.ol-control.ol-bar.ol-editbar.ol-editbar-rail.ol-left::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
public/sw.js
11
public/sw.js
@ -80,7 +80,16 @@
|
|||||||
// Icon. On phones it becomes a horizontally scrolling strip above the
|
// Icon. On phones it becomes a horizontally scrolling strip above the
|
||||||
// dock, which retires the previous two-row wrapping workaround.
|
// dock, which retires the previous two-row wrapping workaround.
|
||||||
// New hashed bundle + updated index.html shell.
|
// New hashed bundle + updated index.html shell.
|
||||||
const CACHE_VERSION = 'v15';
|
// v16: Three fixes to the v15 rail, all reported from the field. The phone
|
||||||
|
// layout stretched down the whole screen because its rule only tied with
|
||||||
|
// ol-ext's on specificity, so stylesheet order decided the winner and the
|
||||||
|
// built app ordered them the other way round from the test harness. A
|
||||||
|
// stray dark shape beside the option bar was ol-ext's pointer triangle,
|
||||||
|
// hidden by a selector that was likewise not specific enough. And the rail
|
||||||
|
// covered the left off-canvas toggle, which sits at exactly the position
|
||||||
|
// ol-ext docks a left bar to — so the rail now starts clear of it and can
|
||||||
|
// be dragged anywhere by its grip, with the position remembered.
|
||||||
|
const CACHE_VERSION = 'v16';
|
||||||
const SHELL_CACHE = `shell-${CACHE_VERSION}`;
|
const SHELL_CACHE = `shell-${CACHE_VERSION}`;
|
||||||
const MODULES_CACHE = `modules-${CACHE_VERSION}`;
|
const MODULES_CACHE = `modules-${CACHE_VERSION}`;
|
||||||
const API_CACHE = `api-${CACHE_VERSION}`;
|
const API_CACHE = `api-${CACHE_VERSION}`;
|
||||||
|
|||||||
@ -1110,6 +1110,117 @@ export class MapView {
|
|||||||
for (const member of members) ordered.appendChild(member);
|
for (const member of members) ordered.appendChild(member);
|
||||||
}
|
}
|
||||||
bar.appendChild(ordered);
|
bar.appendChild(ordered);
|
||||||
|
|
||||||
|
// --- 3. drag grip -------------------------------------------------------
|
||||||
|
const grip = document.createElement('div');
|
||||||
|
grip.className = 'ol-rail-grip';
|
||||||
|
grip.title = 'Drag to move the toolbar — double-click to reset';
|
||||||
|
grip.setAttribute('role', 'button');
|
||||||
|
grip.setAttribute('aria-label', 'Move the drawing toolbar');
|
||||||
|
bar.insertBefore(grip, bar.firstChild);
|
||||||
|
this._makeToolbarDraggable(bar, grip);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Let the user drag the rail by its grip, and remember where they put it.
|
||||||
|
*
|
||||||
|
* A fixed palette always covers something — at the default position it sits
|
||||||
|
* over the left off-canvas toggle on short screens, and officers work at
|
||||||
|
* different zoom levels and with different hands. Rather than pick a spot that
|
||||||
|
* is wrong slightly less often, the rail moves and stays where it is put.
|
||||||
|
*
|
||||||
|
* Only above the phone breakpoint: below it the bar is a strip docked above
|
||||||
|
* the bottom dock, where there is nowhere useful to drag it to.
|
||||||
|
*/
|
||||||
|
_makeToolbarDraggable(bar, grip) {
|
||||||
|
const STORAGE_KEY = 'editbar-position';
|
||||||
|
const phone = window.matchMedia('(max-width: 576px)');
|
||||||
|
|
||||||
|
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
||||||
|
|
||||||
|
/** Apply a position, clamped so the rail can never be dragged off-map. */
|
||||||
|
const place = (left, top) => {
|
||||||
|
const parent = bar.offsetParent || this.map.getTargetElement();
|
||||||
|
if (!parent) return;
|
||||||
|
const maxLeft = Math.max(0, parent.clientWidth - bar.offsetWidth - 4);
|
||||||
|
const maxTop = Math.max(0, parent.clientHeight - bar.offsetHeight - 4);
|
||||||
|
bar.style.left = `${clamp(left, 4, maxLeft)}px`;
|
||||||
|
bar.style.top = `${clamp(top, 4, maxTop)}px`;
|
||||||
|
// ol-ext centres a left-docked bar with translateY(-50%); once the user
|
||||||
|
// has positioned it, top is an absolute value and the offset must go.
|
||||||
|
bar.style.transform = 'none';
|
||||||
|
bar.style.bottom = 'auto';
|
||||||
|
};
|
||||||
|
|
||||||
|
const clearInline = () => {
|
||||||
|
bar.style.left = '';
|
||||||
|
bar.style.top = '';
|
||||||
|
bar.style.transform = '';
|
||||||
|
bar.style.bottom = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Restore a saved position, unless we are in the phone strip layout. */
|
||||||
|
const restore = () => {
|
||||||
|
if (phone.matches) { clearInline(); return; }
|
||||||
|
try {
|
||||||
|
const saved = JSON.parse(localStorage.getItem(STORAGE_KEY) || 'null');
|
||||||
|
if (saved && Number.isFinite(saved.left) && Number.isFinite(saved.top)) {
|
||||||
|
place(saved.left, saved.top);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// A corrupt entry is not worth failing the toolbar over.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let startX = 0;
|
||||||
|
let startY = 0;
|
||||||
|
let originLeft = 0;
|
||||||
|
let originTop = 0;
|
||||||
|
|
||||||
|
const onMove = (evt) => {
|
||||||
|
place(originLeft + (evt.clientX - startX), originTop + (evt.clientY - startY));
|
||||||
|
};
|
||||||
|
|
||||||
|
const onUp = (evt) => {
|
||||||
|
grip.releasePointerCapture?.(evt.pointerId);
|
||||||
|
window.removeEventListener('pointermove', onMove);
|
||||||
|
window.removeEventListener('pointerup', onUp);
|
||||||
|
bar.classList.remove('is-dragging');
|
||||||
|
try {
|
||||||
|
localStorage.setItem(STORAGE_KEY, JSON.stringify({
|
||||||
|
left: parseFloat(bar.style.left) || 0,
|
||||||
|
top: parseFloat(bar.style.top) || 0,
|
||||||
|
}));
|
||||||
|
} catch {
|
||||||
|
// Private browsing or a full quota — the rail still moved this session.
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
grip.addEventListener('pointerdown', (evt) => {
|
||||||
|
if (phone.matches || evt.button !== 0) return;
|
||||||
|
evt.preventDefault();
|
||||||
|
const rect = bar.getBoundingClientRect();
|
||||||
|
const parentRect = (bar.offsetParent || this.map.getTargetElement()).getBoundingClientRect();
|
||||||
|
startX = evt.clientX;
|
||||||
|
startY = evt.clientY;
|
||||||
|
originLeft = rect.left - parentRect.left;
|
||||||
|
originTop = rect.top - parentRect.top;
|
||||||
|
bar.classList.add('is-dragging');
|
||||||
|
grip.setPointerCapture?.(evt.pointerId);
|
||||||
|
window.addEventListener('pointermove', onMove);
|
||||||
|
window.addEventListener('pointerup', onUp);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Double-click the grip to put the rail back where it started.
|
||||||
|
grip.addEventListener('dblclick', () => {
|
||||||
|
try { localStorage.removeItem(STORAGE_KEY); } catch { /* ignore */ }
|
||||||
|
clearInline();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Crossing the phone breakpoint swaps the layout, so drop or re-apply the
|
||||||
|
// inline position to match.
|
||||||
|
phone.addEventListener('change', restore);
|
||||||
|
restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user