@myop/cli 0.1.40 → 0.1.41

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.
@@ -0,0 +1,270 @@
1
+ # Sizing and Layout
2
+
3
+ Myop components run inside a container managed by the host application. Proper sizing and layout ensures the component renders without clipping, scrollbars, or layout shifts.
4
+
5
+ ## Contents
6
+ - [Size Meta Tag](#size-meta-tag)
7
+ - [Required Base CSS](#required-base-css)
8
+ - [Layout Patterns](#layout-patterns)
9
+ - [Dynamic Size Requests](#dynamic-size-requests)
10
+ - [Common Mistakes](#common-mistakes)
11
+
12
+ ## Size Meta Tag
13
+
14
+ Every component should declare its preferred dimensions in a `<meta>` tag inside `<head>`:
15
+
16
+ ```html
17
+ <meta name="myop:size" content='{"width":"100%","height":"100%"}'>
18
+ ```
19
+
20
+ The host reads this BEFORE rendering the component, so the container can be sized correctly from the start (no layout shift).
21
+
22
+ ### Properties
23
+
24
+ All values are either a number (pixels) or the string `"100%"`:
25
+
26
+ | Property | Type | Description |
27
+ |----------|------|-------------|
28
+ | `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 |
30
+ | `minWidth` | `number` | Minimum acceptable width in px |
31
+ | `maxWidth` | `number` | Maximum useful width in px |
32
+ | `minHeight` | `number` | Minimum acceptable height in px |
33
+ | `maxHeight` | `number` | Maximum useful height in px |
34
+
35
+ ### Examples
36
+
37
+ ```html
38
+ <!-- Fill all available space (most common) -->
39
+ <meta name="myop:size" content='{"width":"100%","height":"100%"}'>
40
+
41
+ <!-- Fixed width sidebar component -->
42
+ <meta name="myop:size" content='{"width":300,"height":"100%","minWidth":200,"maxWidth":400}'>
43
+
44
+ <!-- Fixed height banner -->
45
+ <meta name="myop:size" content='{"width":"100%","height":80}'>
46
+
47
+ <!-- Card with constraints -->
48
+ <meta name="myop:size" content='{"width":350,"height":250,"minWidth":250,"maxWidth":500}'>
49
+ ```
50
+
51
+ ## Required Base CSS
52
+
53
+ Every Myop component MUST include this base CSS to prevent unexpected scrollbars and ensure the component fills its container:
54
+
55
+ ```css
56
+ * {
57
+ box-sizing: border-box;
58
+ margin: 0;
59
+ padding: 0;
60
+ }
61
+
62
+ html, body {
63
+ width: 100%;
64
+ height: 100%;
65
+ overflow: hidden; /* Component handles its own scrolling */
66
+ margin: 0;
67
+ padding: 0;
68
+ }
69
+
70
+ #app-root {
71
+ width: 100%;
72
+ height: 100%;
73
+ }
74
+ ```
75
+
76
+ ### Why `overflow: hidden` on body?
77
+
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.
79
+
80
+ ## Layout Patterns
81
+
82
+ ### Full-height Flexbox (recommended)
83
+
84
+ Most components need a fixed header/footer with a scrollable content area:
85
+
86
+ ```html
87
+ <div id="app-root">
88
+ <header class="header">Fixed Header</header>
89
+ <main class="content">
90
+ <!-- Scrollable content goes here -->
91
+ </main>
92
+ <footer class="footer">Fixed Footer</footer>
93
+ </div>
94
+ ```
95
+
96
+ ```css
97
+ #app-root {
98
+ display: flex;
99
+ flex-direction: column;
100
+ height: 100%;
101
+ }
102
+
103
+ .header, .footer {
104
+ flex-shrink: 0; /* Don't collapse */
105
+ padding: 12px 16px;
106
+ }
107
+
108
+ .content {
109
+ flex: 1; /* Fill remaining space */
110
+ overflow-y: auto; /* Scroll when content overflows */
111
+ min-height: 0; /* CRITICAL for flex scrolling */
112
+ }
113
+ ```
114
+
115
+ **The `min-height: 0` on the scrollable area is critical.** Without it, flex items default to `min-height: auto` which prevents overflow from working correctly.
116
+
117
+ ### Grid Layout
118
+
119
+ For dashboard-style components:
120
+
121
+ ```css
122
+ #app-root {
123
+ display: grid;
124
+ grid-template-columns: 1fr 1fr;
125
+ grid-template-rows: auto 1fr;
126
+ gap: 12px;
127
+ height: 100%;
128
+ padding: 16px;
129
+ }
130
+
131
+ .header { grid-column: 1 / -1; }
132
+ .panel { overflow-y: auto; min-height: 0; }
133
+ ```
134
+
135
+ ### Centered Content
136
+
137
+ For simple display components:
138
+
139
+ ```css
140
+ #app-root {
141
+ display: flex;
142
+ align-items: center;
143
+ justify-content: center;
144
+ height: 100%;
145
+ padding: 24px;
146
+ text-align: center;
147
+ }
148
+ ```
149
+
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
+ ## Common Mistakes
192
+
193
+ ### Missing `min-height: 0` on flex children
194
+
195
+ ```css
196
+ /* WRONG: Scrolling won't work */
197
+ .content {
198
+ flex: 1;
199
+ overflow-y: auto;
200
+ }
201
+
202
+ /* CORRECT: Enable flex overflow */
203
+ .content {
204
+ flex: 1;
205
+ overflow-y: auto;
206
+ min-height: 0;
207
+ }
208
+ ```
209
+
210
+ ### Body scrolling instead of internal scrolling
211
+
212
+ ```css
213
+ /* WRONG: Body scrolls, host can't control it */
214
+ html, body {
215
+ overflow: auto;
216
+ }
217
+
218
+ /* CORRECT: Body never scrolls, content region scrolls */
219
+ html, body {
220
+ overflow: hidden;
221
+ }
222
+ .content {
223
+ overflow-y: auto;
224
+ }
225
+ ```
226
+
227
+ ### Forgetting `box-sizing: border-box`
228
+
229
+ ```css
230
+ /* WRONG: Padding adds to width, causing overflow */
231
+ .panel {
232
+ width: 100%;
233
+ padding: 20px;
234
+ /* Actual width = 100% + 40px → overflow */
235
+ }
236
+
237
+ /* CORRECT: Padding included in width */
238
+ * { box-sizing: border-box; }
239
+ .panel {
240
+ width: 100%;
241
+ padding: 20px;
242
+ /* Actual width = 100% → perfect fit */
243
+ }
244
+ ```
245
+
246
+ ### Fixed pixel dimensions instead of fluid
247
+
248
+ ```css
249
+ /* WRONG: Breaks at different container sizes */
250
+ #app-root {
251
+ width: 500px;
252
+ height: 400px;
253
+ }
254
+
255
+ /* CORRECT: Fills whatever container the host provides */
256
+ #app-root {
257
+ width: 100%;
258
+ height: 100%;
259
+ }
260
+ ```
261
+
262
+ ### Size meta tag with invalid JSON
263
+
264
+ ```html
265
+ <!-- WRONG: Using double quotes inside double quotes -->
266
+ <meta name="myop:size" content="{"width":"100%"}">
267
+
268
+ <!-- CORRECT: Single quotes wrapping, double quotes inside -->
269
+ <meta name="myop:size" content='{"width":"100%","height":"100%"}'>
270
+ ```
@@ -0,0 +1,270 @@
1
+ # Type Definitions
2
+
3
+ Myop components declare their data contract using TypeScript interfaces inside a `<script type="myop/types">` block in the HTML `<head>`. These types are not executed by the browser - they serve as documentation for both AI agents and host application developers.
4
+
5
+ ## Contents
6
+ - [Where Types Go](#where-types-go)
7
+ - [MyopInitData](#myopinitdata)
8
+ - [MyopCtaPayloads](#myopctapayloads)
9
+ - [Standard Declarations](#standard-declarations)
10
+ - [Common Type Patterns](#common-type-patterns)
11
+ - [Rules](#rules)
12
+
13
+ ## Where Types Go
14
+
15
+ ```html
16
+ <head>
17
+ <!-- ... other head elements ... -->
18
+ <script type="myop/types">
19
+ // =========================================================================
20
+ // COMPONENT-SPECIFIC TYPE DEFINITIONS
21
+ // =========================================================================
22
+
23
+ interface MyopInitData {
24
+ // Define your data shape here
25
+ }
26
+
27
+ interface MyopCtaPayloads {
28
+ // Define your actions here
29
+ }
30
+
31
+ // =========================================================================
32
+ // DO NOT EDIT BELOW - Standard Myop type declarations
33
+ // =========================================================================
34
+
35
+ declare function myop_init_interface(): MyopInitData;
36
+ declare function myop_init_interface(data: MyopInitData): void;
37
+
38
+ declare function myop_cta_handler<K extends keyof MyopCtaPayloads>(
39
+ action: K,
40
+ payload: MyopCtaPayloads[K]
41
+ ): void;
42
+ </script>
43
+ </head>
44
+ ```
45
+
46
+ ## MyopInitData
47
+
48
+ Defines the shape of data the component receives via `myop_init_interface(data)`.
49
+
50
+ ### Simple Example
51
+
52
+ ```typescript
53
+ interface MyopInitData {
54
+ title: string;
55
+ description?: string;
56
+ count: number;
57
+ }
58
+ ```
59
+
60
+ ### Complex Example
61
+
62
+ ```typescript
63
+ interface MyopInitData {
64
+ user: {
65
+ id: string;
66
+ name: string;
67
+ avatar?: string;
68
+ role: 'admin' | 'editor' | 'viewer';
69
+ };
70
+ items: Array<{
71
+ id: string;
72
+ title: string;
73
+ status: 'active' | 'archived' | 'deleted';
74
+ metadata?: Record<string, string>;
75
+ createdAt: string;
76
+ }>;
77
+ config: {
78
+ theme: 'light' | 'dark';
79
+ locale: string;
80
+ pageSize: number;
81
+ features: {
82
+ canEdit: boolean;
83
+ canDelete: boolean;
84
+ canExport: boolean;
85
+ };
86
+ };
87
+ pagination?: {
88
+ page: number;
89
+ totalPages: number;
90
+ totalItems: number;
91
+ };
92
+ }
93
+ ```
94
+
95
+ ### Rules for MyopInitData
96
+
97
+ 1. **Must match actual data** - Every field you define must correspond to data actually passed by the host
98
+ 2. **Use `?` for optional fields** - Fields that may not always be present
99
+ 3. **Use union types for enums** - `'active' | 'archived'` not `string`
100
+ 4. **Use `Array<T>` for lists** - Be explicit about array item types
101
+ 5. **No `any` type** - Always specify the actual type
102
+
103
+ ## MyopCtaPayloads
104
+
105
+ Defines all actions the component can send via `myop_cta_handler(action, payload)`. Each key is an action ID, and its value is the payload type.
106
+
107
+ ### Simple Example
108
+
109
+ ```typescript
110
+ interface MyopCtaPayloads {
111
+ 'button-clicked': { buttonId: string };
112
+ 'form-submitted': { name: string; email: string };
113
+ 'refresh-requested': void;
114
+ }
115
+ ```
116
+
117
+ ### Complex Example
118
+
119
+ ```typescript
120
+ interface MyopCtaPayloads {
121
+ // User interaction actions
122
+ 'item-selected': { itemId: string; index: number };
123
+ 'item-deleted': { itemId: string; confirmed: boolean };
124
+ 'items-reordered': { orderedIds: string[] };
125
+
126
+ // Form actions
127
+ 'filter-changed': {
128
+ field: string;
129
+ operator: 'eq' | 'neq' | 'gt' | 'lt' | 'contains';
130
+ value: string | number | boolean;
131
+ };
132
+ 'search-submitted': { query: string; scope: 'all' | 'title' | 'content' };
133
+
134
+ // Navigation actions
135
+ 'page-changed': { page: number };
136
+ 'tab-switched': { tabId: string };
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
+ }
149
+ ```
150
+
151
+ ### Rules for MyopCtaPayloads
152
+
153
+ 1. **Use kebab-case** for action names: `'item-selected'` not `'itemSelected'`
154
+ 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
158
+
159
+ ## Standard Declarations
160
+
161
+ These lines MUST appear at the bottom of every `<script type="myop/types">` block. Do not modify them.
162
+
163
+ ```typescript
164
+ // DO NOT EDIT BELOW - Standard Myop type declarations
165
+
166
+ declare function myop_init_interface(): MyopInitData;
167
+ declare function myop_init_interface(data: MyopInitData): void;
168
+
169
+ declare function myop_cta_handler<K extends keyof MyopCtaPayloads>(
170
+ action: K,
171
+ payload: MyopCtaPayloads[K]
172
+ ): void;
173
+ ```
174
+
175
+ ## Common Type Patterns
176
+
177
+ ### List with Selection
178
+
179
+ ```typescript
180
+ interface MyopInitData {
181
+ items: Array<{ id: string; label: string; selected?: boolean }>;
182
+ multiSelect: boolean;
183
+ }
184
+
185
+ interface MyopCtaPayloads {
186
+ 'selection-changed': { selectedIds: string[] };
187
+ }
188
+ ```
189
+
190
+ ### Chart / Data Visualization
191
+
192
+ ```typescript
193
+ interface MyopInitData {
194
+ labels: string[];
195
+ datasets: Array<{
196
+ label: string;
197
+ data: number[];
198
+ color?: string;
199
+ }>;
200
+ options?: {
201
+ showLegend: boolean;
202
+ animate: boolean;
203
+ };
204
+ }
205
+
206
+ interface MyopCtaPayloads {
207
+ '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
+ }
215
+ ```
216
+
217
+ ### Form Component
218
+
219
+ ```typescript
220
+ interface MyopInitData {
221
+ fields: Array<{
222
+ name: string;
223
+ label: string;
224
+ type: 'text' | 'number' | 'email' | 'select' | 'checkbox';
225
+ value?: string | number | boolean;
226
+ options?: Array<{ label: string; value: string }>;
227
+ required?: boolean;
228
+ placeholder?: string;
229
+ }>;
230
+ submitLabel?: string;
231
+ }
232
+
233
+ interface MyopCtaPayloads {
234
+ 'form-submitted': Record<string, string | number | boolean>;
235
+ 'field-changed': { fieldName: string; value: string | number | boolean };
236
+ 'form-cancelled': void;
237
+ }
238
+ ```
239
+
240
+ ### Settings / Configuration Panel
241
+
242
+ ```typescript
243
+ interface MyopInitData {
244
+ settings: Record<string, {
245
+ label: string;
246
+ type: 'toggle' | 'select' | 'range';
247
+ value: boolean | string | number;
248
+ options?: string[];
249
+ min?: number;
250
+ max?: number;
251
+ }>;
252
+ }
253
+
254
+ interface MyopCtaPayloads {
255
+ 'setting-changed': { key: string; value: boolean | string | number };
256
+ 'settings-saved': Record<string, boolean | string | number>;
257
+ 'settings-reset': void;
258
+ }
259
+ ```
260
+
261
+ ## Rules
262
+
263
+ 1. **Keep types in sync** - If you change what `myop_init_interface` does with data, update `MyopInitData`. If you add a new `myop_cta_handler` call, add it to `MyopCtaPayloads`.
264
+
265
+ 2. **Types are documentation** - The `<script type="myop/types">` block is not parsed by the browser. It exists for:
266
+ - AI agents to understand the component contract
267
+ - Host developers to know what data to send and what actions to handle
268
+ - IDE tooling that may parse these types
269
+
270
+ 3. **One source of truth** - The type definitions should be the authoritative reference for the component's data contract. When in doubt, read the types first.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myop/cli",
3
- "version": "0.1.40",
3
+ "version": "0.1.41",
4
4
  "description": "Myop cli",
5
5
  "type": "module",
6
6
  "repository": {
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "scripts": {
27
27
  "try": "myop",
28
- "build": "vite build && chmod +x ./dist/myop-cli.js && mkdir -p ./dist/commands/dev/management-website && cp -R ./src/commands/dev/management-website/* ./dist/commands/dev/management-website/",
28
+ "build": "vite build && chmod +x ./dist/myop-cli.js && mkdir -p ./dist/commands/dev/management-website && cp -R ./src/commands/dev/management-website/* ./dist/commands/dev/management-website/ && mkdir -p ./dist/skills && cp -R ./src/skills/* ./dist/skills/",
29
29
  "release": "npm publish --access public",
30
30
  "cpTemplates": "cp -R ./node_modules/@myop/code-generator/dist/templates ./public"
31
31
  },