react-native-grab 1.0.0 → 1.1.1

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 (83) hide show
  1. package/README.md +8 -0
  2. package/dist/cjs/react-native/__tests__/grab-context-description.test.js +81 -0
  3. package/dist/cjs/react-native/__tests__/grab-context-description.test.js.map +1 -1
  4. package/dist/cjs/react-native/containers.js +107 -25
  5. package/dist/cjs/react-native/containers.js.map +1 -1
  6. package/dist/cjs/react-native/context-menu.js +229 -0
  7. package/dist/cjs/react-native/context-menu.js.map +1 -0
  8. package/dist/cjs/react-native/description.js +31 -4
  9. package/dist/cjs/react-native/description.js.map +1 -1
  10. package/dist/cjs/react-native/focus-effect.js +38 -0
  11. package/dist/cjs/react-native/focus-effect.js.map +1 -0
  12. package/dist/cjs/react-native/grab-colors.js +7 -0
  13. package/dist/cjs/react-native/grab-colors.js.map +1 -0
  14. package/dist/cjs/react-native/grab-control-bar.js +105 -0
  15. package/dist/cjs/react-native/grab-control-bar.js.map +1 -0
  16. package/dist/cjs/react-native/grab-controller.js +109 -7
  17. package/dist/cjs/react-native/grab-controller.js.map +1 -1
  18. package/dist/cjs/react-native/grab-overlay.js +216 -51
  19. package/dist/cjs/react-native/grab-overlay.js.map +1 -1
  20. package/dist/cjs/react-native/grab-root-controls.js +89 -0
  21. package/dist/cjs/react-native/grab-root-controls.js.map +1 -0
  22. package/dist/cjs/react-native/grab-root.js +8 -2
  23. package/dist/cjs/react-native/grab-root.js.map +1 -1
  24. package/dist/cjs/react-native/grab-screen.js +20 -19
  25. package/dist/cjs/react-native/grab-screen.js.map +1 -1
  26. package/dist/cjs/react-native/index.js +4 -1
  27. package/dist/cjs/react-native/index.js.map +1 -1
  28. package/dist/cjs/react-native/open.js +21 -0
  29. package/dist/cjs/react-native/open.js.map +1 -0
  30. package/dist/esm/react-native/__tests__/grab-context-description.test.js +83 -2
  31. package/dist/esm/react-native/__tests__/grab-context-description.test.js.map +1 -1
  32. package/dist/esm/react-native/containers.js +95 -20
  33. package/dist/esm/react-native/containers.js.map +1 -1
  34. package/dist/esm/react-native/context-menu.js +225 -0
  35. package/dist/esm/react-native/context-menu.js.map +1 -0
  36. package/dist/esm/react-native/description.js +28 -3
  37. package/dist/esm/react-native/description.js.map +1 -1
  38. package/dist/esm/react-native/focus-effect.js +33 -0
  39. package/dist/esm/react-native/focus-effect.js.map +1 -0
  40. package/dist/esm/react-native/grab-colors.js +4 -0
  41. package/dist/esm/react-native/grab-colors.js.map +1 -0
  42. package/dist/esm/react-native/grab-control-bar.js +101 -0
  43. package/dist/esm/react-native/grab-control-bar.js.map +1 -0
  44. package/dist/esm/react-native/grab-controller.js +100 -5
  45. package/dist/esm/react-native/grab-controller.js.map +1 -1
  46. package/dist/esm/react-native/grab-overlay.js +220 -55
  47. package/dist/esm/react-native/grab-overlay.js.map +1 -1
  48. package/dist/esm/react-native/grab-root-controls.js +85 -0
  49. package/dist/esm/react-native/grab-root-controls.js.map +1 -0
  50. package/dist/esm/react-native/grab-root.js +11 -5
  51. package/dist/esm/react-native/grab-root.js.map +1 -1
  52. package/dist/esm/react-native/grab-screen.js +23 -22
  53. package/dist/esm/react-native/grab-screen.js.map +1 -1
  54. package/dist/esm/react-native/index.js +3 -0
  55. package/dist/esm/react-native/index.js.map +1 -1
  56. package/dist/esm/react-native/open.js +14 -0
  57. package/dist/esm/react-native/open.js.map +1 -0
  58. package/dist/types/react-native/containers.d.ts +23 -4
  59. package/dist/types/react-native/containers.d.ts.map +1 -1
  60. package/dist/types/react-native/context-menu.d.ts +43 -0
  61. package/dist/types/react-native/context-menu.d.ts.map +1 -0
  62. package/dist/types/react-native/description.d.ts +5 -0
  63. package/dist/types/react-native/description.d.ts.map +1 -1
  64. package/dist/types/react-native/focus-effect.d.ts +3 -0
  65. package/dist/types/react-native/focus-effect.d.ts.map +1 -0
  66. package/dist/types/react-native/grab-colors.d.ts +4 -0
  67. package/dist/types/react-native/grab-colors.d.ts.map +1 -0
  68. package/dist/types/react-native/grab-control-bar.d.ts +13 -0
  69. package/dist/types/react-native/grab-control-bar.d.ts.map +1 -0
  70. package/dist/types/react-native/grab-controller.d.ts +18 -2
  71. package/dist/types/react-native/grab-controller.d.ts.map +1 -1
  72. package/dist/types/react-native/grab-overlay.d.ts +6 -1
  73. package/dist/types/react-native/grab-overlay.d.ts.map +1 -1
  74. package/dist/types/react-native/grab-root-controls.d.ts +2 -0
  75. package/dist/types/react-native/grab-root-controls.d.ts.map +1 -0
  76. package/dist/types/react-native/grab-root.d.ts.map +1 -1
  77. package/dist/types/react-native/grab-screen.d.ts +4 -2
  78. package/dist/types/react-native/grab-screen.d.ts.map +1 -1
  79. package/dist/types/react-native/index.d.ts +1 -0
  80. package/dist/types/react-native/index.d.ts.map +1 -1
  81. package/dist/types/react-native/open.d.ts +7 -0
  82. package/dist/types/react-native/open.d.ts.map +1 -0
  83. package/package.json +1 -1
