@e280/quay 0.0.0-11 → 0.0.0-12
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/package.json +1 -1
- package/s/logic/aspects/codex/parts/hierarchy.ts +1 -0
- package/s/logic/group.ts +5 -3
- package/s/logic/presets/media/library.test.ts +41 -14
- package/s/logic/presets/media/library.ts +23 -14
- package/x/demo/main.bundle.min.js +1 -1
- package/x/demo/main.bundle.min.js.map +2 -2
- package/x/index.html +2 -2
- package/x/logic/aspects/codex/parts/hierarchy.js +1 -0
- package/x/logic/aspects/codex/parts/hierarchy.js.map +1 -1
- package/x/logic/group.d.ts +3 -3
- package/x/logic/group.js +3 -2
- package/x/logic/group.js.map +1 -1
- package/x/logic/presets/media/library.d.ts +4 -40
- package/x/logic/presets/media/library.js +19 -13
- package/x/logic/presets/media/library.js.map +1 -1
- package/x/logic/presets/media/library.test.d.ts +3 -2
- package/x/logic/presets/media/library.test.js +34 -14
- package/x/logic/presets/media/library.test.js.map +1 -1
package/package.json
CHANGED
package/s/logic/group.ts
CHANGED
|
@@ -18,7 +18,7 @@ export class Group<Sc extends Schema = any> {
|
|
|
18
18
|
on = {
|
|
19
19
|
newFolder: sub<[{parent: CodexItem<Sc>}]>(),
|
|
20
20
|
move: sub<[{item: CodexItem<Sc>, target: CodexItem<Sc>}]>(),
|
|
21
|
-
delete: sub<[{
|
|
21
|
+
delete: sub<[{items: CodexItem<Sc>[]}]>(),
|
|
22
22
|
rename: sub<[{item: CodexItem<Sc>, newName: string}]>(),
|
|
23
23
|
upload: sub<[{files: File[], target: CodexItem<Sc>}]>(),
|
|
24
24
|
search: sub<[{terms: string[]}]>(),
|
|
@@ -73,9 +73,11 @@ export class Group<Sc extends Schema = any> {
|
|
|
73
73
|
if(!this.permissions(item).delete)
|
|
74
74
|
throw new Error("delete permission not granted")
|
|
75
75
|
|
|
76
|
+
const items = [...item.crawl()].map(([item]) => item)
|
|
77
|
+
|
|
76
78
|
item.destroy()
|
|
77
79
|
|
|
78
|
-
this.on.delete.pub({
|
|
80
|
+
return this.on.delete.pub({items})
|
|
79
81
|
}
|
|
80
82
|
|
|
81
83
|
rename(item: CodexItem<Sc>, newName: string) {
|
|
@@ -89,7 +91,7 @@ export class Group<Sc extends Schema = any> {
|
|
|
89
91
|
if(!this.permissions(folder).upload)
|
|
90
92
|
throw new Error("upload permission not granted")
|
|
91
93
|
|
|
92
|
-
this.on.upload.pub({files, target: folder})
|
|
94
|
+
return this.on.upload.pub({files, target: folder})
|
|
93
95
|
}
|
|
94
96
|
|
|
95
97
|
addFolder(parent: CodexItem<Sc>) {
|
|
@@ -3,40 +3,67 @@ import {Txt} from "@e280/stz"
|
|
|
3
3
|
import {expect, Science, test} from "@e280/science"
|
|
4
4
|
|
|
5
5
|
import {MediaLibrary} from "./library.js"
|
|
6
|
+
import {Permissions} from "../../permissions.js"
|
|
6
7
|
|
|
7
8
|
delete (globalThis as any).localStorage
|
|
8
9
|
|
|
9
10
|
export default Science.suite({
|
|
10
|
-
"
|
|
11
|
+
"uploads files into cellar and index": test(async() => {
|
|
11
12
|
const group = new MediaLibrary()
|
|
12
|
-
|
|
13
|
+
await group.upload([file("hello.txt", "hello")], group.config.root)
|
|
13
14
|
|
|
14
|
-
const
|
|
15
|
+
const record = await recordByLabel(group, "hello.txt")
|
|
16
|
+
const item = group.findByHash(record.hash)!
|
|
15
17
|
|
|
18
|
+
expect(item.specimen.label).is("hello.txt")
|
|
16
19
|
expect(await group.cellar.has(record.hash)).is(true)
|
|
17
|
-
|
|
20
|
+
}),
|
|
21
|
+
|
|
22
|
+
"upload respects upload permission": test(async() => {
|
|
23
|
+
const group = new MediaLibrary()
|
|
24
|
+
const file = new File([Txt.toBytes("hello")], "hello.txt", {type: "text/plain"})
|
|
25
|
+
group.config.permissions = () => Permissions.readOnly
|
|
26
|
+
|
|
27
|
+
expect(() => group.upload([file], group.config.root)).throws()
|
|
18
28
|
}),
|
|
19
29
|
|
|
20
30
|
"lists media records": test(async() => {
|
|
21
31
|
const store = new MediaLibrary()
|
|
22
|
-
|
|
23
|
-
const record = await store.importFile(file)
|
|
24
|
-
const records = []
|
|
25
|
-
for await (const record of store.records())
|
|
26
|
-
records.push(record)
|
|
32
|
+
await store.upload([file("image.png", "image", "image/png")], store.config.root)
|
|
27
33
|
|
|
28
|
-
expect(
|
|
34
|
+
expect(await recordByLabel(store, "image.png")).ok()
|
|
29
35
|
}),
|
|
30
36
|
|
|
31
|
-
"
|
|
37
|
+
"deletes media records and bytes": test(async() => {
|
|
32
38
|
const store = new MediaLibrary()
|
|
33
|
-
|
|
34
|
-
const record = await store.importFile(file)
|
|
39
|
+
await store.upload([file("delete.png", "delete-image", "image/png")], store.config.root)
|
|
35
40
|
|
|
36
|
-
await store.
|
|
41
|
+
const record = await recordByLabel(store, "delete.png")
|
|
42
|
+
const item = store.findByHash(record.hash)!
|
|
43
|
+
|
|
44
|
+
await store.delete(item)
|
|
37
45
|
|
|
38
46
|
expect(await store.cellar.has(record.hash)).is(false)
|
|
39
47
|
expect(store.findByHash(record.hash)).is(undefined)
|
|
40
48
|
}),
|
|
49
|
+
|
|
41
50
|
})
|
|
42
51
|
|
|
52
|
+
function file(name: string, text: string, type = "text/plain") {
|
|
53
|
+
return new File([Txt.toBytes(text)], name, {type})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function records(store: MediaLibrary) {
|
|
57
|
+
const records = []
|
|
58
|
+
for await (const record of store.records())
|
|
59
|
+
records.push(record)
|
|
60
|
+
return records
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function recordByLabel(store: MediaLibrary, label: string) {
|
|
64
|
+
const record = (await records(store)).find(r => r.label === label)
|
|
65
|
+
if (!record)
|
|
66
|
+
throw new Error(`expected record "${label}"`)
|
|
67
|
+
return record
|
|
68
|
+
}
|
|
69
|
+
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import {Kv, StorageDriver} from "@e280/kv"
|
|
3
3
|
|
|
4
|
-
import {Cellar} from "../../../cellar/cellar.js"
|
|
5
|
-
import {MediaFormat} from "./schema.js"
|
|
6
4
|
import {MediaGroup} from "./group.js"
|
|
5
|
+
import {Cellar} from "../../../cellar/cellar.js"
|
|
6
|
+
import {MediaFormat, MediaSchema} from "./schema.js"
|
|
7
|
+
import {CodexItem} from "../../aspects/codex/parts/codex-item.js"
|
|
7
8
|
|
|
8
9
|
export type MediaRecord = {
|
|
9
10
|
hash: string
|
|
@@ -33,7 +34,11 @@ export class MediaLibrary extends MediaGroup {
|
|
|
33
34
|
super()
|
|
34
35
|
this.#index = mediaIndex("default")
|
|
35
36
|
this.on.upload.sub(({files, target}) => {
|
|
36
|
-
|
|
37
|
+
return this.#upload(files, target)
|
|
38
|
+
})
|
|
39
|
+
this.on.delete.sub(({items}) => {
|
|
40
|
+
const hashes = this.#hashes(items)
|
|
41
|
+
return this.#delete(hashes)
|
|
37
42
|
})
|
|
38
43
|
}
|
|
39
44
|
|
|
@@ -50,11 +55,11 @@ export class MediaLibrary extends MediaGroup {
|
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
async
|
|
54
|
-
|
|
58
|
+
async #upload(files: File[], parent: CodexItem<MediaSchema>) {
|
|
59
|
+
await Promise.all(files.map(file => this.#storeFile(file, parent)))
|
|
55
60
|
}
|
|
56
61
|
|
|
57
|
-
async
|
|
62
|
+
async #storeFile(file: File, parent: CodexItem<MediaSchema>) {
|
|
58
63
|
const bytes = new Uint8Array(await file.arrayBuffer())
|
|
59
64
|
const cask = await this.cellar.save(bytes)
|
|
60
65
|
const existing = await this.#index.get(cask.hash)
|
|
@@ -75,15 +80,18 @@ export class MediaLibrary extends MediaGroup {
|
|
|
75
80
|
return record
|
|
76
81
|
}
|
|
77
82
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
#hashes(items: CodexItem<MediaSchema>[]) {
|
|
84
|
+
return items
|
|
85
|
+
.map(item => item.isKind("file") ? item.specimen.hash : undefined)
|
|
86
|
+
.filter((hash): hash is string => !!hash)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async #delete(hashes: string[]) {
|
|
90
|
+
for (const hash of hashes) {
|
|
91
|
+
await this.#index.del(hash)
|
|
92
|
+
await this.cellar.delete(hash)
|
|
93
|
+
this.#revokePreview(hash)
|
|
85
94
|
}
|
|
86
|
-
this.#revokePreview(hash)
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
findByHash(hash: string) {
|
|
@@ -160,3 +168,4 @@ function mediaIndex(scope: string) {
|
|
|
160
168
|
memoryIndexes.set(scope, index)
|
|
161
169
|
return index
|
|
162
170
|
}
|
|
171
|
+
|
|
@@ -25,7 +25,7 @@ var qr=Object.defineProperty;var Et=(r,e)=>{for(var t in e)qr(r,t,{get:e[t],enum
|
|
|
25
25
|
font-family: monospace;
|
|
26
26
|
color: red;
|
|
27
27
|
}
|
|
28
|
-
`;function z(r,e){return(t,o)=>nr(t,{pending:r,err:e,ok:o})}var Fl=z(P(10,[" "," ",". ",".. ","..."," .."," ."]),O);var Kl=z(P(3,["\u{1F30E}","\u{1F30F}","\u{1F30D}"]),O);var eu=z(P(10,["\u{1F312}","\u{1F313}","\u{1F314}","\u{1F315}","\u{1F316}","\u{1F317}","\u{1F318}","\u{1F311}","\u{1F311}","\u{1F311}"]),O);var nu=z(P(16,["|","/","-","\\"]),O);var uu=z(P(20,[":....",":....","::...",".::..","..::.","...::","....:","....:","...::","..::.",".::..","::..."]),O);var M=Object.freeze({eq(r,e){if(r.length!==e.length)return!1;for(let t=0;t<=r.length;t++)if(r.at(t)!==e.at(t))return!1;return!0},random(r){return crypto.getRandomValues(new Uint8Array(r))}});var R=Object.freeze({fromBytes(r){return[...r].map(e=>e.toString(16).padStart(2,"0")).join("")},toBytes(r){if(r.length%2!==0)throw new Error("must have even number of hex characters");let e=new Uint8Array(r.length/2);for(let t=0;t<r.length;t+=2)e[t/2]=parseInt(r.slice(t,t+2),16);return e},random(r=32){return this.fromBytes(M.random(r))},string(r){return R.fromBytes(r)},bytes(r){return R.toBytes(r)}});var vt=58,Ke="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",$t=Object.freeze({fromBytes(r){let e=BigInt("0x"+R.fromBytes(r)),t="";for(;e>0;){let o=e%BigInt(vt);e=e/BigInt(vt),t=Ke[Number(o)]+t}for(let o of r)if(o===0)t=Ke[0]+t;else break;return t},toBytes(r){let e=BigInt(0);for(let i of r){let l=Ke.indexOf(i);if(l===-1)throw new Error(`Invalid character '${i}' in base58 string`);e=e*BigInt(vt)+BigInt(l)}let t=e.toString(16);t.length%2!==0&&(t="0"+t);let o=R.toBytes(t),s=0;for(let i of r)if(i===Ke[0])s++;else break;let n=new Uint8Array(s+o.length);return n.set(o,s),n},random(r=32){return this.fromBytes(M.random(r))},string(r){return $t.fromBytes(r)},bytes(r){return $t.toBytes(r)}});var wr=class{lexicon;static lexicons=Object.freeze({base2:{characters:"01"},hex:{characters:"0123456789abcdef"},base36:{characters:"0123456789abcdefghijklmnopqrstuvwxyz"},base58:{characters:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"},base62:{characters:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},base64url:{negativePrefix:"~",characters:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"},base64:{characters:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",padding:{character:"=",size:4}}});lookup;negativePrefix;constructor(e){this.lexicon=e,this.lookup=Object.fromEntries([...e.characters].map((t,o)=>[t,o])),this.negativePrefix=e.negativePrefix??"-"}toBytes(e){let t=Math.log2(this.lexicon.characters.length);if(Number.isInteger(t)){let l=0,a=0,c=[];for(let u of e){if(u===this.lexicon.padding?.character)continue;let f=this.lookup[u];if(f===void 0)throw new Error(`Invalid character: ${u}`);for(l=l<<t|f,a+=t;a>=8;)a-=8,c.push(l>>a&255)}return new Uint8Array(c)}let o=0n,s=BigInt(this.lexicon.characters.length),n=!1;e.startsWith(this.negativePrefix)&&(e=e.slice(this.negativePrefix.length),n=!0);for(let l of e){let a=this.lookup[l];if(a===void 0)throw new Error(`Invalid character: ${l}`);o=o*s+BigInt(a)}let i=[];for(;o>0n;)i.unshift(Number(o%256n)),o=o/256n;return new Uint8Array(i)}fromBytes(e){let t=Math.log2(this.lexicon.characters.length);if(Number.isInteger(t)){let i=0,l=0,a="";for(let c of e)for(i=i<<8|c,l+=8;l>=t;){l-=t;let u=i>>l&(1<<t)-1;a+=this.lexicon.characters[u]}if(l>0){let c=i<<t-l&(1<<t)-1;a+=this.lexicon.characters[c]}if(this.lexicon.padding)for(;a.length%this.lexicon.padding.size!==0;)a+=this.lexicon.padding.character;return a}let o=0n;for(let i of e)o=(o<<8n)+BigInt(i);if(o===0n)return this.lexicon.characters[0];let s=BigInt(this.lexicon.characters.length),n="";for(;o>0n;)n=this.lexicon.characters[Number(o%s)]+n,o=o/s;return n}toInteger(e){if(!e)return 0;let t=0n,o=!1,s=BigInt(this.lexicon.characters.length);e.startsWith(this.negativePrefix)&&(e=e.slice(this.negativePrefix.length),o=!0);for(let n of e){let i=this.lookup[n];if(i===void 0)throw new Error(`Invalid character: ${n}`);t=t*s+BigInt(i)}return Number(o?-t:t)}fromInteger(e){e=Math.floor(e);let t=e<0,o=BigInt(t?-e:e);if(o===0n)return this.lexicon.characters[0];let s=BigInt(this.lexicon.characters.length),n="";for(;o>0n;)n=this.lexicon.characters[Number(o%s)]+n,o=o/s;return t?`${this.negativePrefix}${n}`:n}random(e=32){return this.fromBytes(M.random(e))}};var At=Object.freeze({fromBytes(r){return typeof btoa=="function"?btoa(String.fromCharCode(...r)):Buffer.from(r).toString("base64")},toBytes(r){return typeof atob=="function"?Uint8Array.from(atob(r),e=>e.charCodeAt(0)):Uint8Array.from(Buffer.from(r,"base64"))},random(r=32){return this.fromBytes(M.random(r))},string(r){return At.fromBytes(r)},bytes(r){return At.toBytes(r)}});var vr=Object.freeze({fromBytes(r){return new TextDecoder().decode(r)},toBytes(r){return new TextEncoder().encode(r)},string(r){return vr.fromBytes(r)},bytes(r){return vr.toBytes(r)}});var St=Object.freeze({set:r=>r!=null,unset:r=>r==null,boolean:r=>typeof r=="boolean",number:r=>typeof r=="number",string:r=>typeof r=="string",bigint:r=>typeof r=="bigint",object:r=>typeof r=="object"&&r!==null,array:r=>Array.isArray(r),fn:r=>typeof r=="function",symbol:r=>typeof r=="symbol"});function $r(){let r,e,t=new Promise((s,n)=>{r=s,e=n});function o(s){return s.then(r).catch(e),t}return{promise:t,resolve:r,reject:e,entangle:o}}var A=class r extends Map{static require(e,t){let o=e.get(t);if(o===void 0)throw new Error(`required key not found: "${t}"`);return o}static guarantee(e,t,o){let s=e.get(t);return s===void 0&&(s=o(),e.set(t,s)),s}array(){return[...this]}require(e){return r.require(this,e)}guarantee(e,t){return r.guarantee(this,e,t)}};function vo(r){return{map:e=>Ar(r,e),filter:e=>Sr(r,e)}}vo.pipe=Object.freeze({map:r=>(e=>Ar(e,r)),filter:r=>(e=>Sr(e,r))});var Ar=(r,e)=>Object.fromEntries(Object.entries(r).map(([t,o])=>[t,e(o,t)])),Sr=(r,e)=>Object.fromEntries(Object.entries(r).filter(([t,o])=>e(o,t)));function $o(){let r=new Set;function e(n){return r.add(n),()=>{r.delete(n)}}async function t(...n){await Promise.all([...r].map(i=>i(...n)))}async function o(){let{promise:n,resolve:i}=$r(),l=e((...a)=>{i(a),l()});return n}function s(){r.clear()}return e.pub=t,e.sub=e,e.on=e,e.once=o,e.clear=s,t.pub=t,t.sub=e,t.on=e,t.once=o,t.clear=s,[t,e]}function j(r){let e=$o()[1];return r&&e.sub(r),e}var Ze=class{#e=new A;setGroup(e,t){return this.#e.set(e,t),t}getGroup(e){return this.#e.require(e)}};var Je=new Ze;var Ye=class{group;#e=new Le.DragAndDrops({acceptDrop:(e,t,o)=>this.group.move(t,o)});constructor(e){this.group=e}#t=h(void 0);get grabbed(){return this.#e.dragging}get hovering(){return this.#e.hovering??this.#t()}dragenter=(e,t)=>{e.preventDefault(),this.#e.dropzone(()=>t).dragenter(e),this.#t(t)};dragleave=e=>{let t=this.hovering;t&&this.#e.dropzone(()=>t).dragleave(e),this.#t(void 0)};dragstart=(e,t)=>{e.stopPropagation(),this.#e.dragzone(()=>t).dragstart(e)};dragover=(e,t)=>{e.preventDefault(),this.#e.dropzone(()=>t).dragover(e)};dragend=e=>{this.#e.$draggy(void 0),this.#e.$droppy(void 0),this.#t(void 0)};drop=(e,t)=>{e.preventDefault();let o=Array.from(e.dataTransfer?.files||[]);o.length&&this.group.upload(o,t);let s=this.grabbed?.id===this.hovering?.id,n=this.grabbed?.children.some(l=>this.hovering?.id===l.id),i=this.grabbed?.parent?.id===this.hovering?.id;!s&&!n&&!i&&this.#e.dropzone(()=>t).drop(e),this.#t(void 0)};change=(e,t)=>{let o=e.currentTarget,s=Array.from(o.files??[]);s.length&&this.group.upload(s,t)}};var Xe=class{signal=h([]);constructor(e){this.signal([e])}setTrail(e,t){if(e.target!==e.currentTarget)return;let o=[],s=t.kind==="folder"?t:t.parent;for(;s;)o.unshift(s),s=s.parent;this.signal(o)}get currentFolder(){return this.signal().at(-1)?.children??[]}};var et=class{config;trail;dropzone=new Ye(this);searchText=h("");selectedFilter=h("");selectedSort=h("");on={newFolder:j(),move:j(),delete:j(),rename:j(),upload:j(),search:j(),refresh:j()};constructor(e){this.config=e,this.selectedFilter(e.defaultFilter),this.selectedSort(e.defaultSort),this.trail=new Xe(e.root)}get permissions(){return this.config.permissions}getFilterFn(e){return this.config.filters.get(e)??(()=>!0)}getSearchFn(e){let t=e.trim().toLowerCase().split(/\s+/);return o=>this.config.search(t,o)}getSortFn(e){return this.config.sorts?.get(e)??(()=>0)}sort(e){let t=this.getSortFn(this.selectedSort());return[...e].sort(t)}matches(e){let t=this.getFilterFn(this.selectedFilter()),o=this.getSearchFn(this.searchText());return t(e)&&o(e)}move(e,t){if(!this.permissions(e).move)throw new Error("move permission not granted");e.detach(),t.attach(e),this.on.move.pub({item:e,target:t})}delete(e){if(!this.permissions(e).delete)throw new Error("delete permission not granted");e.destroy(),this.on.delete.pub({item:e})}rename(e,t){if(!this.permissions(e).rename)throw new Error("rename permission not granted");this.on.rename.pub({item:e,newName:t})}upload(e,t){if(!this.permissions(t).upload)throw new Error("upload permission not granted");this.on.upload.pub({files:e,target:t})}addFolder(e){if(!this.permissions(e).newFolder)throw new Error("add folder permission not granted");this.on.newFolder.pub({parent:e})}components=()=>this.components};var xe;(function(r){r.rename="rename",r.move="move",r.delete="delete",r.refresh="refresh",r.newFolder="newFolder",r.search="search",r.upload="upload"})(xe||(xe={}));var Ao=Object.values(xe);function _t(r,e={}){let t={};for(let o of Ao)t[o]=o in e?e[o]:r;return t}var _r={all:_t(!0),readOnly:_t(!1,{[xe.refresh]:!0,[xe.search]:!0}),none:_t(!1)};var tt=class{taxonomy;onChange=j();#e=new A;constructor(e){this.taxonomy=e}getSpecimen(e){return this.#e.require(e)}setSpecimen(e,t,o){this.#e.set(e,[t,o]),this.onChange.pub()}query(e){let[t,o]=this.getSpecimen(e),s=this.taxonomy.taxon(t);return{kind:t,taxon:s,specimen:o}}};var rt=class{#e=new A;constructor(e){for(let[t,o]of Object.entries(e))this.#e.set(t,o)}taxon(e){return this.#e.require(e)}};var ot=class{#e=new A;#t=new A;has(e){return this.#e.has(e)}getChildren(e){return this.#e.require(e)}getParent(e){return this.#t.get(e)}establishRoot(e){this.#e.set(e,new Set)}attach(e,...t){let o=this.getChildren(e);for(let s of t){if(this.getParent(s))throw new Error("child already has parent");o.add(s),this.#t.set(s,e),this.#e.set(s,new Set)}}detach(e){if(!this.has(e))return;let t=this.getParent(e);t&&(this.getChildren(t).delete(e),this.#t.delete(e))}destroy(e){let t=[...this.crawl(e)];for(let[o]of t)this.#e.delete(o),this.#t.delete(o)}*crawl(e,t=()=>!0){let o=[[e,[]]],s=new Set;for(;o.length;){let[n,i]=o.shift();if(!(s.has(n)||!t(n,i))){s.add(n),yield[n,i];for(let l of this.getChildren(n))o.push([l,[...i,n]])}}}};var st=class{codex;id;signal=h(this);constructor(e,t){this.codex=e,this.id=t}get kind(){return this.codex.clade.query(this.id).kind}isKind(e){return e===this.kind}get taxon(){return this.codex.clade.query(this.id).taxon}get specimen(){return this.codex.clade.query(this.id).specimen}get parent(){let e=this.codex.hierarchy.getParent(this.id);return e?this.codex.require(e):void 0}get children(){return[...this.codex.hierarchy.getChildren(this.id)].map(e=>this.codex.require(e))}attach(...e){return this.codex.hierarchy.attach(this.id,...e.map(t=>t.id)),this.signal(this),this}detach(){this.codex.hierarchy.detach(this.id),this.signal(this)}create(e,t){let o=this.codex.create(e,t);return this.attach(o),o}destroy(){this.codex.hierarchy.destroy(this.id),this.signal(this)}*crawl(e=()=>!0){let t=this.codex.hierarchy.crawl(this.id,(o,s)=>e(this.codex.require(o),s.map(n=>this.codex.require(n))));for(let[o,s]of t)yield[this.codex.require(o),s.map(n=>this.codex.require(n))]}};function Er(){return R.random()}var nt=class{clade;hierarchy;static setup(e){let t=new rt(e),o=new tt(t),s=new ot;return new this(o,s)}#e=new A;constructor(e,t){this.clade=e,this.hierarchy=t}create(e,t){let o=Er();this.clade.setSpecimen(o,e,t);let s=new st(this,o);return this.#e.set(o,s),s.signal()}root(e){return this.hierarchy.establishRoot(e.id),e.signal()}require(e){return this.#e.require(e).signal()}};var it=class r extends et{static config=()=>{let e=new A().set("audio",p`<sl-icon name=music-note-beamed></sl-icon>`).set("video",p`<sl-icon name=film></sl-icon>`).set("image",p`<sl-icon name=image></sl-icon>`).set("other",p`<sl-icon name=file-earmark></sl-icon>`),t=new Map().set("all",()=>!0).set("video",a=>a.isKind("folder")||a.isKind("file")&&a.specimen.format==="video").set("audio",a=>a.isKind("folder")||a.isKind("file")&&a.specimen.format==="audio"),o=new Map().set("label",(a,c)=>a.specimen.label.localeCompare(c.specimen.label)).set("format",(a,c)=>a.isKind("file")&&c.isKind("file")?a.specimen.format.localeCompare(c.specimen.format):a.isKind("file")?-1:c.isKind("file")?1:0),s=(a,c)=>{let u=a.join(" ").trim().toLowerCase();return u===""?!0:c.kind==="folder"?c.children.some(f=>s(a,f)):c.specimen.label.toLowerCase().includes(u)},n=nt.setup({folder:{icon:p`<sl-icon name="folder"></sl-icon>`},file:{icon:p`<sl-icon name="file"></sl-icon>`}}),i=n.root(n.create("folder",{label:"project"})),l=(a,c)=>a.isKind("file")?e.require(a.specimen.format):c?p`<sl-icon name="folder2-open"></sl-icon>`:a.taxon.icon;return{codex:n,root:i,sorts:o,filters:t,defaultFilter:"all",defaultSort:"label",search:(a,c)=>a.some(u=>c.kind.includes(u)||c.id.includes(u)||c.specimen.label.includes(u))||s(a,c),renderIcon:l,renderLabel:a=>a.specimen.label,renderPreview:a=>a.isKind("file")&&a.specimen.previewUrl?p`<img src=${a.specimen.previewUrl}>`:l(a,!1),permissions:a=>_r.all}};constructor(){super(r.config())}};var $=d`@layer theme, view; @layer theme {
|
|
28
|
+
`;function z(r,e){return(t,o)=>nr(t,{pending:r,err:e,ok:o})}var Fl=z(P(10,[" "," ",". ",".. ","..."," .."," ."]),O);var Kl=z(P(3,["\u{1F30E}","\u{1F30F}","\u{1F30D}"]),O);var eu=z(P(10,["\u{1F312}","\u{1F313}","\u{1F314}","\u{1F315}","\u{1F316}","\u{1F317}","\u{1F318}","\u{1F311}","\u{1F311}","\u{1F311}"]),O);var nu=z(P(16,["|","/","-","\\"]),O);var uu=z(P(20,[":....",":....","::...",".::..","..::.","...::","....:","....:","...::","..::.",".::..","::..."]),O);var M=Object.freeze({eq(r,e){if(r.length!==e.length)return!1;for(let t=0;t<=r.length;t++)if(r.at(t)!==e.at(t))return!1;return!0},random(r){return crypto.getRandomValues(new Uint8Array(r))}});var R=Object.freeze({fromBytes(r){return[...r].map(e=>e.toString(16).padStart(2,"0")).join("")},toBytes(r){if(r.length%2!==0)throw new Error("must have even number of hex characters");let e=new Uint8Array(r.length/2);for(let t=0;t<r.length;t+=2)e[t/2]=parseInt(r.slice(t,t+2),16);return e},random(r=32){return this.fromBytes(M.random(r))},string(r){return R.fromBytes(r)},bytes(r){return R.toBytes(r)}});var vt=58,Ke="123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz",$t=Object.freeze({fromBytes(r){let e=BigInt("0x"+R.fromBytes(r)),t="";for(;e>0;){let o=e%BigInt(vt);e=e/BigInt(vt),t=Ke[Number(o)]+t}for(let o of r)if(o===0)t=Ke[0]+t;else break;return t},toBytes(r){let e=BigInt(0);for(let i of r){let l=Ke.indexOf(i);if(l===-1)throw new Error(`Invalid character '${i}' in base58 string`);e=e*BigInt(vt)+BigInt(l)}let t=e.toString(16);t.length%2!==0&&(t="0"+t);let o=R.toBytes(t),s=0;for(let i of r)if(i===Ke[0])s++;else break;let n=new Uint8Array(s+o.length);return n.set(o,s),n},random(r=32){return this.fromBytes(M.random(r))},string(r){return $t.fromBytes(r)},bytes(r){return $t.toBytes(r)}});var wr=class{lexicon;static lexicons=Object.freeze({base2:{characters:"01"},hex:{characters:"0123456789abcdef"},base36:{characters:"0123456789abcdefghijklmnopqrstuvwxyz"},base58:{characters:"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"},base62:{characters:"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"},base64url:{negativePrefix:"~",characters:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"},base64:{characters:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",padding:{character:"=",size:4}}});lookup;negativePrefix;constructor(e){this.lexicon=e,this.lookup=Object.fromEntries([...e.characters].map((t,o)=>[t,o])),this.negativePrefix=e.negativePrefix??"-"}toBytes(e){let t=Math.log2(this.lexicon.characters.length);if(Number.isInteger(t)){let l=0,a=0,c=[];for(let u of e){if(u===this.lexicon.padding?.character)continue;let f=this.lookup[u];if(f===void 0)throw new Error(`Invalid character: ${u}`);for(l=l<<t|f,a+=t;a>=8;)a-=8,c.push(l>>a&255)}return new Uint8Array(c)}let o=0n,s=BigInt(this.lexicon.characters.length),n=!1;e.startsWith(this.negativePrefix)&&(e=e.slice(this.negativePrefix.length),n=!0);for(let l of e){let a=this.lookup[l];if(a===void 0)throw new Error(`Invalid character: ${l}`);o=o*s+BigInt(a)}let i=[];for(;o>0n;)i.unshift(Number(o%256n)),o=o/256n;return new Uint8Array(i)}fromBytes(e){let t=Math.log2(this.lexicon.characters.length);if(Number.isInteger(t)){let i=0,l=0,a="";for(let c of e)for(i=i<<8|c,l+=8;l>=t;){l-=t;let u=i>>l&(1<<t)-1;a+=this.lexicon.characters[u]}if(l>0){let c=i<<t-l&(1<<t)-1;a+=this.lexicon.characters[c]}if(this.lexicon.padding)for(;a.length%this.lexicon.padding.size!==0;)a+=this.lexicon.padding.character;return a}let o=0n;for(let i of e)o=(o<<8n)+BigInt(i);if(o===0n)return this.lexicon.characters[0];let s=BigInt(this.lexicon.characters.length),n="";for(;o>0n;)n=this.lexicon.characters[Number(o%s)]+n,o=o/s;return n}toInteger(e){if(!e)return 0;let t=0n,o=!1,s=BigInt(this.lexicon.characters.length);e.startsWith(this.negativePrefix)&&(e=e.slice(this.negativePrefix.length),o=!0);for(let n of e){let i=this.lookup[n];if(i===void 0)throw new Error(`Invalid character: ${n}`);t=t*s+BigInt(i)}return Number(o?-t:t)}fromInteger(e){e=Math.floor(e);let t=e<0,o=BigInt(t?-e:e);if(o===0n)return this.lexicon.characters[0];let s=BigInt(this.lexicon.characters.length),n="";for(;o>0n;)n=this.lexicon.characters[Number(o%s)]+n,o=o/s;return t?`${this.negativePrefix}${n}`:n}random(e=32){return this.fromBytes(M.random(e))}};var At=Object.freeze({fromBytes(r){return typeof btoa=="function"?btoa(String.fromCharCode(...r)):Buffer.from(r).toString("base64")},toBytes(r){return typeof atob=="function"?Uint8Array.from(atob(r),e=>e.charCodeAt(0)):Uint8Array.from(Buffer.from(r,"base64"))},random(r=32){return this.fromBytes(M.random(r))},string(r){return At.fromBytes(r)},bytes(r){return At.toBytes(r)}});var vr=Object.freeze({fromBytes(r){return new TextDecoder().decode(r)},toBytes(r){return new TextEncoder().encode(r)},string(r){return vr.fromBytes(r)},bytes(r){return vr.toBytes(r)}});var St=Object.freeze({set:r=>r!=null,unset:r=>r==null,boolean:r=>typeof r=="boolean",number:r=>typeof r=="number",string:r=>typeof r=="string",bigint:r=>typeof r=="bigint",object:r=>typeof r=="object"&&r!==null,array:r=>Array.isArray(r),fn:r=>typeof r=="function",symbol:r=>typeof r=="symbol"});function $r(){let r,e,t=new Promise((s,n)=>{r=s,e=n});function o(s){return s.then(r).catch(e),t}return{promise:t,resolve:r,reject:e,entangle:o}}var A=class r extends Map{static require(e,t){let o=e.get(t);if(o===void 0)throw new Error(`required key not found: "${t}"`);return o}static guarantee(e,t,o){let s=e.get(t);return s===void 0&&(s=o(),e.set(t,s)),s}array(){return[...this]}require(e){return r.require(this,e)}guarantee(e,t){return r.guarantee(this,e,t)}};function vo(r){return{map:e=>Ar(r,e),filter:e=>Sr(r,e)}}vo.pipe=Object.freeze({map:r=>(e=>Ar(e,r)),filter:r=>(e=>Sr(e,r))});var Ar=(r,e)=>Object.fromEntries(Object.entries(r).map(([t,o])=>[t,e(o,t)])),Sr=(r,e)=>Object.fromEntries(Object.entries(r).filter(([t,o])=>e(o,t)));function $o(){let r=new Set;function e(n){return r.add(n),()=>{r.delete(n)}}async function t(...n){await Promise.all([...r].map(i=>i(...n)))}async function o(){let{promise:n,resolve:i}=$r(),l=e((...a)=>{i(a),l()});return n}function s(){r.clear()}return e.pub=t,e.sub=e,e.on=e,e.once=o,e.clear=s,t.pub=t,t.sub=e,t.on=e,t.once=o,t.clear=s,[t,e]}function j(r){let e=$o()[1];return r&&e.sub(r),e}var Ze=class{#e=new A;setGroup(e,t){return this.#e.set(e,t),t}getGroup(e){return this.#e.require(e)}};var Je=new Ze;var Ye=class{group;#e=new Le.DragAndDrops({acceptDrop:(e,t,o)=>this.group.move(t,o)});constructor(e){this.group=e}#t=h(void 0);get grabbed(){return this.#e.dragging}get hovering(){return this.#e.hovering??this.#t()}dragenter=(e,t)=>{e.preventDefault(),this.#e.dropzone(()=>t).dragenter(e),this.#t(t)};dragleave=e=>{let t=this.hovering;t&&this.#e.dropzone(()=>t).dragleave(e),this.#t(void 0)};dragstart=(e,t)=>{e.stopPropagation(),this.#e.dragzone(()=>t).dragstart(e)};dragover=(e,t)=>{e.preventDefault(),this.#e.dropzone(()=>t).dragover(e)};dragend=e=>{this.#e.$draggy(void 0),this.#e.$droppy(void 0),this.#t(void 0)};drop=(e,t)=>{e.preventDefault();let o=Array.from(e.dataTransfer?.files||[]);o.length&&this.group.upload(o,t);let s=this.grabbed?.id===this.hovering?.id,n=this.grabbed?.children.some(l=>this.hovering?.id===l.id),i=this.grabbed?.parent?.id===this.hovering?.id;!s&&!n&&!i&&this.#e.dropzone(()=>t).drop(e),this.#t(void 0)};change=(e,t)=>{let o=e.currentTarget,s=Array.from(o.files??[]);s.length&&this.group.upload(s,t)}};var Xe=class{signal=h([]);constructor(e){this.signal([e])}setTrail(e,t){if(e.target!==e.currentTarget)return;let o=[],s=t.kind==="folder"?t:t.parent;for(;s;)o.unshift(s),s=s.parent;this.signal(o)}get currentFolder(){return this.signal().at(-1)?.children??[]}};var et=class{config;trail;dropzone=new Ye(this);searchText=h("");selectedFilter=h("");selectedSort=h("");on={newFolder:j(),move:j(),delete:j(),rename:j(),upload:j(),search:j(),refresh:j()};constructor(e){this.config=e,this.selectedFilter(e.defaultFilter),this.selectedSort(e.defaultSort),this.trail=new Xe(e.root)}get permissions(){return this.config.permissions}getFilterFn(e){return this.config.filters.get(e)??(()=>!0)}getSearchFn(e){let t=e.trim().toLowerCase().split(/\s+/);return o=>this.config.search(t,o)}getSortFn(e){return this.config.sorts?.get(e)??(()=>0)}sort(e){let t=this.getSortFn(this.selectedSort());return[...e].sort(t)}matches(e){let t=this.getFilterFn(this.selectedFilter()),o=this.getSearchFn(this.searchText());return t(e)&&o(e)}move(e,t){if(!this.permissions(e).move)throw new Error("move permission not granted");e.detach(),t.attach(e),this.on.move.pub({item:e,target:t})}delete(e){if(!this.permissions(e).delete)throw new Error("delete permission not granted");let t=[...e.crawl()].map(([o])=>o);return e.destroy(),this.on.delete.pub({items:t})}rename(e,t){if(!this.permissions(e).rename)throw new Error("rename permission not granted");this.on.rename.pub({item:e,newName:t})}upload(e,t){if(!this.permissions(t).upload)throw new Error("upload permission not granted");return this.on.upload.pub({files:e,target:t})}addFolder(e){if(!this.permissions(e).newFolder)throw new Error("add folder permission not granted");this.on.newFolder.pub({parent:e})}components=()=>this.components};var xe;(function(r){r.rename="rename",r.move="move",r.delete="delete",r.refresh="refresh",r.newFolder="newFolder",r.search="search",r.upload="upload"})(xe||(xe={}));var Ao=Object.values(xe);function _t(r,e={}){let t={};for(let o of Ao)t[o]=o in e?e[o]:r;return t}var _r={all:_t(!0),readOnly:_t(!1,{[xe.refresh]:!0,[xe.search]:!0}),none:_t(!1)};var tt=class{taxonomy;onChange=j();#e=new A;constructor(e){this.taxonomy=e}getSpecimen(e){return this.#e.require(e)}setSpecimen(e,t,o){this.#e.set(e,[t,o]),this.onChange.pub()}query(e){let[t,o]=this.getSpecimen(e),s=this.taxonomy.taxon(t);return{kind:t,taxon:s,specimen:o}}};var rt=class{#e=new A;constructor(e){for(let[t,o]of Object.entries(e))this.#e.set(t,o)}taxon(e){return this.#e.require(e)}};var ot=class{#e=new A;#t=new A;has(e){return this.#e.has(e)}getChildren(e){return this.#e.require(e)}getParent(e){return this.#t.get(e)}establishRoot(e){this.#e.set(e,new Set)}attach(e,...t){let o=this.getChildren(e);for(let s of t){if(this.getParent(s))throw new Error("child already has parent");o.add(s),this.#t.set(s,e),this.#e.set(s,new Set)}}detach(e){if(!this.has(e))return;let t=this.getParent(e);t&&(this.getChildren(t).delete(e),this.#t.delete(e))}destroy(e){this.detach(e);let t=[...this.crawl(e)];for(let[o]of t)this.#e.delete(o),this.#t.delete(o)}*crawl(e,t=()=>!0){let o=[[e,[]]],s=new Set;for(;o.length;){let[n,i]=o.shift();if(!(s.has(n)||!t(n,i))){s.add(n),yield[n,i];for(let l of this.getChildren(n))o.push([l,[...i,n]])}}}};var st=class{codex;id;signal=h(this);constructor(e,t){this.codex=e,this.id=t}get kind(){return this.codex.clade.query(this.id).kind}isKind(e){return e===this.kind}get taxon(){return this.codex.clade.query(this.id).taxon}get specimen(){return this.codex.clade.query(this.id).specimen}get parent(){let e=this.codex.hierarchy.getParent(this.id);return e?this.codex.require(e):void 0}get children(){return[...this.codex.hierarchy.getChildren(this.id)].map(e=>this.codex.require(e))}attach(...e){return this.codex.hierarchy.attach(this.id,...e.map(t=>t.id)),this.signal(this),this}detach(){this.codex.hierarchy.detach(this.id),this.signal(this)}create(e,t){let o=this.codex.create(e,t);return this.attach(o),o}destroy(){this.codex.hierarchy.destroy(this.id),this.signal(this)}*crawl(e=()=>!0){let t=this.codex.hierarchy.crawl(this.id,(o,s)=>e(this.codex.require(o),s.map(n=>this.codex.require(n))));for(let[o,s]of t)yield[this.codex.require(o),s.map(n=>this.codex.require(n))]}};function Er(){return R.random()}var nt=class{clade;hierarchy;static setup(e){let t=new rt(e),o=new tt(t),s=new ot;return new this(o,s)}#e=new A;constructor(e,t){this.clade=e,this.hierarchy=t}create(e,t){let o=Er();this.clade.setSpecimen(o,e,t);let s=new st(this,o);return this.#e.set(o,s),s.signal()}root(e){return this.hierarchy.establishRoot(e.id),e.signal()}require(e){return this.#e.require(e).signal()}};var it=class r extends et{static config=()=>{let e=new A().set("audio",p`<sl-icon name=music-note-beamed></sl-icon>`).set("video",p`<sl-icon name=film></sl-icon>`).set("image",p`<sl-icon name=image></sl-icon>`).set("other",p`<sl-icon name=file-earmark></sl-icon>`),t=new Map().set("all",()=>!0).set("video",a=>a.isKind("folder")||a.isKind("file")&&a.specimen.format==="video").set("audio",a=>a.isKind("folder")||a.isKind("file")&&a.specimen.format==="audio"),o=new Map().set("label",(a,c)=>a.specimen.label.localeCompare(c.specimen.label)).set("format",(a,c)=>a.isKind("file")&&c.isKind("file")?a.specimen.format.localeCompare(c.specimen.format):a.isKind("file")?-1:c.isKind("file")?1:0),s=(a,c)=>{let u=a.join(" ").trim().toLowerCase();return u===""?!0:c.kind==="folder"?c.children.some(f=>s(a,f)):c.specimen.label.toLowerCase().includes(u)},n=nt.setup({folder:{icon:p`<sl-icon name="folder"></sl-icon>`},file:{icon:p`<sl-icon name="file"></sl-icon>`}}),i=n.root(n.create("folder",{label:"project"})),l=(a,c)=>a.isKind("file")?e.require(a.specimen.format):c?p`<sl-icon name="folder2-open"></sl-icon>`:a.taxon.icon;return{codex:n,root:i,sorts:o,filters:t,defaultFilter:"all",defaultSort:"label",search:(a,c)=>a.some(u=>c.kind.includes(u)||c.id.includes(u)||c.specimen.label.includes(u))||s(a,c),renderIcon:l,renderLabel:a=>a.specimen.label,renderPreview:a=>a.isKind("file")&&a.specimen.previewUrl?p`<img src=${a.specimen.previewUrl}>`:l(a,!1),permissions:a=>_r.all}};constructor(){super(r.config())}};var $=d`@layer theme, view; @layer theme {
|
|
29
29
|
|
|
30
30
|
* {
|
|
31
31
|
margin: 0;
|