@nokecy/qc-ui 1.1.52 → 1.1.53
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/cjs/array-table/hooks.d.ts +11 -4
- package/dist/cjs/array-table/hooks.js +54 -8
- package/dist/cjs/array-table/index.js +6 -17
- package/dist/cjs/array-table/preview.js +3 -1
- package/dist/cjs/array-table/theme.d.ts +16 -0
- package/dist/cjs/array-table/theme.js +50 -0
- package/dist/esm/array-table/hooks.d.ts +11 -4
- package/dist/esm/array-table/hooks.js +53 -7
- package/dist/esm/array-table/index.js +6 -17
- package/dist/esm/array-table/preview.js +3 -1
- package/dist/esm/array-table/theme.d.ts +16 -0
- package/dist/esm/array-table/theme.js +44 -0
- package/dist/umd/qc-ui.min.js +1 -1
- package/package.json +1 -1
|
@@ -23,12 +23,19 @@ export declare const useRowDrag: (field: ArrayField) => {
|
|
|
23
23
|
handleRowDragMove: (event: any) => void;
|
|
24
24
|
};
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* 这个按键该不该交给单元格里的输入框自己处理(浏览器原生行为),而不是当成表格的快捷键/单元格导航。
|
|
27
27
|
*
|
|
28
|
-
* AG-Grid 把 Ctrl+A
|
|
29
|
-
*
|
|
28
|
+
* AG-Grid 把 Ctrl+A 当成「选中所有单元格」、Home/End 当成「跳到行首/行尾单元格」并 preventDefault;
|
|
29
|
+
* 我们的 handleCellKeyDown 又把方向键一律当成「跳到相邻单元格」——输入框里全选、用方向键移动光标、
|
|
30
|
+
* Shift+方向键扩选文字就全都做不了。规则:
|
|
31
|
+
* - Ctrl/Cmd+A、Home/End、带 Shift/Ctrl/Alt/Cmd 的方向键、输入法组字期间的按键 -> 输入框自己处理;
|
|
32
|
+
* - 左右方向键:光标还能动就移动光标(有选区时先收起选区),已经在最左/最右再按才跳到相邻单元格;
|
|
33
|
+
* - 上下方向键:单行输入框没有纵向光标,照旧在行间导航;多行文本域在首行/末行才导航;
|
|
34
|
+
* - 焦点不在输入框里(在单元格本身)、只读输入框(如下拉选择)、不支持光标的输入框:照旧导航。
|
|
30
35
|
* 复制/粘贴/剪切/撤销 AG-Grid 本来就没拦,不必处理。@author nokecy
|
|
31
36
|
*/
|
|
32
|
-
export declare const
|
|
37
|
+
export declare const isNativeInputKey: (event: KeyboardEvent) => boolean;
|
|
38
|
+
/** AG-Grid 的 suppressKeyboardEvent:让 AG-Grid 不再拦截输入框自己处理的按键,并记下这次按键的判定 */
|
|
39
|
+
export declare const suppressNativeInputKeys: ({ event }: {
|
|
33
40
|
event: KeyboardEvent;
|
|
34
41
|
}) => boolean;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.useRowDrag = exports.useKeyboardNavigation = exports.useCellFocus = exports.
|
|
6
|
+
exports.useRowDrag = exports.useKeyboardNavigation = exports.useCellFocus = exports.suppressNativeInputKeys = exports.isNativeInputKey = void 0;
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
// setSelectionRange 仅 textarea 与 text/search/url/tel/password 类型 input 支持;
|
|
9
9
|
// checkbox/number/date 等调用会抛 InvalidStateError,故用白名单守卫。@author nokecy
|
|
@@ -17,6 +17,12 @@ var supportsSelectionRange = function supportsSelectionRange(el) {
|
|
|
17
17
|
*/
|
|
18
18
|
var useCellFocus = exports.useCellFocus = function useCellFocus() {
|
|
19
19
|
var focusInputInCell = (0, _react.useCallback)(function (cell) {
|
|
20
|
+
// 焦点已经在本格的输入框里:用户直接点进去定位光标、双击选词、按住拖选,这些留下的光标/选区都是他的。
|
|
21
|
+
// 不能再 focus() 并把光标挪到末尾——那会把这些操作在 10ms 后全部抹掉。
|
|
22
|
+
// 首次点开、键盘导航进来时焦点还不在本格输入框里,不受影响。@author nokecy
|
|
23
|
+
var active = document.activeElement;
|
|
24
|
+
if (active && cell.contains(active) && active.matches('input, textarea')) return;
|
|
25
|
+
|
|
20
26
|
// 首先查找Editable包装的元素
|
|
21
27
|
var editableElement = cell.querySelector('.ant-formily-editable');
|
|
22
28
|
if (editableElement) {
|
|
@@ -101,11 +107,15 @@ var useCellFocus = exports.useCellFocus = function useCellFocus() {
|
|
|
101
107
|
*/
|
|
102
108
|
var useKeyboardNavigation = exports.useKeyboardNavigation = function useKeyboardNavigation(ref, dataSource, focusInputInCell, activateCell) {
|
|
103
109
|
var handleCellKeyDown = (0, _react.useCallback)(function (event) {
|
|
110
|
+
var _nativeKeyDecisions$g;
|
|
104
111
|
var keyEvent = event.event,
|
|
105
112
|
node = event.node,
|
|
106
113
|
colDef = event.colDef,
|
|
107
114
|
api = event.api;
|
|
108
115
|
if (!keyEvent) return;
|
|
116
|
+
// 输入框里移动光标/扩选/全选的按键归输入框,表格不导航(见 isNativeInputKey)。
|
|
117
|
+
// 判定用 keydown 当时记下的(见 suppressNativeInputKeys);没记过(不是 AG-Grid 触发的)才现算。
|
|
118
|
+
if ((_nativeKeyDecisions$g = nativeKeyDecisions.get(keyEvent)) !== null && _nativeKeyDecisions$g !== void 0 ? _nativeKeyDecisions$g : isNativeInputKey(keyEvent)) return;
|
|
109
119
|
|
|
110
120
|
// 处理上下左右键导航
|
|
111
121
|
if (keyEvent.key === 'ArrowDown' || keyEvent.key === 'ArrowUp' || keyEvent.key === 'ArrowLeft' || keyEvent.key === 'ArrowRight') {
|
|
@@ -212,16 +222,52 @@ var useRowDrag = exports.useRowDrag = function useRowDrag(field) {
|
|
|
212
222
|
};
|
|
213
223
|
|
|
214
224
|
/**
|
|
215
|
-
*
|
|
225
|
+
* 这个按键该不该交给单元格里的输入框自己处理(浏览器原生行为),而不是当成表格的快捷键/单元格导航。
|
|
216
226
|
*
|
|
217
|
-
* AG-Grid 把 Ctrl+A
|
|
218
|
-
*
|
|
227
|
+
* AG-Grid 把 Ctrl+A 当成「选中所有单元格」、Home/End 当成「跳到行首/行尾单元格」并 preventDefault;
|
|
228
|
+
* 我们的 handleCellKeyDown 又把方向键一律当成「跳到相邻单元格」——输入框里全选、用方向键移动光标、
|
|
229
|
+
* Shift+方向键扩选文字就全都做不了。规则:
|
|
230
|
+
* - Ctrl/Cmd+A、Home/End、带 Shift/Ctrl/Alt/Cmd 的方向键、输入法组字期间的按键 -> 输入框自己处理;
|
|
231
|
+
* - 左右方向键:光标还能动就移动光标(有选区时先收起选区),已经在最左/最右再按才跳到相邻单元格;
|
|
232
|
+
* - 上下方向键:单行输入框没有纵向光标,照旧在行间导航;多行文本域在首行/末行才导航;
|
|
233
|
+
* - 焦点不在输入框里(在单元格本身)、只读输入框(如下拉选择)、不支持光标的输入框:照旧导航。
|
|
219
234
|
* 复制/粘贴/剪切/撤销 AG-Grid 本来就没拦,不必处理。@author nokecy
|
|
220
235
|
*/
|
|
221
|
-
var
|
|
236
|
+
var isNativeInputKey = exports.isNativeInputKey = function isNativeInputKey(event) {
|
|
222
237
|
var _target$matches;
|
|
223
|
-
var event = _ref.event;
|
|
224
|
-
if (!(event.ctrlKey || event.metaKey) || event.key.toLowerCase() !== 'a') return false;
|
|
225
238
|
var target = event.target;
|
|
226
|
-
|
|
239
|
+
if (!(target !== null && target !== void 0 && (_target$matches = target.matches) !== null && _target$matches !== void 0 && _target$matches.call(target, 'input, textarea, [contenteditable="true"]'))) return false;
|
|
240
|
+
var key = event.key;
|
|
241
|
+
if (event.isComposing) return true;
|
|
242
|
+
if ((event.ctrlKey || event.metaKey) && key.toLowerCase() === 'a') return true;
|
|
243
|
+
if (key === 'Home' || key === 'End') return true;
|
|
244
|
+
if (!key.startsWith('Arrow')) return false;
|
|
245
|
+
if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) return true;
|
|
246
|
+
var el = target;
|
|
247
|
+
var start = el.selectionStart,
|
|
248
|
+
end = el.selectionEnd,
|
|
249
|
+
value = el.value;
|
|
250
|
+
// 不支持光标的输入框(如 checkbox)、只读输入框:没有光标可动,方向键用来导航
|
|
251
|
+
if (start == null || end == null || el.readOnly || el.disabled) return false;
|
|
252
|
+
var collapsed = start === end;
|
|
253
|
+
if (key === 'ArrowLeft') return !(collapsed && start === 0);
|
|
254
|
+
if (key === 'ArrowRight') return !(collapsed && end === value.length);
|
|
255
|
+
if (el.tagName !== 'TEXTAREA') return false;
|
|
256
|
+
// 多行文本域:光标不在首行才能往上移,不在末行才能往下移
|
|
257
|
+
return key === 'ArrowUp' ? value.slice(0, start).includes('\n') : value.slice(end).includes('\n');
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* keydown 当时的判定。AG-Grid 的 onCellKeyDown 回调是在 setTimeout(0) 里才触发的,那时浏览器已经执行完默认动作、
|
|
262
|
+
* 光标被挪过了:光标从 1 挪到最左、选区收起到末尾之后再算,会误当成「本来就在边缘」而跳格。
|
|
263
|
+
* suppressKeyboardEvent 是 keydown 时同步调用的,状态还没变,所以在那里记下,回调里直接用。
|
|
264
|
+
*/
|
|
265
|
+
var nativeKeyDecisions = new WeakMap();
|
|
266
|
+
|
|
267
|
+
/** AG-Grid 的 suppressKeyboardEvent:让 AG-Grid 不再拦截输入框自己处理的按键,并记下这次按键的判定 */
|
|
268
|
+
var suppressNativeInputKeys = exports.suppressNativeInputKeys = function suppressNativeInputKeys(_ref) {
|
|
269
|
+
var event = _ref.event;
|
|
270
|
+
var native = isNativeInputKey(event);
|
|
271
|
+
nativeKeyDecisions.set(event, native);
|
|
272
|
+
return native;
|
|
227
273
|
};
|
|
@@ -18,7 +18,7 @@ var _preview = _interopRequireDefault(require("./preview"));
|
|
|
18
18
|
var _antd = require("antd");
|
|
19
19
|
var _setting = _interopRequireDefault(require("../ag-grid-plus/setting"));
|
|
20
20
|
var _columnGroupUtils = require("../ag-grid-plus/setting/columnGroupUtils");
|
|
21
|
-
var _theme = require("
|
|
21
|
+
var _theme = require("./theme");
|
|
22
22
|
var _agGridPlus = require("../ag-grid-plus");
|
|
23
23
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
24
24
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
@@ -34,18 +34,7 @@ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructur
|
|
|
34
34
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
35
35
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
36
36
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
37
|
-
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } //
|
|
38
|
-
// array-table 派生主题:去掉单元格聚焦/选区视觉(行内编辑更干净)。
|
|
39
|
-
// focusShadow -> 聚焦光环
|
|
40
|
-
// rangeSelectionBorder -> 单格点击形成的 1×1 选区蓝边
|
|
41
|
-
// rangeSelectionBackground -> 选区淡蓝填充
|
|
42
|
-
// 仅去视觉,不动焦点功能——键盘导航/点击进编辑仍依赖 cell focus。共用主题不受影响。@author nokecy
|
|
43
|
-
var arrayTableTheme = _theme.agGridTheme.withParams({
|
|
44
|
-
focusShadow: 'none',
|
|
45
|
-
rangeSelectionBorderColor: 'transparent',
|
|
46
|
-
rangeSelectionBackgroundColor: 'transparent'
|
|
47
|
-
});
|
|
48
|
-
|
|
37
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } // AG-Grid v33 主题:行高、单元格居中、去聚焦/选区视觉(编辑态与阅读态共用一份,见 theme.ts)
|
|
49
38
|
//@ts-ignore
|
|
50
39
|
var ArrayTableInner = (0, _react2.observer)(function (props) {
|
|
51
40
|
var _addition$props;
|
|
@@ -341,7 +330,7 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
|
|
|
341
330
|
minHeight: 0
|
|
342
331
|
}
|
|
343
332
|
}, /*#__PURE__*/_react.default.createElement(_agGridReact.AgGridReact, {
|
|
344
|
-
theme: arrayTableTheme,
|
|
333
|
+
theme: _theme.arrayTableTheme,
|
|
345
334
|
context: gridContext,
|
|
346
335
|
onGridReady: function onGridReady(params) {
|
|
347
336
|
params.api.hidePopupMenu();
|
|
@@ -392,8 +381,8 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
|
|
|
392
381
|
enableCellTextSelection: true,
|
|
393
382
|
defaultColDef: {
|
|
394
383
|
resizable: true,
|
|
395
|
-
//
|
|
396
|
-
suppressKeyboardEvent: _hooks.
|
|
384
|
+
// 输入框里全选、移动光标、扩选等文字编辑按键交给输入框,不让 AG-Grid 当成表格快捷键拦走
|
|
385
|
+
suppressKeyboardEvent: _hooks.suppressNativeInputKeys,
|
|
397
386
|
headerComponentParams: {
|
|
398
387
|
template: '<div class="ag-cell-label-container" role="presentation">' +
|
|
399
388
|
// ' <span data-ref="eMenu" class="ag-header-icon ag-header-cell-menu-button" aria-hidden="true"></span>' +
|
|
@@ -430,7 +419,7 @@ var ArrayTableInner = (0, _react2.observer)(function (props) {
|
|
|
430
419
|
// }
|
|
431
420
|
// }}
|
|
432
421
|
,
|
|
433
|
-
rowHeight:
|
|
422
|
+
rowHeight: _theme.ARRAY_TABLE_ROW_HEIGHT,
|
|
434
423
|
pagination: false,
|
|
435
424
|
columnDefs: gridColumnDefs,
|
|
436
425
|
rowData: dataSource
|
|
@@ -8,6 +8,7 @@ var _react = _interopRequireDefault(require("react"));
|
|
|
8
8
|
var _react2 = require("@formily/react");
|
|
9
9
|
var _utils = require("./utils");
|
|
10
10
|
var _agGridPlus = require("../ag-grid-plus");
|
|
11
|
+
var _theme = require("./theme");
|
|
11
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
13
|
//@ts-ignore
|
|
13
14
|
var ArrayTable = function ArrayTable(props) {
|
|
@@ -31,7 +32,8 @@ var ArrayTable = function ArrayTable(props) {
|
|
|
31
32
|
},
|
|
32
33
|
hideTool: true,
|
|
33
34
|
search: false,
|
|
34
|
-
|
|
35
|
+
theme: _theme.arrayTablePreviewTheme,
|
|
36
|
+
rowHeight: _theme.ARRAY_TABLE_ROW_HEIGHT,
|
|
35
37
|
pagination: false,
|
|
36
38
|
columnDefs: columns,
|
|
37
39
|
rowData: dataSource
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 行高 38:放得下 32px 高的输入框。网格选项 rowHeight 与主题参数 rowHeight 必须同值——
|
|
3
|
+
* AG-Grid 单元格文字的行高(--ag-internal-content-line-height)是从主题的 --ag-row-height 算的,
|
|
4
|
+
* 只设网格选项会让文字的行盒仍是主题默认行高(29.6-3=26.6px),顶在 37px 的格子上方(偏上约 4.5px)。
|
|
5
|
+
*/
|
|
6
|
+
export declare const ARRAY_TABLE_ROW_HEIGHT = 38;
|
|
7
|
+
/** 阅读态主题:共用主题 + 行高 + 单元格居中 */
|
|
8
|
+
export declare const arrayTablePreviewTheme: import("ag-grid-community").Theme<import("ag-grid-community").CoreParams & import("ag-grid-community").ButtonStyleParams & import("ag-grid-community").CheckboxStyleParams & import("ag-grid-community").TabStyleParams & import("ag-grid-community").InputStyleParams & {}>;
|
|
9
|
+
/**
|
|
10
|
+
* 编辑态主题:在阅读态主题上去掉单元格聚焦/选区视觉(行内编辑更干净)。
|
|
11
|
+
* focusShadow -> 聚焦光环
|
|
12
|
+
* rangeSelectionBorder -> 单格点击形成的 1×1 选区蓝边
|
|
13
|
+
* rangeSelectionBackground -> 选区淡蓝填充
|
|
14
|
+
* 仅去视觉,不动焦点功能——键盘导航/点击进编辑仍依赖 cell focus。
|
|
15
|
+
*/
|
|
16
|
+
export declare const arrayTableTheme: import("ag-grid-community").Theme<import("ag-grid-community").CoreParams & import("ag-grid-community").ButtonStyleParams & import("ag-grid-community").CheckboxStyleParams & import("ag-grid-community").TabStyleParams & import("ag-grid-community").InputStyleParams & {}>;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.arrayTableTheme = exports.arrayTablePreviewTheme = exports.ARRAY_TABLE_ROW_HEIGHT = void 0;
|
|
7
|
+
var _agGridCommunity = require("ag-grid-community");
|
|
8
|
+
var _theme = require("../ag-grid-plus/theme");
|
|
9
|
+
/**
|
|
10
|
+
* ArrayTable(明细表格)的 AG-Grid 主题:编辑态(index.tsx)与阅读态(preview.tsx)共用。
|
|
11
|
+
*
|
|
12
|
+
* @author nokecy
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 行高 38:放得下 32px 高的输入框。网格选项 rowHeight 与主题参数 rowHeight 必须同值——
|
|
17
|
+
* AG-Grid 单元格文字的行高(--ag-internal-content-line-height)是从主题的 --ag-row-height 算的,
|
|
18
|
+
* 只设网格选项会让文字的行盒仍是主题默认行高(29.6-3=26.6px),顶在 37px 的格子上方(偏上约 4.5px)。
|
|
19
|
+
*/
|
|
20
|
+
var ARRAY_TABLE_ROW_HEIGHT = exports.ARRAY_TABLE_ROW_HEIGHT = 38;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 单元格里的表单项与内容区垂直居中(只对使用本主题的网格生效,共用主题不受影响):
|
|
24
|
+
* - .ag-cell-wrapper 撑满格子,align-items:center 才起作用(默认只有内容高,贴在格子顶部);
|
|
25
|
+
* - FormItem 默认 margin-bottom:24px(loose 反馈布局给错误文字预留的位置),会把 Editable 外壳撑到 56px、
|
|
26
|
+
* 输入框偏上、还超出 37px 的格子,归零;
|
|
27
|
+
* - 错误提示文字移出文档流(位置仍在输入框下方),出错时输入框不会被挤得上下跳。
|
|
28
|
+
*/
|
|
29
|
+
var arrayTableCellFit = (0, _agGridCommunity.createPart)({
|
|
30
|
+
feature: 'arrayTableCellFit',
|
|
31
|
+
css: "\n .ag-cell .ag-cell-wrapper { height: 100%; }\n .ag-cell .ant-formily-item { margin-bottom: 0; }\n .ag-cell .ant-formily-item-help { position: absolute; }\n "
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/** 阅读态主题:共用主题 + 行高 + 单元格居中 */
|
|
35
|
+
var arrayTablePreviewTheme = exports.arrayTablePreviewTheme = _theme.agGridTheme.withParams({
|
|
36
|
+
rowHeight: ARRAY_TABLE_ROW_HEIGHT
|
|
37
|
+
}).withPart(arrayTableCellFit);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 编辑态主题:在阅读态主题上去掉单元格聚焦/选区视觉(行内编辑更干净)。
|
|
41
|
+
* focusShadow -> 聚焦光环
|
|
42
|
+
* rangeSelectionBorder -> 单格点击形成的 1×1 选区蓝边
|
|
43
|
+
* rangeSelectionBackground -> 选区淡蓝填充
|
|
44
|
+
* 仅去视觉,不动焦点功能——键盘导航/点击进编辑仍依赖 cell focus。
|
|
45
|
+
*/
|
|
46
|
+
var arrayTableTheme = exports.arrayTableTheme = arrayTablePreviewTheme.withParams({
|
|
47
|
+
focusShadow: 'none',
|
|
48
|
+
rangeSelectionBorderColor: 'transparent',
|
|
49
|
+
rangeSelectionBackgroundColor: 'transparent'
|
|
50
|
+
});
|
|
@@ -23,12 +23,19 @@ export declare const useRowDrag: (field: ArrayField) => {
|
|
|
23
23
|
handleRowDragMove: (event: any) => void;
|
|
24
24
|
};
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* 这个按键该不该交给单元格里的输入框自己处理(浏览器原生行为),而不是当成表格的快捷键/单元格导航。
|
|
27
27
|
*
|
|
28
|
-
* AG-Grid 把 Ctrl+A
|
|
29
|
-
*
|
|
28
|
+
* AG-Grid 把 Ctrl+A 当成「选中所有单元格」、Home/End 当成「跳到行首/行尾单元格」并 preventDefault;
|
|
29
|
+
* 我们的 handleCellKeyDown 又把方向键一律当成「跳到相邻单元格」——输入框里全选、用方向键移动光标、
|
|
30
|
+
* Shift+方向键扩选文字就全都做不了。规则:
|
|
31
|
+
* - Ctrl/Cmd+A、Home/End、带 Shift/Ctrl/Alt/Cmd 的方向键、输入法组字期间的按键 -> 输入框自己处理;
|
|
32
|
+
* - 左右方向键:光标还能动就移动光标(有选区时先收起选区),已经在最左/最右再按才跳到相邻单元格;
|
|
33
|
+
* - 上下方向键:单行输入框没有纵向光标,照旧在行间导航;多行文本域在首行/末行才导航;
|
|
34
|
+
* - 焦点不在输入框里(在单元格本身)、只读输入框(如下拉选择)、不支持光标的输入框:照旧导航。
|
|
30
35
|
* 复制/粘贴/剪切/撤销 AG-Grid 本来就没拦,不必处理。@author nokecy
|
|
31
36
|
*/
|
|
32
|
-
export declare const
|
|
37
|
+
export declare const isNativeInputKey: (event: KeyboardEvent) => boolean;
|
|
38
|
+
/** AG-Grid 的 suppressKeyboardEvent:让 AG-Grid 不再拦截输入框自己处理的按键,并记下这次按键的判定 */
|
|
39
|
+
export declare const suppressNativeInputKeys: ({ event }: {
|
|
33
40
|
event: KeyboardEvent;
|
|
34
41
|
}) => boolean;
|
|
@@ -11,6 +11,12 @@ var supportsSelectionRange = function supportsSelectionRange(el) {
|
|
|
11
11
|
*/
|
|
12
12
|
export var useCellFocus = function useCellFocus() {
|
|
13
13
|
var focusInputInCell = useCallback(function (cell) {
|
|
14
|
+
// 焦点已经在本格的输入框里:用户直接点进去定位光标、双击选词、按住拖选,这些留下的光标/选区都是他的。
|
|
15
|
+
// 不能再 focus() 并把光标挪到末尾——那会把这些操作在 10ms 后全部抹掉。
|
|
16
|
+
// 首次点开、键盘导航进来时焦点还不在本格输入框里,不受影响。@author nokecy
|
|
17
|
+
var active = document.activeElement;
|
|
18
|
+
if (active && cell.contains(active) && active.matches('input, textarea')) return;
|
|
19
|
+
|
|
14
20
|
// 首先查找Editable包装的元素
|
|
15
21
|
var editableElement = cell.querySelector('.ant-formily-editable');
|
|
16
22
|
if (editableElement) {
|
|
@@ -95,11 +101,15 @@ export var useCellFocus = function useCellFocus() {
|
|
|
95
101
|
*/
|
|
96
102
|
export var useKeyboardNavigation = function useKeyboardNavigation(ref, dataSource, focusInputInCell, activateCell) {
|
|
97
103
|
var handleCellKeyDown = useCallback(function (event) {
|
|
104
|
+
var _nativeKeyDecisions$g;
|
|
98
105
|
var keyEvent = event.event,
|
|
99
106
|
node = event.node,
|
|
100
107
|
colDef = event.colDef,
|
|
101
108
|
api = event.api;
|
|
102
109
|
if (!keyEvent) return;
|
|
110
|
+
// 输入框里移动光标/扩选/全选的按键归输入框,表格不导航(见 isNativeInputKey)。
|
|
111
|
+
// 判定用 keydown 当时记下的(见 suppressNativeInputKeys);没记过(不是 AG-Grid 触发的)才现算。
|
|
112
|
+
if ((_nativeKeyDecisions$g = nativeKeyDecisions.get(keyEvent)) !== null && _nativeKeyDecisions$g !== void 0 ? _nativeKeyDecisions$g : isNativeInputKey(keyEvent)) return;
|
|
103
113
|
|
|
104
114
|
// 处理上下左右键导航
|
|
105
115
|
if (keyEvent.key === 'ArrowDown' || keyEvent.key === 'ArrowUp' || keyEvent.key === 'ArrowLeft' || keyEvent.key === 'ArrowRight') {
|
|
@@ -206,16 +216,52 @@ export var useRowDrag = function useRowDrag(field) {
|
|
|
206
216
|
};
|
|
207
217
|
|
|
208
218
|
/**
|
|
209
|
-
*
|
|
219
|
+
* 这个按键该不该交给单元格里的输入框自己处理(浏览器原生行为),而不是当成表格的快捷键/单元格导航。
|
|
210
220
|
*
|
|
211
|
-
* AG-Grid 把 Ctrl+A
|
|
212
|
-
*
|
|
221
|
+
* AG-Grid 把 Ctrl+A 当成「选中所有单元格」、Home/End 当成「跳到行首/行尾单元格」并 preventDefault;
|
|
222
|
+
* 我们的 handleCellKeyDown 又把方向键一律当成「跳到相邻单元格」——输入框里全选、用方向键移动光标、
|
|
223
|
+
* Shift+方向键扩选文字就全都做不了。规则:
|
|
224
|
+
* - Ctrl/Cmd+A、Home/End、带 Shift/Ctrl/Alt/Cmd 的方向键、输入法组字期间的按键 -> 输入框自己处理;
|
|
225
|
+
* - 左右方向键:光标还能动就移动光标(有选区时先收起选区),已经在最左/最右再按才跳到相邻单元格;
|
|
226
|
+
* - 上下方向键:单行输入框没有纵向光标,照旧在行间导航;多行文本域在首行/末行才导航;
|
|
227
|
+
* - 焦点不在输入框里(在单元格本身)、只读输入框(如下拉选择)、不支持光标的输入框:照旧导航。
|
|
213
228
|
* 复制/粘贴/剪切/撤销 AG-Grid 本来就没拦,不必处理。@author nokecy
|
|
214
229
|
*/
|
|
215
|
-
export var
|
|
230
|
+
export var isNativeInputKey = function isNativeInputKey(event) {
|
|
216
231
|
var _target$matches;
|
|
217
|
-
var event = _ref.event;
|
|
218
|
-
if (!(event.ctrlKey || event.metaKey) || event.key.toLowerCase() !== 'a') return false;
|
|
219
232
|
var target = event.target;
|
|
220
|
-
|
|
233
|
+
if (!(target !== null && target !== void 0 && (_target$matches = target.matches) !== null && _target$matches !== void 0 && _target$matches.call(target, 'input, textarea, [contenteditable="true"]'))) return false;
|
|
234
|
+
var key = event.key;
|
|
235
|
+
if (event.isComposing) return true;
|
|
236
|
+
if ((event.ctrlKey || event.metaKey) && key.toLowerCase() === 'a') return true;
|
|
237
|
+
if (key === 'Home' || key === 'End') return true;
|
|
238
|
+
if (!key.startsWith('Arrow')) return false;
|
|
239
|
+
if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) return true;
|
|
240
|
+
var el = target;
|
|
241
|
+
var start = el.selectionStart,
|
|
242
|
+
end = el.selectionEnd,
|
|
243
|
+
value = el.value;
|
|
244
|
+
// 不支持光标的输入框(如 checkbox)、只读输入框:没有光标可动,方向键用来导航
|
|
245
|
+
if (start == null || end == null || el.readOnly || el.disabled) return false;
|
|
246
|
+
var collapsed = start === end;
|
|
247
|
+
if (key === 'ArrowLeft') return !(collapsed && start === 0);
|
|
248
|
+
if (key === 'ArrowRight') return !(collapsed && end === value.length);
|
|
249
|
+
if (el.tagName !== 'TEXTAREA') return false;
|
|
250
|
+
// 多行文本域:光标不在首行才能往上移,不在末行才能往下移
|
|
251
|
+
return key === 'ArrowUp' ? value.slice(0, start).includes('\n') : value.slice(end).includes('\n');
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* keydown 当时的判定。AG-Grid 的 onCellKeyDown 回调是在 setTimeout(0) 里才触发的,那时浏览器已经执行完默认动作、
|
|
256
|
+
* 光标被挪过了:光标从 1 挪到最左、选区收起到末尾之后再算,会误当成「本来就在边缘」而跳格。
|
|
257
|
+
* suppressKeyboardEvent 是 keydown 时同步调用的,状态还没变,所以在那里记下,回调里直接用。
|
|
258
|
+
*/
|
|
259
|
+
var nativeKeyDecisions = new WeakMap();
|
|
260
|
+
|
|
261
|
+
/** AG-Grid 的 suppressKeyboardEvent:让 AG-Grid 不再拦截输入框自己处理的按键,并记下这次按键的判定 */
|
|
262
|
+
export var suppressNativeInputKeys = function suppressNativeInputKeys(_ref) {
|
|
263
|
+
var event = _ref.event;
|
|
264
|
+
var native = isNativeInputKey(event);
|
|
265
|
+
nativeKeyDecisions.set(event, native);
|
|
266
|
+
return native;
|
|
221
267
|
};
|
|
@@ -19,7 +19,7 @@ import { connect, mapProps, mapReadPretty } from "@formily/react";
|
|
|
19
19
|
import uniqueId from "lodash/uniqueId";
|
|
20
20
|
import { useAddition, buildArrayTableColumns, useArrayTableSources, useArrayTableActions, isColumnComponent } from "./utils";
|
|
21
21
|
import { groupColumnDefs } from "./columnGroup";
|
|
22
|
-
import { useCellFocus, useKeyboardNavigation, useRowDrag,
|
|
22
|
+
import { useCellFocus, useKeyboardNavigation, useRowDrag, suppressNativeInputKeys } from "./hooks";
|
|
23
23
|
import ArrayBase from "./arrayBase";
|
|
24
24
|
import ArrayAddBtn from "./arrayAddBtn";
|
|
25
25
|
import PreviewArrayTable from "./preview";
|
|
@@ -27,21 +27,10 @@ import { Space } from "antd";
|
|
|
27
27
|
import Setting from "../ag-grid-plus/setting";
|
|
28
28
|
import { flatConfigToColumnState, flatConfigToGridState } from "../ag-grid-plus/setting/columnGroupUtils";
|
|
29
29
|
|
|
30
|
-
//
|
|
31
|
-
import {
|
|
30
|
+
// AG-Grid v33 主题:行高、单元格居中、去聚焦/选区视觉(编辑态与阅读态共用一份,见 theme.ts)
|
|
31
|
+
import { arrayTableTheme, ARRAY_TABLE_ROW_HEIGHT } from "./theme";
|
|
32
32
|
import { useGridSchemes } from "../ag-grid-plus";
|
|
33
33
|
|
|
34
|
-
// array-table 派生主题:去掉单元格聚焦/选区视觉(行内编辑更干净)。
|
|
35
|
-
// focusShadow -> 聚焦光环
|
|
36
|
-
// rangeSelectionBorder -> 单格点击形成的 1×1 选区蓝边
|
|
37
|
-
// rangeSelectionBackground -> 选区淡蓝填充
|
|
38
|
-
// 仅去视觉,不动焦点功能——键盘导航/点击进编辑仍依赖 cell focus。共用主题不受影响。@author nokecy
|
|
39
|
-
var arrayTableTheme = agGridTheme.withParams({
|
|
40
|
-
focusShadow: 'none',
|
|
41
|
-
rangeSelectionBorderColor: 'transparent',
|
|
42
|
-
rangeSelectionBackgroundColor: 'transparent'
|
|
43
|
-
});
|
|
44
|
-
|
|
45
34
|
//@ts-ignore
|
|
46
35
|
var ArrayTableInner = observer(function (props) {
|
|
47
36
|
var _addition$props;
|
|
@@ -388,8 +377,8 @@ var ArrayTableInner = observer(function (props) {
|
|
|
388
377
|
enableCellTextSelection: true,
|
|
389
378
|
defaultColDef: {
|
|
390
379
|
resizable: true,
|
|
391
|
-
//
|
|
392
|
-
suppressKeyboardEvent:
|
|
380
|
+
// 输入框里全选、移动光标、扩选等文字编辑按键交给输入框,不让 AG-Grid 当成表格快捷键拦走
|
|
381
|
+
suppressKeyboardEvent: suppressNativeInputKeys,
|
|
393
382
|
headerComponentParams: {
|
|
394
383
|
template: '<div class="ag-cell-label-container" role="presentation">' +
|
|
395
384
|
// ' <span data-ref="eMenu" class="ag-header-icon ag-header-cell-menu-button" aria-hidden="true"></span>' +
|
|
@@ -426,7 +415,7 @@ var ArrayTableInner = observer(function (props) {
|
|
|
426
415
|
// }
|
|
427
416
|
// }}
|
|
428
417
|
,
|
|
429
|
-
rowHeight:
|
|
418
|
+
rowHeight: ARRAY_TABLE_ROW_HEIGHT,
|
|
430
419
|
pagination: false,
|
|
431
420
|
columnDefs: gridColumnDefs,
|
|
432
421
|
rowData: dataSource
|
|
@@ -2,6 +2,7 @@ import React from "react";
|
|
|
2
2
|
import { useField } from "@formily/react";
|
|
3
3
|
import { buildArrayTableColumns, useArrayTableSources } from "./utils";
|
|
4
4
|
import { AgGridPlus } from "../ag-grid-plus";
|
|
5
|
+
import { arrayTablePreviewTheme, ARRAY_TABLE_ROW_HEIGHT } from "./theme";
|
|
5
6
|
//@ts-ignore
|
|
6
7
|
var ArrayTable = function ArrayTable(props) {
|
|
7
8
|
var height = props.height;
|
|
@@ -24,7 +25,8 @@ var ArrayTable = function ArrayTable(props) {
|
|
|
24
25
|
},
|
|
25
26
|
hideTool: true,
|
|
26
27
|
search: false,
|
|
27
|
-
|
|
28
|
+
theme: arrayTablePreviewTheme,
|
|
29
|
+
rowHeight: ARRAY_TABLE_ROW_HEIGHT,
|
|
28
30
|
pagination: false,
|
|
29
31
|
columnDefs: columns,
|
|
30
32
|
rowData: dataSource
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 行高 38:放得下 32px 高的输入框。网格选项 rowHeight 与主题参数 rowHeight 必须同值——
|
|
3
|
+
* AG-Grid 单元格文字的行高(--ag-internal-content-line-height)是从主题的 --ag-row-height 算的,
|
|
4
|
+
* 只设网格选项会让文字的行盒仍是主题默认行高(29.6-3=26.6px),顶在 37px 的格子上方(偏上约 4.5px)。
|
|
5
|
+
*/
|
|
6
|
+
export declare const ARRAY_TABLE_ROW_HEIGHT = 38;
|
|
7
|
+
/** 阅读态主题:共用主题 + 行高 + 单元格居中 */
|
|
8
|
+
export declare const arrayTablePreviewTheme: import("ag-grid-community").Theme<import("ag-grid-community").CoreParams & import("ag-grid-community").ButtonStyleParams & import("ag-grid-community").CheckboxStyleParams & import("ag-grid-community").TabStyleParams & import("ag-grid-community").InputStyleParams & {}>;
|
|
9
|
+
/**
|
|
10
|
+
* 编辑态主题:在阅读态主题上去掉单元格聚焦/选区视觉(行内编辑更干净)。
|
|
11
|
+
* focusShadow -> 聚焦光环
|
|
12
|
+
* rangeSelectionBorder -> 单格点击形成的 1×1 选区蓝边
|
|
13
|
+
* rangeSelectionBackground -> 选区淡蓝填充
|
|
14
|
+
* 仅去视觉,不动焦点功能——键盘导航/点击进编辑仍依赖 cell focus。
|
|
15
|
+
*/
|
|
16
|
+
export declare const arrayTableTheme: import("ag-grid-community").Theme<import("ag-grid-community").CoreParams & import("ag-grid-community").ButtonStyleParams & import("ag-grid-community").CheckboxStyleParams & import("ag-grid-community").TabStyleParams & import("ag-grid-community").InputStyleParams & {}>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ArrayTable(明细表格)的 AG-Grid 主题:编辑态(index.tsx)与阅读态(preview.tsx)共用。
|
|
3
|
+
*
|
|
4
|
+
* @author nokecy
|
|
5
|
+
*/
|
|
6
|
+
import { createPart } from 'ag-grid-community';
|
|
7
|
+
import { agGridTheme } from "../ag-grid-plus/theme";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 行高 38:放得下 32px 高的输入框。网格选项 rowHeight 与主题参数 rowHeight 必须同值——
|
|
11
|
+
* AG-Grid 单元格文字的行高(--ag-internal-content-line-height)是从主题的 --ag-row-height 算的,
|
|
12
|
+
* 只设网格选项会让文字的行盒仍是主题默认行高(29.6-3=26.6px),顶在 37px 的格子上方(偏上约 4.5px)。
|
|
13
|
+
*/
|
|
14
|
+
export var ARRAY_TABLE_ROW_HEIGHT = 38;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 单元格里的表单项与内容区垂直居中(只对使用本主题的网格生效,共用主题不受影响):
|
|
18
|
+
* - .ag-cell-wrapper 撑满格子,align-items:center 才起作用(默认只有内容高,贴在格子顶部);
|
|
19
|
+
* - FormItem 默认 margin-bottom:24px(loose 反馈布局给错误文字预留的位置),会把 Editable 外壳撑到 56px、
|
|
20
|
+
* 输入框偏上、还超出 37px 的格子,归零;
|
|
21
|
+
* - 错误提示文字移出文档流(位置仍在输入框下方),出错时输入框不会被挤得上下跳。
|
|
22
|
+
*/
|
|
23
|
+
var arrayTableCellFit = createPart({
|
|
24
|
+
feature: 'arrayTableCellFit',
|
|
25
|
+
css: "\n .ag-cell .ag-cell-wrapper { height: 100%; }\n .ag-cell .ant-formily-item { margin-bottom: 0; }\n .ag-cell .ant-formily-item-help { position: absolute; }\n "
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
/** 阅读态主题:共用主题 + 行高 + 单元格居中 */
|
|
29
|
+
export var arrayTablePreviewTheme = agGridTheme.withParams({
|
|
30
|
+
rowHeight: ARRAY_TABLE_ROW_HEIGHT
|
|
31
|
+
}).withPart(arrayTableCellFit);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 编辑态主题:在阅读态主题上去掉单元格聚焦/选区视觉(行内编辑更干净)。
|
|
35
|
+
* focusShadow -> 聚焦光环
|
|
36
|
+
* rangeSelectionBorder -> 单格点击形成的 1×1 选区蓝边
|
|
37
|
+
* rangeSelectionBackground -> 选区淡蓝填充
|
|
38
|
+
* 仅去视觉,不动焦点功能——键盘导航/点击进编辑仍依赖 cell focus。
|
|
39
|
+
*/
|
|
40
|
+
export var arrayTableTheme = arrayTablePreviewTheme.withParams({
|
|
41
|
+
focusShadow: 'none',
|
|
42
|
+
rangeSelectionBorderColor: 'transparent',
|
|
43
|
+
rangeSelectionBackgroundColor: 'transparent'
|
|
44
|
+
});
|