deps: 更新部分第三方库依赖到最新版本 (#2543)

* chore: 更新依赖初步

* 更新部分依赖

* 修复编译报错

* 更新 snapshots
This commit is contained in:
吴多益 2021-09-13 10:30:30 +08:00 committed by GitHub
parent 54c13b9809
commit 3641be8d78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 695 additions and 654 deletions

View File

@ -83,13 +83,9 @@ exports[`Renderer:formula 1`] = `
class="cxd-Number-input-wrap"
>
<input
aria-valuemax="9007199254740991"
aria-valuemin="-9007199254740991"
aria-valuenow="1"
autocomplete="off"
class="cxd-Number-input"
max="9007199254740991"
min="-9007199254740991"
role="spinbutton"
step="1"
value="1"
@ -153,13 +149,9 @@ exports[`Renderer:formula 1`] = `
class="cxd-Number-input-wrap"
>
<input
aria-valuemax="9007199254740991"
aria-valuemin="-9007199254740991"
aria-valuenow="2"
autocomplete="off"
class="cxd-Number-input"
max="9007199254740991"
min="-9007199254740991"
role="spinbutton"
step="1"
value="2"
@ -223,13 +215,9 @@ exports[`Renderer:formula 1`] = `
class="cxd-Number-input-wrap"
>
<input
aria-valuemax="9007199254740991"
aria-valuemin="-9007199254740991"
aria-valuenow="3"
autocomplete="off"
class="cxd-Number-input"
max="9007199254740991"
min="-9007199254740991"
role="spinbutton"
step="1"
value="3"
@ -293,13 +281,9 @@ exports[`Renderer:formula 1`] = `
class="cxd-Number-input-wrap"
>
<input
aria-valuemax="9007199254740991"
aria-valuemin="-9007199254740991"
aria-valuenow="4"
autocomplete="off"
class="cxd-Number-input"
max="9007199254740991"
min="-9007199254740991"
role="spinbutton"
step="1"
value="4"
@ -363,13 +347,9 @@ exports[`Renderer:formula 1`] = `
class="cxd-Number-input-wrap"
>
<input
aria-valuemax="9007199254740991"
aria-valuemin="-9007199254740991"
aria-valuenow="5"
autocomplete="off"
class="cxd-Number-input"
max="9007199254740991"
min="-9007199254740991"
role="spinbutton"
step="1"
value="5"

View File

@ -83,13 +83,9 @@ exports[`Renderer:number 1`] = `
class="cxd-Number-input-wrap"
>
<input
aria-valuemax="9007199254740991"
aria-valuemin="-9007199254740991"
aria-valuenow="456"
autocomplete="off"
class="cxd-Number-input"
max="9007199254740991"
min="-9007199254740991"
role="spinbutton"
step="1"
value="456"

View File

@ -741,25 +741,25 @@ props.onAction(event, {
所有`actionType`都支持的通用配置项
| 属性名 | 类型 | 默认值 | 说明 |
| ---------------- | ------------------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type | `string` | `action` | 指定为 Page 渲染器。 |
| actionType | `string` | - | 【必填】这是 action 最核心的配置,来指定该 action 的作用类型,支持:`ajax`、`link`、`url`、`drawer`、`dialog`、`confirm`、`cancel`、`prev`、`next`、`copy`、`close`。 |
| label | `string` | - | 按钮文本。可用 `${xxx}` 取值。 |
| level | `string` | `default` | 按钮样式,支持:`link`、`primary`、`secondary`、`info`、`success`、`warning`、`danger`、`light`、`dark`、`default`。 |
| size | `string` | - | 按钮大小,支持:`xs`、`sm`、`md`、`lg`。 |
| icon | `string` | - | 设置图标,例如`fa fa-plus`。 |
| iconClassName | `string` | - | 给图标上添加类名。 |
| rightIcon | `string` | - | 在按钮文本右侧设置图标,例如`fa fa-plus`。 |
| rightIconClassName | `string` | - | 给右侧图标上添加类名。 |
| active | `boolean` | - | 按钮是否高亮。 |
| activeLevel | `string` | - | 按钮高亮时的样式,配置支持同`level`。 |
| activeClassName | `string` | `is-active` | 给按钮高亮添加类名。 |
| block | `boolean` | - | 用`display:"block"`来显示按钮。 |
| confirmText | [模板](../../docs/concepts/template) | - | 当设置后,操作在开始前会询问用户。可用 `${xxx}` 取值。 |
| reload | `string` | - | 指定此次操作完后,需要刷新的目标组件名字(组件的`name`值,自己配置的),多个请用 `,` 号隔开。 |
| tooltip | `string` | - | 鼠标停留时弹出该段文字,也可以配置对象类型:字段为`title`和`content`。可用 `${xxx}` 取值。 |
| disabledTip | `string` | - | 被禁用后鼠标停留时弹出该段文字,也可以配置对象类型:字段为`title`和`content`。可用 `${xxx}` 取值。 |
| tooltipPlacement | `string` | `top` | 如果配置了`tooltip`或者`disabledTip`,指定提示信息位置,可配置`top`、`bottom`、`left`、`right`。 |
| close | `boolean` or `string` | - | 当`action`配置在`dialog`或`drawer`的`actions`中时,配置为`true`指定此次操作完后关闭当前`dialog`或`drawer`。当值为字符串,并且是祖先层弹框的名字的时候,会把祖先弹框关闭掉。 |
| required | `Array<string>` | - | 配置字符串数组,指定在`form`中进行操作之前,需要指定的字段名的表单项通过验证 |
| 属性名 | 类型 | 默认值 | 说明 |
| ------------------ | ------------------------------------ | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| type | `string` | `action` | 指定为 Page 渲染器。 |
| actionType | `string` | - | 【必填】这是 action 最核心的配置,来指定该 action 的作用类型,支持:`ajax`、`link`、`url`、`drawer`、`dialog`、`confirm`、`cancel`、`prev`、`next`、`copy`、`close`。 |
| label | `string` | - | 按钮文本。可用 `${xxx}` 取值。 |
| level | `string` | `default` | 按钮样式,支持:`link`、`primary`、`secondary`、`info`、`success`、`warning`、`danger`、`light`、`dark`、`default`。 |
| size | `string` | - | 按钮大小,支持:`xs`、`sm`、`md`、`lg`。 |
| icon | `string` | - | 设置图标,例如`fa fa-plus`。 |
| iconClassName | `string` | - | 给图标上添加类名。 |
| rightIcon | `string` | - | 在按钮文本右侧设置图标,例如`fa fa-plus`。 |
| rightIconClassName | `string` | - | 给右侧图标上添加类名。 |
| active | `boolean` | - | 按钮是否高亮。 |
| activeLevel | `string` | - | 按钮高亮时的样式,配置支持同`level`。 |
| activeClassName | `string` | `is-active` | 给按钮高亮添加类名。 |
| block | `boolean` | - | 用`display:"block"`来显示按钮。 |
| confirmText | [模板](../../docs/concepts/template) | - | 当设置后,操作在开始前会询问用户。可用 `${xxx}` 取值。 |
| reload | `string` | - | 指定此次操作完后,需要刷新的目标组件名字(组件的`name`值,自己配置的),多个请用 `,` 号隔开。 |
| tooltip | `string` | - | 鼠标停留时弹出该段文字,也可以配置对象类型:字段为`title`和`content`。可用 `${xxx}` 取值。 |
| disabledTip | `string` | - | 被禁用后鼠标停留时弹出该段文字,也可以配置对象类型:字段为`title`和`content`。可用 `${xxx}` 取值。 |
| tooltipPlacement | `string` | `top` | 如果配置了`tooltip`或者`disabledTip`,指定提示信息位置,可配置`top`、`bottom`、`left`、`right`。 |
| close | `boolean` or `string` | - | 当`action`配置在`dialog`或`drawer`的`actions`中时,配置为`true`指定此次操作完后关闭当前`dialog`或`drawer`。当值为字符串,并且是祖先层弹框的名字的时候,会把祖先弹框关闭掉。 |
| required | `Array<string>` | - | 配置字符串数组,指定在`form`中进行操作之前,需要指定的字段名的表单项通过验证 |

View File

@ -131,8 +131,7 @@ app.listen(8080, function () {
{
"type": "input-image",
"name": "image",
"label": "限制只能上传jpg图片",
"accept": ".jpg",
"label": "上传后裁剪",
"receiver": "/api/upload/file",
"crop": true
}
@ -140,6 +139,26 @@ app.listen(8080, function () {
}
```
设置裁剪比例等配置,具体细节可以参考[这里](https://github.com/fengyuanchen/cropperjs#options)。
```schema: scope="body"
{
"type": "form",
"api": "/api/mock2/form/saveForm",
"body": [
{
"type": "input-image",
"name": "image",
"label": "上传后裁剪",
"receiver": "/api/upload/file",
"crop": {
"aspectRatio": 1.7777
}
}
]
}
```
## 自动填充
上传成功后,可以通过配置 `autoFill` 将上传接口返回的值填充到某个表单项中:

View File

@ -43,22 +43,20 @@
"attr-accept": "2.2.2",
"blueimp-canvastoblob": "2.1.0",
"classnames": "2.3.1",
"dom-helpers": "^3.3.1",
"downshift": "3.1.4",
"echarts": "5.2.0",
"echarts-stat": "^1.2.0",
"exceljs": "^4.3.0",
"file-saver": "^2.0.2",
"froala-editor": "2.9.6",
"highlight.js": "^10.7.2",
"hls.js": "1.0.10",
"hoist-non-react-statics": "3.3.0",
"hoist-non-react-statics": "^3.3.2",
"immutability-helper": "^3.1.1",
"jquery": "^3.2.1",
"keycode": "^2.1.9",
"lodash": "^4.17.15",
"markdown-it": "^12.0.6",
"match-sorter": "2.2.1",
"match-sorter": "^6.3.0",
"mobx": "^4.5.0",
"mobx-react": "^6.1.4",
"mobx-state-tree": "^3.17.3",
@ -68,15 +66,15 @@
"papaparse": "^5.3.0",
"prop-types": "^15.6.1",
"punycode": "^2.1.1",
"qrcode.react": "^0.8.0",
"qrcode.react": "^1.0.1",
"qs": "6.5.1",
"rc-input-number": "6.1.1",
"rc-input-number": "^7.3.0",
"react": "^16.8.6",
"react-color": "2.13.8",
"react-cropper": "1.0.1",
"react-color": "^2.19.3",
"react-cropper": "^2.1.8",
"react-datetime": "2.16.2",
"react-dom": "^16.8.6",
"react-dropzone": "11.2.4",
"react-dropzone": "^11.3.4",
"react-input-range": "1.3.0",
"react-json-view": "1.21.3",
"react-overlays": "0.8.3",
@ -85,16 +83,15 @@
"react-visibility-sensor": "3.11.0",
"setimmediate": "1.0.5",
"sortablejs": "1.14.0",
"tinymce": ">=5.9.1",
"tinymce": "^5.9.2",
"tslib": "^2.3.1",
"uncontrollable": "7.0.2",
"uncontrollable": "7.2.1",
"video-react": "0.14.1"
},
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.15.4",
"@testing-library/react": "^12.0.0",
"@types/async": "^2.0.45",
"@types/dom-helpers": "^3.4.1",
"@types/echarts": "^4.9.2",
"@types/file-saver": "^2.0.1",
"@types/history": "^4.6.0",
@ -109,11 +106,9 @@
"@types/prop-types": "^15.5.2",
"@types/qs": "^6.5.1",
"@types/react": "^16.9.35",
"@types/react-color": "^2.13.3",
"@types/react-cropper": "^0.10.1",
"@types/react-color": "^3.0.5",
"@types/react-dom": "^16.0.7",
"@types/react-dropzone": "^4.1.0",
"@types/react-json-tree": "^0.6.6",
"@types/react-onclickoutside": "^6.0.2",
"@types/react-overlays": "^0.8.4",
"@types/react-router": "^3.0.24",
@ -126,9 +121,9 @@
"bce-sdk-js": "^0.2.9",
"concurrently": "^6.2.1",
"copy-to-clipboard": "3.3.1",
"core-js": "^3.7.0",
"core-js": "^3.17.3",
"css": "3.0.0",
"faker": "^4.1.0",
"faker": "^5.5.3",
"fis-optimizer-terser": "^1.0.1",
"fis-parser-sass": "^1.0.1",
"fis-parser-svgr": "^1.0.0",
@ -149,16 +144,16 @@
"husky": "^7.0.0",
"jest": "^27.0.6",
"jest-canvas-mock": "^2.3.0",
"js-yaml": "^3.10.0",
"js-yaml": "^4.1.0",
"json5": "^2.2.0",
"marked": "2.0.1",
"marked": "^3.0.3",
"mkdirp": "^1.0.4",
"moment-timezone": "^0.5.33",
"path-to-regexp": "^6.2.0",
"postcss": "^8.2.1",
"postcss-cli": "^8.3.1",
"postcss-custom-properties": "^11.0.0",
"prettier": "2.3.2",
"prettier": "^2.4.0",
"pretty-quick": "^3.1.1",
"prismjs": "^1.20.0",
"react-router": "3.2.0",

View File

@ -16,7 +16,7 @@ glob('./docs/**/*.md', {}, function (er, docs) {
let m = rYml.exec(content);
let info = {};
if (m && m[1]) {
info = yaml.safeLoad(m[1]);
info = yaml.load(m[1]);
content = content.substring(m[0].length);
}

View File

@ -85,7 +85,7 @@ module.exports = function (content, file) {
var m = rYml.exec(content);
var info = {};
if (m && m[1]) {
info = yaml.safeLoad(m[1]);
info = yaml.load(m[1]);
content = content.substring(m[0].length);
}

View File

@ -1,5 +1,4 @@
import isPlainObject from 'lodash/isPlainObject';
import qs from 'qs';
import React from 'react';
import Alert from './components/Alert2';
import ImageGallery from './components/ImageGallery';

View File

@ -5,9 +5,7 @@
import React from 'react';
import find from 'lodash/find';
import PropTypes from 'prop-types';
import hoistNonReactStatic from 'hoist-non-react-statics';
import qs from 'qs';
import {dataMapping} from './utils/tpl-builtin';
import {RendererEnv, RendererProps} from './factory';
import {noop, autobind, qsstringify, qsparse} from './utils/helper';

View File

@ -5,7 +5,6 @@
*/
import React from 'react';
import css from 'dom-helpers/style/index';
import {ClassNamesFn, themeable} from '../theme';
import Transition, {
EXITED,
@ -64,10 +63,9 @@ export class Collapse extends React.Component<CollapseProps, any> {
let offsetHeight = elem['offsetHeight'];
const height =
offsetHeight +
parseInt(css(elem, 'marginTop'), 10) +
parseInt(css(elem, 'marginBottom'), 10);
parseInt(getComputedStyle(elem).getPropertyValue('margin-top'), 10) +
parseInt(getComputedStyle(elem).getPropertyValue('margin-bottom'), 10);
elem.style['height'] = `${height}px`;
// trigger browser reflow
elem.offsetHeight;
}

View File

@ -6,7 +6,7 @@
import React from 'react';
import {findDOMNode} from 'react-dom';
import {SketchPicker, GithubPicker, ColorState} from 'react-color';
import {SketchPicker, GithubPicker, ColorResult} from 'react-color';
import {Icon} from './icons';
import Overlay from './Overlay';
import {uncontrollable} from 'uncontrollable';
@ -176,7 +176,7 @@ export class ColorControl extends React.PureComponent<
return image.style.color !== 'rgb(255, 255, 255)';
}
handleChange(color: ColorState) {
handleChange(color: ColorResult) {
const {
onChange,
format

View File

@ -12,8 +12,7 @@ import Overlay from './Overlay';
import PopOver from './PopOver';
import Downshift, {ControllerStateAndHelpers} from 'downshift';
import {closeIcon, Icon} from './icons';
// @ts-ignore
import matchSorter from 'match-sorter';
import {matchSorter} from 'match-sorter';
import {noop, isObject, findTree, autobind, ucFirst} from '../utils/helper';
import find from 'lodash/find';
import isPlainObject from 'lodash/isPlainObject';
@ -703,11 +702,12 @@ export class Select extends React.Component<SelectProps, SelectState> {
let checkedAll = false;
let checkedPartial = false;
let filtedOptions: Array<Option> = (inputValue && isOpen && !loadOptions
? matchSorter(options, inputValue, {
keys: [labelField || 'label', valueField || 'value']
})
: options.concat()
let filtedOptions: Array<Option> = (
inputValue && isOpen && !loadOptions
? matchSorter(options, inputValue, {
keys: [labelField || 'label', valueField || 'value']
})
: options.concat()
).filter((option: Option) => !option.hidden && option.visible !== false);
const selectionValues = selection.map(select => select[valueField]);

View File

@ -1,5 +1,4 @@
import React from 'react';
import qs from 'qs';
import {RendererStore, IRendererStore, IIRendererStore} from './store/index';
import {getEnv, destroy} from 'mobx-state-tree';
import {wrapFetcher} from './utils/api';

View File

@ -23,7 +23,7 @@ export interface ButtonSchema extends BaseSchema {
/**
* icon css
*/
iconClassName?: SchemaClassName;
iconClassName?: SchemaClassName;
/**
* iconfont
@ -33,7 +33,7 @@ export interface ButtonSchema extends BaseSchema {
/**
* icon css
*/
rightIconClassName?: SchemaClassName;
rightIconClassName?: SchemaClassName;
/**
*
@ -365,17 +365,47 @@ import {BadgeSchema, withBadge} from '../components/Badge';
import {str2AsyncFunction} from '../utils/api';
export interface ActionProps
extends Omit<ButtonSchema, 'className' | 'iconClassName' | 'rightIconClassName'>,
extends Omit<
ButtonSchema,
'className' | 'iconClassName' | 'rightIconClassName'
>,
ThemeProps,
Omit<AjaxActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<UrlActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<LinkActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<DialogActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<DrawerActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<CopyActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<ReloadActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<EmailActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'>,
Omit<OtherActionSchema, 'type' | 'className' | 'iconClassName' | 'rightIconClassName'> {
Omit<
AjaxActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
UrlActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
LinkActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
DialogActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
DrawerActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
CopyActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
ReloadActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
EmailActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
>,
Omit<
OtherActionSchema,
'type' | 'className' | 'iconClassName' | 'rightIconClassName'
> {
actionType: any;
onAction?: (
e: React.MouseEvent<any> | void | null,
@ -547,7 +577,12 @@ export class Action extends React.Component<ActionProps, ActionState> {
}
const iconElement = generateIcon(cx, icon, 'Button-icon', iconClassName);
const rightIconElement = generateIcon(cx, rightIcon, 'Button-icon', rightIconClassName);
const rightIconElement = generateIcon(
cx,
rightIcon,
'Button-icon',
rightIconClassName
);
return (
<Button

View File

@ -29,7 +29,6 @@ import Button from '../components/Button';
import Select from '../components/Select';
import getExprProperties from '../utils/filter-schema';
import pick from 'lodash/pick';
import qs from 'qs';
import {findDOMNode} from 'react-dom';
import {evalExpression, filter} from '../utils/tpl';
import {
@ -956,12 +955,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
}
handleDialogClose() {
const {
store,
stopAutoRefreshWhenModalIsOpen,
silentPolling,
interval
} = this.props;
const {store, stopAutoRefreshWhenModalIsOpen, silentPolling, interval} =
this.props;
store.closeDialog();
if (stopAutoRefreshWhenModalIsOpen && interval) {
@ -1194,14 +1189,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
}
handleSaveOrder(moved: Array<object>, rows: Array<object>) {
const {
store,
saveOrderApi,
orderField,
primaryField,
env,
reload
} = this.props;
const {store, saveOrderApi, orderField, primaryField, env, reload} =
this.props;
if (!saveOrderApi) {
env && env.alert('CRUD saveOrderApi is required!');
@ -1413,11 +1402,8 @@ export default class CRUD extends React.Component<CRUDProps, any> {
}
handleChildPopOverClose(popOver: any) {
const {
stopAutoRefreshWhenModalIsOpen,
silentPolling,
interval
} = this.props;
const {stopAutoRefreshWhenModalIsOpen, silentPolling, interval} =
this.props;
if (popOver && ~['dialog', 'drawer'].indexOf(popOver.mode)) {
this.props.store.setInnerModalOpened(false);

View File

@ -1,7 +1,6 @@
import React from 'react';
import cx from 'classnames';
// @ts-ignore
import matchSorter from 'match-sorter';
import {matchSorter} from 'match-sorter';
import keycode from 'keycode';
import Downshift, {StateChangeOptions} from 'downshift';
import {autobind} from '../../utils/helper';

View File

@ -1,7 +1,5 @@
import React from 'react';
import {FormItem, FormControlProps, FormBaseControl} from './Item';
import cx from 'classnames';
import qs from 'qs';
import find from 'lodash/find';
import isPlainObject from 'lodash/isPlainObject';
// @ts-ignore
@ -358,11 +356,12 @@ export default class FileControl extends React.Component<FileProps, FileState> {
if (value && value instanceof Blob) {
files = [value as any];
} else if (value) {
files = (Array.isArray(value)
? value
: joinValues
? `${(value as any)[valueField] || value}`.split(delimiter)
: [value as any]
files = (
Array.isArray(value)
? value
: joinValues
? `${(value as any)[valueField] || value}`.split(delimiter)
: [value as any]
)
.map(item => FileControl.valueToFile(item, props) as FileValue)
.filter(item => item);
@ -404,11 +403,12 @@ export default class FileControl extends React.Component<FileProps, FileState> {
let files: Array<FileValue> = [];
if (value) {
files = (Array.isArray(value)
? value
: joinValues && typeof value === 'string'
? value.split(delimiter)
: [value as any]
files = (
Array.isArray(value)
? value
: joinValues && typeof value === 'string'
? value.split(delimiter)
: [value as any]
)
.map(item => {
let obj = FileControl.valueToFile(

View File

@ -6,7 +6,6 @@ import DropZone from 'react-dropzone';
import {FileRejection} from 'react-dropzone';
import 'blueimp-canvastoblob';
import find from 'lodash/find';
import qs from 'qs';
import {Payload} from '../../types';
import {buildApi} from '../../utils/api';
import {
@ -389,11 +388,12 @@ export default class ImageControl extends React.Component<
if (value) {
// files = (multiple && Array.isArray(value) ? value : joinValues ? (value as string).split(delimiter) : [value])
files = (Array.isArray(value)
? value
: joinValues && typeof value === 'string' && multiple
? (value as string).split(delimiter)
: [value]
files = (
Array.isArray(value)
? value
: joinValues && typeof value === 'string' && multiple
? (value as string).split(delimiter)
: [value]
)
.map(item => ImageControl.valueToFile(item) as FileValue)
.filter(item => item);
@ -444,11 +444,12 @@ export default class ImageControl extends React.Component<
let files: Array<FileValue> = [];
if (value) {
files = (Array.isArray(value)
? value
: joinValues && typeof value === 'string'
? (value as string).split(delimiter)
: [value]
files = (
Array.isArray(value)
? value
: joinValues && typeof value === 'string'
? (value as string).split(delimiter)
: [value]
)
.map(item => {
let obj = ImageControl.valueToFile(item, props) as FileValue;
@ -1196,14 +1197,8 @@ export default class ImageControl extends React.Component<
fixedSizeClassName,
translate: __
} = this.props;
const {
files,
error,
crop,
uploading,
cropFile,
frameImageWidth
} = this.state;
const {files, error, crop, uploading, cropFile, frameImageWidth} =
this.state;
let frameImageStyle: any = {};
if (fixedSizeClassName && frameImageWidth && fixedSize) {
frameImageStyle.width = frameImageWidth;

View File

@ -7,8 +7,7 @@ import {
} from './Options';
import {Action} from '../../types';
import Downshift, {StateChangeOptions} from 'downshift';
// @ts-ignore
import matchSorter from 'match-sorter';
import {matchSorter} from 'match-sorter';
import debouce from 'lodash/debounce';
import {filter} from '../../utils/tpl';
import find from 'lodash/find';
@ -140,14 +139,8 @@ export default class TextControl extends React.PureComponent<
};
componentDidMount() {
const {
formItem,
autoComplete,
addHook,
formInited,
data,
name
} = this.props;
const {formItem, autoComplete, addHook, formInited, data, name} =
this.props;
if (isEffectiveApi(autoComplete, data) && formItem) {
if (formInited) {
@ -470,13 +463,8 @@ export default class TextControl extends React.PureComponent<
}
loadAutoComplete() {
const {
formItem,
autoComplete,
data,
multiple,
selectedOptions
} = this.props;
const {formItem, autoComplete, data, multiple, selectedOptions} =
this.props;
if (isEffectiveApi(autoComplete, data) && formItem) {
formItem.loadOptions(
@ -564,9 +552,8 @@ export default class TextControl extends React.PureComponent<
{
'is-opened': isOpen,
'TextControl-input--multiple': multiple,
[`TextControl-input--border${ucFirst(
[`TextControl-input--border${ucFirst(borderMode)}`]:
borderMode
)}`]: borderMode
}
)}
onClick={this.handleClick}

View File

@ -10,8 +10,7 @@ import {
} from './Options';
import {Icon} from '../../components/icons';
import TreeSelector from '../../components/Tree';
// @ts-ignore
import matchSorter from 'match-sorter';
import {matchSorter} from 'match-sorter';
import debouce from 'lodash/debounce';
import find from 'lodash/find';
import {Api} from '../../types';
@ -297,8 +296,9 @@ export default class TreeSelectControl extends React.Component<
if (!option.visible && option.children) {
option.children = this.filterOptions(option.children, keywords);
const visibleCount = option.children.filter(item => item.visible)
.length;
const visibleCount = option.children.filter(
item => item.visible
).length;
option.visible = !!visibleCount;
}

View File

@ -30,7 +30,6 @@ import Scoped, {
ScopedComponentType
} from '../../Scoped';
import {IComboStore} from '../../store/combo';
import qs from 'qs';
import {dataMapping} from '../../utils/tpl-builtin';
import {isApiOutdated, isEffectiveApi} from '../../utils/api';
import Spinner from '../../components/Spinner';

View File

@ -12,9 +12,7 @@ import {
FunctionPropertyNames
} from '../types';
import {filter, evalExpression} from '../utils/tpl';
import cx from 'classnames';
import qs from 'qs';
import {isVisible, autobind, bulkBindFunctions, uuid} from '../utils/helper';
import {isVisible, autobind, bulkBindFunctions} from '../utils/helper';
import {ScopedContext, IScopedContext} from '../Scoped';
import Alert from '../components/Alert2';
import {isApiOutdated, isEffectiveApi} from '../utils/api';

View File

@ -5,16 +5,10 @@
import React from 'react';
import {findDOMNode} from 'react-dom';
import find from 'lodash/find';
import PropTypes from 'prop-types';
import isPlainObject from 'lodash/isPlainObject';
import {RendererProps} from '../factory';
import cx from 'classnames';
import hoistNonReactStatic from 'hoist-non-react-statics';
import onClickOutside from 'react-onclickoutside';
import {Action} from '../types';
import keycode from 'keycode';
import matches from 'dom-helpers/query/matches';
import Overlay from '../components/Overlay';
import PopOver from '../components/PopOver';
import {Icon} from '../components/icons';
@ -90,489 +84,487 @@ export interface QuickEditState {
let inited: boolean = false;
let currentOpened: any;
export const HocQuickEdit = (config: Partial<QuickEditConfig> = {}) => (
Component: React.ComponentType<any>
): any => {
class QuickEditComponent extends React.PureComponent<
QuickEditProps,
QuickEditState
> {
target: HTMLElement;
overlay: HTMLElement;
static ComposedComponent = Component;
constructor(props: QuickEditProps) {
super(props);
export const HocQuickEdit =
(config: Partial<QuickEditConfig> = {}) =>
(Component: React.ComponentType<any>): any => {
class QuickEditComponent extends React.PureComponent<
QuickEditProps,
QuickEditState
> {
target: HTMLElement;
overlay: HTMLElement;
static ComposedComponent = Component;
constructor(props: QuickEditProps) {
super(props);
this.openQuickEdit = this.openQuickEdit.bind(this);
this.closeQuickEdit = this.closeQuickEdit.bind(this);
this.handleAction = this.handleAction.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.overlayRef = this.overlayRef.bind(this);
this.handleWindowKeyPress = this.handleWindowKeyPress.bind(this);
this.handleWindowKeyDown = this.handleWindowKeyDown.bind(this);
this.formRef = this.formRef.bind(this);
this.handleInit = this.handleInit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.openQuickEdit = this.openQuickEdit.bind(this);
this.closeQuickEdit = this.closeQuickEdit.bind(this);
this.handleAction = this.handleAction.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleKeyUp = this.handleKeyUp.bind(this);
this.overlayRef = this.overlayRef.bind(this);
this.handleWindowKeyPress = this.handleWindowKeyPress.bind(this);
this.handleWindowKeyDown = this.handleWindowKeyDown.bind(this);
this.formRef = this.formRef.bind(this);
this.handleInit = this.handleInit.bind(this);
this.handleChange = this.handleChange.bind(this);
this.state = {
isOpened: false
};
}
componentDidMount() {
this.target = findDOMNode(this) as HTMLElement;
if (inited) {
return;
this.state = {
isOpened: false
};
}
inited = true;
document.body.addEventListener('keypress', this.handleWindowKeyPress);
document.body.addEventListener('keydown', this.handleWindowKeyDown);
}
componentDidMount() {
this.target = findDOMNode(this) as HTMLElement;
formRef(ref: any) {
const {quickEditFormRef, rowIndex, colIndex} = this.props;
if (quickEditFormRef) {
while (ref && ref.getWrappedInstance) {
ref = ref.getWrappedInstance();
if (inited) {
return;
}
quickEditFormRef(ref, colIndex, rowIndex);
}
}
handleWindowKeyPress(e: Event) {
const ns = this.props.classPrefix;
let el: HTMLElement = (e.target as HTMLElement).closest(
`.${ns}Field--quickEditable`
) as HTMLElement;
if (!el) {
return;
}
const table = el.closest('table');
if (!table) {
return;
inited = true;
document.body.addEventListener('keypress', this.handleWindowKeyPress);
document.body.addEventListener('keydown', this.handleWindowKeyDown);
}
if (
keycode(e) === 'space' &&
!~['INPUT', 'TEXTAREA'].indexOf(el.tagName)
) {
e.preventDefault();
e.stopPropagation();
}
}
formRef(ref: any) {
const {quickEditFormRef, rowIndex, colIndex} = this.props;
handleWindowKeyDown(e: Event) {
const code = keycode(e);
if (quickEditFormRef) {
while (ref && ref.getWrappedInstance) {
ref = ref.getWrappedInstance();
}
if (code === 'esc' && currentOpened) {
currentOpened.closeQuickEdit();
} else if (
~['INPUT', 'TEXTAREA'].indexOf((e.target as HTMLElement).tagName) ||
(e.target as HTMLElement).contentEditable === 'true' ||
!~['up', 'down', 'left', 'right'].indexOf(code)
) {
return;
quickEditFormRef(ref, colIndex, rowIndex);
}
}
e.preventDefault();
const ns = this.props.classPrefix;
let el: HTMLElement =
((e.target as HTMLElement).closest(
handleWindowKeyPress(e: Event) {
const ns = this.props.classPrefix;
let el: HTMLElement = (e.target as HTMLElement).closest(
`.${ns}Field--quickEditable`
) as HTMLElement) ||
document.querySelector(`.${ns}Field--quickEditable`);
if (!el) {
return;
}
let table = el.closest('table');
if (!table) {
return;
}
let current = table.querySelector(
`.${ns}Field--quickEditable:focus`
) as HTMLTableDataCellElement;
if (!current) {
let dom = table.querySelector(
`.${ns}Field--quickEditable[tabindex]`
) as HTMLElement;
dom && dom.focus();
} else {
let prevTr, nextTr, prevTd, nextTd;
if (!el) {
return;
}
const table = el.closest('table');
if (!table) {
return;
}
switch (code) {
case 'up':
prevTr = (current.parentNode as HTMLElement)
.previousSibling as HTMLTableCellElement;
if (
keycode(e) === 'space' &&
!~['INPUT', 'TEXTAREA'].indexOf(el.tagName)
) {
e.preventDefault();
e.stopPropagation();
}
}
if (prevTr) {
let index = current.cellIndex;
(prevTr.children[index] as HTMLElement).focus();
}
break;
case 'down':
nextTr = (current.parentNode as HTMLElement)
.nextSibling as HTMLTableCellElement;
handleWindowKeyDown(e: Event) {
const code = keycode(e);
if (nextTr) {
let index = current.cellIndex;
(nextTr.children[index] as HTMLElement).focus();
}
break;
case 'left':
prevTd = current.previousElementSibling as HTMLTableCellElement;
if (code === 'esc' && currentOpened) {
currentOpened.closeQuickEdit();
} else if (
~['INPUT', 'TEXTAREA'].indexOf((e.target as HTMLElement).tagName) ||
(e.target as HTMLElement).contentEditable === 'true' ||
!~['up', 'down', 'left', 'right'].indexOf(code)
) {
return;
}
while (prevTd) {
if (matches(prevTd, `.${ns}Field--quickEditable[tabindex]`)) {
break;
e.preventDefault();
const ns = this.props.classPrefix;
let el: HTMLElement =
((e.target as HTMLElement).closest(
`.${ns}Field--quickEditable`
) as HTMLElement) ||
document.querySelector(`.${ns}Field--quickEditable`);
if (!el) {
return;
}
let table = el.closest('table');
if (!table) {
return;
}
let current = table.querySelector(
`.${ns}Field--quickEditable:focus`
) as HTMLTableDataCellElement;
if (!current) {
let dom = table.querySelector(
`.${ns}Field--quickEditable[tabindex]`
) as HTMLElement;
dom && dom.focus();
} else {
let prevTr, nextTr, prevTd, nextTd;
switch (code) {
case 'up':
prevTr = (current.parentNode as HTMLElement)
.previousSibling as HTMLTableCellElement;
if (prevTr) {
let index = current.cellIndex;
(prevTr.children[index] as HTMLElement).focus();
}
prevTd = prevTd.previousElementSibling;
}
break;
case 'down':
nextTr = (current.parentNode as HTMLElement)
.nextSibling as HTMLTableCellElement;
if (prevTd) {
(prevTd as HTMLElement).focus();
} else if ((current.parentNode as HTMLElement).previousSibling) {
let tds = ((current.parentNode as HTMLElement)
.previousSibling as HTMLElement).querySelectorAll(
`.${ns}Field--quickEditable[tabindex]`
);
if (tds.length) {
(tds[tds.length - 1] as HTMLElement).focus();
if (nextTr) {
let index = current.cellIndex;
(nextTr.children[index] as HTMLElement).focus();
}
}
break;
case 'right':
nextTd = current.nextSibling;
while (nextTd) {
if (
matches(
nextTd as Element,
`.${ns}Field--quickEditable[tabindex]`
)
) {
break;
break;
case 'left':
prevTd = current.previousElementSibling as HTMLTableCellElement;
while (prevTd) {
if (prevTd.matches(`.${ns}Field--quickEditable[tabindex]`)) {
break;
}
prevTd = prevTd.previousElementSibling;
}
nextTd = nextTd.nextSibling;
}
if (prevTd) {
(prevTd as HTMLElement).focus();
} else if ((current.parentNode as HTMLElement).previousSibling) {
let tds = (
(current.parentNode as HTMLElement)
.previousSibling as HTMLElement
).querySelectorAll(`.${ns}Field--quickEditable[tabindex]`);
if (nextTd) {
(nextTd as HTMLElement).focus();
} else if ((current.parentNode as HTMLElement).nextSibling) {
nextTd = ((current.parentNode as HTMLElement)
.nextSibling as HTMLElement).querySelector(
`.${ns}Field--quickEditable[tabindex]`
);
if (tds.length) {
(tds[tds.length - 1] as HTMLElement).focus();
}
}
break;
case 'right':
nextTd = current.nextSibling;
while (nextTd) {
if (
(nextTd as Element).matches(
`.${ns}Field--quickEditable[tabindex]`
)
) {
break;
}
nextTd = nextTd.nextSibling;
}
if (nextTd) {
(nextTd as any).focus();
(nextTd as HTMLElement).focus();
} else if ((current.parentNode as HTMLElement).nextSibling) {
nextTd = (
(current.parentNode as HTMLElement).nextSibling as HTMLElement
).querySelector(`.${ns}Field--quickEditable[tabindex]`);
if (nextTd) {
(nextTd as any).focus();
}
}
}
break;
break;
}
}
}
}
// handleClickOutside() {
// this.closeQuickEdit();
// }
// handleClickOutside() {
// this.closeQuickEdit();
// }
overlayRef(ref: any) {
this.overlay = ref;
}
overlayRef(ref: any) {
this.overlay = ref;
}
handleAction(e: any, action: Action, ctx: object) {
const {onAction} = this.props;
handleAction(e: any, action: Action, ctx: object) {
const {onAction} = this.props;
if (action.actionType === 'cancel' || action.actionType === 'close') {
this.closeQuickEdit();
return;
}
onAction && onAction(e, action, ctx);
}
handleSubmit(values: object) {
const {onQuickChange, quickEdit} = this.props;
if (action.actionType === 'cancel' || action.actionType === 'close') {
this.closeQuickEdit();
return;
onQuickChange(
values,
(quickEdit as QuickEditConfig).saveImmediately,
false,
(quickEdit as QuickEditConfig).resetOnFailed
);
return false;
}
onAction && onAction(e, action, ctx);
}
handleSubmit(values: object) {
const {onQuickChange, quickEdit} = this.props;
this.closeQuickEdit();
onQuickChange(
values,
(quickEdit as QuickEditConfig).saveImmediately,
false,
(quickEdit as QuickEditConfig).resetOnFailed
);
return false;
}
handleInit(values: object) {
const {onQuickChange} = this.props;
onQuickChange(values, false, true);
}
handleChange(values: object) {
const {onQuickChange, quickEdit} = this.props;
onQuickChange(
values,
(quickEdit as QuickEditConfig).saveImmediately,
false,
(quickEdit as QuickEditConfig).resetOnFailed
);
}
openQuickEdit() {
currentOpened = this;
this.setState({
isOpened: true
});
}
closeQuickEdit() {
if (!this.state.isOpened) {
return;
handleInit(values: object) {
const {onQuickChange} = this.props;
onQuickChange(values, false, true);
}
currentOpened = null;
const ns = this.props.classPrefix;
this.setState(
{
isOpened: false
},
() => {
let el = findDOMNode(this) as HTMLElement;
let table = el.closest('table') as HTMLElement;
((table &&
table.querySelectorAll(`td.${ns}Field--quickEditable:focus`)
.length) ||
el) &&
el.focus();
handleChange(values: object) {
const {onQuickChange, quickEdit} = this.props;
onQuickChange(
values,
(quickEdit as QuickEditConfig).saveImmediately,
false,
(quickEdit as QuickEditConfig).resetOnFailed
);
}
openQuickEdit() {
currentOpened = this;
this.setState({
isOpened: true
});
}
closeQuickEdit() {
if (!this.state.isOpened) {
return;
}
);
}
currentOpened = null;
const ns = this.props.classPrefix;
this.setState(
{
isOpened: false
},
() => {
let el = findDOMNode(this) as HTMLElement;
let table = el.closest('table') as HTMLElement;
((table &&
table.querySelectorAll(`td.${ns}Field--quickEditable:focus`)
.length) ||
el) &&
el.focus();
}
);
}
buildSchema() {
const {quickEdit, name, label, translate: __} = this.props;
buildSchema() {
const {quickEdit, name, label, translate: __} = this.props;
let schema;
let schema;
if (quickEdit === true) {
schema = {
type: 'form',
title: '',
autoFocus: true,
body: [
{
type: 'input-text',
name,
placeholder: label,
label: false
}
]
};
} else if (quickEdit) {
if (
quickEdit.body &&
!~['combo', 'group', 'panel', 'fieldSet', 'fieldset'].indexOf(
(quickEdit as any).type
)
) {
if (quickEdit === true) {
schema = {
title: '',
autoFocus: (quickEdit as QuickEditConfig).mode !== 'inline',
...quickEdit,
mode: 'normal',
type: 'form'
};
} else {
schema = {
title: '',
className: quickEdit.formClassName,
type: 'form',
autoFocus: (quickEdit as QuickEditConfig).mode !== 'inline',
mode: 'normal',
title: '',
autoFocus: true,
body: [
{
type: quickEdit.type || 'input-text',
name: quickEdit.name || name,
...quickEdit,
mode: undefined
type: 'input-text',
name,
placeholder: label,
label: false
}
]
};
} else if (quickEdit) {
if (
quickEdit.body &&
!~['combo', 'group', 'panel', 'fieldSet', 'fieldset'].indexOf(
(quickEdit as any).type
)
) {
schema = {
title: '',
autoFocus: (quickEdit as QuickEditConfig).mode !== 'inline',
...quickEdit,
mode: 'normal',
type: 'form'
};
} else {
schema = {
title: '',
className: quickEdit.formClassName,
type: 'form',
autoFocus: (quickEdit as QuickEditConfig).mode !== 'inline',
mode: 'normal',
body: [
{
type: quickEdit.type || 'input-text',
name: quickEdit.name || name,
...quickEdit,
mode: undefined
}
]
};
}
}
if (schema) {
schema = {
...schema,
wrapWithPanel: (quickEdit as QuickEditConfig).mode !== 'inline',
actions:
(quickEdit as QuickEditConfig).mode === 'inline'
? []
: [
{
type: 'button',
label: __('cancel'),
actionType: 'cancel'
},
{
label: __('confirm'),
type: 'submit',
primary: true
}
]
};
}
return schema || 'error';
}
handleKeyUp(e: Event) {
const code = keycode(e);
if (
code === 'space' &&
!~['INPUT', 'TEXTAREA'].indexOf((e.target as HTMLElement).tagName)
) {
e.preventDefault();
e.stopPropagation();
this.openQuickEdit();
}
}
if (schema) {
schema = {
...schema,
wrapWithPanel: (quickEdit as QuickEditConfig).mode !== 'inline',
actions:
(quickEdit as QuickEditConfig).mode === 'inline'
? []
: [
{
type: 'button',
label: __('cancel'),
actionType: 'cancel'
},
renderPopOver() {
let {
quickEdit,
render,
popOverContainer,
classPrefix: ns,
classnames: cx,
canAccessSuperData
} = this.props;
{
label: __('confirm'),
type: 'submit',
primary: true
}
]
};
}
return schema || 'error';
}
handleKeyUp(e: Event) {
const code = keycode(e);
if (
code === 'space' &&
!~['INPUT', 'TEXTAREA'].indexOf((e.target as HTMLElement).tagName)
) {
e.preventDefault();
e.stopPropagation();
this.openQuickEdit();
}
}
renderPopOver() {
let {
quickEdit,
render,
popOverContainer,
classPrefix: ns,
classnames: cx,
canAccessSuperData
} = this.props;
const content = (
<div
ref={this.overlayRef}
className={cx((quickEdit as QuickEditConfig).className)}
>
{render('quick-edit-form', this.buildSchema(), {
value: undefined,
onSubmit: this.handleSubmit,
onAction: this.handleAction,
onChange: null,
formLazyChange: false,
ref: this.formRef,
popOverContainer: () => this.overlay,
canAccessSuperData
})}
</div>
);
popOverContainer = popOverContainer || (() => findDOMNode(this));
return (
<Overlay
container={popOverContainer}
target={() => this.target}
onHide={this.closeQuickEdit}
placement="left-top right-top left-bottom right-bottom left-top"
show
>
<PopOver
classPrefix={ns}
className={cx(
`${ns}QuickEdit-popover`,
(quickEdit as QuickEditConfig).popOverClassName
)}
onHide={this.closeQuickEdit}
overlay
const content = (
<div
ref={this.overlayRef}
className={cx((quickEdit as QuickEditConfig).className)}
>
{content}
</PopOver>
</Overlay>
);
}
render() {
const {
onQuickChange,
quickEdit,
quickEditEnabled,
className,
classnames: cx,
render,
noHoc,
canAccessSuperData,
disabled
} = this.props;
if (
!quickEdit ||
!onQuickChange ||
quickEditEnabled === false ||
noHoc ||
disabled
) {
return <Component {...this.props} />;
}
if ((quickEdit as QuickEditConfig).mode === 'inline') {
return (
<Component {...this.props}>
{render('inline-form', this.buildSchema(), {
{render('quick-edit-form', this.buildSchema(), {
value: undefined,
wrapperComponent: 'div',
className: cx('Form--quickEdit'),
ref: this.formRef,
simpleMode: true,
onInit: this.handleInit,
onChange: this.handleChange,
onSubmit: this.handleSubmit,
onAction: this.handleAction,
onChange: null,
formLazyChange: false,
ref: this.formRef,
popOverContainer: () => this.overlay,
canAccessSuperData
})}
</Component>
</div>
);
} else {
popOverContainer = popOverContainer || (() => findDOMNode(this));
return (
<Component
{...this.props}
className={cx(`Field--quickEditable`, className, {
in: this.state.isOpened
})}
tabIndex={
(quickEdit as QuickEditConfig).focusable === false
? undefined
: '0'
}
onKeyUp={this.handleKeyUp}
<Overlay
container={popOverContainer}
target={() => this.target}
onHide={this.closeQuickEdit}
placement="left-top right-top left-bottom right-bottom left-top"
show
>
<Component {...this.props} wrapperComponent={''} noHoc />
<span
key="edit-btn"
className={cx('Field-quickEditBtn')}
onClick={this.openQuickEdit}
<PopOver
classPrefix={ns}
className={cx(
`${ns}QuickEdit-popover`,
(quickEdit as QuickEditConfig).popOverClassName
)}
onHide={this.closeQuickEdit}
overlay
>
<Icon icon="pencil" className="icon" />
</span>
{this.state.isOpened ? this.renderPopOver() : null}
</Component>
{content}
</PopOver>
</Overlay>
);
}
render() {
const {
onQuickChange,
quickEdit,
quickEditEnabled,
className,
classnames: cx,
render,
noHoc,
canAccessSuperData,
disabled
} = this.props;
if (
!quickEdit ||
!onQuickChange ||
quickEditEnabled === false ||
noHoc ||
disabled
) {
return <Component {...this.props} />;
}
if ((quickEdit as QuickEditConfig).mode === 'inline') {
return (
<Component {...this.props}>
{render('inline-form', this.buildSchema(), {
value: undefined,
wrapperComponent: 'div',
className: cx('Form--quickEdit'),
ref: this.formRef,
simpleMode: true,
onInit: this.handleInit,
onChange: this.handleChange,
formLazyChange: false,
canAccessSuperData
})}
</Component>
);
} else {
return (
<Component
{...this.props}
className={cx(`Field--quickEditable`, className, {
in: this.state.isOpened
})}
tabIndex={
(quickEdit as QuickEditConfig).focusable === false
? undefined
: '0'
}
onKeyUp={this.handleKeyUp}
>
<Component {...this.props} wrapperComponent={''} noHoc />
<span
key="edit-btn"
className={cx('Field-quickEditBtn')}
onClick={this.openQuickEdit}
>
<Icon icon="pencil" className="icon" />
</span>
{this.state.isOpened ? this.renderPopOver() : null}
</Component>
);
}
}
}
}
hoistNonReactStatic(QuickEditComponent, Component);
hoistNonReactStatic(QuickEditComponent, Component);
return QuickEditComponent;
};
return QuickEditComponent;
};
export default HocQuickEdit;

View File

@ -1,5 +1,4 @@
import {Instance, types} from 'mobx-state-tree';
import qs from 'qs';
import {createObject, qsparse} from '../utils/helper';
import {ServiceStore} from './service';

View File

@ -1,7 +1,6 @@
import {Api, ApiObject, fetcherResult, Payload} from '../types';
import {fetcherConfig} from '../factory';
import {tokenize, dataMapping} from './tpl-builtin';
import qs from 'qs';
import {evalExpression} from './tpl';
import {
isObject,

View File

@ -1,11 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import hoistNonReactStatic from 'hoist-non-react-statics';
import domOwnerDocument from 'dom-helpers/ownerDocument';
import css from 'dom-helpers/style/index';
import getOffset from 'dom-helpers/query/offset';
import getPosition from 'dom-helpers/query/position';
import getScrollTop from 'dom-helpers/query/scrollTop';
import getOffset from './offset';
import getPosition from './position';
const bsMapping: {
[propName: string]: string;
@ -56,7 +53,10 @@ export function getContainer(container: any, defaultContainer: any) {
}
export function ownerDocument(componentOrElement: any) {
return domOwnerDocument(ReactDOM.findDOMNode(componentOrElement) as Element);
return (
(ReactDOM.findDOMNode(componentOrElement) as Element)?.ownerDocument ||
document
);
}
function getContainerDimensions(containerNode: any) {
@ -67,11 +67,11 @@ function getContainerDimensions(containerNode: any) {
height = window.innerHeight;
scroll =
getScrollTop(ownerDocument(containerNode).documentElement) ||
getScrollTop(containerNode);
ownerDocument(containerNode).documentElement.scrollTop ||
containerNode?.scrollTop;
} else {
({width, height} = getOffset(containerNode) as any);
scroll = getScrollTop(containerNode);
scroll = containerNode.scrollTop;
}
return {width, height, scroll};
@ -120,23 +120,6 @@ function getLeftDelta(
return 0;
}
// function position(node: HTMLElement, offsetParent: HTMLElement) {
// const rect = offsetParent.getBoundingClientRect();
// const rect2 = node.getBoundingClientRect();
// return {
// width:
// rect2.width -
// (parseInt(css(node, 'borderLeftWidth') || '', 10) || 0) -
// parseInt(css(node, 'borderRightWidth') || '', 10) || 0,
// height:
// rect2.height -
// (parseInt(css(node, 'borderTopWidth') || '', 10) || 0) -
// parseInt(css(node, 'borderBottomWidth') || '', 10) || 0,
// top: rect2.top - rect.top,
// left: rect2.left - rect.left
// };
// }
export function calculatePosition(
placement: any,
overlayNode: any,

View File

@ -2,32 +2,10 @@
* @file markdown
*/
import hljs from 'highlight.js';
import markdownIt from 'markdown-it';
import {escapeHtml} from 'markdown-it/lib/common/utils';
const markdown = markdownIt({
linkify: true,
highlight(str: string, lang: string) {
if (lang && hljs.getLanguage(lang)) {
try {
return (
'<pre class="hljs language-' +
escapeHtml(lang.toLowerCase()) +
'"><code>' +
hljs.highlight(lang, str, true).value +
'</code></pre>'
);
} catch (__) {}
}
return (
'<pre class="hljs language-' +
escapeHtml(lang.toLowerCase()) +
'"><code>' +
escapeHtml(str) +
'</code></pre>'
);
}
linkify: true
});
export default function (content: string) {

30
src/utils/offset.ts Normal file
View File

@ -0,0 +1,30 @@
/**
* https://github.com/react-bootstrap/dom-helpers/blob/master/src/offset.ts
*/
/**
* Returns the offset of a given element, including top and left positions, width and height.
*
* @param node the element
*/
export default function offset(node: HTMLElement) {
const doc = node?.ownerDocument;
let box = {top: 0, left: 0, height: 0, width: 0};
const docElem = doc && doc.documentElement;
// Make sure it's not a disconnected DOM node
if (!docElem || !docElem.contains(node)) return box;
if (node.getBoundingClientRect !== undefined)
box = node.getBoundingClientRect();
box = {
top: box.top + docElem.scrollTop - (docElem.clientTop || 0),
left: box.left + docElem.scrollLeft - (docElem.clientLeft || 0),
width: box.width,
height: box.height
};
return box;
}

21
src/utils/offsetParent.ts Normal file
View File

@ -0,0 +1,21 @@
/**
* https://github.com/react-bootstrap/dom-helpers/blob/master/src/offsetParent.ts
*/
const isHTMLElement = (e: Element | null): e is HTMLElement =>
!!e && 'offsetParent' in e;
export default function offsetParent(node: HTMLElement): HTMLElement {
const doc = node?.ownerDocument;
let parent = node && node.offsetParent;
while (
isHTMLElement(parent) &&
parent.nodeName !== 'HTML' &&
getComputedStyle(parent).getPropertyValue('position') === 'static'
) {
parent = parent.offsetParent;
}
return (parent || doc.documentElement) as HTMLElement;
}

56
src/utils/position.ts Normal file
View File

@ -0,0 +1,56 @@
/**
* https://github.com/react-bootstrap/dom-helpers/blob/master/src/position.ts
*/
import getOffset from './offset';
import getOffsetParent from './offsetParent';
const nodeName = (node: Element) =>
node.nodeName && node.nodeName.toLowerCase();
/**
* Returns the relative position of a given element.
*
* @param node the element
* @param offsetParent the offset parent
*/
export default function position(
node: HTMLElement,
offsetParent?: HTMLElement
) {
let parentOffset = {top: 0, left: 0};
let offset;
getComputedStyle;
// Fixed elements are offset from window (parentOffset = {top:0, left: 0},
// because it is its only offset parent
if (getComputedStyle(node).getPropertyValue('position') === 'fixed') {
offset = node.getBoundingClientRect();
} else {
const parent: HTMLElement = offsetParent || getOffsetParent(node);
offset = getOffset(node);
if (nodeName(parent) !== 'html') parentOffset = getOffset(parent);
const borderTop = String(
getComputedStyle(parent).getPropertyValue('border-top-width') || 0
);
parentOffset.top += parseInt(borderTop, 10) - parent.scrollTop || 0;
const borderLeft = String(
getComputedStyle(parent).getPropertyValue('border-left-width') || 0
);
parentOffset.left += parseInt(borderLeft, 10) - parent.scrollLeft || 0;
}
const marginTop = String(
getComputedStyle(node).getPropertyValue('margin-top') || 0
);
const marginLeft = String(
getComputedStyle(node).getPropertyValue('margin-left') || 0
);
// Subtract parent offsets and node margins
return {
...offset,
top: offset.top - parentOffset.top - (parseInt(marginTop, 10) || 0),
left: offset.left - parentOffset.left - (parseInt(marginLeft, 10) || 0)
};
}