diff --git a/.github/workflows/build-core.yml b/.github/workflows/build-core.yml index b08c292cc..5050cde0f 100644 --- a/.github/workflows/build-core.yml +++ b/.github/workflows/build-core.yml @@ -99,6 +99,11 @@ jobs: cd packages/core bun run build:lib + - name: Build 3D package + run: | + cd packages/three + bun run build --ci + - name: Run TypeScript tests run: | cd packages/core diff --git a/.github/workflows/build-examples.yml b/.github/workflows/build-examples.yml index e0511e532..9ffe9b4c8 100644 --- a/.github/workflows/build-examples.yml +++ b/.github/workflows/build-examples.yml @@ -101,25 +101,25 @@ jobs: # Check for platform-specific packages in .bun cache (where bun install --os="*" --cpu="*" puts them) echo "" echo "Checking for platform-specific bun-webgpu packages in cache..." - if [ -d node_modules/.bun/bun-webgpu-darwin-arm64@0.1.4 ]; then + if [ -d node_modules/.bun/bun-webgpu-darwin-arm64@0.1.5 ]; then echo "✅ bun-webgpu-darwin-arm64 found in cache" else echo "⚠️ bun-webgpu-darwin-arm64 not found (will be installed during build)" fi - if [ -d node_modules/.bun/bun-webgpu-darwin-x64@0.1.4 ]; then + if [ -d node_modules/.bun/bun-webgpu-darwin-x64@0.1.5 ]; then echo "✅ bun-webgpu-darwin-x64 found in cache" else echo "⚠️ bun-webgpu-darwin-x64 not found (will be installed during build)" fi - if [ -d node_modules/.bun/bun-webgpu-linux-x64@0.1.4 ]; then + if [ -d node_modules/.bun/bun-webgpu-linux-x64@0.1.5 ]; then echo "✅ bun-webgpu-linux-x64 found in cache" else echo "⚠️ bun-webgpu-linux-x64 not found (will be installed during build)" fi - if [ -d node_modules/.bun/bun-webgpu-win32-x64@0.1.4 ]; then + if [ -d node_modules/.bun/bun-webgpu-win32-x64@0.1.5 ]; then echo "✅ bun-webgpu-win32-x64 found in cache" else echo "⚠️ bun-webgpu-win32-x64 not found (will be installed during build)" diff --git a/.github/workflows/build-native.yml b/.github/workflows/build-native.yml index 3e5cac5f8..f9e0117de 100644 --- a/.github/workflows/build-native.yml +++ b/.github/workflows/build-native.yml @@ -43,6 +43,8 @@ jobs: cd packages/core bun run build:native --all bun run build:lib + cd ../three + bun run build cd ../react bun run build cd ../solid @@ -155,6 +157,13 @@ jobs: # Copy other package dists (optional - don't fail if missing) echo "Packaging other packages..." + if [ -d packages/three/dist ]; then + cp -r packages/three/dist artifacts/npm-packages/three-dist + echo "✅ Three dist packaged" + else + echo "⚠️ Three dist not found (skipping)" + fi + if [ -d packages/react/dist ]; then cp -r packages/react/dist artifacts/npm-packages/react-dist echo "✅ React dist packaged" diff --git a/.github/workflows/npm-latest-release.yml b/.github/workflows/npm-latest-release.yml index 427f75b42..c5e06c3e1 100644 --- a/.github/workflows/npm-latest-release.yml +++ b/.github/workflows/npm-latest-release.yml @@ -62,6 +62,11 @@ jobs: fi # Copy other package dists + if [ -d "npm-packages/three-dist" ]; then + cp -r npm-packages/three-dist packages/three/dist + echo "Copied three dist" + fi + if [ -d "npm-packages/react-dist" ]; then cp -r npm-packages/react-dist packages/react/dist echo "Copied react dist" @@ -91,6 +96,10 @@ jobs: echo "📦 Checking @opentui/core..." cd packages/core/dist && npm pack --dry-run + echo "" + echo "📦 Checking @opentui/three..." + cd ../../three/dist && npm pack --dry-run + echo "" echo "📦 Checking @opentui/react..." cd ../../react/dist && npm pack --dry-run diff --git a/.github/workflows/npm-release.yml b/.github/workflows/npm-release.yml index 5c0b35b41..4d35fae08 100644 --- a/.github/workflows/npm-release.yml +++ b/.github/workflows/npm-release.yml @@ -57,6 +57,7 @@ jobs: cd packages/core bun run build:native --all bun run build:lib + cd ../three && bun run build cd ../solid && bun run build cd ../react && bun run build diff --git a/.github/workflows/pkg-pr-new.yml b/.github/workflows/pkg-pr-new.yml index dcbb1ade2..72e125e9b 100644 --- a/.github/workflows/pkg-pr-new.yml +++ b/.github/workflows/pkg-pr-new.yml @@ -50,6 +50,10 @@ jobs: run: bun run build --ci working-directory: packages/react + - name: Build three + run: bun run build --ci + working-directory: packages/three + - name: Build solid run: bun run build --ci working-directory: packages/solid @@ -59,5 +63,6 @@ jobs: npx pkg-pr-new publish --no-template --commentWithSha --bun \ './packages/core/dist' \ ${{ steps.native-packages.outputs.dirs }} \ + './packages/three/dist' \ './packages/react/dist' \ './packages/solid/dist' diff --git a/bun.lock b/bun.lock index ebeac0a4a..0aac73128 100644 --- a/bun.lock +++ b/bun.lock @@ -19,24 +19,20 @@ "yoga-layout": "3.2.1", }, "devDependencies": { + "@opentui/three": "workspace:^", "@types/bun": "latest", "@types/node": "^24.0.0", - "@types/three": "0.177.0", "commander": "^13.1.0", "typescript": "^5", "web-tree-sitter": "0.25.10", }, "optionalDependencies": { - "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.88", "@opentui/core-darwin-x64": "0.1.88", "@opentui/core-linux-arm64": "0.1.88", "@opentui/core-linux-x64": "0.1.88", "@opentui/core-win32-arm64": "0.1.88", "@opentui/core-win32-x64": "0.1.88", - "bun-webgpu": "0.1.5", - "planck": "^1.4.2", - "three": "0.177.0", }, "peerDependencies": { "web-tree-sitter": "0.25.10", @@ -93,6 +89,23 @@ "solid-js": "1.9.11", }, }, + "packages/three": { + "name": "@opentui/three", + "version": "0.1.87", + "dependencies": { + "@dimforge/rapier2d-simd-compat": "^0.17.3", + "@opentui/core": "workspace:^", + "bun-webgpu": "0.1.5", + "jimp": "1.6.0", + "planck": "^1.4.2", + "three": "0.177.0", + }, + "devDependencies": { + "@types/bun": "latest", + "@types/three": "0.177.0", + "typescript": "^5", + }, + }, "packages/web": { "name": "@opentui/web", "version": "0.0.1", @@ -356,10 +369,24 @@ "@opentui/core": ["@opentui/core@workspace:packages/core"], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.88", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oGRexWwZFeQJymOK5ORrLrwJUbPHMYaFa0EcLnlhvPnymm1xyMcRKm39ez0WSIdtiCCi/PmMHX95CfyyJB5VMA=="], + + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.88", "", { "os": "darwin", "cpu": "x64" }, "sha512-ddnruYpXt7gXsAqZoQzNrHtZ50niYQfESVT3rhE5qgsz7zoWBdKe/RxLKcb6zQmHMZML6SjSh0NrMG86lsH4dQ=="], + + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.88", "", { "os": "linux", "cpu": "arm64" }, "sha512-jfcU/Sw8re3aWWb9cQ4OXmVNp/pchu6lgDRqvfy0EKTpzd7CNIu6a0xm+rcUKiPO7BrTrwtumT5/jZWWgCdHlg=="], + + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.88", "", { "os": "linux", "cpu": "x64" }, "sha512-nyfilOYLu6XWRlPl1R0Y6WzdL+jVdIFnwShBWcZL+QC5HiJnQc6LKy5yX8uv0fVbY5xs1wBvlHVeUj1UwFQyFQ=="], + + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.88", "", { "os": "win32", "cpu": "arm64" }, "sha512-jv/dQwcku7YZ4lNnYjivVvjPwTfDfzGfcplUqHxmirnv1Q1pZL1qS5wH1PV6RhAKN779vHTvnYMD4OgHWzqVaA=="], + + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.88", "", { "os": "win32", "cpu": "x64" }, "sha512-saGvsQqwL8H7B0VBCQ+szMCKh9WIfTebOR8cwPa2+DR+1FnrEG2I4kiikoj4hfYfRMX18A0A11vQxSh3vvy8Ig=="], + "@opentui/react": ["@opentui/react@workspace:packages/react"], "@opentui/solid": ["@opentui/solid@workspace:packages/solid"], + "@opentui/three": ["@opentui/three@workspace:packages/three"], + "@opentui/web": ["@opentui/web@workspace:packages/web"], "@oslojs/encoding": ["@oslojs/encoding@1.1.0", "", {}, "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ=="], @@ -442,7 +469,7 @@ "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], - "@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="], + "@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="], "@types/debug": ["@types/debug@4.1.12", "", { "dependencies": { "@types/ms": "*" } }, "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ=="], @@ -540,7 +567,7 @@ "bun-ffi-structs": ["bun-ffi-structs@0.1.2", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-Lh1oQAYHDcnesJauieA4UNkWGXY9hYck7OA5IaRwE3Bp6K2F2pJSNYqq+hIy7P3uOvo3km3oxS8304g5gDMl/w=="], - "bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="], + "bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="], "bun-webgpu": ["bun-webgpu@0.1.5", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.5", "bun-webgpu-darwin-x64": "^0.1.5", "bun-webgpu-linux-x64": "^0.1.5", "bun-webgpu-win32-x64": "^0.1.5" } }, "sha512-91/K6S5whZKX7CWAm9AylhyKrLGRz6BUiiPiM/kXadSnD4rffljCD/q9cNFftm5YXhx4MvLqw33yEilxogJvwA=="], @@ -1242,6 +1269,8 @@ "@opentui/react/@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="], + "@opentui/solid/@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="], + "@opentui/web/@types/bun": ["@types/bun@1.3.6", "", { "dependencies": { "bun-types": "1.3.6" } }, "sha512-uWCv6FO/8LcpREhenN1d1b6fcspAB+cefwD7uti8C8VffIv0Um08TKMn98FynpTiU38+y2dUO55T11NgDt8VAA=="], "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], @@ -1284,6 +1313,8 @@ "@opentui/react/@types/bun/bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="], + "@opentui/solid/@types/bun/bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="], + "@opentui/web/@types/bun/bun-types": ["bun-types@1.3.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-OlFwHcnNV99r//9v5IIOgQ9Uk37gZqrNMCcqEaExdkVq3Avwqok1bJFmvGMCkCE0FqzdY8VMOZpfpR3lwI+CsQ=="], "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], diff --git a/package.json b/package.json index 13516d5c6..3fece527a 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,10 @@ "packages/*" ], "scripts": { - "build": "cd packages/core && bun run build && cd ../solid && bun run build && cd ../react && bun run build", + "build": "cd packages/core && bun run build && cd ../three && bun run build && cd ../solid && bun run build && cd ../react && bun run build", "pre-publish": "bun scripts/pre-publish.ts", - "publish": "bun run pre-publish && bun run publish:core && bun run publish:react && bun run publish:solid", + "publish": "bun run pre-publish && bun run publish:core && bun run publish:three && bun run publish:react && bun run publish:solid", + "publish:three": "cd packages/three && bun run publish", "publish:core": "cd packages/core && bun run publish", "publish:react": "cd packages/react && bun run publish", "publish:solid": "cd packages/solid && bun run publish", diff --git a/packages/core/package.json b/packages/core/package.json index 480c61b6a..feb29a7cf 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -28,9 +28,9 @@ }, "license": "MIT", "devDependencies": { + "@opentui/three": "workspace:^", "@types/bun": "latest", "@types/node": "^24.0.0", - "@types/three": "0.177.0", "commander": "^13.1.0", "typescript": "^5", "web-tree-sitter": "0.25.10" @@ -46,10 +46,6 @@ "web-tree-sitter": "0.25.10" }, "optionalDependencies": { - "@dimforge/rapier2d-simd-compat": "^0.17.3", - "bun-webgpu": "0.1.5", - "planck": "^1.4.2", - "three": "0.177.0", "@opentui/core-darwin-x64": "0.1.88", "@opentui/core-darwin-arm64": "0.1.88", "@opentui/core-linux-x64": "0.1.88", @@ -62,10 +58,6 @@ "types": "./src/index.ts", "import": "./src/index.ts" }, - "./3d": { - "types": "./src/3d.ts", - "import": "./src/3d.ts" - }, "./testing": { "types": "./src/testing.ts", "import": "./src/testing.ts" diff --git a/packages/core/scripts/build.ts b/packages/core/scripts/build.ts index 198b8d726..16f532275 100644 --- a/packages/core/scripts/build.ts +++ b/packages/core/scripts/build.ts @@ -195,7 +195,6 @@ if (buildLib) { const entryPoints: string[] = [ packageJson.module, - "src/3d.ts", "src/testing.ts", "src/runtime-plugin.ts", "src/runtime-plugin-support.ts", @@ -256,7 +255,6 @@ if (buildLib) { console.log("Post-processing bundled files to fix duplicate exports...") const bundledFiles = [ "dist/index.js", - "dist/3d.js", "dist/testing.js", "dist/runtime-plugin.js", "dist/runtime-plugin-support.js", @@ -331,11 +329,6 @@ if (buildLib) { require: "./index.js", types: "./index.d.ts", }, - "./3d": { - import: "./3d.js", - require: "./3d.js", - types: "./3d.d.ts", - }, "./testing": { import: "./testing.js", require: "./testing.js", @@ -362,6 +355,15 @@ if (buildLib) { variants.map(({ platform, arch }) => [`${packageJson.name}-${platform}-${arch}`, packageJson.version]), ) + const processedDevDependencies = Object.fromEntries( + Object.entries(packageJson.devDependencies ?? {}).map(([name, version]) => { + if (version === "workspace:*" || version === "workspace:^") { + return [name, packageJson.version] + } + return [name, version] + }), + ) + writeFileSync( join(distDir, "package.json"), JSON.stringify( @@ -381,7 +383,7 @@ if (buildLib) { bugs: packageJson.bugs, exports, dependencies: packageJson.dependencies, - devDependencies: packageJson.devDependencies, + devDependencies: processedDevDependencies, peerDependencies: packageJson.peerDependencies, optionalDependencies: { ...packageJson.optionalDependencies, diff --git a/packages/core/src/3d.ts b/packages/core/src/3d.ts deleted file mode 100644 index ab5bea528..000000000 --- a/packages/core/src/3d.ts +++ /dev/null @@ -1,3 +0,0 @@ -// 3D module exports - requires optional dependencies -export * from "./3d/index.js" -export * as THREE from "three" diff --git a/packages/core/src/examples/draggable-three-demo.ts b/packages/core/src/examples/draggable-three-demo.ts index 0866d6a2d..cfee212e2 100644 --- a/packages/core/src/examples/draggable-three-demo.ts +++ b/packages/core/src/examples/draggable-three-demo.ts @@ -21,7 +21,7 @@ import { MeshPhongMaterial, Vector3, } from "three" -import { ThreeRenderable } from "../3d.js" +import { ThreeRenderable } from "@opentui/three" let nextZIndex = 200 let keyListener: ((key: KeyEvent) => void) | null = null diff --git a/packages/core/src/examples/fractal-shader-demo.ts b/packages/core/src/examples/fractal-shader-demo.ts index aa862c8b4..0e831fbc9 100644 --- a/packages/core/src/examples/fractal-shader-demo.ts +++ b/packages/core/src/examples/fractal-shader-demo.ts @@ -21,7 +21,7 @@ import { Fn, int, } from "three/tsl" -import { ThreeCliRenderer } from "../3d.js" +import { ThreeCliRenderer } from "@opentui/three" let engine: ThreeCliRenderer | null = null let sceneRoot: ThreeScene | null = null diff --git a/packages/core/src/examples/golden-star-demo.ts b/packages/core/src/examples/golden-star-demo.ts index 67f1d8849..51fa76b37 100644 --- a/packages/core/src/examples/golden-star-demo.ts +++ b/packages/core/src/examples/golden-star-demo.ts @@ -24,7 +24,7 @@ import { Quaternion, ConeGeometry, } from "three" -import { ThreeCliRenderer } from "../3d.js" +import { ThreeCliRenderer } from "@opentui/three" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" interface StarParticle { diff --git a/packages/core/src/examples/lights-phong-demo.ts b/packages/core/src/examples/lights-phong-demo.ts index a75cbb0af..62206bdb5 100644 --- a/packages/core/src/examples/lights-phong-demo.ts +++ b/packages/core/src/examples/lights-phong-demo.ts @@ -10,7 +10,7 @@ import { type KeyEvent, } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" -import { TextureUtils } from "../3d/TextureUtils.js" +import { TextureUtils, ThreeCliRenderer } from "@opentui/three" import { Scene as ThreeScene, Mesh as ThreeMesh, @@ -29,7 +29,6 @@ import { TeapotGeometry } from "three/addons/geometries/TeapotGeometry.js" import normalTexPath from "./assets/Water_2_M_Normal.jpg" with { type: "image/jpeg" } // @ts-ignore import alphaTexPath from "./assets/roughness_map.jpg" with { type: "image/jpeg" } -import { ThreeCliRenderer } from "../3d.js" interface PhongDemoState { camera: PerspectiveCamera diff --git a/packages/core/src/examples/physx-planck-2d-demo.ts b/packages/core/src/examples/physx-planck-2d-demo.ts index 244af9fe4..19f77c81e 100644 --- a/packages/core/src/examples/physx-planck-2d-demo.ts +++ b/packages/core/src/examples/physx-planck-2d-demo.ts @@ -10,17 +10,16 @@ import { } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" import * as THREE from "three" +import { SpriteAnimator, TiledSprite, type SpriteDefinition, type AnimationDefinition } from "@opentui/three" import { - SpriteAnimator, - TiledSprite, - type SpriteDefinition, - type AnimationDefinition, -} from "../3d/animation/SpriteAnimator.js" -import { SpriteResourceManager, type ResourceConfig } from "../3d/SpriteResourceManager.js" -import { PhysicsExplosionManager, type PhysicsExplosionHandle } from "../3d/animation/PhysicsExplodingSpriteEffect.js" -import { PlanckPhysicsWorld } from "../3d/physics/PlanckPhysicsAdapter.js" + SpriteResourceManager, + type ResourceConfig, + PhysicsExplosionManager, + type PhysicsExplosionHandle, + PlanckPhysicsWorld, + ThreeCliRenderer, +} from "@opentui/three" import * as planck from "planck" -import { ThreeCliRenderer } from "../3d.js" // @ts-ignore import cratePath from "./assets/crate.png" with { type: "image/png" } diff --git a/packages/core/src/examples/physx-rapier-2d-demo.ts b/packages/core/src/examples/physx-rapier-2d-demo.ts index 1aa9079cb..52dc72394 100644 --- a/packages/core/src/examples/physx-rapier-2d-demo.ts +++ b/packages/core/src/examples/physx-rapier-2d-demo.ts @@ -10,18 +10,17 @@ import { } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" import * as THREE from "three" +import { SpriteAnimator, TiledSprite, type SpriteDefinition, type AnimationDefinition } from "@opentui/three" import { - SpriteAnimator, - TiledSprite, - type SpriteDefinition, - type AnimationDefinition, -} from "../3d/animation/SpriteAnimator.js" -import { SpriteResourceManager, type ResourceConfig } from "../3d/SpriteResourceManager.js" -import { PhysicsExplosionManager, type PhysicsExplosionHandle } from "../3d/animation/PhysicsExplodingSpriteEffect.js" -import { RapierPhysicsWorld } from "../3d/physics/RapierPhysicsAdapter.js" + SpriteResourceManager, + type ResourceConfig, + PhysicsExplosionManager, + type PhysicsExplosionHandle, + RapierPhysicsWorld, + ThreeCliRenderer, +} from "@opentui/three" import RAPIER from "@dimforge/rapier2d-simd-compat" import { MeshLambertNodeMaterial } from "three/webgpu" -import { ThreeCliRenderer } from "../3d.js" // @ts-ignore import cratePath from "./assets/concrete.png" with { type: "image/png" } diff --git a/packages/core/src/examples/shader-cube-demo.ts b/packages/core/src/examples/shader-cube-demo.ts index 87ddba46e..403e767e3 100644 --- a/packages/core/src/examples/shader-cube-demo.ts +++ b/packages/core/src/examples/shader-cube-demo.ts @@ -10,7 +10,7 @@ import { } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" import { RGBA } from "../lib/index.js" -import { TextureUtils } from "../3d/TextureUtils.js" +import { TextureUtils, ThreeCliRenderer } from "@opentui/three" import { Scene as ThreeScene, Mesh as ThreeMesh, @@ -25,7 +25,6 @@ import { import * as Filters from "../post/filters.js" import { DistortionEffect, VignetteEffect, BrightnessEffect, BlurEffect, BloomEffect } from "../post/filters.js" import type { OptimizedBuffer } from "../buffer.js" -import { ThreeCliRenderer } from "../3d.js" // State management for the demo interface ShaderCubeDemoState { diff --git a/packages/core/src/examples/sprite-animation-demo.ts b/packages/core/src/examples/sprite-animation-demo.ts index a3aee5191..8dace4c0e 100644 --- a/packages/core/src/examples/sprite-animation-demo.ts +++ b/packages/core/src/examples/sprite-animation-demo.ts @@ -11,24 +11,20 @@ import { } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" import * as THREE from "three" +import { SpriteAnimator, TiledSprite, type SpriteDefinition, type AnimationDefinition } from "@opentui/three" import { - SpriteAnimator, - TiledSprite, - type SpriteDefinition, - type AnimationDefinition, -} from "../3d/animation/SpriteAnimator.js" -import { SpriteResourceManager, type ResourceConfig } from "../3d/SpriteResourceManager.js" -import { + SpriteResourceManager, + type ResourceConfig, ExplosionManager, type ExplosionHandle, type ExplosionEffectParameters, -} from "../3d/animation/ExplodingSpriteEffect.js" + ThreeCliRenderer, +} from "@opentui/three" // @ts-ignore import mainCharIdlePath from "./assets/main_char_idle.png" with { type: "image/png" } import { randFloat } from "three/src/math/MathUtils.js" import { MeshLambertNodeMaterial } from "three/webgpu" -import { ThreeCliRenderer } from "../3d.js" interface SpriteAnimationDemoState { engine: ThreeCliRenderer diff --git a/packages/core/src/examples/sprite-particle-generator-demo.ts b/packages/core/src/examples/sprite-particle-generator-demo.ts index fc3f4c6b2..c3d8e4acb 100644 --- a/packages/core/src/examples/sprite-particle-generator-demo.ts +++ b/packages/core/src/examples/sprite-particle-generator-demo.ts @@ -12,15 +12,14 @@ import { } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" import * as THREE from "three" +import { SpriteAnimator, type TiledSprite, type SpriteDefinition, type AnimationDefinition } from "@opentui/three" import { - SpriteAnimator, - type TiledSprite, - type SpriteDefinition, - type AnimationDefinition, -} from "../3d/animation/SpriteAnimator.js" -import { SpriteResourceManager, type ResourceConfig } from "../3d/SpriteResourceManager.js" -import { SpriteParticleGenerator, type ParticleEffectParameters } from "../3d/animation/SpriteParticleGenerator.js" -import { ThreeCliRenderer } from "../3d.js" + SpriteResourceManager, + type ResourceConfig, + SpriteParticleGenerator, + type ParticleEffectParameters, + ThreeCliRenderer, +} from "@opentui/three" // @ts-ignore import heartPath from "./assets/heart.png" with { type: "image/png" } diff --git a/packages/core/src/examples/static-sprite-demo.ts b/packages/core/src/examples/static-sprite-demo.ts index d74614410..f6409eaa2 100644 --- a/packages/core/src/examples/static-sprite-demo.ts +++ b/packages/core/src/examples/static-sprite-demo.ts @@ -11,8 +11,7 @@ import { } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" import * as THREE from "three" -import { ThreeCliRenderer } from "../3d.js" -import { SpriteUtils } from "../3d/SpriteUtils.js" +import { ThreeCliRenderer, SpriteUtils } from "@opentui/three" // @ts-ignore - Bun specific import attribute for assets import staticImagePath from "./assets/main_char_idle.png" with { type: "image/png" } diff --git a/packages/core/src/examples/texture-loading-demo.ts b/packages/core/src/examples/texture-loading-demo.ts index 3723cf68d..35abc29f0 100644 --- a/packages/core/src/examples/texture-loading-demo.ts +++ b/packages/core/src/examples/texture-loading-demo.ts @@ -2,7 +2,7 @@ import { CliRenderer, createCliRenderer, RGBA, BoxRenderable, TextRenderable, type KeyEvent } from "../index.js" import { setupCommonDemoKeys } from "./lib/standalone-keys.js" -import { TextureUtils } from "../3d/TextureUtils.js" +import { TextureUtils, ThreeRenderable, SuperSampleAlgorithm } from "@opentui/three" import { Scene as ThreeScene, Mesh as ThreeMesh, @@ -15,7 +15,6 @@ import { } from "three" import { MeshPhongNodeMaterial } from "three/webgpu" import { lights } from "three/tsl" -import { ThreeRenderable, SuperSampleAlgorithm } from "../3d.js" // @ts-ignore import cratePath from "./assets/crate.png" with { type: "image/png" } diff --git a/packages/core/src/runtime-plugin.ts b/packages/core/src/runtime-plugin.ts index 3b5518dd8..a9e23634f 100644 --- a/packages/core/src/runtime-plugin.ts +++ b/packages/core/src/runtime-plugin.ts @@ -28,7 +28,7 @@ export const isCoreRuntimeModuleSpecifier = (specifier: string): boolean => { } const loadCore3dRuntimeModule = async (): Promise => { - return (await import("./3d")) as RuntimeModuleExports + return (await import("@opentui/three")) as RuntimeModuleExports } const loadCoreTestingRuntimeModule = async (): Promise => { diff --git a/packages/core/tsconfig.build.json b/packages/core/tsconfig.build.json index 39372be56..be264e0ae 100644 --- a/packages/core/tsconfig.build.json +++ b/packages/core/tsconfig.build.json @@ -7,7 +7,7 @@ "outDir": "./dist", "noEmit": false, "rootDir": "./src", - "types": ["bun", "node", "three"], + "types": ["bun", "node"], "skipLibCheck": true }, "include": ["src/**/*"], diff --git a/packages/react/scripts/runtime-plugin-support.ts b/packages/react/scripts/runtime-plugin-support.ts index 46d449c72..83388c845 100644 --- a/packages/react/scripts/runtime-plugin-support.ts +++ b/packages/react/scripts/runtime-plugin-support.ts @@ -1,6 +1,6 @@ import { plugin as registerBunPlugin } from "bun" import * as coreRuntime from "@opentui/core" -import { createRuntimePlugin, type RuntimeModuleEntry } from "@opentui/core/runtime-plugin" +import { createRuntimePlugin } from "@opentui/core/runtime-plugin" import * as reactRuntime from "react" import * as reactJsxRuntime from "react/jsx-runtime" import * as reactJsxDevRuntime from "react/jsx-dev-runtime" @@ -12,8 +12,15 @@ type RuntimePluginSupportState = typeof globalThis & { [runtimePluginSupportInstalledKey]?: boolean } +const loadThreeRuntime = async (): Promise> => { + return (await import(new URL("../../three/src/index.ts", import.meta.url).href)) as Record +} + +type RuntimeModuleEntry = Record | (() => Record | Promise>) + const additionalRuntimeModules: Record = { "@opentui/react": opentuiReactRuntime as Record, + "@opentui/three": loadThreeRuntime, "@opentui/react/jsx-runtime": reactJsxRuntime as Record, "@opentui/react/jsx-dev-runtime": reactJsxDevRuntime as Record, react: reactRuntime as Record, diff --git a/packages/react/tests/runtime-plugin-support.fixture.ts b/packages/react/tests/runtime-plugin-support.fixture.ts index 55d377e0a..5c7646781 100644 --- a/packages/react/tests/runtime-plugin-support.fixture.ts +++ b/packages/react/tests/runtime-plugin-support.fixture.ts @@ -22,12 +22,16 @@ type FixtureState = typeof globalThis & { } } +const loadCore3dHostRuntime = async (): Promise> => { + return (await import("../../three/src/index.ts")) as Record +} + const tempRoot = mkdtempSync(join(tmpdir(), "react-runtime-plugin-support-fixture-")) const entryPath = join(tempRoot, "entry.ts") const source = [ 'import * as core from "@opentui/core"', - 'import * as core3d from "@opentui/core/3d"', + 'import * as core3d from "@opentui/three"', 'import * as coreTesting from "@opentui/core/testing"', 'import * as opentuiReact from "@opentui/react"', 'import * as opentuiReactJsx from "@opentui/react/jsx-runtime"', @@ -57,7 +61,7 @@ writeFileSync(entryPath, source) const state = globalThis as FixtureState state.__reactRuntimeHost__ = { core: coreRuntime as Record, - core3d: (await import("@opentui/core/3d")) as Record, + core3d: await loadCore3dHostRuntime(), coreTesting: (await import("@opentui/core/testing")) as Record, opentuiReact: opentuiReactRuntime as Record, opentuiReactJsx: (await import("../jsx-runtime.js")) as Record, diff --git a/packages/solid/scripts/runtime-plugin-support.ts b/packages/solid/scripts/runtime-plugin-support.ts index d6c145fb8..14559f815 100644 --- a/packages/solid/scripts/runtime-plugin-support.ts +++ b/packages/solid/scripts/runtime-plugin-support.ts @@ -4,7 +4,6 @@ import { createRuntimePlugin, isCoreRuntimeModuleSpecifier, runtimeModuleIdForSpecifier, - type RuntimeModuleEntry, } from "@opentui/core/runtime-plugin" import * as solidJsRuntime from "solid-js" import * as solidJsStoreRuntime from "solid-js/store" @@ -17,8 +16,15 @@ type RuntimePluginSupportState = typeof globalThis & { [runtimePluginSupportInstalledKey]?: boolean } +const loadThreeRuntime = async (): Promise> => { + return (await import(new URL("../../three/src/index.ts", import.meta.url).href)) as Record +} + +type RuntimeModuleEntry = Record | (() => Record | Promise>) + const additionalRuntimeModules: Record = { "@opentui/solid": solidRuntime as Record, + "@opentui/three": loadThreeRuntime, "solid-js": solidJsRuntime as Record, "solid-js/store": solidJsStoreRuntime as Record, } diff --git a/packages/solid/tests/runtime-plugin-support.fixture.ts b/packages/solid/tests/runtime-plugin-support.fixture.ts index ca87304bc..dd404a7e4 100644 --- a/packages/solid/tests/runtime-plugin-support.fixture.ts +++ b/packages/solid/tests/runtime-plugin-support.fixture.ts @@ -16,13 +16,17 @@ type FixtureState = typeof globalThis & { } } +const loadCore3dHostRuntime = async (): Promise> => { + return (await import("../../three/src/index.ts")) as Record +} + const tempRoot = mkdtempSync(join(tmpdir(), "solid-runtime-plugin-support-fixture-")) const entryPath = join(tempRoot, "entry.tsx") const source = [ 'import * as solid from "@opentui/solid"', 'import * as core from "@opentui/core"', - 'import * as core3d from "@opentui/core/3d"', + 'import * as core3d from "@opentui/three"', 'import * as coreTesting from "@opentui/core/testing"', 'import { createSignal } from "solid-js"', "const state = globalThis as { __solidRuntimeHost__?: { solid: Record; core: Record; core3d: Record; coreTesting: Record; solidJs: Record } }", @@ -47,7 +51,7 @@ const state = globalThis as FixtureState state.__solidRuntimeHost__ = { solid: solidRuntime as Record, core: coreRuntime as Record, - core3d: (await import("@opentui/core/3d")) as Record, + core3d: await loadCore3dHostRuntime(), coreTesting: (await import("@opentui/core/testing")) as Record, solidJs: solidJsRuntime as Record, } diff --git a/packages/core/src/benchmark/renderer-benchmark.ts b/packages/three/benchmark/renderer-benchmark.ts similarity index 98% rename from packages/core/src/benchmark/renderer-benchmark.ts rename to packages/three/benchmark/renderer-benchmark.ts index 7ad30f344..d3bb7213f 100644 --- a/packages/core/src/benchmark/renderer-benchmark.ts +++ b/packages/three/benchmark/renderer-benchmark.ts @@ -1,8 +1,8 @@ #!/usr/bin/env bun -import { createCliRenderer, RGBA, TextRenderable, BoxRenderable, FrameBufferRenderable } from "../index.js" -import { ThreeCliRenderer } from "../3d/WGPURenderer.js" -import { TextureUtils } from "../3d/TextureUtils.js" +import { createCliRenderer, RGBA, TextRenderable, BoxRenderable, FrameBufferRenderable } from "@opentui/core" +import { ThreeCliRenderer, TextureUtils } from "../src/index.js" +import type { Mesh, MeshPhongMaterial as MeshPhongMaterialType } from "three" import { Scene as ThreeScene, Mesh as ThreeMesh, @@ -26,9 +26,9 @@ import { mkdir } from "node:fs/promises" type MemorySnapshot = { heapUsed: number; heapTotal: number; arrayBuffers: number } // @ts-ignore -import cratePath from "../examples/assets/crate.png" with { type: "image/png" } +import cratePath from "@opentui/core/src/examples/assets/crate.png" with { type: "image/png" } // @ts-ignore -import crateEmissivePath from "../examples/assets/crate_emissive.png" with { type: "image/png" } +import crateEmissivePath from "@opentui/core/src/examples/assets/crate_emissive.png" with { type: "image/png" } // Setup command line options const program = new Command() @@ -205,7 +205,7 @@ let benchmarkStartTime = 0 let benchmarkActive = true const results: ScenarioResult[] = [] let currentMemorySnapshots: MemorySnapshot[] = [] -let cubeMeshNodes: ThreeMesh[] = [] +let cubeMeshNodes: Mesh[] = [] const RADIUS = 1 const MULTIPLE_CUBES_COUNT = 8 @@ -228,7 +228,7 @@ const singleCubeMaterial = new MeshPhongMaterial({ const cullingCubeMaterial = new MeshPhongMaterial({ color: 0x555555, shininess: 10 }) let texturedMaterial: MeshPhongNodeMaterial | null = null -let multiCubeMaterials: MeshPhongMaterial[] = [] +let multiCubeMaterials: MeshPhongMaterialType[] = [] for (let i = 0; i < MULTIPLE_CUBES_COUNT; i++) { const baseColor = new Color() const hue = i / MULTIPLE_CUBES_COUNT diff --git a/packages/three/package.json b/packages/three/package.json new file mode 100644 index 000000000..c99ca5973 --- /dev/null +++ b/packages/three/package.json @@ -0,0 +1,40 @@ +{ + "name": "@opentui/three", + "version": "0.1.87", + "description": "3D rendering module for OpenTUI", + "repository": { + "type": "git", + "url": "https://github.com/anomalyco/opentui", + "directory": "packages/three" + }, + "module": "src/index.ts", + "type": "module", + "main": "src/index.ts", + "license": "MIT", + "scripts": { + "build": "bun scripts/build.ts", + "publish": "bun scripts/publish.ts" + }, + "devDependencies": { + "@types/bun": "latest", + "@types/three": "0.177.0", + "typescript": "^5" + }, + "dependencies": { + "@dimforge/rapier2d-simd-compat": "^0.17.3", + "@opentui/core": "workspace:^", + "bun-webgpu": "0.1.5", + "jimp": "1.6.0", + "planck": "^1.4.2", + "three": "0.177.0" + }, + "exports": { + ".": { + "types": "./src/index.ts", + "import": "./src/index.ts" + } + }, + "engines": { + "bun": ">=1.2.0" + } +} diff --git a/packages/three/scripts/build.ts b/packages/three/scripts/build.ts new file mode 100644 index 000000000..b2d9bc315 --- /dev/null +++ b/packages/three/scripts/build.ts @@ -0,0 +1,144 @@ +import { spawnSync, type SpawnSyncReturns } from "node:child_process" +import { copyFileSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "fs" +import { dirname, join, resolve } from "path" +import { fileURLToPath } from "url" +import process from "process" + +interface PackageJson { + name: string + version: string + license?: string + repository?: any + description?: string + homepage?: string + author?: string + bugs?: any + keywords?: string[] + module?: string + main?: string + types?: string + type?: string + exports?: any + dependencies?: Record + devDependencies?: Record + peerDependencies?: Record + optionalDependencies?: Record + engines?: Record +} + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) +const rootDir = resolve(__dirname, "..") +const projectRootDir = resolve(rootDir, "../..") +const licensePath = join(projectRootDir, "LICENSE") +const packageJson: PackageJson = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8")) + +const args = process.argv.slice(2) +const isCi = args.includes("--ci") + +const replaceLinks = (text: string): string => { + return packageJson.homepage + ? text.replace( + /(\[.*?\]\()(\.\/.*?\))/g, + (_, p1: string, p2: string) => `${p1}${packageJson.homepage}/blob/HEAD/${p2.replace("./", "")}`, + ) + : text +} + +const requiredFields: (keyof PackageJson)[] = ["name", "version", "description"] +const missingRequired = requiredFields.filter((field) => !packageJson[field]) +if (missingRequired.length > 0) { + console.error(`Error: Missing required fields in package.json: ${missingRequired.join(", ")}`) + process.exit(1) +} + +console.log("Building @opentui/three library...") + +const distDir = join(rootDir, "dist") +rmSync(distDir, { recursive: true, force: true }) +mkdirSync(distDir, { recursive: true }) + +if (!packageJson.module) { + console.error("Error: 'module' field not found in package.json") + process.exit(1) +} + +console.log("Building main entry point...") +const mainBuildResult = await Bun.build({ + entrypoints: [join(rootDir, packageJson.module)], + target: "bun", + outdir: distDir, + packages: "external", + splitting: true, +}) + +if (!mainBuildResult.success) { + console.error("Build failed:", mainBuildResult.logs) + process.exit(1) +} + +console.log("Generating TypeScript declarations...") +const tsconfigBuildPath = join(rootDir, "tsconfig.build.json") +const tscResult: SpawnSyncReturns = spawnSync("bunx", ["tsc", "-p", tsconfigBuildPath], { + cwd: rootDir, + stdio: "inherit", +}) + +if (tscResult.status !== 0) { + if (isCi) { + console.error("Error: TypeScript declaration generation failed") + process.exit(1) + } + console.warn("Warning: TypeScript declaration generation failed") +} else { + console.log("TypeScript declarations generated") +} + +const exports = { + ".": { + types: "./index.d.ts", + import: "./index.js", + require: "./index.js", + }, +} + +const processedDependencies = { ...packageJson.dependencies } +if ( + processedDependencies["@opentui/core"] === "workspace:*" || + processedDependencies["@opentui/core"] === "workspace:^" +) { + processedDependencies["@opentui/core"] = packageJson.version +} + +writeFileSync( + join(distDir, "package.json"), + JSON.stringify( + { + name: packageJson.name, + version: packageJson.version, + description: packageJson.description, + repository: packageJson.repository, + module: "index.js", + main: "index.js", + types: "index.d.ts", + type: packageJson.type, + license: packageJson.license, + exports, + dependencies: processedDependencies, + engines: packageJson.engines, + }, + null, + 2, + ), +) + +const readmePath = join(rootDir, "README.md") +if (existsSync(readmePath)) { + writeFileSync(join(distDir, "README.md"), replaceLinks(readFileSync(readmePath, "utf8"))) +} + +if (existsSync(licensePath)) { + copyFileSync(licensePath, join(distDir, "LICENSE")) +} + +console.log("Library built at:", distDir) diff --git a/packages/three/scripts/publish.ts b/packages/three/scripts/publish.ts new file mode 100644 index 000000000..68924b9b8 --- /dev/null +++ b/packages/three/scripts/publish.ts @@ -0,0 +1,44 @@ +import { spawnSync, type SpawnSyncReturns } from "node:child_process" +import { readFileSync } from "node:fs" +import { dirname, join, resolve } from "node:path" +import process from "node:process" +import { fileURLToPath } from "node:url" + +interface PackageJson { + name: string + version: string + dependencies?: Record +} + +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename) +const rootDir = resolve(__dirname, "..") + +const packageJson: PackageJson = JSON.parse(readFileSync(join(rootDir, "package.json"), "utf8")) + +console.log(`Publishing @opentui/three@${packageJson.version}...`) +console.log("Make sure you've run the pre-publish validation script first!") + +const distDir = join(rootDir, "dist") + +console.log(`\nPublishing ${packageJson.name}@${packageJson.version}...`) + +const isSnapshot = packageJson.version.includes("-snapshot") || /^0\.0\.0-\d{8}-[a-f0-9]{8}$/.test(packageJson.version) +const publishArgs = ["publish", "--access=public"] + +if (isSnapshot) { + publishArgs.push("--tag", "snapshot") + console.log(` Publishing as snapshot (--tag snapshot)`) +} + +const publish: SpawnSyncReturns = spawnSync("npm", publishArgs, { + cwd: distDir, + stdio: "inherit", +}) + +if (publish.status !== 0) { + console.error(`Failed to publish '${packageJson.name}@${packageJson.version}'.`) + process.exit(1) +} + +console.log(`Successfully published '${packageJson.name}@${packageJson.version}'`) diff --git a/packages/core/src/3d/SpriteResourceManager.ts b/packages/three/src/SpriteResourceManager.ts similarity index 100% rename from packages/core/src/3d/SpriteResourceManager.ts rename to packages/three/src/SpriteResourceManager.ts diff --git a/packages/core/src/3d/SpriteUtils.ts b/packages/three/src/SpriteUtils.ts similarity index 100% rename from packages/core/src/3d/SpriteUtils.ts rename to packages/three/src/SpriteUtils.ts diff --git a/packages/core/src/3d/TextureUtils.ts b/packages/three/src/TextureUtils.ts similarity index 100% rename from packages/core/src/3d/TextureUtils.ts rename to packages/three/src/TextureUtils.ts diff --git a/packages/core/src/3d/ThreeRenderable.ts b/packages/three/src/ThreeRenderable.ts similarity index 95% rename from packages/core/src/3d/ThreeRenderable.ts rename to packages/three/src/ThreeRenderable.ts index 965de18c6..14d3aee9f 100644 --- a/packages/core/src/3d/ThreeRenderable.ts +++ b/packages/three/src/ThreeRenderable.ts @@ -1,10 +1,13 @@ import { OrthographicCamera, PerspectiveCamera, Scene } from "three" -import { OptimizedBuffer } from "../buffer.js" -import { RGBA } from "../lib/RGBA.js" -import { Renderable, type RenderableOptions } from "../Renderable.js" -import type { CliRenderer } from "../renderer.js" -import type { RenderContext } from "../types.js" +import { + OptimizedBuffer, + RGBA, + Renderable, + type RenderableOptions, + type CliRenderer, + type RenderContext, +} from "@opentui/core" import { ThreeCliRenderer, type ThreeCliRendererOptions } from "./WGPURenderer.js" export interface ThreeRenderableOptions extends RenderableOptions { diff --git a/packages/core/src/3d/WGPURenderer.ts b/packages/three/src/WGPURenderer.ts similarity index 98% rename from packages/core/src/3d/WGPURenderer.ts rename to packages/three/src/WGPURenderer.ts index 068ef48b8..326448804 100644 --- a/packages/core/src/3d/WGPURenderer.ts +++ b/packages/three/src/WGPURenderer.ts @@ -1,10 +1,8 @@ import { PerspectiveCamera, OrthographicCamera, Color, NoToneMapping, LinearSRGBColorSpace, Scene } from "three" import { WebGPURenderer } from "three/webgpu" -import type { OptimizedBuffer } from "../buffer.js" -import { RGBA } from "../lib/RGBA.js" +import { RGBA, CliRenderEvents, type CliRenderer, type OptimizedBuffer } from "@opentui/core" import { createWebGPUDevice, setupGlobals } from "bun-webgpu" import { CLICanvas, SuperSampleAlgorithm } from "./canvas.js" -import { CliRenderEvents, type CliRenderer } from "../renderer.js" export enum SuperSampleType { NONE = "none", diff --git a/packages/core/src/3d/animation/ExplodingSpriteEffect.ts b/packages/three/src/animation/ExplodingSpriteEffect.ts similarity index 100% rename from packages/core/src/3d/animation/ExplodingSpriteEffect.ts rename to packages/three/src/animation/ExplodingSpriteEffect.ts diff --git a/packages/core/src/3d/animation/PhysicsExplodingSpriteEffect.ts b/packages/three/src/animation/PhysicsExplodingSpriteEffect.ts similarity index 100% rename from packages/core/src/3d/animation/PhysicsExplodingSpriteEffect.ts rename to packages/three/src/animation/PhysicsExplodingSpriteEffect.ts diff --git a/packages/core/src/3d/animation/SpriteAnimator.ts b/packages/three/src/animation/SpriteAnimator.ts similarity index 100% rename from packages/core/src/3d/animation/SpriteAnimator.ts rename to packages/three/src/animation/SpriteAnimator.ts diff --git a/packages/core/src/3d/animation/SpriteParticleGenerator.ts b/packages/three/src/animation/SpriteParticleGenerator.ts similarity index 100% rename from packages/core/src/3d/animation/SpriteParticleGenerator.ts rename to packages/three/src/animation/SpriteParticleGenerator.ts diff --git a/packages/core/src/3d/canvas.ts b/packages/three/src/canvas.ts similarity index 99% rename from packages/core/src/3d/canvas.ts rename to packages/three/src/canvas.ts index be1507d99..4f08c5aa7 100644 --- a/packages/core/src/3d/canvas.ts +++ b/packages/three/src/canvas.ts @@ -1,7 +1,6 @@ import { GPUCanvasContextMock } from "bun-webgpu" -import { RGBA } from "../lib/RGBA.js" +import { RGBA, type OptimizedBuffer } from "@opentui/core" import { SuperSampleType } from "./WGPURenderer.js" -import type { OptimizedBuffer } from "../buffer.js" import { toArrayBuffer } from "bun:ffi" import { Jimp } from "jimp" diff --git a/packages/core/src/3d/index.ts b/packages/three/src/index.ts similarity index 94% rename from packages/core/src/3d/index.ts rename to packages/three/src/index.ts index 3f69276a6..2b0ab7a6f 100644 --- a/packages/core/src/3d/index.ts +++ b/packages/three/src/index.ts @@ -1,3 +1,4 @@ +export * as THREE from "three" export * from "./WGPURenderer.js" export * from "./ThreeRenderable.js" export * from "./TextureUtils.js" diff --git a/packages/core/src/3d/physics/PlanckPhysicsAdapter.ts b/packages/three/src/physics/PlanckPhysicsAdapter.ts similarity index 100% rename from packages/core/src/3d/physics/PlanckPhysicsAdapter.ts rename to packages/three/src/physics/PlanckPhysicsAdapter.ts diff --git a/packages/core/src/3d/physics/RapierPhysicsAdapter.ts b/packages/three/src/physics/RapierPhysicsAdapter.ts similarity index 100% rename from packages/core/src/3d/physics/RapierPhysicsAdapter.ts rename to packages/three/src/physics/RapierPhysicsAdapter.ts diff --git a/packages/core/src/3d/physics/physics-interface.ts b/packages/three/src/physics/physics-interface.ts similarity index 100% rename from packages/core/src/3d/physics/physics-interface.ts rename to packages/three/src/physics/physics-interface.ts diff --git a/packages/core/src/3d/shaders/supersampling.wgsl b/packages/three/src/shaders/supersampling.wgsl similarity index 100% rename from packages/core/src/3d/shaders/supersampling.wgsl rename to packages/three/src/shaders/supersampling.wgsl diff --git a/packages/three/tsconfig.build.json b/packages/three/tsconfig.build.json new file mode 100644 index 000000000..f89f9ebb0 --- /dev/null +++ b/packages/three/tsconfig.build.json @@ -0,0 +1,19 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "./tsconfig.json", + "compilerOptions": { + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "./dist", + "noEmit": false, + "rootDir": "./src", + "types": ["bun"], + "skipLibCheck": true, + "paths": { + "@opentui/core": ["../core/dist"], + "@opentui/core/*": ["../core/dist/*"] + } + }, + "include": ["src/**/*"], + "exclude": ["**/*.test.ts", "**/*.spec.ts", "scripts/**/*", "node_modules/**/*"] +} diff --git a/packages/three/tsconfig.json b/packages/three/tsconfig.json new file mode 100644 index 000000000..4bf488d66 --- /dev/null +++ b/packages/three/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + }, + "exclude": ["dist"] +} diff --git a/scripts/pre-publish.ts b/scripts/pre-publish.ts index 9eec877e5..84fa475c3 100644 --- a/scripts/pre-publish.ts +++ b/scripts/pre-publish.ts @@ -36,6 +36,12 @@ const ALL_PACKAGES: PackageConfig[] = [ rootDir: join(rootDir, "packages", "core"), distDir: join(rootDir, "packages", "core", "dist"), }, + { + name: "@opentui/three", + rootDir: join(rootDir, "packages", "three"), + distDir: join(rootDir, "packages", "three", "dist"), + requiresCore: true, + }, { name: "@opentui/react", rootDir: join(rootDir, "packages", "react"), diff --git a/scripts/prepare-release.ts b/scripts/prepare-release.ts index ecb7f06ca..74e552712 100644 --- a/scripts/prepare-release.ts +++ b/scripts/prepare-release.ts @@ -59,7 +59,7 @@ if (!/^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?$/.test(version)) { process.exit(1) } -console.log(`\nPreparing release ${version} for core, react, and solid packages...\n`) +console.log(`\nPreparing release ${version} for core, three, react, and solid packages...\n`) const corePackageJsonPath = join(rootDir, "packages", "core", "package.json") console.log("Updating @opentui/core...") @@ -101,6 +101,22 @@ try { process.exit(1) } +const threePackageJsonPath = join(rootDir, "packages", "three", "package.json") +console.log("\nUpdating @opentui/three...") + +try { + const threePackageJson: PackageJson = JSON.parse(readFileSync(threePackageJsonPath, "utf8")) + + threePackageJson.version = version + + writeFileSync(threePackageJsonPath, JSON.stringify(threePackageJson, null, 2) + "\n") + console.log(` @opentui/three updated to version ${version}`) + console.log(` Note: @opentui/core dependency will be set to ${version} during build`) +} catch (error) { + console.error(` Failed to update @opentui/three: ${error}`) + process.exit(1) +} + const solidPackageJsonPath = join(rootDir, "packages", "solid", "package.json") console.log("\nUpdating @opentui/solid...") @@ -127,7 +143,7 @@ try { } console.log(` -Successfully prepared release ${version} for core, react, and solid packages! +Successfully prepared release ${version} for core, three, react, and solid packages! Next steps: 1. Review the changes: git diff