gesso-framework 0.4.2 → 0.5.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.
@@ -1,6 +1,8 @@
1
- import { C as CommandMap, I as ReadableCell, N as InputCell, P as OutputCell, S as Command, U as Component, V as InternalState, a as ComponentType, f as ChannelPort, h as Patch, i as ComponentProps, l as ChannelReplica, n as ComponentArgs, r as ComponentContext, s as Inputs, x as ChannelToken } from "./FunctionComponent-CgwLKE5d.js";
1
+ import { f as ChannelToken, m as CommandMap, o as Patch, p as Command, r as ChannelPort } from "./ChannelProtocol-ByNoHujM.js";
2
+ import { E as WorkerHandle, s as AgentConfirmation, t as UiHost, y as ChannelSource } from "./ui-U39HjNFA.js";
3
+ import { S as InternalState, _ as ReadableCell, a as ComponentType, h as OutputCell, i as ComponentProps, l as ChannelReplica, m as InputCell, n as ComponentArgs, r as ComponentContext, s as Inputs, w as Component } from "./FunctionComponent-fYMdePtH.js";
2
4
  import { BehaviorSubject, Observable, Subscription } from "rxjs";
3
- import { AnimatedCell, AnimationDriver, CanvasHost, CaretRect, ComponentLikeElement, ComponentResolver, EditingState, EditingState as EditingState$1, IconRasterizer, ImageResolver, LayoutExplanation, LayoutInspector, MARK_PREFIX, MotionStateInput, MotionTiming, RendererBackend, Size, TextMeasureRequest, TextMeasurer, UI_ROLES, UI_SEMANTIC_STATES, UiAnimation, UiChild, UiDurationToken, UiEasing, UiEasingToken, UiEditingController, UiElement, UiFileDropMessage, UiFindController, UiFocusManager, UiFrameClockFactory, UiInputDispatcher, UiInsets, UiKeyModifiers, UiKeyboardController, UiLength, UiModifier, UiMotion, UiNode, UiPlatformAdapter, UiPointerController, UiPointerDevice, UiReducedMotionPolicy, UiRole, UiScrollability, UiSelectionController, UiSemanticState, UiSemanticsAction, UiSemanticsMap, UiSemanticsMap as UiSemanticsMap$1, UiSemanticsPatch, UiSemanticsRecord, UiSemanticsRecord as UiSemanticsRecord$1, UiSemanticsUpdate, UiShortcutRegistry, UiSpringSpec, UiSpringToken, UiThemeExtension, UiTouchScroller, UiWheelController, VideoClock, VideoResolver, markInstant, markNow, measureSpan, performanceMarksEnabled, setPerformanceMarks as setPerformanceMarks$1 } from "gesso-core";
5
+ import { AnimatedCell, AnimationDriver, CanvasHost, CaretRect, ComponentLikeElement, ComponentResolver, EditingState, EditingState as EditingState$1, FocusOptions, IconRasterizer, ImageResolver, LayoutExplanation, LayoutInspector, MARK_PREFIX, MotionStateInput, MotionTiming, Reactive, RendererBackend, Size, TextMeasureRequest, TextMeasurer, UI_ROLES, UI_SEMANTIC_STATES, UiAnimation, UiChild, UiContrast, UiDurationToken, UiEasing, UiEasingToken, UiEditingController, UiElement, UiFileDropMessage, UiFindController, UiFocusManager, UiFrameClockFactory, UiInputDispatcher, UiInsets, UiKeyModifiers, UiKeyboardController, UiLength, UiModifier, UiMotion, UiNode, UiPlatformAdapter, UiPointerController, UiPointerDevice, UiReducedMotionPolicy, UiRole, UiScrollability, UiSelectionController, UiSemanticState, UiSemanticsAction, UiSemanticsMap, UiSemanticsMap as UiSemanticsMap$1, UiSemanticsPatch, UiSemanticsRecord, UiSemanticsRecord as UiSemanticsRecord$1, UiSemanticsUpdate, UiShortcutRegistry, UiSpringSpec, UiSpringToken, UiTextPosition, UiThemeExtension, UiTouchScroller, UiWheelController, VideoClock, VideoResolver, markInstant, markNow, measureSpan, performanceMarksEnabled, setPerformanceMarks as setPerformanceMarks$1 } from "gesso-core";
4
6
  //#region src/service/ServiceRegistry.d.ts
5
7
  /**
6
8
  * The runtime services a component may inject.
@@ -947,49 +949,6 @@ declare function Channel(token: {
947
949
  name: string;
948
950
  }): PropertyDecorator;
949
951
  //#endregion
950
- //#region src/channel/provide.d.ts
951
- /** What the owning thread supplies for a channel. */
952
- interface ChannelSource<View extends object, Commands extends object> {
953
- /** One observable per declared view key. */
954
- view: { readonly [K in keyof View]: Observable<View[K]>; };
955
- /** One handler per declared command. */
956
- commands?: Commands;
957
- }
958
- /**
959
- * Publishes a channel from the thread that owns its data.
960
- *
961
- * Each view key is subscribed, diffed against what the other side last
962
- * saw, and sent as patches. Whatever produced the observable — a bare
963
- * subject or a stack of layers — stays here; only plain data crosses.
964
- *
965
- * Keys are subscribed on the first sync request, so a channel nobody
966
- * is watching costs nothing.
967
- */
968
- declare function provide<View extends object, Commands extends object>(token: ChannelToken<View, Commands>, source: ChannelSource<View, Commands>, port: ChannelPort): ProvidedChannel;
969
- declare class ProvidedChannel {
970
- private readonly token;
971
- private readonly source;
972
- private readonly port;
973
- private readonly subscriptions;
974
- /**
975
- * What the other side is known to hold, seeded from the token's
976
- * initial value — which the replica also starts from, so an app
977
- * whose first emission equals the initial sends nothing at all.
978
- */
979
- private readonly previous;
980
- private readonly checked;
981
- private synced;
982
- constructor(token: ChannelToken<object, CommandMap>, source: ChannelSource<object, CommandMap>, port: ChannelPort);
983
- private receive;
984
- private runCommand;
985
- private sync;
986
- private publish;
987
- /** Re-sends every key in full, for a client that reattached. */
988
- private resend;
989
- private post;
990
- dispose(): void;
991
- }
992
- //#endregion
993
952
  //#region src/channel/ChannelRegistry.d.ts
994
953
  /**
995
954
  * The channels a runtime can hand to its components, by name.
@@ -1040,154 +999,6 @@ declare function findUnplainPath(value: unknown, path?: readonly (string | numbe
1040
999
  */
1041
1000
  declare function requirePlainData(channelName: string, key: string, value: unknown): void;
1042
1001
  //#endregion
