diff --git a/.gitignore b/.gitignore index f5396519..50316632 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,10 @@ !.yarn/sdks !.yarn/versions +# large yarn cache files (exceed GitHub 100MB limit) +.yarn/cache/@next-swc-*.zip +.yarn/cache/next-npm-*.zip + # build dist esm @@ -24,6 +28,15 @@ coverage .vitepress/cache .vitepress/dist +# next +.next + .env .DS_Store + +# claude +.claude +CLAUDE.md + +docs/ \ No newline at end of file diff --git a/.nvmrc b/.nvmrc index cf573bb7..5fadc1f6 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1,5 +1 @@ -lts/iron - -# 'iron' is the 20.x node release line -# ESLint requires Node.js >=18.18.0, >=20.9.0, or >=21.1.0 — ensure 20.9.0+ if using iron -# See: https://eslint.org/docs/latest/use/getting-started#prerequisites +v22.18.0 \ No newline at end of file diff --git a/.pnp.cjs b/.pnp.cjs index 7baf1d60..ba219d7f 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -13,13 +13,28 @@ const RAW_RUNTIME_STATE = {\ "name": "react-simplikit",\ "reference": "workspace:."\ + },\ + {\ + "name": "with-nextjs",\ + "reference": "workspace:examples/with-nextjs"\ + },\ + {\ + "name": "with-vite",\ + "reference": "workspace:examples/with-vite"\ + },\ + {\ + "name": "@react-simplikit/mobile",\ + "reference": "workspace:packages/mobile"\ }\ ],\ "enableTopLevelFallback": true,\ "ignorePatternData": "(^(?:\\\\.yarn\\\\/sdks(?:\\\\/(?!\\\\.{1,2}(?:\\\\/|$))(?:(?:(?!(?:^|\\\\/)\\\\.{1,2}(?:\\\\/|$)).)*?)|$))$)",\ "pnpZipBackend": "libzip",\ "fallbackExclusionList": [\ - ["react-simplikit", ["workspace:."]]\ + ["@react-simplikit/mobile", ["virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#workspace:packages/mobile", "workspace:packages/mobile"]],\ + ["react-simplikit", ["workspace:."]],\ + ["with-nextjs", ["workspace:examples/with-nextjs"]],\ + ["with-vite", ["workspace:examples/with-vite"]]\ ],\ "fallbackPool": [\ ],\ @@ -380,6 +395,49 @@ const RAW_RUNTIME_STATE = ["picocolors", "npm:1.1.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-code-frame-npm-7.27.1-4dbcabb137-5dd9a18baa.zip/node_modules/@babel/code-frame/",\ + "packageDependencies": [\ + ["@babel/code-frame", "npm:7.27.1"],\ + ["@babel/helper-validator-identifier", "npm:7.28.5"],\ + ["js-tokens", "npm:4.0.0"],\ + ["picocolors", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/compat-data", [\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-compat-data-npm-7.28.5-41f8d327e8-702a25de73.zip/node_modules/@babel/compat-data/",\ + "packageDependencies": [\ + ["@babel/compat-data", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/core", [\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-core-npm-7.28.5-cd68c2d8db-535f822380.zip/node_modules/@babel/core/",\ + "packageDependencies": [\ + ["@babel/code-frame", "npm:7.27.1"],\ + ["@babel/core", "npm:7.28.5"],\ + ["@babel/generator", "npm:7.28.5"],\ + ["@babel/helper-compilation-targets", "npm:7.27.2"],\ + ["@babel/helper-module-transforms", "virtual:cd68c2d8dbe5140515f0d84027dc2f70623ef123c1ed0705293b830925f9fd53fba46ca9553905fee18e47994c7349977bfffe0887f5df2ef5d1d9ded216f039#npm:7.28.3"],\ + ["@babel/helpers", "npm:7.28.4"],\ + ["@babel/parser", "npm:7.28.5"],\ + ["@babel/template", "npm:7.27.2"],\ + ["@babel/traverse", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"],\ + ["@jridgewell/remapping", "npm:2.3.5"],\ + ["convert-source-map", "npm:2.0.0"],\ + ["debug", "virtual:cd68c2d8dbe5140515f0d84027dc2f70623ef123c1ed0705293b830925f9fd53fba46ca9553905fee18e47994c7349977bfffe0887f5df2ef5d1d9ded216f039#npm:4.4.3"],\ + ["gensync", "npm:1.0.0-beta.2"],\ + ["json5", "npm:2.2.3"],\ + ["semver", "npm:6.3.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/generator", [\ @@ -394,6 +452,86 @@ const RAW_RUNTIME_STATE = ["jsesc", "npm:3.1.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-generator-npm-7.28.5-fd8f3ae6b1-9f219fe1d5.zip/node_modules/@babel/generator/",\ + "packageDependencies": [\ + ["@babel/generator", "npm:7.28.5"],\ + ["@babel/parser", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"],\ + ["@jridgewell/gen-mapping", "npm:0.3.13"],\ + ["@jridgewell/trace-mapping", "npm:0.3.31"],\ + ["jsesc", "npm:3.1.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/helper-compilation-targets", [\ + ["npm:7.27.2", {\ + "packageLocation": "./.yarn/cache/@babel-helper-compilation-targets-npm-7.27.2-111dda04b6-f338fa00dc.zip/node_modules/@babel/helper-compilation-targets/",\ + "packageDependencies": [\ + ["@babel/compat-data", "npm:7.28.5"],\ + ["@babel/helper-compilation-targets", "npm:7.27.2"],\ + ["@babel/helper-validator-option", "npm:7.27.1"],\ + ["browserslist", "npm:4.28.1"],\ + ["lru-cache", "npm:5.1.1"],\ + ["semver", "npm:6.3.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/helper-globals", [\ + ["npm:7.28.0", {\ + "packageLocation": "./.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-5a0cd0c0e8.zip/node_modules/@babel/helper-globals/",\ + "packageDependencies": [\ + ["@babel/helper-globals", "npm:7.28.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/helper-module-imports", [\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-helper-module-imports-npm-7.27.1-3bf33978f4-e00aace096.zip/node_modules/@babel/helper-module-imports/",\ + "packageDependencies": [\ + ["@babel/helper-module-imports", "npm:7.27.1"],\ + ["@babel/traverse", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/helper-module-transforms", [\ + ["npm:7.28.3", {\ + "packageLocation": "./.yarn/cache/@babel-helper-module-transforms-npm-7.28.3-7b69ec189a-549be62515.zip/node_modules/@babel/helper-module-transforms/",\ + "packageDependencies": [\ + ["@babel/helper-module-transforms", "npm:7.28.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:cd68c2d8dbe5140515f0d84027dc2f70623ef123c1ed0705293b830925f9fd53fba46ca9553905fee18e47994c7349977bfffe0887f5df2ef5d1d9ded216f039#npm:7.28.3", {\ + "packageLocation": "./.yarn/__virtual__/@babel-helper-module-transforms-virtual-613b6112f1/0/cache/@babel-helper-module-transforms-npm-7.28.3-7b69ec189a-549be62515.zip/node_modules/@babel/helper-module-transforms/",\ + "packageDependencies": [\ + ["@babel/core", "npm:7.28.5"],\ + ["@babel/helper-module-imports", "npm:7.27.1"],\ + ["@babel/helper-module-transforms", "virtual:cd68c2d8dbe5140515f0d84027dc2f70623ef123c1ed0705293b830925f9fd53fba46ca9553905fee18e47994c7349977bfffe0887f5df2ef5d1d9ded216f039#npm:7.28.3"],\ + ["@babel/helper-validator-identifier", "npm:7.28.5"],\ + ["@babel/traverse", "npm:7.28.5"],\ + ["@types/babel__core", null]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@types/babel__core"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/helper-plugin-utils", [\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-helper-plugin-utils-npm-7.27.1-4f91e7999b-94cf22c81a.zip/node_modules/@babel/helper-plugin-utils/",\ + "packageDependencies": [\ + ["@babel/helper-plugin-utils", "npm:7.27.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-string-parser", [\ @@ -403,6 +541,13 @@ const RAW_RUNTIME_STATE = ["@babel/helper-string-parser", "npm:7.25.9"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-8bda3448e0.zip/node_modules/@babel/helper-string-parser/",\ + "packageDependencies": [\ + ["@babel/helper-string-parser", "npm:7.27.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/helper-validator-identifier", [\ @@ -412,6 +557,33 @@ const RAW_RUNTIME_STATE = ["@babel/helper-validator-identifier", "npm:7.25.9"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-42aaebed91.zip/node_modules/@babel/helper-validator-identifier/",\ + "packageDependencies": [\ + ["@babel/helper-validator-identifier", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/helper-validator-option", [\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-6fec5f006e.zip/node_modules/@babel/helper-validator-option/",\ + "packageDependencies": [\ + ["@babel/helper-validator-option", "npm:7.27.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/helpers", [\ + ["npm:7.28.4", {\ + "packageLocation": "./.yarn/cache/@babel-helpers-npm-7.28.4-d9f7567704-aaa5fb8098.zip/node_modules/@babel/helpers/",\ + "packageDependencies": [\ + ["@babel/helpers", "npm:7.28.4"],\ + ["@babel/template", "npm:7.27.2"],\ + ["@babel/types", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/parser", [\ @@ -422,6 +594,60 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.27.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-parser-npm-7.28.5-f2345a6b62-5bbe48bf2c.zip/node_modules/@babel/parser/",\ + "packageDependencies": [\ + ["@babel/parser", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/plugin-transform-react-jsx-self", [\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-plugin-transform-react-jsx-self-npm-7.27.1-bd0fa344f1-00a4f917b7.zip/node_modules/@babel/plugin-transform-react-jsx-self/",\ + "packageDependencies": [\ + ["@babel/plugin-transform-react-jsx-self", "npm:7.27.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:a63355dca4fbc96fc1c4d4bfd9dc8483babadd47b7d586115e666cbff0d3f16de70d6f129ba88c43e008e51a9a4dc7744f7355fa96c40977d849c701bf3b8adf#npm:7.27.1", {\ + "packageLocation": "./.yarn/__virtual__/@babel-plugin-transform-react-jsx-self-virtual-abb00be27d/0/cache/@babel-plugin-transform-react-jsx-self-npm-7.27.1-bd0fa344f1-00a4f917b7.zip/node_modules/@babel/plugin-transform-react-jsx-self/",\ + "packageDependencies": [\ + ["@babel/core", "npm:7.28.5"],\ + ["@babel/helper-plugin-utils", "npm:7.27.1"],\ + ["@babel/plugin-transform-react-jsx-self", "virtual:a63355dca4fbc96fc1c4d4bfd9dc8483babadd47b7d586115e666cbff0d3f16de70d6f129ba88c43e008e51a9a4dc7744f7355fa96c40977d849c701bf3b8adf#npm:7.27.1"],\ + ["@types/babel__core", "npm:7.20.5"]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@types/babel__core"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@babel/plugin-transform-react-jsx-source", [\ + ["npm:7.27.1", {\ + "packageLocation": "./.yarn/cache/@babel-plugin-transform-react-jsx-source-npm-7.27.1-36a9716d8f-5e67b56c39.zip/node_modules/@babel/plugin-transform-react-jsx-source/",\ + "packageDependencies": [\ + ["@babel/plugin-transform-react-jsx-source", "npm:7.27.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:a63355dca4fbc96fc1c4d4bfd9dc8483babadd47b7d586115e666cbff0d3f16de70d6f129ba88c43e008e51a9a4dc7744f7355fa96c40977d849c701bf3b8adf#npm:7.27.1", {\ + "packageLocation": "./.yarn/__virtual__/@babel-plugin-transform-react-jsx-source-virtual-4e439ac411/0/cache/@babel-plugin-transform-react-jsx-source-npm-7.27.1-36a9716d8f-5e67b56c39.zip/node_modules/@babel/plugin-transform-react-jsx-source/",\ + "packageDependencies": [\ + ["@babel/core", "npm:7.28.5"],\ + ["@babel/helper-plugin-utils", "npm:7.27.1"],\ + ["@babel/plugin-transform-react-jsx-source", "virtual:a63355dca4fbc96fc1c4d4bfd9dc8483babadd47b7d586115e666cbff0d3f16de70d6f129ba88c43e008e51a9a4dc7744f7355fa96c40977d849c701bf3b8adf#npm:7.27.1"],\ + ["@types/babel__core", "npm:7.20.5"]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@types/babel__core"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/runtime", [\ @@ -451,6 +677,16 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.27.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.27.2", {\ + "packageLocation": "./.yarn/cache/@babel-template-npm-7.27.2-77e67eabbd-ed9e902265.zip/node_modules/@babel/template/",\ + "packageDependencies": [\ + ["@babel/code-frame", "npm:7.27.1"],\ + ["@babel/parser", "npm:7.28.5"],\ + ["@babel/template", "npm:7.27.2"],\ + ["@babel/types", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/traverse", [\ @@ -467,6 +703,20 @@ const RAW_RUNTIME_STATE = ["globals", "npm:11.12.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-traverse-npm-7.28.5-2b51d83636-f6c4a59599.zip/node_modules/@babel/traverse/",\ + "packageDependencies": [\ + ["@babel/code-frame", "npm:7.27.1"],\ + ["@babel/generator", "npm:7.28.5"],\ + ["@babel/helper-globals", "npm:7.28.0"],\ + ["@babel/parser", "npm:7.28.5"],\ + ["@babel/template", "npm:7.27.2"],\ + ["@babel/traverse", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"],\ + ["debug", "virtual:643ed7cc338bcf145a82d8b05b3bef6bcf150ca545df386225596f10ce53cc90b88b3ca83e348ade1ccea5f3f8e76c92d2f0e2ba544da60d40aff9921c56872d#npm:4.4.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@babel/types", [\ @@ -478,6 +728,15 @@ const RAW_RUNTIME_STATE = ["@babel/types", "npm:7.27.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.28.5", {\ + "packageLocation": "./.yarn/cache/@babel-types-npm-7.28.5-582d7cca8a-a5a483d210.zip/node_modules/@babel/types/",\ + "packageDependencies": [\ + ["@babel/helper-string-parser", "npm:7.27.1"],\ + ["@babel/helper-validator-identifier", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@bcoe/v8-coverage", [\ @@ -911,6 +1170,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@emnapi/runtime", [\ + ["npm:1.8.1", {\ + "packageLocation": "./.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-f4929d75e3.zip/node_modules/@emnapi/runtime/",\ + "packageDependencies": [\ + ["@emnapi/runtime", "npm:1.8.1"],\ + ["tslib", "npm:2.8.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@esbuild/aix-ppc64", [\ ["npm:0.21.5", {\ "packageLocation": "./.yarn/unplugged/@esbuild-aix-ppc64-npm-0.21.5-ebeb42da03/node_modules/@esbuild/aix-ppc64/",\ @@ -932,6 +1201,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/aix-ppc64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-aix-ppc64-npm-0.27.2-345b18ab38/node_modules/@esbuild/aix-ppc64/",\ + "packageDependencies": [\ + ["@esbuild/aix-ppc64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/android-arm", [\ @@ -955,6 +1231,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/android-arm", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-android-arm-npm-0.27.2-b9ce8adb94/node_modules/@esbuild/android-arm/",\ + "packageDependencies": [\ + ["@esbuild/android-arm", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/android-arm64", [\ @@ -978,6 +1261,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/android-arm64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-android-arm64-npm-0.27.2-15df2cdd67/node_modules/@esbuild/android-arm64/",\ + "packageDependencies": [\ + ["@esbuild/android-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/android-x64", [\ @@ -1001,6 +1291,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/android-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-android-x64-npm-0.27.2-66d99a6933/node_modules/@esbuild/android-x64/",\ + "packageDependencies": [\ + ["@esbuild/android-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/darwin-arm64", [\ @@ -1024,6 +1321,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/darwin-arm64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521/node_modules/@esbuild/darwin-arm64/",\ + "packageDependencies": [\ + ["@esbuild/darwin-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/darwin-x64", [\ @@ -1047,6 +1351,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/darwin-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-darwin-x64-npm-0.27.2-ae63bf405f/node_modules/@esbuild/darwin-x64/",\ + "packageDependencies": [\ + ["@esbuild/darwin-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/freebsd-arm64", [\ @@ -1070,6 +1381,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/freebsd-arm64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-freebsd-arm64-npm-0.27.2-e37daed3be/node_modules/@esbuild/freebsd-arm64/",\ + "packageDependencies": [\ + ["@esbuild/freebsd-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/freebsd-x64", [\ @@ -1093,6 +1411,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/freebsd-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-freebsd-x64-npm-0.27.2-4cb2e19a78/node_modules/@esbuild/freebsd-x64/",\ + "packageDependencies": [\ + ["@esbuild/freebsd-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-arm", [\ @@ -1116,6 +1441,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-arm", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-arm-npm-0.27.2-43d77dd61a/node_modules/@esbuild/linux-arm/",\ + "packageDependencies": [\ + ["@esbuild/linux-arm", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-arm64", [\ @@ -1139,6 +1471,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-arm64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-arm64-npm-0.27.2-bf1b0979ac/node_modules/@esbuild/linux-arm64/",\ + "packageDependencies": [\ + ["@esbuild/linux-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-ia32", [\ @@ -1162,6 +1501,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-ia32", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-ia32-npm-0.27.2-9e57150846/node_modules/@esbuild/linux-ia32/",\ + "packageDependencies": [\ + ["@esbuild/linux-ia32", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-loong64", [\ @@ -1185,6 +1531,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-loong64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-loong64-npm-0.27.2-a322ec9c1d/node_modules/@esbuild/linux-loong64/",\ + "packageDependencies": [\ + ["@esbuild/linux-loong64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-mips64el", [\ @@ -1208,6 +1561,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-mips64el", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-mips64el-npm-0.27.2-9b26d4ee73/node_modules/@esbuild/linux-mips64el/",\ + "packageDependencies": [\ + ["@esbuild/linux-mips64el", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-ppc64", [\ @@ -1231,6 +1591,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-ppc64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-ppc64-npm-0.27.2-28d849768e/node_modules/@esbuild/linux-ppc64/",\ + "packageDependencies": [\ + ["@esbuild/linux-ppc64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-riscv64", [\ @@ -1254,6 +1621,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-riscv64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-riscv64-npm-0.27.2-73c96cf77f/node_modules/@esbuild/linux-riscv64/",\ + "packageDependencies": [\ + ["@esbuild/linux-riscv64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-s390x", [\ @@ -1277,6 +1651,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-s390x", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-s390x-npm-0.27.2-1b2065e648/node_modules/@esbuild/linux-s390x/",\ + "packageDependencies": [\ + ["@esbuild/linux-s390x", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/linux-x64", [\ @@ -1300,6 +1681,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/linux-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db/node_modules/@esbuild/linux-x64/",\ + "packageDependencies": [\ + ["@esbuild/linux-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/netbsd-arm64", [\ @@ -1316,6 +1704,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/netbsd-arm64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-netbsd-arm64-npm-0.27.2-dd6c103966/node_modules/@esbuild/netbsd-arm64/",\ + "packageDependencies": [\ + ["@esbuild/netbsd-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/netbsd-x64", [\ @@ -1339,6 +1734,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/netbsd-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-netbsd-x64-npm-0.27.2-1e03e8a7a5/node_modules/@esbuild/netbsd-x64/",\ + "packageDependencies": [\ + ["@esbuild/netbsd-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/openbsd-arm64", [\ @@ -1355,6 +1757,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/openbsd-arm64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-openbsd-arm64-npm-0.27.2-1d7a76cae4/node_modules/@esbuild/openbsd-arm64/",\ + "packageDependencies": [\ + ["@esbuild/openbsd-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/openbsd-x64", [\ @@ -1378,6 +1787,22 @@ const RAW_RUNTIME_STATE = ["@esbuild/openbsd-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-openbsd-x64-npm-0.27.2-27238acba8/node_modules/@esbuild/openbsd-x64/",\ + "packageDependencies": [\ + ["@esbuild/openbsd-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@esbuild/openharmony-arm64", [\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-openharmony-arm64-npm-0.27.2-b815985320/node_modules/@esbuild/openharmony-arm64/",\ + "packageDependencies": [\ + ["@esbuild/openharmony-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/sunos-x64", [\ @@ -1401,6 +1826,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/sunos-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-sunos-x64-npm-0.27.2-fb3c4c523d/node_modules/@esbuild/sunos-x64/",\ + "packageDependencies": [\ + ["@esbuild/sunos-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/win32-arm64", [\ @@ -1424,6 +1856,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/win32-arm64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-win32-arm64-npm-0.27.2-78a0e828ec/node_modules/@esbuild/win32-arm64/",\ + "packageDependencies": [\ + ["@esbuild/win32-arm64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/win32-ia32", [\ @@ -1447,6 +1886,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/win32-ia32", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-win32-ia32-npm-0.27.2-f7488076af/node_modules/@esbuild/win32-ia32/",\ + "packageDependencies": [\ + ["@esbuild/win32-ia32", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@esbuild/win32-x64", [\ @@ -1470,6 +1916,13 @@ const RAW_RUNTIME_STATE = ["@esbuild/win32-x64", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/@esbuild-win32-x64-npm-0.27.2-fb03408001/node_modules/@esbuild/win32-x64/",\ + "packageDependencies": [\ + ["@esbuild/win32-x64", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@eslint-community/eslint-utils", [\ @@ -1654,6 +2107,242 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@img/colour", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/@img-colour-npm-1.0.0-964a21c987-02261719c1.zip/node_modules/@img/colour/",\ + "packageDependencies": [\ + ["@img/colour", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-darwin-arm64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-darwin-arm64-npm-0.34.5-5cc67024f5/node_modules/@img/sharp-darwin-arm64/",\ + "packageDependencies": [\ + ["@img/sharp-darwin-arm64", "npm:0.34.5"],\ + ["@img/sharp-libvips-darwin-arm64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-darwin-x64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-darwin-x64-npm-0.34.5-86b67542ce/node_modules/@img/sharp-darwin-x64/",\ + "packageDependencies": [\ + ["@img/sharp-darwin-x64", "npm:0.34.5"],\ + ["@img/sharp-libvips-darwin-x64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-darwin-arm64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-darwin-arm64-npm-1.2.4-09e109d5ab/node_modules/@img/sharp-libvips-darwin-arm64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-darwin-arm64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-darwin-x64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-darwin-x64-npm-1.2.4-8eefe980b0/node_modules/@img/sharp-libvips-darwin-x64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-darwin-x64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linux-arm", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linux-arm-npm-1.2.4-b54afd61bd/node_modules/@img/sharp-libvips-linux-arm/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-arm", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linux-arm64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linux-arm64-npm-1.2.4-df7b9ebec3/node_modules/@img/sharp-libvips-linux-arm64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-arm64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linux-ppc64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linux-ppc64-npm-1.2.4-9f23708b41/node_modules/@img/sharp-libvips-linux-ppc64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-ppc64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linux-riscv64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linux-riscv64-npm-1.2.4-185ba3695c/node_modules/@img/sharp-libvips-linux-riscv64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-riscv64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linux-s390x", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linux-s390x-npm-1.2.4-4ab19140fd/node_modules/@img/sharp-libvips-linux-s390x/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-s390x", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linux-x64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linux-x64-npm-1.2.4-105fd6d44d/node_modules/@img/sharp-libvips-linux-x64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-x64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linuxmusl-arm64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linuxmusl-arm64-npm-1.2.4-6882b67804/node_modules/@img/sharp-libvips-linuxmusl-arm64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linuxmusl-arm64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-libvips-linuxmusl-x64", [\ + ["npm:1.2.4", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-libvips-linuxmusl-x64-npm-1.2.4-8810e87949/node_modules/@img/sharp-libvips-linuxmusl-x64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linuxmusl-x64", "npm:1.2.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linux-arm", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linux-arm-npm-0.34.5-86ee3e54c1/node_modules/@img/sharp-linux-arm/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-arm", "npm:1.2.4"],\ + ["@img/sharp-linux-arm", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linux-arm64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linux-arm64-npm-0.34.5-efb30e243a/node_modules/@img/sharp-linux-arm64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-arm64", "npm:1.2.4"],\ + ["@img/sharp-linux-arm64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linux-ppc64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linux-ppc64-npm-0.34.5-07dc7c17e0/node_modules/@img/sharp-linux-ppc64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-ppc64", "npm:1.2.4"],\ + ["@img/sharp-linux-ppc64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linux-riscv64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linux-riscv64-npm-0.34.5-10a9344074/node_modules/@img/sharp-linux-riscv64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-riscv64", "npm:1.2.4"],\ + ["@img/sharp-linux-riscv64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linux-s390x", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linux-s390x-npm-0.34.5-07a833eb3c/node_modules/@img/sharp-linux-s390x/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-s390x", "npm:1.2.4"],\ + ["@img/sharp-linux-s390x", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linux-x64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linux-x64-npm-0.34.5-06b002e5f6/node_modules/@img/sharp-linux-x64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linux-x64", "npm:1.2.4"],\ + ["@img/sharp-linux-x64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linuxmusl-arm64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linuxmusl-arm64-npm-0.34.5-ec7806d52a/node_modules/@img/sharp-linuxmusl-arm64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linuxmusl-arm64", "npm:1.2.4"],\ + ["@img/sharp-linuxmusl-arm64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-linuxmusl-x64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-linuxmusl-x64-npm-0.34.5-e1fc3b763c/node_modules/@img/sharp-linuxmusl-x64/",\ + "packageDependencies": [\ + ["@img/sharp-libvips-linuxmusl-x64", "npm:1.2.4"],\ + ["@img/sharp-linuxmusl-x64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-wasm32", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-wasm32-npm-0.34.5-4dd529dbb8/node_modules/@img/sharp-wasm32/",\ + "packageDependencies": [\ + ["@emnapi/runtime", "npm:1.8.1"],\ + ["@img/sharp-wasm32", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-win32-arm64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-win32-arm64-npm-0.34.5-bb5628280c/node_modules/@img/sharp-win32-arm64/",\ + "packageDependencies": [\ + ["@img/sharp-win32-arm64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-win32-ia32", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-win32-ia32-npm-0.34.5-9ae99ec602/node_modules/@img/sharp-win32-ia32/",\ + "packageDependencies": [\ + ["@img/sharp-win32-ia32", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@img/sharp-win32-x64", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/@img-sharp-win32-x64-npm-0.34.5-105bbc4083/node_modules/@img/sharp-win32-x64/",\ + "packageDependencies": [\ + ["@img/sharp-win32-x64", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@inquirer/external-editor", [\ ["npm:1.0.2", {\ "packageLocation": "./.yarn/cache/@inquirer-external-editor-npm-1.0.2-389c6568ea-414a3a2a97.zip/node_modules/@inquirer/external-editor/",\ @@ -1720,6 +2409,15 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["@jridgewell/gen-mapping", [\ + ["npm:0.3.13", {\ + "packageLocation": "./.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-9a7d65fb13.zip/node_modules/@jridgewell/gen-mapping/",\ + "packageDependencies": [\ + ["@jridgewell/gen-mapping", "npm:0.3.13"],\ + ["@jridgewell/sourcemap-codec", "npm:1.5.0"],\ + ["@jridgewell/trace-mapping", "npm:0.3.25"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:0.3.8", {\ "packageLocation": "./.yarn/cache/@jridgewell-gen-mapping-npm-0.3.8-647be6e286-c668feaf86.zip/node_modules/@jridgewell/gen-mapping/",\ "packageDependencies": [\ @@ -1731,6 +2429,17 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@jridgewell/remapping", [\ + ["npm:2.3.5", {\ + "packageLocation": "./.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-3de494219f.zip/node_modules/@jridgewell/remapping/",\ + "packageDependencies": [\ + ["@jridgewell/gen-mapping", "npm:0.3.8"],\ + ["@jridgewell/remapping", "npm:2.3.5"],\ + ["@jridgewell/trace-mapping", "npm:0.3.25"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@jridgewell/resolve-uri", [\ ["npm:3.1.2", {\ "packageLocation": "./.yarn/cache/@jridgewell-resolve-uri-npm-3.1.2-5bc4245992-d502e6fb51.zip/node_modules/@jridgewell/resolve-uri/",\ @@ -1767,6 +2476,15 @@ const RAW_RUNTIME_STATE = ["@jridgewell/trace-mapping", "npm:0.3.25"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.3.31", {\ + "packageLocation": "./.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-4b30ec8cd5.zip/node_modules/@jridgewell/trace-mapping/",\ + "packageDependencies": [\ + ["@jridgewell/resolve-uri", "npm:3.1.2"],\ + ["@jridgewell/sourcemap-codec", "npm:1.5.0"],\ + ["@jridgewell/trace-mapping", "npm:0.3.31"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@manypkg/find-root", [\ @@ -1797,6 +2515,87 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@next/env", [\ + ["npm:15.5.9", {\ + "packageLocation": "./.yarn/cache/@next-env-npm-15.5.9-dcfb92230e-92c4e29d81.zip/node_modules/@next/env/",\ + "packageDependencies": [\ + ["@next/env", "npm:15.5.9"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-darwin-arm64", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-darwin-arm64-npm-15.5.7-fcd408d003/node_modules/@next/swc-darwin-arm64/",\ + "packageDependencies": [\ + ["@next/swc-darwin-arm64", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-darwin-x64", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-darwin-x64-npm-15.5.7-06eece9a9c/node_modules/@next/swc-darwin-x64/",\ + "packageDependencies": [\ + ["@next/swc-darwin-x64", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-linux-arm64-gnu", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-linux-arm64-gnu-npm-15.5.7-b1a623929b/node_modules/@next/swc-linux-arm64-gnu/",\ + "packageDependencies": [\ + ["@next/swc-linux-arm64-gnu", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-linux-arm64-musl", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-linux-arm64-musl-npm-15.5.7-27fda8742b/node_modules/@next/swc-linux-arm64-musl/",\ + "packageDependencies": [\ + ["@next/swc-linux-arm64-musl", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-linux-x64-gnu", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-linux-x64-gnu-npm-15.5.7-43740fe0d6/node_modules/@next/swc-linux-x64-gnu/",\ + "packageDependencies": [\ + ["@next/swc-linux-x64-gnu", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-linux-x64-musl", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-linux-x64-musl-npm-15.5.7-84b87ecaf5/node_modules/@next/swc-linux-x64-musl/",\ + "packageDependencies": [\ + ["@next/swc-linux-x64-musl", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-win32-arm64-msvc", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-win32-arm64-msvc-npm-15.5.7-bf2ed87e86/node_modules/@next/swc-win32-arm64-msvc/",\ + "packageDependencies": [\ + ["@next/swc-win32-arm64-msvc", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@next/swc-win32-x64-msvc", [\ + ["npm:15.5.7", {\ + "packageLocation": "./.yarn/unplugged/@next-swc-win32-x64-msvc-npm-15.5.7-ac0b4ccc34/node_modules/@next/swc-win32-x64-msvc/",\ + "packageDependencies": [\ + ["@next/swc-win32-x64-msvc", "npm:15.5.7"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@nodelib/fs.scandir", [\ ["npm:2.1.5", {\ "packageLocation": "./.yarn/cache/@nodelib-fs.scandir-npm-2.1.5-89c67370dd-732c3b6d1b.zip/node_modules/@nodelib/fs.scandir/",\ @@ -1870,6 +2669,56 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@react-simplikit/mobile", [\ + ["virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#workspace:packages/mobile", {\ + "packageLocation": "./.yarn/__virtual__/@react-simplikit-mobile-virtual-b8ca648f23/1/packages/mobile/",\ + "packageDependencies": [\ + ["@react-simplikit/mobile", "virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#workspace:packages/mobile"],\ + ["@testing-library/dom", "npm:10.4.0"],\ + ["@testing-library/jest-dom", "npm:6.6.3"],\ + ["@testing-library/react", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:16.3.0"],\ + ["@types/react", "npm:19.1.0"],\ + ["@types/react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.2"],\ + ["react", "npm:19.1.0"],\ + ["react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.0"],\ + ["rimraf", "npm:6.0.1"],\ + ["tsup", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:8.4.0"],\ + ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ + ["vitest", "virtual:b8ca648f23ac8db9e48f501f3417b5d22664f520096d4c3f324c7f27acb059637b178631fb2aa9474c5307a2c176eb80c2a4069538d26cb000262efba27773fe#npm:2.1.9"]\ + ],\ + "packagePeers": [\ + "react"\ + ],\ + "linkType": "SOFT"\ + }],\ + ["workspace:packages/mobile", {\ + "packageLocation": "./packages/mobile/",\ + "packageDependencies": [\ + ["@react-simplikit/mobile", "workspace:packages/mobile"],\ + ["@testing-library/dom", "npm:10.4.0"],\ + ["@testing-library/jest-dom", "npm:6.6.3"],\ + ["@testing-library/react", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:16.3.0"],\ + ["@types/react", "npm:19.1.0"],\ + ["@types/react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.2"],\ + ["react", "npm:19.1.0"],\ + ["react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.0"],\ + ["rimraf", "npm:6.0.1"],\ + ["tsup", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:8.4.0"],\ + ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ + ["vitest", "virtual:b8ca648f23ac8db9e48f501f3417b5d22664f520096d4c3f324c7f27acb059637b178631fb2aa9474c5307a2c176eb80c2a4069538d26cb000262efba27773fe#npm:2.1.9"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ + ["@rolldown/pluginutils", [\ + ["npm:1.0.0-beta.27", {\ + "packageLocation": "./.yarn/cache/@rolldown-pluginutils-npm-1.0.0-beta.27-108701b3b0-9658f235b3.zip/node_modules/@rolldown/pluginutils/",\ + "packageDependencies": [\ + ["@rolldown/pluginutils", "npm:1.0.0-beta.27"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@rollup/rollup-android-arm-eabi", [\ ["npm:4.39.0", {\ "packageLocation": "./.yarn/unplugged/@rollup-rollup-android-arm-eabi-npm-4.39.0-896aaf182d/node_modules/@rollup/rollup-android-arm-eabi/",\ @@ -1877,6 +2726,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-android-arm-eabi", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-android-arm-eabi-npm-4.55.1-fcd5dcd23f/node_modules/@rollup/rollup-android-arm-eabi/",\ + "packageDependencies": [\ + ["@rollup/rollup-android-arm-eabi", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-android-arm64", [\ @@ -1886,6 +2742,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-android-arm64", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-android-arm64-npm-4.55.1-ef84caf370/node_modules/@rollup/rollup-android-arm64/",\ + "packageDependencies": [\ + ["@rollup/rollup-android-arm64", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-darwin-arm64", [\ @@ -1895,6 +2758,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-darwin-arm64", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-darwin-arm64-npm-4.55.1-16138f7e16/node_modules/@rollup/rollup-darwin-arm64/",\ + "packageDependencies": [\ + ["@rollup/rollup-darwin-arm64", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-darwin-x64", [\ @@ -1904,6 +2774,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-darwin-x64", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-darwin-x64-npm-4.55.1-4fbf131c62/node_modules/@rollup/rollup-darwin-x64/",\ + "packageDependencies": [\ + ["@rollup/rollup-darwin-x64", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-freebsd-arm64", [\ @@ -1913,6 +2790,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-freebsd-arm64", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-freebsd-arm64-npm-4.55.1-b0e8c1492d/node_modules/@rollup/rollup-freebsd-arm64/",\ + "packageDependencies": [\ + ["@rollup/rollup-freebsd-arm64", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-freebsd-x64", [\ @@ -1922,6 +2806,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-freebsd-x64", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-freebsd-x64-npm-4.55.1-9172fa35a1/node_modules/@rollup/rollup-freebsd-x64/",\ + "packageDependencies": [\ + ["@rollup/rollup-freebsd-x64", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-arm-gnueabihf", [\ @@ -1931,13 +2822,27 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-arm-gnueabihf", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-arm-gnueabihf-npm-4.55.1-a4bdba0486/node_modules/@rollup/rollup-linux-arm-gnueabihf/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-arm-gnueabihf", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-arm-musleabihf", [\ ["npm:4.39.0", {\ "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-arm-musleabihf-npm-4.39.0-3a462cb95b/node_modules/@rollup/rollup-linux-arm-musleabihf/",\ "packageDependencies": [\ - ["@rollup/rollup-linux-arm-musleabihf", "npm:4.39.0"]\ + ["@rollup/rollup-linux-arm-musleabihf", "npm:4.39.0"]\ + ],\ + "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-arm-musleabihf-npm-4.55.1-e57ef0fc4f/node_modules/@rollup/rollup-linux-arm-musleabihf/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-arm-musleabihf", "npm:4.55.1"]\ ],\ "linkType": "HARD"\ }]\ @@ -1949,6 +2854,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-arm64-gnu", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-arm64-gnu-npm-4.55.1-d65df7c795/node_modules/@rollup/rollup-linux-arm64-gnu/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-arm64-gnu", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-arm64-musl", [\ @@ -1958,6 +2870,31 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-arm64-musl", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-arm64-musl-npm-4.55.1-0e3b42b0bc/node_modules/@rollup/rollup-linux-arm64-musl/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-arm64-musl", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@rollup/rollup-linux-loong64-gnu", [\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-loong64-gnu-npm-4.55.1-c98edf5ca4/node_modules/@rollup/rollup-linux-loong64-gnu/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-loong64-gnu", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@rollup/rollup-linux-loong64-musl", [\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-loong64-musl-npm-4.55.1-bc92a8e81c/node_modules/@rollup/rollup-linux-loong64-musl/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-loong64-musl", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-loongarch64-gnu", [\ @@ -1978,6 +2915,24 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@rollup/rollup-linux-ppc64-gnu", [\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-ppc64-gnu-npm-4.55.1-8ebb289534/node_modules/@rollup/rollup-linux-ppc64-gnu/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-ppc64-gnu", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@rollup/rollup-linux-ppc64-musl", [\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-ppc64-musl-npm-4.55.1-3b1eab69c1/node_modules/@rollup/rollup-linux-ppc64-musl/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-ppc64-musl", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@rollup/rollup-linux-riscv64-gnu", [\ ["npm:4.39.0", {\ "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-riscv64-gnu-npm-4.39.0-63962a47da/node_modules/@rollup/rollup-linux-riscv64-gnu/",\ @@ -1985,6 +2940,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-riscv64-gnu", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-riscv64-gnu-npm-4.55.1-f03972774c/node_modules/@rollup/rollup-linux-riscv64-gnu/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-riscv64-gnu", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-riscv64-musl", [\ @@ -1994,6 +2956,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-riscv64-musl", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-riscv64-musl-npm-4.55.1-f251574b3d/node_modules/@rollup/rollup-linux-riscv64-musl/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-riscv64-musl", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-s390x-gnu", [\ @@ -2003,6 +2972,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-s390x-gnu", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-s390x-gnu-npm-4.55.1-2b21359f12/node_modules/@rollup/rollup-linux-s390x-gnu/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-s390x-gnu", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-x64-gnu", [\ @@ -2012,6 +2988,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-x64-gnu", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-x64-gnu-npm-4.55.1-d5556ae8f7/node_modules/@rollup/rollup-linux-x64-gnu/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-x64-gnu", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-linux-x64-musl", [\ @@ -2021,6 +3004,31 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-linux-x64-musl", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-linux-x64-musl-npm-4.55.1-0f107901e9/node_modules/@rollup/rollup-linux-x64-musl/",\ + "packageDependencies": [\ + ["@rollup/rollup-linux-x64-musl", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@rollup/rollup-openbsd-x64", [\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-openbsd-x64-npm-4.55.1-a173c20402/node_modules/@rollup/rollup-openbsd-x64/",\ + "packageDependencies": [\ + ["@rollup/rollup-openbsd-x64", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@rollup/rollup-openharmony-arm64", [\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-openharmony-arm64-npm-4.55.1-4b8072ac60/node_modules/@rollup/rollup-openharmony-arm64/",\ + "packageDependencies": [\ + ["@rollup/rollup-openharmony-arm64", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-win32-arm64-msvc", [\ @@ -2030,6 +3038,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-win32-arm64-msvc", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-win32-arm64-msvc-npm-4.55.1-5c69276205/node_modules/@rollup/rollup-win32-arm64-msvc/",\ + "packageDependencies": [\ + ["@rollup/rollup-win32-arm64-msvc", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-win32-ia32-msvc", [\ @@ -2039,6 +3054,22 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-win32-ia32-msvc", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-win32-ia32-msvc-npm-4.55.1-d54e4e5db3/node_modules/@rollup/rollup-win32-ia32-msvc/",\ + "packageDependencies": [\ + ["@rollup/rollup-win32-ia32-msvc", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@rollup/rollup-win32-x64-gnu", [\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-win32-x64-gnu-npm-4.55.1-877dfcd18a/node_modules/@rollup/rollup-win32-x64-gnu/",\ + "packageDependencies": [\ + ["@rollup/rollup-win32-x64-gnu", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rollup/rollup-win32-x64-msvc", [\ @@ -2048,6 +3079,13 @@ const RAW_RUNTIME_STATE = ["@rollup/rollup-win32-x64-msvc", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/unplugged/@rollup-rollup-win32-x64-msvc-npm-4.55.1-92f193fa89/node_modules/@rollup/rollup-win32-x64-msvc/",\ + "packageDependencies": [\ + ["@rollup/rollup-win32-x64-msvc", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@rtsao/scc", [\ @@ -2148,6 +3186,16 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@swc/helpers", [\ + ["npm:0.5.15", {\ + "packageLocation": "./.yarn/cache/@swc-helpers-npm-0.5.15-a7a06a73bc-33002f74f6.zip/node_modules/@swc/helpers/",\ + "packageDependencies": [\ + ["@swc/helpers", "npm:0.5.15"],\ + ["tslib", "npm:2.8.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@testing-library/dom", [\ ["npm:10.4.0", {\ "packageLocation": "./.yarn/cache/@testing-library-dom-npm-10.4.0-a0d2ca848e-0352487720.zip/node_modules/@testing-library/dom/",\ @@ -2261,6 +3309,51 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@types/babel__core", [\ + ["npm:7.20.5", {\ + "packageLocation": "./.yarn/cache/@types-babel__core-npm-7.20.5-4d95f75eab-bdee3bb699.zip/node_modules/@types/babel__core/",\ + "packageDependencies": [\ + ["@babel/parser", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"],\ + ["@types/babel__core", "npm:7.20.5"],\ + ["@types/babel__generator", "npm:7.27.0"],\ + ["@types/babel__template", "npm:7.4.4"],\ + ["@types/babel__traverse", "npm:7.28.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/babel__generator", [\ + ["npm:7.27.0", {\ + "packageLocation": "./.yarn/cache/@types-babel__generator-npm-7.27.0-a5af33547a-9f9e959a87.zip/node_modules/@types/babel__generator/",\ + "packageDependencies": [\ + ["@babel/types", "npm:7.28.5"],\ + ["@types/babel__generator", "npm:7.27.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/babel__template", [\ + ["npm:7.4.4", {\ + "packageLocation": "./.yarn/cache/@types-babel__template-npm-7.4.4-f34eba762c-cc84f6c6ab.zip/node_modules/@types/babel__template/",\ + "packageDependencies": [\ + ["@babel/parser", "npm:7.28.5"],\ + ["@babel/types", "npm:7.28.5"],\ + ["@types/babel__template", "npm:7.4.4"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["@types/babel__traverse", [\ + ["npm:7.28.0", {\ + "packageLocation": "./.yarn/cache/@types-babel__traverse-npm-7.28.0-44a48c1b20-b52d7d4e8f.zip/node_modules/@types/babel__traverse/",\ + "packageDependencies": [\ + ["@babel/types", "npm:7.28.5"],\ + ["@types/babel__traverse", "npm:7.28.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@types/estree", [\ ["npm:1.0.7", {\ "packageLocation": "./.yarn/cache/@types-estree-npm-1.0.7-692605611f-be81525431.zip/node_modules/@types/estree/",\ @@ -2268,6 +3361,13 @@ const RAW_RUNTIME_STATE = ["@types/estree", "npm:1.0.7"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:1.0.8", {\ + "packageLocation": "./.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-39d34d1afa.zip/node_modules/@types/estree/",\ + "packageDependencies": [\ + ["@types/estree", "npm:1.0.8"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["@types/hast", [\ @@ -2621,6 +3721,34 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["@vitejs/plugin-react", [\ + ["npm:4.7.0", {\ + "packageLocation": "./.yarn/cache/@vitejs-plugin-react-npm-4.7.0-650e714693-692f239609.zip/node_modules/@vitejs/plugin-react/",\ + "packageDependencies": [\ + ["@vitejs/plugin-react", "npm:4.7.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:4.7.0", {\ + "packageLocation": "./.yarn/__virtual__/@vitejs-plugin-react-virtual-a63355dca4/0/cache/@vitejs-plugin-react-npm-4.7.0-650e714693-692f239609.zip/node_modules/@vitejs/plugin-react/",\ + "packageDependencies": [\ + ["@babel/core", "npm:7.28.5"],\ + ["@babel/plugin-transform-react-jsx-self", "virtual:a63355dca4fbc96fc1c4d4bfd9dc8483babadd47b7d586115e666cbff0d3f16de70d6f129ba88c43e008e51a9a4dc7744f7355fa96c40977d849c701bf3b8adf#npm:7.27.1"],\ + ["@babel/plugin-transform-react-jsx-source", "virtual:a63355dca4fbc96fc1c4d4bfd9dc8483babadd47b7d586115e666cbff0d3f16de70d6f129ba88c43e008e51a9a4dc7744f7355fa96c40977d849c701bf3b8adf#npm:7.27.1"],\ + ["@rolldown/pluginutils", "npm:1.0.0-beta.27"],\ + ["@types/babel__core", "npm:7.20.5"],\ + ["@types/vite", null],\ + ["@vitejs/plugin-react", "virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:4.7.0"],\ + ["react-refresh", "npm:0.17.0"],\ + ["vite", "virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:7.3.1"]\ + ],\ + "packagePeers": [\ + "@types/vite",\ + "vite"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["@vitejs/plugin-vue", [\ ["npm:5.2.3", {\ "packageLocation": "./.yarn/cache/@vitejs-plugin-vue-npm-5.2.3-cdfec94325-34a719c705.zip/node_modules/@vitejs/plugin-vue/",\ @@ -2706,6 +3834,26 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["virtual:423b9a6ace2bd918b4b597aa98f0f600755f8a0a285c0c99bc0f8056fb5e45b4daf15ed3117bfa81c8b1a5a92e84fdf1aadde2e2276ce4b48103698da8012572#npm:2.1.9", {\ + "packageLocation": "./.yarn/__virtual__/@vitest-mocker-virtual-a54e040387/0/cache/@vitest-mocker-npm-2.1.9-2c6df8716a-f734490d8d.zip/node_modules/@vitest/mocker/",\ + "packageDependencies": [\ + ["@types/msw", null],\ + ["@types/vite", null],\ + ["@vitest/mocker", "virtual:423b9a6ace2bd918b4b597aa98f0f600755f8a0a285c0c99bc0f8056fb5e45b4daf15ed3117bfa81c8b1a5a92e84fdf1aadde2e2276ce4b48103698da8012572#npm:2.1.9"],\ + ["@vitest/spy", "npm:2.1.9"],\ + ["estree-walker", "npm:3.0.3"],\ + ["magic-string", "npm:0.30.17"],\ + ["msw", null],\ + ["vite", "virtual:348918d46d804e1055941d3cb4f02d509dd574186c93b1616aca6d22329efc5b51c3b53592599b59bca564f388541841d54386f899ea132ac7d7d7efb506a049#npm:5.4.18"]\ + ],\ + "packagePeers": [\ + "@types/msw",\ + "@types/vite",\ + "msw",\ + "vite"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:5e5511474973e0d2f03e5b7a8326f39848901a0ad107a485e77678894cea7c2ff13446c8384f74e4b15cfbd3fcef2065532b77d8ec6f8e8df93c66891484047d#npm:2.1.9", {\ "packageLocation": "./.yarn/__virtual__/@vitest-mocker-virtual-b114875fde/0/cache/@vitest-mocker-npm-2.1.9-2c6df8716a-f734490d8d.zip/node_modules/@vitest/mocker/",\ "packageDependencies": [\ @@ -3429,6 +4577,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["baseline-browser-mapping", [\ + ["npm:2.9.14", {\ + "packageLocation": "./.yarn/cache/baseline-browser-mapping-npm-2.9.14-76c8c0db34-c9bf03c65e.zip/node_modules/baseline-browser-mapping/",\ + "packageDependencies": [\ + ["baseline-browser-mapping", "npm:2.9.14"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["better-path-resolve", [\ ["npm:1.0.0", {\ "packageLocation": "./.yarn/cache/better-path-resolve-npm-1.0.0-ea479f476b-7335130729.zip/node_modules/better-path-resolve/",\ @@ -3477,6 +4634,20 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["browserslist", [\ + ["npm:4.28.1", {\ + "packageLocation": "./.yarn/cache/browserslist-npm-4.28.1-e455c4c2e8-545a5fa9d7.zip/node_modules/browserslist/",\ + "packageDependencies": [\ + ["baseline-browser-mapping", "npm:2.9.14"],\ + ["browserslist", "npm:4.28.1"],\ + ["caniuse-lite", "npm:1.0.30001764"],\ + ["electron-to-chromium", "npm:1.5.267"],\ + ["node-releases", "npm:2.0.27"],\ + ["update-browserslist-db", "virtual:e455c4c2e8dc3f3e2b2f64927f2b0dff7ca09ff7730ccbb69cae3e9342c0b24fae16e40b2aa46a2b677c172a1365ba425382266fccbf1e96179eec79a4a5c294#npm:1.2.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["bundle-require", [\ ["npm:5.1.0", {\ "packageLocation": "./.yarn/cache/bundle-require-npm-5.1.0-022b2c8e1b-8bff9df68e.zip/node_modules/bundle-require/",\ @@ -3574,6 +4745,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["caniuse-lite", [\ + ["npm:1.0.30001764", {\ + "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001764-b7ddad43f9-3fbc2bcb35.zip/node_modules/caniuse-lite/",\ + "packageDependencies": [\ + ["caniuse-lite", "npm:1.0.30001764"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["ccount", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/ccount-npm-2.0.1-f4b7827860-3939b16643.zip/node_modules/ccount/",\ @@ -3718,6 +4898,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["client-only", [\ + ["npm:0.0.1", {\ + "packageLocation": "./.yarn/cache/client-only-npm-0.0.1-07d3e9505c-9d6cfd0c19.zip/node_modules/client-only/",\ + "packageDependencies": [\ + ["client-only", "npm:0.0.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["color-convert", [\ ["npm:2.0.1", {\ "packageLocation": "./.yarn/cache/color-convert-npm-2.0.1-79730e935b-37e1150172.zip/node_modules/color-convert/",\ @@ -3808,6 +4997,24 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["convert-source-map", [\ + ["npm:2.0.0", {\ + "packageLocation": "./.yarn/cache/convert-source-map-npm-2.0.0-7ab664dc4e-8f2f7a27a1.zip/node_modules/convert-source-map/",\ + "packageDependencies": [\ + ["convert-source-map", "npm:2.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["cookie", [\ + ["npm:1.1.1", {\ + "packageLocation": "./.yarn/cache/cookie-npm-1.1.1-881103ddeb-79c4ddc0fc.zip/node_modules/cookie/",\ + "packageDependencies": [\ + ["cookie", "npm:1.1.1"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["copy-anything", [\ ["npm:3.0.5", {\ "packageLocation": "./.yarn/cache/copy-anything-npm-3.0.5-562d15fb3f-01eadd500c.zip/node_modules/copy-anything/",\ @@ -3939,6 +5146,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:4.4.3", {\ + "packageLocation": "./.yarn/cache/debug-npm-4.4.3-0105c6123a-d79136ec6c.zip/node_modules/debug/",\ + "packageDependencies": [\ + ["debug", "npm:4.4.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:2a426afc4b2eef43db12a540d29c2b5476640459bfcd5c24f86bb401cf8cce97e63bd81794d206a5643057e7f662643afd5ce3dfc4d4bfd8e706006c6309c5fa#npm:3.2.7", {\ "packageLocation": "./.yarn/__virtual__/debug-virtual-d2345003b7/0/cache/debug-npm-3.2.7-754e818c7a-37d96ae42c.zip/node_modules/debug/",\ "packageDependencies": [\ @@ -3966,6 +5180,20 @@ const RAW_RUNTIME_STATE = "supports-color"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:cd68c2d8dbe5140515f0d84027dc2f70623ef123c1ed0705293b830925f9fd53fba46ca9553905fee18e47994c7349977bfffe0887f5df2ef5d1d9ded216f039#npm:4.4.3", {\ + "packageLocation": "./.yarn/__virtual__/debug-virtual-f2c85efc82/0/cache/debug-npm-4.4.3-0105c6123a-d79136ec6c.zip/node_modules/debug/",\ + "packageDependencies": [\ + ["@types/supports-color", null],\ + ["debug", "virtual:cd68c2d8dbe5140515f0d84027dc2f70623ef123c1ed0705293b830925f9fd53fba46ca9553905fee18e47994c7349977bfffe0887f5df2ef5d1d9ded216f039#npm:4.4.3"],\ + ["ms", "npm:2.1.3"],\ + ["supports-color", null]\ + ],\ + "packagePeers": [\ + "@types/supports-color",\ + "supports-color"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["decimal.js", [\ @@ -4046,6 +5274,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["detect-libc", [\ + ["npm:2.1.2", {\ + "packageLocation": "./.yarn/cache/detect-libc-npm-2.1.2-d0c382b1e2-acc675c29a.zip/node_modules/detect-libc/",\ + "packageDependencies": [\ + ["detect-libc", "npm:2.1.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["devlop", [\ ["npm:1.1.0", {\ "packageLocation": "./.yarn/cache/devlop-npm-1.1.0-d4a98d724c-e0928ab8f9.zip/node_modules/devlop/",\ @@ -4129,6 +5366,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["electron-to-chromium", [\ + ["npm:1.5.267", {\ + "packageLocation": "./.yarn/cache/electron-to-chromium-npm-1.5.267-b62f38d65a-0732bdb891.zip/node_modules/electron-to-chromium/",\ + "packageDependencies": [\ + ["electron-to-chromium", "npm:1.5.267"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["emoji-regex", [\ ["npm:10.4.0", {\ "packageLocation": "./.yarn/cache/emoji-regex-npm-10.4.0-919f0a031a-a3fcedfc58.zip/node_modules/emoji-regex/",\ @@ -4469,6 +5715,48 @@ const RAW_RUNTIME_STATE = ["esbuild", "npm:0.25.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.27.2", {\ + "packageLocation": "./.yarn/unplugged/esbuild-npm-0.27.2-7789e62c6d/node_modules/esbuild/",\ + "packageDependencies": [\ + ["@esbuild/aix-ppc64", "npm:0.27.2"],\ + ["@esbuild/android-arm", "npm:0.27.2"],\ + ["@esbuild/android-arm64", "npm:0.27.2"],\ + ["@esbuild/android-x64", "npm:0.27.2"],\ + ["@esbuild/darwin-arm64", "npm:0.27.2"],\ + ["@esbuild/darwin-x64", "npm:0.27.2"],\ + ["@esbuild/freebsd-arm64", "npm:0.27.2"],\ + ["@esbuild/freebsd-x64", "npm:0.27.2"],\ + ["@esbuild/linux-arm", "npm:0.27.2"],\ + ["@esbuild/linux-arm64", "npm:0.27.2"],\ + ["@esbuild/linux-ia32", "npm:0.27.2"],\ + ["@esbuild/linux-loong64", "npm:0.27.2"],\ + ["@esbuild/linux-mips64el", "npm:0.27.2"],\ + ["@esbuild/linux-ppc64", "npm:0.27.2"],\ + ["@esbuild/linux-riscv64", "npm:0.27.2"],\ + ["@esbuild/linux-s390x", "npm:0.27.2"],\ + ["@esbuild/linux-x64", "npm:0.27.2"],\ + ["@esbuild/netbsd-arm64", "npm:0.27.2"],\ + ["@esbuild/netbsd-x64", "npm:0.27.2"],\ + ["@esbuild/openbsd-arm64", "npm:0.27.2"],\ + ["@esbuild/openbsd-x64", "npm:0.27.2"],\ + ["@esbuild/openharmony-arm64", "npm:0.27.2"],\ + ["@esbuild/sunos-x64", "npm:0.27.2"],\ + ["@esbuild/win32-arm64", "npm:0.27.2"],\ + ["@esbuild/win32-ia32", "npm:0.27.2"],\ + ["@esbuild/win32-x64", "npm:0.27.2"],\ + ["esbuild", "npm:0.27.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["escalade", [\ + ["npm:3.2.0", {\ + "packageLocation": "./.yarn/cache/escalade-npm-3.2.0-19b50dd48f-ced4dd3a78.zip/node_modules/escalade/",\ + "packageDependencies": [\ + ["escalade", "npm:3.2.0"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["escape-string-regexp", [\ @@ -5013,6 +6301,26 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:6.5.0", {\ + "packageLocation": "./.yarn/cache/fdir-npm-6.5.0-8814a0dec7-e345083c43.zip/node_modules/fdir/",\ + "packageDependencies": [\ + ["fdir", "npm:6.5.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:0e783aadbd2b4b8e6f6056033c0b290501892d23bc7c5dad5477e00e48ad8bd3e4434c3962a52dd75a58e06dbb7218094a494bac954ef2f7f6fdb65d9717e5f4#npm:6.5.0", {\ + "packageLocation": "./.yarn/__virtual__/fdir-virtual-abd4ab2082/0/cache/fdir-npm-6.5.0-8814a0dec7-e345083c43.zip/node_modules/fdir/",\ + "packageDependencies": [\ + ["@types/picomatch", null],\ + ["fdir", "virtual:0e783aadbd2b4b8e6f6056033c0b290501892d23bc7c5dad5477e00e48ad8bd3e4434c3962a52dd75a58e06dbb7218094a494bac954ef2f7f6fdb65d9717e5f4#npm:6.5.0"],\ + ["picomatch", "npm:4.0.3"]\ + ],\ + "packagePeers": [\ + "@types/picomatch",\ + "picomatch"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:c8807de691826868d9a774dfe20fb184997709c19896ccda6c1d382d679c7c2453bf893d9e0510372bd84566a8523db06ec721126eb95bb24e97992998e8a625#npm:6.4.3", {\ "packageLocation": "./.yarn/__virtual__/fdir-virtual-4be5a9f550/0/cache/fdir-npm-6.4.3-938f734d57-d13c10120e.zip/node_modules/fdir/",\ "packageDependencies": [\ @@ -5226,6 +6534,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["gensync", [\ + ["npm:1.0.0-beta.2", {\ + "packageLocation": "./.yarn/cache/gensync-npm-1.0.0-beta.2-224666d72f-782aba6cba.zip/node_modules/gensync/",\ + "packageDependencies": [\ + ["gensync", "npm:1.0.0-beta.2"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["get-east-asian-width", [\ ["npm:1.3.0", {\ "packageLocation": "./.yarn/cache/get-east-asian-width-npm-1.3.0-96a4370305-1a049ba697.zip/node_modules/get-east-asian-width/",\ @@ -6258,6 +7575,13 @@ const RAW_RUNTIME_STATE = ["minimist", "npm:1.2.8"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:2.2.3", {\ + "packageLocation": "./.yarn/cache/json5-npm-2.2.3-9962c55073-5a04eed948.zip/node_modules/json5/",\ + "packageDependencies": [\ + ["json5", "npm:2.2.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["jsonfile", [\ @@ -6458,6 +7782,14 @@ const RAW_RUNTIME_STATE = ["lru-cache", "npm:11.1.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:5.1.1", {\ + "packageLocation": "./.yarn/cache/lru-cache-npm-5.1.1-f475882a51-89b2ef2ef4.zip/node_modules/lru-cache/",\ + "packageDependencies": [\ + ["lru-cache", "npm:5.1.1"],\ + ["yallist", "npm:3.1.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["lz-string", [\ @@ -6858,14 +8190,70 @@ const RAW_RUNTIME_STATE = "packageDependencies": [\ ["natural-compare", "npm:1.4.0"]\ ],\ - "linkType": "HARD"\ - }]\ - ]],\ - ["negotiator", [\ - ["npm:1.0.0", {\ - "packageLocation": "./.yarn/cache/negotiator-npm-1.0.0-47d727e27e-4c559dd526.zip/node_modules/negotiator/",\ - "packageDependencies": [\ - ["negotiator", "npm:1.0.0"]\ + "linkType": "HARD"\ + }]\ + ]],\ + ["negotiator", [\ + ["npm:1.0.0", {\ + "packageLocation": "./.yarn/cache/negotiator-npm-1.0.0-47d727e27e-4c559dd526.zip/node_modules/negotiator/",\ + "packageDependencies": [\ + ["negotiator", "npm:1.0.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["next", [\ + ["npm:15.5.9", {\ + "packageLocation": "./.yarn/cache/next-npm-15.5.9-c16f969d8a-6a120afbc4.zip/node_modules/next/",\ + "packageDependencies": [\ + ["next", "npm:15.5.9"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#npm:15.5.9", {\ + "packageLocation": "./.yarn/__virtual__/next-virtual-1ab38d9462/0/cache/next-npm-15.5.9-c16f969d8a-6a120afbc4.zip/node_modules/next/",\ + "packageDependencies": [\ + ["@next/env", "npm:15.5.9"],\ + ["@next/swc-darwin-arm64", "npm:15.5.7"],\ + ["@next/swc-darwin-x64", "npm:15.5.7"],\ + ["@next/swc-linux-arm64-gnu", "npm:15.5.7"],\ + ["@next/swc-linux-arm64-musl", "npm:15.5.7"],\ + ["@next/swc-linux-x64-gnu", "npm:15.5.7"],\ + ["@next/swc-linux-x64-musl", "npm:15.5.7"],\ + ["@next/swc-win32-arm64-msvc", "npm:15.5.7"],\ + ["@next/swc-win32-x64-msvc", "npm:15.5.7"],\ + ["@opentelemetry/api", null],\ + ["@playwright/test", null],\ + ["@swc/helpers", "npm:0.5.15"],\ + ["@types/babel-plugin-react-compiler", null],\ + ["@types/opentelemetry__api", null],\ + ["@types/playwright__test", null],\ + ["@types/react", "npm:19.1.0"],\ + ["@types/react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.2"],\ + ["@types/sass", null],\ + ["babel-plugin-react-compiler", null],\ + ["caniuse-lite", "npm:1.0.30001764"],\ + ["next", "virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#npm:15.5.9"],\ + ["postcss", "npm:8.4.31"],\ + ["react", "npm:19.1.0"],\ + ["react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.0"],\ + ["sass", null],\ + ["sharp", "npm:0.34.5"],\ + ["styled-jsx", "virtual:1ab38d94624c09c74dfbcbb673066703afdd0fed3fb460e00f505a986b1f87b9d946d6b0ed45b484e26926fb09bd7f227c798cb2557dffc0eaa492f6233a81c1#npm:5.1.6"]\ + ],\ + "packagePeers": [\ + "@opentelemetry/api",\ + "@playwright/test",\ + "@types/babel-plugin-react-compiler",\ + "@types/opentelemetry__api",\ + "@types/playwright__test",\ + "@types/react-dom",\ + "@types/react",\ + "@types/sass",\ + "babel-plugin-react-compiler",\ + "react-dom",\ + "react",\ + "sass"\ ],\ "linkType": "HARD"\ }]\ @@ -6921,6 +8309,15 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["node-releases", [\ + ["npm:2.0.27", {\ + "packageLocation": "./.yarn/cache/node-releases-npm-2.0.27-b2d1b8de4a-f1e6583b78.zip/node_modules/node-releases/",\ + "packageDependencies": [\ + ["node-releases", "npm:2.0.27"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["nopt", [\ ["npm:8.1.0", {\ "packageLocation": "./.yarn/cache/nopt-npm-8.1.0-5570ef63cd-62e9ea70c7.zip/node_modules/nopt/",\ @@ -7358,6 +8755,13 @@ const RAW_RUNTIME_STATE = ["picomatch", "npm:4.0.2"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.0.3", {\ + "packageLocation": "./.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-9582c951e9.zip/node_modules/picomatch/",\ + "packageDependencies": [\ + ["picomatch", "npm:4.0.3"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["pify", [\ @@ -7388,6 +8792,16 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["postcss", [\ + ["npm:8.4.31", {\ + "packageLocation": "./.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip/node_modules/postcss/",\ + "packageDependencies": [\ + ["nanoid", "npm:3.3.11"],\ + ["picocolors", "npm:1.1.1"],\ + ["postcss", "npm:8.4.31"],\ + ["source-map-js", "npm:1.2.1"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:8.5.3", {\ "packageLocation": "./.yarn/cache/postcss-npm-8.5.3-37174aa03d-b75510d7b2.zip/node_modules/postcss/",\ "packageDependencies": [\ @@ -7397,6 +8811,16 @@ const RAW_RUNTIME_STATE = ["source-map-js", "npm:1.2.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:8.5.6", {\ + "packageLocation": "./.yarn/cache/postcss-npm-8.5.6-e7f126c6f3-5127cc7c91.zip/node_modules/postcss/",\ + "packageDependencies": [\ + ["nanoid", "npm:3.3.11"],\ + ["picocolors", "npm:1.1.1"],\ + ["postcss", "npm:8.5.6"],\ + ["source-map-js", "npm:1.2.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["postcss-load-config", [\ @@ -7629,6 +9053,70 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["react-refresh", [\ + ["npm:0.17.0", {\ + "packageLocation": "./.yarn/cache/react-refresh-npm-0.17.0-85b5aa925e-002cba9403.zip/node_modules/react-refresh/",\ + "packageDependencies": [\ + ["react-refresh", "npm:0.17.0"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["react-router", [\ + ["npm:7.12.0", {\ + "packageLocation": "./.yarn/cache/react-router-npm-7.12.0-e7bf49854a-abde366f71.zip/node_modules/react-router/",\ + "packageDependencies": [\ + ["react-router", "npm:7.12.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:2d4abf7f7c9f4314f88eaaeb3e508a15308aef55bea5b05f77169d136ba3db582bb89e421f931dbdd740ae79ac9d4ae3207dfa2909f042a9075d665dba57a5e8#npm:7.12.0", {\ + "packageLocation": "./.yarn/__virtual__/react-router-virtual-c8a4675e13/0/cache/react-router-npm-7.12.0-e7bf49854a-abde366f71.zip/node_modules/react-router/",\ + "packageDependencies": [\ + ["@types/react", "npm:19.1.0"],\ + ["@types/react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.2"],\ + ["cookie", "npm:1.1.1"],\ + ["react", "npm:19.1.0"],\ + ["react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.0"],\ + ["react-router", "virtual:2d4abf7f7c9f4314f88eaaeb3e508a15308aef55bea5b05f77169d136ba3db582bb89e421f931dbdd740ae79ac9d4ae3207dfa2909f042a9075d665dba57a5e8#npm:7.12.0"],\ + ["set-cookie-parser", "npm:2.7.2"]\ + ],\ + "packagePeers": [\ + "@types/react-dom",\ + "@types/react",\ + "react-dom",\ + "react"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["react-router-dom", [\ + ["npm:7.12.0", {\ + "packageLocation": "./.yarn/cache/react-router-dom-npm-7.12.0-56055c7fac-48cb6e5d47.zip/node_modules/react-router-dom/",\ + "packageDependencies": [\ + ["react-router-dom", "npm:7.12.0"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:7.12.0", {\ + "packageLocation": "./.yarn/__virtual__/react-router-dom-virtual-2d4abf7f7c/0/cache/react-router-dom-npm-7.12.0-56055c7fac-48cb6e5d47.zip/node_modules/react-router-dom/",\ + "packageDependencies": [\ + ["@types/react", "npm:19.1.0"],\ + ["@types/react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.2"],\ + ["react", "npm:19.1.0"],\ + ["react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.0"],\ + ["react-router", "virtual:2d4abf7f7c9f4314f88eaaeb3e508a15308aef55bea5b05f77169d136ba3db582bb89e421f931dbdd740ae79ac9d4ae3207dfa2909f042a9075d665dba57a5e8#npm:7.12.0"],\ + ["react-router-dom", "virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:7.12.0"]\ + ],\ + "packagePeers": [\ + "@types/react-dom",\ + "@types/react",\ + "react-dom",\ + "react"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["react-simplikit", [\ ["workspace:.", {\ "packageLocation": "./",\ @@ -7909,6 +9397,40 @@ const RAW_RUNTIME_STATE = ["rollup", "npm:4.39.0"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:4.55.1", {\ + "packageLocation": "./.yarn/cache/rollup-npm-4.55.1-f1a4b4314a-267309f0db.zip/node_modules/rollup/",\ + "packageDependencies": [\ + ["@rollup/rollup-android-arm-eabi", "npm:4.55.1"],\ + ["@rollup/rollup-android-arm64", "npm:4.55.1"],\ + ["@rollup/rollup-darwin-arm64", "npm:4.55.1"],\ + ["@rollup/rollup-darwin-x64", "npm:4.55.1"],\ + ["@rollup/rollup-freebsd-arm64", "npm:4.55.1"],\ + ["@rollup/rollup-freebsd-x64", "npm:4.55.1"],\ + ["@rollup/rollup-linux-arm-gnueabihf", "npm:4.55.1"],\ + ["@rollup/rollup-linux-arm-musleabihf", "npm:4.55.1"],\ + ["@rollup/rollup-linux-arm64-gnu", "npm:4.55.1"],\ + ["@rollup/rollup-linux-arm64-musl", "npm:4.55.1"],\ + ["@rollup/rollup-linux-loong64-gnu", "npm:4.55.1"],\ + ["@rollup/rollup-linux-loong64-musl", "npm:4.55.1"],\ + ["@rollup/rollup-linux-ppc64-gnu", "npm:4.55.1"],\ + ["@rollup/rollup-linux-ppc64-musl", "npm:4.55.1"],\ + ["@rollup/rollup-linux-riscv64-gnu", "npm:4.55.1"],\ + ["@rollup/rollup-linux-riscv64-musl", "npm:4.55.1"],\ + ["@rollup/rollup-linux-s390x-gnu", "npm:4.55.1"],\ + ["@rollup/rollup-linux-x64-gnu", "npm:4.55.1"],\ + ["@rollup/rollup-linux-x64-musl", "npm:4.55.1"],\ + ["@rollup/rollup-openbsd-x64", "npm:4.55.1"],\ + ["@rollup/rollup-openharmony-arm64", "npm:4.55.1"],\ + ["@rollup/rollup-win32-arm64-msvc", "npm:4.55.1"],\ + ["@rollup/rollup-win32-ia32-msvc", "npm:4.55.1"],\ + ["@rollup/rollup-win32-x64-gnu", "npm:4.55.1"],\ + ["@rollup/rollup-win32-x64-msvc", "npm:4.55.1"],\ + ["@types/estree", "npm:1.0.8"],\ + ["fsevents", "patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1"],\ + ["rollup", "npm:4.55.1"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["rrweb-cssom", [\ @@ -8016,6 +9538,22 @@ const RAW_RUNTIME_STATE = ["semver", "npm:7.7.1"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:7.7.3", {\ + "packageLocation": "./.yarn/cache/semver-npm-7.7.3-9cf7b3b46c-4afe5c9865.zip/node_modules/semver/",\ + "packageDependencies": [\ + ["semver", "npm:7.7.3"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ + ["set-cookie-parser", [\ + ["npm:2.7.2", {\ + "packageLocation": "./.yarn/cache/set-cookie-parser-npm-2.7.2-e1a4d1221b-4381a9eb7e.zip/node_modules/set-cookie-parser/",\ + "packageDependencies": [\ + ["set-cookie-parser", "npm:2.7.2"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["set-function-length", [\ @@ -8058,6 +9596,42 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["sharp", [\ + ["npm:0.34.5", {\ + "packageLocation": "./.yarn/unplugged/sharp-npm-0.34.5-dc08218742/node_modules/sharp/",\ + "packageDependencies": [\ + ["@img/colour", "npm:1.0.0"],\ + ["@img/sharp-darwin-arm64", "npm:0.34.5"],\ + ["@img/sharp-darwin-x64", "npm:0.34.5"],\ + ["@img/sharp-libvips-darwin-arm64", "npm:1.2.4"],\ + ["@img/sharp-libvips-darwin-x64", "npm:1.2.4"],\ + ["@img/sharp-libvips-linux-arm", "npm:1.2.4"],\ + ["@img/sharp-libvips-linux-arm64", "npm:1.2.4"],\ + ["@img/sharp-libvips-linux-ppc64", "npm:1.2.4"],\ + ["@img/sharp-libvips-linux-riscv64", "npm:1.2.4"],\ + ["@img/sharp-libvips-linux-s390x", "npm:1.2.4"],\ + ["@img/sharp-libvips-linux-x64", "npm:1.2.4"],\ + ["@img/sharp-libvips-linuxmusl-arm64", "npm:1.2.4"],\ + ["@img/sharp-libvips-linuxmusl-x64", "npm:1.2.4"],\ + ["@img/sharp-linux-arm", "npm:0.34.5"],\ + ["@img/sharp-linux-arm64", "npm:0.34.5"],\ + ["@img/sharp-linux-ppc64", "npm:0.34.5"],\ + ["@img/sharp-linux-riscv64", "npm:0.34.5"],\ + ["@img/sharp-linux-s390x", "npm:0.34.5"],\ + ["@img/sharp-linux-x64", "npm:0.34.5"],\ + ["@img/sharp-linuxmusl-arm64", "npm:0.34.5"],\ + ["@img/sharp-linuxmusl-x64", "npm:0.34.5"],\ + ["@img/sharp-wasm32", "npm:0.34.5"],\ + ["@img/sharp-win32-arm64", "npm:0.34.5"],\ + ["@img/sharp-win32-ia32", "npm:0.34.5"],\ + ["@img/sharp-win32-x64", "npm:0.34.5"],\ + ["detect-libc", "npm:2.1.2"],\ + ["semver", "npm:7.7.3"],\ + ["sharp", "npm:0.34.5"]\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["shebang-command", [\ ["npm:2.0.0", {\ "packageLocation": "./.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-a41692e7d8.zip/node_modules/shebang-command/",\ @@ -8489,6 +10063,37 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["styled-jsx", [\ + ["npm:5.1.6", {\ + "packageLocation": "./.yarn/cache/styled-jsx-npm-5.1.6-623e2e7d45-ace50e7ea5.zip/node_modules/styled-jsx/",\ + "packageDependencies": [\ + ["styled-jsx", "npm:5.1.6"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:1ab38d94624c09c74dfbcbb673066703afdd0fed3fb460e00f505a986b1f87b9d946d6b0ed45b484e26926fb09bd7f227c798cb2557dffc0eaa492f6233a81c1#npm:5.1.6", {\ + "packageLocation": "./.yarn/__virtual__/styled-jsx-virtual-4042518b75/0/cache/styled-jsx-npm-5.1.6-623e2e7d45-ace50e7ea5.zip/node_modules/styled-jsx/",\ + "packageDependencies": [\ + ["@babel/core", null],\ + ["@types/babel-plugin-macros", null],\ + ["@types/babel__core", null],\ + ["@types/react", "npm:19.1.0"],\ + ["babel-plugin-macros", null],\ + ["client-only", "npm:0.0.1"],\ + ["react", "npm:19.1.0"],\ + ["styled-jsx", "virtual:1ab38d94624c09c74dfbcbb673066703afdd0fed3fb460e00f505a986b1f87b9d946d6b0ed45b484e26926fb09bd7f227c798cb2557dffc0eaa492f6233a81c1#npm:5.1.6"]\ + ],\ + "packagePeers": [\ + "@babel/core",\ + "@types/babel-plugin-macros",\ + "@types/babel__core",\ + "@types/react",\ + "babel-plugin-macros",\ + "react"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["sucrase", [\ ["npm:3.35.0", {\ "packageLocation": "./.yarn/cache/sucrase-npm-3.35.0-60ad876a0c-ac85f3359d.zip/node_modules/sucrase/",\ @@ -8646,6 +10251,15 @@ const RAW_RUNTIME_STATE = ["tinyglobby", "npm:0.2.12"]\ ],\ "linkType": "HARD"\ + }],\ + ["npm:0.2.15", {\ + "packageLocation": "./.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-869c31490d.zip/node_modules/tinyglobby/",\ + "packageDependencies": [\ + ["fdir", "virtual:0e783aadbd2b4b8e6f6056033c0b290501892d23bc7c5dad5477e00e48ad8bd3e4434c3962a52dd75a58e06dbb7218094a494bac954ef2f7f6fdb65d9717e5f4#npm:6.5.0"],\ + ["picomatch", "npm:4.0.3"],\ + ["tinyglobby", "npm:0.2.15"]\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["tinypool", [\ @@ -9088,6 +10702,30 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["update-browserslist-db", [\ + ["npm:1.2.3", {\ + "packageLocation": "./.yarn/cache/update-browserslist-db-npm-1.2.3-de1d320326-13a00355ea.zip/node_modules/update-browserslist-db/",\ + "packageDependencies": [\ + ["update-browserslist-db", "npm:1.2.3"]\ + ],\ + "linkType": "SOFT"\ + }],\ + ["virtual:e455c4c2e8dc3f3e2b2f64927f2b0dff7ca09ff7730ccbb69cae3e9342c0b24fae16e40b2aa46a2b677c172a1365ba425382266fccbf1e96179eec79a4a5c294#npm:1.2.3", {\ + "packageLocation": "./.yarn/__virtual__/update-browserslist-db-virtual-ec2db3efcb/0/cache/update-browserslist-db-npm-1.2.3-de1d320326-13a00355ea.zip/node_modules/update-browserslist-db/",\ + "packageDependencies": [\ + ["@types/browserslist", null],\ + ["browserslist", "npm:4.28.1"],\ + ["escalade", "npm:3.2.0"],\ + ["picocolors", "npm:1.1.1"],\ + ["update-browserslist-db", "virtual:e455c4c2e8dc3f3e2b2f64927f2b0dff7ca09ff7730ccbb69cae3e9342c0b24fae16e40b2aa46a2b677c172a1365ba425382266fccbf1e96179eec79a4a5c294#npm:1.2.3"]\ + ],\ + "packagePeers": [\ + "@types/browserslist",\ + "browserslist"\ + ],\ + "linkType": "HARD"\ + }]\ + ]],\ ["uri-js", [\ ["npm:4.4.1", {\ "packageLocation": "./.yarn/cache/uri-js-npm-4.4.1-66d11cbcaf-4ef57b45aa.zip/node_modules/uri-js/",\ @@ -9128,6 +10766,13 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "SOFT"\ }],\ + ["npm:7.3.1", {\ + "packageLocation": "./.yarn/cache/vite-npm-7.3.1-330baf2f0d-5c7548f5f4.zip/node_modules/vite/",\ + "packageDependencies": [\ + ["vite", "npm:7.3.1"]\ + ],\ + "linkType": "SOFT"\ + }],\ ["virtual:348918d46d804e1055941d3cb4f02d509dd574186c93b1616aca6d22329efc5b51c3b53592599b59bca564f388541841d54386f899ea132ac7d7d7efb506a049#npm:5.4.18", {\ "packageLocation": "./.yarn/__virtual__/vite-virtual-72b7c035b7/0/cache/vite-npm-5.4.18-7cad39367b-a8cbbec6bd.zip/node_modules/vite/",\ "packageDependencies": [\ @@ -9171,6 +10816,64 @@ const RAW_RUNTIME_STATE = ],\ "linkType": "HARD"\ }],\ + ["virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:7.3.1", {\ + "packageLocation": "./.yarn/__virtual__/vite-virtual-eb8356a1a8/0/cache/vite-npm-7.3.1-330baf2f0d-5c7548f5f4.zip/node_modules/vite/",\ + "packageDependencies": [\ + ["@types/jiti", null],\ + ["@types/less", null],\ + ["@types/lightningcss", null],\ + ["@types/node", null],\ + ["@types/sass", null],\ + ["@types/sass-embedded", null],\ + ["@types/stylus", null],\ + ["@types/sugarss", null],\ + ["@types/terser", null],\ + ["@types/tsx", null],\ + ["@types/yaml", null],\ + ["esbuild", "npm:0.27.2"],\ + ["fdir", "virtual:0e783aadbd2b4b8e6f6056033c0b290501892d23bc7c5dad5477e00e48ad8bd3e4434c3962a52dd75a58e06dbb7218094a494bac954ef2f7f6fdb65d9717e5f4#npm:6.5.0"],\ + ["fsevents", "patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1"],\ + ["jiti", null],\ + ["less", null],\ + ["lightningcss", null],\ + ["picomatch", "npm:4.0.3"],\ + ["postcss", "npm:8.5.6"],\ + ["rollup", "npm:4.55.1"],\ + ["sass", null],\ + ["sass-embedded", null],\ + ["stylus", null],\ + ["sugarss", null],\ + ["terser", null],\ + ["tinyglobby", "npm:0.2.15"],\ + ["tsx", null],\ + ["vite", "virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:7.3.1"],\ + ["yaml", null]\ + ],\ + "packagePeers": [\ + "@types/jiti",\ + "@types/less",\ + "@types/lightningcss",\ + "@types/node",\ + "@types/sass-embedded",\ + "@types/sass",\ + "@types/stylus",\ + "@types/sugarss",\ + "@types/terser",\ + "@types/tsx",\ + "@types/yaml",\ + "jiti",\ + "less",\ + "lightningcss",\ + "sass-embedded",\ + "sass",\ + "stylus",\ + "sugarss",\ + "terser",\ + "tsx",\ + "yaml"\ + ],\ + "linkType": "HARD"\ + }],\ ["virtual:5e5511474973e0d2f03e5b7a8326f39848901a0ad107a485e77678894cea7c2ff13446c8384f74e4b15cfbd3fcef2065532b77d8ec6f8e8df93c66891484047d#npm:5.4.18", {\ "packageLocation": "./.yarn/__virtual__/vite-virtual-c78fca9d5b/0/cache/vite-npm-5.4.18-7cad39367b-a8cbbec6bd.zip/node_modules/vite/",\ "packageDependencies": [\ @@ -9331,6 +11034,57 @@ const RAW_RUNTIME_STATE = "jsdom"\ ],\ "linkType": "HARD"\ + }],\ + ["virtual:b8ca648f23ac8db9e48f501f3417b5d22664f520096d4c3f324c7f27acb059637b178631fb2aa9474c5307a2c176eb80c2a4069538d26cb000262efba27773fe#npm:2.1.9", {\ + "packageLocation": "./.yarn/__virtual__/vitest-virtual-423b9a6ace/0/cache/vitest-npm-2.1.9-da245b091d-e339e16dcc.zip/node_modules/vitest/",\ + "packageDependencies": [\ + ["@edge-runtime/vm", null],\ + ["@types/edge-runtime__vm", null],\ + ["@types/happy-dom", null],\ + ["@types/jsdom", null],\ + ["@types/node", null],\ + ["@types/vitest__browser", null],\ + ["@types/vitest__ui", null],\ + ["@vitest/browser", null],\ + ["@vitest/expect", "npm:2.1.9"],\ + ["@vitest/mocker", "virtual:423b9a6ace2bd918b4b597aa98f0f600755f8a0a285c0c99bc0f8056fb5e45b4daf15ed3117bfa81c8b1a5a92e84fdf1aadde2e2276ce4b48103698da8012572#npm:2.1.9"],\ + ["@vitest/pretty-format", "npm:2.1.9"],\ + ["@vitest/runner", "npm:2.1.9"],\ + ["@vitest/snapshot", "npm:2.1.9"],\ + ["@vitest/spy", "npm:2.1.9"],\ + ["@vitest/ui", null],\ + ["@vitest/utils", "npm:2.1.9"],\ + ["chai", "npm:5.2.0"],\ + ["debug", "virtual:643ed7cc338bcf145a82d8b05b3bef6bcf150ca545df386225596f10ce53cc90b88b3ca83e348ade1ccea5f3f8e76c92d2f0e2ba544da60d40aff9921c56872d#npm:4.4.0"],\ + ["expect-type", "npm:1.2.1"],\ + ["happy-dom", null],\ + ["jsdom", null],\ + ["magic-string", "npm:0.30.17"],\ + ["pathe", "npm:1.1.2"],\ + ["std-env", "npm:3.9.0"],\ + ["tinybench", "npm:2.9.0"],\ + ["tinyexec", "npm:0.3.2"],\ + ["tinypool", "npm:1.0.2"],\ + ["tinyrainbow", "npm:1.2.0"],\ + ["vite", "virtual:348918d46d804e1055941d3cb4f02d509dd574186c93b1616aca6d22329efc5b51c3b53592599b59bca564f388541841d54386f899ea132ac7d7d7efb506a049#npm:5.4.18"],\ + ["vite-node", "npm:2.1.9"],\ + ["vitest", "virtual:b8ca648f23ac8db9e48f501f3417b5d22664f520096d4c3f324c7f27acb059637b178631fb2aa9474c5307a2c176eb80c2a4069538d26cb000262efba27773fe#npm:2.1.9"],\ + ["why-is-node-running", "npm:2.3.0"]\ + ],\ + "packagePeers": [\ + "@edge-runtime/vm",\ + "@types/edge-runtime__vm",\ + "@types/happy-dom",\ + "@types/jsdom",\ + "@types/node",\ + "@types/vitest__browser",\ + "@types/vitest__ui",\ + "@vitest/browser",\ + "@vitest/ui",\ + "happy-dom",\ + "jsdom"\ + ],\ + "linkType": "HARD"\ }]\ ]],\ ["vue", [\ @@ -9563,6 +11317,41 @@ const RAW_RUNTIME_STATE = "linkType": "HARD"\ }]\ ]],\ + ["with-nextjs", [\ + ["workspace:examples/with-nextjs", {\ + "packageLocation": "./examples/with-nextjs/",\ + "packageDependencies": [\ + ["@react-simplikit/mobile", "virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#workspace:packages/mobile"],\ + ["@types/node", "npm:22.14.0"],\ + ["@types/react", "npm:19.1.0"],\ + ["@types/react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.2"],\ + ["next", "virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#npm:15.5.9"],\ + ["react", "npm:19.1.0"],\ + ["react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.0"],\ + ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ + ["with-nextjs", "workspace:examples/with-nextjs"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ + ["with-vite", [\ + ["workspace:examples/with-vite", {\ + "packageLocation": "./examples/with-vite/",\ + "packageDependencies": [\ + ["@react-simplikit/mobile", "virtual:f9522faed4c7e558462ef89aa232afe8b28f40173b914f756ee38b21c9ce10bf830de8334e264bc007ff37043ac2a4f134dac81249be2bcb7033ff024ce27466#workspace:packages/mobile"],\ + ["@types/react", "npm:19.1.0"],\ + ["@types/react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.2"],\ + ["@vitejs/plugin-react", "virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:4.7.0"],\ + ["react", "npm:19.1.0"],\ + ["react-dom", "virtual:58f1f645458156471f2dd4bfe69f887061e36f232f989d41ce7ee0c9c6542f794a4662e41944ab04718e40cc5d7284a0aa8cb5039289908ecfcadbccf753070f#npm:19.1.0"],\ + ["react-router-dom", "virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:7.12.0"],\ + ["typescript", "patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5"],\ + ["vite", "virtual:4859486b80a38e1e55778596b129478b56d21224c49a057e6f204bd0ef112f450c0ab6db41bd028bc885a6d06a104f1faffa30cd30b973c26726b0fe33e03341#npm:7.3.1"],\ + ["with-vite", "workspace:examples/with-vite"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["word-wrap", [\ ["npm:1.2.5", {\ "packageLocation": "./.yarn/cache/word-wrap-npm-1.2.5-42d00c4b09-e0e4a1ca27.zip/node_modules/word-wrap/",\ @@ -9649,6 +11438,13 @@ const RAW_RUNTIME_STATE = }]\ ]],\ ["yallist", [\ + ["npm:3.1.1", {\ + "packageLocation": "./.yarn/cache/yallist-npm-3.1.1-a568a556b4-c66a5c46bc.zip/node_modules/yallist/",\ + "packageDependencies": [\ + ["yallist", "npm:3.1.1"]\ + ],\ + "linkType": "HARD"\ + }],\ ["npm:4.0.0", {\ "packageLocation": "./.yarn/cache/yallist-npm-4.0.0-b493d9e907-2286b5e8db.zip/node_modules/yallist/",\ "packageDependencies": [\ diff --git a/.yarn/cache/@babel-code-frame-npm-7.27.1-4dbcabb137-5dd9a18baa.zip b/.yarn/cache/@babel-code-frame-npm-7.27.1-4dbcabb137-5dd9a18baa.zip new file mode 100644 index 00000000..d14baf66 Binary files /dev/null and b/.yarn/cache/@babel-code-frame-npm-7.27.1-4dbcabb137-5dd9a18baa.zip differ diff --git a/.yarn/cache/@babel-compat-data-npm-7.28.5-41f8d327e8-702a25de73.zip b/.yarn/cache/@babel-compat-data-npm-7.28.5-41f8d327e8-702a25de73.zip new file mode 100644 index 00000000..cd68cd98 Binary files /dev/null and b/.yarn/cache/@babel-compat-data-npm-7.28.5-41f8d327e8-702a25de73.zip differ diff --git a/.yarn/cache/@babel-core-npm-7.28.5-cd68c2d8db-535f822380.zip b/.yarn/cache/@babel-core-npm-7.28.5-cd68c2d8db-535f822380.zip new file mode 100644 index 00000000..024d697f Binary files /dev/null and b/.yarn/cache/@babel-core-npm-7.28.5-cd68c2d8db-535f822380.zip differ diff --git a/.yarn/cache/@babel-generator-npm-7.28.5-fd8f3ae6b1-9f219fe1d5.zip b/.yarn/cache/@babel-generator-npm-7.28.5-fd8f3ae6b1-9f219fe1d5.zip new file mode 100644 index 00000000..9765350e Binary files /dev/null and b/.yarn/cache/@babel-generator-npm-7.28.5-fd8f3ae6b1-9f219fe1d5.zip differ diff --git a/.yarn/cache/@babel-helper-compilation-targets-npm-7.27.2-111dda04b6-f338fa00dc.zip b/.yarn/cache/@babel-helper-compilation-targets-npm-7.27.2-111dda04b6-f338fa00dc.zip new file mode 100644 index 00000000..98018e12 Binary files /dev/null and b/.yarn/cache/@babel-helper-compilation-targets-npm-7.27.2-111dda04b6-f338fa00dc.zip differ diff --git a/.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-5a0cd0c0e8.zip b/.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-5a0cd0c0e8.zip new file mode 100644 index 00000000..49a88370 Binary files /dev/null and b/.yarn/cache/@babel-helper-globals-npm-7.28.0-8d79c12faf-5a0cd0c0e8.zip differ diff --git a/.yarn/cache/@babel-helper-module-imports-npm-7.27.1-3bf33978f4-e00aace096.zip b/.yarn/cache/@babel-helper-module-imports-npm-7.27.1-3bf33978f4-e00aace096.zip new file mode 100644 index 00000000..38f5a297 Binary files /dev/null and b/.yarn/cache/@babel-helper-module-imports-npm-7.27.1-3bf33978f4-e00aace096.zip differ diff --git a/.yarn/cache/@babel-helper-module-transforms-npm-7.28.3-7b69ec189a-549be62515.zip b/.yarn/cache/@babel-helper-module-transforms-npm-7.28.3-7b69ec189a-549be62515.zip new file mode 100644 index 00000000..575cfcb8 Binary files /dev/null and b/.yarn/cache/@babel-helper-module-transforms-npm-7.28.3-7b69ec189a-549be62515.zip differ diff --git a/.yarn/cache/@babel-helper-plugin-utils-npm-7.27.1-4f91e7999b-94cf22c81a.zip b/.yarn/cache/@babel-helper-plugin-utils-npm-7.27.1-4f91e7999b-94cf22c81a.zip new file mode 100644 index 00000000..deeac67f Binary files /dev/null and b/.yarn/cache/@babel-helper-plugin-utils-npm-7.27.1-4f91e7999b-94cf22c81a.zip differ diff --git a/.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-8bda3448e0.zip b/.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-8bda3448e0.zip new file mode 100644 index 00000000..345c3010 Binary files /dev/null and b/.yarn/cache/@babel-helper-string-parser-npm-7.27.1-d1471e0598-8bda3448e0.zip differ diff --git a/.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-42aaebed91.zip b/.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-42aaebed91.zip new file mode 100644 index 00000000..7768ce2a Binary files /dev/null and b/.yarn/cache/@babel-helper-validator-identifier-npm-7.28.5-1953d49d2b-42aaebed91.zip differ diff --git a/.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-6fec5f006e.zip b/.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-6fec5f006e.zip new file mode 100644 index 00000000..70054502 Binary files /dev/null and b/.yarn/cache/@babel-helper-validator-option-npm-7.27.1-7c563f0423-6fec5f006e.zip differ diff --git a/.yarn/cache/@babel-helpers-npm-7.28.4-d9f7567704-aaa5fb8098.zip b/.yarn/cache/@babel-helpers-npm-7.28.4-d9f7567704-aaa5fb8098.zip new file mode 100644 index 00000000..e896f14f Binary files /dev/null and b/.yarn/cache/@babel-helpers-npm-7.28.4-d9f7567704-aaa5fb8098.zip differ diff --git a/.yarn/cache/@babel-parser-npm-7.28.5-f2345a6b62-5bbe48bf2c.zip b/.yarn/cache/@babel-parser-npm-7.28.5-f2345a6b62-5bbe48bf2c.zip new file mode 100644 index 00000000..3a3e5922 Binary files /dev/null and b/.yarn/cache/@babel-parser-npm-7.28.5-f2345a6b62-5bbe48bf2c.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-react-jsx-self-npm-7.27.1-bd0fa344f1-00a4f917b7.zip b/.yarn/cache/@babel-plugin-transform-react-jsx-self-npm-7.27.1-bd0fa344f1-00a4f917b7.zip new file mode 100644 index 00000000..272b2041 Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-react-jsx-self-npm-7.27.1-bd0fa344f1-00a4f917b7.zip differ diff --git a/.yarn/cache/@babel-plugin-transform-react-jsx-source-npm-7.27.1-36a9716d8f-5e67b56c39.zip b/.yarn/cache/@babel-plugin-transform-react-jsx-source-npm-7.27.1-36a9716d8f-5e67b56c39.zip new file mode 100644 index 00000000..acd7b29b Binary files /dev/null and b/.yarn/cache/@babel-plugin-transform-react-jsx-source-npm-7.27.1-36a9716d8f-5e67b56c39.zip differ diff --git a/.yarn/cache/@babel-template-npm-7.27.2-77e67eabbd-ed9e902265.zip b/.yarn/cache/@babel-template-npm-7.27.2-77e67eabbd-ed9e902265.zip new file mode 100644 index 00000000..5cfdf72f Binary files /dev/null and b/.yarn/cache/@babel-template-npm-7.27.2-77e67eabbd-ed9e902265.zip differ diff --git a/.yarn/cache/@babel-traverse-npm-7.28.5-2b51d83636-f6c4a59599.zip b/.yarn/cache/@babel-traverse-npm-7.28.5-2b51d83636-f6c4a59599.zip new file mode 100644 index 00000000..57ea72c5 Binary files /dev/null and b/.yarn/cache/@babel-traverse-npm-7.28.5-2b51d83636-f6c4a59599.zip differ diff --git a/.yarn/cache/@babel-types-npm-7.28.5-582d7cca8a-a5a483d210.zip b/.yarn/cache/@babel-types-npm-7.28.5-582d7cca8a-a5a483d210.zip new file mode 100644 index 00000000..af941d48 Binary files /dev/null and b/.yarn/cache/@babel-types-npm-7.28.5-582d7cca8a-a5a483d210.zip differ diff --git a/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-f4929d75e3.zip b/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-f4929d75e3.zip new file mode 100644 index 00000000..ee079115 Binary files /dev/null and b/.yarn/cache/@emnapi-runtime-npm-1.8.1-1ce27dc028-f4929d75e3.zip differ diff --git a/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10c0.zip b/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10c0.zip new file mode 100644 index 00000000..88737fba Binary files /dev/null and b/.yarn/cache/@esbuild-darwin-arm64-npm-0.27.2-d675c4a521-10c0.zip differ diff --git a/.yarn/cache/@esbuild-darwin-x64-npm-0.27.2-ae63bf405f-10c0.zip b/.yarn/cache/@esbuild-darwin-x64-npm-0.27.2-ae63bf405f-10c0.zip new file mode 100644 index 00000000..6a0d1fdd Binary files /dev/null and b/.yarn/cache/@esbuild-darwin-x64-npm-0.27.2-ae63bf405f-10c0.zip differ diff --git a/.yarn/cache/@esbuild-linux-arm64-npm-0.27.2-bf1b0979ac-10c0.zip b/.yarn/cache/@esbuild-linux-arm64-npm-0.27.2-bf1b0979ac-10c0.zip new file mode 100644 index 00000000..b9df0fe6 Binary files /dev/null and b/.yarn/cache/@esbuild-linux-arm64-npm-0.27.2-bf1b0979ac-10c0.zip differ diff --git a/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10c0.zip b/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10c0.zip new file mode 100644 index 00000000..b6db6ba9 Binary files /dev/null and b/.yarn/cache/@esbuild-linux-x64-npm-0.27.2-11f1a3d9db-10c0.zip differ diff --git a/.yarn/cache/@img-colour-npm-1.0.0-964a21c987-02261719c1.zip b/.yarn/cache/@img-colour-npm-1.0.0-964a21c987-02261719c1.zip new file mode 100644 index 00000000..6266aa25 Binary files /dev/null and b/.yarn/cache/@img-colour-npm-1.0.0-964a21c987-02261719c1.zip differ diff --git a/.yarn/cache/@img-sharp-darwin-arm64-npm-0.34.5-5cc67024f5-10c0.zip b/.yarn/cache/@img-sharp-darwin-arm64-npm-0.34.5-5cc67024f5-10c0.zip new file mode 100644 index 00000000..4938305f Binary files /dev/null and b/.yarn/cache/@img-sharp-darwin-arm64-npm-0.34.5-5cc67024f5-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-darwin-x64-npm-0.34.5-86b67542ce-10c0.zip b/.yarn/cache/@img-sharp-darwin-x64-npm-0.34.5-86b67542ce-10c0.zip new file mode 100644 index 00000000..dad8f481 Binary files /dev/null and b/.yarn/cache/@img-sharp-darwin-x64-npm-0.34.5-86b67542ce-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-darwin-arm64-npm-1.2.4-09e109d5ab-10c0.zip b/.yarn/cache/@img-sharp-libvips-darwin-arm64-npm-1.2.4-09e109d5ab-10c0.zip new file mode 100644 index 00000000..5fc30b61 Binary files /dev/null and b/.yarn/cache/@img-sharp-libvips-darwin-arm64-npm-1.2.4-09e109d5ab-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-darwin-x64-npm-1.2.4-8eefe980b0-10c0.zip b/.yarn/cache/@img-sharp-libvips-darwin-x64-npm-1.2.4-8eefe980b0-10c0.zip new file mode 100644 index 00000000..40770f8b Binary files /dev/null and b/.yarn/cache/@img-sharp-libvips-darwin-x64-npm-1.2.4-8eefe980b0-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-linux-arm64-npm-1.2.4-df7b9ebec3-10c0.zip b/.yarn/cache/@img-sharp-libvips-linux-arm64-npm-1.2.4-df7b9ebec3-10c0.zip new file mode 100644 index 00000000..3b18718c Binary files /dev/null and b/.yarn/cache/@img-sharp-libvips-linux-arm64-npm-1.2.4-df7b9ebec3-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-linux-x64-npm-1.2.4-105fd6d44d-10c0.zip b/.yarn/cache/@img-sharp-libvips-linux-x64-npm-1.2.4-105fd6d44d-10c0.zip new file mode 100644 index 00000000..00436367 Binary files /dev/null and b/.yarn/cache/@img-sharp-libvips-linux-x64-npm-1.2.4-105fd6d44d-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-linuxmusl-arm64-npm-1.2.4-6882b67804-10c0.zip b/.yarn/cache/@img-sharp-libvips-linuxmusl-arm64-npm-1.2.4-6882b67804-10c0.zip new file mode 100644 index 00000000..0a8d3d51 Binary files /dev/null and b/.yarn/cache/@img-sharp-libvips-linuxmusl-arm64-npm-1.2.4-6882b67804-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-libvips-linuxmusl-x64-npm-1.2.4-8810e87949-10c0.zip b/.yarn/cache/@img-sharp-libvips-linuxmusl-x64-npm-1.2.4-8810e87949-10c0.zip new file mode 100644 index 00000000..e943db1b Binary files /dev/null and b/.yarn/cache/@img-sharp-libvips-linuxmusl-x64-npm-1.2.4-8810e87949-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-linux-arm64-npm-0.34.5-efb30e243a-10c0.zip b/.yarn/cache/@img-sharp-linux-arm64-npm-0.34.5-efb30e243a-10c0.zip new file mode 100644 index 00000000..ee2e40d3 Binary files /dev/null and b/.yarn/cache/@img-sharp-linux-arm64-npm-0.34.5-efb30e243a-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-linux-x64-npm-0.34.5-06b002e5f6-10c0.zip b/.yarn/cache/@img-sharp-linux-x64-npm-0.34.5-06b002e5f6-10c0.zip new file mode 100644 index 00000000..52ee0479 Binary files /dev/null and b/.yarn/cache/@img-sharp-linux-x64-npm-0.34.5-06b002e5f6-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-linuxmusl-arm64-npm-0.34.5-ec7806d52a-10c0.zip b/.yarn/cache/@img-sharp-linuxmusl-arm64-npm-0.34.5-ec7806d52a-10c0.zip new file mode 100644 index 00000000..14cb4cad Binary files /dev/null and b/.yarn/cache/@img-sharp-linuxmusl-arm64-npm-0.34.5-ec7806d52a-10c0.zip differ diff --git a/.yarn/cache/@img-sharp-linuxmusl-x64-npm-0.34.5-e1fc3b763c-10c0.zip b/.yarn/cache/@img-sharp-linuxmusl-x64-npm-0.34.5-e1fc3b763c-10c0.zip new file mode 100644 index 00000000..b610552d Binary files /dev/null and b/.yarn/cache/@img-sharp-linuxmusl-x64-npm-0.34.5-e1fc3b763c-10c0.zip differ diff --git a/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-9a7d65fb13.zip b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-9a7d65fb13.zip new file mode 100644 index 00000000..4fe96708 Binary files /dev/null and b/.yarn/cache/@jridgewell-gen-mapping-npm-0.3.13-9bd96ac800-9a7d65fb13.zip differ diff --git a/.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-3de494219f.zip b/.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-3de494219f.zip new file mode 100644 index 00000000..4071ecec Binary files /dev/null and b/.yarn/cache/@jridgewell-remapping-npm-2.3.5-df8dacc063-3de494219f.zip differ diff --git a/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-4b30ec8cd5.zip b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-4b30ec8cd5.zip new file mode 100644 index 00000000..dddfb698 Binary files /dev/null and b/.yarn/cache/@jridgewell-trace-mapping-npm-0.3.31-1ae81d75ac-4b30ec8cd5.zip differ diff --git a/.yarn/cache/@next-env-npm-15.5.9-dcfb92230e-92c4e29d81.zip b/.yarn/cache/@next-env-npm-15.5.9-dcfb92230e-92c4e29d81.zip new file mode 100644 index 00000000..7b128028 Binary files /dev/null and b/.yarn/cache/@next-env-npm-15.5.9-dcfb92230e-92c4e29d81.zip differ diff --git a/.yarn/cache/@rolldown-pluginutils-npm-1.0.0-beta.27-108701b3b0-9658f235b3.zip b/.yarn/cache/@rolldown-pluginutils-npm-1.0.0-beta.27-108701b3b0-9658f235b3.zip new file mode 100644 index 00000000..1c68ea5b Binary files /dev/null and b/.yarn/cache/@rolldown-pluginutils-npm-1.0.0-beta.27-108701b3b0-9658f235b3.zip differ diff --git a/.yarn/cache/@rollup-rollup-darwin-arm64-npm-4.55.1-16138f7e16-10c0.zip b/.yarn/cache/@rollup-rollup-darwin-arm64-npm-4.55.1-16138f7e16-10c0.zip new file mode 100644 index 00000000..2fdfec66 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-darwin-arm64-npm-4.55.1-16138f7e16-10c0.zip differ diff --git a/.yarn/cache/@rollup-rollup-darwin-x64-npm-4.55.1-4fbf131c62-10c0.zip b/.yarn/cache/@rollup-rollup-darwin-x64-npm-4.55.1-4fbf131c62-10c0.zip new file mode 100644 index 00000000..cf28343c Binary files /dev/null and b/.yarn/cache/@rollup-rollup-darwin-x64-npm-4.55.1-4fbf131c62-10c0.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-arm64-gnu-npm-4.55.1-d65df7c795-10c0.zip b/.yarn/cache/@rollup-rollup-linux-arm64-gnu-npm-4.55.1-d65df7c795-10c0.zip new file mode 100644 index 00000000..6d08ccc5 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-arm64-gnu-npm-4.55.1-d65df7c795-10c0.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-arm64-musl-npm-4.55.1-0e3b42b0bc-10c0.zip b/.yarn/cache/@rollup-rollup-linux-arm64-musl-npm-4.55.1-0e3b42b0bc-10c0.zip new file mode 100644 index 00000000..f775d3d4 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-arm64-musl-npm-4.55.1-0e3b42b0bc-10c0.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-x64-gnu-npm-4.55.1-d5556ae8f7-10c0.zip b/.yarn/cache/@rollup-rollup-linux-x64-gnu-npm-4.55.1-d5556ae8f7-10c0.zip new file mode 100644 index 00000000..0f65603a Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-x64-gnu-npm-4.55.1-d5556ae8f7-10c0.zip differ diff --git a/.yarn/cache/@rollup-rollup-linux-x64-musl-npm-4.55.1-0f107901e9-10c0.zip b/.yarn/cache/@rollup-rollup-linux-x64-musl-npm-4.55.1-0f107901e9-10c0.zip new file mode 100644 index 00000000..590c4ae7 Binary files /dev/null and b/.yarn/cache/@rollup-rollup-linux-x64-musl-npm-4.55.1-0f107901e9-10c0.zip differ diff --git a/.yarn/cache/@swc-helpers-npm-0.5.15-a7a06a73bc-33002f74f6.zip b/.yarn/cache/@swc-helpers-npm-0.5.15-a7a06a73bc-33002f74f6.zip new file mode 100644 index 00000000..8d69ba74 Binary files /dev/null and b/.yarn/cache/@swc-helpers-npm-0.5.15-a7a06a73bc-33002f74f6.zip differ diff --git a/.yarn/cache/@types-babel__core-npm-7.20.5-4d95f75eab-bdee3bb699.zip b/.yarn/cache/@types-babel__core-npm-7.20.5-4d95f75eab-bdee3bb699.zip new file mode 100644 index 00000000..72c29708 Binary files /dev/null and b/.yarn/cache/@types-babel__core-npm-7.20.5-4d95f75eab-bdee3bb699.zip differ diff --git a/.yarn/cache/@types-babel__generator-npm-7.27.0-a5af33547a-9f9e959a87.zip b/.yarn/cache/@types-babel__generator-npm-7.27.0-a5af33547a-9f9e959a87.zip new file mode 100644 index 00000000..4de5beb7 Binary files /dev/null and b/.yarn/cache/@types-babel__generator-npm-7.27.0-a5af33547a-9f9e959a87.zip differ diff --git a/.yarn/cache/@types-babel__template-npm-7.4.4-f34eba762c-cc84f6c6ab.zip b/.yarn/cache/@types-babel__template-npm-7.4.4-f34eba762c-cc84f6c6ab.zip new file mode 100644 index 00000000..ef9a7aea Binary files /dev/null and b/.yarn/cache/@types-babel__template-npm-7.4.4-f34eba762c-cc84f6c6ab.zip differ diff --git a/.yarn/cache/@types-babel__traverse-npm-7.28.0-44a48c1b20-b52d7d4e8f.zip b/.yarn/cache/@types-babel__traverse-npm-7.28.0-44a48c1b20-b52d7d4e8f.zip new file mode 100644 index 00000000..1a4968cf Binary files /dev/null and b/.yarn/cache/@types-babel__traverse-npm-7.28.0-44a48c1b20-b52d7d4e8f.zip differ diff --git a/.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-39d34d1afa.zip b/.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-39d34d1afa.zip new file mode 100644 index 00000000..ec25ec1c Binary files /dev/null and b/.yarn/cache/@types-estree-npm-1.0.8-2195bac6d6-39d34d1afa.zip differ diff --git a/.yarn/cache/@vitejs-plugin-react-npm-4.7.0-650e714693-692f239609.zip b/.yarn/cache/@vitejs-plugin-react-npm-4.7.0-650e714693-692f239609.zip new file mode 100644 index 00000000..022bc323 Binary files /dev/null and b/.yarn/cache/@vitejs-plugin-react-npm-4.7.0-650e714693-692f239609.zip differ diff --git a/.yarn/cache/baseline-browser-mapping-npm-2.9.14-76c8c0db34-c9bf03c65e.zip b/.yarn/cache/baseline-browser-mapping-npm-2.9.14-76c8c0db34-c9bf03c65e.zip new file mode 100644 index 00000000..3edd1b7f Binary files /dev/null and b/.yarn/cache/baseline-browser-mapping-npm-2.9.14-76c8c0db34-c9bf03c65e.zip differ diff --git a/.yarn/cache/browserslist-npm-4.28.1-e455c4c2e8-545a5fa9d7.zip b/.yarn/cache/browserslist-npm-4.28.1-e455c4c2e8-545a5fa9d7.zip new file mode 100644 index 00000000..81d37ea0 Binary files /dev/null and b/.yarn/cache/browserslist-npm-4.28.1-e455c4c2e8-545a5fa9d7.zip differ diff --git a/.yarn/cache/caniuse-lite-npm-1.0.30001764-b7ddad43f9-3fbc2bcb35.zip b/.yarn/cache/caniuse-lite-npm-1.0.30001764-b7ddad43f9-3fbc2bcb35.zip new file mode 100644 index 00000000..b3e11d26 Binary files /dev/null and b/.yarn/cache/caniuse-lite-npm-1.0.30001764-b7ddad43f9-3fbc2bcb35.zip differ diff --git a/.yarn/cache/client-only-npm-0.0.1-07d3e9505c-9d6cfd0c19.zip b/.yarn/cache/client-only-npm-0.0.1-07d3e9505c-9d6cfd0c19.zip new file mode 100644 index 00000000..ba191a89 Binary files /dev/null and b/.yarn/cache/client-only-npm-0.0.1-07d3e9505c-9d6cfd0c19.zip differ diff --git a/.yarn/cache/convert-source-map-npm-2.0.0-7ab664dc4e-8f2f7a27a1.zip b/.yarn/cache/convert-source-map-npm-2.0.0-7ab664dc4e-8f2f7a27a1.zip new file mode 100644 index 00000000..9f1b30fc Binary files /dev/null and b/.yarn/cache/convert-source-map-npm-2.0.0-7ab664dc4e-8f2f7a27a1.zip differ diff --git a/.yarn/cache/cookie-npm-1.1.1-881103ddeb-79c4ddc0fc.zip b/.yarn/cache/cookie-npm-1.1.1-881103ddeb-79c4ddc0fc.zip new file mode 100644 index 00000000..9477b991 Binary files /dev/null and b/.yarn/cache/cookie-npm-1.1.1-881103ddeb-79c4ddc0fc.zip differ diff --git a/.yarn/cache/debug-npm-4.4.3-0105c6123a-d79136ec6c.zip b/.yarn/cache/debug-npm-4.4.3-0105c6123a-d79136ec6c.zip new file mode 100644 index 00000000..665263e5 Binary files /dev/null and b/.yarn/cache/debug-npm-4.4.3-0105c6123a-d79136ec6c.zip differ diff --git a/.yarn/cache/detect-libc-npm-2.1.2-d0c382b1e2-acc675c29a.zip b/.yarn/cache/detect-libc-npm-2.1.2-d0c382b1e2-acc675c29a.zip new file mode 100644 index 00000000..fe37d970 Binary files /dev/null and b/.yarn/cache/detect-libc-npm-2.1.2-d0c382b1e2-acc675c29a.zip differ diff --git a/.yarn/cache/electron-to-chromium-npm-1.5.267-b62f38d65a-0732bdb891.zip b/.yarn/cache/electron-to-chromium-npm-1.5.267-b62f38d65a-0732bdb891.zip new file mode 100644 index 00000000..a058df44 Binary files /dev/null and b/.yarn/cache/electron-to-chromium-npm-1.5.267-b62f38d65a-0732bdb891.zip differ diff --git a/.yarn/cache/esbuild-npm-0.27.2-7789e62c6d-cf83f626f5.zip b/.yarn/cache/esbuild-npm-0.27.2-7789e62c6d-cf83f626f5.zip new file mode 100644 index 00000000..42a0f649 Binary files /dev/null and b/.yarn/cache/esbuild-npm-0.27.2-7789e62c6d-cf83f626f5.zip differ diff --git a/.yarn/cache/escalade-npm-3.2.0-19b50dd48f-ced4dd3a78.zip b/.yarn/cache/escalade-npm-3.2.0-19b50dd48f-ced4dd3a78.zip new file mode 100644 index 00000000..456294aa Binary files /dev/null and b/.yarn/cache/escalade-npm-3.2.0-19b50dd48f-ced4dd3a78.zip differ diff --git a/.yarn/cache/fdir-npm-6.5.0-8814a0dec7-e345083c43.zip b/.yarn/cache/fdir-npm-6.5.0-8814a0dec7-e345083c43.zip new file mode 100644 index 00000000..5ee7a91a Binary files /dev/null and b/.yarn/cache/fdir-npm-6.5.0-8814a0dec7-e345083c43.zip differ diff --git a/.yarn/cache/gensync-npm-1.0.0-beta.2-224666d72f-782aba6cba.zip b/.yarn/cache/gensync-npm-1.0.0-beta.2-224666d72f-782aba6cba.zip new file mode 100644 index 00000000..421c21ba Binary files /dev/null and b/.yarn/cache/gensync-npm-1.0.0-beta.2-224666d72f-782aba6cba.zip differ diff --git a/.yarn/cache/json5-npm-2.2.3-9962c55073-5a04eed948.zip b/.yarn/cache/json5-npm-2.2.3-9962c55073-5a04eed948.zip new file mode 100644 index 00000000..dd0b0095 Binary files /dev/null and b/.yarn/cache/json5-npm-2.2.3-9962c55073-5a04eed948.zip differ diff --git a/.yarn/cache/lru-cache-npm-5.1.1-f475882a51-89b2ef2ef4.zip b/.yarn/cache/lru-cache-npm-5.1.1-f475882a51-89b2ef2ef4.zip new file mode 100644 index 00000000..0dfe956c Binary files /dev/null and b/.yarn/cache/lru-cache-npm-5.1.1-f475882a51-89b2ef2ef4.zip differ diff --git a/.yarn/cache/node-releases-npm-2.0.27-b2d1b8de4a-f1e6583b78.zip b/.yarn/cache/node-releases-npm-2.0.27-b2d1b8de4a-f1e6583b78.zip new file mode 100644 index 00000000..73d693ec Binary files /dev/null and b/.yarn/cache/node-releases-npm-2.0.27-b2d1b8de4a-f1e6583b78.zip differ diff --git a/.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-9582c951e9.zip b/.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-9582c951e9.zip new file mode 100644 index 00000000..6a2cc014 Binary files /dev/null and b/.yarn/cache/picomatch-npm-4.0.3-0a647b87cc-9582c951e9.zip differ diff --git a/.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip b/.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip new file mode 100644 index 00000000..d814012d Binary files /dev/null and b/.yarn/cache/postcss-npm-8.4.31-385051a82b-748b82e6e5.zip differ diff --git a/.yarn/cache/postcss-npm-8.5.6-e7f126c6f3-5127cc7c91.zip b/.yarn/cache/postcss-npm-8.5.6-e7f126c6f3-5127cc7c91.zip new file mode 100644 index 00000000..70e991ec Binary files /dev/null and b/.yarn/cache/postcss-npm-8.5.6-e7f126c6f3-5127cc7c91.zip differ diff --git a/.yarn/cache/react-refresh-npm-0.17.0-85b5aa925e-002cba9403.zip b/.yarn/cache/react-refresh-npm-0.17.0-85b5aa925e-002cba9403.zip new file mode 100644 index 00000000..9b0fc660 Binary files /dev/null and b/.yarn/cache/react-refresh-npm-0.17.0-85b5aa925e-002cba9403.zip differ diff --git a/.yarn/cache/react-router-dom-npm-7.12.0-56055c7fac-48cb6e5d47.zip b/.yarn/cache/react-router-dom-npm-7.12.0-56055c7fac-48cb6e5d47.zip new file mode 100644 index 00000000..0843f815 Binary files /dev/null and b/.yarn/cache/react-router-dom-npm-7.12.0-56055c7fac-48cb6e5d47.zip differ diff --git a/.yarn/cache/react-router-npm-7.12.0-e7bf49854a-abde366f71.zip b/.yarn/cache/react-router-npm-7.12.0-e7bf49854a-abde366f71.zip new file mode 100644 index 00000000..23dd80d8 Binary files /dev/null and b/.yarn/cache/react-router-npm-7.12.0-e7bf49854a-abde366f71.zip differ diff --git a/.yarn/cache/rollup-npm-4.55.1-f1a4b4314a-267309f0db.zip b/.yarn/cache/rollup-npm-4.55.1-f1a4b4314a-267309f0db.zip new file mode 100644 index 00000000..10010e30 Binary files /dev/null and b/.yarn/cache/rollup-npm-4.55.1-f1a4b4314a-267309f0db.zip differ diff --git a/.yarn/cache/semver-npm-7.7.3-9cf7b3b46c-4afe5c9865.zip b/.yarn/cache/semver-npm-7.7.3-9cf7b3b46c-4afe5c9865.zip new file mode 100644 index 00000000..de83a134 Binary files /dev/null and b/.yarn/cache/semver-npm-7.7.3-9cf7b3b46c-4afe5c9865.zip differ diff --git a/.yarn/cache/set-cookie-parser-npm-2.7.2-e1a4d1221b-4381a9eb7e.zip b/.yarn/cache/set-cookie-parser-npm-2.7.2-e1a4d1221b-4381a9eb7e.zip new file mode 100644 index 00000000..8c8c9383 Binary files /dev/null and b/.yarn/cache/set-cookie-parser-npm-2.7.2-e1a4d1221b-4381a9eb7e.zip differ diff --git a/.yarn/cache/sharp-npm-0.34.5-dc08218742-fd79e29df0.zip b/.yarn/cache/sharp-npm-0.34.5-dc08218742-fd79e29df0.zip new file mode 100644 index 00000000..5aaf970d Binary files /dev/null and b/.yarn/cache/sharp-npm-0.34.5-dc08218742-fd79e29df0.zip differ diff --git a/.yarn/cache/styled-jsx-npm-5.1.6-623e2e7d45-ace50e7ea5.zip b/.yarn/cache/styled-jsx-npm-5.1.6-623e2e7d45-ace50e7ea5.zip new file mode 100644 index 00000000..bd14176d Binary files /dev/null and b/.yarn/cache/styled-jsx-npm-5.1.6-623e2e7d45-ace50e7ea5.zip differ diff --git a/.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-869c31490d.zip b/.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-869c31490d.zip new file mode 100644 index 00000000..3092b12a Binary files /dev/null and b/.yarn/cache/tinyglobby-npm-0.2.15-0e783aadbd-869c31490d.zip differ diff --git a/.yarn/cache/update-browserslist-db-npm-1.2.3-de1d320326-13a00355ea.zip b/.yarn/cache/update-browserslist-db-npm-1.2.3-de1d320326-13a00355ea.zip new file mode 100644 index 00000000..bf3c7adf Binary files /dev/null and b/.yarn/cache/update-browserslist-db-npm-1.2.3-de1d320326-13a00355ea.zip differ diff --git a/.yarn/cache/vite-npm-7.3.1-330baf2f0d-5c7548f5f4.zip b/.yarn/cache/vite-npm-7.3.1-330baf2f0d-5c7548f5f4.zip new file mode 100644 index 00000000..3e7dfed6 Binary files /dev/null and b/.yarn/cache/vite-npm-7.3.1-330baf2f0d-5c7548f5f4.zip differ diff --git a/.yarn/cache/yallist-npm-3.1.1-a568a556b4-c66a5c46bc.zip b/.yarn/cache/yallist-npm-3.1.1-a568a556b4-c66a5c46bc.zip new file mode 100644 index 00000000..09d1a6f4 Binary files /dev/null and b/.yarn/cache/yallist-npm-3.1.1-a568a556b4-c66a5c46bc.zip differ diff --git a/.yarnrc.yml b/.yarnrc.yml index 95a39e35..b60bcf7e 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -3,6 +3,8 @@ changesetBaseRefs: enableGlobalCache: false +nodeLinker: pnp + npmScopes: jsr: npmRegistryServer: 'https://npm.jsr.io' diff --git a/eslint.config.js b/eslint.config.js index 7229838e..e15a64cf 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -26,6 +26,7 @@ export default [ 'tsup.*', 'vitest.*', '.vitepress', + '.next', ], }, { @@ -36,6 +37,14 @@ export default [ }, }, }, + { + files: ['examples/**/*.{ts,tsx}'], + languageOptions: { + parserOptions: { + project: './examples/*/tsconfig.json', + }, + }, + }, js.configs.recommended, ...tseslint.configs.recommended, react.configs.flat.recommended, diff --git a/examples/with-nextjs/app/demos/is-server/page.tsx b/examples/with-nextjs/app/demos/is-server/page.tsx new file mode 100644 index 00000000..e66efd7d --- /dev/null +++ b/examples/with-nextjs/app/demos/is-server/page.tsx @@ -0,0 +1,39 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { isServer } from '@react-simplikit/mobile'; + +import { DemoLayout } from '../../../components/DemoLayout.tsx'; + +export default function IsServerDemo() { + const [mounted, setMounted] = useState(false); + const currentValue = isServer(); + + useEffect(() => { + setMounted(true); + }, []); + + return ( + +
+

