plain-design 1.0.0-beta.31 → 1.0.0-beta.33
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/plain-design.commonjs.min.js +18 -18
- package/dist/plain-design.min.css +11 -6
- package/dist/plain-design.min.js +18 -18
- package/dist/report.html +38 -38
- package/package.json +3 -3
- package/src/packages/components/$previewer/ImagePreviewerFixedContainer.tsx +107 -0
- package/src/packages/components/$previewer/image-previewer-fixed-container.scss +18 -0
- package/src/packages/components/$previewer/index.tsx +52 -0
- package/src/packages/components/Application/service/useApplicationService.tsx +2 -0
- package/src/packages/components/Carousel/carousel.scss +391 -0
- package/src/packages/components/Carousel/index.tsx +569 -22
- package/src/packages/components/CarouselItem/index.tsx +77 -0
- package/src/packages/components/ImagePreviewer/ImagePreviewer.tsx +572 -0
- package/src/packages/components/ImagePreviewer/ImagePreviewerButtonBar.tsx +140 -0
- package/src/packages/components/ImagePreviewer/ImagePreviewerCarouselImage.tsx +54 -0
- package/src/packages/components/ImagePreviewer/ImagePreviewerGallery.tsx +202 -0
- package/src/packages/components/ImagePreviewer/PreviewerLoading.tsx +26 -0
- package/src/packages/components/ImagePreviewer/image-previewer.scss +244 -0
- package/src/packages/components/ImagePreviewer/image-previewer.utils.tsx +135 -0
- package/src/packages/components/ImagePreviewer/index.tsx +5 -0
- package/src/packages/components/ImagePreviewer/previewer-loading.scss +52 -0
- package/src/packages/components/Input/useMultipleInput.tsx +2 -79
- package/src/packages/components/Scroll/index.tsx +6 -6
- package/src/packages/components/SortList/index.tsx +191 -0
- package/src/packages/components/SortList/sort-list.scss +11 -0
- package/src/packages/components/StackCard/index.tsx +260 -0
- package/src/packages/components/StackCard/stack-card.scss +28 -0
- package/src/packages/components/StackCardItem/index.tsx +23 -0
- package/src/packages/components/Table/standard/PlcOperation/PlcOperation.tsx +1 -1
- package/src/packages/components/Table/standard/PlcTree/RenderPlcTreeNode.tsx +2 -1
- package/src/packages/components/Table/table/body/row.tsx +1 -1
- package/src/packages/components/Table/table/use/useTableDraggier.row.tsx +1 -1
- package/src/packages/components/Table/table/utils/createTableHooks.ts +1 -1
- package/src/packages/components/ThemeEditor/index.tsx +25 -24
- package/src/packages/components/Tree/RenderTreeNode.tsx +2 -1
- package/src/packages/components/Tree/index.tsx +2 -1
- package/src/packages/components/VirtualList/index.tsx +12 -3
- package/src/packages/components/VirtualList/useVirtualList.tsx +129 -86
- package/src/packages/components/VirtualList/virtual-list.scss +31 -17
- package/src/packages/components/VirtualTable/index.tsx +1 -1
- package/src/packages/entry.tsx +5 -1
- package/src/packages/i18n/lang/en-us.ts +36 -0
- package/src/packages/i18n/lang/zh-cn.ts +36 -0
- package/src/packages/uses/useDragHorizontalScroll.ts +82 -0
- package/src/packages/utils/ComponentUtils.ts +10 -0
- package/src/packages/utils/buildCycleIndexList.ts +31 -0
- package/src/packages/utils/getDeviceInfo.ts +44 -44
- package/src/packages/utils/getRectAutoFormat.ts +9 -0
- package/src/packages/utils/notNull.ts +9 -0
- package/src/pages/index/app.scss +1 -1
- package/src/pages/index/components/normal/DemoCarousel.tsx +178 -73
- package/src/pages/index/components/normal/DemoKeepAlive.tsx +25 -25
- package/src/pages/index/components/normal/DemoSortList.tsx +70 -0
- package/src/pages/index/components/normal/DemoStackCard.tsx +356 -0
- package/src/pages/index/components/normal/DemoVirtualList.tsx +89 -3
- package/src/pages/index/components/service/DemoImagePreviewer.tsx +185 -0
- package/src/pages/index/home/AppHome.tsx +18 -3
- package/src/pages/index/home/menus.tsx +3 -1
- package/src/packages/components/CarouselGroup/carousel.scss +0 -143
- package/src/packages/components/CarouselGroup/index.tsx +0 -274
@@ -0,0 +1,260 @@
|
|
1
|
+
import {CSSProperties, designComponent, getComponentCls, iHTMLDivElement, isReact, mergeAttrs, onBeforeUnmount, onMounted, PropType, reactive, useClasses, useModel, useRefs} from "plain-design-composition";
|
2
|
+
import './stack-card.scss';
|
3
|
+
import {findReactElement} from "../../utils/findReactElement";
|
4
|
+
import StackCardItem from "../StackCardItem";
|
5
|
+
import {createEffects} from "plain-utils/utils/createEffects";
|
6
|
+
import {addElementListener} from "plain-utils/dom/addElementListener";
|
7
|
+
import {delay} from "plain-utils/utils/delay";
|
8
|
+
|
9
|
+
export const StackCard = designComponent({
|
10
|
+
name: 'stack-card',
|
11
|
+
props: {
|
12
|
+
modelValue: { type: [String, Number] }, // 双向绑定值,当前显示哪一个子节点
|
13
|
+
leftBufferCount: { type: Number }, // 左侧显示元素个数
|
14
|
+
rightBufferCount: { type: Number }, // 右侧显示元素个数
|
15
|
+
stackItemWidth: { type: Number, default: 24 }, // 每一张折叠卡片横向偏移距离
|
16
|
+
stackItemHeight: { type: Number, default: 12 }, //每一张折叠卡片纵向向偏移距离
|
17
|
+
scaleRate: { type: Number, default: 0.1 }, // 缩放比例
|
18
|
+
verticalOffset: { type: Boolean }, // 开启纵向偏移
|
19
|
+
verticalAlign: { type: String as PropType<'top' | 'center' | 'bottom'>, default: 'center' }, // 纵向对齐方式
|
20
|
+
},
|
21
|
+
emits: {
|
22
|
+
onUpdateModelValue: (val?: string | number) => true,
|
23
|
+
},
|
24
|
+
slots: ['default'],
|
25
|
+
setup({ props, slots, event: { emit } }) {
|
26
|
+
|
27
|
+
const { effects } = createEffects();
|
28
|
+
|
29
|
+
const { refs, onRef } = useRefs({ el: iHTMLDivElement, container: iHTMLDivElement });
|
30
|
+
|
31
|
+
const model = useModel(() => props.modelValue, emit.onUpdateModelValue, { onChange: async () => {await utils.resetData();} });
|
32
|
+
|
33
|
+
const classes = useClasses(() => [
|
34
|
+
getComponentCls('stack-card'),
|
35
|
+
{
|
36
|
+
'stack-card-touching': draggier.draggierState.touching
|
37
|
+
}
|
38
|
+
]);
|
39
|
+
|
40
|
+
const draggier = (() => {
|
41
|
+
|
42
|
+
const draggierState = reactive({ left: 0, touching: false, });
|
43
|
+
|
44
|
+
const touchstart = (e: TouchEvent | MouseEvent) => {
|
45
|
+
e.preventDefault();
|
46
|
+
e.stopPropagation();
|
47
|
+
|
48
|
+
let staticState = {
|
49
|
+
startLeft: draggierState.left,
|
50
|
+
startX: 'touches' in e ? e.touches[0].clientX : e.clientX,
|
51
|
+
};
|
52
|
+
const { effects: draggierEffects } = createEffects();
|
53
|
+
|
54
|
+
const touchmove = (e: TouchEvent | MouseEvent) => {
|
55
|
+
let durX = Math.ceil(('touches' in e ? e.touches[0].clientX : e.clientX) - staticState.startX);
|
56
|
+
if (!draggierState.touching) {
|
57
|
+
if (Math.abs(durX) > 10) {
|
58
|
+
draggierState.touching = true;
|
59
|
+
draggierEffects.push(() => {
|
60
|
+
draggierState.touching = false;
|
61
|
+
if (!!renderData) {
|
62
|
+
/**
|
63
|
+
* 设置滚动位置为最近的子节点
|
64
|
+
* @author 韦胜健
|
65
|
+
* @date 2024/1/4 21:12
|
66
|
+
*/
|
67
|
+
const { closestItem, itemsList, itemValList } = renderData;
|
68
|
+
draggierState.left = itemsList.find(i => i.index === closestItem.index)!.startLeft;
|
69
|
+
const newVal = itemValList[closestItem.index];
|
70
|
+
if (newVal != model.value) {model.value = newVal;}
|
71
|
+
}
|
72
|
+
});
|
73
|
+
}
|
74
|
+
}
|
75
|
+
if (!draggierState.touching) {return;}
|
76
|
+
/*实时设置滚动位置*/
|
77
|
+
durX = Math.ceil(durX / 3);
|
78
|
+
draggierState.left = -durX + staticState.startLeft;
|
79
|
+
};
|
80
|
+
|
81
|
+
draggierEffects.push(addElementListener(document.body, 'mousemove', touchmove));
|
82
|
+
draggierEffects.push(addElementListener(document.body, 'mouseup', draggierEffects.clear));
|
83
|
+
draggierEffects.push(addElementListener(document.body, 'touchmove', touchmove));
|
84
|
+
draggierEffects.push(addElementListener(document.body, 'touchend', draggierEffects.clear));
|
85
|
+
};
|
86
|
+
|
87
|
+
return { draggierState, touchstart };
|
88
|
+
})();
|
89
|
+
|
90
|
+
const utils = {
|
91
|
+
/**
|
92
|
+
* 重新计算当前渲染信息数据
|
93
|
+
* @author 韦胜健
|
94
|
+
* @date 2024/1/4 21:13
|
95
|
+
*/
|
96
|
+
resetData: async () => {
|
97
|
+
await delay();
|
98
|
+
const activeIndex = model.value == null ? -1 : renderData.itemValList.indexOf(model.value);
|
99
|
+
if (activeIndex === -1) {return;}
|
100
|
+
const newItem = renderData.itemsList.find(i => i.index === activeIndex);
|
101
|
+
if (!!newItem) {
|
102
|
+
draggier.draggierState.left = renderData.itemsList.find(i => i.index === activeIndex)!.startLeft;
|
103
|
+
}
|
104
|
+
},
|
105
|
+
};
|
106
|
+
|
107
|
+
onMounted(() => {
|
108
|
+
refs.el!.addEventListener('touchstart', draggier.touchstart);
|
109
|
+
refs.el!.addEventListener('mousedown', draggier.touchstart);
|
110
|
+
utils.resetData();
|
111
|
+
});
|
112
|
+
|
113
|
+
onBeforeUnmount(effects.clear);
|
114
|
+
|
115
|
+
let renderData = {
|
116
|
+
/*子节点信息,listLeft为子节点相对于o位置的偏移量*/
|
117
|
+
itemsList: [] as { index: number, startLeft: number, endLeft: number }[],
|
118
|
+
/*子节点的val数组*/
|
119
|
+
itemValList: [] as (string | number)[],
|
120
|
+
/*子节点转换为循环列表的信息,distance为循环列表中元素距离选中元素的偏移量*/
|
121
|
+
listData: [] as { index: number, startLeft: number, endLeft: number, distance: number }[],
|
122
|
+
/*最靠近选中元素的节点数据*/
|
123
|
+
closestItem: {} as { index: number, startLeft: number, endLeft: number },
|
124
|
+
};
|
125
|
+
|
126
|
+
return () => {
|
127
|
+
|
128
|
+
const content = slots.default() as any;
|
129
|
+
/*从内容解析出来StackCardItem的数量及其props*/
|
130
|
+
const items: any[] = !content ? [] : findReactElement(content, (i: any) => i.type?.name === StackCardItem.name) || [];
|
131
|
+
const itemValList = items.map((i, index) => i.props?.val == null ? index : i.props?.val);
|
132
|
+
const total = items.length;
|
133
|
+
|
134
|
+
let leftBufferCount = props.leftBufferCount == null ? Math.ceil(total / 2) : props.leftBufferCount;
|
135
|
+
let rightBufferCount = props.rightBufferCount == null ? Math.ceil(total / 2) : props.rightBufferCount;
|
136
|
+
|
137
|
+
const elStyles = {} as CSSProperties;
|
138
|
+
elStyles.paddingLeft = `${(leftBufferCount) * props.stackItemWidth}px`;
|
139
|
+
elStyles.paddingRight = `${(rightBufferCount - 1) * props.stackItemWidth}px`;
|
140
|
+
if (!!props.verticalOffset) {
|
141
|
+
elStyles.paddingBottom = `${Math.max(leftBufferCount, rightBufferCount - 1) * props.stackItemHeight}px`;
|
142
|
+
}
|
143
|
+
|
144
|
+
let itemStyles: CSSProperties[] = [];
|
145
|
+
|
146
|
+
/*实际中拖拽的left距离,与item的startLeft匹配,item的startLeft实际上是item的中心距离*/
|
147
|
+
let pointLeft = draggier.draggierState.left;
|
148
|
+
/*拖拽的left距离向右偏移半个stackItemWidth得到offsetPointLeft, 通过offsetPointLeft在item的startLeft到endLeft之间的位置找到closetItem*/
|
149
|
+
let offsetPointLeft = Math.floor(props.stackItemWidth / 2 + pointLeft);
|
150
|
+
/*计算每个item的startLeft以及endLeft*/
|
151
|
+
const itemsList: { index: number, startLeft: number, endLeft: number; }[] = itemValList.map((_, index) => ({ index, startLeft: index * props.stackItemWidth, endLeft: (index + 1) * props.stackItemWidth, }));
|
152
|
+
|
153
|
+
/*总长度*/
|
154
|
+
const maxEndLeft = itemsList[itemsList.length - 1]?.endLeft;
|
155
|
+
|
156
|
+
/*修正left,超出maxListLeft或者小于0时,循环计算left使其落在0到maxListLeft的范围*/
|
157
|
+
if (!!itemsList.length && !!maxEndLeft) {
|
158
|
+
while (offsetPointLeft > maxEndLeft) {
|
159
|
+
offsetPointLeft -= maxEndLeft;
|
160
|
+
pointLeft -= maxEndLeft;
|
161
|
+
}
|
162
|
+
while (offsetPointLeft < 0) {
|
163
|
+
offsetPointLeft += maxEndLeft;
|
164
|
+
pointLeft += maxEndLeft;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
/*找到最靠近的位置*/
|
169
|
+
const closestItem = itemsList.reduce((prev, item) => {
|
170
|
+
if (item.startLeft <= offsetPointLeft && item.endLeft >= offsetPointLeft) {
|
171
|
+
return { distance: Math.abs(item.startLeft - pointLeft), item };
|
172
|
+
} else {
|
173
|
+
return prev;
|
174
|
+
}
|
175
|
+
}, { distance: Infinity, item: null } as { distance: number, item: { index: number, startLeft: number, endLeft: number } | null }).item!;
|
176
|
+
|
177
|
+
/*循环列表前半部分*/
|
178
|
+
const leftItemsList = itemsList.slice(0, closestItem.index);
|
179
|
+
/*循环列表后半部分*/
|
180
|
+
const rightItemsList = itemsList.slice(closestItem.index);
|
181
|
+
|
182
|
+
/*根据左侧右侧预留的空位填补前后列表*/
|
183
|
+
while (leftItemsList.length - rightItemsList.length > 1) {rightItemsList.push(leftItemsList.shift()!);}
|
184
|
+
while (rightItemsList.length - leftItemsList.length > 1) {leftItemsList.unshift(rightItemsList.pop()!);}
|
185
|
+
while (leftItemsList.length > leftBufferCount) {
|
186
|
+
const shiftItem = leftItemsList.shift()!;
|
187
|
+
if (rightItemsList.length < rightBufferCount) {
|
188
|
+
rightItemsList.push(shiftItem);
|
189
|
+
}
|
190
|
+
}
|
191
|
+
while (rightItemsList.length > rightBufferCount) {
|
192
|
+
const popItem = rightItemsList.pop()!;
|
193
|
+
if (leftItemsList.length < leftBufferCount) {
|
194
|
+
leftItemsList.unshift(popItem);
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
/*此时后半部分的第一个元素就是选中的元素,索引就是前半部分列表的最后一个位置+1*/
|
199
|
+
const activeIndex = leftItemsList.length;
|
200
|
+
/*根据最靠近left的节点来计算当前的少量偏移*/
|
201
|
+
const offsetLeft = closestItem.startLeft - pointLeft;
|
202
|
+
/*计算循环列表中每个节点距离选中节点的偏移距离*/
|
203
|
+
const list = [...leftItemsList, ...rightItemsList].map((item, index) => ({
|
204
|
+
...item,
|
205
|
+
distance: (index - activeIndex) * props.stackItemWidth,
|
206
|
+
zIndex: 0,
|
207
|
+
}));
|
208
|
+
/*先排序,然后根据顺序设置zIndex,最靠近left的节点zIndex最大*/
|
209
|
+
list.sort((a, b) => Math.abs(a.distance) - Math.abs(b.distance)).forEach((i, index) => {
|
210
|
+
i.zIndex = total - index;
|
211
|
+
});
|
212
|
+
/*计算子节点样式*/
|
213
|
+
itemStyles = itemsList.map((_, index) => {
|
214
|
+
const item = list.find(i => i.index === index);
|
215
|
+
if (!item) {
|
216
|
+
/*不在前部分列表后部分列表的元素,可能是因为预留位置不足,这里不做显示*/
|
217
|
+
return {
|
218
|
+
opacity: 0,
|
219
|
+
transition: 'none'
|
220
|
+
};
|
221
|
+
}
|
222
|
+
/*元素的偏移距离*/
|
223
|
+
const left = item.distance + offsetLeft;
|
224
|
+
/*根据偏移距离实时计算缩放大小,越靠近left,越接近1*/
|
225
|
+
const scale = Math.max(0, 1 - Number((Math.abs(left) / props.stackItemWidth * props.scaleRate).toFixed(2)));
|
226
|
+
return {
|
227
|
+
transform: `translate3d(${left}px,${props.verticalOffset ? `${left / props.stackItemWidth * props.stackItemHeight}px` : 0},0) scale(${scale})`,
|
228
|
+
transformOrigin: `${left > 0 ? 'right' : 'left'} ${props.verticalAlign}`,
|
229
|
+
zIndex: item.zIndex,
|
230
|
+
// opacity: total - item.zIndex === 0 ? 1 : 0.75,
|
231
|
+
};
|
232
|
+
});
|
233
|
+
|
234
|
+
renderData = {
|
235
|
+
itemsList,
|
236
|
+
closestItem,
|
237
|
+
listData: list,
|
238
|
+
itemValList,
|
239
|
+
};
|
240
|
+
|
241
|
+
return (
|
242
|
+
<div className={classes.value} style={elStyles} ref={onRef.el}>
|
243
|
+
<div className="stack-card-container" ref={onRef.container}>
|
244
|
+
{items.map((Item: any, index: number) => {
|
245
|
+
const ItemComp = isReact ? Item.type : Item;
|
246
|
+
return (
|
247
|
+
<ItemComp
|
248
|
+
{...mergeAttrs({ style: itemStyles[index] || {} }, Item.props)}
|
249
|
+
key={index}
|
250
|
+
/>
|
251
|
+
);
|
252
|
+
})}
|
253
|
+
</div>
|
254
|
+
</div>
|
255
|
+
);
|
256
|
+
};
|
257
|
+
},
|
258
|
+
});
|
259
|
+
|
260
|
+
export default StackCard;
|
@@ -0,0 +1,28 @@
|
|
1
|
+
@include comp(stack-card) {
|
2
|
+
display: block;
|
3
|
+
box-sizing: border-box;
|
4
|
+
|
5
|
+
.stack-card-container {
|
6
|
+
position: relative;
|
7
|
+
@include comp(stack-card-item) {
|
8
|
+
transition: transform linear 100ms, opacity linear 300ms;
|
9
|
+
|
10
|
+
&:not(:first-child) {
|
11
|
+
position: absolute;
|
12
|
+
inset: 0;
|
13
|
+
}
|
14
|
+
&:first-child {
|
15
|
+
position: relative;
|
16
|
+
}
|
17
|
+
|
18
|
+
& > img {
|
19
|
+
width: 100%;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
&:not(.stack-card-touching) {
|
25
|
+
@include comp(stack-card-item) {
|
26
|
+
}
|
27
|
+
}
|
28
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import {designComponent, getComponentCls, useClasses} from "plain-design-composition";
|
2
|
+
|
3
|
+
export const StackCardItem = designComponent({
|
4
|
+
name: 'stack-card-item',
|
5
|
+
props: {
|
6
|
+
val: { type: [String, Number] },
|
7
|
+
},
|
8
|
+
slots: ['default'],
|
9
|
+
setup({ props, slots, event: { emit } }) {
|
10
|
+
|
11
|
+
const classes = useClasses(() => [
|
12
|
+
getComponentCls('stack-card-item')
|
13
|
+
]);
|
14
|
+
|
15
|
+
return () => (
|
16
|
+
<div className={classes.value}>
|
17
|
+
{slots.default()}
|
18
|
+
</div>
|
19
|
+
);
|
20
|
+
},
|
21
|
+
});
|
22
|
+
|
23
|
+
export default StackCardItem;
|
@@ -281,7 +281,7 @@ export const PlcOperation = designComponent({
|
|
281
281
|
* @author 韦胜健
|
282
282
|
* @date 2022.11.25 19:20
|
283
283
|
*/
|
284
|
-
effects.push(table.hooks.onVirtualPageIndexChange.use(({
|
284
|
+
effects.push(table.hooks.onVirtualPageIndexChange.use(({ startIndex }) => {state.virtualRowStart = startIndex;}));
|
285
285
|
|
286
286
|
onBeforeUnmount(() => effects.clear());
|
287
287
|
|
@@ -80,6 +80,7 @@ export const RenderPlcTreeNode = designComponent({
|
|
80
80
|
{props.treeCore.props.multiple && (
|
81
81
|
<div className={`tree-node-checker plc-tree-button`}>
|
82
82
|
<Checkbox
|
83
|
+
key={props.treeNode.id}
|
83
84
|
checkStatus={checkStatus.value}
|
84
85
|
disabled={!props.treeNode.isCheckAble()}
|
85
86
|
onClick={handler.onClickCheckbox}
|
@@ -89,7 +90,7 @@ export const RenderPlcTreeNode = designComponent({
|
|
89
90
|
{props.treeCore.props.draggable && (
|
90
91
|
<div
|
91
92
|
className={classnames(['tree-node-draggier', 'plc-tree-button', { 'tree-node-draggier-disable': !props.treeCore.utils.isAllowDraggable(props.treeNode) }])}
|
92
|
-
onMouseDown={handler.onMousedownDraggier.value}
|
93
|
+
onMouseDown={props.treeNode.empty ? undefined : handler.onMousedownDraggier.value}
|
93
94
|
>
|
94
95
|
<Icon icon="pi-menu"/>
|
95
96
|
</div>
|
@@ -34,7 +34,7 @@ export const PltRow = designComponent({
|
|
34
34
|
render: () => {
|
35
35
|
return props.table.hooks.onRenderRow.exec({
|
36
36
|
content: (
|
37
|
-
<tr className={classes.value} style={{ height: `${props.table.numberState.bodyRowHeight}px` }} data-vid={props.vid} {...handler}>
|
37
|
+
<tr className={classes.value} style={{ height: `${props.table.numberState.bodyRowHeight}px` }} data-vid={props.vid} data-idx={String(props.node.state.index == null ? "" : props.node.state.index)} {...handler}>
|
38
38
|
{(props.table.bodyPlcList.value?.map((plc) => <PltCell key={plc.plcKey} table={props.table} node={props.node} plc={plc}/>))}
|
39
39
|
</tr>
|
40
40
|
),
|
@@ -191,7 +191,7 @@ export function useTableDraggierRow(
|
|
191
191
|
|
192
192
|
const start = (e: iMouseEvent, node: iTableNode) => {
|
193
193
|
const { clientY } = !e ? { clientY: prevClientY } : ClientZoom.getClientPosition(e);
|
194
|
-
const rowEl = (Array.from(refs.el!.querySelectorAll(`.plt-row`)) as HTMLTableRowElement[]).find(i => i.dataset.
|
194
|
+
const rowEl = (Array.from(refs.el!.querySelectorAll(`.plt-row`)) as HTMLTableRowElement[]).find(i => i.dataset.idx == node.state.index.toString())!;
|
195
195
|
const rowRect = rowEl.getBoundingClientRect();
|
196
196
|
staticState = { startY: clientY, startTop: rowRect.top, node, rowEl, data: null, };
|
197
197
|
/*清理状态*/
|
@@ -19,7 +19,7 @@ export const createTableHooks = () => {
|
|
19
19
|
/*是否可以开启虚拟滚动*/
|
20
20
|
onEnableVirtual: createSyncHooks<(data: boolean) => void>(),
|
21
21
|
/*当虚拟滚动的pageIndex变化的时候触发动作*/
|
22
|
-
onVirtualPageIndexChange: createHooks<(data: { pageIndex: number,
|
22
|
+
onVirtualPageIndexChange: createHooks<(data: { pageIndex: number, startIndex: number }) => void>(),
|
23
23
|
/*点击行动作*/
|
24
24
|
onClickRow: createHooks<(data: { e: iMouseEvent, node: iTableNode }) => void>(),
|
25
25
|
/*双击行动作*/
|
@@ -8,6 +8,7 @@ import {SelectOption} from "../SelectOption";
|
|
8
8
|
import PageThemeUtils, {ThemePrimaryColors} from "../PageThemeUtils";
|
9
9
|
import ClientZoom from "../ClientZoom";
|
10
10
|
import {addWindowListener} from 'plain-utils/dom/addWindowListener';
|
11
|
+
import i18n from "../i18n";
|
11
12
|
|
12
13
|
export const ThemeEditor = designComponent({
|
13
14
|
name: 'theme-editor',
|
@@ -86,24 +87,24 @@ export const ThemeEditor = designComponent({
|
|
86
87
|
{state.isExpand && (
|
87
88
|
<div className="theme-editor-form">
|
88
89
|
<div>
|
89
|
-
<div
|
90
|
+
<div>{i18n('theme.inputMode').d('输入框类型')}</div>
|
90
91
|
<div>
|
91
|
-
<Select v-model={state.inputMode} onChange={handler.onInputModeChange} size="mini"
|
92
|
-
<SelectOption label=
|
93
|
-
<SelectOption label=
|
92
|
+
<Select v-model={state.inputMode} onChange={handler.onInputModeChange} size="mini" popperAttrs={publicPopperAttrs}>
|
93
|
+
<SelectOption label={i18n('theme.inputModeFlat').d('输入框:填充')} val="flat"/>
|
94
|
+
<SelectOption label={i18n('theme.inputModelStroke').d('输入框:描边')} val="stroke"/>
|
94
95
|
</Select>
|
95
96
|
</div>
|
96
97
|
</div>
|
97
98
|
|
98
99
|
<div>
|
99
|
-
<div
|
100
|
+
<div>{i18n('theme.primaryColor').d('主题颜色')}</div>
|
100
101
|
<div>
|
101
|
-
<Select v-model={state.primaryKey} onChange={handler.onPrimaryChange} size="mini"
|
102
|
+
<Select v-model={state.primaryKey} onChange={handler.onPrimaryChange} size="mini" popperAttrs={publicPopperAttrs}>
|
102
103
|
{Object.entries(ThemePrimaryColors).map(([key, value]) => (
|
103
|
-
<SelectOption label={value!.label} val={key} key={key}>
|
104
|
+
<SelectOption label={i18n('colorName.' + value!.label as any).d(value!.label)} val={key} key={key}>
|
104
105
|
<div className={getComponentCls('theme-editor-block-item')}>
|
105
106
|
{!!value!.primary && <span style={{ ...publicBlockStyles, background: value!.primary }}/>}
|
106
|
-
<span>{value!.label}</span>
|
107
|
+
<span>{i18n('colorName.' + value!.label as any).d(value!.label)}</span>
|
107
108
|
</div>
|
108
109
|
</SelectOption>
|
109
110
|
))}
|
@@ -112,40 +113,40 @@ export const ThemeEditor = designComponent({
|
|
112
113
|
</div>
|
113
114
|
|
114
115
|
<div>
|
115
|
-
<div
|
116
|
+
<div>{i18n('theme.size').d('大小尺寸')}</div>
|
116
117
|
<div>
|
117
|
-
<Select v-model={state.size} onChange={handler.onSizeChange} size="mini"
|
118
|
-
<SelectOption label=
|
119
|
-
<SelectOption label=
|
120
|
-
<SelectOption label=
|
121
|
-
<SelectOption label=
|
118
|
+
<Select v-model={state.size} onChange={handler.onSizeChange} size="mini" popperAttrs={publicPopperAttrs}>
|
119
|
+
<SelectOption label={i18n('theme.sizeLarge').d('大尺寸')} val="large"/>
|
120
|
+
<SelectOption label={i18n('theme.sizeNormal').d('中等尺寸')} val="normal"/>
|
121
|
+
<SelectOption label={i18n('theme.sizeSmall').d('小尺寸')} val="small"/>
|
122
|
+
<SelectOption label={i18n('theme.sizeMini').d('极小尺寸')} val="mini"/>
|
122
123
|
</Select>
|
123
124
|
</div>
|
124
125
|
</div>
|
125
126
|
|
126
127
|
<div>
|
127
|
-
<div
|
128
|
+
<div>{i18n('theme.darkMode').d('黑白主题')}</div>
|
128
129
|
<div>
|
129
|
-
<Select v-model={state.dark} onChange={handler.onDarkChange} size="mini"
|
130
|
-
<SelectOption label=
|
131
|
-
<SelectOption label=
|
130
|
+
<Select v-model={state.dark} onChange={handler.onDarkChange} size="mini" popperAttrs={publicPopperAttrs}>
|
131
|
+
<SelectOption label={i18n('theme.darkModeOn').d('黑色主题')} val="dark"/>
|
132
|
+
<SelectOption label={i18n('theme.darkModeOff').d('白色主题')} val="light"/>
|
132
133
|
</Select>
|
133
134
|
</div>
|
134
135
|
</div>
|
135
136
|
|
136
137
|
<div>
|
137
|
-
<div
|
138
|
+
<div>{i18n('theme.radiusMode').d('圆角类型')}</div>
|
138
139
|
<div>
|
139
|
-
<Select v-model={state.shape} onChange={handler.onShapeChange} size="mini"
|
140
|
-
<SelectOption label=
|
141
|
-
<SelectOption label=
|
142
|
-
<SelectOption label=
|
140
|
+
<Select v-model={state.shape} onChange={handler.onShapeChange} size="mini" popperAttrs={publicPopperAttrs}>
|
141
|
+
<SelectOption label={i18n('theme.radiusModeRound').d('圆角')} val="round"/>
|
142
|
+
<SelectOption label={i18n('theme.radiusModeNormal').d('小圆角')} val="square"/>
|
143
|
+
<SelectOption label={i18n('theme.radiusModeNone').d('无圆角')} val="none"/>
|
143
144
|
</Select>
|
144
145
|
</div>
|
145
146
|
</div>
|
146
147
|
|
147
148
|
<div>
|
148
|
-
<div
|
149
|
+
<div>{i18n('theme.scale').d('大小缩放')}</div>
|
149
150
|
<Select v-model={state.zoom} onChange={handler.onZoomChange} size="mini" placeholder="页面缩放" popperAttrs={publicPopperAttrs}>
|
150
151
|
<SelectOption label="0.6" val={0.6}/>
|
151
152
|
<SelectOption label="0.7" val={0.7}/>
|
@@ -131,7 +131,7 @@ export const RenderTreeNode = designComponent({
|
|
131
131
|
{tree.props.draggable && !tree.props.customDraggier && (
|
132
132
|
<div
|
133
133
|
className={classnames(['tree-node-draggier', { 'tree-node-draggier-disable': !tree.utils.isAllowDraggable(props.treeNode) }])}
|
134
|
-
onMouseDown={handler.onMousedownDraggier.value}
|
134
|
+
onMouseDown={props.treeNode.empty ? undefined : handler.onMousedownDraggier.value}
|
135
135
|
>
|
136
136
|
<Icon icon="pi-menu"/>
|
137
137
|
</div>
|
@@ -139,6 +139,7 @@ export const RenderTreeNode = designComponent({
|
|
139
139
|
{tree.props.multiple && (
|
140
140
|
<div className="tree-node-checker">
|
141
141
|
<Checkbox
|
142
|
+
key={props.treeNode.id}
|
142
143
|
checkStatus={checkStatus.value}
|
143
144
|
disabled={!props.treeNode.isCheckAble()}
|
144
145
|
onClick={handler.onClickCheckbox}
|
@@ -26,6 +26,7 @@ export const Tree = designComponent({
|
|
26
26
|
scroll: { type: Boolean }, // 是否使用滚动容器
|
27
27
|
innerAttrs: { type: Object as PropType<PlainObject> },// inner 节点属性类型
|
28
28
|
contentWrap: { type: Boolean }, // 节点内容是否换行显示,默认不换行
|
29
|
+
virtualRowType: { type: String as PropType<'virtualIndex' | 'realIndex'> }, // 虚拟滚动的行渲染类型,virtualIndex意思为使用虚拟的行索引作为key渲染行,好处是虚拟滚动时完全复用行组件实例;realIndex意味着虚拟滚动时新的行会重新初始化
|
29
30
|
...TreePropsOptions,
|
30
31
|
},
|
31
32
|
emits: {
|
@@ -94,7 +95,7 @@ export const Tree = designComponent({
|
|
94
95
|
{{
|
95
96
|
content: ({ data }: { data: { item: iTreeNode, index: number, vIndex: number, vid: string }[] }) => (
|
96
97
|
<div className="tree-node-list">
|
97
|
-
{data.map(({ item, vid },
|
98
|
+
{data.map(({ item, vid, index }, vIndex) => <RenderTreeNode key={(props.virtualRowType === 'realIndex') ? index : vIndex} treeNode={item} dataVid={vid} multiple={props.multiple}/>)}
|
98
99
|
</div>
|
99
100
|
)
|
100
101
|
}}
|
@@ -11,12 +11,14 @@ export const VirtualList = designComponent({
|
|
11
11
|
size: { type: Number, require: true, default: 40 }, // 每一行高度
|
12
12
|
dynamicSize: { type: Boolean }, // 标识列表中的每一行高度不是固定的,但是还是需要提供 size 属性,而且size属性不能与每一行的高度差距太多;
|
13
13
|
disabled: { type: Boolean }, // 禁用虚拟滚动
|
14
|
-
|
14
|
+
horizontal: { type: Boolean }, // 启用横向虚拟滚动
|
15
|
+
width: { type: [String, Number] }, // 纵向虚拟滚动需要横向滚动时,需要指定内容宽度
|
16
|
+
height: { type: [String, Number] }, // 横向虚拟滚动需要纵向滚动时,需要指定内容高度
|
15
17
|
},
|
16
18
|
emits: {
|
17
19
|
onScroll: (e: Event) => true,
|
18
20
|
onRefScroll: (scroll: typeof Scroll.use.class | null) => true,
|
19
|
-
onPageIndexChange: (data: { pageIndex: number,
|
21
|
+
onPageIndexChange: (data: { pageIndex: number, startIndex: number, endIndex: number }) => true,
|
20
22
|
},
|
21
23
|
scopeSlots: {
|
22
24
|
default: (scope: { item: any, index: number, vid: string, vIndex: number }) => {},
|
@@ -43,7 +45,14 @@ export const VirtualList = designComponent({
|
|
43
45
|
render: () => {
|
44
46
|
const { list } = virtual.offsetData.value;
|
45
47
|
return (
|
46
|
-
<Scroll
|
48
|
+
<Scroll
|
49
|
+
scrollX={!!props.width || props.horizontal}
|
50
|
+
scrollY={!!props.height || !props.horizontal}
|
51
|
+
onScroll={virtual.handler.onScroll}
|
52
|
+
ref={onRefScroll as any}
|
53
|
+
className={virtual.classes.value}
|
54
|
+
disableTransitionWhenScroll
|
55
|
+
>
|
47
56
|
<div className="virtual-list-strut" style={virtual.strutStyles.value}>
|
48
57
|
<div className="virtual-list-content" style={virtual.contentStyles.value} ref={onRef.content}>
|
49
58
|
{scopeSlots.content.isExist() ?
|