npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jack-ui/j-form

v0.1.3

Published

Schema-driven React form package built on Ant Design with runtime API, search form, async options, and modal/drawer submit pages.

Readme

@jack-ui/j-form

npm version downloads React Ant Design

English

面向 Ant Design 的 schema 驱动 React 表单系统,统一覆盖:

  • 通用业务表单
  • 查询 / 搜索区表单
  • 异步选项字段
  • 弹窗与抽屉提交页

为什么是 JForm

很多表单体系最终会拆成几块互相割裂的能力:

  • 常规表单一套渲染方式
  • 查询表单再包一层
  • 命令式控制另起一套 API
  • 弹窗 / 抽屉表单再独立实现一次

@jack-ui/j-form 的目标是把这些表面能力压在同一套运行时模型上。

产品能力面

| 能力面 | 最适合解决的问题 | | --- | --- | | JForm | 通用 schema 驱动业务表单 | | JSearchForm | 查询区、折叠区、内联操作区、横向 label | | createJFormApi() / useJForm() | 运行时编排、schema 变更、校验、重置、订阅 | | optionsSource | 防抖、缓存、远程选项加载 | | submit-page | 多步、默认底栏动作、service 打开的弹窗 / 抽屉提交页 |

30 秒开始

安装

pnpm add @jack-ui/j-form antd @ant-design/icons react react-dom

导入样式

import '@jack-ui/j-form/styles.css';
import '@jack-ui/j-form/submit-page/styles.css'; // 只有使用 submit-page 时才需要

渲染一个表单

import '@jack-ui/j-form/styles.css';
import { JForm } from '@jack-ui/j-form';

type ProjectValues = {
  name?: string;
  status?: string;
  budget?: number;
};

export function ProjectForm() {
  return (
    <JForm<ProjectValues>
      gridColumns={2}
      layout="vertical"
      onSubmit={async (values) => {
        console.log(values);
      }}
      schema={[
        { name: 'name', label: '项目名称', required: true },
        {
          name: 'status',
          kind: 'select',
          label: '状态',
          options: [
            { label: '草稿', value: 'draft' },
            { label: '已审批', value: 'approved' },
          ],
        },
        { name: 'budget', kind: 'number', label: '预算' },
      ]}
    />
  );
}

导入入口

核心表单运行时:

import {
  JForm,
  JSearchForm,
  createJFormApi,
  useJForm,
  useJFormSelector,
} from '@jack-ui/j-form';

提交页运行时:

import {
  JFormSubmitPage,
  useJFormSubmitPage,
} from '@jack-ui/j-form/submit-page';

import {
  JFormSubmitPageProvider,
  useJFormSubmitPageService,
} from '@jack-ui/j-form/submit-page/service';

说明:

  • submit-page 运行时代码通过子路径拆分。
  • submit-page 的 TypeScript 类型仍然从 @jack-ui/j-form 根入口导出。
  • 样式不会由 JS 自动注入,必须显式导入。

该选哪一层能力

JForm

通用录入表单使用 JForm

<JForm
  gridColumns={3}
  schema={[
    { name: 'name', label: '名称', required: true },
    { name: 'owner', label: '负责人' },
    { name: 'summary', kind: 'textarea', label: '说明', span: 24 },
  ]}
/>

JSearchForm

查询区场景使用 JSearchForm

它在 JForm 基础上额外提供:

  • 固定查询态
  • 默认横向布局
  • 折叠 / 展开能力
  • 最后一行末尾的内联操作区
  • 隐藏校验字段需要暴露时自动展开
<JSearchForm
  collapsedRows={1}
  gridColumns={4}
  schema={[
    { name: 'keyword', label: '关键字' },
    { name: 'status', kind: 'select', label: '状态' },
    { name: 'city', kind: 'select', label: '城市' },
    { name: 'owner', label: '负责人', required: true },
  ]}
/>

submit-page

当表单放在弹窗或抽屉里时,使用 JFormSubmitPage

import '@jack-ui/j-form/submit-page/styles.css';
import { JFormSubmitPage } from '@jack-ui/j-form/submit-page';

