diff --git a/declarations.d.ts b/declarations.d.ts index c6593da..14f6120 100644 --- a/declarations.d.ts +++ b/declarations.d.ts @@ -1 +1,2 @@ /// +/// diff --git a/package-lock.json b/package-lock.json index 890175c..eedd16c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "vitest-axe": "^0.1.0" }, "devDependencies": { + "@iconify-json/lucide": "^1.2.116", "@types/mime-types": "^3.0.1", "@types/node": "^22.20.0", "@vitest/coverage-v8": "^4.0.18", @@ -2320,22 +2321,24 @@ } }, "node_modules/@emnapi/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", - "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.2.tgz", + "integrity": "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "node_modules/@emnapi/runtime": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", - "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.2.tgz", + "integrity": "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -2653,6 +2656,16 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@iconify-json/lucide": { + "version": "1.2.117", + "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.117.tgz", + "integrity": "sha512-7isYKJKWRZ8NfLNSY8pIYmRWiMBkopL4/X22gZfFmePFhc7az0hQ5biqBLG6vdDEvMctFu2suZB3yQ29RL+8tA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@iconify/types": "*" + } + }, "node_modules/@iconify/types": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", @@ -2982,10 +2995,12 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.139.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", - "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", + "version": "0.140.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.140.0.tgz", + "integrity": "sha512-h5LUOzGArYemnW1NMz/DuuQhBi96J6JL2Bk8zE4kvqxB5Sg3jxmCiH4uyOWHDkiKSt5vWlG4FIwCR/DbstcNRQ==", + "dev": true, "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/Boshen" } @@ -3033,209 +3048,235 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", - "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.0.tgz", + "integrity": "sha512-9yB1l95IrJuNGDFdOYe79vdApdz6WWBCObE+rQ2LUliYUlcyFwSYIb2xb5/Ifw7dAtMy2ZqNyd8QTSOc7duAKw==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "android" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", - "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.0.tgz", + "integrity": "sha512-pexNaW9ACLUOaBITOpU6qVu4VrsOFIjTv6bzgu0YUATo4eUJx0V605PxwZfndpPOn0ilqGqvGQ0M8UW0IE24jg==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", - "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.0.tgz", + "integrity": "sha512-NqKYaq0355ZmNMG4QGpxtEDxsc7tGDhjhCm4PpE0cwnBW+5Il95LJyq414niEiaKLVjnVHBEjSo1wngKxJNiFw==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "darwin" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", - "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.0.tgz", + "integrity": "sha512-3vPoHzh6eBTz9IbB0/qZdSr0Qeks2echn+I4cHu2joV74VriPDdldswksEDzrl1mBB+oPRi+67+3Ib59paxIPQ==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", - "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.0.tgz", + "integrity": "sha512-E6NNefZ1bUVmKJq2tJkf45J4Zyczj7qm9rUT7NY+Xo2474Y13qWAwc2tvBt0BAVbmtXR1llkxXg0Ou1jbDf2SQ==", "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", - "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.0.tgz", + "integrity": "sha512-D+TgkdgM1vu+7/Fpf8+v0ARW+RXEP9Ccazgm8zQ4JFFd9Q7SrYQ2TakU5S5ihazQDgpKyAgZDOcIFsvoHmTZ8w==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", - "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.0.tgz", + "integrity": "sha512-wUqdwJBbAv0APN87GecstdMUtLjjNTs0hBALpxETD73mccFxdmt/XeizXDtN5RAlBwNKmI+Tg+blect2G+8IeQ==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", - "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.0.tgz", + "integrity": "sha512-9DtF35qR9/NrfhM4oxLplCzVVjE+KKm8Pjemi0i/sdhAWkUasjmSo8WTTubNJClhSHCfyk2yeyoXDQEDPtDAAw==", "cpu": [ "ppc64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", - "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.0.tgz", + "integrity": "sha512-RzuHrBh8X8Hntd2N4VR02QGEciq/9JhcZoTpR/Cee6otRrlILGCf3cg2ygHuih+ZebUnWmMrDX6ITI85btO6rQ==", "cpu": [ "s390x" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", - "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.0.tgz", + "integrity": "sha512-MK7L0018jjh1jR3mh21G2j1zAVcpscJBlPo2z19pRjv2XOYGRhaV4LyiD8HO6nCDdZln9IFgCMIV5yt4E3klGQ==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", - "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.0.tgz", + "integrity": "sha512-gyrxLQ9NfGb/9LoVnC4kb9miUghw1mghnkfYvNHSnVIXriabnfgGPUP4RLcJm87q3KgYz4FYUG8IDiWUT+CpSw==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "linux" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", - "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.0.tgz", + "integrity": "sha512-/6VFMQGRmrhP77KXDC+StIxGzcNp5JOIyYtw0CQ8gPlzhpiIRucYfoM5FaFamHd5BJYIdH86yfP46l1p3WdrFA==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "openharmony" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", - "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.0.tgz", + "integrity": "sha512-rwdbUL465kisF24WEJLvP3JrEG6E5GRuIHt5wpMwHGERtHe4Wm2CIvtf5gTBgr2tGOHKh5NdKEAFS2VkOPE91g==", "cpu": [ "wasm32" ], + "dev": true, "license": "MIT", "optional": true, + "peer": true, "dependencies": { - "@emnapi/core": "1.11.1", - "@emnapi/runtime": "1.11.1", + "@emnapi/core": "1.11.2", + "@emnapi/runtime": "1.11.2", "@napi-rs/wasm-runtime": "^1.1.6" }, "engines": { @@ -3243,33 +3284,37 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", - "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.0.tgz", + "integrity": "sha512-+5suHwRiKGmhwyUaNT8a5QbrBvLFh2DbO910TEmGRH1aSxwrCezodvGQnulv4uiWEIv1Kq4ypRsJ5+O+ry1DiA==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", - "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.0.tgz", + "integrity": "sha512-WfFv6/qGufotqBSBzBYwgpCkJBk8Nj7697LL9vTz/XWc67e0r3oewu8iMRwQj3AUL45GVD7wVsPjCsAAtW66Wg==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ "win32" ], + "peer": true, "engines": { "node": "^20.19.0 || >=22.12.0" } @@ -4307,9 +4352,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001805", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001805.tgz", - "integrity": "sha512-52noaS3DubycKSXaU30TwPGIp+POyQSUVa5jBEq3vkRkY0kjyb3LQgvhU6WGyCcyXqVLWO0Cw0Q6BSdD0kUfVA==", + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", "dev": true, "funding": [ { @@ -4789,9 +4834,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.392", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.392.tgz", - "integrity": "sha512-1yQq3VQCZRwsnYc67Oc+1fge6Lwtn0hzi6zmEVkB61Zx21kTbwJAW4dFLadl5Rc1tKhG/kSpYXnfiAhu0f0a1g==", + "version": "1.5.393", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.393.tgz", + "integrity": "sha512-kiDJdIUawuEIcp9XoICKp1iTYDEbgguIPq526N1Q7jIQDeQ3CqoMx71025PI/7E48Ddtw2HuWsVjY7afEgNxmg==", "dev": true, "license": "ISC" }, @@ -7699,9 +7744,9 @@ } }, "node_modules/obug": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", - "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", "funding": [ "https://github.com/sponsors/sxzz", "https://opencollective.com/debug" @@ -8472,12 +8517,14 @@ } }, "node_modules/rolldown": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", - "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.0.tgz", + "integrity": "sha512-u7tgm5l4Yw1iTqUL4EcYOAt7fFvCgQMLeidrnD4GALlC6aOznCjezYajgxeyKw27u0Q5N7fwgCzjVyPIWzwuBA==", + "dev": true, "license": "MIT", + "peer": true, "dependencies": { - "@oxc-project/types": "=0.139.0", + "@oxc-project/types": "=0.140.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -8487,21 +8534,21 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.1.5", - "@rolldown/binding-darwin-arm64": "1.1.5", - "@rolldown/binding-darwin-x64": "1.1.5", - "@rolldown/binding-freebsd-x64": "1.1.5", - "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", - "@rolldown/binding-linux-arm64-gnu": "1.1.5", - "@rolldown/binding-linux-arm64-musl": "1.1.5", - "@rolldown/binding-linux-ppc64-gnu": "1.1.5", - "@rolldown/binding-linux-s390x-gnu": "1.1.5", - "@rolldown/binding-linux-x64-gnu": "1.1.5", - "@rolldown/binding-linux-x64-musl": "1.1.5", - "@rolldown/binding-openharmony-arm64": "1.1.5", - "@rolldown/binding-wasm32-wasi": "1.1.5", - "@rolldown/binding-win32-arm64-msvc": "1.1.5", - "@rolldown/binding-win32-x64-msvc": "1.1.5" + "@rolldown/binding-android-arm64": "1.2.0", + "@rolldown/binding-darwin-arm64": "1.2.0", + "@rolldown/binding-darwin-x64": "1.2.0", + "@rolldown/binding-freebsd-x64": "1.2.0", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.0", + "@rolldown/binding-linux-arm64-gnu": "1.2.0", + "@rolldown/binding-linux-arm64-musl": "1.2.0", + "@rolldown/binding-linux-ppc64-gnu": "1.2.0", + "@rolldown/binding-linux-s390x-gnu": "1.2.0", + "@rolldown/binding-linux-x64-gnu": "1.2.0", + "@rolldown/binding-linux-x64-musl": "1.2.0", + "@rolldown/binding-openharmony-arm64": "1.2.0", + "@rolldown/binding-wasm32-wasi": "1.2.0", + "@rolldown/binding-win32-arm64-msvc": "1.2.0", + "@rolldown/binding-win32-x64-msvc": "1.2.0" } }, "node_modules/safe-array-concat": { @@ -8813,9 +8860,9 @@ } }, "node_modules/solidos-toolkit": { - "version": "0.0.0-dev.c12653a8e6e099052a4fade85552d2c77e1ab5c9", - "resolved": "https://registry.npmjs.org/solidos-toolkit/-/solidos-toolkit-0.0.0-dev.c12653a8e6e099052a4fade85552d2c77e1ab5c9.tgz", - "integrity": "sha512-6JhnR/coSwd5zomAU9uEVFZo84mmYiYYDtpHaxZX6NtoW3StD+/9c22LMyTuNBMF+pb5V4PO7lle7zbEBI6S/w==", + "version": "0.0.0-dev.761b46f81590c0224a612fba4771aa9c84e7944a", + "resolved": "https://registry.npmjs.org/solidos-toolkit/-/solidos-toolkit-0.0.0-dev.761b46f81590c0224a612fba4771aa9c84e7944a.tgz", + "integrity": "sha512-4KXTvJEYBuymrNTJoT15bT2Ml7a6871g4HExEgNNtmnTDhkl6f0H07BChXuotk/awCkJztaE4VHFJgzRqQYcwg==", "dev": true, "dependencies": { "@babel/core": "^7.29.0", @@ -9132,22 +9179,22 @@ } }, "node_modules/tldts": { - "version": "7.4.8", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.8.tgz", - "integrity": "sha512-htwgN/8KRB3z3vnC0BOETVh2m499g5GmyTK9Wq5JBLX3FNz6tSBveAd+fQhzy9hkjif8vy2jwDMR1sGhLtZl2A==", + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.9.tgz", + "integrity": "sha512-3kZ8wQQ/k5DrChD4X4FVvr2D7E5uoRgAqkPyLpSCGUvqOvqu+JEdr3mwMUaVWb+vMHZaKhF5fp2PBigKsui7hA==", "devOptional": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.4.8" + "tldts-core": "^7.4.9" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.4.8", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.8.tgz", - "integrity": "sha512-c1P7u0EhACHj7lPy4MJm8iTFEU8+nB0LCtddH0fhP7noaVoXAqafMtOOeX+ulpuPBqnrRgRhw494RICT3mbhnw==", + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.9.tgz", + "integrity": "sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg==", "devOptional": true, "license": "MIT" }, @@ -9640,15 +9687,15 @@ } }, "node_modules/vite": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz", - "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==", + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", + "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", "license": "MIT", "dependencies": { "lightningcss": "^1.32.0", "picomatch": "^4.0.5", - "postcss": "^8.5.16", - "rolldown": "~1.1.4", + "postcss": "^8.5.17", + "rolldown": "~1.1.5", "tinyglobby": "^0.2.17" }, "bin": { @@ -9739,6 +9786,311 @@ "vite": "^7.0.0 || ^8.0.0" } }, + "node_modules/vite/node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/vite/node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/vite/node_modules/@oxc-project/types": { + "version": "0.139.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-android-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-darwin-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/vite/node_modules/rolldown": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.139.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.1.5", + "@rolldown/binding-darwin-arm64": "1.1.5", + "@rolldown/binding-darwin-x64": "1.1.5", + "@rolldown/binding-freebsd-x64": "1.1.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", + "@rolldown/binding-linux-arm64-gnu": "1.1.5", + "@rolldown/binding-linux-arm64-musl": "1.1.5", + "@rolldown/binding-linux-ppc64-gnu": "1.1.5", + "@rolldown/binding-linux-s390x-gnu": "1.1.5", + "@rolldown/binding-linux-x64-gnu": "1.1.5", + "@rolldown/binding-linux-x64-musl": "1.1.5", + "@rolldown/binding-openharmony-arm64": "1.1.5", + "@rolldown/binding-wasm32-wasi": "1.1.5", + "@rolldown/binding-win32-arm64-msvc": "1.1.5", + "@rolldown/binding-win32-x64-msvc": "1.1.5" + } + }, "node_modules/vitest": { "version": "4.1.10", "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", diff --git a/package.json b/package.json index afa7dfc..0aa4ac6 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ }, "homepage": "https://github.com/SolidOS/source-pane", "devDependencies": { + "@iconify-json/lucide": "^1.2.116", "@types/mime-types": "^3.0.1", "@types/node": "^22.20.0", "@vitest/coverage-v8": "^4.0.18", diff --git a/src/Header.ts b/src/Header.ts index 7c6cb3d..f994c9f 100644 --- a/src/Header.ts +++ b/src/Header.ts @@ -19,7 +19,7 @@ export function renderHeader (store: LiveStore, subject: NamedNode, sourcePaneSt function setEditable (sourcePaneState: SourcePaneState) { if (sourcePaneState.broken) return - const editorCard = document.querySelector('solid-panes-source-editor-card') as SourceEditorCard | null + const editorCard = document.querySelector('source-pane-source-editor-card') as SourceEditorCard | null editorCard?.updateEditingState(true) editorCard?.setReadOnly(false) editorCard?.focusEditor() diff --git a/src/components/header/SourceHeader.styles.css b/src/components/header/SourceHeader.styles.css new file mode 100644 index 0000000..032fa26 --- /dev/null +++ b/src/components/header/SourceHeader.styles.css @@ -0,0 +1,72 @@ +:host { + .sourcePaneHeader { + display: flex; + justify-content: space-between; + align-items: center; + gap: 6px; + flex-wrap: nowrap; + width: 100%; + text-align: right; + padding: 0 3px 16px 0; + } + + .sourcePaneIcon { + display: flex; + width: 40px; + height: 40px; + padding: 7.5px 7px 6.5px 7px; + justify-content: center; + align-items: center; + aspect-ratio: 1/1; + border-radius: 100px; + background: var(--slate-600, #45556C); + } + + .sourcePaneHeaderInfo { + display: flex; + justify-content: flex-start; + align-items: center; + gap: 6px; + flex-wrap: wrap; + flex: 1 1 auto; + min-width: 0; + text-align: left; + padding: 0 3px 16px 0; + } + + .sourcePaneControls { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 6px; + flex: 0 0 auto; + text-align: right; + padding: 0 3px 16px 0; + } + + /* generative ai */ + .sourcePaneControls > * { + flex: 0 1 auto; + } + + @media (max-width: 900px) { + .sourcePaneControls { + padding-right: 3px; + } + } + + @media (max-width: 600px) { + .sourcePaneControls { + justify-content: flex-start; + gap: 5px; + } + } + + .sourcePaneControlVisible { + display: block; + } + + .sourcePaneControlHidden { + display: none; + } +} \ No newline at end of file diff --git a/src/components/header/SourceHeader.ts b/src/components/header/SourceHeader.ts new file mode 100644 index 0000000..b7ddf8f --- /dev/null +++ b/src/components/header/SourceHeader.ts @@ -0,0 +1,57 @@ +import { WebComponent } from 'solid-ui' +import { customElement } from 'lit/decorators.js' +import { html } from 'lit' +import 'solid-ui/components/button' +import { consume } from '@lit/context' +import { sourceContext, SourceContext } from '../../primitives/context' +import '~icons/lucide/share-2' +import '~icons/lucide/pencil' +import '~icons/lucide/ellipsis-vertical' +import styles from './SourceHeader.styles.css' +import { sourcePaneIcon } from '../../icons/sourcePaneIcon' + +@customElement('source-pane-source-header') +export default class SourceHeader extends WebComponent { + static styles = styles + + @consume({ context: sourceContext, subscribe: true }) + accessor sourceContext: SourceContext = undefined as unknown as SourceContext + + /* private canEditSource (subject: NamedNode, sourcePaneState: SourcePaneState) { + const { allowed } = sourcePaneState + return !subject.uri.endsWith('/') && (!allowed || allowed.includes('PUT')) + } */ + + private setEditable() { + const sourcePaneState = this.sourceContext?.sourcePaneState + if (!sourcePaneState || sourcePaneState.broken) return + this.sourceContext?.setEditing() + } + + render () { + return html` +
+
+ ${sourcePaneIcon} +
+

