@swifttui/web 0.0.13 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/README.md +24 -10
  2. package/dist/index.d.ts +9 -0
  3. package/dist/index.js +9 -0
  4. package/dist/manifest.d.ts +2 -0
  5. package/dist/manifest.js +2 -0
  6. package/dist/src/AccessibilityTree.js +156 -0
  7. package/dist/src/AccessibilityTree.js.map +1 -0
  8. package/dist/src/BoxDrawingRenderer.js +1106 -0
  9. package/dist/src/BoxDrawingRenderer.js.map +1 -0
  10. package/dist/src/WebHostApp.d.ts +41 -0
  11. package/dist/src/WebHostApp.js +135 -0
  12. package/dist/src/WebHostApp.js.map +1 -0
  13. package/dist/src/WebHostSceneManifest.d.ts +18 -0
  14. package/dist/src/WebHostSceneManifest.js +70 -0
  15. package/dist/src/WebHostSceneManifest.js.map +1 -0
  16. package/dist/src/WebHostSceneRuntime.d.ts +112 -0
  17. package/dist/src/WebHostSceneRuntime.js +651 -0
  18. package/dist/src/WebHostSceneRuntime.js.map +1 -0
  19. package/dist/src/WebHostSurfaceTransport.d.ts +166 -0
  20. package/dist/src/WebHostSurfaceTransport.js +252 -0
  21. package/dist/src/WebHostSurfaceTransport.js.map +1 -0
  22. package/dist/src/WebHostTerminalStyle.d.ts +92 -0
  23. package/dist/src/WebHostTerminalStyle.js +277 -0
  24. package/dist/src/WebHostTerminalStyle.js.map +1 -0
  25. package/dist/src/WebHostTestFixtures.d.ts +5 -0
  26. package/dist/src/WebHostTestFixtures.js +9 -0
  27. package/dist/src/WebHostTestFixtures.js.map +1 -0
  28. package/dist/src/WebSocketSceneBridge.d.ts +53 -0
  29. package/dist/src/WebSocketSceneBridge.js +124 -0
  30. package/dist/src/WebSocketSceneBridge.js.map +1 -0
  31. package/dist/src/wasi/BrowserWASIBridge.d.ts +33 -0
  32. package/dist/src/wasi/BrowserWASIBridge.js +97 -0
  33. package/dist/src/wasi/BrowserWASIBridge.js.map +1 -0
  34. package/dist/src/wasi/SharedInputQueue.d.ts +31 -0
  35. package/dist/src/wasi/SharedInputQueue.js +102 -0
  36. package/dist/src/wasi/SharedInputQueue.js.map +1 -0
  37. package/dist/src/wasi/StdIOPipe.d.ts +15 -0
  38. package/dist/src/wasi/StdIOPipe.js +56 -0
  39. package/dist/src/wasi/StdIOPipe.js.map +1 -0
  40. package/dist/src/wasi/WasiPollScheduler.js +114 -0
  41. package/dist/src/wasi/WasiPollScheduler.js.map +1 -0
  42. package/dist/src/wasi/WasmSceneRuntime.d.ts +23 -0
  43. package/dist/src/wasi/WasmSceneRuntime.js +119 -0
  44. package/dist/src/wasi/WasmSceneRuntime.js.map +1 -0
  45. package/dist/src/wasi/WasmSceneWorker.d.ts +27 -0
  46. package/dist/src/wasi/WasmSceneWorker.js +109 -0
  47. package/dist/src/wasi/WasmSceneWorker.js.map +1 -0
  48. package/dist/testing.d.ts +2 -0
  49. package/dist/testing.js +2 -0
  50. package/dist/wasi-worker.d.ts +2 -0
  51. package/dist/wasi-worker.js +2 -0
  52. package/dist/wasi.d.ts +6 -0
  53. package/dist/wasi.js +6 -0
  54. package/dist/websocket.d.ts +2 -0
  55. package/dist/websocket.js +2 -0
  56. package/package.json +49 -18
  57. package/AGENTS.md +0 -52
  58. package/cli.ts +0 -168
  59. package/index.html +0 -50
  60. package/index.ts +0 -8
  61. package/manifest.ts +0 -1
  62. package/src/AccessibilityTree.ts +0 -262
  63. package/src/BoxDrawingRenderer.ts +0 -585
  64. package/src/PublicEntrypointBoundary.test.ts +0 -20
  65. package/src/WebHostApp.test.ts +0 -222
  66. package/src/WebHostApp.ts +0 -269
  67. package/src/WebHostSceneManifest.test.ts +0 -38
  68. package/src/WebHostSceneManifest.ts +0 -156
  69. package/src/WebHostSceneRuntime.test.ts +0 -1982
  70. package/src/WebHostSceneRuntime.ts +0 -1142
  71. package/src/WebHostSurfaceTransport.test.ts +0 -362
  72. package/src/WebHostSurfaceTransport.ts +0 -691
  73. package/src/WebHostTerminalStyle.test.ts +0 -123
  74. package/src/WebHostTerminalStyle.ts +0 -471
  75. package/src/WebHostTestFixtures.ts +0 -10
  76. package/src/WebSocketSceneBridge.test.ts +0 -198
  77. package/src/WebSocketSceneBridge.ts +0 -233
  78. package/src/browser.ts +0 -59
  79. package/src/wasi/BrowserWASIBridge.test.ts +0 -168
  80. package/src/wasi/BrowserWASIBridge.ts +0 -167
  81. package/src/wasi/SharedInputQueue.test.ts +0 -146
  82. package/src/wasi/SharedInputQueue.ts +0 -199
  83. package/src/wasi/StdIOPipe.ts +0 -72
  84. package/src/wasi/WasiPollScheduler.test.ts +0 -176
  85. package/src/wasi/WasiPollScheduler.ts +0 -305
  86. package/src/wasi/WasmSceneRuntime.ts +0 -205
  87. package/src/wasi/WasmSceneWorker.ts +0 -182
  88. package/testing.ts +0 -1
  89. package/tsconfig.json +0 -29
  90. package/wasi-worker.ts +0 -1
  91. package/wasi.ts +0 -4
  92. package/websocket.ts +0 -1