package/README.md CHANGED
@@ -74,6 +74,14 @@ export default function AppLayout() {
74
74
  - `ReactNativeGrabScreen`: When using native navigators (native stack, native tabs), wrap **each screen** with this component for accurate selection.
75
75
  - `ReactNativeGrabContextProvider`: Adds custom metadata to grabbed elements. Nested providers are shallow-merged and child keys override parent keys. This provider is a no-op in production builds.
76
76
  - `enableGrabbing()`: Programmatically enables grabbing flow.
77
+ - `setFocusEffect(impl)`: Overrides the hook used by `ReactNativeGrabScreen` to detect when a screen is focused. By default the library auto-detects `useFocusEffect` from `expo-router` or `@react-navigation/native`. Call `setFocusEffect` once at app startup when neither package is present (e.g. a custom router) or when you want explicit control over which implementation is used.
78
+
79
+ ```ts
80
+ import { setFocusEffect } from "react-native-grab";
81
+ import { useFocusEffect } from "my-custom-router";
82
+
83
+ setFocusEffect(useFocusEffect);
84
+ ```
77
85
 
78
86
  When grab context is available for a selected element, copied output includes an additional `Context:` JSON block appended after the existing element preview and stack trace lines.
79
87
 
@@ -6,6 +6,8 @@ const grab_context_1 = require("../grab-context");
6
6
  vitest_1.vi.mock("../get-rendered-by", () => ({
7
7
  getRenderedBy: vitest_1.vi.fn(async () => []),
8
8
  }));
9
+ const get_rendered_by_1 = require("../get-rendered-by");
10
+ const mockedGetRenderedBy = vitest_1.vi.mocked(get_rendered_by_1.getRenderedBy);
9
11
  const createHostFiber = (props, parent = null) => ({
10
12
  type: "Text",
11
13
  memoizedProps: props,
@@ -22,6 +24,74 @@ const createContextProviderFiber = (value, parent = null) => ({
22
24
  _debugStack: new Error(),
23
25
  _debugOwner: null,
24
26
  });
27
+ const frame = (name) => ({
28
+ name,
29
+ file: null,
30
+ line: null,
31
+ column: null,
32
+ collapse: false,
33
+ });
34
+ (0, vitest_1.describe)("isHostLikeComponentName", () => {
35
+ (0, vitest_1.it)("treats View and Text as host-like", () => {
36
+ for (const name of description_1.GRAB_HOST_LIKE_COMPONENT_NAMES) {
37
+ (0, vitest_1.expect)((0, description_1.isHostLikeComponentName)(name)).toBe(true);
38
+ }
39
+ (0, vitest_1.expect)((0, description_1.isHostLikeComponentName)("InstallTabs")).toBe(false);
40
+ });
41
+ (0, vitest_1.it)("trims names before matching", () => {
42
+ (0, vitest_1.expect)((0, description_1.isHostLikeComponentName)(" Text ")).toBe(true);
43
+ });
44
+ });
45
+ (0, vitest_1.describe)("getGrabSelectionTitle", () => {
46
+ (0, vitest_1.it)("skips host-like owners to show Text (in InstallTabs)", () => {
47
+ const fiber = createHostFiber({ children: "x" });
48
+ (0, vitest_1.expect)((0, description_1.getGrabSelectionTitle)(fiber, [frame("Text"), frame("InstallTabs")])).toBe("Text (in InstallTabs)");
49
+ });
50
+ (0, vitest_1.it)("skips multiple host-like owners", () => {
51
+ const viewFiber = {
52
+ type: "View",
53
+ memoizedProps: {},
54
+ return: null,
55
+ stateNode: null,
56
+ _debugStack: new Error(),
57
+ _debugOwner: null,
58
+ };
59
+ (0, vitest_1.expect)((0, description_1.getGrabSelectionTitle)(viewFiber, [frame("View"), frame("Text"), frame("Screen")])).toBe("View (in Screen)");
60
+ });
61
+ (0, vitest_1.it)("returns host only when every owner is host-like", () => {
62
+ const viewFiber = {
63
+ type: "View",
64
+ memoizedProps: {},
65
+ return: null,
66
+ stateNode: null,
67
+ _debugStack: new Error(),
68
+ _debugOwner: null,
69
+ };
70
+ (0, vitest_1.expect)((0, description_1.getGrabSelectionTitle)(viewFiber, [frame("View"), frame("Text")])).toBe("View");
71
+ });
72
+ (0, vitest_1.it)("returns Selected element when host is unknown", () => {
73
+ const fiber = {
74
+ type: () => null,
75
+ memoizedProps: {},
76
+ return: null,
77
+ stateNode: null,
78
+ _debugStack: new Error(),
79
+ _debugOwner: null,
80
+ };
81
+ (0, vitest_1.expect)((0, description_1.getGrabSelectionTitle)(fiber, [])).toBe("Selected element");
82
+ });
83
+ (0, vitest_1.it)("uses host-like name from renderedBy when the fiber has no string host", () => {
84
+ const fiber = {
85
+ type: () => null,
86
+ memoizedProps: {},
87
+ return: null,
88
+ stateNode: null,
89
+ _debugStack: new Error(),
90
+ _debugOwner: null,
91
+ };
92
+ (0, vitest_1.expect)((0, description_1.getGrabSelectionTitle)(fiber, [frame("Text"), frame("InstallTabs")])).toBe("Text (in InstallTabs)");
93
+ });
94
+ });
25
95
  (0, vitest_1.describe)("composeGrabContextValue", () => {
26
96
  (0, vitest_1.it)("returns shallow copy when parent context does not exist", () => {
27
97
  const result = (0, grab_context_1.composeGrabContextValue)(null, { screen: "home", attempt: 1 });
@@ -38,6 +108,10 @@ const createContextProviderFiber = (value, parent = null) => ({
38
108
  });
39
109
  });
40
110
  (0, vitest_1.describe)("getDescription with grab context", () => {
111
+ (0, vitest_1.beforeEach)(() => {
112
+ mockedGetRenderedBy.mockReset();
113
+ mockedGetRenderedBy.mockResolvedValue([]);
114
+ });
41
115
  (0, vitest_1.it)("keeps current output format when no context provider is in ancestors", async () => {
42
116
  const selectedFiber = createHostFiber({ children: "Hello" });
43
117
  const description = await (0, description_1.getDescription)(selectedFiber);
@@ -45,6 +119,13 @@ const createContextProviderFiber = (value, parent = null) => ({
45
119
  (0, vitest_1.expect)(description).toContain("Hello");
46
120
  (0, vitest_1.expect)(description).not.toContain("Context:");
47
121
  });
122
+ (0, vitest_1.it)("uses first non-host-like renderedBy name for the preview tag", async () => {
123
+ mockedGetRenderedBy.mockResolvedValue([frame("Text"), frame("InstallTabs")]);
124
+ const selectedFiber = createHostFiber({ children: "Hello" });
125
+ const description = await (0, description_1.getDescription)(selectedFiber);
126
+ (0, vitest_1.expect)(description.startsWith("<InstallTabs")).toBe(true);
127
+ (0, vitest_1.expect)(description).toContain("Hello");
128
+ });
48
129
  (0, vitest_1.it)("appends Context block from nearest provider value", async () => {
49
130
  const parentProvider = createContextProviderFiber({ screen: "home", locale: "en" });
50
131
  const childProvider = createContextProviderFiber({ locale: "pl", section: "cta" }, parentProvider);
@@ -1 +1 @@
1
- {"version":3,"file":"grab-context-description.test.js","sourceRoot":"","sources":["../../../../src/react-native/__tests__/grab-context-description.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"grab-context-description.test.js","sourceRoot":"","sources":["../../../../src/react-native/__tests__/grab-context-description.test.ts"],"names":[],"mappings":"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"}
@@ -1,41 +1,123 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFocusedScreenShadowNode = exports.getAppRootShadowNode = exports.setAppRootRef = exports.setFocusedScreenRef = void 0;
3
+ exports.useSelectionOwnersStore = exports.useIsResolvedGrabSelectionOwner = exports.useResolvedGrabSelectionOwnerId = exports.getResolvedGrabSelectionOwnerId = exports.getResolvedGrabSelectionOwner = exports.getGrabSelectionOwner = exports.clearGrabSelectionOwnerFocus = exports.setGrabSelectionOwnerFocused = exports.unregisterGrabSelectionOwner = exports.registerGrabSelectionOwner = exports.createGrabSelectionOwnerId = void 0;
4
+ const react_1 = require("react");
4
5
  const react_native_1 = require("react-native");
5
6
  const fabric_1 = require("./fabric");
6
- let focusedScreenShadowNode = null;
7
- let appRootShadowNode = null;
8
- const setFocusedScreenRef = (ref) => {
9
- // @ts-expect-error - findNodeHandle is not typed correctly
10
- const nativeTag = (0, react_native_1.findNodeHandle)(ref);
11
- if (!nativeTag) {
12
- throw new Error("Failed to find native tag for focused screen");
7
+ let ownerIdCounter = 0;
8
+ let registrationOrder = 0;
9
+ let focusedScreenOwnerId = null;
10
+ const owners = new Map();
11
+ const listeners = new Set();
12
+ const notify = () => {
13
+ for (const listener of listeners) {
14
+ listener();
13
15
  }
14
- focusedScreenShadowNode = (0, fabric_1.getFabricUIManager)().findShadowNodeByTag_DEPRECATED(nativeTag);
15
16
  };
16
- exports.setFocusedScreenRef = setFocusedScreenRef;
17
- const setAppRootRef = (ref) => {
17
+ const subscribe = (listener) => {
18
+ listeners.add(listener);
19
+ return () => {
20
+ listeners.delete(listener);
21
+ };
22
+ };
23
+ const getSnapshot = () => ({
24
+ owners: new Map(owners),
25
+ focusedScreenOwnerId,
26
+ });
27
+ const getOwnerShadowNode = (ref, errorMessage) => {
18
28
  // @ts-expect-error - findNodeHandle is not typed correctly
19
29
  const nativeTag = (0, react_native_1.findNodeHandle)(ref);
20
30
  if (!nativeTag) {
21
- throw new Error("Failed to find native tag for app root");
31
+ throw new Error(errorMessage);
22
32
  }
23
- appRootShadowNode = (0, fabric_1.getFabricUIManager)().findShadowNodeByTag_DEPRECATED(nativeTag);
33
+ return (0, fabric_1.getFabricUIManager)().findShadowNodeByTag_DEPRECATED(nativeTag);
34
+ };
35
+ const getFallbackRootOwner = () => {
36
+ const rootOwners = Array.from(owners.values()).filter((owner) => owner.kind === "root");
37
+ rootOwners.sort((left, right) => right.registrationOrder - left.registrationOrder);
38
+ return rootOwners[0] ?? null;
24
39
  };
25
- exports.setAppRootRef = setAppRootRef;
26
- const getAppRootShadowNode = () => {
27
- if (!appRootShadowNode) {
28
- throw new Error("You seem to forgot to wrap your app root with ReactNativeGrabRoot.");
40
+ const createGrabSelectionOwnerId = (kind) => {
41
+ ownerIdCounter += 1;
42
+ return `react-native-grab-${kind}-${ownerIdCounter}`;
43
+ };
44
+ exports.createGrabSelectionOwnerId = createGrabSelectionOwnerId;
45
+ const registerGrabSelectionOwner = (id, kind, ref) => {
46
+ const shadowNode = getOwnerShadowNode(ref, kind === "root"
47
+ ? "Failed to find native tag for app root"
48
+ : "Failed to find native tag for screen");
49
+ registrationOrder += 1;
50
+ owners.set(id, {
51
+ id,
52
+ kind,
53
+ shadowNode,
54
+ registrationOrder,
55
+ });
56
+ notify();
57
+ };
58
+ exports.registerGrabSelectionOwner = registerGrabSelectionOwner;
59
+ const unregisterGrabSelectionOwner = (id) => {
60
+ const removedOwner = owners.get(id);
61
+ if (!removedOwner) {
62
+ return;
63
+ }
64
+ owners.delete(id);
65
+ if (focusedScreenOwnerId === id) {
66
+ focusedScreenOwnerId = null;
29
67
  }
30
- return appRootShadowNode;
68
+ notify();
31
69
  };
32
- exports.getAppRootShadowNode = getAppRootShadowNode;
33
- const getFocusedScreenShadowNode = () => {
34
- if (!focusedScreenShadowNode) {
35
- // No native screens, so there will be only the app root.
36
- return (0, exports.getAppRootShadowNode)();
70
+ exports.unregisterGrabSelectionOwner = unregisterGrabSelectionOwner;
71
+ const setGrabSelectionOwnerFocused = (id, isFocused) => {
72
+ const owner = owners.get(id);
73
+ if (!owner || owner.kind !== "screen") {
74
+ return;
75
+ }
76
+ if (isFocused) {
77
+ focusedScreenOwnerId = id;
78
+ }
79
+ else if (focusedScreenOwnerId === id) {
80
+ focusedScreenOwnerId = null;
37
81
  }
38
- return focusedScreenShadowNode;
82
+ notify();
83
+ };
84
+ exports.setGrabSelectionOwnerFocused = setGrabSelectionOwnerFocused;
85
+ const clearGrabSelectionOwnerFocus = (id) => {
86
+ if (focusedScreenOwnerId !== id) {
87
+ return;
88
+ }
89
+ focusedScreenOwnerId = null;
90
+ notify();
91
+ };
92
+ exports.clearGrabSelectionOwnerFocus = clearGrabSelectionOwnerFocus;
93
+ const getGrabSelectionOwner = (id) => {
94
+ return owners.get(id) ?? null;
95
+ };
96
+ exports.getGrabSelectionOwner = getGrabSelectionOwner;
97
+ const getResolvedGrabSelectionOwner = () => {
98
+ if (focusedScreenOwnerId) {
99
+ const focusedOwner = owners.get(focusedScreenOwnerId);
100
+ if (focusedOwner) {
101
+ return focusedOwner;
102
+ }
103
+ }
104
+ return getFallbackRootOwner();
105
+ };
106
+ exports.getResolvedGrabSelectionOwner = getResolvedGrabSelectionOwner;
107
+ const getResolvedGrabSelectionOwnerId = () => {
108
+ return (0, exports.getResolvedGrabSelectionOwner)()?.id ?? null;
109
+ };
110
+ exports.getResolvedGrabSelectionOwnerId = getResolvedGrabSelectionOwnerId;
111
+ const useResolvedGrabSelectionOwnerId = () => {
112
+ return (0, react_1.useSyncExternalStore)(subscribe, () => (0, exports.getResolvedGrabSelectionOwnerId)(), () => null);
113
+ };
114
+ exports.useResolvedGrabSelectionOwnerId = useResolvedGrabSelectionOwnerId;
115
+ const useIsResolvedGrabSelectionOwner = (id) => {
116
+ return (0, react_1.useSyncExternalStore)(subscribe, () => (0, exports.getResolvedGrabSelectionOwnerId)() === id, () => false);
117
+ };
118
+ exports.useIsResolvedGrabSelectionOwner = useIsResolvedGrabSelectionOwner;
119
+ const useSelectionOwnersStore = () => {
120
+ return (0, react_1.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
39
121
  };
40
- exports.getFocusedScreenShadowNode = getFocusedScreenShadowNode;
122
+ exports.useSelectionOwnersStore = useSelectionOwnersStore;
41
123
  //# sourceMappingURL=containers.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"containers.js","sourceRoot":"","sources":["../../../src/react-native/containers.ts"],"names":[],"mappings":";;;AAAA,+CAAuE;AAEvE,qCAA8C;AAE9C,IAAI,uBAAuB,GAAiC,IAAI,CAAC;AACjE,IAAI,iBAAiB,GAAiC,IAAI,CAAC;AAEpD,MAAM,mBAAmB,GAAG,CAAC,GAAuB,EAAE,EAAE;IAC7D,2DAA2D;IAC3D,MAAM,SAAS,GAAG,IAAA,6BAAc,EAAC,GAAG,CAAC,CAAC;IAEtC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,uBAAuB,GAAG,IAAA,2BAAkB,GAAE,CAAC,8BAA8B,CAAC,SAAS,CAAC,CAAC;AAC3F,CAAC,CAAC;AATW,QAAA,mBAAmB,uBAS9B;AAEK,MAAM,aAAa,GAAG,CAAC,GAAuB,EAAE,EAAE;IACvD,2DAA2D;IAC3D,MAAM,SAAS,GAAG,IAAA,6BAAc,EAAC,GAAG,CAAC,CAAC;IAEtC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,iBAAiB,GAAG,IAAA,2BAAkB,GAAE,CAAC,8BAA8B,CAAC,SAAS,CAAC,CAAC;AACrF,CAAC,CAAC;AATW,QAAA,aAAa,iBASxB;AAEK,MAAM,oBAAoB,GAAG,GAA0B,EAAE;IAC9D,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACxF,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC,CAAC;AANW,QAAA,oBAAoB,wBAM/B;AACK,MAAM,0BAA0B,GAAG,GAAG,EAAE;IAC7C,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC7B,yDAAyD;QACzD,OAAO,IAAA,4BAAoB,GAAE,CAAC;IAChC,CAAC;IAED,OAAO,uBAAuB,CAAC;AACjC,CAAC,CAAC;AAPW,QAAA,0BAA0B,8BAOrC"}
1
+ {"version":3,"file":"containers.js","sourceRoot":"","sources":["../../../src/react-native/containers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ContextMenu = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const react_native_1 = require("react-native");
7
+ const SCREEN_EDGE_MARGIN = 8;
8
+ const ContextMenuContext = (0, react_1.createContext)(null);
9
+ const getAlignedLeft = (anchorX, menuWidth, horizontalAlignment) => {
10
+ switch (horizontalAlignment) {
11
+ case "left":
12
+ return anchorX;
13
+ case "right":
14
+ return anchorX - menuWidth;
15
+ case "center":
16
+ default:
17
+ return anchorX - menuWidth / 2;
18
+ }
19
+ };
20
+ const getAlignedTop = (anchorY, menuHeight, verticalAlignment) => {
21
+ switch (verticalAlignment) {
22
+ case "center":
23
+ return anchorY - menuHeight / 2;
24
+ case "bottom":
25
+ return anchorY - menuHeight;
26
+ case "top":
27
+ default:
28
+ return anchorY;
29
+ }
30
+ };
31
+ const getMenuPosition = (anchor, menuWidth, menuHeight, horizontalAlignment, verticalAlignment, offset, bounds) => {
32
+ const { width: screenWidth, height: screenHeight } = bounds ?? react_native_1.Dimensions.get("window");
33
+ const preferredLeft = getAlignedLeft(anchor.x, menuWidth, horizontalAlignment) + offset.x;
34
+ const preferredTop = getAlignedTop(anchor.y, menuHeight, verticalAlignment) + offset.y;
35
+ return {
36
+ left: Math.min(Math.max(SCREEN_EDGE_MARGIN, preferredLeft), screenWidth - menuWidth - SCREEN_EDGE_MARGIN),
37
+ top: Math.min(Math.max(SCREEN_EDGE_MARGIN, preferredTop), screenHeight - menuHeight - SCREEN_EDGE_MARGIN),
38
+ };
39
+ };
40
+ const ContextMenuItem = ({ children, destructive = false, disabled = false, onPress, }) => {
41
+ const context = (0, react_1.useContext)(ContextMenuContext);
42
+ if (!context) {
43
+ throw new Error("ContextMenu.Item must be rendered inside ContextMenu.");
44
+ }
45
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { accessibilityRole: "menuitem", disabled: disabled, onPress: () => {
46
+ context.onClose();
47
+ onPress();
48
+ }, style: ({ pressed }) => [
49
+ styles.item,
50
+ pressed && !disabled && styles.itemPressed,
51
+ disabled && styles.itemDisabled,
52
+ ], children: (0, jsx_runtime_1.jsx)(react_native_1.Text, { style: [styles.itemText, destructive && styles.destructiveText], children: children }) }));
53
+ };
54
+ const ContextMenu = ({ anchor, bounds = null, children, cutout = null, horizontalAlignment = "center", offset = { x: 0, y: 10 }, onClose, verticalAlignment = "top", visible, }) => {
55
+ const [isRendered, setIsRendered] = (0, react_1.useState)(visible);
56
+ const [menuSize, setMenuSize] = (0, react_1.useState)({ width: 0, height: 0 });
57
+ const [renderedAnchor, setRenderedAnchor] = (0, react_1.useState)(anchor);
58
+ const animation = (0, react_1.useRef)(new react_native_1.Animated.Value(visible ? 1 : 0)).current;
59
+ (0, react_1.useEffect)(() => {
60
+ if (visible) {
61
+ setIsRendered(true);
62
+ }
63
+ if (anchor) {
64
+ setRenderedAnchor(anchor);
65
+ }
66
+ react_native_1.Animated.timing(animation, {
67
+ toValue: visible ? 1 : 0,
68
+ duration: visible ? 180 : 140,
69
+ easing: visible ? react_native_1.Easing.out(react_native_1.Easing.cubic) : react_native_1.Easing.in(react_native_1.Easing.cubic),
70
+ useNativeDriver: true,
71
+ }).start(({ finished }) => {
72
+ if (finished && !visible) {
73
+ setIsRendered(false);
74
+ setRenderedAnchor(null);
75
+ }
76
+ });
77
+ }, [anchor, animation, visible]);
78
+ const handleLayout = (event) => {
79
+ const { width, height } = event.nativeEvent.layout;
80
+ if (width === menuSize.width && height === menuSize.height) {
81
+ return;
82
+ }
83
+ setMenuSize({ width, height });
84
+ };
85
+ const position = (0, react_1.useMemo)(() => {
86
+ if (!renderedAnchor) {
87
+ return { left: SCREEN_EDGE_MARGIN, top: SCREEN_EDGE_MARGIN };
88
+ }
89
+ return getMenuPosition(renderedAnchor, menuSize.width, menuSize.height, horizontalAlignment, verticalAlignment, offset, bounds);
90
+ }, [
91
+ bounds,
92
+ horizontalAlignment,
93
+ menuSize.height,
94
+ menuSize.width,
95
+ offset,
96
+ renderedAnchor,
97
+ verticalAlignment,
98
+ ]);
99
+ const renderedItems = (0, react_1.useMemo)(() => react_1.Children.toArray(children).filter((child) => (0, react_1.isValidElement)(child)), [children]);
100
+ const dismissalRegions = (0, react_1.useMemo)(() => {
101
+ const { width: screenWidth, height: screenHeight } = bounds ?? react_native_1.Dimensions.get("window");
102
+ if (!cutout) {
103
+ return [
104
+ {
105
+ key: "full",
106
+ style: react_native_1.StyleSheet.absoluteFillObject,
107
+ },
108
+ ];
109
+ }
110
+ const left = Math.max(0, cutout.x);
111
+ const top = Math.max(0, cutout.y);
112
+ const right = Math.min(screenWidth, cutout.x + cutout.width);
113
+ const bottom = Math.min(screenHeight, cutout.y + cutout.height);
114
+ return [
115
+ {
116
+ key: "top",
117
+ style: {
118
+ position: "absolute",
119
+ top: 0,
120
+ left: 0,
121
+ right: 0,
122
+ height: top,
123
+ },
124
+ },
125
+ {
126
+ key: "left",
127
+ style: {
128
+ position: "absolute",
129
+ top,
130
+ left: 0,
131
+ width: left,
132
+ height: Math.max(0, bottom - top),
133
+ },
134
+ },
135
+ {
136
+ key: "right",
137
+ style: {
138
+ position: "absolute",
139
+ top,
140
+ left: right,
141
+ right: 0,
142
+ height: Math.max(0, bottom - top),
143
+ },
144
+ },
145
+ {
146
+ key: "bottom",
147
+ style: {
148
+ position: "absolute",
149
+ top: bottom,
150
+ left: 0,
151
+ right: 0,
152
+ bottom: 0,
153
+ },
154
+ },
155
+ ];
156
+ }, [bounds, cutout]);
157
+ if (!isRendered || !renderedAnchor || renderedItems.length === 0) {
158
+ return null;
159
+ }
160
+ return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { pointerEvents: "box-none", style: styles.overlay, children: [dismissalRegions.map((region) => ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { accessibilityLabel: "Close context menu", onPress: onClose, style: region.style }, `pressable-${region.key}`))), (0, jsx_runtime_1.jsx)(ContextMenuContext.Provider, { value: { onClose }, children: (0, jsx_runtime_1.jsx)(react_native_1.Animated.View, { onLayout: handleLayout, style: [
161
+ styles.menu,
162
+ position,
163
+ {
164
+ opacity: animation,
165
+ transform: [
166
+ {
167
+ translateY: animation.interpolate({
168
+ inputRange: [0, 1],
169
+ outputRange: [-10, 0],
170
+ }),
171
+ },
172
+ {
173
+ scale: animation.interpolate({
174
+ inputRange: [0, 1],
175
+ outputRange: [0.94, 1],
176
+ }),
177
+ },
178
+ ],
179
+ },
180
+ ], children: (0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.menuContent, children: renderedItems.map((child, index) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: index > 0 ? styles.itemBorder : undefined, children: child }, index))) }) }) })] }));
181
+ };
182
+ exports.ContextMenu = ContextMenu;
183
+ exports.ContextMenu.Item = ContextMenuItem;
184
+ const styles = react_native_1.StyleSheet.create({
185
+ overlay: {
186
+ ...react_native_1.StyleSheet.absoluteFillObject,
187
+ zIndex: 10,
188
+ elevation: 10,
189
+ },
190
+ menu: {
191
+ position: "absolute",
192
+ zIndex: 11,
193
+ minWidth: 176,
194
+ borderRadius: 14,
195
+ shadowColor: "#000000",
196
+ shadowOffset: { width: 0, height: 10 },
197
+ shadowOpacity: 0.16,
198
+ shadowRadius: 24,
199
+ elevation: 10,
200
+ },
201
+ menuContent: {
202
+ borderRadius: 14,
203
+ backgroundColor: "#FFFFFF",
204
+ overflow: "hidden",
205
+ },
206
+ item: {
207
+ paddingHorizontal: 14,
208
+ paddingVertical: 12,
209
+ },
210
+ itemBorder: {
211
+ borderTopWidth: react_native_1.StyleSheet.hairlineWidth,
212
+ borderTopColor: "rgba(17, 17, 17, 0.12)",
213
+ },
214
+ itemPressed: {
215
+ backgroundColor: "rgba(17, 17, 17, 0.06)",
216
+ },
217
+ itemDisabled: {
218
+ opacity: 0.5,
219
+ },
220
+ itemText: {
221
+ color: "#111111",
222
+ fontSize: 14,
223
+ fontWeight: "500",
224
+ },
225
+ destructiveText: {
226
+ color: "#C43D2F",
227
+ },
228
+ });
229
+ //# sourceMappingURL=context-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-menu.js","sourceRoot":"","sources":["../../../src/react-native/context-menu.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getDescription = void 0;
3
+ exports.getDescription = exports.getGrabSelectionTitle = exports.isHostLikeComponentName = exports.GRAB_HOST_LIKE_COMPONENT_NAMES = void 0;
4
4
  const get_rendered_by_1 = require("./get-rendered-by");
5
5
  const grab_context_1 = require("./grab-context");
6
6
  const MAX_STACK_LINES = 6;
@@ -15,6 +15,21 @@ const PRIORITY_ATTRS = [
15
15
  "accessibilityHint",
16
16
  "accessibilityValue",
17
17
  ];
18
+ /** Owner names treated as host-like when resolving `Text (in Owner)` for the grab menu. */
19
+ exports.GRAB_HOST_LIKE_COMPONENT_NAMES = ["View", "Text"];
20
+ const HOST_LIKE_NAME_SET = new Set(exports.GRAB_HOST_LIKE_COMPONENT_NAMES);
21
+ const isHostLikeComponentName = (name) => HOST_LIKE_NAME_SET.has(name.trim());
22
+ exports.isHostLikeComponentName = isHostLikeComponentName;
23
+ const firstHostLikeRenderedByName = (renderedBy) => {
24
+ const frame = renderedBy.find((f) => (0, exports.isHostLikeComponentName)(f.name));
25
+ const trimmed = frame?.name?.trim();
26
+ return trimmed && trimmed.length > 0 ? trimmed : null;
27
+ };
28
+ const firstNonHostRenderedByName = (renderedBy) => {
29
+ const frame = renderedBy.find((f) => !(0, exports.isHostLikeComponentName)(f.name));
30
+ const trimmed = frame?.name?.trim();
31
+ return trimmed && trimmed.length > 0 ? trimmed : null;
32
+ };
18
33
  const truncate = (value, maxLength) => {
19
34
  if (value.length <= maxLength)
20
35
  return value;
@@ -109,9 +124,9 @@ const extractPriorityAttrs = (props) => {
109
124
  return pairs.length > 0 ? ` ${pairs.join(" ")}` : "";
110
125
  };
111
126
  const getPreviewComponentName = (node, renderedBy) => {
112
- const firstRenderedBy = renderedBy[0]?.name?.trim();
113
- if (firstRenderedBy)
114
- return firstRenderedBy;
127
+ const fromRenderedBy = firstNonHostRenderedByName(renderedBy);
128
+ if (fromRenderedBy)
129
+ return fromRenderedBy;
115
130
  const hostFiber = getHostFiber(node);
116
131
  return getHostComponentName(hostFiber);
117
132
  };
@@ -169,6 +184,18 @@ const buildContextBlock = (contextValue) => {
169
184
  }
170
185
  return `\n\nContext:\n${JSON.stringify(contextValue, null, 2)}`;
171
186
  };
187
+ const getGrabSelectionTitle = (node, renderedBy) => {
188
+ const fromFiber = getHostComponentName(getHostFiber(node));
189
+ const rawHostLabel = firstHostLikeRenderedByName(renderedBy) ?? (fromFiber !== "(unknown)" ? fromFiber : null);
190
+ const hostUnknown = rawHostLabel == null;
191
+ const hostLabel = hostUnknown ? "Selected element" : rawHostLabel;
192
+ const ownerName = firstNonHostRenderedByName(renderedBy);
193
+ if (ownerName && ownerName !== hostLabel) {
194
+ return `${hostLabel} (in ${ownerName})`;
195
+ }
196
+ return hostLabel;
197
+ };
198
+ exports.getGrabSelectionTitle = getGrabSelectionTitle;
172
199
  const getDescription = async (node) => {
173
200
  let renderedBy = await (0, get_rendered_by_1.getRenderedBy)(node);
174
201
  const preview = buildElementPreview(node, renderedBy);