rn-studio 0.1.0 → 0.2.0

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.
@@ -39,71 +39,42 @@ const react_native_1 = require("react-native");
39
39
  const StudioProvider_1 = require("../StudioProvider");
40
40
  const StyleEditor_1 = require("./StyleEditor");
41
41
  const ComponentTree_1 = require("./ComponentTree");
42
- // Reanimated is a declared peer dependency. We attempt to use it for
43
- // the spring-based slide, falling back to the stock Animated API so the
44
- // overlay remains functional in environments where reanimated is not
45
- // yet configured.
46
- let Reanimated = null;
47
- let useSharedValue = null;
48
- let useAnimatedStyle = null;
49
- let withSpring = null;
50
- let withTiming = null;
51
- try {
52
- // eslint-disable-next-line @typescript-eslint/no-var-requires
53
- const r = require('react-native-reanimated');
54
- Reanimated = r.default;
55
- useSharedValue = r.useSharedValue;
56
- useAnimatedStyle = r.useAnimatedStyle;
57
- withSpring = r.withSpring;
58
- withTiming = r.withTiming;
59
- }
60
- catch { }
61
- const { height: SCREEN_HEIGHT } = react_native_1.Dimensions.get('window');
62
- const PANEL_HEIGHT = SCREEN_HEIGHT * 0.6;
42
+ const SCREEN_HEIGHT = react_native_1.Dimensions.get('window').height;
43
+ const PANEL_HEIGHT = Math.round(SCREEN_HEIGHT * 0.6);
63
44
  /**
64
45
  * InspectorPanel
65
46
  *
66
47
  * Bottom sheet shown when a component is selected. Three tabs:
67
- * Styles | Tree | Props. Slides up with a spring animation.
48
+ * Styles | Tree | Props. Slides up with a spring animation powered
49
+ * by the stock `Animated` API — no reanimated dependency, so there's
50
+ * no worklets babel plugin requirement on the consumer side.
68
51
  */
69
52
  const InspectorPanel = () => {
70
53
  const { selectedComponent, clearSelection } = (0, StudioProvider_1.useStudio)();
71
54
  const [tab, setTab] = (0, react_1.useState)('styles');
55
+ const translateY = (0, react_1.useRef)(new react_native_1.Animated.Value(PANEL_HEIGHT)).current;
72
56
  const visible = !!selectedComponent;
73
- if (Reanimated && useSharedValue) {
74
- return (react_1.default.createElement(ReanimatedPanel, { visible: visible, onDismiss: clearSelection, tab: tab, setTab: setTab }));
75
- }
76
- // Fallback: render plainly when reanimated is unavailable.
77
- if (!visible)
78
- return null;
79
- return (react_1.default.createElement(react_native_1.View, { style: [styles.panel, { transform: [{ translateY: 0 }] }] },
80
- react_1.default.createElement(PanelChrome, { tab: tab, setTab: setTab, onDismiss: clearSelection }),
81
- tab === 'styles' && react_1.default.createElement(StyleEditor_1.StyleEditor, null),
82
- tab === 'tree' && react_1.default.createElement(ComponentTree_1.ComponentTree, null),
83
- tab === 'props' && react_1.default.createElement(PropsView, null)));
84
- };
85
- exports.InspectorPanel = InspectorPanel;
86
- const ReanimatedPanel = ({ visible, onDismiss, tab, setTab }) => {
87
- const translateY = useSharedValue(PANEL_HEIGHT);
88
57
  (0, react_1.useEffect)(() => {
89
- translateY.value = visible
90
- ? withSpring(0, { damping: 20, stiffness: 200 })
91
- : withTiming(PANEL_HEIGHT, { duration: 220 });
58
+ react_native_1.Animated.spring(translateY, {
59
+ toValue: visible ? 0 : PANEL_HEIGHT,
60
+ useNativeDriver: true,
61
+ damping: 20,
62
+ stiffness: 200,
63
+ mass: 1,
64
+ }).start();
92
65
  }, [visible, translateY]);
93
- const animStyle = useAnimatedStyle(() => ({
94
- transform: [{ translateY: translateY.value }],
95
- }));
96
- if (!visible)
66
+ if (!selectedComponent)
97
67
  return null;
98
- const AnimatedView = Reanimated.View;
99
68
  return (react_1.default.createElement(react_1.default.Fragment, null,
100
- react_1.default.createElement(react_native_1.TouchableOpacity, { activeOpacity: 1, onPress: onDismiss, style: styles.backdrop }),
101
- react_1.default.createElement(AnimatedView, { style: [styles.panel, animStyle] },
102
- react_1.default.createElement(PanelChrome, { tab: tab, setTab: setTab, onDismiss: onDismiss }),
103
- tab === 'styles' && react_1.default.createElement(StyleEditor_1.StyleEditor, null),
104
- tab === 'tree' && react_1.default.createElement(ComponentTree_1.ComponentTree, null),
105
- tab === 'props' && react_1.default.createElement(PropsView, null))));
69
+ react_1.default.createElement(react_native_1.TouchableOpacity, { activeOpacity: 1, onPress: clearSelection, style: styles.backdrop }),
70
+ react_1.default.createElement(react_native_1.Animated.View, { style: [styles.panel, { transform: [{ translateY }] }] },
71
+ react_1.default.createElement(PanelChrome, { tab: tab, setTab: setTab, onDismiss: clearSelection }),
72
+ react_1.default.createElement(react_native_1.View, { style: styles.tabBody },
73
+ tab === 'styles' && react_1.default.createElement(StyleEditor_1.StyleEditor, null),
74
+ tab === 'tree' && react_1.default.createElement(ComponentTree_1.ComponentTree, null),
75
+ tab === 'props' && react_1.default.createElement(PropsView, null)))));
106
76
  };
