# lh-ui-share **Repository Path**: lh-ui/lh-ui-share ## Basic Information - **Project Name**: lh-ui-share - **Description**: LH UI核心包 - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-09 - **Last Updated**: 2026-10-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # @lh-ui/share > lh-ui 家族唯一的**框架无关共享层**:core 纯函数 / theme / constants / locales / types / utils / 组件样式源。 [English](./README.en.md) | 中文 📚 **文档站**: —— 每个纯函数的签名、返回值、边界与示例都可交互试运行(中英双语)。 各框架 UI 层(lh-ui-vue2 / lh-ui-react / lh-ui-uniapp)以 npm 依赖消费本包。**本包不依赖任何 UI 库、任何框架**——`vite` 构建配置 `external: []`,且 `verify:dts` 会扫描产物 `.d.ts`,一旦出现 `vue` / `react` / `@dcloudio/*` 或旧别名导入即失败。 ## 特性 - **框架无关的组件逻辑**:56 个组件的纯函数(`logic.ts` / `types.ts` / `index.ts` 三件套)+ 12 个共享内核(`a11y` / `date` / `delay` / `focus-trap` / `format` / `keyboard` / `popper` / `pt` / `sanitize` / `sx` / `types` / `virtual`)。状态进、类名/样式出,零副作用,可直接单测。 - **计数口径**(`src/core/` 与 `styles/` 目录数不同,以 core 为准):`src/core/config/` 与 `styles/config-provider/` 是同一组件(ConfigProvider,目录名不一致);`styles/` 另有 `layout` / `tree-select` 两个组件目录**暂无 core 纯函数层**(逻辑仍在各 UI 库,未下沉), 故 core 计 56、styles 计 58。 - **样式唯一源**:`styles/` 是全部组件 BEM 样式的唯一来源;过渡类名已**双写**(`-enter` 与 `-enter-from` 并列),同时服务 Vue2 / Vue3 / React。 - **国风主题系统**:SCSS 令牌(`variables.scss`,全部 `!default` 可覆盖)+ 5 个预设主题(青花瓷 / 松花绿 / 朱砂 / 水墨 / 藤黄)+ 暗色模式 + 6 种内置纹理(柳 / 云 / 水 / 雪 / 梅 / 竹)。 - **纯 emitter 国际化**:`LhLocale` 不含任何框架响应式,靠 `version` 自增 + `subscribe` 供各框架自行接线。 - **对消费方友好的产物**:ESM(`es/`)+ CJS(`lib/`)双产物,`preserveModules` 镜像 `src/` 结构,子路径导入天然支持 tree-shaking;dts 由 `tsc` 按同一镜像结构直出。 ## 安装 ```bash pnpm add @lh-ui/share ``` ## 使用 > 优先使用**子路径导入**(分层与 tree-shaking 更清晰);根入口 `@lh-ui/share` 仅作便捷聚合。 ### Core —— 组件纯函数 以 button 为例:把框架侧收集到的状态传进去,拿到 BEM 类名与内联样式。 ```ts import { getClassNames, getSize, isClickable, getStyle } from '@lh-ui/share/core/button' const classes = getClassNames({ type: 'primary', size: getSize(props.size, configProvider.size), // 优先级:props > ConfigProvider > 默认 medium loading: false, disabled: false, plain: false, block: false, round: true, circle: false, }) // => ['lh-button', 'lh-button--primary', 'lh-button--medium', 'lh-button--round', ...] isClickable({ loading, disabled }) // => 可点击与否 getStyle() // => {}(CSS 变量已在 :root 全局定义,无需在按钮上重复设置) ``` 类型从同目录导入:`import type { LhButtonState } from '@lh-ui/share/core/button'`。 ### 共享内核 ```ts // sx:Tailwind 风格的间距简写 → 内联样式(数值间距 ×8px) import { sxToStyle } from '@lh-ui/share/core/shared/sx' sxToStyle({ mt: 2, px: 4, display: 'flex' }) // => { marginTop: '16px', paddingLeft: '32px', paddingRight: '32px', display: 'flex' } // pt:内部元素的透传属性合并(class 支持 字符串/数组/对象 三种形式) import { mergePt } from '@lh-ui/share/core/shared/pt' mergePt({ class: 'extra', style: { color: 'red' } }, 'lh-button__text') // popper:定位引擎,入参全部是 rect 字面量、不触碰 DOM,可直接单测 import { computePosition } from '@lh-ui/share/core/shared/popper' computePosition(triggerRect, popperRect, viewportRect, { placement: 'bottom-start', gap: 8, flip: true, shift: true }) // => { top, left, placement, arrowOffset };支持 12 方位、主轴翻转、交叉轴吸附 // focus-trap:Dialog / Drawer 等浮层的焦点管理 import { focusFirst, trapTabKey, setInertOutside } from '@lh-ui/share/core/shared/focus-trap' ``` ### Theme —— 主题 TS 侧提供 5 个预设(主色重染): ```ts import { LH_THEME_PRESETS, getThemeVars, getThemePreset } from '@lh-ui/share/theme' LH_THEME_PRESETS // [{ name: 'cerblue', label: '青花瓷', labelEn: 'Ceramic Blue', ... }, ...] getThemeVars('zhusha') // => { '--lh-primary-color': '#B23A3A', ... } ``` | 预设 | 中文名 | 主色 | | --- | --- | --- | | `cerblue` | 青花瓷 | `#2B4C7C` | | `songhua` | 松花绿 | `#5B8C5A` | | `zhusha` | 朱砂 | `#B23A3A` | | `shuimo` | 水墨 | `#2C2C2C` | | `golden` | 藤黄 | `#B8860B` | CSS 侧引入令牌(`styles/theme/` 是 SCSS 源,`dist/theme/` 是构建产物): ```ts // 全量令牌(明色 + 暗色 + 纹理,一个文件) import '@lh-ui/share/theme.css' // 仅暗色(可独立编译,按需引入) import '@lh-ui/share/theme-dark.css' // 全量样式(主题 + 全部组件) import '@lh-ui/share/styles.css' ``` 暗色模式由选择器开关,二选一即可: ```html
``` 纹理(国风底纹):先引入 `theme.css`,再指定纹理变量—— ```css :root { --lh-bg-pattern: var(--lh-pattern-willow); /* 柳 / 云 cloud / 水 water / 雪 snow / 梅 plum / 竹 bamboo */ } ``` 也可以在 ConfigProvider 的 `themeVars` 里传入 `bg-pattern`。若自行 `@use` SCSS 源,所有令牌都是 `!default`,可用 `@use '...' with ($lh-primary: ...)` 覆盖。 ### Locales —— 国际化 ```ts import { lhlocale, zhCN, enUS } from '@lh-ui/share/locales' lhlocale.use({ locale: 'en-US', messages: enUS }) // 切换并注册语言包 lhlocale.t('input.placeholder') // => 'Please input' lhlocale.setLocale('zh-CN') // 切回(语言包已注册时直接生效) lhlocale.add('xx-XX', customMessages) // 只注册、不切换 ``` 框架接线:`LhLocale` 是纯 emitter,靠版本号驱动更新。 ```ts // Vue2 / Vue3 const version = ref(lhlocale.version) const unsubscribe = lhlocale.subscribe((v) => (version.value = v)) onUnmounted(unsubscribe) // React useSyncExternalStore(lhlocale.subscribe, () => lhlocale.version) ``` > **注意**:`t()` 按点路径取字符串,第二参数传**对象**时按 `{name}` 占位符插值(如 `t('pagination.total', { total: 100 })` → `共 100 条`),未知占位符原样保留;传**字符串**时作为 `fallback`(取不到翻译时返回它,未传则返回路径本身)。当前完整语言包为 `zh-CN` / `en-US`,ja-JP / ko-KR / de-DE / fr-FR 为英文兜底骨架。 ### Utils —— 工具 ```ts import { createNamespace, cssVars, toCssVarName, stripCssVarName } from '@lh-ui/share/utils' const ns = createNamespace('button') ns.b() // 'lh-button' ns.e('text') // 'lh-button__text' ns.m('primary') // 'lh-button--primary' ns.em('text', 'disabled') // 'lh-button__text--disabled' ns.is('loading', true) // 'is-loading'(false/undefined 返回空串) cssVars({ 'primary-color': '#2B4C7C' }) // => { '--lh-primary-color': '#2B4C7C' } toCssVarName('primary-color') // => '--lh-primary-color'(幂等,已带前缀则原样返回) stripCssVarName('--lh-primary-color') // => 'primary-color' ``` 另有 `debounce` / `throttle` / `deepMerge` / `generateId` / `isEmpty` / `getScrollbarWidth` 等纯工具(`generateId` 等带 DOM 访问的需浏览器环境)。 ### Constants —— 常量 ```ts import { LH_TYPES_CONST, LH_SIZE_CONST, LH_SIZE_DEFAULT, LH_LANGUAGE_CONST, LH_LANGUAGE_DEFAULT } from '@lh-ui/share/constants' LH_TYPES_CONST // { success, warning, error, info, danger } LH_SIZE_CONST // { small, medium, large, mini, old: 'x-large' }(old 为老年模式专用档) LH_LANGUAGE_CONST // { zhCN: 'zh-CN', enUS: 'en-US' } ``` ### Styles —— 组件样式 ```ts // 单组件样式(原始 SCSS 源码,消费方需具备 SCSS 编译管道) import '@lh-ui/share/styles/button' import '@lh-ui/share/styles/dialog' // 单组件编译产物(无 SCSS 管道时按组件引入,避免加载全量包) import '@lh-ui/share/dist/button/style.css' import '@lh-ui/share/dist/dialog/style.css' // 或一次引入全量编译产物 import '@lh-ui/share/styles.css' ``` 类名遵循 BEM `lh-*`,颜色一律使用 `var(--lh-*, )` 形式,不引入硬编码色值。 ## 子路径导出 | 子路径 | 内容 | | --- | --- | | `.` | 根聚合入口(全部子层) | | `./core` / `./core/*` | 组件纯函数;`./core/button` 等按目录匹配 | | `./core/<组件>/*` | 组件内深文件(`./core/tooltip/logic`、`./core/date-picker/adapter` 等),由 `pnpm sync:exports` 按 `es/` 产物自动生成 | | `./constants` | 常量 | | `./locales` / `./locales/lang/*` | 国际化(`lhLocale` + 语言包 + 类型);按语言深引入 `./locales/lang/zh-CN` | | `./theme` | 主题预设与类型 | | `./types` | 仅类型(无运行时产物) | | `./utils` / `./utils/*` | 工具函数;深文件 `./utils/css-var`、`./utils/namespace` | | `./theme.css` | `dist/theme/index.css`(明色 + 暗色 + 纹理) | | `./theme-dark.css` | `dist/theme/index-dark.css`(仅暗色) | | `./styles/*` | `styles/*/index.scss`(**原始 SCSS 源码**) | | `./styles.css` | `dist/styles/index.css`(主题 + 全部组件,编译产物) | | `./dist/*` | `dist/<组件>/style.css`(**单组件编译产物**,无 SCSS 管道时按需引入) | ## 目录结构 ``` src/core// 组件纯函数三件套:logic.ts / types.ts / index.ts src/core/shared/ 共享内核:sx / pt / popper / focus-trap / types src/theme/ 主题 TS 侧(类型 + 5 个预设) src/constants/ 常量 src/locales/ 语言包(LhLocale 为纯 emitter) src/types/ src/utils/ 类型 / 纯工具 styles/ 组件 BEM 样式唯一源:/index.scss + theme/common/*.scss(令牌) tests/unit/ core 单测唯一一份(三库共享,不重复拷贝) scripts/ build-styles / normalize-styles / sync-exports / verify-dts / verify-styles / extract-from-plus ``` ## 命令 | 任务 | 命令 | | --- | --- | | 构建(es/lib,preserveModules 镜像结构) | `pnpm build` | | 样式产物(dist/theme + dist/styles) | `pnpm build:styles` | | dts(tsc 镜像直出) | `pnpm build:dts` | | dts 校验(镜像完整性 + 禁止框架导入) | `pnpm verify:dts` | | 单测 | `pnpm test` | | Lint / 类型 | `pnpm lint` / `pnpm typecheck` | | 文档站构建(Astro Starlight,中英双语) | `pnpm docs:build` | CI 按 `lint → typecheck → test → build → build:styles → build:dts → verify:dts → verify:styles → docs:build` 顺序执行。测试、构建等验证由**用户手动运行**,交付后仅列出命令清单。 ## 边界与贡献 - `src/` 内禁止 `import 'vue' | 'react' | '@dcloudio/*'` 及任何框架 API;响应式接线属于各 UI 层。 - `styles/` 是组件样式唯一源:禁止把样式拷贝到 UI 库手改;一切样式改动只在本仓库发生。 - core 单测唯一一份在本仓库,UI 库不得复制。 - 版本发布顺序:**share 先发版,UI 库随其后**——share 改动 → changeset → 发版 → 各库 `pnpm up @lh-ui/share` 回归。