From 5094d341fa71e006e53693a53a175860456e3337 Mon Sep 17 00:00:00 2001 From: folinhilo Date: Sun, 14 Jun 2026 23:29:30 +0800 Subject: [PATCH] mm --- packages/css/package.json | 44 --- packages/css/scripts/gen-index.ts | 254 ------------------ packages/css/src/index.css | 36 --- packages/css/src/index.ts | 7 - packages/css/src/types/env.d.ts | 4 - packages/css/tsconfig.build.json | 41 --- packages/css/tsconfig.json | 20 -- packages/css/vite.config.ts | 39 --- packages/ui-react/package.json | 10 +- .../ui-react/src/componnets/Button/Button.tsx | 83 ++++++ .../ui-react/src/componnets/Icon/Icon.tsx | 21 ++ .../src/componnets/button/ButtonIcon.tsx | 19 -- .../src/componnets/button/ButtonLoading.tsx | 25 -- .../src/componnets/button/ButtonRoot.tsx | 60 ----- .../componnets/button/common/ButtonContext.ts | 26 -- .../ui-react/src/componnets/button/index.ts | 9 - packages/ui-react/src/index.css | 37 +++ packages/ui-react/src/index.ts | 61 +++-- .../src/recipes/brandRecipe.ts | 0 .../src/recipes/inlineSizeRecipe.ts | 0 .../src/recipes/itemSizeRecipe.ts | 26 +- .../src/recipes/variantRecipe.ts | 0 .../src/styles/base/root.css | 0 .../size-insensitive/align-content.css | 0 .../utility/size-insensitive/align-items.css | 0 .../utility/size-insensitive/align-self.css | 0 .../utility/size-insensitive/animation.css | 0 .../size-insensitive/box-decoration.css | 0 .../utility/size-insensitive/box-inside.css | 0 .../utility/size-insensitive/box-sizing.css | 0 .../styles/utility/size-insensitive/brand.css | 0 .../utility/size-insensitive/break-after.css | 0 .../utility/size-insensitive/break-before.css | 0 .../utility/size-insensitive/cursor.css | 0 .../utility/size-insensitive/display.css | 0 .../utility/size-insensitive/drop-shadow.css | 0 .../size-insensitive/flex-direction.css | 0 .../utility/size-insensitive/flex-wrap.css | 0 .../utility/size-insensitive/font-family.css | 0 .../size-insensitive/justify-content.css | 0 .../size-insensitive/justify-items.css | 0 .../utility/size-insensitive/justify-self.css | 0 .../utility/size-insensitive/overflow.css | 0 .../size-insensitive/overscroll-behavior.css | 0 .../utility/size-insensitive/position.css | 2 +- .../size-insensitive/screen-reader.css | 0 .../styles/utility/size-insensitive/theme.css | 0 .../utility/size-insensitive/user-select.css | 0 .../utility/size-insensitive/variant.css | 0 .../utility/size-insensitive/visibility.css | 11 + .../utility/size-insensitive/z-index.css | 0 .../utility/size-sensitive/border-radius.css | 0 .../utility/size-sensitive/font-size.css | 0 .../utility/size-sensitive/font-weight.css | 0 .../src/styles/utility/size-sensitive/gap.css | 6 +- .../styles/utility/size-sensitive/height.css | 0 .../styles/utility/size-sensitive/margin.css | 0 .../styles/utility/size-sensitive/padding.css | 0 .../styles/utility/size-sensitive/width.css | 6 +- .../{css => ui-react}/src/styles/utils/cpm.ts | 11 +- .../{css => ui-react}/src/styles/utils/cvr.ts | 0 packages/ui-react/src/utils/camelToKebab.ts | 3 + packages/ui-react/src/utils/mergeProps.ts | 23 +- .../ui-react/src/utils/useDefaultedProps.ts | 10 - .../ui-react/src/utils/useSlotRegistry.ts | 8 - .../ui-react/src/utils/useSlotsRegistry.ts | 69 +++++ packages/ui-react/tsconfig.build.json | 6 +- packages/ui-web-tw/scripts/gen-index.ts | 147 ---------- .../ui-gallery/src/gallery/ButtonGallery.tsx | 66 ++--- pnpm-lock.yaml | 37 --- 70 files changed, 313 insertions(+), 914 deletions(-) delete mode 100644 packages/css/package.json delete mode 100644 packages/css/scripts/gen-index.ts delete mode 100644 packages/css/src/index.css delete mode 100644 packages/css/src/index.ts delete mode 100644 packages/css/src/types/env.d.ts delete mode 100644 packages/css/tsconfig.build.json delete mode 100644 packages/css/tsconfig.json delete mode 100644 packages/css/vite.config.ts create mode 100644 packages/ui-react/src/componnets/Button/Button.tsx create mode 100644 packages/ui-react/src/componnets/Icon/Icon.tsx delete mode 100644 packages/ui-react/src/componnets/button/ButtonIcon.tsx delete mode 100644 packages/ui-react/src/componnets/button/ButtonLoading.tsx delete mode 100644 packages/ui-react/src/componnets/button/ButtonRoot.tsx delete mode 100644 packages/ui-react/src/componnets/button/common/ButtonContext.ts delete mode 100644 packages/ui-react/src/componnets/button/index.ts create mode 100644 packages/ui-react/src/index.css rename packages/{css => ui-react}/src/recipes/brandRecipe.ts (100%) rename packages/{css => ui-react}/src/recipes/inlineSizeRecipe.ts (100%) rename packages/{css => ui-react}/src/recipes/itemSizeRecipe.ts (52%) rename packages/{css => ui-react}/src/recipes/variantRecipe.ts (100%) rename packages/{css => ui-react}/src/styles/base/root.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/align-content.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/align-items.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/align-self.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/animation.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/box-decoration.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/box-inside.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/box-sizing.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/brand.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/break-after.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/break-before.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/cursor.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/display.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/drop-shadow.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/flex-direction.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/flex-wrap.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/font-family.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/justify-content.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/justify-items.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/justify-self.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/overflow.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/overscroll-behavior.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/position.css (99%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/screen-reader.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/theme.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/user-select.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-insensitive/variant.css (100%) create mode 100644 packages/ui-react/src/styles/utility/size-insensitive/visibility.css rename packages/{css => ui-react}/src/styles/utility/size-insensitive/z-index.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/border-radius.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/font-size.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/font-weight.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/gap.css (70%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/height.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/margin.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/padding.css (100%) rename packages/{css => ui-react}/src/styles/utility/size-sensitive/width.css (93%) rename packages/{css => ui-react}/src/styles/utils/cpm.ts (67%) rename packages/{css => ui-react}/src/styles/utils/cvr.ts (100%) create mode 100644 packages/ui-react/src/utils/camelToKebab.ts delete mode 100644 packages/ui-react/src/utils/useDefaultedProps.ts delete mode 100644 packages/ui-react/src/utils/useSlotRegistry.ts create mode 100644 packages/ui-react/src/utils/useSlotsRegistry.ts delete mode 100644 packages/ui-web-tw/scripts/gen-index.ts diff --git a/packages/css/package.json b/packages/css/package.json deleted file mode 100644 index 983bd59..0000000 --- a/packages/css/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "@dg/css", - "version": "0.0.0", - "private": true, - "type": "module", - "sideEffects": [ - "*.css" - ], - "module": "./dist/index.es.js", - "main": "./dist/index.cjs.js", - "types": "./dist/index.d.ts", - "style": "./dist/index.css", - "exports": { - ".": { - "import": "./dist/index.es.js", - "require": "./dist/index.cjs.js", - "types": "./dist/index.d.ts" - }, - "./index.css": "./dist/index.css" - }, - "files": [ - "dist" - ], - "scripts": { - "gen-index": "ts-node scripts/gen-index.ts", - "gen-dts": "tsc -p tsconfig.build.json", - "dev": "pnpm gen-index && vite build --watch", - "build": "pnpm gen-index && vite build && pnpm gen-dts" - }, - "devDependencies": { - "@types/node": "^25.6.0", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^6.0.1", - "tinyglobby": "^0.2.16", - "ts-node": "^10.9.2", - "typescript": "^6.0.3", - "vite": "^8.0.10" - }, - "peerDependencies": { - "react": "^19", - "react-dom": "^19" - } -} diff --git a/packages/css/scripts/gen-index.ts b/packages/css/scripts/gen-index.ts deleted file mode 100644 index ffe64b1..0000000 --- a/packages/css/scripts/gen-index.ts +++ /dev/null @@ -1,254 +0,0 @@ -import * as fs from "fs"; -import * as path from "path"; - -/** - * 默认测试 / story / example / fixture / type 文件匹配规则 - * 仅用于“识别”,不直接决定是否排除 - */ -const DEFAULT_TEST_FILE_PATTERNS: RegExp[] = [ - // ========================= - // Test / Spec - // ========================= - /\.(test|spec)\.(ts|tsx|js|jsx)$/, - /\.(test|spec)\.(ts|tsx|js|jsx)\?.*$/, // query param safe - - // ========================= - // E2E / Playwright / Cypress - // ========================= - /\.(cy|playwright|e2e)\.(ts|tsx|js|jsx)$/, - - // ========================= - // Storybook - // ========================= - /\.(story|stories)\.(ts|tsx|js|jsx|mdx)$/, - - // ========================= - // Snapshot / Mock / Fixture - // ========================= - /\.snap$/, - /\.mock\.(ts|tsx|js|jsx)$/, - /\.fixture\.(ts|tsx|js|jsx)$/, - - // ========================= - // Type declarations - // ========================= - /\.d\.ts$/, - - // ========================= - // Examples / Demos / Docs - // ========================= - /\.(example|demo|docs)\.(ts|tsx|js|jsx)$/, -]; - -/** - * 测试 / 辅助目录(目录级排除) - */ -const DEFAULT_TEST_DIR_PATTERNS: RegExp[] = [ - /[/\\](__tests__|tests|test|spec|__mocks__|__fixtures__|__snapshots__)[\/\\]/, - /[/\\](cypress|playwright|e2e|__e2e__|__playwright__)[\/\\]/, - /[/\\](story|stories|\.storybook)[\/\\]/, - /[/\\](types|type|typings|interfaces)[\/\\]/, - /[/\\](examples|example|demo|demos|docs)[\/\\]/, -]; - -type Config = { - outputDir: string; - outputFile: string; - scanDirs: string[]; - preamble?: string[]; - importPrefix?: string; - entryFilePatterns?: RegExp[]; - barrelFirstMode?: boolean; - includeFilePatterns?: RegExp[]; - excludeFilePatterns?: RegExp[]; - excludeDirPatterns?: RegExp[]; -}; - -const tsConfig: Config = { - outputDir: "src", - outputFile: "index.ts", - scanDirs: ["src"], - importPrefix: "export * from", - barrelFirstMode: true, - preamble: ["import './index.css';"], - entryFilePatterns: [/^index\.(js|ts|jsx|tsx)$/], - includeFilePatterns: [/\.(js|ts|jsx|tsx)$/], - excludeFilePatterns: DEFAULT_TEST_FILE_PATTERNS, - excludeDirPatterns: DEFAULT_TEST_DIR_PATTERNS, -}; - -const cssConfig: Config = { - outputDir: "src", - outputFile: "index.css", - scanDirs: ["src"], - importPrefix: "@import", - barrelFirstMode: false, - entryFilePatterns: [/^index\.(css)$/], - includeFilePatterns: [/\.(css)$/], - excludeFilePatterns: DEFAULT_TEST_FILE_PATTERNS, - excludeDirPatterns: DEFAULT_TEST_DIR_PATTERNS, -}; - -function isEntryFile(fileName: string, config: Config): boolean { - const regExps = config.entryFilePatterns; - - if (!regExps || regExps.length === 0) return false; - - return regExps.some((regExp) => regExp.test(fileName)); -} - -function isIncludeFile(fileName: string, config: Config): boolean { - const regExps = config.includeFilePatterns; - - if (!regExps || regExps.length === 0) return false; - - return regExps.some((regExp) => regExp.test(fileName)); -} - -function isExcludeFile(fileName: string, config: Config): boolean { - const regExps = config.excludeFilePatterns; - - if (!regExps || regExps.length === 0) return false; - - return regExps.some((regExp) => regExp.test(fileName)); -} - -function isExcludeDir(filePath: string, config: Config): boolean { - const regExps = config.excludeDirPatterns; - - if (!regExps || regExps.length === 0) return false; - - return regExps.some((regExp) => regExp.test(filePath)); -} - -function isValidDir(filePath: string, config: Config): boolean { - if (isExcludeDir(filePath, config)) { - return false; - } - return true; -} - -function isValidFile(fileName: string, config: Config): boolean { - if (isIncludeFile(fileName, config) && !isExcludeFile(fileName, config)) { - return true; - } - - return false; -} - -const buildExportStatement = (filePath: string, config: Config) => { - // 文件夹(不是文件)与目标文件的相对路径 - let exportFilePath = path.relative(config.outputDir, filePath); - - // 去除扩展名,并且转化成正斜杠 - const exportFilePathWithoutExt = path - .join( - path.dirname(exportFilePath), - path.basename(exportFilePath, path.extname(exportFilePath)), - ) - .replace(/\\/g, "/"); - - // 加上 ./ 前缀 - return `${config.importPrefix} './${exportFilePathWithoutExt}';`; -}; - -function isOutputEntry(filePath: string, config: Config) { - const outputFilePath = path.resolve(config.outputDir, config.outputFile); - const targetFilePath = path.resolve(filePath); - - return outputFilePath === targetFilePath; -} - -function generateExports(dirPath: string, config: Config): string[] { - const fileNames = fs.readdirSync(dirPath); - const exports: string[] = []; - - // ========================= - // 逻辑分支:Barrel First Mode - // ========================= - if (config.barrelFirstMode) { - // 查找当前目录有没有 index.ts - const entryFileName = fileNames.find((fileName) => { - const filePath = path.join(dirPath, fileName); - return fs.statSync(filePath).isFile() && isEntryFile(fileName, config); - }); - // 如果有 - if (entryFileName) { - const entryFilePath = path.join(dirPath, entryFileName); - - // 如果是 outputFile 自身,则跳过 - if (isOutputEntry(entryFilePath, config)) { - console.log(`⏭️ 跳过自身入口文件: ${entryFilePath}`); - } else { - exports.push(buildExportStatement(entryFilePath, config)); - } - } - } - - // ========================= - // 逻辑分支:index.ts 不存在,则继续正常遍历与递归 - // ========================= - fileNames.forEach((fileName) => { - const filePath = path.join(dirPath, fileName); - const stat = fs.statSync(filePath); - - // 情况1:是文件,且通过了校验 - if ( - stat.isFile() && - isValidFile(fileName, config) && - !isEntryFile(fileName, config) - ) { - exports.push(buildExportStatement(filePath, config)); - } - // 情况2:是文件夹,且通过了校验,递归扫描子文件夹 - else if (stat.isDirectory() && isValidDir(filePath, config)) { - const subExports = generateExports(filePath, config); - exports.push(...subExports); - } - }); - - return exports; -} - -async function genIndexFile(config: Config) { - const allExports: string[] = []; - - // 遍历所有需要扫描的根目录 - config.scanDirs.forEach((scanDir) => { - // 只有当目录真实存在时才进行扫描 - if (fs.existsSync(scanDir)) { - const exports = generateExports(scanDir, config); - allExports.push(...exports); - } else { - console.warn(`⚠️ 警告:扫描目录不存在,已跳过 -> ${scanDir}`); - } - }); - - // 拼接最终的文件内容:前言 + 导出语句(使用 Set 自动去重) - const fileContent = [ - ...(config.preamble ?? []), - ...Array.from(new Set(allExports)), - ].join("\n"); - - // 写入之前,确保输出目录存在,如果不存在就递归创建 - if (!fs.existsSync(config.outputDir)) { - fs.mkdirSync(config.outputDir, { recursive: true }); - } - - // 将内容写入到最终的 index.ts 文件中 - const outputFilePath = path.join(config.outputDir, config.outputFile); - fs.writeFileSync(outputFilePath, fileContent, "utf-8"); - - console.log(`✨ 成功生成入口文件: ${outputFilePath}`); -} - -// ================= 脚本执行入口 ================= -try { - console.log("🚀 开始扫描并生成入口文件..."); - await genIndexFile(cssConfig); - await genIndexFile(tsConfig); - console.log("✅ 脚本执行完毕!"); -} catch (error) { - console.error("❌ 脚本执行失败:", error); - process.exit(1); // 如果报错,让进程以非 0 状态码退出 -} diff --git a/packages/css/src/index.css b/packages/css/src/index.css deleted file mode 100644 index e17c1b6..0000000 --- a/packages/css/src/index.css +++ /dev/null @@ -1,36 +0,0 @@ -@import "./styles/base/root"; -@import "./styles/utility/size-insensitive/align-content"; -@import "./styles/utility/size-insensitive/align-items"; -@import "./styles/utility/size-insensitive/align-self"; -@import "./styles/utility/size-insensitive/animation"; -@import "./styles/utility/size-insensitive/box-decoration"; -@import "./styles/utility/size-insensitive/box-inside"; -@import "./styles/utility/size-insensitive/box-sizing"; -@import "./styles/utility/size-insensitive/brand"; -@import "./styles/utility/size-insensitive/break-after"; -@import "./styles/utility/size-insensitive/break-before"; -@import "./styles/utility/size-insensitive/cursor"; -@import "./styles/utility/size-insensitive/display"; -@import "./styles/utility/size-insensitive/drop-shadow"; -@import "./styles/utility/size-insensitive/flex-direction"; -@import "./styles/utility/size-insensitive/flex-wrap"; -@import "./styles/utility/size-insensitive/font-family"; -@import "./styles/utility/size-insensitive/justify-content"; -@import "./styles/utility/size-insensitive/justify-items"; -@import "./styles/utility/size-insensitive/justify-self"; -@import "./styles/utility/size-insensitive/overflow"; -@import "./styles/utility/size-insensitive/overscroll-behavior"; -@import "./styles/utility/size-insensitive/position"; -@import "./styles/utility/size-insensitive/screen-reader"; -@import "./styles/utility/size-insensitive/theme"; -@import "./styles/utility/size-insensitive/user-select"; -@import "./styles/utility/size-insensitive/variant"; -@import "./styles/utility/size-insensitive/z-index"; -@import "./styles/utility/size-sensitive/border-radius"; -@import "./styles/utility/size-sensitive/font-size"; -@import "./styles/utility/size-sensitive/font-weight"; -@import "./styles/utility/size-sensitive/gap"; -@import "./styles/utility/size-sensitive/height"; -@import "./styles/utility/size-sensitive/margin"; -@import "./styles/utility/size-sensitive/padding"; -@import "./styles/utility/size-sensitive/width"; diff --git a/packages/css/src/index.ts b/packages/css/src/index.ts deleted file mode 100644 index 271cdb6..0000000 --- a/packages/css/src/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import "./index.css"; -export * from "./recipes/brandRecipe"; -export * from "./recipes/inlineSizeRecipe"; -export * from "./recipes/itemSizeRecipe"; -export * from "./recipes/variantRecipe"; -export * from "./styles/utils/cpm"; -export * from "./styles/utils/cvr"; diff --git a/packages/css/src/types/env.d.ts b/packages/css/src/types/env.d.ts deleted file mode 100644 index 31058d4..0000000 --- a/packages/css/src/types/env.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -declare module "*.css" { - const content: string; - export default content; -} diff --git a/packages/css/tsconfig.build.json b/packages/css/tsconfig.build.json deleted file mode 100644 index a5bcc27..0000000 --- a/packages/css/tsconfig.build.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "noEmit": false, - "emitDeclarationOnly": true, - "declaration": true, - "rootDir": "./src", - "outDir": "./dist", - "declarationDir": "./dist" - }, - "include": ["src"], - "exclude": [ - "node_modules", - "dist", - ".turbo/**/*", - ".cache/**/*", - ".vite/**/*", - "vite.config.ts", - "*.config.ts", - "*.config.js", - "tsconfig.*.json", - "__tests__/**/*", - "test/**/*", - "tests/**/*", - "**/*.test.ts", - "**/*.test.tsx", - "**/*.spec.ts", - "**/*.spec.tsx", - ".storybook/**/*", - "stories/**/*", - "example/**/*", - "examples/**/*", - "scripts/**/*", - ".env", - ".env.*", - "public/**/*", - "docs/**/*", - "README.md", - "LICENSE" - ] -} diff --git a/packages/css/tsconfig.json b/packages/css/tsconfig.json deleted file mode 100644 index fcbe200..0000000 --- a/packages/css/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "es2025", - "lib": ["ES2025", "DOM", "DOM.Iterable"], - "module": "ESNext", - "types": ["node", "vite/client"], - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx" - }, - "include": ["src", "scripts", "vite.config.ts"] -} diff --git a/packages/css/vite.config.ts b/packages/css/vite.config.ts deleted file mode 100644 index ea4923d..0000000 --- a/packages/css/vite.config.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import path from "path"; - -export default defineConfig({ - plugins: [react()], - - build: { - cssMinify: false, - - lib: { - entry: path.resolve(import.meta.dirname, "src/index.ts"), - formats: ["es", "cjs"], - fileName: (format) => `index.${format}.js`, - }, - - rolldownOptions: { - external: ["react", "react-dom", "react/jsx-runtime"], - output: { - // 强制将生成的 CSS 命名为 index.css - assetFileNames: (assetInfo) => { - if (assetInfo.name && assetInfo.name.endsWith(".css")) { - return "index.css"; - } - return "[name].[hash][extname]"; - }, - globals: { - react: "React", - "react-dom": "ReactDOM", - }, - }, - }, - - emptyOutDir: true, - sourcemap: true, - cssCodeSplit: false, - outDir: "dist", - }, -}); diff --git a/packages/ui-react/package.json b/packages/ui-react/package.json index d0cbc0a..13b0e2f 100644 --- a/packages/ui-react/package.json +++ b/packages/ui-react/package.json @@ -26,18 +26,16 @@ "gen-dts": "tsc -p tsconfig.build.json", "build": "pnpm gen-index && vite build && pnpm gen-dts" }, - "dependencies": { - "@dg/css": "workspace:*" - }, + "dependencies": {}, "devDependencies": { "@types/node": "^25.6.0", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^6.0.1", "tinyglobby": "^0.2.16", "ts-node": "^10.9.2", "typescript": "^6.0.3", - "vite": "^8.0.10", - "@types/react": "^19.2.14", - "@types/react-dom": "^19.2.3" + "vite": "^8.0.10" }, "peerDependencies": { "react": "^19", diff --git a/packages/ui-react/src/componnets/Button/Button.tsx b/packages/ui-react/src/componnets/Button/Button.tsx new file mode 100644 index 0000000..ab065cc --- /dev/null +++ b/packages/ui-react/src/componnets/Button/Button.tsx @@ -0,0 +1,83 @@ +import { + type ComponentPropsWithoutRef, + forwardRef, + type ReactNode, +} from "react"; + +import { Icon } from "../Icon/Icon"; +import { SpinnerSvg } from "../../assets/svg/SpinnerSvg"; +import { cpm } from "../../styles/utils/cpm"; +import { itemSizeRecipe } from "../../recipes/itemSizeRecipe"; +import { variantRecipe } from "../../recipes/variantRecipe"; +import { brandRecipe } from "../../recipes/brandRecipe"; +import { inlineSizeRecipe } from "../../recipes/inlineSizeRecipe"; + +export type ButtonSize = "xs" | "sm" | "md" | "lg"; + +export type ButtonProps = ComponentPropsWithoutRef<"button"> & { + size?: ButtonSize; + variant?: "filled" | "outline" | "subtle" | "ghost"; + shape?: "rounded" | "square" | "circle"; + brand?: "success" | "danger" | "info" | "warning" | "emphasize"; +} & { + iconOnly?: boolean; + hideIcon?: boolean; + loading?: boolean; +} & { + iconSvg?: ReactNode; + loadingIconSvg?: ReactNode; +}; + +export const Button = forwardRef( + (props, ref) => { + const { + size = "md", + variant = "filled", + shape = "rounded", + brand = "info", + // =========================== + iconOnly = false, + hideIcon = false, + loading, + disabled = false, + // ========================= + className = "", + children, + // ========================== + iconSvg, + loadingIconSvg = , + ...rest + } = props; + + const mergedClass = cpm( + itemSizeRecipe({ size, shape, iconOnly }), + variantRecipe({ variant, disabled }), + brandRecipe({ brand }), + className, + ); + + const contentClass = loading + ? cpm("visible--hidden", inlineSizeRecipe({ size })) + : inlineSizeRecipe({ size }); + + const loadingIconClass = loading ? "position--absolute" : ""; + + const icon = {iconSvg}; + const loadingIcon = ( + + {loadingIconSvg} + + ); + + return ( + + ); + }, +); +Button.displayName = "Button"; diff --git a/packages/ui-react/src/componnets/Icon/Icon.tsx b/packages/ui-react/src/componnets/Icon/Icon.tsx new file mode 100644 index 0000000..48e392d --- /dev/null +++ b/packages/ui-react/src/componnets/Icon/Icon.tsx @@ -0,0 +1,21 @@ +import { forwardRef, type ComponentPropsWithoutRef } from "react"; +import { Slot } from "../../utils/Slot"; +import { inlineSizeRecipe } from "../../recipes/inlineSizeRecipe"; +import { cpm } from "../../styles/utils/cpm"; + +export type IconProps = { + size?: "xs" | "sm" | "md" | "lg" | "xl" | "2xl"; +} & ComponentPropsWithoutRef<"svg">; + +export const Icon = forwardRef((props, ref) => { + const { size = "md", className = "", children, ...rest } = props; + const mergedClass = cpm(inlineSizeRecipe({ size }), className); + + return ( + + {children} + + ); +}); + +Icon.displayName = "Icon"; diff --git a/packages/ui-react/src/componnets/button/ButtonIcon.tsx b/packages/ui-react/src/componnets/button/ButtonIcon.tsx deleted file mode 100644 index 3483b6d..0000000 --- a/packages/ui-react/src/componnets/button/ButtonIcon.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { useEffect } from "react"; -import { Slot } from "../../utils/Slot"; -import { useButtonContext } from "./common/ButtonContext"; - -export const ButtonIcon = (props: any) => { - const { children, ...rest } = props; - - const { slotRegistry } = useButtonContext(); - - useEffect(() => { - slotRegistry.setSlots?.((prev) => ({ - ...prev, - icon: {children}, - })); - }, [children, slotRegistry]); - - return null; -}; -ButtonIcon.displayName = "ButtonIcon"; diff --git a/packages/ui-react/src/componnets/button/ButtonLoading.tsx b/packages/ui-react/src/componnets/button/ButtonLoading.tsx deleted file mode 100644 index ada35e1..0000000 --- a/packages/ui-react/src/componnets/button/ButtonLoading.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useEffect } from "react"; -import type { ReactNode } from "react"; -import { useButtonContext } from "./common/ButtonContext"; -import { Slot } from "../../utils/Slot"; - - -type ButtonLoadingProps = { - children: ReactNode; -}; - -export const ButtonLoading = (props: ButtonLoadingProps) => { - const { children, ...rest } = props; - const { slotRegistry } = useButtonContext(); - - useEffect(() => { - slotRegistry.setSlots?.(prev => ({ - ...prev, - loading: {children}, - })); - }, [children, slotRegistry]); - - return null; -}; - -ButtonLoading.displayName = "ButtonLoading"; \ No newline at end of file diff --git a/packages/ui-react/src/componnets/button/ButtonRoot.tsx b/packages/ui-react/src/componnets/button/ButtonRoot.tsx deleted file mode 100644 index 29be6f9..0000000 --- a/packages/ui-react/src/componnets/button/ButtonRoot.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { type ComponentPropsWithoutRef, forwardRef } from "react"; -import { ButtonContext, type ButtonSlot } from "./common/ButtonContext"; -import { useSlotRegistry } from "../../utils/useSlotRegistry"; -import { mergeProps } from "../../utils/mergeProps"; -import { useDefaultedProps } from "../../utils/useDefaultedProps"; -import { brandRecipe, cpm, itemSizeRecipe, variantRecipe } from "@dg/css"; - -export type ButtonRootOwnProps = { - size?: "xs" | "sm" | "md" | "lg"; - variant?: "filled" | "outline" | "subtle" | "ghost"; - shape?: "rounded" | "square" | "circle"; - brand?: "success" | "danger" | "info" | "warning" | "emphasize"; - iconOnly?: boolean; - hideIcon?: boolean; - loading?: boolean; - disabled?: boolean; -}; - -export type ButtonRootPrimitiveProps = Omit< - ComponentPropsWithoutRef<"button">, - keyof ButtonRootOwnProps ->; - -export type ButtonRootProps = ButtonRootOwnProps & ButtonRootPrimitiveProps; - -export const ButtonRoot = forwardRef( - (props, ref) => { - const defaultedProps = useDefaultedProps(props, { - size: "md", - variant: "filled", - shape: "rounded", - brand: "info", - iconOnly: false, - disabled: false, - }); - const { size, variant, shape, brand, iconOnly, disabled, children } = - defaultedProps; - - const clx = cpm( - itemSizeRecipe({ size, shape, iconOnly }), - variantRecipe({ variant, disabled }), - brandRecipe({ brand }), - ); - - const mergedProps = mergeProps({ className: clx }, defaultedProps); - - const slotRegistry = useSlotRegistry(); - - return ( - - - - ); - }, -); -ButtonRoot.displayName = "Button.Root"; diff --git a/packages/ui-react/src/componnets/button/common/ButtonContext.ts b/packages/ui-react/src/componnets/button/common/ButtonContext.ts deleted file mode 100644 index dd1e25d..0000000 --- a/packages/ui-react/src/componnets/button/common/ButtonContext.ts +++ /dev/null @@ -1,26 +0,0 @@ -// ButtonContext.ts -import { createContext, useContext, type ReactNode } from "react"; - -export type ButtonSlot = { - icon?: ReactNode; - loading?: ReactNode; -}; - -type ButtonContextValue = { - slotRegistry: { - slots?: ButtonSlot; - setSlots?: React.Dispatch>; - }; -}; - -export const ButtonContext = createContext( - undefined, -); - -export const useButtonContext = () => { - const ctx = useContext(ButtonContext); - if (!ctx) { - throw new Error("Button 子组件必须在 Button.Root 内使用"); - } - return ctx; -}; diff --git a/packages/ui-react/src/componnets/button/index.ts b/packages/ui-react/src/componnets/button/index.ts deleted file mode 100644 index e32665e..0000000 --- a/packages/ui-react/src/componnets/button/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ButtonIcon } from "./ButtonIcon"; -import { ButtonLoading } from "./ButtonLoading"; -import { ButtonRoot } from "./ButtonRoot"; - -export const Button = { - Root: ButtonRoot, - Icon: ButtonIcon, - Loading: ButtonLoading, -} \ No newline at end of file diff --git a/packages/ui-react/src/index.css b/packages/ui-react/src/index.css new file mode 100644 index 0000000..ad71dd2 --- /dev/null +++ b/packages/ui-react/src/index.css @@ -0,0 +1,37 @@ +@import './styles/base/root'; +@import './styles/utility/size-insensitive/align-content'; +@import './styles/utility/size-insensitive/align-items'; +@import './styles/utility/size-insensitive/align-self'; +@import './styles/utility/size-insensitive/animation'; +@import './styles/utility/size-insensitive/box-decoration'; +@import './styles/utility/size-insensitive/box-inside'; +@import './styles/utility/size-insensitive/box-sizing'; +@import './styles/utility/size-insensitive/brand'; +@import './styles/utility/size-insensitive/break-after'; +@import './styles/utility/size-insensitive/break-before'; +@import './styles/utility/size-insensitive/cursor'; +@import './styles/utility/size-insensitive/display'; +@import './styles/utility/size-insensitive/drop-shadow'; +@import './styles/utility/size-insensitive/flex-direction'; +@import './styles/utility/size-insensitive/flex-wrap'; +@import './styles/utility/size-insensitive/font-family'; +@import './styles/utility/size-insensitive/justify-content'; +@import './styles/utility/size-insensitive/justify-items'; +@import './styles/utility/size-insensitive/justify-self'; +@import './styles/utility/size-insensitive/overflow'; +@import './styles/utility/size-insensitive/overscroll-behavior'; +@import './styles/utility/size-insensitive/position'; +@import './styles/utility/size-insensitive/screen-reader'; +@import './styles/utility/size-insensitive/theme'; +@import './styles/utility/size-insensitive/user-select'; +@import './styles/utility/size-insensitive/variant'; +@import './styles/utility/size-insensitive/visibility'; +@import './styles/utility/size-insensitive/z-index'; +@import './styles/utility/size-sensitive/border-radius'; +@import './styles/utility/size-sensitive/font-size'; +@import './styles/utility/size-sensitive/font-weight'; +@import './styles/utility/size-sensitive/gap'; +@import './styles/utility/size-sensitive/height'; +@import './styles/utility/size-sensitive/margin'; +@import './styles/utility/size-sensitive/padding'; +@import './styles/utility/size-sensitive/width'; \ No newline at end of file diff --git a/packages/ui-react/src/index.ts b/packages/ui-react/src/index.ts index 7f9f795..0e763a6 100644 --- a/packages/ui-react/src/index.ts +++ b/packages/ui-react/src/index.ts @@ -1,29 +1,32 @@ -import "./index.css"; -export * from "./assets/svg/BoldSvg"; -export * from "./assets/svg/CheckIndicatorSvg"; -export * from "./assets/svg/ChevronRightSvg"; -export * from "./assets/svg/CutSvg"; -export * from "./assets/svg/DownloadSvg"; -export * from "./assets/svg/FileSvg"; -export * from "./assets/svg/KeySvg"; -export * from "./assets/svg/MeshSvg"; -export * from "./assets/svg/MoonSvg"; -export * from "./assets/svg/PasteSvg"; -export * from "./assets/svg/Ruler"; -export * from "./assets/svg/SearchSvg"; -export * from "./assets/svg/SettingSvg"; -export * from "./assets/svg/SpinnerSvg"; -export * from "./assets/svg/SunSvg"; -export * from "./assets/svg/UserSvg"; -export * from "./assets/svg/VolumeHighSvg"; -export * from "./assets/svg/VolumeLowSvg"; -export * from "./assets/svg/VolumeMuteSvg"; -export * from "./componnets/button/index"; -export * from "./componnets/button/ButtonIcon"; -export * from "./componnets/button/ButtonLoading"; -export * from "./componnets/button/ButtonRoot"; -export * from "./componnets/button/common/ButtonContext"; -export * from "./utils/mergeProps"; -export * from "./utils/Slot"; -export * from "./utils/useDefaultedProps"; -export * from "./utils/useSlotRegistry"; +import './index.css'; +export * from './assets/svg/BoldSvg'; +export * from './assets/svg/CheckIndicatorSvg'; +export * from './assets/svg/ChevronRightSvg'; +export * from './assets/svg/CutSvg'; +export * from './assets/svg/DownloadSvg'; +export * from './assets/svg/FileSvg'; +export * from './assets/svg/KeySvg'; +export * from './assets/svg/MeshSvg'; +export * from './assets/svg/MoonSvg'; +export * from './assets/svg/PasteSvg'; +export * from './assets/svg/Ruler'; +export * from './assets/svg/SearchSvg'; +export * from './assets/svg/SettingSvg'; +export * from './assets/svg/SpinnerSvg'; +export * from './assets/svg/SunSvg'; +export * from './assets/svg/UserSvg'; +export * from './assets/svg/VolumeHighSvg'; +export * from './assets/svg/VolumeLowSvg'; +export * from './assets/svg/VolumeMuteSvg'; +export * from './componnets/Button/Button'; +export * from './componnets/Icon/Icon'; +export * from './recipes/brandRecipe'; +export * from './recipes/inlineSizeRecipe'; +export * from './recipes/itemSizeRecipe'; +export * from './recipes/variantRecipe'; +export * from './styles/utils/cpm'; +export * from './styles/utils/cvr'; +export * from './utils/camelToKebab'; +export * from './utils/mergeProps'; +export * from './utils/Slot'; +export * from './utils/useSlotsRegistry'; \ No newline at end of file diff --git a/packages/css/src/recipes/brandRecipe.ts b/packages/ui-react/src/recipes/brandRecipe.ts similarity index 100% rename from packages/css/src/recipes/brandRecipe.ts rename to packages/ui-react/src/recipes/brandRecipe.ts diff --git a/packages/css/src/recipes/inlineSizeRecipe.ts b/packages/ui-react/src/recipes/inlineSizeRecipe.ts similarity index 100% rename from packages/css/src/recipes/inlineSizeRecipe.ts rename to packages/ui-react/src/recipes/inlineSizeRecipe.ts diff --git a/packages/css/src/recipes/itemSizeRecipe.ts b/packages/ui-react/src/recipes/itemSizeRecipe.ts similarity index 52% rename from packages/css/src/recipes/itemSizeRecipe.ts rename to packages/ui-react/src/recipes/itemSizeRecipe.ts index 161b03a..9b338c0 100644 --- a/packages/css/src/recipes/itemSizeRecipe.ts +++ b/packages/ui-react/src/recipes/itemSizeRecipe.ts @@ -5,10 +5,10 @@ export const itemSizeRecipe = cvr({ variants: { size: { xs: "text--xs h--item-xs gap--xs px--xs", - sm: "text--sm h--item-sm gap-sm px--sm", - md: "text--md h--item-md gap-md px--md", - lg: "text--lg h--item-lg gap-lg px--lg", - xl: "text--xl h--item-xl gap-xl px--xl", + sm: "text--sm h--item-sm gap--sm px--sm", + md: "text--md h--item-md gap--md px--md", + lg: "text--lg h--item-lg gap--lg px--lg", + xl: "text--xl h--item-xl gap--xl px--xl", "2xl": "text--2xl h--item-2xl gap--2xl px--2xl", }, shape: { @@ -22,19 +22,13 @@ export const itemSizeRecipe = cvr({ }, }, compoundVariants: [ - { iconOnly: false, size: "xs", class: "px--xs" }, - { iconOnly: false, size: "sm", class: "px--sm" }, - { iconOnly: false, size: "md", class: "px--md" }, - { iconOnly: false, size: "lg", class: "px--lg" }, - { iconOnly: false, size: "xl", class: "px--xl" }, - { iconOnly: false, size: "2xl", class: "px--2xl" }, // ================================================== - { shape: "rounded", size: "xs", class: "rounded--sm" }, - { shape: "rounded", size: "sm", class: "rounded--md" }, - { shape: "rounded", size: "md", class: "rounded--lg" }, - { shape: "rounded", size: "lg", class: "rounded--xl" }, - { shape: "rounded", size: "xl", class: "rounded--2xl" }, - { shape: "rounded", size: "2xl", class: "rounded--3xl" }, + { shape: "rounded", size: "xs", class: "rounded--xs" }, + { shape: "rounded", size: "sm", class: "rounded--sm" }, + { shape: "rounded", size: "md", class: "rounded--md" }, + { shape: "rounded", size: "lg", class: "rounded--lg" }, + { shape: "rounded", size: "xl", class: "rounded--xl" }, + { shape: "rounded", size: "2xl", class: "rounded--2xl" }, // ================================================== { iconOnly: true, size: "xs", class: "w--item-xs" }, { iconOnly: true, size: "sm", class: "w--item-sm" }, diff --git a/packages/css/src/recipes/variantRecipe.ts b/packages/ui-react/src/recipes/variantRecipe.ts similarity index 100% rename from packages/css/src/recipes/variantRecipe.ts rename to packages/ui-react/src/recipes/variantRecipe.ts diff --git a/packages/css/src/styles/base/root.css b/packages/ui-react/src/styles/base/root.css similarity index 100% rename from packages/css/src/styles/base/root.css rename to packages/ui-react/src/styles/base/root.css diff --git a/packages/css/src/styles/utility/size-insensitive/align-content.css b/packages/ui-react/src/styles/utility/size-insensitive/align-content.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/align-content.css rename to packages/ui-react/src/styles/utility/size-insensitive/align-content.css diff --git a/packages/css/src/styles/utility/size-insensitive/align-items.css b/packages/ui-react/src/styles/utility/size-insensitive/align-items.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/align-items.css rename to packages/ui-react/src/styles/utility/size-insensitive/align-items.css diff --git a/packages/css/src/styles/utility/size-insensitive/align-self.css b/packages/ui-react/src/styles/utility/size-insensitive/align-self.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/align-self.css rename to packages/ui-react/src/styles/utility/size-insensitive/align-self.css diff --git a/packages/css/src/styles/utility/size-insensitive/animation.css b/packages/ui-react/src/styles/utility/size-insensitive/animation.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/animation.css rename to packages/ui-react/src/styles/utility/size-insensitive/animation.css diff --git a/packages/css/src/styles/utility/size-insensitive/box-decoration.css b/packages/ui-react/src/styles/utility/size-insensitive/box-decoration.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/box-decoration.css rename to packages/ui-react/src/styles/utility/size-insensitive/box-decoration.css diff --git a/packages/css/src/styles/utility/size-insensitive/box-inside.css b/packages/ui-react/src/styles/utility/size-insensitive/box-inside.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/box-inside.css rename to packages/ui-react/src/styles/utility/size-insensitive/box-inside.css diff --git a/packages/css/src/styles/utility/size-insensitive/box-sizing.css b/packages/ui-react/src/styles/utility/size-insensitive/box-sizing.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/box-sizing.css rename to packages/ui-react/src/styles/utility/size-insensitive/box-sizing.css diff --git a/packages/css/src/styles/utility/size-insensitive/brand.css b/packages/ui-react/src/styles/utility/size-insensitive/brand.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/brand.css rename to packages/ui-react/src/styles/utility/size-insensitive/brand.css diff --git a/packages/css/src/styles/utility/size-insensitive/break-after.css b/packages/ui-react/src/styles/utility/size-insensitive/break-after.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/break-after.css rename to packages/ui-react/src/styles/utility/size-insensitive/break-after.css diff --git a/packages/css/src/styles/utility/size-insensitive/break-before.css b/packages/ui-react/src/styles/utility/size-insensitive/break-before.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/break-before.css rename to packages/ui-react/src/styles/utility/size-insensitive/break-before.css diff --git a/packages/css/src/styles/utility/size-insensitive/cursor.css b/packages/ui-react/src/styles/utility/size-insensitive/cursor.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/cursor.css rename to packages/ui-react/src/styles/utility/size-insensitive/cursor.css diff --git a/packages/css/src/styles/utility/size-insensitive/display.css b/packages/ui-react/src/styles/utility/size-insensitive/display.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/display.css rename to packages/ui-react/src/styles/utility/size-insensitive/display.css diff --git a/packages/css/src/styles/utility/size-insensitive/drop-shadow.css b/packages/ui-react/src/styles/utility/size-insensitive/drop-shadow.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/drop-shadow.css rename to packages/ui-react/src/styles/utility/size-insensitive/drop-shadow.css diff --git a/packages/css/src/styles/utility/size-insensitive/flex-direction.css b/packages/ui-react/src/styles/utility/size-insensitive/flex-direction.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/flex-direction.css rename to packages/ui-react/src/styles/utility/size-insensitive/flex-direction.css diff --git a/packages/css/src/styles/utility/size-insensitive/flex-wrap.css b/packages/ui-react/src/styles/utility/size-insensitive/flex-wrap.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/flex-wrap.css rename to packages/ui-react/src/styles/utility/size-insensitive/flex-wrap.css diff --git a/packages/css/src/styles/utility/size-insensitive/font-family.css b/packages/ui-react/src/styles/utility/size-insensitive/font-family.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/font-family.css rename to packages/ui-react/src/styles/utility/size-insensitive/font-family.css diff --git a/packages/css/src/styles/utility/size-insensitive/justify-content.css b/packages/ui-react/src/styles/utility/size-insensitive/justify-content.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/justify-content.css rename to packages/ui-react/src/styles/utility/size-insensitive/justify-content.css diff --git a/packages/css/src/styles/utility/size-insensitive/justify-items.css b/packages/ui-react/src/styles/utility/size-insensitive/justify-items.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/justify-items.css rename to packages/ui-react/src/styles/utility/size-insensitive/justify-items.css diff --git a/packages/css/src/styles/utility/size-insensitive/justify-self.css b/packages/ui-react/src/styles/utility/size-insensitive/justify-self.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/justify-self.css rename to packages/ui-react/src/styles/utility/size-insensitive/justify-self.css diff --git a/packages/css/src/styles/utility/size-insensitive/overflow.css b/packages/ui-react/src/styles/utility/size-insensitive/overflow.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/overflow.css rename to packages/ui-react/src/styles/utility/size-insensitive/overflow.css diff --git a/packages/css/src/styles/utility/size-insensitive/overscroll-behavior.css b/packages/ui-react/src/styles/utility/size-insensitive/overscroll-behavior.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/overscroll-behavior.css rename to packages/ui-react/src/styles/utility/size-insensitive/overscroll-behavior.css diff --git a/packages/css/src/styles/utility/size-insensitive/position.css b/packages/ui-react/src/styles/utility/size-insensitive/position.css similarity index 99% rename from packages/css/src/styles/utility/size-insensitive/position.css rename to packages/ui-react/src/styles/utility/size-insensitive/position.css index 786d32e..dae49ec 100644 --- a/packages/css/src/styles/utility/size-insensitive/position.css +++ b/packages/ui-react/src/styles/utility/size-insensitive/position.css @@ -16,4 +16,4 @@ .position--sticky { position: sticky; -} \ No newline at end of file +} diff --git a/packages/css/src/styles/utility/size-insensitive/screen-reader.css b/packages/ui-react/src/styles/utility/size-insensitive/screen-reader.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/screen-reader.css rename to packages/ui-react/src/styles/utility/size-insensitive/screen-reader.css diff --git a/packages/css/src/styles/utility/size-insensitive/theme.css b/packages/ui-react/src/styles/utility/size-insensitive/theme.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/theme.css rename to packages/ui-react/src/styles/utility/size-insensitive/theme.css diff --git a/packages/css/src/styles/utility/size-insensitive/user-select.css b/packages/ui-react/src/styles/utility/size-insensitive/user-select.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/user-select.css rename to packages/ui-react/src/styles/utility/size-insensitive/user-select.css diff --git a/packages/css/src/styles/utility/size-insensitive/variant.css b/packages/ui-react/src/styles/utility/size-insensitive/variant.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/variant.css rename to packages/ui-react/src/styles/utility/size-insensitive/variant.css diff --git a/packages/ui-react/src/styles/utility/size-insensitive/visibility.css b/packages/ui-react/src/styles/utility/size-insensitive/visibility.css new file mode 100644 index 0000000..5beb010 --- /dev/null +++ b/packages/ui-react/src/styles/utility/size-insensitive/visibility.css @@ -0,0 +1,11 @@ +@layer utility { + .visible { + visibility: visible; + } + .visible--hidden { + visibility: hidden; + } + .visible--collapse { + visibility: collapse; + } +} diff --git a/packages/css/src/styles/utility/size-insensitive/z-index.css b/packages/ui-react/src/styles/utility/size-insensitive/z-index.css similarity index 100% rename from packages/css/src/styles/utility/size-insensitive/z-index.css rename to packages/ui-react/src/styles/utility/size-insensitive/z-index.css diff --git a/packages/css/src/styles/utility/size-sensitive/border-radius.css b/packages/ui-react/src/styles/utility/size-sensitive/border-radius.css similarity index 100% rename from packages/css/src/styles/utility/size-sensitive/border-radius.css rename to packages/ui-react/src/styles/utility/size-sensitive/border-radius.css diff --git a/packages/css/src/styles/utility/size-sensitive/font-size.css b/packages/ui-react/src/styles/utility/size-sensitive/font-size.css similarity index 100% rename from packages/css/src/styles/utility/size-sensitive/font-size.css rename to packages/ui-react/src/styles/utility/size-sensitive/font-size.css diff --git a/packages/css/src/styles/utility/size-sensitive/font-weight.css b/packages/ui-react/src/styles/utility/size-sensitive/font-weight.css similarity index 100% rename from packages/css/src/styles/utility/size-sensitive/font-weight.css rename to packages/ui-react/src/styles/utility/size-sensitive/font-weight.css diff --git a/packages/css/src/styles/utility/size-sensitive/gap.css b/packages/ui-react/src/styles/utility/size-sensitive/gap.css similarity index 70% rename from packages/css/src/styles/utility/size-sensitive/gap.css rename to packages/ui-react/src/styles/utility/size-sensitive/gap.css index 0534faa..967acf9 100644 --- a/packages/css/src/styles/utility/size-sensitive/gap.css +++ b/packages/ui-react/src/styles/utility/size-sensitive/gap.css @@ -12,12 +12,12 @@ gap: calc(var(--spacing) * 3); } .gap--lg { - gap: calc(var(--spacing) * 2); + gap: calc(var(--spacing) * 4); } .gap--xl { - gap: calc(var(--spacing) * 2.5); + gap: calc(var(--spacing) * 5); } .gap--2xl { - gap: calc(var(--spacing) * 2.5); + gap: calc(var(--spacing) * 6); } } diff --git a/packages/css/src/styles/utility/size-sensitive/height.css b/packages/ui-react/src/styles/utility/size-sensitive/height.css similarity index 100% rename from packages/css/src/styles/utility/size-sensitive/height.css rename to packages/ui-react/src/styles/utility/size-sensitive/height.css diff --git a/packages/css/src/styles/utility/size-sensitive/margin.css b/packages/ui-react/src/styles/utility/size-sensitive/margin.css similarity index 100% rename from packages/css/src/styles/utility/size-sensitive/margin.css rename to packages/ui-react/src/styles/utility/size-sensitive/margin.css diff --git a/packages/css/src/styles/utility/size-sensitive/padding.css b/packages/ui-react/src/styles/utility/size-sensitive/padding.css similarity index 100% rename from packages/css/src/styles/utility/size-sensitive/padding.css rename to packages/ui-react/src/styles/utility/size-sensitive/padding.css diff --git a/packages/css/src/styles/utility/size-sensitive/width.css b/packages/ui-react/src/styles/utility/size-sensitive/width.css similarity index 93% rename from packages/css/src/styles/utility/size-sensitive/width.css rename to packages/ui-react/src/styles/utility/size-sensitive/width.css index c90e8d3..fff1416 100644 --- a/packages/css/src/styles/utility/size-sensitive/width.css +++ b/packages/ui-react/src/styles/utility/size-sensitive/width.css @@ -11,7 +11,7 @@ .w--item-md { /* 34px most used size */ - width: var(--height-item-lg); + width: var(--height-item-md); } .w--item-lg { @@ -26,7 +26,7 @@ .w--item--2xl { /* 64px navigation bar */ - width: var(--height-item-xl); + width: var(--height-item-2xl); } /* ---------------------------------------------------- */ @@ -53,4 +53,4 @@ .w--inline-xl { width: calc(var(--font-size-2xl) * var(--line-height-2xl)); } -} \ No newline at end of file +} diff --git a/packages/css/src/styles/utils/cpm.ts b/packages/ui-react/src/styles/utils/cpm.ts similarity index 67% rename from packages/css/src/styles/utils/cpm.ts rename to packages/ui-react/src/styles/utils/cpm.ts index c20f0e2..5763db3 100644 --- a/packages/css/src/styles/utils/cpm.ts +++ b/packages/ui-react/src/styles/utils/cpm.ts @@ -2,11 +2,14 @@ export function cpm(...classes: (string[] | string)[]) { const map = new Map(); function dealClass(cls: string) { - // 提取前缀和后缀 - const prifix = cls.split("--")[0]; + const clsArr = cls.trim().split(/\s+/); + // 提取前缀 + clsArr.forEach((i) => { + const prifix = i.trim().split("--")[0]; - // 使用set覆盖(自动新建),而不是push - map.set(prifix, cls); + // 使用set覆盖(自动新建),而不是push + map.set(prifix, i); + }); } classes.forEach((item) => { diff --git a/packages/css/src/styles/utils/cvr.ts b/packages/ui-react/src/styles/utils/cvr.ts similarity index 100% rename from packages/css/src/styles/utils/cvr.ts rename to packages/ui-react/src/styles/utils/cvr.ts diff --git a/packages/ui-react/src/utils/camelToKebab.ts b/packages/ui-react/src/utils/camelToKebab.ts new file mode 100644 index 0000000..6aa90bc --- /dev/null +++ b/packages/ui-react/src/utils/camelToKebab.ts @@ -0,0 +1,3 @@ +export function camelToKebab(str: string) { + return str.replace(/([A-Z])/g, "-$1").toLowerCase(); +} diff --git a/packages/ui-react/src/utils/mergeProps.ts b/packages/ui-react/src/utils/mergeProps.ts index ddecc39..ca9fc3c 100644 --- a/packages/ui-react/src/utils/mergeProps.ts +++ b/packages/ui-react/src/utils/mergeProps.ts @@ -9,28 +9,23 @@ function defaultClassMergeFn(...classes: string[]): string { } // 工具类型 -type UnionToIntersection = - (U extends any ? (k: U) => void : never) extends - (k: infer I) => void ? I : never; +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( + k: infer I, +) => void + ? I + : never; // 泛型入口 -export function mergeProps< - T extends AnyProps[] ->( +export function mergeProps( ...args: [...T] ): UnionToIntersection; -export function mergeProps< - T extends AnyProps[] ->( +export function mergeProps( options: { classMergeFn: (...cls: string[]) => string }, ...args: [...T] ): UnionToIntersection; -export function mergeProps( - arg1: any, - ...rest: any[] -): any { +export function mergeProps(arg1: any, ...rest: any[]): any { let options = { classMergeFn: defaultClassMergeFn, }; @@ -104,4 +99,4 @@ export function mergeProps( }); return result; -} \ No newline at end of file +} diff --git a/packages/ui-react/src/utils/useDefaultedProps.ts b/packages/ui-react/src/utils/useDefaultedProps.ts deleted file mode 100644 index f8bdefa..0000000 --- a/packages/ui-react/src/utils/useDefaultedProps.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { useMemo } from "react"; - -export function useDefaultedProps< - P extends Record, - D extends Partial

, ->(props: P, defaults: D): P & D { - return useMemo(() => { - return { ...defaults, ...props }; - }, [props, defaults]); -} diff --git a/packages/ui-react/src/utils/useSlotRegistry.ts b/packages/ui-react/src/utils/useSlotRegistry.ts deleted file mode 100644 index 93871f7..0000000 --- a/packages/ui-react/src/utils/useSlotRegistry.ts +++ /dev/null @@ -1,8 +0,0 @@ -// useButtonSlots.ts -import { useState } from "react"; - -export function useSlotRegistry() { - const [slots, setSlots] = useState() - - return { slots, setSlots } -} \ No newline at end of file diff --git a/packages/ui-react/src/utils/useSlotsRegistry.ts b/packages/ui-react/src/utils/useSlotsRegistry.ts new file mode 100644 index 0000000..1314483 --- /dev/null +++ b/packages/ui-react/src/utils/useSlotsRegistry.ts @@ -0,0 +1,69 @@ +import { useRef, useState } from "react"; + +export type UseSlotsRegistryReturn = { + slots: Partial>; + canRender: boolean; + generateId: (prefix: string) => string; + registerSlot: ( + id: string, + slotName: Names[number], + content: React.ReactNode, + ) => void; + markReady: (id: string) => void; +}; + +type SlotRecord = { + [K in Names[number]]: React.ReactNode[]; +}; + +export function useSlotsRegistry< + const Names extends readonly string[], +>(): UseSlotsRegistryReturn { + type SlotName = Names[number]; + + const [slots, setSlots] = useState>>({}); + const readySet = useRef(new Set()); + const totalSet = useRef(new Set()); + const [canRender, setCanRender] = useState(false); + const [ids, setIds] = useState([]); + + const generateId = (prefix: string): string => { + while (true) { + const rand = Math.random().toString(36).slice(2, 8); + const id = `${prefix}-${rand}`; + if (!ids.includes(id)) { + setIds((prev) => [...prev, id]); + return id; + } + } + }; + + const registerSlot = ( + id: string, + slotName: SlotName, + content: React.ReactNode, + ) => { + totalSet.current.add(id); + + setSlots((prev) => ({ + ...prev, + [slotName]: [...(prev[slotName] ?? []), content], + })); + }; + + const markReady = (id: string) => { + readySet.current.add(id); + + if (readySet.current.size === totalSet.current.size) { + setCanRender(true); + } + }; + + return { + slots, + canRender, + generateId, + registerSlot, + markReady, + }; +} diff --git a/packages/ui-react/tsconfig.build.json b/packages/ui-react/tsconfig.build.json index e9fcb7d..a5bcc27 100644 --- a/packages/ui-react/tsconfig.build.json +++ b/packages/ui-react/tsconfig.build.json @@ -4,14 +4,12 @@ "noEmit": false, "emitDeclarationOnly": true, "declaration": true, - "declarationDir": "./dist", "rootDir": "./src", - "outDir": "./dist" + "outDir": "./dist", + "declarationDir": "./dist" }, "include": ["src"], "exclude": [ - "src/App.tsx", - "src/main.tsx", "node_modules", "dist", ".turbo/**/*", diff --git a/packages/ui-web-tw/scripts/gen-index.ts b/packages/ui-web-tw/scripts/gen-index.ts deleted file mode 100644 index 234df90..0000000 --- a/packages/ui-web-tw/scripts/gen-index.ts +++ /dev/null @@ -1,147 +0,0 @@ -import fs from "fs"; -import path from "path"; -// 1. 引入 tinyglobby -import { globSync } from "tinyglobby"; - -interface Config { - outputDir: string; - outputFilenameWithExt: string; - scanDirs: string[]; - importPrefix: string; - predefineStatements: string[]; - includeExtensions: string[]; - excludeDirs: string[]; - excludeFileExtensions: string[]; - excludePatterns: RegExp[]; -} - -const cssConfig: Config = { - outputDir: "src", - outputFilenameWithExt: "index.css", - scanDirs: ["src"], - importPrefix: "@import", - predefineStatements: ['@import "tailwindcss";'], - includeExtensions: [".css"], - excludeDirs: ["__tests__", "tests", "story", "stories", "types"], - excludeFileExtensions: [], - excludePatterns: [/^index\.(css)$/, /\.(test|spec)\./, /\.(story|stories)\./], -}; - -const tsConfig: Config = { - outputDir: "src", - outputFilenameWithExt: "index.ts", - scanDirs: ["src"], - importPrefix: "export * from", - predefineStatements: ["import './index.css'"], - includeExtensions: [".ts", "tsx", "js", "jsx"], - excludeDirs: ["__tests__", "tests", "story", "stories", "types"], - excludeFileExtensions: [".d.ts"], - excludePatterns: [ - /^index\.(ts|tsx|js|jsx)$/, - /\.(test|spec)\./, - /\.(story|stories)\./, - ], -}; - -const normalizePath = (p: string) => p.replace(/\\/g, "/"); - -const isExcludeDir = (filePath: string, excludeDirs: string[]) => { - const normalized = normalizePath(filePath); - return excludeDirs.some((dir) => normalized.includes(`/${dir}/`)); -}; - -const isExcludeFileExtensions = ( - filePath: string, - excludeFileExtensions: string[], -) => excludeFileExtensions.some((ext) => filePath.endsWith(ext)); - -const isExcludePattern = (fileName: string, excludePatterns: RegExp[]) => - excludePatterns.some((pattern) => pattern.test(fileName)); - -// ---------------------------------------- -function isValidFile(filePath: string, config: Config): boolean { - const fileName = filePath.split(/[\\/]/).pop()!; - - if (isExcludeDir(filePath, config.excludeDirs)) return false; - if (isExcludeFileExtensions(filePath, config.excludeFileExtensions)) - return false; - if (isExcludePattern(fileName, config.excludePatterns)) return false; - - const ext = path.extname(filePath); - return config.includeExtensions.includes(ext); -} -// ----------------------------------------- -function generateIndexFile(config: Config) { - const currentPath = process.cwd(); - const outputPath = path.resolve(currentPath, config.outputDir); - let exportStatements: string[] = []; - - // ------ scanDirs forEach start ------------------------ - config.scanDirs.forEach((dir) => { - // 2. 路径模式保持不变,tinyglobby 能够正确处理 - const scanPattern = path.resolve(currentPath, dir, "**", "*.*"); - - const allFilePath = globSync(scanPattern, { - absolute: true, - // 3. 移除了 windowsPathsNoEscape,tinyglobby 默认处理路径更智能 - }); - - const validFiles = allFilePath.filter((filePath) => { - return isValidFile(filePath, config); - }); - - if (validFiles.length === 0) { - console.log( - `⚠️ 未找到符合条件的文件,跳过生成 ${config.outputFilenameWithExt}`, - ); - return; - } - - validFiles.sort(); - - validFiles.forEach((file) => { - const relativePath = path.relative(outputPath, file); - const importPath = `./${relativePath.replace(/\\/g, "/")}`; - exportStatements.push(`${config.importPrefix} '${importPath}';`); - }); - }); - - // --------- scanDirs forEach end ---------------- - - const indexFileContent = ` -${config.predefineStatements.join("\n")} -${exportStatements.join("\n")} -`.trim(); - - const indexFilePath = path.resolve( - currentPath, - config.outputDir, - config.outputFilenameWithExt, - ); - - // ✅ 内容比对,避免重复写入 - if (fs.existsSync(indexFilePath)) { - const old = fs.readFileSync(indexFilePath, "utf8"); - if (old === indexFileContent) { - console.log( - `✅ ${config.outputFilenameWithExt} 内容无变化,无需重新生成`, - ); - return; - } - } - - fs.writeFileSync(indexFilePath, indexFileContent, "utf8"); - console.log(`✅ 成功生成 ${config.outputFilenameWithExt}: ${indexFilePath}`); -} - -// -------------------------------------------------- - -try { - console.log(`🚀 [gen-index] 开始扫描`); - generateIndexFile(cssConfig); - generateIndexFile(tsConfig); -} catch (err) { - const msg = err instanceof Error ? err.message : String(err); - console.error(`❌ [gen-index] 执行失败: ${msg}`); - process.exit(1); -} diff --git a/playground/ui-gallery/src/gallery/ButtonGallery.tsx b/playground/ui-gallery/src/gallery/ButtonGallery.tsx index 0f594d6..947936f 100644 --- a/playground/ui-gallery/src/gallery/ButtonGallery.tsx +++ b/playground/ui-gallery/src/gallery/ButtonGallery.tsx @@ -6,58 +6,28 @@ export const ButtonGallery = () => { return ( - XSmall - - - - + + + + + + + + + + ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 235cabe..7fa454f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,45 +12,8 @@ importers: specifier: ^2.8.0 version: 2.9.12 - packages/css: - dependencies: - react: - specifier: ^19 - version: 19.2.6 - react-dom: - specifier: ^19 - version: 19.2.6(react@19.2.6) - devDependencies: - '@types/node': - specifier: ^25.6.0 - version: 25.6.2 - '@types/react': - specifier: ^19.2.14 - version: 19.2.14 - '@types/react-dom': - specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.14) - '@vitejs/plugin-react': - specifier: ^6.0.1 - version: 6.0.1(vite@8.0.12(@types/node@25.6.2)(jiti@2.7.0)) - tinyglobby: - specifier: ^0.2.16 - version: 0.2.16 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@25.6.2)(typescript@6.0.3) - typescript: - specifier: ^6.0.3 - version: 6.0.3 - vite: - specifier: ^8.0.10 - version: 8.0.12(@types/node@25.6.2)(jiti@2.7.0) - packages/ui-react: dependencies: - '@dg/css': - specifier: workspace:* - version: link:../css react: specifier: ^19 version: 19.2.6