# @canonical/react-ds-global-form 中文文档

规范地址：https://npmcn.com/package/%40canonical/react-ds-global-form/

版本：0\.45\.0
npm 元数据更新时间：2026-10-23T01:47:28.375Z
中文译文更新时间：2026-11-09T01:35:08.921Z
软件包许可：LGPL-3\.0

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

原始 npm 页面：https://www.npmjs.com/package/%40canonical/react-ds-global-form
原文对照：https://npmcn.com/package/%40canonical/react-ds-global-form/?lang=original
项目主页：https://github.com/canonical/pragma-web#readme
源码仓库：https://github.com/canonical/pragma-web

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

- 包体积（解压后）：1 MB，851 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：9 个
- 首次发布：2026-01-18T11:36:05.172Z
- 最新版本发布：2026-10-23T01:47:27.998Z
- 近 30 天下载量：7734（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：38（近 12 个月 38 个）

## 中文简介

Pragma设计系统的形式组件. 这个软件包提供了一个基于反应-hook-form的字段系统,它有两种核心模式:一个用于渲染不同输入类型并用于扩展字段行为的字段切换.

## 安装

```sh
npm install @canonical/react-ds-global-form
```

也可以使用：`pnpm add @canonical/react-ds-global-form`、`yarn add @canonical/react-ds-global-form`、`bun add @canonical/react-ds-global-form`

## README

# @ canonical/ react-ds- global-form (英语)

Pragma设计系统的形式组件. 这个软件包提供了一个基于反应-hook-form的字段系统,它有两种核心模式:一个用于渲染不同输入类型并用于扩展字段行为的字段切换.

## 先决条件

-   反应19或以上

## 安装

```bash
bun add @canonical/react-ds-global-form @canonical/styles
```

导入设计系统的样式 **第一个** 在应用程序条目中,在进口部件之前:

```ts
import "@canonical/styles";
```

或者,从样式表: `@import url("@canonical/styles");`。 。 。 .

每个组件在导入时都会带出自己的样式表。 软件包样式表(字段布局、输入铬、窗体符号)不是由任何组件导入的,所以在样式之后直接导入:

```ts
import "@canonical/react-ds-global-form/dist/esm/index.css";
```

### CSS 组件如何到达页面

这个软件包将CSS放在了两条路的页面上. `dist/esm/index.css` —— 导入上方的文件片段—— 是软件包级别样式表: `--form-*` 符号块、字段网格、共享输入铬和 `density.css`,使每个控件大小达到根上下文和密度单元格。 每个组件模块然后自导自出样式表(`import "./styles.css"`),所以导入一个组件就是将该组件的CSS放入页面;一个捆绑器将这些进口物收集到应用程序的CSS中. 这里没有在运行时间注入, 和组件 你从来没有进口船只 没有CSS.

后果是,捆绑者碰巧发出这些被单的指令并不是你能够依赖的,这就是下面的级联层的目的.

### 每个样式表都在 `ds.components.global`

每个样式表下 `src/` - 包项, `density.css`,29个组件表和密度示例,共32个——用一个级联层包裹:

```css
@layer ds.components.global {
  .ds.field-label {
    /* … */
  }
}
```

`@canonical/styles` 在一个语句中宣布每层的顺序 `ds.components.global` 坐于其上相近相. 二事随顺.

`ds.components.app`上面一层是应用层 `@canonical/react-ds-app-lxd` 他们的兄弟姐妹。 还没有一个被包起来( 在撰写时, 没有样式表 ) `packages/react/ds-app-*` 内装一层; 正在将它们与这个包件一起包装。 今天,一个应用级仍然比这个软件包好,原因恰恰相反——它是无层的,无层的节拍分层. 一旦这些软件包落地,层层保证的是,一个字段的应用级规则或一个输入,这个软件包也用级联层来取胜,而不是用装载器最后释放的哪个捆绑来取胜.

父层 `ds.components` 位于两层之上,而不是两层之间: 直接写入其中的一条规则 落在这层隐含的底层中, 它的分数超过了它下面的每一个被命名的底层。 因此,没有普拉克马船 直接写入 `ds.components` ——布局预设于 `src/index.css` 以前是,在孤独 `@layer ds.components` 块,它们现在像其他东西一样 被装在这个包里.

