@ethlete/cli 3.0.0-next.23 → 3.0.0-next.25

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 (202) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/design/contrast.ts +49 -0
  3. package/design/define-call.ts +48 -8
  4. package/design/define-part.ts +83 -1
  5. package/design/embed-page.ts +37 -4
  6. package/design/icon-sheet.ts +151 -0
  7. package/design/mark-part.ts +79 -2
  8. package/design/morph.ts +67 -0
  9. package/design/motion-runtime.ts +407 -0
  10. package/design/spring.ts +53 -0
  11. package/design/token-sheet.ts +87 -0
  12. package/design/web/env.d.ts +6 -2
  13. package/design/web/frame.ts +159 -6
  14. package/package.json +2 -1
  15. package/src/lib/design/calls-tsconfig.js +1 -2
  16. package/src/lib/design/calls-tsconfig.js.map +1 -1
  17. package/src/lib/design/changed-parts.d.ts +4 -4
  18. package/src/lib/design/changed-parts.js +10 -6
  19. package/src/lib/design/changed-parts.js.map +1 -1
  20. package/src/lib/design/contact-sheet.d.ts +26 -13
  21. package/src/lib/design/contact-sheet.js +122 -40
  22. package/src/lib/design/contact-sheet.js.map +1 -1
  23. package/src/lib/design/design-command.js +50 -2
  24. package/src/lib/design/design-command.js.map +1 -1
  25. package/src/lib/design/force-interactions.d.ts +2 -1
  26. package/src/lib/design/force-interactions.js +7 -4
  27. package/src/lib/design/force-interactions.js.map +1 -1
  28. package/src/lib/design/generated-stylesheets.d.ts +15 -0
  29. package/src/lib/design/generated-stylesheets.js +52 -0
  30. package/src/lib/design/generated-stylesheets.js.map +1 -0
  31. package/src/lib/design/inbox-command.d.ts +1 -0
  32. package/src/lib/design/inbox-command.js +15 -0
  33. package/src/lib/design/inbox-command.js.map +1 -1
  34. package/src/lib/design/mcp-command.d.ts +60 -0
  35. package/src/lib/design/mcp-command.js +327 -0
  36. package/src/lib/design/mcp-command.js.map +1 -0
  37. package/src/lib/design/merge-compare.d.ts +10 -0
  38. package/src/lib/design/merge-compare.js +17 -4
  39. package/src/lib/design/merge-compare.js.map +1 -1
  40. package/src/lib/design/motion-command.d.ts +71 -0
  41. package/src/lib/design/motion-command.js +314 -0
  42. package/src/lib/design/motion-command.js.map +1 -0
  43. package/src/lib/design/motion-endpoint.d.ts +61 -0
  44. package/src/lib/design/motion-endpoint.js +133 -0
  45. package/src/lib/design/motion-endpoint.js.map +1 -0
  46. package/src/lib/design/motion-flow.d.ts +5 -0
  47. package/src/lib/design/motion-flow.js +29 -0
  48. package/src/lib/design/motion-flow.js.map +1 -0
  49. package/src/lib/design/motion-shot.d.ts +43 -0
  50. package/src/lib/design/motion-shot.js +97 -0
  51. package/src/lib/design/motion-shot.js.map +1 -0
  52. package/src/lib/design/paths.d.ts +11 -0
  53. package/src/lib/design/paths.js.map +1 -1
  54. package/src/lib/design/ready-shots.d.ts +7 -0
  55. package/src/lib/design/ready-shots.js +22 -1
  56. package/src/lib/design/ready-shots.js.map +1 -1
  57. package/src/lib/design/render-packages.d.ts +9 -0
  58. package/src/lib/design/render-packages.js +13 -3
  59. package/src/lib/design/render-packages.js.map +1 -1
  60. package/src/lib/design/render.js +3 -3
  61. package/src/lib/design/render.js.map +1 -1
  62. package/src/lib/design/serve.js +108 -21
  63. package/src/lib/design/serve.js.map +1 -1
  64. package/src/lib/design/shot-command.d.ts +12 -6
  65. package/src/lib/design/shot-command.js +60 -48
  66. package/src/lib/design/shot-command.js.map +1 -1
  67. package/src/lib/design/shot.d.ts +30 -4
  68. package/src/lib/design/shot.js +138 -53
  69. package/src/lib/design/shot.js.map +1 -1
  70. package/src/lib/design/sketch-command.js +132 -39
  71. package/src/lib/design/sketch-command.js.map +1 -1
  72. package/src/lib/design/sketch-stylesheets.d.ts +7 -0
  73. package/src/lib/design/sketch-stylesheets.js +63 -0
  74. package/src/lib/design/sketch-stylesheets.js.map +1 -0
  75. package/src/lib/design/studio-api.d.ts +28 -6
  76. package/src/lib/design/studio-api.js +102 -17
  77. package/src/lib/design/studio-api.js.map +1 -1
  78. package/src/lib/design/system/check-system.js +8 -0
  79. package/src/lib/design/system/check-system.js.map +1 -1
  80. package/src/lib/design/system/comments/comment.d.ts +17 -0
  81. package/src/lib/design/system/comments/comment.js +35 -1
  82. package/src/lib/design/system/comments/comment.js.map +1 -1
  83. package/src/lib/design/system/comments/complete.js +4 -2
  84. package/src/lib/design/system/comments/complete.js.map +1 -1
  85. package/src/lib/design/system/complete-command.d.ts +9 -0
  86. package/src/lib/design/system/complete-command.js +134 -0
  87. package/src/lib/design/system/complete-command.js.map +1 -0
  88. package/src/lib/design/system/complete.d.ts +171 -0
  89. package/src/lib/design/system/complete.js +1106 -0
  90. package/src/lib/design/system/complete.js.map +1 -0
  91. package/src/lib/design/system/contrast-check.d.ts +26 -0
  92. package/src/lib/design/system/contrast-check.js +153 -0
  93. package/src/lib/design/system/contrast-check.js.map +1 -0
  94. package/src/lib/design/system/exceptions.d.ts +59 -0
  95. package/src/lib/design/system/exceptions.js +132 -0
  96. package/src/lib/design/system/exceptions.js.map +1 -0
  97. package/src/lib/design/system/flows/flow.d.ts +3 -0
  98. package/src/lib/design/system/flows/flow.js +5 -3
  99. package/src/lib/design/system/flows/flow.js.map +1 -1
  100. package/src/lib/design/system/handoff.d.ts +11 -0
  101. package/src/lib/design/system/handoff.js +30 -0
  102. package/src/lib/design/system/handoff.js.map +1 -0
  103. package/src/lib/design/system/imports.d.ts +28 -3
  104. package/src/lib/design/system/imports.js +84 -7
  105. package/src/lib/design/system/imports.js.map +1 -1
  106. package/src/lib/design/system/inventory-approval.d.ts +41 -0
  107. package/src/lib/design/system/inventory-approval.js +71 -0
  108. package/src/lib/design/system/inventory-approval.js.map +1 -0
  109. package/src/lib/design/system/inventory.d.ts +65 -0
  110. package/src/lib/design/system/inventory.js +168 -0
  111. package/src/lib/design/system/inventory.js.map +1 -0
  112. package/src/lib/design/system/list-system.d.ts +11 -0
  113. package/src/lib/design/system/list-system.js +26 -3
  114. package/src/lib/design/system/list-system.js.map +1 -1
  115. package/src/lib/design/system/product-stylesheets.d.ts +3 -0
  116. package/src/lib/design/system/product-stylesheets.js +40 -0
  117. package/src/lib/design/system/product-stylesheets.js.map +1 -0
  118. package/src/lib/design/system/render-check.js +30 -4
  119. package/src/lib/design/system/render-check.js.map +1 -1
  120. package/src/lib/design/system/resolve-product.d.ts +2 -3
  121. package/src/lib/design/system/resolve-product.js +4 -6
  122. package/src/lib/design/system/resolve-product.js.map +1 -1
  123. package/src/lib/design/system/rules/canonical-class.d.ts +9 -0
  124. package/src/lib/design/system/rules/canonical-class.js +132 -0
  125. package/src/lib/design/system/rules/canonical-class.js.map +1 -0
  126. package/src/lib/design/system/rules/inline-svg.d.ts +7 -0
  127. package/src/lib/design/system/rules/inline-svg.js +28 -0
  128. package/src/lib/design/system/rules/inline-svg.js.map +1 -0
  129. package/src/lib/design/system/rules/motion.d.ts +4 -0
  130. package/src/lib/design/system/rules/motion.js +46 -2
  131. package/src/lib/design/system/rules/motion.js.map +1 -1
  132. package/src/lib/design/system/rules/stale-replace.js +41 -2
  133. package/src/lib/design/system/rules/stale-replace.js.map +1 -1
  134. package/src/lib/design/system/rules/token-selectors.js +1 -1
  135. package/src/lib/design/system/rules/token-selectors.js.map +1 -1
  136. package/src/lib/design/system/rules/utility-css.d.ts +11 -0
  137. package/src/lib/design/system/rules/utility-css.js +290 -0
  138. package/src/lib/design/system/rules/utility-css.js.map +1 -0
  139. package/src/lib/design/system/sketch/baseline.d.ts +3 -2
  140. package/src/lib/design/system/sketch/baseline.js +10 -4
  141. package/src/lib/design/system/sketch/baseline.js.map +1 -1
  142. package/src/lib/design/system/sketch/host-edit.d.ts +4 -0
  143. package/src/lib/design/system/sketch/host-edit.js +68 -0
  144. package/src/lib/design/system/sketch/host-edit.js.map +1 -0
  145. package/src/lib/design/system/sketch/merge-preview.d.ts +4 -2
  146. package/src/lib/design/system/sketch/merge-preview.js +20 -3
  147. package/src/lib/design/system/sketch/merge-preview.js.map +1 -1
  148. package/src/lib/design/system/sketch/merge-shared.d.ts +42 -6
  149. package/src/lib/design/system/sketch/merge-shared.js +122 -24
  150. package/src/lib/design/system/sketch/merge-shared.js.map +1 -1
  151. package/src/lib/design/system/sketch/merge.d.ts +6 -5
  152. package/src/lib/design/system/sketch/merge.js +95 -35
  153. package/src/lib/design/system/sketch/merge.js.map +1 -1
  154. package/src/lib/design/system/sketch/merged-parts.d.ts +17 -0
  155. package/src/lib/design/system/sketch/merged-parts.js +35 -2
  156. package/src/lib/design/system/sketch/merged-parts.js.map +1 -1
  157. package/src/lib/design/system/sketch/no-visible-change.d.ts +10 -3
  158. package/src/lib/design/system/sketch/no-visible-change.js +75 -20
  159. package/src/lib/design/system/sketch/no-visible-change.js.map +1 -1
  160. package/src/lib/design/system/sketch/overlay.js +16 -3
  161. package/src/lib/design/system/sketch/overlay.js.map +1 -1
  162. package/src/lib/design/system/sketch/part-definition.d.ts +12 -0
  163. package/src/lib/design/system/sketch/part-definition.js +40 -1
  164. package/src/lib/design/system/sketch/part-definition.js.map +1 -1
  165. package/src/lib/design/system/sketch/sketch.d.ts +40 -3
  166. package/src/lib/design/system/sketch/sketch.js +147 -50
  167. package/src/lib/design/system/sketch/sketch.js.map +1 -1
  168. package/src/lib/design/system/sketch/unchanged-states.d.ts +10 -4
  169. package/src/lib/design/system/sketch/unchanged-states.js +37 -23
  170. package/src/lib/design/system/sketch/unchanged-states.js.map +1 -1
  171. package/src/lib/design/system/sketch/unused-closure.d.ts +12 -0
  172. package/src/lib/design/system/sketch/unused-closure.js +185 -0
  173. package/src/lib/design/system/sketch/unused-closure.js.map +1 -0
  174. package/src/lib/design/system/system-modules.d.ts +5 -1
  175. package/src/lib/design/system/system-modules.js +32 -17
  176. package/src/lib/design/system/system-modules.js.map +1 -1
  177. package/src/lib/design/system/system-tsconfig.d.ts +2 -1
  178. package/src/lib/design/system/system-tsconfig.js +11 -6
  179. package/src/lib/design/system/system-tsconfig.js.map +1 -1
  180. package/src/lib/design/thumb.d.ts +6 -2
  181. package/src/lib/design/thumb.js +36 -15
  182. package/src/lib/design/thumb.js.map +1 -1
  183. package/src/lib/design/variant-diff.d.ts +12 -10
  184. package/src/lib/design/variant-diff.js +14 -13
  185. package/src/lib/design/variant-diff.js.map +1 -1
  186. package/src/lib/design/warm-pages.d.ts +20 -0
  187. package/src/lib/design/warm-pages.js +78 -0
  188. package/src/lib/design/warm-pages.js.map +1 -0
  189. package/src/lib/update/commits.d.ts +9 -0
  190. package/src/lib/update/commits.js +15 -1
  191. package/src/lib/update/commits.js.map +1 -1
  192. package/src/lib/update/migration-manifest.d.ts +6 -0
  193. package/src/lib/update/migration-manifest.js +7 -0
  194. package/src/lib/update/migration-manifest.js.map +1 -1
  195. package/src/lib/update/migrations-command.js +1 -0
  196. package/src/lib/update/migrations-command.js.map +1 -1
  197. package/src/lib/update/run-migrations.d.ts +22 -0
  198. package/src/lib/update/run-migrations.js +60 -1
  199. package/src/lib/update/run-migrations.js.map +1 -1
  200. package/src/lib/update/update-command.d.ts +10 -0
  201. package/src/lib/update/update-command.js +28 -2
  202. package/src/lib/update/update-command.js.map +1 -1
