Skip to content

release: 合并 2.x,发布 v2.0.0(1.2.2 → 2.0.0 大版本) - #16

Merged
vaebe merged 279 commits into
mainfrom
2.x
Jun 3, 2026
Merged

release: 合并 2.x,发布 v2.0.0(1.2.2 → 2.0.0 大版本)#16
vaebe merged 279 commits into
mainfrom
2.x

Conversation

@vaebe

@vaebe vaebe commented Jun 2, 2026

Copy link
Copy Markdown
Owner

概述

ccui 2.0 正式版。将 2.x 合并入 main,对应已发布到 npm latestv2.0.0

相对 main(1.2.2):275 commits / 649 files / +90619 −9905,含 108 feat、26 fix、19 refactor、66 docs。三个公开包(@vaebe/ccui / @vaebe/ccui-icons / @vaebe/unplugin-vue-components-ccui)版本对齐 2.0.0

亮点

工程 / 发包

  • 🔧 重做发包链路:按需引入 + tree-shake + 真实 .d.ts 一次到位(@vaebe/unplugin-vue-components-ccui resolver)
  • 🎨 @vaebe/ccui-icons 内置 mdi collection,组件图标默认离线可用(无网 / 内网环境不空白)

组件能力

  • 组件覆盖扩充至 82 个,按 Ant Design 对标但全量 Vue 化(render props → 作用域插槽,静态命名空间 → 平铺顶层组件)
  • 录入组件统一 variant 形态(12 组件)、classNames / styles 语义化 DOM 钩子(24 组件)、自定义图标钩子(8 组件)、status 与 Form item 双向联动
  • 命令式 API:useModal / useMessage / useNotification composables;message / notification 增强(duration 秒制、多 placement、maxCount、stack、pauseOnHover)
  • 新增组件(节选):BorderBeam、SpaceCompact、ErrorBoundary、StatisticTimer、DirectoryTree、DropdownButton、Skeleton 5 形态、Table Column/ColumnGroup/Summary、CardMeta/CardGrid、ListItemMeta、FormErrorList、TimeRangePicker 等
  • i18n 二期:dayjs locale 接入 + ja-JP / ko-KR 覆盖
  • ConfigProvider theme.algorithm(default/dark/compact)与 locale 全部接通,不留死接口

文档

  • VitePress 文档站重做侧边栏分类(7 组),简介 / 快速开始拆页,全量组件 demo + props + events

⚠️ 破坏性变更(1.x → 2.0)

  • feat(pkg)! 发包链路重做:导入路径 / 产物结构变化,按需引入改用新 resolver
  • feat(tree)! Tree 推翻重写,按 80% 目标重新设计协议(prop / slot 不向后兼容 1.x)

迁移

提供 v1 → v2 自动迁移 codemod,覆盖 26 项命名变更(详见 packages/cli 迁移脚本与文档站迁移说明)。

发布状态

  • v2.0.0 已发布到 npm(dist-tag latest),tag v2.0.0 已推送
  • ✅ 测试基线:@vaebe/ccui 93 文件 / 2023 用例全绿
  • ✅ 体积基线见 docs-notes/bundle-size-baseline.md(2026-06-02 快照)

🤖 Generated with Claude Code

claude code 含量90%

zcj and others added 30 commits May 8, 2026 12:45
- loading 状态:开启后图标内容被 spinner SVG 替换,自动开 spin 动画并挂
  aria-busy="true",常用于异步操作中按钮的图标占位
- disabled 状态:仅对 clickable=true 生效,自动阻止 click 和键盘激活,
  挂 aria-disabled="true" + tabindex="-1",外观降透明 + cursor: not-allowed
- themePrefixMap:按 theme 自动映射 Iconify 前缀
  (比如 outlined 走 material-symbols、filled 走 mdi),优先级 name 含 ':' >
  themePrefixMap 命中 > iconifyPrefix
- 文档:新增加载状态、禁用状态、主题→Iconify 前缀映射 共 3 个章节,
  Props 表加 loading / disabled / themePrefixMap 三个新字段
- 测试:从 26 个扩展到 33 个,新增 loading 替换内容+spin+aria-busy、disabled
  阻止 click 和键盘、disabled 不挂在非 clickable、themePrefixMap 命中前缀、
  themePrefixMap 命中失败回退 iconifyPrefix、含冒号忽略两个映射、loading +
  spinDirection=ccw
- 状态:components-diff.md / sidebar.ts / icon/index.ts 全部 95% -> 100% / 已完成

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… tagsDraggable)

- optionLabelProp:已选展示用独立字段,下拉项仍按 label 渲染。字段缺失
  回退到 label。多选 / tags 模式 tag 文本也走该字段
- showSearch:filterable 别名,与社区 API 对齐;与 filterOption=false
  组合可作为远程搜索语义糖
- transitionName:浮层用 Vue <Transition> 包裹,默认 ccui-select-fade
  (淡入 + 4px 上滑),可换任意 transition 名搭配自定义 CSS;appear:true
  让初次打开也走 enter 动画,配合 Teleport 时仍能正确触发
- tagsDraggable:多选 / tags 模式下用户可拖拽 tag 调整顺序,被拖中 tag
  降透明,drop 目标高亮边框,松开后 update:modelValue 直接给出新顺序;
  use-select 内新增 reorderTagValue helper
- 文档:新增 optionLabelProp、showSearch 别名、自定义浮层动画、拖拽排序
  已选 tag 共 4 个章节,Props 表加 4 个新字段
- 测试:从 49 个扩展到 59 个,新增 optionLabelProp 单选展示、字段缺失回退、
  多选 tag 显示、showSearch 启用搜索框、showSearch+filterOption=false
  不过滤、transitionName 不破坏 dropdown、tagsDraggable 挂 draggable+grab
  类、拖拽 reorder modelValue、同 tag drop noop、tagsDraggable=false 不挂
  draggable
- 状态:components-diff.md / sidebar.ts / select/index.ts 全部 95% -> 100% / 已完成

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 键盘导航:↑/↓ 上下移动焦点;→ 展开节点或进入第一个子节点;← 折叠或回到
  父节点;Home/End 跳首末可见节点;Enter / Space 触发选中(或勾选,当
  checkable=true)
- roving tabindex:聚焦节点 tabindex=0,其它 -1;未聚焦时根容器可 Tab 进入
- focusedKey 受控:支持 v-model:focused-key,新增 update:focusedKey 和
  focus-change 事件;prop 受控时内部 ref 不写
- 虚拟滚动:virtualScroll 启用后只渲染可视区 + 缓冲,每项 absolute 摆放;
  新增 virtualItemHeight / virtualMaxHeight props
- autoScroll:聚焦变化后自动滚到可见区——虚拟模式用 virtual.scrollToIndex,
  非虚拟用 el.focus({ preventScroll: false }),对 jsdom 没有 CSS.escape 兜底
- 抽公共 hook:把 use-virtual-list 从 select 移到 shared/hooks,
  Select / Tree 共用,后续 TreeSelect / Cascader 也能复用
- 文档:新增键盘导航、虚拟滚动 2 章节;Props 表加 4 个新字段,事件表加
  update:focused-key 和 focus-change
- 测试:从 31 个扩展到 43 个,新增 ↑/↓ 移焦点、→ 展开/移子节点、← 折叠/
  移父节点、Enter 选中、Space + checkable 勾选、Home/End 跳首末、roving
  tabindex、虚拟滚动只渲染可视区、disabled 阻止键盘、focusedKey 受控行为
- 状态:components-diff.md / sidebar.ts / tree/index.ts 全部 80% -> 95%

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ta 错误重试)

- showLine:每个节点按祖先深度自动渲染垂直连接线(绝对定位 __guide
  span),新增 connector 插槽允许消费者替换每根 guide 内容
- 拖拽 hover 自动展开:dragover 在 inside 区超过 dragHoverExpandDelay
  (默认 600ms)后自动 triggerExpand;drop / dragend / 离开 inside 都
  会清掉计时器;视觉上挂 --hover-expand 类
- 拖拽 auto-scroll:dragAutoScroll 启用时(默认 true),dragover 接近
  滚动容器顶/底 dragAutoScrollEdge(默认 32px)以内时按
  dragAutoScrollSpeed(默认 12px/帧)滚动;用 requestAnimationFrame
  持续推进,drop / dragend / 离边缘自动停
- loadData 错误状态 + retryLoad:runLoadData 抽出 try/catch,失败的
  节点进 loadErrorKeys 集合并 emit load-error;switcher 渲染为红色
  感叹号按钮,点击 retry。expose({ retryLoad, isNodeLoading,
  hasLoadError }) 让父组件编程式重试
- switcher slot 扩展:除 expanded / node 外新增 loading / loadFailed,
  让自定义 switcher 也能展示加载和错误态
- computePosition 对 jsdom 的 0 高度 rect 兜底为 'inside',避免 NaN
  比较推到 'after' 导致测试假阴性
- onUnmounted 清理 hover 计时器和 auto-scroll RAF
- 文档:新增 showLine、拖拽 hover 自动展开、拖拽 auto-scroll、loadData
  错误重试 共 4 章节;Props 加 4 个新字段、事件加 load-error、插槽加
  connector、新增"组件方法"小节列出 expose 的 3 个 API
