@jsenv/dom 0.17.40 → 0.17.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/jsenv_dom.js +77 -27
  2. package/package.json +1 -1
package/dist/jsenv_dom.js CHANGED
@@ -9597,7 +9597,17 @@ import.meta.css = [css$4, "@jsenv/dom/src/interaction/drag/drag_after_intent.js"
9597
9597
  * on its way home is pressed through the pictures of a view transition, and the
9598
9598
  * touch lands on the document root (see letCopyBeCaught in drag_to.js). Same
9599
9599
  * rule, other element — and it has to be the same function, or the listener put
9600
- * down is not the one taken back off.
9600
+ * down is not the one taken back off. A box that TRAVELS says it too, from its
9601
+ * own render: given as a JSX prop (`onTouchMove={keepTouchRefusable}`), next to
9602
+ * the attribute naming its axes.
9603
+ *
9604
+ * Registered `{ passive: false }` where it is added by hand — but a framework's
9605
+ * event prop cannot say that (Preact's third addEventListener argument is only
9606
+ * useCapture), and it does not need to: passive-by-default only covers
9607
+ * touchmove listeners on window, document and document.body, so on any other
9608
+ * element a plain addEventListener is non-passive already. The document root is
9609
+ * exactly the one place this goes down where the explicit option is load-
9610
+ * bearing.
9601
9611
  */
9602
9612
  const keepTouchRefusable = () => {
9603
9613
  // Being registered IS the whole of it — see above.
@@ -13470,16 +13480,33 @@ import.meta.css = [/* css */`
13470
13480
  // How far a pointer goes before it is a travel rather than a click: below this
13471
13481
  // a press that wandered a pixel is still a press, and nothing budges.
13472
13482
  const DRAG_START_THRESHOLD = 10;
13483
+ // How much the cross axis must dominate the travel axis, over the first
13484
+ // reported pixels, to take the press away from the box (see the axis decision
13485
+ // in onDrag). Sized against the two hands it separates: a thumb's arc leans up
13486
+ // to about twice as far off-axis as along it at the start of a sideways swipe,
13487
+ // while a scroll is four or five times purer than that on its own axis.
13488
+ const AXIS_CROSS_DOMINANCE = 2;
13473
13489
  // How much of a box has to be pulled for letting go to carry on rather than put
13474
13490
  // things back, when the caller does not say. Under half, because a gesture that
13475
13491
  // has clearly begun is an intention: asking for the box to be dragged all the
13476
13492
  // way across turns a travel into work.
13477
13493
  const DRAG_COMMIT_RATIO = 0.3;
13478
- // A flick travels whatever the distance: the hand said "away" quickly, which is
13479
- // the whole gesture — px/ms of pointer, and a few pixels to tell it from a tap
13480
- // that shook.
13481
- const DRAG_FLICK_VELOCITY = 0.4;
13482
- const DRAG_FLICK_DISTANCE = 8;
13494
+ // A hand still moving towards what it is pulling in when it lets go has said
13495
+ // where this goes, however slowly: an intention still being acted on at the
13496
+ // lift travels whatever the distance. The bar sits just above stillness —
13497
+ // capacitive jitter and a hand settling before it lifts measure under it — so
13498
+ // only a release at rest is left to the position alone (the commit ratio).
13499
+ // It has to sit that low for another reason too: velocity is averaged over
13500
+ // the trailing window (see createVelocityMeter) and the release repeats the
13501
+ // last position a moment later, both pulling the measure down from the speed
13502
+ // the fingertip actually has. A few pixels of pull are asked besides, to tell
13503
+ // a movement from a tap that shook.
13504
+ const DRAG_DRIFT_VELOCITY = 0.03;
13505
+ const DRAG_DRIFT_DISTANCE = 8;
13506
+ // Thrown back: a hand moving AWAY from what it was bringing in this fast asks
13507
+ // for it to be put back, whatever the distance already covered. Well above the
13508
+ // drift bar, so a hand merely wavering as it lets go does not read as a throw.
13509
+ const DRAG_THROW_BACK_VELOCITY = 0.3;
13483
13510
  // Pulling towards nothing: what travels follows at a fraction of the finger, so
13484
13511
  // the gesture is answered (something moves) while saying there is nothing that
13485
13512
  // way. Let go and it comes back — a wall one can lean on, never walk through.
@@ -13693,21 +13720,23 @@ const travelsAfter = ({
13693
13720
  return true;
13694
13721
  }
13695
13722
  const sign = pulled > 0 ? 1 : -1;
13696
- const goingFast = Math.abs(velocity) > DRAG_FLICK_VELOCITY;
13697
13723
  // A hand that is still moving says where it is going, and it says it about
13698
- // BOTH answers. Going away from what it was bringing in is "put it back",
13699
- // whatever the distance already covered — which is the whole of what one asks
13700
- // for when catching something in flight and throwing it back the other way.
13701
- // Without this the picture alone decides, and a screen caught at two thirds
13702
- // and thrown back still arrives: the gesture was read as the place it was let
13703
- // go of rather than as a movement.
13704
- if (goingFast && Math.sign(velocity) !== sign) {
13724
+ // BOTH answers. Going away from what it was bringing in fast is "put it
13725
+ // back", whatever the distance already covered — which is the whole of what
13726
+ // one asks for when catching something in flight and throwing it back the
13727
+ // other way. Without this the picture alone decides, and a screen caught at
13728
+ // two thirds and thrown back still arrives: the gesture was read as the
13729
+ // place it was let go of rather than as a movement.
13730
+ if (Math.abs(velocity) > DRAG_THROW_BACK_VELOCITY && Math.sign(velocity) !== sign) {
13705
13731
  return false;
13706
13732
  }
13707
- // …and going towards it travels whatever the distance: the hand said "away"
13708
- // quickly, which is the whole gesture.
13709
- const flicked = goingFast && Math.abs(pulled) > DRAG_FLICK_DISTANCE;
13710
- return flicked || Math.abs(pulled) > size * commitRatio;
13733
+ // …and going towards it travels, however slowly: see DRAG_DRIFT_VELOCITY.
13734
+ const drifting = Math.abs(velocity) > DRAG_DRIFT_VELOCITY && Math.sign(velocity) === sign;
13735
+ if (drifting && Math.abs(pulled) > DRAG_DRIFT_DISTANCE) {
13736
+ return true;
13737
+ }
13738
+ // At rest: the position is the only witness left.
13739
+ return Math.abs(pulled) > size * commitRatio;
13711
13740
  };
13712
13741
 
13713
13742
  /**
@@ -13907,12 +13936,30 @@ const startDragToTravel = (pointerDownEvent, {
13907
13936
  // ONE axis, decided by the first movement reported and never
13908
13937
  // revisited: a diagonal would ask for two travels at once and only
13909
13938
  // one thing can arrive.
13939
+ //
13940
+ // The axis this box travels is favoured in that reading: a thumb
13941
+ // swiping a box sideways moves along an ARC, and its first reported
13942
+ // pixels — which are all this decision ever sees — lean off-axis
13943
+ // far more than the gesture does. Read even, that lean hands the
13944
+ // whole gesture to an axis nobody meant (the press is given up, and
13945
+ // the hand's remaining hundred pixels are read by no one). So the
13946
+ // cross axis has to win CLEARLY to take the press — and a gesture
13947
+ // that is really the page's own (a scroll is near-pure on its axis
13948
+ // from the first pixel) still is, at once, whole.
13910
13949
  const reachX = Math.abs(coveredOn("x", gestureInfo));
13911
13950
  const reachY = Math.abs(coveredOn("y", gestureInfo));
13912
13951
  if (!reachX && !reachY) {
13913
13952
  return;
13914
13953
  }
13915
- axis = reachX >= reachY ? "x" : "y";
13954
+ const travelsX = axesLeft.includes("x");
13955
+ const travelsY = axesLeft.includes("y");
13956
+ if (travelsX && !travelsY) {
13957
+ axis = reachY > reachX * AXIS_CROSS_DOMINANCE ? "y" : "x";
13958
+ } else if (travelsY && !travelsX) {
13959
+ axis = reachX > reachY * AXIS_CROSS_DOMINANCE ? "x" : "y";
13960
+ } else {
13961
+ axis = reachX >= reachY ? "x" : "y";
13962
+ }
13916
13963
  if (!axesLeft.includes(axis)) {
13917
13964
  giveUp();
13918
13965
  return;
@@ -13947,13 +13994,16 @@ const startDragToTravel = (pointerDownEvent, {
13947
13994
  travelBack: Boolean(started.travelBack),
13948
13995
  travelOn: Boolean(started.travelOn),
13949
13996
  slack: started.slack || 0,
13950
- // The pixels spent deciding the axis are not pulled back — what
13951
- // travels sets off from where the finger is at that moment rather
13952
- // than jumping the threshold it just crossed. Except when the intent
13953
- // was established before the press (see immediate): there was no
13954
- // threshold to cross, so every pixel since the grab is the hand's and
13955
- // is owed to it.
13956
- origin: immediate ? 0 : covered,
13997
+ // Only what the intent threshold cost is withheld, so what travels
13998
+ // does not jump those few pixels at the start — and nothing more:
13999
+ // a fast gesture arrives coalesced, and the first report can carry
14000
+ // most of a flick. Charged whole, the flick would set off with
14001
+ // nothing left of itself to have pulled, move nothing on screen and
14002
+ // be refused at the release for it. Except when the intent was
14003
+ // established before the press (see immediate): there was no
14004
+ // threshold to cross, so every pixel since the grab is the hand's
14005
+ // and is owed to it.
14006
+ origin: immediate ? 0 : covered > DRAG_START_THRESHOLD ? DRAG_START_THRESHOLD : covered < -DRAG_START_THRESHOLD ? -DRAG_START_THRESHOLD : covered,
13957
14007
  pulled: started.slack || 0
13958
14008
  };
13959
14009
  document.documentElement.setAttribute(WALKING_ATTRIBUTE, axis);
@@ -20239,4 +20289,4 @@ const useResizeStatus = (elementRef, { as = "number" } = {}) => {
20239
20289
  };
20240
20290
  };
20241
20291
 
20242
- export { EASING, ELEMENT_SIZE_CHANGE, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, applyNewPosition, canScroll, captureScrollState, chainEvent, claimWheelGesture, clickIsSuppressed, closestOpenableAncestor, contrastColor, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createEventGroupLogger, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dispatchCustomEvent, dispatchInternalCustomEvent, dispatchPublicCustomEvent, dragAfterIntent, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findEvent, findFocusDelegateTarget, findFocusable, findSelfOrAncestorFixedPosition, formatEventSideEffect, getAncestorOpenType, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getKeyboardEventDefaultAction, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPositioningScrollOffset, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollIntoViewScopedOffsets, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVirtualKeyboardOverlayHeight, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isAncestorOpen, isDisplayedDespiteClosedAncestor, isPressDisputedByDrag, isPrimaryButtonEvent, isSameColor, isScrollable, isTouchDrivenEvent, markDragSource, measureLongestVisualLineWidth, measureScrollbar, measureWidestChildRow, mergeOneStyle, mergeTwoStyles, normalizeKeyboardKey, normalizeStyle, normalizeStyles, observeAncestorOpenState, onAncestorReopen, parsePositionArea, parseStyle, performTabNavigation, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, releaseWheelGesture, resolveCSSColor, resolveCSSSize, resolveColorLuminance, resolveOklchLightness, scrollIntoViewScoped, scrollIntoViewThroughScrollables, scrollIntoViewWithStickyAwareness, scrollRoomTowards, setAttribute, setAttributes, setStyles, setVirtualKeyboardOverlaysContent, snapToPixel, startDragTo, startDragToResizeGesture, startDragToTravel, stickyAsRelativeCoords, stringifyStyle, subscribeVirtualKeyboardGeometryChange, subscribeVisualViewportResizeSettled, subscribeWindowResizeSettled, suppressClickAfterGesture, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect, waitForPressHeld, watchWheelTravel, wheelGestureIsTakenFrom };
20292
+ export { EASING, ELEMENT_SIZE_CHANGE, activeElementSignal, addActiveElementEffect, addAttributeEffect, allowWheelThrough, appendStyles, applyNewPosition, canScroll, captureScrollState, chainEvent, claimWheelGesture, clickIsSuppressed, closestOpenableAncestor, contrastColor, createBackgroundColorTransition, createBackgroundTransition, createBorderRadiusTransition, createBorderTransition, createDragGestureController, createDragToMoveGestureController, createEventGroupLogger, createGroupTransitionController, createHeightTransition, createIterableWeakSet, createOpacityTransition, createPubSub, createStyleController, createTimelineTransition, createTransition, createTranslateXTransition, createValueEffect, createWidthTransition, cubicBezier, dispatchCustomEvent, dispatchInternalCustomEvent, dispatchPublicCustomEvent, dragAfterIntent, elementIsFocusable, elementIsVisibleForFocus, elementIsVisuallyVisible, findAfter, findAncestor, findBefore, findDescendant, findEvent, findFocusDelegateTarget, findFocusable, findSelfOrAncestorFixedPosition, formatEventSideEffect, getAncestorOpenType, getAvailableHeight, getAvailableWidth, getBackground, getBackgroundColor, getBorder, getBorderRadius, getBorderSizes, getContrastRatio, getDefaultStyles, getDragCoordinates, getDropTargetInfo, getElementSignature, getFirstVisuallyVisibleAncestor, getFocusVisibilityInfo, getHeight, getHeightWithoutTransition, getInnerHeight, getInnerWidth, getKeyboardEventDefaultAction, getLuminance, getMarginSizes, getMaxHeight, getMaxWidth, getMinHeight, getMinWidth, getOpacity, getOpacityWithoutTransition, getPaddingSizes, getPositionedParent, getPositioningScrollOffset, getPreferedColorScheme, getScrollBox, getScrollContainer, getScrollContainerSet, getScrollIntoViewScopedOffsets, getScrollRelativeRect, getSelfAndAncestorScrolls, getStyle, getTranslateX, getTranslateXWithoutTransition, getTranslateY, getVirtualKeyboardOverlayHeight, getVisuallyVisibleInfo, getWidth, getWidthWithoutTransition, hasCSSSizeUnit, initFlexDetailsSet, initFocusGroup, initPositionSticky, isAncestorOpen, isDisplayedDespiteClosedAncestor, isPressDisputedByDrag, isPrimaryButtonEvent, isSameColor, isScrollable, isTouchDrivenEvent, keepTouchRefusable, markDragSource, measureLongestVisualLineWidth, measureScrollbar, measureWidestChildRow, mergeOneStyle, mergeTwoStyles, normalizeKeyboardKey, normalizeStyle, normalizeStyles, observeAncestorOpenState, onAncestorReopen, parsePositionArea, parseStyle, performTabNavigation, pickPositionRelativeTo, prefersDarkColors, prefersLightColors, preventFocusNav, preventFocusNavViaKeyboard, preventIntermediateScrollbar, releaseWheelGesture, resolveCSSColor, resolveCSSSize, resolveColorLuminance, resolveOklchLightness, scrollIntoViewScoped, scrollIntoViewThroughScrollables, scrollIntoViewWithStickyAwareness, scrollRoomTowards, setAttribute, setAttributes, setStyles, setVirtualKeyboardOverlaysContent, snapToPixel, startDragTo, startDragToResizeGesture, startDragToTravel, stickyAsRelativeCoords, stringifyStyle, subscribeVirtualKeyboardGeometryChange, subscribeVisualViewportResizeSettled, subscribeWindowResizeSettled, suppressClickAfterGesture, trapFocusInside, trapScrollInside, useActiveElement, useAvailableHeight, useAvailableWidth, useMaxHeight, useMaxWidth, useResizeStatus, visibleRectEffect, waitForPressHeld, watchWheelTravel, wheelGestureIsTakenFrom };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/dom",
3
- "version": "0.17.40",
3
+ "version": "0.17.41",
4
4
  "type": "module",
5
5
  "description": "DOM utilities for writing frontend code",
6
6
  "repository": {