gesso-framework 0.1.0 → 0.2.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.
- package/CHANGELOG.md +45 -0
- package/README.md +1 -1
- package/dist/{index-BkYPVXSJ.d.ts → index-C8yYHFKz.d.ts} +191 -8
- package/dist/index.d.ts +2 -2
- package/dist/index.js +479 -17
- package/dist/index.js.map +1 -1
- package/dist/worker/index.d.ts +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { $ as InternalState, A as printPropValue, B as channel, C as captureConsole, D as formatNodePath, E as formatAge, F as applyPatch, G as mutate, H as viewKeys, I as applyPatches, J as select, K as Resource, L as diffProjection, M as provide, N as findUnplainPath, O as formatNodeReport, P as requirePlainData, Q as structurallyEqual, R as isChannelClientMessage, S as workerHandle, T as describeStream, U as debounced, V as defineChannel, W as throttled, X as computed, Y as ComputedCell, Z as derive, _ as isHubMessage, a as undoable, at as output, b as portHandle, c as classifyStorageError, d as storageReadValue, et as internalState, f as pick, g as APPLICATION_WORKER, h as serveChannels, i as OpfsStorage, it as isOutputTarget, j as ProvidedChannel, k as formatStream, l as storageErrorMessage, m as serve, n as persisted, nt as input, o as UndoStack, ot as outputTargetOf, p as pickKeys, q as resource, r as IndexedDbStorage, rt as into, s as MemoryStorage, st as withBodyOf, t as PersistedState, tt as InputCell, u as storageReadFailure, v as isPortErrorMessage, w as isConsoleEntryMessage, x as servePorts, y as isPortHandshake, z as isChannelHostMessage } from "./persisted-Ddb51avc.js";
|
|
2
2
|
import { a as Each, i as show, n as getComponentMetadata, o as each, r as Show, t as createComponent } from "./createComponent-3n1ZSql8.js";
|
|
3
3
|
import { BehaviorSubject, EMPTY, Subject, Subscription, distinctUntilChanged, map } from "rxjs";
|
|
4
|
-
import { AnimationDriver, Box, Canvas2DRenderer, CanvasPlatformSurface, CanvasTextMeasurer, Constraints, DefaultImageResolver, DefaultVideoResolver, DirtyFlags, EnvironmentNotifier, FocusNotifier, IconRasterizer, LayoutEngine, LayoutInspector, LayoutNotifier, MARK_PREFIX, Stack, UI_ROLES, UI_SEMANTIC_STATES, UiAnimationFrameClock, UiEditingController, UiEnvironmentKeys, UiEventType, UiFindController, UiFocusManager, UiGestureRecognizer, UiGraph, UiGraphBuilder, UiHitTester, UiHostFrameClock, UiInputDispatcher, UiInsetRegistry, UiKeyboardController, UiNodeType, UiPlatformAdapter, UiPointerController, UiPointerEvent, UiScheduler, UiSelectionController, UiSharedElements, UiSpring, UiTimerFrameClock, UiTouchScroller, UiVirtualWindow, UiWheelController, VIRTUAL_INDEX_PROP, VIRTUAL_LEAD_PROP, VIRTUAL_WINDOW_PROP, WebGPURenderer, buildSemanticsTree, bumpFontStack, capturePointer, createCanvasSurface, createTween, createWebGPUSurface, defaultMotion, describeOverrides, diffSemantics, easings, formatExplanation, insetsEqual, isComponentLikeElement, isObservable, isWebGPUAvailable, linear, linkOf, markInstant, markNow, measure, measureSpan, motion, noInsets, observeViewportInsets, percent, performanceMarksEnabled, pointerDeviceOf, prepareInputSurface, propertyEffects, registerFontStack, resolveCursor, scrollbarThumb, setPerformanceMarks, setPerformanceMarks as setPerformanceMarks$1, textRunOfRecordId, themeTokens, touchActionFor, wheelDeltaYOf } from "gesso-core";
|
|
4
|
+
import { AnimationDriver, Box, Canvas2DRenderer, CanvasPlatformSurface, CanvasTextMeasurer, Constraints, DefaultImageResolver, DefaultVideoResolver, DirtyFlags, EnvironmentNotifier, FocusNotifier, IconRasterizer, LayoutEngine, LayoutInspector, LayoutNotifier, MARK_PREFIX, Stack, TEXT_RUN_ID_SEPARATOR, UI_ROLES, UI_SEMANTIC_STATES, UiAnimationFrameClock, UiEditingController, UiEnvironmentKeys, UiEventType, UiFindController, UiFocusManager, UiGestureRecognizer, UiGraph, UiGraphBuilder, UiHitTester, UiHostFrameClock, UiInputDispatcher, UiInsetRegistry, UiKeyboardController, UiNodeType, UiPlatformAdapter, UiPointerController, UiPointerEvent, UiScheduler, UiSelectionController, UiSharedElements, UiSpring, UiTimerFrameClock, UiTouchScroller, UiVirtualWindow, UiWheelController, VIRTUAL_INDEX_PROP, VIRTUAL_LEAD_PROP, VIRTUAL_WINDOW_PROP, WebGPURenderer, buildSemanticsSubtree, buildSemanticsTree, bumpFontStack, capturePointer, createCanvasSurface, createTween, createWebGPUSurface, defaultMotion, describeOverrides, diffSemantics, easings, formatExplanation, insetsEqual, isComponentLikeElement, isObservable, isWebGPUAvailable, linear, linkOf, markInstant, markNow, measure, measureSpan, motion, noInsets, observeViewportInsets, percent, performanceMarksEnabled, pointerDeviceOf, prepareInputSurface, propertyEffects, recordsEqual, registerFontStack, resolveCursor, scrollbarThumb, semanticsInertAbove, setPerformanceMarks, setPerformanceMarks as setPerformanceMarks$1, textRunOfRecordId, themeTokens, touchActionFor, wheelDeltaYOf } from "gesso-core";
|
|
5
5
|
//#region src/Component.ts
|
|
6
6
|
/**
|
|
7
7
|
* Base class for all Gesso framework components.
|
|
@@ -1057,6 +1057,7 @@ var ShellService = class {
|
|
|
1057
1057
|
handler = null;
|
|
1058
1058
|
scheme = internalState("light");
|
|
1059
1059
|
insets = internalState(noInsets);
|
|
1060
|
+
isFullscreen = internalState(false);
|
|
1060
1061
|
/** Popups asked for and not yet answered, by the id sent with each. */
|
|
1061
1062
|
popups = /* @__PURE__ */ new Map();
|
|
1062
1063
|
nextPopupId = 1;
|
|
@@ -1156,6 +1157,35 @@ var ShellService = class {
|
|
|
1156
1157
|
});
|
|
1157
1158
|
}
|
|
1158
1159
|
/**
|
|
1160
|
+
* Whether the application's surface is filling the screen.
|
|
1161
|
+
*
|
|
1162
|
+
* Read rather than assumed: the person can leave fullscreen with
|
|
1163
|
+
* Escape, which no request here hears about, and a button that
|
|
1164
|
+
* tracked its own last press would then point the wrong way. The
|
|
1165
|
+
* shell reports the real state and this follows it.
|
|
1166
|
+
*/
|
|
1167
|
+
fullscreen = this.isFullscreen;
|
|
1168
|
+
/**
|
|
1169
|
+
* Asks the shell to fill the screen, or to stop.
|
|
1170
|
+
*
|
|
1171
|
+
* A request rather than a call, for the reason the clipboard is one:
|
|
1172
|
+
* the Fullscreen API is the document's, and the thread this runs on
|
|
1173
|
+
* may not have a document. It can also be refused outright, because
|
|
1174
|
+
* browsers only grant it during a gesture, which is why nothing here
|
|
1175
|
+
* returns a promise pretending otherwise. Watch `fullscreen` for what
|
|
1176
|
+
* actually happened.
|
|
1177
|
+
*/
|
|
1178
|
+
requestFullscreen(enter) {
|
|
1179
|
+
this.handler?.({
|
|
1180
|
+
type: "fullscreen",
|
|
1181
|
+
enter
|
|
1182
|
+
});
|
|
1183
|
+
}
|
|
1184
|
+
/** Called by the runtime when the shell reports the state. Not for applications. */
|
|
1185
|
+
applyFullscreen(active) {
|
|
1186
|
+
if (this.isFullscreen.value !== active) this.isFullscreen.value = active;
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1159
1189
|
* Opens a sized window and answers whether the browser allowed it.
|
|
1160
1190
|
*
|
|
1161
1191
|
* Separate from `openUrl` because the two differ in three ways that
|
|
@@ -3065,6 +3095,12 @@ var GessoRuntime = class {
|
|
|
3065
3095
|
replicas = [];
|
|
3066
3096
|
phaseTimings = emptyPhaseTimings();
|
|
3067
3097
|
started = false;
|
|
3098
|
+
/**
|
|
3099
|
+
* Whether the engine holds a laid-out tree, so `resize` knows which
|
|
3100
|
+
* path it is on. Set by the first resize and by the first frame that
|
|
3101
|
+
* lays out, whichever comes first; see `resize`.
|
|
3102
|
+
*/
|
|
3103
|
+
laidOutOnce = false;
|
|
3068
3104
|
constructor(options) {
|
|
3069
3105
|
this.services = options.services ?? new ServiceRegistry();
|
|
3070
3106
|
this.channels = options.channels ?? new ChannelRegistry();
|
|
@@ -3150,6 +3186,12 @@ var GessoRuntime = class {
|
|
|
3150
3186
|
y: record.scrollY
|
|
3151
3187
|
};
|
|
3152
3188
|
},
|
|
3189
|
+
viewport: () => ({
|
|
3190
|
+
x: 0,
|
|
3191
|
+
y: 0,
|
|
3192
|
+
width: this.width,
|
|
3193
|
+
height: this.height
|
|
3194
|
+
}),
|
|
3153
3195
|
onLayout: (node, listener) => this.layoutNotifier.add(node, listener)
|
|
3154
3196
|
},
|
|
3155
3197
|
animations: this.animations,
|
|
@@ -3323,8 +3365,12 @@ var GessoRuntime = class {
|
|
|
3323
3365
|
this.renderer.resize(width, height, dpr);
|
|
3324
3366
|
this.constraints = Constraints.loose(width, height);
|
|
3325
3367
|
if (this.root === void 0) return;
|
|
3326
|
-
this.
|
|
3327
|
-
|
|
3368
|
+
if (this.laidOutOnce) this.graph.markDirty(this.root, DirtyFlags.Layout | DirtyFlags.Paint);
|
|
3369
|
+
else {
|
|
3370
|
+
this.laidOutOnce = true;
|
|
3371
|
+
this.engine.layout(this.root, this.constraints);
|
|
3372
|
+
this.graph.markDirty(this.root, DirtyFlags.Paint);
|
|
3373
|
+
}
|
|
3328
3374
|
if (this.started) this.scheduler.flush(now());
|
|
3329
3375
|
}
|
|
3330
3376
|
/**
|
|
@@ -3614,6 +3660,17 @@ var GessoRuntime = class {
|
|
|
3614
3660
|
* `AnimationDriver.setHidden` for why an entrance frozen at its
|
|
3615
3661
|
* first value is a hole in the page rather than a paused animation.
|
|
3616
3662
|
*/
|
|
3663
|
+
/**
|
|
3664
|
+
* The shell says the surface entered or left fullscreen.
|
|
3665
|
+
*
|
|
3666
|
+
* Reported rather than inferred from the request that asked for it,
|
|
3667
|
+
* because the person can leave with Escape and a browser can refuse
|
|
3668
|
+
* to enter at all; a control that tracked its own last press would
|
|
3669
|
+
* then point the wrong way.
|
|
3670
|
+
*/
|
|
3671
|
+
setFullscreen(active) {
|
|
3672
|
+
this.services.get(ShellService).applyFullscreen(active);
|
|
3673
|
+
}
|
|
3617
3674
|
setVisible(visible) {
|
|
3618
3675
|
this.input.editing.setVisible(visible);
|
|
3619
3676
|
if (visible === this.visible) return;
|
|
@@ -4284,17 +4341,12 @@ var GessoRuntime = class {
|
|
|
4284
4341
|
* to say. `UiSemanticsUpdate` explains why they travel together
|
|
4285
4342
|
* anyway.
|
|
4286
4343
|
*/
|
|
4287
|
-
updateSemantics(rebuild, moved) {
|
|
4344
|
+
updateSemantics(frame, rebuild, moved) {
|
|
4288
4345
|
let patches = EMPTY_PATCHES;
|
|
4289
4346
|
const listener = this.semanticsListener;
|
|
4290
4347
|
if (rebuild) {
|
|
4291
4348
|
if (listener === null) this.semanticsStale = true;
|
|
4292
|
-
else
|
|
4293
|
-
const next = buildSemanticsTree(this.layoutRoot());
|
|
4294
|
-
patches = diffSemantics(this.semantics, next);
|
|
4295
|
-
this.semantics = next;
|
|
4296
|
-
this.semanticsStale = false;
|
|
4297
|
-
}
|
|
4349
|
+
else patches = this.rescopeSemantics(frame) ?? this.rebuildSemantics();
|
|
4298
4350
|
}
|
|
4299
4351
|
if (listener === null) return;
|
|
4300
4352
|
const boxes = moved || patches.length > 0 ? this.collectSemanticsBoxes() : EMPTY_BOXES;
|
|
@@ -4311,23 +4363,160 @@ var GessoRuntime = class {
|
|
|
4311
4363
|
boxes
|
|
4312
4364
|
});
|
|
4313
4365
|
}
|
|
4366
|
+
/** Walks the whole tree and diffs it against the last one. */
|
|
4367
|
+
rebuildSemantics() {
|
|
4368
|
+
const next = buildSemanticsTree(this.layoutRoot());
|
|
4369
|
+
const patches = diffSemantics(this.semantics, next);
|
|
4370
|
+
this.semantics = next;
|
|
4371
|
+
this.semanticsStale = false;
|
|
4372
|
+
return patches;
|
|
4373
|
+
}
|
|
4374
|
+
/**
|
|
4375
|
+
* The patches for a frame that changed what some nodes *mean*
|
|
4376
|
+
* without changing which nodes there are — or null when that cannot
|
|
4377
|
+
* be established cheaply, and the whole tree has to be walked.
|
|
4378
|
+
*
|
|
4379
|
+
* This is the common case and it used to cost the uncommon one. A
|
|
4380
|
+
* bound label is `text`, `text` marks semantics dirty, and the phase
|
|
4381
|
+
* answered every one of them by rebuilding the tree from the root
|
|
4382
|
+
* and diffing two maps: on the benchmark list, 2 ms on any frame a
|
|
4383
|
+
* clock ticked, next to 0.03 ms for the layout of the same change.
|
|
4384
|
+
*
|
|
4385
|
+
* So the walk is rooted at what actually changed. For each dirty
|
|
4386
|
+
* node the nearest ancestor *carrying a record* is found — a
|
|
4387
|
+
* `Button`'s label lives on the button, not on the `Text` inside it
|
|
4388
|
+
* that a parent claimed — and only that node's subtree is walked.
|
|
4389
|
+
* `buildSemanticsSubtree` explains why the owner has to be a record
|
|
4390
|
+
* holder for the indices to come out the same.
|
|
4391
|
+
*
|
|
4392
|
+
* It gives up, and says so with null, whenever the *shape* of the
|
|
4393
|
+
* tree could have moved:
|
|
4394
|
+
*
|
|
4395
|
+
* - a frame that changed the tree's children, which is a structural
|
|
4396
|
+
* change by definition;
|
|
4397
|
+
* - a dirty node with no record-holding ancestor, whose records sit
|
|
4398
|
+
* at the top level and are numbered among everything else there;
|
|
4399
|
+
* - an owner that is no longer describable, whose children would
|
|
4400
|
+
* reattach further up;
|
|
4401
|
+
* - a subtree that gained or lost a record, because `this.semantics`
|
|
4402
|
+
* is insertion-ordered and the diff promises adds in document
|
|
4403
|
+
* order — splicing one into the middle of a Map cannot preserve
|
|
4404
|
+
* that, and a mirror appending a child before its parent is a
|
|
4405
|
+
* worse bug than a slow frame.
|
|
4406
|
+
*
|
|
4407
|
+
* Each of those falls back to the full rebuild, which is correct by
|
|
4408
|
+
* construction. Nothing here decides what a record says; it only
|
|
4409
|
+
* decides how much of the tree has to be asked.
|
|
4410
|
+
*/
|
|
4411
|
+
rescopeSemantics(frame) {
|
|
4412
|
+
if (this.semantics.size === 0 || this.semanticsStale) return null;
|
|
4413
|
+
const owners = /* @__PURE__ */ new Set();
|
|
4414
|
+
for (const [node, flags] of frame.entries()) {
|
|
4415
|
+
if ((flags & DirtyFlags.Children) !== 0) return null;
|
|
4416
|
+
if ((flags & DirtyFlags.Semantics) === 0) continue;
|
|
4417
|
+
const owner = this.semanticsOwnerOf(node);
|
|
4418
|
+
if (owner === null) return null;
|
|
4419
|
+
owners.add(owner);
|
|
4420
|
+
if (owners.size > SCOPED_SEMANTICS_OWNERS) return null;
|
|
4421
|
+
}
|
|
4422
|
+
if (owners.size === 0) return null;
|
|
4423
|
+
const updates = [];
|
|
4424
|
+
for (const owner of owners) {
|
|
4425
|
+
const previous = this.semantics.get(owner.id);
|
|
4426
|
+
const subtree = buildSemanticsSubtree(owner, previous.parent, previous.index, semanticsInertAbove(owner));
|
|
4427
|
+
if (subtree === null) return null;
|
|
4428
|
+
let covered = 0;
|
|
4429
|
+
for (const id of this.semanticIdsUnder(owner)) {
|
|
4430
|
+
const next = subtree.get(id);
|
|
4431
|
+
if (next === void 0) return null;
|
|
4432
|
+
covered++;
|
|
4433
|
+
const before = this.semantics.get(id);
|
|
4434
|
+
if (!recordsEqual(before, next)) updates.push(next);
|
|
4435
|
+
}
|
|
4436
|
+
if (covered !== subtree.size) return null;
|
|
4437
|
+
}
|
|
4438
|
+
const patches = [];
|
|
4439
|
+
for (const record of updates) {
|
|
4440
|
+
this.semantics.set(record.id, record);
|
|
4441
|
+
patches.push({
|
|
4442
|
+
op: "update",
|
|
4443
|
+
node: record
|
|
4444
|
+
});
|
|
4445
|
+
}
|
|
4446
|
+
return patches;
|
|
4447
|
+
}
|
|
4314
4448
|
/**
|
|
4315
|
-
* The
|
|
4449
|
+
* The nearest node at or above `node` that holds a semantics record,
|
|
4450
|
+
* or null when nothing above it does.
|
|
4451
|
+
*/
|
|
4452
|
+
semanticsOwnerOf(node) {
|
|
4453
|
+
for (let current = node; current !== null; current = current.parent) if (this.semantics.has(current.id)) return current;
|
|
4454
|
+
return null;
|
|
4455
|
+
}
|
|
4456
|
+
/**
|
|
4457
|
+
* The ids in the current tree that belong to `node`'s subtree.
|
|
4458
|
+
*
|
|
4459
|
+
* Read off the graph rather than remembered, which is sound here
|
|
4460
|
+
* precisely because the caller has established that no node's
|
|
4461
|
+
* children changed this frame.
|
|
4462
|
+
*
|
|
4463
|
+
* A text run is not a node and has no id of its own: it borrows its
|
|
4464
|
+
* paragraph's and adds its position, numbered from zero without
|
|
4465
|
+
* gaps. So the runs of a node are found by counting up until one is
|
|
4466
|
+
* missing, rather than by scanning every key for the prefix.
|
|
4467
|
+
*/
|
|
4468
|
+
semanticIdsUnder(node) {
|
|
4469
|
+
const ids = [];
|
|
4470
|
+
const stack = [node];
|
|
4471
|
+
while (stack.length > 0) {
|
|
4472
|
+
const current = stack.pop();
|
|
4473
|
+
if (this.semantics.has(current.id)) {
|
|
4474
|
+
ids.push(current.id);
|
|
4475
|
+
for (let run = 0;; run++) {
|
|
4476
|
+
const id = `${current.id}${TEXT_RUN_ID_SEPARATOR}${run}`;
|
|
4477
|
+
if (!this.semantics.has(id)) break;
|
|
4478
|
+
ids.push(id);
|
|
4479
|
+
}
|
|
4480
|
+
}
|
|
4481
|
+
for (let child = current.firstChild; child !== null; child = child.nextSibling) stack.push(child);
|
|
4482
|
+
}
|
|
4483
|
+
return ids;
|
|
4484
|
+
}
|
|
4485
|
+
/**
|
|
4486
|
+
* The mirrored nodes whose box differs from the one last sent, and
|
|
4487
|
+
* which are on screen.
|
|
4488
|
+
*
|
|
4489
|
+
* This runs on every frame that laid out, and `frameNeedsLayout`
|
|
4490
|
+
* counts a transform — so it runs on every scrolled frame, where
|
|
4491
|
+
* every box beneath the scroll container has moved. Whatever it
|
|
4492
|
+
* returns crosses to the shell and is written as four inline styles
|
|
4493
|
+
* per element, on the main thread, before the next paint. That is
|
|
4494
|
+
* the one per-frame cost this architecture puts back on the thread
|
|
4495
|
+
* it exists to keep free, and it was proportional to the whole
|
|
4496
|
+
* mounted tree.
|
|
4497
|
+
*
|
|
4498
|
+
* So it is bounded by the viewport instead. A node scrolled out of
|
|
4499
|
+
* sight keeps the last box the mirror was told about; there is
|
|
4500
|
+
* nothing on screen for it to be wrong about, and the sweep picks it
|
|
4501
|
+
* up again on the frame it comes back, because the box it is
|
|
4502
|
+
* compared against is still the stale one. The focused node is
|
|
4503
|
+
* always included whether or not it is on screen: the focus ring is
|
|
4504
|
+
* drawn from its rectangle, and focus moving to something off screen
|
|
4505
|
+
* is answered by `scrollIntoView`, whose own frame reports it.
|
|
4316
4506
|
*
|
|
4317
|
-
* Bounded by the semantics tree, which is bounded by the *mounted*
|
|
4318
|
-
* nodes — so a 100k-row list costs the fifteen rows it has mounted,
|
|
4319
|
-
* the same bound the semantics tree walk has.
|
|
4320
4507
|
* Ids that have left the tree are dropped here rather than tracked,
|
|
4321
4508
|
* since a removal patch has already told the mirror about them.
|
|
4322
4509
|
*/
|
|
4323
4510
|
collectSemanticsBoxes() {
|
|
4324
4511
|
const changed = [];
|
|
4512
|
+
const focused = this.focusManager.focusedNode?.id;
|
|
4325
4513
|
for (const id of this.semantics.keys()) {
|
|
4326
4514
|
const node = this.graph.getNode(id);
|
|
4327
4515
|
if (node === void 0 || this.engine.recordFor(node) === void 0) continue;
|
|
4328
4516
|
const box = this.engine.visibleBox(node);
|
|
4329
4517
|
const last = this.semanticsBoxes.get(id);
|
|
4330
4518
|
if (last !== void 0 && boxesEqual(last, box)) continue;
|
|
4519
|
+
if (id !== focused && !this.onScreen(box)) continue;
|
|
4331
4520
|
this.semanticsBoxes.set(id, box);
|
|
4332
4521
|
changed.push({
|
|
4333
4522
|
id,
|
|
@@ -4339,6 +4528,15 @@ var GessoRuntime = class {
|
|
|
4339
4528
|
}
|
|
4340
4529
|
return changed;
|
|
4341
4530
|
}
|
|
4531
|
+
/**
|
|
4532
|
+
* Whether a box in viewport coordinates overlaps the canvas at all.
|
|
4533
|
+
*
|
|
4534
|
+
* Generous by a margin, so that something a scroll is about to bring
|
|
4535
|
+
* in has its rectangle before it arrives rather than one frame after.
|
|
4536
|
+
*/
|
|
4537
|
+
onScreen(box) {
|
|
4538
|
+
return box.x < this.width + SEMANTICS_VIEWPORT_MARGIN && box.y < this.height + SEMANTICS_VIEWPORT_MARGIN && box.x + box.width > -SEMANTICS_VIEWPORT_MARGIN && box.y + box.height > -SEMANTICS_VIEWPORT_MARGIN;
|
|
4539
|
+
}
|
|
4342
4540
|
/** Scrolls every scroll container above `node` so a node-local box is visible. */
|
|
4343
4541
|
revealBox(node, box) {
|
|
4344
4542
|
for (const adjustment of this.engine.revealAdjustments(node, 0, box)) {
|
|
@@ -4508,7 +4706,10 @@ var GessoRuntime = class {
|
|
|
4508
4706
|
this.focusManager.settleScope();
|
|
4509
4707
|
const laidOut = frameNeedsLayout(frame);
|
|
4510
4708
|
this.phaseTimings.layout = this.timePhase(() => laidOut, () => this.engine.layoutForFrame(frame, this.constraints, root));
|
|
4511
|
-
if (laidOut)
|
|
4709
|
+
if (laidOut) {
|
|
4710
|
+
this.laidOutOnce = true;
|
|
4711
|
+
this.inspector.recordLayout(started);
|
|
4712
|
+
}
|
|
4512
4713
|
if (!this.layoutNotifier.isEmpty()) this.layoutNotifier.notify((node) => {
|
|
4513
4714
|
const record = this.engine.recordFor(node);
|
|
4514
4715
|
return {
|
|
@@ -4523,7 +4724,7 @@ var GessoRuntime = class {
|
|
|
4523
4724
|
}
|
|
4524
4725
|
this.sendEditingState();
|
|
4525
4726
|
const rebuildSemantics = frameNeedsSemantics(frame);
|
|
4526
|
-
this.phaseTimings.semantics = this.timePhase(() => rebuildSemantics || this.semanticsListener !== null && (laidOut || this.focusManager.focusedNode?.id !== this.lastFocusedId), () => this.updateSemantics(rebuildSemantics, laidOut));
|
|
4727
|
+
this.phaseTimings.semantics = this.timePhase(() => rebuildSemantics || this.semanticsListener !== null && (laidOut || this.focusManager.focusedNode?.id !== this.lastFocusedId), () => this.updateSemantics(frame, rebuildSemantics, laidOut));
|
|
4527
4728
|
if (this.renderer.backend === "webgpu" && this.renderer.isLost) this.fallBackToCanvas2D(this.renderer);
|
|
4528
4729
|
const overlay = this.inspector.hasOverlay ? this.inspector.overlay(started) : null;
|
|
4529
4730
|
this.gpuTimings = null;
|
|
@@ -4823,6 +5024,24 @@ function frameNeedsLayout(frame) {
|
|
|
4823
5024
|
* a closed dialog leaves the tree.
|
|
4824
5025
|
*/
|
|
4825
5026
|
/** Shared empties, so a frame that changed nothing allocates nothing. */
|
|
5027
|
+
/**
|
|
5028
|
+
* How many separate subtrees a scoped semantics update will walk
|
|
5029
|
+
* before it gives up and walks the whole tree once.
|
|
5030
|
+
*
|
|
5031
|
+
* A frame that re-meant a handful of nodes is the case this exists
|
|
5032
|
+
* for — a clock, a counter, a row whose label changed. A frame that
|
|
5033
|
+
* re-meant a hundred has almost certainly re-meant a shared ancestor's
|
|
5034
|
+
* worth of them, and the subtrees start to overlap, so one walk of
|
|
5035
|
+
* everything is both cheaper and simpler than many walks of parts.
|
|
5036
|
+
*/
|
|
5037
|
+
const SCOPED_SEMANTICS_OWNERS = 32;
|
|
5038
|
+
/**
|
|
5039
|
+
* How far outside the canvas a mirrored box is still worth reporting.
|
|
5040
|
+
*
|
|
5041
|
+
* One screenful of slack, so a fling that covers a lot of ground in
|
|
5042
|
+
* one frame still hands the mirror the rows it is about to show.
|
|
5043
|
+
*/
|
|
5044
|
+
const SEMANTICS_VIEWPORT_MARGIN = 400;
|
|
4826
5045
|
const EMPTY_PATCHES = [];
|
|
4827
5046
|
const EMPTY_BOXES = [];
|
|
4828
5047
|
function boxesEqual(a, b) {
|
|
@@ -6117,6 +6336,113 @@ function observeReducedMotion(onChange) {
|
|
|
6117
6336
|
return observeMediaQuery("(prefers-reduced-motion: reduce)", onChange);
|
|
6118
6337
|
}
|
|
6119
6338
|
//#endregion
|
|
6339
|
+
//#region src/app/fullscreen.ts
|
|
6340
|
+
/**
|
|
6341
|
+
* Enters or leaves fullscreen on an element, across the prefixes that
|
|
6342
|
+
* are still out there.
|
|
6343
|
+
*
|
|
6344
|
+
* Deliberately fire-and-forget. `requestFullscreen` returns a promise
|
|
6345
|
+
* that rejects when the browser refuses -- it only grants fullscreen
|
|
6346
|
+
* during a gesture -- and there is nothing useful to do about that
|
|
6347
|
+
* here: whether it worked is reported back by the `fullscreenchange`
|
|
6348
|
+
* event, which is also the only thing that hears about the person
|
|
6349
|
+
* pressing Escape.
|
|
6350
|
+
*/
|
|
6351
|
+
function setElementFullscreen(element, enter) {
|
|
6352
|
+
const document = documentOf(element);
|
|
6353
|
+
if (document === null) return;
|
|
6354
|
+
const anyDocument = document;
|
|
6355
|
+
if (enter) {
|
|
6356
|
+
const target = element;
|
|
6357
|
+
try {
|
|
6358
|
+
if (typeof target.requestFullscreen === "function") target.requestFullscreen().catch(() => {});
|
|
6359
|
+
else target.webkitRequestFullscreen?.();
|
|
6360
|
+
} catch {}
|
|
6361
|
+
return;
|
|
6362
|
+
}
|
|
6363
|
+
try {
|
|
6364
|
+
if (typeof document.exitFullscreen === "function") document.exitFullscreen().catch(() => {});
|
|
6365
|
+
else anyDocument.webkitExitFullscreen?.();
|
|
6366
|
+
} catch {}
|
|
6367
|
+
}
|
|
6368
|
+
/**
|
|
6369
|
+
* The document an element belongs to, or null where there is not one.
|
|
6370
|
+
*
|
|
6371
|
+
* A canvas double in a spec has no `ownerDocument`, and neither has an
|
|
6372
|
+
* `OffscreenCanvas`. Falling back to the ambient `document` covers the
|
|
6373
|
+
* first case where a real one exists, and answering null covers the
|
|
6374
|
+
* rest: fullscreen is a thing a page has, and somewhere without a page
|
|
6375
|
+
* should decline rather than throw.
|
|
6376
|
+
*/
|
|
6377
|
+
function documentOf(element) {
|
|
6378
|
+
const owner = element.ownerDocument ?? null;
|
|
6379
|
+
if (owner !== null && typeof owner.addEventListener === "function") return owner;
|
|
6380
|
+
const ambient = typeof globalThis.document === "undefined" ? null : globalThis.document;
|
|
6381
|
+
return ambient !== null && typeof ambient.addEventListener === "function" ? ambient : null;
|
|
6382
|
+
}
|
|
6383
|
+
/** Whether anything in the element's document is currently fullscreen. */
|
|
6384
|
+
function isDocumentFullscreen(element) {
|
|
6385
|
+
const document = documentOf(element);
|
|
6386
|
+
if (document === null) return false;
|
|
6387
|
+
return (document.fullscreenElement ?? document.webkitFullscreenElement ?? null) !== null;
|
|
6388
|
+
}
|
|
6389
|
+
/** Calls back whenever the document enters or leaves fullscreen. */
|
|
6390
|
+
function observeFullscreen(element, onChange) {
|
|
6391
|
+
const document = documentOf(element);
|
|
6392
|
+
if (document === null) return () => {};
|
|
6393
|
+
const report = () => onChange(isDocumentFullscreen(element));
|
|
6394
|
+
document.addEventListener("fullscreenchange", report);
|
|
6395
|
+
document.addEventListener("webkitfullscreenchange", report);
|
|
6396
|
+
return () => {
|
|
6397
|
+
document.removeEventListener("fullscreenchange", report);
|
|
6398
|
+
document.removeEventListener("webkitfullscreenchange", report);
|
|
6399
|
+
};
|
|
6400
|
+
}
|
|
6401
|
+
/**
|
|
6402
|
+
* The box an application should lay itself out in, given whether its
|
|
6403
|
+
* canvas is currently filling the screen.
|
|
6404
|
+
*
|
|
6405
|
+
* **A `ResizeObserver` on the host does not see this happen**, and
|
|
6406
|
+
* that is the whole reason this exists. The fullscreen API lifts the
|
|
6407
|
+
* *canvas* out of the page and stretches it to the screen; the host
|
|
6408
|
+
* around it keeps the size it always had, so the observer never fires,
|
|
6409
|
+
* the runtime keeps laying out at the old size, and the browser scales
|
|
6410
|
+
* the result up. The picture looks right, and every coordinate is
|
|
6411
|
+
* wrong by the ratio between the two: a press near the bottom of a
|
|
6412
|
+
* fullscreen clip lands somewhere near the middle of the layout.
|
|
6413
|
+
*
|
|
6414
|
+
* So the size is read from the canvas while it is fullscreen and from
|
|
6415
|
+
* the host when it is not. On the way *out* the canvas has not been
|
|
6416
|
+
* put back yet when the event fires, which is why the host is the
|
|
6417
|
+
* right answer there rather than simply always asking the canvas.
|
|
6418
|
+
*/
|
|
6419
|
+
function surfaceBox(canvas, host, active) {
|
|
6420
|
+
const box = (active ? canvas : host).getBoundingClientRect();
|
|
6421
|
+
return box.width > 0 && box.height > 0 ? {
|
|
6422
|
+
width: box.width,
|
|
6423
|
+
height: box.height
|
|
6424
|
+
} : null;
|
|
6425
|
+
}
|
|
6426
|
+
/**
|
|
6427
|
+
* Runs a callback once the browser has actually applied the new
|
|
6428
|
+
* geometry.
|
|
6429
|
+
*
|
|
6430
|
+
* `fullscreenchange` fires *before* the new size is in the layout, so
|
|
6431
|
+
* reading a box from inside it gives the size the element had a moment
|
|
6432
|
+
* ago. Measured here: entering fullscreen reported the canvas as its
|
|
6433
|
+
* old preview size, the surface stayed that size, and the browser
|
|
6434
|
+
* stretched it to the screen, which is precisely the thing
|
|
6435
|
+
* `surfaceBox` exists to prevent. Two frames, because the first is the
|
|
6436
|
+
* one the change lands on.
|
|
6437
|
+
*/
|
|
6438
|
+
function afterLayout(run) {
|
|
6439
|
+
if (typeof globalThis.requestAnimationFrame !== "function") {
|
|
6440
|
+
run();
|
|
6441
|
+
return;
|
|
6442
|
+
}
|
|
6443
|
+
globalThis.requestAnimationFrame(() => globalThis.requestAnimationFrame(run));
|
|
6444
|
+
}
|
|
6445
|
+
//#endregion
|
|
6120
6446
|
//#region src/app/shellHistory.ts
|
|
6121
6447
|
function createShellHistory(options = {}, host = typeof window === "undefined" ? void 0 : window) {
|
|
6122
6448
|
const mode = options.mode ?? (host === void 0 ? "memory" : "path");
|
|
@@ -6367,6 +6693,8 @@ var WorkerApp = class {
|
|
|
6367
6693
|
* what the cache costs.
|
|
6368
6694
|
*/
|
|
6369
6695
|
canvasOrigin = null;
|
|
6696
|
+
/** Whether the canvas is filling the screen; see the resize observer. */
|
|
6697
|
+
fullscreen = false;
|
|
6370
6698
|
/**
|
|
6371
6699
|
* The hover move being held for this frame, and the frame holding
|
|
6372
6700
|
* it. See `flushPendingMove`.
|
|
@@ -6758,6 +7086,10 @@ var WorkerApp = class {
|
|
|
6758
7086
|
openUrlWith(this.options.onOpenUrl, message.url);
|
|
6759
7087
|
return;
|
|
6760
7088
|
}
|
|
7089
|
+
if (message.type === "fullscreen") {
|
|
7090
|
+
if (this.canvas !== void 0) setElementFullscreen(this.canvas, message.enter);
|
|
7091
|
+
return;
|
|
7092
|
+
}
|
|
6761
7093
|
if (message.type === "popup") {
|
|
6762
7094
|
this.openPopup(message);
|
|
6763
7095
|
return;
|
|
@@ -6847,6 +7179,7 @@ var WorkerApp = class {
|
|
|
6847
7179
|
const entry = entries[0];
|
|
6848
7180
|
if (entry === void 0) return;
|
|
6849
7181
|
this.canvasOrigin = null;
|
|
7182
|
+
if (this.fullscreen) return;
|
|
6850
7183
|
const { width, height } = entry.contentRect;
|
|
6851
7184
|
if (width > 0 && height > 0) this.requestResize({
|
|
6852
7185
|
width,
|
|
@@ -7050,6 +7383,26 @@ var WorkerApp = class {
|
|
|
7050
7383
|
visible: document.visibilityState !== "hidden"
|
|
7051
7384
|
});
|
|
7052
7385
|
};
|
|
7386
|
+
const detachFullscreen = observeFullscreen(canvas, (active) => {
|
|
7387
|
+
this.canvasOrigin = null;
|
|
7388
|
+
this.fullscreen = active;
|
|
7389
|
+
this.post({
|
|
7390
|
+
type: "fullscreenChanged",
|
|
7391
|
+
active
|
|
7392
|
+
});
|
|
7393
|
+
afterLayout(() => {
|
|
7394
|
+
this.canvasOrigin = null;
|
|
7395
|
+
const box = this.host === void 0 ? null : surfaceBox(canvas, this.host, active);
|
|
7396
|
+
if (box !== null) this.requestResize({
|
|
7397
|
+
...box,
|
|
7398
|
+
dpr: window.devicePixelRatio || 1
|
|
7399
|
+
});
|
|
7400
|
+
});
|
|
7401
|
+
});
|
|
7402
|
+
this.post({
|
|
7403
|
+
type: "fullscreenChanged",
|
|
7404
|
+
active: isDocumentFullscreen(canvas)
|
|
7405
|
+
});
|
|
7053
7406
|
onVisibilityChange();
|
|
7054
7407
|
const detachReducedMotion = observeReducedMotion((reduced) => {
|
|
7055
7408
|
this.post({
|
|
@@ -7147,6 +7500,7 @@ var WorkerApp = class {
|
|
|
7147
7500
|
window.addEventListener("resize", onCanvasMayHaveMoved);
|
|
7148
7501
|
return () => {
|
|
7149
7502
|
detachReducedMotion();
|
|
7503
|
+
detachFullscreen();
|
|
7150
7504
|
canvas.removeEventListener("mousedown", onMouseDown);
|
|
7151
7505
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
7152
7506
|
canvas.removeEventListener("pointerdown", onPointerDown);
|
|
@@ -7258,6 +7612,8 @@ var GessoApp = class {
|
|
|
7258
7612
|
mirror = null;
|
|
7259
7613
|
history = null;
|
|
7260
7614
|
detachVisibility = null;
|
|
7615
|
+
detachFullscreen = null;
|
|
7616
|
+
fullscreen = false;
|
|
7261
7617
|
detachReducedMotion = null;
|
|
7262
7618
|
/** Stops watching `prefers-color-scheme`; null while overridden. */
|
|
7263
7619
|
detachColorScheme = null;
|
|
@@ -7421,6 +7777,8 @@ var GessoApp = class {
|
|
|
7421
7777
|
this.mirror = null;
|
|
7422
7778
|
this.detachVisibility?.();
|
|
7423
7779
|
this.detachVisibility = null;
|
|
7780
|
+
this.detachFullscreen?.();
|
|
7781
|
+
this.detachFullscreen = null;
|
|
7424
7782
|
this.detachReducedMotion?.();
|
|
7425
7783
|
this.detachReducedMotion = null;
|
|
7426
7784
|
this.detachColorScheme?.();
|
|
@@ -7462,6 +7820,15 @@ var GessoApp = class {
|
|
|
7462
7820
|
const onVisibility = () => this.runtime.setVisible(document.visibilityState !== "hidden");
|
|
7463
7821
|
document.addEventListener("visibilitychange", onVisibility);
|
|
7464
7822
|
this.detachVisibility = () => document.removeEventListener("visibilitychange", onVisibility);
|
|
7823
|
+
this.detachFullscreen = observeFullscreen(canvas, (active) => {
|
|
7824
|
+
this.fullscreen = active;
|
|
7825
|
+
this.runtime.setFullscreen(active);
|
|
7826
|
+
afterLayout(() => {
|
|
7827
|
+
const box = surfaceBox(canvas, this.host, active);
|
|
7828
|
+
if (box !== null) this.resize(box.width, box.height);
|
|
7829
|
+
});
|
|
7830
|
+
});
|
|
7831
|
+
this.runtime.setFullscreen(isDocumentFullscreen(canvas));
|
|
7465
7832
|
}
|
|
7466
7833
|
this.detachReducedMotion = observeReducedMotion((reduced) => this.runtime.setReducedMotion(reduced));
|
|
7467
7834
|
this.setColorScheme(this.colorSchemePreference);
|
|
@@ -7526,6 +7893,10 @@ var GessoApp = class {
|
|
|
7526
7893
|
writeClipboard(request.text, this.canvas.ownerDocument);
|
|
7527
7894
|
return;
|
|
7528
7895
|
}
|
|
7896
|
+
if (request.type === "fullscreen") {
|
|
7897
|
+
setElementFullscreen(this.canvas, request.enter);
|
|
7898
|
+
return;
|
|
7899
|
+
}
|
|
7529
7900
|
const view = this.canvas.ownerDocument.defaultView;
|
|
7530
7901
|
if (request.type === "storage") {
|
|
7531
7902
|
this.runtime.settleStorage(request.id, performShellStorage(request, () => view?.localStorage));
|
|
@@ -7549,6 +7920,7 @@ var GessoApp = class {
|
|
|
7549
7920
|
this.resizeObserver = new ResizeObserver((entries) => {
|
|
7550
7921
|
const entry = entries[0];
|
|
7551
7922
|
if (entry === void 0) return;
|
|
7923
|
+
if (this.fullscreen) return;
|
|
7552
7924
|
this.resize(entry.contentRect.width, entry.contentRect.height);
|
|
7553
7925
|
});
|
|
7554
7926
|
this.resizeObserver.observe(this.host);
|
|
@@ -7937,6 +8309,89 @@ var ShellStorage = class {
|
|
|
7937
8309
|
}
|
|
7938
8310
|
};
|
|
7939
8311
|
//#endregion
|
|
8312
|
+
//#region src/app/videoClock.ts
|
|
8313
|
+
/**
|
|
8314
|
+
* A clip's position, taken from the sound playing beside it.
|
|
8315
|
+
*
|
|
8316
|
+
* **This is the clock inversion, and it is worth being explicit about
|
|
8317
|
+
* why it exists.** Everywhere else in this framework the animation
|
|
8318
|
+
* driver owns time: a video is a pure function of a position and the
|
|
8319
|
+
* position comes from a tween, which is what lets a clip be scheduled,
|
|
8320
|
+
* paced and stopped by exactly the machinery every other animated
|
|
8321
|
+
* thing uses. That arrangement is correct right up until the clip has
|
|
8322
|
+
* sound, and then it is exactly backwards.
|
|
8323
|
+
*
|
|
8324
|
+
* The asymmetry is in what the two media can survive. Video drops
|
|
8325
|
+
* frames: an application that stalled for 50ms shows the picture it
|
|
8326
|
+
* should be showing now and throws away the ones it missed, and nobody
|
|
8327
|
+
* can tell. Audio cannot do either — a gap is audible, and resampling
|
|
8328
|
+
* to catch up changes the pitch — so the sound plays at its own rate
|
|
8329
|
+
* whatever else is happening, and anything that must agree with it has
|
|
8330
|
+
* to follow. Which means the picture follows the sound, and a tween
|
|
8331
|
+
* driving the picture independently would drift against it within
|
|
8332
|
+
* seconds. There is no arrangement in which both lead.
|
|
8333
|
+
*
|
|
8334
|
+
* **And the sound cannot be played here.** `AudioContext` does not
|
|
8335
|
+
* exist on a worker, which is where this framework decodes and draws.
|
|
8336
|
+
* So the sound is the shell's to play — `AudioService` already does
|
|
8337
|
+
* exactly that, reporting where it has got to about once a second and
|
|
8338
|
+
* extrapolating in between on the animation driver — and what crosses
|
|
8339
|
+
* the thread boundary is one number. That is the whole of this file:
|
|
8340
|
+
* `AudioService` is already the right shape, and this is the adapter
|
|
8341
|
+
* that lets `videoSource` read it.
|
|
8342
|
+
*
|
|
8343
|
+
* ```ts
|
|
8344
|
+
* // The same file, played twice: the shell for its sound, the worker
|
|
8345
|
+
* // for its pictures. A `<video>` element does this internally and
|
|
8346
|
+
* // calls it one thing.
|
|
8347
|
+
* audio.load('clip.mp4', { autoplay: false });
|
|
8348
|
+
* Video({ src: 'clip.mp4', clock: audioClock(audio, 'clip.mp4') });
|
|
8349
|
+
* ```
|
|
8350
|
+
*
|
|
8351
|
+
* `source` is checked on every read, and that check is not
|
|
8352
|
+
* decoration: `AudioService` is one playback for the whole
|
|
8353
|
+
* application, so a screen that starts a podcast while this clip is
|
|
8354
|
+
* still mounted would otherwise drive the picture from the podcast's
|
|
8355
|
+
* position. A clock whose source is no longer loaded reports that it
|
|
8356
|
+
* is not running and holds the position it last had, which shows a
|
|
8357
|
+
* still frame rather than a clip that has jumped somewhere absurd.
|
|
8358
|
+
*/
|
|
8359
|
+
function audioClock(audio, source) {
|
|
8360
|
+
let held = 0;
|
|
8361
|
+
let listeners = /* @__PURE__ */ new Set();
|
|
8362
|
+
let wasRunning = false;
|
|
8363
|
+
let subscription = null;
|
|
8364
|
+
const mine = () => audio.state.value.src === source;
|
|
8365
|
+
const running = () => mine() && audio.state.value.status === "playing";
|
|
8366
|
+
const announce = () => {
|
|
8367
|
+
const now = running();
|
|
8368
|
+
if (now === wasRunning) return;
|
|
8369
|
+
wasRunning = now;
|
|
8370
|
+
for (const listener of listeners) listener();
|
|
8371
|
+
};
|
|
8372
|
+
return {
|
|
8373
|
+
positionSeconds() {
|
|
8374
|
+
if (!mine()) return held;
|
|
8375
|
+
held = audio.state.value.position;
|
|
8376
|
+
return held;
|
|
8377
|
+
},
|
|
8378
|
+
get running() {
|
|
8379
|
+
return running();
|
|
8380
|
+
},
|
|
8381
|
+
onChange(listener) {
|
|
8382
|
+
listeners.add(listener);
|
|
8383
|
+
subscription ??= audio.state.subscribe(() => announce());
|
|
8384
|
+
return () => {
|
|
8385
|
+
listeners.delete(listener);
|
|
8386
|
+
if (listeners.size > 0) return;
|
|
8387
|
+
subscription?.unsubscribe();
|
|
8388
|
+
subscription = null;
|
|
8389
|
+
listeners = /* @__PURE__ */ new Set();
|
|
8390
|
+
};
|
|
8391
|
+
}
|
|
8392
|
+
};
|
|
8393
|
+
}
|
|
8394
|
+
//#endregion
|
|
7940
8395
|
//#region src/Presence.ts
|
|
7941
8396
|
const DEFAULT_EXIT_TIMEOUT_MS = 2e3;
|
|
7942
8397
|
function Presence(inputs, ctx) {
|
|
@@ -8518,6 +8973,9 @@ var RenderWorkerApp = class {
|
|
|
8518
8973
|
case "tick":
|
|
8519
8974
|
this.clock?.tick(message.time);
|
|
8520
8975
|
break;
|
|
8976
|
+
case "fullscreenChanged":
|
|
8977
|
+
runtime.setFullscreen(message.active);
|
|
8978
|
+
return;
|
|
8521
8979
|
case "visibility":
|
|
8522
8980
|
runtime.setVisible(message.visible);
|
|
8523
8981
|
break;
|
|
@@ -8652,6 +9110,10 @@ var RenderWorkerApp = class {
|
|
|
8652
9110
|
type: "openUrl",
|
|
8653
9111
|
url: request.url
|
|
8654
9112
|
});
|
|
9113
|
+
else if (request.type === "fullscreen") this.host.postMessage({
|
|
9114
|
+
type: "fullscreen",
|
|
9115
|
+
enter: request.enter
|
|
9116
|
+
});
|
|
8655
9117
|
else if (request.type === "popup") this.host.postMessage({
|
|
8656
9118
|
type: "popup",
|
|
8657
9119
|
id: request.id,
|
|
@@ -8715,6 +9177,6 @@ function locationOf(event) {
|
|
|
8715
9177
|
return `${event.filename}:${line}:${column}`;
|
|
8716
9178
|
}
|
|
8717
9179
|
//#endregion
|
|
8718
|
-
export { APPLICATION_WORKER, AnimationService, AudioService, AudioSink, BoundsCell, Channel, ChannelRegistry, ChannelReplica, Component, ComponentHost, ComponentHostResolver, ComputedCell, Define, Each, EditingProxy, FindService, FocusService, FontService, FrameService, GessoApp, GessoAppBuilder, GessoRuntime, IndexedDbStorage, Inject, Input, InputCell, InternalState, MARK_PREFIX, MediaService, MemoryStorage, OpfsStorage, Output, OverlayLayer, OverlayService, PersistedState, Presence, ProvidedChannel, RenderWorkerApp, Resource, RouteState, RouterOutlet, RouterService, SemanticsMirror, ServiceRegistry, ShellService, ShellStorage, Show, ThemeTokenCell, UI_FRAME_PHASES, UI_ROLES, UI_SEMANTIC_STATES, UndoStack, WorkerApp, applyPatch, applyPatches, bind, bounds, buildPath, channel, classifyStorageError, computed, controlled, createApp, createChannelRegistry, createComponent, createShellHistory, debounced, defineChannel, derive, describeStream, diffProjection, each, findUnplainPath, formatAge, formatNodePath, formatNodeReport, formatStream, formatUrl, input, internalState, into, isChannelClientMessage, isChannelHostMessage, isClassComponent, isComponentElement, isHubMessage, isOutputTarget, isPortErrorMessage, isPortHandshake, markInstant, markNow, measureSpan, mutate, observeColorScheme, observeMediaQuery, observeReducedMotion, output, parseUrl, performShellStorage, performanceMarksEnabled, persisted, pick, pickKeys, portHandle, printPropValue, provide, registerUndoShortcuts, renderRoot, requirePlainData, resource, route, select, serve, serveChannels, servePorts, setPerformanceMarks, shellStorageDenied, show, storageErrorMessage, storageReadFailure, storageReadValue, structurallyEqual, themeTokenCell, throttled, to, treeText, undoable, viewKeys, workerHandle, writeClipboard };
|
|
9180
|
+
export { APPLICATION_WORKER, AnimationService, AudioService, AudioSink, BoundsCell, Channel, ChannelRegistry, ChannelReplica, Component, ComponentHost, ComponentHostResolver, ComputedCell, Define, Each, EditingProxy, FindService, FocusService, FontService, FrameService, GessoApp, GessoAppBuilder, GessoRuntime, IndexedDbStorage, Inject, Input, InputCell, InternalState, MARK_PREFIX, MediaService, MemoryStorage, OpfsStorage, Output, OverlayLayer, OverlayService, PersistedState, Presence, ProvidedChannel, RenderWorkerApp, Resource, RouteState, RouterOutlet, RouterService, SemanticsMirror, ServiceRegistry, ShellService, ShellStorage, Show, ThemeTokenCell, UI_FRAME_PHASES, UI_ROLES, UI_SEMANTIC_STATES, UndoStack, WorkerApp, applyPatch, applyPatches, audioClock, bind, bounds, buildPath, channel, classifyStorageError, computed, controlled, createApp, createChannelRegistry, createComponent, createShellHistory, debounced, defineChannel, derive, describeStream, diffProjection, each, findUnplainPath, formatAge, formatNodePath, formatNodeReport, formatStream, formatUrl, input, internalState, into, isChannelClientMessage, isChannelHostMessage, isClassComponent, isComponentElement, isHubMessage, isOutputTarget, isPortErrorMessage, isPortHandshake, markInstant, markNow, measureSpan, mutate, observeColorScheme, observeMediaQuery, observeReducedMotion, output, parseUrl, performShellStorage, performanceMarksEnabled, persisted, pick, pickKeys, portHandle, printPropValue, provide, registerUndoShortcuts, renderRoot, requirePlainData, resource, route, select, serve, serveChannels, servePorts, setPerformanceMarks, shellStorageDenied, show, storageErrorMessage, storageReadFailure, storageReadValue, structurallyEqual, themeTokenCell, throttled, to, treeText, undoable, viewKeys, workerHandle, writeClipboard };
|
|
8719
9181
|
|
|
8720
9182
|
//# sourceMappingURL=index.js.map
|