├── .gitignore
├── .npmignore
├── docs
├── demo
│ ├── static
│ │ └── js
│ │ │ ├── _vendor_.6c270d91.js
│ │ │ └── runtime.35902342.js
│ └── index.html
├── static
│ └── css
│ │ ├── vendor.less
│ │ └── modules
│ │ ├── color
│ │ └── colors.less
│ │ └── antd-custom.less
├── app
│ ├── index.js
│ └── modules
│ │ ├── App.js
│ │ └── config.js
├── .gitignore
├── README.md
├── .tern-project
├── public
│ └── index.html
├── scripts
│ ├── config
│ │ ├── polyfills.js
│ │ ├── tslintrc.json
│ │ ├── env.js
│ │ ├── checkMissDependencies.js
│ │ ├── paths.js
│ │ ├── eslintrc.js
│ │ ├── helper.js
│ │ ├── webpack.config.dev.js
│ │ └── webpack.config.prod.js
│ ├── start.js
│ ├── i18n.js
│ ├── cdn.js
│ └── build.js
├── .tern-webpack-config.js
├── global.d.ts
├── tsconfig.json
└── package.json
├── src
├── index.js
├── FormItem.test.tsx
└── FormItem.js
├── dist
├── index.cjs.js
├── index.esm.js
├── index.umd.js
├── react-antd-formutil.esm.production.js
├── react-antd-formutil.cjs.production.js
└── react-antd-formutil.umd.production.js
├── npm
├── index.cjs.js
├── index.esm.js
└── index.umd.js
├── babel.config.json
├── jest
├── setupTests.ts
├── cssTransform.js
├── fileTransform.js
├── test.js
└── jest.config.js
├── tsconfig.json
├── LICENSE
├── index.d.ts
├── eslint.config.js
├── package.json
├── rollup.config.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | *.un~
2 | .DS_Store
3 | node_modules
4 | /.git-tsconfig.json
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | docs/
2 | src/
3 | npm/
4 | rollup.config.*
5 | babel.config.json
6 | *.un~
7 |
--------------------------------------------------------------------------------
/docs/demo/static/js/_vendor_.6c270d91.js:
--------------------------------------------------------------------------------
1 | /*! @author qiqiboy */
2 | (this.webpackJsonp=this.webpackJsonp||[]).push([[2],[],[[0,0,1]]]);
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | //export react-formutil
2 | export * from 'react-formutil';
3 |
4 | export { default as FormItem, setErrorLevel } from './FormItem';
5 |
--------------------------------------------------------------------------------
/docs/static/css/vendor.less:
--------------------------------------------------------------------------------
1 | @import '~antd/dist/antd.less';
2 |
3 | .app {
4 | padding: 20px;
5 | > h2 {
6 | text-align: center;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/docs/app/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from 'react-dom';
3 |
4 | import App from 'modules/App';
5 |
6 | render(, document.getElementById('wrap'));
7 |
--------------------------------------------------------------------------------
/docs/.gitignore:
--------------------------------------------------------------------------------
1 | *.un~
2 | .*.swp
3 | .*.swo
4 | *.rdb
5 | .DS_Store
6 | node_modules
7 | bower_components
8 | /npm-debug.log
9 | /dump.rdb
10 | Thumbs.db
11 |
12 | # git pre-commit tsc lint
13 | .git-tsconfig.json
--------------------------------------------------------------------------------
/dist/index.cjs.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production') {
2 | module.exports = require('./react-antd-formutil.cjs.production.js');
3 | } else {
4 | module.exports = require('./react-antd-formutil.cjs.development.js');
5 | }
6 |
--------------------------------------------------------------------------------
/dist/index.esm.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production') {
2 | module.exports = require('./react-antd-formutil.esm.production.js');
3 | } else {
4 | module.exports = require('./react-antd-formutil.esm.development.js');
5 | }
6 |
--------------------------------------------------------------------------------
/npm/index.cjs.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production') {
2 | module.exports = require('./react-antd-formutil.cjs.production.js');
3 | } else {
4 | module.exports = require('./react-antd-formutil.cjs.development.js');
5 | }
6 |
--------------------------------------------------------------------------------
/npm/index.esm.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production') {
2 | module.exports = require('./react-antd-formutil.esm.production.js');
3 | } else {
4 | module.exports = require('./react-antd-formutil.esm.development.js');
5 | }
6 |
--------------------------------------------------------------------------------
/dist/index.umd.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production') {
2 | module.exports = require('./react-antd-formutil.umd.production.js');
3 | } else {
4 | module.exports = require('./react-antd-formutil.umd.development.js');
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/npm/index.umd.js:
--------------------------------------------------------------------------------
1 | if (process.env.NODE_ENV === 'production') {
2 | module.exports = require('./react-antd-formutil.umd.production.js');
3 | } else {
4 | module.exports = require('./react-antd-formutil.umd.development.js');
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react-app"],
3 | "plugins": [
4 | "react-hot-loader/babel",
5 | [
6 | "@babel/plugin-proposal-decorators",
7 | {
8 | "legacy": true
9 | }
10 | ]
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | 支持React + ES6的标准开发环境
2 | ================
3 |
4 | ### 开始开发
5 | $ npm start
6 |
7 | 该命令会在本地通过`webpack-dev-server`创建一个本地开发服务,支持hot reload.
8 |
9 | ### 部署测试
10 | $ npm run build:dev
11 |
12 | ### 上线
13 | $ npm run pack
14 |
15 |
--------------------------------------------------------------------------------
/jest/setupTests.ts:
--------------------------------------------------------------------------------
1 | // jest-dom adds custom jest matchers for asserting on DOM nodes.
2 | // allows you to do things like:
3 | // expect(element).toHaveTextContent(/react/i)
4 | // learn more: https://github.com/testing-library/jest-dom
5 | import '@testing-library/jest-dom/extend-expect';
6 |
--------------------------------------------------------------------------------
/docs/.tern-project:
--------------------------------------------------------------------------------
1 | {
2 | "libs": [
3 | "browser",
4 | "jquery",
5 | "ecma5",
6 | "ecma6",
7 | "underscore",
8 | "angular"
9 | ],
10 | "plugins": {
11 | "angular": {},
12 | "node": {},
13 | "es_modules": {},
14 | "commonjs": {},
15 | "webpack": {
16 | "configPath": "./.tern-webpack-config.js"
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/docs/app/modules/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import MyForm from './MyForm';
3 |
4 | class App extends Component {
5 | render() {
6 | return (
7 |
8 |
react-antd-formutil
9 |
10 |
11 | );
12 | }
13 | }
14 |
15 | export default App;
16 |
--------------------------------------------------------------------------------
/jest/cssTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This is a custom Jest transformer turning style imports into empty objects.
4 | // http://facebook.github.io/jest/docs/en/webpack.html
5 |
6 | module.exports = {
7 | process() {
8 | return 'module.exports = {};';
9 | },
10 | getCacheKey() {
11 | // The output is always the same.
12 | return 'cssTransform';
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/docs/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | react-antd-formutil
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docs/scripts/config/polyfills.js:
--------------------------------------------------------------------------------
1 | /* eslint @typescript-eslint/no-var-requires: 0 */
2 | // classList
3 | require('classlist-polyfill');
4 |
5 | // requestAnimationFrame
6 | require('raf-dom').polyfill();
7 |
8 | // ECMAScript
9 | require('core-js/features/object');
10 | require('core-js/features/promise');
11 | require('core-js/features/map');
12 | require('core-js/features/set');
13 | require('core-js/features/array');
14 | require('core-js/features/string');
15 | require('core-js/features/number');
16 | require('core-js/features/symbol');
17 |
18 | // require('core-js/features/url');
19 | // require('core-js/features/url-search-params');
20 |
--------------------------------------------------------------------------------
/docs/scripts/config/tslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "trailing-comma": false,
4 | "quotemark": false,
5 | "no-console": false,
6 | "semicolon": false,
7 | "no-namespace": [true, "allow-declarations"],
8 | "max-classes-per-file": false,
9 | "ordered-imports": false,
10 | "member-ordering": false,
11 | "object-literal-sort-keys": false,
12 | "member-access": false,
13 | "arrow-parens": [true, "ban-single-arg-parens"],
14 | "variable-name": false,
15 | "prefer-const": false,
16 | "jsx-boolean-value": false,
17 | "only-arrow-functions": false,
18 | "jsx-no-lambda": false,
19 | "interface-name": false
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/docs/.tern-webpack-config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const DirectoryNamedWebpackPlugin = require('directory-named-webpack-plugin');
3 |
4 | module.exports = {
5 | resolve: {
6 | modules: [path.resolve(__dirname, 'node_modules'), path.resolve(__dirname)],
7 | alias: {
8 | utils: path.resolve(__dirname, 'app/utils'),
9 | components: path.resolve(__dirname, 'app/components'),
10 | modules: path.resolve(__dirname, 'app/modules')
11 | },
12 | plugins: [
13 | new DirectoryNamedWebpackPlugin({
14 | honorIndex: true,
15 | exclude: /node_modules|libs/
16 | })
17 | ]
18 | }
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/docs/global.d.ts:
--------------------------------------------------------------------------------
1 | // 声明资源文件类型
2 | declare module '*.svg';
3 | declare module '*.png';
4 | declare module '*.jpg';
5 | declare module '*.jpeg';
6 | declare module '*.gif';
7 | declare module '*.bmp';
8 | declare module '*.tiff';
9 | declare module '*.html';
10 | declare module '*.txt';
11 | declare module '*.htm';
12 |
13 | interface Window {
14 | __: I18nFunc;
15 | }
16 |
17 | /**
18 | * create HOC(Higher Order Component)
19 | *
20 | */
21 | type HOC = (
22 | Component: React.ComponentType
23 | ) => React.ComponentType>;
24 |
25 | /**
26 | * i18n
27 | */
28 | type I18nFunc = (key: string) => string;
29 |
30 | declare const __: I18nFunc;
31 |
32 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES5",
4 | "module": "ESNext",
5 | "lib": ["ESNext", "DOM"],
6 | "jsx": "react",
7 | "resolveJsonModule": true,
8 | "experimentalDecorators": true,
9 | "allowSyntheticDefaultImports": true,
10 | "allowUnreachableCode": false,
11 | "moduleResolution": "node",
12 | "forceConsistentCasingInFileNames": true,
13 | "noFallthroughCasesInSwitch": true,
14 | "noImplicitReturns": true,
15 | "noImplicitThis": true,
16 | "noImplicitAny": false,
17 | "importHelpers": true,
18 | "strictNullChecks": true,
19 | "suppressImplicitAnyIndexErrors": true,
20 | "skipLibCheck": true,
21 | "noUnusedLocals": true,
22 | "importHelpers": true,
23 | "declaration": true,
24 | "outDir": "dist"
25 | },
26 | "include": ["*.d.ts", "src"],
27 | "exclude": ["node_modules", "dist", "build"]
28 | }
29 |
--------------------------------------------------------------------------------
/docs/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES5",
4 | "allowJs": true,
5 | "checkJs": true,
6 | "module": "ESNext",
7 | "lib": ["ESNext", "DOM"],
8 | "jsx": "react",
9 | "resolveJsonModule": true,
10 | "experimentalDecorators": true,
11 | "allowSyntheticDefaultImports": true,
12 | "allowUnreachableCode": false,
13 | "moduleResolution": "node",
14 | "forceConsistentCasingInFileNames": true,
15 | "noFallthroughCasesInSwitch": true,
16 | "skipLibCheck": true,
17 | "noEmit": true,
18 | "noImplicitReturns": true,
19 | "noImplicitThis": true,
20 | "noImplicitAny": false,
21 | "importHelpers": true,
22 | "strictNullChecks": true,
23 | "suppressImplicitAnyIndexErrors": true,
24 | "noUnusedLocals": false,
25 | "baseUrl": ".",
26 | "paths": {
27 | "*": ["*", "app/*"]
28 | }
29 | },
30 | "exclude": ["scripts", "node_modules", "dist", "build", "buildDev"]
31 | }
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 qiqiboy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/jest/fileTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const camelcase = require('camelcase');
5 |
6 | // This is a custom Jest transformer turning file imports into filenames.
7 | // http://facebook.github.io/jest/docs/en/webpack.html
8 |
9 | module.exports = {
10 | process(src, filename) {
11 | const assetFilename = JSON.stringify(path.basename(filename));
12 |
13 | if (filename.match(/\.svg$/)) {
14 | // Based on how SVGR generates a component name:
15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
16 | const pascalCaseFilename = camelcase(path.parse(filename).name, {
17 | pascalCase: true,
18 | });
19 | const componentName = `Svg${pascalCaseFilename}`;
20 | return `const React = require('react');
21 | module.exports = {
22 | __esModule: true,
23 | default: ${assetFilename},
24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
25 | return {
26 | $$typeof: Symbol.for('react.element'),
27 | type: 'svg',
28 | ref: ref,
29 | key: null,
30 | props: Object.assign({}, props, {
31 | children: ${assetFilename}
32 | })
33 | };
34 | }),
35 | };`;
36 | }
37 |
38 | return `module.exports = ${assetFilename};`;
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for react-antd-formutil@>=1.0.0
2 | // Project: react-antd-formutil
3 | // Definitions by: qiqiboy
4 |
5 | import { FormItemProps } from 'antd/es/form/FormItem';
6 | // If the next line occur error, please install rc-field-form or add 'skipLibCheck' to tsconfig.json for disable t.ds check.
7 | import { FieldProps } from 'rc-field-form/es/Field';
8 | import React from 'react';
9 | import { BaseEasyFieldComponentProps, $FieldHandler, Omit, OtherKeys } from 'react-formutil';
10 |
11 | export * from 'react-formutil';
12 |
13 | export type ErrorLevel = 0 | 1 | 2 | 'off';
14 |
15 | // Compatible with antd@3 & antd@4
16 | type FilterPropNames = any extends FieldProps ? '__NO__' : keyof FieldProps;
17 |
18 | export interface FormItemComponentProps
19 | extends BaseEasyFieldComponentProps,
20 | Omit {
21 | itemProps?: Omit;
22 | errorLevel?: ErrorLevel;
23 | noStyle?: boolean;
24 | children: React.ReactElement | (($fieldHandler: Partial<$FieldHandler> & OtherKeys) => React.ReactNode);
25 | }
26 |
27 | export class FormItem extends React.Component<
28 | FormItemComponentProps & OtherKeys
29 | > {}
30 |
31 | export function setErrorLevel(errorLevel: ErrorLevel): void;
32 |
--------------------------------------------------------------------------------
/docs/demo/static/js/runtime.35902342.js:
--------------------------------------------------------------------------------
1 | /*! @author qiqiboy */!function(e){function r(r){for(var n,l,f=r[0],i=r[1],a=r[2],c=0,s=[];c {
10 | throw err;
11 | });
12 |
13 | const jest = require('jest');
14 | const execSync = require('child_process').execSync;
15 | let argv = process.argv.slice(2);
16 |
17 | argv.push('-c', 'jest/jest.config.js');
18 |
19 | function isInGitRepository() {
20 | try {
21 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
22 |
23 | return true;
24 | } catch (e) {
25 | return false;
26 | }
27 | }
28 |
29 | function isInMercurialRepository() {
30 | try {
31 | execSync('hg --cwd . root', { stdio: 'ignore' });
32 |
33 | return true;
34 | } catch (e) {
35 | return false;
36 | }
37 | }
38 |
39 | // Watch unless on CI or explicitly running all tests
40 | if (!process.env.CI && argv.indexOf('--watchAll') === -1 && argv.indexOf('--watchAll=false') === -1) {
41 | // https://github.com/facebook/create-react-app/issues/5210
42 | const hasSourceControl = isInGitRepository() || isInMercurialRepository();
43 |
44 | argv.push(hasSourceControl ? '--watch' : '--watchAll');
45 | }
46 |
47 | jest.run(argv);
48 |
--------------------------------------------------------------------------------
/docs/demo/index.html:
--------------------------------------------------------------------------------
1 | react-antd-formutil
--------------------------------------------------------------------------------
/docs/scripts/config/env.js:
--------------------------------------------------------------------------------
1 | /* eslint @typescript-eslint/no-var-requires: 0 */
2 | const fs = require('fs');
3 | const path = require('path');
4 | const paths = require('./paths');
5 | const pkg = require(paths.appPackageJson);
6 |
7 | delete require.cache[require.resolve('./paths')];
8 |
9 | const NODE_ENV = process.env.NODE_ENV;
10 |
11 | let dotenvFiles = [
12 | `${paths.dotenv}.${NODE_ENV}.local`,
13 | `${paths.dotenv}.${NODE_ENV}`,
14 | NODE_ENV !== 'test' && `${paths.dotenv}.local`,
15 | paths.dotenv
16 | ].filter(Boolean);
17 |
18 | dotenvFiles.forEach(dotenvFile => {
19 | if (fs.existsSync(dotenvFile)) {
20 | require('dotenv-expand')(
21 | require('dotenv').config({
22 | path: dotenvFile
23 | })
24 | );
25 | }
26 | });
27 |
28 | const appDirectory = fs.realpathSync(process.cwd());
29 |
30 | process.env.NODE_PATH = (process.env.NODE_PATH || '')
31 | .split(path.delimiter)
32 | .filter(folder => folder && !path.isAbsolute(folder))
33 | .map(folder => path.resolve(appDirectory, folder))
34 | .join(path.delimiter);
35 |
36 | if (!('BASE_NAME' in process.env) && 'basename' in pkg) {
37 | process.env.BASE_NAME = pkg.basename;
38 | }
39 |
40 | const REACT_APP = /^(REACT_APP_|TIGER_)/i;
41 | const whitelists = ['BASE_NAME'];
42 |
43 | function getClientEnvironment(publicUrl) {
44 | const raw = Object.keys(process.env)
45 | .filter(key => REACT_APP.test(key) || whitelists.includes(key))
46 | .reduce(
47 | (env, key) => {
48 | env[key] = process.env[key];
49 | return env;
50 | },
51 | {
52 | NODE_ENV: process.env.NODE_ENV || 'development',
53 | PUBLIC_URL: publicUrl
54 | }
55 | );
56 | // Stringify all values so we can feed into Webpack DefinePlugin
57 | const stringified = {
58 | 'process.env': Object.keys(raw).reduce((env, key) => {
59 | env[key] = JSON.stringify(raw[key]);
60 | return env;
61 | }, {})
62 | };
63 |
64 | return { raw, stringified };
65 | }
66 |
67 | module.exports = getClientEnvironment;
68 |
--------------------------------------------------------------------------------
/docs/scripts/config/checkMissDependencies.js:
--------------------------------------------------------------------------------
1 | /* eslint @typescript-eslint/no-var-requires: 0 */
2 | const checkDependencies = require('check-dependencies');
3 | const inquirer = require('react-dev-utils/inquirer');
4 | const spawn = require('cross-spawn');
5 | const chalk = require('chalk');
6 | const paths = require('./paths');
7 |
8 | async function checkMissDeps(spinner) {
9 | const result = await checkDependencies({
10 | packageDir: paths.root
11 | });
12 |
13 | if (result.status !== 0) {
14 | spinner.stop();
15 |
16 | // 输出错误信息
17 | result.error.forEach(function(err) {
18 | console.log(err);
19 | });
20 |
21 | console.log();
22 |
23 | const { reInstall } = await inquirer.prompt([
24 | {
25 | name: 'reInstall',
26 | type: 'confirm',
27 | message:
28 | '你当前安装的依赖版本和要求的不一致,是否要重新安装所有依赖?\n' +
29 | chalk.dim('重新运行 npm install 安装所有依赖项.'),
30 | default: true
31 | }
32 | ]);
33 |
34 | console.log();
35 |
36 | if (reInstall) {
37 | await new Promise((resolve, reject) => {
38 | install(function(code, command, args) {
39 | if (code !== 0) {
40 | spinner.fail('`' + command + ' ' + args.join(' ') + '` 运行失败');
41 |
42 | reject();
43 | } else {
44 | resolve();
45 | }
46 | });
47 | });
48 |
49 | spinner.succeed(chalk.green('项目依赖已更新'));
50 | } else {
51 | spinner.warn(chalk.yellow('你需要按照下面命令操作后才能继续:'));
52 | console.log();
53 |
54 | console.log(chalk.green(' ' + paths.npmCommander + ' install'));
55 |
56 | return Promise.reject();
57 | }
58 | }
59 | }
60 |
61 | function install(callback) {
62 | let command = paths.npmCommander;
63 | let args = ['install'];
64 |
65 | var child = spawn(command, args, {
66 | stdio: 'inherit'
67 | });
68 |
69 | child.on('close', function(code) {
70 | callback(code, command, args);
71 | });
72 | }
73 |
74 | module.exports = checkMissDeps;
75 |
--------------------------------------------------------------------------------
/jest/jest.config.js:
--------------------------------------------------------------------------------
1 | // For a detailed explanation regarding each configuration property, visit:
2 | // https://jestjs.io/docs/en/configuration.html
3 | const fs = require('fs-extra');
4 |
5 | module.exports = {
6 | projects: [
7 | {
8 | displayName: 'lint',
9 | runner: 'eslint',
10 | rootDir: process.cwd(),
11 | roots: ['/src', fs.existsSync(process.cwd() + '/tests') && '/tests'].filter(Boolean),
12 | testMatch: [
13 | '/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
14 | '/{src,tests}/**/*.{spec,test}.{js,jsx,ts,tsx}'
15 | ]
16 | },
17 | {
18 | displayName: 'test',
19 | rootDir: process.cwd(),
20 | roots: ['/src', fs.existsSync(process.cwd() + '/tests') && '/tests'].filter(Boolean),
21 | collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'],
22 | setupFiles: [],
23 | setupFilesAfterEnv: ['/jest/setupTests.ts'],
24 | testMatch: [
25 | '/src/**/__tests__/**/*.{js,jsx,ts,tsx}',
26 | '/{src,tests}/**/*.{spec,test}.{js,jsx,ts,tsx}'
27 | ],
28 | testEnvironment: 'jest-environment-jsdom-fourteen',
29 | transform: {
30 | '^.+\\.(js|jsx|ts|tsx)$': '/node_modules/babel-jest',
31 | '^.+\\.(css|less|sass|scss$)': '/jest/cssTransform.js',
32 | '^(?!.*\\.(js|jsx|ts|tsx|css|less|sass|scss|json)$)': '/jest/fileTransform.js'
33 | },
34 | transformIgnorePatterns: [
35 | '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$',
36 | '^.+\\.module\\.(css|sass|scss|less)$'
37 | ],
38 | modulePaths: [],
39 | moduleNameMapper: {
40 | '^react-native$': 'react-native-web',
41 | '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy'
42 | },
43 | moduleFileExtensions: ['web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', 'node'],
44 | verbose: true,
45 | // resetMocks: true,
46 | watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname']
47 | }
48 | ]
49 | };
50 |
--------------------------------------------------------------------------------
/docs/app/modules/config.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Select } from 'antd';
3 |
4 | export const formItemLayout = {
5 | labelCol: {
6 | xs: { span: 24 },
7 | sm: { span: 8 }
8 | },
9 | wrapperCol: {
10 | xs: { span: 24 },
11 | sm: { span: 16 }
12 | }
13 | };
14 |
15 | export const hobbiesOptions = [
16 | { label: 'Apple', value: 'Apple' },
17 | { label: 'Pear', value: 'Pear' },
18 | { label: 'Orange', value: 'Orange' }
19 | ];
20 |
21 | export const selectOption = Array(36)
22 | .fill('')
23 | .map((n, i) => {i.toString(36) + i})
24 | .slice(10);
25 |
26 | export const sliderMarks = {
27 | 0: '0°C',
28 | 26: '26°C',
29 | 37: '37°C',
30 | 100: {
31 | style: {
32 | color: '#f50'
33 | },
34 | label: 100°C
35 | }
36 | };
37 |
38 | export const cascaderOptions = [
39 | {
40 | value: 'zhejiang',
41 | label: 'Zhejiang',
42 | children: [
43 | {
44 | value: 'hangzhou',
45 | label: 'Hangzhou',
46 | children: [
47 | {
48 | value: 'xihu',
49 | label: 'West Lake'
50 | }
51 | ]
52 | }
53 | ]
54 | },
55 | {
56 | value: 'jiangsu',
57 | label: 'Jiangsu',
58 | children: [
59 | {
60 | value: 'nanjing',
61 | label: 'Nanjing',
62 | children: [
63 | {
64 | value: 'zhonghuamen',
65 | label: 'Zhong Hua Men'
66 | }
67 | ]
68 | }
69 | ]
70 | }
71 | ];
72 |
73 | export const mentionOptions = ['afc163', 'benjycui', 'yiminghe', 'RaoHai', '中文', 'にほんご'];
74 |
75 | export const uplodConfig = {
76 | name: 'file',
77 | action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
78 | headers: {
79 | authorization: 'authorization-text'
80 | }
81 | };
82 |
83 | export const transferData = [];
84 |
85 | for (let i = 0; i < 20; i++) {
86 | transferData.push({
87 | key: i.toString(),
88 | title: `content${i + 1}`,
89 | description: `description of content${i + 1}`
90 | });
91 | }
92 |
--------------------------------------------------------------------------------
/docs/scripts/config/paths.js:
--------------------------------------------------------------------------------
1 | /* eslint @typescript-eslint/no-var-requires: 0 */
2 | const path = require('path');
3 | const fs = require('fs-extra');
4 | const glob = require('glob');
5 | const execSync = require('child_process').execSync;
6 | const isDev = process.env.NODE_ENV === 'development';
7 | const lodash = require('lodash');
8 |
9 | // Make sure any symlinks in the project folder are resolved:
10 | // https://github.com/facebookincubator/create-react-app/issues/637
11 | const appDirectory = fs.realpathSync(process.cwd());
12 | const pkg = require(resolveApp('package.json'));
13 |
14 | function resolveApp(relativePath) {
15 | return path.resolve(appDirectory, relativePath);
16 | }
17 |
18 | const nodePaths = (process.env.NODE_PATH || '')
19 | .split(path.delimiter)
20 | .filter(Boolean)
21 | .map(resolveApp);
22 |
23 | const entries = {};
24 |
25 | glob.sync(resolveApp('app/!(_)*.{j,t}s?(x)')).forEach(function(file) {
26 | const basename = path.basename(file).replace(/\.[jt]sx?$/, '');
27 |
28 | entries[basename] = file;
29 | });
30 |
31 | const alias = Object.assign(
32 | {
33 | components: resolveApp('app/components'),
34 | modules: resolveApp('app/modules'),
35 | utils: resolveApp('app/utils'),
36 | stores: resolveApp('app/stores'),
37 | types: resolveApp('app/types'),
38 | hooks: resolveApp('app/hooks')
39 | },
40 | lodash.mapValues(pkg.alias, function(relativePath) {
41 | if (fs.pathExistsSync(resolveApp(relativePath))) {
42 | return resolveApp(relativePath);
43 | }
44 |
45 | return relativePath;
46 | })
47 | );
48 |
49 | // config after eject: we're in ./config/
50 | module.exports = {
51 | dotenv: resolveApp('.env'),
52 | root: resolveApp(''),
53 | appBuild: resolveApp(process.env.BUILD_DIR || 'demo'),
54 | appPublic: resolveApp('public'),
55 | appHtml: resolveApp('public/index.html'),
56 | appIndexJs: Object.values(entries)[0] || resolveApp('app/index.js'),
57 | appPackageJson: resolveApp('package.json'),
58 | appSrc: resolveApp('app'),
59 | formutilSrc: resolveApp('app/../../src'),
60 | appTsConfig: resolveApp('tsconfig.json'),
61 | staticSrc: resolveApp('static'),
62 | locals: resolveApp('locals'),
63 | proxySetup: resolveApp('setupProxy.js'),
64 | appNodeModules: resolveApp('node_modules'),
65 | ownNodeModules: resolveApp('node_modules'),
66 | nodePaths: nodePaths,
67 | alias: alias,
68 | entries: entries,
69 | pageEntries: glob.sync(resolveApp('public/!(_)*.html')).map(function(file) {
70 | return path.basename(file, '.html');
71 | }),
72 | moduleFileExtensions: ['.js', '.json', '.jsx', '.mjs', '.ts', '.tsx'],
73 | // 一些命令检测
74 | serve: hasInstall('serve'),
75 | npmCommander: ['tnpm', 'cnpm', 'npm'].find(hasInstall)
76 | };
77 |
78 | function hasInstall(command) {
79 | try {
80 | execSync(command + ' --version', {
81 | stdio: 'ignore'
82 | });
83 |
84 | return true;
85 | } catch (e) {
86 | return false;
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/eslint.config.js:
--------------------------------------------------------------------------------
1 | const pkg = require('./package.json');
2 |
3 | /**
4 | * 0: off
5 | * 1: warn
6 | * 2: error
7 | */
8 | module.exports = {
9 | overrides: [
10 | {
11 | files: ['**/__tests__/**/*', '**/*.{spec,test}.*'],
12 | rules: {
13 | 'jest/consistent-test-it': [1, { fn: 'test' }],
14 | 'jest/expect-expect': 1,
15 | 'jest/no-deprecated-functions': 2
16 | }
17 | }
18 | ],
19 | settings: {
20 | 'import/core-modules': [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
21 | },
22 | rules: {
23 | 'react/react-in-jsx-scope': 2,
24 | 'react/no-unsafe': [2, { checkAliases: true }],
25 | 'react/no-deprecated': 2,
26 | 'import/no-anonymous-default-export': [
27 | 2,
28 | {
29 | allowArray: true,
30 | allowArrowFunction: false,
31 | allowAnonymousClass: false,
32 | allowAnonymousFunction: false,
33 | allowCallExpression: true, // The true value here is for backward compatibility
34 | allowLiteral: true,
35 | allowObject: true
36 | }
37 | ],
38 | 'import/no-duplicates': 1,
39 | 'import/order': [
40 | 1,
41 | {
42 | groups: ['builtin', 'external', 'internal', ['parent', 'sibling', 'index'], 'object', 'unknown']
43 | }
44 | ],
45 | 'import/no-useless-path-segments': [
46 | 1,
47 | {
48 | noUselessIndex: true
49 | }
50 | ],
51 | 'lines-between-class-members': [1, 'always', { exceptAfterSingleLine: true }],
52 | 'padding-line-between-statements': [
53 | 1,
54 | {
55 | blankLine: 'always',
56 | prev: [
57 | 'multiline-block-like',
58 | 'multiline-expression',
59 | 'const',
60 | 'let',
61 | 'var',
62 | 'cjs-import',
63 | 'import',
64 | 'export',
65 | 'cjs-export',
66 | 'class',
67 | 'throw',
68 | 'directive'
69 | ],
70 | next: '*'
71 | },
72 | {
73 | blankLine: 'always',
74 | prev: '*',
75 | next: [
76 | 'multiline-block-like',
77 | 'multiline-expression',
78 | 'const',
79 | 'let',
80 | 'var',
81 | 'cjs-import',
82 | 'import',
83 | 'export',
84 | 'cjs-export',
85 | 'class',
86 | 'throw',
87 | 'return'
88 | ]
89 | },
90 | { blankLine: 'any', prev: ['cjs-import', 'import'], next: ['cjs-import', 'import'] },
91 | { blankLine: 'any', prev: ['export', 'cjs-export'], next: ['export', 'cjs-export'] },
92 | { blankLine: 'any', prev: ['const', 'let', 'var'], next: ['const', 'let', 'var'] }
93 | ]
94 | }
95 | };
96 |
--------------------------------------------------------------------------------
/docs/scripts/start.js:
--------------------------------------------------------------------------------
1 | /* eslint @typescript-eslint/no-var-requires: 0 */
2 | process.env.BABEL_ENV = 'development';
3 | process.env.NODE_ENV = 'development';
4 |
5 | process.on('unhandledRejection', err => {
6 | throw err;
7 | });
8 |
9 | require('./config/env');
10 |
11 | const chalk = require('chalk');
12 | const webpack = require('webpack');
13 | const ora = require('ora');
14 | const WebpackDevServer = require('webpack-dev-server');
15 | const { choosePort, prepareProxy, createCompiler, createDevServerConfig } = require('./config/helper');
16 | const { prepareUrls } = require('react-dev-utils/WebpackDevServerUtils');
17 | const openBrowser = require('react-dev-utils/openBrowser');
18 | const clearConsole = require('react-dev-utils/clearConsole');
19 | const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
20 | const checkMissDependencies = require('./config/checkMissDependencies');
21 | const config = require('./config/webpack.config.dev');
22 | const paths = require('./config/paths');
23 | const { ensureLocals } = require('./i18n');
24 | const pkg = require(paths.appPackageJson);
25 |
26 | const spinner = ora('webpack启动中...').start();
27 | const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
28 | const HOST = process.env.HOST || '0.0.0.0';
29 | const isInteractive = process.stdout.isTTY;
30 |
31 | if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
32 | console.log();
33 | process.exit(1);
34 | }
35 |
36 | ensureLocals();
37 |
38 | checkMissDependencies(spinner)
39 | .then(() => {
40 | return choosePort(HOST, DEFAULT_PORT, spinner).then(port => {
41 | if (port === null) {
42 | console.log();
43 |
44 | spinner.fail(
45 | '请关闭占用 ' +
46 | chalk.bold(chalk.yellow(DEFAULT_PORT)) +
47 | ' 端口的程序后再运行;或者指定一个新的端口:' +
48 | chalk.bold(chalk.yellow('PORT=4000 npm start'))
49 | );
50 |
51 | console.log();
52 | process.exit(0);
53 | } else {
54 | spinner.start();
55 |
56 | const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
57 | const appName = pkg.name;
58 | const urls = prepareUrls(protocol, HOST, port);
59 | const devSocket = {
60 | warnings: warnings => devServer.sockWrite(devServer.sockets, 'warnings', warnings),
61 | errors: errors => devServer.sockWrite(devServer.sockets, 'errors', errors)
62 | };
63 | const compiler = createCompiler(webpack, config, appName, urls, devSocket, spinner);
64 | const proxyConfig = prepareProxy(process.env.PROXY || pkg.proxy, paths.appPublic);
65 | const serverConfig = createDevServerConfig(proxyConfig, urls.lanUrlForConfig);
66 | const devServer = new WebpackDevServer(compiler, serverConfig);
67 |
68 | // Launch WebpackDevServer.
69 | devServer.listen(port, HOST, err => {
70 | if (err) {
71 | return console.log(err);
72 | }
73 |
74 | if (isInteractive) {
75 | clearConsole();
76 | }
77 |
78 | spinner.text = chalk.cyan('正在启动测试服务器...');
79 | openBrowser(urls.localUrlForBrowser);
80 | });
81 |
82 | ['SIGINT', 'SIGTERM'].forEach(function(sig) {
83 | process.on(sig, function() {
84 | devServer.close();
85 | spinner.stop();
86 | process.exit();
87 | });
88 | });
89 | }
90 | });
91 | })
92 | .catch(function(err) {
93 | if (err) {
94 | console.log(err.message || err);
95 | console.log();
96 | }
97 |
98 | process.kill(process.pid, 'SIGINT');
99 | });
100 |
--------------------------------------------------------------------------------
/docs/scripts/i18n.js:
--------------------------------------------------------------------------------
1 | /* eslint @typescript-eslint/no-var-requires: 0 */
2 | const fs = require('fs-extra');
3 | const glob = require('glob');
4 | const Parser = require('i18next-scanner').Parser;
5 | const xlsx = require('node-xlsx');
6 | const paths = require('./config/paths');
7 | const path = require('path');
8 | const chalk = require('chalk');
9 | const ora = require('ora');
10 | const lodash = require('lodash');
11 | const pkg = require(paths.appPackageJson);
12 |
13 | const spinner = ora();
14 |
15 | const xlsxOptions = {
16 | '!cols': [{ wch: 50 }, { wch: 50 }]
17 | };
18 |
19 | const terminalArg = process.argv[2];
20 |
21 | if (terminalArg === '--scan') {
22 | ensureLocalsConfig();
23 | scanner();
24 | } else if (terminalArg === '--read') {
25 | ensureLocalsConfig();
26 | reader();
27 | }
28 |
29 | function ensureLocalsConfig() {
30 | if (Array.isArray(pkg.locals) === false) {
31 | spinner.fail(chalk.red('未在 package.json 中找到相关语言包配置!'));
32 |
33 | spinner.warn(
34 | chalk.yellow('需要 package.json 中添加 { "locals": ["zh_CN", "en_US"] } 配置后,才能运行该命令!')
35 | );
36 |
37 | process.exit(0);
38 | }
39 | }
40 |
41 | /**
42 | * @description
43 | * 扫描源代码文件,匹配需要翻译的文案,并输出excel文件待翻译
44 | */
45 | function scanner() {
46 | const i18nParser = new Parser({
47 | lngs: pkg.locals,
48 | nsSeparator: false,
49 | keySeparator: false,
50 | pluralSeparator: false,
51 | contextSeparator: false
52 | });
53 |
54 | fs.ensureDirSync(path.join(paths.locals, 'xlsx'));
55 |
56 | glob.sync(paths.appSrc + '/**/*.{js,jsx,ts,tsx}').forEach(file => {
57 | const content = fs.readFileSync(file);
58 |
59 | i18nParser.parseFuncFromString(content, { list: ['__', 'i18n.__', 'window.__'] }, key => {
60 | if (key) {
61 | i18nParser.set(key, key);
62 | }
63 | });
64 | });
65 |
66 | const i18nJson = i18nParser.get();
67 |
68 | Object.keys(i18nJson).forEach(key => {
69 | const jsonDestination = path.join(paths.locals, key + '.json');
70 | const excelDestination = path.join(paths.locals, 'xlsx', key + '.xlsx');
71 |
72 | const translation = i18nJson[key].translation;
73 | const existConfig = fs.existsSync(jsonDestination) ? JSON.parse(fs.readFileSync(jsonDestination)) : {};
74 | const newConfig = lodash.pickBy(existConfig, (value, key) => key in translation);
75 |
76 | lodash.each(translation, (value, key) => {
77 | if (!(key in newConfig)) {
78 | newConfig[key] = value;
79 | }
80 | });
81 |
82 | fs.outputFile(path.join(paths.locals, key + '.json'), JSON.stringify(newConfig, '\n', 2));
83 |
84 | convertJson2Excel(newConfig, key, path.join(excelDestination));
85 |
86 | spinner.succeed('输出 ' + chalk.bold(chalk.green(key)) + ' 到 ' + chalk.cyan(excelDestination));
87 | });
88 |
89 | console.log();
90 | spinner.warn(chalk.yellow('你可以将生成的excel文件进行翻译后,放回原处。然后运行:'));
91 | console.log(chalk.green(' npm run i18n-read'));
92 | }
93 |
94 | /**
95 | * @description
96 | * 读取excel文件,并转换为json语言包
97 | */
98 | function reader() {
99 | glob.sync(path.join(paths.locals, 'xlsx', '!(~$)*.xlsx')).forEach(file => {
100 | const lang = path.basename(file, '.xlsx');
101 | const jsonDestination = path.join(paths.locals, lang + '.json');
102 |
103 | convertExcel2Json(file, lang, jsonDestination);
104 |
105 | spinner.succeed('输出 ' + chalk.bold(chalk.green(lang)) + ' 到 ' + chalk.cyan(jsonDestination));
106 | });
107 |
108 | console.log();
109 | spinner.succeed(chalk.green('语言包转换成功!'));
110 | }
111 |
112 | function convertJson2Excel(jsonContent, lang, destination) {
113 | const sheets = [[pkg.name + ' v' + pkg.version, lang], ['原始文案(禁止修改)', '翻译文案'], []];
114 |
115 | Object.keys(jsonContent).forEach(key => {
116 | const text = jsonContent[key];
117 |
118 | sheets.push([key, text]);
119 | });
120 |
121 | const buffer = xlsx.build([{ name: 'locals', data: sheets }], xlsxOptions);
122 |
123 | fs.writeFileSync(destination, buffer);
124 | }
125 |
126 | function convertExcel2Json(file, lang, destination) {
127 | const sheets = xlsx.parse(fs.readFileSync(file));
128 |
129 | const jsonData = require(destination) || {};
130 |
131 | sheets[0].data.slice(2).forEach(item => {
132 | if (item.length) {
133 | jsonData[item[0]] = item[1];
134 | }
135 | });
136 |
137 | fs.outputFileSync(destination, JSON.stringify(jsonData, '\n', 2));
138 | }
139 |
140 | exports.ensureLocals = function() {
141 | fs.ensureDirSync(path.join(paths.locals));
142 |
143 | if (Array.isArray(pkg.locals)) {
144 | pkg.locals.forEach(lang => {
145 | const file = path.join(paths.locals, lang + '.json');
146 |
147 | if (!fs.existsSync(file)) {
148 | fs.outputJSONSync(file, {});
149 | }
150 | });
151 | }
152 | };
153 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-antd-formutil",
3 | "version": "1.1.13",
4 | "description": "Happy to use react-formutil in the project based on ant-design ^_^",
5 | "main": "dist/index.cjs.js",
6 | "module": "dist/index.esm.js",
7 | "directories": {
8 | "doc": "docs"
9 | },
10 | "scripts": {
11 | "start": "cd docs && npm start",
12 | "build": "rimraf dist && rollup -c",
13 | "test": "node jest/test.js",
14 | "tsc": "node -e \"require('fs-extra').outputJsonSync('.git-tsconfig.json',{ extends: './tsconfig.json', include: ['*.d.ts'].concat(process.env.StagedFiles.split(/\\n+/)) })\" && echo 'TS checking...\\n' && tsc -p .git-tsconfig.json --noEmit --checkJs false"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/qiqiboy/react-antd-formutil.git"
19 | },
20 | "entryFile": "src/index.js",
21 | "keywords": [
22 | "react",
23 | "ant-design",
24 | "react-component",
25 | "react-form",
26 | "react-formutil",
27 | "ant-design-form"
28 | ],
29 | "author": "qiqiboy",
30 | "license": "ISC",
31 | "bugs": {
32 | "url": "https://github.com/qiqiboy/react-antd-formutil/issues"
33 | },
34 | "eslintConfig": {
35 | "extends": [
36 | "react-app",
37 | "react-app/jest",
38 | "./eslint.config.js"
39 | ]
40 | },
41 | "prettier": {
42 | "printWidth": 120,
43 | "tabWidth": 4,
44 | "trailingComma": "none",
45 | "jsxBracketSameLine": true,
46 | "semi": true,
47 | "singleQuote": true,
48 | "arrowParens": "avoid",
49 | "overrides": [
50 | {
51 | "files": [
52 | "*.json"
53 | ],
54 | "options": {
55 | "tabWidth": 2
56 | }
57 | }
58 | ]
59 | },
60 | "homepage": "https://github.com/qiqiboy/react-antd-formutil#readme",
61 | "types": "./index.d.ts",
62 | "peerDependencies": {
63 | "react": "^16.3.0 || ^17.0.0",
64 | "prop-types": ">15.0.0",
65 | "antd": "^3.0.0 || ^4.0.0",
66 | "react-formutil": "^1.0.11"
67 | },
68 | "devDependencies": {
69 | "@babel/cli": "7.12.1",
70 | "@babel/core": "7.12.3",
71 | "@commitlint/cli": "11.0.0",
72 | "@commitlint/config-conventional": "11.0.0",
73 | "@rollup/plugin-babel": "5.2.1",
74 | "@rollup/plugin-commonjs": "11.1.0",
75 | "@rollup/plugin-eslint": "8.0.0",
76 | "@rollup/plugin-node-resolve": "10.0.0",
77 | "@rollup/plugin-replace": "2.3.4",
78 | "@testing-library/jest-dom": "5.11.5",
79 | "@testing-library/react": "11.1.2",
80 | "@testing-library/user-event": "12.2.2",
81 | "@types/jest": "26.0.15",
82 | "@types/node": "14.14.7",
83 | "@types/prop-types": "15.7.3",
84 | "@types/react": "16.9.23",
85 | "@types/react-dom": "16.9.5",
86 | "@types/react-is": "16.7.1",
87 | "@typescript-eslint/eslint-plugin": "4.7.0",
88 | "@typescript-eslint/parser": "4.7.0",
89 | "antd": "4.9.2",
90 | "babel-eslint": "10.1.0",
91 | "babel-jest": "26.6.3",
92 | "babel-preset-react-app": "10.0.0",
93 | "eslint": "7.13.0",
94 | "eslint-config-react-app": "6.0.0",
95 | "eslint-plugin-flowtype": "5.2.0",
96 | "eslint-plugin-import": "2.22.1",
97 | "eslint-plugin-jest": "24.1.3",
98 | "eslint-plugin-jsx-a11y": "6.4.1",
99 | "eslint-plugin-react": "7.21.5",
100 | "eslint-plugin-react-hooks": "4.2.0",
101 | "eslint-plugin-testing-library": "3.10.0",
102 | "husky": "3.1.0",
103 | "jest": "26.6.3",
104 | "jest-environment-jsdom-fourteen": "1.0.1",
105 | "jest-resolve": "26.6.2",
106 | "jest-runner-eslint": "0.10.0",
107 | "jest-watch-typeahead": "0.4.2",
108 | "lint-staged": "10.5.1",
109 | "memo-render": "^0.0.2",
110 | "prettier": "2.1.2",
111 | "prop-types": "15.7.2",
112 | "react": "17.0.1",
113 | "react-dom": "17.0.1",
114 | "react-formutil": "^1.1.3",
115 | "react-hot-loader": "^4.12.19",
116 | "rimraf": "3.0.2",
117 | "rollup": "2.33.1",
118 | "rollup-plugin-babel": "4.4.0",
119 | "rollup-plugin-clear": "^2.0.7",
120 | "rollup-plugin-copy": "3.3.0",
121 | "rollup-plugin-filesize": "9.0.2",
122 | "rollup-plugin-sass": "1.2.2",
123 | "rollup-plugin-terser": "7.0.2",
124 | "typescript": "4.0.5"
125 | },
126 | "engines": {
127 | "node": ">=10.13.0",
128 | "tiger-new": "6.2.7"
129 | },
130 | "husky": {
131 | "hooks": {
132 | "commit-msg": "node_modules/.bin/commitlint --edit $HUSKY_GIT_PARAMS",
133 | "pre-commit": "lint-staged && export StagedFiles=$(git diff --diff-filter AM --name-only --relative --staged | grep -E '^src/.*\\.m?[jt]sx?$') && if [ -n \"$StagedFiles\" ]; then npm run tsc ; fi"
134 | }
135 | },
136 | "commitlint": {
137 | "extends": [
138 | "@commitlint/config-conventional"
139 | ],
140 | "rules": {
141 | "subject-case": [
142 | 0
143 | ],
144 | "scope-case": [
145 | 0
146 | ]
147 | }
148 | },
149 | "lint-staged": {
150 | "src/**/*.{js,jsx,mjs,ts,tsx}": [
151 | "node_modules/.bin/prettier --write",
152 | "node_modules/.bin/eslint --fix"
153 | ],
154 | "src/**/*.{css,scss,less,json,html,md}": [
155 | "node_modules/.bin/prettier --write"
156 | ]
157 | },
158 | "stylelint": {
159 | "extends": "stylelint-config-recommended"
160 | },
161 | "browserslist": [
162 | ">0.2%",
163 | "not dead",
164 | "not op_mini all"
165 | ],
166 | "config": {
167 | "commitizen": {
168 | "path": "cz-conventional-changelog"
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "docs",
3 | "author": "qiqiboy",
4 | "version": "1.0.2",
5 | "private": true,
6 | "vendor": [
7 | "react",
8 | "react-dom",
9 | "antd",
10 | "react-formutil",
11 | "./static/css/vendor.less"
12 | ],
13 | "noRewrite": true,
14 | "proxy": null,
15 | "scripts": {
16 | "start": "node scripts/start.js",
17 | "build": "node scripts/build.js",
18 | "build:dev": "node scripts/build.js --dev",
19 | "pack": "npm run build",
20 | "count": "node scripts/count.js",
21 | "tsc": "node -e \"require('fs-extra').outputJsonSync('.git-tsconfig.json',{ extends: './tsconfig.json', include: ['*.d.ts', 'app/utils/i18n/*'].concat(process.env.StagedFiles.split(/\\n+/)) })\" && echo 'TS checking...\\n' && tsc -p .git-tsconfig.json --checkJs false"
22 | },
23 | "eslintConfig": {
24 | "extends": [
25 | "react-app",
26 | "./scripts/config/eslintrc.js"
27 | ]
28 | },
29 | "prettier": {
30 | "printWidth": 120,
31 | "tabWidth": 4,
32 | "parser": "babylon",
33 | "trailingComma": "none",
34 | "jsxBracketSameLine": true,
35 | "semi": true,
36 | "singleQuote": true,
37 | "overrides": [
38 | {
39 | "files": "*.json",
40 | "options": {
41 | "tabWidth": 2
42 | }
43 | }
44 | ]
45 | },
46 | "lint-staged": {
47 | "{app,static}/**/*.{js,jsx,mjs,css,scss,less,json,ts}": [
48 | "node_modules/.bin/prettier --write",
49 | "git add"
50 | ]
51 | },
52 | "dependencies": {
53 | "axios": "0.17.0",
54 | "lodash": "^4.17.10",
55 | "moment": "^2.22.2",
56 | "react-animated-router": "0.1.11",
57 | "react-awesome-snippets": "0.0.22",
58 | "react-router-dom": "4.2.2",
59 | "react-transition-group": "2.4.0"
60 | },
61 | "devDependencies": {
62 | "@babel/core": "7.8.6",
63 | "@babel/plugin-proposal-decorators": "7.8.3",
64 | "@commitlint/cli": "7.6.1",
65 | "@commitlint/config-conventional": "7.6.0",
66 | "@svgr/webpack": "4.3.3",
67 | "@types/node": "12.12.29",
68 | "@types/react-is": "16.7.1",
69 | "@types/react-router-dom": "5.1.3",
70 | "@types/react-transition-group": "4.2.4",
71 | "@typescript-eslint/eslint-plugin": "2.21.0",
72 | "@typescript-eslint/parser": "2.21.0",
73 | "address": "1.0.2",
74 | "ali-oss": "6.5.1",
75 | "babel-loader": "8.0.6",
76 | "babel-plugin-named-asset-import": "0.3.6",
77 | "case-sensitive-paths-webpack-plugin": "2.2.0",
78 | "chalk": "3.0.0",
79 | "check-dependencies": "1.1.0",
80 | "classlist-polyfill": "1.2.0",
81 | "core-js": "3.6.4",
82 | "css-loader": "3.4.2",
83 | "cz-conventional-changelog": "2.1.0",
84 | "directory-named-webpack-plugin": "4.0.1",
85 | "dotenv": "8.2.0",
86 | "dotenv-expand": "5.1.0",
87 | "eslint": "7.14.0",
88 | "eslint-config-react-app": "6.0.0",
89 | "eslint-loader": "4.0.2",
90 | "eslint-plugin-flowtype": "4.6.0",
91 | "eslint-plugin-import": "2.22.1",
92 | "eslint-plugin-jsx-a11y": "6.4.1",
93 | "eslint-plugin-react": "7.21.5",
94 | "eslint-plugin-react-hooks": "2.5.0",
95 | "file-loader": "4.3.0",
96 | "fork-ts-checker-webpack-plugin-alt": "0.4.14",
97 | "fs-extra": "8.1.0",
98 | "glob": "7.1.6",
99 | "html-loader": "1.0.0-alpha.0",
100 | "html-webpack-plugin": "4.0.0-beta.11",
101 | "husky": "3.1.0",
102 | "i18next-scanner": "2.10.3",
103 | "imagemin-webpack-plugin": "2.4.2",
104 | "less": "3.11.1",
105 | "less-loader": "5.0.0",
106 | "lint-staged": "9.5.0",
107 | "mini-css-extract-plugin": "0.9.0",
108 | "node-xlsx": "0.15.0",
109 | "optimize-css-assets-webpack-plugin": "5.0.3",
110 | "ora": "4.0.3",
111 | "postcss-flexbugs-fixes": "4.2.0",
112 | "postcss-loader": "3.0.0",
113 | "postcss-preset-env": "6.7.0",
114 | "postcss-safe-parser": "4.0.2",
115 | "prettier": "1.19.1",
116 | "raf-dom": "1.1.0",
117 | "raw-loader": "3.1.0",
118 | "react-dev-utils": "10.1.0",
119 | "rsync": "0.6.1",
120 | "sass": "1.26.2",
121 | "sass-loader": "8.0.2",
122 | "style-loader": "1.1.3",
123 | "stylelint": "12.0.1",
124 | "stylelint-config-recommended": "3.0.0",
125 | "sw-precache-webpack-plugin": "0.11.5",
126 | "terser-webpack-plugin": "2.3.5",
127 | "typescript": "3.7.5",
128 | "webpack": "4.41.6",
129 | "webpack-bundle-analyzer": "^3.6.0",
130 | "webpack-dev-server": "3.10.3"
131 | },
132 | "husky": {
133 | "hooks": {
134 | "pre-commit": "lint-staged && export StagedFiles=$(git diff --name-only --diff-filter AM --relative --staged | grep -E '.tsx?$') && if [ -n \"$StagedFiles\" ]; then npm run tsc; fi",
135 | "commit-msg": "node_modules/.bin/commitlint --edit $HUSKY_GIT_PARAMS",
136 | "pre-push": "CF=$(git diff --diff-filter AM --name-only @{u}..) || CF=$(git diff --diff-filter AM --name-only origin/master...HEAD); FILES=$(echo \"$CF\" | grep -E '^app/.*\\.m?[jt]sx?$'); if [ -n \"$FILES\" ]; then node_modules/.bin/eslint $FILES --max-warnings 0; fi"
137 | }
138 | },
139 | "commitlint": {
140 | "extends": [
141 | "@commitlint/config-conventional"
142 | ],
143 | "rules": {
144 | "subject-case": [
145 | 0
146 | ],
147 | "scope-case": [
148 | 0
149 | ]
150 | }
151 | },
152 | "stylelint": {
153 | "extends": "stylelint-config-recommended"
154 | },
155 | "browserslist": [
156 | ">0.2%",
157 | "not dead",
158 | "not op_mini all",
159 | "ie > 10"
160 | ],
161 | "config": {
162 | "commitizen": {
163 | "path": "cz-conventional-changelog"
164 | }
165 | },
166 | "engines": {
167 | "node": ">=8.10.0",
168 | "tiger-new": "4.3.10"
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/FormItem.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Input, Checkbox, Switch, Radio } from 'antd';
3 | import { render } from '@testing-library/react';
4 | import userEvent from '@testing-library/user-event';
5 | import FormItem from './FormItem';
6 | import { Form, $Formutil } from '..';
7 |
8 | if (!window.matchMedia) {
9 | Object.defineProperty(window, 'matchMedia', {
10 | value: jest.fn((query) => ({
11 | matches: query.includes('max-width'),
12 | addListener: () => {},
13 | removeListener: () => {}
14 | }))
15 | });
16 | }
17 |
18 | function renderForm(content: React.ReactNode) {
19 | let $formutil: $Formutil;
20 |
21 | const wrapper = render(
22 |