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.
Files changed (38) hide show
  1. package/dist/index.js +1798 -1116
  2. package/package.json +21 -11
  3. package/runtime/sdk-types.json +1 -1
  4. package/runtime/web/VERSION.json +3 -3
  5. package/runtime/web/assets/creator-2d-BSJoqaE1.wasm +0 -0
  6. package/runtime/web/assets/{creator-2d-CYlV77UR.js → creator-2d-DG2jJnoQ.js} +1 -1
  7. package/runtime/web/assets/creator-ui-Bu2prHDl.wasm +0 -0
  8. package/runtime/web/assets/creator-ui-HDloYDcM.js +1 -0
  9. package/runtime/web/player.js +15 -15
  10. package/runtime/web-lite/assets/pager-DpGa2uaE.js +1 -0
  11. package/runtime/web-lite/assets/vlist-CwSYpLz-.js +1 -0
  12. package/runtime/web-lite/features.json +2 -2
  13. package/runtime/web-lite/lite.js +21 -10
  14. package/src/commands/app/android.ts +7 -7
  15. package/src/commands/app/index.ts +58 -84
  16. package/src/commands/app/shared.ts +53 -74
  17. package/src/commands/app/templates/ios.ts +75 -78
  18. package/src/commands/compile.ts +1 -1
  19. package/src/commands/init/templates.ts +7 -0
  20. package/src/commands/render.ts +17 -4
  21. package/src/commands/test.ts +10 -6
  22. package/src/compile/collect.ts +12 -3
  23. package/src/compile/headlessBundle.ts +10 -3
  24. package/src/declarations/lecodes-headless.d.ts +3 -0
  25. package/src/dev/backendWorker.ts +17 -6
  26. package/src/dev/localBackend.ts +8 -2
  27. package/src/dev/projectBackend.ts +31 -9
  28. package/src/hosts/desktopScript.ts +11 -1
  29. package/src/hosts/flowPick.ts +111 -0
  30. package/src/hosts/liteBrowser.mjs +5 -0
  31. package/src/hosts/liteRunner.ts +30 -0
  32. package/src/hosts/peerInstall.ts +5 -1
  33. package/src/hosts/peers.ts +2 -0
  34. package/runtime/web/assets/creator-2d-nG7rGEmq.wasm +0 -0
  35. package/runtime/web/assets/creator-ui-CbtoaRlz.js +0 -1
  36. package/runtime/web/assets/creator-ui-DZaoxIpX.wasm +0 -0
  37. package/runtime/web-lite/assets/pager-Db5BY7FB.js +0 -1
  38. 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
- try {
112
- const body = await req.text()
113
- args = body.length > BODY_LIMIT ? null : JSON.parse(body)?.args
114
- } catch { args = null }
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
- return envelope(await backend.invoke(id, args, { headers: Object.fromEntries(req.headers), ip, sessionToken: bearerOf(req) ?? undefined }))
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
- const frameCap = Math.max(0, opts.headroomFrames) + Math.ceil(budgetMs / FRAME_MS) + 600
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(() => {})
@@ -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)}`)
@@ -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[] => name === "lecodes-headless" ? ["lecodes-headless", "@napi-rs/canvas"] : [name]
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
 
@@ -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
 
@@ -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};
@@ -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};