@oddkin/workbench 0.0.0-stage → 1.0.0-beta.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 (223) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +36 -2
  3. package/dist/app/copy.d.ts +43 -0
  4. package/dist/app/copy.d.ts.map +1 -0
  5. package/dist/app/copy.js +47 -0
  6. package/dist/app/copy.js.map +1 -0
  7. package/dist/app/define.d.ts +3 -0
  8. package/dist/app/define.d.ts.map +1 -0
  9. package/dist/app/define.js +10 -0
  10. package/dist/app/define.js.map +1 -0
  11. package/dist/app/details.d.ts +22 -0
  12. package/dist/app/details.d.ts.map +1 -0
  13. package/dist/app/details.js +16 -0
  14. package/dist/app/details.js.map +1 -0
  15. package/dist/app/index.d.ts +12 -0
  16. package/dist/app/index.d.ts.map +1 -0
  17. package/dist/app/index.js +9 -0
  18. package/dist/app/index.js.map +1 -0
  19. package/dist/app/routes.d.ts +26 -0
  20. package/dist/app/routes.d.ts.map +1 -0
  21. package/dist/app/routes.js +94 -0
  22. package/dist/app/routes.js.map +1 -0
  23. package/dist/app/search.d.ts +17 -0
  24. package/dist/app/search.d.ts.map +1 -0
  25. package/dist/app/search.js +52 -0
  26. package/dist/app/search.js.map +1 -0
  27. package/dist/app/shell.d.ts +29 -0
  28. package/dist/app/shell.d.ts.map +1 -0
  29. package/dist/app/shell.js +435 -0
  30. package/dist/app/shell.js.map +1 -0
  31. package/dist/app/styles.d.ts +2 -0
  32. package/dist/app/styles.d.ts.map +1 -0
  33. package/dist/app/styles.js +373 -0
  34. package/dist/app/styles.js.map +1 -0
  35. package/dist/app/theme-studio.d.ts +12 -0
  36. package/dist/app/theme-studio.d.ts.map +1 -0
  37. package/dist/app/theme-studio.js +14 -0
  38. package/dist/app/theme-studio.js.map +1 -0
  39. package/dist/app/views.d.ts +34 -0
  40. package/dist/app/views.d.ts.map +1 -0
  41. package/dist/app/views.js +230 -0
  42. package/dist/app/views.js.map +1 -0
  43. package/dist/config/index.d.ts +170 -0
  44. package/dist/config/index.d.ts.map +1 -0
  45. package/dist/config/index.js +148 -0
  46. package/dist/config/index.js.map +1 -0
  47. package/dist/conformance/button.d.ts +2 -0
  48. package/dist/conformance/button.d.ts.map +1 -0
  49. package/dist/conformance/button.js +233 -0
  50. package/dist/conformance/button.js.map +1 -0
  51. package/dist/conformance/index.d.ts +107 -0
  52. package/dist/conformance/index.d.ts.map +1 -0
  53. package/dist/conformance/index.js +60 -0
  54. package/dist/conformance/index.js.map +1 -0
  55. package/dist/data/build.d.ts +36 -0
  56. package/dist/data/build.d.ts.map +1 -0
  57. package/dist/data/build.js +248 -0
  58. package/dist/data/build.js.map +1 -0
  59. package/dist/data/import-map.d.ts +53 -0
  60. package/dist/data/import-map.d.ts.map +1 -0
  61. package/dist/data/import-map.js +160 -0
  62. package/dist/data/import-map.js.map +1 -0
  63. package/dist/data/index.d.ts +14 -0
  64. package/dist/data/index.d.ts.map +1 -0
  65. package/dist/data/index.js +10 -0
  66. package/dist/data/index.js.map +1 -0
  67. package/dist/data/theme-studio.d.ts +21 -0
  68. package/dist/data/theme-studio.d.ts.map +1 -0
  69. package/dist/data/theme-studio.js +116 -0
  70. package/dist/data/theme-studio.js.map +1 -0
  71. package/dist/data/types.d.ts +169 -0
  72. package/dist/data/types.d.ts.map +1 -0
  73. package/dist/data/types.js +4 -0
  74. package/dist/data/types.js.map +1 -0
  75. package/dist/examples/index.d.ts +101 -0
  76. package/dist/examples/index.d.ts.map +1 -0
  77. package/dist/examples/index.js +106 -0
  78. package/dist/examples/index.js.map +1 -0
  79. package/dist/frame/index.d.ts +9 -0
  80. package/dist/frame/index.d.ts.map +1 -0
  81. package/dist/frame/index.js +468 -0
  82. package/dist/frame/index.js.map +1 -0
  83. package/dist/internal/diagnostics.d.ts +17 -0
  84. package/dist/internal/diagnostics.d.ts.map +1 -0
  85. package/dist/internal/diagnostics.js +19 -0
  86. package/dist/internal/diagnostics.js.map +1 -0
  87. package/dist/node/bin.d.ts +3 -0
  88. package/dist/node/bin.d.ts.map +1 -0
  89. package/dist/node/bin.js +12 -0
  90. package/dist/node/bin.js.map +1 -0
  91. package/dist/node/cli.d.ts +17 -0
  92. package/dist/node/cli.d.ts.map +1 -0
  93. package/dist/node/cli.js +198 -0
  94. package/dist/node/cli.js.map +1 -0
  95. package/dist/node/config.d.ts +28 -0
  96. package/dist/node/config.d.ts.map +1 -0
  97. package/dist/node/config.js +80 -0
  98. package/dist/node/config.js.map +1 -0
  99. package/dist/node/generated.d.ts +19 -0
  100. package/dist/node/generated.d.ts.map +1 -0
  101. package/dist/node/generated.js +109 -0
  102. package/dist/node/generated.js.map +1 -0
  103. package/dist/node/html.d.ts +35 -0
  104. package/dist/node/html.d.ts.map +1 -0
  105. package/dist/node/html.js +51 -0
  106. package/dist/node/html.js.map +1 -0
  107. package/dist/node/index.d.ts +24 -0
  108. package/dist/node/index.d.ts.map +1 -0
  109. package/dist/node/index.js +15 -0
  110. package/dist/node/index.js.map +1 -0
  111. package/dist/node/inputs.d.ts +24 -0
  112. package/dist/node/inputs.d.ts.map +1 -0
  113. package/dist/node/inputs.js +259 -0
  114. package/dist/node/inputs.js.map +1 -0
  115. package/dist/node/packages.d.ts +35 -0
  116. package/dist/node/packages.d.ts.map +1 -0
  117. package/dist/node/packages.js +87 -0
  118. package/dist/node/packages.js.map +1 -0
  119. package/dist/node/preload.d.ts +10 -0
  120. package/dist/node/preload.d.ts.map +1 -0
  121. package/dist/node/preload.js +61 -0
  122. package/dist/node/preload.js.map +1 -0
  123. package/dist/node/server.d.ts +42 -0
  124. package/dist/node/server.d.ts.map +1 -0
  125. package/dist/node/server.js +369 -0
  126. package/dist/node/server.js.map +1 -0
  127. package/dist/node/static.d.ts +33 -0
  128. package/dist/node/static.d.ts.map +1 -0
  129. package/dist/node/static.js +141 -0
  130. package/dist/node/static.js.map +1 -0
  131. package/dist/node/workbench.d.ts +43 -0
  132. package/dist/node/workbench.d.ts.map +1 -0
  133. package/dist/node/workbench.js +183 -0
  134. package/dist/node/workbench.js.map +1 -0
  135. package/dist/pages/build.d.ts +22 -0
  136. package/dist/pages/build.d.ts.map +1 -0
  137. package/dist/pages/build.js +363 -0
  138. package/dist/pages/build.js.map +1 -0
  139. package/dist/pages/defaults.d.ts +16 -0
  140. package/dist/pages/defaults.d.ts.map +1 -0
  141. package/dist/pages/defaults.js +88 -0
  142. package/dist/pages/defaults.js.map +1 -0
  143. package/dist/pages/index.d.ts +14 -0
  144. package/dist/pages/index.d.ts.map +1 -0
  145. package/dist/pages/index.js +10 -0
  146. package/dist/pages/index.js.map +1 -0
  147. package/dist/pages/navigation.d.ts +48 -0
  148. package/dist/pages/navigation.d.ts.map +1 -0
  149. package/dist/pages/navigation.js +83 -0
  150. package/dist/pages/navigation.js.map +1 -0
  151. package/dist/pages/types.d.ts +143 -0
  152. package/dist/pages/types.d.ts.map +1 -0
  153. package/dist/pages/types.js +3 -0
  154. package/dist/pages/types.js.map +1 -0
  155. package/dist/panels/catalog-define.d.ts +3 -0
  156. package/dist/panels/catalog-define.d.ts.map +1 -0
  157. package/dist/panels/catalog-define.js +7 -0
  158. package/dist/panels/catalog-define.js.map +1 -0
  159. package/dist/panels/catalog.d.ts +33 -0
  160. package/dist/panels/catalog.d.ts.map +1 -0
  161. package/dist/panels/catalog.js +54 -0
  162. package/dist/panels/catalog.js.map +1 -0
  163. package/dist/panels/component-define.d.ts +3 -0
  164. package/dist/panels/component-define.d.ts.map +1 -0
  165. package/dist/panels/component-define.js +6 -0
  166. package/dist/panels/component-define.js.map +1 -0
  167. package/dist/panels/component-detail.d.ts +46 -0
  168. package/dist/panels/component-detail.d.ts.map +1 -0
  169. package/dist/panels/component-detail.js +1120 -0
  170. package/dist/panels/component-detail.js.map +1 -0
  171. package/dist/panels/component.d.ts +17 -0
  172. package/dist/panels/component.d.ts.map +1 -0
  173. package/dist/panels/component.js +10 -0
  174. package/dist/panels/component.js.map +1 -0
  175. package/dist/panels/foundation-define.d.ts +3 -0
  176. package/dist/panels/foundation-define.d.ts.map +1 -0
  177. package/dist/panels/foundation-define.js +6 -0
  178. package/dist/panels/foundation-define.js.map +1 -0
  179. package/dist/panels/foundation-detail.d.ts +23 -0
  180. package/dist/panels/foundation-detail.d.ts.map +1 -0
  181. package/dist/panels/foundation-detail.js +216 -0
  182. package/dist/panels/foundation-detail.js.map +1 -0
  183. package/dist/panels/foundation.d.ts +15 -0
  184. package/dist/panels/foundation.d.ts.map +1 -0
  185. package/dist/panels/foundation.js +9 -0
  186. package/dist/panels/foundation.js.map +1 -0
  187. package/dist/panels/model.d.ts +173 -0
  188. package/dist/panels/model.d.ts.map +1 -0
  189. package/dist/panels/model.js +462 -0
  190. package/dist/panels/model.js.map +1 -0
  191. package/dist/panels/styles.d.ts +3 -0
  192. package/dist/panels/styles.d.ts.map +1 -0
  193. package/dist/panels/styles.js +316 -0
  194. package/dist/panels/styles.js.map +1 -0
  195. package/dist/panels/theme-model.d.ts +49 -0
  196. package/dist/panels/theme-model.d.ts.map +1 -0
  197. package/dist/panels/theme-model.js +146 -0
  198. package/dist/panels/theme-model.js.map +1 -0
  199. package/dist/panels/theme-studio.d.ts +32 -0
  200. package/dist/panels/theme-studio.d.ts.map +1 -0
  201. package/dist/panels/theme-studio.js +312 -0
  202. package/dist/panels/theme-studio.js.map +1 -0
  203. package/dist/preview/frame.d.ts +44 -0
  204. package/dist/preview/frame.d.ts.map +1 -0
  205. package/dist/preview/frame.js +250 -0
  206. package/dist/preview/frame.js.map +1 -0
  207. package/dist/preview/index.d.ts +26 -0
  208. package/dist/preview/index.d.ts.map +1 -0
  209. package/dist/preview/index.js +58 -0
  210. package/dist/preview/index.js.map +1 -0
  211. package/dist/preview/theme-generation.d.ts +33 -0
  212. package/dist/preview/theme-generation.d.ts.map +1 -0
  213. package/dist/preview/theme-generation.js +48 -0
  214. package/dist/preview/theme-generation.js.map +1 -0
  215. package/dist/protocol/index.d.ts +207 -0
  216. package/dist/protocol/index.d.ts.map +1 -0
  217. package/dist/protocol/index.js +261 -0
  218. package/dist/protocol/index.js.map +1 -0
  219. package/dist/testing/index.d.ts +47 -0
  220. package/dist/testing/index.d.ts.map +1 -0
  221. package/dist/testing/index.js +145 -0
  222. package/dist/testing/index.js.map +1 -0
  223. package/package.json +118 -4
