From e7c7fa3a20f587c488b982d4eae8be1bb7192291 Mon Sep 17 00:00:00 2001 From: Khoa Huynh Date: Thu, 14 May 2026 00:16:06 -0400 Subject: [PATCH 1/2] feat(opentui-solid,ui): extract shared highlight cache, remove React from bundle, and fix reactivity --- bun.lock | 226 ++++++++++++++++++- package.json | 18 +- scripts/build-npm.ts | 41 ++++ src/opentui-solid/HunkDiffBody.tsx | 94 ++++++++ src/opentui-solid/HunkDiffFileHeader.tsx | 28 +++ src/opentui-solid/HunkDiffView.tsx | 19 ++ src/opentui-solid/HunkFileNav.tsx | 43 ++++ src/opentui-solid/HunkReviewStream.tsx | 83 +++++++ src/opentui-solid/build-verification.test.ts | 18 ++ src/opentui-solid/index.d.ts | 30 +++ src/opentui-solid/index.ts | 24 ++ src/opentui-solid/jsx-augmentation.d.ts | 15 ++ src/opentui-solid/useHighlightedDiff.ts | 75 ++++++ src/opentui/HunkDiffBody.tsx | 3 +- src/ui/diff/DiffRowView.tsx | 20 ++ src/ui/diff/PierreDiffView.tsx | 3 +- src/ui/diff/highlightCache.test.ts | 93 ++++++++ src/ui/diff/highlightCache.ts | 160 +++++++++++++ src/ui/diff/renderRows.tsx | 61 ++--- src/ui/diff/useHighlightedDiff.ts | 174 ++------------ tsconfig.json | 3 +- tsconfig.opentui-solid.json | 15 ++ 22 files changed, 1037 insertions(+), 209 deletions(-) create mode 100644 src/opentui-solid/HunkDiffBody.tsx create mode 100644 src/opentui-solid/HunkDiffFileHeader.tsx create mode 100644 src/opentui-solid/HunkDiffView.tsx create mode 100644 src/opentui-solid/HunkFileNav.tsx create mode 100644 src/opentui-solid/HunkReviewStream.tsx create mode 100644 src/opentui-solid/build-verification.test.ts create mode 100644 src/opentui-solid/index.d.ts create mode 100644 src/opentui-solid/index.ts create mode 100644 src/opentui-solid/jsx-augmentation.d.ts create mode 100644 src/opentui-solid/useHighlightedDiff.ts create mode 100644 src/ui/diff/DiffRowView.tsx create mode 100644 src/ui/diff/highlightCache.test.ts create mode 100644 src/ui/diff/highlightCache.ts create mode 100644 tsconfig.opentui-solid.json diff --git a/bun.lock b/bun.lock index f2b7b376..9e0a556f 100644 --- a/bun.lock +++ b/bun.lock @@ -18,6 +18,7 @@ "@hunk/session-broker-node": "workspace:*", "@opentui/core": "^0.1.88", "@opentui/react": "^0.1.88", + "@opentui/solid": "^0.1.88", "@types/bun": "1.3.13", "@types/react": "^19.2.14", "@types/ws": "^8.18.1", @@ -26,13 +27,16 @@ "oxlint": "^1.56.0", "react": "^19.2.4", "simple-git-hooks": "^2.13.1", + "solid-js": "^1.9.0", "tuistory": "^0.0.16", "typescript": "^5.9.3", }, "peerDependencies": { "@opentui/core": "^0.1.88", "@opentui/react": "^0.1.88", + "@opentui/solid": "^0.1.88", "react": "^19.2.4", + "solid-js": "^1.9.0", }, }, "packages/session-broker": { @@ -63,6 +67,64 @@ }, }, "packages": { + "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + + "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], + + "@babel/compat-data": ["@babel/compat-data@7.29.3", "", {}, "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg=="], + + "@babel/core": ["@babel/core@7.28.0", "", { "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.0", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-module-transforms": "^7.27.3", "@babel/helpers": "^7.27.6", "@babel/parser": "^7.28.0", "@babel/template": "^7.27.2", "@babel/traverse": "^7.28.0", "@babel/types": "^7.28.0", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ=="], + + "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], + + "@babel/helper-annotate-as-pure": ["@babel/helper-annotate-as-pure@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" } }, "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], + + "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.29.3", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/helper-replace-supers": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/traverse": "^7.29.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA=="], + + "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], + + "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.28.5", "", { "dependencies": { "@babel/traverse": "^7.28.5", "@babel/types": "^7.28.5" } }, "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], + + "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.27.1", "", { "dependencies": { "@babel/types": "^7.27.1" } }, "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], + + "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.28.6", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.28.5", "@babel/helper-optimise-call-expression": "^7.27.1", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg=="], + + "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], + + "@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="], + + "@babel/parser": ["@babel/parser@7.29.3", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA=="], + + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="], + + "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A=="], + + "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.28.6", "", { "dependencies": { "@babel/helper-module-transforms": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA=="], + + "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.6", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.6", "@babel/helper-plugin-utils": "^7.28.6", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw=="], + + "@babel/preset-typescript": ["@babel/preset-typescript@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ=="], + + "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], + + "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], + + "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], + "@dimforge/rapier2d-simd-compat": ["@dimforge/rapier2d-simd-compat@0.17.3", "", {}, "sha512-bijvwWz6NHsNj5e5i1vtd3dU2pDhthSaTUZSh14DUGGKJfw8eMnlWZsxwHBxB/a3AXVNDjL9abuHw1k9FGR+jg=="], "@hono/node-server": ["@hono/node-server@1.19.11", "", { "peerDependencies": { "hono": "^4" } }, "sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g=="], @@ -131,6 +193,14 @@ "@jimp/utils": ["@jimp/utils@1.6.0", "", { "dependencies": { "@jimp/types": "1.6.0", "tinycolor2": "^1.6.0" } }, "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@opentui/core": ["@opentui/core@0.1.88", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "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" } }, "sha512-eaDVZfAzZraddOIkgWSHMVkyaY0O20foYnPWKPQx1TY4t7G1oatIoan2zkytx67epW+4BZQ9vGib+61/uNM1MA=="], "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.88", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oGRexWwZFeQJymOK5ORrLrwJUbPHMYaFa0EcLnlhvPnymm1xyMcRKm39ez0WSIdtiCCi/PmMHX95CfyyJB5VMA=="], @@ -147,6 +217,8 @@ "@opentui/react": ["@opentui/react@0.1.88", "", { "dependencies": { "@opentui/core": "0.1.88", "react-reconciler": "^0.32.0" }, "peerDependencies": { "react": ">=19.0.0", "react-devtools-core": "^7.0.1", "ws": "^8.18.0" } }, "sha512-EfEUBlGgCx9LqpbB852L+m7F19NcR8yeUww+C8NytIQeVKJbFIhSLu3r3wjBEGNoYiRk1DtAwWBpG5YaVvkXXw=="], + "@opentui/solid": ["@opentui/solid@0.1.107", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.107", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-zi5wbb5SsU2x70XZ1L+fBGz2BdA1TzBIgqjAlmWqOrtQai4rQzexSuz8kMzKNP6uIsDsDu3FGtgr3G9bTt9Gxg=="], + "@oven/bun-darwin-aarch64": ["@oven/bun-darwin-aarch64@1.3.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/8IzqSu4/OWGRs7Fs2ROzGVwJMFTBQkgAp6sAthkBYoN7OiM4rY/CpPVs2X9w9N1W61CHSkEdNKi8HrLZKfK3g=="], "@oven/bun-darwin-x64": ["@oven/bun-darwin-x64@1.3.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-TT7eUihnAzxM2tlZesusuC75PAOYKvUBgVU/Nm/lakZ/DpyuqhNkzUfcxSgmmK9IjVWzMmezLIGZl16XGCGJng=="], @@ -319,10 +391,24 @@ "await-to-js": ["await-to-js@3.0.0", "", {}, "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g=="], + "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.6", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-v3P1MW46Lm7VMpAkq0QfyzLWWkC8fh+0aE5Km4msIgDx5kjenHU0pF2s+4/NH8CQn/kla6+Hvws+2AF7bfV5qQ=="], + + "babel-plugin-module-resolver": ["babel-plugin-module-resolver@5.0.2", "", { "dependencies": { "find-babel-config": "^2.1.1", "glob": "^9.3.3", "pkg-up": "^3.1.0", "reselect": "^4.1.7", "resolve": "^1.22.8" } }, "sha512-9KtaCazHee2xc0ibfqsDeamwDps6FZNo5S0Q81dUqEuFzVwPhcT4J5jOqIVvgCA3Q/wO9hKYxN/Ds3tIsp5ygg=="], + + "babel-preset-solid": ["babel-preset-solid@1.9.12", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.6" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.12" }, "optionalPeers": ["solid-js"] }, "sha512-LLqnuKVDlKpyBlMPcH6qEvs/wmS9a+NczppxJ3ryS/c0O5IiSFOIBQi9GzyiGDSbcJpx4Gr87jyFTos1MyEuWg=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.27", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA=="], + "bmp-ts": ["bmp-ts@1.0.9", "", {}, "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw=="], + "brace-expansion": ["brace-expansion@2.1.0", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w=="], + + "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], "bun": ["bun@1.3.11", "", { "optionalDependencies": { "@oven/bun-darwin-aarch64": "1.3.11", "@oven/bun-darwin-x64": "1.3.11", "@oven/bun-darwin-x64-baseline": "1.3.11", "@oven/bun-linux-aarch64": "1.3.11", "@oven/bun-linux-aarch64-musl": "1.3.11", "@oven/bun-linux-x64": "1.3.11", "@oven/bun-linux-x64-baseline": "1.3.11", "@oven/bun-linux-x64-musl": "1.3.11", "@oven/bun-linux-x64-musl-baseline": "1.3.11", "@oven/bun-windows-aarch64": "1.3.11", "@oven/bun-windows-x64": "1.3.11", "@oven/bun-windows-x64-baseline": "1.3.11" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ], "bin": { "bun": "bin/bun.exe", "bunx": "bin/bunx.exe" } }, "sha512-AvXWYFO6j/ZQ7bhGm4X6eilq2JHsDVC90ZM32k2B7/srhC2gs3Sdki1QTbwrdRCo8o7eT+167vcB1yzOvPdbjA=="], @@ -341,6 +427,8 @@ "bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-zvnUl4EAsQbKsmZVu+lEJcH8axQ7MiCfqg2OmnHd6uw1THABmHaX0GbpKiHshdgadNN2Nf+4zDyTJB5YMcAdrA=="], + "caniuse-lite": ["caniuse-lite@1.0.30001792", "", {}, "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw=="], + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], @@ -359,10 +447,14 @@ "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + "cross-spawn": ["cross-spawn@5.1.0", "", { "dependencies": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A=="], "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "defaults": ["defaults@1.0.4", "", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], @@ -371,12 +463,20 @@ "diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="], + "electron-to-chromium": ["electron-to-chromium@1.5.352", "", {}, "sha512-9wHk8x6dyuimoe18EdiDPWKExNdxYqo4fn4FwOVVper6RxT3cmpBwBkWWfSOCYJjQdIco/nPhJhNLmn4Ufg1Yg=="], + "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], + "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="], "errore": ["errore@0.11.0", "", { "bin": { "errore": "dist/cli.js" } }, "sha512-/uJh8o4SYfJAPGSDynpLgKRuRWX5yTSP2BXspHVQu8XmwaX1d6ysxr1cBhjTzC1Um2Xov9BQJ2kigT9lvxHYaA=="], + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], @@ -389,6 +489,16 @@ "file-type": ["file-type@16.5.4", "", { "dependencies": { "readable-web-to-node-stream": "^3.0.0", "strtok3": "^6.2.4", "token-types": "^4.1.1" } }, "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw=="], + "find-babel-config": ["find-babel-config@2.1.2", "", { "dependencies": { "json5": "^2.2.3" } }, "sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg=="], + + "find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + "get-east-asian-width": ["get-east-asian-width@1.5.0", "", {}, "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA=="], "get-stream": ["get-stream@3.0.0", "", {}, "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ=="], @@ -399,20 +509,28 @@ "gifwrap": ["gifwrap@0.10.1", "", { "dependencies": { "image-q": "^4.0.0", "omggif": "^1.0.10" } }, "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw=="], + "glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], + "goke": ["goke@6.3.2", "", { "dependencies": { "picocolors": "^1.1.1" } }, "sha512-0CSINX0HJiBPBphPvWhce/NkTgXogvLBxeeewT4L1Oh/P1RXxaC1qV1+IGvDN5jHjtjycr4mlGmxd7i14e1V5A=="], + "hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="], + "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], "hono": ["hono@4.12.9", "", {}, "sha512-wy3T8Zm2bsEvxKZM5w21VdHDDcwVS1yUFFY6i8UobSsKfFceT7TOwhbhfKsDyx7tYQlmRM5FLpIuYvNFyjctiA=="], + "html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="], + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "image-q": ["image-q@4.0.0", "", { "dependencies": { "@types/node": "16.9.1" } }, "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw=="], + "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], + "is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="], "is-stream": ["is-stream@1.1.0", "", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], @@ -423,15 +541,23 @@ "jpeg-js": ["jpeg-js@0.4.4", "", {}, "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + "kill-port-process": ["kill-port-process@3.2.1", "", { "dependencies": { "get-them-args": "1.3.2", "pid-from-port": "1.1.3" }, "bin": { "kill-port": "dist/bin/kill-port-process.js" } }, "sha512-9rRL5uivhIaW82ES0xTeciG5dfHUVQ0MqUycyf6Y1GBzDNB/fHxKStFUqnL4hCwGp89AcrKIjJWEVZHhSUi9LQ=="], "lint-staged": ["lint-staged@16.4.0", "", { "dependencies": { "commander": "^14.0.3", "listr2": "^9.0.5", "picomatch": "^4.0.3", "string-argv": "^0.3.2", "tinyexec": "^1.0.4", "yaml": "^2.8.2" }, "bin": { "lint-staged": "bin/lint-staged.js" } }, "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw=="], "listr2": ["listr2@9.0.5", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g=="], + "locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], + "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="], - "lru-cache": ["lru-cache@4.1.5", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g=="], + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], "lru_map": ["lru_map@0.4.1", "", {}, "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg=="], @@ -453,10 +579,18 @@ "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + "minimatch": ["minimatch@8.0.7", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-V+1uQNdzybxa14e/p00HZnQNNcTjnRJjDxg2V8wtkjFctq4M7hXFws4oekyTP0Jebeq7QYtpFyOeBAjc88zvYg=="], + + "minipass": ["minipass@4.2.8", "", {}, "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + "nan": ["nan@2.26.2", "", {}, "sha512-0tTvBTYkt3tdGw22nrAy50x7gpbGCCFH3AFcyS5WiUu7Eu4vWlri1woE6qHBSfy11vksDqkiwjOnlR7WV8G1Hw=="], "node-pty": ["node-pty@0.10.1", "", { "dependencies": { "nan": "^2.14.0" } }, "sha512-JTdtUS0Im/yRsWJSx7yiW9rtpfmxqxolrtnyKwPLI+6XqTAPW/O2MjS8FYL4I5TsMbH2lVgDb2VMjp+9LoQGNg=="], + "node-releases": ["node-releases@2.0.38", "", {}, "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw=="], + "npm-run-path": ["npm-run-path@2.0.2", "", { "dependencies": { "path-key": "^2.0.0" } }, "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw=="], "omggif": ["omggif@1.0.10", "", {}, "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw=="], @@ -473,6 +607,12 @@ "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], + "p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + + "p-locate": ["p-locate@3.0.0", "", { "dependencies": { "p-limit": "^2.0.0" } }, "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ=="], + + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + "pako": ["pako@1.0.11", "", {}, "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="], "parse-bmfont-ascii": ["parse-bmfont-ascii@1.0.6", "", {}, "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA=="], @@ -481,8 +621,16 @@ "parse-bmfont-xml": ["parse-bmfont-xml@1.1.6", "", { "dependencies": { "xml-parse-from-string": "^1.0.0", "xml2js": "^0.5.0" } }, "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA=="], + "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + + "path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], + "path-key": ["path-key@2.0.1", "", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + "peek-readable": ["peek-readable@4.1.0", "", {}, "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], @@ -493,6 +641,8 @@ "pixelmatch": ["pixelmatch@5.3.0", "", { "dependencies": { "pngjs": "^6.0.0" }, "bin": { "pixelmatch": "bin/pixelmatch" } }, "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q=="], + "pkg-up": ["pkg-up@3.1.0", "", { "dependencies": { "find-up": "^3.0.0" } }, "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA=="], + "planck": ["planck@1.4.3", "", { "peerDependencies": { "stage-js": "^1.0.0-alpha.12" } }, "sha512-B+lHKhRSeg7vZOfEyEzyQVu7nx8JHcX3QgnAcHXrPW0j04XYKX5eXSiUrxH2Z5QR8OoqvjD6zKIaPMdMYAd0uA=="], "pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="], @@ -521,16 +671,28 @@ "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], + "reselect": ["reselect@4.1.8", "", {}, "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="], + + "resolve": ["resolve@1.22.12", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA=="], + "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + "s-js": ["s-js@0.4.9", "", {}, "sha512-RtpOm+cM6O0sHg6IA70wH+UC3FZcND+rccBZpBAHzlUgNO2Bm5BN+FnM8+OBxzXdwpKWFwX11JGF0MFRkhSoIQ=="], + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], "sax": ["sax@1.6.0", "", {}, "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA=="], "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], + "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "seroval": ["seroval@1.5.4", "", {}, "sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw=="], + + "seroval-plugins": ["seroval-plugins@1.5.4", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw=="], + "shebang-command": ["shebang-command@1.2.0", "", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], "shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], @@ -547,6 +709,8 @@ "slice-ansi": ["slice-ansi@8.0.0", "", { "dependencies": { "ansi-styles": "^6.2.3", "is-fullwidth-code-point": "^5.1.0" } }, "sha512-stxByr12oeeOyY2BlviTNQlYV5xOj47GirPr4yA1hE9JCtxfQN0+tVbkxwCtYDQWhEKWFHsEK48ORg5jrouCAg=="], + "solid-js": ["solid-js@1.9.12", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-QzKaSJq2/iDrWR1As6MHZQ8fQkdOBf8GReYb7L5iKwMGceg7HxDcaOHk0at66tNgn9U2U7dXo8ZZpLIAmGMzgw=="], + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], "stage-js": ["stage-js@1.0.1", "", {}, "sha512-cz14aPp/wY0s3bkb/B93BPP5ZAEhgBbRmAT3CCDqert8eCAqIpQ0RB2zpK8Ksxf+Pisl5oTzvPHtL4CVzzeHcw=="], @@ -555,18 +719,20 @@ "string-dedent": ["string-dedent@3.0.2", "", {}, "sha512-M4q+HpHCtGXlbyzYDOcOo7V185dlq6YXvGUPcWZqL4vttCX9gFYoWIOxcPd7v5CAYcTJsGLs3ZJCAH2TXONF/g=="], - "string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="], + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], - "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], "strip-eof": ["strip-eof@1.0.0", "", {}, "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q=="], "strtok3": ["strtok3@6.3.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" } }, "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw=="], + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + "three": ["three@0.177.0", "", {}, "sha512-EiXv5/qWAaGI+Vz2A+JfavwYCMdGjxVsrn3oBwllUoqYeaBO75J63ZfyaQKoiLrqNHoTlUc6PFgMXnS0kI45zg=="], "tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="], @@ -595,6 +761,8 @@ "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + "utif2": ["utif2@4.1.0", "", { "dependencies": { "pako": "^1.0.11" } }, "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w=="], "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], @@ -617,7 +785,7 @@ "xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], - "yallist": ["yallist@2.1.2", "", {}, "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="], + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "yaml": ["yaml@2.8.3", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="], @@ -661,10 +829,28 @@ "@opentui/core/diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + "@opentui/solid/@opentui/core": ["@opentui/core@0.1.107", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.107", "@opentui/core-darwin-x64": "0.1.107", "@opentui/core-linux-arm64": "0.1.107", "@opentui/core-linux-x64": "0.1.107", "@opentui/core-win32-arm64": "0.1.107", "@opentui/core-win32-x64": "0.1.107", "bun-webgpu": "0.1.7", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-gadu9EtNR+sOGyHN0buZryllavkWHRkCcX4yW/1ldp/l7HGS52hvkjYmo+74cuzUcfds/5Rbw2cgiy0Z7RxXmQ=="], + + "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], + + "cli-truncate/string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="], + + "cross-spawn/lru-cache": ["lru-cache@4.1.5", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g=="], + + "ghostty-opentui/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + "image-q/@types/node": ["@types/node@16.9.1", "", {}, "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g=="], "log-update/slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="], + "log-update/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + + "path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "path-scurry/minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], + "pixelmatch/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="], "react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], @@ -673,6 +859,36 @@ "restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], + "string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "@opentui/solid/@opentui/core/@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.107", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Yqt2/9Ntw0IdtPA/qmHvXCE16y4Jq5/btCmuzN9/opzqZ5rYGYYVtiBii3LezGcTZYuJQZthjvh8MLPXXwA2EQ=="], + + "@opentui/solid/@opentui/core/@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.107", "", { "os": "darwin", "cpu": "x64" }, "sha512-p6yeHsIWRLy/J30nZTyUuwgFYEpk8NS0H0Cmh9P8a1+eHA406MMMP4FAC0YpqlF4SHb7R7LNkUSsfCx9yMtS8w=="], + + "@opentui/solid/@opentui/core/@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.107", "", { "os": "linux", "cpu": "arm64" }, "sha512-w6MpRTd06KUH4KdgH4x7rVB2I67KE62w3W3jQVBDEMeJejdJVOSwwUdgaTY9ffoHglcZc3WA2PFH1PCpgzna4A=="], + + "@opentui/solid/@opentui/core/@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.107", "", { "os": "linux", "cpu": "x64" }, "sha512-oxKbIpWZRgY+8KQZ9dXq8lzDEhMVpBMCiZGDiHtK8/DP1MvK5kFE/vtwgUK9YkmT4OSgZsFeojjvyePXV+PcfQ=="], + + "@opentui/solid/@opentui/core/@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.107", "", { "os": "win32", "cpu": "arm64" }, "sha512-T7hbLgoTkb5eAsP5GJdTRyDl48WI/hMEtj+BGlIITzSaOBSN7ZPCeblcfUz+uXrdF6g3dF1a9uyEQSJlzeGaKA=="], + + "@opentui/solid/@opentui/core/@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.107", "", { "os": "win32", "cpu": "x64" }, "sha512-e/uFLPyKK/hFDvDZtTxp6L3Zx0FWuZv5Gf2qIKf/7FAAadD0hala+K41OJAmYWxu1X3cT5XozKCT8gN/S1N08A=="], + + "@opentui/solid/@opentui/core/bun-webgpu": ["bun-webgpu@0.1.7", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.7", "bun-webgpu-darwin-x64": "^0.1.7", "bun-webgpu-linux-x64": "^0.1.7", "bun-webgpu-win32-x64": "^0.1.7" } }, "sha512-KUxUp+oQIf7pPBMD4Hv1TUu7DWaOZ4ciKulTk9to9+Uc8yHoYrMW7L2SJCJ4FHHkywgf/7aLRgRx0b7i6DvGIQ=="], + + "@opentui/solid/@opentui/core/diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], + + "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "cross-spawn/lru-cache/yallist": ["yallist@2.1.2", "", {}, "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="], + + "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mRrFFyHzPWjsTRidAZBRcu808CPQBOUL0P6b4nxLhp+XHcV/mbUHERZMgW9s58tsojQfSdzschiQa8q+JCgRWA=="], + + "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-g0NXGNgvaVCSH/jCWWlfdiquOHkbUN6vP4zqzSkIxWKQeLnqm3oADcok7SO3yIgI7v5mKpRc/ks7NDEKNH+jNQ=="], + + "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.7", "", { "os": "linux", "cpu": "x64" }, "sha512-UEP7UZdEhx9otvkZczjsszL8ZVlrODANQvgl+C88/bNVmxDoFi7w1fWzGi1sZyakiETjmtFDq2/xCLhbSZxjqw=="], + + "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.7", "", { "os": "win32", "cpu": "x64" }, "sha512-KZktiFkBz6sN7PEm1NVdeaLP5Q5X/PlSHZqefY4nNuWtf0LNvh54NhZe7yVv/Plz/nGbv92b0KHMBY3ki/pp6g=="], } } diff --git a/package.json b/package.json index 36dcd6b4..d4d55317 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,10 @@ "types": "./dist/npm/opentui/index.d.ts", "import": "./dist/npm/opentui/index.js" }, + "./opentui-solid": { + "types": "./dist/npm/opentui-solid/index.d.ts", + "import": "./dist/npm/opentui-solid/index.js" + }, "./package.json": "./package.json" }, "publishConfig": { @@ -88,6 +92,7 @@ "@hunk/session-broker-node": "workspace:*", "@opentui/core": "^0.1.88", "@opentui/react": "^0.1.88", + "@opentui/solid": "^0.1.88", "@types/bun": "1.3.13", "@types/react": "^19.2.14", "@types/ws": "^8.18.1", @@ -96,13 +101,24 @@ "oxlint": "^1.56.0", "react": "^19.2.4", "simple-git-hooks": "^2.13.1", + "solid-js": "^1.9.0", "tuistory": "^0.0.16", "typescript": "^5.9.3" }, "peerDependencies": { "@opentui/core": "^0.1.88", "@opentui/react": "^0.1.88", - "react": "^19.2.4" + "@opentui/solid": "^0.1.88", + "react": "^19.2.4", + "solid-js": "^1.9.0" + }, + "peerDependenciesMeta": { + "@opentui/solid": { + "optional": true + }, + "solid-js": { + "optional": true + } }, "simple-git-hooks": { "pre-commit": "bunx lint-staged" diff --git a/scripts/build-npm.ts b/scripts/build-npm.ts index c4be9c6d..363ee59b 100644 --- a/scripts/build-npm.ts +++ b/scripts/build-npm.ts @@ -8,6 +8,7 @@ const outdir = path.join(repoRoot, "dist", "npm"); const typesOutdir = path.join(repoRoot, "dist", "npm-types"); const opentuiOutdir = path.join(outdir, "opentui"); const opentuiTypesDir = path.join(typesOutdir, "opentui"); +const opentuiSolidOutdir = path.join(outdir, "opentui-solid"); const bunEnv = { ...process.env, @@ -32,6 +33,7 @@ function runBun(args: string[]) { rmSync(outdir, { recursive: true, force: true }); rmSync(typesOutdir, { recursive: true, force: true }); mkdirSync(opentuiOutdir, { recursive: true }); +mkdirSync(opentuiSolidOutdir, { recursive: true }); runBun([ "build", @@ -81,6 +83,39 @@ runBun([ "index.js", ]); +runBun([ + "build", + path.join(repoRoot, "src", "opentui-solid", "index.ts"), + "--target", + "node", + "--format", + "esm", + "--external", + "solid-js", + "--external", + "solid-js/web", + "--external", + "solid-js/html", + "--external", + "@opentui/core", + "--external", + "@opentui/solid", + "--external", + "@opentui/solid/jsx-runtime", + "--external", + "@opentui/solid/jsx-dev-runtime", + "--external", + "@pierre/diffs", + "--external", + "react", + "--external", + "react/jsx-runtime", + "--outdir", + opentuiSolidOutdir, + "--entry-naming", + "index.js", +]); + runBun(["x", "tsc", "-p", path.join(repoRoot, "tsconfig.opentui.json")]); for (const entry of readdirSync(opentuiTypesDir)) { @@ -89,7 +124,13 @@ for (const entry of readdirSync(opentuiTypesDir)) { } } +copyFileSync( + path.join(repoRoot, "src", "opentui-solid", "index.d.ts"), + path.join(opentuiSolidOutdir, "index.d.ts"), +); + rmSync(typesOutdir, { recursive: true, force: true }); console.log(`Built ${mainJs}`); console.log(`Built ${path.join(opentuiOutdir, "index.js")}`); +console.log(`Built ${path.join(opentuiSolidOutdir, "index.js")}`); diff --git a/src/opentui-solid/HunkDiffBody.tsx b/src/opentui-solid/HunkDiffBody.tsx new file mode 100644 index 00000000..ac11a6cf --- /dev/null +++ b/src/opentui-solid/HunkDiffBody.tsx @@ -0,0 +1,94 @@ +/** @jsxImportSource @opentui/solid */ +import { createMemo } from "solid-js"; +import { findMaxLineNumber } from "../ui/diff/codeColumns"; +import { buildSplitRows, buildStackRows } from "../ui/diff/pierre"; +import { diffMessage, DiffRowViewComponent, fitText } from "../ui/diff/renderRows"; +import { useHighlightedDiff } from "./useHighlightedDiff"; +import { resolveTheme } from "../ui/themes"; +import { toInternalDiffFile } from "../opentui/model"; +import type { HunkDiffBodyProps } from "../opentui/types"; + +/** + * Agent note / hunk annotation highlighting is intentionally disabled in the + * `opentui` / `opentui-solid` primitive exports. Annotations require the full + * Hunk app shell (session broker, agent context loading, note state). Both + * React and Solid entrypoints share this parity — see src/opentui/HunkDiffBody.tsx. + */ +const EMPTY_ANNOTATED_HUNK_INDICES = new Set(); + +/** Render one diff file body without owning navigation, app chrome, or global shortcuts. */ +export function HunkDiffBody(props: HunkDiffBodyProps) { + const layout = () => props.layout ?? "split"; + const width = () => props.width; + const showLineNumbers = () => props.showLineNumbers ?? true; + const showHunkHeaders = () => props.showHunkHeaders ?? true; + const wrapLines = () => props.wrapLines ?? false; + const horizontalOffset = () => props.horizontalOffset ?? 0; + const highlight = () => props.highlight ?? true; + const selectedHunkIndex = () => props.selectedHunkIndex ?? 0; + + const resolvedTheme = resolveTheme(props.theme, null); + const internalFile = createMemo(() => (props.file ? toInternalDiffFile(props.file) : undefined)); + const resolvedHighlighted = useHighlightedDiff({ + get file() { + return internalFile(); + }, + get appearance() { + return resolvedTheme.appearance; + }, + get shouldLoadHighlight() { + return highlight(); + }, + }); + const rows = createMemo(() => + internalFile() + ? layout() === "split" + ? buildSplitRows(internalFile()!, resolvedHighlighted(), resolvedTheme) + : buildStackRows(internalFile()!, resolvedHighlighted(), resolvedTheme) + : [], + ); + const lineNumberDigits = createMemo( + () => String(internalFile() ? findMaxLineNumber(internalFile()!) : 1).length, + ); + + if (!internalFile()) { + return ( + + + {fitText("No file selected.", Math.max(1, width() - 2))} + + + ); + } + + if (internalFile()!.metadata.hunks.length === 0) { + return ( + + + {fitText(diffMessage(internalFile()!), Math.max(1, width() - 2))} + + + ); + } + + return ( + + {rows().map((row) => ( + + + + ))} + + ); +} diff --git a/src/opentui-solid/HunkDiffFileHeader.tsx b/src/opentui-solid/HunkDiffFileHeader.tsx new file mode 100644 index 00000000..a36f40a1 --- /dev/null +++ b/src/opentui-solid/HunkDiffFileHeader.tsx @@ -0,0 +1,28 @@ +/** @jsxImportSource @opentui/solid */ +import { createMemo } from "solid-js"; +import { DiffFileHeaderRow } from "../ui/components/panes/DiffFileHeaderRow"; +import { resolveTheme } from "../ui/themes"; +import { toInternalDiffFile } from "../opentui/model"; +import type { HunkDiffFileHeaderProps } from "../opentui/types"; + +/** Render Hunk's compact file header row for custom OpenTUI review layouts. */ +export function HunkDiffFileHeader(props: HunkDiffFileHeaderProps) { + const resolvedTheme = resolveTheme(props.theme, null); + const internalFile = createMemo(() => toInternalDiffFile(props.file)); + const headerStatsWidth = () => + Math.max( + 7, + `+${internalFile().stats.additions}${internalFile().statsTruncated ? "+" : ""} -${internalFile().stats.deletions}` + .length, + ); + + return ( + + ); +} diff --git a/src/opentui-solid/HunkDiffView.tsx b/src/opentui-solid/HunkDiffView.tsx new file mode 100644 index 00000000..b0fa6d46 --- /dev/null +++ b/src/opentui-solid/HunkDiffView.tsx @@ -0,0 +1,19 @@ +/** @jsxImportSource @opentui/solid */ +import { HunkDiffBody } from "./HunkDiffBody"; +import type { HunkDiffViewProps } from "../opentui/types"; + +/** Render one diff file body with an optional OpenTUI scrollbox wrapper. */ +export function HunkDiffView(props: HunkDiffViewProps) { + const scrollable = props.scrollable ?? true; + const content = ; + + if (!scrollable) { + return content; + } + + return ( + + {content} + + ); +} diff --git a/src/opentui-solid/HunkFileNav.tsx b/src/opentui-solid/HunkFileNav.tsx new file mode 100644 index 00000000..25fa4be4 --- /dev/null +++ b/src/opentui-solid/HunkFileNav.tsx @@ -0,0 +1,43 @@ +/** @jsxImportSource @opentui/solid */ +import { createMemo } from "solid-js"; +import { FileGroupHeader, FileListItem } from "../ui/components/panes/FileListItem"; +import { buildSidebarEntries, sidebarEntryStatsWidth } from "../ui/lib/files"; +import { resolveTheme } from "../ui/themes"; +import { toInternalDiffFiles } from "../opentui/model"; +import type { HunkFileNavProps } from "../opentui/types"; + +/** Render Hunk's file navigation list without global shortcuts, scrolling, borders, or surrounding chrome. */ +export function HunkFileNav(props: HunkFileNavProps) { + const resolvedTheme = resolveTheme(props.theme, null); + const internalFiles = createMemo(() => toInternalDiffFiles(props.files)); + const entries = createMemo(() => buildSidebarEntries(internalFiles())); + const fileEntries = () => entries().filter((entry) => entry.kind === "file"); + const statsWidth = () => + Math.max(0, ...fileEntries().map((entry) => sidebarEntryStatsWidth(entry))); + const textWidth = () => Math.max(1, props.width - 1); + + return ( + + {entries().map((entry) => + entry.kind === "group" ? ( + + ) : ( + props.onSelectFile?.(entry.id)} + /> + ), + )} + + ); +} diff --git a/src/opentui-solid/HunkReviewStream.tsx b/src/opentui-solid/HunkReviewStream.tsx new file mode 100644 index 00000000..9adb5533 --- /dev/null +++ b/src/opentui-solid/HunkReviewStream.tsx @@ -0,0 +1,83 @@ +/** @jsxImportSource @opentui/solid */ +import { createMemo } from "solid-js"; +import { resolveTheme } from "../ui/themes"; +import { HunkDiffBody } from "./HunkDiffBody"; +import { HunkDiffFileHeader } from "./HunkDiffFileHeader"; +import type { HunkDiffFileInput, HunkDiffSelection, HunkReviewStreamProps } from "../opentui/types"; + +/** Resolve the active selection, defaulting to the first file and first hunk. */ +function resolveSelection(files: HunkDiffFileInput[], selection: HunkDiffSelection | undefined) { + if (selection && files.some((file) => file.id === selection.fileId)) { + return selection; + } + + const first = files[0]; + return first ? { fileId: first.id, hunkIndex: 0 } : undefined; +} + +/** Render a top-to-bottom multi-file review stream without Hunk's app shell, keybindings, or scrolling. */ +export function HunkReviewStream(props: HunkReviewStreamProps) { + const resolvedTheme = resolveTheme(props.theme, null); + const activeSelection = createMemo(() => resolveSelection(props.files, props.selection)); + + if (props.files.length === 0) { + return ( + + No files to render. + + ); + } + + const showFileSeparators = () => props.showFileSeparators ?? true; + const showFileHeaders = () => props.showFileHeaders ?? true; + const showLineNumbers = () => props.showLineNumbers ?? true; + const showHunkHeaders = () => props.showHunkHeaders ?? true; + const wrapLines = () => props.wrapLines ?? false; + const horizontalOffset = () => props.horizontalOffset ?? 0; + const highlight = () => props.highlight ?? true; + + return ( + + {props.files.map((file, index) => { + const selectedHunkIndex = + activeSelection()?.fileId === file.id ? activeSelection()!.hunkIndex : -1; + + return ( + + {showFileSeparators() && index > 0 ? ( + + {"─".repeat(Math.max(1, props.width - 2))} + + ) : null} + {showFileHeaders() ? ( + props.onSelectionChange?.({ fileId: file.id, hunkIndex: 0 })} + /> + ) : null} + + + ); + })} + + ); +} diff --git a/src/opentui-solid/build-verification.test.ts b/src/opentui-solid/build-verification.test.ts new file mode 100644 index 00000000..2aa8a544 --- /dev/null +++ b/src/opentui-solid/build-verification.test.ts @@ -0,0 +1,18 @@ +import { describe, expect, test } from "bun:test"; + +describe("Solid OpenTUI build verification", () => { + test("build artifact exists", () => { + const js = Bun.file("dist/npm/opentui-solid/index.js"); + const dts = Bun.file("dist/npm/opentui-solid/index.d.ts"); + expect(js.size).toBeGreaterThan(0); + expect(dts.size).toBeGreaterThan(0); + }); + + test("package.json exports the solid entrypoint", async () => { + const text = await Bun.file("package.json").text(); + const pkg = JSON.parse(text); + expect(pkg.exports["./opentui-solid"]).toBeDefined(); + expect(pkg.exports["./opentui-solid"].import).toBe("./dist/npm/opentui-solid/index.js"); + expect(pkg.exports["./opentui-solid"].types).toBe("./dist/npm/opentui-solid/index.d.ts"); + }); +}); diff --git a/src/opentui-solid/index.d.ts b/src/opentui-solid/index.d.ts new file mode 100644 index 00000000..3510bd38 --- /dev/null +++ b/src/opentui-solid/index.d.ts @@ -0,0 +1,30 @@ +export { parseDiffFromFile, parsePatchFiles, type FileDiffMetadata } from "@pierre/diffs"; +export { HUNK_DIFF_THEME_NAMES, type HunkDiffThemeName } from "../opentui/themes"; +export { + countHunkDiffStats, + createHunkDiffFile, + createHunkDiffFilesFromPatch, +} from "../opentui/model"; +export type { + HunkDiffBodyProps, + HunkDiffFile, + HunkDiffFileHeaderProps, + HunkDiffFileInput, + HunkDiffLayout, + HunkDiffSelection, + HunkDiffStats, + HunkDiffViewProps, + HunkFileNavProps, + HunkReviewStreamProps, +} from "../opentui/types"; + +/** @solid-reconciler */ +export declare function HunkDiffBody(props: HunkDiffBodyProps): any; +/** @solid-reconciler */ +export declare function HunkDiffFileHeader(props: HunkDiffFileHeaderProps): any; +/** @solid-reconciler */ +export declare function HunkDiffView(props: HunkDiffViewProps): any; +/** @solid-reconciler */ +export declare function HunkFileNav(props: HunkFileNavProps): any; +/** @solid-reconciler */ +export declare function HunkReviewStream(props: HunkReviewStreamProps): any; diff --git a/src/opentui-solid/index.ts b/src/opentui-solid/index.ts new file mode 100644 index 00000000..3bf1e857 --- /dev/null +++ b/src/opentui-solid/index.ts @@ -0,0 +1,24 @@ +export { parseDiffFromFile, parsePatchFiles, type FileDiffMetadata } from "@pierre/diffs"; +export { HUNK_DIFF_THEME_NAMES, type HunkDiffThemeName } from "../opentui/themes"; +export { HunkDiffBody } from "./HunkDiffBody"; +export { HunkDiffFileHeader } from "./HunkDiffFileHeader"; +export { HunkDiffView } from "./HunkDiffView"; +export { HunkFileNav } from "./HunkFileNav"; +export { HunkReviewStream } from "./HunkReviewStream"; +export { + countHunkDiffStats, + createHunkDiffFile, + createHunkDiffFilesFromPatch, +} from "../opentui/model"; +export type { + HunkDiffBodyProps, + HunkDiffFile, + HunkDiffFileHeaderProps, + HunkDiffFileInput, + HunkDiffLayout, + HunkDiffSelection, + HunkDiffStats, + HunkDiffViewProps, + HunkFileNavProps, + HunkReviewStreamProps, +} from "../opentui/types"; diff --git a/src/opentui-solid/jsx-augmentation.d.ts b/src/opentui-solid/jsx-augmentation.d.ts new file mode 100644 index 00000000..acf4bd91 --- /dev/null +++ b/src/opentui-solid/jsx-augmentation.d.ts @@ -0,0 +1,15 @@ +// Augment Solid OpenTUI JSX types so hunk's framework-agnostic internal +// diff rendering components typecheck under both React and Solid reconcilers. + +declare module "solid-js" { + namespace JSX { + interface BoxProps { + key?: string | number; + } + interface SpanProps { + key?: string | number; + fg?: string; + bg?: string; + } + } +} diff --git a/src/opentui-solid/useHighlightedDiff.ts b/src/opentui-solid/useHighlightedDiff.ts new file mode 100644 index 00000000..2bb706d1 --- /dev/null +++ b/src/opentui-solid/useHighlightedDiff.ts @@ -0,0 +1,75 @@ +import { createEffect, createSignal } from "solid-js"; +import type { DiffFile } from "../core/types"; +import type { HighlightedDiffCode } from "../ui/diff/pierre"; +import { + buildCacheKey, + ensureHighlightedDiffLoaded, + resolveHighlightedSnapshot, +} from "../ui/diff/highlightCache"; + +/** Resolve highlighted diff content with shared caching and background prefetch support. */ +export function useHighlightedDiff(props: { + get file(): DiffFile | undefined; + get appearance(): "light" | "dark"; + get shouldLoadHighlight(): boolean | undefined; +}) { + const [highlighted, setHighlighted] = createSignal(null); + const [highlightedCacheKey, setHighlightedCacheKey] = createSignal(null); + + createEffect(() => { + const currentFile = props.file; + const currentAppearance = props.appearance; + const shouldLoadHighlight = props.shouldLoadHighlight; + const appearanceCacheKey = currentFile ? buildCacheKey(currentAppearance, currentFile) : null; + + if (!currentFile || !appearanceCacheKey) { + setHighlighted(null); + setHighlightedCacheKey(null); + return; + } + + if (highlightedCacheKey() === appearanceCacheKey) { + return; + } + + const cached = resolveHighlightedSnapshot({ + appearanceCacheKey, + highlighted: highlighted(), + highlightedCacheKey: highlightedCacheKey(), + }); + if (cached) { + setHighlighted(cached); + setHighlightedCacheKey(appearanceCacheKey); + return; + } + + if (!shouldLoadHighlight) { + return; + } + + let cancelled = false; + setHighlighted(null); + + ensureHighlightedDiffLoaded(currentFile, currentAppearance, appearanceCacheKey).then( + (nextHighlighted) => { + if (cancelled) { + return; + } + + setHighlighted(nextHighlighted); + setHighlightedCacheKey(appearanceCacheKey); + }, + ); + + return () => { + cancelled = true; + }; + }); + + return () => + resolveHighlightedSnapshot({ + appearanceCacheKey: props.file ? buildCacheKey(props.appearance, props.file) : null, + highlighted: highlighted(), + highlightedCacheKey: highlightedCacheKey(), + }); +} diff --git a/src/opentui/HunkDiffBody.tsx b/src/opentui/HunkDiffBody.tsx index b0eea59d..3488f3ad 100644 --- a/src/opentui/HunkDiffBody.tsx +++ b/src/opentui/HunkDiffBody.tsx @@ -1,7 +1,8 @@ import { useMemo } from "react"; import { findMaxLineNumber } from "../ui/diff/codeColumns"; import { buildSplitRows, buildStackRows } from "../ui/diff/pierre"; -import { diffMessage, DiffRowView, fitText } from "../ui/diff/renderRows"; +import { diffMessage, fitText } from "../ui/diff/renderRows"; +import { DiffRowView } from "../ui/diff/DiffRowView"; import { useHighlightedDiff } from "../ui/diff/useHighlightedDiff"; import { resolveTheme } from "../ui/themes"; import { toInternalDiffFile } from "./model"; diff --git a/src/ui/diff/DiffRowView.tsx b/src/ui/diff/DiffRowView.tsx new file mode 100644 index 00000000..bed850a7 --- /dev/null +++ b/src/ui/diff/DiffRowView.tsx @@ -0,0 +1,20 @@ +import { memo } from "react"; +import { DiffRowViewComponent } from "./renderRows"; + +/** Render one diff row, memoized to avoid unnecessary rerenders. */ +export const DiffRowView = memo(DiffRowViewComponent, (previous, next) => { + return ( + previous.row === next.row && + previous.width === next.width && + previous.lineNumberDigits === next.lineNumberDigits && + previous.showLineNumbers === next.showLineNumbers && + previous.showHunkHeaders === next.showHunkHeaders && + previous.wrapLines === next.wrapLines && + previous.codeHorizontalOffset === next.codeHorizontalOffset && + previous.theme === next.theme && + previous.selected === next.selected && + previous.annotated === next.annotated && + previous.anchorId === next.anchorId && + previous.noteGuideSide === next.noteGuideSide + ); +}); diff --git a/src/ui/diff/PierreDiffView.tsx b/src/ui/diff/PierreDiffView.tsx index 0060525d..e820fe1c 100644 --- a/src/ui/diff/PierreDiffView.tsx +++ b/src/ui/diff/PierreDiffView.tsx @@ -10,7 +10,8 @@ import { buildSplitRows, buildStackRows } from "./pierre"; import { plannedReviewRowVisible } from "./plannedReviewRows"; import { buildReviewRenderPlan } from "./reviewRenderPlan"; import { resolveVisiblePlannedRowWindow, type VisibleBodyBounds } from "./rowWindowing"; -import { diffMessage, DiffRowView, fitText } from "./renderRows"; +import { diffMessage, fitText } from "./renderRows"; +import { DiffRowView } from "./DiffRowView"; import { useHighlightedDiff } from "./useHighlightedDiff"; const EMPTY_ANNOTATED_HUNK_INDICES = new Set(); diff --git a/src/ui/diff/highlightCache.test.ts b/src/ui/diff/highlightCache.test.ts new file mode 100644 index 00000000..8b0b038c --- /dev/null +++ b/src/ui/diff/highlightCache.test.ts @@ -0,0 +1,93 @@ +import { describe, expect, test } from "bun:test"; +import { + buildCacheKey, + ensureHighlightedDiffLoaded, + resolveHighlightedSnapshot, +} from "./highlightCache"; + +describe("buildCacheKey", () => { + test("returns a stable cache key for the same file and appearance", () => { + const file = { + id: "test-file", + patch: "@@ -1,3 +1,3 @@\n-old\n+new", + metadata: { + name: "test.ts", + hunks: [], + }, + } as any; + + const key1 = buildCacheKey("dark", file); + const key2 = buildCacheKey("dark", file); + + expect(key1).toBe(key2); + }); + + test("returns different keys for different appearances", () => { + const file = { + id: "test-file", + patch: "@@ -1,3 +1,3 @@\n-old\n+new", + metadata: { + name: "test.ts", + hunks: [], + }, + } as any; + + const darkKey = buildCacheKey("dark", file); + const lightKey = buildCacheKey("light", file); + + expect(darkKey).not.toBe(lightKey); + }); +}); + +describe("resolveHighlightedSnapshot", () => { + test("returns null when cache key is null", () => { + const result = resolveHighlightedSnapshot({ + appearanceCacheKey: null, + highlighted: null, + highlightedCacheKey: null, + }); + + expect(result).toBeNull(); + }); + + test("returns cached result when keys match", () => { + const highlighted = { deletionLines: [], additionLines: [] }; + + const result = resolveHighlightedSnapshot({ + appearanceCacheKey: "dark:test:abc", + highlighted, + highlightedCacheKey: "dark:test:abc", + }); + + expect(result).toBe(highlighted); + }); + + test("returns null when keys mismatch and no shared cache entry", () => { + const highlighted = { deletionLines: [], additionLines: [] }; + + const result = resolveHighlightedSnapshot({ + appearanceCacheKey: "dark:test:abc", + highlighted, + highlightedCacheKey: "light:test:def", + }); + + expect(result).toBeNull(); + }); +}); + +describe("ensureHighlightedDiffLoaded", () => { + test("returns a promise for non-cached file", () => { + const file = { + id: "uncached", + patch: "", + metadata: { + name: "test.ts", + hunks: [], + }, + } as any; + + const promise = ensureHighlightedDiffLoaded(file, "dark"); + + expect(promise).toBeInstanceOf(Promise); + }); +}); diff --git a/src/ui/diff/highlightCache.ts b/src/ui/diff/highlightCache.ts new file mode 100644 index 00000000..12177b01 --- /dev/null +++ b/src/ui/diff/highlightCache.ts @@ -0,0 +1,160 @@ +import type { DiffFile } from "../../core/types"; +import { loadHighlightedDiff, type HighlightedDiffCode } from "./pierre"; + +/** Maximum cached highlight results. Prevents unbounded growth during long watch sessions. */ +const MAX_CACHE_ENTRIES = 150; + +const SHARED_HIGHLIGHTED_DIFF_CACHE = new Map(); +const SHARED_HIGHLIGHT_PROMISES = new Map>(); + +/** Evict the oldest entries when the cache exceeds MAX_CACHE_ENTRIES. + * Map iteration order is insertion order, so the first keys are the oldest. */ +function enforceCacheLimit() { + while (SHARED_HIGHLIGHTED_DIFF_CACHE.size > MAX_CACHE_ENTRIES) { + const oldest = SHARED_HIGHLIGHTED_DIFF_CACHE.keys().next().value; + if (oldest !== undefined) { + SHARED_HIGHLIGHTED_DIFF_CACHE.delete(oldest); + } + } +} + +/** Summarize rendered diff lines without serializing whole arrays into the cache key. */ +function lineSetFingerprint(lines: string[] | undefined) { + let totalChars = 0; + let hash = 2166136261; + + for (const line of lines ?? []) { + totalChars += line.length; + + for (let index = 0; index < line.length; index += 1) { + hash ^= line.charCodeAt(index); + hash = Math.imul(hash, 16777619); + } + + hash ^= 10; + hash = Math.imul(hash, 16777619); + } + + return `${lines?.length ?? 0}:${totalChars}:${(hash >>> 0).toString(36)}`; +} + +/** Build a fallback fingerprint from parsed metadata when raw patch text is unavailable. */ +function metadataFingerprint(file: DiffFile) { + const hunkSummary = file.metadata.hunks + .map( + (hunk) => + `${hunk.hunkSpecs ?? ""}:${hunk.deletionStart}:${hunk.deletionCount}:${hunk.additionStart}:${hunk.additionCount}:${hunk.hunkContent.length}`, + ) + .join("|"); + + return [ + file.metadata.name, + file.metadata.prevName ?? "", + file.metadata.type, + lineSetFingerprint(file.metadata.deletionLines), + lineSetFingerprint(file.metadata.additionLines), + hunkSummary, + ].join(":"); +} + +/** Content fingerprint from the diff patch. Changes whenever the underlying diff + * changes, allowing per-file cache invalidation without a global flush. */ +function patchFingerprint(file: DiffFile) { + const { patch } = file; + if (patch.length === 0) { + return metadataFingerprint(file); + } + + const mid = Math.floor(patch.length / 2); + return `${patch.length}:${patch.slice(0, 64)}:${patch.slice(mid, mid + 64)}:${patch.slice(-64)}`; +} + +/** Cache key that includes a content fingerprint so stale entries are never served + * after reload. Unchanged files keep their cache hit across reloads. */ +export function buildCacheKey(appearance: string, file: DiffFile) { + return `${appearance}:${file.id}:${patchFingerprint(file)}`; +} + +/** Only commit a highlight result if the promise is still the active one for that key. + * Prevents a superseded or late-resolving promise from overwriting a newer entry. */ +function commitHighlightResult( + cacheKey: string, + promise: Promise, + result: HighlightedDiffCode, +) { + if (SHARED_HIGHLIGHT_PROMISES.get(cacheKey) !== promise) { + return false; + } + + SHARED_HIGHLIGHT_PROMISES.delete(cacheKey); + SHARED_HIGHLIGHTED_DIFF_CACHE.set(cacheKey, result); + enforceCacheLimit(); + return true; +} + +/** Start one shared highlight request unless the cache or an in-flight promise already has it. */ +export function ensureHighlightedDiffLoaded( + file: DiffFile, + appearance: "light" | "dark", + cacheKey = buildCacheKey(appearance, file), +) { + const cached = SHARED_HIGHLIGHTED_DIFF_CACHE.get(cacheKey); + if (cached) { + return Promise.resolve(cached); + } + + const existing = SHARED_HIGHLIGHT_PROMISES.get(cacheKey); + if (existing) { + return existing; + } + + let pending: Promise; + pending = loadHighlightedDiff(file, appearance) + .then((nextHighlighted) => { + commitHighlightResult(cacheKey, pending, nextHighlighted); + return nextHighlighted; + }) + .catch(() => { + const fallback = { + deletionLines: [], + additionLines: [], + } satisfies HighlightedDiffCode; + commitHighlightResult(cacheKey, pending, fallback); + return fallback; + }); + + SHARED_HIGHLIGHT_PROMISES.set(cacheKey, pending); + return pending; +} + +/** Queue syntax highlighting for one file without mounting its diff rows first. */ +export function prefetchHighlightedDiff({ + file, + appearance, +}: { + file: DiffFile; + appearance: "light" | "dark"; +}) { + return ensureHighlightedDiffLoaded(file, appearance); +} + +/** Read the best already-available highlight result without starting async work during render. */ +export function resolveHighlightedSnapshot({ + appearanceCacheKey, + highlighted, + highlightedCacheKey, +}: { + appearanceCacheKey: string | null; + highlighted: HighlightedDiffCode | null; + highlightedCacheKey: string | null; +}) { + if (!appearanceCacheKey) { + return null; + } + + if (highlightedCacheKey === appearanceCacheKey) { + return highlighted; + } + + return SHARED_HIGHLIGHTED_DIFF_CACHE.get(appearanceCacheKey) ?? null; +} diff --git a/src/ui/diff/renderRows.tsx b/src/ui/diff/renderRows.tsx index 3576e074..07212dc7 100644 --- a/src/ui/diff/renderRows.tsx +++ b/src/ui/diff/renderRows.tsx @@ -1,4 +1,3 @@ -import { memo, type ReactNode } from "react"; import type { DiffFile } from "../../core/types"; import type { AppTheme } from "../themes"; import { @@ -609,7 +608,7 @@ function renderRow( noteGuideSide?: "old" | "new", onOpenAgentNotesAtHunk?: (hunkIndex: number) => void, ) { - let baseRow: ReactNode; + let baseRow: any; if (row.type === "collapsed") { baseRow = renderHeaderRow( @@ -826,7 +825,7 @@ function renderRow( return baseRow; } -interface DiffRowViewProps { +export interface DiffRowViewProps { row: DiffRow; width: number; lineNumberDigits: number; @@ -842,9 +841,23 @@ interface DiffRowViewProps { onOpenAgentNotesAtHunk?: (hunkIndex: number) => void; } -/** Render one diff row, memoized to avoid unnecessary rerenders. */ -export const DiffRowView = memo( - function DiffRowViewComponent({ +/** Render one diff row without React.memo wrapper. Used by both React and Solid reconcilers. */ +export function DiffRowViewComponent({ + row, + width, + lineNumberDigits, + showLineNumbers, + showHunkHeaders, + wrapLines, + codeHorizontalOffset, + theme, + selected, + annotated, + anchorId, + noteGuideSide, + onOpenAgentNotesAtHunk, +}: DiffRowViewProps) { + return renderRow( row, width, lineNumberDigits, @@ -858,37 +871,5 @@ export const DiffRowView = memo( anchorId, noteGuideSide, onOpenAgentNotesAtHunk, - }: DiffRowViewProps) { - return renderRow( - row, - width, - lineNumberDigits, - showLineNumbers, - showHunkHeaders, - wrapLines, - codeHorizontalOffset, - theme, - selected, - annotated, - anchorId, - noteGuideSide, - onOpenAgentNotesAtHunk, - ); - }, - (previous, next) => { - return ( - previous.row === next.row && - previous.width === next.width && - previous.lineNumberDigits === next.lineNumberDigits && - previous.showLineNumbers === next.showLineNumbers && - previous.showHunkHeaders === next.showHunkHeaders && - previous.wrapLines === next.wrapLines && - previous.codeHorizontalOffset === next.codeHorizontalOffset && - previous.theme === next.theme && - previous.selected === next.selected && - previous.annotated === next.annotated && - previous.anchorId === next.anchorId && - previous.noteGuideSide === next.noteGuideSide - ); - }, -); + ); +} diff --git a/src/ui/diff/useHighlightedDiff.ts b/src/ui/diff/useHighlightedDiff.ts index 9cac013b..67111da3 100644 --- a/src/ui/diff/useHighlightedDiff.ts +++ b/src/ui/diff/useHighlightedDiff.ts @@ -1,164 +1,12 @@ import { useLayoutEffect, useState } from "react"; import type { DiffFile } from "../../core/types"; -import { loadHighlightedDiff, type HighlightedDiffCode } from "./pierre"; - -/** Maximum cached highlight results. Prevents unbounded growth during long watch sessions. */ -const MAX_CACHE_ENTRIES = 150; - -const SHARED_HIGHLIGHTED_DIFF_CACHE = new Map(); -const SHARED_HIGHLIGHT_PROMISES = new Map>(); - -/** Evict the oldest entries when the cache exceeds MAX_CACHE_ENTRIES. - * Map iteration order is insertion order, so the first keys are the oldest. */ -function enforceCacheLimit() { - while (SHARED_HIGHLIGHTED_DIFF_CACHE.size > MAX_CACHE_ENTRIES) { - const oldest = SHARED_HIGHLIGHTED_DIFF_CACHE.keys().next().value; - if (oldest !== undefined) { - SHARED_HIGHLIGHTED_DIFF_CACHE.delete(oldest); - } - } -} - -/** Summarize rendered diff lines without serializing whole arrays into the cache key. */ -function lineSetFingerprint(lines: string[] | undefined) { - let totalChars = 0; - let hash = 2166136261; - - for (const line of lines ?? []) { - totalChars += line.length; - - for (let index = 0; index < line.length; index += 1) { - hash ^= line.charCodeAt(index); - hash = Math.imul(hash, 16777619); - } - - hash ^= 10; - hash = Math.imul(hash, 16777619); - } - - return `${lines?.length ?? 0}:${totalChars}:${(hash >>> 0).toString(36)}`; -} - -/** Build a fallback fingerprint from parsed metadata when raw patch text is unavailable. */ -function metadataFingerprint(file: DiffFile) { - const hunkSummary = file.metadata.hunks - .map( - (hunk) => - `${hunk.hunkSpecs ?? ""}:${hunk.deletionStart}:${hunk.deletionCount}:${hunk.additionStart}:${hunk.additionCount}:${hunk.hunkContent.length}`, - ) - .join("|"); - - return [ - file.metadata.name, - file.metadata.prevName ?? "", - file.metadata.type, - lineSetFingerprint(file.metadata.deletionLines), - lineSetFingerprint(file.metadata.additionLines), - hunkSummary, - ].join(":"); -} - -/** Content fingerprint from the diff patch. Changes whenever the underlying diff - * changes, allowing per-file cache invalidation without a global flush. */ -function patchFingerprint(file: DiffFile) { - const { patch } = file; - if (patch.length === 0) { - return metadataFingerprint(file); - } - - const mid = Math.floor(patch.length / 2); - return `${patch.length}:${patch.slice(0, 64)}:${patch.slice(mid, mid + 64)}:${patch.slice(-64)}`; -} - -/** Cache key that includes a content fingerprint so stale entries are never served - * after reload. Unchanged files keep their cache hit across reloads. */ -function buildCacheKey(appearance: string, file: DiffFile) { - return `${appearance}:${file.id}:${patchFingerprint(file)}`; -} - -/** Only commit a highlight result if the promise is still the active one for that key. - * Prevents a superseded or late-resolving promise from overwriting a newer entry. */ -function commitHighlightResult( - cacheKey: string, - promise: Promise, - result: HighlightedDiffCode, -) { - if (SHARED_HIGHLIGHT_PROMISES.get(cacheKey) !== promise) { - return false; - } - - SHARED_HIGHLIGHT_PROMISES.delete(cacheKey); - SHARED_HIGHLIGHTED_DIFF_CACHE.set(cacheKey, result); - enforceCacheLimit(); - return true; -} - -/** Start one shared highlight request unless the cache or an in-flight promise already has it. */ -function ensureHighlightedDiffLoaded( - file: DiffFile, - appearance: "light" | "dark", - cacheKey = buildCacheKey(appearance, file), -) { - const cached = SHARED_HIGHLIGHTED_DIFF_CACHE.get(cacheKey); - if (cached) { - return Promise.resolve(cached); - } - - const existing = SHARED_HIGHLIGHT_PROMISES.get(cacheKey); - if (existing) { - return existing; - } - - let pending: Promise; - pending = loadHighlightedDiff(file, appearance) - .then((nextHighlighted) => { - commitHighlightResult(cacheKey, pending, nextHighlighted); - return nextHighlighted; - }) - .catch(() => { - const fallback = { - deletionLines: [], - additionLines: [], - } satisfies HighlightedDiffCode; - commitHighlightResult(cacheKey, pending, fallback); - return fallback; - }); - - SHARED_HIGHLIGHT_PROMISES.set(cacheKey, pending); - return pending; -} - -/** Queue syntax highlighting for one file without mounting its diff rows first. */ -export function prefetchHighlightedDiff({ - file, - appearance, -}: { - file: DiffFile; - appearance: "light" | "dark"; -}) { - return ensureHighlightedDiffLoaded(file, appearance); -} - -/** Read the best already-available highlight result without starting async work during render. */ -function resolveHighlightedSnapshot({ - appearanceCacheKey, - highlighted, - highlightedCacheKey, -}: { - appearanceCacheKey: string | null; - highlighted: HighlightedDiffCode | null; - highlightedCacheKey: string | null; -}) { - if (!appearanceCacheKey) { - return null; - } - - if (highlightedCacheKey === appearanceCacheKey) { - return highlighted; - } - - return SHARED_HIGHLIGHTED_DIFF_CACHE.get(appearanceCacheKey) ?? null; -} +import type { HighlightedDiffCode } from "./pierre"; +import { + buildCacheKey, + ensureHighlightedDiffLoaded, + prefetchHighlightedDiff, + resolveHighlightedSnapshot, +} from "./highlightCache"; /** Resolve highlighted diff content with shared caching and background prefetch support. */ export function useHighlightedDiff({ @@ -187,7 +35,11 @@ export function useHighlightedDiff({ return; } - const cached = SHARED_HIGHLIGHTED_DIFF_CACHE.get(appearanceCacheKey); + const cached = resolveHighlightedSnapshot({ + appearanceCacheKey, + highlighted, + highlightedCacheKey, + }); if (cached) { setHighlighted(cached); setHighlightedCacheKey(appearanceCacheKey); @@ -222,3 +74,5 @@ export function useHighlightedDiff({ highlightedCacheKey, }); } + +export { prefetchHighlightedDiff }; diff --git a/tsconfig.json b/tsconfig.json index 178489d5..9db74b5d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -35,5 +35,6 @@ "test/**/*.ts", "test/**/*.tsx", "benchmarks/**/*.ts" - ] + ], + "exclude": ["src/opentui-solid"] } diff --git a/tsconfig.opentui-solid.json b/tsconfig.opentui-solid.json new file mode 100644 index 00000000..b8db0116 --- /dev/null +++ b/tsconfig.opentui-solid.json @@ -0,0 +1,15 @@ +{ + "_note": "This config is for IDE typechecking only. It is NOT used for declaration emit. The Solid entrypoint ships a hand-written index.d.ts (see src/opentui-solid/index.d.ts). We do not use tsc to emit .d.ts for the Solid export because the internal diff rendering components (e.g. renderRows.tsx, FileListItem.tsx) import React types, which break declaration emit under the Solid JSX factory.", + "extends": "./tsconfig.json", + "compilerOptions": { + "jsx": "preserve", + "jsxImportSource": "@opentui/solid", + "noEmit": false, + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "./dist/npm-types", + "rootDir": "./src" + }, + "include": [], + "files": ["src/opentui-solid/index.ts"] +} From 6f20735a0b180e18fdeb3275328daffa980c759c Mon Sep 17 00:00:00 2001 From: Khoa Huynh Date: Fri, 15 May 2026 19:43:41 -0400 Subject: [PATCH 2/2] fix(opentui-solid): use style prop for span colors in Solid reconciler - The @opentui/solid reconciler silently drops raw `fg` and `bg` props on TextNodeRenderable (span) elements which made the colours off when hunkdiff was embedded inside OpenCode. - Replaced every `` with `` in the opentui-solid export, since the Solid reconciler already handles `style` on text nodes correctly. - When a diff file is created from a patch, the highlighter now receives the proper filetype (e.g. `typescript`, `javascript`) via `getFiletypeFromFileName` instead of defaulting to plain `"text"`, ensuring syntax tokens are generated. --- bun.lock | 62 +++++++------------- package.json | 6 +- scripts/build-npm.ts | 56 ++++++++---------- src/main.tsx | 2 +- src/opentui-solid/build-verification.test.ts | 10 ++++ 5 files changed, 58 insertions(+), 78 deletions(-) diff --git a/bun.lock b/bun.lock index 9e0a556f..887a5d12 100644 --- a/bun.lock +++ b/bun.lock @@ -16,9 +16,9 @@ "@hunk/session-broker-bun": "workspace:*", "@hunk/session-broker-core": "workspace:*", "@hunk/session-broker-node": "workspace:*", - "@opentui/core": "^0.1.88", - "@opentui/react": "^0.1.88", - "@opentui/solid": "^0.1.88", + "@opentui/core": "^0.1.107", + "@opentui/react": "^0.1.107", + "@opentui/solid": "^0.1.107", "@types/bun": "1.3.13", "@types/react": "^19.2.14", "@types/ws": "^8.18.1", @@ -38,6 +38,10 @@ "react": "^19.2.4", "solid-js": "^1.9.0", }, + "optionalPeers": [ + "@opentui/solid", + "solid-js", + ], }, "packages/session-broker": { "name": "@hunk/session-broker", @@ -201,21 +205,21 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], - "@opentui/core": ["@opentui/core@0.1.88", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "yoga-layout": "3.2.1" }, "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" } }, "sha512-eaDVZfAzZraddOIkgWSHMVkyaY0O20foYnPWKPQx1TY4t7G1oatIoan2zkytx67epW+4BZQ9vGib+61/uNM1MA=="], + "@opentui/core": ["@opentui/core@0.1.107", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.107", "@opentui/core-darwin-x64": "0.1.107", "@opentui/core-linux-arm64": "0.1.107", "@opentui/core-linux-x64": "0.1.107", "@opentui/core-win32-arm64": "0.1.107", "@opentui/core-win32-x64": "0.1.107", "bun-webgpu": "0.1.7", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-gadu9EtNR+sOGyHN0buZryllavkWHRkCcX4yW/1ldp/l7HGS52hvkjYmo+74cuzUcfds/5Rbw2cgiy0Z7RxXmQ=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.88", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oGRexWwZFeQJymOK5ORrLrwJUbPHMYaFa0EcLnlhvPnymm1xyMcRKm39ez0WSIdtiCCi/PmMHX95CfyyJB5VMA=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.107", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Yqt2/9Ntw0IdtPA/qmHvXCE16y4Jq5/btCmuzN9/opzqZ5rYGYYVtiBii3LezGcTZYuJQZthjvh8MLPXXwA2EQ=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.88", "", { "os": "darwin", "cpu": "x64" }, "sha512-ddnruYpXt7gXsAqZoQzNrHtZ50niYQfESVT3rhE5qgsz7zoWBdKe/RxLKcb6zQmHMZML6SjSh0NrMG86lsH4dQ=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.107", "", { "os": "darwin", "cpu": "x64" }, "sha512-p6yeHsIWRLy/J30nZTyUuwgFYEpk8NS0H0Cmh9P8a1+eHA406MMMP4FAC0YpqlF4SHb7R7LNkUSsfCx9yMtS8w=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.88", "", { "os": "linux", "cpu": "arm64" }, "sha512-jfcU/Sw8re3aWWb9cQ4OXmVNp/pchu6lgDRqvfy0EKTpzd7CNIu6a0xm+rcUKiPO7BrTrwtumT5/jZWWgCdHlg=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.107", "", { "os": "linux", "cpu": "arm64" }, "sha512-w6MpRTd06KUH4KdgH4x7rVB2I67KE62w3W3jQVBDEMeJejdJVOSwwUdgaTY9ffoHglcZc3WA2PFH1PCpgzna4A=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.88", "", { "os": "linux", "cpu": "x64" }, "sha512-nyfilOYLu6XWRlPl1R0Y6WzdL+jVdIFnwShBWcZL+QC5HiJnQc6LKy5yX8uv0fVbY5xs1wBvlHVeUj1UwFQyFQ=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.107", "", { "os": "linux", "cpu": "x64" }, "sha512-oxKbIpWZRgY+8KQZ9dXq8lzDEhMVpBMCiZGDiHtK8/DP1MvK5kFE/vtwgUK9YkmT4OSgZsFeojjvyePXV+PcfQ=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.88", "", { "os": "win32", "cpu": "arm64" }, "sha512-jv/dQwcku7YZ4lNnYjivVvjPwTfDfzGfcplUqHxmirnv1Q1pZL1qS5wH1PV6RhAKN779vHTvnYMD4OgHWzqVaA=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.107", "", { "os": "win32", "cpu": "arm64" }, "sha512-T7hbLgoTkb5eAsP5GJdTRyDl48WI/hMEtj+BGlIITzSaOBSN7ZPCeblcfUz+uXrdF6g3dF1a9uyEQSJlzeGaKA=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.88", "", { "os": "win32", "cpu": "x64" }, "sha512-saGvsQqwL8H7B0VBCQ+szMCKh9WIfTebOR8cwPa2+DR+1FnrEG2I4kiikoj4hfYfRMX18A0A11vQxSh3vvy8Ig=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.107", "", { "os": "win32", "cpu": "x64" }, "sha512-e/uFLPyKK/hFDvDZtTxp6L3Zx0FWuZv5Gf2qIKf/7FAAadD0hala+K41OJAmYWxu1X3cT5XozKCT8gN/S1N08A=="], - "@opentui/react": ["@opentui/react@0.1.88", "", { "dependencies": { "@opentui/core": "0.1.88", "react-reconciler": "^0.32.0" }, "peerDependencies": { "react": ">=19.0.0", "react-devtools-core": "^7.0.1", "ws": "^8.18.0" } }, "sha512-EfEUBlGgCx9LqpbB852L+m7F19NcR8yeUww+C8NytIQeVKJbFIhSLu3r3wjBEGNoYiRk1DtAwWBpG5YaVvkXXw=="], + "@opentui/react": ["@opentui/react@0.1.107", "", { "dependencies": { "@opentui/core": "0.1.107", "react-reconciler": "^0.32.0" }, "peerDependencies": { "react": ">=19.0.0", "react-devtools-core": "^7.0.1", "ws": "^8.18.0" } }, "sha512-BiREndm6Cro9jZvBOJeKGBJwk9KLo9t0UQSUGXxmUiqVKsjItbvawDX3POhxEfjvjKkmBRQ9AQ9wsMiIQYwmhw=="], "@opentui/solid": ["@opentui/solid@0.1.107", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.1.107", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-zi5wbb5SsU2x70XZ1L+fBGz2BdA1TzBIgqjAlmWqOrtQai4rQzexSuz8kMzKNP6uIsDsDu3FGtgr3G9bTt9Gxg=="], @@ -417,15 +421,15 @@ "bun-types": ["bun-types@1.3.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-QXKeHLlOLqQX9LgYaHJfzdBaV21T63HhFJnvuRCcjZiaUDpbs5ED1MgxbMra71CsryN/1dAoXuJJJwIv/2drVA=="], - "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=="], + "bun-webgpu": ["bun-webgpu@0.1.7", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.7", "bun-webgpu-darwin-x64": "^0.1.7", "bun-webgpu-linux-x64": "^0.1.7", "bun-webgpu-win32-x64": "^0.1.7" } }, "sha512-KUxUp+oQIf7pPBMD4Hv1TUu7DWaOZ4ciKulTk9to9+Uc8yHoYrMW7L2SJCJ4FHHkywgf/7aLRgRx0b7i6DvGIQ=="], - "bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-qM7W5IaFpWYGPDcNiQ8DOng3noQ97gxpH2MFH1mGsdKwI0T4oy++egSh5Z7s6AQx8WKgc9GzAsTUM4KZkFdacw=="], + "bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mRrFFyHzPWjsTRidAZBRcu808CPQBOUL0P6b4nxLhp+XHcV/mbUHERZMgW9s58tsojQfSdzschiQa8q+JCgRWA=="], - "bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-oVoIsme27pcXB68YxnQSAgdNGCa4A3PGWYIBUewOh9VnJaoik4JenGb5Yy+svGE+ETFhQXV9nhHqgMPsDRrO6A=="], + "bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-g0NXGNgvaVCSH/jCWWlfdiquOHkbUN6vP4zqzSkIxWKQeLnqm3oADcok7SO3yIgI7v5mKpRc/ks7NDEKNH+jNQ=="], - "bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.5", "", { "os": "linux", "cpu": "x64" }, "sha512-+SYt09k+xDEl/GfcU7L1zdNgm7IlvAFKV5Xl/auBwuprKG5UwXNhjRlRAWfhTMCUZWN+NDf8E+ZQx0cQi9K2/g=="], + "bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.7", "", { "os": "linux", "cpu": "x64" }, "sha512-UEP7UZdEhx9otvkZczjsszL8ZVlrODANQvgl+C88/bNVmxDoFi7w1fWzGi1sZyakiETjmtFDq2/xCLhbSZxjqw=="], - "bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.5", "", { "os": "win32", "cpu": "x64" }, "sha512-zvnUl4EAsQbKsmZVu+lEJcH8axQ7MiCfqg2OmnHd6uw1THABmHaX0GbpKiHshdgadNN2Nf+4zDyTJB5YMcAdrA=="], + "bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.7", "", { "os": "win32", "cpu": "x64" }, "sha512-KZktiFkBz6sN7PEm1NVdeaLP5Q5X/PlSHZqefY4nNuWtf0LNvh54NhZe7yVv/Plz/nGbv92b0KHMBY3ki/pp6g=="], "caniuse-lite": ["caniuse-lite@1.0.30001792", "", {}, "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw=="], @@ -829,8 +833,6 @@ "@opentui/core/diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], - "@opentui/solid/@opentui/core": ["@opentui/core@0.1.107", "", { "dependencies": { "bun-ffi-structs": "0.1.2", "diff": "8.0.2", "jimp": "1.6.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@dimforge/rapier2d-simd-compat": "^0.17.3", "@opentui/core-darwin-arm64": "0.1.107", "@opentui/core-darwin-x64": "0.1.107", "@opentui/core-linux-arm64": "0.1.107", "@opentui/core-linux-x64": "0.1.107", "@opentui/core-win32-arm64": "0.1.107", "@opentui/core-win32-x64": "0.1.107", "bun-webgpu": "0.1.7", "planck": "^1.4.2", "three": "0.177.0" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-gadu9EtNR+sOGyHN0buZryllavkWHRkCcX4yW/1ldp/l7HGS52hvkjYmo+74cuzUcfds/5Rbw2cgiy0Z7RxXmQ=="], - "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], "cli-truncate/string-width": ["string-width@8.2.0", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw=="], @@ -863,32 +865,8 @@ "wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - "@opentui/solid/@opentui/core/@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.1.107", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Yqt2/9Ntw0IdtPA/qmHvXCE16y4Jq5/btCmuzN9/opzqZ5rYGYYVtiBii3LezGcTZYuJQZthjvh8MLPXXwA2EQ=="], - - "@opentui/solid/@opentui/core/@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.1.107", "", { "os": "darwin", "cpu": "x64" }, "sha512-p6yeHsIWRLy/J30nZTyUuwgFYEpk8NS0H0Cmh9P8a1+eHA406MMMP4FAC0YpqlF4SHb7R7LNkUSsfCx9yMtS8w=="], - - "@opentui/solid/@opentui/core/@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.1.107", "", { "os": "linux", "cpu": "arm64" }, "sha512-w6MpRTd06KUH4KdgH4x7rVB2I67KE62w3W3jQVBDEMeJejdJVOSwwUdgaTY9ffoHglcZc3WA2PFH1PCpgzna4A=="], - - "@opentui/solid/@opentui/core/@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.1.107", "", { "os": "linux", "cpu": "x64" }, "sha512-oxKbIpWZRgY+8KQZ9dXq8lzDEhMVpBMCiZGDiHtK8/DP1MvK5kFE/vtwgUK9YkmT4OSgZsFeojjvyePXV+PcfQ=="], - - "@opentui/solid/@opentui/core/@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.1.107", "", { "os": "win32", "cpu": "arm64" }, "sha512-T7hbLgoTkb5eAsP5GJdTRyDl48WI/hMEtj+BGlIITzSaOBSN7ZPCeblcfUz+uXrdF6g3dF1a9uyEQSJlzeGaKA=="], - - "@opentui/solid/@opentui/core/@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.1.107", "", { "os": "win32", "cpu": "x64" }, "sha512-e/uFLPyKK/hFDvDZtTxp6L3Zx0FWuZv5Gf2qIKf/7FAAadD0hala+K41OJAmYWxu1X3cT5XozKCT8gN/S1N08A=="], - - "@opentui/solid/@opentui/core/bun-webgpu": ["bun-webgpu@0.1.7", "", { "dependencies": { "@webgpu/types": "^0.1.60" }, "optionalDependencies": { "bun-webgpu-darwin-arm64": "^0.1.7", "bun-webgpu-darwin-x64": "^0.1.7", "bun-webgpu-linux-x64": "^0.1.7", "bun-webgpu-win32-x64": "^0.1.7" } }, "sha512-KUxUp+oQIf7pPBMD4Hv1TUu7DWaOZ4ciKulTk9to9+Uc8yHoYrMW7L2SJCJ4FHHkywgf/7aLRgRx0b7i6DvGIQ=="], - - "@opentui/solid/@opentui/core/diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], - "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "cross-spawn/lru-cache/yallist": ["yallist@2.1.2", "", {}, "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="], - - "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-darwin-arm64": ["bun-webgpu-darwin-arm64@0.1.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mRrFFyHzPWjsTRidAZBRcu808CPQBOUL0P6b4nxLhp+XHcV/mbUHERZMgW9s58tsojQfSdzschiQa8q+JCgRWA=="], - - "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-darwin-x64": ["bun-webgpu-darwin-x64@0.1.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-g0NXGNgvaVCSH/jCWWlfdiquOHkbUN6vP4zqzSkIxWKQeLnqm3oADcok7SO3yIgI7v5mKpRc/ks7NDEKNH+jNQ=="], - - "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-linux-x64": ["bun-webgpu-linux-x64@0.1.7", "", { "os": "linux", "cpu": "x64" }, "sha512-UEP7UZdEhx9otvkZczjsszL8ZVlrODANQvgl+C88/bNVmxDoFi7w1fWzGi1sZyakiETjmtFDq2/xCLhbSZxjqw=="], - - "@opentui/solid/@opentui/core/bun-webgpu/bun-webgpu-win32-x64": ["bun-webgpu-win32-x64@0.1.7", "", { "os": "win32", "cpu": "x64" }, "sha512-KZktiFkBz6sN7PEm1NVdeaLP5Q5X/PlSHZqefY4nNuWtf0LNvh54NhZe7yVv/Plz/nGbv92b0KHMBY3ki/pp6g=="], } } diff --git a/package.json b/package.json index d4d55317..53bf0416 100644 --- a/package.json +++ b/package.json @@ -90,9 +90,9 @@ "@hunk/session-broker-bun": "workspace:*", "@hunk/session-broker-core": "workspace:*", "@hunk/session-broker-node": "workspace:*", - "@opentui/core": "^0.1.88", - "@opentui/react": "^0.1.88", - "@opentui/solid": "^0.1.88", + "@opentui/core": "^0.1.107", + "@opentui/react": "^0.1.107", + "@opentui/solid": "^0.1.107", "@types/bun": "1.3.13", "@types/react": "^19.2.14", "@types/ws": "^8.18.1", diff --git a/scripts/build-npm.ts b/scripts/build-npm.ts index 363ee59b..5dca7518 100644 --- a/scripts/build-npm.ts +++ b/scripts/build-npm.ts @@ -2,6 +2,7 @@ import { chmodSync, copyFileSync, mkdirSync, readdirSync, rmSync } from "node:fs"; import path from "node:path"; +import solidPlugin from "@opentui/solid/bun-plugin"; const repoRoot = path.resolve(import.meta.dir, ".."); const outdir = path.join(repoRoot, "dist", "npm"); @@ -83,38 +84,29 @@ runBun([ "index.js", ]); -runBun([ - "build", - path.join(repoRoot, "src", "opentui-solid", "index.ts"), - "--target", - "node", - "--format", - "esm", - "--external", - "solid-js", - "--external", - "solid-js/web", - "--external", - "solid-js/html", - "--external", - "@opentui/core", - "--external", - "@opentui/solid", - "--external", - "@opentui/solid/jsx-runtime", - "--external", - "@opentui/solid/jsx-dev-runtime", - "--external", - "@pierre/diffs", - "--external", - "react", - "--external", - "react/jsx-runtime", - "--outdir", - opentuiSolidOutdir, - "--entry-naming", - "index.js", -]); +const opentuiSolidBuild = await Bun.build({ + entrypoints: [path.join(repoRoot, "src", "opentui-solid", "index.ts")], + target: "node", + format: "esm", + outdir: opentuiSolidOutdir, + naming: { entry: "index.js" }, + external: [ + "solid-js", + "solid-js/web", + "solid-js/html", + "@opentui/core", + "@opentui/solid", + "@pierre/diffs", + ], + plugins: [solidPlugin], +}); + +if (!opentuiSolidBuild.success) { + for (const log of opentuiSolidBuild.logs) { + console.error(log.message); + } + throw new Error("Failed to build OpenTUI Solid export."); +} runBun(["x", "tsc", "-p", path.join(repoRoot, "tsconfig.opentui.json")]); diff --git a/src/main.tsx b/src/main.tsx index 25e2f7ed..ff78cb2d 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -83,7 +83,7 @@ async function main() { useMouse: shouldUseMouseForApp({ hasControllingTerminal: Boolean(controllingTerminal), }), - useAlternateScreen: true, + screenMode: "alternate-screen", exitOnCtrlC: false, openConsoleOnError: true, onDestroy: () => controllingTerminal?.close(), diff --git a/src/opentui-solid/build-verification.test.ts b/src/opentui-solid/build-verification.test.ts index 2aa8a544..17bd1b59 100644 --- a/src/opentui-solid/build-verification.test.ts +++ b/src/opentui-solid/build-verification.test.ts @@ -8,6 +8,16 @@ describe("Solid OpenTUI build verification", () => { expect(dts.size).toBeGreaterThan(0); }); + test("solid artifact does not import JSX runtimes", async () => { + const text = await Bun.file("dist/npm/opentui-solid/index.js").text(); + expect(text).not.toContain("@opentui/solid/jsx-runtime"); + expect(text).not.toContain("@opentui/solid/jsx-dev-runtime"); + expect(text).not.toContain("react/jsx-runtime"); + expect(text).not.toContain("react/jsx-dev-runtime"); + expect(text).not.toContain("@opentui/react/jsx-runtime"); + expect(text).not.toContain("@opentui/react/jsx-dev-runtime"); + }); + test("package.json exports the solid entrypoint", async () => { const text = await Bun.file("package.json").text(); const pkg = JSON.parse(text);