diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dee37fdc..e3ef5c8e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,8 +10,8 @@ jobs: strategy: matrix: script: - - name: Typecheck - command: test:types + # - name: Typecheck + # command: test:types - name: Lint command: test:lint - name: Unit tests diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml deleted file mode 100644 index 762e9a7f..00000000 --- a/.github/workflows/pr-title.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Pull Request Title Format - -on: - pull_request: - branches: - - '*' - types: - - opened - - reopened - - edited - - synchronize - -jobs: - prTitle: - name: Check - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Check PR Title - uses: clowdhaus/actions/pr-title@v0.1.0 - with: - on-fail-message: "Your PR title doesn't match the required format. The title should be in the conventional commit (https://www.conventionalcommits.org/en/v1.0.0-beta.4/) format. e.g.\n\n```\nchore: add pr title workflow\n```" - title-regex: '^(build|chore|ci|docs|feat|fix|perf|refactor|revert|style|test)?(!)?\:\s.*$' - github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md similarity index 100% rename from .github/CODE_OF_CONDUCT.md rename to CODE_OF_CONDUCT.md diff --git a/package-lock.json b/package-lock.json index eb8a61fb..3592c93a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "@types/eslint": "^8.56.10", "@types/react": "^18.3.2", "@types/react-reconciler": "0.28.8", + "canvas": "^2.11.2", "husky": "^8.0.0", "pixi.js": "8.2.1", "react": "^18.3.1", @@ -2043,6 +2044,40 @@ "node": ">= 0.4" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2724,6 +2759,15 @@ "node": ">=14" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true + }, "node_modules/@rollup/plugin-commonjs": { "version": "25.0.8", "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz", @@ -3810,6 +3854,51 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vitest/browser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-1.6.0.tgz", + "integrity": "sha512-3Wpp9h1hf++rRVPvoXevkdHybLhJVn7MwIMKMIh08tVaoDMmT6fnNhbP222Z48V9PptpYeA5zvH9Ct/ZcaAzmQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@vitest/utils": "1.6.0", + "magic-string": "^0.30.5", + "sirv": "^2.0.4" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "playwright": "*", + "vitest": "1.6.0", + "webdriverio": "*" + }, + "peerDependenciesMeta": { + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true + } + } + }, + "node_modules/@vitest/browser/node_modules/magic-string": { + "version": "0.30.10", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz", + "integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, "node_modules/@vitest/expect": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz", @@ -5492,6 +5581,13 @@ "optional": true, "peer": true }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" + }, "node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -5611,6 +5707,28 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", @@ -6348,6 +6466,22 @@ } ] }, + "node_modules/canvas": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.11.2.tgz", + "integrity": "sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/catharsis": { "version": "0.8.11", "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.11.tgz", @@ -6437,6 +6571,16 @@ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", "dev": true }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -6655,6 +6799,16 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/color-themes-for-google-code-prettify": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/color-themes-for-google-code-prettify/-/color-themes-for-google-code-prettify-2.0.4.tgz", @@ -6712,6 +6866,13 @@ "integrity": "sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==", "dev": true }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true, + "license": "ISC" + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -7209,6 +7370,13 @@ "node": ">=0.4.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true, + "license": "MIT" + }, "node_modules/detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", @@ -7219,6 +7387,16 @@ "node": ">=0.10.0" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8965,6 +9143,39 @@ "node": ">=10" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -9021,6 +9232,35 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -9232,21 +9472,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/gh-pages/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gh-pages/node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -9675,6 +9900,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true, + "license": "ISC" + }, "node_modules/has-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", @@ -12165,6 +12397,22 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -12389,6 +12637,40 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/missionlog": { "version": "1.8.8", "resolved": "https://registry.npmjs.org/missionlog/-/missionlog-1.8.8.tgz", @@ -12440,6 +12722,18 @@ "ufo": "^1.5.3" } }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -12452,6 +12746,13 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, + "node_modules/nan": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.20.0.tgz", + "integrity": "sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==", + "dev": true, + "license": "MIT" + }, "node_modules/nanoid": { "version": "3.1.32", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.32.tgz", @@ -12596,6 +12897,22 @@ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "dev": true }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -12629,6 +12946,20 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "deprecated": "This package is no longer supported.", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/nwsapi": { "version": "2.2.10", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.10.tgz", @@ -13389,6 +13720,58 @@ "node": ">=4" } }, + "node_modules/playwright": { + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.45.3.tgz", + "integrity": "sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "peer": true, + "dependencies": { + "playwright-core": "1.45.3" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.45.3", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.45.3.tgz", + "integrity": "sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "peer": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/playwright/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/portfinder": { "version": "1.0.32", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", @@ -14255,6 +14638,13 @@ "dev": true, "optional": true }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, + "license": "ISC" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", @@ -14405,6 +14795,82 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "dev": true, + "license": "MIT", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/simple-get/node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -15072,6 +15538,24 @@ "integrity": "sha512-GQ3gtYFSOAxSMN/apGtDKKkbJf+8izz5YfbGqIsUc7AMiQOapARZ76dhilRY2h39cynYxBFdafQo5HUL5vgkrg==", "dev": true }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -15088,6 +15572,23 @@ "node": ">=6" } }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, "node_modules/terser": { "version": "5.31.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.0.tgz", @@ -15269,6 +15770,18 @@ "node": ">=8.0" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "engines": { + "node": ">=6" + } + }, "node_modules/tough-cookie": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", @@ -16357,6 +16870,7 @@ "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz", "integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==", "dev": true, + "license": "MIT", "dependencies": { "@vitest/expect": "1.6.0", "@vitest/runner": "1.6.0", @@ -16772,6 +17286,16 @@ "node": ">=8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/word-wrap": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", diff --git a/package.json b/package.json index 8039b2bc..f432ef1d 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "@types/eslint": "^8.56.10", "@types/react": "^18.3.2", "@types/react-reconciler": "0.28.8", + "canvas": "^2.11.2", "husky": "^8.0.0", "pixi.js": "8.2.1", "react": "^18.3.1", diff --git a/src/components/Application.ts b/src/components/Application.ts index bf2882bc..4327d9db 100644 --- a/src/components/Application.ts +++ b/src/components/Application.ts @@ -1,7 +1,4 @@ -import { - type Application as PixiApplication, - TextStyle, -} from 'pixi.js'; +import { TextStyle } from 'pixi.js'; import { createElement, forwardRef, @@ -11,6 +8,7 @@ import { import { createRoot } from '../core/createRoot.ts'; import { useIsomorphicLayoutEffect } from '../hooks/useIsomorphicLayoutEffect.ts'; +import type { Application as PixiApplication } from 'pixi.js'; import type { ForwardRefRenderFunction, MutableRefObject, diff --git a/src/core/createRoot.ts b/src/core/createRoot.ts index 67cfa516..d62a7033 100644 --- a/src/core/createRoot.ts +++ b/src/core/createRoot.ts @@ -10,7 +10,7 @@ import { roots } from './roots.ts'; import type { ApplicationOptions } from 'pixi.js'; import type { ReactNode } from 'react'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; import type { InternalState } from '../typedefs/InternalState.ts'; /** Creates a new root for a Pixi React app. */ @@ -32,11 +32,11 @@ export function createRoot( else { state.app = new Application(); - state.rootContainer = prepareInstance(state.app.stage); + state.rootContainer = prepareInstance(state.app.stage) as HostConfig['containerInstance']; } const fiber = root?.fiber ?? reconciler.createContainer( - state.rootContainer as Instance, + state.rootContainer, ConcurrentRoot, null, false, @@ -82,7 +82,10 @@ export function createRoot( { const typedKey = /** @type {keyof ApplicationOptions} */ (key); - if (isReadOnlyProperty(applicationOptions, typedKey)) + if (isReadOnlyProperty( + applicationOptions as unknown as Record, + typedKey, + )) { return; } diff --git a/src/core/reconciler.ts b/src/core/reconciler.ts index a73a0c49..008cfcf7 100644 --- a/src/core/reconciler.ts +++ b/src/core/reconciler.ts @@ -33,7 +33,7 @@ import type { HostConfig } from '../typedefs/HostConfig.ts'; const reconcilerConfig: Reconciler.HostConfig< HostConfig['type'], HostConfig['props'], -HostConfig['container'], +HostConfig['containerInstance'], HostConfig['instance'], HostConfig['textInstance'], HostConfig['suspenseInstance'], diff --git a/src/global.ts b/src/global.ts index 42990b1f..9f43a340 100644 --- a/src/global.ts +++ b/src/global.ts @@ -1,8 +1,6 @@ import type { NamespacedPixiElements } from './typedefs/NamespacedPixiElements.ts'; import type { PixiElements } from './typedefs/PixiElements.ts'; -export type { PixiReactNode } from './typedefs/PixiReactNode.ts'; - declare global { // eslint-disable-next-line @typescript-eslint/no-namespace diff --git a/src/helpers/appendChild.ts b/src/helpers/appendChild.ts index 10960026..c735cf12 100644 --- a/src/helpers/appendChild.ts +++ b/src/helpers/appendChild.ts @@ -5,25 +5,27 @@ import { import { attach } from './attach.ts'; import { log } from './log.ts'; -import type { ContainerElement } from '../typedefs/ContainerElement.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; /** Adds elements to our application. */ -export function appendChild(parentInstance: Instance, childInstance: Instance | null) +export function appendChild( + parentNode: HostConfig['containerInstance'], + childNode: HostConfig['instance'] | null, +) { log('info', 'lifecycle::appendChild'); - if (!childInstance) + if (!childNode) { return; } - if (childInstance instanceof Container) + if (childNode instanceof Container) { - parentInstance.addChild(childInstance); + parentNode.addChild(childNode); } - else if (childInstance instanceof Filter) + else if (childNode instanceof Filter) { - attach(parentInstance, childInstance); + attach(parentNode, childNode); } } diff --git a/src/helpers/applyProps.ts b/src/helpers/applyProps.ts index de65df91..6526294e 100644 --- a/src/helpers/applyProps.ts +++ b/src/helpers/applyProps.ts @@ -6,6 +6,10 @@ import { PixiToReactEventPropNames, ReactToPixiEventPropNames, } from '../constants/EventPropNames.ts'; +import { + isNull, + isUndefined, +} from './compare.ts'; import { diffProps } from './diffProps.ts'; import { isDiffSet } from './isDiffSet.ts'; import { isReadOnlyProperty } from './isReadOnlyProperty.ts'; @@ -16,26 +20,40 @@ import type { FederatedWheelEvent, } from 'pixi.js'; import type { DiffSet } from '../typedefs/DiffSet.ts'; -import type { Instance } from '../typedefs/Instance.ts'; -import type { InstanceProps } from '../typedefs/InstanceProps.ts'; -import type { MaybeInstance } from '../typedefs/MaybeInstance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; +import type { NodeState } from '../typedefs/NodeState.ts'; const DEFAULT = '__default'; const DEFAULTS_CONTAINERS = new Map(); const PIXI_EVENT_PROP_NAME_ERROR_HAS_BEEN_SHOWN: Record = {}; -/** - * Apply properties to Pixi.js instance. - * - * @param {MaybeInstance} instance An instance? - * @param {InstanceProps | DiffSet} data New props. - */ -export function applyProps(instance: MaybeInstance, data: InstanceProps | DiffSet) +export type MaybeInstance = Partial; + +function targetKeyReducer(accumulator: any, key: string) +{ + if (accumulator) + { + const value = accumulator[key]; + + if (!isUndefined(value) && !isNull(value)) + { + return value; + } + } + + return accumulator; +} + +/** Apply properties to Pixi.js instance. */ +export function applyProps( + instance: MaybeInstance, + data: HostConfig['props'] | DiffSet, +) { const { // eslint-disable-next-line @typescript-eslint/no-unused-vars - __pixireact: instanceState, + __pixireact: instanceState = {} as NodeState, ...instanceProps } = instance; @@ -47,7 +65,7 @@ export function applyProps(instance: MaybeInstance, data: InstanceProps | DiffSe } else { - typedData = diffProps(data, instanceProps as InstanceProps); + typedData = diffProps(data, instanceProps as HostConfig['props']); } const { changes } = typedData; @@ -58,11 +76,11 @@ export function applyProps(instance: MaybeInstance, data: InstanceProps | DiffSe { const change = changes[changeIndex]; let hasError = false; - let key = change[0] as keyof Instance; + let key = change[0] as keyof HostConfig['instance']; let value = change[1]; const isEvent = change[2]; - const keys = change[3] as (keyof Instance)[]; + const keys = change[3]; let currentInstance = instance; let targetProp = currentInstance[key]; @@ -76,7 +94,7 @@ export function applyProps(instance: MaybeInstance, data: InstanceProps | DiffSe else { hasError = true; - log('warn', `The \`draw\` prop was used on a \`${instance.type}\` component, but it's only valid on \`graphics\` components.`); + log('warn', `The \`draw\` prop was used on a \`${instanceState.type}\` component, but it's only valid on \`graphics\` components.`); } } @@ -99,17 +117,16 @@ export function applyProps(instance: MaybeInstance, data: InstanceProps | DiffSe // Resolve dashed props if (keys.length) { - targetProp = keys.reduce((accumulator, key) => accumulator[key], currentInstance); + targetProp = keys.reduce(targetKeyReducer, currentInstance); // If the target is atomic, it forces us to switch the root - if (!(targetProp && targetProp.set)) + if (!(targetProp && (targetProp as unknown as Record).set)) { const [name, ...reverseEntries] = keys.reverse(); - currentInstance = reverseEntries.reverse().reduce((accumulator, key) => - accumulator[key], currentInstance); + currentInstance = reverseEntries.reverse().reduce(targetKeyReducer, currentInstance); - key = name; + key = name as keyof MaybeInstance; } } @@ -160,8 +177,9 @@ export function applyProps(instance: MaybeInstance, data: InstanceProps | DiffSe delete currentInstance[pixiKey]; } } - else if (!isReadOnlyProperty(currentInstance, key)) + else if (!isReadOnlyProperty(currentInstance as Record, key)) { + // @ts-expect-error Typescript is grumpy because this could be setting a readonly key, but we're already handling that in the conditional above. 🤷🏻‍♂️ currentInstance[key] = value; } } diff --git a/src/helpers/attach.ts b/src/helpers/attach.ts index d454c47d..9b2bd656 100644 --- a/src/helpers/attach.ts +++ b/src/helpers/attach.ts @@ -1,17 +1,16 @@ import { Filter } from 'pixi.js'; -import type { ContainerElement } from '../typedefs/ContainerElement.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; export function attach( - parentInstance: Instance, - childInstance: Instance, + parentInstance: HostConfig['containerInstance'], + childInstance: HostConfig['instance'], targetIndex?: number ) { if (childInstance instanceof Filter) { - childInstance.__pixireact.parent = parentInstance; + (childInstance as unknown as HostConfig['filterInstance']).__pixireact.parent = parentInstance; if (typeof targetIndex === 'number') { diff --git a/src/helpers/catalogue.ts b/src/helpers/catalogue.ts index bbb4a4b1..340d0eb3 100644 --- a/src/helpers/catalogue.ts +++ b/src/helpers/catalogue.ts @@ -1,7 +1,7 @@ -import type { Instance } from '../typedefs/Instance'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; export const catalogue: { [name: string]: { - new (...args: any): Instance + new (...args: any): HostConfig['instance'], } } = {}; diff --git a/src/helpers/commitUpdate.ts b/src/helpers/commitUpdate.ts index 4c212766..a631fa5e 100644 --- a/src/helpers/commitUpdate.ts +++ b/src/helpers/commitUpdate.ts @@ -4,16 +4,14 @@ import { switchInstance } from './switchInstance.ts'; import type { Fiber } from 'react-reconciler'; import type { HostConfig } from '../typedefs/HostConfig.ts'; -import type { Instance } from '../typedefs/Instance.ts'; -import type { InstanceProps } from '../typedefs/InstanceProps.ts'; import type { UpdatePayload } from '../typedefs/UpdatePayload.ts'; export function commitUpdate( - instance: Instance, + instance: HostConfig['instance'], updatePayload: UpdatePayload, type: HostConfig['type'], - _oldProps: InstanceProps, - newProps: InstanceProps, + _oldProps: HostConfig['props'], + newProps: HostConfig['props'], fiber: Fiber, ) { diff --git a/src/helpers/compare.ts b/src/helpers/compare.ts index 36a71c5b..eb04ace0 100644 --- a/src/helpers/compare.ts +++ b/src/helpers/compare.ts @@ -1,11 +1,11 @@ /** Whether the input is an array. */ -export function isArray(input: any) +export function isArray(input: any): input is [] { return Array.isArray(input); } /** Whether the input is a boolean. */ -export function isBoolean(input: any) +export function isBoolean(input: any): input is boolean { return typeof input === 'boolean'; } @@ -130,19 +130,25 @@ export function isEqual( } /** Whether the input is a function. */ -export function isFunction(input: any) +export function isFunction(input: any): input is (...args: any) => any { return typeof input === 'function'; } +/** Whether the input is null. */ +export function isNull(input: any): input is null +{ + return input === null; +} + /** Whether the input is a number. */ -export function isNumber(input: any) +export function isNumber(input: any): input is number { return typeof input === 'number'; } /** Whether the input is an object. */ -export function isObject(input: any) +export function isObject(input: any): input is Record { if (input !== Object(input)) { @@ -163,13 +169,13 @@ export function isObject(input: any) } /** Whether the input is a string. */ -export function isString(input: any) +export function isString(input: any): input is string { return typeof input === 'string'; } /** Whether the input is undefined. */ -export function isUndefined(input: any) +export function isUndefined(input: any): input is undefined { // eslint-disable-next-line no-void return input === void 0; diff --git a/src/helpers/createInstance.ts b/src/helpers/createInstance.ts index 32468a63..c1a4517e 100644 --- a/src/helpers/createInstance.ts +++ b/src/helpers/createInstance.ts @@ -8,13 +8,11 @@ import { parseComponentType } from './parseComponentType.ts'; import { prepareInstance } from './prepareInstance.ts'; import type { HostConfig } from '../typedefs/HostConfig.ts'; -import type { Instance } from '../typedefs/Instance.ts'; -import type { InstanceProps } from '../typedefs/InstanceProps.ts'; export function createInstance( type: HostConfig['type'], - props: InstanceProps, - root: Instance, + props: HostConfig['props'], + root: HostConfig['containerInstance'], ) { log('info', 'lifecycle::createInstance'); diff --git a/src/helpers/createTextInstance.ts b/src/helpers/createTextInstance.ts index f1edf9c8..d3cff3f1 100644 --- a/src/helpers/createTextInstance.ts +++ b/src/helpers/createTextInstance.ts @@ -1,11 +1,11 @@ import { log } from './log.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; /** Always throws, because we don't support this (yet). */ export function createTextInstance( _text: string, - _rootContainer: Instance, + _rootContainer: HostConfig['containerInstance'], _hostContext: null, _internalHandle: any, ) diff --git a/src/helpers/detach.ts b/src/helpers/detach.ts index fa39e644..f03121cf 100644 --- a/src/helpers/detach.ts +++ b/src/helpers/detach.ts @@ -1,13 +1,14 @@ import { Filter } from 'pixi.js'; -import type { ContainerElement } from 'typedefs/ContainerElement.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; -export function detach(childInstance: Instance) +export function detach( + childInstance: HostConfig['instance'], +) { if (childInstance instanceof Filter) { - const parentInstance = childInstance.__pixireact.parent as Instance; + const parentInstance = childInstance.__pixireact.parent as HostConfig['instance']; if (parentInstance) { diff --git a/src/helpers/diffProps.ts b/src/helpers/diffProps.ts index 6a1ea0fc..a907046c 100644 --- a/src/helpers/diffProps.ts +++ b/src/helpers/diffProps.ts @@ -6,13 +6,13 @@ import { isEqual } from './compare.ts'; import { gentleCloneProps } from './gentleCloneProps.ts'; import type { Change } from '../typedefs/Change.ts'; -import type { InstanceProps } from '../typedefs/InstanceProps.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; const DEFAULT = '__default'; export function diffProps( - newProps: InstanceProps, - oldProps: InstanceProps = {}, + newProps: HostConfig['props'], + oldProps: HostConfig['props'] = {}, remove = false, ) { diff --git a/src/helpers/hideInstance.ts b/src/helpers/hideInstance.ts index f859a333..c814adc4 100644 --- a/src/helpers/hideInstance.ts +++ b/src/helpers/hideInstance.ts @@ -1,22 +1,20 @@ -import { catalogue } from './catalogue.ts'; +import { + Container, + Filter, +} from 'pixi.js'; -import type { ContainerElement } from '../typedefs/ContainerElement.ts'; -import type { FilterElement } from '../typedefs/FilterElement.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; -export function hideInstance(instance: Instance) +export function hideInstance( + instance: HostConfig['instance'] +) { - const { - Container, - Filter, - } = catalogue; - - if (Container && instance instanceof Container) + if (instance instanceof Container) { - (instance as ContainerElement).visible = false; + instance.visible = false; } - else if (Filter && instance instanceof Filter) + else if (instance instanceof Filter) { - (instance as FilterElement).enabled = false; + instance.enabled = false; } } diff --git a/src/helpers/insertBefore.ts b/src/helpers/insertBefore.ts index 2b5feb80..4c8fe115 100644 --- a/src/helpers/insertBefore.ts +++ b/src/helpers/insertBefore.ts @@ -7,11 +7,13 @@ import { detach } from './detach.ts'; import { invariant } from './invariant.ts'; import { log } from './log.ts'; -import type { ContainerElement } from '../typedefs/ContainerElement.ts'; -import type { FilterElement } from '../typedefs/FilterElement.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; -export function insertBefore(parentInstance: Instance, childInstance: Instance, beforeChildInstance: Instance) +export function insertBefore( + parentInstance: HostConfig['containerInstance'], + childInstance: HostConfig['instance'], + beforeChildInstance: HostConfig['instance'], +) { log('info', 'lifecycle::insertBefore'); @@ -19,23 +21,24 @@ export function insertBefore(parentInstance: Instance, childIn if (childInstance instanceof Container) { - const childContainerInstance = childInstance as Instance; + const childContainerInstance = childInstance as HostConfig['containerInstance']; + const childContainer = childInstance as unknown as Container; if (childContainerInstance.parent === parentInstance) { - parentInstance.removeChild(childContainerInstance); + parentInstance.removeChild(childContainer); } - const index = parentInstance.getChildIndex(beforeChildInstance as Instance); + const index = parentInstance.getChildIndex(childContainer); - parentInstance.addChildAt(childContainerInstance, index); + parentInstance.addChildAt(childContainer, index); } else if (childInstance instanceof Filter) { - const childFilterInstance = childInstance as Instance; + const childFilterInstance = childInstance; const instanceState = childFilterInstance.__pixireact; - const targetIndex = instanceState.filters.indexOf(beforeChildInstance as Instance); + const targetIndex = instanceState.filters.indexOf(beforeChildInstance as unknown as Filter); detach(childInstance); attach(parentInstance, childInstance, targetIndex); diff --git a/src/helpers/isReadOnlyProperty.ts b/src/helpers/isReadOnlyProperty.ts index 16c012ee..3da59563 100644 --- a/src/helpers/isReadOnlyProperty.ts +++ b/src/helpers/isReadOnlyProperty.ts @@ -1,4 +1,7 @@ -export function isReadOnlyProperty(objectInstance: Record, propertyKey: string) +export function isReadOnlyProperty( + objectInstance: Record, + propertyKey: string, +) { const prototype = Object.getPrototypeOf(objectInstance); const propertyDescriptor = Object.getOwnPropertyDescriptor(prototype, propertyKey); diff --git a/src/helpers/prepareInstance.ts b/src/helpers/prepareInstance.ts index 63f28ee7..1362d1b5 100644 --- a/src/helpers/prepareInstance.ts +++ b/src/helpers/prepareInstance.ts @@ -1,23 +1,24 @@ -import type { Container } from 'pixi.js'; -import type { Instance } from '../typedefs/Instance.ts'; -import type { InstanceState } from '../typedefs/InstanceState.ts'; -import type { PixiElement } from '../typedefs/PixiElement.ts'; +import type { + Container, + Filter, +} from 'pixi.js'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; +import type { NodeState } from '../typedefs/NodeState.ts'; /** Create the instance with the provided sate and attach the component to it. */ -export function prepareInstance( +export function prepareInstance( component: T, - state: Partial = {}, + state: Partial = {}, ) { - const instance = component as Instance; + const instance = component as HostConfig['instance']; - instance.__pixireact = { + instance.__pixireact = Object.assign({ filters: [], parent: null, - root: null as unknown as Instance, + root: null as unknown as HostConfig['containerInstance'], type: '', - ...state, - }; + }, state); return instance; } diff --git a/src/helpers/prepareUpdate.ts b/src/helpers/prepareUpdate.ts index ffffcdbb..3a902417 100644 --- a/src/helpers/prepareUpdate.ts +++ b/src/helpers/prepareUpdate.ts @@ -1,15 +1,14 @@ import { diffProps } from './diffProps.ts'; import { log } from './log.ts'; -import type { Instance } from '../typedefs/Instance.ts'; -import type { InstanceProps } from '../typedefs/InstanceProps.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; import type { UpdatePayload } from '../typedefs/UpdatePayload.ts'; export function prepareUpdate( - _instance: Instance, - _type: string, - oldProps: InstanceProps, - newProps: InstanceProps, + _instance: HostConfig['instance'], + _type: HostConfig['type'], + oldProps: HostConfig['props'], + newProps: HostConfig['props'], ) { log('info', 'lifecycle::prepareUpdate'); diff --git a/src/helpers/removeChild.ts b/src/helpers/removeChild.ts index 59f3d5d9..60f22099 100644 --- a/src/helpers/removeChild.ts +++ b/src/helpers/removeChild.ts @@ -2,10 +2,13 @@ import { Filter } from 'pixi.js'; import { detach } from './detach.ts'; import { log } from './log.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; /** Removes elements from our scene and disposes of them. */ -export function removeChild(_parentInstance: Instance, childInstance: Instance) +export function removeChild( + _parentInstance: HostConfig['containerInstance'], + childInstance: HostConfig['instance'], +) { log('info', 'lifecycle::removeChild'); diff --git a/src/helpers/switchInstance.ts b/src/helpers/switchInstance.ts index e116771a..b00202ad 100644 --- a/src/helpers/switchInstance.ts +++ b/src/helpers/switchInstance.ts @@ -3,12 +3,10 @@ import { createInstance } from './createInstance.ts'; import { removeChild } from './removeChild.ts'; import type { Fiber } from 'react-reconciler'; -import type { ContainerElement } from '../typedefs/ContainerElement.ts'; import type { HostConfig } from '../typedefs/HostConfig.ts'; -import type { Instance } from '../typedefs/Instance.ts'; export function switchInstance( - instance: Instance, + instance: HostConfig['instance'], type: HostConfig['type'], newProps: HostConfig['props'], fiber: Fiber, @@ -21,20 +19,20 @@ export function switchInstance( return; } - const root = instance.__pixireact?.root as Instance; + const root = instance.__pixireact.root as HostConfig['containerInstance']; const newInstance = createInstance(type, newProps, root); - if (!instance.autoRemovedBeforeAppend) + if (!instance.__pixireact.autoRemovedBeforeAppend) { removeChild(parent, instance); } if (newInstance.parent) { - newInstance.autoRemovedBeforeAppend = true; + newInstance.__pixireact.autoRemovedBeforeAppend = true; } - appendChild(parent as Instance, newInstance); + appendChild(parent as HostConfig['containerInstance'], newInstance); // This evil hack switches the react-internal fiber node // https://github.com/facebook/react/issues/14983 diff --git a/src/helpers/unhideInstance.ts b/src/helpers/unhideInstance.ts index 7a94d9e9..f42ccc23 100644 --- a/src/helpers/unhideInstance.ts +++ b/src/helpers/unhideInstance.ts @@ -3,18 +3,18 @@ import { Filter, } from 'pixi.js'; -import type { ContainerElement } from '../typedefs/ContainerElement.ts'; -import type { FilterElement } from '../typedefs/FilterElement.ts'; -import type { Instance } from '../typedefs/Instance.ts'; +import type { HostConfig } from '../typedefs/HostConfig.ts'; -export function unhideInstance(instance: Instance) +export function unhideInstance( + instance: HostConfig['instance'], +) { - if (Container && instance instanceof Container) + if (instance instanceof Container) { - (instance as ContainerElement).visible = true; + instance.visible = true; } - else if (Filter && instance instanceof Filter) + else if (instance instanceof Filter) { - (instance as FilterElement).enabled = true; + instance.enabled = true; } } diff --git a/src/typedefs/ApplicationProps.ts b/src/typedefs/ApplicationProps.ts index 560bf782..e702fcd8 100644 --- a/src/typedefs/ApplicationProps.ts +++ b/src/typedefs/ApplicationProps.ts @@ -5,22 +5,37 @@ import type { TextStyleOptions, } from 'pixi.js'; import type { - PropsWithChildren, + Key, RefObject, } from 'react'; -import type { Overwrite } from './Overwrite.ts'; +import type { PixiReactChildNode } from './PixiReactChildNode.ts'; -export interface BaseApplicationProps extends ApplicationOptions +export interface BaseApplicationProps { /** @description Whether this application chould be attached to the dev tools. NOTE: This should only be enabled on one application at a time. */ attachToDevTools?: boolean + /** @description CSS classes to be applied to the Pixi Application's canvas element. */ className?: string + + /** @description Child components. */ + children: PixiReactChildNode; + /** @description The default style to be applied to text nodes. */ defaultTextStyle?: TextStyle | TextStyleOptions, + + /** @description A unique key which allows React to manage this component across changes in parent state. */ + key?: Key, + /** @description Callback to be fired when the application finishes initializing. */ onInit?: (app: Application) => void + + /** @description An element (or React ref) to which the application's canvas will be resized. */ + resizeTo?: HTMLElement | Window | RefObject } -export type ApplicationPropsWithResizeToRef = Overwrite }>; -export type ApplicationProps = Partial>>; +export type ApplicationProps = BaseApplicationProps & Partial<{ + [K in keyof ApplicationOptions as K]?: K extends keyof BaseApplicationProps + ? BaseApplicationProps[K] + : ApplicationOptions[K]; +}>; diff --git a/src/typedefs/BasePixiReactNode.ts b/src/typedefs/BasePixiReactNode.ts new file mode 100644 index 00000000..2ef7fbdf --- /dev/null +++ b/src/typedefs/BasePixiReactNode.ts @@ -0,0 +1,7 @@ +import type { + Container, + Filter, +} from 'pixi.js'; +import type { PixiReactNode } from './PixiReactNode.ts'; + +export type BasePixiReactNode any = typeof Container | typeof Filter> = PixiReactNode; diff --git a/src/typedefs/ConstructorOptions.ts b/src/typedefs/ConstructorOptions.ts index 8c01a3bb..14993e20 100644 --- a/src/typedefs/ConstructorOptions.ts +++ b/src/typedefs/ConstructorOptions.ts @@ -4,7 +4,7 @@ import type { ConstructorOverrides } from './ConstructorOverrides'; * We're adding a specific options type overrides for some components because their deprecated overloads get in the way. * @see https://github.com/pixijs/pixi-react/issues/500 */ -export type ConstructorOptions any> = +export type ConstructorOptions any> = Extract extends [T, infer R] ? unknown extends R ? ConstructorParameters[0] diff --git a/src/typedefs/ContainerElement.ts b/src/typedefs/ContainerElement.ts deleted file mode 100644 index f2fe638e..00000000 --- a/src/typedefs/ContainerElement.ts +++ /dev/null @@ -1,4 +0,0 @@ -import type { Container } from 'pixi.js'; -import type { ReactElement } from 'react'; - -export type ContainerElement = Container & ReactElement; diff --git a/src/typedefs/DrawCallback.ts b/src/typedefs/DrawCallback.ts new file mode 100644 index 00000000..52be2a04 --- /dev/null +++ b/src/typedefs/DrawCallback.ts @@ -0,0 +1,3 @@ +import type { Graphics } from 'pixi.js'; + +export type DrawCallback = (graphics: Graphics) => void; diff --git a/src/typedefs/EventHandlers.ts b/src/typedefs/EventHandlers.ts index 2d4a4990..8ab30c82 100644 --- a/src/typedefs/EventHandlers.ts +++ b/src/typedefs/EventHandlers.ts @@ -1,9 +1,13 @@ import type { + FederatedEventHandler, FederatedPointerEvent, FederatedWheelEvent, } from 'pixi.js'; import type { ReactToPixiEventPropNames } from '../constants/EventPropNames.ts'; export type EventHandlers = { - -readonly [K in keyof typeof ReactToPixiEventPropNames]?: (event: FederatedPointerEvent | FederatedWheelEvent) => void + -readonly [K in keyof typeof ReactToPixiEventPropNames]?: + | FederatedEventHandler + | FederatedEventHandler + | null }; diff --git a/src/typedefs/FilterElement.ts b/src/typedefs/FilterElement.ts deleted file mode 100644 index 4df48eec..00000000 --- a/src/typedefs/FilterElement.ts +++ /dev/null @@ -1,4 +0,0 @@ -import type { Filter } from 'pixi.js'; -import type { ReactElement } from 'react'; - -export type FilterElement = Filter & ReactElement; diff --git a/src/typedefs/HostConfig.ts b/src/typedefs/HostConfig.ts index 3fbac6bd..1e02d267 100644 --- a/src/typedefs/HostConfig.ts +++ b/src/typedefs/HostConfig.ts @@ -1,20 +1,25 @@ -import type { Instance } from './Instance.ts'; +import type { + Container, + Filter, +} from 'pixi.js'; import type { NamespacedPixiElements } from './NamespacedPixiElements.ts'; import type { PixiElements } from './PixiElements.ts'; +import type { PixiReactNode } from './PixiReactNode.ts'; export interface HostConfig { - type: keyof PixiElements | keyof NamespacedPixiElements; - props: Record; - container: Instance; - instance: Instance; - textInstance: Instance; - suspenseInstance: Instance; - hydratableInstance: never; - publicInstance: Instance; - hostContext: null; - updatePayload: object; childSet: never; - timeoutHandle: number; + containerInstance: PixiReactNode; + filterInstance: PixiReactNode; + hostContext: null; + hydratableInstance: never; + instance: PixiReactNode; noTimeout: -1; + props: Record; + publicInstance: PixiReactNode; + suspenseInstance: PixiReactNode; + textInstance: PixiReactNode; + timeoutHandle: number; + type: keyof PixiElements | keyof NamespacedPixiElements; + updatePayload: object; } diff --git a/src/typedefs/Instance.ts b/src/typedefs/Instance.ts deleted file mode 100644 index e6b343a1..00000000 --- a/src/typedefs/Instance.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Graphics } from 'pixi.js'; -import type { ContainerElement } from './ContainerElement.ts'; -import type { EventHandlers } from './EventHandlers.ts'; -import type { InstanceState } from './InstanceState.ts'; -import type { PixiElement } from './PixiElement.ts'; - -export type Instance = T & EventHandlers & -{ - __pixireact: InstanceState; - autoRemovedBeforeAppend?: boolean; - children?: T extends ContainerElement - ? ContainerElement | ContainerElement[] - : never; - draw?: T extends Graphics - ? (graphics: Graphics) => void - : null; - parent?: Instance, -}; diff --git a/src/typedefs/InstanceProps.ts b/src/typedefs/InstanceProps.ts deleted file mode 100644 index 22263360..00000000 --- a/src/typedefs/InstanceProps.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Graphics } from 'pixi.js'; -import type { ContainerElement } from './ContainerElement.ts'; -import type { InstanceState } from './InstanceState.ts'; - -export type InstanceProps = { - [key: string]: unknown - __pixireact?: InstanceState - autoRemovedBeforeAppend?: boolean - children?: ContainerElement | ContainerElement[] - draw?: (graphics: Graphics) => void -}; diff --git a/src/typedefs/InstanceState.ts b/src/typedefs/InstanceState.ts deleted file mode 100644 index 339ed625..00000000 --- a/src/typedefs/InstanceState.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Filter } from 'pixi.js'; -import type { ContainerElement } from './ContainerElement.ts'; -import type { Instance } from './Instance.ts'; - -export interface InstanceState -{ - autoRemovedBeforeAppend?: boolean; - filters: Filter[], - parent: null | Instance; - root: Instance; - type: string; -} diff --git a/src/typedefs/InternalState.ts b/src/typedefs/InternalState.ts index 1d9d75b2..1f3bc333 100644 --- a/src/typedefs/InternalState.ts +++ b/src/typedefs/InternalState.ts @@ -1,5 +1,5 @@ import type { Application } from 'pixi.js'; -import type { Instance } from './Instance.ts'; +import type { HostConfig } from './HostConfig.ts'; export interface InternalState { @@ -7,5 +7,5 @@ export interface InternalState canvas?: HTMLCanvasElement; debug?: boolean; isInitialising?: boolean; - rootContainer: Instance; + rootContainer: HostConfig['containerInstance']; } diff --git a/src/typedefs/MaybeInstance.ts b/src/typedefs/MaybeInstance.ts deleted file mode 100644 index d0018050..00000000 --- a/src/typedefs/MaybeInstance.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { - FederatedEventHandler, - FederatedPointerEvent, - FederatedWheelEvent, -} from 'pixi.js'; -import type { PixiToReactEventPropNames } from '../constants/EventPropNames.ts'; -import type { Instance } from './Instance.ts'; -import type { PartialBy } from './PartialBy.ts'; - -export type StupidEventHandlers = { - -readonly [K in keyof typeof PixiToReactEventPropNames]?: - | FederatedEventHandler - | FederatedEventHandler - | null -}; - -export type MaybeInstance = PartialBy & Partial; diff --git a/src/typedefs/NodeState.ts b/src/typedefs/NodeState.ts new file mode 100644 index 00000000..13b83a12 --- /dev/null +++ b/src/typedefs/NodeState.ts @@ -0,0 +1,11 @@ +import type { Filter } from 'pixi.js'; +import type { HostConfig } from './HostConfig.ts'; + +export interface NodeState +{ + autoRemovedBeforeAppend?: boolean; + filters: Filter[], + parent: null | HostConfig['containerInstance']; + root: HostConfig['containerInstance']; + type: string; +} diff --git a/src/typedefs/NonFunctionKeys.ts b/src/typedefs/NonFunctionKeys.ts deleted file mode 100644 index 096312cc..00000000 --- a/src/typedefs/NonFunctionKeys.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare type NonFunctionKeys = { - [K in keyof T]-?: T[K] extends (...args: any[]) => any ? never : K; -}[keyof T]; diff --git a/src/typedefs/OmitChildren.ts b/src/typedefs/OmitChildren.ts deleted file mode 100644 index dd25dde2..00000000 --- a/src/typedefs/OmitChildren.ts +++ /dev/null @@ -1 +0,0 @@ -export type OmitChildren = T extends undefined ? never : Omit; diff --git a/src/typedefs/Overwrite.ts b/src/typedefs/Overwrite.ts deleted file mode 100644 index 661ca6ee..00000000 --- a/src/typedefs/Overwrite.ts +++ /dev/null @@ -1,3 +0,0 @@ -import type { NonFunctionKeys } from './NonFunctionKeys.ts'; - -export declare type Overwrite = T extends undefined ? never : Omit> & O; diff --git a/src/typedefs/PartialBy.ts b/src/typedefs/PartialBy.ts deleted file mode 100644 index daa3fda3..00000000 --- a/src/typedefs/PartialBy.ts +++ /dev/null @@ -1,2 +0,0 @@ -/** @see https://stackoverflow.com/a/54178819 */ -export type PartialBy = Omit & Partial>; diff --git a/src/typedefs/AutoFilteredKeys.ts b/src/typedefs/PixiComponents.ts similarity index 84% rename from src/typedefs/AutoFilteredKeys.ts rename to src/typedefs/PixiComponents.ts index da080575..4df9e33d 100644 --- a/src/typedefs/AutoFilteredKeys.ts +++ b/src/typedefs/PixiComponents.ts @@ -2,6 +2,6 @@ import type * as PIXI from 'pixi.js'; export type PixiType = typeof PIXI; -export type AutoFilteredKeys = { +export type PixiComponents = { [K in keyof PixiType]: PixiType[K] extends new (...args: any) => any ? K : never }[keyof PixiType]; diff --git a/src/typedefs/PixiElement.ts b/src/typedefs/PixiElement.ts deleted file mode 100644 index 7ab035c3..00000000 --- a/src/typedefs/PixiElement.ts +++ /dev/null @@ -1,4 +0,0 @@ -import type { ContainerElement } from './ContainerElement'; -import type { FilterElement } from './FilterElement'; - -export type PixiElement = FilterElement | ContainerElement; diff --git a/src/typedefs/PixiElements.ts b/src/typedefs/PixiElements.ts index d903a8a9..7c974ebf 100644 --- a/src/typedefs/PixiElements.ts +++ b/src/typedefs/PixiElements.ts @@ -1,8 +1,12 @@ import type * as PIXI from 'pixi.js'; import type { NameOverrides } from '../constants/NameOverrides.ts'; -import type { AutoFilteredKeys } from './AutoFilteredKeys.ts'; -import type { PixiReactNode } from './PixiReactNode.ts'; +import type { PixiComponents } from './PixiComponents.ts'; +import type { PixiReactElementProps } from './PixiReactNode.ts'; export type PixiElements = { - [K in AutoFilteredKeys as K extends keyof typeof NameOverrides ? typeof NameOverrides[K] : Uncapitalize]: PixiReactNode + [K in PixiComponents as K extends keyof typeof NameOverrides ? typeof NameOverrides[K] : Uncapitalize]: { + [K2 in keyof PixiReactElementProps as K2]?: PixiReactElementProps[K2] extends (...args: any) => any + ? never + : PixiReactElementProps[K2]; + }; }; diff --git a/src/typedefs/PixiReactChildNode.ts b/src/typedefs/PixiReactChildNode.ts new file mode 100644 index 00000000..250633b1 --- /dev/null +++ b/src/typedefs/PixiReactChildNode.ts @@ -0,0 +1,4 @@ +import type { ReactNode } from 'react'; +import type { BasePixiReactNode } from './BasePixiReactNode.ts'; + +export type PixiReactChildNode = BasePixiReactNode | Iterable | ReactNode; diff --git a/src/typedefs/PixiReactNode.ts b/src/typedefs/PixiReactNode.ts index 872de320..26e586ae 100644 --- a/src/typedefs/PixiReactNode.ts +++ b/src/typedefs/PixiReactNode.ts @@ -1,6 +1,58 @@ +import type { + Container, + Graphics, +} from 'pixi.js'; +import type { + Key, + Ref, +} from 'react'; +import type { PixiToReactEventPropNames } from '../constants/EventPropNames.ts'; import type { ConstructorOptions } from './ConstructorOptions.ts'; -import type { Overwrite } from './Overwrite.ts'; -import type { PixiReactNodeProps } from './PixiReactNodeProps.ts'; +import type { DrawCallback } from './DrawCallback.ts'; +import type { EventHandlers } from './EventHandlers.ts'; +import type { NodeState } from './NodeState.ts'; +import type { PixiReactChildNode } from './PixiReactChildNode.ts'; -export type PixiReactNode any> = - Overwrite>, PixiReactNodeProps>>; +export interface BaseNodeProps any = typeof Container> +{ + children: T extends Container + ? PixiReactChildNode + : never; + draw?: T extends Graphics + ? DrawCallback + : null; + key?: Key; + ref?: Ref; +} + +export interface NodeProps any = typeof Container> extends BaseNodeProps +{ + __pixireact: NodeState, + parent?: PixiReactNode; +} + +export type PixiReactNode any = typeof Container> = + NodeProps> + & EventHandlers + & { + [K in keyof InstanceType as K]: K extends keyof NodeProps> + ? NodeProps>[K] + : InstanceType[K]; + }; + +export type PixiReactElementProps any = typeof Container> = + BaseNodeProps> + & EventHandlers + & { + [ + K in keyof ConstructorOptions as ( + K extends keyof typeof PixiToReactEventPropNames + ? never + : K extends keyof NodeProps> + ? ConstructorOptions[K] extends NodeProps>[K] + ? never + : K + : K + ) + ]: ConstructorOptions[K]; + }; diff --git a/src/typedefs/PixiReactNodeProps.ts b/src/typedefs/PixiReactNodeProps.ts deleted file mode 100644 index 23c9184d..00000000 --- a/src/typedefs/PixiReactNodeProps.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Graphics } from 'pixi.js'; -import type { - Key, - ReactNode, - Ref, -} from 'react'; -import type { EventHandlers } from './EventHandlers.ts'; - -export interface BaseNodeProps any> -{ - children?: ReactNode; - key?: Key; - ref?: Ref; -} - -export type PixiReactNodeProps any> = T extends Graphics - ? BaseNodeProps & EventHandlers & { draw?: (graphics: Graphics) => void; } - : BaseNodeProps & EventHandlers; diff --git a/test/unit/core/createRoot.test.js b/test/unit/core/createRoot.test.ts similarity index 100% rename from test/unit/core/createRoot.test.js rename to test/unit/core/createRoot.test.ts diff --git a/test/unit/helpers/afterActiveInstanceBlur.test.js b/test/unit/helpers/afterActiveInstanceBlur.test.ts similarity index 100% rename from test/unit/helpers/afterActiveInstanceBlur.test.js rename to test/unit/helpers/afterActiveInstanceBlur.test.ts diff --git a/test/unit/helpers/appendChild.test.js b/test/unit/helpers/appendChild.test.ts similarity index 100% rename from test/unit/helpers/appendChild.test.js rename to test/unit/helpers/appendChild.test.ts diff --git a/test/unit/helpers/applyProps.test.js b/test/unit/helpers/applyProps.test.ts similarity index 100% rename from test/unit/helpers/applyProps.test.js rename to test/unit/helpers/applyProps.test.ts diff --git a/test/unit/index.test.js b/test/unit/index.test.ts similarity index 96% rename from test/unit/index.test.js rename to test/unit/index.test.ts index 2346f3a3..3ec4f75c 100644 --- a/test/unit/index.test.js +++ b/test/unit/index.test.ts @@ -3,7 +3,7 @@ import { expect, it, } from 'vitest'; -import * as PixiReact from '../../src/index.js'; +import * as PixiReact from '../../src/index.ts'; describe('exports', () => { diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index f6197d79..9f9c7b6e 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -8,6 +8,7 @@ "include": [ "test/**/*", "rollup.config.mjs", - "vitest.config.js", + "vitest.config.ts", + "vitest.workspace.ts", ] } diff --git a/vitest.config.js b/vitest.config.js deleted file mode 100644 index 1c9a076f..00000000 --- a/vitest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from 'vitest/config'; - -export default defineConfig({ - test: { - environment: 'jsdom', - }, -}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..94ede10e --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,3 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({}); diff --git a/vitest.workspace.ts b/vitest.workspace.ts new file mode 100644 index 00000000..736729bb --- /dev/null +++ b/vitest.workspace.ts @@ -0,0 +1,11 @@ +import { defineWorkspace } from 'vitest/config'; + +export default defineWorkspace([ + { + test: { + environment: 'jsdom', + include: ['test/unit/**/*.test.ts'], + pool: 'forks', + }, + }, +]);