react-native-grab 0.0.3 → 0.0.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.
Files changed (36) hide show
  1. package/README.md +1 -0
  2. package/dist/cjs/react-native/__tests__/dom-traversal.test.js +160 -0
  3. package/dist/cjs/react-native/__tests__/dom-traversal.test.js.map +1 -0
  4. package/dist/cjs/react-native/__tests__/mock-dom.js +65 -0
  5. package/dist/cjs/react-native/__tests__/mock-dom.js.map +1 -0
  6. package/dist/cjs/react-native/__tests__/setup.js +43 -0
  7. package/dist/cjs/react-native/__tests__/setup.js.map +1 -0
  8. package/dist/cjs/react-native/__tests__/z-index.test.js +106 -0
  9. package/dist/cjs/react-native/__tests__/z-index.test.js.map +1 -0
  10. package/dist/cjs/react-native/dom-traversal.js +39 -44
  11. package/dist/cjs/react-native/dom-traversal.js.map +1 -1
  12. package/dist/cjs/react-native/z-index.js +18 -8
  13. package/dist/cjs/react-native/z-index.js.map +1 -1
  14. package/dist/esm/react-native/__tests__/dom-traversal.test.js +158 -0
  15. package/dist/esm/react-native/__tests__/dom-traversal.test.js.map +1 -0
  16. package/dist/esm/react-native/__tests__/mock-dom.js +58 -0
  17. package/dist/esm/react-native/__tests__/mock-dom.js.map +1 -0
  18. package/dist/esm/react-native/__tests__/setup.js +41 -0
  19. package/dist/esm/react-native/__tests__/setup.js.map +1 -0
  20. package/dist/esm/react-native/__tests__/z-index.test.js +104 -0
  21. package/dist/esm/react-native/__tests__/z-index.test.js.map +1 -0
  22. package/dist/esm/react-native/dom-traversal.js +40 -45
  23. package/dist/esm/react-native/dom-traversal.js.map +1 -1
  24. package/dist/esm/react-native/z-index.js +18 -8
  25. package/dist/esm/react-native/z-index.js.map +1 -1
  26. package/dist/types/react-native/__tests__/dom-traversal.test.d.ts +2 -0
  27. package/dist/types/react-native/__tests__/dom-traversal.test.d.ts.map +1 -0
  28. package/dist/types/react-native/__tests__/mock-dom.d.ts +24 -0
  29. package/dist/types/react-native/__tests__/mock-dom.d.ts.map +1 -0
  30. package/dist/types/react-native/__tests__/setup.d.ts +2 -0
  31. package/dist/types/react-native/__tests__/setup.d.ts.map +1 -0
  32. package/dist/types/react-native/__tests__/z-index.test.d.ts +2 -0
  33. package/dist/types/react-native/__tests__/z-index.test.d.ts.map +1 -0
  34. package/dist/types/react-native/dom-traversal.d.ts.map +1 -1
  35. package/dist/types/react-native/z-index.d.ts.map +1 -1
  36. package/package.json +5 -2
@@ -27,9 +27,17 @@ const getNodeZIndex = (node) => {
27
27
  }
28
28
  return 0;
29
29
  };