<JFormSubmitPage
  defaultOpen
  mode="drawer"
  drawer={{ width: '60%' }}
  schema={[
    { name: 'name', label: '名称', required: true },
    { name: 'summary', kind: 'textarea', label: '说明' },
  ]}
  title="新建项目"
/>;

运行时控制

useJForm()

在 React 里,如果你需要稳定的 formApi,使用它。

import { JForm, useJForm } from '@jack-ui/j-form';

export function ControlledForm() {
  const formApi = useJForm({
    values: {
      status: 'draft',
    },
  });

  return (
    <JForm
      formApi={formApi}
      schema={[{ name: 'status', label: '状态' }]}
    />
  );
}

createJFormApi()

如果你需要 React 外部的独立运行时控制器,使用它。

import { createJFormApi } from '@jack-ui/j-form';

const formApi = createJFormApi({
  schema: [{ name: 'name', label: '名称' }],
  values: { name: '初始值' },
});

formApi.setFieldValue('name', '更新后的值');
console.log(formApi.getValues());

JFormApi 重点方法

状态和值:

  • setValues(values)
  • replaceValues(values)
  • setFieldValue(name, value)
  • getValues()
  • getFieldValue(name)
  • getSnapshot()
  • subscribe(listener)

Schema:

  • setSchema(schema)
  • getSchema()
  • updateSchema(name, updater)
  • appendSchemaByField(name, fields)
  • removeSchemaByField(name)
  • removeSchemaByFields(names)
  • setVisibleFields(names)

校验与提交:

  • validate(names?)
  • validateResult(names?)
  • validateField(name)
  • validateFieldResult(name)
  • isFieldValid(name)
  • clearErrors(names?)
  • clearValidate(names?)
  • reset()
  • resetForm(values?)
  • submit()
  • submitForm()
  • validateAndSubmitForm()

事件:

  • submit
  • reset
  • lazy-options-start
  • lazy-options-success
  • lazy-options-error
  • lazy-options-end

Schema 模型

常用字段属性

| 属性 | 说明 | | --- | --- | | name | 字段名,支持点路径,例如 user.name | | kind | 内建字段类型 | | label | 表单项标题 | | required | 是否必填 | | rules | Ant Design 校验规则 | | defaultValue | 字段加入时若当前值缺失则应用默认值 | | span | 手动覆盖字段宽度 | | width | 控件显式宽度 | | options | 静态选项 | | optionsSource | 异步选项配置 | | dependsOn | 依赖驱动 hidden / disabled / required / rules / componentProps | | component | 自定义字段组件 | | render | 自定义字段渲染函数 | | componentProps | 透传给控件的 props | | itemProps | 透传给 Form.Item 的 props | | normalize | 值标准化钩子 |

内建字段类型

  • input
  • password
  • textarea
  • select
  • date
  • datetime
  • daterange
  • datetimerange
  • month
  • year
  • time
  • timerange
  • number
  • switch
  • radio
  • radio-button
  • checkbox
  • custom

依赖联动字段

依赖联动可以推导:

  • hidden
  • disabled
  • required
  • rules
  • componentProps
{
  name: 'reviewer',
  label: '审批人',
  dependsOn: {
    watch: ['status'],
    hidden: ({ values }) => values.status !== 'approved',
    required: ({ values }) => values.status === 'approved',
  },
}

自定义字段上下文

自定义 component / render 会拿到:

  • api
  • field
  • values
  • value
  • setValue(value, { rawData })
  • options
  • loading
  • disabled
  • onSearch(keyword)
  • getPopupContainer()

异步选项

optionsSource

支持字段:

  • triggers
  • debounceMs
  • cache
  • cacheMaxEntries
  • cacheTtlMs
  • cacheKey
  • minKeywordLength
  • preserveOnError
  • clearBeforeLoad
  • once
  • mapOptions
  • load(context)
{
  name: 'city',
  kind: 'select',
  label: '城市',
  optionsSource: {
    triggers: ['search'],
    debounceMs: 300,
    cache: true,
    minKeywordLength: 2,
    async load({ keyword, signal }) {
      const response = await fetch(`/api/cities?q=${keyword}`, { signal });
      const data = await response.json();
      return {
        options: data.items,
        raw: data,
      };
    },
  },
}

