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`
+
+ `
+ }
+}
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()