77
+ exports.InspectorPanel = InspectorPanel;
107
78
  const PanelChrome = ({ tab, setTab, onDismiss }) => {
108
79
  const { selectedComponent } = (0, StudioProvider_1.useStudio)();
109
80
  return (react_1.default.createElement(react_native_1.View, null,
@@ -118,22 +89,24 @@ const PanelChrome = ({ tab, setTab, onDismiss }) => {
118
89
  react_1.default.createElement(TabButton, { label: "Tree", active: tab === 'tree', onPress: () => setTab('tree') }),
119
90
  react_1.default.createElement(TabButton, { label: "Props", active: tab === 'props', onPress: () => setTab('props') }))));
120
91
  };
121
- const TabButton = ({ label, active, onPress, }) => (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.tab, active && styles.tabActive], onPress: onPress },
92
+ const TabButton = ({ label, active, onPress }) => (react_1.default.createElement(react_native_1.TouchableOpacity, { style: [styles.tab, active && styles.tabActive], onPress: onPress },
122
93
  react_1.default.createElement(react_native_1.Text, { style: [styles.tabText, active && styles.tabTextActive] }, label)));
123
94
  const PropsView = () => {
124
95
  const { selectedComponent } = (0, StudioProvider_1.useStudio)();
125
- if (!selectedComponent) {
126
- return (react_1.default.createElement(react_native_1.View, { style: styles.empty },
127
- react_1.default.createElement(react_native_1.Text, { style: styles.emptyText }, "No component selected")));
128
- }
129
- const entries = Object.entries(selectedComponent.props).filter(([k]) => k !== 'style' && k !== 'children' && k !== '__rnStudioSource');
96
+ if (!selectedComponent)
97
+ return null;
98
+ const entries = Object.entries(selectedComponent.props || {}).filter(([k]) => k !== 'style' &&
99
+ k !== 'children' &&
100
+ k !== '__rnStudioSource' &&
101
+ k !== '__source' &&
102
+ k !== '__self');
130
103
  if (!entries.length) {
131
104
  return (react_1.default.createElement(react_native_1.View, { style: styles.empty },
132
105
  react_1.default.createElement(react_native_1.Text, { style: styles.emptyText }, "No inspectable props")));
133
106
  }
134
- return (react_1.default.createElement(react_native_1.View, { style: { padding: 16 } }, entries.map(([k, v]) => (react_1.default.createElement(react_native_1.View, { key: k, style: styles.propRow },
107
+ return (react_1.default.createElement(react_native_1.ScrollView, { style: { flex: 1 }, contentContainerStyle: { padding: 16, paddingBottom: 40 }, showsVerticalScrollIndicator: true }, entries.map(([k, v]) => (react_1.default.createElement(react_native_1.View, { key: k, style: styles.propRow },
135
108
  react_1.default.createElement(react_native_1.Text, { style: styles.propKey }, k),
136
- react_1.default.createElement(react_native_1.Text, { style: styles.propValue, numberOfLines: 2 }, safeStringify(v)))))));
109
+ react_1.default.createElement(react_native_1.Text, { style: styles.propValue, numberOfLines: 4 }, safeStringify(v)))))));
137
110
  };
