diff --git a/package.json b/package.json index 0b5bf24..fdbb9be 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@atcute/tid": "^1.1.1", "@cloudflare/workers-types": "^4.20260123.0", "@ethercorps/sveltekit-og": "^4.2.1", + "@foxui/3d": "^0.4.7", "@foxui/colors": "^0.4.7", "@foxui/core": "^0.4.7", "@foxui/social": "^0.4.7", @@ -57,6 +58,8 @@ "@foxui/visual": "^0.4.7", "@number-flow/svelte": "^0.3.10", "@tailwindcss/typography": "^0.5.19", + "@threlte/core": "^8.3.1", + "@threlte/extras": "^9.7.1", "@tiptap/core": "^3.16.0", "@tiptap/extension-document": "^3.16.0", "@tiptap/extension-image": "^3.16.0", @@ -65,6 +68,7 @@ "@tiptap/extension-placeholder": "^3.16.0", "@tiptap/extension-text": "^3.16.0", "@tiptap/starter-kit": "^3.16.0", + "@types/three": "^0.176.0", "bits-ui": "^2.15.4", "clsx": "^2.1.1", "gsap": "^3.14.2", @@ -80,6 +84,7 @@ "svelte-sonner": "^1.0.7", "tailwind-merge": "^3.4.0", "tailwind-variants": "^3.2.2", + "three": "^0.176.0", "turndown": "^7.2.2", "wrangler": "^4.60.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb68836..bbbed09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: '@ethercorps/sveltekit-og': specifier: ^4.2.1 version: 4.2.1(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2))) + '@foxui/3d': + specifier: ^0.4.7 + version: 0.4.7(svelte@5.48.0)(tailwindcss@4.1.18) '@foxui/colors': specifier: ^0.4.7 version: 0.4.7(svelte@5.48.0)(tailwindcss@4.1.18) @@ -62,6 +65,12 @@ importers: '@tailwindcss/typography': specifier: ^0.5.19 version: 0.5.19(tailwindcss@4.1.18) + '@threlte/core': + specifier: ^8.3.1 + version: 8.3.1(svelte@5.48.0)(three@0.176.0) + '@threlte/extras': + specifier: ^9.7.1 + version: 9.7.1(@types/three@0.176.0)(svelte@5.48.0)(three@0.176.0) '@tiptap/core': specifier: ^3.16.0 version: 3.16.0(@tiptap/pm@3.16.0) @@ -86,6 +95,9 @@ importers: '@tiptap/starter-kit': specifier: ^3.16.0 version: 3.16.0 + '@types/three': + specifier: ^0.176.0 + version: 0.176.0 bits-ui: specifier: ^2.15.4 version: 2.15.4(@internationalized/date@3.10.1)(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.0)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.6.1)(lightningcss@1.30.2)))(svelte@5.48.0) @@ -131,6 +143,9 @@ importers: tailwind-variants: specifier: ^3.2.2 version: 3.2.2(tailwind-merge@3.4.0)(tailwindcss@4.1.18) + three: + specifier: ^0.176.0 + version: 0.176.0 turndown: specifier: ^7.2.2 version: 7.2.2 @@ -329,6 +344,9 @@ packages: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} + '@dimforge/rapier3d-compat@0.12.0': + resolution: {integrity: sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==} + '@emnapi/runtime@1.8.1': resolution: {integrity: sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==} @@ -709,6 +727,12 @@ packages: '@floating-ui/utils@0.2.10': resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + '@foxui/3d@0.4.7': + resolution: {integrity: sha512-6aFWbdvMPbVqvRlr1gc438RoWE/1+B7/dB1b682tl+K1ycMhWkgMzicckxafLY2A1haOv8bgAArZJ+Lt63RMNg==} + peerDependencies: + svelte: '>=5' + tailwindcss: '>=3' + '@foxui/colors@0.4.7': resolution: {integrity: sha512-P40GBuwerikysWctVL1KSUrjxzlAf5j1jZ0z6+pzkWdfTv8wGxXlJcvJCkA1MkTeatLkyBrHLrIF17u2iRrMkw==} peerDependencies: @@ -1313,6 +1337,23 @@ packages: '@texel/color@1.1.11': resolution: {integrity: sha512-/3kKgfBqzrRfLl4RsEccx+Yfj1kVL6Bh6DejVWZ+DPg/jJdcfdYZ5fpD1nXFwWd8OQNATjz+WqsfQfUynSsgRg==} + '@threejs-kit/instanced-sprite-mesh@2.5.1': + resolution: {integrity: sha512-pmt1ALRhbHhCJQTj2FuthH6PeLIeaM4hOuS2JO3kWSwlnvx/9xuUkjFR3JOi/myMqsH7pSsLIROSaBxDfttjeA==} + peerDependencies: + three: '>=0.170.0' + + '@threlte/core@8.3.1': + resolution: {integrity: sha512-qKjjNCQ+40hyeBcfOMh/8ef5x/j5PG5Wmo/L9Ye0aDCcdD6fCewWxfp7tV/J3CxPzX1dEp1JGK7sjyc7ntZSrg==} + peerDependencies: + svelte: '>=5' + three: '>=0.160' + + '@threlte/extras@9.7.1': + resolution: {integrity: sha512-SGm59HDCdHxADFHuweHfFDknwubkCPodyK0pbfsVtOWWOX26gE2xfK7aKolh6YFDiPAjWjGxN0jIgkNbbr1ohg==} + peerDependencies: + svelte: '>=5' + three: '>=0.160' + '@tiptap/core@3.16.0': resolution: {integrity: sha512-XegRaNuoQ/guzBQU2xHxOwFXXrtoXW9tiyXDhssSqylvZmBVSlRIPNHA6ArkHBKm6ehLf6+6Y9fF3uky1yCXYQ==} peerDependencies: @@ -1449,6 +1490,9 @@ packages: '@tiptap/starter-kit@3.16.0': resolution: {integrity: sha512-eWi+77SgKyhSx91Hmn32ER+gPN6FfInGtod4A+XxSG+LqS/sn6kpUEdowYrnqiZzhUXZCSTSJvC+UcMUZHOkxQ==} + '@tweenjs/tween.js@23.1.3': + resolution: {integrity: sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==} + '@types/bun@1.3.6': resolution: {integrity: sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA==} @@ -1485,12 +1529,21 @@ packages: '@types/pbf@3.0.5': resolution: {integrity: sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==} + '@types/stats.js@0.17.4': + resolution: {integrity: sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==} + '@types/supercluster@7.1.3': resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==} + '@types/three@0.176.0': + resolution: {integrity: sha512-FwfPXxCqOtP7EdYMagCFePNKoG1AGBDUEVKtluv2BTVRpSt7b+X27xNsirPCTCqY1pGYsPUzaM3jgWP7dXSxlw==} + '@types/turndown@5.0.6': resolution: {integrity: sha512-ru00MoyeeouE5BX4gRL+6m/BsDfbRayOskWqUvh7CLGW+UXxHQItqALa38kKnOiZPqJrtzJUgAC2+F0rL1S4Pg==} + '@types/webxr@0.5.24': + resolution: {integrity: sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==} + '@typescript-eslint/eslint-plugin@8.53.1': resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1556,6 +1609,9 @@ packages: '@use-gesture/vanilla@10.3.1': resolution: {integrity: sha512-lT4scGLu59ovA3zmtUonukAGcA0AdOOh+iwNDS05Bsu7Lq9aZToDHhI6D8Q2qvsVraovtsLLYwPrWdG/noMAKw==} + '@webgpu/types@0.1.69': + resolution: {integrity: sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1594,6 +1650,9 @@ packages: resolution: {integrity: sha512-3XSA2cR/h/73EzlXXdU6YNycmYI7+kicTxks4eJg2g39biHR84slg2+des+p7iHYhbRg/udIS4TD53WabcOUkw==} engines: {node: '>= 0.4'} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + bits-ui@1.8.0: resolution: {integrity: sha512-CXD6Orp7l8QevNDcRPLXc/b8iMVgxDWT2LyTwsdLzJKh9CxesOmPuNePSPqAxKoT59FIdU4aFPS1k7eBdbaCxg==} engines: {node: '>=18', pnpm: '>=8.7.0'} @@ -1629,6 +1688,12 @@ packages: camelize@1.0.1: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + camera-controls@3.1.2: + resolution: {integrity: sha512-xkxfpG2ECZ6Ww5/9+kf4mfg1VEYAoe9aDSY+IwF0UEs7qEzwy0aVRfs2grImIECs/PoBtWFrh7RXsQkwG922JA==} + engines: {node: '>=22.0.0', npm: '>=10.5.1'} + peerDependencies: + three: '>=0.126.1' + canvas-confetti@1.9.4: resolution: {integrity: sha512-yxQbJkAVrFXWNbTUjPqjF7G+g6pDotOUHGbkZq2NELZUMDpiJ85rIEazVb8GTaAptNW2miJAXbs1BtioA251Pw==} @@ -1753,6 +1818,9 @@ packages: devalue@5.6.2: resolution: {integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==} + diet-sprite@0.0.1: + resolution: {integrity: sha512-zSHI2WDAn1wJqJYxcmjWfJv3Iw8oL9reQIbEyx2x2/EZ4/qmUTIo8/5qOCurnAcq61EwtJJaZ0XTy2NRYqpB5A==} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -1766,6 +1834,9 @@ packages: domutils@3.2.2: resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} + earcut@2.2.4: + resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==} + earcut@3.0.2: resolution: {integrity: sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==} @@ -1902,6 +1973,9 @@ packages: fflate@0.7.4: resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -2157,6 +2231,12 @@ packages: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true + maath@0.10.8: + resolution: {integrity: sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==} + peerDependencies: + '@types/three': '>=0.134.0' + three: '>=0.134.0' + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -2178,6 +2258,9 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + meshoptimizer@0.18.1: + resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==} + mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} hasBin: true @@ -2194,6 +2277,9 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} @@ -2518,6 +2604,10 @@ packages: resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} engines: {node: '>=8'} + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -2708,6 +2798,29 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + three-instanced-uniforms-mesh@0.52.4: + resolution: {integrity: sha512-YwDBy05hfKZQtU+Rp0KyDf9yH4GxfhxMbVt9OYruxdgLfPwmDG5oAbGoW0DrKtKZSM3BfFcCiejiOHCjFBTeng==} + peerDependencies: + three: '>=0.125.0' + + three-mesh-bvh@0.9.7: + resolution: {integrity: sha512-EYSJbykeAjhVxwZjuUYq/kelIbqBoV9sbAgvZ+j1xCgZyNYSkr51WDJWS4WIfK2OX6YcjBGoTicX4RoOVQzx0g==} + peerDependencies: + three: '>= 0.159.0' + + three-perf@1.0.11: + resolution: {integrity: sha512-OgBpZjwL+csQKGKZjpkH/QHdbGFMxqngMbSEJeSnVNfXDYd6On7WHNv/GhUZH4YxIpNMwMahBWrNnsJvnbSJHQ==} + peerDependencies: + three: '>=0.170' + + three-viewport-gizmo@2.2.0: + resolution: {integrity: sha512-Jo9Liur1rUmdKk75FZumLU/+hbF+RtJHi1qsKZpntjKlCYScK6tjbYoqvJ9M+IJphrlQJF5oReFW7Sambh0N4Q==} + peerDependencies: + three: '>=0.162.0 <1.0.0' + + three@0.176.0: + resolution: {integrity: sha512-PWRKYWQo23ojf9oZSlRGH8K09q7nRSWx6LY/HF/UUrMdYgN9i1e2OwJYHoQjwc6HF/4lvvYLC5YC1X8UJL2ZpA==} + tiny-inflate@1.0.3: resolution: {integrity: sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==} @@ -2726,6 +2839,19 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + troika-three-text@0.52.4: + resolution: {integrity: sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg==} + peerDependencies: + three: '>=0.125.0' + + troika-three-utils@0.52.4: + resolution: {integrity: sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A==} + peerDependencies: + three: '>=0.125.0' + + troika-worker-utils@0.52.0: + resolution: {integrity: sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==} + ts-api-utils@2.4.0: resolution: {integrity: sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==} engines: {node: '>=18.12'} @@ -2738,6 +2864,9 @@ packages: turndown@7.2.2: resolution: {integrity: sha512-1F7db8BiExOKxjSMU2b7if62D/XOyQyZbPKq/nUwopfgnHlqXHqQ0lvfUTeUIr1lZJzOPFn43dODyMSIfvWRKQ==} + tweakpane@3.1.10: + resolution: {integrity: sha512-rqwnl/pUa7+inhI2E9ayGTqqP0EPOOn/wVvSWjZsRbZUItzNShny7pzwL3hVlaN4m9t/aZhsP0aFQ9U5VVR2VQ==} + type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -2849,6 +2978,9 @@ packages: w3c-keyname@2.2.8: resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + webgl-sdf-generator@1.1.1: + resolution: {integrity: sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==} + whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -3078,6 +3210,8 @@ snapshots: dependencies: '@jridgewell/trace-mapping': 0.3.9 + '@dimforge/rapier3d-compat@0.12.0': {} + '@emnapi/runtime@1.8.1': dependencies: tslib: 2.8.1 @@ -3318,6 +3452,17 @@ snapshots: '@floating-ui/utils@0.2.10': {} + '@foxui/3d@0.4.7(svelte@5.48.0)(tailwindcss@4.1.18)': + dependencies: + '@foxui/core': 0.4.7(svelte@5.48.0)(tailwindcss@4.1.18) + '@threlte/core': 8.3.1(svelte@5.48.0)(three@0.176.0) + '@threlte/extras': 9.7.1(@types/three@0.176.0)(svelte@5.48.0)(three@0.176.0) + '@types/three': 0.176.0 + bits-ui: 1.8.0(svelte@5.48.0) + svelte: 5.48.0 + tailwindcss: 4.1.18 + three: 0.176.0 + '@foxui/colors@0.4.7(svelte@5.48.0)(tailwindcss@4.1.18)': dependencies: '@foxui/core': 0.4.7(svelte@5.48.0)(tailwindcss@4.1.18) @@ -3814,6 +3959,36 @@ snapshots: '@texel/color@1.1.11': {} + '@threejs-kit/instanced-sprite-mesh@2.5.1(@types/three@0.176.0)(three@0.176.0)': + dependencies: + diet-sprite: 0.0.1 + earcut: 2.2.4 + maath: 0.10.8(@types/three@0.176.0)(three@0.176.0) + three: 0.176.0 + three-instanced-uniforms-mesh: 0.52.4(three@0.176.0) + troika-three-utils: 0.52.4(three@0.176.0) + transitivePeerDependencies: + - '@types/three' + + '@threlte/core@8.3.1(svelte@5.48.0)(three@0.176.0)': + dependencies: + mitt: 3.0.1 + svelte: 5.48.0 + three: 0.176.0 + + '@threlte/extras@9.7.1(@types/three@0.176.0)(svelte@5.48.0)(three@0.176.0)': + dependencies: + '@threejs-kit/instanced-sprite-mesh': 2.5.1(@types/three@0.176.0)(three@0.176.0) + camera-controls: 3.1.2(three@0.176.0) + svelte: 5.48.0 + three: 0.176.0 + three-mesh-bvh: 0.9.7(three@0.176.0) + three-perf: 1.0.11(three@0.176.0) + three-viewport-gizmo: 2.2.0(three@0.176.0) + troika-three-text: 0.52.4(three@0.176.0) + transitivePeerDependencies: + - '@types/three' + '@tiptap/core@3.16.0(@tiptap/pm@3.16.0)': dependencies: '@tiptap/pm': 3.16.0 @@ -3968,6 +4143,8 @@ snapshots: '@tiptap/extensions': 3.16.0(@tiptap/core@3.16.0(@tiptap/pm@3.16.0))(@tiptap/pm@3.16.0) '@tiptap/pm': 3.16.0 + '@tweenjs/tween.js@23.1.3': {} + '@types/bun@1.3.6': dependencies: bun-types: 1.3.6 @@ -4001,12 +4178,26 @@ snapshots: '@types/pbf@3.0.5': {} + '@types/stats.js@0.17.4': {} + '@types/supercluster@7.1.3': dependencies: '@types/geojson': 7946.0.16 + '@types/three@0.176.0': + dependencies: + '@dimforge/rapier3d-compat': 0.12.0 + '@tweenjs/tween.js': 23.1.3 + '@types/stats.js': 0.17.4 + '@types/webxr': 0.5.24 + '@webgpu/types': 0.1.69 + fflate: 0.8.2 + meshoptimizer: 0.18.1 + '@types/turndown@5.0.6': {} + '@types/webxr@0.5.24': {} + '@typescript-eslint/eslint-plugin@8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -4104,6 +4295,8 @@ snapshots: dependencies: '@use-gesture/core': 10.3.1 + '@webgpu/types@0.1.69': {} + acorn-jsx@5.3.2(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -4133,6 +4326,10 @@ snapshots: base64-js@0.0.8: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + bits-ui@1.8.0(svelte@5.48.0): dependencies: '@floating-ui/core': 1.7.3 @@ -4179,6 +4376,10 @@ snapshots: camelize@1.0.1: {} + camera-controls@3.1.2(three@0.176.0): + dependencies: + three: 0.176.0 + canvas-confetti@1.9.4: {} chalk@4.1.2: @@ -4298,6 +4499,8 @@ snapshots: devalue@5.6.2: {} + diet-sprite@0.0.1: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -4316,6 +4519,8 @@ snapshots: domelementtype: 2.3.0 domhandler: 5.0.3 + earcut@2.2.4: {} + earcut@3.0.2: {} emoji-picker-element@1.28.1: {} @@ -4512,6 +4717,8 @@ snapshots: fflate@0.7.4: {} + fflate@0.8.2: {} + file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -4713,6 +4920,11 @@ snapshots: lz-string@1.5.0: {} + maath@0.10.8(@types/three@0.176.0)(three@0.176.0): + dependencies: + '@types/three': 0.176.0 + three: 0.176.0 + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -4765,6 +4977,8 @@ snapshots: mdurl@2.0.0: {} + meshoptimizer@0.18.1: {} + mini-svg-data-uri@1.4.4: {} miniflare@4.20260120.0: @@ -4788,6 +5002,8 @@ snapshots: dependencies: brace-expansion: 2.0.2 + mitt@3.0.1: {} + mlly@1.8.0: dependencies: acorn: 8.15.0 @@ -5083,6 +5299,8 @@ snapshots: regexparam@3.0.0: {} + require-from-string@2.0.2: {} + resolve-from@4.0.0: {} resolve-protobuf-schema@2.1.0: @@ -5331,6 +5549,27 @@ snapshots: tapable@2.3.0: {} + three-instanced-uniforms-mesh@0.52.4(three@0.176.0): + dependencies: + three: 0.176.0 + troika-three-utils: 0.52.4(three@0.176.0) + + three-mesh-bvh@0.9.7(three@0.176.0): + dependencies: + three: 0.176.0 + + three-perf@1.0.11(three@0.176.0): + dependencies: + three: 0.176.0 + troika-three-text: 0.52.4(three@0.176.0) + tweakpane: 3.1.10 + + three-viewport-gizmo@2.2.0(three@0.176.0): + dependencies: + three: 0.176.0 + + three@0.176.0: {} + tiny-inflate@1.0.3: {} tinyglobby@0.2.15: @@ -5344,6 +5583,20 @@ snapshots: totalist@3.0.1: {} + troika-three-text@0.52.4(three@0.176.0): + dependencies: + bidi-js: 1.0.3 + three: 0.176.0 + troika-three-utils: 0.52.4(three@0.176.0) + troika-worker-utils: 0.52.0 + webgl-sdf-generator: 1.1.1 + + troika-three-utils@0.52.4(three@0.176.0): + dependencies: + three: 0.176.0 + + troika-worker-utils@0.52.0: {} + ts-api-utils@2.4.0(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -5354,6 +5607,8 @@ snapshots: dependencies: '@mixmark-io/domino': 2.2.0 + tweakpane@3.1.10: {} + type-check@0.4.0: dependencies: prelude-ls: 1.2.1 @@ -5435,6 +5690,8 @@ snapshots: w3c-keyname@2.2.8: {} + webgl-sdf-generator@1.1.1: {} + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 diff --git a/src/lib/cards/Model3DCard/CreateModel3DCardModal.svelte b/src/lib/cards/Model3DCard/CreateModel3DCardModal.svelte new file mode 100644 index 0000000..b5898ed --- /dev/null +++ b/src/lib/cards/Model3DCard/CreateModel3DCardModal.svelte @@ -0,0 +1,103 @@ + + + + Add a 3D Model + +
+

