diff --git a/.gitignore b/.gitignore
index e9254ac..adf5574 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,6 @@ target
.env
.DS_Store
node_modules
-css_dist
js_dist
pgdata
.vite
diff --git a/Containerfile b/Containerfile
index 66baebd..bbb8b07 100644
--- a/Containerfile
+++ b/Containerfile
@@ -25,7 +25,6 @@ USER 1000
WORKDIR /home/app
COPY --from=builder /app/target/release/phono-server /usr/local/bin
-COPY ./css_dist ./css_dist
COPY ./js_dist ./js_dist
COPY ./static ./static
diff --git a/deno.lock b/deno.lock
index 1a523ef..1c44806 100644
--- a/deno.lock
+++ b/deno.lock
@@ -14,7 +14,6 @@
"npm:@sveltejs/vite-plugin-svelte@^6.1.1": "6.1.1_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0",
"npm:@tsconfig/svelte@^5.0.4": "5.0.4",
"npm:date-fns@^4.1.0": "4.1.0",
- "npm:sass-embedded@^1.91.0": "1.91.0",
"npm:svelte-check@^4.3.1": "4.3.1_svelte@5.38.1__acorn@8.15.0_typescript@5.8.3",
"npm:svelte-language-server@~0.17.19": "0.17.19_prettier@3.3.3_svelte@4.2.20_typescript@5.9.2",
"npm:svelte@^5.37.3": "5.38.1_acorn@8.15.0",
@@ -70,16 +69,10 @@
"@date-fns/utc@2.1.1": {
"integrity": "sha512-SlJDfG6RPeEX8wEVv6ZB3kak4MmbtyiI2qX/5zuKdordbrhB/iaJ58GVMZgJ6P1sJaM1gMgENFYYeg1JWrCFrA=="
},
- "@deno/vite-plugin@1.0.5_vite@7.1.2__picomatch@4.0.3": {
- "integrity": "sha512-tLja5n4dyMhcze1NzvSs2iiriBymfBlDCZIrjMTxb9O2ru0gvmV6mn5oBD2teNw5Sd92cj3YJzKwsAs8tMJXlg==",
- "dependencies": [
- "vite@7.1.2_picomatch@4.0.3"
- ]
- },
"@deno/vite-plugin@1.0.5_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0": {
"integrity": "sha512-tLja5n4dyMhcze1NzvSs2iiriBymfBlDCZIrjMTxb9O2ru0gvmV6mn5oBD2teNw5Sd92cj3YJzKwsAs8tMJXlg==",
"dependencies": [
- "vite@7.1.2_picomatch@4.0.3_sass-embedded@1.91.0"
+ "vite"
]
},
"@emmetio/abbreviation@2.3.3": {
@@ -97,261 +90,131 @@
"@emmetio/scanner@1.0.4": {
"integrity": "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA=="
},
- "@esbuild/aix-ppc64@0.25.8": {
- "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==",
- "os": ["aix"],
- "cpu": ["ppc64"]
- },
"@esbuild/aix-ppc64@0.25.9": {
"integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==",
"os": ["aix"],
"cpu": ["ppc64"]
},
- "@esbuild/android-arm64@0.25.8": {
- "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==",
- "os": ["android"],
- "cpu": ["arm64"]
- },
"@esbuild/android-arm64@0.25.9": {
"integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==",
"os": ["android"],
"cpu": ["arm64"]
},
- "@esbuild/android-arm@0.25.8": {
- "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==",
- "os": ["android"],
- "cpu": ["arm"]
- },
"@esbuild/android-arm@0.25.9": {
"integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==",
"os": ["android"],
"cpu": ["arm"]
},
- "@esbuild/android-x64@0.25.8": {
- "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==",
- "os": ["android"],
- "cpu": ["x64"]
- },
"@esbuild/android-x64@0.25.9": {
"integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==",
"os": ["android"],
"cpu": ["x64"]
},
- "@esbuild/darwin-arm64@0.25.8": {
- "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==",
- "os": ["darwin"],
- "cpu": ["arm64"]
- },
"@esbuild/darwin-arm64@0.25.9": {
"integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==",
"os": ["darwin"],
"cpu": ["arm64"]
},
- "@esbuild/darwin-x64@0.25.8": {
- "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==",
- "os": ["darwin"],
- "cpu": ["x64"]
- },
"@esbuild/darwin-x64@0.25.9": {
"integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==",
"os": ["darwin"],
"cpu": ["x64"]
},
- "@esbuild/freebsd-arm64@0.25.8": {
- "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==",
- "os": ["freebsd"],
- "cpu": ["arm64"]
- },
"@esbuild/freebsd-arm64@0.25.9": {
"integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==",
"os": ["freebsd"],
"cpu": ["arm64"]
},
- "@esbuild/freebsd-x64@0.25.8": {
- "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==",
- "os": ["freebsd"],
- "cpu": ["x64"]
- },
"@esbuild/freebsd-x64@0.25.9": {
"integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==",
"os": ["freebsd"],
"cpu": ["x64"]
},
- "@esbuild/linux-arm64@0.25.8": {
- "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==",
- "os": ["linux"],
- "cpu": ["arm64"]
- },
"@esbuild/linux-arm64@0.25.9": {
"integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==",
"os": ["linux"],
"cpu": ["arm64"]
},
- "@esbuild/linux-arm@0.25.8": {
- "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==",
- "os": ["linux"],
- "cpu": ["arm"]
- },
"@esbuild/linux-arm@0.25.9": {
"integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==",
"os": ["linux"],
"cpu": ["arm"]
},
- "@esbuild/linux-ia32@0.25.8": {
- "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==",
- "os": ["linux"],
- "cpu": ["ia32"]
- },
"@esbuild/linux-ia32@0.25.9": {
"integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==",
"os": ["linux"],
"cpu": ["ia32"]
},
- "@esbuild/linux-loong64@0.25.8": {
- "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==",
- "os": ["linux"],
- "cpu": ["loong64"]
- },
"@esbuild/linux-loong64@0.25.9": {
"integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==",
"os": ["linux"],
"cpu": ["loong64"]
},
- "@esbuild/linux-mips64el@0.25.8": {
- "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==",
- "os": ["linux"],
- "cpu": ["mips64el"]
- },
"@esbuild/linux-mips64el@0.25.9": {
"integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==",
"os": ["linux"],
"cpu": ["mips64el"]
},
- "@esbuild/linux-ppc64@0.25.8": {
- "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==",
- "os": ["linux"],
- "cpu": ["ppc64"]
- },
"@esbuild/linux-ppc64@0.25.9": {
"integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==",
"os": ["linux"],
"cpu": ["ppc64"]
},
- "@esbuild/linux-riscv64@0.25.8": {
- "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==",
- "os": ["linux"],
- "cpu": ["riscv64"]
- },
"@esbuild/linux-riscv64@0.25.9": {
"integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==",
"os": ["linux"],
"cpu": ["riscv64"]
},
- "@esbuild/linux-s390x@0.25.8": {
- "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==",
- "os": ["linux"],
- "cpu": ["s390x"]
- },
"@esbuild/linux-s390x@0.25.9": {
"integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==",
"os": ["linux"],
"cpu": ["s390x"]
},
- "@esbuild/linux-x64@0.25.8": {
- "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==",
- "os": ["linux"],
- "cpu": ["x64"]
- },
"@esbuild/linux-x64@0.25.9": {
"integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==",
"os": ["linux"],
"cpu": ["x64"]
},
- "@esbuild/netbsd-arm64@0.25.8": {
- "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==",
- "os": ["netbsd"],
- "cpu": ["arm64"]
- },
"@esbuild/netbsd-arm64@0.25.9": {
"integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==",
"os": ["netbsd"],
"cpu": ["arm64"]
},
- "@esbuild/netbsd-x64@0.25.8": {
- "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==",
- "os": ["netbsd"],
- "cpu": ["x64"]
- },
"@esbuild/netbsd-x64@0.25.9": {
"integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==",
"os": ["netbsd"],
"cpu": ["x64"]
},
- "@esbuild/openbsd-arm64@0.25.8": {
- "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==",
- "os": ["openbsd"],
- "cpu": ["arm64"]
- },
"@esbuild/openbsd-arm64@0.25.9": {
"integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==",
"os": ["openbsd"],
"cpu": ["arm64"]
},
- "@esbuild/openbsd-x64@0.25.8": {
- "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==",
- "os": ["openbsd"],
- "cpu": ["x64"]
- },
"@esbuild/openbsd-x64@0.25.9": {
"integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==",
"os": ["openbsd"],
"cpu": ["x64"]
},
- "@esbuild/openharmony-arm64@0.25.8": {
- "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==",
- "os": ["openharmony"],
- "cpu": ["arm64"]
- },
"@esbuild/openharmony-arm64@0.25.9": {
"integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==",
"os": ["openharmony"],
"cpu": ["arm64"]
},
- "@esbuild/sunos-x64@0.25.8": {
- "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==",
- "os": ["sunos"],
- "cpu": ["x64"]
- },
"@esbuild/sunos-x64@0.25.9": {
"integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==",
"os": ["sunos"],
"cpu": ["x64"]
},
- "@esbuild/win32-arm64@0.25.8": {
- "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==",
- "os": ["win32"],
- "cpu": ["arm64"]
- },
"@esbuild/win32-arm64@0.25.9": {
"integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==",
"os": ["win32"],
"cpu": ["arm64"]
},
- "@esbuild/win32-ia32@0.25.8": {
- "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==",
- "os": ["win32"],
- "cpu": ["ia32"]
- },
"@esbuild/win32-ia32@0.25.9": {
"integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==",
"os": ["win32"],
"cpu": ["ia32"]
},
- "@esbuild/win32-x64@0.25.8": {
- "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==",
- "os": ["win32"],
- "cpu": ["x64"]
- },
"@esbuild/win32-x64@0.25.9": {
"integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==",
"os": ["win32"],
@@ -580,48 +443,26 @@
"acorn"
]
},
- "@sveltejs/vite-plugin-svelte-inspector@5.0.0_@sveltejs+vite-plugin-svelte@6.1.1__svelte@5.38.1___acorn@8.15.0__vite@7.1.2___picomatch@4.0.3_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3": {
- "integrity": "sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==",
- "dependencies": [
- "@sveltejs/vite-plugin-svelte@6.1.1_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3",
- "debug",
- "svelte@5.38.1_acorn@8.15.0",
- "vite@7.1.2_picomatch@4.0.3"
- ]
- },
"@sveltejs/vite-plugin-svelte-inspector@5.0.0_@sveltejs+vite-plugin-svelte@6.1.1__svelte@5.38.1___acorn@8.15.0__vite@7.1.2___picomatch@4.0.3_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0": {
"integrity": "sha512-iwQ8Z4ET6ZFSt/gC+tVfcsSBHwsqc6RumSaiLUkAurW3BCpJam65cmHw0oOlDMTO0u+PZi9hilBRYN+LZNHTUQ==",
"dependencies": [
- "@sveltejs/vite-plugin-svelte@6.1.1_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0",
+ "@sveltejs/vite-plugin-svelte",
"debug",
"svelte@5.38.1_acorn@8.15.0",
- "vite@7.1.2_picomatch@4.0.3_sass-embedded@1.91.0"
- ]
- },
- "@sveltejs/vite-plugin-svelte@6.1.1_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3": {
- "integrity": "sha512-vB0Vq47Js7C11L2JrwhncIAoDNkdKDPI500SjLSb34X48dDcsSH5JpLl0cHT0sfO997BrzAS6PKjiZEey/S0VQ==",
- "dependencies": [
- "@sveltejs/vite-plugin-svelte-inspector@5.0.0_@sveltejs+vite-plugin-svelte@6.1.1__svelte@5.38.1___acorn@8.15.0__vite@7.1.2___picomatch@4.0.3_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3",
- "debug",
- "deepmerge",
- "kleur",
- "magic-string",
- "svelte@5.38.1_acorn@8.15.0",
- "vite@7.1.2_picomatch@4.0.3",
- "vitefu@1.1.1_vite@7.1.2__picomatch@4.0.3"
+ "vite"
]
},
"@sveltejs/vite-plugin-svelte@6.1.1_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0": {
"integrity": "sha512-vB0Vq47Js7C11L2JrwhncIAoDNkdKDPI500SjLSb34X48dDcsSH5JpLl0cHT0sfO997BrzAS6PKjiZEey/S0VQ==",
"dependencies": [
- "@sveltejs/vite-plugin-svelte-inspector@5.0.0_@sveltejs+vite-plugin-svelte@6.1.1__svelte@5.38.1___acorn@8.15.0__vite@7.1.2___picomatch@4.0.3_svelte@5.38.1__acorn@8.15.0_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0",
+ "@sveltejs/vite-plugin-svelte-inspector",
"debug",
"deepmerge",
"kleur",
"magic-string",
"svelte@5.38.1_acorn@8.15.0",
- "vite@7.1.2_picomatch@4.0.3_sass-embedded@1.91.0",
- "vitefu@1.1.1_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0"
+ "vite",
+ "vitefu"
]
},
"@tsconfig/svelte@5.0.4": {
@@ -721,32 +562,32 @@
"esbuild@0.25.9": {
"integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==",
"optionalDependencies": [
- "@esbuild/aix-ppc64@0.25.9",
- "@esbuild/android-arm@0.25.9",
- "@esbuild/android-arm64@0.25.9",
- "@esbuild/android-x64@0.25.9",
- "@esbuild/darwin-arm64@0.25.9",
- "@esbuild/darwin-x64@0.25.9",
- "@esbuild/freebsd-arm64@0.25.9",
- "@esbuild/freebsd-x64@0.25.9",
- "@esbuild/linux-arm@0.25.9",
- "@esbuild/linux-arm64@0.25.9",
- "@esbuild/linux-ia32@0.25.9",
- "@esbuild/linux-loong64@0.25.9",
- "@esbuild/linux-mips64el@0.25.9",
- "@esbuild/linux-ppc64@0.25.9",
- "@esbuild/linux-riscv64@0.25.9",
- "@esbuild/linux-s390x@0.25.9",
- "@esbuild/linux-x64@0.25.9",
- "@esbuild/netbsd-arm64@0.25.9",
- "@esbuild/netbsd-x64@0.25.9",
- "@esbuild/openbsd-arm64@0.25.9",
- "@esbuild/openbsd-x64@0.25.9",
- "@esbuild/openharmony-arm64@0.25.9",
- "@esbuild/sunos-x64@0.25.9",
- "@esbuild/win32-arm64@0.25.9",
- "@esbuild/win32-ia32@0.25.9",
- "@esbuild/win32-x64@0.25.9"
+ "@esbuild/aix-ppc64",
+ "@esbuild/android-arm",
+ "@esbuild/android-arm64",
+ "@esbuild/android-x64",
+ "@esbuild/darwin-arm64",
+ "@esbuild/darwin-x64",
+ "@esbuild/freebsd-arm64",
+ "@esbuild/freebsd-x64",
+ "@esbuild/linux-arm",
+ "@esbuild/linux-arm64",
+ "@esbuild/linux-ia32",
+ "@esbuild/linux-loong64",
+ "@esbuild/linux-mips64el",
+ "@esbuild/linux-ppc64",
+ "@esbuild/linux-riscv64",
+ "@esbuild/linux-s390x",
+ "@esbuild/linux-x64",
+ "@esbuild/netbsd-arm64",
+ "@esbuild/netbsd-x64",
+ "@esbuild/openbsd-arm64",
+ "@esbuild/openbsd-x64",
+ "@esbuild/openharmony-arm64",
+ "@esbuild/sunos-x64",
+ "@esbuild/win32-arm64",
+ "@esbuild/win32-ia32",
+ "@esbuild/win32-x64"
],
"scripts": true,
"bin": true
@@ -1242,21 +1083,6 @@
"varint@6.0.0": {
"integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg=="
},
- "vite@7.1.2_picomatch@4.0.3": {
- "integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==",
- "dependencies": [
- "esbuild",
- "fdir",
- "picomatch@4.0.3",
- "postcss",
- "rollup",
- "tinyglobby"
- ],
- "optionalDependencies": [
- "fsevents"
- ],
- "bin": true
- },
"vite@7.1.2_picomatch@4.0.3_sass-embedded@1.91.0": {
"integrity": "sha512-J0SQBPlQiEXAF7tajiH+rUooJPo0l8KQgyg4/aMunNtrOa7bwuZJsJbDWzeljqQpgftxuq5yNJxQ91O9ts29UQ==",
"dependencies": [
@@ -1276,22 +1102,13 @@
],
"bin": true
},
- "vitefu@1.1.1_vite@7.1.2__picomatch@4.0.3": {
- "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==",
- "dependencies": [
- "vite@7.1.2_picomatch@4.0.3"
- ],
- "optionalPeers": [
- "vite@7.1.2_picomatch@4.0.3"
- ]
- },
"vitefu@1.1.1_vite@7.1.2__picomatch@4.0.3_sass-embedded@1.91.0": {
"integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==",
"dependencies": [
- "vite@7.1.2_picomatch@4.0.3_sass-embedded@1.91.0"
+ "vite"
],
"optionalPeers": [
- "vite@7.1.2_picomatch@4.0.3_sass-embedded@1.91.0"
+ "vite"
]
},
"vscode-css-languageservice@6.3.7": {
@@ -1364,7 +1181,6 @@
"npm:@sveltejs/vite-plugin-svelte@^6.1.1",
"npm:@tsconfig/svelte@^5.0.4",
"npm:date-fns@^4.1.0",
- "npm:sass-embedded@^1.91.0",
"npm:svelte-check@^4.3.1",
"npm:svelte-language-server@~0.17.19",
"npm:svelte@^5.37.3",
diff --git a/mise.toml b/mise.toml
index 6a3bf11..650f1a1 100644
--- a/mise.toml
+++ b/mise.toml
@@ -3,7 +3,6 @@ deno = "latest"
rebar = "latest"
rust = { version = "nightly", components = "rust-analyzer,clippy,rustc-codegen-cranelift-preview" }
watchexec = "latest"
-"github:sass/dart-sass" = "1.89.2"
"cargo:sqlx-cli" = "0.8.6"
[tasks.dev-services]
@@ -20,10 +19,6 @@ run = "deno run -A npm:vite build"
dir = "./svelte"
sources = ["**/*.svelte.ts", "**/*.svelte"]
-[tasks.build-css]
-run = "sass sass/:css_dist/"
-sources = ["**/*.scss"]
-
[tasks.docker-services]
dir = "./dev-services"
run = "docker compose up"
diff --git a/package.json b/package.json
index 41ca75b..f408c25 100644
--- a/package.json
+++ b/package.json
@@ -15,7 +15,6 @@
"@deno/vite-plugin": "^1.0.5",
"@sveltejs/vite-plugin-svelte": "^6.1.1",
"date-fns": "^4.1.0",
- "sass-embedded": "^1.91.0",
"svelte-language-server": "^0.17.19",
"uuid": "^11.1.0",
"vite": "^7.1.1",
diff --git a/phono-server/src/routes/mod.rs b/phono-server/src/routes/mod.rs
index 8e057e3..d558d7f 100644
--- a/phono-server/src/routes/mod.rs
+++ b/phono-server/src/routes/mod.rs
@@ -71,31 +71,6 @@ pub(crate) fn new_router(app: App) -> Router<()> {
),
),
)
- .nest_service(
- "/css_dist",
- ServiceBuilder::new()
- .layer(SetResponseHeaderLayer::if_not_present(
- CACHE_CONTROL,
- HeaderValue::from_static(if cfg!(debug_assertions) {
- // Disable caching when developing locally.
- "no-cache"
- } else {
- "max-age=120, stale-while-revalidate=86400"
- }),
- ))
- .service(
- ServeDir::new("css_dist").not_found_service(
- ServiceBuilder::new()
- .layer(SetResponseHeaderLayer::if_not_present(
- CACHE_CONTROL,
- // Do not allow caching of paths if they return
- // a 404 error.
- HeaderValue::from_static("no-cache"),
- ))
- .service(ServeFile::new("static/_404.html")),
- ),
- ),
- )
.fallback_service(
ServiceBuilder::new()
.layer(SetResponseHeaderLayer::if_not_present(
diff --git a/phono-server/templates/base.html b/phono-server/templates/base.html
index 9270b28..00b1b9a 100644
--- a/phono-server/templates/base.html
+++ b/phono-server/templates/base.html
@@ -3,7 +3,9 @@
{% block title %}Phonograph{% endblock %}
{% include "meta_tags.html" %}
-
+
+
+
{%- block head_extras %}{% endblock -%}
diff --git a/phono-server/templates/portal_table.html b/phono-server/templates/portal_table.html
index 8375225..7c629cc 100644
--- a/phono-server/templates/portal_table.html
+++ b/phono-server/templates/portal_table.html
@@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block head_extras %}
-
+
{% endblock %}
@@ -10,7 +10,7 @@
-
+
Portal Settings
- {{ self.relname }}
-
- {%- match self.kind -%}
- {%- when RelPermissionKind::Owner -%}
- owner
- {%- when RelPermissionKind::Reader -%}
- reader
- {%- when RelPermissionKind::Writer -%}
- writer
- {%- endmatch -%}
+
+
{{ self.kind }} of {{ self.relname }}
+
{{ self.relname }}
+
+ {{ self.kind }}
diff --git a/phono-server/templates/relations_single/portal_settings.html b/phono-server/templates/relations_single/portal_settings.html
index 7e0f225..05a6559 100644
--- a/phono-server/templates/relations_single/portal_settings.html
+++ b/phono-server/templates/relations_single/portal_settings.html
@@ -5,7 +5,7 @@
-
+
-
diff --git a/phono-server/templates/workspace_nav.html b/phono-server/templates/workspace_nav.html
index 9bf3abb..8ef9bc9 100644
--- a/phono-server/templates/workspace_nav.html
+++ b/phono-server/templates/workspace_nav.html
@@ -47,28 +47,23 @@
method="post"
>
-
diff --git a/phono-server/templates/workspaces_single/permissions_editor.html b/phono-server/templates/workspaces_single/permissions_editor.html
index dd628b5..7ac9bd4 100644
--- a/phono-server/templates/workspaces_single/permissions_editor.html
+++ b/phono-server/templates/workspaces_single/permissions_editor.html
@@ -1,16 +1,18 @@
-{% for perm in current_perms.clone() %}
-{{ perm | safe }}
-{% endfor %}
-
- Edit
-
+
+ {% for perm in current_perms.clone() %}
+ {{ perm | safe }}
+ {% endfor %}
+
+ Edit
+
+
-
+
diff --git a/phono-server/templates/workspaces_single/settings.html b/phono-server/templates/workspaces_single/settings.html
index a4a7c1e..4f2e0bb 100644
--- a/phono-server/templates/workspaces_single/settings.html
+++ b/phono-server/templates/workspaces_single/settings.html
@@ -10,21 +10,35 @@
{{ workspace_nav | safe }}
-
+
Sharing
-
- Invite
-
+
+
+ Invite
+
+
-
+
| Email |
@@ -63,7 +77,7 @@
{% for permissions_editor in collaborators %}
{% let collaborator = User::try_from(permissions_editor.target.clone())? %}
- | {{ collaborator.email }} |
+ {{ collaborator.email }} |
{{ permissions_editor | safe }}
|
@@ -80,7 +94,9 @@
{% endfor %}
- Save
+
+ Save
+
diff --git a/sass/_basic-dropdown.scss b/sass/_basic-dropdown.scss
deleted file mode 100644
index dd3345f..0000000
--- a/sass/_basic-dropdown.scss
+++ /dev/null
@@ -1,40 +0,0 @@
-@use 'globals';
-
-.basic-dropdown {
- &__button {
- anchor-name: --anchor-button;
- }
-
- &__popover {
- &:popover-open {
- @include globals.popover;
-
- padding: 0;
- position: absolute;
- position-anchor: --anchor-button;
- top: anchor(bottom);
- }
- }
-
- &__menu {
- list-style-type: none;
- margin: 0;
- padding: 8px 0;
-
- & > li {
- padding: 0;
-
- &:hover {
- background: #0001;
- }
-
- & > button, & > [role="button"] {
- @include globals.reset-button;
- @include globals.reset-anchor;
-
- display: block;
- padding: 8px 16px;
- }
- }
- }
-}
diff --git a/sass/_field-adder.scss b/sass/_field-adder.scss
deleted file mode 100644
index 0dc19af..0000000
--- a/sass/_field-adder.scss
+++ /dev/null
@@ -1,30 +0,0 @@
-@use 'globals';
-@use 'viewer-shared';
-
-.field-adder {
- &__container {
- align-items: stretch;
- display: flex;
- }
-
- &__header-lookalike {
- @include viewer-shared.th;
- border-bottom-style: dashed;
- border-right-style: dashed;
- }
-
- &__label-input {
- @include globals.reset-input;
- }
-
- &__popover:popover-open {
- @include globals.popover;
- padding: 1rem;
- }
-
- &__summary-buttons {
- align-items: center;
- display: flex;
- }
-}
-
diff --git a/sass/_forms.scss b/sass/_forms.scss
deleted file mode 100644
index fdc8c6c..0000000
--- a/sass/_forms.scss
+++ /dev/null
@@ -1,57 +0,0 @@
-@use 'globals';
-
-$section-gap: 1.5rem;
-$label-gap: 0.5rem;
-$button-gap: 0.25rem;
-
-.form-section {
- &__heading {
- margin: 0;
- font-size: 1rem;
- font-weight: 700;
- }
-
- &__label {
- display: block;
- font-weight: 600;
- margin-top: $section-gap;
- }
-
- &__input {
- display: block;
- margin-top: $label-gap;
- font-family: globals.$font-family-data;
-
- &--text {
- @include globals.rounded;
- border: globals.$default-border;
- padding: 0.5rem;
- }
- }
-}
-
-.form-buttons {
- display: flex;
- margin-top: $section-gap;
- justify-content: flex-end;
-
- &__button {
- margin: 0 $button-gap;
-
- &:first-child {
- margin-left: 0;
- }
-
- &:last-child {
- margin-right: 0;
- }
-
- &--cancel {
- @include globals.button-clear;
- }
-
- &--submit {
- @include globals.button-primary;
- }
- }
-}
diff --git a/sass/_globals.scss b/sass/_globals.scss
deleted file mode 100644
index 914d636..0000000
--- a/sass/_globals.scss
+++ /dev/null
@@ -1,153 +0,0 @@
-@use 'sass:color';
-
-$button-primary-background: #fc0;
-$button-primary-color: #000;
-$button-shadow: 0 0.15rem 0.15rem #3331;
-$default-border-color: #ccc;
-$default-border: solid 1px $default-border-color;
-$font-family-default: 'Funnel Sans', 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
-$font-family-data: Menlo, 'Courier New', 'Open Sans', 'Helvetica Neue', Arial, sans-serif;
-$font-family-mono: Menlo, 'Courier New', Courier, mono;
-$popover-border: $default-border;
-$popover-shadow: 0 0.5rem 0.5rem #3333;
-$border-radius-rounded-sm: 0.25rem;
-$border-radius-rounded: 0.5rem;
-$link-color: #069;
-$notice-color-info: #39d;
-$hover-lightness-scale-factor: -5%;
-
-@mixin reset-button {
- appearance: none;
- background: none;
- border: none;
- padding: 0;
- box-sizing: border-box;
- cursor: pointer;
- font-family: inherit;
- font-size: inherit;
- font-weight: inherit;
-}
-
-@mixin button-base {
- @include reset-button;
- @include rounded;
-
- box-shadow: $button-shadow;
- font-family: $font-family-mono;
- font-weight: 500;
- padding: 0.5rem 1rem;
- transition: background 0.2s ease;
-}
-
-@mixin button-primary {
- @include button-base;
-
- background: $button-primary-background;
- border: solid 1px color.scale(
- $button-primary-background,
- $lightness: -5%,
- $space: oklch
- );
- color: $button-primary-color;
-
- &:hover {
- background: color.scale(
- $button-primary-background,
- $lightness: $hover-lightness-scale-factor,
- $space: oklch
- );
- border-color: color.scale(
- $button-primary-background,
- $lightness: -10%,
- $space: oklch
- );
- }
-}
-
-@mixin button-outline {
- @include button-base;
-
- background: $button-primary-color;
- border: solid 1px color.scale(
- $button-primary-background,
- $lightness: -5%,
- $space: oklch
- );
- color: $button-primary-background;
-
- &:hover {
- border-color: color.scale(
- $button-primary-background,
- $lightness: -10%,
- $space: oklch
- );
- }
-}
-
-@mixin button-secondary {
- @include button-base;
-
- background: #fff;
- color: #000;
- border: $default-border;
-
- &:hover {
- border-color: color.scale(
- $default-border-color,
- $lightness: $hover-lightness-scale-factor,
- $space: oklch
- );
- }
-}
-
-@mixin button-clear {
- @include button-base;
-
- box-shadow: none;
-
- &:hover {
- background: #0000001f;
- }
-}
-
-@mixin button-small {
- padding: 4px 8px;
- font-size: 0.9rem;
-}
-
-@mixin reset-input {
- appearance: none;
- background: none;
- border: none;
- box-sizing: border-box;
- font-family: inherit;
- font-size: inherit;
- font-weight: inherit;
- outline: none;
-}
-
-@mixin reset-anchor {
- color: inherit;
- text-decoration: none;
-}
-
-@mixin rounded-sm {
- border-radius: $border-radius-rounded-sm;
-}
-
-@mixin rounded {
- border-radius: $border-radius-rounded;
-}
-
-@mixin popover {
- @include rounded;
- inset: unset;
- border: $popover-border;
- margin: 0;
- margin-top: 4px;
- padding: 0;
- position: relative;
- display: block;
- background: #fff;
- box-shadow: $popover-shadow;
-}
diff --git a/sass/_hoverbar.scss b/sass/_hoverbar.scss
deleted file mode 100644
index d7b3a43..0000000
--- a/sass/_hoverbar.scss
+++ /dev/null
@@ -1,121 +0,0 @@
-@use 'globals';
-
-$background-color: #fff;
-$tab-button-color-active: #0001;
-
-.container-positioner {
- position: fixed;
- bottom: 2rem;
- display: flex;
- justify-content: center;
- align-items: flex-end;
- overflow: visible;
- width: 100%;
- height: 0;
-}
-
-.container {
- display: grid;
- grid-template-columns: max-content max-content 1rem max-content;
- filter: drop-shadow(globals.$popover-shadow);
-}
-
-.tab-box {
- @include globals.rounded;
- height: 3rem;
- display: flex;
- align-items: center;
- list-style-type: none;
- padding: 0.5rem;
- margin: 0;
- border: globals.$popover-border;
- border-right: none;
- border-top-right-radius: 0;
- border-bottom-right-radius: 0;
- background: $background-color;
- grid-row: 2;
-
- &__button {
- @include globals.reset-button;
- @include globals.rounded-sm;
- display: flex;
- align-items: center;
- padding: 0.25rem 0.5rem;
- cursor: pointer;
- height: 2rem;
-
- &--active {
- background: $tab-button-color-active;
- }
- }
-}
-
-.control-bar {
- @include globals.rounded;
- height: 3rem;
- flex-shrink: 0;
- border: globals.$popover-border;
- border-top-left-radius: 0;
- border-bottom-left-radius: 0;
- overflow: hidden;
- width: 40rem;
- grid-row: 2;
- background: $background-color;
-
- &--open {
- border-top-right-radius: 0;
- }
-}
-
-.control-buttons {
- height: 3rem;
- gird-row: 2;
- grid-column: 4;
- height: 100%;
-}
-
-.control-panel-positioner {
- grid-template-columns: subgrid;
- grid-column: 2;
- grid-row: 1;
- position: relative;
- overflow: visible;
- /* Flexbox positioning is required for Safari */
- display: flex;
- align-items: flex-end;
- anchor-name: --control-bar;
-}
-
-.control-panel__container:popover-open {
- @include globals.rounded;
- inset: unset;
- border: globals.$popover-border;
- border-bottom: none;
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- margin: 0;
- position: fixed;
- display: block;
- width: 40rem;
- /* Anchor positioning is required for Chromium */
- position-anchor: --control-bar;
- position-area: top;
- padding: 0;
- background: $background-color;
- box-shadow: globals.$popover-shadow;
- /* Clip drop shadow */
- clip-path: polygon(
- -100% -100%,
- 200% -100%,
- 200% 200%,
- 100% 200%,
- 100% 100%,
- -100% 100%
- );
-}
-
-.control-panel {
- padding: 0.5rem;
- overflow: auto;
- max-height: 8rem;
-}
diff --git a/sass/_viewer-shared.scss b/sass/_viewer-shared.scss
deleted file mode 100644
index 52fdba9..0000000
--- a/sass/_viewer-shared.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-@use 'globals';
-
-@mixin th {
- border: globals.$default-border;
- border-top: none;
- font-family: 'Funnel Sans';
- font-weight: bolder;
- background: #0001;
- height: 100%; /* css hack to make percentage based cell heights work */
- padding: 0.25rem 0.5rem;
- text-align: left;
-
- &:first-child {
- border-left: none;
- }
-}
diff --git a/sass/cells.scss b/sass/cells.scss
deleted file mode 100644
index 4e81076..0000000
--- a/sass/cells.scss
+++ /dev/null
@@ -1,34 +0,0 @@
-@use 'globals';
-
-.cell__container {
- display: block;
- width: 100%;
- height: 100%;
- border: solid 2px transparent;
-
- &--selected {
- border-color: #07f;
- }
-}
-
-.cell__content {
- font-family: globals.$font-family-data;
- max-width: 100%;
-
- &--padded {
- padding: 0.25rem;
- }
-
- &--null {
- opacity: 0.5;
- font-style: oblique;
- text-align: center;
- }
-
- &--uuid {
- font-family: globals.$font-family-mono;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-}
diff --git a/sass/collapsible_menu.scss b/sass/collapsible_menu.scss
deleted file mode 100644
index 64fdf90..0000000
--- a/sass/collapsible_menu.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-@use 'globals';
-
-.collapsible-menu {
- &__summary {
- @include globals.reset-button;
- }
-
- &__content {
- overflow: hidden;
- max-height: 0;
- transition: max-height 0.3s ease-in;
- padding-left: 0.5rem;
-
- &--expanded {
- // todo: adjust max-height dynamically based on content
- max-height: 40rem;
- transition: max-height 0.3s ease-out;
- }
- }
-}
diff --git a/sass/condition-editor.scss b/sass/condition-editor.scss
deleted file mode 100644
index c1c5400..0000000
--- a/sass/condition-editor.scss
+++ /dev/null
@@ -1,93 +0,0 @@
-@use 'sass:color';
-@use 'globals';
-
-.expression-editor {
- &__container {
- @include globals.rounded;
- background: #eee;
- display: flex;
- }
-
- &__sidebar {
- display: grid;
- grid-template:
- 'padding-top' 1fr
- 'operator-selector' max-content
- 'actions' minmax(max-content, 1fr);
- }
-
- &__main {
- @include globals.rounded;
- background: #fff;
- border: globals.$default-border;
- flex: 1;
- padding: 0.5rem;
- }
-
- &__action-button {
- padding: 0.5rem;
-
- svg path {
- fill: currentColor;
- }
- }
-
- &__params {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- }
-}
-
-.expression-selector {
- &__container {
- grid-area: operator-selector;
- }
-
- &__expression-button {
- @include globals.button-clear;
- align-items: center;
- display: flex;
- justify-content: center;
- height: 2.5rem;
- padding: 0;
- width: 2.5rem;
-
- svg path {
- fill: currentColor;
- }
- }
-
- &__popover {
- &:popover-open {
- @include globals.rounded;
- inset: unset;
- top: anchor(bottom);
- border: globals.$popover-border;
- margin: 0;
- margin-top: 0.25rem;
- position: absolute;
- display: flex;
- flex-direction: column;
- padding: 0;
- background: #fff;
- box-shadow: globals.$popover-shadow;
- }
- }
-
- &__section {
- align-items: center;
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- justify-content: center;
- list-style-type: none;
- margin: 1rem;
- padding: 0;
- }
-
- &__li {
- align-items: center;
- display: flex;
- justify-content: center;
- }
-}
diff --git a/sass/field_adder/index.scss b/sass/field_adder/index.scss
deleted file mode 100644
index 0f39907..0000000
--- a/sass/field_adder/index.scss
+++ /dev/null
@@ -1,48 +0,0 @@
-@use '../globals';
-@use '../forms';
-@use '../viewer-shared';
-
-:host {
- height: 100%;
-}
-
-.expander__button {
- @include globals.reset-button;
- width: 100%;
- height: 100%;
-}
-
-.header {
- @include viewer-shared.th;
- border-right-style: dashed;
- border-bottom-style: dashed;
- border-left: none;
- display: flex;
-
- &__input {
- appearance: none;
- background: none;
- border: none;
- outline: none;
- font-weight: inherit;
- }
-}
-
-.config-popover {
- &__container {
- @include globals.rounded;
- font-family: globals.$font-family-default;
- position: fixed;
- inset: unset;
- margin: 0;
- width: 20rem;
- padding: 1rem;
- font-weight: normal;
- border: globals.$popover-border;
- filter: drop-shadow(globals.$popover-shadow);
-
- &:popover-open {
- display: block;
- }
- }
-}
diff --git a/sass/form.scss b/sass/form.scss
deleted file mode 100644
index c28ef94..0000000
--- a/sass/form.scss
+++ /dev/null
@@ -1,10 +0,0 @@
-@use 'globals';
-
-.phono-form{
- &__container {
- margin: 0 auto;
- max-width: 48rem;
- padding: 2rem;
- position: relative;
- }
-}
diff --git a/sass/main.scss b/sass/main.scss
deleted file mode 100644
index 0fbe848..0000000
--- a/sass/main.scss
+++ /dev/null
@@ -1,212 +0,0 @@
-@use 'sass:color';
-
-@use 'basic-dropdown';
-@use 'globals';
-@use 'modern-normalize';
-@use 'forms';
-@use 'collapsible_menu';
-@use 'condition-editor';
-@use 'tabler-icons' with (
- $ti-font-path: '../tabler-icons/webfont/fonts'
-);
-@use 'workspace-nav';
-
-html {
- font-family: globals.$font-family-default;
-}
-
-button, input[type="submit"] {
- @include globals.reset-button;
-}
-
-@font-face {
- font-family: "Averia Serif Libre";
- src: url("../averia_serif_libre/averia_serif_libre_regular.ttf");
-}
-
-@font-face {
- font-family: "Averia Serif Libre";
- src: url("../averia_serif_libre/averia_serif_libre_bold.ttf");
- font-weight: 700;
-}
-
-@font-face {
- font-family: "Averia Serif Libre";
- src: url("../averia_serif_libre/averia_serif_libre_light.ttf");
- font-weight: 300;
-}
-
-@font-face {
- font-family: "Funnel Sans";
- src: url("../funnel_sans/funnel_sans_variable.ttf");
-}
-
-@view-transitions {
- navigation: auto;
-}
-
-// https://css-tricks.com/inclusively-hidden/
-.sr-only:not(:focus):not(:active) {
- clip: rect(0 0 0 0);
- clip-path: inset(50%);
- height: 1px;
- overflow: hidden;
- position: absolute;
- white-space: nowrap;
- width: 1px;
-}
-
-.button {
- &--primary {
- @include globals.reset-anchor;
- @include globals.button-primary;
- }
-
- &--secondary {
- @include globals.reset-anchor;
- @include globals.button-secondary;
- }
-
- &--clear {
- @include globals.reset-anchor;
- @include globals.button-clear;
- }
-
- &--small {
- @include globals.reset-anchor;
- @include globals.button-small;
- }
-}
-
-.padded {
- padding: 8px;
-
- &--lg {
- padding: 32px;
- }
-}
-
-.page-grid {
- height: 100vh;
- width: 100vw;
- display: grid;
- grid-template:
- 'sidebar toolbar' 4rem
- 'sidebar main' 1fr / max-content 1fr;
-
- &__toolbar {
- align-items: center;
- border-bottom: globals.$default-border;
- display: grid;
- grid-area: toolbar;
- grid-template:
- 'utilities user' 1fr / 1fr max-content;
- }
-
- &__toolbar-utilities {
- align-items: center;
- display: flex;
- gap: 12px;
- grid-area: utilities;
- justify-content: flex-start;
- padding: 0 12px;
- }
-
- &__toolbar-user {
- align-items: center;
- display: flex;
- gap: 12px;
- grid-area: user;
- justify-content: flex-end;
- padding: 0 12px;
- }
-
- &__sidebar {
- grid-area: sidebar;
- width: 15rem;
- max-height: 100vh;
- overflow: auto;
- border-right: globals.$default-border;
- }
-
- &__main {
- grid-area: main;
- overflow: auto;
- }
-}
-
-.toolbar-item {
- flex: 0;
-}
-
-.section {
- padding: 1rem 2rem;
-}
-
-.notice {
- @include globals.rounded;
- margin: 1rem 0rem;
- padding: 1rem;
- max-width: 40rem;
-
- &--info {
- border: solid 1px globals.$notice-color-info;
- background: color.scale(globals.$notice-color-info, $lightness: 90%, $space: hsl);
- color: color.scale(globals.$notice-color-info, $lightness: -80%, $space: hsl);
- }
-}
-
-.role-tree {
- font-family: globals.$font-family-data;
-
- &--no-inherit {
- opacity: 0.6;
- font-style: italic;
- }
-
- &__branches {
- border-left: solid 1px #000;
- list-style-type: none;
- margin: 0;
- margin-top: 0.25rem;
- padding: 0;
- }
-
- &__branch {
- padding-top: 0.25rem;
- padding-left: 1rem;
- }
-}
-
-.table {
- border-collapse: collapse;
-
- th, td {
- border: globals.$default-border;
- padding: 8px;
- }
-
- th {
- background: #eee;
- }
-
- &__message {
- opacity: 0.5;
- text-align: center;
- }
-}
-
-.phono-popover:popover-open {
- @include globals.popover;
-}
-
-.dialog:popover-open, .dialog:open {
- @include globals.rounded;
-
- background: #fff;
- border: globals.$popover-border;
- box-shadow: globals.$popover-shadow;
- display: block;
- max-height: 90vh;
- overflow: auto;
-}
diff --git a/sass/tabler-icons.scss b/sass/tabler-icons.scss
deleted file mode 120000
index a07b2f8..0000000
--- a/sass/tabler-icons.scss
+++ /dev/null
@@ -1 +0,0 @@
-../static/tabler-icons/webfont/tabler-icons.scss
\ No newline at end of file
diff --git a/sass/viewer.scss b/sass/viewer.scss
deleted file mode 100644
index 995bef4..0000000
--- a/sass/viewer.scss
+++ /dev/null
@@ -1,384 +0,0 @@
-@use 'globals';
-@use 'sass:color';
-@use 'condition-editor';
-@use 'field-adder';
-
-$table-border-color: #ccc;
-
-.lens-grid {
- display: grid;
- grid-template:
- 'table' 1fr
- 'editor' max-content;
- height: 100%;
- width: 100%;
-}
-
-.lens-table {
- display: grid;
- grid-area: table;
- grid-template:
- 'headers' max-content
- 'main' 1fr
- 'inserter' max-content;
- height: 100%;
- outline: none;
- overflow: auto;
- width: 100%;
-
- &__headers {
- align-items: stretch;
- display: flex;
- grid-area: headers;
- // Ensure that there will be enough space on the right for popovers to
- // render without overflowing the container.
- padding-right: 480px;
- }
-
- &__main {
- grid-area: main;
- overflow-y: auto;
- }
-
- &__row {
- align-items: stretch;
- display: flex;
- height: 2.25rem;
- }
-}
-
-.lens-cell {
- align-items: stretch;
- border: solid 1px $table-border-color;
- border-left: none;
- border-top: none;
- display: flex;
- flex: none;
- padding: 0;
-
- &:focus {
- outline: none;
- }
-
- &--insertable {
- border-style: dashed;
- }
-
- &__container {
- align-items: center;
- display: flex;
- flex: none;
- user-select: none;
- width: 100%;
-
- &--selected {
- background: #07f3;
- }
-
- &--cursor {
- outline: 3px solid #37f;
- outline-offset: -2px;
- }
- }
-
- &__content {
- flex: 1;
- font-family: globals.$font-family-data;
-
- &--dropdown {
- overflow: hidden;
- padding: 0 8px;
- }
-
- &--numeric {
- overflow: hidden;
- text-align: right;
- text-overflow: ellipsis;
- white-space: nowrap;
- padding: 0 8px;
- }
-
- &--text {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- padding: 0 8px;
- }
-
- &--timestamp {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- padding: 0 8px;
- }
-
- &--uuid {
- font-family: globals.$font-family-mono;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- padding: 0 0.5rem;
- }
-
- &--null {
- align-items: center;
- color: color.scale(#000, $lightness: 65%, $space: hsl);
- display: flex;
- font-family: globals.$font-family-data;
- font-style: oblique;
- justify-content: center;
- padding: 0 0.25rem;
-
- svg path {
- fill: currentColor;
- }
- }
- }
-
- &__notice {
- align-items: center;
- color: color.scale(#000, $lightness: 50%, $space: hsl);
- display: flex;
- padding: 0 0.25rem;
-
- svg path {
- fill: currentColor;
- }
- }
-}
-
-.field-header {
- &__container {
- align-items: center;
- background: #0001;
- border: solid 1px #ccc;
- border-top: none;
- border-left: none;
- display: flex;
- flex: none;
- font-family: globals.$font-family-data;
- justify-content: space-between;
- padding: 0.25rem;
- text-align: left;
- }
-
- &__label {
- padding: 0.25rem;
- }
-
- &__type-indicator {
- @include globals.button-clear;
- align-items: center;
- display: flex;
- height: 2rem;
- justify-content: center;
- padding: 0;
- width: 2rem;
-
- svg path {
- fill: currentColor;
- }
- }
-
- &__popover {
- &:popover-open {
- @include globals.popover;
- left: anchor(left);
- top: anchor(bottom);
- padding: 1rem;
- position: absolute;
- }
- }
-}
-
-.lens-inserter {
- grid-area: inserter;
- margin-bottom: 2rem;
-
- &__help {
- font-size: 1rem;
- font-weight: lighter;
- margin: 8px;
- opacity: 0.5;
- }
-
- &__main {
- align-items: stretch;
- display: flex;
- justify-items: flex-start;
- }
-
- &__rows {
- .lens-cell {
- border: dashed 1px $table-border-color;
- border-left: none;
-
- &:last-child {
- border-right: none;
- }
- }
-
- .lens-table__row:first-child .lens-table__cell {
- border-top: dashed 1px $table-border-color;
- }
- }
-
- &__submit {
- @include globals.reset-button;
- align-items: center;
- border: dashed 1px globals.$button-primary-background;
- border-bottom-right-radius: globals.$border-radius-rounded-sm;
- border-top-right-radius: globals.$border-radius-rounded-sm;
- color: globals.$button-primary-background;
- display: flex;
- justify-content: center;
- padding: 0 1rem;
-
- svg path {
- fill: currentColor;
- }
- }
-}
-
-.table-viewer__datum-editor {
- border-top: globals.$default-border;
- display: flex;
- grid-area: editor;
- height: 6rem;
-}
-
-.dropdown-option-badge {
- background: #ccc;
- border-radius: 999px;
- display: block;
- width: max-content;
-
- &:not(:has(button)) {
- padding: 6px 12px;
- }
-
- &--red {
- background: #f99;
- color: color.scale(#f99, $lightness: -66%, $space: oklch);
- }
-
- &--orange {
- background: color.adjust(#f99, $hue: 50deg, $space: oklch);
- color: color.scale(color.adjust(#f99, $hue: 50deg, $space: oklch), $lightness: -66%, $space: oklch);
- }
-
- &--yellow {
- background: color.adjust(#f99, $hue: 100deg, $space: oklch);
- color: color.scale(color.adjust(#f99, $hue: 100deg, $space: oklch), $lightness: -66%, $space: oklch);
- }
-
- &--green {
- background: color.adjust(#f99, $hue: 150deg, $space: oklch);
- color: color.scale(color.adjust(#f99, $hue: 150deg, $space: oklch), $lightness: -66%, $space: oklch);
- }
-
- &--blue {
- background: color.adjust(#f99, $hue: 200deg, $space: oklch);
- color: color.scale(color.adjust(#f99, $hue: 200deg, $space: oklch), $lightness: -66%, $space: oklch);
- }
-
- &--indigo {
- background: color.adjust(#f99, $hue: 250deg, $space: oklch);
- color: color.scale(color.adjust(#f99, $hue: 250deg, $space: oklch), $lightness: -66%, $space: oklch);
- }
-
- &--violet {
- background: color.adjust(#f99, $hue: 300deg, $space: oklch);
- color: color.scale(color.adjust(#f99, $hue: 300deg, $space: oklch), $lightness: -66%, $space: oklch);
- }
-
- button {
- @include globals.button-clear;
-
- color: inherit;
- padding: 6px 12px;
- }
-}
-
-.datum-editor {
- &__container {
- border-left: solid 4px transparent;
- display: grid;
- flex: 1;
- grid-template: 'type-selector type-selector' max-content
- 'null-control value-control' max-content
- 'helpers helpers' auto / max-content auto;
-
- &:has(:focus) {
- border-left-color: #07f;
- }
-
- &--incomplete {
- border-left-color: #f33;
- }
- }
-
- &__type-selector {
- grid-area: type-selector;
- }
-
- &__null-control {
- @include globals.reset_button;
- align-self: start;
- grid-area: null-control;
- padding: 0.75rem;
-
- &--disabled {
- opacity: 0.75;
- }
- }
-
- &__text-input {
- @include globals.reset_input;
- grid-area: value-control;
- font-family: globals.$font-family-data;
- padding: 0.75rem 0.5rem;
- }
-
- &__timestamp-inputs {
- align-items: center;
- display: flex;
- grid-area: value-control;
- justify-content: start;
-
- input {
- @include globals.reset_input;
- }
- }
-
- &__helpers {
- grid-area: helpers;
- overflow: auto;
- }
-
- &__dropdown-options {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- gap: 8px;
- justify-content: flex-start;
- margin: 0;
- padding: 0 8px;
- }
-}
-
-.toolbar-popover {
- &:popover-open {
- @include globals.rounded;
- inset: unset;
- border: globals.$popover-border;
- margin: 0;
- margin-top: 0.25rem;
- position: fixed;
- display: block;
- width: 24rem;
- padding: 0.5rem;
- background: #fff;
- box-shadow: globals.$popover-shadow;
- }
-}
diff --git a/sass/viewer_hoverbar.scss b/sass/viewer_hoverbar.scss
deleted file mode 100644
index e80bada..0000000
--- a/sass/viewer_hoverbar.scss
+++ /dev/null
@@ -1,35 +0,0 @@
-@use 'globals';
-@use 'hoverbar';
-
-.text-editor {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: stretch;
-
- &__input {
- @include globals.reset-input;
- padding: 0.5rem;
- font-family: globals.$font-family-data;
- flex: 1;
- }
-}
-
-.toggle {
- &__container {
- display: flex;
- align-items: center;
- }
-
- &__checkbox {
- margin-right: 0.25rem;
- }
-
- &__label {
- margin-right: 0.5rem;
-
- &--disabled {
- opacity: 0.5;
- }
- }
-}
diff --git a/sass/workspace-nav.scss b/sass/workspace-nav.scss
deleted file mode 100644
index 6371785..0000000
--- a/sass/workspace-nav.scss
+++ /dev/null
@@ -1,80 +0,0 @@
-@use 'globals';
-
-$background-current-item: #0001;
-
-.workspace-nav {
- & h1, h2, h3, h4, h5, h6 {
- margin: 0;
- font-weight: 600;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
-
- & h1 {
- font-size: 1.5rem;
- }
-
- & h2 {
- font-size: 1.25rem;
- }
-
- & h3 {
- font-size: 1.125rem;
- }
-
- & h4, h5, h6 {
- font-size: 1rem;
- }
-
- &__section {
- margin-top: 16px;
- }
-
- &__menu {
- list-style-type: none;
- padding: 0;
- margin: 0;
- margin-top: 16px;
- }
-
- &__heading {
- align-items: center;
- display: flex;
- font-size: inherit;
- justify-content: space-between;
- margin: 8px;
- }
-
- &__aux-button {
- @include globals.button-secondary;
- @include globals.button-small;
-
- text-decoration: none;
- }
-
- &__menu-item {
- display: block;
- margin-left: 8px;
- padding: 0;
- }
-
- &__menu-leaf {
- @include globals.rounded-sm;
- align-items: center;
- display: flex;
- justify-content: space-between;
- padding: 0 8px;
-
- &--current, &:hover {
- background: $background-current-item;
- }
- }
-
- &__menu-link {
- color: globals.$link-color;
- flex: 1;
- padding: 12px 0;
- text-decoration: none;
- }
-}
diff --git a/static/expression-editor.css b/static/expression-editor.css
new file mode 100644
index 0000000..8972599
--- /dev/null
+++ b/static/expression-editor.css
@@ -0,0 +1,78 @@
+.expression-editor__container {
+ background: #eee;
+ border-radius: var(--default-border-radius--rounded);
+ display: flex;
+}
+
+.expression-editor__sidebar {
+ display: grid;
+ grid-template:
+ 'padding-top' 1fr
+ 'operator-selector' max-content
+ 'actions' minmax(max-content, 1fr);
+}
+
+.expression-editor__main {
+ background: #fff;
+ border-radius: var(--default-border-radius--rounded);
+ border: solid 1px var(--default-border-color);
+ flex: 1;
+ padding: var(--default-padding);
+}
+
+.expression-editor__action-button {
+ padding: var(--default-padding);
+
+ svg path {
+ fill: currentColor;
+ }
+}
+
+.expression-editor__params {
+ display: flex;
+ flex-direction: column;
+ gap: var(--default-padding);
+}
+
+.expression-selector {
+ grid-area: operator-selector;
+}
+
+.expression-selector__expression-button {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ height: 2.5rem;
+ padding: 0;
+ width: 2.5rem;
+
+ svg path {
+ fill: currentColor;
+ }
+}
+
+.expression-selector__popover:popover-open {
+ top: anchor(bottom);
+ margin-top: 0.25rem;
+ position: absolute;
+ display: flex;
+ flex-direction: column;
+ padding: 0;
+ background: #fff;
+}
+
+.expression-selector__section {
+ align-items: center;
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ justify-content: center;
+ list-style-type: none;
+ margin: var(--default-padding);
+ padding: 0;
+}
+
+.expression-selector__li {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+}
diff --git a/static/main.css b/static/main.css
new file mode 100644
index 0000000..7ec496d
--- /dev/null
+++ b/static/main.css
@@ -0,0 +1,480 @@
+/*
+@use 'forms';
+@use 'condition-editor';
+*/
+
+/* ======== Theming ======== */
+
+:root {
+ --accent-color: #fc0;
+
+ --default-border-color: #ccc;
+ --default-border-radius--rounded: 8px;
+ --default-border-radius--rounded-sm: 4px;
+ --default-font-family:
+ 'Funnel Sans',
+ 'Open Sans',
+ 'Helvetica Neue',
+ Arial,
+ sans-serif;
+ --default-font-family--data:
+ Menlo,
+ 'Courier New',
+ 'Open Sans',
+ 'Helvetica Neue',
+ Arial,
+ sans-serif;
+ --default-font-family--mono:
+ Menlo,
+ 'Courier New',
+ Courier,
+ mono;
+ --default-padding: 16px;
+ --default-padding--xs: 4px;
+ --default-padding--sm: 8px;
+ --default-padding--lg: 32px;
+
+ --a-color: #069;
+
+ --button-background--primary: var(--accent-color);
+ --button-background--secondary: #fff;
+ --button-border-color--primary: oklch(from var(--button-background--primary) calc(l * 0.9) c h);
+ --button-border-color--secondary: oklch(from var(--button-background--secondary) calc(l * 0.85) c h);
+ --button-border-radius: var(--default-border-radius--rounded);
+ --button-color--primary: #000;
+ --button-color--secondary: #000;
+ --button-font-family: var(--default-font-family);
+ --button-font-size: 1rem;
+ --button-font-size--small: 0.9rem;
+ --button-padding--default: var(--default-padding--sm) var(--default-padding);
+ --button-padding--small: var(--default-padding--xs) var(--default-padding--sm);
+ --button-padding: var(--button-padding--default);
+ --button-shadow: 0 2px 2px #3331;
+
+ --notice-color--info: #39d;
+
+ --popover-border-color: var(--default-border-color);
+ --popover-shadow: 0 8px 8px #3333;
+}
+
+/* ======== Global Setup ======== */
+
+@font-face {
+ font-family: "Funnel Sans";
+ src: url("../funnel_sans/funnel_sans_variable.ttf");
+}
+
+@view-transitions {
+ navigation: auto;
+}
+
+/* https://css-tricks.com/inclusively-hidden/ */
+.sr-only:not(:focus):not(:active) {
+ clip: rect(0 0 0 0);
+ clip-path: inset(50%);
+ height: 1px;
+ overflow: hidden;
+ position: absolute;
+ white-space: nowrap;
+ width: 1px;
+}
+
+/* ======== Basic Elements / Style Resets ======== */
+
+html {
+ font-family: var(--default-font-family);
+}
+
+button {
+ appearance: none;
+ background: none;
+ border: none;
+ padding: 0;
+ box-sizing: border-box;
+ cursor: pointer;
+ font-family: inherit;
+ font-size: inherit;
+ font-weight: inherit;
+}
+
+input[type="text"] {
+ appearance: none;
+ background: none;
+ border: none;
+ box-sizing: border-box;
+ font-family: inherit;
+ font-size: inherit;
+ font-weight: inherit;
+ outline: none;
+}
+
+a {
+ color: var(--a-color);
+ text-decoration: none;
+}
+
+/* ======== Utility Classes ======== */
+
+.text--data {
+ font-family: var(--default-font-family--data);
+}
+
+.padded {
+ padding: var(--default-padding);
+}
+
+.padded-sm {
+ padding: var(--default-padding--sm);
+}
+
+.padded--lg {
+ padding: var(--default-padding--lg);
+}
+
+/* ======== Components: Buttons ======== */
+
+.button {
+ --button-color: inherit;
+
+ background: var(--button-background);
+ border: solid 1px var(--button-border-color);
+ border-radius: var(--button-border-radius);
+ box-shadow: var(--button-shadow);
+ color: var(--button-color);
+ font-family: var(--button-font-family);
+ font-size: var(--button-font-size);
+ padding: var(--button-padding);
+ text-decoration: none;
+ transition: background 0.2s ease;
+
+ &:hover {
+ border-color: oklch(from var(--button-border-color) calc(l * 0.95) c h);
+ background: oklch(from var(--button-background) calc(l * 0.95) c h);
+ }
+}
+
+.button--primary {
+ --button-background: var(--button-background--primary);
+ --button-border-color: var(--button-border-color--primary);
+ --button-color: var(--button-color--primary);
+}
+
+.button--secondary {
+ --button-background: var(--button-background--secondary);
+ --button-border-color: var(--button-border-color--secondary);
+ --button-color: var(--button-color--secondary);
+}
+
+.button--clear {
+ --button-background: transparent;
+ --button-border-color: transparent;
+ --button-color: inherit;
+ --button-font-family: inherit;
+ --button-shadow: none;
+}
+
+.button--small {
+ --button-font-size: var(--button-font-size--small);
+ --button-padding: var(--button-padding--small);
+}
+
+/* ========= Components: Popovers ======== */
+
+.popover:popover-open {
+ background: #fff;
+ border: solid 1px var(--popover-border-color);
+ border-radius: var(--default-border-radius--rounded);
+ box-shadow: var(--popover-shadow);
+ display: block;
+ inset: unset;
+ margin: 0;
+ margin-top: 4px;
+ padding: 0;
+ position: relative;
+}
+
+.dialog:popover-open, .dialog:open {
+ background: #fff;
+ border: solid 1px var(--popover-border-color);
+ border-radius: var(--default-border-radius--rounded);
+ box-shadow: var(--popover-shadow);
+ display: block;
+ max-height: 90vh;
+ overflow: auto;
+}
+
+.basic-dropdown__menu {
+ list-style-type: none;
+ margin: 0;
+ padding: var(--default-padding--sm) 0;
+
+ & > li {
+ padding: 0;
+
+ &:hover {
+ background: #0001;
+ }
+
+ & > button, & > [role="button"] {
+ background: transparent;
+ color: inherit;
+ display: block;
+ font-family: var(--button-font-family--default);
+ padding: var(--button-padding--default);
+ text-decoration: none;
+ transition: background 0.2s ease;
+ }
+ }
+}
+
+/* ======== Components: Miscellaneous ======== */
+
+.table {
+ border-collapse: collapse;
+
+ th, td {
+ border: solid 1px var(--default-border-color);
+ padding: var(--default-padding--sm);
+ }
+
+ th {
+ background: #eee;
+ }
+
+ .table__message {
+ opacity: 0.5;
+ text-align: center;
+ }
+}
+
+.section {
+ padding: 1rem 2rem;
+}
+
+.notice {
+ border-radius: var(--default-border-radius--rounded);
+ margin: 1rem 0rem;
+ padding: 1rem;
+ max-width: 40rem;
+
+ &.notice--info {
+ border: solid 1px globals.$notice-color-info;
+ background: oklch(from var(--notice-color--info) calc(l * 0.9) c h);
+ color: oklch(from var(--notice-color--info) calc(l * 0.2) c h);
+ }
+}
+
+.permissions-list {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--default-padding--sm);
+}
+
+.permission-badge {
+ --permission-badge-resource-color: #f9f9f9;
+ --permission-badge-description-color: #eee;
+
+ display: flex;
+ flex-grow: 0;
+ flex-shrink: 0;
+}
+
+.permission-badge__resource {
+ background: var(--permission-badge-resource-color);
+ border: solid 1px oklch(from var(--permission-badge-resource-color) calc(l * 0.8) c h);
+ border-right: none;
+ border-bottom-left-radius: var(--default-border-radius--rounded-sm);
+ border-top-left-radius: var(--default-border-radius--rounded-sm);
+ font-family: var(--default-font-family--data);
+ font-size: 0.9rem;
+ padding: var(--default-padding--xs);
+}
+
+.permission-badge__description {
+ background: var(--permission-badge-description-color);
+ border: solid 1px oklch(from var(--permission-badge-description-color) calc(l * 0.8) c h);
+ border-bottom-right-radius: var(--default-border-radius--rounded-sm);
+ border-top-right-radius: var(--default-border-radius--rounded-sm);
+ font-family: var(--default-font-family--data);
+ font-size: 0.9rem;
+ padding: var(--default-padding--xs);
+}
+
+/* ======== Forms ======== */
+
+.form__label {
+ display: block;
+ font-weight: 600;
+ margin-top: var(--default-padding);
+}
+
+.form__input {
+ display: block;
+ margin-top: var(--default-padding--sm);
+ font-family: var(--default-font-family--data);
+
+ &:is(input[type="text"]) {
+ border: solid 1px var(--default-border-color);
+ border-radius: var(--default-border-radius--rounded);
+ padding: 0.5rem;
+ }
+}
+
+.form__buttons {
+ display: flex;
+ margin-top: var(--default-padding);
+
+ &.form__buttons--justify-end {
+ justify-content: end;
+ }
+
+ button {
+ margin: 0 var(--default-padding--xs);
+
+ &:first-child {
+ margin-left: 0;
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+}
+
+/* ======== Layout ======== */
+
+.page-grid {
+ height: 100vh;
+ width: 100vw;
+ display: grid;
+ grid-template:
+ 'sidebar toolbar' 4rem
+ 'sidebar main' 1fr / max-content 1fr;
+
+ .page-grid__toolbar {
+ align-items: center;
+ border-bottom: solid 1px var(--default-border-color);
+ display: grid;
+ grid-area: toolbar;
+ grid-template: 'utilities user' 1fr / 1fr max-content;
+
+ .toolbar-item {
+ flex: 0;
+ }
+ }
+
+ .page-grid__toolbar-utilities {
+ align-items: center;
+ display: flex;
+ gap: 12px;
+ grid-area: utilities;
+ justify-content: flex-start;
+ padding: 0 12px;
+ }
+
+ .page-grid__toolbar-user {
+ align-items: center;
+ display: flex;
+ gap: 12px;
+ grid-area: user;
+ justify-content: flex-end;
+ padding: 0 12px;
+
+ basic-dropdown {
+ --button-background: var(--button-background--secondary);
+ --button-border-color: var(--button-border-color--secondary);
+ --button-color: var(--button-color--secondary);
+ }
+ }
+
+ .page-grid__sidebar {
+ grid-area: sidebar;
+ width: 15rem;
+ max-height: 100vh;
+ overflow: auto;
+ border-right: solid 1px var(--default-border-color);
+ }
+
+ .page-grid__main {
+ grid-area: main;
+ overflow: auto;
+ }
+}
+
+/* ======== Workspace Nav ======== */
+
+.workspace-nav {
+ h1, h2, h3, h4, h5, h6 {
+ margin: 0;
+ font-weight: 600;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ h1 {
+ font-size: 1.5rem;
+ }
+
+ h2 {
+ font-size: 1.25rem;
+ }
+
+ h3 {
+ font-size: 1.125rem;
+ }
+
+ h4, h5, h6 {
+ font-size: 1rem;
+ }
+
+ basic-dropdown {
+ --button-background: var(--button-background--secondary);
+ --button-border-color: var(--button-border-color--secondary);
+ --button-color: var(--button-color--secondary);
+ --button-font-size: var(--button-font-size--small);
+ --button-padding: var(--button-padding--small);
+ }
+
+ .workspace-nav__section {
+ margin-top: var(--default-padding);
+ }
+
+ .workspace-nav__menu {
+ list-style-type: none;
+ padding: var(--default-padding--xs) 0;
+ margin: 0;
+ }
+
+ .workspace-nav__heading {
+ align-items: center;
+ display: flex;
+ font-size: inherit;
+ justify-content: space-between;
+ padding: var(--default-padding--sm);
+ padding-bottom: 0;
+ }
+
+ .workspace-nav__menu-item {
+ display: block;
+ margin-left: var(--default-padding--sm);
+ padding: 0;
+ }
+
+ .workspace-nav__menu-leaf {
+ align-items: center;
+ border-radius: var(--default-border-radius--rounded-sm);
+ display: flex;
+ justify-content: space-between;
+ padding: var(--default-padding--xs) var(--default-padding--sm);
+
+ .workspace-nav__menu-leaf--current, &:hover {
+ background: #0001;
+ }
+ }
+
+ .workspace-nav__menu-link {
+ flex: 1;
+ padding: var(--default-padding--sm) 0;
+ }
+}
diff --git a/sass/_modern-normalize.css b/static/modern-normalize.min.css
similarity index 100%
rename from sass/_modern-normalize.css
rename to static/modern-normalize.min.css
diff --git a/static/portal-table.css b/static/portal-table.css
new file mode 100644
index 0000000..ce7d92a
--- /dev/null
+++ b/static/portal-table.css
@@ -0,0 +1,422 @@
+@import "./expression-editor.css";
+
+/* ======== Toolbar ======== */
+
+.filter-menu {
+ --button-background: var(--button-background--secondary);
+ --button-border-color: var(--button-border-color--secondary);
+ --button-color: var(--button-color--secondary);
+}
+
+/* ======== Layout ======== */
+
+.table-viewer__layout {
+ display: grid;
+ grid-template:
+ 'table' 1fr
+ 'editor' max-content;
+ height: 100%;
+ width: 100%;
+}
+
+.table-viewer__table {
+ display: grid;
+ grid-area: table;
+ grid-template:
+ 'headers' max-content
+ 'main' 1fr
+ 'inserter' max-content;
+ height: 100%;
+ outline: none;
+ overflow: auto;
+ width: 100%;
+}
+
+.table-viewer__headers {
+ align-items: stretch;
+ display: flex;
+ grid-area: headers;
+ /*
+ Ensure that there will be enough space on the right for popovers to
+ render without overflowing the container.
+ */
+ padding-right: 480px;
+}
+
+/* ======== Table Headers ======== */
+
+.field-header,
+.field-adder__header-lookalike {
+ align-items: center;
+ background: #0001;
+ border: solid 1px #ccc;
+ border-top: none;
+ border-left: none;
+ display: flex;
+ flex: none;
+ font-family: var(--default-font-family--data);
+ height: 100%;
+ justify-content: space-between;
+ padding: 0.25rem;
+ text-align: left;
+}
+
+.field-header .basic-dropdown__button {
+ --button-background: transparent;
+ --button-border-color: transparent;
+ --button-color: var(--button-color--secondary);
+ --button-shadow: none;
+}
+
+.field-header__label {
+ padding: 4px;
+}
+
+.field-header__type-indicator {
+ align-items: center;
+ display: flex;
+ justify-content: center;
+ padding: 0;
+
+ height: 2rem;
+ width: 2rem;
+
+ svg path {
+ fill: currentColor;
+ }
+}
+
+.field-header__popover:popover-open {
+ left: anchor(left);
+ top: anchor(bottom);
+ padding: 1rem;
+ position: absolute;
+}
+
+/* ======== Component: Field Adder ======== */
+
+.field-adder {
+ align-items: stretch;
+ display: flex;
+ height: 100%;
+}
+
+.field-adder__summary-buttons {
+ align-items: center;
+ display: flex;
+}
+
+.field-adder__header-lookalike:not(.field-adder__header-lookalike--visible) {
+ display: none;
+}
+
+.field-adder__popover:popover-open {
+ display: grid;
+ font-family: var(--default-font-family);
+ grid-template: "completions configs" 1fr / 1fr 2fr;
+ left: anchor(left);
+ position: absolute;
+ top: anchor(bottom);
+ width: 480px;
+}
+
+.field-adder__completions {
+ align-items: stretch;
+ border-right: solid 1px var(--default-border-color);
+ grid-area: completions;
+ display: flex;
+ flex-direction: column;
+ font-family: var(--default-font-family--data);
+ justify-content: start;
+
+ & > button {
+ display: block;
+ padding: 0.5rem;
+ font-weight: normal;
+ text-align: left;
+ width: 100%;
+
+ &:hover,
+ &:focus,
+ &[aria-selected="true"] {
+ background: #0000001f;
+ }
+ }
+}
+
+.field-adder__configs {
+ grid-area: configs;
+ padding: var(--default-padding);
+}
+
+/* ======== Table Body ======== */
+
+.table-viewer__main {
+ grid-area: main;
+ overflow-y: auto;
+}
+
+.table-viewer__row {
+ align-items: stretch;
+ display: flex;
+ height: 2.25rem;
+}
+
+.table-viewer__cell {
+ align-items: stretch;
+ border: solid 1px var(--default-border-color);
+ border-left: none;
+ border-top: none;
+ display: flex;
+ flex: none;
+ padding: 0;
+
+ &:focus {
+ outline: none;
+ }
+
+ .table-viewer__cell-container {
+ align-items: center;
+ display: flex;
+ flex: none;
+ user-select: none;
+ width: 100%;
+
+ &.table-viewer__cell-container--selected {
+ background: #07f3;
+ }
+
+ &.table-viewer__cell-container--cursor {
+ outline: 3px solid #37f;
+ outline-offset: -2px;
+ }
+ }
+
+ .table-viewer__cell-content {
+ flex: 1;
+ font-family: var(--default-font-family--data);
+
+ &.table-viewer__cell-content--dropdown {
+ overflow: hidden;
+ padding: 0 8px;
+ }
+
+ &.table-viewer__cell-content--numeric {
+ overflow: hidden;
+ text-align: right;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 0 8px;
+ }
+
+ &.table-viewer__cell-content--text {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 0 8px;
+ }
+
+ &.table-viewer__cell-content--timestamp {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 0 8px;
+ }
+
+ &.table-viewer__cell-content--uuid {
+ font-family: var(--default-font-family--mono);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding: 0 8px;
+ }
+
+ &.table-viewer__cell-content--null {
+ align-items: center;
+ color: #aaa;
+ display: flex;
+ font-family: var(--default-font-family--data);
+ font-style: oblique;
+ justify-content: center;
+ padding: 0 4px;
+
+ svg path {
+ fill: currentColor;
+ }
+ }
+ }
+}
+
+.table-viewer__notice {
+ align-items: center;
+ color: #888;
+ display: flex;
+ padding: 0 4px;
+
+ svg path {
+ fill: currentColor;
+ }
+}
+
+.table-viewer__inserter {
+ grid-area: inserter;
+ margin-bottom: 2rem;
+
+ .table-viewer__inserter-help {
+ font-size: 1rem;
+ font-weight: 300;
+ margin: 8px;
+ opacity: 0.5;
+ }
+
+ .table-viewer__inserter-main {
+ align-items: stretch;
+ display: flex;
+ justify-items: flex-start;
+ }
+
+ .table-viewer__inserter-rows {
+ .table-viewer__cell {
+ border: dashed 1px var(--default-border-color);
+ border-left: none;
+
+ &:last-child {
+ border-right: none;
+ }
+ }
+ }
+
+ .table-viewer__inserter-submit {
+ align-items: center;
+ border: dashed 1px var(--button-background--primary);
+ border-bottom-right-radius: var(--default-border-radius--rounded-sm);
+ border-top-right-radius: var(--default-border-radius--rounded-sm);
+ color: var(--button-background--primary);
+ display: flex;
+ justify-content: center;
+ padding: 0 var(--default-padding);
+
+ svg path {
+ fill: currentColor;
+ }
+ }
+}
+
+/* ======== Datum Editor ======== */
+
+.datum-editor {
+ border-top: solid 1px var(--default-border-color);
+ display: flex;
+ grid-area: editor;
+ height: 6rem;
+
+ .datum-editor__container {
+ border-left: solid 4px transparent;
+ display: grid;
+ flex: 1;
+ grid-template:
+ 'null-control value-control' max-content
+ 'helpers helpers' auto / max-content auto;
+
+ &:has(:focus) {
+ border-left-color: #07f;
+ }
+
+ &.datum-editor__container--incomplete {
+ border-left-color: #f33;
+ }
+ }
+
+ .datum-editor__type-selector {
+ grid-area: type-selector;
+ }
+
+ .datum-editor__null-control {
+ align-self: start;
+ grid-area: null-control;
+ padding: 12px;
+
+ &.datum-editor__null-control--disabled {
+ opacity: 0.75;
+ }
+ }
+
+ .datum-editor__text-input {
+ grid-area: value-control;
+ font-family: var(--default-font-family--data);
+ padding: 12px 8px;
+ }
+
+ .datum-editor__timestamp-inputs {
+ align-items: center;
+ display: flex;
+ grid-area: value-control;
+ justify-content: start;
+ }
+
+ .datum-editor__helpers {
+ grid-area: helpers;
+ overflow: auto;
+ }
+
+ .datum-editor__dropdown-options {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ gap: 8px;
+ justify-content: flex-start;
+ margin: 0;
+ padding: 0 8px;
+ }
+}
+
+/* ======== Data Display ======== */
+
+.dropdown-option-badge {
+ --badge-color-base: #f99;
+ --badge-hue-rot: 0;
+ --badge-background: oklch(from var(--badge-color-base) l c calc(h + var(--badge-hue-rot)));
+
+ background: var(--badge-background);
+ border-radius: 999px;
+ color: oklch(from var(--badge-background) calc(l * 0.3) c h);
+ display: block;
+ width: max-content;
+
+ &:not(:has(button)) {
+ padding: 6px 12px;
+ }
+
+ &.dropdown-option-badge--red {
+ --badge-hue-rot: 50;
+ }
+
+ &.dropdown-option-badge--orange {
+ --badge-hue-rot: 50;
+ }
+
+ &.dropdown-option-badge--yellow {
+ --badge-hue-rot: 100;
+ }
+
+ &.dropdown-option-badge--green {
+ --badge-hue-rot: 150;
+ }
+
+ &.dropdown-option-badge--blue {
+ --badge-hue-rot: 200;
+ }
+
+ &.dropdown-option-badge--indigo {
+ --badge-hue-rot: 250;
+ }
+
+ &.dropdown-option-badge--violet {
+ --badge-hue-rot: 300;
+ }
+
+ button {
+ color: inherit;
+ padding: 6px 12px;
+ }
+}
diff --git a/svelte/src/basic-dropdown.webc.svelte b/svelte/src/basic-dropdown.webc.svelte
index 0c5b2ff..41ef7b0 100644
--- a/svelte/src/basic-dropdown.webc.svelte
+++ b/svelte/src/basic-dropdown.webc.svelte
@@ -3,7 +3,6 @@
// `shadowRoot` field must remain as the default, else named slots break.
props: {
button_aria_label: { attribute: "button-aria-label" },
- button_class: { attribute: "button-class" },
alignment: { attribute: "alignment" },
},
tag: "basic-dropdown",
@@ -30,16 +29,10 @@ stylesheet, which is merely a copy of the "main" application stylesheet.
type Props = {
alignment?: string;
button_aria_label?: string;
- button_class?: string;
on_toggle?(ev: ToggleEvent): unknown;
};
- let {
- alignment,
- button_aria_label,
- button_class = "button--secondary",
- on_toggle,
- }: Props = $props();
+ let { alignment, button_aria_label, on_toggle }: Props = $props();
let popover_element: HTMLElement | undefined = $state();
// Hacky workaround because as of September 2025 implicit anchor association
@@ -69,7 +62,7 @@ stylesheet, which is merely a copy of the "main" application stylesheet.
{
popover_element?.showPopover();
@@ -91,6 +84,41 @@ stylesheet, which is merely a copy of the "main" application stylesheet.
-
diff --git a/svelte/src/collapsible-menu.webc.svelte b/svelte/src/collapsible-menu.webc.svelte
deleted file mode 100644
index b1ab6ef..0000000
--- a/svelte/src/collapsible-menu.webc.svelte
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
diff --git a/svelte/src/expression-editor.webc.svelte b/svelte/src/expression-editor.webc.svelte
index 612c571..a62cac8 100644
--- a/svelte/src/expression-editor.webc.svelte
+++ b/svelte/src/expression-editor.webc.svelte
@@ -15,21 +15,22 @@
import { type PgExpressionAny } from "./expression.svelte";
import ExpressionEditor from "./expression-editor.webc.svelte";
import { type FieldInfo } from "./field.svelte";
- import { type Presentation } from "./presentation.svelte";
+ import { RFC_3339_S, type Presentation } from "./presentation.svelte";
import type { Datum } from "./datum.svelte";
const ASSIGNABLE_PRESENTATIONS: Presentation[] = [
{ t: "Text", c: { input_mode: { t: "MultiLine", c: {} } } },
- { t: "Timestamp", c: {} },
+ { t: "Timestamp", c: { format: RFC_3339_S } },
{ t: "Uuid", c: {} },
];
const ASSIGNABLE_FIELDS: FieldInfo[] = ASSIGNABLE_PRESENTATIONS.map(
(presentation) => ({
field: {
id: "",
- table_label: "",
name: "",
+ ordinality: -1,
presentation,
+ table_label: "",
table_width_px: -1,
},
not_null: true,
diff --git a/svelte/src/expression-selector.svelte b/svelte/src/expression-selector.svelte
index 45dc357..4aad7bb 100644
--- a/svelte/src/expression-selector.svelte
+++ b/svelte/src/expression-selector.svelte
@@ -136,7 +136,7 @@
}
-
+
diff --git a/svelte/src/field-adder.svelte b/svelte/src/field-adder.svelte
index 841b2ed..a4f47ea 100644
--- a/svelte/src/field-adder.svelte
+++ b/svelte/src/field-adder.svelte
@@ -16,7 +16,6 @@ submission.
incompatible with the current presentation configuration.-->
-