lecodes-cli 2.0.7 → 2.0.9
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/dist/index.js +1798 -1116
- package/package.json +21 -11
- package/runtime/sdk-types.json +1 -1
- package/runtime/web/VERSION.json +3 -3
- package/runtime/web/assets/creator-2d-BSJoqaE1.wasm +0 -0
- package/runtime/web/assets/{creator-2d-CYlV77UR.js → creator-2d-DG2jJnoQ.js} +1 -1
- package/runtime/web/assets/creator-ui-Bu2prHDl.wasm +0 -0
- package/runtime/web/assets/creator-ui-HDloYDcM.js +1 -0
- package/runtime/web/player.js +15 -15
- package/runtime/web-lite/assets/pager-DpGa2uaE.js +1 -0
- package/runtime/web-lite/assets/vlist-CwSYpLz-.js +1 -0
- package/runtime/web-lite/features.json +2 -2
- package/runtime/web-lite/lite.js +21 -10
- package/src/commands/app/android.ts +7 -7
- package/src/commands/app/index.ts +58 -84
- package/src/commands/app/shared.ts +53 -74
- package/src/commands/app/templates/ios.ts +75 -78
- package/src/commands/compile.ts +1 -1
- package/src/commands/init/templates.ts +7 -0
- package/src/commands/render.ts +17 -4
- package/src/commands/test.ts +10 -6
- package/src/compile/collect.ts +12 -3
- package/src/compile/headlessBundle.ts +10 -3
- package/src/declarations/lecodes-headless.d.ts +3 -0
- package/src/dev/backendWorker.ts +17 -6
- package/src/dev/localBackend.ts +8 -2
- package/src/dev/projectBackend.ts +31 -9
- package/src/hosts/desktopScript.ts +11 -1
- package/src/hosts/flowPick.ts +111 -0
- package/src/hosts/liteBrowser.mjs +5 -0
- package/src/hosts/liteRunner.ts +30 -0
- package/src/hosts/peerInstall.ts +5 -1
- package/src/hosts/peers.ts +2 -0
- package/runtime/web/assets/creator-2d-nG7rGEmq.wasm +0 -0
- package/runtime/web/assets/creator-ui-CbtoaRlz.js +0 -1
- package/runtime/web/assets/creator-ui-DZaoxIpX.wasm +0 -0
- package/runtime/web-lite/assets/pager-Db5BY7FB.js +0 -1
- package/runtime/web-lite/assets/vlist-DrV2Q7P5.js +0 -1
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { rmSync } from "node:fs"
|
|
2
2
|
import { join, relative } from "node:path"
|
|
3
|
-
import { createChannelHub } from "lecodes-sdk/server"
|
|
3
|
+
import { createChannelHub, fileResponse, isMultipart, receiveUploads, UploadError, type Upload } from "lecodes-sdk/server"
|
|
4
4
|
import { compileServer, hasServerFiles, type CompileEntry } from "../compile/projectCompile"
|
|
5
5
|
import { loadPeer } from "../hosts/peerInstall"
|
|
6
6
|
import { LECODES_DIR } from "../project/manifest"
|
|
7
7
|
import { readAppConfigAt } from "../commands/app/shared"
|
|
8
|
-
import { startLocalBackend, type LocalBackend } from "./localBackend"
|
|
8
|
+
import { filesDirOf, startLocalBackend, type LocalBackend } from "./localBackend"
|
|
9
9
|
import { serve, type Served, type Socket, type SocketHandlers } from "./serve"
|
|
10
10
|
|
|
11
11
|
/*
|
|
12
12
|
* The project's backend ON THE WIRE, on this machine: its server bundle run by localBackend.ts, put
|
|
13
13
|
* behind the routes the SDK's client transport speaks (sdk/src/runtime/rpc.ts) —
|
|
14
14
|
*
|
|
15
|
-
* POST <base>/api/<id> an endpoint call, the envelope always HTTP 200 (the client reads `ok`)
|
|
15
|
+
* POST <base>/api/<id> an endpoint call, the envelope always HTTP 200 (the client reads `ok`);
|
|
16
|
+
* multipart when it carries files
|
|
17
|
+
* GET <base>/files/<id>/<name> a stored file (`t.file()`): `.lecodes/files`, beside the database
|
|
16
18
|
* WS <base>/ws the channel socket: the SDK's hub, the one the runner serves on le.codes
|
|
17
19
|
*
|
|
18
20
|
* Two users: the dev server mounts the routes under its token path (`lecodes dev`, `web dev`, the
|
|
@@ -59,6 +61,7 @@ const BODY_LIMIT = 8 * 1024 * 1024
|
|
|
59
61
|
export const createProjectBackend = (options: ProjectBackendOptions): ProjectBackend => {
|
|
60
62
|
const { root, log } = options
|
|
61
63
|
const dbDir = options.dbDir ?? join(root, LECODES_DIR, "db")
|
|
64
|
+
const filesDir = filesDirOf(dbDir)
|
|
62
65
|
let backend: LocalBackend | null = null
|
|
63
66
|
let running: string | null = null
|
|
64
67
|
|
|
@@ -91,6 +94,8 @@ export const createProjectBackend = (options: ProjectBackendOptions): ProjectBac
|
|
|
91
94
|
// the embedded database is a peer, installed the first time a project defines models
|
|
92
95
|
if (Object.keys(bundle.manifest.modules).length && /\bdefineDb\s*\(/.test(bundle.code)) {
|
|
93
96
|
await loadPeer("marcidb-embedded", undefined, { for: `${options.command} (the project's database)` })
|
|
97
|
+
// …and so is the codec of its pictures, the first time a model has a t.image() field
|
|
98
|
+
if (/\bimage\s*\(/.test(bundle.code)) await loadPeer("sharp", undefined, { for: `${options.command} (the project's t.image() fields)` })
|
|
94
99
|
}
|
|
95
100
|
backend ??= start()
|
|
96
101
|
const deployed = await backend.deploy(bundle.code)
|
|
@@ -104,16 +109,32 @@ export const createProjectBackend = (options: ProjectBackendOptions): ProjectBac
|
|
|
104
109
|
},
|
|
105
110
|
handle: async (req, route, ip) => {
|
|
106
111
|
if (req.method === "OPTIONS") return new Response(null, { status: 204, headers: CORS })
|
|
112
|
+
if (route.startsWith("/files/") && (req.method === "GET" || req.method === "HEAD")) {
|
|
113
|
+
return fileResponse(filesDir, route.slice("/files/".length), req, { "access-control-allow-origin": "*" })
|
|
114
|
+
}
|
|
107
115
|
const id = route.startsWith("/api/") ? decodeURIComponent(route.slice("/api/".length)) : ""
|
|
108
116
|
if (!id || req.method !== "POST") return envelope({ ok: false, status: 404, message: "not an endpoint call" })
|
|
109
117
|
if (!backend) return envelope({ ok: false, status: 404, message: "The project has no server files" })
|
|
110
118
|
let args: unknown
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
119
|
+
let uploads: Upload[] = []
|
|
120
|
+
if (isMultipart(req)) {
|
|
121
|
+
try {
|
|
122
|
+
({ args, uploads } = await receiveUploads(req, filesDir))
|
|
123
|
+
} catch (e) {
|
|
124
|
+
if (e instanceof UploadError) return envelope({ ok: false, status: e.status, message: e.message })
|
|
125
|
+
throw e
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
try {
|
|
129
|
+
const body = await req.text()
|
|
130
|
+
args = body.length > BODY_LIMIT ? null : JSON.parse(body)?.args
|
|
131
|
+
} catch { args = null }
|
|
132
|
+
}
|
|
115
133
|
if (!Array.isArray(args)) return envelope({ ok: false, status: 400, message: "body must be {\"args\":[…]}" })
|
|
116
|
-
|
|
134
|
+
// a stored file's url starts where this very request found the backend (a phone's address of this machine, a tunnel)
|
|
135
|
+
const url = new URL(req.url)
|
|
136
|
+
const filesBase = url.origin + url.pathname.slice(0, url.pathname.length - route.length)
|
|
137
|
+
return envelope(await backend.invoke(id, args, { headers: Object.fromEntries(req.headers), ip, sessionToken: bearerOf(req) ?? undefined, uploads, filesBase }))
|
|
117
138
|
},
|
|
118
139
|
socket: (req, ip) => (conn) => {
|
|
119
140
|
const c = hub.connect(conn, { ip, session: bearerOf(req) })
|
|
@@ -127,6 +148,7 @@ export const createProjectBackend = (options: ProjectBackendOptions): ProjectBac
|
|
|
127
148
|
if (!backend || running === null) return
|
|
128
149
|
await backend.close()
|
|
129
150
|
rmSync(dbDir, { recursive: true, force: true })
|
|
151
|
+
rmSync(filesDir, { recursive: true, force: true })
|
|
130
152
|
backend = start()
|
|
131
153
|
await backend.deploy(running)
|
|
132
154
|
},
|
|
@@ -165,7 +187,7 @@ const stablePort = (root: string): number => {
|
|
|
165
187
|
export const runBackend = (options: { root: string, command: string, log: (msg: string) => void, test?: boolean }): RunBackend => {
|
|
166
188
|
const { root } = options
|
|
167
189
|
const dbDir = join(root, LECODES_DIR, options.test ? "test-db" : "db")
|
|
168
|
-
if (options.test) rmSync(dbDir, { recursive: true, force: true })
|
|
190
|
+
if (options.test) { rmSync(dbDir, { recursive: true, force: true }); rmSync(filesDirOf(dbDir), { recursive: true, force: true }) }
|
|
169
191
|
const backend = createProjectBackend({ root, dbDir, log: options.log, command: options.command })
|
|
170
192
|
let server: Served | null = null
|
|
171
193
|
|
|
@@ -26,6 +26,7 @@ const isPoint = (v: unknown): v is Point =>
|
|
|
26
26
|
typeof v === "object" && v !== null && typeof (v as Point).x === "number" && typeof (v as Point).y === "number"
|
|
27
27
|
|
|
28
28
|
const FRAME_MS = 16
|
|
29
|
+
const SETTLE_FRAMES = 640
|
|
29
30
|
|
|
30
31
|
export type DesktopPlanStep = {
|
|
31
32
|
index: number
|
|
@@ -136,6 +137,14 @@ export const translateScenario = (rawSteps: unknown, opts: { outDir: string, hea
|
|
|
136
137
|
} else throw new CliError(`${at}: "camera" wants { "at": [x,y,z], "lookAt": [x,y,z], "fov"? } or "off".`)
|
|
137
138
|
budgetMs += 2 * FRAME_MS
|
|
138
139
|
}
|
|
140
|
+
if (s.pick !== undefined) {
|
|
141
|
+
// the files of the step's file dialog: armed first, the action that opens it follows
|
|
142
|
+
const files = typeof s.pick === "string" ? [s.pick] : s.pick
|
|
143
|
+
if (!Array.isArray(files) || files.length === 0 || !files.every((f) => typeof f === "string")) throw new CliError(`${at}: "pick" must be a file path or a list of them.`)
|
|
144
|
+
if (opts.sim) throw new CliError(`${at}: "pick" isn't available with --sim (the windowless host has no file dialog) — run this scenario with --desktop or headless.`)
|
|
145
|
+
plan.lines.push(emit(`pick ${(files as string[]).map(wire).join(" ")}`)); budgetMs += FRAME_MS
|
|
146
|
+
parts.push(`pick ${(files as string[]).map((f) => f.split(/[\\/]/).pop()).join(" + ")}`)
|
|
147
|
+
}
|
|
139
148
|
if (s.fov !== undefined && action !== "view") throw new CliError(`${at}: "fov" only goes with "view" (inside "camera" use camera.fov).`)
|
|
140
149
|
if (action === "tap") {
|
|
141
150
|
const p = target(at, "tap", s.tap)
|
|
@@ -316,7 +325,8 @@ export const translateScenario = (rawSteps: unknown, opts: { outDir: string, hea
|
|
|
316
325
|
steps.push(plan)
|
|
317
326
|
})
|
|
318
327
|
|
|
319
|
-
|
|
328
|
+
// + what the host may wait for the requests a command left in flight (script.cpp: 5 s of 8 ms frames)
|
|
329
|
+
const frameCap = Math.max(0, opts.headroomFrames) + Math.ceil(budgetMs / FRAME_MS) + 600 + lines.length * SETTLE_FRAMES
|
|
320
330
|
return { text: lines.join("\n") + "\n", steps, frameCap }
|
|
321
331
|
}
|
|
322
332
|
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"
|
|
2
|
+
import { tmpdir } from "node:os"
|
|
3
|
+
import { join, resolve } from "node:path"
|
|
4
|
+
import { deflateSync } from "node:zlib"
|
|
5
|
+
import { CliError } from "../cli"
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* `pick` of a flow step: the files the step's file dialog is answered with (`openFilePicker`).
|
|
9
|
+
*
|
|
10
|
+
* { "tap": "attach", "pick": "cat.png" } a file beside the flow file
|
|
11
|
+
* { "tap": "attach", "pick": ["cat.png", "notes.txt"] } several (a `multiple` picker)
|
|
12
|
+
* { "tap": "avatar", "pick": { "name": "me.png", "width": 400, "height": 300 } } a picture made for the run
|
|
13
|
+
* { "tap": "attach", "pick": { "name": "notes.txt", "text": "hello" } } a text file made for the run
|
|
14
|
+
*
|
|
15
|
+
* A flow names its files the way it is convenient to write; every host is handed the same thing —
|
|
16
|
+
* absolute paths of files that exist. This module is that step: a path is resolved against the flow
|
|
17
|
+
* file's folder, a described file is written to a folder of this run (removed when the CLI exits).
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const MAX_SIDE = 4096
|
|
21
|
+
|
|
22
|
+
const crcTable = (() => {
|
|
23
|
+
const table = new Uint32Array(256)
|
|
24
|
+
for (let n = 0; n < 256; n++) {
|
|
25
|
+
let c = n
|
|
26
|
+
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1
|
|
27
|
+
table[n] = c >>> 0
|
|
28
|
+
}
|
|
29
|
+
return table
|
|
30
|
+
})()
|
|
31
|
+
const crc32 = (bytes: Uint8Array): number => {
|
|
32
|
+
let c = 0xffffffff
|
|
33
|
+
for (const b of bytes) c = crcTable[(c ^ b) & 0xff]! ^ (c >>> 8)
|
|
34
|
+
return (c ^ 0xffffffff) >>> 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** A PNG of one colour: what a test of an upload needs of a picture is its type and its size. */
|
|
38
|
+
const png = (width: number, height: number): Uint8Array => {
|
|
39
|
+
const chunk = (type: string, data: Uint8Array): Uint8Array => {
|
|
40
|
+
const out = new Uint8Array(12 + data.length)
|
|
41
|
+
const view = new DataView(out.buffer)
|
|
42
|
+
view.setUint32(0, data.length)
|
|
43
|
+
out.set([...type].map((ch) => ch.charCodeAt(0)), 4)
|
|
44
|
+
out.set(data, 8)
|
|
45
|
+
view.setUint32(8 + data.length, crc32(out.subarray(4, 8 + data.length)))
|
|
46
|
+
return out
|
|
47
|
+
}
|
|
48
|
+
const header = new Uint8Array(13)
|
|
49
|
+
const view = new DataView(header.buffer)
|
|
50
|
+
view.setUint32(0, width)
|
|
51
|
+
view.setUint32(4, height)
|
|
52
|
+
header.set([8, 2, 0, 0, 0], 8) // 8 bits, RGB
|
|
53
|
+
const row = new Uint8Array(1 + width * 3)
|
|
54
|
+
for (let x = 0; x < width; x++) row.set([0xd4, 0x53, 0x2b], 1 + x * 3)
|
|
55
|
+
const pixels = new Uint8Array(row.length * height)
|
|
56
|
+
for (let y = 0; y < height; y++) pixels.set(row, y * row.length)
|
|
57
|
+
const parts = [Uint8Array.of(0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a), chunk("IHDR", header), chunk("IDAT", deflateSync(pixels)), chunk("IEND", new Uint8Array(0))]
|
|
58
|
+
const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0))
|
|
59
|
+
let at = 0
|
|
60
|
+
for (const p of parts) { out.set(p, at); at += p.length }
|
|
61
|
+
return out
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let madeDir: string | null = null
|
|
65
|
+
let made = 0
|
|
66
|
+
/** A described file, written for this run: a folder of its own, so two of one name do not meet. */
|
|
67
|
+
const write = (name: string, bytes: Uint8Array): string => {
|
|
68
|
+
if (!madeDir) {
|
|
69
|
+
madeDir = mkdtempSync(join(tmpdir(), "lecodes-pick-"))
|
|
70
|
+
const dir = madeDir
|
|
71
|
+
process.on("exit", () => { try { rmSync(dir, { recursive: true, force: true }) } catch { /* the OS clears its temp */ } })
|
|
72
|
+
}
|
|
73
|
+
const dir = join(madeDir, String(made++))
|
|
74
|
+
mkdirSync(dir)
|
|
75
|
+
const path = join(dir, name)
|
|
76
|
+
writeFileSync(path, bytes)
|
|
77
|
+
return path
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const fileOf = (at: string, value: unknown, baseDir: string): string => {
|
|
81
|
+
if (typeof value === "string") {
|
|
82
|
+
const path = resolve(baseDir, value)
|
|
83
|
+
if (!existsSync(path)) throw new CliError(`${at}: "pick": no file "${value}" (looked for ${path}).`)
|
|
84
|
+
return path
|
|
85
|
+
}
|
|
86
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) throw new CliError(`${at}: "pick" wants a file path, { "name", "text" } or { "name", "width", "height" } — or a list of them.`)
|
|
87
|
+
const { name, text, width, height, ...rest } = value as { name?: unknown, text?: unknown, width?: unknown, height?: unknown }
|
|
88
|
+
const unknown = Object.keys(rest)
|
|
89
|
+
if (unknown.length > 0) throw new CliError(`${at}: "pick": unknown key "${unknown[0]}" (a described file is { "name", "text" } or { "name", "width", "height" }).`)
|
|
90
|
+
if (typeof name !== "string" || name === "" || /[\\/]/.test(name)) throw new CliError(`${at}: "pick": a described file needs a "name" (a file name, no folders).`)
|
|
91
|
+
if (text !== undefined) {
|
|
92
|
+
if (typeof text !== "string" || width !== undefined || height !== undefined) throw new CliError(`${at}: "pick": "${name}" is { "name", "text" } or { "name", "width", "height" }.`)
|
|
93
|
+
return write(name, new TextEncoder().encode(text))
|
|
94
|
+
}
|
|
95
|
+
const side = (n: unknown) => typeof n === "number" && Number.isInteger(n) && n >= 1 && n <= MAX_SIDE
|
|
96
|
+
if (!side(width) || !side(height)) throw new CliError(`${at}: "pick": "${name}" needs a "text", or a "width" and a "height" (1…${MAX_SIDE}).`)
|
|
97
|
+
if (!/\.png$/i.test(name)) throw new CliError(`${at}: "pick": a picture made for the run is a PNG — name it "….png" (got "${name}").`)
|
|
98
|
+
return write(name, png(width as number, height as number))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The steps with every `pick` as a list of absolute paths. `baseDir`: the flow file's folder. */
|
|
102
|
+
export const resolvePicks = (steps: unknown, baseDir: string): unknown => {
|
|
103
|
+
if (!Array.isArray(steps)) return steps
|
|
104
|
+
return steps.map((step, i) => {
|
|
105
|
+
if (typeof step !== "object" || step === null || Array.isArray(step) || (step as { pick?: unknown }).pick === undefined) return step
|
|
106
|
+
const pick = (step as { pick: unknown }).pick
|
|
107
|
+
const list = Array.isArray(pick) ? pick : [pick]
|
|
108
|
+
if (list.length === 0) throw new CliError(`steps[${i}]: "pick" is empty — leave it out for a dialog that is cancelled.`)
|
|
109
|
+
return { ...step, pick: list.map((value) => fileOf(`steps[${i}]`, value, baseDir)) }
|
|
110
|
+
})
|
|
111
|
+
}
|
|
@@ -59,6 +59,11 @@ const ops = {
|
|
|
59
59
|
else if (action === "up") await page.keyboard.up(text)
|
|
60
60
|
return null
|
|
61
61
|
},
|
|
62
|
+
/** The page's next file dialog is answered with these files (a picker of one file takes the first). */
|
|
63
|
+
async pick({ files }) {
|
|
64
|
+
page.once("filechooser", (chooser) => { chooser.setFiles(chooser.isMultiple() ? files : files.slice(0, 1)).catch(() => {}) })
|
|
65
|
+
return null
|
|
66
|
+
},
|
|
62
67
|
async screenshot({ path, clip }) { await page.screenshot({ path, ...(clip ? { clip } : {}) }); return null },
|
|
63
68
|
async close() {
|
|
64
69
|
await context?.close().catch(() => {})
|
package/src/hosts/liteRunner.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { dirname, join } from "node:path"
|
|
|
5
5
|
import { createInterface } from "node:readline"
|
|
6
6
|
import { CliError } from "../cli"
|
|
7
7
|
import { startDevServer, type DevServer } from "../dev/devServer"
|
|
8
|
+
import { filesDirOf } from "../dev/localBackend"
|
|
8
9
|
import type { WebRunner } from "../dev/webRunner"
|
|
9
10
|
import { LECODES_DIR, type Manifest } from "../project/manifest"
|
|
10
11
|
import { distRoot } from "./distRoot"
|
|
@@ -41,6 +42,8 @@ type Driver = {
|
|
|
41
42
|
mouse(action: "move" | "down" | "up" | "wheel", x?: number, y?: number): Promise<void>
|
|
42
43
|
keyboard(action: "type" | "down" | "up", text: string): Promise<void>
|
|
43
44
|
screenshot(path: string, clip: Clip | null): Promise<void>
|
|
45
|
+
/** The files the page's next file dialog is answered with. */
|
|
46
|
+
pick(files: string[]): Promise<void>
|
|
44
47
|
close(): Promise<void>
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -110,6 +113,7 @@ const startDriver = async (): Promise<Driver> => {
|
|
|
110
113
|
mouse: (action, x, y) => call("mouse", { action, x, y }),
|
|
111
114
|
keyboard: (action, text) => call("keyboard", { action, text }),
|
|
112
115
|
screenshot: (path, clip) => call("screenshot", { path, clip }),
|
|
116
|
+
pick: (files) => call("pick", { files }),
|
|
113
117
|
async close() {
|
|
114
118
|
await call("close").catch(() => {})
|
|
115
119
|
child.kill()
|
|
@@ -141,6 +145,7 @@ export const startLiteSession = async (options: { root: string, manifest: Manife
|
|
|
141
145
|
// The project's backend, when it has one: a database of the tests' own, emptied before every case.
|
|
142
146
|
const dbDir = join(options.root, LECODES_DIR, "test-db")
|
|
143
147
|
rmSync(dbDir, { recursive: true, force: true })
|
|
148
|
+
rmSync(filesDirOf(dbDir), { recursive: true, force: true })
|
|
144
149
|
let ran = 0
|
|
145
150
|
const server: DevServer = await startDevServer({
|
|
146
151
|
root: options.root, manifest: options.manifest, name: options.name, lite: options.lite, web: options.web,
|
|
@@ -212,6 +217,17 @@ const ON_SHOW = ".lc-root > .lc:not(.lc-covered)"
|
|
|
212
217
|
|
|
213
218
|
const FRAME = "new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(() => r(null))))"
|
|
214
219
|
|
|
220
|
+
// The page's requests in flight, counted from here on: a command that left one waits for its answer
|
|
221
|
+
// (what the headless session and the native host's script do — one flow file, no `wait` for the backend).
|
|
222
|
+
const COUNT_REQUESTS = `(() => {
|
|
223
|
+
if (window.__lecodesPending !== undefined) return
|
|
224
|
+
window.__lecodesPending = 0
|
|
225
|
+
const send = window.fetch
|
|
226
|
+
window.fetch = (...args) => { window.__lecodesPending++; return send(...args).finally(() => { window.__lecodesPending-- }) }
|
|
227
|
+
})()`
|
|
228
|
+
const SETTLE_MAX_MS = 5000
|
|
229
|
+
const SETTLE_QUIET_FRAMES = 2
|
|
230
|
+
|
|
215
231
|
const FILL_VALUE = `(f) => f.type === "email" ? "test@example.com" : f.type === "tel" ? "5550100" : f.inputMode === "numeric" || f.inputMode === "decimal" ? "1" : f.type === "date" ? "2026-01-01" : f.type === "time" ? "12:00" : "test"`
|
|
216
232
|
|
|
217
233
|
const runPlan = async (driver: Driver, url: string, plan: DesktopPlan, options: LiteRunOptions, page: "lite" | "web"): Promise<string> => {
|
|
@@ -256,11 +272,23 @@ const runPlan = async (driver: Driver, url: string, plan: DesktopPlan, options:
|
|
|
256
272
|
}
|
|
257
273
|
}
|
|
258
274
|
|
|
275
|
+
/** After a command: while a request it left is in flight, and two frames past its answer. */
|
|
276
|
+
const settle = async () => {
|
|
277
|
+
const pending = () => driver.evaluate<number>("window.__lecodesPending || 0")
|
|
278
|
+
if (await pending() === 0) return
|
|
279
|
+
const until = Date.now() + SETTLE_MAX_MS
|
|
280
|
+
for (let quiet = 0; quiet <= SETTLE_QUIET_FRAMES && Date.now() < until;) {
|
|
281
|
+
await frame()
|
|
282
|
+
quiet = await pending() > 0 ? 0 : quiet + 1
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
259
286
|
let clip: Clip | null = null
|
|
260
287
|
|
|
261
288
|
const play = async (op: string, rest: string, line: number): Promise<void> => {
|
|
262
289
|
const args = parseArgs(rest)
|
|
263
290
|
switch (op) {
|
|
291
|
+
case "pick": await driver.pick(args.map(String)); return
|
|
264
292
|
case "frames": await waitFor(Math.max(0, Number(args[0])) * FRAME_MS, line); return
|
|
265
293
|
case "wait": await waitFor(Math.max(0, Number(args[0])), line); return
|
|
266
294
|
case "tap": {
|
|
@@ -405,6 +433,7 @@ const runPlan = async (driver: Driver, url: string, plan: DesktopPlan, options:
|
|
|
405
433
|
try {
|
|
406
434
|
await driver.goto(url)
|
|
407
435
|
await driver.waitFor("window.lecodesTest && window.lecodesTest.ready === true", 20000)
|
|
436
|
+
await driver.evaluate<null>(COUNT_REQUESTS)
|
|
408
437
|
say("[script] loaded")
|
|
409
438
|
const lines = plan.text.split("\n")
|
|
410
439
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -415,6 +444,7 @@ const runPlan = async (driver: Driver, url: string, plan: DesktopPlan, options:
|
|
|
415
444
|
const rest = space < 0 ? "" : text.slice(space + 1)
|
|
416
445
|
try {
|
|
417
446
|
await play(op, rest, i + 1)
|
|
447
|
+
await settle()
|
|
418
448
|
say(`[script] #${i + 1} done ${op}`)
|
|
419
449
|
} catch (e) {
|
|
420
450
|
say(`[script] #${i + 1} error ${op}: ${e instanceof Error ? e.message.split("\n")[0] : String(e)}`)
|
package/src/hosts/peerInstall.ts
CHANGED
|
@@ -48,7 +48,11 @@ export const peerSpec = async (name: string): Promise<string> => {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/** Peers that only make sense together: the renderer's PNG output needs canvas next to it. */
|
|
51
|
-
const companions = (name: string): string[] =>
|
|
51
|
+
const companions = (name: string): string[] =>
|
|
52
|
+
name === "lecodes-headless" ? ["lecodes-headless", "@napi-rs/canvas"]
|
|
53
|
+
// the codec of t.image() fields, and the reader of the one format it does not read (an iPhone's HEIC)
|
|
54
|
+
: name === "sharp" ? ["sharp", "heic-decode"]
|
|
55
|
+
: [name]
|
|
52
56
|
|
|
53
57
|
const manualCommand = (dir: string, specs: string[]) => commandLine(ownManager(), installIntoArgv(ownManager(), dir, specs))
|
|
54
58
|
|
package/src/hosts/peers.ts
CHANGED
|
@@ -24,6 +24,8 @@ export const OPTIONAL_PEERS: [name: string, probe: string][] = [
|
|
|
24
24
|
["lecodes-assets", "lecodes-assets/cli"],
|
|
25
25
|
["@napi-rs/canvas", "@napi-rs/canvas"],
|
|
26
26
|
["marcidb-embedded", "marcidb-embedded"],
|
|
27
|
+
["sharp", "sharp"],
|
|
28
|
+
["heic-decode", "heic-decode"],
|
|
27
29
|
["typescript", "typescript"],
|
|
28
30
|
]
|
|
29
31
|
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var Ts=(async function(_e={}){var Q,t=_e,X,U,fe=new Promise((e,r)=>{X=e,U=r}),Z="./this.program",le=import.meta.url,V="";function be(e){return t.locateFile?t.locateFile(e,V):V+e}var Y;{try{V=new URL(".",le).href}catch{}Y=async e=>{var r=await fetch(e,{credentials:"same-origin"});if(r.ok)return r.arrayBuffer();throw new Error(r.status+" : "+r.url)}}var ee=console.log.bind(console),P=console.error.bind(console),A,x,te=!1,R,m,L,j,W;function re(){var e=x.buffer;R=new Int8Array(e),t.HEAPU8=m=new Uint8Array(e),t.HEAPU16=new Uint16Array(e),t.HEAP32=L=new Int32Array(e),t.HEAPU32=j=new Uint32Array(e),t.HEAPF32=W=new Float32Array(e),t.HEAPF64=new Float64Array(e),new BigInt64Array(e),new BigUint64Array(e)}function he(){if(t.preRun)for(typeof t.preRun=="function"&&(t.preRun=[t.preRun]);t.preRun.length;)Te(t.preRun.shift());ne(oe)}function ve(){o.Bc()}function je(){if(t.postRun)for(typeof t.postRun=="function"&&(t.postRun=[t.postRun]);t.postRun.length;)We(t.postRun.shift());ne(se)}var k=0,N=null;function de(e){var r;k++,(r=t.monitorRunDependencies)==null||r.call(t,k)}function ge(e){var n;if(k--,(n=t.monitorRunDependencies)==null||n.call(t,k),k==0&&N){var r=N;N=null,r()}}function $(e){var n;(n=t.onAbort)==null||n.call(t,e),e="Aborted("+e+")",P(e),te=!0,e+=". Build with -sASSERTIONS for more info.";var r=new WebAssembly.RuntimeError(e);throw U(r),r}var H;function pe(){return t.locateFile?be("creator-ui.wasm"):new URL(""+new URL("creator-ui-DZaoxIpX.wasm",import.meta.url).href,import.meta.url).href}function ye(e){if(e==H&&A)return new Uint8Array(A);throw"both async and sync fetching of the wasm failed"}async function we(e){if(!A)try{var r=await Y(e);return new Uint8Array(r)}catch{}return ye(e)}async function me(e,r){try{var n=await we(e),s=await WebAssembly.instantiate(n,r);return s}catch(i){P(`failed to asynchronously prepare wasm: ${i}`),$(i)}}async function ke(e,r,n){if(!e&&typeof WebAssembly.instantiateStreaming=="function")try{var s=fetch(r,{credentials:"same-origin"}),i=await WebAssembly.instantiateStreaming(s,n);return i}catch(a){P(`wasm streaming compile failed: ${a}`),P("falling back to ArrayBuffer instantiation")}return me(r,n)}function Se(){return{a:Vn}}async function Pe(){function e(a,c){return o=a.exports,x=o.Ac,re(),T=o.Cc,ge(),o}de();function r(a){return e(a.instance)}var n=Se();if(t.instantiateWasm)return new Promise((a,c)=>{t.instantiateWasm(n,(_,f)=>{a(e(_))})});H??(H=pe());try{var s=await ke(A,H,n),i=r(s);return i}catch(a){return U(a),Promise.reject(a)}}var ne=e=>{for(;e.length>0;)e.shift()(t)},se=[],We=e=>se.push(e),oe=[],Te=e=>oe.push(e),h=e=>Dn(e),v=()=>Mn(),B=[],Ae=e=>{var r=new D(e);return r.get_caught()||r.set_caught(!0),r.set_rethrown(!1),B.push(r),zn(e),Jn(e)},w=0,Re=()=>{b(0,0);var e=B.pop();Gn(e.excPtr),w=0};class D{constructor(r){this.excPtr=r,this.ptr=r-24}set_type(r){j[this.ptr+4>>2]=r}get_type(){return j[this.ptr+4>>2]}set_destructor(r){j[this.ptr+8>>2]=r}get_destructor(){return j[this.ptr+8>>2]}set_caught(r){r=r?1:0,R[this.ptr+12]=r}get_caught(){return R[this.ptr+12]!=0}set_rethrown(r){r=r?1:0,R[this.ptr+13]=r}get_rethrown(){return R[this.ptr+13]!=0}init(r,n){this.set_adjusted_ptr(0),this.set_type(r),this.set_destructor(n)}set_adjusted_ptr(r){j[this.ptr+16>>2]=r}get_adjusted_ptr(){return j[this.ptr+16>>2]}}var I=e=>Hn(e),ie=e=>{var r=w;if(!r)return I(0),0;var n=new D(r);n.set_adjusted_ptr(r);var s=n.get_type();if(!s)return I(0),r;for(var i of e){if(i===0||i===s)break;var a=n.ptr+16;if(Kn(i,s,a))return I(i),r}return I(s),r},Ne=()=>ie([]),Ee=e=>ie([e]),Fe=()=>{var e=B.pop();e||$("no exception to throw");var r=e.excPtr;throw e.get_rethrown()||(B.push(e),e.set_rethrown(!0),e.set_caught(!1)),w=r,w},Ce=(e,r,n)=>{var s=new D(e);throw s.init(r,n),w=e,w},xe=e=>{throw w||(w=e),w},Le=()=>$(""),Be=()=>2147483648,Ie=(e,r)=>Math.ceil(e/r)*r,Oe=e=>{var r=x.buffer,n=(e-r.byteLength+65535)/65536|0;try{return x.grow(n),re(),1}catch{}},Ue=e=>{var r=m.length;e>>>=0;var n=Be();if(e>n)return!1;for(var s=1;s<=4;s*=2){var i=r*(1+.2/s);i=Math.min(i,e+100663296);var a=Math.min(n,Ie(Math.max(e,i),65536)),c=Oe(a);if(c)return!0}return!1},O={},Ve=()=>Z||"./this.program",E=()=>{if(!E.strings){var e=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8",r={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:e,_:Ve()};for(var n in O)O[n]===void 0?delete r[n]:r[n]=O[n];var s=[];for(var n in r)s.push(`${n}=${r[n]}`);E.strings=s}return E.strings},$e=(e,r,n,s)=>{if(!(s>0))return 0;for(var i=n,a=n+s-1,c=0;c<e.length;++c){var _=e.charCodeAt(c);if(_>=55296&&_<=57343){var f=e.charCodeAt(++c);_=65536+((_&1023)<<10)|f&1023}if(_<=127){if(n>=a)break;r[n++]=_}else if(_<=2047){if(n+1>=a)break;r[n++]=192|_>>6,r[n++]=128|_&63}else if(_<=65535){if(n+2>=a)break;r[n++]=224|_>>12,r[n++]=128|_>>6&63,r[n++]=128|_&63}else{if(n+3>=a)break;r[n++]=240|_>>18,r[n++]=128|_>>12&63,r[n++]=128|_>>6&63,r[n++]=128|_&63}}return r[n]=0,n-i},M=(e,r,n)=>$e(e,m,r,n),He=(e,r)=>{var n=0,s=0;for(var i of E()){var a=r+n;j[e+s>>2]=a,n+=M(i,a,1/0)+1,s+=4}return 0},G=e=>{for(var r=0,n=0;n<e.length;++n){var s=e.charCodeAt(n);s<=127?r++:s<=2047?r+=2:s>=55296&&s<=57343?(r+=4,++n):r+=3}return r},De=(e,r)=>{var n=E();j[e>>2]=n.length;var s=0;for(var i of n)s+=G(i)+1;return j[r>>2]=s,0},Me=e=>52;function Ge(e,r,n,s){return 70}var ze=[null,[],[]],ae=typeof TextDecoder<"u"?new TextDecoder:void 0,ce=(e,r=0,n=NaN)=>{for(var s=r+n,i=r;e[i]&&!(i>=s);)++i;if(i-r>16&&e.buffer&&ae)return ae.decode(e.subarray(r,i));for(var a="";r<i;){var c=e[r++];if(!(c&128)){a+=String.fromCharCode(c);continue}var _=e[r++]&63;if((c&224)==192){a+=String.fromCharCode((c&31)<<6|_);continue}var f=e[r++]&63;if((c&240)==224?c=(c&15)<<12|_<<6|f:c=(c&7)<<18|_<<12|f<<6|e[r++]&63,c<65536)a+=String.fromCharCode(c);else{var d=c-65536;a+=String.fromCharCode(55296|d>>10,56320|d&1023)}}return a},Ke=(e,r)=>{var n=ze[e];r===0||r===10?((e===1?ee:P)(ce(n)),n.length=0):n.push(r)},u=(e,r)=>e?ce(m,e,r):"",Je=(e,r,n,s)=>{for(var i=0,a=0;a<n;a++){var c=j[r>>2],_=j[r+4>>2];r+=8;for(var f=0;f<_;f++)Ke(e,m[c+f]);i+=_}return j[s>>2]=i,0},T,l=e=>T.get(e),F=e=>{var r=G(e)+1,n=$n(r);return n&&M(e,n,r),n},ue=(e,r)=>{e<128?r.push(e):r.push(e%128|128,e>>7)},qe=e=>{for(var r={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"},n={parameters:[],results:e[0]=="v"?[]:[r[e[0]]]},s=1;s<e.length;++s)n.parameters.push(r[e[s]]);return n},Qe=(e,r)=>{var n=e.slice(0,1),s=e.slice(1),i={i:127,p:127,j:126,f:125,d:124,e:111};r.push(96),ue(s.length,r);for(var a of s)r.push(i[a]);n=="v"?r.push(0):r.push(1,i[n])},Xe=(e,r)=>{if(typeof WebAssembly.Function=="function")return new WebAssembly.Function(qe(r),e);var n=[1];Qe(r,n);var s=[0,97,115,109,1,0,0,0,1];ue(n.length,s),s.push(...n),s.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var i=new WebAssembly.Module(new Uint8Array(s)),a=new WebAssembly.Instance(i,{e:{f:e}}),c=a.exports.f;return c},Ze=(e,r)=>{if(S)for(var n=e;n<e+r;n++){var s=l(n);s&&S.set(s,n)}},S,Ye=e=>(S||(S=new WeakMap,Ze(0,T.length)),S.get(e)||0),z=[],et=()=>{if(z.length)return z.pop();try{T.grow(1)}catch(e){throw e instanceof RangeError?"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.":e}return T.length-1},K=(e,r)=>T.set(e,r),tt=(e,r)=>{var n=Ye(e);if(n)return n;var s=et();try{K(s,e)}catch(a){if(!(a instanceof TypeError))throw a;var i=Xe(e,r);K(s,i)}return S.set(e,s),s},rt=e=>{S.delete(l(e)),K(e,null),z.push(e)};t.noExitRuntime&&t.noExitRuntime,t.print&&(ee=t.print),t.printErr&&(P=t.printErr),t.wasmBinary&&(A=t.wasmBinary),t.arguments&&t.arguments,t.thisProgram&&(Z=t.thisProgram),t.ENV=O,t.addFunction=tt,t.removeFunction=rt,t.UTF8ToString=u,t.stringToUTF8=M,t.lengthBytesUTF8=G,t.stringToNewUTF8=F;function nt(e){t.jsb._init(e)}function st(e){t.jsb.dup(e)}function ot(e){t.jsb.release(e)}function it(e){t.jsb.global(e)}function at(e,r,n){t.jsb.get(e,r,u(n))}function ct(e,r,n){t.jsb.getIndex(e,r,n)}function ut(e,r,n){return t.jsb.has(e,r,u(n))?1:0}function _t(e,r,n,s){t.jsb.set(e,u(r),n,s)}function ft(e,r,n,s){t.jsb.setIndex(e,r,n,s)}function lt(e,r,n){return t.jsb.keys(e,r,n)}function bt(e,r){t.jsb.newObject(e,r)}function ht(){t.jsb.newArray()}function vt(e,r){t.jsb.newString(u(e,r))}function jt(e,r,n){return t.jsb.str(e,r,n)}function dt(e,r){return t.jsb.logString(e,r)}function gt(e){return t.jsb.toNumber(e)}function pt(e){return t.jsb.truthy(e)?1:0}function yt(e){t.jsb.newError(u(e))}function wt(e,r){t.jsb.throwNew(e,u(r))}function mt(){t.jsb.takeException()}function kt(e,r,n,s,i,a){t.jsb.call(e,r,n,s,i,a)}function St(e,r,n,s){t.jsb.eval(e,u(r,n),u(s))}function Pt(){return t.jsb.newContext()}function Wt(e){t.jsb.freeContext(e)}function Tt(e,r){t.jsb.parseJson(u(e,r))}function At(e,r,n){t.jsb.typedArray(e,r,n)}function Rt(e,r,n,s){return t.jsb.arrayIn(e,r,n,s)}function Nt(e,r,n){t.jsb.arrayOut(e,r,n)}function Et(e,r,n,s){t.jsb.makeFunction(e,r,n?u(n):"",s)}function Ft(e,r,n,s,i,a){t.jsb.defineMethod(e,r,u(n),s,i,a)}function Ct(){t.jsb.gc()}function xt(e){return t.jsb.host[u(e)]?1:0}function Lt(e,r){const n=t.jsb.host[u(e)];return n&&typeof n[u(r)]=="function"?1:0}function Bt(e,r){const n=t.jsb.host[u(e)],s=n?n[u(r)]:void 0;return s==null?0:F(String(s))}function It(e,r){const n=t.jsb.host[u(e)],s=n?Number(n[u(r)]):0;return s===s?s:0}function Ot(){return t.jsb.host.gl.getGLContext()|0}function Ut(){t.jsb.host.gl.engineCreated()}function Vt(){t.jsb.host.gl.createGLView()}function $t(){t.jsb.host.gl.closeScene()}function Ht(e,r,n,s){const i=t.jsb.group(n,s);t.jsb.host.gl.createTexture(e,r,t.jsb.callback(n,i),t.jsb.callback(s,i))}function Dt(e){return t.jsb.host.gl.createMediaPlayerTexture(e)||0}function Mt(e,r,n){const s=t.jsb.group(r,n);t.jsb.host.gl.launchAR(e,t.jsb.callback(r,s),t.jsb.callback(n,s))}function Gt(){t.jsb.host.gl.stopAR()}function zt(e,r,n){const s=t.jsb.group(r,n);t.jsb.host.gl.launchVR(e,t.jsb.callback(r,s),t.jsb.callback(n,s))}function Kt(){t.jsb.host.gl.stopVR()}function Jt(e,r,n){t.jsb.host.gl.createARController(e,r,n?u(n):null)}function qt(e,r){t.jsb.host.gl.createRootAnchor(e,r)}function Qt(e,r,n,s){t.jsb.host.gl.createAnchor(e,r,n,s)}function Xt(e){t.jsb.host.scene2d.open2DScene(e)}function Zt(){t.jsb.host.scene2d.close2DScene()}function Yt(){t.jsb.host.scene2d.init2D()}function er(e,r,n,s){t.jsb.host.ui.nodeFactory(e,r?u(r):null,n,s)}function tr(e,r,n){t.jsb.host.ui.setPropertyString(e,r?u(r):null,n?u(n):null)}function rr(e,r,n){t.jsb.host.ui.setPropertyInt(e,r?u(r):null,n)}function nr(e,r){t.jsb.host.ui.setFlags(e,r)}function sr(e,r,n){t.jsb.host.ui.insertNode(e,r,n)}function or(e,r){t.jsb.host.ui.removeNode(e,r)}function ir(e){t.jsb.host.ui.releaseNode(e)}function ar(e,r,n,s,i,a){t.jsb.host.ui.openView(e,r,n,s?u(s):null,i?u(i):null,!!a)}function cr(e,r,n){t.jsb.host.ui.dropView(e,r,n)}function ur(){t.jsb.host.ui.closeView()}function _r(e){return t.jsb.host.ui.isViewSupported(e?u(e):null)?1:0}function fr(e){return t.jsb.host.ui.viewVersion(e?u(e):null)||0}function lr(e,r,n,s,i){const a=t.jsb.group(s,i);t.jsb.host.ui.viewCall(e,r?u(r):null,t.jsb.valueAt(n),t.jsb.callback(s,a),t.jsb.callback(i,a))}function br(e,r,n,s){t.jsb.host.ui.widgetOpen(e,r,n,s)}function hr(e){t.jsb.host.ui.widgetClose(e)}function vr(e,r,n,s,i,a){const c=t.jsb.group(i,a);t.jsb.host.ui.registerFont(e?u(e):null,r?u(r):null,n,s,t.jsb.callback(i,c),t.jsb.callback(a,c))}function jr(e,r){t.jsb.host.ui.showToast(e?u(e):null,r)}function dr(e){return t.jsb.host.ui.getButtonPressed(e)?1:0}function gr(e){const r=t.jsb.host.ui.getTextValue(e);return r==null?0:F(String(r))}function pr(e,r){const n=t.jsb.host.ui.getBoundingRect(e);if(!n)return 0;for(let s=0;s<4;s++)W[(r>>2)+s]=n[s]||0;return 1}function yr(e,r,n,s){t.jsb.host.ui.touchHandler(e,!!r,n,s)}function wr(e,r){t.jsb.host.ui.longPressHandler(e,r)}function mr(e,r,n){t.jsb.host.ui.vlistScroll(e,r,!!n)}function kr(e,r,n){t.jsb.host.ui.pagerCommand(e,r?u(r):null,!!n)}function Sr(e,r,n){t.jsb.host.ui.pagerShowPage(e,r,!!n)}function Pr(e,r){t.jsb.host.ui.pagerDropPage(e,r)}function Wr(e,r){t.jsb.host.ui.pagerPageMounted(e,!!r)}function Tr(e,r,n,s,i,a,c,_,f,d){return t.jsb.host.ui.tweenClaim(e,r?u(r):null,n,W.subarray(s>>2,(s>>2)+i),a,c,_,!!f,d)?1:0}function Ar(e,r,n){t.jsb.host.ui.tweenRelease(e,r?u(r):null,n)}function Rr(e,r,n,s,i,a,c,_){t.jsb.host.canvas.paint(e,r,n,s,W.subarray(i>>2,(i>>2)+a),t.jsb.strings(c,_))}function Nr(e,r,n,s,i,a){t.jsb.host.canvas.measureText(e?u(e):null,r?u(r):null,n,s,!!i,W.subarray(a>>2,(a>>2)+16))}function Er(e,r,n){return t.jsb.host.canvas.decodeImage(e,r,L.subarray(n>>2,(n>>2)+16))?1:0}function Fr(e,r){const n=t.jsb.host.canvas.readPixels(e,L.subarray(r>>2,(r>>2)+16));return t.jsb.bytesOut(n,0)}function Cr(e){t.jsb.host.canvas.releaseSurface(e)}function xr(){const e=t.jsb.host.app.state();return e==null?0:F(String(e))}function Lr(){return t.jsb.host.app.isOnline()?1:0}function Br(e){t.jsb.host.app.openUrl(e?u(e):null)}function Ir(e){t.jsb.host.app.setOrientation(e?u(e):null)}function Or(e,r){t.jsb.host.app.worldChange(e?u(e):null,!!r)}function Ur(){t.jsb.host.app.exit()}function Vr(e){t.jsb.host.device.setPreciseTouch(!!e)}function $r(e){t.jsb.host.device.vibrate(e?u(e):null)}function Hr(e){t.jsb.host.device.setStatsOverlay(!!e)}function Dr(){return t.jsb.host.device.statsOverlay()?1:0}function Mr(){return t.jsb.host.device.motionAvailable()?1:0}function Gr(e){return t.jsb.host.device.motionStart(e)?1:0}function zr(){t.jsb.host.device.motionStop()}function Kr(e){const r=t.jsb.host.device.motionSample();if(!r)return 0;for(let n=0;n<8;n++)W[(e>>2)+n]=r[n]||0;return 1}function Jr(e){t.jsb.host.device.clipboardWrite(e?u(e):null)}function qr(e,r){const n=t.jsb.group(e,r);t.jsb.host.device.clipboardRead(t.jsb.callback(e,n),t.jsb.callback(r,n))}function Qr(e,r){t.jsb.host.device.share(e,r?u(r):null)}function Xr(e,r,n,s){const i=t.jsb.group(e,r);t.jsb.host.device.openFilePicker(t.jsb.callback(e,i),t.jsb.callback(r,i),!!n,s?u(s):null)}function Zr(e,r){const n=t.jsb.group(e,r);t.jsb.host.device.requestCamera(t.jsb.callback(e,n),t.jsb.callback(r,n))}function Yr(e){return t.jsb.host.fetch.local(e?u(e):null)||0}function en(e){t.jsb.host.fetch.dispose(e)}function tn(e,r,n,s,i,a,c,_,f,d){const g=t.jsb.group(_,f,d);t.jsb.host.fetch.request(e?u(e):null,r?u(r):null,t.jsb.strings(n,s),i?u(i):null,Array.from({length:c},(y,p)=>({key:j[a+p*16+0>>2]?u(j[a+p*16+0>>2]):null,value:j[a+p*16+4>>2]?u(j[a+p*16+4>>2]):null,bufferId:L[a+p*16+8>>2],filename:j[a+p*16+12>>2]?u(j[a+p*16+12>>2]):null})),t.jsb.callback(_,g),t.jsb.callback(f,g),t.jsb.callback(d,g))}function rn(e,r,n){const s=t.jsb.host.fetch.buffer(e,!!r);return t.jsb.bytesOut(s,n)}function nn(e,r,n,s,i){const a=t.jsb.host.fetch.bufferSlice(e,r,n,!!s);return t.jsb.bytesOut(a,i)}function sn(e,r){const n=t.jsb.host.fetch.systemBuffer(e);return t.jsb.bytesOut(n,r)}function on(e,r){return t.jsb.host.fetch.putBuffer(m.subarray(e,e+r))||0}function an(e,r,n){const s=t.jsb.group(r,n);t.jsb.host.files.readBytes(e?u(e):null,t.jsb.callback(r,s),t.jsb.callback(n,s))}function cn(e,r,n){const s=t.jsb.group(r,n);t.jsb.host.files.readText(e?u(e):null,t.jsb.callback(r,s),t.jsb.callback(n,s))}function un(e,r,n,s){const i=t.jsb.group(n,s);t.jsb.host.files.remove(e?u(e):null,!!r,t.jsb.callback(n,i),t.jsb.callback(s,i))}function _n(e,r,n){const s=t.jsb.group(r,n);t.jsb.host.files.mkdir(e?u(e):null,t.jsb.callback(r,s),t.jsb.callback(n,s))}function fn(e,r,n,s){const i=t.jsb.group(n,s);t.jsb.host.files.list(e?u(e):null,!!r,t.jsb.callback(n,i),t.jsb.callback(s,i))}function ln(e,r,n){const s=t.jsb.group(r,n);t.jsb.host.files.stat(e?u(e):null,t.jsb.callback(r,s),t.jsb.callback(n,s))}function bn(e,r,n,s,i,a){const c=t.jsb.group(i,a);t.jsb.host.files.write(e?u(e):null,m.subarray(r,r+n),!!s,t.jsb.callback(i,c),t.jsb.callback(a,c))}function hn(e){const r=t.jsb.host.storage.load(e?u(e):null);return r==null?0:F(String(r))}function vn(e,r){t.jsb.host.storage.save(e?u(e):null,r?u(r):null)}function jn(e,r){t.jsb.host.socket.send(e,r?u(r):null)}function dn(e,r){return t.jsb.host.socket.open(e?u(e):null,t.jsb.callback(r,null))||0}function gn(e){t.jsb.host.socket.close(e)}function pn(e){return t.jsb.host.service.supported(e?u(e):null)?1:0}function yn(e,r,n){return t.jsb.host.service.open(e?u(e):null,r?u(r):null,t.jsb.callback(n,null))||0}function wn(e){t.jsb.host.service.close(e)}function mn(e){return t.jsb.host.service.version(e?u(e):null)||0}function kn(e,r,n,s,i){const a=t.jsb.group(s,i);t.jsb.host.service.call(e,r?u(r):null,t.jsb.valueAt(n),t.jsb.callback(s,a),t.jsb.callback(i,a))}function Sn(e,r){return t.jsb.host.input.key(e?u(e):null,r)?1:0}function Pn(e){return t.jsb.host.input.read(e)||0}function Wn(e){return t.jsb.host.input.setPointerLock(!!e)?1:0}function Tn(e,r,n,s){return t.jsb.host.input.rumble(e,r,n,s)?1:0}function An(){return t.jsb.host.input.keyboardHeight()||0}function Rn(e,r){t.jsb.host.media.setVolume(e,r)}function Nn(e){return t.jsb.host.media.time(e)||0}function En(e,r){t.jsb.host.media.setTime(e,r)}function Fn(e){return t.jsb.host.media.duration(e)||0}function Cn(e,r){return t.jsb.host.media.createAudio(e?u(e):null,t.jsb.callback(r,null))||0}function xn(e,r){return t.jsb.host.media.createVideo(e?u(e):null,t.jsb.callback(r,null))||0}function Ln(e,r){t.jsb.host.media.setLoop(e,!!r)}function Bn(e,r){t.jsb.host.media.setPlaying(e,!!r)}function In(e){t.jsb.host.media.remove(e)}function On(e){console.error(u(e))}function Un(e){const r=t.jsb.host.ui;r.refreshDone&&r.refreshDone(e)}var Vn={D:Ae,zb:Re,a:Ne,m:Ee,Ab:Fe,x:Ce,e:xe,qb:Le,xb:On,lb:Ue,nb:He,ob:De,pb:Me,mb:Ge,H:Je,p:ns,K:Yn,l:us,i:cs,j:as,I:hs,d:Xn,z:_s,g:qn,t:gs,u:ls,vb:ms,J:rs,wb:ps,o:vs,c:Qn,s:is,ub:ks,n:ts,f:ss,v:ys,Db:os,k:bs,Bb:fs,Eb:es,h:Zn,tb:Ss,C:js,w:ws,y:ds,Jb:Rt,Fb:Nt,hb:kt,fb:Ft,A:st,$a:St,ab:Wt,bb:Ct,Cb:at,yb:ct,jb:it,sb:ut,db:nt,kb:lt,gb:dt,eb:Et,zc:ht,cb:Pt,da:yt,E:bt,oa:vt,ib:Tt,r:ot,oc:_t,dc:ft,za:jt,G:mt,B:wt,Va:gt,Ka:pt,Ub:At,U:Ur,Y:Lr,X:Br,W:Ir,Z:xr,V:Or,aa:Er,ba:Nr,ca:Rr,$:Fr,_:Cr,yc:qr,L:Jr,P:Mr,M:Kr,O:Gr,N:zr,wc:Xr,vc:Zr,T:Vr,R:Hr,xc:Qr,Q:Dr,S:$r,rc:rn,qc:nn,tc:en,uc:Yr,nc:on,sc:tn,pc:sn,_a:It,F:Bt,ic:fn,jc:_n,mc:an,lc:cn,kc:un,hc:ln,gc:bn,Wa:$t,Oa:Jt,Ma:Qt,Xa:Vt,Ta:Dt,Na:qt,Ua:Ht,Ya:Ut,Za:Ot,Sa:Mt,Qa:zt,Ra:Gt,Pa:Kt,b:Lt,Xb:Sn,Sb:An,Wb:Pn,Tb:Tn,Vb:Wn,Nb:Cn,Mb:xn,Ob:Fn,Ib:In,Lb:Ln,Kb:Bn,Pb:En,Rb:Rn,Qb:Nn,rb:Un,Ja:Zt,Ia:Yt,La:Xt,Gb:kn,Zb:wn,_b:yn,$b:pn,Yb:mn,ac:gn,bc:dn,cc:jn,fc:hn,ec:vn,q:xt,xa:ur,ya:cr,na:pr,qa:dr,pa:gr,Da:sr,wa:_r,la:wr,Ha:er,Aa:ar,ja:kr,ha:Pr,ga:Wr,ia:Sr,sa:vr,Ba:ir,Ca:or,Ea:nr,Fa:rr,Ga:tr,ra:jr,ma:yr,fa:Tr,ea:Ar,Hb:lr,va:fr,ka:mr,ta:hr,ua:br},o=await Pe();o.Bc,t._free=o.Dc,t._setNodeClass=o.Ec,t._applyTheme=o.Fc,t._applyNodeTheme=o.Gc,t._setNodeThemeValue=o.Hc,t._setThemeValue=o.Ic,t._getScreenId=o.Jc,t._getParentNode=o.Kc;var $n=t._malloc=o.Lc;t._jsbInvoke=o.Mc,t._jsbInvokeGetter=o.Nc,t._jsbInvokeData=o.Oc,t._jsbFunctionGone=o.Pc,t._jsbFinalize=o.Qc,t._jsbHostCall=o.Rc,t._jsbRejection=o.Sc,t._calculate=o.Tc,t._widgetDetach=o.Uc,t._recalculate=o.Vc,t._calculateRoot=o.Wc,t._calculateWidget=o.Xc,t._collectBegin=o.Yc,t._collectRoot=o.Zc,t._collectCount=o._c,t._jsbViewEvent=o.$c,t._getNodeOwner=o.ad,t._createNodeRoot=o.bd,t._setNodeMeasure=o.cd,t._setNodeThemeRoot=o.dd,t._setNodeOwner=o.ed,t._forEachNode=o.fd,t._freeNode=o.gd,t._vlistExists=o.hd,t._adoptNode=o.id,t._detachNode=o.jd,t._cuiChildCount=o.kd,t._cuiChildAt=o.ld,t._setStringExt=o.md,t._resetPropExt=o.nd,t._nodeHasMeasure=o.od,t._nodeHasFixedSize=o.pd,t._markNodeDirty=o.qd,t._setNodeInteractive=o.rd,t._setFloatExt=o.sd,t._getLayer=o.td,t._setNodeHovered=o.ud,t._cuiPaintJson=o.vd,t._setVListHandlers=o.wd,t._vlistInit=o.xd,t._vlistFree=o.yd,t._vlistSetKeys=o.zd,t._vlistInsertKeys=o.Ad,t._vlistRemoveKeys=o.Bd,t._vlistInvalidate=o.Cd,t._vlistCreateItemRoot=o.Dd,t._vlistItemMounted=o.Ed,t._vlistItemUnmounted=o.Fd,t._vlistToPhysical=o.Gd,t._getContentHeight=o.Hd,t._vlistOffsetOf=o.Id,t._setNodeThemeHost=o.Jd,t._setMeasureFunc=o.Kd,t._createNode=o.Ld,t._cuiStringOf=o.Md,t._removeNode=o.Nd,t._paintCollect=o.Od,t._paintNodes=o.Pd,t._paintRecords=o.Qd,t._cuiPaintOf=o.Rd,t._cuiGradientOf=o.Sd,t._getColor=o.Td,t._setFloat=o.Ud,t._setString=o.Vd,t._resetProp=o.Wd,t._enableNodeLayer=o.Xd,t._disableNodeLayer=o.Yd,t._resetNodeLayer=o.Zd,t._mergeNodeLayer=o._d,t._setNodePressed=o.$d,t._setNodeFocused=o.ae,t._setConditionValue=o.be,t._freeWidget=o.ce,t._setSafePaddings=o.de,t._overrideRootSafeBottom=o.ee,t._setSafeAreaBars=o.fe,t._getThemeValue=o.ge,t._consumeNeedsLayout=o.he,t._getCachedRoot=o.ie,t._collectNodes=o.je,t._collectRects=o.ke,t._getOffset=o.le,t._getContentWidth=o.me,t._getLayoutPointer=o.ne,t._getLayoutDOMPointer=o.oe,t._getPaddingPointer=o.pe,t._vlistOnScroll=o.qe,t._vlistUpdateLayout=o.re,t._vlistItemOffsetOf=o.se,t._creatorWebVersion=o.te,t._creatorWebInit=o.ue,t._creatorWebRun=o.ve,t._creatorWebTick=o.we,t._creatorWebTickCore=o.xe,t._creatorWebResize=o.ye,t._creatorWebLayoutFrame=o.ze,t._creatorWebDebugDump=o.Ae,t._creatorWebBackPressed=o.Be,t._creatorWebSetStepEveryTick=o.Ce,t._creatorWebSceneOpen=o.De,t._creatorWebFrameRendered=o.Ee,t._creatorWebSetViewport=o.Fe,t._creatorWebSceneRenderScale=o.Ge,t._creatorWebAppEvent=o.He,t._creatorWebInputEvent=o.Ie,t._creatorWebKeyboardEvent=o.Je,t._creatorWebSetLaunchUrl=o.Ke,t._creatorWebSetBootProjectUuid=o.Le,t._creatorWebQuitToLauncher=o.Me,t._creatorWebViewEvent=o.Ne,t._creatorWebNodeEvent=o.Oe,t._creatorWebNodeEventNum=o.Pe,t._creatorWebNodeEventStr=o.Qe,t._creatorWebNodeLayout=o.Re,t._creatorWebNodeScroll=o.Se,t._creatorWebNodeTouchStart=o.Te,t._creatorWebNodeLongPress=o.Ue,t._creatorWebNodeClick=o.Ve,t._creatorWebTouchMove=o.We,t._creatorWebTouchEnd=o.Xe,t._creatorWebTouchCancel=o.Ye,t._creatorWebRefresh=o.Ze,t._creatorWebHover=o._e,t._creatorWebSceneTouchStart=o.$e,t._creatorWebSceneTouchClick=o.af,t._creatorWebSetShrunkRoot=o.bf,t._creatorWebSetWidgetBox=o.cf,t._creatorWebRootLayoutHeight=o.df,t._creatorWebPagerLayoutPages=o.ef,t._creatorWebPagerDidSelect=o.ff,t._creatorWebPagerTabCount=o.gf,t._creatorWebPagerSelectedIndex=o.hf,t._creatorWebPagerStackLen=o.jf,t._creatorWebPagerPageNode=o.kf,t._creatorWeb2dEnsureInited=o.lf,t._creatorWeb2dSceneOpen=o.mf,t._creatorWeb2dRenderFrame=o.nf,t._creatorWeb2dEmitPointer=o.of;var b=o.pf,Hn=o.qf,Dn=o.rf,Mn=o.sf,Gn=o.tf,zn=o.uf,Kn=o.vf,Jn=o.wf;function qn(e,r,n){var s=v();try{return l(e)(r,n)}catch(i){if(h(s),i!==i+0)throw i;b(1,0)}}function Qn(e,r){var n=v();try{l(e)(r)}catch(s){if(h(n),s!==s+0)throw s;b(1,0)}}function Xn(e,r){var n=v();try{return l(e)(r)}catch(s){if(h(n),s!==s+0)throw s;b(1,0)}}function Zn(e,r,n,s,i){var a=v();try{l(e)(r,n,s,i)}catch(c){if(h(a),c!==c+0)throw c;b(1,0)}}function Yn(e,r,n){var s=v();try{return l(e)(r,n)}catch(i){if(h(s),i!==i+0)throw i;b(1,0)}}function es(e,r,n,s,i,a,c,_,f,d,g){var y=v();try{l(e)(r,n,s,i,a,c,_,f,d,g)}catch(p){if(h(y),p!==p+0)throw p;b(1,0)}}function ts(e,r,n,s){var i=v();try{l(e)(r,n,s)}catch(a){if(h(i),a!==a+0)throw a;b(1,0)}}function rs(e,r,n,s,i,a,c,_,f,d,g,y){var p=v();try{return l(e)(r,n,s,i,a,c,_,f,d,g,y)}catch(C){if(h(p),C!==C+0)throw C;b(1,0)}}function ns(e,r){var n=v();try{return l(e)(r)}catch(s){if(h(n),s!==s+0)throw s;b(1,0)}}function ss(e,r,n){var s=v();try{l(e)(r,n)}catch(i){if(h(s),i!==i+0)throw i;b(1,0)}}function os(e,r,n,s,i){var a=v();try{l(e)(r,n,s,i)}catch(c){if(h(a),c!==c+0)throw c;b(1,0)}}function is(e,r,n){var s=v();try{l(e)(r,n)}catch(i){if(h(s),i!==i+0)throw i;b(1,0)}}function as(e,r,n,s,i,a){var c=v();try{return l(e)(r,n,s,i,a)}catch(_){if(h(c),_!==_+0)throw _;b(1,0)}}function cs(e,r,n,s,i){var a=v();try{return l(e)(r,n,s,i)}catch(c){if(h(a),c!==c+0)throw c;b(1,0)}}function us(e,r,n,s){var i=v();try{return l(e)(r,n,s)}catch(a){if(h(i),a!==a+0)throw a;b(1,0)}}function _s(e,r,n,s,i,a,c,_,f,d,g,y,p,C){var Ws=v();try{return l(e)(r,n,s,i,a,c,_,f,d,g,y,p,C)}catch(q){if(h(Ws),q!==q+0)throw q;b(1,0)}}function fs(e,r,n,s,i,a,c,_,f,d){var g=v();try{l(e)(r,n,s,i,a,c,_,f,d)}catch(y){if(h(g),y!==y+0)throw y;b(1,0)}}function ls(e,r,n,s,i){var a=v();try{return l(e)(r,n,s,i)}catch(c){if(h(a),c!==c+0)throw c;b(1,0)}}function bs(e,r,n,s){var i=v();try{l(e)(r,n,s)}catch(a){if(h(i),a!==a+0)throw a;b(1,0)}}function hs(e,r,n,s,i,a,c){var _=v();try{return l(e)(r,n,s,i,a,c)}catch(f){if(h(_),f!==f+0)throw f;b(1,0)}}function vs(e){var r=v();try{l(e)()}catch(n){if(h(r),n!==n+0)throw n;b(1,0)}}function js(e,r,n,s,i,a){var c=v();try{l(e)(r,n,s,i,a)}catch(_){if(h(c),_!==_+0)throw _;b(1,0)}}function ds(e,r,n,s,i,a,c,_,f){var d=v();try{l(e)(r,n,s,i,a,c,_,f)}catch(g){if(h(d),g!==g+0)throw g;b(1,0)}}function gs(e,r,n,s){var i=v();try{return l(e)(r,n,s)}catch(a){if(h(i),a!==a+0)throw a;b(1,0)}}function ps(e,r,n,s,i,a,c,_,f,d){var g=v();try{return l(e)(r,n,s,i,a,c,_,f,d)}catch(y){if(h(g),y!==y+0)throw y;b(1,0)}}function ys(e,r,n,s){var i=v();try{l(e)(r,n,s)}catch(a){if(h(i),a!==a+0)throw a;b(1,0)}}function ws(e,r,n,s,i,a,c){var _=v();try{l(e)(r,n,s,i,a,c)}catch(f){if(h(_),f!==f+0)throw f;b(1,0)}}function ms(e,r,n,s,i,a){var c=v();try{return l(e)(r,n,s,i,a)}catch(_){if(h(c),_!==_+0)throw _;b(1,0)}}function ks(e,r,n,s,i){var a=v();try{l(e)(r,n,s,i)}catch(c){if(h(a),c!==c+0)throw c;b(1,0)}}function Ss(e,r,n,s,i,a){var c=v();try{l(e)(r,n,s,i,a)}catch(_){if(h(c),_!==_+0)throw _;b(1,0)}}function J(){if(k>0){N=J;return}if(he(),k>0){N=J;return}function e(){var r;t.calledRun=!0,!te&&(ve(),X(t),(r=t.onRuntimeInitialized)==null||r.call(t),je())}t.setStatus?(t.setStatus("Running..."),setTimeout(()=>{setTimeout(()=>t.setStatus(""),1),e()},1)):e()}function Ps(){if(t.preInit)for(typeof t.preInit=="function"&&(t.preInit=[t.preInit]);t.preInit.length>0;)t.preInit.shift()()}return Ps(),J(),Q=fe,Q});export{Ts as default};
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{f as B,i as L,j as O,k as R,l as j,t as q,m as x,n as H,o as K,q as U,s as J}from"../lite.js";const Q=120,X=i=>{const l=new Map,u=new Map;let r=[];const a=e=>{let t=e;for(;t.parent;)t=t.parent;return t},d=e=>e.tabs.flat(),g=(e,t)=>e.tabs.some(s=>s.includes(t)),h=e=>{const t=e.tabs[e.selected];return t&&t.length>0?t[t.length-1]:null},_=e=>{const t=a(e.node),s=u.get(t);return s?s.open===t:i.shown(t)},p=(e,t)=>{const s=e.node.el.ownerDocument;for(;e.cells.length<=t;){const o=s.createElement("div");o.className="lc-pager-cell",e.track.appendChild(o),e.cells.push(o)}return e.cells[t]},V=(e,t)=>{const s=e.selected*e.track.clientWidth;if(Math.abs(e.track.scrollLeft-s)<1){e.heading=null;return}e.heading=e.selected,e.track.scrollTo({left:s,behavior:t?"smooth":"instant"})},M=e=>{var t;for(const s of e.tabs)s.forEach((o,n)=>o.el.classList.toggle("lc-covered",n!==s.length-1));for(const s of e.stash)s.el.classList.add("lc-covered");e.track.classList.toggle("lc-drilled",(((t=e.tabs[e.selected])==null?void 0:t.length)??0)>1)},N=(e,t,s)=>t.type!=="screen"?(i.warn("pager: a page must be a live screen node"),!1):e.stash.delete(t)?(R(p(e,s),t.el),!0):t.parent!==null||t.rooted?(i.warn("pager: the page is attached elsewhere (remove it first)"),!1):(u.set(t,e),i.rootOwned(t,!0),t.el.classList.add("lc-covered"),R(p(e,s),t.el),!0),v=(e,t,s=!0)=>{if(t.el.classList.remove("lc-above"),s&&(t.flags&j)!==0){e.stash.add(t),t.el.classList.add("lc-covered");return}q(t.el),t.el.classList.remove("lc-covered"),u.delete(t),i.rootOwned(t,!1),i.emit(t.id,x)},I=(e,t)=>{i.emit(e.id,t,H,e.id)},S=(e,t)=>{e.active!==t&&(e.active=t,k(e))},A=(e,t)=>{for(const s of[...l.values()])l.get(s.node)===s&&s.node!==e&&a(s.node)===e&&S(s,t)};function k(e){const t=e.active?h(e):null;if(e.open!==t){if(e.open){const s=e.open;A(s,!1),I(s,U),e.open=null,r=r.filter(o=>o!==e)}t&&(e.open=t,r.push(e),I(t,J),A(t,!0))}}const z=e=>{const t=e.track.clientWidth;if(t<=0||e.tabs.length===0)return;const s=Math.max(0,Math.min(e.tabs.length-1,Math.round(e.track.scrollLeft/t)));if(e.heading!==null){s===e.heading&&(e.heading=null);return}s!==e.selected&&(e.stage.settle(),e.selected=s,M(e),i.emit(e.node.id,K,s),k(e))},F=e=>{const t=l.get(e);if(t)return t;const s=e.el.ownerDocument,o=s.defaultView??window,n=s.createElement("div");n.className="lc-pager-track",e.el.appendChild(n);const c={node:e,track:n,cells:[],tabs:[],backs:new Map,stash:new Set,selected:0,active:!1,open:null,heading:null,stage:i.stage(),sizes:new ResizeObserver(()=>{c.track.scrollLeft=c.selected*c.track.clientWidth}),settle:0};c.sizes.observe(n),"onscrollend"in n?n.addEventListener("scrollend",()=>z(c)):n.addEventListener("scroll",()=>{o.clearTimeout(c.settle),c.settle=o.setTimeout(()=>z(c),Q)},{passive:!0});const f=()=>{c.heading=null};return n.addEventListener("touchstart",f,{passive:!0}),n.addEventListener("wheel",f,{passive:!0}),l.set(e,c),c},C=(e,t,s,o)=>{const n=o===O?L:o;k(e),M(e),s&&s.el.classList.remove("lc-covered");const c=e.stage.enterOnTop(n);t.el.classList.toggle("lc-above",c),s==null||s.el.classList.toggle("lc-above",!c),e.stage.run(t,s,n,()=>{t.el.classList.remove("lc-above"),s&&(s.el.classList.remove("lc-above"),!(l.get(e.node)!==e||u.get(s)!==e)&&h(e)!==s&&(s.el.classList.add("lc-covered"),!g(e,s)&&!e.stash.has(s)&&v(e,s)))})},P=(e,t,s)=>{const o=e.tabs[e.selected],n=o[o.length-1],c=s===O?e.backs.get(n)??L:s,f=o.slice(t,o.length-1);o.length=t;for(const m of f)e.backs.delete(m),v(e,m);e.backs.delete(n),C(e,o[o.length-1],n,c)},w=e=>{const t=l.get(e);return t&&t.tabs.length>0?t:null},G=()=>{var e;for(let t=r.length-1;t>=0;t--){const s=r[t];if((((e=s.tabs[s.selected])==null?void 0:e.length)??0)>1)return s}return null},W=e=>{e.stage.settle(),S(e,!1);for(const t of d(e))v(e,t,!1);e.tabs=[];for(const t of[...e.stash])e.stash.delete(t),v(e,t,!1);r=r.filter(t=>t!==e),e.sizes.disconnect(),clearTimeout(e.settle),e.track.remove(),l.delete(e.node)};return{ownerOf:e=>{var t;return((t=u.get(e))==null?void 0:t.node)??null},pages(e){const t=l.get(e);return t?t.tabs.flatMap((s,o)=>s.map((n,c)=>({tab:o,pos:c,node:n}))):null},selected:e=>{var t;return((t=l.get(e))==null?void 0:t.selected)??0},isCell:e=>e.classList.contains("lc-pager-cell"),setContent(e,t,s,o){const n=F(e);n.stage.settle();const c=d(n),f=[];let m=0;s.forEach((E,T)=>{const y=[];for(let D=0;D<E&&m<t.length;D++,m++){const b=t[m];b&&(c.includes(b)&&u.get(b)===n?(R(p(n,T),b.el),y.push(b)):N(n,b,T)&&y.push(b))}f.push(y)}),n.tabs=f,n.backs.clear();for(const E of c)g(n,E)||v(n,E);for(;n.cells.length>Math.max(f.length,0);){const E=n.cells.pop();for(const T of n.stash)T.el.parentElement===E&&R(n.node.el,T.el);E.remove()}n.selected=f.length===0?0:Math.max(0,Math.min(o,f.length-1)),!n.active&&_(n)&&(n.active=!0),k(n),M(n),V(n,!1)},select(e,t,s){const o=w(e);if(!o)return;o.stage.settle();const n=Math.max(0,Math.min(t,o.tabs.length-1));n!==o.selected&&(o.selected=n,k(o),M(o)),V(o,s)},push(e,t,s,o){const n=w(e);if(!n||!t)return;n.stage.settle();const c=n.tabs[n.selected],f=c[c.length-1]??null;N(n,t,n.selected)&&(c.push(t),n.backs.set(t,o===O?L:o),C(n,t,f,s))},pop(e,t){const s=w(e);if(!s)return;s.stage.settle();const o=s.tabs[s.selected].length;o>1&&P(s,o-1,t)},popToRoot(e,t){const s=w(e);s&&(s.stage.settle(),s.tabs[s.selected].length>1&&P(s,1,t))},replace(e,t,s,o){const n=w(e);if(!n||!t)return;n.stage.settle();const c=n.tabs[n.selected],f=c[c.length-1]??null;f!==t&&N(n,t,n.selected)&&(n.backs.set(t,o===O?f?n.backs.get(f)??L:L:o),f?(c[c.length-1]=t,n.backs.delete(f)):c.push(t),C(n,t,f,s))},popForBack(){const e=G();if(!e)return!1;e.stage.settle();const t=e.tabs[e.selected].length-1;return i.emit(e.node.id,B,t),P(e,t,O),!0},rootActive:(e,t)=>A(e,t),subtreeMoved(e){for(const t of[...l.values()])if(l.get(t.node)===t){for(let s=t.node;s;s=s.parent)if(s===e){S(t,_(t));break}}},forget(e){const t=l.get(e);t&&W(t);const s=u.get(e);if(s){s.open===e&&(s.open=null,r=r.filter(o=>o!==s));for(const o of s.tabs){const n=o.indexOf(e);n>=0&&o.splice(n,1)}s.backs.delete(e),s.stash.delete(e),u.delete(e)}},destroy(){for(const e of l.values())e.sizes.disconnect(),clearTimeout(e.settle),e.track.remove();l.clear(),u.clear(),r=[]}}},Z={name:"pager",install(i){const l=X({emit:i.emitLater,warn:i.warn,rootOwned:i.rootOwned,shown:i.shown,stage:i.stage}),u=r=>{const a=i.node(r);return(a==null?void 0:a.type)==="pager"?a:void 0};return{bridge:{pagerSetContent(r,a,d,g){const h=u(r);h&&l.setContent(h,a.map(_=>i.node(_)),d,g)},pagerSelect(r,a,d){const g=u(r);g&&l.select(g,a,d)},pagerPush(r,a,d,g){const h=u(r);h&&l.push(h,i.node(a),d,g)},pagerPop(r,a){const d=u(r);d&&l.pop(d,a)},pagerPopToRoot(r,a){const d=u(r);d&&l.popToRoot(d,a)},pagerReplace(r,a,d,g){const h=u(r);h&&l.replace(h,i.node(a),d,g)}},forget:l.forget,destroy:l.destroy,rootActive:l.rootActive,subtreeMoved:l.subtreeMoved,back:l.popForBack,boundary:l.isCell,ownerOf:l.ownerOf,roots:r=>{var a;return((a=l.pages(r))==null?void 0:a.map(d=>d.node))??null},dump(r,a,d){const g=l.pages(r);g&&(a.selected=l.selected(r),a.pages=g.map(h=>({tab:h.tab,pos:h.pos,node:d(h.node)})))}}}};export{X as createPagers,Z as pager};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{u as D,w as W}from"../lite.js";const $=(m,c)=>{let f=[],l=[];const r=new Map,a=new Map,d=new Set;let e=[0],o=0,n=0,i=0,y=0,w=!0,O=!1,v=!1,p=!1,M=!1,S=!0;const L=t=>a.get(f[t])??l[t],b=t=>{o=Math.min(o,t)},x=()=>{const t=f.length;e.length=t+1,o>t&&(o=t),o===0&&(e[0]=0);for(let s=o;s<t;s++)e[s+1]=e[s]+L(s);o=t},H=()=>(x(),e[f.length]??0),_=t=>{for(let s=t;s<f.length;s++)r.set(f[s],s)},V=()=>m.inverted?Math.max(0,y-H()):0,N=()=>Math.max(0,H()-y),B=()=>{x();const t=f.length;if(t===0||y<=0)return[-1,-2];const s=m.overscan<0?y:m.overscan,u=n-s,h=n+y+s;let T=0,g=t;for(;T<g;){const K=T+g>>1;e[K+1]>u?g=K:T=K+1}const z=Math.min(T,t-1);for(T=0,g=t;T<g;){const K=T+g>>1;e[K]<h?T=K+1:g=K}return[Math.max(z,0),Math.min(T-1,t-1)]},k=()=>{m.endThreshold>0&&(H()-(n+y)<=m.endThreshold?O||(O=!0,c.edge(!0)):O=!1),m.startThreshold>0&&(n<=m.startThreshold?v||(v=!0,c.edge(!1)):v=!1)},I=()=>{if(p){M=!0;return}p=!0;try{for(let t=0;t<4;t++){M=!1;const[s,u]=B(),h=[],T=[];for(const g of d){const z=r.get(g);(z===void 0||z<s||z>u)&&h.push(g)}for(let g=s;g<=u;g++)d.has(f[g])||T.push(f[g]);if(h.length===0&&T.length===0||(c.sync(h,T),!M))break}}finally{p=!1}},E=t=>{n=Math.max(0,Math.min(t,N())),c.adjust(n)},C=(t,s,u)=>{const h=L(s);if(a.set(t,u),Math.abs(u-h)<=.5)return;x();const T=e[s];b(s),T<n?E(n+(u-h)):m.inverted&&w&&E(N()),M=!0};return{setKeys(t,s){f=t.slice(),l=f.map((u,h)=>s[h]??0),r.clear(),_(0),b(0),E(n),I(),k()},insertKeys(t,s,u){if(s.length===0)return;const h=f.length;(t<0||t>h)&&(t=h);const T=h>0,g=t===h;let z=0;s.forEach((R,A)=>{z+=a.get(R)??u[A]??0}),f.splice(t,0,...s),l.splice(t,0,...s.map((R,A)=>u[A]??0)),_(t),b(t);const K=w;x(),T&&!g&&e[t]<=n+.5&&E(n+z),m.inverted&&K&&g&&(E(N()),w=!0),I(),k()},removeKeys(t){let s=0;x();for(const u of t){const h=r.get(u);h!==void 0&&(e[h+1]<=n&&(s+=L(h)),f.splice(h,1),l.splice(h,1),r.delete(u),a.delete(u),_(h),b(h),x())}E(s>0?n-s:n),I(),k()},invalidate(t){if(!(!d.has(t)||p)){p=!0;try{c.sync([t],[t])}finally{p=!1}M&&(M=!1,I())}},mounted(t,s){const u=r.get(t);u!==void 0&&(d.add(t),C(t,u,s))},unmounted(t){d.delete(t)},isMounted:t=>d.has(t),resized(t,s){const u=r.get(t);u===void 0||!d.has(t)||(C(t,u,s),M&&!p&&(M=!1,I()))},scrolled(t){n=Math.max(0,t),w=n+y>=H()-2,I(),k()},viewport(t,s,u){if(!(t>0)||!(s>0))return;const h=Math.abs(t-i)>.5,T=Math.abs(s-y)>.5;if(i=t,y=s,H()<=y&&(w=!0),h){b(0);for(const g of d)a.set(g,u(g))}S?(S=!1,m.inverted&&(E(N()),w=!0)):m.inverted&&w&&T?E(N()):h&&E(n),I()},offsetOf(t){const s=r.get(t);return s===void 0?NaN:(x(),V()+e[s])},mountedTop(){let t=-1;for(const s of d){const u=r.get(s);u!==void 0&&(t<0||u<t)&&(t=u)}return x(),V()+(t<0?0:e[t])},indexOf:t=>r.get(t)??-1,contentHeight:()=>m.inverted?Math.max(H(),y):H(),maxScroll:N,scrollY:()=>n,mountedKeys:()=>[...d]}},j=m=>{const c=new Map,f=new Map,l=e=>{e.content.style.minHeight=`${e.window.contentHeight()}px`,e.content.style.paddingTop=`${e.window.mountedTop()}px`},r=(e,o)=>{const n=e.items.get(o);e.window.unmounted(o),n&&(e.items.delete(o),e.keyOf.delete(n),f.delete(n),e.sizes.unobserve(n.el),n.el.remove(),m.rootOwned(n,!1))},a=(e,o,n)=>{if(Number.isNaN(o))return;l(e);const i=Math.max(0,Math.min(o,e.window.maxScroll()));e.node.el.scrollTo({top:i,behavior:n?"smooth":"instant"})},d=e=>{for(const o of[...e.items.keys()])r(e,o);e.sizes.disconnect(),e.node.el.removeEventListener("scroll",e.onScroll),e.content.remove(),c.delete(e.node)};return{init(e,o,n,i,y){if(c.has(e))return;const w=e.el,O=w.ownerDocument.createElement("div");O.className="lc-vlist-content",w.appendChild(O);const v={node:e,content:O,items:new Map,keyOf:new Map,onScroll:()=>{v.window.scrolled(w.scrollTop),l(v)}};v.window=$({overscan:o,inverted:n,startThreshold:i,endThreshold:y},{sync(p,M){for(const S of p)r(v,S);m.emit(e.id,W,p,M),l(v)},adjust(p){l(v),Math.abs(w.scrollTop-p)>=.5&&(w.scrollTop=p)},edge:p=>{m.emitLater(e.id,D,p)}}),v.sizes=new ResizeObserver(p=>{for(const M of p){const S=M.target;if(S===w){v.window.viewport(w.clientWidth,w.clientHeight,L=>{var b;return((b=v.items.get(L))==null?void 0:b.el.offsetHeight)??0});continue}for(const[L,b]of v.keyOf)if(L.el===S){v.window.resized(b,S.offsetHeight);break}}l(v)}),v.sizes.observe(w),w.addEventListener("scroll",v.onScroll,{passive:!0}),c.set(e,v)},setKeys(e,o,n){const i=c.get(e);i&&(i.window.setKeys(o,Array.from(n)),l(i))},insertKeys(e,o,n,i){const y=c.get(e);y&&(y.window.insertKeys(o,n,Array.from(i)),l(y))},removeKeys(e,o){const n=c.get(e);n&&(n.window.removeKeys(o),l(n))},invalidate(e,o){const n=c.get(e);n&&(n.window.invalidate(o),l(n))},mount(e,o,n){const i=c.get(e);if(!i||!n)return;if(n.parent!==null||n.rooted){m.warn(`vlist: the item for key '${o}' is attached elsewhere`);return}const y=i.window.indexOf(o);if(y<0)return;i.items.has(o)&&r(i,o);let w=null,O=1/0;for(const[v,p]of i.items){const M=i.window.indexOf(v);M>y&&M<O&&(w=p,O=M)}i.items.set(o,n),i.keyOf.set(n,o),f.set(n,i),m.rootOwned(n,!0),i.content.insertBefore(n.el,(w==null?void 0:w.el)??null),m.flush(),i.sizes.observe(n.el),i.window.mounted(o,n.el.offsetHeight)},scrollTo(e,o,n){const i=c.get(e);i&&a(i,o,n)},scrollToKey(e,o,n){const i=c.get(e);i&&a(i,i.window.offsetOf(o),n)},scrollToEnd(e,o){const n=c.get(e);n&&a(n,n.window.maxScroll(),o)},ownerOf:e=>{var o;return((o=f.get(e))==null?void 0:o.node)??null},forget(e){const o=c.get(e);o&&d(o);const n=f.get(e),i=n==null?void 0:n.keyOf.get(e);n&&i!==void 0&&(n.window.unmounted(i),n.items.delete(i),n.keyOf.delete(e),n.sizes.unobserve(e.el),f.delete(e))},destroy(){for(const e of c.values())e.sizes.disconnect(),e.content.remove();c.clear(),f.clear()}}},Y={name:"vlist",install(m){const c=j({emit:m.emit,emitLater:m.emitLater,warn:m.warn,rootOwned:m.rootOwned,flush:m.flush}),f=l=>{const r=m.node(l);return(r==null?void 0:r.type)==="vlist"?r:void 0};return{bridge:{vlistInit(l,r,a,d,e){const o=f(l);o&&c.init(o,r,a,d,e)},vlistSetKeys(l,r,a){const d=f(l);d&&c.setKeys(d,r,a)},vlistInsertKeys(l,r,a,d){const e=f(l);e&&c.insertKeys(e,r,a,d)},vlistRemoveKeys(l,r){const a=f(l);a&&c.removeKeys(a,r)},vlistInvalidate(l,r){const a=f(l);a&&c.invalidate(a,r)},vlistMount(l,r,a){const d=f(l);d&&c.mount(d,r,m.node(a))},vlistScrollTo(l,r,a){const d=f(l);d&&c.scrollTo(d,r,a)},vlistScrollToKey(l,r,a){const d=f(l);d&&c.scrollToKey(d,r,a)},vlistScrollToEnd(l,r){const a=f(l);a&&c.scrollToEnd(a,r)}},forget:c.forget,destroy:c.destroy}}};export{j as createVLists,Y as vlist};
|