Name of file

+
+

by Person date icon public/private

+
+
+
+
+ + + + + + + + + +
+
+ ` + } +} diff --git a/src/components/source-editor-card/SourceEditorCard.ts b/src/components/source-editor-card/SourceEditorCard.ts index e875966..a37d431 100644 --- a/src/components/source-editor-card/SourceEditorCard.ts +++ b/src/components/source-editor-card/SourceEditorCard.ts @@ -3,7 +3,8 @@ import { consume } from '@lit/context' import { customElement, query, state } from 'lit/decorators.js' import { NamedNode, parse, serialize } from 'rdflib' import type { SourceEditor } from './SourceEditor' -import { applyResponseHeaders, checkSyntax, fetchContentAndMetadata, getResponseHeaders, happy } from '../../helpers' +import { checkSyntax, happy } from '../../helpers' +import { applyResponseHeaders, fetchContentAndMetadata, getResponseHeaders } from '../../resourceMetadata' import styles from './SourceEditorCard.styles.css' import { WebComponent } from 'solid-ui' import { getStatusSection } from '../../StatusSection' @@ -12,7 +13,7 @@ import { compactable } from '../../compactableFormats' import { SourceContext } from '../../primitives/context' import { sourceContext } from '../../primitives/context' -@customElement('solid-panes-source-editor-card') +@customElement('source-pane-source-editor-card') export default class SourceEditorCard extends WebComponent { static styles = styles diff --git a/src/components/source-provider/SourceProvider.ts b/src/components/source-provider/SourceProvider.ts index 705d2c1..699a0ee 100644 --- a/src/components/source-provider/SourceProvider.ts +++ b/src/components/source-provider/SourceProvider.ts @@ -1,13 +1,14 @@ import { html, type PropertyValues } from 'lit' import { provide } from '@lit/context' -import { customElement, property } from 'lit/decorators.js' +import { customElement, property, query } from 'lit/decorators.js' import { NamedNode } from 'rdflib' import { DataBrowserContext } from 'pane-registry' -import { renderHeader } from '../../Header' import { getStatusSection } from '../../StatusSection' import { WebComponent } from 'solid-ui' import { sourceContext, SourceContext } from '../../primitives/context' import { SourcePaneState } from '../../types' +import type SourceEditorCard from '../source-editor-card/SourceEditorCard' +import '../header/SourceHeader' void import('../source-editor-card/SourceEditorCard').then(() => undefined) @@ -17,7 +18,9 @@ const defaultSourcePaneState: SourcePaneState = { editing: false, allowed: undefined, contentType: undefined, - eTag: undefined + eTag: undefined, + title: undefined, + modified: undefined } @customElement('source-pane-source-provider') @@ -37,8 +40,11 @@ export default class SourceProvider extends WebComponent { subject: '', sourcePaneState: defaultSourcePaneState, updateSourcePaneState: () => {}, + setEditing: () => {} } + @query('source-pane-source-editor-card') + private accessor editorCard: SourceEditorCard | null = null // need this while we are using document.querySelector // and rendering plain HTML children. Can remove later when all // code is refactored to use context and components. @@ -46,22 +52,6 @@ export default class SourceProvider extends WebComponent { return this } - private _requireContext () { - if (!this.context) { - throw new Error('The element is missing the required `context` property.') - } - - return this.context - } - - private _requireSubject () { - if (!this.subject) { - throw new Error('The element is missing the required `subject` property.') - } - - return this.subject - } - updateSourcePaneState = (key: K, value: SourcePaneState[K]) => { this.sourcePaneState = { ...this.sourcePaneState, @@ -69,29 +59,35 @@ export default class SourceProvider extends WebComponent { } } - protected override willUpdate (changedProperties: PropertyValues) { + setEditing = () => { + this.updateSourcePaneState('editing', true) + this.editorCard?.updateEditingState(true) + this.editorCard?.setReadOnly(false) + this.editorCard?.focusEditor() + } + + protected willUpdate (changedProperties: PropertyValues) { super.willUpdate(changedProperties) - const context = this._requireContext() - const subject = this._requireSubject() + if (!this.context) { + throw new Error('The element is missing the required `context` property.') + } this.sourceContextValue = { - context, - subject: subject.uri, + context: this.context, + subject: this.subject?.uri ?? '', sourcePaneState: this.sourcePaneState, updateSourcePaneState: this.updateSourcePaneState, + setEditing: this.setEditing } } render() { - const context = this._requireContext() - const subject = this._requireSubject() - const store = context.session.store const { renderStatusSection } = getStatusSection() return html` - ${renderHeader(store as any, subject as any, this.sourcePaneState)} - + + ${renderStatusSection()} ` } diff --git a/src/helpers.ts b/src/helpers.ts index a4c5385..aa78938 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -1,8 +1,6 @@ import { LiveStore, NamedNode, parse, serialize } from 'rdflib' import { getStatusSection } from './StatusSection' -import { error, log } from './debug' -import { ns } from 'solid-ui' -import { HttpResourceMetadata, SourcePaneState } from './types' +import { error } from './debug' const parseable: Record = { 'text/n3': true, @@ -131,69 +129,3 @@ export function setControlVisible (button: HTMLElement | null, visible: boolean) button.classList.toggle('sourcePaneControlVisible', visible) button.classList.toggle('sourcePaneControlHidden', !visible) } - -export function applyResponseHeaders (sourcePaneState: SourcePaneState, metadata: HttpResourceMetadata) { - sourcePaneState.contentType = metadata.contentType - sourcePaneState.allowed = metadata.allowed - sourcePaneState.eTag = metadata.eTag -} - -export function getResponseHeaders (store: LiveStore, subject: NamedNode, response: Response): HttpResourceMetadata { - let contentType: string | undefined - let allowed: string | undefined - let eTag: string | undefined - if (response.headers && response.headers.get('content-type')) { - contentType = response.headers.get('content-type')?.split(';')[0] ?? undefined // Should work but headers may be empty - allowed = response.headers.get('allow') ?? undefined // const cts = store.fetcher.getHeader(subject.doc(), 'content-type') - eTag = response.headers.get('etag') ?? undefined - } else { - const reqs = store.each( - null, - store.sym('http://www.w3.org/2007/ont/link#requestedURI'), - subject - ) - reqs.forEach((req: any) => { - const rrr = store.any( - req as any, - store.sym('http://www.w3.org/2007/ont/link#response') - ) - if (rrr && rrr.termType === 'NamedNode') { - contentType = store.anyValue(rrr as any, ns.httph('content-type')) || undefined - allowed = store.anyValue(rrr as any, ns.httph('allow')) || undefined - eTag = store.anyValue(rrr as any, ns.httph('etag')) || undefined - if (!eTag) log('sourcePane: No eTag on GET') - } - }) - } - return { contentType, allowed, eTag } -} - -export async function fetchContentAndMetadata(store: LiveStore, subject: NamedNode, sourcePaneState: SourcePaneState): Promise<{ content: string, metadata: HttpResourceMetadata }> { - const fetcher = store.fetcher - const { showError } = getStatusSection() - - try { - const response = await fetcher.webOperation('GET', subject.uri) - if (!happy(response, 'GET')) { - throw new Error('GET request failed') - } - - const content = (response as Response & { responseText?: string }).responseText - if (content === undefined) { // Defensive https://github.com/linkeddata/rdflib.js/issues/506 - throw new Error('source pane: No text in response object!!') - } - - const metadata = getResponseHeaders(store, subject, response) - if (!metadata.contentType) { - throw new Error('Error: No content-type available!') - } - applyResponseHeaders(sourcePaneState, metadata) - if (!metadata.allowed) { - error('@@@@@@@@@@ No Allow: header from this server') - } - return { content, metadata } - } catch (err: any) { - showError('Error reading file: ' + err) - throw err - } -} diff --git a/src/icons/sourcePaneIcon.ts b/src/icons/sourcePaneIcon.ts new file mode 100644 index 0000000..103c714 --- /dev/null +++ b/src/icons/sourcePaneIcon.ts @@ -0,0 +1,8 @@ +import { html } from 'lit' + +export const sourcePaneIcon = html` + + + + +` diff --git a/src/primitives/context.ts b/src/primitives/context.ts index 3ce007d..4f9ca60 100644 --- a/src/primitives/context.ts +++ b/src/primitives/context.ts @@ -6,7 +6,8 @@ export interface SourceContext { context: DataBrowserContext, readonly subject: string, sourcePaneState: SourcePaneState, - updateSourcePaneState: (key: K, value: SourcePaneState[K]) => void + updateSourcePaneState: (key: K, value: SourcePaneState[K]) => void, + setEditing: () => void } export const sourceContext = createContext(Symbol('source')) diff --git a/src/resourceMetadata.ts b/src/resourceMetadata.ts new file mode 100644 index 0000000..d5187fa --- /dev/null +++ b/src/resourceMetadata.ts @@ -0,0 +1,80 @@ +import { ns } from 'solid-ui' +import { getStatusSection } from './StatusSection' +import { error, log } from './debug' +import { HttpResourceMetadata, SourcePaneState } from './types' +import { LiveStore, NamedNode } from 'rdflib' +import { happy } from './helpers' + +export function applyResponseHeaders (sourcePaneState: SourcePaneState, metadata: HttpResourceMetadata) { + sourcePaneState.contentType = metadata.contentType + sourcePaneState.allowed = metadata.allowed + sourcePaneState.eTag = metadata.eTag +} + +export function getResponseHeaders (store: LiveStore, subject: NamedNode, response: Response): HttpResourceMetadata { + let contentType: string | undefined + let allowed: string | undefined + let eTag: string | undefined + let title: string | undefined + let modified: string | undefined + + if (response.headers && response.headers.get('content-type')) { + contentType = response.headers.get('content-type')?.split(';')[0] ?? undefined // Should work but headers may be empty + allowed = response.headers.get('allow') ?? undefined // const cts = store.fetcher.getHeader(subject.doc(), 'content-type') + eTag = response.headers.get('etag') ?? undefined + title = store.anyValue(subject as any, ns.rdfs('label')) || store.anyValue(subject as any, ns.dct('title')) || undefined + modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined + + } else { + const reqs = store.each( + null, + store.sym('http://www.w3.org/2007/ont/link#requestedURI'), + subject + ) + reqs.forEach((req: any) => { + const rrr = store.any( + req as any, + store.sym('http://www.w3.org/2007/ont/link#response') + ) + if (rrr && rrr.termType === 'NamedNode') { + contentType = store.anyValue(rrr as any, ns.httph('content-type')) || undefined + allowed = store.anyValue(rrr as any, ns.httph('allow')) || undefined + eTag = store.anyValue(rrr as any, ns.httph('etag')) || undefined + title = store.anyValue(subject as any, ns.rdfs('label')) || store.anyValue(subject as any, ns.dct('title')) || undefined + modified = store.anyValue(subject as any, ns.dct('modified')) || store.anyValue(subject as any, ns.dc('modified')) || undefined + if (!eTag) log('sourcePane: No eTag on GET') + } + }) + } + return { contentType, allowed, eTag, title, modified } +} + +export async function fetchContentAndMetadata(store: LiveStore, subject: NamedNode, sourcePaneState: SourcePaneState): Promise<{ content: string, metadata: HttpResourceMetadata }> { + const fetcher = store.fetcher + const { showError } = getStatusSection() + + try { + const response = await fetcher.webOperation('GET', subject.uri) + if (!happy(response, 'GET')) { + throw new Error('GET request failed') + } + + const content = (response as Response & { responseText?: string }).responseText + if (content === undefined) { // Defensive https://github.com/linkeddata/rdflib.js/issues/506 + throw new Error('source pane: No text in response object!!') + } + + const metadata = getResponseHeaders(store, subject, response) + if (!metadata.contentType) { + throw new Error('Error: No content-type available!') + } + applyResponseHeaders(sourcePaneState, metadata) + if (!metadata.allowed) { + error('@@@@@@@@@@ No Allow: header from this server') + } + return { content, metadata } + } catch (err: any) { + showError('Error reading file: ' + err) + throw err + } +} diff --git a/src/sourcePane.css b/src/sourcePane.css index f69e3e6..cb9c942 100644 --- a/src/sourcePane.css +++ b/src/sourcePane.css @@ -8,22 +8,6 @@ border: 1px solid var(--color-border, var(--gray-200, #E5E7EB)); } -.sourcePaneControls { - display: flex; - justify-content: flex-end; - align-items: center; - gap: 6px; - flex-wrap: wrap; - width: 100%; - text-align: right; - padding: 0 3px 16px 0; -} -/* generative ai */ -.sourcePaneControls > * { - flex: 0 1 auto; -} - -.sourcePaneHeader, .sourcePaneCard, .sourcePaneStatus { width: 100%; @@ -41,10 +25,6 @@ } @media (max-width: 900px) { - .sourcePaneControls { - padding-right: 3px; - } - .sourcePaneTextArea { margin: 12px 2px; padding: 12px; @@ -52,11 +32,6 @@ } @media (max-width: 600px) { - .sourcePaneControls { - justify-content: flex-start; - gap: 5px; - } - .sourcePaneCompactButton { min-width: 0; } @@ -65,11 +40,3 @@ .sourcePaneTextAreaError { color: var(--solid-ui-color-error, #b00020); } - -.sourcePaneControlVisible { - display: block; -} - -.sourcePaneControlHidden { - display: none; -} diff --git a/src/sourcePane.ts b/src/sourcePane.ts index 8d717b2..ffd3521 100644 --- a/src/sourcePane.ts +++ b/src/sourcePane.ts @@ -90,7 +90,9 @@ const pane = { editing: false, allowed: undefined, contentType: undefined, - eTag: undefined + eTag: undefined, + title: undefined, + modified: undefined } const sourcePane = context.dom.createElement('div') diff --git a/src/types.ts b/src/types.ts index e4ea537..4132ef3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -2,6 +2,8 @@ export type HttpResourceMetadata = { contentType: string | undefined allowed: string | undefined eTag: string | undefined + title: string | undefined + modified: string | undefined } export type SourcePaneState = { diff --git a/test/helpers.test.js b/test/helpers.test.js index 617cbdc..19cf3d8 100644 --- a/test/helpers.test.js +++ b/test/helpers.test.js @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest' -import { fetchContentAndMetadata, getResponseHeaders } from '../src/helpers.ts' +import { fetchContentAndMetadata, getResponseHeaders } from '../src/resourceMetadata.ts' describe('helpers', () => { beforeEach(() => { diff --git a/test/sourceEditorCard.test.js b/test/sourceEditorCard.test.js index c50268c..f0e4155 100644 --- a/test/sourceEditorCard.test.js +++ b/test/sourceEditorCard.test.js @@ -2,7 +2,7 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest' const fetchContentAndMetadata = vi.fn() -vi.mock('../src/helpers.ts', () => ({ +vi.mock('../src/resourceMetadata.ts', () => ({ fetchContentAndMetadata, })) diff --git a/test/sourcePane.test.js b/test/sourcePane.test.js index f0dcb80..60fe339 100644 --- a/test/sourcePane.test.js +++ b/test/sourcePane.test.js @@ -13,8 +13,8 @@ beforeAll(async () => { } } - if (!globalThis.customElements.get('solid-panes-source-editor-card')) { - globalThis.customElements.define('solid-panes-source-editor-card', MockSourceEditorCard) + if (!globalThis.customElements.get('source-pane-source-editor-card')) { + globalThis.customElements.define('source-pane-source-editor-card', MockSourceEditorCard) } const headerModule = await import('../src/Header.ts') @@ -66,7 +66,7 @@ describe('source-pane', () => { } const { container } = renderHeaderIntoDocument(sourcePaneState) - const editorCard = document.createElement('solid-panes-source-editor-card') + const editorCard = document.createElement('source-pane-source-editor-card') document.body.appendChild(editorCard) await Promise.resolve()