1043
- //#region src/worker/WorkerPorts.d.ts
1044
- /**
1045
- * Named `MessagePort`s into a worker.
1046
- *
1047
- * A worker's global `onmessage` is a single channel, so a worker that
1048
- * receives messages on it can host exactly one conversation. That is
1049
- * why a store in a data worker used to mean a worker per store: the
1050
- * client claimed the `Worker` object itself, and a second one had
1051
- * nowhere to go.
1052
- *
1053
- * A handshake fixes it. The client opens a `MessageChannel`, keeps one
1054
- * end and transfers the other with a name; the worker serves that name
1055
- * and the two ends talk privately from then on. The global channel is
1056
- * used once per conversation and carries nothing else.
1057
- *
1058
- * Nothing here knows what travels over a port. It is the transport the
1059
- * store replication in `../store/worker` runs on today and the barrier
1060
- * contract will run on next.
1061
- */
1062
- /** A port-shaped thing: `MessagePort` and `Worker` both satisfy it. */
1063
- interface MessageEndpoint {
1064
- postMessage(message: unknown): void;
1065
- onmessage: ((event: {
1066
- data: unknown;
1067
- }) => void) | null;
1068
- }
1069
- /** The one message the global channel carries. */
1070
- interface PortHandshake {
1071
- type: 'gesso:port';
1072
- key: string;
1073
- }
1074
- declare function isPortHandshake(value: unknown): value is PortHandshake;
1075
- /**
1076
- * A worker spawned at most once, serving any number of named ports.
1077
- *
1078
- * Handed to several `useChannel` calls, it is what lets one worker
1079
- * hold a whole application layer instead of one channel. Spawning is
1080
- * deferred to the first `open`, so a handle nobody uses costs nothing.
1081
- */
1082
- interface WorkerHandle {
1083
- /**
1084
- * Opens a private channel under `key`, spawning the worker if this
1085
- * is the first one.
1086
- */
1087
- open(key: string): MessagePort;
1088
- /** Whether the worker has been spawned. */
1089
- readonly spawned: boolean;
1090
- /** Stops the worker, if it was ever started. */
1091
- terminate(): void;
1092
- }
1093
- /**
1094
- * Stands for "whichever worker the shell spawned for the application".
1095
- *
1096
- * A registration inside the render worker cannot name that worker: it
1097
- * is created by the shell and its port only arrives with `init`, long
1098
- * after `useChannel` and `useService` have run. This sentinel is what a
1099
- * registration puts there instead, and the render worker swaps it for
1100
- * the real handle once the port shows up.
1101
- *
1102
- * Opening a port on it before then is a bug rather than a race, so it
1103
- * says so.
1104
- */
1105
- declare const APPLICATION_WORKER: WorkerHandle;
1106
- /**
1107
- * Anything a handshake can be posted to with a port attached.
1108
- * `Worker` and `MessagePort` both satisfy it.
1109
- */
1110
- interface TransferTarget {
1111
- postMessage(message: unknown, transfer: Transferable[]): void;
1112
- }
1113
- /**
1114
- * A handle over an endpoint someone else owns.
1115
- *
1116
- * The shell spawns the application worker and hands the render worker
1117
- * one end of a channel to it; this is what the render worker opens
1118
- * named ports over. `terminate` is a no-op — the lifetime belongs to
1119
- * whoever created the endpoint, and a handle that could kill a worker
1120
- * it did not spawn would be a surprising thing to hand out.
1121
- */
1122
- declare function portHandle(endpoint: TransferTarget): WorkerHandle;
1123
- /**
1124
- * Routes handshakes arriving on a transferred port through the same
1125
- * handlers as the worker's own global channel.
1126
- *
1127
- * The shell owns the application worker and gives the render worker a
1128
- * port to it, so handshakes reach this worker two ways: on its global
1129
- * channel (whoever spawned it) and on that port (whoever was given
1130
- * it). Both should be served by the same handlers, and neither end
1131
- * should have to know which route a channel came in on.
1132
- */
1133
- interface HubMessage {
1134
- type: 'gesso:hub';
1135
- }
1136
- declare function isHubMessage(value: unknown): value is HubMessage;
1137
- /**
1138
- * Wraps a worker factory so the worker is created once and shared.
1139
- *
1140
- * A factory rather than a URL for the same reason the render worker
1141
- * takes one: a bundler only emits a chunk for a worker it can see
1142
- * constructed literally in the calling module.
1143
- *
1144
- * const data = workerHandle(
1145
- * () => new Worker(new URL('./data.worker.ts', import.meta.url), { type: 'module' })
1146
- * );
1147
- */
1148
- declare function workerHandle(factory: () => Worker): WorkerHandle;
1149
- /**
1150
- * Minimal view of a worker's global scope, so this module type-checks
1151
- * against the DOM lib without pulling in the WebWorker lib.
1152
- */
1153
- interface PortHost {
1154
- onmessage: ((event: {
1155
- data: unknown;
1156
- ports?: readonly MessagePort[];
1157
- }) => void) | null;
1158
- }
1159
- /**
1160
- * What a port is answered with when no handler claimed its name.
1161
- *
1162
- * Its own message type rather than a store's or a channel's, because
1163
- * the transport does not know which of them the client is: both
1164
- * recognise it, so a mismatched name is loud either way.
1165
- */
1166
- interface PortErrorMessage {
1167
- type: 'port:error';
1168
- message: string;
1169
- }
1170
- declare function isPortErrorMessage(value: unknown): value is PortErrorMessage;
1171
- /**
1172
- * Serves named ports inside a worker.
1173
- *
1174
- * Call it synchronously at the top level of the worker module, before
1175
- * any await, so no handshake is missed.
1176
- *
1177
- * `onPort` returns whether it took the port. Returning false passes
1178
- * the handshake to whatever was serving before, which is what lets two
1179
- * kinds of thing — stores and channels, during the migration — share
1180
- * one worker: each answers for its own names and declines the rest.
1181
- * When nobody accepts, the port is answered with an error naming
1182
- * everything the worker does serve, because a handshake that silently
1183
- * matched nothing leaves the client waiting forever with nothing said.
1184
- *
1185
- * `names` is only read to build that message.
1186
- *
1187
- * Returns a function that stops serving.
1188
- */
1189
- declare function servePorts(onPort: (key: string, port: MessagePort) => boolean, names: () => readonly string[], host?: PortHost): () => void;
1190
- //#endregion
1191
1002
  //#region src/channel/createChannelRegistry.d.ts
1192
1003
  /**
1193
1004
  * A registration with its types erased.
@@ -1227,6 +1038,12 @@ interface ChannelRegistration {
1227
1038
  }
1228
1039
  interface ChannelRegistryHandle {
1229
1040
  registry: ChannelRegistry;
1041
+ /**
1042
+ * The workers serving this registry's channels, so a thread can reach
1043
+ * them for something other than a channel: an agent asking what each
1044
+ * one serves.
1045
+ */
1046
+ readonly workers: ReadonlySet<WorkerHandle>;
1230
1047
  dispose(): void;
1231
1048
  }
1232
1049
  /**
@@ -1234,64 +1051,6 @@ interface ChannelRegistryHandle {
1234
1051
  */
1235
1052
  declare function createChannelRegistry(registrations: readonly ChannelRegistration[], onError?: (channelName: string, message: string, stack?: string) => void): ChannelRegistryHandle;
1236
1053
  //#endregion
1237
- //#region src/channel/serveChannels.d.ts
1238
- /**
1239
- * One channel a worker offers: its token and what feeds it.
1240
- *
1241
- * Types erased structurally, for the same reason `ChannelRegistration`
1242
- * erases them — a list of channels has no single generic
1243
- * instantiation, and making every caller cast to reach one is worse
1244
- * than describing what is actually needed.
1245
- */
1246
- interface ServedChannel {
1247
- token: {
1248
- name: string;
1249
- initial: object;
1250
- };
1251
- source: {
1252
- view: Record<string, Observable<unknown>>;
1253
- commands?: Record<string, Command>;
1254
- };
1255
- }
1256
- /**
1257
- * One served channel, with its source checked against its token.
1258
- *
1259
- * `ServedChannel` is erased on purpose, so one list can hold channels
1260
- * of every shape; the cost is that a view key the token declares and
1261
- * the source forgets is found at startup, by the error `provide`
1262
- * reports, rather than by the compiler. This is the typed seam: the
1263
- * source must hold an Observable for every key of the token's view and
1264
- * a handler for every command, and each handler takes the arguments
1265
- * the token declares, so none of them needs an annotation.
1266
- *
1267
- * serveChannels([
1268
- * serve(Catalog, { view: catalog, commands: { add: name => catalog.add(name) } })
1269
- * ]);
1270
- *
1271
- * The view may be any object with the right observables on it, which
1272
- * is often the domain object itself when its properties are named
1273
- * after the keys. Only the declared keys are read from it.
1274
- */
1275
- declare function serve<View extends object, Commands extends object>(token: ChannelToken<View, Commands>, source: ChannelSource<View, Commands>): ServedChannel;
1276
- /**
1277
- * Publishes channels from an application worker.
1278
- *
1279
- * Call it synchronously at the top level of the worker module, before
1280
- * any await, so no handshake is missed:
1281
- *
1282
- * const catalog = new CatalogViewModel(new CatalogDomain(new OpfsStore()));
1283
- * serveChannels([
1284
- * serve(Catalog, { view: { products: catalog.products$ }, commands: { … } })
1285
- * ]);
1286
- *
1287
- * Everything above this call is the application's own — plain classes,
1288
- * plain observables, no framework import. This function is the entire
1289
- * seam between it and the view.
1290
- *
1291
- * Returns a function that stops serving and disposes what it provided.
1292
- */
1293
- declare function serveChannels(channels: readonly ServedChannel[], host?: PortHost): () => void;
1294
- //#endregion
1295
1054
  //#region src/channel/pick.d.ts