+ Upload a 3D model file (.glb, .stl, .fbx, or .gltf) +

+ {#if item.cardData.modelFile} +
+ {item.cardData.modelFile.name} + +
+ {:else} + + + {/if} +
+ + {#if errorMessage} + {errorMessage} + {/if} + +
+ + +
+
diff --git a/src/lib/cards/Model3DCard/Model3DCard.svelte b/src/lib/cards/Model3DCard/Model3DCard.svelte new file mode 100644 index 0000000..2181aac --- /dev/null +++ b/src/lib/cards/Model3DCard/Model3DCard.svelte @@ -0,0 +1,74 @@ + + + diff --git a/src/lib/cards/Model3DCard/Model3DScene.svelte b/src/lib/cards/Model3DCard/Model3DScene.svelte new file mode 100644 index 0000000..9d0bbab --- /dev/null +++ b/src/lib/cards/Model3DCard/Model3DScene.svelte @@ -0,0 +1,161 @@ + + + + + + + + + + + {#if modelType === 'stl'} + {#if stlLoaded && stlMesh} + + {/if} + {:else if modelType === 'fbx'} + {#if fbxLoaded && fbxGroup} + + {/if} + {:else} + + + + {/if} + diff --git a/src/lib/cards/Model3DCard/index.ts b/src/lib/cards/Model3DCard/index.ts new file mode 100644 index 0000000..3ad0663 --- /dev/null +++ b/src/lib/cards/Model3DCard/index.ts @@ -0,0 +1,62 @@ +import { uploadBlob } from '$lib/atproto'; +import type { CardDefinition } from '../types'; +import CreateModel3DCardModal from './CreateModel3DCardModal.svelte'; +import Model3DCard from './Model3DCard.svelte'; + +export const Model3DCardDefinition = { + type: 'model3d', + contentComponent: Model3DCard, + creationModalComponent: CreateModel3DCardModal, + sidebarButtonText: '3D Model', + + createNew: (card) => { + card.w = 4; + card.h = 4; + card.mobileW = 4; + card.mobileH = 4; + card.cardData = { + modelType: 'gltf' // 'gltf' | 'stl' + }; + }, + + upload: async (item) => { + // Handle file upload + if (item.cardData.modelFile?.blob) { + let blob: Blob = item.cardData.modelFile.blob; + const modelType = item.cardData.modelFile.type || 'glb'; + + // Ensure blob has a MIME type (STL/FBX files often have empty type) + if (!blob.type) { + const mimeTypes: Record = { + stl: 'model/stl', + glb: 'model/gltf-binary', + gltf: 'model/gltf+json', + fbx: 'application/octet-stream' + }; + const mimeType = mimeTypes[modelType] || 'application/octet-stream'; + blob = new Blob([blob], { type: mimeType }); + } + + // Upload the blob to the PDS + const uploadedBlob = await uploadBlob({ blob }); + + if (uploadedBlob) { + item.cardData.modelBlob = uploadedBlob; + item.cardData.modelType = modelType; + } + + // Clean up the temporary file data + if (item.cardData.modelFile.objectUrl) { + URL.revokeObjectURL(item.cardData.modelFile.objectUrl); + } + delete item.cardData.modelFile; + } + + return item; + }, + + minW: 2, + minH: 2, + + name: '3D Model Card' +} as CardDefinition & { type: 'model3d' }; diff --git a/src/lib/cards/TimerCard/TimerCard.svelte b/src/lib/cards/TimerCard/TimerCard.svelte index effa268..ed6b84c 100644 --- a/src/lib/cards/TimerCard/TimerCard.svelte +++ b/src/lib/cards/TimerCard/TimerCard.svelte @@ -88,15 +88,15 @@ class="text-base-900 dark:text-base-100 accent:text-base-900 flex items-center text-3xl font-bold @xs:text-4xl @sm:text-5xl @md:text-6xl @lg:text-7xl" style="font-variant-numeric: tabular-nums;" > - - : + + : - : + : {#if eventDays > 0}
- - days + + days
{/if}
@@ -136,7 +133,7 @@ format={{ minimumIntegerDigits: 2 }} class="text-3xl font-bold @xs:text-4xl @sm:text-5xl @md:text-6xl @lg:text-7xl" /> - hrs + hrs
- min + min
- sec + sec
diff --git a/src/lib/cards/index.ts b/src/lib/cards/index.ts index b86875f..2c7e6f8 100644 --- a/src/lib/cards/index.ts +++ b/src/lib/cards/index.ts @@ -30,6 +30,7 @@ import { EventCardDefinition } from './EventCard'; import { VCardCardDefinition } from './VCardCard'; import { DrawCardDefinition } from './DrawCard'; import { TimerCardDefinition } from './TimerCard'; +import { Model3DCardDefinition } from './Model3DCard'; export const AllCardDefinitions = [ ImageCardDefinition, @@ -62,7 +63,8 @@ export const AllCardDefinitions = [ EventCardDefinition, VCardCardDefinition, DrawCardDefinition, - TimerCardDefinition + TimerCardDefinition, + Model3DCardDefinition ] as const; export const CardDefinitionsByType = AllCardDefinitions.reduce(