summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2025-01-11 13:34:40 -0500
committerOwen Jacobson <owen@grimoire.ca>2025-01-11 13:34:40 -0500
commitea0392a2bb12c158f9167105752f8fa315cff47d (patch)
treedec4545ccbe44c8e2baf6e633308359f40ac610a
parent4e3ad13aca163e733724b205c250bdb67cc56c29 (diff)
parent6d51f8568e337e768505ccfdef916b84dd6eb1b3 (diff)
Merge branch 'prop/stylize'
-rw-r--r--build.rs1
-rw-r--r--package-lock.json1020
-rw-r--r--package.json5
-rw-r--r--postcss.config.js1
-rw-r--r--tailwind.config.js25
-rw-r--r--ui/app.css63
-rw-r--r--ui/app.html4
-rw-r--r--ui/lib/components/ActiveChannel.svelte4
-rw-r--r--ui/lib/components/ChangePassword.svelte14
-rw-r--r--ui/lib/components/Channel.svelte14
-rw-r--r--ui/lib/components/CreateChannelForm.svelte15
-rw-r--r--ui/lib/components/Invite.svelte10
-rw-r--r--ui/lib/components/Invites.svelte8
-rw-r--r--ui/lib/components/LogIn.svelte20
-rw-r--r--ui/lib/components/LogOut.svelte4
-rw-r--r--ui/lib/components/Message.svelte33
-rw-r--r--ui/lib/components/MessageInput.svelte16
-rw-r--r--ui/lib/components/MessageRun.svelte12
-rw-r--r--ui/lib/store/channels.svelte.js9
-rw-r--r--ui/lib/store/messages.svelte.js2
-rw-r--r--ui/routes/(app)/+layout.svelte70
-rw-r--r--ui/routes/(app)/+page.svelte3
-rw-r--r--ui/routes/(app)/ch/[channel]/+page.svelte25
-rw-r--r--ui/routes/(app)/me/+page.svelte16
-rw-r--r--ui/routes/(login)/invite/[invite]/+page.svelte4
-rw-r--r--ui/routes/+layout.svelte19
-rw-r--r--ui/static/manifest.json2
-rw-r--r--ui/styles/active-channel.css6
-rw-r--r--ui/styles/app-bar.css40
-rw-r--r--ui/styles/app-layout.css56
-rw-r--r--ui/styles/forms.css21
-rw-r--r--ui/styles/invites.css11
-rw-r--r--ui/styles/messages.css121
-rw-r--r--ui/styles/overscroll.css9
-rw-r--r--ui/styles/reset.css129
-rw-r--r--ui/styles/sidebar.css85
-rw-r--r--ui/styles/textarea.css31
-rw-r--r--ui/styles/variables.css72
38 files changed, 851 insertions, 1149 deletions
diff --git a/build.rs b/build.rs
index a61b2db..3b7abda 100644
--- a/build.rs
+++ b/build.rs
@@ -30,7 +30,6 @@ fn main() -> Result<(), io::Error> {
// println!("cargo::rerun-if-changed=node_modules");
println!("cargo::rerun-if-changed=postcss.config.js");
println!("cargo::rerun-if-changed=svelte.config.js");
- println!("cargo::rerun-if-changed=tailwind.config.js");
println!("cargo::rerun-if-changed=vite.config.js");
println!("cargo::rerun-if-changed=ui");
let status = Command::new("npm").args(["run", "build"]).status()?;
diff --git a/package-lock.json b/package-lock.json
index 7d8be51..edf23f7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,12 +15,9 @@
"tinygesture": "^3.0.0"
},
"devDependencies": {
- "@skeletonlabs/skeleton": "^2.10.3",
- "@skeletonlabs/tw-plugin": "^0.4.0",
"@sveltejs/adapter-static": "^3.0.6",
"@sveltejs/kit": "^2.7.4",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
- "@tailwindcss/forms": "^0.5.9",
"@types/eslint": "^9.6.1",
"@vitest/coverage-v8": "^2.1.4",
"autoprefixer": "^10.4.20",
@@ -33,7 +30,7 @@
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.7",
"svelte": "^5.1.9",
- "tailwindcss": "^3.4.14",
+ "svelte-copy": "^2.0.0",
"vite": "^5.4.10",
"vitest": "^2.1.4"
},
@@ -42,19 +39,6 @@
"npm": ">=10.0.0 <11.0.0"
}
},
- "node_modules/@alloc/quick-lru": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
- "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -143,40 +127,6 @@
"node": ">=12"
}
},
- "node_modules/@esbuild/linux-arm64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
- "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@esbuild/linux-x64": {
- "version": "0.21.5",
- "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
- "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
@@ -299,9 +249,9 @@
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.1.tgz",
- "integrity": "sha512-HFZ4Mp26nbWk9d/BpvP0YNL6W4UoZF0VFcTw/aPPA8RpOxeFQgK+ClABGgAUXs9Y/RGX/l1vOmrqz1MQt9MNuw==",
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz",
+ "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
@@ -440,6 +390,19 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
@@ -458,44 +421,6 @@
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -528,89 +453,10 @@
"darwin"
]
},
- "node_modules/@rollup/rollup-linux-arm64-gnu": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz",
- "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-arm64-musl": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz",
- "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==",
- "cpu": [
- "arm64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-gnu": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz",
- "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@rollup/rollup-linux-x64-musl": {
- "version": "4.24.0",
- "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz",
- "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==",
- "cpu": [
- "x64"
- ],
- "dev": true,
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ]
- },
- "node_modules/@skeletonlabs/skeleton": {
- "version": "2.10.3",
- "resolved": "https://registry.npmjs.org/@skeletonlabs/skeleton/-/skeleton-2.10.3.tgz",
- "integrity": "sha512-O1RecF68zEVvZl3GgRS4emqWMUIQLHvTOFoqGOw/2OXCPE06IxUQrHQf2hnxCPxtGZNXY2YX8UNV38l+eH8GNQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "esm-env": "1.0.0"
- },
- "peerDependencies": {
- "svelte": "^3.56.0 || ^4.0.0 || ^5.0.0"
- }
- },
- "node_modules/@skeletonlabs/tw-plugin": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@skeletonlabs/tw-plugin/-/tw-plugin-0.4.0.tgz",
- "integrity": "sha512-v6Y4deBq9ByRx3kTRGgekhhYkWEYgNNNu8UXOwJngCStB7w8SwmbNFSeHkluxMbgCgMnJyp220EMpw9nj/rEsQ==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "tailwindcss": ">=3.0.0"
- }
- },
"node_modules/@sveltejs/adapter-static": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.6.tgz",
- "integrity": "sha512-MGJcesnJWj7FxDcB/GbrdYD3q24Uk0PIL4QIX149ku+hlJuj//nxUbb0HxUTpjkecWfHjVveSUnUaQWnPRXlpg==",
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@sveltejs/adapter-static/-/adapter-static-3.0.8.tgz",
+ "integrity": "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@@ -618,9 +464,9 @@
}
},
"node_modules/@sveltejs/kit": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.7.4.tgz",
- "integrity": "sha512-3DOPQYck3CpAmPgGq/HuhJMCCz8GF0ukbompPJQ2zShoSzrEKW9iG/l0nZmaxMvuOO3NNLmZj8F3W9uzqmkNdw==",
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.15.1.tgz",
+ "integrity": "sha512-8t7D3hQHbUDMiaQ2RVnjJJ/+Ur4Fn/tkeySJCsHtX346Q9cp3LAnav8xXdfuqYNJwpUGX0x3BqF1uvbmXQw93A==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
@@ -628,7 +474,7 @@
"@types/cookie": "^0.6.0",
"cookie": "^0.6.0",
"devalue": "^5.1.0",
- "esm-env": "^1.0.0",
+ "esm-env": "^1.2.1",
"import-meta-resolve": "^4.1.0",
"kleur": "^4.1.5",
"magic-string": "^0.30.5",
@@ -645,9 +491,9 @@
"node": ">=18.13"
},
"peerDependencies": {
- "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1",
+ "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0",
"svelte": "^4.0.0 || ^5.0.0-next.0",
- "vite": "^5.0.3"
+ "vite": "^5.0.3 || ^6.0.0"
}
},
"node_modules/@sveltejs/vite-plugin-svelte": {
@@ -690,19 +536,6 @@
"vite": "^5.0.0"
}
},
- "node_modules/@tailwindcss/forms": {
- "version": "0.5.9",
- "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.9.tgz",
- "integrity": "sha512-tM4XVr2+UVTxXJzey9Twx48c1gcxFStqn1pQz0tRsX8o3DvxhN5oY5pvyAbUx7VTaZxpej4Zzvc6h+1RJBzpIg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "mini-svg-data-uri": "^1.2.3"
- },
- "peerDependencies": {
- "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20"
- }
- },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -735,6 +568,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/node": {
+ "version": "22.10.2",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz",
+ "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
"node_modules/@vitest/coverage-v8": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-2.1.4.tgz",
@@ -973,34 +818,6 @@
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
- "node_modules/any-promise": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/anymatch": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
- "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "normalize-path": "^3.0.0",
- "picomatch": "^2.0.4"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/arg": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -1100,19 +917,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/binary-extensions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
- "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1124,19 +928,6 @@
"concat-map": "0.0.1"
}
},
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/browserslist": {
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz",
@@ -1170,6 +961,15 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
"node_modules/cac": {
"version": "6.7.14",
"resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
@@ -1190,16 +990,6 @@
"node": ">=6"
}
},
- "node_modules/camelcase-css": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
- "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/caniuse-lite": {
"version": "1.0.30001669",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz",
@@ -1265,44 +1055,6 @@
"node": ">= 16"
}
},
- "node_modules/chokidar": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
- "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "anymatch": "~3.1.2",
- "braces": "~3.0.2",
- "glob-parent": "~5.1.2",
- "is-binary-path": "~2.1.0",
- "is-glob": "~4.0.1",
- "normalize-path": "~3.0.0",
- "readdirp": "~3.6.0"
- },
- "engines": {
- "node": ">= 8.10.0"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
- "node_modules/chokidar/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -1336,14 +1088,13 @@
}
},
"node_modules/commander": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
- "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true,
"license": "MIT",
- "engines": {
- "node": ">= 6"
- }
+ "optional": true,
+ "peer": true
},
"node_modules/concat-map": {
"version": "0.0.1",
@@ -1363,9 +1114,9 @@
}
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1485,20 +1236,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/didyoumean": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true,
- "license": "Apache-2.0"
- },
- "node_modules/dlv": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/dompurify": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz",
@@ -1757,9 +1494,9 @@
}
},
"node_modules/esm-env": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.0.0.tgz",
- "integrity": "sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.1.tgz",
+ "integrity": "sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==",
"dev": true,
"license": "MIT"
},
@@ -1865,36 +1602,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8.6.0"
- }
- },
- "node_modules/fast-glob/node_modules/glob-parent": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
- "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -1909,16 +1616,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fastq": {
- "version": "1.17.1",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
- "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -1932,19 +1629,6 @@
"node": ">=16.0.0"
}
},
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -2063,16 +1747,6 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "dev": true,
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
@@ -2170,19 +1844,6 @@
"node": ">=8"
}
},
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
"node_modules/html-encoding-sniffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz",
@@ -2292,35 +1953,6 @@
"node": ">=0.8.19"
}
},
- "node_modules/is-binary-path": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
- "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "binary-extensions": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-core-module": {
- "version": "2.15.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
- "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -2354,16 +1986,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
"node_modules/is-potential-custom-element-name": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
@@ -2464,6 +2086,8 @@
"integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
"dev": true,
"license": "MIT",
+ "optional": true,
+ "peer": true,
"bin": {
"jiti": "bin/jiti.js"
}
@@ -2594,13 +2218,6 @@
"node": ">=10"
}
},
- "node_modules/lines-and-columns": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
- "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/locate-character": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz",
@@ -2704,30 +2321,6 @@
"node": ">= 18"
}
},
- "node_modules/merge2": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
- "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
@@ -2749,16 +2342,6 @@
"node": ">= 0.6"
}
},
- "node_modules/mini-svg-data-uri": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
- "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "mini-svg-data-uri": "cli.js"
- }
- },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -2809,22 +2392,10 @@
"dev": true,
"license": "MIT"
},
- "node_modules/mz": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
- "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "any-promise": "^1.0.0",
- "object-assign": "^4.0.1",
- "thenify-all": "^1.0.0"
- }
- },
"node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"dev": true,
"funding": [
{
@@ -2854,16 +2425,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/normalize-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
- "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/normalize-range": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
@@ -2881,26 +2442,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-hash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
- "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
@@ -3004,13 +2545,6 @@
"node": ">=8"
}
},
- "node_modules/path-parse": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
@@ -3052,39 +2586,6 @@
"dev": true,
"license": "ISC"
},
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/pirates": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
- "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 6"
- }
- },
"node_modules/postcss": {
"version": "8.4.47",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
@@ -3114,44 +2615,6 @@
"node": "^10 || ^12 || >=14"
}
},
- "node_modules/postcss-import": {
- "version": "15.1.0",
- "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
- "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "postcss-value-parser": "^4.0.0",
- "read-cache": "^1.0.0",
- "resolve": "^1.1.7"
- },
- "engines": {
- "node": ">=14.0.0"
- },
- "peerDependencies": {
- "postcss": "^8.0.0"
- }
- },
- "node_modules/postcss-js": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
- "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "camelcase-css": "^2.0.1"
- },
- "engines": {
- "node": "^12 || ^14 || >= 16"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- "peerDependencies": {
- "postcss": "^8.4.21"
- }
- },
"node_modules/postcss-load-config": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz",
@@ -3182,32 +2645,6 @@
}
}
},
- "node_modules/postcss-nested": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
- "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "postcss-selector-parser": "^6.1.1"
- },
- "engines": {
- "node": ">=12.0"
- },
- "peerDependencies": {
- "postcss": "^8.2.14"
- }
- },
"node_modules/postcss-safe-parser": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz",
@@ -3326,68 +2763,6 @@
"node": ">=6"
}
},
- "node_modules/queue-microtask": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
- "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT"
- },
- "node_modules/read-cache": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
- "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "pify": "^2.3.0"
- }
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "picomatch": "^2.2.1"
- },
- "engines": {
- "node": ">=8.10.0"
- }
- },
- "node_modules/resolve": {
- "version": "1.22.8",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
- "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-core-module": "^2.13.0",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -3398,17 +2773,6 @@
"node": ">=4"
}
},
- "node_modules/reusify": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
- "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "iojs": ">=1.0.0",
- "node": ">=0.10.0"
- }
- },
"node_modules/rollup": {
"version": "4.24.0",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz",
@@ -3452,30 +2816,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/run-parallel": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
- "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/feross"
- },
- {
- "type": "patreon",
- "url": "https://www.patreon.com/feross"
- },
- {
- "type": "consulting",
- "url": "https://feross.org/support"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "queue-microtask": "^1.2.2"
- }
- },
"node_modules/sade": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
@@ -3523,9 +2863,9 @@
}
},
"node_modules/set-cookie-parser": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.0.tgz",
- "integrity": "sha512-lXLOiqpkUumhRdFF3k1osNXCy9akgx/dyPZ5p8qAg9seJzXr5ZrlqZuWIMuY6ejOsVLE6flJ5/h3lsn57fQ/PQ==",
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
+ "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"dev": true,
"license": "MIT"
},
@@ -3597,6 +2937,31 @@
"node": ">=0.10.0"
}
},
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/stackback": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
@@ -3728,29 +3093,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/sucrase": {
- "version": "3.35.0",
- "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
- "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/gen-mapping": "^0.3.2",
- "commander": "^4.0.0",
- "glob": "^10.3.10",
- "lines-and-columns": "^1.1.6",
- "mz": "^2.7.0",
- "pirates": "^4.0.1",
- "ts-interface-checker": "^0.1.9"
- },
- "bin": {
- "sucrase": "bin/sucrase",
- "sucrase-node": "bin/sucrase-node"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -3764,19 +3106,6 @@
"node": ">=8"
}
},
- "node_modules/supports-preserve-symlinks-flag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
- "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/svelte": {
"version": "5.1.9",
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.1.9.tgz",
@@ -3802,6 +3131,16 @@
"node": ">=18"
}
},
+ "node_modules/svelte-copy": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/svelte-copy/-/svelte-copy-2.0.0.tgz",
+ "integrity": "sha512-wJ784qrc9CF7EtrlT2kwJfHnqae/pp4fkgzYeUxex4iFBm6HosT2904t5cZZ1GAZzg/z9V+lCZVP5rpiYsN6Tw==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "svelte": "^5.0.0"
+ }
+ },
"node_modules/svelte-eslint-parser": {
"version": "0.43.0",
"resolved": "https://registry.npmjs.org/svelte-eslint-parser/-/svelte-eslint-parser-0.43.0.tgz",
@@ -3885,104 +3224,25 @@
"dev": true,
"license": "MIT"
},
- "node_modules/tailwindcss": {
- "version": "3.4.14",
- "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
- "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@alloc/quick-lru": "^5.2.0",
- "arg": "^5.0.2",
- "chokidar": "^3.5.3",
- "didyoumean": "^1.2.2",
- "dlv": "^1.1.3",
- "fast-glob": "^3.3.0",
- "glob-parent": "^6.0.2",
- "is-glob": "^4.0.3",
- "jiti": "^1.21.0",
- "lilconfig": "^2.1.0",
- "micromatch": "^4.0.5",
- "normalize-path": "^3.0.0",
- "object-hash": "^3.0.0",
- "picocolors": "^1.0.0",
- "postcss": "^8.4.23",
- "postcss-import": "^15.1.0",
- "postcss-js": "^4.0.1",
- "postcss-load-config": "^4.0.1",
- "postcss-nested": "^6.0.1",
- "postcss-selector-parser": "^6.0.11",
- "resolve": "^1.22.2",
- "sucrase": "^3.32.0"
- },
- "bin": {
- "tailwind": "lib/cli.js",
- "tailwindcss": "lib/cli.js"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/tailwindcss/node_modules/postcss-load-config": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
- "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "node_modules/terser": {
+ "version": "5.37.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz",
+ "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==",
"dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "github",
- "url": "https://github.com/sponsors/ai"
- }
- ],
- "license": "MIT",
+ "license": "BSD-2-Clause",
+ "optional": true,
+ "peer": true,
"dependencies": {
- "lilconfig": "^3.0.0",
- "yaml": "^2.3.4"
- },
- "engines": {
- "node": ">= 14"
- },
- "peerDependencies": {
- "postcss": ">=8.0.9",
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "postcss": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- }
- }
- },
- "node_modules/tailwindcss/node_modules/postcss-load-config/node_modules/lilconfig": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
- "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14"
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
},
- "funding": {
- "url": "https://github.com/sponsors/antonk52"
- }
- },
- "node_modules/tailwindcss/node_modules/yaml": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
- "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
- "dev": true,
- "license": "ISC",
"bin": {
- "yaml": "bin.mjs"
+ "terser": "bin/terser"
},
"engines": {
- "node": ">= 14"
+ "node": ">=10"
}
},
"node_modules/test-exclude": {
@@ -4033,29 +3293,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/thenify": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
- "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "any-promise": "^1.0.0"
- }
- },
- "node_modules/thenify-all": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "thenify": ">= 3.1.0 < 4"
- },
- "engines": {
- "node": ">=0.8"
- }
- },
"node_modules/tiny-glob": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
@@ -4137,19 +3374,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
"node_modules/totalist": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
@@ -4186,13 +3410,6 @@
"node": ">=18"
}
},
- "node_modules/ts-interface-checker": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
- "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
- "dev": true,
- "license": "Apache-2.0"
- },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -4206,6 +3423,15 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
"node_modules/update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
diff --git a/package.json b/package.json
index 961b44b..392affe 100644
--- a/package.json
+++ b/package.json
@@ -16,12 +16,9 @@
"coverage": "vitest run --coverage"
},
"devDependencies": {
- "@skeletonlabs/skeleton": "^2.10.3",
- "@skeletonlabs/tw-plugin": "^0.4.0",
"@sveltejs/adapter-static": "^3.0.6",
"@sveltejs/kit": "^2.7.4",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
- "@tailwindcss/forms": "^0.5.9",
"@types/eslint": "^9.6.1",
"@vitest/coverage-v8": "^2.1.4",
"autoprefixer": "^10.4.20",
@@ -34,7 +31,7 @@
"prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.7",
"svelte": "^5.1.9",
- "tailwindcss": "^3.4.14",
+ "svelte-copy": "^2.0.0",
"vite": "^5.4.10",
"vitest": "^2.1.4"
},
diff --git a/postcss.config.js b/postcss.config.js
index 2e7af2b..b6dc034 100644
--- a/postcss.config.js
+++ b/postcss.config.js
@@ -1,6 +1,5 @@
export default {
plugins: {
- tailwindcss: {},
autoprefixer: {},
},
}
diff --git a/tailwind.config.js b/tailwind.config.js
deleted file mode 100644
index d6511b8..0000000
--- a/tailwind.config.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// @ts-check
-import { join } from 'path';
-import { skeleton } from '@skeletonlabs/tw-plugin';
-import forms from '@tailwindcss/forms';
-
-/** @type {import('tailwindcss').Config} */
-export default {
- darkMode: 'class',
- content: [
- 'ui/**/*.{html,js,svelte,ts}',
- join(
- require.resolve('@skeletonlabs/skeleton'),
- '../**/*.{html,js,svelte,ts}'
- )
- ],
- theme: {
- extend: {},
- },
- plugins: [
- forms,
- skeleton({
- themes: { preset: [ "skeleton" ] }
- })
- ]
-}
diff --git a/ui/app.css b/ui/app.css
index b316dea..a02106d 100644
--- a/ui/app.css
+++ b/ui/app.css
@@ -1,13 +1,54 @@
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
-
-/* This should help minimize swipe-to-go-back behaviour, enabling our
-* swipe-to-reveal-channel-menu behaviour. It won't work in all cases; in iOS
-* Safari, when swiping from the screen edge, the OS gets th event and
-* handles it before the browser does.
-*/
-html,
+@import url('styles/reset.css');
+@import url('styles/variables.css');
+@import url('styles/overscroll.css');
+@import url('styles/app-bar.css');
+@import url('styles/app-layout.css');
+@import url('styles/sidebar.css');
+@import url('styles/active-channel.css');
+@import url('styles/messages.css');
+@import url('styles/textarea.css');
+@import url('styles/forms.css');
+@import url('styles/invites.css');
+
body {
- overscroll-behavior-x: none;
+ background-color: var(--colour-active-channel-bg);
+ color: var(--dark-text);
+}
+
+hr {
+ width: 90%;
+}
+
+.no-active-channel {
+ display: table;
+ height: 100%;
+ width: 100%;
+ text-align: center;
+}
+
+.vertical-aligner {
+ display: table-cell;
+ vertical-align: middle;
+ font-style: italic;
+}
+
+/* TODO:
+ * put this somewhere appropriate,
+ * use a correct variable,
+ * be sensitive to background colour context.
+ */
+a,
+a:hover,
+a:visited,
+a:active {
+ color: var(--light-text);
+}
+
+/* Debugging */
+/* * /
+div {
+ outline: 1px dashed grey;
+ background-color: var(--colour-background);
+ box-shadow: 5px 5px 5px var(--colour-border);
}
+/* */
diff --git a/ui/app.html b/ui/app.html
index 5e7d92b..e6be518 100644
--- a/ui/app.html
+++ b/ui/app.html
@@ -7,7 +7,7 @@
<link rel="manifest" href="%sveltekit.assets%/manifest.json" />
%sveltekit.head%
</head>
- <body data-sveltekit-preload-data="hover" data-theme="skeleton">
- <div class="m-0 p-0 h-vh w-full">%sveltekit.body%</div>
+ <body data-sveltekit-preload-data="hover">
+ <div>%sveltekit.body%</div>
</body>
</html>
diff --git a/ui/lib/components/ActiveChannel.svelte b/ui/lib/components/ActiveChannel.svelte
index ba62d6c..9c181e4 100644
--- a/ui/lib/components/ActiveChannel.svelte
+++ b/ui/lib/components/ActiveChannel.svelte
@@ -5,7 +5,5 @@
</script>
{#each messageRuns as { sender, messages }}
- <div>
- <MessageRun {sender} {messages} />
- </div>
+ <MessageRun {sender} {messages} />
{/each}
diff --git a/ui/lib/components/ChangePassword.svelte b/ui/lib/components/ChangePassword.svelte
index 1e48bee..bf94ea7 100644
--- a/ui/lib/components/ChangePassword.svelte
+++ b/ui/lib/components/ChangePassword.svelte
@@ -22,11 +22,10 @@
}
</script>
-<form {onsubmit} bind:this={form}>
+<form class="form" {onsubmit} bind:this={form}>
<label
>current password
<input
- class="input"
name="currentPassword"
type="password"
placeholder="password"
@@ -36,19 +35,12 @@
<label
>new password
- <input
- class="input"
- name="newPassword"
- type="password"
- placeholder="password"
- bind:value={newPassword}
- />
+ <input name="newPassword" type="password" placeholder="password" bind:value={newPassword} />
</label>
<label
>confirm new password
<input
- class="input"
name="confirmPassword"
type="password"
placeholder="password"
@@ -56,5 +48,5 @@
/>
</label>
- <button class="btn bg-orange-500 mt-4" type="submit" {disabled}>change password</button>
+ <button type="submit" {disabled}>change password</button>
</form>
diff --git a/ui/lib/components/Channel.svelte b/ui/lib/components/Channel.svelte
index 01b1c87..c73340f 100644
--- a/ui/lib/components/Channel.svelte
+++ b/ui/lib/components/Channel.svelte
@@ -2,13 +2,13 @@
let { id, name, active, hasUnreads } = $props();
</script>
-<li class="rounded-full" class:bg-slate-400={active}>
- <a href="/ch/{id}">
+<a href="/ch/{id}">
+ <li class:active>
{#if hasUnreads}
- <span class="badge bg-warning-500">❦</span>
+ <span class="badge has-unreads">❦</span>
{:else}
- <span class="badge bg-primary-500">¶</span>
+ <span class="badge has-no-unreads">¶</span>
{/if}
- <span class="flex-auto">{name}</span>
- </a>
-</li>
+ <span>{name}</span>
+ </li>
+</a>
diff --git a/ui/lib/components/CreateChannelForm.svelte b/ui/lib/components/CreateChannelForm.svelte
index d50e60d..85c85bb 100644
--- a/ui/lib/components/CreateChannelForm.svelte
+++ b/ui/lib/components/CreateChannelForm.svelte
@@ -15,16 +15,7 @@
}
</script>
-<form onsubmit={handleSubmit} class="form form-row flex-nowrap">
- <input
- type="text"
- placeholder="create channel"
- bind:value={name}
- {disabled}
- class="input flex-auto h-6 w-9/12"
- />
- <button type="submit" class="flex-none w-6 h-6">&#x2795;</button>
+<form onsubmit={handleSubmit}>
+ <input type="text" placeholder="create channel" bind:value={name} {disabled} />
+ <button type="submit">&#x2795;</button>
</form>
-
-<style>
-</style>
diff --git a/ui/lib/components/Invite.svelte b/ui/lib/components/Invite.svelte
index 937c911..29631f4 100644
--- a/ui/lib/components/Invite.svelte
+++ b/ui/lib/components/Invite.svelte
@@ -1,9 +1,13 @@
<script>
- import { clipboard } from '@skeletonlabs/skeleton';
+ import { copy } from 'svelte-copy';
let { id } = $props();
let inviteUrl = $derived(new URL(`/invite/${id}`, document.location));
+ // Nota bene: we cannot use:copy={inviteUrl}, because inviteUrl is not a
+ // string, and therefore will get treated as an options object. So we must
+ // explicitly build an options object, containing the value that will
+ // eventually be interpreted as a string.
</script>
-<button class="btn bg-secondary-500" use:clipboard={inviteUrl}>copy</button>
-<span data-clipboard="inviteUrl">{inviteUrl}</span>
+<button use:copy={{ text: inviteUrl }}>copy</button>
+<span class="invite-url-literal">{inviteUrl}</span>
diff --git a/ui/lib/components/Invites.svelte b/ui/lib/components/Invites.svelte
index 493bf1c..27d3754 100644
--- a/ui/lib/components/Invites.svelte
+++ b/ui/lib/components/Invites.svelte
@@ -13,12 +13,12 @@
}
</script>
-<form {onsubmit}>
- <button class="btn bg-primary-500" type="submit">create invitation</button>
+<form class="form" {onsubmit}>
+ <button type="submit">create invitation</button>
</form>
-<ul class="mt-4">
+<ul class="invite-list">
{#each invites as invite}
- <li class="my-1"><Invite id={invite.id} /></li>
+ <li><Invite id={invite.id} /></li>
{/each}
</ul>
diff --git a/ui/lib/components/LogIn.svelte b/ui/lib/components/LogIn.svelte
index 7fb91e8..5bfdae2 100644
--- a/ui/lib/components/LogIn.svelte
+++ b/ui/lib/components/LogIn.svelte
@@ -8,23 +8,15 @@
} = $props();
</script>
-<div class="card m-4 p-4">
- <form {onsubmit}>
- <label class="label" for="username">
+<div>
+ <form class="form" {onsubmit}>
+ <label for="username">
username
- <input
- class="input"
- name="username"
- type="text"
- placeholder="username"
- bind:value={username}
- {disabled}
- />
+ <input name="username" type="text" placeholder="username" bind:value={username} {disabled} />
</label>
- <label class="label" for="password">
+ <label for="password">
password
<input
- class="input"
name="password"
type="password"
placeholder="password"
@@ -32,7 +24,7 @@
{disabled}
/>
</label>
- <button class="btn variant-filled" type="submit">
+ <button type="submit">
{legend}
</button>
</form>
diff --git a/ui/lib/components/LogOut.svelte b/ui/lib/components/LogOut.svelte
index 52aa039..b699cfd 100644
--- a/ui/lib/components/LogOut.svelte
+++ b/ui/lib/components/LogOut.svelte
@@ -13,6 +13,6 @@
}
</script>
-<form {onsubmit}>
- <button class="btn bg-orange-400" type="submit">log out</button>
+<form class="form" {onsubmit}>
+ <button type="submit">log out</button>
</form>
diff --git a/ui/lib/components/Message.svelte b/ui/lib/components/Message.svelte
index 5673248..1b1598b 100644
--- a/ui/lib/components/Message.svelte
+++ b/ui/lib/components/Message.svelte
@@ -25,42 +25,15 @@
}
</script>
-<div
- class="message relative"
- class:bg-warning-800={deleteArmed}
- role="article"
- data-at={at}
- {onmouseleave}
- >
- <div class="handle chip bg-surface-700 absolute -top-6 right-0">
+<div class="message" class:delete-armed={deleteArmed} role="article" data-at={at} {onmouseleave}>
+ <div class="handle">
{atFormatted}
{#if editable}
<button onclick={onDelete}>&#x1F5D1;&#xFE0F;</button>
{/if}
</div>
- <section use:scroll class="py-1 message-body">
+ <section use:scroll class="message-body">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html renderedBody}
</section>
</div>
-
-<style>
- .message .handle {
- display: none;
- }
- .message:hover .handle {
- display: flex;
- }
- .message-body {
- overflow: auto;
- max-width: 80vw;
- @media (width > 640px) {
- /* 21rem is width of the nav bar in full-screen mode. */
- max-width: calc(90vw - 21rem);
- }
- }
- .message-body:empty:after {
- content: '.';
- visibility: hidden;
- }
-</style>
diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte
index 22456f3..162db1b 100644
--- a/ui/lib/components/MessageInput.svelte
+++ b/ui/lib/components/MessageInput.svelte
@@ -23,17 +23,7 @@
}
</script>
-<form bind:this={form} onsubmit={onSubmit} class="flex flex-row flex-nowrap">
- <textarea
- onkeydown={onKeyDown}
- bind:value
- {disabled}
- type="search"
- class="flex-auto h-6 py-0 input rounded-r-none text-nowrap"
- ></textarea>
- <button
- color="primary variant-filled-secondary"
- type="submit"
- class="flex-none w-6 h-6 btn-icon variant-filled rounded-l-none">&raquo;</button
- >
+<form bind:this={form} onsubmit={onSubmit}>
+ <textarea onkeydown={onKeyDown} bind:value {disabled} type="search"></textarea>
+ <button type="submit">&raquo;</button>
</form>
diff --git a/ui/lib/components/MessageRun.svelte b/ui/lib/components/MessageRun.svelte
index 39ee155..bee64e8 100644
--- a/ui/lib/components/MessageRun.svelte
+++ b/ui/lib/components/MessageRun.svelte
@@ -8,15 +8,11 @@
let ownMessage = $derived($currentUser !== null && $currentUser.id == sender);
</script>
-<div
- class="card my-4 px-4 py-1 relative"
- class:own-message={ownMessage}
- class:other-message={!ownMessage}
->
- <span class="chip variant-soft sticky top-o left-0">
+<div class="message-run" class:own-message={ownMessage} class:other-message={!ownMessage}>
+ <span class="username">
@{name}:
</span>
- {#each messages as { id, at, body, renderedBody }}
- <Message {id} {at} {body} {renderedBody} editable={ownMessage} />
+ {#each messages as message}
+ <Message {...message} editable={ownMessage} />
{/each}
</div>
diff --git a/ui/lib/store/channels.svelte.js b/ui/lib/store/channels.svelte.js
index 8919be0..c82f9aa 100644
--- a/ui/lib/store/channels.svelte.js
+++ b/ui/lib/store/channels.svelte.js
@@ -1,5 +1,5 @@
import { DateTime } from 'luxon';
-const EPOCH_STRING = "1970-01-01T00:00:00Z";
+const EPOCH_STRING = '1970-01-01T00:00:00Z';
// For reasons unclear to me, a straight up class definition with a constructor
// doesn't seem to work, reactively. So we resort to this.
@@ -15,7 +15,7 @@ function makeChannelObject({ id, name, draft = '', lastReadAt = null, scrollPosi
name,
lastReadAt: lastReadAt || DateTime.fromISO(EPOCH_STRING),
draft,
- scrollPosition,
+ scrollPosition
};
}
@@ -33,10 +33,7 @@ export class Channels {
}
addChannel(id, name) {
- this.channels = [
- ...this.channels,
- makeChannelObject({ id, name }),
- ];
+ this.channels = [...this.channels, makeChannelObject({ id, name })];
this.sort();
return this;
}
diff --git a/ui/lib/store/messages.svelte.js b/ui/lib/store/messages.svelte.js
index ba4c895..dadade6 100644
--- a/ui/lib/store/messages.svelte.js
+++ b/ui/lib/store/messages.svelte.js
@@ -5,7 +5,7 @@ import DOMPurify from 'dompurify';
const RUN_COALESCE_MAX_INTERVAL = 10 /* min */ * 60 /* sec */ * 1000; /* ms */
export class Messages {
- channels = $state({}); // Mapping<ChannelId, Message>
+ channels = $state({}); // Mapping<ChannelId, Message>
inChannel(channel) {
return this.channels[channel] || [];
diff --git a/ui/routes/(app)/+layout.svelte b/ui/routes/(app)/+layout.svelte
index 81324fd..cbfef54 100644
--- a/ui/routes/(app)/+layout.svelte
+++ b/ui/routes/(app)/+layout.svelte
@@ -41,7 +41,7 @@
let hasUnreads = lastMessageAt > ch.lastReadAt;
enrichedChannels.push({
...ch,
- hasUnreads,
+ hasUnreads
});
}
}
@@ -104,8 +104,20 @@
gesture.destroy();
}
});
+
+ function beforeUnload(evt) {
+ evt.preventDefault();
+ if (events !== null) {
+ events.close();
+ }
+ // For some compat reasons?
+ evt.returnValue = '';
+ return '';
+ }
</script>
+<svelte:window on:beforeunload={beforeUnload} />
+
<svelte:head>
<!-- TODO: unread count? -->
<title>pilcrow</title>
@@ -114,65 +126,15 @@
{#if loading}
<h2>Loading&hellip;</h2>
{:else}
- <div id="interface" class="p-2">
+ <div id="interface">
<nav id="sidebar" data-expanded={pageContext.showMenu}>
- <div class="channel-list">
- <ChannelList active={channel} channels={enrichedChannels} />
- </div>
+ <ChannelList active={channel} channels={enrichedChannels} />
<div class="create-channel">
<CreateChannelForm />
</div>
</nav>
- <main class="pl-4">
+ <main>
{@render children?.()}
</main>
</div>
{/if}
-
-<style>
- /* Just some global CSS variables, don't mind them.
- */
- :root {
- --app-bar-height: 48px;
- --input-row-height: 2rem;
- --interface-padding: 16px;
- }
-
- #interface {
- margin: unset;
- display: grid;
- grid-template:
- 'side main' 1fr
- / auto 1fr;
- height: calc(100vh - var(--app-bar-height));
-
- @media (width > 640px) {
- --overlay: static;
- --translate: 0;
- }
- }
- nav {
- grid-area: side;
- background-color: rgb(var(--color-surface-800));
- inset: auto auto 0 0;
- padding: 0.25rem;
- position: var(--overlay, absolute);
- transition: translate 300ms ease-out;
- width: 21rem;
- height: calc(100vh - var(--app-bar-height) - var(--interface-padding));
- z-index: 10;
- }
- main {
- grid-area: main;
- height: calc(100vh - var(--app-bar-height) - var(--interface-padding));
- }
- .channel-list {
- height: calc(
- 100vh - var(--app-bar-height) - var(--interface-padding) - var(--input-row-height)
- );
- overflow: auto;
- }
- nav[data-expanded='false'] {
- translate: var(--translate, -100% 0);
- }
-</style>
diff --git a/ui/routes/(app)/+page.svelte b/ui/routes/(app)/+page.svelte
index e69de29..007c5c6 100644
--- a/ui/routes/(app)/+page.svelte
+++ b/ui/routes/(app)/+page.svelte
@@ -0,0 +1,3 @@
+<div class="no-active-channel">
+ <span class="vertical-aligner"> Please select or create a channel. </span>
+</div>
diff --git a/ui/routes/(app)/ch/[channel]/+page.svelte b/ui/routes/(app)/ch/[channel]/+page.svelte
index 7d5b8cf..dbdb507 100644
--- a/ui/routes/(app)/ch/[channel]/+page.svelte
+++ b/ui/routes/(app)/ch/[channel]/+page.svelte
@@ -18,15 +18,17 @@
const elementTop = elRect.top;
const elementBottom = elRect.bottom;
- return ((parentTop < elementTop) && (parentBottom > elementBottom));
+ return parentTop < elementTop && parentBottom > elementBottom;
}
function getLastVisibleMessage() {
const parentElement = activeChannel;
const childElements = parentElement.getElementsByClassName('message');
- const lastInView = Array.from(childElements).reverse().find((el) => {
- return inView(parentElement, el);
- });
+ const lastInView = Array.from(childElements)
+ .reverse()
+ .find((el) => {
+ return inView(parentElement, el);
+ });
return lastInView;
}
@@ -50,14 +52,14 @@
});
function handleKeydown(event) {
- if (event.key === 'Escape') {
+ if (event.key === 'Escape') {
setLastRead(); // TODO: pass in "last message DT"?
}
}
let lastReadCallback = null;
function handleScroll() {
- clearTimeout(lastReadCallback); // Fine if lastReadCallback is null still.
+ clearTimeout(lastReadCallback); // Fine if lastReadCallback is null still.
lastReadCallback = setTimeout(setLastRead, 2 * 1000);
}
</script>
@@ -67,15 +69,6 @@
<div class="active-channel" on:scroll={handleScroll} bind:this={activeChannel}>
<ActiveChannel {messageRuns} />
</div>
-<div class="create-message max-h-full">
+<div class="create-message">
<MessageInput {channel} />
</div>
-
-<style>
- .active-channel {
- height: calc(
- 100vh - var(--app-bar-height) - var(--interface-padding) - var(--input-row-height)
- );
- overflow: auto;
- }
-</style>
diff --git a/ui/routes/(app)/me/+page.svelte b/ui/routes/(app)/me/+page.svelte
index aded292..14a9db8 100644
--- a/ui/routes/(app)/me/+page.svelte
+++ b/ui/routes/(app)/me/+page.svelte
@@ -4,14 +4,8 @@
import ChangePassword from '$lib/components/ChangePassword.svelte';
</script>
-<div class="mb-4">
- <ChangePassword />
-</div>
-
-<div class="mb-4">
- <Invites />
-</div>
-
-<div>
- <LogOut />
-</div>
+<ChangePassword />
+<hr />
+<Invites />
+<hr />
+<LogOut />
diff --git a/ui/routes/(login)/invite/[invite]/+page.svelte b/ui/routes/(login)/invite/[invite]/+page.svelte
index 4433bd6..132cbc1 100644
--- a/ui/routes/(login)/invite/[invite]/+page.svelte
+++ b/ui/routes/(login)/invite/[invite]/+page.svelte
@@ -25,11 +25,11 @@
</script>
{#await data.invite}
- <div class="card m-4 p-4">
+ <div class="invite-text">
<p>Loading invitation…</p>
</div>
{:then invite}
- <div class="card m-4 p-4">
+ <div class="invite-text">
<p>Hi there! {invite.issuer} invites you to the conversation.</p>
</div>
<LogIn {disabled} bind:username bind:password onsubmit={(event) => onSubmit(event, invite.id)} />
diff --git a/ui/routes/+layout.svelte b/ui/routes/+layout.svelte
index 26033e0..750f1f8 100644
--- a/ui/routes/+layout.svelte
+++ b/ui/routes/+layout.svelte
@@ -4,7 +4,6 @@
import '../app.css';
import logo from '$lib/assets/logo.png';
- import { AppBar } from '@skeletonlabs/skeleton';
import { currentUser } from '$lib/store';
let pageContext = $state({
@@ -24,20 +23,20 @@
let { children } = $props();
</script>
-<AppBar padding="px-4 pt-0 pb-4">
- <svelte:fragment slot="lead">
- <button onclick={toggleMenu} class="cursor-pointer">
- <img class="w-8 h-8" alt="logo" src={logo} />
+<div class="app-bar">
+ <div class="lead">
+ <button onclick={toggleMenu}>
+ <img alt="logo" src={logo} />
</button>
- </svelte:fragment>
+ </div>
<a href="/">pilcrow</a>
- <svelte:fragment slot="trail">
+ <div class="trail">
{#if $currentUser}
- <div class="rounded-full bg-secondary-400 px-3 py-1">
+ <div>
<a href="/me">@{$currentUser.username}</a>
</div>
{/if}
- </svelte:fragment>
-</AppBar>
+ </div>
+</div>
{@render children?.()}
diff --git a/ui/static/manifest.json b/ui/static/manifest.json
index 5d735d0..6677d94 100644
--- a/ui/static/manifest.json
+++ b/ui/static/manifest.json
@@ -4,7 +4,7 @@
"start_url": "/",
"display": "standalone",
"background_color": "#fdfdfd",
- "theme_color": "#2c3656",
+ "theme_color": "#211b2a",
"orientation": "portrait-primary",
"icons": [
{
diff --git a/ui/styles/active-channel.css b/ui/styles/active-channel.css
new file mode 100644
index 0000000..d6a9b42
--- /dev/null
+++ b/ui/styles/active-channel.css
@@ -0,0 +1,6 @@
+.active-channel {
+ padding-left: 1rem;
+ padding-right: 1rem;
+ overflow: auto;
+ flex-grow: 1;
+}
diff --git a/ui/styles/app-bar.css b/ui/styles/app-bar.css
new file mode 100644
index 0000000..dcc447a
--- /dev/null
+++ b/ui/styles/app-bar.css
@@ -0,0 +1,40 @@
+/* App Bar */
+.app-bar {
+ height: var(--app-bar-height);
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: stretch;
+ background-color: var(--colour-header-bg);
+}
+
+.app-bar > * {
+ display: inline-block;
+}
+
+.app-bar .lead {
+ flex-basis: 60px;
+}
+
+.app-bar .lead button {
+ padding: 0;
+ border: 0;
+}
+
+.app-bar .trail {
+ flex-basis: 60px;
+ line-height: var(--app-bar-height);
+}
+
+.app-bar > a {
+ line-height: var(--app-bar-height);
+}
+
+.app-bar a {
+ text-decoration: none;
+}
+
+.app-bar button,
+.app-bar button img {
+ height: var(--app-bar-height);
+}
diff --git a/ui/styles/app-layout.css b/ui/styles/app-layout.css
new file mode 100644
index 0000000..82d9914
--- /dev/null
+++ b/ui/styles/app-layout.css
@@ -0,0 +1,56 @@
+/* TODO: generally remove literals from this file. */
+
+#interface {
+ margin: unset;
+ display: grid;
+ grid-template:
+ 'side main' 1fr
+ / auto 1fr;
+ height: calc(100vh - var(--app-bar-height));
+
+ @media (width > 640px) {
+ --overlay: static;
+ --translate: 0;
+ }
+}
+
+nav#sidebar {
+ grid-area: side;
+ inset: auto auto 0 0;
+ padding-right: 0.5rem;
+ position: var(--overlay, absolute);
+ transition: translate 300ms ease-out;
+ width: var(--nav-width);
+ height: 100vh;
+ z-index: 10;
+
+ background-color: var(--colour-navbar-bg);
+
+ @media (width > 640px) {
+ height: calc(100vh - var(--app-bar-height));
+ }
+}
+
+nav.list-nav {
+ height: calc(100vh - var(--input-row-height) - var(--interface-padding));
+ overflow: auto;
+
+ @media (width > 640px) {
+ height: calc(
+ 100vh - var(--app-bar-height) - var(--input-row-height) - var(--interface-padding)
+ );
+ }
+}
+
+main {
+ grid-area: main;
+ height: calc(100vh - var(--app-bar-height));
+}
+
+main textarea {
+ resize: none;
+}
+
+nav[data-expanded='false'] {
+ translate: var(--translate, -100% 0);
+}
diff --git a/ui/styles/forms.css b/ui/styles/forms.css
new file mode 100644
index 0000000..1d6421b
--- /dev/null
+++ b/ui/styles/forms.css
@@ -0,0 +1,21 @@
+label {
+ display: block;
+ padding: 0.25rem;
+ font-style: italic;
+}
+
+label input {
+ display: block;
+ width: 90%;
+ padding: 0.25rem;
+ border-radius: 0.25rem;
+ border: 1px solid var(--colour-input-border);
+}
+
+form.form > button {
+ background-color: var(--colour-input-bg);
+ padding: 0.25rem;
+ border-radius: 0.25rem;
+ border: 1px solid var(--colour-input-border);
+ margin: 0.25rem;
+}
diff --git a/ui/styles/invites.css b/ui/styles/invites.css
new file mode 100644
index 0000000..9cd3fd4
--- /dev/null
+++ b/ui/styles/invites.css
@@ -0,0 +1,11 @@
+.invite-list {
+ padding: 0.25rem;
+}
+
+.invite-url-literal {
+ font-family: monospace;
+}
+
+.invite-text {
+ margin: 1rem;
+}
diff --git a/ui/styles/messages.css b/ui/styles/messages.css
new file mode 100644
index 0000000..a07c5d9
--- /dev/null
+++ b/ui/styles/messages.css
@@ -0,0 +1,121 @@
+.message-run {
+ position: relative;
+ border-radius: 0.25rem;
+ padding: 0 0 0.5rem 0;
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ box-shadow: 0 0.25rem 0.25rem rgba(0, 0, 0, 0.5);
+ overflow: hidden;
+}
+
+.own-message {
+ background-color: var(--colour-message-run-self-bg);
+ border: 1px solid var(--colour-message-run-self-border);
+ margin-left: 2rem;
+}
+
+.own-message * {
+ color: var(--colour-message-run-self-text);
+}
+
+.other-message {
+ background-color: var(--colour-message-run-other-bg);
+ border: 1px solid var(--colour-message-run-other-border);
+ margin-right: 2rem;
+}
+
+.other-message * {
+ color: var(--colour-message-run-other-text);
+}
+
+.message-run > .username {
+ background-color: var(--colour-message-run-username-bg);
+ color: var(--colour-message-run-username-text);
+ display: inline-block;
+ border-bottom-right-radius: 0.25rem;
+ padding: 0.25rem;
+ border-bottom: 1px solid var(--colour-message-run-username-border);
+ border-right: 1px solid var(--colour-message-run-username-border);
+}
+
+.message {
+ padding: 0.5rem 0 0 0.5rem;
+ position: relative;
+}
+
+.message.delete-armed,
+.message.delete-armed:hover {
+ background-color: var(--colour-warn);
+}
+
+.message:hover {
+ background-color: var(--colour-message-hover-bg);
+}
+.message:hover * {
+ color: var(--colour-message-hover-text);
+}
+
+.message .handle {
+ --text-size: 0.75rem;
+ float: right;
+ line-height: var(--text-size);
+ font-size: var(--text-size);
+ top: -0.75rem;
+ right: 0.5rem;
+ position: absolute;
+ padding: 0.25rem;
+ border-radius: 0.25rem;
+ display: none;
+ background-color: var(--colour-message-handle-bg);
+ color: var(--colour-message-handle-text);
+ border: 1px solid var(--colour-message-handle-border);
+}
+
+.message:hover .handle {
+ display: flex;
+}
+
+.message .handle button {
+ line-height: 0.35rem;
+ background: none;
+ border: none;
+ cursor: pointer;
+}
+
+.message-body {
+ overflow: auto;
+ max-width: 80vw;
+
+ @media (width > 640px) {
+ /* 21rem is width of the nav bar in full-screen mode. */
+ max-width: calc(90vw - 21rem);
+ }
+}
+
+.message-body:empty:after {
+ content: '.';
+ visibility: hidden;
+}
+
+/* For rendered message bodies: */
+.message-body blockquote {
+ margin-left: 0.25rem;
+ padding-left: 0.5rem;
+ border-left: 2px solid grey;
+ border-radius: 0.125rem;
+}
+
+.message-body blockquote * {
+ color: grey;
+}
+
+.message-body pre {
+ border: 1px solid #312e81;
+ border-radius: 0.25rem;
+ background-color: var(--colour-message-run-text);
+ padding: 0.25rem;
+}
+
+.message-body code {
+ font-family: monospace;
+}
diff --git a/ui/styles/overscroll.css b/ui/styles/overscroll.css
new file mode 100644
index 0000000..8898f9a
--- /dev/null
+++ b/ui/styles/overscroll.css
@@ -0,0 +1,9 @@
+/* This should help minimize swipe-to-go-back behaviour, enabling our
+* swipe-to-reveal-channel-menu behaviour. It won't work in all cases; in iOS
+* Safari, when swiping from the screen edge, the OS gets th event and
+* handles it before the browser does.
+*/
+html,
+body {
+ overscroll-behavior-x: none;
+}
diff --git a/ui/styles/reset.css b/ui/styles/reset.css
new file mode 100644
index 0000000..a3f7681
--- /dev/null
+++ b/ui/styles/reset.css
@@ -0,0 +1,129 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+
+html,
+body,
+div,
+span,
+applet,
+object,
+iframe,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+blockquote,
+pre,
+a,
+abbr,
+acronym,
+address,
+big,
+cite,
+code,
+del,
+dfn,
+em,
+img,
+ins,
+kbd,
+q,
+s,
+samp,
+small,
+strike,
+strong,
+sub,
+sup,
+tt,
+var,
+b,
+u,
+i,
+center,
+dl,
+dt,
+dd,
+ol,
+ul,
+li,
+fieldset,
+form,
+label,
+legend,
+table,
+caption,
+tbody,
+tfoot,
+thead,
+tr,
+th,
+td,
+article,
+aside,
+canvas,
+details,
+embed,
+figure,
+figcaption,
+footer,
+header,
+hgroup,
+menu,
+nav,
+output,
+ruby,
+section,
+summary,
+time,
+mark,
+audio,
+video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+menu,
+nav,
+section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol,
+ul {
+ list-style: none;
+}
+blockquote,
+q {
+ quotes: none;
+}
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+ content: '';
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
diff --git a/ui/styles/sidebar.css b/ui/styles/sidebar.css
new file mode 100644
index 0000000..5e5e16a
--- /dev/null
+++ b/ui/styles/sidebar.css
@@ -0,0 +1,85 @@
+/* Sidebar and channel selector */
+#sidebar {
+ background-color: var(--colour-navbar-bg);
+}
+
+.list-nav a {
+ text-decoration: none;
+}
+
+.list-nav ul {
+ padding: 0.5rem;
+}
+
+.list-nav li {
+ padding: 0.5rem;
+ border-radius: 0.5rem;
+ border: 1px solid var(--colour-navbar-border);
+ margin: 0.25rem;
+}
+
+.list-nav li.active {
+ background-color: var(--colour-navbar-active-bg);
+ color: var(--colour-navbar-active-text);
+}
+
+.list-nav li:hover {
+ background-color: var(--colour-navbar-hover-bg);
+ color: var(--colour-navbar-hover-text);
+}
+
+/* create channel form */
+.create-channel {
+ padding-left: 0.5rem;
+}
+
+.create-channel form {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: stretch;
+}
+
+.create-channel input {
+ padding: 0.5rem;
+ border-radius: 0.5rem 0 0 0.5rem;
+ border: 1px solid var(--colour-input-border);
+ z-index: 1; /* Just to make the focus-active border go over the following button. */
+ flex-grow: 1;
+ background-color: var(--colour-input-bg);
+ color: var(--colour-input-text);
+}
+
+.create-channel button {
+ border-radius: 0 0.5rem 0.5rem 0;
+ border: 1px solid var(--colour-input-border);
+ background-color: var(--colour-input-bg);
+ color: var(--colour-input-text);
+}
+
+.badge {
+ --dimensions: 1.25rem;
+ display: inline-block;
+
+ width: var(--dimensions);
+ height: var(--dimensions);
+ border-radius: var(--dimensions);
+ line-height: var(--dimensions);
+ text-align: center;
+}
+
+.badge.has-unreads {
+ /* TODO: Obvs this is a placeholder */
+ border: 1px solid mediumaquamarine;
+ background-color: lightgreen;
+ color: black;
+}
+
+.badge.has-no-unreads {
+ /* TODO: Obvs this is a placeholder */
+ border: 1px solid bisque;
+ background-color: antiquewhite;
+ color: black;
+}
+
+/* TODO: media-query stuff. Margin-left at a constant zero? */
diff --git a/ui/styles/textarea.css b/ui/styles/textarea.css
new file mode 100644
index 0000000..c38de46
--- /dev/null
+++ b/ui/styles/textarea.css
@@ -0,0 +1,31 @@
+/* Message input */
+.create-message form {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: stretch;
+}
+
+.create-message textarea {
+ padding: 0.5rem;
+ border-radius: 0.5rem 0 0 0.5rem;
+ border: 1px solid var(--colour-input-border);
+ z-index: 1; /* Just to make the focus-active border go over the following button. */
+ flex-grow: 1;
+ background-color: var(--colour-input-bg);
+ color: var(--colour-input-text);
+}
+
+.create-message button {
+ border-radius: 0 0.5rem 0.5rem 0;
+ border: 1px solid var(--colour-input-border);
+ background-color: var(--colour-input-bg);
+ color: var(--colour-input-text);
+}
+
+main {
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-start;
+ align-items: stretch;
+}
diff --git a/ui/styles/variables.css b/ui/styles/variables.css
new file mode 100644
index 0000000..80817f3
--- /dev/null
+++ b/ui/styles/variables.css
@@ -0,0 +1,72 @@
+:root {
+ /*
+ * Not great that these are in px, but not sure what else to do.
+ */
+ --app-bar-height: 48px;
+ --input-row-height: 2rem;
+ --interface-padding: 16px;
+ --nav-width: 21rem;
+
+ /* coloUrs */
+ --colour-okay: #6a994e;
+ --colour-warn: #ebc3be;
+ --colour-error: #de5f55;
+
+ /* I dunno, I liked this colour: */
+ --colour-base: rgb(121, 96, 159);
+
+ /* Light text is a bit hard to read; I may need to adjust it. */
+ --light-text: color-mix(in srgb, var(--colour-base) 40%, white);
+ --dark-text: color-mix(in srgb, var(--colour-base) 40%, black);
+
+ /* Header */
+ --colour-header-bg: color-mix(in srgb, var(--colour-base) 30%, black);
+ --colour-header-border: color-mix(in srgb, var(--colour-header-bg) 50%, black);
+ --colour-header-text: var(--light-text);
+
+ /* Navbar */
+ --colour-navbar-bg: color-mix(in srgb, var(--colour-base) 50%, black);
+ --colour-navbar-border: color-mix(in srgb, var(--colour-navbar-bg) 50%, black);
+ --colour-navbar-text: var(--light-text);
+ --colour-navbar-active-bg: color-mix(in srgb, var(--colour-navbar-bg) 40%, white);
+ --colour-navbar-active-text: color-mix(in srgb, var(--colour-navbar-bg) 40%, black);
+ --colour-navbar-hover-bg: color-mix(in srgb, var(--colour-navbar-bg) 30%, white);
+ --colour-navbar-hover-text: color-mix(in srgb, var(--colour-navbar-bg) 30%, black);
+
+ /* Input */
+ --colour-input-bg: color-mix(in srgb, var(--colour-base) 10%, white);
+ --colour-input-border: color-mix(in srgb, var(--colour-input-bg) 50%, black);
+ --colour-input-text: var(--dark-text);
+
+ /* Active channel */
+ --colour-active-channel-bg: color-mix(in srgb, var(--colour-base) 25%, white);
+
+ /* MessageRun */
+ --colour-message-run-self-bg: color-mix(in srgb, var(--colour-base) 30%, white);
+ --colour-message-run-self-border: color-mix(
+ in srgb,
+ var(--colour-message-run-self-bg) 50%,
+ black
+ );
+ --colour-message-run-other-bg: color-mix(in srgb, var(--colour-base) 50%, white);
+ --colour-message-run-other-border: color-mix(
+ in srgb,
+ var(--colour-message-run-other-bg) 50%,
+ black
+ );
+ --colour-message-run-self-text: var(--dark-text);
+ --colour-message-run-other-text: var(--dark-text);
+
+ --colour-message-run-username-bg: color-mix(in srgb, var(--colour-base) 70%, white);
+ --colour-message-run-username-border: color-mix(in srgb, var(--colour-base) 50%, black);
+ --colour-message-run-username-text: color-mix(in srgb, var(--colour-base) 50%, black);
+
+ /* Message */
+ --colour-message-hover-bg: color-mix(in srgb, var(--colour-base) 70%, white);
+ --colour-message-hover-text: var(--dark-text);
+
+ /* Message handle */
+ --colour-message-handle-bg: color-mix(in srgb, var(--colour-base) 90%, black);
+ --colour-message-handle-border: color-mix(in srgb, var(--colour-message-handle-bg) 50%, black);
+ --colour-message-handle-text: var(--dark-text);
+}