30
- const isAbsolutePositioned = (node) => {
30
+ const getNodePositionType = (node) => {
31
31
  const style = (0, fiber_1.getNormalizedStyle)(node);
32
- return style?.position === "absolute";
32
+ const position = style?.position;
33
+ if (position === "static" || position === "relative" || position === "absolute") {
34
+ return position;
35
+ }
36
+ // Yoga defaults to relative positioning when `position` is not set.
37
+ return "relative";
38
+ };
39
+ const getNodeOrderIndex = (node) => {
40
+ return getNodePositionType(node) === "static" ? 0 : getNodeZIndex(node);
33
41
  };
34
42
  const getChildrenInHitTestOrder = (node) => {
35
43
  const children = Array.from(node.children ?? []);
@@ -37,16 +45,18 @@ const getChildrenInHitTestOrder = (node) => {
37
45
  .map((child, index) => ({
38
46
  child,
39
47
  index,
40
- zIndex: getNodeZIndex(child),
41
- isAbsolute: isAbsolutePositioned(child),
48
+ orderIndex: getNodeOrderIndex(child),
49
+ isStatic: getNodePositionType(child) === "static",
42
50
  }))
43
51
  .sort((a, b) => {
44
- if (a.zIndex !== b.zIndex) {
45
- return a.zIndex - b.zIndex;
52
+ if (a.orderIndex !== b.orderIndex) {
53
+ return a.orderIndex - b.orderIndex;
46
54
  }
47
- if (a.isAbsolute !== b.isAbsolute) {
48
- return a.isAbsolute ? 1 : -1;
55
+ // RN keeps static siblings before non-static siblings for equal orderIndex.
56
+ if (a.isStatic !== b.isStatic) {
57
+ return a.isStatic ? -1 : 1;
49
58
  }
59
+ // Preserve sibling insertion order for fully-equal ranking.
50
60
  return a.index - b.index;
51
61
  })
52
62
  .map(({ child }) => child);
@@ -1 +1 @@
1
- {"version":3,"file":"z-index.js","sourceRoot":"","sources":["../../../src/react-native/z-index.ts"],"names":[],"mappings":";;;AAAA,mCAA+D;AAG/D,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAsB,EAAE;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC5B,OAAO,MAAM,CAAC;QAChB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,aAAa,GAAG,CAAC,IAAgB,EAAU,EAAE;IACjD,MAAM,KAAK,GAAG,IAAA,wBAAgB,EAAC,IAAI,CAAC,CAAC;IACrC,MAAM,eAAe,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;QAC5B,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,MAAM,KAAK,GAAG,IAAA,0BAAkB,EAAC,IAAI,CAAC,CAAC;IACvC,MAAM,eAAe,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAChD,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;QAC5B,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,OAAO,CAAC,CAAC;AACX,CAAC,CAAC;AAEF,MAAM,oBAAoB,GAAG,CAAC,IAAgB,EAAW,EAAE;IACzD,MAAM,KAAK,GAAG,IAAA,0BAAkB,EAAC,IAAI,CAAC,CAAC;IACvC,OAAO,KAAK,EAAE,QAAQ,KAAK,UAAU,CAAC;AACxC,CAAC,CAAC;AAEK,MAAM,yBAAyB,GAAG,CAAC,IAAgB,EAAgB,EAAE;IAC1E,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IACjD,OAAO,QAAQ;SACZ,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACtB,KAAK;QACL,KAAK;QACL,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC;QAC5B,UAAU,EAAE,oBAAoB,CAAC,KAAK,CAAC;KACxC,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACb,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YAC1B,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;QAC7B,CAAC;QACD,IAAI,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC;YAClC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAC3B,CAAC,CAAC;SACD,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC,CAAC;AAnBW,QAAA,yBAAyB,6BAmBpC"}
1
+ {"version":3,"file":"z-index.js","sourceRoot":"","sources":["../../../src/react-native/z-index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { startSession } from "../dom-traversal";
3
+ import { appendChild, createMockNode, createRoot, finalizeTree } from "./mock-dom";
4
+ const createSession = (root) => {
5
+ return startSession({
6
+ anchorRef: { current: root },
7
+ skipRefs: [],
8
+ });
9
+ };
10
+ const hitNameAt = (root, x, y) => {
11
+ const session = createSession(root);
12
+ const hit = session.move({ x, y });
13
+ session.stop();
14
+ return hit?.node ? hit.node.name : null;
15
+ };
16
+ describe("dom traversal hit testing", () => {
17
+ it("uses child-first fallback for pointerEvents:auto", () => {
18
+ const root = createRoot({ rect: { x: 0, y: 0, width: 100, height: 100 } });
19
+ const child = createMockNode({
20
+ name: "child",
21
+ rect: { x: 10, y: 10, width: 20, height: 20 },
22
+ });
23
+ appendChild(root, child);
24
+ finalizeTree(root);
25
+ expect(hitNameAt(root, 15, 15)).toBe("child");
26
+ expect(hitNameAt(root, 2, 2)).toBe("root");
27
+ });
28
+ it("respects pointerEvents box-only", () => {
29
+ const root = createRoot({
30
+ rect: { x: 0, y: 0, width: 100, height: 100 },
31
+ pointerEvents: "box-only",
32
+ });
33
+ const child = createMockNode({
34
+ name: "child",
35
+ rect: { x: 10, y: 10, width: 20, height: 20 },
36
+ });
37
+ appendChild(root, child);
38
+ finalizeTree(root);
39
+ expect(hitNameAt(root, 15, 15)).toBe("root");
40
+ });
41
+ it("respects pointerEvents box-none", () => {
42
+ const root = createRoot({
43
+ rect: { x: 0, y: 0, width: 100, height: 100 },
44
+ pointerEvents: "box-none",
45
+ });
46
+ const child = createMockNode({
47
+ name: "child",
48
+ rect: { x: 10, y: 10, width: 20, height: 20 },
49
+ });
50
+ appendChild(root, child);
51
+ finalizeTree(root);
52
+ expect(hitNameAt(root, 15, 15)).toBe("child");
53
+ expect(hitNameAt(root, 5, 5)).toBe(null);
54
+ });
55
+ it("respects pointerEvents none", () => {
56
+ const root = createRoot({
57
+ rect: { x: 0, y: 0, width: 100, height: 100 },
58
+ pointerEvents: "none",
59
+ });
60
+ const child = createMockNode({
61
+ name: "child",
62
+ rect: { x: 10, y: 10, width: 20, height: 20 },
63
+ });
64
+ appendChild(root, child);
65
+ finalizeTree(root);
66
+ expect(hitNameAt(root, 15, 15)).toBe(null);
67
+ });
68
+ it("honors zIndex for overlapping siblings", () => {
69
+ const root = createRoot({ rect: { x: 0, y: 0, width: 120, height: 120 } });
70
+ const back = createMockNode({
71
+ name: "back",
72
+ rect: { x: 20, y: 20, width: 80, height: 80 },
73
+ style: { zIndex: 0 },
74
+ });
75
+ const front = createMockNode({
76
+ name: "front",
77
+ rect: { x: 20, y: 20, width: 80, height: 80 },
78
+ style: { zIndex: 10, position: "absolute" },
79
+ });
80
+ appendChild(root, back);
81
+ appendChild(root, front);
82
+ finalizeTree(root);
83
+ expect(hitNameAt(root, 40, 40)).toBe("front");
84
+ });
85
+ it("can hit absolute children outside parent bounds when overflow is visible", () => {
86
+ const root = createRoot({ rect: { x: 0, y: 0, width: 220, height: 220 } });
87
+ const parent = createMockNode({
88
+ name: "parent",
89
+ rect: { x: 50, y: 50, width: 100, height: 100 },
90
+ style: { overflow: "visible" },
91
+ });
92
+ const badge = createMockNode({
93
+ name: "badge",
94
+ rect: { x: 130, y: 35, width: 30, height: 20 },
95
+ style: { position: "absolute", zIndex: 2 },
96
+ });
97
+ appendChild(root, parent);
98
+ appendChild(parent, badge);
99
+ finalizeTree(root);
100
+ expect(hitNameAt(root, 135, 40)).toBe("badge");
101
+ });
102
+ it("clips outside-parent hits when overflow is hidden", () => {
103
+ const root = createRoot({ rect: { x: 0, y: 0, width: 220, height: 220 } });
104
+ const parent = createMockNode({
105
+ name: "parent",
106
+ rect: { x: 50, y: 50, width: 100, height: 100 },
107
+ style: { overflow: "hidden" },
108
+ });
109
+ const badge = createMockNode({
110
+ name: "badge",
111
+ rect: { x: 130, y: 35, width: 30, height: 20 },
112
+ style: { position: "absolute", zIndex: 2 },
113
+ });
114
+ appendChild(root, parent);
115
+ appendChild(parent, badge);
116
+ finalizeTree(root);
117
+ expect(hitNameAt(root, 135, 40)).toBe("root");
118
+ });
119
+ it("treats right/bottom edges as out-of-bounds", () => {
120
+ const root = createRoot({ rect: { x: 0, y: 0, width: 100, height: 100 } });
121
+ const child = createMockNode({
122
+ name: "child",
123
+ rect: { x: 10, y: 10, width: 20, height: 20 },
124
+ });
125
+ appendChild(root, child);
126
+ finalizeTree(root);
127
+ expect(hitNameAt(root, 30, 15)).toBe("root");
128
+ expect(hitNameAt(root, 15, 30)).toBe("root");
129
+ });
130
+ it("selects an absolute badge in a card fixture similar to explore screen", () => {
131
+ const root = createRoot({ rect: { x: 0, y: 0, width: 360, height: 640 } });
132
+ const card = createMockNode({
133
+ name: "card",
134
+ rect: { x: 40, y: 120, width: 200, height: 140 },
135
+ style: { overflow: "visible", borderRadius: 12 },
136
+ });
137
+ const image = createMockNode({
138
+ name: "image",
139
+ rect: { x: 40, y: 120, width: 200, height: 88 },
140
+ });
141
+ const content = createMockNode({
142
+ name: "content",
143
+ rect: { x: 40, y: 208, width: 200, height: 52 },
144
+ });
145
+ const badge = createMockNode({
146
+ name: "badge",
147
+ rect: { x: 180, y: 110, width: 64, height: 24 },
148
+ style: { position: "absolute", zIndex: 20 },
149
+ });
150
+ appendChild(root, card);
151
+ appendChild(card, badge);
152
+ appendChild(card, image);
153
+ appendChild(card, content);
154
+ finalizeTree(root);
155
+ expect(hitNameAt(root, 190, 116)).toBe("badge");
156
+ });
157
+ });
158
+ //# sourceMappingURL=dom-traversal.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-traversal.test.js","sourceRoot":"","sources":["../../../../src/react-native/__tests__/dom-traversal.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ const createFiberHandle = (style, pointerEvents, extraProps) => {
2
+ return {
3
+ tag: 5,
4
+ stateNode: {
5
+ canonical: {
6
+ currentProps: {
7
+ ...extraProps,
8
+ ...(pointerEvents ? { pointerEvents } : null),
9
+ ...(style ? { style } : null),
10
+ },
11
+ },
12
+ },
13
+ };
14
+ };
15
+ export const createMockNode = ({ name, rect, style, pointerEvents, hasFiber = true, tagName = "RN:View", props = {}, }) => {
16
+ const node = {
17
+ name,
18
+ tagName,
19
+ parentElement: null,
20
+ children: [],
21
+ childElementCount: 0,
22
+ getBoundingClientRect: () => rect,
23
+ contains(target) {
24
+ if (!target)
25
+ return false;
26
+ if (target === node)
27
+ return true;
28
+ return node.children.some((child) => child.contains(target));
29
+ },
30
+ __internalInstanceHandle: hasFiber
31
+ ? createFiberHandle(style, pointerEvents, props)
32
+ : undefined,
33
+ };
34
+ return node;
35
+ };
36
+ export const appendChild = (parent, child) => {
37
+ parent.children.push(child);
38
+ parent.childElementCount = parent.children.length;
39
+ child.parentElement = parent;
40
+ };
41
+ const setRootView = (node, root) => {
42
+ node.__rootView = root;
43
+ for (const child of node.children) {
44
+ setRootView(child, root);
45
+ }
46
+ };
47
+ export const createRoot = ({ name = "root", rect = { x: 0, y: 0, width: 400, height: 800 }, style, pointerEvents, props, } = {}) => {
48
+ const root = createMockNode({ name, rect, style, pointerEvents, props });
49
+ root.ownerDocument = {
50
+ documentElement: root,
51
+ };
52
+ setRootView(root, root);
53
+ return root;
54
+ };
55
+ export const finalizeTree = (root) => {
56
+ setRootView(root, root);
57
+ };
58
+ //# sourceMappingURL=mock-dom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-dom.js","sourceRoot":"","sources":["../../../../src/react-native/__tests__/mock-dom.ts"],"names":[],"mappings":"AAkBA,MAAM,iBAAiB,GAAG,CACxB,KAA0C,EAC1C,aAA+C,EAC/C,UAAmC,EACnC,EAAE;IACF,OAAO;QACL,GAAG,EAAE,CAAC;QACN,SAAS,EAAE;YACT,SAAS,EAAE;gBACT,YAAY,EAAE;oBACZ,GAAG,UAAU;oBACb,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;oBAC7C,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAC9B;aACF;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,EAC7B,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,aAAa,EACb,QAAQ,GAAG,IAAI,EACf,OAAO,GAAG,SAAS,EACnB,KAAK,GAAG,EAAE,GACM,EAAY,EAAE;IAC9B,MAAM,IAAI,GAAG;QACX,IAAI;QACJ,OAAO;QACP,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,EAAgB;QAC1B,iBAAiB,EAAE,CAAC;QACpB,qBAAqB,EAAE,GAAG,EAAE,CAAC,IAAI;QACjC,QAAQ,CAAC,MAAqC;YAC5C,IAAI,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;YAC1B,IAAI,MAAM,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YACjC,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC/D,CAAC;QACD,wBAAwB,EAAE,QAAQ;YAChC,CAAC,CAAC,iBAAiB,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,CAAC;YAChD,CAAC,CAAC,SAAS;KACK,CAAC;IAErB,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,MAAgB,EAAE,KAAe,EAAE,EAAE;IAC/D,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,MAAM,CAAC,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;IAClD,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;AAC/B,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,CAAC,IAAc,EAAE,IAAc,EAAE,EAAE;IACrD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACvB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,EAC9C,KAAK,EACL,aAAa,EACb,KAAK,MAIH,EAAE,EAAY,EAAE;IAClB,MAAM,IAAI,GAAG,cAAc,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,aAAa,GAAG;QACnB,eAAe,EAAE,IAAI;KACtB,CAAC;IACF,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxB,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAc,EAAE,EAAE;IAC7C,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { vi } from "vitest";
2
+ const flattenStyle = (style) => {
3
+ if (style == null) {
4
+ return undefined;
5
+ }
6
+ if (Array.isArray(style)) {
7
+ const merged = {};
8
+ for (const item of style) {
9
+ const next = flattenStyle(item);
10
+ if (!next)
11
+ continue;
12
+ Object.assign(merged, next);
13
+ }
14
+ return merged;
15
+ }
16
+ if (typeof style === "object") {
17
+ return { ...style };
18
+ }
19
+ return undefined;
20
+ };
21
+ vi.mock("react-native", () => {
22
+ return {
23
+ StyleSheet: {
24
+ flatten: flattenStyle,
25
+ },
26
+ };
27
+ });
28
+ vi.mock("react-native/Libraries/Debugging/DebuggingOverlayRegistry", () => {
29
+ return {
30
+ default: {
31
+ __findLowestParentFromRegistryForInstance(node) {
32
+ return {
33
+ rootViewRef: {
34
+ current: node.__rootView ?? node,
35
+ },
36
+ };
37
+ },
38
+ },
39
+ };
40
+ });
41
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../../src/react-native/__tests__/setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE5B,MAAM,YAAY,GAAG,CAAC,KAAc,EAAuC,EAAE;IAC3E,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,MAAM,GAA4B,EAAE,CAAC;QAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YAChC,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,EAAE,GAAI,KAAiC,EAAE,CAAC;IACnD,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC;AAEF,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,GAAG,EAAE;IAC3B,OAAO;QACL,UAAU,EAAE;YACV,OAAO,EAAE,YAAY;SACtB;KACF,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,EAAE,CAAC,IAAI,CAAC,2DAA2D,EAAE,GAAG,EAAE;IACxE,OAAO;QACL,OAAO,EAAE;YACP,yCAAyC,CAAC,IAA8B;gBACtE,OAAO;oBACL,WAAW,EAAE;wBACX,OAAO,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI;qBACjC;iBACF,CAAC;YACJ,CAAC;SACF;KACF,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,104 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { appendChild, createMockNode, createRoot, finalizeTree } from "./mock-dom";
3
+ import { getChildrenInHitTestOrder } from "../z-index";
4
+ describe("getChildrenInHitTestOrder", () => {
5
+ it("orders by zIndex ascending", () => {
6
+ const root = createRoot();
7
+ const c1 = createMockNode({
8
+ name: "c1",
9
+ rect: { x: 0, y: 0, width: 10, height: 10 },
10
+ style: { zIndex: 3 },
11
+ });
12
+ const c2 = createMockNode({
13
+ name: "c2",
14
+ rect: { x: 0, y: 0, width: 10, height: 10 },
15
+ style: { zIndex: 1 },
16
+ });
17
+ const c3 = createMockNode({
18
+ name: "c3",
19
+ rect: { x: 0, y: 0, width: 10, height: 10 },
20
+ style: { zIndex: 2 },
21
+ });
22
+ appendChild(root, c1);
23
+ appendChild(root, c2);
24
+ appendChild(root, c3);
25
+ finalizeTree(root);
26
+ expect(getChildrenInHitTestOrder(root).map((n) => n.name)).toEqual([
27
+ "c2",
28
+ "c3",
29
+ "c1",
30
+ ]);
31
+ });
32
+ it("supports negative zIndex", () => {
33
+ const root = createRoot();
34
+ const low = createMockNode({
35
+ name: "low",
36
+ rect: { x: 0, y: 0, width: 10, height: 10 },
37
+ style: { zIndex: -10 },
38
+ });
39
+ const mid = createMockNode({
40
+ name: "mid",
41
+ rect: { x: 0, y: 0, width: 10, height: 10 },
42
+ style: { zIndex: 0 },
43
+ });
44
+ const high = createMockNode({
45
+ name: "high",
46
+ rect: { x: 0, y: 0, width: 10, height: 10 },
47
+ style: { zIndex: 10 },
48
+ });
49
+ appendChild(root, mid);
50
+ appendChild(root, high);
51
+ appendChild(root, low);
52
+ finalizeTree(root);
53
+ expect(getChildrenInHitTestOrder(root).map((n) => n.name)).toEqual([
54
+ "low",
55
+ "mid",
56
+ "high",
57
+ ]);
58
+ });
59
+ it("preserves sibling order when order index matches", () => {
60
+ const root = createRoot();
61
+ const a = createMockNode({
62
+ name: "a",
63
+ rect: { x: 0, y: 0, width: 10, height: 10 },
64
+ });
65
+ const b = createMockNode({
66
+ name: "b",
67
+ rect: { x: 0, y: 0, width: 10, height: 10 },
68
+ });
69
+ const c = createMockNode({
70
+ name: "c",
71
+ rect: { x: 0, y: 0, width: 10, height: 10 },
72
+ });
73
+ appendChild(root, a);
74
+ appendChild(root, b);
75
+ appendChild(root, c);
76
+ finalizeTree(root);
77
+ expect(getChildrenInHitTestOrder(root).map((n) => n.name)).toEqual([
78
+ "a",
79
+ "b",
80
+ "c",
81
+ ]);
82
+ });
83
+ it("puts static nodes before non-static nodes for equal order index", () => {
84
+ const root = createRoot();
85
+ const staticNode = createMockNode({
86
+ name: "static",
87
+ rect: { x: 0, y: 0, width: 10, height: 10 },
88
+ style: { position: "static", zIndex: 999 },
89
+ });
90
+ const relativeNode = createMockNode({
91
+ name: "relative",
92
+ rect: { x: 0, y: 0, width: 10, height: 10 },
93
+ style: { position: "relative" },
94
+ });
95
+ appendChild(root, relativeNode);
96
+ appendChild(root, staticNode);
97
+ finalizeTree(root);
98
+ expect(getChildrenInHitTestOrder(root).map((n) => n.name)).toEqual([
99
+ "static",
100
+ "relative",
101
+ ]);
102
+ });
103
+ });
104
+ //# sourceMappingURL=z-index.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"z-index.test.js","sourceRoot":"","sources":["../../../../src/react-native/__tests__/z-index.test.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,10 @@
1
1
  import DebuggingOverlayRegistry from "react-native/Libraries/Debugging/DebuggingOverlayRegistry";
2
- import { getMemoizedProps, hasFiberNodeInInternalInstanceHandle } from "./fiber";
2
+ import { getMemoizedProps, getNormalizedStyle, hasFiberNodeInInternalInstanceHandle, } from "./fiber";
3
3
  import { getPointerEventsMode, isNodeDisplayed } from "./pointer-events";
4
4
  import { getChildrenInHitTestOrder } from "./z-index";
5
5
  const key = Object.getOwnPropertyNames(DebuggingOverlayRegistry).find((key) => key.endsWith("findLowestParentFromRegistryForInstance"));
6
6
  const findLowestParentFromRegistryForInstance = DebuggingOverlayRegistry[key].bind(DebuggingOverlayRegistry);
7
7
  const RULE_REJECT = 1 << 0;
8
- const RULE_DISABLE_SELF_HIT = 1 << 1;
9
- const RULE_DISABLE_CHILD_TRAVERSAL = 1 << 2;
10
- const RULE_STOP_HIT_RULES = 1 << 3;
11
8
  const getRootNode = (anchorRef) => {
12
9
  const anchor = anchorRef.current;
13
10
  return anchor?.ownerDocument?.documentElement ?? null;
@@ -21,7 +18,7 @@ const hasPointInBounds = (rectX, rectY, rectWidth, rectHeight, x, y) => {
21
18
  if (rectWidth <= 0 || rectHeight <= 0) {
22
19
  return false;
23
20
  }
24
- return x >= rectX && x <= rectX + rectWidth && y >= rectY && y <= rectY + rectHeight;
21
+ return x >= rectX && x < rectX + rectWidth && y >= rectY && y < rectY + rectHeight;
25
22
  };
26
23
  const getElementHighlightRect = (element, rootViewInstance) => {
27
24
  const { x, y, width, height } = element.getBoundingClientRect();
@@ -100,34 +97,32 @@ const rnsVisibilityRule = (node) => {
100
97
  }
101
98
  return 0;
102
99
  };
103
- const boundsRule = (_node, rectX, rectY, rectWidth, rectHeight, x, y) => {
104
- if (!hasPointInBounds(rectX, rectY, rectWidth, rectHeight, x, y)) {
105
- return RULE_DISABLE_SELF_HIT | RULE_STOP_HIT_RULES;
106
- }
107
- return 0;
108
- };
109
- const interactivityRule = (node, _rectX, _rectY, _rectWidth, _rectHeight, _x, _y, flags) => {
110
- if ((flags & RULE_STOP_HIT_RULES) !== 0) {
111
- return 0;
112
- }
100
+ const getHitTargetCapabilities = (node) => {
113
101
  if (!isNodeDisplayed(node)) {
114
- return RULE_REJECT;
102
+ return null;
115
103
  }
116
104
  const pointerEvents = getPointerEventsMode(node);
117
105
  if (pointerEvents === "none") {
118
- return RULE_REJECT;
106
+ return null;
119
107
  }
120
108
  const hasFiberNode = hasFiberNodeInInternalInstanceHandle(node);
121
- if (!hasFiberNode) {
122
- return RULE_DISABLE_SELF_HIT;
123
- }
124
- if (pointerEvents === "box-only") {
125
- return RULE_DISABLE_CHILD_TRAVERSAL;
126
- }
127
- if (pointerEvents === "box-none") {
128
- return RULE_DISABLE_SELF_HIT;
109
+ const canBeTouchTarget = hasFiberNode && (pointerEvents === "auto" || pointerEvents === "box-only");
110
+ const canChildrenBeTouchTarget = pointerEvents === "auto" || pointerEvents === "box-none";
111
+ if (!canBeTouchTarget && !canChildrenBeTouchTarget) {
112
+ return null;
129
113
  }
130
- return 0;
114
+ return {
115
+ canBeTouchTarget,
116
+ canChildrenBeTouchTarget,
117
+ };
118
+ };
119
+ const shouldClipOverflow = (node) => {
120
+ const style = getNormalizedStyle(node);
121
+ const overflow = style?.overflow;
122
+ // Fabric uses layout overflow insets in hit testing. Those insets are not exposed
123
+ // in this DOM traversal API, so we approximate by clipping when explicit overflow
124
+ // behavior is hidden/scroll and otherwise allow overflow hits.
125
+ return overflow === "hidden" || overflow === "scroll";
131
126
  };
132
127
  const safeAreaStateRule = (node, rectHeight, runtime, state) => {
133
128
  if (node.tagName !== "RN:RNSSafeAreaView") {
@@ -151,7 +146,6 @@ const modalStateRule = (node, _rectHeight, _runtime, state) => {
151
146
  }
152
147
  };
153
148
  const NODE_RULES = [skipRule, rnsVisibilityRule];
154
- const HIT_RULES = [boundsRule, interactivityRule];
155
149
  const STATE_RULES = [safeAreaStateRule, modalStateRule];
156
150
  const applyNodeRules = (node, runtime) => {
157
151
  let flags = 0;
@@ -163,16 +157,6 @@ const applyNodeRules = (node, runtime) => {
163
157
  }
164
158
  return flags;
165
159
  };
166
- const applyHitRules = (node, rectX, rectY, rectWidth, rectHeight, x, y) => {
167
- let flags = 0;
168
- for (let i = 0; i < HIT_RULES.length; i++) {
169
- flags |= HIT_RULES[i](node, rectX, rectY, rectWidth, rectHeight, x, y, flags);
170
- if ((flags & RULE_REJECT) !== 0 || (flags & RULE_STOP_HIT_RULES) !== 0) {
171
- break;
172
- }
173
- }
174
- return flags;
175
- };
176
160
  const applyStateRules = (node, rectHeight, runtime, state) => {
177
161
  for (let i = 0; i < STATE_RULES.length; i++) {
178
162
  STATE_RULES[i](node, rectHeight, runtime, state);
@@ -184,17 +168,28 @@ const findHitTargetFromNode = (node, runtime, state, x, y) => {
184
168
  const rectY = baseRect.y + state.yOffset;
185
169
  const rectWidth = baseRect.width;
186
170
  const rectHeight = baseRect.height;
187
- let flags = applyNodeRules(node, runtime);
188
- if ((flags & RULE_REJECT) !== 0) {
171
+ const nodeFlags = applyNodeRules(node, runtime);
172
+ if ((nodeFlags & RULE_REJECT) !== 0) {
173
+ return null;
174
+ }
175
+ const capabilities = getHitTargetCapabilities(node);
176
+ if (!capabilities) {
189
177
  return null;
190
178
  }
191
- flags |= applyHitRules(node, rectX, rectY, rectWidth, rectHeight, x, y);
192
- if ((flags & RULE_REJECT) !== 0) {
179
+ const isPointInside = hasPointInBounds(rectX, rectY, rectWidth, rectHeight, x, y);
180
+ if (isPointInside && !capabilities.canChildrenBeTouchTarget) {
181
+ if (!capabilities.canBeTouchTarget) {
182
+ return null;
183
+ }
184
+ return {
185
+ node,
186
+ rect: { x: rectX, y: rectY, width: rectWidth, height: rectHeight },
187
+ };
188
+ }
189
+ if (!isPointInside && shouldClipOverflow(node)) {
193
190
  return null;
194
191
  }
195
- const allowSelfHit = (flags & RULE_DISABLE_SELF_HIT) === 0;
196
- const allowChildTraversal = (flags & RULE_DISABLE_CHILD_TRAVERSAL) === 0;
197
- if (allowChildTraversal) {
192
+ if (capabilities.canChildrenBeTouchTarget) {
198
193
  const previousYOffset = state.yOffset;
199
194
  runtime.ancestorChain.push(node);
200
195
  applyStateRules(node, rectHeight, runtime, state);
@@ -210,7 +205,7 @@ const findHitTargetFromNode = (node, runtime, state, x, y) => {
210
205
  runtime.ancestorChain.pop();
211
206
  state.yOffset = previousYOffset;
212
207
  }
213
- if (!allowSelfHit) {
208
+ if (!isPointInside || !capabilities.canBeTouchTarget) {
214
209
  return null;
215
210
  }
216
211
  return {