@bit-sun/business-component 4.2.0-alpha.32-wyl → 4.2.0-alpha.34-wyl
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/dist/index.esm.js +27 -3
- package/dist/index.js +27 -3
- package/package.json +1 -1
- package/src/components/Business/BsSulaQueryTable/__tests__/useRangeCopy.test.tsx +88 -0
- package/src/components/Business/BsSulaQueryTable/rangeCopy.less +5 -2
- package/src/components/Business/BsSulaQueryTable/useRangeCopy.tsx +29 -2
package/dist/index.esm.js
CHANGED
|
@@ -20049,12 +20049,14 @@ var resolveExcludeCols = function resolveExcludeCols(tbody, titles) {
|
|
|
20049
20049
|
return excludeCols;
|
|
20050
20050
|
};
|
|
20051
20051
|
|
|
20052
|
-
var css_248z$k = ".bs-range-copy tbody.ant-table-tbody > tr.ant-table-row > td.ant-table-cell:not(.ant-table-cell-fix-right) {\n cursor: cell;\n}\n.bs-range-copy .ant-table-body {\n position: relative;\n}\n.bs-range-copy__overlay {\n position: absolute;\n z-index:
|
|
20052
|
+
var css_248z$k = ".bs-range-copy tbody.ant-table-tbody > tr.ant-table-row > td.ant-table-cell:not(.ant-table-cell-fix-right) {\n cursor: cell;\n}\n.bs-range-copy .ant-table-body {\n position: relative;\n}\n.bs-range-copy__overlay {\n position: absolute;\n z-index: 5;\n display: none;\n box-sizing: border-box;\n pointer-events: none;\n background: rgba(24, 144, 255, 0.12);\n border: 1px solid rgba(24, 144, 255, 0.55);\n}\n";
|
|
20053
20053
|
styleInject(css_248z$k);
|
|
20054
20054
|
|
|
20055
20055
|
var CELL_SELECTOR = 'td.ant-table-cell';
|
|
20056
|
-
//
|
|
20057
|
-
|
|
20056
|
+
// 这些目标上不启动框选:真正的可编辑控件(勾选框本身是 input,点击仍是原生行为)。
|
|
20057
|
+
// 注意不要把整个 .ant-table-selection-column 排除:bssula 会把勾选列强制 fixed=true,
|
|
20058
|
+
// 它是最左边的固定列,整列不可起手就等于「固定列无法框选」。
|
|
20059
|
+
var IGNORE_TARGET_SELECTOR = 'input, textarea, select, [contenteditable="true"]';
|
|
20058
20060
|
var DEFAULT_EXCLUDE_TITLES = ['操作'];
|
|
20059
20061
|
// 指针进入容器边缘这个带宽内开始自动滚动,最多 24px/帧
|
|
20060
20062
|
var EDGE_BAND = 36;
|
|
@@ -20112,6 +20114,23 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20112
20114
|
var stepY = 0;
|
|
20113
20115
|
var range = null;
|
|
20114
20116
|
var anchorState = null;
|
|
20117
|
+
// 固定列(position: sticky)做角点时,它的"内容坐标"会随 scrollLeft 变化:
|
|
20118
|
+
// 高亮层虽然随内容滚动,但这种角点必须在容器滚动时重算,否则会与固定列脱开。
|
|
20119
|
+
// 只挂在表格自己的滚动容器上,且仅在存在选区时重绘,空闲期零开销。
|
|
20120
|
+
var scrollAnchor = null;
|
|
20121
|
+
var handleAnchorScroll = function handleAnchorScroll() {
|
|
20122
|
+
if (range) schedulePaint();
|
|
20123
|
+
};
|
|
20124
|
+
var bindAnchorScroll = function bindAnchorScroll(anchor) {
|
|
20125
|
+
if (scrollAnchor === anchor) return;
|
|
20126
|
+
if (scrollAnchor) {
|
|
20127
|
+
scrollAnchor.removeEventListener('scroll', handleAnchorScroll);
|
|
20128
|
+
}
|
|
20129
|
+
scrollAnchor = anchor;
|
|
20130
|
+
scrollAnchor.addEventListener('scroll', handleAnchorScroll, {
|
|
20131
|
+
passive: true
|
|
20132
|
+
});
|
|
20133
|
+
};
|
|
20115
20134
|
var hideOverlay = function hideOverlay() {
|
|
20116
20135
|
overlay.style.display = 'none';
|
|
20117
20136
|
};
|
|
@@ -20316,6 +20335,7 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20316
20335
|
colEnd: cell.cellIndex,
|
|
20317
20336
|
excludeCols: base.excludeCols
|
|
20318
20337
|
};
|
|
20338
|
+
bindAnchorScroll(anchorEl);
|
|
20319
20339
|
schedulePaint();
|
|
20320
20340
|
if ((_optionsRef$current$a = (_optionsRef$current = optionsRef.current) === null || _optionsRef$current === void 0 ? void 0 : _optionsRef$current.autoCopy) !== null && _optionsRef$current$a !== void 0 ? _optionsRef$current$a : true) copyRange();
|
|
20321
20341
|
return;
|
|
@@ -20358,6 +20378,7 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20358
20378
|
colEnd: cell.cellIndex,
|
|
20359
20379
|
excludeCols: base.excludeCols
|
|
20360
20380
|
};
|
|
20381
|
+
bindAnchorScroll(base.anchor);
|
|
20361
20382
|
} else {
|
|
20362
20383
|
applyCell(cell);
|
|
20363
20384
|
}
|
|
@@ -20430,6 +20451,9 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20430
20451
|
container.removeEventListener('mousedown', handleMouseDown);
|
|
20431
20452
|
container.removeEventListener('mousemove', handleMouseMove);
|
|
20432
20453
|
container.removeEventListener('dragstart', handleDragStart);
|
|
20454
|
+
if (scrollAnchor) {
|
|
20455
|
+
scrollAnchor.removeEventListener('scroll', handleAnchorScroll);
|
|
20456
|
+
}
|
|
20433
20457
|
container.removeEventListener('click', handleClickCapture, true);
|
|
20434
20458
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
20435
20459
|
document.removeEventListener('copy', handleCopy);
|
package/dist/index.js
CHANGED
|
@@ -20072,12 +20072,14 @@ var resolveExcludeCols = function resolveExcludeCols(tbody, titles) {
|
|
|
20072
20072
|
return excludeCols;
|
|
20073
20073
|
};
|
|
20074
20074
|
|
|
20075
|
-
var css_248z$k = ".bs-range-copy tbody.ant-table-tbody > tr.ant-table-row > td.ant-table-cell:not(.ant-table-cell-fix-right) {\n cursor: cell;\n}\n.bs-range-copy .ant-table-body {\n position: relative;\n}\n.bs-range-copy__overlay {\n position: absolute;\n z-index:
|
|
20075
|
+
var css_248z$k = ".bs-range-copy tbody.ant-table-tbody > tr.ant-table-row > td.ant-table-cell:not(.ant-table-cell-fix-right) {\n cursor: cell;\n}\n.bs-range-copy .ant-table-body {\n position: relative;\n}\n.bs-range-copy__overlay {\n position: absolute;\n z-index: 5;\n display: none;\n box-sizing: border-box;\n pointer-events: none;\n background: rgba(24, 144, 255, 0.12);\n border: 1px solid rgba(24, 144, 255, 0.55);\n}\n";
|
|
20076
20076
|
styleInject(css_248z$k);
|
|
20077
20077
|
|
|
20078
20078
|
var CELL_SELECTOR = 'td.ant-table-cell';
|
|
20079
|
-
//
|
|
20080
|
-
|
|
20079
|
+
// 这些目标上不启动框选:真正的可编辑控件(勾选框本身是 input,点击仍是原生行为)。
|
|
20080
|
+
// 注意不要把整个 .ant-table-selection-column 排除:bssula 会把勾选列强制 fixed=true,
|
|
20081
|
+
// 它是最左边的固定列,整列不可起手就等于「固定列无法框选」。
|
|
20082
|
+
var IGNORE_TARGET_SELECTOR = 'input, textarea, select, [contenteditable="true"]';
|
|
20081
20083
|
var DEFAULT_EXCLUDE_TITLES = ['操作'];
|
|
20082
20084
|
// 指针进入容器边缘这个带宽内开始自动滚动,最多 24px/帧
|
|
20083
20085
|
var EDGE_BAND = 36;
|
|
@@ -20135,6 +20137,23 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20135
20137
|
var stepY = 0;
|
|
20136
20138
|
var range = null;
|
|
20137
20139
|
var anchorState = null;
|
|
20140
|
+
// 固定列(position: sticky)做角点时,它的"内容坐标"会随 scrollLeft 变化:
|
|
20141
|
+
// 高亮层虽然随内容滚动,但这种角点必须在容器滚动时重算,否则会与固定列脱开。
|
|
20142
|
+
// 只挂在表格自己的滚动容器上,且仅在存在选区时重绘,空闲期零开销。
|
|
20143
|
+
var scrollAnchor = null;
|
|
20144
|
+
var handleAnchorScroll = function handleAnchorScroll() {
|
|
20145
|
+
if (range) schedulePaint();
|
|
20146
|
+
};
|
|
20147
|
+
var bindAnchorScroll = function bindAnchorScroll(anchor) {
|
|
20148
|
+
if (scrollAnchor === anchor) return;
|
|
20149
|
+
if (scrollAnchor) {
|
|
20150
|
+
scrollAnchor.removeEventListener('scroll', handleAnchorScroll);
|
|
20151
|
+
}
|
|
20152
|
+
scrollAnchor = anchor;
|
|
20153
|
+
scrollAnchor.addEventListener('scroll', handleAnchorScroll, {
|
|
20154
|
+
passive: true
|
|
20155
|
+
});
|
|
20156
|
+
};
|
|
20138
20157
|
var hideOverlay = function hideOverlay() {
|
|
20139
20158
|
overlay.style.display = 'none';
|
|
20140
20159
|
};
|
|
@@ -20339,6 +20358,7 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20339
20358
|
colEnd: cell.cellIndex,
|
|
20340
20359
|
excludeCols: base.excludeCols
|
|
20341
20360
|
};
|
|
20361
|
+
bindAnchorScroll(anchorEl);
|
|
20342
20362
|
schedulePaint();
|
|
20343
20363
|
if ((_optionsRef$current$a = (_optionsRef$current = optionsRef.current) === null || _optionsRef$current === void 0 ? void 0 : _optionsRef$current.autoCopy) !== null && _optionsRef$current$a !== void 0 ? _optionsRef$current$a : true) copyRange();
|
|
20344
20364
|
return;
|
|
@@ -20381,6 +20401,7 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20381
20401
|
colEnd: cell.cellIndex,
|
|
20382
20402
|
excludeCols: base.excludeCols
|
|
20383
20403
|
};
|
|
20404
|
+
bindAnchorScroll(base.anchor);
|
|
20384
20405
|
} else {
|
|
20385
20406
|
applyCell(cell);
|
|
20386
20407
|
}
|
|
@@ -20453,6 +20474,9 @@ var useRangeCopy = function useRangeCopy(options) {
|
|
|
20453
20474
|
container.removeEventListener('mousedown', handleMouseDown);
|
|
20454
20475
|
container.removeEventListener('mousemove', handleMouseMove);
|
|
20455
20476
|
container.removeEventListener('dragstart', handleDragStart);
|
|
20477
|
+
if (scrollAnchor) {
|
|
20478
|
+
scrollAnchor.removeEventListener('scroll', handleAnchorScroll);
|
|
20479
|
+
}
|
|
20456
20480
|
container.removeEventListener('click', handleClickCapture, true);
|
|
20457
20481
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
20458
20482
|
document.removeEventListener('copy', handleCopy);
|
package/package.json
CHANGED
|
@@ -172,6 +172,94 @@ if (!env) {
|
|
|
172
172
|
expect(writes[0]).toBe('r0c1\tr0c2\r\nr1c1\tr1c2\r\nr2c1\tr2c2');
|
|
173
173
|
});
|
|
174
174
|
|
|
175
|
+
it('从勾选列(bssula 强制 fixed=true 的最左固定列)起手也能框选,且单击仍原生', async () => {
|
|
176
|
+
mount();
|
|
177
|
+
let rowClicks = 0;
|
|
178
|
+
host
|
|
179
|
+
.querySelectorAll('tr.ant-table-row')[1]
|
|
180
|
+
.addEventListener('click', () => {
|
|
181
|
+
rowClicks += 1;
|
|
182
|
+
});
|
|
183
|
+
fire(cellAt(0, 0), 'mousedown');
|
|
184
|
+
fire(cellAt(1, 2), 'mousemove');
|
|
185
|
+
fire(document.body, 'mouseup');
|
|
186
|
+
await flush();
|
|
187
|
+
expect(writes[0]).toBe('r0c1\tr0c2\r\nr1c1\tr1c2');
|
|
188
|
+
expect(rowClicks).toBe(0);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('勾选列上的纯单击保持原生(不建立选区、不复制)', async () => {
|
|
192
|
+
mount();
|
|
193
|
+
let rowClicks = 0;
|
|
194
|
+
host
|
|
195
|
+
.querySelectorAll('tr.ant-table-row')[0]
|
|
196
|
+
.addEventListener('click', () => {
|
|
197
|
+
rowClicks += 1;
|
|
198
|
+
});
|
|
199
|
+
fire(cellAt(0, 0), 'mousedown');
|
|
200
|
+
fire(cellAt(0, 0), 'mouseup');
|
|
201
|
+
fire(cellAt(0, 0), 'click');
|
|
202
|
+
await flush();
|
|
203
|
+
expect(rowClicks).toBe(1);
|
|
204
|
+
expect(writes).toEqual([]);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('固定列角点:横向滚动后高亮重算并跟随', async () => {
|
|
208
|
+
mount();
|
|
209
|
+
const anchor = host.querySelector('.ant-table-body') as HTMLElement;
|
|
210
|
+
let scrollLeftValue = 50;
|
|
211
|
+
Object.defineProperty(anchor, 'scrollLeft', {
|
|
212
|
+
configurable: true,
|
|
213
|
+
get: () => scrollLeftValue,
|
|
214
|
+
set: (v: number) => {
|
|
215
|
+
scrollLeftValue = v;
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
anchor.getBoundingClientRect = () =>
|
|
219
|
+
({
|
|
220
|
+
left: 0,
|
|
221
|
+
top: 0,
|
|
222
|
+
right: 500,
|
|
223
|
+
bottom: 300,
|
|
224
|
+
width: 500,
|
|
225
|
+
height: 300,
|
|
226
|
+
} as DOMRect);
|
|
227
|
+
const stickyCell = cellAt(1, 1);
|
|
228
|
+
stickyCell.getBoundingClientRect = () =>
|
|
229
|
+
({
|
|
230
|
+
left: 0,
|
|
231
|
+
top: 0,
|
|
232
|
+
right: 100,
|
|
233
|
+
bottom: 20,
|
|
234
|
+
width: 100,
|
|
235
|
+
height: 20,
|
|
236
|
+
} as DOMRect);
|
|
237
|
+
const normalCell = cellAt(1, 2);
|
|
238
|
+
normalCell.getBoundingClientRect = () =>
|
|
239
|
+
({
|
|
240
|
+
left: 200 - scrollLeftValue,
|
|
241
|
+
top: 0,
|
|
242
|
+
right: 300 - scrollLeftValue,
|
|
243
|
+
bottom: 20,
|
|
244
|
+
width: 100,
|
|
245
|
+
height: 20,
|
|
246
|
+
} as DOMRect);
|
|
247
|
+
|
|
248
|
+
fire(cellAt(0, 1), 'mousedown');
|
|
249
|
+
fire(stickyCell, 'mousemove');
|
|
250
|
+
fire(normalCell, 'mousemove');
|
|
251
|
+
await flush();
|
|
252
|
+
const overlay = document.querySelector(
|
|
253
|
+
'.bs-range-copy__overlay',
|
|
254
|
+
) as HTMLElement;
|
|
255
|
+
expect(overlay.style.left).toBe('50px');
|
|
256
|
+
|
|
257
|
+
scrollLeftValue = 100;
|
|
258
|
+
anchor.dispatchEvent(new Event('scroll'));
|
|
259
|
+
await flush();
|
|
260
|
+
expect(overlay.style.left).toBe('100px');
|
|
261
|
+
});
|
|
262
|
+
|
|
175
263
|
it('容器外有非折叠选区时,Ctrl+C 不被劫持', async () => {
|
|
176
264
|
mount();
|
|
177
265
|
fire(cellAt(0, 1), 'mousedown');
|
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
//
|
|
16
|
+
// 框选高亮层:绝对定位在滚动容器内容坐标系里,随内容滚动。
|
|
17
|
+
// z-index 必须高于 antd 的固定列:.ant-table-cell-fix-left/right 是 position:sticky + z-index:2 + background:#fff
|
|
18
|
+
// (不透明白底),低于它就会"固定列那一段没有高亮"。表格内部最高的就是固定列的 2,取 5 足够,
|
|
19
|
+
// 仍远低于 antd 弹层/弹窗(1000+)。
|
|
17
20
|
.bs-range-copy__overlay {
|
|
18
21
|
position: absolute;
|
|
19
|
-
z-index:
|
|
22
|
+
z-index: 5;
|
|
20
23
|
display: none;
|
|
21
24
|
box-sizing: border-box;
|
|
22
25
|
pointer-events: none;
|
|
@@ -10,9 +10,11 @@ import {
|
|
|
10
10
|
import './rangeCopy.less';
|
|
11
11
|
|
|
12
12
|
const CELL_SELECTOR = 'td.ant-table-cell';
|
|
13
|
-
//
|
|
13
|
+
// 这些目标上不启动框选:真正的可编辑控件(勾选框本身是 input,点击仍是原生行为)。
|
|
14
|
+
// 注意不要把整个 .ant-table-selection-column 排除:bssula 会把勾选列强制 fixed=true,
|
|
15
|
+
// 它是最左边的固定列,整列不可起手就等于「固定列无法框选」。
|
|
14
16
|
const IGNORE_TARGET_SELECTOR =
|
|
15
|
-
'input, textarea, select, [contenteditable="true"]
|
|
17
|
+
'input, textarea, select, [contenteditable="true"]';
|
|
16
18
|
const DEFAULT_EXCLUDE_TITLES = ['操作'];
|
|
17
19
|
// 指针进入容器边缘这个带宽内开始自动滚动,最多 24px/帧
|
|
18
20
|
const EDGE_BAND = 36;
|
|
@@ -127,6 +129,26 @@ export const useRangeCopy = (options?: UseRangeCopyOptions) => {
|
|
|
127
129
|
let range: RangeState | null = null;
|
|
128
130
|
let anchorState: AnchorState | null = null;
|
|
129
131
|
|
|
132
|
+
// 固定列(position: sticky)做角点时,它的"内容坐标"会随 scrollLeft 变化:
|
|
133
|
+
// 高亮层虽然随内容滚动,但这种角点必须在容器滚动时重算,否则会与固定列脱开。
|
|
134
|
+
// 只挂在表格自己的滚动容器上,且仅在存在选区时重绘,空闲期零开销。
|
|
135
|
+
let scrollAnchor: HTMLElement | null = null;
|
|
136
|
+
|
|
137
|
+
const handleAnchorScroll = () => {
|
|
138
|
+
if (range) schedulePaint();
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const bindAnchorScroll = (anchor: HTMLElement) => {
|
|
142
|
+
if (scrollAnchor === anchor) return;
|
|
143
|
+
if (scrollAnchor) {
|
|
144
|
+
scrollAnchor.removeEventListener('scroll', handleAnchorScroll);
|
|
145
|
+
}
|
|
146
|
+
scrollAnchor = anchor;
|
|
147
|
+
scrollAnchor.addEventListener('scroll', handleAnchorScroll, {
|
|
148
|
+
passive: true,
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
|
|
130
152
|
const hideOverlay = () => {
|
|
131
153
|
overlay.style.display = 'none';
|
|
132
154
|
};
|
|
@@ -376,6 +398,7 @@ export const useRangeCopy = (options?: UseRangeCopyOptions) => {
|
|
|
376
398
|
colEnd: cell.cellIndex,
|
|
377
399
|
excludeCols: base.excludeCols,
|
|
378
400
|
};
|
|
401
|
+
bindAnchorScroll(anchorEl);
|
|
379
402
|
schedulePaint();
|
|
380
403
|
if (optionsRef.current?.autoCopy ?? true) copyRange();
|
|
381
404
|
return;
|
|
@@ -424,6 +447,7 @@ export const useRangeCopy = (options?: UseRangeCopyOptions) => {
|
|
|
424
447
|
colEnd: cell.cellIndex,
|
|
425
448
|
excludeCols: base.excludeCols,
|
|
426
449
|
};
|
|
450
|
+
bindAnchorScroll(base.anchor);
|
|
427
451
|
} else {
|
|
428
452
|
applyCell(cell);
|
|
429
453
|
}
|
|
@@ -507,6 +531,9 @@ export const useRangeCopy = (options?: UseRangeCopyOptions) => {
|
|
|
507
531
|
container.removeEventListener('mousedown', handleMouseDown);
|
|
508
532
|
container.removeEventListener('mousemove', handleMouseMove);
|
|
509
533
|
container.removeEventListener('dragstart', handleDragStart);
|
|
534
|
+
if (scrollAnchor) {
|
|
535
|
+
scrollAnchor.removeEventListener('scroll', handleAnchorScroll);
|
|
536
|
+
}
|
|
510
537
|
container.removeEventListener('click', handleClickCapture, true);
|
|
511
538
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
512
539
|
document.removeEventListener('copy', handleCopy);
|