@vscode/component-explorer 0.2.1-18 → 0.2.1-180

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +198 -27
  2. package/dist/browserDaemonClient-AB8d4x2O.js +3465 -0
  3. package/dist/browserDaemonClient-AB8d4x2O.js.map +1 -0
  4. package/dist/components/BottomDebugPanel.d.ts +8 -0
  5. package/dist/components/BottomDebugPanel.d.ts.map +1 -0
  6. package/dist/components/DebugPanelPlacement.d.ts +3 -0
  7. package/dist/components/DebugPanelPlacement.d.ts.map +1 -0
  8. package/dist/components/DebugWorkbench.d.ts +42 -0
  9. package/dist/components/DebugWorkbench.d.ts.map +1 -0
  10. package/dist/components/DebugWorkbenchLayout.d.ts +30 -0
  11. package/dist/components/DebugWorkbenchLayout.d.ts.map +1 -0
  12. package/dist/components/DebugWorkbenchState.d.ts +31 -0
  13. package/dist/components/DebugWorkbenchState.d.ts.map +1 -0
  14. package/dist/components/ExplorerModel.d.ts +28 -5
  15. package/dist/components/ExplorerModel.d.ts.map +1 -1
  16. package/dist/components/FixtureDebugStore.d.ts +20 -0
  17. package/dist/components/FixtureDebugStore.d.ts.map +1 -0
  18. package/dist/components/FixturePreviewItem.d.ts +11 -0
  19. package/dist/components/FixturePreviewItem.d.ts.map +1 -1
  20. package/dist/components/LeftSidebar.d.ts.map +1 -1
  21. package/dist/components/PageViewportState.d.ts +34 -0
  22. package/dist/components/PageViewportState.d.ts.map +1 -0
  23. package/dist/components/PreviewArea.d.ts.map +1 -1
  24. package/dist/components/RightSidebar.d.ts +8 -2
  25. package/dist/components/RightSidebar.d.ts.map +1 -1
  26. package/dist/components/TitleBar.d.ts.map +1 -1
  27. package/dist/components/TreeView.d.ts +3 -1
  28. package/dist/components/TreeView.d.ts.map +1 -1
  29. package/dist/components/favoriteFixtures.d.ts +4 -0
  30. package/dist/components/favoriteFixtures.d.ts.map +1 -0
  31. package/dist/components/icons.d.ts +12 -8
  32. package/dist/components/icons.d.ts.map +1 -1
  33. package/dist/components/types.d.ts +2 -0
  34. package/dist/components/types.d.ts.map +1 -1
  35. package/dist/core/ComponentRenderer.d.ts +26 -3
  36. package/dist/core/ComponentRenderer.d.ts.map +1 -1
  37. package/dist/core/ErrorInfo.d.ts +21 -1
  38. package/dist/core/ErrorInfo.d.ts.map +1 -1
  39. package/dist/core/FixtureInputStore.d.ts +32 -0
  40. package/dist/core/FixtureInputStore.d.ts.map +1 -0
  41. package/dist/core/FixtureInteractionRuntime.d.ts +30 -0
  42. package/dist/core/FixtureInteractionRuntime.d.ts.map +1 -0
  43. package/dist/core/FixtureNode.d.ts.map +1 -1
  44. package/dist/core/FixtureRegistry.d.ts +2 -0
  45. package/dist/core/FixtureRegistry.d.ts.map +1 -1
  46. package/dist/core/RenderTimeout.d.ts +39 -0
  47. package/dist/core/RenderTimeout.d.ts.map +1 -0
  48. package/dist/core/fixtureApi.d.ts +234 -32
  49. package/dist/core/fixtureApi.d.ts.map +1 -1
  50. package/dist/core/fixtureApiConsumer.d.ts +22 -2
  51. package/dist/core/fixtureApiConsumer.d.ts.map +1 -1
  52. package/dist/core/index.d.ts +7 -3
  53. package/dist/core/index.d.ts.map +1 -1
  54. package/dist/core/inputAggregation.d.ts +31 -0
  55. package/dist/core/inputAggregation.d.ts.map +1 -0
  56. package/dist/daemon/DaemonConfig.d.ts +0 -2
  57. package/dist/daemon/DaemonConfig.d.ts.map +1 -1
  58. package/dist/daemon/DaemonModel.d.ts +12 -6
  59. package/dist/daemon/DaemonModel.d.ts.map +1 -1
  60. package/dist/daemon/browserDaemonClient.d.ts +3 -0
  61. package/dist/daemon/browserDaemonClient.d.ts.map +1 -0
  62. package/dist/fixtureApi.d-DjVuiRlO.d.ts +533 -0
  63. package/dist/index.d.ts +53 -10
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +11 -9
  66. package/dist/lib/explorerQueryParams.d.ts +2 -2
  67. package/dist/lib/explorerQueryParams.d.ts.map +1 -1
  68. package/dist/lib/fixtureSizeCache.d.ts +2 -0
  69. package/dist/lib/fixtureSizeCache.d.ts.map +1 -1
  70. package/dist/modes/EmbeddedMode.d.ts +7 -0
  71. package/dist/modes/EmbeddedMode.d.ts.map +1 -1
  72. package/dist/modes/ExplorerUIMode.d.ts +1 -1
  73. package/dist/modes/ExplorerUIMode.d.ts.map +1 -1
  74. package/dist/modes/HeadlessMode.d.ts +12 -3
  75. package/dist/modes/HeadlessMode.d.ts.map +1 -1
  76. package/dist/{runtimeVersion-DLeDvOjy.js → runtimeVersion-D9F0L_-O.js} +80 -39
  77. package/dist/runtimeVersion-D9F0L_-O.js.map +1 -0
  78. package/dist/viewer.d.ts +2900 -24
  79. package/dist/viewer.d.ts.map +1 -1
  80. package/dist/viewer.js +5596 -2332
  81. package/dist/viewer.js.map +1 -1
  82. package/package.json +10 -6
  83. package/dist/core/PropertySchema.d.ts +0 -40
  84. package/dist/core/PropertySchema.d.ts.map +0 -1
  85. package/dist/runtimeVersion-DLeDvOjy.js.map +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @vscode/component-explorer
