@charcuterie/logic
5个 Charcuterie 状态类型, 作为无框架核心与 React 19 和 Preact
装订。 没有组成部分——这些组成部分是: @charcuterie/ui (M3级).
@charcuterie/logic React 19 binding (default entry)
@charcuterie/logic/core framework-free factories, zero dependencies
@charcuterie/logic/preact Preact binding (no preact/compat)
@charcuterie/logic/jotai optional store adapter
@charcuterie/logic/signals optional store adapter
@charcuterie/logic/query request/response data layer (TanStack Query)
@charcuterie/logic/openapi the typed HTTP seam, for a backend with an OpenAPI spec
@charcuterie/logic/query ——数据层
分舰队获取的方法之一: TanStack 查询缓存,默认为2 应用程序在它存在之前就已经调了.
import { QueryProvider } from "@charcuterie/logic/query"
import {
createApiClient,
createApiHooks,
} from "@charcuterie/logic/openapi"
import type { paths } from "./__generated__/api.gen.ts"
const fetchClient = createApiClient<paths>({ baseUrl: "/" })
export const api = createApiHooks(fetchClient)
const App = () => (
<QueryProvider>
<Jobs />
</QueryProvider>
)
const Jobs = () => {
// path, params, and response are all typed off the OpenAPI spec:
const { data } = api.useQuery("get", "/jobs")
return <JobList jobs={data ?? []} />
}
createQueryClient 保持反应-凯里自己的默认—— 继续尝试这样
层从一瞬间发光中恢复出来 深层会覆盖 A 类
希望申请失败的投票程序 没有 重试( 因为返回会
保留屏幕上的陈旧数据) 明确选择退出 :
createQueryClient({ defaultOptions: { queries: { retry: false } } }) - 电话
夹克和棋盘游戏。 三个图书馆都是 选项 同行,以及
两个子路径选择不同的路径: ./query 仅需要
@tanstack/react-query,以及 ./openapi 添加 openapi-fetch + 键
openapi-react-query。不导入 OpenAPI 文件的应用程序 ./query 一个人
并安装两个 为什么他们分开
子路径。 。 。 .
这个 paths 类型来自后端的 OpenAPI 文档
openapi-typescript a. 与《公约》 .gen.ts 文档 Biome 和 ESLint
忽略——见 生成的系统
决定。 。 。 .
这是 请求/答复 层; RxJS 推动 层 (SSE/ WebSocket)
是单独的,未来的 @charcuterie/streams。 。 。 .
这五种
| 仁爱 | 问它答案 | 用于 |
|---|---|---|
createVisibility | 显示了吗? | Modal、 Drawer、 Popover、 工具提示、 披露 |
createVisibilityGroup | 哪个 一个 显示吗 ? | 标签 协议 一个菜单的子菜单 |
createSinglePicker | 哪个 一个 被选中了吗? | 无线电、 选择、 分区控制 |
createMultiplePicker | 哪个 设定 被选中了吗? | 复选框组,多选择过滤器 |
createRovingFocus | 哪个是 选项卡? 吗? | 列表框、菜单、工具栏、标签列表 |
createStatus | 在哪个地方 生命周期? 吗? | 徽章、生活状况指示器、进步栏 |
后两个在v2中为新;参见
五种状态的决定。 。 。 .
createLinkedIds 与众同坐 aria-controls 编号 : aria-labelledby
簿记——它没有出现用户状态,所以它不是第六种.
useFlipList 也不是那种东西
它完全没有状态。 它在承诺前读出布局 之后又读出 以变换方式回放差异——所以没有核心,没有商店,也没有预告 双胞胎保持步入正轨。 它住在反应入口 因为那里是它的两分之一 (渲染相测量,布局效果)必须坐.
const listRef = useFlipList({ signature: ids.join(",") })
<ul ref={listRef}>
{ids.map((id) => <li data-flip-key={id} key={id}>…</li>)}
</ul>
两个应用程序独立地发展了它——队列飞行员的海报网格和Docket的相位
列表——这是它属于这里而不是属于其中任何一个的门槛.
时间和放松来自 --duration-normal 编号 : --easing-standard,所以重排顺序
移动的速度与周围的一切一样 prefers-reduced-motion 已经
已处理: @charcuterie/tokens 崩溃每个持续时间 0ms 里面的查询,和
钩子在零时提前返回.
形状
每个核心 { getState, subscribe, ...commands } 加纯选择器 :
import {
createVisibilityGroup,
selectIsKeyVisible,
} from "@charcuterie/logic/core"
const tabs = createVisibilityGroup()
const release = tabs.register("overview")
tabs.show("overview")
selectIsKeyVisible(tabs.getState(), "overview") // true
getState() 返回 a 只有在状态改变时其身份才会改变的被冻结对象。 。 。 .
这是负载的,而不是家务 useSyncExternalStore 重新放弃身份,所以
一个在每一个读数上重建其派生数组的核心将重新发送一个完整的列表框
- 在预告装订中,循环.
React and Preact 钩子将它固定在一个物体上:
const { register, show, visibleKey } = useVisibilityGroup()
他们是 无控制数字 : visibleKey 是一个初始值,并且 onChange 这是
观察出逃舱门 见
不受控制的决定。 。 。 .
意向,注册,什么掉下来
四家会员店 消费者要求的 并引导公众 回答 + 谁是当前挂载的 。 三个属性自由:
- 成员挂起前设定的值不丢失 . 它停在
pendingKey编号 :pendingValue(s)在登记时得到促进——这就是: 表单的初始值在选项中幸存. - 复挂圆通. 严格模式的双挂载, 路由更改, 虚拟化列表 卷出一行又一行——意向从未被抛弃,故复出 选中 .
- 众生无常者从代表入正. "最能见者"为一地.
" (中文(简体) )
selectedValue总是注册的选项或null"是引出,不是规则六 命令必须记住.
登记为a 多集组合而不是一组。 两样东西都登记在同一个密钥上 而不是你猜想的,以一个平地,第一座升起的升起 生还者.
createRovingFocus 故意打破对称性:
重点 成员移动焦点在邻居身上,而不是停车,因为键盘
用户的行已消失 .
存储注射
import { createStoreFromJotai } from "@charcuterie/logic/jotai"
useVisibility({ createStore: createStoreFromJotai(jotaiStore) })
接缝有三名成员—— get, (中文(简体) ), set, (中文(简体) ), subscribe 默认是
20行的可观察参考文献,没有依赖性。 Jotai不是从属关系
存储注入决定。 。 。 .
测试
pnpm vitest run --project logic # cores, node
pnpm vitest run --project logic-dom # React + Preact bindings, chromium
src/conformance/ 持有 一个 基于模型的套件,与五个适配器相对应:
核心,核心过一个乔泰商店,核心过一个 @preact/signals-core 存储, 反应
装有19个 装有Preact的 快检查生成随机命令序列, 应用
每一个都给一个天真的参考模型 和一个真实的东西, 并声称之后 每个 步骤.
DOM 适配器挂载一个主机组件,使 null 重建项目 getState() 从
页:1 最后一次承诺 - 所以一个没有重新交代的绑定 读 stale and the
模型在下一个断言上抓住它.
因为一个不能失败的绿色套房
| 故意回归 | 结果 |
|---|---|
多集 −平原 Set 内 registrations.ts | 15个核心属性失效 |
预录 useStoreValue 停止签名 | 10 事前属性失败, 不受影响 |
沙盒纸条. 这个
logic-dom项目需要铬建造。 代理集装箱 船舶浏览器 拥有 全球设置的 Playwright 属于根主/opt/pw-browsers和点PLAYWRIGHT_BROWSERS_PATH在这里。 截止2026-08-24年 目录持有铬 第1234条 这回波的剧作家想要 第1234条,所以运行 双方同意 巧合而来而不是设计。 双方 以自己的时间表行动, 舰队中的两个重机已经不同意.当运行结束, 命名一个未在其中的建筑编号
/opt/pw-browsers,安装此选项 repo的建筑在可写的地方,而不是改变repo:PLAYWRIGHT_BROWSERS_PATH=/tmp/pw-browsers pnpm playwright install chromium-headless-shell PLAYWRIGHT_BROWSERS_PATH=/tmp/pw-browsers pnpm vitest run --project logic-dom
/tmp没有$HOME/.cache/ms-playwright——M2推荐这条路径,甚至是错误的 那麽.--dry-run在安装打印上不下载精确的修订版.⚠️ 永远不要碰这个包的 Playwright 来匹配容器,从不编辑
vitest.browser.config.ts对于它。 被绑定的版本是 CI 安装什么 和什么 符合性套间对照衡量 从不报告浏览器套件无法运行 - 它运行的很好 在覆盖下; 说你使用了它。 长版本 :docs/runbooks/agent-sandbox-runtime.md输入agentic工作空间.
什么是故意不在这里
浮起定位、抛出层、焦点陷阱、打字头、虚拟化和日期
逻辑 他们抵达M4 @floating-ui/react,这是 施工控制 —— 说
你通过状态, 它从来没有存储它,所以 VisibilityGroup 保持独主。 拉迪克丝,
Base UI 和 Ark UI 都拥有 open 本身,这就是冲突 包存在到
避开.
优先布局
selectPriorityLayout 从 @charcuterie/logic/core 比较测量布局
候选人。 每节宣布一个数字 priority,分配数 width 财务报告和审定财务报表
height,可选最小维度,以及可选介质 aspectRatio。 。 。 .
所需内容首先适合;然后在降级时尽量扩大有用区域
优先秩序. idealArea 一旦区域有足够的空间,它就会盖上。 候选人
命令断开联系。 该功能是框架独立的; apps 拥有它们
测量、内容和渲染.
可选章节声明单独的数值 visibilityPriority 和候选人
可能标记它们 isHidden可见内容必须首先符合其最小维度.
在合适的候选人中,较高可见度的优先事项比较低者优先;
焦点 priority 然后用剩下的空间。 隐藏可选段落被消耗
没有最小的维度,也没有有用的领域。 奥米 visibilityPriority
用于控制等必要部分。 Apps列举了测量可见度状态;
选择者从不更改候选人或默片内容.
图表
@charcuterie/logic/charts 曝光共享的 TanStack 图表定义和独立的 SVG 渲染器 . /charts/react 财务报告和审定财务报表 /charts/preact 曝光 ChartPlot 用于本地框架表面,具有共性 ChartOptions,徘徊/touch/键盘交互,以及可选的减动-意识过渡. TanStack在α时被钉入0.1.8. 导入核心或已存在的绑定不会加载此引擎.
现有 renderChartSvg 内 /core 仍然是受限制客户的可移动倒数。 两个引擎都接受分组条,签名堆栈(barLayout: "stacked"、线条和无效样本。 诺尔是没有的,从零。 Apps 供应序列和标签; 没有引擎执行请求或计算报告数据.
压缩便携式图表预览
renderChartSvg 接受 isSparkline: true 中长期可见的小趋势
限制显示 。 通过预览 width 财务报告和审定财务报表 height; SVG 伸展
输入其容器时没有轴标签或密集点标记。 缺失值
仍然断线, 孤立的观测仍然可见, 负值仍然存在
在域中,标题和描述仍可访问。 完整图表保存
它们的默认演示文稿。 互动图外观继续渲染
详细情况; isSparkline 适用于便携式渲染器.