@@ -0,0 +1,26 @@
1
+ /**
2
+ * `@oddkin/workbench/preview` — isolated preview frames and preview-owned stylesheets. Each
3
+ * frame has its own registry and module realm. `reload()` advances its generation for reset or
4
+ * registration replacement; frames execute trusted project code and are not a security sandbox.
5
+ * A shared component stylesheet is never mutated: inside one preview scope it is swapped for a
6
+ * copy, and edits replace the copy's rules without remounting elements (theming-and-styling.md §11).
7
+ */
8
+ import type { CSSResult } from '@oddkin/core/styles';
9
+ export interface PreviewStyles {
10
+ /** The preview-owned copy adopted in place of the shared sheet. */
11
+ readonly sheet: CSSStyleSheet;
12
+ /** Replace the copy's rules, e.g. with a recipe regenerated from edited conditions. */
13
+ update(cssText: string): void;
14
+ /** Swap the copy into roots added to the scope since the last call; returns how many. */
15
+ refresh(): number;
16
+ /** Put the shared sheet back everywhere the copy was adopted. */
17
+ restore(): void;
18
+ }
19
+ /**
20
+ * Within `scope`, adopt a preview-owned copy of `shared` wherever the shared sheet is adopted.
21
+ * Roots outside the scope, and the shared sheet itself, are left exactly as they were.
22
+ */
23
+ export declare function previewStyles(shared: CSSResult, scope: Element): PreviewStyles;
24
+ export { createIsolatedPreview, PreviewFrameError, previewProtocolStats } from './frame.js';
25
+ export type { IsolatedPreview, IsolatedPreviewOptions } from './frame.js';
26
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preview/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,uFAAuF;IACvF,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,yFAAyF;IACzF,OAAO,IAAI,MAAM,CAAC;IAClB,iEAAiE;IACjE,OAAO,IAAI,IAAI,CAAC;CACjB;AAqBD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,aAAa,CAgC9E;AAED,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC5F,YAAY,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,58 @@
1
+ /** Open shadow roots under `scope`, nested ones included. */
2
+ function shadowRoots(scope) {
3
+ const roots = [];
4
+ const visit = (node) => {
5
+ for (const element of node.querySelectorAll('*')) {
6
+ if (element.shadowRoot) {
7
+ roots.push(element.shadowRoot);
8
+ visit(element.shadowRoot);
9
+ }
10
+ }
11
+ };
12
+ if (scope.shadowRoot) {
13
+ roots.push(scope.shadowRoot);
14
+ visit(scope.shadowRoot);
15
+ }
16
+ visit(scope);
17
+ return roots;
18
+ }
19
+ /**
20
+ * Within `scope`, adopt a preview-owned copy of `shared` wherever the shared sheet is adopted.
21
+ * Roots outside the scope, and the shared sheet itself, are left exactly as they were.
22
+ */
23
+ export function previewStyles(shared, scope) {
24
+ const doc = scope.ownerDocument;
25
+ const original = shared.sheetFor(doc);
26
+ if (!original)
27
+ throw new Error('previewStyles: constructable stylesheets are unavailable in this document.');
28
+ const view = doc.defaultView;
29
+ const sheet = new view.CSSStyleSheet();
30
+ sheet.replaceSync(shared.cssText);
31
+ const swapped = new Set();
32
+ const swap = (root, from, to) => {
33
+ root.adoptedStyleSheets = root.adoptedStyleSheets.map((s) => (s === from ? to : s));
34
+ };
35
+ const refresh = () => {
36
+ let count = 0;
37
+ for (const root of shadowRoots(scope))
38
+ if (!swapped.has(root) && root.adoptedStyleSheets.includes(original)) {
39
+ swap(root, original, sheet);
40
+ swapped.add(root);
41
+ count++;
42
+ }
43
+ return count;
44
+ };
45
+ refresh();
46
+ return {
47
+ sheet,
48
+ update: (cssText) => sheet.replaceSync(cssText),
49
+ refresh,
50
+ restore() {
51
+ for (const root of swapped)
52
+ swap(root, sheet, original);
53
+ swapped.clear();
54
+ },
55
+ };
56
+ }
57
+ export { createIsolatedPreview, PreviewFrameError, previewProtocolStats } from './frame.js';
58
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/preview/index.ts"],"names":[],"mappings":"AAoBA,6DAA6D;AAC7D,SAAS,WAAW,CAAC,KAAc;IACjC,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,CAAC,IAA0B,EAAE,EAAE;QAC3C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;YACjD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;gBACvB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC/B,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC7B,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1B,CAAC;IACD,KAAK,CAAC,KAAK,CAAC,CAAC;IACb,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,MAAiB,EAAE,KAAc;IAC7D,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,QAAQ;QACX,MAAM,IAAI,KAAK,CAAC,4EAA4E,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,GAAG,CAAC,WAAyC,CAAC;IAC3D,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;IACvC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAc,CAAC;IACtC,MAAM,IAAI,GAAG,CAAC,IAAgB,EAAE,IAAmB,EAAE,EAAiB,EAAE,EAAE;QACxE,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACrE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;gBAC5B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAClB,KAAK,EAAE,CAAC;YACV,CAAC;QACH,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IACF,OAAO,EAAE,CAAC;IACV,OAAO;QACL,KAAK;QACL,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC;QAC/C,OAAO;QACP,OAAO;YACL,KAAK,MAAM,IAAI,IAAI,OAAO;gBAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACxD,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Theme generation off the main thread (workbench.md §6.4, theming-and-styling.md §8): one
3
+ * module Worker running the library's own `@oddkin/tokens/generate`. Latest wins: while a run is
4
+ * in flight, newer drafts replace each other and only the newest is generated next; a result
5
+ * for a superseded draft is discarded, never applied.
6
+ */
7
+ import type { Scope } from '@oddkin/core/scope';
8
+ export interface GenerationDiagnostic {
9
+ readonly severity?: string;
10
+ readonly code?: string;
11
+ readonly path?: string;
12
+ readonly message?: string;
13
+ }
14
+ export interface GenerationResult {
15
+ readonly id: number;
16
+ readonly ok: boolean;
17
+ readonly css?: string;
18
+ readonly diagnostics: readonly GenerationDiagnostic[];
19
+ /** Generation time inside the Worker. */
20
+ readonly ms: number;
21
+ }
22
+ export interface ThemeGeneration {
23
+ /** Generate `draft`; supersedes every earlier request that has not produced a result. */
24
+ request(draft: unknown): void;
25
+ readonly stats: {
26
+ readonly sent: number;
27
+ readonly superseded: number;
28
+ readonly delivered: number;
29
+ };
30
+ }
31
+ /** The Worker lives as long as `scope`. */
32
+ export declare function createThemeGeneration(workerUrl: string, scope: Scope, onResult: (result: GenerationResult) => void, onError: (message: string) => void): ThemeGeneration;
33
+ //# sourceMappingURL=theme-generation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-generation.d.ts","sourceRoot":"","sources":["../../src/preview/theme-generation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACtD,yCAAyC;IACzC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,yFAAyF;IACzF,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC5B,CAAC;CACH;AAED,2CAA2C;AAC3C,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,EAC5C,OAAO,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACjC,eAAe,CAyCjB"}
@@ -0,0 +1,48 @@
1
+ /** The Worker lives as long as `scope`. */
2
+ export function createThemeGeneration(workerUrl, scope, onResult, onError) {
3
+ const worker = new Worker(workerUrl, { type: 'module', name: 'oddkin-theme-studio' });
4
+ scope.add(() => worker.terminate(), 'theme generation worker');
5
+ const stats = { sent: 0, superseded: 0, delivered: 0 };
6
+ let nextId = 0;
7
+ let inFlight;
8
+ let queued;
9
+ const send = (draft) => {
10
+ inFlight = ++nextId;
11
+ stats.sent++;
12
+ worker.postMessage({ id: inFlight, draft });
13
+ };
14
+ scope.listen(worker, 'message', (event) => {
15
+ if (event.data.id !== inFlight)
16
+ return;
17
+ inFlight = undefined;
18
+ if (queued) {
19
+ stats.superseded++;
20
+ const next = queued;
21
+ queued = undefined;
22
+ send(next.draft);
23
+ return;
24
+ }
25
+ stats.delivered++;
26
+ onResult(event.data);
27
+ });
28
+ scope.listen(worker, 'error', (event) => {
29
+ inFlight = undefined;
30
+ queued = undefined;
31
+ onError(event.message || 'The theme generator could not be loaded.');
32
+ });
33
+ return {
34
+ request(draft) {
35
+ if (scope.disposed)
36
+ return;
37
+ if (inFlight === undefined)
38
+ send(draft);
39
+ else {
40
+ if (queued)
41
+ stats.superseded++;
42
+ queued = { draft };
43
+ }
44
+ },
45
+ stats,
46
+ };
47
+ }
48
+ //# sourceMappingURL=theme-generation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-generation.js","sourceRoot":"","sources":["../../src/preview/theme-generation.ts"],"names":[],"mappings":"AAkCA,2CAA2C;AAC3C,MAAM,UAAU,qBAAqB,CACnC,SAAiB,EACjB,KAAY,EACZ,QAA4C,EAC5C,OAAkC;IAElC,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC,CAAC;IACtF,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,yBAAyB,CAAC,CAAC;IAC/D,MAAM,KAAK,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACvD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,QAA4B,CAAC;IACjC,IAAI,MAA+C,CAAC;IACpD,MAAM,IAAI,GAAG,CAAC,KAAc,EAAE,EAAE;QAC9B,QAAQ,GAAG,EAAE,MAAM,CAAC;QACpB,KAAK,CAAC,IAAI,EAAE,CAAC;QACb,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,KAAqC,EAAE,EAAE;QACxE,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO;QACvC,QAAQ,GAAG,SAAS,CAAC;QACrB,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,CAAC,UAAU,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,MAAM,CAAC;YACpB,MAAM,GAAG,SAAS,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QACD,KAAK,CAAC,SAAS,EAAE,CAAC;QAClB,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE;QAClD,QAAQ,GAAG,SAAS,CAAC;QACrB,MAAM,GAAG,SAAS,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,0CAA0C,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IACH,OAAO;QACL,OAAO,CAAC,KAAK;YACX,IAAI,KAAK,CAAC,QAAQ;gBAAE,OAAO;YAC3B,IAAI,QAAQ,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,CAAC,CAAC;iBACnC,CAAC;gBACJ,IAAI,MAAM;oBAAE,KAAK,CAAC,UAAU,EAAE,CAAC;gBAC/B,MAAM,GAAG,EAAE,KAAK,EAAE,CAAC;YACrB,CAAC;QACH,CAAC;QACD,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,207 @@
1
+ /** DOM-free message contracts shared by the Workbench host and preview frames. */
2
+ export declare const FRAME_PROTOCOL = "oddkin.frame";
3
+ export declare const FRAME_PROTOCOL_VERSION = 1;
4
+ export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
5
+ readonly [key: string]: JsonValue;
6
+ };
7
+ export type ExampleId = `example:${string}/${string}`;
8
+ export type EventId = `event:${string}#${string}`;
9
+ export type PropertyId = `property:${string}#${string}`;
10
+ export interface FrameIdentity {
11
+ readonly frame: string;
12
+ readonly generation: number;
13
+ }
14
+ export interface FrameSettings {
15
+ readonly viewport?: {
16
+ readonly width: number;
17
+ readonly height: number;
18
+ };
19
+ readonly container?: {
20
+ readonly width: number;
21
+ readonly height?: number;
22
+ };
23
+ readonly direction?: 'ltr' | 'rtl';
24
+ readonly mode?: 'light' | 'dark';
25
+ readonly density?: string;
26
+ readonly product?: string;
27
+ readonly profile?: string;
28
+ }
29
+ export interface FrameMountPayload {
30
+ readonly tag: string;
31
+ readonly registration: string;
32
+ readonly example: ExampleId;
33
+ readonly properties?: Readonly<Record<string, JsonValue>>;
34
+ readonly attributes?: Readonly<Record<string, string | null>>;
35
+ readonly slots?: Readonly<Record<string, string>>;
36
+ readonly events?: readonly string[];
37
+ /**
38
+ * Declared property ↔ event sync pairs (metadata `syncPairs`). After such an event the frame
39
+ * reports the property's value in a `state` notification (`{ property, value }`); nothing is
40
+ * inferred from event names.
41
+ */
42
+ readonly sync?: readonly {
43
+ readonly property: string;
44
+ readonly event: string;
45
+ }[];
46
+ readonly settings?: FrameSettings;
47
+ }
48
+ export interface FrameSetPayload {
49
+ readonly property?: string;
50
+ readonly value?: JsonValue;
51
+ readonly unset?: boolean;
52
+ readonly attribute?: string;
53
+ readonly attributeValue?: string | null;
54
+ }
55
+ export interface FrameSlotPayload {
56
+ readonly name: string;
57
+ readonly text: string;
58
+ }
59
+ /** One element per preview role, mounted together (Theme Studio specimens). */
60
+ export interface FrameSpecimenItem extends FrameMountPayload {
61
+ /** The preview role this element plays, e.g. `primaryAction`. */
62
+ readonly role: string;
63
+ /** Visible caption naming the role. */
64
+ readonly label: string;
65
+ }
66
+ export interface FrameSpecimenPayload {
67
+ readonly items: readonly FrameSpecimenItem[];
68
+ readonly settings?: FrameSettings;
69
+ }
70
+ export interface FrameThemePayload {
71
+ readonly cssText: string;
72
+ }
73
+ export interface InspectPreviewRequest {
74
+ /** Stable example id, e.g. `example:odd-button/primary`. */
75
+ readonly example: ExampleId;
76
+ readonly settings?: FrameSettings;
77
+ readonly properties?: Readonly<Record<string, JsonValue>>;
78
+ readonly slots?: Readonly<Record<string, string>>;
79
+ readonly interactions?: readonly {
80
+ readonly id: EventId;
81
+ readonly event: string;
82
+ readonly target?: string;
83
+ }[];
84
+ readonly limits?: {
85
+ readonly errors?: number;
86
+ readonly events?: number;
87
+ readonly state?: number;
88
+ readonly checks?: number;
89
+ };
90
+ }
91
+ export interface InspectPreviewResponse {
92
+ readonly errors: readonly {
93
+ readonly id: EventId;
94
+ readonly phase: string;
95
+ readonly message: string;
96
+ }[];
97
+ readonly events: readonly {
98
+ readonly id: EventId;
99
+ readonly name: string;
100
+ readonly time: number;
101
+ readonly bubbles: boolean;
102
+ readonly composed: boolean;
103
+ readonly cancelable: boolean;
104
+ readonly detail?: JsonValue;
105
+ }[];
106
+ readonly state: readonly {
107
+ readonly id: PropertyId;
108
+ readonly value: JsonValue;
109
+ }[];
110
+ readonly checks: readonly {
111
+ readonly id: string;
112
+ readonly status: 'pass' | 'fail' | 'skip';
113
+ readonly engine: string;
114
+ readonly version: string;
115
+ readonly configuration: JsonValue;
116
+ readonly verification: string;
117
+ }[];
118
+ readonly conditions: JsonValue;
119
+ readonly engine: string;
120
+ readonly version: string;
121
+ readonly configuration: JsonValue;
122
+ readonly truncated: {
123
+ readonly errors: boolean;
124
+ readonly events: boolean;
125
+ readonly state: boolean;
126
+ readonly checks: boolean;
127
+ };
128
+ }
129
+ interface Envelope extends FrameIdentity {
130
+ readonly protocol: typeof FRAME_PROTOCOL;
131
+ readonly version: number;
132
+ }
133
+ export interface FrameHello extends Envelope {
134
+ readonly kind: 'hello';
135
+ }
136
+ export interface FrameConnect extends Envelope {
137
+ readonly kind: 'connect';
138
+ }
139
+ export type FrameRequest = (Envelope & {
140
+ readonly kind: 'mount';
141
+ readonly id: number;
142
+ readonly payload: FrameMountPayload;
143
+ }) | (Envelope & {
144
+ readonly kind: 'specimen';
145
+ readonly id: number;
146
+ readonly payload: FrameSpecimenPayload;
147
+ }) | (Envelope & {
148
+ readonly kind: 'set';
149
+ readonly id: number;
150
+ readonly payload: FrameSetPayload;
151
+ }) | (Envelope & {
152
+ readonly kind: 'slot';
153
+ readonly id: number;
154
+ readonly payload: FrameSlotPayload;
155
+ }) | (Envelope & {
156
+ readonly kind: 'reset';
157
+ readonly id: number;
158
+ }) | (Envelope & {
159
+ readonly kind: 'dispose';
160
+ readonly id: number;
161
+ }) | (Envelope & {
162
+ readonly kind: 'theme';
163
+ readonly id: number;
164
+ readonly payload: FrameThemePayload;
165
+ }) | (Envelope & {
166
+ readonly kind: 'settings';
167
+ readonly id: number;
168
+ readonly payload: FrameSettings;
169
+ }) | (Envelope & {
170
+ readonly kind: 'inspect';
171
+ readonly id: number;
172
+ readonly payload: InspectPreviewRequest;
173
+ });
174
+ export interface FrameReply extends Envelope {
175
+ readonly kind: 'reply';
176
+ readonly replyTo: number;
177
+ readonly payload?: JsonValue;
178
+ readonly error?: {
179
+ readonly code: string;
180
+ readonly message: string;
181
+ };
182
+ }
183
+ export interface FrameNotification extends Envelope {
184
+ readonly kind: 'event' | 'error' | 'state' | 'size';
185
+ readonly payload?: JsonValue;
186
+ }
187
+ export type FrameRequestPayload = Extract<FrameRequest, {
188
+ readonly payload: unknown;
189
+ }>['payload'];
190
+ export type FrameMessage = FrameHello | FrameConnect | FrameRequest | FrameReply | FrameNotification;
191
+ /** True only for finite, acyclic data that can be transferred as plain JSON without coercion. */
192
+ export declare function isJsonValue(value: unknown): value is JsonValue;
193
+ export declare const isExampleId: (value: unknown) => value is ExampleId;
194
+ export declare function isFrameMountPayload(value: unknown): value is FrameMountPayload;
195
+ export declare function isFrameSpecimenPayload(value: unknown): value is FrameSpecimenPayload;
196
+ /** Validates the common envelope and its JSON payload, without accepting a specific version. */
197
+ export declare function isFrameMessage(value: unknown): value is FrameMessage;
198
+ export declare function isCompatibleFrameMessage(value: unknown): value is FrameMessage;
199
+ export declare const isFrameHello: (value: unknown) => value is FrameHello;
200
+ export declare function isInspectPreviewRequest(value: unknown): value is InspectPreviewRequest;
201
+ export declare function isFrameRequest(value: unknown): value is FrameRequest;
202
+ export declare const isFrameReply: (value: unknown) => value is FrameReply;
203
+ export declare function frameEnvelope<T extends FrameMessage['kind']>(identity: FrameIdentity, kind: T): Envelope & {
204
+ readonly kind: T;
205
+ };
206
+ export {};
207
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/protocol/index.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAC7C,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,MAAM,MAAM,SAAS,GACnB,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,SAAS,EAAE,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,CAAC;AAElG,MAAM,MAAM,SAAS,GAAG,WAAW,MAAM,IAAI,MAAM,EAAE,CAAC;AACtD,MAAM,MAAM,OAAO,GAAG,SAAS,MAAM,IAAI,MAAM,EAAE,CAAC;AAClD,MAAM,MAAM,UAAU,GAAG,YAAY,MAAM,IAAI,MAAM,EAAE,CAAC;AAExD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IACnC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IAC9D,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjF,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D,iEAAiE;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;CACnC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAC1D,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS;QAC/B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,CAAC,MAAM,CAAC,EAAE;QAChB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;KAC1B,EAAE,CAAC;IACJ,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;QACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC3B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;QAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC;KAC7B,EAAE,CAAC;IACJ,QAAQ,CAAC,KAAK,EAAE,SAAS;QAAE,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;KAAE,EAAE,CAAC;IAClF,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;QAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;QAClC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;KAC/B,EAAE,CAAC;IACJ,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;QACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;QACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;KAC1B,CAAC;CACH;AAED,UAAU,QAAS,SAAQ,aAAa;IACtC,QAAQ,CAAC,QAAQ,EAAE,OAAO,cAAc,CAAC;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAED,MAAM,MAAM,YAAY,GACpB,CAAC,QAAQ,GAAG;IACV,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;CACrC,CAAC,GACF,CAAC,QAAQ,GAAG;IACV,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;CACxC,CAAC,GACF,CAAC,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAA;CAAE,CAAC,GAC7F,CAAC,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC,GAC/F,CAAC,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAC5D,CAAC,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9D,CAAC,QAAQ,GAAG;IACV,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;CACrC,CAAC,GACF,CAAC,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;CAAE,CAAC,GAChG,CAAC,QAAQ,GAAG;IACV,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;CACzC,CAAC,CAAC;AAEP,MAAM,WAAW,UAAW,SAAQ,QAAQ;IAC1C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAED,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IACjD,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,MAAM,MAAM,mBAAmB,GAAG,OAAO,CAAC,YAAY,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC,SAAS,CAAC,CAAC;AAElG,MAAM,MAAM,YAAY,GACtB,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,iBAAiB,CAAC;AAK5E,iGAAiG;AACjG,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CA+C9D;AAOD,eAAO,MAAM,WAAW,UAAW,OAAO,KAAG,KAAK,IAAI,SACa,CAAC;AAqCpE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,iBAAiB,CAqC9E;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAYpF;AAED,gGAAgG;AAChG,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CA4CpE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAE9E;AAED,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,KAAK,IAAI,UACI,CAAC;AAE5D,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qBAAqB,CAiCtF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAkDpE;AAED,eAAO,MAAM,YAAY,UAAW,OAAO,KAAG,KAAK,IAAI,UACI,CAAC;AAE5D,wBAAgB,aAAa,CAAC,CAAC,SAAS,YAAY,CAAC,MAAM,CAAC,EAC1D,QAAQ,EAAE,aAAa,EACvB,IAAI,EAAE,CAAC,GACN,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;CAAE,CAQjC"}
@@ -0,0 +1,261 @@
1
+ /** DOM-free message contracts shared by the Workbench host and preview frames. */
2
+ export const FRAME_PROTOCOL = 'oddkin.frame';
3
+ export const FRAME_PROTOCOL_VERSION = 1;
4
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
5
+ /** True only for finite, acyclic data that can be transferred as plain JSON without coercion. */
6
+ export function isJsonValue(value) {
7
+ const active = new WeakSet();
8
+ const stack = [{ value, exit: false }];
9
+ while (stack.length) {
10
+ const item = stack.pop();
11
+ const current = item.value;
12
+ if (current === null ||
13
+ typeof current === 'string' ||
14
+ typeof current === 'boolean' ||
15
+ (typeof current === 'number' && Number.isFinite(current)))
16
+ continue;
17
+ if (typeof current !== 'object')
18
+ return false;
19
+ if (item.exit) {
20
+ active.delete(current);
21
+ continue;
22
+ }
23
+ if (active.has(current))
24
+ return false;
25
+ const array = Array.isArray(current);
26
+ if (array ? Object.getPrototypeOf(current) !== Array.prototype : !isRecord(current))
27
+ return false;
28
+ if (!array) {
29
+ const prototype = Object.getPrototypeOf(current);
30
+ if (prototype !== Object.prototype && prototype !== null)
31
+ return false;
32
+ }
33
+ active.add(current);
34
+ stack.push({ value: current, exit: true });
35
+ const keys = Reflect.ownKeys(current);
36
+ if (array) {
37
+ const list = current;
38
+ if (keys.length !== list.length + 1 || !keys.includes('length'))
39
+ return false;
40
+ for (let i = 0; i < list.length; i++) {
41
+ const descriptor = Object.getOwnPropertyDescriptor(list, String(i));
42
+ if (!descriptor?.enumerable || !('value' in descriptor))
43
+ return false;
44
+ stack.push({ value: descriptor.value, exit: false });
45
+ }
46
+ continue;
47
+ }
48
+ for (const key of keys) {
49
+ if (typeof key !== 'string')
50
+ return false;
51
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
52
+ if (!descriptor?.enumerable || !('value' in descriptor))
53
+ return false;
54
+ stack.push({ value: descriptor.value, exit: false });
55
+ }
56
+ }
57
+ return true;
58
+ }
59
+ const isPositiveInteger = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value > 0;
60
+ const isStringRecord = (value) => isRecord(value) && Object.values(value).every((item) => typeof item === 'string');
61
+ export const isExampleId = (value) => typeof value === 'string' && /^example:[^/]+\/[^/]+$/.test(value);
62
+ const isEventId = (value) => typeof value === 'string' && /^event:[^#]+#[^#]+$/.test(value);
63
+ function isFrameSettings(value) {
64
+ if (!isRecord(value))
65
+ return false;
66
+ if (value['direction'] !== undefined &&
67
+ value['direction'] !== 'ltr' &&
68
+ value['direction'] !== 'rtl')
69
+ return false;
70
+ if (value['mode'] !== undefined && value['mode'] !== 'light' && value['mode'] !== 'dark')
71
+ return false;
72
+ for (const key of ['density', 'product', 'profile'])
73
+ if (value[key] !== undefined && typeof value[key] !== 'string')
74
+ return false;
75
+ for (const key of ['viewport', 'container']) {
76
+ const size = value[key];
77
+ if (size === undefined)
78
+ continue;
79
+ if (!isRecord(size) ||
80
+ typeof size['width'] !== 'number' ||
81
+ !Number.isFinite(size['width']) ||
82
+ size['width'] <= 0)
83
+ return false;
84
+ if (size['height'] !== undefined &&
85
+ (typeof size['height'] !== 'number' ||
86
+ !Number.isFinite(size['height']) ||
87
+ size['height'] <= 0))
88
+ return false;
89
+ }
90
+ return true;
91
+ }
92
+ export function isFrameMountPayload(value) {
93
+ if (!isRecord(value) ||
94
+ typeof value['tag'] !== 'string' ||
95
+ typeof value['registration'] !== 'string' ||
96
+ !/^[a-z][a-z0-9]*(?:-[a-z0-9]+)+$/.test(value['tag']) ||
97
+ !isExampleId(value['example']) ||
98
+ !value['example'].startsWith(`example:${value['tag']}/`))
99
+ return false;
100
+ if (value['properties'] !== undefined && !isJsonValue(value['properties']))
101
+ return false;
102
+ if (value['attributes'] !== undefined) {
103
+ const attributes = value['attributes'];
104
+ if (!isRecord(attributes) ||
105
+ !Object.values(attributes).every((item) => item === null || typeof item === 'string'))
106
+ return false;
107
+ }
108
+ if (value['slots'] !== undefined && !isStringRecord(value['slots']))
109
+ return false;
110
+ if (value['events'] !== undefined &&
111
+ (!Array.isArray(value['events']) || !value['events'].every((item) => typeof item === 'string')))
112
+ return false;
113
+ if (value['sync'] !== undefined &&
114
+ (!Array.isArray(value['sync']) ||
115
+ !value['sync'].every((pair) => isRecord(pair) &&
116
+ typeof pair['property'] === 'string' &&
117
+ typeof pair['event'] === 'string')))
118
+ return false;
119
+ return value['settings'] === undefined || isFrameSettings(value['settings']);
120
+ }
121
+ export function isFrameSpecimenPayload(value) {
122
+ return (isRecord(value) &&
123
+ Array.isArray(value['items']) &&
124
+ value['items'].every((item) => isFrameMountPayload(item) &&
125
+ typeof item['role'] === 'string' &&
126
+ typeof item['label'] === 'string') &&
127
+ (value['settings'] === undefined || isFrameSettings(value['settings'])));
128
+ }
129
+ /** Validates the common envelope and its JSON payload, without accepting a specific version. */
130
+ export function isFrameMessage(value) {
131
+ if (!isRecord(value))
132
+ return false;
133
+ if (value['protocol'] !== FRAME_PROTOCOL ||
134
+ !Number.isSafeInteger(value['version']) ||
135
+ typeof value['frame'] !== 'string' ||
136
+ value['frame'].length === 0 ||
137
+ !isPositiveInteger(value['generation']) ||
138
+ typeof value['kind'] !== 'string')
139
+ return false;
140
+ const hasPayload = Object.hasOwn(value, 'payload');
141
+ if (hasPayload && !isJsonValue(value['payload']))
142
+ return false;
143
+ switch (value['kind']) {
144
+ case 'hello':
145
+ case 'connect':
146
+ return !Object.hasOwn(value, 'id') && !Object.hasOwn(value, 'replyTo');
147
+ case 'mount':
148
+ case 'specimen':
149
+ case 'set':
150
+ case 'slot':
151
+ case 'reset':
152
+ case 'theme':
153
+ case 'settings':
154
+ case 'dispose':
155
+ case 'inspect':
156
+ return isPositiveInteger(value['id']) && !Object.hasOwn(value, 'replyTo');
157
+ case 'reply':
158
+ return (isPositiveInteger(value['replyTo']) &&
159
+ !(Object.hasOwn(value, 'payload') && Object.hasOwn(value, 'error')) &&
160
+ (!Object.hasOwn(value, 'error') ||
161
+ (isRecord(value['error']) &&
162
+ typeof value['error']['code'] === 'string' &&
163
+ typeof value['error']['message'] === 'string')));
164
+ case 'event':
165
+ case 'error':
166
+ case 'state':
167
+ case 'size':
168
+ return !Object.hasOwn(value, 'id') && !Object.hasOwn(value, 'replyTo');
169
+ default:
170
+ return false;
171
+ }
172
+ }
173
+ export function isCompatibleFrameMessage(value) {
174
+ return isFrameMessage(value) && value.version === FRAME_PROTOCOL_VERSION;
175
+ }
176
+ export const isFrameHello = (value) => isCompatibleFrameMessage(value) && value.kind === 'hello';
177
+ export function isInspectPreviewRequest(value) {
178
+ if (!isRecord(value) || !isExampleId(value['example']))
179
+ return false;
180
+ if ((value['settings'] !== undefined && !isFrameSettings(value['settings'])) ||
181
+ (value['properties'] !== undefined && !isJsonValue(value['properties'])) ||
182
+ (value['slots'] !== undefined && !isStringRecord(value['slots'])))
183
+ return false;
184
+ const limits = value['limits'];
185
+ if (limits !== undefined &&
186
+ (!isRecord(limits) ||
187
+ !['errors', 'events', 'state', 'checks'].every((key) => {
188
+ const limit = limits[key];
189
+ return (limit === undefined ||
190
+ (typeof limit === 'number' && Number.isSafeInteger(limit) && limit >= 0));
191
+ })))
192
+ return false;
193
+ const interactions = value['interactions'];
194
+ return (interactions === undefined ||
195
+ (Array.isArray(interactions) &&
196
+ interactions.every((item) => isRecord(item) &&
197
+ isEventId(item['id']) &&
198
+ typeof item['event'] === 'string' &&
199
+ (item['target'] === undefined || typeof item['target'] === 'string'))));
200
+ }
201
+ export function isFrameRequest(value) {
202
+ if (!isCompatibleFrameMessage(value))
203
+ return false;
204
+ if (![
205
+ 'mount',
206
+ 'specimen',
207
+ 'set',
208
+ 'slot',
209
+ 'reset',
210
+ 'theme',
211
+ 'settings',
212
+ 'dispose',
213
+ 'inspect',
214
+ ].includes(value.kind))
215
+ return false;
216
+ const request = value;
217
+ switch (request.kind) {
218
+ case 'mount':
219
+ return isFrameMountPayload(request.payload);
220
+ case 'specimen':
221
+ return isFrameSpecimenPayload(request.payload);
222
+ case 'set': {
223
+ if (!isRecord(request.payload))
224
+ return false;
225
+ const hasProperty = typeof request.payload['property'] === 'string';
226
+ const hasAttribute = typeof request.payload['attribute'] === 'string';
227
+ if (hasProperty === hasAttribute)
228
+ return false;
229
+ return hasProperty
230
+ ? (request.payload['unset'] === true ||
231
+ (Object.hasOwn(request.payload, 'value') && isJsonValue(request.payload['value']))) &&
232
+ (request.payload['unset'] !== true || !Object.hasOwn(request.payload, 'value'))
233
+ : request.payload['attributeValue'] === null ||
234
+ typeof request.payload['attributeValue'] === 'string';
235
+ }
236
+ case 'slot':
237
+ return (isRecord(request.payload) &&
238
+ typeof request.payload['name'] === 'string' &&
239
+ typeof request.payload['text'] === 'string');
240
+ case 'reset':
241
+ case 'dispose':
242
+ return !Object.hasOwn(request, 'payload');
243
+ case 'theme':
244
+ return isRecord(request.payload) && typeof request.payload['cssText'] === 'string';
245
+ case 'settings':
246
+ return isFrameSettings(request.payload);
247
+ case 'inspect':
248
+ return isInspectPreviewRequest(request.payload);
249
+ }
250
+ }
251
+ export const isFrameReply = (value) => isCompatibleFrameMessage(value) && value.kind === 'reply';
252
+ export function frameEnvelope(identity, kind) {
253
+ return {
254
+ protocol: FRAME_PROTOCOL,
255
+ version: FRAME_PROTOCOL_VERSION,
256
+ frame: identity.frame,
257
+ generation: identity.generation,
258
+ kind,
259
+ };
260
+ }
261
+ //# sourceMappingURL=index.js.map