@@ -0,0 +1,87 @@
1
+ import { Drawing, html } from './define-call';
2
+
3
+ export type TokenSheetOptions = {
4
+ title: string;
5
+ note?: string;
6
+ scope?: string;
7
+ css: string;
8
+ sample: string;
9
+ sampleOf: (name: string) => string;
10
+ sampleClass?: string;
11
+ only?: (name: string) => boolean;
12
+ pixels?: boolean;
13
+ styles?: string;
14
+ setup?: (root: HTMLElement) => void;
15
+ };
16
+
17
+ const SHEET_STYLES = `
18
+ .ts-root { position: relative; display: flex; flex-direction: column; gap: var(--space-4, 1.6rem); width: 960px; padding: var(--space-6, 2.4rem); box-sizing: border-box; background: var(--surface, oklch(0.17 0 0)); color: var(--text, oklch(0.94 0 0)); font-family: var(--font-ui, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif); font-size: var(--text-md, 1.3rem); line-height: var(--text-md-line, 1.8rem); }
19
+ .ts-title { margin: 0; font-size: var(--text-xl, 1.7rem); line-height: var(--text-xl-line, 2.2rem); font-weight: var(--weight-strong, 600); }
20
+ .ts-note { margin: 0; max-width: 64rem; color: var(--text-muted, oklch(0.72 0 0)); }
21
+ .ts-panel { margin: 0; padding: var(--space-4, 1.6rem); background: var(--surface, oklch(0.17 0 0)); border: 1px solid var(--surface-border, oklch(0.34 0 0)); border-radius: var(--radius-control-lg, 1rem); }
22
+ .ts-list { list-style: none; display: flex; flex-direction: column; gap: var(--space-1, 0.4rem); }
23
+ .ts-row { display: grid; grid-template-columns: 200px 240px 1fr; align-items: center; gap: var(--space-3, 1.2rem); min-height: var(--row, 2.4rem); }
24
+ .ts-name { font-family: var(--font-code, ui-monospace, "SF Mono", Menlo, Consolas, monospace); font-size: var(--text-sm, 1.15rem); line-height: var(--text-sm-line, 1.6rem); color: var(--text-muted, oklch(0.72 0 0)); }
25
+ .ts-value { font-family: var(--font-code, ui-monospace, "SF Mono", Menlo, Consolas, monospace); font-size: var(--text-sm, 1.15rem); line-height: var(--text-sm-line, 1.6rem); overflow-wrap: anywhere; }
26
+ .ts-sample { display: flex; align-items: center; min-width: 0; }
27
+ .ts-probe { position: absolute; left: 0; top: 0; height: 0; visibility: hidden; }
28
+ `;
29
+
30
+ const tokenNamesOf = (css: string, only: (name: string) => boolean) => [
31
+ ...new Set([...css.matchAll(/^\s*--([\w-]+):/gmu)].map(([, name]) => name ?? '').filter(only)),
32
+ ];
33
+
34
+ const fillTokenValues = (root: HTMLElement, pixels: boolean) => {
35
+ const sheet = root.querySelector<HTMLElement>('.ts-root') ?? root;
36
+ const style = getComputedStyle(sheet);
37
+ const probe = sheet.querySelector<HTMLElement>('.ts-probe');
38
+
39
+ for (const cell of sheet.querySelectorAll<HTMLElement>('[data-token]')) {
40
+ const value = style.getPropertyValue(`--${cell.dataset['token']}`).trim();
41
+ let suffix = '';
42
+ if (pixels && probe && /^[\d.]+rem$/u.test(value)) {
43
+ probe.style.width = value;
44
+ suffix = ` · ${Math.round(probe.getBoundingClientRect().width * 10) / 10}px`;
45
+ }
46
+ cell.textContent = value + suffix;
47
+ }
48
+ };
49
+
50
+ /**
51
+ * Draws a foundation sheet: a sample panel, then one row per custom property declared in `css` (narrowed by `only`)
52
+ * with its value as the drawing resolves it, in px too for rem values when `pixels` is set.
53
+ * `scope` adds classes to the sheet root, so tokens scoped to a theme class resolve; `note` is markup under the title.
54
+ */
55
+ export const tokenSheet = ({
56
+ title,
57
+ note,
58
+ scope,
59
+ css,
60
+ sample,
61
+ sampleOf,
62
+ sampleClass = '',
63
+ only = () => true,
64
+ pixels = false,
65
+ styles = '',
66
+ setup,
67
+ }: TokenSheetOptions): Drawing => ({
68
+ body: html`<div class="ts-root${scope ? ` ${scope}` : ''}">
69
+ <h2 class="ts-title">${title}</h2>
70
+ ${note && html`<p class="ts-note">${note}</p>`}
71
+ <section class="ts-panel ${sampleClass}">${sample}</section>
72
+ <ul class="ts-panel ts-list">
73
+ ${tokenNamesOf(css, only)
74
+ .map(
75
+ (name) =>
76
+ html`<li class="ts-row">
77
+ <span class="ts-name">--${name}</span><span class="ts-value" data-token="${name}"></span
78
+ ><span class="ts-sample">${sampleOf(name)}</span>
79
+ </li>`,
80
+ )
81
+ .join('')}
82
+ </ul>
83
+ <span class="ts-probe"></span>
84
+ </div>`,
85
+ styles: `${SHEET_STYLES}${styles}`,
86
+ setup: [(root: HTMLElement) => fillTokenValues(root, pixels), ...(setup ? [setup] : [])],
87
+ });
@@ -9,8 +9,12 @@ declare module 'virtual:design-explore/env' {
9
9
  export const loadEnv: (project: string) => Promise<unknown>;
10
10
  /** The theme names the config declares for the project. The first of each list is the default. */
11
11
  export const themesOf: (project: string) => { surface: string[]; color: string[] };
12
- /** Loads the stylesheet a product draws under, which its base parts draw under too. */
13
- export const loadProductEnv: (product: string) => Promise<unknown>;
12
+ /** Loads the stylesheet a product, or one variant of one of its sketches, draws under, which its base parts draw under too. */
13
+ export const loadProductEnv: (options: {
14
+ product: string;
15
+ sketch: string | null;
16
+ variant: string;
17
+ }) => Promise<unknown>;
14
18
  }