+ isServer(): {currentValue ? 'true' : 'false'} +

+

+ Hydration complete: {mounted ? 'true' : 'false'} +

+
+ +
+

During SSR, isServer() returns true.

+

After hydration on client, isServer() returns false.

+
+
+ ); +} diff --git a/examples/with-nextjs/app/layout.tsx b/examples/with-nextjs/app/layout.tsx new file mode 100644 index 00000000..240295d0 --- /dev/null +++ b/examples/with-nextjs/app/layout.tsx @@ -0,0 +1,15 @@ +import type { ReactNode } from 'react'; +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'with-nextjs | @react-simplikit/mobile', + description: 'Next.js example for @react-simplikit/mobile', +}; + +export default function RootLayout({ children }: { children: ReactNode }) { + return ( + + {children} + + ); +} diff --git a/examples/with-nextjs/app/page.tsx b/examples/with-nextjs/app/page.tsx new file mode 100644 index 00000000..356f50e4 --- /dev/null +++ b/examples/with-nextjs/app/page.tsx @@ -0,0 +1,34 @@ +import Link from 'next/link'; + +export default function Home() { + return ( +
+

@react-simplikit/mobile

+

Examples for Next.js (App Router)

+ + +
+ ); +} diff --git a/examples/with-nextjs/components/DemoLayout.tsx b/examples/with-nextjs/components/DemoLayout.tsx new file mode 100644 index 00000000..1b9c7eba --- /dev/null +++ b/examples/with-nextjs/components/DemoLayout.tsx @@ -0,0 +1,25 @@ +import type { ReactNode } from 'react'; +import Link from 'next/link'; + +type DemoLayoutProps = { + title: string; + description: string; + children: ReactNode; +}; + +export function DemoLayout({ title, description, children }: DemoLayoutProps) { + return ( +
+ + +
+

{title}

+

{description}

+
+ +
{children}
+
+ ); +} diff --git a/examples/with-nextjs/next-env.d.ts b/examples/with-nextjs/next-env.d.ts new file mode 100644 index 00000000..830fb594 --- /dev/null +++ b/examples/with-nextjs/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/examples/with-nextjs/next.config.ts b/examples/with-nextjs/next.config.ts new file mode 100644 index 00000000..020f6f1d --- /dev/null +++ b/examples/with-nextjs/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from 'next'; + +const nextConfig: NextConfig = { + transpilePackages: ['@react-simplikit/mobile'], +}; + +export default nextConfig; diff --git a/examples/with-nextjs/package.json b/examples/with-nextjs/package.json new file mode 100644 index 00000000..81dc05a4 --- /dev/null +++ b/examples/with-nextjs/package.json @@ -0,0 +1,22 @@ +{ + "name": "with-nextjs", + "version": "0.0.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start" + }, + "dependencies": { + "@react-simplikit/mobile": "workspace:*", + "next": "^15.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0" + }, + "devDependencies": { + "@types/node": "^22.10.2", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "typescript": "^5.7.2" + } +} diff --git a/examples/with-nextjs/tsconfig.json b/examples/with-nextjs/tsconfig.json new file mode 100644 index 00000000..7469ac5c --- /dev/null +++ b/examples/with-nextjs/tsconfig.json @@ -0,0 +1,36 @@ +{ + "compilerOptions": { + "lib": [ + "ESNext", + "DOM" + ], + "target": "ESNext", + "module": "ESNext", + "noEmit": true, + "allowImportingTsExtensions": true, + "moduleResolution": "Bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "jsx": "preserve", + "incremental": true, + "isolatedModules": true, + "plugins": [ + { + "name": "next" + } + ], + "allowJs": true, + "resolveJsonModule": true + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/examples/with-vite/index.html b/examples/with-vite/index.html new file mode 100644 index 00000000..015ece3e --- /dev/null +++ b/examples/with-vite/index.html @@ -0,0 +1,12 @@ + + + + + + with-react | @react-simplikit/mobile + + +
+ + + diff --git a/examples/with-vite/package.json b/examples/with-vite/package.json new file mode 100644 index 00000000..5cd14e41 --- /dev/null +++ b/examples/with-vite/package.json @@ -0,0 +1,24 @@ +{ + "name": "with-vite", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@react-simplikit/mobile": "workspace:*", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-router-dom": "^7.0.0" + }, + "devDependencies": { + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "^5.7.2", + "vite": "^7.0.0" + } +} diff --git a/examples/with-vite/src/App.tsx b/examples/with-vite/src/App.tsx new file mode 100644 index 00000000..c15314d9 --- /dev/null +++ b/examples/with-vite/src/App.tsx @@ -0,0 +1,15 @@ +import { BrowserRouter, Route, Routes } from 'react-router-dom'; + +import { IsServerDemo } from './pages/demos/IsServerDemo.tsx'; +import { Home } from './pages/Home.tsx'; + +export default function App() { + return ( + + + } /> + } /> + + + ); +} diff --git a/examples/with-vite/src/components/DemoLayout.tsx b/examples/with-vite/src/components/DemoLayout.tsx new file mode 100644 index 00000000..aab095bc --- /dev/null +++ b/examples/with-vite/src/components/DemoLayout.tsx @@ -0,0 +1,25 @@ +import type { ReactNode } from 'react'; +import { Link } from 'react-router-dom'; + +type DemoLayoutProps = { + title: string; + description: string; + children: ReactNode; +}; + +export function DemoLayout({ title, description, children }: DemoLayoutProps) { + return ( +
+ + +
+

{title}

+

{description}

+
+ +
{children}
+
+ ); +} diff --git a/examples/with-vite/src/main.tsx b/examples/with-vite/src/main.tsx new file mode 100644 index 00000000..c6492961 --- /dev/null +++ b/examples/with-vite/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; + +import App from './App.tsx'; + +createRoot(document.getElementById('root')!).render( + + + +); diff --git a/examples/with-vite/src/pages/Home.tsx b/examples/with-vite/src/pages/Home.tsx new file mode 100644 index 00000000..d81e8e32 --- /dev/null +++ b/examples/with-vite/src/pages/Home.tsx @@ -0,0 +1,34 @@ +import { Link } from 'react-router-dom'; + +export function Home() { + return ( +
+

@react-simplikit/mobile

+

Examples for Vite + React (CSR)

+ + +
+ ); +} diff --git a/examples/with-vite/src/pages/demos/IsServerDemo.tsx b/examples/with-vite/src/pages/demos/IsServerDemo.tsx new file mode 100644 index 00000000..057fbf42 --- /dev/null +++ b/examples/with-vite/src/pages/demos/IsServerDemo.tsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from 'react'; +import { isServer } from '@react-simplikit/mobile'; + +import { DemoLayout } from '../../components/DemoLayout.tsx'; + +export function IsServerDemo() { + const [mounted, setMounted] = useState(false); + const currentValue = isServer(); + + useEffect(() => { + setMounted(true); + }, []); + + return ( + +
+

+ isServer(): {currentValue ? 'true' : 'false'} +

+

+ Component mounted: {mounted ? 'true' : 'false'} +

+
+ +
+

In CSR (Vite), isServer() always returns false.

+

There is no SSR step, so it's always running on the client.

+
+
+ ); +} diff --git a/examples/with-vite/tsconfig.json b/examples/with-vite/tsconfig.json new file mode 100644 index 00000000..f0aed0b4 --- /dev/null +++ b/examples/with-vite/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "noEmit": true, + "allowImportingTsExtensions": true, + "moduleResolution": "Bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "jsx": "react-jsx", + "isolatedModules": true + }, + "include": ["src"] +} diff --git a/examples/with-vite/vite.config.ts b/examples/with-vite/vite.config.ts new file mode 100644 index 00000000..fabde1a8 --- /dev/null +++ b/examples/with-vite/vite.config.ts @@ -0,0 +1,6 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/package.json b/package.json index 91b47ae9..a26a9558 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,10 @@ "main": "./src/index.ts", "type": "module", "sideEffects": false, + "workspaces": [ + "packages/*", + "examples/*" + ], "keywords": [ "react" ], @@ -20,6 +24,9 @@ ], "scripts": { "clean": "rimraf ./dist ./esm ./coverage ./node_modules", + "clean:all": "yarn clean && yarn workspace @react-simplikit/mobile clean", + "example:vite": "yarn workspace with-vite dev", + "example:next": "yarn workspace with-nextjs dev", "scaffold": "tsx .scripts/index.ts scaffold", "changeset": "changeset", "changeset:version": "changeset version", @@ -37,6 +44,10 @@ "test:type": "tsc --noEmit", "test:spec": "vitest run", "test:coverage": "vitest run --coverage", + "test:mobile": "yarn workspace @react-simplikit/mobile test", + "build": "tsup", + "build:mobile": "yarn workspace @react-simplikit/mobile build", + "build:all": "yarn build && yarn build:mobile", "prepack": "tsup" }, "publishConfig": { diff --git a/packages/mobile/package.json b/packages/mobile/package.json new file mode 100644 index 00000000..3bbf7dd1 --- /dev/null +++ b/packages/mobile/package.json @@ -0,0 +1,71 @@ +{ + "name": "@react-simplikit/mobile", + "version": "0.1.0", + "description": "Mobile web utilities for React - fixing viewport, keyboard, and layout issues", + "type": "module", + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + } + }, + "./package.json": "./package.json" + }, + "files": [ + "dist/**/*" + ], + "sideEffects": false, + "keywords": [ + "react", + "mobile", + "viewport", + "keyboard", + "mobile-web", + "ios-safari", + "android-chrome", + "visual-viewport", + "keyboard-avoiding", + "safe-area" + ], + "homepage": "https://react-simplikit.slash.page", + "bugs": "https://github.com/toss/react-simplikit/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/toss/react-simplikit.git", + "directory": "packages/mobile" + }, + "license": "MIT", + "scripts": { + "build": "tsup", + "clean": "rimraf ./dist", + "test": "vitest run", + "test:watch": "vitest" + }, + "peerDependencies": { + "react": ">=18.0.0" + }, + "devDependencies": { + "@testing-library/dom": "^10.4.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.1.0", + "@types/react": "^19.0.0", + "@types/react-dom": "^19.0.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "rimraf": "^6.0.1", + "tsup": "^8.3.5", + "typescript": "^5.7.2", + "vitest": "^2.1.8" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/mobile/src/hooks/index.ts b/packages/mobile/src/hooks/index.ts new file mode 100644 index 00000000..0051ce9a --- /dev/null +++ b/packages/mobile/src/hooks/index.ts @@ -0,0 +1,3 @@ +export { useScrollDirection } from './useScrollDirection.ts'; +export { useVisualViewport } from './useVisualViewport.ts'; +export { useBodyScrollLock } from './useBodyScrollLock.ts'; diff --git a/packages/mobile/src/hooks/keyboardHeight/useKeyboardHeight.test.ts b/packages/mobile/src/hooks/keyboardHeight/useKeyboardHeight.test.ts new file mode 100644 index 00000000..14dfb82b --- /dev/null +++ b/packages/mobile/src/hooks/keyboardHeight/useKeyboardHeight.test.ts @@ -0,0 +1,197 @@ +import { act, renderHook } from '@testing-library/react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { subscribeKeyboardHeight } from '../../utils/keyboard/subscribeKeyboardHeight.ts'; + +import { useKeyboardHeight } from './useKeyboardHeight.ts'; + +vi.mock('../../utils/keyboardHeight/subscribeKeyboardHeight.ts', () => ({ + subscribeKeyboardHeight: vi.fn(), +})); + +const mockSubscribeKeyboardHeight = vi.mocked(subscribeKeyboardHeight); + +describe('useKeyboardHeight', () => { + let mockUnsubscribe: ReturnType; + + beforeEach(() => { + mockUnsubscribe = vi.fn(); + mockSubscribeKeyboardHeight.mockReturnValue({ unsubscribe: mockUnsubscribe }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('initial state', () => { + it('should return 0 as initial keyboard height', () => { + const { result } = renderHook(() => useKeyboardHeight()); + + expect(result.current.keyboardHeight).toBe(0); + }); + }); + + describe('subscription behavior', () => { + it('should call subscribeKeyboardHeight with immediate: true by default', () => { + renderHook(() => useKeyboardHeight()); + + expect(mockSubscribeKeyboardHeight).toHaveBeenCalledWith({ + callback: expect.any(Function), + immediate: true, + }); + }); + + it('should call subscribeKeyboardHeight with immediate: false when specified', () => { + renderHook(() => useKeyboardHeight({ immediate: false })); + + expect(mockSubscribeKeyboardHeight).toHaveBeenCalledWith({ + callback: expect.any(Function), + immediate: false, + }); + }); + + it('should update keyboard height when callback is invoked', () => { + mockSubscribeKeyboardHeight.mockImplementation(({ callback }) => { + callback(300); + return { unsubscribe: mockUnsubscribe }; + }); + + const { result } = renderHook(() => useKeyboardHeight()); + + expect(result.current.keyboardHeight).toBe(300); + }); + }); + + describe('cleanup behavior', () => { + it('should call unsubscribe on unmount', () => { + const { unmount } = renderHook(() => useKeyboardHeight()); + + expect(mockUnsubscribe).not.toHaveBeenCalled(); + + unmount(); + + expect(mockUnsubscribe).toHaveBeenCalledTimes(1); + }); + + it('should resubscribe when immediate option changes', () => { + const { rerender } = renderHook(({ immediate }) => useKeyboardHeight({ immediate }), { + initialProps: { immediate: true }, + }); + + expect(mockSubscribeKeyboardHeight).toHaveBeenCalledTimes(1); + + rerender({ immediate: false }); + + expect(mockUnsubscribe).toHaveBeenCalledTimes(1); + expect(mockSubscribeKeyboardHeight).toHaveBeenCalledTimes(2); + }); + }); + + describe('keyboard height updates', () => { + it('should track keyboard height changes', () => { + let capturedCallback: ((height: number) => void) | null = null; + + mockSubscribeKeyboardHeight.mockImplementation(({ callback }) => { + capturedCallback = callback; + return { unsubscribe: mockUnsubscribe }; + }); + + const { result } = renderHook(() => useKeyboardHeight()); + + expect(result.current.keyboardHeight).toBe(0); + + act(() => { + capturedCallback?.(250); + }); + + expect(result.current.keyboardHeight).toBe(250); + + act(() => { + capturedCallback?.(0); + }); + + expect(result.current.keyboardHeight).toBe(0); + }); + + it('should handle various keyboard heights', () => { + const heights = [0, 100, 250, 350, 500]; + + for (const expectedHeight of heights) { + mockSubscribeKeyboardHeight.mockImplementation(({ callback }) => { + callback(expectedHeight); + return { unsubscribe: mockUnsubscribe }; + }); + + const { result } = renderHook(() => useKeyboardHeight()); + + expect(result.current.keyboardHeight).toBe(expectedHeight); + } + }); + }); + + describe('use cases', () => { + it('should provide keyboard height for bottom padding adjustment', () => { + mockSubscribeKeyboardHeight.mockImplementation(({ callback }) => { + callback(300); + return { unsubscribe: mockUnsubscribe }; + }); + + const { result } = renderHook(() => useKeyboardHeight()); + + const paddingBottom = `${result.current.keyboardHeight}px`; + expect(paddingBottom).toBe('300px'); + }); + + it('should detect keyboard visibility', () => { + mockSubscribeKeyboardHeight.mockImplementation(({ callback }) => { + callback(300); + return { unsubscribe: mockUnsubscribe }; + }); + + const { result } = renderHook(() => useKeyboardHeight()); + + const isKeyboardVisible = result.current.keyboardHeight > 0; + expect(isKeyboardVisible).toBe(true); + }); + + it('should detect keyboard hidden state', () => { + mockSubscribeKeyboardHeight.mockImplementation(({ callback }) => { + callback(0); + return { unsubscribe: mockUnsubscribe }; + }); + + const { result } = renderHook(() => useKeyboardHeight()); + + const isKeyboardVisible = result.current.keyboardHeight > 0; + expect(isKeyboardVisible).toBe(false); + }); + }); + + describe('multiple instances', () => { + it('should allow multiple independent hook instances', () => { + let callback1: ((height: number) => void) | null = null; + let callback2: ((height: number) => void) | null = null; + + mockSubscribeKeyboardHeight + .mockImplementationOnce(({ callback }) => { + callback1 = callback; + return { unsubscribe: mockUnsubscribe }; + }) + .mockImplementationOnce(({ callback }) => { + callback2 = callback; + return { unsubscribe: mockUnsubscribe }; + }); + + const { result: result1 } = renderHook(() => useKeyboardHeight()); + const { result: result2 } = renderHook(() => useKeyboardHeight()); + + act(() => { + callback1?.(200); + callback2?.(200); + }); + + expect(result1.current.keyboardHeight).toBe(200); + expect(result2.current.keyboardHeight).toBe(200); + }); + }); +}); diff --git a/packages/mobile/src/hooks/keyboardHeight/useKeyboardHeight.ts b/packages/mobile/src/hooks/keyboardHeight/useKeyboardHeight.ts new file mode 100644 index 00000000..dc48d907 --- /dev/null +++ b/packages/mobile/src/hooks/keyboardHeight/useKeyboardHeight.ts @@ -0,0 +1,61 @@ +import { useEffect, useState } from 'react'; + +import { subscribeKeyboardHeight } from '../../utils/keyboard/subscribeKeyboardHeight.ts'; + +type UseKeyboardHeightOptions = { + /** + * If true, the hook will get the initial keyboard height on mount. + * @default true + */ + immediate?: boolean; +}; + +type UseKeyboardHeightResult = { + /** + * The current keyboard height in pixels. + */ + keyboardHeight: number; +}; + +/** + * React hook to track the on-screen keyboard height. + * + * Returns an object containing the current keyboard height in pixels, + * which updates automatically when the keyboard appears, disappears, or changes size. + * + * @param options - Configuration options + * @param options.immediate - If true, gets the initial keyboard height on mount (default: true) + * @returns An object containing the current keyboard height + * + * @example + * ```tsx + * function ChatInput() { + * const { keyboardHeight } = useKeyboardHeight(); + * + * return ( + *
+ * + *
+ * ); + * } + * ``` + */ +export function useKeyboardHeight(options: UseKeyboardHeightOptions = {}): UseKeyboardHeightResult { + const { immediate = true } = options; + + const [keyboardHeight, setKeyboardHeight] = useState(0); + + useEffect( + function subscribeToKeyboardHeight() { + const { unsubscribe } = subscribeKeyboardHeight({ + callback: setKeyboardHeight, + immediate, + }); + + return unsubscribe; + }, + [immediate] + ); + + return { keyboardHeight }; +} diff --git a/packages/mobile/src/hooks/useAvoidKeyboard.test.ts b/packages/mobile/src/hooks/useAvoidKeyboard.test.ts new file mode 100644 index 00000000..2e24c802 --- /dev/null +++ b/packages/mobile/src/hooks/useAvoidKeyboard.test.ts @@ -0,0 +1,171 @@ +import { renderHook } from '@testing-library/react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { useAvoidKeyboard } from './useAvoidKeyboard.ts'; + +// Mock useKeyboardHeight hook +vi.mock('./keyboardHeight/useKeyboardHeight.ts', () => ({ + useKeyboardHeight: vi.fn(() => ({ keyboardHeight: 0 })), +})); + +// Get reference to the mocked function +import { useKeyboardHeight } from './keyboardHeight/useKeyboardHeight.ts'; +const mockUseKeyboardHeight = vi.mocked(useKeyboardHeight); + +describe('useAvoidKeyboard', () => { + beforeEach(() => { + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 0 }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + describe('initial state', () => { + it('should return initial style with keyboard hidden', () => { + const { result } = renderHook(() => useAvoidKeyboard()); + + expect(result.current.style).toEqual({ + transform: 'translateY(0px)', + transition: 'transform 200ms ease-out', + }); + }); + }); + + describe('style generation', () => { + it('should generate correct transform when keyboard is visible', () => { + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 300 }); + + const { result } = renderHook(() => useAvoidKeyboard()); + + expect(result.current.style).toEqual({ + transform: 'translateY(-300px)', + transition: 'transform 200ms ease-out', + }); + }); + + it('should include safeAreaBottom in transform calculation', () => { + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 300 }); + + const { result } = renderHook(() => useAvoidKeyboard({ safeAreaBottom: 20 })); + + expect(result.current.style).toEqual({ + transform: 'translateY(-320px)', + transition: 'transform 200ms ease-out', + }); + }); + + it('should apply custom transition duration', () => { + const { result } = renderHook(() => useAvoidKeyboard({ transitionDuration: 300 })); + + expect(result.current.style.transition).toBe('transform 300ms ease-out'); + }); + + it('should apply custom transition timing function', () => { + const { result } = renderHook(() => + useAvoidKeyboard({ transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)' }) + ); + + expect(result.current.style.transition).toBe('transform 200ms cubic-bezier(0.4, 0, 0.2, 1)'); + }); + + it('should apply all custom options together', () => { + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 250 }); + + const { result } = renderHook(() => + useAvoidKeyboard({ + safeAreaBottom: 30, + transitionDuration: 150, + transitionTimingFunction: 'linear', + }) + ); + + expect(result.current.style).toEqual({ + transform: 'translateY(-280px)', + transition: 'transform 150ms linear', + }); + }); + }); + + describe('keyboard height updates', () => { + it('should update style when keyboard height changes', () => { + const { result, rerender } = renderHook(() => useAvoidKeyboard()); + + expect(result.current.style.transform).toBe('translateY(0px)'); + + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 350 }); + rerender(); + + expect(result.current.style.transform).toBe('translateY(-350px)'); + + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 0 }); + rerender(); + + expect(result.current.style.transform).toBe('translateY(0px)'); + }); + }); + + describe('immediate option', () => { + it('should pass immediate: true by default to useKeyboardHeight', () => { + renderHook(() => useAvoidKeyboard()); + + expect(mockUseKeyboardHeight).toHaveBeenCalledWith({ immediate: true }); + }); + + it('should pass immediate: false when specified', () => { + renderHook(() => useAvoidKeyboard({ immediate: false })); + + expect(mockUseKeyboardHeight).toHaveBeenCalledWith({ immediate: false }); + }); + }); + + describe('use cases', () => { + it('should provide style for fixed bottom CTA', () => { + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 300 }); + + const { result } = renderHook(() => useAvoidKeyboard()); + + const elementStyle = { + position: 'fixed' as const, + bottom: 0, + left: 0, + right: 0, + ...result.current.style, + }; + + expect(elementStyle.transform).toBe('translateY(-300px)'); + expect(elementStyle.transition).toBe('transform 200ms ease-out'); + }); + + it('should handle safe area with safeAreaBottom', () => { + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 300 }); + + const { result } = renderHook(() => useAvoidKeyboard({ safeAreaBottom: 34 })); + + expect(result.current.style.transform).toBe('translateY(-334px)'); + }); + }); + + describe('style memoization', () => { + it('should return same style object when values do not change', () => { + const { result, rerender } = renderHook(() => useAvoidKeyboard()); + + const firstStyle = result.current.style; + + rerender(); + + expect(result.current.style).toBe(firstStyle); + }); + + it('should return new style object when keyboard height changes', () => { + const { result, rerender } = renderHook(() => useAvoidKeyboard()); + + const firstStyle = result.current.style; + + mockUseKeyboardHeight.mockReturnValue({ keyboardHeight: 100 }); + rerender(); + + expect(result.current.style).not.toBe(firstStyle); + }); + }); +}); diff --git a/packages/mobile/src/hooks/useAvoidKeyboard.ts b/packages/mobile/src/hooks/useAvoidKeyboard.ts new file mode 100644 index 00000000..36db4061 --- /dev/null +++ b/packages/mobile/src/hooks/useAvoidKeyboard.ts @@ -0,0 +1,114 @@ +import type { CSSProperties } from 'react'; +import { useMemo } from 'react'; + +import { useKeyboardHeight } from './keyboardHeight/useKeyboardHeight.ts'; + +type UseAvoidKeyboardOptions = { + /** + * Base bottom offset in pixels when keyboard is hidden. + * @default 0 + */ + safeAreaBottom?: number; + /** + * Transition duration in milliseconds for smooth animation. + * @default 200 + */ + transitionDuration?: number; + /** + * Transition timing function for the animation. + * @default 'ease-out' + */ + transitionTimingFunction?: CSSProperties['transitionTimingFunction']; + /** + * If true, the hook will get the initial keyboard height on mount. + * @default true + */ + immediate?: boolean; +}; + +type UseAvoidKeyboardResult = { + /** + * CSS style object to apply to the fixed bottom element. + * Contains transform and transition properties. + */ + style: CSSProperties; +}; + +/** + * React hook to help fixed-bottom elements avoid the on-screen keyboard. + * + * Returns an object containing a CSS style that can be applied to position:fixed elements + * to smoothly move them above the keyboard when it appears. + * + * @param options - Configuration options + * @param options.safeAreaBottom - Base bottom offset in pixels when keyboard is hidden (default: 0) + * @param options.transitionDuration - Transition duration in milliseconds (default: 200) + * @param options.transitionTimingFunction - Transition timing function (default: 'ease-out') + * @param options.immediate - If true, gets the initial keyboard height on mount (default: true) + * + * @returns An object containing the style property + * + * @example + * ```tsx + * function FixedBottomCTA() { + * const { style } = useAvoidKeyboard(); + * + * return ( + *
+ * + *
+ * ); + * } + * ``` + * + * @example + * ```tsx + * // With safe area bottom offset (e.g., for iPhone home indicator) + * function FixedBottomCTA() { + * const { style } = useAvoidKeyboard({ safeAreaBottom: 34 }); + * + * return ( + *
+ * + *
+ * ); + * } + * ``` + */ +export function useAvoidKeyboard(options: UseAvoidKeyboardOptions = {}): UseAvoidKeyboardResult { + const { + safeAreaBottom = 0, + transitionDuration = 200, + transitionTimingFunction = 'ease-out', + immediate = true, + } = options; + + const { keyboardHeight } = useKeyboardHeight({ immediate }); + + const style = useMemo(() => { + const translateY = -(keyboardHeight + safeAreaBottom); + + return { + transform: `translateY(${translateY}px)`, + transition: `transform ${transitionDuration}ms ${transitionTimingFunction}`, + }; + }, [keyboardHeight, safeAreaBottom, transitionDuration, transitionTimingFunction]); + + return { style }; +} diff --git a/packages/mobile/src/hooks/useBodyScrollLock.ssr.test.ts b/packages/mobile/src/hooks/useBodyScrollLock.ssr.test.ts new file mode 100644 index 00000000..b51fcdf1 --- /dev/null +++ b/packages/mobile/src/hooks/useBodyScrollLock.ssr.test.ts @@ -0,0 +1,25 @@ +/** + * @vitest-environment node + * + * SSR environment tests - runs in Node.js where window is truly undefined + */ +import { describe, expect, it } from 'vitest'; + +import { useBodyScrollLock } from './useBodyScrollLock.ts'; + +describe('useBodyScrollLock SSR environment', () => { + it('should be safe on server side rendering', () => { + expect(typeof window).toBe('undefined'); + + // Should not throw during module evaluation + expect(() => useBodyScrollLock).not.toThrow(); + }); + + it('should not throw when imported in SSR', () => { + // In Node environment, window is undefined + expect(typeof window).toBe('undefined'); + + // Just verify the hook can be called (doesn't actually run without React context) + expect(typeof useBodyScrollLock).toBe('function'); + }); +}); diff --git a/packages/mobile/src/hooks/useBodyScrollLock.test.ts b/packages/mobile/src/hooks/useBodyScrollLock.test.ts new file mode 100644 index 00000000..eef812f0 --- /dev/null +++ b/packages/mobile/src/hooks/useBodyScrollLock.test.ts @@ -0,0 +1,82 @@ +import { renderHook } from '@testing-library/react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { useBodyScrollLock } from './useBodyScrollLock.ts'; + +describe('useBodyScrollLock', () => { + beforeEach(() => { + // Reset body styles + document.body.style.cssText = ''; + + // Mock window.scrollY + Object.defineProperty(window, 'scrollY', { + writable: true, + configurable: true, + value: 0, + }); + + // Mock window.scrollTo + window.scrollTo = vi.fn(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should lock body scroll on mount', () => { + renderHook(() => useBodyScrollLock()); + + expect(document.body.style.overflow).toBe('hidden'); + expect(document.body.style.position).toBe('fixed'); + // jsdom normalizes '0' to '0px' + expect(['0', '0px']).toContain(document.body.style.left); + expect(['0', '0px']).toContain(document.body.style.right); + }); + + it('should preserve scroll position with negative top', () => { + Object.defineProperty(window, 'scrollY', { value: 500 }); + + renderHook(() => useBodyScrollLock()); + + expect(document.body.style.top).toBe('-500px'); + }); + + it('should unlock body scroll on unmount', () => { + const { unmount } = renderHook(() => useBodyScrollLock()); + + expect(document.body.style.position).toBe('fixed'); + + unmount(); + + expect(document.body.style.overflow).toBe(''); + expect(document.body.style.position).toBe(''); + expect(document.body.style.top).toBe(''); + expect(document.body.style.left).toBe(''); + expect(document.body.style.right).toBe(''); + }); + + it('should restore scroll position on unmount', () => { + Object.defineProperty(window, 'scrollY', { value: 300 }); + + const { unmount } = renderHook(() => useBodyScrollLock()); + unmount(); + + expect(window.scrollTo).toHaveBeenCalledWith(0, 300); + }); + + it('should handle multiple mount/unmount cycles', () => { + // First cycle + Object.defineProperty(window, 'scrollY', { value: 100 }); + const { unmount: unmount1 } = renderHook(() => useBodyScrollLock()); + expect(document.body.style.top).toBe('-100px'); + unmount1(); + expect(window.scrollTo).toHaveBeenCalledWith(0, 100); + + // Second cycle with different scroll position + Object.defineProperty(window, 'scrollY', { value: 200 }); + const { unmount: unmount2 } = renderHook(() => useBodyScrollLock()); + expect(document.body.style.top).toBe('-200px'); + unmount2(); + expect(window.scrollTo).toHaveBeenLastCalledWith(0, 200); + }); +}); diff --git a/packages/mobile/src/hooks/useBodyScrollLock.ts b/packages/mobile/src/hooks/useBodyScrollLock.ts new file mode 100644 index 00000000..7d7ae01b --- /dev/null +++ b/packages/mobile/src/hooks/useBodyScrollLock.ts @@ -0,0 +1,49 @@ +import { useEffect } from 'react'; + +import { disableBodyScrollLock, enableBodyScrollLock } from '../utils/bodyScrollLock.ts'; + +/** + * Hook to lock body scroll + * + * Automatically locks body scroll when mounted, unlocks when unmounted. + * + * **Note:** For multiple overlapping modals, use a single lock at the parent level. + * + * @example + * ```tsx + * function Modal() { + * useBodyScrollLock(); + * return
Modal content
; + * } + * ``` + * + * @example + * ```tsx + * // Multiple modals - single lock pattern + * function BodyScrollLock() { + * useBodyScrollLock(); + * return null; + * } + * + * function App() { + * const hasModal = showModal1 || showModal2; + * + * return ( + * <> + * {hasModal && } + * {showModal1 && } + * {showModal2 && } + * + * ); + * } + * ``` + */ +export function useBodyScrollLock(): void { + useEffect(() => { + enableBodyScrollLock(); + + return () => { + disableBodyScrollLock(); + }; + }, []); +} diff --git a/packages/mobile/src/hooks/useScrollDirection.ssr.test.ts b/packages/mobile/src/hooks/useScrollDirection.ssr.test.ts new file mode 100644 index 00000000..f9c5803e --- /dev/null +++ b/packages/mobile/src/hooks/useScrollDirection.ssr.test.ts @@ -0,0 +1,25 @@ +/** + * @vitest-environment node + * + * SSR environment tests - runs in Node.js where window is truly undefined + */ +import { describe, expect, it } from 'vitest'; + +import { useScrollDirection } from './useScrollDirection.ts'; + +describe('useScrollDirection SSR environment', () => { + it('should be safe on server side rendering', () => { + expect(typeof window).toBe('undefined'); + + // Should not throw during module evaluation + expect(() => useScrollDirection).not.toThrow(); + }); + + it('should not throw when imported in SSR', () => { + // In Node environment, window is undefined + expect(typeof window).toBe('undefined'); + + // Just verify the hook can be called (doesn't actually run without React context) + expect(typeof useScrollDirection).toBe('function'); + }); +}); diff --git a/packages/mobile/src/hooks/useScrollDirection.test.ts b/packages/mobile/src/hooks/useScrollDirection.test.ts new file mode 100644 index 00000000..eaf4119d --- /dev/null +++ b/packages/mobile/src/hooks/useScrollDirection.test.ts @@ -0,0 +1,355 @@ +import { act, renderHook } from '@testing-library/react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { useScrollDirection } from './useScrollDirection.ts'; + +describe('useScrollDirection', () => { + beforeEach(() => { + vi.useFakeTimers(); + + // Mock window.scrollY + Object.defineProperty(window, 'scrollY', { + writable: true, + configurable: true, + value: 0, + }); + }); + + afterEach(() => { + vi.restoreAllMocks(); + vi.useRealTimers(); + }); + + it('should return initial state with null direction', () => { + const { result } = renderHook(() => useScrollDirection()); + + expect(result.current).toEqual({ + direction: null, + position: 0, + }); + }); + + it('should detect scroll down', async () => { + const { result } = renderHook(() => useScrollDirection()); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 100 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current).toEqual({ + direction: 'down', + position: 100, + }); + }); + + it('should detect scroll up', async () => { + Object.defineProperty(window, 'scrollY', { value: 200 }); + const { result } = renderHook(() => useScrollDirection()); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 100 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current).toEqual({ + direction: 'up', + position: 100, + }); + }); + + it('should not update when scroll position is the same', async () => { + const { result } = renderHook(() => useScrollDirection()); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 0 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + // Direction should remain null as position hasn't changed + expect(result.current).toEqual({ + direction: null, + position: 0, + }); + }); + + it('should throttle scroll events (default 50ms)', async () => { + const { result } = renderHook(() => useScrollDirection()); + + // First scroll - should update + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 50 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(50); + + // Second scroll immediately - should be throttled + Object.defineProperty(window, 'scrollY', { value: 100 }); + window.dispatchEvent(new Event('scroll')); + // Don't advance timers yet - should still be throttled + + // Should still show previous position (throttled) + expect(result.current.position).toBe(50); + + // Advance past throttle period and trigger new scroll + await act(async () => { + vi.advanceTimersByTime(50); + Object.defineProperty(window, 'scrollY', { value: 150 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(150); + }); + + it('should respect custom throttle time', async () => { + const { result } = renderHook(() => useScrollDirection({ throttleMs: 100 })); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 50 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(50); + + // Try to scroll immediately - should be throttled + Object.defineProperty(window, 'scrollY', { value: 100 }); + window.dispatchEvent(new Event('scroll')); + // Advance only 50ms - should still be throttled + vi.advanceTimersByTime(50); + + expect(result.current.position).toBe(50); + + // Advance past throttle period + await act(async () => { + vi.advanceTimersByTime(50); // Total 100ms + Object.defineProperty(window, 'scrollY', { value: 150 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(150); + }); + + it('should handle throttle time of 0', async () => { + const { result } = renderHook(() => useScrollDirection({ throttleMs: 0 })); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 50 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(50); + + await act(async () => { + // With 0ms throttle, should update immediately + Object.defineProperty(window, 'scrollY', { value: 100 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(100); + }); + + it('should remove event listener on unmount', () => { + const removeEventListenerSpy = vi.spyOn(window, 'removeEventListener'); + const { unmount } = renderHook(() => useScrollDirection()); + + unmount(); + + expect(removeEventListenerSpy).toHaveBeenCalledWith('scroll', expect.any(Function)); + }); + + it('should clear throttle timer on unmount', () => { + const clearTimeoutSpy = vi.spyOn(global, 'clearTimeout'); + const { unmount } = renderHook(() => useScrollDirection()); + + act(() => { + Object.defineProperty(window, 'scrollY', { value: 100 }); + window.dispatchEvent(new Event('scroll')); + // Don't run timers - timer should be pending + }); + + unmount(); + + expect(clearTimeoutSpy).toHaveBeenCalled(); + }); + + it('should handle rapid scroll events correctly', async () => { + const { result } = renderHook(() => useScrollDirection()); + + await act(async () => { + // Rapid scrolls + Object.defineProperty(window, 'scrollY', { value: 10 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(10); + + // Try immediate scroll - should be throttled + Object.defineProperty(window, 'scrollY', { value: 20 }); + window.dispatchEvent(new Event('scroll')); + + // Should still show previous position (throttled) + expect(result.current.position).toBe(10); + + // Wait for throttle period + await act(async () => { + vi.advanceTimersByTime(50); + Object.defineProperty(window, 'scrollY', { value: 30 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(30); + expect(result.current.direction).toBe('down'); + }); + + it('should handle scroll direction changes', async () => { + Object.defineProperty(window, 'scrollY', { value: 100 }); + const { result } = renderHook(() => useScrollDirection()); + + // Scroll down + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 200 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.direction).toBe('down'); + + await act(async () => { + vi.advanceTimersByTime(50); + // Scroll up + Object.defineProperty(window, 'scrollY', { value: 150 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.direction).toBe('up'); + + await act(async () => { + vi.advanceTimersByTime(50); + // Scroll down again + Object.defineProperty(window, 'scrollY', { value: 250 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.direction).toBe('down'); + }); + + it('should handle scroll to top (position 0)', async () => { + Object.defineProperty(window, 'scrollY', { value: 500 }); + const { result } = renderHook(() => useScrollDirection()); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 0 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current).toEqual({ + direction: 'up', + position: 0, + }); + }); + + it('should handle large scroll distances', async () => { + const { result } = renderHook(() => useScrollDirection()); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 10000 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current).toEqual({ + direction: 'down', + position: 10000, + }); + }); + + it('should use passive event listener', () => { + const addEventListenerSpy = vi.spyOn(window, 'addEventListener'); + renderHook(() => useScrollDirection()); + + expect(addEventListenerSpy).toHaveBeenCalledWith('scroll', expect.any(Function), { + passive: true, + }); + }); + + it('should handle options update', async () => { + const { result, rerender } = renderHook, { throttleMs: number }>( + ({ throttleMs }) => useScrollDirection({ throttleMs }), + { + initialProps: { throttleMs: 50 }, + } + ); + + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 100 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(100); + + // Update throttle time + await act(async () => { + vi.advanceTimersByTime(50); // Clear previous throttle + rerender({ throttleMs: 200 }); + }); + + // New scroll with updated throttle + await act(async () => { + Object.defineProperty(window, 'scrollY', { value: 200 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(200); + + // Try immediate scroll - should be throttled with new 200ms value + Object.defineProperty(window, 'scrollY', { value: 250 }); + window.dispatchEvent(new Event('scroll')); + vi.advanceTimersByTime(150); // Only 150ms - still throttled + + expect(result.current.position).toBe(200); + + // Wait full throttle period + await act(async () => { + vi.advanceTimersByTime(50); // Total 200ms + Object.defineProperty(window, 'scrollY', { value: 300 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + expect(result.current.position).toBe(300); + }); + + it('should handle edge case with negative scroll (should not happen in practice)', async () => { + // Start with positive scroll + Object.defineProperty(window, 'scrollY', { value: 100 }); + const { result } = renderHook(() => useScrollDirection()); + + await act(async () => { + // Simulating invalid/edge case scenario - scroll to negative + Object.defineProperty(window, 'scrollY', { value: -100 }); + window.dispatchEvent(new Event('scroll')); + vi.runAllTimers(); + }); + + // -100 < 100, so direction should be 'up' + expect(result.current.direction).toBe('up'); + expect(result.current.position).toBe(-100); + }); +}); diff --git a/packages/mobile/src/hooks/useScrollDirection.ts b/packages/mobile/src/hooks/useScrollDirection.ts new file mode 100644 index 00000000..50528e4c --- /dev/null +++ b/packages/mobile/src/hooks/useScrollDirection.ts @@ -0,0 +1,104 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; + +import { isServer } from '../utils/isServer.ts'; + +type ScrollDirection = 'up' | 'down' | null; + +type ScrollDirectionState = { + /** Current scroll direction */ + direction: ScrollDirection; + /** Current scroll Y position (px) */ + position: number; +}; + +type UseScrollDirectionOptions = { + /** Throttle interval (ms) - default: 50ms */ + throttleMs?: number; +}; + +/** + * React hook to detect scroll direction + * + * Returns scroll direction (up/down) and current scroll position. + * Throttled by default (50ms) for performance. + * + * @param options.throttleMs - Throttle interval (default: 50ms) + * @returns Scroll direction state (direction: 'up' | 'down' | null, position: number) + * + * @example + * ```tsx + * function Header() { + * const { direction, position } = useScrollDirection(); + * + * // Hide header on scroll down + * const isHidden = direction === 'down' && position > 100; + * + * return ( + *
+ * My Header + *
+ * ); + * } + * ``` + */ +export function useScrollDirection(options: UseScrollDirectionOptions = {}): ScrollDirectionState { + const { throttleMs = 50 } = options; + + const [scrollInfo, setScrollInfo] = useState({ + direction: null, + position: isServer() ? 0 : window.scrollY, + }); + + const lastScrollYRef = useRef(isServer() ? 0 : window.scrollY); + const throttleTimerRef = useRef | null>(null); + + const updateScrollDirection = useCallback( + ({ currentScrollY, lastScrollY }: { currentScrollY: number; lastScrollY: number }) => { + if (currentScrollY > lastScrollY) { + setScrollInfo({ direction: 'down', position: currentScrollY }); + return; + } + + if (currentScrollY < lastScrollY) { + setScrollInfo({ direction: 'up', position: currentScrollY }); + return; + } + }, + [] + ); + + const startThrottle = useCallback(() => { + throttleTimerRef.current = setTimeout(function clearThrottle() { + throttleTimerRef.current = null; + }, throttleMs); + }, [throttleMs]); + + useEffect( + function handleScrollDirectionChange() { + function handleScroll() { + if (throttleTimerRef.current != null) { + return; + } + + const currentScrollY = window.scrollY; + const lastScrollY = lastScrollYRef.current; + + lastScrollYRef.current = currentScrollY; + startThrottle(); + updateScrollDirection({ currentScrollY, lastScrollY }); + } + + window.addEventListener('scroll', handleScroll, { passive: true }); + + return function cleanup() { + window.removeEventListener('scroll', handleScroll); + if (throttleTimerRef.current != null) { + clearTimeout(throttleTimerRef.current); + } + }; + }, + [startThrottle, updateScrollDirection] + ); + + return scrollInfo; +} diff --git a/packages/mobile/src/hooks/useVisualViewport.ssr.test.ts b/packages/mobile/src/hooks/useVisualViewport.ssr.test.ts new file mode 100644 index 00000000..98d160de --- /dev/null +++ b/packages/mobile/src/hooks/useVisualViewport.ssr.test.ts @@ -0,0 +1,25 @@ +/** + * @vitest-environment node + * + * SSR environment tests - runs in Node.js where window is truly undefined + */ +import { describe, expect, it } from 'vitest'; + +import { useVisualViewport } from './useVisualViewport.ts'; + +describe('useVisualViewport SSR environment', () => { + it('should be safe on server side rendering', () => { + expect(typeof window).toBe('undefined'); + + // Should not throw during module evaluation + expect(() => useVisualViewport).not.toThrow(); + }); + + it('should not throw when imported in SSR', () => { + // In Node environment, window is undefined + expect(typeof window).toBe('undefined'); + + // Just verify the hook can be called (doesn't actually run without React context) + expect(typeof useVisualViewport).toBe('function'); + }); +}); diff --git a/packages/mobile/src/hooks/useVisualViewport.test.ts b/packages/mobile/src/hooks/useVisualViewport.test.ts new file mode 100644 index 00000000..6ffa385f --- /dev/null +++ b/packages/mobile/src/hooks/useVisualViewport.test.ts @@ -0,0 +1,247 @@ +import { act, renderHook } from '@testing-library/react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { useVisualViewport } from './useVisualViewport.ts'; + +describe('useVisualViewport', () => { + let mockVisualViewport: { + width: number; + height: number; + offsetLeft: number; + offsetTop: number; + scale: number; + addEventListener: ReturnType; + removeEventListener: ReturnType; + }; + + beforeEach(() => { + mockVisualViewport = { + width: 375, + height: 667, + offsetLeft: 0, + offsetTop: 0, + scale: 1, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + }; + + Object.defineProperty(window, 'visualViewport', { + writable: true, + configurable: true, + value: mockVisualViewport, + }); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + it('should return initial viewport state', () => { + const { result } = renderHook(() => useVisualViewport()); + + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport).toEqual({ + width: 375, + height: 667, + offsetLeft: 0, + offsetTop: 0, + scale: 1, + }); + }); + + it('should register resize and scroll event listeners on mount', () => { + renderHook(() => useVisualViewport()); + + expect(mockVisualViewport.addEventListener).toHaveBeenCalledWith('resize', expect.any(Function)); + expect(mockVisualViewport.addEventListener).toHaveBeenCalledWith('scroll', expect.any(Function)); + expect(mockVisualViewport.addEventListener).toHaveBeenCalledTimes(2); + }); + + it('should update viewport state on resize event', async () => { + const { result } = renderHook(() => useVisualViewport()); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(([event]) => event === 'resize')?.[1]; + + // Simulate viewport resize (e.g., keyboard appears) + mockVisualViewport.height = 400; + mockVisualViewport.offsetTop = -267; + + await act(async () => { + resizeHandler?.(); + // Wait for startTransition + await new Promise(resolve => setTimeout(resolve, 0)); + }); + + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport).toEqual({ + width: 375, + height: 400, + offsetLeft: 0, + offsetTop: -267, + scale: 1, + }); + }); + + it('should update viewport state on scroll event', async () => { + const { result } = renderHook(() => useVisualViewport()); + + const scrollHandler = mockVisualViewport.addEventListener.mock.calls.find(([event]) => event === 'scroll')?.[1]; + + // Simulate viewport scroll + mockVisualViewport.offsetLeft = 10; + mockVisualViewport.offsetTop = -50; + + await act(async () => { + scrollHandler?.(); + // Wait for startTransition + await new Promise(resolve => setTimeout(resolve, 0)); + }); + + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport).toEqual({ + width: 375, + height: 667, + offsetLeft: 10, + offsetTop: -50, + scale: 1, + }); + }); + + it('should handle pinch-zoom scale changes', async () => { + const { result } = renderHook(() => useVisualViewport()); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(([event]) => event === 'resize')?.[1]; + + // Simulate pinch-zoom + mockVisualViewport.scale = 2.0; + mockVisualViewport.width = 187; // Width halves when scale doubles + mockVisualViewport.height = 333; + + await act(async () => { + resizeHandler?.(); + await new Promise(resolve => setTimeout(resolve, 0)); + }); + + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport?.scale).toBe(2.0); + expect(result.current.viewport?.width).toBe(187); + expect(result.current.viewport?.height).toBe(333); + }); + + it('should remove event listeners on unmount', () => { + const { unmount } = renderHook(() => useVisualViewport()); + + unmount(); + + expect(mockVisualViewport.removeEventListener).toHaveBeenCalledWith('resize', expect.any(Function)); + expect(mockVisualViewport.removeEventListener).toHaveBeenCalledWith('scroll', expect.any(Function)); + expect(mockVisualViewport.removeEventListener).toHaveBeenCalledTimes(2); + }); + + it('should handle missing visualViewport gracefully', () => { + Object.defineProperty(window, 'visualViewport', { + writable: true, + configurable: true, + value: undefined, + }); + + const { result } = renderHook(() => useVisualViewport()); + + expect(result.current.viewport).toBeNull(); + }); + + it('should handle null visualViewport', () => { + Object.defineProperty(window, 'visualViewport', { + writable: true, + configurable: true, + value: null, + }); + + const { result } = renderHook(() => useVisualViewport()); + + expect(result.current.viewport).toBeNull(); + }); + + it('should handle multiple rapid updates correctly', async () => { + const { result } = renderHook(() => useVisualViewport()); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(([event]) => event === 'resize')?.[1]; + + // Simulate multiple rapid viewport changes (e.g., keyboard animation) + await act(async () => { + mockVisualViewport.height = 600; + resizeHandler?.(); + mockVisualViewport.height = 500; + resizeHandler?.(); + mockVisualViewport.height = 400; + resizeHandler?.(); + await new Promise(resolve => setTimeout(resolve, 0)); + }); + + // Should reflect the last update + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport?.height).toBe(400); + }); + + it('should handle edge case with zero dimensions', async () => { + const { result } = renderHook(() => useVisualViewport()); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(([event]) => event === 'resize')?.[1]; + + mockVisualViewport.width = 0; + mockVisualViewport.height = 0; + + await act(async () => { + resizeHandler?.(); + await new Promise(resolve => setTimeout(resolve, 0)); + }); + + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport).toEqual({ + width: 0, + height: 0, + offsetLeft: 0, + offsetTop: 0, + scale: 1, + }); + }); + + it('should handle negative offsetTop (iOS keyboard)', async () => { + const { result } = renderHook(() => useVisualViewport()); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(([event]) => event === 'resize')?.[1]; + + // iOS keyboard scenario + mockVisualViewport.offsetTop = -300; + mockVisualViewport.height = 367; // 667 - 300 + + await act(async () => { + resizeHandler?.(); + await new Promise(resolve => setTimeout(resolve, 0)); + }); + + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport?.offsetTop).toBe(-300); + expect(result.current.viewport?.height).toBe(367); + }); + + it('should handle zoom out scenario (scale < 1)', async () => { + const { result } = renderHook(() => useVisualViewport()); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(([event]) => event === 'resize')?.[1]; + + // Zoom out (rare, but possible with certain viewport settings) + mockVisualViewport.scale = 0.5; + mockVisualViewport.width = 750; + mockVisualViewport.height = 1334; + + await act(async () => { + resizeHandler?.(); + await new Promise(resolve => setTimeout(resolve, 0)); + }); + + expect(result.current.viewport).not.toBeNull(); + expect(result.current.viewport?.scale).toBe(0.5); + expect(result.current.viewport?.width).toBe(750); + }); +}); diff --git a/packages/mobile/src/hooks/useVisualViewport.ts b/packages/mobile/src/hooks/useVisualViewport.ts new file mode 100644 index 00000000..92b88a86 --- /dev/null +++ b/packages/mobile/src/hooks/useVisualViewport.ts @@ -0,0 +1,121 @@ +import { startTransition, useCallback, useEffect, useState } from 'react'; + +import { isServer } from '../utils/isServer.ts'; + +type VisualViewportState = { + /** Viewport width (px) */ + width: number; + /** Viewport height (px) */ + height: number; + /** + * Viewport left offset (px) from the layout viewport + * + * Typically 0 unless horizontal scrolling or panning occurs + */ + offsetLeft: number; + /** + * Viewport top offset (px) from the layout viewport + * + * On iOS: Becomes negative when keyboard appears (e.g., -300px means 300px keyboard height) + * On Android: Typically remains 0 + * + * Use `-offsetTop` to get accurate keyboard height on iOS + */ + offsetTop: number; + /** + * Pinch-zoom scaling factor + * + * - 1.0 = no zoom (default) + * - > 1.0 = zoomed in + * - < 1.0 = zoomed out (rare, depends on viewport settings) + * + * @example + * ```tsx + * const { viewport } = useVisualViewport(); + * if (viewport && viewport.scale > 1.3) { + * // Hide floating UI when user zooms in + * setShowFloatingButton(false); + * } + * ``` + */ + scale: number; +}; + +/** + * React hook to track Visual Viewport changes + * + * Returns the actual visible area in mobile WebView, which changes when + * the keyboard appears or the user zooms/scrolls. + * + * **Important:** `viewport` is `null` on SSR or in browsers that don't support Visual Viewport API. + * Always check for null before accessing viewport properties. + * + * **Tip:** If you only need keyboard height, use `useKeyboardHeight()` instead + * for a simpler API. + * + * @returns Object containing Visual Viewport state or `null` if not supported + * + * @see {@link useKeyboardHeight} - Simpler hook for keyboard height only + * + * @example + * ```tsx + * function CustomLayout() { + * const { viewport } = useVisualViewport(); + * + * // Always check for null first + * if (!viewport) { + * return
Visual Viewport not supported
; + * } + * + * const { width, height, offsetTop, scale } = viewport; + * + * // Hide floating UI when user zooms in + * const showFloatingUI = scale <= 1.3; + * + * return ( + *
+ * {showFloatingUI && } + * Viewport-aware content + *
+ * ); + * } + * ``` + */ +export function useVisualViewport(): { viewport: VisualViewportState | null } { + const visualViewport = isServer() ? null : window.visualViewport; + + const [viewport, setViewport] = useState(() => + visualViewport != null ? getVisualViewportState(visualViewport) : null + ); + + const updateViewportState = useCallback(() => { + startTransition(() => { + setViewport(window.visualViewport != null ? getVisualViewportState(window.visualViewport) : null); + }); + }, []); + + useEffect( + function handleVisualViewportChange() { + window.visualViewport?.addEventListener('resize', updateViewportState); + window.visualViewport?.addEventListener('scroll', updateViewportState); + + return function cleanup() { + window.visualViewport?.removeEventListener('resize', updateViewportState); + window.visualViewport?.removeEventListener('scroll', updateViewportState); + }; + }, + [updateViewportState] + ); + + return { viewport }; +} + +function getVisualViewportState(visualViewport: VisualViewport): VisualViewportState { + return { + width: visualViewport.width, + height: visualViewport.height, + offsetLeft: visualViewport.offsetLeft, + offsetTop: visualViewport.offsetTop, + scale: visualViewport.scale, + }; +} diff --git a/packages/mobile/src/index.ts b/packages/mobile/src/index.ts new file mode 100644 index 00000000..00f6cd98 --- /dev/null +++ b/packages/mobile/src/index.ts @@ -0,0 +1,13 @@ +// Hooks +export { useAvoidKeyboard } from './hooks/useAvoidKeyboard.ts'; +export { useBodyScrollLock } from './hooks/useBodyScrollLock.ts'; +export { useScrollDirection } from './hooks/useScrollDirection.ts'; +export { useVisualViewport } from './hooks/useVisualViewport.ts'; + +// Utils +export { disableBodyScrollLock, enableBodyScrollLock } from './utils/bodyScrollLock.ts'; +export { isAndroid, isIOS } from './utils/device/device.ts'; +export { isServer } from './utils/isServer.ts'; +export { getKeyboardHeight } from './utils/keyboard/getKeyboardHeight.ts'; +export { isKeyboardVisible } from './utils/keyboard/isKeyboardVisible.ts'; +export { subscribeKeyboardHeight } from './utils/keyboard/subscribeKeyboardHeight.ts'; diff --git a/packages/mobile/src/utils/bodyScrollLock.ssr.test.ts b/packages/mobile/src/utils/bodyScrollLock.ssr.test.ts new file mode 100644 index 00000000..13ddb721 --- /dev/null +++ b/packages/mobile/src/utils/bodyScrollLock.ssr.test.ts @@ -0,0 +1,22 @@ +/** + * @vitest-environment node + * + * SSR environment tests - runs in Node.js where window is truly undefined + */ +import { describe, expect, it } from 'vitest'; + +import { disableBodyScrollLock, enableBodyScrollLock } from './bodyScrollLock.ts'; + +describe('bodyScrollLock SSR environment', () => { + it('should do nothing when enableBodyScrollLock is called on server', () => { + // In Node environment, window is undefined + expect(typeof window).toBe('undefined'); + expect(() => enableBodyScrollLock()).not.toThrow(); + }); + + it('should do nothing when disableBodyScrollLock is called on server', () => { + // In Node environment, window is undefined + expect(typeof window).toBe('undefined'); + expect(() => disableBodyScrollLock()).not.toThrow(); + }); +}); diff --git a/packages/mobile/src/utils/bodyScrollLock.test.ts b/packages/mobile/src/utils/bodyScrollLock.test.ts new file mode 100644 index 00000000..23b03733 --- /dev/null +++ b/packages/mobile/src/utils/bodyScrollLock.test.ts @@ -0,0 +1,159 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { disableBodyScrollLock, enableBodyScrollLock } from './bodyScrollLock.ts'; + +describe('bodyScrollLock', () => { + const SCROLL_POSITION_ATTR = 'data-simplikit-scroll-y'; + + beforeEach(() => { + document.body.style.cssText = ''; + document.body.removeAttribute(SCROLL_POSITION_ATTR); + + // Mock window.scrollY + Object.defineProperty(window, 'scrollY', { + writable: true, + configurable: true, + value: 0, + }); + + // Mock window.scrollTo + window.scrollTo = vi.fn(); + }); + + afterEach(() => { + vi.restoreAllMocks(); + }); + + describe('enableBodyScrollLock', () => { + it('should set body styles for scroll lock', () => { + enableBodyScrollLock(); + + expect(document.body.style.overflow).toBe('hidden'); + expect(document.body.style.position).toBe('fixed'); + expect(document.body.style.left).toBe('0px'); + expect(document.body.style.right).toBe('0px'); + expect(document.body.style.bottom).toBe('0px'); + }); + + it('should save current scroll position', () => { + Object.defineProperty(window, 'scrollY', { value: 500 }); + + enableBodyScrollLock(); + + expect(document.body.getAttribute(SCROLL_POSITION_ATTR)).toBe('500'); + expect(document.body.style.top).toBe('-500px'); + }); + + it('should not apply lock twice (prevent duplicate calls)', () => { + Object.defineProperty(window, 'scrollY', { value: 100 }); + enableBodyScrollLock(); + + // Change scroll position and call again + Object.defineProperty(window, 'scrollY', { value: 200 }); + enableBodyScrollLock(); + + // Should still have the first scroll position + expect(document.body.getAttribute(SCROLL_POSITION_ATTR)).toBe('100'); + expect(document.body.style.top).toBe('-100px'); + }); + }); + + describe('disableBodyScrollLock', () => { + it('should restore body styles after unlock', () => { + enableBodyScrollLock(); + disableBodyScrollLock(); + + expect(document.body.style.overflow).toBe(''); + expect(document.body.style.position).toBe(''); + expect(document.body.style.top).toBe(''); + expect(document.body.style.left).toBe(''); + expect(document.body.style.right).toBe(''); + expect(document.body.style.bottom).toBe(''); + }); + + it('should restore scroll position', () => { + Object.defineProperty(window, 'scrollY', { value: 300 }); + + enableBodyScrollLock(); + disableBodyScrollLock(); + + expect(window.scrollTo).toHaveBeenCalledWith(0, 300); + }); + + it('should remove scroll position attribute', () => { + enableBodyScrollLock(); + disableBodyScrollLock(); + + expect(document.body.getAttribute(SCROLL_POSITION_ATTR)).toBeNull(); + }); + + it('should do nothing if not locked', () => { + disableBodyScrollLock(); + + expect(window.scrollTo).not.toHaveBeenCalled(); + }); + }); + + describe('lock/unlock cycle', () => { + it('should handle multiple lock/unlock cycles correctly', () => { + Object.defineProperty(window, 'scrollY', { value: 100 }); + + // First cycle + enableBodyScrollLock(); + expect(document.body.style.position).toBe('fixed'); + disableBodyScrollLock(); + expect(document.body.style.position).toBe(''); + + // Second cycle with different scroll position + Object.defineProperty(window, 'scrollY', { value: 200 }); + enableBodyScrollLock(); + expect(document.body.getAttribute(SCROLL_POSITION_ATTR)).toBe('200'); + disableBodyScrollLock(); + expect(window.scrollTo).toHaveBeenLastCalledWith(0, 200); + }); + }); + + describe('edge cases', () => { + it('should handle zero scroll position', () => { + Object.defineProperty(window, 'scrollY', { value: 0 }); + + enableBodyScrollLock(); + + // Note: `-0px` and `0px` are functionally equivalent + expect(['0px', '-0px']).toContain(document.body.style.top); + expect(document.body.getAttribute(SCROLL_POSITION_ATTR)).toBe('0'); + }); + + it('should handle large scroll position', () => { + Object.defineProperty(window, 'scrollY', { value: 999999 }); + + enableBodyScrollLock(); + + expect(document.body.style.top).toBe('-999999px'); + expect(document.body.getAttribute(SCROLL_POSITION_ATTR)).toBe('999999'); + }); + + it('should handle negative scroll position gracefully', () => { + Object.defineProperty(window, 'scrollY', { value: -100 }); + + enableBodyScrollLock(); + disableBodyScrollLock(); + + expect(window.scrollTo).toHaveBeenCalledWith(0, -100); + }); + + it('should handle invalid scroll position with NaN', () => { + const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {}); + + enableBodyScrollLock(); + // Manually corrupt the saved scroll position + document.body.setAttribute(SCROLL_POSITION_ATTR, 'invalid'); + disableBodyScrollLock(); + + expect(consoleWarnSpy).toHaveBeenCalledWith('[@react-simplikit/mobile] Invalid scroll position, defaulting to 0'); + expect(window.scrollTo).toHaveBeenCalledWith(0, 0); + + consoleWarnSpy.mockRestore(); + }); + }); +}); diff --git a/packages/mobile/src/utils/bodyScrollLock.ts b/packages/mobile/src/utils/bodyScrollLock.ts new file mode 100644 index 00000000..419bcfa7 --- /dev/null +++ b/packages/mobile/src/utils/bodyScrollLock.ts @@ -0,0 +1,110 @@ +import { isServer } from './isServer.ts'; + +/** + * Data attribute key for storing scroll position + */ +const SCROLL_POSITION_ATTR = 'data-simplikit-scroll-y'; + +/** + * Lock body scroll + * + * Prevents the body from scrolling by applying fixed positioning. + * Safe to call in SSR environment (no-op on server). + * Calling multiple times has no effect until unlocked. + * + * @example + * ```ts + * // When modal opens + * enableBodyScrollLock(); + * + * // When modal closes + * disableBodyScrollLock(); + * ``` + */ +export function enableBodyScrollLock(): void { + if (isServer()) { + return; + } + + if (isBodyScrollLocked()) { + return; + } + + const scrollY = window.scrollY; + saveScrollPosition(scrollY); + applyScrollLockStyles(scrollY); +} + +/** + * Unlock body scroll + * + * Unlocks the scroll locked by enableBodyScrollLock() and + * restores the saved scroll position. + * Safe to call in SSR environment (no-op on server). + * Safe to call even if not locked (no-op). + * + * @example + * ```ts + * // When modal closes + * disableBodyScrollLock(); + * ``` + */ +export function disableBodyScrollLock(): void { + if (isServer()) { + return; + } + + const savedScrollY = document.body.getAttribute(SCROLL_POSITION_ATTR); + + if (savedScrollY == null) { + return; + } + + removeScrollLockStyles(); + restoreScrollPosition(savedScrollY); + clearSavedScrollPosition(); +} + +function isBodyScrollLocked(): boolean { + return document.body.getAttribute(SCROLL_POSITION_ATTR) != null; +} + +function saveScrollPosition(scrollY: number): void { + document.body.setAttribute(SCROLL_POSITION_ATTR, scrollY.toString()); +} + +function applyScrollLockStyles(scrollY: number): void { + const { body } = document; + body.style.overflow = 'hidden'; + body.style.position = 'fixed'; + body.style.top = `-${scrollY}px`; + body.style.left = '0px'; + body.style.right = '0px'; + body.style.bottom = '0px'; +} + +function removeScrollLockStyles(): void { + const { body } = document; + body.style.removeProperty('overflow'); + body.style.removeProperty('position'); + body.style.removeProperty('top'); + body.style.removeProperty('left'); + body.style.removeProperty('right'); + body.style.removeProperty('bottom'); +} + +function restoreScrollPosition(savedScrollY: string): void { + const scrollY = Number(savedScrollY); + + if (Number.isNaN(scrollY)) { + console.warn('[@react-simplikit/mobile] Invalid scroll position, defaulting to 0'); + window.scrollTo(0, 0); + return; + } + + window.scrollTo(0, scrollY); +} + +function clearSavedScrollPosition(): void { + document.body.removeAttribute(SCROLL_POSITION_ATTR); +} diff --git a/packages/mobile/src/utils/device/device.test.ts b/packages/mobile/src/utils/device/device.test.ts new file mode 100644 index 00000000..a316d609 --- /dev/null +++ b/packages/mobile/src/utils/device/device.test.ts @@ -0,0 +1,26 @@ +import { describe, expect, it } from 'vitest'; + +import { isAndroid, isIOS } from './device.ts'; + +describe('device utils', () => { + it('should detect iOS', () => { + expect(isIOS('Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X)')).toBe(true); + }); + + it('should detect iPadOS (MacIntel + touch)', () => { + Object.defineProperty(navigator, 'platform', { + value: 'MacIntel', + configurable: true, + }); + Object.defineProperty(navigator, 'maxTouchPoints', { + value: 5, + configurable: true, + }); + + expect(isIOS('Mozilla/5.0 (Macintosh; Intel Mac OS X)')).toBe(true); + }); + + it('should detect Android', () => { + expect(isAndroid('Mozilla/5.0 (Linux; Android 12; Pixel 6) Chrome/120')).toBe(true); + }); +}); diff --git a/packages/mobile/src/utils/device/device.ts b/packages/mobile/src/utils/device/device.ts new file mode 100644 index 00000000..f3b427f7 --- /dev/null +++ b/packages/mobile/src/utils/device/device.ts @@ -0,0 +1,44 @@ +import { isServer } from '../isServer.ts'; + +/** + * Detects whether the current device is running iOS or iPadOS. + * + * Notes on platform inconsistencies: + * - Prior to iPadOS 13, iPads reported their platform as "iPad" (or matched /iPad/ in UA). + * - Starting from iPadOS 13, Apple changed the platform string to "MacIntel" + * to make websites treat iPadOS as desktop-class Safari. + * However, these devices still expose multi-touch capabilities. + * + * @returns `false` on server-side rendering environments. + */ +export function isIOS(userAgent?: string): boolean { + if (isServer()) { + return false; + } + + const ua = userAgent ?? navigator.userAgent; + const platform = navigator.platform; + const maxTouchPoints = navigator.maxTouchPoints; + + const matchesClassicIOS = /iPhone|iPad|iPod/i.test(ua); + const matchesModernIPad = platform === 'MacIntel' && typeof maxTouchPoints === 'number' && maxTouchPoints > 1; + + return matchesClassicIOS || matchesModernIPad; +} + +/** + * Detects whether the current device is running Android. + * + * Notes: + * - All Android browsers include the token "Android" in the user agent. + * + * @returns `false` on server-side rendering environments. + */ +export function isAndroid(userAgent?: string): boolean { + if (isServer()) { + return false; + } + + const ua = userAgent ?? navigator.userAgent; + return /Android/i.test(ua); +} diff --git a/packages/mobile/src/utils/index.ts b/packages/mobile/src/utils/index.ts new file mode 100644 index 00000000..bafa4e85 --- /dev/null +++ b/packages/mobile/src/utils/index.ts @@ -0,0 +1,2 @@ +export { isServer } from './isServer.ts'; +export { enableBodyScrollLock, disableBodyScrollLock } from './bodyScrollLock.ts'; diff --git a/packages/mobile/src/utils/isServer.ssr.test.ts b/packages/mobile/src/utils/isServer.ssr.test.ts new file mode 100644 index 00000000..81aed057 --- /dev/null +++ b/packages/mobile/src/utils/isServer.ssr.test.ts @@ -0,0 +1,25 @@ +/** + * @vitest-environment node + * + * SSR environment tests - runs in Node.js where window is truly undefined + */ +import { describe, expect, it } from 'vitest'; + +import { isServer } from './isServer.ts'; + +describe('isServer SSR environment', () => { + it('should return true in Node.js environment (server-side)', () => { + expect(typeof window).toBe('undefined'); + expect(isServer()).toBe(true); + }); + + it('should return consistent results on multiple calls in SSR', () => { + const firstCall = isServer(); + const secondCall = isServer(); + const thirdCall = isServer(); + + expect(firstCall).toBe(true); + expect(secondCall).toBe(true); + expect(thirdCall).toBe(true); + }); +}); diff --git a/packages/mobile/src/utils/isServer.test.ts b/packages/mobile/src/utils/isServer.test.ts new file mode 100644 index 00000000..9c589d76 --- /dev/null +++ b/packages/mobile/src/utils/isServer.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, it } from 'vitest'; + +import { isServer } from './isServer.ts'; + +describe('isServer', () => { + it('should return false in jsdom environment (client-side)', () => { + expect(typeof window).toBe('object'); + expect(isServer()).toBe(false); + }); + + it('should return consistent results on multiple calls', () => { + const firstCall = isServer(); + const secondCall = isServer(); + const thirdCall = isServer(); + + expect(firstCall).toBe(secondCall); + expect(secondCall).toBe(thirdCall); + }); +}); diff --git a/packages/mobile/src/utils/isServer.ts b/packages/mobile/src/utils/isServer.ts new file mode 100644 index 00000000..3883ecc7 --- /dev/null +++ b/packages/mobile/src/utils/isServer.ts @@ -0,0 +1,19 @@ +/** + * @description Check if the code is running on the server. + * + * @returns {boolean} true if running in a server environment (SSR), false otherwise. + * + * @example + * ```ts + * if (isServer()) { + * // SSR-safe code + * return null; + * } + * + * // Client-only code + * window.addEventListener('resize', handleResize); + * ``` + */ +export function isServer(): boolean { + return typeof window === 'undefined'; +} diff --git a/packages/mobile/src/utils/keyboard/getKeyboardHeight.test.ts b/packages/mobile/src/utils/keyboard/getKeyboardHeight.test.ts new file mode 100644 index 00000000..23aa1be0 --- /dev/null +++ b/packages/mobile/src/utils/keyboard/getKeyboardHeight.test.ts @@ -0,0 +1,86 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; + +import { getKeyboardHeight } from './getKeyboardHeight.ts'; + +describe('getKeyboardHeight', () => { + const originalVisualViewport = window.visualViewport; + + afterEach(() => { + vi.restoreAllMocks(); + Object.defineProperty(window, 'visualViewport', { + value: originalVisualViewport, + writable: true, + configurable: true, + }); + }); + + it('should return 0 when visualViewport is not available', () => { + Object.defineProperty(window, 'visualViewport', { + value: null, + writable: true, + configurable: true, + }); + + expect(getKeyboardHeight()).toBe(0); + }); + + it('should return keyboard height when keyboard is visible', () => { + vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800); + + Object.defineProperty(window, 'visualViewport', { + value: { + height: 500, + offsetTop: 0, + }, + writable: true, + configurable: true, + }); + + expect(getKeyboardHeight()).toBe(300); + }); + + it('should account for offsetTop in iOS behavior', () => { + vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800); + + Object.defineProperty(window, 'visualViewport', { + value: { + height: 450, + offsetTop: 50, + }, + writable: true, + configurable: true, + }); + + expect(getKeyboardHeight()).toBe(300); + }); + + it('should return 0 when keyboard is not visible', () => { + vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800); + + Object.defineProperty(window, 'visualViewport', { + value: { + height: 800, + offsetTop: 0, + }, + writable: true, + configurable: true, + }); + + expect(getKeyboardHeight()).toBe(0); + }); + + it('should return 0 when calculated height is negative', () => { + vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800); + + Object.defineProperty(window, 'visualViewport', { + value: { + height: 900, + offsetTop: 0, + }, + writable: true, + configurable: true, + }); + + expect(getKeyboardHeight()).toBe(0); + }); +}); diff --git a/packages/mobile/src/utils/keyboard/getKeyboardHeight.ts b/packages/mobile/src/utils/keyboard/getKeyboardHeight.ts new file mode 100644 index 00000000..1712aae2 --- /dev/null +++ b/packages/mobile/src/utils/keyboard/getKeyboardHeight.ts @@ -0,0 +1,40 @@ +import { isServer } from '../isServer.ts'; + +/** + * Returns the current on-screen keyboard height in pixels. + * + * This function uses the Visual Viewport API to calculate the keyboard height. + * It assumes a modern environment where Visual Viewport is supported + * (Safari / WKWebView 14+, Chrome / Android WebView 80+). + * + * The keyboard height is computed as: + * window.innerHeight - visualViewport.height - visualViewport.offsetTop + * + * The subtraction of `offsetTop` is required to correctly handle iOS behavior + * where the visual viewport may shift vertically when the keyboard appears. + * + * @returns {number} The keyboard height in pixels. Returns 0 if the keyboard + * is not visible. + * + * @example + * ```ts + * const height = getKeyboardHeight(); + * + * if (height > 0) { + * footer.style.paddingBottom = `${height}px`; + * } + * ``` + */ +export function getKeyboardHeight(): number { + if (isServer()) { + return 0; + } + + const visualViewport = window.visualViewport; + if (visualViewport == null) { + // Defensive guard; not expected to run in supported environments + return 0; + } + const height = window.innerHeight - visualViewport.height - visualViewport.offsetTop; + return Math.max(0, height); +} diff --git a/packages/mobile/src/utils/keyboard/isKeyboardVisible.test.ts b/packages/mobile/src/utils/keyboard/isKeyboardVisible.test.ts new file mode 100644 index 00000000..90f7161d --- /dev/null +++ b/packages/mobile/src/utils/keyboard/isKeyboardVisible.test.ts @@ -0,0 +1,50 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; + +import { getKeyboardHeight } from './getKeyboardHeight.ts'; +import { isKeyboardVisible } from './isKeyboardVisible.ts'; + +vi.mock('./getKeyboardHeight.ts', () => ({ + getKeyboardHeight: vi.fn(), +})); + +const mockGetKeyboardHeight = vi.mocked(getKeyboardHeight); + +describe('isKeyboardVisible', () => { + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should return true when keyboard height is greater than 0', () => { + mockGetKeyboardHeight.mockReturnValue(300); + + expect(isKeyboardVisible()).toBe(true); + }); + + it('should return false when keyboard height is 0', () => { + mockGetKeyboardHeight.mockReturnValue(0); + + expect(isKeyboardVisible()).toBe(false); + }); + + it('should call getKeyboardHeight internally', () => { + mockGetKeyboardHeight.mockReturnValue(0); + + isKeyboardVisible(); + + expect(mockGetKeyboardHeight).toHaveBeenCalledTimes(1); + }); + + describe('edge cases', () => { + it('should return true for small keyboard height', () => { + mockGetKeyboardHeight.mockReturnValue(1); + + expect(isKeyboardVisible()).toBe(true); + }); + + it('should return true for large keyboard height', () => { + mockGetKeyboardHeight.mockReturnValue(500); + + expect(isKeyboardVisible()).toBe(true); + }); + }); +}); diff --git a/packages/mobile/src/utils/keyboard/isKeyboardVisible.ts b/packages/mobile/src/utils/keyboard/isKeyboardVisible.ts new file mode 100644 index 00000000..4812e8d1 --- /dev/null +++ b/packages/mobile/src/utils/keyboard/isKeyboardVisible.ts @@ -0,0 +1,29 @@ +import { getKeyboardHeight } from './getKeyboardHeight.ts'; + +/** + * Checks whether the on-screen keyboard is currently visible. + * + * This function uses `getKeyboardHeight()` internally and returns `true` + * if the keyboard height is greater than 0. + * + * @returns {boolean} `true` if the keyboard is visible, `false` otherwise. + * + * @example + * ```ts + * if (isKeyboardVisible()) { + * console.log('Keyboard is open'); + * } else { + * console.log('Keyboard is closed'); + * } + * ``` + * + * @example + * ```ts + * // Conditionally show/hide elements based on keyboard visibility + * const showFloatingButton = !isKeyboardVisible(); + * ``` + */ +export function isKeyboardVisible(): boolean { + const keyboardHeight = getKeyboardHeight(); + return keyboardHeight > 0; +} diff --git a/packages/mobile/src/utils/keyboard/subscribeKeyboardHeight.test.ts b/packages/mobile/src/utils/keyboard/subscribeKeyboardHeight.test.ts new file mode 100644 index 00000000..98d0b010 --- /dev/null +++ b/packages/mobile/src/utils/keyboard/subscribeKeyboardHeight.test.ts @@ -0,0 +1,359 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; + +import { subscribeKeyboardHeight } from './subscribeKeyboardHeight.ts'; + +describe('subscribeKeyboardHeight', () => { + let mockVisualViewport: { + height: number; + offsetTop: number; + addEventListener: ReturnType; + removeEventListener: ReturnType; + }; + + beforeEach(() => { + vi.useFakeTimers(); + + mockVisualViewport = { + height: 500, + offsetTop: 0, + addEventListener: vi.fn(), + removeEventListener: vi.fn(), + }; + + vi.spyOn(window, 'innerHeight', 'get').mockReturnValue(800); + + Object.defineProperty(window, 'visualViewport', { + value: mockVisualViewport, + writable: true, + configurable: true, + }); + }); + + afterEach(() => { + vi.restoreAllMocks(); + vi.useRealTimers(); + }); + + it('should return an object with unsubscribe function when visualViewport is not available', () => { + Object.defineProperty(window, 'visualViewport', { + value: null, + writable: true, + configurable: true, + }); + + const callback = vi.fn(); + const { unsubscribe } = subscribeKeyboardHeight({ callback }); + + expect(typeof unsubscribe).toBe('function'); + unsubscribe(); // should not throw + }); + + it('should add resize and scroll event listeners', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback }); + + expect(mockVisualViewport.addEventListener).toHaveBeenCalledTimes(2); + expect(mockVisualViewport.addEventListener).toHaveBeenCalledWith('resize', expect.any(Function)); + expect(mockVisualViewport.addEventListener).toHaveBeenCalledWith('scroll', expect.any(Function)); + }); + + it('should call callback with keyboard height on resize event', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 0 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + resizeHandler?.(); + + expect(callback).toHaveBeenCalledWith(300); + }); + + it('should call callback with keyboard height on scroll event', () => { + const callback = vi.fn(); + + // Use immediate to set lastHeight, then change height for scroll test + subscribeKeyboardHeight({ callback, immediate: true, throttleMs: 0 }); + vi.runAllTimers(); + + // Reset callback tracking + callback.mockClear(); + + // Change keyboard height + mockVisualViewport.height = 400; + + const scrollHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'scroll')?.[1]; + + scrollHandler?.(); + + expect(callback).toHaveBeenCalledWith(400); + }); + + it('should not call callback immediately by default', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback }); + + expect(callback).not.toHaveBeenCalled(); + }); + + it('should call callback immediately when immediate option is true', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, immediate: true }); + + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(300); + }); + + it('should remove event listeners when unsubscribe is called', () => { + const callback = vi.fn(); + + const { unsubscribe } = subscribeKeyboardHeight({ callback }); + unsubscribe(); + + expect(mockVisualViewport.removeEventListener).toHaveBeenCalledTimes(2); + expect(mockVisualViewport.removeEventListener).toHaveBeenCalledWith('resize', expect.any(Function)); + expect(mockVisualViewport.removeEventListener).toHaveBeenCalledWith('scroll', expect.any(Function)); + }); + + it('should remove the same handler that was added', () => { + const callback = vi.fn(); + + const { unsubscribe } = subscribeKeyboardHeight({ callback }); + unsubscribe(); + + const addedResizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + const removedResizeHandler = mockVisualViewport.removeEventListener.mock.calls.find( + call => call[0] === 'resize' + )?.[1]; + + expect(addedResizeHandler).toBe(removedResizeHandler); + }); + + describe('throttle behavior', () => { + it('should throttle events by default (16ms)', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // First call - should invoke callback + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(300); + + // Change height and call again immediately - should be throttled + mockVisualViewport.height = 400; + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + + // Wait for throttle to clear + vi.advanceTimersByTime(16); + + // Now should invoke callback + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(2); + expect(callback).toHaveBeenLastCalledWith(400); + }); + + it('should respect custom throttle time', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 100 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // First call + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + + // Change height + mockVisualViewport.height = 400; + + // Wait 50ms - should still be throttled + vi.advanceTimersByTime(50); + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + + // Wait another 50ms (total 100ms) + vi.advanceTimersByTime(50); + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(2); + }); + + it('should handle throttleMs of 0 (no throttling)', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 0 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // First call + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + + // Change height and call immediately - should work with 0ms throttle + mockVisualViewport.height = 400; + vi.advanceTimersByTime(0); + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(2); + }); + }); + + describe('deduplication behavior', () => { + it('should skip callback when height has not changed', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 0 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + const scrollHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'scroll')?.[1]; + + // First resize call + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(300); + + // Scroll call with same height - should be skipped + scrollHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + + // Another resize with same height - should be skipped + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + }); + + it('should call callback when height changes after deduplication', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 0 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // First call + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(300); + + // Same height - skipped + vi.advanceTimersByTime(0); + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + + // Change height + mockVisualViewport.height = 600; + vi.advanceTimersByTime(0); + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(2); + expect(callback).toHaveBeenLastCalledWith(200); + }); + + it('should handle resize and scroll firing simultaneously with same value', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 0 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + const scrollHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'scroll')?.[1]; + + // Simulate simultaneous resize and scroll events + resizeHandler?.(); + scrollHandler?.(); + + // Only one callback should have been invoked due to deduplication + expect(callback).toHaveBeenCalledTimes(1); + expect(callback).toHaveBeenCalledWith(300); + }); + }); + + describe('rapid event firing', () => { + it('should handle rapid events correctly with throttling', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 16 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // Simulate rapid events (100 events) + for (let i = 0; i < 100; i++) { + resizeHandler?.(); + } + + // Should only call once due to throttling and same value + expect(callback).toHaveBeenCalledTimes(1); + }); + + it('should limit callbacks during rapid height changes', () => { + const callback = vi.fn(); + + subscribeKeyboardHeight({ callback, throttleMs: 50 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // First event + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(1); + + // Simulate rapid events with changing heights + for (let i = 0; i < 100; i++) { + mockVisualViewport.height = 500 - i; + resizeHandler?.(); + } + + // Should still be 1 due to throttling + expect(callback).toHaveBeenCalledTimes(1); + + // Wait for throttle to clear + vi.advanceTimersByTime(50); + + // Now trigger another event + mockVisualViewport.height = 200; + resizeHandler?.(); + expect(callback).toHaveBeenCalledTimes(2); + expect(callback).toHaveBeenLastCalledWith(600); + }); + + it('should not exceed reasonable callback count during animation simulation', () => { + const callback = vi.fn(); + + // 50ms throttle + subscribeKeyboardHeight({ callback, throttleMs: 50 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // Simulate 500ms of animation with events every 10ms + // Without throttle: 50 events, With 50ms throttle: ~10 events max + for (let i = 0; i < 50; i++) { + mockVisualViewport.height = 500 - i * 6; // Gradually decrease viewport (keyboard appearing) + resizeHandler?.(); + vi.advanceTimersByTime(10); + } + + // With 50ms throttle, we should have at most 11 calls (500ms / 50ms + 1) + expect(callback.mock.calls.length).toBeLessThanOrEqual(11); + expect(callback.mock.calls.length).toBeGreaterThanOrEqual(1); + }); + }); + + describe('cleanup', () => { + it('should clear throttle timer on unsubscribe', () => { + const clearTimeoutSpy = vi.spyOn(global, 'clearTimeout'); + const callback = vi.fn(); + + const { unsubscribe } = subscribeKeyboardHeight({ callback, throttleMs: 100 }); + + const resizeHandler = mockVisualViewport.addEventListener.mock.calls.find(call => call[0] === 'resize')?.[1]; + + // Trigger an event to start throttle timer + resizeHandler?.(); + + // Unsubscribe while throttle is active + unsubscribe(); + + expect(clearTimeoutSpy).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/mobile/src/utils/keyboard/subscribeKeyboardHeight.ts b/packages/mobile/src/utils/keyboard/subscribeKeyboardHeight.ts new file mode 100644 index 00000000..a0dbe4e2 --- /dev/null +++ b/packages/mobile/src/utils/keyboard/subscribeKeyboardHeight.ts @@ -0,0 +1,122 @@ +import { isServer } from '../isServer.ts'; +import { getKeyboardHeight } from '../keyboard/getKeyboardHeight.ts'; + +type SubscribeKeyboardHeightOptions = { + /** + * A function that will be called with the updated keyboard height in pixels. + */ + callback: (height: number) => void; + /** + * If true, the callback will be invoked immediately with the current keyboard height. + * @default false + */ + immediate?: boolean; + /** + * Throttle interval in milliseconds. + * Events within this interval will be ignored to improve performance. + * @default 16 (~60fps) + */ + throttleMs?: number; +}; + +type SubscribeKeyboardHeightResult = { + /** + * Unsubscribes all listeners and stops receiving keyboard height updates. + */ + unsubscribe: () => void; +}; + +/** + * Subscribes to changes in the on-screen keyboard height. + * + * The provided callback is invoked whenever the keyboard height may change, + * including when the keyboard appears, disappears, or changes size. + * + * Internally, this function listens to both `resize` and `scroll` events + * on the Visual Viewport: + * - `resize`: triggered when the visual viewport height changes + * - `scroll`: triggered when the visual viewport offset changes + * (important for iOS where the viewport can shift without resizing) + * + * Performance optimizations: + * - Throttled by default (16ms, ~60fps) to prevent excessive callback invocations + * - Skips callback when height hasn't changed (deduplication) + * + * @param options - Configuration options + * @param options.callback - A function that will be called with the updated keyboard height in pixels. + * @param options.immediate - If true, the callback will be invoked immediately with the current keyboard height. + * @param options.throttleMs - Throttle interval in milliseconds (default: 16ms). + * + * @returns An object containing the unsubscribe function. + * + * @example + * ```ts + * const { unsubscribe } = subscribeKeyboardHeight({ + * callback: (height) => { + * footer.style.paddingBottom = `${height}px`; + * }, + * immediate: true, + * }); + * + * // Later, when cleanup is needed + * unsubscribe(); + * ``` + */ +export function subscribeKeyboardHeight({ + callback, + immediate = false, + throttleMs = 16, +}: SubscribeKeyboardHeightOptions): SubscribeKeyboardHeightResult { + if (isServer()) { + return { unsubscribe: () => {} }; + } + + const visualViewport = window.visualViewport; + if (!visualViewport) { + return { unsubscribe: () => {} }; + } + + let lastHeight: number | null = null; + let throttleTimer: ReturnType | null = null; + + const handler = () => { + // Skip if throttled + if (throttleTimer != null) { + return; + } + + const currentHeight = getKeyboardHeight(); + + // Skip if height hasn't changed (deduplication) + if (lastHeight === currentHeight) { + return; + } + + lastHeight = currentHeight; + callback(currentHeight); + + // Start throttle timer + throttleTimer = setTimeout(() => { + throttleTimer = null; + }, throttleMs); + }; + + if (immediate) { + const currentHeight = getKeyboardHeight(); + lastHeight = currentHeight; + callback(currentHeight); + } + + visualViewport.addEventListener('resize', handler); + visualViewport.addEventListener('scroll', handler); + + return { + unsubscribe: () => { + visualViewport.removeEventListener('resize', handler); + visualViewport.removeEventListener('scroll', handler); + if (throttleTimer != null) { + clearTimeout(throttleTimer); + } + }, + }; +} diff --git a/packages/mobile/tsconfig.json b/packages/mobile/tsconfig.json new file mode 100644 index 00000000..41818e82 --- /dev/null +++ b/packages/mobile/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "noEmit": true, + "allowImportingTsExtensions": true, + "moduleResolution": "Bundler", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "jsx": "react-jsx", + "paths": { + "@react-simplikit/mobile": ["./src/index.ts"] + } + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/mobile/tsup.config.ts b/packages/mobile/tsup.config.ts new file mode 100644 index 00000000..8caf8450 --- /dev/null +++ b/packages/mobile/tsup.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from 'tsup'; + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['esm', 'cjs'], + dts: true, + clean: true, + sourcemap: true, + splitting: false, + // To support React Server Components + banner: { + js: '"use client";', + }, +}); diff --git a/packages/mobile/vitest.config.ts b/packages/mobile/vitest.config.ts new file mode 100644 index 00000000..c3419289 --- /dev/null +++ b/packages/mobile/vitest.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + environment: 'jsdom', + setupFiles: ['./vitest.setup.ts'], + globals: true, + sequence: { + concurrent: false, + }, + coverage: { + provider: 'v8', + reporter: ['text', 'json'], + extension: ['.ts', '.tsx'], + include: ['src/**/*.ts?(x)'], + exclude: ['src/**/index.ts', 'src/**/*.spec.ts?(x)'], + }, + }, +}); diff --git a/packages/mobile/vitest.setup.ts b/packages/mobile/vitest.setup.ts new file mode 100644 index 00000000..5b1c53e2 --- /dev/null +++ b/packages/mobile/vitest.setup.ts @@ -0,0 +1,11 @@ +import '@testing-library/jest-dom/vitest'; +import { cleanup } from '@testing-library/react'; +import { afterEach } from 'vitest'; + +import { TextEncoder } from 'util'; +global.TextEncoder = TextEncoder; + +// Cleanup after each test for @testing-library/react +afterEach(() => { + cleanup(); +}); diff --git a/tsconfig.json b/tsconfig.json index fb992aac..b4e392d3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,7 +13,7 @@ "jsx": "react-jsx", "types": ["@testing-library/jest-dom"] }, - "include": ["src", ".scripts/**/*"], + "include": ["src", "packages/**/src", ".scripts/**/*"], "vueCompilerOptions": { "vitePressExtensions": [".md"] } diff --git a/yarn.lock b/yarn.lock index 7c3fb04e..bf53b852 100644 --- a/yarn.lock +++ b/yarn.lock @@ -231,6 +231,47 @@ __metadata: languageName: node linkType: hard +"@babel/code-frame@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/code-frame@npm:7.27.1" + dependencies: + "@babel/helper-validator-identifier": "npm:^7.27.1" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10c0/5dd9a18baa5fce4741ba729acc3a3272c49c25cb8736c4b18e113099520e7ef7b545a4096a26d600e4416157e63e87d66db46aa3fbf0a5f2286da2705c12da00 + languageName: node + linkType: hard + +"@babel/compat-data@npm:^7.27.2": + version: 7.28.5 + resolution: "@babel/compat-data@npm:7.28.5" + checksum: 10c0/702a25de73087b0eba325c1d10979eed7c9b6662677386ba7b5aa6eace0fc0676f78343bae080a0176ae26f58bd5535d73b9d0fbb547fef377692e8b249353a7 + languageName: node + linkType: hard + +"@babel/core@npm:^7.28.0": + version: 7.28.5 + resolution: "@babel/core@npm:7.28.5" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.28.5" + "@babel/helper-compilation-targets": "npm:^7.27.2" + "@babel/helper-module-transforms": "npm:^7.28.3" + "@babel/helpers": "npm:^7.28.4" + "@babel/parser": "npm:^7.28.5" + "@babel/template": "npm:^7.27.2" + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + "@jridgewell/remapping": "npm:^2.3.5" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 10c0/535f82238027621da6bdffbdbe896ebad3558b311d6f8abc680637a9859b96edbf929ab010757055381570b29cf66c4a295b5618318d27a4273c0e2033925e72 + languageName: node + linkType: hard + "@babel/generator@npm:^7.26.5, @babel/generator@npm:^7.27.0": version: 7.27.0 resolution: "@babel/generator@npm:7.27.0" @@ -244,6 +285,69 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/generator@npm:7.28.5" + dependencies: + "@babel/parser": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10c0/9f219fe1d5431b6919f1a5c60db8d5d34fe546c0d8f5a8511b32f847569234ffc8032beb9e7404649a143f54e15224ecb53a3d11b6bb85c3203e573d91fca752 + languageName: node + linkType: hard + +"@babel/helper-compilation-targets@npm:^7.27.2": + version: 7.27.2 + resolution: "@babel/helper-compilation-targets@npm:7.27.2" + dependencies: + "@babel/compat-data": "npm:^7.27.2" + "@babel/helper-validator-option": "npm:^7.27.1" + browserslist: "npm:^4.24.0" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: 10c0/f338fa00dcfea931804a7c55d1a1c81b6f0a09787e528ec580d5c21b3ecb3913f6cb0f361368973ce953b824d910d3ac3e8a8ee15192710d3563826447193ad1 + languageName: node + linkType: hard + +"@babel/helper-globals@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/helper-globals@npm:7.28.0" + checksum: 10c0/5a0cd0c0e8c764b5f27f2095e4243e8af6fa145daea2b41b53c0c1414fe6ff139e3640f4e2207ae2b3d2153a1abd346f901c26c290ee7cb3881dd922d4ee9232 + languageName: node + linkType: hard + +"@babel/helper-module-imports@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-module-imports@npm:7.27.1" + dependencies: + "@babel/traverse": "npm:^7.27.1" + "@babel/types": "npm:^7.27.1" + checksum: 10c0/e00aace096e4e29290ff8648455c2bc4ed982f0d61dbf2db1b5e750b9b98f318bf5788d75a4f974c151bd318fd549e81dbcab595f46b14b81c12eda3023f51e8 + languageName: node + linkType: hard + +"@babel/helper-module-transforms@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/helper-module-transforms@npm:7.28.3" + dependencies: + "@babel/helper-module-imports": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.3" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/549be62515a6d50cd4cfefcab1b005c47f89bd9135a22d602ee6a5e3a01f27571868ada10b75b033569f24dc4a2bb8d04bfa05ee75c16da7ade2d0db1437fcdb + languageName: node + linkType: hard + +"@babel/helper-plugin-utils@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-plugin-utils@npm:7.27.1" + checksum: 10c0/94cf22c81a0c11a09b197b41ab488d416ff62254ce13c57e62912c85700dc2e99e555225787a4099ff6bae7a1812d622c80fbaeda824b79baa10a6c5ac4cf69b + languageName: node + linkType: hard + "@babel/helper-string-parser@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-string-parser@npm:7.25.9" @@ -251,6 +355,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-string-parser@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-string-parser@npm:7.27.1" + checksum: 10c0/8bda3448e07b5583727c103560bcf9c4c24b3c1051a4c516d4050ef69df37bb9a4734a585fe12725b8c2763de0a265aa1e909b485a4e3270b7cfd3e4dbe4b602 + languageName: node + linkType: hard + "@babel/helper-validator-identifier@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-validator-identifier@npm:7.25.9" @@ -258,6 +369,41 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.27.1, @babel/helper-validator-identifier@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-validator-identifier@npm:7.28.5" + checksum: 10c0/42aaebed91f739a41f3d80b72752d1f95fd7c72394e8e4bd7cdd88817e0774d80a432451bcba17c2c642c257c483bf1d409dd4548883429ea9493a3bc4ab0847 + languageName: node + linkType: hard + +"@babel/helper-validator-option@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-option@npm:7.27.1" + checksum: 10c0/6fec5f006eba40001a20f26b1ef5dbbda377b7b68c8ad518c05baa9af3f396e780bdfded24c4eef95d14bb7b8fd56192a6ed38d5d439b97d10efc5f1a191d148 + languageName: node + linkType: hard + +"@babel/helpers@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/helpers@npm:7.28.4" + dependencies: + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.28.4" + checksum: 10c0/aaa5fb8098926dfed5f223adf2c5e4c7fbba4b911b73dfec2d7d3083f8ba694d201a206db673da2d9b3ae8c01793e795767654558c450c8c14b4c2175b4fcb44 + languageName: node + linkType: hard + +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.27.2, @babel/parser@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/parser@npm:7.28.5" + dependencies: + "@babel/types": "npm:^7.28.5" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef + languageName: node + linkType: hard + "@babel/parser@npm:^7.25.3, @babel/parser@npm:^7.25.4, @babel/parser@npm:^7.25.7, @babel/parser@npm:^7.26.7, @babel/parser@npm:^7.27.0": version: 7.27.0 resolution: "@babel/parser@npm:7.27.0" @@ -269,6 +415,28 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-react-jsx-self@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/00a4f917b70a608f9aca2fb39aabe04a60aa33165a7e0105fd44b3a8531630eb85bf5572e9f242f51e6ad2fa38c2e7e780902176c863556c58b5ba6f6e164031 + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-source@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.27.1" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/5e67b56c39c4d03e59e03ba80692b24c5a921472079b63af711b1d250fc37c1733a17069b63537f750f3e937ec44a42b1ee6a46cd23b1a0df5163b17f741f7f2 + languageName: node + linkType: hard + "@babel/runtime@npm:^7.12.5": version: 7.27.0 resolution: "@babel/runtime@npm:7.27.0" @@ -296,6 +464,17 @@ __metadata: languageName: node linkType: hard +"@babel/template@npm:^7.27.2": + version: 7.27.2 + resolution: "@babel/template@npm:7.27.2" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/parser": "npm:^7.27.2" + "@babel/types": "npm:^7.27.1" + checksum: 10c0/ed9e9022651e463cc5f2cc21942f0e74544f1754d231add6348ff1b472985a3b3502041c0be62dc99ed2d12cfae0c51394bf827452b98a2f8769c03b87aadc81 + languageName: node + linkType: hard + "@babel/traverse@npm:^7.26.7": version: 7.27.0 resolution: "@babel/traverse@npm:7.27.0" @@ -311,6 +490,31 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/traverse@npm:7.28.5" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.28.5" + "@babel/helper-globals": "npm:^7.28.0" + "@babel/parser": "npm:^7.28.5" + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.28.5" + debug: "npm:^4.3.1" + checksum: 10c0/f6c4a595993ae2b73f2d4cd9c062f2e232174d293edd4abe1d715bd6281da8d99e47c65857e8d0917d9384c65972f4acdebc6749a7c40a8fcc38b3c7fb3e706f + languageName: node + linkType: hard + +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.27.1, @babel/types@npm:^7.28.2, @babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/types@npm:7.28.5" + dependencies: + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.28.5" + checksum: 10c0/a5a483d2100befbf125793640dec26b90b95fd233a94c19573325898a5ce1e52cdfa96e495c7dcc31b5eca5b66ce3e6d4a0f5a4a62daec271455959f208ab08a + languageName: node + linkType: hard + "@babel/types@npm:^7.25.4, @babel/types@npm:^7.26.7, @babel/types@npm:^7.27.0": version: 7.27.0 resolution: "@babel/types@npm:7.27.0" @@ -672,6 +876,15 @@ __metadata: languageName: node linkType: hard +"@emnapi/runtime@npm:^1.7.0": + version: 1.8.1 + resolution: "@emnapi/runtime@npm:1.8.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/f4929d75e37aafb24da77d2f58816761fe3f826aad2e37fa6d4421dac9060cbd5098eea1ac3c9ecc4526b89deb58153852fa432f87021dc57863f2ff726d713f + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/aix-ppc64@npm:0.21.5" @@ -693,6 +906,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/aix-ppc64@npm:0.27.2" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/android-arm64@npm:0.21.5" @@ -714,6 +934,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm64@npm:0.27.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/android-arm@npm:0.21.5" @@ -735,6 +962,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm@npm:0.27.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/android-x64@npm:0.21.5" @@ -756,6 +990,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-x64@npm:0.27.2" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/darwin-arm64@npm:0.21.5" @@ -777,6 +1018,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-arm64@npm:0.27.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/darwin-x64@npm:0.21.5" @@ -798,6 +1046,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-x64@npm:0.27.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/freebsd-arm64@npm:0.21.5" @@ -819,6 +1074,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-arm64@npm:0.27.2" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/freebsd-x64@npm:0.21.5" @@ -840,6 +1102,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-x64@npm:0.27.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-arm64@npm:0.21.5" @@ -861,6 +1130,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm64@npm:0.27.2" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-arm@npm:0.21.5" @@ -882,6 +1158,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm@npm:0.27.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-ia32@npm:0.21.5" @@ -903,6 +1186,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ia32@npm:0.27.2" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-loong64@npm:0.21.5" @@ -924,6 +1214,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-loong64@npm:0.27.2" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-mips64el@npm:0.21.5" @@ -945,6 +1242,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-mips64el@npm:0.27.2" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-ppc64@npm:0.21.5" @@ -966,6 +1270,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ppc64@npm:0.27.2" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-riscv64@npm:0.21.5" @@ -987,6 +1298,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-riscv64@npm:0.27.2" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-s390x@npm:0.21.5" @@ -1008,6 +1326,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-s390x@npm:0.27.2" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/linux-x64@npm:0.21.5" @@ -1029,6 +1354,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-x64@npm:0.27.2" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-arm64@npm:0.24.2": version: 0.24.2 resolution: "@esbuild/netbsd-arm64@npm:0.24.2" @@ -1043,6 +1375,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-arm64@npm:0.27.2" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/netbsd-x64@npm:0.21.5" @@ -1064,6 +1403,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-x64@npm:0.27.2" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-arm64@npm:0.24.2": version: 0.24.2 resolution: "@esbuild/openbsd-arm64@npm:0.24.2" @@ -1078,6 +1424,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-arm64@npm:0.27.2" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/openbsd-x64@npm:0.21.5" @@ -1099,6 +1452,20 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-x64@npm:0.27.2" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openharmony-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openharmony-arm64@npm:0.27.2" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/sunos-x64@npm:0.21.5" @@ -1120,6 +1487,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/sunos-x64@npm:0.27.2" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/win32-arm64@npm:0.21.5" @@ -1141,6 +1515,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-arm64@npm:0.27.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/win32-ia32@npm:0.21.5" @@ -1162,6 +1543,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-ia32@npm:0.27.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.21.5": version: 0.21.5 resolution: "@esbuild/win32-x64@npm:0.21.5" @@ -1183,6 +1571,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-x64@npm:0.27.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.5.1 resolution: "@eslint-community/eslint-utils@npm:4.5.1" @@ -1332,6 +1727,233 @@ __metadata: languageName: node linkType: hard +"@img/colour@npm:^1.0.0": + version: 1.0.0 + resolution: "@img/colour@npm:1.0.0" + checksum: 10c0/02261719c1e0d7aa5a2d585981954f2ac126f0c432400aa1a01b925aa2c41417b7695da8544ee04fd29eba7ecea8eaf9b8bef06f19dc8faba78f94eeac40667d + languageName: node + linkType: hard + +"@img/sharp-darwin-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-darwin-arm64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-darwin-arm64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-arm64": + optional: true + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-darwin-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-darwin-x64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-darwin-x64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-x64": + optional: true + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-arm64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-darwin-arm64@npm:1.2.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-x64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-darwin-x64@npm:1.2.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-arm64@npm:1.2.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-arm@npm:1.2.4" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-ppc64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-ppc64@npm:1.2.4" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-riscv64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-riscv64@npm:1.2.4" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-s390x@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-s390x@npm:1.2.4" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-x64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-x64@npm:1.2.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-arm64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.2.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-x64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.2.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linux-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-arm64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-arm64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-arm@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-arm@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-arm": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-arm": + optional: true + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-ppc64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-ppc64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-ppc64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-ppc64": + optional: true + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-riscv64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-riscv64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-riscv64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-riscv64": + optional: true + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-s390x@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-s390x@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-s390x": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-s390x": + optional: true + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-x64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-x64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linuxmusl-arm64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linuxmusl-x64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linuxmusl-x64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-wasm32@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-wasm32@npm:0.34.5" + dependencies: + "@emnapi/runtime": "npm:^1.7.0" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@img/sharp-win32-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-win32-arm64@npm:0.34.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-win32-ia32@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-win32-ia32@npm:0.34.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@img/sharp-win32-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-win32-x64@npm:0.34.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@inquirer/external-editor@npm:^1.0.0": version: 1.0.2 resolution: "@inquirer/external-editor@npm:1.0.2" @@ -1377,6 +1999,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/gen-mapping@npm:^0.3.12": + version: 0.3.13 + resolution: "@jridgewell/gen-mapping@npm:0.3.13" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.0" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/9a7d65fb13bd9aec1fbab74cda08496839b7e2ceb31f5ab922b323e94d7c481ce0fc4fd7e12e2610915ed8af51178bdc61e168e92a8c8b8303b030b03489b13b + languageName: node + linkType: hard + "@jridgewell/gen-mapping@npm:^0.3.2, @jridgewell/gen-mapping@npm:^0.3.5": version: 0.3.8 resolution: "@jridgewell/gen-mapping@npm:0.3.8" @@ -1388,6 +2020,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 + languageName: node + linkType: hard + "@jridgewell/resolve-uri@npm:^3.1.0": version: 3.1.2 resolution: "@jridgewell/resolve-uri@npm:3.1.2" @@ -1419,6 +2061,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/trace-mapping@npm:^0.3.28": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/4b30ec8cd56c5fd9a661f088230af01e0c1a3888d11ffb6b47639700f71225be21d1f7e168048d6d4f9449207b978a235c07c8f15c07705685d16dc06280e9d9 + languageName: node + linkType: hard + "@manypkg/find-root@npm:^1.1.0": version: 1.1.0 resolution: "@manypkg/find-root@npm:1.1.0" @@ -1431,17 +2083,80 @@ __metadata: languageName: node linkType: hard -"@manypkg/get-packages@npm:^1.1.3": - version: 1.1.3 - resolution: "@manypkg/get-packages@npm:1.1.3" - dependencies: - "@babel/runtime": "npm:^7.5.5" - "@changesets/types": "npm:^4.0.1" - "@manypkg/find-root": "npm:^1.1.0" - fs-extra: "npm:^8.1.0" - globby: "npm:^11.0.0" - read-yaml-file: "npm:^1.1.0" - checksum: 10c0/f05907d1174ae28861eaa06d0efdc144f773d9a4b8b65e1e7cdc01eb93361d335351b4a336e05c6aac02661be39e8809a3f7ad28bc67b6b338071434ab442130 +"@manypkg/get-packages@npm:^1.1.3": + version: 1.1.3 + resolution: "@manypkg/get-packages@npm:1.1.3" + dependencies: + "@babel/runtime": "npm:^7.5.5" + "@changesets/types": "npm:^4.0.1" + "@manypkg/find-root": "npm:^1.1.0" + fs-extra: "npm:^8.1.0" + globby: "npm:^11.0.0" + read-yaml-file: "npm:^1.1.0" + checksum: 10c0/f05907d1174ae28861eaa06d0efdc144f773d9a4b8b65e1e7cdc01eb93361d335351b4a336e05c6aac02661be39e8809a3f7ad28bc67b6b338071434ab442130 + languageName: node + linkType: hard + +"@next/env@npm:15.5.9": + version: 15.5.9 + resolution: "@next/env@npm:15.5.9" + checksum: 10c0/92c4e29d81a8e78c33c2da179648a4f478a9a6852966192e079007b19ec9955e72530d5ca7df55ea0efeccbf5b1c9d0efcaf80433e26af89c6478193e1d088f1 + languageName: node + linkType: hard + +"@next/swc-darwin-arm64@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-darwin-arm64@npm:15.5.7" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@next/swc-darwin-x64@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-darwin-x64@npm:15.5.7" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@next/swc-linux-arm64-gnu@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-linux-arm64-gnu@npm:15.5.7" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@next/swc-linux-arm64-musl@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-linux-arm64-musl@npm:15.5.7" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@next/swc-linux-x64-gnu@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-linux-x64-gnu@npm:15.5.7" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@next/swc-linux-x64-musl@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-linux-x64-musl@npm:15.5.7" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@next/swc-win32-arm64-msvc@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-win32-arm64-msvc@npm:15.5.7" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@next/swc-win32-x64-msvc@npm:15.5.7": + version: 15.5.7 + resolution: "@next/swc-win32-x64-msvc@npm:15.5.7" + conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1508,6 +2223,33 @@ __metadata: languageName: node linkType: hard +"@react-simplikit/mobile@workspace:*, @react-simplikit/mobile@workspace:packages/mobile": + version: 0.0.0-use.local + resolution: "@react-simplikit/mobile@workspace:packages/mobile" + dependencies: + "@testing-library/dom": "npm:^10.4.0" + "@testing-library/jest-dom": "npm:^6.6.3" + "@testing-library/react": "npm:^16.1.0" + "@types/react": "npm:^19.0.0" + "@types/react-dom": "npm:^19.0.0" + react: "npm:^19.0.0" + react-dom: "npm:^19.0.0" + rimraf: "npm:^6.0.1" + tsup: "npm:^8.3.5" + typescript: "npm:^5.7.2" + vitest: "npm:^2.1.8" + peerDependencies: + react: ">=18.0.0" + languageName: unknown + linkType: soft + +"@rolldown/pluginutils@npm:1.0.0-beta.27": + version: 1.0.0-beta.27 + resolution: "@rolldown/pluginutils@npm:1.0.0-beta.27" + checksum: 10c0/9658f235b345201d4f6bfb1f32da9754ca164f892d1cb68154fe5f53c1df42bd675ecd409836dff46884a7847d6c00bdc38af870f7c81e05bba5c2645eb4ab9c + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-android-arm-eabi@npm:4.39.0" @@ -1515,6 +2257,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.55.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@rollup/rollup-android-arm64@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-android-arm64@npm:4.39.0" @@ -1522,6 +2271,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm64@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-android-arm64@npm:4.55.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-arm64@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-darwin-arm64@npm:4.39.0" @@ -1529,6 +2285,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-arm64@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.55.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-darwin-x64@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-darwin-x64@npm:4.39.0" @@ -1536,6 +2299,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-darwin-x64@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.55.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-arm64@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-freebsd-arm64@npm:4.39.0" @@ -1543,6 +2313,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-arm64@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.55.1" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-freebsd-x64@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-freebsd-x64@npm:4.39.0" @@ -1550,6 +2327,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-freebsd-x64@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-freebsd-x64@npm:4.55.1" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-gnueabihf@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.39.0" @@ -1557,6 +2341,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-gnueabihf@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.55.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm-musleabihf@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.39.0" @@ -1564,6 +2355,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm-musleabihf@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.55.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-gnu@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.39.0" @@ -1571,6 +2369,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-gnu@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.55.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-arm64-musl@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-arm64-musl@npm:4.39.0" @@ -1578,6 +2383,27 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-arm64-musl@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.55.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-loong64-gnu@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.55.1" + conditions: os=linux & cpu=loong64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-loong64-musl@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-loong64-musl@npm:4.55.1" + conditions: os=linux & cpu=loong64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-loongarch64-gnu@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.39.0" @@ -1592,6 +2418,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-ppc64-gnu@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.55.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-ppc64-musl@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.55.1" + conditions: os=linux & cpu=ppc64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-gnu@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.39.0" @@ -1599,6 +2439,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-gnu@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.55.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-riscv64-musl@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.39.0" @@ -1606,6 +2453,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-riscv64-musl@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.55.1" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + "@rollup/rollup-linux-s390x-gnu@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.39.0" @@ -1613,6 +2467,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-s390x-gnu@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.55.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-gnu@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-x64-gnu@npm:4.39.0" @@ -1620,6 +2481,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-gnu@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.55.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + "@rollup/rollup-linux-x64-musl@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-linux-x64-musl@npm:4.39.0" @@ -1627,6 +2495,27 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-linux-x64-musl@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.55.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-openbsd-x64@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-openbsd-x64@npm:4.55.1" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-openharmony-arm64@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.55.1" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-arm64-msvc@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.39.0" @@ -1634,6 +2523,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-arm64-msvc@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.55.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@rollup/rollup-win32-ia32-msvc@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.39.0" @@ -1641,6 +2537,20 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-ia32-msvc@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.55.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-gnu@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.55.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rollup/rollup-win32-x64-msvc@npm:4.39.0": version: 4.39.0 resolution: "@rollup/rollup-win32-x64-msvc@npm:4.39.0" @@ -1648,6 +2558,13 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-win32-x64-msvc@npm:4.55.1": + version: 4.55.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.55.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rtsao/scc@npm:^1.1.0": version: 1.1.0 resolution: "@rtsao/scc@npm:1.1.0" @@ -1735,6 +2652,15 @@ __metadata: languageName: node linkType: hard +"@swc/helpers@npm:0.5.15": + version: 0.5.15 + resolution: "@swc/helpers@npm:0.5.15" + dependencies: + tslib: "npm:^2.8.0" + checksum: 10c0/33002f74f6f885f04c132960835fdfc474186983ea567606db62e86acd0680ca82f34647e8e610f4e1e422d1c16fce729dde22cd3b797ab1fd9061a825dabca4 + languageName: node + linkType: hard + "@testing-library/dom@npm:^10.4.0": version: 10.4.0 resolution: "@testing-library/dom@npm:10.4.0" @@ -1819,6 +2745,47 @@ __metadata: languageName: node linkType: hard +"@types/babel__core@npm:^7.20.5": + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" + dependencies: + "@babel/parser": "npm:^7.20.7" + "@babel/types": "npm:^7.20.7" + "@types/babel__generator": "npm:*" + "@types/babel__template": "npm:*" + "@types/babel__traverse": "npm:*" + checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff + languageName: node + linkType: hard + +"@types/babel__generator@npm:*": + version: 7.27.0 + resolution: "@types/babel__generator@npm:7.27.0" + dependencies: + "@babel/types": "npm:^7.0.0" + checksum: 10c0/9f9e959a8792df208a9d048092fda7e1858bddc95c6314857a8211a99e20e6830bdeb572e3587ae8be5429e37f2a96fcf222a9f53ad232f5537764c9e13a2bbd + languageName: node + linkType: hard + +"@types/babel__template@npm:*": + version: 7.4.4 + resolution: "@types/babel__template@npm:7.4.4" + dependencies: + "@babel/parser": "npm:^7.1.0" + "@babel/types": "npm:^7.0.0" + checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b + languageName: node + linkType: hard + +"@types/babel__traverse@npm:*": + version: 7.28.0 + resolution: "@types/babel__traverse@npm:7.28.0" + dependencies: + "@babel/types": "npm:^7.28.2" + checksum: 10c0/b52d7d4e8fc6a9018fe7361c4062c1c190f5778cf2466817cb9ed19d69fbbb54f9a85ffedeb748ed8062d2cf7d4cc088ee739848f47c57740de1c48cbf0d0994 + languageName: node + linkType: hard + "@types/estree@npm:1.0.7, @types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6": version: 1.0.7 resolution: "@types/estree@npm:1.0.7" @@ -1826,6 +2793,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:1.0.8": + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 + languageName: node + linkType: hard + "@types/hast@npm:^3.0.0, @types/hast@npm:^3.0.4": version: 3.0.4 resolution: "@types/hast@npm:3.0.4" @@ -2068,6 +3042,22 @@ __metadata: languageName: node linkType: hard +"@vitejs/plugin-react@npm:^4.3.4": + version: 4.7.0 + resolution: "@vitejs/plugin-react@npm:4.7.0" + dependencies: + "@babel/core": "npm:^7.28.0" + "@babel/plugin-transform-react-jsx-self": "npm:^7.27.1" + "@babel/plugin-transform-react-jsx-source": "npm:^7.27.1" + "@rolldown/pluginutils": "npm:1.0.0-beta.27" + "@types/babel__core": "npm:^7.20.5" + react-refresh: "npm:^0.17.0" + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + checksum: 10c0/692f23960972879485d647713663ec299c478222c96567d60285acf7c7dc5c178e71abfe9d2eefddef1eeb01514dacbc2ed68aad84628debf9c7116134734253 + languageName: node + linkType: hard + "@vitejs/plugin-vue@npm:^5.2.1": version: 5.2.3 resolution: "@vitejs/plugin-vue@npm:5.2.3" @@ -2719,6 +3709,15 @@ __metadata: languageName: node linkType: hard +"baseline-browser-mapping@npm:^2.9.0": + version: 2.9.14 + resolution: "baseline-browser-mapping@npm:2.9.14" + bin: + baseline-browser-mapping: dist/cli.js + checksum: 10c0/c9bf03c65e9a6690e4abbe60c269ad14ce5578cac09fed51ff1ed6e899e049afb094c2b173365cb2397d48012a83747500db6e79dca2761faf548aee10574d3d + languageName: node + linkType: hard + "better-path-resolve@npm:1.0.0": version: 1.0.0 resolution: "better-path-resolve@npm:1.0.0" @@ -2763,6 +3762,21 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.24.0": + version: 4.28.1 + resolution: "browserslist@npm:4.28.1" + dependencies: + baseline-browser-mapping: "npm:^2.9.0" + caniuse-lite: "npm:^1.0.30001759" + electron-to-chromium: "npm:^1.5.263" + node-releases: "npm:^2.0.27" + update-browserslist-db: "npm:^1.2.0" + bin: + browserslist: cli.js + checksum: 10c0/545a5fa9d7234e3777a7177ec1e9134bb2ba60a69e6b95683f6982b1473aad347c77c1264ccf2ac5dea609a9731fbfbda6b85782bdca70f80f86e28a402504bd + languageName: node + linkType: hard + "bundle-require@npm:^5.1.0": version: 5.1.0 resolution: "bundle-require@npm:5.1.0" @@ -2840,6 +3854,13 @@ __metadata: languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001579, caniuse-lite@npm:^1.0.30001759": + version: 1.0.30001764 + resolution: "caniuse-lite@npm:1.0.30001764" + checksum: 10c0/3fbc2bcb35792bd860e20210283e7c700aab10c5af435dbb8bfbf952edccaa3e7de8b479af0f600c4d23f269dbc166e16b7b72df5cd1981653b252174c9cbfa8 + languageName: node + linkType: hard + "ccount@npm:^2.0.0": version: 2.0.1 resolution: "ccount@npm:2.0.1" @@ -2964,6 +3985,13 @@ __metadata: languageName: node linkType: hard +"client-only@npm:0.0.1": + version: 0.0.1 + resolution: "client-only@npm:0.0.1" + checksum: 10c0/9d6cfd0c19e1c96a434605added99dff48482152af791ec4172fb912a71cff9027ff174efd8cdb2160cc7f377543e0537ffc462d4f279bc4701de3f2a3c4b358 + languageName: node + linkType: hard + "color-convert@npm:^2.0.1": version: 2.0.1 resolution: "color-convert@npm:2.0.1" @@ -3038,6 +4066,20 @@ __metadata: languageName: node linkType: hard +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b + languageName: node + linkType: hard + +"cookie@npm:^1.0.1": + version: 1.1.1 + resolution: "cookie@npm:1.1.1" + checksum: 10c0/79c4ddc0fcad9c4f045f826f42edf54bcc921a29586a4558b0898277fa89fb47be95bc384c2253f493af7b29500c830da28341274527328f18eba9f58afa112c + languageName: node + linkType: hard + "copy-anything@npm:^3.0.2": version: 3.0.5 resolution: "copy-anything@npm:3.0.5" @@ -3166,6 +4208,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.1.0": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 + languageName: node + linkType: hard + "decimal.js@npm:^10.4.3": version: 10.5.0 resolution: "decimal.js@npm:10.5.0" @@ -3230,6 +4284,13 @@ __metadata: languageName: node linkType: hard +"detect-libc@npm:^2.1.2": + version: 2.1.2 + resolution: "detect-libc@npm:2.1.2" + checksum: 10c0/acc675c29a5649fa1fb6e255f993b8ee829e510b6b56b0910666949c80c364738833417d0edb5f90e4e46be17228b0f2b66a010513984e18b15deeeac49369c4 + languageName: node + linkType: hard + "devlop@npm:^1.0.0": version: 1.1.0 resolution: "devlop@npm:1.1.0" @@ -3303,6 +4364,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.5.263": + version: 1.5.267 + resolution: "electron-to-chromium@npm:1.5.267" + checksum: 10c0/0732bdb891b657f2e43266a3db8cf86fff6cecdcc8d693a92beff214e136cb5c2ee7dc5945ed75fa1db16e16bad0c38695527a020d15f39e79084e0b2e447621 + languageName: node + linkType: hard + "emoji-regex-xs@npm:^1.0.0": version: 1.0.0 resolution: "emoji-regex-xs@npm:1.0.0" @@ -3771,7 +4839,103 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10c0/87ce0b78699c4d192b8cf7e9b688e9a0da10e6f58ff85a368bf3044ca1fa95626c98b769b5459352282e0065585b6f994a5e6699af5cccf9d31178960e2b58fd + checksum: 10c0/87ce0b78699c4d192b8cf7e9b688e9a0da10e6f58ff85a368bf3044ca1fa95626c98b769b5459352282e0065585b6f994a5e6699af5cccf9d31178960e2b58fd + languageName: node + linkType: hard + +"esbuild@npm:^0.27.0": + version: 0.27.2 + resolution: "esbuild@npm:0.27.2" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.2" + "@esbuild/android-arm": "npm:0.27.2" + "@esbuild/android-arm64": "npm:0.27.2" + "@esbuild/android-x64": "npm:0.27.2" + "@esbuild/darwin-arm64": "npm:0.27.2" + "@esbuild/darwin-x64": "npm:0.27.2" + "@esbuild/freebsd-arm64": "npm:0.27.2" + "@esbuild/freebsd-x64": "npm:0.27.2" + "@esbuild/linux-arm": "npm:0.27.2" + "@esbuild/linux-arm64": "npm:0.27.2" + "@esbuild/linux-ia32": "npm:0.27.2" + "@esbuild/linux-loong64": "npm:0.27.2" + "@esbuild/linux-mips64el": "npm:0.27.2" + "@esbuild/linux-ppc64": "npm:0.27.2" + "@esbuild/linux-riscv64": "npm:0.27.2" + "@esbuild/linux-s390x": "npm:0.27.2" + "@esbuild/linux-x64": "npm:0.27.2" + "@esbuild/netbsd-arm64": "npm:0.27.2" + "@esbuild/netbsd-x64": "npm:0.27.2" + "@esbuild/openbsd-arm64": "npm:0.27.2" + "@esbuild/openbsd-x64": "npm:0.27.2" + "@esbuild/openharmony-arm64": "npm:0.27.2" + "@esbuild/sunos-x64": "npm:0.27.2" + "@esbuild/win32-arm64": "npm:0.27.2" + "@esbuild/win32-ia32": "npm:0.27.2" + "@esbuild/win32-x64": "npm:0.27.2" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/openharmony-arm64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/cf83f626f55500f521d5fe7f4bc5871bec240d3deb2a01fbd379edc43b3664d1167428738a5aad8794b35d1cca985c44c375b1cd38a2ca613c77ced2c83aafcd + languageName: node + linkType: hard + +"escalade@npm:^3.2.0": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 languageName: node linkType: hard @@ -4164,6 +5328,18 @@ __metadata: languageName: node linkType: hard +"fdir@npm:^6.5.0": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f + languageName: node + linkType: hard + "file-entry-cache@npm:^8.0.0": version: 8.0.0 resolution: "file-entry-cache@npm:8.0.0" @@ -4354,6 +5530,13 @@ __metadata: languageName: node linkType: hard +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: 10c0/782aba6cba65b1bb5af3b095d96249d20edbe8df32dbf4696fd49be2583faf676173bf4809386588828e4dd76a3354fcbeb577bab1c833ccd9fc4577f26103f8 + languageName: node + linkType: hard + "get-east-asian-width@npm:^1.0.0": version: 1.3.0 resolution: "get-east-asian-width@npm:1.3.0" @@ -5276,6 +6459,15 @@ __metadata: languageName: node linkType: hard +"json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 10c0/5a04eed94810fa55c5ea138b2f7a5c12b97c3750bc63d11e511dcecbfef758003861522a070c2272764ee0f4e3e323862f386945aeb5b85b87ee43f084ba586c + languageName: node + linkType: hard + "jsonfile@npm:^4.0.0": version: 4.0.0 resolution: "jsonfile@npm:4.0.0" @@ -5455,6 +6647,15 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^5.1.1": + version: 5.1.1 + resolution: "lru-cache@npm:5.1.1" + dependencies: + yallist: "npm:^3.0.2" + checksum: 10c0/89b2ef2ef45f543011e38737b8a8622a2f8998cddf0e5437174ef8f1f70a8b9d14a918ab3e232cb3ba343b7abddffa667f0b59075b2b80e6b4d63c3de6127482 + languageName: node + linkType: hard + "lz-string@npm:^1.5.0": version: 1.5.0 resolution: "lz-string@npm:1.5.0" @@ -5790,7 +6991,7 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.8": +"nanoid@npm:^3.3.11, nanoid@npm:^3.3.6, nanoid@npm:^3.3.8": version: 3.3.11 resolution: "nanoid@npm:3.3.11" bin: @@ -5822,6 +7023,65 @@ __metadata: languageName: node linkType: hard +"next@npm:^15.0.0": + version: 15.5.9 + resolution: "next@npm:15.5.9" + dependencies: + "@next/env": "npm:15.5.9" + "@next/swc-darwin-arm64": "npm:15.5.7" + "@next/swc-darwin-x64": "npm:15.5.7" + "@next/swc-linux-arm64-gnu": "npm:15.5.7" + "@next/swc-linux-arm64-musl": "npm:15.5.7" + "@next/swc-linux-x64-gnu": "npm:15.5.7" + "@next/swc-linux-x64-musl": "npm:15.5.7" + "@next/swc-win32-arm64-msvc": "npm:15.5.7" + "@next/swc-win32-x64-msvc": "npm:15.5.7" + "@swc/helpers": "npm:0.5.15" + caniuse-lite: "npm:^1.0.30001579" + postcss: "npm:8.4.31" + sharp: "npm:^0.34.3" + styled-jsx: "npm:5.1.6" + peerDependencies: + "@opentelemetry/api": ^1.1.0 + "@playwright/test": ^1.51.1 + babel-plugin-react-compiler: "*" + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + dependenciesMeta: + "@next/swc-darwin-arm64": + optional: true + "@next/swc-darwin-x64": + optional: true + "@next/swc-linux-arm64-gnu": + optional: true + "@next/swc-linux-arm64-musl": + optional: true + "@next/swc-linux-x64-gnu": + optional: true + "@next/swc-linux-x64-musl": + optional: true + "@next/swc-win32-arm64-msvc": + optional: true + "@next/swc-win32-x64-msvc": + optional: true + sharp: + optional: true + peerDependenciesMeta: + "@opentelemetry/api": + optional: true + "@playwright/test": + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + bin: + next: dist/bin/next + checksum: 10c0/6a120afbc45b96aa14debba6375602d6319093af4e3e8c648cf22b12ffb9db016c889df5e764cf5e0aa414ad60505db4e2095624a19f4b71316561076158651a + languageName: node + linkType: hard + "node-domexception@npm:1.0.0": version: 1.0.0 resolution: "node-domexception@npm:1.0.0" @@ -5863,6 +7123,13 @@ __metadata: languageName: node linkType: hard +"node-releases@npm:^2.0.27": + version: 2.0.27 + resolution: "node-releases@npm:2.0.27" + checksum: 10c0/f1e6583b7833ea81880627748d28a3a7ff5703d5409328c216ae57befbced10ce2c991bea86434e8ec39003bd017f70481e2e5f8c1f7e0a7663241f81d6e00e2 + languageName: node + linkType: hard + "nopt@npm:^8.0.0": version: 8.1.0 resolution: "nopt@npm:8.1.0" @@ -6247,6 +7514,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.3": + version: 4.0.3 + resolution: "picomatch@npm:4.0.3" + checksum: 10c0/9582c951e95eebee5434f59e426cddd228a7b97a0161a375aed4be244bd3fe8e3a31b846808ea14ef2c8a2527a6eeab7b3946a67d5979e81694654f939473ae2 + languageName: node + linkType: hard + "pify@npm:^4.0.1": version: 4.0.1 resolution: "pify@npm:4.0.1" @@ -6291,6 +7565,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:8.4.31": + version: 8.4.31 + resolution: "postcss@npm:8.4.31" + dependencies: + nanoid: "npm:^3.3.6" + picocolors: "npm:^1.0.0" + source-map-js: "npm:^1.0.2" + checksum: 10c0/748b82e6e5fc34034dcf2ae88ea3d11fd09f69b6c50ecdd3b4a875cfc7cdca435c958b211e2cb52355422ab6fccb7d8f2f2923161d7a1b281029e4a913d59acf + languageName: node + linkType: hard + "postcss@npm:^8.4.43, postcss@npm:^8.4.48": version: 8.5.3 resolution: "postcss@npm:8.5.3" @@ -6302,6 +7587,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.5.6": + version: 8.5.6 + resolution: "postcss@npm:8.5.6" + dependencies: + nanoid: "npm:^3.3.11" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/5127cc7c91ed7a133a1b7318012d8bfa112da9ef092dddf369ae699a1f10ebbd89b1b9f25f3228795b84585c72aabd5ced5fc11f2ba467eedf7b081a66fad024 + languageName: node + linkType: hard + "preact@npm:^10.0.0": version: 10.26.5 resolution: "preact@npm:10.26.5" @@ -6446,6 +7742,41 @@ __metadata: languageName: node linkType: hard +"react-refresh@npm:^0.17.0": + version: 0.17.0 + resolution: "react-refresh@npm:0.17.0" + checksum: 10c0/002cba940384c9930008c0bce26cac97a9d5682bc623112c2268ba0c155127d9c178a9a5cc2212d560088d60dfd503edd808669a25f9b377f316a32361d0b23c + languageName: node + linkType: hard + +"react-router-dom@npm:^7.0.0": + version: 7.12.0 + resolution: "react-router-dom@npm:7.12.0" + dependencies: + react-router: "npm:7.12.0" + peerDependencies: + react: ">=18" + react-dom: ">=18" + checksum: 10c0/48cb6e5d47e9aa91dd3982555bb84512d7048a7d1fc676a182c444d470f00b3cf9bef311c1c0f8fbc711c95cc5b3dde39b26cf8ec7feb3ebaf21a00e4cef6816 + languageName: node + linkType: hard + +"react-router@npm:7.12.0": + version: 7.12.0 + resolution: "react-router@npm:7.12.0" + dependencies: + cookie: "npm:^1.0.1" + set-cookie-parser: "npm:^2.6.0" + peerDependencies: + react: ">=18" + react-dom: ">=18" + peerDependenciesMeta: + react-dom: + optional: true + checksum: 10c0/abde366f716cb3961a5a390c278375c0591bace5773e1b4420001f0a913b4dd53d490e7dea866acebcac2c0fa07378aa83702769d449449027406ed517a8ea00 + languageName: node + linkType: hard + "react-simplikit@workspace:.": version: 0.0.0-use.local resolution: "react-simplikit@workspace:." @@ -6787,6 +8118,96 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.43.0": + version: 4.55.1 + resolution: "rollup@npm:4.55.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.55.1" + "@rollup/rollup-android-arm64": "npm:4.55.1" + "@rollup/rollup-darwin-arm64": "npm:4.55.1" + "@rollup/rollup-darwin-x64": "npm:4.55.1" + "@rollup/rollup-freebsd-arm64": "npm:4.55.1" + "@rollup/rollup-freebsd-x64": "npm:4.55.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.55.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.55.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.55.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.55.1" + "@rollup/rollup-linux-loong64-gnu": "npm:4.55.1" + "@rollup/rollup-linux-loong64-musl": "npm:4.55.1" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.55.1" + "@rollup/rollup-linux-ppc64-musl": "npm:4.55.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.55.1" + "@rollup/rollup-linux-riscv64-musl": "npm:4.55.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.55.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.55.1" + "@rollup/rollup-linux-x64-musl": "npm:4.55.1" + "@rollup/rollup-openbsd-x64": "npm:4.55.1" + "@rollup/rollup-openharmony-arm64": "npm:4.55.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.55.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.55.1" + "@rollup/rollup-win32-x64-gnu": "npm:4.55.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.55.1" + "@types/estree": "npm:1.0.8" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-freebsd-arm64": + optional: true + "@rollup/rollup-freebsd-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-loong64-gnu": + optional: true + "@rollup/rollup-linux-loong64-musl": + optional: true + "@rollup/rollup-linux-ppc64-gnu": + optional: true + "@rollup/rollup-linux-ppc64-musl": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-riscv64-musl": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-openbsd-x64": + optional: true + "@rollup/rollup-openharmony-arm64": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-gnu": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/267309f0db5c5493b2b163643dceed6e57aa20fcd75d40cf44740b8b572e747a0f9e1694b11ff518583596c37fe13ada09bf676956f50073c16cdac09e633a66 + languageName: node + linkType: hard + "rrweb-cssom@npm:^0.7.1": version: 0.7.1 resolution: "rrweb-cssom@npm:0.7.1" @@ -6885,6 +8306,22 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.3": + version: 7.7.3 + resolution: "semver@npm:7.7.3" + bin: + semver: bin/semver.js + checksum: 10c0/4afe5c986567db82f44c8c6faef8fe9df2a9b1d98098fc1721f57c696c4c21cebd572f297fc21002f81889492345b8470473bc6f4aff5fb032a6ea59ea2bc45e + languageName: node + linkType: hard + +"set-cookie-parser@npm:^2.6.0": + version: 2.7.2 + resolution: "set-cookie-parser@npm:2.7.2" + checksum: 10c0/4381a9eb7ee951dfe393fe7aacf76b9a3b4e93a684d2162ab35594fa4053cc82a4d7d7582bf397718012c9adcf839b8cd8f57c6c42901ea9effe33c752da4a45 + languageName: node + linkType: hard + "set-function-length@npm:^1.2.2": version: 1.2.2 resolution: "set-function-length@npm:1.2.2" @@ -6922,6 +8359,90 @@ __metadata: languageName: node linkType: hard +"sharp@npm:^0.34.3": + version: 0.34.5 + resolution: "sharp@npm:0.34.5" + dependencies: + "@img/colour": "npm:^1.0.0" + "@img/sharp-darwin-arm64": "npm:0.34.5" + "@img/sharp-darwin-x64": "npm:0.34.5" + "@img/sharp-libvips-darwin-arm64": "npm:1.2.4" + "@img/sharp-libvips-darwin-x64": "npm:1.2.4" + "@img/sharp-libvips-linux-arm": "npm:1.2.4" + "@img/sharp-libvips-linux-arm64": "npm:1.2.4" + "@img/sharp-libvips-linux-ppc64": "npm:1.2.4" + "@img/sharp-libvips-linux-riscv64": "npm:1.2.4" + "@img/sharp-libvips-linux-s390x": "npm:1.2.4" + "@img/sharp-libvips-linux-x64": "npm:1.2.4" + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.2.4" + "@img/sharp-libvips-linuxmusl-x64": "npm:1.2.4" + "@img/sharp-linux-arm": "npm:0.34.5" + "@img/sharp-linux-arm64": "npm:0.34.5" + "@img/sharp-linux-ppc64": "npm:0.34.5" + "@img/sharp-linux-riscv64": "npm:0.34.5" + "@img/sharp-linux-s390x": "npm:0.34.5" + "@img/sharp-linux-x64": "npm:0.34.5" + "@img/sharp-linuxmusl-arm64": "npm:0.34.5" + "@img/sharp-linuxmusl-x64": "npm:0.34.5" + "@img/sharp-wasm32": "npm:0.34.5" + "@img/sharp-win32-arm64": "npm:0.34.5" + "@img/sharp-win32-ia32": "npm:0.34.5" + "@img/sharp-win32-x64": "npm:0.34.5" + detect-libc: "npm:^2.1.2" + semver: "npm:^7.7.3" + dependenciesMeta: + "@img/sharp-darwin-arm64": + optional: true + "@img/sharp-darwin-x64": + optional: true + "@img/sharp-libvips-darwin-arm64": + optional: true + "@img/sharp-libvips-darwin-x64": + optional: true + "@img/sharp-libvips-linux-arm": + optional: true + "@img/sharp-libvips-linux-arm64": + optional: true + "@img/sharp-libvips-linux-ppc64": + optional: true + "@img/sharp-libvips-linux-riscv64": + optional: true + "@img/sharp-libvips-linux-s390x": + optional: true + "@img/sharp-libvips-linux-x64": + optional: true + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + "@img/sharp-libvips-linuxmusl-x64": + optional: true + "@img/sharp-linux-arm": + optional: true + "@img/sharp-linux-arm64": + optional: true + "@img/sharp-linux-ppc64": + optional: true + "@img/sharp-linux-riscv64": + optional: true + "@img/sharp-linux-s390x": + optional: true + "@img/sharp-linux-x64": + optional: true + "@img/sharp-linuxmusl-arm64": + optional: true + "@img/sharp-linuxmusl-x64": + optional: true + "@img/sharp-wasm32": + optional: true + "@img/sharp-win32-arm64": + optional: true + "@img/sharp-win32-ia32": + optional: true + "@img/sharp-win32-x64": + optional: true + checksum: 10c0/fd79e29df0597a7d5704b8461c51f944ead91a5243691697be6e8243b966402beda53ddc6f0a53b96ea3cb8221f0b244aa588114d3ebf8734fb4aefd41ab802f + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -7071,7 +8592,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": +"source-map-js@npm:^1.0.2, source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf @@ -7308,6 +8829,22 @@ __metadata: languageName: node linkType: hard +"styled-jsx@npm:5.1.6": + version: 5.1.6 + resolution: "styled-jsx@npm:5.1.6" + dependencies: + client-only: "npm:0.0.1" + peerDependencies: + react: ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + peerDependenciesMeta: + "@babel/core": + optional: true + babel-plugin-macros: + optional: true + checksum: 10c0/ace50e7ea5ae5ae6a3b65a50994c51fca6ae7df9c7ecfd0104c36be0b4b3a9c5c1a2374d16e2a11e256d0b20be6d47256d768ecb4f91ab390f60752a075780f5 + languageName: node + linkType: hard + "sucrase@npm:^3.35.0": version: 3.35.0 resolution: "sucrase@npm:3.35.0" @@ -7449,6 +8986,16 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:^0.2.15": + version: 0.2.15 + resolution: "tinyglobby@npm:0.2.15" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.3" + checksum: 10c0/869c31490d0d88eedb8305d178d4c75e7463e820df5a9b9d388291daf93e8b1eb5de1dad1c1e139767e4269fe75f3b10d5009b2cc14db96ff98986920a186844 + languageName: node + linkType: hard + "tinypool@npm:^1.0.1": version: 1.0.2 resolution: "tinypool@npm:1.0.2" @@ -7575,7 +9122,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.8.1": +"tslib@npm:^2.4.0, tslib@npm:^2.8.0, tslib@npm:^2.8.1": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 @@ -7834,6 +9381,20 @@ __metadata: languageName: node linkType: hard +"update-browserslist-db@npm:^1.2.0": + version: 1.2.3 + resolution: "update-browserslist-db@npm:1.2.3" + dependencies: + escalade: "npm:^3.2.0" + picocolors: "npm:^1.1.1" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 10c0/13a00355ea822388f68af57410ce3255941d5fb9b7c49342c4709a07c9f230bbef7f7499ae0ca7e0de532e79a82cc0c4edbd125f1a323a1845bf914efddf8bec + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -7921,6 +9482,61 @@ __metadata: languageName: node linkType: hard +"vite@npm:^7.0.0": + version: 7.3.1 + resolution: "vite@npm:7.3.1" + dependencies: + esbuild: "npm:^0.27.0" + fdir: "npm:^6.5.0" + fsevents: "npm:~2.3.3" + picomatch: "npm:^4.0.3" + postcss: "npm:^8.5.6" + rollup: "npm:^4.43.0" + tinyglobby: "npm:^0.2.15" + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + jiti: ">=1.21.0" + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/5c7548f5f43a23533e53324304db4ad85f1896b1bfd3ee32ae9b866bac2933782c77b350eb2b52a02c625c8ad1ddd4c000df077419410650c982cd97fde8d014 + languageName: node + linkType: hard + "vitepress@npm:^1.5.0": version: 1.6.3 resolution: "vitepress@npm:1.6.3" @@ -8204,6 +9820,37 @@ __metadata: languageName: node linkType: hard +"with-nextjs@workspace:examples/with-nextjs": + version: 0.0.0-use.local + resolution: "with-nextjs@workspace:examples/with-nextjs" + dependencies: + "@react-simplikit/mobile": "workspace:*" + "@types/node": "npm:^22.10.2" + "@types/react": "npm:^19.0.0" + "@types/react-dom": "npm:^19.0.0" + next: "npm:^15.0.0" + react: "npm:^19.0.0" + react-dom: "npm:^19.0.0" + typescript: "npm:^5.7.2" + languageName: unknown + linkType: soft + +"with-vite@workspace:examples/with-vite": + version: 0.0.0-use.local + resolution: "with-vite@workspace:examples/with-vite" + dependencies: + "@react-simplikit/mobile": "workspace:*" + "@types/react": "npm:^19.0.0" + "@types/react-dom": "npm:^19.0.0" + "@vitejs/plugin-react": "npm:^4.3.4" + react: "npm:^19.0.0" + react-dom: "npm:^19.0.0" + react-router-dom: "npm:^7.0.0" + typescript: "npm:^5.7.2" + vite: "npm:^7.0.0" + languageName: unknown + linkType: soft + "word-wrap@npm:^1.2.5": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" @@ -8273,6 +9920,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^3.0.2": + version: 3.1.1 + resolution: "yallist@npm:3.1.1" + checksum: 10c0/c66a5c46bc89af1625476f7f0f2ec3653c1a1791d2f9407cfb4c2ba812a1e1c9941416d71ba9719876530e3340a99925f697142989371b72d93b9ee628afd8c1 + languageName: node + linkType: hard + "yallist@npm:^4.0.0": version: 4.0.0 resolution: "yallist@npm:4.0.0"