@fusion.dev/helix 0.205.0 → 0.205.1

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.
@@ -178501,7 +178501,7 @@
178501
178501
  }
178502
178502
  }
178503
178503
  ],
178504
- "description": "Serves the frame side of a sandbox preview, in the document its `src` loads.\n\nCall it once from that document, after the elements your examples use are\ndefined. It does what the preview's protocol asks of a frame:\n\n- Posts `helix-preview-ready` once it listens.\n- Writes each `helix-preview-render` into the root: the markup, the\n stylesheet, the direction, the layout and the color mode. Scripts in the\n markup run.\n- Posts every console call, uncaught error, and unhandled promise rejection\n as `helix-preview-console`, an uncaught one marked `uncaught`, which marks\n the preview `failed`.\n- Posts `helix-preview-size` whenever what was drawn changes height.\n- Posts `helix-preview-press` on every press, so menus outside close.\n\nOnly a message from the parent window is rendered. Answers go to `*`, which\nis the only target a sandboxed frame can name, and carry only what the\nexample itself wrote."
178504
+ "description": "Serves the frame side of a sandbox preview, in the document its `src` loads.\n\nCall it once from that document, after the elements your examples use are\ndefined. It does what the preview's protocol asks of a frame:\n\n- Posts `helix-preview-ready` once it listens.\n- Writes each `helix-preview-render` into the root: the markup, the\n stylesheet, the direction, the layout and the color mode. Scripts in the\n markup run.\n- Posts every console call, uncaught error, and unhandled promise rejection\n as `helix-preview-console`, an uncaught one marked `uncaught`, which marks\n the preview `failed`.\n- Posts `helix-preview-rendered` after each render, which shows a frame\n the preview held transparent until it drew.\n- Posts `helix-preview-size` whenever what was drawn changes height.\n- Posts `helix-preview-press` on every press, so menus outside close.\n\nOnly a message from the parent window is rendered. Answers go to `*`, which\nis the only target a sandboxed frame can name, and carry only what the\nexample itself wrote."
178505
178505
  },
178506
178506
  {
178507
178507
  "kind": "function",
@@ -179240,6 +179240,54 @@
179240
179240
  "default": "new DelayController(this, { renders: false })",
179241
179241
  "description": "Holds a coalesced send, so only one is ever queued, and drops it on\ndisconnect.\n\n**It renders nothing**, so it asks for no update when its wait starts or\nends. One that did sent the source at once from that update, ahead of the\nwait, and the send at the end of the wait then cleared `failed` after the\nerror it should have reported."
179242
179242
  },
179243
+ {
179244
+ "kind": "field",
179245
+ "name": "patience",
179246
+ "privacy": "private",
179247
+ "readonly": true,
179248
+ "default": "new DelayController(this, { renders: false })",
179249
+ "description": "Shows a frame that was sent an example and never said it drew it."
179250
+ },
179251
+ {
179252
+ "kind": "field",
179253
+ "name": "blank",
179254
+ "type": {
179255
+ "text": "boolean"
179256
+ },
179257
+ "privacy": "private",
179258
+ "default": "false",
179259
+ "description": "Whether the frame has drawn nothing since its document started loading."
179260
+ },
179261
+ {
179262
+ "kind": "method",
179263
+ "name": "setBlank",
179264
+ "privacy": "private",
179265
+ "return": {
179266
+ "type": {
179267
+ "text": "void"
179268
+ }
179269
+ },
179270
+ "parameters": [
179271
+ {
179272
+ "name": "on",
179273
+ "type": {
179274
+ "text": "boolean"
179275
+ }
179276
+ }
179277
+ ],
179278
+ "description": "Marks the frame `blank`, or shown."
179279
+ },
179280
+ {
179281
+ "kind": "method",
179282
+ "name": "drawn",
179283
+ "privacy": "private",
179284
+ "return": {
179285
+ "type": {
179286
+ "text": "void"
179287
+ }
179288
+ },
179289
+ "description": "The frame has drawn an example, so it is shown."
179290
+ },
179243
179291
  {
179244
179292
  "kind": "method",
179245
179293
  "name": "scheduleSend",
@@ -179844,6 +179892,10 @@
179844
179892
  }
179845
179893
  ],
179846
179894
  "cssStates": [
179895
+ {
179896
+ "description": "From the moment the frame's document starts loading until it has drawn an example. The styled tier keeps the frame transparent meanwhile, so a document that has not yet drawn in the page's color mode does not show as a white flash.",
179897
+ "name": "blank"
179898
+ },
179847
179899
  {
179848
179900
  "description": "Since the example threw an error it did not catch, until the next source is sent.",
179849
179901
  "name": "failed"
@@ -272893,6 +272945,6 @@
272893
272945
  ],
272894
272946
  "helix": {
272895
272947
  "package": "@fusion.dev/helix",
272896
- "version": "0.205.0"
272948
+ "version": "0.205.1"
272897
272949
  }
272898
272950
  }
