@tutti-os/workspace-file-preview 0.0.181 → 0.0.183
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/README.md +14 -4
- package/dist/{chunk-FYAXIZ3F.js → chunk-SUQYO7VX.js} +288 -14
- package/dist/chunk-SUQYO7VX.js.map +1 -0
- package/dist/core/index.d.ts +76 -6
- package/dist/core/index.js +3 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -1
- package/dist/react/index.d.ts +4 -17
- package/dist/react/index.js +45 -38
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FYAXIZ3F.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,17 @@ It also exposes a small React preview surface for consumers that want the shared
|
|
|
10
10
|
image, text, loading, and readonly rendering shell while keeping host-specific
|
|
11
11
|
icons and localized copy outside this package.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
`createWorkspaceFilePreviewController` owns the shared frontend loading
|
|
14
|
+
lifecycle. Consumers inject a byte reader and entry projection; the controller
|
|
15
|
+
owns readiness checks, stale-request fencing, cancellation, decoding, canonical
|
|
16
|
+
language-neutral state, and media object-URL cleanup. Product controllers keep
|
|
17
|
+
selection, editing, persistence, transport, and localized error presentation.
|
|
18
|
+
|
|
19
|
+
Sources may provide `canReadEntry` as a capability gate. Returning `false`
|
|
20
|
+
blocks reads for every non-directory entry, while returning `true` also allows
|
|
21
|
+
the injected reader to classify file types that local extension detection does
|
|
22
|
+
not recognize. Omitting the callback keeps the default local classification.
|
|
23
|
+
|
|
24
|
+
HTML files are shown as source text. Opening or executing an HTML document
|
|
25
|
+
belongs to a separate browser activation flow rather than the ordinary file
|
|
26
|
+
preview surface.
|
|
@@ -316,13 +316,6 @@ function createWorkspaceFilePreviewLoadedState(input) {
|
|
|
316
316
|
status: "readonly"
|
|
317
317
|
};
|
|
318
318
|
}
|
|
319
|
-
if (input.renderHtml && isWorkspaceHtmlFileName(input.target.name)) {
|
|
320
|
-
return {
|
|
321
|
-
content,
|
|
322
|
-
entry: input.target,
|
|
323
|
-
status: "html"
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
319
|
return {
|
|
327
320
|
content,
|
|
328
321
|
entry: input.target,
|
|
@@ -336,11 +329,6 @@ function createWorkspaceFilePreviewLoadedState(input) {
|
|
|
336
329
|
};
|
|
337
330
|
}
|
|
338
331
|
}
|
|
339
|
-
function isWorkspaceHtmlFileName(pathOrName) {
|
|
340
|
-
return browserOpenableHtmlExtensions.has(
|
|
341
|
-
resolveWorkspaceFileExtension(pathOrName)
|
|
342
|
-
);
|
|
343
|
-
}
|
|
344
332
|
function resolveWorkspaceFilePreviewName(entry) {
|
|
345
333
|
return entry.name?.trim() || entry.displayName?.trim() || entry.path.split("/").pop()?.trim() || entry.path;
|
|
346
334
|
}
|
|
@@ -398,6 +386,291 @@ function formatWorkspacePreviewByteLimit(sizeBytes) {
|
|
|
398
386
|
return `${mebibytes.toFixed(1)} MiB`;
|
|
399
387
|
}
|
|
400
388
|
|
|
389
|
+
// src/core/workspaceFilePreviewController.ts
|
|
390
|
+
function createWorkspaceFilePreviewController(input) {
|
|
391
|
+
return new WorkspaceFilePreviewControllerImpl(input);
|
|
392
|
+
}
|
|
393
|
+
var WorkspaceFilePreviewControllerImpl = class {
|
|
394
|
+
activeEntry = null;
|
|
395
|
+
activeEntryKey = null;
|
|
396
|
+
abortController = null;
|
|
397
|
+
disposed = false;
|
|
398
|
+
generation = 0;
|
|
399
|
+
loadPromise = Promise.resolve();
|
|
400
|
+
objectUrl = null;
|
|
401
|
+
listeners = /* @__PURE__ */ new Set();
|
|
402
|
+
input;
|
|
403
|
+
objectUrls;
|
|
404
|
+
state = {
|
|
405
|
+
status: "empty"
|
|
406
|
+
};
|
|
407
|
+
constructor(input) {
|
|
408
|
+
this.input = input;
|
|
409
|
+
this.objectUrls = input.objectUrls ?? browserWorkspaceFilePreviewObjectUrls;
|
|
410
|
+
}
|
|
411
|
+
dispose() {
|
|
412
|
+
if (this.disposed) {
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
this.disposed = true;
|
|
416
|
+
this.cancelLoad();
|
|
417
|
+
this.revokeObjectUrl();
|
|
418
|
+
this.listeners.clear();
|
|
419
|
+
}
|
|
420
|
+
getSnapshot() {
|
|
421
|
+
return this.state;
|
|
422
|
+
}
|
|
423
|
+
reload() {
|
|
424
|
+
if (this.disposed || !this.activeEntry) {
|
|
425
|
+
return Promise.resolve();
|
|
426
|
+
}
|
|
427
|
+
return this.start(this.activeEntry);
|
|
428
|
+
}
|
|
429
|
+
setEntry(entry) {
|
|
430
|
+
if (this.disposed) {
|
|
431
|
+
return Promise.resolve();
|
|
432
|
+
}
|
|
433
|
+
const nextKey = entry ? this.resolveEntryKey(entry) : null;
|
|
434
|
+
if (nextKey === this.activeEntryKey) {
|
|
435
|
+
return this.loadPromise;
|
|
436
|
+
}
|
|
437
|
+
this.activeEntry = entry;
|
|
438
|
+
this.activeEntryKey = nextKey;
|
|
439
|
+
if (!entry) {
|
|
440
|
+
this.cancelLoad();
|
|
441
|
+
this.revokeObjectUrl();
|
|
442
|
+
this.updateState({ status: "empty" });
|
|
443
|
+
this.loadPromise = Promise.resolve();
|
|
444
|
+
return this.loadPromise;
|
|
445
|
+
}
|
|
446
|
+
return this.start(entry);
|
|
447
|
+
}
|
|
448
|
+
subscribe(listener) {
|
|
449
|
+
if (this.disposed) {
|
|
450
|
+
return () => {
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
this.listeners.add(listener);
|
|
454
|
+
return () => {
|
|
455
|
+
this.listeners.delete(listener);
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
cancelLoad() {
|
|
459
|
+
this.generation += 1;
|
|
460
|
+
this.abortController?.abort();
|
|
461
|
+
this.abortController = null;
|
|
462
|
+
}
|
|
463
|
+
isStale(generation) {
|
|
464
|
+
return this.disposed || generation !== this.generation;
|
|
465
|
+
}
|
|
466
|
+
async load(entry, previewEntry, target, generation, abortController) {
|
|
467
|
+
try {
|
|
468
|
+
const result = await this.input.read?.({
|
|
469
|
+
entry,
|
|
470
|
+
signal: abortController.signal,
|
|
471
|
+
target
|
|
472
|
+
});
|
|
473
|
+
if (this.isStale(generation)) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
if (!result) {
|
|
477
|
+
this.updateState({
|
|
478
|
+
entry,
|
|
479
|
+
reason: "file_type",
|
|
480
|
+
status: "unsupported"
|
|
481
|
+
});
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const loaded = createWorkspaceFilePreviewLoadedState({
|
|
485
|
+
bytes: result instanceof Uint8Array || result instanceof ArrayBuffer ? result : result.bytes,
|
|
486
|
+
contentType: result instanceof Uint8Array || result instanceof ArrayBuffer ? void 0 : result.contentType,
|
|
487
|
+
entry: previewEntry,
|
|
488
|
+
target: result instanceof Uint8Array || result instanceof ArrayBuffer ? target : { ...target, fileKind: result.kind ?? target.fileKind }
|
|
489
|
+
});
|
|
490
|
+
if (this.isStale(generation)) {
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
if (loaded.status === "image" || loaded.status === "video") {
|
|
494
|
+
const previewSizeBytes = loaded.bytes.byteLength;
|
|
495
|
+
const objectUrl = this.objectUrls.create(
|
|
496
|
+
loaded.bytes,
|
|
497
|
+
loaded.contentType
|
|
498
|
+
);
|
|
499
|
+
if (this.isStale(generation)) {
|
|
500
|
+
this.objectUrls.revoke(objectUrl);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
this.objectUrl = objectUrl;
|
|
504
|
+
this.updateState({
|
|
505
|
+
entry,
|
|
506
|
+
objectUrl,
|
|
507
|
+
previewSizeBytes,
|
|
508
|
+
status: loaded.status
|
|
509
|
+
});
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
if (loaded.status === "text") {
|
|
513
|
+
this.updateState({
|
|
514
|
+
content: loaded.content,
|
|
515
|
+
entry,
|
|
516
|
+
previewSizeBytes: byteLengthOfPreviewReadResult(result),
|
|
517
|
+
status: "text"
|
|
518
|
+
});
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
this.updateState({
|
|
522
|
+
entry,
|
|
523
|
+
previewSizeBytes: byteLengthOfPreviewReadResult(result),
|
|
524
|
+
reason: loaded.reason,
|
|
525
|
+
...loaded.maxSizeBytes === void 0 ? {} : { maxSizeBytes: loaded.maxSizeBytes },
|
|
526
|
+
status: "readonly"
|
|
527
|
+
});
|
|
528
|
+
} catch (error) {
|
|
529
|
+
if (this.isStale(generation)) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
this.updateState({ entry, error, status: "error" });
|
|
533
|
+
} finally {
|
|
534
|
+
if (!this.isStale(generation)) {
|
|
535
|
+
this.abortController = null;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
resolveEntryKey(entry) {
|
|
540
|
+
if (this.input.getEntryKey) {
|
|
541
|
+
return this.input.getEntryKey(entry);
|
|
542
|
+
}
|
|
543
|
+
const previewEntry = this.input.toPreviewEntry(entry);
|
|
544
|
+
return [
|
|
545
|
+
previewEntry.kind,
|
|
546
|
+
previewEntry.path,
|
|
547
|
+
previewEntry.name ?? "",
|
|
548
|
+
previewEntry.displayName ?? "",
|
|
549
|
+
previewEntry.sizeBytes ?? "",
|
|
550
|
+
previewEntry.mtimeMs ?? ""
|
|
551
|
+
].join("\0");
|
|
552
|
+
}
|
|
553
|
+
revokeObjectUrl() {
|
|
554
|
+
if (!this.objectUrl) {
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
this.objectUrls.revoke(this.objectUrl);
|
|
558
|
+
this.objectUrl = null;
|
|
559
|
+
}
|
|
560
|
+
start(entry) {
|
|
561
|
+
this.cancelLoad();
|
|
562
|
+
this.revokeObjectUrl();
|
|
563
|
+
const previewEntry = this.input.toPreviewEntry(entry);
|
|
564
|
+
const readiness = resolveWorkspaceFilePreviewReadiness(previewEntry);
|
|
565
|
+
if (readiness.status === "directory") {
|
|
566
|
+
this.updateState({ entry, status: "directory" });
|
|
567
|
+
this.loadPromise = Promise.resolve();
|
|
568
|
+
return this.loadPromise;
|
|
569
|
+
}
|
|
570
|
+
const canRead = this.input.canReadEntry?.(entry);
|
|
571
|
+
if (canRead === false) {
|
|
572
|
+
this.updateState({
|
|
573
|
+
entry,
|
|
574
|
+
reason: "reader_unavailable",
|
|
575
|
+
status: "unsupported"
|
|
576
|
+
});
|
|
577
|
+
this.loadPromise = Promise.resolve();
|
|
578
|
+
return this.loadPromise;
|
|
579
|
+
}
|
|
580
|
+
if (readiness.status === "unsupported") {
|
|
581
|
+
if (canRead !== true) {
|
|
582
|
+
this.updateState({
|
|
583
|
+
entry,
|
|
584
|
+
reason: "file_type",
|
|
585
|
+
status: "unsupported"
|
|
586
|
+
});
|
|
587
|
+
this.loadPromise = Promise.resolve();
|
|
588
|
+
return this.loadPromise;
|
|
589
|
+
}
|
|
590
|
+
if (!this.input.read) {
|
|
591
|
+
this.updateState({
|
|
592
|
+
entry,
|
|
593
|
+
reason: "reader_unavailable",
|
|
594
|
+
status: "unsupported"
|
|
595
|
+
});
|
|
596
|
+
this.loadPromise = Promise.resolve();
|
|
597
|
+
return this.loadPromise;
|
|
598
|
+
}
|
|
599
|
+
const target = {
|
|
600
|
+
fileKind: "text",
|
|
601
|
+
name: previewEntry.name ?? previewEntry.displayName ?? previewEntry.path.split("/").pop() ?? previewEntry.path,
|
|
602
|
+
path: previewEntry.path,
|
|
603
|
+
...previewEntry.mtimeMs === void 0 ? {} : { mtimeMs: previewEntry.mtimeMs },
|
|
604
|
+
...previewEntry.sizeBytes === void 0 ? {} : { sizeBytes: previewEntry.sizeBytes }
|
|
605
|
+
};
|
|
606
|
+
const abortController2 = new AbortController();
|
|
607
|
+
this.abortController = abortController2;
|
|
608
|
+
const generation2 = this.generation;
|
|
609
|
+
this.updateState({ entry, status: "loading" });
|
|
610
|
+
this.loadPromise = this.load(
|
|
611
|
+
entry,
|
|
612
|
+
previewEntry,
|
|
613
|
+
target,
|
|
614
|
+
generation2,
|
|
615
|
+
abortController2
|
|
616
|
+
);
|
|
617
|
+
return this.loadPromise;
|
|
618
|
+
}
|
|
619
|
+
if (readiness.status === "readonly") {
|
|
620
|
+
this.updateState({
|
|
621
|
+
entry,
|
|
622
|
+
maxSizeBytes: readiness.maxSizeBytes,
|
|
623
|
+
reason: readiness.reason,
|
|
624
|
+
status: "readonly"
|
|
625
|
+
});
|
|
626
|
+
this.loadPromise = Promise.resolve();
|
|
627
|
+
return this.loadPromise;
|
|
628
|
+
}
|
|
629
|
+
if (!this.input.read) {
|
|
630
|
+
this.updateState({
|
|
631
|
+
entry,
|
|
632
|
+
reason: "reader_unavailable",
|
|
633
|
+
status: "unsupported"
|
|
634
|
+
});
|
|
635
|
+
this.loadPromise = Promise.resolve();
|
|
636
|
+
return this.loadPromise;
|
|
637
|
+
}
|
|
638
|
+
const abortController = new AbortController();
|
|
639
|
+
this.abortController = abortController;
|
|
640
|
+
const generation = this.generation;
|
|
641
|
+
this.updateState({ entry, status: "loading" });
|
|
642
|
+
this.loadPromise = this.load(
|
|
643
|
+
entry,
|
|
644
|
+
previewEntry,
|
|
645
|
+
readiness.target,
|
|
646
|
+
generation,
|
|
647
|
+
abortController
|
|
648
|
+
);
|
|
649
|
+
return this.loadPromise;
|
|
650
|
+
}
|
|
651
|
+
updateState(state) {
|
|
652
|
+
if (this.disposed) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
this.state = state;
|
|
656
|
+
for (const listener of this.listeners) {
|
|
657
|
+
listener();
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
var browserWorkspaceFilePreviewObjectUrls = {
|
|
662
|
+
create(bytes, contentType) {
|
|
663
|
+
return URL.createObjectURL(new Blob([bytes], { type: contentType }));
|
|
664
|
+
},
|
|
665
|
+
revoke(objectUrl) {
|
|
666
|
+
URL.revokeObjectURL(objectUrl);
|
|
667
|
+
}
|
|
668
|
+
};
|
|
669
|
+
function byteLengthOfPreviewReadResult(result) {
|
|
670
|
+
const bytes = result instanceof Uint8Array || result instanceof ArrayBuffer ? result : result.bytes;
|
|
671
|
+
return bytes.byteLength;
|
|
672
|
+
}
|
|
673
|
+
|
|
401
674
|
export {
|
|
402
675
|
workspaceFileVideoHandlerCollisionExtensions,
|
|
403
676
|
workspaceFileTextMaxBytes,
|
|
@@ -419,6 +692,7 @@ export {
|
|
|
419
692
|
normalizeWorkspaceFilePreviewBytes,
|
|
420
693
|
copyWorkspaceFilePreviewBytes,
|
|
421
694
|
looksLikeBinaryText,
|
|
422
|
-
formatWorkspacePreviewByteLimit
|
|
695
|
+
formatWorkspacePreviewByteLimit,
|
|
696
|
+
createWorkspaceFilePreviewController
|
|
423
697
|
};
|
|
424
|
-
//# sourceMappingURL=chunk-
|
|
698
|
+
//# sourceMappingURL=chunk-SUQYO7VX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/workspaceFilePreview.ts","../src/core/workspaceFilePreviewController.ts"],"sourcesContent":["export type WorkspaceFilePreviewEntryKind =\n | \"file\"\n | \"directory\"\n | \"folder\"\n | \"unknown\"\n | (string & {});\n\nexport type WorkspaceFilePreviewKind = \"image\" | \"text\" | \"video\";\n\nexport type WorkspaceFileVisualKind =\n | \"binary\"\n | \"code\"\n | \"directory\"\n | \"document\"\n | \"image\"\n | \"markdown\"\n | \"video\";\n\nexport interface WorkspaceFilePreviewEntry {\n displayName?: string;\n kind: WorkspaceFilePreviewEntryKind;\n mtimeMs?: number | null;\n name?: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport interface WorkspaceFilePreviewActivationTarget {\n fileKind: WorkspaceFilePreviewKind;\n mtimeMs?: number | null;\n name: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport type WorkspaceFilePreviewReadonlyReason =\n | \"binary\"\n | \"decode_failed\"\n | \"file_too_large\"\n | \"text_too_large\";\n\nexport type WorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget =\n WorkspaceFilePreviewActivationTarget\n> =\n | { entry: TEntry; status: \"directory\" }\n | {\n entry: TEntry;\n maxSizeBytes: number;\n reason: Extract<\n WorkspaceFilePreviewReadonlyReason,\n \"file_too_large\" | \"text_too_large\"\n >;\n status: \"readonly\";\n }\n | { entry: TEntry; status: \"unsupported\" }\n | { entry: TEntry; status: \"ready\"; target: TTarget };\n\nexport type WorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n> =\n | { content: string; entry: TTarget; status: \"text\" }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string;\n entry: TTarget;\n status: \"image\";\n }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string;\n entry: TTarget;\n status: \"video\";\n }\n | {\n entry: TEntry;\n maxSizeBytes?: number;\n reason: WorkspaceFilePreviewReadonlyReason;\n status: \"readonly\";\n };\n\nconst imageExtensions = new Set([\n \"avif\",\n \"gif\",\n \"jpeg\",\n \"jpg\",\n \"png\",\n \"svg\",\n \"webp\"\n]);\nconst browserOpenableHtmlExtensions = new Set([\n \"htm\",\n \"html\",\n \"shtml\",\n \"xhtml\"\n]);\nconst browserOpenableVideoExtensions = new Set([\"mp4\", \"webm\"]);\n\nconst videoExtensions = new Set([\n \"avi\",\n \"m2ts\",\n \"mkv\",\n \"mov\",\n \"mp4\",\n \"mpeg\",\n \"mpg\",\n \"mts\",\n \"webm\",\n \"wmv\"\n]);\n/**\n * Extensions where macOS Launch Services may register video handlers even when\n * the workspace file is source code (UTI / uniform type collisions).\n */\nexport const workspaceFileVideoHandlerCollisionExtensions = new Set([\"ts\"]);\nconst markdownExtensions = new Set([\"md\", \"mdx\"]);\nconst codeExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"java\",\n \"js\",\n \"jsx\",\n \"json\",\n \"lua\",\n \"m\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst documentExtensions = new Set([\n \"csv\",\n \"doc\",\n \"docx\",\n \"log\",\n \"pdf\",\n \"rtf\",\n \"txt\",\n \"xls\",\n \"xlsx\"\n]);\nconst textExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"csv\",\n \"env\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"ini\",\n \"java\",\n \"js\",\n \"json\",\n \"jsx\",\n \"log\",\n \"lua\",\n \"m\",\n \"md\",\n \"mdx\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"txt\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst textFileNames = new Set([\n \".gitignore\",\n \".npmrc\",\n \".nvmrc\",\n \"dockerfile\",\n \"makefile\",\n \"readme\"\n]);\n\nexport const workspaceFileTextMaxBytes = 1024 * 1024;\nexport const workspaceFilePreviewMaxBytes = 20 * 1024 * 1024;\n\nexport function resolveWorkspaceFileVisualKind(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): WorkspaceFileVisualKind {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return \"directory\";\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (imageExtensions.has(extension)) {\n return \"image\";\n }\n if (videoExtensions.has(extension)) {\n return \"video\";\n }\n if (markdownExtensions.has(extension)) {\n return \"markdown\";\n }\n if (codeExtensions.has(extension)) {\n return \"code\";\n }\n if (documentExtensions.has(extension)) {\n return \"document\";\n }\n return \"binary\";\n}\n\nexport function resolveWorkspaceFileExtension(pathOrName: string): string {\n const name = pathOrName.split(\"/\").pop()?.trim().toLowerCase() ?? \"\";\n const dotIndex = name.lastIndexOf(\".\");\n return dotIndex > 0 ? name.slice(dotIndex + 1) : \"\";\n}\n\nexport function isWorkspaceFileBrowserOpenable(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (\n extension === \"pdf\" ||\n browserOpenableHtmlExtensions.has(extension) ||\n imageExtensions.has(extension) ||\n browserOpenableVideoExtensions.has(extension)\n ) {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function shouldFilterVideoPlayersForOpenWith(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const visualKind = resolveWorkspaceFileVisualKind(entry);\n if (visualKind === \"video\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (workspaceFileVideoHandlerCollisionExtensions.has(extension)) {\n return true;\n }\n\n if (visualKind === \"code\" || visualKind === \"markdown\") {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function resolveWorkspaceImageMimeType(\n pathOrName: string\n): string | null {\n switch (resolveWorkspaceFileExtension(pathOrName)) {\n case \"avif\":\n return \"image/avif\";\n case \"gif\":\n return \"image/gif\";\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"svg\":\n return \"image/svg+xml\";\n case \"webp\":\n return \"image/webp\";\n default:\n return null;\n }\n}\n\nexport function resolveWorkspaceVideoMimeType(\n pathOrName: string\n): string | null {\n switch (resolveWorkspaceFileExtension(pathOrName)) {\n case \"mp4\":\n return \"video/mp4\";\n case \"webm\":\n return \"video/webm\";\n default:\n return null;\n }\n}\n\nexport function classifyWorkspaceFilePreviewKind(\n entry: Pick<\n WorkspaceFilePreviewEntry,\n \"displayName\" | \"kind\" | \"name\" | \"path\"\n >\n): WorkspaceFilePreviewKind | null {\n if (entry.kind !== \"file\") {\n return null;\n }\n\n const name = resolveWorkspaceFilePreviewName(entry);\n if (resolveWorkspaceImageMimeType(name) !== null) {\n return \"image\";\n }\n if (resolveWorkspaceVideoMimeType(name) !== null) {\n return \"video\";\n }\n\n const normalizedName = name.trim().toLowerCase();\n const extension = resolveWorkspaceFileExtension(name);\n if (textExtensions.has(extension) || textFileNames.has(normalizedName)) {\n return \"text\";\n }\n\n return null;\n}\n\nexport function resolveWorkspaceFileActivationTarget(\n entry: WorkspaceFilePreviewEntry\n): WorkspaceFilePreviewActivationTarget | null {\n const fileKind = classifyWorkspaceFilePreviewKind(entry);\n if (!fileKind) {\n return null;\n }\n\n const target: WorkspaceFilePreviewActivationTarget = {\n fileKind,\n name: resolveWorkspaceFilePreviewName(entry),\n path: entry.path\n };\n if (entry.mtimeMs !== undefined) {\n target.mtimeMs = entry.mtimeMs;\n }\n if (entry.sizeBytes !== undefined) {\n target.sizeBytes = entry.sizeBytes;\n }\n return target;\n}\n\nexport function resolveWorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry\n>(entry: TEntry): WorkspaceFilePreviewReadiness<TEntry> {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return {\n entry,\n status: \"directory\"\n };\n }\n\n const target = resolveWorkspaceFileActivationTarget(entry);\n if (!target) {\n return {\n entry,\n status: \"unsupported\"\n };\n }\n\n if (\n target.fileKind === \"text\" &&\n isWorkspaceTextFileTooLarge(entry.sizeBytes)\n ) {\n return {\n entry,\n maxSizeBytes: workspaceFileTextMaxBytes,\n reason: \"text_too_large\",\n status: \"readonly\"\n };\n }\n\n if (isWorkspacePreviewFileTooLarge(entry.sizeBytes)) {\n return {\n entry,\n maxSizeBytes: workspaceFilePreviewMaxBytes,\n reason: \"file_too_large\",\n status: \"readonly\"\n };\n }\n\n return {\n entry,\n status: \"ready\",\n target\n };\n}\n\nexport function createWorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n>(input: {\n bytes: Uint8Array | ArrayBuffer;\n contentType?: string | null;\n entry: TEntry;\n target: TTarget;\n}): WorkspaceFilePreviewLoadedState<TEntry, TTarget> {\n if (input.target.fileKind === \"image\") {\n return {\n bytes: copyWorkspaceFilePreviewBytes(input.bytes),\n contentType:\n input.contentType ??\n resolveWorkspaceImageMimeType(input.target.name) ??\n \"application/octet-stream\",\n entry: input.target,\n status: \"image\"\n };\n }\n if (input.target.fileKind === \"video\") {\n return {\n bytes: copyWorkspaceFilePreviewBytes(input.bytes),\n contentType:\n input.contentType ??\n resolveWorkspaceVideoMimeType(input.target.name) ??\n \"application/octet-stream\",\n entry: input.target,\n status: \"video\"\n };\n }\n\n try {\n const content = decodeWorkspaceTextFile(input.bytes);\n if (looksLikeBinaryText(content)) {\n return {\n entry: input.entry,\n reason: \"binary\",\n status: \"readonly\"\n };\n }\n return {\n content,\n entry: input.target,\n status: \"text\"\n };\n } catch {\n return {\n entry: input.entry,\n reason: \"decode_failed\",\n status: \"readonly\"\n };\n }\n}\n\nexport function resolveWorkspaceFilePreviewName(\n entry: Pick<WorkspaceFilePreviewEntry, \"displayName\" | \"name\" | \"path\">\n): string {\n return (\n entry.name?.trim() ||\n entry.displayName?.trim() ||\n entry.path.split(\"/\").pop()?.trim() ||\n entry.path\n );\n}\n\nexport function isWorkspaceTextFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFileTextMaxBytes\n );\n}\n\nexport function isWorkspacePreviewFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFilePreviewMaxBytes\n );\n}\n\nexport function decodeWorkspaceTextFile(\n bytes: Uint8Array | ArrayBuffer\n): string {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n normalizeWorkspaceFilePreviewBytes(bytes)\n );\n}\n\nexport function normalizeWorkspaceFilePreviewBytes(\n value: Uint8Array | ArrayBuffer\n): Uint8Array {\n if (value instanceof Uint8Array) {\n return value;\n }\n return new Uint8Array(value);\n}\n\nexport function copyWorkspaceFilePreviewBytes(\n bytes: Uint8Array | ArrayBuffer\n): Uint8Array<ArrayBuffer> {\n const normalized = normalizeWorkspaceFilePreviewBytes(bytes);\n const buffer = new ArrayBuffer(normalized.byteLength);\n const copy = new Uint8Array(buffer);\n copy.set(normalized);\n return copy;\n}\n\nexport function looksLikeBinaryText(content: string): boolean {\n if (content.length === 0) {\n return false;\n }\n\n const sample = content.slice(0, 4096);\n if (sample.includes(\"\\u0000\")) {\n return true;\n }\n\n let suspiciousControlChars = 0;\n for (let index = 0; index < sample.length; index += 1) {\n const code = sample.charCodeAt(index);\n const isAllowedWhitespace = code === 9 || code === 10 || code === 13;\n const isControlChar = code < 32 || (code >= 127 && code <= 159);\n if (isControlChar && !isAllowedWhitespace) {\n suspiciousControlChars += 1;\n }\n }\n\n return suspiciousControlChars / sample.length > 0.12;\n}\n\nexport function formatWorkspacePreviewByteLimit(sizeBytes: number): string {\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n const mebibytes = sizeBytes / (1024 * 1024);\n if (Number.isInteger(mebibytes)) {\n return `${mebibytes} MiB`;\n }\n return `${mebibytes.toFixed(1)} MiB`;\n}\n","import {\n createWorkspaceFilePreviewLoadedState,\n resolveWorkspaceFilePreviewReadiness,\n type WorkspaceFilePreviewActivationTarget,\n type WorkspaceFilePreviewEntry,\n type WorkspaceFilePreviewKind,\n type WorkspaceFilePreviewReadonlyReason\n} from \"./workspaceFilePreview.ts\";\n\nexport type WorkspaceFilePreviewUnsupportedReason =\n | \"file_type\"\n | \"reader_unavailable\";\n\nexport type WorkspaceFilePreviewControllerState<TEntry> =\n | { status: \"empty\" }\n | { entry: TEntry; status: \"directory\" }\n | { entry: TEntry; status: \"loading\" }\n | {\n content: string;\n entry: TEntry;\n previewSizeBytes: number;\n status: \"text\";\n }\n | {\n entry: TEntry;\n objectUrl: string;\n previewSizeBytes: number;\n status: \"image\";\n }\n | {\n entry: TEntry;\n objectUrl: string;\n previewSizeBytes: number;\n status: \"video\";\n }\n | {\n entry: TEntry;\n maxSizeBytes?: number;\n previewSizeBytes?: number;\n reason: WorkspaceFilePreviewReadonlyReason;\n status: \"readonly\";\n }\n | {\n entry: TEntry;\n reason: WorkspaceFilePreviewUnsupportedReason;\n status: \"unsupported\";\n }\n | { entry: TEntry; error: unknown; status: \"error\" };\n\nexport interface WorkspaceFilePreviewReadInput<TEntry> {\n entry: TEntry;\n signal: AbortSignal;\n target: WorkspaceFilePreviewActivationTarget;\n}\n\nexport interface WorkspaceFilePreviewReadResult {\n bytes: Uint8Array | ArrayBuffer;\n contentType?: string | null;\n kind?: WorkspaceFilePreviewKind;\n}\n\nexport type WorkspaceFilePreviewReadOutput =\n | WorkspaceFilePreviewReadResult\n | Uint8Array\n | ArrayBuffer;\n\nexport interface WorkspaceFilePreviewObjectUrlFactory {\n create(bytes: Uint8Array<ArrayBuffer>, contentType: string): string;\n revoke(objectUrl: string): void;\n}\n\nexport interface CreateWorkspaceFilePreviewControllerInput<TEntry> {\n /**\n * Optional source capability gate. `false` blocks every non-directory read;\n * `true` also lets the reader classify locally unsupported files. When\n * omitted, the controller relies on local file classification.\n */\n canReadEntry?: (entry: TEntry) => boolean;\n getEntryKey?: (entry: TEntry) => string;\n objectUrls?: WorkspaceFilePreviewObjectUrlFactory;\n read?: (\n input: WorkspaceFilePreviewReadInput<TEntry>\n ) => Promise<WorkspaceFilePreviewReadOutput | null>;\n toPreviewEntry: (entry: TEntry) => WorkspaceFilePreviewEntry;\n}\n\nexport interface WorkspaceFilePreviewController<TEntry> {\n dispose(): void;\n getSnapshot(): WorkspaceFilePreviewControllerState<TEntry>;\n reload(): Promise<void>;\n setEntry(entry: TEntry | null): Promise<void>;\n subscribe(listener: () => void): () => void;\n}\n\nexport function createWorkspaceFilePreviewController<TEntry>(\n input: CreateWorkspaceFilePreviewControllerInput<TEntry>\n): WorkspaceFilePreviewController<TEntry> {\n return new WorkspaceFilePreviewControllerImpl(input);\n}\n\nclass WorkspaceFilePreviewControllerImpl<\n TEntry\n> implements WorkspaceFilePreviewController<TEntry> {\n private activeEntry: TEntry | null = null;\n private activeEntryKey: string | null = null;\n private abortController: AbortController | null = null;\n private disposed = false;\n private generation = 0;\n private loadPromise: Promise<void> = Promise.resolve();\n private objectUrl: string | null = null;\n private readonly listeners = new Set<() => void>();\n private readonly input: CreateWorkspaceFilePreviewControllerInput<TEntry>;\n private readonly objectUrls: WorkspaceFilePreviewObjectUrlFactory;\n private state: WorkspaceFilePreviewControllerState<TEntry> = {\n status: \"empty\"\n };\n\n constructor(input: CreateWorkspaceFilePreviewControllerInput<TEntry>) {\n this.input = input;\n this.objectUrls = input.objectUrls ?? browserWorkspaceFilePreviewObjectUrls;\n }\n\n dispose(): void {\n if (this.disposed) {\n return;\n }\n this.disposed = true;\n this.cancelLoad();\n this.revokeObjectUrl();\n this.listeners.clear();\n }\n\n getSnapshot(): WorkspaceFilePreviewControllerState<TEntry> {\n return this.state;\n }\n\n reload(): Promise<void> {\n if (this.disposed || !this.activeEntry) {\n return Promise.resolve();\n }\n return this.start(this.activeEntry);\n }\n\n setEntry(entry: TEntry | null): Promise<void> {\n if (this.disposed) {\n return Promise.resolve();\n }\n\n const nextKey = entry ? this.resolveEntryKey(entry) : null;\n if (nextKey === this.activeEntryKey) {\n return this.loadPromise;\n }\n\n this.activeEntry = entry;\n this.activeEntryKey = nextKey;\n if (!entry) {\n this.cancelLoad();\n this.revokeObjectUrl();\n this.updateState({ status: \"empty\" });\n this.loadPromise = Promise.resolve();\n return this.loadPromise;\n }\n return this.start(entry);\n }\n\n subscribe(listener: () => void): () => void {\n if (this.disposed) {\n return () => {};\n }\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n private cancelLoad(): void {\n this.generation += 1;\n this.abortController?.abort();\n this.abortController = null;\n }\n\n private isStale(generation: number): boolean {\n return this.disposed || generation !== this.generation;\n }\n\n private async load(\n entry: TEntry,\n previewEntry: WorkspaceFilePreviewEntry,\n target: WorkspaceFilePreviewActivationTarget,\n generation: number,\n abortController: AbortController\n ): Promise<void> {\n try {\n const result = await this.input.read?.({\n entry,\n signal: abortController.signal,\n target\n });\n if (this.isStale(generation)) {\n return;\n }\n if (!result) {\n this.updateState({\n entry,\n reason: \"file_type\",\n status: \"unsupported\"\n });\n return;\n }\n\n const loaded = createWorkspaceFilePreviewLoadedState({\n bytes:\n result instanceof Uint8Array || result instanceof ArrayBuffer\n ? result\n : result.bytes,\n contentType:\n result instanceof Uint8Array || result instanceof ArrayBuffer\n ? undefined\n : result.contentType,\n entry: previewEntry,\n target:\n result instanceof Uint8Array || result instanceof ArrayBuffer\n ? target\n : { ...target, fileKind: result.kind ?? target.fileKind }\n });\n if (this.isStale(generation)) {\n return;\n }\n\n if (loaded.status === \"image\" || loaded.status === \"video\") {\n const previewSizeBytes = loaded.bytes.byteLength;\n const objectUrl = this.objectUrls.create(\n loaded.bytes,\n loaded.contentType\n );\n if (this.isStale(generation)) {\n this.objectUrls.revoke(objectUrl);\n return;\n }\n this.objectUrl = objectUrl;\n this.updateState({\n entry,\n objectUrl,\n previewSizeBytes,\n status: loaded.status\n });\n return;\n }\n if (loaded.status === \"text\") {\n this.updateState({\n content: loaded.content,\n entry,\n previewSizeBytes: byteLengthOfPreviewReadResult(result),\n status: \"text\"\n });\n return;\n }\n this.updateState({\n entry,\n previewSizeBytes: byteLengthOfPreviewReadResult(result),\n reason: loaded.reason,\n ...(loaded.maxSizeBytes === undefined\n ? {}\n : { maxSizeBytes: loaded.maxSizeBytes }),\n status: \"readonly\"\n });\n } catch (error) {\n if (this.isStale(generation)) {\n return;\n }\n this.updateState({ entry, error, status: \"error\" });\n } finally {\n if (!this.isStale(generation)) {\n this.abortController = null;\n }\n }\n }\n\n private resolveEntryKey(entry: TEntry): string {\n if (this.input.getEntryKey) {\n return this.input.getEntryKey(entry);\n }\n const previewEntry = this.input.toPreviewEntry(entry);\n return [\n previewEntry.kind,\n previewEntry.path,\n previewEntry.name ?? \"\",\n previewEntry.displayName ?? \"\",\n previewEntry.sizeBytes ?? \"\",\n previewEntry.mtimeMs ?? \"\"\n ].join(\"\\0\");\n }\n\n private revokeObjectUrl(): void {\n if (!this.objectUrl) {\n return;\n }\n this.objectUrls.revoke(this.objectUrl);\n this.objectUrl = null;\n }\n\n private start(entry: TEntry): Promise<void> {\n this.cancelLoad();\n this.revokeObjectUrl();\n\n const previewEntry = this.input.toPreviewEntry(entry);\n const readiness = resolveWorkspaceFilePreviewReadiness(previewEntry);\n\n if (readiness.status === \"directory\") {\n this.updateState({ entry, status: \"directory\" });\n this.loadPromise = Promise.resolve();\n return this.loadPromise;\n }\n\n const canRead = this.input.canReadEntry?.(entry);\n if (canRead === false) {\n this.updateState({\n entry,\n reason: \"reader_unavailable\",\n status: \"unsupported\"\n });\n this.loadPromise = Promise.resolve();\n return this.loadPromise;\n }\n\n if (readiness.status === \"unsupported\") {\n if (canRead !== true) {\n this.updateState({\n entry,\n reason: \"file_type\",\n status: \"unsupported\"\n });\n this.loadPromise = Promise.resolve();\n return this.loadPromise;\n }\n if (!this.input.read) {\n this.updateState({\n entry,\n reason: \"reader_unavailable\",\n status: \"unsupported\"\n });\n this.loadPromise = Promise.resolve();\n return this.loadPromise;\n }\n const target: WorkspaceFilePreviewActivationTarget = {\n fileKind: \"text\",\n name:\n previewEntry.name ??\n previewEntry.displayName ??\n previewEntry.path.split(\"/\").pop() ??\n previewEntry.path,\n path: previewEntry.path,\n ...(previewEntry.mtimeMs === undefined\n ? {}\n : { mtimeMs: previewEntry.mtimeMs }),\n ...(previewEntry.sizeBytes === undefined\n ? {}\n : { sizeBytes: previewEntry.sizeBytes })\n };\n const abortController = new AbortController();\n this.abortController = abortController;\n const generation = this.generation;\n this.updateState({ entry, status: \"loading\" });\n this.loadPromise = this.load(\n entry,\n previewEntry,\n target,\n generation,\n abortController\n );\n return this.loadPromise;\n }\n\n if (readiness.status === \"readonly\") {\n this.updateState({\n entry,\n maxSizeBytes: readiness.maxSizeBytes,\n reason: readiness.reason,\n status: \"readonly\"\n });\n this.loadPromise = Promise.resolve();\n return this.loadPromise;\n }\n\n if (!this.input.read) {\n this.updateState({\n entry,\n reason: \"reader_unavailable\",\n status: \"unsupported\"\n });\n this.loadPromise = Promise.resolve();\n return this.loadPromise;\n }\n\n const abortController = new AbortController();\n this.abortController = abortController;\n const generation = this.generation;\n this.updateState({ entry, status: \"loading\" });\n this.loadPromise = this.load(\n entry,\n previewEntry,\n readiness.target,\n generation,\n abortController\n );\n return this.loadPromise;\n }\n\n private updateState(\n state: WorkspaceFilePreviewControllerState<TEntry>\n ): void {\n if (this.disposed) {\n return;\n }\n this.state = state;\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n\nconst browserWorkspaceFilePreviewObjectUrls: WorkspaceFilePreviewObjectUrlFactory =\n {\n create(bytes, contentType) {\n return URL.createObjectURL(new Blob([bytes], { type: contentType }));\n },\n revoke(objectUrl) {\n URL.revokeObjectURL(objectUrl);\n }\n };\n\nfunction byteLengthOfPreviewReadResult(\n result: WorkspaceFilePreviewReadOutput\n): number {\n const bytes =\n result instanceof Uint8Array || result instanceof ArrayBuffer\n ? result\n : result.bytes;\n return bytes.byteLength;\n}\n"],"mappings":"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","names":["abortController","generation"]}
|
package/dist/core/index.d.ts
CHANGED
|
@@ -37,10 +37,6 @@ type WorkspaceFilePreviewLoadedState<TEntry extends WorkspaceFilePreviewEntry, T
|
|
|
37
37
|
content: string;
|
|
38
38
|
entry: TTarget;
|
|
39
39
|
status: "text";
|
|
40
|
-
} | {
|
|
41
|
-
content: string;
|
|
42
|
-
entry: TTarget;
|
|
43
|
-
status: "html";
|
|
44
40
|
} | {
|
|
45
41
|
bytes: Uint8Array<ArrayBuffer>;
|
|
46
42
|
contentType: string;
|
|
@@ -77,7 +73,6 @@ declare function createWorkspaceFilePreviewLoadedState<TEntry extends WorkspaceF
|
|
|
77
73
|
bytes: Uint8Array | ArrayBuffer;
|
|
78
74
|
contentType?: string | null;
|
|
79
75
|
entry: TEntry;
|
|
80
|
-
renderHtml?: boolean;
|
|
81
76
|
target: TTarget;
|
|
82
77
|
}): WorkspaceFilePreviewLoadedState<TEntry, TTarget>;
|
|
83
78
|
declare function resolveWorkspaceFilePreviewName(entry: Pick<WorkspaceFilePreviewEntry, "displayName" | "name" | "path">): string;
|
|
@@ -89,4 +84,79 @@ declare function copyWorkspaceFilePreviewBytes(bytes: Uint8Array | ArrayBuffer):
|
|
|
89
84
|
declare function looksLikeBinaryText(content: string): boolean;
|
|
90
85
|
declare function formatWorkspacePreviewByteLimit(sizeBytes: number): string;
|
|
91
86
|
|
|
92
|
-
|
|
87
|
+
type WorkspaceFilePreviewUnsupportedReason = "file_type" | "reader_unavailable";
|
|
88
|
+
type WorkspaceFilePreviewControllerState<TEntry> = {
|
|
89
|
+
status: "empty";
|
|
90
|
+
} | {
|
|
91
|
+
entry: TEntry;
|
|
92
|
+
status: "directory";
|
|
93
|
+
} | {
|
|
94
|
+
entry: TEntry;
|
|
95
|
+
status: "loading";
|
|
96
|
+
} | {
|
|
97
|
+
content: string;
|
|
98
|
+
entry: TEntry;
|
|
99
|
+
previewSizeBytes: number;
|
|
100
|
+
status: "text";
|
|
101
|
+
} | {
|
|
102
|
+
entry: TEntry;
|
|
103
|
+
objectUrl: string;
|
|
104
|
+
previewSizeBytes: number;
|
|
105
|
+
status: "image";
|
|
106
|
+
} | {
|
|
107
|
+
entry: TEntry;
|
|
108
|
+
objectUrl: string;
|
|
109
|
+
previewSizeBytes: number;
|
|
110
|
+
status: "video";
|
|
111
|
+
} | {
|
|
112
|
+
entry: TEntry;
|
|
113
|
+
maxSizeBytes?: number;
|
|
114
|
+
previewSizeBytes?: number;
|
|
115
|
+
reason: WorkspaceFilePreviewReadonlyReason;
|
|
116
|
+
status: "readonly";
|
|
117
|
+
} | {
|
|
118
|
+
entry: TEntry;
|
|
119
|
+
reason: WorkspaceFilePreviewUnsupportedReason;
|
|
120
|
+
status: "unsupported";
|
|
121
|
+
} | {
|
|
122
|
+
entry: TEntry;
|
|
123
|
+
error: unknown;
|
|
124
|
+
status: "error";
|
|
125
|
+
};
|
|
126
|
+
interface WorkspaceFilePreviewReadInput<TEntry> {
|
|
127
|
+
entry: TEntry;
|
|
128
|
+
signal: AbortSignal;
|
|
129
|
+
target: WorkspaceFilePreviewActivationTarget;
|
|
130
|
+
}
|
|
131
|
+
interface WorkspaceFilePreviewReadResult {
|
|
132
|
+
bytes: Uint8Array | ArrayBuffer;
|
|
133
|
+
contentType?: string | null;
|
|
134
|
+
kind?: WorkspaceFilePreviewKind;
|
|
135
|
+
}
|
|
136
|
+
type WorkspaceFilePreviewReadOutput = WorkspaceFilePreviewReadResult | Uint8Array | ArrayBuffer;
|
|
137
|
+
interface WorkspaceFilePreviewObjectUrlFactory {
|
|
138
|
+
create(bytes: Uint8Array<ArrayBuffer>, contentType: string): string;
|
|
139
|
+
revoke(objectUrl: string): void;
|
|
140
|
+
}
|
|
141
|
+
interface CreateWorkspaceFilePreviewControllerInput<TEntry> {
|
|
142
|
+
/**
|
|
143
|
+
* Optional source capability gate. `false` blocks every non-directory read;
|
|
144
|
+
* `true` also lets the reader classify locally unsupported files. When
|
|
145
|
+
* omitted, the controller relies on local file classification.
|
|
146
|
+
*/
|
|
147
|
+
canReadEntry?: (entry: TEntry) => boolean;
|
|
148
|
+
getEntryKey?: (entry: TEntry) => string;
|
|
149
|
+
objectUrls?: WorkspaceFilePreviewObjectUrlFactory;
|
|
150
|
+
read?: (input: WorkspaceFilePreviewReadInput<TEntry>) => Promise<WorkspaceFilePreviewReadOutput | null>;
|
|
151
|
+
toPreviewEntry: (entry: TEntry) => WorkspaceFilePreviewEntry;
|
|
152
|
+
}
|
|
153
|
+
interface WorkspaceFilePreviewController<TEntry> {
|
|
154
|
+
dispose(): void;
|
|
155
|
+
getSnapshot(): WorkspaceFilePreviewControllerState<TEntry>;
|
|
156
|
+
reload(): Promise<void>;
|
|
157
|
+
setEntry(entry: TEntry | null): Promise<void>;
|
|
158
|
+
subscribe(listener: () => void): () => void;
|
|
159
|
+
}
|
|
160
|
+
declare function createWorkspaceFilePreviewController<TEntry>(input: CreateWorkspaceFilePreviewControllerInput<TEntry>): WorkspaceFilePreviewController<TEntry>;
|
|
161
|
+
|
|
162
|
+
export { type CreateWorkspaceFilePreviewControllerInput, type WorkspaceFilePreviewActivationTarget, type WorkspaceFilePreviewController, type WorkspaceFilePreviewControllerState, type WorkspaceFilePreviewEntry, type WorkspaceFilePreviewEntryKind, type WorkspaceFilePreviewKind, type WorkspaceFilePreviewLoadedState, type WorkspaceFilePreviewObjectUrlFactory, type WorkspaceFilePreviewReadInput, type WorkspaceFilePreviewReadOutput, type WorkspaceFilePreviewReadResult, type WorkspaceFilePreviewReadiness, type WorkspaceFilePreviewReadonlyReason, type WorkspaceFilePreviewUnsupportedReason, type WorkspaceFileVisualKind, classifyWorkspaceFilePreviewKind, copyWorkspaceFilePreviewBytes, createWorkspaceFilePreviewController, createWorkspaceFilePreviewLoadedState, decodeWorkspaceTextFile, formatWorkspacePreviewByteLimit, isWorkspaceFileBrowserOpenable, isWorkspacePreviewFileTooLarge, isWorkspaceTextFileTooLarge, looksLikeBinaryText, normalizeWorkspaceFilePreviewBytes, resolveWorkspaceFileActivationTarget, resolveWorkspaceFileExtension, resolveWorkspaceFilePreviewName, resolveWorkspaceFilePreviewReadiness, resolveWorkspaceFileVisualKind, resolveWorkspaceImageMimeType, resolveWorkspaceVideoMimeType, shouldFilterVideoPlayersForOpenWith, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes, workspaceFileVideoHandlerCollisionExtensions };
|
package/dist/core/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
classifyWorkspaceFilePreviewKind,
|
|
3
3
|
copyWorkspaceFilePreviewBytes,
|
|
4
|
+
createWorkspaceFilePreviewController,
|
|
4
5
|
createWorkspaceFilePreviewLoadedState,
|
|
5
6
|
decodeWorkspaceTextFile,
|
|
6
7
|
formatWorkspacePreviewByteLimit,
|
|
@@ -20,10 +21,11 @@ import {
|
|
|
20
21
|
workspaceFilePreviewMaxBytes,
|
|
21
22
|
workspaceFileTextMaxBytes,
|
|
22
23
|
workspaceFileVideoHandlerCollisionExtensions
|
|
23
|
-
} from "../chunk-
|
|
24
|
+
} from "../chunk-SUQYO7VX.js";
|
|
24
25
|
export {
|
|
25
26
|
classifyWorkspaceFilePreviewKind,
|
|
26
27
|
copyWorkspaceFilePreviewBytes,
|
|
28
|
+
createWorkspaceFilePreviewController,
|
|
27
29
|
createWorkspaceFilePreviewLoadedState,
|
|
28
30
|
decodeWorkspaceTextFile,
|
|
29
31
|
formatWorkspacePreviewByteLimit,
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { WorkspaceFilePreviewActivationTarget, WorkspaceFilePreviewEntry, WorkspaceFilePreviewEntryKind, WorkspaceFilePreviewKind, WorkspaceFilePreviewLoadedState, WorkspaceFilePreviewReadiness, WorkspaceFilePreviewReadonlyReason, WorkspaceFileVisualKind, classifyWorkspaceFilePreviewKind, copyWorkspaceFilePreviewBytes, createWorkspaceFilePreviewLoadedState, decodeWorkspaceTextFile, formatWorkspacePreviewByteLimit, isWorkspaceFileBrowserOpenable, isWorkspacePreviewFileTooLarge, isWorkspaceTextFileTooLarge, looksLikeBinaryText, normalizeWorkspaceFilePreviewBytes, resolveWorkspaceFileActivationTarget, resolveWorkspaceFileExtension, resolveWorkspaceFilePreviewName, resolveWorkspaceFilePreviewReadiness, resolveWorkspaceFileVisualKind, resolveWorkspaceImageMimeType, resolveWorkspaceVideoMimeType, shouldFilterVideoPlayersForOpenWith, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes, workspaceFileVideoHandlerCollisionExtensions } from './core/index.js';
|
|
1
|
+
export { CreateWorkspaceFilePreviewControllerInput, WorkspaceFilePreviewActivationTarget, WorkspaceFilePreviewController, WorkspaceFilePreviewControllerState, WorkspaceFilePreviewEntry, WorkspaceFilePreviewEntryKind, WorkspaceFilePreviewKind, WorkspaceFilePreviewLoadedState, WorkspaceFilePreviewObjectUrlFactory, WorkspaceFilePreviewReadInput, WorkspaceFilePreviewReadOutput, WorkspaceFilePreviewReadResult, WorkspaceFilePreviewReadiness, WorkspaceFilePreviewReadonlyReason, WorkspaceFilePreviewUnsupportedReason, WorkspaceFileVisualKind, classifyWorkspaceFilePreviewKind, copyWorkspaceFilePreviewBytes, createWorkspaceFilePreviewController, createWorkspaceFilePreviewLoadedState, decodeWorkspaceTextFile, formatWorkspacePreviewByteLimit, isWorkspaceFileBrowserOpenable, isWorkspacePreviewFileTooLarge, isWorkspaceTextFileTooLarge, looksLikeBinaryText, normalizeWorkspaceFilePreviewBytes, resolveWorkspaceFileActivationTarget, resolveWorkspaceFileExtension, resolveWorkspaceFilePreviewName, resolveWorkspaceFilePreviewReadiness, resolveWorkspaceFileVisualKind, resolveWorkspaceImageMimeType, resolveWorkspaceVideoMimeType, shouldFilterVideoPlayersForOpenWith, workspaceFilePreviewMaxBytes, workspaceFileTextMaxBytes, workspaceFileVideoHandlerCollisionExtensions } from './core/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
classifyWorkspaceFilePreviewKind,
|
|
3
3
|
copyWorkspaceFilePreviewBytes,
|
|
4
|
+
createWorkspaceFilePreviewController,
|
|
4
5
|
createWorkspaceFilePreviewLoadedState,
|
|
5
6
|
decodeWorkspaceTextFile,
|
|
6
7
|
formatWorkspacePreviewByteLimit,
|
|
@@ -20,10 +21,11 @@ import {
|
|
|
20
21
|
workspaceFilePreviewMaxBytes,
|
|
21
22
|
workspaceFileTextMaxBytes,
|
|
22
23
|
workspaceFileVideoHandlerCollisionExtensions
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-SUQYO7VX.js";
|
|
24
25
|
export {
|
|
25
26
|
classifyWorkspaceFilePreviewKind,
|
|
26
27
|
copyWorkspaceFilePreviewBytes,
|
|
28
|
+
createWorkspaceFilePreviewController,
|
|
27
29
|
createWorkspaceFilePreviewLoadedState,
|
|
28
30
|
decodeWorkspaceTextFile,
|
|
29
31
|
formatWorkspacePreviewByteLimit,
|
package/dist/react/index.d.ts
CHANGED
|
@@ -12,10 +12,6 @@ type WorkspaceFilePreviewSurfaceState<TEntry> = {
|
|
|
12
12
|
content: string;
|
|
13
13
|
entry: TEntry;
|
|
14
14
|
status: "text";
|
|
15
|
-
} | {
|
|
16
|
-
content: string;
|
|
17
|
-
entry: TEntry;
|
|
18
|
-
status: "html";
|
|
19
15
|
} | {
|
|
20
16
|
entry: TEntry;
|
|
21
17
|
objectUrl: string;
|
|
@@ -37,26 +33,17 @@ type WorkspaceFilePreviewSurfaceState<TEntry> = {
|
|
|
37
33
|
message: string;
|
|
38
34
|
status: "error";
|
|
39
35
|
};
|
|
36
|
+
type WorkspaceFilePreviewSurfaceVariant = "canvas" | "compact" | "detail";
|
|
40
37
|
interface WorkspaceFilePreviewSurfaceProps<TEntry> {
|
|
41
38
|
directoryMessage: string;
|
|
42
39
|
emptyMessage: string;
|
|
43
|
-
frameClassName: string;
|
|
44
|
-
htmlClassName?: string;
|
|
45
|
-
htmlFrameClassName?: string;
|
|
46
|
-
htmlTitle?: (entry: TEntry) => string;
|
|
47
40
|
imageAlt: (entry: TEntry) => string;
|
|
48
|
-
imageFrameClassName?: string;
|
|
49
|
-
imageClassName?: string;
|
|
50
41
|
loadingIndicator: ReactNode;
|
|
51
42
|
loadingMessage: string;
|
|
52
|
-
messageClassName?: string;
|
|
53
43
|
renderIcon: (entry: TEntry) => ReactNode;
|
|
54
44
|
state: WorkspaceFilePreviewSurfaceState<TEntry>;
|
|
55
|
-
|
|
56
|
-
textFrameClassName?: string;
|
|
57
|
-
videoClassName?: string;
|
|
58
|
-
videoFrameClassName?: string;
|
|
45
|
+
variant: WorkspaceFilePreviewSurfaceVariant;
|
|
59
46
|
}
|
|
60
|
-
declare function WorkspaceFilePreviewSurface<TEntry>({ directoryMessage, emptyMessage,
|
|
47
|
+
declare function WorkspaceFilePreviewSurface<TEntry>({ directoryMessage, emptyMessage, imageAlt, loadingIndicator, loadingMessage, renderIcon, state, variant }: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement;
|
|
61
48
|
|
|
62
|
-
export { WorkspaceFilePreviewSurface, type WorkspaceFilePreviewSurfaceProps, type WorkspaceFilePreviewSurfaceState };
|
|
49
|
+
export { WorkspaceFilePreviewSurface, type WorkspaceFilePreviewSurfaceProps, type WorkspaceFilePreviewSurfaceState, type WorkspaceFilePreviewSurfaceVariant };
|
package/dist/react/index.js
CHANGED
|
@@ -3,31 +3,22 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
function WorkspaceFilePreviewSurface({
|
|
4
4
|
directoryMessage,
|
|
5
5
|
emptyMessage,
|
|
6
|
-
frameClassName,
|
|
7
|
-
htmlClassName = "h-full w-full border-0 bg-white",
|
|
8
|
-
htmlFrameClassName,
|
|
9
|
-
htmlTitle,
|
|
10
6
|
imageAlt,
|
|
11
|
-
imageClassName = "max-h-full max-w-full rounded-[6px] object-contain",
|
|
12
|
-
imageFrameClassName,
|
|
13
7
|
loadingIndicator,
|
|
14
8
|
loadingMessage,
|
|
15
|
-
messageClassName = "max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]",
|
|
16
9
|
renderIcon,
|
|
17
10
|
state,
|
|
18
|
-
|
|
19
|
-
textFrameClassName,
|
|
20
|
-
videoClassName = "block max-h-full max-w-full rounded-[6px] object-contain",
|
|
21
|
-
videoFrameClassName
|
|
11
|
+
variant
|
|
22
12
|
}) {
|
|
13
|
+
const styles = workspaceFilePreviewSurfaceStyles[variant];
|
|
23
14
|
switch (state.status) {
|
|
24
15
|
case "directory":
|
|
25
|
-
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className:
|
|
16
|
+
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className: styles.frame, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2.5 text-center text-[13px] leading-5 text-[var(--text-tertiary)]", children: [
|
|
26
17
|
renderIcon(state.entry),
|
|
27
18
|
/* @__PURE__ */ jsx("span", { children: directoryMessage })
|
|
28
19
|
] }) });
|
|
29
20
|
case "loading":
|
|
30
|
-
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className:
|
|
21
|
+
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className: styles.frame, children: /* @__PURE__ */ jsxs("div", { className: "space-y-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]", children: [
|
|
31
22
|
loadingIndicator,
|
|
32
23
|
/* @__PURE__ */ jsx("span", { children: loadingMessage })
|
|
33
24
|
] }) });
|
|
@@ -35,12 +26,12 @@ function WorkspaceFilePreviewSurface({
|
|
|
35
26
|
return /* @__PURE__ */ jsx(
|
|
36
27
|
WorkspaceFilePreviewFrame,
|
|
37
28
|
{
|
|
38
|
-
className: joinClassNames(
|
|
29
|
+
className: joinClassNames(styles.frame, styles.imageFrame),
|
|
39
30
|
children: /* @__PURE__ */ jsx(
|
|
40
31
|
"img",
|
|
41
32
|
{
|
|
42
33
|
alt: imageAlt(state.entry),
|
|
43
|
-
className:
|
|
34
|
+
className: styles.image,
|
|
44
35
|
src: state.objectUrl
|
|
45
36
|
}
|
|
46
37
|
)
|
|
@@ -50,36 +41,20 @@ function WorkspaceFilePreviewSurface({
|
|
|
50
41
|
return /* @__PURE__ */ jsx(
|
|
51
42
|
WorkspaceFilePreviewFrame,
|
|
52
43
|
{
|
|
53
|
-
className: joinClassNames(
|
|
54
|
-
children: /* @__PURE__ */ jsx("pre", { className:
|
|
55
|
-
}
|
|
56
|
-
);
|
|
57
|
-
case "html":
|
|
58
|
-
return /* @__PURE__ */ jsx(
|
|
59
|
-
WorkspaceFilePreviewFrame,
|
|
60
|
-
{
|
|
61
|
-
className: joinClassNames(frameClassName, htmlFrameClassName),
|
|
62
|
-
children: /* @__PURE__ */ jsx(
|
|
63
|
-
"iframe",
|
|
64
|
-
{
|
|
65
|
-
className: htmlClassName,
|
|
66
|
-
sandbox: "allow-forms allow-scripts",
|
|
67
|
-
srcDoc: state.content,
|
|
68
|
-
title: htmlTitle?.(state.entry) ?? "HTML preview"
|
|
69
|
-
}
|
|
70
|
-
)
|
|
44
|
+
className: joinClassNames(styles.frame, styles.textFrame),
|
|
45
|
+
children: /* @__PURE__ */ jsx("pre", { className: styles.text, children: state.content })
|
|
71
46
|
}
|
|
72
47
|
);
|
|
73
48
|
case "video":
|
|
74
49
|
return /* @__PURE__ */ jsx(
|
|
75
50
|
WorkspaceFilePreviewFrame,
|
|
76
51
|
{
|
|
77
|
-
className: joinClassNames(
|
|
52
|
+
className: joinClassNames(styles.frame, styles.videoFrame),
|
|
78
53
|
children: /* @__PURE__ */ jsx(
|
|
79
54
|
"video",
|
|
80
55
|
{
|
|
81
56
|
"aria-label": imageAlt(state.entry),
|
|
82
|
-
className:
|
|
57
|
+
className: styles.video,
|
|
83
58
|
muted: true,
|
|
84
59
|
playsInline: true,
|
|
85
60
|
preload: "metadata",
|
|
@@ -97,14 +72,46 @@ function WorkspaceFilePreviewSurface({
|
|
|
97
72
|
case "readonly":
|
|
98
73
|
case "unsupported":
|
|
99
74
|
case "error":
|
|
100
|
-
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className:
|
|
75
|
+
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className: styles.frame, children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]", children: [
|
|
101
76
|
renderIcon(state.entry),
|
|
102
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: styles.message, children: state.message })
|
|
103
78
|
] }) });
|
|
104
79
|
case "empty":
|
|
105
|
-
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className:
|
|
80
|
+
return /* @__PURE__ */ jsx(WorkspaceFilePreviewFrame, { className: styles.frame, children: /* @__PURE__ */ jsx("span", { className: styles.message, children: emptyMessage }) });
|
|
106
81
|
}
|
|
107
82
|
}
|
|
83
|
+
var workspaceFilePreviewSurfaceStyles = {
|
|
84
|
+
compact: {
|
|
85
|
+
frame: "flex aspect-[3/2] w-full flex-col items-center justify-center overflow-hidden rounded-[8px] border border-[var(--line-2,var(--border-2))] bg-[var(--transparency-block)] p-0 text-center",
|
|
86
|
+
image: "max-h-full max-w-full rounded-[6px] object-contain",
|
|
87
|
+
imageFrame: "p-3",
|
|
88
|
+
message: "mx-auto max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-secondary)] [overflow-wrap:anywhere]",
|
|
89
|
+
text: "h-full w-full overflow-auto p-3 text-left text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]",
|
|
90
|
+
textFrame: "items-stretch justify-stretch",
|
|
91
|
+
video: "block max-h-full max-w-full rounded-[6px] object-contain",
|
|
92
|
+
videoFrame: "p-3"
|
|
93
|
+
},
|
|
94
|
+
detail: {
|
|
95
|
+
frame: "flex h-60 min-h-60 max-h-60 items-center justify-center overflow-hidden rounded-lg bg-[var(--transparency-block)]",
|
|
96
|
+
image: "max-h-full max-w-full rounded-[6px] object-contain",
|
|
97
|
+
imageFrame: "p-4",
|
|
98
|
+
message: "max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]",
|
|
99
|
+
text: "h-full overflow-auto p-4 text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]",
|
|
100
|
+
textFrame: "items-stretch justify-stretch",
|
|
101
|
+
video: "block max-h-full max-w-full rounded-[6px] object-contain",
|
|
102
|
+
videoFrame: "p-4"
|
|
103
|
+
},
|
|
104
|
+
canvas: {
|
|
105
|
+
frame: "flex h-full min-h-0 min-w-0 w-full items-center justify-center overflow-hidden bg-[var(--background-fronted)] text-[var(--text-tertiary)]",
|
|
106
|
+
image: "block max-h-full max-w-full object-contain",
|
|
107
|
+
imageFrame: "overflow-auto p-3",
|
|
108
|
+
message: "max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]",
|
|
109
|
+
text: "m-0 h-full min-h-0 min-w-0 w-full overflow-auto whitespace-pre-wrap break-words p-3 font-[var(--tsh-font-mono)] text-[11px] leading-[18px] text-[var(--text-secondary)]",
|
|
110
|
+
textFrame: "items-stretch justify-stretch",
|
|
111
|
+
video: "block max-h-full max-w-full object-contain",
|
|
112
|
+
videoFrame: "overflow-auto p-3"
|
|
113
|
+
}
|
|
114
|
+
};
|
|
108
115
|
function WorkspaceFilePreviewFrame({
|
|
109
116
|
children,
|
|
110
117
|
className
|
package/dist/react/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/react/workspaceFilePreviewSurface.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\n\nexport type WorkspaceFilePreviewSurfaceState<TEntry> =\n | { status: \"empty\" }\n | { entry: TEntry; status: \"directory\" }\n | { entry: TEntry; status: \"loading\" }\n | { content: string; entry: TEntry; status: \"text\" }\n | {
|
|
1
|
+
{"version":3,"sources":["../../src/react/workspaceFilePreviewSurface.tsx"],"sourcesContent":["import type { ReactElement, ReactNode } from \"react\";\n\nexport type WorkspaceFilePreviewSurfaceState<TEntry> =\n | { status: \"empty\" }\n | { entry: TEntry; status: \"directory\" }\n | { entry: TEntry; status: \"loading\" }\n | { content: string; entry: TEntry; status: \"text\" }\n | { entry: TEntry; objectUrl: string; status: \"image\" }\n | { entry: TEntry; objectUrl: string; status: \"video\" }\n | { entry: TEntry; message: string; status: \"readonly\" }\n | { entry: TEntry; message: string; status: \"unsupported\" }\n | { entry: TEntry; message: string; status: \"error\" };\n\nexport type WorkspaceFilePreviewSurfaceVariant =\n | \"canvas\"\n | \"compact\"\n | \"detail\";\n\nexport interface WorkspaceFilePreviewSurfaceProps<TEntry> {\n directoryMessage: string;\n emptyMessage: string;\n imageAlt: (entry: TEntry) => string;\n loadingIndicator: ReactNode;\n loadingMessage: string;\n renderIcon: (entry: TEntry) => ReactNode;\n state: WorkspaceFilePreviewSurfaceState<TEntry>;\n variant: WorkspaceFilePreviewSurfaceVariant;\n}\n\nexport function WorkspaceFilePreviewSurface<TEntry>({\n directoryMessage,\n emptyMessage,\n imageAlt,\n loadingIndicator,\n loadingMessage,\n renderIcon,\n state,\n variant\n}: WorkspaceFilePreviewSurfaceProps<TEntry>): ReactElement {\n const styles = workspaceFilePreviewSurfaceStyles[variant];\n switch (state.status) {\n case \"directory\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-2.5 text-center text-[13px] leading-5 text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span>{directoryMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"loading\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"space-y-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {loadingIndicator}\n <span>{loadingMessage}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"image\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.imageFrame)}\n >\n <img\n alt={imageAlt(state.entry)}\n className={styles.image}\n src={state.objectUrl}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"text\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.textFrame)}\n >\n <pre className={styles.text}>{state.content}</pre>\n </WorkspaceFilePreviewFrame>\n );\n case \"video\":\n return (\n <WorkspaceFilePreviewFrame\n className={joinClassNames(styles.frame, styles.videoFrame)}\n >\n <video\n aria-label={imageAlt(state.entry)}\n className={styles.video}\n muted\n playsInline\n preload=\"metadata\"\n src={state.objectUrl}\n onLoadedMetadata={(event) => {\n const video = event.currentTarget;\n if (video.duration > 0 && video.currentTime === 0) {\n video.currentTime = Math.min(0.1, video.duration / 2);\n }\n }}\n />\n </WorkspaceFilePreviewFrame>\n );\n case \"readonly\":\n case \"unsupported\":\n case \"error\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <div className=\"flex flex-col items-center justify-center gap-3 px-4 text-center text-[13px] text-[var(--text-tertiary)]\">\n {renderIcon(state.entry)}\n <span className={styles.message}>{state.message}</span>\n </div>\n </WorkspaceFilePreviewFrame>\n );\n case \"empty\":\n return (\n <WorkspaceFilePreviewFrame className={styles.frame}>\n <span className={styles.message}>{emptyMessage}</span>\n </WorkspaceFilePreviewFrame>\n );\n }\n}\n\nconst workspaceFilePreviewSurfaceStyles: Record<\n WorkspaceFilePreviewSurfaceVariant,\n {\n frame: string;\n image: string;\n imageFrame: string;\n message: string;\n text: string;\n textFrame: string;\n video: string;\n videoFrame: string;\n }\n> = {\n compact: {\n frame:\n \"flex aspect-[3/2] w-full flex-col items-center justify-center overflow-hidden rounded-[8px] border border-[var(--line-2,var(--border-2))] bg-[var(--transparency-block)] p-0 text-center\",\n image: \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrame: \"p-3\",\n message:\n \"mx-auto max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-secondary)] [overflow-wrap:anywhere]\",\n text: \"h-full w-full overflow-auto p-3 text-left text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full rounded-[6px] object-contain\",\n videoFrame: \"p-3\"\n },\n detail: {\n frame:\n \"flex h-60 min-h-60 max-h-60 items-center justify-center overflow-hidden rounded-lg bg-[var(--transparency-block)]\",\n image: \"max-h-full max-w-full rounded-[6px] object-contain\",\n imageFrame: \"p-4\",\n message:\n \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n text: \"h-full overflow-auto p-4 text-[11px] leading-5 whitespace-pre-wrap break-words text-[var(--text-primary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full rounded-[6px] object-contain\",\n videoFrame: \"p-4\"\n },\n canvas: {\n frame:\n \"flex h-full min-h-0 min-w-0 w-full items-center justify-center overflow-hidden bg-[var(--background-fronted)] text-[var(--text-tertiary)]\",\n image: \"block max-h-full max-w-full object-contain\",\n imageFrame: \"overflow-auto p-3\",\n message:\n \"max-w-[24ch] text-center text-[13px] leading-5 text-[var(--text-tertiary)] [overflow-wrap:anywhere]\",\n text: \"m-0 h-full min-h-0 min-w-0 w-full overflow-auto whitespace-pre-wrap break-words p-3 font-[var(--tsh-font-mono)] text-[11px] leading-[18px] text-[var(--text-secondary)]\",\n textFrame: \"items-stretch justify-stretch\",\n video: \"block max-h-full max-w-full object-contain\",\n videoFrame: \"overflow-auto p-3\"\n }\n};\n\nfunction WorkspaceFilePreviewFrame({\n children,\n className\n}: {\n children: ReactNode;\n className: string;\n}): ReactElement {\n return <div className={className}>{children}</div>;\n}\n\nfunction joinClassNames(\n ...classNames: Array<string | false | null | undefined>\n): string {\n return classNames.filter(Boolean).join(\" \");\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/workspaceFilePreview.ts"],"sourcesContent":["export type WorkspaceFilePreviewEntryKind =\n | \"file\"\n | \"directory\"\n | \"folder\"\n | \"unknown\"\n | (string & {});\n\nexport type WorkspaceFilePreviewKind = \"image\" | \"text\" | \"video\";\n\nexport type WorkspaceFileVisualKind =\n | \"binary\"\n | \"code\"\n | \"directory\"\n | \"document\"\n | \"image\"\n | \"markdown\"\n | \"video\";\n\nexport interface WorkspaceFilePreviewEntry {\n displayName?: string;\n kind: WorkspaceFilePreviewEntryKind;\n mtimeMs?: number | null;\n name?: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport interface WorkspaceFilePreviewActivationTarget {\n fileKind: WorkspaceFilePreviewKind;\n mtimeMs?: number | null;\n name: string;\n path: string;\n sizeBytes?: number | null;\n}\n\nexport type WorkspaceFilePreviewReadonlyReason =\n | \"binary\"\n | \"decode_failed\"\n | \"file_too_large\"\n | \"text_too_large\";\n\nexport type WorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget =\n WorkspaceFilePreviewActivationTarget\n> =\n | { entry: TEntry; status: \"directory\" }\n | {\n entry: TEntry;\n maxSizeBytes: number;\n reason: Extract<\n WorkspaceFilePreviewReadonlyReason,\n \"file_too_large\" | \"text_too_large\"\n >;\n status: \"readonly\";\n }\n | { entry: TEntry; status: \"unsupported\" }\n | { entry: TEntry; status: \"ready\"; target: TTarget };\n\nexport type WorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n> =\n | { content: string; entry: TTarget; status: \"text\" }\n | { content: string; entry: TTarget; status: \"html\" }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string;\n entry: TTarget;\n status: \"image\";\n }\n | {\n bytes: Uint8Array<ArrayBuffer>;\n contentType: string;\n entry: TTarget;\n status: \"video\";\n }\n | {\n entry: TEntry;\n maxSizeBytes?: number;\n reason: WorkspaceFilePreviewReadonlyReason;\n status: \"readonly\";\n };\n\nconst imageExtensions = new Set([\n \"avif\",\n \"gif\",\n \"jpeg\",\n \"jpg\",\n \"png\",\n \"svg\",\n \"webp\"\n]);\nconst browserOpenableHtmlExtensions = new Set([\n \"htm\",\n \"html\",\n \"shtml\",\n \"xhtml\"\n]);\nconst browserOpenableVideoExtensions = new Set([\"mp4\", \"webm\"]);\n\nconst videoExtensions = new Set([\n \"avi\",\n \"m2ts\",\n \"mkv\",\n \"mov\",\n \"mp4\",\n \"mpeg\",\n \"mpg\",\n \"mts\",\n \"webm\",\n \"wmv\"\n]);\n/**\n * Extensions where macOS Launch Services may register video handlers even when\n * the workspace file is source code (UTI / uniform type collisions).\n */\nexport const workspaceFileVideoHandlerCollisionExtensions = new Set([\"ts\"]);\nconst markdownExtensions = new Set([\"md\", \"mdx\"]);\nconst codeExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"java\",\n \"js\",\n \"jsx\",\n \"json\",\n \"lua\",\n \"m\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst documentExtensions = new Set([\n \"csv\",\n \"doc\",\n \"docx\",\n \"log\",\n \"pdf\",\n \"rtf\",\n \"txt\",\n \"xls\",\n \"xlsx\"\n]);\nconst textExtensions = new Set([\n \"bash\",\n \"c\",\n \"cc\",\n \"conf\",\n \"cpp\",\n \"cs\",\n \"css\",\n \"csv\",\n \"env\",\n \"go\",\n \"h\",\n \"hpp\",\n \"html\",\n \"ini\",\n \"java\",\n \"js\",\n \"json\",\n \"jsx\",\n \"log\",\n \"lua\",\n \"m\",\n \"md\",\n \"mdx\",\n \"mm\",\n \"php\",\n \"plist\",\n \"proto\",\n \"py\",\n \"rb\",\n \"rs\",\n \"sh\",\n \"sql\",\n \"swift\",\n \"toml\",\n \"ts\",\n \"tsx\",\n \"txt\",\n \"xml\",\n \"yaml\",\n \"yml\",\n \"zsh\"\n]);\nconst textFileNames = new Set([\n \".gitignore\",\n \".npmrc\",\n \".nvmrc\",\n \"dockerfile\",\n \"makefile\",\n \"readme\"\n]);\n\nexport const workspaceFileTextMaxBytes = 1024 * 1024;\nexport const workspaceFilePreviewMaxBytes = 20 * 1024 * 1024;\n\nexport function resolveWorkspaceFileVisualKind(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): WorkspaceFileVisualKind {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return \"directory\";\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (imageExtensions.has(extension)) {\n return \"image\";\n }\n if (videoExtensions.has(extension)) {\n return \"video\";\n }\n if (markdownExtensions.has(extension)) {\n return \"markdown\";\n }\n if (codeExtensions.has(extension)) {\n return \"code\";\n }\n if (documentExtensions.has(extension)) {\n return \"document\";\n }\n return \"binary\";\n}\n\nexport function resolveWorkspaceFileExtension(pathOrName: string): string {\n const name = pathOrName.split(\"/\").pop()?.trim().toLowerCase() ?? \"\";\n const dotIndex = name.lastIndexOf(\".\");\n return dotIndex > 0 ? name.slice(dotIndex + 1) : \"\";\n}\n\nexport function isWorkspaceFileBrowserOpenable(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (\n extension === \"pdf\" ||\n browserOpenableHtmlExtensions.has(extension) ||\n imageExtensions.has(extension) ||\n browserOpenableVideoExtensions.has(extension)\n ) {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function shouldFilterVideoPlayersForOpenWith(\n entry: Pick<WorkspaceFilePreviewEntry, \"kind\" | \"name\" | \"path\">\n): boolean {\n if (entry.kind !== \"file\") {\n return false;\n }\n\n const visualKind = resolveWorkspaceFileVisualKind(entry);\n if (visualKind === \"video\") {\n return false;\n }\n\n const extension = resolveWorkspaceFileExtension(\n entry.path || entry.name || \"\"\n );\n if (workspaceFileVideoHandlerCollisionExtensions.has(extension)) {\n return true;\n }\n\n if (visualKind === \"code\" || visualKind === \"markdown\") {\n return true;\n }\n\n return classifyWorkspaceFilePreviewKind(entry) === \"text\";\n}\n\nexport function resolveWorkspaceImageMimeType(\n pathOrName: string\n): string | null {\n switch (resolveWorkspaceFileExtension(pathOrName)) {\n case \"avif\":\n return \"image/avif\";\n case \"gif\":\n return \"image/gif\";\n case \"jpeg\":\n case \"jpg\":\n return \"image/jpeg\";\n case \"png\":\n return \"image/png\";\n case \"svg\":\n return \"image/svg+xml\";\n case \"webp\":\n return \"image/webp\";\n default:\n return null;\n }\n}\n\nexport function resolveWorkspaceVideoMimeType(\n pathOrName: string\n): string | null {\n switch (resolveWorkspaceFileExtension(pathOrName)) {\n case \"mp4\":\n return \"video/mp4\";\n case \"webm\":\n return \"video/webm\";\n default:\n return null;\n }\n}\n\nexport function classifyWorkspaceFilePreviewKind(\n entry: Pick<\n WorkspaceFilePreviewEntry,\n \"displayName\" | \"kind\" | \"name\" | \"path\"\n >\n): WorkspaceFilePreviewKind | null {\n if (entry.kind !== \"file\") {\n return null;\n }\n\n const name = resolveWorkspaceFilePreviewName(entry);\n if (resolveWorkspaceImageMimeType(name) !== null) {\n return \"image\";\n }\n if (resolveWorkspaceVideoMimeType(name) !== null) {\n return \"video\";\n }\n\n const normalizedName = name.trim().toLowerCase();\n const extension = resolveWorkspaceFileExtension(name);\n if (textExtensions.has(extension) || textFileNames.has(normalizedName)) {\n return \"text\";\n }\n\n return null;\n}\n\nexport function resolveWorkspaceFileActivationTarget(\n entry: WorkspaceFilePreviewEntry\n): WorkspaceFilePreviewActivationTarget | null {\n const fileKind = classifyWorkspaceFilePreviewKind(entry);\n if (!fileKind) {\n return null;\n }\n\n const target: WorkspaceFilePreviewActivationTarget = {\n fileKind,\n name: resolveWorkspaceFilePreviewName(entry),\n path: entry.path\n };\n if (entry.mtimeMs !== undefined) {\n target.mtimeMs = entry.mtimeMs;\n }\n if (entry.sizeBytes !== undefined) {\n target.sizeBytes = entry.sizeBytes;\n }\n return target;\n}\n\nexport function resolveWorkspaceFilePreviewReadiness<\n TEntry extends WorkspaceFilePreviewEntry\n>(entry: TEntry): WorkspaceFilePreviewReadiness<TEntry> {\n if (entry.kind === \"directory\" || entry.kind === \"folder\") {\n return {\n entry,\n status: \"directory\"\n };\n }\n\n const target = resolveWorkspaceFileActivationTarget(entry);\n if (!target) {\n return {\n entry,\n status: \"unsupported\"\n };\n }\n\n if (\n target.fileKind === \"text\" &&\n isWorkspaceTextFileTooLarge(entry.sizeBytes)\n ) {\n return {\n entry,\n maxSizeBytes: workspaceFileTextMaxBytes,\n reason: \"text_too_large\",\n status: \"readonly\"\n };\n }\n\n if (isWorkspacePreviewFileTooLarge(entry.sizeBytes)) {\n return {\n entry,\n maxSizeBytes: workspaceFilePreviewMaxBytes,\n reason: \"file_too_large\",\n status: \"readonly\"\n };\n }\n\n return {\n entry,\n status: \"ready\",\n target\n };\n}\n\nexport function createWorkspaceFilePreviewLoadedState<\n TEntry extends WorkspaceFilePreviewEntry,\n TTarget extends WorkspaceFilePreviewActivationTarget\n>(input: {\n bytes: Uint8Array | ArrayBuffer;\n contentType?: string | null;\n entry: TEntry;\n renderHtml?: boolean;\n target: TTarget;\n}): WorkspaceFilePreviewLoadedState<TEntry, TTarget> {\n if (input.target.fileKind === \"image\") {\n return {\n bytes: copyWorkspaceFilePreviewBytes(input.bytes),\n contentType:\n input.contentType ??\n resolveWorkspaceImageMimeType(input.target.name) ??\n \"application/octet-stream\",\n entry: input.target,\n status: \"image\"\n };\n }\n if (input.target.fileKind === \"video\") {\n return {\n bytes: copyWorkspaceFilePreviewBytes(input.bytes),\n contentType:\n input.contentType ??\n resolveWorkspaceVideoMimeType(input.target.name) ??\n \"application/octet-stream\",\n entry: input.target,\n status: \"video\"\n };\n }\n\n try {\n const content = decodeWorkspaceTextFile(input.bytes);\n if (looksLikeBinaryText(content)) {\n return {\n entry: input.entry,\n reason: \"binary\",\n status: \"readonly\"\n };\n }\n if (input.renderHtml && isWorkspaceHtmlFileName(input.target.name)) {\n return {\n content,\n entry: input.target,\n status: \"html\"\n };\n }\n return {\n content,\n entry: input.target,\n status: \"text\"\n };\n } catch {\n return {\n entry: input.entry,\n reason: \"decode_failed\",\n status: \"readonly\"\n };\n }\n}\n\nfunction isWorkspaceHtmlFileName(pathOrName: string): boolean {\n return browserOpenableHtmlExtensions.has(\n resolveWorkspaceFileExtension(pathOrName)\n );\n}\n\nexport function resolveWorkspaceFilePreviewName(\n entry: Pick<WorkspaceFilePreviewEntry, \"displayName\" | \"name\" | \"path\">\n): string {\n return (\n entry.name?.trim() ||\n entry.displayName?.trim() ||\n entry.path.split(\"/\").pop()?.trim() ||\n entry.path\n );\n}\n\nexport function isWorkspaceTextFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFileTextMaxBytes\n );\n}\n\nexport function isWorkspacePreviewFileTooLarge(\n sizeBytes?: number | null\n): boolean {\n return (\n typeof sizeBytes === \"number\" &&\n Number.isFinite(sizeBytes) &&\n sizeBytes > workspaceFilePreviewMaxBytes\n );\n}\n\nexport function decodeWorkspaceTextFile(\n bytes: Uint8Array | ArrayBuffer\n): string {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(\n normalizeWorkspaceFilePreviewBytes(bytes)\n );\n}\n\nexport function normalizeWorkspaceFilePreviewBytes(\n value: Uint8Array | ArrayBuffer\n): Uint8Array {\n if (value instanceof Uint8Array) {\n return value;\n }\n return new Uint8Array(value);\n}\n\nexport function copyWorkspaceFilePreviewBytes(\n bytes: Uint8Array | ArrayBuffer\n): Uint8Array<ArrayBuffer> {\n const normalized = normalizeWorkspaceFilePreviewBytes(bytes);\n const buffer = new ArrayBuffer(normalized.byteLength);\n const copy = new Uint8Array(buffer);\n copy.set(normalized);\n return copy;\n}\n\nexport function looksLikeBinaryText(content: string): boolean {\n if (content.length === 0) {\n return false;\n }\n\n const sample = content.slice(0, 4096);\n if (sample.includes(\"\\u0000\")) {\n return true;\n }\n\n let suspiciousControlChars = 0;\n for (let index = 0; index < sample.length; index += 1) {\n const code = sample.charCodeAt(index);\n const isAllowedWhitespace = code === 9 || code === 10 || code === 13;\n const isControlChar = code < 32 || (code >= 127 && code <= 159);\n if (isControlChar && !isAllowedWhitespace) {\n suspiciousControlChars += 1;\n }\n }\n\n return suspiciousControlChars / sample.length > 0.12;\n}\n\nexport function formatWorkspacePreviewByteLimit(sizeBytes: number): string {\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n const mebibytes = sizeBytes / (1024 * 1024);\n if (Number.isInteger(mebibytes)) {\n return `${mebibytes} MiB`;\n }\n return `${mebibytes.toFixed(1)} MiB`;\n}\n"],"mappings":";AAoFA,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,gCAAgC,oBAAI,IAAI;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,iCAAiC,oBAAI,IAAI,CAAC,OAAO,MAAM,CAAC;AAE9D,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAKM,IAAM,+CAA+C,oBAAI,IAAI,CAAC,IAAI,CAAC;AAC1E,IAAM,qBAAqB,oBAAI,IAAI,CAAC,MAAM,KAAK,CAAC;AAChD,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,iBAAiB,oBAAI,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,4BAA4B,OAAO;AACzC,IAAM,+BAA+B,KAAK,OAAO;AAEjD,SAAS,+BACd,OACyB;AACzB,MAAI,MAAM,SAAS,eAAe,MAAM,SAAS,UAAU;AACzD,WAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAAA,IAChB,MAAM,QAAQ,MAAM,QAAQ;AAAA,EAC9B;AACA,MAAI,gBAAgB,IAAI,SAAS,GAAG;AAClC,WAAO;AAAA,EACT;AACA,MAAI,gBAAgB,IAAI,SAAS,GAAG;AAClC,WAAO;AAAA,EACT;AACA,MAAI,mBAAmB,IAAI,SAAS,GAAG;AACrC,WAAO;AAAA,EACT;AACA,MAAI,eAAe,IAAI,SAAS,GAAG;AACjC,WAAO;AAAA,EACT;AACA,MAAI,mBAAmB,IAAI,SAAS,GAAG;AACrC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEO,SAAS,8BAA8B,YAA4B;AACxE,QAAM,OAAO,WAAW,MAAM,GAAG,EAAE,IAAI,GAAG,KAAK,EAAE,YAAY,KAAK;AAClE,QAAM,WAAW,KAAK,YAAY,GAAG;AACrC,SAAO,WAAW,IAAI,KAAK,MAAM,WAAW,CAAC,IAAI;AACnD;AAEO,SAAS,+BACd,OACS;AACT,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAAA,IAChB,MAAM,QAAQ,MAAM,QAAQ;AAAA,EAC9B;AACA,MACE,cAAc,SACd,8BAA8B,IAAI,SAAS,KAC3C,gBAAgB,IAAI,SAAS,KAC7B,+BAA+B,IAAI,SAAS,GAC5C;AACA,WAAO;AAAA,EACT;AAEA,SAAO,iCAAiC,KAAK,MAAM;AACrD;AAEO,SAAS,oCACd,OACS;AACT,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,+BAA+B,KAAK;AACvD,MAAI,eAAe,SAAS;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,YAAY;AAAA,IAChB,MAAM,QAAQ,MAAM,QAAQ;AAAA,EAC9B;AACA,MAAI,6CAA6C,IAAI,SAAS,GAAG;AAC/D,WAAO;AAAA,EACT;AAEA,MAAI,eAAe,UAAU,eAAe,YAAY;AACtD,WAAO;AAAA,EACT;AAEA,SAAO,iCAAiC,KAAK,MAAM;AACrD;AAEO,SAAS,8BACd,YACe;AACf,UAAQ,8BAA8B,UAAU,GAAG;AAAA,IACjD,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,8BACd,YACe;AACf,UAAQ,8BAA8B,UAAU,GAAG;AAAA,IACjD,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEO,SAAS,iCACd,OAIiC;AACjC,MAAI,MAAM,SAAS,QAAQ;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,gCAAgC,KAAK;AAClD,MAAI,8BAA8B,IAAI,MAAM,MAAM;AAChD,WAAO;AAAA,EACT;AACA,MAAI,8BAA8B,IAAI,MAAM,MAAM;AAChD,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB,KAAK,KAAK,EAAE,YAAY;AAC/C,QAAM,YAAY,8BAA8B,IAAI;AACpD,MAAI,eAAe,IAAI,SAAS,KAAK,cAAc,IAAI,cAAc,GAAG;AACtE,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEO,SAAS,qCACd,OAC6C;AAC7C,QAAM,WAAW,iCAAiC,KAAK;AACvD,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,SAA+C;AAAA,IACnD;AAAA,IACA,MAAM,gCAAgC,KAAK;AAAA,IAC3C,MAAM,MAAM;AAAA,EACd;AACA,MAAI,MAAM,YAAY,QAAW;AAC/B,WAAO,UAAU,MAAM;AAAA,EACzB;AACA,MAAI,MAAM,cAAc,QAAW;AACjC,WAAO,YAAY,MAAM;AAAA,EAC3B;AACA,SAAO;AACT;AAEO,SAAS,qCAEd,OAAsD;AACtD,MAAI,MAAM,SAAS,eAAe,MAAM,SAAS,UAAU;AACzD,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,SAAS,qCAAqC,KAAK;AACzD,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,MACL;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MACE,OAAO,aAAa,UACpB,4BAA4B,MAAM,SAAS,GAC3C;AACA,WAAO;AAAA,MACL;AAAA,MACA,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI,+BAA+B,MAAM,SAAS,GAAG;AACnD,WAAO;AAAA,MACL;AAAA,MACA,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,sCAGd,OAMmD;AACnD,MAAI,MAAM,OAAO,aAAa,SAAS;AACrC,WAAO;AAAA,MACL,OAAO,8BAA8B,MAAM,KAAK;AAAA,MAChD,aACE,MAAM,eACN,8BAA8B,MAAM,OAAO,IAAI,KAC/C;AAAA,MACF,OAAO,MAAM;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AACA,MAAI,MAAM,OAAO,aAAa,SAAS;AACrC,WAAO;AAAA,MACL,OAAO,8BAA8B,MAAM,KAAK;AAAA,MAChD,aACE,MAAM,eACN,8BAA8B,MAAM,OAAO,IAAI,KAC/C;AAAA,MACF,OAAO,MAAM;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,MAAI;AACF,UAAM,UAAU,wBAAwB,MAAM,KAAK;AACnD,QAAI,oBAAoB,OAAO,GAAG;AAChC,aAAO;AAAA,QACL,OAAO,MAAM;AAAA,QACb,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,IACF;AACA,QAAI,MAAM,cAAc,wBAAwB,MAAM,OAAO,IAAI,GAAG;AAClE,aAAO;AAAA,QACL;AAAA,QACA,OAAO,MAAM;AAAA,QACb,QAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,MACA,OAAO,MAAM;AAAA,MACb,QAAQ;AAAA,IACV;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL,OAAO,MAAM;AAAA,MACb,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,SAAS,wBAAwB,YAA6B;AAC5D,SAAO,8BAA8B;AAAA,IACnC,8BAA8B,UAAU;AAAA,EAC1C;AACF;AAEO,SAAS,gCACd,OACQ;AACR,SACE,MAAM,MAAM,KAAK,KACjB,MAAM,aAAa,KAAK,KACxB,MAAM,KAAK,MAAM,GAAG,EAAE,IAAI,GAAG,KAAK,KAClC,MAAM;AAEV;AAEO,SAAS,4BACd,WACS;AACT,SACE,OAAO,cAAc,YACrB,OAAO,SAAS,SAAS,KACzB,YAAY;AAEhB;AAEO,SAAS,+BACd,WACS;AACT,SACE,OAAO,cAAc,YACrB,OAAO,SAAS,SAAS,KACzB,YAAY;AAEhB;AAEO,SAAS,wBACd,OACQ;AACR,SAAO,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE;AAAA,IAC/C,mCAAmC,KAAK;AAAA,EAC1C;AACF;AAEO,SAAS,mCACd,OACY;AACZ,MAAI,iBAAiB,YAAY;AAC/B,WAAO;AAAA,EACT;AACA,SAAO,IAAI,WAAW,KAAK;AAC7B;AAEO,SAAS,8BACd,OACyB;AACzB,QAAM,aAAa,mCAAmC,KAAK;AAC3D,QAAM,SAAS,IAAI,YAAY,WAAW,UAAU;AACpD,QAAM,OAAO,IAAI,WAAW,MAAM;AAClC,OAAK,IAAI,UAAU;AACnB,SAAO;AACT;AAEO,SAAS,oBAAoB,SAA0B;AAC5D,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,QAAQ,MAAM,GAAG,IAAI;AACpC,MAAI,OAAO,SAAS,IAAQ,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,yBAAyB;AAC7B,WAAS,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,GAAG;AACrD,UAAM,OAAO,OAAO,WAAW,KAAK;AACpC,UAAM,sBAAsB,SAAS,KAAK,SAAS,MAAM,SAAS;AAClE,UAAM,gBAAgB,OAAO,MAAO,QAAQ,OAAO,QAAQ;AAC3D,QAAI,iBAAiB,CAAC,qBAAqB;AACzC,gCAA0B;AAAA,IAC5B;AAAA,EACF;AAEA,SAAO,yBAAyB,OAAO,SAAS;AAClD;AAEO,SAAS,gCAAgC,WAA2B;AACzE,MAAI,YAAY,MAAM;AACpB,WAAO,GAAG,SAAS;AAAA,EACrB;AAEA,QAAM,YAAY,aAAa,OAAO;AACtC,MAAI,OAAO,UAAU,SAAS,GAAG;AAC/B,WAAO,GAAG,SAAS;AAAA,EACrB;AACA,SAAO,GAAG,UAAU,QAAQ,CAAC,CAAC;AAChC;","names":[]}
|