远程 helper

根入口提供这些 helper:

  • createJFormOptionsSource()
  • createJFormRemoteOptionsSource()
  • createJFormRemoteSearchParams()
  • mapJFormRemoteOptionList()
  • mapJFormTreeOptions()
  • resolveJFormOptionsArray()
import { createJFormRemoteOptionsSource } from '@jack-ui/j-form';

const cityOptionsSource = createJFormRemoteOptionsSource({
  cache: true,
  trigger: 'search',
  async request({ keyword, signal }) {
    const response = await fetch(`/api/cities?q=${keyword}`, { signal });
    return response.json();
  },
});

Submit-page 子系统

submit-page 是一个统一抽象,可以渲染成弹窗或抽屉。

声明式

import { JFormSubmitPage } from '@jack-ui/j-form/submit-page';

<JFormSubmitPage
  defaultOpen
  mode="modal"
  schema={[{ name: 'name', label: '名称', required: true }]}
  title="新建项目"
/>;

Hook

import { Button } from 'antd';
import { useJFormSubmitPage } from '@jack-ui/j-form/submit-page';

export function HookDemo() {
  const { controller, node } = useJFormSubmitPage({
    schema: [{ name: 'name', label: '名称', required: true }],
    title: 'Hook 提交页',
  });

  return (
    <>
      <Button onClick={() => controller.open()}>打开</Button>
      {node}
    </>
  );
}

Service

import { Button } from 'antd';
import {
  JFormSubmitPageProvider,
  useJFormSubmitPageService,
} from '@jack-ui/j-form/submit-page/service';

function Trigger() {
  const service = useJFormSubmitPageService();

  return (
    <Button
      onClick={() => {
        const handle = service.open({
          mode: 'drawer',
          drawer: { width: '60%' },
          schema: [{ name: 'name', label: '名称', required: true }],
          title: 'Service 提交页',
        });

        void handle.closed.then((result) => {
          console.log(result.reason, result.values);
        });
      }}
    >
      打开
    </Button>
  );
}

export function ServiceDemo() {
  return (
    <JFormSubmitPageProvider>
      <Trigger />
    </JFormSubmitPageProvider>
  );
}

Submit-page API 重点

主 props:

  • mode
  • schema
  • steps
  • formApi
  • open / defaultOpen
  • title
  • header
  • footer
  • showStepHeader
  • stepTransitionMs
  • resetOnClose
  • resetOnSubmit
  • beforeClose
  • onCancel
  • onOpenChange
  • onStepChange
  • onSubmitSuccess
  • modal
  • drawer

Footer 行为:

  • 默认底栏按钮会自动构建
  • footer.actions 默认是追加
  • 设置 footer.showDefaultActions = false 可以关闭默认按钮
  • 内建 action 支持 text: null 的图标按钮形式

Controller API:

  • open()
  • close(reason?)
  • toggle(open?)
  • setOpen(open, reason?)
  • getOpen()
  • getStep()
  • getTotalSteps()
  • goToStep(step)
  • next()
  • prev()
  • getFormApi()

Service handle API:

  • id
  • controller
  • formApi
  • update(partialOptions)
  • close(reason?)
  • closed

国际化与主题

文案覆盖

import { JFormConfigProvider } from '@jack-ui/j-form';

const localeText = {
  submit: '保存',
  reset: '清空',
  query: '查询',
  expand: '展开',
  collapse: '收起',
};

export function App() {
  return (
    <JFormConfigProvider localeText={localeText}>
      {/* app */}
    </JFormConfigProvider>
  );
}

主题 token

j-form 会跟随外层 Ant Design token。需要在自定义组件中读取时,可以使用 useJFormTokens()

CSS 策略

  • @jack-ui/j-form/styles.cssJFormJSearchForm 基础样式
  • @jack-ui/j-form/submit-page/styles.css:submit-page 样式
  • 根运行时入口没有隐式样式副作用

相关链接