15
19
 
16
20
  declare module 'virtual:design-explore/system' {
@@ -1,5 +1,7 @@
1
- import { CallVariant, Drawing, mountDrawing, placeOverlays } from '../define-call';
2
- import { fitEmbed } from '../embed-page';
1
+ import { CallVariant, Drawing, fitOutOfFlow, mountDrawing, placeOverlays } from '../define-call';
2
+ import { Part } from '../define-part';
3
+ import { applyEmbed, fitEmbed } from '../embed-page';
4
+ import { runRules, stepMotion, SteppedMotion } from '../motion-runtime';
3
5
  import { calls } from 'virtual:design-explore';
4
6
  import { loadEnv, loadProductEnv } from 'virtual:design-explore/env';
5
7
  import { parts, sketchParts, sketchTokens, tokens } from 'virtual:design-explore/system';
@@ -15,6 +17,8 @@ const fit = product !== null && params.has('fit');
15
17
  const interaction = product ? params.get('interaction') : null;
16
18
  const propsSketch = product ? params.get('props') : null;
17
19
  const propsVariant = params.get('props-variant') ?? '';
20
+ const motionName = product ? params.get('motion') : null;
21
+ const flowTo = product ? params.get('flow-to') : null;
18
22
 
19
23
  // Listens before the drawing loads, so an error it throws while loading counts; `report` exists only once `reporting` is set.
20
24
  let errored = false;
@@ -77,6 +81,19 @@ const showSetupError = (message: string) => {
77
81
 
78
82
  const messageOf = (error: unknown) => (error instanceof Error ? error.message : String(error));
79
83
 
84
+ const RETRY_DELAYS = [300, 1500];
85
+
86
+ // A part file that changes while frames load can fail its import once; Chromium fetches a failed module again.
87
+ const retried = <T>(load: () => Promise<T>, attempt = 0): Promise<T> =>
88
+ load().catch((error: unknown) => {
89
+ const delay = RETRY_DELAYS[attempt];
90
+ if (delay === undefined) throw error;
91
+
92
+ return new Promise<void>((resolve) => setTimeout(resolve, delay)).then(() => retried(load, attempt + 1));
93
+ });
94
+
95
+ let drawnPart: { part: Part<unknown>; states: Record<string, unknown> } | null = null;
96
+
80
97
  const drawCall = async (): Promise<Drawing | null> => {
81
98
  const call = calls[slug];
82
99
  if (!call) return fail(`design-explore: no call "${slug}"`);
@@ -106,10 +123,12 @@ const drawPart = async (name: string): Promise<Drawing | null> => {
106
123
  );
107
124
 
108
125
  try {
109
- const [{ default: part }, { default: holder }] = await Promise.all([load(), loadProps()]);
126
+ const [{ default: part }, { default: holder }] = await Promise.all([retried(load), retried(loadProps)]);
110
127
 
111
128
  if (!(key in holder.states)) return fail(`design-explore: part "${partKey}" has no state "${key}"`);
112
129
 
130
+ drawnPart = { part: part as Part<unknown>, states: holder.states };
131
+
113
132
  return await part.render(holder.states[key]);
114
133
  } catch (error) {
115
134
  return fail(`design-explore: state "${key}" of "${partKey}" failed\n${messageOf(error)}`);
@@ -135,7 +154,7 @@ const force = (element: Element, name: string) => {
135
154
  };
136
155
 
137
156
  const forced = async (css: string) => {
138
- if (!/:(?:hover|focus-visible|active)/iu.test(css)) return css;
157
+ if (!/:(?:hover|focus-visible|active|focus-within)/iu.test(css)) return css;
139
158
 
140
159
  const response = await fetch('/__design/force', { method: 'POST', body: css }).catch(() => null);
141
160
 
@@ -162,10 +181,136 @@ const report = () => {
162
181
  );
163
182
  };
164
183
 
184
+ const stateMarkupOf = ({ part, states }: NonNullable<typeof drawnPart>, styles: string) => {
185
+ const sheets = new Set([styles]);
186
+
187
+ return (state: string) =>
188
+ Promise.resolve(part.render(states[state])).then((drawn) =>
189
+ sheets.has(drawn.styles)
190
+ ? drawn.body
191
+ : forced(drawn.styles).then((css) => {
192
+ const style = document.createElement('style');
193
+
194
+ sheets.add(drawn.styles);
195
+ style.textContent = css;
196
+ document.head.append(style);
197
+
198
+ return drawn.body;
199
+ }),
200
+ );
201
+ };
202
+
203
+ const exposeStepped = (options: { start: () => Promise<SteppedMotion>; interrupt: number | null }) => {
204
+ let stepped: SteppedMotion | null = null;
205
+ const steppedOf = () => {
206
+ if (!stepped) throw new Error('design-explore: start the motion first');
207
+
208
+ return stepped;
209
+ };
210
+
211
+ Object.assign(window, {
212
+ etMotion: {
213
+ start: () =>
214
+ options.start().then((started) => {
215
+ stepped = started;
216
+
217
+ return true;
218
+ }),
219
+ seek: (ms: number) => steppedOf().seek(ms),
220
+ bounds: () => steppedOf().bounds(),
221
+ timeline: () => ({ end: steppedOf().end(), tracks: steppedOf().tracks(), interrupt: options.interrupt }),
222
+ },
223
+ });
224
+ };
225
+
226
+ const exposeMotion = (options: { drawn: NonNullable<typeof drawnPart>; name: string; styles: string }) => {
227
+ const { drawn, name, styles } = options;
228
+ const motion = drawn.part.motions?.[name];
229
+
230
+ if (!motion) {
231
+ const known = Object.keys(drawn.part.motions ?? {});
232
+
233
+ showSetupError(`design-explore: part "${partKey}" has no motion "${name}" - it has: ${known.join(', ') || 'none'}`);
234
+
235
+ return;
236
+ }
237
+
238
+ const markupOf = stateMarkupOf(drawn, styles);
239
+
240
+ exposeStepped({
241
+ interrupt: motion.interrupt ?? null,
242
+ start: () =>
243
+ Promise.all([markupOf(motion.to), motion.interrupt === undefined ? null : markupOf(motion.from)]).then(
244
+ ([markup, back]) =>
245
+ stepMotion({
246
+ root,
247
+ markup,
248
+ motion,
249
+ ...(back === null
250
+ ? {}
251
+ : {
252
+ reverse: {
253
+ markup: back,
254
+ motion: Object.values(drawn.part.motions ?? {}).find(
255
+ (other) => other.from === motion.to && other.to === motion.from,
256
+ ),
257
+ },
258
+ }),
259
+ }),
260
+ ),
261
+ });
262
+ };
263
+
264
+ const exposeFlowLine = (options: { product: string; to: string; styles: string }) => {
265
+ const [toPart = '', toState = ''] = options.to.split('#');
266
+ const load = parts[options.product]?.[toPart];
267
+
268
+ if (!load) {
269
+ showSetupError(`design-explore: product "${options.product}" has no part "${toPart}"`);
270
+
271
+ return;
272
+ }
273
+
274
+ exposeStepped({
275
+ interrupt: null,
276
+ start: () =>
277
+ retried(load).then(({ default: part }) => {
278
+ const states = (part as Part<unknown>).states;
279
+
280
+ if (!(toState in states)) throw new Error(`design-explore: part "${toPart}" has no state "${toState}"`);
281
+
282
+ // The styles of the to page ride in the markup: in <head> they would restyle the from page before the View Transition captures it.
283
+
284
+ return Promise.resolve((part as Part<unknown>).render(states[toState]))
285
+ .then((drawn) =>
286
+ drawn.styles === options.styles
287
+ ? drawn.body
288
+ : forced(drawn.styles).then((css) => `<style>${css}</style>${drawn.body}`),
289
+ )
290
+ .then((markup) => stepMotion({ root, markup, motion: { from: key, to: toState, viewTransition: true } }));
291
+ }),
292
+ });
293
+ };
294
+
295
+ const runPartRules = (drawn: NonNullable<typeof drawnPart>, styles: string) => {
296
+ runRules(root, {
297
+ state: key,
298
+ rules: drawn.part.rules ?? [],
299
+ motions: drawn.part.motions,
300
+ render: stateMarkupOf(drawn, styles),
301
+ switched: () => {
302
+ const partRoot = partRootOf(root);
303
+
304
+ if (interaction && partRoot) force(partRoot, interaction);
305
+ },
306
+ failed: (error) => showSetupError(`design-explore: switch of part "${partKey}" failed\n${messageOf(error)}`),
307
+ });
308
+ };
309
+
165
310
  // macOS WebKit can loop in module evaluation when a frame with top-level await is removed.
166
311
  const drawFrame = async () => {
167
312
  parent.postMessage({ type: 'design-explore:loading' }, '*');
168
- await (product ? loadProductEnv(product) : loadEnv(slug.split('/')[0] ?? ''));
313
+ await (product ? loadProductEnv({ product, sketch, variant: sketchVariant }) : loadEnv(slug.split('/')[0] ?? ''));
169
314
  const tokenStyles = product ? await tokensOf(product) : null;
170
315
  const loaded = await (product ? drawPart(product) : drawCall());
171
316
 
@@ -188,9 +333,17 @@ const drawFrame = async () => {
188
333
 
189
334
  if (error)
190
335
  showSetupError(`design-explore: setup of ${product ? 'state' : 'variant'} "${key}" failed\n${messageOf(error)}`);
336
+
337
+ if (flowTo && product) exposeFlowLine({ product, to: flowTo, styles: loaded.styles ?? '' });
338
+ else if (motionName && drawnPart) exposeMotion({ drawn: drawnPart, name: motionName, styles: loaded.styles ?? '' });
339
+ else if (drawnPart?.part.rules?.length) runPartRules(drawnPart, loaded.styles ?? '');
191
340
  }
192
341
 
193
- const place = () => placeOverlays(root);
342
+ const place = () => {
343
+ applyEmbed(frameElement, root);
344
+ placeOverlays(root);
345
+ fitOutOfFlow(root, { sideways: fit });
346
+ };
194
347
 
195
348
  new MutationObserver(place).observe(root, { childList: true, subtree: true });
196
349
  new ResizeObserver(place).observe(root);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ethlete/cli",
3
- "version": "3.0.0-next.23",
3
+ "version": "3.0.0-next.25",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/ethlete-io/ethdk",
@@ -14,6 +14,7 @@
14
14
  "et": "./src/index.js"
15
15
  },
16
16
  "dependencies": {
17
+ "@tailwindcss/node": "4.3.3",
17
18
  "@tailwindcss/postcss": "4.3.3",
18
19
  "postcss": "8.5.32",
19
20
  "postcss-selector-parser": "7.1.7",
@@ -24,12 +24,11 @@ exports.DRAWING_COMPILER_OPTIONS = {
24
24
  * tsconfig an editor finds for a call file.
25
25
  */
26
26
  const writeCallsTsconfig = (target) => {
27
- var _a, _b, _c;
28
27
  const work = (0, paths_1.workRootOf)(target);
29
28
  const path = (0, path_1.resolve)(work, 'tsconfig.json');
30
29
  const defineCall = (0, path_1.resolve)((0, paths_1.installedAssetRoot)(), 'define-call.ts');
31
30
  const inlineCss = (0, path_1.resolve)((0, paths_1.installedAssetRoot)(), 'css-inline.d.ts');
32
- const typePaths = (0, render_packages_1.typePathsOf)({ packages: (_c = (_b = (_a = (0, paths_1.readConfig)(target)) === null || _a === void 0 ? void 0 : _a.render) === null || _b === void 0 ? void 0 : _b.packages) !== null && _c !== void 0 ? _c : {}, target });
31
+ const typePaths = (0, render_packages_1.typePathsOf)({ packages: (0, render_packages_1.renderPackagesOf)({ target, config: (0, paths_1.readConfig)(target) }), target });
33
32
  const config = {
34
33
  compilerOptions: Object.assign(Object.assign({}, exports.DRAWING_COMPILER_OPTIONS), { paths: Object.assign(Object.assign({}, typePaths), { '@design-explore': [defineCall] }) }),
35
34
  include: [`${(0, paths_1.callsRootOf)(target)}/**/*.ts`, defineCall, inlineCss],
@@ -1 +1 @@
1
- {"version":3,"file":"calls-tsconfig.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/design/calls-tsconfig.ts"],"names":[],"mappings":";;;AAAA,2BAA8C;AAC9C,+BAAwC;AACxC,mCAA8F;AAC9F,uDAAgD;AAEnC,QAAA,wBAAwB,GAAG;IACtC,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,UAAU;IAClB,gBAAgB,EAAE,SAAS;IAC3B,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;IACtB,MAAM,EAAE,IAAI;IACZ,wBAAwB,EAAE,IAAI;IAC9B,eAAe,EAAE,IAAI;IACrB,YAAY,EAAE,IAAI;IAClB,MAAM,EAAE,IAAI;CACb,CAAC;AAEF;;;;;GAKG;AACI,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAE,EAAE;;IACnD,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAA,cAAO,EAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAA,cAAO,EAAC,IAAA,0BAAkB,GAAE,EAAE,gBAAgB,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,IAAA,cAAO,EAAC,IAAA,0BAAkB,GAAE,EAAE,iBAAiB,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,IAAA,6BAAW,EAAC,EAAE,QAAQ,EAAE,MAAA,MAAA,MAAA,IAAA,kBAAU,EAAC,MAAM,CAAC,0CAAE,MAAM,0CAAE,QAAQ,mCAAI,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IAEhG,MAAM,MAAM,GAAG;QACb,eAAe,kCACV,gCAAwB,KAC3B,KAAK,kCAAO,SAAS,KAAE,iBAAiB,EAAE,CAAC,UAAU,CAAC,MACvD;QACD,OAAO,EAAE,CAAC,GAAG,IAAA,mBAAW,EAAC,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC;KACnE,CAAC;IAEF,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACpD,MAAM,UAAU,GAAG,IAAA,cAAO,EAAC,MAAM,EAAE,kBAAU,EAAE,eAAe,CAAC,CAAC;IAEhE,IAAA,cAAS,EAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,IAAA,kBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1B,IAAA,cAAS,EAAC,IAAA,cAAO,EAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,IAAA,kBAAa,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEhC,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAxBW,QAAA,kBAAkB,sBAwB7B"}
1
+ {"version":3,"file":"calls-tsconfig.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/design/calls-tsconfig.ts"],"names":[],"mappings":";;;AAAA,2BAA8C;AAC9C,+BAAwC;AACxC,mCAA8F;AAC9F,uDAAkE;AAErD,QAAA,wBAAwB,GAAG;IACtC,KAAK,EAAE,EAAE;IACT,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,UAAU;IAClB,gBAAgB,EAAE,SAAS;IAC3B,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;IACtB,MAAM,EAAE,IAAI;IACZ,wBAAwB,EAAE,IAAI;IAC9B,eAAe,EAAE,IAAI;IACrB,YAAY,EAAE,IAAI;IAClB,MAAM,EAAE,IAAI;CACb,CAAC;AAEF;;;;;GAKG;AACI,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAE,EAAE;IACnD,MAAM,IAAI,GAAG,IAAA,kBAAU,EAAC,MAAM,CAAC,CAAC;IAChC,MAAM,IAAI,GAAG,IAAA,cAAO,EAAC,IAAI,EAAE,eAAe,CAAC,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAA,cAAO,EAAC,IAAA,0BAAkB,GAAE,EAAE,gBAAgB,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,IAAA,cAAO,EAAC,IAAA,0BAAkB,GAAE,EAAE,iBAAiB,CAAC,CAAC;IACnE,MAAM,SAAS,GAAG,IAAA,6BAAW,EAAC,EAAE,QAAQ,EAAE,IAAA,kCAAgB,EAAC,EAAE,MAAM,EAAE,MAAM,EAAE,IAAA,kBAAU,EAAC,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAE9G,MAAM,MAAM,GAAG;QACb,eAAe,kCACV,gCAAwB,KAC3B,KAAK,kCAAO,SAAS,KAAE,iBAAiB,EAAE,CAAC,UAAU,CAAC,MACvD;QACD,OAAO,EAAE,CAAC,GAAG,IAAA,mBAAW,EAAC,MAAM,CAAC,UAAU,EAAE,UAAU,EAAE,SAAS,CAAC;KACnE,CAAC;IAEF,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACpD,MAAM,UAAU,GAAG,IAAA,cAAO,EAAC,MAAM,EAAE,kBAAU,EAAE,eAAe,CAAC,CAAC;IAEhE,IAAA,cAAS,EAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACrC,IAAA,kBAAa,EAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1B,IAAA,cAAS,EAAC,IAAA,cAAO,EAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,IAAA,kBAAa,EAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IAEhC,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAxBW,QAAA,kBAAkB,sBAwB7B"}
@@ -34,10 +34,10 @@ export declare const changedPartsOf: (options: {
34
34
  dependents: string[];
35
35
  }) => PartsChange;
36
36
  /**
37
- * The frames a file that came or went redraws: every part of the product whose part folder holds it,
38
- * since an `@system/...` import anywhere in the product may now resolve to another file, or the parts
39
- * of the variant whose folder holds it. A file in no part folder redraws no part, only the frames
40
- * that show an error.
37
+ * The frames a file that came or went redraws: every part of the product whose part folder or `shared/`
38
+ * holds it, since an `@system/...` or `@shared/...` import anywhere in the product may now resolve to
39
+ * another file, or the parts of the variant whose folder holds it. A file in no part folder redraws no
40
+ * part, only the frames that show an error.
41
41
  */
42
42
  export declare const addedPartsOf: (options: {
43
43
  designRoot: string;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.addedPartsOf = exports.changedPartsOf = exports.redraws = exports.ALL_PARTS = void 0;
4
4
  const path_1 = require("path");
5
+ const imports_1 = require("./system/imports");
5
6
  const layers_1 = require("./system/layers");
6
7
  const resolve_product_1 = require("./system/resolve-product");
7
8
  const system_modules_1 = require("./system/system-modules");
@@ -68,10 +69,10 @@ const partFolderOf = (segments) => {
68
69
  return layer && name && inside !== undefined && (0, layers_1.isLayer)(layer) ? `${layer}/${name}` : null;
69
70
  };
70
71
  /**
71
- * The frames a file that came or went redraws: every part of the product whose part folder holds it,
72
- * since an `@system/...` import anywhere in the product may now resolve to another file, or the parts
73
- * of the variant whose folder holds it. A file in no part folder redraws no part, only the frames
74
- * that show an error.
72
+ * The frames a file that came or went redraws: every part of the product whose part folder or `shared/`
73
+ * holds it, since an `@system/...` or `@shared/...` import anywhere in the product may now resolve to
74
+ * another file, or the parts of the variant whose folder holds it. A file in no part folder redraws no
75
+ * part, only the frames that show an error.
75
76
  */
76
77
  const addedPartsOf = (options) => {
77
78
  var _a;
@@ -89,10 +90,13 @@ const addedPartsOf = (options) => {
89
90
  const parts = everyPartOf(system, product).filter((drawn) => { var _a; return ((_a = drawn.sketch) === null || _a === void 0 ? void 0 : _a.target) === target && drawn.sketch.variant === variant; });
90
91
  return parts.length > 0 ? { all: false, parts } : none;
91
92
  }
92
- return partFolderOf(rest) ? { all: false, parts: everyPartOf(system, product) } : none;
93
+ return partFolderOf(rest) || rest[0] === imports_1.SHARED_FOLDER
94
+ ? { all: false, parts: everyPartOf(system, product) }
95
+ : none;
93
96
  }
94
97
  const baseDir = baseDirs.find((dir) => file.startsWith(`${dir}${path_1.sep}`));
95
- if (!baseDir || !partFolderOf((0, path_1.relative)(baseDir, file).split(path_1.sep)))
98
+ const inBase = baseDir ? (0, path_1.relative)(baseDir, file).split(path_1.sep) : [];
99
+ if (!baseDir || (!partFolderOf(inBase) && inBase[0] !== imports_1.SHARED_FOLDER))
96
100
  return none;
97
101
  return {
98
102
  all: false,
@@ -1 +1 @@
1
- {"version":3,"file":"changed-parts.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/design/changed-parts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"changed-parts.js","sourceRoot":"","sources":["../../../../../libs/cli/src/lib/design/changed-parts.ts"],"names":[],"mappings":"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"}
@@ -25,7 +25,7 @@ type Pixels = {
25
25
  height: number;
26
26
  data: Uint8ClampedArray;
27
27
  };
28
- /** The smallest rectangle around every changed pixel, in pixels from the top left of the picture. */
28
+ /** A rectangle of changed pixels, in pixels from the top left of the picture. */
29
29
  export type ChangedBox = {
30
30
  x: number;
31
31
  y: number;
@@ -34,45 +34,58 @@ export type ChangedBox = {
34
34
  };
35
35
  /**
36
36
  * `after` faded to grey with each pixel that differs from `before` in red, over the larger of both sizes, with the
37
- * count of changed pixels and the `box` around them (`null` without one); a pixel only one of them covers counts as
38
- * changed. Runs in a browser page through its source, so it may use nothing outside its own body.
37
+ * count of changed pixels and one box per group of them (16 pixel tiles that touch); a pixel only one of them covers
38
+ * counts as changed. Runs in a browser page through its source, so it may use nothing outside its own body.
39
39
  */
40
40
  export declare function diffPixelsOf(before: Pixels, after: Pixels): {
41
41
  width: number;
42
42
  height: number;
43
43
  data: Uint8ClampedArray<ArrayBuffer>;
44
44
  changed: number;
45
- box: {
45
+ boxes: {
46
46
  x: number;
47
47
  y: number;
48
48
  width: number;
49
49
  height: number;
50
- } | null;
50
+ }[];
51
51
  };
52
+ /** The smallest box around every one of `boxes`, or `null` for none. */
53
+ export declare const boundsOf: (boxes: ChangedBox[]) => ChangedBox | null;
54
+ /**
55
+ * `boxes` with every two at most `gap` apart merged into one, top to bottom, then left to right. While more than
56
+ * `max` remain, the gap doubles.
57
+ */
58
+ export declare const clusteredBoxesOf: (boxes: ChangedBox[], options: {
59
+ gap: number;
60
+ max?: number;
61
+ }) => ChangedBox[];
52
62
  /** The width and height a PNG declares in its header. */
53
63
  export declare const pngSizeOf: (png: Buffer) => {
54
64
  width: number;
55
65
  height: number;
56
66
  };
57
67
  /**
58
- * One crop in CSS pixels around every changed box (in picture pixels, `scale` per CSS pixel), widened by `margin`
59
- * CSS pixels on each side and kept inside the `frame` picture; `null` when no box has a change.
68
+ * One crop in CSS pixels per cluster of changed `boxes` (in picture pixels, `scale` per CSS pixel), each widened by
69
+ * `margin` CSS pixels on each side and kept inside the `frame` picture; crops that touch merge. Empty without a box.
60
70
  */
61
- export declare const changedCropOf: (options: {
62
- boxes: (ChangedBox | null)[];
71
+ export declare const changedCropsOf: (options: {
72
+ boxes: ChangedBox[];
63
73
  frame: {
64
74
  width: number;
65
75
  height: number;
66
76
  };
67
77
  scale?: number;
68
78
  margin?: number;
69
- }) => ChangedBox | null;
70
- /** The box around the pixels `after` changes from `before`, or `null` when both draw the same pixels. */
71
- export declare const changedBoxOf: (options: {
79
+ }) => ChangedBox[];
80
+ /**
81
+ * One box per cluster of the pixels `after` changes from `before`: groups closer than 16 pixels merge, and at most
82
+ * eight remain. Empty when both draw the same pixels.
83
+ */
84
+ export declare const changedBoxesOf: (options: {
72
85
  browser: Browser;
73
86
  before: Buffer;
74
87
  after: Buffer;
75
- }) => Promise<ChangedBox | null>;
88
+ }) => Promise<ChangedBox[]>;
76
89
  /** The page that lays each row of cells side by side, a label above every cell, the rows stacked. */
77
90
  export declare const contactSheetHtml: (rows: SheetCell[][]) => string;
78
91
  /** Draws the cells into one PNG in the given browser, and returns one line per diff cell with its pixel result. */