@@ -54,6 +54,8 @@ export declare const loggedText: (value: unknown) => string;
54
54
  * - Posts every console call, uncaught error, and unhandled promise rejection
55
55
  * as `helix-preview-console`, an uncaught one marked `uncaught`, which marks
56
56
  * the preview `failed`.
57
+ * - Posts `helix-preview-rendered` after each render, which shows a frame
58
+ * the preview held transparent until it drew.
57
59
  * - Posts `helix-preview-size` whenever what was drawn changes height.
58
60
  * - Posts `helix-preview-press` on every press, so menus outside close.
59
61
  *
@@ -124,6 +124,7 @@ const serveWith = (tools, options = {}) => {
124
124
  sheet.textContent = styles;
125
125
  options.onRender?.(root, fresh);
126
126
  measure();
127
+ post({ type: 'helix-preview-rendered' });
127
128
  };
128
129
  const watcher = new ResizeObserver(measure);
129
130
  const watch = () => {
@@ -1,2 +1,2 @@
1
1
  import { createSheet } from '@fusion.dev/helix-core';
2
- export const styles = createSheet(`:host {display: block;min-block-size: 0;position: relative}[part="frame"] {background-color: var(--helix-color-background);block-size: 100%;border: none;display: block;inline-size: 100%}[part="error"] {background-color: var(--helix-color-background);box-sizing: border-box;color: var(--helix-color-danger);font-family: var(--helix-font-mono);font-size: var(--helix-text-xs);inset: 0;line-height: var(--helix-leading-normal);margin: var(--helix-space-none);overflow: auto;padding: var(--helix-space-md);position: absolute;white-space: pre-wrap;word-break: break-word}[part="controls"] {display: flex;font-family: var(--helix-font-sans);font-size: var(--helix-text-xs);gap: var(--helix-space-2xs);inset-block-end: var(--helix-space-xs);inset-inline-end: var(--helix-space-xs);position: absolute}[part="reload"], [part="open"] {background-color: var(--helix-color-surface);border: var(--helix-border-thin) solid var(--helix-color-border);border-radius: var(--helix-radii-sm);color: var(--helix-color-foreground);cursor: pointer;font: inherit;padding: var(--helix-space-2xs) var(--helix-space-xs)}[part="reload"]:hover, [part="open"]:hover {background-color: var(--helix-color-surface-sunken)}[part="reload"]:focus-visible, [part="open"]:focus-visible {outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);outline-offset: var(--helix-size-focus-offset)}`);
2
+ export const styles = createSheet(`:host {display: block;min-block-size: 0;position: relative}[part="frame"] {background-color: var(--helix-color-background);block-size: 100%;border: none;display: block;inline-size: 100%}[part="error"] {background-color: var(--helix-color-background);box-sizing: border-box;color: var(--helix-color-danger);font-family: var(--helix-font-mono);font-size: var(--helix-text-xs);inset: 0;line-height: var(--helix-leading-normal);margin: var(--helix-space-none);overflow: auto;padding: var(--helix-space-md);position: absolute;white-space: pre-wrap;word-break: break-word}[part="controls"] {display: flex;font-family: var(--helix-font-sans);font-size: var(--helix-text-xs);gap: var(--helix-space-2xs);inset-block-end: var(--helix-space-xs);inset-inline-end: var(--helix-space-xs);position: absolute}[part="reload"], [part="open"] {background-color: var(--helix-color-surface);border: var(--helix-border-thin) solid var(--helix-color-border);border-radius: var(--helix-radii-sm);color: var(--helix-color-foreground);cursor: pointer;font: inherit;padding: var(--helix-space-2xs) var(--helix-space-xs)}[part="reload"]:hover, [part="open"]:hover {background-color: var(--helix-color-surface-sunken)}[part="reload"]:focus-visible, [part="open"]:focus-visible {outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);outline-offset: var(--helix-size-focus-offset)}:host(:state(blank)) [part="frame"] {opacity: 0}`);
@@ -35,12 +35,16 @@ export interface PreviewConsole {
35
35
  export interface PreviewPress {
36
36
  type: 'helix-preview-press';
37
37
  }
38
+ /** The frame saying it has drawn the example it was sent. */
39
+ export interface PreviewRendered {
40
+ type: 'helix-preview-rendered';
41
+ }
38
42
  /** How tall the frame says its content is, in CSS pixels. */
39
43
  export interface PreviewSize {
40
44
  size: number;
41
45
  type: 'helix-preview-size';
42
46
  }
43
- export type PreviewMessage = PreviewConsole | PreviewFetch | PreviewPress | PreviewReady | PreviewRender | PreviewSize;
47
+ export type PreviewMessage = PreviewConsole | PreviewFetch | PreviewPress | PreviewReady | PreviewRender | PreviewRendered | PreviewSize;
44
48
  /**
45
49
  * @summary A frame that renders sandbox source in a separate document.
46
50
  *
@@ -140,6 +144,7 @@ export type PreviewMessage = PreviewConsole | PreviewFetch | PreviewPress | Prev
140
144
  * @csspart open - The button that opens the example in a new tab, under `controls`.
141
145
  * @csspart reload - The button that reloads the frame's document, under `controls`.
142
146
  *
147
+ * @cssstate blank - From the moment the frame's document starts loading until it has drawn an example. The styled tier keeps the frame transparent meanwhile, so a document that has not yet drawn in the page's color mode does not show as a white flash.
143
148
  * @cssstate failed - Since the example threw an error it did not catch, until the next source is sent.
144
149
  * @cssstate loading - While the frame's document loads, until it can take the example.
145
150
  */
@@ -368,6 +373,14 @@ export declare class HelixSandboxPreview extends HelixElement {
368
373
  * error it should have reported.
369
374
  */
370
375
  private readonly settle;
376
+ /** Shows a frame that was sent an example and never said it drew it. */
377
+ private readonly patience;
378
+ /** Whether the frame has drawn nothing since its document started loading. */
379
+ private blank;
380
+ /** Marks the frame `blank`, or shown. */
381
+ private setBlank;
382
+ /** The frame has drawn an example, so it is shown. */
383
+ private drawn;
371
384
  /**
372
385
  * Sends once the typing stops, replacing anything already waiting.
373
386
  *
@@ -2,6 +2,7 @@ var HelixSandboxPreview_1;
2
2
  import { __decorate } from "tslib";
3
3
  import { customElement, DelayController, HelixConsoleEvent, HelixElement, HelixResizeEvent, words, } from '@fusion.dev/helix-core';
4
4
  const SETTLE = 120;
5
+ const PAINT_PATIENCE = 1000;
5
6
  import { html, nothing } from 'lit';
6
7
  import { property, state } from 'lit/decorators.js';
7
8
  import { COMPILED, compile } from '../compile.js';
@@ -47,6 +48,9 @@ let HelixSandboxPreview = class HelixSandboxPreview extends HelixElement {
47
48
  this.handleFrameLoad();
48
49
  return;
49
50
  }
51
+ if (data?.type === 'helix-preview-rendered' || data?.type === 'helix-preview-size') {
52
+ this.drawn();
53
+ }
50
54
  if (data?.type === 'helix-preview-console') {
51
55
  this.dispatchEvent(new HelixConsoleEvent({ level: data.level, text: data.text }));
52
56
  if (data.uncaught) {
@@ -62,6 +66,8 @@ let HelixSandboxPreview = class HelixSandboxPreview extends HelixElement {
62
66
  }
63
67
  };
64
68
  this.settle = new DelayController(this, { renders: false });
69
+ this.patience = new DelayController(this, { renders: false });
70
+ this.blank = false;
65
71
  this.loadedMap = '';
66
72
  }
67
73
  static { HelixSandboxPreview_1 = this; }
@@ -139,6 +145,14 @@ let HelixSandboxPreview = class HelixSandboxPreview extends HelixElement {
139
145
  });
140
146
  }
141
147
  static { this.target = '*'; }
148
+ setBlank(on) {
149
+ this.blank = on;
150
+ this.toggleState('blank', on);
151
+ }
152
+ drawn() {
153
+ this.patience.cancel();
154
+ this.setBlank(false);
155
+ }
142
156
  scheduleSend() {
143
157
  this.settle.start(SETTLE, () => {
144
158
  if (this.sending !== this.failedSource) {
@@ -163,6 +177,9 @@ let HelixSandboxPreview = class HelixSandboxPreview extends HelixElement {
163
177
  }
164
178
  this.frame?.contentWindow?.postMessage(this.message, HelixSandboxPreview_1.target);
165
179
  this.sentSource = this.sending;
180
+ if (this.blank) {
181
+ this.patience.start(PAINT_PATIENCE, () => this.drawn());
182
+ }
166
183
  }
167
184
  open() {
168
185
  const tab = window.open('', '_blank');
@@ -223,7 +240,9 @@ frame.onload = () => frame.contentWindow.postMessage(${JSON.stringify(this.messa
223
240
  this.sentSource = undefined;
224
241
  this.failedSource = undefined;
225
242
  this.fail();
243
+ this.patience.cancel();
226
244
  this.toggleState('loading', true);
245
+ this.setBlank(true);
227
246
  }
228
247
  willUpdate(changed) {
229
248
  super.willUpdate(changed);