From 0e311e541789792ddd796d4cc04efdf1de89d21e Mon Sep 17 00:00:00 2001 From: Iwo Plaza Date: Wed, 10 Sep 2025 18:12:27 +0200 Subject: [PATCH 1/6] Scaffold @typegpu/react --- packages/typegpu-react/README.md | 33 + packages/typegpu-react/deno.json | 7 + packages/typegpu-react/package.json | 45 ++ packages/typegpu-react/src/index.ts | 3 + packages/typegpu-react/src/useFrame.ts | 26 + packages/typegpu-react/src/useRender.ts | 3 + packages/typegpu-react/src/useUniformValue.ts | 3 + packages/typegpu-react/tsconfig.json | 5 + pnpm-lock.yaml | 765 ++++++++++++++++-- pnpm-workspace.yaml | 1 + 10 files changed, 827 insertions(+), 64 deletions(-) create mode 100644 packages/typegpu-react/README.md create mode 100644 packages/typegpu-react/deno.json create mode 100644 packages/typegpu-react/package.json create mode 100644 packages/typegpu-react/src/index.ts create mode 100644 packages/typegpu-react/src/useFrame.ts create mode 100644 packages/typegpu-react/src/useRender.ts create mode 100644 packages/typegpu-react/src/useUniformValue.ts create mode 100644 packages/typegpu-react/tsconfig.json diff --git a/packages/typegpu-react/README.md b/packages/typegpu-react/README.md new file mode 100644 index 000000000..7f2a9a14e --- /dev/null +++ b/packages/typegpu-react/README.md @@ -0,0 +1,33 @@ +
+ +# @typegpu/react + +🚧 **Under Construction** 🚧 + +
+ +# Basic usage (draft) + +```ts +import { hsvToRgb } from '@typegpu/color'; +import { useFrame, useRender, useUniformValue } from '@typegpu/react'; + +const App = () => { + const time = useUniformValue(0); + + // Runs each frame on the CPU 🤖 + useFrame(() => { + time.value = performance.now() / 1000; + }); + + const { ref } = useRender({ + // Runs each frame on the GPU 🌈 + fragment: () => { + 'kernel'; + return hsvToRgb(time.value, 1, 1); + }, + }); + + return ; +}; +``` diff --git a/packages/typegpu-react/deno.json b/packages/typegpu-react/deno.json new file mode 100644 index 000000000..734470f64 --- /dev/null +++ b/packages/typegpu-react/deno.json @@ -0,0 +1,7 @@ +{ + "exclude": ["."], + "fmt": { + "exclude": ["!.", "./dist"], + "singleQuote": true + } +} diff --git a/packages/typegpu-react/package.json b/packages/typegpu-react/package.json new file mode 100644 index 000000000..7fff3f823 --- /dev/null +++ b/packages/typegpu-react/package.json @@ -0,0 +1,45 @@ +{ + "name": "@typegpu/react", + "type": "module", + "version": "0.7.0", + "description": "The best way to integrate TypeGPU into your React app.", + "types": "./src/index.ts", + "exports": { + ".": "./src/index.ts", + "./package.json": "./package.json" + }, + "publishConfig": { + "directory": "dist", + "linkDirectory": false, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + "./package.json": "./dist/package.json", + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, + "sideEffects": false, + "scripts": { + "build": "tsdown", + "test:types": "pnpm tsc --p ./tsconfig.json --noEmit", + "prepublishOnly": "tgpu-dev-cli prepack" + }, + "keywords": [], + "license": "MIT", + "peerDependencies": { + "typegpu": "^0.7.0", + "react": "^18.0.0" + }, + "devDependencies": { + "@typegpu/tgpu-dev-cli": "workspace:*", + "@webgpu/types": "catalog:types", + "@types/react": "^18.0.0", + "tsdown": "catalog:build", + "typegpu": "workspace:*", + "typescript": "catalog:types", + "unplugin-typegpu": "workspace:*" + } +} diff --git a/packages/typegpu-react/src/index.ts b/packages/typegpu-react/src/index.ts new file mode 100644 index 000000000..a29c2c1b9 --- /dev/null +++ b/packages/typegpu-react/src/index.ts @@ -0,0 +1,3 @@ +export { useFrame } from './useFrame.ts'; +export { useRender } from './useRender.ts'; +export { useUniformValue } from './useUniformValue.ts'; diff --git a/packages/typegpu-react/src/useFrame.ts b/packages/typegpu-react/src/useFrame.ts new file mode 100644 index 000000000..66d767053 --- /dev/null +++ b/packages/typegpu-react/src/useFrame.ts @@ -0,0 +1,26 @@ +import { useEffect, useRef } from 'react'; + +export function useFrame(cb: () => void) { + const latestCb = useRef(cb); + + useEffect(() => { + latestCb.current = cb; + }, [cb]); + + useEffect(() => { + let frameId: number | undefined; + + const loop = () => { + frameId = requestAnimationFrame(loop); + latestCb.current(); + }; + + loop(); + + return () => { + if (frameId !== undefined) { + cancelAnimationFrame(frameId); + } + }; + }, []); +} diff --git a/packages/typegpu-react/src/useRender.ts b/packages/typegpu-react/src/useRender.ts new file mode 100644 index 000000000..9be666b11 --- /dev/null +++ b/packages/typegpu-react/src/useRender.ts @@ -0,0 +1,3 @@ +export function useRender() { + // TODO: Implement +} diff --git a/packages/typegpu-react/src/useUniformValue.ts b/packages/typegpu-react/src/useUniformValue.ts new file mode 100644 index 000000000..02e76794f --- /dev/null +++ b/packages/typegpu-react/src/useUniformValue.ts @@ -0,0 +1,3 @@ +export function useUniformValue() { + // TODO: Implement +} diff --git a/packages/typegpu-react/tsconfig.json b/packages/typegpu-react/tsconfig.json new file mode 100644 index 000000000..5f257dc0f --- /dev/null +++ b/packages/typegpu-react/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22c508cd6..3010f2e47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,6 +9,9 @@ catalogs: jiti: specifier: ^2.4.2 version: 2.4.2 + tsdown: + specifier: ^0.15.0 + version: 0.15.0 tsup: specifier: ^8.5.0 version: 8.5.0 @@ -106,7 +109,7 @@ importers: devDependencies: '@types/bun': specifier: latest - version: 1.2.20(@types/react@19.1.8) + version: 1.2.21(@types/react@19.1.8) apps/infra-benchmarks: devDependencies: @@ -121,19 +124,19 @@ importers: version: 0.9.4(prettier@3.5.3)(typescript@5.8.3) '@astrojs/react': specifier: ^4.3.0 - version: 4.3.0(@types/node@24.3.0)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(jiti@2.4.2)(lightningcss@1.30.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tsx@4.19.3)(yaml@2.8.0) + version: 4.3.0(@types/node@24.3.0)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(jiti@2.5.1)(lightningcss@1.30.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tsx@4.19.3)(yaml@2.8.0) '@astrojs/sitemap': specifier: ^3.5.0 version: 3.5.0 '@astrojs/starlight': specifier: ^0.35.2 - version: 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + version: 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) '@astrojs/starlight-tailwind': specifier: ^4.0.1 - version: 4.0.1(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(tailwindcss@4.1.11) + version: 4.0.1(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(tailwindcss@4.1.11) '@astrojs/tailwind': specifier: ^6.0.2 - version: 6.0.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))(tailwindcss@4.1.11) + version: 6.0.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))(tailwindcss@4.1.11) '@babel/standalone': specifier: ^7.27.0 version: 7.27.0 @@ -157,7 +160,7 @@ importers: version: 1.11.0 '@tailwindcss/vite': specifier: ^4.1.11 - version: 4.1.11(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) + version: 4.1.11(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) '@typegpu/color': specifier: workspace:* version: link:../../packages/typegpu-color @@ -178,7 +181,7 @@ importers: version: 2.1.20 astro: specifier: ^5.13.0 - version: 5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + version: 5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) classnames: specifier: ^2.5.1 version: 2.5.1 @@ -223,10 +226,10 @@ importers: version: 0.34.2 starlight-blog: specifier: ^0.23.2 - version: 0.23.2(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + version: 0.23.2(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) starlight-typedoc: specifier: ^0.19.0 - version: 0.19.0(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(typedoc-plugin-markdown@4.4.2(typedoc@0.27.9(typescript@5.8.3)))(typedoc@0.27.9(typescript@5.8.3)) + version: 0.19.0(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(typedoc-plugin-markdown@4.4.2(typedoc@0.27.9(typescript@5.8.3)))(typedoc@0.27.9(typescript@5.8.3)) tinybench: specifier: ^3.1.0 version: 3.1.1 @@ -272,7 +275,7 @@ importers: version: 24.3.0 '@vitejs/plugin-basic-ssl': specifier: ^2.1.0 - version: 2.1.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) + version: 2.1.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) '@webgpu/types': specifier: catalog:types version: 0.1.63 @@ -281,7 +284,7 @@ importers: version: 2.1.6 autoprefixer: specifier: ^10.4.21 - version: 10.4.21(postcss@8.5.3) + version: 10.4.21(postcss@8.5.6) tailwindcss: specifier: ^4.1.11 version: 4.1.11 @@ -293,7 +296,7 @@ importers: version: 7.1.0(rollup@4.34.8) vite-plugin-wasm: specifier: ^3.5.0 - version: 3.5.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) + version: 3.5.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) yaml: specifier: ^2.8.0 version: 2.8.0 @@ -345,7 +348,7 @@ importers: devDependencies: vitest: specifier: catalog:test - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(@vitest/browser@3.2.4)(jiti@2.4.2)(jsdom@26.1.0(canvas@3.2.0))(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(tsx@4.19.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(@vitest/browser@3.2.4)(jiti@2.5.1)(jsdom@26.1.0(canvas@3.2.0))(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(tsx@4.19.3)(yaml@2.8.0) packages/tgpu-wgsl-parser: dependencies: @@ -370,7 +373,7 @@ importers: version: 0.5.2 tsup: specifier: catalog:build - version: 8.5.0(jiti@2.4.2)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) tsx: specifier: ^4.16.2 version: 4.19.3 @@ -379,7 +382,7 @@ importers: version: 5.8.3 vitest: specifier: catalog:test - version: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(@vitest/browser@3.2.4)(jiti@2.4.2)(jsdom@26.1.0(canvas@3.2.0))(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(tsx@4.19.3)(yaml@2.8.0) + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(@vitest/browser@3.2.4)(jiti@2.5.1)(jsdom@26.1.0(canvas@3.2.0))(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(tsx@4.19.3)(yaml@2.8.0) publishDirectory: dist packages/tinyest: @@ -389,7 +392,7 @@ importers: version: link:../tgpu-dev-cli tsup: specifier: catalog:build - version: 8.5.0(jiti@2.4.2)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) typescript: specifier: catalog:types version: 5.8.3 @@ -415,7 +418,7 @@ importers: version: 8.14.1 tsup: specifier: catalog:build - version: 8.5.0(jiti@2.4.2)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) typescript: specifier: catalog:types version: 5.8.3 @@ -509,6 +512,35 @@ importers: version: link:../unplugin-typegpu publishDirectory: dist + packages/typegpu-react: + dependencies: + react: + specifier: ^18.0.0 + version: 18.3.1 + devDependencies: + '@typegpu/tgpu-dev-cli': + specifier: workspace:* + version: link:../tgpu-dev-cli + '@types/react': + specifier: ^18.0.0 + version: 18.3.24 + '@webgpu/types': + specifier: catalog:types + version: 0.1.63 + tsdown: + specifier: catalog:build + version: 0.15.0(typescript@5.8.3) + typegpu: + specifier: workspace:* + version: link:../typegpu + typescript: + specifier: catalog:types + version: 5.8.3 + unplugin-typegpu: + specifier: workspace:* + version: link:../unplugin-typegpu + publishDirectory: dist + packages/typegpu-sdf: devDependencies: '@typegpu/tgpu-dev-cli': @@ -599,7 +631,7 @@ importers: version: 4.34.8 tsup: specifier: catalog:build - version: 8.5.0(jiti@2.4.2)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + version: 8.5.0(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) typescript: specifier: catalog:types version: 5.8.3 @@ -734,6 +766,10 @@ packages: resolution: {integrity: sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==} engines: {node: '>=6.9.0'} + '@babel/generator@7.28.3': + resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} engines: {node: '>=6.9.0'} @@ -796,6 +832,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.28.4': + resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-transform-react-jsx-self@7.27.1': resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} engines: {node: '>=6.9.0'} @@ -844,6 +885,10 @@ packages: resolution: {integrity: sha512-x0LvFTekgSX+83TI28Y9wYPUfzrnl2aT5+5QLnO6v7mSJYtEEevuDRN0F0uSHRk1G1IWZC43o00Y0xDDrpBGPQ==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.4': + resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} + engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} @@ -966,12 +1011,21 @@ packages: '@emmetio/stream-reader@2.2.0': resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + '@emnapi/core@1.5.0': + resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==} + '@emnapi/runtime@1.4.3': resolution: {integrity: sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==} '@emnapi/runtime@1.4.4': resolution: {integrity: sha512-hHyapA4A3gPaDCNfiqyZUStTMqIkKRshqPIuDOXv1hcBnD4U3l8cP0T1HMCfGRxQ6V64TGCcoswChANyOAwbQg==} + '@emnapi/runtime@1.5.0': + resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} @@ -1733,6 +1787,9 @@ packages: '@jridgewell/gen-mapping@0.3.11': resolution: {integrity: sha512-C512c1ytBTio4MrpWKlJpyFHT6+qfFL8SZ58zBzJ1OOzUEjHeF1BtjY2fH7n4x/g2OV/KiiMLAivOp1DXmiMMw==} + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -1801,6 +1858,9 @@ packages: resolution: {integrity: sha512-B9nHSJYtsv79uo7QdkZ/b/WoKm20IkVSmTc/WCKarmDtFwM0dRx2ouEniqwNkzCSLn3fydzKmnMzjtfdOWt3VQ==} engines: {node: '>=18'} + '@napi-rs/wasm-runtime@1.0.3': + resolution: {integrity: sha512-rZxtMsLwjdXkMUGC3WwsPwLNVqVqnTJT6MNIB6e+5fhMcSCPP0AOsNWuMQ5mdCq6HNjs/ZeWAEchpqeprqBD2Q==} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1885,6 +1945,13 @@ packages: '@oslojs/encoding@1.1.0': resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + '@oxc-project/runtime@0.87.0': + resolution: {integrity: sha512-ky2Hqi2q/uGX36UfY79zxMbUqiNIl1RyKKVJfFenG70lbn+/fcaKBVTbhmUwn8a2wPyv2gNtDQxuDytbKX9giQ==} + engines: {node: '>=6.9.0'} + + '@oxc-project/types@0.87.0': + resolution: {integrity: sha512-ipZFWVGE9fADBVXXWJWY/cxpysc41Gt5upKDeb32F6WMgFyO7XETUMVq8UuREKCih+Km5E6p2VhEvf6Fuhey6g==} + '@pagefind/darwin-arm64@1.3.0': resolution: {integrity: sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==} cpu: [arm64] @@ -1934,6 +2001,9 @@ packages: '@probe.gl/stats@4.1.0': resolution: {integrity: sha512-EI413MkWKBDVNIfLdqbeNSJTs7ToBz/KVGkwi3D+dQrSIkRI2IYbWGAU3xX+D6+CI4ls8ehxMhNpUVMaZggDvQ==} + '@quansync/fs@0.1.5': + resolution: {integrity: sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==} + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} @@ -2199,9 +2269,95 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@rolldown/binding-android-arm64@1.0.0-beta.37': + resolution: {integrity: sha512-Pdr3USGBdoYzcygfJTSATHd7x476vVF3rnQ6SuUAh4YjhgGoNaI/ZycQ0RsonptwwU5NmQRWxfWv+aUPL6JlJg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.37': + resolution: {integrity: sha512-iDdmatSgbWhTYOq51G2CkJXwFayiuQpv/ywG7Bv3wKqy31L7d0LltUhWqAdfCl7eBG3gybfUm/iEXiTldH3jYA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.37': + resolution: {integrity: sha512-LQPpi3YJDtIprj6mwMbVM1gLM4BV2m9oqe9h3Y1UwAd20xs+imnzWJqWFpm4Hw9SiFmefIf3q4EPx2k6Nj2K7A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.37': + resolution: {integrity: sha512-9JnfSWfYd/YrZOu4Sj3rb2THBrCj70nJB/2FOSdg0O9ZoRrdTeB8b7Futo6N7HLWZM5uqqnJBX6VTpA0RZD+ow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.37': + resolution: {integrity: sha512-eEmQTpvefEtHxc0vg5sOnWCqBcGQB/SIDlPkkzKR9ESKq9BsjQfHxssJWuNMyQ+rpr9CYaogddyQtZ9GHkp8vA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.37': + resolution: {integrity: sha512-Ekv4OjDzQUl0X9kHM7M23N9hVRiYCYr89neLBNITCp7P4IHs1f6SNZiCIvvBVy6NIFzO1w9LZJGEeJYK5cQBVQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.37': + resolution: {integrity: sha512-z8Aa5Kar5mhh0RVZEL+zKJwNz1cgcDISmwUMcTk0w986T8JZJOJCfJ/u9e8pqUTIJjxdM8SZq9/24nMgMlx5ng==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.37': + resolution: {integrity: sha512-e+fNseKhfE/socjOw6VrQcXrbNKfi2V/KZ+ssuLnmeaYNGuJWqPhvML56oYhGb3IgROEEc61lzr3Riy5BIqoMA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.37': + resolution: {integrity: sha512-dPZfB396PMIasd19X0ikpdCvjK/7SaJFO8y5/TxnozJEy70vOf4GESe/oKcsJPav/MSTWBYsHjJSO6vX0oAW8g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.37': + resolution: {integrity: sha512-rFjLXoHpRqxJqkSBXHuyt6bhyiIFnvLD9X2iPmCYlfpEkdTbrY1AXg4ZbF8UMO5LM7DAAZm/7vPYPO1TKTA7Sg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.37': + resolution: {integrity: sha512-oQAe3lMaBGX6q0GSic0l3Obmd6/rX8R6eHLnRC8kyy/CvPLiCMV82MPGT8fxpPTo/ULFGrupSu2nV1zmOFBt/w==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.37': + resolution: {integrity: sha512-ucO6CiZhpkNRiVAk7ybvA9pZaMreCtfHej3BtJcBL5S3aYmp4h0g6TvaXLD5YRJx5sXobp/9A//xU4wPMul3Bg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.37': + resolution: {integrity: sha512-Ya9DBWJe1EGHwil7ielI8CdE0ELCg6KyDvDQqIFllnTJEYJ1Rb74DK6mvlZo273qz6Mw8WrMm26urfDeZhCc3Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.37': + resolution: {integrity: sha512-r+RI+wMReoTIF/uXqQWJcD8xGWXzCzUyGdpLmQ8FC+MCyPHlkjEsFRv8OFIYI6HhiGAmbfWVYEGf+aeLJzkHGw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/pluginutils@1.0.0-beta.19': resolution: {integrity: sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==} + '@rolldown/pluginutils@1.0.0-beta.37': + resolution: {integrity: sha512-0taU1HpxFzrukvWIhLRI4YssJX2wOW5q1MxPXWztltsQ13TE51/larZIwhFdpyk7+K43TH7x6GJ8oEqAo+vDbA==} + '@rollup/plugin-alias@5.1.1': resolution: {integrity: sha512-PR9zDb+rOzkRb2VD+EuKB7UC41vU5DIwZ5qqCpk0KJudcWAyi8rvYOhS7+L5aZCspw1stTViLgN5v6FF1p5cgQ==} engines: {node: '>=14.0.0'} @@ -2504,6 +2660,9 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@tybys/wasm-util@0.10.0': + resolution: {integrity: sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==} + '@types/acorn@4.0.6': resolution: {integrity: sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==} @@ -2528,8 +2687,8 @@ packages: '@types/bun@1.2.19': resolution: {integrity: sha512-d9ZCmrH3CJ2uYKXQIUuZ/pUnTqIvLDS0SK7pFmbx8ma+ziH/FRMoAq5bYpRG7y+w1gl+HgyNZbtqgMq4W4e2Lg==} - '@types/bun@1.2.20': - resolution: {integrity: sha512-dX3RGzQ8+KgmMw7CsW4xT5ITBSCrSbfHc36SNT31EOUg/LA9JWq0VDdEXDRSe1InVWpd2yLUM1FUF/kEOyTzYA==} + '@types/bun@1.2.21': + resolution: {integrity: sha512-NiDnvEqmbfQ6dmZ3EeUO577s4P5bf4HCTXtI6trMc6f6RzirY5IrF3aIookuSpyslFzrnvv2lmEWv5HyC1X79A==} '@types/chai@5.2.2': resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} @@ -2594,11 +2753,17 @@ packages: '@types/picomatch@4.0.1': resolution: {integrity: sha512-dLqxmi5VJRC9XTvc/oaTtk+bDb4RRqxLZPZ3jIpYBHEnDXX8lu02w2yWI6NsPPsELuVK298Z2iR8jgoWKRdUVQ==} + '@types/prop-types@15.7.15': + resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + '@types/react-dom@19.1.6': resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} peerDependencies: '@types/react': ^19.0.0 + '@types/react@18.3.24': + resolution: {integrity: sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==} + '@types/react@19.1.8': resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} @@ -2790,6 +2955,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansis@4.1.0: + resolution: {integrity: sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==} + engines: {node: '>=14'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -2824,6 +2993,10 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-kit@2.1.2: + resolution: {integrity: sha512-cl76xfBQM6pztbrFWRnxbrDm9EOqDr1BF6+qQnnDZG2Co2LjyUktkN9GTJfBAfdae+DbT2nJf2nCGAdDDN7W2g==} + engines: {node: '>=20.18.0'} + astring@1.9.0: resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==} hasBin: true @@ -2880,6 +3053,9 @@ packages: binary-search-bounds@2.0.5: resolution: {integrity: sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==} + birpc@2.5.0: + resolution: {integrity: sha512-VSWO/W6nNQdyP520F1mhf+Lc2f8pjGQOtoHHm7Ze8Go1kX7akpVIrtTa0fn+HB0QJEDVacl6aO08YE0PgXfdnQ==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -2921,8 +3097,8 @@ packages: peerDependencies: '@types/react': ^19 - bun-types@1.2.20: - resolution: {integrity: sha512-pxTnQYOrKvdOwyiyd/7sMt9yFOenN004Y6O4lCcCUoKVej48FS5cvTw9geRaEcB9TsDZaJKAxPTVvi8tFsVuXA==} + bun-types@1.2.21: + resolution: {integrity: sha512-sa2Tj77Ijc/NTLS0/Odjq/qngmEPZfbfnOERi0KRUYhT9R8M4VBioWVmMWE5GrYbKMc+5lVybXygLdibHaqVqw==} peerDependencies: '@types/react': ^19 @@ -3397,6 +3573,10 @@ packages: resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} engines: {node: '>=0.3.1'} + diff@8.0.2: + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} + engines: {node: '>=0.3.1'} + direction@2.0.1: resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} hasBin: true @@ -3431,6 +3611,15 @@ packages: resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} engines: {node: '>=4'} + dts-resolver@2.1.2: + resolution: {integrity: sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg==} + engines: {node: '>=20.18.0'} + peerDependencies: + oxc-resolver: '>=11.0.0' + peerDependenciesMeta: + oxc-resolver: + optional: true + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} @@ -3452,6 +3641,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + empathic@2.0.0: + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} + end-of-stream@1.4.5: resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} @@ -3591,6 +3784,15 @@ packages: picomatch: optional: true + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + figures@6.1.0: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} @@ -3679,6 +3881,9 @@ packages: get-tsconfig@4.10.0: resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==} + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -3979,6 +4184,10 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true + jiti@2.5.1: + resolution: {integrity: sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==} + hasBin: true + jotai-location@0.6.1: resolution: {integrity: sha512-qn7mCLcstuKckwpJwi/eCrxjimQZnN3PBjQQIIJ34UZSj/724tdSkFM8Tzd+fRflqo+ITOcB//CWRugoKTejOQ==} peerDependencies: @@ -4162,6 +4371,10 @@ packages: longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + loupe@3.1.4: resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} @@ -5006,6 +5219,9 @@ packages: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} + quansync@0.2.11: + resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + query-registry@3.0.1: resolution: {integrity: sha512-M9RxRITi2mHMVPU5zysNjctUT8bAPx6ltEXo/ir9+qmiM47Y7f0Ir3+OxUO5OjYAWdicBQRew7RtHtqUXydqlg==} engines: {node: '>=20'} @@ -5080,6 +5296,10 @@ packages: '@types/react': optional: true + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + react@19.1.0: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} @@ -5221,6 +5441,27 @@ packages: robust-predicates@3.0.2: resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==} + rolldown-plugin-dts@0.16.2: + resolution: {integrity: sha512-WV1J5OqhWL8O8Nd5VAVQghmNcjyQvcGI5w51VszjO9k73avbXpz9X86KLYcKTWXXH6L0f+93JzZxiiSrcYhDLw==} + engines: {node: '>=20.18.0'} + peerDependencies: + '@typescript/native-preview': '>=7.0.0-dev.20250601.1' + rolldown: ^1.0.0-beta.9 + typescript: ^5.0.0 + vue-tsc: ~3.0.3 + peerDependenciesMeta: + '@typescript/native-preview': + optional: true + typescript: + optional: true + vue-tsc: + optional: true + + rolldown@1.0.0-beta.37: + resolution: {integrity: sha512-KiTU6z1kHGaLvqaYjgsrv2LshHqNBn74waRZivlK8WbfN1obZeScVkQPKYunB66E/mxZWv/zyZlCv3xF2t0WOQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + rollup-plugin-dts@6.1.1: resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} engines: {node: '>=16'} @@ -5343,6 +5584,7 @@ packages: source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} + deprecated: The work that was done in this beta branch won't be included in future versions space-separated-tokens@2.0.2: resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} @@ -5514,6 +5756,9 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.0.1: + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + tinyglobby@0.2.12: resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} @@ -5522,6 +5767,10 @@ packages: resolution: {integrity: sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==} engines: {node: '>=12.0.0'} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + tinypool@1.1.1: resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} engines: {node: ^18.0.0 || >=20.0.0} @@ -5594,6 +5843,28 @@ packages: typescript: optional: true + tsdown@0.15.0: + resolution: {integrity: sha512-xbz8tvdlB2wspocZWcJQhZNDLJC+sKV+sTIpiRgfUiQCUxLFGnUZUPc9KoKp3nfMeXQqTyMi6FM9/SasSj+csQ==} + engines: {node: '>=20.19.0'} + hasBin: true + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + publint: ^0.3.0 + typescript: ^5.0.0 + unplugin-lightningcss: ^0.4.0 + unplugin-unused: ^0.5.0 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + publint: + optional: true + typescript: + optional: true + unplugin-lightningcss: + optional: true + unplugin-unused: + optional: true + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -5678,9 +5949,6 @@ packages: uc.micro@2.1.0: resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} - ufo@1.5.4: - resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} - ufo@1.6.1: resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==} @@ -5696,6 +5964,9 @@ packages: typescript: optional: true + unconfig@7.3.3: + resolution: {integrity: sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA==} + uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} @@ -6425,12 +6696,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@4.2.6(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))': + '@astrojs/mdx@4.2.6(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))': dependencies: '@astrojs/markdown-remark': 6.3.1 '@mdx-js/mdx': 3.1.0(acorn@8.15.0) acorn: 8.15.0 - astro: 5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + astro: 5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) es-module-lexer: 1.7.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -6452,15 +6723,15 @@ snapshots: dependencies: prismjs: 1.30.0 - '@astrojs/react@4.3.0(@types/node@24.3.0)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(jiti@2.4.2)(lightningcss@1.30.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tsx@4.19.3)(yaml@2.8.0)': + '@astrojs/react@4.3.0(@types/node@24.3.0)(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(jiti@2.5.1)(lightningcss@1.30.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(tsx@4.19.3)(yaml@2.8.0)': dependencies: '@types/react': 19.1.8 '@types/react-dom': 19.1.6(@types/react@19.1.8) - '@vitejs/plugin-react': 4.6.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) + '@vitejs/plugin-react': 4.6.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) react: 19.1.0 react-dom: 19.1.0(react@19.1.0) ultrahtml: 1.6.0 - vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -6486,22 +6757,22 @@ snapshots: stream-replace-string: 2.0.0 zod: 3.25.76 - '@astrojs/starlight-tailwind@4.0.1(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(tailwindcss@4.1.11)': + '@astrojs/starlight-tailwind@4.0.1(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(tailwindcss@4.1.11)': dependencies: - '@astrojs/starlight': 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + '@astrojs/starlight': 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) tailwindcss: 4.1.11 - '@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))': + '@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))': dependencies: '@astrojs/markdown-remark': 6.3.3 - '@astrojs/mdx': 4.2.6(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + '@astrojs/mdx': 4.2.6(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) '@astrojs/sitemap': 3.5.0 '@pagefind/default-ui': 1.3.0 '@types/hast': 3.0.4 '@types/js-yaml': 4.0.9 '@types/mdast': 4.0.4 - astro: 5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) - astro-expressive-code: 0.41.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + astro: 5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + astro-expressive-code: 0.41.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) bcp-47: 2.1.0 hast-util-from-html: 2.0.3 hast-util-select: 6.0.4 @@ -6524,9 +6795,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/tailwind@6.0.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))(tailwindcss@4.1.11)': + '@astrojs/tailwind@6.0.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0))(tailwindcss@4.1.11)': dependencies: - astro: 5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + astro: 5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) autoprefixer: 10.4.21(postcss@8.5.3) postcss: 8.5.3 postcss-load-config: 4.0.2(postcss@8.5.3) @@ -6586,6 +6857,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.28 jsesc: 3.1.0 + '@babel/generator@7.28.3': + dependencies: + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.28 + jsesc: 3.1.0 + '@babel/helper-compilation-targets@7.27.2': dependencies: '@babel/compat-data': 7.27.7 @@ -6643,6 +6922,10 @@ snapshots: dependencies: '@babel/types': 7.28.1 + '@babel/parser@7.28.4': + dependencies: + '@babel/types': 7.28.4 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.27.7)': dependencies: '@babel/core': 7.27.7 @@ -6702,6 +6985,11 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.27.1 + '@babel/types@7.28.4': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@bcoe/v8-coverage@1.0.2': {} '@biomejs/biome@1.9.4': @@ -6808,6 +7096,12 @@ snapshots: '@emmetio/stream-reader@2.2.0': {} + '@emnapi/core@1.5.0': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.4.3': dependencies: tslib: 2.8.1 @@ -6818,6 +7112,16 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.5.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + '@esbuild/aix-ppc64@0.24.2': optional: true @@ -7306,6 +7610,11 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.4 '@jridgewell/trace-mapping': 0.3.28 + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/trace-mapping': 0.3.28 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -7418,6 +7727,13 @@ snapshots: strict-event-emitter: 0.5.1 optional: true + '@napi-rs/wasm-runtime@1.0.3': + dependencies: + '@emnapi/core': 1.5.0 + '@emnapi/runtime': 1.5.0 + '@tybys/wasm-util': 0.10.0 + optional: true + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -7522,6 +7838,10 @@ snapshots: '@oslojs/encoding@1.1.0': {} + '@oxc-project/runtime@0.87.0': {} + + '@oxc-project/types@0.87.0': {} + '@pagefind/darwin-arm64@1.3.0': optional: true @@ -7557,6 +7877,10 @@ snapshots: '@probe.gl/stats@4.1.0': {} + '@quansync/fs@0.1.5': + dependencies: + quansync: 0.2.11 + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.2': {} @@ -7794,8 +8118,54 @@ snapshots: '@radix-ui/rect@1.1.1': {} + '@rolldown/binding-android-arm64@1.0.0-beta.37': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-beta.37': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.37': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.37': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.37': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.37': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.37': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.37': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.37': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.37': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.37': + dependencies: + '@napi-rs/wasm-runtime': 1.0.3 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.37': + optional: true + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.37': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.37': + optional: true + '@rolldown/pluginutils@1.0.0-beta.19': {} + '@rolldown/pluginutils@1.0.0-beta.37': {} + '@rollup/plugin-alias@5.1.1(rollup@4.34.8)': optionalDependencies: rollup: 4.34.8 @@ -8021,12 +8391,12 @@ snapshots: '@tailwindcss/oxide-win32-arm64-msvc': 4.1.11 '@tailwindcss/oxide-win32-x64-msvc': 4.1.11 - '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))': + '@tailwindcss/vite@4.1.11(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))': dependencies: '@tailwindcss/node': 4.1.11 '@tailwindcss/oxide': 4.1.11 tailwindcss: 4.1.11 - vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) '@testing-library/dom@10.4.0': dependencies: @@ -8045,6 +8415,11 @@ snapshots: '@trysound/sax@0.2.0': {} + '@tybys/wasm-util@0.10.0': + dependencies: + tslib: 2.8.1 + optional: true + '@types/acorn@4.0.6': dependencies: '@types/estree': 1.0.8 @@ -8087,9 +8462,9 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@types/bun@1.2.20(@types/react@19.1.8)': + '@types/bun@1.2.21(@types/react@19.1.8)': dependencies: - bun-types: 1.2.20(@types/react@19.1.8) + bun-types: 1.2.21(@types/react@19.1.8) transitivePeerDependencies: - '@types/react' @@ -8152,10 +8527,17 @@ snapshots: '@types/picomatch@4.0.1': {} + '@types/prop-types@15.7.15': {} + '@types/react-dom@19.1.6(@types/react@19.1.8)': dependencies: '@types/react': 19.1.8 + '@types/react@18.3.24': + dependencies: + '@types/prop-types': 15.7.15 + csstype: 3.1.3 + '@types/react@19.1.8': dependencies: csstype: 3.1.3 @@ -8196,11 +8578,11 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-basic-ssl@2.1.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))': + '@vitejs/plugin-basic-ssl@2.1.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))': dependencies: - vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) - '@vitejs/plugin-react@4.6.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))': + '@vitejs/plugin-react@4.6.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))': dependencies: '@babel/core': 7.27.7 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.27.7) @@ -8208,7 +8590,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.19 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) transitivePeerDependencies: - supports-color @@ -8229,6 +8611,24 @@ snapshots: - utf-8-validate - vite + '@vitest/browser@3.2.4(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))(vitest@3.2.4)': + dependencies: + '@testing-library/dom': 10.4.0 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.0) + '@vitest/mocker': 3.2.4(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) + '@vitest/utils': 3.2.4 + magic-string: 0.30.17 + sirv: 3.0.1 + tinyrainbow: 2.0.0 + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(@vitest/browser@3.2.4)(jiti@2.5.1)(jsdom@26.1.0(canvas@3.2.0))(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(tsx@4.19.3)(yaml@2.8.0) + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true + '@vitest/coverage-v8@3.1.2(@vitest/browser@3.2.4)(vitest@3.2.4)': dependencies: '@ampproject/remapping': 2.3.0 @@ -8266,6 +8666,15 @@ snapshots: msw: 2.10.2(@types/node@24.3.0)(typescript@5.8.3) vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + '@vitest/mocker@3.2.4(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + msw: 2.10.2(@types/node@24.3.0)(typescript@5.8.3) + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 @@ -8392,6 +8801,8 @@ snapshots: ansi-styles@6.2.1: {} + ansis@4.1.0: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -8422,11 +8833,16 @@ snapshots: assertion-error@2.0.1: {} + ast-kit@2.1.2: + dependencies: + '@babel/parser': 7.28.4 + pathe: 2.0.3 + astring@1.9.0: {} - astro-expressive-code@0.41.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)): + astro-expressive-code@0.41.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)): dependencies: - astro: 5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) + astro: 5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0) rehype-expressive-code: 0.41.2 astro-remote@0.3.3: @@ -8445,7 +8861,7 @@ snapshots: '@vtbag/turn-signal': 1.3.1 '@vtbag/utensil-drawer': 1.2.11 - astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0): + astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0): dependencies: '@astrojs/compiler': 2.12.2 '@astrojs/internal-helpers': 0.7.2 @@ -8501,8 +8917,8 @@ snapshots: unist-util-visit: 5.0.0 unstorage: 1.16.1 vfile: 6.0.3 - vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) - vitefu: 1.0.6(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + vitefu: 1.0.6(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 yocto-spinner: 0.2.3 @@ -8588,6 +9004,8 @@ snapshots: binary-search-bounds@2.0.5: {} + birpc@2.5.0: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -8645,7 +9063,7 @@ snapshots: '@types/node': 24.3.0 '@types/react': 19.1.8 - bun-types@1.2.20(@types/react@19.1.8): + bun-types@1.2.21(@types/react@19.1.8): dependencies: '@types/node': 24.3.0 '@types/react': 19.1.8 @@ -9121,6 +9539,8 @@ snapshots: diff@5.2.0: {} + diff@8.0.2: {} + direction@2.0.1: {} discontinuous-range@1.0.0: {} @@ -9159,6 +9579,8 @@ snapshots: dset@3.1.4: {} + dts-resolver@2.1.2: {} + eastasianwidth@0.2.0: {} electron-to-chromium@1.5.168: {} @@ -9176,6 +9598,8 @@ snapshots: emoji-regex@9.2.2: {} + empathic@2.0.0: {} + end-of-stream@1.4.5: dependencies: once: 1.4.0 @@ -9405,6 +9829,10 @@ snapshots: optionalDependencies: picomatch: 4.0.3 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 @@ -9489,6 +9917,10 @@ snapshots: dependencies: resolve-pkg-maps: 1.0.0 + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + github-from-package@0.0.0: optional: true @@ -9895,6 +10327,8 @@ snapshots: jiti@2.4.2: {} + jiti@2.5.1: {} + jotai-location@0.6.1(jotai@2.12.5(@types/react@19.1.8)(react@19.1.0)): dependencies: jotai: 2.12.5(@types/react@19.1.8)(react@19.1.0) @@ -10044,6 +10478,10 @@ snapshots: longest-streak@3.1.0: {} + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + loupe@3.1.4: {} lru-cache@10.4.3: {} @@ -10638,7 +11076,7 @@ snapshots: acorn: 8.15.0 pathe: 2.0.3 pkg-types: 1.3.1 - ufo: 1.5.4 + ufo: 1.6.1 monaco-editor@0.52.2: {} @@ -10955,6 +11393,15 @@ snapshots: tsx: 4.19.3 yaml: 2.8.0 + postcss-load-config@6.0.1(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.3)(yaml@2.8.0): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + jiti: 2.5.1 + postcss: 8.5.6 + tsx: 4.19.3 + yaml: 2.8.0 + postcss-merge-longhand@7.0.4(postcss@8.5.6): dependencies: postcss: 8.5.6 @@ -11160,6 +11607,8 @@ snapshots: punycode@2.3.1: {} + quansync@0.2.11: {} + query-registry@3.0.1: dependencies: query-string: 9.1.1 @@ -11235,6 +11684,10 @@ snapshots: optionalDependencies: '@types/react': 19.1.8 + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + react@19.1.0: {} readable-stream@3.6.2: @@ -11449,6 +11902,45 @@ snapshots: robust-predicates@3.0.2: {} + rolldown-plugin-dts@0.16.2(rolldown@1.0.0-beta.37)(typescript@5.8.3): + dependencies: + '@babel/generator': 7.28.3 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + ast-kit: 2.1.2 + birpc: 2.5.0 + debug: 4.4.1 + dts-resolver: 2.1.2 + get-tsconfig: 4.10.1 + rolldown: 1.0.0-beta.37 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - oxc-resolver + - supports-color + + rolldown@1.0.0-beta.37: + dependencies: + '@oxc-project/runtime': 0.87.0 + '@oxc-project/types': 0.87.0 + '@rolldown/pluginutils': 1.0.0-beta.37 + ansis: 4.1.0 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.37 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.37 + '@rolldown/binding-darwin-x64': 1.0.0-beta.37 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.37 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.37 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.37 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.37 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.37 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.37 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.37 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.37 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.37 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.37 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.37 + rollup-plugin-dts@6.1.1(rollup@4.34.8)(typescript@5.8.3): dependencies: magic-string: 0.30.17 @@ -11639,12 +12131,12 @@ snapshots: stackback@0.0.2: {} - starlight-blog@0.23.2(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)): + starlight-blog@0.23.2(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)): dependencies: '@astrojs/markdown-remark': 6.3.1 - '@astrojs/mdx': 4.2.6(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + '@astrojs/mdx': 4.2.6(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) '@astrojs/rss': 4.0.11 - '@astrojs/starlight': 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + '@astrojs/starlight': 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) astro-remote: 0.3.3 github-slugger: 2.0.0 marked: 15.0.7 @@ -11656,9 +12148,9 @@ snapshots: - astro - supports-color - starlight-typedoc@0.19.0(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(typedoc-plugin-markdown@4.4.2(typedoc@0.27.9(typescript@5.8.3)))(typedoc@0.27.9(typescript@5.8.3)): + starlight-typedoc@0.19.0(@astrojs/starlight@0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)))(typedoc-plugin-markdown@4.4.2(typedoc@0.27.9(typescript@5.8.3)))(typedoc@0.27.9(typescript@5.8.3)): dependencies: - '@astrojs/starlight': 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) + '@astrojs/starlight': 0.35.2(astro@5.13.2(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(rollup@4.34.8)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0)) github-slugger: 2.0.0 typedoc: 0.27.9(typescript@5.8.3) typedoc-plugin-markdown: 4.4.2(typedoc@0.27.9(typescript@5.8.3)) @@ -11825,6 +12317,8 @@ snapshots: tinyexec@0.3.2: {} + tinyexec@1.0.1: {} + tinyglobby@0.2.12: dependencies: fdir: 6.4.3(picomatch@4.0.3) @@ -11835,6 +12329,11 @@ snapshots: fdir: 6.4.6(picomatch@4.0.3) picomatch: 4.0.3 + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tinypool@1.1.1: {} tinyrainbow@2.0.0: {} @@ -11889,6 +12388,30 @@ snapshots: optionalDependencies: typescript: 5.8.3 + tsdown@0.15.0(typescript@5.8.3): + dependencies: + ansis: 4.1.0 + cac: 6.7.14 + chokidar: 4.0.3 + debug: 4.4.1 + diff: 8.0.2 + empathic: 2.0.0 + hookable: 5.5.3 + rolldown: 1.0.0-beta.37 + rolldown-plugin-dts: 0.16.2(rolldown@1.0.0-beta.37)(typescript@5.8.3) + semver: 7.7.2 + tinyexec: 1.0.1 + tinyglobby: 0.2.15 + tree-kill: 1.2.2 + unconfig: 7.3.3 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@typescript/native-preview' + - oxc-resolver + - supports-color + - vue-tsc + tslib@2.8.1: {} tsup@8.5.0(jiti@2.4.2)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0): @@ -11919,6 +12442,34 @@ snapshots: - tsx - yaml + tsup@8.5.0(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.3)(typescript@5.8.3)(yaml@2.8.0): + dependencies: + bundle-require: 5.1.0(esbuild@0.25.6) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.0 + debug: 4.4.1 + esbuild: 0.25.6 + fix-dts-default-cjs-exports: 1.0.0 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(jiti@2.5.1)(postcss@8.5.6)(tsx@4.19.3)(yaml@2.8.0) + resolve-from: 5.0.0 + rollup: 4.34.8 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tree-kill: 1.2.2 + optionalDependencies: + postcss: 8.5.6 + typescript: 5.8.3 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + tsx@4.19.3: dependencies: esbuild: 0.25.5 @@ -11975,8 +12526,6 @@ snapshots: uc.micro@2.1.0: {} - ufo@1.5.4: {} - ufo@1.6.1: {} ultrahtml@1.6.0: {} @@ -12014,6 +12563,13 @@ snapshots: - vue - vue-tsc + unconfig@7.3.3: + dependencies: + '@quansync/fs': 0.1.5 + defu: 6.1.4 + jiti: 2.5.1 + quansync: 0.2.11 + uncrypto@0.1.3: {} undici-types@7.10.0: {} @@ -12209,9 +12765,30 @@ snapshots: - tsx - yaml - vite-plugin-wasm@3.5.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)): + vite-node@3.2.4(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0): dependencies: - vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + cac: 6.7.14 + debug: 4.4.1 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite-plugin-wasm@3.5.0(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)): + dependencies: + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0): dependencies: @@ -12229,9 +12806,25 @@ snapshots: tsx: 4.19.3 yaml: 2.8.0 - vitefu@1.0.6(vite@6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)): + vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0): + dependencies: + esbuild: 0.25.6 + fdir: 6.4.6(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.34.8 + tinyglobby: 0.2.14 optionalDependencies: - vite: 6.3.5(@types/node@24.3.0)(jiti@2.4.2)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + '@types/node': 24.3.0 + fsevents: 2.3.3 + jiti: 2.5.1 + lightningcss: 1.30.1 + tsx: 4.19.3 + yaml: 2.8.0 + + vitefu@1.0.6(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)): + optionalDependencies: + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(@vitest/browser@3.2.4)(jiti@2.4.2)(jsdom@26.1.0(canvas@3.2.0))(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(tsx@4.19.3)(yaml@2.8.0): dependencies: @@ -12277,6 +12870,50 @@ snapshots: - tsx - yaml + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.3.0)(@vitest/browser@3.2.4)(jiti@2.5.1)(jsdom@26.1.0(canvas@3.2.0))(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(tsx@4.19.3)(yaml@2.8.0): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.0 + debug: 4.4.1 + expect-type: 1.2.1 + magic-string: 0.30.17 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 24.3.0 + '@vitest/browser': 3.2.4(msw@2.10.2(@types/node@24.3.0)(typescript@5.8.3))(vite@6.3.5(@types/node@24.3.0)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.19.3)(yaml@2.8.0))(vitest@3.2.4) + jsdom: 26.1.0(canvas@3.2.0) + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + volar-service-css@0.0.62(@volar/language-service@2.4.11): dependencies: vscode-css-languageservice: 6.3.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 0a4608727..7c724f474 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -8,6 +8,7 @@ catalog: catalogs: build: tsup: ^8.5.0 + tsdown: ^0.15.0 unbuild: ^3.5.0 jiti: ^2.4.2 types: From d64d837bfba28c5c74388cad1cdd1bf217accc17 Mon Sep 17 00:00:00 2001 From: Iwo Plaza Date: Tue, 16 Sep 2025 21:49:15 +0200 Subject: [PATCH 2/6] Adapt examples environment to allow for React examples --- apps/typegpu-docs/package.json | 1 + .../src/components/ExampleView.tsx | 12 ++++++--- .../components/stackblitz/openInStackBlitz.ts | 8 +++++- .../examples/react/triangle/index.html | 1 + .../content/examples/react/triangle/index.tsx | 20 ++++++++++++++ .../content/examples/react/triangle/meta.json | 5 ++++ .../examples/react/triangle/thumbnail.png | Bin 0 -> 185059 bytes .../src/examples/exampleContent.ts | 4 +-- .../src/utils/examples/sandboxModules.ts | 25 ++++++++++++++++++ .../utils/liveEditor/embeddedTypeScript.ts | 1 + pnpm-lock.yaml | 3 +++ 11 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 apps/typegpu-docs/src/content/examples/react/triangle/index.html create mode 100644 apps/typegpu-docs/src/content/examples/react/triangle/index.tsx create mode 100644 apps/typegpu-docs/src/content/examples/react/triangle/meta.json create mode 100644 apps/typegpu-docs/src/content/examples/react/triangle/thumbnail.png diff --git a/apps/typegpu-docs/package.json b/apps/typegpu-docs/package.json index 446b422de..dbe4226c7 100644 --- a/apps/typegpu-docs/package.json +++ b/apps/typegpu-docs/package.json @@ -27,6 +27,7 @@ "@typegpu/color": "workspace:*", "@typegpu/noise": "workspace:*", "@typegpu/sdf": "workspace:*", + "@typegpu/react": "workspace:*", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "arktype": "catalog:", diff --git a/apps/typegpu-docs/src/components/ExampleView.tsx b/apps/typegpu-docs/src/components/ExampleView.tsx index b2e655940..ff4bffa2d 100644 --- a/apps/typegpu-docs/src/components/ExampleView.tsx +++ b/apps/typegpu-docs/src/components/ExampleView.tsx @@ -69,17 +69,21 @@ function useExample( export function ExampleView({ example }: Props) { const { tsFiles, tsImport, htmlFile } = example; + const filePaths = tsFiles.map((file) => file.path); + const entryFile = filePaths.find((path) => + path.startsWith('index.ts') + ) as string; + const [snackbarText, setSnackbarText] = useAtom(currentSnackbarAtom); - const [currentFilePath, setCurrentFilePath] = useState('index.ts'); + const [currentFilePath, setCurrentFilePath] = useState(entryFile); const codeEditorShowing = useAtomValue(codeEditorShownAtom); const codeEditorMobileShowing = useAtomValue(codeEditorShownMobileAtom); const exampleHtmlRef = useRef(null); - const filePaths = tsFiles.map((file) => file.path); const editorTabsList = [ - 'index.ts', - ...filePaths.filter((name) => name !== 'index.ts'), + entryFile, + ...filePaths.filter((name) => name !== entryFile), 'index.html', ]; diff --git a/apps/typegpu-docs/src/components/stackblitz/openInStackBlitz.ts b/apps/typegpu-docs/src/components/stackblitz/openInStackBlitz.ts index 5fb6dcb6f..f0e32c2ec 100644 --- a/apps/typegpu-docs/src/components/stackblitz/openInStackBlitz.ts +++ b/apps/typegpu-docs/src/components/stackblitz/openInStackBlitz.ts @@ -10,7 +10,12 @@ import typegpuNoisePackageJson from '@typegpu/noise/package.json' with { import typegpuSdfPackageJson from '@typegpu/sdf/package.json' with { type: 'json', }; -import typegpuPackageJson from 'typegpu/package.json' with { type: 'json' }; +import typegpuReactPackageJson from '@typegpu/react/package.json' with { + type: 'json', +}; +import typegpuPackageJson from 'typegpu/package.json' with { + type: 'json', +}; import unpluginPackageJson from 'unplugin-typegpu/package.json' with { type: 'json', }; @@ -128,6 +133,7 @@ ${example.htmlFile.content} "@typegpu/noise": "${typegpuNoisePackageJson.version}", "@typegpu/color": "${typegpuColorPackageJson.version}", "@typegpu/sdf": "${typegpuSdfPackageJson.version}" + "@typegpu/react": "${typegpuReactPackageJson.version}" } }`, 'vite.config.js': `\ diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.html b/apps/typegpu-docs/src/content/examples/react/triangle/index.html new file mode 100644 index 000000000..2efc24ac5 --- /dev/null +++ b/apps/typegpu-docs/src/content/examples/react/triangle/index.html @@ -0,0 +1 @@ +
diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx new file mode 100644 index 000000000..126580782 --- /dev/null +++ b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx @@ -0,0 +1,20 @@ +function App() { + // TODO: Use useRender to draw a full-screen gradient + // TODO: Provide a time variable to the shader with useUniformValue + // TODO: Make the gradient shift colors over time using hsvToRgb from @typegpu/color + return
Hello
; +} + +// #region Example controls and cleanup + +import { createRoot } from 'react-dom/client'; +const reactRoot = createRoot( + document.getElementById('example-app') as HTMLDivElement, +); +reactRoot.render(); + +export function onCleanup() { + reactRoot.unmount(); +} + +// #endregion diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/meta.json b/apps/typegpu-docs/src/content/examples/react/triangle/meta.json new file mode 100644 index 000000000..537f2f145 --- /dev/null +++ b/apps/typegpu-docs/src/content/examples/react/triangle/meta.json @@ -0,0 +1,5 @@ +{ + "title": "React: Spinning Triangle", + "category": "react", + "tags": ["experimental"] +} diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/thumbnail.png b/apps/typegpu-docs/src/content/examples/react/triangle/thumbnail.png new file mode 100644 index 0000000000000000000000000000000000000000..889b2f297ba683488ec1634279f09728f080fc21 GIT binary patch literal 185059 zcmeFa2{e^!8$bNmaYCm7MUhBoGNcU2v^yD+P&6nRN`slqGN03_%$*8_P%2HR%=7M4 zoXU_0nMHO|4hy>3Slc>oaZ?haJ+TG8M;}WH z3DO>MvQiQ<(B37u&CcPNpsd6Oi48)^?1F-ViVjDQZ_!g#pMD*FQW7$Eac-NbDjS4|D_Z5-8Oj%E%P_D&Xdwt{Hf z!$<6#os@)x&_sX#nOf&DH;eBx**Z>d3pOZ;ej_O*u|e|hvEfxk^y!ve7H-F^52#w$ z0L@?y<&7I;HY(Cy_~BRIr=)w;fc{nK&GfI*{fhC`y^hBmw%OUhq)y7;88-bg{V%6q zRFp(}r=!Ibp=qB2rIpzgCI9A{GJ98Ab_OtVxrM6k9{36(hyF05uWP2h!uL!hp{H8~ z7ZL=S&{W;J$Bn78_ThX&aM2v88Xp78b?0k-y?DiUv&r$Kw6b2-MS^5sc!T*redCwR za*K&lJu#yAUml|U%8m3BvB2-YjfEa#X8xHVi3I%jN#VhtiTZyUY7r~zQi6HM;(wfT zDUtb4ix*t9Xam7|X$|S09^63K&-stUntoYO(3DuTW;gSHrs~v#rbP2k|B3G3)O2ew=FmIOk7qMCvrax;d^YRkPie?(6!|?qn~fr;X)&9o_?`fmO;b$M zVm3`No2K|4lh39pzC*+`YR;x9X44ekA!1rQX44e2X^J0Eb2d#eo2K}l$($CC*)+v$ zn&O9=>1>)}Hcdg7-==}aY?@*=O+lB*oDz@OG{tP1;(I1@T0CaEDQ43YvuTPSV)EHE z#SbKzO;gOKDQ43YKg8s-X^J06GMlEDO;gOKDHvn&X@`5Zo8o&6GMlEDO;gOKDZc9i zPK()YitjPVY?@*=O);CM_^uB)EoKjWe2+n9(-gC5irF;9cYVNUF?;A^_Rt6JWP*77 z-+1UFn6!8Ax4Qu7t>SD%IU7;_AmFow@7col4?*^9L^&H#;!zZ&tY`c4r`^Tbi1ND! zJsVNZMwD0-g&d68{`~)&3*VGuJv!A#i_(5t+0)~$)3EAQv9#m1O>(bfcC~N39J#Ff zp=f&aol8#+zdRUlsp6emi^ki-lG@3a3aV;%e=lqTAgY?PO|!iO=od-8C3oC&esZlJDv!a>Z(VPad$-!PB`6pH?s0Mc4;> zrLyDY&+b{7-TZawfcGxeG0=N5j!-fGrEf}eJkdmBdoWU*I~<7MhI5$p^iSZDlRY;MBOj`~8fz-#>FJWa8^VSfXhbAxc;~X&O-2R+8{+#+q#iuD}9jS)vOANMtR>iY0V|&f& z6k(jGd;Q#*$m~JfOydOwle@Z_v@qg=gpR}3N((fOZ^yRAe3$g{gU^C}GZ4^Nssh%L|W9(&~ls(Z;y6r5S)p0ONc zCpfoSarl}rWe)p2RKyoCv&e<99Q@xzj>*sG>r1;5ptfV`VkXeM`>hO`7o$aHqBwR% zyyc|V2*OWOP=wl_AaWT>G?E1 zHqIsaW`%oTTNCVE4vdO1i!Hu@Gv1RG^l9Xov7Sm%Ylm^JkgwPeYu$#{+IjH+!&(<2 z#ajFzqLTXY!^AD_WWw}Ls{+2-%^AQp$DYu)3{uMHckqkK+^P$s^2faspRFfd*2-dl z%64v0=I#k8M(A1fN{=|tTX|trjz8b$ZNPrw!L8P143j3HNxK6NFifi8SM|ZiHZ!cU ztS6#6(M^reTHA!FsV_yIWib)$Xi^-2)2NuDDFvf1?JD}ym?tcMd;7#ZDh+1dv@3%Fa&G{4bh4#xso`vGBV`eS zN`_jm%FL>}<88wG*omq=N~>@kZRZ49B~5JL!#QrhdV}s{d&Em-FK^=<^*XVZB}|o0 zc?|EGNCN(K3{if@mrdSlnn(!B7>ItncQv;lDE&&&dcvH80l%2@bzslcZ~3m^r08U~ z7NI&masO3Wr4A-8hKV~rozlg3_8;HvTteJf(8e~}u%KzqbsGne<$Z@wGEmD6l%Obz z?+<)lX|_~hs-uSd*4ToKL-FvckT189)W3XHm7UN#E5Eg=a>Qd-sx}DLA`WgXe90kP zKc3Y&FNqOY*m)F=hS-H$hgqLgp=287BhWlILTlT+mX8w z;@4DEg$~4l$}scFP_h!LBE3r>0AG%$zXou{1QL-4El=>#P?Z5 zZ|74Z+)pr?$7--Y!=p+Y=KL_{e&Rf7729ac@OC~HLi6QWoOjU(WaI}Qi{ZqjWQ2e4 zIj;Ak86o_{;s`;lOa@Gn8aHEMDEdoovq%idJESwNu(*Qp>QWJy+m#PjVwWIceK#VENfTXl7CExooG{d&%i6s zV4!F6Nx5}6nTHo$UQO+PQm#2+PPH)hpz+X=frlomU{c{G;38pgVdP;o-OaNk;axRXus+~*m&92_=}_ElNGs^Xx^)g^A;gLqOtxQ z{a(S^Z!=9M1X-#$y9M}5Y}JdZ(X{Ctwz$Yrki;(dNp3m5-M>iU&#B85w%ifuQYo>z z7cAtPYsKjA8X(0!#TSeVhbJr2&iF*w?b*Pn@;*aHJ>o$Ps|mxjThX+?%KnT`dwJeC zU%@!H&c}p7+Kw~YZm^o>*L5?zECnxzoRnq9U(V#%4raCg0NYShDUZo@Gu4*rs%wPl zL$-Vd!J7ka;c{PVR-Dosc>V&nt8)`)cUE$ul~a(pC$H;Ubq-3Et(y*xErs9}Ep55G zAAkSB+6Q99cE6V&Mvk|<4K#7{no40jp#uH3br*uJ%#*-JO-lwJA3y|6S>Bbh!^JXI1kvyJLI~QxlCCHW!$Hn z9BX%11DDs{JfeB1hu!C@=sV@63%fNZ6xFq;?8KvRhIn;Y5xsum&T9Pi4Q#m}*k`~+ zewe$CWDqdSpu;P`Kj^(2TZMD2S*JOj5X{@hY=8FagdfRQW=R=tC~l?XNOi!_og9?;RYQ{OM7R*6N$`fPO}HFn zU=yF;DVS^>Og3_t^+&T>1n8#NmLS7Grf9hNo5qm@@I>QqihTs{R%`p zu1SX>Lfyc2?;hew<*j=i8;@(3R4YJW8(ZT)fegpB*r<(Uv?9_ zR74sXsHOz8^!TNb0YU;O8vz8CFdg+Db^dgNHLkl=9H-lDwl&14-BC*|`8XWothjMC3o(|U%8UuGKQ7 z!dxFUV&p5Mn}lTNa)dc9-n}bPZ1rpV^RCdsH&N9Rq+P@=rRBy9d)9_MM@btqfP@W- zt-7}YPj8!~ASz#Eq_Q?pIWph`&Q(*5=BAO>q27Ydvgch_lTIX?3`G!&iQ*7H1_SqM z4e*v@$5MR9f6)?7@WWRwn37@IAQ|9`mlDui?1YQVh;lu}nRK zbnv67xl$~$KBTbVy(IkKA~o{ojTxS~0_<6KhJggTxDb1D%=J`wVSic-K+8nZ0>)@@ zFh;az$XXC#@M?e7Xfa7dPO^(-orfES61LN)*-NtX?^l_cz1mL5|jW5o72XDQ{DhUmtC=t(>%CcMs!@Ww4h>DhzOoueg))YxA$Vwb1GkRw^z9d3}A>I{Zo@|KqiH*50 z62o)N)no}%{U7(0&($VD3drE*z#s(mk^X&3(V#-0uM)8(iHD_5z;tSaSv+FKA zX-0+X0Z>ojyh#SgXkOyl5Q#~A4=gDGlRsPN+lnoo%u%yrvi+RWB9TQ*mg79KY2KE^8`$9 z?QjYYTO@^mc51S<8*#=N3IbA}i+S4bQr2O&nCX6wSgiWcd+PYW*<(D6PEG_E$X>lV zn}?VhK3I(6?Hu#>^1QKy;6$W#RNqbnTa|#@DtjA%w(3TcdzjDa$M2U0z%3l<7E-8d zHvXja19x&f#Df)gdZS^yPt)S;qSqey!kV@KuP&es&LtiA{l}THlP2HF63Km zl&3!U3kNyuHSW1&J^(8)&o1dE##^!xionxCgkwD3C&&g6oKLzFoFx|%oqFt;n)?N^ z0~0?M9^}Sgw~__Pz}c#&j&`1wLlH3h{=D>Vz`k|y5g4uPcLNc48Vp|IqLEF$K?n|1 zM!J>8tG6UTrt4__=d@>#xet5Au=?Au`as+J$FS8?(kTVh{+^1L;i_M9Bg*?M#0r=< z@HFMyy`85<)Oj~zUIj%4iLs+eBA$(1hf<=yrwU(aHwq4kZTk>Gw0(#g^6-EV@nR{S z>dKsX5!n>Qk=Rv(oX_PYOf-rTPJ(||m1Hu6n9xv$TiwiX*oIYC!W(>LA(Vq)RUbuc zH+E6j;vIR>gkeYu1^Jae(|!OBHziS0(#A{XSc z1y;~jVcplHXi}%ZLddD+|C?0=P<(npCL+?F+WTi0C>VN1UNa$OHYKF3w(>||HPwEB zo3zXez>@V{x6<&j?;^V(SjknNO`_dDmvEAsEj+d?NbDi?$R+h;?T30seW`=9m_OSqqKYCL@F;fh5_q+ zNMN5ocEqi`v%BN%`vjR`5#JoIgB}~2fFxGG#NZ0C7nKu_txo(6qcyk{7pU^~F-uF! zEUQzVC1j0?_|}Gmx%TJjGw(W7j}I|(Me;bw0|G&(n58i?4Y^8&F06p z0k?E7?v_%*&@wFK5`V{*p^Pks{N~kX`iJshD;1s-oRr3-yu32tOI(Q-?n^610AJc` zB~!4>gP*$Jb|&)YjjPY_<)|3ZR`Dv;%OZIRA-$Uo$ClM7d_Kx|JR1X|2a>%4lj9zn zx5l2@%lyEOPiDtml;h|(UQeoNvg5#>?L7p#7GqUVjC+i{%z8}ZQB|(zN;cQcfUqP{Mh3yqQC(z0M0qU7SqV*`1mhw#3Y8UhQQ1ZZC*0>if zA{fLfBJX{5-G&OB4%w7PgrJ%R*Vk{0h+`F$+M~iw+*QOwEXqX)58WQk-(-ZzRSma+ z)@1uf^FNi+0@LLYKOwMVwKhg>h#PJ|bs^MgelA<=gaMJMVH~9W531oSu=ZX|{M!MH zOeIHR4b`~1?--?)AjyWPTEi4*U>f#p8@5=tjbJ@=(+}UmD<~bbtdFzw)}{*4ErlP4 zE#@Nw_F038vM%r}#)jUbh?CY&c1Bnh+(hiuq?H z{|zAmXqnw$(Wj^q^Iaf|i}rF*=KhYGkN?07H6#w#)mPVtE^RpvtXy;U^Vn6AFW&+a z+=KB)`cQuS3SPWe?3ee!Cqz-$FJ`V)Zb*!NDpk6x06?-cM(D>OG|>>x)vt(Ric-&> z%1zwZSAN<}dh(pqb;p20npQ2n6-xS{Ri#WASb4?eC7w(*osa7zE_Y=sVFB`k&&BWs9a~{A_h20-)*z{!X+n@}Wzwh5T7bOWk6p-PsDEWBWEtR^d^p4eh$wR2ArOhW8FU~aI2Q@0q z-qeP>Py(bspq{^2+deczx1U$3@Z;nZA{8?vC8ANL|5N(Y)0kYFuI<(Jo>Yof)b$F| zIj1qE(h{9r)q7oy@MbX`iTH#!GDM^7)mxXRp4bqOlZ+i7FB%&v_>*m-azkYE3VvXr zTD2lDk$i+Pot=Q(g}YrFmSHGkze?+4M4`Kb9lAu)%T;#zXQR(>!qLud~Lz z*%(}goHaU=?QM_-d)g?2-cRT=>4F>{Q|Hw! zc)6!}J)nT+@7YqA0GsYNEg%G)!RzJuq9i!IfL{ujAz3%@fnfow&;st*;69r%u>ohj6%5OR$wU9$v(bXh1xgKG^n8rL2=rVq)&3( z?_>9`h4kkl6~2SGmx=0=W?ln$s${F*rSY;@gD(d-$S!p`g@>TeLJ{>^m8zOq72}fjr*V;JE>WtSNVBH58@9&U@ls+!G{%I<|O+<>h&(#Bg6^Z+}jjl^Aqw zMZT*|xonlXw8iG>y~!R>hWl67;6`=?<+3PS!g%M z_#rD0{l(!g=PETyOo;Gb%vuE}oN`pGVh zIUx;aGs>a&r|Vb7;>t`J^`(NS{BVXp%5xv{tL!v05JT?$>rmHb;%Y6tmB8~B2xnPk zB@ZSB(EcMzbv*IUo3De-r`zOWqtAaUH1gLe%Do?prMq;wSswfETU{ch^ zpjA*5^?!wzt2$Wn*l-1gu68dfTbtjusdR1nLJO9r>O|J&`G5LgulSOG1Iqp+yb||8 zeAtZfLzZ4!)7#e*ZNRtf<2H6OO%#+)mT^^X713Lk!&%$qu+0T4_ z=y(sWV{lJhYIOiHnEn`lT(B3C-rMN2l1!wttf)0ilNQGvFX9uHo&bDV^0NY(X^7;sRM znpU!XZ8%W>QxMHJ&nY0Cum~tHdflBd96cDQI?hg!$iX|A+{gekbKD{^On`JFq|5)% z*ONJ)8NB*%3-!99Y@zoBxnyVW;9#j!^X)b%)J0$K*Sxojd4tL^2Dj}EtTA_#?SVJF zB>cSC0CLz*wEd0Mh@3Ap=if}y<%Aw-Dl}iTSxe)-{MFvt>vo%RL^W{4Q|Wn5wASPbz9*8%Ds`kxaQcE%#6N&LMW?_i z`Fh&|clL8o?&QvIYnK6bRy#PAQ;Li`OK&jKNNF+OFU9F;q!rCYi579iHN_o-PPt4^ z7yne^)rIjggQ-%X_Bm+N_*gD`A~3cpjy2Bvd@gQbv{3T>>)=5Q@$%IL0UM8R7P&CT zzs~&qh*=P!Vf`~z!FONnWvkpZhif}12Y7vC8`TXAGfbGwm1N#y6pGsmwX1uVHq-NA zkvZpZna`+MfT5OK)t1Ze(ZE!T&M8^0oh)s7cBo}cw#&I$OuMh2O}1X6`ux6!Rq7n% zIq8e=aiCN8)lLz-)^Ly+8XE(QVCd25p&K0UYLB)xoVqY1dbCx`i67#X#Trxb3XPzE z0?=XPj&~Rhi-DPp6}iLksjTkgiI5~!JHeBD&`P$xR+JkmqCFFhGHtv~85YTNK-8O} zzP|Tzf>4Ot7jM;~Bmg`O@6owR?^raau|PlFh3(RsTb|A3%qXACX|K%919$Mwbq}84 z*ugFK;f1lm860gL$Q&i8Va#Fe1bgs9M|~tp;brwHzPl3pCQ09uw$xyLz+ot9)-{df zT(ea zEJp)&Gr!ugL_)&c@Y`Jg4LRoHsnq~S&oXo-l_ZoC9F!Lm%nyIZK!b7@0BJ8bp0pMe zLJ~WncJapa%4tM4xsdxdu9cV1>??2ManE#lwf2kq`t~CMvD31fwDZ(y^#oKt&W-mN z@qtRnnkr&_Dt<1ste{M!@YN~7YjCs_U8mXDCYqDMlk>W@wrW75@}rdcP%QU#)@Cz>2Fzeneh1Y* zWWGrp%XyltJP(bPt0PmpEH(wdiy%aMYJIMIa0K@>=G5Nc>6yw>utwipRTVuMF!?N5 zMNAlX5t&Fc`c}UPLg}d`N!Z%9-tB53tFZ0DDE*dk{R=~$j$0o1#=l*woFGw6Ij}=N zG=w8qchwpa>vGO(__k3e=$R)xnDU)t6@&1h&h5`ljmLRcozGOV)+urOTW(9O5pxnR z`h*6Seli&!&1h!*6Sw!2D5%n|#;dg1%vB({@#cSS0vmbd8-HG~=0LYjj%p86d0t>) z!r@7F5Zy^H+r$WHR%1$i5r8>3ekf99>{&9WB^z|Evz5ijRxI^<+I85`a^D^#wMbH( zCP^pmjOEHo7%-7nUD|+cGm`_H-6!wnVg6n!YbP{B2pDPB)Mxf>3Fg>dzd|;la3n#` zzrW-Yg%ol;VK_Sb(3}%%wUxH03mbEgo9$U~tkonl`TmBh)?r%j;Ys0lS5|Y{Y?=ZC zk17tnZ5-srF^Fx_`o~#HU;mW?)utY4H@v5PrVfm_b-gB&Uo|#EyISonHr2YFeSS}E zQmNhYdu7@smoOE}SPs$X`H+g}nJ@b;%r((bkNLr`?RdY0HNt@#eZOLUUllE}ohrJ) zQJ{RdTZ-gg_oVF-hf8t*;o{#o2SJzaljv&@K9D>77vZit+PWjY^%9iX;j@t1v@ZERqZb{bxNQ8zQ{a zTXKqMYFWW))(?%F+L6x!KQ^khRM?x06wHBss~UT}-`Et4>JJ&;4LmiFji@o#lYtVm zKWGp1Vv5)1x@6f7rcWOEx-@=F_a1OJKO+X;qdZ_yw3$FL#@_^Pb8%vO;AUYqzRF0{ zwY_S3VRZB^jQS)7WMf)=*G;6Xf*U<>=Lw;#rvCLH}BnOdg2%J0h9 z!5rYR7oEB!`rTLV*COtTtzQ_AdV~exV<#7Zq-eom#}B=ylEmHQUy=l`|jj zKGDJ3r82YkQq4cQR`yLHEP8cZD!&y4& z#J!^p9>|t_51jxaJ%m!!4?0uy^N`(w1KXO#ZZ1=ybpv`xU_vruo6Cb$C^1_iplRBs zY*}qiy_0MnwN@Ei_`xQn1m5Bjg#zfm*ge7txa-L~`WIsNuD907|Ga$}8a!(Jy-G`s zBd1(z^Xjg;vu!>Kp7EvQRSLlGVc!u$Z!8r5K3X;!9H`)%H66H_N=-rOnOUN)gcfPdg>h`F#yD4kO~X5~!paeOn^ znq?`^T$7Nr-@A?x7Aj_&WuQc0uVLVSfw&R6ey&8Nx1s^(%u5>V7LR^|~#P+-&mFg`OZ1d;`bmK7)rEc0O z{q9PwT3xhwzQ=qJLZ^}j#~t&dl)c&F{6Bf@a_YI>XR#u7S_t>!tDNaHx;b|Z6zKS! zL^ecec+U$8k=l}fqM-szO=tJG#gMIQn@BUl@Yjv*dx>3xrC80+7@Qo+`mXdedRyCU z6c;{Tw!QrH3CM~$rVn?^AYqhoEn6#NJqoQFqPKds(mXPE&o+eK<_!n1(}$TM02Ljb zH^b;{Oxyu<{M)%IjA9-0%+S;+sJu_9BLyIMr|9n!FOwJ1NUU=g#4ZB1tA`DX)bA$i|ekq4h>xcvZhlW z%1Dq9!9rxT|0zeWafgh6oNrufM(NGO1}=24Twd7k%J(`j*cwQJcZaxUbq}86+i)tV zd?Mk^8d7G1eiQwxxb7CL#vvinTjo95KXz(I?W6iM@lCw3r-Gr~!E=ZgSia(J zxkp3ZcXC!$b%Ounokj2eP*B$Ckk{Entjy3uvU^S~-u*hfRifaYNqpa(3{*77sM?;~ zn}5?bzGLaPA|CLos_H(g;GJQ5RyU7=^-d}%+D9Md`e~vw9!l#h{&J{3vn05H-==tJ zxx89SPW2*MRFW<}yy7NnT-ds7*Ye>{D1un55(SOI3{BpLP|NG@a@DWt$#kBj8!V2t z=C<&h@g(oy!i2`_HuTo)<{51PH980wUT+_MYxryIP$+aXV>dqdbs(tfZaj!}7%MZU zLkPJYjURgJO_cd~m-(9{6=U_HrTo(-^GvtA*P5ONFi>1CdT8EP%U5nF&-|71f!@l^ zJiI76S+Xij`e@e6p3l|ho}b015DYvHm7Q~=gQxItsh4pAQe)4O0B~q=h9X2fbaH>9 zKfNEe$&Wgipu)%1En;(^`#AqzTj1%vA9#vsN_;yyTaelvhvmT((P{Dadbt$(1O@pb z8M4*7hQB^k4a=$DHo+ULn>USV0mSFCpL|owr^GP6tRwXd<-iN8eayQC|H9BGNfbcW zQo&M*9wRTaLAmdBOZw@f{_9**bk=8-4-d+RZKa{F@is^j8EqSiX74Y(Y689Nqi*~( z|76Xm7D0WP>@#*b7Vqqsu`#fDo9UJDGRa!bAd$QEttqR%I<$nbU1S{ScoqhHTU%p-m(iqzKYwBD?@2wDAiwnM8wxYsKZsNx~ibOPRbB$0TU(h ziXA-x++1Mzvi#rL=(81mS13M16|of=<_=OamR9=LUo=>g!s^UD$D&`vl}o7?A&-yz zwlX*eVvs`5>Ji@Xk#!%o5QP58tzkcNPf9S zYIOngt`DDq1EqOM(IPCwz(gNbb1FkZdBEj`B7JPKi*^z~6vnr#uDS&vqi6{rgD507 zMWH>M8OPG>T+3yg$}Hr2+g#zmg>)bf%`tgrNmT$ZIdFa-7E|k@^A2osC70;uc|bcc z&}a1g&sOriCatnoTbbVO!_vymi@r%{rh>}Lx$#5U9zEe)iJm|tz7v{E2yVaH9I*8I z4ESpSX-Yfq8A=F z5-6PR1I=5Qiy-cIh&bPZk-%gzJ4PQ z&%b!NffJNk9XEBlwqrkZsYCDbv7_PiGiIX3<^Gr3F8uEP;By-6VK1L&Zct&unJE%I z5jr{Mm+8P|FO znlRn&rzNcN7h*}T=3-!YX|6&WM!)%fd9?F){MV<7nn*C~2HVIy!$=&w&ZuQ2C{{oUA zQ~5y&Q?(h1BS-oJR^5C4=)01iGx9G1brNgp+JQP-zIjvj9&Y>cY4N4um5!?TZB@M! zVk1j@6Zw0w%5gioB&*a*YCXLo-)A51kDZK;3DucY8`HfwWez^;^{h~DscYYJCICfU z9*|Uham%*;s!NY-Th8DxY8f?%AHq8N5>TLCno2I$n@CF|VM4XIP9rnDlB`;f_q%*76(ZjJ?;)8FO4j6P{)O1lDwB?Qp~ zfcaBaeWJt!U}wIU&avC5)fC0_an_#;8z2rf%eM;ENZtxZT(kdq*9M0Y0P{wHU61G$I1#H z-KfhICUeS~PI@RcuAOw{eLGi;XuY3_c@E1E3Y^?u%;4AGAq2hbb~dVCaKBSm-q&S@ zguU_h%RJ?eR8E0?1U)dNb<*Cny_nxLFVM`!R(dhj&z6DXi| zP@`0h&AtrYD(PO+^}L{dZz{DiDN!37a`#GHa?BMqro61Rq&2G_dGk2hOz=$%YQr(1 z219xg_q+-6lUyk$OK-JYXvLX&;V--wGvsVs3bXjk$bg#1+FFwi|I)OLMza=;sVM6k z&7e>+<;|rRtYjga9qs7Rw>JzFAYZSkh93EEv!ZheS(+bYMD6TqKZLBShEr7^)1`Lo z$-1}Gb8sC^5w=e$!jIb-98GBLu z(&)+Q{IjYECkjKSaN-+#AeGdrTGewTY0PIElyw@hvQG0o5HioO+>`V>+{J;;IP^}l zN4xvB17s-9*z(1LgY@F*iDVkhew(tEf6Lk5G@B^ctwuQ8;WS%JiM|oyL8)O|CQm+y)+~_ zKZPW(+(J%`_E>O1>2H_L(FuvRgH*(tj6uwm)Ie_V!Fo4*GpI<^@VA_`Is7lIsiU!` z6lcv$eVR-BV!g*VMc>b#7J)r&7fpggbX!t`cZ1^>a}4)hrDNh_COvAOLZ0pt*MWk- zEL&Pz=Ue1e%?;j8(=Nm*GN@g&h;`6y6XJ({qf5jQ+2|GAy)KG(|=5kaS z*luG+kL+h|O|(ROqDD=7+cWXMvb)GwZy6=fwOjn}4S=Lo~kR<9wN^XLN}lv|KLm`9?3r z@)t6-KA-Q>;4I9)*jNo|=1>0rK{JPZ;vt{GFbyksuNrIkuoGztBy{-o>o=0QR8^;( z8I=8ZSXM{FGDA!+?a_UXt1bo8A6)VapcsEqk@FIk8cLLMAA7ab{d$-cVDnzXD2S}r zaa{qYABDi2(;;x#Ze6O9%@L@Tz3{&e?Mil3b?Cab$)m6FQ;;mj|2}|)zWlTzR>>-V zc{p^+$KmYdCYhe_rB8HAf;lbE=-F9brR^kny$@;~GVj9L%jH|$ScvtPv0mh6boJZ+{a#&`epHPnxN%>EhK5WmX zE8QTMY&Qy?Kx1mwC!2|vaKgs2ZYii}VwwAhG|jH*{Rg`?G1%oZI@a`={}esmFp;)_ zmi~PB&02ah{h3zK6^b)r9Z*KwR%x!-vfUZ2LHjcFH3#Q&cqeG z*MCH|Oh9NujADLe(A(Gh_WCI1w}p_c;6$hB1#^$hKrxSx(Jo^B9qIC6w;dupZqwz~ z|2Ca)qtLPp&x1xwh*a|c`mSqAJL;rX)Ka2HXVd+H5JX)~6RlMinHvAgpDsx@j_Y=} z+9tFNRYTAtHWl=I^Jkzzc6*_C>^|@Z#Uqc<2V}kSVE&bhc4KGipz*P_NacyN{1xzY9*lN6ZOO)(0oxgyrWz`aJa#+S!os z8wWy4peq$)i>?vP^-tRP$J=`}6&0LWMFZjbr|fGP^jb1wUt}jMI!a=$_1gOFvDA`n zeZkM`&K4R-*tdEBh^o;*bf4&hFKcM3V=$xYWVFM!y4&$>p^HsVXnw|yDl9>FN}uf( zDRHPD=e6nI)oZGm-}p@Xs67PNd~p)hwSE%KPd5E)E+Y#wk<(iy+CdB}Xx>Q4Pf7K( z82qQ;87+AFp(R9R1J*%Ii3gEiv7{1fb6!Hbp6SSXi}0poqj;NX5Gt${;wgg=w2db6 zhCk=`O~uW$`elRFH}!%Z2NeBew8CNM?lw#|RzP1~@41+CdfBYu7#8pzPm$_7w54`O zWZ1beI50ge_a_UU=B$Rz&81D4!{x~@}-$a&Vx2iOEjhdI-gEryuO3Q6N}Od8|%L+4y_v!Xe{-oa#2ZnOWZH z3iHddj3huk-M^K(=Fclip@U7`D85heV<;lE$bbG+kf2?x$wBibZX)!Ez|i9(aP3w6 zt@*exPTfAnX`OJ-9_{P?HMFnecI62U>o!S(b^mCv?Xxqg5BC^vqnl%+?MN{~_H+L9 z$WDfXV&q~iERE~JVhQ=tNX>&~xhWyMN24NB2mK7nz-dYR9<%fBNGfWVJY%k=UHS zG#`w6^+2I;Lak15aT6_iQMwT#lc5lHB_ihx+x)Bg%Y42@U!Taxk*N9>?ipr4F(_&v zrxU5x2TZkuK#heC9-$ZX2djEJLVZ?5**9I$^}fnwGcwjVFpW^1;>}}Y5X8Ks!G_Gv z+ga4QeA;o~)W{?$-f34EU0M)isQetjFz^!Qilu@fHh1KtKVa);GWqu_jf@NdIU^j!os`Q2QI89Ty zVUPFeh2L9R7RKs>0dc>If}@JvY_Y*lhLR31gRYF^Z%#zItr{_3!-9Q8fI68`wF_&> z5ZnaqSEiflA2QB zX-P?z(}RG)64aFPIG)R~e3G_w+3XNVRp}fPZIwuCq^h>)hfXEl|5lVYl0ca}IM}YV zvIk=++*xSav>m(OkM@5L*e=!L4$=K`%bkCk>@T8H9BrcX!O>RWFDM8pOgPRk1^Cw+ z8^=(Q9>3ckwSzhfVA0ou_2{VG7Jrd>MMVP2h^_rwkd!vGY+_MuS=f|w=GgLdlwdKd ztPn+%_t1b!1j8MPw;>sEd&~_pb9c#BUsPN<|2LwyhoU}c>_QSjsGSS8iD0MPed3=V^@FyH?ToKgX8JJuRLkG<;bS>Nv z!ElLU4crv=z)l$J^Kk`IN!=Xj*7q9H?T&0z+zfZ>)L(OiU=)-%iobU9wQK@JqUmGN z1^$Hz=`#qDF$fZ)BFrR6>w3{u;tdI--Ldyw`ucjU`#SE8Uhe)}vdzjI#W{ta@7oDL zD{o?5Eu_6%6$Yy^Xu5Z9CO6F?frvA}a>V3&;G^wZi)p(X&zk4doer^|b9^qCRVSYa z)J;)z(gA08TYGB$URT|^wmneHHrh{BQE;tp%MOV?;bs&ulpG_Yp`a5jS)_TqQ@B8O zpQbibr%>QPxT>_UlH%n;(!AgQ)b5mL%9c~8bkn*Xaz#8p_sj?7yC0H+$`55Rn-(?+ zNHBTwylY|=^d(5&{vnG|SbS^FW_G91&;~!aiK@*Y$)df~JfSaT#m3?%UV;D)PeFjBQr6lY5fn_Ui{) zibq(cYzxj1{(SlE`o0S^Ianv-*|WE$UncEJrF?0KWb(?a&~+p0&7@aL zFs1U3bnx&Hr{>pUbeoZw6r*O9@d209uAb-HS9z8xbsaZLcU$jZuKoN;-8C5-@3l== z;Ih=T@UpZw@r8y9oQtjdT4jWXc8mBN3u=2ILToZ#A;BcZIj%}DF)t#2`{xLg1o2ck zSMA%+wBK}-UP9meX63*7Ir7_MPNhg0dfGO0-2BG3`!5^DBO+CLDmP|S9cN3@4=$^& zyrtK^S>d~&L}xNT=-e(r{JZ&*NE7dxCTJ18PV-7!T>)G6tp#py;LaRE#sy}dj_ z8>B)LKN+QI*!VZ%r#!|9#knw`VThba10(-ygFEqDm20r!E!yriBeUOC* zgUu%RHjPZP2vh#r$A?54PkdDx(v#&&c^2D}YCLLL0{Z*rvU7Hc&sF|dSIe-}s^iaR z)+yy7P6~CbKQw(A1FKl;VNUymIKS_B4BtunP4@bHdb6MnbTN~E!t*Z~nv`qI%go*1 zZ}@_SP5!^W9;wbMjcMr|Pmg@P{JGbj=O)YI6a4@Ti+{sL6SU`QCJ_oum^jods>voy z4}aShAB&3-+E%6b@asc~^6qXqyeT>vBgrW(Hm~cKi{AwibeT~Ezg~$ThSw8a1=|kd zWD^3bqV{Vn{$T{A@g0?PgTMIL0(URA$3TT1EjIhb&m&~X3YT9#9Sh1Y3d{a{S$uMN!kY`#O$aZtbrQc+ z9rWm&&>6b689kebpj|yosy17thm-JOi5m+&ElNM6pgji=u@0Mj(MRTuXQ^75 zE*pwOe4llFY~Pjy5^=U|^Fc~$USyMA8#0eO7GEkYD0LoOexg0&&84)8E+!R8!eX~)c?}!VyProY;t1oQ9dKf z+?%_Kin+hfmNdimDwtt=7ADaH^md<;M1k#*V5&{;y;$;3xUQ|{NqM%=ReMEaev=PP2MC0~K-K{fI80%6pzhBzwOpWjj5|YPgUwGE4hS791N} z4VAOmq6_WLRyi?$9Z;qTRXww1?y9;s z(3Iqk%5`>$Zn|Q2Z-(DB*{+oymbab{z$tY%sJv>Tkp^UseFSrVq0@4|44!5ZrOxLF z_c?m4@gPw@B`2R^Z3`XsENi@LH<9wpaPKy&9V;5aq)r|k%Ahf#LI3o8nZ^ru%#H_s zcOI+vPf%4Z9#AptXyc^Rp7Wt!I;EY}o~hX}UuHeMRrRwYxj^Ka_$1!$T6gT{%k4!p zRLcWYYYgC*sjsnpOz+5pvqj)QiUZhZG}|G#Mn*;VVIUV5WPSUYdy1bQ}&#vJ?o|E;VUA?=qix!_Dczprrb1j%=P)q)b+if>b027l^B zhMW0(8kU|LITSoV5M)AAb?Y9L#{-E|-Yb}Ot#iDw$#+VUOHaCZx+69s`zN2*E<#MQ zlgE03xG^ydL1Nf$n4(87hQpjSTgFZ7Q@5qmt#K~yZ$T#MzWx8|#4>%9q^N>i38^>MePMQeuXrKISy;m1^J|Bpj8Eg8W44K^TO$_9D4Xa< znOtq@q;oD$6(F?m9c)@Ej&0*-@Gdhw;yQEtX=}5deewNoxvr;PM+4l%;eFRZ_8F!c6_QF)TpCjUJ=@+nu z?WiPS;L!D|b6?1owvj&N_#XdH#{-i+1HXk;!(4}&?vC{9h&x(|uxFp9#f#&3yjbC3 zgb+QIns1J&#MnF#(TM`7_4MHna{NZ`dEdSX1QperCTL$eD8yaZp`ny`_YfN49r7VQibkSglq^*r6<@AvPZ zK647{w>4u>pBoH<-`J-AXc7GmYq*e(9ZB1^VG8P-O2L`+7|eb%K6ur^46GHuS8JWe zOw#_IlU(-)Lloc+fWM(9BH}kJ67#% z8J4jxcXfD%<#?}M#$w)a$O=MIWa-{Q^A2w~!v_l0tU@xzWX=!?fVlFiKrGl$0-5uY zZ``pw)8ee@AyQ5MWFyrj$v^MtPbZQMO8|^Ob$d*l$C_xdS}bF%=9|8X!TaxrNY^yq z?iV#oZ&m#|ScsPqo9!!LL)(nkw{*&f^pCMNnT2($fSI`oW~TGzJDDz@q&HE~$OGFO z+28{Lz8x3v{6U0-zFmtjFVk&5Qs9n=V@BAV9V#Z?V?NHe!#3L+K3o0s8#k>xA@1I} zWgk7>KP%%_sh4>eai)5)&!e%r`V1=&KV1%4NHN{QO-#WA^`7=+w^aGkI=(}s?Ve)4 z(1&o%BFI=@hz-6@FNT7vOnHdT1N@ss7S!+S^Y^cG+h4)vxV-uUxSWS-km2U?uyE6+ zDYI7&Al1;~!;k_xiu-B<&XP>_Oca;73+X{WHy#OO-@Qko^wN?!Ip|aNU`r*iG4cJF zs)CJ75Znn0sern8XtUvy|+s?5mNiD5PNv#I53s-P=(W_+2U0jCE+iMHc zx@AbdI7Lry%EX|L?xX)R`_x64oKQgYW06V)OS<=1LG00KF&grBsfEB`_cS^y%$xiS zSDI&99g&=$Jmn+VRbM|iGdkxtP6;nNF1)Le@K#hG6{i>8MTns(|A#gT8rq!j;R+9Z zjG@D^d9;h_{rb(deeWqYOPW^KTHNakSLg2^M-f`5*zi3M1U~+G(z&;WFE%u_^&*}IT?G$Po5g-eXSRxRCLlC4DbH{N;7Eb8jzx(3&%0h z+PpWefH38V5NuP0RJ~KdzQ@nh$1X$%4e^7p(_Bpolf? zN~!bRzHl;*`3`K9Aa{BYApBAQb?wtPjL?H_vy)#QBuE~*ke$~%%ZMUW(!IYgIQjmz zt1X)wfxm8jv=|(jnP;(`ld?lyV5nz~W=15LdiN97Jh%t79sxvH!HP5tAiC|SL(;WO zZ)`qT?xbmsZhpnS7V+R|pYiR1-u*-W7V=TnpTYBv7J-~o%2Bw{kq&;hF<)<*?3wp! z!EM`B`==P|{pD&puboAuR9WcIGOx1IUkkEneou|o6RQA~w-Ywqb&v|pPGIGOC|Vy6 zLLE(zlUlQ&nLZEYw|@yp@jY+(&zNji!ghE5pWCjYA*4FWxJ3l$cFX!R*Kl&dz#QQ& z-_Pln-duj_SGP|28sN^3>G+0A()-_H(_O01@Q6&qAg2!t8kn*FsXMsca>sP$Mmx67BmoZ8P&b zulF>0zg^$o=iVDWpa1T|=kfUTn)5p6d7kHa&UwAdCZkk-!NARz;8oYfI8y3nibL?$2}ab6abv6YzK1Ferr9b)UFG8sOf#_0<@ zJn0)T^CIGde=1MfkC(1gCU#MQq`wtHEfbJw6|Fkp2m0>^K@$Wrpq{sR!Gj4J-$noL z{6ul&Nr9(a*W>H)@*(z9N%zJPe&XzZ`4f{6cR$E=dxNhLoC?OlpEYxs7fz^nq@1do zX{+A-&>t8MFc|tuS_q#|scUCi3Z#w76S~=Mvtm6U16-6;d!MhvI_AWw%XO1`-&=GS z#6zPdPV-nS0A`22qWN!nAl{T8h!f$?GJ;>3)VsaKE4J{OU zZ0l=*bt+~->k%3~SnCmk1FS;+F7Nyf2!+D$+xp@h;r_@IyUZadXTb$h<}Y()h@zC{ zuv){-TGnrAhQ(&+$UHyu`tN4c4sI?bLK3KbW-Fm)T!fr-a>@i*ypyI$DfAimzu#r| zDZn_RxIRK2OKk~#pf!{-jz1O6kVXA8F!JAIps2s~P2XfEq|<#t=homomOQx{ipyC= z0`Iz8qJja13eAqn?#y`7)_A$0~35XjI9 z{%AJmOemqrrJc%VS{@YKP(|+Bc{sus`>9k5#PAspuf#WLSIN1v#;1ftr^SPAItp}C zg!ruiCb9FX{!fMWJ3n|mT(R7QPfB>)?Mp~wp*-_W=u!@)E4D~m7At7jpAZL*Fqvo0 zjLfkRMMAoPlX>nGbI9cjkT-v(;WH-9^8!Bu_V`Lx&1M8^~>`Tx5$=G2qh||0dxdbF;c`l9}AkL z;d`kygbMZ&FmnHm3MwnPWx1xhjH{@QWnC-=VjdOjm+Tn7GQ%R-qge@B3`*d7ay-|& z!d1JWBp(7*<&7G>5E1i{MA!R{{?)YvGEmd(z8QGK2akUVC5S=HkN))-RL4YT5!!h& z=+~!5uii|gk*VAiv7sg|t5(RJ$S!QrW|+ETssBFt-xbu~0X9_I?wHec9#5_`M*a?o zX@0}f>PKVH-#sD*$W|`%t+tc=3$kMZtVsVR=3ynx^Py4%-xi`f^+ zt*B4m%^=KHgajn=GL#rGL)n7cEzOO;H347CcTK1k=1!die}DNVF-xmttvFu^uHZIx27egJucjk9z#2kMrJQSU2S4j#s}f~rQKr*EJhd-VHEe383A__>J`$KOZJeR2)er8&CAz}WlYCE=WG(8Cx@(2; z{B}RW98C5_m~-v#wOO5V5h!mANo;0--7q^o4)z^ z$ojcGG79*713lWdrsDhVRteAMo~-|E`|icjeC2)kfxpqOJF-MznC>|p0*IW22)B9W z@ye6`BjM-T{OR;%$Vo<&SYvgIMCI0kGE>ma!Yo5uq9p6&Z1~0TMQ9Bp;e9~b!9ex9 zl<7qF+>^B4HeuaS1g&mnb0GZnu5DCFJaZD5h~j&E!_oDWtFg8@{%c-04fgN<71^4k z;Cfly^n2rQ*IP53(;e?s?QzUOJ$aHW)&6}|PRr5F=ZCI1AtXx`nr9H#)Lm#E@?Hj~ zjNUx_f2lln98Aq}{F5L#bZvwz-gj5ol29Xm0g-1I?P`U6j|~%QW9OBX^)@;h7$^2G z?NCgW1c@o(4{b3}f-U-$;K-CW91503zu)@%iv-e~f^M2=p7jcU(<7ZaU_r2u`~~WN z6VtxVd%1oU<%mSpikkL`Zb>m^w#72HL>l81Jo)1PQ;{vfM3CN7L=i*-UGf6kN`l&B z4z$g=D^Qe~m(dG_`E-P4N$3v)Ictxq>Xz+BLmc<{?M^I)JI-`+FIyrZBp{X+m|nbt z$eaGcTbx)h1e4b5sG)rthhbSGx`4E)vewI|gm|!kC;kx%P-2a^8&I>F-MMXMtR#?kd5}qpatl+pRUE!Y6snb~P$El95hVn<>lC^v({+Et*+7wA2VFWK5*GX6FI(>|m8-B4A}3~gDi z{U3y|vJNC!^e`_?#??&C$A+-sufND}k>x}-)x>uHAn)tx<9UE7!2_0Vhf9!%^C8^K zav<%-=Y`GsbeVa^Z9m8Z|B7+ZivZ&a*jAeO46Zt=9$0&-cUMe$YKM~J@*jma0rqIp z$k4!*pwp~F&91A<2*qPsIhcR#FSvZvWVK_uUcl*9HanfN;jdr3_=An#VaqGo;s}zy zA)13(H(!R(8S3k~&g>EJzW)OAzw<4Ot_t5i2Y_3kt`=p%Ik$nvDPFAG#-p%6xbo-9jc5-yw;uUMXVaU*i(yfbXUtt*VsE)y~)ns;0l;X zZ+e6~%upo23rDTa}rvC)}%N&Zy@pJjT)b<)Gp2>B6S86C`+TEtzCi3rpj zj+=-%q^tk`97iRhl*!Dqg#16+DH4+5)Zm|Rf;uB!Oq?OaMA`3f7dPjs>JPALAYdZ^ z5Ubt_=^v4(kVc@qsQIUX;`iF`$!=+H!5K$0e!>ajsJwu1AqE60?xu%-{)QK{vAP9! zrHhi^cg3g72YFBL|H?##5 zLl~_GSpi7tX1_I1YS~UH2;_-d|BxxgS&b|+;PyS+RDll;fnoj&AzOtU^BnV)kP8e` zGnDT$SoY9)5}TA=dA_RI+%b21L#MhdCqa_pvC>5ZR~h7fvg@x*22C5P5N&8cVZ*w8)D`^{3I?^3M^SN*wzRrGdU?2YLR%Dy%U-(}cCj zE&eu<#Q&8-Re&cfExkD%2iZ2dPJswAqkj0Gm!H_N zW}Dd7!hRMxk*0@*M8MAq3B#M{D-l8$Ne*l(Cb z1}}$BCg#xbC?@V??D!5S{O}X}WvE|H9ZH(2LQgy>c#Ok9p}gqHOUPi_x_VboOiu23 zBtp~6tFTnm>(3hj&oXry?E6@?_LyFUS~0bht#5L$DX&%U8ofl!*ARJ(nFB85S6wMoiDcuKfL!SK@#fQ_C@W7!5@P&s%#RVA9Vw~lHzhDx`@@)#9(FfTW|Ta zTetjrt)L-s>h8xyvZZIk2@MIIB?8{kgo;)X^%Zkh%$2|e16kr|dofq(wAIpM9H(oH zDFvSam8oZd(vl0>yF`Tx`pfI8qpe!K;#_)G)9YJ5O;`91AUO$7iWyDnJSZsE_JSP! zB>D|YZ-EteJxY)2K|d%x7GsehnM-Jlgaa&TN`Jz^vr1VH+=H{#8)>G1SL9rMXK+Nj z@jnF#Di98pTpEMB1c#ext;JmS(>Q1MZlTaai(5nxslV7Y_&A8bRxOsEAh3h2P~zS? zIG!;3(g<4Ogoay2DMJ_PswV%2!eI6faKpcfYiQ)X*2)z}Vap`2VL+ERLMtm3Zas*5 zZU%%+UFy>hz`;6<8%(Uib4I6oaDoThpX2A(RJ!2yJ$}LMpM<6$>7(m-{N>-n%7~>! zt1=t}H6LBG8H>`upALg3CUMx5y!Ubf4DExgT#@60DzyXc*-JANiSu5-l^x& z-XjpC-2$L1q@6F&?+tnU*mcW|hXQQFxfpf|i0P z`ti{pSS7zB%>|VYcYhE*a=8UeD64|Y@gX8G%nB|lM)lcfJXKig)a1gwc){wR#f%`J z;HBE*v2^w4(cTcq*H;48V-+6g;aJIc#n?irzo|CZ9z+c4x;V}##mTWJ)BZGU8gjDy zpv#mMThLu))OAko^}q3=lpBu9PT0c#5oPC#jwTw%dGixO_84&p_0_MOA#C<7bxLJ_ z$(kiMf1A+aDO#BKxbwV6gy=mV)~lYt{K&*dt}Cp6&|~YHFRM=q_x>BU+kP8C4*SGgH~vTV*m9}O|(ywrytInU)^fT8&1Q9FK#St!4&klo(8Kyy(3g$nU7&B z^Z0)}kV`>@mZw!q64HnXwGx`XwLL1fjcDo-|BkhtDqK5OjEfXglx5bS}U4g9% ztiLxQQ)2F`0+VG+-KCxNN2 zkJ2M8)gsW7YQUa1W^V}du?!H}L~po^d$KC?fJ4C1z(~wWlQ1id^^Q`7BZaAQ7@Als z>WT8Ma9-*_6Vm;%%BfRJqM<8f+CR$mVB|z>mP&he_uRGLEcALyAojkHkT$K_iy>e0jfp04`94_0OiKONqQmEwg@x@(a<*4l;* zF$5cu7c+SOwf|FDNIw%?FykH zO(3O-6Gl}c(o#8JHo7Q)qnF0GQpSB*Ut2*F-A(U4_9U5~tS3QrZC4vv$Y9bR|2}N@rgE!GN zWFq{~Hay7+nzu2Hri~+NY1jsan6AsH@eJO%$eWw*`JR%`_szGtu~NJOs%S$2m+trs zeH^-O9MG#K%Dug@b~u)V&6PS(G^?41<5pBSJA1zFihRC10K z6;hIb5KO}7-!474N{7aH<1e@v)El0{h2^JK_SW09ct)wKFiL>&6RaIEk6*wOpH!Cn zV$@*5kD&%N$YzAG4u>dYGgfizF`Uh?Y1A6w$vqr;XTO_W?~5=1)|0$gA}SLa&eEQk z#ngX{#q1Eg&&1hHkRb+L(d6$-B^iG~OjNxhEx*KAkLj^-%iyiF&1|NQnRPLbe-v zKuNZ9&>xD~$bQr3og}8bY<`=qpNG2p>XpzO! zR$cGn%DTa3>1mcQZI;=B!}DfaK=`g?^Bm~iXG|)9w*UlE&|3fl)8<_r=Cs6Fp@LE{ z0vgLR9oaz!D<7hu7xH5nU^*gO#|VIN4LN_Eee5or^GBg)xO!denzv7nm0yoAmKN#2 zr6Gn)PJ;eKZc45Nr{TVF?(ItJx)A_lvj;=gyNd(3hR^UWrc&mNZgUm+Mi6cpzz{vw zHT#Zu@&_0a?vKey$!!`ClYRFipc1Vwb2t(41Nrh#8zClJY%wT|W|68kr%oahbyY!9mlV~&fHNM1g- zu+u1Zv!elL$2OzJU^1>k-9nXE@ouwIg37ywrA7=QfLw_gg!1G!}@KFhq>#I$b_# zZyp_AK~LOW3uF4%>>r#uzbGRtymtO&hby6WS>fp=n`w_-J}a+;4@h)JbG|f9c{&_- z0D%#GlEXNkNonS-!6p;?Plf&OGn`5@xI@;noA+9ns%elN=9|=BEYI2PmUx4j%~0r+ z5tB;|)?$CS63shLjK>9qxU=Eb{+r6nqTWxdqd(0ZcJ@(FQqAjz?ds?04@<60R@0N; zqNTO|{O22M8M@lCl}CE=l;*JB`t+HOaUr=*n+onjYYbiyuc`!N8pqVNms)(0)6x=~>uEkg z3(6Jmq#AV=JXL7ix=31d$kJVUJkQ}BtIGkIsn1%?1^=%$<6ic4aK*iP%3thdcn2$Y zZGD&Dw0T9kY4*ovpij|Hc2F;ip#?;o&Pc&0)?7hsr?OIxnCR-lEF+oSS}>l(xZQ75<)J zV1ZQD#*`K#+@1%wl58+8igRhNR&f3Z<*T9HA+|lMKlJHz+^x+}>T;z9o3Q1>YBT)( z!vco#&!skqbB*}+T(Rg}u}rCtgww9NB}$5MiJ;t7ix}@Pf1AB`W#)tvOBh$e;~!YK z8g$5rwf!(x_n9U{nl^U{-h~{N3kZ=MI(vf@@c*ia9P3l9@B(eKO>Sjt&im4QLzG@# zzhAqN;bGrAot=HL=K6XqN@x3aLwilLP`j!HAJ)I{!+b30=usUr*AD%1;~{H`-+gSa zvbChJ1Xh?W?;M&&BcWM_$h*+***NA)eR;zK;Py|jOM4<9@k|1!UkME{` z4Fb|I@nM}bcIx_L9WIk1WP{c<-(LHg@;XoabJh<29ag?*&k6*@vRe?N6pma9iiJ;G zB5&9Fg>08gh>%UUi*A;2x_!9jh@E9pJ`7?nX6+k3QO8|Fi?MBXx8$~tYg&LYoa4fo zj>jdr^Un??tvfdw4@?275QqW2M{364|Mhh$hiR19v*rTBce_N_);pB}l_tWi`|sIp z@2C)WSVw8w+w)}`!$XNa>4P|9uuw{y^lTPM;yE5jopR@-37pJzh(1pES3##z18!4` z9(&dc)6HSXyV}&-9tw8SZVd&W*B^Dr!*r}xlj88+&;$*1qhXVT z8cp5qmoDm4Gd!sK_(o~Tk`7qS$Wq$*#m>>d-da-=$$XjJzqoFHf;yRf?;YdN{SjIk(zaUoBNJ z93bNQkmA5WBiDL_Tq}vlrHGI#*?QCZ?;sb0LEe7v{Z&Bt39{T}>h_nUj364xtTLG% zpQ(9L9^usbnxM4KPz>G&lX>VU9H$e*Q5=P1sX~whJ{6vEqzX zBO$d?8lONajK1WNi;m@9n%jE*=83?mdBtp6ogjP;&ZQ03SUXDO<_l{l^|L;SM z12~Dmw6rp2`EaDPp9f*`t|v4>Q_r!xyMC>m69aU3H^ za{Y~%T%1vIsZe@19G_gMY+x;Gxozud`^g3wI(3on1|VQ^;EXW-(d3F&Y)Ob<7Zs1aLI`^!G zL?iZ&B0gx&p86bdD##F=cGxr-udICq1W-;kI80di>ava(N2{U` z;8)f{NhWmDAn(Tn2lXP@aN9RFoQrJO+jvxnU_+;Zp`_)7+?N&yg2p}$FmYFIToc+) zSHli-r6c%EXX3J$#X#=o8K`5V3vkyO;}rnCyCbFF+n)&-Ip(mcb>5BQAb;rhCC*#q zop9`Cc)0t7%oXRuj8DhB+f@7A`uP zXTIsF<0|=b*1O9r>dih;lB+4(dpSIQ2mf;I^W5$uHtZc?U2iO6Xr%#{YjVA>VC zC?QJ$EKS0^uF(o2>SqCa|spgNRwUHiR z+2PJs8=8G&6W~jOCs$;U{Q7QX)wq-6D~JIsft-((b94;R`Q8GJmF}P%yScN_II4mg z9A4<5Nq-UEAHmEUM_f^*nxRKGqU4ccZ)}GMPWqgBc94vA0dm2IL>Fuufn1O-BZ_yy zG7m0?Oxx1;@-3FwQcp*8XrCA;oR+`KxW_M?)ZU~$f^yT}L5W{s{>#euYTsYW@tw&1 zVoRqUA-bQTAgSJ$_4ZCcSZZrb87FZUC9(->x}s;x)ZGvGZRM8&VN_iS1kDklgR7ga zzRndONxUEwA_0g-QtBMbr{Kwe2dbL9c_({dz5Q3@-1#>GfT>&{Fcpdm&;e>r($fWa zIv_sm6*!$mcJINrx%mc#3Skv+sU`!Ldf}~`Ccj#_+3@T%)SN5t(i8`4yG*cMAhEOy zSc7a=wYz*0-gb@AT-Jt4$A{I%wbAu{`M-h?y!s3QyN#$z<<3L_+v0z8Br#y$gYDk_ zTH7sqh5YUt+aVH4sZc7PfVW*a9IoY;AMP(TdoQ9=Z02|&Vz@3v*&^7Mytv1wXOaE9 z6Ap2u3kQmKP3gy%`B>r_>*$TRic7nP;2_cDP9KyO#1c7y0;!^eD^@-ZZ#r6^Ft@AC z4GtGT=~>ip-72m$d<$P$$Y0mvt;L6vks=?if%rIRg?8Ij6tOOZh-D$3XP-(g!HWuI ztI~u>A39Pz#<5?qy5lg2tr>@JCt~DTIh3!2q!B;<~8}}}~4arNWhAceD)Ed`nNlFVPmKG_HzK$}j zon`RcBmr`Sge`OZIqDbAt5RDrgUI+z1EqzQ>yf*B;#qNsEQ!SKS?r2cgCkCX+SI=k z{Uui*M>KZpA0?zUK_?97lA9#frXHj1Z%THLey33Nf*2F)QB2s+lOs?)=d@}#p7*ak-ob!? zp`>-rL@+^|vzIF_N?^Tkl$4bxh|GcwYqZYiAXSAmCrl`L?LYrxH7Hl*V(SztuTX+W1Ft+QhUa4bqd zqPeFfb?Y|D{2ez%WYn3!LKpanH|f-cSd4=1m6BT9@wK)#0{|nx!%7&b0$vGysk3Bvma&iutp{`KiyexOE1!17Dod*m=31?|O{XGGE1S zNEUYn#13@+Y(E_oLYY@8aBvVf9`f!|BE}%1$FdPlz#7~AR#agD!W_&O9tE{*b{7OwtA#?tW=&6q^PrTo59^_>eN2#5Y@~pR zCSRv8h&;KO!mh~8g6O!-ay(tF(-{45MF#F}e}e4j?D!lij4XWYI$+%{{;reg`AQ?9wTyuA;;~2+_!3t7*lO!|X0<8Ts~b!eA5C{-{`ks&ix^8r>oxUm z?P6^=lUfDxrku}|iFxh&&aW(B*e#k-&>TSxHsTaK9Q^PP91>(c;vwyzYqcZy<^}v^ z+l)KMfd*Q2t?)4Ix>^x-pRso5@!EudFw;&6Eps&B!tCC944%UD4xXo)p9pQO!i2Lw zY&>FFC(0?3gq-po)#rAVnx}zs@qt^V7LnE{j*4MiRMgvC+JXJ*Aq2(LO?d7L9Swsi z3f3@&V`sLg^Ro_HO)w|gWbj=NH^=9|4>Jky69+X@%(WGafdlr_LvBTGvE$68M*R%d z#5@=Qx2*EjtL~`Tw(vI*YkpPdbGGHrPss$s@IRQH@}|y4Y*t}& z@{gZYh$&tVBFqH>=IlVFQ{4`Yk@)Q50wr-pmp8eOwRvnh+duc-!;2jQRC$7dKw%M>kZ9l|ONZr&SZj=nzUL z_)Aa5W6LE>ob>2^LSyC|mNa!|Z%W!h$rGjT_kp>mG8DRDZq+}!_$(WD@;0$g^aV*p z@_R=S>P`;|=QV}X=SXXwx?Bb82U?X=gXQhA{(w&Tlg%(HrZMBKkv5;QN**-SMUA2q ze?Hs#=d+QyouILFTaPBBH`1^rXc}vDxu*y|Y}chJbFSANp_D~X?+MEu@K1q$%=VXL zte^|mt@@DGdAD=v>noPq=M6L#!kOSYq>m7r4r>SQGr3wMQ+>;B|dOEoa2fho{OkmT{>YfV#O$QOHw#ybnfiz?rwjW=Fj zi#eyKA!5QlxFMBbuI^l=`5`G^z>aI*l(Jy;Zx|2RhmG zBJjDVi=WT_%9}{TwjefTa(ozmCU>S}vm(jxL77D6M{1f5dxyPgwxT0NgZ4tSw+=+; zo7;`h(K0I>a@1~sWHRv`xvHd3l&0gYi-?nv^q5{2A zX08PO#I=ycb`B$NZ0sDGQkzkvX;fL$3oV)6sT!Ey`6gTswuKtFnyp74O2Oo3`tXSU zQ+ZWhw}&(JI;g{t<$s=d*d+XyZmu^PG_|z#97_yRl>B8zDtneR2s$u4;==gChEyS0{RI)WrPM+$D8EL$Rudpd8v<94z*9@_v}!P%HQ#Vn zKi_ccAxvkMEcu-Ptf&oXqB#ODRlJ#Zsk_VIP7)(_7S^Sma;l(mrlKv zDn5W8sE_MN(P>KK&0&^4;A5@N`=~GeDX-3Qb6D`arq7#qUv6qrDz)9ZuPLMLp9=6SkJs{0;Ftp#cTPO^M`0Ws z4=|2+ytGSjytC(EQTZ#p%#_?JMDjK*@~C^V-qS>O<>B3aw1x8$U8vS z>|?25xg?(DrmCch^GoZAtan(^Rk%P&uscJ^MvyAG9>DvV3HoHR&csr zq_zJk$9=n!uG#l2oWW6G!o#=5t5vUCZfASz%2w+3pv9L3)cv^(Jtpj)eehNN7$AMO&a?XW-&Fv%Gp=vm1LWzQ)4Q9*_HfYqTia*9v8e4}{7r?+9 zR()Yi3DsT-K~*!k34##3&xa3o{sK-p%y2DX0PYshxRW`qBZvlc1rIzp;DJpYwS5}$ znM&irCg$xaazBAqUFCK&5DjECO3cy>7cZ0#fWfdQ-kO9pgAyiSBb(cgeT zt5R`>P#Ovkc_ly^?cG^n*L->3F1H+ol$Bh~Eysk}jWA;~`==x{0}T9RiQtEZ9DH|p z<5?AiFt@XyK<7d{dxyBg9NQZqLQ5DPLEHMta6|e}$r>r`X|qlqH6s9w0Mf#QMoz?& zfpa6T4kZQK6?=RE?2EUpHPm1ydzm$_V<<=Q$#8z5>Y`Q;v#u3&Ja#v@;qy|vu3RYi zlL$%)X~;&D&`z!X4VTaaBx1N-2IrC+GFqX&DOQ|3U&@-{aVDa_Cw~3xPojAAjx1ea+^L!_PF3Xm>R z2mGx}^XK~875|~6L`SDlU$Z?4nM{~qvQ;zNT2k-Y@(;CetA1lRd9+S{gi4L&+9m&l z9Ja*{RT54F09FKSJL$&nm5`vAb{ZxCt71X+{KM5YYyDh{T|^dB!dt8in-*mDvh$R_ zR`)8W(o)%V>fJ8KRC^zhvw+r_x8;}L>#oL-rP?ewBloVq5HEB7`K?^I_d!Dh-V1*9ZVNOlD;^X#Pkp*=ATL9dW&0OuM zCri3^YyswE&-7y!8~3>y^=)aEIV`nb8#F_&?2ah@ki{abaq{<9x>D*yl7S5P=XK;Gn?&5X?JUdnZ|qbMRq&#LW57)k%-dmDp#!uafD;xSS{IE~4etdSo zVBRkaV>?9;Y+Z2Tn&rj;H@I-j~*oz1NlEX`1r=Yr2IBokq|=Y-fuw zJNZjfO;0kDI%Upm=%ub;AA_%GKP=Jc)k-WZNs0(xc`VF#B1k2n(r~a5x4LV6@F_iw z3>KS+x7e*UGgp!fXMJO_V?Whm`N(3z1dCA-;`Y)lR}w7N6;ER~TwlmBQP4j;b-Ph; z4OW9a)J^GgKIP?TAdJe_<)J^J&M6J68mH3LvlC~#uFYrzX@z6U!?9me{kVytATmwm zJ`{_7R2M3p*N)X;MT>>!_snE??BCiC#3@yimDD1nkwAwEY{oRtoromMz0h1_|X%3SbQB+ zM000mk5_)JTOgPljOiu%LWUxqYH+KB$1Ac*?$o5t96 zrC{%xga!YzrDwl%9q(Hx63Hab#V%hH-y!&03z`haEo7t#Z&U4Ccxn1~d+c6th zB@@j6-QF^$OdJ)Yi=?Z|dokr9$oHR3C?1GIMzPX`ednroxRT7=+G7sDzdptyNbmJ;u1Bnxy#Z#h@SfLpn<{0r$ zUU$&0l_y=YZwkf9>dL5FqRbV`n}xS|T6G0&V>#_*r_7&btp5pg*@XC3lNg?F8H0S0 zW}Is97&nlzVZuvsQp|A-U8H9GFQCiLpem9|qhBDdVCy;rJg2LkrD{zeVB8D?+KuKl zR(*L^$wkY<_^5a=Ua?&1_=KilX2BY?nPBX&B6*j2P;kCCLX{#52eBk zdwi~+hDR+*pECNp9-Dgq{!0l5y!?@0yW?>X+tRgUF80H*p*bTz2#}IexX+H?oTY#G zh87YRI1(9WViqD+Dz=~TmeA6b$HZEL`gES=~@oXw8+eA!FE_Ad9EZ|d#k72V2j{gX(*)4~m|%+L zF5JJq9FJJ=WhQse%A9f0Q>JDl@e@nMhuXH9+CJ@S-TquycJkG?ur*oZ>vx zNA%b1yH)6XUC9`-O*+cvidicJ(eTjqe?2@DhdHqu-ifh2-?q{PVgx5f;QWF`^LCec z9?>9~&v%W6Yx9y_wtV{7-fM>jk?UQX&cgc<`Bz0SSzEz9`q=`dR7po$chtXb^K6E< zfOHc?EaNchVM0qpZxiKWEtUW9oSI%30tO`lFnsSRn~_5TJ-BoECw=jvC5n#>a*ui( z5Yv0i)8Oa%KD!lAGt*ufn4Tt|>CKx=IoMgYKX*E~HkL(lTVFe&NzncO_DKmi_qcD* z{W}7*d#sHsaDcXPNa0Y@wZ>kGTE_HG468M!*~_4O14+~>Yhvk|c`ZkJ9F@?PnpL{> zGg!wp-Qs$&bPY&%EH*i~VoZyvg+=l}o_3E^4v5MzKf{|3{c^r?X|?gnm;S=x zr9&~hC^*HE+qkS*515^Hx%=U1TrbS+$`Mt;~O`wT*wMtjZ5 zRlDDf#HDG^G;VhR^D{YUaR=XzEB_0Ad>i>O8xIv--+RhtBxKi)2z zH0)}ui8$2N#GB1nygO%OhtUy+w|UJ(c#k5a%S%be(osiCOiAN3R1ul^-ix3}8DX&K zBF<0A>p-?4cdj-O{Hn~<kn7n>yB4%1Ec24Jb@<|6gGH*+`jS9U=JhZ%|=5q}$&e zjT3l=ITZk6tYu#={FFZ}nkDlh*Qd{T?_NRs6$TYi*z`n84Os@>?FeJp)}m#LCqH38 zK}Hu!lV-06xV~cZDwL#GNnO##CF#9G=tD_Uf;cZ7B-0C;WqO4^G3XE62Qqcs>u1%F zMCy4-M99Wpn60Lsxd)QS4t^35+UG9(THM|98N9MmCYKH*$ay#mMWEjKRl>{y?5RXX zeu~yVd6Q740~Bt$4!)SBAf`;^DBK-NFf}mckvg<}kK|<2>)2{7mT0Q|!;{k21ql(@ zG>Ah_20Vjupq4icayaHEbbzw+El13B@WW3HIE+Ak@$%x`vADx}t5lLs?%zt=r#!L3 ztjou7MN6&z&Wr(EE~?yf`~-E8)d@E$M`n?rVy+7{IOOxvtsPVD!Sf+lAPWAG;c`HD zeP%f&!=N$1KoW>!YTwvUHP*msUHVLcg(T_fc@oVa$#oSBQAEmiwk8`VGlv(@dHPe$Y zkDW{K*p0|z+vw%EUhvFSWgP$x-HjgUbJdS?scy&%tb)IKfkU_8@I}2T;%H3l@YbII z3=TR7gC`R(_e0aX5xSop8EtO90P34&!&tC-T{S3Zq^ z1wCB`PgC2#VWl7Q9aiIOo%GZ7F%RlrKoT@wQEyyy-fE4O`E7n7`mmyP<)O~zg+)pccB9>l zfD;!^KRC!8kb9W;b`FmV#%O~f*Ulh;pfbOt_DO~1a1QEyl3_I!oP$#7u**Qgu*$kl z+ZywLSMI<2?ZiN@8D2@M$A(sUbNSac_p|qx53Lrn+O?MVSz|9Zp1!uE>TZv8ylHlP zJJ$2)d*vUIm=Y20?!VwENT>Tuvv;Cqu1*H7nVTkz2J*>W?_zL6j^ieFS<~2u3q8{B zU#X}qBnO*agJ9bgTfctbu#SOAEg-q&_irDT)t_anDZD)bwS^|1NLcCVySx_H|1-%L z%#RgI3Pas)qhjgLe_Jfwe2XX>hoI+UoK1sgJW8u>JO~#%2 z75@ud$QTLxbP9nBp;s5F>Gn_YO06dX=QB6E$II=kou$#1+cHVVO{W+S&;}_hDwFHn zyAARj*TFJY9Dk9BNAlNt{J4p+a1MnH0!AgCE31?VB57RMW+OgqUyiq7!zg7w*(v({ zjcA^apUM7j7ulhhR3wH6!tXsXf7U?84q5pR!lx6-An zc3Wq2eH&#~#=eVUt}6bRholD#>;+Wy|lKcFnb+uoY5Jkl1m zTbe%K{UV|=&47dT8y zC2_hyfJ$ctE%Oq4yp30Btpig7=-gs>ZGwMTH=~H$5NKB2<~6Hq@5qno@ez7ZrQpYc zhakuI$T-@lQx7n$|0jBFcagZX`#=7KRfgP_)R*fi)l)ulqF|PHg*h{Nyzx05*74dM zd_de*tmq12-iv-Q?_^c?o80!RqQ5~qc0kNisqA`FUp`-6G0bkXJK|dMJC5?6Vwu+7 z?1()QU)Cm? zh{>qx1Yk#RSF-HL3AiQa4HKrp+c(SJ3O}a*fpdS_|APAmhamSCBN%=vGJKt58SWML znY^*V8ul&S_qy;{fhpa#k5_KqS@ujr!Q7|8ZqzT^Ov=kc5{WEcA}K+u4oAAS$Kd>Z z+(cM)*b!VR{CL}BI5FEtIe8u>)_C0iLeJKu2KC7)1kXV)cd~4!%Hcg{TvsZBdq$7b z@=-b+*HppfDH$5|f9M~ch;#Q82lH&(0`%#RUe}y^56$=s{=7{(*fPXfdse zQC!M`aKbC>;Gn2v1|MtvWhKMYq!4TFcxPZSq+v zzF1PhSiXB;*eU5t7AyVcuhD(95Q9ltg<~+yR5-T{S0PORcWzHKjeRDCqoS}Wq*f>2 z#v>%bG`T1km;d|9d!yB(Q?Zh{h!*mLdmMBq?#t^8aa)UJ>p+?~8hG7lGEPfVMxSMx zaG&e+DEm(^Zz9gTd;S~dJrIr93jG$Yx%|D?qCAJK1Fh;cN3ck3msaYXbbG}YTHp~T zxFZWQX^wXNgM=IfKQt!s4UH|o9 z-EN$9_v4QG%bYhDt8(VyA*~cCYfVP#`*BV&2OIJJo$^L9FAJa{U%b-hLPUDR;i7@! z!78hjx}D7jH2A9W_Qk(N_Fq#@B#LBXi56Q~_+A5>gpog0i^0 z|K95@rZ*D!(+GhdTff*FzFb7emoABT5pBKqH{>7U|k_x5{dd5Koy46DPRhM*aQ zfBnG zi-Dhv@j&c`G~#t#S8-F()f2mfxwYm77yZbOyvPR^zh&S8uU}&@mhyRKBI}Uk;Si38Iqzn4UdiUGI8pfANJU|i_r11fk6MRD1|{xFy>qtcnW(x2!-gT+ zr3%GXQ~g{^xyZBTENROV99HL>rYK&f`@tSu2p<+YU5%gUwwVajIC-Svew+Z`Gfarg zy$GkZ>J%*U1ZK=ge00?{J&JE*BKVRqeg|8f{ zxKr@F^8`3fjJvEC4)7)n;{?z;;$6afoz1FT8lqA(+Dz%NddLf~n74<`7tpaR+x+wJ> z#Gv~lO6TC{)(+ODx&03t`O~FwJKeRcrI?;Q$nRl^z}N3)W)P;0I}n9dGFpiDi4ka_ z`_2EJrOn{0f+t0-c`n_|jcq%k8(o+1cz2vuonJ&_#Fv;W#+fMP+E$CcorBIr9VEI$I;W^vALzLfTn0DHGvu=r1PX-^$ ziU_cO*O4rnZ1*M8JMdGE?z0FT|4n-;Y9pl!%+Babk2$QH8ay>V#BP^&P@dApCuf)< zA-m(4i{YE0`t*Hba6N`@@_4+_177&@i>eil%MKs12)1_Lxhf}c4mazs8NDmh`=sYY1l_nbj@XQacxm1hZ^>bLum+Usc3)|G<5U=JyHB zqNGb#1BIhRhkS4np58FwM3viHJNmKT_cn=p_0m^Js+spmY~0~Se_gvoA$3w#lynX^ zbIX}3_R^g8Ynm(c>BH=e9`~f}9Mz_IIgI>RDc`d;Gvd0T!n&qfuUDt+nro~4HP3Gp zX4ZMlGjiV~YtH;9zrjojz{o85KmCSrUFMu_^N$`Ov2RKR3)W|2UNiq{ ziiKJYA30gg|BYLKU$ExeUjT5bBBb*G*R%S4!lj|4);dQ;zo2R9W0VgGcQ~&u>{0JY zahX>fL@%aIFZEu^HoQh{`DkmO^2p_WaZ8SD?D+HrN3T6q?6|C~9m{-{EZCqDJ#FkE z-9b5x*^FoK`r&&#`X7TlHPdC$P8{EvGU6(r|GUl#lb!KV&%B?wG~A|couezYKi15q zEyLzPL{Sp^db!)kJmCWi&T6CEeGlQ?g8E*7h<@(UZW@C}=^JgQX0lCE7n`PrLC9cFeG_TeFCcCP$* zWs+W3q(zZd@5j}xn?EsB-y^DHb`S3`&nJSp6*c}KnERkGX~T}*mg937OAny1B~QwF zPkYBwQY>8Z)m7RrHsutz#VNUdbhnQ3aa+2D7o+X>ec9rbN(Tk)UK}(mZUqNFu4Fzo zTHp4M%Fu+i_sz9lA=^JB*qLQ_?7FQpW=-+?=$aP|Vg6GN)ErmeezZJ3-9)FsdNh2! zOh;;`2YjM&M};ennaxD?#U~$69HBRKQfY#g=7$!r_l?~y($2!gYuLB80?Zs3fSF#Y zXBaSU9}_~2-Y#V&_dGQ^Rd!2~X{s)K zJ2%-ba~Bj(G3nEA3rZ^JsfOqG=S;*&6|tMF zYjQt7r{NYgg-l+)C|GmG@1w3DUii|s~528GhhfQ(w^L-5zP8+j?yp_T(D|(^S z71I!TIdW>#S1fOwL3htHytY@a!+vpu{uX^UFGffC^!P>!S4@&q-Q#b1m66w>7dMo? zeW$jtK7CGe`aUcJjXIeJUv*8FExnQx`k#VxE?^1qushLVrF}&i(QXjckSXcP1@U4~9 zCG*md)|@(*xUX*5pD6}sKXnAGYV|fR|ftk%JpSjnuspGMq&bX zr?JLl;$Db|*>FpVG;>d>aHu|gr&05sVqFPc^Uj$!{FprO-jY}BiMjS%i|N{d%wu*O zGy7?IGn(30?XP<_Koe^*-`Kk>=CEyt=j$0)B6a*-Snwe2`hb{*Lc_6?=~PuLfx z+};j;d}~y{ZOg*A$se+?8^tgSU(Oi-q~iJJkM`i zwD+}l^0w@Ay5`wBJy<4ZzbZ{Kb8HG{H~KwIZmEVZDc;#P5m&OEgTtOu@x*l`4b{p3 zD4L2Z``W7YwiPtj&b8yAb%A!NIvm?2{$fw1xc{N+oku>J+qPo#Z%)cn)2os<%&d@G zSg$BGA<@NSJNDe+0WQZJ8j?GdbjOD#?zgCR zmp;8_FW-^3R@hQLKD*NJuGBGp*GC(pr|r%=Cs^*04d23Ysqce=r}0Q~Y^;3gfHOaEd-Sd`RjXj(ETHz&~g3k(c)|B_&WODU7M;t zcSszeOB>WoMHH%Yk$qEC2OTJg^{BQ3&@LlQl(>N_9u1HTew{QDH+mj35@9rhytXbx z|7_wN_tx6DkTofMuzq&iucCnm9!Bw4#Y6F)YcWOJ$UOFORu1j3a7AOf!eoEenn%h! zPGYB#zk&zYosN1?X}#~qkA?JrM#NNk=l=g>a&4Go+hIhQm`A6(^$P!V8oW-j81g<&D*&dFIrb4EVcHWI~oHj_-5m{N?4%&bO8$4BhY} z>H_E+fL%W0ai1mX$7`PBSYeLSP;<$g@9#$s{y*y8JF2O4>jMsmf)y1jN*hr|QGr1O zr35P~Dk{wes3@o?h$tnLz*rCzP)9^TilX#l!$J!qDi(@J6O^uW2rZOAl5amJBtlsEmpK=o#hVpe{;IFJEc zvgn`F2nqKAv4>Mgn+_w@X*v=j-}Gyusq^aZ^IX346u&DD(wtwms-gmOGMe@&mCjrz zV|h@eXJu>(&&lXlJCP6bBBtsFS36B(C@_y!X3b1AJ(Q+YieW0B2O1HeB2M3IS@@Tg z0t`tW@R1>4DFTSv)8}}X(4*KbtvHayxqgo=y_Y;Qr(?D8{GuM=lD#j8XqS~x_SmvA7krLp!C;}(hm~pVR0z6S}lL$Cx@efuq@0^-dkl_?;TDV{4>d@ zNG}s*0_$9Zdsu*}ti|(iRd&-`Uey`1fiboC+=oxf7~Cz5kQ?^YHz8NEmV{L z=RkdtGLOE(-PEs?iNgRC%p@?(CGBw6kRMtvPb<*W{1`~B)oi>%dGqu}?)zq)Zxr+N z&kD#DwHWtQm^3>B0zjWpw@nXP&th|l(Q7-zfm4F(2)EP~7fFLu+|vAlj@X=uH*bnG z%^pn;fbjd%1E!z{WUM9ZyFVbNCP|ulgkBpFeAnl;6cW|?`x>v^yg4;w(QML4~+|km~F7;!vr|kq(km_8`VPO&A^DS%1G|Kp1 zUIZBUKSlr}pa!W}6H$OVP#Z_2rHAg*wMlu z)kXUd@FKgnKe(-NPx0V9%$G(yIJ4c9TvI%+%irzb&F#I1X^(r`_ErKC;2f!Fvlo2O z*8RjnZz)Q8e);t(_b{iz1KH^4j)O7XuPf_wzyo z{oi_k0hr^(PTMCMiTj&xF{5XbjSF|0rmYv{0!n2c1{Oo%-EP0L@*9>)#1Aaf8$vpa zcl&%kY?s5!ohOHtnDcUHgy)&&8LEGh-#F&$O=E@9RBkG090R2lkt)uYC7`k?yum!Aw^Efig1+9wFTnJeSpk=X&2a#E_gElo)YJIRdG*)z}H zFjmOtV(#hBI^8}%I+tovsLDl~n%zGB!394$W*UXBDBb^rmqL$eVBF%R(0>cybP465 zzYz1#N#OYvs~!@#GF;F910K*if$|(4aEviCWXf^?B%5a~N3tStIt@ob=HA5@gHHVf0XXdTL&DK5MVSLE7;I*^e7i9x(KIVt zIeX?CR##Jzm7b>y50~;>r=Ind8-25^d!2`Z*V4GR6&7a$cm>!J4Z0@}bLftUvPr_S(%sSzPm{DiJ8D_G-78V*^0vEhxSR@Ja|+jMmTx>806stJPKzklVtY;f z9EQB+zTH0N;hqD$m}Tc~_acXvHVFH+wsLcxPidPRW=jr`F1)9C+Y2PRwQVlJ zdS%cR_EyK*XHdPzK7YGEaVF)>{~`fPIoKwf<7q;OT!D}_9GBD}V6Iz521Pl8123gK za@?YH9kuXLw}O>sD=*?pZ>{FqBKusQtq_y259 zPZ79M`fv=cR6E1~|IRrlhf7D`Tt)}U{hg7Pkz~P<=A=lcH!o|xc+f1l0Fe6EKU8U@ z2z`r(>W|x(l1wS5bGw0WPL&NbmtSCf(q-=*A|24K*+$GsJ3Kym8tU*cFGZiu9@e)e;;6cL(=L$~jMD zu}|^n0e;`%o=1-xKB(+dINK!7(C@HK&7G-pHi%X+Pjd*MI44+2SsY}N8AN{jhe=UI zD{T_jBPrcsrrj)hD7ocTt_l~N2p;$B!9VgAp`YKPjdq-A#oRzVOT zzZjDHlwRv?tng?E@!#3VI->_7;I>o#m&SeY_S}E@xdqTi2acB~_}R$<%^-k6=I%W! zvVdN5yhx=fGCbfk*?7he2no7{BVG`s+NcS&Z~SvIu0|Q|;F-o9*i8VqzKoBXPnw#< zcyv1NS>=#D9O_N%Dsc`U!WG?iNblopuH=RWUQ7R<Acr}6W z5;#i@dFa*rtPhVXO`kA!B|;{b)$<)$3^#ElKXi-Eu)pum42m^ z)??sG9luh)IWo!$WGZq`qsoF=kn@-IWSRrB3Ar)Hc&kFaG*b-wDG8avR>Oau>re>y8KbyZpnx*#BDA9 zFO%zE#@^CS7A zSF+ya_X;%9$1cgDz zp!z2Kd1V$9X_1f=O9Bdh7Bvt-=Iz96a#YWuU-Dg+tf>M}t9VDtCJS{e!8 zmy07a>QzcqGrnORYCLj9?RVcXq=^TJ209fP=mpc2@q9jx$6OCiV62x3mGVj5G^h{MmOI!I@^?Hx%GYKX%K2Tfbz_ zx&LB%V@c@F%&+HqR^%xf7Y?RUMyjRD6y;DPzng6GAwZW^qNpK99voXB$xmW-FFZ8} zgQ!oayOzrL6vc8$DcBER_-*9AzGiBMpaBjTS1D*i=1cVm*otpoIdDOnPI743nmME8PL>eDiGBkC{Mw~8^<0i^w zA!59(|If5l_;Qh-zuXg&-3%%A@5e;>xmeuPTN0$J^R1*Ldykv4=BlLkA{}qJqSaW6 z8iw538?kf{hZF1lx1|(~OdGVD!}0;Iqe$>N?xeeu>jUT(}@1JQ$;QP~4)x%jJnWmbx9 zMEG%9Z_~oh^9qWD5fxhEa&mJ|n8CpB#tPT$uT&JtJF_Z+5koiD5z(Okj||VI#WuC_6MxM%sCKRqP_+!%^_s7 zG$gg3TZ5;mq%twOF;0zHe6gUyjJ`b1)3mc>FZW?gpDTYS&?bKeMS|)0Q~K7Sd0kQ0 zM^ABN-$(=o)$W<}Uv3$BiTXl-u=ta8sRU=|WQIA)B*4dKQHPJm|fj!VVCoR^vhnc31 zKttmWM6mxqf`-c5QCsU09vcR+^@*P8yUTFMb|~d9^?ZF#zT`w&;d|&vBw{}HLc>Vm z&G6xZKYzFffQ0Qouf>-~d)Z{Idt@Hv1P=+}-lFEBpga5;1&pJB+ZlC;E%MAv8><7IyhkI#~uLRv~9nzJ@C=P_nW zmf_|+*CQWL1hwXMhw|qqj#A}^hY0-q5Oi^{FVpnbR=o6@iKYCR%&T8wukn8Oh!OeS z7hwABNzm_uNKHJ`c9h{&i!wH$cKV8z>`hirV0-|D@Bfjuj7U2Lz8ln=_}yzT^-kNm z7yoW~Aq`OP%7%3{QAW?$k|A|7>bwIV8rz%}=h4^-9RY2@SoW3iMyf+4`2O8KF$F9c z9%rZJgs%g?1Q&Vyl7``w;srV3#tPLuobnjwFL6qS8p?R)6EYrQw8vDc`?q6w2PIo% zP=Pa;GEf`+y~TCY)8j{)>D9-!A54f^?95mc$;;{2`P8${aOsZa$IsSs$qLy(t6yC% z#iKjs=GHj|@Orhr(m?}UTD?-a28A)bjR!RK{3Xz2<|hWlYlaN|b5hZ=?m-!a>nrhE ze1gC#k~FPC=g&Q^N!ItvfA_+As`wy+$UR3xM+GNG5uHs|w5H=&Z9ZkAX>^yG&;L!58jYW;@tGte;{mQHq zUPtqcQ0X@_3|8`KtjmuLIK_jNo>Ko3R`R_AL^;wVLYNe3GSxXaW-sMWfcr7c?$lSk^Hg{wy5OwU=RwVq|h`n{Hi@3!5;aW6s){*7+yL`Wv z7fKnx7%Ph4qh%5+zOUdZNK{8^D3|+$XO3PkABr1B4y@xfI!a6D)A@~#X@~8o80l|C zM37FR=_@`Dmi?DJSjeg1$DWA)*e_OrF@75ydq|33cVuHzXRibNe*fY01N*J(3BR?( z$o$saWRUpbO6bG;ejJqGe|X%~-7t{z@`KKw{;3;kK}o2ev-(32^w>Er#CRlrZZQ-V zNf+?2`0W-{Mb?9z4{=(hg%G;{v4fNhH106}JX_pt#p%_|k;t8?GAYq?1SxW#RXs@+ zYJ}B+R5ai>Xq$NBBJQ`hYXiJakM#?3Ufs1EDr?SMS1SEj2m~9m%OepWSpgj8^RYAW z07>#tM}$O)O7RdJwiCo$cOXm2py@EotwP!0WNf#=>0@5(NPIJb0;c0%d}t#`G_VKGy;v*$Ynxu9DuWf>m zwr?YD<YcP{=10nGKN1_8h~BLP@^PYOl& z#0fN)RaTH%v%iBPka!vECaKsN*bm>wzm=~gxeItM;{z%GgR#z;)@R1)=Mw9;>o;m%3cN)1+Hd0jZAK7Ie|fZ>U-``g>=hkF|eL6H+7*ocN2m$VIkXI5?Z{ zBCm)%1qKZ7!-Hx}S=S>KtOjp~)S2YWRN0+a;o>l?o;@-b^jlkaf-WDjt-6RZ+RT89 z_}0Wv(;I*enZK26v{Fhol6k%FETd^*Ht6;c`o{QdIvaAW!t9;V-!WSGuMt7bT_+pfT$MxDx}j>9hnGtwoNo zw|zyVqH(HeS#!;>JMkR(+Ns)O&g1#=5l`0aul09dolFkmA5*Y0yJFr)aG@s zpdU|&`jf(_OUZtdWy{+IU{x1o(230i&M3%XaN95i?aldI2F#ZUfA1KAgy~#i(iBC) z^%qq%yErd>1;N#<&FF&0v<36g<9_K?MFFo9V~rIK0#d_*)N66}%*246WJf?$EPS^t z#C9#LQ!3xjWvi{6Oq1l22fgC|-r@9uYJXdiD$==qfA!O=P4BB@cR2KVZt)6ri-Rb- zouQ*I-#;%+1FdNpN_Sbm4ZBlpWPAWnQ1DM2s~TFBO}uV%-hHr^3TrGhwtQO=fqwYe z%J9RFu&JUi7y9|jub@h<=M{m>Ji((@fV8IzSTEkkv^G(oZ=)Ns{!AZg&+Yoa5B_5c zMJdI=-+{DCo!g**K-$Eo&*Hi7KTOtq_B&7jn+EY(j)hvjzIqlvvTBGt0v((xdeNy8kcES+me?wU^sg@zgOI%Y2N1mgZU#4y#p zg}!_n_T{chUCASyh?Rz@2_48=n!?wNsuH9uB^4rWxc;2afDON!t6A+YW`MGE1Jo6u z;nmQNxb+Wip#F_!j(qM+;V7x@INMQvNg1%j-QeJqk}8TnzkhE zqh0unUoV=v8Az4CgBO7`mJO$`clL!Oy{lF+;w@ZfRMJ>3rMFOnP=E*24|Dk4syAQo zVZA@jpla7eJqul%F$#S799UaLt(-z?k(%DCE`MU1q2;Z&D^Rw!nswLHBGVBWu!0f4 zo{ci|9`<5tsUD1iSpM}ZGNiGA;{ngttb`Uuf>q4w(_BB)+}-9EIXwi5LJs8kkSsGk zb`3KOauXVKU!Hux^PRq#s7K(h>LJPx&5AOoG)U5)S?g-tEFbLFFPa;n1PD%a`gUr= z-BLwKw4?5_A%e-d&5nQ?tO*7wzr=9m6PX3njzsDcvl+N)lLX0YAPXgTh%4gDGfoJ? zCal>Ewu~)J-Z`x~Fvj=JkV2(FpXt0MA+6{f?zE!XYaOZQ&SQM2$jt*nvs?ADDtyoC zR*@^PhT;qQ{wJT~qnjob+``i7NOJe56LYYj@Fs@uqZqm!*j^S3-w(dSR52dGLPIz) zG@#Cnnd3x9d^n988n9Q4HYvdOPj%NMet#??Yc#29;|EO@Wza<0F0NBz1jghl`aqtv zopF}APBiCY$1Q~M#Gy_XhVksA&A?g>P#Cm04iDh4D*_sSU%KAoM*RX!btSlsDa3d9 zjPodhf^2b*sMml=X|qX*!P)PlB{VE9fL?1$|6v?q*pCji8h?&l$uG-pP31@X()x^|JW0+IBJy?dc2zR4ZOAw6jt#KA_JDf)|Xq(6!#TT<)M#OB><7Rj8 z!*@B{39LD%V*`_zSaIy(G`wZyhxXTSn_+n=4wV=qT7lvBXxynz!XiLpz0|mpUrG$# zM(eP(um5;g4EcT_uQOJ)80ql4&U{Dm^v!=G;KvPLN?p;zcr&20fsAWoA8#z zcn`FDqK5a|-yS``{Wa{jUqJZnPrz@l7No}DS2gZyu>Ei>uFoGNkMT{7Hz3Z<1`b9oNC1r3$&Zd!791UAiM#u(&;{5yi z)pHmUNjO%AQn$)E-Tw|K4kw8CD=Nb*ui<6bsaXK<-`Nnj znplN7lCioK2EFC7^E7IX`IJ3CJ-Ec*U<#Qd{=SCo#DJ2S zyDOZ(M+UZ6HzrVFWji#2ht}h|E%=+ZIEX+gHr1Pe1YyhnS;RA6efwYs(b)G+;Qg1x zM|%&9A}hes|M^5KK#8;Ruli&7XwXphZ!E=JbhdfW%D>p)Y&G8t%`I|OeLv36ac{W& zV!(1g#Ad@#J8k3R7qBdWM|*zG-^2y1;pAqsOiDu}HEw8&c;&mlX-V-uB!}M#a!5kH zbQv`U?|xNNS=9A*6%YuvSjCtNPn1#(61|Q_&0nCcUtFHwsoagrs2Y>4R@fP=^<@5X z6z2992S9GkodrK>`f3PN|3?>ecgI70EV9OpZwpncQCRcU^v6TRId_H`M`~Jd@4-{? zp97n|{P_y?Oz#7UUZD-=P?>yQ0Q3@8nL0SCiZn{X|h#WO=t@VO+(S8KX z5pAqZAYK!D*bR?S`Y(A50I0;rTtttl-fqZ8F4|!U2Rz62zv4MfNH)F%+5G!+o^t?H zWrtO<-pQ@0xRu91Ss?QPKLgKc*q`9Dr&cM&#>OoNqb~^zdxu_&@fyh<{5tgE`1x?d_}4V4R@vNnT`%31o!(}++6^!0EM!Nt zo(pwEc!mR^8bwQ`-i2-1&bJXonNR8@X_*Q?`_R{pRxM0c?r|F;(&}e-GF#lQ)YZA` za?$Dtx2B}uu(f5t3ogmtS=uo?z0QS+2+~l_!e#Leg~v%T-_MhHvKZ%q<{_rib=1AO z-nt~1UEZ(n?;BczN65{N=-vRhW5fbc$OD$}FtR|dmmpB%wmA-JtQUjzE-Q9+5=)Fy zpbPc7JspsJyU)CY?qC!PU~wi7m!aOVGB0+_Zu<)O5-h*dPxR-nULHn>&k0L;Rq>Qp zdj%N9da;GL=Ta1jgXSlC$RBDp+4W3R?ltx~1@o}hplc%v(ZCC!+9SR|7QNuJ>};MY zO}#Z0UGXs>8in(yGl~a>So6UL&)ugYob1|)_xNDhBtcFunaz4MP^6=_fMYA4@-~D@ zQ!lom1K?N4Q>>Bh1sy9wwy}q38|bjojLn_+oWghy09_B8xtQ0ErDt%!B)U8$ zA-d@u-@q%+ji_41J0j%IlHhB91z&sVm(7xVUwdGx8oQQy&6P1NLH0J>tZM1+RsZ;z z03nY!3bnTbh3{NK_?`ygd+M5N^NHcxfuy}QohhOkz2_PBh?HF^4kr3V*Ldv+2b%DR zVrhXG2y0Fdg$NQw*rq82QOrT>@cNq;?BDzwTvGbdMR&OQK*ccl;AjCxR&*gzyd{XD z5|IX<3whxvz8D&vo6auMd9j)GIM~EIk5=hl_AiYs%}pa3_kKWH+vD;GhhWneLgcm? zKV6i+>1+}I-ksy(;OE_dc&Vy4AHO3cKQ+VJt z+6kvF-8-svb}ZDWI5UVNwj+$YZN&N%vk3CgNAkEa-C;o~b!LQ{0D7&R1`DCD{uH+6{NGk3=++2w0dIaR|Cs?``Vx#Cq zO~ZE@F2Y8vzr$1h2n_wsk*({JEQUUe$`w3_e|^a>{{peOxH0X+-NjDA0CfVHph^sB z*LiUzzIJ6uWBWKdi*%B%zkWgK(p|z!bSLuzi1o($)4bZrYCG&&*f2Q*+hT+`bHg;} zQb<7spgyi&0t%4pI(psxA7V(-W|m$jb$XYRD8d!Q-}04<-a7KQf-fc$G2G%a&{;gw zLk)Z&4tgADFGn9({FdppO*snDsY;>EsLiKxp08eWgFhxIS!r1Gw&oHP{J&#x-K~5Z1o_GlsQl{eycEBItM5E1j zadw@UAk-jk6{3d`QsT(qK4g0RfDJcg>@D}UE7({8uu>k|-Osp( zjfU~T1#kGj4_t9V(;U7&HqCm}efoQpiOv3$<*m=)7VC4-^44`JthJ3}H-B3*T{h#T zVA#!HB9`BDyC#2S?oSn}j>a zHM4yBZ^D@hN9Zlev|T5SzsmiSF+o6*wEOP*$-KWHjh`d55okQ8yT{yqeHVHSX(7eQ zd-VOEpQOw?HcS1fNYguxc`Z*c0*+4)vM5d8{%>hC{#2B0m(XSnOQ3zIa~ev=cJE9507cCbwKtlEkVY6hE6nvYkt3$6Pc3sgVvt)s|SVU;{b(pqLvWBA%X`0!MISz06ccTjCG(Mt` z(eIq&nT{;!(BM{@AP4{PBp;EK9^6w8~AAPOmhM!9bQQ7m2kZ2>_P z8BM@{KIbOwEH^IRqY0h?-gxa5$2d#Nc{C9&Sh{0>746qkF6i5&EbL7v=evxxi48F5$d2CF(BR8^tHR)`Rm6d zWt0v0K-N4sDgEA9cgQuDn5pU<5gr=)N*PebZWt$2H&27%Ks}4iFdR4s4F^_8)^*pZ zoAZYQk6r2BofgWyzh}BH%JeZ9Bs%H^mpGEj3*ZtBeg(78@5Ki5^arXIP|CNIRxiix zIUCd}wPJE16Y>*VTGk z#E-f?y8JdZ5j9Sd!uavyO3&$5tN|3>uOdf2mv~eljM5tYp(JN#>6#%vYa4qKc6i#V zkFp+S_5av29cK04qFMdto~zRObLa49^~D!x8qtStnU>6o2{-{RoqL-1^vT{cH&yT> zU*q9KW&SOjM&T!~p{mS26~MCxcOeSAkEwh?PAip(ZBVAzTeMcbU2e33Zm}g?sZLC$ zakWx%VszOip24@DK*hi>Q7z~f_l{Wc9QnCbDTwd z^9S&S(@Ez%?mZV!{h)$btdq1l|9j<8x6S8xmO}b=tLfZ#-w=nwQ_j}YB=nF*+jYt_ zy`R|{Bx)M=LtIopif&lLTxEGE_vr6rGryy7-10ZwL-KKNU%+CB-X6tB)ylc}VhHp5 zSxqc-Zu`)R_Oi8%>ywApRCyUCw1(t9uETHs-gSGuOuTEEtBS4$3^z@1z#~W4)G7h@ zwZA*y7Jmxe)_$4J5cn9~v7PO3=&|z`Zt6eq`{;ND3tj;{((!-!3VtLx;4k}D0_yxv zklsVeSRNN$HoF#V{W-FAHyh`d_87XCKN$E&=%2<A2+i(|L+Cn?g^t2V9~d!xMSA|q7}S;h2>eW_HQb<(&p!qd`=o;>EL#xwdo zSMdw|-YX}-r8d};6u#?NjKc42A@KpHOI1E`&!t-TPEX*b?r?y(vsrH z#y71-dWo0^+eq|aYr*c-gz*%(YU&(T2kra`R+XXm>fXxMWAOtjh7-$t8nvubm@730 zF`92!KUe|%gYi=ZQEuAkKMZLjlPit|L~%%xswNFpR#0ELuR|-Y?p8A0e-ygOanzMc zHCq@@i*o{FT-R7{?X~?{^t`cpPuWN&jNzP6n1`M>m0%rJ0b*d}W?G~Zp}a7Xv8W1! zu%22!#_0XQ^8CT;6Tx@Thn}L$e@gGO04qyGCzuCFSpQs?4HHQKejBD+`+k`6&wF2; zJc#NpcvP=)K<}tzu}d|1LBxIC0S25-@6Q!pn)UXP56?a(k52nou7@1gxapJZkMni` z;9_!9g;3vDP7f{rgICPY5xNR&l@%$F4pZcLrlR|Gh&9Rw~W&*gGoH`&`dKsL?O7pXhrqa(hd^`l22BT$y2>>MYH^k zcPU;WZ_hwgvW>CfQ#o8dSq^o;&~YErSBy)rQBdy5jLc)-to8s$Sa$xmCsx^Av?t0? z;I7D<5gxEqMg`rKFPM}6Nc{7YYn4OCuMFtUpBbOTqfjOp^8080?4R1R-*$lgV z)m_G1k@ljz+Dn+!^0JCwY-P|FfSc00#AvFu82b=KKOihSg8=5$VR3yB)yVn1{4)0Y(Q?Aa_&-v`z`!M|C zSG&s%j;Npy{KG8Y_^D6$u;ur23^;z&!Saj59IWqxkRz#TcKVrTTY2RqoIQj>MHaom z{KkE4-Wv=reh0}EEp2raRX_eh^Z6xTIaI2y>YwSl;VT?>A1;t<4FkzRh#&_kBnMae z9SMRQ0%5^(yw;|BQsJ`m!66qEh*zule;Q2wcI)^}*$+k32U_e4O%8>9w?hUKTs91J z?nvuzgWU0-502yVyMVVMibuviS0sVnG&_4-0#kRO^({^3WIL5&&WEFmBL1k%Dk%s| z0pR#!eYsDx#W9_{k(EO?lEWB+9A+aqn9zgD`53C2Py{T&O<+oUxm;PYFdwc(^nE~> zO7pRt^1ztXA6;#44W2v=ua{8y7P4=BmKb1afDC!3-#a;f_@ZN6lM^7nWAO@Wa5hOuxr#G*(BA&RU+Q6w+LB9a(I7rukL5fF$~xUmR++9LIO20QpEwN z&D#`C#dFo_{;A`SBJyJEzB~MoFIzN>iM)3RM2%I%sDZM0TD{2={eOuX@=^hPoGH@v z;U-SPKhnFGd-t8Cn$b|(Zc@Bsla_V3%8s-bD6DXC)6b110NTPPfSjGtzZK11$8q; z%G>Bh69!EC%h(-h^vxw$6nuXxyk-i3xc=xMQn-psno+~d%uiO$1>H3(GsPgz+Yu$S z21zK(*&=`-AtsD^254(ZTZ7|DU={tP5um&<6WrAQr^^joL>K2{^!62q^m)3HL=vdL~y3AZra8zb( zDNVJOPFUMv4TV*JTymE4mz|ldFE^agKxlN%`@{zMvbQ^jtq#8Opk9D9z_R0`cUAQ$ z&kyDJmdfCw$zTE#?}^s(nK_j)=ruIKJZczxt}Py8iu!#&CStmV0WHf<#i;XL^YK20 z-ta*!=8aAw8EzaxxGY8C(voIouft1Ns;2ISMc|9${B)`QQCgdpH*zLua6F(X^u`c@ zUEKCoz4~&R^;Q*KbxH*iQARZK;aun_rn-bYd_v0JitHz)9?y*P7J-i=53nAq<328< z37|>u(yRxMsoyZ2Tcp-@&N!eaQHR2uc%k17cXVIWof=((*G$+m)E)d4ze!UE7AdTP)ET&{hqJF8{ZZD|xYUZxy(D;Saj;mE&bNC?X(%Ib$i-8e(9Os{*Et_C z=KJSy9&FgE|6v{J!g*IZIi|FUPJPq}-Z_1QJXTNc}V< zklyX3({OI{Gpe+TS$PiH!r$z{*l(esjuGfT zZjDDF#`UjX0jmcf#MH{TuYHwXB2{$a$IGDjfF-3W>77*8$0pZpMHZ*bll{IXK$Bki zdOOO(EFC*jI%l?iTn9TWtYJ0cKTeg1MpY!uhTyf9BCqwNLM}yy*N!+P0taue&d?C5 za!-BM>~~y#8WdtzO={&iCA7GT63q8IhL0 zW&Y%PlgDEGsOU+ez;Sx$8INIA!9P=3-?DWlHgcTGQqZ7vgG-fg(@=e?VS09!0{Em43Jp6b~;R86{; zV%cy-=15jwhk$eEM#GbPM=j7VN4EN5yvsGtqZBe>kQ-w_UfrKV~1hq`|A~1}4KjO)XC91zHY2;)+`|gy8BS2#F`*#?8=-^0b%N(rS z`3!2WAg()J3L6?mJjll?L34$+508x+L0~8v1FU?!TLkQH2r4d&bvyGv273Y>p^F-R z;t8WZC1^mRHI;r0CbNrH+YLo|+F-}iDIWp&n{9)NE@#xQXD+LPlYv+RZ2L306*R12 zpD!N8y|{-H@(!u_I4_GmsCnc3IcIwxC$@wAxXGzE>uw+FzP|AO#;Tf8A<9ga>mNYsGqM-uVX%}Hw$=Ug=17aB49d29$IS#Hk> zs<#}eURz2y-k$Izq0MvgZokHS?3}8-&75s>7Jd62)KS=KHjI;&|8+WkwjN!S2vtsj@5s_2+ zzIR+MD4{L-Z0>|*nK65=Z$iy|hWha^O^snD>zPgh#tZ#M3cpUtlZBKf&&B4`lH_Rj64lx{jB|jP(RQ&~ZH9qp zTznacDVQK8CnP2(`W0V-n8JZ0R^!^&Sa6T|WZbNz`w0k{N!f_lBk!Y?8#RWqgT1Fl zJ`N>eaVV7F3?z{=s8A0#=jWd1GFrgly=J!SuV6?N=`Q8yl2rcer-Ackc9rL_eC;cG zp91=PJeb!oS0#tof2P5{*0BCJa}atK0*#HDMB`I~V}`4@VfChcsyj;y&w1LhA}6kQ z!*jk)P7#0u&FA+?xovFRNw6mqW$@JO?}fL|NK$V`CRrC7EK|ecEB&C(~a+&>Hl)ZPy?q2heSn0auO(BjlunN_t?4%t zY*_3Y$`zDPTCPzgS5W0VL4~?$v>whe2dI#C3pEVNP+xXMqCnf8A+q>m&AV{Y*1NII z7XT3KW-^X*{6p>YV5b@|F%yD`twJWYitfFgU}8Wo+pIFst}K79DNlTN;q_#u^vnBn zanxLvi_E>>)%Qdr{_K;8?&pk^Sgy};HX(Bb$&{? z=&Frh+B5a;o1X5V2_2ZmDjUdl=>1{y!;Fp%W*rYs<}m~~HfST=uydTg?wkZ&1Nt?B zYnMi@-BIt%W}a)Wn))l;X<5m7)S(g1*f~ z`ZkyDwVbbSld#$-j&oJN*s>RJsUOtw2R717^4w-0Wp|Y)Nv6p?eH*|Apvp(ZFzC-A zYE2r`vFxO%6y^nGd0z0ItHf{>eqXgvO78FuPs#J-KvK{WX}HQyk7N{qizdVJoG-U6 zncaQ<owL)qdoU1$$MkVrJbL`377wmhVa7`JPrNWalny^?U0GJ`e?~ z`)m+ZoHJm$U0_CO9*Jo!4jy&n%JKl3KlQFkI_w^M+ypGnNj&f;$S<}#kNUJLCf*pClB& zW+K&pKW_#F!%jIRSq0XmF4?HAdcv=(dXk2Xcc6gX38jrO(hA~YO&-x3@KBCdrFST_*bKkcEM!P+ky$aOA( zrh!$|@fnW!Ma7osDIcm{kt^v3QS~c+mWOduKlzUY$Zd28S(6RHnzkZqx=p{3K(HoM zO?~oP6&gWy&e*?<+u!zG1)iGo+99n3(WVRs9+v}a%Dy{w1j%b0PhhUC%;8H#V0xc6 zdX0y|g`51>@X)(kUB@Vm=Qs=9J6E<2Sf;CgwWAHVVPp2i{=5cC-?@Yl>7bytgE9`S zxS&d-FV$hK4xW*FgLI4CB49UEIjOUedlRc4t8`2q58|c^0$YVzlTy)q%%>el>s&OI%PklQ`bQti z-%Mctq5a&ecr`L)8v7{tK8oP^qnFrfV{ zK00Q0+N&fkG<@w<^qWAf#6WCnGe~ehl7DFo1o5mEq8lmg_YgyEg7a~ahBF44YB zzx(@GxAeDAiIzVxtl1Z8ZN2Tmo9jEcgrlP0G3pc|9gfTxR6G;ON0Xp$%9y^T3MUhq z5NQ0#h@4&6`018jL8z;F!cZ$>GQ-Eg18Qlk3c3XU;EXL2NUB2Y+>whj$KGH*?GnMK zA(Ea}t>&k({Dfvr7#PteBdzQiCtrpug+>HuvB$f0?rpk@YVXl#N>6J%Q3dpxA38k- zP``*pcb~!!obv@)(8No0xdmt)yoo&UmX``lSvuNW!}osV>R1H+p&KLur#R|i_^j8t zj0PZtw7K3|oXqrn3ppC4nmRtrExe0Lt>bnmDl<`!^=uu#nHMGxt7C_^$Li#U5;QWN zpuGqH$MEfAXc52Wo{z4Nj%R3PU-^ubjVPGqqfIb}F~O7*1Y?Q>qd+y{H@_4`9Dz4= zx7hRcy+-=c?8wFkQtSW{^Z9BwcD93R&+2`yLuocynfU+$8a?W6UQuyl6@%0bif_hrZ=!r@=kgevl!zmg+fDEO%ux>gN$gh`*s! zt<5~|13%}4J#<}p^qoBB($?%YlScddDV=dOh(K|l??v-*$R+M(w0*!q#}=m+*= zjUs}oNg`Dfbui*H_PN8i7E*gHs-xU=CKrmuK!L;Sh4=14Z3wyaW=If##9zi`D2&`3 z!U9Y}Vt85b4e|Hes&iuq66%D5>~md@E_M!Aj|rHMtS3)W(O9<$=Ao~rJIjo!@*wh> z6rzq0CX0JeC!CeN=NgW>!8q>J{)Tmz{l^v2qdX{U8J41a5ZiRps479Ddl7s+Kp0Fw zLFZxUDtQ8WjdlZdve)VE2`%55_I-`H);4O7I}c1O*Ifg+Z)jfvEJj(78ZqKrR|Xb* zr10SL1%Wp`ofi1Y3htVq0nugKR|B{BZHVN~UyuSch0in81nSBmYY;uPQOzy%IVo~~uktLJFuuuqEj#s7+{U9}H zG0)k;cL-BFir_+01p8CXea&Y(S-#>?at5Gp8-_5Pwy|hKm7YrpILNQ_(eUj~Cw|NVij2{aMdMl`l?CGSsSz@_GLXX5s6|YaZ)r8X(5Fgu-Y8 z45P6+RTB?H2Sg!N_>y_skdRvgizK15`t>zVQgA$Hz24D0+|O~E8xVj)+D@UxUzD0n?lKHU^o5LDaJuO(ub%KpQ=p91aU%K25=4+eG0SVI8Pw<>B zuaF%Zaod@_pa@Z5-t6TL`B1z+C-8OwpnY~lmrbkp!pt>HFkyq4p~k~Fm-zvv-%s@X z)vKh@+KBURpFQvBG0y*Xor@yG>_q(8*Xx(B%O zuo`kjXtzw{Q^v879b`FU9vyfTKF1a|s0FG2#d8!z(16b|tsm>QcP!}D>pIU|g;x)g z8Dn0CpmJzInQF|?EHk$v8mS6m#dc^b*x@5(+EXA3y{rBZN5~d919{{szopkZ^|ihi zwqkz!{Y;)?P%%gcka2L@k%4q{RHvw?779GsYiL5F*`ZL|*>U)Gc)dcVQ%5izGzYM1 z|80N1L*NcyF?VjP!KygQT4yc3aMI>PFGpi##rRlRjA{3T5-zT|aYE!QD`x8P?P$2+ zq~I{{ux231C=(>30g}07`QZvdGHB{I-|si>GEO-PB~h4XIuo;-5Six?VM@DcL*j@{ zX-}wsJ%+TBFf{WT6?Kjg*_-e*y8-x&_ZxKPVkmJv6qG;POrKzW|vV*%Prk*584e}b=Ra0wh(A@G_7wpjV5 zc~=uqo}Jv9&h(1GY$&;BTOkybi^m%(P%c<;CuSF1(7&wWY6^Tm*yOj;V;Be_zsdoC zum_)PlJi}0i^113*4d$`?j!d9n}^9!8u*Bme!Rj-*N2R)!wfAyMk*u?LI z?(i$vYGJ+Z^F1#7YL23`%LGJb8g~R{{-8vyv)*Qy)-W>xwy`ug>G;gpzO1<0spt-x zF#Ret469fU-T~ygE*ozt%z-3yYUZ^)gsO*=7fLWhm)XWIf6R>zRbCr~2Jeg7x&*QeQqMKi(9KT8nz!-KKoFO5xm@a@cM%Y7j+u z4MZLMH5t7K59yuz+ZcWy3mg6Y+~T(sG2>lEvtzTdL)n@Fo~@;$4GrmeSLgDzZIU1h z#naU3HfakmQIhBW<7Hy@@)MCs--g`9XJop;ZFrrO}zyr&%^%; z;b5usGJRl1Jn(huQE{Pkb{D}+M{LQ8b^6UG^^F%7?Y;e1ChUy#GdBUi9R zYVNbG=0T?8G3qm&&-?Dc6r{xmJec+(Duwg6IUDe-x-XH_lU2#KcimLhk^lPPZ{O}k z%G|V=c0~41ju6>tSrNAOBxrdj+32&ruuEs(o5p4{vBpQxXHb3t-2ctkZ33o*$|uQ? zVcQ0p_69*a5qKq+0YQkAdu1BmGfeTQCAl9>5Z$b<6{vQzaHZyA+2aC7WXC&-Xdj%v zJPeyBoVPc4c{+EVu#7iPC_4O%O2tSHTZ;Nz4EGG~LWqD!5)8-3>=w0`pwm&zt2bEr zLOBXOqrN;{cnevS25wRA0LqiD%r3%3Bmk!(x=TFoxA-lBjpgW$2034>tP6*H-)uUI zmK{C1iEpT5+%tY*#NF$*OD$=4LA{|JTJLaDY#3PoYcOki&$lLlD^NEaNR8qnRf-~$ zphQJa%Jy5dYeEiZ)R%S(FCi%{#ijIcJH*)HJv#}rCW=5uXko}K?h5z1v8IbAb`Dro zp$&~`IFzjzJDPZL$8L)Oe{}v|yy?KyQy`~9iK3hLNNw9PcLnXgpf37|)kTD16BTd~ z58rw%Ar!5h0;KnLuA4qEkM4@Q*S~NI;*s8yds_d5kNRA`HmXpcy)_8+S%;Go;!x*K zWxD|%CV|1NO6ov~d2gt0=!%5(U|LuF79|;i$j~B)(Ot^wB9U3(A`?K(p}s3o1RCQF zxIa-VLlQ1d@^Slhb!oznCKn`#a?}i_MJeCwBidP-;1<| zdg3_bJw^!&{WlCwC5!{vf%8+e%#^^LpF5l~egzBtJRDDkOL=d9X7%#&1lTD6%&eHD z+|d)khU8I(3@t{`-AkP5d;kUCx)U$f;o13aK!(QGW9zQqS+esmMxZdC5okJj6mgkW z{D2EDD^+oCeg#28w9KIZ~=s?Vo8`sXS^;|#2)$mkL9`Na$LoB?qnqhT_f+2$S zhOS*WG>qi7Vi|-?+{X1#8~MPT^YVDAj@@kU6P_$x!@MfAetzx~2A$!$dmnp^bKg&Z zSlhDEL=EyriC`-3^ujO7Ie6SF%ldvm&Bvf{(xjv!OozYP~XfN5Mr~I>v=HOid#CLr{>lbed zhZ3*~6tjM(ej@z>C9wAE{0-08Y3ZU?AIV2We|lPF+Cpe)a=hpiSk(Lqj+Pw3_OJu; zKN6c5qN`ClD33dkrvP7u{rFQ37Z|oGLx>Y5uztVPb@xk|M$b&W4@2kTr~VmBX@eOV zLuYt1ZDw?*XwTy}Z+4%g^ifsOKJD(DbQ&F z3%(H05$$f`KP)`_1k2e~s`w`LlcW~0{gm#k`_s!tc3SVV8A>$j2ooUx_OhYbuv)1V z?w6X^O`mG}p&FX(BGmaZhC2NuO_;10-Y$; zN)xyl`466#qN$-4t{3k1(M^UbS$>+kbecARwQC2@jhkxgx=HXCU&;Rtrznh)j=8wA zuR@!H?g;TsEFgo^Yr~-&t?1XTUX&=rS+B(cQ|r_;95udDqupv5+F zz3P%zu-0eG?|=yGngGHZI!;5e9l6f?6s$j0!!J)VD%o%0eS-M=v|()gm4nuf7h{(Q zbn8?!uiKR#`Jt+Y-1uJj!f)5Fd~%sjsT39!_|BHkV4BXn zQp)1%Xz`|3NJTTBua`B$l?AK0aT>2{TKxmbm_2(x!*wK1`InswE)=K^u+y6oab~)&n%Bnn8||F2Bun12Ho^J%0m$&zXzkcEDM5HBS_1+w z>ZA3CZ_`BuvP(~S4)uH7)CJhHNp1r|52-_@1`}Bj(q{B)cZ5hrox)sX+kbEm4oDmCkNQ)FCa`B*pV36p|&_IHy&-=dR#weK=RIi-{8DfJG%cQ=+e*fsSn zKdWA#)ab(KO87DUgSC@tNdkiGiKGevK_L2HbwWzAF-aif&}HM56q&Kle3%RE`gM?(BC{ zJ>L0BLZZd)DQN=(>bVBwBdoUN?E~h`fz}K;`sXuo*3R>FB-w*`7HTExG`mSE$>~A* zSq{-(Z~Jbpj}3KLrnkd1TBt9%XfIha{%lSIvu3M*@6niGH%W4V)z>CE+j2?hZqri9 z_oR&COgXMV;jJ0!n3RP?T7+&=`)T{rnU4=f@8g^_DKM>kSi{<|E7N<`hX&@cKk}WQ zYH{R38uNa88lP;K#$4NJ#2TFC$~kVLoXnQ%VU{YFi=`Vg%Io*dHKKoxXSUV`aU5#B zG%u>LjvDSu(=~q(?$+QiXG-Q+v|WzU!?oZBDdZW^ci9Tutj`ieXadteLlQl*uo{_*I+8C$|u zk`(=6x@@)l;qw?{vrQE-p_TXO zWA!h}1khEj$C+cFN&K;Y;{=s?N+4Aw?4|aZKu}UjrvV4V^tV-Oi1wIL(E9a)^ zGr{b5|A9+cE{|a`9+j9 z)^{kUJ&R|zQ6oCNe)yMMnCYWj#G;g5l}QW+C;6&c$7L?VX(^L;7JCNS_nu&7^|hC$RLKafh3}GBmp^- zKxC7Cy9qRr&h(cWJMX`p%}!?bd!P3?-rY?IF=zLIwiO>2$ulcWnk^)#ydpEi%T_ma zw0EYguL>0y>8rbLx0OiEo3J#+`*SGJ2Kn^sk8KI}on+M=uTETG9{nu%RC-nrW4n|B zFMV@7@$21&fN=a}&EX#_6p&Y9@z_H&raT|47Mh;7XATu|HKBx|wbWA3dV9>Gv*wvb zHLfuYmU~vYXX<6DCRO^T%as93E% z;+mXjJ=fxYnmIMg+vUn9OS$bfa7s9B>l%uSr%-G!INUgPrXy`$p4n{zp_d6me2^r;77^ycu?H1VpzEjxudd|tTj zOu7C}%H-y97LAzCza-CJw|H4)Q~t zy7!pt1Y4&PSP@HNX-hL7G?*qDTG%dmT7{0!$-*^C$qm0R1xe?lWwyd5W6e^sZp>mI zlCKacNh*{=-kdI?etW4lf;X=Hja$VhrlbA#MbWCQS6AaY6gwD`z0c~5*FA1voBd=u zzu`%o94R8V8{u{`Tjw2NIbJd9qDJ0OosL_!M_1K`>a}inztYq6&g?4k3O5c)Q@m?~ z^JWC+^HozuQExq*Wu}F0-q;}J`WnhX73CMnkbw%F#vU^j&obv$GRru2hB4*qc*38t z?VM8%i)ngk+O+g&BmE$^|;;4ET^unGrK`?j~pNQqB zqO-B%Z zHqN-M@!Me`Qm)~#$Xk?$vzwGC(e8?R_0B?bbnL#Ukv5tdOVZR<;Yy08(xy!xhK0~; z<^A1Q(y@-_CVN<>-D%Y3Im8lPEA2<_Oyn-asVl4* zD8uC*>e{0vSp$=3#e!vWW58 z8lLwNooeS59YtU{7Ia!|b&Ku{RL{JmA=Y|6a7`o~l!V}I$mf~4$PBkP1av234_*`$ zRwxo8d7{7?J>6oL>eNff1o_W&A}88lowL=wVgFxYIC2=v=(bVsN<_U2b5?s>hcedu zP9=9rX-RgbHvX85>dvXJ{iJ6{?bajC>bc30~7YmF!QK@RdP3Bw@jkkfzuAOAL_l&AG9I}J8`q(ziRWXr#mJNjG5Dy zVI1~c7%%|4O8a5#zkGUMDNEv8*pk4>jSIS3tDOeu;$=?phF$p zIgkgChXWvhJRAVgBeK?I0rGIb3Xq2bR{jspV?zSlW1FuK_eC}sTfT&`_}an^2mS_| C9n6pb literal 0 HcmV?d00001 diff --git a/apps/typegpu-docs/src/examples/exampleContent.ts b/apps/typegpu-docs/src/examples/exampleContent.ts index 058dc998b..50a9e4a64 100644 --- a/apps/typegpu-docs/src/examples/exampleContent.ts +++ b/apps/typegpu-docs/src/examples/exampleContent.ts @@ -76,7 +76,7 @@ const metaFiles = R.pipe( ); const readonlyTsFiles = R.pipe( - import.meta.glob('./**/*.ts', { + import.meta.glob(['./**/*.ts', './**/*.tsx'], { query: 'raw', eager: true, import: 'default', @@ -85,7 +85,7 @@ const readonlyTsFiles = R.pipe( ); const tsFilesImportFunctions = R.pipe( - import.meta.glob('./**/index.ts') as Record< + import.meta.glob(['./**/index.ts', './**/index.tsx']) as Record< string, () => Promise >, diff --git a/apps/typegpu-docs/src/utils/examples/sandboxModules.ts b/apps/typegpu-docs/src/utils/examples/sandboxModules.ts index 350e809dd..21b3d9efe 100644 --- a/apps/typegpu-docs/src/utils/examples/sandboxModules.ts +++ b/apps/typegpu-docs/src/utils/examples/sandboxModules.ts @@ -36,6 +36,21 @@ const allPackagesSrcFiles = pipe( fromEntries(), ); +const reactModules = pipe( + entries( + import.meta.glob( + '../../../node_modules/@types/react/**/*.d.ts', + { + query: 'raw', + eager: true, + import: 'default', + }, + ) as Record, + ), + map((dtsFile) => dtsFileToModule(dtsFile, '../../../node_modules/')), + fromEntries(), +); + const mediacaptureModules = pipe( entries( import.meta.glob( @@ -54,7 +69,11 @@ const mediacaptureModules = pipe( export const SANDBOX_MODULES: Record = { ...allPackagesSrcFiles, ...mediacaptureModules, + ...reactModules, + 'react': { + typeDef: { reroute: ['@types/react/index.d.ts'] }, + }, '@webgpu/types': { typeDef: { content: dtsWebGPU }, }, @@ -78,4 +97,10 @@ export const SANDBOX_MODULES: Record = { '@typegpu/color': { typeDef: { reroute: ['typegpu-color/src/index.ts'] }, }, + '@typegpu/sdf': { + typeDef: { reroute: ['typegpu-sdf/src/index.ts'] }, + }, + '@typegpu/react': { + typeDef: { reroute: ['typegpu-react/src/index.ts'] }, + }, }; diff --git a/apps/typegpu-docs/src/utils/liveEditor/embeddedTypeScript.ts b/apps/typegpu-docs/src/utils/liveEditor/embeddedTypeScript.ts index 4880ba14a..ee8e6513f 100644 --- a/apps/typegpu-docs/src/utils/liveEditor/embeddedTypeScript.ts +++ b/apps/typegpu-docs/src/utils/liveEditor/embeddedTypeScript.ts @@ -10,5 +10,6 @@ export const tsCompilerOptions: languages.typescript.CompilerOptions = { skipLibCheck: true, exactOptionalPropertyTypes: true, baseUrl: '.', + jsx: languages.typescript.JsxEmit.React, lib: ['dom', 'es2021'], }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3010f2e47..677a04ffa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -167,6 +167,9 @@ importers: '@typegpu/noise': specifier: workspace:* version: link:../../packages/typegpu-noise + '@typegpu/react': + specifier: workspace:* + version: link:../../packages/typegpu-react '@typegpu/sdf': specifier: workspace:* version: link:../../packages/typegpu-sdf From f41774045a60329e650be540955715361f1df03b Mon Sep 17 00:00:00 2001 From: Iwo Plaza Date: Thu, 11 Sep 2025 12:22:44 +0200 Subject: [PATCH 3/6] Implemented stuff --- .../content/examples/react/triangle/index.tsx | 18 +++- packages/typegpu-react/README.md | 9 +- packages/typegpu-react/package.json | 4 +- packages/typegpu-react/src/index.ts | 6 +- packages/typegpu-react/src/root-context.tsx | 56 ++++++++++++ .../src/{useFrame.ts => use-frame.ts} | 0 packages/typegpu-react/src/use-render.ts | 86 +++++++++++++++++++ .../typegpu-react/src/use-uniform-value.ts | 13 +++ packages/typegpu-react/src/useRender.ts | 3 - packages/typegpu-react/src/useUniformValue.ts | 3 - packages/typegpu-react/tsconfig.json | 3 + pnpm-lock.yaml | 37 +------- 12 files changed, 188 insertions(+), 50 deletions(-) create mode 100644 packages/typegpu-react/src/root-context.tsx rename packages/typegpu-react/src/{useFrame.ts => use-frame.ts} (100%) create mode 100644 packages/typegpu-react/src/use-render.ts create mode 100644 packages/typegpu-react/src/use-uniform-value.ts delete mode 100644 packages/typegpu-react/src/useRender.ts delete mode 100644 packages/typegpu-react/src/useUniformValue.ts diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx index 126580782..ab1a8c6e8 100644 --- a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx +++ b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx @@ -1,8 +1,22 @@ +import { vec4f } from 'typegpu/data'; +import { useRender } from '@typegpu/react'; + function App() { - // TODO: Use useRender to draw a full-screen gradient + const { ref } = useRender({ + fragment: ({ uv }) => { + 'kernel'; + return vec4f(uv.x, uv.y, 1, 1); + }, + }); + // TODO: Provide a time variable to the shader with useUniformValue // TODO: Make the gradient shift colors over time using hsvToRgb from @typegpu/color - return
Hello
; + + return ( +
+ +
+ ); } // #region Example controls and cleanup diff --git a/packages/typegpu-react/README.md b/packages/typegpu-react/README.md index 7f2a9a14e..e3d4081a2 100644 --- a/packages/typegpu-react/README.md +++ b/packages/typegpu-react/README.md @@ -12,8 +12,9 @@ import { hsvToRgb } from '@typegpu/color'; import { useFrame, useRender, useUniformValue } from '@typegpu/react'; -const App = () => { - const time = useUniformValue(0); +const App = (props: Props) => { + const time = useUniformValue(d.f32, 0); + const color = useMirroredUniform(d.vec3f, props.color); // Runs each frame on the CPU 🤖 useFrame(() => { @@ -22,9 +23,9 @@ const App = () => { const { ref } = useRender({ // Runs each frame on the GPU 🌈 - fragment: () => { + fragment: ({ uv }) => { 'kernel'; - return hsvToRgb(time.value, 1, 1); + return hsvToRgb(time.$, uv.x, uv.y) * color.$; }, }); diff --git a/packages/typegpu-react/package.json b/packages/typegpu-react/package.json index 7fff3f823..31f277437 100644 --- a/packages/typegpu-react/package.json +++ b/packages/typegpu-react/package.json @@ -31,12 +31,12 @@ "license": "MIT", "peerDependencies": { "typegpu": "^0.7.0", - "react": "^18.0.0" + "react": "^19.0.0" }, "devDependencies": { "@typegpu/tgpu-dev-cli": "workspace:*", "@webgpu/types": "catalog:types", - "@types/react": "^18.0.0", + "@types/react": "^19.0.0", "tsdown": "catalog:build", "typegpu": "workspace:*", "typescript": "catalog:types", diff --git a/packages/typegpu-react/src/index.ts b/packages/typegpu-react/src/index.ts index a29c2c1b9..f92b8da8f 100644 --- a/packages/typegpu-react/src/index.ts +++ b/packages/typegpu-react/src/index.ts @@ -1,3 +1,3 @@ -export { useFrame } from './useFrame.ts'; -export { useRender } from './useRender.ts'; -export { useUniformValue } from './useUniformValue.ts'; +export { useFrame } from './use-frame.ts'; +export { useRender } from './use-render.ts'; +export { useUniformValue } from './use-uniform-value.ts'; diff --git a/packages/typegpu-react/src/root-context.tsx b/packages/typegpu-react/src/root-context.tsx new file mode 100644 index 000000000..e0443f3cf --- /dev/null +++ b/packages/typegpu-react/src/root-context.tsx @@ -0,0 +1,56 @@ +import { + createContext, + type ReactNode, + use, + useContext, + useState, +} from 'react'; +import tgpu, { type TgpuRoot } from 'typegpu'; + +class RootContext { + #root: TgpuRoot | undefined; + #rootPromise: Promise | undefined; + + initOrGetRoot(): Promise | TgpuRoot { + if (this.#root) { + return this.#root; + } + + if (!this.#rootPromise) { + this.#rootPromise = tgpu.init().then((root) => { + this.#root = root; + return root; + }); + } + + return this.#rootPromise; + } +} + +/** + * Used in case no provider is mounted + */ +const globalRootContextValue = new RootContext(); + +const rootContext = createContext(null); + +export interface RootProps { + children?: ReactNode | undefined; +} + +export const Root = ({ children }: RootProps) => { + const [ctx] = useState(() => new RootContext()); + + return ( + + {children} + + ); +}; + +export function useRoot(): TgpuRoot { + const context = useContext(rootContext) ?? globalRootContextValue; + + const maybeRoot = context.initOrGetRoot(); + return maybeRoot instanceof Promise ? use(maybeRoot) : maybeRoot; +} diff --git a/packages/typegpu-react/src/useFrame.ts b/packages/typegpu-react/src/use-frame.ts similarity index 100% rename from packages/typegpu-react/src/useFrame.ts rename to packages/typegpu-react/src/use-frame.ts diff --git a/packages/typegpu-react/src/use-render.ts b/packages/typegpu-react/src/use-render.ts new file mode 100644 index 000000000..fdbbe45e2 --- /dev/null +++ b/packages/typegpu-react/src/use-render.ts @@ -0,0 +1,86 @@ +import * as d from 'typegpu/data'; +import tgpu from 'typegpu'; +import { useRoot } from './root-context.tsx'; +import { useMemo, useRef } from 'react'; +import { useFrame } from './use-frame.ts'; + +type InferRecord = { + [K in keyof T]: d.Infer; +}; + +export interface UseRenderOptions { + vertex?: () => void; + + /** + * A kernel function that runs per-pixel on the GPU. + */ + fragment: (input: InferRecord) => d.v4f; +} + +const DefaultVarying = { + uv: d.vec2f, +}; + +const fullScreenTriangle = tgpu['~unstable'].vertexFn({ + in: { vertexIndex: d.builtin.vertexIndex }, + out: { pos: d.builtin.position, ...DefaultVarying }, +})((input) => { + const pos = [d.vec2f(-1, -1), d.vec2f(3, -1), d.vec2f(-1, 3)]; + const uv = [d.vec2f(0, 1), d.vec2f(2, 1), d.vec2f(0, -1)]; + + return { + pos: d.vec4f(pos[input.vertexIndex] as d.v2f, 0, 1), + uv: uv[input.vertexIndex] as d.v2f, + }; +}); + +const presentationFormat = navigator.gpu.getPreferredCanvasFormat(); + +export function useRender(options: UseRenderOptions) { + const ref = useRef(null); + const ctxRef = useRef(null); + const root = useRoot(); + + // Only considering the first passed-in fragment function. + // This assumes that users won't swap shaders in the same useRender call, + // but we can make this more robust by computing a hash with unplugin-typegpu. + // TODO: You can also use the React Nook trick to track functions based on their + // place in the code. Simpler and more reliable? ((x)=>x)`` + const fragmentRef = useRef(options.fragment); + + const fragmentFn = useMemo(() => { + return tgpu['~unstable'].fragmentFn({ + in: { ...DefaultVarying }, + out: d.vec4f, + })(fragmentRef.current); + }, []); + + const pipeline = useMemo(() => { + return root['~unstable'] + .withVertex(fullScreenTriangle, {}) + .withFragment(fragmentFn, { format: presentationFormat }) + .createPipeline(); + }, [root, fragmentFn]); + + useFrame(() => { + const canvas = ref.current; + if (!canvas) return; + if (ctxRef.current === null) { + ctxRef.current = canvas.getContext('webgpu') as GPUCanvasContext; + ctxRef.current.configure({ + device: root.device, + format: presentationFormat, + }); + } + + pipeline + .withColorAttachment({ + view: ctxRef.current.getCurrentTexture().createView(), + loadOp: 'load', + storeOp: 'store', + }) + .draw(3); + }); + + return { ref }; +} diff --git a/packages/typegpu-react/src/use-uniform-value.ts b/packages/typegpu-react/src/use-uniform-value.ts new file mode 100644 index 000000000..6d4c4bcc7 --- /dev/null +++ b/packages/typegpu-react/src/use-uniform-value.ts @@ -0,0 +1,13 @@ +import type * as d from 'typegpu/data'; + +interface UniformValue> { + schema: TSchema; + value: TValue; +} + +export function useUniformValue>( + schema: d.AnyWgslData, + initialValue?: TValue | undefined, +): UniformValue { + // TODO: Implement +} diff --git a/packages/typegpu-react/src/useRender.ts b/packages/typegpu-react/src/useRender.ts deleted file mode 100644 index 9be666b11..000000000 --- a/packages/typegpu-react/src/useRender.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function useRender() { - // TODO: Implement -} diff --git a/packages/typegpu-react/src/useUniformValue.ts b/packages/typegpu-react/src/useUniformValue.ts deleted file mode 100644 index 02e76794f..000000000 --- a/packages/typegpu-react/src/useUniformValue.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function useUniformValue() { - // TODO: Implement -} diff --git a/packages/typegpu-react/tsconfig.json b/packages/typegpu-react/tsconfig.json index 5f257dc0f..d503ef3ff 100644 --- a/packages/typegpu-react/tsconfig.json +++ b/packages/typegpu-react/tsconfig.json @@ -1,5 +1,8 @@ { "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx" + }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 677a04ffa..b279ce343 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -518,15 +518,15 @@ importers: packages/typegpu-react: dependencies: react: - specifier: ^18.0.0 - version: 18.3.1 + specifier: ^19.0.0 + version: 19.1.0 devDependencies: '@typegpu/tgpu-dev-cli': specifier: workspace:* version: link:../tgpu-dev-cli '@types/react': - specifier: ^18.0.0 - version: 18.3.24 + specifier: ^19.0.0 + version: 19.1.8 '@webgpu/types': specifier: catalog:types version: 0.1.63 @@ -2756,17 +2756,11 @@ packages: '@types/picomatch@4.0.1': resolution: {integrity: sha512-dLqxmi5VJRC9XTvc/oaTtk+bDb4RRqxLZPZ3jIpYBHEnDXX8lu02w2yWI6NsPPsELuVK298Z2iR8jgoWKRdUVQ==} - '@types/prop-types@15.7.15': - resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/react-dom@19.1.6': resolution: {integrity: sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==} peerDependencies: '@types/react': ^19.0.0 - '@types/react@18.3.24': - resolution: {integrity: sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==} - '@types/react@19.1.8': resolution: {integrity: sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==} @@ -4374,10 +4368,6 @@ packages: longest-streak@3.1.0: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - loupe@3.1.4: resolution: {integrity: sha512-wJzkKwJrheKtknCOKNEtDK4iqg/MxmZheEMtSTYvnzRdEYaZzmgH976nenp8WdJRdx5Vc1X/9MO0Oszl6ezeXg==} @@ -5299,10 +5289,6 @@ packages: '@types/react': optional: true - react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - react@19.1.0: resolution: {integrity: sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==} engines: {node: '>=0.10.0'} @@ -8530,17 +8516,10 @@ snapshots: '@types/picomatch@4.0.1': {} - '@types/prop-types@15.7.15': {} - '@types/react-dom@19.1.6(@types/react@19.1.8)': dependencies: '@types/react': 19.1.8 - '@types/react@18.3.24': - dependencies: - '@types/prop-types': 15.7.15 - csstype: 3.1.3 - '@types/react@19.1.8': dependencies: csstype: 3.1.3 @@ -10481,10 +10460,6 @@ snapshots: longest-streak@3.1.0: {} - loose-envify@1.4.0: - dependencies: - js-tokens: 4.0.0 - loupe@3.1.4: {} lru-cache@10.4.3: {} @@ -11687,10 +11662,6 @@ snapshots: optionalDependencies: '@types/react': 19.1.8 - react@18.3.1: - dependencies: - loose-envify: 1.4.0 - react@19.1.0: {} readable-stream@3.6.2: From 61ab04f61002024656f5f593fd4be3e781eeb7d4 Mon Sep 17 00:00:00 2001 From: Sebastian Piaskowy <86687829+piaccho@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:06:28 +0200 Subject: [PATCH 4/6] feat(@typegpu/react): Implement useUniformValue hook (#1694) --- .../examples/react/triangle/index.html | 2 +- .../content/examples/react/triangle/index.tsx | 22 ++++--- apps/typegpu-docs/vitest.config.mts | 4 +- .../typegpu-react/src/use-uniform-value.ts | 57 +++++++++++++++++-- 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.html b/apps/typegpu-docs/src/content/examples/react/triangle/index.html index 2efc24ac5..974ed97c0 100644 --- a/apps/typegpu-docs/src/content/examples/react/triangle/index.html +++ b/apps/typegpu-docs/src/content/examples/react/triangle/index.html @@ -1 +1 @@ -
+
diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx index ab1a8c6e8..8401cea97 100644 --- a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx +++ b/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx @@ -1,17 +1,23 @@ -import { vec4f } from 'typegpu/data'; -import { useRender } from '@typegpu/react'; +import * as d from 'typegpu/data'; +import { useFrame, useRender, useUniformValue } from '@typegpu/react'; +import { hsvToRgb } from '@typegpu/color'; function App() { + const time = useUniformValue(d.f32, 0); + + useFrame(() => { + time.value = performance.now() / 1000; + }); + const { ref } = useRender({ - fragment: ({ uv }) => { + fragment: () => { 'kernel'; - return vec4f(uv.x, uv.y, 1, 1); + const t = time.$; + const rgb = hsvToRgb(d.vec3f(t * 0.5, 1, 1)); + return d.vec4f(rgb, 1); }, }); - // TODO: Provide a time variable to the shader with useUniformValue - // TODO: Make the gradient shift colors over time using hsvToRgb from @typegpu/color - return (
@@ -28,7 +34,7 @@ const reactRoot = createRoot( reactRoot.render(); export function onCleanup() { - reactRoot.unmount(); + setTimeout(() => reactRoot.unmount(), 0); } // #endregion diff --git a/apps/typegpu-docs/vitest.config.mts b/apps/typegpu-docs/vitest.config.mts index f8fe6776e..bd7dc9541 100644 --- a/apps/typegpu-docs/vitest.config.mts +++ b/apps/typegpu-docs/vitest.config.mts @@ -1,5 +1,5 @@ import { createJiti } from 'jiti'; -import { defineConfig } from 'vitest/config'; +import { defineConfig, type Plugin } from 'vitest/config'; import { imagetools } from 'vite-imagetools'; import type TypeGPUPlugin from 'unplugin-typegpu/vite'; @@ -13,7 +13,7 @@ export default defineConfig({ plugins: [ typegpu({ include: [/\.m?[jt]sx?/] }), /** @type {any} */ imagetools(), - ], + ] as Plugin[], server: { proxy: { '/TypeGPU': { diff --git a/packages/typegpu-react/src/use-uniform-value.ts b/packages/typegpu-react/src/use-uniform-value.ts index 6d4c4bcc7..752d86690 100644 --- a/packages/typegpu-react/src/use-uniform-value.ts +++ b/packages/typegpu-react/src/use-uniform-value.ts @@ -1,13 +1,62 @@ import type * as d from 'typegpu/data'; +import { useRoot } from './root-context.tsx'; +import { useEffect, useMemo, useRef, useState } from 'react'; +import type { ValidateUniformSchema } from 'typegpu'; interface UniformValue> { schema: TSchema; - value: TValue; + value: TValue | undefined; + readonly $: d.InferGPU; } -export function useUniformValue>( - schema: d.AnyWgslData, +export function useUniformValue< + TSchema extends d.AnyWgslData, + TValue extends d.Infer, +>( + schema: ValidateUniformSchema, initialValue?: TValue | undefined, ): UniformValue { - // TODO: Implement + const root = useRoot(); + + const [uniformBuffer] = useState(() => { + return root.createUniform( + schema, + initialValue, + ); + }); + + const cleanupRef = useRef | null>(null); + useEffect(() => { + if (cleanupRef.current) { + clearTimeout(cleanupRef.current); + } + + return () => { + cleanupRef.current = setTimeout(() => { + uniformBuffer.buffer.destroy(); + }, 200); + }; + }, [uniformBuffer]); + + // biome-ignore lint/correctness/useExhaustiveDependencies: This value needs to be stable + const uniformValue = useMemo(() => { + let currentValue = initialValue; + return { + schema, + get value() { + return currentValue; + }, + set value(newValue: TValue | undefined) { + currentValue = newValue; + if (newValue !== undefined) { + uniformBuffer.write(newValue); + } + }, + get $() { + return uniformBuffer.$; + }, + }; + }, []); + + return uniformValue as UniformValue; } From c574ca5dabff522e620097a08e702b0839d84bbb Mon Sep 17 00:00:00 2001 From: Iwo Plaza Date: Tue, 16 Sep 2025 21:46:43 +0200 Subject: [PATCH 5/6] Use callable schemas for initial value --- .../typegpu-react/src/use-uniform-value.ts | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/typegpu-react/src/use-uniform-value.ts b/packages/typegpu-react/src/use-uniform-value.ts index 752d86690..9330c47f3 100644 --- a/packages/typegpu-react/src/use-uniform-value.ts +++ b/packages/typegpu-react/src/use-uniform-value.ts @@ -5,10 +5,20 @@ import type { ValidateUniformSchema } from 'typegpu'; interface UniformValue> { schema: TSchema; - value: TValue | undefined; + value: TValue; readonly $: d.InferGPU; } +function initialValueFromSchema( + schema: ValidateUniformSchema, +): d.Infer { + if (typeof schema !== 'function') { + throw new Error('Cannot use a non-callable schema with `useUniformValue`'); + } + + return schema() as d.Infer; +} + export function useUniformValue< TSchema extends d.AnyWgslData, TValue extends d.Infer, @@ -40,17 +50,15 @@ export function useUniformValue< // biome-ignore lint/correctness/useExhaustiveDependencies: This value needs to be stable const uniformValue = useMemo(() => { - let currentValue = initialValue; + let currentValue = initialValue ?? initialValueFromSchema(schema) as TValue; return { schema, get value() { return currentValue; }, - set value(newValue: TValue | undefined) { + set value(newValue: TValue) { currentValue = newValue; - if (newValue !== undefined) { - uniformBuffer.write(newValue); - } + uniformBuffer.write(newValue); }, get $() { return uniformBuffer.$; From 64e3b9ee084d7232a85dfdcfcecfb6a363249216 Mon Sep 17 00:00:00 2001 From: Iwo Plaza Date: Tue, 16 Sep 2025 21:53:37 +0200 Subject: [PATCH 6/6] Move example to appropriate place --- .../examples/react/triangle/index.html | 0 .../{content => }/examples/react/triangle/index.tsx | 0 .../{content => }/examples/react/triangle/meta.json | 0 .../examples/react/triangle/thumbnail.png | Bin .../src/examples/tests/tgsl-parsing-test/index.html | 2 +- 5 files changed, 1 insertion(+), 1 deletion(-) rename apps/typegpu-docs/src/{content => }/examples/react/triangle/index.html (100%) rename apps/typegpu-docs/src/{content => }/examples/react/triangle/index.tsx (100%) rename apps/typegpu-docs/src/{content => }/examples/react/triangle/meta.json (100%) rename apps/typegpu-docs/src/{content => }/examples/react/triangle/thumbnail.png (100%) diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.html b/apps/typegpu-docs/src/examples/react/triangle/index.html similarity index 100% rename from apps/typegpu-docs/src/content/examples/react/triangle/index.html rename to apps/typegpu-docs/src/examples/react/triangle/index.html diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/index.tsx b/apps/typegpu-docs/src/examples/react/triangle/index.tsx similarity index 100% rename from apps/typegpu-docs/src/content/examples/react/triangle/index.tsx rename to apps/typegpu-docs/src/examples/react/triangle/index.tsx diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/meta.json b/apps/typegpu-docs/src/examples/react/triangle/meta.json similarity index 100% rename from apps/typegpu-docs/src/content/examples/react/triangle/meta.json rename to apps/typegpu-docs/src/examples/react/triangle/meta.json diff --git a/apps/typegpu-docs/src/content/examples/react/triangle/thumbnail.png b/apps/typegpu-docs/src/examples/react/triangle/thumbnail.png similarity index 100% rename from apps/typegpu-docs/src/content/examples/react/triangle/thumbnail.png rename to apps/typegpu-docs/src/examples/react/triangle/thumbnail.png diff --git a/apps/typegpu-docs/src/examples/tests/tgsl-parsing-test/index.html b/apps/typegpu-docs/src/examples/tests/tgsl-parsing-test/index.html index e183a8ea7..90dccfb83 100644 --- a/apps/typegpu-docs/src/examples/tests/tgsl-parsing-test/index.html +++ b/apps/typegpu-docs/src/examples/tests/tgsl-parsing-test/index.html @@ -1 +1 @@ -
Wait for the tests to finish running...
; +
Wait for the tests to finish running...
;