2
2
 
3
- Core library for the [Component Explorer](../../README.md). Contains the fixture API, property schemas, fixture registry, and the Explorer React UI.
3
+ Core library for the [Component Explorer](../../README.md). Contains the fixture API, input schemas, fixture registry, and the Explorer React UI.
4
4
 
5
5
  ## Fixture API
6
6
 
@@ -10,46 +10,85 @@ Defines a single component fixture.
10
10
 
11
11
  ```tsx
12
12
  import { defineFixture } from '@vscode/component-explorer';
13
+ import { z } from 'zod';
13
14
 
14
15
  export default defineFixture({
15
- properties: [
16
- { type: 'string', name: 'label', defaultValue: 'Click me' },
17
- { type: 'boolean', name: 'disabled', defaultValue: false },
18
- ],
19
- render: (container, props) => {
16
+ inputSchema: z.object({
17
+ label: z.string().default('Click me'),
18
+ disabled: z.boolean().default(false),
19
+ }),
20
+ render: (container, { input }) => {
20
21
  const root = createRoot(container);
21
- root.render(<Button label={props.label as string} disabled={props.disabled as boolean} />);
22
+ root.render(<Button label={input.label} disabled={input.disabled} />);
22
23
  return { dispose: () => root.unmount() };
23
24
  },
24
25
  });
25
26
  ```
26
27
 
