From 7b5533258acce60ffb850b273baef70399095f66 Mon Sep 17 00:00:00 2001 From: krutoo Date: Sat, 28 Mar 2026 20:16:11 +0500 Subject: [PATCH 1/4] feat: component registry added --- docs/package-lock.json | 185 ++++++++++------ docs/rspack.config.ts | 2 +- .../components/app-aside/app-aside.m.css | 13 ++ .../components/app-aside/app-aside.tsx | 96 ++++++++ .../components/app-aside/index.ts | 1 + .../components/app-header/app-header.tsx | 14 ++ .../components/app-header/index.ts | 1 + .../components/app-main/app-main.tsx | 14 ++ .../components/app-main/index.ts | 1 + .../components/app-modals/app-modals.tsx | 15 ++ .../components/app-modals/index.ts | 1 + .../components/app-search/app-search.m.css | 12 + .../components/app-search/app-search.tsx | 21 ++ .../components/app-search/index.ts | 1 + src/runtime-showcase/components/app/app.m.css | 32 --- src/runtime-showcase/components/app/app.tsx | 206 +++--------------- .../components/app/use-color-scheme-state.ts | 42 ++++ src/runtime-showcase/components/link/link.tsx | 2 +- .../components/menu-modal/menu-modal.tsx | 2 +- .../standalone-provider.tsx | 4 +- src/runtime-showcase/context/color-schemes.ts | 2 + .../context/component-registry.ts | 25 +++ src/runtime-showcase/context/routing.ts | 2 + src/runtime-showcase/context/showcase.ts | 2 +- src/runtime-showcase/index.ts | 7 +- src/runtime-showcase/shared/router-react.ts | 34 --- src/runtime-showcase/shared/router.ts | 94 -------- src/runtime-showcase/types.ts | 2 +- src/runtime-showcase/utils/routing.ts | 2 +- 29 files changed, 424 insertions(+), 411 deletions(-) create mode 100644 src/runtime-showcase/components/app-aside/app-aside.m.css create mode 100644 src/runtime-showcase/components/app-aside/app-aside.tsx create mode 100644 src/runtime-showcase/components/app-aside/index.ts create mode 100644 src/runtime-showcase/components/app-header/app-header.tsx create mode 100644 src/runtime-showcase/components/app-header/index.ts create mode 100644 src/runtime-showcase/components/app-main/app-main.tsx create mode 100644 src/runtime-showcase/components/app-main/index.ts create mode 100644 src/runtime-showcase/components/app-modals/app-modals.tsx create mode 100644 src/runtime-showcase/components/app-modals/index.ts create mode 100644 src/runtime-showcase/components/app-search/app-search.m.css create mode 100644 src/runtime-showcase/components/app-search/app-search.tsx create mode 100644 src/runtime-showcase/components/app-search/index.ts create mode 100644 src/runtime-showcase/components/app/use-color-scheme-state.ts create mode 100644 src/runtime-showcase/context/component-registry.ts delete mode 100644 src/runtime-showcase/shared/router-react.ts delete mode 100644 src/runtime-showcase/shared/router.ts diff --git a/docs/package-lock.json b/docs/package-lock.json index 56173bd..eee343c 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -39,7 +39,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.5.0.tgz", "integrity": "sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -51,7 +50,6 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.5.0.tgz", "integrity": "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -62,7 +60,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -369,7 +366,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.5.tgz", "integrity": "sha512-TBr9Cf9onSAS2LQ2+QHx6XcC6h9+RIzJgbqG3++9TUZSH204AwEy5jg3BTQ0VATsyoGj4ee49tN/y6rvaOOtcg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -411,7 +407,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -425,7 +420,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -439,7 +433,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -453,7 +446,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -467,7 +459,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -481,7 +472,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -495,7 +485,6 @@ "cpu": [ "wasm32" ], - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -509,7 +498,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -523,7 +511,6 @@ "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -537,7 +524,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -690,7 +676,6 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1040,9 +1025,9 @@ } }, "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", + "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", "dev": true, "license": "MIT", "dependencies": { @@ -1189,24 +1174,24 @@ } }, "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz", + "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", + "bytes": "~3.1.2", "content-type": "~1.0.5", "debug": "2.6.9", "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.14.0", + "raw-body": "~2.5.3", "type-is": "~1.6.18", - "unpipe": "1.0.0" + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8", @@ -1223,6 +1208,27 @@ "ms": "2.0.0" } }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1230,6 +1236,16 @@ "dev": true, "license": "MIT" }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/bonjour-service": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", @@ -2009,40 +2025,40 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "dev": true, "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -3015,9 +3031,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", @@ -3848,9 +3864,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", "dev": true, "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { @@ -4012,9 +4028,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", "dev": true, "license": "MIT" }, @@ -4026,9 +4042,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "license": "MIT", "engines": { @@ -4090,13 +4106,13 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -4116,21 +4132,52 @@ } }, "node_modules/raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" }, "engines": { "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/raw-body/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/react": { "version": "19.1.1", "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", @@ -4992,7 +5039,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, + "devOptional": true, "license": "0BSD" }, "node_modules/type-is": { diff --git a/docs/rspack.config.ts b/docs/rspack.config.ts index 3d55830..5a78e66 100644 --- a/docs/rspack.config.ts +++ b/docs/rspack.config.ts @@ -11,7 +11,7 @@ import dotenv from 'dotenv'; import packageJson from './package.json' with { type: 'json' }; if (process.env.NODE_ENV) { - dotenv.config({ path: `./.env.${process.env.NODE_ENV}` }); + dotenv.config({ path: `./.env.${process.env.NODE_ENV}`, quiet: true }); } await fs.rm('./dist', { recursive: true, force: true }); diff --git a/src/runtime-showcase/components/app-aside/app-aside.m.css b/src/runtime-showcase/components/app-aside/app-aside.m.css new file mode 100644 index 0000000..01a38d6 --- /dev/null +++ b/src/runtime-showcase/components/app-aside/app-aside.m.css @@ -0,0 +1,13 @@ +.menu { + box-sizing: border-box; + padding-top: 0.5rem; + padding-bottom: 1rem; + width: 100%; + height: 100%; + overflow: hidden; + overflow-y: auto; +} + +.menu:first-child { + padding-top: 1rem; +} diff --git a/src/runtime-showcase/components/app-aside/app-aside.tsx b/src/runtime-showcase/components/app-aside/app-aside.tsx new file mode 100644 index 0000000..d066a7a --- /dev/null +++ b/src/runtime-showcase/components/app-aside/app-aside.tsx @@ -0,0 +1,96 @@ +import { useContext, useState } from 'react'; +import { useLocation, useMatchMedia, useNavigate } from '@krutoo/utils/react'; +import { ComponentRegistryContext } from '../../context/component-registry'; +import { + ShowcaseContext, + useCurrentStory, + useMenuItems, + useStorySearchResult, +} from '../../context/showcase'; +import { Aside } from '../layout'; +import { Menu } from '../menu'; +import styles from './app-aside.m.css'; + +export function AppAside() { + const location = useLocation(); + const navigate = useNavigate(); + const { config } = useContext(ShowcaseContext); + const { routing } = config; + const { Search } = useContext(ComponentRegistryContext); + const menuItems = useMenuItems(); + const mobile = useMatchMedia('(max-width: 960px)'); + const [search, setSearch] = useState(''); + const searchResult = useStorySearchResult(search); + const currentStory = useCurrentStory(); + const enabled = currentStory?.isAsideEnabled(); + + if (mobile || !enabled) { + return null; + } + + return ( + + ); +} diff --git a/src/runtime-showcase/components/app-aside/index.ts b/src/runtime-showcase/components/app-aside/index.ts new file mode 100644 index 0000000..c9602da --- /dev/null +++ b/src/runtime-showcase/components/app-aside/index.ts @@ -0,0 +1 @@ +export { AppAside } from './app-aside'; diff --git a/src/runtime-showcase/components/app-header/app-header.tsx b/src/runtime-showcase/components/app-header/app-header.tsx new file mode 100644 index 0000000..72ec54c --- /dev/null +++ b/src/runtime-showcase/components/app-header/app-header.tsx @@ -0,0 +1,14 @@ +import { useContext } from 'react'; +import { ComponentRegistryContext } from '../../context/component-registry'; +import { Header } from '../layout'; + +export function AppHeader() { + const { HeaderLogo, HeaderLinks } = useContext(ComponentRegistryContext); + + return ( +
+ + +
+ ); +} diff --git a/src/runtime-showcase/components/app-header/index.ts b/src/runtime-showcase/components/app-header/index.ts new file mode 100644 index 0000000..1126d28 --- /dev/null +++ b/src/runtime-showcase/components/app-header/index.ts @@ -0,0 +1 @@ +export { AppHeader } from './app-header'; diff --git a/src/runtime-showcase/components/app-main/app-main.tsx b/src/runtime-showcase/components/app-main/app-main.tsx new file mode 100644 index 0000000..4d80093 --- /dev/null +++ b/src/runtime-showcase/components/app-main/app-main.tsx @@ -0,0 +1,14 @@ +import { useCurrentStory } from '../../context/showcase'; +import { Main } from '../layout'; +import { StoryPlaceholder } from '../story-placeholder'; +import { StoryViewer } from '../story-viewer'; + +export function AppMain() { + const story = useCurrentStory(); + + return ( +
+ {story ? : } +
+ ); +} diff --git a/src/runtime-showcase/components/app-main/index.ts b/src/runtime-showcase/components/app-main/index.ts new file mode 100644 index 0000000..8f412c0 --- /dev/null +++ b/src/runtime-showcase/components/app-main/index.ts @@ -0,0 +1 @@ +export { AppMain } from './app-main'; diff --git a/src/runtime-showcase/components/app-modals/app-modals.tsx b/src/runtime-showcase/components/app-modals/app-modals.tsx new file mode 100644 index 0000000..5b12e42 --- /dev/null +++ b/src/runtime-showcase/components/app-modals/app-modals.tsx @@ -0,0 +1,15 @@ +import { useContext } from 'react'; +import { useMatchMedia } from '@krutoo/utils/react'; +import { ShowcaseContext } from '../../context/showcase'; +import { MenuModal } from '../menu-modal'; + +export function AppModals() { + const { menuOpen, toggleMenu } = useContext(ShowcaseContext); + const mobile = useMatchMedia('(max-width: 960px)'); + + if (!mobile) { + return null; + } + + return toggleMenu(false)} />; +} diff --git a/src/runtime-showcase/components/app-modals/index.ts b/src/runtime-showcase/components/app-modals/index.ts new file mode 100644 index 0000000..dd55678 --- /dev/null +++ b/src/runtime-showcase/components/app-modals/index.ts @@ -0,0 +1 @@ +export { AppModals } from './app-modals'; diff --git a/src/runtime-showcase/components/app-search/app-search.m.css b/src/runtime-showcase/components/app-search/app-search.m.css new file mode 100644 index 0000000..d49e8ac --- /dev/null +++ b/src/runtime-showcase/components/app-search/app-search.m.css @@ -0,0 +1,12 @@ +.root { + padding-left: 1rem; + padding-right: 1rem; + padding-top: 1rem; + padding-bottom: 0.5rem; + display: flex; +} + +input.input { + width: 0; + flex-grow: 1; +} diff --git a/src/runtime-showcase/components/app-search/app-search.tsx b/src/runtime-showcase/components/app-search/app-search.tsx new file mode 100644 index 0000000..40dffc3 --- /dev/null +++ b/src/runtime-showcase/components/app-search/app-search.tsx @@ -0,0 +1,21 @@ +import { Input } from '../input'; +import styles from './app-search.m.css'; + +export interface AppSearchProps { + value: string; + onValueChange: (value: string) => void; +} + +export function AppSearch({ value, onValueChange }: AppSearchProps) { + return ( +
+ onValueChange(event.target.value)} + /> +
+ ); +} diff --git a/src/runtime-showcase/components/app-search/index.ts b/src/runtime-showcase/components/app-search/index.ts new file mode 100644 index 0000000..17d616c --- /dev/null +++ b/src/runtime-showcase/components/app-search/index.ts @@ -0,0 +1 @@ +export { AppSearch } from './app-search'; diff --git a/src/runtime-showcase/components/app/app.m.css b/src/runtime-showcase/components/app/app.m.css index 846846f..0e0b257 100644 --- a/src/runtime-showcase/components/app/app.m.css +++ b/src/runtime-showcase/components/app/app.m.css @@ -60,35 +60,3 @@ background: var(--showcase-ui-background, #fff); color: var(--showcase-ui-color, #222); } - -.aside { - padding-top: 1rem; - padding-bottom: 1rem; -} - -.search { - padding-left: 1rem; - padding-right: 1rem; - padding-top: 1rem; - padding-bottom: 0.5rem; - display: flex; -} - -input.searchField { - width: 0; - flex-grow: 1; -} - -.search + .menu { - padding-top: 0.5rem; -} - -.menu { - box-sizing: border-box; - padding-top: 1rem; - padding-bottom: 1rem; - width: 100%; - height: 100%; - overflow: hidden; - overflow-y: auto; -} diff --git a/src/runtime-showcase/components/app/app.tsx b/src/runtime-showcase/components/app/app.tsx index dc4ab5b..9cfe4b1 100644 --- a/src/runtime-showcase/components/app/app.tsx +++ b/src/runtime-showcase/components/app/app.tsx @@ -1,186 +1,48 @@ -import { type ReactNode, useContext, useEffect, useState } from 'react'; -import { useMatchMedia, useStorageItem } from '@krutoo/utils/react'; +import { useContext, useMemo } from 'react'; import classNames from 'classnames'; import { ColorSchemesContext } from '../../context/color-schemes'; -import { - ShowcaseContext, - useCurrentStory, - useMainMenu, - useMenuItems, - useStorySearchResult, -} from '../../context/showcase'; -import { useLocation, useNavigate } from '../../shared/router-react'; -import { HeaderLinks } from '../header-links'; -import { Input } from '../input'; -import { Aside, Header, Layout, Main } from '../layout'; -import { Logo } from '../logo'; -import { Menu } from '../menu'; -import { MenuModal } from '../menu-modal'; -import { StoryPlaceholder } from '../story-placeholder'; -import { StoryViewer } from '../story-viewer'; +import { ComponentRegistryContext } from '../../context/component-registry'; +import { ShowcaseContext } from '../../context/showcase'; +import { Layout } from '../layout'; +import { useColorSchemeState } from './use-color-scheme-state'; import styles from './app.m.css'; -export function App(): ReactNode { - const navigate = useNavigate(); - const location = useLocation(); - +export function App() { const { config } = useContext(ShowcaseContext); - const { routing } = config; - - const [menuOpen, setMenuOpen] = useMainMenu(); - const menuItems = useMenuItems(); - const mobile = useMatchMedia('(max-width: 960px)'); - const currentStory = useCurrentStory(); - - const [search, setSearch] = useState(''); - const searchResult = useStorySearchResult(search); + const { Header, Aside, Main, Modals } = useContext(ComponentRegistryContext); + const { colorScheme, toggleColorScheme } = useColorSchemeState({ + classes: { + dark: styles[`default-color-scheme-dark`], + light: styles[`default-color-scheme-light`], + }, + }); - const { colorScheme, toggleColorScheme } = useColorSchemeState(); + const rootClassName = classNames( + styles.root, + config.colorSchemes.defaults && styles[`default-color-scheme-${colorScheme}`], + ); - const colorSchemeContext = { - colorScheme, - onColorSchemeToggle: toggleColorScheme, - }; + const dataColorScheme = + config.colorSchemes.enabled && config.colorSchemes.attributeTarget === 'rootElement' + ? colorScheme + : undefined; + + const colorSchemeContext = useMemo( + () => ({ + colorScheme, + onColorSchemeToggle: toggleColorScheme, + }), + [colorScheme, toggleColorScheme], + ); return ( - -
- - -
- - {!mobile && (!currentStory || currentStory?.isAsideEnabled()) && ( - - )} - -
- {!currentStory && } - {currentStory && } -
- - {mobile && setMenuOpen(false)} />} + +
+