@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 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: 1;\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";
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
- var IGNORE_TARGET_SELECTOR = 'input, textarea, select, [contenteditable="true"], .ant-table-selection-column';
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: 1;\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";
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
- var IGNORE_TARGET_SELECTOR = 'input, textarea, select, [contenteditable="true"], .ant-table-selection-column';
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bit-sun/business-component",
3
- "version": "4.2.0-alpha.32-wyl",
3
+ "version": "4.2.0-alpha.34-wyl",
4
4
  "scripts": {
5
5
  "start": "dumi dev",
6
6
  "docs:build": "dumi build",
@@ -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
- // 框选高亮层:绝对定位在滚动容器内容坐标系里,随内容滚动;z-index 低于固定列,不遮挡它们
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: 1;
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"], .ant-table-selection-column';
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);