@@ -1,691 +0,0 @@
1
- import {
2
- encodeWebHostTerminalRenderStyleBase64,
3
- type WebHostTerminalStyle,
4
- } from "./WebHostTerminalStyle.ts";
5
-
6
- export interface WebHostSurfaceStyle {
7
- fg?: string;
8
- bg?: string;
9
- em?: number;
10
- underline?: WebHostSurfaceLineStyle;
11
- strikethrough?: WebHostSurfaceLineStyle;
12
- opacity?: number;
13
- }
14
-
15
- export interface WebHostSurfaceLineStyle {
16
- pattern: "solid" | "dot" | "dash" | "dashDot" | "dashDotDot" | "double" | "curly";
17
- color?: string;
18
- }
19
-
20
- export type WebHostSurfaceCell = [
21
- x: number,
22
- text: string,
23
- span: number,
24
- styleIndex: number,
25
- ];
26
-
27
- export type WebHostSurfaceRect = [
28
- x: number,
29
- y: number,
30
- width: number,
31
- height: number,
32
- ];
33
-
34
- export type WebHostSurfaceSize = [
35
- width: number,
36
- height: number,
37
- ];
38
-
39
- export type WebHostAccessibilityPoint = [
40
- x: number,
41
- y: number,
42
- ];
43
-
44
- export type WebHostAccessibilityLiveRegion = "off" | "polite" | "assertive";
45
-
46
- export interface WebHostAccessibilityNode {
47
- id: string;
48
- parentId?: string;
49
- rect: WebHostSurfaceRect;
50
- role: string;
51
- label?: string;
52
- hint?: string;
53
- liveRegion?: WebHostAccessibilityLiveRegion;
54
- cursorAnchor?: WebHostAccessibilityPoint;
55
- isFocused?: boolean;
56
- }
57
-
58
- export interface WebHostAccessibilityAnnouncement {
59
- message: string;
60
- politeness: WebHostAccessibilityLiveRegion;
61
- }
62
-
63
- export type WebHostSurfaceImageFormat = "png" | "jpeg" | "gif";
64
-
65
- export interface WebHostSurfaceImage {
66
- id: string;
67
- format: WebHostSurfaceImageFormat;
68
- bounds: WebHostSurfaceRect;
69
- visibleBounds: WebHostSurfaceRect;
70
- scalingMode: "stretch" | "fit" | "fill";
71
- pixelSize?: WebHostSurfaceSize;
72
- dataBase64?: string;
73
- }
74
-
75
- export type WebHostSurfaceDamageRange = [
76
- start: number,
77
- end: number,
78
- ];
79
-
80
- export type WebHostSurfaceDamageTextRow = [
81
- row: number,
82
- ranges: WebHostSurfaceDamageRange[],
83
- ];
84
-
85
- export interface WebHostSurfaceDamage {
86
- textRows: WebHostSurfaceDamageTextRow[];
87
- requiresFullTextRepaint: boolean;
88
- requiresFullGraphicsReplay: boolean;
89
- }
90
-
91
- /**
92
- * Per-region scroll extent published with each frame so the host can implement
93
- * scroll-chaining: capture the wheel only while the region under the pointer can
94
- * still scroll in the wheel's direction, otherwise let it fall through to the
95
- * page. The host recomputes the per-direction headroom from `offset`/`content`/
96
- * the viewport `rect`, mirroring SwiftTUI's
97
- * `min(max(0, offset), max(0, content - viewport))` clamp.
98
- */
99
- export interface WebHostScrollRegion {
100
- /** identity path — same key space as accessibility node ids */
101
- id: string;
102
- /** viewport rect in cells: [x, y, width, height] */
103
- rect: WebHostSurfaceRect;
104
- /** current clamped scroll offset in cells: [x, y] */
105
- offset: WebHostAccessibilityPoint;
106
- /** total content size in cells: [width, height] */
107
- content: WebHostSurfaceSize;
108
- }
109
-
110
- export interface WebHostSurfaceFrame {
111
- version: 1 | 2;
112
- sequence?: number;
113
- width: number;
114
- height: number;
115
- styles: Array<WebHostSurfaceStyle | null>;
116
- rows: WebHostSurfaceCell[][];
117
- images?: WebHostSurfaceImage[];
118
- damage?: WebHostSurfaceDamage;
119
- accessibilityTree?: WebHostAccessibilityNode[];
120
- accessibilityAnnouncements?: WebHostAccessibilityAnnouncement[];
121
- scrollRegions?: WebHostScrollRegion[];
122
- }
123
-
124
- export type WebHostSurfaceDeltaRow = [
125
- row: number,
126
- cells: WebHostSurfaceCell[],
127
- ];
128
-
129
- export interface WebHostSurfaceDeltaFrame {
130
- version: 3;
131
- encoding: "delta";
132
- sequence?: number;
133
- width: number;
134
- height: number;
135
- styles: Array<WebHostSurfaceStyle | null>;
136
- deltaRows: WebHostSurfaceDeltaRow[];
137
- images?: WebHostSurfaceImage[];
138
- damage?: WebHostSurfaceDamage;
139
- accessibilityTree?: WebHostAccessibilityNode[];
140
- accessibilityAnnouncements?: WebHostAccessibilityAnnouncement[];
141
- scrollRegions?: WebHostScrollRegion[];
142
- }
143
-
144
- export interface WebHostRuntimeIssue {
145
- severity: "warning" | "error";
146
- code: string;
147
- message: string;
148
- description: string;
149
- identity?: string;
150
- source?: string;
151
- }
152
-
153
- export interface WebHostFrameDiagnosticRecord {
154
- format: "swift-tui-frame-diagnostics-v1";
155
- header: string[];
156
- fields: string[];
157
- }
158
-
159
- export type WebHostOutputRecord =
160
- | { type: "surface"; frame: WebHostSurfaceFrame }
161
- | { type: "clipboard"; text: string }
162
- | { type: "runtimeIssue"; issue: WebHostRuntimeIssue }
163
- | { type: "frameDiagnostic"; diagnostic: WebHostFrameDiagnosticRecord }
164
- | { type: "text"; text: string };
165
-
166
- export interface WebHostOutputSink {
167
- presentSurface(frame: WebHostSurfaceFrame): void;
168
- writeClipboard?(text: string): void | Promise<void>;
169
- notifyRuntimeIssue?(issue: WebHostRuntimeIssue): void;
170
- recordFrameDiagnostic?(diagnostic: WebHostFrameDiagnosticRecord): void;
171
- writeOutput?(text: string): void;
172
- writeError?(text: string): void;
173
- }
174
-
175
- export interface WebHostKeyInput {
176
- key:
177
- | "return"
178
- | "space"
179
- | "tab"
180
- | "arrowLeft"
181
- | "arrowRight"
182
- | "arrowUp"
183
- | "arrowDown"
184
- | "backspace"
185
- | "escape"
186
- | "home"
187
- | "end"
188
- | "character";
189
- character?: string;
190
- modifiers?: number;
191
- }
192
-
193
- export interface WebHostMouseInput {
194
- kind: "down" | "up" | "moved" | "dragged" | "scrolled";
195
- x: number;
196
- y: number;
197
- button?: "primary" | "middle" | "secondary";
198
- deltaX?: number;
199
- deltaY?: number;
200
- modifiers?: number;
201
- }
202
-
203
- const recordPrefix = "\u001E";
204
- const textEncoder = new TextEncoder();
205
-
206
- export class WebHostOutputDecoder {
207
- private readonly textDecoder = new TextDecoder();
208
- private bufferedText = "";
209
- private lastSurfaceFrame?: WebHostSurfaceFrame;
210
-
211
- feed(
212
- chunk: Uint8Array
213
- ): WebHostOutputRecord[] {
214
- this.bufferedText += this.textDecoder.decode(chunk, { stream: true });
215
- const records: WebHostOutputRecord[] = [];
216
-
217
- while (true) {
218
- const newlineIndex = this.bufferedText.indexOf("\n");
219
- if (newlineIndex < 0) {
220
- break;
221
- }
222
-
223
- const line = this.bufferedText.slice(0, newlineIndex);
224
- this.bufferedText = this.bufferedText.slice(newlineIndex + 1);
225
- records.push(this.decodeLine(line));
226
- }
227
-
228
- if (this.bufferedText.length > 4096 && !this.bufferedText.startsWith(recordPrefix)) {
229
- records.push({ type: "text", text: this.bufferedText });
230
- this.bufferedText = "";
231
- }
232
-
233
- return records;
234
- }
235
-
236
- flush(): WebHostOutputRecord[] {
237
- if (!this.bufferedText) {
238
- return [];
239
- }
240
- const text = this.bufferedText;
241
- this.bufferedText = "";
242
- return [this.decodeLine(text)];
243
- }
244
-
245
- private decodeLine(
246
- line: string
247
- ): WebHostOutputRecord {
248
- if (line.startsWith(`${recordPrefix}clipboard:`)) {
249
- try {
250
- const record = JSON.parse(line.slice(`${recordPrefix}clipboard:`.length));
251
- if (isWebHostClipboardRecord(record)) {
252
- return { type: "clipboard", text: record.text };
253
- }
254
- } catch {
255
- // Fall through to the text path below so malformed output remains visible.
256
- }
257
-
258
- return { type: "text", text: `${line}\n` };
259
- }
260
-
261
- if (line.startsWith(`${recordPrefix}runtimeIssue:`)) {
262
- try {
263
- const record = JSON.parse(line.slice(`${recordPrefix}runtimeIssue:`.length));
264
- if (isWebHostRuntimeIssue(record)) {
265
- return { type: "runtimeIssue", issue: record };
266
- }
267
- } catch {
268
- // Fall through to the text path below so malformed output remains visible.
269
- }
270
-
271
- return { type: "text", text: `${line}\n` };
272
- }
273
-
274
- if (line.startsWith(`${recordPrefix}frameDiagnostic:`)) {
275
- try {
276
- const record = JSON.parse(line.slice(`${recordPrefix}frameDiagnostic:`.length));
277
- if (isWebHostFrameDiagnosticRecord(record)) {
278
- return { type: "frameDiagnostic", diagnostic: record };
279
- }
280
- } catch {
281
- // Fall through to the text path below so malformed output remains visible.
282
- }
283
-
284
- return { type: "text", text: `${line}\n` };
285
- }
286
-
287
- if (!line.startsWith(`${recordPrefix}surface:`)) {
288
- return { type: "text", text: `${line}\n` };
289
- }
290
-
291
- try {
292
- const frame = JSON.parse(line.slice(`${recordPrefix}surface:`.length));
293
- if (isWebHostSurfaceFrame(frame)) {
294
- this.lastSurfaceFrame = frame;
295
- return { type: "surface", frame };
296
- }
297
- if (isWebHostSurfaceDeltaFrame(frame)) {
298
- const materialized = this.materializeDeltaFrame(frame);
299
- if (materialized) {
300
- this.lastSurfaceFrame = materialized;
301
- return { type: "surface", frame: materialized };
302
- }
303
- }
304
- } catch {
305
- // Fall through to the text path below so malformed output remains visible.
306
- }
307
-
308
- return { type: "text", text: `${line}\n` };
309
- }
310
-
311
- private materializeDeltaFrame(
312
- frame: WebHostSurfaceDeltaFrame
313
- ): WebHostSurfaceFrame | undefined {
314
- const baseline = this.lastSurfaceFrame;
315
- if (!baseline || baseline.width !== frame.width || baseline.height !== frame.height) {
316
- return undefined;
317
- }
318
-
319
- const rows = baseline.rows.slice();
320
- for (const [row, cells] of frame.deltaRows) {
321
- if (!Number.isSafeInteger(row) || row < 0 || row >= frame.height) {
322
- return undefined;
323
- }
324
- rows[row] = cells;
325
- }
326
-
327
- return {
328
- version: baseline.version,
329
- sequence: frame.sequence,
330
- width: frame.width,
331
- height: frame.height,
332
- styles: frame.styles,
333
- rows,
334
- images: frame.images,
335
- damage: frame.damage,
336
- accessibilityTree: frame.accessibilityTree,
337
- accessibilityAnnouncements: frame.accessibilityAnnouncements,
338
- scrollRegions: frame.scrollRegions,
339
- };
340
- }
341
- }
342
-
343
- function isWebHostClipboardRecord(
344
- value: unknown
345
- ): value is { text: string } {
346
- return !!value && typeof value === "object" && typeof (value as { text?: unknown }).text === "string";
347
- }
348
-
349
- function isWebHostRuntimeIssue(
350
- value: unknown
351
- ): value is WebHostRuntimeIssue {
352
- if (!value || typeof value !== "object") {
353
- return false;
354
- }
355
- const record = value as Partial<WebHostRuntimeIssue>;
356
- return (record.severity === "warning" || record.severity === "error")
357
- && typeof record.code === "string"
358
- && typeof record.message === "string"
359
- && typeof record.description === "string"
360
- && (record.identity === undefined || typeof record.identity === "string")
361
- && (record.source === undefined || typeof record.source === "string");
362
- }
363
-
364
- function isWebHostFrameDiagnosticRecord(
365
- value: unknown
366
- ): value is WebHostFrameDiagnosticRecord {
367
- if (!value || typeof value !== "object") {
368
- return false;
369
- }
370
- const record = value as Partial<WebHostFrameDiagnosticRecord>;
371
- return record.format === "swift-tui-frame-diagnostics-v1"
372
- && Array.isArray(record.header)
373
- && record.header.every((field) => typeof field === "string")
374
- && Array.isArray(record.fields)
375
- && record.fields.every((field) => typeof field === "string");
376
- }
377
-
378
- export function encodeResizeControlMessage(
379
- columns: number,
380
- rows: number,
381
- cellWidth?: number,
382
- cellHeight?: number
383
- ): Uint8Array {
384
- const normalizedColumns = Math.max(1, Math.round(columns));
385
- const normalizedRows = Math.max(1, Math.round(rows));
386
- if (cellWidth && cellHeight) {
387
- return textEncoder.encode(
388
- `${recordPrefix}resize:${normalizedColumns}:${normalizedRows}:${Math.max(1, Math.round(cellWidth))}:${Math.max(1, Math.round(cellHeight))}\n`
389
- );
390
- }
391
-
392
- return textEncoder.encode(`${recordPrefix}resize:${normalizedColumns}:${normalizedRows}\n`);
393
- }
394
-
395
- export function encodeRenderStyleControlMessage(
396
- style: WebHostTerminalStyle
397
- ): Uint8Array {
398
- const encoded = encodeWebHostTerminalRenderStyleBase64(style);
399
- return textEncoder.encode(`${recordPrefix}style:${encoded}\n`);
400
- }
401
-
402
- export function encodeKeyInputMessage(
403
- input: WebHostKeyInput
404
- ): Uint8Array {
405
- const modifiers = Math.max(0, Math.round(input.modifiers ?? 0));
406
- if (input.key === "character") {
407
- return textEncoder.encode(
408
- `${recordPrefix}key:character:${encodeURIComponent(input.character ?? "")}:${modifiers}\n`
409
- );
410
- }
411
- return textEncoder.encode(`${recordPrefix}key:${input.key}:${modifiers}\n`);
412
- }
413
-
414
- export function encodePasteInputMessage(
415
- text: string
416
- ): Uint8Array {
417
- return textEncoder.encode(`${recordPrefix}paste:${encodeURIComponent(text)}\n`);
418
- }
419
-
420
- export function encodeMouseInputMessage(
421
- input: WebHostMouseInput
422
- ): Uint8Array {
423
- return textEncoder.encode(
424
- recordPrefix + [
425
- "mouse",
426
- input.kind,
427
- formatCellCoordinate(input.x),
428
- formatCellCoordinate(input.y),
429
- input.button ?? "none",
430
- Math.round(input.deltaX ?? 0),
431
- Math.round(input.deltaY ?? 0),
432
- Math.max(0, Math.round(input.modifiers ?? 0)),
433
- ].join(":") + "\n"
434
- );
435
- }
436
-
437
- function formatCellCoordinate(
438
- value: number
439
- ): string {
440
- return Number.isFinite(value) ? String(value) : "0";
441
- }
442
-
443
- function isWebHostSurfaceFrame(
444
- value: unknown
445
- ): value is WebHostSurfaceFrame {
446
- if (!value || typeof value !== "object") {
447
- return false;
448
- }
449
- const frame = value as Partial<WebHostSurfaceFrame>;
450
- return (frame.version === 1 || frame.version === 2)
451
- && (
452
- frame.sequence === undefined
453
- || (Number.isSafeInteger(frame.sequence) && frame.sequence >= 0)
454
- )
455
- && typeof frame.width === "number"
456
- && typeof frame.height === "number"
457
- && Array.isArray(frame.styles)
458
- && Array.isArray(frame.rows)
459
- && frame.rows.every(isWebHostSurfaceRow)
460
- && (frame.images === undefined || isWebHostSurfaceImages(frame.images))
461
- && (frame.damage === undefined || isWebHostSurfaceDamage(frame.damage))
462
- && (
463
- frame.accessibilityTree === undefined
464
- || isWebHostAccessibilityNodes(frame.accessibilityTree)
465
- )
466
- && (
467
- frame.accessibilityAnnouncements === undefined
468
- || isWebHostAccessibilityAnnouncements(frame.accessibilityAnnouncements)
469
- )
470
- && (frame.scrollRegions === undefined || isWebHostScrollRegions(frame.scrollRegions));
471
- }
472
-
473
- function isWebHostSurfaceDeltaFrame(
474
- value: unknown
475
- ): value is WebHostSurfaceDeltaFrame {
476
- if (!value || typeof value !== "object") {
477
- return false;
478
- }
479
- const frame = value as Partial<WebHostSurfaceDeltaFrame>;
480
- return frame.version === 3
481
- && frame.encoding === "delta"
482
- && (
483
- frame.sequence === undefined
484
- || (Number.isSafeInteger(frame.sequence) && frame.sequence >= 0)
485
- )
486
- && typeof frame.width === "number"
487
- && typeof frame.height === "number"
488
- && Array.isArray(frame.styles)
489
- && Array.isArray(frame.deltaRows)
490
- && frame.deltaRows.every(isWebHostSurfaceDeltaRow)
491
- && (frame.images === undefined || isWebHostSurfaceImages(frame.images))
492
- && (frame.damage === undefined || isWebHostSurfaceDamage(frame.damage))
493
- && (
494
- frame.accessibilityTree === undefined
495
- || isWebHostAccessibilityNodes(frame.accessibilityTree)
496
- )
497
- && (
498
- frame.accessibilityAnnouncements === undefined
499
- || isWebHostAccessibilityAnnouncements(frame.accessibilityAnnouncements)
500
- )
501
- && (frame.scrollRegions === undefined || isWebHostScrollRegions(frame.scrollRegions));
502
- }
503
-
504
- function isWebHostSurfaceDeltaRow(
505
- value: unknown
506
- ): value is WebHostSurfaceDeltaRow {
507
- return Array.isArray(value)
508
- && value.length === 2
509
- && Number.isSafeInteger(value[0])
510
- && value[0] >= 0
511
- && isWebHostSurfaceRow(value[1]);
512
- }
513
-
514
- function isWebHostSurfaceRow(
515
- value: unknown
516
- ): value is WebHostSurfaceCell[] {
517
- return Array.isArray(value) && value.every(isWebHostSurfaceCell);
518
- }
519
-
520
- function isWebHostSurfaceCell(
521
- value: unknown
522
- ): value is WebHostSurfaceCell {
523
- return Array.isArray(value)
524
- && value.length === 4
525
- && Number.isSafeInteger(value[0])
526
- && value[0] >= 0
527
- && typeof value[1] === "string"
528
- && Number.isSafeInteger(value[2])
529
- && value[2] >= 1
530
- && Number.isSafeInteger(value[3])
531
- && value[3] >= 0;
532
- }
533
-
534
- function isWebHostAccessibilityNodes(
535
- value: unknown
536
- ): value is WebHostAccessibilityNode[] {
537
- return Array.isArray(value) && value.every(isWebHostAccessibilityNode);
538
- }
539
-
540
- function isWebHostAccessibilityNode(
541
- value: unknown
542
- ): value is WebHostAccessibilityNode {
543
- if (!value || typeof value !== "object") {
544
- return false;
545
- }
546
- const node = value as Partial<WebHostAccessibilityNode>;
547
- return typeof node.id === "string"
548
- && (node.parentId === undefined || typeof node.parentId === "string")
549
- && isWebHostSurfaceRect(node.rect)
550
- && typeof node.role === "string"
551
- && (node.label === undefined || typeof node.label === "string")
552
- && (node.hint === undefined || typeof node.hint === "string")
553
- && (
554
- node.liveRegion === undefined
555
- || node.liveRegion === "off"
556
- || node.liveRegion === "polite"
557
- || node.liveRegion === "assertive"
558
- )
559
- && (node.cursorAnchor === undefined || isWebHostAccessibilityPoint(node.cursorAnchor))
560
- && (node.isFocused === undefined || typeof node.isFocused === "boolean");
561
- }
562
-
563
- function isWebHostAccessibilityPoint(
564
- value: unknown
565
- ): value is WebHostAccessibilityPoint {
566
- return Array.isArray(value)
567
- && value.length === 2
568
- && value.every((entry) => typeof entry === "number");
569
- }
570
-
571
- function isWebHostAccessibilityAnnouncements(
572
- value: unknown
573
- ): value is WebHostAccessibilityAnnouncement[] {
574
- return Array.isArray(value) && value.every(isWebHostAccessibilityAnnouncement);
575
- }
576
-
577
- function isWebHostAccessibilityAnnouncement(
578
- value: unknown
579
- ): value is WebHostAccessibilityAnnouncement {
580
- if (!value || typeof value !== "object") {
581
- return false;
582
- }
583
- const announcement = value as Partial<WebHostAccessibilityAnnouncement>;
584
- return typeof announcement.message === "string"
585
- && (
586
- announcement.politeness === "off"
587
- || announcement.politeness === "polite"
588
- || announcement.politeness === "assertive"
589
- );
590
- }
591
-
592
- function isWebHostSurfaceImages(
593
- value: unknown
594
- ): value is WebHostSurfaceImage[] {
595
- return Array.isArray(value) && value.every(isWebHostSurfaceImage);
596
- }
597
-
598
- function isWebHostSurfaceImage(
599
- value: unknown
600
- ): value is WebHostSurfaceImage {
601
- if (!value || typeof value !== "object") {
602
- return false;
603
- }
604
- const image = value as Partial<WebHostSurfaceImage>;
605
- return typeof image.id === "string"
606
- && isWebHostSurfaceImageFormat(image.format)
607
- && isWebHostSurfaceRect(image.bounds)
608
- && isWebHostSurfaceRect(image.visibleBounds)
609
- && isWebHostSurfaceScalingMode(image.scalingMode)
610
- && (image.pixelSize === undefined || isWebHostSurfaceSize(image.pixelSize))
611
- && (image.dataBase64 === undefined || typeof image.dataBase64 === "string");
612
- }
613
-
614
- function isWebHostSurfaceDamage(
615
- value: unknown
616
- ): value is WebHostSurfaceDamage {
617
- if (!value || typeof value !== "object") {
618
- return false;
619
- }
620
- const damage = value as Partial<WebHostSurfaceDamage>;
621
- return Array.isArray(damage.textRows)
622
- && damage.textRows.every(isWebHostSurfaceDamageTextRow)
623
- && typeof damage.requiresFullTextRepaint === "boolean"
624
- && typeof damage.requiresFullGraphicsReplay === "boolean";
625
- }
626
-
627
- function isWebHostSurfaceDamageTextRow(
628
- value: unknown
629
- ): value is WebHostSurfaceDamageTextRow {
630
- return Array.isArray(value)
631
- && value.length === 2
632
- && typeof value[0] === "number"
633
- && Array.isArray(value[1])
634
- && value[1].every(isWebHostSurfaceDamageRange);
635
- }
636
-
637
- function isWebHostSurfaceDamageRange(
638
- value: unknown
639
- ): value is WebHostSurfaceDamageRange {
640
- return Array.isArray(value)
641
- && value.length === 2
642
- && typeof value[0] === "number"
643
- && typeof value[1] === "number";
644
- }
645
-
646
- function isWebHostSurfaceImageFormat(
647
- value: unknown
648
- ): value is WebHostSurfaceImageFormat {
649
- return value === "png" || value === "jpeg" || value === "gif";
650
- }
651
-
652
- function isWebHostScrollRegions(
653
- value: unknown
654
- ): value is WebHostScrollRegion[] {
655
- return Array.isArray(value) && value.every(isWebHostScrollRegion);
656
- }
657
-
658
- function isWebHostScrollRegion(
659
- value: unknown
660
- ): value is WebHostScrollRegion {
661
- if (!value || typeof value !== "object") {
662
- return false;
663
- }
664
- const region = value as Partial<WebHostScrollRegion>;
665
- return typeof region.id === "string"
666
- && isWebHostSurfaceRect(region.rect)
667
- && isWebHostSurfaceSize(region.offset)
668
- && isWebHostSurfaceSize(region.content);
669
- }
670
-
671
- function isWebHostSurfaceRect(
672
- value: unknown
673
- ): value is WebHostSurfaceRect {
674
- return Array.isArray(value)
675
- && value.length === 4
676
- && value.every((entry) => typeof entry === "number");
677
- }
678
-
679
- function isWebHostSurfaceSize(
680
- value: unknown
681
- ): value is WebHostSurfaceSize {
682
- return Array.isArray(value)
683
- && value.length === 2
684
- && value.every((entry) => typeof entry === "number");
685
- }
686
-
687
- function isWebHostSurfaceScalingMode(
688
- value: unknown
689
- ): value is WebHostSurfaceImage["scalingMode"] {
690
- return value === "stretch" || value === "fit" || value === "fill";
691
- }