feat: enhance demo modes across 12 modules + add inbox/sharp/x402 deps
Improve interactive demos for notes, maps, network, vote, calendar, choices, trips, work, books, wallet, and inbox modules with richer mock data and better mobile responsiveness. Update server routing and landing page. Add sharp, imapflow, mailparser, and x402 dependencies. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7e5a8624d7
commit
01fa8b1ba5
465
bun.lock
465
bun.lock
|
|
@ -6,15 +6,22 @@
|
|||
"name": "rspace-online",
|
||||
"dependencies": {
|
||||
"@automerge/automerge": "^2.2.8",
|
||||
"@aws-sdk/client-s3": "^3.700.0",
|
||||
"@encryptid/sdk": "file:../encryptid-sdk",
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
"@x402/core": "^2.3.1",
|
||||
"@x402/evm": "^2.3.1",
|
||||
"hono": "^4.11.7",
|
||||
"imapflow": "^1.0.170",
|
||||
"mailparser": "^3.7.2",
|
||||
"nodemailer": "^6.9.0",
|
||||
"perfect-arrows": "^0.3.7",
|
||||
"perfect-freehand": "^1.2.2",
|
||||
"postgres": "^3.4.5",
|
||||
"sharp": "^0.33.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mailparser": "^3.4.0",
|
||||
"@types/node": "^22.10.1",
|
||||
"@types/nodemailer": "^6.4.0",
|
||||
"bun-types": "^1.1.38",
|
||||
|
|
@ -26,8 +33,92 @@
|
|||
},
|
||||
},
|
||||
"packages": {
|
||||
"@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.11.1", "", {}, "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ=="],
|
||||
|
||||
"@automerge/automerge": ["@automerge/automerge@2.2.9", "", { "dependencies": { "uuid": "^9.0.0" } }, "sha512-6HM52Ops79hAQBWMg/t0MNfGOdEiXyenQjO9F1hKZq0RWDsMLpPa1SzRy/C4/4UyX67sTHuA5CwBpH34SpfZlA=="],
|
||||
|
||||
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
|
||||
|
||||
"@aws-crypto/crc32c": ["@aws-crypto/crc32c@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag=="],
|
||||
|
||||
"@aws-crypto/sha1-browser": ["@aws-crypto/sha1-browser@5.2.0", "", { "dependencies": { "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg=="],
|
||||
|
||||
"@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="],
|
||||
|
||||
"@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="],
|
||||
|
||||
"@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="],
|
||||
|
||||
"@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="],
|
||||
|
||||
"@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.1000.0", "", { "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.15", "@aws-sdk/credential-provider-node": "^3.972.14", "@aws-sdk/middleware-bucket-endpoint": "^3.972.6", "@aws-sdk/middleware-expect-continue": "^3.972.6", "@aws-sdk/middleware-flexible-checksums": "^3.973.1", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-location-constraint": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", "@aws-sdk/middleware-sdk-s3": "^3.972.15", "@aws-sdk/middleware-ssec": "^3.972.6", "@aws-sdk/middleware-user-agent": "^3.972.15", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/signature-v4-multi-region": "^3.996.3", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", "@aws-sdk/util-user-agent-node": "^3.973.0", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.6", "@smithy/eventstream-serde-browser": "^4.2.10", "@smithy/eventstream-serde-config-resolver": "^4.3.10", "@smithy/eventstream-serde-node": "^4.2.10", "@smithy/fetch-http-handler": "^5.3.11", "@smithy/hash-blob-browser": "^4.2.11", "@smithy/hash-node": "^4.2.10", "@smithy/hash-stream-node": "^4.2.10", "@smithy/invalid-dependency": "^4.2.10", "@smithy/md5-js": "^4.2.10", "@smithy/middleware-content-length": "^4.2.10", "@smithy/middleware-endpoint": "^4.4.20", "@smithy/middleware-retry": "^4.4.37", "@smithy/middleware-serde": "^4.2.11", "@smithy/middleware-stack": "^4.2.10", "@smithy/node-config-provider": "^4.3.10", "@smithy/node-http-handler": "^4.4.12", "@smithy/protocol-http": "^5.3.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "@smithy/url-parser": "^4.2.10", "@smithy/util-base64": "^4.3.1", "@smithy/util-body-length-browser": "^4.2.1", "@smithy/util-body-length-node": "^4.2.2", "@smithy/util-defaults-mode-browser": "^4.3.36", "@smithy/util-defaults-mode-node": "^4.2.39", "@smithy/util-endpoints": "^3.3.1", "@smithy/util-middleware": "^4.2.10", "@smithy/util-retry": "^4.2.10", "@smithy/util-stream": "^4.5.15", "@smithy/util-utf8": "^4.2.1", "@smithy/util-waiter": "^4.2.10", "tslib": "^2.6.2" } }, "sha512-7kPy33qNGq3NfwHC0412T6LDK1bp4+eiPzetX0sVd9cpTSXuQDKpoOFnB0Njj6uZjJDcLS3n2OeyarwwgkQ0Ow=="],
|
||||
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.973.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@aws-sdk/xml-builder": "^3.972.8", "@smithy/core": "^3.23.6", "@smithy/node-config-provider": "^4.3.10", "@smithy/property-provider": "^4.2.10", "@smithy/protocol-http": "^5.3.10", "@smithy/signature-v4": "^5.3.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "@smithy/util-base64": "^4.3.1", "@smithy/util-middleware": "^4.2.10", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-AlC0oQ1/mdJ8vCIqu524j5RB7M8i8E24bbkZmya1CuiQxkY7SdIZAyw7NDNMGaNINQFq/8oGRMX0HeOfCVsl/A=="],
|
||||
|
||||
"@aws-sdk/crc64-nvme": ["@aws-sdk/crc64-nvme@3.972.3", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-UExeK+EFiq5LAcbHm96CQLSia+5pvpUVSAsVApscBzayb7/6dJBJKwV4/onsk4VbWSmqxDMcfuTD+pC4RxgZHg=="],
|
||||
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.13", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-6ljXKIQ22WFKyIs1jbORIkGanySBHaPPTOI4OxACP5WXgbcR0nDYfqNJfXEGwCK7IzHdNbCSFsNKKs0qCexR8Q=="],
|
||||
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.15", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/types": "^3.973.4", "@smithy/fetch-http-handler": "^5.3.11", "@smithy/node-http-handler": "^4.4.12", "@smithy/property-provider": "^4.2.10", "@smithy/protocol-http": "^5.3.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "@smithy/util-stream": "^4.5.15", "tslib": "^2.6.2" } }, "sha512-dJuSTreu/T8f24SHDNTjd7eQ4rabr0TzPh2UTCwYexQtzG3nTDKm1e5eIdhiroTMDkPEJeY+WPkA6F9wod/20A=="],
|
||||
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.13", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/credential-provider-env": "^3.972.13", "@aws-sdk/credential-provider-http": "^3.972.15", "@aws-sdk/credential-provider-login": "^3.972.13", "@aws-sdk/credential-provider-process": "^3.972.13", "@aws-sdk/credential-provider-sso": "^3.972.13", "@aws-sdk/credential-provider-web-identity": "^3.972.13", "@aws-sdk/nested-clients": "^3.996.3", "@aws-sdk/types": "^3.973.4", "@smithy/credential-provider-imds": "^4.2.10", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-JKSoGb7XeabZLBJptpqoZIFbROUIS65NuQnEHGOpuT9GuuZwag2qciKANiDLFiYk4u8nSrJC9JIOnWKVvPVjeA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.13", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/nested-clients": "^3.996.3", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/protocol-http": "^5.3.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-RtYcrxdnJHKY8MFQGLltCURcjuMjnaQpAxPE6+/QEdDHHItMKZgabRe/KScX737F9vJMQsmJy9EmMOkCnoC1JQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.14", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.13", "@aws-sdk/credential-provider-http": "^3.972.15", "@aws-sdk/credential-provider-ini": "^3.972.13", "@aws-sdk/credential-provider-process": "^3.972.13", "@aws-sdk/credential-provider-sso": "^3.972.13", "@aws-sdk/credential-provider-web-identity": "^3.972.13", "@aws-sdk/types": "^3.973.4", "@smithy/credential-provider-imds": "^4.2.10", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-WqoC2aliIjQM/L3oFf6j+op/enT2i9Cc4UTxxMEKrJNECkq4/PlKE5BOjSYFcq6G9mz65EFbXJh7zOU4CvjSKQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.13", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-rsRG0LQA4VR+jnDyuqtXi2CePYSmfm5GNL9KxiW8DSe25YwJSr06W8TdUfONAC+rjsTI+aIH2rBGG5FjMeANrw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.13", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/nested-clients": "^3.996.3", "@aws-sdk/token-providers": "3.999.0", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-fr0UU1wx8kNHDhTQBXioc/YviSW8iXuAxHvnH7eQUtn8F8o/FU3uu6EUMvAQgyvn7Ne5QFnC0Cj0BFlwCk+RFw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.13", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/nested-clients": "^3.996.3", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-a6iFMh1pgUH0TdcouBppLJUfPM7Yd3R9S1xFodPtCRoLqCz2RQFA3qjA8x4112PVYXEd4/pHX2eihapq39w0rA=="],
|
||||
|
||||
"@aws-sdk/middleware-bucket-endpoint": ["@aws-sdk/middleware-bucket-endpoint@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-arn-parser": "^3.972.2", "@smithy/node-config-provider": "^4.3.10", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "@smithy/util-config-provider": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-3H2bhvb7Cb/S6WFsBy/Dy9q2aegC9JmGH1inO8Lb2sWirSqpLJlZmvQHPE29h2tIxzv6el/14X/tLCQ8BQU6ZQ=="],
|
||||
|
||||
"@aws-sdk/middleware-expect-continue": ["@aws-sdk/middleware-expect-continue@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-QMdffpU+GkSGC+bz6WdqlclqIeCsOfgX8JFZ5xvwDtX+UTj4mIXm3uXu7Ko6dBseRcJz1FA6T9OmlAAY6JgJUg=="],
|
||||
|
||||
"@aws-sdk/middleware-flexible-checksums": ["@aws-sdk/middleware-flexible-checksums@3.973.1", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", "@aws-sdk/core": "^3.973.15", "@aws-sdk/crc64-nvme": "^3.972.3", "@aws-sdk/types": "^3.973.4", "@smithy/is-array-buffer": "^4.2.1", "@smithy/node-config-provider": "^4.3.10", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "@smithy/util-middleware": "^4.2.10", "@smithy/util-stream": "^4.5.15", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-QLXsxsI6VW8LuGK+/yx699wzqP/NMCGk/hSGP+qtB+Lcff+23UlbahyouLlk+nfT7Iu021SkXBhnAuVd6IZcPw=="],
|
||||
|
||||
"@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-5XHwjPH1lHB+1q4bfC7T8Z5zZrZXfaLcjSMwTd1HPSPrCmPFMbg3UQ5vgNWcVj0xoX4HWqTGkSf2byrjlnRg5w=="],
|
||||
|
||||
"@aws-sdk/middleware-location-constraint": ["@aws-sdk/middleware-location-constraint@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-XdZ2TLwyj3Am6kvUc67vquQvs6+D8npXvXgyEUJAdkUDx5oMFJKOqpK+UpJhVDsEL068WAJl2NEGzbSik7dGJQ=="],
|
||||
|
||||
"@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-iFnaMFMQdljAPrvsCVKYltPt2j40LQqukAbXvW7v0aL5I+1GO7bZ/W8m12WxW3gwyK5p5u1WlHg8TSAizC5cZw=="],
|
||||
|
||||
"@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-dY4v3of5EEMvik6+UDwQ96KfUFDk8m1oZDdkSc5lwi4o7rFrjnv0A+yTV+gu230iybQZnKgDLg/rt2P3H+Vscw=="],
|
||||
|
||||
"@aws-sdk/middleware-sdk-s3": ["@aws-sdk/middleware-sdk-s3@3.972.15", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-arn-parser": "^3.972.2", "@smithy/core": "^3.23.6", "@smithy/node-config-provider": "^4.3.10", "@smithy/protocol-http": "^5.3.10", "@smithy/signature-v4": "^5.3.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "@smithy/util-config-provider": "^4.2.1", "@smithy/util-middleware": "^4.2.10", "@smithy/util-stream": "^4.5.15", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-WDLgssevOU5BFx1s8jA7jj6cE5HuImz28sy9jKOaVtz0AW1lYqSzotzdyiybFaBcQTs5zxXOb2pUfyMxgEKY3Q=="],
|
||||
|
||||
"@aws-sdk/middleware-ssec": ["@aws-sdk/middleware-ssec@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-acvMUX9jF4I2Ew+Z/EA6gfaFaz9ehci5wxBmXCZeulLuv8m+iGf6pY9uKz8TPjg39bdAz3hxoE0eLP8Qz+IYlA=="],
|
||||
|
||||
"@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.972.15", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@smithy/core": "^3.23.6", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-ABlFVcIMmuRAwBT+8q5abAxOr7WmaINirDJBnqGY5b5jSDo00UMlg/G4a0xoAgwm6oAECeJcwkvDlxDwKf58fQ=="],
|
||||
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.996.3", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.973.15", "@aws-sdk/middleware-host-header": "^3.972.6", "@aws-sdk/middleware-logger": "^3.972.6", "@aws-sdk/middleware-recursion-detection": "^3.972.6", "@aws-sdk/middleware-user-agent": "^3.972.15", "@aws-sdk/region-config-resolver": "^3.972.6", "@aws-sdk/types": "^3.973.4", "@aws-sdk/util-endpoints": "^3.996.3", "@aws-sdk/util-user-agent-browser": "^3.972.6", "@aws-sdk/util-user-agent-node": "^3.973.0", "@smithy/config-resolver": "^4.4.9", "@smithy/core": "^3.23.6", "@smithy/fetch-http-handler": "^5.3.11", "@smithy/hash-node": "^4.2.10", "@smithy/invalid-dependency": "^4.2.10", "@smithy/middleware-content-length": "^4.2.10", "@smithy/middleware-endpoint": "^4.4.20", "@smithy/middleware-retry": "^4.4.37", "@smithy/middleware-serde": "^4.2.11", "@smithy/middleware-stack": "^4.2.10", "@smithy/node-config-provider": "^4.3.10", "@smithy/node-http-handler": "^4.4.12", "@smithy/protocol-http": "^5.3.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "@smithy/url-parser": "^4.2.10", "@smithy/util-base64": "^4.3.1", "@smithy/util-body-length-browser": "^4.2.1", "@smithy/util-body-length-node": "^4.2.2", "@smithy/util-defaults-mode-browser": "^4.3.36", "@smithy/util-defaults-mode-node": "^4.2.39", "@smithy/util-endpoints": "^3.3.1", "@smithy/util-middleware": "^4.2.10", "@smithy/util-retry": "^4.2.10", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-AU5TY1V29xqwg/MxmA2odwysTez+ccFAhmfRJk+QZT5HNv90UTA9qKd1J9THlsQkvmH7HWTEV1lDNxkQO5PzNw=="],
|
||||
|
||||
"@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/config-resolver": "^4.4.9", "@smithy/node-config-provider": "^4.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-Aa5PusHLXAqLTX1UKDvI3pHQJtIsF7Q+3turCHqfz/1F61/zDMWfbTC8evjhrrYVAtz9Vsv3SJ/waSUeu7B6gw=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.3", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "^3.972.15", "@aws-sdk/types": "^3.973.4", "@smithy/protocol-http": "^5.3.10", "@smithy/signature-v4": "^5.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-gQYI/Buwp0CAGQxY7mR5VzkP56rkWq2Y1ROkFuXh5XY94DsSjJw62B3I0N0lysQmtwiL2ht2KHI9NylM/RP4FA=="],
|
||||
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.999.0", "", { "dependencies": { "@aws-sdk/core": "^3.973.15", "@aws-sdk/nested-clients": "^3.996.3", "@aws-sdk/types": "^3.973.4", "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-cx0hHUlgXULfykx4rdu/ciNAJaa3AL5xz3rieCz7NKJ68MJwlj3664Y8WR5MGgxfyYJBdamnkjNSx5Kekuc0cg=="],
|
||||
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.973.4", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-RW60aH26Bsc016Y9B98hC0Plx6fK5P2v/iQYwMzrSjiDh1qRMUCP6KrXHYEHe3uFvKiOC93Z9zk4BJsUi6Tj1Q=="],
|
||||
|
||||
"@aws-sdk/util-arn-parser": ["@aws-sdk/util-arn-parser@3.972.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-VkykWbqMjlSgBFDyrY3nOSqupMc6ivXuGmvci6Q3NnLq5kC+mKQe2QBZ4nrWRE/jqOxeFP2uYzLtwncYYcvQDg=="],
|
||||
|
||||
"@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.996.3", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/types": "^4.13.0", "@smithy/url-parser": "^4.2.10", "@smithy/util-endpoints": "^3.3.1", "tslib": "^2.6.2" } }, "sha512-yWIQSNiCjykLL+ezN5A+DfBb1gfXTytBxm57e64lYmwxDHNmInYHRJYYRAGWG1o77vKEiWaw4ui28e3yb1k5aQ=="],
|
||||
|
||||
"@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.4", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-H1onv5SkgPBK2P6JR2MjGgbOnttoNzSPIRoeZTNPZYyaplwGg50zS3amXvXqF0/qfXpWEC9rLWU564QTB9bSog=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.972.6", "", { "dependencies": { "@aws-sdk/types": "^3.973.4", "@smithy/types": "^4.13.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-Fwr/llD6GOrFgQnKaI2glhohdGuBDfHfora6iG9qsBBBR8xv1SdCSwbtf5CWlUdCw5X7g76G/9Hf0Inh0EmoxA=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.973.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "^3.972.15", "@aws-sdk/types": "^3.973.4", "@smithy/node-config-provider": "^4.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-A9J2G4Nf236e9GpaC1JnA8wRn6u6GjnOXiTwBLA6NUJhlBTIGfrTy+K1IazmF8y+4OFdW3O5TZlhyspJMqiqjA=="],
|
||||
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.8", "", { "dependencies": { "@smithy/types": "^4.13.0", "fast-xml-parser": "5.3.6", "tslib": "^2.6.2" } }, "sha512-Ql8elcUdYCha83Ol7NznBsgN5GVZnv3vUd86fEc6waU6oUdY0T1O9NODkEEOS/Uaogr87avDrUC6DSeM4oXjZg=="],
|
||||
|
||||
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.3", "", {}, "sha512-oLvsaPMTBejkkmHhjf09xTgk71mOqyr/409NKhRIL08If7AhVfUsJhVsx386uJaqNd42v9kWamQ9lFbkoC2dYw=="],
|
||||
|
||||
"@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
|
||||
|
||||
"@encryptid/sdk": ["@encryptid/sdk@file:../encryptid-sdk", { "dependencies": { "@noble/curves": "^2.0.1", "@noble/hashes": "^2.0.1", "hono": "^4.11.0" }, "devDependencies": { "@types/react": "^19.0.0", "typescript": "^5.7.0" }, "peerDependencies": { "next": ">=14.0.0", "react": ">=18.0.0" }, "optionalPeers": ["next", "react"] }],
|
||||
|
||||
"@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
|
||||
|
|
@ -82,14 +173,56 @@
|
|||
|
||||
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
|
||||
|
||||
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
|
||||
|
||||
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="],
|
||||
|
||||
"@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="],
|
||||
|
||||
"@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="],
|
||||
|
||||
"@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="],
|
||||
|
||||
"@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="],
|
||||
|
||||
"@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="],
|
||||
|
||||
"@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="],
|
||||
|
||||
"@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="],
|
||||
|
||||
"@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="],
|
||||
|
||||
"@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="],
|
||||
|
||||
"@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="],
|
||||
|
||||
"@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="],
|
||||
|
||||
"@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="],
|
||||
|
||||
"@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="],
|
||||
|
||||
"@lit-labs/ssr-dom-shim": ["@lit-labs/ssr-dom-shim@1.5.0", "", {}, "sha512-HLomZXMmrCFHSRKESF5vklAKsDY7/fsT/ZhqCu3V0UoW/Qbv8wxmO4W9bx4KnCCF2Zak4yuk+AGraK/bPmI4kA=="],
|
||||
|
||||
"@lit/reactive-element": ["@lit/reactive-element@2.1.2", "", { "dependencies": { "@lit-labs/ssr-dom-shim": "^1.5.0" } }, "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A=="],
|
||||
|
||||
"@noble/ciphers": ["@noble/ciphers@1.3.0", "", {}, "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw=="],
|
||||
|
||||
"@noble/curves": ["@noble/curves@2.0.1", "", { "dependencies": { "@noble/hashes": "2.0.1" } }, "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw=="],
|
||||
|
||||
"@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="],
|
||||
|
||||
"@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="],
|
||||
|
||||
"@rollup/plugin-virtual": ["@rollup/plugin-virtual@3.0.2", "", { "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A=="],
|
||||
|
||||
"@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.54.0", "", { "os": "android", "cpu": "arm" }, "sha512-OywsdRHrFvCdvsewAInDKCNyR3laPA2mc9bRYJ6LBp5IyvF3fvXbbNR0bSzHlZVFtn6E0xw2oZlyjg4rKCVcng=="],
|
||||
|
|
@ -136,6 +269,126 @@
|
|||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.54.0", "", { "os": "win32", "cpu": "x64" }, "sha512-hYT5d3YNdSh3mbCU1gwQyPgQd3T2ne0A3KG8KSBdav5TiBg6eInVmV+TeR5uHufiIgSFg0XsOWGW5/RhNcSvPg=="],
|
||||
|
||||
"@scure/base": ["@scure/base@1.2.6", "", {}, "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg=="],
|
||||
|
||||
"@scure/bip32": ["@scure/bip32@1.7.0", "", { "dependencies": { "@noble/curves": "~1.9.0", "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw=="],
|
||||
|
||||
"@scure/bip39": ["@scure/bip39@1.6.0", "", { "dependencies": { "@noble/hashes": "~1.8.0", "@scure/base": "~1.2.5" } }, "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A=="],
|
||||
|
||||
"@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="],
|
||||
|
||||
"@smithy/abort-controller": ["@smithy/abort-controller@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-qocxM/X4XGATqQtUkbE9SPUB6wekBi+FyJOMbPj0AhvyvFGYEmOlz6VB22iMePCQsFmMIvFSeViDvA7mZJG47g=="],
|
||||
|
||||
"@smithy/chunked-blob-reader": ["@smithy/chunked-blob-reader@5.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-y5d4xRiD6TzeP5BWlb+Ig/VFqF+t9oANNhGeMqyzU7obw7FYgTgVi50i5JqBTeKp+TABeDIeeXFZdz65RipNtA=="],
|
||||
|
||||
"@smithy/chunked-blob-reader-native": ["@smithy/chunked-blob-reader-native@4.2.2", "", { "dependencies": { "@smithy/util-base64": "^4.3.1", "tslib": "^2.6.2" } }, "sha512-QzzYIlf4yg0w5TQaC9VId3B3ugSk1MI/wb7tgcHtd7CBV9gNRKZrhc2EPSxSZuDy10zUZ0lomNMgkc6/VVe8xg=="],
|
||||
|
||||
"@smithy/config-resolver": ["@smithy/config-resolver@4.4.9", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.10", "@smithy/types": "^4.13.0", "@smithy/util-config-provider": "^4.2.1", "@smithy/util-endpoints": "^3.3.1", "@smithy/util-middleware": "^4.2.10", "tslib": "^2.6.2" } }, "sha512-ejQvXqlcU30h7liR9fXtj7PIAau1t/sFbJpgWPfiYDs7zd16jpH0IsSXKcba2jF6ChTXvIjACs27kNMc5xxE2Q=="],
|
||||
|
||||
"@smithy/core": ["@smithy/core@3.23.6", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.11", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "@smithy/util-base64": "^4.3.1", "@smithy/util-body-length-browser": "^4.2.1", "@smithy/util-middleware": "^4.2.10", "@smithy/util-stream": "^4.5.15", "@smithy/util-utf8": "^4.2.1", "@smithy/uuid": "^1.1.1", "tslib": "^2.6.2" } }, "sha512-4xE+0L2NrsFKpEVFlFELkIHQddBvMbQ41LRIP74dGCXnY1zQ9DgksrBcRBDJT+iOzGy4VEJIeU3hkUK5mn06kg=="],
|
||||
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.10", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.10", "@smithy/property-provider": "^4.2.10", "@smithy/types": "^4.13.0", "@smithy/url-parser": "^4.2.10", "tslib": "^2.6.2" } }, "sha512-3bsMLJJLTZGZqVGGeBVFfLzuRulVsGTj12BzRKODTHqUABpIr0jMN1vN3+u6r2OfyhAQ2pXaMZWX/swBK5I6PQ=="],
|
||||
|
||||
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.10", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.13.0", "@smithy/util-hex-encoding": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-A4ynrsFFfSXUHicfTcRehytppFBcY3HQxEGYiyGktPIOye3Ot7fxpiy4VR42WmtGI4Wfo6OXt/c1Ky1nUFxYYQ=="],
|
||||
|
||||
"@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.2.10", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-0xupsu9yj9oDVuQ50YCTS9nuSYhGlrwqdaKQel9y2Fz7LU9fNErVlw9N0o4pm4qqvWEGbSTI4HKc6XJfB30MVw=="],
|
||||
|
||||
"@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.3.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-8kn6sinrduk0yaYHMJDsNuiFpXwQwibR7n/4CDUqn4UgaG+SeBHu5jHGFdU9BLFAM7Q4/gvr9RYxBHz9/jKrhA=="],
|
||||
|
||||
"@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.2.10", "", { "dependencies": { "@smithy/eventstream-serde-universal": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-uUrxPGgIffnYfvIOUmBM5i+USdEBRTdh7mLPttjphgtooxQ8CtdO1p6K5+Q4BBAZvKlvtJ9jWyrWpBJYzBKsyQ=="],
|
||||
|
||||
"@smithy/eventstream-serde-universal": ["@smithy/eventstream-serde-universal@4.2.10", "", { "dependencies": { "@smithy/eventstream-codec": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-aArqzOEvcs2dK+xQVCgLbpJQGfZihw8SD4ymhkwNTtwKbnrzdhJsFDKuMQnam2kF69WzgJYOU5eJlCx+CA32bw=="],
|
||||
|
||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.11", "", { "dependencies": { "@smithy/protocol-http": "^5.3.10", "@smithy/querystring-builder": "^4.2.10", "@smithy/types": "^4.13.0", "@smithy/util-base64": "^4.3.1", "tslib": "^2.6.2" } }, "sha512-wbTRjOxdFuyEg0CpumjZO0hkUl+fetJFqxNROepuLIoijQh51aMBmzFLfoQdwRjxsuuS2jizzIUTjPWgd8pd7g=="],
|
||||
|
||||
"@smithy/hash-blob-browser": ["@smithy/hash-blob-browser@4.2.11", "", { "dependencies": { "@smithy/chunked-blob-reader": "^5.2.1", "@smithy/chunked-blob-reader-native": "^4.2.2", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-DrcAx3PM6AEbWZxsKl6CWAGnVwiz28Wp1ZhNu+Hi4uI/6C1PIZBIaPM2VoqBDAsOWbM6ZVzOEQMxFLLdmb4eBQ=="],
|
||||
|
||||
"@smithy/hash-node": ["@smithy/hash-node@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "@smithy/util-buffer-from": "^4.2.1", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-1VzIOI5CcsvMDvP3iv1vG/RfLJVVVc67dCRyLSB2Hn9SWCZrDO3zvcIzj3BfEtqRW5kcMg5KAeVf1K3dR6nD3w=="],
|
||||
|
||||
"@smithy/hash-stream-node": ["@smithy/hash-stream-node@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-w78xsYrOlwXKwN5tv1GnKIRbHb1HygSpeZMP6xDxCPGf1U/xDHjCpJu64c5T35UKyEPwa0bPeIcvU69VY3khUA=="],
|
||||
|
||||
"@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-vy9KPNSFUU0ajFYk0sDZIYiUlAWGEAhRfehIr5ZkdFrRFTAuXEPUd41USuqHU6vvLX4r6Q9X7MKBco5+Il0Org=="],
|
||||
|
||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Yfu664Qbf1B4IYIsYgKoABt010daZjkaCRvdU/sPnZG6TtHOB0md0RjNdLGzxe5UIdn9js4ftPICzmkRa9RJ4Q=="],
|
||||
|
||||
"@smithy/md5-js": ["@smithy/md5-js@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-Op+Dh6dPLWTjWITChFayDllIaCXRofOed8ecpggTC5fkh8yXes0vAEX7gRUfjGK+TlyxoCAA05gHbZW/zB9JwQ=="],
|
||||
|
||||
"@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.10", "", { "dependencies": { "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-TQZ9kX5c6XbjhaEBpvhSvMEZ0klBs1CFtOdPFwATZSbC9UeQfKHPLPN9Y+I6wZGMOavlYTOlHEPDrt42PMSH9w=="],
|
||||
|
||||
"@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.20", "", { "dependencies": { "@smithy/core": "^3.23.6", "@smithy/middleware-serde": "^4.2.11", "@smithy/node-config-provider": "^4.3.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "@smithy/url-parser": "^4.2.10", "@smithy/util-middleware": "^4.2.10", "tslib": "^2.6.2" } }, "sha512-9W6Np4ceBP3XCYAGLoMCmn8t2RRVzuD1ndWPLBbv7H9CrwM9Bprf6Up6BM9ZA/3alodg0b7Kf6ftBK9R1N04vw=="],
|
||||
|
||||
"@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.37", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.10", "@smithy/protocol-http": "^5.3.10", "@smithy/service-error-classification": "^4.2.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "@smithy/util-middleware": "^4.2.10", "@smithy/util-retry": "^4.2.10", "@smithy/uuid": "^1.1.1", "tslib": "^2.6.2" } }, "sha512-/1psZZllBBSQ7+qo5+hhLz7AEPGLx3Z0+e3ramMBEuPK2PfvLK4SrncDB9VegX5mBn+oP/UTDrM6IHrFjvX1ZA=="],
|
||||
|
||||
"@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.11", "", { "dependencies": { "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-STQdONGPwbbC7cusL60s7vOa6He6A9w2jWhoapL0mgVjmR19pr26slV+yoSP76SIssMTX/95e5nOZ6UQv6jolg=="],
|
||||
|
||||
"@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-pmts/WovNcE/tlyHa8z/groPeOtqtEpp61q3W0nW1nDJuMq/x+hWa/OVQBtgU0tBqupeXq0VBOLA4UZwE8I0YA=="],
|
||||
|
||||
"@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.10", "", { "dependencies": { "@smithy/property-provider": "^4.2.10", "@smithy/shared-ini-file-loader": "^4.4.5", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-UALRbJtVX34AdP2VECKVlnNgidLHA2A7YgcJzwSBg1hzmnO/bZBHl/LDQQyYifzUwp1UOODnl9JJ3KNawpUJ9w=="],
|
||||
|
||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.12", "", { "dependencies": { "@smithy/abort-controller": "^4.2.10", "@smithy/protocol-http": "^5.3.10", "@smithy/querystring-builder": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-zo1+WKJkR9x7ZtMeMDAAsq2PufwiLDmkhcjpWPRRkmeIuOm6nq1qjFICSZbnjBvD09ei8KMo26BWxsu2BUU+5w=="],
|
||||
|
||||
"@smithy/property-provider": ["@smithy/property-provider@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-5jm60P0CU7tom0eNrZ7YrkgBaoLFXzmqB0wVS+4uK8PPGmosSrLNf6rRd50UBvukztawZ7zyA8TxlrKpF5z9jw=="],
|
||||
|
||||
"@smithy/protocol-http": ["@smithy/protocol-http@5.3.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-2NzVWpYY0tRdfeCJLsgrR89KE3NTWT2wGulhNUxYlRmtRmPwLQwKzhrfVaiNlA9ZpJvbW7cjTVChYKgnkqXj1A=="],
|
||||
|
||||
"@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "@smithy/util-uri-escape": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-HeN7kEvuzO2DmAzLukE9UryiUvejD3tMp9a1D1NJETerIfKobBUCLfviP6QEk500166eD2IATaXM59qgUI+YDA=="],
|
||||
|
||||
"@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-4Mh18J26+ao1oX5wXJfWlTT+Q1OpDR8ssiC9PDOuEgVBGloqg18Fw7h5Ct8DyT9NBYwJgtJ2nLjKKFU6RP1G1Q=="],
|
||||
|
||||
"@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0" } }, "sha512-0R/+/Il5y8nB/By90o8hy/bWVYptbIfvoTYad0igYQO5RefhNCDmNzqxaMx7K1t/QWo0d6UynqpqN5cCQt1MCg=="],
|
||||
|
||||
"@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.5", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-pHgASxl50rrtOztgQCPmOXFjRW+mCd7ALr/3uXNzRrRoGV5G2+78GOsQ3HlQuBVHCh9o6xqMNvlIKZjWn4Euug=="],
|
||||
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.3.10", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.1", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "@smithy/util-hex-encoding": "^4.2.1", "@smithy/util-middleware": "^4.2.10", "@smithy/util-uri-escape": "^4.2.1", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-Wab3wW8468WqTKIxI+aZe3JYO52/RYT/8sDOdzkUhjnLakLe9qoQqIcfih/qxcF4qWEFoWBszY0mj5uxffaVXA=="],
|
||||
|
||||
"@smithy/smithy-client": ["@smithy/smithy-client@4.12.0", "", { "dependencies": { "@smithy/core": "^3.23.6", "@smithy/middleware-endpoint": "^4.4.20", "@smithy/middleware-stack": "^4.2.10", "@smithy/protocol-http": "^5.3.10", "@smithy/types": "^4.13.0", "@smithy/util-stream": "^4.5.15", "tslib": "^2.6.2" } }, "sha512-R8bQ9K3lCcXyZmBnQqUZJF4ChZmtWT5NLi6x5kgWx5D+/j0KorXcA0YcFg/X5TOgnTCy1tbKc6z2g2y4amFupQ=="],
|
||||
|
||||
"@smithy/types": ["@smithy/types@4.13.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-COuLsZILbbQsdrwKQpkkpyep7lCsByxwj7m0Mg5v66/ZTyenlfBc40/QFQ5chO0YN/PNEH1Bi3fGtfXPnYNeDw=="],
|
||||
|
||||
"@smithy/url-parser": ["@smithy/url-parser@4.2.10", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-uypjF7fCDsRk26u3qHmFI/ePL7bxxB9vKkE+2WKEciHhz+4QtbzWiHRVNRJwU3cKhrYDYQE3b0MRFtqfLYdA4A=="],
|
||||
|
||||
"@smithy/util-base64": ["@smithy/util-base64@4.3.1", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.1", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-BKGuawX4Doq/bI/uEmg+Zyc36rJKWuin3py89PquXBIBqmbnJwBBsmKhdHfNEp0+A4TDgLmT/3MSKZ1SxHcR6w=="],
|
||||
|
||||
"@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-SiJeLiozrAoCrgDBUgsVbmqHmMgg/2bA15AzcbcW+zan7SuyAVHN4xTSbq0GlebAIwlcaX32xacnrG488/J/6g=="],
|
||||
|
||||
"@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.2.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4rHqBvxtJEBvsZcFQSPQqXP2b/yy/YlB66KlcEgcH2WNoOKCKB03DSLzXmOsXjbl8dJ4OEYTn31knhdznwk7zw=="],
|
||||
|
||||
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.1", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-/swhmt1qTiVkaejlmMPPDgZhEaWb/HWMGRBheaxwuVkusp/z+ErJyQxO6kaXumOciZSWlmq6Z5mNylCd33X7Ig=="],
|
||||
|
||||
"@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-462id/00U8JWFw6qBuTSWfN5TxOHvDu4WliI97qOIOnuC/g+NDAknTU8eoGXEPlLkRVgWEr03jJBLV4o2FL8+A=="],
|
||||
|
||||
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.36", "", { "dependencies": { "@smithy/property-provider": "^4.2.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-R0smq7EHQXRVMxkAxtH5akJ/FvgAmNF6bUy/GwY/N20T4GrwjT633NFm0VuRpC+8Bbv8R9A0DoJ9OiZL/M3xew=="],
|
||||
|
||||
"@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.39", "", { "dependencies": { "@smithy/config-resolver": "^4.4.9", "@smithy/credential-provider-imds": "^4.2.10", "@smithy/node-config-provider": "^4.3.10", "@smithy/property-provider": "^4.2.10", "@smithy/smithy-client": "^4.12.0", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-otWuoDm35btJV1L8MyHrPl462B07QCdMTktKc7/yM+Psv6KbED/ziXiHnmr7yPHUjfIwE9S8Max0LO24Mo3ZVg=="],
|
||||
|
||||
"@smithy/util-endpoints": ["@smithy/util-endpoints@3.3.1", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-xyctc4klmjmieQiF9I1wssBWleRV0RhJ2DpO8+8yzi2LO1Z+4IWOZNGZGNj4+hq9kdo+nyfrRLmQTzc16Op2Vg=="],
|
||||
|
||||
"@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-c1hHtkgAWmE35/50gmdKajgGAKV3ePJ7t6UtEmpfCWJmQE9BQAQPz0URUVI89eSkcDqCtzqllxzG28IQoZPvwA=="],
|
||||
|
||||
"@smithy/util-middleware": ["@smithy/util-middleware@4.2.10", "", { "dependencies": { "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-LxaQIWLp4y0r72eA8mwPNQ9va4h5KeLM0I3M/HV9klmFaY2kN766wf5vsTzmaOpNNb7GgXAd9a25P3h8T49PSA=="],
|
||||
|
||||
"@smithy/util-retry": ["@smithy/util-retry@4.2.10", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-HrBzistfpyE5uqTwiyLsFHscgnwB0kgv8vySp7q5kZ0Eltn/tjosaSGGDj/jJ9ys7pWzIP/icE2d+7vMKXLv7A=="],
|
||||
|
||||
"@smithy/util-stream": ["@smithy/util-stream@4.5.15", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.11", "@smithy/node-http-handler": "^4.4.12", "@smithy/types": "^4.13.0", "@smithy/util-base64": "^4.3.1", "@smithy/util-buffer-from": "^4.2.1", "@smithy/util-hex-encoding": "^4.2.1", "@smithy/util-utf8": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-OlOKnaqnkU9X+6wEkd7mN+WB7orPbCVDauXOj22Q7VtiTkvy7ZdSsOg4QiNAZMgI4OkvNf+/VLUC3VXkxuWJZw=="],
|
||||
|
||||
"@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YmiUDn2eo2IOiWYYvGQkgX5ZkBSiTQu4FlDo5jNPpAxng2t6Sjb6WutnZV9l6VR4eJul1ABmCrnWBC9hKHQa6Q=="],
|
||||
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.2.1", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.1", "tslib": "^2.6.2" } }, "sha512-DSIwNaWtmzrNQHv8g7DBGR9mulSit65KSj5ymGEIAknmIN8IpbZefEep10LaMG/P/xquwbmJ1h9ectz8z6mV6g=="],
|
||||
|
||||
"@smithy/util-waiter": ["@smithy/util-waiter@4.2.10", "", { "dependencies": { "@smithy/abort-controller": "^4.2.10", "@smithy/types": "^4.13.0", "tslib": "^2.6.2" } }, "sha512-4eTWph/Lkg1wZEDAyObwme0kmhEb7J/JjibY2znJdrYRgKbKqB7YoEhhJVJ4R1g/SYih4zuwX7LpJaM8RsnTVg=="],
|
||||
|
||||
"@smithy/uuid": ["@smithy/uuid@1.1.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-dSfDCeihDmZlV2oyr0yWPTUfh07suS+R5OB+FZGiv/hHyK3hrFBW5rR1UYjfa57vBsrP9lciFkRPzebaV1Qujw=="],
|
||||
|
||||
"@spruceid/siwe-parser": ["@spruceid/siwe-parser@2.1.2", "", { "dependencies": { "@noble/hashes": "^1.1.2", "apg-js": "^4.3.0", "uri-js": "^4.4.1", "valid-url": "^1.0.9" } }, "sha512-d/r3S1LwJyMaRAKQ0awmo9whfXeE88Qt00vRj91q5uv5ATtWIQEGJ67Yr5eSZw5zp1/fZCXZYuEckt8lSkereQ=="],
|
||||
|
||||
"@stablelib/binary": ["@stablelib/binary@1.0.1", "", { "dependencies": { "@stablelib/int": "^1.0.1" } }, "sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q=="],
|
||||
|
||||
"@stablelib/int": ["@stablelib/int@1.0.1", "", {}, "sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w=="],
|
||||
|
||||
"@stablelib/random": ["@stablelib/random@1.0.2", "", { "dependencies": { "@stablelib/binary": "^1.0.1", "@stablelib/wipe": "^1.0.1" } }, "sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w=="],
|
||||
|
||||
"@stablelib/wipe": ["@stablelib/wipe@1.0.1", "", {}, "sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg=="],
|
||||
|
||||
"@swc/core": ["@swc/core@1.15.8", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.25" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.15.8", "@swc/core-darwin-x64": "1.15.8", "@swc/core-linux-arm-gnueabihf": "1.15.8", "@swc/core-linux-arm64-gnu": "1.15.8", "@swc/core-linux-arm64-musl": "1.15.8", "@swc/core-linux-x64-gnu": "1.15.8", "@swc/core-linux-x64-musl": "1.15.8", "@swc/core-win32-arm64-msvc": "1.15.8", "@swc/core-win32-ia32-msvc": "1.15.8", "@swc/core-win32-x64-msvc": "1.15.8" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-T8keoJjXaSUoVBCIjgL6wAnhADIb09GOELzKg10CjNg+vLX48P93SME6jTfte9MZIm5m+Il57H3rTSk/0kzDUw=="],
|
||||
|
||||
"@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.15.8", "", { "os": "darwin", "cpu": "arm64" }, "sha512-M9cK5GwyWWRkRGwwCbREuj6r8jKdES/haCZ3Xckgkl8MUQJZA3XB7IXXK1IXRNeLjg6m7cnoMICpXv1v1hlJOg=="],
|
||||
|
|
@ -166,28 +419,122 @@
|
|||
|
||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||
|
||||
"@types/mailparser": ["@types/mailparser@3.4.6", "", { "dependencies": { "@types/node": "*", "iconv-lite": "^0.6.3" } }, "sha512-wVV3cnIKzxTffaPH8iRnddX1zahbYB1ZEoAxyhoBo3TBCBuK6nZ8M8JYO/RhsCuuBVOw/DEN/t/ENbruwlxn6Q=="],
|
||||
|
||||
"@types/node": ["@types/node@22.19.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA=="],
|
||||
|
||||
"@types/nodemailer": ["@types/nodemailer@6.4.22", "", { "dependencies": { "@types/node": "*" } }, "sha512-HV16KRsW7UyZBITE07B62k8PRAKFqRSFXn1T7vslurVjN761tMDBhk5Lbt17ehyTzK6XcyJnAgUpevrvkcVOzw=="],
|
||||
|
||||
"@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
|
||||
|
||||
"@x402/core": ["@x402/core@2.5.0", "", { "dependencies": { "zod": "^3.24.2" } }, "sha512-nUr8HW8WhkU1DvrpUfsRvALy5NF8UWKoFezZOtX61mohxp2lWZpJ2GnvscxDM8nmBAbtIollmksd5z5pj8InXw=="],
|
||||
|
||||
"@x402/evm": ["@x402/evm@2.5.0", "", { "dependencies": { "@x402/core": "~2.5.0", "@x402/extensions": "~2.5.0", "viem": "^2.39.3", "zod": "^3.24.2" } }, "sha512-MBSTQZwLobMVcmYO7itOMJRkxfHstsDyr7F94o9Rk/Oinz0kjvCe4DFgZmFXyz3nQUgQFmDVgTK5KIzfYR5uIA=="],
|
||||
|
||||
"@x402/extensions": ["@x402/extensions@2.5.0", "", { "dependencies": { "@scure/base": "^1.2.6", "@x402/core": "~2.5.0", "ajv": "^8.17.1", "siwe": "^2.3.2", "tweetnacl": "^1.0.3", "viem": "^2.43.5", "zod": "^3.24.2" } }, "sha512-e7IQShbGUM/XQmzI8DQh2tX/k2XDUGI9DNF+ij2NHUyPEqAt5/mJCwOlaxS/60FWFdfFRfWjTsqaoS7Z8WLi+A=="],
|
||||
|
||||
"@zone-eu/mailsplit": ["@zone-eu/mailsplit@5.4.8", "", { "dependencies": { "libbase64": "1.3.0", "libmime": "5.3.7", "libqp": "2.1.1" } }, "sha512-eEyACj4JZ7sjzRvy26QhLgKEMWwQbsw1+QZnlLX+/gihcNH07lVPOcnwf5U6UAL7gkc//J3jVd76o/WS+taUiA=="],
|
||||
|
||||
"abitype": ["abitype@1.2.3", "", { "peerDependencies": { "typescript": ">=5.0.4", "zod": "^3.22.0 || ^4.0.0" }, "optionalPeers": ["typescript", "zod"] }, "sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg=="],
|
||||
|
||||
"aes-js": ["aes-js@4.0.0-beta.5", "", {}, "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q=="],
|
||||
|
||||
"ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="],
|
||||
|
||||
"apg-js": ["apg-js@4.4.0", "", {}, "sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q=="],
|
||||
|
||||
"atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="],
|
||||
|
||||
"bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
|
||||
|
||||
"color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
|
||||
|
||||
"csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
|
||||
|
||||
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="],
|
||||
|
||||
"domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="],
|
||||
|
||||
"domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="],
|
||||
|
||||
"domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="],
|
||||
|
||||
"encoding-japanese": ["encoding-japanese@2.2.0", "", {}, "sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A=="],
|
||||
|
||||
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||
|
||||
"esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
|
||||
|
||||
"ethers": ["ethers@6.16.0", "", { "dependencies": { "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "22.7.5", "aes-js": "4.0.0-beta.5", "tslib": "2.7.0", "ws": "8.17.1" } }, "sha512-U1wulmetNymijEhpSEQ7Ct/P/Jw9/e7R1j5XIbPRydgV2DjLVMsULDlNksq3RQnFgKoLlZf88ijYtWEXcPa07A=="],
|
||||
|
||||
"eventemitter3": ["eventemitter3@5.0.1", "", {}, "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
||||
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
|
||||
|
||||
"fast-xml-parser": ["fast-xml-parser@5.3.6", "", { "dependencies": { "strnum": "^2.1.2" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA=="],
|
||||
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
||||
|
||||
"he": ["he@1.2.0", "", { "bin": { "he": "bin/he" } }, "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="],
|
||||
|
||||
"hono": ["hono@4.11.7", "", {}, "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw=="],
|
||||
|
||||
"html-to-text": ["html-to-text@9.0.5", "", { "dependencies": { "@selderee/plugin-htmlparser2": "^0.11.0", "deepmerge": "^4.3.1", "dom-serializer": "^2.0.0", "htmlparser2": "^8.0.2", "selderee": "^0.11.0" } }, "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg=="],
|
||||
|
||||
"htmlparser2": ["htmlparser2@8.0.2", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.0.1", "entities": "^4.4.0" } }, "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA=="],
|
||||
|
||||
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||
|
||||
"imapflow": ["imapflow@1.2.10", "", { "dependencies": { "@zone-eu/mailsplit": "5.4.8", "encoding-japanese": "2.2.0", "iconv-lite": "0.7.2", "libbase64": "1.3.0", "libmime": "5.3.7", "libqp": "2.1.1", "nodemailer": "8.0.1", "pino": "10.3.1", "socks": "2.8.7" } }, "sha512-tqmk0Gj4YBEnGCjjrUYWIf3Z4tzn4iihUcMkBRbafvHF3LqEiYNCSJAAYYbwERFxlikOJ3zzqtEcoxCUTjMv2Q=="],
|
||||
|
||||
"ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
|
||||
|
||||
"is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="],
|
||||
|
||||
"isows": ["isows@1.0.7", "", { "peerDependencies": { "ws": "*" } }, "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg=="],
|
||||
|
||||
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
|
||||
|
||||
"leac": ["leac@0.6.0", "", {}, "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg=="],
|
||||
|
||||
"libbase64": ["libbase64@1.3.0", "", {}, "sha512-GgOXd0Eo6phYgh0DJtjQ2tO8dc0IVINtZJeARPeiIJqge+HdsWSuaDTe8ztQ7j/cONByDZ3zeB325AHiv5O0dg=="],
|
||||
|
||||
"libmime": ["libmime@5.3.7", "", { "dependencies": { "encoding-japanese": "2.2.0", "iconv-lite": "0.6.3", "libbase64": "1.3.0", "libqp": "2.1.1" } }, "sha512-FlDb3Wtha8P01kTL3P9M+ZDNDWPKPmKHWaU/cG/lg5pfuAwdflVpZE+wm9m7pKmC5ww6s+zTxBKS1p6yl3KpSw=="],
|
||||
|
||||
"libqp": ["libqp@2.1.1", "", {}, "sha512-0Wd+GPz1O134cP62YU2GTOPNA7Qgl09XwCqM5zpBv87ERCXdfDtyKXvV7c9U22yWJh44QZqBocFnXN11K96qow=="],
|
||||
|
||||
"linkify-it": ["linkify-it@5.0.0", "", { "dependencies": { "uc.micro": "^2.0.0" } }, "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ=="],
|
||||
|
||||
"mailparser": ["mailparser@3.9.3", "", { "dependencies": { "@zone-eu/mailsplit": "5.4.8", "encoding-japanese": "2.2.0", "he": "1.2.0", "html-to-text": "9.0.5", "iconv-lite": "0.7.2", "libmime": "5.3.7", "linkify-it": "5.0.0", "nodemailer": "7.0.13", "punycode.js": "2.3.1", "tlds": "1.261.0" } }, "sha512-AnB0a3zROum6fLaa52L+/K2SoRJVyFDk78Ea6q1D0ofcZLxWEWDtsS1+OrVqKbV7r5dulKL/AwYQccFGAPpuYQ=="],
|
||||
|
||||
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
||||
|
||||
"nodemailer": ["nodemailer@6.10.1", "", {}, "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA=="],
|
||||
|
||||
"on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
|
||||
|
||||
"ox": ["ox@0.12.4", "", { "dependencies": { "@adraffy/ens-normalize": "^1.11.0", "@noble/ciphers": "^1.3.0", "@noble/curves": "1.9.1", "@noble/hashes": "^1.8.0", "@scure/bip32": "^1.7.0", "@scure/bip39": "^1.6.0", "abitype": "^1.2.3", "eventemitter3": "5.0.1" }, "peerDependencies": { "typescript": ">=5.4.0" }, "optionalPeers": ["typescript"] }, "sha512-+P+C7QzuwPV8lu79dOwjBKfB2CbnbEXe/hfyyrff1drrO1nOOj3Hc87svHfcW1yneRr3WXaKr6nz11nq+/DF9Q=="],
|
||||
|
||||
"parseley": ["parseley@0.12.1", "", { "dependencies": { "leac": "^0.6.0", "peberminta": "^0.9.0" } }, "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw=="],
|
||||
|
||||
"peberminta": ["peberminta@0.9.0", "", {}, "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ=="],
|
||||
|
||||
"perfect-arrows": ["perfect-arrows@0.3.7", "", {}, "sha512-wEN2gerTPVWl3yqoFEF8OeGbg3aRe2sxNUi9rnyYrCsL4JcI6K2tBDezRtqVrYG0BNtsWLdYiiTrYm+X//8yLQ=="],
|
||||
|
||||
"perfect-freehand": ["perfect-freehand@1.2.2", "", {}, "sha512-eh31l019WICQ03pkF3FSzHxB8n07ItqIQ++G5UV8JX0zVOXzgTGCqnRR0jJ2h9U8/2uW4W4mtGJELt9kEV0CFQ=="],
|
||||
|
|
@ -196,28 +543,146 @@
|
|||
|
||||
"picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"pino": ["pino@10.3.1", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^4.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg=="],
|
||||
|
||||
"pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="],
|
||||
|
||||
"pino-std-serializers": ["pino-std-serializers@7.1.0", "", {}, "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw=="],
|
||||
|
||||
"postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
|
||||
|
||||
"postgres": ["postgres@3.4.8", "", {}, "sha512-d+JFcLM17njZaOLkv6SCev7uoLaBtfK86vMUXhW1Z4glPWh4jozno9APvW/XKFJ3CCxVoC7OL38BqRydtu5nGg=="],
|
||||
|
||||
"process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="],
|
||||
|
||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||
|
||||
"punycode.js": ["punycode.js@2.3.1", "", {}, "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA=="],
|
||||
|
||||
"quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="],
|
||||
|
||||
"real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
|
||||
|
||||
"require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
|
||||
|
||||
"rollup": ["rollup@4.54.0", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.54.0", "@rollup/rollup-android-arm64": "4.54.0", "@rollup/rollup-darwin-arm64": "4.54.0", "@rollup/rollup-darwin-x64": "4.54.0", "@rollup/rollup-freebsd-arm64": "4.54.0", "@rollup/rollup-freebsd-x64": "4.54.0", "@rollup/rollup-linux-arm-gnueabihf": "4.54.0", "@rollup/rollup-linux-arm-musleabihf": "4.54.0", "@rollup/rollup-linux-arm64-gnu": "4.54.0", "@rollup/rollup-linux-arm64-musl": "4.54.0", "@rollup/rollup-linux-loong64-gnu": "4.54.0", "@rollup/rollup-linux-ppc64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-gnu": "4.54.0", "@rollup/rollup-linux-riscv64-musl": "4.54.0", "@rollup/rollup-linux-s390x-gnu": "4.54.0", "@rollup/rollup-linux-x64-gnu": "4.54.0", "@rollup/rollup-linux-x64-musl": "4.54.0", "@rollup/rollup-openharmony-arm64": "4.54.0", "@rollup/rollup-win32-arm64-msvc": "4.54.0", "@rollup/rollup-win32-ia32-msvc": "4.54.0", "@rollup/rollup-win32-x64-gnu": "4.54.0", "@rollup/rollup-win32-x64-msvc": "4.54.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-3nk8Y3a9Ea8szgKhinMlGMhGMw89mqule3KWczxhIzqudyHdCIOHw8WJlj/r329fACjKLEh13ZSk7oE22kyeIw=="],
|
||||
|
||||
"safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="],
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"selderee": ["selderee@0.11.0", "", { "dependencies": { "parseley": "^0.12.0" } }, "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA=="],
|
||||
|
||||
"semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
|
||||
|
||||
"sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="],
|
||||
|
||||
"simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="],
|
||||
|
||||
"siwe": ["siwe@2.3.2", "", { "dependencies": { "@spruceid/siwe-parser": "^2.1.2", "@stablelib/random": "^1.0.1", "uri-js": "^4.4.1", "valid-url": "^1.0.9" }, "peerDependencies": { "ethers": "^5.6.8 || ^6.0.8" } }, "sha512-aSf+6+Latyttbj5nMu6GF3doMfv2UYj83hhwZgUF20ky6fTS83uVhkQABdIVnEuS8y1bBdk7p6ltb9SmlhTTlA=="],
|
||||
|
||||
"smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
|
||||
|
||||
"socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
|
||||
|
||||
"sonic-boom": ["sonic-boom@4.2.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q=="],
|
||||
|
||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||
|
||||
"split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
|
||||
|
||||
"strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="],
|
||||
|
||||
"thread-stream": ["thread-stream@4.0.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"tlds": ["tlds@1.261.0", "", { "bin": { "tlds": "bin.js" } }, "sha512-QXqwfEl9ddlGBaRFXIvNKK6OhipSiLXuRuLJX5DErz0o0Q0rYxulWLdFryTkV5PkdZct5iMInwYEGe/eR++1AA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"tweetnacl": ["tweetnacl@1.0.3", "", {}, "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="],
|
||||
|
||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||
|
||||
"uc.micro": ["uc.micro@2.1.0", "", {}, "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A=="],
|
||||
|
||||
"undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
|
||||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="],
|
||||
|
||||
"valid-url": ["valid-url@1.0.9", "", {}, "sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA=="],
|
||||
|
||||
"viem": ["viem@2.46.3", "", { "dependencies": { "@noble/curves": "1.9.1", "@noble/hashes": "1.8.0", "@scure/bip32": "1.7.0", "@scure/bip39": "1.6.0", "abitype": "1.2.3", "isows": "1.0.7", "ox": "0.12.4", "ws": "8.18.3" }, "peerDependencies": { "typescript": ">=5.0.4" }, "optionalPeers": ["typescript"] }, "sha512-2LJS+Hyh2sYjHXQtzfv1kU9pZx9dxFzvoU/ZKIcn0FNtOU0HQuIICuYdWtUDFHaGXbAdVo8J1eCvmjkL9JVGwg=="],
|
||||
|
||||
"vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
|
||||
|
||||
"vite-plugin-top-level-await": ["vite-plugin-top-level-await@1.6.0", "", { "dependencies": { "@rollup/plugin-virtual": "^3.0.2", "@swc/core": "^1.12.14", "@swc/wasm": "^1.12.14", "uuid": "10.0.0" }, "peerDependencies": { "vite": ">=2.8" } }, "sha512-bNhUreLamTIkoulCR9aDXbTbhLk6n1YE8NJUTTxl5RYskNRtzOR0ASzSjBVRtNdjIfngDXo11qOsybGLNsrdww=="],
|
||||
|
||||
"vite-plugin-wasm": ["vite-plugin-wasm@3.5.0", "", { "peerDependencies": { "vite": "^2 || ^3 || ^4 || ^5 || ^6 || ^7" } }, "sha512-X5VWgCnqiQEGb+omhlBVsvTfxikKtoOgAzQ95+BZ8gQ+VfMHIjSHr0wyvXFQCa0eKQ0fKyaL0kWcEnYqBac4lQ=="],
|
||||
|
||||
"ws": ["ws@8.18.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg=="],
|
||||
|
||||
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||
|
||||
"@automerge/automerge/uuid": ["uuid@9.0.1", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA=="],
|
||||
|
||||
"@aws-crypto/sha1-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@scure/bip32/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="],
|
||||
|
||||
"@scure/bip32/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||
|
||||
"@scure/bip39/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||
|
||||
"@spruceid/siwe-parser/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||
|
||||
"ethers/@adraffy/ens-normalize": ["@adraffy/ens-normalize@1.10.1", "", {}, "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw=="],
|
||||
|
||||
"ethers/@noble/curves": ["@noble/curves@1.2.0", "", { "dependencies": { "@noble/hashes": "1.3.2" } }, "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw=="],
|
||||
|
||||
"ethers/@noble/hashes": ["@noble/hashes@1.3.2", "", {}, "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ=="],
|
||||
|
||||
"ethers/@types/node": ["@types/node@22.7.5", "", { "dependencies": { "undici-types": "~6.19.2" } }, "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ=="],
|
||||
|
||||
"ethers/tslib": ["tslib@2.7.0", "", {}, "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA=="],
|
||||
|
||||
"ethers/ws": ["ws@8.17.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ=="],
|
||||
|
||||
"imapflow/iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
||||
|
||||
"imapflow/nodemailer": ["nodemailer@8.0.1", "", {}, "sha512-5kcldIXmaEjZcHR6F28IKGSgpmZHaF1IXLWFTG+Xh3S+Cce4MiakLtWY+PlBU69fLbRa8HlaGIrC/QolUpHkhg=="],
|
||||
|
||||
"mailparser/iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
|
||||
|
||||
"mailparser/nodemailer": ["nodemailer@7.0.13", "", {}, "sha512-PNDFSJdP+KFgdsG3ZzMXCgquO7I6McjY2vlqILjtJd0hy8wEvtugS9xKRF2NWlPNGxvLCXlTNIae4serI7dinw=="],
|
||||
|
||||
"ox/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="],
|
||||
|
||||
"ox/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||
|
||||
"viem/@noble/curves": ["@noble/curves@1.9.1", "", { "dependencies": { "@noble/hashes": "1.8.0" } }, "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA=="],
|
||||
|
||||
"viem/@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="],
|
||||
|
||||
"@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"ethers/@types/node/undici-types": ["undici-types@6.19.8", "", {}, "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="],
|
||||
|
||||
"@aws-crypto/sha1-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,12 +54,12 @@ export class FolkBookShelf extends HTMLElement {
|
|||
|
||||
private loadDemoBooks() {
|
||||
this.books = [
|
||||
{ id: "b1", slug: "governing-the-commons", title: "Governing the Commons", author: "Elinor Ostrom", description: "Analysis of collective action and the governance of common-pool resources", pdf_size_bytes: 2457600, page_count: 280, tags: ["economics", "governance"], cover_color: "#2563eb", contributor_name: "Community Library", featured: true, view_count: 342, created_at: "2026-01-15" },
|
||||
{ id: "b2", slug: "the-mushroom-at-the-end-of-the-world", title: "The Mushroom at the End of the World", author: "Anna Lowenhaupt Tsing", description: "On the possibility of life in capitalist ruins", pdf_size_bytes: 3145728, page_count: 352, tags: ["ecology", "anthropology"], cover_color: "#059669", contributor_name: null, featured: false, view_count: 187, created_at: "2026-01-20" },
|
||||
{ id: "b3", slug: "doughnut-economics", title: "Doughnut Economics", author: "Kate Raworth", description: "Seven ways to think like a 21st-century economist", pdf_size_bytes: 1887436, page_count: 320, tags: ["economics"], cover_color: "#d97706", contributor_name: "Reading Circle", featured: true, view_count: 256, created_at: "2026-02-01" },
|
||||
{ id: "b4", slug: "patterns-of-commoning", title: "Patterns of Commoning", author: "David Bollier & Silke Helfrich", description: "A collection of essays on commons-based peer production", pdf_size_bytes: 4194304, page_count: 416, tags: ["commons", "governance"], cover_color: "#7c3aed", contributor_name: null, featured: false, view_count: 98, created_at: "2026-02-05" },
|
||||
{ id: "b5", slug: "entangled-life", title: "Entangled Life", author: "Merlin Sheldrake", description: "How fungi make our worlds, change our minds, and shape our futures", pdf_size_bytes: 2621440, page_count: 368, tags: ["ecology", "science"], cover_color: "#0891b2", contributor_name: "Mycofi Lab", featured: false, view_count: 431, created_at: "2026-02-10" },
|
||||
{ id: "b6", slug: "free-fair-and-alive", title: "Free, Fair, and Alive", author: "David Bollier & Silke Helfrich", description: "The insurgent power of the commons", pdf_size_bytes: 3670016, page_count: 340, tags: ["commons", "politics"], cover_color: "#e11d48", contributor_name: null, featured: true, view_count: 175, created_at: "2026-02-12" }
|
||||
{ id: "b1", slug: "amusing-ourselves-to-death", title: "Amusing Ourselves to Death", author: "Neil Postman", description: "A prophetic look at what happens when politics, journalism, education, and even religion become subject to the demands of entertainment. Originally published in 1985, this book remains incredibly relevant in the age of social media and constant digital distraction.", pdf_size_bytes: 2457600, page_count: 231, tags: ["media criticism", "society", "technology", "culture"], cover_color: "#1e3a5f", contributor_name: null, featured: true, view_count: 523, created_at: "2025-11-10" },
|
||||
{ id: "b2", slug: "interference", title: "Interference: A Grand Scientific Musical Theory", author: "Richard Merrick", description: "A groundbreaking exploration of Harmonic Interference Theory - a set of principles explaining music perception using the physics of harmonic standing waves, connecting music theory to cymatics, Fibonacci sequences, and the fundamental patterns found throughout nature.", pdf_size_bytes: 8388608, page_count: 524, tags: ["music theory", "harmonics", "cymatics", "science", "perception"], cover_color: "#7c3aed", contributor_name: null, featured: true, view_count: 312, created_at: "2025-12-05" },
|
||||
{ id: "b3", slug: "governing-the-commons", title: "Governing the Commons", author: "Elinor Ostrom", description: "Analysis of collective action and the governance of common-pool resources", pdf_size_bytes: 2457600, page_count: 280, tags: ["economics", "governance"], cover_color: "#2563eb", contributor_name: "Community Library", featured: true, view_count: 342, created_at: "2026-01-15" },
|
||||
{ id: "b4", slug: "the-mushroom-at-the-end-of-the-world", title: "The Mushroom at the End of the World", author: "Anna Lowenhaupt Tsing", description: "On the possibility of life in capitalist ruins", pdf_size_bytes: 3145728, page_count: 352, tags: ["ecology", "anthropology"], cover_color: "#059669", contributor_name: null, featured: false, view_count: 187, created_at: "2026-01-20" },
|
||||
{ id: "b5", slug: "doughnut-economics", title: "Doughnut Economics", author: "Kate Raworth", description: "Seven ways to think like a 21st-century economist", pdf_size_bytes: 1887436, page_count: 320, tags: ["economics"], cover_color: "#d97706", contributor_name: "Reading Circle", featured: false, view_count: 256, created_at: "2026-02-01" },
|
||||
{ id: "b6", slug: "entangled-life", title: "Entangled Life", author: "Merlin Sheldrake", description: "How fungi make our worlds, change our minds, and shape our futures", pdf_size_bytes: 2621440, page_count: 368, tags: ["ecology", "science"], cover_color: "#0891b2", contributor_name: "Mycofi Lab", featured: false, view_count: 431, created_at: "2026-02-10" },
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,29 +35,61 @@ class FolkCalendarView extends HTMLElement {
|
|||
const month = now.getMonth();
|
||||
|
||||
const sources = [
|
||||
{ name: "rSpace Team", color: "#6366f1" },
|
||||
{ name: "Community", color: "#22c55e" },
|
||||
{ name: "Personal", color: "#f59e0b" },
|
||||
{ name: "Work (Google Calendar)", color: "#3b82f6" },
|
||||
{ name: "Travel (Manual)", color: "#f97316" },
|
||||
{ name: "Personal (ICS)", color: "#10b981" },
|
||||
{ name: "Conferences (Manual)", color: "#8b5cf6" },
|
||||
];
|
||||
|
||||
const demoEvents = [
|
||||
{ day: 3, title: "Sprint Planning", source: 0, desc: "Plan the next two-week sprint", location: "Room A", virtual: false },
|
||||
{ day: 5, title: "Community Call", source: 1, desc: "Open community discussion", location: null, virtual: true },
|
||||
{ day: 8, title: "Design Review", source: 0, desc: "Review new component designs", location: "Design Lab", virtual: false },
|
||||
{ day: 10, title: "Standup", source: 0, desc: "Daily sync — async-first format", location: null, virtual: true },
|
||||
{ day: 14, title: "Hackathon Day 1", source: 1, desc: "Build something local-first in 48h", location: "Hackerspace", virtual: false },
|
||||
{ day: 15, title: "Hackathon Day 2", source: 1, desc: "Demos and judging", location: "Hackerspace", virtual: false },
|
||||
{ day: 18, title: "Release Planning", source: 0, desc: "Scope the next release milestone", location: null, virtual: true },
|
||||
{ day: 20, title: "Town Hall", source: 1, desc: "Monthly all-hands update", location: null, virtual: true },
|
||||
{ day: 22, title: "Retrospective", source: 0, desc: "Reflect on what went well and what to improve", location: "Room B", virtual: false },
|
||||
{ day: 25, title: "Workshop: Local-First", source: 1, desc: "Hands-on local-first architecture workshop", location: "Community Center", virtual: false },
|
||||
{ day: 27, title: "Demo Day", source: 0, desc: "Show off what shipped this month", location: null, virtual: true },
|
||||
{ day: 28, title: "Social Meetup", source: 2, desc: "Casual evening hangout", location: "Cafe Decentralized", virtual: false },
|
||||
// Dense workday calendar across multiple cities
|
||||
const demoEvents: { day: number; title: string; source: number; desc: string; location: string | null; virtual: boolean; startH: number; startM: number; durationMin: number }[] = [
|
||||
// --- Berlin Work Block (Days 3-10) ---
|
||||
{ day: 3, title: "Team Standup", source: 0, desc: "Daily sync — Berlin engineering team", location: "Factory Berlin, Rheinsberger Str. 76/77", virtual: false, startH: 9, startM: 30, durationMin: 30 },
|
||||
{ day: 3, title: "Code Review Session", source: 0, desc: "Review PRs from the weekend batch", location: "Factory Berlin", virtual: false, startH: 14, startM: 0, durationMin: 60 },
|
||||
{ day: 5, title: "Product Review", source: 0, desc: "Quarterly product roadmap review with stakeholders", location: "Factory Berlin, Conference Room 3", virtual: false, startH: 10, startM: 0, durationMin: 90 },
|
||||
{ day: 5, title: "Lunch with Alex", source: 2, desc: "Catch up over Vietnamese food", location: "District Mot, Rosenthaler Str. 62, Berlin", virtual: false, startH: 12, startM: 30, durationMin: 60 },
|
||||
{ day: 7, title: "Sprint Planning", source: 0, desc: "Plan sprint 24 — local-first sync features", location: "Factory Berlin, Conference Room 1", virtual: false, startH: 10, startM: 0, durationMin: 120 },
|
||||
{ day: 7, title: "Architecture Deep-Dive", source: 0, desc: "CRDT merge strategy for offline-first mobile", location: "Factory Berlin", virtual: false, startH: 15, startM: 0, durationMin: 90 },
|
||||
{ day: 8, title: "Client Call NYC", source: 0, desc: "Sync with NYC partner team on API integration", location: null, virtual: true, startH: 16, startM: 0, durationMin: 60 },
|
||||
{ day: 10, title: "1:1 with Manager", source: 0, desc: "Monthly check-in — career growth, project scope", location: "Factory Berlin, Phone Booth 4", virtual: false, startH: 11, startM: 0, durationMin: 45 },
|
||||
{ day: 10, title: "Deploy Prep", source: 0, desc: "Pre-release checklist and staging verification", location: null, virtual: true, startH: 15, startM: 30, durationMin: 60 },
|
||||
|
||||
// --- Travel: Berlin to Amsterdam (Days 12-14) ---
|
||||
{ day: 12, title: "Train Berlin \u2192 Amsterdam", source: 1, desc: "ICE 643 Berlin Hbf \u2192 Amsterdam Centraal, Seat 64 Window", location: "Berlin Hauptbahnhof, Platform 11", virtual: false, startH: 7, startM: 15, durationMin: 390 },
|
||||
{ day: 12, title: "Hotel Check-in", source: 1, desc: "Hotel V Nesplein, Nes 49, Amsterdam", location: "Hotel V Nesplein, Amsterdam", virtual: false, startH: 14, startM: 30, durationMin: 30 },
|
||||
{ day: 13, title: "Partner Meeting", source: 0, desc: "On-site collaboration with Amsterdam design team", location: "WeWork Weteringschans, Amsterdam", virtual: false, startH: 10, startM: 0, durationMin: 180 },
|
||||
{ day: 13, title: "Canal District Walk", source: 2, desc: "Afternoon stroll along Prinsengracht and Jordaan", location: "Prinsengracht, Amsterdam", virtual: false, startH: 15, startM: 0, durationMin: 120 },
|
||||
{ day: 13, title: "Dinner at Moeders", source: 2, desc: "Traditional Dutch dinner — try the stamppot", location: "Restaurant Moeders, Rozengracht 251, Amsterdam", virtual: false, startH: 19, startM: 0, durationMin: 90 },
|
||||
{ day: 14, title: "Return Train Amsterdam \u2192 Berlin", source: 1, desc: "ICE 148 Amsterdam Centraal \u2192 Berlin Hbf, Seat 38 Aisle", location: "Amsterdam Centraal, Platform 7b", virtual: false, startH: 9, startM: 30, durationMin: 390 },
|
||||
|
||||
// --- Personal (Days 15-20) ---
|
||||
{ day: 15, title: "Dinner with Friends", source: 2, desc: "Birthday dinner for Mia at the Italian place", location: "Il Casolare, Grimmstr. 30, Berlin", virtual: false, startH: 19, startM: 30, durationMin: 120 },
|
||||
{ day: 16, title: "Grocery Run", source: 2, desc: "Weekly groceries at the Saturday market", location: "Maybachufer Market, Berlin", virtual: false, startH: 10, startM: 0, durationMin: 60 },
|
||||
{ day: 17, title: "Weekend Hike", source: 2, desc: "Grunewald forest loop trail, ~14 km", location: "S-Bahn Grunewald, Berlin", virtual: false, startH: 8, startM: 0, durationMin: 300 },
|
||||
{ day: 19, title: "Dentist Appointment", source: 2, desc: "Regular checkup, Dr. Weber", location: "Zahnarzt Weber, Torstr. 140, Berlin", virtual: false, startH: 9, startM: 0, durationMin: 45 },
|
||||
{ day: 20, title: "Yoga Class", source: 2, desc: "Vinyasa flow — bring own mat", location: "Yoga Studio Kreuzberg, Oranienstr. 25, Berlin", virtual: false, startH: 7, startM: 30, durationMin: 75 },
|
||||
{ day: 20, title: "Book Club", source: 2, desc: "Discussing \"The Mushroom at the End of the World\" by Anna Tsing", location: "Shakespeare & Sons, Warschauer Str. 74, Berlin", virtual: false, startH: 19, startM: 0, durationMin: 90 },
|
||||
|
||||
// --- Work Wrap-up (Days 21-22) ---
|
||||
{ day: 21, title: "Sprint Retro", source: 0, desc: "Sprint 23 retrospective — what worked, what didn't", location: "Factory Berlin, Conference Room 2", virtual: false, startH: 10, startM: 0, durationMin: 60 },
|
||||
{ day: 21, title: "Release Deploy", source: 0, desc: "Push v2.4.0 to production, monitor metrics", location: null, virtual: true, startH: 14, startM: 0, durationMin: 120 },
|
||||
{ day: 22, title: "Demo Day", source: 0, desc: "Sprint 23 showcase — live demos for stakeholders and community", location: "Factory Berlin, Main Hall", virtual: false, startH: 14, startM: 0, durationMin: 90 },
|
||||
{ day: 22, title: "Team Drinks", source: 2, desc: "Celebrate the release with the team", location: "Prater Garten, Kastanienallee 7-9, Berlin", virtual: false, startH: 17, startM: 30, durationMin: 120 },
|
||||
|
||||
// --- Conference: Web Summit (Days 24-27, Lisbon) ---
|
||||
{ day: 24, title: "Flight Berlin \u2192 Lisbon", source: 1, desc: "TAP TP 571 BER \u2192 LIS, Gate B22", location: "BER Airport, Berlin", virtual: false, startH: 6, startM: 45, durationMin: 195 },
|
||||
{ day: 24, title: "Hotel Check-in Lisbon", source: 1, desc: "Hotel da Baixa, Rua da Prata 242, Lisbon", location: "Hotel da Baixa, Lisbon", virtual: false, startH: 13, startM: 0, durationMin: 30 },
|
||||
{ day: 25, title: "Web Summit Day 1", source: 3, desc: "Opening keynotes, startup pavilion, networking. Main stage + Centre Stage tracks.", location: "Altice Arena / FIL, Lisbon", virtual: false, startH: 9, startM: 0, durationMin: 540 },
|
||||
{ day: 25, title: "Speaker Dinner", source: 3, desc: "Invited speakers dinner at the riverside venue", location: "Ponto Final, Cacilhas, Lisbon", virtual: false, startH: 20, startM: 0, durationMin: 120 },
|
||||
{ day: 26, title: "Web Summit Day 2", source: 3, desc: "Panel: \"Local-First Software & the Future of Collaboration\". Our talk at 14:00 on Centre Stage.", location: "Altice Arena / FIL, Lisbon", virtual: false, startH: 9, startM: 0, durationMin: 540 },
|
||||
{ day: 26, title: "Networking Happy Hour", source: 3, desc: "Post-conference drinks with open-source community", location: "Time Out Market, Lisbon", virtual: false, startH: 18, startM: 30, durationMin: 120 },
|
||||
{ day: 27, title: "Lisbon City Tour", source: 2, desc: "Alfama neighborhood, Tram 28, Pasteis de Belem, Praca do Comercio", location: "Alfama, Lisbon", virtual: false, startH: 10, startM: 0, durationMin: 360 },
|
||||
{ day: 27, title: "Flight Lisbon \u2192 Berlin", source: 1, desc: "TAP TP 572 LIS \u2192 BER, Gate 41", location: "Lisbon Humberto Delgado Airport", virtual: false, startH: 19, startM: 30, durationMin: 195 },
|
||||
];
|
||||
|
||||
this.events = demoEvents.map((e, i) => {
|
||||
const startDate = new Date(year, month, e.day, 10 + (i % 4), 0);
|
||||
const endDate = new Date(startDate.getTime() + 3600000);
|
||||
const startDate = new Date(year, month, e.day, e.startH, e.startM);
|
||||
const endDate = new Date(startDate.getTime() + e.durationMin * 60000);
|
||||
const src = sources[e.source];
|
||||
return {
|
||||
id: `demo-${i + 1}`,
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
private hoveredPerson: string | null = null;
|
||||
private rankItems: { id: number; name: string; emoji: string }[] = [];
|
||||
private rankDragging: number | null = null;
|
||||
private voteOptions: { id: number; name: string; emoji: string; votes: number }[] = [];
|
||||
private voteOptions: { id: string; name: string; color: string; votes: number }[] = [];
|
||||
private voted = false;
|
||||
private votedId: string | null = null;
|
||||
private simTimer: number | null = null;
|
||||
|
||||
constructor() {
|
||||
|
|
@ -140,19 +141,20 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
|
||||
private loadDemoData() {
|
||||
this.rankItems = [
|
||||
{ id: 1, name: "Thai", emoji: "🍜" },
|
||||
{ id: 1, name: "Thai Place", emoji: "🍜" },
|
||||
{ id: 2, name: "Pizza", emoji: "🍕" },
|
||||
{ id: 3, name: "Sushi", emoji: "🍣" },
|
||||
{ id: 3, name: "Sushi Bar", emoji: "🍣" },
|
||||
{ id: 4, name: "Tacos", emoji: "🌮" },
|
||||
{ id: 5, name: "Burgers", emoji: "🍔" },
|
||||
];
|
||||
this.voteOptions = [
|
||||
{ id: 1, name: "Inception", emoji: "🌀", votes: 4 },
|
||||
{ id: 2, name: "Spirited Away", emoji: "🐉", votes: 3 },
|
||||
{ id: 3, name: "The Matrix", emoji: "💊", votes: 5 },
|
||||
{ id: 4, name: "Parasite", emoji: "🪨", votes: 2 },
|
||||
{ id: "action", name: "Action Movie", color: "#ef4444", votes: 2 },
|
||||
{ id: "comedy", name: "Comedy", color: "#f59e0b", votes: 3 },
|
||||
{ id: "horror", name: "Horror", color: "#8b5cf6", votes: 1 },
|
||||
{ id: "scifi", name: "Sci-Fi", color: "#06b6d4", votes: 2 },
|
||||
];
|
||||
this.voted = false;
|
||||
this.votedId = null;
|
||||
this.startVoteSim();
|
||||
this.renderDemo();
|
||||
}
|
||||
|
|
@ -162,7 +164,7 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
const tick = () => {
|
||||
if (this.voted) return;
|
||||
const idx = Math.floor(Math.random() * this.voteOptions.length);
|
||||
this.voteOptions[idx].votes += 1 + Math.floor(Math.random() * 3);
|
||||
this.voteOptions[idx].votes += 1;
|
||||
if (this.demoTab === "voting") this.renderDemo();
|
||||
};
|
||||
const scheduleNext = () => {
|
||||
|
|
@ -217,9 +219,9 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
.rank-item.dragging { opacity: 0.4; transform: scale(0.97); }
|
||||
.rank-item.drag-over { border-color: #6366f1; box-shadow: 0 0 0 2px rgba(99,102,241,0.3); }
|
||||
.rank-pos { width: 28px; height: 28px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 0.8rem; color: #0f172a; flex-shrink: 0; }
|
||||
.rank-pos.gold { background: #fbbf24; }
|
||||
.rank-pos.gold { background: #f59e0b; }
|
||||
.rank-pos.silver { background: #94a3b8; }
|
||||
.rank-pos.bronze { background: #d97706; }
|
||||
.rank-pos.bronze { background: #cd7f32; }
|
||||
.rank-pos.plain { background: #334155; color: #94a3b8; }
|
||||
.rank-emoji { font-size: 1.5rem; flex-shrink: 0; }
|
||||
.rank-name { flex: 1; color: #f1f5f9; font-weight: 600; font-size: 1rem; }
|
||||
|
|
@ -230,11 +232,12 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
.vote-option { display: flex; align-items: center; gap: 12px; padding: 0.75rem 1rem; margin-bottom: 8px; background: #1e293b; border: 1px solid #334155; border-radius: 10px; cursor: pointer; position: relative; overflow: hidden; transition: border-color 0.15s; }
|
||||
.vote-option:hover { border-color: #6366f1; }
|
||||
.vote-option.voted { border-color: #6366f1; }
|
||||
.vote-fill { position: absolute; left: 0; top: 0; bottom: 0; background: rgba(99,102,241,0.12); transition: width 0.4s ease; pointer-events: none; }
|
||||
.vote-emoji { font-size: 1.5rem; flex-shrink: 0; position: relative; z-index: 1; }
|
||||
.vote-fill { position: absolute; left: 0; top: 0; bottom: 0; opacity: 0.12; transition: width 0.7s ease-out; pointer-events: none; }
|
||||
.vote-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; position: relative; z-index: 1; }
|
||||
.vote-name { flex: 1; color: #f1f5f9; font-weight: 600; font-size: 1rem; position: relative; z-index: 1; }
|
||||
.vote-count { color: #818cf8; font-weight: 700; font-size: 1rem; min-width: 36px; text-align: right; position: relative; z-index: 1; }
|
||||
.vote-badge { font-size: 0.65rem; padding: 2px 7px; border-radius: 999px; background: #6366f1; color: #fff; margin-left: 6px; position: relative; z-index: 1; font-weight: 500; }
|
||||
.vote-count { color: #94a3b8; font-weight: 400; font-size: 0.8rem; min-width: 24px; text-align: right; position: relative; z-index: 1; font-variant-numeric: tabular-nums; }
|
||||
.vote-pct { font-weight: 600; font-size: 0.8rem; min-width: 40px; text-align: right; position: relative; z-index: 1; font-variant-numeric: tabular-nums; }
|
||||
.vote-badge { font-size: 0.625rem; padding: 2px 6px; border-radius: 999px; background: rgba(255,255,255,0.05); color: #94a3b8; margin-left: 6px; position: relative; z-index: 1; font-weight: 400; }
|
||||
.vote-actions { display: flex; justify-content: center; margin-top: 1rem; }
|
||||
.vote-reset { padding: 0.5rem 1.25rem; border-radius: 8px; border: 1px solid #334155; background: #1e293b; color: #94a3b8; cursor: pointer; font-size: 0.875rem; font-family: inherit; transition: all 0.15s; }
|
||||
.vote-reset:hover { border-color: #ef4444; color: #fca5a5; }
|
||||
|
|
@ -269,9 +272,9 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
const cx = 200, cy = 200, maxR = 150;
|
||||
const axes = ["Taste", "Price", "Speed", "Healthy", "Distance"];
|
||||
const people: { name: string; color: string; values: number[] }[] = [
|
||||
{ name: "Alice", color: "#f472b6", values: [0.9, 0.5, 0.7, 0.8, 0.4] },
|
||||
{ name: "Bob", color: "#38bdf8", values: [0.6, 0.8, 0.5, 0.4, 0.9] },
|
||||
{ name: "Carol", color: "#a3e635", values: [0.7, 0.6, 0.9, 0.7, 0.6] },
|
||||
{ name: "Alice", color: "#7c5bf5", values: [0.9, 0.6, 0.8, 0.4, 0.7] },
|
||||
{ name: "Bob", color: "#f59e0b", values: [0.5, 0.9, 0.6, 0.7, 0.8] },
|
||||
{ name: "Carol", color: "#10b981", values: [0.7, 0.4, 0.9, 0.8, 0.3] },
|
||||
];
|
||||
const angleStep = 360 / axes.length;
|
||||
|
||||
|
|
@ -351,30 +354,29 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
|
||||
private renderVoting(): string {
|
||||
const sorted = [...this.voteOptions].sort((a, b) => b.votes - a.votes);
|
||||
const total = sorted.reduce((s, o) => s + o.votes, 0);
|
||||
const maxVotes = Math.max(...sorted.map((o) => o.votes), 1);
|
||||
const leaderId = sorted[0]?.id;
|
||||
|
||||
const items = sorted.map((opt) => {
|
||||
const pct = (opt.votes / maxVotes) * 100;
|
||||
const isLeader = opt.id === leaderId;
|
||||
return `<div class="vote-option${this.voted ? " voted" : ""}" data-vote-id="${opt.id}">
|
||||
<div class="vote-fill" style="width:${pct}%"></div>
|
||||
<span class="vote-emoji">${opt.emoji}</span>
|
||||
<span class="vote-name">${this.esc(opt.name)}${isLeader ? `<span class="vote-badge">Leading</span>` : ""}</span>
|
||||
const pct = total > 0 ? (opt.votes / total) * 100 : 0;
|
||||
const isLeader = opt.votes === maxVotes && total > 4;
|
||||
return `<div class="vote-option${this.voted ? " voted" : ""}" data-vote-id="${opt.id}" style="border-color:${this.voted === true ? (this.votedId === opt.id ? opt.color : '#334155') : '#334155'}">
|
||||
<div class="vote-fill" style="width:${pct}%;background:${opt.color}"></div>
|
||||
<span class="vote-dot" style="background:${opt.color}"></span>
|
||||
<span class="vote-name">${this.esc(opt.name)}${isLeader ? `<span class="vote-badge">leading</span>` : ""}</span>
|
||||
<span class="vote-count">${opt.votes}</span>
|
||||
<span class="vote-pct" style="color:${opt.color}">${pct.toFixed(0)}%</span>
|
||||
</div>`;
|
||||
}).join("");
|
||||
|
||||
const status = this.voted
|
||||
? "You voted! Simulation paused."
|
||||
: "Votes are rolling in live...";
|
||||
? "Results are in!"
|
||||
: "Pick a movie \u2014 votes update live";
|
||||
|
||||
return `<div class="vote-wrap">
|
||||
<div class="vote-status">${status}</div>
|
||||
${items}
|
||||
<div class="vote-actions">
|
||||
<button class="vote-reset">Reset</button>
|
||||
</div>
|
||||
${this.voted ? `<div class="vote-actions"><button class="vote-reset">Reset demo</button></div>` : ""}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
|
|
@ -455,11 +457,12 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
this.shadow.querySelectorAll<HTMLElement>(".vote-option").forEach((el) => {
|
||||
el.addEventListener("click", () => {
|
||||
if (this.voted) return;
|
||||
const id = parseInt(el.dataset.voteId || "0", 10);
|
||||
const id = el.dataset.voteId || "";
|
||||
const opt = this.voteOptions.find((o) => o.id === id);
|
||||
if (opt) {
|
||||
opt.votes += 1;
|
||||
this.voted = true;
|
||||
this.votedId = id;
|
||||
this.renderDemo();
|
||||
}
|
||||
});
|
||||
|
|
@ -469,8 +472,14 @@ class FolkChoicesDashboard extends HTMLElement {
|
|||
const resetBtn = this.shadow.querySelector<HTMLButtonElement>(".vote-reset");
|
||||
if (resetBtn) {
|
||||
resetBtn.addEventListener("click", () => {
|
||||
this.voteOptions.forEach((o) => (o.votes = Math.floor(Math.random() * 5) + 1));
|
||||
this.voteOptions = [
|
||||
{ id: "action", name: "Action Movie", color: "#ef4444", votes: 2 },
|
||||
{ id: "comedy", name: "Comedy", color: "#f59e0b", votes: 3 },
|
||||
{ id: "horror", name: "Horror", color: "#8b5cf6", votes: 1 },
|
||||
{ id: "scifi", name: "Sci-Fi", color: "#06b6d4", votes: 2 },
|
||||
];
|
||||
this.voted = false;
|
||||
this.votedId = null;
|
||||
this.startVoteSim();
|
||||
this.renderDemo();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ class FolkInboxClient extends HTMLElement {
|
|||
|
||||
private loadDemoData() {
|
||||
this.mailboxes = [
|
||||
{ slug: "team", name: "Team Inbox", email: "team@rspace.online", description: "Internal team communications" },
|
||||
{ slug: "support", name: "Support", email: "support@rspace.online", description: "User support requests" },
|
||||
{ slug: "team", name: "Team Inbox", email: "team@rspace.online", description: "Shared workspace inbox for internal team communications" },
|
||||
{ slug: "support", name: "Support", email: "support@rspace.online", description: "Community support requests with multi-sig approval workflows" },
|
||||
];
|
||||
this.render();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,12 @@
|
|||
/**
|
||||
* <folk-map-viewer> — real-time location sharing map.
|
||||
* <folk-map-viewer> -- real-time location sharing map.
|
||||
*
|
||||
* Creates/joins map rooms, shows participant locations on a map,
|
||||
* and provides location sharing controls.
|
||||
*
|
||||
* Demo mode: shows 6 cosmolocal print providers on a world map with
|
||||
* connection arcs, interactive hover tooltips, and a feature summary
|
||||
* matching the standalone rMaps capabilities.
|
||||
*/
|
||||
|
||||
class FolkMapViewer extends HTMLElement {
|
||||
|
|
@ -51,28 +55,70 @@ class FolkMapViewer extends HTMLElement {
|
|||
}
|
||||
|
||||
private renderDemo() {
|
||||
const mapWidth = 800;
|
||||
const mapHeight = 400;
|
||||
const W = 900;
|
||||
const H = 460;
|
||||
|
||||
const projectX = (lng: number) => ((lng + 180) * (mapWidth / 360));
|
||||
const projectY = (lat: number) => ((90 - lat) * (mapHeight / 180));
|
||||
const px = (lng: number) => ((lng + 180) / 360) * W;
|
||||
const py = (lat: number) => ((90 - lat) / 180) * H;
|
||||
|
||||
const providerDots = this.providers.map((p) => {
|
||||
const x = projectX(p.lng);
|
||||
const y = projectY(p.lat);
|
||||
const labelX = x + 10;
|
||||
const labelY = y + 4;
|
||||
// Label offsets to avoid overlapping (Pittsburgh/Toronto are close)
|
||||
const labelOffsets: Record<string, [number, number]> = {
|
||||
"Radiant Hall Press": [10, -8],
|
||||
"Tiny Splendor": [-110, 14],
|
||||
"People's Print Shop": [10, 14],
|
||||
"Colour Code Press": [10, -8],
|
||||
"Druckwerkstatt Berlin": [10, 14],
|
||||
"Kink\u014D Printing Collective": [-150, -8],
|
||||
};
|
||||
|
||||
// Connection arcs between providers (great-circle style curves)
|
||||
const connections = [
|
||||
[0, 2], // Pittsburgh -- Toronto
|
||||
[0, 3], // Pittsburgh -- London
|
||||
[3, 4], // London -- Berlin
|
||||
[4, 5], // Berlin -- Tokyo
|
||||
[1, 5], // LA -- Tokyo (Pacific)
|
||||
[0, 1], // Pittsburgh -- LA
|
||||
];
|
||||
|
||||
const arcs = connections.map(([i, j]) => {
|
||||
const a = this.providers[i];
|
||||
const b = this.providers[j];
|
||||
const x1 = px(a.lng), y1 = py(a.lat);
|
||||
const x2 = px(b.lng), y2 = py(b.lat);
|
||||
// Curved midpoint -- arc above the straight line
|
||||
const mx = (x1 + x2) / 2;
|
||||
const my = (y1 + y2) / 2 - Math.abs(x2 - x1) * 0.12;
|
||||
return `<path d="M${x1},${y1} Q${mx},${my} ${x2},${y2}" fill="none" stroke="rgba(148,163,184,0.15)" stroke-width="1" stroke-dasharray="4,3" />`;
|
||||
}).join("\n");
|
||||
|
||||
// Provider pins (drop-pin style) and labels
|
||||
const pins = this.providers.map((p, i) => {
|
||||
const x = px(p.lng);
|
||||
const y = py(p.lat);
|
||||
const [lx, ly] = labelOffsets[p.name] || [10, 4];
|
||||
return `
|
||||
<circle cx="${x}" cy="${y}" r="6" fill="${p.color}" stroke="#fff" stroke-width="1.5" opacity="0.9">
|
||||
<animate attributeName="r" values="6;8;6" dur="2s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
<text x="${labelX}" y="${labelY}" fill="${p.color}" font-size="10" font-weight="600" font-family="system-ui, sans-serif">${this.esc(p.name)}</text>
|
||||
<g class="pin-group" data-idx="${i}">
|
||||
<!-- Pulse ring -->
|
||||
<circle cx="${x}" cy="${y}" r="4" fill="none" stroke="${p.color}" stroke-width="1" opacity="0.5">
|
||||
<animate attributeName="r" values="4;14;4" dur="3s" repeatCount="indefinite" />
|
||||
<animate attributeName="opacity" values="0.5;0;0.5" dur="3s" repeatCount="indefinite" />
|
||||
</circle>
|
||||
<!-- Drop pin body -->
|
||||
<path d="M${x},${y - 2} c0,-7 -6,-12 -6,-16 a6,6 0 1,1 12,0 c0,4 -6,9 -6,16z" fill="${p.color}" stroke="#0f172a" stroke-width="0.8" opacity="0.92" />
|
||||
<!-- Pin center dot -->
|
||||
<circle cx="${x}" cy="${y - 14}" r="2.5" fill="#fff" opacity="0.85" />
|
||||
<!-- Label -->
|
||||
<text x="${x + lx}" y="${y + ly}" fill="${p.color}" font-size="10" font-weight="600" font-family="system-ui,sans-serif" opacity="0.9">${this.esc(p.name)}</text>
|
||||
<text x="${x + lx}" y="${y + ly + 12}" fill="#64748b" font-size="8.5" font-family="system-ui,sans-serif">${this.esc(p.city)}</text>
|
||||
</g>
|
||||
`;
|
||||
}).join("");
|
||||
|
||||
// Legend items
|
||||
const legendItems = this.providers.map((p) => `
|
||||
<div style="display:flex;align-items:center;gap:8px;padding:6px 0;">
|
||||
<div style="width:10px;height:10px;border-radius:50%;background:${p.color};flex-shrink:0;"></div>
|
||||
<div style="display:flex;align-items:center;gap:8px;padding:5px 0;">
|
||||
<div style="width:10px;height:10px;border-radius:50%;background:${p.color};flex-shrink:0;box-shadow:0 0 6px ${p.color}40;"></div>
|
||||
<div>
|
||||
<span style="font-weight:600;font-size:13px;color:#e2e8f0;">${this.esc(p.name)}</span>
|
||||
<span style="font-size:12px;color:#64748b;margin-left:8px;">${this.esc(p.city)}</span>
|
||||
|
|
@ -84,61 +130,91 @@ class FolkMapViewer extends HTMLElement {
|
|||
<style>
|
||||
:host { display: block; font-family: system-ui, -apple-system, sans-serif; color: #e0e0e0; }
|
||||
* { box-sizing: border-box; }
|
||||
.rapp-nav { display: flex; gap: 8px; margin-bottom: 16px; align-items: center; min-height: 36px; }
|
||||
.rapp-nav__title { font-size: 15px; font-weight: 600; flex: 1; color: #e2e8f0; }
|
||||
.status-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
|
||||
.status-connected { background: #22c55e; }
|
||||
.map-container {
|
||||
width: 100%; border-radius: 10px;
|
||||
background: #1a1a2e; border: 1px solid #333;
|
||||
overflow: hidden; padding: 16px;
|
||||
.demo-nav {
|
||||
display: flex; gap: 8px; margin-bottom: 16px; align-items: center; min-height: 36px; flex-wrap: wrap;
|
||||
}
|
||||
.map-svg { width: 100%; height: auto; }
|
||||
.demo-nav__title { font-size: 15px; font-weight: 600; flex: 1; color: #e2e8f0; min-width: 140px; }
|
||||
.demo-nav__badge {
|
||||
display: inline-flex; align-items: center; gap: 5px;
|
||||
font-size: 11px; color: #94a3b8; background: rgba(16,185,129,0.1);
|
||||
border: 1px solid rgba(16,185,129,0.2); border-radius: 20px; padding: 3px 10px;
|
||||
}
|
||||
.demo-nav__badge .dot { width: 6px; height: 6px; border-radius: 50%; background: #22c55e; }
|
||||
.map-wrap {
|
||||
width: 100%; border-radius: 12px; background: #0c1221; border: 1px solid #1e293b;
|
||||
overflow: hidden; position: relative;
|
||||
}
|
||||
.map-svg { display: block; width: 100%; height: auto; }
|
||||
|
||||
/* Hover tooltip */
|
||||
.pin-group { cursor: pointer; }
|
||||
.tooltip {
|
||||
position: absolute; pointer-events: none; opacity: 0; transition: opacity 0.15s;
|
||||
background: #1e293b; border: 1px solid #334155; border-radius: 8px;
|
||||
padding: 8px 12px; font-size: 12px; color: #e2e8f0; white-space: nowrap;
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,0.4); z-index: 10;
|
||||
}
|
||||
.tooltip.visible { opacity: 1; }
|
||||
.tooltip strong { display: block; margin-bottom: 2px; }
|
||||
.tooltip .city { color: #94a3b8; font-size: 11px; }
|
||||
.tooltip .coords { color: #64748b; font-size: 10px; font-family: monospace; }
|
||||
|
||||
.legend {
|
||||
background: rgba(15,23,42,0.5); border: 1px solid #1e293b; border-radius: 10px;
|
||||
background: rgba(15,23,42,0.6); border: 1px solid #1e293b; border-radius: 10px;
|
||||
padding: 16px; margin-top: 16px;
|
||||
}
|
||||
.legend-title { font-size: 13px; font-weight: 600; color: #94a3b8; text-transform: uppercase; letter-spacing: 0.05em; margin-bottom: 8px; }
|
||||
.legend-title {
|
||||
font-size: 12px; font-weight: 600; color: #94a3b8;
|
||||
text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.map-container { height: 300px; }
|
||||
/* Feature highlights row */
|
||||
.features {
|
||||
display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
||||
gap: 10px; margin-top: 16px;
|
||||
}
|
||||
.feat {
|
||||
background: rgba(15,23,42,0.4); border: 1px solid #1e293b; border-radius: 10px;
|
||||
padding: 12px; text-align: center;
|
||||
}
|
||||
.feat-icon { font-size: 20px; margin-bottom: 4px; }
|
||||
.feat-label { font-size: 12px; font-weight: 600; color: #e2e8f0; }
|
||||
.feat-desc { font-size: 10.5px; color: #64748b; margin-top: 2px; line-height: 1.4; }
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.features { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="rapp-nav">
|
||||
<span class="rapp-nav__title">Cosmolocal Print Network</span>
|
||||
<span class="status-dot status-connected"></span>
|
||||
<span style="font-size:12px;color:#888;margin-left:4px;">6 providers</span>
|
||||
<div class="demo-nav">
|
||||
<span class="demo-nav__title">Cosmolocal Print Network</span>
|
||||
<span class="demo-nav__badge"><span class="dot"></span> 6 providers online</span>
|
||||
</div>
|
||||
|
||||
<div class="map-container">
|
||||
<svg class="map-svg" viewBox="0 0 ${mapWidth} ${mapHeight}" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Grid lines -->
|
||||
<line x1="0" y1="${mapHeight / 2}" x2="${mapWidth}" y2="${mapHeight / 2}" stroke="#2a2a4e" stroke-width="0.5" stroke-dasharray="4,4" />
|
||||
<line x1="${mapWidth / 2}" y1="0" x2="${mapWidth / 2}" y2="${mapHeight}" stroke="#2a2a4e" stroke-width="0.5" stroke-dasharray="4,4" />
|
||||
<line x1="0" y1="${mapHeight / 4}" x2="${mapWidth}" y2="${mapHeight / 4}" stroke="#1e1e3e" stroke-width="0.3" stroke-dasharray="2,4" />
|
||||
<line x1="0" y1="${mapHeight * 3 / 4}" x2="${mapWidth}" y2="${mapHeight * 3 / 4}" stroke="#1e1e3e" stroke-width="0.3" stroke-dasharray="2,4" />
|
||||
<line x1="${mapWidth / 4}" y1="0" x2="${mapWidth / 4}" y2="${mapHeight}" stroke="#1e1e3e" stroke-width="0.3" stroke-dasharray="2,4" />
|
||||
<line x1="${mapWidth * 3 / 4}" y1="0" x2="${mapWidth * 3 / 4}" y2="${mapHeight}" stroke="#1e1e3e" stroke-width="0.3" stroke-dasharray="2,4" />
|
||||
<div class="map-wrap">
|
||||
<div class="tooltip" id="tooltip"></div>
|
||||
<svg class="map-svg" viewBox="0 0 ${W} ${H}" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<radialGradient id="ocean" cx="50%" cy="40%" r="70%">
|
||||
<stop offset="0%" stop-color="#0f1b33" />
|
||||
<stop offset="100%" stop-color="#060d1a" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
|
||||
<!-- Simplified continent outlines -->
|
||||
<!-- North America -->
|
||||
<path d="M80,60 Q120,55 140,80 L160,90 Q170,110 150,130 L130,150 Q110,160 100,150 L80,120 Q60,90 80,60Z" fill="#2a2a4e" opacity="0.5" />
|
||||
<!-- South America -->
|
||||
<path d="M160,180 Q170,170 175,190 L180,230 Q185,260 170,280 L160,290 Q145,280 150,250 L155,220 Q150,200 160,180Z" fill="#2a2a4e" opacity="0.5" />
|
||||
<!-- Europe -->
|
||||
<path d="M380,65 Q400,55 420,60 L440,70 Q445,85 430,95 L410,100 Q390,95 380,80Z" fill="#2a2a4e" opacity="0.5" />
|
||||
<!-- Africa -->
|
||||
<path d="M390,110 Q410,105 430,115 L440,140 Q445,180 430,220 L415,240 Q400,245 390,230 L385,190 Q380,150 390,110Z" fill="#2a2a4e" opacity="0.5" />
|
||||
<!-- Asia -->
|
||||
<path d="M440,50 Q500,40 560,55 L600,70 Q640,80 660,100 L670,130 Q660,140 640,130 L600,110 Q550,100 500,90 L460,85 Q440,75 440,50Z" fill="#2a2a4e" opacity="0.5" />
|
||||
<!-- Australia -->
|
||||
<path d="M600,220 Q630,210 650,220 L660,240 Q655,260 640,265 L620,260 Q600,250 600,220Z" fill="#2a2a4e" opacity="0.5" />
|
||||
<!-- Japan -->
|
||||
<path d="M665,85 Q670,80 672,90 L670,100 Q665,105 663,95Z" fill="#2a2a4e" opacity="0.5" />
|
||||
<!-- Ocean background -->
|
||||
<rect width="${W}" height="${H}" fill="url(#ocean)" />
|
||||
|
||||
<!-- Graticule (lat/lng grid) -->
|
||||
${this.graticule(W, H)}
|
||||
|
||||
<!-- Simplified continent fills -->
|
||||
${this.continents(W, H)}
|
||||
|
||||
<!-- Connection arcs -->
|
||||
${arcs}
|
||||
|
||||
<!-- Provider pins -->
|
||||
${providerDots}
|
||||
${pins}
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
|
|
@ -146,7 +222,199 @@ class FolkMapViewer extends HTMLElement {
|
|||
<div class="legend-title">Print Providers</div>
|
||||
${legendItems}
|
||||
</div>
|
||||
|
||||
<div class="features">
|
||||
<div class="feat">
|
||||
<div class="feat-icon">📍</div>
|
||||
<div class="feat-label">Live GPS</div>
|
||||
<div class="feat-desc">Real-time location sharing via WebSocket</div>
|
||||
</div>
|
||||
<div class="feat">
|
||||
<div class="feat-icon">🏢</div>
|
||||
<div class="feat-label">Indoor Nav</div>
|
||||
<div class="feat-desc">c3nav integration for CCC events</div>
|
||||
</div>
|
||||
<div class="feat">
|
||||
<div class="feat-icon">📌</div>
|
||||
<div class="feat-label">Waypoints</div>
|
||||
<div class="feat-desc">Drop meeting points and pins</div>
|
||||
</div>
|
||||
<div class="feat">
|
||||
<div class="feat-icon">🔗</div>
|
||||
<div class="feat-label">QR Sharing</div>
|
||||
<div class="feat-desc">Scan to join any room instantly</div>
|
||||
</div>
|
||||
<div class="feat">
|
||||
<div class="feat-icon">📡</div>
|
||||
<div class="feat-label">Ping Friends</div>
|
||||
<div class="feat-desc">Request location with one tap</div>
|
||||
</div>
|
||||
<div class="feat">
|
||||
<div class="feat-icon">🛡</div>
|
||||
<div class="feat-label">Privacy First</div>
|
||||
<div class="feat-desc">Ghost mode, precision levels, zero tracking</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
this.attachDemoListeners();
|
||||
}
|
||||
|
||||
/** Generate SVG graticule lines */
|
||||
private graticule(W: number, H: number): string {
|
||||
const lines: string[] = [];
|
||||
// Latitude lines every 30 degrees
|
||||
for (let lat = -60; lat <= 60; lat += 30) {
|
||||
const y = ((90 - lat) / 180) * H;
|
||||
lines.push(`<line x1="0" y1="${y}" x2="${W}" y2="${y}" stroke="#1a2744" stroke-width="0.5" stroke-dasharray="3,5" />`);
|
||||
}
|
||||
// Longitude lines every 30 degrees
|
||||
for (let lng = -150; lng <= 180; lng += 30) {
|
||||
const x = ((lng + 180) / 360) * W;
|
||||
lines.push(`<line x1="${x}" y1="0" x2="${x}" y2="${H}" stroke="#1a2744" stroke-width="0.5" stroke-dasharray="3,5" />`);
|
||||
}
|
||||
// Equator and Prime Meridian slightly brighter
|
||||
const eq = ((90 - 0) / 180) * H;
|
||||
const pm = ((0 + 180) / 360) * W;
|
||||
lines.push(`<line x1="0" y1="${eq}" x2="${W}" y2="${eq}" stroke="#1e3050" stroke-width="0.7" stroke-dasharray="4,3" />`);
|
||||
lines.push(`<line x1="${pm}" y1="0" x2="${pm}" y2="${H}" stroke="#1e3050" stroke-width="0.7" stroke-dasharray="4,3" />`);
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
/** Simplified continent outlines using equirectangular projection */
|
||||
private continents(W: number, H: number): string {
|
||||
const p = (lat: number, lng: number) => {
|
||||
const x = ((lng + 180) / 360) * W;
|
||||
const y = ((90 - lat) / 180) * H;
|
||||
return `${x.toFixed(1)},${y.toFixed(1)}`;
|
||||
};
|
||||
|
||||
const fill = "#162236";
|
||||
const stroke = "#1e3050";
|
||||
|
||||
// Each continent as a polygon path
|
||||
const continents = [
|
||||
// North America
|
||||
`M${p(50, -130)} L${p(60, -130)} L${p(65, -120)} L${p(70, -100)} L${p(72, -80)}
|
||||
L${p(65, -65)} L${p(50, -55)} L${p(45, -65)} L${p(40, -75)}
|
||||
L${p(30, -82)} L${p(28, -90)} L${p(25, -100)} L${p(20, -105)}
|
||||
L${p(18, -100)} L${p(15, -88)} L${p(10, -84)} L${p(10, -78)}
|
||||
L${p(20, -88)} L${p(25, -80)} L${p(30, -82)} L${p(30, -75)}
|
||||
L${p(40, -75)} L${p(48, -90)} L${p(48, -95)}
|
||||
L${p(50, -120)} Z`,
|
||||
|
||||
// South America
|
||||
`M${p(12, -75)} L${p(10, -68)} L${p(5, -60)} L${p(0, -50)}
|
||||
L${p(-5, -45)} L${p(-10, -38)} L${p(-15, -40)} L${p(-20, -42)}
|
||||
L${p(-25, -48)} L${p(-30, -50)} L${p(-35, -56)} L${p(-40, -62)}
|
||||
L${p(-45, -66)} L${p(-50, -70)} L${p(-55, -68)}
|
||||
L${p(-50, -74)} L${p(-42, -72)} L${p(-35, -70)}
|
||||
L${p(-25, -70)} L${p(-20, -70)} L${p(-15, -76)}
|
||||
L${p(-5, -78)} L${p(0, -80)} L${p(5, -78)} L${p(10, -76)} Z`,
|
||||
|
||||
// Europe
|
||||
`M${p(40, -8)} L${p(42, 0)} L${p(44, 5)} L${p(46, 8)}
|
||||
L${p(48, 10)} L${p(50, 5)} L${p(52, 8)} L${p(55, 10)}
|
||||
L${p(58, 12)} L${p(60, 10)} L${p(62, 18)} L${p(65, 20)}
|
||||
L${p(70, 25)} L${p(68, 30)} L${p(62, 32)} L${p(58, 30)}
|
||||
L${p(55, 28)} L${p(50, 30)} L${p(48, 28)} L${p(45, 25)}
|
||||
L${p(42, 28)} L${p(38, 25)} L${p(36, 22)} L${p(38, 10)}
|
||||
L${p(38, 0)} Z`,
|
||||
|
||||
// Africa
|
||||
`M${p(35, -5)} L${p(37, 10)} L${p(35, 20)} L${p(32, 32)}
|
||||
L${p(28, 33)} L${p(15, 42)} L${p(10, 42)} L${p(5, 38)}
|
||||
L${p(0, 40)} L${p(-5, 38)} L${p(-10, 34)} L${p(-15, 30)}
|
||||
L${p(-20, 28)} L${p(-25, 28)} L${p(-30, 28)} L${p(-34, 25)}
|
||||
L${p(-34, 20)} L${p(-30, 15)} L${p(-20, 12)} L${p(-15, 12)}
|
||||
L${p(-10, 15)} L${p(-5, 10)} L${p(0, 8)} L${p(5, 2)}
|
||||
L${p(10, 0)} L${p(15, -5)} L${p(20, -10)} L${p(25, -15)}
|
||||
L${p(30, -10)} L${p(35, -5)} Z`,
|
||||
|
||||
// Asia (mainland)
|
||||
`M${p(70, 30)} L${p(72, 50)} L${p(72, 80)} L${p(70, 110)}
|
||||
L${p(68, 140)} L${p(65, 165)} L${p(60, 165)} L${p(55, 140)}
|
||||
L${p(50, 130)} L${p(45, 135)} L${p(40, 130)} L${p(35, 120)}
|
||||
L${p(30, 120)} L${p(25, 105)} L${p(22, 100)} L${p(20, 98)}
|
||||
L${p(15, 100)} L${p(10, 105)} L${p(5, 100)} L${p(0, 104)}
|
||||
L${p(-5, 105)} L${p(-8, 112)} L${p(-6, 118)}
|
||||
L${p(2, 110)} L${p(8, 108)} L${p(12, 110)}
|
||||
L${p(20, 108)} L${p(22, 114)} L${p(30, 110)}
|
||||
L${p(28, 88)} L${p(25, 68)} L${p(30, 50)}
|
||||
L${p(35, 45)} L${p(40, 40)} L${p(42, 32)}
|
||||
L${p(48, 30)} L${p(55, 30)} L${p(62, 32)}
|
||||
L${p(68, 30)} Z`,
|
||||
|
||||
// Australia
|
||||
`M${p(-12, 132)} L${p(-15, 140)} L${p(-20, 148)} L${p(-25, 150)}
|
||||
L${p(-30, 148)} L${p(-35, 140)} L${p(-38, 146)} L${p(-35, 150)}
|
||||
L${p(-32, 152)} L${p(-28, 153)} L${p(-25, 152)}
|
||||
L${p(-20, 150)} L${p(-15, 145)} L${p(-12, 138)}
|
||||
L${p(-14, 130)} L${p(-18, 122)} L${p(-22, 115)}
|
||||
L${p(-28, 114)} L${p(-32, 116)} L${p(-35, 118)}
|
||||
L${p(-34, 125)} L${p(-30, 130)} L${p(-25, 132)}
|
||||
L${p(-20, 130)} L${p(-16, 128)} L${p(-12, 132)} Z`,
|
||||
|
||||
// Japan (simplified)
|
||||
`M${p(35, 133)} L${p(38, 136)} L${p(40, 140)} L${p(42, 142)}
|
||||
L${p(44, 144)} L${p(45, 142)} L${p(43, 140)} L${p(40, 137)}
|
||||
L${p(37, 135)} L${p(35, 133)} Z`,
|
||||
|
||||
// UK/Ireland
|
||||
`M${p(51, -5)} L${p(53, 0)} L${p(55, -2)} L${p(57, -5)}
|
||||
L${p(58, -3)} L${p(56, 0)} L${p(54, 1)} L${p(52, 0)}
|
||||
L${p(50, -3)} L${p(51, -5)} Z`,
|
||||
|
||||
// Greenland
|
||||
`M${p(62, -50)} L${p(68, -52)} L${p(75, -45)} L${p(78, -35)}
|
||||
L${p(76, -20)} L${p(70, -22)} L${p(65, -35)} L${p(62, -45)} Z`,
|
||||
|
||||
// Indonesia (simplified)
|
||||
`M${p(-2, 100)} L${p(-4, 108)} L${p(-6, 112)} L${p(-8, 115)}
|
||||
L${p(-7, 118)} L${p(-5, 116)} L${p(-3, 112)} L${p(-1, 106)} L${p(-2, 100)} Z`,
|
||||
|
||||
// New Zealand
|
||||
`M${p(-36, 174)} L${p(-38, 176)} L${p(-42, 174)} L${p(-46, 168)}
|
||||
L${p(-44, 168)} L${p(-42, 172)} L${p(-38, 174)} L${p(-36, 174)} Z`,
|
||||
];
|
||||
|
||||
return continents.map((d) =>
|
||||
`<path d="${d.replace(/\s+/g, " ").trim()}" fill="${fill}" stroke="${stroke}" stroke-width="0.5" opacity="0.75" />`
|
||||
).join("\n");
|
||||
}
|
||||
|
||||
private attachDemoListeners() {
|
||||
const tooltip = this.shadow.getElementById("tooltip");
|
||||
if (!tooltip) return;
|
||||
|
||||
this.shadow.querySelectorAll(".pin-group").forEach((el) => {
|
||||
const idx = parseInt((el as HTMLElement).dataset.idx || "0", 10);
|
||||
const p = this.providers[idx];
|
||||
|
||||
el.addEventListener("mouseenter", (e) => {
|
||||
const rect = this.shadow.querySelector(".map-wrap")?.getBoundingClientRect();
|
||||
const me = e as MouseEvent;
|
||||
if (rect) {
|
||||
tooltip.innerHTML = `<strong>${this.esc(p.name)}</strong><span class="city">${this.esc(p.city)}</span><span class="coords">${p.lat.toFixed(2)}, ${p.lng.toFixed(2)}</span>`;
|
||||
tooltip.style.left = `${me.clientX - rect.left + 12}px`;
|
||||
tooltip.style.top = `${me.clientY - rect.top - 10}px`;
|
||||
tooltip.classList.add("visible");
|
||||
}
|
||||
});
|
||||
|
||||
el.addEventListener("mousemove", (e) => {
|
||||
const rect = this.shadow.querySelector(".map-wrap")?.getBoundingClientRect();
|
||||
const me = e as MouseEvent;
|
||||
if (rect) {
|
||||
tooltip.style.left = `${me.clientX - rect.left + 12}px`;
|
||||
tooltip.style.top = `${me.clientY - rect.top - 10}px`;
|
||||
}
|
||||
});
|
||||
|
||||
el.addEventListener("mouseleave", () => {
|
||||
tooltip.classList.remove("visible");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private getApiBase(): string {
|
||||
|
|
@ -288,7 +556,7 @@ class FolkMapViewer extends HTMLElement {
|
|||
|
||||
${this.rooms.length > 0 ? this.rooms.map((r) => `
|
||||
<div class="room-card" data-room="${r}">
|
||||
<span class="room-icon">🗺</span>
|
||||
<span class="room-icon">🗺</span>
|
||||
<span class="room-name">${this.esc(r)}</span>
|
||||
</div>
|
||||
`).join("") : ""}
|
||||
|
|
@ -304,14 +572,14 @@ class FolkMapViewer extends HTMLElement {
|
|||
const shareUrl = `${window.location.origin}/${this.space}/maps/${this.room}`;
|
||||
return `
|
||||
<div class="rapp-nav">
|
||||
<button class="rapp-nav__back" data-back="lobby">← Rooms</button>
|
||||
<span class="rapp-nav__title">🗺 ${this.esc(this.room)}</span>
|
||||
<button class="rapp-nav__back" data-back="lobby">← Rooms</button>
|
||||
<span class="rapp-nav__title">🗺 ${this.esc(this.room)}</span>
|
||||
<span class="status-dot ${this.syncStatus === "connected" ? "status-connected" : "status-disconnected"}"></span>
|
||||
</div>
|
||||
|
||||
<div class="map-container">
|
||||
<div class="map-placeholder">
|
||||
<p style="font-size:48px">🌍</p>
|
||||
<p style="font-size:48px">🌎</p>
|
||||
<p style="font-size:16px">Map Room: <strong>${this.esc(this.room)}</strong></p>
|
||||
<p>Connect the MapLibre GL library to display the interactive map.</p>
|
||||
<p style="font-size:12px;color:#555">WebSocket sync: ${this.syncStatus}</p>
|
||||
|
|
|
|||
|
|
@ -10,6 +10,16 @@ interface GraphNode {
|
|||
name: string;
|
||||
type: "person" | "company" | "opportunity";
|
||||
workspace: string;
|
||||
role?: string;
|
||||
location?: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface GraphEdge {
|
||||
source: string;
|
||||
target: string;
|
||||
type: "work_at" | "point_of_contact" | "collaborates";
|
||||
label?: string;
|
||||
}
|
||||
|
||||
class FolkGraphViewer extends HTMLElement {
|
||||
|
|
@ -18,6 +28,7 @@ class FolkGraphViewer extends HTMLElement {
|
|||
private workspaces: any[] = [];
|
||||
private info: any = null;
|
||||
private nodes: GraphNode[] = [];
|
||||
private edges: GraphEdge[] = [];
|
||||
private filter: "all" | "person" | "company" | "opportunity" = "all";
|
||||
private searchQuery = "";
|
||||
private error = "";
|
||||
|
|
@ -35,21 +46,59 @@ class FolkGraphViewer extends HTMLElement {
|
|||
}
|
||||
|
||||
private loadDemoData() {
|
||||
this.info = { name: "rSpace Community", member_count: 42, company_count: 8, opportunity_count: 5 };
|
||||
this.info = { name: "rSpace Community", member_count: 10, company_count: 3, opportunity_count: 0 };
|
||||
|
||||
this.workspaces = [
|
||||
{ name: "Core Contributors", slug: "core-contributors", nodeCount: 12, edgeCount: 3 },
|
||||
{ name: "Extended Network", slug: "extended-network", nodeCount: 30, edgeCount: 5 },
|
||||
{ name: "Commons DAO", slug: "commons-dao", nodeCount: 5, edgeCount: 4 },
|
||||
{ name: "Mycelial Lab", slug: "mycelial-lab", nodeCount: 5, edgeCount: 4 },
|
||||
{ name: "Regenerative Fund", slug: "regenerative-fund", nodeCount: 5, edgeCount: 4 },
|
||||
];
|
||||
|
||||
// Organizations
|
||||
this.nodes = [
|
||||
{ id: "demo-p1", name: "Alice Chen", type: "person", workspace: "Core Contributors" },
|
||||
{ id: "demo-p2", name: "Bob Marley", type: "person", workspace: "Core Contributors" },
|
||||
{ id: "demo-p3", name: "Carol Danvers", type: "person", workspace: "Extended Network" },
|
||||
{ id: "demo-p4", name: "Diana Prince", type: "person", workspace: "Extended Network" },
|
||||
{ id: "demo-c1", name: "Radiant Hall Press", type: "company", workspace: "Core Contributors" },
|
||||
{ id: "demo-c2", name: "Tiny Splendor", type: "company", workspace: "Extended Network" },
|
||||
{ id: "demo-c3", name: "Commons Hub", type: "company", workspace: "Core Contributors" },
|
||||
{ id: "org-1", name: "Commons DAO", type: "company", workspace: "Commons DAO", description: "Decentralized governance cooperative" },
|
||||
{ id: "org-2", name: "Mycelial Lab", type: "company", workspace: "Mycelial Lab", description: "Protocol research collective" },
|
||||
{ id: "org-3", name: "Regenerative Fund", type: "company", workspace: "Regenerative Fund", description: "Impact funding vehicle" },
|
||||
|
||||
// People — Commons DAO
|
||||
{ id: "p-1", name: "Alice Chen", type: "person", workspace: "Commons DAO", role: "Lead Engineer", location: "Vancouver" },
|
||||
{ id: "p-2", name: "Bob Nakamura", type: "person", workspace: "Commons DAO", role: "Community Lead", location: "Tokyo" },
|
||||
{ id: "p-3", name: "Carol Santos", type: "person", workspace: "Commons DAO", role: "Treasury Steward", location: "S\u00e3o Paulo" },
|
||||
{ id: "p-4", name: "Dave Okafor", type: "person", workspace: "Commons DAO", role: "Governance Facilitator", location: "Lagos" },
|
||||
|
||||
// People — Mycelial Lab
|
||||
{ id: "p-5", name: "Eva Larsson", type: "person", workspace: "Mycelial Lab", role: "Ops Coordinator", location: "Stockholm" },
|
||||
{ id: "p-6", name: "Frank M\u00fcller", type: "person", workspace: "Mycelial Lab", role: "Protocol Designer", location: "Berlin" },
|
||||
{ id: "p-7", name: "Grace Kim", type: "person", workspace: "Mycelial Lab", role: "Strategy Lead", location: "Seoul" },
|
||||
|
||||
// People — Regenerative Fund
|
||||
{ id: "p-8", name: "Hiro Tanaka", type: "person", workspace: "Regenerative Fund", role: "Research Lead", location: "Osaka" },
|
||||
{ id: "p-9", name: "Iris Patel", type: "person", workspace: "Regenerative Fund", role: "Developer Relations", location: "Mumbai" },
|
||||
{ id: "p-10", name: "James Wright", type: "person", workspace: "Regenerative Fund", role: "Security Auditor", location: "London" },
|
||||
];
|
||||
|
||||
// Edges: work_at links + cross-org point_of_contact
|
||||
this.edges = [
|
||||
// Work_at — Commons DAO
|
||||
{ source: "p-1", target: "org-1", type: "work_at" },
|
||||
{ source: "p-2", target: "org-1", type: "work_at" },
|
||||
{ source: "p-3", target: "org-1", type: "work_at" },
|
||||
{ source: "p-4", target: "org-1", type: "work_at" },
|
||||
|
||||
// Work_at — Mycelial Lab
|
||||
{ source: "p-5", target: "org-2", type: "work_at" },
|
||||
{ source: "p-6", target: "org-2", type: "work_at" },
|
||||
{ source: "p-7", target: "org-2", type: "work_at" },
|
||||
|
||||
// Work_at — Regenerative Fund
|
||||
{ source: "p-8", target: "org-3", type: "work_at" },
|
||||
{ source: "p-9", target: "org-3", type: "work_at" },
|
||||
{ source: "p-10", target: "org-3", type: "work_at" },
|
||||
|
||||
// Cross-org point_of_contact edges
|
||||
{ source: "p-1", target: "p-6", type: "point_of_contact", label: "Alice \u2194 Frank" },
|
||||
{ source: "p-2", target: "p-3", type: "point_of_contact", label: "Bob \u2194 Carol" },
|
||||
{ source: "p-4", target: "p-7", type: "point_of_contact", label: "Dave \u2194 Grace" },
|
||||
];
|
||||
|
||||
this.render();
|
||||
|
|
@ -83,7 +132,10 @@ class FolkGraphViewer extends HTMLElement {
|
|||
const q = this.searchQuery.toLowerCase();
|
||||
filtered = filtered.filter(n =>
|
||||
n.name.toLowerCase().includes(q) ||
|
||||
n.workspace.toLowerCase().includes(q)
|
||||
n.workspace.toLowerCase().includes(q) ||
|
||||
(n.role && n.role.toLowerCase().includes(q)) ||
|
||||
(n.location && n.location.toLowerCase().includes(q)) ||
|
||||
(n.description && n.description.toLowerCase().includes(q))
|
||||
);
|
||||
}
|
||||
return filtered;
|
||||
|
|
@ -105,39 +157,121 @@ class FolkGraphViewer extends HTMLElement {
|
|||
`;
|
||||
}
|
||||
|
||||
// Render demo nodes as positioned circles inside the graph canvas
|
||||
const cx = 250;
|
||||
const cy = 250;
|
||||
const r = 180;
|
||||
const nodesSvg = filtered.map((node, i) => {
|
||||
const angle = (2 * Math.PI * i) / filtered.length - Math.PI / 2;
|
||||
const x = cx + r * Math.cos(angle);
|
||||
const y = cy + r * Math.sin(angle);
|
||||
const color = node.type === "person" ? "#3b82f6" : node.type === "company" ? "#22c55e" : "#f59e0b";
|
||||
const radius = node.type === "company" ? 18 : 14;
|
||||
return `
|
||||
<circle cx="${x}" cy="${y}" r="${radius}" fill="${color}" opacity="0.8"/>
|
||||
<text x="${x}" y="${y + radius + 14}" fill="#aaa" font-size="10" text-anchor="middle">${this.esc(node.name)}</text>
|
||||
`;
|
||||
}).join("");
|
||||
const W = 700;
|
||||
const H = 500;
|
||||
const filteredIds = new Set(filtered.map(n => n.id));
|
||||
|
||||
// Draw edges between nodes in the same workspace
|
||||
const edgesSvg: string[] = [];
|
||||
for (let i = 0; i < filtered.length; i++) {
|
||||
for (let j = i + 1; j < filtered.length; j++) {
|
||||
if (filtered[i].workspace === filtered[j].workspace) {
|
||||
const a1 = (2 * Math.PI * i) / filtered.length - Math.PI / 2;
|
||||
const a2 = (2 * Math.PI * j) / filtered.length - Math.PI / 2;
|
||||
const x1 = cx + r * Math.cos(a1);
|
||||
const y1 = cy + r * Math.sin(a1);
|
||||
const x2 = cx + r * Math.cos(a2);
|
||||
const y2 = cy + r * Math.sin(a2);
|
||||
edgesSvg.push(`<line x1="${x1}" y1="${y1}" x2="${x2}" y2="${y2}" stroke="#333" stroke-width="1" opacity="0.4"/>`);
|
||||
// Cluster layout: position org nodes as hubs, people orbit around their org
|
||||
// Three orgs arranged in a triangle
|
||||
const orgCenters: Record<string, { x: number; y: number }> = {
|
||||
"org-1": { x: W / 2, y: 120 }, // Commons DAO — top center
|
||||
"org-2": { x: 160, y: 380 }, // Mycelial Lab — bottom left
|
||||
"org-3": { x: W - 160, y: 380 }, // Regenerative Fund — bottom right
|
||||
};
|
||||
|
||||
// Build a position map for all nodes
|
||||
const positions: Record<string, { x: number; y: number }> = {};
|
||||
|
||||
// Position org nodes at their centers
|
||||
for (const [id, pos] of Object.entries(orgCenters)) {
|
||||
positions[id] = pos;
|
||||
}
|
||||
|
||||
// Group people by their workspace (org)
|
||||
const orgNameToId: Record<string, string> = {
|
||||
"Commons DAO": "org-1",
|
||||
"Mycelial Lab": "org-2",
|
||||
"Regenerative Fund": "org-3",
|
||||
};
|
||||
|
||||
const peopleByOrg: Record<string, GraphNode[]> = {};
|
||||
for (const node of this.nodes) {
|
||||
if (node.type === "person") {
|
||||
const orgId = orgNameToId[node.workspace];
|
||||
if (orgId) {
|
||||
if (!peopleByOrg[orgId]) peopleByOrg[orgId] = [];
|
||||
peopleByOrg[orgId].push(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return `<svg viewBox="0 0 500 500" width="100%" height="100%" style="max-height:500px">${edgesSvg.join("")}${nodesSvg}</svg>`;
|
||||
// Position people in a semicircle around their org
|
||||
const orbitRadius = 110;
|
||||
for (const [orgId, people] of Object.entries(peopleByOrg)) {
|
||||
const center = orgCenters[orgId];
|
||||
if (!center) continue;
|
||||
const count = people.length;
|
||||
// Spread people in an arc facing outward from the graph center
|
||||
const graphCx = W / 2;
|
||||
const graphCy = (120 + 380) / 2; // vertical center of the triangle
|
||||
const baseAngle = Math.atan2(center.y - graphCy, center.x - graphCx);
|
||||
const spread = Math.PI * 0.8; // 144 degrees arc
|
||||
for (let i = 0; i < count; i++) {
|
||||
const angle = baseAngle - spread / 2 + (spread * i) / Math.max(count - 1, 1);
|
||||
positions[people[i].id] = {
|
||||
x: center.x + orbitRadius * Math.cos(angle),
|
||||
y: center.y + orbitRadius * Math.sin(angle),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Org background cluster circles
|
||||
const orgColors: Record<string, string> = {
|
||||
"org-1": "#6366f1", // indigo for Commons DAO
|
||||
"org-2": "#22c55e", // green for Mycelial Lab
|
||||
"org-3": "#f59e0b", // amber for Regenerative Fund
|
||||
};
|
||||
const clustersSvg = Object.entries(orgCenters).map(([orgId, pos]) => {
|
||||
const color = orgColors[orgId] || "#333";
|
||||
return `<circle cx="${pos.x}" cy="${pos.y}" r="${orbitRadius + 30}" fill="${color}" opacity="0.04" stroke="${color}" stroke-width="1" stroke-opacity="0.15" stroke-dasharray="4 4"/>`;
|
||||
}).join("");
|
||||
|
||||
// Render edges
|
||||
const edgesSvg: string[] = [];
|
||||
for (const edge of this.edges) {
|
||||
const sp = positions[edge.source];
|
||||
const tp = positions[edge.target];
|
||||
if (!sp || !tp) continue;
|
||||
if (!filteredIds.has(edge.source) || !filteredIds.has(edge.target)) continue;
|
||||
|
||||
if (edge.type === "work_at") {
|
||||
edgesSvg.push(`<line x1="${sp.x}" y1="${sp.y}" x2="${tp.x}" y2="${tp.y}" stroke="#555" stroke-width="1" opacity="0.35"/>`);
|
||||
} else if (edge.type === "point_of_contact") {
|
||||
// Cross-org edges: dashed, brighter
|
||||
const mx = (sp.x + tp.x) / 2;
|
||||
const my = (sp.y + tp.y) / 2;
|
||||
edgesSvg.push(`<line x1="${sp.x}" y1="${sp.y}" x2="${tp.x}" y2="${tp.y}" stroke="#c084fc" stroke-width="1.5" stroke-dasharray="6 3" opacity="0.6"/>`);
|
||||
if (edge.label) {
|
||||
edgesSvg.push(`<text x="${mx}" y="${my - 6}" fill="#c084fc" font-size="8" text-anchor="middle" opacity="0.7">${this.esc(edge.label)}</text>`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render nodes
|
||||
const nodesSvg = filtered.map(node => {
|
||||
const pos = positions[node.id];
|
||||
if (!pos) return "";
|
||||
const isOrg = node.type === "company";
|
||||
const color = isOrg ? (orgColors[node.id] || "#22c55e") : "#3b82f6";
|
||||
const radius = isOrg ? 22 : 12;
|
||||
|
||||
let label = this.esc(node.name);
|
||||
let sublabel = "";
|
||||
if (isOrg && node.description) {
|
||||
sublabel = `<text x="${pos.x}" y="${pos.y + radius + 26}" fill="#888" font-size="8" text-anchor="middle">${this.esc(node.description)}</text>`;
|
||||
} else if (!isOrg && node.role) {
|
||||
sublabel = `<text x="${pos.x}" y="${pos.y + radius + 24}" fill="#666" font-size="8" text-anchor="middle">${this.esc(node.role)}${node.location ? " \u00b7 " + this.esc(node.location) : ""}</text>`;
|
||||
}
|
||||
|
||||
return `
|
||||
<circle cx="${pos.x}" cy="${pos.y}" r="${radius}" fill="${color}" opacity="${isOrg ? 0.9 : 0.75}" stroke="${isOrg ? color : "none"}" stroke-width="${isOrg ? 2 : 0}" stroke-opacity="0.3"/>
|
||||
${isOrg ? `<text x="${pos.x}" y="${pos.y + 4}" fill="#fff" font-size="9" font-weight="600" text-anchor="middle">${label.length > 14 ? label.slice(0, 12) + "\u2026" : label}</text>` : ""}
|
||||
<text x="${pos.x}" y="${pos.y + radius + 13}" fill="#ccc" font-size="${isOrg ? 11 : 10}" font-weight="${isOrg ? 600 : 400}" text-anchor="middle">${label}</text>
|
||||
${sublabel}
|
||||
`;
|
||||
}).join("");
|
||||
|
||||
return `<svg viewBox="0 0 ${W} ${H}" width="100%" height="100%" style="max-height:500px">${clustersSvg}${edgesSvg.join("")}${nodesSvg}</svg>`;
|
||||
}
|
||||
|
||||
private render() {
|
||||
|
|
@ -183,6 +317,7 @@ class FolkGraphViewer extends HTMLElement {
|
|||
.legend { display: flex; gap: 16px; margin-top: 12px; }
|
||||
.legend-item { display: flex; align-items: center; gap: 6px; font-size: 12px; color: #888; }
|
||||
.legend-dot { width: 10px; height: 10px; border-radius: 50%; }
|
||||
.legend-line { display: inline-block; }
|
||||
.dot-person { background: #3b82f6; }
|
||||
.dot-company { background: #22c55e; }
|
||||
.dot-opportunity { background: #f59e0b; }
|
||||
|
|
@ -211,17 +346,18 @@ class FolkGraphViewer extends HTMLElement {
|
|||
|
||||
${this.info ? `
|
||||
<div class="stats">
|
||||
<div class="stat"><div class="stat-value">${this.info.member_count || 0}</div><div class="stat-label">Members</div></div>
|
||||
<div class="stat"><div class="stat-value">${this.info.company_count || 0}</div><div class="stat-label">Companies</div></div>
|
||||
<div class="stat"><div class="stat-value">${this.info.opportunity_count || 0}</div><div class="stat-label">Opportunities</div></div>
|
||||
<div class="stat"><div class="stat-value">${this.info.member_count || 0}</div><div class="stat-label">People</div></div>
|
||||
<div class="stat"><div class="stat-value">${this.info.company_count || 0}</div><div class="stat-label">Organizations</div></div>
|
||||
<div class="stat"><div class="stat-value">${this.edges?.filter((e: GraphEdge) => e.type === "point_of_contact").length || 0}</div><div class="stat-label">Cross-org Links</div></div>
|
||||
</div>
|
||||
` : ""}
|
||||
|
||||
<div class="toolbar">
|
||||
<input class="search-input" type="text" placeholder="Search nodes..." id="search-input" value="${this.esc(this.searchQuery)}">
|
||||
${(["all", "person", "company", "opportunity"] as const).map(f =>
|
||||
`<button class="filter-btn ${this.filter === f ? "active" : ""}" data-filter="${f}">${f === "all" ? "All" : f.charAt(0).toUpperCase() + f.slice(1)}s</button>`
|
||||
).join("")}
|
||||
${(["all", "person", "company", "opportunity"] as const).map(f => {
|
||||
const labels: Record<string, string> = { all: "All", person: "People", company: "Organizations", opportunity: "Opportunities" };
|
||||
return `<button class="filter-btn ${this.filter === f ? "active" : ""}" data-filter="${f}">${labels[f]}</button>`;
|
||||
}).join("")}
|
||||
</div>
|
||||
|
||||
<div class="graph-canvas">
|
||||
|
|
@ -237,12 +373,13 @@ class FolkGraphViewer extends HTMLElement {
|
|||
|
||||
<div class="legend">
|
||||
<div class="legend-item"><span class="legend-dot dot-person"></span> People</div>
|
||||
<div class="legend-item"><span class="legend-dot dot-company"></span> Companies</div>
|
||||
<div class="legend-item"><span class="legend-dot dot-opportunity"></span> Opportunities</div>
|
||||
<div class="legend-item"><span class="legend-dot dot-company"></span> Organizations</div>
|
||||
<div class="legend-item"><svg width="20" height="10"><line x1="0" y1="5" x2="20" y2="5" stroke="#555" stroke-width="2"/></svg> Works at</div>
|
||||
<div class="legend-item"><svg width="20" height="10"><line x1="0" y1="5" x2="20" y2="5" stroke="#c084fc" stroke-width="2" stroke-dasharray="4 2"/></svg> Point of contact</div>
|
||||
</div>
|
||||
|
||||
${this.workspaces.length > 0 ? `
|
||||
<div style="margin-top:20px;font-size:14px;font-weight:600;color:#aaa">Workspaces</div>
|
||||
<div style="margin-top:20px;font-size:14px;font-weight:600;color:#aaa">${this.space === "demo" ? "Organizations" : "Workspaces"}</div>
|
||||
<div class="workspace-list">
|
||||
${this.workspaces.map(ws => `
|
||||
<div class="ws-card">
|
||||
|
|
|
|||
|
|
@ -86,121 +86,479 @@ class FolkNotesApp extends HTMLElement {
|
|||
const hour = 3600000;
|
||||
const day = 86400000;
|
||||
|
||||
const projectNotes: Note[] = [
|
||||
const tripPlanningNotes: Note[] = [
|
||||
{
|
||||
id: "demo-note-1", title: "Cosmolocal Marketplace",
|
||||
content: "Build a decentralized marketplace connecting local makers with global designers. Use rCart for orders, rFunds for revenue splits.",
|
||||
content_plain: "Build a decentralized marketplace connecting local makers with global designers. Use rCart for orders, rFunds for revenue splits.",
|
||||
type: "NOTE", tags: ["cosmolocal", "marketplace"], is_pinned: true,
|
||||
created_at: new Date(now - 2 * day).toISOString(), updated_at: new Date(now - hour).toISOString(),
|
||||
id: "demo-note-1", title: "Pre-trip Preparation",
|
||||
content: `## Pre-trip Preparation
|
||||
|
||||
### Flights & Transfers
|
||||
- **Jul 6**: Fly Geneva, shuttle to Chamonix (~1.5h)
|
||||
- **Jul 14**: Train Zermatt to Dolomites (Bernina Express, ~6h scenic route)
|
||||
- **Jul 20**: Fly home from Innsbruck
|
||||
|
||||
> Book the Aiguille du Midi cable car tickets at least 2 weeks in advance -- they sell out fast in July.
|
||||
|
||||
### Travel Documents
|
||||
1. Passports (valid 6+ months)
|
||||
2. EU health insurance cards (EHIC)
|
||||
3. Travel insurance policy (ref: WA-2026-7891)
|
||||
4. Hut reservation confirmations (printed copies)
|
||||
5. Drone registration for Italy
|
||||
|
||||
### Budget Overview
|
||||
Total budget: **EUR 4,000** across 4 travelers.
|
||||
|
||||
\`\`\`
|
||||
Transport: EUR 800 (20%)
|
||||
Accommodation: EUR 1200 (30%)
|
||||
Activities: EUR 1000 (25%)
|
||||
Food: EUR 600 (15%)
|
||||
Gear: EUR 400 (10%)
|
||||
\`\`\`
|
||||
|
||||
*Maya is tracking expenses in rFunds. Current spend: EUR 1,203.*`,
|
||||
content_plain: "Pre-trip preparation checklist covering flights, transfers, travel documents, and budget overview for the Alpine Explorer 2026 trip.",
|
||||
type: "NOTE", tags: ["planning", "budget", "transport"], is_pinned: true,
|
||||
created_at: new Date(now - 14 * day).toISOString(), updated_at: new Date(now - hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-2", title: "Community Garden App",
|
||||
content: "Track plots, plantings, and harvests. Share surplus through a local exchange network.",
|
||||
content_plain: "Track plots, plantings, and harvests. Share surplus through a local exchange network.",
|
||||
type: "NOTE", tags: ["community", "local"], is_pinned: false,
|
||||
created_at: new Date(now - 3 * day).toISOString(), updated_at: new Date(now - 2 * hour).toISOString(),
|
||||
id: "demo-note-2", title: "Accommodation Research",
|
||||
content: `## Accommodation Research
|
||||
|
||||
### Chamonix (Jul 6-10)
|
||||
- **Refuge du Lac Blanc** -- Jul 7, 4 beds, conf #LB2026-234
|
||||
- Airbnb in town for other nights (~EUR 120/night for 4 pax)
|
||||
- Consider Hotel Le Morgane if Airbnb falls through
|
||||
|
||||
### Zermatt (Jul 10-14)
|
||||
- **Hornlihutte** (Matterhorn base) -- Waitlisted for Jul 12
|
||||
- Main accommodation: Apartment near Bahnhofstrasse
|
||||
- Car-free village, arrive by Glacier Express
|
||||
|
||||
> Zermatt is expensive. Budget EUR 80-100pp/night minimum. The apartment saves us about 40% vs hotels.
|
||||
|
||||
### Dolomites (Jul 14-20)
|
||||
- **Rifugio Locatelli** -- Jul 15, 4 beds, conf #TRE2026-089
|
||||
- Val Gardena base: Ortisei area
|
||||
- Look for agriturismo options for authentic experience
|
||||
|
||||
### Booking Status
|
||||
| Location | Status | Cost/Night | Notes |
|
||||
|----------|--------|-----------|-------|
|
||||
| Lac Blanc | Confirmed | EUR 65pp | Half-board included |
|
||||
| Chamonix Airbnb | Confirmed | EUR 120 total | 2-bed apartment |
|
||||
| Zermatt apartment | Confirmed | EUR 180 total | Near station |
|
||||
| Hornlihutte | Waitlisted | EUR 85pp | Fingers crossed |
|
||||
| Locatelli | Confirmed | EUR 55pp | Half-board |
|
||||
| Val Gardena | Searching | ~EUR 100 total | Need 4+ beds |`,
|
||||
content_plain: "Accommodation research for all three destinations: Chamonix, Zermatt, and Dolomites. Includes confirmed bookings, waitlists, and budget estimates.",
|
||||
type: "NOTE", tags: ["accommodation", "budget"], is_pinned: false,
|
||||
created_at: new Date(now - 12 * day).toISOString(), updated_at: new Date(now - 3 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-3", title: "Mesh Network Map",
|
||||
content: "Visualize community mesh networks using rMaps. Show signal strength, coverage areas.",
|
||||
content_plain: "Visualize community mesh networks using rMaps. Show signal strength, coverage areas.",
|
||||
type: "NOTE", tags: ["mesh", "infrastructure"], is_pinned: false,
|
||||
created_at: new Date(now - 5 * day).toISOString(), updated_at: new Date(now - 3 * hour).toISOString(),
|
||||
id: "demo-note-3", title: "Activity Planning",
|
||||
content: `## Activity Planning
|
||||
|
||||
### Hiking Routes
|
||||
- **Lac Blanc** (Jul 7) -- Acclimatization hike, ~6h round trip, 1000m elevation gain. Stunning Mont Blanc reflection at sunrise.
|
||||
- **Gornergrat Sunrise** (Jul 11) -- Take the first train up at 7am, hike down. Matterhorn panorama.
|
||||
- **Matterhorn Base Camp** (Jul 12) -- Full day trek to Hornlihutte. 1500m gain. Only if weather permits.
|
||||
- **Tre Cime di Lavaredo** (Jul 15) -- Classic loop, ~4h. Stay at Rifugio Locatelli for golden hour photos.
|
||||
- **Seceda Ridgeline** (Jul 17) -- Gondola up, ridge walk, hike down to Ortisei. Best drone location.
|
||||
|
||||
### Adventure Activities
|
||||
1. **Via Ferrata at Aiguille du Midi** (Jul 8) -- Rent harness + lanyard + helmet in Chamonix, ~EUR 25/day
|
||||
2. **Paragliding over Zermatt** (Jul 13) -- Tandem flights ~EUR 180pp. Book with Paragliding Zermatt (best reviews)
|
||||
3. **Kayaking at Lago di Braies** (Jul 16) -- Turquoise glacial lake, kayak rental ~EUR 15/hour
|
||||
|
||||
### Rest Days
|
||||
- Jul 9: Explore Chamonix town, gear shopping
|
||||
- Jul 19: Free day before flying home, packing
|
||||
|
||||
> Omar suggested we vote on the Day 5 alternative activity -- Via Ferrata is winning 7-3 over kayaking on Lac d'Annecy.
|
||||
|
||||
### Difficulty Ratings
|
||||
\`\`\`
|
||||
Lac Blanc: Moderate (T2)
|
||||
Gornergrat: Easy (T1)
|
||||
Matterhorn Base: Difficult (T3)
|
||||
Tre Cime Loop: Moderate (T2)
|
||||
Seceda Ridge: Easy (T1)
|
||||
Via Ferrata: Difficult (K3)
|
||||
\`\`\``,
|
||||
content_plain: "Detailed activity planning including hiking routes with difficulty ratings, adventure activities with costs, and rest day plans.",
|
||||
type: "NOTE", tags: ["hiking", "activities", "adventure"], is_pinned: false,
|
||||
created_at: new Date(now - 10 * day).toISOString(), updated_at: new Date(now - 5 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-4", title: "Open Hardware Library",
|
||||
content: "Catalog open-source hardware designs. Link to local fabrication providers.",
|
||||
content_plain: "Catalog open-source hardware designs. Link to local fabrication providers.",
|
||||
type: "NOTE", tags: ["hardware", "open-source"], is_pinned: false,
|
||||
created_at: new Date(now - 7 * day).toISOString(), updated_at: new Date(now - 4 * hour).toISOString(),
|
||||
id: "demo-note-4", title: "Gear Research",
|
||||
content: `## Gear Research
|
||||
|
||||
### Via Ferrata Kit
|
||||
Need harness + lanyard + helmet. Can rent in Chamonix for ~EUR 25/day per person. Renting is better than buying for a one-time activity.
|
||||
|
||||
### Paragliding
|
||||
Tandem flights in Zermatt: ~EUR 180pp. Book at **Paragliding Zermatt** (best reviews on TripAdvisor). They offer morning flights with better thermals.
|
||||
|
||||
### Camera & Drone
|
||||
- Bring the **DJI Mini 4 Pro** for Tre Cime and Seceda
|
||||
- Check Italian drone regulations! Need ENAC registration for flights over 250g
|
||||
- ND filters for long exposure water shots at Lago di Braies
|
||||
- Extra batteries (3x) -- cold altitude drains them fast
|
||||
|
||||
> Liam scored the DJI Mini 4 Pro over GoPro Hero 12 and Sony A7C II in our decision matrix. Best weight-to-quality ratio for hiking.
|
||||
|
||||
### Group Gear (Shared)
|
||||
\`\`\`
|
||||
Item Cost Status Owner
|
||||
-------------------------- ------- ---------- -----
|
||||
Adventure First-Aid Kit EUR 85 Funded Omar
|
||||
Water Filter (Sawyer) EUR 45 Funded Maya
|
||||
Bear Canisters 2x (BV500) EUR 120 In Cart Liam
|
||||
Camp Stove + Fuel EUR 65 Funded Priya
|
||||
DJI Mini 4 Pro Rental EUR 350 Needs Fund Liam
|
||||
Starlink Mini Rental EUR 200 Needs Fund Omar
|
||||
\`\`\`
|
||||
|
||||
### Personal Gear Checklist
|
||||
- Hiking boots (broken in!)
|
||||
- Rain jacket (waterproof, not just resistant)
|
||||
- Headlamp + spare batteries
|
||||
- Trekking poles (collapsible for flights)
|
||||
- Sunscreen SPF 50 + lip balm
|
||||
- Wool base layers for hut nights`,
|
||||
content_plain: "Gear research including Via Ferrata rental, paragliding booking, camera and drone regulations, shared group gear status, and personal gear checklist.",
|
||||
type: "NOTE", tags: ["gear", "equipment", "budget"], is_pinned: false,
|
||||
created_at: new Date(now - 8 * day).toISOString(), updated_at: new Date(now - 2 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-5", title: "Emergency Contacts & Safety",
|
||||
content: `## Emergency Contacts & Safety
|
||||
|
||||
### Emergency Numbers
|
||||
- **France**: 112 (EU general), PGHM Mountain Rescue: +33 4 50 53 16 89
|
||||
- **Switzerland**: 1414 (REGA air rescue), 144 (ambulance)
|
||||
- **Italy**: 118 (medical), 112 (general emergency)
|
||||
|
||||
### Insurance
|
||||
- Policy #: **WA-2026-7891**
|
||||
- Emergency line: +1-800-555-0199
|
||||
- Covers: mountain rescue, helicopter evacuation, medical repatriation
|
||||
- Deductible: EUR 150 per incident
|
||||
|
||||
### Altitude Sickness Protocol
|
||||
1. Acclimatize in Chamonix (1,035m) for 2 days before going high
|
||||
2. Stay hydrated -- minimum 3L water per day above 2,500m
|
||||
3. Watch for symptoms: headache, nausea, dizziness
|
||||
4. Descend immediately if symptoms worsen
|
||||
5. Omar packed altitude sickness medication (Diamox) in the first-aid kit
|
||||
|
||||
### Weather Contingency
|
||||
> If the Matterhorn trek gets rained out, Omar found a cheese museum in Zermatt as backup. Priya suggests the Glacier Paradise instead.
|
||||
|
||||
- Check MeteoSwiss and Meteotrentino daily
|
||||
- Alpine weather changes fast -- always carry rain gear
|
||||
- Lightning protocol: descend ridgelines immediately, avoid isolated trees
|
||||
|
||||
### Emergency Meeting Points
|
||||
\`\`\`
|
||||
Chamonix: Place Balmat (town center)
|
||||
Zermatt: Bahnhofplatz (train station)
|
||||
Dolomites: Rifugio Auronzo parking lot
|
||||
\`\`\``,
|
||||
content_plain: "Emergency contacts for France, Switzerland, and Italy. Insurance details, altitude sickness protocol, weather contingency plans, and emergency meeting points.",
|
||||
type: "NOTE", tags: ["safety", "emergency", "contacts"], is_pinned: false,
|
||||
created_at: new Date(now - 7 * day).toISOString(), updated_at: new Date(now - 6 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-6", title: "Photo Spots & Creative Plan",
|
||||
content: `## Photo Spots & Creative Plan
|
||||
|
||||
### Must-Capture Locations
|
||||
1. **Lac Blanc** -- Reflection of Mont Blanc at sunrise. Arrive by 5:30am. Tripod essential.
|
||||
2. **Gornergrat Panorama** -- 360-degree view with Matterhorn. Golden hour is best.
|
||||
3. **Tre Cime from Rifugio Locatelli** -- The iconic three peaks at golden hour. Drone shots here.
|
||||
4. **Seceda Ridgeline** -- Dramatic Dolomite spires. Best drone footage location.
|
||||
5. **Lago di Braies** -- Turquoise water, use ND filters for long exposure reflections.
|
||||
|
||||
### Drone Shot List (Liam)
|
||||
- Tre Cime circular orbit (check wind < 20km/h)
|
||||
- Seceda ridge reveal shot (low to high)
|
||||
- Lago di Braies top-down turquoise pattern
|
||||
- Matterhorn time-lapse from Gornergrat (if weather permits)
|
||||
|
||||
### Zine Plan (Maya)
|
||||
We are making an **Alpine Explorer Zine** after the trip:
|
||||
- Format: A5 risograph, 50 copies
|
||||
- Print at Chamonix Print Collective
|
||||
- Content: best photos, trail notes, hand-drawn maps
|
||||
- Price: EUR 12 per copy on rCart
|
||||
|
||||
> Bring ND filters for long exposure water shots. Pack the circular polarizer for cutting glare on alpine lakes.
|
||||
|
||||
### Video Plan
|
||||
- Daily 30-second clips for trip recap
|
||||
- Lac Blanc sunrise test footage already uploaded to rTube (3:42)
|
||||
- Final edit: 5-8 minute highlight reel`,
|
||||
content_plain: "Photography and creative plan including must-capture locations, drone shot list, zine production details, and video plan.",
|
||||
type: "NOTE", tags: ["photography", "creative", "planning"], is_pinned: false,
|
||||
created_at: new Date(now - 5 * day).toISOString(), updated_at: new Date(now - 4 * hour).toISOString(),
|
||||
},
|
||||
];
|
||||
|
||||
const meetingNotes: Note[] = [
|
||||
const packingNotes: Note[] = [
|
||||
{
|
||||
id: "demo-note-5", title: "Sprint Planning \u2014 Feb 24",
|
||||
content: "Discussed module porting progress. Canvas and books done. Next: work, cal, vote...",
|
||||
content_plain: "Discussed module porting progress. Canvas and books done. Next: work, cal, vote...",
|
||||
type: "NOTE", tags: ["sprint", "planning"], is_pinned: false,
|
||||
created_at: new Date(now - 4 * day).toISOString(), updated_at: new Date(now - 3 * hour).toISOString(),
|
||||
id: "demo-note-7", title: "Packing Checklist",
|
||||
content: `## Packing Checklist
|
||||
|
||||
### Footwear
|
||||
- [x] Hiking boots (broken in!)
|
||||
- [ ] Camp sandals / flip-flops
|
||||
- [ ] Extra laces
|
||||
|
||||
### Clothing
|
||||
- [x] Rain jacket (Gore-Tex)
|
||||
- [ ] Down jacket for hut nights
|
||||
- [ ] 3x wool base layers
|
||||
- [ ] 2x hiking pants
|
||||
- [ ] Sun hat + warm beanie
|
||||
- [ ] Gloves (lightweight)
|
||||
|
||||
### Gear
|
||||
- [x] Headlamp + spare batteries
|
||||
- [ ] Trekking poles (collapsible)
|
||||
- [x] First aid kit
|
||||
- [ ] Sunscreen SPF 50
|
||||
- [ ] Water filter (Sawyer Squeeze)
|
||||
- [ ] Dry bags (2x)
|
||||
- [ ] Repair kit (duct tape, zip ties)
|
||||
|
||||
### Electronics
|
||||
- [ ] Camera + 3 batteries
|
||||
- [ ] Drone + 3 batteries (Liam)
|
||||
- [x] Power bank (20,000mAh)
|
||||
- [ ] Universal adapter (EU plugs)
|
||||
|
||||
### Documents
|
||||
- [x] Passports
|
||||
- [ ] Travel insurance printout
|
||||
- [x] Hut reservation confirmations
|
||||
- [ ] Italian drone registration
|
||||
- [ ] Emergency contacts card
|
||||
|
||||
### Food & Water
|
||||
- [ ] Reusable water bottles (1L each)
|
||||
- [ ] Trail snacks (energy bars, nuts)
|
||||
- [ ] Electrolyte tablets
|
||||
- [ ] Coffee/tea for hut mornings`,
|
||||
content_plain: "Complete packing checklist organized by category: footwear, clothing, gear, electronics, documents, and food. Includes checked-off items.",
|
||||
type: "NOTE", tags: ["packing", "gear", "checklist"], is_pinned: true,
|
||||
created_at: new Date(now - 6 * day).toISOString(), updated_at: new Date(now - hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-6", title: "Design Review \u2014 Feb 22",
|
||||
content: "Reviewed new shell header. Consensus on simplified nav. Action items: finalize color palette.",
|
||||
content_plain: "Reviewed new shell header. Consensus on simplified nav. Action items: finalize color palette.",
|
||||
type: "NOTE", tags: ["design", "review"], is_pinned: false,
|
||||
created_at: new Date(now - 6 * day).toISOString(), updated_at: new Date(now - 6 * hour).toISOString(),
|
||||
id: "demo-note-8", title: "Food & Cooking Plan",
|
||||
content: `## Food & Cooking Plan
|
||||
|
||||
### Hut Meals (Half-Board)
|
||||
Lac Blanc and Locatelli include dinner + breakfast. Budget EUR 0 for those nights.
|
||||
|
||||
### Self-Catering Days
|
||||
We have a kitchen in the Chamonix Airbnb and Zermatt apartment.
|
||||
|
||||
**Chamonix Grocery Run (Omar)**
|
||||
- Pasta, rice, couscous
|
||||
- Cheese, bread, cured meats
|
||||
- Fresh vegetables
|
||||
- Coffee, tea, milk
|
||||
- Trail mix ingredients
|
||||
|
||||
> Omar already spent EUR 93 at Chamonix Carrefour. Receipts in rFunds.
|
||||
|
||||
### Trail Lunches
|
||||
Pack these the night before each hike:
|
||||
- Sandwiches (baguette + cheese + ham)
|
||||
- Energy bars (2 per person)
|
||||
- Nuts and dried fruit
|
||||
- Chocolate (the altitude calls for it)
|
||||
- 1.5L water minimum
|
||||
|
||||
### Special Meals
|
||||
- **Jul 10**: Fondue at Chez Vrony, Zermatt (won the dinner vote 5-4 over pizza)
|
||||
- **Jul 18**: Cooking class in Bolzano (South Tyrolean cuisine)
|
||||
|
||||
### Dietary Notes
|
||||
\`\`\`
|
||||
Maya: Vegetarian (eggs & dairy OK)
|
||||
Priya: No shellfish allergy
|
||||
Others: No restrictions
|
||||
\`\`\``,
|
||||
content_plain: "Food and cooking plan covering hut meals, self-catering, trail lunches, special restaurant meals, and dietary notes for all travelers.",
|
||||
type: "NOTE", tags: ["food", "planning", "budget"], is_pinned: false,
|
||||
created_at: new Date(now - 4 * day).toISOString(), updated_at: new Date(now - 8 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-7", title: "Community Call \u2014 Feb 20",
|
||||
content: "30 participants. Demoed rFunds river view. Positive feedback on enoughness score.",
|
||||
content_plain: "30 participants. Demoed rFunds river view. Positive feedback on enoughness score.",
|
||||
type: "NOTE", tags: ["community", "call"], is_pinned: false,
|
||||
created_at: new Date(now - 8 * day).toISOString(), updated_at: new Date(now - 8 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-8", title: "Infrastructure Sync \u2014 Feb 18",
|
||||
content: "Mailcow migration complete. All 20 domains verified. DKIM keys rotated.",
|
||||
content_plain: "Mailcow migration complete. All 20 domains verified. DKIM keys rotated.",
|
||||
type: "NOTE", tags: ["infra", "mail"], is_pinned: false,
|
||||
created_at: new Date(now - 10 * day).toISOString(), updated_at: new Date(now - 10 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-9", title: "Retrospective \u2014 Feb 15",
|
||||
content: "What went well: EncryptID launch. What to improve: documentation coverage.",
|
||||
content_plain: "What went well: EncryptID launch. What to improve: documentation coverage.",
|
||||
type: "NOTE", tags: ["retro"], is_pinned: false,
|
||||
created_at: new Date(now - 13 * day).toISOString(), updated_at: new Date(now - 13 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-10", title: "Onboarding Session \u2014 Feb 12",
|
||||
content: "Walked 3 new contributors through rSpace setup. Created video guide.",
|
||||
content_plain: "Walked 3 new contributors through rSpace setup. Created video guide.",
|
||||
type: "NOTE", tags: ["onboarding"], is_pinned: false,
|
||||
created_at: new Date(now - 16 * day).toISOString(), updated_at: new Date(now - 16 * hour).toISOString(),
|
||||
id: "demo-note-9", title: "Transport & Logistics",
|
||||
content: `## Transport & Logistics
|
||||
|
||||
### Getting There
|
||||
- **Jul 6**: Fly to Geneva (everyone arrives by 14:00)
|
||||
- Geneva to Chamonix shuttle: EUR 186 for 4 pax (Maya paid, tracked in rFunds)
|
||||
|
||||
### Between Destinations
|
||||
- **Jul 10**: Chamonix to Zermatt
|
||||
- Option A: Train via Martigny (~3.5h, scenic)
|
||||
- Option B: Drive via Grand St Bernard tunnel (~2.5h)
|
||||
- *Decision: Train (Liam prefers scenic route)*
|
||||
|
||||
- **Jul 14**: Zermatt to Dolomites
|
||||
- Bernina Express is 6 hours but spectacular
|
||||
- Rental car is 3.5 hours
|
||||
- *Under discussion in rForum -- Priya prefers the train*
|
||||
|
||||
### Local Transport
|
||||
- **Chamonix**: Free local bus with guest card
|
||||
- **Zermatt**: Car-free! Electric taxis + Gornergrat railway
|
||||
- **Dolomites**: Need rental car or local bus (limited schedule)
|
||||
|
||||
### Getting Home
|
||||
- **Jul 20**: Drive to Innsbruck airport (~2.5h from Val Gardena)
|
||||
- Return flights booked separately
|
||||
|
||||
### Important Timetables
|
||||
\`\`\`
|
||||
Gornergrat Railway (first): 07:00 from Zermatt
|
||||
Lac Blanc trailhead shuttle: 06:30 from Chamonix
|
||||
Seceda gondola (first): 08:30 from Ortisei
|
||||
\`\`\`
|
||||
|
||||
> Sam is researching rail passes -- the Swiss Travel Pass might save us money for the Zermatt segment.`,
|
||||
content_plain: "Transport and logistics plan covering flights, inter-city transfers, local transport options, return journey, and important timetables.",
|
||||
type: "NOTE", tags: ["transport", "logistics"], is_pinned: false,
|
||||
created_at: new Date(now - 9 * day).toISOString(), updated_at: new Date(now - 5 * hour).toISOString(),
|
||||
},
|
||||
];
|
||||
|
||||
const readingNotes: Note[] = [
|
||||
const itineraryNotes: Note[] = [
|
||||
{
|
||||
id: "demo-note-11", title: "Governing the Commons",
|
||||
content: "Ostrom's 8 principles for managing shared resources. Especially relevant to our governance module.",
|
||||
content_plain: "Ostrom's 8 principles for managing shared resources. Especially relevant to our governance module.",
|
||||
type: "NOTE", tags: ["book", "governance"], is_pinned: false,
|
||||
created_at: new Date(now - 14 * day).toISOString(), updated_at: new Date(now - day).toISOString(),
|
||||
id: "demo-note-10", title: "Full Itinerary -- Alpine Explorer 2026",
|
||||
content: `## Full Itinerary -- Alpine Explorer 2026
|
||||
**Jul 6-20 | France, Switzerland, Italy**
|
||||
**Travelers: Maya, Liam, Priya, Omar, Alex, Sam**
|
||||
|
||||
### Week 1: Chamonix, France (Jul 6-10)
|
||||
| Date | Activity | Category |
|
||||
|------|----------|----------|
|
||||
| Jul 6 | Fly Geneva, shuttle to Chamonix | Travel |
|
||||
| Jul 7 | Acclimatization hike -- Lac Blanc | Hike |
|
||||
| Jul 8 | Via Ferrata -- Aiguille du Midi | Adventure |
|
||||
| Jul 9 | Rest day / Chamonix town | Rest |
|
||||
| Jul 10 | Train to Zermatt | Travel |
|
||||
|
||||
### Week 2: Zermatt, Switzerland (Jul 10-14)
|
||||
| Date | Activity | Category |
|
||||
|------|----------|----------|
|
||||
| Jul 10 | Arrive Zermatt, settle in | Travel |
|
||||
| Jul 11 | Gornergrat sunrise hike | Hike |
|
||||
| Jul 12 | Matterhorn base camp trek | Hike |
|
||||
| Jul 13 | Paragliding over Zermatt | Adventure |
|
||||
| Jul 14 | Transfer to Dolomites | Travel |
|
||||
|
||||
### Week 3: Dolomites, Italy (Jul 14-20)
|
||||
| Date | Activity | Category |
|
||||
|------|----------|----------|
|
||||
| Jul 14 | Arrive Val Gardena | Travel |
|
||||
| Jul 15 | Tre Cime di Lavaredo loop | Hike |
|
||||
| Jul 16 | Lago di Braies kayaking | Adventure |
|
||||
| Jul 17 | Seceda ridgeline hike | Hike |
|
||||
| Jul 18 | Cooking class in Bolzano | Culture |
|
||||
| Jul 19 | Free day -- shopping & packing | Rest |
|
||||
| Jul 20 | Fly home from Innsbruck | Travel |
|
||||
|
||||
> This itinerary is also tracked in rTrips and synced to the shared rCal calendar.`,
|
||||
content_plain: "Complete day-by-day itinerary for the Alpine Explorer 2026 trip covering three weeks across Chamonix, Zermatt, and the Dolomites.",
|
||||
type: "NOTE", tags: ["itinerary", "planning"], is_pinned: true,
|
||||
created_at: new Date(now - 15 * day).toISOString(), updated_at: new Date(now - 2 * hour).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-12", title: "Entangled Life",
|
||||
content: "Sheldrake's exploration of fungal networks. The wood wide web metaphor maps perfectly to mesh networks.",
|
||||
content_plain: "Sheldrake's exploration of fungal networks. The wood wide web metaphor maps perfectly to mesh networks.",
|
||||
type: "NOTE", tags: ["book", "mycelium"], is_pinned: false,
|
||||
created_at: new Date(now - 20 * day).toISOString(), updated_at: new Date(now - 2 * day).toISOString(),
|
||||
id: "demo-note-11", title: "Mountain Hut Reservations",
|
||||
content: `## Mountain Hut Reservations
|
||||
|
||||
### Confirmed
|
||||
- **Refuge du Lac Blanc** (Jul 7)
|
||||
- 4 beds reserved, half-board
|
||||
- Confirmation: #LB2026-234
|
||||
- Check-in after 15:00, dinner at 19:00
|
||||
- Bring sleeping bag liner (required)
|
||||
|
||||
- **Rifugio Locatelli** (Jul 15)
|
||||
- 4 beds reserved, half-board
|
||||
- Confirmation: #TRE2026-089
|
||||
- Famous for Tre Cime sunset views
|
||||
- Cash only! Bring EUR 55pp
|
||||
|
||||
### Waitlisted
|
||||
- **Hornlihutte** (Matterhorn base, Jul 12)
|
||||
- Waitlisted -- will know by Jul 1
|
||||
- If no luck, camp at Zermatt and do a long day hike instead
|
||||
- Alex is monitoring the cancellation list
|
||||
|
||||
### Hut Etiquette Reminders
|
||||
1. Arrive before 17:00 if possible
|
||||
2. Remove boots at entrance (bring hut shoes or thick socks)
|
||||
3. Lights out by 22:00
|
||||
4. Pack out all trash
|
||||
5. Tip is appreciated but not required
|
||||
|
||||
> Priya handled all the hut bookings. She has the confirmations printed and digital copies in rFiles.`,
|
||||
content_plain: "Mountain hut reservations with confirmation numbers, check-in details, and hut etiquette reminders. Two confirmed, one waitlisted.",
|
||||
type: "NOTE", tags: ["accommodation", "hiking"], is_pinned: false,
|
||||
created_at: new Date(now - 11 * day).toISOString(), updated_at: new Date(now - day).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "demo-note-13", title: "Doughnut Economics",
|
||||
content: "Raworth's framework for staying within planetary boundaries while meeting human needs.",
|
||||
content_plain: "Raworth's framework for staying within planetary boundaries while meeting human needs.",
|
||||
type: "NOTE", tags: ["book", "economics"], is_pinned: false,
|
||||
created_at: new Date(now - 25 * day).toISOString(), updated_at: new Date(now - 3 * day).toISOString(),
|
||||
id: "demo-note-12", title: "Group Decisions & Votes",
|
||||
content: `## Group Decisions & Votes
|
||||
|
||||
### Decided
|
||||
- **Camera Gear**: DJI Mini 4 Pro (Liam's decision matrix: 8.5/10)
|
||||
- **First Night Dinner in Zermatt**: Fondue at Chez Vrony (won 5-4 over pizza)
|
||||
- **Day 5 Activity**: Via Ferrata at Aiguille du Midi (won 7-3 over kayaking)
|
||||
|
||||
### Active Votes (in rVote)
|
||||
- **Zermatt to Dolomites transfer**: Train vs rental car
|
||||
- Train: 3 votes (Liam, Priya, Sam)
|
||||
- Car: 2 votes (Maya, Omar)
|
||||
- Alex: undecided
|
||||
|
||||
### Pending Decisions
|
||||
- Val Gardena accommodation (agriturismo vs apartment)
|
||||
- Whether to rent the Starlink Mini (EUR 200, needs funding)
|
||||
- Trip zine print run size (50 vs 100 copies)
|
||||
|
||||
### Decision Framework
|
||||
We are using a simple majority vote for group activities. For expenses over EUR 100, we need consensus (all 6 agree). Individual expenses are each person's choice.
|
||||
|
||||
> All votes are tracked in rVote and synced to the canvas.`,
|
||||
content_plain: "Summary of group decisions made and active votes. Covers camera gear, dining, activities, and pending decisions with the group's voting framework.",
|
||||
type: "NOTE", tags: ["decisions", "planning"], is_pinned: false,
|
||||
created_at: new Date(now - 3 * day).toISOString(), updated_at: new Date(now - 3 * hour).toISOString(),
|
||||
},
|
||||
];
|
||||
|
||||
this.demoNotebooks = [
|
||||
{
|
||||
id: "demo-nb-1", title: "Project Ideas", description: "Ideas for new projects and features",
|
||||
cover_color: "#6366f1", note_count: "4", updated_at: new Date(now - hour).toISOString(),
|
||||
notes: projectNotes, space: "demo",
|
||||
id: "demo-nb-1", title: "Alpine Explorer Planning", description: "Shared knowledge base for our July 2026 trip across France, Switzerland, and Italy",
|
||||
cover_color: "#f59e0b", note_count: "6", updated_at: new Date(now - hour).toISOString(),
|
||||
notes: tripPlanningNotes, space: "demo",
|
||||
} as any,
|
||||
{
|
||||
id: "demo-nb-2", title: "Meeting Notes", description: "Team meetings and sync calls",
|
||||
cover_color: "#22c55e", note_count: "6", updated_at: new Date(now - 3 * hour).toISOString(),
|
||||
notes: meetingNotes, space: "demo",
|
||||
id: "demo-nb-2", title: "Packing & Logistics", description: "Checklists, food plans, and transport details",
|
||||
cover_color: "#22c55e", note_count: "3", updated_at: new Date(now - hour).toISOString(),
|
||||
notes: packingNotes, space: "demo",
|
||||
} as any,
|
||||
{
|
||||
id: "demo-nb-3", title: "Reading Journal", description: "Books, articles, and reflections",
|
||||
cover_color: "#f59e0b", note_count: "3", updated_at: new Date(now - day).toISOString(),
|
||||
notes: readingNotes, space: "demo",
|
||||
id: "demo-nb-3", title: "Itinerary & Decisions", description: "Day-by-day schedule, hut reservations, and group votes",
|
||||
cover_color: "#6366f1", note_count: "3", updated_at: new Date(now - 2 * hour).toISOString(),
|
||||
notes: itineraryNotes, space: "demo",
|
||||
} as any,
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -28,90 +28,77 @@ class FolkTripsPlanner extends HTMLElement {
|
|||
|
||||
private loadDemoData() {
|
||||
this.trips = [
|
||||
{ id: "t1", title: "Berlin Maker Week", status: "PLANNING", start_date: "2026-04-14", end_date: "2026-04-20", budget_total: "2500", total_spent: "850", destination_count: 3, description: "Visiting makerspaces and cosmolocal print providers across Berlin" },
|
||||
{ id: "t2", title: "Mediterranean Commons Tour", status: "BOOKED", start_date: "2026-06-01", end_date: "2026-06-15", budget_total: "4000", total_spent: "3200", destination_count: 4, description: "Connecting with commons communities in Barcelona, Marseille, and Athens" }
|
||||
{ id: "alpine-2026", title: "Alpine Explorer 2026", status: "PLANNING", start_date: "2026-07-06", end_date: "2026-07-20", budget_total: "4500", total_spent: "1203", destination_count: 3, description: "15-day adventure through Chamonix (France) \u2192 Zermatt (Switzerland) \u2192 Dolomites (Italy)" }
|
||||
];
|
||||
this.render();
|
||||
}
|
||||
|
||||
private getDemoTripDetail(id: string): any {
|
||||
if (id === "t1") {
|
||||
return {
|
||||
id: "t1",
|
||||
title: "Berlin Maker Week",
|
||||
status: "PLANNING",
|
||||
start_date: "2026-04-14",
|
||||
end_date: "2026-04-20",
|
||||
budget_total: "2500",
|
||||
description: "Visiting makerspaces and cosmolocal print providers across Berlin",
|
||||
destinations: [
|
||||
{ id: "d1", name: "Druckwerkstatt Berlin", country: "Germany", arrival_date: "2026-04-14" },
|
||||
{ id: "d2", name: "c-base Hackerspace", country: "Germany", arrival_date: "2026-04-16" },
|
||||
{ id: "d3", name: "Fab Lab Berlin", country: "Germany", arrival_date: "2026-04-18" }
|
||||
],
|
||||
itinerary: [
|
||||
{ id: "i1", title: "Visit Druckwerkstatt", category: "ACTIVITY", date: "2026-04-14", start_time: "10:00" },
|
||||
{ id: "i2", title: "Print workshop", category: "WORKSHOP", date: "2026-04-15", start_time: "09:00" },
|
||||
{ id: "i3", title: "c-base tour", category: "ACTIVITY", date: "2026-04-16", start_time: "14:00" },
|
||||
{ id: "i4", title: "Fab Lab session", category: "WORKSHOP", date: "2026-04-18", start_time: "10:00" },
|
||||
{ id: "i5", title: "Team dinner", category: "SOCIAL", date: "2026-04-19", start_time: "19:00" }
|
||||
],
|
||||
bookings: [
|
||||
{ id: "bk1", type: "HOTEL", provider: "Hotel Amano", confirmation_number: "AMN-29381", cost: "560" },
|
||||
{ id: "bk2", type: "TRANSPORT", provider: "Deutsche Bahn", confirmation_number: "DB-773920", cost: "85" }
|
||||
],
|
||||
expenses: [
|
||||
{ id: "e1", category: "TRANSPORT", description: "Flights", amount: "450", date: "2026-04-14" },
|
||||
{ id: "e2", category: "ACCOMMODATION", description: "Accommodation", amount: "280", date: "2026-04-14" },
|
||||
{ id: "e3", category: "ACTIVITY", description: "Workshop fee", amount: "120", date: "2026-04-15" }
|
||||
],
|
||||
packing: [
|
||||
{ id: "pk1", name: "Laptop", category: "TECH", quantity: 1, packed: true },
|
||||
{ id: "pk2", name: "Notebook", category: "SUPPLIES", quantity: 1, packed: true },
|
||||
{ id: "pk3", name: "USB drives", category: "TECH", quantity: 3, packed: false },
|
||||
{ id: "pk4", name: "Camera", category: "TECH", quantity: 1, packed: false },
|
||||
{ id: "pk5", name: "Adapters", category: "TECH", quantity: 2, packed: false }
|
||||
]
|
||||
};
|
||||
}
|
||||
return {
|
||||
id: "t2",
|
||||
title: "Mediterranean Commons Tour",
|
||||
status: "BOOKED",
|
||||
start_date: "2026-06-01",
|
||||
end_date: "2026-06-15",
|
||||
budget_total: "4000",
|
||||
description: "Connecting with commons communities in Barcelona, Marseille, and Athens",
|
||||
id: "alpine-2026",
|
||||
title: "Alpine Explorer 2026",
|
||||
status: "PLANNING",
|
||||
start_date: "2026-07-06",
|
||||
end_date: "2026-07-20",
|
||||
budget_total: "4500",
|
||||
description: "15-day adventure through Chamonix (France) \u2192 Zermatt (Switzerland) \u2192 Dolomites (Italy). 6 explorers, 3 countries, endless peaks.",
|
||||
destinations: [
|
||||
{ id: "d4", name: "Fab Lab Barcelona", country: "Spain", arrival_date: "2026-06-01" },
|
||||
{ id: "d5", name: "La Coop des Communs", country: "France", arrival_date: "2026-06-05" },
|
||||
{ id: "d6", name: "P2P Foundation Athens", country: "Greece", arrival_date: "2026-06-09" },
|
||||
{ id: "d7", name: "Synergatika Cooperative", country: "Greece", arrival_date: "2026-06-12" }
|
||||
{ id: "d1", name: "Chamonix", country: "France", arrival_date: "2026-07-06" },
|
||||
{ id: "d2", name: "Zermatt", country: "Switzerland", arrival_date: "2026-07-12" },
|
||||
{ id: "d3", name: "Dolomites", country: "Italy", arrival_date: "2026-07-17" }
|
||||
],
|
||||
itinerary: [
|
||||
{ id: "i6", title: "Fab Lab Barcelona tour", category: "ACTIVITY", date: "2026-06-01", start_time: "10:00" },
|
||||
{ id: "i7", title: "Commons workshop", category: "WORKSHOP", date: "2026-06-02", start_time: "09:00" },
|
||||
{ id: "i8", title: "Marseille meetup", category: "SOCIAL", date: "2026-06-05", start_time: "18:00" },
|
||||
{ id: "i9", title: "P2P Foundation visit", category: "ACTIVITY", date: "2026-06-09", start_time: "11:00" },
|
||||
{ id: "i10", title: "Cooperative workshop", category: "WORKSHOP", date: "2026-06-12", start_time: "10:00" }
|
||||
{ id: "i1", title: "Fly Geneva \u2192 Chamonix shuttle", category: "TRANSPORT", date: "2026-07-06", start_time: "10:00" },
|
||||
{ id: "i2", title: "Acclimatization hike \u2014 Lac Blanc", category: "ACTIVITY", date: "2026-07-07", start_time: "07:00" },
|
||||
{ id: "i3", title: "Via Ferrata \u2014 Aiguille du Midi", category: "ACTIVITY", date: "2026-07-08", start_time: "08:00" },
|
||||
{ id: "i4", title: "Rest day / Chamonix town", category: "FREE_TIME", date: "2026-07-09", start_time: "10:00" },
|
||||
{ id: "i5", title: "Group dinner \u2014 La Cabane", category: "MEAL", date: "2026-07-09", start_time: "19:00" },
|
||||
{ id: "i6", title: "Mont Blanc viewpoint hike", category: "ACTIVITY", date: "2026-07-10", start_time: "06:30" },
|
||||
{ id: "i7", title: "Farewell lunch in Chamonix", category: "MEAL", date: "2026-07-11", start_time: "12:00" },
|
||||
{ id: "i8", title: "Train to Zermatt via Glacier Express", category: "TRANSPORT", date: "2026-07-12", start_time: "08:00" },
|
||||
{ id: "i9", title: "Gornergrat sunrise hike", category: "ACTIVITY", date: "2026-07-13", start_time: "05:30" },
|
||||
{ id: "i10", title: "Matterhorn base camp trek", category: "ACTIVITY", date: "2026-07-14", start_time: "07:00" },
|
||||
{ id: "i11", title: "Paragliding over Zermatt", category: "ACTIVITY", date: "2026-07-15", start_time: "10:00" },
|
||||
{ id: "i12", title: "Fondue dinner \u2014 Chez Vrony", category: "MEAL", date: "2026-07-15", start_time: "19:30" },
|
||||
{ id: "i13", title: "Transfer to Dolomites", category: "TRANSPORT", date: "2026-07-16", start_time: "09:00" },
|
||||
{ id: "i14", title: "Tre Cime di Lavaredo loop", category: "ACTIVITY", date: "2026-07-17", start_time: "07:00" },
|
||||
{ id: "i15", title: "Lago di Braies kayaking", category: "ACTIVITY", date: "2026-07-18", start_time: "09:00" },
|
||||
{ id: "i16", title: "Cooking class in Bolzano", category: "ACTIVITY", date: "2026-07-19", start_time: "11:00" },
|
||||
{ id: "i17", title: "Free day \u2014 shopping & packing", category: "FREE_TIME", date: "2026-07-19", start_time: "14:00" },
|
||||
{ id: "i18", title: "Fly home from Innsbruck", category: "TRANSPORT", date: "2026-07-20", start_time: "12:00" }
|
||||
],
|
||||
bookings: [
|
||||
{ id: "bk3", type: "TRANSPORT", provider: "Vueling Airlines", confirmation_number: "VY-482910", cost: "320" },
|
||||
{ id: "bk4", type: "HOTEL", provider: "Hotel Casa Bonay", confirmation_number: "CB-11204", cost: "780" },
|
||||
{ id: "bk5", type: "TRANSPORT", provider: "Eurostar", confirmation_number: "ES-556271", cost: "190" }
|
||||
{ id: "bk1", type: "FLIGHT", provider: "easyJet \u2014 Geneva", confirmation_number: "EZY-20260706-ALP", cost: "890" },
|
||||
{ id: "bk2", type: "TRANSPORT", provider: "Glacier Express", confirmation_number: "GEX-445920", cost: "240" },
|
||||
{ id: "bk3", type: "ACCOMMODATION", provider: "Refuge du Lac Blanc", confirmation_number: "LB2026-234", cost: "320" },
|
||||
{ id: "bk4", type: "ACCOMMODATION", provider: "Hotel Matterhorn Focus, Zermatt", confirmation_number: "MF-88201", cost: "780" },
|
||||
{ id: "bk5", type: "ACCOMMODATION", provider: "Rifugio Locatelli, Dolomites", confirmation_number: "TRE2026-089", cost: "280" },
|
||||
{ id: "bk6", type: "ACTIVITY", provider: "Paragliding Zermatt (tandem x6)", confirmation_number: "PGZ-1120", cost: "1080" }
|
||||
],
|
||||
expenses: [
|
||||
{ id: "e4", category: "TRANSPORT", description: "Flights and trains", amount: "1200", date: "2026-06-01" },
|
||||
{ id: "e5", category: "ACCOMMODATION", description: "Hotels and hostels", amount: "1400", date: "2026-06-01" },
|
||||
{ id: "e6", category: "FOOD", description: "Meals and groceries", amount: "450", date: "2026-06-01" },
|
||||
{ id: "e7", category: "ACTIVITY", description: "Workshop fees", amount: "150", date: "2026-06-02" }
|
||||
{ id: "e1", category: "TRANSPORT", description: "Geneva \u2192 Chamonix shuttle (6 pax)", amount: "186", date: "2026-07-06" },
|
||||
{ id: "e2", category: "ACCOMMODATION", description: "Mountain hut reservations (3 nights)", amount: "420", date: "2026-07-07" },
|
||||
{ id: "e3", category: "ACTIVITY", description: "Via Ferrata gear rental (6 sets)", amount: "216", date: "2026-07-08" },
|
||||
{ id: "e4", category: "FOOD", description: "Groceries \u2014 Chamonix Carrefour", amount: "93", date: "2026-07-06" },
|
||||
{ id: "e5", category: "ACTIVITY", description: "Paragliding deposit (4 of 6 booked)", amount: "288", date: "2026-07-13" }
|
||||
],
|
||||
packing: [
|
||||
{ id: "pk6", name: "Laptop", category: "TECH", quantity: 1, packed: true },
|
||||
{ id: "pk7", name: "Sunscreen", category: "PERSONAL", quantity: 1, packed: true },
|
||||
{ id: "pk8", name: "Phrasebooks", category: "SUPPLIES", quantity: 2, packed: false },
|
||||
{ id: "pk9", name: "Camera", category: "TECH", quantity: 1, packed: true },
|
||||
{ id: "pk10", name: "Power bank", category: "TECH", quantity: 1, packed: false }
|
||||
{ id: "pk1", name: "Hiking boots (broken in)", category: "FOOTWEAR", quantity: 1, packed: true },
|
||||
{ id: "pk2", name: "Rain jacket", category: "CLOTHING", quantity: 1, packed: true },
|
||||
{ id: "pk3", name: "Trekking poles", category: "GEAR", quantity: 1, packed: false },
|
||||
{ id: "pk4", name: "Headlamp + batteries", category: "GEAR", quantity: 1, packed: true },
|
||||
{ id: "pk5", name: "Sunscreen SPF 50", category: "PERSONAL", quantity: 1, packed: false },
|
||||
{ id: "pk6", name: "Water filter", category: "GEAR", quantity: 1, packed: false },
|
||||
{ id: "pk7", name: "First aid kit", category: "SAFETY", quantity: 1, packed: true },
|
||||
{ id: "pk8", name: "Passport + travel insurance", category: "DOCUMENTS", quantity: 1, packed: true }
|
||||
],
|
||||
collaborators: [
|
||||
{ name: "Alex", role: "organizer" },
|
||||
{ name: "Sam", role: "photographer" },
|
||||
{ name: "Jordan", role: "logistics" },
|
||||
{ name: "Riley", role: "navigator" },
|
||||
{ name: "Casey", role: "gear lead" },
|
||||
{ name: "Morgan", role: "safety" }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,12 @@ interface VoteSpace {
|
|||
slug: string;
|
||||
name: string;
|
||||
description: string;
|
||||
visibility: string;
|
||||
promotion_threshold: number;
|
||||
voting_period_days: number;
|
||||
credits_per_day: number;
|
||||
max_credits: number;
|
||||
starting_credits: number;
|
||||
}
|
||||
|
||||
interface Proposal {
|
||||
|
|
@ -51,7 +54,17 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
|
||||
private loadDemoData() {
|
||||
this.spaces = [
|
||||
{ slug: "rspace", name: "rSpace Governance", description: "Community proposals for the rSpace ecosystem", promotion_threshold: 100, voting_period_days: 7, credits_per_day: 10 }
|
||||
{
|
||||
slug: "community",
|
||||
name: "Community Governance",
|
||||
description: "Proposals for the rSpace ecosystem",
|
||||
visibility: "public_read",
|
||||
promotion_threshold: 100,
|
||||
voting_period_days: 7,
|
||||
credits_per_day: 10,
|
||||
max_credits: 500,
|
||||
starting_credits: 50,
|
||||
},
|
||||
];
|
||||
this.selectedSpace = this.spaces[0];
|
||||
this.view = "proposals";
|
||||
|
|
@ -59,10 +72,61 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
const now = Date.now();
|
||||
const day = 86400000;
|
||||
this.proposals = [
|
||||
{ id: "p1", title: "Fund local-first infrastructure sprint", description: "Allocate 5000 DAI for a 2-week sprint on Automerge integration", status: "RANKING", score: 73, vote_count: "12", final_yes: 0, final_no: 0, final_abstain: 0, created_at: new Date(now - 2 * day).toISOString(), voting_ends_at: null },
|
||||
{ id: "p2", title: "Add dark mode to all rApps", description: "Standardize dark theme tokens across the ecosystem", status: "VOTING", score: 100, vote_count: "8", final_yes: 14, final_no: 3, final_abstain: 2, created_at: new Date(now - 5 * day).toISOString(), voting_ends_at: new Date(now + 3 * day).toISOString() },
|
||||
{ id: "p3", title: "Create onboarding tutorial series", description: "Video walkthrough series for new community members", status: "PASSED", score: 100, vote_count: "15", final_yes: 22, final_no: 4, final_abstain: 1, created_at: new Date(now - 14 * day).toISOString(), voting_ends_at: new Date(now - 3 * day).toISOString() },
|
||||
{ id: "p4", title: "Migrate to paid hosting tier", description: "Move from shared to dedicated infrastructure", status: "FAILED", score: 100, vote_count: "11", final_yes: 5, final_no: 18, final_abstain: 3, created_at: new Date(now - 14 * day).toISOString(), voting_ends_at: new Date(now - 5 * day).toISOString() }
|
||||
{
|
||||
id: "p1",
|
||||
title: "Implement real-time collaboration in rNotes",
|
||||
description: "Use Automerge CRDTs (already in the stack) to enable simultaneous editing of notes, similar to how rSpace canvas works.",
|
||||
status: "RANKING",
|
||||
score: 72,
|
||||
vote_count: "9",
|
||||
final_yes: 0, final_no: 0, final_abstain: 0,
|
||||
created_at: new Date(now - 3 * day).toISOString(),
|
||||
voting_ends_at: null,
|
||||
},
|
||||
{
|
||||
id: "p2",
|
||||
title: "Add dark mode across all r* modules",
|
||||
description: "Implement a consistent dark theme with a toggle in shell.css. Use CSS custom properties for theming so each module inherits automatically.",
|
||||
status: "RANKING",
|
||||
score: 45,
|
||||
vote_count: "6",
|
||||
final_yes: 0, final_no: 0, final_abstain: 0,
|
||||
created_at: new Date(now - 5 * day).toISOString(),
|
||||
voting_ends_at: null,
|
||||
},
|
||||
{
|
||||
id: "p3",
|
||||
title: "Adopt cosmolocal print-on-demand for all merch",
|
||||
description: "Route all merchandise orders through the provider registry to find the closest printer. Reduces shipping emissions and supports local economies.",
|
||||
status: "VOTING",
|
||||
score: 105,
|
||||
vote_count: "14",
|
||||
final_yes: 5, final_no: 2, final_abstain: 0,
|
||||
created_at: new Date(now - 10 * day).toISOString(),
|
||||
voting_ends_at: new Date(now + 5 * day).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "p4",
|
||||
title: "Use EncryptID passkeys for all authentication",
|
||||
description: "Standardize on WebAuthn passkeys via EncryptID across the entire r* ecosystem. One passkey, all apps.",
|
||||
status: "PASSED",
|
||||
score: 150,
|
||||
vote_count: "17",
|
||||
final_yes: 12, final_no: 3, final_abstain: 2,
|
||||
created_at: new Date(now - 21 * day).toISOString(),
|
||||
voting_ends_at: new Date(now - 7 * day).toISOString(),
|
||||
},
|
||||
{
|
||||
id: "p5",
|
||||
title: "Switch from PostgreSQL to SQLite for simpler deployment",
|
||||
description: "Evaluate replacing PostgreSQL with SQLite for modules that don't need concurrent writes.",
|
||||
status: "FAILED",
|
||||
score: 30,
|
||||
vote_count: "11",
|
||||
final_yes: 2, final_no: 8, final_abstain: 1,
|
||||
created_at: new Date(now - 18 * day).toISOString(),
|
||||
voting_ends_at: new Date(now - 4 * day).toISOString(),
|
||||
},
|
||||
];
|
||||
this.render();
|
||||
}
|
||||
|
|
@ -120,7 +184,18 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
private async castVote(proposalId: string, weight: number) {
|
||||
if (this.space === "demo") {
|
||||
const p = this.proposals.find(p => p.id === proposalId);
|
||||
if (p) { p.score += weight; this.selectedProposal = p; }
|
||||
if (p) {
|
||||
p.score += weight;
|
||||
p.vote_count = String(parseInt(p.vote_count) + 1);
|
||||
// Auto-promote if score reaches threshold (matches server-side behavior)
|
||||
const threshold = this.selectedSpace?.promotion_threshold || 100;
|
||||
if (p.score >= threshold && p.status === "RANKING") {
|
||||
p.status = "VOTING";
|
||||
const votingDays = this.selectedSpace?.voting_period_days || 7;
|
||||
p.voting_ends_at = new Date(Date.now() + votingDays * 86400000).toISOString();
|
||||
}
|
||||
this.selectedProposal = p;
|
||||
}
|
||||
this.render();
|
||||
return;
|
||||
}
|
||||
|
|
@ -251,18 +326,30 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
${this.spaces.length === 0 ? '<div class="empty">No voting spaces yet. Create one to get started.</div>' : ""}
|
||||
${this.spaces.map((s) => `
|
||||
<div class="card" data-space="${s.slug}">
|
||||
<div class="card-title">${this.esc(s.name)}</div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center">
|
||||
<div class="card-title">${this.esc(s.name)}</div>
|
||||
<span class="badge" style="background:rgba(129,140,248,0.15);color:#818cf8">${s.visibility === "public_read" ? "Public" : s.visibility}</span>
|
||||
</div>
|
||||
<div class="card-desc">${this.esc(s.description || "")}</div>
|
||||
<div class="card-meta">
|
||||
<span>Threshold: ${s.promotion_threshold}</span>
|
||||
<span>Voting: ${s.voting_period_days}d</span>
|
||||
<span>${s.credits_per_day} credits/day</span>
|
||||
<span>Max: ${s.max_credits}</span>
|
||||
<span>Start: ${s.starting_credits}</span>
|
||||
</div>
|
||||
</div>
|
||||
`).join("")}
|
||||
`;
|
||||
}
|
||||
|
||||
private relativeTime(dateStr: string): string {
|
||||
const daysAgo = Math.floor((Date.now() - new Date(dateStr).getTime()) / 86400000);
|
||||
if (daysAgo === 0) return "today";
|
||||
if (daysAgo === 1) return "1 day ago";
|
||||
return `${daysAgo} days ago`;
|
||||
}
|
||||
|
||||
private renderProposals(): string {
|
||||
const s = this.selectedSpace!;
|
||||
return `
|
||||
|
|
@ -282,13 +369,26 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
<div class="score-bar">
|
||||
<div class="score-fill" style="width:${Math.min(100, (p.score / (s.promotion_threshold || 100)) * 100)}%;background:${this.getStatusColor(p.status)}"></div>
|
||||
</div>
|
||||
<div class="card-meta"><span>Score: ${Math.round(p.score)} / ${s.promotion_threshold}</span></div>
|
||||
<div class="card-meta">
|
||||
<span>Score: ${Math.round(p.score)} / ${s.promotion_threshold}</span>
|
||||
<span>${p.vote_count} votes</span>
|
||||
<span>${this.relativeTime(p.created_at)}</span>
|
||||
</div>
|
||||
` : ""}
|
||||
${p.status === "VOTING" || p.status === "PASSED" || p.status === "FAILED" ? `
|
||||
${p.status === "VOTING" ? `
|
||||
<div class="card-meta">
|
||||
<span style="color:#22c55e">Yes: ${p.final_yes}</span>
|
||||
<span style="color:#ef4444">No: ${p.final_no}</span>
|
||||
<span style="color:#f59e0b">Abstain: ${p.final_abstain}</span>
|
||||
${p.voting_ends_at ? `<span>Ends: ${new Date(p.voting_ends_at).toLocaleDateString()}</span>` : ""}
|
||||
</div>
|
||||
` : ""}
|
||||
${p.status === "PASSED" || p.status === "FAILED" ? `
|
||||
<div class="card-meta">
|
||||
<span style="color:#22c55e">Yes: ${p.final_yes}</span>
|
||||
<span style="color:#ef4444">No: ${p.final_no}</span>
|
||||
<span style="color:#f59e0b">Abstain: ${p.final_abstain}</span>
|
||||
<span>${this.relativeTime(p.created_at)}</span>
|
||||
</div>
|
||||
` : ""}
|
||||
</div>
|
||||
|
|
@ -298,6 +398,11 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
|
||||
private renderProposal(): string {
|
||||
const p = this.selectedProposal!;
|
||||
const threshold = this.selectedSpace?.promotion_threshold || 100;
|
||||
const created = new Date(p.created_at);
|
||||
const daysAgo = Math.floor((Date.now() - created.getTime()) / 86400000);
|
||||
const ageText = daysAgo === 0 ? "today" : daysAgo === 1 ? "1 day ago" : `${daysAgo} days ago`;
|
||||
|
||||
return `
|
||||
<div class="rapp-nav">
|
||||
<button class="rapp-nav__back" data-back="proposals">← Proposals</button>
|
||||
|
|
@ -306,23 +411,34 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
</div>
|
||||
<div class="card" style="cursor:default">
|
||||
<div class="card-desc" style="font-size:14px;color:#ccc;margin-bottom:12px">${this.esc(p.description || "No description")}</div>
|
||||
<div class="card-meta" style="margin-bottom:12px">
|
||||
<span>${p.vote_count} votes</span>
|
||||
<span>Created ${ageText}</span>
|
||||
</div>
|
||||
|
||||
${p.status === "RANKING" ? `
|
||||
<div style="margin-bottom:8px;font-size:13px;color:#888">Conviction score: <strong style="color:#3b82f6">${Math.round(p.score)}</strong></div>
|
||||
<div class="score-bar">
|
||||
<div class="score-fill" style="width:${Math.min(100, (p.score / 100) * 100)}%;background:#3b82f6"></div>
|
||||
<div style="margin-bottom:8px;font-size:13px;color:#888">
|
||||
Conviction score: <strong style="color:#3b82f6">${Math.round(p.score)}</strong> / ${threshold}
|
||||
</div>
|
||||
<div class="score-bar">
|
||||
<div class="score-fill" style="width:${Math.min(100, (p.score / threshold) * 100)}%;background:#3b82f6"></div>
|
||||
</div>
|
||||
<div style="font-size:12px;color:#666;margin-top:4px">
|
||||
Needs ${threshold} to advance to voting (quadratic cost: weight² credits)
|
||||
</div>
|
||||
<div style="font-size:12px;color:#666;margin-top:4px">Needs 100 to advance to voting</div>
|
||||
<div class="vote-controls">
|
||||
${[1, 2, 3, 5].map((w) => `
|
||||
<button class="vote-btn" data-vote-weight="${w}">
|
||||
Vote +${w} (${w * w} credits)
|
||||
+${w} (${w * w} credits)
|
||||
</button>
|
||||
`).join("")}
|
||||
</div>
|
||||
` : ""}
|
||||
|
||||
${p.status === "VOTING" ? `
|
||||
<div style="margin-bottom:8px;font-size:13px;color:#888">
|
||||
Promoted with conviction score <strong style="color:#f59e0b">${Math.round(p.score)}</strong> — now in ${this.selectedSpace?.voting_period_days || 7}-day final vote
|
||||
</div>
|
||||
<div class="tally">
|
||||
<div class="tally-item"><div class="tally-value" style="color:#22c55e">${p.final_yes}</div><div class="tally-label">Yes</div></div>
|
||||
<div class="tally-item"><div class="tally-value" style="color:#ef4444">${p.final_no}</div><div class="tally-label">No</div></div>
|
||||
|
|
@ -337,6 +453,10 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
` : ""}
|
||||
|
||||
${p.status === "PASSED" || p.status === "FAILED" ? `
|
||||
<div style="margin-bottom:8px;font-size:13px;color:#888">
|
||||
Final result: <strong style="color:${this.getStatusColor(p.status)}">${p.status}</strong>
|
||||
(conviction score was ${Math.round(p.score)})
|
||||
</div>
|
||||
<div class="tally">
|
||||
<div class="tally-item"><div class="tally-value" style="color:#22c55e">${p.final_yes}</div><div class="tally-label">Yes</div></div>
|
||||
<div class="tally-item"><div class="tally-value" style="color:#ef4444">${p.final_no}</div><div class="tally-label">No</div></div>
|
||||
|
|
@ -354,7 +474,11 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
const slug = (el as HTMLElement).dataset.space!;
|
||||
this.selectedSpace = this.spaces.find((s) => s.slug === slug) || null;
|
||||
this.view = "proposals";
|
||||
this.loadProposals(slug);
|
||||
if (this.space === "demo") {
|
||||
this.render();
|
||||
} else {
|
||||
this.loadProposals(slug);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -363,7 +487,12 @@ class FolkVoteDashboard extends HTMLElement {
|
|||
el.addEventListener("click", () => {
|
||||
const id = (el as HTMLElement).dataset.proposal!;
|
||||
this.view = "proposal";
|
||||
this.loadProposal(id);
|
||||
if (this.space === "demo") {
|
||||
this.selectedProposal = this.proposals.find((p) => p.id === id) || null;
|
||||
this.render();
|
||||
} else {
|
||||
this.loadProposal(id);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -41,10 +41,10 @@ async function seedDemoIfEmpty() {
|
|||
);
|
||||
const userId = user[0].id;
|
||||
|
||||
// Create voting space
|
||||
// Create voting space (matches standalone rVote settings)
|
||||
await sql.unsafe(
|
||||
`INSERT INTO rvote.spaces (slug, name, description, owner_did, visibility, promotion_threshold)
|
||||
VALUES ('community', 'Community Governance', 'Proposals for the rSpace ecosystem', 'did:demo:seed', 'public', 100)`
|
||||
`INSERT INTO rvote.spaces (slug, name, description, owner_did, visibility, promotion_threshold, voting_period_days, credits_per_day, max_credits, starting_credits)
|
||||
VALUES ('community', 'Community Governance', 'Proposals for the rSpace ecosystem', 'did:demo:seed', 'public_read', 100, 7, 10, 500, 50)`
|
||||
);
|
||||
|
||||
// Seed proposals in various states
|
||||
|
|
|
|||
|
|
@ -66,12 +66,16 @@ class FolkWalletViewer extends HTMLElement {
|
|||
this.address = "0x29567BdBcC92aCF37AC6B56B69180857bB69f7D1";
|
||||
this.detectedChains = [
|
||||
{ chainId: "1", name: "Ethereum", prefix: "eth", color: "#627eea" },
|
||||
{ chainId: "100", name: "Gnosis Chain", prefix: "gno", color: "#04795b" },
|
||||
{ chainId: "137", name: "Polygon", prefix: "matic", color: "#8247e5" },
|
||||
{ chainId: "10", name: "Optimism", prefix: "oeth", color: "#ff0420" },
|
||||
{ chainId: "100", name: "Gnosis", prefix: "gno", color: "#04795b" },
|
||||
{ chainId: "137", name: "Polygon", prefix: "pol", color: "#8247e5" },
|
||||
{ chainId: "8453", name: "Base", prefix: "base", color: "#0052ff" },
|
||||
{ chainId: "42161", name: "Arbitrum", prefix: "arb1", color: "#28a0f0" },
|
||||
{ chainId: "43114", name: "Avalanche", prefix: "avax", color: "#e84142" },
|
||||
];
|
||||
this.selectedChain = "100";
|
||||
this.balances = [
|
||||
{ tokenAddress: null, token: { name: "xDAI", symbol: "XDAI", decimals: 18 }, balance: "45230000000000000000000", fiatBalance: "45230", fiatConversion: "1" },
|
||||
{ tokenAddress: null, token: { name: "xDAI", symbol: "xDAI", decimals: 18 }, balance: "45230000000000000000000", fiatBalance: "45230", fiatConversion: "1" },
|
||||
{ tokenAddress: "0x5dF8339c5E282ee48c0c7cE252A7842F74e378b2", token: { name: "Token Engineering Commons", symbol: "TEC", decimals: 18 }, balance: "1250000000000000000000000", fiatBalance: "12500", fiatConversion: "0.01" },
|
||||
{ tokenAddress: "0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1", token: { name: "Wrapped Ether", symbol: "WETH", decimals: 18 }, balance: "8500000000000000000", fiatBalance: "28050", fiatConversion: "3300" },
|
||||
{ tokenAddress: "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83", token: { name: "USD Coin", symbol: "USDC", decimals: 6 }, balance: "15750000000", fiatBalance: "15750", fiatConversion: "1" },
|
||||
|
|
|
|||
|
|
@ -32,21 +32,21 @@ class FolkWorkBoard extends HTMLElement {
|
|||
|
||||
private loadDemoData() {
|
||||
this.isDemo = true;
|
||||
this.workspaces = [{ slug: "rspace-dev", name: "rSpace Development", icon: "\u{1F680}", task_count: 11, member_count: 4 }];
|
||||
this.workspaces = [{ slug: "rspace-dev", name: "rSpace Development", icon: "\u{1F680}", task_count: 11, member_count: 2 }];
|
||||
this.view = "board";
|
||||
this.workspaceSlug = "rspace-dev";
|
||||
this.tasks = [
|
||||
{ id: "d1", title: "Add dark theme toggle", status: "TODO", priority: "NORMAL", labels: ["frontend"] },
|
||||
{ id: "d2", title: "Write API docs", status: "TODO", priority: "NORMAL", labels: ["backend", "docs"] },
|
||||
{ id: "d3", title: "Set up CI pipeline", status: "TODO", priority: "NORMAL", labels: ["devops"] },
|
||||
{ id: "d4", title: "Port canvas to WebGL", status: "IN_PROGRESS", priority: "NORMAL", labels: ["frontend"] },
|
||||
{ id: "d5", title: "Implement search API", status: "IN_PROGRESS", priority: "HIGH", labels: ["backend"] },
|
||||
{ id: "d6", title: "Design mobile nav", status: "IN_PROGRESS", priority: "NORMAL", labels: ["frontend", "design"] },
|
||||
{ id: "d7", title: "Fix WebSocket reconnection", status: "REVIEW", priority: "URGENT", labels: ["backend"] },
|
||||
{ id: "d8", title: "Add rate limiting", status: "REVIEW", priority: "NORMAL", labels: ["backend", "security"] },
|
||||
{ id: "d9", title: "Deploy auth service", status: "DONE", priority: "NORMAL", labels: ["devops"] },
|
||||
{ id: "d10", title: "Set up monitoring", status: "DONE", priority: "NORMAL", labels: ["devops"] },
|
||||
{ id: "d11", title: "Create landing page", status: "DONE", priority: "NORMAL", labels: ["frontend", "design"] },
|
||||
{ id: "d1", title: "Add dark mode toggle to settings page", status: "TODO", priority: "MEDIUM", labels: ["feature"], assignee: "Alice" },
|
||||
{ id: "d2", title: "Write API documentation for rPubs endpoints", status: "TODO", priority: "LOW", labels: ["docs"], assignee: "Bob" },
|
||||
{ id: "d3", title: "Investigate slow PDF generation on large documents", status: "TODO", priority: "HIGH", labels: ["bug"], assignee: "Alice" },
|
||||
{ id: "d4", title: "Implement file search and filtering in rFiles", status: "IN_PROGRESS", priority: "HIGH", labels: ["feature"], assignee: "Alice" },
|
||||
{ id: "d5", title: "Set up SMTP relay for transactional notifications", status: "IN_PROGRESS", priority: "MEDIUM", labels: ["chore"], assignee: "Bob" },
|
||||
{ id: "d6", title: "Add PDF export to rNotes notebooks", status: "REVIEW", priority: "MEDIUM", labels: ["feature"], assignee: "Bob" },
|
||||
{ id: "d7", title: "Fix conviction score decay calculation in rVote", status: "REVIEW", priority: "HIGH", labels: ["bug"], assignee: "Alice" },
|
||||
{ id: "d8", title: "Deploy EncryptID passkey authentication", status: "DONE", priority: "URGENT", labels: ["feature"], assignee: "Alice" },
|
||||
{ id: "d9", title: "Set up Cloudflare tunnel for all r* domains", status: "DONE", priority: "HIGH", labels: ["chore"], assignee: "Bob" },
|
||||
{ id: "d10", title: "Create cosmolocal provider directory with 6 printers", status: "DONE", priority: "MEDIUM", labels: ["feature"], assignee: "Alice" },
|
||||
{ id: "d11", title: "Migrate email from Resend to self-hosted Mailcow", status: "DONE", priority: "MEDIUM", labels: ["chore"], assignee: "Bob" },
|
||||
];
|
||||
this.render();
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ class FolkWorkBoard extends HTMLElement {
|
|||
const title = prompt("Task title:");
|
||||
if (!title?.trim()) return;
|
||||
if (this.isDemo) {
|
||||
this.tasks.push({ id: `d${Date.now()}`, title: title.trim(), status: "TODO", priority: "NORMAL", labels: [] });
|
||||
this.tasks.push({ id: `d${Date.now()}`, title: title.trim(), status: "TODO", priority: "MEDIUM", labels: [] });
|
||||
this.render();
|
||||
return;
|
||||
}
|
||||
|
|
@ -188,6 +188,8 @@ class FolkWorkBoard extends HTMLElement {
|
|||
.badge { font-size: 10px; padding: 2px 6px; border-radius: 4px; background: #2a2a3a; color: #aaa; }
|
||||
.badge-urgent { background: #3b1111; color: #f87171; }
|
||||
.badge-high { background: #3b2611; color: #fb923c; }
|
||||
.badge-medium { background: #3b3511; color: #facc15; }
|
||||
.badge-low { background: #112a3b; color: #60a5fa; }
|
||||
|
||||
.move-btns { display: flex; gap: 4px; margin-top: 6px; }
|
||||
.move-btn { font-size: 10px; padding: 2px 6px; border-radius: 4px; border: 1px solid #333; background: #16161e; color: #888; cursor: pointer; }
|
||||
|
|
@ -253,14 +255,18 @@ class FolkWorkBoard extends HTMLElement {
|
|||
|
||||
private renderTaskCard(task: any, currentStatus: string): string {
|
||||
const otherStatuses = this.statuses.filter(s => s !== currentStatus);
|
||||
const priorityBadge = (p: string) => {
|
||||
const map: Record<string, string> = { URGENT: "badge-urgent", HIGH: "badge-high", MEDIUM: "badge-medium", LOW: "badge-low" };
|
||||
return map[p] ? `<span class="badge ${map[p]}">${this.esc(p.toLowerCase())}</span>` : "";
|
||||
};
|
||||
return `
|
||||
<div class="task-card" draggable="true" data-task-id="${task.id}">
|
||||
<div class="task-title">${this.esc(task.title)}</div>
|
||||
<div class="task-meta">
|
||||
${task.priority === "URGENT" ? '<span class="badge badge-urgent">URGENT</span>' : ""}
|
||||
${task.priority === "HIGH" ? '<span class="badge badge-high">HIGH</span>' : ""}
|
||||
${priorityBadge(task.priority || "")}
|
||||
${(task.labels || []).map((l: string) => `<span class="badge">${this.esc(l)}</span>`).join("")}
|
||||
</div>
|
||||
${task.assignee ? `<div style="font-size:11px;color:#888;margin-top:4px">${this.esc(task.assignee)}</div>` : ""}
|
||||
<div class="move-btns">
|
||||
${otherStatuses.map(s => `<button class="move-btn" data-move="${task.id}" data-to="${s}">→ ${this.esc(s.replace(/_/g, " ").substring(0, 8))}</button>`).join("")}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ import { photosModule } from "../modules/photos/mod";
|
|||
import { socialsModule } from "../modules/rsocials/mod";
|
||||
import { spaces } from "./spaces";
|
||||
import { renderShell, renderModuleLanding } from "./shell";
|
||||
import { renderMainLanding } from "./landing";
|
||||
import { renderMainLanding, renderSpaceDashboard } from "./landing";
|
||||
import { fetchLandingPage } from "./landing-proxy";
|
||||
import { syncServer } from "./sync-instance";
|
||||
import { loadAllDocs } from "./local-first/doc-persistence";
|
||||
|
|
@ -844,12 +844,12 @@ app.get("/admin", async (c) => {
|
|||
return c.text("Admin", 200);
|
||||
});
|
||||
|
||||
// Space root: /:space → redirect to /:space/rspace
|
||||
// Space root: /:space → space dashboard
|
||||
app.get("/:space", (c) => {
|
||||
const space = c.req.param("space");
|
||||
// Don't redirect for static file paths
|
||||
// Don't serve dashboard for static file paths
|
||||
if (space.includes(".")) return c.notFound();
|
||||
return c.redirect(`/${space}/rspace`);
|
||||
return c.html(renderSpaceDashboard(space, getModuleInfoList()));
|
||||
});
|
||||
|
||||
// ── WebSocket types ──
|
||||
|
|
@ -1101,9 +1101,11 @@ const server = Bun.serve<WSData>({
|
|||
if (subdomain) {
|
||||
const pathSegments = url.pathname.split("/").filter(Boolean);
|
||||
|
||||
// Root: redirect to default module (rspace)
|
||||
// Root: show space dashboard
|
||||
if (pathSegments.length === 0) {
|
||||
return Response.redirect(`${url.protocol}//${host}/rspace`, 302);
|
||||
return new Response(renderSpaceDashboard(subdomain, getModuleInfoList()), {
|
||||
headers: { "Content-Type": "text/html" },
|
||||
});
|
||||
}
|
||||
|
||||
// Global routes pass through without subdomain prefix
|
||||
|
|
|
|||
|
|
@ -241,6 +241,147 @@ export function renderMainLanding(modules: ModuleInfo[]): string {
|
|||
</html>`;
|
||||
}
|
||||
|
||||
// ── Space Dashboard ──
|
||||
|
||||
export function renderSpaceDashboard(space: string, modules: ModuleInfo[]): string {
|
||||
const moduleListJSON = JSON.stringify(modules);
|
||||
const displayName = space === "demo" ? "Demo Space" : space;
|
||||
const subtitle = space === "demo"
|
||||
? "Explore the rSpace ecosystem — click any rApp to try it live with sample data."
|
||||
: `${modules.length} rApps available in this space.`;
|
||||
|
||||
const appCards = modules
|
||||
.map((m) => {
|
||||
const href = `/${escapeAttr(space)}/${escapeAttr(m.id)}`;
|
||||
return `
|
||||
<a href="${href}" class="sd-card">
|
||||
<div class="sd-card__icon">${m.icon}</div>
|
||||
<div class="sd-card__body">
|
||||
<h3 class="sd-card__name">${escapeHtml(m.name)}</h3>
|
||||
<p class="sd-card__desc">${escapeHtml(m.description)}</p>
|
||||
</div>
|
||||
</a>`;
|
||||
})
|
||||
.join("\n");
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🌌</text></svg>">
|
||||
<title>${escapeHtml(displayName)} | rSpace</title>
|
||||
<link rel="stylesheet" href="/shell.css">
|
||||
<style>${MODULE_LANDING_CSS}</style>
|
||||
<style>${SPACE_DASHBOARD_CSS}</style>
|
||||
<script defer src="https://rdata.online/collect.js" data-website-id="6ee7917b-0ed7-44cb-a4c8-91037638526b"></script>
|
||||
</head>
|
||||
<body data-theme="dark">
|
||||
<header class="rstack-header" data-theme="dark">
|
||||
<div class="rstack-header__left">
|
||||
<a href="/" style="display:flex;align-items:center;margin-right:4px"><img src="/favicon.png" alt="rSpace" class="rstack-header__logo"></a>
|
||||
<rstack-app-switcher current=""></rstack-app-switcher>
|
||||
<rstack-space-switcher current="${escapeAttr(space)}" name="${escapeAttr(displayName)}"></rstack-space-switcher>
|
||||
</div>
|
||||
<div class="rstack-header__center">
|
||||
<rstack-mi></rstack-mi>
|
||||
</div>
|
||||
<div class="rstack-header__right">
|
||||
<rstack-identity></rstack-identity>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="sd-hero">
|
||||
<h1 class="sd-hero__title">${escapeHtml(displayName)}</h1>
|
||||
<p class="sd-hero__subtitle">${subtitle}</p>
|
||||
</div>
|
||||
|
||||
<div class="sd-container">
|
||||
<div class="sd-grid">
|
||||
${appCards}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${space === "demo" ? `
|
||||
<div class="sd-footer">
|
||||
<p>Want your own space? <a href="/create-space">Create one</a> — it’s free and instant.</p>
|
||||
</div>` : ""}
|
||||
|
||||
<script type="module">
|
||||
import '/shell.js';
|
||||
document.querySelector('rstack-app-switcher')?.setModules(${moduleListJSON});
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
const SPACE_DASHBOARD_CSS = `
|
||||
.sd-hero {
|
||||
text-align: center;
|
||||
padding: 100px 1.5rem 2rem;
|
||||
}
|
||||
.sd-hero__title {
|
||||
font-size: 2.25rem; font-weight: 700; margin: 0 0 0.5rem;
|
||||
background: linear-gradient(135deg, #14b8a6, #22d3ee);
|
||||
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
.sd-hero__subtitle {
|
||||
font-size: 1.05rem; color: #94a3b8; margin: 0;
|
||||
max-width: 520px; margin: 0 auto; line-height: 1.5;
|
||||
}
|
||||
.sd-container {
|
||||
max-width: 1100px; margin: 0 auto;
|
||||
padding: 1rem 1.5rem 3rem;
|
||||
}
|
||||
.sd-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.sd-card {
|
||||
display: flex; align-items: flex-start; gap: 1rem;
|
||||
padding: 1rem 1.25rem;
|
||||
background: rgba(255,255,255,0.025);
|
||||
border: 1px solid rgba(255,255,255,0.06);
|
||||
border-radius: 0.75rem;
|
||||
text-decoration: none; color: inherit;
|
||||
transition: border-color 0.2s, background 0.2s, transform 0.15s;
|
||||
cursor: pointer;
|
||||
}
|
||||
.sd-card:hover {
|
||||
border-color: rgba(20,184,166,0.35);
|
||||
background: rgba(20,184,166,0.04);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.sd-card__icon {
|
||||
font-size: 1.75rem; flex-shrink: 0;
|
||||
width: 2.5rem; height: 2.5rem;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
}
|
||||
.sd-card__body { min-width: 0; }
|
||||
.sd-card__name {
|
||||
font-size: 0.9rem; font-weight: 600; color: #e2e8f0;
|
||||
margin: 0 0 0.2rem;
|
||||
}
|
||||
.sd-card__desc {
|
||||
font-size: 0.78rem; color: #64748b; margin: 0;
|
||||
line-height: 1.45;
|
||||
}
|
||||
.sd-footer {
|
||||
text-align: center; padding: 2rem 1.5rem 3rem;
|
||||
border-top: 1px solid rgba(255,255,255,0.06);
|
||||
}
|
||||
.sd-footer p { color: #64748b; font-size: 0.9rem; margin: 0; }
|
||||
.sd-footer a { color: #14b8a6; text-decoration: none; font-weight: 600; }
|
||||
.sd-footer a:hover { text-decoration: underline; }
|
||||
@media (max-width: 480px) {
|
||||
.sd-grid { grid-template-columns: 1fr; }
|
||||
.sd-hero__title { font-size: 1.75rem; }
|
||||
.sd-hero { padding-top: 80px; }
|
||||
}
|
||||
`;
|
||||
|
||||
const MAIN_LANDING_CSS = `
|
||||
/* Main landing page extras (on top of rl-* utilities) */
|
||||
.main-wordmark {
|
||||
|
|
|
|||
Loading…
Reference in New Issue