@astryxdesign/core 0.7.7-canary.bf14580 → 0.7.7-canary.c19ca12
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/AlertDialog/AlertDialog.d.ts +4 -1
- package/dist/AlertDialog/AlertDialog.d.ts.map +1 -1
- package/dist/AlertDialog/AlertDialog.js +36 -6
- package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheet.js +76 -6
- package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
- package/dist/BottomSheet/BottomSheetPanel.js +23 -4
- package/dist/BottomSheet/bottomSheetStack.d.ts.map +1 -1
- package/dist/BottomSheet/bottomSheetStack.js +5 -4
- package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -1
- package/dist/BottomSheet/useSheetGestures.js +3 -1
- package/dist/Button/Button.d.ts.map +1 -1
- package/dist/Button/Button.js +47 -3
- package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
- package/dist/CheckboxInput/CheckboxInput.js +13 -2
- package/dist/ComplexSelector/ComplexSelector.d.ts +4 -1
- package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
- package/dist/ComplexSelector/ComplexSelector.js +14 -4
- package/dist/ContextMenu/ContextMenu.js +2 -2
- package/dist/DateInput/MonthScroller.d.ts.map +1 -1
- package/dist/DateInput/MonthScroller.js +13 -27
- package/dist/DateInput/Wheel.d.ts.map +1 -1
- package/dist/DateInput/Wheel.js +22 -41
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +7 -31
- package/dist/Field/Field.js +2 -2
- package/dist/HoverCard/HoverCard.d.ts +4 -3
- package/dist/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/HoverCard/HoverCard.js +27 -2
- package/dist/HoverCard/useHoverCard.d.ts +5 -4
- package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
- package/dist/HoverCard/useHoverCard.js +17 -31
- package/dist/Icon/Icon.d.ts +5 -1
- package/dist/Icon/Icon.d.ts.map +1 -1
- package/dist/Icon/Icon.js +5 -2
- package/dist/Layer/layerAnimations.stylex.d.ts +7 -8
- package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
- package/dist/Layer/layerAnimations.stylex.js +25 -20
- package/dist/Layer/usePressPin.d.ts +17 -5
- package/dist/Layer/usePressPin.d.ts.map +1 -1
- package/dist/Layer/usePressPin.js +62 -12
- package/dist/Lightbox/Lightbox.d.ts.map +1 -1
- package/dist/Lightbox/Lightbox.js +18 -0
- package/dist/PowerSearch/PowerSearch.d.ts +36 -3
- package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearch.js +522 -269
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts +100 -0
- package/dist/PowerSearch/PowerSearchBottomSheet.d.ts.map +1 -0
- package/dist/PowerSearch/PowerSearchBottomSheet.js +1913 -0
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts +32 -1
- package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchEditPopover.js +17 -6
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts +38 -3
- package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
- package/dist/PowerSearch/PowerSearchValueEditor.js +170 -61
- package/dist/PowerSearch/formatFilterValue.d.ts +7 -0
- package/dist/PowerSearch/formatFilterValue.d.ts.map +1 -1
- package/dist/PowerSearch/formatFilterValue.js +11 -1
- package/dist/PowerSearch/formatTokenValue.d.ts +28 -0
- package/dist/PowerSearch/formatTokenValue.d.ts.map +1 -0
- package/dist/PowerSearch/formatTokenValue.js +160 -0
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts +65 -0
- package/dist/PowerSearch/powerSearchSheetUtils.d.ts.map +1 -0
- package/dist/PowerSearch/powerSearchSheetUtils.js +168 -0
- package/dist/RadioList/RadioList.d.ts.map +1 -1
- package/dist/RadioList/RadioList.js +3 -2
- package/dist/RadioList/RadioListItem.d.ts +1 -1
- package/dist/RadioList/RadioListItem.d.ts.map +1 -1
- package/dist/RadioList/RadioListItem.js +5 -3
- package/dist/SegmentedControl/useSegmentedSelectionMotion.d.ts.map +1 -1
- package/dist/SegmentedControl/useSegmentedSelectionMotion.js +3 -3
- package/dist/Slider/sliderTouchController.js +2 -2
- package/dist/Spinner/Spinner.d.ts +1 -1
- package/dist/Spinner/Spinner.d.ts.map +1 -1
- package/dist/Spinner/Spinner.js +60 -58
- package/dist/Switch/useSwitchTouch.js +4 -4
- package/dist/Table/BaseTable.d.ts.map +1 -1
- package/dist/Table/BaseTable.js +29 -8
- package/dist/TextInput/TextInput.d.ts +2 -2
- package/dist/TextInput/TextInput.d.ts.map +1 -1
- package/dist/TextInput/TextInput.js +10 -7
- package/dist/Toast/Toast.d.ts +11 -1
- package/dist/Toast/Toast.d.ts.map +1 -1
- package/dist/Toast/Toast.js +25 -15
- package/dist/Toast/ToastViewport.d.ts.map +1 -1
- package/dist/Toast/ToastViewport.js +94 -34
- package/dist/Toast/types.d.ts +9 -3
- package/dist/Toast/types.d.ts.map +1 -1
- package/dist/Token/Token.d.ts +2 -2
- package/dist/Token/Token.d.ts.map +1 -1
- package/dist/Token/Token.js +12 -4
- package/dist/Token/TokenNamingContext.d.ts +14 -0
- package/dist/Token/TokenNamingContext.d.ts.map +1 -0
- package/dist/Token/TokenNamingContext.js +23 -0
- package/dist/Tooltip/useTooltip.d.ts +19 -1
- package/dist/Tooltip/useTooltip.d.ts.map +1 -1
- package/dist/Tooltip/useTooltip.js +34 -53
- package/dist/Typeahead/TypeaheadItem.d.ts +2 -1
- package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
- package/dist/animator/createAnimator.d.ts +98 -0
- package/dist/animator/createAnimator.d.ts.map +1 -0
- package/dist/animator/createAnimator.js +259 -0
- package/dist/astryx.css +22 -6
- package/dist/gestures/GestureHost.d.ts +27 -1
- package/dist/gestures/GestureHost.d.ts.map +1 -1
- package/dist/gestures/GestureHost.js +90 -8
- package/dist/gestures/PressTracker.d.ts.map +1 -1
- package/dist/gestures/PressTracker.js +4 -3
- package/dist/hooks/actionGroupTracker.d.ts +4 -1
- package/dist/hooks/actionGroupTracker.d.ts.map +1 -1
- package/dist/hooks/actionGroupTracker.js +13 -3
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/pressGroupContext.d.ts +6 -0
- package/dist/hooks/pressGroupContext.d.ts.map +1 -0
- package/dist/hooks/pressGroupContext.js +20 -0
- package/dist/hooks/useActionGroupTracking.d.ts +53 -0
- package/dist/hooks/useActionGroupTracking.d.ts.map +1 -0
- package/dist/hooks/useActionGroupTracking.js +174 -0
- package/dist/hooks/useAnimator.d.ts +41 -0
- package/dist/hooks/useAnimator.d.ts.map +1 -0
- package/dist/hooks/useAnimator.js +70 -0
- package/dist/hooks/useAttachment.d.ts +1 -1
- package/dist/hooks/useAttachment.js +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts +1 -1
- package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
- package/dist/hooks/useInputStatusIcon.js +2 -2
- package/dist/hooks/useLongPress.d.ts +6 -2
- package/dist/hooks/useLongPress.d.ts.map +1 -1
- package/dist/hooks/useLongPress.js +95 -15
- package/dist/hooks/useMenuPress.d.ts.map +1 -1
- package/dist/hooks/useMenuPress.js +4 -2
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts +8 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.js +42 -0
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.d.ts.map +1 -1
- package/dist/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.js +6 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts +8 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.d.ts.map +1 -0
- package/dist/i18n/generated-english/PowerSearch/formatTokenValue.generated.js +14 -0
- package/dist/i18n/generated-locales/en.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/en.generated.js +30 -0
- package/dist/i18n/generated-locales/pseudo.generated.d.ts.map +1 -1
- package/dist/i18n/generated-locales/pseudo.generated.js +30 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/internal/indicatorPress.stylex.d.ts +20 -0
- package/dist/internal/indicatorPress.stylex.d.ts.map +1 -0
- package/dist/internal/indicatorPress.stylex.js +26 -0
- package/dist/motion/animator.d.ts +14 -14
- package/dist/motion/animator.d.ts.map +1 -1
- package/dist/motion/animator.js +41 -18
- package/dist/motion/reducedMotion.d.ts +24 -0
- package/dist/motion/reducedMotion.d.ts.map +1 -1
- package/dist/motion/reducedMotion.js +78 -1
- package/dist/motion/uikit/alert.d.ts +41 -0
- package/dist/motion/uikit/alert.d.ts.map +1 -0
- package/dist/motion/uikit/alert.js +43 -0
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts +15 -0
- package/dist/privateAttributes/pressGroupItem.stylex.d.ts.map +1 -0
- package/dist/privateAttributes/pressGroupItem.stylex.js +23 -0
- package/dist/utils/clickGuard.d.ts +8 -1
- package/dist/utils/clickGuard.d.ts.map +1 -1
- package/dist/utils/clickGuard.js +24 -1
- package/dist/utils/dateParser.d.ts.map +1 -1
- package/dist/utils/dateParser.js +12 -0
- package/dist/utils/focusReturn.d.ts +15 -0
- package/dist/utils/focusReturn.d.ts.map +1 -1
- package/dist/utils/focusReturn.js +28 -0
- package/dist/utils/interactionOverlay.stylex.d.ts +3 -2
- package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
- package/dist/utils/interactionOverlay.stylex.js +3 -2
- package/dist/utils/pressFeedback.d.ts.map +1 -1
- package/dist/utils/pressFeedback.js +19 -6
- package/dist/utils/triggerFocus.d.ts +36 -0
- package/dist/utils/triggerFocus.d.ts.map +1 -0
- package/dist/utils/triggerFocus.js +65 -0
- package/locales/en.json +120 -0
- package/locales/pseudo.json +90 -0
- package/package.json +9 -4
- package/src/AlertDialog/AlertDialog.doc.mjs +2 -2
- package/src/AlertDialog/AlertDialog.tsx +37 -5
- package/src/BottomSheet/BottomSheet.tsx +85 -5
- package/src/BottomSheet/BottomSheetPanel.tsx +40 -5
- package/src/BottomSheet/bottomSheetStack.ts +8 -4
- package/src/BottomSheet/useSheetGestures.ts +3 -1
- package/src/Button/Button.tsx +63 -5
- package/src/CheckboxInput/CheckboxInput.doc.mjs +18 -0
- package/src/CheckboxInput/CheckboxInput.tsx +36 -9
- package/src/ComplexSelector/ComplexSelector.tsx +20 -5
- package/src/ContextMenu/ContextMenu.tsx +2 -2
- package/src/DateInput/MonthScroller.tsx +18 -22
- package/src/DateInput/Wheel.tsx +30 -32
- package/src/Dialog/Dialog.tsx +10 -31
- package/src/Field/Field.tsx +2 -2
- package/src/HoverCard/HoverCard.doc.mjs +4 -2
- package/src/HoverCard/HoverCard.tsx +35 -4
- package/src/HoverCard/useHoverCard.doc.mjs +178 -36
- package/src/HoverCard/useHoverCard.tsx +46 -52
- package/src/Icon/Icon.doc.mjs +49 -8
- package/src/Icon/Icon.tsx +15 -7
- package/src/Layer/layerAnimations.stylex.ts +24 -16
- package/src/Layer/usePressPin.ts +81 -15
- package/src/Lightbox/Lightbox.tsx +18 -0
- package/src/PowerSearch/PowerSearch.doc.mjs +54 -5
- package/src/PowerSearch/PowerSearch.tsx +734 -288
- package/src/PowerSearch/PowerSearchBottomSheet.tsx +2515 -0
- package/src/PowerSearch/PowerSearchEditPopover.tsx +28 -6
- package/src/PowerSearch/PowerSearchValueEditor.tsx +203 -38
- package/src/PowerSearch/formatFilterValue.ts +18 -1
- package/src/PowerSearch/formatTokenValue.ts +215 -0
- package/src/PowerSearch/powerSearchSheetUtils.ts +224 -0
- package/src/RadioList/RadioList.tsx +3 -2
- package/src/RadioList/RadioListItem.tsx +5 -3
- package/src/SegmentedControl/useSegmentedSelectionMotion.ts +6 -3
- package/src/Slider/sliderTouchController.ts +2 -2
- package/src/Spinner/Spinner.tsx +77 -63
- package/src/Switch/useSwitchTouch.ts +4 -4
- package/src/Table/BaseTable.tsx +46 -12
- package/src/TextInput/TextInput.tsx +11 -10
- package/src/Toast/Toast.doc.mjs +4 -3
- package/src/Toast/Toast.tsx +52 -32
- package/src/Toast/ToastViewport.tsx +121 -35
- package/src/Toast/types.ts +9 -3
- package/src/Token/Token.tsx +13 -4
- package/src/Token/TokenNamingContext.ts +28 -0
- package/src/Tooltip/useTooltip.doc.mjs +24 -0
- package/src/Tooltip/useTooltip.tsx +61 -56
- package/src/Typeahead/TypeaheadItem.doc.mjs +6 -3
- package/src/Typeahead/TypeaheadItem.tsx +2 -1
- package/src/animator/createAnimator.doc.mjs +153 -0
- package/src/animator/createAnimator.ts +324 -0
- package/src/gestures/GestureHost.ts +105 -10
- package/src/gestures/PressTracker.ts +4 -3
- package/src/gestures/README.md +7 -1
- package/src/hooks/actionGroupTracker.ts +20 -5
- package/src/hooks/index.ts +2 -0
- package/src/hooks/pressGroupContext.ts +21 -0
- package/src/hooks/useActionGroupTracking.ts +224 -0
- package/src/hooks/useAnimator.doc.mjs +109 -0
- package/src/hooks/useAnimator.ts +67 -0
- package/src/hooks/useAttachment.ts +1 -1
- package/src/hooks/useInputStatusIcon.tsx +3 -2
- package/src/hooks/useLongPress.doc.mjs +2 -2
- package/src/hooks/useLongPress.ts +136 -15
- package/src/hooks/useMenuPress.ts +8 -2
- package/src/i18n/generated-english/PowerSearch/PowerSearchBottomSheet.generated.ts +43 -0
- package/src/i18n/generated-english/PowerSearch/PowerSearchValueEditor.generated.ts +6 -0
- package/src/i18n/generated-english/PowerSearch/formatTokenValue.generated.ts +15 -0
- package/src/i18n/generated-locales/en.generated.ts +41 -0
- package/src/i18n/generated-locales/pseudo.generated.ts +42 -0
- package/src/index.ts +13 -0
- package/src/internal/indicatorPress.stylex.ts +24 -0
- package/src/motion/README.md +8 -5
- package/src/motion/animator.ts +61 -29
- package/src/motion/reducedMotion.ts +79 -1
- package/src/motion/uikit/alert.ts +43 -0
- package/src/privateAttributes/pressGroupItem.stylex.ts +23 -0
- package/src/utils/clickGuard.ts +37 -1
- package/src/utils/dateParser.ts +16 -0
- package/src/utils/focusReturn.ts +30 -0
- package/src/utils/interactionOverlay.stylex.ts +3 -2
- package/src/utils/pressFeedback.ts +19 -6
- package/src/utils/triggerFocus.ts +80 -0
|
@@ -457,6 +457,12 @@ export class GestureHost {
|
|
|
457
457
|
* lift click (`spec:AST-094` FR28: nothing acts).
|
|
458
458
|
*/
|
|
459
459
|
cancelledFingers = new Set();
|
|
460
|
+
/**
|
|
461
|
+
* The pens and pointer-read fingers that the app's lost focus cancelled,
|
|
462
|
+
* by pointer id. Each is kept until its lift, which must not click either,
|
|
463
|
+
* or until a new press.
|
|
464
|
+
*/
|
|
465
|
+
cancelledPointers = new Map();
|
|
460
466
|
/** Touch.identifier → the element the finger landed on. */
|
|
461
467
|
touchTargets = new Map();
|
|
462
468
|
/**
|
|
@@ -478,6 +484,8 @@ export class GestureHost {
|
|
|
478
484
|
processed = new WeakSet();
|
|
479
485
|
/** pointerId → arena id, for live mouse and pen contacts. */
|
|
480
486
|
pointerIds = new Map();
|
|
487
|
+
/** Each contact's kind: a blur refuses a pen's or a pointer-read finger's lift, never a mouse's. */
|
|
488
|
+
pointerKinds = new Map();
|
|
481
489
|
/**
|
|
482
490
|
* The boxes the host watches for screen-edge pans (syncLayoutWatch): each
|
|
483
491
|
* element with an enabled one, and the root for one whose band moves with
|
|
@@ -1420,13 +1428,32 @@ export class GestureHost {
|
|
|
1420
1428
|
}
|
|
1421
1429
|
}
|
|
1422
1430
|
|
|
1423
|
-
/**
|
|
1431
|
+
/**
|
|
1432
|
+
* A new press is a new gesture, as the click guard reads one, so the lifts
|
|
1433
|
+
* the blur cancelled owe nothing after it. A second finger keeps the other
|
|
1434
|
+
* fingers' refusals, since those fingers may still be down.
|
|
1435
|
+
*/
|
|
1436
|
+
dropCancelledLifts(event) {
|
|
1437
|
+
const isSecond = event.pointerType === 'touch' && event.isPrimary === false;
|
|
1438
|
+
for (const [pointerId, kind] of [...this.cancelledPointers]) {
|
|
1439
|
+
if (pointerId === event.pointerId || !(isSecond && kind === 'touch')) {
|
|
1440
|
+
this.cancelledPointers.delete(pointerId);
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
/**
|
|
1446
|
+
* After a contact ends: an armed press that is over stops listening. A
|
|
1447
|
+
* contact the lost focus cancelled still owes its lift, so the press is
|
|
1448
|
+
* not over until that lift comes. A lift the page never hears ends it at
|
|
1449
|
+
* the next press, or at a cancel.
|
|
1450
|
+
*/
|
|
1424
1451
|
releaseArmedPress() {
|
|
1425
1452
|
if (!this.isArmedPress) {
|
|
1426
1453
|
return;
|
|
1427
1454
|
}
|
|
1428
1455
|
queueMicrotask(() => {
|
|
1429
|
-
if (this.isArmedPress && this.arena.touches.length === 0) {
|
|
1456
|
+
if (this.isArmedPress && this.arena.touches.length === 0 && this.cancelledPointers.size === 0) {
|
|
1430
1457
|
this.isArmedPress = false;
|
|
1431
1458
|
this.syncKeptPresses();
|
|
1432
1459
|
this.syncListeners();
|
|
@@ -1457,6 +1484,7 @@ export class GestureHost {
|
|
|
1457
1484
|
return;
|
|
1458
1485
|
}
|
|
1459
1486
|
this.cancelledFingers.clear();
|
|
1487
|
+
this.cancelledPointers.clear();
|
|
1460
1488
|
this.clearClaimedLifts();
|
|
1461
1489
|
this.cancelCallerRead?.();
|
|
1462
1490
|
this.cancelCallerRead = null;
|
|
@@ -2415,8 +2443,9 @@ export class GestureHost {
|
|
|
2415
2443
|
consumerElement
|
|
2416
2444
|
});
|
|
2417
2445
|
}
|
|
2418
|
-
// The finger's events keep going to what the engine hit.
|
|
2419
|
-
|
|
2446
|
+
// The finger's events keep going to what the engine hit. A disabled
|
|
2447
|
+
// participant can never claim, so a scroll never waits on it.
|
|
2448
|
+
this.watchTarget(touch.identifier, native, recognizers.some(recognizer => recognizer.isEnabled && claimsWhileMoving(recognizer)) || consumer?.keepsTouch != null && consumer.isEnabled?.() !== false, consumer != null && consumer.isEnabled?.() !== false || recognizers.some(recognizer => recognizer.isEnabled && recognizer.claimsTouches));
|
|
2420
2449
|
this.lastFed.set(id, {
|
|
2421
2450
|
x: touch.clientX,
|
|
2422
2451
|
y: touch.clientY,
|
|
@@ -2460,6 +2489,11 @@ export class GestureHost {
|
|
|
2460
2489
|
for (const input of untracked) {
|
|
2461
2490
|
this.arena.untrackedBegan(input);
|
|
2462
2491
|
}
|
|
2492
|
+
// Again once the new fingers are delivered: a pinch's second finger may
|
|
2493
|
+
// have landed on another one-finger pan, the next row.
|
|
2494
|
+
if (this.fingerTargets.length > 1 && !this.isFingerClaimed()) {
|
|
2495
|
+
this.failUnclaimedLoneFingerPans();
|
|
2496
|
+
}
|
|
2463
2497
|
// Stamped after the consumers judged the touch: the brake asks whether
|
|
2464
2498
|
// an EARLIER finger is still driving a scroll.
|
|
2465
2499
|
const landed = landedOn(event);
|
|
@@ -2985,6 +3019,7 @@ export class GestureHost {
|
|
|
2985
3019
|
if (!isPointerKind(event.pointerType)) {
|
|
2986
3020
|
return;
|
|
2987
3021
|
}
|
|
3022
|
+
this.dropCancelledLifts(event);
|
|
2988
3023
|
if (event.pointerType === 'touch' && this.usesTouchEvents) {
|
|
2989
3024
|
this.pairPointer(event.pointerId, {
|
|
2990
3025
|
x: event.clientX,
|
|
@@ -2993,6 +3028,13 @@ export class GestureHost {
|
|
|
2993
3028
|
});
|
|
2994
3029
|
return;
|
|
2995
3030
|
}
|
|
3031
|
+
if (event.pointerType === 'touch' && event.isPrimary === false) {
|
|
3032
|
+
// Fingers from pointer events: a second one, wherever either lands,
|
|
3033
|
+
// leaves the two to the page's pinch, as onTouchStart does. A finger
|
|
3034
|
+
// that is not the primary pointer is a second finger, even where the
|
|
3035
|
+
// host never heard the first.
|
|
3036
|
+
this.failUnclaimedLoneFingerPans();
|
|
3037
|
+
}
|
|
2996
3038
|
// A right click, a pen's barrel button, or a ctrl-click on macOS (its
|
|
2997
3039
|
// context click) starts no press (FR43).
|
|
2998
3040
|
if (event.pointerType !== 'touch' && !isPrimaryClick(event)) {
|
|
@@ -3010,6 +3052,7 @@ export class GestureHost {
|
|
|
3010
3052
|
}
|
|
3011
3053
|
const id = this.nextId++;
|
|
3012
3054
|
this.pointerIds.set(event.pointerId, id);
|
|
3055
|
+
this.pointerKinds.set(event.pointerId, event.pointerType);
|
|
3013
3056
|
if (target !== landed && target != null) {
|
|
3014
3057
|
this.retargeted.set(id, {
|
|
3015
3058
|
x: event.clientX,
|
|
@@ -3033,6 +3076,11 @@ export class GestureHost {
|
|
|
3033
3076
|
recognizers,
|
|
3034
3077
|
consumer
|
|
3035
3078
|
}]);
|
|
3079
|
+
if (event.pointerType === 'touch' && event.isPrimary === false && !this.isFingerClaimed()) {
|
|
3080
|
+
// Again once this finger is delivered: it may have landed on another
|
|
3081
|
+
// one-finger pan.
|
|
3082
|
+
this.failUnclaimedLoneFingerPans();
|
|
3083
|
+
}
|
|
3036
3084
|
if (locksSelectionFor(event.pointerType)) {
|
|
3037
3085
|
// The presented target: what the pen is on, where the engine's own
|
|
3038
3086
|
// hit test may still see the motion's start.
|
|
@@ -3079,9 +3127,14 @@ export class GestureHost {
|
|
|
3079
3127
|
}
|
|
3080
3128
|
const id = this.pointerIds.get(event.pointerId);
|
|
3081
3129
|
if (id == null) {
|
|
3130
|
+
// A contact the lost focus cancelled: its lift clicks nothing.
|
|
3131
|
+
if (this.cancelledPointers.delete(event.pointerId)) {
|
|
3132
|
+
this.refuseCancelledLift(event);
|
|
3133
|
+
}
|
|
3082
3134
|
return;
|
|
3083
3135
|
}
|
|
3084
3136
|
this.pointerIds.delete(event.pointerId);
|
|
3137
|
+
this.pointerKinds.delete(event.pointerId);
|
|
3085
3138
|
this.unlockSelection(id);
|
|
3086
3139
|
const dispositions = this.arena.ended([{
|
|
3087
3140
|
id,
|
|
@@ -3176,9 +3229,12 @@ export class GestureHost {
|
|
|
3176
3229
|
}
|
|
3177
3230
|
return;
|
|
3178
3231
|
}
|
|
3232
|
+
// A contact that ends in a cancel owes no refused lift.
|
|
3233
|
+
this.cancelledPointers.delete(event.pointerId);
|
|
3179
3234
|
const id = this.pointerIds.get(event.pointerId);
|
|
3180
3235
|
if (id != null) {
|
|
3181
3236
|
this.pointerIds.delete(event.pointerId);
|
|
3237
|
+
this.pointerKinds.delete(event.pointerId);
|
|
3182
3238
|
this.unlockSelection(id, true);
|
|
3183
3239
|
this.retargeted.delete(id);
|
|
3184
3240
|
this.arena.cancelled([id], eventTime(event));
|
|
@@ -3348,18 +3404,22 @@ export class GestureHost {
|
|
|
3348
3404
|
}
|
|
3349
3405
|
}
|
|
3350
3406
|
}
|
|
3407
|
+
/** Whether a finger's drag is claimed: then two fingers make no pinch. */
|
|
3408
|
+
isFingerClaimed() {
|
|
3409
|
+
return this.arena.touches.some(touch => touch.pointerType === 'touch' && this.arena.isClaimed(touch.id));
|
|
3410
|
+
}
|
|
3351
3411
|
onVisibilityChange = () => {
|
|
3352
3412
|
if (this.doc.visibilityState === 'hidden') {
|
|
3353
3413
|
this.cancelEverything(this.arena.now());
|
|
3354
|
-
// As at a blur:
|
|
3355
|
-
//
|
|
3414
|
+
// As at a blur: an armed press's page listeners go once nothing is left
|
|
3415
|
+
// to hear.
|
|
3356
3416
|
this.releaseArmedPress();
|
|
3357
3417
|
}
|
|
3358
3418
|
};
|
|
3359
3419
|
onBlur = () => {
|
|
3360
3420
|
this.cancelEverything(this.arena.now());
|
|
3361
|
-
//
|
|
3362
|
-
//
|
|
3421
|
+
// An armed press's page listeners go once nothing is left to hear. A pen
|
|
3422
|
+
// or a pointer-read finger the blur cancelled still owes its lift.
|
|
3363
3423
|
this.releaseArmedPress();
|
|
3364
3424
|
};
|
|
3365
3425
|
|
|
@@ -3379,8 +3439,29 @@ export class GestureHost {
|
|
|
3379
3439
|
return this.inputMode === 'pointer-events' || view != null && !('ontouchstart' in view);
|
|
3380
3440
|
}
|
|
3381
3441
|
|
|
3442
|
+
/**
|
|
3443
|
+
* The lift of a contact the lost focus cancelled: its click is refused,
|
|
3444
|
+
* and a finger's touchend after it is cancelled.
|
|
3445
|
+
*/
|
|
3446
|
+
refuseCancelledLift(event) {
|
|
3447
|
+
armClickGuard(this.doc, {
|
|
3448
|
+
takesLateMouse: event.pointerType === 'touch'
|
|
3449
|
+
});
|
|
3450
|
+
if (event.pointerType === 'touch') {
|
|
3451
|
+
// Noted as a claimed lift is: capped, and gone after its time.
|
|
3452
|
+
this.noteClaimedLift(event);
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3382
3456
|
/** The app lost focus: UIKit cancels every touch in flight. */
|
|
3383
3457
|
cancelEverything(time) {
|
|
3458
|
+
// The browser may keep a pen or a pointer-read finger down: its lift must
|
|
3459
|
+
// not click. A mouse button held through the blur keeps its click.
|
|
3460
|
+
for (const [pointerId, kind] of this.pointerKinds) {
|
|
3461
|
+
if (kind !== 'mouse') {
|
|
3462
|
+
this.cancelledPointers.set(pointerId, kind);
|
|
3463
|
+
}
|
|
3464
|
+
}
|
|
3384
3465
|
const ids = [...this.pointerIds.values()];
|
|
3385
3466
|
for (const id of ids) {
|
|
3386
3467
|
this.unlockSelection(id, true);
|
|
@@ -3394,6 +3475,7 @@ export class GestureHost {
|
|
|
3394
3475
|
}
|
|
3395
3476
|
}
|
|
3396
3477
|
this.pointerIds.clear();
|
|
3478
|
+
this.pointerKinds.clear();
|
|
3397
3479
|
this.retargeted.clear();
|
|
3398
3480
|
this.fingerPointers.clear();
|
|
3399
3481
|
this.pendingPointers.clear();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PressTracker.d.ts","sourceRoot":"","sources":["../../src/gestures/PressTracker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PressTracker.d.ts","sourceRoot":"","sources":["../../src/gestures/PressTracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,7 +47,8 @@
|
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
49
|
import { UIKIT_CONTROL, UIKIT_PAN, UIKIT_PRESS } from "../motion/uikit/gestures.js";
|
|
50
|
-
|
|
50
|
+
// Importing the whole table bundles its curves into each press-tracking control.
|
|
51
|
+
import { press as pressClocks } from "../motion/uikit/timing.js";
|
|
51
52
|
import { travel } from "./geometry.js";
|
|
52
53
|
const PRESS = UIKIT_PRESS;
|
|
53
54
|
|
|
@@ -63,7 +64,7 @@ export const PRESS_PROFILES = {
|
|
|
63
64
|
// The shared press styles release every surface on the deselect clock
|
|
64
65
|
// until a control runs its own release (UIButton's 250 ms), so a
|
|
65
66
|
// painter's `fading` never outlasts the fade it shows.
|
|
66
|
-
releaseMs:
|
|
67
|
+
releaseMs: pressClocks.highlightOutMs
|
|
67
68
|
},
|
|
68
69
|
/**
|
|
69
70
|
* A table or collection cell: inside a scroll view it highlights after the
|
|
@@ -74,7 +75,7 @@ export const PRESS_PROFILES = {
|
|
|
74
75
|
highlightDelay: 'inScrollers',
|
|
75
76
|
cancelTravel: UIKIT_PAN.hysteresis.value,
|
|
76
77
|
quickTapFlash: 0,
|
|
77
|
-
releaseMs:
|
|
78
|
+
releaseMs: pressClocks.highlightOutMs
|
|
78
79
|
}
|
|
79
80
|
};
|
|
80
81
|
/**
|
|
@@ -31,7 +31,8 @@ export interface ActionGroupTrackerOptions {
|
|
|
31
31
|
* target past the group's ends commits the lift there wherever the finger
|
|
32
32
|
* lifts.
|
|
33
33
|
* @default the target whose rect, grown by `highlightExpansion`, holds the
|
|
34
|
-
* point; none between or
|
|
34
|
+
* point, the one the press landed on where several do; none between or
|
|
35
|
+
* outside them
|
|
35
36
|
*/
|
|
36
37
|
resolveTarget?: (x: number, y: number, targets: ReadonlyArray<ActionGroupTarget>) => HTMLElement | null;
|
|
37
38
|
/** Every finger position it is given (the begin and each move), first. */
|
|
@@ -52,9 +53,11 @@ export interface ActionGroupTracker {
|
|
|
52
53
|
/**
|
|
53
54
|
* A press began at viewport (x, y): read the actions' rects once and
|
|
54
55
|
* highlight the one under it. An inert press is taken but tracks nothing.
|
|
56
|
+
* `landed` is the node the press landed on.
|
|
55
57
|
*/
|
|
56
58
|
begin(x: number, y: number, options?: {
|
|
57
59
|
inert?: boolean;
|
|
60
|
+
landed?: Node | null;
|
|
58
61
|
}): void;
|
|
59
62
|
/** The finger moved to viewport (x, y). */
|
|
60
63
|
move(x: number, y: number): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actionGroupTracker.d.ts","sourceRoot":"","sources":["../../src/hooks/actionGroupTracker.ts"],"names":[],"mappings":"AAsBA,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,wEAAwE;IACxE,KAAK,EAAE,MAAM,QAAQ,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClD,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAClB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,QAAQ,EAAE,WAAW,GAAG,IAAI,KACzB,IAAI,CAAC;IACV,2EAA2E;IAC3E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC
|
|
1
|
+
{"version":3,"file":"actionGroupTracker.d.ts","sourceRoot":"","sources":["../../src/hooks/actionGroupTracker.ts"],"names":[],"mappings":"AAsBA,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC,wEAAwE;IACxE,KAAK,EAAE,MAAM,QAAQ,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAClD,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,CAClB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,QAAQ,EAAE,WAAW,GAAG,IAAI,KACzB,IAAI,CAAC;IACV,2EAA2E;IAC3E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IACzC;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,CACd,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,KACtC,WAAW,GAAG,IAAI,CAAC;IACxB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,KAAK,CACH,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,OAAO,CAAC,EAAE;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;KAAC,GAChD,IAAI,CAAC;IACR,2CAA2C;IAC3C,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;;;OAKG;IACH,GAAG,IAAI,WAAW,GAAG,IAAI,CAAC;IAC1B,+EAA+E;IAC/E,MAAM,IAAI,IAAI,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;;OAIG;IACH,SAAS,IAAI,IAAI,CAAC;IAClB,kCAAkC;IAClC,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IACzC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC,0EAA0E;IAC1E,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;;OAGG;IACH,OAAO,IAAI,IAAI,CAAC;CACjB;AAUD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,MAAM,yBAAyB,GAC1C,kBAAkB,CAyOpB"}
|
|
@@ -42,6 +42,7 @@ export function createActionGroupTracker(getOptions) {
|
|
|
42
42
|
let actions = [];
|
|
43
43
|
let highlighted = null;
|
|
44
44
|
let beganOn = null;
|
|
45
|
+
let landedOn = null;
|
|
45
46
|
let isTracking = false;
|
|
46
47
|
let isInert = false;
|
|
47
48
|
// The finger's last position: `remeasure` resolves it again.
|
|
@@ -131,23 +132,31 @@ export function createActionGroupTracker(getOptions) {
|
|
|
131
132
|
if (resolveTarget != null) {
|
|
132
133
|
return actions.length === 0 ? null : resolveTarget(x, y, actions);
|
|
133
134
|
}
|
|
135
|
+
// Rects that share an edge, or that have no layout (a test renderer), can
|
|
136
|
+
// both hold the point: the one the press landed on wins.
|
|
137
|
+
let first = null;
|
|
134
138
|
for (const action of actions) {
|
|
135
139
|
if (x >= action.left - margin && x <= action.right + margin && y >= action.top - margin && y <= action.bottom + margin) {
|
|
136
|
-
|
|
140
|
+
if (landedOn != null && action.element.contains(landedOn)) {
|
|
141
|
+
return action.element;
|
|
142
|
+
}
|
|
143
|
+
first ??= action.element;
|
|
137
144
|
}
|
|
138
145
|
}
|
|
139
|
-
return
|
|
146
|
+
return first;
|
|
140
147
|
};
|
|
141
148
|
const reset = () => {
|
|
142
149
|
actions = [];
|
|
143
150
|
highlighted = null;
|
|
144
151
|
beganOn = null;
|
|
152
|
+
landedOn = null;
|
|
145
153
|
isTracking = false;
|
|
146
154
|
isInert = false;
|
|
147
155
|
};
|
|
148
156
|
return {
|
|
149
157
|
begin(x, y, {
|
|
150
|
-
inert = false
|
|
158
|
+
inert = false,
|
|
159
|
+
landed = null
|
|
151
160
|
} = {}) {
|
|
152
161
|
// A press can begin while another is tracked, when a second recognizer
|
|
153
162
|
// takes over the finger (a trigger's held press, then the menu's): the
|
|
@@ -161,6 +170,7 @@ export function createActionGroupTracker(getOptions) {
|
|
|
161
170
|
highlighted = null;
|
|
162
171
|
isTracking = true;
|
|
163
172
|
isInert = inert;
|
|
173
|
+
landedOn = landed;
|
|
164
174
|
lastX = x;
|
|
165
175
|
lastY = y;
|
|
166
176
|
getOptions().onMove?.(x, y);
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -53,6 +53,7 @@ export { useInputStatusIcon } from './useInputStatusIcon.js';
|
|
|
53
53
|
export type { UseInputStatusIconOptions, UseInputStatusIconReturn, } from './useInputStatusIcon.js';
|
|
54
54
|
export { useInteractiveRole } from './useInteractiveRole.js';
|
|
55
55
|
export type { InteractiveRole, UseInteractiveRoleOptions, } from './useInteractiveRole.js';
|
|
56
|
+
export { useAnimator } from './useAnimator.js';
|
|
56
57
|
export { useLongPress } from './useLongPress.js';
|
|
57
58
|
export type { UseLongPressOptions, UseLongPressHandlers } from './useLongPress.js';
|
|
58
59
|
export { usePressFeedback } from './usePressFeedback.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAC,wBAAwB,EAAE,YAAY,EAAC,MAAM,gBAAgB,CAAC;AACtE,YAAY,EAAC,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,YAAY,EACV,UAAU,EACV,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AACxC,YAAY,EAAC,MAAM,EAAC,MAAM,cAAc,CAAC;AAEzC,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAE5C,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAC,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAC,aAAa,EAAE,oBAAoB,EAAC,MAAM,oBAAoB,CAAC;AACvE,YAAY,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,GACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAC;AAClD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAC,mBAAmB,EAAE,kBAAkB,EAAC,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAC,kBAAkB,EAAE,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAEzE,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAC,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AAE7D,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EACV,cAAc,EACd,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAC,oBAAoB,EAAC,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,YAAY,EACV,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,iBAAiB,EAAE,mBAAmB,EAAC,MAAM,gBAAgB,CAAC;AAE3E,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC;AACtD,YAAY,EAAC,wBAAwB,EAAC,MAAM,qBAAqB,CAAC;AAElE,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACxD,YAAY,EACV,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACxD,YAAY,EACV,eAAe,EACf,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAC;AAC5C,YAAY,EAAC,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,gBAAgB,CAAC;AAE9E,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,qBAAqB,EAAC,MAAM,yBAAyB,CAAC;AAE9D,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AACxD,YAAY,EACV,yBAAyB,EACzB,wBAAwB,EACxB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -35,6 +35,7 @@ export { useClickableContainer, INTERACTIVE_SELECTORS, hasInteractiveAncestor, h
|
|
|
35
35
|
export { useInputContainer } from "./useInputContainer.js";
|
|
36
36
|
export { useInputStatusIcon } from "./useInputStatusIcon.js";
|
|
37
37
|
export { useInteractiveRole } from "./useInteractiveRole.js";
|
|
38
|
+
export { useAnimator } from "./useAnimator.js";
|
|
38
39
|
export { useLongPress } from "./useLongPress.js";
|
|
39
40
|
export { usePressFeedback } from "./usePressFeedback.js";
|
|
40
41
|
export { useDevWarning } from "./useDevWarning.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True inside a group whose tracker paints a pointer's press on its actions.
|
|
3
|
+
* Those actions take no `:active` paint, so one press never lights two.
|
|
4
|
+
*/
|
|
5
|
+
export declare const PressGroupContext: import("react").Context<boolean>;
|
|
6
|
+
//# sourceMappingURL=pressGroupContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pressGroupContext.d.ts","sourceRoot":"","sources":["../../src/hooks/pressGroupContext.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,eAAO,MAAM,iBAAiB,kCAAuB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file pressGroupContext.ts
|
|
7
|
+
* @input Nothing
|
|
8
|
+
* @output PressGroupContext: true inside a group whose own tracker paints
|
|
9
|
+
* its actions' press
|
|
10
|
+
* @position Internal; not exported from the hooks entry. AlertDialog
|
|
11
|
+
* provides it around its tracked actions, and Button reads it.
|
|
12
|
+
*/
|
|
13
|
+
import { createContext } from 'react';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* True inside a group whose tracker paints a pointer's press on its actions.
|
|
17
|
+
* Those actions take no `:active` paint, so one press never lights two.
|
|
18
|
+
*/
|
|
19
|
+
export const PressGroupContext = /*#__PURE__*/createContext(false);
|
|
20
|
+
PressGroupContext.displayName = 'PressGroupContext';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file useActionGroupTracking.ts
|
|
3
|
+
* @input A ref to a group of sibling actions, the actions' selector, and the
|
|
4
|
+
* component's tracking constants
|
|
5
|
+
* @output Exports useActionGroupTracking and ActionGroupTrackingOptions
|
|
6
|
+
* @position Internal hook, not exported from the hooks entry. A long press
|
|
7
|
+
* drives the shared action-group tracker (hooks/actionGroupTracker.ts) for
|
|
8
|
+
* a group that a held pointer slides across. AlertDialog consumes it.
|
|
9
|
+
*
|
|
10
|
+
* SYNC: When modified, update useActionGroupTracking.test.tsx
|
|
11
|
+
*/
|
|
12
|
+
import { type RefObject } from 'react';
|
|
13
|
+
import { LongPressGestureRecognizer } from '../gestures/LongPressGestureRecognizer.js';
|
|
14
|
+
import type { GestureTouch, PointerKind } from '../gestures/types.js';
|
|
15
|
+
export interface ActionGroupTrackingOptions {
|
|
16
|
+
/** Selects the actions inside the tracked element. */
|
|
17
|
+
itemSelector: string;
|
|
18
|
+
/** How long after touch-down the touched action highlights, ms. */
|
|
19
|
+
highlightOnsetMs: number;
|
|
20
|
+
/**
|
|
21
|
+
* How far outside an action a finger keeps it highlighted, px. A mouse or a
|
|
22
|
+
* pen hit-tests the actions' exact rects.
|
|
23
|
+
*/
|
|
24
|
+
highlightExpansion: number;
|
|
25
|
+
/** Pointers that are tracked; others keep the browser's click. @default every pointer */
|
|
26
|
+
pointerTypes?: ReadonlyArray<PointerKind>;
|
|
27
|
+
/** A press whose target this rejects is not tracked. */
|
|
28
|
+
shouldTrack?: (target: unknown) => boolean;
|
|
29
|
+
/** Off, nothing is attached and nothing is tracked. @default true */
|
|
30
|
+
isEnabled?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Let the gesture host write the group's `touch-action` and refuse a text
|
|
33
|
+
* selection while a finger or a pen holds it.
|
|
34
|
+
* @default true
|
|
35
|
+
*/
|
|
36
|
+
manageStyle?: boolean;
|
|
37
|
+
/** Runs the action under the finger at the lift. @default its own click */
|
|
38
|
+
onActivate?: (item: HTMLElement) => void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The group's press: a long press that a second finger on the group ends with
|
|
42
|
+
* nothing acting. A plain long press ignores a second finger.
|
|
43
|
+
*/
|
|
44
|
+
declare class ActionGroupPress extends LongPressGestureRecognizer {
|
|
45
|
+
protected acceptsTouch(touch: GestureTouch): boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Track a held pointer on the group behind `ref` across the actions inside
|
|
49
|
+
* it, through the shared action-group tracker.
|
|
50
|
+
*/
|
|
51
|
+
export declare function useActionGroupTracking(ref: RefObject<HTMLElement | null>, options: ActionGroupTrackingOptions): ActionGroupPress;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=useActionGroupTracking.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useActionGroupTracking.d.ts","sourceRoot":"","sources":["../../src/hooks/useActionGroupTracking.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,EAA8B,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAElE,OAAO,EAAC,0BAA0B,EAAC,MAAM,wCAAwC,CAAC;AAElF,OAAO,KAAK,EAAC,YAAY,EAAE,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAOjE,MAAM,WAAW,0BAA0B;IACzC,sDAAsD;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB,mEAAmE;IACnE,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B,yFAAyF;IACzF,YAAY,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,wDAAwD;IACxD,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAC3C,qEAAqE;IACrE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;CAC1C;AASD;;;GAGG;AACH,cAAM,gBAAiB,SAAQ,0BAA0B;cACpC,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO;CAO9D;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,EAClC,OAAO,EAAE,0BAA0B,GAClC,gBAAgB,CAoHlB"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
'use client';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file useActionGroupTracking.ts
|
|
7
|
+
* @input A ref to a group of sibling actions, the actions' selector, and the
|
|
8
|
+
* component's tracking constants
|
|
9
|
+
* @output Exports useActionGroupTracking and ActionGroupTrackingOptions
|
|
10
|
+
* @position Internal hook, not exported from the hooks entry. A long press
|
|
11
|
+
* drives the shared action-group tracker (hooks/actionGroupTracker.ts) for
|
|
12
|
+
* a group that a held pointer slides across. AlertDialog consumes it.
|
|
13
|
+
*
|
|
14
|
+
* SYNC: When modified, update useActionGroupTracking.test.tsx
|
|
15
|
+
*/
|
|
16
|
+
import { useEffect, useRef, useState } from 'react';
|
|
17
|
+
import { isActive } from "../gestures/GestureRecognizer.js";
|
|
18
|
+
import { LongPressGestureRecognizer } from "../gestures/LongPressGestureRecognizer.js";
|
|
19
|
+
import { lockSelection } from "../utils/selectionLock.js";
|
|
20
|
+
import { useGestureRecognizer } from "../gestures/useGestureRecognizer.js";
|
|
21
|
+
import { UIKIT_PRESS } from "../motion/uikit/gestures.js";
|
|
22
|
+
import { isIosWebKit } from "../utils/touchQueries.js";
|
|
23
|
+
import { createActionGroupTracker } from "./actionGroupTracker.js";
|
|
24
|
+
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
|
|
25
|
+
const PRESS = UIKIT_PRESS;
|
|
26
|
+
|
|
27
|
+
/** The ref handed to the recognizer while tracking is off: no element. */
|
|
28
|
+
const DETACHED = {
|
|
29
|
+
current: null
|
|
30
|
+
};
|
|
31
|
+
const EVERY_POINTER = ['touch', 'pen', 'mouse'];
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The group's press: a long press that a second finger on the group ends with
|
|
35
|
+
* nothing acting. A plain long press ignores a second finger.
|
|
36
|
+
*/
|
|
37
|
+
class ActionGroupPress extends LongPressGestureRecognizer {
|
|
38
|
+
acceptsTouch(touch) {
|
|
39
|
+
if (isActive(this.state)) {
|
|
40
|
+
this.setState('cancelled');
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
return super.acceptsTouch(touch);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Track a held pointer on the group behind `ref` across the actions inside
|
|
49
|
+
* it, through the shared action-group tracker.
|
|
50
|
+
*/
|
|
51
|
+
export function useActionGroupTracking(ref, options) {
|
|
52
|
+
const optionsRef = useRef(options);
|
|
53
|
+
// Keeps the recognizer's delegate and the tracker, which run outside
|
|
54
|
+
// render, reading the latest options.
|
|
55
|
+
useIsomorphicLayoutEffect(() => {
|
|
56
|
+
optionsRef.current = options;
|
|
57
|
+
});
|
|
58
|
+
// The pointer that started the current press. Only a finger gets the hit
|
|
59
|
+
// expansion; a mouse or a pen hit-tests the actions' exact rects.
|
|
60
|
+
const pointerRef = useRef('touch');
|
|
61
|
+
const landedRef = useRef(null);
|
|
62
|
+
const [tracker] = useState(() => createActionGroupTracker(() => ({
|
|
63
|
+
roots: () => [ref.current],
|
|
64
|
+
itemSelector: optionsRef.current.itemSelector,
|
|
65
|
+
highlightExpansion: pointerRef.current === 'touch' ? optionsRef.current.highlightExpansion : 0,
|
|
66
|
+
onActivate: optionsRef.current.onActivate,
|
|
67
|
+
// The browser's own click for a press the group ran is taken, so the
|
|
68
|
+
// action runs once. The gesture host swallows it for a press it claims.
|
|
69
|
+
// This covers one it does not claim, a mouse under a coarse pointer.
|
|
70
|
+
swallowsNativeClick: true
|
|
71
|
+
})));
|
|
72
|
+
const isEnabled = options.isEnabled ?? true;
|
|
73
|
+
// Synchronizes the tracker with tracking on and mounted. Turning tracking
|
|
74
|
+
// off, or unmounting, drops a tracked press and ends its release fades.
|
|
75
|
+
// The host reports no cancellation to a disabled recognizer, and the lift
|
|
76
|
+
// that runs an action often closes the owner before its fade ends.
|
|
77
|
+
useEffect(() => () => {
|
|
78
|
+
tracker.cancel();
|
|
79
|
+
tracker.dispose();
|
|
80
|
+
}, [tracker, isEnabled]);
|
|
81
|
+
return useGestureRecognizer(isEnabled ? ref : DETACHED, () => new ActionGroupPress({
|
|
82
|
+
name: 'ActionGroupTracking',
|
|
83
|
+
minimumPressDuration: options.highlightOnsetMs,
|
|
84
|
+
allowableMovement: Number.POSITIVE_INFINITY,
|
|
85
|
+
allowedPointerTypes: options.pointerTypes ?? EVERY_POINTER,
|
|
86
|
+
delaysTouchesBegan: true,
|
|
87
|
+
// The hold picks an action, so a held finger or pen starts no text
|
|
88
|
+
// selection and opens no callout while down. A long press brings this
|
|
89
|
+
// lock by default; this hold has no minimum duration, so it names it.
|
|
90
|
+
selectionLock: lockSelection,
|
|
91
|
+
shouldReceiveTouch: (recognizer, touch) => {
|
|
92
|
+
if (recognizer.numberOfTouches === 0) {
|
|
93
|
+
pointerRef.current = touch.pointerType;
|
|
94
|
+
const target = touch.target;
|
|
95
|
+
landedRef.current = typeof target?.nodeType === 'number' ? target : null;
|
|
96
|
+
}
|
|
97
|
+
return receiveTouch(recognizer, touch, optionsRef.current);
|
|
98
|
+
}
|
|
99
|
+
}), recognizer => {
|
|
100
|
+
switch (recognizer.state) {
|
|
101
|
+
case 'began':
|
|
102
|
+
{
|
|
103
|
+
const {
|
|
104
|
+
x,
|
|
105
|
+
y
|
|
106
|
+
} = recognizer.location();
|
|
107
|
+
tracker.begin(x, y, {
|
|
108
|
+
landed: landedRef.current
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
case 'changed':
|
|
113
|
+
{
|
|
114
|
+
const {
|
|
115
|
+
x,
|
|
116
|
+
y
|
|
117
|
+
} = recognizer.location();
|
|
118
|
+
tracker.move(x, y);
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
case 'ended':
|
|
122
|
+
{
|
|
123
|
+
const doc = ref.current?.ownerDocument;
|
|
124
|
+
const focusedBefore = doc?.activeElement ?? null;
|
|
125
|
+
const beganOn = tracker.beganOn;
|
|
126
|
+
// Whether a click on the lifted action would focus it. A mouse's or
|
|
127
|
+
// a pen's pointerdown already gave the engine's answer, on the action
|
|
128
|
+
// it began on. A tap focuses on a later mousedown, which the claimed
|
|
129
|
+
// touch cancels, so the platform answers for a finger.
|
|
130
|
+
// iOS WebKit focuses no tapped button; Chromium and Firefox do.
|
|
131
|
+
const clickFocuses = pointerRef.current === 'touch' ? !isIosWebKit(doc?.defaultView) : beganOn != null && focusedBefore === beganOn;
|
|
132
|
+
const lifted = tracker.end();
|
|
133
|
+
// The lift runs the action's own click(), which moves no focus. So
|
|
134
|
+
// focus moves to the lifted action, unless its click moved focus.
|
|
135
|
+
if (clickFocuses && lifted != null && lifted.isConnected && doc?.activeElement === focusedBefore && focusedBefore !== lifted) {
|
|
136
|
+
lifted.focus({
|
|
137
|
+
preventScroll: true,
|
|
138
|
+
focusVisible: false
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case 'cancelled':
|
|
144
|
+
tracker.cancel();
|
|
145
|
+
break;
|
|
146
|
+
case 'possible':
|
|
147
|
+
case 'failed':
|
|
148
|
+
// Listeners are not called for these.
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}, {
|
|
152
|
+
isEnabled,
|
|
153
|
+
manageStyle: options.manageStyle ?? true,
|
|
154
|
+
actionGroup: true
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The recognizer's should-receive delegate. It also picks the press's clock.
|
|
160
|
+
* Inside a scroller the press waits the content-touch delay and fails past
|
|
161
|
+
* the slop, so the scroller takes a flick. Elsewhere it begins at once, with
|
|
162
|
+
* no movement limit.
|
|
163
|
+
*/
|
|
164
|
+
function receiveTouch(recognizer, touch, options) {
|
|
165
|
+
if (options.shouldTrack?.(touch.target) === false) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
if (recognizer.numberOfTouches === 0) {
|
|
169
|
+
const isInsideScroller = touch.scroll?.isInsideScroller === true;
|
|
170
|
+
recognizer.minimumPressDuration = isInsideScroller ? PRESS.contentTouchDelay.value : options.highlightOnsetMs;
|
|
171
|
+
recognizer.allowableMovement = isInsideScroller ? PRESS.slop.value : Number.POSITIVE_INFINITY;
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
}
|