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

react-shadcn-crud-form

v1.0.0

Published

一个基于 shadcn/ui 和 react-hook-form 的现代化 React CRUD 表单组件库,支持动态表单生成、类型安全和全局状态管理

Downloads

10

Readme

🚀 React Shadcn CRUD Form

Version License TypeScript React

一个基于 shadcn/ui 和 react-hook-form 的现代化 React CRUD 表单组件库

支持动态表单生成、类型安全和全局状态管理

文档 · 示例 · API · 贡献


✨ 特性

  • 🎯 类型安全: 完全基于 TypeScript,提供完整的类型推导
  • 🎨 现代化 UI: 基于 shadcn/ui,提供美观的用户界面
  • 🔧 动态表单: 根据 Zod Schema 自动生成表单字段
  • 📱 响应式设计: 适配移动端和桌面端
  • 🎭 自定义渲染: 支持完全自定义的字段渲染器
  • 🌍 全局状态: 提供 Context API 进行全局配置管理
  • 🚀 零配置: 开箱即用,同时支持深度自定义
  • 📦 轻量级: 最小化依赖,性能优先

🛠 前置要求

在安装本组件库之前,请确保您的项目满足以下要求:

基础要求

  • React 17.0.0 或更高版本
  • TypeScript 项目(推荐)
  • 已配置 Tailwind CSS

必需的 Peer Dependencies

本组件库需要以下 peer dependencies,请根据您的包管理器选择安装命令:

# 使用 npm
npm install react react-dom react-hook-form zod @hookform/resolvers @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-label @radix-ui/react-select @radix-ui/react-slot class-variance-authority clsx tailwind-merge

# 使用 yarn  
yarn add react react-dom react-hook-form zod @hookform/resolvers @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-label @radix-ui/react-select @radix-ui/react-slot class-variance-authority clsx tailwind-merge

# 使用 pnpm
pnpm add react react-dom react-hook-form zod @hookform/resolvers @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-label @radix-ui/react-select @radix-ui/react-slot class-variance-authority clsx tailwind-merge

可选依赖

# 如果需要使用图标(推荐)
npm install lucide-react

📦 安装

方法一:使用 shadcn/ui 项目(推荐)

如果您的项目已经使用 shadcn/ui,大部分依赖可能已经安装:

# 1. 确保已安装所需的 shadcn/ui 组件
npx shadcn@latest add button dialog form input textarea select checkbox

# 2. 安装组件库
npm install react-shadcn-crud-form

# 3. 检查并安装缺失的依赖
npm install react-hook-form zod @hookform/resolvers

方法二:全新项目安装

# 1. 安装核心依赖
npm install react-hook-form zod @hookform/resolvers

# 2. 安装 UI 相关依赖
npm install @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-label @radix-ui/react-select @radix-ui/react-slot

# 3. 安装工具库
npm install class-variance-authority clsx tailwind-merge

# 4. 安装图标库(可选)
npm install lucide-react

# 5. 最后安装组件库
npm install react-shadcn-crud-form

依赖版本兼容性

| 依赖包 | 最低版本 | 推荐版本 | 说明 | |--------|----------|----------|------| | react | >=17.0.0 | ^18.0.0+ | React 核心库 | | react-dom | >=17.0.0 | ^18.0.0+ | React DOM | | react-hook-form | ^7.0.0 | ^7.45.0+ | 表单状态管理 | | zod | ^3.0.0 | ^3.20.0+ | Schema 验证 | | @hookform/resolvers | ^5.0.0 | ^5.0.0+ | React Hook Form 解析器 | | class-variance-authority | ^0.7.0 | ^0.7.0+ | CSS 类变体管理 | | clsx | ^2.0.0 | ^2.0.0+ | CSS 类名工具 | | tailwind-merge | ^2.0.0 | ^2.0.0+ | Tailwind 类名合并 | | lucide-react | ^0.400.0 | ^0.400.0+ | 图标库(可选) |

✅ 安装验证

安装完成后,您可以通过以下代码验证安装是否成功:

import { DialogForm, FormProvider } from 'react-shadcn-crud-form';
import { z } from 'zod';

// 如果没有报错,说明安装成功
console.log('✅ react-shadcn-crud-form 安装成功!');

🚀 快速开始

基础用法

import React, { useState } from 'react';
import { DialogForm, FormProvider } from 'react-shadcn-crud-form';
import { z } from 'zod';