- 测试:从 43 个扩展到 50 个,新增 showLine 渲染 N 个 guide、connector
  slot 自定义、drag hover-expand 在 delay 后展开、drop / dragend 取消
  hover 计时、loadData 失败 emit load-error 和错误 switcher、点击错误
  switcher 触发 retry、expose retryLoad / isNodeLoading / hasLoadError
- 状态:components-diff.md / sidebar.ts / tree/index.ts 全部 95% -> 100% / 已完成

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 通用 / 导航 / 反馈 / 数据录入 / 数据展示 / 布局 / 其他 共 60 个组件
  全部列出,旧版只列了 ~30 个
- Form (80%) 和 Table (85%) 标注剩余项
- Icon / Select / Tree 三个最近推到 100% 的标注关键能力
- 新增"还没交付的常见组件"表,列 P1-P3 路线图组件
- 在介绍段链到 docs-notes/components-diff/references/components-diff.md
  作为详细的覆盖度记录

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Form.List:默认作用域插槽 (fields, { add, remove, move }),按 name path 自动拼接父级前缀,稳定 key 在 move 后不丢;支持 initialValue 与受控/非受控数组。
- Form.Provider:forms 注册表 + form-change / form-finish 聚合;getFieldsValue 暴露在 FormInstance 上。
- preserve:form-level 默认 true,item-level preserve 优先;卸载时按策略 deleteValueByPath 清理。
- FormItem 增加 formList prefix 注入与 onChangeCapture -> notifyFieldChange,驱动 Provider 联动。
- 文档增 Form.List / Provider / preserve 三段示例与参数表,sidebar 标 95%。
- vue-ccui.ts 增 FormList / FormProvider 运行时导出。
- 测试 32 -> 44(+12):动态字段、prefix 拼接、move/remove/批量删除、preserve 三档、Provider finish/change/forms 注册表。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- column.fixed='left'|'right':按列宽累加偏移生成 sticky left/right;selection 列与 expand 列在存在左固定列或显式 fixed 时自动跟随;新增 has-fixed-left / has-fixed-right 阴影修饰类。
- expandable.expandedRowRender:受控 expandedRowKeys(v-model:expandedRowKeys + onChange)、defaultExpandedRowKeys、defaultExpandAllRows、rowExpandable、expandRowByClick、columnWidth/fixed;额外发出 expand 事件 (expanded, record)。
- column.onCell / column.onHeaderCell:返回 { rowSpan, colSpan, style, class };rowSpan === 0 / colSpan === 0 时跳过被吞并单元格不渲染。
- scroll: { x, y } 控制容器溢出和最小宽度,与固定列联动。
- 文档增固定列、展开行、合并单元格三段示例与完整参数/事件表,sidebar 标 95%。
- 测试 52 -> 64(+12):列重排顺序、左右偏移累加、selection 跟随、展开行受控/默认全展开/rowExpandable/expandRowByClick、onCell rowSpan/colSpan=0、onHeaderCell colSpan。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- README 把 Form / Table 的备注从 "80%/85% 待补" 改为已交付能力清单。
- components-diff 头部 timestamp 增加本批次摘要(Form 44 用例 +12、Table 64 用例 +12),表格行从 80% / 85% 改为已完成,并在备注中列出 Form.List / Form.Provider / preserve、固定列 / 展开行 / onCell+onHeaderCell 的具体口径。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- packages/docs/index.md:首页 hero 四张特性卡换成「Vite 8 + Rolldown / 60 个组件 / TS + 800+ 单测 / SeedToken+MapToken」实际能力描述。
- components-diff.md:补 Batch 18(Form 44 用例 / Form.List + Provider + preserve)与 Batch 19(Table 64 用例 / 固定列 + 展开行 + 合并单元格)两段批次说明,把「P0:补齐核心复杂组件」标题改成「P0:核心复杂组件(已收口)」并列出每个组件的批次锚点,剩余低频项收进 P0 长尾,不再阻塞 P1。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vp check --fix 把上一轮 Form / Table 95% 文档遗漏的格式补齐:TS 内联对象类型分隔符 `,` 改成 prettier 偏好的 `;`、Markdown 表格列宽重新对齐。仅格式调整,无内容变更。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Affix 此前 \`category: '其他'\` 不在 \`packages/cli/shared/constant.js\` 的 \`VITEPRESS_SIDEBAR_CATEGORY\`(通用 / 导航 / 反馈 / 数据录入 / 数据展示 / 布局)里。\`packages/cli/templates/vitepress-sidebar.js\` 走 \`categoryMap.has(info.category)\` 判断,命中不到只打一个 warning 就把组件跳过,导致 vitepress sidebar 一直没有 Affix 入口。

- \`packages/ccui/ui/affix/index.ts\`:修源头 category。
- \`packages/docs/.vitepress/config/sidebar.ts\`:在 导航 分类首项加 Affix 入口,保持手写风格(2 空格 / 单引号 / 无分号 / 尾随逗号),不让生成器机器排版覆盖。
- \`README.md\`:把 Affix 移到 \`### 导航\` 段,删除只剩 Affix 一个组件的 \`### 其他\` 段。
- \`docs-notes/components-diff/references/components-diff.md\`:表格 Affix / ConfigProvider / Util 三行从「其他」改成实际分类(导航 / 通用 / 通用),与代码 \`index.ts\` 一致;同时被 prettier 重新对齐了状态列列宽。

验证:从 \`packages/docs\` 跑 \`node ../cli/index.js create -t ccui --ignore-parse-error\` 不再有 \`组件 Affix 的分类 其他 不存在\` warning;从 \`packages/ccui\` 跑 \`pnpm test ui/affix --run\` 10 个用例通过。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第一项落地。新增 packages/ccui/ui/shared/utils/date.ts 作为后续 TimePicker / Range / Cascader 的共享底座,避免每个日期组件各自散用 dayjs:

- toDayjs(value, format?):把 string / number / Date / Dayjs / null 统一成 Dayjs,按 format 严格解析(dayjs/plugin/customParseFormat),失败返回 null。
- emitValue(dayjs, 'string' | 'date' | 'number', format):把内部 Dayjs 输出为外部 v-model 期望形态,避免把 dayjs 类型暴露给业务层。
- generateMonthGrid(viewMonth, weekStart):6×7 = 42 格 cell { date, day, isCurrentMonth, isToday },weekStart 0 周日开头、1 周一开头。
- isSameDay / isSameMonth / isToday 比较谓词。

DatePicker 80% 范围(packages/ccui/ui/date-picker/):

- v-model 受控/非受控 + valueFormat 三档:默认 'string' 按 format 输出;'date' 输出原生 Date;'number' 输出毫秒时间戳。
- format(默认 YYYY-MM-DD,dayjs token)/ placeholder / disabled / clearable(默认 true)/ size 三档 / status / autoFocus / inputReadOnly / popupClassName / transitionName / weekStart。
- disabledDate(current: Dayjs) => boolean 屏蔽不可选日期,禁用 cell 加 --disabled modifier 并不响应 click。
- placement 4 个方位(bottomLeft / bottomRight / topLeft / topRight,对齐 Ant Design 命名),内部常量表 PLACEMENT_TO_FLOATING 映射到 floating-ui 的 bottom-start / top-end,便于以后切定位库。
- popupAppendToBody / 自定义 getPopupContainer,复用 Select 同款 Teleport + Transition 模式 + @floating-ui/vue 的 flip + shift({ padding: 8 }) + offset(4)。
- Form 联动:通过 formItemInjectionKey inject validateStatus 合到 mergedStatus,FormItem 校验失败 root 自动加 --status-error;emitChange 同步触发 formItem.validate('change')。
- 同一天再点不重发 change(仅关闭面板,避免重复校验回路);打开时把 viewMonth 重置到选中月。

测试 40 用例(packages/ccui/ui/date-picker/test/date-picker.test.ts)覆盖:基础渲染、popup open/close、selection 三种 valueFormat、disabledDate、clearable 5 种组合、月/年 4 个箭头、grid 结构 + today 唯一 + 周日/周一两套周标签 + outside 月格子、size + status modifier、Form integration(findComponent.vm.$.exposed)、Teleport 两种容器。

文档(packages/docs/components/date-picker/index.md):基础 / 显示已选值 / 自定义格式(含 valueFormat 三档 demo)/ 禁用日期 / 三种尺寸 / 禁用与不可清除 / 表单联动 / 弹层容器;API Props 表 18 行 + Events 表 5 行 + 已知限制清单。

未交付(计入 P0 / P1 长尾):range 区间、week / month / year / quarter mode、showTime + TimePicker、presets / renderExtraFooter / showToday、locale 切换、键盘导航。

收口:

- packages/ccui/ui/vue-ccui.ts:DatePickerInstall + DatePicker 三处插入,按字母序对齐 ConfigProvider / Descriptions 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(CheckBox 与 Form 之间)。
- README:### 数据录入 加 DatePicker 条目,组件计数 60 → 61,「还没交付的常见组件」表把 DatePicker / TimePicker 改成单条 TimePicker。
- components-diff.md:表格 +1 行 (DatePicker 数据录入 80%),组件计数 60 → 61,缺失清单复杂组件改 9 项 → 8 项剩余 + 1 项进行中,新增 Batch 20 写明能力 / 工程决策 / 验证结果,时间戳更新到 2026-05-09。

验证:

- vp check 通过(467 文件 prettier、294 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/date-picker --run 通过 40/40。
- 从 packages/docs 跑 node ../cli/index.js 没有 分类不存在 warning,DatePicker 出现在 sidebar 数据录入分类 status=80%。
- 仓库内 pnpm test --run 全量 879/881 通过;2 个失败(statistic countdown 11ms 时钟精度、float-button backTop window mock)在本提交前就已存在,单独跑 ui/statistic / ui/float-button 复现,与本次改动无关。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第二项落地。复用 DatePicker 同款 dayjs 工具层(toDayjs / emitValue),扩展 packages/ccui/ui/shared/utils/date.ts 加一个通用列构造函数:

- buildTimeColumnValues(range, step, disabledValues?):输出 { value, disabled }[],TimePicker 三列(hour 0-23 / minute 0-59 / second 0-59)和未来 DatePicker showTime 都共用。step <= 0 兜底成 1,disabledValues 用 Set 标记。

TimePicker 80% 范围(packages/ccui/ui/time-picker/):

- v-model 受控/非受控 + valueFormat 三档('string' / 'date' / 'number',与 DatePicker 同款 emitValue 协议)。
- format 默认 HH:mm:ss(dayjs token)/ placeholder / disabled / clearable / size 三档 / status / placement 4 个方位(映射到 floating-ui) / popupAppendToBody / 自定义 getPopupContainer / autoFocus / inputReadOnly / popupClassName / transitionName。
- 三列控制:showHour / showMinute / showSecond 任意组合(关到只剩 1 列也能用);hourStep / minuteStep / secondStep 控制每列步长;disabledHours / disabledMinutes(hour) / disabledSeconds(hour, minute) 三层联动屏蔽。
- footer 双按钮 + showOk 行为分流:showOk=true(默认)点击单元格只更 pending、不 emit、面板不关,等点确定才提交并关;showOk=false 点击单元格立即 emit + 关。showNow 控制「此刻」按钮,showOk=false 模式下「此刻」也立即 emit + 关;两按钮都关时 footer 整段不渲染。
- pending 状态机:内部 shallowRef pendingDayjs,watch(selectedDayjs) 同步外部受控值变化,openPopup 时把 pending 重置到当前 selected(外部无值时回 dayjs().startOf('day')),避免上次面板状态泄漏。
- Form 联动:与 DatePicker 同套机制——formItemInjectionKey inject validateStatus,校验失败 root 加 --status-error;emitChange 同步触发 formItem.validate('change')。

测试 45 用例(packages/ccui/ui/time-picker/test/time-picker.test.ts)覆盖:基础渲染(默认/自定义 placeholder、3 类 modelValue + format + 无效值);popup open/close(click 切换 / outside / disabled / autoFocus);columns(默认 3 列、3 种 show-X 关闭、24 cells 全集、3 种 step 验证 cells 数 + 文本、selected modifier 三列定位);disabled values(disabledHours 命中、disabledMinutes 联动、disabled cell click 不变 pending);selection showOk=false 急切 emit 三档 valueFormat;footer showOk=true(hour click 只更 pending、ok 提交、now 设 pending 不关、now+ok 提交、showOk=false 时 now 立即 emit、both off 不渲染、自定义文案);clearable 4 种组合 + size 三档 + status;Form integration + Teleport 两种容器 + 外部 v-model 回写。

文档(packages/docs/components/time-picker/index.md):基础(默认 showOk)/ 选中即提交(showOk=false)/ 自定义格式(含 valueFormat 三档 demo)/ 步长 / 屏蔽时间(含 hour-minute 联动)/ 隐藏某列 / 三种尺寸 / 表单联动 / 弹层容器;API Props 表 27 行 + Events 表 5 行 + 已知限制清单(12 小时制 / 键盘 / 范围 / showTime / 滚轮 snap)。

未交付(计入 P1 / 后续批次):12 小时制 use12Hours、键盘导航、range 区间、showTime 嵌入 DatePicker、滚轮 snap。

收口:

- packages/ccui/ui/vue-ccui.ts:TimePickerInstall + TimePicker 三处插入,按字母序对齐 Tag / Timeline 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(Switch 之后)。
- README:### 数据录入 加 TimePicker 条目,组件计数 61 → 62,「还没交付的常见组件」表删掉 TimePicker 行。
- components-diff.md:表格 +1 行 (TimePicker 数据录入 80%),组件计数 61 → 62,缺失清单复杂组件改 8 项剩余 → 7 项剩余 + 2 项推进中(DatePicker / TimePicker),新增 Batch 21 写明能力 / 工程决策 / 验证。

工程决策:

- 复用 DatePicker 的内部抽象但不抽 use-popup hook:DatePicker / TimePicker 的 popup 渲染内容差别足够大(grid vs columns),抽象 hook 会要传入太多 render slot,损可读性。先保持两份相似代码,等推第三个浮层组件(Cascader / TreeSelect)再回头抽。
- showOk=true 是默认:与 Ant Design TimePicker 默认行为一致——避免每次微调都 emit 触发外部 reactive / Form rules。showOk=false 留给「快速选时间」场景。
- buildTimeColumnValues 输出 cell list 而不是 disabled 函数:数据规模小(最多 60 cell),用 Set 一次性求值后直接当 cell.disabled 用,computed 缓存命中也轻松。
- 不引入 dayjs 默认插件外的额外插件:date.ts 已经 extend customParseFormat,TimePicker 用的 hour() / minute() / second() / .hour(x) 都是核心 API,与上一批次工具层口径一致。

验证:

- vp check 通过(473 文件 prettier、298 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/time-picker --run 通过 45/45。
- 生成器 (node ../cli/index.js create -t ccui --ignore-parse-error) 无 warning,TimePicker 出现在数据录入分类。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第三项落地。独立组件 packages/ccui/ui/range-picker/,复用 DatePicker 同款 dayjs 工具层(toDayjs / emitValue / generateMonthGrid / isSameDay)与 @floating-ui/vue popup 模式,零新增工具层。

设计:独立 c-range-picker 而非在 DatePicker 上加 mode='range'。现有 DatePicker 80% props 已不少,叠 range mode 会让 modelValue 类型分裂、disabledDate 签名分裂、hover 状态新增成 props,损耗 single 单选用户的可读性与测试隔离。Ant Design 也是分两个组件。

协议:

- v-model 是 [start, end] 数组,与 DatePicker 同款 valueFormat 三档:'string' → [string, string],'date' → [Date, Date],'number' → [ms, ms],全空时 v-model = null。
- change(value, [startStr, endStr]) 同时 emit 数组值与格式化字符串对。
- disabledDate(current: Dayjs) => boolean 一份共用,对 start/end 都生效(独立 disabledDate 留下一切片)。

双面板:

- 左 viewMonth,右 viewMonth + 1。一个 viewMonth 控制左面板,右面板永远 +1 跟随,避免左右独立 viewMonth 的同步成本。
- 左 panel header 只有 ‹ 上月 / « 上年;右 panel header 只有 下月 › / 下年 »。中间 label 不可点。

状态机 phase: 'start' | 'end':

- 打开面板时 phase=start;click end input 直接 phase=end。
- 第一次点击设 pendingStart、phase 切到 end、pendingEnd 重置为 null,不 emit、面板不关。
- 第二次点击若 cell.isBefore(pendingStart) 则 [s,e] = [e,s] 自动调换;emit + close。两次提交都满足 start <= end。
- 输出永远满足 start <= end。

hover in-range 预览:

- phase=end 且 pendingStart 已选时,cell mouseenter 把 hoverDate 设为该 cell;isCellInHoverRange 计算 min(start, hover) 与 max(start, hover) 之间(不含两端)的 cell 加 --in-hover-range 给用户「此刻提交将选这一段」的视觉反馈。
- mouseleave 不立即清空(避免 1px 间隙抖动),下次 mouseenter 覆盖;closePopup / phase 切换时统一清。

已确认 in-range:

- pendingStart && pendingEnd 都有时,两端之间的 cell 加 --in-range;两端本身加 --range-start / --range-end 与 --in-range 浅蓝背景配合画出连续段。

input 显示分流:

- 打开期间 startInputDisplay 显示 pendingStart、endInputDisplay 显示 pendingEnd——选 start 后右 input 立即换上 pendingEnd 状态,UI 反馈直观。
- 关闭时回退到 selectedStart / selectedEnd 受控值。

Teleport / Form 联动:与 DatePicker 同套机制(formItemInjectionKey + popupAppendToBody + getPopupContainer + floating-ui placement 4 个方位映射)。

测试 38 用例(packages/ccui/ui/range-picker/test/range-picker.test.ts)覆盖:基础渲染(默认/自定义 placeholder + separator + 3 类 modelValue + format + null);popup(start/end input 都能打开、outside 关、disabled 不开、双面板月相邻、autoFocus 落 start input);selection flow(首次只设 pending、二次 emit + close、end<start 自动调换、跨月 start-left-end-right、valueFormat 三档输出 + 类型校验);hover preview(in-hover-range 数量精确、phase=start 阶段无高亮、已确认 in-range 数量、range-start/end modifier 文本);disabledDate;月切换(左 prev、右 next 联动);clearable 4 种 + size 三档 + status;Form integration + Teleport 两种容器 + 外部 v-model 回写。

文档(packages/docs/components/range-picker/index.md):基础 / 显示已选 / 自定义格式(valueFormat 三档)/ 自动调换 / 禁用日期 / 自定义分隔符与占位 / 三种尺寸 / 表单联动 / 弹层容器;API Props 18 行 + Events 5 行 + 已知限制(preset / showTime / 独立 disabledDate / 键盘 / 响应式单面板)。

未交付(计入下一切片):preset 快捷预设、showTime 时间联动、start/end 独立 disabledDate、键盘导航、响应式单面板。

收口:

- packages/ccui/ui/vue-ccui.ts:RangePickerInstall + RangePicker 三处插入,按字母序对齐 Radio / Rate 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(Radio 与 Select 之间)。
- README:### 数据录入 加 RangePicker 条目,组件计数 62 → 63。
- components-diff.md:表格 +1 行(RangePicker 数据录入 80%),组件计数 62 → 63,缺失清单复杂组件改 7 项剩余 + 2 项推进中 → 7 项剩余 + 3 项推进中(DatePicker 备注里说明 range 拆为独立组件,新增 RangePicker 单独一行),新增 Batch 22 写明协议 / 工程决策 / 验证。

工程决策:

- 不抽 use-date-popup 通用 hook:DatePicker / RangePicker / TimePicker 三个组件 popup 的 cell 渲染差异(grid / 双 grid / columns)足够大,emit 协议又不同(单值 / 数组 / 单值),抽出来要传一堆 render slot 反而损可读。等做第四个浮层组件(Cascader / TreeSelect)时再回头评估。
- emit 路径仅在第二次点击触发:第一次点击只更 pending,不发 update:modelValue 也不调 formItem.validate('change'),避免「点了 start 还没选完 end,Form rules 已经判半成品无效」这种回路。
- hover 不立即清空:mouseleave 不清 hoverDate,避免 1px 间隙抖动;closePopup / phase 切换统一清。
- isBefore 而不是 <:所有比较走 dayjs 的 isBefore(other, 'day') / isAfter(other, 'day'),按"日"粒度比较,防止外部 Date 携带时分秒导致同日误判。

验证:

- vp check 通过(302 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/range-picker --run 通过 38/38。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 第四项落地。复用 DatePicker / RangePicker / TimePicker 三个 P1 组件已经验证过的 popup 模式(@floating-ui/vue + Teleport + formItemInjectionKey 联动 + click outside),不抽公共 hook。

数据结构与 fieldNames:

- options 是递归 children 的树。fieldNames: { label?, value?, children?, disabled? } 把字段名映射到任意业务字段(默认 'label' / 'value' / 'children' / 'disabled')。
- 组件内统一通过 getOptionLabel / getOptionValue / getOptionChildren / isOptionDisabled 4 个 helper 读字段,所有渲染分支共用。

路径数组 v-model:

- v-model 永远是 (string | number)[] | null。findOptionPath 沿 options 一级一级查匹配 value 的节点,构造 selectedPath: CascaderOption[]。
- 任一级 value 在 options 中找不到则降级为空路径(input 显示空),避免外部脏数据导致渲染崩。

多列联动渲染:

- 内部 activePath 决定渲染哪几列。第 0 列永远是顶级 options,第 i 列是 activePath[i-1].children。
- 点击非叶子:activePath = activePath.slice(0, columnIndex).push(item.raw),自动截掉更深的列,下一列填新 children。
- 点击叶子:emit 完整路径数组 + close。

changeOnSelect:默认 false。开启后中间节点点击时也 emit 一次 update:modelValue 与 change,但不关闭面板,让用户继续展开下一级。任一时刻 v-model 总是反映「当前已确定的最深路径」。

change 事件双参:第一个参数是 (string | number)[] | null,第二个参数是 selectedOptions: CascaderOption[] 原始路径节点数组。

displayRender:默认 labels.join(separator),separator 默认 ' / '。传 displayRender(labels, selectedOptions) 完全自定义展示文本。

Teleport / Form 联动:与 DatePicker / RangePicker / TimePicker 同套(popupAppendToBody + 自定义 getPopupContainer + formItemInjectionKey 注入校验状态 + emit 时同步触发 formItem.validate('change'))。

空数据兜底:传 options: [] 时面板首列显示 notFoundContent(默认 '暂无数据')。

测试 39 用例(packages/ccui/ui/cascader/test/cascader.test.ts)覆盖:

- 基础渲染(默认/自定义 placeholder + separator + displayRender、modelValue 路径解析、找不到路径降级、null 兜底)
- popup(click 切换 / outside / disabled / autoFocus)
- column expansion(无值时 1 列、有值时 N+1 列、点击非叶子展开下一列、切换 sibling 截深列、active modifier 三列定位、expand-icon 仅非叶子有)
- selection(叶子提交完整路径并关、非叶子 changeOnSelect=false 不 emit、changeOnSelect=true 每级都 emit 但不关到叶子才关、change 第二参数是原始 options 数组、disabled item click 不 emit)
- fieldNames 自定义;clearable 4 种;size 三档;status;Form integration;Teleport 两种容器;外部 v-model 回写;notFoundContent 默认 + 自定义。

文档(packages/docs/components/cascader/index.md):基础 / changeOnSelect / fieldNames / 禁用某项 / 自定义 displayRender / 三种尺寸 / 表单联动 / 弹层容器;API Props 19 行 + Events 5 行 + 已知限制(multiple / showSearch / loadData / hover trigger / 键盘)。

未交付(计入下一切片):multiple 多选、showSearch 搜索、loadData 异步、expandTrigger='hover'、键盘导航。

收口:

- packages/ccui/ui/vue-ccui.ts:CascaderInstall + Cascader 三处插入,按字母序对齐 Card / CheckBox 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(CheckBox 之前)。
- README:### 数据录入 加 Cascader 条目,组件计数 63 → 64,「还没交付的常见组件」表把 Cascader / TreeSelect 合行改为单条 TreeSelect。
- components-diff.md:表格 +1 行(Cascader 数据录入 80%),组件计数 63 → 64,缺失清单复杂组件改 7 项剩余 + 3 项推进中 → 6 项剩余 + 4 项推进中(Cascader 备注更新为已交付 80%),新增 Batch 23 写明协议 / 工程决策 / 验证。

工程决策:

- activePath 与 selectedPath 解耦:selectedPath 是从 modelValue 推导的「确定」路径,activePath 是面板上「悬停 / 编辑」中的路径。点击非叶子时只改 activePath,不动 selectedPath;只有叶子点击或 changeOnSelect=true 时才 emit 让 selectedPath 通过 modelValue 回写。这种解耦让用户可以在面板里自由展开探索,不会污染 v-model 的「确定」状态。
- watch(selectedPath, ...) 同步 activePath:外部 modelValue 变化时把 activePath 同步到新的 selectedPath,避免外部 setState 后面板上还停留在旧路径的展开状态。
- getOptionLabel 显式判 string/number/boolean:而不是直接 String(v)——后者对 object 会返回 [object Object] 这种无意义字符串。显式列出三种基础类型与 Select 的 labelAsString 一致。
- 不引入公共 popup hook:DatePicker / TimePicker / RangePicker / Cascader 四个浮层组件 popup 内部内容差异巨大(grid / columns / 双 grid / 多列 menu),抽出来要传太多 render slot 反而损可读性。同款决策第 4 次复用,等推到 5 个+ 浮层组件再回头评估抽离。
- 空 options 不进入选择流程:第 0 列直接渲染 notFoundContent 占位,避免空 ul + click 后进入"半空状态"。

验证:

- vp check 通过(306 文件 lint/type 全干净,485 文件 prettier 全干净)。
- 从 packages/ccui 跑 pnpm test ui/cascader --run 通过 39/39。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 数据录入复杂组件最后一项落地。本次最大的工程红利:popup 直接复用现有 c-tree 当浮层内容,TreeSelect 只做「外壳 + 状态桥接 + 输入框渲染」。

架构:

- TreeSelect 不重写 Tree 渲染,直接 h(Tree, props) 当 popup 内容。c-tree 已经支持 selectable / multiple / checkable / checkStrictly / selectedKeys / checkedKeys / expandedKeys / defaultExpandAll / fieldNames / blockNode / disabled 全套能力。
- fieldNames 双层映射:TreeSelect 对外暴露 { label, value, children, disabled }(与 Cascader / Select 一致),通过 toTreeFieldNames 内部转 c-tree 的 { title, key, children, disabled }。业务端只用一套字段名习惯。

v-model 类型分支:

- 单选 (multiple=false):modelValue 是 string | number | null
- 多选 (multiple=true):modelValue 是 (string | number)[] | null
- normalizeMultipleValue 把单值包成数组喂给 c-tree 的 selectedKeys / checkedKeys;emit 时单选只取 keys.at(-1),多选回数组(empty 转 null 与其他 picker 一致)。

三种交互模式:

- 单选 (multiple=false 默认):c-tree selectable + selectedKeys=[v]。点击任意节点(含父节点)→ emit + close。
- 多选 checkable (multiple=true treeCheckable=true 默认):c-tree checkable + checkedKeys=v + selectable=false。监听 check 事件 emit 数组,select 不响应。父子节点联动除非 treeCheckStrictly=true。
- 多选 selectable (multiple=true treeCheckable=false):c-tree multiple selectable + selectedKeys=v。监听 select emit 数组,不显示 checkbox。

多选 tags 渲染:

- buildNodeIndex 一次性扁平化整棵 treeData 成 Map<key, {label, disabled}>,从 modelValue 反查 label 拼成 tags。
- 超过 maxTagCount 折叠成 "+ N" 占位 tag。
- 单 tag 移除:removeTag(e, key) e.stopPropagation() 不触发面板打开,emitChange(filtered.length === 0 ? null : filtered)。

clear 一键清空:单选 / 多选都 emit null(与 Cascader / DatePicker 一致),stopPropagation 不触发面板打开。

Teleport / Form 联动:与前 4 个 P1 组件同套(popupAppendToBody + 自定义 getPopupContainer + formItemInjectionKey 注入校验状态 + emitChange 同步触发 formItem.validate('change'))。

空数据兜底:treeData: [] 时面板渲染 notFoundContent(默认 '暂无数据'),不触发 c-tree mount。

测试 43 用例(packages/ccui/ui/tree-select/test/tree-select.test.ts)覆盖:

- 基础渲染(默认/自定义 placeholder + modelValue label 反查 + 单值未知降级 + null 兜底)
- 多选渲染(tags 数量 + 内容、placeholder 占位、+N 折叠 tag、多选模式无 input 元素、tag close 单移除 + stopPropagation、最后一个移除 emit null、disabled 时无 close 按钮)
- popup(click 切换 / outside / disabled / empty + 自定义 notFoundContent)
- single selection(叶子提交 + close、change 带 labels 数组、父节点单选可选)
- multiple checkable(check emit 数组、追加 keys、uncheck 退出、checkable 模式渲染 checkbox、treeCheckable=false 不渲染、selectable 模式不关面板)
- fieldNames 自定义 + emit 路径
- clearable 5 种 + size 三档 + status + is-multiple modifier
- Form integration + Teleport 两种容器 + 单选外部 v-model 回写

文档(packages/docs/components/tree-select/index.md):单选 / 多选 / treeCheckStrictly / 多选 selectable / fieldNames / 三种尺寸 / 表单联动 / 弹层容器;API Props 23 行 + Events 5 行 + 已知限制(showSearch / loadData / showCheckedStrategy / 键盘 / halfCheckedKeys 输出)。

未交付(计入下一切片):showSearch 搜索过滤、loadData 异步加载、showCheckedStrategy 切换、键盘导航、halfCheckedKeys v-model 输出。

收口:

- packages/ccui/ui/vue-ccui.ts:TreeSelectInstall + TreeSelect 三处插入,按字母序对齐 Tree / Typography 之间。
- packages/docs/.vitepress/config/sidebar.ts:手写风格 +5 行加进 数据录入 分类(TimePicker 之后)。
- README:### 数据录入 加 TreeSelect 条目,组件计数 64 → 65,「还没交付的常见组件」表删 TreeSelect 行(Cascader 已在前一批次删除)。
- components-diff.md:表格 +1 行(TreeSelect 数据录入 80%),组件计数 64 → 65,缺失清单复杂组件改 6 项剩余 + 4 项推进中 → 5 项剩余 + 5 项推进中(P1 数据录入 5/5 收口里程碑),新增 Batch 24 写明协议 / 工程决策 / 验证 + P1 数据录入复杂组件全景表(5 个组件 / 205 个新增用例)。

工程决策:

- 不在 c-tree 上加 wrapper component,直接 h(Tree, props):TreeSelect 对 c-tree 的需求是 props 驱动 + 事件透传,没有自定义渲染需求。
- buildNodeIndex 一次性扁平化:tags 渲染需要 value→label 反查,每次 modelValue 变化逐节点 walk 是 O(N)。treeData 大时可加 memoize,80% 切片不优化。
- treeCheckable=true 是默认:与 Ant Design TreeSelect 常用模式一致——多选场景下用户期望看到 checkbox。
- 不在 v-model 中输出 halfCheckedKeys:业务可监听 c-tree-select 自身的 change 事件或直接渲染 c-tree 处理;把半选状态放进 v-model 会让类型膨胀。

P1 数据录入复杂组件全景(5/5 全部 80%,累计 205 个新增用例):

- DatePicker (40 用例) — shared/utils/date.ts + popup 模式 + valueFormat 三档
- TimePicker (45 用例) — shared/utils/date.ts (buildTimeColumnValues) + popup 模式
- RangePicker (38 用例) — shared/utils/date.ts + popup 模式 + 双面板 hover 预览
- Cascader (39 用例) — popup 模式 + 多列联动 + 路径数组 v-model
- TreeSelect (43 用例) — popup 模式 + c-tree 复用

5 个组件共享:@floating-ui/vue placement / Teleport + Transition / Form formItemInjectionKey 联动 / click outside 关闭 / emit 同步 validate('change')。

验证:

- vp check 通过(310 文件 lint/type 全干净)。
- 从 packages/ccui 跑 pnpm test ui/tree-select --run 通过 43/43。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 数据录入复杂组件 5/5 全部 80% 收口(DatePicker / TimePicker / RangePicker / Cascader / TreeSelect)后,首页 hero 的 feature card 同步更新:

- "60 个组件" → "65 个组件 / 工具入口(含 P1 数据录入 5 大复杂组件 80%)"
- "800+ 定向单测" → "1000+ 定向单测"

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e + 命令式 expose)

P2 启动批次。Carousel 一次性把 23 个用例打底:scrollx + fade 双 effect、autoplay + pauseOnHover、4 向 dots、infinite wrap、arrows、受控/非受控双模、prev/next/goTo expose。
中等复杂度剩余从 3 项降到 2 项(QRCode / ColorPicker)。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 第二个组件。基于 qrcode-generator (3KB) 提供矩阵数据,组件层用 horizontal-run 合并 path 自渲 SVG,比 N×N rect 节点轻一个数量级。
17 个用例打底:viewBox 模块数随 errorLevel 单调递增、color/bgColor/size/bordered、icon 30% 截断、status 四态遮罩 + refresh emit + statusRender slot、value/errorLevel reactivity、empty value 兜底。
中等复杂度剩余从 2 项降到 1 项(仅余 ColorPicker)。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 中等复杂度收口批次。25 个用例分两层:5 个覆盖 shared/utils/color.ts 互转(含 alpha 8 位 hex round-trip),20 个覆盖组件层。
新增 shared/utils/color.ts(与 date.ts 同款 utility-first 风格,零外部颜色库);ColorPicker 自渲 SV 三层叠加 + 棋盘格 alpha 轨道;hex 输入 edit-on-blur;preset 色板;disabledAlpha 三处守门;与 P1 五件套同款 popup 模式 + Form 联动。
中等复杂度剩余清零(QRCode + Carousel + ColorPicker 共 3 项 80% 全收口)。65→68 组件。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P3 第一个组件。本质是「Input + 浮层下拉」,区别于 Select 在于值可以是任意字符串。
24 个用例:options 兼容 string[] / {value,label,disabled}[]、filterOption 三态(true/false/function)+ caseSensitive、ArrowUp/Down/Enter/Esc 键盘导航跳过 disabled、allowClear、Form 联动 + Teleport、空数据 notFoundContent、受控/非受控双模、option 自定义 slot。
不复用 c-select 内部实现(语义对立),共享 popup 模式(floating-ui + Teleport + formItemInjectionKey + click outside)。
68→69 组件。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P1 5/5 之后追加 P2 中等复杂度三件套(Carousel / QRCode / ColorPicker)+ P3 第一个 AutoComplete,新增 89 个用例。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 大件第一项。24 个用例:partition 顺序按 targetKeys、跨列 selectedKeys 单源、header indeterminate 三态、disabled 单项不进统计、move 自动清除被移动的勾选、filterOption + 两列独立搜索、render slot + prop 双入口、Form 联动。
69→70 组件。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P3 体验型组件第一项。19 个用例。
4 块 div 围出 target 矩形做镂空(不用 SVG/clip-path),highlight 蓝色光晕;无 target 时浮层退化为居中模态。
v-model:open + v-model:current 双键,末步 finish emit + 自动关闭,Esc / 蒙层点击 / × 同一条 close 路径。
70→71 组件。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P2 大件第二项。22 个用例。
不内置 HTTP 上传 —— 业务监听 change 自己发请求、回写 fileList 状态。组件只负责 UI + 状态机 + 三层守门(maxSize → maxCount → beforeUpload)。
拖拽四件套(dragenter/over/leave/drop)+ 隐藏 input + input.value 重置技巧 + size 格式化 B/KB/MB + 受控/非受控双模 + reject emit。
71→72 组件,P2 大件只剩 Mentions。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
P3 体验型组件最后一项,至此 P2 大件 + P3 全部 80% 收口。31 个用例(含 7 个 findActiveMention 纯函数测例覆盖 email-style 防误触发等边界)。
textarea + 浮层模式(不用 contenteditable);refreshMatch 在 input/keyup/click 三处刷新;selectOption 字符串拼接 + setSelectionRange 光标后置;多 prefix 选最近;filterOption 三态;Form blur/change validate。
72→73 组件。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Transfer / Tour / Upload / Mentions 四件 P2 大件 + P3 体验组件全部 80% 落地,新增 96 个用例。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- vite.config.ts: vueJsx({ tsTransform: 'built-in' }) 修复 64 个 TSX 文件 import-analysis 加载失败
- slider.test.ts: 重写 30→32 个用例,消除 wrapper.vm.* 内部访问,改为 emitted/DOM/ARIA 断言
- statistic.test.ts: countdown 毫秒断言改为 ±50ms 范围,消除 setInterval 粒度漂移
- back-top.tsx: getScrollTop/scrollTo 增加 t === window 判断,修复 jsdom instanceof Window 为 false
- float-button.test.ts: window.scrollY mock 改用 defineProperty + 属性恢复
- 全量 74/74 文件通过、1220/1220 测试通过

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…dient/toDataURL)

Carousel 95%:
- 键盘导航 ArrowLeft/Right/Up/Down/Home/End
- ARIA 增强 role=region, aria-roledescription=carousel, aria-live=polite, role=tabpanel
- swipe 手势 pointerdown/up + swipeThreshold + 横竖自适应
- afterChange 事件在 duration 后触发
- customDot 作用域插槽自定义指示器
- 39 个测试全通过(+14)

QRCode 95%:
- dotRadius 圆角点阵(0=方形,0.5=正圆)
- gradient 渐变前景色(linearGradient + 6 向 direction)
- toDataURL expose(SVG→canvas→dataURL)
- 25 个测试全通过(+8)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ear)

- RGB 三联 number input(R/G/B 独立编辑,0~255 范围,自动 commit HSV)
- trigger 作用域插槽({ color, open, disabled } 自定义触发器)
- SV/hue/alpha 键盘 Arrow 微调(±1,Shift ±10),三区域 tabindex=0
- allowClear prop + clear 按钮(emit null + stopPropagation)
- 34 个测试全通过(+9)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
zcj and others added 21 commits May 19, 2026 20:11
- 加「其他」组,把 ConfigProvider/Util 从「通用」搬过去(基建非 UI 原子)
- Tag/CheckableTag → 通用、Dropdown → 通用、Status → 数据展示、Calendar/Rate/Segmented → 数据录入,归位错置
- 调整分类顺序:通用→布局→导航→数据录入→数据展示→反馈→其他

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 提取 Vue 状态语义 + 测试优先级到 decisions/testing-principles.md
- 删除已烂的「后续任务入口」(statistic 组件不存在、覆盖率数字过期、TODO 状态不明),按 docs-notes/README 规则 3「修复记录/批次记录不再单独写」处理
- docs-notes/README.md 索引补一行

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- introduce.md 收回为「ccui 是什么 / 设计取向 / token 概念」,不再夹杂安装步骤
- 新增 quick-start.md,承载安装 / 完整引入 / 按需引入 / CDN
- sidebar 模板 root 改名「指南 / Guide」,新增「快速开始」入口
- home hero 主按钮改指向 /quick-start,「简介」做次按钮;feature 卡片「六大类 83」同步改为「七大类 84」

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- offset-path rect(round 100px) + mask 边框环实现,过弯平滑
- color 支持单色 / 渐变停靠点数组,停靠点映射进前 70% 预留拖尾
- 内置 6 套配色预设(ocean/sunset/aurora/forest/ember/nebula)并导出
- 文档含 card 包裹、预设切换、调速、外扩等 demo;16 个单测

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 删除 archive/ 整目录(roadmap / components-diff / per-component / 审查报告)
- decisions 剥离 commit 哈希 / Batch / 测试 delta 等实现历史,保留决策、理由、不变性约束与 TODO
- config-provider-locale 重写为接口契约 + 约束 + Drawer 未决项
- README 移除 archive 索引,过期内容改为直接删除靠 git 溯源

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README 移除过期组件清单(含未交付的幽灵条目与进度括注),改为引导至文档站
- 统一组件数与测试数字,软化对标措辞为 honest 致敬
- date-picker / upload / table-summary 文档去除进度标注式措辞
- cli 生成器注入 CCUI_VERSION(读 ccui package.json),修复库误报 cli 版本
- 补 Tabs 组件 status 徽标

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
按 docs-notes/issue.md 逐项定位根因并修复:

间距/对齐
- Space 水平方向默认 align-items:center,不再撑高 Tag/Button
- Tag 多彩标签示例改用 c-space 提供间距
- ColorPicker trigger 加 vertical-align:middle 与文字对齐
- Steps 连接线两端等距,补 small/dot/vertical 变体覆盖
- Badge __sup 提 z-index 并贴合右上角;移除 BadgeRibbon 缎带示例
- Carousel/Upload 首项偏上 → docs-theme 统一复位 vp-doc li margin 渗透
- Spin 延迟示例两按钮用 c-space 对齐

图标一致性(统一走 renderIconNode/mdi,消除 Unicode 字形回退)
- 新增 renderIconWithFallback helper;Select/InputSearch/TimePicker/
  TimeRangePicker/Transfer/TreeSelect/DatePicker/RangePicker 统一图标
- InputSearch primary 按钮内图标改白色并上调字号
- TimePicker 修 input min-width:0,图标回到边框内
- TimePicker 新增 showSuffix prop;TimeRangePicker 仅外层渲染单个时钟/清除
- 图标字号统一用 $ccui-font-size-icon

行为修复
- Anchor 高亮对应、Affix 0px 固定核对修正
- Watermark 防篡改:观察 style/class 属性改动,disconnect-around-writes 避免自触发
- Tooltip 采用 flip 后的实际 placement,箭头随翻转;offset 下调
- Popover/Tooltip 箭头仅保留指向侧边框,消除明显边框

结构调整(硬删除/硬重命名,无废弃别名)
- 删除 UploadDragger(Upload 已内置 drag)、AvatarGroup
- ImagePreviewGroup → ImagePreview(图片预览组 → 图片预览)
- resolver 组件表同步;重新生成入口/侧边栏

文档
- 示例小节标题「基本用法」统一为「基本使用」
- Watermark 图片水印 / Empty 自定义图片:替换抄自蚂蚁的 CDN 图片为
  自带中性 base64 SVG

测试:ccui 2029 passed / 94 files,resolver 26 passed,vp check 0 errors

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
与 Tooltip 同源问题:popover 的箭头方位(哪两条边透明、静态边偏移)
此前基于请求的 props.placement,flip() 翻转后未更新——「12 个出现位置」
示例中 bottom 触发元素下方无空间翻到上方时,箭头仍停在上方、指向错误。

修复(对齐 Tooltip 的做法):
- useFloating 解构响应式 placement,传 toRef(props,'placement')
- 新增 actualSide(翻转后实际方位),arrowStyles 静态边与箭头 __arrow--<side>
  class 均改用 actualSide
- popperClass 仍用 props.placement(保留 __popper--<placement> 断言)
- scss 把透明边规则从 __popper--<side> .__arrow 迁到 __arrow--<side>,
  由 actualSide 驱动;位置偏移完全交给 inline arrowStyles

浏览器验证:bottom 触发元素贴近视口底部时翻到上方,arrow class 变为
__arrow--top、落在浮层底部指向触发元素。ccui 2029 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- transfer: 操作按钮用 flex 居中并放大 icon(13px→16px)
- select: __arrow 放大到 20px,修正 mdi:menu-down 视觉偏小
- steps: 垂直连接线改挂 item 并用 top/bottom 双向锚定,两端间距对称(含 small 覆写)
- docs showcase: 间距规则改用 :has(~ …),最后/唯一组件不再带 trailing 右下边距

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…出、Badge 间距修正锚点、收敛 showcase 间距修正 ColorPicker 对齐

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
删除 packages/ccui/ui/status 组件与文档页,同步清理 resolver 映射、
install.test.ts 静态导入;vue-ccui/sidebar 等生成入口重新生成后不再含 Status。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- bundle-size-baseline: 重跑 pnpm build:lib 刷新快照(2026-06-02 @ eafddf9);
  css 产物更名 ccui-cli.css→style.css,子 bundle 57→82,主包/各 chunk 体积重测
- releasing.md: 补全 publish.mjs 实际流程(工作区检查 + bumpp 自动 bump、
  --release/--skip-bump 等 flag),版本号管理章节同步
- 修正 4 处过期包名 vue3-ccui→@vaebe/ccui,design-values 移除已删的 Status 引用
- 删除 issue.md(bug 已全部修复并入库,靠 git 历史溯源)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 300 files, which is 150 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 890fffb1-75f6-42a6-894c-aaf69870baf2

📥 Commits

Reviewing files that changed from the base of the PR and between dad160b and 1b075cc.

📒 Files selected for processing (300)
  • .github/workflows/buildComponents.yml
  • .github/workflows/deploy.yml
  • .github/workflows/test.yml
  • .gitignore
  • .husky/commit-msg
  • .husky/pre-commit
  • .vite-hooks/pre-commit
  • AGENTS.md
  • CHANGELOG.md
  • README.md
  • docs-notes/README.md
  • docs-notes/bundle-size-baseline.md
  • docs-notes/decisions/benchmark-principles.md
  • docs-notes/decisions/brand-color.md
  • docs-notes/decisions/config-provider-locale.md
  • docs-notes/decisions/design-values.md
  • docs-notes/decisions/testing-principles.md
  • docs-notes/releasing.md
  • eslint.config.mjs
  • examples/consumer/.gitignore
  • examples/consumer/README.md
  • examples/consumer/index.html
  • examples/consumer/package.json
  • examples/consumer/src/App.vue
  • examples/consumer/src/main.ts
  • examples/consumer/src/page-main.ts
  • examples/consumer/src/page-resolver.ts
  • examples/consumer/src/page-subpath.ts
  • examples/consumer/tsconfig.json
  • examples/consumer/vite.config.ts
  • package.json
  • packages/ccui/README.md
  • packages/ccui/env.d.ts
  • packages/ccui/index.d.ts
  • packages/ccui/package.json
  • packages/ccui/tsconfig.build.json
  • packages/ccui/tsconfig.json
  • packages/ccui/tsconfig.node.json
  • packages/ccui/ui/affix/index.ts
  • packages/ccui/ui/affix/src/affix-types.ts
  • packages/ccui/ui/affix/src/affix.scss
  • packages/ccui/ui/affix/src/affix.tsx
  • packages/ccui/ui/affix/test/affix.test.ts
  • packages/ccui/ui/alert/index.ts
  • packages/ccui/ui/alert/src/alert-types.ts
  • packages/ccui/ui/alert/src/alert.scss
  • packages/ccui/ui/alert/src/alert.tsx
  • packages/ccui/ui/alert/test/alert.test.ts
  • packages/ccui/ui/anchor/index.ts
  • packages/ccui/ui/anchor/src/anchor-types.ts
  • packages/ccui/ui/anchor/src/anchor.scss
  • packages/ccui/ui/anchor/src/anchor.tsx
  • packages/ccui/ui/anchor/test/anchor.test.ts
  • packages/ccui/ui/auto-complete/index.ts
  • packages/ccui/ui/auto-complete/src/auto-complete-types.ts
  • packages/ccui/ui/auto-complete/src/auto-complete.scss
  • packages/ccui/ui/auto-complete/src/auto-complete.tsx
  • packages/ccui/ui/auto-complete/test/auto-complete.test.ts
  • packages/ccui/ui/avatar/src/avatar-types.ts
  • packages/ccui/ui/avatar/src/avatar.scss
  • packages/ccui/ui/avatar/src/avatar.tsx
  • packages/ccui/ui/avatar/src/components/icon-body.tsx
  • packages/ccui/ui/avatar/src/components/icon-img-error.tsx
  • packages/ccui/ui/avatar/src/components/icon-nobody.tsx
  • packages/ccui/ui/avatar/src/composables/use-get-background-color.ts
  • packages/ccui/ui/avatar/src/composables/use-get-display-name.ts
  • packages/ccui/ui/avatar/test/avatar.test.ts
  • packages/ccui/ui/badge-ribbon/index.ts
  • packages/ccui/ui/badge-ribbon/src/badge-ribbon-types.ts
  • packages/ccui/ui/badge-ribbon/src/badge-ribbon.scss
  • packages/ccui/ui/badge-ribbon/src/badge-ribbon.tsx
  • packages/ccui/ui/badge-ribbon/test/badge-ribbon.test.ts
  • packages/ccui/ui/badge/index.ts
  • packages/ccui/ui/badge/src/badge-types.ts
  • packages/ccui/ui/badge/src/badge.scss
  • packages/ccui/ui/badge/src/badge.tsx
  • packages/ccui/ui/badge/test/badge.test.ts
  • packages/ccui/ui/border-beam/index.ts
  • packages/ccui/ui/border-beam/src/border-beam-presets.ts
  • packages/ccui/ui/border-beam/src/border-beam-types.ts
  • packages/ccui/ui/border-beam/src/border-beam.scss
  • packages/ccui/ui/border-beam/src/border-beam.tsx
  • packages/ccui/ui/border-beam/test/border-beam.test.ts
  • packages/ccui/ui/breadcrumb/index.ts
  • packages/ccui/ui/breadcrumb/src/breadcrumb-types.ts
  • packages/ccui/ui/breadcrumb/src/breadcrumb.scss
  • packages/ccui/ui/breadcrumb/src/breadcrumb.tsx
  • packages/ccui/ui/breadcrumb/test/breadcrumb.test.ts
  • packages/ccui/ui/button-3d/src/button-3d-types.ts
  • packages/ccui/ui/button-3d/src/button-3d.scss
  • packages/ccui/ui/button-3d/src/button-3d.tsx
  • packages/ccui/ui/button-3d/test/button-3d.test.ts
  • packages/ccui/ui/button/index.ts
  • packages/ccui/ui/button/src/button-group.scss
  • packages/ccui/ui/button/src/button-group.tsx
  • packages/ccui/ui/button/src/button-types.ts
  • packages/ccui/ui/button/src/button.scss
  • packages/ccui/ui/button/src/button.tsx
  • packages/ccui/ui/button/test/button.test.ts
  • packages/ccui/ui/calendar/index.ts
  • packages/ccui/ui/calendar/src/calendar-types.ts
  • packages/ccui/ui/calendar/src/calendar.tsx
  • packages/ccui/ui/calendar/test/calendar.test.ts
  • packages/ccui/ui/card-meta/index.ts
  • packages/ccui/ui/card-meta/src/card-meta-types.ts
  • packages/ccui/ui/card-meta/src/card-meta.scss
  • packages/ccui/ui/card-meta/src/card-meta.tsx
  • packages/ccui/ui/card-meta/test/card-meta.test.ts
  • packages/ccui/ui/card/src/card-types.ts
  • packages/ccui/ui/card/src/card.scss
  • packages/ccui/ui/card/src/card.tsx
  • packages/ccui/ui/card/test/card.test.ts
  • packages/ccui/ui/carousel/index.ts
  • packages/ccui/ui/carousel/src/carousel-types.ts
  • packages/ccui/ui/carousel/src/carousel.scss
  • packages/ccui/ui/carousel/src/carousel.tsx
  • packages/ccui/ui/carousel/test/carousel.test.ts
  • packages/ccui/ui/cascader/index.ts
  • packages/ccui/ui/cascader/src/cascader-types.ts
  • packages/ccui/ui/cascader/src/cascader.scss
  • packages/ccui/ui/cascader/src/cascader.tsx
  • packages/ccui/ui/cascader/test/cascader.test.ts
  • packages/ccui/ui/check-box/src/check-box-group.scss
  • packages/ccui/ui/check-box/src/check-box-group.tsx
  • packages/ccui/ui/check-box/src/check-box-types.ts
  • packages/ccui/ui/check-box/src/check-box.scss
  • packages/ccui/ui/check-box/src/check-box.tsx
  • packages/ccui/ui/check-box/test/check-box.test.ts
  • packages/ccui/ui/checkable-tag/index.ts
  • packages/ccui/ui/checkable-tag/src/checkable-tag-group.tsx
  • packages/ccui/ui/checkable-tag/src/checkable-tag-types.ts
  • packages/ccui/ui/checkable-tag/src/checkable-tag.scss
  • packages/ccui/ui/checkable-tag/src/checkable-tag.tsx
  • packages/ccui/ui/checkable-tag/test/checkable-tag.test.ts
  • packages/ccui/ui/collapse/index.ts
  • packages/ccui/ui/collapse/src/collapse-item.tsx
  • packages/ccui/ui/collapse/src/collapse-types.ts
  • packages/ccui/ui/collapse/src/collapse.scss
  • packages/ccui/ui/collapse/src/collapse.tsx
  • packages/ccui/ui/collapse/test/collapse.test.ts
  • packages/ccui/ui/color-picker/index.ts
  • packages/ccui/ui/color-picker/src/color-picker-types.ts
  • packages/ccui/ui/color-picker/src/color-picker.scss
  • packages/ccui/ui/color-picker/src/color-picker.tsx
  • packages/ccui/ui/color-picker/test/color-picker.test.ts
  • packages/ccui/ui/config-provider/index.ts
  • packages/ccui/ui/config-provider/src/config-provider-types.ts
  • packages/ccui/ui/config-provider/src/config-provider.tsx
  • packages/ccui/ui/config-provider/test/config-provider.test.ts
  • packages/ccui/ui/date-picker/index.ts
  • packages/ccui/ui/date-picker/src/date-picker-types.ts
  • packages/ccui/ui/date-picker/src/date-picker.scss
  • packages/ccui/ui/date-picker/src/date-picker.tsx
  • packages/ccui/ui/date-picker/test/date-picker.test.ts
  • packages/ccui/ui/descriptions/index.ts
  • packages/ccui/ui/descriptions/src/descriptions-item.tsx
  • packages/ccui/ui/descriptions/src/descriptions-types.ts
  • packages/ccui/ui/descriptions/src/descriptions.scss
  • packages/ccui/ui/descriptions/src/descriptions.tsx
  • packages/ccui/ui/descriptions/test/descriptions.test.ts
  • packages/ccui/ui/divider/src/divider.scss
  • packages/ccui/ui/divider/src/divider.tsx
  • packages/ccui/ui/divider/test/divider.test.ts
  • packages/ccui/ui/drawer/index.ts
  • packages/ccui/ui/drawer/src/drawer-types.ts
  • packages/ccui/ui/drawer/src/drawer.scss
  • packages/ccui/ui/drawer/src/drawer.tsx
  • packages/ccui/ui/drawer/test/drawer.test.ts
  • packages/ccui/ui/dropdown/index.ts
  • packages/ccui/ui/dropdown/src/dropdown-types.ts
  • packages/ccui/ui/dropdown/src/dropdown.scss
  • packages/ccui/ui/dropdown/src/dropdown.tsx
  • packages/ccui/ui/dropdown/test/dropdown.test.ts
  • packages/ccui/ui/empty/index.ts
  • packages/ccui/ui/empty/src/empty-types.ts
  • packages/ccui/ui/empty/src/empty.scss
  • packages/ccui/ui/empty/src/empty.tsx
  • packages/ccui/ui/empty/test/empty.test.ts
  • packages/ccui/ui/flex/index.ts
  • packages/ccui/ui/flex/src/flex-types.ts
  • packages/ccui/ui/flex/src/flex.scss
  • packages/ccui/ui/flex/src/flex.tsx
  • packages/ccui/ui/flex/test/flex.test.ts
  • packages/ccui/ui/float-button/index.ts
  • packages/ccui/ui/float-button/src/back-top.tsx
  • packages/ccui/ui/float-button/src/float-button-types.ts
  • packages/ccui/ui/float-button/src/float-button.scss
  • packages/ccui/ui/float-button/src/float-button.tsx
  • packages/ccui/ui/float-button/test/float-button.test.ts
  • packages/ccui/ui/form/index.ts
  • packages/ccui/ui/form/src/form-item.tsx
  • packages/ccui/ui/form/src/form-list.tsx
  • packages/ccui/ui/form/src/form-provider.tsx
  • packages/ccui/ui/form/src/form-types.ts
  • packages/ccui/ui/form/src/form.scss
  • packages/ccui/ui/form/src/form.tsx
  • packages/ccui/ui/form/src/utils.ts
  • packages/ccui/ui/form/test/form.test.ts
  • packages/ccui/ui/grid/index.ts
  • packages/ccui/ui/grid/src/grid-types.ts
  • packages/ccui/ui/grid/src/grid.scss
  • packages/ccui/ui/grid/src/grid.tsx
  • packages/ccui/ui/grid/test/grid.test.ts
  • packages/ccui/ui/icon/index.ts
  • packages/ccui/ui/icon/src/icon-registry.ts
  • packages/ccui/ui/icon/src/icon-types.ts
  • packages/ccui/ui/icon/src/icon.scss
  • packages/ccui/ui/icon/src/icon.tsx
  • packages/ccui/ui/icon/test/icon.test.ts
  • packages/ccui/ui/image-preview/index.ts
  • packages/ccui/ui/image-preview/src/image-preview-types.ts
  • packages/ccui/ui/image-preview/src/image-preview.scss
  • packages/ccui/ui/image-preview/src/image-preview.tsx
  • packages/ccui/ui/image-preview/test/image-preview.test.ts
  • packages/ccui/ui/image/index.ts
  • packages/ccui/ui/image/src/image-types.ts
  • packages/ccui/ui/image/src/image.scss
  • packages/ccui/ui/image/src/image.tsx
  • packages/ccui/ui/image/test/image.test.ts
  • packages/ccui/ui/input-number/src/input-number-types.ts
  • packages/ccui/ui/input-number/src/input-number.scss
  • packages/ccui/ui/input-number/src/input-number.tsx
  • packages/ccui/ui/input-number/test/input-number.test.ts
  • packages/ccui/ui/input-otp/index.ts
  • packages/ccui/ui/input-otp/src/input-otp-types.ts
  • packages/ccui/ui/input-otp/src/input-otp.scss
  • packages/ccui/ui/input-otp/src/input-otp.tsx
  • packages/ccui/ui/input-otp/test/input-otp.test.ts
  • packages/ccui/ui/input-search/index.ts
  • packages/ccui/ui/input-search/src/input-search-types.ts
  • packages/ccui/ui/input-search/src/input-search.scss
  • packages/ccui/ui/input-search/src/input-search.tsx
  • packages/ccui/ui/input-search/test/input-search.test.ts
  • packages/ccui/ui/input/index.ts
  • packages/ccui/ui/input/src/input-types.ts
  • packages/ccui/ui/input/src/input.scss
  • packages/ccui/ui/input/src/input.tsx
  • packages/ccui/ui/input/test/input.test.ts
  • packages/ccui/ui/layout/index.ts
  • packages/ccui/ui/layout/src/layout-types.ts
  • packages/ccui/ui/layout/src/layout.scss
  • packages/ccui/ui/layout/src/layout.tsx
  • packages/ccui/ui/layout/test/layout.test.ts
  • packages/ccui/ui/locale/en-US.ts
  • packages/ccui/ui/locale/index.ts
  • packages/ccui/ui/locale/ja-JP.ts
  • packages/ccui/ui/locale/ko-KR.ts
  • packages/ccui/ui/locale/zh-CN.ts
  • packages/ccui/ui/masonry/index.ts
  • packages/ccui/ui/masonry/src/masonry-types.ts
  • packages/ccui/ui/masonry/src/masonry.scss
  • packages/ccui/ui/masonry/src/masonry.tsx
  • packages/ccui/ui/masonry/test/masonry.test.ts
  • packages/ccui/ui/mentions/index.ts
  • packages/ccui/ui/mentions/src/mentions-types.ts
  • packages/ccui/ui/mentions/src/mentions.scss
  • packages/ccui/ui/mentions/src/mentions.tsx
  • packages/ccui/ui/mentions/test/mentions.test.ts
  • packages/ccui/ui/menu/index.ts
  • packages/ccui/ui/menu/src/menu-types.ts
  • packages/ccui/ui/menu/src/menu.scss
  • packages/ccui/ui/menu/src/menu.tsx
  • packages/ccui/ui/menu/test/menu.test.ts
  • packages/ccui/ui/message/index.ts
  • packages/ccui/ui/message/src/message-item.tsx
  • packages/ccui/ui/message/src/message-types.ts
  • packages/ccui/ui/message/src/message.scss
  • packages/ccui/ui/message/src/message.ts
  • packages/ccui/ui/message/src/use-message.ts
  • packages/ccui/ui/message/test/message.test.ts
  • packages/ccui/ui/message/test/use-message.test.ts
  • packages/ccui/ui/modal/index.ts
  • packages/ccui/ui/modal/src/confirm-types.ts
  • packages/ccui/ui/modal/src/confirm.tsx
  • packages/ccui/ui/modal/src/modal-types.ts
  • packages/ccui/ui/modal/src/modal.scss
  • packages/ccui/ui/modal/src/modal.tsx
  • packages/ccui/ui/modal/src/use-modal.ts
  • packages/ccui/ui/modal/test/modal-confirm.test.ts
  • packages/ccui/ui/modal/test/modal.test.ts
  • packages/ccui/ui/modal/test/use-modal.test.ts
  • packages/ccui/ui/notification/index.ts
  • packages/ccui/ui/notification/src/notification-item.tsx
  • packages/ccui/ui/notification/src/notification-types.ts
  • packages/ccui/ui/notification/src/notification.scss
  • packages/ccui/ui/notification/src/notification.ts
  • packages/ccui/ui/notification/src/use-notification.ts
  • packages/ccui/ui/notification/test/notification.test.ts
  • packages/ccui/ui/notification/test/use-notification.test.ts
  • packages/ccui/ui/pagination/index.ts
  • packages/ccui/ui/pagination/src/pagination-types.ts
  • packages/ccui/ui/pagination/src/pagination.scss
  • packages/ccui/ui/pagination/src/pagination.tsx
  • packages/ccui/ui/pagination/test/pagination.test.ts
  • packages/ccui/ui/popconfirm/index.ts
  • packages/ccui/ui/popconfirm/src/popconfirm-types.ts
  • packages/ccui/ui/popconfirm/src/popconfirm.scss
  • packages/ccui/ui/popconfirm/src/popconfirm.tsx
  • packages/ccui/ui/popconfirm/test/popconfirm.test.ts
  • packages/ccui/ui/popover/index.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 2.x

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

vaebe and others added 4 commits June 2, 2026 23:41
pnpm/action-setup@v4 同时收到 with.version 与 package.json packageManager
(pnpm@10.33.2) 两个来源会报 ERR_PNPM_BAD_PM_VERSION。删掉 workflow 里的
version(test/buildComponents 为 10、deploy 误写为 9),单一 source of truth。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- test: vue3-ccui → @vaebe/ccui(vue3-ccui 包不存在,该步一直空跑)
- buildComponents: cli → ccui-cli(pnpm --filter 按包名匹配,cli 匹配不到)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
两者都是 gitignored 产物,全新 checkout 不存在;既无 postinstall 也无
prepare 去构建。组件 icon.tsx 的 @vaebe/ccui-icons/install 副作用 import 与
style-var 经 @vaebe/ccui-theme/theme 的 @forward 因此解析失败。
test / buildComponents 在 pnpm install 后补一步 icons build + generate:theme
(与 docs predev 一致)。本地从干净态复现验证:2023 用例全绿 + build:components 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
新增 root bootstrap 脚本(pnpm --filter @vaebe/ccui-icons build &&
pnpm --filter ccui-cli generate:theme),挂到 postinstall。这样全新
git clone + pnpm install 即可开箱跑 test / build,无需手动构建这两个
gitignored 产物。CI 的 test/buildComponents 随之去掉显式 prepare 步,
统一由 pnpm install 兜底。本地 wipe + pnpm install 验证:postinstall
正确重建 icons dist(15 文件) 与 theme.scss。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vaebe
vaebe merged commit 6648981 into main Jun 3, 2026
4 checks passed
@vaebe
vaebe deleted the 2.x branch June 3, 2026 03:19
@vaebe
vaebe restored the 2.x branch June 3, 2026 07:12
@vaebe
vaebe deleted the 2.x branch June 8, 2026 15:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant