@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.
@@ -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 @myop/cli
17
+ npm install -g myop
18
+ # Or use without installing: npx myop <command>
18
19
  ```
19
20
 
20
- After installation, the `myop` command is available globally.
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":"100%"}'>
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
- <!-- Fill all available space (most common) -->
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 component -->
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
- Every Myop component MUST include this base CSS to prevent unexpected scrollbars and ensure the component fills its container:
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
- box-sizing: border-box;
58
- margin: 0;
59
- padding: 0;
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
- html, body {
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
- #app-root {
71
- width: 100%;
72
- height: 100%;
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, the component should manage scrolling internally with specific scrollable regions.
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. **Include `size-requested`** if the component ever needs to request a resize
156
- 4. **Payload must be JSON-serializable** - no functions, DOM elements, or class instances
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. This skill 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."
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