@design.estate/wcctools 5.1.0 → 6.1.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 (262) hide show
  1. package/.smartconfig.json +7 -3
  2. package/changelog.md +28 -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 +51 -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 +20 -0
  22. package/dist_ts/plugins.js +27 -0
  23. package/dist_ts/shellcontent.d.ts +9 -0
  24. package/dist_ts/shellcontent.js +42 -0
  25. package/dist_ts/standards/baselines.d.ts +27 -0
  26. package/dist_ts/standards/baselines.js +83 -0
  27. package/dist_ts/standards/checker.d.ts +21 -0
  28. package/dist_ts/standards/checker.js +88 -0
  29. package/dist_ts/standards/classes.gitrepo.d.ts +13 -0
  30. package/dist_ts/standards/classes.gitrepo.js +43 -0
  31. package/dist_ts/standards/classes.sourceedits.d.ts +15 -0
  32. package/dist_ts/standards/classes.sourceedits.js +54 -0
  33. package/dist_ts/standards/classes.standardfixer.d.ts +40 -0
  34. package/dist_ts/standards/classes.standardfixer.js +210 -0
  35. package/dist_ts/standards/classes.standardproject.d.ts +80 -0
  36. package/dist_ts/standards/classes.standardproject.js +195 -0
  37. package/dist_ts/standards/classes.standardtree.d.ts +56 -0
  38. package/dist_ts/standards/classes.standardtree.js +207 -0
  39. package/dist_ts/standards/cli.d.ts +7 -0
  40. package/dist_ts/standards/cli.js +89 -0
  41. package/dist_ts/standards/config.d.ts +33 -0
  42. package/dist_ts/standards/config.js +139 -0
  43. package/dist_ts/standards/errors.d.ts +9 -0
  44. package/dist_ts/standards/errors.js +17 -0
  45. package/dist_ts/standards/helpers.ast.d.ts +56 -0
  46. package/dist_ts/standards/helpers.ast.js +172 -0
  47. package/dist_ts/standards/helpers.paths.d.ts +36 -0
  48. package/dist_ts/standards/helpers.paths.js +86 -0
  49. package/dist_ts/standards/index.d.ts +14 -0
  50. package/dist_ts/standards/index.js +15 -0
  51. package/dist_ts/standards/output.d.ts +7 -0
  52. package/dist_ts/standards/output.js +57 -0
  53. package/dist_ts/standards/ratchet.d.ts +15 -0
  54. package/dist_ts/standards/ratchet.js +45 -0
  55. package/dist_ts/standards/rule.d.ts +50 -0
  56. package/dist_ts/standards/rule.js +9 -0
  57. package/dist_ts/standards/rules/barrel.element-index.d.ts +7 -0
  58. package/dist_ts/standards/rules/barrel.element-index.js +108 -0
  59. package/dist_ts/standards/rules/barrel.no-demo-export.d.ts +3 -0
  60. package/dist_ts/standards/rules/barrel.no-demo-export.js +29 -0
  61. package/dist_ts/standards/rules/demo.fixture-not-exported.d.ts +3 -0
  62. package/dist_ts/standards/rules/demo.fixture-not-exported.js +29 -0
  63. package/dist_ts/standards/rules/demo.groups.d.ts +6 -0
  64. package/dist_ts/standards/rules/demo.groups.js +72 -0
  65. package/dist_ts/standards/rules/demo.required.d.ts +3 -0
  66. package/dist_ts/standards/rules/demo.required.js +48 -0
  67. package/dist_ts/standards/rules/demo.separate-file.d.ts +3 -0
  68. package/dist_ts/standards/rules/demo.separate-file.js +38 -0
  69. package/dist_ts/standards/rules/demo.shape.d.ts +3 -0
  70. package/dist_ts/standards/rules/demo.shape.js +38 -0
  71. package/dist_ts/standards/rules/docs.component-index.d.ts +8 -0
  72. package/dist_ts/standards/rules/docs.component-index.js +84 -0
  73. package/dist_ts/standards/rules/element.exported.d.ts +3 -0
  74. package/dist_ts/standards/rules/element.exported.js +33 -0
  75. package/dist_ts/standards/rules/element.literal-tag.d.ts +3 -0
  76. package/dist_ts/standards/rules/element.literal-tag.js +30 -0
  77. package/dist_ts/standards/rules/element.reachable.d.ts +3 -0
  78. package/dist_ts/standards/rules/element.reachable.js +48 -0
  79. package/dist_ts/standards/rules/element.tag-map.d.ts +3 -0
  80. package/dist_ts/standards/rules/element.tag-map.js +83 -0
  81. package/dist_ts/standards/rules/i18n.literals.d.ts +3 -0
  82. package/dist_ts/standards/rules/i18n.literals.js +52 -0
  83. package/dist_ts/standards/rules/index.d.ts +12 -0
  84. package/dist_ts/standards/rules/index.js +83 -0
  85. package/dist_ts/standards/rules/layout.element-folder.d.ts +3 -0
  86. package/dist_ts/standards/rules/layout.element-folder.js +47 -0
  87. package/dist_ts/standards/rules/layout.entry-file-name.d.ts +3 -0
  88. package/dist_ts/standards/rules/layout.entry-file-name.js +71 -0
  89. package/dist_ts/standards/rules/layout.entry.d.ts +3 -0
  90. package/dist_ts/standards/rules/layout.entry.js +38 -0
  91. package/dist_ts/standards/rules/layout.group-folder.d.ts +3 -0
  92. package/dist_ts/standards/rules/layout.group-folder.js +22 -0
  93. package/dist_ts/standards/rules/layout.shared-00.d.ts +3 -0
  94. package/dist_ts/standards/rules/layout.shared-00.js +36 -0
  95. package/dist_ts/standards/rules/naming.class-matches-tag.d.ts +3 -0
  96. package/dist_ts/standards/rules/naming.class-matches-tag.js +26 -0
  97. package/dist_ts/standards/rules/naming.lowercase-files.d.ts +3 -0
  98. package/dist_ts/standards/rules/naming.lowercase-files.js +26 -0
  99. package/dist_ts/standards/rules/naming.tag-prefix.d.ts +3 -0
  100. package/dist_ts/standards/rules/naming.tag-prefix.js +23 -0
  101. package/dist_ts/standards/rules/props.accessor.d.ts +3 -0
  102. package/dist_ts/standards/rules/props.accessor.js +35 -0
  103. package/dist_ts/standards/rules/props.object-no-attribute.d.ts +3 -0
  104. package/dist_ts/standards/rules/props.object-no-attribute.js +42 -0
  105. package/dist_ts/standards/rules/props.reflect-primitive.d.ts +5 -0
  106. package/dist_ts/standards/rules/props.reflect-primitive.js +41 -0
  107. package/dist_ts/standards/rules/props.typed.d.ts +6 -0
  108. package/dist_ts/standards/rules/props.typed.js +64 -0
  109. package/dist_ts/standards/rules/shared.d.ts +38 -0
  110. package/dist_ts/standards/rules/shared.js +103 -0
  111. package/dist_ts/standards/rules/style.bdtheme.d.ts +5 -0
  112. package/dist_ts/standards/rules/style.bdtheme.js +28 -0
  113. package/dist_ts_interfaces/bridge.d.ts +88 -0
  114. package/dist_ts_interfaces/bridge.js +2 -0
  115. package/dist_ts_interfaces/catalog.d.ts +32 -0
  116. package/dist_ts_interfaces/catalog.js +6 -0
  117. package/dist_ts_interfaces/index.d.ts +4 -0
  118. package/dist_ts_interfaces/index.js +5 -0
  119. package/dist_ts_interfaces/plugins.d.ts +2 -0
  120. package/dist_ts_interfaces/plugins.js +3 -0
  121. package/dist_ts_interfaces/requests.d.ts +15 -0
  122. package/dist_ts_interfaces/requests.js +2 -0
  123. package/dist_ts_interfaces/standard.d.ts +93 -0
  124. package/dist_ts_interfaces/standard.js +6 -0
  125. package/dist_ts_shared/index.d.ts +1 -0
  126. package/dist_ts_shared/index.js +2 -0
  127. package/dist_ts_shared/plugins.d.ts +2 -0
  128. package/dist_ts_shared/plugins.js +3 -0
  129. package/dist_ts_shared/previewroute.d.ts +18 -0
  130. package/dist_ts_shared/previewroute.js +47 -0
  131. package/{dist_ts_web → dist_ts_shell}/elements/wcc-contextmenu.js +1 -1
  132. package/dist_ts_shell/elements/wcc-preview-frame.d.ts +23 -0
  133. package/dist_ts_shell/elements/wcc-preview-frame.js +197 -0
  134. package/dist_ts_shell/elements/wcc-properties.d.ts +49 -0
  135. package/{dist_ts_web → dist_ts_shell}/elements/wcc-properties.js +149 -216
  136. package/{dist_ts_web → dist_ts_shell}/elements/wcc-record-button.js +1 -1
  137. package/{dist_ts_web → dist_ts_shell}/elements/wcc-recording-panel.d.ts +2 -2
  138. package/{dist_ts_web → dist_ts_shell}/elements/wcc-recording-panel.js +12 -16
  139. package/dist_ts_shell/elements/wcc-shell.d.ts +87 -0
  140. package/dist_ts_shell/elements/wcc-shell.js +524 -0
  141. package/{dist_ts_web → dist_ts_shell}/elements/wcc-sidebar.d.ts +12 -10
  142. package/{dist_ts_web → dist_ts_shell}/elements/wcc-sidebar.js +137 -183
  143. package/dist_ts_shell/index.d.ts +4 -0
  144. package/dist_ts_shell/index.js +5 -0
  145. package/dist_ts_shell/plugins.d.ts +4 -0
  146. package/dist_ts_shell/plugins.js +5 -0
  147. package/dist_ts_shell/previewconnection.d.ts +30 -0
  148. package/dist_ts_shell/previewconnection.js +86 -0
  149. package/dist_ts_shell/services/recorder.service.js +353 -0
  150. package/dist_ts_web/00_commitinfo_data.js +2 -2
  151. package/dist_ts_web/catalog.d.ts +45 -0
  152. package/dist_ts_web/catalog.js +153 -0
  153. package/dist_ts_web/elementproperties.d.ts +15 -0
  154. package/dist_ts_web/elementproperties.js +89 -0
  155. package/dist_ts_web/elements/wcc-preview.d.ts +19 -0
  156. package/dist_ts_web/elements/wcc-preview.js +164 -0
  157. package/dist_ts_web/elements/wcc-standalone-notice.d.ts +14 -0
  158. package/dist_ts_web/elements/wcc-standalone-notice.js +110 -0
  159. package/dist_ts_web/elements/wcctools.helpers.d.ts +2 -6
  160. package/dist_ts_web/elements/wcctools.helpers.js +1 -7
  161. package/dist_ts_web/index.d.ts +2 -5
  162. package/dist_ts_web/index.js +38 -17
  163. package/dist_ts_web/previewbridge.d.ts +39 -0
  164. package/dist_ts_web/previewbridge.js +153 -0
  165. package/dist_ts_web/renderedtree.d.ts +5 -0
  166. package/dist_ts_web/renderedtree.js +37 -0
  167. package/dist_ts_web/wcctools.interfaces.d.ts +3 -6
  168. package/dist_ts_web/wcctools.interfaces.js +1 -1
  169. package/dist_ts_web/wcctools.plugins.d.ts +3 -1
  170. package/dist_ts_web/wcctools.plugins.js +4 -2
  171. package/package.json +17 -7
  172. package/readme.md +93 -28
  173. package/ts/00_commitinfo_data.ts +8 -0
  174. package/ts/classes.devapi.ts +25 -0
  175. package/ts/classes.devserver.ts +161 -0
  176. package/ts/cli.ts +53 -0
  177. package/ts/index.ts +3 -0
  178. package/ts/paths.ts +7 -0
  179. package/ts/plugins.ts +37 -0
  180. package/ts/shellcontent.ts +42 -0
  181. package/ts/standards/baselines.ts +100 -0
  182. package/ts/standards/checker.ts +114 -0
  183. package/ts/standards/classes.gitrepo.ts +48 -0
  184. package/ts/standards/classes.sourceedits.ts +58 -0
  185. package/ts/standards/classes.standardfixer.ts +234 -0
  186. package/ts/standards/classes.standardproject.ts +250 -0
  187. package/ts/standards/classes.standardtree.ts +220 -0
  188. package/ts/standards/cli.ts +86 -0
  189. package/ts/standards/config.ts +160 -0
  190. package/ts/standards/errors.ts +18 -0
  191. package/ts/standards/helpers.ast.ts +208 -0
  192. package/ts/standards/helpers.paths.ts +119 -0
  193. package/ts/standards/index.ts +22 -0
  194. package/ts/standards/output.ts +65 -0
  195. package/ts/standards/ratchet.ts +63 -0
  196. package/ts/standards/rule.ts +58 -0
  197. package/ts/standards/rules/barrel.element-index.ts +112 -0
  198. package/ts/standards/rules/barrel.no-demo-export.ts +30 -0
  199. package/ts/standards/rules/demo.fixture-not-exported.ts +30 -0
  200. package/ts/standards/rules/demo.groups.ts +74 -0
  201. package/ts/standards/rules/demo.required.ts +49 -0
  202. package/ts/standards/rules/demo.separate-file.ts +40 -0
  203. package/ts/standards/rules/demo.shape.ts +42 -0
  204. package/ts/standards/rules/docs.component-index.ts +88 -0
  205. package/ts/standards/rules/element.exported.ts +35 -0
  206. package/ts/standards/rules/element.literal-tag.ts +30 -0
  207. package/ts/standards/rules/element.reachable.ts +49 -0
  208. package/ts/standards/rules/element.tag-map.ts +87 -0
  209. package/ts/standards/rules/i18n.literals.ts +58 -0
  210. package/ts/standards/rules/index.ts +87 -0
  211. package/ts/standards/rules/layout.element-folder.ts +49 -0
  212. package/ts/standards/rules/layout.entry-file-name.ts +73 -0
  213. package/ts/standards/rules/layout.entry.ts +40 -0
  214. package/ts/standards/rules/layout.group-folder.ts +23 -0
  215. package/ts/standards/rules/layout.shared-00.ts +37 -0
  216. package/ts/standards/rules/naming.class-matches-tag.ts +27 -0
  217. package/ts/standards/rules/naming.lowercase-files.ts +27 -0
  218. package/ts/standards/rules/naming.tag-prefix.ts +24 -0
  219. package/ts/standards/rules/props.accessor.ts +37 -0
  220. package/ts/standards/rules/props.object-no-attribute.ts +45 -0
  221. package/ts/standards/rules/props.reflect-primitive.ts +44 -0
  222. package/ts/standards/rules/props.typed.ts +70 -0
  223. package/ts/standards/rules/shared.ts +127 -0
  224. package/ts/standards/rules/style.bdtheme.ts +31 -0
  225. package/ts_web/00_commitinfo_data.ts +1 -1
  226. package/ts_web/catalog.ts +194 -0
  227. package/ts_web/elementproperties.ts +96 -0
  228. package/ts_web/elements/wcc-preview.ts +111 -0
  229. package/ts_web/elements/wcc-standalone-notice.ts +65 -0
  230. package/ts_web/elements/wcctools.helpers.ts +2 -10
  231. package/ts_web/index.ts +38 -19
  232. package/ts_web/previewbridge.ts +189 -0
  233. package/ts_web/readme.md +26 -85
  234. package/ts_web/renderedtree.ts +43 -0
  235. package/ts_web/wcctools.interfaces.ts +4 -7
  236. package/ts_web/wcctools.plugins.ts +6 -1
  237. package/dist_bundle/bundle.js +0 -92419
  238. package/dist_bundle/bundle.js.map +0 -1
  239. package/dist_ts_web/elements/wcc-dashboard.d.ts +0 -119
  240. package/dist_ts_web/elements/wcc-dashboard.js +0 -700
  241. package/dist_ts_web/elements/wcc-frame.d.ts +0 -22
  242. package/dist_ts_web/elements/wcc-frame.js +0 -256
  243. package/dist_ts_web/elements/wcc-properties.d.ts +0 -43
  244. package/dist_ts_web/pages/index.d.ts +0 -1
  245. package/dist_ts_web/pages/index.js +0 -2
  246. package/dist_ts_web/services/recorder.service.js +0 -353
  247. package/ts_web/elements/wcc-contextmenu.ts +0 -291
  248. package/ts_web/elements/wcc-dashboard.ts +0 -672
  249. package/ts_web/elements/wcc-frame.ts +0 -189
  250. package/ts_web/elements/wcc-properties.ts +0 -1089
  251. package/ts_web/elements/wcc-record-button.ts +0 -108
  252. package/ts_web/elements/wcc-recording-panel.ts +0 -1010
  253. package/ts_web/elements/wcc-sidebar.ts +0 -1470
  254. package/ts_web/pages/index.ts +0 -1
  255. package/ts_web/services/recorder.service.ts +0 -451
  256. package/ts_web/types/dom-mediacapture-stub/index.d.ts +0 -12
  257. package/ts_web/types/dom-mediacapture-stub/package.json +0 -6
  258. package/ts_web/types/dom-webcodecs-stub/index.d.ts +0 -2
  259. package/ts_web/types/dom-webcodecs-stub/package.json +0 -6
  260. /package/{dist_ts_web → dist_ts_shell}/elements/wcc-contextmenu.d.ts +0 -0
  261. /package/{dist_ts_web → dist_ts_shell}/elements/wcc-record-button.d.ts +0 -0
  262. /package/{dist_ts_web → dist_ts_shell}/services/recorder.service.d.ts +0 -0