28
+ The `inputSchema` is a [zod](https://zod.dev) schema. It is converted to JSON Schema at define
29
+ time, and `input` (typed as `z.infer<typeof schema>`) is populated with the schema's defaults
30
+ plus any overrides set in the explorer's properties panel.
31
+
27
32
  Options:
28
33
 
29
34
  | Option | Type | Default | Description |
30
35
  |---|---|---|---|
31
- | `render` | `(container, props) => Disposable` | **(required)** | Renders the component. Must return `{ dispose() }` for cleanup. |
32
- | `properties` | `PropertySchema[]` | `[]` | Configurable properties shown in the properties panel. |
36
+ | `render` | `(container, context) => Disposable` | **(required)** | Renders the component. Must return `{ dispose() }` for cleanup. |
37
+ | `inputSchema` | `z.ZodType` | — | Zod schema describing `input`. Drives the properties panel controls. |
38
+ | `inputControls` | `Record<inputKey, options>` | — | Places selected boolean/enum inputs in the fixture toolbar, sidebar, or both. |
39
+ | `debugPanels` | `DebugPanelDefinition[]` | — | Statically declares typed, interactive debug panels. |
33
40
  | `isolation` | `'shadow-dom' \| 'iframe'` | `'shadow-dom'` | Component isolation strategy. |
34
41
  | `displayMode` | `DisplayMode` | `{ type: 'component' }` | `'component'` for natural size, or `'page'` with viewport presets. |
35
42
  | `styles` | `StyleDefinition[]` | — | Stylesheets injected into the shadow root (shadow-dom isolation only). |
36
43
  | `background` | `'light' \| 'dark'` | `'light'` | Preview canvas background pattern. |
37
44
  | `description` | `string` | — | Documentation description. |
38
45
 
39
- ### `defineFixtureGroup(entries)`
46
+ The sidebar's **Preview Sizing** dropdown applies to all fixtures and persists across navigation
47
+ and reloads. **Fit** scales down to fit the preview viewport's width and height, **1:1** shows
48
+ natural size, and **Responsive (Pages)** resizes page fixtures while using Fit for components.
49
+ Page fixtures retain their per-fixture toolbar for selecting a viewport preset and editing logical
50
+ width/height. These UI settings do not affect embedded or headless rendering.
51
+
52
+ Natural-size component fixtures also default to **Fit**, shrinking to the available preview
53
+ width and height without upscaling small components. Both fixed dimensions and dynamically
54
+ changing content retain their natural layout: only the preview presentation is scaled.
55
+ Dynamic size changes and preview resizing update the scale without remounting the fixture.
56
+ Fit uses a shared preview-viewport budget with fixed allowances for padding and fixture chrome.
57
+ It does not depend on a fixture's position, wrapping, neighboring fixtures, or its scaled bounds.
58
+ Small variants can share a row; large variants wrap without shrinking to their toolbar's width.
59
+
60
+ ### Render timeout and diagnostics
61
+
62
+ Fixtures have a 3,000 ms asynchronous render/readiness budget. Synchronous work
63
+ in an installed V8 `Error.prepareStackTrace` formatter, including source-map
64
+ loading, parsing, and mapping, is excluded from that budget. The formatter's
65
+ result and exceptions are preserved; genuine fixture errors still fail with
66
+ their mapped stacks, and renders that never finish still time out.
40
67
 
41
- Groups multiple fixtures (supports nesting):
68
+ The watchdog uses captured real timers, not a fixture's virtual clock. Diagnostic
69
+ time is shared across same-origin embedded frames, including synchronous fixture
70
+ setup. Overlapping renders keep
71
+ the formatter wrapped until the last render finishes. Headless timing reports
72
+ remain real wall-clock durations, including diagnostics. The browser runner's
73
+ outer timeout remains the limit on total wall-clock work.
74
+
75
+ ### `defineFixtureGroup(entries)` / `defineFixtureGroup(options, entries)`
76
+
77
+ Groups multiple fixtures (supports nesting). An optional first argument can declare an
78
+ `inputSchema` shared by — and merged into — every descendant fixture, so common input (e.g. a
79
+ `theme` switch) is declared once for the whole group:
42
80
 
43
81
  ```tsx
44
82
  import { defineFixture, defineFixtureGroup } from '@vscode/component-explorer';
83
+ import { z } from 'zod';
45
84
 
46
- export default defineFixtureGroup({
47
- Primary: defineFixture({ render: (c) => { /* ... */ } }),
48
- Secondary: defineFixture({ render: (c) => { /* ... */ } }),
49
- Nested: defineFixtureGroup({
50
- Small: defineFixture({ render: (c) => { /* ... */ } }),
51
- }),
52
- });
85
+ export default defineFixtureGroup(
86
+ { inputSchema: z.object({ theme: z.enum(['light', 'dark']).default('dark') }) },
87
+ {
88
+ Primary: defineFixture({ render: (c) => { /* ... */ } }),
89
+ Secondary: defineFixture({ render: (c) => { /* ... */ } }),
90
+ },
91
+ );
53
92
  ```
54
93
 
55
94
  ### `defineFixtureVariants(variants)`
@@ -66,16 +105,149 @@ defineFixtureVariants({
66
105
  });
67
106
  ```
68
107
 
69
- ## Property Types
108
+ ## Input Schemas
109
+
110
+ Fixture `input` is described with a [zod](https://zod.dev) schema (`inputSchema`). The explorer
111
+ converts it to JSON Schema and renders a control per property in the properties panel:
112
+
113
+ | Zod type | Control |
114
+ |---|---|
115
+ | `z.boolean()` | Toggle checkbox |
116
+ | `z.string()` | Text input |
117
+ | `z.number()` / `z.int()` | Number input |
118
+ | `z.enum([...])` | Dropdown select |
119
+
120
+ Use `.default(...)` to set the initial value and `.describe(...)` to document a property. When
121
+ multiple rendered fixtures share a property of the same name and schema, the panel exposes a
122
+ single control that edits them all at once.
123
+
124
+ Use `inputControls` with `placement: 'toolbar'` for compact boolean or enum controls beside the
125
+ fixture dimensions. Opt a property into live updates with `watchInput`; changed properties without
126
+ a watcher keep the default full-remount behavior. A fixture can call
127
+ `reportInput(key, value)` after its component changes a watched property itself.
128
+ This updates the sidebar/shared input store without echoing the change to that
129
+ fixture's watcher or remounting it. Reports are coalesced per microtask and
130
+ discarded after disposal; unwatched properties are rejected. This also works
131
+ across iframe isolation.
132
+
133
+ ```ts
134
+ defineFixture({
135
+ inputSchema: z.object({ showBounds: z.boolean().default(false) }),
136
+ inputControls: {
137
+ showBounds: { placement: 'toolbar', label: 'bounds' },
138
+ },
139
+ render(container, { watchInput }) {
140
+ const overlay = createBoundsOverlay(container);
141
+ watchInput('showBounds', value => overlay.setVisible(value));
142
+ return overlay;
143
+ },
144
+ });
145
+ ```
146
+
147
+ ## Typed Debug Panels and Output
148
+
149
+ `defineDebugPanel<TState, TAction>()` defines a custom panel UI. The fixture connects its live
150
+ state/action channel through `context.debug.connect`. The connection callback runs only while that
151
+ panel is visible, so hidden panels do not parse, subscribe, or publish data.
152
+
153
+ ```ts
154
+ const sourcePanel = defineDebugPanel<
155
+ { source: string },
156
+ { type: 'setSource'; source: string }
157
+ >({
158
+ id: 'source',
159
+ title: 'Source',
160
+ render: (container, { sendAction }) => createSourceView(container, sendAction),
161
+ });
162
+
163
+ defineFixture({
164
+ debugPanels: [sourcePanel],
165
+ render(container, { debug }) {
166
+ const model = createModel(container);
167
+ debug.connect(sourcePanel, channel => {
168
+ const actions = channel.onAction(action => model.setSource(action.source));
169
+ const state = model.onDidChange(() => channel.publish({ source: model.source }));
170
+ channel.publish({ source: model.source });
171
+ return { dispose: () => { actions.dispose(); state.dispose(); } };
172
+ });
173
+ return model;
174
+ },
175
+ });
176
+ ```
177
+
178
+ Panels default beside a single logical fixture and in the shared bottom workbench for variant rows.
179
+ Set `placement: 'canvas-right'` or `'bottom-panel'` on the panel to override this rule.
180
+ Closed inline panels are grouped in a **Debug panels** dropdown. When a stack's tabs do not fit,
181
+ the active tab remains visible and a **More debug panels** dropdown (`...`) offers the other panels.
182
+ Select a panel, then drag its tab into a split to keep multiple panels visible. During dragging,
183
+ overflowing tabs are revealed; hovering near the tab strip's edges scrolls it. Drop onto a tab
184
+ header to reorder or move tabs between panes.
185
+
186
+ **Split right** creates a second live view of the selected debug panel, leaving the original open.
187
+ Both copies share fixture state but have independent tab selections and view instances. Close a
188
+ pane using its **Close debug pane** button; its other tabs remain available in the workbench.
189
+
190
+ Drag the bottom edge of inline debug panes to give them more vertical space independently of the
191
+ fixture. The resize handle also supports Up/Down arrow keys; double-click or press Home to reset.
192
+ **Viewport height** fills the available preview height without stretching or remounting the fixture.
193
+ Open/closed panes, tab order and selection, duplicate views, split ratios, widths, and heights
194
+ survive navigation and reload in this browser. Storage is scoped to the project supplied by the
195
+ Vite/Webpack plugin. Custom hosts can supply `ExplorerAppOptions.storageScope` (the default is the
196
+ Explorer URL path). Storage errors are reported in the sidebar and console.
197
+
198
+ Enable **Synchronize debug panes** in the properties sidebar to copy the current fixture's
199
+ arrangement into a shared template. Other fixtures use that template with their own live data.
200
+ Missing panel types are temporarily hidden, and empty groups collapse. Navigation and panel
201
+ preference changes do not rewrite the template. An explicit layout edit (including selecting a
202
+ tab or resizing) saves the visible arrangement, discarding hidden groups from the template.
203
+ Turning synchronization off restores the independent fixture layouts and preferences from before
204
+ it was enabled. The aggregated bottom workbench, including Console, persists independently and
205
+ does not participate in synchronization.
206
+
207
+ ### Persistent panel UI state
208
+
209
+ Panels can opt into validated, versioned, JSON-serializable view preferences without accessing
210
+ browser storage. Call `context.viewState` with a stable schema/version and one state object per
211
+ panel and scope. `get()` restores state before rendering; `set()` validates and saves it; `onChange()`
212
+ subscribes to changes (dispose the subscription with the panel).
213
+
214
+ ```ts
215
+ render(container, context) {
216
+ const preferences = context.viewState({
217
+ version: 1,
218
+ scope: 'pane',
219
+ schema: z.object({ renderer: z.enum(['cmark-gfm', 'markdown-it']) }),
220
+ defaultValue: { renderer: 'cmark-gfm' },
221
+ });
222
+ const select = document.createElement('select');
223
+ for (const renderer of ['cmark-gfm', 'markdown-it']) {
224
+ select.add(new Option(renderer, renderer));
225
+ }
226
+ select.value = preferences.get().renderer;
227
+ select.onchange = () => {
228
+ preferences.set({ renderer: select.value === 'markdown-it' ? 'markdown-it' : 'cmark-gfm' });
229
+ };
230
+ const subscription = preferences.onChange(value => { select.value = value.renderer; });
231
+ container.append(select);
232
+ return {
233
+ update(source) { /* render live fixture data separately */ },
234
+ dispose() { subscription.dispose(); select.remove(); },
235
+ };
236
+ }
237
+ ```
70
238
 
71
- | Type | Fields | Description |
72
- |---|---|---|
73
- | `boolean` | `name`, `defaultValue` | Toggle checkbox |
74
- | `string` | `name`, `defaultValue`, `multiline?` | Text input (or textarea) |
75
- | `number` | `name`, `defaultValue`, `min?`, `max?`, `step?` | Number input with optional range |
76
- | `enum` | `name`, `defaultValue`, `options` | Dropdown select |
239
+ Use `scope: 'pane'` for preferences that follow a synchronized pane between fixtures (for example,
240
+ the Markdown Reference renderer). Use `scope: 'fixture'` for fixture-dependent selections or scroll
241
+ positions. Split right copies the current preferences once; the two tab instances then evolve
242
+ independently. Docking and reordering retain their identities, even when duplicate tabs are placed
243
+ in the same group. Unsupported versions or invalid saved values use the declared default and
244
+ report a warning; bump the version when changing the state shape. Fixture data, actions, and
245
+ headless rendering are unaffected.
77
246
 
78
- All property types support an optional `description` field.
247
+ Any defined `RenderResult.output` gets a built-in read-only JSON panel. Wrap it with
248
+ `interactiveOutput({ getSnapshot, activate })` to opt into JSON editing; output actions update the
249
+ live fixture without remounting. Headless and CLI consumers continue to receive the unwrapped
250
+ snapshot value.
79
251
 
80
252
  ## Explorer UI Components
81
253
 
@@ -96,7 +268,6 @@ The package exports the full Explorer UI as React components:
96
268
  |---|---|
97
269
  | `FixtureRegistry` | Observable registry of discovered fixtures. |
98
270
  | `createFixtureTree` | Builds a `FixtureNode` tree from registered fixtures. |
99
- | `getDefaultPropertyValues` | Extracts default values from a `PropertySchema[]`. |
100
271
  | `VIEWPORT_SIZES` | Built-in viewport preset dimensions (`mobile`, `tablet`, `desktop`). |
101
272
 
102
273
  ## Styles