@design.estate/wcctools 5.1.0 → 6.0.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.
Files changed (128) hide show
  1. package/.smartconfig.json +7 -3
  2. package/changelog.md +15 -0
  3. package/cli.js +3 -0
  4. package/dist_shell/bundle.js +2970 -0
  5. package/dist_shell/bundle.js.map +1 -0
  6. package/dist_shell/bundle.js.third-party-notices.json +1722 -0
  7. package/dist_shell/bundle.js.third-party-notices.txt +4195 -0
  8. package/dist_shell/index.html +21 -0
  9. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  10. package/dist_ts/00_commitinfo_data.js +9 -0
  11. package/dist_ts/classes.devapi.d.ts +11 -0
  12. package/dist_ts/classes.devapi.js +21 -0
  13. package/dist_ts/classes.devserver.d.ts +49 -0
  14. package/dist_ts/classes.devserver.js +142 -0
  15. package/dist_ts/cli.d.ts +6 -0
  16. package/dist_ts/cli.js +45 -0
  17. package/dist_ts/index.d.ts +3 -0
  18. package/dist_ts/index.js +4 -0
  19. package/dist_ts/paths.d.ts +4 -0
  20. package/dist_ts/paths.js +6 -0
  21. package/dist_ts/plugins.d.ts +15 -0
  22. package/dist_ts/plugins.js +21 -0
  23. package/dist_ts/shellcontent.d.ts +9 -0
  24. package/dist_ts/shellcontent.js +42 -0
  25. package/dist_ts_interfaces/bridge.d.ts +88 -0
  26. package/dist_ts_interfaces/bridge.js +2 -0
  27. package/dist_ts_interfaces/catalog.d.ts +32 -0
  28. package/dist_ts_interfaces/catalog.js +6 -0
  29. package/dist_ts_interfaces/index.d.ts +3 -0
  30. package/dist_ts_interfaces/index.js +4 -0
  31. package/dist_ts_interfaces/plugins.d.ts +2 -0
  32. package/dist_ts_interfaces/plugins.js +3 -0
  33. package/dist_ts_interfaces/requests.d.ts +15 -0
  34. package/dist_ts_interfaces/requests.js +2 -0
  35. package/dist_ts_shared/index.d.ts +1 -0
  36. package/dist_ts_shared/index.js +2 -0
  37. package/dist_ts_shared/plugins.d.ts +2 -0
  38. package/dist_ts_shared/plugins.js +3 -0
  39. package/dist_ts_shared/previewroute.d.ts +18 -0
  40. package/dist_ts_shared/previewroute.js +47 -0
  41. package/{dist_ts_web → dist_ts_shell}/elements/wcc-contextmenu.js +1 -1
  42. package/dist_ts_shell/elements/wcc-preview-frame.d.ts +23 -0
  43. package/dist_ts_shell/elements/wcc-preview-frame.js +197 -0
  44. package/dist_ts_shell/elements/wcc-properties.d.ts +49 -0
  45. package/{dist_ts_web → dist_ts_shell}/elements/wcc-properties.js +149 -216
  46. package/{dist_ts_web → dist_ts_shell}/elements/wcc-record-button.js +1 -1
  47. package/{dist_ts_web → dist_ts_shell}/elements/wcc-recording-panel.d.ts +2 -2
  48. package/{dist_ts_web → dist_ts_shell}/elements/wcc-recording-panel.js +12 -16
  49. package/dist_ts_shell/elements/wcc-shell.d.ts +87 -0
  50. package/dist_ts_shell/elements/wcc-shell.js +524 -0
  51. package/{dist_ts_web → dist_ts_shell}/elements/wcc-sidebar.d.ts +12 -10
  52. package/{dist_ts_web → dist_ts_shell}/elements/wcc-sidebar.js +137 -183
  53. package/dist_ts_shell/index.d.ts +4 -0
  54. package/dist_ts_shell/index.js +5 -0
  55. package/dist_ts_shell/plugins.d.ts +4 -0
  56. package/dist_ts_shell/plugins.js +5 -0
  57. package/dist_ts_shell/previewconnection.d.ts +30 -0
  58. package/dist_ts_shell/previewconnection.js +86 -0
  59. package/dist_ts_shell/services/recorder.service.js +353 -0
  60. package/dist_ts_web/00_commitinfo_data.js +2 -2
  61. package/dist_ts_web/catalog.d.ts +45 -0
  62. package/dist_ts_web/catalog.js +153 -0
  63. package/dist_ts_web/elementproperties.d.ts +15 -0
  64. package/dist_ts_web/elementproperties.js +89 -0
  65. package/dist_ts_web/elements/wcc-preview.d.ts +19 -0
  66. package/dist_ts_web/elements/wcc-preview.js +164 -0
  67. package/dist_ts_web/elements/wcc-standalone-notice.d.ts +14 -0
  68. package/dist_ts_web/elements/wcc-standalone-notice.js +110 -0
  69. package/dist_ts_web/elements/wcctools.helpers.d.ts +2 -6
  70. package/dist_ts_web/elements/wcctools.helpers.js +1 -7
  71. package/dist_ts_web/index.d.ts +2 -5
  72. package/dist_ts_web/index.js +38 -17
  73. package/dist_ts_web/previewbridge.d.ts +39 -0
  74. package/dist_ts_web/previewbridge.js +153 -0
  75. package/dist_ts_web/renderedtree.d.ts +5 -0
  76. package/dist_ts_web/renderedtree.js +37 -0
  77. package/dist_ts_web/wcctools.interfaces.d.ts +3 -6
  78. package/dist_ts_web/wcctools.interfaces.js +1 -1
  79. package/dist_ts_web/wcctools.plugins.d.ts +3 -1
  80. package/dist_ts_web/wcctools.plugins.js +4 -2
  81. package/package.json +16 -8
  82. package/readme.md +60 -28
  83. package/ts/00_commitinfo_data.ts +8 -0
  84. package/ts/classes.devapi.ts +25 -0
  85. package/ts/classes.devserver.ts +161 -0
  86. package/ts/cli.ts +46 -0
  87. package/ts/index.ts +3 -0
  88. package/ts/paths.ts +7 -0
  89. package/ts/plugins.ts +29 -0
  90. package/ts/shellcontent.ts +42 -0
  91. package/ts_web/00_commitinfo_data.ts +1 -1
  92. package/ts_web/catalog.ts +194 -0
  93. package/ts_web/elementproperties.ts +96 -0
  94. package/ts_web/elements/wcc-preview.ts +111 -0
  95. package/ts_web/elements/wcc-standalone-notice.ts +65 -0
  96. package/ts_web/elements/wcctools.helpers.ts +2 -10
  97. package/ts_web/index.ts +38 -19
  98. package/ts_web/previewbridge.ts +189 -0
  99. package/ts_web/readme.md +26 -85
  100. package/ts_web/renderedtree.ts +43 -0
  101. package/ts_web/wcctools.interfaces.ts +4 -7
  102. package/ts_web/wcctools.plugins.ts +6 -1
  103. package/dist_bundle/bundle.js +0 -92419
  104. package/dist_bundle/bundle.js.map +0 -1
  105. package/dist_ts_web/elements/wcc-dashboard.d.ts +0 -119
  106. package/dist_ts_web/elements/wcc-dashboard.js +0 -700
  107. package/dist_ts_web/elements/wcc-frame.d.ts +0 -22
  108. package/dist_ts_web/elements/wcc-frame.js +0 -256
  109. package/dist_ts_web/elements/wcc-properties.d.ts +0 -43
  110. package/dist_ts_web/pages/index.d.ts +0 -1
  111. package/dist_ts_web/pages/index.js +0 -2
  112. package/dist_ts_web/services/recorder.service.js +0 -353
  113. package/ts_web/elements/wcc-contextmenu.ts +0 -291
  114. package/ts_web/elements/wcc-dashboard.ts +0 -672
  115. package/ts_web/elements/wcc-frame.ts +0 -189
  116. package/ts_web/elements/wcc-properties.ts +0 -1089
  117. package/ts_web/elements/wcc-record-button.ts +0 -108
  118. package/ts_web/elements/wcc-recording-panel.ts +0 -1010
  119. package/ts_web/elements/wcc-sidebar.ts +0 -1470
  120. package/ts_web/pages/index.ts +0 -1
  121. package/ts_web/services/recorder.service.ts +0 -451
  122. package/ts_web/types/dom-mediacapture-stub/index.d.ts +0 -12
  123. package/ts_web/types/dom-mediacapture-stub/package.json +0 -6
  124. package/ts_web/types/dom-webcodecs-stub/index.d.ts +0 -2
  125. package/ts_web/types/dom-webcodecs-stub/package.json +0 -6
  126. /package/{dist_ts_web → dist_ts_shell}/elements/wcc-contextmenu.d.ts +0 -0
  127. /package/{dist_ts_web → dist_ts_shell}/elements/wcc-record-button.d.ts +0 -0
  128. /package/{dist_ts_web → dist_ts_shell}/services/recorder.service.d.ts +0 -0
