rn-studio 0.3.2 β†’ 0.3.3

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 (2) hide show
  1. package/README.md +213 -54
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,66 +1,76 @@
1
- # rn-studio
1
+ # 🎨 rn-studio
2
2
 
3
- > Live UI editor for React Native. Inspect and edit any component directly inside the iOS Simulator or Android Emulator β€” changes are written to your source code automatically.
3
+ > **Live UI editor for React Native.** Tap any component in your running simulator and edit its styles β€” every change is written straight back to your source code, with Metro Fast Refresh updating the UI in milliseconds.
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/rn-studio.svg)](https://www.npmjs.com/package/rn-studio)
6
- [![license](https://img.shields.io/npm/l/rn-studio.svg)](https://github.com/dgutierrezd/rn-studio/blob/main/LICENSE)
7
- [![platform](https://img.shields.io/badge/platform-iOS%20%7C%20Android-blue.svg)](https://github.com/dgutierrezd/rn-studio)
5
+ [![npm version](https://img.shields.io/npm/v/rn-studio.svg?color=7C9BFF&label=npm&style=flat)](https://www.npmjs.com/package/rn-studio)
6
+ [![license](https://img.shields.io/npm/l/rn-studio.svg?color=7C9BFF&style=flat)](https://github.com/dgutierrezd/rn-studio/blob/main/LICENSE)
7
+ [![platform](https://img.shields.io/badge/platform-iOS%20%7C%20Android-7C9BFF.svg?style=flat)](https://github.com/dgutierrezd/rn-studio)
8
+ [![react-native](https://img.shields.io/badge/react--native-%E2%89%A50.70-7C9BFF.svg?style=flat)](https://github.com/dgutierrezd/rn-studio)
8
9
 
9
- ## What it does
10
+ ---
10
11
 
11
- rn-studio adds a floating bubble to your app in DEV mode. Tap it, tap any component, and a panel appears showing all its styles and the internal component tree. Edit a value β€” the change is written directly to your source file and Metro Fast Refresh updates the UI instantly. Zero impact on production.
12
-
13
- ## Demo
12
+ ## 🎬 Demo
14
13
 
15
14
  [![rn-studio demo β€” click to watch](https://raw.githubusercontent.com/dgutierrezd/rn-studio/main/docs/demo-thumbnail.png)](https://github.com/dgutierrezd/rn-studio/releases/download/v0.2.0/rn-studio-demo.mov)
16
15
 
17
16
  > Tap the floating bubble β†’ selection mode activates β†’ tap any component β†’ the inspector panel slides up with the component's styles, tree, and props. Edit a value, and the source file is rewritten via AST in real time while Metro Fast Refresh re-renders the UI.
18
17
  >
19
- > _Click the thumbnail to watch the full demo video (20 MB, iPhone 15 Pro capture)._
18
+ > _Click the thumbnail to watch the full video._
19
+
20
+ ---
21
+
22
+ ## ✨ What you get
23
+
24
+ | | Feature | Details |
25
+ |---|---|---|
26
+ | 🎯 | **Tap-to-inspect** | Tap any on-screen component. Walks the React fiber tree to find the nearest user-code source, skipping library internals. Works on both **Fabric** and the **legacy architecture**. |
27
+ | πŸ’… | **Live style editing** | Edit any style and watch it apply instantly via Metro Fast Refresh. The AST engine rewrites the exact JSX element in your source β€” including `style={styles.foo}` references, which are resolved back into your `StyleSheet.create()` declaration. |
28
+ | πŸ” | **Preview mode** | Every edit is held in a server-side preview buffer until you tap **βœ“ Commit** or **β†Ί Cancel**. Cancel reverts the file to its exact original state β€” your git diff stays clean. |
29
+ | β†Άβ†· | **Undo / Redo** | 50-deep edit history. Commit a preview β†’ get a single consolidated undo entry. Tap β†Ά to revert the whole batch in one go. |
30
+ | βž• | **Add any RN property** | Tap "+ Add property" to open a searchable modal of ~80 React Native style properties, grouped by category (Layout, Flex, Spacing, Sizing, Position, Background, Border, Shadow, Typography, Transform, Visibility). |
31
+ | πŸ“œ | **Auto-scroll on select** | Tap a component hidden behind the inspector panel and rn-studio walks the fiber tree to find the nearest `ScrollView` / `FlatList` / `SectionList` ancestor and scrolls it so your component lands in the top 12% of the screen. |
32
+ | πŸ’Ύ | **Selection persists across reloads** | Cmd+R the simulator and your last-selected component is re-selected automatically via the React DevTools fiber-root walker. |
33
+ | πŸŽ›οΈ | **Three-tab inspector** | **Styles** (edit), **Tree** (component hierarchy), **Props** (read-only inspection). All scrollable. |
34
+ | 🎨 | **Minimal indigo UI** | Clean `#7C9BFF` accent on a pure `#111` dark background. No distracting lime greens. |
35
+ | πŸͺΆ | **Zero extra deps** | No `react-native-reanimated`, no `react-native-gesture-handler` required. Pure RN + stock `Animated` API. |
36
+ | 🚫 | **Zero production overhead** | `<StudioProvider enabled={__DEV__}>` short-circuits to `{children}` in release builds. Babel plugin is dev-only. |
37
+ | πŸš€ | **One-command setup** | `npx rn-studio init` wires up `babel.config.js` and `package.json` for you. |
20
38
 
21
- ## Install
39
+ ---
40
+
41
+ ## πŸ“¦ Install
22
42
 
23
43
  ```bash
24
44
  npm install rn-studio
25
45
  ```
26
46
 
27
- Optional peer dependencies (already present in most RN apps β€” install only if missing):
47
+ Then run the init command β€” it patches `babel.config.js`, adds the `studio` script to `package.json`, and prints the snippet to paste into `App.tsx`:
28
48
 
29
49
  ```bash
30
- npm install react-native-safe-area-context react-native-haptic-feedback
50
+ npx rn-studio init
31
51
  ```
32
52
 
33
- > `rn-studio@0.2+` drops the hard peer on `react-native-reanimated` and
34
- > `react-native-gesture-handler`. The inspector panel uses the stock
35
- > `Animated` API so consumers don't need the worklets babel plugin.
36
-
37
- ## Setup
53
+ <details>
54
+ <summary><strong>πŸ“‹ Manual setup (if you prefer)</strong></summary>
38
55
 
39
- ### 1. Add the babel plugin
56
+ ### 1. Register the babel plugin (dev only)
40
57
 
41
58
  ```js
42
59
  // babel.config.js
43
60
  module.exports = {
44
- presets: ['module:metro-react-native-babel-preset'],
61
+ presets: ['module:@react-native/babel-preset'],
45
62
  plugins: [
46
- ...(process.env.NODE_ENV !== 'production' ? ['rn-studio/babel-plugin'] : []),
63
+ ...(process.env.NODE_ENV !== 'production'
64
+ ? ['rn-studio/babel-plugin']
65
+ : []),
47
66
  ],
48
67
  };
49
68
  ```
50
69
 
51
- ### 2. Start the server (alongside Metro)
52
-
53
- ```bash
54
- # Terminal 1
55
- npx react-native start
56
-
57
- # Terminal 2
58
- npm run studio
59
- ```
60
-
61
- Add to your app's `package.json`:
70
+ ### 2. Add the studio script
62
71
 
63
72
  ```json
73
+ // package.json
64
74
  {
65
75
  "scripts": {
66
76
  "studio": "rn-studio-server"
@@ -82,47 +92,196 @@ export default function App() {
82
92
  }
83
93
  ```
84
94
 
85
- ## How it works
95
+ </details>
96
+
97
+ ---
98
+
99
+ ## ▢️ Run it
100
+
101
+ Open two terminal tabs:
102
+
103
+ ```bash
104
+ # Terminal 1 β€” Metro
105
+ npx react-native start
106
+
107
+ # Terminal 2 β€” rn-studio server
108
+ npm run studio
109
+ ```
110
+
111
+ Launch your app in the simulator. A floating 🎨 bubble appears in the bottom-right. Tap it, tap any component, and start editing.
112
+
113
+ ---
114
+
115
+ ## 🧠 How it works
86
116
 
87
117
  | Layer | What it does |
88
118
  |---|---|
89
- | Babel plugin | Annotates every JSX element with file + line metadata at compile time |
90
- | Floating bubble | Toggles selection mode on tap |
91
- | Selection overlay | Tap any component to inspect it |
92
- | Inspector panel | Shows styles, component tree, and editable props |
93
- | WebSocket bridge | Sends changes from the app to the local CLI server |
94
- | AST engine | Locates and rewrites the exact prop in your source file |
95
- | Metro Fast Refresh | Picks up the file change and updates the UI |
119
+ | πŸ”§ **Babel plugin** | Annotates every JSX element at compile time with `__rnStudioSource = { file, line, column, componentName }` |
120
+ | 🫧 **Floating bubble** | Toggles selection mode with a spring-animated draggable overlay |
121
+ | 🎯 **Selection overlay** | Uses RN's built-in `getInspectorDataForViewAtPoint` (Fabric + legacy) to hit-test touches, then walks the fiber `.return` chain to the nearest user-code source |
122
+ | πŸͺž **Inspector panel** | Bottom-sheet with Styles / Tree / Props tabs β€” fully scrollable, auto-scrolls the underlying `ScrollView` so the selected component stays visible |
123
+ | πŸŒ‰ **WebSocket bridge** | Streams edits from the app over `ws://localhost:7878` with exponential-backoff reconnect |
124
+ | πŸ› οΈ **AST engine** | Reads the target file with `recast` + `@babel/parser`, locates the exact JSX opening element by `(line, column)`, and rewrites the `style` prop. Handles inline objects, array styles, and `StyleSheet.create()` references. Refuses to touch `node_modules`. |
125
+ | πŸ”„ **Metro Fast Refresh** | Picks up the file change and updates your UI in milliseconds |
126
+ | πŸ“š **Undo / Preview state** | Server keeps a 50-deep undo stack plus a preview buffer for uncommitted edits |
127
+
128
+ ---
96
129
 
97
- ## API
130
+ ## πŸ“– API
98
131
 
99
132
  ### `<StudioProvider>` props
100
133
 
101
134
  | Prop | Type | Default | Description |
102
135
  |---|---|---|---|
103
- | `enabled` | `boolean` | `false` | Show the studio UI |
136
+ | `enabled` | `boolean` | `false` | Show the studio UI. Pass `__DEV__` to enable in development only. |
104
137
  | `serverPort` | `number` | `7878` | CLI server port |
105
- | `bubblePosition` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | `'bottom-right'` | Bubble starting corner |
106
- | `theme` | `'dark' \| 'light'` | `'dark'` | Panel theme |
138
+ | `bubblePosition` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | `'bottom-right'` | Starting corner for the floating bubble |
139
+ | `theme` | `'dark' \| 'light'` | `'dark'` | Panel theme (currently dark only) |
107
140
 
108
141
  ### `useStudio()`
109
142
 
110
143
  ```ts
111
144
  const {
112
- isActive,
113
- isSelecting,
114
- selectedComponent,
115
- toggleActive,
116
- selectComponent,
117
- clearSelection,
118
- updateStyle,
145
+ // Selection state
146
+ isActive, // boolean β€” selection mode toggled?
147
+ isSelecting, // boolean β€” waiting for a tap?
148
+ selectedComponent, // ComponentNode | null
149
+
150
+ // Actions
151
+ toggleActive, // () => void
152
+ selectComponent, // (node: ComponentNode) => void
153
+ clearSelection, // () => void
154
+
155
+ // Style editing
156
+ updateStyle, // (key: string, value: string | number) => void
157
+ addStyleProperty, // (key: string, value: string | number | boolean) => void
158
+
159
+ // Undo / Redo
160
+ undo, // () => void
161
+ redo, // () => void
162
+ canUndo, // boolean
163
+ canRedo, // boolean
164
+
165
+ // Preview mode
166
+ hasPendingPreview, // boolean
167
+ commitPreview, // () => void
168
+ cancelPreview, // () => void
119
169
  } = useStudio();
120
170
  ```
121
171
 
122
- ## Contributing
172
+ ---
173
+
174
+ ## πŸ›‘οΈ Preview mode explained
175
+
176
+ Every edit made while a component is selected is held in a **server-side preview buffer** until you explicitly commit or cancel.
177
+
178
+ ```
179
+ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
180
+ β”‚ Tap component β†’ BEGIN_PREVIEW β†’ server snapshots β”‚
181
+ β”‚ the file β”‚
182
+ β”‚ β”‚
183
+ β”‚ Edit fontSize 14β†’28 ┐ β”‚
184
+ β”‚ Edit color #fffβ†’blue β”œβ”€β”€ each write hits disk β”‚
185
+ β”‚ Edit padding 10β†’24 β”‚ Metro Fast Refresh shows it β”‚
186
+ β”‚ β”‚ BUT nothing enters the undo stack β”‚
187
+ β”‚ β”‚
188
+ β”‚ β”Œβ”€β”€β”€β”€ Preview badge shows in panel header ────┐ β”‚
189
+ β”‚ β”‚ β†Ί βœ“ replace β†Ά β†· β”‚ β”‚
190
+ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
191
+ β”‚ β”‚
192
+ β”‚ Your choice: β”‚
193
+ β”‚ β”‚
194
+ β”‚ βœ“ Commit β†’ server packs all edits into a SINGLE undo β”‚
195
+ β”‚ entry labeled "preview (N edits)". β”‚
196
+ β”‚ You can still β†Ά to revert the whole batch. β”‚
197
+ β”‚ β”‚
198
+ β”‚ β†Ί Cancel β†’ server writes the original snapshot back. β”‚
199
+ β”‚ File is pristine. No undo entry created. β”‚
200
+ β”‚ Your git diff stays clean. β”‚
201
+ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
202
+ ```
203
+
204
+ **Auto-commit triggers:** switching to a different component, closing the panel, toggling the bubble off. **Auto-cancel triggers:** client disconnect (app reload, server restart).
205
+
206
+ ---
207
+
208
+ ## πŸ’‘ Tips
209
+
210
+ - πŸŽ›οΈ **Drag the floating bubble** anywhere on screen β€” its position is saved to `AsyncStorage` (optional dependency).
211
+ - ⌫ **Cmd+R** in the simulator β€” your last-selected component is re-selected automatically.
212
+ - 🎨 **Tap a color swatch** to see it highlighted, then edit the hex directly.
213
+ - βž• **Tap "+ Add property"** inside the Styles tab to search all ~80 React Native style properties.
214
+ - πŸ“‘ **Switch to the Props tab** to inspect every non-style prop of the selected component (read-only for now).
215
+ - 🌳 **Switch to the Tree tab** to navigate nested rn-studio-annotated children.
216
+
217
+ ---
218
+
219
+ ## 🚫 Production safety
220
+
221
+ Three independent guarantees ensure **zero production overhead**:
222
+
223
+ 1. πŸ”Œ **Babel plugin** early-returns when `NODE_ENV === 'production'` β€” `__rnStudioSource` is never emitted in release bundles.
224
+ 2. 🧩 **`<StudioProvider enabled={false}>`** short-circuits to `<>{children}</>` β€” no context, no WebSocket, no overlay.
225
+ 3. πŸ“¦ **Consumer convention** β€” pass `enabled={__DEV__}` so the whole system ties to React Native's own dev flag.
226
+
227
+ ---
228
+
229
+ ## πŸ“œ Changelog highlights
230
+
231
+ <details>
232
+ <summary><strong>v0.3.2</strong> β€” Fix styles disappearing on undo</summary>
233
+
234
+ Undo/redo/cancel now refresh the inspector's style list from the live fiber tree instead of leaving stale or empty state. New shared `extractStylesFromFiber` utility used by both the overlay and the provider.
235
+
236
+ </details>
237
+
238
+ <details>
239
+ <summary><strong>v0.3.1</strong> β€” Preview mode βœ“ β†Ί</summary>
240
+
241
+ Every style edit is held in a server-side preview buffer. Tap βœ“ to commit (single consolidated undo entry) or β†Ί to revert the file to its exact state at selection time. Auto-commits on deselect, auto-cancels on disconnect.
242
+
243
+ </details>
244
+
245
+ <details>
246
+ <summary><strong>v0.3.0</strong> β€” Add property picker, init CLI, undo/redo, persistence, auto-scroll</summary>
247
+
248
+ Five major features shipped together:
249
+ - Searchable modal listing ~80 RN style properties across 11 groups
250
+ - `npx rn-studio init` β€” zero-config project bootstrap
251
+ - 50-deep undo/redo stack with β†Ά β†· buttons
252
+ - Selection persistence across Cmd+R via AsyncStorage + fiber walker
253
+ - Auto-scroll walks the fiber tree to bring the selected component into view above the 60% panel
254
+
255
+ </details>
256
+
257
+ <details>
258
+ <summary><strong>v0.2.0</strong> β€” Selection flow fix for Fabric + AST StyleSheet resolution</summary>
259
+
260
+ Replaces legacy `UIManager.findSubviewIn` with `getInspectorDataForViewAtPoint`. Walks the fiber `.return` chain instead of the flat hierarchy. AST engine resolves `style={styles.foo}` into `StyleSheet.create()` entries. Dropped hard peer deps on reanimated and gesture-handler.
261
+
262
+ </details>
263
+
264
+ Full history: [GitHub Releases](https://github.com/dgutierrezd/rn-studio/releases)
265
+
266
+ ---
267
+
268
+ ## 🀝 Contributing
269
+
270
+ Pull requests welcome! For major changes, please open an issue first so we can talk it through.
271
+
272
+ Local development:
273
+
274
+ ```bash
275
+ git clone https://github.com/dgutierrezd/rn-studio.git
276
+ cd rn-studio
277
+ npm install
278
+ npm run build # compile TS to dist/
279
+ ```
280
+
281
+ The `dist/` output is what gets published to npm. The `bin/` folder contains the CLI entry points (`rn-studio-server`, `rn-studio-init`), which run against the compiled `dist/ast/AstEngine.js`.
123
282
 
124
- Pull requests are welcome. For major changes, please open an issue first.
283
+ ---
125
284
 
126
- ## License
285
+ ## πŸ“„ License
127
286
 
128
287
  MIT Β© [dgutierrezd](https://github.com/dgutierrezd)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rn-studio",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Live UI editor for React Native β€” inspect and edit components directly in your emulator",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",