pick fix: 修复弹窗中 className 使用表达式无效的问题、 fix: 修复下拉弹窗在某些情况点击外层不关闭的问题、style: 调整 table 固顶模式的样式兼容 safari (#8884)

* fix: 修复弹窗中 className 使用表达式无效的问题

* fix: 修复下拉弹窗在某些情况点击外层不关闭的问题

* style: 调整 table 固顶模式的样式兼容 safari Close: #8708 (#8863)
This commit is contained in:
liaoxuezhi 2023-11-24 13:48:18 +08:00 committed by GitHub
parent a4c0954fdc
commit c97f337d5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 164 additions and 48 deletions

View File

@ -6,7 +6,9 @@ import React from 'react';
import {RendererProps} from './factory';
import {IIRendererStore, IRendererStore} from './store';
import {RendererData, SchemaNode} from './types';
import getExprProperties from './utils/filter-schema';
import getExprProperties, {
hasExprPropertiesChanged
} from './utils/filter-schema';
import {
createObject,
extendObject,
@ -127,26 +129,19 @@ export function HocStoreFactory(renderer: {
this.state = {};
const {detectField, ...rest} = props;
let exprProps: any = {};
if (!detectField || detectField === 'data') {
exprProps = getExprProperties(rest, store.data, undefined, rest);
exprProps = getExprProperties(rest, store.data);
this.state = {
...exprProps
};
this.unReaction = reaction(
() =>
JSON.stringify(
getExprProperties(this.props, store.data, undefined, this.props)
),
() => JSON.stringify(getExprProperties(this.props, store.data)),
() =>
this.setState({
...getExprProperties(
this.props,
store.data,
undefined,
this.props
)
...getExprProperties(this.props, store.data)
})
);
}
@ -173,6 +168,27 @@ export function HocStoreFactory(renderer: {
componentDidUpdate(prevProps: Props) {
const props = this.props;
const store = this.store;
// dialog 场景下 schema 是显示的时候更新的,
// 所以 schema 里面有表达式属性其实是监听不到变化的
// 所以这里需要根据新属性重新 reaction 一下
if (
(!props.detectField || props.detectField === 'data') &&
hasExprPropertiesChanged(this.props, prevProps)
) {
const state = getExprProperties(this.props, store.data);
isObjectShallowModified(state, this.state) && this.setState(state);
// 需要重新监听
this.unReaction?.();
this.unReaction = reaction(
() => JSON.stringify(getExprProperties(props, store.data)),
() =>
this.setState({
...getExprProperties(this.props, store.data)
})
);
}
const shouldSync = renderer.shouldSyncSuperStore?.(
store,
props,

View File

@ -7,7 +7,7 @@
import React from 'react';
import {findDOMNode} from 'react-dom';
import {ClassNamesFn, themeable} from '../theme';
import {camel, preventDefault} from '../utils';
import {autobind, camel, preventDefault} from '../utils';
export interface Offset {
x: number;
@ -54,6 +54,7 @@ export class PopOver extends React.PureComponent<PopOverProps, PopOverState> {
parent: HTMLElement;
wrapperRef: React.RefObject<HTMLDivElement> = React.createRef();
isRootClosed = false;
componentDidMount() {
this.mayUpdateOffset();
@ -68,6 +69,23 @@ export class PopOver extends React.PureComponent<PopOverProps, PopOverState> {
capture: false
});
}
// 从弹窗中处理复制过来的,如果要修改,请同步修改
// 因为 overlay 功能其实是用 postion: fixed 来实现的
// 目的是加一个蒙层监听蒙层点击然后关闭弹窗。意图就是 closeOnOutside
// 但是如果上层有个 translateZ 之类的样式就会影响 fixed 的定位,导致功能失效
// 所以这里兜底加了个 closeOnOutside 的功能
document.body.addEventListener(
'mousedown',
this.handleRootMouseDownCapture,
true
);
document.body.addEventListener(
'mouseup',
this.handleRootMouseUpCapture,
true
);
document.body.addEventListener('mouseup', this.handleRootMouseUp);
}
componentDidUpdate() {
@ -80,6 +98,62 @@ export class PopOver extends React.PureComponent<PopOverProps, PopOverState> {
if (this.wrapperRef && this.wrapperRef.current) {
this.wrapperRef.current.removeEventListener('touchmove', preventDefault);
}
document.body.removeEventListener('mouseup', this.handleRootMouseUp);
document.body.removeEventListener(
'mousedown',
this.handleRootMouseDownCapture,
true
);
document.body.removeEventListener(
'mouseup',
this.handleRootMouseUpCapture,
true
);
}
@autobind
handleRootMouseDownCapture(e: MouseEvent) {
const target = e.target as HTMLElement;
const {overlay: closeOnOutside, classPrefix: ns} = this.props;
const isLeftButton =
(e.button === 1 && window.event !== null) || e.button === 0;
this.isRootClosed = !!(
isLeftButton &&
closeOnOutside &&
target &&
this.wrapperRef.current &&
((!this.wrapperRef.current.contains(target) &&
!target.closest('[role=dialog]')) ||
(target.matches(`.${ns}Modal`) && target === this.wrapperRef.current))
); // 干脆过滤掉来自弹框里面的点击
}
@autobind
handleRootMouseUpCapture(e: MouseEvent) {
// mousedown 的时候不在弹窗里面,则不需要判断了
if (!this.isRootClosed) {
return;
}
// 再判断 mouseup 的时候是不是在弹窗里面
this.handleRootMouseDownCapture(e);
}
@autobind
handleRootMouseUp(e: MouseEvent) {
const {onHide} = this.props;
if (this.isRootClosed && !e.defaultPrevented) {
// 因为原来 overlay 是不会让别的部分还有点击事件的,所以这里要阻止默认事件
// 参考https://stackoverflow.com/questions/8643739/cancel-click-event-in-the-mouseup-event-handler
let captureClick = (e: Event) => {
e.stopPropagation();
window.removeEventListener('click', captureClick, true);
};
window.addEventListener('click', captureClick, true);
onHide?.();
}
}
mayUpdateOffset() {

View File

@ -528,7 +528,8 @@ export const TableStore = iRendererStore
exportExcelLoading: false,
searchFormExpanded: false, // 用来控制搜索框是否展开了,那个自动根据 searchable 生成的表单 autoGenerateFilter
lazyRenderAfter: 100,
tableLayout: 'auto'
tableLayout: 'auto',
theadHeight: 0
})
.views(self => {
function getColumnsExceptBuiltinTypes() {
@ -1001,7 +1002,7 @@ export const TableStore = iRendererStore
},
buildStyles(style: any) {
style = {...style};
style = {...style, '--Table-thead-height': self.theadHeight + 'px'};
getFilteredColumns().forEach(column => {
style[`--Table-column-${column.index}-width`] =
@ -1301,9 +1302,9 @@ export const TableStore = iRendererStore
if (!table) {
return;
}
const cols = [].slice.call(
table.querySelectorAll(':scope>thead>tr>th[data-index]')
);
const thead = table.querySelector(':scope>thead') as HTMLElement;
const cols = [].slice.call(thead.querySelectorAll('tr>th[data-index]'));
self.theadHeight = thead.offsetHeight;
cols.forEach((col: HTMLElement) => {
const index = parseInt(col.getAttribute('data-index')!, 10);
const column = self.columns[index];

View File

@ -45,14 +45,14 @@ export function filterClassNameObject(
export function getExprProperties(
schema: PlainObject,
data: object = {},
blackList: Array<string> = ['addOn', 'ref'],
ignoreList: Array<string> = ['addOn', 'ref'],
props?: any
): PlainObject {
const exprProps: PlainObject = {};
let ctx: any = null;
Object.getOwnPropertyNames(schema).forEach(key => {
if (blackList && ~blackList.indexOf(key)) {
if (ignoreList && ~ignoreList.indexOf(key)) {
return;
}
@ -102,4 +102,18 @@ export function getExprProperties(
return exprProps;
}
export function hasExprPropertiesChanged(
schema: PlainObject,
prevSchema: PlainObject
) {
return Object.getOwnPropertyNames(schema).some(key => {
let parts = /^(.*)(On|Expr|(?:c|C)lassName)(Raw)?$/.exec(key);
if (parts) {
return schema[key] !== prevSchema[key];
}
return false;
});
}
export default getExprProperties;

View File

@ -273,8 +273,12 @@
padding-top: 0;
}
&--affixHeader > thead {
visibility: collapse;
&--affixHeader {
margin-top: calc(var(--Table-thead-height) * -1);
> thead {
visibility: hidden;
}
}
&--withCombine {

View File

@ -28,7 +28,7 @@ exports[`doAction:crud reload 1`] = `
>
<div
class="cxd-Table cxd-Crud-body"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -335,7 +335,7 @@ exports[`doAction:crud reload with data1 1`] = `
>
<div
class="cxd-Table cxd-Crud-body"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -642,7 +642,7 @@ exports[`doAction:crud reload with data2 1`] = `
>
<div
class="cxd-Table cxd-Crud-body"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"

View File

@ -53,7 +53,7 @@ exports[`Renderer:input table 1`] = `
>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-contentWrap"
@ -378,7 +378,7 @@ exports[`Renderer:input table add 1`] = `
>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; position: relative;"
>
<div
class="cxd-Table-contentWrap"
@ -690,7 +690,7 @@ exports[`Renderer:input-table cell selects delete 1`] = `
>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-contentWrap"
@ -1029,7 +1029,7 @@ exports[`Renderer:input-table init display 1`] = `
>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; position: relative;"
>
<div
class="cxd-Table-contentWrap"
@ -1716,7 +1716,7 @@ exports[`Renderer:input-table with combo column 1`] = `
>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; position: relative;"
>
<div
class="cxd-Table-contentWrap"

View File

@ -20,7 +20,7 @@ exports[`1. Renderer:crud basic interval headerToolbar footerToolbar 1`] = `
>
<div
class="cxd-Table cxd-Crud-body"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -2157,7 +2157,7 @@ exports[`6. Renderer:crud source & alwaysShowPagination 1`] = `
>
<div
class="cxd-Table cxd-Crud-body"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -2799,7 +2799,7 @@ exports[`13. enderer: crud keepItemSelectionOnPageChange & maxKeepItemSelectionL
</div>
<div
class="cxd-Table cxd-Crud-body"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative; --Table-column-1-width: 0px;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative; --Table-column-1-width: 0px;"
>
<div
class="cxd-Table-fixedTop"

View File

@ -83,7 +83,7 @@ exports[`Renderer:Pagination 1`] = `
</div>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"

View File

@ -4,7 +4,7 @@ exports[`Renderer:table 1`] = `
<div>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -370,7 +370,7 @@ exports[`Renderer:table align 1`] = `
<div>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -775,7 +775,7 @@ exports[`Renderer:table children 1`] = `
>
<div
class="cxd-Table m-b-none"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -1355,7 +1355,7 @@ exports[`Renderer:table classNameExpr 1`] = `
<div>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -1721,7 +1721,7 @@ exports[`Renderer:table column head style className 1`] = `
<div>
<div
class="cxd-Table className"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -2114,7 +2114,7 @@ exports[`Renderer:table combine Renderer:table combineNum only 1`] = `
>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -2689,7 +2689,7 @@ exports[`Renderer:table combine Renderer:table combineNum with fromIndex 1`] = `
>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -3334,7 +3334,7 @@ exports[`Renderer:table groupName-default 1`] = `
>
<div
class="cxd-Table m-b-none"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -4113,7 +4113,7 @@ exports[`Renderer:table groupName-middleNoGroupName 1`] = `
>
<div
class="cxd-Table m-b-none"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -4896,7 +4896,7 @@ exports[`Renderer:table groupName-startNoGroupName 1`] = `
>
<div
class="cxd-Table m-b-none"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -5667,7 +5667,7 @@ exports[`Renderer:table groupName-withTpl 1`] = `
>
<div
class="cxd-Table m-b-none"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-8-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -6430,7 +6430,7 @@ exports[`Renderer:table isHead fixed 1`] = `
<div>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; position: relative;"
>
<div
class="cxd-Table-fixedTop"
@ -6807,7 +6807,7 @@ exports[`Renderer:table list 1`] = `
<div>
<div
class="cxd-Table"
style="--Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; --Table-column-10-width: 0px; --Table-column-11-width: 0px; position: relative;"
style="--Table-thead-height: 0px; --Table-column-3-width: 0px; --Table-column-4-width: 0px; --Table-column-5-width: 0px; --Table-column-6-width: 0px; --Table-column-7-width: 0px; --Table-column-8-width: 0px; --Table-column-9-width: 0px; --Table-column-10-width: 0px; --Table-column-11-width: 0px; position: relative;"
>
<div
class="cxd-Table-toolbar cxd-Table-headToolbar"

View File

@ -30,7 +30,10 @@ function ItemActionsWrapper(props: ItemActionsProps) {
}
const rect = dom.getBoundingClientRect();
const height = rect.height;
const top = rect.top - frame.getBoundingClientRect().top;
const top =
rect.top -
frame.getBoundingClientRect().top +
parseInt(getComputedStyle(frame)['marginTop'], 10);
divRef.current!.style.cssText += `top: ${top}px;height: ${height}px;`;
}, [store.hoverRow?.id]);

View File

@ -1591,6 +1591,10 @@ export default class Table extends React.Component<TableProps, object> {
document.addEventListener('mousemove', this.handleColResizeMouseMove);
document.addEventListener('mouseup', this.handleColResizeMouseUp);
// 防止选中文本
e.preventDefault();
e.stopPropagation();
}
// 垂直线拖拽移动