@canonical/react-ds-global-form

中文文档
0.45.0发布于 2026/10/23LGPL-3.0TypeScriptES Module构建来源已验证近 30 天下载 7734

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

中文使用文档
文档目录17 节
  1. 先决条件
  2. 安装
  3. CSS 组件如何到达页面
  4. 每个样式表都在 ds.components.global
  5. 拥有他们制作的原生人的盒子
  6. 过渡读取运动符号
  7. 依赖关系
  8. 使用量
  9. 窗体模式
  10. 字段切换模式
  11. 自定义字段
  12. 独立输入
  13. 中间软件模式
  14. 内置中件
  15. 有条件显示
  16. 故事书
  17. 构成部分规格

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

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

先决条件

  • 反应19或以上

安装

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

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

import "@canonical/styles";

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

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

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个——用一个级联层包裹:

@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 用于输入:

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 提交 , 共享状态,或多步骤形式.

    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 (单位:千美元)^7.71: 审定规则(registerProps, (中文(简体) ), formState字段 数组,和计数解析器都是RHF的API. 见 开始 指南 在童话书中, 完整地走过 与可运行的例子 反应- hook-form 文件 整个地表.

字段切换模式

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

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

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

自定义字段

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

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> 自己来的.

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 道具 :

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

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

内置中件

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

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

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

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

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

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

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

有条件显示

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

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

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

故事书

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

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

构成部分规格

表格组件规格定义载于 设计系统本体学。 。 。 .

版本与发布记录

@canonical/react-ds-global-form 共发布 38 个版本,首次发布于 2026/01/18;过去 12 个月发布了 38 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.45.0latest2026/10/2317 天前
0.44.12026/10/081 个月前
0.44.02026/10/051 个月前
0.43.02026/10/011 个月前
0.42.02026/09/281 个月前
0.40.02026/09/211 个月前

关于 @canonical/react-ds-global-form 的常见问题

@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 和提交记录判断。