diff --git a/.pnp.cjs b/.pnp.cjs index 80c38005f..80115a324 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -51,6 +51,10 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "name": "@stackflow/plugin-preload",\ "reference": "workspace:extensions/plugin-preload"\ },\ + {\ + "name": "@stackflow/plugin-redirect",\ + "reference": "workspace:extensions/plugin-redirect"\ + },\ {\ "name": "@stackflow/plugin-renderer-basic",\ "reference": "workspace:extensions/plugin-renderer-basic"\ @@ -91,6 +95,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@stackflow/plugin-google-analytics-4", ["workspace:extensions/plugin-google-analytics-4"]],\ ["@stackflow/plugin-history-sync", ["virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-history-sync", "workspace:extensions/plugin-history-sync"]],\ ["@stackflow/plugin-preload", ["virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-preload", "workspace:extensions/plugin-preload"]],\ + ["@stackflow/plugin-redirect", ["virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-redirect", "workspace:extensions/plugin-redirect"]],\ ["@stackflow/plugin-renderer-basic", ["virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-renderer-basic", "workspace:extensions/plugin-renderer-basic"]],\ ["@stackflow/plugin-renderer-web", ["workspace:extensions/plugin-renderer-web"]],\ ["@stackflow/plugin-stack-depth-change", ["virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-stack-depth-change", "workspace:extensions/plugin-stack-depth-change"]],\ @@ -3038,6 +3043,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@stackflow/plugin-basic-ui", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-basic-ui"],\ ["@stackflow/plugin-history-sync", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-history-sync"],\ ["@stackflow/plugin-preload", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-preload"],\ + ["@stackflow/plugin-redirect", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-redirect"],\ ["@stackflow/plugin-renderer-basic", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-renderer-basic"],\ ["@stackflow/plugin-stack-depth-change", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-stack-depth-change"],\ ["@stackflow/react", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:integrations/react"],\ @@ -3477,6 +3483,76 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "SOFT"\ }]\ ]],\ + ["@stackflow/plugin-redirect", [\ + ["virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-redirect", {\ + "packageLocation": "./.yarn/__virtual__/@stackflow-plugin-redirect-virtual-4c921715e4/1/extensions/plugin-redirect/",\ + "packageDependencies": [\ + ["@stackflow/plugin-redirect", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-redirect"],\ + ["@stackflow/core", "workspace:core"],\ + ["@stackflow/esbuild-config", "workspace:packages/esbuild-config"],\ + ["@stackflow/eslint-config", "workspace:packages/eslint-config"],\ + ["@stackflow/react", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:integrations/react"],\ + ["@types/node", "npm:18.6.3"],\ + ["@types/react", "npm:18.0.15"],\ + ["@types/stackflow__core", null],\ + ["@types/stackflow__react", null],\ + ["@typescript-eslint/eslint-plugin", "virtual:b327d7e228fba669b88a8bb23bcf526374e46fa67e617b1e6848e8a205357fee5ce94b47c49b5a570fd9e8a44fa218a13cd00e2eca327c99114cbd21d72ecf9c#npm:5.32.0"],\ + ["@typescript-eslint/parser", "virtual:b327d7e228fba669b88a8bb23bcf526374e46fa67e617b1e6848e8a205357fee5ce94b47c49b5a570fd9e8a44fa218a13cd00e2eca327c99114cbd21d72ecf9c#npm:5.28.0"],\ + ["esbuild", "npm:0.14.51"],\ + ["eslint", "npm:8.14.0"],\ + ["eslint-config-airbnb", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#npm:19.0.4"],\ + ["eslint-config-prettier", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:8.5.0"],\ + ["eslint-plugin-import", "virtual:b327d7e228fba669b88a8bb23bcf526374e46fa67e617b1e6848e8a205357fee5ce94b47c49b5a570fd9e8a44fa218a13cd00e2eca327c99114cbd21d72ecf9c#npm:2.26.0"],\ + ["eslint-plugin-json-format", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:2.0.1"],\ + ["eslint-plugin-jsx-a11y", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:6.5.1"],\ + ["eslint-plugin-react", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:7.30.0"],\ + ["eslint-plugin-react-hooks", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:4.6.0"],\ + ["eslint-plugin-simple-import-sort", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:7.0.0"],\ + ["react", "npm:18.2.0"],\ + ["rimraf", "npm:3.0.2"],\ + ["typescript", "patch:typescript@npm%3A4.7.4#~builtin::version=4.7.4&hash=701156"],\ + ["url-pattern", "npm:1.0.3"]\ + ],\ + "packagePeers": [\ + "@stackflow/core",\ + "@stackflow/react",\ + "@types/react",\ + "@types/stackflow__core",\ + "@types/stackflow__react",\ + "react"\ + ],\ + "linkType": "SOFT"\ + }],\ + ["workspace:extensions/plugin-redirect", {\ + "packageLocation": "./extensions/plugin-redirect/",\ + "packageDependencies": [\ + ["@stackflow/plugin-redirect", "workspace:extensions/plugin-redirect"],\ + ["@stackflow/core", "workspace:core"],\ + ["@stackflow/esbuild-config", "workspace:packages/esbuild-config"],\ + ["@stackflow/eslint-config", "workspace:packages/eslint-config"],\ + ["@stackflow/react", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:integrations/react"],\ + ["@types/node", "npm:18.6.3"],\ + ["@types/react", "npm:18.0.15"],\ + ["@typescript-eslint/eslint-plugin", "virtual:b327d7e228fba669b88a8bb23bcf526374e46fa67e617b1e6848e8a205357fee5ce94b47c49b5a570fd9e8a44fa218a13cd00e2eca327c99114cbd21d72ecf9c#npm:5.32.0"],\ + ["@typescript-eslint/parser", "virtual:b327d7e228fba669b88a8bb23bcf526374e46fa67e617b1e6848e8a205357fee5ce94b47c49b5a570fd9e8a44fa218a13cd00e2eca327c99114cbd21d72ecf9c#npm:5.28.0"],\ + ["esbuild", "npm:0.14.51"],\ + ["eslint", "npm:8.14.0"],\ + ["eslint-config-airbnb", "virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#npm:19.0.4"],\ + ["eslint-config-prettier", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:8.5.0"],\ + ["eslint-plugin-import", "virtual:b327d7e228fba669b88a8bb23bcf526374e46fa67e617b1e6848e8a205357fee5ce94b47c49b5a570fd9e8a44fa218a13cd00e2eca327c99114cbd21d72ecf9c#npm:2.26.0"],\ + ["eslint-plugin-json-format", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:2.0.1"],\ + ["eslint-plugin-jsx-a11y", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:6.5.1"],\ + ["eslint-plugin-react", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:7.30.0"],\ + ["eslint-plugin-react-hooks", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:4.6.0"],\ + ["eslint-plugin-simple-import-sort", "virtual:5d222998b86cceed4c8d843e557f0e3b94c8ccb1e8952571a8d45c8a6806e6624abcd819a5fa16c66371a9250ca177cd0fc04f42e577bbbc49771098023bb79e#npm:7.0.0"],\ + ["react", "npm:18.2.0"],\ + ["rimraf", "npm:3.0.2"],\ + ["typescript", "patch:typescript@npm%3A4.7.4#~builtin::version=4.7.4&hash=701156"],\ + ["url-pattern", "npm:1.0.3"]\ + ],\ + "linkType": "SOFT"\ + }]\ + ]],\ ["@stackflow/plugin-renderer-basic", [\ ["virtual:413bca98ff76262f6f1f73762ccc4b7edee04a5da42f3d6b9ed2cb2d6dbc397b2094da59b50f6e828091c88e7b5f86990feff596c43f0eb50a58fc42aae64a20#workspace:extensions/plugin-renderer-basic", {\ "packageLocation": "./.yarn/__virtual__/@stackflow-plugin-renderer-basic-virtual-84c5c2a317/1/extensions/plugin-renderer-basic/",\ diff --git a/demo/package.json b/demo/package.json index 3b133ae93..b2721b85c 100644 --- a/demo/package.json +++ b/demo/package.json @@ -36,6 +36,7 @@ "@stackflow/plugin-basic-ui": "^0.20.2", "@stackflow/plugin-history-sync": "^0.20.1", "@stackflow/plugin-preload": "^0.20.1", + "@stackflow/plugin-redirect": "^0.19.0", "@stackflow/plugin-renderer-basic": "^0.20.1", "@stackflow/plugin-stack-depth-change": "^0.20.0", "@stackflow/react": "^0.20.1", diff --git a/demo/src/stackflow.ts b/demo/src/stackflow.ts index 23abfd445..118fda46f 100644 --- a/demo/src/stackflow.ts +++ b/demo/src/stackflow.ts @@ -1,6 +1,7 @@ import { vars } from "@seed-design/design-token"; import { basicUIPlugin } from "@stackflow/plugin-basic-ui"; import { historySyncPlugin } from "@stackflow/plugin-history-sync"; +import { redirectPlugin } from "@stackflow/plugin-redirect"; import { basicRendererPlugin } from "@stackflow/plugin-renderer-basic"; import { stackflow } from "@stackflow/react"; @@ -38,6 +39,11 @@ export const { Stack, activities } = stackflow({ borderColor: vars.$semantic.color.divider3, }, }), + redirectPlugin({ + redirects: { + Article: ["Main"], + }, + }), historySyncPlugin({ routes: { Main: "/", diff --git a/extensions/plugin-redirect/.eslintrc.js b/extensions/plugin-redirect/.eslintrc.js new file mode 100644 index 000000000..e70f69f40 --- /dev/null +++ b/extensions/plugin-redirect/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ["@stackflow/eslint-config/react"], +}; diff --git a/extensions/plugin-redirect/README.md b/extensions/plugin-redirect/README.md new file mode 100644 index 000000000..27a3c3f74 --- /dev/null +++ b/extensions/plugin-redirect/README.md @@ -0,0 +1,44 @@ +# @stackflow/plugin-history-sync + +Synchronizes the stack state with the current browser's history + +- [Documentation](https://stackflow.so) + +## Usage + +```typescript +import { stackflow } from "@stackflow/react"; +import { historySyncPlugin } from "@stackflow/plugin-history-sync"; +import { MyHome } from "./MyHome"; +import { MyArticle } from "./MyArticle"; +import { NotFoundPage } from "./NotFoundPage"; + +const { Stack, useFlow } = stackflow({ + activities: { + MyHome, + MyArticle, + NotFoundPage, + }, + plugins: [ + // ... + historySyncPlugin({ + routes: { + /** + * You can link the registered activity with the URL template. + */ + MyHome: "/", + MyArticle: "/articles/:articleId", + NotFoundPage: "/404", + }, + /** + * If a URL that does not correspond to the URL template is given, it moves to the `fallbackActivity`. + */ + fallbackActivity: ({ context }) => "NotFoundPage", + /** + * Uses the hash portion of the URL (i.e. window.location.hash) + */ + useHash: false, + }), + ], +}); +``` diff --git a/extensions/plugin-redirect/esbuild.config.js b/extensions/plugin-redirect/esbuild.config.js new file mode 100644 index 000000000..d09623a78 --- /dev/null +++ b/extensions/plugin-redirect/esbuild.config.js @@ -0,0 +1,35 @@ +const { build } = require("esbuild"); +const config = require("@stackflow/esbuild-config"); +const pkg = require("./package.json"); + +const watch = process.argv.includes("--watch"); +const external = Object.keys({ + ...pkg.dependencies, + ...pkg.peerDependencies, +}); + +Promise.all([ + build({ + ...config({}), + format: "cjs", + external, + define: { + "process.env.PACKAGE_NAME": `"${pkg.name}"`, + "process.env.PACKAGE_VERSION": `"${pkg.version}"`, + }, + watch, + }), + build({ + ...config({}), + format: "esm", + outExtension: { + ".js": ".mjs", + }, + external, + define: { + "process.env.PACKAGE_NAME": `"${pkg.name}"`, + "process.env.PACKAGE_VERSION": `"${pkg.version}"`, + }, + watch, + }), +]).catch(() => process.exit(1)); diff --git a/extensions/plugin-redirect/package.json b/extensions/plugin-redirect/package.json new file mode 100644 index 000000000..7b5274246 --- /dev/null +++ b/extensions/plugin-redirect/package.json @@ -0,0 +1,67 @@ +{ + "name": "@stackflow/plugin-redirect", + "version": "0.19.0", + "license": "MIT", + "exports": { + ".": { + "require": "./dist/index.js", + "import": "./dist/index.mjs" + } + }, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "files": [ + "dist", + "src", + "README.md" + ], + "scripts": { + "build": "yarn build:js && yarn build:dts", + "build:dts": "tsc --emitDeclarationOnly", + "build:js": "node ./esbuild.config.js", + "clean": "rimraf dist", + "dev": "yarn build:js --watch && yarn build:dts --watch" + }, + "dependencies": { + "url-pattern": "^1.0.3" + }, + "devDependencies": { + "@stackflow/core": "^0.20.0", + "@stackflow/esbuild-config": "^0.20.0", + "@stackflow/eslint-config": "^0.20.0", + "@stackflow/react": "^0.20.1", + "@types/node": "^18.6.3", + "@types/react": "^18.0.10", + "@typescript-eslint/eslint-plugin": "^5.32.0", + "@typescript-eslint/parser": "^5.20.0", + "esbuild": "^0.14.51", + "eslint": "^8.13.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-json-format": "^2.0.1", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.29.4", + "eslint-plugin-react-hooks": "^4.4.0", + "eslint-plugin-simple-import-sort": "^7.0.0", + "react": "^18.1.0", + "rimraf": "^3.0.2", + "typescript": "^4.7.4" + }, + "peerDependencies": { + "@stackflow/core": "0", + "@stackflow/react": "0", + "@types/react": ">=16.8.0", + "react": ">=16.8.0" + }, + "publishConfig": { + "access": "public" + }, + "ultra": { + "concurrent": [ + "dev", + "build" + ] + } +} diff --git a/extensions/plugin-redirect/src/index.ts b/extensions/plugin-redirect/src/index.ts new file mode 100644 index 000000000..2947b6daa --- /dev/null +++ b/extensions/plugin-redirect/src/index.ts @@ -0,0 +1 @@ +export * from "./redirectPlugin"; diff --git a/extensions/plugin-redirect/src/redirectPlugin.ts b/extensions/plugin-redirect/src/redirectPlugin.ts new file mode 100644 index 000000000..7f1f5f96d --- /dev/null +++ b/extensions/plugin-redirect/src/redirectPlugin.ts @@ -0,0 +1,17 @@ +import type { StackflowReactPlugin } from "@stackflow/react"; + +type HistorySyncPluginOptions = { + redirects: { + [key in K]?: Exclude | Exclude[]; + }; +}; + +export function redirectPlugin( + options: HistorySyncPluginOptions>, +): StackflowReactPlugin { + type K = Extract; + + return () => ({ + key: "@stackflow/plugin-redirect", + }); +} diff --git a/extensions/plugin-redirect/tsconfig.json b/extensions/plugin-redirect/tsconfig.json new file mode 100644 index 000000000..b1d123121 --- /dev/null +++ b/extensions/plugin-redirect/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "./src", + "outDir": "./dist" + }, + "exclude": ["./dist"] +} diff --git a/yarn.lock b/yarn.lock index f40259bad..20b36477f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2206,6 +2206,7 @@ __metadata: "@stackflow/plugin-basic-ui": ^0.20.2 "@stackflow/plugin-history-sync": ^0.20.1 "@stackflow/plugin-preload": ^0.20.1 + "@stackflow/plugin-redirect": ^0.19.0 "@stackflow/plugin-renderer-basic": ^0.20.1 "@stackflow/plugin-stack-depth-change": ^0.20.0 "@stackflow/react": ^0.20.1 @@ -2489,6 +2490,40 @@ __metadata: languageName: unknown linkType: soft +"@stackflow/plugin-redirect@^0.19.0, @stackflow/plugin-redirect@workspace:extensions/plugin-redirect": + version: 0.0.0-use.local + resolution: "@stackflow/plugin-redirect@workspace:extensions/plugin-redirect" + dependencies: + "@stackflow/core": ^0.20.0 + "@stackflow/esbuild-config": ^0.20.0 + "@stackflow/eslint-config": ^0.20.0 + "@stackflow/react": ^0.20.1 + "@types/node": ^18.6.3 + "@types/react": ^18.0.10 + "@typescript-eslint/eslint-plugin": ^5.32.0 + "@typescript-eslint/parser": ^5.20.0 + esbuild: ^0.14.51 + eslint: ^8.13.0 + eslint-config-airbnb: ^19.0.4 + eslint-config-prettier: ^8.5.0 + eslint-plugin-import: ^2.26.0 + eslint-plugin-json-format: ^2.0.1 + eslint-plugin-jsx-a11y: ^6.5.1 + eslint-plugin-react: ^7.29.4 + eslint-plugin-react-hooks: ^4.4.0 + eslint-plugin-simple-import-sort: ^7.0.0 + react: ^18.1.0 + rimraf: ^3.0.2 + typescript: ^4.7.4 + url-pattern: ^1.0.3 + peerDependencies: + "@stackflow/core": 0 + "@stackflow/react": 0 + "@types/react": ">=16.8.0" + react: ">=16.8.0" + languageName: unknown + linkType: soft + "@stackflow/plugin-renderer-basic@^0.20.1, @stackflow/plugin-renderer-basic@workspace:extensions/plugin-renderer-basic": version: 0.0.0-use.local resolution: "@stackflow/plugin-renderer-basic@workspace:extensions/plugin-renderer-basic"