// 定义表单 Schema
const userSchema = z.object({
  name: z.string().min(1, '姓名不能为空'),
  email: z.string().email('请输入有效的邮箱地址'),
  age: z.number().min(18, '年龄必须大于18岁'),
  bio: z.string().optional(),
});

function App() {
  const [open, setOpen] = useState(false);

  const handleSubmit = (data: z.infer<typeof userSchema>) => {
    console.log('提交的数据:', data);
    setOpen(false);
  };

  return (
    <FormProvider>
      <button onClick={() => setOpen(true)}>
        创建用户
      </button>
      
      <DialogForm
        title="创建新用户"
        description="请填写用户信息"
        open={open}
        onOpenChange={setOpen}
        formSchema={userSchema}
        defaultValues={{
          name: '',
          email: '',
          age: 18,
          bio: '',
        }}
        fieldConfigs={{
          name: { type: 'input', label: '姓名' },
          email: { type: 'input', label: '邮箱地址' },
          age: { type: 'number', label: '年龄' },
          bio: { type: 'textarea', label: '个人简介' },
        }}
        onSubmit={handleSubmit}
        showCancelButton
      />
    </FormProvider>
  );
}

全局配置

import { FormProvider } from 'react-shadcn-crud-form';

function App() {
  return (
    <FormProvider
      config={{
        defaultSubmitText: '保存',
        defaultCancelText: '取消',
        defaultShowCancelButton: true,
        theme: {
          dialogMaxWidth: '80%',
          dialogMaxHeight: '90vh',
          fieldSpacing: 'space-y-6',
        },
        globalFieldConfigs: {
          email: { type: 'input', placeholder: '请输入邮箱地址' },
          password: { type: 'input', placeholder: '请输入密码' },
        },
      }}
    >
      {/* 你的应用内容 */}
    </FormProvider>
  );
}

💡 使用示例

1. 选择框和多选

const productSchema = z.object({
  category: z.string(),
  tags: z.array(z.string()),
  status: z.enum(['active', 'inactive']),
});

<DialogForm
  formSchema={productSchema}
  fieldConfigs={{
    category: {
      type: 'select',
      label: '产品分类',
      options: [
        { value: 'electronics', label: '电子产品' },
        { value: 'clothing', label: '服装' },
        { value: 'books', label: '图书' },
      ],
    },
    tags: {
      type: 'multiselect',
      label: '标签',
      options: [
        { value: 'new', label: '新品' },
        { value: 'hot', label: '热销' },
        { value: 'sale', label: '促销' },
      ],
    },
    status: {
      type: 'select',
      label: '状态',
      options: [
        { value: 'active', label: '激活' },
        { value: 'inactive', label: '未激活' },
      ],
    },
  }}
  // ... 其他属性
/>

2. 自定义字段渲染器

const customSchema = z.object({
  avatar: z.string().optional(),
  preferences: z.object({
    theme: z.enum(['light', 'dark']),
    notifications: z.boolean(),
  }),
});

<DialogForm
  formSchema={customSchema}
  fieldConfigs={{
    avatar: {
      type: 'custom',
      label: '头像',
      render: ({ field, fieldConfig }) => (
        <div className="flex items-center space-x-4">
          <img
            src={field.value || '/default-avatar.png'}
            alt="Avatar"
            className="w-16 h-16 rounded-full"
          />
          <input
            type="file"
            accept="image/*"
            onChange={(e) => {
              // 处理文件上传逻辑
              const file = e.target.files?.[0];
              if (file) {
                const url = URL.createObjectURL(file);
                field.onChange(url);
              }
            }}
          />
        </div>
      ),
    },
    'preferences.theme': {
      type: 'select',
      label: '主题',
      options: [
        { value: 'light', label: '浅色' },
        { value: 'dark', label: '深色' },
      ],
    },
    'preferences.notifications': {
      type: 'checkbox',
      label: '接收通知',
    },
  }}
  // ... 其他属性
/>

🎯 API 参考

DialogForm Props