138
111
  function safeStringify(v) {
139
112
  if (v === null)
@@ -175,6 +148,7 @@ const styles = react_native_1.StyleSheet.create({
175
148
  shadowOpacity: 0.4,
176
149
  shadowRadius: 12,
177
150
  },
151
+ tabBody: { flex: 1, minHeight: 0 },
178
152
  handleWrap: { alignItems: 'center', paddingTop: 8 },
179
153
  handle: {
180
154
  width: 40,
@@ -189,36 +163,13 @@ const styles = react_native_1.StyleSheet.create({
189
163
  paddingHorizontal: 16,
190
164
  paddingVertical: 12,
191
165
  },
192
- title: {
193
- color: '#fff',
194
- fontSize: 16,
195
- fontWeight: '700',
196
- },
197
- close: {
198
- color: '#888',
199
- fontSize: 18,
200
- },
201
- tabs: {
202
- flexDirection: 'row',
203
- backgroundColor: '#1a1a1a',
204
- },
205
- tab: {
206
- flex: 1,
207
- paddingVertical: 12,
208
- alignItems: 'center',
209
- },
210
- tabActive: {
211
- borderBottomWidth: 2,
212
- borderBottomColor: '#C6F135',
213
- },
214
- tabText: {
215
- color: '#888',
216
- fontSize: 13,
217
- fontWeight: '600',
218
- },
219
- tabTextActive: {
220
- color: '#C6F135',
221
- },
166
+ title: { color: '#fff', fontSize: 16, fontWeight: '700' },
167
+ close: { color: '#888', fontSize: 18 },
168
+ tabs: { flexDirection: 'row', backgroundColor: '#1a1a1a' },
169
+ tab: { flex: 1, paddingVertical: 12, alignItems: 'center' },
170
+ tabActive: { borderBottomWidth: 2, borderBottomColor: '#7C9BFF' },
171
+ tabText: { color: '#888', fontSize: 13, fontWeight: '600' },
172
+ tabTextActive: { color: '#7C9BFF' },
222
173
  empty: { padding: 32, alignItems: 'center' },
223
174
  emptyText: { color: '#888', fontSize: 13 },
224
175
  propRow: {
@@ -226,17 +177,7 @@ const styles = react_native_1.StyleSheet.create({
226
177
  borderBottomWidth: react_native_1.StyleSheet.hairlineWidth,
227
178
  borderBottomColor: '#222',
228
179
  },
229
- propKey: {
230
- color: '#C6F135',
231
- fontSize: 12,
232
- fontFamily: 'Menlo',
233
- fontWeight: '600',
234
- },
235
- propValue: {
236
- color: '#ddd',
237
- fontSize: 12,
238
- fontFamily: 'Menlo',
239
- marginTop: 2,
240
- },
180
+ propKey: { color: '#7C9BFF', fontSize: 12, fontWeight: '600' },
181
+ propValue: { color: '#ddd', fontSize: 12, marginTop: 2 },
241
182
  });
242
183
  //# sourceMappingURL=InspectorPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InspectorPanel.js","sourceRoot":"","sources":["../../src/components/InspectorPanel.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"InspectorPanel.js","sourceRoot":"","sources":["../../src/components/InspectorPanel.tsx"],"names":[],"mappings":"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"}
@@ -3,13 +3,11 @@ import React from 'react';
3
3
  * SelectionOverlay
4
4
  *
5
5
  * Full-screen overlay that dims the app when selection mode is active
6
- * and draws a lime-green highlight box around the selected component.
7
- *
8
- * Touch resolution strategy: the overlay captures the touch, then asks
9
- * the UIManager which native view is under the touch point via
10
- * `findSubviewIn`. From that view ref we walk the fiber tree upwards
11
- * (see fiberWalker.ts) to find the nearest component with
12
- * `__rnStudioSource` metadata.
6
+ * and draws an accent-colored highlight box around the selected
7
+ * component. Touches are routed via `getInspectorDataForViewAtPoint`
8
+ * against the app root view (provided by StudioProvider via
9
+ * `appRootRef`). The nearest user-code fiber is then resolved by
10
+ * walking the fiber `.return` chain.
13
11
  */
14
12
  export declare const SelectionOverlay: React.FC;
15
13
  //# sourceMappingURL=SelectionOverlay.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SelectionOverlay.d.ts","sourceRoot":"","sources":["../../src/components/SelectionOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AAa3D;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAqHpC,CAAC"}
1
+ {"version":3,"file":"SelectionOverlay.d.ts","sourceRoot":"","sources":["../../src/components/SelectionOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAsC,MAAM,OAAO,CAAC;AA6M3D;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAmHpC,CAAC"}
@@ -37,116 +37,258 @@ exports.SelectionOverlay = void 0;
37
37
  const react_1 = __importStar(require("react"));
38
38
  const react_native_1 = require("react-native");
39
39
  const StudioProvider_1 = require("../StudioProvider");
40
- const fiberWalker_1 = require("../utils/fiberWalker");
40
+ /* eslint-disable @typescript-eslint/no-explicit-any */
41
+ // React Native's built-in inspector data API. Uses the React DevTools
42
+ // hook under the hood and works on both the Fabric and legacy
43
+ // architectures. We import it lazily so consumers that somehow run
44
+ // this file in production don't trip on the dev-only module path.
45
+ let getInspectorDataForViewAtPoint = null;
46
+ try {
47
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
48
+ const mod = require('react-native/src/private/devsupport/devmenu/elementinspector/getInspectorDataForViewAtPoint');
49
+ getInspectorDataForViewAtPoint = (mod && (mod.default || mod)) || null;
50
+ }
51
+ catch (e) {
52
+ // eslint-disable-next-line no-console
53
+ console.warn('[rn-studio] Unable to load getInspectorDataForViewAtPoint:', e && e.message);
54
+ }
55
+ function triggerHaptic(type) {
56
+ try {
57
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
58
+ const Haptic = require('react-native-haptic-feedback').default;
59
+ Haptic.trigger(type, {
60
+ enableVibrateFallback: false,
61
+ ignoreAndroidSystemSettings: false,
62
+ });
63
+ }
64
+ catch { }
65
+ }
66
+ function inferStyleType(key, value) {
67
+ if (typeof value === 'number')
68
+ return 'number';
69
+ if (typeof value === 'boolean')
70
+ return 'boolean';
71
+ if (typeof value === 'string') {
72
+ if (/color/i.test(key) ||
73
+ /^#[0-9a-f]{3,8}$/i.test(value) ||
74
+ /^rgba?\(/i.test(value) ||
75
+ /^hsla?\(/i.test(value)) {
76
+ return 'color';
77
+ }
78
+ return 'string';
79
+ }
80
+ return 'string';
81
+ }
82
+ function extractStyles(rawStyle) {
83
+ const flat = (react_native_1.StyleSheet.flatten(rawStyle) || {});
84
+ const out = [];
85
+ for (const key of Object.keys(flat)) {
86
+ const value = flat[key];
87
+ if (value == null)
88
+ continue;
89
+ if (typeof value === 'object')
90
+ continue; // skip nested (shadowOffset etc.)
91
+ out.push({ key, value, type: inferStyleType(key, value) });
92
+ }
93
+ return out;
94
+ }
95
+ /**
96
+ * Excludes known library paths so the AST engine only ever rewrites
97
+ * files in the user's project.
98
+ */
99
+ function isUserCodePath(file) {
100
+ if (!file || typeof file !== 'string')
101
+ return false;
102
+ if (file.indexOf('/node_modules/') !== -1)
103
+ return false;
104
+ if (file.indexOf('react-native/Libraries/') !== -1)
105
+ return false;
106
+ if (file.indexOf('react-native/src/') !== -1)
107
+ return false;
108
+ if (file === 'unknown' || file === '<anonymous>')
109
+ return false;
110
+ return true;
111
+ }
112
+ function sourceFromProps(p, fallbackName) {
113
+ if (!p)
114
+ return null;
115
+ if (p.__rnStudioSource && p.__rnStudioSource.file) {
116
+ return {
117
+ file: p.__rnStudioSource.file,
118
+ line: p.__rnStudioSource.line,
119
+ column: p.__rnStudioSource.column || 0,
120
+ componentName: p.__rnStudioSource.componentName || fallbackName || 'Component',
121
+ };
122
+ }
123
+ if (p.__source && p.__source.fileName) {
124
+ return {
125
+ file: p.__source.fileName,
126
+ line: p.__source.lineNumber,
127
+ column: p.__source.columnNumber || 0,
128
+ componentName: fallbackName || 'Component',
129
+ };
130
+ }
131
+ return null;
132
+ }
133
+ /**
134
+ * Walks a fiber's `.return` chain, reading each fiber's own
135
+ * memoizedProps for a source location. This is the correct strategy
136
+ * because `getInspectorDataForViewAtPoint`'s `hierarchy` items all
137
+ * share the deepest host's props, which is useless for mapping back
138
+ * to user JSX.
139
+ */
140
+ function walkFiberForUserSource(fiber) {
141
+ let current = fiber;
142
+ let libraryFallback = null;
143
+ let safety = 0;
144
+ while (current && safety < 200) {
145
+ safety++;
146
+ const p = current.memoizedProps;
147
+ if (p && typeof p === 'object') {
148
+ const src = sourceFromProps(p, (current.type && (current.type.displayName || current.type.name)) ||
149
+ null);
150
+ if (src) {
151
+ const resolved = {
152
+ source: src,
153
+ props: p,
154
+ componentName: src.componentName,
155
+ };
156
+ if (isUserCodePath(src.file))
157
+ return resolved;
158
+ if (!libraryFallback)
159
+ libraryFallback = resolved;
160
+ }
161
+ }
162
+ current = current.return;
163
+ }
164
+ return libraryFallback;
165
+ }
166
+ /**
167
+ * Resolve the nearest user-code JSX source location from the data
168
+ * returned by `getInspectorDataForViewAtPoint`.
169
+ */
170
+ function resolveSourceFromViewData(viewData) {
171
+ if (!viewData)
172
+ return null;
173
+ if (viewData.closestInstance) {
174
+ const found = walkFiberForUserSource(viewData.closestInstance);
175
+ if (found && isUserCodePath(found.source.file))
176
+ return found;
177
+ if (found) {
178
+ // eslint-disable-next-line no-console
179
+ console.warn('[rn-studio] fiber walk only found library source:', found.source.file);
180
+ }
181
+ }
182
+ const topSrc = sourceFromProps(viewData.props, null);
183
+ if (topSrc && isUserCodePath(topSrc.file)) {
184
+ return {
185
+ source: topSrc,
186
+ props: (viewData.props || {}),
187
+ componentName: topSrc.componentName,
188
+ };
189
+ }
190
+ // eslint-disable-next-line no-console
191
+ console.warn('[rn-studio] no user-code source found; closestInstance?', !!viewData.closestInstance, 'topLevelSrc=', topSrc && topSrc.file);
192
+ return null;
193
+ }
41
194
  /**
42
195
  * SelectionOverlay
43
196
  *
44
197
  * Full-screen overlay that dims the app when selection mode is active
45
- * and draws a lime-green highlight box around the selected component.
46
- *
47
- * Touch resolution strategy: the overlay captures the touch, then asks
48
- * the UIManager which native view is under the touch point via
49
- * `findSubviewIn`. From that view ref we walk the fiber tree upwards
50
- * (see fiberWalker.ts) to find the nearest component with
51
- * `__rnStudioSource` metadata.
198
+ * and draws an accent-colored highlight box around the selected
199
+ * component. Touches are routed via `getInspectorDataForViewAtPoint`
200
+ * against the app root view (provided by StudioProvider via
201
+ * `appRootRef`). The nearest user-code fiber is then resolved by
202
+ * walking the fiber `.return` chain.
52
203
  */
53
204
  const SelectionOverlay = () => {
54
205
  const { isActive, isSelecting, selectedComponent, selectComponent } = (0, StudioProvider_1.useStudio)();
55
- const rootRef = (0, react_1.useRef)(null);
56
206
  const [highlight, setHighlight] = (0, react_1.useState)(null);
57
207
  const opacity = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
58
- const borderOpacity = (0, react_1.useRef)(new react_native_1.Animated.Value(0)).current;
59
208
  (0, react_1.useEffect)(() => {
60
209
  react_native_1.Animated.timing(opacity, {
61
- toValue: isActive ? 1 : 0,
210
+ toValue: isActive ? 0.3 : 0,
62
211
  duration: 200,
63
212
  useNativeDriver: true,
64
213
  }).start();
65
214
  }, [isActive, opacity]);
66
215
  (0, react_1.useEffect)(() => {
67
- if (selectedComponent) {
68
- react_native_1.Animated.timing(borderOpacity, {
69
- toValue: 1,
70
- duration: 150,
71
- useNativeDriver: true,
72
- }).start();
73
- }
74
- else {
75
- borderOpacity.setValue(0);
76
- }
77
- }, [selectedComponent, borderOpacity]);
216
+ if (!selectedComponent)
217
+ setHighlight(null);
218
+ }, [selectedComponent]);
78
219
  const handleTouch = (evt) => {
79
220
  if (!isSelecting)
80
- return false;
221
+ return;
81
222
  const { pageX, pageY } = evt.nativeEvent;
82
- const rootHandle = (0, react_native_1.findNodeHandle)(rootRef.current);
83
- if (!rootHandle)
84
- return true;
85
- // findSubviewIn gives us the native view at a point. Then we climb
86
- // the fiber tree to locate the nearest source-annotated owner.
223
+ const appRoot = StudioProvider_1.appRootRef && StudioProvider_1.appRootRef.current;
224
+ if (!getInspectorDataForViewAtPoint || !appRoot) {
225
+ // eslint-disable-next-line no-console
226
+ console.warn('[rn-studio] inspector API or app root ref not available', {
227
+ hasAPI: !!getInspectorDataForViewAtPoint,
228
+ hasRoot: !!appRoot,
229
+ });
230
+ return;
231
+ }
87
232
  try {
88
- react_native_1.UIManager.findSubviewIn(rootHandle, [pageX, pageY, 1, 1], (_nativeX, _nativeY, _w, _h, tag) => {
89
- if (!tag)
90
- return;
91
- const fiber = (0, fiberWalker_1.fiberFromRef)({ stateNode: { _nativeTag: tag } });
92
- // Most RN versions expose the fiber via private keys on the
93
- // underlying view component instance; the walker defensively
94
- // searches for them. If no fiber is found we still draw a
95
- // placeholder highlight at the touch location.
96
- let owner = null;
97
- if (fiber)
98
- owner = (0, fiberWalker_1.findSourceOwner)(fiber);
99
- if (owner) {
100
- const node = (0, fiberWalker_1.buildComponentNode)(owner.fiber, owner.source);
101
- selectComponent(node);
233
+ getInspectorDataForViewAtPoint(appRoot, pageX, pageY, (viewData) => {
234
+ if (!viewData)
235
+ return false;
236
+ const resolved = resolveSourceFromViewData(viewData);
237
+ if (!resolved) {
238
+ if (viewData.frame) {
239
+ setHighlight({
240
+ x: viewData.frame.left,
241
+ y: viewData.frame.top,
242
+ width: viewData.frame.width,
243
+ height: viewData.frame.height,
244
+ });
245
+ }
246
+ return true;
247
+ }
248
+ const nodeStyles = extractStyles(resolved.props.style);
249
+ const node = {
250
+ id: `${resolved.source.file}:${resolved.source.line}:${resolved.source.column}`,
251
+ componentName: resolved.componentName,
252
+ source: resolved.source,
253
+ props: resolved.props,
254
+ styles: nodeStyles,
255
+ children: [],
256
+ };
257
+ if (viewData.frame) {
258
+ setHighlight({
259
+ x: viewData.frame.left,
260
+ y: viewData.frame.top,
261
+ width: viewData.frame.width,
262
+ height: viewData.frame.height,
263
+ });
102
264
  }
103
- // Draw highlight at touch point (approximate). A production
104
- // implementation would call measureInWindow on the resolved
105
- // native component for a pixel-perfect box.
106
- setHighlight({
107
- x: pageX - 30,
108
- y: pageY - 30,
109
- width: 60,
110
- height: 60,
111
- });
265
+ selectComponent(node);
266
+ triggerHaptic('impactMedium');
267
+ return true;
112
268
  });
113
269
  }
114
- catch {
115
- // UIManager.findSubviewIn is not available on every platform; in
116
- // that case we still acknowledge the touch so the user gets
117
- // feedback.
270
+ catch (err) {
271
+ // eslint-disable-next-line no-console
272
+ console.warn('[rn-studio] hit-test error:', err && err.message);
118
273
  }
119
- triggerHaptic('impactMedium');
120
- return true;
121
274
  };
122
275
  if (!isActive)
123
276
  return null;
124
- const { width, height } = react_native_1.Dimensions.get('window');
125
- return (react_1.default.createElement(react_native_1.View, { ref: rootRef, pointerEvents: isSelecting ? 'box-only' : 'none', style: react_native_1.StyleSheet.absoluteFill, onStartShouldSetResponder: () => isSelecting, onResponderGrant: handleTouch },
277
+ return (react_1.default.createElement(react_native_1.View, { pointerEvents: isSelecting ? 'box-only' : 'none', style: react_native_1.StyleSheet.absoluteFill, onStartShouldSetResponder: () => isSelecting, onResponderGrant: handleTouch },
126
278
  react_1.default.createElement(react_native_1.Animated.View, { pointerEvents: "none", style: [
127
279
  react_native_1.StyleSheet.absoluteFill,
128
- { backgroundColor: 'rgba(0,0,0,0.3)', opacity },
280
+ { backgroundColor: '#000', opacity },
129
281
  ] }),
130
- highlight && (react_1.default.createElement(react_native_1.Animated.View, { pointerEvents: "none", style: {
282
+ highlight && (react_1.default.createElement(react_native_1.View, { pointerEvents: "none", style: {
131
283
  position: 'absolute',
132
284
  left: highlight.x,
133
285
  top: highlight.y,
134
286
  width: highlight.width,
135
287
  height: highlight.height,
136
288
  borderWidth: 2,
137
- borderColor: '#C6F135',
289
+ borderColor: '#7C9BFF',
138
290
  borderRadius: 4,
139
- opacity: borderOpacity,
140
- } })),
141
- react_1.default.createElement(react_native_1.View, { pointerEvents: "none", style: { position: 'absolute', width, height } })));
291
+ } }))));
142
292
  };
143
293
  exports.SelectionOverlay = SelectionOverlay;
144
- function triggerHaptic(type) {
145
- try {
146
- // eslint-disable-next-line @typescript-eslint/no-var-requires
147
- const Haptic = require('react-native-haptic-feedback').default;
148
- Haptic.trigger(type, { enableVibrateFallback: false, ignoreAndroidSystemSettings: false });
149
- }
150
- catch { }
151
- }
152
294
  //# sourceMappingURL=SelectionOverlay.js.map