1296
1055
  /**
1297
1056
  * One key of a view model, as its own Observable, emitting only when
@@ -1356,6 +1115,13 @@ declare function createComponent<C extends ComponentType>(component: C, ...args:
1356
1115
  //#endregion
1357
1116
  //#region src/overlay/OverlayService.d.ts
1358
1117
  type OverlayPlacement = 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end' | 'right' | 'right-start' | 'right-end';
1118
+ /** A rectangle inside an anchor, from its border box's top left. */
1119
+ interface OverlayRect {
1120
+ readonly x: number;
1121
+ readonly y: number;
1122
+ readonly width: number;
1123
+ readonly height: number;
1124
+ }
1359
1125
  /**
1360
1126
  * One thing floating above the app: a menu, a tooltip, a dialog.
1361
1127
  *
@@ -1371,6 +1137,15 @@ interface OverlayEntry {
1371
1137
  readonly id: string;
1372
1138
  readonly content: UiChild;
1373
1139
  readonly anchor?: UiNode | null;
1140
+ /**
1141
+ * The part of `anchor` to open beside, in the anchor's own
1142
+ * coordinates: a character in a field, from
1143
+ * `EditingService.caretRectOf(field, offset)`. The entry follows the
1144
+ * anchor as it would without it, through scrolling and layout. It can
1145
+ * be a stream, so a list under a word being typed moves with the word
1146
+ * when it wraps to the next line, without being opened again.
1147
+ */
1148
+ readonly anchorRect?: Reactive<OverlayRect | undefined>;
1374
1149
  /** Default 'bottom'. */
1375
1150
  readonly placement?: OverlayPlacement;
1376
1151
  /** Gap between content and anchor. */
@@ -1861,6 +1636,7 @@ declare function observeColorScheme(onChange: (scheme: ColorScheme) => void): ()
1861
1636
  */
