@formily-design/react 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/containers/Layout.js +1 -0
- package/esm/types.d.ts +2 -0
- package/esm/widgets/AuxToolWidget/DashedBox.js +3 -0
- package/esm/widgets/AuxToolWidget/Insertion.js +5 -4
- package/esm/widgets/AuxToolWidget/NonInteractiveMark.d.ts +5 -0
- package/esm/widgets/AuxToolWidget/NonInteractiveMark.js +115 -0
- package/esm/widgets/AuxToolWidget/Selection.js +41 -2
- package/esm/widgets/AuxToolWidget/Selector.js +1 -1
- package/esm/widgets/AuxToolWidget/index.js +2 -0
- package/esm/widgets/AuxToolWidget/styles.less +76 -0
- package/lib/containers/Layout.js +1 -0
- package/lib/types.d.ts +2 -0
- package/lib/widgets/AuxToolWidget/DashedBox.js +3 -0
- package/lib/widgets/AuxToolWidget/Insertion.js +5 -4
- package/lib/widgets/AuxToolWidget/NonInteractiveMark.d.ts +5 -0
- package/lib/widgets/AuxToolWidget/NonInteractiveMark.js +155 -0
- package/lib/widgets/AuxToolWidget/Selection.js +40 -1
- package/lib/widgets/AuxToolWidget/Selector.js +1 -1
- package/lib/widgets/AuxToolWidget/index.js +2 -0
- package/lib/widgets/AuxToolWidget/styles.less +76 -0
- package/package.json +4 -4
package/esm/containers/Layout.js
CHANGED
package/esm/types.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface IDesignerLayoutProps {
|
|
|
8
8
|
position?: 'fixed' | 'absolute' | 'relative';
|
|
9
9
|
style?: React.CSSProperties;
|
|
10
10
|
className?: string;
|
|
11
|
+
nonInteractiveMarkMessage?: string;
|
|
11
12
|
}
|
|
12
13
|
export interface IDesignerProps extends IDesignerLayoutProps {
|
|
13
14
|
engine: Engine;
|
|
@@ -19,6 +20,7 @@ export interface IDesignerLayoutContext {
|
|
|
19
20
|
theme?: 'dark' | 'light' | (string & {});
|
|
20
21
|
prefixCls: string;
|
|
21
22
|
position: 'fixed' | 'absolute' | 'relative';
|
|
23
|
+
nonInteractiveMarkMessage?: string;
|
|
22
24
|
}
|
|
23
25
|
export interface IWorkspaceContext {
|
|
24
26
|
id: string;
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { useHover, usePrefix, useValidNodeOffsetRect, useSelection, } from '../../hooks';
|
|
3
3
|
import { observer } from '@formily/reactive-react';
|
|
4
4
|
export const DashedBox = observer(() => {
|
|
5
|
+
var _a, _b;
|
|
5
6
|
const hover = useHover();
|
|
6
7
|
const prefix = usePrefix('aux-dashed-box');
|
|
7
8
|
const selection = useSelection();
|
|
@@ -27,6 +28,8 @@ export const DashedBox = observer(() => {
|
|
|
27
28
|
return null;
|
|
28
29
|
if (hover.node.hidden)
|
|
29
30
|
return null;
|
|
31
|
+
if ((_b = (_a = hover.node).isNonInteractive) === null || _b === void 0 ? void 0 : _b.call(_a))
|
|
32
|
+
return null;
|
|
30
33
|
if (selection.selected.includes(hover.node.id))
|
|
31
34
|
return null;
|
|
32
35
|
return (React.createElement("div", { className: prefix, style: createTipsStyle() },
|
|
@@ -2,7 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { useMoveHelper, usePrefix } from '../../hooks';
|
|
3
3
|
import { ClosestPosition } from '@formily-design/core';
|
|
4
4
|
import { observer } from '@formily/reactive-react';
|
|
5
|
+
import cls from 'classnames';
|
|
5
6
|
export const Insertion = observer(() => {
|
|
7
|
+
var _a;
|
|
6
8
|
const moveHelper = useMoveHelper();
|
|
7
9
|
const prefix = usePrefix('aux-insertion');
|
|
8
10
|
const createInsertionStyle = () => {
|
|
@@ -60,11 +62,10 @@ export const Insertion = observer(() => {
|
|
|
60
62
|
baseStyle.transform = `perspective(1px) translate3d(${closestRect.x}px,${closestRect.y}px,0)`;
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
|
-
if (closestDirection.includes('FORBID')) {
|
|
64
|
-
baseStyle.backgroundColor = 'red';
|
|
65
|
-
}
|
|
66
65
|
return baseStyle;
|
|
67
66
|
};
|
|
68
|
-
return React.createElement("div", { className: prefix,
|
|
67
|
+
return (React.createElement("div", { className: cls(prefix, {
|
|
68
|
+
forbidden: (_a = moveHelper.viewportClosestDirection) === null || _a === void 0 ? void 0 : _a.includes('FORBID'),
|
|
69
|
+
}), style: createInsertionStyle() }));
|
|
69
70
|
});
|
|
70
71
|
Insertion.displayName = 'Insertion';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TreeNode } from '@formily-design/core';
|
|
3
|
+
export declare const DEFAULT_NON_INTERACTIVE_MARK_MESSAGE = "\u7CFB\u7EDF\u5185\u7F6E\u7EC4\u4EF6\uFF0C\u4E0D\u53EF\u7F16\u8F91";
|
|
4
|
+
export declare const getNonInteractiveMarkNodes: (tree: TreeNode) => TreeNode[];
|
|
5
|
+
export declare const NonInteractiveMark: React.MemoExoticComponent<import("@formily/reactive-react").ReactFC<unknown>>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { DragStopEvent } from '@formily-design/core';
|
|
3
|
+
import { observer } from '@formily/reactive-react';
|
|
4
|
+
import cls from 'classnames';
|
|
5
|
+
import { useDesigner, useHover, useLayout, usePrefix, useTree, useValidNodeOffsetRect, } from '../../hooks';
|
|
6
|
+
export const DEFAULT_NON_INTERACTIVE_MARK_MESSAGE = '系统内置组件,不可编辑';
|
|
7
|
+
export const getNonInteractiveMarkNodes = (tree) => {
|
|
8
|
+
if (!tree)
|
|
9
|
+
return [];
|
|
10
|
+
return tree.descendants.filter((node) => {
|
|
11
|
+
var _a;
|
|
12
|
+
return !node.hidden && ((_a = node.isNonInteractive) === null || _a === void 0 ? void 0 : _a.call(node));
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
const NonInteractiveMarkBox = observer(({ node, active, message }) => {
|
|
16
|
+
const prefix = usePrefix('aux-non-interactive-mark');
|
|
17
|
+
const rect = useValidNodeOffsetRect(node);
|
|
18
|
+
if (!(rect === null || rect === void 0 ? void 0 : rect.width) || !(rect === null || rect === void 0 ? void 0 : rect.height))
|
|
19
|
+
return null;
|
|
20
|
+
return (React.createElement("div", { className: cls(prefix, {
|
|
21
|
+
active,
|
|
22
|
+
}), style: {
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
top: 0,
|
|
25
|
+
left: 0,
|
|
26
|
+
boxSizing: 'border-box',
|
|
27
|
+
pointerEvents: 'none',
|
|
28
|
+
zIndex: 1,
|
|
29
|
+
transform: `perspective(1px) translate3d(${rect.x}px,${rect.y}px,0)`,
|
|
30
|
+
width: rect.width,
|
|
31
|
+
height: rect.height,
|
|
32
|
+
}, "aria-label": message },
|
|
33
|
+
React.createElement("span", { className: prefix + '-lock', "aria-hidden": "true" }),
|
|
34
|
+
active && React.createElement("span", { className: prefix + '-tip' }, message)));
|
|
35
|
+
});
|
|
36
|
+
export const NonInteractiveMark = observer(() => {
|
|
37
|
+
var _a;
|
|
38
|
+
const [measureTick, refreshMarks] = useState(0);
|
|
39
|
+
const engine = useDesigner();
|
|
40
|
+
const layout = useLayout();
|
|
41
|
+
const tree = useTree();
|
|
42
|
+
const hover = useHover();
|
|
43
|
+
const nodes = getNonInteractiveMarkNodes(tree);
|
|
44
|
+
const nodeIds = nodes.map((node) => node.id).join('|');
|
|
45
|
+
const message = ((_a = layout === null || layout === void 0 ? void 0 : layout.nonInteractiveMarkMessage) === null || _a === void 0 ? void 0 : _a.trim()) ||
|
|
46
|
+
DEFAULT_NON_INTERACTIVE_MARK_MESSAGE;
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
/*
|
|
49
|
+
* tree 数据在首次渲染时通常已经存在,但画布中的真实组件 DOM
|
|
50
|
+
* 可能还没有完成挂载或布局测量。此时 NonInteractiveMarkBox 内部的
|
|
51
|
+
* useValidNodeOffsetRect(node) 会拿不到有效 rect,并因为无尺寸直接
|
|
52
|
+
* return null;mark box 没有真正挂载后,也就没有机会依赖自身的
|
|
53
|
+
* LayoutObserver 等待后续布局变化。
|
|
54
|
+
*
|
|
55
|
+
* 之前用户看到的现象是:默认没有 dn-aux-non-interactive-mark,
|
|
56
|
+
* 只有 hover 改变 hover.node、触发辅助层重新渲染后,rect 才能被
|
|
57
|
+
* 重新计算出来,锁标识和虚线边框才出现。
|
|
58
|
+
*
|
|
59
|
+
* 业务也可能在 FormilyDesigner 挂载后通过 engine.setCurrentTree()
|
|
60
|
+
* 设置默认 schema。setCurrentTree 会更新同一个 root tree 的 children,
|
|
61
|
+
* root tree 引用本身不会变化;如果 effect 只依赖 tree,就不会在不可操作
|
|
62
|
+
* 节点列表从空变为有值时重新安排测量刷新。因此这里使用不可操作节点 id
|
|
63
|
+
* 签名作为依赖,让默认 schema 后置注入时也能触发一次补偿测量。
|
|
64
|
+
*
|
|
65
|
+
* 这里在父级统一安排一次 requestAnimationFrame,让浏览器进入下一帧
|
|
66
|
+
* 后再刷新不可操作标识层。measureTick 会参与 mark box 的 key,让这些
|
|
67
|
+
* 辅助标识组件在下一帧 remount 一次,重新初始化 useValidNodeOffsetRect
|
|
68
|
+
* 内部缓存的初始 rect。这样可以等画布 DOM 有机会完成挂载/布局后重新
|
|
69
|
+
* 计算 rect,使默认锁标识在不 hover 时也能显示。刷新只发生一次,不在
|
|
70
|
+
* 每个节点上分别调度,避免不可操作节点较多时产生重复更新;同时这只
|
|
71
|
+
* 影响设计器辅助层,不改变节点交互规则,也不会影响 preview 或运行态。
|
|
72
|
+
*/
|
|
73
|
+
const frame = requestAnimationFrame(() => {
|
|
74
|
+
refreshMarks((tick) => tick + 1);
|
|
75
|
+
});
|
|
76
|
+
return () => {
|
|
77
|
+
cancelAnimationFrame(frame);
|
|
78
|
+
};
|
|
79
|
+
}, [nodeIds]);
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
/*
|
|
82
|
+
* 拖拽移动普通节点到不可操作节点前方时(尤其是
|
|
83
|
+
* protectNonInteractiveInsertion 关闭的合法场景),不可操作节点会在
|
|
84
|
+
* 真实画布中被后移。useValidNodeOffsetRect 为了避免拖拽过程中高频测量,
|
|
85
|
+
* 会在 cursor 处于 Move 拖拽状态时跳过 LayoutObserver 触发的 compute。
|
|
86
|
+
*
|
|
87
|
+
* drop 时树结构 mutation 和 DOM 位移通常发生在同一次 drag:stop 事件流程里;
|
|
88
|
+
* 如果这次布局变化刚好被拖拽态保护跳过,之后 mark box 自身没有新的布局
|
|
89
|
+
* 事件可依赖,就会继续使用旧 rect。表现上就是锁定虚线框停留在原来的位置,
|
|
90
|
+
* 而新插入到该位置的可编辑节点看起来被套上了不可操作样式。
|
|
91
|
+
*
|
|
92
|
+
* 这里仅在拖拽结束后由父级统一安排一个 requestAnimationFrame,并通过
|
|
93
|
+
* measureTick remount mark box,让它在下一帧重新读取不可操作节点的最新
|
|
94
|
+
* offset rect。这样标识跟随真正的不可操作节点移动,同时不改变节点交互
|
|
95
|
+
* 规则、不影响 preview/运行态,也不会在每个 mark box 上分别创建刷新任务。
|
|
96
|
+
*/
|
|
97
|
+
let frame = 0;
|
|
98
|
+
const unsubscribe = engine.subscribeTo(DragStopEvent, () => {
|
|
99
|
+
if (!nodeIds)
|
|
100
|
+
return;
|
|
101
|
+
cancelAnimationFrame(frame);
|
|
102
|
+
frame = requestAnimationFrame(() => {
|
|
103
|
+
refreshMarks((tick) => tick + 1);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
return () => {
|
|
107
|
+
cancelAnimationFrame(frame);
|
|
108
|
+
unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
|
|
109
|
+
};
|
|
110
|
+
}, [engine, nodeIds]);
|
|
111
|
+
return (React.createElement(React.Fragment, null, nodes.map((node) => {
|
|
112
|
+
return (React.createElement(NonInteractiveMarkBox, { key: `${node.id}-${measureTick}`, node: node, active: (hover === null || hover === void 0 ? void 0 : hover.node) === node, message: message }));
|
|
113
|
+
})));
|
|
114
|
+
});
|
|
115
|
+
NonInteractiveMark.displayName = 'NonInteractiveMark';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import React, { Fragment } from 'react';
|
|
1
|
+
import React, { Fragment, useEffect, useState } from 'react';
|
|
2
2
|
import { Helpers } from './Helpers';
|
|
3
3
|
import { ResizeHandler } from './ResizeHandler';
|
|
4
4
|
import { useSelection, useValidNodeOffsetRect, useTree, useCursor, useMoveHelper, usePrefix, useDesigner, } from '../../hooks';
|
|
5
5
|
import { observer } from '@formily/reactive-react';
|
|
6
|
+
import { CursorDragType, DragStopEvent } from '@formily-design/core';
|
|
6
7
|
import { TranslateHandler } from './TranslateHandler';
|
|
7
8
|
export const SelectionBox = (props) => {
|
|
8
9
|
var _a;
|
|
@@ -39,10 +40,46 @@ export const SelectionBox = (props) => {
|
|
|
39
40
|
props.showHelpers && (React.createElement(Helpers, { ...props, node: props.node, nodeRect: nodeRect }))));
|
|
40
41
|
};
|
|
41
42
|
export const Selection = observer(() => {
|
|
43
|
+
const designer = useDesigner();
|
|
44
|
+
const [measureTick, refreshSelectionBox] = useState(0);
|
|
42
45
|
const selection = useSelection();
|
|
43
46
|
const tree = useTree();
|
|
44
47
|
const cursor = useCursor();
|
|
45
48
|
const viewportMoveHelper = useMoveHelper();
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
/*
|
|
51
|
+
* SelectionBox 会在拖拽过程中被下面的条件隐藏并卸载:
|
|
52
|
+
* cursor.status !== 'NORMAL' && viewportMoveHelper.touchNode。
|
|
53
|
+
* 因此把 drag:stop 后的补偿测量只放在 SelectionBox 内部的
|
|
54
|
+
* useValidNodeOffsetRect 是不够的:真正释放鼠标时,选择框组件可能
|
|
55
|
+
* 还没有重新挂载,收不到这次 drag:stop 事件。
|
|
56
|
+
*
|
|
57
|
+
* 拖拽排序完成后,selection 仍然指向正确节点 id,但辅助框可能使用
|
|
58
|
+
* 重新挂载时读到的旧 rect,表现为节点已经换位,dn-aux-selection-box
|
|
59
|
+
* 还停在拖拽前的位置。这里在始终挂载的 Selection 父层监听 drag:stop,
|
|
60
|
+
* 等 drop mutation、moveHelper.dragEnd、React 提交和浏览器布局稳定后,
|
|
61
|
+
* 通过 measureTick remount 选择框,让 useValidNodeOffsetRect 重新读取
|
|
62
|
+
* 当前 DOM 位置。
|
|
63
|
+
*
|
|
64
|
+
* 这里先使用单帧 RAF 做低成本补偿,等拖拽结束引发的状态更新和
|
|
65
|
+
* React 重挂载有机会提交后再刷新选择框 key。该刷新只发生在 Move
|
|
66
|
+
* 拖拽结束后,影响范围限于设计器辅助层,不改变节点数据、选择状态或
|
|
67
|
+
* preview/运行态渲染。
|
|
68
|
+
*/
|
|
69
|
+
let frame = 0;
|
|
70
|
+
const unsubscribe = designer.subscribeTo(DragStopEvent, () => {
|
|
71
|
+
if (designer.cursor.dragType !== CursorDragType.Move)
|
|
72
|
+
return;
|
|
73
|
+
cancelAnimationFrame(frame);
|
|
74
|
+
frame = requestAnimationFrame(() => {
|
|
75
|
+
refreshSelectionBox((tick) => tick + 1);
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
return () => {
|
|
79
|
+
cancelAnimationFrame(frame);
|
|
80
|
+
unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
|
|
81
|
+
};
|
|
82
|
+
}, [designer]);
|
|
46
83
|
if (cursor.status !== 'NORMAL' && viewportMoveHelper.touchNode)
|
|
47
84
|
return null;
|
|
48
85
|
return (React.createElement(Fragment, null, selection.selected.map((id) => {
|
|
@@ -51,7 +88,9 @@ export const Selection = observer(() => {
|
|
|
51
88
|
return;
|
|
52
89
|
if (node.hidden)
|
|
53
90
|
return;
|
|
54
|
-
|
|
91
|
+
if (!node.allowSelect())
|
|
92
|
+
return;
|
|
93
|
+
return (React.createElement(SelectionBox, { key: `${id}-${measureTick}`, node: node, showHelpers: selection.selected.length === 1 }));
|
|
55
94
|
})));
|
|
56
95
|
});
|
|
57
96
|
Selection.displayName = 'Selection';
|
|
@@ -51,7 +51,7 @@ export const Selector = observer(({ node }) => {
|
|
|
51
51
|
return React.createElement(IconWidget, { infer: "Component" });
|
|
52
52
|
};
|
|
53
53
|
const renderMenu = () => {
|
|
54
|
-
const parents = node.getParents();
|
|
54
|
+
const parents = node.getParents().filter((parent) => parent.allowSelect());
|
|
55
55
|
return (React.createElement("div", { className: prefix + '-menu', style: {
|
|
56
56
|
position: 'absolute',
|
|
57
57
|
top: '100%',
|
|
@@ -7,6 +7,7 @@ import { Cover } from './Cover';
|
|
|
7
7
|
import { DashedBox } from './DashedBox';
|
|
8
8
|
import { SpaceBlock } from './SpaceBlock';
|
|
9
9
|
import { SnapLine } from './SnapLine';
|
|
10
|
+
import { NonInteractiveMark } from './NonInteractiveMark';
|
|
10
11
|
import './styles.less';
|
|
11
12
|
export const AuxToolWidget = () => {
|
|
12
13
|
const engine = useDesigner();
|
|
@@ -26,6 +27,7 @@ export const AuxToolWidget = () => {
|
|
|
26
27
|
React.createElement(Insertion, null),
|
|
27
28
|
React.createElement(SpaceBlock, null),
|
|
28
29
|
React.createElement(SnapLine, null),
|
|
30
|
+
React.createElement(NonInteractiveMark, null),
|
|
29
31
|
React.createElement(DashedBox, null),
|
|
30
32
|
React.createElement(Selection, null),
|
|
31
33
|
React.createElement(Cover, null),
|
|
@@ -174,6 +174,11 @@
|
|
|
174
174
|
|
|
175
175
|
.@{prefix-cls}-aux-insertion {
|
|
176
176
|
background-color: var(--dn-aux-insertion-color);
|
|
177
|
+
|
|
178
|
+
&.forbidden {
|
|
179
|
+
background-color: var(--dn-aux-insertion-forbidden-color, red);
|
|
180
|
+
box-shadow: 0 0 0 1px rgba(255, 0, 0, 0.18);
|
|
181
|
+
}
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
.@{prefix-cls}-aux-dashed-box {
|
|
@@ -184,6 +189,77 @@
|
|
|
184
189
|
}
|
|
185
190
|
}
|
|
186
191
|
|
|
192
|
+
.@{prefix-cls}-aux-non-interactive-mark {
|
|
193
|
+
border: 1px dashed var(--dn-aux-non-interactive-border-color, #7f93aa);
|
|
194
|
+
background: var(--dn-aux-non-interactive-bg-color, rgba(127, 147, 170, 0.04));
|
|
195
|
+
transition: border-color 0.12s ease, background-color 0.12s ease,
|
|
196
|
+
box-shadow 0.12s ease;
|
|
197
|
+
|
|
198
|
+
&.active {
|
|
199
|
+
border-color: var(--dn-aux-non-interactive-active-border-color, #3f5f7f);
|
|
200
|
+
background: var(
|
|
201
|
+
--dn-aux-non-interactive-active-bg-color,
|
|
202
|
+
rgba(63, 95, 127, 0.07)
|
|
203
|
+
);
|
|
204
|
+
box-shadow: 0 0 0 1px rgba(63, 95, 127, 0.12);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
&-lock {
|
|
208
|
+
position: absolute;
|
|
209
|
+
top: -1px;
|
|
210
|
+
right: -1px;
|
|
211
|
+
width: 16px;
|
|
212
|
+
height: 16px;
|
|
213
|
+
border-radius: 0 1px 0 6px;
|
|
214
|
+
background: var(--dn-aux-non-interactive-lock-bg-color, #5f7286);
|
|
215
|
+
box-shadow: 0 1px 3px rgba(31, 45, 61, 0.18);
|
|
216
|
+
|
|
217
|
+
&::before {
|
|
218
|
+
content: '';
|
|
219
|
+
position: absolute;
|
|
220
|
+
left: 5px;
|
|
221
|
+
top: 3px;
|
|
222
|
+
width: 6px;
|
|
223
|
+
height: 5px;
|
|
224
|
+
border: 1.5px solid #fff;
|
|
225
|
+
border-bottom: 0;
|
|
226
|
+
border-radius: 5px 5px 0 0;
|
|
227
|
+
box-sizing: border-box;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
&::after {
|
|
231
|
+
content: '';
|
|
232
|
+
position: absolute;
|
|
233
|
+
left: 4px;
|
|
234
|
+
top: 7px;
|
|
235
|
+
width: 8px;
|
|
236
|
+
height: 6px;
|
|
237
|
+
border-radius: 1px;
|
|
238
|
+
background: #fff;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
&.active &-lock {
|
|
243
|
+
background: var(--dn-aux-non-interactive-active-lock-bg-color, #334f6b);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
&-tip {
|
|
247
|
+
position: absolute;
|
|
248
|
+
right: -1px;
|
|
249
|
+
bottom: 100%;
|
|
250
|
+
margin-bottom: 4px;
|
|
251
|
+
padding: 2px 6px;
|
|
252
|
+
border-radius: 2px;
|
|
253
|
+
color: #fff;
|
|
254
|
+
background: var(--dn-aux-non-interactive-tip-bg-color, #334f6b);
|
|
255
|
+
box-shadow: 0 2px 8px rgba(31, 45, 61, 0.18);
|
|
256
|
+
font-size: 12px;
|
|
257
|
+
line-height: 18px;
|
|
258
|
+
white-space: nowrap;
|
|
259
|
+
user-select: none;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
187
263
|
.@{prefix-cls}-aux-selection-box {
|
|
188
264
|
border: 2px solid var(--dn-aux-selection-box-border-color);
|
|
189
265
|
position: relative;
|
package/lib/containers/Layout.js
CHANGED
package/lib/types.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface IDesignerLayoutProps {
|
|
|
8
8
|
position?: 'fixed' | 'absolute' | 'relative';
|
|
9
9
|
style?: React.CSSProperties;
|
|
10
10
|
className?: string;
|
|
11
|
+
nonInteractiveMarkMessage?: string;
|
|
11
12
|
}
|
|
12
13
|
export interface IDesignerProps extends IDesignerLayoutProps {
|
|
13
14
|
engine: Engine;
|
|
@@ -19,6 +20,7 @@ export interface IDesignerLayoutContext {
|
|
|
19
20
|
theme?: 'dark' | 'light' | (string & {});
|
|
20
21
|
prefixCls: string;
|
|
21
22
|
position: 'fixed' | 'absolute' | 'relative';
|
|
23
|
+
nonInteractiveMarkMessage?: string;
|
|
22
24
|
}
|
|
23
25
|
export interface IWorkspaceContext {
|
|
24
26
|
id: string;
|
|
@@ -8,6 +8,7 @@ const react_1 = __importDefault(require("react"));
|
|
|
8
8
|
const hooks_1 = require("../../hooks");
|
|
9
9
|
const reactive_react_1 = require("@formily/reactive-react");
|
|
10
10
|
exports.DashedBox = (0, reactive_react_1.observer)(() => {
|
|
11
|
+
var _a, _b;
|
|
11
12
|
const hover = (0, hooks_1.useHover)();
|
|
12
13
|
const prefix = (0, hooks_1.usePrefix)('aux-dashed-box');
|
|
13
14
|
const selection = (0, hooks_1.useSelection)();
|
|
@@ -33,6 +34,8 @@ exports.DashedBox = (0, reactive_react_1.observer)(() => {
|
|
|
33
34
|
return null;
|
|
34
35
|
if (hover.node.hidden)
|
|
35
36
|
return null;
|
|
37
|
+
if ((_b = (_a = hover.node).isNonInteractive) === null || _b === void 0 ? void 0 : _b.call(_a))
|
|
38
|
+
return null;
|
|
36
39
|
if (selection.selected.includes(hover.node.id))
|
|
37
40
|
return null;
|
|
38
41
|
return (react_1.default.createElement("div", { className: prefix, style: createTipsStyle() },
|
|
@@ -8,7 +8,9 @@ const react_1 = __importDefault(require("react"));
|
|
|
8
8
|
const hooks_1 = require("../../hooks");
|
|
9
9
|
const core_1 = require("@formily-design/core");
|
|
10
10
|
const reactive_react_1 = require("@formily/reactive-react");
|
|
11
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
11
12
|
exports.Insertion = (0, reactive_react_1.observer)(() => {
|
|
13
|
+
var _a;
|
|
12
14
|
const moveHelper = (0, hooks_1.useMoveHelper)();
|
|
13
15
|
const prefix = (0, hooks_1.usePrefix)('aux-insertion');
|
|
14
16
|
const createInsertionStyle = () => {
|
|
@@ -66,11 +68,10 @@ exports.Insertion = (0, reactive_react_1.observer)(() => {
|
|
|
66
68
|
baseStyle.transform = `perspective(1px) translate3d(${closestRect.x}px,${closestRect.y}px,0)`;
|
|
67
69
|
}
|
|
68
70
|
}
|
|
69
|
-
if (closestDirection.includes('FORBID')) {
|
|
70
|
-
baseStyle.backgroundColor = 'red';
|
|
71
|
-
}
|
|
72
71
|
return baseStyle;
|
|
73
72
|
};
|
|
74
|
-
return react_1.default.createElement("div", { className:
|
|
73
|
+
return (react_1.default.createElement("div", { className: (0, classnames_1.default)(prefix, {
|
|
74
|
+
forbidden: (_a = moveHelper.viewportClosestDirection) === null || _a === void 0 ? void 0 : _a.includes('FORBID'),
|
|
75
|
+
}), style: createInsertionStyle() }));
|
|
75
76
|
});
|
|
76
77
|
exports.Insertion.displayName = 'Insertion';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TreeNode } from '@formily-design/core';
|
|
3
|
+
export declare const DEFAULT_NON_INTERACTIVE_MARK_MESSAGE = "\u7CFB\u7EDF\u5185\u7F6E\u7EC4\u4EF6\uFF0C\u4E0D\u53EF\u7F16\u8F91";
|
|
4
|
+
export declare const getNonInteractiveMarkNodes: (tree: TreeNode) => TreeNode[];
|
|
5
|
+
export declare const NonInteractiveMark: React.MemoExoticComponent<import("@formily/reactive-react").ReactFC<unknown>>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.NonInteractiveMark = exports.getNonInteractiveMarkNodes = exports.DEFAULT_NON_INTERACTIVE_MARK_MESSAGE = void 0;
|
|
40
|
+
const react_1 = __importStar(require("react"));
|
|
41
|
+
const core_1 = require("@formily-design/core");
|
|
42
|
+
const reactive_react_1 = require("@formily/reactive-react");
|
|
43
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
44
|
+
const hooks_1 = require("../../hooks");
|
|
45
|
+
exports.DEFAULT_NON_INTERACTIVE_MARK_MESSAGE = '系统内置组件,不可编辑';
|
|
46
|
+
const getNonInteractiveMarkNodes = (tree) => {
|
|
47
|
+
if (!tree)
|
|
48
|
+
return [];
|
|
49
|
+
return tree.descendants.filter((node) => {
|
|
50
|
+
var _a;
|
|
51
|
+
return !node.hidden && ((_a = node.isNonInteractive) === null || _a === void 0 ? void 0 : _a.call(node));
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
exports.getNonInteractiveMarkNodes = getNonInteractiveMarkNodes;
|
|
55
|
+
const NonInteractiveMarkBox = (0, reactive_react_1.observer)(({ node, active, message }) => {
|
|
56
|
+
const prefix = (0, hooks_1.usePrefix)('aux-non-interactive-mark');
|
|
57
|
+
const rect = (0, hooks_1.useValidNodeOffsetRect)(node);
|
|
58
|
+
if (!(rect === null || rect === void 0 ? void 0 : rect.width) || !(rect === null || rect === void 0 ? void 0 : rect.height))
|
|
59
|
+
return null;
|
|
60
|
+
return (react_1.default.createElement("div", { className: (0, classnames_1.default)(prefix, {
|
|
61
|
+
active,
|
|
62
|
+
}), style: {
|
|
63
|
+
position: 'absolute',
|
|
64
|
+
top: 0,
|
|
65
|
+
left: 0,
|
|
66
|
+
boxSizing: 'border-box',
|
|
67
|
+
pointerEvents: 'none',
|
|
68
|
+
zIndex: 1,
|
|
69
|
+
transform: `perspective(1px) translate3d(${rect.x}px,${rect.y}px,0)`,
|
|
70
|
+
width: rect.width,
|
|
71
|
+
height: rect.height,
|
|
72
|
+
}, "aria-label": message },
|
|
73
|
+
react_1.default.createElement("span", { className: prefix + '-lock', "aria-hidden": "true" }),
|
|
74
|
+
active && react_1.default.createElement("span", { className: prefix + '-tip' }, message)));
|
|
75
|
+
});
|
|
76
|
+
exports.NonInteractiveMark = (0, reactive_react_1.observer)(() => {
|
|
77
|
+
var _a;
|
|
78
|
+
const [measureTick, refreshMarks] = (0, react_1.useState)(0);
|
|
79
|
+
const engine = (0, hooks_1.useDesigner)();
|
|
80
|
+
const layout = (0, hooks_1.useLayout)();
|
|
81
|
+
const tree = (0, hooks_1.useTree)();
|
|
82
|
+
const hover = (0, hooks_1.useHover)();
|
|
83
|
+
const nodes = (0, exports.getNonInteractiveMarkNodes)(tree);
|
|
84
|
+
const nodeIds = nodes.map((node) => node.id).join('|');
|
|
85
|
+
const message = ((_a = layout === null || layout === void 0 ? void 0 : layout.nonInteractiveMarkMessage) === null || _a === void 0 ? void 0 : _a.trim()) ||
|
|
86
|
+
exports.DEFAULT_NON_INTERACTIVE_MARK_MESSAGE;
|
|
87
|
+
(0, react_1.useEffect)(() => {
|
|
88
|
+
/*
|
|
89
|
+
* tree 数据在首次渲染时通常已经存在,但画布中的真实组件 DOM
|
|
90
|
+
* 可能还没有完成挂载或布局测量。此时 NonInteractiveMarkBox 内部的
|
|
91
|
+
* useValidNodeOffsetRect(node) 会拿不到有效 rect,并因为无尺寸直接
|
|
92
|
+
* return null;mark box 没有真正挂载后,也就没有机会依赖自身的
|
|
93
|
+
* LayoutObserver 等待后续布局变化。
|
|
94
|
+
*
|
|
95
|
+
* 之前用户看到的现象是:默认没有 dn-aux-non-interactive-mark,
|
|
96
|
+
* 只有 hover 改变 hover.node、触发辅助层重新渲染后,rect 才能被
|
|
97
|
+
* 重新计算出来,锁标识和虚线边框才出现。
|
|
98
|
+
*
|
|
99
|
+
* 业务也可能在 FormilyDesigner 挂载后通过 engine.setCurrentTree()
|
|
100
|
+
* 设置默认 schema。setCurrentTree 会更新同一个 root tree 的 children,
|
|
101
|
+
* root tree 引用本身不会变化;如果 effect 只依赖 tree,就不会在不可操作
|
|
102
|
+
* 节点列表从空变为有值时重新安排测量刷新。因此这里使用不可操作节点 id
|
|
103
|
+
* 签名作为依赖,让默认 schema 后置注入时也能触发一次补偿测量。
|
|
104
|
+
*
|
|
105
|
+
* 这里在父级统一安排一次 requestAnimationFrame,让浏览器进入下一帧
|
|
106
|
+
* 后再刷新不可操作标识层。measureTick 会参与 mark box 的 key,让这些
|
|
107
|
+
* 辅助标识组件在下一帧 remount 一次,重新初始化 useValidNodeOffsetRect
|
|
108
|
+
* 内部缓存的初始 rect。这样可以等画布 DOM 有机会完成挂载/布局后重新
|
|
109
|
+
* 计算 rect,使默认锁标识在不 hover 时也能显示。刷新只发生一次,不在
|
|
110
|
+
* 每个节点上分别调度,避免不可操作节点较多时产生重复更新;同时这只
|
|
111
|
+
* 影响设计器辅助层,不改变节点交互规则,也不会影响 preview 或运行态。
|
|
112
|
+
*/
|
|
113
|
+
const frame = requestAnimationFrame(() => {
|
|
114
|
+
refreshMarks((tick) => tick + 1);
|
|
115
|
+
});
|
|
116
|
+
return () => {
|
|
117
|
+
cancelAnimationFrame(frame);
|
|
118
|
+
};
|
|
119
|
+
}, [nodeIds]);
|
|
120
|
+
(0, react_1.useEffect)(() => {
|
|
121
|
+
/*
|
|
122
|
+
* 拖拽移动普通节点到不可操作节点前方时(尤其是
|
|
123
|
+
* protectNonInteractiveInsertion 关闭的合法场景),不可操作节点会在
|
|
124
|
+
* 真实画布中被后移。useValidNodeOffsetRect 为了避免拖拽过程中高频测量,
|
|
125
|
+
* 会在 cursor 处于 Move 拖拽状态时跳过 LayoutObserver 触发的 compute。
|
|
126
|
+
*
|
|
127
|
+
* drop 时树结构 mutation 和 DOM 位移通常发生在同一次 drag:stop 事件流程里;
|
|
128
|
+
* 如果这次布局变化刚好被拖拽态保护跳过,之后 mark box 自身没有新的布局
|
|
129
|
+
* 事件可依赖,就会继续使用旧 rect。表现上就是锁定虚线框停留在原来的位置,
|
|
130
|
+
* 而新插入到该位置的可编辑节点看起来被套上了不可操作样式。
|
|
131
|
+
*
|
|
132
|
+
* 这里仅在拖拽结束后由父级统一安排一个 requestAnimationFrame,并通过
|
|
133
|
+
* measureTick remount mark box,让它在下一帧重新读取不可操作节点的最新
|
|
134
|
+
* offset rect。这样标识跟随真正的不可操作节点移动,同时不改变节点交互
|
|
135
|
+
* 规则、不影响 preview/运行态,也不会在每个 mark box 上分别创建刷新任务。
|
|
136
|
+
*/
|
|
137
|
+
let frame = 0;
|
|
138
|
+
const unsubscribe = engine.subscribeTo(core_1.DragStopEvent, () => {
|
|
139
|
+
if (!nodeIds)
|
|
140
|
+
return;
|
|
141
|
+
cancelAnimationFrame(frame);
|
|
142
|
+
frame = requestAnimationFrame(() => {
|
|
143
|
+
refreshMarks((tick) => tick + 1);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
return () => {
|
|
147
|
+
cancelAnimationFrame(frame);
|
|
148
|
+
unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
|
|
149
|
+
};
|
|
150
|
+
}, [engine, nodeIds]);
|
|
151
|
+
return (react_1.default.createElement(react_1.default.Fragment, null, nodes.map((node) => {
|
|
152
|
+
return (react_1.default.createElement(NonInteractiveMarkBox, { key: `${node.id}-${measureTick}`, node: node, active: (hover === null || hover === void 0 ? void 0 : hover.node) === node, message: message }));
|
|
153
|
+
})));
|
|
154
|
+
});
|
|
155
|
+
exports.NonInteractiveMark.displayName = 'NonInteractiveMark';
|
|
@@ -39,6 +39,7 @@ const Helpers_1 = require("./Helpers");
|
|
|
39
39
|
const ResizeHandler_1 = require("./ResizeHandler");
|
|
40
40
|
const hooks_1 = require("../../hooks");
|
|
41
41
|
const reactive_react_1 = require("@formily/reactive-react");
|
|
42
|
+
const core_1 = require("@formily-design/core");
|
|
42
43
|
const TranslateHandler_1 = require("./TranslateHandler");
|
|
43
44
|
const SelectionBox = (props) => {
|
|
44
45
|
var _a;
|
|
@@ -76,10 +77,46 @@ const SelectionBox = (props) => {
|
|
|
76
77
|
};
|
|
77
78
|
exports.SelectionBox = SelectionBox;
|
|
78
79
|
exports.Selection = (0, reactive_react_1.observer)(() => {
|
|
80
|
+
const designer = (0, hooks_1.useDesigner)();
|
|
81
|
+
const [measureTick, refreshSelectionBox] = (0, react_1.useState)(0);
|
|
79
82
|
const selection = (0, hooks_1.useSelection)();
|
|
80
83
|
const tree = (0, hooks_1.useTree)();
|
|
81
84
|
const cursor = (0, hooks_1.useCursor)();
|
|
82
85
|
const viewportMoveHelper = (0, hooks_1.useMoveHelper)();
|
|
86
|
+
(0, react_1.useEffect)(() => {
|
|
87
|
+
/*
|
|
88
|
+
* SelectionBox 会在拖拽过程中被下面的条件隐藏并卸载:
|
|
89
|
+
* cursor.status !== 'NORMAL' && viewportMoveHelper.touchNode。
|
|
90
|
+
* 因此把 drag:stop 后的补偿测量只放在 SelectionBox 内部的
|
|
91
|
+
* useValidNodeOffsetRect 是不够的:真正释放鼠标时,选择框组件可能
|
|
92
|
+
* 还没有重新挂载,收不到这次 drag:stop 事件。
|
|
93
|
+
*
|
|
94
|
+
* 拖拽排序完成后,selection 仍然指向正确节点 id,但辅助框可能使用
|
|
95
|
+
* 重新挂载时读到的旧 rect,表现为节点已经换位,dn-aux-selection-box
|
|
96
|
+
* 还停在拖拽前的位置。这里在始终挂载的 Selection 父层监听 drag:stop,
|
|
97
|
+
* 等 drop mutation、moveHelper.dragEnd、React 提交和浏览器布局稳定后,
|
|
98
|
+
* 通过 measureTick remount 选择框,让 useValidNodeOffsetRect 重新读取
|
|
99
|
+
* 当前 DOM 位置。
|
|
100
|
+
*
|
|
101
|
+
* 这里先使用单帧 RAF 做低成本补偿,等拖拽结束引发的状态更新和
|
|
102
|
+
* React 重挂载有机会提交后再刷新选择框 key。该刷新只发生在 Move
|
|
103
|
+
* 拖拽结束后,影响范围限于设计器辅助层,不改变节点数据、选择状态或
|
|
104
|
+
* preview/运行态渲染。
|
|
105
|
+
*/
|
|
106
|
+
let frame = 0;
|
|
107
|
+
const unsubscribe = designer.subscribeTo(core_1.DragStopEvent, () => {
|
|
108
|
+
if (designer.cursor.dragType !== core_1.CursorDragType.Move)
|
|
109
|
+
return;
|
|
110
|
+
cancelAnimationFrame(frame);
|
|
111
|
+
frame = requestAnimationFrame(() => {
|
|
112
|
+
refreshSelectionBox((tick) => tick + 1);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
return () => {
|
|
116
|
+
cancelAnimationFrame(frame);
|
|
117
|
+
unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
|
|
118
|
+
};
|
|
119
|
+
}, [designer]);
|
|
83
120
|
if (cursor.status !== 'NORMAL' && viewportMoveHelper.touchNode)
|
|
84
121
|
return null;
|
|
85
122
|
return (react_1.default.createElement(react_1.Fragment, null, selection.selected.map((id) => {
|
|
@@ -88,7 +125,9 @@ exports.Selection = (0, reactive_react_1.observer)(() => {
|
|
|
88
125
|
return;
|
|
89
126
|
if (node.hidden)
|
|
90
127
|
return;
|
|
91
|
-
|
|
128
|
+
if (!node.allowSelect())
|
|
129
|
+
return;
|
|
130
|
+
return (react_1.default.createElement(exports.SelectionBox, { key: `${id}-${measureTick}`, node: node, showHelpers: selection.selected.length === 1 }));
|
|
92
131
|
})));
|
|
93
132
|
});
|
|
94
133
|
exports.Selection.displayName = 'Selection';
|
|
@@ -87,7 +87,7 @@ exports.Selector = (0, reactive_react_1.observer)(({ node }) => {
|
|
|
87
87
|
return react_1.default.createElement(IconWidget_1.IconWidget, { infer: "Component" });
|
|
88
88
|
};
|
|
89
89
|
const renderMenu = () => {
|
|
90
|
-
const parents = node.getParents();
|
|
90
|
+
const parents = node.getParents().filter((parent) => parent.allowSelect());
|
|
91
91
|
return (react_1.default.createElement("div", { className: prefix + '-menu', style: {
|
|
92
92
|
position: 'absolute',
|
|
93
93
|
top: '100%',
|
|
@@ -43,6 +43,7 @@ const Cover_1 = require("./Cover");
|
|
|
43
43
|
const DashedBox_1 = require("./DashedBox");
|
|
44
44
|
const SpaceBlock_1 = require("./SpaceBlock");
|
|
45
45
|
const SnapLine_1 = require("./SnapLine");
|
|
46
|
+
const NonInteractiveMark_1 = require("./NonInteractiveMark");
|
|
46
47
|
require("./styles.less");
|
|
47
48
|
const AuxToolWidget = () => {
|
|
48
49
|
const engine = (0, hooks_1.useDesigner)();
|
|
@@ -62,6 +63,7 @@ const AuxToolWidget = () => {
|
|
|
62
63
|
react_1.default.createElement(Insertion_1.Insertion, null),
|
|
63
64
|
react_1.default.createElement(SpaceBlock_1.SpaceBlock, null),
|
|
64
65
|
react_1.default.createElement(SnapLine_1.SnapLine, null),
|
|
66
|
+
react_1.default.createElement(NonInteractiveMark_1.NonInteractiveMark, null),
|
|
65
67
|
react_1.default.createElement(DashedBox_1.DashedBox, null),
|
|
66
68
|
react_1.default.createElement(Selection_1.Selection, null),
|
|
67
69
|
react_1.default.createElement(Cover_1.Cover, null),
|
|
@@ -174,6 +174,11 @@
|
|
|
174
174
|
|
|
175
175
|
.@{prefix-cls}-aux-insertion {
|
|
176
176
|
background-color: var(--dn-aux-insertion-color);
|
|
177
|
+
|
|
178
|
+
&.forbidden {
|
|
179
|
+
background-color: var(--dn-aux-insertion-forbidden-color, red);
|
|
180
|
+
box-shadow: 0 0 0 1px rgba(255, 0, 0, 0.18);
|
|
181
|
+
}
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
.@{prefix-cls}-aux-dashed-box {
|
|
@@ -184,6 +189,77 @@
|
|
|
184
189
|
}
|
|
185
190
|
}
|
|
186
191
|
|
|
192
|
+
.@{prefix-cls}-aux-non-interactive-mark {
|
|
193
|
+
border: 1px dashed var(--dn-aux-non-interactive-border-color, #7f93aa);
|
|
194
|
+
background: var(--dn-aux-non-interactive-bg-color, rgba(127, 147, 170, 0.04));
|
|
195
|
+
transition: border-color 0.12s ease, background-color 0.12s ease,
|
|
196
|
+
box-shadow 0.12s ease;
|
|
197
|
+
|
|
198
|
+
&.active {
|
|
199
|
+
border-color: var(--dn-aux-non-interactive-active-border-color, #3f5f7f);
|
|
200
|
+
background: var(
|
|
201
|
+
--dn-aux-non-interactive-active-bg-color,
|
|
202
|
+
rgba(63, 95, 127, 0.07)
|
|
203
|
+
);
|
|
204
|
+
box-shadow: 0 0 0 1px rgba(63, 95, 127, 0.12);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
&-lock {
|
|
208
|
+
position: absolute;
|
|
209
|
+
top: -1px;
|
|
210
|
+
right: -1px;
|
|
211
|
+
width: 16px;
|
|
212
|
+
height: 16px;
|
|
213
|
+
border-radius: 0 1px 0 6px;
|
|
214
|
+
background: var(--dn-aux-non-interactive-lock-bg-color, #5f7286);
|
|
215
|
+
box-shadow: 0 1px 3px rgba(31, 45, 61, 0.18);
|
|
216
|
+
|
|
217
|
+
&::before {
|
|
218
|
+
content: '';
|
|
219
|
+
position: absolute;
|
|
220
|
+
left: 5px;
|
|
221
|
+
top: 3px;
|
|
222
|
+
width: 6px;
|
|
223
|
+
height: 5px;
|
|
224
|
+
border: 1.5px solid #fff;
|
|
225
|
+
border-bottom: 0;
|
|
226
|
+
border-radius: 5px 5px 0 0;
|
|
227
|
+
box-sizing: border-box;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
&::after {
|
|
231
|
+
content: '';
|
|
232
|
+
position: absolute;
|
|
233
|
+
left: 4px;
|
|
234
|
+
top: 7px;
|
|
235
|
+
width: 8px;
|
|
236
|
+
height: 6px;
|
|
237
|
+
border-radius: 1px;
|
|
238
|
+
background: #fff;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
&.active &-lock {
|
|
243
|
+
background: var(--dn-aux-non-interactive-active-lock-bg-color, #334f6b);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
&-tip {
|
|
247
|
+
position: absolute;
|
|
248
|
+
right: -1px;
|
|
249
|
+
bottom: 100%;
|
|
250
|
+
margin-bottom: 4px;
|
|
251
|
+
padding: 2px 6px;
|
|
252
|
+
border-radius: 2px;
|
|
253
|
+
color: #fff;
|
|
254
|
+
background: var(--dn-aux-non-interactive-tip-bg-color, #334f6b);
|
|
255
|
+
box-shadow: 0 2px 8px rgba(31, 45, 61, 0.18);
|
|
256
|
+
font-size: 12px;
|
|
257
|
+
line-height: 18px;
|
|
258
|
+
white-space: nowrap;
|
|
259
|
+
user-select: none;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
187
263
|
.@{prefix-cls}-aux-selection-box {
|
|
188
264
|
border: 2px solid var(--dn-aux-selection-box-border-color);
|
|
189
265
|
position: relative;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formily-design/react",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "lib",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -35,12 +35,12 @@
|
|
|
35
35
|
"react": "18.x || 17.x"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@formily-design/core": "1.0.
|
|
39
|
-
"@formily-design/shared": "1.0.
|
|
38
|
+
"@formily-design/core": "1.0.12",
|
|
39
|
+
"@formily-design/shared": "1.0.12",
|
|
40
40
|
"dateformat": "^4.5.1"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public"
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "21f497829728c1205fcd2c3867088640ab2c04b7"
|
|
46
46
|
}
|