申请本身 **无层** CSS现在击败了这个软件包中的每一个规则,无论哪一边的选取者,因为没有层次的作者规则排在每层的分数后. 这是CSS按照设计工作,这是故意逃出舱门:一个需要覆盖窗体控件的应用程序会写出一个简单的规则,它会获胜。 实际的应用程序 _没有_ 无意中取胜,让CSS进入 `@layer app`。 。 。 .

**捐助者规则:** 每个样式表下 `src/` 用包装打开. `@keyframes` 和软件包本身 `:root` 默认值会进入其中; `@property` 财务报告和审定财务报表 `@font-face` 登记在区块上方。 最后一个是惯例,而不是级联力:用Chromium 151测量,两个共享一个名字的注册完全按照风格规则排序——一个在更高层的胜者无论来源顺序如何,一个无层次的胜者胜出一个分层的 `@property`, (中文(简体) ), `@font-face` 财务报告和审定财务报表 `@keyframes` 一样。 将登记保留在区块上方是他们读成的全文件权威,并把它们放在某个人查查登记的名字会找到的地方。 一个 `@import` 也保留在块上方——进口只有在其他规则之前有效——而且需要 `layer(ds.components.global)` 关键词 _仅限_ 当工作表没有被包起来时; `src/index.css` 进口 `density.css` 裸体,因为 `density.css` 声明层本身,关键词将嵌入声明 `ds.components.global.ds.components.global`,一个会输给 `index.css`自己的规矩 永远无法到达 `!important` 以赢得争斗——一项重要宣言颠倒了地层秩序,完全不能被地层仲裁. 这个 `@canonical/styles` README"卡斯卡德地层"部分是全序和被故意留下的未分层的参考. 一个例外是 `.storybook/styles.css`,这是故意的外面 `src/`:这是《故事书》的用具,而不是包的一部分——从未出版(`files: ["dist"]`,然后在预览页中添加一个 `.rtl` 工具 —— 保持未分层是它能够覆盖预览的内容 .

### 拥有他们制作的原生人的盒子

这个软件包使本地元素比其他任何元素都多: `<input>` 有十几类, `<select>`, (中文(简体) ), `<textarea>`, (中文(简体) ), `<label>`, (中文(简体) ), `<legend>`, (中文(简体) ), `<fieldset>`, (中文(简体) ), `<button>`构成原生元素的组件负责该元素的框-其边距、宽度、宽度、宽度、宽度 `min-width`页:1 `box-sizing` 用于 `::placeholder` 用于提供文本输入。 任何未申报的组件,都由主机页面加载的其他内容填入,并在同样运行另一个框架的页面上填入,这个框架是可见的bug而不是默认. 宣布这个盒子是做它自己的改变;在它着陆之前,把"控制在我们自己的页面上看对了"视为比听起来更弱的保证.

本软件包门户中没有任何内容: 否 `createPortal`,没有 `appendChild`,没有 `<dialog>`. 逃避集装箱的两个表面——组合框清单(`ComboboxInput/common/List/List.tsx:42`)和取色器的监视面板(`ColorInput/ColorInput.tsx:198`)——使用"波波弗"API,将一个元素推广到上层进行绘画,但将其留在了DOM中的位置. 所以他们留在里面 `.ds` 树的呼号 和元素层 `@canonical/styles` 潜入树下的地方仍然有.

### 过渡读取运动符号

本一揽子方案中的每一个过渡都从 `--motion-duration-fast`三个期限标志的快步 `@canonical/styles` 永远不要从字面上说出来。 这不是一个平庸的规则。 下 `prefers-reduced-motion: reduce` 样式软件包将所有三个期限符号设置为 `0s`,零化是pragma的减动机制:一个组件本身 `transition` 宣言保持其在级联中的位置,只是一意孤行。 硬码持续时间对于它来说是隐形的,并且为要求其系统不要的读者保持动画. 这是代码标准 `cs:css.properties.values` ("设计活值的标志") 有牙齿在上面.

**捐助者规则:** a 没有字面持续时间 `transition` 或一个 `animation`新的一个读出一个符号 一个赤裸的 `0s` 只有一个例外,因为它已经说"没有运动"。 象征他们自己生活 `@canonical/styles` (单位:千美元)`motion.css`;如果一个控制需要一个步骤,则三个步骤不提供,则该步骤将添加在那里,而不是写入一个组件。 减肥是例外,是故意的: `ease` 这里,而不是 `var(--motion-easing-standard)`,因为那个标志是 `ease-out` 换掉是第二个改变 控制的感觉, 它骑着PRA-153 和缺失的子`fast` 持续时间.

## 依赖关系

表格系统以两个主要库为基础:

-   **反应- hook-form** - 实行国家管理、验证和实地登记。 这个 `Field` 组件用途 `useFormContext` 内部,所以形式必须用 `FormProvider`。 。 。 .
-   **下调** - 给组合框域提供可访问的自动完成行为.

## 使用量

将表格包装为 `Form` 组件和使用 `Field` 用于输入:

```tsx
import { Form, Field } from "@canonical/react-ds-global-form";

function ContactForm() {
  const onSubmit = (data) => console.log(data);

  return (
    <Form onSubmit={onSubmit}>
      <Field
        name="email"
        inputType="email"
        label="Email address"
        description="We'll never share your email."
      />
      <Field
        name="message"
        inputType="textarea"
        label="Message"
      />
      <button type="submit">Send</button>
    </Form>
  );
}
```

### 窗体模式

`Form` 将孩子包裹在反应上 `FormProvider` 并使用两种模式:

-   **内部模式** (以上)——通过 `onSubmit`,可选择 `defaultValues` (单位:千美元) 验证 `mode`· ; `Form` 创建 `useForm` 以你为例 最好的一个 自成形而来.
    
-   **外部模式** - 创建 `useForm` 以你为榜样,通过它作为 `methods`因为你拥有它,你可以读 `formState` (例如:. `isSubmitting`和 调用其方法`reset`, (中文(简体) ), `setValue`, (中文(简体) ), `watch`(中文(简体) ). 用于 Aync 提交 , 共享状态,或多步骤形式.
    
    ```tsx
    import { useForm } from "react-hook-form";
    
    const methods = useForm({ mode: "onBlur", defaultValues: { email: "" } });
    const { reset, formState: { isSubmitting } } = methods;
    
    <Form methods={methods} onSubmit={async (data) => { await save(data); reset(); }}>
      <Field name="email" inputType="email" label="Email" />
      <button type="submit" disabled={isSubmitting}>Send</button>
    </Form>;
    ```
    
    当你通过 `methods`, (中文(简体) ), `Form`属于自己的 `defaultValues`编号 :`mode` 道具被忽略了—— 配置您所显示的 `useForm` 电话.
    

这个图书馆是一层薄薄的 [反应- hook-form](https://react-hook-form.com/) (单位:千美元)`^7.71`: 审定规则(`registerProps`, (中文(简体) ), `formState`字段 数组,和计数解析器都是RHF的API. 见 **开始** 指南 在童话书中, 完整地走过 与可运行的例子 [反应- hook-form 文件](https://react-hook-form.com/docs) 整个地表.

## 字段切换模式

这个 `Field` 组件用途 `inputType` 选择适当的输入组件:

| 输入类型 | 构成部分 | 说明 |
| --- | --- | --- |
| `text`, (中文(简体) ), `email`, (中文(简体) ), `password`, (中文(简体) ), `number`, (中文(简体) ), `tel`, (中文(简体) ), `url` | 文本 | 标准文本输入 |
| `textarea` | 文本区域 | 多行文本 |
| `checkbox` | 复选框 | 布尔切换 |
| `range` | 范围 | 滑动器输入 |
| `select` | 选择 | 下拉选择 |
| `simple-choices` | 简单选择 | 无线电按钮或复选框 |
| `combobox` | 组合框 | 可搜索的下拉 |
| `hidden` | 隐藏 | 隐藏输入 |
| `custom` | 您的组件 | 通过 `CustomComponent` 道具 |

所有字段都被包裹着 `withWrapper`,它提供格式注册,标签,描述,出错显示,以及中间软件支持.

### 自定义字段

对于内置未覆盖的字段类型,使用 `inputType="custom"`数字 :

```tsx
import { Field } from "@canonical/react-ds-global-form";
import { MyColorPicker } from "./MyColorPicker";

<Field
  name="brandColor"
  inputType="custom"
  CustomComponent={MyColorPicker}
  label="Brand Color"
/>
```

自定义组件必须用 `withWrapper`自定义组件必须满足 `InputProps` 键入并整合到反应-hook-form 通过 `useFormContext`。 。 。 .

### 独立输入

字段图案构成的每个输入也单独输出: `TextInput`, (中文(简体) ), `SelectInput`, (中文(简体) ), `CheckboxInput`, (中文(简体) ), `SwitchInput`, (中文(简体) ), `RadioInput`, (中文(简体) ), `NumberInput`, (中文(简体) ), `PasswordInput`, (中文(简体) ), `RangeInput`, (中文(简体) ), `RatingInput`, (中文(简体) ), `DateInput`, (中文(简体) ), `TimeInput`, (中文(简体) ), `DateTimeInput`, (中文(简体) ), `ColorInput`, (中文(简体) ), `ComboboxInput`, (中文(简体) ), `PhoneInput`, (中文(简体) ), `FileUploadInput`, (中文(简体) ), `TextareaInput` 财务报告和审定财务报表 `HiddenInput`,每个都有它的道具类型。 介绍性:否 `<Form>`,没有反应-hook-form上下文和标签,所以表单以外的一个控制保持相同的输入铬. 说吧 `aria-label` 或一个 `<label>` 自己来的.

```tsx
import { SelectInput } from "@canonical/react-ds-global-form";

<SelectInput
  aria-label="Language"
  value={locale}
  onChange={(event) => setLocale(event.target.value)}
  options={[
    { value: "en", label: "English", lang: "en" },
    { value: "fr", label: "français", lang: "fr" },
  ]}
/>
```

一个选项是可选的 `lang` 标记用另一种语言书写的标签,所以辅助技术可以正确宣告它.

## 中间软件模式

Middleware是包接字段来添加功能的更高级的组件. 他们通过 `middleware` 道具 :

```tsx
<Field
  name="country"
  inputType="select"
  label="Country"
  middleware={[addRESTOptions("/api/countries")]}
/>
```

中间软件签名是 `(Component) => Component`。多个中间软件按阵列顺序组成,第一个中间软件是最外层的包装器.

### 内置中件

**添加REST 选项** - 从 API 端点获取选项 :

```tsx
import { addRESTOptions } from "@canonical/react-ds-global-form";

<Field
  name="category"
  inputType="select"
  middleware={[
    addRESTOptions("/api/categories", {
      transformData: (data) => data.categories,
    }),
  ]}
/>
```

**添加RESTV升级** - 用 API 验证字段值:

```tsx
import { addRESTValidation } from "@canonical/react-ds-global-form";

<Field
  name="username"
  inputType="text"
  middleware={[
    addRESTValidation("/api/validate-username", {
      debounceWait: 300,
      minLength: 3,
    }),
  ]}
/>
```

自定义中件遵循相同的工厂模式:一个外函数接受配置并返回一个HOC.

## 有条件显示

字段可以根据其它字段值有条件地渲染:

```tsx
<Field
  name="company"
  inputType="text"
  label="Company"
  condition={[
    ["accountType"],
    ([type]) => type === "business",
  ]}
/>
```

字段只使条件函数返回真实时生效 .

## 故事书

```bash
cd packages/react/ds-global-form
bun run storybook
```

Storybook配置包括MSW集成来模拟后端响应.

## 构成部分规格

表格组件规格定义载于 [设计系统本体学](https://github.com/canonical/pragma-core/tree/main/packages/semantics/design-system)。 。 。 .

## 常见问题

### @canonical/react-ds-global-form 是什么？

Pragma设计系统的形式组件\. 这个软件包提供了一个基于反应-hook-form的字段系统,它有两种核心模式:一个用于渲染不同输入类型并用于扩展字段行为的字段切换\.

### 如何安装 @canonical/react-ds-global-form？

在项目目录运行 npm install @canonical/react-ds-global-form，或使用 pnpm add / yarn add / bun add。

### @canonical/react-ds-global-form 支持 TypeScript 吗？

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

### @canonical/react-ds-global-form 支持 ESM 还是 CommonJS？

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

### @canonical/react-ds-global-form 可以商用吗？

@canonical/react-ds-global-form 使用 LGPL-3\.0 许可。弱 Copyleft：作为库被调用时通常不要求开源你自己的代码，但修改库本身需以 LGPL 开源；前端打包合并后的适用边界存在不同理解。以上为概括，不构成法律意见，请以许可原文为准。

### @canonical/react-ds-global-form 的下载量有多少？

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

### @canonical/react-ds-global-form 还在维护吗？

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

