mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
chore: 调整 lodash 引用大文件改成异步加载 (#7469)
This commit is contained in:
parent
95d7451af6
commit
f7373c5abf
@ -282,6 +282,10 @@ function handleChange() {
|
||||
amisScoped.unmount();
|
||||
```
|
||||
|
||||
## vue
|
||||
|
||||
可以基于 SDK 版本封装成 component 供 vue 使用,具体请参考示例:https://github.com/aisuda/vue2-amis-demo
|
||||
|
||||
## react
|
||||
|
||||
初始项目请参考 <https://github.com/aisuda/amis-react-starter>。
|
||||
|
69
fis-conf.js
69
fis-conf.js
@ -7,6 +7,7 @@ const package = require('./packages/amis/package.json');
|
||||
const parserMarkdown = require('./scripts/md-parser');
|
||||
const convertSCSSIE11 = require('./scripts/scss-ie11');
|
||||
const parserCodeMarkdown = require('./scripts/code-md-parser');
|
||||
const transformNodeEnvInline = require('./scripts/transform-node-env-inline');
|
||||
fis.set('project.ignore', [
|
||||
'public/**',
|
||||
'scripts/**',
|
||||
@ -28,10 +29,32 @@ Resource.extend({
|
||||
}
|
||||
|
||||
const map = JSON.parse(resourceMap.substring(20, resourceMap.length - 2));
|
||||
const self = this;
|
||||
|
||||
Object.keys(map.res).forEach(function (key) {
|
||||
if (map.res[key].pkg) {
|
||||
map.res[key].pkg = `${versionHash}-${map.res[key].pkg}`;
|
||||
const item = map.res[key];
|
||||
if (item.pkg) {
|
||||
const pkgNode = self.getNode(item.pkg, 'pkg');
|
||||
item.pkg = `${versionHash}-${item.pkg}`;
|
||||
|
||||
if (Array.isArray(item.deps) && pkgNode) {
|
||||
item.deps = item.deps.filter(
|
||||
dep =>
|
||||
!pkgNode.has.find(id => {
|
||||
const node = self.getNode(id);
|
||||
const file = self.getFileById(id);
|
||||
const moduleId =
|
||||
(node.extras && node.extras.moduleId) ||
|
||||
(file && file.moduleId) ||
|
||||
id.replace(/\.js$/i, '');
|
||||
|
||||
return moduleId === dep;
|
||||
})
|
||||
);
|
||||
if (!item.deps.length) {
|
||||
delete item.deps;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
Object.keys(map.pkg).forEach(function (key) {
|
||||
@ -242,6 +265,10 @@ fis.match(
|
||||
}
|
||||
);
|
||||
|
||||
// 过滤掉 process.env.NODE_ENV 分支中无关代码
|
||||
// 避免被分析成依赖,因为 fis 中是通过正则分析 require 语句的
|
||||
fis.on('process:start', transformNodeEnvInline);
|
||||
|
||||
if (fis.project.currentMedia() === 'dev') {
|
||||
fis.match('/packages/**/*.{ts,tsx,js}', {
|
||||
isMod: true
|
||||
@ -371,7 +398,7 @@ fis.match('{monaco-editor,amis,amis-core}/**', {
|
||||
});
|
||||
|
||||
if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
const env = fis.media('publish-sdk');
|
||||
const sdkEnv = fis.media('publish-sdk');
|
||||
|
||||
fis.on('compile:end', function (file) {
|
||||
if (
|
||||
@ -389,32 +416,32 @@ if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
}
|
||||
});
|
||||
|
||||
env.get('project.ignore').push('sdk/**');
|
||||
env.set('project.files', ['examples/sdk-placeholder.html']);
|
||||
sdkEnv.get('project.ignore').push('sdk/**');
|
||||
sdkEnv.set('project.files', ['examples/sdk-placeholder.html']);
|
||||
|
||||
env.match('/{examples,scss,src}/(**)', {
|
||||
sdkEnv.match('/{examples,scss,src}/(**)', {
|
||||
release: '/$1'
|
||||
});
|
||||
|
||||
env.match('*.map', {
|
||||
sdkEnv.match('*.map', {
|
||||
release: false
|
||||
});
|
||||
|
||||
env.match('/node_modules/(**)', {
|
||||
sdkEnv.match('/node_modules/(**)', {
|
||||
release: '/thirds/$1'
|
||||
});
|
||||
|
||||
env.match('/node_modules/(*)/dist/(**)', {
|
||||
sdkEnv.match('/node_modules/(*)/dist/(**)', {
|
||||
release: '/thirds/$1/$2'
|
||||
});
|
||||
|
||||
env.match('*.scss', {
|
||||
sdkEnv.match('*.scss', {
|
||||
parser: fis.plugin('sass', {
|
||||
sourceMap: false
|
||||
})
|
||||
});
|
||||
|
||||
env.match('{*.ts,*.jsx,*.tsx,/examples/**.js,/src/**.js,/src/**.ts}', {
|
||||
sdkEnv.match('{*.ts,*.jsx,*.tsx,/examples/**.js,/src/**.js,/src/**.ts}', {
|
||||
parser: [
|
||||
// docsGennerator,
|
||||
fis.plugin('typescript', {
|
||||
@ -440,19 +467,19 @@ if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
rExt: '.js'
|
||||
});
|
||||
|
||||
env.match('/examples/mod.js', {
|
||||
sdkEnv.match('/examples/mod.js', {
|
||||
isMod: false,
|
||||
optimizer: fis.plugin('terser')
|
||||
});
|
||||
|
||||
env.match('*.{js,jsx,ts,tsx}', {
|
||||
sdkEnv.match('*.{js,jsx,ts,tsx}', {
|
||||
optimizer: fis.plugin('terser'),
|
||||
moduleId: function (m, path) {
|
||||
return fis.util.md5(package.version + 'amis-sdk' + path);
|
||||
}
|
||||
});
|
||||
|
||||
env.match('::package', {
|
||||
sdkEnv.match('::package', {
|
||||
packager: fis.plugin('deps-pack', {
|
||||
'sdk.js': [
|
||||
'examples/mod.js',
|
||||
@ -481,6 +508,7 @@ if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
'!reactcss/**',
|
||||
'!tinycolor2/**',
|
||||
'!cropperjs/**',
|
||||
'!react-json-view/**',
|
||||
'!react-cropper/**',
|
||||
'!jsbarcode/**',
|
||||
'!amis-ui/lib/components/BarCode.js',
|
||||
@ -496,7 +524,8 @@ if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
'!markdown-it-html5-media/**',
|
||||
'!punycode/**',
|
||||
'!office-viewer/**',
|
||||
'!fflate/**'
|
||||
'!fflate/**',
|
||||
'!amis-formula/lib/doc.js'
|
||||
],
|
||||
|
||||
'rich-text.js': [
|
||||
@ -545,6 +574,8 @@ if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
],
|
||||
|
||||
'office-viewer.js': ['office-viewer/**', 'fflate/**'],
|
||||
'json-view.js': 'react-json-view/**',
|
||||
'fomula-doc.js': 'amis-formula/lib/doc.js',
|
||||
|
||||
'rest.js': [
|
||||
'*.js',
|
||||
@ -583,11 +614,11 @@ if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
]
|
||||
});
|
||||
|
||||
env.match('{*.min.js,monaco-editor/min/**.js}', {
|
||||
sdkEnv.match('{*.min.js,monaco-editor/min/**.js}', {
|
||||
optimizer: null
|
||||
});
|
||||
|
||||
env.match('monaco-editor/**.css', {
|
||||
sdkEnv.match('monaco-editor/**.css', {
|
||||
standard: false
|
||||
});
|
||||
|
||||
@ -620,11 +651,11 @@ if (fis.project.currentMedia() === 'publish-sdk') {
|
||||
}
|
||||
});
|
||||
|
||||
env.match('/examples/loader.ts', {
|
||||
sdkEnv.match('/examples/loader.ts', {
|
||||
isMod: false
|
||||
});
|
||||
|
||||
env.match('*', {
|
||||
sdkEnv.match('*', {
|
||||
domain: '.',
|
||||
deploy: [
|
||||
fis.plugin('skip-packed'),
|
||||
|
@ -43,6 +43,10 @@
|
||||
"qs": "6.9.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/generator": "^7.22.9",
|
||||
"@babel/parser": "^7.22.7",
|
||||
"@babel/traverse": "^7.22.8",
|
||||
"@babel/types": "^7.22.5",
|
||||
"@rollup/plugin-replace": "^5.0.1",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/jest": "^28.1.0",
|
||||
@ -70,11 +74,11 @@
|
||||
"fis3-preprocessor-js-require-css": "^0.1.3",
|
||||
"fis3-preprocessor-js-require-file": "^0.1.3",
|
||||
"husky": "^8.0.0",
|
||||
"lint-staged": "^12.1.2",
|
||||
"jest": "^29.0.3",
|
||||
"jest-environment-jsdom": "^29.0.3",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lerna": "^6.6.2",
|
||||
"lint-staged": "^12.1.2",
|
||||
"magic-string": "^0.26.7",
|
||||
"marked": "^4.2.1",
|
||||
"monaco-editor": "0.30.1",
|
||||
|
@ -47,7 +47,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"amis-formula": "^3.3.0-beta.4",
|
||||
"classnames": "2.3.1",
|
||||
"classnames": "2.3.2",
|
||||
"file-saver": "^2.0.2",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"lodash": "^4.17.15",
|
||||
|
@ -126,6 +126,37 @@ function transpileDynamicImportForCJS(options) {
|
||||
};
|
||||
}
|
||||
|
||||
// 参考:https://github.com/theKashey/jsx-compress-loader/blob/master/src/index.js
|
||||
function transpileReactCreateElement() {
|
||||
return {
|
||||
name: 'transpile-react-create-element',
|
||||
enforce: 'post',
|
||||
transform: (code, id) => {
|
||||
if (
|
||||
/\.(?:t|j)sx/.test(id) &&
|
||||
code.indexOf('React.createElement') !== -1
|
||||
) {
|
||||
const separator = '\n\n;';
|
||||
const appendText =
|
||||
`\n` +
|
||||
`var __react_jsx__ = require('react');\n` +
|
||||
`var _J$X_ = (__react_jsx__["default"] || __react_jsx__).createElement;\n` +
|
||||
`var _J$F_ = (__react_jsx__["default"] || __react_jsx__).Fragment;\n`;
|
||||
|
||||
const newSource = code
|
||||
.replace(/React\.createElement\(/g, '_J$X_(')
|
||||
.replace(/React\.createElement\(/g, '_J$F_(');
|
||||
|
||||
code = [appendText, newSource].join(separator);
|
||||
}
|
||||
|
||||
return {
|
||||
code
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getPlugins(format = 'esm') {
|
||||
const overridePaths = ['amis-formula'].reduce(
|
||||
(prev, current) => ({
|
||||
@ -173,11 +204,12 @@ function getPlugins(format = 'esm') {
|
||||
commonjs({
|
||||
sourceMap: false
|
||||
}),
|
||||
format === 'esm' ? null : transpileReactCreateElement(),
|
||||
license({
|
||||
banner: `
|
||||
${name} v${version}
|
||||
Copyright 2018<%= moment().format('YYYY') > 2018 ? '-' + moment().format('YYYY') : null %> ${author}
|
||||
`
|
||||
})
|
||||
];
|
||||
].filter(item => item);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
registerAction
|
||||
} from './Action';
|
||||
import {createObject, filter, render} from '../index';
|
||||
import {reject} from 'lodash';
|
||||
import reject from 'lodash/reject';
|
||||
|
||||
export interface IAlertAction extends ListenerAction {
|
||||
actionType: 'alert';
|
||||
|
@ -590,7 +590,9 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
.fetchInitData(initApi as any, store.data, {
|
||||
successMessage: fetchSuccess,
|
||||
errorMessage: fetchFailed,
|
||||
onSuccess: () => {
|
||||
onSuccess: (json: Payload, data: any) => {
|
||||
store.setValues(data);
|
||||
|
||||
if (
|
||||
!isEffectiveApi(initAsyncApi, store.data) ||
|
||||
store.data[initFinishedField || 'finished']
|
||||
@ -745,7 +747,12 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
);
|
||||
}
|
||||
|
||||
reload(subPath?: string, query?: any, ctx?: any, silent?: boolean) {
|
||||
async reload(
|
||||
subPath?: string,
|
||||
query?: any,
|
||||
ctx?: any,
|
||||
silent?: boolean
|
||||
): Promise<any> {
|
||||
if (query) {
|
||||
return this.receive(query);
|
||||
}
|
||||
@ -763,44 +770,46 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
[initFinishedField || 'finished']: false
|
||||
});
|
||||
|
||||
isEffectiveApi(initApi, store.data)
|
||||
? store
|
||||
.fetchInitData(initApi, store.data, {
|
||||
successMessage: fetchSuccess,
|
||||
errorMessage: fetchFailed,
|
||||
silent,
|
||||
onSuccess: () => {
|
||||
if (
|
||||
!isEffectiveApi(initAsyncApi, store.data) ||
|
||||
store.data[initFinishedField || 'finished']
|
||||
) {
|
||||
return;
|
||||
}
|
||||
if (isEffectiveApi(initApi, store.data)) {
|
||||
const result: Payload = await store.fetchInitData(initApi, store.data, {
|
||||
successMessage: fetchSuccess,
|
||||
errorMessage: fetchFailed,
|
||||
silent,
|
||||
onSuccess: (json: Payload, data: any) => {
|
||||
store.setValues(data);
|
||||
|
||||
return until(
|
||||
() => store.checkRemote(initAsyncApi, store.data),
|
||||
(ret: any) => ret && ret[initFinishedField || 'finished'],
|
||||
cancel => (this.asyncCancel = cancel)
|
||||
);
|
||||
}
|
||||
})
|
||||
.then(async (result: Payload) => {
|
||||
// 派发初始化接口请求完成事件
|
||||
await this.dispatchInited(result);
|
||||
if (
|
||||
!isEffectiveApi(initAsyncApi, store.data) ||
|
||||
store.data[initFinishedField || 'finished']
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result?.ok) {
|
||||
this.initInterval(result);
|
||||
store.reset(undefined, false);
|
||||
}
|
||||
})
|
||||
: store.reset(undefined, false);
|
||||
return until(
|
||||
() => store.checkRemote(initAsyncApi, store.data),
|
||||
(ret: any) => ret && ret[initFinishedField || 'finished'],
|
||||
cancel => (this.asyncCancel = cancel)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// 派发初始化接口请求完成事件
|
||||
await this.dispatchInited(result);
|
||||
|
||||
if (result?.ok) {
|
||||
this.initInterval(result);
|
||||
store.reset(undefined, false);
|
||||
}
|
||||
} else {
|
||||
store.reset(undefined, false);
|
||||
}
|
||||
}
|
||||
|
||||
receive(values: object, name?: string, replace?: boolean) {
|
||||
const {store} = this.props;
|
||||
|
||||
store.updateData(values, undefined, replace);
|
||||
this.reload();
|
||||
return this.reload();
|
||||
}
|
||||
|
||||
silentReload(target?: string, query?: any) {
|
||||
@ -1742,19 +1751,13 @@ export default class Form extends React.Component<FormProps, object> {
|
||||
<input type="submit" style={{display: 'none'}} />
|
||||
|
||||
{debug
|
||||
? render(
|
||||
'form-debug-json',
|
||||
extend(
|
||||
{
|
||||
type: 'json',
|
||||
value: store.data,
|
||||
ellipsisThreshold: 120,
|
||||
className: cx('Form--debug')
|
||||
},
|
||||
/** 定制debug输出格式 */
|
||||
isObject(debugConfig) ? debugConfig : {}
|
||||
)
|
||||
)
|
||||
? render('form-debug-json', {
|
||||
type: 'json',
|
||||
value: store.data,
|
||||
ellipsisThreshold: 120,
|
||||
className: cx('Form--debug'),
|
||||
...debugConfig
|
||||
})
|
||||
: null}
|
||||
|
||||
{render(
|
||||
@ -2009,13 +2012,13 @@ export class FormRenderer extends Form {
|
||||
scoped.close(target);
|
||||
}
|
||||
|
||||
reload(
|
||||
async reload(
|
||||
target?: string,
|
||||
query?: any,
|
||||
ctx?: any,
|
||||
silent?: boolean,
|
||||
replace?: boolean
|
||||
) {
|
||||
): Promise<any> {
|
||||
if (query) {
|
||||
return this.receive(query, undefined, replace);
|
||||
}
|
||||
@ -2045,18 +2048,22 @@ export class FormRenderer extends Form {
|
||||
) {
|
||||
component.reload(subPath, subQuery, ctx);
|
||||
} else if (target === '*') {
|
||||
super.reload(target, query, ctx, silent);
|
||||
await super.reload(target, query, ctx, silent);
|
||||
const components = scoped.getComponents();
|
||||
components.forEach(
|
||||
(component: any) =>
|
||||
component.reload && component.reload('', subQuery, ctx)
|
||||
);
|
||||
} else {
|
||||
super.reload(target, query, ctx, silent);
|
||||
return super.reload(target, query, ctx, silent);
|
||||
}
|
||||
}
|
||||
|
||||
receive(values: object, name?: string, replace?: boolean) {
|
||||
async receive(
|
||||
values: object,
|
||||
name?: string,
|
||||
replace?: boolean
|
||||
): Promise<any> {
|
||||
if (name) {
|
||||
const scoped = this.context as IScopedContext;
|
||||
const idx = name.indexOf('.');
|
||||
|
@ -18,7 +18,8 @@ import {
|
||||
mapObject,
|
||||
keyToPath,
|
||||
isObject,
|
||||
ValidateError
|
||||
ValidateError,
|
||||
extendObject
|
||||
} from '../utils/helper';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import flatten from 'lodash/flatten';
|
||||
@ -395,7 +396,7 @@ export const FormStore = ServiceStore.named('FormStore')
|
||||
throw new ServerError(self.msg, json);
|
||||
} else {
|
||||
updateSavedData();
|
||||
let ret = options && options.onSuccess && options.onSuccess(json);
|
||||
let ret = options?.onSuccess?.(json, json.data);
|
||||
if (ret?.then) {
|
||||
ret = yield ret;
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export const ServiceStore = iRendererStore
|
||||
reInitData(data, replace);
|
||||
self.hasRemoteData = true;
|
||||
if (options && options.onSuccess) {
|
||||
const ret = options.onSuccess(json);
|
||||
const ret = options.onSuccess(json, data);
|
||||
|
||||
if (ret && ret.then) {
|
||||
yield ret;
|
||||
@ -215,7 +215,7 @@ export const ServiceStore = iRendererStore
|
||||
);
|
||||
} else {
|
||||
if (options && options.onSuccess) {
|
||||
const ret = options.onSuccess(json);
|
||||
const ret = options.onSuccess(json, json.data);
|
||||
|
||||
if (ret && ret.then) {
|
||||
yield ret;
|
||||
@ -310,7 +310,7 @@ export const ServiceStore = iRendererStore
|
||||
throw new ServerError(self.msg, json);
|
||||
} else {
|
||||
if (options && options.onSuccess) {
|
||||
const ret = options.onSuccess(json);
|
||||
const ret = options.onSuccess(json, json.data);
|
||||
|
||||
if (ret && ret.then) {
|
||||
yield ret;
|
||||
|
@ -252,7 +252,7 @@ export interface fetchOptions {
|
||||
errorMessage?: string;
|
||||
autoAppend?: boolean;
|
||||
beforeSend?: (data: any) => any;
|
||||
onSuccess?: (json: Payload) => any;
|
||||
onSuccess?: (json: Payload, data: any) => any;
|
||||
onFailed?: (json: Payload) => any;
|
||||
silent?: boolean;
|
||||
[propName: string]: any;
|
||||
|
@ -5,12 +5,13 @@
|
||||
import React, {Component, useEffect, useRef, useState} from 'react';
|
||||
import cx from 'classnames';
|
||||
import {findDOMNode, render} from 'react-dom';
|
||||
import JsonView from 'react-json-view';
|
||||
import {autorun, observable} from 'mobx';
|
||||
import {observer} from 'mobx-react';
|
||||
import {uuidv4} from './helper';
|
||||
import position from './position';
|
||||
|
||||
export const JsonView = React.lazy(() => import('react-json-view'));
|
||||
|
||||
class Log {
|
||||
@observable cat = '';
|
||||
@observable level = '';
|
||||
|
@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {isObject} from 'lodash';
|
||||
import isObject from 'lodash/isObject';
|
||||
import {ClassNamesFn} from '../theme';
|
||||
|
||||
interface IconCheckedSchema {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {OptionValue, Option} from '../types';
|
||||
import {isObject} from './helper';
|
||||
import {isEqual} from 'lodash';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
export function matchOptionValue(
|
||||
a: OptionValue,
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
RendererInfoResolveEventContext
|
||||
} from '../plugin';
|
||||
import {autobind} from '../util';
|
||||
import {omit} from 'lodash';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
export interface SubEditorProps {
|
||||
store: EditorStoreType;
|
||||
|
@ -25,7 +25,7 @@ import type {Schema} from 'amis';
|
||||
import type {DataScope} from 'amis-core';
|
||||
import type {RendererConfig} from 'amis-core';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import {omit} from 'lodash';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
// 创建 Node Store 并构建成树
|
||||
export function makeWrapper(
|
||||
|
@ -1,7 +1,8 @@
|
||||
import {registerEditorPlugin} from '../manager';
|
||||
import {BaseEventContext, BasePlugin, BasicToolbarItem} from '../plugin';
|
||||
import React from 'react';
|
||||
import JsonView, {InteractionProps} from 'react-json-view';
|
||||
import {InteractionProps} from 'react-json-view';
|
||||
export const JsonView = React.lazy(() => import('react-json-view'));
|
||||
|
||||
/**
|
||||
* 添加调试功能
|
||||
@ -98,16 +99,18 @@ export class DataDebugPlugin extends BasePlugin {
|
||||
</ul>
|
||||
</div>
|
||||
<div className="aeDataChain-main">
|
||||
<JsonView
|
||||
name={false}
|
||||
src={stacks[index]}
|
||||
enableClipboard={false}
|
||||
iconStyle="square"
|
||||
onAdd={index === 0 && !readOnly ? emitChange : false}
|
||||
onEdit={index === 0 && !readOnly ? emitChange : false}
|
||||
onDelete={index === 0 && !readOnly ? emitChange : false}
|
||||
collapsed={2}
|
||||
/>
|
||||
<React.Suspense fallback={<div>...</div>}>
|
||||
<JsonView
|
||||
name={false}
|
||||
src={stacks[index]}
|
||||
enableClipboard={false}
|
||||
iconStyle="square"
|
||||
onAdd={index === 0 && !readOnly ? emitChange : false}
|
||||
onEdit={index === 0 && !readOnly ? emitChange : false}
|
||||
onDelete={index === 0 && !readOnly ? emitChange : false}
|
||||
collapsed={2}
|
||||
/>
|
||||
</React.Suspense>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -9,7 +9,8 @@ import isPlainObject from 'lodash/isPlainObject';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
import type {Schema} from 'amis';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {assign, cloneDeep} from 'lodash';
|
||||
import assign from 'lodash/assign';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {getGlobalData} from 'amis-theme-editor-helper';
|
||||
import {isExpression, resolveVariableAndFilter} from 'amis-core';
|
||||
import type {VariableItem} from 'amis-ui';
|
||||
|
@ -23,7 +23,10 @@ import {
|
||||
RendererPluginAction,
|
||||
RendererPluginEvent
|
||||
} from 'amis-editor-core';
|
||||
import {flattenDeep, fromPairs, isObject, remove} from 'lodash';
|
||||
import flattenDeep from 'lodash/flattenDeep';
|
||||
import fromPairs from 'lodash/fromPairs';
|
||||
import isObject from 'lodash/isObject';
|
||||
import remove from 'lodash/remove';
|
||||
import type {ButtonSchema} from 'amis';
|
||||
import type {FormSchema, SchemaObject} from 'amis';
|
||||
import {findTree} from 'amis';
|
||||
|
@ -10,7 +10,8 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
import {isObject, isString} from 'lodash';
|
||||
import isObject from 'lodash/isObject';
|
||||
import isString from 'lodash/isString';
|
||||
import defaultConfig, {
|
||||
OperationMap
|
||||
} from 'amis-ui/lib/components/condition-builder/config';
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
tipedLabel
|
||||
} from 'amis-editor-core';
|
||||
import type {DSField} from 'amis-editor-core';
|
||||
import {fromPairs} from 'lodash';
|
||||
import fromPairs from 'lodash/fromPairs';
|
||||
import type {TabsSchema} from 'amis';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {remarkTpl} from '../component/BaseControl';
|
||||
|
@ -11,7 +11,8 @@ import {
|
||||
Spinner
|
||||
} from 'amis';
|
||||
import {FormControlProps, Renderer, RendererProps} from 'amis-core';
|
||||
import {debounce, remove} from 'lodash';
|
||||
import debounce from 'lodash/debounce';
|
||||
import remove from 'lodash/remove';
|
||||
import React from 'react';
|
||||
import {EditorManager, EditorNodeType, autobind} from 'amis-editor-core';
|
||||
import type {DSField, DSFieldGroup} from 'amis-editor-core';
|
||||
|
@ -7,7 +7,8 @@ import {findDOMNode} from 'react-dom';
|
||||
import cx from 'classnames';
|
||||
import {FormItem, Button, Icon, FormControlProps, autobind} from 'amis';
|
||||
|
||||
import {clone, remove} from 'lodash';
|
||||
import clone from 'lodash/clone';
|
||||
import remove from 'lodash/remove';
|
||||
import {GoConfigControl} from './GoConfigControl';
|
||||
import Sortable from 'sortablejs';
|
||||
|
||||
|
@ -16,7 +16,8 @@ import type {SchemaCollection} from 'amis';
|
||||
import type {IScopedContext} from 'amis-core';
|
||||
import type {FormSchema} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import {fromPairs, some} from 'lodash';
|
||||
import fromPairs from 'lodash/fromPairs';
|
||||
import some from 'lodash/some';
|
||||
|
||||
export interface SwitchMoreProps extends FormControlProps {
|
||||
className?: string;
|
||||
|
@ -7,7 +7,8 @@ import {FormControlProps, FormItem, styleMap} from 'amis-core';
|
||||
// @ts-ignore
|
||||
import {parse as cssParse} from 'amis-postcss';
|
||||
import {PlainObject} from './types';
|
||||
import {debounce, isEmpty} from 'lodash';
|
||||
import debounce from 'lodash/debounce';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
import {Icon} from '../../icons/index';
|
||||
import editorFactory from './themeLanguage';
|
||||
import cx from 'classnames';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {PlainObject} from 'amis-core';
|
||||
import {isEmpty} from 'lodash';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
const conf: any = {
|
||||
ws: '[ \t\n\r\f]*',
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import React from 'react';
|
||||
import {buildApi, Html} from 'amis';
|
||||
import {get} from 'lodash';
|
||||
import get from 'lodash/get';
|
||||
|
||||
setSchemaTpl('api', (patch: any = {}) => {
|
||||
const {name, label, value, description, sampleBuilder, apiDesc, ...rest} =
|
||||
|
@ -9,10 +9,13 @@ import {
|
||||
import type {DSField} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import flatten from 'lodash/flatten';
|
||||
import _ from 'lodash';
|
||||
import {InputComponentName} from '../component/InputComponentName';
|
||||
import {FormulaDateType} from '../renderer/FormulaControl';
|
||||
import {VariableItem} from 'amis-ui/lib/components/formula/Editor';
|
||||
import reduce from 'lodash/reduce';
|
||||
import map from 'lodash/map';
|
||||
import omit from 'lodash/omit';
|
||||
import keys from 'lodash/keys';
|
||||
|
||||
/**
|
||||
* @deprecated 兼容当前组件的switch
|
||||
@ -585,7 +588,7 @@ setSchemaTpl(
|
||||
});
|
||||
}
|
||||
if (schema.options) {
|
||||
let optionItem = _.reduce(
|
||||
let optionItem = reduce(
|
||||
schema.options,
|
||||
function (result, item) {
|
||||
return {...result, ...item};
|
||||
@ -594,12 +597,12 @@ setSchemaTpl(
|
||||
);
|
||||
delete optionItem?.$$id;
|
||||
|
||||
optionItem = _.omit(
|
||||
optionItem = omit(
|
||||
optionItem,
|
||||
_.map(children, item => item?.label)
|
||||
map(children, item => item?.label)
|
||||
);
|
||||
|
||||
let otherItem = _.map(_.keys(optionItem), item => ({
|
||||
let otherItem = map(keys(optionItem), item => ({
|
||||
label:
|
||||
item === 'label' ? '选项文本' : item === 'value' ? '选项值' : item,
|
||||
value: item,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {setSchemaTpl, getSchemaTpl, defaultValue} from 'amis-editor-core';
|
||||
import {isObject} from 'lodash';
|
||||
import isObject from 'lodash/isObject';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
|
||||
setSchemaTpl('horizontal-align', {
|
||||
|
@ -38,7 +38,7 @@
|
||||
"@rc-component/mini-decimal": "^1.0.1",
|
||||
"amis-core": "^3.3.0-beta.4",
|
||||
"amis-formula": "^3.3.0-beta.4",
|
||||
"classnames": "2.3.1",
|
||||
"classnames": "2.3.2",
|
||||
"codemirror": "^5.63.0",
|
||||
"downshift": "6.1.12",
|
||||
"echarts": "5.4.0",
|
||||
@ -64,7 +64,7 @@
|
||||
"react-hook-form": "7.39.0",
|
||||
"react-json-view": "1.21.3",
|
||||
"react-overlays": "5.1.1",
|
||||
"react-textarea-autosize": "8.3.3",
|
||||
"react-textarea-autosize": "8.5.2",
|
||||
"react-transition-group": "4.4.2",
|
||||
"react-visibility-sensor": "5.1.1",
|
||||
"sortablejs": "1.15.0",
|
||||
|
@ -30,6 +30,7 @@ const external = id =>
|
||||
`^(?:${Object.keys(dependencies)
|
||||
.concat([
|
||||
'linkify-it',
|
||||
'react-is',
|
||||
'markdown-it',
|
||||
'markdown-it-html5-media',
|
||||
'mdurl',
|
||||
@ -145,6 +146,37 @@ function transpileDynamicImportForCJS(options) {
|
||||
};
|
||||
}
|
||||
|
||||
// 参考:https://github.com/theKashey/jsx-compress-loader/blob/master/src/index.js
|
||||
function transpileReactCreateElement() {
|
||||
return {
|
||||
name: 'transpile-react-create-element',
|
||||
enforce: 'post',
|
||||
transform: (code, id) => {
|
||||
if (
|
||||
/\.(?:t|j)sx/.test(id) &&
|
||||
code.indexOf('React.createElement') !== -1
|
||||
) {
|
||||
const separator = '\n\n;';
|
||||
const appendText =
|
||||
`\n` +
|
||||
`var __react_jsx__ = require('react');\n` +
|
||||
`var _J$X_ = (__react_jsx__["default"] || __react_jsx__).createElement;\n` +
|
||||
`var _J$F_ = (__react_jsx__["default"] || __react_jsx__).Fragment;\n`;
|
||||
|
||||
const newSource = code
|
||||
.replace(/React\.createElement\(/g, '_J$X_(')
|
||||
.replace(/React\.createElement\(/g, '_J$F_(');
|
||||
|
||||
code = [appendText, newSource].join(separator);
|
||||
}
|
||||
|
||||
return {
|
||||
code
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getPlugins(format = 'esm') {
|
||||
const overridePaths = ['amis-formula', 'amis-core'].reduce(
|
||||
(prev, current) => ({
|
||||
@ -194,13 +226,16 @@ function getPlugins(format = 'esm') {
|
||||
commonjs({
|
||||
sourceMap: false
|
||||
}),
|
||||
|
||||
format === 'esm' ? null : transpileReactCreateElement(),
|
||||
|
||||
license({
|
||||
banner: `
|
||||
${name} v${version}
|
||||
Copyright 2018<%= moment().format('YYYY') > 2018 ? '-' + moment().format('YYYY') : null %> ${author}
|
||||
`
|
||||
})
|
||||
];
|
||||
].filter(item => item);
|
||||
}
|
||||
|
||||
function processSass(context, payload) {
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
Controller as ReactHookFormController,
|
||||
RegisterOptions
|
||||
} from 'react-hook-form';
|
||||
import {method} from 'lodash';
|
||||
import method from 'lodash/method';
|
||||
|
||||
export interface FormFieldProps extends LocaleProps, ThemeProps {
|
||||
mode?: 'normal' | 'horizontal';
|
||||
|
@ -10,7 +10,7 @@ import {isObject} from 'amis-core';
|
||||
import {validations} from 'amis-core';
|
||||
import {Icon} from './icons';
|
||||
import {isObjectShallowModified} from 'amis-core';
|
||||
import {isEmpty} from 'lodash';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
export type textPositionType = 'left' | 'right';
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
import React from 'react';
|
||||
import Sortable from 'sortablejs';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import {cloneDeep} from 'lodash';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
|
||||
import {Option, Options} from './Select';
|
||||
import {ThemeProps, themeable} from 'amis-core';
|
||||
|
@ -2,7 +2,9 @@
|
||||
* 结果树(暂时不支持结果排序)
|
||||
*/
|
||||
import React from 'react';
|
||||
import {cloneDeep, isEqual, omit} from 'lodash';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
import {Option, Options} from './Select';
|
||||
import {ThemeProps, themeable} from 'amis-core';
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import _ from 'lodash';
|
||||
import isInteger from 'lodash/isInteger';
|
||||
import debounce from 'lodash/debounce';
|
||||
import moment from 'moment';
|
||||
@ -8,6 +7,7 @@ import {Icon} from './icons';
|
||||
import {uncontrollable} from 'amis-core';
|
||||
import {autobind, isMobile} from 'amis-core';
|
||||
import {LocaleProps, localeable} from 'amis-core';
|
||||
import chain from 'lodash/chain';
|
||||
|
||||
export interface HistoryRecord {
|
||||
/** 历史记录值 */
|
||||
@ -211,7 +211,7 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
|
||||
try {
|
||||
const storageValues = localStorage.getItem(key);
|
||||
|
||||
return _.chain(storageValues ? JSON.parse(storageValues) : [])
|
||||
return chain(storageValues ? JSON.parse(storageValues) : [])
|
||||
.uniqBy('value')
|
||||
.orderBy(['timestamp'], ['desc'])
|
||||
.slice(0, limit)
|
||||
@ -257,7 +257,7 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
|
||||
|
||||
try {
|
||||
const {key, limit} = this.getHistoryOptions();
|
||||
const newDatasource = _.chain([
|
||||
const newDatasource = chain([
|
||||
...datasource,
|
||||
{value, timestamp: moment().unix()}
|
||||
])
|
||||
|
@ -7,7 +7,8 @@ import {Option} from './Select';
|
||||
import {resolveVariable} from 'amis-core';
|
||||
import {localeable} from 'amis-core';
|
||||
import VirtualList, {AutoSizer, RenderedRows} from './virtual-list';
|
||||
import {isEqual, forEach} from 'lodash';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import forEach from 'lodash/forEach';
|
||||
|
||||
export interface TableSelectionProps extends BaseSelectionProps {
|
||||
/** 是否为结果渲染列表 */
|
||||
|
@ -1,13 +1,10 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
intersectionWith,
|
||||
differenceWith,
|
||||
includes,
|
||||
debounce,
|
||||
result,
|
||||
isEqual,
|
||||
unionWith
|
||||
} from 'lodash';
|
||||
import intersectionWith from 'lodash/intersectionWith';
|
||||
import differenceWith from 'lodash/differenceWith';
|
||||
import includes from 'lodash/includes';
|
||||
import debounce from 'lodash/debounce';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import unionWith from 'lodash/unionWith';
|
||||
|
||||
import {ThemeProps, themeable, findTree} from 'amis-core';
|
||||
import {BaseSelectionProps, BaseSelection, ItemRenderStates} from './Selection';
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Tranasfer搜索
|
||||
*/
|
||||
import React from 'react';
|
||||
import {debounce} from 'lodash';
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
import {ThemeProps, themeable} from 'amis-core';
|
||||
import {Icon} from './icons';
|
||||
|
@ -14,7 +14,6 @@ import {
|
||||
eachTree
|
||||
} from 'amis-core';
|
||||
import {functionDocs} from 'amis-formula';
|
||||
import {doc} from 'amis-formula/lib/doc';
|
||||
import type {FunctionDocMap} from 'amis-formula/lib/types';
|
||||
|
||||
import {FormulaPlugin, editorFactory} from './plugin';
|
||||
@ -107,6 +106,7 @@ export interface FunctionProps {
|
||||
}
|
||||
|
||||
export interface FormulaState {
|
||||
functions: FuncGroup[];
|
||||
focused: boolean;
|
||||
isCodeMode: boolean;
|
||||
expandTree: boolean;
|
||||
@ -121,9 +121,11 @@ export class FormulaEditor extends React.Component<
|
||||
focused: false,
|
||||
isCodeMode: false,
|
||||
expandTree: false,
|
||||
normalizeVariables: []
|
||||
normalizeVariables: [],
|
||||
functions: []
|
||||
};
|
||||
editorPlugin?: FormulaPlugin;
|
||||
unmounted: boolean = false;
|
||||
|
||||
static buildDefaultFunctions(
|
||||
doc: Array<{
|
||||
@ -244,6 +246,7 @@ export class FormulaEditor extends React.Component<
|
||||
componentDidMount(): void {
|
||||
const {variables} = this.props;
|
||||
this.normalizeVariables(variables as VariableItem[]);
|
||||
this.buildFunctions();
|
||||
}
|
||||
|
||||
componentDidUpdate(
|
||||
@ -254,10 +257,33 @@ export class FormulaEditor extends React.Component<
|
||||
if (prevProps.variables !== this.props.variables) {
|
||||
this.normalizeVariables(this.props.variables as VariableItem[]);
|
||||
}
|
||||
|
||||
if (prevProps.functions !== this.props.functions) {
|
||||
this.buildFunctions();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.editorPlugin?.dispose();
|
||||
this.unmounted = true;
|
||||
}
|
||||
|
||||
async buildFunctions() {
|
||||
const {doc} = await import('amis-formula/lib/doc');
|
||||
if (this.unmounted) {
|
||||
return;
|
||||
}
|
||||
const customFunctions = Array.isArray(this.props.functions)
|
||||
? this.props.functions
|
||||
: [];
|
||||
const functionList = [
|
||||
...FormulaEditor.buildDefaultFunctions(doc),
|
||||
...FormulaEditor.buildCustomFunctions(functionDocs),
|
||||
...customFunctions
|
||||
];
|
||||
this.setState({
|
||||
functions: functionList
|
||||
});
|
||||
}
|
||||
|
||||
normalizeVariables(variables?: Array<VariableItem>) {
|
||||
@ -414,13 +440,13 @@ export class FormulaEditor extends React.Component<
|
||||
classPrefix,
|
||||
selfVariableName
|
||||
} = this.props;
|
||||
const {focused, isCodeMode, expandTree, normalizeVariables} = this.state;
|
||||
const customFunctions = Array.isArray(functions) ? functions : [];
|
||||
const functionList = [
|
||||
...FormulaEditor.buildDefaultFunctions(doc),
|
||||
...FormulaEditor.buildCustomFunctions(functionDocs),
|
||||
...customFunctions
|
||||
];
|
||||
const {
|
||||
focused,
|
||||
isCodeMode,
|
||||
expandTree,
|
||||
normalizeVariables,
|
||||
functions: functionList
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -27,6 +27,10 @@ export function FuncList(props: FuncListProps) {
|
||||
const [filteredFuncs, setFiteredFuncs] = React.useState(props.data);
|
||||
const [activeFunc, setActiveFunc] = React.useState<any>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
setFiteredFuncs(props.data);
|
||||
}, [props.data]);
|
||||
|
||||
function onSearch(term: string) {
|
||||
const filtered = props.data
|
||||
.map(item => {
|
||||
|
@ -101,7 +101,7 @@ import NewEdit from '../icons/new-edit.svg';
|
||||
import RotateLeft from '../icons/rotate-left.svg';
|
||||
import RotateRight from '../icons/rotate-right.svg';
|
||||
import ScaleOrigin from '../icons/scale-origin.svg';
|
||||
import {isObject} from 'lodash';
|
||||
import isObject from 'lodash/isObject';
|
||||
|
||||
// 兼容原来的用法,后续不直接试用。
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -364,7 +364,7 @@ test('doAction:form setValue', async () => {
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('doAction:form reload', async () => {
|
||||
test('doAction:form reload default', async () => {
|
||||
const notify = jest.fn();
|
||||
const fetcher = jest.fn().mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
@ -427,31 +427,33 @@ test('doAction:form reload', async () => {
|
||||
)
|
||||
);
|
||||
|
||||
fireEvent.change(container.querySelector('[name="author"]')!, {
|
||||
await wait(200); // 等待 initApi 加载完
|
||||
expect(
|
||||
(container.querySelector('[name="author"]') as HTMLInputElement).value
|
||||
).toEqual('fex');
|
||||
|
||||
const author: HTMLInputElement = container.querySelector('[name="author"]')!;
|
||||
fireEvent.change(author, {
|
||||
target: {value: 'amis'}
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect((container.querySelector('[name="author"]') as any)?.value).toEqual(
|
||||
'amis'
|
||||
);
|
||||
});
|
||||
expect(
|
||||
(container.querySelector('[name="author"]') as HTMLInputElement).value
|
||||
).toEqual('amis');
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
// expect(container).toMatchSnapshot();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText('刷新表单')).toBeInTheDocument();
|
||||
});
|
||||
await wait(200);
|
||||
expect(getByText('刷新表单')).toBeInTheDocument();
|
||||
fireEvent.click(getByText('刷新表单'));
|
||||
|
||||
fireEvent.click(getByText(/刷新表单/));
|
||||
await wait(200);
|
||||
|
||||
await waitFor(() => {
|
||||
expect((container.querySelector('[name="author"]') as any)?.value).toEqual(
|
||||
'fex'
|
||||
);
|
||||
});
|
||||
expect(
|
||||
(container.querySelector('[name="author"]') as HTMLInputElement).value
|
||||
).toEqual('fex');
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
// expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('doAction:form reload with data', async () => {
|
||||
@ -525,34 +527,23 @@ test('doAction:form reload with data', async () => {
|
||||
)
|
||||
);
|
||||
|
||||
fireEvent.change(container.querySelector('[name="author"]')!, {
|
||||
await wait(200);
|
||||
const author: HTMLInputElement = container.querySelector('[name="author"]')!;
|
||||
expect(author).toBeInTheDocument();
|
||||
fireEvent.change(author, {
|
||||
target: {value: 'amis'}
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect((container.querySelector('[name="author"]') as any)?.value).toEqual(
|
||||
'amis'
|
||||
);
|
||||
});
|
||||
await wait(200);
|
||||
expect(author.value).toEqual('amis');
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
expect(getByText('刷新表单')).toBeInTheDocument();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(getByText('刷新表单')).toBeInTheDocument();
|
||||
});
|
||||
fireEvent.click(getByText('刷新表单'));
|
||||
await wait(200);
|
||||
|
||||
fireEvent.click(getByText(/刷新表单/));
|
||||
|
||||
await waitFor(() => {
|
||||
expect((container.querySelector('[name="author"]') as any)?.value).toEqual(
|
||||
'fex'
|
||||
);
|
||||
expect((container.querySelector('[name="age"]') as any)?.value).toEqual(
|
||||
'18'
|
||||
);
|
||||
});
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
expect(author.value).toEqual('fex');
|
||||
expect((container.querySelector('[name="age"]') as any)?.value).toEqual('18');
|
||||
});
|
||||
|
||||
test('doAction:form reset', async () => {
|
||||
@ -707,6 +698,7 @@ test('doAction:form clear', async () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(200);
|
||||
await waitFor(() => {
|
||||
expect(getByText('清空表单')).toBeInTheDocument();
|
||||
});
|
||||
|
@ -96,6 +96,7 @@ test('EventAction:inputRange', async () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(200);
|
||||
const inputs = container.querySelector('.cxd-InputRange-input input')!;
|
||||
|
||||
// input change
|
||||
|
@ -221,7 +221,157 @@ exports[`Renderer:input table 1`] = `
|
||||
<div
|
||||
class="cxd-Form-item cxd-Form-item--normal"
|
||||
data-role="form-item"
|
||||
/>
|
||||
>
|
||||
<div
|
||||
class="cxd-InputTable cxd-Form-control"
|
||||
>
|
||||
<div
|
||||
class="cxd-Table"
|
||||
>
|
||||
<div
|
||||
class="cxd-Table-contentWrap"
|
||||
>
|
||||
<div
|
||||
class="cxd-Table-content"
|
||||
>
|
||||
<table
|
||||
class="cxd-Table-table"
|
||||
>
|
||||
<colgroup>
|
||||
<col
|
||||
data-index="3"
|
||||
/>
|
||||
<col
|
||||
data-index="4"
|
||||
/>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr
|
||||
class=""
|
||||
>
|
||||
<th
|
||||
class=""
|
||||
data-index="3"
|
||||
>
|
||||
<div
|
||||
class="cxd-TableCell--title"
|
||||
>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
<span>
|
||||
A
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-Table-content-colDragLine"
|
||||
data-index="3"
|
||||
/>
|
||||
</th>
|
||||
<th
|
||||
class=""
|
||||
data-index="4"
|
||||
>
|
||||
<div
|
||||
class="cxd-TableCell--title"
|
||||
>
|
||||
<span
|
||||
class="cxd-TplField"
|
||||
>
|
||||
<span>
|
||||
B
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-Table-content-colDragLine"
|
||||
data-index="4"
|
||||
/>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
class="cxd-Table-tr--odd cxd-Table-tr--1th"
|
||||
data-id="1"
|
||||
data-index="0"
|
||||
>
|
||||
<td
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="cxd-PlainField"
|
||||
>
|
||||
a1
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="cxd-PlainField"
|
||||
>
|
||||
b1
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="cxd-Table-tr--even cxd-Table-tr--1th"
|
||||
data-id="2"
|
||||
data-index="1"
|
||||
>
|
||||
<td
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="cxd-PlainField"
|
||||
>
|
||||
a2
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="cxd-PlainField"
|
||||
>
|
||||
b2
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr
|
||||
class="cxd-Table-tr--odd cxd-Table-tr--1th"
|
||||
data-id="3"
|
||||
data-index="2"
|
||||
>
|
||||
<td
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="cxd-PlainField"
|
||||
>
|
||||
a3
|
||||
</span>
|
||||
</td>
|
||||
<td
|
||||
class=""
|
||||
>
|
||||
<span
|
||||
class="cxd-PlainField"
|
||||
>
|
||||
b3
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<span />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
|
@ -2,7 +2,7 @@ import React = require('react');
|
||||
import {fireEvent, render, screen} from '@testing-library/react';
|
||||
import '../../../src';
|
||||
import {render as amisRender} from '../../../src';
|
||||
import {makeEnv} from '../../helper';
|
||||
import {makeEnv, wait} from '../../helper';
|
||||
|
||||
test('Renderer:input-formula', async () => {
|
||||
const {container, findByText, findByDisplayValue} = render(
|
||||
@ -78,6 +78,7 @@ test('Renderer:input-formula', async () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(200);
|
||||
expect(container).toMatchSnapshot();
|
||||
|
||||
await findByDisplayValue('SUM(1 + 2)');
|
||||
@ -103,7 +104,7 @@ test('Renderer:input-formula', async () => {
|
||||
// });
|
||||
});
|
||||
|
||||
test('Renderer:input-formula button', () => {
|
||||
test('Renderer:input-formula button', async () => {
|
||||
const {container} = render(
|
||||
amisRender(
|
||||
{
|
||||
@ -179,10 +180,11 @@ test('Renderer:input-formula button', () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(200);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('Renderer:input-formula input-group', () => {
|
||||
test('Renderer:input-formula input-group', async () => {
|
||||
const {container} = render(
|
||||
amisRender(
|
||||
{
|
||||
@ -258,5 +260,6 @@ test('Renderer:input-formula input-group', () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(200);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ afterEach(() => {
|
||||
clearStoresCache();
|
||||
});
|
||||
|
||||
test('Renderer:input table', () => {
|
||||
test('Renderer:input table', async () => {
|
||||
const {container} = render(
|
||||
amisRender(
|
||||
{
|
||||
@ -62,6 +62,7 @@ test('Renderer:input table', () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(300);
|
||||
replaceReactAriaIds(container);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
@ -175,6 +176,7 @@ test('Renderer:input table add', async () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(200);
|
||||
const add = await findByText(/新增/);
|
||||
|
||||
fireEvent.click(add);
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React = require('react');
|
||||
import {render} from '@testing-library/react';
|
||||
import {render, waitFor} from '@testing-library/react';
|
||||
import '../../src';
|
||||
import {render as amisRender} from '../../src';
|
||||
import {makeEnv} from '../helper';
|
||||
import {makeEnv, wait} from '../helper';
|
||||
|
||||
test('Renderer:json', () => {
|
||||
test('Renderer:json', async () => {
|
||||
const {container} = render(
|
||||
amisRender(
|
||||
{
|
||||
@ -25,5 +25,6 @@ test('Renderer:json', () => {
|
||||
)
|
||||
);
|
||||
|
||||
await wait(1000);
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
@ -41,7 +41,7 @@
|
||||
"amis-ui": "^3.3.0-beta.4",
|
||||
"attr-accept": "2.2.2",
|
||||
"blueimp-canvastoblob": "2.1.0",
|
||||
"classnames": "2.3.1",
|
||||
"classnames": "2.3.2",
|
||||
"downshift": "6.1.12",
|
||||
"echarts": "5.4.0",
|
||||
"echarts-stat": "^1.2.0",
|
||||
|
@ -114,6 +114,37 @@ function transpileDynamicImportForCJS(options) {
|
||||
};
|
||||
}
|
||||
|
||||
// 参考:https://github.com/theKashey/jsx-compress-loader/blob/master/src/index.js
|
||||
function transpileReactCreateElement() {
|
||||
return {
|
||||
name: 'transpile-react-create-element',
|
||||
enforce: 'post',
|
||||
transform: (code, id) => {
|
||||
if (
|
||||
/\.(?:t|j)sx/.test(id) &&
|
||||
code.indexOf('React.createElement') !== -1
|
||||
) {
|
||||
const separator = '\n\n;';
|
||||
const appendText =
|
||||
`\n` +
|
||||
`var __react_jsx__ = require('react');\n` +
|
||||
`var _J$X_ = (__react_jsx__["default"] || __react_jsx__).createElement;\n` +
|
||||
`var _J$F_ = (__react_jsx__["default"] || __react_jsx__).Fragment;\n`;
|
||||
|
||||
const newSource = code
|
||||
.replace(/React\.createElement\(/g, '_J$X_(')
|
||||
.replace(/React\.createElement\(/g, '_J$F_(');
|
||||
|
||||
code = [appendText, newSource].join(separator);
|
||||
}
|
||||
|
||||
return {
|
||||
code
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getPlugins(format = 'esm') {
|
||||
const overridePaths = [
|
||||
'amis-formula',
|
||||
@ -169,11 +200,12 @@ function getPlugins(format = 'esm') {
|
||||
commonjs({
|
||||
sourceMap: false
|
||||
}),
|
||||
format === 'esm' ? null : transpileReactCreateElement(),
|
||||
license({
|
||||
banner: `
|
||||
${name} v${version}
|
||||
Copyright 2018<%= moment().format('YYYY') > 2018 ? '-' + moment().format('YYYY') : null %> ${author}
|
||||
`
|
||||
})
|
||||
];
|
||||
].filter(item => item);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import {ActionObject} from 'amis-core';
|
||||
import {FormOptionsSchema} from '../../Schema';
|
||||
import {supportStatic} from './StaticHoc';
|
||||
import find from 'lodash/find';
|
||||
import {isEmpty} from 'lodash';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
/**
|
||||
* 链式下拉框
|
||||
|
@ -1,10 +1,12 @@
|
||||
import React from 'react';
|
||||
import {Renderer, RendererProps} from 'amis-core';
|
||||
|
||||
import JsonView, {InteractionProps} from 'react-json-view';
|
||||
import type {InteractionProps} from 'react-json-view';
|
||||
import {autobind, getPropValue, noop} from 'amis-core';
|
||||
import {BaseSchema} from '../Schema';
|
||||
import {resolveVariableAndFilter, isPureVariable} from 'amis-core';
|
||||
|
||||
export const JsonView = React.lazy(() => import('react-json-view'));
|
||||
/**
|
||||
* JSON 数据展示控件。
|
||||
* 文档:https://aisuda.bce.baidu.com/amis/zh-CN/components/json
|
||||
@ -158,21 +160,23 @@ export class JSONField extends React.Component<JSONProps, object> {
|
||||
{typeof data === 'undefined' || data === null ? (
|
||||
placeholder
|
||||
) : (
|
||||
<JsonView
|
||||
name={false}
|
||||
src={data}
|
||||
theme={(jsonThemeValue as any) ?? 'rjv-default'}
|
||||
shouldCollapse={this.shouldExpandNode}
|
||||
enableClipboard={enableClipboard}
|
||||
displayDataTypes={displayDataTypes}
|
||||
collapseStringsAfterLength={ellipsisThreshold}
|
||||
iconStyle={iconStyle}
|
||||
quotesOnKeys={quotesOnKeys}
|
||||
sortKeys={sortKeys}
|
||||
onEdit={name && mutable ? this.emitChange : false}
|
||||
onDelete={name && mutable ? this.emitChange : false}
|
||||
onAdd={name && mutable ? this.emitChange : false}
|
||||
/>
|
||||
<React.Suspense fallback={<div>...</div>}>
|
||||
<JsonView
|
||||
name={false}
|
||||
src={data}
|
||||
theme={(jsonThemeValue as any) ?? 'rjv-default'}
|
||||
shouldCollapse={this.shouldExpandNode}
|
||||
enableClipboard={enableClipboard}
|
||||
displayDataTypes={displayDataTypes}
|
||||
collapseStringsAfterLength={ellipsisThreshold}
|
||||
iconStyle={iconStyle}
|
||||
quotesOnKeys={quotesOnKeys}
|
||||
sortKeys={sortKeys}
|
||||
onEdit={name && mutable ? this.emitChange : false}
|
||||
onDelete={name && mutable ? this.emitChange : false}
|
||||
onAdd={name && mutable ? this.emitChange : false}
|
||||
/>
|
||||
</React.Suspense>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -34,7 +34,7 @@ import {ActionSchema} from './Action';
|
||||
import {tokenize, evalExpressionWithConditionBuilder} from 'amis-core';
|
||||
import {StepSchema} from './Steps';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import {omit} from 'lodash';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
export type WizardStepSchema = Omit<FormSchema, 'type'> &
|
||||
StepSchema & {
|
||||
|
@ -12,27 +12,60 @@ const readInterface = readline.createInterface({
|
||||
let currentModule = '';
|
||||
let moduleSizeMap = {};
|
||||
|
||||
readInterface.on('line', (line) => {
|
||||
if (line.startsWith(`;/*`)) {
|
||||
currentModule = line.trim();
|
||||
}
|
||||
if (currentModule in moduleSizeMap) {
|
||||
moduleSizeMap[currentModule] += line.length;
|
||||
} else {
|
||||
moduleSizeMap[currentModule] = line.length;
|
||||
}
|
||||
}).on('close', () => {
|
||||
let sizeArray = [];
|
||||
for (let module in moduleSizeMap) {
|
||||
sizeArray.push([module, moduleSizeMap[module]]);
|
||||
}
|
||||
readInterface
|
||||
.on('line', line => {
|
||||
if (line.startsWith(`;/*`)) {
|
||||
currentModule = line.trim();
|
||||
}
|
||||
if (currentModule in moduleSizeMap) {
|
||||
moduleSizeMap[currentModule] += line.length;
|
||||
} else {
|
||||
moduleSizeMap[currentModule] = line.length;
|
||||
}
|
||||
})
|
||||
.on('close', () => {
|
||||
const moduleSize2Map = {};
|
||||
let sizeArray = [];
|
||||
for (let module in moduleSizeMap) {
|
||||
sizeArray.push([module, moduleSizeMap[module]]);
|
||||
|
||||
sizeArray.sort(function(a, b) {
|
||||
return a[1] - b[1];
|
||||
const parts = module.substring(4, module.length - 2).split('/');
|
||||
while (parts.length > 1 && parts[parts.length - 2] !== 'node_modules') {
|
||||
if (
|
||||
parts[parts.length - 3] === 'node_modules' &&
|
||||
parts[parts.length - 2][0] === '@'
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
parts.pop();
|
||||
}
|
||||
if (parts[0] === 'node_modules') {
|
||||
parts.shift();
|
||||
}
|
||||
const moduleName = parts.join('/');
|
||||
moduleSize2Map[moduleName] = moduleSize2Map[moduleName] || 0;
|
||||
moduleSize2Map[moduleName] += moduleSizeMap[module];
|
||||
}
|
||||
|
||||
sizeArray.sort(function (a, b) {
|
||||
return a[1] - b[1];
|
||||
});
|
||||
|
||||
for (size of sizeArray) {
|
||||
console.log(size[0], size[1]);
|
||||
}
|
||||
|
||||
console.log('\n\n\npackages\n\n');
|
||||
|
||||
const sizeArray2 = [];
|
||||
for (let module in moduleSize2Map) {
|
||||
sizeArray2.push([module, moduleSize2Map[module]]);
|
||||
}
|
||||
sizeArray2.sort(function (a, b) {
|
||||
return a[1] - b[1];
|
||||
});
|
||||
for (size of sizeArray2) {
|
||||
console.log(size[0], size[1]);
|
||||
}
|
||||
});
|
||||
|
||||
for (size of sizeArray) {
|
||||
console.log(size[0], size[1]);
|
||||
}
|
||||
});
|
||||
|
||||
|
90
scripts/transform-node-env-inline.js
Normal file
90
scripts/transform-node-env-inline.js
Normal file
@ -0,0 +1,90 @@
|
||||
const parse = require('@babel/parser').parse;
|
||||
const traverse = require('@babel/traverse').default;
|
||||
const generate = require('@babel/generator').default;
|
||||
const types = require('@babel/types');
|
||||
|
||||
module.exports = function transformNodeEnvInline(file) {
|
||||
// if (file.subpath !== '/node_modules/mobx/lib/index.js') {
|
||||
// return;
|
||||
// }
|
||||
|
||||
if (!file.isJsLike || !file.isMod) {
|
||||
return;
|
||||
}
|
||||
|
||||
let contents = file.getContent();
|
||||
const idx = contents.indexOf('process.env.NODE_ENV');
|
||||
if (idx === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const idx2 = contents.indexOf('require(', idx);
|
||||
if (idx2 === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const env = file.optimizer ? 'production' : 'development';
|
||||
|
||||
contents = contents.replace(/typeof\s+process\b/g, () =>
|
||||
JSON.stringify('object')
|
||||
);
|
||||
const ast = parse(contents, {
|
||||
sourceType: 'module'
|
||||
});
|
||||
|
||||
traverse(ast, {
|
||||
// 参考: https://www.trickster.dev/post/javascript-ast-manipulation-with-babel-removing-unreachable-code/
|
||||
// 参考:https://github.com/babel/minify/blob/master/packages/babel-plugin-transform-node-env-inline/src/index.js
|
||||
MemberExpression(path) {
|
||||
if (path.matchesPattern('process.env.NODE_ENV')) {
|
||||
path.replaceWith(types.valueToNode(env));
|
||||
let parentPath = path.parentPath;
|
||||
if (parentPath.isBinaryExpression()) {
|
||||
const evaluated = parentPath.evaluate();
|
||||
if (evaluated.confident) {
|
||||
parentPath.replaceWith(types.valueToNode(evaluated.value));
|
||||
}
|
||||
}
|
||||
|
||||
let ifStatement = null;
|
||||
while (parentPath) {
|
||||
if (
|
||||
parentPath.isIfStatement() ||
|
||||
parentPath.isConditionalExpression()
|
||||
) {
|
||||
ifStatement = parentPath;
|
||||
}
|
||||
|
||||
parentPath = parentPath.parentPath;
|
||||
}
|
||||
|
||||
if (ifStatement) {
|
||||
let isTruthy = ifStatement.get('test').evaluateTruthy();
|
||||
const node = ifStatement.node;
|
||||
|
||||
if (isTruthy) {
|
||||
if (types.isBlockStatement(node.consequent)) {
|
||||
ifStatement.replaceWithMultiple(node.consequent.body);
|
||||
} else {
|
||||
ifStatement.replaceWith(node.consequent);
|
||||
}
|
||||
} else if (node.alternate != null) {
|
||||
if (types.isBlockStatement(node.alternate)) {
|
||||
ifStatement.replaceWithMultiple(node.alternate.body);
|
||||
} else {
|
||||
ifStatement.replaceWith(node.alternate);
|
||||
}
|
||||
} else {
|
||||
ifStatement.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
contents = generate(ast, {}).code;
|
||||
file.setContent(contents);
|
||||
|
||||
// console.log('\n', file.subpath, '\n', file.getContent());
|
||||
// process.exit(1);
|
||||
};
|
Loading…
Reference in New Issue
Block a user