@@ -1,10 +1,7 @@
1
1
  import type { IWccConfig } from './wcctools.interfaces.js';
2
- export { RecorderService, type IRecorderEvents, type IRecordingOptions, type TOutputFormat } from './services/recorder.service.js';
3
- export { WccRecordButton } from './elements/wcc-record-button.js';
4
- export { WccRecordingPanel } from './elements/wcc-recording-panel.js';
5
2
  export type { IWccConfig, IWccSection } from './wcctools.interfaces.js';
6
3
  /**
7
- * Set up the WCC Tools dashboard:
4
+ * Set up the catalog's preview document:
8
5
  * ```typescript
9
6
  * setupWccTools({
10
7
  * sections: [
@@ -14,5 +11,5 @@ export type { IWccConfig, IWccSection } from './wcctools.interfaces.js';
14
11
  * });
15
12
  * ```
16
13
  */
17
- declare const setupWccTools: (config: IWccConfig) => void;
14
+ declare const setupWccTools: (configArg: IWccConfig) => void;
18
15
  export { setupWccTools };
@@ -1,10 +1,30 @@
1
- import { WccDashboard } from './elements/wcc-dashboard.js';
2
- // Export recording components and service
3
- export { RecorderService } from './services/recorder.service.js';
4
- export { WccRecordButton } from './elements/wcc-record-button.js';
5
- export { WccRecordingPanel } from './elements/wcc-recording-panel.js';
1
+ import * as plugins from './wcctools.plugins.js';
2
+ import { WccCatalog } from './catalog.js';
3
+ import { WccPreview } from './elements/wcc-preview.js';
4
+ import { WccStandaloneNotice } from './elements/wcc-standalone-notice.js';
5
+ import { WccPreviewBridge } from './previewbridge.js';
6
6
  /**
7
- * Set up the WCC Tools dashboard:
7
+ * Start the preview document of a catalog. `wcctools dev` loads this document into the shell's
8
+ * preview frame; opened on the preview route it renders the one demo the route names.
9
+ * Opened anywhere else it shows how to start the catalog.
10
+ */
11
+ const startPreview = async (configArg) => {
12
+ const isFramed = window.parent !== window;
13
+ if (!isFramed && window.location.pathname !== plugins.shared.previewRoutePath) {
14
+ document.body.append(new WccStandaloneNotice());
15
+ return;
16
+ }
17
+ const preview = new WccPreview();
18
+ document.body.append(preview);
19
+ const bridge = new WccPreviewBridge(new WccCatalog(configArg), preview);
20
+ await bridge.renderRoute(plugins.shared.parsePreviewQuery(window.location.search));
21
+ window.wccPreview = bridge;
22
+ if (isFramed) {
23
+ window.parent.postMessage(plugins.shared.previewReadyMessage, window.location.origin);
24
+ }
25
+ };
26
+ /**
27
+ * Set up the catalog's preview document:
8
28
  * ```typescript
9
29
  * setupWccTools({
10
30
  * sections: [
@@ -14,17 +34,18 @@ export { WccRecordingPanel } from './elements/wcc-recording-panel.js';
14
34
  * });
15
35
  * ```
16
36
  */
