Avivash/58 improve homepage UI(does not include 404 or User Settings) (#83)
|
|
@ -17,8 +17,10 @@
|
|||
"@sveltejs/adapter-static": "1.0.0-next.43",
|
||||
"@sveltejs/kit": "1.0.0-next.489",
|
||||
"@tailwindcss/typography": "^0.5.2",
|
||||
"@types/qrcode-svg": "^1.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"ava": "^4.3.1",
|
||||
"daisyui": "^2.0.2",
|
||||
"eslint": "^7.32.0",
|
||||
|
|
@ -32,7 +34,7 @@
|
|||
"svelte-check": "^2.0.0",
|
||||
"svelte-preprocess": "^4.0.0",
|
||||
"svelte-seo": "^1.2.1",
|
||||
"tailwindcss": "^3.0.22",
|
||||
"tailwindcss": "^3.2.1",
|
||||
"ts-node": "^10.4.0",
|
||||
"tsconfig-paths": "^3.12.0",
|
||||
"tslib": "^2.0.0",
|
||||
|
|
@ -637,6 +639,12 @@
|
|||
"integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/qrcode-svg": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/qrcode-svg/-/qrcode-svg-1.1.1.tgz",
|
||||
"integrity": "sha512-uTuEgFXMknpun//Jj6b1R8T8LiMi9fNpH+cnhZr4b7col2HHTMmjYfm/WOZ7nzjuGpk+oTrpHhePe1qlWtHWTA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/sass": {
|
||||
"version": "1.43.1",
|
||||
"integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==",
|
||||
|
|
@ -1010,8 +1018,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/autoprefixer": {
|
||||
"version": "10.4.7",
|
||||
"integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==",
|
||||
"version": "10.4.13",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
|
||||
"integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1023,10 +1032,9 @@
|
|||
"url": "https://tidelift.com/funding/github/npm/autoprefixer"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"browserslist": "^4.20.3",
|
||||
"caniuse-lite": "^1.0.30001335",
|
||||
"browserslist": "^4.21.4",
|
||||
"caniuse-lite": "^1.0.30001426",
|
||||
"fraction.js": "^4.2.0",
|
||||
"normalize-range": "^0.1.2",
|
||||
"picocolors": "^1.0.0",
|
||||
|
|
@ -1371,8 +1379,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/browserslist": {
|
||||
"version": "4.21.2",
|
||||
"integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
|
||||
"version": "4.21.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
|
||||
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1384,12 +1393,11 @@
|
|||
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001366",
|
||||
"electron-to-chromium": "^1.4.188",
|
||||
"caniuse-lite": "^1.0.30001400",
|
||||
"electron-to-chromium": "^1.4.251",
|
||||
"node-releases": "^2.0.6",
|
||||
"update-browserslist-db": "^1.0.4"
|
||||
"update-browserslist-db": "^1.0.9"
|
||||
},
|
||||
"bin": {
|
||||
"browserslist": "cli.js"
|
||||
|
|
@ -1454,8 +1462,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001366",
|
||||
"integrity": "sha512-yy7XLWCubDobokgzudpkKux8e0UOOnLHE6mlNJBzT3lZJz6s5atSEzjoL+fsCPkI0G8MP5uVdDx1ur/fXEWkZA==",
|
||||
"version": "1.0.30001429",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz",
|
||||
"integrity": "sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -1466,8 +1475,7 @@
|
|||
"type": "tidelift",
|
||||
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
|
||||
}
|
||||
],
|
||||
"peer": true
|
||||
]
|
||||
},
|
||||
"node_modules/catering": {
|
||||
"version": "2.1.1",
|
||||
|
|
@ -2087,10 +2095,10 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.189",
|
||||
"integrity": "sha512-dQ6Zn4ll2NofGtxPXaDfY2laIa6NyCQdqXYHdwH90GJQW0LpJJib0ZU/ERtbb0XkBEmUD2eJtagbOie3pdMiPg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"version": "1.4.284",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/emittery": {
|
||||
"version": "0.11.0",
|
||||
|
|
@ -2768,8 +2776,9 @@
|
|||
"integrity": "sha512-Kl29QoNbNvn4nhDsLYjyIAaIqaJB6rBx5p3sL9VjaefJ+eMFBWVZiaoguaoZfzEKr5RhAti0UgM8703akGPJ6g=="
|
||||
},
|
||||
"node_modules/fast-glob": {
|
||||
"version": "3.2.11",
|
||||
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
|
||||
"version": "3.2.12",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
|
||||
"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
|
|
@ -2945,7 +2954,6 @@
|
|||
"version": "4.2.0",
|
||||
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
|
|
@ -4348,9 +4356,9 @@
|
|||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
|
||||
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nofilter": {
|
||||
"version": "3.1.0",
|
||||
|
|
@ -4373,7 +4381,6 @@
|
|||
"version": "0.1.2",
|
||||
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -4622,9 +4629,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.4.16",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
|
||||
"integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
|
||||
"version": "8.4.18",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
|
||||
"integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -4708,11 +4715,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/postcss-nested": {
|
||||
"version": "5.0.6",
|
||||
"integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz",
|
||||
"integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"postcss-selector-parser": "^6.0.6"
|
||||
"postcss-selector-parser": "^6.0.10"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0"
|
||||
|
|
@ -4727,6 +4735,7 @@
|
|||
},
|
||||
"node_modules/postcss-selector-parser": {
|
||||
"version": "6.0.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
|
|
@ -5655,8 +5664,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.1.6",
|
||||
"integrity": "sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.1.tgz",
|
||||
"integrity": "sha512-Uw+GVSxp5CM48krnjHObqoOwlCt5Qo6nw1jlCRwfGy68dSYb/LwS9ZFidYGRiM+w6rMawkZiu1mEMAsHYAfoLg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"arg": "^5.0.2",
|
||||
|
|
@ -5665,18 +5675,19 @@
|
|||
"detective": "^5.2.1",
|
||||
"didyoumean": "^1.2.2",
|
||||
"dlv": "^1.1.3",
|
||||
"fast-glob": "^3.2.11",
|
||||
"fast-glob": "^3.2.12",
|
||||
"glob-parent": "^6.0.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"lilconfig": "^2.0.5",
|
||||
"lilconfig": "^2.0.6",
|
||||
"micromatch": "^4.0.5",
|
||||
"normalize-path": "^3.0.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss": "^8.4.17",
|
||||
"postcss-import": "^14.1.0",
|
||||
"postcss-js": "^4.0.0",
|
||||
"postcss-load-config": "^3.1.4",
|
||||
"postcss-nested": "5.0.6",
|
||||
"postcss-nested": "6.0.0",
|
||||
"postcss-selector-parser": "^6.0.10",
|
||||
"postcss-value-parser": "^4.2.0",
|
||||
"quick-lru": "^5.1.1",
|
||||
|
|
@ -5912,8 +5923,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.0.4",
|
||||
"integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==",
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
||||
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -5925,7 +5937,6 @@
|
|||
"url": "https://tidelift.com/funding/github/npm/browserslist"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"escalade": "^3.1.1",
|
||||
"picocolors": "^1.0.0"
|
||||
|
|
@ -5947,6 +5958,7 @@
|
|||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true
|
||||
},
|
||||
|
|
@ -6694,6 +6706,12 @@
|
|||
"integrity": "sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/qrcode-svg": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/qrcode-svg/-/qrcode-svg-1.1.1.tgz",
|
||||
"integrity": "sha512-uTuEgFXMknpun//Jj6b1R8T8LiMi9fNpH+cnhZr4b7col2HHTMmjYfm/WOZ7nzjuGpk+oTrpHhePe1qlWtHWTA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/sass": {
|
||||
"version": "1.43.1",
|
||||
"integrity": "sha512-BPdoIt1lfJ6B7rw35ncdwBZrAssjcwzI5LByIrYs+tpXlj/CAkuVdRsgZDdP4lq5EjyWzwxZCqAoFyHKFwp32g==",
|
||||
|
|
@ -6925,13 +6943,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"autoprefixer": {
|
||||
"version": "10.4.7",
|
||||
"integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==",
|
||||
"version": "10.4.13",
|
||||
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz",
|
||||
"integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"browserslist": "^4.20.3",
|
||||
"caniuse-lite": "^1.0.30001335",
|
||||
"browserslist": "^4.21.4",
|
||||
"caniuse-lite": "^1.0.30001426",
|
||||
"fraction.js": "^4.2.0",
|
||||
"normalize-range": "^0.1.2",
|
||||
"picocolors": "^1.0.0",
|
||||
|
|
@ -7163,15 +7181,15 @@
|
|||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.21.2",
|
||||
"integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
|
||||
"version": "4.21.4",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
|
||||
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001366",
|
||||
"electron-to-chromium": "^1.4.188",
|
||||
"caniuse-lite": "^1.0.30001400",
|
||||
"electron-to-chromium": "^1.4.251",
|
||||
"node-releases": "^2.0.6",
|
||||
"update-browserslist-db": "^1.0.4"
|
||||
"update-browserslist-db": "^1.0.9"
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
|
|
@ -7204,10 +7222,10 @@
|
|||
"dev": true
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001366",
|
||||
"integrity": "sha512-yy7XLWCubDobokgzudpkKux8e0UOOnLHE6mlNJBzT3lZJz6s5atSEzjoL+fsCPkI0G8MP5uVdDx1ur/fXEWkZA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"version": "1.0.30001429",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz",
|
||||
"integrity": "sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg==",
|
||||
"dev": true
|
||||
},
|
||||
"catering": {
|
||||
"version": "2.1.1",
|
||||
|
|
@ -7661,10 +7679,10 @@
|
|||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.4.189",
|
||||
"integrity": "sha512-dQ6Zn4ll2NofGtxPXaDfY2laIa6NyCQdqXYHdwH90GJQW0LpJJib0ZU/ERtbb0XkBEmUD2eJtagbOie3pdMiPg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"version": "1.4.284",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
|
||||
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
|
||||
"dev": true
|
||||
},
|
||||
"emittery": {
|
||||
"version": "0.11.0",
|
||||
|
|
@ -8069,8 +8087,9 @@
|
|||
"integrity": "sha512-Kl29QoNbNvn4nhDsLYjyIAaIqaJB6rBx5p3sL9VjaefJ+eMFBWVZiaoguaoZfzEKr5RhAti0UgM8703akGPJ6g=="
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "3.2.11",
|
||||
"integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
|
||||
"version": "3.2.12",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
|
||||
"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
|
|
@ -8201,8 +8220,7 @@
|
|||
"fraction.js": {
|
||||
"version": "4.2.0",
|
||||
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
|
|
@ -9238,9 +9256,9 @@
|
|||
},
|
||||
"node-releases": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
|
||||
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"nofilter": {
|
||||
"version": "3.1.0",
|
||||
|
|
@ -9256,8 +9274,7 @@
|
|||
"normalize-range": {
|
||||
"version": "0.1.2",
|
||||
"integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
|
||||
"dev": true,
|
||||
"peer": true
|
||||
"dev": true
|
||||
},
|
||||
"object-hash": {
|
||||
"version": "3.0.0",
|
||||
|
|
@ -9418,9 +9435,9 @@
|
|||
}
|
||||
},
|
||||
"postcss": {
|
||||
"version": "8.4.16",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz",
|
||||
"integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==",
|
||||
"version": "8.4.18",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.18.tgz",
|
||||
"integrity": "sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"nanoid": "^3.3.4",
|
||||
|
|
@ -9456,15 +9473,17 @@
|
|||
}
|
||||
},
|
||||
"postcss-nested": {
|
||||
"version": "5.0.6",
|
||||
"integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz",
|
||||
"integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"postcss-selector-parser": "^6.0.6"
|
||||
"postcss-selector-parser": "^6.0.10"
|
||||
}
|
||||
},
|
||||
"postcss-selector-parser": {
|
||||
"version": "6.0.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
|
@ -10072,8 +10091,9 @@
|
|||
}
|
||||
},
|
||||
"tailwindcss": {
|
||||
"version": "3.1.6",
|
||||
"integrity": "sha512-7skAOY56erZAFQssT1xkpk+kWt2NrO45kORlxFPXUt3CiGsVPhH1smuH5XoDH6sGPXLyBv+zgCKA2HWBsgCytg==",
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.1.tgz",
|
||||
"integrity": "sha512-Uw+GVSxp5CM48krnjHObqoOwlCt5Qo6nw1jlCRwfGy68dSYb/LwS9ZFidYGRiM+w6rMawkZiu1mEMAsHYAfoLg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"arg": "^5.0.2",
|
||||
|
|
@ -10082,18 +10102,19 @@
|
|||
"detective": "^5.2.1",
|
||||
"didyoumean": "^1.2.2",
|
||||
"dlv": "^1.1.3",
|
||||
"fast-glob": "^3.2.11",
|
||||
"fast-glob": "^3.2.12",
|
||||
"glob-parent": "^6.0.2",
|
||||
"is-glob": "^4.0.3",
|
||||
"lilconfig": "^2.0.5",
|
||||
"lilconfig": "^2.0.6",
|
||||
"micromatch": "^4.0.5",
|
||||
"normalize-path": "^3.0.0",
|
||||
"object-hash": "^3.0.0",
|
||||
"picocolors": "^1.0.0",
|
||||
"postcss": "^8.4.14",
|
||||
"postcss": "^8.4.17",
|
||||
"postcss-import": "^14.1.0",
|
||||
"postcss-js": "^4.0.0",
|
||||
"postcss-load-config": "^3.1.4",
|
||||
"postcss-nested": "5.0.6",
|
||||
"postcss-nested": "6.0.0",
|
||||
"postcss-selector-parser": "^6.0.10",
|
||||
"postcss-value-parser": "^4.2.0",
|
||||
"quick-lru": "^5.1.1",
|
||||
|
|
@ -10256,10 +10277,10 @@
|
|||
"integrity": "sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g=="
|
||||
},
|
||||
"update-browserslist-db": {
|
||||
"version": "1.0.4",
|
||||
"integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==",
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
|
||||
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"requires": {
|
||||
"escalade": "^3.1.1",
|
||||
"picocolors": "^1.0.0"
|
||||
|
|
@ -10275,6 +10296,7 @@
|
|||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true
|
||||
},
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@
|
|||
"@sveltejs/adapter-static": "1.0.0-next.43",
|
||||
"@sveltejs/kit": "1.0.0-next.489",
|
||||
"@tailwindcss/typography": "^0.5.2",
|
||||
"@types/qrcode-svg": "^1.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"ava": "^4.3.1",
|
||||
"daisyui": "^2.0.2",
|
||||
"eslint": "^7.32.0",
|
||||
|
|
@ -30,7 +32,7 @@
|
|||
"svelte-check": "^2.0.0",
|
||||
"svelte-preprocess": "^4.0.0",
|
||||
"svelte-seo": "^1.2.1",
|
||||
"tailwindcss": "^3.0.22",
|
||||
"tailwindcss": "^3.2.1",
|
||||
"ts-node": "^10.4.0",
|
||||
"tsconfig-paths": "^3.12.0",
|
||||
"tslib": "^2.0.0",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
},
|
||||
};
|
||||
plugins: [require('tailwindcss'), require('autoprefixer')]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<script lang="ts">
|
||||
import { themeStore } from '../stores'
|
||||
|
||||
/**
|
||||
* Firefox doesn't fully support background-clip so the marquee text is cut off half way through the animation
|
||||
*/
|
||||
const isFirefox = navigator.userAgent.indexOf('Firefox') !== -1
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="fixed z-0 lg:z-20 right-0 bottom-0 left-0 h-8 flex items-center motion-reduce:justify-center motion-safe:justify-end bg-base-content overflow-x-hidden"
|
||||
>
|
||||
{#if $themeStore === 'light'}
|
||||
<p
|
||||
class="motion-safe:animate-marquee motion-safe:left-full whitespace-nowrap font-bold text-xxs {isFirefox
|
||||
? 'text-orange-500'
|
||||
: 'text-transparent bg-clip-text bg-gradient-to-r from-orange-600 to-orange-300'}"
|
||||
>
|
||||
*** Experimental *** - You are currently previewing Webnative SDK Alpha
|
||||
0.2
|
||||
</p>
|
||||
{:else}
|
||||
<p
|
||||
class="motion-safe:animate-marquee motion-safe:left-full whitespace-nowrap font-bold text-xxs text-[#DD1F13]"
|
||||
>
|
||||
*** Experimental *** - You are currently previewing Webnative SDK Alpha
|
||||
0.2
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -1,11 +1,14 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
|
||||
import { appName } from '$lib/app-info'
|
||||
import { page } from '$app/stores'
|
||||
import { sessionStore, themeStore } from '../stores'
|
||||
import { storeTheme, type Theme } from '$lib/theme'
|
||||
import Brand from '$components/icons/Brand.svelte'
|
||||
import AlphaTag from '$components/nav/AlphaTag.svelte'
|
||||
import Avatar from '$components/settings/Avatar.svelte'
|
||||
import BrandLogo from '$components/icons/BrandLogo.svelte'
|
||||
import BrandWordmark from '$components/icons/BrandWordmark.svelte'
|
||||
import DarkMode from '$components/icons/DarkMode.svelte'
|
||||
import Hamburger from '$components/icons/Hamburger.svelte'
|
||||
import LightMode from '$components/icons/LightMode.svelte'
|
||||
import Shield from '$components/icons/Shield.svelte'
|
||||
|
||||
|
|
@ -13,33 +16,69 @@
|
|||
themeStore.set(newTheme)
|
||||
storeTheme(newTheme)
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<header class="navbar bg-base-100 pt-0">
|
||||
<div class="flex-1 cursor-pointer hover:underline" on:click={() => goto('/')}>
|
||||
<Brand />
|
||||
<span class="text-xl ml-2 hidden md:inline">{appName}</span>
|
||||
<header class="navbar flex bg-base-100 pt-4">
|
||||
<div class="lg:hidden">
|
||||
{#if $sessionStore.authed}
|
||||
<label
|
||||
for="sidebar-nav"
|
||||
class="drawer-button cursor-pointer -translate-x-2"
|
||||
>
|
||||
<Hamburger />
|
||||
</label>
|
||||
{:else}
|
||||
<div
|
||||
class="flex items-center cursor-pointer gap-3"
|
||||
on:click={() => goto('/')}
|
||||
>
|
||||
<BrandLogo />
|
||||
<AlphaTag />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<!-- Even if the user is not authed, render this header in the connection flow -->
|
||||
{#if !$sessionStore.authed || $page.url.pathname.match(/register|backup|delegate/)}
|
||||
<div
|
||||
class="hidden lg:flex flex-1 items-center cursor-pointer gap-3"
|
||||
on:click={() => goto('/')}
|
||||
>
|
||||
<BrandLogo />
|
||||
<div class="hidden lg:inline-block">
|
||||
<BrandWordmark />
|
||||
</div>
|
||||
<div class="hidden sm:inline-block">
|
||||
<AlphaTag />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="ml-auto">
|
||||
{#if !$sessionStore.loading && !$sessionStore.authed}
|
||||
<div class="flex-none">
|
||||
<a class="btn btn-sm h-10 btn-primary normal-case" href="/connect">
|
||||
Connect
|
||||
</a>
|
||||
<a class="btn btn-primary btn-sm !h-10" href="/connect">Connect</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if !$sessionStore.loading && $sessionStore.backupCreated === false}
|
||||
<span
|
||||
on:click={() => goto('/delegate-account')}
|
||||
class="btn btn-sm h-10 btn-warning rounded-full font-normal transition-colors ease-in hover:bg-orange-500 hover:border-orange-500"
|
||||
class="btn btn-sm h-10 btn-warning rounded-full bg-orange-300 border-2 border-neutral font-semiBold text-neutral transition-colors ease-in hover:bg-orange-300"
|
||||
>
|
||||
<span class="mr-2">Backup recommended</span>
|
||||
<Shield />
|
||||
<span class="ml-2 hidden md:block">Backup recommended</span>
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
<span class="ml-2">
|
||||
{#if $sessionStore.authed}
|
||||
<a href="/settings" class="ml-2 cursor-pointer">
|
||||
<Avatar size="small" />
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
<span class="ml-2 cursor-pointer">
|
||||
{#if $themeStore === 'light'}
|
||||
<span on:click={() => setTheme('dark')}>
|
||||
<LightMode />
|
||||
|
|
@ -50,4 +89,5 @@
|
|||
</span>
|
||||
{/if}
|
||||
</span>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<div
|
||||
class="min-h-[calc(100vh-128px)] md:min-h-[calc(100vh-160px)] pt-8 md:pt-16 flex flex-col items-start max-w-[690px] m-auto gap-10 pb-5 text-sm"
|
||||
>
|
||||
<h1 class="text-xl">About This Template</h1>
|
||||
|
||||
<div class="max-w-[573px]">
|
||||
<p class="mb-5">
|
||||
<a
|
||||
class="link link-primary whitespace-nowrap"
|
||||
href="https://github.com/fission-codes/webnative"
|
||||
target="_blank"
|
||||
>
|
||||
Webnative SDK
|
||||
<span class="-scale-x-100 scale-y-100 inline-block">⎋</span>
|
||||
</a>
|
||||
is a true local-first edge computing stack.
|
||||
</p>
|
||||
<p>
|
||||
You can fork this
|
||||
<a
|
||||
class="link link-primary whitespace-nowrap"
|
||||
href="https://github.com/webnative-examples/webnative-app-template"
|
||||
target="_blank"
|
||||
>
|
||||
template
|
||||
<span class="-scale-x-100 scale-y-100 inline-block">⎋</span>
|
||||
</a>
|
||||
to start writing your own Webnative app. Learn more in the
|
||||
<a
|
||||
class="link link-primary whitespace-nowrap"
|
||||
href="https://guide.fission.codes/"
|
||||
target="_blank"
|
||||
>
|
||||
Webnative Guide
|
||||
<span class="-scale-x-100 scale-y-100 inline-block">⎋</span>
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -18,16 +18,15 @@
|
|||
|
||||
<input type="checkbox" id="are-you-sure-modal" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<div class="modal-box w-narrowModal relative text-center">
|
||||
<div>
|
||||
<h3 class="mb-7 text-xl font-serif">Are you sure?</h3>
|
||||
<h3 class="mb-8 text-base">Are you sure?</h3>
|
||||
|
||||
<p class="mt-8 mb-6">
|
||||
<p class="mb-7 text-left">
|
||||
Without a backup device, if you lose this device or reset your browser,
|
||||
you will not be able to recover your account data.
|
||||
</p>
|
||||
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
on:click={() => goto('/delegate-account')}
|
||||
|
|
@ -35,7 +34,7 @@
|
|||
Connect a backup device
|
||||
</button>
|
||||
<span
|
||||
class="text-error underline block mt-4 cursor-pointer"
|
||||
class="text-error underline block mt-4 text-sm text-red-600 cursor-pointer"
|
||||
on:click={skipBackup}
|
||||
>
|
||||
YOLO—I'll risk just one device for now
|
||||
|
|
|
|||
|
|
@ -14,18 +14,16 @@
|
|||
|
||||
<input type="checkbox" id="backup-modal" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<div class="modal-box w-narrowModal relative text-center">
|
||||
<div id="backup-message" class="peer-checked:hidden">
|
||||
<h3 class="mb-7 text-xl font-serif">Backup your account</h3>
|
||||
<p class="mt-8 mb-4">
|
||||
<h3 class="mb-8 text-base">Backup your account</h3>
|
||||
<p class="mb-5 text-left">
|
||||
Your {appName} account & its data live only on your devices.
|
||||
</p>
|
||||
|
||||
<p class="mt-8 mb-4">
|
||||
We highly recommend connecting your account on at least one more device,
|
||||
so that you have a backup.
|
||||
<p class="mb-8 text-left">
|
||||
We highly recommend backing up your account on at least one additional
|
||||
device.
|
||||
</p>
|
||||
|
||||
<button
|
||||
|
|
@ -35,7 +33,7 @@
|
|||
Connect a backup device
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-xs btn-link text-base font-normal underline mt-4"
|
||||
class="btn btn-xs btn-link text-sm underline mt-4"
|
||||
on:click={() => navigate('are-you-sure')}
|
||||
>
|
||||
Skip for now
|
||||
|
|
|
|||
|
|
@ -13,24 +13,17 @@
|
|||
|
||||
<input type="checkbox" id="connect-modal" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<a
|
||||
href="/"
|
||||
class="btn btn-xs btn-circle absolute right-2 top-2 dark:bg-slate-600"
|
||||
>
|
||||
✕
|
||||
</a>
|
||||
<div class="modal-box w-narrowModal relative text-center">
|
||||
<a href="/" class="btn btn-xs btn-circle absolute right-2 top-2">✕</a>
|
||||
|
||||
<div>
|
||||
<h3 class="mb-7 text-xl font-serif">Connect to {appName}</h3>
|
||||
<h3 class="mb-7 text-base">Connect to {appName}</h3>
|
||||
<div>
|
||||
<a class="btn btn-primary mb-5 w-full" href="/register">
|
||||
Create a new account
|
||||
</a>
|
||||
<button
|
||||
class="btn btn-primary btn-outline w-full"
|
||||
class="btn btn-outline w-full"
|
||||
on:click={() => navigate('open-connected-device')}
|
||||
>
|
||||
I have an existing account
|
||||
|
|
|
|||
|
|
@ -5,18 +5,18 @@
|
|||
class="modal-toggle"
|
||||
/>
|
||||
<div class="modal">
|
||||
<div class="modal-box w-96 relative text-center">
|
||||
<div class="modal-box w-96 sm:w-wideModal relative text-center">
|
||||
<a href="/" class="btn btn-xs btn-circle absolute right-2 top-2">✕</a>
|
||||
<div>
|
||||
<h3 class="mb-5 text-2xl font-serif">Connect an existing account</h3>
|
||||
<h3 class="mb-8 text-base">Connect your existing account</h3>
|
||||
<div>
|
||||
<p class="text-sm mb-3">
|
||||
To connect with an existing account, you'll need a device that's
|
||||
already connected to that account.
|
||||
<p class="text-sm text-left mb-6">
|
||||
To connect your existing account on this device, you’ll need a device
|
||||
you are already connected on.
|
||||
</p>
|
||||
<p class="text-sm">
|
||||
On that device, click "Connect a new device" and follow the
|
||||
instuctions.
|
||||
<p class="text-sm text-left">
|
||||
On that device, click “Connect a new device” and follow the
|
||||
instructions.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,39 +2,48 @@
|
|||
import { goto } from '$app/navigation'
|
||||
import clipboardCopy from 'clipboard-copy'
|
||||
|
||||
import ClipboardIcon from '$components/icons/ClipboardIcon.svelte'
|
||||
import Share from '$components/icons/Share.svelte'
|
||||
import { addNotification } from '$lib/notifications'
|
||||
|
||||
export let qrcode
|
||||
export let qrcode: HTMLOrSVGElement
|
||||
export let connectionLink: string
|
||||
export let backupCreated: boolean
|
||||
|
||||
const copyLink = async () => {
|
||||
await clipboardCopy(connectionLink)
|
||||
addNotification('Copied to clipboard', 'success')
|
||||
}
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="backup-device-modal" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<div class="modal-box w-narrowModal relative text-center">
|
||||
<div>
|
||||
<h3 class="pb-1 text-xl font-serif">Connect a backup device</h3>
|
||||
<h3 class="mb-8 text-base">Connect a backup device</h3>
|
||||
<div class="w-max m-auto mb-7 rounded-lg overflow-hidden">
|
||||
{@html qrcode}
|
||||
<p class="pt-1 mb-8">
|
||||
</div>
|
||||
<p class="mb-7 text-left">
|
||||
Scan this code on the new device, or share the connection link.
|
||||
</p>
|
||||
<button class="btn btn-primary btn-outline" on:click={copyLink}>
|
||||
<ClipboardIcon />
|
||||
<span class="ml-2">Copy connection link</span>
|
||||
<button class="btn btn-outline" on:click={copyLink}>
|
||||
<Share />
|
||||
<span class="ml-2">Share connection link</span>
|
||||
</button>
|
||||
{#if !backupCreated}
|
||||
<button
|
||||
class="btn btn-xs btn-link text-base text-error font-normal underline mt-4"
|
||||
class="btn btn-xs btn-link text-sm font-normal underline mt-4"
|
||||
on:click={() => goto('/backup?view=are-you-sure')}
|
||||
>
|
||||
Skip for now
|
||||
</button>
|
||||
{:else}
|
||||
<a
|
||||
class="btn btn-xs btn-link text-sm font-normal underline mt-4"
|
||||
href="/"
|
||||
>
|
||||
Cancel
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,8 +10,16 @@
|
|||
dispatch('cancel')
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto submit the form when the pinInput is equal to the TARGET_PIN_LENGTH
|
||||
*/
|
||||
const TARGET_PIN_LENGTH = 6
|
||||
const checkPin = () => {
|
||||
if (pinInput.length === TARGET_PIN_LENGTH) {
|
||||
dispatch('checkpin')
|
||||
} else {
|
||||
pinError = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -22,24 +30,27 @@
|
|||
class="modal-toggle"
|
||||
/>
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<div class="modal-box w-narrowModal relative text-center">
|
||||
<div>
|
||||
<h3 class="mb-7 text-xl font-serif">
|
||||
<h3 class="mb-8 text-base">
|
||||
A new device would like to connect to your account
|
||||
</h3>
|
||||
<div class="mb-5">
|
||||
<input
|
||||
id="pin"
|
||||
type="text"
|
||||
class="input input-bordered w-full max-w-xs mb-2 rounded-full h-16 font-mono text-3xl text-center tracking-[0.18em] font-light dark:border-slate-300"
|
||||
class="input input-bordered w-full max-w-[197px] mb-2 rounded-full h-[68px] focus:outline-none font-mono text-deviceCode text-center tracking-[0.1em] font-light {pinError
|
||||
? '!text-red-500 !border-red-500'
|
||||
: ''}"
|
||||
maxlength="6"
|
||||
bind:value={pinInput}
|
||||
on:keyup={checkPin}
|
||||
/>
|
||||
<label for="pin" class="label">
|
||||
{#if !pinError}
|
||||
<span class="label-text-alt text-slate-500">
|
||||
Enter the connection code to approve the connection.
|
||||
<span class="label-text-alt">
|
||||
Enter the connection code from that device to approve this
|
||||
connection.
|
||||
</span>
|
||||
{:else}
|
||||
<span class="label-text-alt text-error">
|
||||
|
|
@ -49,13 +60,7 @@
|
|||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-primary mb-5 w-full" on:click={checkPin}>
|
||||
Approve the connection
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-primary btn-outline w-full"
|
||||
on:click={cancelConnection}
|
||||
>
|
||||
<button class="btn btn-outline w-full" on:click={cancelConnection}>
|
||||
Cancel Request
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import clipboardCopy from 'clipboard-copy'
|
||||
|
||||
import { appName } from '$lib/app-info'
|
||||
import { addNotification } from '$lib/notifications'
|
||||
|
||||
export let pin: string
|
||||
|
||||
|
|
@ -8,24 +12,32 @@
|
|||
const cancelConnection = () => {
|
||||
dispatch('cancel')
|
||||
}
|
||||
|
||||
const copyCode = async () => {
|
||||
await clipboardCopy(pin)
|
||||
addNotification('Copied to clipboard', 'success')
|
||||
}
|
||||
</script>
|
||||
|
||||
<input type="checkbox" id="my-modal-5" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
class="modal-box w-narrowModal relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<div class="grid grid-flow-row auto-rows-max gap-7">
|
||||
<h3 class="text-xl font-serif">Connection Requested</h3>
|
||||
<h3 class="text-base">Connect to {appName}</h3>
|
||||
<div class="grid grid-flow-row auto-rows-max gap-4 justify-items-center">
|
||||
{#if pin}
|
||||
<span
|
||||
class="btn bg-blue-100 dark:bg-blue-900 hover:bg-blue-100 dark:hover:bg-blue-900 border-0 btn-lg rounded-full text-3xl tracking-[.18em] w-3/4 cursor-default font-mono font-light"
|
||||
on:click={copyCode}
|
||||
class="btn text-base-100 hover:text-base-100 bg-base-content hover:bg-base-content border-0 btn-lg rounded-full text-deviceCode tracking-[.18em] w-3/4 cursor-pointer font-mono font-light"
|
||||
>
|
||||
{pin}
|
||||
</span>
|
||||
{/if}
|
||||
<span class="text-md">Enter this code on your connected device.</span>
|
||||
<span class="text-sm text-left">
|
||||
Enter this code on your connected device.
|
||||
</span>
|
||||
<div
|
||||
class="grid grid-flow-col auto-cols-max gap-4 justify-center items-center text-slate-500"
|
||||
>
|
||||
|
|
@ -37,7 +49,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-primary btn-outline text-base font-normal mt-4"
|
||||
class="btn btn-outline text-base mt-4"
|
||||
on:click={cancelConnection}
|
||||
>
|
||||
Cancel Request
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@
|
|||
}
|
||||
|
||||
const registerUser = async () => {
|
||||
if (checkingUsername) {
|
||||
return
|
||||
}
|
||||
|
||||
initializingFilesystem = true
|
||||
|
||||
registrationSuccess = await register(username)
|
||||
|
|
@ -45,40 +49,33 @@
|
|||
{:else}
|
||||
<input type="checkbox" id="register-modal" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<a
|
||||
href="/"
|
||||
class="btn btn-xs btn-circle absolute right-2 top-2 dark:bg-slate-600"
|
||||
>
|
||||
✕
|
||||
</a>
|
||||
<div class="modal-box w-narrowModal relative text-center">
|
||||
<a href="/" class="btn btn-xs btn-circle absolute right-2 top-2">✕</a>
|
||||
|
||||
<div>
|
||||
<h3 class="mb-7 text-xl font-serif">Choose a username</h3>
|
||||
<h3 class="mb-7 text-base">Choose a username</h3>
|
||||
<div class="relative">
|
||||
<input
|
||||
id="registration"
|
||||
type="text"
|
||||
placeholder="Type here"
|
||||
class="input input-bordered w-full block dark:border-slate-300"
|
||||
class="input input-bordered focus:outline-none w-full px-3 block"
|
||||
class:input-error={username.length !== 0 &&
|
||||
(!usernameValid || !usernameAvailable)}
|
||||
on:input={checkUsername}
|
||||
/>
|
||||
{#if checkingUsername}
|
||||
<span
|
||||
class="rounded-lg border-t-2 border-l-2 border-slate-600 dark:border-slate-50 w-4 h-4 block absolute top-4 right-4 animate-spin"
|
||||
class="rounded-lg border-t-2 border-l-2 border-base-content w-4 h-4 block absolute top-4 right-4 animate-spin"
|
||||
/>
|
||||
{/if}
|
||||
{#if !(username.length === 0) && usernameAvailable && usernameValid && !checkingUsername}
|
||||
<span class="w-4 h-4 block absolute top-5 right-4">
|
||||
<span class="w-4 h-4 block absolute top-[17px] right-4">
|
||||
<CheckIcon />
|
||||
</span>
|
||||
{/if}
|
||||
{#if !(username.length === 0) && !checkingUsername && !(usernameAvailable && usernameValid)}
|
||||
<span class="w-4 h-4 block absolute top-5 right-4">
|
||||
<span class="w-4 h-4 block absolute top-[17px] right-4">
|
||||
<XIcon />
|
||||
</span>
|
||||
{/if}
|
||||
|
|
@ -88,16 +85,16 @@
|
|||
<!-- Status of username: valid, available, etc -->
|
||||
<label for="registration" class="label mt-1">
|
||||
{#if usernameValid && usernameAvailable}
|
||||
<span class="label-text-alt text-success">
|
||||
The username is available.
|
||||
<span class="label-text-alt text-green-700 dark:text-green-500">
|
||||
This username is available.
|
||||
</span>
|
||||
{:else if !usernameValid}
|
||||
<span class="label-text-alt text-error">
|
||||
The username is invalid.
|
||||
This username is invalid.
|
||||
</span>
|
||||
{:else if !usernameAvailable}
|
||||
<span class="label-text-alt text-error">
|
||||
The username is unavailable.
|
||||
This username is unavailable.
|
||||
</span>
|
||||
{/if}
|
||||
</label>
|
||||
|
|
@ -115,7 +112,7 @@
|
|||
<input
|
||||
type="checkbox"
|
||||
id="shared-computer"
|
||||
class="peer checkbox checkbox-primary inline-grid align-bottom dark:border-slate-300"
|
||||
class="peer checkbox checkbox-primary border-2 border-base-content hover:border-orange-300 transition-colors duration-250 ease-in-out inline-grid align-bottom"
|
||||
/>
|
||||
<!-- Warning when "This is a shared computer" is checked -->
|
||||
<label
|
||||
|
|
@ -136,12 +133,13 @@
|
|||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<a class="btn btn-primary btn-outline" href="/connect">Back</a>
|
||||
<a class="btn btn-outline" href="/connect">Back</a>
|
||||
<button
|
||||
class="ml-2 btn btn-primary"
|
||||
class="ml-2 btn btn-primary disabled:opacity-50 disabled:border-neutral disabled:text-neutral"
|
||||
disabled={username.length === 0 ||
|
||||
!usernameValid ||
|
||||
!usernameAvailable}
|
||||
!usernameAvailable ||
|
||||
checkingUsername}
|
||||
on:click={registerUser}
|
||||
>
|
||||
Register
|
||||
|
|
|
|||
|
|
@ -6,22 +6,18 @@
|
|||
|
||||
<input type="checkbox" id="link-device-modal" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box w-80 relative text-center dark:border-slate-600 dark:border"
|
||||
>
|
||||
<div class="modal-box w-narrowModal relative text-center">
|
||||
<div>
|
||||
<h3 class="mb-7 text-xl font-serif">
|
||||
<h3 class="mb-14 text-base">
|
||||
Welcome, {$sessionStore.username}!
|
||||
</h3>
|
||||
<div class="flex justify-center">
|
||||
<span>
|
||||
<div class="flex justify-center mb-11 text-base-content">
|
||||
<WelcomeCheckIcon />
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mt-8 mb-4">Your account has been created.</p>
|
||||
<p class="mb-4 text-left">Your account has been created.</p>
|
||||
|
||||
<div class="mb-8">
|
||||
<div class="mb-8 text-left">
|
||||
<input type="checkbox" id="password-message" class="peer hidden" />
|
||||
<label
|
||||
class="text-primary underline mb-8 hover:cursor-pointer peer-checked:hidden"
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
<input type="checkbox" id="my-modal-5" checked class="modal-toggle" />
|
||||
<div class="modal">
|
||||
<div
|
||||
class="modal-box rounded-lg shadow-sm bg-slate-100 w-80 relative text-center dark:bg-slate-900 dark:border-slate-600 dark:border "
|
||||
class="modal-box rounded-lg shadow-sm w-narrowModal relative text-center"
|
||||
>
|
||||
<p class="text-slate-500 dark:text-slate-50">
|
||||
<p class="flex items-center justify-center text-base-content">
|
||||
<span
|
||||
class="rounded-lg border-t-2 border-l-2 border-slate-500 dark:border-slate-50 w-4 h-4 inline-block animate-spin mr-1"
|
||||
class="rounded-lg border-t-2 border-l-2 border-base-content w-4 h-4 inline-block animate-spin mr-2"
|
||||
/>
|
||||
{activity} file system...
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
<div
|
||||
class="loader ease-linear rounded-full border-4 border-t-4 border-neutral h-16 w-16"
|
||||
/>
|
||||
|
||||
<style>
|
||||
.loader {
|
||||
border-top-color: #3498db;
|
||||
animation: spinner 1s linear infinite;
|
||||
}
|
||||
|
||||
@-webkit-keyframes spinner {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<script lang="ts">
|
||||
import { sessionStore } from '../../stores'
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="min-h-[calc(100vh-128px)] md:min-h-[calc(100vh-160px)] pt-8 md:pt-16 flex flex-col items-start max-w-[690px] m-auto gap-10 pb-5 text-sm"
|
||||
>
|
||||
<h1 class="text-xl">Welcome, {$sessionStore.username}!</h1>
|
||||
|
||||
<div class="flex flex-col items-start justify-center gap-5">
|
||||
<h2 class="text-lg">Photo Gallery Demo</h2>
|
||||
<p>
|
||||
Webnative makes it easy to implement private, encrypted, user-owned
|
||||
storage in your app. See it in action with our photo gallery demo.
|
||||
</p>
|
||||
<a class="btn btn-primary" href="/gallery">Try the Photo Gallery Demo</a>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col items-start justify-center gap-5">
|
||||
<h2 class="text-lg">Device Connection Demo</h2>
|
||||
<p>
|
||||
With Webnative SDK, a user’s account lives only on their connected devices
|
||||
— entirely under their control. It’s easy for them to connect as many
|
||||
devices as they’d like. For recoverability, we recommend they always
|
||||
connect at least two.
|
||||
</p>
|
||||
<a class="btn btn-primary" href="/delegate-account">
|
||||
Connect an additional device
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<script lang="ts">
|
||||
import { appName } from '$lib/app-info'
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="min-h-[calc(100vh-96px)] flex flex-col items-start justify-center max-w-[700px] m-auto gap-6 pb-5 text-sm"
|
||||
>
|
||||
<h1 class="text-xl">Welcome to the {appName}</h1>
|
||||
|
||||
<div class="max-w-[590px]">
|
||||
<p class="mb-5">
|
||||
Webnative SDK is a true local-first edge computing stack. Effortlessly
|
||||
give your users:
|
||||
</p>
|
||||
|
||||
<ul class="mb-6 pl-6 list-disc">
|
||||
<li>
|
||||
<span class="font-bold">modern, passwordless accounts</span>
|
||||
, without a complex and costly cloud-native back-end
|
||||
</li>
|
||||
<li>
|
||||
<span class="font-bold">user-controlled data</span>
|
||||
, secured by default with our encrypted-at-rest file storage protocol
|
||||
</li>
|
||||
<li>
|
||||
<span class="font-bold">local-first functionality</span>
|
||||
, including the ability to work offline and collaborate across multiple devices
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<a class="btn btn-primary btn-sm !h-10" href="/connect">Connect</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M11 14h-1v-4H9m1-4h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 266 B |
|
|
@ -1,22 +0,0 @@
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="35"
|
||||
height="35"
|
||||
viewBox="0 0 35 35"
|
||||
version="1.1"
|
||||
>
|
||||
<g id="surface1">
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="35"
|
||||
height="35"
|
||||
style="fill:rgb(12.54902%,12.941176%,14.117647%);fill-opacity:1;stroke:none;"
|
||||
/>
|
||||
<path
|
||||
style=" stroke:none;fill-rule:nonzero;fill:rgb(90.980392%,91.764706%,92.941176%);fill-opacity:1;"
|
||||
d="M 2.039062 27.171875 L 4.1875 7.121094 C 5.070312 7.085938 5.898438 7.003906 6.671875 6.871094 C 7.460938 6.71875 8.242188 6.617188 9.011719 6.558594 C 9.011719 6.578125 8.984375 6.777344 8.925781 7.152344 C 8.871094 7.507812 8.796875 7.992188 8.703125 8.59375 C 8.609375 9.175781 8.507812 9.84375 8.394531 10.597656 C 8.277344 11.332031 8.109375 12.347656 7.886719 13.648438 C 7.675781 14.945312 7.398438 16.746094 7.039062 19.042969 L 7.460938 19.042969 C 7.949219 17.308594 8.355469 15.898438 8.675781 14.804688 C 8.996094 13.695312 9.25 12.800781 9.4375 12.125 C 9.644531 11.425781 9.832031 10.757812 10 10.117188 C 10.1875 9.476562 10.359375 8.882812 10.511719 8.339844 C 10.679688 7.792969 10.8125 7.332031 10.90625 6.957031 L 11.160156 6.957031 C 11.496094 6.957031 11.835938 6.933594 12.175781 6.898438 C 12.535156 6.859375 12.863281 6.820312 13.164062 6.785156 C 13.484375 6.730469 13.816406 6.664062 14.152344 6.589844 C 14.117188 6.757812 14.070312 7.105469 14.011719 7.632812 C 13.972656 8.160156 13.917969 8.800781 13.84375 9.554688 C 13.765625 10.289062 13.691406 11.105469 13.617188 12.011719 C 13.542969 12.890625 13.46875 13.769531 13.390625 14.636719 C 13.316406 15.484375 13.242188 16.292969 13.164062 17.0625 C 13.109375 17.835938 13.054688 18.496094 12.996094 19.042969 L 13.503906 19.042969 L 16.1875 6.898438 C 16.828125 6.804688 17.457031 6.71875 18.078125 6.644531 C 18.625 6.570312 19.1875 6.492188 19.773438 6.417969 C 20.355469 6.34375 20.875 6.257812 21.324219 6.164062 C 21.042969 6.957031 20.761719 7.839844 20.476562 8.816406 C 20.195312 9.777344 19.902344 10.792969 19.601562 11.867188 C 19.300781 12.941406 19.011719 14.023438 18.726562 15.113281 C 18.464844 16.207031 18.199219 17.261719 17.9375 18.28125 C 17.332031 20.6875 16.75 23.164062 16.1875 25.703125 L 9.804688 26.777344 L 11.046875 15.875 L 10.707031 15.875 L 7.914062 26.128906 Z M 18.007812 27.199219 C 18.535156 24.542969 19.042969 21.957031 19.535156 19.433594 C 19.722656 18.382812 19.917969 17.28125 20.128906 16.132812 C 20.355469 14.964844 20.558594 13.824219 20.746094 12.714844 C 20.933594 11.585938 21.105469 10.503906 21.257812 9.46875 C 21.425781 8.414062 21.558594 7.453125 21.652344 6.589844 C 22.234375 6.550781 22.800781 6.515625 23.34375 6.472656 C 23.835938 6.4375 24.332031 6.410156 24.84375 6.390625 C 25.351562 6.355469 25.800781 6.316406 26.199219 6.277344 C 26.441406 7.726562 26.660156 9.109375 26.847656 10.429688 C 26.941406 10.992188 27.035156 11.585938 27.128906 12.207031 C 27.242188 12.808594 27.347656 13.390625 27.441406 13.960938 C 27.535156 14.523438 27.628906 15.070312 27.722656 15.597656 C 27.816406 16.101562 27.910156 16.558594 28.003906 16.949219 C 28.078125 16.558594 28.164062 16.101562 28.261719 15.597656 C 28.351562 15.070312 28.457031 14.523438 28.570312 13.960938 C 28.683594 13.375 28.796875 12.78125 28.910156 12.179688 C 29.039062 11.578125 29.164062 10.992188 29.273438 10.429688 C 29.558594 9.109375 29.847656 7.734375 30.148438 6.304688 L 33.59375 5.882812 C 32.957031 8.707031 32.390625 11.378906 31.898438 13.902344 C 31.675781 14.996094 31.449219 16.09375 31.222656 17.207031 C 31.019531 18.316406 30.820312 19.386719 30.632812 20.421875 C 30.445312 21.457031 30.285156 22.417969 30.148438 23.304688 C 30.019531 24.167969 29.914062 24.902344 29.839844 25.503906 C 29.785156 25.503906 29.558594 25.554688 29.164062 25.648438 C 28.785156 25.722656 28.34375 25.816406 27.835938 25.929688 C 27.347656 26.042969 26.847656 26.164062 26.339844 26.296875 C 25.851562 26.410156 25.480469 26.503906 25.238281 26.578125 C 25.105469 25.054688 24.964844 23.605469 24.816406 22.230469 C 24.757812 21.644531 24.691406 21.042969 24.617188 20.421875 C 24.542969 19.804688 24.464844 19.210938 24.390625 18.644531 C 24.332031 18.082031 24.269531 17.550781 24.191406 17.0625 C 24.136719 16.558594 24.078125 16.132812 24.023438 15.792969 C 23.96875 16.132812 23.890625 16.546875 23.800781 17.035156 C 23.703125 17.523438 23.609375 18.050781 23.515625 18.617188 C 23.417969 19.160156 23.328125 19.734375 23.230469 20.339844 C 23.140625 20.921875 23.035156 21.496094 22.921875 22.058594 C 22.679688 23.394531 22.414062 24.789062 22.132812 26.238281 Z M 18.007812 27.199219 "
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 4.6 KiB |
|
|
@ -0,0 +1,8 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="41" height="40" fill="none">
|
||||
<path
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
d="M5.8 0C2.111 0 .5 1.599.5 5.333v29.334C.5 38.255 2.156 40 5.8 40h29.15c3.674 0 5.301-1.678 5.301-5.333V5.333c0-3.67-1.658-5.333-5.3-5.333H5.8Zm3.82 26.397L11.407 8.2c.165-1.681-1.147-3.138-2.825-3.138-2.04 0-3.579 2.19-3.014 4.276.755 2.793 1.486 6.496 1.533 10.49.027 2.326-.207 4.576-.56 6.615-.354 2.05.202 4.187 1.37 5.81 1.167 1.62 2.912 2.687 4.924 2.687h1.037c2.546 0 4.61-2.077 4.61-4.638v-1.935c0-1.164-.84-2.155-1.982-2.339l-1.412-.228a1.018 1.018 0 0 0-1.174.917l-.008.092a2.158 2.158 0 0 1-2.144 1.969 2.161 2.161 0 0 1-2.142-2.38Zm8.862-5.777v-7.53c0-1.03.83-1.867 1.855-1.867s1.856.836 1.856 1.868v16.246c0 3.094 2.493 5.602 5.567 5.602h.237c3.995 0 6.975-4.28 6.242-8.41-.366-2.06-.62-4.339-.62-6.695 0-4.102.771-7.898 1.563-10.716.554-1.97-.9-4.057-2.825-4.057-1.55 0-2.772 1.33-2.65 2.885l1.446 18.476a2.178 2.178 0 0 1-2.163 2.355 2.175 2.175 0 0 1-2.16-1.984l-1.576-17.26c-.232-2.534-2.343-4.472-4.871-4.472-2.539 0-4.656 1.954-4.873 4.5l-1.046 10.886a2.022 2.022 0 0 0 1.715 2.177 2.017 2.017 0 0 0 2.303-2.004Z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
|
@ -1,16 +1,19 @@
|
|||
<svg
|
||||
width="41"
|
||||
height="40"
|
||||
viewBox="0 0 41 40"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="stroke-slate-50 fill-slate-900 hover:stroke-slate-900 hover:fill-slate-50 hover:cursor-pointer transition-colors"
|
||||
>
|
||||
<rect x="1" y="0.5" width="39" height="39" rx="19.5" />
|
||||
<path
|
||||
d="M28.8542 23.3542C27.8176 23.7708 26.6856 24.0001 25.5 24.0001C20.5294 24.0001 16.5 19.9706 16.5 15.0001C16.5 13.8145 16.7292 12.6825 17.1458 11.6459C13.8365 12.9758 11.5 16.2151 11.5 20.0001C11.5 24.9706 15.5294 29.0001 20.5 29.0001C24.285 29.0001 27.5243 26.6636 28.8542 23.3542Z"
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="none">
|
||||
<rect
|
||||
width="38"
|
||||
height="38"
|
||||
x="1"
|
||||
y="1"
|
||||
fill="#171717"
|
||||
stroke="#FAFAFA"
|
||||
stroke-width="2"
|
||||
rx="19"
|
||||
/>
|
||||
<path
|
||||
stroke="#FAFAFA"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M28.354 23.354a9 9 0 0 1-11.708-11.708A9.003 9.003 0 0 0 20 29a9.003 9.003 0 0 0 8.354-5.646Z"
|
||||
/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 673 B After Width: | Height: | Size: 432 B |
|
|
@ -0,0 +1,6 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="20" fill="none">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M20.317 2.37A19.791 19.791 0 0 0 15.432.855a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.271 18.271 0 0 0-5.487 0 12.643 12.643 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.737 19.737 0 0 0 3.677 2.37a.07.07 0 0 0-.032.027C.533 7.046-.32 11.58.099 16.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.296 1.226-1.995.021-.04.001-.09-.041-.105a13.109 13.109 0 0 1-1.872-.893.077.077 0 0 1-.008-.127c.126-.095.252-.193.372-.292a.074.074 0 0 1 .078-.01c3.927 1.793 8.18 1.793 12.061 0a.074.074 0 0 1 .079.01c.12.098.245.197.372.292.044.032.04.1-.006.127-.598.35-1.22.645-1.873.892a.077.077 0 0 0-.041.106c.36.699.772 1.363 1.225 1.994a.076.076 0 0 0 .084.028 19.834 19.834 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.06.06 0 0 0-.031-.03ZM8.02 13.33c-1.182 0-2.157-1.086-2.157-2.419S6.82 8.493 8.02 8.493c1.21 0 2.176 1.095 2.157 2.42 0 1.332-.956 2.418-2.157 2.418Zm7.975 0c-1.183 0-2.157-1.086-2.157-2.419s.955-2.419 2.157-2.419c1.21 0 2.176 1.095 2.157 2.42 0 1.332-.946 2.418-2.157 2.418Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2.5"
|
||||
d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6M15 3h6v6M10 14 21 3"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 285 B |
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="23" height="24" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2.5"
|
||||
d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 500 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="40" fill="none">
|
||||
<path fill="currentColor" d="M8 8h32v2H8zM8 19h32v2H8zM8 30h32v2H8z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 157 B |
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m1 10 2-2m0 0 7-7 7 7M3 8v10a1 1 0 0 0 1 1h3M17 8l2 2m-2-2v10a1 1 0 0 1-1 1h-3m-6 0a1 1 0 0 0 1-1v-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 0 1 1m-6 0h6"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 360 B |
|
|
@ -1,16 +1,19 @@
|
|||
<svg
|
||||
width="41"
|
||||
height="40"
|
||||
viewBox="0 0 41 40"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="stroke-slate-900 fill-slate-50 hover:stroke-slate-50 hover:fill-slate-900 hover:cursor-pointer transition-colors"
|
||||
>
|
||||
<rect x="1" y="0.5" width="39" height="39" rx="19.5" />
|
||||
<path
|
||||
d="M20.5 11V12M20.5 28V29M29.5 20H28.5M12.5 20H11.5M26.864 26.364L26.1569 25.6569M14.8431 14.3431L14.136 13.636M26.864 13.6361L26.1569 14.3432M14.8432 25.6569L14.1361 26.364M24.5 20C24.5 22.2091 22.7091 24 20.5 24C18.2909 24 16.5 22.2091 16.5 20C16.5 17.7909 18.2909 16 20.5 16C22.7091 16 24.5 17.7909 24.5 20Z"
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" fill="none">
|
||||
<rect
|
||||
width="38"
|
||||
height="38"
|
||||
x="1"
|
||||
y="1"
|
||||
fill="#FAFAFA"
|
||||
stroke="#171717"
|
||||
stroke-width="2"
|
||||
rx="19"
|
||||
/>
|
||||
<path
|
||||
stroke="#111827"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M20 11v1m0 16v1m9-9h-1m-16 0h-1m15.364 6.364-.707-.707M14.343 14.343l-.707-.707m12.728 0-.707.707M14.343 25.657l-.707.707M24 20a4 4 0 1 1-8 0 4 4 0 0 1 8 0Z"
|
||||
/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 700 B After Width: | Height: | Size: 495 B |
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m1 13 4.586-4.586a2 2 0 0 1 2.828 0L13 13m-2-2 1.586-1.586a2 2 0 0 1 2.828 0L17 11m-6-6h.01M3 17h12a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2H3a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 370 B |
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 3V1m0 2a2 2 0 1 0 0 4m0-4a2 2 0 1 1 0 4m-6 8a2 2 0 1 0 0-4m0 4a2 2 0 1 1 0-4m0 4v2m0-6V1m6 6v10m6-2a2 2 0 1 0 0-4m0 4a2 2 0 1 1 0-4m0 4v2m0-6V1"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 353 B |
|
|
@ -0,0 +1,9 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none">
|
||||
<path
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6.684 11.342C6.886 10.938 7 10.482 7 10c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 1 1 0-2.684m0 2.684 6.632 3.316m-6.632-6 6.632-3.316m0 0a3 3 0 1 0 5.367-2.684 3 3 0 0 0-5.367 2.684Zm0 9.316a3 3 0 1 0 5.368 2.684 3 3 0 0 0-5.368-2.684Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 444 B |
|
|
@ -1,15 +1,9 @@
|
|||
<svg
|
||||
width="17"
|
||||
height="18"
|
||||
viewBox="0 0 17 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="inline-block"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="21" fill="none">
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M8.5 0.944458C6.41528 2.81033 3.67437 3.95809 0.666107 3.99891C0.556864 4.64968 0.5 5.31821 0.5 6.00003C0.5 11.2249 3.83923 15.6698 8.5 17.3172C13.1608 15.6698 16.5 11.2249 16.5 6.00003C16.5 5.31821 16.4431 4.64968 16.3339 3.99891C13.3256 3.95809 10.5847 2.81033 8.5 0.944458ZM9.5 13C9.5 13.5523 9.05228 14 8.5 14C7.94772 14 7.5 13.5523 7.5 13C7.5 12.4477 7.94772 12 8.5 12C9.05228 12 9.5 12.4477 9.5 13ZM9.5 6C9.5 5.44772 9.05229 5 8.5 5C7.94772 5 7.5 5.44772 7.5 6V9C7.5 9.55228 7.94772 10 8.5 10C9.05229 10 9.5 9.55228 9.5 9V6Z"
|
||||
fill="#7C2D12"
|
||||
stroke="#171717"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 8v2m0 4h.01m8.608-9.016A11.955 11.955 0 0 1 10 1.944a11.955 11.955 0 0 1-8.618 3.04A12.02 12.02 0 0 0 1 8c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016Z"
|
||||
/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 756 B After Width: | Height: | Size: 399 B |
|
|
@ -1,14 +1,8 @@
|
|||
<svg
|
||||
width="100"
|
||||
height="101"
|
||||
viewBox="0 0 100 101"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="79" height="56" fill="none">
|
||||
<path
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
d="M77.06 1.64a5.6 5.6 0 0 1 0 7.92l-44.8 44.8a5.6 5.6 0 0 1-7.92 0l-22.4-22.4a5.6 5.6 0 0 1 7.92-7.92L28.3 42.48 69.14 1.64a5.6 5.6 0 0 1 7.92 0Z"
|
||||
clip-rule="evenodd"
|
||||
d="M26.8559 9.92063C30.8429 9.60246 34.6279 8.03465 37.6722 5.44038C44.7761 -0.613591 55.2246 -0.613591 62.3286 5.44038C65.3728 8.03465 69.1579 9.60246 73.1449 9.92063C82.449 10.6631 89.8372 18.0513 90.5797 27.3554C90.8978 31.3424 92.4656 35.1274 95.0599 38.1717C101.114 45.2757 101.114 55.7241 95.0599 62.8281C92.4656 65.8724 90.8978 69.6574 90.5797 73.6444C89.8372 82.9485 82.449 90.3367 73.1449 91.0792C69.1579 91.3973 65.3728 92.9652 62.3286 95.5594C55.2246 101.613 44.7761 101.613 37.6722 95.5594C34.6279 92.9652 30.8429 91.3973 26.8559 91.0792C17.5518 90.3367 10.1636 82.9485 9.42112 73.6444C9.10295 69.6574 7.53514 65.8724 4.94087 62.8281C-1.1131 55.7241 -1.1131 45.2757 4.94087 38.1717C7.53514 35.1274 9.10295 31.3424 9.42112 27.3554C10.1636 18.0513 17.5518 10.6631 26.8559 9.92063ZM72.9845 42.484C75.4057 40.0627 75.4057 36.1371 72.9845 33.7158C70.5632 31.2946 66.6376 31.2946 64.2163 33.7158L43.8004 54.1318L35.7845 46.1158C33.3632 43.6946 29.4376 43.6946 27.0163 46.1158C24.5951 48.5371 24.5951 52.4627 27.0163 54.884L39.4163 67.284C41.8376 69.7052 45.7632 69.7052 48.1844 67.284L72.9845 42.484Z"
|
||||
fill="#6EE7B7"
|
||||
/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 320 B |
|
|
@ -0,0 +1,5 @@
|
|||
<span
|
||||
class="inline-block px-2 py-[2px] !no-underline font-semiBold text-center text-xs text-neutral bg-gradient-to-r from-orange-600 to-orange-300"
|
||||
>
|
||||
ALPHA
|
||||
</span>
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { page } from '$app/stores'
|
||||
import { sessionStore } from '$src/stores'
|
||||
import About from '$components/icons/About.svelte'
|
||||
import AlphaTag from '$components/nav/AlphaTag.svelte'
|
||||
import BrandLogo from '$components/icons/BrandLogo.svelte'
|
||||
import BrandWordmark from '$components/icons/BrandWordmark.svelte'
|
||||
import Home from '$components/icons/Home.svelte'
|
||||
import PhotoGallery from '$components/icons/PhotoGallery.svelte'
|
||||
import Settings from '$components/icons/Settings.svelte'
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
label: 'Home',
|
||||
href: '/',
|
||||
icon: Home
|
||||
},
|
||||
{
|
||||
label: 'Photo Gallery Demo',
|
||||
href: '/gallery/',
|
||||
icon: PhotoGallery
|
||||
},
|
||||
{
|
||||
label: 'About This Template',
|
||||
href: '/about/',
|
||||
icon: About
|
||||
},
|
||||
{
|
||||
label: 'Account Settings',
|
||||
href: '/settings/',
|
||||
icon: Settings
|
||||
}
|
||||
]
|
||||
|
||||
let checked = false
|
||||
const handleCloseDrawer = (): void => {
|
||||
checked = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Only render the nav if the user is authed and not in the connection flow -->
|
||||
{#if $sessionStore.authed && !$page.url.pathname.match(/register|backup|delegate/)}
|
||||
<div class="drawer drawer-mobile h-screen">
|
||||
<input
|
||||
id="sidebar-nav"
|
||||
class="drawer-toggle"
|
||||
type="checkbox"
|
||||
bind:checked
|
||||
/>
|
||||
<div class="drawer-content flex flex-col">
|
||||
<slot />
|
||||
</div>
|
||||
<div class="drawer-side">
|
||||
<label
|
||||
for="sidebar-nav"
|
||||
class="drawer-overlay !bg-[#262626] !opacity-[.85]"
|
||||
/>
|
||||
<div class="menu p-4 overflow-y-auto w-80 bg-base-100 text-base-content">
|
||||
<!-- Brand -->
|
||||
<div
|
||||
class="flex items-center gap-3 cursor-pointer mb-8"
|
||||
on:click={() => {
|
||||
handleCloseDrawer()
|
||||
goto('/')
|
||||
}}
|
||||
>
|
||||
<BrandLogo />
|
||||
<BrandWordmark />
|
||||
<AlphaTag />
|
||||
</div>
|
||||
|
||||
<!-- Menu -->
|
||||
<ul>
|
||||
{#each navItems as item}
|
||||
<li>
|
||||
<a
|
||||
class="flex items-center justify-start gap-2 font-bold text-sm text-base-content hover:text-base-100 bg-base-100 hover:bg-base-content ease-in-out duration-[250ms] {$page
|
||||
.url.pathname === item.href
|
||||
? '!text-base-100 !bg-base-content'
|
||||
: ''}"
|
||||
href={item.href}
|
||||
on:click={handleCloseDrawer}
|
||||
>
|
||||
<svelte:component this={item.icon} />{item.label}
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<slot />
|
||||
{/if}
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
success: {
|
||||
component: CheckThinIcon,
|
||||
props: {
|
||||
color: $themeStore === 'light' ? '#b8ffd3' : '#002e12'
|
||||
color: '#14532D'
|
||||
}
|
||||
},
|
||||
warning: {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
</script>
|
||||
|
||||
{#if $notificationStore.length}
|
||||
<div class="fixed z-50 right-6 bottom-6 flex flex-col justify-center">
|
||||
<div class="fixed z-max right-4 bottom-8 flex flex-col justify-center">
|
||||
{#each $notificationStore as notification (notification.id)}
|
||||
<div animate:flip>
|
||||
<Notification {notification} />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<script lang="ts">
|
||||
import { accountSettingsStore, sessionStore } from '$src/stores'
|
||||
import { getAvatarFromWNFS } from '$lib/account-settings'
|
||||
|
||||
export let size = 'large'
|
||||
|
||||
const sizeClasses =
|
||||
size === 'large'
|
||||
? 'w-[88px] h-[88px] text-[40px]'
|
||||
: 'w-[40px] h-[40px] text-sm'
|
||||
|
||||
const loaderSizeClasses =
|
||||
size === 'large' ? 'w-[28px] h-[28px]' : 'w-[16px] h-[16px]'
|
||||
|
||||
getAvatarFromWNFS()
|
||||
</script>
|
||||
|
||||
{#if $accountSettingsStore.avatar}
|
||||
{#if $accountSettingsStore.loading}
|
||||
<div
|
||||
class="flex items-center justify-center object-cover rounded-full border-2 border-base-content {sizeClasses}"
|
||||
>
|
||||
<span
|
||||
class="animate-spin ease-linear rounded-full border-2 border-t-2 border-t-orange-300 border-base-content {loaderSizeClasses}"
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<img
|
||||
class="object-cover rounded-full border-2 border-base-content {sizeClasses}"
|
||||
src={$accountSettingsStore.avatar.src}
|
||||
alt="User Avatar"
|
||||
/>
|
||||
{/if}
|
||||
{:else}
|
||||
<div
|
||||
class="flex items-center justify-center bg-base-content text-base-100 uppercase font-bold rounded-full {sizeClasses}"
|
||||
>
|
||||
{$sessionStore.username[0]}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
<script lang="ts">
|
||||
import { getAvatarFromWNFS, uploadAvatarToWNFS } from '$lib/account-settings'
|
||||
import Avatar from '$components/settings/Avatar.svelte'
|
||||
|
||||
/**
|
||||
* Handle uploads made by interacting with the file input
|
||||
*/
|
||||
const handleFileInput: (file: File) => Promise<void> = async file => {
|
||||
await uploadAvatarToWNFS(file)
|
||||
|
||||
// Refetch avatar and update accountSettingsStore
|
||||
await getAvatarFromWNFS()
|
||||
}
|
||||
|
||||
// Handle a file uploaded directly through the file input
|
||||
let files: FileList
|
||||
$: if (files) {
|
||||
const file = Array.from(files)[0]
|
||||
handleFileInput(file)
|
||||
}
|
||||
</script>
|
||||
|
||||
<h3 class="text-lg mb-4">Avatar</h3>
|
||||
<div class="flex items-center gap-4">
|
||||
<Avatar />
|
||||
|
||||
<label for="upload-avatar" class="btn btn-outline">Upload a new avatar</label>
|
||||
<input
|
||||
bind:files
|
||||
id="upload-avatar"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
class="hidden"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
<script lang="ts">
|
||||
import { themeStore } from '$src/stores'
|
||||
import { storeTheme, type Theme } from '$lib/theme'
|
||||
|
||||
const options = [
|
||||
{
|
||||
label: 'Dark',
|
||||
value: 'dark'
|
||||
},
|
||||
{
|
||||
label: 'Light',
|
||||
value: 'light'
|
||||
}
|
||||
]
|
||||
|
||||
let selected = $themeStore
|
||||
|
||||
themeStore.subscribe((updatedTheme) => {
|
||||
selected = updatedTheme
|
||||
})
|
||||
|
||||
const setTheme = (newTheme: Theme) => {
|
||||
themeStore.set(newTheme)
|
||||
storeTheme(newTheme)
|
||||
}
|
||||
|
||||
$: if (selected) {
|
||||
setTheme(selected)
|
||||
}
|
||||
</script>
|
||||
|
||||
<h3 class="text-lg mb-4">Theme preference</h3>
|
||||
|
||||
{#each options as option}
|
||||
<div class="form-control items-start">
|
||||
<label class="label cursor-pointer">
|
||||
<input
|
||||
type="radio"
|
||||
name="theme-preference"
|
||||
class="radio checked:bg-base-content"
|
||||
value={option.value}
|
||||
checked={selected === option.value}
|
||||
bind:group={selected}
|
||||
/>
|
||||
<span class="label-text text-sm ml-2">{option.label}</span>
|
||||
</label>
|
||||
</div>
|
||||
{/each}
|
||||
|
|
@ -2,10 +2,95 @@
|
|||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.modal-box {
|
||||
@apply p-8;
|
||||
@font-face {
|
||||
font-family: 'UncutSans_Regular';
|
||||
src: url('/fonts/uncut-sans-regular-webfont.woff2') format('woff2'),
|
||||
url('/fonts/uncut-sans-regular-webfont.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'UncutSans_Medium';
|
||||
src: url('/fonts/uncut-sans-medium-webfont.woff2') format('woff2'),
|
||||
url('/fonts/uncut-sans-medium-webfont.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'UncutSans_Bold';
|
||||
src: url('/fonts/uncut-sans-bold-webfont.woff2') format('woff2'),
|
||||
url('/fonts/uncut-sans-bold-webfont.woff') format('woff');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
h4, h5, h6 {
|
||||
@apply font-semiBold;
|
||||
}
|
||||
|
||||
body, p, li, a, span, input {
|
||||
@apply font-sans;
|
||||
}
|
||||
|
||||
/* Button default styles */
|
||||
.btn {
|
||||
@apply font-semiBold;
|
||||
@apply border-2;
|
||||
@apply min-h-0;
|
||||
}
|
||||
|
||||
.btn-circle {
|
||||
@apply text-base-100;
|
||||
@apply bg-base-content;
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
@apply text-sm;
|
||||
@apply text-base-content;
|
||||
@apply border-base-content;
|
||||
@apply bg-base-100;
|
||||
@apply shadow-orange;
|
||||
@apply h-11;
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
@apply text-sm;
|
||||
@apply text-neutral;
|
||||
@apply border-neutral;
|
||||
@apply shadow-orange;
|
||||
@apply bg-gradient-to-r;
|
||||
@apply from-orange-600;
|
||||
@apply to-orange-300;
|
||||
@apply h-11;
|
||||
@apply px-4;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-warning:hover {
|
||||
@apply border-orange-300;
|
||||
}
|
||||
|
||||
/* Input default styles */
|
||||
.input-bordered {
|
||||
@apply text-base-content;
|
||||
@apply border-2;
|
||||
@apply border-base-content;
|
||||
}
|
||||
|
||||
/* Modal default styles */
|
||||
.modal-box {
|
||||
@apply p-8;
|
||||
@apply border-2;
|
||||
@apply border-base-content;
|
||||
}
|
||||
|
||||
/* Label default styles */
|
||||
.label {
|
||||
@apply px-0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
import { get as getStore } from 'svelte/store'
|
||||
import * as wn from 'webnative'
|
||||
import * as uint8arrays from 'uint8arrays'
|
||||
import type { CID } from 'multiformats/cid'
|
||||
import type { PuttableUnixTree, File as WNFile } from 'webnative/fs/types'
|
||||
import type { Metadata } from 'webnative/fs/metadata'
|
||||
|
||||
import { accountSettingsStore, filesystemStore } from '$src/stores'
|
||||
import { addNotification } from '$lib/notifications'
|
||||
|
||||
export type Avatar = {
|
||||
cid: string
|
||||
ctime: number
|
||||
name: string
|
||||
size?: number
|
||||
src: string
|
||||
}
|
||||
|
||||
export type AccountSettings = {
|
||||
avatar: Avatar
|
||||
loading: boolean
|
||||
}
|
||||
interface AvatarFile extends PuttableUnixTree, WNFile {
|
||||
cid: CID
|
||||
content: Uint8Array
|
||||
header: {
|
||||
content: Uint8Array
|
||||
metadata: Metadata
|
||||
}
|
||||
}
|
||||
|
||||
export const ACCOUNT_SETTINGS_DIR = ['private', 'settings']
|
||||
const AVATAR_DIR = [...ACCOUNT_SETTINGS_DIR, 'avatars']
|
||||
const AVATAR_ARCHIVE_DIR = [...AVATAR_DIR, 'archive']
|
||||
const AVATAR_FILE_NAME = 'avatar'
|
||||
const FILE_SIZE_LIMIT = 5
|
||||
|
||||
/**
|
||||
* Move old avatar to the archive directory
|
||||
*/
|
||||
const archiveOldAvatar = async (): Promise<void> => {
|
||||
const fs = getStore(filesystemStore)
|
||||
|
||||
// Return if user has not uploaded an avatar yet
|
||||
const avatarDirExists = await fs.exists(wn.path.file(...AVATAR_DIR))
|
||||
if (!avatarDirExists) {
|
||||
return
|
||||
}
|
||||
|
||||
// Find the filename of the old avatar
|
||||
const path = wn.path.directory(...AVATAR_DIR)
|
||||
const links = await fs.ls(path)
|
||||
const oldAvatarFileName = Object.keys(links).find(key =>
|
||||
key.includes(AVATAR_FILE_NAME)
|
||||
)
|
||||
const oldFileNameArray = oldAvatarFileName.split('.')[0]
|
||||
const archiveFileName = `${oldFileNameArray[0]}-${Date.now()}.${
|
||||
oldFileNameArray[1]
|
||||
}`
|
||||
|
||||
// Move old avatar to archive dir
|
||||
const fromPath = wn.path.file(...AVATAR_DIR, oldAvatarFileName)
|
||||
const toPath = wn.path.file(...AVATAR_ARCHIVE_DIR, archiveFileName)
|
||||
await fs.mv(fromPath, toPath)
|
||||
|
||||
// Announce the changes to the server
|
||||
await fs.publish()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Avatar from the user's WNFS and construct its `src`
|
||||
*/
|
||||
export const getAvatarFromWNFS = async (): Promise<void> => {
|
||||
try {
|
||||
// Set loading: true on the accountSettingsStore
|
||||
accountSettingsStore.update(store => ({ ...store, loading: true }))
|
||||
|
||||
const fs = getStore(filesystemStore)
|
||||
|
||||
// If the avatar dir doesn't exist, silently fail and let the UI handle it
|
||||
const avatarDirExists = await fs.exists(wn.path.file(...AVATAR_DIR))
|
||||
if (!avatarDirExists) {
|
||||
accountSettingsStore.update(store => ({
|
||||
...store,
|
||||
loading: false
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
// Find the file that matches the AVATAR_FILE_NAME
|
||||
const path = wn.path.directory(...AVATAR_DIR)
|
||||
const links = await fs.ls(path)
|
||||
const avatarName = Object.keys(links).find(key =>
|
||||
key.includes(AVATAR_FILE_NAME)
|
||||
)
|
||||
|
||||
// If user has not uploaded an avatar, silently fail and let the UI handle it
|
||||
if (!avatarName) {
|
||||
accountSettingsStore.update(store => ({
|
||||
...store,
|
||||
loading: false
|
||||
}))
|
||||
return
|
||||
}
|
||||
|
||||
const file = await fs.get(wn.path.file(...AVATAR_DIR, `${avatarName}`))
|
||||
|
||||
// The CID for private files is currently located in `file.header.content`
|
||||
const cid = (file as AvatarFile).header.content.toString()
|
||||
|
||||
// Create a base64 string to use as the image `src`
|
||||
const src = `data:image/jpeg;base64, ${uint8arrays.toString(
|
||||
(file as AvatarFile).content,
|
||||
'base64'
|
||||
)}`
|
||||
|
||||
const avatar = {
|
||||
cid,
|
||||
ctime: (file as AvatarFile).header.metadata.unixMeta.ctime,
|
||||
name: avatarName,
|
||||
src
|
||||
}
|
||||
|
||||
// Push images to the accountSettingsStore
|
||||
accountSettingsStore.update(store => ({
|
||||
...store,
|
||||
avatar,
|
||||
loading: false
|
||||
}))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
accountSettingsStore.update(store => ({
|
||||
...store,
|
||||
avatar: null,
|
||||
loading: false
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload an avatar image to the user's private WNFS
|
||||
* @param image
|
||||
*/
|
||||
export const uploadAvatarToWNFS = async (image: File): Promise<void> => {
|
||||
try {
|
||||
// Set loading: true on the accountSettingsStore
|
||||
accountSettingsStore.update(store => ({ ...store, loading: true }))
|
||||
|
||||
const fs = getStore(filesystemStore)
|
||||
|
||||
// Reject files over 5MB
|
||||
const imageSizeInMB = image.size / (1024 * 1024)
|
||||
if (imageSizeInMB > FILE_SIZE_LIMIT) {
|
||||
throw new Error('Image can be no larger than 5MB')
|
||||
}
|
||||
|
||||
// Archive old avatar
|
||||
await archiveOldAvatar()
|
||||
|
||||
// Rename the file to `avatar.[extension]`
|
||||
const updatedImage = new File(
|
||||
[image],
|
||||
`${AVATAR_FILE_NAME}.${image.name.split('.')[1]}`,
|
||||
{
|
||||
type: image.type
|
||||
}
|
||||
)
|
||||
|
||||
// Create a sub directory and add the avatar
|
||||
await fs.write(wn.path.file(...AVATAR_DIR, updatedImage.name), updatedImage)
|
||||
|
||||
// Announce the changes to the server
|
||||
await fs.publish()
|
||||
|
||||
addNotification(`Your avatar has been updated!`, 'success')
|
||||
} catch (error) {
|
||||
addNotification(error.message, 'error')
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
export const appName = 'Awesome Webnative App'
|
||||
export const appName = 'Webnative SDK Demo'
|
||||
export const appDescription = 'This is another awesome Webnative app.'
|
||||
export const appURL = 'https://webnative.netlify.app'
|
||||
export const appImageURL = `${appURL}/preview.png`
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import type FileSystem from 'webnative/fs/index'
|
|||
import { asyncDebounce } from '$lib/utils'
|
||||
import { filesystemStore, sessionStore } from '../../stores'
|
||||
import { getBackupStatus } from '$lib/auth/backup'
|
||||
import { ACCOUNT_SETTINGS_DIR } from '$lib/account-settings'
|
||||
import { AREAS } from '$routes/gallery/stores'
|
||||
import { GALLERY_DIRS } from '$routes/gallery/lib/gallery'
|
||||
|
||||
|
|
@ -50,6 +51,7 @@ export const register = async (username: string): Promise<boolean> => {
|
|||
const initializeFilesystem = async (fs: FileSystem): Promise<void> => {
|
||||
await fs.mkdir(webnative.path.directory(...GALLERY_DIRS[AREAS.PUBLIC]))
|
||||
await fs.mkdir(webnative.path.directory(...GALLERY_DIRS[AREAS.PRIVATE]))
|
||||
await fs.mkdir(webnative.path.directory(...ACCOUNT_SETTINGS_DIR))
|
||||
}
|
||||
|
||||
export const loadAccount = async (username: string): Promise<void> => {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
import { browser } from '$app/environment'
|
||||
|
||||
export type Theme = 'light' | 'dark'
|
||||
export type Theme = 'light' | 'dark' | 'default'
|
||||
|
||||
export const getSystemDefaultTheme = (): Theme =>
|
||||
window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
|
||||
export const loadTheme = (): Theme => {
|
||||
if (browser) {
|
||||
const browserTheme = localStorage.getItem('theme') as Theme
|
||||
const osTheme = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||
? 'dark'
|
||||
: 'light'
|
||||
const osTheme = getSystemDefaultTheme()
|
||||
|
||||
return browserTheme ?? (osTheme as Theme) ?? 'light'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
<script lang="ts">
|
||||
import Discord from '$components/icons/Discord.svelte'
|
||||
import ExternalLink from '$components/icons/ExternalLink.svelte'
|
||||
import Github from '$components/icons/Github.svelte'
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="min-h-[calc(100vh-96px)] flex flex-col items-center justify-center max-w-[700px] m-auto gap-6 pb-5 text-sm"
|
||||
>
|
||||
<h1 class="text-xl">404 - Page not found</h1>
|
||||
|
||||
<p>The page you have requested does not exist.</p>
|
||||
|
||||
<img
|
||||
class="relative z-0 w-[227px] h-[227px] rounded-full border-[16px] border-base-content"
|
||||
src={`${window.location.origin}/wn-404.gif`}
|
||||
alt={`Circle animation`}
|
||||
/>
|
||||
|
||||
<div class="flex items-center justify-between gap-6">
|
||||
<a
|
||||
class="flex items-center justify-center gap-2 font-bold text-sm text-base-content"
|
||||
href="https://guide.fission.codes/"
|
||||
target="_blank"
|
||||
>
|
||||
Docs <ExternalLink />
|
||||
</a>
|
||||
<a
|
||||
class="flex items-center justify-center gap-2 font-bold text-sm text-base-content"
|
||||
href="https://github.com/webnative-examples/"
|
||||
target="_blank"
|
||||
>
|
||||
Github <Github />
|
||||
</a>
|
||||
<a
|
||||
class="flex items-center justify-center gap-2 font-bold text-sm text-base-content"
|
||||
href="https://fission.codes/discord"
|
||||
target="_blank"
|
||||
>
|
||||
Discord <Discord />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -5,8 +5,10 @@
|
|||
import { sessionStore, themeStore } from '../stores'
|
||||
import { errorToMessage } from '$lib/session'
|
||||
import { initialize } from '$lib/init'
|
||||
import Footer from '$components/Footer.svelte'
|
||||
import Header from '$components/Header.svelte'
|
||||
import Notifications from '$components/notifications/Notifications.svelte'
|
||||
import SidebarNav from '$components/nav/SidebarNav.svelte'
|
||||
|
||||
sessionStore.subscribe(session => {
|
||||
if (session.error) {
|
||||
|
|
@ -51,7 +53,12 @@
|
|||
</svelte:head>
|
||||
|
||||
<div data-theme={$themeStore} class="min-h-screen">
|
||||
<Header />
|
||||
<Notifications />
|
||||
<SidebarNav>
|
||||
<Header />
|
||||
<div class="px-4">
|
||||
<slot />
|
||||
</div>
|
||||
</SidebarNav>
|
||||
<Footer />
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,108 +1,11 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { onDestroy } from 'svelte'
|
||||
|
||||
import { appName } from '$lib/app-info'
|
||||
import { sessionStore } from '../stores'
|
||||
import type { Session } from '$lib/session'
|
||||
import Shield from '$components/icons/Shield.svelte'
|
||||
|
||||
let session: Session
|
||||
|
||||
const unsubscribe = sessionStore.subscribe(val => {
|
||||
session = val
|
||||
})
|
||||
|
||||
onDestroy(unsubscribe)
|
||||
import Authed from '$components/home/Authed.svelte'
|
||||
import Public from '$components/home/Public.svelte'
|
||||
</script>
|
||||
|
||||
<div class="grid grid-flow-row auto-rows-max gap-5 justify-items-center pb-5">
|
||||
<h1 class="text-2xl">Welcome to {appName}!</h1>
|
||||
|
||||
{#if session?.authed}
|
||||
<div class="card card-bordered w-96 dark:border-slate-600">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">👋 Account</h2>
|
||||
<p>
|
||||
Your username is
|
||||
<span
|
||||
class="inline-block px-2 font-mono bg-slate-300 dark:bg-slate-700 rounded-md"
|
||||
>
|
||||
{session.username}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
{#if session.backupCreated}
|
||||
<p>✅ You have connected your account on another device.</p>
|
||||
{#if $sessionStore?.authed}
|
||||
<Authed />
|
||||
{:else}
|
||||
<p>
|
||||
<span
|
||||
class="h-7 w-7 inline-block bg-orange-300 rounded-full font-normal text-center"
|
||||
>
|
||||
<Shield />
|
||||
</span>
|
||||
|
||||
You have not connected your account on another device.
|
||||
</p>
|
||||
<Public />
|
||||
{/if}
|
||||
<div class="card-actions justify-center mt-3">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
on:click={() => goto('/delegate-account')}
|
||||
>
|
||||
Connect a new device
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card w-96 card-bordered dark:border-slate-600">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">📷 Photo Gallery Demo</h2>
|
||||
<p>
|
||||
Try out the Webnative File System by storing your photos in public and
|
||||
private storage.
|
||||
</p>
|
||||
<div class="card-actions justify-center">
|
||||
<a class="btn btn-primary" href="/gallery">Go to Photos</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
<div class="card card-bordered w-96 dark:border-slate-600">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">About</h2>
|
||||
<p>
|
||||
This app is a template for building apps with the
|
||||
<a
|
||||
class="link link-primary whitespace-nowrap"
|
||||
href="https://github.com/fission-codes/webnative"
|
||||
target="_blank"
|
||||
>
|
||||
Webnative SDK
|
||||
<span class="-scale-x-100 scale-y-100 inline-block">⎋</span>
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
Get started
|
||||
<a
|
||||
class="link link-primary"
|
||||
href="https://github.com/fission-codes/webnative-app-template"
|
||||
target="_blank"
|
||||
>
|
||||
using this template
|
||||
<span class="-scale-x-100 scale-y-100 inline-block">⎋</span>
|
||||
</a>
|
||||
and learn more in the
|
||||
<a
|
||||
class="link link-primary"
|
||||
href="https://guide.fission.codes/developers/webnative"
|
||||
target="_blank"
|
||||
>
|
||||
Webnative Guide
|
||||
<span class="-scale-x-100 scale-y-100 inline-block">⎋</span>
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<script lang="ts">
|
||||
import AboutThisTemplate from '$components/about/AboutThisTemplate.svelte'
|
||||
</script>
|
||||
|
||||
<AboutThisTemplate />
|
||||
|
|
@ -48,8 +48,11 @@
|
|||
connectionLink = `${origin}/link-device?username=${username}`
|
||||
qrcode = new QRCode({
|
||||
content: connectionLink,
|
||||
color: $themeStore === 'light' ? '#334155' : '#E2E8F0',
|
||||
background: '#ffffff00'
|
||||
color: $themeStore === 'light' ? '#171717' : '#FAFAFA',
|
||||
background: $themeStore === 'light' ? '#FAFAFA' : '#171717',
|
||||
padding: 0,
|
||||
width: 216,
|
||||
height: 216
|
||||
}).svg()
|
||||
|
||||
initAccountLinkingProducer(username)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { onDestroy } from 'svelte'
|
||||
import { goto } from '$app/navigation'
|
||||
|
||||
import { sessionStore, themeStore } from '$src/stores'
|
||||
import { sessionStore } from '$src/stores'
|
||||
import { AREAS, galleryStore } from '$routes/gallery/stores'
|
||||
import Dropzone from '$routes/gallery/components/upload/Dropzone.svelte'
|
||||
import ImageGallery from '$routes/gallery/components/imageGallery/ImageGallery.svelte'
|
||||
|
|
@ -27,22 +27,19 @@
|
|||
onDestroy(unsubscribe)
|
||||
</script>
|
||||
|
||||
<div class="p-2 text-center">
|
||||
<div class="p-2 mb-14 text-center">
|
||||
{#if $sessionStore.authed}
|
||||
<div class="flex mb-4">
|
||||
<div
|
||||
class="tabs tabs-boxed w-fit border {$themeStore === 'light'
|
||||
? 'button-transparent'
|
||||
: 'border-primary'}"
|
||||
>
|
||||
<div class="flex items-center justify-center translate-y-1/2 w-fit m-auto">
|
||||
<div class="tabs border-2 overflow-hidden border-base-content rounded-lg">
|
||||
{#each Object.keys(AREAS) as area}
|
||||
<button
|
||||
on:click={() => handleChangeTab(AREAS[area])}
|
||||
class="tab {$galleryStore.selectedArea === AREAS[area]
|
||||
? 'tab-active'
|
||||
: 'hover:text-primary'} ease-in"
|
||||
class="tab h-10 font-bold text-sm ease-in {$galleryStore.selectedArea ===
|
||||
AREAS[area]
|
||||
? 'tab-active bg-base-content text-base-100'
|
||||
: 'bg-base-100 text-base-content'}"
|
||||
>
|
||||
{AREAS[area]} WNFS
|
||||
{AREAS[area]} Photos
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,9 @@
|
|||
<script lang="ts">
|
||||
export let classes: string = 'mb-3 w-10 h-10'
|
||||
</script>
|
||||
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class={classes}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="66" fill="none">
|
||||
<path
|
||||
stroke="#171717"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M7 16a4 4 0 0 1-.88-7.903A5 5 0 1 1 15.9 6h.1a5 5 0 0 1 1 9.9M15 13l-3-3m0 0-3 3m3-3v12"
|
||||
d="M14.167 45.667C7.17 45.667 1.5 39.996 1.5 33c0-6.039 4.226-11.09 9.882-12.36A15.89 15.89 0 0 1 11 17.167c0-8.745 7.089-15.834 15.833-15.834 7.662 0 14.052 5.441 15.518 12.67.105-.002.21-.003.316-.003C51.41 14 58.5 21.089 58.5 29.833c0 7.66-5.44 14.05-12.667 15.517M39.5 36.167l-9.5-9.5m0 0-9.5 9.5m9.5-9.5v38"
|
||||
/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 413 B After Width: | Height: | Size: 510 B |
|
|
@ -2,20 +2,19 @@
|
|||
import type { Image } from '$routes/gallery/lib/gallery'
|
||||
|
||||
export let image: Image
|
||||
export let openModal
|
||||
export let openModal: (image: Image) => void
|
||||
|
||||
const handleOpenModal = () => openModal(image)
|
||||
</script>
|
||||
|
||||
<div class="flex flex-wrap w-1/2 sm:w-1/4 lg:w-1/6">
|
||||
<div
|
||||
class="relative group w-full m-1 md:m-2 rounded-lg border-4 border-transparent hover:border-primary overflow-hidden transition-colors ease-in"
|
||||
class="relative group w-full aspect-[22/23] rounded-lg border-2 border-transparent hover:border-base-content box-border overflow-hidden transition-colors ease-in"
|
||||
on:click={handleOpenModal}
|
||||
>
|
||||
<div
|
||||
class="flex items-center justify-center absolute z-10 top-0 right-0 bottom-0 left-0 bg-[#00000035] opacity-0 group-hover:opacity-100 transition-opacity ease-in"
|
||||
/>
|
||||
<div class="relative pb-[100%]">
|
||||
<div class="relative pb-[105%]">
|
||||
<img
|
||||
class="absolute block object-cover object-center w-full h-full"
|
||||
alt={`Gallery Image: ${image.name}`}
|
||||
|
|
@ -23,4 +22,3 @@
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -49,8 +49,10 @@
|
|||
</script>
|
||||
|
||||
<section class="overflow-hidden text-gray-700">
|
||||
<div class="p-4 mx-auto">
|
||||
<div class="flex flex-wrap -m-1 md:-m-2">
|
||||
<div class="pt-8 p-6 md:p-8 mx-auto">
|
||||
<div
|
||||
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:lg:grid-cols-6 gap-4"
|
||||
>
|
||||
<FileUploadCard />
|
||||
{#each $galleryStore.selectedArea === AREAS.PRIVATE ? $galleryStore.privateImages : $galleryStore.publicImages as image}
|
||||
<ImageCard {image} openModal={setSelectedImage} />
|
||||
|
|
|
|||
|
|
@ -102,18 +102,16 @@
|
|||
class="modal cursor-pointer z-50"
|
||||
on:click|self={handleCloseModal}
|
||||
>
|
||||
<div
|
||||
class="modal-box relative text-center text-base-content border dark:border-slate-600"
|
||||
>
|
||||
<div class="modal-box relative text-center text-base-content">
|
||||
<label
|
||||
for={`image-modal-${image.cid}`}
|
||||
class="btn btn-xs btn-circle absolute right-2 top-2 dark:bg-slate-600"
|
||||
class="btn btn-xs btn-circle absolute right-2 top-2"
|
||||
on:click={handleCloseModal}
|
||||
>
|
||||
✕
|
||||
</label>
|
||||
<div>
|
||||
<h3 class="mb-7 text-xl font-serif">{image.name}</h3>
|
||||
<h3 class="mb-7 text-lg break-all">{image.name}</h3>
|
||||
|
||||
<div class="relative">
|
||||
{#if showPreviousArrow}
|
||||
|
|
@ -125,7 +123,7 @@
|
|||
</button>
|
||||
{/if}
|
||||
<img
|
||||
class="block object-cover object-center w-full h-full mb-4 rounded-[1rem]"
|
||||
class="block object-cover object-center border-2 border-base-content w-full h-full mb-4 rounded-[1rem]"
|
||||
alt={`Image: ${image.name}`}
|
||||
src={image.src}
|
||||
/>
|
||||
|
|
@ -153,10 +151,7 @@
|
|||
<a href={image.src} download={image.name} class="btn btn-primary">
|
||||
Download Image
|
||||
</a>
|
||||
<button
|
||||
class="btn bg-error text-white"
|
||||
on:click={handleDeleteImage}
|
||||
>
|
||||
<button class="btn btn-outline" on:click={handleDeleteImage}>
|
||||
Delete Image
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
// Iterate over the dropped files and upload them to WNFS
|
||||
await Promise.all(
|
||||
files.map(async (item, index) => {
|
||||
files.map(async item => {
|
||||
if (item.kind === 'file') {
|
||||
const file: File = item.getAsFile()
|
||||
|
||||
|
|
@ -61,8 +61,8 @@
|
|||
on:dragenter={handleDragEnter}
|
||||
on:dragleave={handleDragLeave}
|
||||
for="dropzone-file"
|
||||
class="block w-full min-h-[calc(100vh-154px)] rounded-lg border-2 border-gray-300 border-dashed transition-colors ease-in cursor-pointer {isDragging
|
||||
? '!border-primary'
|
||||
class="block w-full min-h-[calc(100vh-190px)] rounded-lg border-2 border-solid border-base-content transition ease-in cursor-pointer {isDragging
|
||||
? 'border-dashed !border-orange-700 bg-orange-50'
|
||||
: ''}"
|
||||
>
|
||||
<slot />
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
import { galleryStore } from '$routes/gallery/stores'
|
||||
import { handleFileInput } from '$routes/gallery/lib/gallery'
|
||||
import FileUploadIcon from '$routes/gallery/components/icons/FileUploadIcon.svelte'
|
||||
import LoadingSpinner from '$components/common/LoadingSpinner.svelte'
|
||||
|
||||
// Handle files uploaded directly through the file input
|
||||
let files: FileList
|
||||
|
|
@ -11,22 +10,23 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<div class="flex flex-wrap w-1/2 sm:w-1/4 lg:w-1/6">
|
||||
<label
|
||||
for="upload-file"
|
||||
class="group flex flex-col justify-center items-center w-full m-2 md:m-3 object-cover rounded-lg hover:border-primary overflow-hidden text-gray-500 dark:text-gray-400 hover:text-primary transition-colors ease-in bg-base-100 border-2 box-border border-gray-300 border-dashed cursor-pointer"
|
||||
class="group flex flex-col justify-center items-center aspect-[22/23] object-cover rounded-lg shadow-orange hover:border-neutral-50 overflow-hidden transition-colors ease-in bg-base-100 border-2 box-content border-neutral cursor-pointer text-neutral bg-gradient-to-r from-orange-600 to-orange-300"
|
||||
>
|
||||
{#if $galleryStore.loading}
|
||||
<div class="flex justify-center items-center p-12">
|
||||
<LoadingSpinner />
|
||||
<div
|
||||
class="loader ease-linear rounded-full border-4 border-t-4 border-t-orange-300 border-neutral h-16 w-16 animate-spin"
|
||||
/>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col justify-center items-center pt-5 pb-6">
|
||||
<FileUploadIcon />
|
||||
<p class="mb-2 text-sm">
|
||||
<span class="font-semibold">Click to upload</span>
|
||||
<p class="mt-4 mb-2 text-sm">
|
||||
<span class="font-bold text-sm">Upload a photo</span>
|
||||
</p>
|
||||
<p class="text-xs">SVG, PNG, JPG or GIF</p>
|
||||
<p class="text-xxs">SVG, PNG, JPG or GIF</p>
|
||||
</div>
|
||||
<input
|
||||
bind:files
|
||||
|
|
@ -38,4 +38,3 @@
|
|||
/>
|
||||
{/if}
|
||||
</label>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation'
|
||||
import { sessionStore } from '$src/stores'
|
||||
import AvatarUpload from '$components/settings/AvatarUpload.svelte'
|
||||
import ThemePreferences from '$components/settings/ThemePreferences.svelte'
|
||||
</script>
|
||||
|
||||
{#if $sessionStore.authed}
|
||||
<div
|
||||
class="min-h-[calc(100vh-128px)] md:min-h-[calc(100vh-160px)] pt-8 md:pt-16 flex flex-col items-start max-w-[690px] m-auto gap-10 pb-5 text-sm"
|
||||
>
|
||||
<h1 class="text-xl">Account Settings</h1>
|
||||
|
||||
<div class="flex flex-col items-start justify-center gap-6">
|
||||
<div>
|
||||
<AvatarUpload />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="text-lg mb-4">Username</h3>
|
||||
<p>{$sessionStore.username}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<ThemePreferences />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 class="text-lg mb-4">Connected devices</h3>
|
||||
{#if $sessionStore.backupCreated}
|
||||
<p class="mb-4">
|
||||
You've already connected an additional device, but you can connect
|
||||
more.
|
||||
</p>
|
||||
{:else}
|
||||
<p class="mb-4">You have no other connected devices.</p>
|
||||
{/if}
|
||||
<a class="btn btn-primary" href="/delegate-account">
|
||||
Connect an additional device
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
{goto('/')}
|
||||
{/if}
|
||||
|
|
@ -3,6 +3,7 @@ import type { Writable } from 'svelte/store'
|
|||
import type FileSystem from 'webnative/fs/index'
|
||||
|
||||
import { loadTheme } from '$lib/theme'
|
||||
import type { AccountSettings } from '$lib/account-settings'
|
||||
import type { Notification } from '$lib/notifications'
|
||||
import type { Session } from '$lib/session'
|
||||
import type { Theme } from '$lib/theme'
|
||||
|
|
@ -19,3 +20,8 @@ export const sessionStore: Writable<Session> = writable({
|
|||
export const filesystemStore: Writable<FileSystem | null> = writable(null)
|
||||
|
||||
export const notificationStore: Writable<Notification[]> = writable([])
|
||||
|
||||
export const accountSettingsStore: Writable<AccountSettings> = writable({
|
||||
avatar: null,
|
||||
loading: true,
|
||||
})
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 7.2 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 13 KiB |
|
|
@ -1,11 +1,3 @@
|
|||
<svg width="119" height="119" viewBox="0 0 119 119" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_102_3)">
|
||||
<rect width="119" height="119" fill="#202124"/>
|
||||
<path d="M6.936 92.384L14.232 24.224C17.24 24.096 20.056 23.808 22.68 23.36C25.368 22.848 28.024 22.496 30.648 22.304C30.648 22.368 30.552 23.04 30.36 24.32C30.168 25.536 29.912 27.168 29.592 29.216C29.272 31.2 28.92 33.472 28.536 36.032C28.152 38.528 27.576 41.984 26.808 46.4C26.104 50.816 25.144 56.928 23.928 64.736H25.368C27.032 58.848 28.408 54.048 29.496 50.336C30.584 46.56 31.448 43.52 32.088 41.216C32.792 38.848 33.432 36.576 34.008 34.4C34.648 32.224 35.224 30.208 35.736 28.352C36.312 26.496 36.76 24.928 37.08 23.648H37.944C39.096 23.648 40.248 23.584 41.4 23.456C42.616 23.328 43.736 23.2 44.76 23.072C45.848 22.88 46.968 22.656 48.12 22.4C47.992 22.976 47.832 24.16 47.64 25.952C47.512 27.744 47.32 29.92 47.064 32.48C46.808 34.976 46.552 37.76 46.296 40.832C46.04 43.84 45.784 46.816 45.528 49.76C45.272 52.64 45.016 55.392 44.76 58.016C44.568 60.64 44.376 62.88 44.184 64.736H45.912L55.032 23.456C57.208 23.136 59.352 22.848 61.464 22.592C63.32 22.336 65.24 22.08 67.224 21.824C69.208 21.568 70.968 21.28 72.504 20.96C71.544 23.648 70.584 26.656 69.624 29.984C68.664 33.248 67.672 36.704 66.648 40.352C65.624 44 64.632 47.68 63.672 51.392C62.776 55.104 61.88 58.688 60.984 62.144C58.936 70.336 56.952 78.752 55.032 87.392L33.336 91.04L37.56 53.984H36.408L26.904 88.832L6.936 92.384ZM61.2323 92.48C63.0243 83.456 64.7523 74.656 66.4163 66.08C67.0563 62.496 67.7283 58.752 68.4323 54.848C69.2003 50.88 69.9043 47.008 70.5443 43.232C71.1843 39.392 71.7603 35.712 72.2723 32.192C72.8483 28.608 73.2963 25.344 73.6163 22.4C75.6003 22.272 77.5203 22.144 79.3763 22.016C81.0403 21.888 82.7363 21.792 84.4643 21.728C86.1923 21.6 87.7283 21.472 89.0723 21.344C89.9043 26.272 90.6403 30.976 91.2803 35.456C91.6003 37.376 91.9203 39.392 92.2403 41.504C92.6243 43.552 92.9763 45.536 93.2963 47.456C93.6163 49.376 93.9363 51.232 94.2563 53.024C94.5763 54.752 94.8963 56.288 95.2163 57.632C95.4723 56.288 95.7603 54.752 96.0803 53.024C96.4003 51.232 96.7523 49.376 97.1363 47.456C97.5203 45.472 97.9043 43.456 98.2883 41.408C98.7363 39.36 99.1523 37.376 99.5363 35.456C100.496 30.976 101.488 26.304 102.512 21.44L114.224 20C112.048 29.6 110.128 38.688 108.464 47.264C107.696 50.976 106.928 54.72 106.16 58.496C105.456 62.272 104.784 65.92 104.144 69.44C103.504 72.96 102.96 76.224 102.512 79.232C102.064 82.176 101.712 84.672 101.456 86.72C101.264 86.72 100.496 86.88 99.1523 87.2C97.8723 87.456 96.3683 87.776 94.6403 88.16C92.9763 88.544 91.2803 88.96 89.5523 89.408C87.8883 89.792 86.6403 90.112 85.8083 90.368C85.3603 85.184 84.8803 80.256 84.3683 75.584C84.1763 73.6 83.9523 71.552 83.6963 69.44C83.4403 67.328 83.1843 65.312 82.9283 63.392C82.7363 61.472 82.5123 59.68 82.2563 58.016C82.0643 56.288 81.8723 54.848 81.6803 53.696C81.4883 54.848 81.2323 56.256 80.9123 57.92C80.5923 59.584 80.2723 61.376 79.9523 63.296C79.6323 65.152 79.3123 67.104 78.9923 69.152C78.6723 71.136 78.3203 73.088 77.9363 75.008C77.1043 79.552 76.2083 84.288 75.2483 89.216L61.2323 92.48Z" fill="#E8EAED"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_102_3">
|
||||
<rect width="119" height="119" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<svg width="41" height="40" viewBox="0 0 41 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.80014 0C2.11147 0 0.5 1.5988 0.5 5.33333V34.6667C0.5 38.2546 2.15638 40 5.80014 40H34.9509C38.6237 40 40.2511 38.3217 40.2511 34.6667V20V5.33333C40.2511 1.66328 38.5933 0 34.9509 0H5.80014ZM9.61977 26.3973L11.4071 8.19874C11.5721 6.51804 10.2601 5.06087 8.5817 5.06087C6.54113 5.06087 5.00311 7.25162 5.56756 9.33737C6.32321 12.1297 7.05409 15.8329 7.1008 19.8269C7.12801 22.1528 6.89382 24.4032 6.5413 26.4418C6.18692 28.4913 6.74291 30.6292 7.91183 32.2521C9.078 33.8711 10.8225 34.939 12.8345 34.939H13.8722C16.4179 34.939 18.4816 32.8623 18.4816 30.3007V28.366C18.4816 27.2024 17.6418 26.2111 16.5001 26.027L15.0877 25.7993C14.5066 25.7056 13.9681 26.1263 13.9142 26.716L13.9058 26.8085C13.804 27.9234 12.8747 28.7766 11.7621 28.7766C10.4895 28.7766 9.49461 27.6717 9.61977 26.3973ZM18.4816 20.6202V13.0906C18.4816 12.0593 19.3125 11.2232 20.3374 11.2232C21.3623 11.2232 22.1931 12.0593 22.1931 13.0906V29.3368C22.1931 32.4308 24.6857 34.939 27.7604 34.939H27.9968C31.9921 34.939 34.9722 30.6591 34.2387 26.5283C33.873 24.4687 33.6186 22.1901 33.6186 19.8342C33.6186 15.7318 34.3901 11.9363 35.1823 9.11807C35.7362 7.14741 34.2829 5.06087 32.3573 5.06087C30.8068 5.06087 29.5853 6.39061 29.707 7.94602L31.1527 26.4221C31.2521 27.6914 30.2552 28.7766 28.9899 28.7766C27.8686 28.7766 26.932 27.9168 26.8294 26.7932L25.2537 9.53259C25.0224 6.99939 22.9109 5.06087 20.3828 5.06087C17.844 5.06087 15.7272 7.01542 15.5095 9.56072L14.4642 20.4466C14.3728 21.5149 15.1249 22.4697 16.1794 22.6241C17.3934 22.8019 18.4816 21.8547 18.4816 20.6202Z" fill="#171717"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 397 KiB |
|
After Width: | Height: | Size: 4.3 MiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 346 KiB |
|
|
@ -1,57 +1,130 @@
|
|||
module.exports = {
|
||||
mode: "jit",
|
||||
content: ["./src/**/*.{html,js,svelte,ts}"],
|
||||
plugins: [require("daisyui")],
|
||||
mode: 'jit',
|
||||
content: ['./src/**/*.{html,js,svelte,ts}'],
|
||||
plugins: [require('daisyui')],
|
||||
darkMode: ['class', '[data-theme="dark"]'],
|
||||
daisyui: {
|
||||
styled: true,
|
||||
themes: [
|
||||
{
|
||||
dark: {
|
||||
primary: "#3b82f6",
|
||||
secondary: "#30aadd",
|
||||
accent: "#00ffc6",
|
||||
neutral: "#282828",
|
||||
info: "#93c5fd",
|
||||
success: "#22c55e",
|
||||
warning: "#fdba74",
|
||||
error: "#ef4444",
|
||||
"base-content": "#f8fafc", // Base text content color
|
||||
"base-100": "#0f172a", // Base background color
|
||||
"--rounded-box": "16px",
|
||||
"--rounded-btn": "8px",
|
||||
"--rounded-badge": "2px",
|
||||
"--tab-radius": "2px",
|
||||
"--btn-text-case": "normal-case"
|
||||
primary: '#3b82f6',
|
||||
secondary: '#30aadd',
|
||||
accent: '#00ffc6',
|
||||
neutral: '#171717',
|
||||
info: '#93c5fd',
|
||||
success: '#BBF7D0',
|
||||
warning: '#fdba74',
|
||||
error: '#DC2626',
|
||||
'base-content': '#FAFAFA', // Base text content color
|
||||
'base-100': '#171717', // Base background color
|
||||
'--rounded-box': '16px',
|
||||
'--rounded-btn': '8px',
|
||||
'--rounded-badge': '2px',
|
||||
'--tab-radius': '2px',
|
||||
'--btn-text-case': 'normal-case',
|
||||
'--navbar-padding': '16px'
|
||||
},
|
||||
light: {
|
||||
primary: "#3b82f6",
|
||||
secondary: "#30aadd",
|
||||
accent: "#00ffc6",
|
||||
neutral: "#e5e5e5",
|
||||
info: "#bfdbfe",
|
||||
success: "#15803d",
|
||||
warning: "#fed7aa",
|
||||
error: "#b91c1c",
|
||||
"base-content": "#0f172a", // Base text content color
|
||||
"base-100": "#f8fafc", // Base background color
|
||||
"--rounded-box": "16px",
|
||||
"--rounded-btn": "8px",
|
||||
"--rounded-badge": "2px",
|
||||
"--tab-radius": "2px",
|
||||
"--btn-text-case": "normal-case"
|
||||
},
|
||||
},
|
||||
primary: '#3b82f6',
|
||||
secondary: '#30aadd',
|
||||
accent: '#00ffc6',
|
||||
neutral: '#171717',
|
||||
info: '#bfdbfe',
|
||||
success: '#BBF7D0',
|
||||
warning: '#fed7aa',
|
||||
error: '#DC2626',
|
||||
'base-content': '#171717', // Base text content color
|
||||
'base-100': '#FAFAFA', // Base background color
|
||||
'--rounded-box': '16px',
|
||||
'--rounded-btn': '8px',
|
||||
'--rounded-badge': '2px',
|
||||
'--tab-radius': '2px',
|
||||
'--btn-text-case': 'normal-case',
|
||||
'--navbar-padding': '16px'
|
||||
}
|
||||
}
|
||||
],
|
||||
base: true,
|
||||
utils: true,
|
||||
logs: true,
|
||||
rtl: false,
|
||||
darkTheme: "dark",
|
||||
darkTheme: 'dark'
|
||||
},
|
||||
theme: {
|
||||
extend: {
|
||||
animation: {
|
||||
marquee: 'marquee 20s linear infinite'
|
||||
},
|
||||
aspectRatio: {
|
||||
'22/23': '22 / 23'
|
||||
},
|
||||
boxShadow: {
|
||||
orange: '0px 8px 0px rgba(243, 110, 101, 0.2)'
|
||||
},
|
||||
color: {
|
||||
blue: {
|
||||
100: '#DBEAFE',
|
||||
900: '#1E3A8A'
|
||||
},
|
||||
green: {
|
||||
500: '#22C55E',
|
||||
700: '#15803D'
|
||||
},
|
||||
neutral: {
|
||||
50: '#FAFAFA',
|
||||
500: '#737373',
|
||||
800: '#262626'
|
||||
},
|
||||
orange: {
|
||||
50: '#FFF7ED',
|
||||
300: '#F26D64',
|
||||
500: '#F36E65',
|
||||
600: '#EED082',
|
||||
700: '#C2410C'
|
||||
},
|
||||
red: {
|
||||
600: '#DC2626'
|
||||
}
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['UncutSans_Regular'],
|
||||
semiBold: ['UncutSans_Medium'],
|
||||
bold: ['UncutSans_Bold']
|
||||
},
|
||||
fontSize: {
|
||||
mobileNav: ['24px', { lineHeight: '24px' }],
|
||||
deviceCode: ['30px', { lineHeight: '36px' }],
|
||||
xxs: ['12px', { lineHeight: '16px' }],
|
||||
xs: ['13px', { lineHeight: '24px', letterSpacing: '0.1em' }],
|
||||
sm: ['16px', { lineHeight: '24px' }],
|
||||
base: ['20px', { lineHeight: '28px' }],
|
||||
lg: ['24px', { lineHeight: '32px' }],
|
||||
xl: ['38px', { lineHeight: '48px' }],
|
||||
'2xl': ['50px', { lineHeight: '62px' }]
|
||||
},
|
||||
keyframes: {
|
||||
marquee: {
|
||||
'0%': { transform: 'translateX(102%)' },
|
||||
'100%': { transform: 'translateX(-100vw)' }
|
||||
}
|
||||
},
|
||||
width: {
|
||||
narrowModal: '327px',
|
||||
wideModal: '471px'
|
||||
},
|
||||
zIndex: {
|
||||
max: '1000' // High enough to appear above the modal(999)
|
||||
}
|
||||
// spacing: {
|
||||
// headerHeight: '64px',
|
||||
// footerHeight: '32px',
|
||||
// },
|
||||
}
|
||||
},
|
||||
purge: {
|
||||
options: {
|
||||
safelist: ['alert-success', 'alert-error', 'alert-info', 'alert-warning']
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||