# @charcuterie/logic 中文文档

规范地址：https://npmcn.com/package/%40charcuterie/logic/

版本：2\.12\.0
npm 元数据更新时间：2026-11-02T05:18:08.577Z
中文译文更新时间：2026-11-09T10:43:42.076Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40charcuterie/logic
原文对照：https://npmcn.com/package/%40charcuterie/logic/?lang=original
项目主页：https://github.com/Sawtaytoes/charcuterie#readme
源码仓库：https://github.com/Sawtaytoes/charcuterie

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：846 kB，388 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：jotai \>=2，react \>=18，preact \>=10\.11，openapi-fetch \>=0\.17，openapi-react-query \>=0\.5，@preact/signals-core \>=1\.8，@tanstack/react-query \>=5
- 首次发布：2026-07-31T04:30:58.657Z
- 最新版本发布：2026-11-02T05:18:08.193Z
- 近 30 天下载量：5835（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：22（近 12 个月 22 个）

## 中文简介

Charcuterie的五种状态类型——能见度,能见度组,单接器,多接器,RovingFocus,和Status——作为带有React和Preact绑定的无框架核心.

## 安装

```sh
npm install @charcuterie/logic
```

也可以使用：`pnpm add @charcuterie/logic`、`yarn add @charcuterie/logic`、`bun add @charcuterie/logic`

## README

# `@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 应用程序在它存在之前就已经调了.

```tsx
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` 一个人 并安装两个 [为什么他们分开 子路径](https://npmcn.com/package/docs/decisions/2026-08-13-the-openapi-seam-is-its-own-subpath-not-part-of-query.md)。 。 。 .

这个 `paths` 类型来自后端的 OpenAPI 文档 `openapi-typescript` a. 与《公约》 `.gen.ts` 文档 Biome 和 ESLint 忽略——见 [生成的系统 决定](https://npmcn.com/package/docs/decisions/2026-08-11-typed-api-calls-via-openapi-typescript-generated-schemas-committed.md)。 。 。 . 这是 **请求/答复** 层; RxJS **推动** 层 (SSE/ WebSocket) 是单独的,未来的 `@charcuterie/streams`。 。 。 .

## 这五种

| 仁爱 | 问它答案 | 用于 |
| --- | --- | --- |
| `createVisibility` | 显示了吗? | Modal、 Drawer、 Popover、 工具提示、 披露 |
| `createVisibilityGroup` | 哪个 **一个** 显示吗 ? | 标签 协议 一个菜单的子菜单 |
| `createSinglePicker` | 哪个 **一个** 被选中了吗? | 无线电、 选择、 分区控制 |
| `createMultiplePicker` | 哪个 **设定** 被选中了吗? | 复选框组,多选择过滤器 |
| `createRovingFocus` | 哪个是 **选项卡**? 吗? | 列表框、菜单、工具栏、标签列表 |
| `createStatus` | 在哪个地方 **生命周期**? 吗? | 徽章、生活状况指示器、进步栏 |

后两个在v2中为新;参见 [五种状态的决定](https://npmcn.com/package/docs/decisions/2026-07-29-five-state-kinds.md)。 。 。 . `createLinkedIds` 与众同坐 `aria-controls` 编号 : `aria-labelledby` 簿记——它没有出现用户状态,所以它不是第六种.

### `useFlipList` 也不是那种东西

它完全没有状态。 它在承诺前读出布局 之后又读出 以变换方式回放差异——所以没有核心,没有商店,也没有预告 双胞胎保持步入正轨。 它住在反应入口 因为那里是它的两分之一 (渲染相测量,布局效果)必须坐.

```tsx
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 }` 加纯选择器 :

```ts
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 钩子将它固定在一个物体上:

```ts
const { register, show, visibleKey } = useVisibilityGroup()
```

他们是 **无控制**数字 : `visibleKey` 是一个初始值,并且 `onChange` 这是 观察出逃舱门 见 [不受控制的决定](https://npmcn.com/package/docs/decisions/2026-07-29-logic-hooks-are-uncontrolled.md)。 。 。 .

## 意向,注册,什么掉下来

四家会员店 _消费者要求的_ 并引导公众 回答 + 谁是当前挂载的 。 三个属性自由:

-   **成员挂起前设定的值不丢失 .** 它停在 `pendingKey`编号 :`pendingValue(s)` 在登记时得到促进——这就是: 表单的初始值在选项中幸存.
-   **复挂圆通.** 严格模式的双挂载, 路由更改, 虚拟化列表 卷出一行又一行——意向从未被抛弃,故复出 选中 .
-   **众生无常者从代表入正.** "最能见者"为一地. " (中文(简体) )`selectedValue` 总是注册的选项或 `null`"是引出,不是规则六 命令必须记住.

登记为a **多集组合**而不是一组。 两样东西都登记在同一个密钥上 而不是你猜想的,以一个平地,第一座升起的升起 生还者.

`createRovingFocus` 故意打破对称性: _重点_ 成员移动焦点在邻居身上,而不是停车,因为键盘 用户的行已消失 .

## 存储注射

```ts
import { createStoreFromJotai } from "@charcuterie/logic/jotai"

useVisibility({ createStore: createStoreFromJotai(jotaiStore) })
```

接缝有三名成员—— `get`, (中文(简体) ), `set`, (中文(简体) ), `subscribe` 默认是 20行的可观察参考文献,没有依赖性。 Jotai不是从属关系 [存储注入决定](https://npmcn.com/package/docs/decisions/2026-07-29-store-injection-not-a-jotai-dependency.md)。 。 。 .

## 测试

```bash
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:
> 
> ```bash
> 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` 适用于便携式渲染器.

## 常见问题

### @charcuterie/logic 是什么？

Charcuterie的五种状态类型——能见度,能见度组,单接器,多接器,RovingFocus,和Status——作为带有React和Preact绑定的无框架核心\.

### 如何安装 @charcuterie/logic？

在项目目录运行 npm install @charcuterie/logic，或使用 pnpm add / yarn add / bun add。

### @charcuterie/logic 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @charcuterie/logic 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @charcuterie/logic 可以商用吗？

@charcuterie/logic 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @charcuterie/logic 的下载量有多少？

根据 npm 官方下载统计，@charcuterie/logic 在 2026/10/10 – 2026/11/08 这 30 天内被下载 5,835 次，日均约 195 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @charcuterie/logic 还在维护吗？

最新版本 2\.12\.0 发布于 2026/11/02（7 天前）；至今共发布 22 个版本，其中过去 12 个月发布了 22 个；首次发布于 2026/07/31。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