@@ -0,0 +1,65 @@
1
+ import { DeesElement, html, customElement, type TemplateResult, css } from '@design.estate/dees-element';
2
+
3
+ declare global {
4
+ interface HTMLElementTagNameMap {
5
+ 'wcc-standalone-notice': WccStandaloneNotice;
6
+ }
7
+ }
8
+
9
+ /**
10
+ * Shown when a catalog bundle is opened outside `wcctools dev`: the catalog UI lives in the
11
+ * wcctools shell, which loads this document into its preview frame.
12
+ */
13
+ @customElement('wcc-standalone-notice')
14
+ export class WccStandaloneNotice extends DeesElement {
15
+ public static styles = [
16
+ css`
17
+ :host {
18
+ position: fixed;
19
+ inset: 0;
20
+ display: flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ padding: 24px;
24
+ background: #0a0a0a;
25
+ color: #e5e5e5;
26
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
27
+ }
28
+ .card {
29
+ max-width: 480px;
30
+ padding: 24px 28px;
31
+ border: 1px solid rgba(255, 255, 255, 0.08);
32
+ border-radius: 8px;
33
+ background: #0f0f0f;
34
+ }
35
+ h1 {
36
+ margin: 0 0 8px;
37
+ font-size: 16px;
38
+ font-weight: 600;
39
+ }
40
+ p {
41
+ margin: 0 0 12px;
42
+ font-size: 13px;
43
+ line-height: 1.5;
44
+ color: #a3a3a3;
45
+ }
46
+ code {
47
+ padding: 2px 6px;
48
+ border-radius: 4px;
49
+ background: #1a1a1a;
50
+ color: #e5e5e5;
51
+ font-size: 12px;
52
+ }
53
+ `,
54
+ ];
55
+
56
+ public render(): TemplateResult {
57
+ return html`
58
+ <div class="card" role="status">
59
+ <h1>This catalog runs in wcctools dev</h1>
60
+ <p>The page you opened is the catalog's preview document. The catalog UI loads it into its preview frame.</p>
61
+ <p>Start it with <code>pnpm exec wcctools dev</code> and open the address it prints.</p>
62
+ </div>
63
+ `;
64
+ }
65
+ }
@@ -1,4 +1,5 @@
1
1
  import type { TemplateResult } from 'lit';
