@astryxdesign/core 0.4.4-canary.eb069fd → 0.4.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astryxdesign/core",
3
- "version": "0.4.4-canary.eb069fd",
3
+ "version": "0.4.4",
4
4
  "displayName": "Astryx Core",
5
5
  "description": "The component library. Accessible, themeable React components with built-in spacing, dark mode, and StyleX styling.",
6
6
  "author": "Meta Open Source",
@@ -656,7 +656,6 @@
656
656
  "react-dom": ">=19.0.0"
657
657
  },
658
658
  "devDependencies": {
659
- "@astryxdesign/cli": "0.4.4-canary.eb069fd",
660
659
  "@babel/cli": "^8.0.4",
661
660
  "@babel/core": "^7.29.7",
662
661
  "@babel/preset-react": "^8.0.1",
@@ -665,7 +664,8 @@
665
664
  "@testing-library/dom": "^10.0.0",
666
665
  "@testing-library/jest-dom": "^6.6.0",
667
666
  "@testing-library/react": "^16.3.2",
668
- "rimraf": "^6.0.1"
667
+ "rimraf": "^6.0.1",
668
+ "@astryxdesign/cli": "0.4.4"
669
669
  },
670
670
  "dependencies": {
671
671
  "intl-messageformat": "^11.2.9"
@@ -726,51 +726,6 @@ describe('useSheetGestures', () => {
726
726
  return el;
727
727
  }
728
728
 
729
- // iOS Safari raises PointerEvents for a finger under the SAME numeric id
730
- // it puts in `Touch.identifier`, so a drag the touch path starts is keyed
731
- // to a live pointer. WebKit takes that pointer's capture straight back,
732
- // and the `lostpointercapture` that follows used to cancel the drag one
733
- // event after it began — leaving the sheet inert for the rest of the pull
734
- // while the handle still worked. Every browser that keeps the two id
735
- // spaces apart hides this, which is why it only showed up on device.
736
- it('survives a lostpointercapture for the finger driving it', () => {
737
- const {hook} = setup({snapHeights: () => [200]});
738
- const el = midDetentScroller(hook, 600); // parked at the content end
739
- act(() => {
740
- touch(el, 'touchstart', 500, 7);
741
- touch(el, 'touchmove', 450, 7); // promotes at the armed bottom edge
742
- });
743
- expect(hook.result.current.isDragging).toBe(true);
744
- act(() => {
745
- hook.result.current.bodyProps.onLostPointerCapture(
746
- pointerEvent(450, 0, el, 7), // same id as the touch: iOS does this
747
- );
748
- });
749
- expect(hook.result.current.isDragging).toBe(true);
750
- act(() => {
751
- touch(el, 'touchmove', 400, 7);
752
- });
753
- // 100px of pull past the touchstart, from the 200px detent.
754
- expect(hook.result.current.dragOffset).toBe(100);
755
- });
756
-
757
- // `pointercancel` for that same finger arrives the moment WebKit claims
758
- // the gesture. Ending the drag on it settles the sheet mid-pull.
759
- it('does not end the touch drag on a pointercancel for that finger', () => {
760
- const {hook} = setup({snapHeights: () => [200]});
761
- const el = midDetentScroller(hook, 600);
762
- act(() => {
763
- touch(el, 'touchstart', 500, 7);
764
- touch(el, 'touchmove', 450, 7);
765
- });
766
- act(() => {
767
- hook.result.current.bodyProps.onPointerCancel(
768
- pointerEvent(450, 0, el, 7),
769
- );
770
- });
771
- expect(hook.result.current.isDragging).toBe(true);
772
- });
773
-
774
729
  it('hands off when the content runs out under a moving finger', () => {
775
730
  const {hook} = setup({snapHeights: () => [200]});
776
731
  const el = midDetentScroller(hook, 300); // finger lands mid-content
@@ -82,19 +82,6 @@ const DISMISS_OVERSHOOT_RATIO = 0.4;
82
82
  // Within this many px of a detent, the live drag is magnetically eased toward
83
83
  // it so it "clicks" into place instead of hovering just off the mark.
84
84
  const MAGNET_RANGE = 40;
85
- // The touch path drives the sheet through the same machinery the pointer path
86
- // uses, by handing it a pointer-shaped object built from a `Touch`. On iOS
87
- // Safari that object is indistinguishable from the real thing: WebKit raises
88
- // PointerEvents for a finger under the SAME numeric id it puts in
89
- // `Touch.identifier`, so such a drag is keyed to a live pointer and the
90
- // handlers that guard a mouse drag fire against it. Mark the synthetic object
91
- // so they can tell the two apart.
92
- type SyntheticTouchPointer = ReactPointerEvent & {syntheticTouch?: true};
93
-
94
- function isSyntheticTouch(event: ReactPointerEvent): boolean {
95
- return (event as SyntheticTouchPointer).syntheticTouch === true;
96
- }
97
-
98
85
  // Rubber-band factor for dragging up past fully-open, capped at OVERSCROLL_MAX
99
86
  // (the sheet reserves that much bottom padding for the lift to reveal).
100
87
  const OVERSCROLL_RESISTANCE = 0.35;
@@ -447,10 +434,6 @@ export function useSheetGestures({
447
434
 
448
435
  // Live drag bookkeeping (refs so pointermove doesn't churn renders).
449
436
  const dragStateRef = useRef<{
450
- // Whether the touch path drives this drag. Such a drag holds no pointer
451
- // capture and takes its events from `touchmove`, so every real-pointer
452
- // handler has to leave it alone.
453
- syntheticTouch: boolean;
454
437
  pointerId: number;
455
438
  startCoord: number;
456
439
  lastCoord: number;
@@ -872,16 +855,7 @@ export function useSheetGestures({
872
855
  const beginDrag = useCallback(
873
856
  (event: ReactPointerEvent, sheetHeight: number, startCoord?: number) => {
874
857
  const target = event.currentTarget as HTMLElement;
875
- const syntheticTouch = isSyntheticTouch(event);
876
- // Never capture for a touch drag. The id came from `Touch.identifier`,
877
- // which on iOS names a live pointer: the capture succeeds, WebKit takes
878
- // it straight back for its own gesture handling, and the
879
- // `lostpointercapture` a millisecond later cancels the drag that just
880
- // started. Touch drags need no capture — the listener is on the
881
- // scroller itself.
882
- if (!syntheticTouch) {
883
- target.setPointerCapture?.(event.pointerId);
884
- }
858
+ target.setPointerCapture?.(event.pointerId);
885
859
  // `startCoord` lets a body-overscroll drag anchor at the original
886
860
  // pointer-down position (not the promotion point), so the first frame's
887
861
  // delta reflects the full pull distance.
@@ -889,7 +863,6 @@ export function useSheetGestures({
889
863
  const naturalEndGap = naturalEndGapFor(bodyNodeRef.current);
890
864
  const baseLayoutOffset = settledLayoutOffsetRef.current;
891
865
  dragStateRef.current = {
892
- syntheticTouch,
893
866
  pointerId: event.pointerId,
894
867
  startCoord: start,
895
868
  lastCoord: event.clientY,
@@ -944,12 +917,6 @@ export function useSheetGestures({
944
917
 
945
918
  const handleLostPointerCapture = useCallback(
946
919
  (event: ReactPointerEvent) => {
947
- // A touch drag never took capture, so this is WebKit reclaiming its own
948
- // pointer for the finger doing the dragging — not the drag losing its
949
- // grip.
950
- if (dragStateRef.current?.syntheticTouch) {
951
- return;
952
- }
953
920
  if (dragStateRef.current?.pointerId === event.pointerId) {
954
921
  cancelDrag();
955
922
  }
@@ -963,11 +930,6 @@ export function useSheetGestures({
963
930
  if (!state || state.pointerId !== event.pointerId) {
964
931
  return;
965
932
  }
966
- // Same finger, real pointer event: the touch path already drove this
967
- // move. Let it own the drag rather than driving it twice.
968
- if (state.syntheticTouch && !isSyntheticTouch(event)) {
969
- return;
970
- }
971
933
  const delta = event.clientY - state.startCoord;
972
934
  const dt = event.timeStamp - state.lastTime;
973
935
  if (dt > 0) {
@@ -1029,20 +991,12 @@ export function useSheetGestures({
1029
991
  if (!state || state.pointerId !== event.pointerId) {
1030
992
  return;
1031
993
  }
1032
- // `pointercancel` fires for the finger the moment WebKit claims the
1033
- // gesture; ending a touch drag on it settles the sheet mid-pull. The
1034
- // touchend handler is what finishes a touch drag.
1035
- if (state.syntheticTouch && !isSyntheticTouch(event)) {
1036
- return;
1037
- }
1038
994
  const target = event.currentTarget as HTMLElement;
1039
995
  const delta = event.clientY - state.startCoord;
1040
996
  const offset = Math.max(0, state.baseOffset + delta);
1041
997
  const dir = delta === 0 ? 0 : delta > 0 ? 1 : -1;
1042
998
  dragStateRef.current = null;
1043
- if (!state.syntheticTouch) {
1044
- target.releasePointerCapture?.(event.pointerId);
1045
- }
999
+ target.releasePointerCapture?.(event.pointerId);
1046
1000
  setIsDragging(false);
1047
1001
  settleFromDrag(
1048
1002
  offset,
@@ -1113,11 +1067,6 @@ export function useSheetGestures({
1113
1067
  const handleBodyEnd = useCallback(
1114
1068
  (event: ReactPointerEvent) => {
1115
1069
  armedBodyRef.current = null;
1116
- // The pointerup/pointercancel for a finger already driving a touch drag
1117
- // arrives here carrying that drag's own id; touchend ends those.
1118
- if (dragStateRef.current?.syntheticTouch) {
1119
- return;
1120
- }
1121
1070
  if (dragStateRef.current) {
1122
1071
  endDrag(event);
1123
1072
  }
@@ -1169,7 +1118,6 @@ export function useSheetGestures({
1169
1118
  const bodyRef = useCallback((node: HTMLElement | null) => {
1170
1119
  const asPointer = (touch: Touch, target: HTMLElement) =>
1171
1120
  ({
1172
- syntheticTouch: true,
1173
1121
  pointerId: touch.identifier,
1174
1122
  clientY: touch.clientY,
1175
1123
  timeStamp: Date.now(),