@myop/cli 0.1.46 → 0.1.48
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.
- package/dist/myop-cli.js +844 -812
- package/dist/skills/myop-angular-host/SKILL.md +118 -1
- package/dist/skills/myop-cli/SKILL.md +147 -0
- package/dist/skills/myop-component/SKILL.md +105 -73
- package/dist/skills/myop-component/references/component-api.md +0 -28
- package/dist/skills/myop-component/references/dev-workflow.md +3 -2
- package/dist/skills/myop-component/references/sizing-and-layout.md +41 -71
- package/dist/skills/myop-component/references/type-definitions.md +2 -19
- package/dist/skills/myop-react-host/SKILL.md +143 -1
- package/dist/skills/myop-react-native-host/SKILL.md +119 -1
- package/dist/skills/myop-vue-host/SKILL.md +112 -1
- package/package.json +1 -1
|
@@ -122,25 +122,6 @@ window.myop_cta_handler(action_id, payload);
|
|
|
122
122
|
})();
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
### Standard Actions
|
|
126
|
-
|
|
127
|
-
These action IDs have special meaning and are handled by the Myop SDK:
|
|
128
|
-
|
|
129
|
-
| Action ID | Payload | Purpose |
|
|
130
|
-
|-----------|---------|---------|
|
|
131
|
-
| `'size-requested'` | `{ width?, height?, minWidth?, maxWidth?, minHeight?, maxHeight?, required? }` | Request the host to resize the component container |
|
|
132
|
-
|
|
133
|
-
```javascript
|
|
134
|
-
// Request more width
|
|
135
|
-
window.myop_cta_handler('size-requested', {
|
|
136
|
-
width: 400,
|
|
137
|
-
minWidth: 300,
|
|
138
|
-
maxWidth: 600,
|
|
139
|
-
required: true // true = content is clipped without this size
|
|
140
|
-
// false = preference only, host may ignore
|
|
141
|
-
});
|
|
142
|
-
```
|
|
143
|
-
|
|
144
125
|
### Custom Actions
|
|
145
126
|
|
|
146
127
|
Define any custom actions your component needs. Use kebab-case for action IDs:
|
|
@@ -226,15 +207,6 @@ The `<script id="myop_preview">` block provides mock data for development. In pr
|
|
|
226
207
|
interface MyopCtaPayloads {
|
|
227
208
|
'task-toggled': { taskId: string; completed: boolean };
|
|
228
209
|
'task-deleted': { taskId: string };
|
|
229
|
-
'size-requested': {
|
|
230
|
-
width?: number | null;
|
|
231
|
-
height?: number | null;
|
|
232
|
-
minWidth?: number | null;
|
|
233
|
-
maxWidth?: number | null;
|
|
234
|
-
minHeight?: number | null;
|
|
235
|
-
maxHeight?: number | null;
|
|
236
|
-
required?: boolean;
|
|
237
|
-
};
|
|
238
210
|
}
|
|
239
211
|
|
|
240
212
|
declare function myop_init_interface(): MyopInitData;
|
|
@@ -14,10 +14,11 @@ The Myop CLI provides commands for creating, developing, and deploying component
|
|
|
14
14
|
## CLI Installation
|
|
15
15
|
|
|
16
16
|
```bash
|
|
17
|
-
npm install -g
|
|
17
|
+
npm install -g myop
|
|
18
|
+
# Or use without installing: npx myop <command>
|
|
18
19
|
```
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
The npm package name is `myop`.
|
|
21
22
|
|
|
22
23
|
## Commands Reference
|
|
23
24
|
|
|
@@ -6,7 +6,6 @@ Myop components run inside a container managed by the host application. Proper s
|
|
|
6
6
|
- [Size Meta Tag](#size-meta-tag)
|
|
7
7
|
- [Required Base CSS](#required-base-css)
|
|
8
8
|
- [Layout Patterns](#layout-patterns)
|
|
9
|
-
- [Dynamic Size Requests](#dynamic-size-requests)
|
|
10
9
|
- [Common Mistakes](#common-mistakes)
|
|
11
10
|
|
|
12
11
|
## Size Meta Tag
|
|
@@ -14,10 +13,13 @@ Myop components run inside a container managed by the host application. Proper s
|
|
|
14
13
|
Every component should declare its preferred dimensions in a `<meta>` tag inside `<head>`:
|
|
15
14
|
|
|
16
15
|
```html
|
|
17
|
-
<meta name="myop:size" content='{"width":"100%","height":
|
|
16
|
+
<meta name="myop:size" content='{"width":"100%","height":300}'>
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
The host reads this BEFORE rendering the component, so the container can be sized correctly from the start (no layout shift).
|
|
19
|
+
The host reads this BEFORE rendering the component, so the container can be sized correctly from the start (no layout shift). The `height` value also determines the sizing mode:
|
|
20
|
+
|
|
21
|
+
- **Number (or absent)** → **Content mode** (default): component auto-sizes to its content, like a `<div>`
|
|
22
|
+
- **`"100%"`** → **Fill mode**: component fills its parent container
|
|
21
23
|
|
|
22
24
|
### Properties
|
|
23
25
|
|
|
@@ -26,7 +28,7 @@ All values are either a number (pixels) or the string `"100%"`:
|
|
|
26
28
|
| Property | Type | Description |
|
|
27
29
|
|----------|------|-------------|
|
|
28
30
|
| `width` | `number \| "100%"` | Preferred width in px, or `"100%"` to fill container |
|
|
29
|
-
| `height` | `number \| "100%"` | Preferred height in px, or `"100%"` to fill container |
|
|
31
|
+
| `height` | `number \| "100%"` | Preferred height in px (content mode), or `"100%"` to fill container (fill mode) |
|
|
30
32
|
| `minWidth` | `number` | Minimum acceptable width in px |
|
|
31
33
|
| `maxWidth` | `number` | Maximum useful width in px |
|
|
32
34
|
| `minHeight` | `number` | Minimum acceptable height in px |
|
|
@@ -35,13 +37,16 @@ All values are either a number (pixels) or the string `"100%"`:
|
|
|
35
37
|
### Examples
|
|
36
38
|
|
|
37
39
|
```html
|
|
38
|
-
<!--
|
|
40
|
+
<!-- Content mode (default): auto-sizes to content -->
|
|
41
|
+
<meta name="myop:size" content='{"width":"100%","height":300}'>
|
|
42
|
+
|
|
43
|
+
<!-- Fill mode: fills all available space -->
|
|
39
44
|
<meta name="myop:size" content='{"width":"100%","height":"100%"}'>
|
|
40
45
|
|
|
41
|
-
<!-- Fixed width sidebar
|
|
46
|
+
<!-- Fixed width sidebar, fills height -->
|
|
42
47
|
<meta name="myop:size" content='{"width":300,"height":"100%","minWidth":200,"maxWidth":400}'>
|
|
43
48
|
|
|
44
|
-
<!-- Fixed height banner -->
|
|
49
|
+
<!-- Fixed height banner, content mode -->
|
|
45
50
|
<meta name="myop:size" content='{"width":"100%","height":80}'>
|
|
46
51
|
|
|
47
52
|
<!-- Card with constraints -->
|
|
@@ -50,32 +55,31 @@ All values are either a number (pixels) or the string `"100%"`:
|
|
|
50
55
|
|
|
51
56
|
## Required Base CSS
|
|
52
57
|
|
|
53
|
-
|
|
58
|
+
There are two base CSS patterns depending on the sizing mode:
|
|
59
|
+
|
|
60
|
+
### Content Mode (default) — component acts like a `<div>`
|
|
61
|
+
|
|
62
|
+
The component auto-sizes to its content. Width fills the parent, height grows with content. Use for cards, forms, lists, banners, modals, and any component where the height depends on the content.
|
|
54
63
|
|
|
55
64
|
```css
|
|
56
|
-
* {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
}
|
|
65
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
66
|
+
html, body { width: 100%; margin: 0; padding: 0; }
|
|
67
|
+
#app-root { width: 100%; }
|
|
68
|
+
```
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
width: 100%;
|
|
64
|
-
height: 100%;
|
|
65
|
-
overflow: hidden; /* Component handles its own scrolling */
|
|
66
|
-
margin: 0;
|
|
67
|
-
padding: 0;
|
|
68
|
-
}
|
|
70
|
+
### Fill Mode (opt-in) — component fills its parent container
|
|
69
71
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
72
|
+
The component fills all available space. Use for sidebars, full-page panels, dashboards, and any component that must stretch to fit the parent.
|
|
73
|
+
|
|
74
|
+
```css
|
|
75
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
76
|
+
html, body { width: 100%; height: 100%; overflow: hidden; margin: 0; padding: 0; }
|
|
77
|
+
#app-root { width: 100%; height: 100%; }
|
|
74
78
|
```
|
|
75
79
|
|
|
76
|
-
### Why `overflow: hidden` on body?
|
|
80
|
+
### Why `overflow: hidden` on body in fill mode?
|
|
77
81
|
|
|
78
|
-
The component is rendered inside an iframe by the host. If the body scrolls, the host has no way to control or sync that scroll. Instead,
|
|
82
|
+
The component is rendered inside an iframe by the host. If the body scrolls, the host has no way to control or sync that scroll. Instead, fill-mode components should manage scrolling internally with specific scrollable regions. In content mode, overflow is omitted so the host can control it.
|
|
79
83
|
|
|
80
84
|
## Layout Patterns
|
|
81
85
|
|
|
@@ -147,47 +151,6 @@ For simple display components:
|
|
|
147
151
|
}
|
|
148
152
|
```
|
|
149
153
|
|
|
150
|
-
## Dynamic Size Requests
|
|
151
|
-
|
|
152
|
-
If the component needs to change its size after initialization (e.g., content loaded, accordion expanded), use the `size-requested` CTA:
|
|
153
|
-
|
|
154
|
-
```javascript
|
|
155
|
-
// Request specific dimensions
|
|
156
|
-
window.myop_cta_handler('size-requested', {
|
|
157
|
-
width: 400,
|
|
158
|
-
height: 600,
|
|
159
|
-
required: true // true = content will be clipped without this size
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Request only width change
|
|
163
|
-
window.myop_cta_handler('size-requested', {
|
|
164
|
-
width: 500,
|
|
165
|
-
minWidth: 350,
|
|
166
|
-
maxWidth: 700
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
// Request based on content height
|
|
170
|
-
var contentHeight = document.getElementById('content').scrollHeight;
|
|
171
|
-
window.myop_cta_handler('size-requested', {
|
|
172
|
-
height: contentHeight + 40, // Add padding
|
|
173
|
-
required: false // Preference, not critical
|
|
174
|
-
});
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
### Size Request Payload
|
|
178
|
-
|
|
179
|
-
| Property | Type | Description |
|
|
180
|
-
|----------|------|-------------|
|
|
181
|
-
| `width` | `number \| null` | Desired width in px (`null` = no preference) |
|
|
182
|
-
| `height` | `number \| null` | Desired height in px (`null` = no preference) |
|
|
183
|
-
| `minWidth` | `number \| null` | Minimum acceptable width |
|
|
184
|
-
| `maxWidth` | `number \| null` | Maximum acceptable width |
|
|
185
|
-
| `minHeight` | `number \| null` | Minimum acceptable height |
|
|
186
|
-
| `maxHeight` | `number \| null` | Maximum acceptable height |
|
|
187
|
-
| `required` | `boolean` | `true` = content is clipped/broken without this size; `false` = preference only |
|
|
188
|
-
|
|
189
|
-
**Important:** The host application may choose to ignore size requests. Always design the component to be functional at any reasonable size, and use `required: true` sparingly.
|
|
190
|
-
|
|
191
154
|
## Common Mistakes
|
|
192
155
|
|
|
193
156
|
### Missing `min-height: 0` on flex children
|
|
@@ -207,15 +170,15 @@ window.myop_cta_handler('size-requested', {
|
|
|
207
170
|
}
|
|
208
171
|
```
|
|
209
172
|
|
|
210
|
-
### Body scrolling instead of internal scrolling
|
|
173
|
+
### Body scrolling instead of internal scrolling (fill mode)
|
|
211
174
|
|
|
212
175
|
```css
|
|
213
|
-
/* WRONG: Body scrolls, host can't control it */
|
|
176
|
+
/* WRONG: Body scrolls in fill mode, host can't control it */
|
|
214
177
|
html, body {
|
|
215
178
|
overflow: auto;
|
|
216
179
|
}
|
|
217
180
|
|
|
218
|
-
/* CORRECT: Body never scrolls, content region scrolls */
|
|
181
|
+
/* CORRECT (fill mode): Body never scrolls, content region scrolls */
|
|
219
182
|
html, body {
|
|
220
183
|
overflow: hidden;
|
|
221
184
|
}
|
|
@@ -224,6 +187,8 @@ html, body {
|
|
|
224
187
|
}
|
|
225
188
|
```
|
|
226
189
|
|
|
190
|
+
Note: In content mode, body overflow is not set — the host controls overflow.
|
|
191
|
+
|
|
227
192
|
### Forgetting `box-sizing: border-box`
|
|
228
193
|
|
|
229
194
|
```css
|
|
@@ -252,11 +217,16 @@ html, body {
|
|
|
252
217
|
height: 400px;
|
|
253
218
|
}
|
|
254
219
|
|
|
255
|
-
/* CORRECT: Fills whatever container the host provides */
|
|
220
|
+
/* CORRECT (fill mode): Fills whatever container the host provides */
|
|
256
221
|
#app-root {
|
|
257
222
|
width: 100%;
|
|
258
223
|
height: 100%;
|
|
259
224
|
}
|
|
225
|
+
|
|
226
|
+
/* CORRECT (content mode): Width fills, height is content-driven */
|
|
227
|
+
#app-root {
|
|
228
|
+
width: 100%;
|
|
229
|
+
}
|
|
260
230
|
```
|
|
261
231
|
|
|
262
232
|
### Size meta tag with invalid JSON
|
|
@@ -135,16 +135,6 @@ interface MyopCtaPayloads {
|
|
|
135
135
|
'page-changed': { page: number };
|
|
136
136
|
'tab-switched': { tabId: string };
|
|
137
137
|
|
|
138
|
-
// Standard Myop actions (always include if component needs resizing)
|
|
139
|
-
'size-requested': {
|
|
140
|
-
width?: number | null;
|
|
141
|
-
height?: number | null;
|
|
142
|
-
minWidth?: number | null;
|
|
143
|
-
maxWidth?: number | null;
|
|
144
|
-
minHeight?: number | null;
|
|
145
|
-
maxHeight?: number | null;
|
|
146
|
-
required?: boolean;
|
|
147
|
-
};
|
|
148
138
|
}
|
|
149
139
|
```
|
|
150
140
|
|
|
@@ -152,9 +142,8 @@ interface MyopCtaPayloads {
|
|
|
152
142
|
|
|
153
143
|
1. **Use kebab-case** for action names: `'item-selected'` not `'itemSelected'`
|
|
154
144
|
2. **Use `void`** for actions with no payload (e.g., `'refresh-requested': void`)
|
|
155
|
-
3. **
|
|
156
|
-
4. **
|
|
157
|
-
5. **Every action called in code must be defined here** - keep types in sync with implementation
|
|
145
|
+
3. **Payload must be JSON-serializable** - no functions, DOM elements, or class instances
|
|
146
|
+
4. **Every action called in code must be defined here** - keep types in sync with implementation
|
|
158
147
|
|
|
159
148
|
## Standard Declarations
|
|
160
149
|
|
|
@@ -205,12 +194,6 @@ interface MyopInitData {
|
|
|
205
194
|
|
|
206
195
|
interface MyopCtaPayloads {
|
|
207
196
|
'point-clicked': { datasetIndex: number; pointIndex: number; value: number };
|
|
208
|
-
'size-requested': {
|
|
209
|
-
width?: number | null; height?: number | null;
|
|
210
|
-
minWidth?: number | null; maxWidth?: number | null;
|
|
211
|
-
minHeight?: number | null; maxHeight?: number | null;
|
|
212
|
-
required?: boolean;
|
|
213
|
-
};
|
|
214
197
|
}
|
|
215
198
|
```
|
|
216
199
|
|
|
@@ -1,12 +1,144 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: myop-react-host
|
|
3
|
-
description: "Integrate Myop components into React applications using @myop/react. This skill covers MyopComponent props, typed event handlers, data binding, preloading, auto-generated packages, and local dev setup. Activate when the user is building a React app that hosts Myop components, or when you see @myop/react in package.json."
|
|
3
|
+
description: "Integrate Myop components into React applications using @myop/react. ALWAYS use the MyopComponent React component or auto-generated packages — NEVER create iframes manually. This skill covers MyopComponent props, typed event handlers, data binding, preloading, auto-generated packages, and local dev setup. Activate when the user is building a React app that hosts Myop components, or when you see @myop/react in package.json."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Myop React Host Integration
|
|
7
7
|
|
|
8
8
|
Embed Myop components in React applications using `@myop/react`.
|
|
9
9
|
|
|
10
|
+
## CRITICAL: Always Use the SDK
|
|
11
|
+
|
|
12
|
+
**NEVER create `<iframe>` elements manually. NEVER call `myop_init_interface()` or wire `myop_cta_handler()` directly.**
|
|
13
|
+
|
|
14
|
+
The `@myop/react` SDK handles all iframe management, communication, loading, error handling, sizing, and caching. Always use `<MyopComponent>` or an auto-generated package.
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// WRONG — never do this
|
|
18
|
+
<iframe ref={ref} src="/component.html" />
|
|
19
|
+
ref.current.contentWindow.myop_init_interface(data)
|
|
20
|
+
|
|
21
|
+
// CORRECT — always use the SDK
|
|
22
|
+
<MyopComponent componentId="abc-123" data={data} on={handler} />
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## End-to-End Workflow: React App with Myop Components
|
|
26
|
+
|
|
27
|
+
Each Myop component is a **separate project** in its own directory. You create them, develop them, push them to get a `componentId`, then reference that ID in your React host app.
|
|
28
|
+
|
|
29
|
+
### Step 1: Create component projects
|
|
30
|
+
|
|
31
|
+
Each component needs its own directory with `myop.config.json` + `index.html`:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Create first component
|
|
35
|
+
mkdir components/sidebar && cd components/sidebar
|
|
36
|
+
npx myop create # Scaffolds index.html + myop.config.json, starts dev server
|
|
37
|
+
# Build the component UI (see myop-component skill)
|
|
38
|
+
# Ctrl+C to stop dev server when done
|
|
39
|
+
|
|
40
|
+
# Create second component
|
|
41
|
+
cd ../
|
|
42
|
+
mkdir chart && cd chart
|
|
43
|
+
npx myop create
|
|
44
|
+
# Build this component too
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Step 2: Push components to get IDs
|
|
48
|
+
|
|
49
|
+
Each component must be pushed to the Myop platform to get a `componentId`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
cd components/sidebar
|
|
53
|
+
npx myop push # Uploads and assigns a componentId (UUID)
|
|
54
|
+
# Output: componentId is now in myop.config.json
|
|
55
|
+
|
|
56
|
+
cd ../chart
|
|
57
|
+
npx myop push
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
After push, each `myop.config.json` has a real `componentId` (UUID).
|
|
61
|
+
|
|
62
|
+
### Step 3: Set up the React host app
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd my-react-app
|
|
66
|
+
npm install @myop/react @myop/sdk
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Step 4: Use components in React
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { MyopComponent } from "@myop/react";
|
|
73
|
+
|
|
74
|
+
function App() {
|
|
75
|
+
return (
|
|
76
|
+
<div style={{ display: "flex", gap: 16 }}>
|
|
77
|
+
<MyopComponent
|
|
78
|
+
componentId="<sidebar-componentId-from-step-2>"
|
|
79
|
+
data={{ items: ["Home", "Settings"] }}
|
|
80
|
+
onItemSelected={({ itemId }) => console.log(itemId)}
|
|
81
|
+
style={{ width: 300, height: "100%" }}
|
|
82
|
+
/>
|
|
83
|
+
<MyopComponent
|
|
84
|
+
componentId="<chart-componentId-from-step-2>"
|
|
85
|
+
data={{ values: [10, 20, 30] }}
|
|
86
|
+
style={{ flex: 1 }}
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Working locally on existing components (componentId already in code)
|
|
94
|
+
|
|
95
|
+
When you find `componentId` values already used in the codebase and the developer wants to modify those components locally:
|
|
96
|
+
|
|
97
|
+
**Step A: Pull the component source**
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Create a directory for the component and pull it by ID
|
|
101
|
+
mkdir components/sidebar && cd components/sidebar
|
|
102
|
+
npx myop pull <componentId>
|
|
103
|
+
# Downloads index.html + creates myop.config.json with the componentId
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Step B: Start the local dev server**
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx myop dev # Serves component on port 9292 with HMR
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Step C: Point the React app to local dev server**
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { enableLocalDev } from "@myop/react";
|
|
116
|
+
enableLocalDev(); // All <MyopComponent> instances load from localhost:9292 instead of cloud
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Now edits to `index.html` in the component directory are reflected instantly in the React app.
|
|
120
|
+
|
|
121
|
+
**Step D: Push changes when done**
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
cd components/sidebar
|
|
125
|
+
npx myop push # Uploads updated component to the same componentId
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Remove or comment out `enableLocalDev()` to go back to loading from the Myop cloud.
|
|
129
|
+
|
|
130
|
+
**Full local dev flow (multiple components):**
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Pull all components you need to work on
|
|
134
|
+
mkdir -p components && cd components
|
|
135
|
+
npx myop pull <sidebar-id> -o sidebar/index.html
|
|
136
|
+
npx myop pull <chart-id> -o chart/index.html
|
|
137
|
+
|
|
138
|
+
# Start dev server (serves all components in subdirectories)
|
|
139
|
+
npx myop dev -m # Monorepo mode — select which components to serve
|
|
140
|
+
```
|
|
141
|
+
|
|
10
142
|
## When This Skill Activates
|
|
11
143
|
|
|
12
144
|
- `@myop/react` is in `package.json` dependencies
|
|
@@ -260,6 +392,16 @@ import type {
|
|
|
260
392
|
} from "@myop/react";
|
|
261
393
|
```
|
|
262
394
|
|
|
395
|
+
## Common Mistakes — WRONG vs CORRECT
|
|
396
|
+
|
|
397
|
+
| WRONG | CORRECT |
|
|
398
|
+
|-------|---------|
|
|
399
|
+
| Creating `<iframe>` elements manually | Using `<MyopComponent>` from `@myop/react` |
|
|
400
|
+
| Calling `myop_init_interface()` on iframe contentWindow | Passing `data` prop to `<MyopComponent>` |
|
|
401
|
+
| Wiring `myop_cta_handler` via refs | Using `on` or `onActionName` props |
|
|
402
|
+
| Loading component HTML from local file | Using `componentId` — SDK fetches from Myop cloud |
|
|
403
|
+
| Managing iframe lifecycle with useEffect | SDK handles load, error, cleanup automatically |
|
|
404
|
+
|
|
263
405
|
## Reference
|
|
264
406
|
|
|
265
407
|
- [Auto-Generated Packages](references/auto-generated-packages.md)
|
|
@@ -1,12 +1,130 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: myop-react-native-host
|
|
3
|
-
description: "Integrate Myop components into React Native applications using @myop/react-native.
|
|
3
|
+
description: "Integrate Myop components into React Native applications using @myop/react-native. ALWAYS use the MyopComponent component or auto-generated packages — NEVER create WebViews manually. Covers MyopComponent props, CTA event handling, data binding, preloading, auto-generated packages, native-specific features (scroll, zoom, selection control), and local dev setup. Activate when the user is building a React Native app that hosts Myop components, or when you see @myop/react-native in package.json."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Myop React Native Host Integration
|
|
7
7
|
|
|
8
8
|
Embed Myop components in React Native applications using `@myop/react-native`. Components render inside a WebView with a native bridge for CTA communication.
|
|
9
9
|
|
|
10
|
+
## CRITICAL: Always Use the SDK
|
|
11
|
+
|
|
12
|
+
**NEVER create `<WebView>` elements manually. NEVER call `myop_init_interface()` or wire `myop_cta_handler()` directly.**
|
|
13
|
+
|
|
14
|
+
The `@myop/react-native` SDK handles all WebView management, native bridge communication, loading, error handling, and caching. Always use `<MyopComponent>` or an auto-generated package.
|
|
15
|
+
|
|
16
|
+
```tsx
|
|
17
|
+
// WRONG — never do this
|
|
18
|
+
<WebView source={{ uri: componentUrl }} />
|
|
19
|
+
|
|
20
|
+
// CORRECT — always use the SDK
|
|
21
|
+
<MyopComponent componentId="abc-123" data={data} on={handler} />
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## End-to-End Workflow: React Native App with Myop Components
|
|
25
|
+
|
|
26
|
+
Each Myop component is a **separate project** in its own directory. You create them, develop them, push them to get a `componentId`, then reference that ID in your React Native host app.
|
|
27
|
+
|
|
28
|
+
### Step 1: Create component projects
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Each component gets its own directory
|
|
32
|
+
mkdir components/sidebar && cd components/sidebar
|
|
33
|
+
npx myop create # Scaffolds index.html + myop.config.json
|
|
34
|
+
# Build the component UI (see myop-component skill), then Ctrl+C
|
|
35
|
+
|
|
36
|
+
cd ../ && mkdir chart && cd chart
|
|
37
|
+
npx myop create
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Step 2: Push components to get IDs
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
cd components/sidebar
|
|
44
|
+
npx myop push # Uploads → componentId written to myop.config.json
|
|
45
|
+
|
|
46
|
+
cd ../chart
|
|
47
|
+
npx myop push
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Step 3: Use in your React Native app
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd my-rn-app
|
|
54
|
+
npm install @myop/react-native react-native-webview
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
import { MyopComponent } from "@myop/react-native";
|
|
59
|
+
|
|
60
|
+
function App() {
|
|
61
|
+
return (
|
|
62
|
+
<View style={{ flex: 1 }}>
|
|
63
|
+
<MyopComponent
|
|
64
|
+
componentId="<sidebar-componentId-from-step-2>"
|
|
65
|
+
data={{ items: ["Home", "Settings"] }}
|
|
66
|
+
on={(action, payload) => console.log(action, payload)}
|
|
67
|
+
style={{ height: 300 }}
|
|
68
|
+
/>
|
|
69
|
+
<MyopComponent
|
|
70
|
+
componentId="<chart-componentId-from-step-2>"
|
|
71
|
+
data={{ values: [10, 20, 30] }}
|
|
72
|
+
style={{ flex: 1 }}
|
|
73
|
+
/>
|
|
74
|
+
</View>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Working locally on existing components (componentId already in code)
|
|
80
|
+
|
|
81
|
+
When you find `componentId` values already used in the codebase and the developer wants to modify those components locally:
|
|
82
|
+
|
|
83
|
+
**Step A: Pull the component source**
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
mkdir components/sidebar && cd components/sidebar
|
|
87
|
+
npx myop pull <componentId>
|
|
88
|
+
# Downloads index.html + creates myop.config.json with the componentId
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Step B: Start the local dev server**
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
npx myop dev # Serves component on port 9292 with HMR
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Step C: Point the React Native app to local dev server**
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
import { enableLocalDev, setCloudRepositoryUrl } from "@myop/react-native";
|
|
101
|
+
enableLocalDev(); // All <MyopComponent> instances load from localhost:9292
|
|
102
|
+
|
|
103
|
+
// Android emulator requires explicit IP:
|
|
104
|
+
// setCloudRepositoryUrl("http://10.0.2.2:9292");
|
|
105
|
+
// Physical device — use your machine's IP:
|
|
106
|
+
// setCloudRepositoryUrl("http://192.168.1.100:9292");
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Now edits to `index.html` are reflected instantly in the React Native app.
|
|
110
|
+
|
|
111
|
+
**Step D: Push changes when done**
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npx myop push # Uploads updated component to the same componentId
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Remove or comment out `enableLocalDev()` to go back to loading from the Myop cloud.
|
|
118
|
+
|
|
119
|
+
**Multiple components:**
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
mkdir -p components && cd components
|
|
123
|
+
npx myop pull <sidebar-id> -o sidebar/index.html
|
|
124
|
+
npx myop pull <chart-id> -o chart/index.html
|
|
125
|
+
npx myop dev -m # Monorepo mode — select which components to serve
|
|
126
|
+
```
|
|
127
|
+
|
|
10
128
|
## When This Skill Activates
|
|
11
129
|
|
|
12
130
|
- `@myop/react-native` is in `package.json` dependencies
|