2
+ import type * as plugins from '../wcctools.plugins.js';
2
3
 
3
4
  export type TTemplateFactory = () => TemplateResult | Promise<TemplateResult>;
4
5
 
@@ -77,8 +78,6 @@ export const getElementDemoGroups = (itemArg: unknown): string[] => {
77
78
  return list.filter((groupArg): groupArg is string => typeof groupArg === 'string' && groupArg.length > 0);
78
79
  };
79
80
 
80
- export type TPropertyType = 'String' | 'Number' | 'Boolean' | 'Object' | 'Enum' | 'Array';
81
-
82
81
  export interface IReactivePropertyDeclaration {
83
82
  state?: boolean;
84
83
  type?: unknown;
@@ -97,7 +96,7 @@ const isEnumerationType = (typeArg: unknown): boolean => {
97
96
 
98
97
  export const determinePropertyType = (
99
98
  propertyArg: IReactivePropertyDeclaration
100
- ): TPropertyType | null => {
99
+ ): plugins.interfaces.TWccPropertyKind | null => {
101
100
  if (!propertyArg || typeof propertyArg !== 'object' || propertyArg.state) {
102
101
  return null;
103
102
  }
@@ -144,10 +143,3 @@ export const getDemoAtIndex = (demo: TDemoDefinition, index: number): TTemplateF
144
143
  // Single demo - only index 0 is valid
145
144
  return index === 0 ? demo : null;
146
145
  };
147
-
148
- /**
149
- * Check if an element has multiple demos
150
- */
151
- export const hasMultipleDemos = (demo: TDemoDefinition): boolean => {
152
- return Array.isArray(demo) && demo.length > 1;
153
- };
package/ts_web/index.ts CHANGED
@@ -1,16 +1,35 @@
1
- import { WccDashboard } from './elements/wcc-dashboard.js';
2
- import type { IWccConfig, IWccSection } from './wcctools.interfaces.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
+ import type { IWccConfig } from './wcctools.interfaces.js';
3
7
 
4
- // Export recording components and service
5
- export { RecorderService, type IRecorderEvents, type IRecordingOptions, type TOutputFormat } from './services/recorder.service.js';
6
- export { WccRecordButton } from './elements/wcc-record-button.js';
7
- export { WccRecordingPanel } from './elements/wcc-recording-panel.js';
8
-
9
- // Export types for external use
10
8
  export type { IWccConfig, IWccSection } from './wcctools.interfaces.js';
11
9
 
12
10
  /**
13
- * Set up the WCC Tools dashboard:
11
+ * Start the preview document of a catalog. `wcctools dev` loads this document into the shell's
12
+ * preview frame; opened on the preview route it renders the one demo the route names.
13
+ * Opened anywhere else it shows how to start the catalog.
14
+ */
15
+ const startPreview = async (configArg: IWccConfig) => {
16
+ const isFramed = window.parent !== window;
17
+ if (!isFramed && window.location.pathname !== plugins.shared.previewRoutePath) {
18
+ document.body.append(new WccStandaloneNotice());
19
+ return;
20
+ }
21
+ const preview = new WccPreview();
22
+ document.body.append(preview);
23
+ const bridge = new WccPreviewBridge(new WccCatalog(configArg), preview);
24
+ await bridge.renderRoute(plugins.shared.parsePreviewQuery(window.location.search));
25
+ window.wccPreview = bridge;
26
+ if (isFramed) {
27
+ window.parent.postMessage(plugins.shared.previewReadyMessage, window.location.origin);
28
+ }
29
+ };
30
+
31
+ /**
32
+ * Set up the catalog's preview document:
14
33
  * ```typescript
15
34
  * setupWccTools({
16
35
  * sections: [
@@ -20,17 +39,17 @@ export type { IWccConfig, IWccSection } from './wcctools.interfaces.js';
20
39
  * });
21
40
  * ```
22
41
  */
23
- const setupWccTools = (config: IWccConfig) => {
24
- let hasRun = false;
25
- const runWccToolsSetup = async () => {
26
- if (document.readyState === 'complete' && !hasRun) {
27
- hasRun = true;
28
- const wccTools = new WccDashboard(config);
29
- document.querySelector('body').append(wccTools);
30
- }
42
+ const setupWccTools = (configArg: IWccConfig) => {
43
+ const start = () => {
44
+ startPreview(configArg).catch((error) => {
45
+ console.error('wcctools: the preview failed to start', error);
46
+ });
31
47
  };
32
- document.addEventListener('readystatechange', runWccToolsSetup);
33
- runWccToolsSetup();
48
+ if (document.readyState === 'complete') {
49
+ start();
50
+ } else {
51
+ window.addEventListener('load', start, { once: true });
52
+ }
34
53
  };
35
54
 
36
55
  export {
@@ -0,0 +1,189 @@
1
+ import { html, render } from '@design.estate/dees-element';
2
+ import * as plugins from './wcctools.plugins.js';
3
+ import type { WccCatalog, TWccCatalogTarget } from './catalog.js';
4
+ import { WccElementProperties } from './elementproperties.js';
5
+ import { findElementInstance, resolveTemplateFactory, type ICatalogElementConstructor } from './elements/wcctools.helpers.js';
6
+ import type { WccPreview } from './elements/wcc-preview.js';
7
+ import { waitForRenderedTree } from './renderedtree.js';
8
+
9
+ type TPreviewEvent = plugins.interfaces.TWccPreviewEvent;
10
+
11
+ /** What the last render put on screen. */
12
+ interface IRenderedState {
13
+ selection: plugins.interfaces.IWccSelection | null;
14
+ elementClass: ICatalogElementConstructor | null;
15
+ outcome: plugins.interfaces.TWccRenderOutcome;
16
+ }
17
+
18
+ /**
19
+ * The preview document's side of the shell bridge: renders the catalog's demos and pages into
20
+ * the preview surface, switches its theme and reads and edits the rendered element's properties.
21
+ */
22
+ export class WccPreviewBridge implements plugins.interfaces.IWccPreviewBridge {
23
+ private readonly listeners = new Set<(eventArg: TPreviewEvent) => void>();
24
+ private theme: plugins.interfaces.TWccTheme = 'dark';
25
+ private rendered: IRenderedState | null = null;
26
+ private renderGeneration = 0;
27
+ /** Settles when the latest render, including its elements' first updates, has finished. */
28
+ private renderPromise: Promise<unknown> = Promise.resolve();
29
+
30
+ constructor(
31
+ private readonly catalog: WccCatalog,
32
+ private readonly preview: WccPreview,
33
+ ) {}
34
+
35
+ public getManifest(): plugins.interfaces.IWccCatalogManifest {
36
+ return this.catalog.getManifest();
37
+ }
38
+
39
+ public getSelection(): plugins.interfaces.IWccSelection | null {
40
+ return this.rendered?.selection ? { ...this.rendered.selection } : null;
41
+ }
42
+
43
+ public getTheme(): plugins.interfaces.TWccTheme {
44
+ return this.theme;
45
+ }
46
+
47
+ /** Render the preview route the document was loaded with. */
48
+ public async renderRoute(routeArg: plugins.shared.IWccPreviewRoute): Promise<void> {
49
+ await this.setTheme(routeArg.theme);
50
+ await this.renderSelection(routeArg.selection);
51
+ }
52
+
53
+ public async render(selectionArg: plugins.interfaces.IWccSelection): Promise<plugins.interfaces.TWccRenderOutcome> {
54
+ const { sectionName, itemName, demoIndex } = selectionArg;
55
+ return this.renderSelection({ sectionName, itemName, demoIndex });
56
+ }
57
+
58
+ public async setTheme(themeArg: plugins.interfaces.TWccTheme): Promise<void> {
59
+ this.theme = themeArg === 'bright' ? 'bright' : 'dark';
60
+ const domtools = await plugins.deesDomtools.elementBasic.setup();
61
+ this.theme === 'bright' ? domtools.themeManager.goBright() : domtools.themeManager.goDark();
62
+ this.writeRoute();
63
+ }
64
+
65
+ public async getProperties(): Promise<plugins.interfaces.TWccPropertyListing> {
66
+ await this.renderPromise;
67
+ const rendered = this.rendered;
68
+ if (!rendered?.selection || rendered.outcome.kind !== 'rendered') {
69
+ return { kind: 'unavailable', reason: 'Nothing is rendered.' };
70
+ }
71
+ if (rendered.outcome.type === 'page') {
72
+ return { kind: 'unavailable', reason: 'You selected a page.' };
73
+ }
74
+ const instance = this.findRenderedInstance();
75
+ if (!instance) {
76
+ return { kind: 'unavailable', reason: `The demo of ${rendered.selection.itemName} renders no <${customElements.getName(rendered.elementClass) ?? rendered.selection.itemName}> instance.` };
77
+ }
78
+ const properties = new WccElementProperties(rendered.elementClass, instance).describe();
79
+ if (!properties) {
80
+ return { kind: 'unavailable', reason: `${rendered.selection.itemName} does not expose element properties.` };
81
+ }
82
+ return { kind: 'properties', elementName: rendered.selection.itemName, properties };
83
+ }
84
+
85
+ public setProperty(nameArg: string, valueArg: plugins.interfaces.TWccPropertyScalar): plugins.interfaces.TWccPropertyEditResult {
86
+ const properties = this.getRenderedProperties();
87
+ return properties ? properties.set(nameArg, valueArg) : { ok: false, error: 'No element is rendered.' };
88
+ }
89
+
90
+ public setPropertyJson(nameArg: string, jsonArg: string): plugins.interfaces.TWccPropertyEditResult {
91
+ const properties = this.getRenderedProperties();
92
+ return properties ? properties.setJson(nameArg, jsonArg) : { ok: false, error: 'No element is rendered.' };
93
+ }
94
+
95
+ public findRenderedInstance(): HTMLElement | null {
96
+ const elementClass = this.rendered?.elementClass;
97
+ const viewport = this.preview.shadowRoot?.querySelector('.viewport');
98
+ if (!elementClass || !viewport) {
99
+ return null;
100
+ }
101
+ return findElementInstance(viewport, elementClass as unknown as new () => HTMLElement);
102
+ }
103
+
104
+ public subscribe(listenerArg: (eventArg: TPreviewEvent) => void): () => void {
105
+ this.listeners.add(listenerArg);
106
+ return () => {
107
+ this.listeners.delete(listenerArg);
108
+ };
109
+ }
110
+
111
+ private getRenderedProperties(): WccElementProperties | null {
112
+ const instance = this.findRenderedInstance();
113
+ return instance ? new WccElementProperties(this.rendered.elementClass, instance) : null;
114
+ }
115
+
116
+ private async renderSelection(
117
+ selectionArg: plugins.interfaces.IWccSelection | null,
118
+ ): Promise<plugins.interfaces.TWccRenderOutcome> {
119
+ const generation = ++this.renderGeneration;
120
+ const target = this.catalog.resolve(selectionArg);
121
+ const renderPromise = this.renderTarget(target, selectionArg?.itemName ?? '', generation);
122
+ this.renderPromise = renderPromise.catch(() => undefined);
123
+ const outcome = await renderPromise;
124
+ if (generation === this.renderGeneration) {
125
+ this.rendered = {
126
+ selection: selectionArg ? { ...selectionArg } : null,
127
+ elementClass: target.kind === 'element' ? target.elementClass : null,
128
+ outcome,
129
+ };
130
+ this.writeRoute();
131
+ this.emit({ type: 'rendered', selection: this.getSelection(), outcome });
132
+ }
133
+ return outcome;
134
+ }
135
+
136
+ private async renderTarget(
137
+ targetArg: TWccCatalogTarget,
138
+ itemNameArg: string,
139
+ generationArg: number,
140
+ ): Promise<plugins.interfaces.TWccRenderOutcome> {
141
+ const viewport = await this.preview.getViewportElement();
142
+ if (targetArg.kind === 'empty') {
143
+ this.showEmptyState(viewport, targetArg.emptyState, generationArg);
144
+ return { kind: 'empty', reason: targetArg.reason, emptyState: targetArg.emptyState };
145
+ }
146
+ try {
147
+ const template = await resolveTemplateFactory(targetArg.factory);
148
+ if (generationArg !== this.renderGeneration) {
149
+ return { kind: 'rendered', type: targetArg.kind };
150
+ }
151
+ render(template, viewport);
152
+ this.preview.emptyState = null;
153
+ await waitForRenderedTree(viewport);
154
+ return { kind: 'rendered', type: targetArg.kind };
155
+ } catch (error) {
156
+ console.error(`wcctools: rendering "${itemNameArg}" failed`, error);
157
+ const emptyState = {
158
+ title: `${itemNameArg} failed to render`,
159
+ detail: error instanceof Error ? error.message : String(error),
160
+ };
161
+ this.showEmptyState(viewport, emptyState, generationArg);
162
+ return { kind: 'empty', reason: 'failed', emptyState };
163
+ }
164
+ }
165
+
166
+ private showEmptyState(
167
+ viewportArg: HTMLElement,
168
+ emptyStateArg: plugins.interfaces.IWccEmptyState,
169
+ generationArg: number,
170
+ ) {
171
+ if (generationArg !== this.renderGeneration) {
172
+ return;
173
+ }
174
+ render(html``, viewportArg);
175
+ this.preview.emptyState = emptyStateArg;
176
+ }
177
+
178
+ /** Keep the document's URL on what it shows, so a live reload comes back to it. */
179
+ private writeRoute() {
180
+ const query = plugins.shared.formatPreviewQuery({ selection: this.rendered?.selection ?? null, theme: this.theme });
181
+ window.history.replaceState(window.history.state, '', `${window.location.pathname}${query}`);
182
+ }
183
+
184
+ private emit(eventArg: TPreviewEvent) {
185
+ for (const listener of this.listeners) {
186
+ listener(eventArg);
187
+ }
188
+ }
189
+ }
package/ts_web/readme.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## Overview
6
6
 
7
- This is the main module of `@design.estate/wcctools`, providing the complete dashboard experience for developing, testing, and documenting web components.
7
+ This is the main module (`.`) of `@design.estate/wcctools`: the **preview runtime** that runs inside a catalogue's own bundle. `setupWccTools()` classifies the catalogue, renders demos and pages into the preview document and installs the bridge (`window.wccPreview`) the wcctools shell drives it through. The shell itself (sidebar, properties panel, recorder) is prebuilt into the package and served by `wcctools dev`.
8
8
 
9
9
  ## Installation
10
10
 
@@ -60,20 +60,13 @@ In an `elements` section, only classes extending `HTMLElement` with a static `de
60
60
 
61
61
  | Export | Description |
62
62
  |--------|-------------|
63
- | `setupWccTools` | Initialize the component catalogue dashboard |
63
+ | `setupWccTools` | Set up the catalogue's preview document |
64
64
  | `IWccConfig` | TypeScript interface for sections configuration |
65
65
  | `IWccSection` | TypeScript interface for individual section |
66
66
 
67
- ### Recording Components
67
+ ### `@design.estate/wcctools/interfaces`
68
68
 
69
- | Export | Description |
70
- |--------|-------------|
71
- | `RecorderService` | Service class for screen/viewport recording and MP4 conversion |
72
- | `WccRecordButton` | Record button UI component |
73
- | `WccRecordingPanel` | Recording options and preview panel |
74
- | `IRecorderEvents` | TypeScript interface for recorder callbacks |
75
- | `IRecordingOptions` | TypeScript interface for recording options |
76
- | `TOutputFormat` | Type for output format selection (`'webm' \| 'mp4'`) |
69
+ The data-only contracts: the catalogue manifest, the preview bridge (`IWccPreviewBridge`) and the dev server's typed requests.
77
70
 
78
71
  ## Section Configuration
79
72
 
@@ -87,91 +80,39 @@ In an `elements` section, only classes extending `HTMLElement` with a static `de
87
80
  | `icon` | `string` | Material Symbols icon name |
88
81
  | `collapsed` | `boolean` | Start section collapsed (default: false) |
89
82
 
90
- ## Internal Components
91
-
92
- The module includes these internal web components:
93
-
94
- | Component | Description |
95
- |-----------|-------------|
96
- | `wcc-dashboard` | Main dashboard container with routing |
97
- | `wcc-sidebar` | Navigation sidebar with collapsible sections and search |
98
- | `wcc-frame` | Responsive viewport with size controls |
99
- | `wcc-properties` | Property panel with live editing |
100
- | `wcc-record-button` | Recording state indicator button |
101
- | `wcc-recording-panel` | Recording workflow UI with format selection |
102
-
103
- ## RecorderService API
104
-
105
- For programmatic recording and MP4 conversion:
106
-
107
- ```typescript
108
- import { RecorderService, type IRecorderEvents } from '@design.estate/wcctools';
109
-
110
- const events: IRecorderEvents = {
111
- onDurationUpdate: (duration) => console.log(`Recording: ${duration}s`),
112
- onRecordingComplete: (blob) => saveBlob(blob),
113
- onAudioLevelUpdate: (level) => updateMeter(level),
114
- onError: (error) => console.error(error),
115
- onStreamEnded: () => console.log('User stopped sharing'),
116
- };
83
+ ## Where the Preview Runs
117
84
 
118
- const recorder = new RecorderService(events);
119
-
120
- // Load available microphones
121
- const mics = await recorder.loadMicrophones(true);
122
-
123
- // Start audio level monitoring
124
- await recorder.startAudioMonitoring(mics[0].deviceId);
125
-
126
- // Start recording (always captures as WebM internally at up to 60fps)
127
- await recorder.startRecording({
128
- mode: 'viewport',
129
- audioDeviceId: mics[0].deviceId,
130
- viewportElement: document.querySelector('.viewport'),
131
- });
132
-
133
- // Stop recording
134
- recorder.stopRecording();
135
-
136
- // Convert to MP4 for universal playback (H.264 + AAC via WebCodecs)
137
- const mp4Blob = await recorder.convertToMp4(recorder.recordedBlob);
138
-
139
- // Or export trimmed video
140
- const trimmedBlob = await recorder.exportTrimmedVideo(videoElement, startTime, endTime);
141
-
142
- // Cleanup
143
- recorder.dispose();
144
- ```
85
+ | Opened as | Behaviour |
86
+ |-----------|-----------|
87
+ | The shell's preview frame (`wcctools dev`) | Installs the bridge and reports ready to the shell; renders what the shell selects |
88
+ | `/wcctools-preview?section=…&item=…&demo=…&theme=…` | Renders that one demo alone; the bridge is available for headless tools |
89
+ | Anywhere else (for example plain `tswatch`) | Shows a notice naming `wcctools dev` |
145
90
 
146
91
  ## Architecture
147
92
 
148
93
  ```
149
- ts_web/
150
- ├── index.ts # Main exports
151
- ├── wcctools.interfaces.ts # Type definitions
152
- ├── types/
153
- │ ├── dom-webcodecs-stub/ # TS6 compatibility shim
154
- │ └── dom-mediacapture-stub/ # MediaCapture Transform types
155
- ├── elements/
156
- │ ├── wcc-dashboard.ts # Root dashboard component
157
- │ ├── wcc-sidebar.ts # Navigation sidebar
158
- │ ├── wcc-frame.ts # Responsive viewport
159
- │ ├── wcc-properties.ts # Property editing panel
160
- │ ├── wcc-record-button.ts # Recording button
161
- │ ├── wcc-recording-panel.ts # Recording options/preview
162
- │ └── wcctools.helpers.ts # Shared utilities
163
- ├── services/
164
- │ └── recorder.service.ts # MediaRecorder + mediabunny MP4 conversion
165
- └── pages/
166
- └── index.ts # Built-in pages
94
+ ts_web/ # preview runtime, exported as "."
95
+ ├── index.ts # setupWccTools
96
+ ├── catalog.ts # classification, manifest, selection resolution
97
+ ├── previewbridge.ts # IWccPreviewBridge implementation
98
+ ├── elementproperties.ts # editable properties of a rendered element
99
+ ├── renderedtree.ts # waits for a rendered tree's Lit updates
100
+ └── elements/
101
+ ├── wcc-preview.ts # render surface (wccToolsViewport container, empty states)
102
+ ├── wcc-standalone-notice.ts
103
+ └── wcctools.helpers.ts # classification and demo helpers
104
+ ts_shell/ # the shell, bundled to dist_shell/
105
+ ts_interfaces/ # contracts, exported as "./interfaces"
106
+ ts_shared/ # the preview route format
107
+ ts/ # wcctools CLI and dev server
167
108
  ```
168
109
 
169
110
  ## Features
170
111
 
171
- - 🎨 Interactive component preview
112
+ - 🎨 Interactive component preview at the exact viewport width
172
113
  - 📂 Section-based sidebar with filtering, sorting & search (by name, tag, or group)
173
114
  - 🔧 Real-time property editing with type detection
174
115
  - 🌓 Theme switching (light/dark)
175
- - 📱 Responsive viewport testing
116
+ - 📱 Responsive viewport testing with width media queries
176
117
  - 🎬 Screen recording with MP4/WebM export, trimming, and audio
177
118
  - 🔗 URL-based deep linking
@@ -0,0 +1,43 @@
1
+ /** An element with Lit's update lifecycle, identified by shape: catalogs may bundle their own Lit. */
2
+ interface IUpdatingElement extends Element {
3
+ updateComplete: Promise<unknown>;
4
+ }
5
+
6
+ const isUpdatingElement = (elementArg: Element): elementArg is IUpdatingElement => {
7
+ const updateComplete = (elementArg as Partial<IUpdatingElement>).updateComplete;
8
+ return typeof updateComplete?.then === 'function';
9
+ };
10
+
11
+ const collectUpdatingElements = (rootArg: Element | ShadowRoot): IUpdatingElement[] => {
12
+ const result: IUpdatingElement[] = [];
13
+ const pending = Array.from(rootArg.children);
14
+ for (let index = 0; index < pending.length; index++) {
15
+ const element = pending[index];
16
+ if (isUpdatingElement(element)) {
17
+ result.push(element);
18
+ }
19
+ pending.push(...element.children);
20
+ if (element.shadowRoot) {
21
+ pending.push(...element.shadowRoot.children);
22
+ }
23
+ }
24
+ return result;
25
+ };
26
+
27
+ /**
28
+ * Resolves once every Lit element below the root, including the ones their updates create,
29
+ * has completed its pending update.
30
+ */
31
+ export const waitForRenderedTree = async (rootArg: Element | ShadowRoot): Promise<void> => {
32
+ const settled = new Set<Element>();
33
+ for (;;) {
34
+ const pending = collectUpdatingElements(rootArg).filter((elementArg) => !settled.has(elementArg));
35
+ if (pending.length === 0) {
36
+ return;
37
+ }
38
+ await Promise.all(pending.map((elementArg) => elementArg.updateComplete));
39
+ for (const element of pending) {
40
+ settled.add(element);
41
+ }
42
+ }
43
+ };
@@ -1,11 +1,13 @@
1
+ import type { TWccSectionType } from '../ts_interfaces/index.js';
2
+
1
3
  /**
2
- * Configuration for a section in the WCC Tools sidebar
4
+ * Configuration for a section of the catalog
3
5
  */
4
6
  export interface IWccSection {
5
7
  /** Display name for the section header */
6
8
  name: string;
7
9
  /** How items in this section are rendered - 'elements' show demos, 'pages' render directly */
8
- type: 'elements' | 'pages';
10
+ type: TWccSectionType;
9
11
  /** The items in this section - either element classes or page factory functions */
10
12
  items: Record<string, any>;
11
13
  /** Optional filter function to include/exclude items */
@@ -24,8 +26,3 @@ export interface IWccSection {
24
26
  export interface IWccConfig {
25
27
  sections: IWccSection[];
26
28
  }
27
-
28
- /**
29
- * Type for element selection types - now section-based
30
- */
31
- export type TElementType = 'element' | 'page';
@@ -1,5 +1,10 @@
1
1
  import * as deesDomtools from '@design.estate/dees-domtools';
2
2
 
3
+ import * as interfaces from '../ts_interfaces/index.js';
4
+ import * as shared from '../ts_shared/index.js';
5
+
3
6
  export {
4
- deesDomtools
7
+ deesDomtools,
8
+ interfaces,
9
+ shared,
5
10
  };