17
- const setupWccTools = (config) => {
18
- let hasRun = false;
19
- const runWccToolsSetup = async () => {
20
- if (document.readyState === 'complete' && !hasRun) {
21
- hasRun = true;
22
- const wccTools = new WccDashboard(config);
23
- document.querySelector('body').append(wccTools);
24
- }
37
+ const setupWccTools = (configArg) => {
38
+ const start = () => {
39
+ startPreview(configArg).catch((error) => {
40
+ console.error('wcctools: the preview failed to start', error);
41
+ });
25
42
  };
26
- document.addEventListener('readystatechange', runWccToolsSetup);
27
- runWccToolsSetup();
43
+ if (document.readyState === 'complete') {
44
+ start();
45
+ }
46
+ else {
47
+ window.addEventListener('load', start, { once: true });
48
+ }
28
49
  };
29
50
  export { setupWccTools };
30
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90c193ZWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRzNELDBDQUEwQztBQUMxQyxPQUFPLEVBQUUsZUFBZSxFQUFvRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25JLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNsRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUt0RTs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxhQUFhLEdBQUcsQ0FBQyxNQUFrQixFQUFFLEVBQUU7SUFDM0MsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ25CLE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxJQUFJLEVBQUU7UUFDbEMsSUFBSSxRQUFRLENBQUMsVUFBVSxLQUFLLFVBQVUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2xELE1BQU0sR0FBRyxJQUFJLENBQUM7WUFDZCxNQUFNLFFBQVEsR0FBRyxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUMxQyxRQUFRLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsRCxDQUFDO0lBQ0gsQ0FBQyxDQUFDO0lBQ0YsUUFBUSxDQUFDLGdCQUFnQixDQUFDLGtCQUFrQixFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDaEUsZ0JBQWdCLEVBQUUsQ0FBQztBQUNyQixDQUFDLENBQUM7QUFFRixPQUFPLEVBQ0wsYUFBYSxFQUNkLENBQUMifQ==
51
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90c193ZWIvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSx1QkFBdUIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUMxRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUt0RDs7OztHQUlHO0FBQ0gsTUFBTSxZQUFZLEdBQUcsS0FBSyxFQUFFLFNBQXFCLEVBQUUsRUFBRTtJQUNuRCxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsTUFBTSxLQUFLLE1BQU0sQ0FBQztJQUMxQyxJQUFJLENBQUMsUUFBUSxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxLQUFLLE9BQU8sQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUM5RSxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLG1CQUFtQixFQUFFLENBQUMsQ0FBQztRQUNoRCxPQUFPO0lBQ1QsQ0FBQztJQUNELE1BQU0sT0FBTyxHQUFHLElBQUksVUFBVSxFQUFFLENBQUM7SUFDakMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDOUIsTUFBTSxNQUFNLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN4RSxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDbkYsTUFBTSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUM7SUFDM0IsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUNiLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN4RixDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sYUFBYSxHQUFHLENBQUMsU0FBcUIsRUFBRSxFQUFFO0lBQzlDLE1BQU0sS0FBSyxHQUFHLEdBQUcsRUFBRTtRQUNqQixZQUFZLENBQUMsU0FBUyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7WUFDdEMsT0FBTyxDQUFDLEtBQUssQ0FBQyx1Q0FBdUMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNoRSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQztJQUNGLElBQUksUUFBUSxDQUFDLFVBQVUsS0FBSyxVQUFVLEVBQUUsQ0FBQztRQUN2QyxLQUFLLEVBQUUsQ0FBQztJQUNWLENBQUM7U0FBTSxDQUFDO1FBQ04sTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN6RCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBRUYsT0FBTyxFQUNMLGFBQWEsRUFDZCxDQUFDIn0=
@@ -0,0 +1,39 @@
1
+ import * as plugins from './wcctools.plugins.js';
2
+ import type { WccCatalog } from './catalog.js';
3
+ import type { WccPreview } from './elements/wcc-preview.js';
4
+ type TPreviewEvent = plugins.interfaces.TWccPreviewEvent;
5
+ /**
6
+ * The preview document's side of the shell bridge: renders the catalog's demos and pages into
7
+ * the preview surface, switches its theme and reads and edits the rendered element's properties.
8
+ */
9
+ export declare class WccPreviewBridge implements plugins.interfaces.IWccPreviewBridge {
10
+ private readonly catalog;
11
+ private readonly preview;
12
+ private readonly listeners;
13
+ private theme;
14
+ private rendered;
15
+ private renderGeneration;
16
+ /** Settles when the latest render, including its elements' first updates, has finished. */
17
+ private renderPromise;
18
+ constructor(catalog: WccCatalog, preview: WccPreview);
19
+ getManifest(): plugins.interfaces.IWccCatalogManifest;
20
+ getSelection(): plugins.interfaces.IWccSelection | null;
21
+ getTheme(): plugins.interfaces.TWccTheme;
22
+ /** Render the preview route the document was loaded with. */
23
+ renderRoute(routeArg: plugins.shared.IWccPreviewRoute): Promise<void>;
24
+ render(selectionArg: plugins.interfaces.IWccSelection): Promise<plugins.interfaces.TWccRenderOutcome>;
25
+ setTheme(themeArg: plugins.interfaces.TWccTheme): Promise<void>;
26
+ getProperties(): Promise<plugins.interfaces.TWccPropertyListing>;
27
+ setProperty(nameArg: string, valueArg: plugins.interfaces.TWccPropertyScalar): plugins.interfaces.TWccPropertyEditResult;
28
+ setPropertyJson(nameArg: string, jsonArg: string): plugins.interfaces.TWccPropertyEditResult;
29
+ findRenderedInstance(): HTMLElement | null;
30
+ subscribe(listenerArg: (eventArg: TPreviewEvent) => void): () => void;
31
+ private getRenderedProperties;
32
+ private renderSelection;
33
+ private renderTarget;
34
+ private showEmptyState;
35
+ /** Keep the document's URL on what it shows, so a live reload comes back to it. */
36
+ private writeRoute;
37
+ private emit;
38
+ }
39
+ export {};
@@ -0,0 +1,153 @@
1
+ import { html, render } from '@design.estate/dees-element';
2
+ import * as plugins from './wcctools.plugins.js';
3
+ import { WccElementProperties } from './elementproperties.js';
4
+ import { findElementInstance, resolveTemplateFactory } from './elements/wcctools.helpers.js';
5
+ import { waitForRenderedTree } from './renderedtree.js';
6
+ /**
7
+ * The preview document's side of the shell bridge: renders the catalog's demos and pages into
8
+ * the preview surface, switches its theme and reads and edits the rendered element's properties.
9
+ */
10
+ export class WccPreviewBridge {
11
+ catalog;
12
+ preview;
13
+ listeners = new Set();
14
+ theme = 'dark';
15
+ rendered = null;
16
+ renderGeneration = 0;
17
+ /** Settles when the latest render, including its elements' first updates, has finished. */
18
+ renderPromise = Promise.resolve();
19
+ constructor(catalog, preview) {
20
+ this.catalog = catalog;
21
+ this.preview = preview;
22
+ }
23
+ getManifest() {
24
+ return this.catalog.getManifest();
25
+ }
26
+ getSelection() {
27
+ return this.rendered?.selection ? { ...this.rendered.selection } : null;
28
+ }
29
+ getTheme() {
30
+ return this.theme;
31
+ }
32
+ /** Render the preview route the document was loaded with. */
33
+ async renderRoute(routeArg) {
34
+ await this.setTheme(routeArg.theme);
35
+ await this.renderSelection(routeArg.selection);
36
+ }
37
+ async render(selectionArg) {
38
+ const { sectionName, itemName, demoIndex } = selectionArg;
39
+ return this.renderSelection({ sectionName, itemName, demoIndex });
40
+ }
41
+ async setTheme(themeArg) {
42
+ this.theme = themeArg === 'bright' ? 'bright' : 'dark';
43
+ const domtools = await plugins.deesDomtools.elementBasic.setup();
44
+ this.theme === 'bright' ? domtools.themeManager.goBright() : domtools.themeManager.goDark();
45
+ this.writeRoute();
46
+ }
47
+ async getProperties() {
48
+ await this.renderPromise;
49
+ const rendered = this.rendered;
50
+ if (!rendered?.selection || rendered.outcome.kind !== 'rendered') {
51
+ return { kind: 'unavailable', reason: 'Nothing is rendered.' };
52
+ }
53
+ if (rendered.outcome.type === 'page') {
54
+ return { kind: 'unavailable', reason: 'You selected a page.' };
55
+ }
56
+ const instance = this.findRenderedInstance();
57
+ if (!instance) {
58
+ return { kind: 'unavailable', reason: `The demo of ${rendered.selection.itemName} renders no <${customElements.getName(rendered.elementClass) ?? rendered.selection.itemName}> instance.` };
59
+ }
60
+ const properties = new WccElementProperties(rendered.elementClass, instance).describe();
61
+ if (!properties) {
62
+ return { kind: 'unavailable', reason: `${rendered.selection.itemName} does not expose element properties.` };
63
+ }
64
+ return { kind: 'properties', elementName: rendered.selection.itemName, properties };
65
+ }
66
+ setProperty(nameArg, valueArg) {
67
+ const properties = this.getRenderedProperties();
68
+ return properties ? properties.set(nameArg, valueArg) : { ok: false, error: 'No element is rendered.' };
69
+ }
70
+ setPropertyJson(nameArg, jsonArg) {
71
+ const properties = this.getRenderedProperties();
72
+ return properties ? properties.setJson(nameArg, jsonArg) : { ok: false, error: 'No element is rendered.' };
73
+ }
74
+ findRenderedInstance() {
75
+ const elementClass = this.rendered?.elementClass;
76
+ const viewport = this.preview.shadowRoot?.querySelector('.viewport');
77
+ if (!elementClass || !viewport) {
78
+ return null;
79
+ }
80
+ return findElementInstance(viewport, elementClass);
81
+ }
82
+ subscribe(listenerArg) {
83
+ this.listeners.add(listenerArg);
84
+ return () => {
85
+ this.listeners.delete(listenerArg);
86
+ };
87
+ }
88
+ getRenderedProperties() {
89
+ const instance = this.findRenderedInstance();
90
+ return instance ? new WccElementProperties(this.rendered.elementClass, instance) : null;
91
+ }
92
+ async renderSelection(selectionArg) {
93
+ const generation = ++this.renderGeneration;
94
+ const target = this.catalog.resolve(selectionArg);
95
+ const renderPromise = this.renderTarget(target, selectionArg?.itemName ?? '', generation);
96
+ this.renderPromise = renderPromise.catch(() => undefined);
97
+ const outcome = await renderPromise;
98
+ if (generation === this.renderGeneration) {
99
+ this.rendered = {
100
+ selection: selectionArg ? { ...selectionArg } : null,
101
+ elementClass: target.kind === 'element' ? target.elementClass : null,
102
+ outcome,
103
+ };
104
+ this.writeRoute();
105
+ this.emit({ type: 'rendered', selection: this.getSelection(), outcome });
106
+ }
107
+ return outcome;
108
+ }
109
+ async renderTarget(targetArg, itemNameArg, generationArg) {
110
+ const viewport = await this.preview.getViewportElement();
111
+ if (targetArg.kind === 'empty') {
112
+ this.showEmptyState(viewport, targetArg.emptyState, generationArg);
113
+ return { kind: 'empty', reason: targetArg.reason, emptyState: targetArg.emptyState };
114
+ }
115
+ try {
116
+ const template = await resolveTemplateFactory(targetArg.factory);
117
+ if (generationArg !== this.renderGeneration) {
118
+ return { kind: 'rendered', type: targetArg.kind };
119
+ }
120
+ render(template, viewport);
121
+ this.preview.emptyState = null;
122
+ await waitForRenderedTree(viewport);
123
+ return { kind: 'rendered', type: targetArg.kind };
124
+ }
125
+ catch (error) {
126
+ console.error(`wcctools: rendering "${itemNameArg}" failed`, error);
127
+ const emptyState = {
128
+ title: `${itemNameArg} failed to render`,
129
+ detail: error instanceof Error ? error.message : String(error),
130
+ };
131
+ this.showEmptyState(viewport, emptyState, generationArg);
132
+ return { kind: 'empty', reason: 'failed', emptyState };
133
+ }
134
+ }
135
+ showEmptyState(viewportArg, emptyStateArg, generationArg) {
136
+ if (generationArg !== this.renderGeneration) {
137
+ return;
138
+ }
139
+ render(html ``, viewportArg);
140
+ this.preview.emptyState = emptyStateArg;
141
+ }
142
+ /** Keep the document's URL on what it shows, so a live reload comes back to it. */
143
+ writeRoute() {
144
+ const query = plugins.shared.formatPreviewQuery({ selection: this.rendered?.selection ?? null, theme: this.theme });
145
+ window.history.replaceState(window.history.state, '', `${window.location.pathname}${query}`);
146
+ }
147
+ emit(eventArg) {
148
+ for (const listener of this.listeners) {
149
+ listener(eventArg);
150
+ }
151
+ }
152
+ }
153
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJldmlld2JyaWRnZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3dlYi9wcmV2aWV3YnJpZGdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDM0QsT0FBTyxLQUFLLE9BQU8sTUFBTSx1QkFBdUIsQ0FBQztBQUVqRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsc0JBQXNCLEVBQW1DLE1BQU0sZ0NBQWdDLENBQUM7QUFFOUgsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFXeEQ7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGdCQUFnQjtJQVNSO0lBQ0E7SUFURixTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQXFDLENBQUM7SUFDbEUsS0FBSyxHQUFpQyxNQUFNLENBQUM7SUFDN0MsUUFBUSxHQUEwQixJQUFJLENBQUM7SUFDdkMsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0lBQzdCLDJGQUEyRjtJQUNuRixhQUFhLEdBQXFCLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUU1RCxZQUNtQixPQUFtQixFQUNuQixPQUFtQjtRQURuQixZQUFPLEdBQVAsT0FBTyxDQUFZO1FBQ25CLFlBQU8sR0FBUCxPQUFPLENBQVk7SUFDbkMsQ0FBQztJQUVHLFdBQVc7UUFDaEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ3BDLENBQUM7SUFFTSxZQUFZO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDMUUsQ0FBQztJQUVNLFFBQVE7UUFDYixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7SUFDcEIsQ0FBQztJQUVELDZEQUE2RDtJQUN0RCxLQUFLLENBQUMsV0FBVyxDQUFDLFFBQXlDO1FBQ2hFLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEMsTUFBTSxJQUFJLENBQUMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUNqRCxDQUFDO0lBRU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxZQUE4QztRQUNoRSxNQUFNLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsR0FBRyxZQUFZLENBQUM7UUFDMUQsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFTSxLQUFLLENBQUMsUUFBUSxDQUFDLFFBQXNDO1FBQzFELElBQUksQ0FBQyxLQUFLLEdBQUcsUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDdkQsTUFBTSxRQUFRLEdBQUcsTUFBTSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUNqRSxJQUFJLENBQUMsS0FBSyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM1RixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVNLEtBQUssQ0FBQyxhQUFhO1FBQ3hCLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUN6QixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQy9CLElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO1lBQ2pFLE9BQU8sRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxzQkFBc0IsRUFBRSxDQUFDO1FBQ2pFLENBQUM7UUFDRCxJQUFJLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ3JDLE9BQU8sRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxzQkFBc0IsRUFBRSxDQUFDO1FBQ2pFLENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM3QyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDZCxPQUFPLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsZUFBZSxRQUFRLENBQUMsU0FBUyxDQUFDLFFBQVEsZ0JBQWdCLGNBQWMsQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsUUFBUSxhQUFhLEVBQUUsQ0FBQztRQUM5TCxDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3hGLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUNoQixPQUFPLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLFFBQVEsc0NBQXNDLEVBQUUsQ0FBQztRQUMvRyxDQUFDO1FBQ0QsT0FBTyxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsV0FBVyxFQUFFLFFBQVEsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQ3RGLENBQUM7SUFFTSxXQUFXLENBQUMsT0FBZSxFQUFFLFFBQStDO1FBQ2pGLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1FBQ2hELE9BQU8sVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSx5QkFBeUIsRUFBRSxDQUFDO0lBQzFHLENBQUM7SUFFTSxlQUFlLENBQUMsT0FBZSxFQUFFLE9BQWU7UUFDckQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDaEQsT0FBTyxVQUFVLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLHlCQUF5QixFQUFFLENBQUM7SUFDN0csQ0FBQztJQUVNLG9CQUFvQjtRQUN6QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLFlBQVksQ0FBQztRQUNqRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxhQUFhLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLFlBQVksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQy9CLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE9BQU8sbUJBQW1CLENBQUMsUUFBUSxFQUFFLFlBQWdELENBQUMsQ0FBQztJQUN6RixDQUFDO0lBRU0sU0FBUyxDQUFDLFdBQThDO1FBQzdELElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQ2hDLE9BQU8sR0FBRyxFQUFFO1lBQ1YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDckMsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVPLHFCQUFxQjtRQUMzQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztRQUM3QyxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzFGLENBQUM7SUFFTyxLQUFLLENBQUMsZUFBZSxDQUMzQixZQUFxRDtRQUVyRCxNQUFNLFVBQVUsR0FBRyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQztRQUMzQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNsRCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxZQUFZLEVBQUUsUUFBUSxJQUFJLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUMxRixJQUFJLENBQUMsYUFBYSxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxhQUFhLENBQUM7UUFDcEMsSUFBSSxVQUFVLEtBQUssSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDekMsSUFBSSxDQUFDLFFBQVEsR0FBRztnQkFDZCxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUk7Z0JBQ3BELFlBQVksRUFBRSxNQUFNLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFDcEUsT0FBTzthQUNSLENBQUM7WUFDRixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxZQUFZLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFDRCxPQUFPLE9BQU8sQ0FBQztJQUNqQixDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVksQ0FDeEIsU0FBNEIsRUFDNUIsV0FBbUIsRUFDbkIsYUFBcUI7UUFFckIsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDekQsSUFBSSxTQUFTLENBQUMsSUFBSSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFLFNBQVMsQ0FBQyxVQUFVLEVBQUUsYUFBYSxDQUFDLENBQUM7WUFDbkUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLFNBQVMsQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN2RixDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQUcsTUFBTSxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDakUsSUFBSSxhQUFhLEtBQUssSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7Z0JBQzVDLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDcEQsQ0FBQztZQUNELE1BQU0sQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDM0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO1lBQy9CLE1BQU0sbUJBQW1CLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDcEMsT0FBTyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNwRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0JBQXdCLFdBQVcsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ3BFLE1BQU0sVUFBVSxHQUFHO2dCQUNqQixLQUFLLEVBQUUsR0FBRyxXQUFXLG1CQUFtQjtnQkFDeEMsTUFBTSxFQUFFLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7YUFDL0QsQ0FBQztZQUNGLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFLFVBQVUsRUFBRSxhQUFhLENBQUMsQ0FBQztZQUN6RCxPQUFPLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxDQUFDO1FBQ3pELENBQUM7SUFDSCxDQUFDO0lBRU8sY0FBYyxDQUNwQixXQUF3QixFQUN4QixhQUFnRCxFQUNoRCxhQUFxQjtRQUVyQixJQUFJLGFBQWEsS0FBSyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUM1QyxPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sQ0FBQyxJQUFJLENBQUEsRUFBRSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxHQUFHLGFBQWEsQ0FBQztJQUMxQyxDQUFDO0lBRUQsbUZBQW1GO0lBQzNFLFVBQVU7UUFDaEIsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLFNBQVMsSUFBSSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3BILE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsUUFBUSxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDL0YsQ0FBQztJQUVPLElBQUksQ0FBQyxRQUF1QjtRQUNsQyxLQUFLLE1BQU0sUUFBUSxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN0QyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDckIsQ0FBQztJQUNILENBQUM7Q0FDRiJ9
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Resolves once every Lit element below the root, including the ones their updates create,
3
+ * has completed its pending update.
4
+ */
5
+ export declare const waitForRenderedTree: (rootArg: Element | ShadowRoot) => Promise<void>;
@@ -0,0 +1,37 @@
1
+ const isUpdatingElement = (elementArg) => {
2
+ const updateComplete = elementArg.updateComplete;
3
+ return typeof updateComplete?.then === 'function';
4
+ };
5
+ const collectUpdatingElements = (rootArg) => {
6
+ const result = [];
7
+ const pending = Array.from(rootArg.children);
8
+ for (let index = 0; index < pending.length; index++) {
9
+ const element = pending[index];
10
+ if (isUpdatingElement(element)) {
11
+ result.push(element);
12
+ }
13
+ pending.push(...element.children);
14
+ if (element.shadowRoot) {
15
+ pending.push(...element.shadowRoot.children);
16
+ }
17
+ }
18
+ return result;
19
+ };
20
+ /**
21
+ * Resolves once every Lit element below the root, including the ones their updates create,
22
+ * has completed its pending update.
23
+ */
24
+ export const waitForRenderedTree = async (rootArg) => {
25
+ const settled = new Set();
26
+ for (;;) {
27
+ const pending = collectUpdatingElements(rootArg).filter((elementArg) => !settled.has(elementArg));
28
+ if (pending.length === 0) {
29
+ return;
30
+ }
31
+ await Promise.all(pending.map((elementArg) => elementArg.updateComplete));
32
+ for (const element of pending) {
33
+ settled.add(element);
34
+ }
35
+ }
36
+ };
37
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyZWR0cmVlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViL3JlbmRlcmVkdHJlZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFLQSxNQUFNLGlCQUFpQixHQUFHLENBQUMsVUFBbUIsRUFBa0MsRUFBRTtJQUNoRixNQUFNLGNBQWMsR0FBSSxVQUF3QyxDQUFDLGNBQWMsQ0FBQztJQUNoRixPQUFPLE9BQU8sY0FBYyxFQUFFLElBQUksS0FBSyxVQUFVLENBQUM7QUFDcEQsQ0FBQyxDQUFDO0FBRUYsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLE9BQTZCLEVBQXNCLEVBQUU7SUFDcEYsTUFBTSxNQUFNLEdBQXVCLEVBQUUsQ0FBQztJQUN0QyxNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3QyxLQUFLLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ3BELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMvQixJQUFJLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDL0IsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2QixDQUFDO1FBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsQyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUN2QixPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMvQyxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUMsQ0FBQztBQUVGOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLEtBQUssRUFBRSxPQUE2QixFQUFpQixFQUFFO0lBQ3hGLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFXLENBQUM7SUFDbkMsU0FBUyxDQUFDO1FBQ1IsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQztRQUNsRyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDekIsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFDMUUsS0FBSyxNQUFNLE9BQU8sSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7SUFDSCxDQUFDO0FBQ0gsQ0FBQyxDQUFDIn0=
@@ -1,11 +1,12 @@
1
+ import type { TWccSectionType } from '../dist_ts_interfaces/index.js';
1
2
  /**
2
- * Configuration for a section in the WCC Tools sidebar
3
+ * Configuration for a section of the catalog
3
4
  */
4
5
  export interface IWccSection {
5
6
  /** Display name for the section header */
6
7
  name: string;
7
8
  /** How items in this section are rendered - 'elements' show demos, 'pages' render directly */
8
- type: 'elements' | 'pages';
9
+ type: TWccSectionType;
9
10
  /** The items in this section - either element classes or page factory functions */
10
11
  items: Record<string, any>;
11
12
  /** Optional filter function to include/exclude items */
@@ -23,7 +24,3 @@ export interface IWccSection {
23
24
  export interface IWccConfig {
24
25
  sections: IWccSection[];
25
26
  }
26
- /**
27
- * Type for element selection types - now section-based
28
- */
29
- export type TElementType = 'element' | 'page';
@@ -1,2 +1,2 @@
1
1
  export {};
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjdG9vbHMuaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3dlYi93Y2N0b29scy5pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjdG9vbHMuaW50ZXJmYWNlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3dlYi93Y2N0b29scy5pbnRlcmZhY2VzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
@@ -1,2 +1,4 @@
1
1
  import * as deesDomtools from '@design.estate/dees-domtools';
2
- export { deesDomtools };
2
+ import * as interfaces from '../dist_ts_interfaces/index.js';
3
+ import * as shared from '../dist_ts_shared/index.js';
4
+ export { deesDomtools, interfaces, shared, };
@@ -1,3 +1,5 @@
1
1
  import * as deesDomtools from '@design.estate/dees-domtools';
2
- export { deesDomtools };
3
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjdG9vbHMucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzX3dlYi93Y2N0b29scy5wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxZQUFZLE1BQU0sOEJBQThCLENBQUM7QUFFN0QsT0FBTyxFQUNMLFlBQVksRUFDYixDQUFDIn0=
2
+ import * as interfaces from '../dist_ts_interfaces/index.js';
3
+ import * as shared from '../dist_ts_shared/index.js';
4
+ export { deesDomtools, interfaces, shared, };
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2NjdG9vbHMucGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzX3dlYi93Y2N0b29scy5wbHVnaW5zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxZQUFZLE1BQU0sOEJBQThCLENBQUM7QUFFN0QsT0FBTyxLQUFLLFVBQVUsTUFBTSwyQkFBMkIsQ0FBQztBQUN4RCxPQUFPLEtBQUssTUFBTSxNQUFNLHVCQUF1QixDQUFDO0FBRWhELE9BQU8sRUFDTCxZQUFZLEVBQ1osVUFBVSxFQUNWLE1BQU0sR0FDUCxDQUFDIn0=
package/package.json CHANGED
@@ -1,30 +1,38 @@
1
1
  {
2
2
  "name": "@design.estate/wcctools",
3
- "version": "5.1.0",
3
+ "version": "6.0.0",
4
4
  "private": false,
5
5
  "description": "A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.",
6
+ "bin": {
7
+ "wcctools": "./cli.js"
8
+ },
6
9
  "exports": {
7
- ".": "./dist_ts_web/index.js"
10
+ ".": "./dist_ts_web/index.js",
11
+ "./interfaces": "./dist_ts_interfaces/index.js"
8
12
  },
9
13
  "type": "module",
10
14
  "author": "Lossless GmbH",
11
15
  "license": "MIT",
12
16
  "dependencies": {
17
+ "@api.global/typedrequest": "^8.2.0",
18
+ "@api.global/typedrequest-interfaces": "^7.1.0",
19
+ "@api.global/typedserver": "^14.2.1",
13
20
  "@design.estate/dees-domtools": "^5.0.0",
14
21
  "@design.estate/dees-element": "^4.0.0",
15
- "lit": "^3.3.2",
16
- "mediabunny": "^1.40.1"
22
+ "@git.zone/tswatch": "^6.0.1",
23
+ "@push.rocks/smartconsole": "^2.1.0",
24
+ "@push.rocks/smartexit": "^2.2.0",
25
+ "lit": "^3.3.2"
17
26
  },
18
27
  "devDependencies": {
19
- "@api.global/typedserver": "^8.4.7",
20
28
  "@git.zone/tsbuild": "^5.1.2",
21
29
  "@git.zone/tsbundle": "^3.1.3",
22
30
  "@git.zone/tsdoc": "^3.0.2",
23
31
  "@git.zone/tsrun": "^3.0.2",
24
32
  "@git.zone/tstest": "^7.1.0",
25
- "@git.zone/tswatch": "^6.0.1",
26
33
  "@push.rocks/projectinfo": "^5.1.0",
27
- "@types/node": "^26.6.3"
34
+ "@types/node": "^26.6.3",
35
+ "mediabunny": "^1.40.1"
28
36
  },
29
37
  "files": [
30
38
  "ts/**/*",
@@ -58,7 +66,7 @@
58
66
  "scripts": {
59
67
  "test": "pnpm run build && tstest \"test/test.*.*.ts\" --verbose --logfile",
60
68
  "build": "(tsbuild tsfolders --allowimplicitany && tsbundle)",
61
- "watch": "tswatch",
69
+ "watch": "pnpm run build && node ./cli.ts.js dev",
62
70
  "buildDocs": "tsdoc"
63
71
  }
64
72
  }
package/readme.md CHANGED
@@ -6,10 +6,11 @@
6
6
 
7
7
  `@design.estate/wcctools` provides a comprehensive development environment for web components, featuring:
8
8
 
9
+ - 🖥️ **`wcctools dev`** — One command bundles your catalogue with live reload and serves it in the wcctools shell
9
10
  - 🎨 **Interactive Component Catalogue** — Live preview with customizable sidebar sections
10
11
  - 🔧 **Real-time Property Editing** — Modify component props on the fly with auto-detected editors
11
12
  - 🌓 **Theme Switching** — Test light/dark modes instantly
12
- - 📱 **Responsive Viewport Testing** — Phone, phablet, tablet, and desktop views
13
+ - 📱 **Responsive Viewport Testing** — Phone, phablet, tablet, and desktop views in a frame of the exact width, so width media queries respond
13
14
  - 🎬 **Screen Recording** — Record component demos with audio, trimming, and MP4/WebM export
14
15
  - 🧪 **Advanced Demo Tools** — Post-render hooks for interactive testing
15
16
  - 📂 **Section-based Organization** — Group components into custom sections with filtering and sorting
@@ -45,6 +46,16 @@ import { setupWccTools } from '@design.estate/wcctools';
45
46
 
46
47
  A catalogue still on a 4.x or older release also follows the 5.0.0 changes: [`setupWccTools()` takes only the config object](#migration-from-setupwcctoolselements-pages) and [`DeesDemoWrapper` moved to `@design.estate/dees-element/demotools`](#-demo-tools).
47
48
 
49
+ ### Migrating to 6.0.0
50
+
51
+ 6.0.0 splits the catalogue into two documents. The **shell** (sidebar, properties panel, recorder) is prebuilt into the package and served by the new `wcctools dev` command; your catalogue bundle runs as the **preview** document in a same-origin iframe that is exactly as wide as the selected viewport. Your `html/index.ts` and `html/index.html` stay as they are.
52
+
53
+ 1. Keep `@design.estate/wcctools` as a devDependency at `^6.0.0`.
54
+ 2. Replace the `watch` script: `"watch": "wcctools dev"` (it reads the same `@git.zone/tswatch` configuration from `.smartconfig.json`, or uses tswatch's `element` preset).
55
+ 3. Open the address `wcctools dev` prints (`http://localhost:<port>/wcctools/`).
56
+
57
+ Opened outside `wcctools dev` (for example from plain `tswatch`), the catalogue bundle shows a notice that names the command instead of the catalogue UI. `RecorderService`, `WccRecordButton` and `WccRecordingPanel` are no longer exported: recording lives in the shell.
58
+
48
59
  ## Quick Start
49
60
 
50
61
  ### 1. Create Your Component
@@ -98,9 +109,8 @@ export class MyButton extends DeesElement {
98
109
  ### 2. Set Up Your Catalogue
99
110
 
100
111
  ```typescript
101
- // catalogue.ts
112
+ // html/index.ts
102
113
  import { setupWccTools } from '@design.estate/wcctools';
103
- import { html } from 'lit';
104
114
 
105
115
  // Import your components
106
116
  import * as elements from './components/index.js';
@@ -133,19 +143,30 @@ setupWccTools({
133
143
 
134
144
  ### 3. Create an HTML Entry Point
135
145
 
146
+ `wcctools dev` bundles `html/index.ts` to `dist_watch/bundle.js` and serves `html/index.html` as the preview document:
147
+
136
148
  ```html
137
149
  <!DOCTYPE html>
138
150
  <html>
139
151
  <head>
140
152
  <title>Component Catalogue</title>
141
153
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
154
+ <script type="module" src="/bundle.js"></script>
142
155
  </head>
143
156
  <body style="margin: 0; padding: 0;">
144
- <script type="module" src="./catalogue.js"></script>
145
157
  </body>
146
158
  </html>
147
159
  ```
148
160
 
161
+ ### 4. Run the Catalogue
162
+
163
+ ```bash
164
+ pnpm exec wcctools dev # port from the tswatch configuration, else 3002
165
+ pnpm exec wcctools dev --port 0 # any free port
166
+ ```
167
+
168
+ It prints the shell's address, for example `wcctools dev: http://localhost:3002/wcctools/`. Saving a source file rebuilds the bundle and reloads only the preview frame; the shell keeps its state. `Ctrl+C` stops the server and the watchers.
169
+
149
170
  ## 📂 Sections Configuration
150
171
 
151
172
  The sections-based API gives you full control over how components are organized in the sidebar.
@@ -258,7 +279,9 @@ Test your components across different screen sizes:
258
279
  - **Tablet** — 1024px width
259
280
  - **Desktop** — Available preview width
260
281
 
261
- On browser viewports up to 600px wide, the catalogue sidebar moves above the preview and the property controls wrap into a compact bottom toolbar. Selecting phone, phablet, or tablet still gives the preview container its exact target width; wider targets scroll inside the frame instead of widening the document.
282
+ The preview document runs in an iframe of the selected width, so both width `@media` queries and `wccToolsViewport` container queries respond to it.
283
+
284
+ On browser viewports up to 600px wide, the catalogue sidebar moves above the preview and the property controls wrap into a compact bottom toolbar. Selecting phone, phablet, or tablet still gives the preview frame its exact target width; wider targets scroll inside the frame instead of widening the document.
262
285
 
263
286
  ### 🌓 Theme Support
264
287
 
@@ -371,7 +394,7 @@ public static demo = async () => {
371
394
 
372
395
  ### 🎯 Container Queries
373
396
 
374
- Components can respond to their container size using the `wccToolsViewport` container:
397
+ Components can respond to their container size using the `wccToolsViewport` container, which wraps every rendered demo in the preview document:
375
398
 
376
399
  ```typescript
377
400
  public static styles = [
@@ -442,13 +465,13 @@ The sidebar is an ARIA tree with a single tab stop (the selected entry, or the l
442
465
  | `Enter` / `Space` | Open the entry (or toggle a header) |
443
466
  | `ContextMenu` / `Shift+F10` | Open the entry's context menu (pin, show in group) at the entry; `↑` / `↓` / `Home` / `End` move, `Enter` / `Space` act, `Esc` / `Tab` close — focus returns to the entry |
444
467
 
445
- The sidebar resize handle is a focusable separator: `←` / `→` resize by 10 px (`Shift` for 50 px), `Home` / `End` jump to the minimum / maximum width. Theme and viewport controls are toggle buttons (`aria-pressed`), and `Esc` leaves the native viewport.
468
+ The sidebar resize handle is a focusable separator: `←` / `→` resize by 10 px (`Shift` for 50 px), `Home` / `End` jump to the minimum / maximum width. Theme and viewport controls are toggle buttons (`aria-pressed`), and `Esc` leaves the native viewport, also while the focus is inside the preview.
446
469
 
447
470
  Rendered demos keep their state while you search, pin, resize the sidebar, or switch theme or viewport; only selecting another entry or demo renders a new one.
448
471
 
449
472
  ## URL Routing
450
473
 
451
- The catalogue uses URL routing for deep linking:
474
+ The shell uses URL routing for deep linking:
452
475
 
453
476
  ```
454
477
  /wcctools-route/:sectionName/:itemName/:demoIndex/:viewport/:theme
@@ -459,11 +482,30 @@ Examples:
459
482
  /wcctools-route/Pages/home/0/desktop/dark
460
483
  ```
461
484
 
485
+ The preview document alone renders one demo from its own route, for tools that capture a single element:
486
+
487
+ ```
488
+ /wcctools-preview?section=Elements&item=my-button&demo=0&theme=dark
489
+ ```
490
+
462
491
  ## API Reference
463
492
 
493
+ ### `wcctools dev [--port <port>]`
494
+
495
+ Bundles and watches the catalogue as the project's `@git.zone/tswatch` configuration describes (or tswatch's `element` preset) and serves on one port:
496
+
497
+ | Path | Serves |
498
+ |------|--------|
499
+ | `/` | Redirects to `/wcctools/` |
500
+ | `/wcctools/`, `/wcctools-route/...` | The shell |
501
+ | `/wcctools/typedrequest` | The shell's typed API |
502
+ | every other path | The catalogue's serve directory (default `dist_watch/`), with live reload for the preview document |
503
+
504
+ `--port` overrides the configured port; `0` picks a free port.
505
+
464
506
  ### `setupWccTools(config)`
465
507
 
466
- Initialize the WCC Tools dashboard with sections configuration.
508
+ Sets up the catalogue's preview document with sections configuration. The shell reads a data-only description of the sections from it; element classes and template factories never leave the preview document.
467
509
 
468
510
  ```typescript
469
511
  interface IWccSection {
@@ -496,26 +538,16 @@ The wrapper provides full DOM API access:
496
538
  - `wrapper.querySelectorAll()` — Find multiple elements
497
539
  - `wrapper.children` — Access child elements directly
498
540
 
499
- ### Recording Components (Advanced)
541
+ ### `@design.estate/wcctools/interfaces`
500
542
 
501
- For custom recording integrations:
543
+ The contracts between the shell, the preview document and the dev server, for tools that drive a preview: the catalogue manifest (`IWccCatalogManifest`), the preview bridge the preview document installs as `window.wccPreview` (`IWccPreviewBridge`: render a demo, switch the theme, read and edit the rendered element's properties) and the dev server's typed requests.
502
544
 
503
545
  ```typescript
504
- import { RecorderService, type TOutputFormat } from '@design.estate/wcctools';
505
-
506
- const recorder = new RecorderService({
507
- onDurationUpdate: (duration) => console.log(`${duration}s`),
508
- onRecordingComplete: (blob) => console.log('Recording done!', blob),
509
- onAudioLevelUpdate: (level) => console.log(`Audio: ${level}%`),
510
- });
511
-
512
- // Record (always captures as WebM internally)
513
- await recorder.startRecording({ mode: 'viewport' });
514
- // ... later
515
- recorder.stopRecording();
546
+ import type { IWccPreviewBridge } from '@design.estate/wcctools/interfaces';
516
547
 
517
- // Convert to MP4 for universal playback (H.264 + AAC via WebCodecs)
518
- const mp4Blob = await recorder.convertToMp4(recorder.recordedBlob);
548
+ const bridge: IWccPreviewBridge = previewFrame.contentWindow.wccPreview;
549
+ await bridge.render({ sectionName: 'Elements', itemName: 'MyButton', demoIndex: 0 });
550
+ const properties = await bridge.getProperties();
519
551
  ```
520
552
 
521
553
  ## Project Structure
@@ -533,10 +565,10 @@ my-component-library/
533
565
  │ ├── pages/ # Documentation pages
534
566
  │ │ ├── home.ts
535
567
  │ │ └── index.ts
536
- │ └── catalogue.ts # WCC Tools setup
537
568
  ├── html/
538
- │ └── index.html
539
- └── package.json
569
+ │ ├── index.ts # setupWccTools: the catalogue
570
+ │ └── index.html # the preview document
571
+ └── package.json # "watch": "wcctools dev"
540
572
  ```
541
573
 
542
574
  ## Browser Support
@@ -0,0 +1,8 @@
1
+ /**
2
+ * autocreated commitinfo by @push.rocks/commitinfo
3
+ */
4
+ export const commitinfo = {
5
+ name: '@design.estate/wcctools',
6
+ version: '6.0.0',
7
+ description: 'A set of web component tools for creating element catalogues, enabling the structured development and documentation of custom elements and pages.'
8
+ }