react-native-element-inspector 0.1.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.
Files changed (213) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +134 -0
  3. package/lib/ElementCycler.d.ts +14 -0
  4. package/lib/ElementCycler.d.ts.map +1 -0
  5. package/lib/ElementCycler.js +33 -0
  6. package/lib/ElementCycler.js.map +1 -0
  7. package/lib/ElementHighlighter.d.ts +21 -0
  8. package/lib/ElementHighlighter.d.ts.map +1 -0
  9. package/lib/ElementHighlighter.js +89 -0
  10. package/lib/ElementHighlighter.js.map +1 -0
  11. package/lib/ElementInspector.d.ts +12 -0
  12. package/lib/ElementInspector.d.ts.map +1 -0
  13. package/lib/ElementInspector.js +74 -0
  14. package/lib/ElementInspector.js.map +1 -0
  15. package/lib/components/Checkbox.d.ts +7 -0
  16. package/lib/components/Checkbox.d.ts.map +1 -0
  17. package/lib/components/Checkbox.js +30 -0
  18. package/lib/components/Checkbox.js.map +1 -0
  19. package/lib/components/index.d.ts +2 -0
  20. package/lib/components/index.d.ts.map +1 -0
  21. package/lib/components/index.js +2 -0
  22. package/lib/components/index.js.map +1 -0
  23. package/lib/constants/colors.d.ts +24 -0
  24. package/lib/constants/colors.d.ts.map +1 -0
  25. package/lib/constants/colors.js +18 -0
  26. package/lib/constants/colors.js.map +1 -0
  27. package/lib/constants/index.d.ts +3 -0
  28. package/lib/constants/index.d.ts.map +1 -0
  29. package/lib/constants/index.js +3 -0
  30. package/lib/constants/index.js.map +1 -0
  31. package/lib/constants/ui.d.ts +56 -0
  32. package/lib/constants/ui.d.ts.map +1 -0
  33. package/lib/constants/ui.js +46 -0
  34. package/lib/constants/ui.js.map +1 -0
  35. package/lib/fiber/FiberAdapter.d.ts +52 -0
  36. package/lib/fiber/FiberAdapter.d.ts.map +1 -0
  37. package/lib/fiber/FiberAdapter.js +112 -0
  38. package/lib/fiber/FiberAdapter.js.map +1 -0
  39. package/lib/fiber/detectVersion.d.ts +9 -0
  40. package/lib/fiber/detectVersion.d.ts.map +1 -0
  41. package/lib/fiber/detectVersion.js +17 -0
  42. package/lib/fiber/detectVersion.js.map +1 -0
  43. package/lib/fiber/index.d.ts +5 -0
  44. package/lib/fiber/index.d.ts.map +1 -0
  45. package/lib/fiber/index.js +4 -0
  46. package/lib/fiber/index.js.map +1 -0
  47. package/lib/fiber/types.d.ts +35 -0
  48. package/lib/fiber/types.d.ts.map +1 -0
  49. package/lib/fiber/types.js +3 -0
  50. package/lib/fiber/types.js.map +1 -0
  51. package/lib/floatingPanel/AddPropertyRow.d.ts +13 -0
  52. package/lib/floatingPanel/AddPropertyRow.d.ts.map +1 -0
  53. package/lib/floatingPanel/AddPropertyRow.js +61 -0
  54. package/lib/floatingPanel/AddPropertyRow.js.map +1 -0
  55. package/lib/floatingPanel/CloseButton.d.ts +7 -0
  56. package/lib/floatingPanel/CloseButton.d.ts.map +1 -0
  57. package/lib/floatingPanel/CloseButton.js +21 -0
  58. package/lib/floatingPanel/CloseButton.js.map +1 -0
  59. package/lib/floatingPanel/EditableValue.d.ts +12 -0
  60. package/lib/floatingPanel/EditableValue.d.ts.map +1 -0
  61. package/lib/floatingPanel/EditableValue.js +67 -0
  62. package/lib/floatingPanel/EditableValue.js.map +1 -0
  63. package/lib/floatingPanel/FloatingPanel.d.ts +7 -0
  64. package/lib/floatingPanel/FloatingPanel.d.ts.map +1 -0
  65. package/lib/floatingPanel/FloatingPanel.js +70 -0
  66. package/lib/floatingPanel/FloatingPanel.js.map +1 -0
  67. package/lib/floatingPanel/HandleContent.d.ts +7 -0
  68. package/lib/floatingPanel/HandleContent.d.ts.map +1 -0
  69. package/lib/floatingPanel/HandleContent.js +35 -0
  70. package/lib/floatingPanel/HandleContent.js.map +1 -0
  71. package/lib/floatingPanel/InspectorBubble.d.ts +6 -0
  72. package/lib/floatingPanel/InspectorBubble.d.ts.map +1 -0
  73. package/lib/floatingPanel/InspectorBubble.js +91 -0
  74. package/lib/floatingPanel/InspectorBubble.js.map +1 -0
  75. package/lib/floatingPanel/PanelBody.d.ts +8 -0
  76. package/lib/floatingPanel/PanelBody.d.ts.map +1 -0
  77. package/lib/floatingPanel/PanelBody.js +72 -0
  78. package/lib/floatingPanel/PanelBody.js.map +1 -0
  79. package/lib/floatingPanel/PanelFooter.d.ts +9 -0
  80. package/lib/floatingPanel/PanelFooter.d.ts.map +1 -0
  81. package/lib/floatingPanel/PanelFooter.js +21 -0
  82. package/lib/floatingPanel/PanelFooter.js.map +1 -0
  83. package/lib/floatingPanel/PanelHeader.d.ts +13 -0
  84. package/lib/floatingPanel/PanelHeader.d.ts.map +1 -0
  85. package/lib/floatingPanel/PanelHeader.js +56 -0
  86. package/lib/floatingPanel/PanelHeader.js.map +1 -0
  87. package/lib/floatingPanel/index.d.ts +12 -0
  88. package/lib/floatingPanel/index.d.ts.map +1 -0
  89. package/lib/floatingPanel/index.js +11 -0
  90. package/lib/floatingPanel/index.js.map +1 -0
  91. package/lib/floatingPanel/panelUtils.d.ts +3 -0
  92. package/lib/floatingPanel/panelUtils.d.ts.map +1 -0
  93. package/lib/floatingPanel/panelUtils.js +12 -0
  94. package/lib/floatingPanel/panelUtils.js.map +1 -0
  95. package/lib/floatingPanel/types.d.ts +23 -0
  96. package/lib/floatingPanel/types.d.ts.map +1 -0
  97. package/lib/floatingPanel/types.js +2 -0
  98. package/lib/floatingPanel/types.js.map +1 -0
  99. package/lib/hooks/index.d.ts +8 -0
  100. package/lib/hooks/index.d.ts.map +1 -0
  101. package/lib/hooks/index.js +8 -0
  102. package/lib/hooks/index.js.map +1 -0
  103. package/lib/hooks/useDebouncedCallback.d.ts +2 -0
  104. package/lib/hooks/useDebouncedCallback.d.ts.map +1 -0
  105. package/lib/hooks/useDebouncedCallback.js +12 -0
  106. package/lib/hooks/useDebouncedCallback.js.map +1 -0
  107. package/lib/hooks/useDebouncedValue.d.ts +2 -0
  108. package/lib/hooks/useDebouncedValue.d.ts.map +1 -0
  109. package/lib/hooks/useDebouncedValue.js +10 -0
  110. package/lib/hooks/useDebouncedValue.js.map +1 -0
  111. package/lib/hooks/useFloatingPanel.d.ts +14 -0
  112. package/lib/hooks/useFloatingPanel.d.ts.map +1 -0
  113. package/lib/hooks/useFloatingPanel.js +132 -0
  114. package/lib/hooks/useFloatingPanel.js.map +1 -0
  115. package/lib/hooks/useLayoutSnapshot.d.ts +14 -0
  116. package/lib/hooks/useLayoutSnapshot.d.ts.map +1 -0
  117. package/lib/hooks/useLayoutSnapshot.js +39 -0
  118. package/lib/hooks/useLayoutSnapshot.js.map +1 -0
  119. package/lib/hooks/useStyleMutation.d.ts +14 -0
  120. package/lib/hooks/useStyleMutation.d.ts.map +1 -0
  121. package/lib/hooks/useStyleMutation.js +22 -0
  122. package/lib/hooks/useStyleMutation.js.map +1 -0
  123. package/lib/hooks/useStyleOverrides.d.ts +24 -0
  124. package/lib/hooks/useStyleOverrides.d.ts.map +1 -0
  125. package/lib/hooks/useStyleOverrides.js +165 -0
  126. package/lib/hooks/useStyleOverrides.js.map +1 -0
  127. package/lib/hooks/useTapToSelect.d.ts +20 -0
  128. package/lib/hooks/useTapToSelect.d.ts.map +1 -0
  129. package/lib/hooks/useTapToSelect.js +58 -0
  130. package/lib/hooks/useTapToSelect.js.map +1 -0
  131. package/lib/index.d.ts +3 -0
  132. package/lib/index.d.ts.map +1 -0
  133. package/lib/index.js +2 -0
  134. package/lib/index.js.map +1 -0
  135. package/lib/utils/clamp.d.ts +2 -0
  136. package/lib/utils/clamp.d.ts.map +1 -0
  137. package/lib/utils/clamp.js +2 -0
  138. package/lib/utils/clamp.js.map +1 -0
  139. package/lib/utils/flattenStyles.d.ts +6 -0
  140. package/lib/utils/flattenStyles.d.ts.map +1 -0
  141. package/lib/utils/flattenStyles.js +11 -0
  142. package/lib/utils/flattenStyles.js.map +1 -0
  143. package/lib/utils/hitTest.d.ts +7 -0
  144. package/lib/utils/hitTest.d.ts.map +1 -0
  145. package/lib/utils/hitTest.js +20 -0
  146. package/lib/utils/hitTest.js.map +1 -0
  147. package/lib/utils/index.d.ts +12 -0
  148. package/lib/utils/index.d.ts.map +1 -0
  149. package/lib/utils/index.js +9 -0
  150. package/lib/utils/index.js.map +1 -0
  151. package/lib/utils/layoutSnapshot.d.ts +7 -0
  152. package/lib/utils/layoutSnapshot.d.ts.map +1 -0
  153. package/lib/utils/layoutSnapshot.js +42 -0
  154. package/lib/utils/layoutSnapshot.js.map +1 -0
  155. package/lib/utils/sourceMapping.d.ts +26 -0
  156. package/lib/utils/sourceMapping.d.ts.map +1 -0
  157. package/lib/utils/sourceMapping.js +53 -0
  158. package/lib/utils/sourceMapping.js.map +1 -0
  159. package/lib/utils/styleFormatting.d.ts +5 -0
  160. package/lib/utils/styleFormatting.d.ts.map +1 -0
  161. package/lib/utils/styleFormatting.js +38 -0
  162. package/lib/utils/styleFormatting.js.map +1 -0
  163. package/lib/utils/styleInputParsing.d.ts +5 -0
  164. package/lib/utils/styleInputParsing.d.ts.map +1 -0
  165. package/lib/utils/styleInputParsing.js +33 -0
  166. package/lib/utils/styleInputParsing.js.map +1 -0
  167. package/lib/utils/yogaLayout.d.ts +33 -0
  168. package/lib/utils/yogaLayout.d.ts.map +1 -0
  169. package/lib/utils/yogaLayout.js +33 -0
  170. package/lib/utils/yogaLayout.js.map +1 -0
  171. package/package.json +74 -0
  172. package/src/ElementCycler.tsx +64 -0
  173. package/src/ElementHighlighter.tsx +122 -0
  174. package/src/ElementInspector.tsx +119 -0
  175. package/src/components/Checkbox.tsx +41 -0
  176. package/src/components/index.ts +1 -0
  177. package/src/constants/colors.ts +18 -0
  178. package/src/constants/index.ts +9 -0
  179. package/src/constants/ui.ts +51 -0
  180. package/src/fiber/FiberAdapter.ts +153 -0
  181. package/src/fiber/detectVersion.ts +19 -0
  182. package/src/fiber/index.ts +4 -0
  183. package/src/fiber/types.ts +36 -0
  184. package/src/floatingPanel/AddPropertyRow.tsx +102 -0
  185. package/src/floatingPanel/CloseButton.tsx +34 -0
  186. package/src/floatingPanel/EditableValue.tsx +109 -0
  187. package/src/floatingPanel/FloatingPanel.tsx +114 -0
  188. package/src/floatingPanel/HandleContent.tsx +45 -0
  189. package/src/floatingPanel/InspectorBubble.tsx +121 -0
  190. package/src/floatingPanel/PanelBody.tsx +162 -0
  191. package/src/floatingPanel/PanelFooter.tsx +36 -0
  192. package/src/floatingPanel/PanelHeader.tsx +111 -0
  193. package/src/floatingPanel/index.ts +11 -0
  194. package/src/floatingPanel/panelUtils.ts +13 -0
  195. package/src/floatingPanel/types.ts +26 -0
  196. package/src/hooks/index.ts +7 -0
  197. package/src/hooks/useDebouncedCallback.ts +18 -0
  198. package/src/hooks/useDebouncedValue.ts +12 -0
  199. package/src/hooks/useFloatingPanel.ts +191 -0
  200. package/src/hooks/useLayoutSnapshot.ts +42 -0
  201. package/src/hooks/useStyleMutation.ts +31 -0
  202. package/src/hooks/useStyleOverrides.ts +176 -0
  203. package/src/hooks/useTapToSelect.ts +76 -0
  204. package/src/index.ts +2 -0
  205. package/src/utils/clamp.ts +2 -0
  206. package/src/utils/flattenStyles.ts +12 -0
  207. package/src/utils/hitTest.ts +29 -0
  208. package/src/utils/index.ts +11 -0
  209. package/src/utils/layoutSnapshot.ts +48 -0
  210. package/src/utils/sourceMapping.ts +67 -0
  211. package/src/utils/styleFormatting.ts +34 -0
  212. package/src/utils/styleInputParsing.ts +33 -0
  213. package/src/utils/yogaLayout.ts +49 -0
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Given a tap point and a layout snapshot, return all elements
3
+ * whose bounds contain the point, sorted by area (smallest first).
4
+ */
5
+ export const hitTest = (snapshot, tapX, tapY) => {
6
+ const matches = [];
7
+ for (const element of snapshot) {
8
+ const { x, y, width, height } = element;
9
+ // Skip zero-size elements
10
+ if (width === 0 || height === 0)
11
+ continue;
12
+ if (tapX >= x && tapX <= x + width && tapY >= y && tapY <= y + height) {
13
+ matches.push(element);
14
+ }
15
+ }
16
+ // Sort by area ascending — smallest (most specific) element first
17
+ matches.sort((a, b) => a.width * a.height - b.width * b.height);
18
+ return matches;
19
+ };
20
+ //# sourceMappingURL=hitTest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hitTest.js","sourceRoot":"","sources":["../../src/utils/hitTest.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CACrB,QAA2B,EAC3B,IAAY,EACZ,IAAY,EACO,EAAE;IACrB,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAExC,0BAA0B;QAC1B,IAAI,KAAK,KAAK,CAAC,IAAI,MAAM,KAAK,CAAC;YAAE,SAAS;QAE1C,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,GAAG,MAAM,EAAE,CAAC;YACtE,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,kEAAkE;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAEhE,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { clamp } from './clamp';
2
+ export type { StyleObject } from './flattenStyles';
3
+ export { flattenStyles } from './flattenStyles';
4
+ export { hitTest } from './hitTest';
5
+ export { buildLayoutSnapshot } from './layoutSnapshot';
6
+ export type { SourceLocation } from './sourceMapping';
7
+ export { formatSourceLocation, getOwnerName, getSourceLocation } from './sourceMapping';
8
+ export { formatValue, isColorProp } from './styleFormatting';
9
+ export { parseInput, toEditableString } from './styleInputParsing';
10
+ export type { BoxModel } from './yogaLayout';
11
+ export { extractBoxModel } from './yogaLayout';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { clamp } from './clamp';
2
+ export { flattenStyles } from './flattenStyles';
3
+ export { hitTest } from './hitTest';
4
+ export { buildLayoutSnapshot } from './layoutSnapshot';
5
+ export { formatSourceLocation, getOwnerName, getSourceLocation } from './sourceMapping';
6
+ export { formatValue, isColorProp } from './styleFormatting';
7
+ export { parseInput, toEditableString } from './styleInputParsing';
8
+ export { extractBoxModel } from './yogaLayout';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACxF,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEnE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { type FiberNode, type MeasuredElement } from '../fiber';
2
+ /**
3
+ * Build a layout snapshot: walk the fiber tree, measure every host fiber,
4
+ * return a flat array sorted by zIndex (desc) → depth (desc).
5
+ */
6
+ export declare const buildLayoutSnapshot: (root: FiberNode) => Promise<MeasuredElement[]>;
7
+ //# sourceMappingURL=layoutSnapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layoutSnapshot.d.ts","sourceRoot":"","sources":["../../src/utils/layoutSnapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,SAAS,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAE9E;;;GAGG;AACH,eAAO,MAAM,mBAAmB,SAAgB,SAAS,KAAG,OAAO,CAAC,eAAe,EAAE,CAyCpF,CAAC"}
@@ -0,0 +1,42 @@
1
+ import { FiberAdapter } from '../fiber';
2
+ /**
3
+ * Build a layout snapshot: walk the fiber tree, measure every host fiber,
4
+ * return a flat array sorted by zIndex (desc) → depth (desc).
5
+ */
6
+ export const buildLayoutSnapshot = async (root) => {
7
+ const hostFibers = FiberAdapter.walkHostFibers(root);
8
+ const elements = [];
9
+ // Measure all host fibers in parallel
10
+ const measurements = await Promise.allSettled(hostFibers.map(async ({ fiber, depth }) => {
11
+ const rect = await FiberAdapter.measure(fiber);
12
+ const style = FiberAdapter.getStyle(fiber);
13
+ return {
14
+ fiber,
15
+ x: rect.x,
16
+ y: rect.y,
17
+ width: rect.width,
18
+ height: rect.height,
19
+ depth,
20
+ zIndex: typeof style?.zIndex === 'number' ? style.zIndex : 0,
21
+ componentName: FiberAdapter.getComponentName(fiber),
22
+ };
23
+ }));
24
+ for (const result of measurements) {
25
+ if (result.status === 'fulfilled') {
26
+ const element = result.value;
27
+ // Skip zero-size elements — invisible and untappable
28
+ if (element.width > 0 && element.height > 0) {
29
+ elements.push(element);
30
+ }
31
+ }
32
+ // Skip fibers that fail to measure (unmounted, off-screen, etc.)
33
+ }
34
+ // Sort: zIndex descending, then depth descending
35
+ elements.sort((a, b) => {
36
+ if (a.zIndex !== b.zIndex)
37
+ return b.zIndex - a.zIndex;
38
+ return b.depth - a.depth;
39
+ });
40
+ return elements;
41
+ };
42
+ //# sourceMappingURL=layoutSnapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layoutSnapshot.js","sourceRoot":"","sources":["../../src/utils/layoutSnapshot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAwC,MAAM,UAAU,CAAC;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,IAAe,EAA8B,EAAE;IACvF,MAAM,UAAU,GAAG,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAsB,EAAE,CAAC;IAEvC,sCAAsC;IACtC,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,UAAU,CAC3C,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAE3C,OAAO;YACL,KAAK;YACL,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,CAAC,EAAE,IAAI,CAAC,CAAC;YACT,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK;YACL,MAAM,EAAE,OAAO,KAAK,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC5D,aAAa,EAAE,YAAY,CAAC,gBAAgB,CAAC,KAAK,CAAC;SAC1B,CAAC;IAC9B,CAAC,CAAC,CACH,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;QAClC,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC;YAC7B,qDAAqD;YACrD,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5C,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QACD,iEAAiE;IACnE,CAAC;IAED,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrB,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;QACtD,OAAO,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { FiberNode } from '../fiber';
2
+ export interface SourceLocation {
3
+ fileName: string;
4
+ lineNumber: number;
5
+ columnNumber?: number;
6
+ }
7
+ /**
8
+ * Extract the source file location from a fiber node.
9
+ * Host components (RCTView, RCTText, etc.) don't have _debugSource,
10
+ * so we check _debugOwner (the component that rendered this element)
11
+ * and walk up the fiber tree as a fallback.
12
+ */
13
+ export declare const getSourceLocation: (fiber: FiberNode) => SourceLocation | null;
14
+ /**
15
+ * Format a source location for display.
16
+ * Strips the project root for readability.
17
+ * Adds extension to the file name and line number, e.g. "MyComponent.js:42"
18
+ */
19
+ export declare const formatSourceLocation: (source: SourceLocation) => string;
20
+ /**
21
+ * Get the name of the nearest user component that owns this fiber.
22
+ * React 19 dropped _debugSource, so we use _debugOwner to find the
23
+ * parent component name as a fallback.
24
+ */
25
+ export declare const getOwnerName: (fiber: FiberNode) => string | null;
26
+ //# sourceMappingURL=sourceMapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sourceMapping.d.ts","sourceRoot":"","sources":["../../src/utils/sourceMapping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,UAAW,SAAS,KAAG,cAAc,GAAG,IAerE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,WAAY,cAAc,KAAG,MAI7D,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,YAAY,UAAW,SAAS,KAAG,MAAM,GAAG,IAmBxD,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Extract the source file location from a fiber node.
3
+ * Host components (RCTView, RCTText, etc.) don't have _debugSource,
4
+ * so we check _debugOwner (the component that rendered this element)
5
+ * and walk up the fiber tree as a fallback.
6
+ */
7
+ export const getSourceLocation = (fiber) => {
8
+ // Check the fiber itself first
9
+ if (fiber._debugSource)
10
+ return fiber._debugSource;
11
+ // Check _debugOwner — points to the component that created this JSX
12
+ if (fiber._debugOwner?._debugSource)
13
+ return fiber._debugOwner._debugSource;
14
+ // Walk up the return (parent) chain
15
+ let current = fiber.return;
16
+ while (current) {
17
+ if (current._debugSource)
18
+ return current._debugSource;
19
+ current = current.return;
20
+ }
21
+ return null;
22
+ };
23
+ /**
24
+ * Format a source location for display.
25
+ * Strips the project root for readability.
26
+ * Adds extension to the file name and line number, e.g. "MyComponent.js:42"
27
+ */
28
+ export const formatSourceLocation = (source) => {
29
+ const lastSlash = source.fileName.lastIndexOf('/');
30
+ const fileName = lastSlash === -1 ? source.fileName : source.fileName.substring(lastSlash + 1);
31
+ return `${fileName}:${source.lineNumber}`;
32
+ };
33
+ /**
34
+ * Get the name of the nearest user component that owns this fiber.
35
+ * React 19 dropped _debugSource, so we use _debugOwner to find the
36
+ * parent component name as a fallback.
37
+ */
38
+ export const getOwnerName = (fiber) => {
39
+ let owner = fiber._debugOwner;
40
+ while (owner) {
41
+ const ownerType = owner.type;
42
+ if (typeof ownerType === 'function') {
43
+ const name = ownerType.displayName ?? ownerType.name;
44
+ // Skip generic RN host wrappers
45
+ if (name && name !== 'View' && name !== 'Text' && name !== 'ScrollView') {
46
+ return `in ${name}`;
47
+ }
48
+ }
49
+ owner = owner._debugOwner;
50
+ }
51
+ return null;
52
+ };
53
+ //# sourceMappingURL=sourceMapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sourceMapping.js","sourceRoot":"","sources":["../../src/utils/sourceMapping.ts"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAgB,EAAyB,EAAE;IAC3E,+BAA+B;IAC/B,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,KAAK,CAAC,YAAY,CAAC;IAElD,oEAAoE;IACpE,IAAI,KAAK,CAAC,WAAW,EAAE,YAAY;QAAE,OAAO,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC;IAE3E,oCAAoC;IACpC,IAAI,OAAO,GAAqB,KAAK,CAAC,MAAM,CAAC;IAC7C,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,YAAY;YAAE,OAAO,OAAO,CAAC,YAAY,CAAC;QACtD,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAsB,EAAU,EAAE;IACrE,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;IAC/F,OAAO,GAAG,QAAQ,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAgB,EAAiB,EAAE;IAM9D,IAAI,KAAK,GAAG,KAAK,CAAC,WAAoC,CAAC;IACvD,OAAO,KAAK,EAAE,CAAC;QACb,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;QAC7B,IAAI,OAAO,SAAS,KAAK,UAAU,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,IAAI,CAAC;YACrD,gCAAgC;YAChC,IAAI,IAAI,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;gBACxE,OAAO,MAAM,IAAI,EAAE,CAAC;YACtB,CAAC;QACH,CAAC;QACD,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC;IAC5B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Returns true if the style property name holds a color value */
2
+ export declare const isColorProp: (propertyName: string) => boolean;
3
+ /** Format a style value for display in the inspector panel */
4
+ export declare const formatValue: (value: unknown) => string;
5
+ //# sourceMappingURL=styleFormatting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styleFormatting.d.ts","sourceRoot":"","sources":["../../src/utils/styleFormatting.ts"],"names":[],"mappings":"AAsBA,kEAAkE;AAClE,eAAO,MAAM,WAAW,iBAAkB,MAAM,KAAG,OAAwC,CAAC;AAE5F,8DAA8D;AAC9D,eAAO,MAAM,WAAW,UAAW,OAAO,KAAG,MAO5C,CAAC"}
@@ -0,0 +1,38 @@
1
+ /** Complete set of React Native style properties typed as ColorValue */
2
+ const COLOR_PROPS = new Set([
3
+ 'color',
4
+ 'backgroundColor',
5
+ 'borderColor',
6
+ 'borderTopColor',
7
+ 'borderRightColor',
8
+ 'borderBottomColor',
9
+ 'borderLeftColor',
10
+ 'borderStartColor',
11
+ 'borderEndColor',
12
+ 'borderBlockColor',
13
+ 'borderBlockStartColor',
14
+ 'borderBlockEndColor',
15
+ 'outlineColor',
16
+ 'shadowColor',
17
+ 'textDecorationColor',
18
+ 'textShadowColor',
19
+ 'tintColor',
20
+ 'overlayColor',
21
+ ]);
22
+ /** Returns true if the style property name holds a color value */
23
+ export const isColorProp = (propertyName) => COLOR_PROPS.has(propertyName);
24
+ /** Format a style value for display in the inspector panel */
25
+ export const formatValue = (value) => {
26
+ if (value === undefined)
27
+ return 'undefined';
28
+ if (value === null)
29
+ return 'null';
30
+ if (typeof value === 'number')
31
+ return String(value);
32
+ if (typeof value === 'string')
33
+ return `"${value}"`;
34
+ if (typeof value === 'boolean')
35
+ return String(value);
36
+ return JSON.stringify(value);
37
+ };
38
+ //# sourceMappingURL=styleFormatting.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styleFormatting.js","sourceRoot":"","sources":["../../src/utils/styleFormatting.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,OAAO;IACP,iBAAiB;IACjB,aAAa;IACb,gBAAgB;IAChB,kBAAkB;IAClB,mBAAmB;IACnB,iBAAiB;IACjB,kBAAkB;IAClB,gBAAgB;IAChB,kBAAkB;IAClB,uBAAuB;IACvB,qBAAqB;IACrB,cAAc;IACd,aAAa;IACb,qBAAqB;IACrB,iBAAiB;IACjB,WAAW;IACX,cAAc;CACf,CAAC,CAAC;AAEH,kEAAkE;AAClE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,YAAoB,EAAW,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAE5F,8DAA8D;AAC9D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAc,EAAU,EAAE;IACpD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC5C,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,KAAK,GAAG,CAAC;IACnD,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /** Parses user input back to the appropriate type. */
2
+ export declare const parseInput: (text: string, originalValue: unknown) => unknown;
3
+ /** Raw value → editable string (no quotes around strings). */
4
+ export declare const toEditableString: (value: unknown) => string;
5
+ //# sourceMappingURL=styleInputParsing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styleInputParsing.d.ts","sourceRoot":"","sources":["../../src/utils/styleInputParsing.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,eAAO,MAAM,UAAU,SAAU,MAAM,iBAAiB,OAAO,KAAG,OAwBjE,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,UAAW,OAAO,KAAG,MAIjD,CAAC"}
@@ -0,0 +1,33 @@
1
+ /** Parses user input back to the appropriate type. */
2
+ export const parseInput = (text, originalValue) => {
3
+ const trimmed = text.trim();
4
+ if (trimmed === '')
5
+ return originalValue;
6
+ // Strip surrounding quotes if the user typed them
7
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
8
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
9
+ return trimmed.slice(1, -1);
10
+ }
11
+ // Only coerce to number when the original was numeric
12
+ if (typeof originalValue === 'number') {
13
+ const asNumber = Number(trimmed);
14
+ if (!Number.isNaN(asNumber))
15
+ return asNumber;
16
+ }
17
+ // Boolean
18
+ if (trimmed === 'true')
19
+ return true;
20
+ if (trimmed === 'false')
21
+ return false;
22
+ // Everything else is a string (e.g. color names, hex codes)
23
+ return trimmed;
24
+ };
25
+ /** Raw value → editable string (no quotes around strings). */
26
+ export const toEditableString = (value) => {
27
+ if (value === undefined)
28
+ return '';
29
+ if (value === null)
30
+ return '';
31
+ return String(value);
32
+ };
33
+ //# sourceMappingURL=styleInputParsing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styleInputParsing.js","sourceRoot":"","sources":["../../src/utils/styleInputParsing.ts"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,aAAsB,EAAW,EAAE;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,aAAa,CAAC;IAEzC,kDAAkD;IAClD,IACE,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAClD,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAClD,CAAC;QACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC;IAED,sDAAsD;IACtD,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACtC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,OAAO,QAAQ,CAAC;IAC/C,CAAC;IAED,UAAU;IACV,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,OAAO,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAEtC,4DAA4D;IAC5D,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC;AAEF,8DAA8D;AAC9D,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAU,EAAE;IACzD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { StyleObject } from './flattenStyles';
2
+ export interface BoxModel {
3
+ margin: {
4
+ top: number;
5
+ right: number;
6
+ bottom: number;
7
+ left: number;
8
+ };
9
+ border: {
10
+ top: number;
11
+ right: number;
12
+ bottom: number;
13
+ left: number;
14
+ };
15
+ padding: {
16
+ top: number;
17
+ right: number;
18
+ bottom: number;
19
+ left: number;
20
+ };
21
+ content: {
22
+ width: number;
23
+ height: number;
24
+ };
25
+ }
26
+ /**
27
+ * Extract box model values from a flattened style object.
28
+ */
29
+ export declare const extractBoxModel: (style: StyleObject | null, measured: {
30
+ width: number;
31
+ height: number;
32
+ }) => BoxModel;
33
+ //# sourceMappingURL=yogaLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yogaLayout.d.ts","sourceRoot":"","sources":["../../src/utils/yogaLayout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,OAAO,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC5C;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,UACnB,WAAW,GAAG,IAAI,YACf;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KAC1C,QAiCF,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Extract box model values from a flattened style object.
3
+ */
4
+ export const extractBoxModel = (style, measured) => {
5
+ const num = (key) => {
6
+ const val = style?.[key];
7
+ return typeof val === 'number' ? val : undefined;
8
+ };
9
+ const margin = {
10
+ top: num('marginTop') ?? num('marginVertical') ?? num('margin') ?? 0,
11
+ right: num('marginRight') ?? num('marginHorizontal') ?? num('margin') ?? 0,
12
+ bottom: num('marginBottom') ?? num('marginVertical') ?? num('margin') ?? 0,
13
+ left: num('marginLeft') ?? num('marginHorizontal') ?? num('margin') ?? 0,
14
+ };
15
+ const border = {
16
+ top: num('borderTopWidth') ?? num('borderWidth') ?? 0,
17
+ right: num('borderRightWidth') ?? num('borderWidth') ?? 0,
18
+ bottom: num('borderBottomWidth') ?? num('borderWidth') ?? 0,
19
+ left: num('borderLeftWidth') ?? num('borderWidth') ?? 0,
20
+ };
21
+ const padding = {
22
+ top: num('paddingTop') ?? num('paddingVertical') ?? num('padding') ?? 0,
23
+ right: num('paddingRight') ?? num('paddingHorizontal') ?? num('padding') ?? 0,
24
+ bottom: num('paddingBottom') ?? num('paddingVertical') ?? num('padding') ?? 0,
25
+ left: num('paddingLeft') ?? num('paddingHorizontal') ?? num('padding') ?? 0,
26
+ };
27
+ const content = {
28
+ width: measured.width - padding.left - padding.right - border.left - border.right,
29
+ height: measured.height - padding.top - padding.bottom - border.top - border.bottom,
30
+ };
31
+ return { margin, border, padding, content };
32
+ };
33
+ //# sourceMappingURL=yogaLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"yogaLayout.js","sourceRoot":"","sources":["../../src/utils/yogaLayout.ts"],"names":[],"mappings":"AASA;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAAyB,EACzB,QAA2C,EACjC,EAAE;IACZ,MAAM,GAAG,GAAG,CAAC,GAAW,EAAsB,EAAE;QAC9C,MAAM,GAAG,GAAG,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC;QACzB,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;IACnD,CAAC,CAAC;IAEF,MAAM,MAAM,GAAG;QACb,GAAG,EAAE,GAAG,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QACpE,KAAK,EAAE,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC1E,MAAM,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC1E,IAAI,EAAE,GAAG,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;KACzE,CAAC;IAEF,MAAM,MAAM,GAAG;QACb,GAAG,EAAE,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC;QACrD,KAAK,EAAE,GAAG,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC;QACzD,MAAM,EAAE,GAAG,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC;QAC3D,IAAI,EAAE,GAAG,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC;KACxD,CAAC;IAEF,MAAM,OAAO,GAAG;QACd,GAAG,EAAE,GAAG,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;QACvE,KAAK,EAAE,GAAG,CAAC,cAAc,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;QAC7E,MAAM,EAAE,GAAG,CAAC,eAAe,CAAC,IAAI,GAAG,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;QAC7E,IAAI,EAAE,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;KAC5E,CAAC;IAEF,MAAM,OAAO,GAAG;QACd,KAAK,EAAE,QAAQ,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK;QACjF,MAAM,EAAE,QAAQ,CAAC,MAAM,GAAG,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,MAAM;KACpF,CAAC;IAEF,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9C,CAAC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,74 @@
1
+ {
2
+ "name": "react-native-element-inspector",
3
+ "version": "0.1.0",
4
+ "description": "On-device element inspector for React Native — the Inspect Element experience for mobile.",
5
+ "main": "lib/index.js",
6
+ "module": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "source": "src/index.ts",
9
+ "files": [
10
+ "src",
11
+ "lib",
12
+ "!**/__tests__",
13
+ "!**/__mocks__",
14
+ "!**/*.test.*"
15
+ ],
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/mabdinasira/react-native-element-inspector.git"
19
+ },
20
+ "homepage": "https://github.com/mabdinasira/react-native-element-inspector#readme",
21
+ "bugs": {
22
+ "url": "https://github.com/mabdinasira/react-native-element-inspector/issues"
23
+ },
24
+ "author": "Mohamed Abdinasir",
25
+ "scripts": {
26
+ "lint": "biome lint --write .",
27
+ "fmt": "biome format --write .",
28
+ "check": "biome check --write . --unsafe",
29
+ "typecheck": "tsc --noEmit",
30
+ "build": "tsc --project tsconfig.build.json",
31
+ "prepublishOnly": "rm -rf lib && bun run build",
32
+ "fixall": "biome check --write . --unsafe && tsc --noEmit",
33
+ "clean": "rm -rf node_modules lib && bun install",
34
+ "test": "jest",
35
+ "example:start": "bun run --cwd example start",
36
+ "example:ios": "bun run --cwd example ios",
37
+ "example:android": "bun run --cwd example android",
38
+ "example:prebuild": "bun run --cwd example prebuild",
39
+ "example:fixall": "bun run --cwd example check && bun run --cwd example typecheck",
40
+ "example:clean": "bun run --cwd example clean",
41
+ "example:install": "cd example && bun install"
42
+ },
43
+ "keywords": [
44
+ "react-native",
45
+ "inspector",
46
+ "devtools",
47
+ "style-editor",
48
+ "debug"
49
+ ],
50
+ "license": "MIT",
51
+ "peerDependencies": {
52
+ "react": ">=18.0.0",
53
+ "react-native": ">=0.72.0"
54
+ },
55
+ "devDependencies": {
56
+ "@babel/core": "^7.29.0",
57
+ "@babel/plugin-transform-flow-strip-types": "^7.27.1",
58
+ "@babel/preset-env": "^7.29.0",
59
+ "@babel/preset-flow": "^7.27.1",
60
+ "@babel/preset-react": "^7.28.5",
61
+ "@babel/preset-typescript": "^7.28.5",
62
+ "@biomejs/biome": "~2.4.4",
63
+ "@testing-library/react-native": "^13.3.3",
64
+ "@types/jest": "^30.0.0",
65
+ "@types/react": "~19.0.0",
66
+ "@types/react-test-renderer": "^19.1.0",
67
+ "babel-jest": "^30.2.0",
68
+ "jest": "^30.2.0",
69
+ "react": "~19.1.0",
70
+ "react-native": "~0.81.0",
71
+ "react-test-renderer": "^19.2.4",
72
+ "typescript": "~5.7.0"
73
+ }
74
+ }
@@ -0,0 +1,64 @@
1
+ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
2
+
3
+ interface ElementCyclerProps {
4
+ /** Total number of overlapping elements at the tap point */
5
+ total: number;
6
+ /** Currently selected index (0-based) */
7
+ currentIndex: number;
8
+ /** Name of the currently selected component */
9
+ componentName: string;
10
+ onPrevious: () => void;
11
+ onNext: () => void;
12
+ }
13
+
14
+ /** UI for cycling through overlapping elements at a tap point. */
15
+ export const ElementCycler = ({
16
+ total,
17
+ currentIndex,
18
+ componentName,
19
+ onPrevious,
20
+ onNext,
21
+ }: ElementCyclerProps) => {
22
+ if (total <= 1) return null;
23
+
24
+ return (
25
+ <View style={styles.container}>
26
+ <TouchableOpacity onPress={onPrevious} style={styles.button} activeOpacity={0.6}>
27
+ <Text style={styles.arrow}>▲</Text>
28
+ </TouchableOpacity>
29
+
30
+ <Text style={styles.label} numberOfLines={1}>
31
+ {componentName} ({currentIndex + 1}/{total})
32
+ </Text>
33
+
34
+ <TouchableOpacity onPress={onNext} style={styles.button} activeOpacity={0.6}>
35
+ <Text style={styles.arrow}>▼</Text>
36
+ </TouchableOpacity>
37
+ </View>
38
+ );
39
+ };
40
+
41
+ const styles = StyleSheet.create({
42
+ container: {
43
+ flexDirection: 'row',
44
+ alignItems: 'center',
45
+ borderRadius: 6,
46
+ paddingHorizontal: 4,
47
+ paddingVertical: 2,
48
+ },
49
+ button: {
50
+ paddingHorizontal: 8,
51
+ paddingVertical: 4,
52
+ },
53
+ arrow: {
54
+ color: '#AAAAAA',
55
+ fontSize: 13,
56
+ },
57
+ label: {
58
+ color: '#DDDDDD',
59
+ fontSize: 13,
60
+ fontWeight: '500',
61
+ marginHorizontal: 4,
62
+ flexShrink: 1,
63
+ },
64
+ });
@@ -0,0 +1,122 @@
1
+ import { StyleSheet, View } from 'react-native';
2
+ import { BOX_MODEL_COLORS, Z_INDEX } from './constants';
3
+ import { FiberAdapter, type MeasuredElement } from './fiber';
4
+ import { extractBoxModel } from './utils';
5
+
6
+ interface ElementHighlighterProps {
7
+ element: MeasuredElement | null;
8
+ outlineOnly?: boolean;
9
+ }
10
+
11
+ /**
12
+ * Draws a Chrome DevTools-style highlight on the selected element.
13
+ *
14
+ * Full mode: margin (orange), padding (green), content (blue) fills + outline.
15
+ * Outline-only mode: just the crisp border — keeps selection visible without obscuring content.
16
+ *
17
+ * The measured rect is the border box (includes border + padding, NOT margin).
18
+ * Margin extends outward, padding/content sit inside.
19
+ *
20
+ * Layering trick: each nested View's background covers the parent's color,
21
+ * so only the "strips" around the edges remain visible:
22
+ * orange margin strips → green padding strips → blue content fill
23
+ */
24
+ export const ElementHighlighter = ({ element, outlineOnly = false }: ElementHighlighterProps) => {
25
+ if (!element) return null;
26
+
27
+ const style = FiberAdapter.getStyle(element.fiber);
28
+ const { margin, border, padding } = extractBoxModel(style, {
29
+ width: element.width,
30
+ height: element.height,
31
+ });
32
+
33
+ // Margin box extends outward from the measured rect
34
+ const marginBoxLeft = element.x - margin.left;
35
+ const marginBoxTop = element.y - margin.top;
36
+ const marginBoxWidth = element.width + margin.left + margin.right;
37
+ const marginBoxHeight = element.height + margin.top + margin.bottom;
38
+
39
+ return (
40
+ <View pointerEvents='none' style={styles.root}>
41
+ {!outlineOnly && (
42
+ <>
43
+ {/* Margin layer — orange, covers full area including margins */}
44
+ <View
45
+ style={[
46
+ styles.marginLayer,
47
+ {
48
+ left: marginBoxLeft,
49
+ top: marginBoxTop,
50
+ width: marginBoxWidth,
51
+ height: marginBoxHeight,
52
+ },
53
+ ]}
54
+ >
55
+ {/* Padding layer — green, covers the element's border box */}
56
+ <View
57
+ style={[
58
+ styles.paddingLayer,
59
+ {
60
+ position: 'absolute',
61
+ left: margin.left,
62
+ top: margin.top,
63
+ width: element.width,
64
+ height: element.height,
65
+ },
66
+ ]}
67
+ >
68
+ {/* Content layer — blue, inset by border + padding */}
69
+ <View
70
+ style={[
71
+ styles.contentLayer,
72
+ {
73
+ position: 'absolute',
74
+ left: border.left + padding.left,
75
+ top: border.top + padding.top,
76
+ right: border.right + padding.right,
77
+ bottom: border.bottom + padding.bottom,
78
+ },
79
+ ]}
80
+ />
81
+ </View>
82
+ </View>
83
+ </>
84
+ )}
85
+
86
+ {/* Crisp outline at the border box edge */}
87
+ <View
88
+ style={[
89
+ styles.outline,
90
+ {
91
+ left: element.x,
92
+ top: element.y,
93
+ width: element.width,
94
+ height: element.height,
95
+ },
96
+ ]}
97
+ />
98
+ </View>
99
+ );
100
+ };
101
+
102
+ const styles = StyleSheet.create({
103
+ root: {
104
+ ...StyleSheet.absoluteFillObject,
105
+ zIndex: Z_INDEX.HIGHLIGHT,
106
+ },
107
+ marginLayer: {
108
+ position: 'absolute',
109
+ backgroundColor: BOX_MODEL_COLORS.margin,
110
+ },
111
+ paddingLayer: {
112
+ backgroundColor: BOX_MODEL_COLORS.padding,
113
+ },
114
+ contentLayer: {
115
+ backgroundColor: BOX_MODEL_COLORS.content,
116
+ },
117
+ outline: {
118
+ position: 'absolute',
119
+ borderWidth: 1.5,
120
+ borderColor: BOX_MODEL_COLORS.outline,
121
+ },
122
+ });