@walkeros/explorer 0.0.8 โ 0.3.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.
- package/LICENSE +42 -0
- package/README.md +646 -374
- package/dist/chunk-P5UDSGZL.mjs +18485 -0
- package/dist/chunk-P5UDSGZL.mjs.map +1 -0
- package/dist/index.d.cts +1248 -0
- package/dist/index.d.ts +1185 -180
- package/dist/index.js +31721 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +12983 -2300
- package/dist/index.mjs.map +1 -1
- package/dist/monaco-types-T3WXA7KH.mjs +34 -0
- package/dist/monaco-types-T3WXA7KH.mjs.map +1 -0
- package/dist/styles.css +4923 -0
- package/package.json +96 -55
- package/dist/examples/destination.html +0 -143
- package/dist/examples/index.html +0 -110
- package/dist/examples/livecode-js.html +0 -396
- package/dist/explorer.js +0 -2997
- package/dist/explorer.js.map +0 -1
- package/dist/index.cjs +0 -2528
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.mts +0 -243
- package/serve.js +0 -52
package/README.md
CHANGED
|
@@ -1,476 +1,748 @@
|
|
|
1
|
-
#
|
|
1
|
+
# walkerOS Explorer
|
|
2
2
|
|
|
3
|
-
Interactive
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Interactive React components for walkerOS documentation and exploration.
|
|
4
|
+
Provides ready-to-use demo components with Monaco Editor integration for live
|
|
5
|
+
code editing and event visualization.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Installation
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
experiences.
|
|
9
|
+
```bash
|
|
10
|
+
npm install @walkeros/explorer
|
|
11
|
+
```
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
## Usage
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
- ๐จ **Theme-aware** - Built-in light/dark theme support
|
|
21
|
-
- ๐ฑ **Responsive Design** - Works on all screen sizes
|
|
22
|
-
- โก **High Performance** - Optimized for speed and memory efficiency
|
|
23
|
-
- ๐งช **Fully Tested** - 101 comprehensive tests with Jest and JSDOM
|
|
15
|
+
```tsx
|
|
16
|
+
import { MappingDemo } from '@walkeros/explorer';
|
|
17
|
+
import '@walkeros/explorer/styles.css';
|
|
18
|
+
```
|
|
24
19
|
|
|
25
|
-
##
|
|
20
|
+
## Architecture
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
# In walkerOS monorepo (already included)
|
|
29
|
-
npm install
|
|
22
|
+
Components follow atomic design principles:
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
- **Atoms**: Basic UI elements (Box, Button, Header, ButtonGroup, Toggle, etc.)
|
|
25
|
+
- **Molecules**: Component combinations (AutoSelect, MappingEditor, TreeSidebar)
|
|
26
|
+
- **Organisms**: Complex components (MappingBox, CodeBox, MappingEditorTabs)
|
|
27
|
+
- **Demos**: Ready-to-use complete demos (MappingDemo, DestinationDemo)
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
### Design Principles
|
|
36
30
|
|
|
37
|
-
|
|
31
|
+
**Component Reusability**
|
|
38
32
|
|
|
39
|
-
|
|
33
|
+
- All components are composable and reusable
|
|
34
|
+
- Shared components over duplicate code
|
|
35
|
+
- Atomic design ensures scalability
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
- **Event Bus** - Global communication system
|
|
43
|
-
- **DOM Utilities** - Safe DOM manipulation and event handling
|
|
44
|
-
- **Performance Utilities** - Debounce, throttle, and memoization
|
|
45
|
-
- **Syntax Highlighting** - Code syntax detection and highlighting
|
|
37
|
+
**No Inline Styles**
|
|
46
38
|
|
|
47
|
-
|
|
39
|
+
- All styling via CSS classes and CSS variables
|
|
40
|
+
- Inline styles are forbidden
|
|
41
|
+
- Use CSS modules or SCSS for styling
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
- **Preview** - HTML preview with iframe sandboxing
|
|
51
|
-
- **ResultDisplay** - Execution results with multiple result types
|
|
43
|
+
**Theme Support Required**
|
|
52
44
|
|
|
53
|
-
|
|
45
|
+
- All components support light/dark themes
|
|
46
|
+
- Theme switching via `data-theme` attribute
|
|
47
|
+
- CSS variables automatically adapt
|
|
54
48
|
|
|
55
|
-
|
|
56
|
-
- **EventFlow** - walkerOS event visualization and debugging
|
|
57
|
-
- **Destination** - walkerOS destination testing and configuration
|
|
49
|
+
## Components
|
|
58
50
|
|
|
59
|
-
|
|
51
|
+
### Demos (Ready-to-Use)
|
|
60
52
|
|
|
61
|
-
|
|
53
|
+
#### MappingDemo
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
import {
|
|
65
|
-
createCodeEditor,
|
|
66
|
-
createPreview,
|
|
67
|
-
createResultDisplay,
|
|
68
|
-
} from '@walkeros/explorer';
|
|
55
|
+
Interactive three-panel editor: input โ config โ output transformation.
|
|
69
56
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
// Create a results display
|
|
85
|
-
const results = createResultDisplay('#results', {
|
|
86
|
-
maxResults: 100,
|
|
87
|
-
});
|
|
57
|
+
```tsx
|
|
58
|
+
<MappingDemo
|
|
59
|
+
input='{"name": "example"}'
|
|
60
|
+
config='{"transform": "uppercase"}'
|
|
61
|
+
labelInput="Event"
|
|
62
|
+
labelConfig="Rules"
|
|
63
|
+
labelOutput="Result"
|
|
64
|
+
fn={async (input, config) => {
|
|
65
|
+
const data = JSON.parse(input);
|
|
66
|
+
const rules = JSON.parse(config);
|
|
67
|
+
return JSON.stringify(result, null, 2);
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
88
70
|
```
|
|
89
71
|
|
|
90
|
-
|
|
72
|
+
#### DestinationDemo
|
|
91
73
|
|
|
92
|
-
|
|
93
|
-
import {
|
|
94
|
-
createLiveCode,
|
|
95
|
-
createEventFlow,
|
|
96
|
-
createDestination,
|
|
97
|
-
} from '@walkeros/explorer';
|
|
74
|
+
Interactive destination testing with event processing and mapping. Automatically captures destination.push() calls and displays the output.
|
|
98
75
|
|
|
99
|
-
|
|
100
|
-
const liveCode = createLiveCode('#livecode', {
|
|
101
|
-
layout: 'horizontal',
|
|
102
|
-
showTabs: true,
|
|
103
|
-
initialHTML: '<h1>Hello World</h1>',
|
|
104
|
-
initialCSS: 'h1 { color: blue; }',
|
|
105
|
-
initialJS: 'console.log("Hello");',
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Event flow visualization
|
|
109
|
-
const eventFlow = createEventFlow('#events', {
|
|
110
|
-
maxEvents: 1000,
|
|
111
|
-
showMetrics: true,
|
|
112
|
-
onEventCapture: (event) => console.log('Event:', event),
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Destination testing
|
|
116
|
-
const destination = createDestination('#destination', {
|
|
117
|
-
showTemplates: true,
|
|
118
|
-
enableValidation: true,
|
|
119
|
-
});
|
|
120
|
-
```
|
|
76
|
+
**Simple Usage** (Recommended):
|
|
121
77
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```typescript
|
|
129
|
-
const editor = createCodeEditor(elementOrSelector, {
|
|
130
|
-
language: 'javascript' | 'typescript' | 'html' | 'css' | 'json' | 'markdown',
|
|
131
|
-
value: string,
|
|
132
|
-
height: string,
|
|
133
|
-
readOnly: boolean,
|
|
134
|
-
onChange: (value: string, language: string) => void
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
// API Methods
|
|
138
|
-
editor.getValue() // Get current code
|
|
139
|
-
editor.setValue(code) // Set code content
|
|
140
|
-
editor.getLanguage() // Get current language
|
|
141
|
-
editor.setLanguage(lang) // Set programming language
|
|
142
|
-
editor.focus() // Focus the editor
|
|
143
|
-
editor.selectAll() // Select all content
|
|
144
|
-
editor.insertText(text) // Insert text at cursor
|
|
145
|
-
```
|
|
78
|
+
```tsx
|
|
79
|
+
import { DestinationDemo } from '@walkeros/explorer';
|
|
80
|
+
import { getEvent } from '@walkeros/core';
|
|
81
|
+
import destinationPlausible from '@walkeros/web-destination-plausible';
|
|
82
|
+
import { examples } from '@walkeros/web-destination-plausible';
|
|
146
83
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
onLoad: (iframe) => void,
|
|
158
|
-
onError: (error) => void
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// API Methods
|
|
162
|
-
preview.setHTML(html) // Set HTML content
|
|
163
|
-
preview.getHTML() // Get current HTML
|
|
164
|
-
preview.refresh() // Refresh preview
|
|
165
|
-
preview.executeScript(script) // Execute script in preview
|
|
166
|
-
preview.injectCSS(css) // Inject CSS into preview
|
|
84
|
+
// Attach examples to destination for auto-capture
|
|
85
|
+
const destination = { ...destinationPlausible, examples };
|
|
86
|
+
|
|
87
|
+
<DestinationDemo
|
|
88
|
+
destination={destination}
|
|
89
|
+
event={getEvent('order complete')}
|
|
90
|
+
mapping={examples.mapping.purchase}
|
|
91
|
+
settings={{ domain: 'elbwalker.com' }}
|
|
92
|
+
generic={true}
|
|
93
|
+
/>
|
|
167
94
|
```
|
|
168
95
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
96
|
+
The component auto-detects `destination.examples.env.push` and uses it to capture function calls.
|
|
97
|
+
|
|
98
|
+
**Props:**
|
|
99
|
+
- `destination`: Destination instance with `examples.env.push` export
|
|
100
|
+
- `event`: walkerOS event to process
|
|
101
|
+
- `mapping`: Optional mapping rules (object or JSON string)
|
|
102
|
+
- `settings`: Destination-specific settings
|
|
103
|
+
- `generic`: If true, wraps mapping in `{ '*': { '*': mapping } }`
|
|
104
|
+
- `labelEvent`: Label for event panel (default: 'Event')
|
|
105
|
+
- `labelMapping`: Label for mapping panel (default: 'Mapping')
|
|
106
|
+
- `labelOutput`: Label for output panel (default: 'Result')
|
|
107
|
+
|
|
108
|
+
#### DestinationInitDemo
|
|
109
|
+
|
|
110
|
+
Interactive destination initialization testing. Automatically captures destination.init() calls and displays the output (script loading, configuration calls).
|
|
111
|
+
|
|
112
|
+
**Simple Usage** (Recommended):
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import { DestinationInitDemo } from '@walkeros/explorer';
|
|
116
|
+
import destinationGtag from '@walkeros/web-destination-gtag';
|
|
117
|
+
import { examples } from '@walkeros/web-destination-gtag';
|
|
118
|
+
|
|
119
|
+
// Attach examples to destination for auto-capture
|
|
120
|
+
const destination = { ...destinationGtag, examples };
|
|
121
|
+
|
|
122
|
+
<DestinationInitDemo
|
|
123
|
+
destination={destination}
|
|
124
|
+
settings={{
|
|
125
|
+
ga4: {
|
|
126
|
+
measurementId: 'G-XXXXXXXXXX',
|
|
127
|
+
debug: false,
|
|
128
|
+
pageview: false,
|
|
129
|
+
},
|
|
130
|
+
}}
|
|
131
|
+
/>
|
|
188
132
|
```
|
|
189
133
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
134
|
+
The component auto-detects `destination.examples.env.init` and uses it to capture function calls during initialization.
|
|
135
|
+
|
|
136
|
+
**Props:**
|
|
137
|
+
- `destination`: Destination instance with `examples.env.init` export
|
|
138
|
+
- `settings`: Destination-specific settings (object or JSON string)
|
|
139
|
+
- `labelSettings`: Label for settings panel (default: 'Settings')
|
|
140
|
+
- `labelOutput`: Label for output panel (default: 'Result')
|
|
141
|
+
|
|
142
|
+
**Use Cases:**
|
|
143
|
+
- Testing destination initialization (script loading, gtag config calls)
|
|
144
|
+
- Documenting initialization behavior
|
|
145
|
+
- Debugging destination setup
|
|
146
|
+
|
|
147
|
+
#### PromotionPlayground
|
|
148
|
+
|
|
149
|
+
Interactive playground for walkerOS promotion events (used in documentation).
|
|
150
|
+
|
|
151
|
+
### Organisms
|
|
152
|
+
|
|
153
|
+
#### MappingBox
|
|
154
|
+
|
|
155
|
+
Visual mapping configuration editor with code view toggle.
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
import { MappingBox } from '@walkeros/explorer';
|
|
159
|
+
|
|
160
|
+
<MappingBox
|
|
161
|
+
mapping={{
|
|
162
|
+
product: {
|
|
163
|
+
view: { name: 'view_item', data: { map: { value: 'data.price' } } },
|
|
164
|
+
},
|
|
165
|
+
}}
|
|
166
|
+
onMappingChange={setMapping}
|
|
167
|
+
label="GA4 Mapping"
|
|
168
|
+
useNewEditor={true}
|
|
169
|
+
showTree={true}
|
|
170
|
+
/>;
|
|
217
171
|
```
|
|
218
172
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
eventFlow.getMetrics() // Get performance metrics
|
|
173
|
+
Features:
|
|
174
|
+
|
|
175
|
+
- Visual/Code view toggle
|
|
176
|
+
- Tab-based navigation
|
|
177
|
+
- Tree sidebar with breadcrumbs
|
|
178
|
+
- Property-focused editing panels
|
|
179
|
+
- RJSF-based forms with custom widgets
|
|
180
|
+
|
|
181
|
+
#### MappingEditorTabs
|
|
182
|
+
|
|
183
|
+
Advanced tab-based mapping editor with tree navigation.
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
import { MappingEditorTabs } from '@walkeros/explorer';
|
|
187
|
+
|
|
188
|
+
<MappingEditorTabs
|
|
189
|
+
initialMapping={config}
|
|
190
|
+
onChange={handleChange}
|
|
191
|
+
layout="responsive"
|
|
192
|
+
showTree={true}
|
|
193
|
+
/>;
|
|
241
194
|
```
|
|
242
195
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
destination.importConfig(json) // Import config from JSON
|
|
264
|
-
destination.loadTemplate(name) // Load predefined template
|
|
265
|
-
destination.getAvailableTemplates() // Get available templates
|
|
196
|
+
Layouts:
|
|
197
|
+
|
|
198
|
+
- `compact`: Single column, mobile-optimized (< 800px)
|
|
199
|
+
- `medium`: Two columns with collapsible sidebar (800-1200px)
|
|
200
|
+
- `wide`: Three columns with persistent sidebar (> 1200px)
|
|
201
|
+
- `responsive`: Auto-detects based on viewport
|
|
202
|
+
|
|
203
|
+
#### LiveCode
|
|
204
|
+
|
|
205
|
+
Generic live code execution with input/config/output panels.
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
<LiveCode
|
|
209
|
+
input={{ name: 'test event', data: {} }}
|
|
210
|
+
config={{ mapping: 'rules' }}
|
|
211
|
+
fn={async (input, config, log) => {
|
|
212
|
+
log('Processing...', input);
|
|
213
|
+
}}
|
|
214
|
+
fnName="myFunction"
|
|
215
|
+
/>
|
|
266
216
|
```
|
|
267
217
|
|
|
268
|
-
|
|
218
|
+
#### CodePanel
|
|
269
219
|
|
|
270
|
-
|
|
220
|
+
Monaco editor with label and formatting controls.
|
|
271
221
|
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
|
|
222
|
+
```tsx
|
|
223
|
+
<CodePanel
|
|
224
|
+
label="Configuration"
|
|
225
|
+
value='{"key": "value"}'
|
|
226
|
+
language="json"
|
|
227
|
+
onChange={setValue}
|
|
228
|
+
/>
|
|
229
|
+
```
|
|
275
230
|
|
|
276
|
-
|
|
277
|
-
npm run test:watch
|
|
231
|
+
#### BrowserBox
|
|
278
232
|
|
|
279
|
-
|
|
280
|
-
npm run test foundation.test.ts
|
|
233
|
+
Multi-tab code editor (HTML/CSS/JS) with live preview.
|
|
281
234
|
|
|
282
|
-
|
|
283
|
-
|
|
235
|
+
```tsx
|
|
236
|
+
<BrowserBox
|
|
237
|
+
html="<div>Hello</div>"
|
|
238
|
+
css="div { color: red; }"
|
|
239
|
+
js="console.log('loaded')"
|
|
240
|
+
onHtmlChange={setHtml}
|
|
241
|
+
showPreview={true}
|
|
242
|
+
initialTab="preview"
|
|
243
|
+
/>
|
|
284
244
|
```
|
|
285
245
|
|
|
286
|
-
|
|
246
|
+
#### CollectorBox
|
|
247
|
+
|
|
248
|
+
Displays collector processing with mapping and destination output.
|
|
287
249
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
250
|
+
```tsx
|
|
251
|
+
<CollectorBox
|
|
252
|
+
event='{"name": "page view"}'
|
|
253
|
+
mapping='{"page": {"view": {"name": "pageview"}}}'
|
|
254
|
+
destination={destination}
|
|
255
|
+
/>
|
|
256
|
+
```
|
|
293
257
|
|
|
294
|
-
|
|
258
|
+
### Molecules
|
|
295
259
|
|
|
296
|
-
|
|
260
|
+
#### CodeEditor
|
|
297
261
|
|
|
298
|
-
|
|
262
|
+
Monaco Editor wrapper.
|
|
299
263
|
|
|
300
|
-
```
|
|
301
|
-
|
|
302
|
-
|
|
264
|
+
```tsx
|
|
265
|
+
<CodeEditor
|
|
266
|
+
value="console.log('hello')"
|
|
267
|
+
language="javascript"
|
|
268
|
+
onChange={setValue}
|
|
269
|
+
/>
|
|
303
270
|
```
|
|
304
271
|
|
|
305
|
-
|
|
272
|
+
#### Preview
|
|
306
273
|
|
|
307
|
-
|
|
274
|
+
HTML preview in isolated iframe with walkerOS event capture.
|
|
308
275
|
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
|
|
276
|
+
```tsx
|
|
277
|
+
<Preview
|
|
278
|
+
html="<div data-elb='product'>Item</div>"
|
|
279
|
+
css="div { padding: 20px; }"
|
|
280
|
+
onEvent={(event) => console.log(event)}
|
|
281
|
+
/>
|
|
312
282
|
```
|
|
313
283
|
|
|
314
|
-
|
|
284
|
+
#### MappingTreeSidebar
|
|
315
285
|
|
|
316
|
-
|
|
286
|
+
Hierarchical tree view for mapping navigation.
|
|
317
287
|
|
|
318
|
-
|
|
288
|
+
```tsx
|
|
289
|
+
import { MappingTreeSidebar } from '@walkeros/explorer';
|
|
319
290
|
|
|
291
|
+
<MappingTreeSidebar
|
|
292
|
+
config={mappingConfig}
|
|
293
|
+
currentPath={['product', 'view']}
|
|
294
|
+
expandedPaths={expandedPaths}
|
|
295
|
+
visible={true}
|
|
296
|
+
onToggle={handleToggle}
|
|
297
|
+
onNavigate={handleNavigate}
|
|
298
|
+
onAddAction={handleAddAction}
|
|
299
|
+
onAddEntity={handleAddEntity}
|
|
300
|
+
/>;
|
|
320
301
|
```
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
โ โโโ syntax.ts # Syntax highlighting
|
|
336
|
-
โโโ __tests__/ # Test suites
|
|
337
|
-
โโโ foundation.test.ts
|
|
338
|
-
โโโ phase2-components.test.ts
|
|
339
|
-
โโโ phase3-composites.test.ts
|
|
302
|
+
|
|
303
|
+
#### AutoSelect
|
|
304
|
+
|
|
305
|
+
Dropdown with autocomplete for key selection.
|
|
306
|
+
|
|
307
|
+
```tsx
|
|
308
|
+
import { AutoSelect } from '@walkeros/explorer';
|
|
309
|
+
|
|
310
|
+
<AutoSelect
|
|
311
|
+
value={selectedKey}
|
|
312
|
+
options={['data.id', 'data.name', 'user.email']}
|
|
313
|
+
onChange={setValue}
|
|
314
|
+
placeholder="Select property..."
|
|
315
|
+
/>;
|
|
340
316
|
```
|
|
341
317
|
|
|
342
|
-
###
|
|
318
|
+
### Atoms
|
|
343
319
|
|
|
344
|
-
|
|
345
|
-
# Development build with watch
|
|
346
|
-
npm run dev
|
|
320
|
+
#### Box, Header, Button, ButtonGroup
|
|
347
321
|
|
|
348
|
-
|
|
349
|
-
npm run build
|
|
322
|
+
Basic UI building blocks. See exported types for prop details.
|
|
350
323
|
|
|
351
|
-
|
|
352
|
-
|
|
324
|
+
```tsx
|
|
325
|
+
import { Box, Button, ButtonGroup } from '@walkeros/explorer';
|
|
353
326
|
|
|
354
|
-
|
|
355
|
-
|
|
327
|
+
<Box header="Title" resizable={true}>
|
|
328
|
+
<ButtonGroup
|
|
329
|
+
buttons={[
|
|
330
|
+
{ label: 'Option 1', value: '1', active: true },
|
|
331
|
+
{ label: 'Option 2', value: '2', active: false },
|
|
332
|
+
]}
|
|
333
|
+
onButtonClick={handleClick}
|
|
334
|
+
/>
|
|
335
|
+
</Box>;
|
|
356
336
|
```
|
|
357
337
|
|
|
358
|
-
|
|
338
|
+
#### Toggle
|
|
339
|
+
|
|
340
|
+
Theme-aware toggle switch component.
|
|
359
341
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
- **Jest** with JSDOM for testing
|
|
363
|
-
- **ESLint** for code quality
|
|
342
|
+
```tsx
|
|
343
|
+
import { Toggle } from '@walkeros/explorer';
|
|
364
344
|
|
|
365
|
-
|
|
345
|
+
<Toggle checked={isEnabled} onChange={setIsEnabled} label="Enable feature" />;
|
|
346
|
+
```
|
|
366
347
|
|
|
367
|
-
###
|
|
348
|
+
### Helpers
|
|
368
349
|
|
|
369
|
-
|
|
350
|
+
#### Destination Creators
|
|
370
351
|
|
|
371
|
-
```
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
352
|
+
```tsx
|
|
353
|
+
import {
|
|
354
|
+
createGtagDestination,
|
|
355
|
+
createFbqDestination,
|
|
356
|
+
createPlausibleDestination,
|
|
357
|
+
} from '@walkeros/explorer';
|
|
358
|
+
|
|
359
|
+
const gtag = createGtagDestination();
|
|
360
|
+
gtag.env = { elb: (output) => console.log(output) };
|
|
377
361
|
```
|
|
378
362
|
|
|
379
|
-
|
|
363
|
+
## Styling
|
|
364
|
+
|
|
365
|
+
**Complete styling documentation:** [STYLE.md](./STYLE.md)
|
|
380
366
|
|
|
381
|
-
|
|
367
|
+
### Quick Start
|
|
382
368
|
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
showMetrics: true,
|
|
386
|
-
onEventCapture: (event) => {
|
|
387
|
-
console.log('Event captured:', event);
|
|
388
|
-
// Send to analytics, log to server, etc.
|
|
389
|
-
}
|
|
390
|
-
});
|
|
369
|
+
```tsx
|
|
370
|
+
import '@walkeros/explorer/styles.css';
|
|
391
371
|
```
|
|
392
372
|
|
|
393
|
-
|
|
373
|
+
```html
|
|
374
|
+
<!-- Theme switching -->
|
|
375
|
+
<html data-theme="dark">...</html>
|
|
376
|
+
```
|
|
394
377
|
|
|
395
|
-
|
|
378
|
+
### Customization
|
|
396
379
|
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
});
|
|
380
|
+
```css
|
|
381
|
+
.my-app .elb-explorer {
|
|
382
|
+
--color-button-primary: #ff6b35;
|
|
383
|
+
--bg-box: #fafafa;
|
|
384
|
+
--font-size-base: 16px;
|
|
385
|
+
}
|
|
404
386
|
```
|
|
405
387
|
|
|
406
|
-
|
|
388
|
+
**See [STYLE.md](./STYLE.md) for:**
|
|
389
|
+
- Complete Theme Variables Reference (all CSS variables)
|
|
390
|
+
- Grid System (height modes, implementation)
|
|
391
|
+
- Monaco Editor (theming, tokens, IntelliSense)
|
|
392
|
+
- SCSS Architecture & Design Rules
|
|
393
|
+
- Common Tasks & Troubleshooting
|
|
394
|
+
|
|
395
|
+
### Component Styling Guidelines
|
|
396
|
+
|
|
397
|
+
When contributing components:
|
|
407
398
|
|
|
408
|
-
|
|
409
|
-
- **[Testing Guide](./TESTING.md)** - Testing strategy and best practices
|
|
410
|
-
- **[Development Guidelines](./DEVELOPMENT_GUIDELINES.md)** - Development best
|
|
411
|
-
practices
|
|
399
|
+
**โ
DO:**
|
|
412
400
|
|
|
413
|
-
|
|
401
|
+
- Use CSS classes with the `elb-` prefix
|
|
402
|
+
- Use CSS variables for colors, spacing, typography
|
|
403
|
+
- Support both light and dark themes
|
|
404
|
+
- Use responsive design patterns
|
|
405
|
+
- Reuse existing components and styles
|
|
414
406
|
|
|
415
|
-
|
|
407
|
+
**โ DON'T:**
|
|
416
408
|
|
|
417
|
-
-
|
|
418
|
-
-
|
|
419
|
-
-
|
|
420
|
-
-
|
|
409
|
+
- Use inline `style` attributes
|
|
410
|
+
- Hardcode colors or spacing values
|
|
411
|
+
- Create duplicate components
|
|
412
|
+
- Use theme-specific selectors in component files
|
|
413
|
+
- Use magic numbers (use CSS variables instead)
|
|
421
414
|
|
|
422
|
-
###
|
|
415
|
+
### SCSS Architecture (CRITICAL - Must Follow Exactly)
|
|
423
416
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
- **Maintenance** - Clean, well-organized codebase
|
|
417
|
+
**IMPORTANCE**: The explorer uses a strict, modular SCSS architecture. All new
|
|
418
|
+
components MUST follow the established patterns. Non-compliance breaks the
|
|
419
|
+
design system.
|
|
428
420
|
|
|
429
|
-
|
|
421
|
+
**Architecture:**
|
|
430
422
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
423
|
+
```
|
|
424
|
+
src/styles/
|
|
425
|
+
โโโ index.scss # Main entry point (import new components here)
|
|
426
|
+
โโโ theme/
|
|
427
|
+
โ โโโ _tokens.scss # SCSS tokens ($spacing-md: 12px, $radius-sm: 3px)
|
|
428
|
+
โ โโโ _variables.scss # CSS variables (--bg-input, --color-text, etc.)
|
|
429
|
+
โ โโโ _dark.scss # Dark theme overrides
|
|
430
|
+
โโโ foundation/
|
|
431
|
+
โ โโโ _reset.scss
|
|
432
|
+
โ โโโ _typography.scss
|
|
433
|
+
โ โโโ _layout.scss # Grid/flex mixins
|
|
434
|
+
โ โโโ _spacing.scss # Spacing mixins
|
|
435
|
+
โ โโโ _responsive.scss # Breakpoint mixins
|
|
436
|
+
โโโ components/
|
|
437
|
+
โโโ atoms/ # _button.scss, _consent-widget.scss, etc.
|
|
438
|
+
โโโ molecules/ # _rjsf-form.scss, _mapping-editor.scss, etc.
|
|
439
|
+
โโโ organisms/ # _box.scss, _mapping-box.scss, etc.
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### SCSS Compliance Rules (MANDATORY)
|
|
443
|
+
|
|
444
|
+
**โ
DO:**
|
|
445
|
+
|
|
446
|
+
1. **Use ONLY defined CSS variables** from `theme/_variables.scss`:
|
|
447
|
+
- `--bg-input`, `--border-input`, `--radius-button` (standard form elements)
|
|
448
|
+
- `--color-text`, `--color-text-muted`, `--color-text-label` (typography)
|
|
449
|
+
- `--font-family-base`, `--font-mono` (fonts)
|
|
450
|
+
- `--font-size-base` (base font size)
|
|
451
|
+
2. **Use `calc()` for font size variations**:
|
|
452
|
+
- Small text: `calc(var(--font-size-base) - 1px)` (NOT `--font-size-sm`)
|
|
453
|
+
- Tiny text: `calc(var(--font-size-base) - 2px)` (NOT `--font-size-xs`)
|
|
454
|
+
3. **Follow BEM naming**: `elb-{component}-{element}--{modifier}`
|
|
455
|
+
- Example: `.elb-settings-widget-wrapper`, `.elb-settings-widget-form`
|
|
456
|
+
4. **Use standard gaps**: `12px` for vertical spacing in flex/grid layouts
|
|
457
|
+
5. **One file per component**: Create `_component-name.scss` in appropriate
|
|
458
|
+
directory
|
|
459
|
+
6. **Import alphabetically**: Add `@use './components/atoms/your-widget';` in
|
|
460
|
+
`index.scss`
|
|
461
|
+
|
|
462
|
+
**โ DON'T:**
|
|
463
|
+
|
|
464
|
+
1. **NEVER use undefined CSS variables**:
|
|
465
|
+
- โ `--bg-secondary`, `--bg-code`, `--border-subtle`, `--radius-base` (don't
|
|
466
|
+
exist)
|
|
467
|
+
- โ `--font-size-sm`, `--font-size-xs` (don't exist as CSS variables)
|
|
468
|
+
- โ `--font-family-mono` (should be `--font-mono`)
|
|
469
|
+
2. **NEVER hardcode values** that have CSS variable equivalents
|
|
470
|
+
3. **NEVER skip the wrapper pattern**: All widgets need `elb-rjsf-widget` โ
|
|
471
|
+
`elb-{name}-widget-wrapper`
|
|
472
|
+
4. **NEVER create duplicate styles** - check existing components first
|
|
473
|
+
|
|
474
|
+
#### CSS Variable Reference (Commonly Used)
|
|
475
|
+
|
|
476
|
+
```scss
|
|
477
|
+
// Backgrounds
|
|
478
|
+
--bg-input: #ffffff; // Form inputs, fallback containers
|
|
479
|
+
--bg-input-hover: #f9f9f9; // Hover states
|
|
480
|
+
|
|
481
|
+
// Borders
|
|
482
|
+
--border-input: #d1d5db; // Form inputs, containers
|
|
483
|
+
--border-input-focus: #3b82f6; // Focus states
|
|
484
|
+
|
|
485
|
+
// Border Radius
|
|
486
|
+
--radius-button: 3px; // Forms, small elements
|
|
487
|
+
--radius-box: 4px; // Boxes, containers
|
|
488
|
+
|
|
489
|
+
// Typography
|
|
490
|
+
--color-text: #000; // Primary text
|
|
491
|
+
--color-text-muted: #666; // Secondary/hint text
|
|
492
|
+
--color-text-label: #424242; // Labels
|
|
493
|
+
--font-family-base: system-ui, ...; // Body text
|
|
494
|
+
--font-mono: 'SF Mono', ...; // Code blocks
|
|
495
|
+
--font-size-base: 14px; // Base size
|
|
496
|
+
|
|
497
|
+
// Buttons
|
|
498
|
+
--color-button-primary: #3b82f6; // Primary actions
|
|
499
|
+
--color-button-danger: #ef4444; // Destructive actions
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
**Full list**: See `src/styles/theme/_variables.scss`
|
|
503
|
+
|
|
504
|
+
#### Example: Widget SCSS (Correct Pattern)
|
|
505
|
+
|
|
506
|
+
```scss
|
|
507
|
+
// _my-widget.scss
|
|
508
|
+
.elb-my-widget-wrapper {
|
|
509
|
+
width: 100%;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.elb-my-widget-form {
|
|
513
|
+
display: flex;
|
|
514
|
+
flex-direction: column;
|
|
515
|
+
gap: 12px; // Standard gap
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
.elb-my-widget-hint {
|
|
519
|
+
font-size: calc(var(--font-size-base) - 1px); // โ
Correct
|
|
520
|
+
color: var(--color-text-muted); // โ
Defined variable
|
|
521
|
+
margin: 0;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
.elb-my-widget-code {
|
|
525
|
+
padding: 12px;
|
|
526
|
+
background-color: var(--bg-input); // โ
Defined variable
|
|
527
|
+
border: 1px solid var(--border-input); // โ
Defined variable
|
|
528
|
+
border-radius: var(--radius-button); // โ
Defined variable
|
|
529
|
+
font-family: var(--font-mono); // โ
Correct variable name
|
|
530
|
+
}
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
#### Verification Checklist
|
|
534
|
+
|
|
535
|
+
Before submitting SCSS changes:
|
|
536
|
+
|
|
537
|
+
- [ ] All CSS variables exist in `theme/_variables.scss`
|
|
538
|
+
- [ ] No hardcoded colors, spacing, or font sizes (use CSS variables)
|
|
539
|
+
- [ ] BEM naming convention followed (`elb-{component}-{element}`)
|
|
540
|
+
- [ ] File imported in `index.scss` (alphabetical order)
|
|
541
|
+
- [ ] Build succeeds: `npm run build`
|
|
542
|
+
- [ ] Component matches pattern of similar existing components
|
|
543
|
+
- [ ] Tested in both light and dark themes
|
|
544
|
+
|
|
545
|
+
See [LAYOUT.md](./LAYOUT.md) for the complete SCSS migration plan.
|
|
546
|
+
|
|
547
|
+
## Development
|
|
548
|
+
|
|
549
|
+
```bash
|
|
550
|
+
npm install # Install dependencies
|
|
551
|
+
npm run start # Start Vite dev server
|
|
552
|
+
npm test # Run tests
|
|
553
|
+
npm run build # Build package
|
|
554
|
+
npm run lint # Lint code
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
### Contributing Components
|
|
558
|
+
|
|
559
|
+
Follow these principles when creating new components:
|
|
560
|
+
|
|
561
|
+
1. **Atomic Design**: Place components in correct directory
|
|
562
|
+
(atoms/molecules/organisms)
|
|
563
|
+
2. **Reusability**: Extract shared logic into hooks, shared styles into SCSS
|
|
564
|
+
modules
|
|
565
|
+
3. **Theme Support**: Use CSS variables, test both light/dark themes
|
|
566
|
+
4. **No Inline Styles**: All styling via CSS classes
|
|
567
|
+
5. **TypeScript**: Strict typing, export all public types
|
|
568
|
+
6. **Accessibility**: Semantic HTML, ARIA attributes, keyboard navigation
|
|
569
|
+
7. **RJSF Patterns**: Follow Field/Widget separation for RJSF components (see
|
|
570
|
+
[PATTERNS.md](./PATTERNS.md))
|
|
571
|
+
|
|
572
|
+
### RJSF Component Architecture (CRITICAL)
|
|
573
|
+
|
|
574
|
+
**When creating RJSF custom components, you MUST follow the Field/Widget
|
|
575
|
+
separation pattern.**
|
|
576
|
+
|
|
577
|
+
See [PATTERNS.md](./PATTERNS.md) for comprehensive documentation of:
|
|
578
|
+
|
|
579
|
+
- **Field/Widget Separation**: Mandatory two-layer architecture
|
|
580
|
+
- **Component Composition**: MappingCollapsible, MappingFormWrapper, IconButton
|
|
581
|
+
- **State Management**: Controlled state, external sync, deduplication
|
|
582
|
+
- **Data Flow**: Schema passing via `ui:options`, props threading
|
|
583
|
+
- **CSS Conventions**: BEM with `elb-` prefix
|
|
584
|
+
- **Common Utilities**: `cleanFormData`, type guards, validators
|
|
585
|
+
- **Anti-Patterns**: What NOT to do (with examples)
|
|
586
|
+
|
|
587
|
+
**Quick Reference - All RJSF Components:**
|
|
588
|
+
|
|
589
|
+
| Field | Widget | Purpose |
|
|
590
|
+
| ----------------------- | ------------------------ | ------------------------- |
|
|
591
|
+
| `MappingConsentField` | `MappingConsentWidget` | Consent states (checkbox) |
|
|
592
|
+
| `MappingConditionField` | `MappingConditionWidget` | Condition code editor |
|
|
593
|
+
| `MappingDataField` | `MappingDataWidget` | Data transformation rows |
|
|
594
|
+
| `MappingGlobalsField` | `MappingGlobalsWidget` | Global properties |
|
|
595
|
+
| `MappingContextField` | `MappingContextWidget` | Context properties |
|
|
596
|
+
| `MappingNestedField` | `MappingNestedWidget` | Nested entities |
|
|
597
|
+
| `MappingSettingsField` | `MappingSettingsWidget` | Destination settings |
|
|
598
|
+
|
|
599
|
+
**Field responsibilities** (~20 lines):
|
|
600
|
+
|
|
601
|
+
- Convert `FieldProps` โ `WidgetProps`
|
|
602
|
+
- Pass through props (id, value, onChange, schema, uiSchema, rawErrors,
|
|
603
|
+
disabled, readonly)
|
|
604
|
+
- No UI logic
|
|
605
|
+
|
|
606
|
+
**Widget responsibilities** (100-300 lines):
|
|
607
|
+
|
|
608
|
+
- Implement full UI using standard building blocks
|
|
609
|
+
- Manage component state (expand/collapse, show/hide, previous values)
|
|
610
|
+
- Handle form changes and cleanup
|
|
611
|
+
- Sync with external value changes via `useEffect`
|
|
612
|
+
- Use `MappingCollapsible` for toggle/checkbox UI
|
|
613
|
+
- Use `MappingFormWrapper` for nested forms
|
|
614
|
+
- Use `IconButton` for actions
|
|
615
|
+
- Use `cleanFormData` to remove empty values
|
|
616
|
+
|
|
617
|
+
See [PATTERNS.md](./PATTERNS.md) for detailed examples and implementation
|
|
618
|
+
checklist.
|
|
619
|
+
|
|
620
|
+
### Component Checklist
|
|
621
|
+
|
|
622
|
+
**Before submitting any component:**
|
|
623
|
+
|
|
624
|
+
- [ ] Component placed in correct atomic layer (atoms/molecules/organisms)
|
|
625
|
+
- [ ] TypeScript types exported from component file
|
|
626
|
+
- [ ] **SCSS compliance verified** (see SCSS Architecture section above):
|
|
627
|
+
- [ ] All CSS variables exist in `theme/_variables.scss`
|
|
628
|
+
- [ ] BEM naming: `elb-{component}-{element}`
|
|
629
|
+
- [ ] SCSS file created in correct directory (`atoms/`, `molecules/`,
|
|
630
|
+
`organisms/`)
|
|
631
|
+
- [ ] SCSS imported in `index.scss` (alphabetical order)
|
|
632
|
+
- [ ] No hardcoded values (colors, spacing, fonts)
|
|
633
|
+
- [ ] Uses `calc(var(--font-size-base) - Npx)` for size variations
|
|
634
|
+
- [ ] Light and dark theme tested
|
|
635
|
+
- [ ] No inline `style` attributes
|
|
636
|
+
- [ ] Responsive design considered
|
|
637
|
+
- [ ] Reuses existing components where possible (MappingCollapsible, IconButton,
|
|
638
|
+
etc.)
|
|
639
|
+
- [ ] **RJSF components follow Field/Widget separation pattern** (see
|
|
640
|
+
[PATTERNS.md](./PATTERNS.md))
|
|
641
|
+
- [ ] Build succeeds: `npm run build`
|
|
642
|
+
- [ ] Exported from `src/index.ts` (if public API)
|
|
643
|
+
|
|
644
|
+
## Monaco Editor Height Management
|
|
645
|
+
|
|
646
|
+
The explorer uses Monaco Editor with a flexible, responsive height system that works across all contexts.
|
|
647
|
+
|
|
648
|
+
### Height Modes
|
|
649
|
+
|
|
650
|
+
CodeBox supports three height modes:
|
|
651
|
+
|
|
652
|
+
1. **Default (height="100%")**: Fills parent container
|
|
653
|
+
- Use in Grid contexts for equal row heights
|
|
654
|
+
- Use in Flex contexts to fill available space
|
|
655
|
+
- Requires parent with explicit height or bounded context
|
|
656
|
+
|
|
657
|
+
2. **Auto-height (autoHeight prop)**: Dynamically sizes to content
|
|
658
|
+
- Grows/shrinks based on Monaco's content height
|
|
659
|
+
- Respects min/max boundaries (customizable)
|
|
660
|
+
- Eliminates blank space in standalone contexts
|
|
661
|
+
- Updates automatically when content changes
|
|
662
|
+
|
|
663
|
+
3. **Explicit height**: Fixed pixel or viewport height
|
|
664
|
+
- Override with `height` prop (e.g., `height="600px"` or `height="50vh"`)
|
|
665
|
+
|
|
666
|
+
### Usage Examples
|
|
667
|
+
|
|
668
|
+
**Grid Context - Equal Heights:**
|
|
669
|
+
```tsx
|
|
670
|
+
// Don't use autoHeight - maintains equal row heights
|
|
671
|
+
<Grid columns={3}>
|
|
672
|
+
<CodeBox code={event} label="Event" />
|
|
673
|
+
<CodeBox code={mapping} label="Mapping" />
|
|
674
|
+
<CodeBox code={output} label="Output" />
|
|
675
|
+
</Grid>
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
**Standalone - Content-Based Height:**
|
|
679
|
+
```tsx
|
|
680
|
+
// Use autoHeight to eliminate blank space
|
|
681
|
+
<CodeBox
|
|
682
|
+
code={setupExample}
|
|
683
|
+
label="Setup"
|
|
684
|
+
autoHeight={{ min: 100, max: 600 }}
|
|
685
|
+
disabled
|
|
686
|
+
/>
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
**Flex Context - Fill Parent:**
|
|
690
|
+
```tsx
|
|
691
|
+
// Don't use autoHeight - fills available flex space
|
|
692
|
+
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
|
|
693
|
+
<CodeBox code={largeConfig} onChange={setConfig} />
|
|
694
|
+
</div>
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**Explicit Height Override:**
|
|
698
|
+
```tsx
|
|
699
|
+
<CodeBox code={longCode} height="600px" />
|
|
700
|
+
```
|
|
435
701
|
|
|
436
|
-
|
|
702
|
+
### How Auto-Height Works
|
|
437
703
|
|
|
438
|
-
|
|
704
|
+
When `autoHeight` is enabled:
|
|
705
|
+
1. Monaco Editor's `getContentHeight()` API measures actual content height
|
|
706
|
+
2. Hook listens to `onDidContentSizeChange` events (debounced)
|
|
707
|
+
3. Height calculated and bounded by min/max values
|
|
708
|
+
4. Monaco receives explicit pixel height (e.g., `height="347px"`)
|
|
709
|
+
5. Updates automatically on content changes, typing, or formatting
|
|
439
710
|
|
|
440
|
-
|
|
441
|
-
-
|
|
442
|
-
-
|
|
443
|
-
-
|
|
444
|
-
-
|
|
711
|
+
**Technical Details:**
|
|
712
|
+
- Uses `useMonacoHeight` hook with Monaco's official APIs
|
|
713
|
+
- Avoids infinite loops by not calling `layout()` in content change handler
|
|
714
|
+
- Includes overhead calculation for header/borders (45px)
|
|
715
|
+
- Default boundaries: min=100px, max=600px (customizable)
|
|
445
716
|
|
|
446
|
-
###
|
|
717
|
+
### Key Files
|
|
447
718
|
|
|
448
|
-
-
|
|
449
|
-
-
|
|
450
|
-
-
|
|
451
|
-
-
|
|
719
|
+
- `explorer/src/components/atoms/code.tsx` - Monaco wrapper with autoHeight integration
|
|
720
|
+
- `explorer/src/hooks/useMonacoHeight.ts` - Content height calculation hook
|
|
721
|
+
- `explorer/src/styles/components/atoms/_code.scss` - Flex-based Monaco container
|
|
722
|
+
- `explorer/src/styles/components/organisms/_box.scss` - Context-specific height rules
|
|
452
723
|
|
|
453
|
-
###
|
|
724
|
+
### Troubleshooting
|
|
454
725
|
|
|
455
|
-
|
|
456
|
-
-
|
|
457
|
-
-
|
|
458
|
-
-
|
|
726
|
+
**Monaco shows wrong height?**
|
|
727
|
+
- Check parent context: Grid, Flex, or standalone?
|
|
728
|
+
- Grid/Flex: Don't use autoHeight (use default height="100%")
|
|
729
|
+
- Standalone: Add `autoHeight={{ min: 100, max: 600 }}`
|
|
730
|
+
- Override with explicit `height` prop if needed
|
|
459
731
|
|
|
460
|
-
|
|
732
|
+
**AutoHeight not working?**
|
|
733
|
+
- Ensure Monaco has mounted (check browser console for errors)
|
|
734
|
+
- Verify min/max boundaries aren't too restrictive
|
|
735
|
+
- Check that content is actually rendering (empty code = min height)
|
|
461
736
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
5. Follow TypeScript best practices
|
|
737
|
+
**Height grows infinitely?**
|
|
738
|
+
- Should not happen with current implementation
|
|
739
|
+
- Hook avoids calling `layout()` in content change handler
|
|
740
|
+
- Report if you encounter this bug
|
|
467
741
|
|
|
468
|
-
##
|
|
742
|
+
## Browser Support
|
|
469
743
|
|
|
470
|
-
|
|
744
|
+
Chrome 80+, Firefox 75+, Safari 13+, Edge 80+
|
|
471
745
|
|
|
472
|
-
##
|
|
746
|
+
## License
|
|
473
747
|
|
|
474
|
-
|
|
475
|
-
- **GitHub Repository**: https://github.com/elbwalker/walkerOS
|
|
476
|
-
- **Issues**: https://github.com/elbwalker/walkerOS/issues
|
|
748
|
+
MIT
|