| 属性 | 类型 | 必需 | 描述 | |------|------|------|------| | title | string | ✅ | 对话框标题 | | description | string | ✅ | 对话框描述 | | open | boolean | ✅ | 对话框是否打开 | | onOpenChange | (open: boolean) => void | ✅ | 对话框状态改变回调 | | formSchema | ZodObject | ✅ | Zod Schema 定义 | | onSubmit | (data: T) => void | ✅ | 表单提交回调 | | defaultValues | DefaultValues<T> | ✅ | 表单默认值 | | fieldConfigs | Record<string, FieldConfig> | ❌ | 字段配置 | | formMethods | UseFormReturn<T> | ❌ | 外部表单方法 | | submitButtonText | string | ❌ | 提交按钮文本 | | cancelButtonText | string | ❌ | 取消按钮文本 | | showCancelButton | boolean | ❌ | 是否显示取消按钮 | | onCancel | () => void | ❌ | 取消按钮回调 | | footer | ReactNode | ❌ | 自定义底部内容 | | hideFields | string[] | ❌ | 需要隐藏的字段 | | fieldOrder | string[] | ❌ | 字段显示顺序 |

FieldConfig

interface FieldConfig {
  type: 'input' | 'select' | 'textarea' | 'checkbox' | 'custom' | 'multiselect' | 'number' | 'image';
  label?: string;
  placeholder?: string;
  options?: { value: string; label: string }[];
  onChange?: (value: any) => void;
  disabled?: boolean;
  hideLabel?: boolean;
  render?: (props: {
    field: any;
    fieldConfig: FieldConfig;
    control: Control<any>;
  }) => ReactNode;
  renderAccessory?: (methods: { setValue: UseFormSetValue<any> }) => ReactNode;
  // 图片类型特有属性
  alt?: string;
  width?: number;
  height?: number;
}

FormProvider Props

interface FormProviderProps {
  children: ReactNode;
  config?: {
    globalFieldConfigs?: Record<string, Partial<FieldConfig>>;
    defaultSubmitText?: string;
    defaultCancelText?: string;
    defaultShowCancelButton?: boolean;
    validationMode?: 'onSubmit' | 'onBlur' | 'onChange' | 'onTouched' | 'all';
    theme?: {
      dialogMaxWidth?: string;
      dialogMaxHeight?: string;
      fieldSpacing?: string;
    };
  };
}

Hooks

useFormContext

const {
  defaultSubmitText,
  defaultCancelText,
  defaultShowCancelButton,
  theme,
  globalFieldConfigs,
  activeFormId,
  setActiveFormId,
  updateConfig,
} = useFormContext();

useFieldConfig

const fieldConfig = useFieldConfig('fieldName', localConfig);

useFormInstance

const { isActive, activate, deactivate } = useFormInstance('formId');

🎨 自定义主题

通过 FormProvider 配置全局主题:

<FormProvider
  config={{
    theme: {
      dialogMaxWidth: '90%',
      dialogMaxHeight: '85vh',
      fieldSpacing: 'space-y-8',
    },
  }}
>
  {/* 应用内容 */}
</FormProvider>

🔧 高级用法

字段间依赖

const schemaWithDependency = z.object({
  hasAddress: z.boolean(),
  address: z.string().optional(),
});

<DialogForm
  formSchema={schemaWithDependency}
  fieldConfigs={{
    hasAddress: {
      type: 'checkbox',
      label: '有地址信息',
    },
    address: {
      type: 'textarea',
      label: '详细地址',
      // 可以通过 watch 监听其他字段变化
    },
  }}
  hideFields={!form.watch('hasAddress') ? ['address'] : []}
/>

动态字段配置

const { updateConfig } = useFormContext();

// 动态更新全局配置
const handleThemeChange = (theme: string) => {
  updateConfig({
    theme: {
      dialogMaxWidth: theme === 'mobile' ? '95%' : '60%',
      fieldSpacing: theme === 'compact' ? 'space-y-2' : 'space-y-4',
    },
  });
};

📝 类型安全

本库完全支持 TypeScript,提供完整的类型推导:

// 从 Schema 自动推导类型
const userSchema = z.object({
  name: z.string(),
  age: z.number(),
});

type User = z.infer<typeof userSchema>; // { name: string; age: number }

// 表单提交时自动获得正确类型
const handleSubmit = (data: User) => {
  // data.name 是 string 类型
  // data.age 是 number 类型
};

🤝 贡献

我们欢迎所有形式的贡献!

  1. Fork 这个仓库
  2. 创建你的特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交你的更改 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 打开一个 Pull Request

📄 许可证

本项目基于 MIT 许可证 - 查看 LICENSE 文件了解详情。

🙏 致谢

⬆ 回到顶部

Made with ❤️ by the SakuraPuare