@ cssints/ 机器
用于 UI 协议的最小、无依赖、无类型安全的状态机器: 动画披露, 打开的菜单 盘旋并关闭在 休眠的假期, 敬酒 逆转中飞行.
信号控制状态,不是协议 组件动画的一瞬间,协议出现:a closing 还有一个
opening ; 已取消的动画仍然点出其完成; 中断的关闭必须倒转
从盒子所在的地方 pointerenter编号 :pointerleave 不得产生五种效果
吞下最后一个意图。 这些都无法作为信号表达。 这个软件包是运行时间的一半:最小的
可以驱动这些协议的机器, 和一种没有浏览器就能证明这些协议的管子.
无依取相. 核心是平版Script(它通过节点的类型去除:没有enums,没有命名空间,没有)
参数属性; @cssints/machine/solid 是唯一一个导入任何文件的文件,以及 solid-js 它是可选的
鼠标.
动画披露
import { createMachine, defineMachine } from "@cssints/machine";
type Events = { open: undefined; close: undefined; finish: { id: number } };
const disclosure = defineMachine<Events>()({
start: "closed",
initial: { progress: 0 },
states: {
closed: {
on: { open: { target: "opening", effect: { type: "animate", to: "open" } } },
},
opening: {
on: {
finish: "open",
close: { target: "closing", effect: { type: "animate", to: "closed" } },
},
after: { 400: "open" }, // an animation that never reports back still ends: no state is a trap
},
open: {
on: {
close: { target: "closing", effect: { type: "animate", to: "closed" } },
tick: {
target: "open",
assign: (context, event) => ({
progress: event.type === "tick" ? event.value : context.progress,
}),
},
},
},
closing: {
on: {
finish: "closed",
open: { target: "opening", effect: { type: "animate", to: "open" } },
},
after: { 400: "closed" },
},
},
});
const machine = createMachine(disclosure);
// The host runs the effects; the machine holds one handle per effect and cancels it when the state is left.
machine.onEffect((handle) => {
const animation = box.animate(keyframes[handle.spec.to], { duration: 200 });
animation.finished.then(() => machine.send({ type: "finish", id: handle.id }));
});
button.addEventListener("click", () => {
machine.send(machine.getState().state === "closed" ? { type: "open" } : { type: "close" });
});
5个地产
- 由开口倒转而结束的关闭中断. 脱离短暂状态的过渡 就像 任何其它;反向效果取代了收尾效果.
- 被取消的动画完成被忽略. A 类
finish携带寄存器所给出的手柄 ID。 离开 州取消手柄,所以晚到的完成会被扭曲并丢弃,不适用于新州. - 一个框架的两个事件每个状态最多产生一个效果. 每次过渡都会取消状态的控件 离开; 主机只运行最后的意向 .
- 被解除的爆裂产生一种效果,具有最后的意向.
send(event, { debounce })(或机器一级)debounce地图)按事件类型组合;flush(){\fn黑体\fs22\bord1\shad0\3ahbe\4ah00\fscx67\fscy66\2chffffff\3ch808080}最终的意向,cancel()丢弃一个被取代的. - 没有什么是永远卡住. 每个州都有出口;
after是一种从不报告的后果的倒置.
API 密码
| 成员 | 它会做什么 |
|---|---|
defineMachine(config) | 定义 : { initial, states, start?, debounce? }事件是工会 on 键,从 initial;没有状态接受的事件是类型错误. |
defineMachine<Payloads>()(config) | 与打出的有效载荷相同: { close: undefined; finish: { id: number } }警卫或 assign 缩入 event.type。 。 。 . |
createMachine(definition, options?) | 一个例子。 选项 : clock, (中文(简体) ), autoStart, (中文(简体) ), onEffect, (中文(简体) ), onCancel, (中文(简体) ), onTransition。 。 。 . |
machine.getState() | { state, context };每个转换时新对象,旧对象仍可读取. |
machine.subscribe(listener) | 每一个过渡和每分出一分. |
machine.subscribe(selector, listener) | 只有改变 selector' 值 (e)Object.is),商店桥 一个主机读取一个切片. |
machine.send(event, { debounce? }) | 现在就交货,或者安排一个连结交货. |
machine.flush() 编号 : machine.cancel(type?) | 瞷祇瞷 瞷 斌. |
machine.effects() | 活柄:已发,未完成,未取消. |
machine.onEffect 编号 : onCancel 编号 : onTransition | 宿主侧:跑出一出效果,停止,观察一出送出. |
machine.start() 编号 : machine.destroy() | 输入起始状态( 参数) / 清除每个计时器, 取消每个手柄, 丢弃每个收听器 . |
harness(definition) | 假钟上的机器: advance(ms),队列(enqueue, (中文(简体) ), deliver, (中文(简体) ), deliverAll, (中文(简体) ), race, (中文(简体) ), interleave, (中文(简体) ), flushEffects现场直播 cancelled() 编号和编号 log。 。 。 . |
过渡是一个目标字符串(open: "opening")或(或) { target, guard?, effect?, assign? }; 一个州的 on 值为 1
过渡或名单, 第一个其警卫通过. after 映射 ms 到一个过渡; 离开状态清除计时器.
assign 是一个 Partial<context> 或者说 (context, event) => Partial<context>。 。 。 .
效果和手柄
效果是数据,而不是回调 : { type: "animate", to: "open", duration: 200 }该机器发行a 控件
(单位:千美元){ id, type, spec, state }对于州条目或过渡声明的每一项效果,当州为时取消
左侧或过渡取代它。 完成事件是指任何带有数字的事件 id: 已丢弃了 stale id(和
登录为 cancelled),活人完成手柄而无需取消. effects() 应该是主机
现在运行.
超过州命的效应被取消;宿主停止(onCancel)及其延迟完成
无法移动机器 .
时钟
createMachine(definition, { clock }) 带 { now(), setTimeout(callback, ms), clearTimeout(handle) }; 默认为
systemClock。同一时钟驱动器 after,解跳和过渡的时间戳, 所以测试驱动时间与
advance(ms) 和主机使用实时.
绳子
import { harness } from "@cssints/machine";
const h = harness(disclosure);
h.send({ type: "open" });
const animation = h.machine.effects().at(-1);
h.send({ type: "close" }); // the open's animation is cancelled, the close's is issued
h.send({ type: "finish", id: animation.id }); // stale: ignored
assert.equal(h.machine.getState().state, "closing");
h.advance(400); // the `after` fallback settles it
assert.equal(h.machine.getState().state, "closed");
h.log 每交付一行(及其发布的一行效果): { at, event, from, to, effect, context, cancelled }。 。 。 .
h.race(...events) 在一个瞬间传递一个帧的事件; h.interleave(...sequences) 圆相罗宾数令.
h.flushEffects() 返回当前主机要运行的控点,而不是在同一框架中已经取消的控点.
实心桥
@cssints/machine/solid (solid-js是同级)将机器曝光为Solid的存储层:
import { createMachineStore } from "@cssints/machine/solid";
const store = createMachineStore(machine, {
settled: (phase) => phase === "open" || phase === "closed",
intent: (event) =>
event.type === "close" ? "closed" : event.type === "open" ? "open" : undefined,
});
const view = store.projection(
(draft, from) => {
draft.visible = from.phase !== "closed";
},
{ visible: false },
);
store.state是一个createStore联 合 国{ ...context, phase },每个转换时一个设置调用,只写字段 改变了:state.phase仅在时不重运行progress变化.store.optimistic是同一字段的第二个商店:state,而意向书写它的阶段 向上飞去。 过渡一到解决阶段,铅就会被丢弃,因此,观点恢复到 刻不容缓的快照——这一意图在完成前被取而代之,而不是坚持下去.store.projection(compute, seed)是一个createProjection结束state:只有已改变的字段通知,所以读取view.visible不重运行当progress变化。 预测读取承诺的框架,而不是乐观 超接( Solid holds the overer),因此视相被读取optimistic直接说.store.send(event)是机器的发送与乐观的引导;发送到机器上直接跳过.
一个 setState 每一次过渡都是同样的原子性 反应性运行时间从一次冲出
(单位:千美元)packages/reactive/src/runtime.ts, (中文(简体) ), packages/apg-specs/specs/patterns/reactive.qnt:读者从未看到从
一个转变,一个进步.
限制
- 相克一州:无相克相克相克相克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克克 两个独立的协议 区域是两台机器,是寄给两者的主机.
- 效果是数据,由主机运行;机器不等待承诺,拥有动画或调用回调.
一个从未到达的完成由
after(或由取消的东道主). - 数字
id在事件上保留一个效果控点:一个带有 stale id 的事件被丢弃. - 按事件类型排列的解跳组合;同一事件类型的两个不同来源共享一个待决意图.
- 商店桥的乐观取向只取自一个固定阶段(协调员的)
settled);新的意图 过渡的中间卷起以前的铅,而不是叠起第二个铅. - 这个运行时间还没有昆特谱; 绳子的五个属性是神谕(
test/machine.mjs) (中文(简体) ).
测试
cd packages/machine && bun run test # node test/machine.mjs, then node test/store.mjs (Solid's client build)
cd packages/machine && bun run typecheck # src and test/types (the @ts-expect-error cases)
仓库测试在纯节点运行 --conditions=browser --conditions=development索利德的店层不需要DOM,
但节点默认是SSR构建,商店的客户端交易不在此地活. 包裹 test 脚本
带着旗帜.