fix: stuff

This commit is contained in:
Torsten Dittmann
2025-02-26 20:58:38 +04:00
parent a581e1ce38
commit 333bd9beb7
40 changed files with 661 additions and 1191 deletions
+7 -2
View File
@@ -22,7 +22,7 @@
"@appwrite.io/console": "https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@08ec153",
"@appwrite.io/pink-icons": "0.25.0",
"@appwrite.io/pink-icons-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@67808bca",
"@appwrite.io/pink-legacy": "^1.0.1",
"@appwrite.io/pink-legacy": "^1.0.2",
"@appwrite.io/pink-svelte": "https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@67808bca",
"@popperjs/core": "^2.11.8",
"@sentry/sveltekit": "^8.38.0",
@@ -80,5 +80,10 @@
"vitest": "^1.6.0"
},
"type": "module",
"packageManager": "pnpm@10.4.1"
"packageManager": "pnpm@10.4.1",
"pnpm": {
"overrides": {
"@appwrite.io/pink-svelte": "link:../../../../Library/pnpm/global/5/node_modules/@appwrite.io/pink-svelte"
}
}
}
+10 -447
View File
@@ -4,6 +4,9 @@ settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
overrides:
'@appwrite.io/pink-svelte': link:../../../../Library/pnpm/global/5/node_modules/@appwrite.io/pink-svelte
importers:
.:
@@ -18,11 +21,11 @@ importers:
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@67808bca
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@67808bca(svelte@4.2.19)
'@appwrite.io/pink-legacy':
specifier: ^1.0.1
version: 1.0.1
specifier: ^1.0.2
version: 1.0.2
'@appwrite.io/pink-svelte':
specifier: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@67808bca
version: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@67808bca(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)
specifier: link:../../../../Library/pnpm/global/5/node_modules/@appwrite.io/pink-svelte
version: link:../../../../Library/pnpm/global/5/node_modules/@appwrite.io/pink-svelte
'@popperjs/core':
specifier: ^2.11.8
version: 2.11.8
@@ -221,27 +224,14 @@ packages:
peerDependencies:
svelte: ^4.0.0
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@67808bca2fea00f91dddf487b43f79c085c032f1':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@67808bca2fea00f91dddf487b43f79c085c032f1}
version: 1.0.0-next.7
peerDependencies:
svelte: ^4.0.0
'@appwrite.io/pink-icons@0.25.0':
resolution: {integrity: sha512-0O3i2oEuh5mWvjO80i+X6rbzrWLJ1m5wmv2/M3a1p2PyBJsFxN8xQMTEmTn3Wl/D26SsM7SpzbdW6gmfgoVU9Q==}
'@appwrite.io/pink-icons@1.0.0':
resolution: {integrity: sha512-+zpksP07MvOYwhx9AZDFW0pxXQNC2juKwyOQVRAwAOkN1ACSQKPlyytkI1u2ci6CQPWjJe20CzbvBBuRNXOKjA==}
'@appwrite.io/pink-legacy@1.0.1':
resolution: {integrity: sha512-e5IZx2drqSxgl2WXvmr0eLfg/WiOCzuqQE8oksD+9GoFBkcL9HWvXul5GjFni3RBAN9XFRL3nUExGk4T0H8sFw==}
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@67808bca':
resolution: {tarball: https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@67808bca}
version: 1.0.0-next.85
peerDependencies:
react-dom: ^18.0.0
svelte: ^4.0.0
'@appwrite.io/pink-legacy@1.0.2':
resolution: {integrity: sha512-1AYNcfbV+x0Tyj56CoieSq5g7+u+7F5/LDVN/z+Hx1kp9gj7xc1eT39Dy832xxfihImF6ksjp0FXEMVSBR8cew==}
'@babel/code-frame@7.26.2':
resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
@@ -1232,27 +1222,6 @@ packages:
resolution: {integrity: sha512-zIieP1VLWQb3wUjFJlwOAoaaJygJhXeUoGd0e/Ha2RLb2eW2S+4gjf6y6NqyY71tZ74LYVZKg/4prB6FAZSMXQ==}
engines: {node: '>= 14'}
'@shikijs/core@1.29.2':
resolution: {integrity: sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ==}
'@shikijs/engine-javascript@1.29.2':
resolution: {integrity: sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A==}
'@shikijs/engine-oniguruma@1.29.2':
resolution: {integrity: sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==}
'@shikijs/langs@1.29.2':
resolution: {integrity: sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ==}
'@shikijs/themes@1.29.2':
resolution: {integrity: sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g==}
'@shikijs/types@1.29.2':
resolution: {integrity: sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==}
'@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
'@sinclair/typebox@0.27.8':
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
@@ -1362,9 +1331,6 @@ packages:
'@types/graceful-fs@4.1.9':
resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==}
'@types/hast@3.0.4':
resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
'@types/istanbul-lib-coverage@2.0.6':
resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==}
@@ -1374,9 +1340,6 @@ packages:
'@types/istanbul-reports@3.0.4':
resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==}
'@types/mdast@4.0.4':
resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
'@types/mysql@2.15.26':
resolution: {integrity: sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ==}
@@ -1392,15 +1355,9 @@ packages:
'@types/prismjs@1.26.5':
resolution: {integrity: sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==}
'@types/prop-types@15.7.14':
resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==}
'@types/pug@2.0.10':
resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==}
'@types/react@18.3.18':
resolution: {integrity: sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==}
'@types/remarkable@2.0.8':
resolution: {integrity: sha512-eKXqPZfpQl1kOADjdKchHrp2gwn9qMnGXhH/AtZe0UrklzhGJkawJo/Y/D0AlWcdWoWamFNIum8+/nkAISQVGg==}
@@ -1413,9 +1370,6 @@ packages:
'@types/tedious@4.0.14':
resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==}
'@types/unist@3.0.3':
resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==}
'@types/yargs-parser@21.0.3':
resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==}
@@ -1604,9 +1558,6 @@ packages:
resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==}
engines: {node: '>=10'}
ansicolor@2.0.3:
resolution: {integrity: sha512-pzusTqk9VHrjgMCcTPDTTvfJfx6Q3+L5tQ6yKC8Diexmoit4YROTFIkxFvRTNL9y5s0Q8HrSrgerCD5bIC+Kiw==}
anymatch@3.1.3:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'}
@@ -1741,9 +1692,6 @@ packages:
caniuse-lite@1.0.30001700:
resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==}
ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
chai@4.5.0:
resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==}
engines: {node: '>=4'}
@@ -1760,12 +1708,6 @@ packages:
resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
engines: {node: '>=10'}
character-entities-html4@2.1.0:
resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
character-entities-legacy@3.0.0:
resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
check-error@1.0.3:
resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==}
@@ -1809,9 +1751,6 @@ packages:
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
engines: {node: '>= 0.8'}
comma-separated-tokens@2.0.3:
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
concat-map@0.0.1:
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
@@ -1931,9 +1870,6 @@ packages:
devalue@5.1.1:
resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
diff-sequences@29.6.3:
resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1978,9 +1914,6 @@ packages:
resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==}
engines: {node: '>=12'}
emoji-regex-xs@1.0.0:
resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==}
emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
@@ -2184,9 +2117,6 @@ packages:
forwarded-parse@2.1.2:
resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==}
framesync@6.1.2:
resolution: {integrity: sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==}
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
@@ -2206,10 +2136,6 @@ packages:
functions-have-names@1.2.3:
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
fuse.js@7.1.0:
resolution: {integrity: sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==}
engines: {node: '>=10'}
gensync@1.0.0-beta.2:
resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
engines: {node: '>=6.9.0'}
@@ -2308,15 +2234,6 @@ packages:
resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
engines: {node: '>= 0.4'}
hast-util-to-html@9.0.5:
resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
hast-util-whitespace@3.0.0:
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
hey-listen@1.0.8:
resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==}
html-encoding-sniffer@3.0.0:
resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==}
engines: {node: '>=12'}
@@ -2324,9 +2241,6 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
html-void-elements@3.0.0:
resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
http-proxy-agent@5.0.0:
resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
engines: {node: '>= 6'}
@@ -2801,9 +2715,6 @@ packages:
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
engines: {node: '>= 0.4'}
mdast-util-to-hast@13.2.0:
resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
mdn-data@2.0.30:
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
@@ -2814,21 +2725,6 @@ packages:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
engines: {node: '>= 8'}
micromark-util-character@2.1.1:
resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==}
micromark-util-encode@2.0.1:
resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==}
micromark-util-sanitize-uri@2.0.1:
resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==}
micromark-util-symbol@2.0.1:
resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==}
micromark-util-types@2.0.1:
resolution: {integrity: sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==}
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
@@ -2977,9 +2873,6 @@ packages:
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
engines: {node: '>=12'}
oniguruma-to-es@2.3.0:
resolution: {integrity: sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g==}
optionator@0.9.4:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
@@ -3101,9 +2994,6 @@ packages:
engines: {node: '>=18'}
hasBin: true
popmotion@11.0.5:
resolution: {integrity: sha512-la8gPM1WYeFznb/JqF4GiTkRRPZsfaj2+kCxqQgr2MJylMmIKUwBfWW8Wa5fml/8gmtlD5yI01MP1QCZPWmppA==}
possible-typed-array-names@1.1.0:
resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==}
engines: {node: '>= 0.4'}
@@ -3195,9 +3085,6 @@ packages:
resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==}
engines: {node: '>= 6'}
property-information@7.0.0:
resolution: {integrity: sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==}
proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
@@ -3217,11 +3104,6 @@ packages:
queue-microtask@1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
react-dom@18.3.1:
resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
peerDependencies:
react: ^18.3.1
react-is@17.0.2:
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
@@ -3251,15 +3133,6 @@ packages:
regenerator-runtime@0.14.1:
resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==}
regex-recursion@5.1.1:
resolution: {integrity: sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w==}
regex-utilities@2.3.0:
resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
regex@5.1.1:
resolution: {integrity: sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw==}
regexp.prototype.flags@1.5.4:
resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==}
engines: {node: '>= 0.4'}
@@ -3349,9 +3222,6 @@ packages:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'}
scheduler@0.23.2:
resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
@@ -3390,9 +3260,6 @@ packages:
resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
engines: {node: '>=8'}
shiki@1.29.2:
resolution: {integrity: sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg==}
shimmer@1.2.1:
resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==}
@@ -3466,9 +3333,6 @@ packages:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
space-separated-tokens@2.0.2:
resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==}
sprintf-js@1.0.3:
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
@@ -3499,9 +3363,6 @@ packages:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
stringify-entities@4.0.4:
resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
@@ -3529,9 +3390,6 @@ packages:
strip-literal@2.1.1:
resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==}
style-value-types@5.1.2:
resolution: {integrity: sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==}
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
@@ -3577,11 +3435,6 @@ packages:
jest: '>= 27'
svelte: '>= 3'
svelte-motion@0.12.2:
resolution: {integrity: sha512-7RrdRz9iVP55B9HT/C0hYW3pyrKlF61kAby/AkDtOAP0uHFQDrfd0qQetDC81cEsK9b40jt+jfcqSAXcA7LPEw==}
peerDependencies:
svelte: '>=3.35.0 || ^4.0.0 || ^5.0.0 || ^5.0.0-next.0'
svelte-preprocess@5.1.4:
resolution: {integrity: sha512-IvnbQ6D6Ao3Gg6ftiM5tdbR6aAETwjhHV+UKGf5bHGYR69RQvF1ho0JKPcbUON4vy4R7zom13jPjgdOWCQ5hDA==}
engines: {node: '>= 16.0.0'}
@@ -3660,11 +3513,6 @@ packages:
resolution: {integrity: sha512-DIFm0kSNscVxtBmKkBiygAHB5otoqN1aVmJ3t57jZhJfCB7Np/lUSoTtSrvPFjmlBbMeOsb1VQ06cut1+rBYOg==}
engines: {node: '>=16'}
svelte-sonner@0.3.28:
resolution: {integrity: sha512-K3AmlySeFifF/cKgsYNv5uXqMVNln0NBAacOYgmkQStLa/UoU0LhfAACU6Gr+YYC8bOCHdVmFNoKuDbMEsppJg==}
peerDependencies:
svelte: ^3.0.0 || ^4.0.0 || ^5.0.0-next.1
svelte@4.2.19:
resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==}
engines: {node: '>=16'}
@@ -3744,9 +3592,6 @@ packages:
resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==}
engines: {node: '>=14'}
trim-lines@3.0.1:
resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
ts-api-utils@1.4.3:
resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==}
engines: {node: '>=16'}
@@ -3756,9 +3601,6 @@ packages:
tslib@2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
tslib@2.4.0:
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
tslib@2.7.0:
resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==}
@@ -3796,21 +3638,6 @@ packages:
undici-types@6.20.0:
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
unist-util-is@6.0.0:
resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
unist-util-position@5.0.0:
resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
unist-util-stringify-position@4.0.0:
resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
unist-util-visit-parents@6.0.1:
resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
unist-util-visit@5.0.0:
resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
universalify@0.2.0:
resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==}
engines: {node: '>= 4.0.0'}
@@ -3842,12 +3669,6 @@ packages:
resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==}
engines: {node: '>=10.12.0'}
vfile-message@4.0.2:
resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
vite-node@1.6.1:
resolution: {integrity: sha512-YAXkfvGtuTzwWbDSACdJSg4A4DZiAqckWe90Zapc/sEX3XvHcw1NdurM/6od8J207tSDqNbSsgdCacBgvJKFuA==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -4051,9 +3872,6 @@ packages:
zrender@5.6.1:
resolution: {integrity: sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==}
zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
snapshots:
'@adobe/css-tools@4.4.2': {}
@@ -4103,34 +3921,15 @@ snapshots:
dependencies:
svelte: 4.2.19
'@appwrite.io/pink-icons-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@67808bca2fea00f91dddf487b43f79c085c032f1(svelte@4.2.19)':
dependencies:
svelte: 4.2.19
'@appwrite.io/pink-icons@0.25.0': {}
'@appwrite.io/pink-icons@1.0.0': {}
'@appwrite.io/pink-legacy@1.0.1':
'@appwrite.io/pink-legacy@1.0.2':
dependencies:
'@appwrite.io/pink-icons': 1.0.0
the-new-css-reset: 1.11.3
'@appwrite.io/pink-svelte@https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-svelte@67808bca(react-dom@18.3.1(react@18.3.1))(svelte@4.2.19)':
dependencies:
'@appwrite.io/pink-icons-svelte': https://pkg.pr.new/appwrite/pink/@appwrite.io/pink-icons-svelte@67808bca2fea00f91dddf487b43f79c085c032f1(svelte@4.2.19)
'@floating-ui/dom': 1.6.13
'@melt-ui/pp': 0.3.2(@melt-ui/svelte@0.86.3(svelte@4.2.19))(svelte@4.2.19)
'@melt-ui/svelte': 0.86.3(svelte@4.2.19)
ansicolor: 2.0.3
fuse.js: 7.1.0
pretty-bytes: 6.1.1
react-dom: 18.3.1(react@18.3.1)
shiki: 1.29.2
svelte: 4.2.19
svelte-motion: 0.12.2(svelte@4.2.19)
svelte-sonner: 0.3.28(svelte@4.2.19)
'@babel/code-frame@7.26.2':
dependencies:
'@babel/helper-validator-identifier': 7.25.9
@@ -5259,41 +5058,6 @@ snapshots:
- encoding
- supports-color
'@shikijs/core@1.29.2':
dependencies:
'@shikijs/engine-javascript': 1.29.2
'@shikijs/engine-oniguruma': 1.29.2
'@shikijs/types': 1.29.2
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
hast-util-to-html: 9.0.5
'@shikijs/engine-javascript@1.29.2':
dependencies:
'@shikijs/types': 1.29.2
'@shikijs/vscode-textmate': 10.0.2
oniguruma-to-es: 2.3.0
'@shikijs/engine-oniguruma@1.29.2':
dependencies:
'@shikijs/types': 1.29.2
'@shikijs/vscode-textmate': 10.0.2
'@shikijs/langs@1.29.2':
dependencies:
'@shikijs/types': 1.29.2
'@shikijs/themes@1.29.2':
dependencies:
'@shikijs/types': 1.29.2
'@shikijs/types@1.29.2':
dependencies:
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
'@shikijs/vscode-textmate@10.0.2': {}
'@sinclair/typebox@0.27.8': {}
'@sinonjs/commons@3.0.1':
@@ -5428,10 +5192,6 @@ snapshots:
dependencies:
'@types/node': 22.13.4
'@types/hast@3.0.4':
dependencies:
'@types/unist': 3.0.3
'@types/istanbul-lib-coverage@2.0.6': {}
'@types/istanbul-lib-report@3.0.3':
@@ -5442,10 +5202,6 @@ snapshots:
dependencies:
'@types/istanbul-lib-report': 3.0.3
'@types/mdast@4.0.4':
dependencies:
'@types/unist': 3.0.3
'@types/mysql@2.15.26':
dependencies:
'@types/node': 22.13.4
@@ -5466,15 +5222,8 @@ snapshots:
'@types/prismjs@1.26.5': {}
'@types/prop-types@15.7.14': {}
'@types/pug@2.0.10': {}
'@types/react@18.3.18':
dependencies:
'@types/prop-types': 15.7.14
csstype: 3.1.3
'@types/remarkable@2.0.8': {}
'@types/shimmer@1.2.0': {}
@@ -5485,8 +5234,6 @@ snapshots:
dependencies:
'@types/node': 22.13.4
'@types/unist@3.0.3': {}
'@types/yargs-parser@21.0.3': {}
'@types/yargs@17.0.33':
@@ -5739,8 +5486,6 @@ snapshots:
ansi-styles@5.2.0: {}
ansicolor@2.0.3: {}
anymatch@3.1.3:
dependencies:
normalize-path: 3.0.0
@@ -5897,8 +5642,6 @@ snapshots:
caniuse-lite@1.0.30001700: {}
ccount@2.0.1: {}
chai@4.5.0:
dependencies:
assertion-error: 1.1.0
@@ -5921,10 +5664,6 @@ snapshots:
char-regex@1.0.2: {}
character-entities-html4@2.1.0: {}
character-entities-legacy@3.0.0: {}
check-error@1.0.3:
dependencies:
get-func-name: 2.0.2
@@ -5977,8 +5716,6 @@ snapshots:
dependencies:
delayed-stream: 1.0.0
comma-separated-tokens@2.0.3: {}
concat-map@0.0.1: {}
confbox@0.1.8: {}
@@ -6097,10 +5834,6 @@ snapshots:
devalue@5.1.1: {}
devlop@1.1.0:
dependencies:
dequal: 2.0.3
diff-sequences@29.6.3: {}
dir-glob@3.0.1:
@@ -6138,8 +5871,6 @@ snapshots:
emittery@0.13.1: {}
emoji-regex-xs@1.0.0: {}
emoji-regex@8.0.0: {}
entities@4.5.0: {}
@@ -6420,10 +6151,6 @@ snapshots:
forwarded-parse@2.1.2: {}
framesync@6.1.2:
dependencies:
tslib: 2.4.0
fs.realpath@1.0.0: {}
fsevents@2.3.2:
@@ -6436,8 +6163,6 @@ snapshots:
functions-have-names@1.2.3: {}
fuse.js@7.1.0: {}
gensync@1.0.0-beta.2: {}
get-caller-file@2.0.5: {}
@@ -6535,34 +6260,12 @@ snapshots:
dependencies:
function-bind: 1.1.2
hast-util-to-html@9.0.5:
dependencies:
'@types/hast': 3.0.4
'@types/unist': 3.0.3
ccount: 2.0.1
comma-separated-tokens: 2.0.3
hast-util-whitespace: 3.0.0
html-void-elements: 3.0.0
mdast-util-to-hast: 13.2.0
property-information: 7.0.0
space-separated-tokens: 2.0.2
stringify-entities: 4.0.4
zwitch: 2.0.4
hast-util-whitespace@3.0.0:
dependencies:
'@types/hast': 3.0.4
hey-listen@1.0.8: {}
html-encoding-sniffer@3.0.0:
dependencies:
whatwg-encoding: 2.0.0
html-escaper@2.0.2: {}
html-void-elements@3.0.0: {}
http-proxy-agent@5.0.0:
dependencies:
'@tootallnate/once': 2.0.0
@@ -7221,41 +6924,12 @@ snapshots:
math-intrinsics@1.1.0: {}
mdast-util-to-hast@13.2.0:
dependencies:
'@types/hast': 3.0.4
'@types/mdast': 4.0.4
'@ungap/structured-clone': 1.3.0
devlop: 1.1.0
micromark-util-sanitize-uri: 2.0.1
trim-lines: 3.0.1
unist-util-position: 5.0.0
unist-util-visit: 5.0.0
vfile: 6.0.3
mdn-data@2.0.30: {}
merge-stream@2.0.0: {}
merge2@1.4.1: {}
micromark-util-character@2.1.1:
dependencies:
micromark-util-symbol: 2.0.1
micromark-util-types: 2.0.1
micromark-util-encode@2.0.1: {}
micromark-util-sanitize-uri@2.0.1:
dependencies:
micromark-util-character: 2.1.1
micromark-util-encode: 2.0.1
micromark-util-symbol: 2.0.1
micromark-util-symbol@2.0.1: {}
micromark-util-types@2.0.1: {}
micromatch@4.0.8:
dependencies:
braces: 3.0.3
@@ -7373,12 +7047,6 @@ snapshots:
dependencies:
mimic-fn: 4.0.0
oniguruma-to-es@2.3.0:
dependencies:
emoji-regex-xs: 1.0.0
regex: 5.1.1
regex-recursion: 5.1.1
optionator@0.9.4:
dependencies:
deep-is: 0.1.4
@@ -7492,13 +7160,6 @@ snapshots:
optionalDependencies:
fsevents: 2.3.2
popmotion@11.0.5:
dependencies:
framesync: 6.1.2
hey-listen: 1.0.8
style-value-types: 5.1.2
tslib: 2.4.0
possible-typed-array-names@1.1.0: {}
postcss-load-config@3.1.4(postcss@8.5.2):
@@ -7569,8 +7230,6 @@ snapshots:
kleur: 3.0.3
sisteransi: 1.0.5
property-information@7.0.0: {}
proxy-from-env@1.1.0: {}
psl@1.15.0:
@@ -7585,12 +7244,6 @@ snapshots:
queue-microtask@1.2.3: {}
react-dom@18.3.1(react@18.3.1):
dependencies:
loose-envify: 1.4.0
react: 18.3.1
scheduler: 0.23.2
react-is@17.0.2: {}
react-is@18.3.1: {}
@@ -7620,17 +7273,6 @@ snapshots:
regenerator-runtime@0.14.1: {}
regex-recursion@5.1.1:
dependencies:
regex: 5.1.1
regex-utilities: 2.3.0
regex-utilities@2.3.0: {}
regex@5.1.1:
dependencies:
regex-utilities: 2.3.0
regexp.prototype.flags@1.5.4:
dependencies:
call-bind: 1.0.8
@@ -7745,10 +7387,6 @@ snapshots:
dependencies:
xmlchars: 2.2.0
scheduler@0.23.2:
dependencies:
loose-envify: 1.4.0
semver@6.3.1: {}
semver@7.7.1: {}
@@ -7783,17 +7421,6 @@ snapshots:
shebang-regex@3.0.0: {}
shiki@1.29.2:
dependencies:
'@shikijs/core': 1.29.2
'@shikijs/engine-javascript': 1.29.2
'@shikijs/engine-oniguruma': 1.29.2
'@shikijs/langs': 1.29.2
'@shikijs/themes': 1.29.2
'@shikijs/types': 1.29.2
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
shimmer@1.2.1: {}
side-channel-list@1.0.0:
@@ -7879,8 +7506,6 @@ snapshots:
source-map@0.6.1: {}
space-separated-tokens@2.0.2: {}
sprintf-js@1.0.3: {}
sswr@2.0.0(svelte@4.2.19):
@@ -7912,11 +7537,6 @@ snapshots:
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
stringify-entities@4.0.4:
dependencies:
character-entities-html4: 2.1.0
character-entities-legacy: 3.0.0
strip-ansi@6.0.1:
dependencies:
ansi-regex: 5.0.1
@@ -7937,11 +7557,6 @@ snapshots:
dependencies:
js-tokens: 9.0.1
style-value-types@5.1.2:
dependencies:
hey-listen: 1.0.8
tslib: 2.4.0
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
@@ -7995,15 +7610,6 @@ snapshots:
jest: 29.7.0(@types/node@22.13.4)
svelte: 4.2.19
svelte-motion@0.12.2(svelte@4.2.19):
dependencies:
'@types/react': 18.3.18
framesync: 6.1.2
popmotion: 11.0.5
style-value-types: 5.1.2
svelte: 4.2.19
tslib: 2.8.1
svelte-preprocess@5.1.4(@babel/core@7.26.9)(postcss-load-config@3.1.4(postcss@8.5.2))(postcss@8.5.2)(sass@1.85.0)(svelte@4.2.19)(typescript@5.7.3):
dependencies:
'@types/pug': 2.0.10
@@ -8034,10 +7640,6 @@ snapshots:
svelte: 4.2.19
tslib: 2.7.0
svelte-sonner@0.3.28(svelte@4.2.19):
dependencies:
svelte: 4.2.19
svelte@4.2.19:
dependencies:
'@ampproject/remapping': 2.3.0
@@ -8122,16 +7724,12 @@ snapshots:
dependencies:
punycode: 2.3.1
trim-lines@3.0.1: {}
ts-api-utils@1.4.3(typescript@5.7.3):
dependencies:
typescript: 5.7.3
tslib@2.3.0: {}
tslib@2.4.0: {}
tslib@2.7.0: {}
tslib@2.8.1: {}
@@ -8154,29 +7752,6 @@ snapshots:
undici-types@6.20.0: {}
unist-util-is@6.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-position@5.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-stringify-position@4.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-visit-parents@6.0.1:
dependencies:
'@types/unist': 3.0.3
unist-util-is: 6.0.0
unist-util-visit@5.0.0:
dependencies:
'@types/unist': 3.0.3
unist-util-is: 6.0.0
unist-util-visit-parents: 6.0.1
universalify@0.2.0: {}
unplugin@1.0.1:
@@ -8213,16 +7788,6 @@ snapshots:
'@types/istanbul-lib-coverage': 2.0.6
convert-source-map: 2.0.0
vfile-message@4.0.2:
dependencies:
'@types/unist': 3.0.3
unist-util-stringify-position: 4.0.0
vfile@6.0.3:
dependencies:
'@types/unist': 3.0.3
vfile-message: 4.0.2
vite-node@1.6.1(@types/node@22.13.4)(sass@1.85.0):
dependencies:
cac: 6.7.14
@@ -8414,5 +7979,3 @@ snapshots:
zrender@5.6.1:
dependencies:
tslib: 2.3.0
zwitch@2.0.4: {}
+7 -15
View File
@@ -1,20 +1,12 @@
<script lang="ts">
export let radius: keyof typeof radiuses = 'small';
export let padding = 24;
let classes = '';
export { classes as class };
import { Card } from '@appwrite.io/pink-svelte';
import type Base from '@appwrite.io/pink-svelte/dist/card/Base.svelte';
import type { ComponentProps } from 'svelte';
enum radiuses {
xsmall = '--border-radius-xsmall',
small = '--border-radius-small',
medium = '--border-radius-medium',
large = '--border-radius-large'
}
export let radius: ComponentProps<Base>['radius'] = 'm';
export let padding: ComponentProps<Base>['padding'] = 's';
</script>
<div
class="box {classes}"
style:--box-border-radius={`var(${radiuses[radius]})`}
style:--box-padding={`${padding / 16}rem`}>
<Card.Base variant="secondary" {radius} {padding}>
<slot />
</div>
</Card.Base>
+5 -32
View File
@@ -1,39 +1,12 @@
<script lang="ts">
import { portal } from '$lib/actions/portal';
import { fly } from 'svelte/transition';
import { FloatingActionBar } from '@appwrite.io/pink-svelte';
export let show = false;
</script>
{#if show}
<div class="floating-action-bar" transition:fly={{ y: '6rem' }} use:portal>
<slot />
</div>
<FloatingActionBar>
<slot name="start" slot="start" />
<slot name="end" slot="end" />
</FloatingActionBar>
{/if}
<style lang="scss">
.floating-action-bar {
position: fixed;
bottom: 2rem;
left: 50%;
transform: translateX(-50%);
z-index: 100;
border-radius: 0.5rem;
padding: 0.75rem 1rem;
width: clamp(0px, calc(100vw - 4rem), 32.5rem);
}
:global(.theme-dark) .floating-action-bar {
border: 1px solid hsl(var(--color-neutral-85));
background: hsl(var(--color-neutral-90));
box-shadow: 0px 6px 16px 8px hsl(var(--color-neutral-105));
}
:global(.theme-light) .floating-action-bar {
border: 1px solid hsl(var(--color-neutral-15));
background: hsl(var(--color-neutral-0));
box-shadow: 0px 6px 16px 0px rgba(55, 59, 77, 0.14);
}
</style>
+2 -1
View File
@@ -6,6 +6,7 @@
export let tags: string[] = [];
export let placeholder = '';
export let disabled = false;
export let helper: string | undefined = undefined;
let value = '';
let error: string;
@@ -31,6 +32,6 @@
{placeholder}
{disabled}
bind:value={tags}
helper={error}
helper={error || helper}
on:invalid={handleInvalid}
state={error ? 'error' : 'default'} />
-3
View File
@@ -12,9 +12,6 @@
</script>
<Container>
<Layout.Stack direction="row" justifyContent="space-between">
<Typography.Title>Activity</Typography.Title>
</Layout.Stack>
{#if logs.total}
<Table.Root>
<svelte:fragment slot="header">
+1 -1
View File
@@ -13,6 +13,6 @@
</Button.Anchor>
</span>
{/if}
<Typography.Title color="--color-fgcolor-neutral-primary" size={$isSmallViewport ? 'm' : 'l'}>
<Typography.Title truncate color="--color-fgcolor-neutral-primary" size={$isSmallViewport ? 'm' : 'l'}>
<slot />
</Typography.Title>
-1
View File
@@ -3,7 +3,6 @@ export { default as Cover } from './cover.svelte';
export { default as CoverTitle } from './coverTitle.svelte';
export { default as Footer } from './footer.svelte';
export { default as Navigation } from './navigation.svelte';
export { default as Notification } from './notification.svelte';
export { default as Notifications } from './notifications.svelte';
export { default as Shell } from './shell.svelte';
export { default as Logs } from './logs.svelte';
-60
View File
@@ -1,60 +0,0 @@
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { fly } from 'svelte/transition';
import type { Notification } from '../stores/notifications';
export let type: Notification['type'] = 'info';
export let icon: Notification['icon'] = null;
export let title: Notification['title'];
export let buttons: Notification['buttons'];
export let message: Notification['message'];
export let html: Notification['isHtml'] = false;
const dispatch = createEventDispatcher();
</script>
<div
class="alert-sticky"
class:is-success={type === 'success'}
class:is-warning={type === 'warning'}
class:is-danger={type === 'error'}
class:is-info={type === 'info'}
transition:fly|global={{ x: 50 }}>
<button
class="button is-text is-only-icon"
style="--button-size:1.5rem;"
aria-label="close alert"
on:click={() => dispatch('dismiss')}>
<span class="icon-x" aria-hidden="true" />
</button>
<div class="alert-sticky-image">
<span
class:icon-check-circle={type === 'success' && !icon}
class:icon-exclamation={type === 'warning' && !icon}
class:icon-exclamation-circle={type === 'error' && !icon}
class:icon-info={type === 'info'}
class={icon ? `icon-${icon}` : ''}
aria-hidden="true" />
</div>
<div class="alert-sticky-content" data-private>
{#if title}
<h4 class="alert-sticky-title">{title}</h4>
{/if}
{#if html}
{@html message}
{:else}
<p>{message}</p>
{/if}
</div>
{#if buttons}
<div class="alert-sticky-buttons u-flex">
{#each buttons as button}
<button
class="button is-text is-small"
on:click|preventDefault|stopPropagation={button.method}>
<span class="text">{button.name}</span>
</button>
{/each}
</div>
{/if}
</div>
+9 -12
View File
@@ -1,25 +1,22 @@
<script lang="ts">
import Notification from './notification.svelte';
import { dismissNotification, notifications } from '../stores/notifications';
import { flip } from 'svelte/animate';
import { Layout, Toast } from '@appwrite.io/pink-svelte';
</script>
{#if $notifications}
<section>
<ul class="u-flex u-flex-vertical u-gap-16">
<Layout.Stack gap="s">
{#each $notifications as notification (notification.id)}
<li animate:flip={{ duration: 500 }}>
<Notification
type={notification.type}
<span animate:flip={{ duration: 500 }}>
<Toast
title={notification.title}
icon={notification.icon}
on:dismiss={() => dismissNotification(notification.id)}
buttons={notification?.buttons}
message={notification.message}
html={notification?.isHtml} />
</li>
status={notification.type}
description={notification.message}
on:dismiss={() => dismissNotification(notification.id)} />
</span>
{/each}
</ul>
</Layout.Stack>
</section>
{/if}
@@ -1,6 +1,6 @@
<script lang="ts">
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { CardGrid, Heading } from '$lib/components';
import { CardGrid } from '$lib/components';
import { InputPhone, InputOTP } from '$lib/elements/forms';
import { Button, Form } from '$lib/elements/forms';
import { sdk } from '$lib/stores/sdk';
@@ -18,7 +18,7 @@
import Empty from '$lib/components/empty.svelte';
import type { Models } from '@appwrite.io/console';
import { Icon, Input, Layout, Link, Tooltip } from '@appwrite.io/pink-svelte';
import { IconPlus, IconRefresh, IconX } from '@appwrite.io/pink-icons-svelte';
import { IconPlus, IconRefresh } from '@appwrite.io/pink-icons-svelte';
let numbers: Models.MockNumber[] = $project?.authMockNumbers ?? [];
let initialNumbers = [];
@@ -161,32 +161,34 @@
<span slot="tooltip">Regenerate</span>
</Tooltip>
</InputPhone>
<InputOTP
id={`value-${index}`}
bind:value={number.otp}
fullWidth
placeholder="Enter value"
label={index === 0 ? 'Verification code' : undefined}
maxlength={6}
pattern={'^[0-9]{6}$'}
patternError="The value must contain 6 digits"
required>
<Tooltip slot="end">
<Input.Action
icon={IconRefresh}
on:click={() => (number.otp = generateOTP())} />
<span slot="tooltip">Regenerate</span>
</Tooltip>
</InputOTP>
<Button
compact
size="s"
disabled={numbers.length === 0}
on:click={() => {
deletePhoneNumber(index);
}}>
<Icon icon={IconX} size="s" />
</Button>
<Layout.Stack direction="row" alignItems="flex-end" gap="xs">
<InputOTP
id={`value-${index}`}
bind:value={number.otp}
fullWidth
placeholder="Enter value"
label={index === 0 ? 'Verification code' : undefined}
maxlength={6}
pattern={'^[0-9]{6}$'}
patternError="The value must contain 6 digits"
required>
<Tooltip slot="end">
<Input.Action
icon={IconRefresh}
on:click={() => (number.otp = generateOTP())} />
<span slot="tooltip">Regenerate</span>
</Tooltip>
</InputOTP>
<Button
icon
compact
disabled={numbers.length === 0}
on:click={() => {
deletePhoneNumber(index);
}}>
<span class="icon-x" aria-hidden="true" />
</Button>
</Layout.Stack>
</Layout.Stack>
{/each}
{#if numbers?.length < 10}
@@ -6,15 +6,14 @@
import UpdatePrefs from './updatePrefs.svelte';
import UpdateName from './updateName.svelte';
import DangerZone from './dangerZone.svelte';
import { Typography } from '@appwrite.io/pink-svelte';
</script>
<Container>
<CardGrid>
<div class="grid-1-2-col-1 u-flex u-cross-center u-gap-16">
<AvatarInitials size="l" name={$team.name} />
<div>
<Heading tag="h6" size="7">{$team.name}</Heading>
</div>
<AvatarInitials name={$team.name} />
<Typography.Title size="s" truncate>{$team.name}</Typography.Title>
</div>
<svelte:fragment slot="aside">
<div>
@@ -2,10 +2,11 @@
import { base } from '$app/paths';
import { page } from '$app/stores';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { Modal, Alert } from '$lib/components';
import { Modal } from '$lib/components';
import { Button, InputEmail, InputText, InputTags, FormList } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { Alert } from '@appwrite.io/pink-svelte';
import { createEventDispatcher } from 'svelte';
export let showCreate = false;
@@ -43,7 +44,7 @@
}
</script>
<Modal title="Create membership" {error} onSubmit={create} size="big" bind:show={showCreate}>
<Modal title="Create membership" {error} onSubmit={create} bind:show={showCreate}>
<FormList>
<InputEmail
id="email"
@@ -52,12 +53,12 @@
required={true}
autofocus={true}
bind:value={email} />
<InputText id="name" label="Name (optional)" placeholder="Enter name" bind:value={name} />
<Alert type="info">
<InputText id="name" label="Name" placeholder="Enter name" bind:value={name} />
<Alert.Inline status="info">
Roles are used to manage access permissions. You can create any role you want.
</Alert>
</Alert.Inline>
<InputTags id="tags" label="Roles" placeholder="Add roles" bind:tags={roles} />
<InputTags id="tags" label="Roles" placeholder="Add roles" bind:tags={roles} helper="Roles are used to manage access permissions. You can create any role you want." />
</FormList>
<svelte:fragment slot="footer">
<Button text on:click={() => (showCreate = false)}>Cancel</Button>
@@ -1,5 +1,5 @@
<script lang="ts">
import { AvatarInitials, BoxAvatar, CardGrid, Heading } from '$lib/components';
import { AvatarInitials, BoxAvatar, CardGrid } from '$lib/components';
import { Button } from '$lib/elements/forms';
import DeleteTeam from './deleteTeam.svelte';
import { team } from './store';
@@ -14,7 +14,7 @@
<svelte:fragment slot="aside">
<BoxAvatar>
<svelte:fragment slot="image">
<AvatarInitials size="l" name={$team.name} />
<AvatarInitials name={$team.name} />
</svelte:fragment>
<svelte:fragment slot="title">
<h6 class="u-bold u-trim-1">{$team.name}</h6>
@@ -8,6 +8,7 @@
import { Button } from '$lib/elements/forms';
import { sdk } from '$lib/stores/sdk';
import type { Models } from '@appwrite.io/console';
import { Typography } from '@appwrite.io/pink-svelte';
import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
@@ -37,5 +38,8 @@
</script>
<Confirm onSubmit={deleteMembership} title="Delete member" bind:open={showDelete} bind:error>
Are you sure you want to delete <b>{selectedMembership.userName}</b> from '{selectedMembership.teamName}'?
<Typography.Text>
Are you sure you want to delete <b>{selectedMembership.userName}</b> from
<b>{selectedMembership.teamName}</b>?
</Typography.Text>
</Confirm>
@@ -6,6 +6,7 @@
import Confirm from '$lib/components/confirm.svelte';
import { sdk } from '$lib/stores/sdk';
import type { Models } from '@appwrite.io/console';
import { Typography } from '@appwrite.io/pink-svelte';
export let showDelete = false;
export let team: Models.Team<Record<string, unknown>>;
@@ -26,5 +27,7 @@
</script>
<Confirm onSubmit={deleteTeam} title="Delete team" bind:open={showDelete} bind:error>
Are you sure you want to delete <b>{team.name}</b>?
<Typography.Text>
Are you sure you want to delete <b>{team.name}</b>?
</Typography.Text>
</Confirm>
@@ -45,11 +45,12 @@
<Table.Header.Cell width="40px" />
</svelte:fragment>
{#each data.memberships.memberships as membership}
{@const username = membership.userName ? membership.userName : '-'}
<Table.Link href={`${base}/project-${project}/auth/user-${membership.userId}`}>
<Table.Cell>
<Layout.Stack direction="row" alignItems="center">
<AvatarInitials size="xs" name={membership.teamName} />
<span>{membership.teamName ? membership.teamName : 'n/a'}</span>
<AvatarInitials size="xs" name={username} />
<span>{username}</span>
</Layout.Stack>
</Table.Cell>
<Table.Cell>
@@ -6,6 +6,7 @@ import type { PageLoad } from './$types';
export const load: PageLoad = async ({ params, depends, url, route }) => {
depends(Dependencies.MEMBERSHIPS);
const teamId = params.team;
const page = getPage(url);
const search = getSearch(url);
@@ -1,7 +1,7 @@
<script lang="ts">
import { invalidate } from '$app/navigation';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { CardGrid, Heading } from '$lib/components';
import { CardGrid } from '$lib/components';
import { Dependencies } from '$lib/constants';
import { Button, Form, InputText } from '$lib/elements/forms';
import { addNotification } from '$lib/stores/notifications';
@@ -69,45 +69,51 @@
id={`key-${index}`}
bind:value={key}
placeholder="Enter key"
label="Key"
label={index === 0 ? 'Key' : undefined}
required />
<InputText
id={`value-${index}`}
bind:value
placeholder="Enter value"
label="Value"
required />
<Button
text
icon
disabled={(!key || !value) && index === 0}
on:click={() => {
if (index === 0 && prefs?.length === 1) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
}}>
<span class="icon-x" aria-hidden="true" />
</Button>
<Layout.Stack direction="row" alignItems="flex-end" gap="xs">
<InputText
id={`value-${index}`}
bind:value
placeholder="Enter value"
label={index === 0 ? 'Value' : undefined}
required />
<Button
icon
compact
disabled={(!key || !value) && index === 0}
on:click={() => {
if (index === 0 && prefs?.length === 1) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
}}>
<span class="icon-x" aria-hidden="true" />
</Button>
</Layout.Stack>
</Layout.Stack>
{/each}
{/if}
<Button
text
disabled={prefs?.length && prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]
? false
: true}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
}
}}>
<Icon icon={IconPlus} slot="start" size="s" />
Add Preference
</Button>
<div>
<Button
secondary
disabled={prefs?.length &&
prefs[prefs.length - 1][0] &&
prefs[prefs.length - 1][1]
? false
: true}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
}
}}>
<Icon icon={IconPlus} slot="start" size="s" />
Add preference
</Button>
</div>
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -5,4 +5,4 @@
export let data: PageData;
</script>
<Activity logs={data.logs} offset={data.offset} service="logs" />
<Activity logs={data.logs} offset={data.offset} limit={data.limit} />
@@ -8,6 +8,7 @@
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import type { Models } from '@appwrite.io/console';
import { Typography } from '@appwrite.io/pink-svelte';
export let showDelete = false;
export let selectedMembership: Models.Membership;
@@ -38,5 +39,8 @@
</script>
<Confirm onSubmit={deleteMembership} title="Delete member" bind:open={showDelete} bind:error>
Are you sure you want to delete <b>{selectedMembership.userName}</b> from '{selectedMembership.teamName}'?
<Typography.Text>
Are you sure you want to delete <b>{selectedMembership.userName}</b> from
<b>{selectedMembership.teamName}</b>?
</Typography.Text>
</Confirm>
@@ -8,6 +8,7 @@
import { project } from '../../store';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import Confirm from '$lib/components/confirm.svelte';
import { Typography } from '@appwrite.io/pink-svelte';
export let showDelete = false;
let error: string;
@@ -29,5 +30,7 @@
</script>
<Confirm onSubmit={deleteUser} title="Delete user" bind:open={showDelete} bind:error>
Are you sure you want to delete <b>{$user.name || 'User'}</b> from '{$project.name}'?
<Typography.Text>
Are you sure you want to delete <b>{$user.name || 'User'}</b> from <b>{$project.name}</b>?
</Typography.Text>
</Confirm>
@@ -1,11 +1,5 @@
<script lang="ts">
import {
PaginationWithLimit,
Heading,
ViewSelector,
EmptyFilter,
DropList
} from '$lib/components';
import { PaginationWithLimit, ViewSelector, EmptyFilter } from '$lib/components';
import { Container } from '$lib/layout';
import type { PageData } from './$types';
import Table from './table.svelte';
@@ -13,13 +7,12 @@
import { View } from '$lib/helpers/load';
import type { Column } from '$lib/helpers/types';
import { writable } from 'svelte/store';
import { Pill } from '$lib/elements';
import { Card, Empty } from '@appwrite.io/pink-svelte';
import { Card, Empty, Icon, Popover, Tag } from '@appwrite.io/pink-svelte';
import Button from '$lib/elements/forms/button.svelte';
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
export let data: PageData;
let showMoreInfo = false;
const columns = writable<Column[]>([
{ id: '$id', title: 'Identity ID', type: 'string', show: true, width: 140 },
{ id: 'provider', title: 'Provider', type: 'string', show: true, width: 80 },
@@ -41,43 +34,28 @@
<div class="u-flex u-flex-vertical">
<div class="u-flex u-main-space-between u-cross-center">
<div class="u-flex u-gap-16 u-cross-center">
<Heading tag="h2" size="5">Identities</Heading>
<DropList bind:show={showMoreInfo} width="16">
<Pill button on:click={() => (showMoreInfo = !showMoreInfo)}>
<span class="icon-info" />More info
</Pill>
<svelte:fragment slot="list">
<slot name="tooltip">
<p>
User identities are the user's connected OAuth accounts. The user
can sign in using these identities.
</p>
</slot>
</svelte:fragment>
</DropList>
<Popover let:toggle placement="bottom-start">
<Tag on:click={toggle}>
<Icon slot="start" icon={IconInfo} size="s" />
More info
</Tag>
<p slot="tooltip">
User identities are the user's connected OAuth accounts. <br /> The user can
sign in using these identities.
</p>
</Popover>
</div>
<!-- TODO: Remove when searching is added -->
<div class="u-flex u-main-end u-gap-16 is-not-mobile">
<Filters query={data.query} {columns} />
<div>
<ViewSelector
view={View.Table}
{columns}
hideView
allowNoColumns
showColsTextMobile />
<ViewSelector view={View.Table} {columns} hideView allowNoColumns />
</div>
</div>
</div>
<div class="u-flex u-gap-16 is-only-mobile u-margin-block-start-16">
<div class="u-flex-basis-50-percent">
<ViewSelector
view={View.Table}
{columns}
hideView
allowNoColumns
showColsTextMobile
fullWidthMobile />
<ViewSelector view={View.Table} {columns} hideView allowNoColumns fullWidthMobile />
</div>
<div class="u-flex-basis-50-percent">
<Filters query={data.query} {columns} fullWidthMobile />
@@ -1,17 +1,6 @@
<script lang="ts">
import { FloatingActionBar, Id, Modal } from '$lib/components';
import { FloatingActionBar, Id } from '$lib/components';
import { Button } from '$lib/elements/forms';
import {
TableBody,
TableCell,
TableCellCheck,
TableCellHead,
TableCellHeadCheck,
TableCellText,
TableHeader,
TableRow,
TableScroll
} from '$lib/elements/table';
import type { PageData } from './$types';
import { toLocaleDateTime } from '$lib/helpers/date';
import { sdk } from '$lib/stores/sdk';
@@ -23,6 +12,8 @@
import { oAuthProviders } from '$lib/stores/oauth-providers';
import { app } from '$lib/stores/app';
import { base } from '$app/paths';
import { Badge, Selector, Table, Typography } from '@appwrite.io/pink-svelte';
import Confirm from '$lib/components/confirm.svelte';
export let columns: Column[];
export let data: PageData;
@@ -59,95 +50,84 @@
}
</script>
<TableScroll>
<TableHeader>
<TableCellHeadCheck
bind:selected={selectedIds}
pageItemsIds={data.identities.identities.map((d) => d.$id)} />
<Table.Root>
<svelte:fragment slot="header">
<Table.Header.Selector width="40px" />
{#each columns as column}
{#if column.show}
<TableCellHead width={column.width}>{column.title}</TableCellHead>
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
{/if}
{/each}
</TableHeader>
<TableBody>
{#each data.identities.identities as identity (identity.$id)}
<TableRow>
<TableCellCheck bind:selectedIds id={identity.$id} />
</svelte:fragment>
{#each data.identities.identities as identity (identity.$id)}
<Table.Row>
<Table.Cell>
<Selector.Checkbox size="s" />
</Table.Cell>
{#each columns as column}
{#if column.show}
{#if column.id === '$id'}
{#key columns}
<TableCell title={column.title}>
<Id value={identity[column.id]}>
{identity[column.id]}
</Id>
</TableCell>
{/key}
{:else if column.id === 'provider'}
{@const provider = oAuthProviders[identity[column.id]]}
<TableCellText title={column.title} width={column.width}>
<div class="u-inline-flex u-cross-center u-gap-8">
<div class="avatar is-size-small">
<img
style="--p-text-size: 1rem"
height="20"
width="20"
src={`${base}/icons/${$app.themeInUse}/color/${provider.icon}.svg`}
alt={provider.name} />
</div>
{provider.name}
{#each columns as column}
{#if column.show}
{#if column.id === '$id'}
{#key columns}
<Table.Cell>
<Id value={identity[column.id]}>
{identity[column.id]}
</Id>
</Table.Cell>
{/key}
{:else if column.id === 'provider'}
{@const provider = oAuthProviders[identity[column.id]]}
<Table.Cell width={column.width + 'px'}>
<div class="u-inline-flex u-cross-center u-gap-8">
<div class="avatar is-size-small">
<img
style="--p-text-size: 1rem"
height="20"
width="20"
src={`${base}/icons/${$app.themeInUse}/color/${provider.icon}.svg`}
alt={provider.name} />
</div>
</TableCellText>
{:else if column.type === 'datetime'}
<TableCellText title={column.title} width={column.width}>
{#if !identity[column.id]}
-
{:else}
{toLocaleDateTime(identity[column.id])}
{/if}
</TableCellText>
{:else}
<TableCellText title={column.title} width={column.width}>
{identity[column.id]}
</TableCellText>
{/if}
{provider.name}
</div>
</Table.Cell>
{:else if column.type === 'datetime'}
<Table.Cell width={column.width + 'px'}>
{#if !identity[column.id]}
-
{:else}
{toLocaleDateTime(identity[column.id])}
{/if}
</Table.Cell>
{:else}
<Table.Cell width={column.width + 'px'}>
{identity[column.id]}
</Table.Cell>
{/if}
{/each}
</TableRow>
{/each}
</TableBody>
</TableScroll>
{/if}
{/each}
</Table.Row>
{/each}
</Table.Root>
<FloatingActionBar show={selectedIds.length > 0}>
<div class="u-flex u-cross-center u-main-space-between actions">
<div class="u-flex u-cross-center u-gap-8">
<span class="indicator body-text-2 u-bold">{selectedIds.length}</span>
<p>
<span class="is-only-desktop">
{selectedIds.length > 1 ? 'identities' : 'identity'}
</span>
selected
</p>
</div>
<div class="u-flex u-cross-center u-gap-8">
<Button text on:click={() => (selectedIds = [])}>Cancel</Button>
<Button secondary on:click={() => (showDelete = true)}>
<p>Delete</p>
</Button>
</div>
</div>
<svelte:fragment slot="start">
<Badge content={selectedIds.length.toString()} />
<span>
<span class="is-only-desktop">
{selectedIds.length > 1 ? 'identities' : 'identity'}
</span>
selected
</span>
</svelte:fragment>
<svelte:fragment slot="end">
<Button text on:click={() => (selectedIds = [])}>Cancel</Button>
<Button secondary on:click={() => (showDelete = true)}>Delete</Button>
</svelte:fragment>
</FloatingActionBar>
<Modal title="Delete identity" bind:show={showDelete} onSubmit={handleDelete} closable={!deleting}>
<p class="text" data-private>
<Confirm title="Delete Identity" bind:open={showDelete} onSubmit={handleDelete}>
<Typography.Text>
Are you sure you want to delete <b>{selectedIds.length}</b>
{selectedIds.length > 1 ? 'identities' : 'identity'}?
</p>
<svelte:fragment slot="footer">
<Button text on:click={() => (showDelete = false)} disabled={deleting}>Cancel</Button>
<Button secondary submit disabled={deleting}>Delete</Button>
</svelte:fragment>
</Modal>
</Typography.Text>
</Confirm>
@@ -1,36 +1,25 @@
<script lang="ts">
import { EmptySearch } from '$lib/components';
import { Pill } from '$lib/elements';
import { Button } from '$lib/elements/forms';
import {
TableBody,
TableCell,
TableCellHead,
TableCellText,
TableHeader,
TableRow,
TableScroll
} from '$lib/elements/table';
import { isValueOfStringEnum } from '$lib/helpers/types';
import { Container, ContainerHeader } from '$lib/layout';
import { Container } from '$lib/layout';
import { sdk } from '$lib/stores/sdk';
import { Browser } from '@appwrite.io/console';
import DeleteAllSessions from '../deleteAllSessions.svelte';
import DeleteSessions from '../deleteSession.svelte';
import type { PageData } from './$types';
import { Card, Empty, Layout } from '@appwrite.io/pink-svelte';
import { Badge, Card, Empty, Layout, Table } from '@appwrite.io/pink-svelte';
export let data: PageData;
let showDelete = false;
let showDeleteAll = false;
let selectedSessionId: string;
function getBrowser(clientCode: string) {
const code = clientCode.toLowerCase();
if (!isValueOfStringEnum(Browser, code)) return '';
return sdk.forProject.avatars.getBrowser(code, 40, 40);
}
let showDelete = false;
let showDeleteAll = false;
let selectedSessionId: string;
</script>
<Container>
@@ -40,21 +29,20 @@
<span class="text">Delete All</span>
</Button>
</Layout.Stack>
<TableScroll>
<TableHeader>
<TableCellHead width={140}>Browser and device</TableCellHead>
<TableCellHead width={140}>Session</TableCellHead>
<TableCellHead width={140}>Location</TableCellHead>
<TableCellHead width={140}>IP</TableCellHead>
<TableCellHead width={30} />
</TableHeader>
<TableBody>
{#each data.sessions.sessions as session}
{@const browser = getBrowser(session.clientCode)}
<TableRow>
<TableCell title="Client">
<div class="u-flex u-gap-12 u-cross-center">
<div class="avatar">
<Table.Root>
<svelte:fragment slot="header">
<Table.Header.Cell>Client</Table.Header.Cell>
<Table.Header.Cell>Location</Table.Header.Cell>
<Table.Header.Cell>IP</Table.Header.Cell>
<Table.Header.Cell width="40px" />
</svelte:fragment>
{#each data.sessions.sessions as session}
{@const browser = getBrowser(session.clientCode)}
<Table.Row>
<Table.Cell>
<Layout.Stack direction="row" alignItems="center">
{#if session.clientName}
<div class="avatar is-size-small">
{#if browser}
<img
height="20"
@@ -74,31 +62,36 @@
{session.clientVersion} on {session.osName}
{session.osVersion}
</p>
{#if session.current}
<Pill success>current session</Pill>
{/if}
</div>
</TableCell>
<TableCellText title="Session">{session.clientType}</TableCellText>
<TableCellText title="Location">{session.countryName}</TableCellText>
<TableCellText title="IP">{session.ip}</TableCellText>
<TableCell>
<Button
text
icon
ariaLabel="Delete item"
on:click={() => {
selectedSessionId = session.$id;
showDelete = true;
}}>
<span class="icon-trash" aria-hidden="true" />
</Button>
</TableCell>
</TableRow>
{/each}
</TableBody>
</TableScroll>
{:else}
<span class="avatar is-color-empty" />
<p class="text u-trim">Unknown</p>
{/if}
<Badge variant="secondary" content={session.provider} />
</Layout.Stack>
</Table.Cell>
<Table.Cell>
{#if session.countryCode !== '--'}
{session.countryName}
{:else}
Unknown
{/if}
</Table.Cell>
<Table.Cell>{session.ip}</Table.Cell>
<Table.Cell>
<Button
compact
icon
ariaLabel="Delete item"
on:click={() => {
selectedSessionId = session.$id;
showDelete = true;
}}>
<span class="icon-trash" aria-hidden="true" />
</Button>
</Table.Cell>
</Table.Row>
{/each}
</Table.Root>
{:else}
<Card.Base padding="none">
<Empty
@@ -15,96 +15,38 @@
import { columns } from './store';
import { View } from '$lib/helpers/load';
import Create from './create.svelte';
import { Pill } from '$lib/elements';
import { Icon } from '@appwrite.io/pink-svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { Card, Empty, Icon, Popover, Tag } from '@appwrite.io/pink-svelte';
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
export let data: PageData;
let showAdd = false;
let showMoreInfo = false;
</script>
<Container>
<div class="u-flex u-flex-vertical">
<div class="u-flex u-main-space-between u-cross-center">
<div class="u-flex u-gap-16 u-cross-center">
<Heading tag="h2" size="5">Targets</Heading>
<DropList bind:show={showMoreInfo} width="16">
<Pill button on:click={() => (showMoreInfo = !showMoreInfo)}>
<span class="icon-info" />More info
</Pill>
<svelte:fragment slot="list">
<slot name="tooltip">
<p>
User targets include emails, phone numbers, and devices with your
app installed. These targets can subscribe to a topic and receive
messages published to it.
</p>
</slot>
</svelte:fragment>
</DropList>
<Popover let:toggle placement="bottom-start">
<Tag on:click={toggle}>
<Icon slot="start" icon={IconInfo} size="s" />
More info
</Tag>
<p slot="tooltip">
User targets include emails, phone numbers, and devices with your app
installed.<br /> These targets can subscribe to a topic and receive messages
published to it.
</p>
</Popover>
</div>
<!-- TODO: Remove u-hide to add creating a target -->
<div class="is-only-mobile u-hide">
<Button on:click={() => (showAdd = true)} event="create_user_target">
<Icon icon={IconPlus} slot="start" size="s" />
Add target
</Button>
</div>
<!-- TODO: Remove when searching is added -->
<div class="u-flex u-main-end u-gap-16 is-not-mobile">
<Filters query={data.query} {columns} />
<div>
<ViewSelector
view={View.Table}
{columns}
hideView
allowNoColumns
showColsTextMobile />
<div class="u-hide">
<Button on:click={() => (showAdd = true)} event="create_user_target">
<Icon icon={IconPlus} slot="start" size="s" />
Add target
</Button>
</div>
</div>
</div>
</div>
<!-- TODO: Add searching when API supports it -->
<!-- <SearchQuery search={data.search} placeholder="Search by name">
<div class="u-flex u-gap-16 is-not-mobile">
<Filters query={data.query} {columns} />
<ViewSelector
view={View.Table}
{columns}
hideView
allowNoColumns
showColsTextMobile />
<Button on:click={() => (showAdd = true)} event="create_user_target">
<span class="icon-plus" aria-hidden="true" />
<span class="text">Add target</span>
</Button>
</div>
</SearchQuery> -->
<div class="u-flex u-gap-16 is-only-mobile u-margin-block-start-16">
<div class="u-flex-basis-50-percent">
<ViewSelector
view={View.Table}
{columns}
hideView
allowNoColumns
showColsTextMobile
fullWidthMobile />
</div>
<div class="u-flex-basis-50-percent">
<Filters query={data.query} {columns} fullWidthMobile />
<ViewSelector view={View.Table} {columns} hideView allowNoColumns />
</div>
</div>
</div>
{#if data.targets.total}
<Table {data} />
<PaginationWithLimit
name="Targets"
limit={data.limit}
@@ -112,33 +54,22 @@
total={data.targets.total} />
{:else if $hasPageQueries}
<EmptyFilter resource="targets" />
<!-- {:else if data.search}
<EmptySearch>
<div class="u-text-center">
<b>Sorry, we couldn't find '{data.search}'</b>
<p>There are no targets that match your search.</p>
</div>
<Button
secondary
href={`/console/project-${$page.params.project}/auth/user-${$page.params.user}/targets`}>
Clear Search
</Button>
</EmptySearch> -->
{:else}
<EmptySearch hidePagination>
<div class="u-text-center">
<p>No targets are assigned to this user. Messages can not be sent to them.</p>
<p>
Need a hand? Check out our <Button
link
<Card.Base padding="none">
<Empty
title="No targets available"
description="No targets are assigned to this user. Messages can not be sent to them."
type="secondary">
<svelte:fragment slot="actions">
<Button
external
href="https://appwrite.io/docs/products/messaging/targets"
text>
documentation</Button
>.
</p>
</div>
</EmptySearch>
secondary
href="https://appwrite.io/docs/products/messaging/targets">
Documentation
</Button>
</svelte:fragment>
</Empty>
</Card.Base>
{/if}
</Container>
@@ -1,17 +1,6 @@
<script lang="ts">
import { FloatingActionBar, Id, Modal } from '$lib/components';
import { Button } from '$lib/elements/forms';
import {
TableBody,
TableCell,
TableCellCheck,
TableCellHead,
TableCellHeadCheck,
TableCellText,
TableHeader,
TableRow,
TableScroll
} from '$lib/elements/table';
import type { PageData } from './$types';
import { columns } from './store';
import { toLocaleDateTime } from '$lib/helpers/date';
@@ -24,6 +13,8 @@
import { addNotification } from '$lib/stores/notifications';
import { invalidate } from '$app/navigation';
import { MessagingProviderType } from '@appwrite.io/console';
import { Badge, Selector, Table, Typography } from '@appwrite.io/pink-svelte';
import Confirm from '$lib/components/confirm.svelte';
export let data: PageData;
@@ -61,95 +52,84 @@
}
</script>
<TableScroll>
<TableHeader>
<TableCellHeadCheck
bind:selected={selectedIds}
pageItemsIds={data.targets.targets.map((d) => d.$id)} />
<Table.Root>
<svelte:fragment slot="header">
<Table.Header.Selector width="40px" />
{#each $columns as column}
{#if column.show}
<TableCellHead width={column.width}>{column.title}</TableCellHead>
<Table.Header.Cell width={column.width + 'px'}>{column.title}</Table.Header.Cell>
{/if}
{/each}
</TableHeader>
<TableBody>
{#each data.targets.targets as target (target.$id)}
{@const provider = data.providersById[target.providerId]}
<TableRow>
<TableCellCheck bind:selectedIds id={target.$id} />
</svelte:fragment>
{#each data.targets.targets as target (target.$id)}
{@const provider = data.providersById[target.providerId]}
<Table.Row>
<Table.Cell>
<Selector.Checkbox size="s" />
</Table.Cell>
{#each $columns as column}
{#if column.show}
{#if column.id === '$id'}
{#key $columns}
<TableCell title={column.title}>
<Id value={target[column.id]}>
{target[column.id]}
</Id>
</TableCell>
{/key}
{:else if column.id === 'target'}
<TableCell title={column.title}>
{#if target.providerType === MessagingProviderType.Push}
{target.name}
{:else}
{target.identifier}
{/if}
</TableCell>
{:else if column.id === 'providerType'}
<TableCellText title={column.title} width={column.width}>
<ProviderType type={target.providerType} size="s" />
</TableCellText>
{:else if column.id === 'provider'}
<TableCellText title={column.title} width={column.width}>
{#if provider}
<Provider provider={provider.provider} size="s" />
{/if}
</TableCellText>
{:else if column.id === '$createdAt'}
<TableCellText title={column.title} width={column.width}>
{toLocaleDateTime(target[column.id])}
</TableCellText>
{:else}
<TableCellText title={column.title} width={column.width}>
{target[column.id]}
</TableCellText>
{/if}
{#each $columns as column}
{#if column.show}
{#if column.id === '$id'}
{#key $columns}
<Table.Cell>
<Id value={target[column.id]}>
{target[column.id]}
</Id>
</Table.Cell>
{/key}
{:else if column.id === 'target'}
<Table.Cell>
{#if target.providerType === MessagingProviderType.Push}
{target.name}
{:else}
{target.identifier}
{/if}
</Table.Cell>
{:else if column.id === 'providerType'}
<Table.Cell width={column.width + 'px'}>
<ProviderType type={target.providerType} size="s" />
</Table.Cell>
{:else if column.id === 'provider'}
<Table.Cell width={column.width + 'px'}>
{#if provider}
<Provider provider={provider.provider} size="s" />
{/if}
</Table.Cell>
{:else if column.id === '$createdAt'}
<Table.Cell width={column.width + 'px'}>
{toLocaleDateTime(target[column.id])}
</Table.Cell>
{:else}
<Table.Cell width={column.width + 'px'}>
{target[column.id]}
</Table.Cell>
{/if}
{/each}
</TableRow>
{/each}
</TableBody>
</TableScroll>
{/if}
{/each}
</Table.Row>
{/each}
</Table.Root>
<FloatingActionBar show={selectedIds.length > 0}>
<div class="u-flex u-cross-center u-main-space-between actions">
<div class="u-flex u-cross-center u-gap-8">
<span class="indicator body-text-2 u-bold">{selectedIds.length}</span>
<p>
<span class="is-only-desktop">
{selectedIds.length > 1 ? 'subscribers' : 'subscriber'}
</span>
selected
</p>
</div>
<div class="u-flex u-cross-center u-gap-8">
<Button text on:click={() => (selectedIds = [])}>Cancel</Button>
<Button secondary on:click={() => (showDelete = true)}>
<p>Delete</p>
</Button>
</div>
</div>
<svelte:fragment slot="start">
<Badge content={selectedIds.length.toString()} />
<span>
<span class="is-only-desktop">
{selectedIds.length > 1 ? 'subscribers' : 'subscriber'}
</span>
selected
</span>
</svelte:fragment>
<svelte:fragment slot="end">
<Button text on:click={() => (selectedIds = [])}>Cancel</Button>
<Button secondary on:click={() => (showDelete = true)}>Delete</Button>
</svelte:fragment>
</FloatingActionBar>
<Modal title="Delete target" bind:show={showDelete} onSubmit={handleDelete} closable={!deleting}>
<p class="text" data-private>
<Confirm title="Delete Identity" bind:open={showDelete} onSubmit={handleDelete}>
<Typography.Text>
Are you sure you want to delete <b>{selectedIds.length}</b>
{selectedIds.length > 1 ? 'targets' : 'target'}?
</p>
<svelte:fragment slot="footer">
<Button text on:click={() => (showDelete = false)} disabled={deleting}>Cancel</Button>
<Button secondary submit disabled={deleting}>Delete</Button>
</svelte:fragment>
</Modal>
</Typography.Text>
</Confirm>
@@ -36,17 +36,13 @@
<Form onSubmit={updateEmail}>
<CardGrid>
<svelte:fragment slot="title">Email</svelte:fragment>
Update user's email. An Email should be formatted as:
<span class="inline-code">name@example.com</span>.
<svelte:fragment slot="aside">
<ul>
<InputEmail
id="email"
label="Email"
placeholder="Enter email"
autocomplete={false}
bind:value={userEmail} />
</ul>
<InputEmail
id="email"
label="Email"
placeholder="Enter email"
autocomplete={false}
bind:value={userEmail} />
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -9,7 +9,7 @@
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { user } from './store';
import { Pill } from '$lib/elements';
import { Tag, Input, Layout } from '@appwrite.io/pink-svelte';
const alphaNumericRegExp = /^[a-zA-Z0-9]+$/;
let suggestedLabels = ['admin', 'premium', 'mvp'];
@@ -67,17 +67,17 @@
Categorize and manage your users based on specific criteria by assigning them customizable labels.
New label-based roles will be assigned.
<svelte:fragment slot="aside">
<ul class="common-section">
<Layout.Stack gap="s">
<InputTags
id="user-labels"
label="Labels"
placeholder="Select or type user labels"
bind:tags={labels} />
<li class="u-flex u-gap-12 u-margin-block-start-8">
<Layout.Stack direction="row">
{#each suggestedLabels as suggestedLabel}
<Pill
<Tag
size="s"
selected={labels.includes(suggestedLabel)}
button
on:click={() => {
if (!labels.includes(suggestedLabel)) {
labels = [...labels, suggestedLabel];
@@ -87,14 +87,12 @@
}}>
<span class="icon-plus" aria-hidden="true" />
{suggestedLabel}
</Pill>
</Tag>
{/each}
</li>
<li>
<Helper type={error ? 'warning' : 'neutral'}
>{error ? error : 'Only alphanumeric characters are allowed'}</Helper>
</li>
</ul>
</Layout.Stack>
<Input.Helper state={error ? 'warning' : 'default'}
>{error ? error : 'Only alphanumeric characters are allowed'}</Input.Helper>
</Layout.Stack>
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -1,16 +1,6 @@
<script lang="ts">
import { CardGrid, Heading } from '$lib/components';
import EmptySearch from '$lib/components/emptySearch.svelte';
import { Form, Button, FormList, InputChoice } from '$lib/elements/forms';
import {
Table,
TableBody,
TableCell,
TableCellHead,
TableCellText,
TableHeader,
TableRow
} from '$lib/elements/table';
import { CardGrid } from '$lib/components';
import { Form, Button, InputChoice } from '$lib/elements/forms';
import { onMount } from 'svelte';
import DeleteMfa from './deleteMfa.svelte';
import { userFactors } from './store';
@@ -20,8 +10,7 @@
import { addNotification } from '$lib/stores/notifications';
import { Dependencies } from '$lib/constants';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { Icon } from '@appwrite.io/pink-svelte';
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
import { Card, Empty, Table } from '@appwrite.io/pink-svelte';
let showDelete = false;
let userMfa: boolean = null;
@@ -54,46 +43,37 @@
<svelte:fragment slot="title">Multi-factor authentication</svelte:fragment>
MFA allows users to enhance the security of their accounts in your app.
<svelte:fragment slot="aside">
<FormList>
<InputChoice
type="switchbox"
id="mfa"
label="Multi-factor authentication"
bind:value={userMfa} />
</FormList>
<InputChoice
type="switchbox"
id="mfa"
label="Multi-factor authentication"
bind:value={userMfa} />
{#if $userFactors.totp}
<Table noMargin noStyles transparent>
<TableHeader>
<TableCellHead>Authenticator</TableCellHead>
<TableCellHead width={40} />
</TableHeader>
<TableBody>
<TableRow>
<TableCellText title="Authenticator"
>TOTP (One-time code)</TableCellText>
<TableCell>
<Button
on:click={() => (showDelete = true)}
icon
text
ariaLabel="Delete authenticator">
<span class="icon-trash" aria-hidden="true" />
</Button>
</TableCell>
</TableRow>
</TableBody>
</Table>
<Button disabled text>
<Icon icon={IconPlus} slot="start" size="s" />
Add authentication factor
</Button>
<Table.Root>
<svelte:fragment slot="header">
<Table.Header.Cell>Authenticator</Table.Header.Cell>
<Table.Header.Cell width="40px" />
</svelte:fragment>
<Table.Row>
<Table.Cell>TOTP (One-time code)</Table.Cell>
<Table.Cell>
<Button
on:click={() => (showDelete = true)}
icon
text
ariaLabel="Delete authenticator">
<span class="icon-trash" aria-hidden="true" />
</Button>
</Table.Cell>
</Table.Row>
</Table.Root>
{:else}
<EmptySearch hidePagination hidePages>
<p class="text u-text-center">
No authenticators have been enabled.<br />Once the user adds an
authenticator, you'll see it here.
</p>
</EmptySearch>
<Card.Base variant="primary">
<Empty
type="secondary"
title="No authenticators have been enabled."
description="Once the user adds an authenticator, you'll see it here." />
</Card.Base>
{/if}
</svelte:fragment>
@@ -30,18 +30,14 @@
<Form onSubmit={updatePassword}>
<CardGrid>
<svelte:fragment slot="title">Password</svelte:fragment>
Enter a new password. A password must contain at least 8 characters.
A password must contain at least 8 characters.
<svelte:fragment slot="aside">
<ul>
<InputPassword
id="newPassword"
label="New Password"
placeholder="Enter new password"
autocomplete={false}
meter={false}
showPasswordButton={true}
bind:value={newPassword} />
</ul>
<InputPassword
id="newPassword"
label="New password"
placeholder="Enter new password"
autocomplete={false}
bind:value={newPassword} />
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -36,17 +36,14 @@
<Form onSubmit={updatePhone}>
<CardGrid>
<svelte:fragment slot="title">Phone</svelte:fragment>
Update user's phone. Phone number must start with '+' and maximum of 15 digits, for example:
+14155552671.
Phone number must start with '+' and maximum of 15 digits.
<svelte:fragment slot="aside">
<ul>
<InputPhone
id="phone"
label="Phone"
placeholder="Enter phone number"
autocomplete={false}
bind:value={userPhone} />
</ul>
<InputPhone
id="phone"
label="Phone"
placeholder="For example: +14155552671"
autocomplete={false}
bind:value={userPhone} />
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -64,45 +64,51 @@
id={`key-${index}`}
bind:value={key}
placeholder="Enter key"
label="Key"
label={index === 0 ? 'Key' : undefined}
required />
<InputText
id={`value-${index}`}
bind:value
placeholder="Enter value"
label="Value"
required />
<Button
text
icon
disabled={(!key || !value) && index === 0}
on:click={() => {
if (index === 0 && prefs?.length === 1) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
}}>
<span class="icon-x" aria-hidden="true" />
</Button>
<Layout.Stack direction="row" alignItems="flex-end" gap="xs">
<InputText
id={`value-${index}`}
bind:value
placeholder="Enter value"
label={index === 0 ? 'Value' : undefined}
required />
<Button
icon
compact
disabled={(!key || !value) && index === 0}
on:click={() => {
if (index === 0 && prefs?.length === 1) {
prefs = [['', '']];
} else {
prefs.splice(index, 1);
prefs = prefs;
}
}}>
<span class="icon-x" aria-hidden="true" />
</Button>
</Layout.Stack>
</Layout.Stack>
{/each}
{/if}
<Button
text
disabled={prefs?.length && prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]
? false
: true}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
}
}}>
<Icon icon={IconPlus} slot="start" size="s" />
Add preference
</Button>
<div>
<Button
secondary
disabled={prefs?.length &&
prefs[prefs.length - 1][0] &&
prefs[prefs.length - 1][1]
? false
: true}
on:click={() => {
if (prefs[prefs.length - 1][0] && prefs[prefs.length - 1][1]) {
prefs.push(['', '']);
prefs = prefs;
}
}}>
<Icon icon={IconPlus} slot="start" size="s" />
Add preference
</Button>
</div>
</svelte:fragment>
<svelte:fragment slot="actions">
@@ -8,7 +8,10 @@
import { toLocaleDate, toLocaleDateTime } from '$lib/helpers/date';
import { addNotification } from '$lib/stores/notifications';
import { sdk } from '$lib/stores/sdk';
import { Badge, Icon, Typography } from '@appwrite.io/pink-svelte';
import { user } from './store';
import Avatar from '$lib/components/avatar.svelte';
import { IconAnonymous, IconUser } from '@appwrite.io/pink-icons-svelte';
let showVerificationDropdown = false;
@@ -80,17 +83,17 @@
<div class="grid-1-2-col-1 u-flex u-cross-center u-gap-16" data-private>
{#if $user.email || $user.phone}
{#if $user.name}
<AvatarInitials size="l" name={$user.name} />
<Heading tag="h6" size="7">{$user.name}</Heading>
<AvatarInitials name={$user.name} />
<Typography.Title size="s" truncate>{$user.name}</Typography.Title>
{:else}
<div class="avatar">
<span class="icon-minus-sm" aria-hidden="true" />
</div>
<Avatar alt="avatar">
<Icon icon={IconUser} size="s" />
</Avatar>
{/if}
{:else}
<div class="avatar">
<span class="icon-anonymous" aria-hidden="true" />
</div>
<Avatar alt="avatar">
<Icon icon={IconAnonymous} size="s" />
</Avatar>
{/if}
</div>
<svelte:fragment slot="aside">
@@ -105,27 +108,35 @@
<p>Joined: {toLocaleDateTime($user.registration)}</p>
<p>Last activity: {accessedAt ? toLocaleDate(accessedAt) : 'never'}</p>
</div>
{#if !$user.status}
<Pill danger>blocked</Pill>
{:else if $user.email && $user.phone}
<Pill success={$user.emailVerification || $user.phoneVerification}>
{$user.emailVerification && $user.phoneVerification
? 'verified'
: $user.emailVerification
? 'verified email'
: $user.phoneVerification
? 'verified phone'
: 'unverified'}
</Pill>
{:else}
<Pill success={$user.emailVerification || $user.phoneVerification}>
{$user.emailVerification
? 'verified '
: $user.phoneVerification
? 'verified '
: 'unverified'}
</Pill>
{/if}
<div>
{#if !$user.status}
<Badge content="blocked" variant="secondary" type="warning" />
{:else if $user.email && $user.phone}
<Badge
variant="secondary"
type={$user.emailVerification || $user.phoneVerification
? 'success'
: undefined}
content={$user.emailVerification && $user.phoneVerification
? 'verified'
: $user.emailVerification
? 'verified email'
: $user.phoneVerification
? 'verified phone'
: 'unverified'} />
{:else}
<Badge
variant="secondary"
type={$user.emailVerification || $user.phoneVerification
? 'success'
: undefined}
content={$user.emailVerification
? 'verified '
: $user.phoneVerification
? 'verified '
: 'unverified'} />
{/if}
</div>
</div>
</svelte:fragment>
@@ -0,0 +1,27 @@
<script lang="ts">
import { InputText, InputURL, FormList } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
</script>
<WizardStep>
<svelte:fragment slot="title">Configuration</svelte:fragment>
<svelte:fragment slot="subtitle">
Use webhooks to build integrations that subscribe to specific events on Appwrite. Appwrite
will send an HTTP POST payload to the webhook's configured URL when one of the specified
events is triggered.
</svelte:fragment>
<FormList>
<InputText
label="Name"
id="name"
placeholder="Enter name"
bind:value={$createWebhook.name}
required />
<InputURL
label="POST URL"
id="url"
placeholder="https://example.com/callback"
bind:value={$createWebhook.url}
required />
</FormList>
</WizardStep>
@@ -0,0 +1,72 @@
<script lang="ts">
import { WizardStep } from '$lib/layout';
import { Button } from '$lib/elements/forms';
import { Empty } from '$lib/components';
import { EventModal } from '$lib/components';
import { Icon, Typography, Link, Table, Layout } from '@appwrite.io/pink-svelte';
import { IconPlus, IconX } from '@appwrite.io/pink-icons-svelte';
let showCreate = false;
export let events: string[];
let eventSet = new Set<string>();
function handleCreated(event: CustomEvent) {
eventSet.add(event.detail);
$createWebhook.events = Array.from(eventSet);
}
</script>
<WizardStep>
<svelte:fragment slot="title">Webhook events</svelte:fragment>
<svelte:fragment slot="subtitle">
Set the events that will trigger your function. Maximum 100 events allowed.
</svelte:fragment>
{#if $createWebhook?.events?.length}
{#each $createWebhook.events as event}
<Table.Root>
<Table.Row>
<Table.Cell>
<Layout.Stack
direction="row"
justifyContent="space-between"
alignItems="center">
{event}
<Button
extraCompact
ariaLabel="delete event"
on:click={() => {
eventSet.delete(event);
$createWebhook.events = Array.from(eventSet);
}}>
<Icon icon={IconX} size="s" />
</Button>
</Layout.Stack>
</Table.Cell>
</Table.Row>
</Table.Root>
{/each}
<div>
<Button secondary on:click={() => (showCreate = !showCreate)}>
<Icon icon={IconPlus} slot="start" size="s" />
Add event
</Button>
</div>
{:else}
<Empty on:click={() => (showCreate = !showCreate)}>Add an event</Empty>
{/if}
</WizardStep>
{#if showCreate}
<EventModal bind:show={showCreate} on:created={handleCreated}>
<Typography.Text>
Select events in your Appwrite project that will trigger your webhook. <Link.Anchor
href="https://appwrite.io/docs/advanced/platform/events"
target="_blank"
rel="noopener noreferrer"
class="link">Learn more</Link.Anchor>
</Typography.Text>
</EventModal>
{/if}
@@ -0,0 +1,36 @@
<script lang="ts">
import { InputText, InputPassword, InputChoice } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
export let httpUser: string;
export let httpPass: string;
export let security: boolean;
</script>
<WizardStep>
<svelte:fragment slot="title">Security</svelte:fragment>
<svelte:fragment slot="subtitle">
Set an optional basic HTTP authentication username and password to protect your endpoint
from unauthorized access.
</svelte:fragment>
<div>
<h2 class="heading-level-7">HTTP Authentication</h2>
<p class="text">Use to secure your endpoint from untrusted sources.</p>
</div>
<InputText label="User" id="user" placeholder="Enter username" bind:value={httpUser} />
<InputPassword
label="Password"
id="password"
placeholder="Enter password"
minlength={0}
bind:value={httpPass} />
<InputChoice id="Security" label="Certificate verification (SSL/TLS)" bind:value={security}>
<span class="u-color-text-danger">Warning:</span> Untrusted or self-signed certificates may
not be secure.
<a
href="https://appwrite.io/docs/advanced/self-hosting/tls-certificates"
target="_blank"
rel="noopener noreferrer"
class="link">
Learn more</a
></InputChoice>
</WizardStep>
@@ -2,7 +2,6 @@
import { InputText, InputURL, FormList } from '$lib/elements/forms';
import { WizardStep } from '$lib/layout';
import { createWebhook } from './store';
//TODO: Create InputURL component
</script>
<WizardStep>
@@ -4,7 +4,6 @@
import { Empty } from '$lib/components';
import { createWebhook } from './store';
import { EventModal } from '$lib/components';
import { TableList, TableCellText, TableCell } from '$lib/elements/table';
import { Icon, Typography, Link, Table, Layout } from '@appwrite.io/pink-svelte';
import { IconPlus, IconX } from '@appwrite.io/pink-icons-svelte';