Jixoai UI v0.5:spin 组件与 loader pack
jixoai-ui v0.5.0 新增 spin 组件:<Spin spinner> 先解析生成的 svg 工件(blocks-wave 默认,94+12 枚 loader 位于插件的 ./spinners 子入口),其次解析 59 名 cli-spinners 文字目录。文字通道为平铺 CSS 动画——帧全量渲染,JS 只写入动画参数;lingerType end/start/both 控制残影形状,每个目录名携带手调的 interval/linger 配对。
$ git log v0.4.0..v0.5.1 --oneline | wc -l
41
jixoai-ui v0.5(2026-09-13,当前 0.5.1)包含 41 个提交:7 feat、14 fix、14 docs,其余为 test、chore 与合并提交。主要变更为 spin 组件与插件侧的 spinners 特性(含 0.5.1 的完整 channel API)。无破坏性变更,升级无迁移动作。
spin 组件
新增 <Spin>。加载指示器以名字为参数,参照 ora:纯文本输出,无 [ ] 包裹。spinner 属性按两条车道解析,svg 工件名优先,文字目录名其次:
<!-- svg 车道:编译期工件名,blocks-wave 为默认值 -->
<Spin spinner="blocks-wave" />
<!-- 文字车道:59 名 cli-spinners 目录,帧逐字节取自 cli-spinners@2.9.2 -->
<Spin spinner="dots" />
名字为编译期联合类型,未知名在类型检查时报错;运行期输出一次带缓存的警告。尺寸不引入独立单位:文字通道使用 var(--jx-text),svg 通道使用 var(--jx-icon),两者为密度标尺变量,与 jixoai.com 的站点排版使用同一组值。
无障碍为内建行为:role="status"(含隐式 aria-live)、包裹姿态的 aria-busy、prefers-reduced-motion 下输出静态帧,调用方无需配置。
文字通道:平铺 CSS 动画
全部帧一次性渲染(单格 grid + white-space: pre,帧切换不产生布局变化),JS 只写入动画参数:每个参数组合注入一条 @keyframes,每帧以负 animation-delay 定相到自己的时隙。
结果:帧切换不产生 DOM 变更;动画由合成器执行,主线程阻塞不影响节拍;DevTools 的 Animations 面板可逐帧检查每个时隙与残影区间。prefers-reduced-motion 以媒体查询静态关闭,无运行期分支。
linger 与 lingerType
残影参数命名为 linger:上一帧在交接后继续显示 linger 毫秒,线性淡出。类型 number | 'auto'。淡出形状由 lingerType 决定:
end(默认):完整显示当前时隙,尾段线性淡出;start:淡入在交接边界前完成,下一帧接管时已完全显示;both:两端渐变。
'auto' 为逐名手调值,定义于策展脚本:dots 80/160、dots2 120/0、pipe 120/120、line 160/0、simpleDots 160/160(· 字形)。interval 与 linger 支持显式传值,优先级为:显式值 > Defaults 槽位 > 目录手调值。
实现过程中修正的两个问题:
同百分比 keyframe 停点合并:
10%{opacity:1}10%{opacity:0}中后者覆盖前者,整段退化为线性过渡;离散隐藏需在停点上声明steps(1,start)。实心帧约束:linger ≥ interval 时,入场时长必须封顶在 interval/2,否则不透明度只在单一时间点达到峰值。
SVG 通道:SMIL
svg 车道执行动画自带的 SMIL。组件负责三项处理:
实例级 id 命名空间:同一 loader 渲染多份时,
begin="x.end"一类 syncbase 引用不会跨实例解析;切换时
{#key}整体重建:在常驻 svg 元素内替换 innerHTML,Chrome 的动画激活率为 1/12;动态插入的激活处理:样式表文本重解析 +
setCurrentTime(0),仅在document.readyState === 'complete'时执行,避免水合期间重置运行中的动画。
94 枚 magecdn loader 经组件路径逐枚像素验证:83 枚直接通过,11 枚依赖激活处理;15 枚依赖外部上下文的动态 loader 带回执排除。颜色统一为 currentColor,跟随文字颜色,无需按主题配置。本文中的演示均为实际组件渲染,切换站点主题可直接验证暗色下的表现。
vite-plugin:spinners 特性
@jixoai/ui-vite-plugin 新增 spinners 特性(0.4.0;channel API 于 0.5.1 补齐),与图标库的接口一致:jixoai({ spinners }),默认关闭,开启后才执行代码生成;来源支持 inline 与 { file };RAW 安全闸门拒绝不可信形状;产物单写者——gen:spins 生成、verify:spins 校验,CI 中手改产物即失败。
该特性不使用 svgo:convertShapeToPath 会把 <circle> 重写为 <path>,而 SMIL 的 <animate> 按形状元素类型定位目标,处理后动画目标丢失。loader 的 svg 按 RAW 语义处理,归一化仅限明确清单内的改写(移除 xml 声明、#fff → currentColor)。
自定义扩展与图标系统对齐,提供完整 channel API(0.5.1)。channel 为一等实例:defineSpinnerChannel({ id, prefix, spinners, peerPackage?, defaultsNote? }),id 文法 /^[a-z][a-z0-9-]*$/、prefix 文法 /^[a-z][a-z0-9]*$/,工厂期校验形状与文法,配置期校验集合唯一性(每个 id 一条、每个 prefix 一个 channel——两个 channel 共用 myco: 命名空间为命名启动错误)。channel 的条目以 prefix:name 键并入工件(如 myco:pulse、magecdn:clock、sam:tail-spin)。合并顺序:内置清单 → channel(注册序)→ flat 记录;同名全名键后者覆盖(图标覆盖法则)。
来源仍为内联 svg 字符串或 { file } 文件引用;全名文法扩展为 flat(/^[a-z0-9][a-z0-9-]*$/,数字开头合法)或 prefix:name,因此 flat 记录也能以 myco:pulse 键显式覆盖 channel 条目。生成的 SpinName 联合随工件收口——拼错名字是编译错误。组件零改动:带命名空间的名字是联合中的普通字符串。
import { jixoai, defineSpinnerChannel } from '@jixoai/ui-vite-plugin';
import { magecdn } from '@jixoai/ui-vite-plugin/spinners/magecdn';
import { sam } from '@jixoai/ui-vite-plugin/spinners/svg-loaders';
export default defineConfig({
plugins: [
jixoai({
spinners: {
channels: [
// 自有 channel:条目以 myco:… 并入
defineSpinnerChannel({
id: 'myco',
prefix: 'myco',
spinners: {
cadence: '<svg …>…</svg>', // 内联字面量
'wave-loader': { file: './src/loaders/wave.svg' }, // {file} 引用
},
}),
// pack 的 channel 形式:pick 为过滤器(94 枚中选取)
magecdn({ pick: ['clock', 'bars-scale'] }),
// SamHerbert 的 12 枚,sam: 前缀
sam(),
],
spinners: {
'flat-loader': { file: './src/loaders/flat.svg' }, // flat 车道照旧
'myco:cadence': '<svg …>…</svg>', // 同全名覆盖 channel 条目
},
},
}),
],
});
// 重新生成产物:npm run gen:spins
// <Spin spinner="myco:cadence" />、<Spin spinner="magecdn:clock" />、
// <Spin spinner="sam:tail-spin" /> 均进入类型联合
随包提供两个 pack 子入口:@jixoai/ui-vite-plugin/spinners/magecdn(94 枚,逐枚验证)与 @jixoai/ui-vite-plugin/spinners/svg-loaders(SamHerbert 的 12 枚,MIT,上游致谢)。每个子入口同时提供两种接法——spread 车道(magecdnSpinners Record,按名展开、同名按展开顺序覆盖,0.4.0 起不变)与 channel 工厂(magecdn({ pick? }) / sam({ pick? }))。本站文档页的 docs:cadence 即经 channel 车道接入的实渲染示例。

其他变更
图标基线:a0a512e9 新增 gripVertical 为第 39 枚内置图标,但未更新冻结期望,main 上遗留 14 个测试失败。本版本重录全部相关期望,插件套件首次全绿(0.5.0 时 489/489;channel 电池加入后 0.5.1 为 510/510);verify:all 通过。
游乐场控件:新增 PlayTiming(auto | custom 分段控件 + 门控数字输入);PlaySegmented 补充
bind:通道;PlayNumber 改为事件驱动提交,修复输入值被陈旧重同步回退的问题(输入 32 被回退为 16)。密度标尺:
--jx-text/--jx-icon作为 spin 尺寸的默认值来源。其余 12 个 fix 为走查过程中的修复。
升级
无破坏性变更:
npx jixoai-ui@latest add spin
已有工程执行 npx jixoai-ui@latest upgrade。
链接
Changelog:GitHub Release v0.5.1 · compare v0.4.0...v0.5.1
文档与 registry:ui.jixoai.com · spin 文档页 · README
契约来源:spin-ora-svg-lane 提案
本站系列:Jixoai UI v0.4.0 · Jixoai UI v0.3.0
English version: /blog/2026-09-13-ui-0-5-0/