1862
1637
  type ShellRequest = {
1863
1638
  type: 'clipboard';
1639
+ id: number;
1864
1640
  text: string;
1865
1641
  } | {
1866
1642
  type: 'openUrl';
@@ -2027,6 +1803,7 @@ interface ShellStorageResult {
2027
1803
  declare class ShellService {
2028
1804
  private handler;
2029
1805
  private readonly scheme;
1806
+ private readonly contrastState;
2030
1807
  private readonly insets;
2031
1808
  private readonly isFullscreen;
2032
1809
  /** Popups asked for and not yet answered, by the id sent with each. */
@@ -2035,6 +1812,9 @@ declare class ShellService {
2035
1812
  /** Storage requests asked for and not yet answered, by the id sent with each. */
2036
1813
  private readonly stores;
2037
1814
  private nextStorageId;
1815
+ /** Clipboard writes asked for and not yet answered, by the id sent with each. */
1816
+ private readonly copies;
1817
+ private nextCopyId;
2038
1818
  /** File requests asked for and not yet answered, by the id sent with each. */
2039
1819
  private readonly files;
2040
1820
  private nextFileId;
@@ -2067,6 +1847,18 @@ declare class ShellService {
2067
1847
  * read it beside a channel's view; its setter stays private here.
2068
1848
  */
2069
1849
  readonly colorScheme: ReadableCell<ColorScheme>;
1850
+ /**
1851
+ * The contrast the platform is asking for: `high` when the person has
1852
+ * turned up contrast or turned on a contrast theme, `standard`
1853
+ * otherwise. Reported by the shell like `colorScheme`, and as with it,
1854
+ * what it means is the application's: `withContrast(theme, contrast)`
1855
+ * is the theme that answers it.
1856
+ *
1857
+ * const theme = combineLatest([shell.colorScheme, shell.contrast]).pipe(
1858
+ * map(([scheme, contrast]) => withContrast(scheme === 'dark' ? darkTheme : lightTheme, contrast))
1859
+ * );
1860
+ */
1861
+ readonly contrast: ReadableCell<UiContrast>;
2070
1862
  /** The current appearance, for code that needs it without subscribing. */
2071
1863
  get currentColorScheme(): ColorScheme;
2072
1864
  /**
@@ -2098,6 +1890,8 @@ declare class ShellService {
2098
1890
  * answer, and `colorScheme` is how an application hears about it.
2099
1891
  */
2100
1892
  applyColorScheme(scheme: ColorScheme): void;
1893
+ /** Called by the runtime when the shell reports the contrast; not for applications. */
1894
+ applyContrast(contrast: UiContrast): void;
2101
1895
  /**
2102
1896
  * Called by the runtime when the shell reports the platform's insets.
2103
1897
  *
@@ -2106,8 +1900,27 @@ declare class ShellService {
2106
1900
  * scroll event that moved no edge does not wake every subscriber.
2107
1901
  */
2108
1902
  applyViewportInsets(insets: UiInsets): void;
2109
- /** Puts text on the system clipboard. */
2110
- copyText(text: string): void;
1903
+ /**
1904
+ * Puts text on the system clipboard, and answers whether it got there.
1905
+ *
1906
+ * Most callers ignore the answer, and may: the text is on its way the
1907
+ * moment this returns. It is for an application that tells the person
1908
+ * what happened, a "Copied" toast after a menu command, say, which
1909
+ * would be a lie on the occasions the browser refused. It does refuse:
1910
+ * the clipboard wants a focused document, and some browsers a fresh
1911
+ * gesture, and a key pressed in a render worker reaches the window's
1912
+ * clipboard a message later than it reached the canvas.
1913
+ *
1914
+ * With no shell installed the answer is false, as `openPopup`'s is,
1915
+ * rather than a promise that never settles.
1916
+ */
1917
+ copyText(text: string): Promise<boolean>;
1918
+ /**
1919
+ * Called by the runtime when the shell reports whether a clipboard
1920
+ * write landed. Not for applications. An unknown id is ignored, on
1921
+ * `settlePopup`'s terms.
1922
+ */
1923
+ settleClipboard(id: number, copied: boolean): void;
2111
1924
  /** Opens a URL in the user's browser, in a new tab or window. */
2112
1925
  openUrl(url: string): void;
2113
1926
  /**
@@ -3481,7 +3294,20 @@ declare class GessoRuntime {
3481
3294
  private readonly sharedElements;
3482
3295
  private readonly focusNotifier;
3483
3296
  private readonly environmentNotifier;
3297
+ /**
3298
+ * The semantics tree: every record by id, and each record's children
3299
+ * in order.
3300
+ *
3301
+ * A record's own `index` is only kept current for the records that
3302
+ * are sent; the order is `semanticsChildren`. Renumbering every
3303
+ * record after an insertion cost a pass over the whole tree on every
3304
+ * structural change, for indices nothing would read until a record
3305
+ * was next sent or the tree was asked for (`semanticsTree`).
3306
+ */
3484
3307
  private semantics;
3308
+ private semanticsChildren;
3309
+ /** The tree in document order with every index current, built when asked for. */
3310
+ private semanticsOrdered;
3485
3311
  private semanticsListener;
3486
3312
  /**
3487
3313
  * The box last reported for each mirrored node, so a frame that
@@ -3489,6 +3315,8 @@ declare class GessoRuntime {
3489
3315
  * them. Only populated while a listener is attached.
3490
3316
  */
3491
3317
  private semanticsBoxes;
3318
+ /** What each semantics walk leaves for the next; see `SemanticsMemory`. */
3319
+ private readonly semanticsMemory;
3492
3320
  private lastFocusedId;
3493
3321
  /**
3494
3322
  * Where the caret was when `reload` replaced the tree, put back on
@@ -3502,6 +3330,14 @@ declare class GessoRuntime {
3502
3330
  private focusAfterReload;
3503
3331
  /** Whether `focusAfterReload` is waiting to be applied. */
3504
3332
  private restoringFocus;
3333
+ /**
3334
+ * Reveals asked for while the layout listeners run, kept until the
3335
+ * frame's boxes have settled; null outside `settleLayout`, where a
3336
+ * reveal is applied at once.
3337
+ */
3338
+ private deferredReveals;
3339
+ /** Whether a frame has run out of layout passes and been warned about; see `MAX_LAYOUT_PASSES`. */
3340
+ private warnedLayoutPasses;
3505
3341
  /** A frame changed semantics while nothing was listening; see `semanticsTree`. */
3506
3342
  private semanticsStale;
3507
3343
  private lastEditingState;
@@ -3800,6 +3636,8 @@ declare class GessoRuntime {
3800
3636
  * dark should look like.
3801
3637
  */
3802
3638
  setColorScheme(scheme: ColorScheme): void;
3639
+ /** The contrast the platform asks for, passed straight to `ShellService`; see `ShellService.contrast`. */
3640
+ setContrast(contrast: UiContrast): void;
3803
3641
  /**
3804
3642
  * The platform's own insets, as the shell reports them: the safe area
3805
3643
  * under a notch or a home indicator and the strip a soft keyboard
@@ -3844,6 +3682,11 @@ declare class GessoRuntime {
3844
3682
  * preference setters beside it this carries the id it is replying to.
3845
3683
  */
3846
3684
  settlePopup(id: number, opened: boolean): void;
3685
+ /**
3686
+ * Reports whether a clipboard write landed, settling the promise
3687
+ * `ShellService.copyText` returned.
3688
+ */
3689
+ settleClipboard(id: number, copied: boolean): void;
3847
3690
  /**
3848
3691
  * Reports what the shell found in `localStorage`, settling the
3849
3692
  * promise `ShellService.requestStorage` returned.
@@ -3939,6 +3782,11 @@ declare class GessoRuntime {
3939
3782
  * Scrolls every scroll container above `node` just enough that the
3940
3783
  * node is inside its viewport, `padding` pixels from the nearest edge.
3941
3784
  * Nothing moves when it is already visible.
3785
+ *
3786
+ * Asked for from a layout listener — `autoFocus` taking focus is the
3787
+ * usual one — it waits until the frame's layout has settled, so it
3788
+ * reveals where the node ends up rather than where the first pass
3789
+ * put it (see `settleLayout`).
3942
3790
  */
3943
3791
  scrollIntoView(node: UiNode, padding?: number): void;
3944
3792
  /**
@@ -4028,6 +3876,12 @@ declare class GessoRuntime {
4028
3876
  * boxes at all.
4029
3877
  */
4030
3878
  onSemantics(listener: ((update: UiSemanticsUpdate) => void) | null): void;
3879
+ /**
3880
+ * The id of the node that holds focus, or null. The same id the
3881
+ * semantics tree keys its records by, so a reader of the tree can
3882
+ * say which control a key press would reach.
3883
+ */
3884
+ focusedNodeId(): string | null;
4031
3885
  /**
4032
3886
  * The semantics tree as of the last frame that changed it.
4033
3887
  *
@@ -4036,6 +3890,17 @@ declare class GessoRuntime {
4036
3890
  * every frame having paid to keep one nothing was reading.
4037
3891
  */
4038
3892
  semanticsTree(): UiSemanticsMap;
3893
+ /** Replaces the tree with one built in full, which is in document order. */
3894
+ private storeSemantics;
3895
+ /**
3896
+ * The tree in document order, every index current: a walk down
3897
+ * `semanticsChildren`, done when someone asks rather than per frame.
3898
+ * Records whose index had gone out of date are brought up to date in
3899
+ * the store as well.
3900
+ */
3901
+ private orderedSemantics;
3902
+ /** A record's index among its siblings now, which its own `index` may not say. */
3903
+ private semanticsIndexOf;
4039
3904
  /**
4040
3905
  * Something an assistive technology did to a mirrored element,
4041
3906
  * turned back into ordinary input.
@@ -4125,6 +3990,28 @@ declare class GessoRuntime {
4125
3990
  * decides how much of the tree has to be asked.
4126
3991
  */
4127
3992
  private rescopeSemantics;
3993
+ /**
3994
+ * The patches for a frame that changed the shape of the tree, without
3995
+ * walking all of it, or null when the whole tree has to be rebuilt.
3996
+ *
3997
+ * Any frame that added or removed a child used to rebuild the tree
3998
+ * from the root, describing every node again. In a 5,000-line editor
3999
+ * that was 11 ms of every Enter, for one new paragraph. Now the walk
4000
+ * starts at the nearest record above each change, as
4001
+ * `rescopeSemantics` does for a change of meaning, and inside it a
4002
+ * subtree nothing touched keeps its records: renumbered if its
4003
+ * siblings moved, never described again (see
4004
+ * `rebuildSemanticsSubtree`). What is described is the path down to
4005
+ * each change, whatever is new, and everything under a node whose
4006
+ * own meaning changed.
4007
+ *
4008
+ * The result is spliced into `this.semantics` in place, since the map
4009
+ * is in document order and a record's subtree is a contiguous run of
4010
+ * it, so adds still arrive in document order. Removals come first.
4011
+ */
4012
+ private restructureSemantics;
4013
+ /** Whether a node is still in the tree being laid out. */
4014
+ private attached;
4128
4015
  /**
4129
4016
  * The nearest node at or above `node` that holds a semantics record,
4130
4017
  * or null when nothing above it does.
@@ -4167,6 +4054,15 @@ declare class GessoRuntime {
4167
4054
  *
4168
4055
  * Ids that have left the tree are dropped here rather than tracked,
4169
4056
  * since a removal patch has already told the mirror about them.
4057
+ *
4058
+ * **Found by walking what is on screen, not by checking everything.**
4059
+ * Bounding what was sent still computed every node's box to find out
4060
+ * whether it was on screen: a 5,000-line document has three thousand
4061
+ * fields, and the sweep cost 4 to 24 ms of every keystroke. The walk
4062
+ * goes down from the root carrying the scroll and sticky offsets that
4063
+ * `visibleBox` adds up per node, and passes over any subtree whose
4064
+ * bounds (the hit tester's, see `subtreeBoundsFor`) are off screen.
4065
+ * A node it passes over is one this skipped before anyway.
4170
4066
  */
4171
4067
  private collectSemanticsBoxes;
4172
4068
  /**
@@ -4240,6 +4136,58 @@ declare class GessoRuntime {
4240
4136
  private collectVirtualMeasures;
4241
4137
  /** A node's outer extent along the list's axis. */
4242
4138
  private extentOf;
4139
+ /**
4140
+ * Tells the layout listeners what moved, and lays out again for as
4141
+ * long as what they do in answer needs it, so the frame paints the
4142
+ * layout they settle on rather than the one they were told about.
4143
+ *
4144
+ * The browser's answer to the same problem. A `ResizeObserver`
4145
+ * callback runs after layout and before paint, and when it changes
4146
+ * layout the browser lays out again before it paints rather than
4147
+ * showing the stale boxes for a frame. The listeners here are
4148
+ * `breakpoint`, `sizeContainer` (and so `Responsive`),
4149
+ * `scrollPosition`, `autoFocus` and anything else on `host.onLayout`.
4150
+ * Before this a page whose breakpoint gave it wide padding was
4151
+ * painted with its narrow padding on the frame it appeared, and
4152
+ * jumped 16 px on the next.
4153
+ *
4154
+ * A pass after the first lays out only what the listeners dirtied,
4155
+ * the same incremental pass any frame runs, and then tells only the
4156
+ * listeners whose boxes it changed. A frame whose listeners wrote
4157
+ * nothing that lays out, which is almost every frame, runs no second
4158
+ * pass: it pays one look at the dirty set.
4159
+ *
4160
+ * **Bounded.** Listeners that keep moving each other's boxes would
4161
+ * otherwise never let the frame paint. ResizeObserver bounds its loop
4162
+ * by tree depth; this one is bounded by count, `MAX_LAYOUT_PASSES` in
4163
+ * all, which is easier to reason about and more than a real chain
4164
+ * needs (a breakpoint inside a `Responsive` inside a `Responsive` is
4165
+ * four passes). Past it the frame paints what it has, the rest waits
4166
+ * for the next frame as it always used to, and a warning says so
4167
+ * once, as the browser's "ResizeObserver loop completed with
4168
+ * undelivered notifications" does.
4169
+ *
4170
+ * **Reveals wait for the end.** `autoFocus` takes focus from a layout
4171
+ * listener, on its node's first layout, and focus reveals the node:
4172
+ * revealed from the first pass's boxes, it scrolled to where the node
4173
+ * was before a breakpoint moved it. A reveal asked for while the
4174
+ * listeners run is applied once they are quiet, from final boxes, and
4175
+ * its scroll laid out like any other write. So is the focus a hot
4176
+ * reload restores, after the listeners rather than before because
4177
+ * `autoFocus` is one of them and the restore has to be the last word:
4178
+ * every node in a subtree a reload replaced has its first layout on
4179
+ * this frame.
4180
+ */
4181
+ private settleLayout;
4182
+ /**
4183
+ * Whether something written since the frame was collected has to be
4184
+ * laid out before the frame paints: the same flags that make a frame
4185
+ * lay out, or an inherited value still to be handed down.
4186
+ */
4187
+ private layoutPending;
4188
+ /** Applies what waits for settled boxes: a reload's focus, then the reveals asked for. */
4189
+ private finishSettling;
4190
+ private warnLayoutPasses;
4243
4191
  private handleFrame;
4244
4192
  /**
4245
4193
  * Keeps frames coming while something is animating.
@@ -4348,6 +4296,14 @@ interface FrameMetrics {
4348
4296
  measured: number;
4349
4297
  /** Relayout boundaries the layout phase started from; 0 when it ran from the root or not at all. */
4350
4298
  relayoutRoots: number;
4299
+ /**
4300
+ * Times the frame laid out: 0 when it laid nothing out, 1 usually,
4301
+ * more when a layout listener (a `breakpoint`, a `sizeContainer`, an
4302
+ * `autoFocus`'s reveal) changed what the first pass laid out and the
4303
+ * frame laid it out again before painting. `measured` and
4304
+ * `relayoutRoots` count every pass.
4305
+ */
4306
+ layoutPasses: number;
4351
4307
  /** Milliseconds per phase. A phase with no work reports 0. */
4352
4308
  phases: FramePhaseTimings;
4353
4309
  /** The backend that drew this frame, or `pending` while WebGPU initialises. */
@@ -4538,9 +4494,12 @@ type ShellToRuntimeMessage = {
4538
4494
  type: 'compositionEnd';
4539
4495
  text: string;
4540
4496
  at?: number;
4541
- } | {
4497
+ } |
4498
+ /** `html` is the clipboard's HTML, when it held some. */
4499
+ {
4542
4500
  type: 'paste';
4543
4501
  text: string;
4502
+ html?: string;
4544
4503
  at?: number;
4545
4504
  } |
4546
4505
  /** The editing proxy lost focus to something outside the app. */
@@ -4589,6 +4548,9 @@ type ShellToRuntimeMessage = {
4589
4548
  {
4590
4549
  type: 'colorScheme';
4591
4550
  scheme: ColorScheme;
4551
+ } | {
4552
+ type: 'contrast';
4553
+ contrast: UiContrast;
4592
4554
  } |
4593
4555
  /**
4594
4556
  * What the window's own chrome is covering on each edge: the safe
@@ -4639,6 +4601,16 @@ type ShellToRuntimeMessage = {
4639
4601
  id: number;
4640
4602
  opened: boolean;
4641
4603
  } |
4604
+ /**
4605
+ * Whether a `clipboard` request's text reached the clipboard, under
4606
+ * the request's `id`. False when the browser refused both ways of
4607
+ * writing it.
4608
+ */
4609
+ {
4610
+ type: 'clipboardResult';
4611
+ id: number;
4612
+ copied: boolean;
4613
+ } |
4642
4614
  /**
4643
4615
  * What the shell found in `localStorage` for a `storage` request
4644
4616
  * (ShellStorage). The second reply on this protocol, and it carries
@@ -4775,6 +4747,7 @@ type RuntimeToShellMessage = {
4775
4747
  nodes: number;
4776
4748
  measured: number;
4777
4749
  relayoutRoots: number;
4750
+ layoutPasses: number;
4778
4751
  at: number;
4779
4752
  inputLatencyMs: number | null;
4780
4753
  phases: FramePhaseTimings;
@@ -4828,9 +4801,13 @@ type RuntimeToShellMessage = {
4828
4801
  type: 'editing';
4829
4802
  state: EditingState | null;
4830
4803
  } |
4831
- /** Put text on the clipboard (ShellService.copyText). */
4804
+ /**
4805
+ * Put text on the clipboard (ShellService.copyText). `id` pairs it
4806
+ * with the `clipboardResult` that comes back, once.
4807
+ */
4832
4808
  {
4833
4809
  type: 'clipboard';
4810
+ id: number;
4834
4811
  text: string;
4835
4812
  } |
4836
4813
  /** Open a URL in a new tab (ShellService.openUrl). */
@@ -5388,6 +5365,30 @@ interface WorkerAppOptions {
5388
5365
  * reach. `gesso-electrobun`'s bridge is what goes here.
5389
5366
  */
5390
5367
  onOpenUrl?: (url: string) => void;
5368
+ /**
5369
+ * Offer the application's channels to an AI agent in the browser,
5370
+ * through WebMCP (default false). Each channel's view and commands
5371
+ * become tools registered with `document.modelContext` once the app
5372
+ * mounts, removed when it is disposed. A browser without WebMCP
5373
+ * registers nothing. Pass `{ confirm }` to ask the person about a
5374
+ * `@confirm` command with the application's own dialog instead of
5375
+ * the browser's. `gesso-framework/agent` has the rest.
5376
+ */
5377
+ webmcp?: boolean | {
5378
+ confirm?: (request: AgentConfirmation) => boolean | Promise<boolean>;
5379
+ };
5380
+ /**
5381
+ * The app is the page (default false): a key pressed while nothing
5382
+ * on the page has focus goes to the app, and the canvas takes focus.
5383
+ *
5384
+ * Keys reach the app through the canvas, which has focus only once
5385
+ * something put it there. A page that is all app loads with focus on
5386
+ * the body, so its shortcuts did nothing until the first click, and a
5387
+ * person who pressed `c` or Mod+K straight away got nothing. An app
5388
+ * embedded in a page with other things on it leaves this off: a key
5389
+ * pressed on that page isn't its.
5390
+ */
5391
+ pageKeys?: boolean;
5391
5392
  /**
5392
5393
  * Receives errors thrown inside the render worker: while handling a
5393
5394
  * message, uncaught during a frame, from the renderer, or from a
@@ -5554,7 +5555,16 @@ declare class WorkerApp {
5554
5555
  * uses this; its own view of the application is nothing at all.
5555
5556
  */
5556
5557
  get appLogic(): WorkerHandle | undefined;
5558
+ /**
5559
+ * Opens a port to whatever the render worker serves under `key`, or
5560
+ * returns undefined before `mount` has started it. The development
5561
+ * agent bridge asks for `gesso:agent` this way; nothing else in the
5562
+ * shell talks to the render worker except through its protocol.
5563
+ */
5564
+ openRenderPort(key: string): MessagePort | undefined;
5557
5565
  mount(host: HTMLElement | string): () => void;
5566
+ /** Removes the WebMCP tools `webmcp` registered, if it did. */
5567
+ private disconnectWebMcp;
5558
5568
  /**
5559
5569
  * An error the browser raised *at the worker object*, which is not
5560
5570
  * the same thing as the worker reporting one.
@@ -5828,6 +5838,10 @@ interface CreateAppOptions extends Omit<WorkerAppOptions, 'renderWorker'> {
5828
5838
  declare function createApp(options?: CreateAppOptions): WorkerApp;
5829
5839
  //#endregion
5830
5840
  //#region src/app/GessoAppBuilder.d.ts
5841
+ /** What `useWebMcp` takes besides a boolean: the app's own way to ask the person. */
5842
+ interface WebMcpChoice {
5843
+ confirm?: (request: AgentConfirmation) => boolean | Promise<boolean>;
5844
+ }
5831
5845
  /**
5832
5846
  * Fluent builder for the single-thread configuration.
5833
5847
  */
@@ -5845,6 +5859,10 @@ declare class GessoAppBuilder {
5845
5859
  private mediaOptions;
5846
5860
  private fontDeclarations;
5847
5861
  private app;
5862
+ /** The mounted app's channel registry, for the workers an agent port asks. */
5863
+ private channelHandle;
5864
+ private webmcpChoice;
5865
+ private disconnectWebMcp;
5848
5866
  private colorSchemePreference;
5849
5867
  constructor(root: FrameworkChild | ComponentType);
5850
5868
  /**
@@ -5964,6 +5982,25 @@ declare class GessoAppBuilder {
5964
5982
  * Returns a dispose function that tears the app down.
5965
5983
  */
5966
5984
  mountSync(host: HTMLElement | string): () => void;
5985
+ /**
5986
+ * Offer the app's channels and screen to an AI agent in the browser,
5987
+ * through WebMCP (default false). The single-thread form of
5988
+ * `createApp({ webmcp })`: registered once `mountSync` has run,
5989
+ * removed when the app is unmounted. Call before `mountSync`.
5990
+ */
5991
+ useWebMcp(choice?: boolean | WebMcpChoice): this;
5992
+ /**
5993
+ * Opens a port to what this app serves under `key`, or returns
5994
+ * undefined before `mountSync`.
5995
+ *
5996
+ * The same question `WorkerApp.openRenderPort` answers, asked of the
5997
+ * page instead of a render worker, because in this configuration the
5998
+ * page is the thread that draws. It serves one thing, `gesso:agent`:
5999
+ * the channels fed here, the workers behind them, and the screen.
6000
+ * The agent code is loaded the first time one is opened.
6001
+ */
6002
+ openRenderPort(key: string): MessagePort | undefined;
6003
+ private connectWebMcp;
5967
6004
  }
5968
6005
  //#endregion
5969
6006
  //#region src/app/createSyncApp.d.ts
@@ -6065,6 +6102,14 @@ interface GessoAppOptions {
6065
6102
  */
6066
6103
  declare class GessoApp {
6067
6104
  private readonly runtime;
6105
+ /**
6106
+ * The clock the runtime was given, its callback, and whether a frame
6107
+ * is waiting on it: what `uiHost().flush` needs to run that frame now,
6108
+ * since a background tab gets no animation frames to run it.
6109
+ */
6110
+ private clock;
6111
+ private frameCallback;
6112
+ private framePending;
6068
6113
  private readonly canvas;
6069
6114
  private readonly host;
6070
6115
  private readonly inputEnabled;
@@ -6085,6 +6130,7 @@ declare class GessoApp {
6085
6130
  private detachFullscreen;
6086
6131
  private fullscreen;
6087
6132
  private detachReducedMotion;
6133
+ private detachContrast;
6088
6134
  /** Stops watching `prefers-color-scheme`; null while overridden. */
6089
6135
  private detachColorScheme;
6090
6136
  /** Stops watching `visualViewport` for the safe area and the keyboard. */
@@ -6092,6 +6138,12 @@ declare class GessoApp {
6092
6138
  /** The appearance this shell reports; watched or overridden. */
6093
6139
  private colorSchemePreference;
6094
6140
  constructor(options: GessoAppOptions);
6141
+ /**
6142
+ * The running app, as the agent's screen tools need it: its semantics
6143
+ * tree and focus, the mirror's actions, keys, and a way to run a
6144
+ * pending frame now. See `uiSurface` in `gesso-framework/agent`.
6145
+ */
6146
+ uiHost(): UiHost;
6095
6147
  /** The runtime services a component in this app can inject. */
6096
6148
  get services(): ServiceRegistry;
6097
6149
  /**
@@ -7492,12 +7544,53 @@ declare class EditingService {
7492
7544
  * scroll already applied: a popup placed under the caret adds the
7493
7545
  * node's position on screen and nothing else.
7494
7546
  *
7547
+ * `offset` asks about a caret at another character than the one the
7548
+ * caret is at: the start of the word being completed, so its list
7549
+ * stays put as the word grows. With an overlay's `anchorRect` and the
7550
+ * field as its anchor, the list follows the field from then on.
7551
+ *
7495
7552
  * Null when the node is not an editable, when it has not been laid
7496
7553
  * out yet, or before the runtime has wired the controller — all
7497
7554
  * three of which are "ask again next frame" rather than errors, and
7498
7555
  * all three of which happen during the frame a field first appears.
7499
7556
  */
7500
- caretRectOf(node: UiNode | null): CaretRect | null;
7557
+ caretRectOf(node: UiNode | null, offset?: number): CaretRect | null;
7558
+ /**
7559
+ * Selects from `anchor` to `focus` and focuses the field the focus is
7560
+ * in: within one field, or across the fields of an editing group (see
7561
+ * `UiEditingGroup`). What an editor does after a command over a
7562
+ * selection (making it bold, say) to leave it selected, since its
7563
+ * fields can only select their own text.
7564
+ *
7565
+ * False when the two ends aren't editables of one group, or before
7566
+ * the runtime has wired the controller.
7567
+ */
7568
+ select(anchor: UiTextPosition, focus: UiTextPosition): boolean;
7569
+ }
7570
+ //#endregion
7571
+ //#region src/app/ScrollService.d.ts
7572
+ /**
7573
+ * Scrolling a node into view, for a component that moves a highlight
7574
+ * rather than focus.
7575
+ *
7576
+ * Focus moved from the keyboard already brings its node into view. A
7577
+ * highlight doesn't move focus: a combobox's arrows walk its list while
7578
+ * the caret stays in the field, and a grid's cursor can do the same.
7579
+ * The list has to follow the highlight all the same, and only the
7580
+ * runtime knows where the scroll containers above a node are and how
7581
+ * far each has to move. This is the asking.
7582
+ */
7583
+ declare class ScrollService {
7584
+ private scroller;
7585
+ /** Installed by the runtime; without one nothing scrolls. */
7586
+ setScroller(scroller: ((node: UiNode, padding: number) => void) | null): void;
7587
+ /**
7588
+ * Scrolls every container above `node` just enough that it's inside
7589
+ * the container's viewport, `padding` pixels from the nearest edge.
7590
+ * Nothing moves when it's visible already. Before the node has been
7591
+ * laid out there is nowhere to scroll it to, and nothing happens.
7592
+ */
7593
+ scrollIntoView(node: UiNode, padding?: number): void;
7501
7594
  }
7502
7595
  //#endregion
7503
7596
  //#region src/app/FocusService.d.ts
@@ -7525,14 +7618,28 @@ declare class FocusService {
7525
7618
  readonly focused: InternalState<UiNode | null>;
7526
7619
  /** Whether focus is confined to a subtree by an open trap. */
7527
7620
  readonly trapped: InternalState<boolean>;
7621
+ /**
7622
+ * Whether the focus held is focus the keyboard can see: reached by Tab
7623
+ * or an arrow key, or by code with no pointer since, rather than by a
7624
+ * press. CSS's `:focus-visible`, for something other than a ring that
7625
+ * should answer the keyboard and not the click that happened to focus
7626
+ * the same control: a tooltip, say.
7627
+ */
7628
+ readonly focusVisible: InternalState<boolean>;
7528
7629
  private manager;
7529
7630
  private detach;
7530
7631
  /** Actions taken before the runtime installed a manager, in order. */
7531
7632
  private queued;
7532
7633
  /** Installed by the runtime; without one every action is queued. */
7533
7634
  setManager(manager: UiFocusManager | null): void;
7534
- /** Gives the node keyboard focus. Non-focusable nodes are ignored. */
7535
- focus(node: UiNode): void;
7635
+ /**
7636
+ * Gives the node keyboard focus. Non-focusable nodes are ignored.
7637
+ *
7638
+ * The node is scrolled into view, unless `options.preventScroll` asks
7639
+ * for the page to stay where it is, as `element.focus({ preventScroll:
7640
+ * true })` does in a browser.
7641
+ */
7642
+ focus(node: UiNode, options?: FocusOptions): void;
7536
7643
  /** Drops focus without moving it anywhere. */
7537
7644
  blur(): void;
7538
7645
  /** Moves focus to the next focusable node, wrapping around. */
@@ -7565,7 +7672,8 @@ interface EditingProxySink {
7565
7672
  compositionStart(): void;
7566
7673
  compositionUpdate(text: string, caret: number): void;
7567
7674
  compositionEnd(text: string): void;
7568
- paste(text: string): void;
7675
+ /** Pasted text, and the clipboard's HTML when it held some. */
7676
+ paste(text: string, html: string | null): void;
7569
7677
  /** The proxy lost focus to something outside the app. */
7570
7678
  blur(): void;
7571
7679
  /**
@@ -7677,7 +7785,7 @@ declare class EditingProxy {
7677
7785
  * the reason the field's semantics live here rather than on a second
7678
7786
  * element beside it.
7679
7787
  */
7680
- describe(record: UiSemanticsRecord | null): void;
7788
+ describe(record: UiSemanticsRecord | null, activeDescendant?: string, controls?: string): void;
7681
7789
  dispose(): void;
7682
7790
  /** Puts the element where the caret is, so the IME window opens there. */
7683
7791
  private position;
@@ -7686,11 +7794,12 @@ declare class EditingProxy {
7686
7794
  private listen;
7687
7795
  }
7688
7796
  /**
7689
- * Writes text to the system clipboard from the main thread. The async
7690
- * API needs a secure context and, in some browsers, a recent user
7691
- * gesture; the `execCommand` fallback covers the rest.
7797
+ * Writes text to the system clipboard from the main thread, and answers
7798
+ * whether it got there. The async API needs a secure context and, in
7799
+ * some browsers, a recent user gesture; the `execCommand` fallback
7800
+ * covers the rest. False means both refused. It never rejects.
7692
7801
  */
7693
- declare function writeClipboard(text: string, doc?: Document): void;
7802
+ declare function writeClipboard(text: string, doc?: Document): Promise<boolean>;
7694
7803
  //#endregion
7695
7804
  //#region src/app/SemanticsMirror.d.ts
7696
7805
  /**
@@ -7722,7 +7831,7 @@ interface SemanticsMirrorSink {
7722
7831
  * nothing at all and the text is dropped before the application
7723
7832
  * sees it.
7724
7833
  */
7725
- paste?(text: string): void;
7834
+ paste?(text: string, html: string | null): void;
7726
7835
  }
7727
7836
  /**
7728
7837
  * The editing proxy, as the mirror needs it.
@@ -7736,8 +7845,13 @@ interface SemanticsMirrorSink {
7736
7845
  interface EditingMirrorTarget {
7737
7846
  /** True while the proxy holds DOM focus for a focused editable. */
7738
7847
  readonly active: boolean;
7739
- /** Describes the focused editable on the proxy's element, or clears it. */
7740
- describe(record: UiSemanticsRecord | null): void;
7848
+ /**
7849
+ * Describes the focused editable on the proxy's element, or clears it.
7850
+ * `activeDescendant` and `controls` are the DOM ids of the elements
7851
+ * its record's `activeDescendant` and `controls` name, for
7852
+ * `aria-activedescendant` and `aria-controls`.
7853
+ */
7854
+ describe(record: UiSemanticsRecord | null, activeDescendant?: string, controls?: string): void;
7741
7855
  /** Takes DOM focus back for the focused editable. */
7742
7856
  focus(): void;
7743
7857
  }
@@ -7786,6 +7900,12 @@ declare class SemanticsMirror {
7786
7900
  private applying;
7787
7901
  private focusedId;
7788
7902
  private disposed;
7903
+ /**
7904
+ * Prefixes every element's DOM id, which `aria-activedescendant`
7905
+ * refers to. Per mirror, because two apps on one page have nodes with
7906
+ * the same ids.
7907
+ */
7908
+ private readonly idPrefix;
7789
7909
  constructor(canvas: HTMLCanvasElement, sink: SemanticsMirrorSink, editing?: EditingMirrorTarget | null);
7790
7910
  /** The container, for tests and for a shell that wants to inspect it. */
7791
7911
  get element(): HTMLElement;
@@ -7799,6 +7919,8 @@ declare class SemanticsMirror {
7799
7919
  apply(update: UiSemanticsUpdate): void;
7800
7920
  dispose(): void;
7801
7921
  private upsert;
7922
+ /** Hands the proxy the focused editable's record, with the DOM ids of its active descendant and what it controls. */
7923
+ private describeEditing;
7802
7924
  private createElement;
7803
7925
  /** Writes a record onto its element as ARIA, clearing what it no longer says. */
7804
7926
  private describe;
@@ -8067,6 +8189,15 @@ declare class RenderWorkerApp {
8067
8189
  * console is the worker global's, and this class is what owns the
8068
8190
  * global.
8069
8191
  */
8192
+ /**
8193
+ * Answers an agent port with every channel this application can
8194
+ * reach: the ones fed from this thread, and whatever each worker
8195
+ * behind them serves, asked over a port of its own. Imported rather
8196
+ * than loaded on demand: a worker built as an IIFE, which is Vite's
8197
+ * default, cannot split off a chunk, and a dynamic import here failed
8198
+ * every such build. Nothing runs until an agent asks.
8199
+ */
8200
+ private serveAgent;
8070
8201
  private setConsoleForwarding;
8071
8202
  private dispatch;
8072
8203
  /**
@@ -8080,5 +8211,5 @@ declare class RenderWorkerApp {
8080
8211
  private initialize;
8081
8212
  }
8082
8213
  //#endregion
8083
- export { StorageOutcome as $, UiPropReport as $n, themeTokenCell as $r, FontFamilyDeclaration as $t, PresenceProps as A, Equality as Ai, AnimateOptions as An, PortHost as Ar, ChannelErrorEntry as At, PersistedState as B, ShellRequest as Bn, ChannelRegistry as Br, RuntimeErrorSource as Bt, FocusService as C, FanOutOptions as Ci, AudioAction as Cn, serveChannels as Cr, WorkerAppOptions as Ct, observeMediaQuery as D, ReadSource as Di, AudioService as Dn, APPLICATION_WORKER as Dr, createShellHistory as Dt, FindService as E, ComputedOptions as Ei, AudioSample as En, createChannelRegistry as Er, ShellHistoryOptions as Et, AudioSinkOutput as F, ShellFile as Fn, portHandle as Fr, FrameEntry as Ft, IndexedDbStorageOptions as G, ColorSchemePreference as Gn, Define as Gr, GessoRuntime as Gt, ShellStorage as H, ShellStorageOp as Hn, ProvidedChannel as Hr, ShellToRuntimeMessage as Ht, MediaSessionLike as I, ShellFileRequest as In, servePorts as Ir, PatchEntry as It, OpfsStorage as J, NodePathTarget as Jn, Output as Jr, RuntimeInput as Jt, OpfsDirectory as K, observeColorScheme as Kn, Inject as Kr, GessoRuntimeOptions as Kt, audioClock as L, ShellFileResult as Ln, workerHandle as Lr, UiTreeNode as Lt, AudioElementLike as M, ServiceRegistry as Mi, SpringOptions as Mn, isHubMessage as Mr, ConsoleEntry as Mt, AudioSink as N, UiDuration as Nn, isPortErrorMessage as Nr, DevtoolsEvent as Nt, observeReducedMotion as O, computed as Oi, AudioState as On, MessageEndpoint as Or, ActionCause as Ot, AudioSinkOptions as P, UiEasingChoice as Pn, isPortHandshake as Pr, DevtoolsRequest as Pt, StorageAdapter as Q, UiPropOrigin as Qn, ThemeTokenCell as Qr, FontFaceLike as Qt, FrameService as R, ShellFileType as Rn, findUnplainPath as Rr, UiTreeSnapshot as Rt, writeClipboard as S, FanOut as Si, parseUrl as Sn, serve as Sr, WorkerApp as St, TextService as T, ComputedCell as Ti, AudioRequest as Tn, ChannelRegistryHandle as Tr, ShellHistoryMode as Tt, ShellStorageOptions as U, ShellStorageResult as Un, provide as Ur, FrameMetrics as Ut, persisted as V, ShellService as Vn, ChannelSource as Vr, RuntimeToShellMessage as Vt, IndexedDbStorage as W, ColorScheme as Wn, Channel as Wr, FramePhaseTimings as Wt, OpfsWritable as X, UiNodeReport as Xn, ControlledValue as Xr, UiFramePhase as Xt, OpfsStorageOptions as Y, UiEnvironmentReport as Yn, ControlledOptions as Yr, UI_FRAME_PHASES as Yt, MemoryStorage as Z, UiOwnerReport as Zn, controlled as Zr, FontFaceDeclaration as Zt, EditingMirrorTarget as _, resource as _i, route as _n, isComponentElement as _r, createSyncApp as _t, UiRole as a, EachKey as ai, RouteAnswer as an, formatNodeReport as ar, UndoShortcutOptions as at, EditingProxy as b, FanCell as bi, buildPath as bn, pickKeys as br, createApp as bt, UiSemanticsPatch as c, debounced as ci, RouterRoutes as cn, ComponentHostResolver as cr, undoable as ct, markNow as d, Mutation as di, OutletProps as dn, OverlayEntry as dr, UndoTransaction as dt, bind as ei, FontFamilyStatus as en, UiSemanticsReport as er, StorageRead as et, measureSpan as f, mutate as fi, RouteContext as fn, OverlayPlacement as fr, ShellLocalStore as ft, renderRoot as g, ResourceStatus as gi, RouteTarget as gn, FrameworkChild as gr, GessoAppOptions as gt, RenderWorkerApp as h, ResourceState as hi, RouteOptions as hn, ComponentElement as hr, GessoApp as ht, UI_SEMANTIC_STATES as i, Each as ii, MediaService as in, formatNodePath as ir, storageReadValue as it, RouterOutlet as j, derive as ji, AnimationService as jn, WorkerHandle as jr, CommandEntry as jt, Presence as k, DeriveOptions as ki, AudioStatus as kn, PortHandshake as kr, ActionEntry as kt, UiSemanticsRecord$1 as l, throttled as li, RouterService as ln, ComponentHost as lr, UndoStack as lt, setPerformanceMarks$1 as m, ResourceOptions as mi, RouteGuard as mn, createComponent as mr, shellStorageDenied as mt, MARK_PREFIX as n, ShowProps as ni, FontService as nn, describeStream as nr, storageErrorMessage as nt, UiSemanticState as o, EachProps as oi, RouteMatch as on, formatStream as or, registerUndoShortcuts as ot, performanceMarksEnabled as p, Resource as pi, RouteDefinition as pn, OverlayService as pr, performShellStorage as pt, OpfsFileHandle as q, BoundStream as qn, Input as qr, RendererChoice as qt, UI_ROLES as r, show as ri, MediaOptions as rn, formatAge as rr, storageReadFailure as rt, UiSemanticsMap$1 as s, each as si, RouterHistorySink as sn, printPropValue as sr, UndoableOptions as st, EditingState$1 as t, Show as ti, FontHost as tn, UiStreamReport as tr, classifyStorageError as tt, markInstant as u, MutateOptions as ui, RouteState as un, OverlayLayer as ur, UndoStackOptions as ut, SemanticsMirror as v, SelectOptions as vi, to as vn, structurallyEqual as vr, GessoAppBuilder as vt, EditingService as w, fanOut as wi, AudioMetadata as wn, ChannelRegistration as wr, ShellHistory as wt, EditingProxySink as x, FanKey as xi, formatUrl as xn, ServedChannel as xr, AppLogicEndpoint as xt, SemanticsMirrorSink as y, select as yi, RouteParams as yn, pick as yr, CreateAppOptions as yt, PersistedOptions as z, ShellRecentFile as zn, requirePlainData as zr, treeText as zt };
8084
- //# sourceMappingURL=index-C9FAI_Kt.d.ts.map
8214
+ export { StorageAdapter as $, UiOwnerReport as $n, Resource as $r, FontFaceDeclaration as $t, Presence as A, AudioState as An, Channel as Ar, ActionCause as At, PersistedOptions as B, ShellFileType as Bn, bind as Br, UiTreeSnapshot as Bt, FocusService as C, formatUrl as Cn, pickKeys as Cr, AppLogicEndpoint as Ct, FindService as D, AudioRequest as Dn, findUnplainPath as Dr, ShellHistoryMode as Dt, TextService as E, AudioMetadata as En, createChannelRegistry as Er, ShellHistory as Et, AudioSinkOptions as F, UiDuration as Fn, ControlledOptions as Fr, DevtoolsEvent as Ft, IndexedDbStorage as G, ShellStorageResult as Gn, EachKey as Gr, FrameMetrics as Gt, persisted as H, ShellRequest as Hn, ShowProps as Hr, RuntimeErrorSource as Ht, AudioSinkOutput as I, UiEasingChoice as In, ControlledValue as Ir, DevtoolsRequest as It, OpfsFileHandle as J, observeColorScheme as Jn, debounced as Jr, GessoRuntimeOptions as Jt, IndexedDbStorageOptions as K, ColorScheme as Kn, EachProps as Kr, FramePhaseTimings as Kt, MediaSessionLike as L, ShellFile as Ln, controlled as Lr, FrameEntry as Lt, RouterOutlet as M, AnimateOptions as Mn, Inject as Mr, ChannelErrorEntry as Mt, AudioElementLike as N, AnimationService as Nn, Input as Nr, CommandEntry as Nt, observeMediaQuery as O, AudioSample as On, requirePlainData as Or, ShellHistoryOptions as Ot, AudioSink as P, SpringOptions as Pn, Output as Pr, ConsoleEntry as Pt, MemoryStorage as Q, UiNodeReport as Qn, mutate as Qr, UiFramePhase as Qt, audioClock as R, ShellFileRequest as Rn, ThemeTokenCell as Rr, PatchEntry as Rt, writeClipboard as S, buildPath as Sn, pick as Sr, createApp as St, EditingService as T, AudioAction as Tn, ChannelRegistryHandle as Tr, WorkerAppOptions as Tt, ShellStorage as U, ShellService as Un, show as Ur, RuntimeToShellMessage as Ut, PersistedState as V, ShellRecentFile as Vn, Show as Vr, treeText as Vt, ShellStorageOptions as W, ShellStorageOp as Wn, Each as Wr, ShellToRuntimeMessage as Wt, OpfsStorageOptions as X, NodePathTarget as Xn, MutateOptions as Xr, RuntimeInput as Xt, OpfsStorage as Y, BoundStream as Yn, throttled as Yr, RendererChoice as Yt, OpfsWritable as Z, UiEnvironmentReport as Zn, Mutation as Zr, UI_FRAME_PHASES as Zt, EditingMirrorTarget as _, derive as _i, RouteOptions as _n, createComponent as _r, GessoAppOptions as _t, UiRole as a, select as ai, MediaOptions as an, formatAge as ar, storageReadValue as at, EditingProxy as b, to as bn, isComponentElement as br, WebMcpChoice as bt, UiSemanticsPatch as c, FanOut as ci, RouteMatch as cn, formatStream as cr, UndoableOptions as ct, markNow as d, ComputedCell as di, RouterService as dn, ComponentHost as dr, UndoStackOptions as dt, ResourceOptions as ei, FontFaceLike as en, UiPropOrigin as er, StorageOutcome as et, measureSpan as f, ComputedOptions as fi, RouteState as fn, OverlayLayer as fr, UndoTransaction as ft, renderRoot as g, Equality as gi, RouteGuard as gn, OverlayService as gr, GessoApp as gt, RenderWorkerApp as h, DeriveOptions as hi, RouteDefinition as hn, OverlayRect as hr, shellStorageDenied as ht, UI_SEMANTIC_STATES as i, SelectOptions as ii, FontService as in, describeStream as ir, storageReadFailure as it, PresenceProps as j, AudioStatus as jn, Define as jr, ActionEntry as jt, observeReducedMotion as k, AudioService as kn, ChannelRegistry as kr, createShellHistory as kt, UiSemanticsRecord$1 as l, FanOutOptions as li, RouterHistorySink as ln, printPropValue as lr, undoable as lt, setPerformanceMarks$1 as m, computed as mi, RouteContext as mn, OverlayPlacement as mr, performShellStorage as mt, MARK_PREFIX as n, ResourceStatus as ni, FontFamilyStatus as nn, UiSemanticsReport as nr, classifyStorageError as nt, UiSemanticState as o, FanCell as oi, MediaService as on, formatNodePath as or, UndoShortcutOptions as ot, performanceMarksEnabled as p, ReadSource as pi, OutletProps as pn, OverlayEntry as pr, ShellLocalStore as pt, OpfsDirectory as q, ColorSchemePreference as qn, each as qr, GessoRuntime as qt, UI_ROLES as r, resource as ri, FontHost as rn, UiStreamReport as rr, storageErrorMessage as rt, UiSemanticsMap$1 as s, FanKey as si, RouteAnswer as sn, formatNodeReport as sr, registerUndoShortcuts as st, EditingState$1 as t, ResourceState as ti, FontFamilyDeclaration as tn, UiPropReport as tr, StorageRead as tt, markInstant as u, fanOut as ui, RouterRoutes as un, ComponentHostResolver as ur, UndoStack as ut, SemanticsMirror as v, ServiceRegistry as vi, RouteTarget as vn, ComponentElement as vr, createSyncApp as vt, ScrollService as w, parseUrl as wn, ChannelRegistration as wr, WorkerApp as wt, EditingProxySink as x, RouteParams as xn, structurallyEqual as xr, CreateAppOptions as xt, SemanticsMirrorSink as y, route as yn, FrameworkChild as yr, GessoAppBuilder as yt, FrameService as z, ShellFileResult as zn, themeTokenCell as zr, UiTreeNode as zt };
8215
+ //# sourceMappingURL=index-Sff7qPGU.d.ts.map