@nokecy/qc-ui 1.1.50 → 1.1.52

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.
@@ -1,26 +1,39 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
7
6
  exports.useArrayTableSources = exports.useArrayTableActions = exports.useAddition = exports.isColumnComponent = exports.buildArrayTableColumns = exports.LazyReadOnlyText = exports.LazyAgField = void 0;
8
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
9
8
  var _antd = require("antd");
10
9
  var _react2 = require("@formily/react");
11
10
  var _shared = require("@formily/shared");
12
11
  var _jsonSchema = require("@formily/json-schema");
13
12
  var _arrayBase = _interopRequireDefault(require("./arrayBase"));
14
13
  var _readOnlyFormatters = require("./readOnlyFormatters");
15
- var _excluded = ["hide", "sort", "sortIndex", "forceAgField"];
14
+ var _columnGroup = require("./columnGroup");
15
+ var _cellFocusScope = require("./cellFocusScope");
16
+ var _excluded = ["hide", "sort", "sortIndex", "forceAgField", "headerGroup", "defaultHide"];
16
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
+ 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); }
19
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
20
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
21
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
17
22
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
18
23
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
19
24
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
20
25
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
21
26
  function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
22
- function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
23
- function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
27
+ function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == _typeof(h) && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator.return && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(_typeof(e) + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, catch: function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
28
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
29
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
30
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
31
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
32
+ 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); }
33
+ 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; }
34
+ 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; } }
35
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
36
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
24
37
  var isColumnComponent = exports.isColumnComponent = function isColumnComponent(schema) {
25
38
  var _schema$xComponent;
26
39
  return ((_schema$xComponent = schema['x-component']) === null || _schema$xComponent === void 0 ? void 0 : _schema$xComponent.indexOf('Column')) > -1;
@@ -212,10 +225,12 @@ var resolveLazyCellPattern = function resolveLazyCellPattern(arrayField, record,
212
225
  try {
213
226
  var _arrayField$value$ind, _arrayField$value, _arrayField$value$ind2;
214
227
  var index = (_arrayField$value$ind = (_arrayField$value = arrayField.value) === null || _arrayField$value === void 0 || (_arrayField$value$ind2 = _arrayField$value.indexOf) === null || _arrayField$value$ind2 === void 0 ? void 0 : _arrayField$value$ind2.call(_arrayField$value, record)) !== null && _arrayField$value$ind !== void 0 ? _arrayField$value$ind : -1;
215
- var path = arrayField.address.concat(index).concat(dataKey);
228
+ // 与真字段一致:path 是数据路径(不含 void 容器),address 含 void 容器;表达式里 getValuesIn($self.path...) 靠前者
229
+ var path = arrayField.path.concat(index).concat(dataKey);
230
+ var address = arrayField.address.concat(index).concat(dataKey);
216
231
  var self = {
217
232
  path: path,
218
- address: path,
233
+ address: address,
219
234
  index: index,
220
235
  form: form,
221
236
  parent: arrayField,
@@ -239,21 +254,60 @@ var resolveLazyCellPattern = function resolveLazyCellPattern(arrayField, record,
239
254
  }
240
255
  };
241
256
 
257
+ /**
258
+ * 值算不算「没填」:null/undefined/空串,或成员全是这类值的数组/对象(如 labelInValue 的
259
+ * {value:undefined,label:undefined})。0 和 false 是有效值,不算空。@author nokecy
260
+ */
261
+ var isBlank = function isBlank(value) {
262
+ if (value == null || value === '') return true;
263
+ if (Array.isArray(value)) return value.every(isBlank);
264
+ if (Object.prototype.toString.call(value) === '[object Object]') return Object.values(value).every(isBlank);
265
+ return false;
266
+ };
267
+ var hasRequiredRule = function hasRequiredRule(rule) {
268
+ if (rule == null) return false;
269
+ if (rule === 'required') return true;
270
+ if (Array.isArray(rule)) return rule.some(hasRequiredRule);
271
+ if (_typeof(rule) === 'object') return rule.required != null && rule.required !== false;
272
+ return false;
273
+ };
274
+
275
+ /**
276
+ * 数据字段是否必填(静态判定):字段上写了 required,或 x-validator 里带 required 规则。
277
+ *
278
+ * 判不准(required 写成表达式串)时按必填算:误判必填只是多挂一个控件,
279
+ * 误判非必填会让空的必填格没人校验——与只读判定同样的安全不对称。
280
+ * 靠 x-reactions 动态改必填的列本就整列 eager,不走这里。@author nokecy
281
+ */
282
+ var isRequiredSchema = function isRequiredSchema(fieldSchema) {
283
+ if (!fieldSchema) return false;
284
+ var required = fieldSchema.required;
285
+ if (required === true || typeof required === 'string') return true;
286
+ return hasRequiredRule(fieldSchema['x-validator']);
287
+ };
288
+
242
289
  /**
243
290
  * 懒挂载单元格渲染器(可编辑列)。
244
291
  *
245
292
  * 已有行的可编辑格被 Editable 装饰器默认转成 readPretty 只读文本态(点击才进编辑),
246
- * 但仍挂着完整 Formily 树——这是行多列多滚动卡的主因。本渲染器:
247
- * - 新增行(_isNew,保持编辑态需即时校验) 或 已被激活(点击/导航进过)的格 -> 挂 AgField 全树;
248
- * - 其余(存量行、没碰过) -> 只渲染廉价纯文本(复用 readOnlyFormatters),不挂 Formily 树。
293
+ * 但仍挂着完整 Formily 树——这是行多列多滚动卡的主因。本渲染器让每个格在两种形态间切换:
294
+ * - 懒挂载文本:只渲染廉价纯文本(复用 readOnlyFormatters),不挂 Formily 树。默认形态。
295
+ * - 挂载态:挂 AgField 全树,可编辑、可校验。
249
296
  *
250
- * 激活态存放在 AG-Grid context.activeCells(Set),由 index.tsx 在点击/键盘导航时写入并 refreshCells。
251
- * 「挂了不卸」:一旦激活保持挂载(直到行被虚拟化销毁),不做失焦退回,避开一堆边界。
297
+ * 何时挂载:
298
+ * 1. 被激活(点击/键盘导航进来):激活态存放在 AG-Grid context.activeCells(Set),
299
+ * 由 index.tsx 写入并 refreshCells;
300
+ * 2. 必填且为空:空的必填格必须是真控件,否则没有字段节点,提交时没人校验它。
301
+ * 不区分新增行、存量行、initialValues 带进来的行——只看「必填且空」。
302
+ * 例外:Editable 装饰器的非新增行,Editable 自己会把它转成只读态,挂了也不校验,留在文本态。
303
+ * 何时卸回文本:焦点离开本格,且该字段校验通过(必填的已填上、没有格式错误)。
304
+ * 必填仍为空或校验有错则留着控件,让用户看见错误——与 Editable 失焦时的判断一致。
305
+ * 卸掉的只是渲染树,Formily 字段节点与值都还在,再次点击会接着用。
252
306
  *
253
- * 校验安全:未碰过的存量格本就是 readPretty、本就不参与校验,不挂树校验语义零变化。@author nokecy
307
+ * 校验安全:空的必填格不会卸成文本(见上);其余格卸载前已校验通过。@author nokecy
254
308
  */
255
309
  var LazyAgField = exports.LazyAgField = function LazyAgField(params) {
256
- var _context$activeCells, _context$activeCells$, _fieldSchema$name;
310
+ var _context$activeCells, _fieldSchema$name;
257
311
  var value = params.value,
258
312
  record = params.data,
259
313
  dataSource = params.dataSource,
@@ -264,32 +318,105 @@ var LazyAgField = exports.LazyAgField = function LazyAgField(params) {
264
318
  context = params.context,
265
319
  formatter = params.formatter,
266
320
  columnProps = params.columnProps,
267
- fieldSchema = params.fieldSchema;
321
+ fieldSchema = params.fieldSchema,
322
+ required = params.required;
268
323
  // hook 必须在下面的条件 return 之前调用
269
324
  var _theme$useToken = _antd.theme.useToken(),
270
325
  token = _theme$useToken.token;
271
326
  var scope = (0, _react2.useExpressionScope)();
327
+ var _useReducer = (0, _react.useReducer)(function (n) {
328
+ return n + 1;
329
+ }, 0),
330
+ _useReducer2 = _slicedToArray(_useReducer, 2),
331
+ rerender = _useReducer2[1];
332
+ var localCells = (0, _react.useRef)(new Set());
333
+ var activeCells = (_context$activeCells = context === null || context === void 0 ? void 0 : context.activeCells) !== null && _context$activeCells !== void 0 ? _context$activeCells : localCells.current;
272
334
  var key = "".concat(node === null || node === void 0 ? void 0 : node.id, ":").concat(colDef === null || colDef === void 0 ? void 0 : colDef.field);
273
- var activated = (record === null || record === void 0 ? void 0 : record._isNew) === true || (context === null || context === void 0 || (_context$activeCells = context.activeCells) === null || _context$activeCells === void 0 || (_context$activeCells$ = _context$activeCells.has) === null || _context$activeCells$ === void 0 ? void 0 : _context$activeCells$.call(_context$activeCells, key)) === true;
274
- if (activated) {
275
- return /*#__PURE__*/_react.default.createElement(AgField, {
276
- value: value,
277
- data: record,
278
- dataSource: dataSource,
279
- schema: schema,
280
- field: field,
281
- node: node
282
- });
283
- }
335
+ // 内层字段名:Column key 与它可能不一致(设计器形态),取值/找字段节点都按它
336
+ var dataKey = (_fieldSchema$name = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.name) !== null && _fieldSchema$name !== void 0 ? _fieldSchema$name : colDef === null || colDef === void 0 ? void 0 : colDef.field;
284
337
 
285
- // Observer 包裹纯文本:让未激活的廉价文本格反应式跟随内层 Formily 字段值。
338
+ /** 焦点离开本格:校验通过才卸回懒挂载文本。isStale 为真说明校验期间焦点又回来了或格子已销毁 */
339
+ var handleLeave = /*#__PURE__*/function () {
340
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(isStale) {
341
+ var _field$value$indexOf3, _field$value3, _field$value3$indexOf, _field$form;
342
+ var index, cellField;
343
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
344
+ while (1) switch (_context.prev = _context.next) {
345
+ case 0:
346
+ index = (_field$value$indexOf3 = field === null || field === void 0 || (_field$value3 = field.value) === null || _field$value3 === void 0 || (_field$value3$indexOf = _field$value3.indexOf) === null || _field$value3$indexOf === void 0 ? void 0 : _field$value3$indexOf.call(_field$value3, record)) !== null && _field$value$indexOf3 !== void 0 ? _field$value$indexOf3 : -1; // 字段节点按数据路径找(不含 void 容器);从没挂载过就没有节点,无需校验
347
+ cellField = index >= 0 && dataKey ? (_field$form = field.form) === null || _field$form === void 0 ? void 0 : _field$form.query(field.path.concat(index).concat(dataKey)).take() : undefined;
348
+ if (!cellField) {
349
+ _context.next = 11;
350
+ break;
351
+ }
352
+ _context.prev = 3;
353
+ _context.next = 6;
354
+ return cellField.validate();
355
+ case 6:
356
+ _context.next = 11;
357
+ break;
358
+ case 8:
359
+ _context.prev = 8;
360
+ _context.t0 = _context["catch"](3);
361
+ return _context.abrupt("return");
362
+ case 11:
363
+ if (!isStale()) {
364
+ _context.next = 13;
365
+ break;
366
+ }
367
+ return _context.abrupt("return");
368
+ case 13:
369
+ if (!(required && isBlank(dataKey != null ? readByFieldPath(record, dataKey) : undefined))) {
370
+ _context.next = 15;
371
+ break;
372
+ }
373
+ return _context.abrupt("return");
374
+ case 15:
375
+ activeCells.delete(key);
376
+ rerender();
377
+ case 17:
378
+ case "end":
379
+ return _context.stop();
380
+ }
381
+ }, _callee, null, [[3, 8]]);
382
+ }));
383
+ return function handleLeave(_x) {
384
+ return _ref3.apply(this, arguments);
385
+ };
386
+ }();
387
+
388
+ // Observer 让本格反应式跟随内层 Formily 字段值。
286
389
  // record 即 field.value[index] 的可观察对象;在 Observer 里按内层字段名直接读 record[dataKey]
287
390
  // (而非 AG-Grid 渲染时快照的 params.value)建立依赖后,onFieldValueChange/setValuesIn 程序化原地
288
391
  // 改值(行引用不变 → AG-Grid 不刷新该格、外层 observer 也不重渲)时,本格能自行重渲刷新——
289
392
  // 免去调用方加 forceAgField 逃生阀。字段名缺失才回退 params.value。@author nokecy
290
- var dataKey = (_fieldSchema$name = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.name) !== null && _fieldSchema$name !== void 0 ? _fieldSchema$name : colDef === null || colDef === void 0 ? void 0 : colDef.field;
291
393
  return /*#__PURE__*/_react.default.createElement(_react2.Observer, null, function () {
292
- var liveValue = dataKey != null && record ? readByFieldPath(record, dataKey) : value;
394
+ var activated = activeCells.has(key);
395
+ // 已挂载时不读值:挂载后每敲一个字都会变,追踪它会让整棵字段树跟着重渲
396
+ var liveValue = activated ? undefined : dataKey != null && record ? readByFieldPath(record, dataKey) : value;
397
+ // Editable 装饰器会把非新增行的格转成只读态、不参与校验(见 editable/index.tsx),
398
+ // 这时挂了没用,还会把灰色「请输入」占位换成只读态的「N/A」,所以留在文本态
399
+ var editableWillReadPretty = (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema['x-decorator']) === 'Editable' && (record === null || record === void 0 ? void 0 : record._isNew) !== true;
400
+ if (!activated && required && !editableWillReadPretty && isBlank(liveValue)) {
401
+ var _pattern = resolveLazyCellPattern(field, record, dataKey, fieldSchema, scope);
402
+ if (_pattern == null || _pattern === 'editable') {
403
+ // 记进激活集合:用户填了第一个字后值不再为空,但格子仍在编辑,要挂到失焦为止
404
+ activeCells.add(key);
405
+ activated = true;
406
+ }
407
+ }
408
+ if (activated) {
409
+ return /*#__PURE__*/_react.default.createElement(_cellFocusScope.CellFocusScope, {
410
+ onLeave: handleLeave
411
+ }, /*#__PURE__*/_react.default.createElement(AgField, {
412
+ value: value,
413
+ data: record,
414
+ dataSource: dataSource,
415
+ schema: schema,
416
+ field: field,
417
+ node: node
418
+ }));
419
+ }
293
420
  var text = formatter ? formatter(liveValue, {
294
421
  columnProps: columnProps,
295
422
  fieldSchema: fieldSchema
@@ -400,14 +527,35 @@ var isColumnReadOnlyEligible = function isColumnReadOnlyEligible(arrayPattern, d
400
527
  return false;
401
528
  };
402
529
 
530
+ /** 明细单元格里的数字输入组件(antd InputNumber 及其 Formily 封装) */
531
+ var NUMBER_INPUT_COMPONENTS = new Set(['NumberPicker', 'InputNumber']);
532
+
533
+ /**
534
+ * 明细单元格里的数字输入默认去掉上下步进:不显示上下按钮、不响应方向键步进。
535
+ *
536
+ * 上下按钮会压住右对齐数字的末尾;方向键步进则与单元格间的方向键导航冲突——
537
+ * 在数字格里按 ↑/↓,导航到别的格的同时,被离开的那格数值也被悄悄 +1/-1。
538
+ * 字段的 x-component-props 里显式写了 controls/keyboard 的以使用方为准。
539
+ * 只对会挂真控件的列调用(只读快路径没有输入框)。幂等。@author nokecy
540
+ */
541
+ var applyNumberInputDefaults = function applyNumberInputDefaults(dataField) {
542
+ if (!dataField || !NUMBER_INPUT_COMPONENTS.has(dataField['x-component'])) return;
543
+ var props = dataField['x-component-props'];
544
+ if (props != null && _typeof(props) !== 'object') return; // 整个 props 写成了表达式串,不动
545
+ dataField['x-component-props'] = _objectSpread({
546
+ controls: false,
547
+ keyboard: false
548
+ }, props);
549
+ };
550
+
403
551
  // 重命名自 useArrayTableColumns:内部无任何 Hook 调用,use 前缀违反 Hook 命名约定且曾在 useMemo 内被调用 @author nokecy
404
552
  var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArrayTableColumns(dataSource, field, sources) {
405
553
  var arrayPattern = field === null || field === void 0 ? void 0 : field.pattern;
406
- return sources.reduce(function (buf, _ref3, key) {
407
- var name = _ref3.name,
408
- columnProps = _ref3.columnProps,
409
- schema = _ref3.schema,
410
- display = _ref3.display;
554
+ return sources.reduce(function (buf, _ref4, key) {
555
+ var name = _ref4.name,
556
+ columnProps = _ref4.columnProps,
557
+ schema = _ref4.schema,
558
+ display = _ref4.display;
411
559
  if (display && display !== 'visible') return buf;
412
560
  if (!isColumnComponent(schema)) return buf;
413
561
 
@@ -420,6 +568,8 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
420
568
  sort = columnProps.sort,
421
569
  sortIndex = columnProps.sortIndex,
422
570
  forceAgField = columnProps.forceAgField,
571
+ headerGroup = columnProps.headerGroup,
572
+ defaultHide = columnProps.defaultHide,
423
573
  safeColumnProps = _objectWithoutProperties(columnProps, _excluded);
424
574
  var base = _objectSpread(_objectSpread({}, safeColumnProps), {}, {
425
575
  // 保留 width 作为列的初始宽度
@@ -427,18 +577,27 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
427
577
  //@ts-ignore
428
578
  headerName: columnProps.headerName || columnProps.title,
429
579
  field: name
430
- });
580
+ }, defaultHide === true ? {
581
+ initialHide: true
582
+ } : {});
583
+
584
+ // 记下分组名再输出列定义;真正合并成列组在 index.tsx 交给 AG-Grid 之前(groupColumnDefs)做,
585
+ // 这里产出的仍是扁平列定义。@author nokecy
586
+ var emit = function emit(colDef) {
587
+ return buf.concat((0, _columnGroup.markHeaderGroup)(colDef, headerGroup));
588
+ };
431
589
 
432
590
  // 三分流渲染策略:@author nokecy
433
591
  // ① 只读纯文本(永不可编辑):只读列 + 有格式化器 -> valueFormatter,不挂 Formily 树。
434
592
  // ② 可编辑懒挂载:可编辑列 + 有格式化器 + 无 reactions + 未强制 eager -> LazyAgField,
435
- // 存量格先出廉价文本、点击/导航才挂全树(挂了不卸)。
593
+ // 格子先出廉价文本、点击/导航(或必填且为空)才挂全树,焦点离开且校验通过再卸回文本。
436
594
  // ③ 兜底全树:其余(无格式化器/带 reactions/forceAgField/复杂字段名/只读但无格式化器) -> AgField。
437
595
  var dataField = findDataFieldSchema(schema, name);
438
596
  var component = dataField === null || dataField === void 0 ? void 0 : dataField['x-component'];
439
597
  var formatter = (0, _readOnlyFormatters.getReadOnlyFormatter)(component);
440
598
  var readOnly = isColumnReadOnlyEligible(arrayPattern, dataField, columnProps);
441
599
  var hasReactions = !!(dataField && dataField['x-reactions']);
600
+ if (!readOnly) applyNumberInputDefaults(dataField);
442
601
  var forceEager = (columnProps === null || columnProps === void 0 ? void 0 : columnProps.forceAgField) === true;
443
602
  // Switch/Checkbox 是「单击直控」组件:可编辑态本就该常驻渲染真控件(优化前即如此)。
444
603
  // 懒挂载会把它降成「是/否」纯文本(点击才挂出开关),用户会以为开关消失。故可编辑态强制 eager。
@@ -463,7 +622,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
463
622
  // 读 AG-Grid 缓存值不刷新 → 反应式只读渲染。整表 readPretty(明细/详情页,数据 setValues 整体加载、
464
623
  // 行引用整体替换、AG-Grid 自然刷新)仍走更廉价的静态 valueFormatter 快路径。@author nokecy
465
624
  if (arrayPattern !== 'readPretty') {
466
- return buf.concat(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
625
+ return emit(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
467
626
  valueGetter: valueGetter
468
627
  } : {}), {}, {
469
628
  cellRenderer: LazyReadOnlyText,
@@ -474,7 +633,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
474
633
  }
475
634
  }));
476
635
  }
477
- return buf.concat(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
636
+ return emit(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
478
637
  valueGetter: valueGetter
479
638
  } : {}), {}, {
480
639
  // 显式清掉可能从 safeColumnProps 漏带的 cellRenderer(AG-Grid 中 renderer 优先级高于 formatter)
@@ -490,7 +649,7 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
490
649
 
491
650
  // ② 可编辑懒挂载(排除单击直控的 Switch/Checkbox:须 eager 出真控件)
492
651
  if (!readOnly && formatter && !hasReactions && !forceEager && !isInlineToggle && canFastPath) {
493
- return buf.concat(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
652
+ return emit(_objectSpread(_objectSpread(_objectSpread({}, base), valueGetter ? {
494
653
  valueGetter: valueGetter
495
654
  } : {}), {}, {
496
655
  cellRenderer: LazyAgField,
@@ -501,13 +660,15 @@ var buildArrayTableColumns = exports.buildArrayTableColumns = function buildArra
501
660
  formatter: formatter,
502
661
  columnProps: columnProps,
503
662
  fieldSchema: dataField,
504
- lazyEditable: true // 供 index.tsx 识别懒列(激活/导航用)
663
+ lazyEditable: true,
664
+ // 供 index.tsx 识别懒列(激活/导航用)
665
+ required: isRequiredSchema(dataField) // 必填且为空的格必须挂真控件,见 LazyAgField
505
666
  }
506
667
  }));
507
668
  }
508
669
 
509
670
  // ③ 兜底全树
510
- return buf.concat(_objectSpread(_objectSpread({}, base), {}, {
671
+ return emit(_objectSpread(_objectSpread({}, base), {}, {
511
672
  cellRendererParams: {
512
673
  dataSource: dataSource,
513
674
  schema: schema,
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ /**
3
+ * 判断「焦点离开了这个单元格」的作用域,给懒挂载格「用完卸回纯文本」用。
4
+ *
5
+ * 用 React 合成的 onFocus/onBlur 而不是原生监听:合成事件会沿 React 树冒泡,
6
+ * 穿过 portal。下拉面板、日期面板、选择对话框这类渲染到 body 上的弹层,焦点进去时
7
+ * 对本格来说仍是「格内」,不会被误判成离开;弹层的挂载点是哪、有没有 antd 的类名都不用管。
8
+ *
9
+ * 失焦不立刻判定,而是推到下一个任务再看:焦点从输入框换到格内别的元素(或弹层)时,
10
+ * blur 之后紧跟着 focus,后者会作废这次判定。判定时若 document.activeElement 仍在格内
11
+ * (窗口切走时输入框依旧是 activeElement),同样不算离开。
12
+ *
13
+ * 用 display: contents,不产生盒子,不改变单元格里原有的布局。
14
+ *
15
+ * @author nokecy
16
+ */
17
+ export type CellLeaveHandler = (isStale: () => boolean) => void;
18
+ export declare const CellFocusScope: ({ onLeave, children }: {
19
+ onLeave: CellLeaveHandler;
20
+ children: React.ReactNode;
21
+ }) => React.JSX.Element;
@@ -0,0 +1,54 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ /**
4
+ * 判断「焦点离开了这个单元格」的作用域,给懒挂载格「用完卸回纯文本」用。
5
+ *
6
+ * 用 React 合成的 onFocus/onBlur 而不是原生监听:合成事件会沿 React 树冒泡,
7
+ * 穿过 portal。下拉面板、日期面板、选择对话框这类渲染到 body 上的弹层,焦点进去时
8
+ * 对本格来说仍是「格内」,不会被误判成离开;弹层的挂载点是哪、有没有 antd 的类名都不用管。
9
+ *
10
+ * 失焦不立刻判定,而是推到下一个任务再看:焦点从输入框换到格内别的元素(或弹层)时,
11
+ * blur 之后紧跟着 focus,后者会作废这次判定。判定时若 document.activeElement 仍在格内
12
+ * (窗口切走时输入框依旧是 activeElement),同样不算离开。
13
+ *
14
+ * 用 display: contents,不产生盒子,不改变单元格里原有的布局。
15
+ *
16
+ * @author nokecy
17
+ */
18
+
19
+ export var CellFocusScope = function CellFocusScope(_ref) {
20
+ var onLeave = _ref.onLeave,
21
+ children = _ref.children;
22
+ var rootRef = useRef(null);
23
+ var timerRef = useRef();
24
+ // 每次焦点回到格内、或卸载时递增;进行中的异步判定拿它判断自己是否已过期
25
+ var generationRef = useRef(0);
26
+ var onLeaveRef = useRef(onLeave);
27
+ onLeaveRef.current = onLeave;
28
+ var cancel = function cancel() {
29
+ generationRef.current += 1;
30
+ window.clearTimeout(timerRef.current);
31
+ };
32
+ useEffect(function () {
33
+ return cancel;
34
+ }, []);
35
+ var handleBlur = function handleBlur() {
36
+ cancel();
37
+ var generation = generationRef.current;
38
+ timerRef.current = window.setTimeout(function () {
39
+ var _rootRef$current;
40
+ if ((_rootRef$current = rootRef.current) !== null && _rootRef$current !== void 0 && _rootRef$current.contains(document.activeElement)) return;
41
+ onLeaveRef.current(function () {
42
+ return generation !== generationRef.current;
43
+ });
44
+ }, 0);
45
+ };
46
+ return /*#__PURE__*/React.createElement("div", {
47
+ ref: rootRef,
48
+ style: {
49
+ display: 'contents'
50
+ },
51
+ onFocus: cancel,
52
+ onBlur: handleBlur
53
+ }, children);
54
+ };
@@ -0,0 +1,39 @@
1
+ /**
2
+ * ArrayTable 分组表头(多级表头)。
3
+ *
4
+ * 背景:schema 里的每个 ArrayTable.Column 被抽成「扁平」列定义(buildArrayTableColumns),
5
+ * 内部一批逻辑(懒挂载列识别、列方案还原、首列拖拽等)都按扁平列取值,不能改。
6
+ * 所以分组只在「交给 AG-Grid 的那一份 columnDefs」上做:
7
+ * 1. buildArrayTableColumns 生成列定义时,用 markHeaderGroup 把列声明的 headerGroup 记下来;
8
+ * 2. index.tsx 把扁平列定义交给 groupColumnDefs,得到含列组的 columnDefs 传给 AgGridReact。
9
+ *
10
+ * 分组名记在模块内的 WeakMap 里,不往 colDef 上塞自定义字段——AG-Grid 会把未知属性当作错误告警。
11
+ *
12
+ * 只支持一级分组;分组名相同但不相邻的列各自成组。
13
+ *
14
+ * @author nokecy
15
+ */
16
+ import type { ColDef, ColGroupDef } from 'ag-grid-community';
17
+ /**
18
+ * 记下列定义所属的表头分组。
19
+ * headerGroup 不是非空字符串(没声明、空串、纯空白)时不做任何事,该列按无分组处理。
20
+ * 返回传入的 colDef 本身,方便链式使用。
21
+ */
22
+ export declare const markHeaderGroup: <T extends object>(colDef: T, headerGroup: unknown) => T;
23
+ /**
24
+ * 把扁平列定义按「相邻且 headerGroup 相同」合并成 AG-Grid 列组。
25
+ *
26
+ * - 相邻同名的列 -> 一个 { headerName, groupId, children } 列组;
27
+ * - 同名但被别的列隔开 -> 各自成组,groupId 各不相同;
28
+ * - 没声明分组的列原样保留(同一个对象);
29
+ * - 一个分组也没有时直接返回传入的数组本身,没用到分组的表格行为零变化。
30
+ *
31
+ * groupId 由分组名派生(同名第 N 次出现追加 _N),同样的输入永远得到同样的 id:
32
+ * columnDefs 因别的原因重建时,AG-Grid 靠 groupId 认出还是那个列组,列组状态不丢。
33
+ *
34
+ * 有意不设 marryChildren:设了以后,任何打破组内相邻的列顺序(用户旧的扁平列方案、
35
+ * 列设置面板里跨组拖动的实时预览)都会被 AG-Grid 整体丢弃并报 error #39;不设则顺序照常生效,
36
+ * 组被隔开时表头显示成多段。
37
+ * openByDefault:列组默认展开(只对配了 columnGroupShow 的可折叠列组有意义)。
38
+ */
39
+ export declare const groupColumnDefs: (colDefs: ColDef[]) => (ColDef | ColGroupDef)[];
@@ -0,0 +1,100 @@
1
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
2
+ 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); }
3
+ 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; }
4
+ /**
5
+ * ArrayTable 分组表头(多级表头)。
6
+ *
7
+ * 背景:schema 里的每个 ArrayTable.Column 被抽成「扁平」列定义(buildArrayTableColumns),
8
+ * 内部一批逻辑(懒挂载列识别、列方案还原、首列拖拽等)都按扁平列取值,不能改。
9
+ * 所以分组只在「交给 AG-Grid 的那一份 columnDefs」上做:
10
+ * 1. buildArrayTableColumns 生成列定义时,用 markHeaderGroup 把列声明的 headerGroup 记下来;
11
+ * 2. index.tsx 把扁平列定义交给 groupColumnDefs,得到含列组的 columnDefs 传给 AgGridReact。
12
+ *
13
+ * 分组名记在模块内的 WeakMap 里,不往 colDef 上塞自定义字段——AG-Grid 会把未知属性当作错误告警。
14
+ *
15
+ * 只支持一级分组;分组名相同但不相邻的列各自成组。
16
+ *
17
+ * @author nokecy
18
+ */
19
+
20
+ /** 列定义 -> 它在 schema 里声明的 headerGroup */
21
+ var headerGroupOf = new WeakMap();
22
+
23
+ /** 列组 id 前缀,与列方案里生成的 col_N 区分开 */
24
+ var GROUP_ID_PREFIX = 'arrayTableGroup_';
25
+
26
+ /**
27
+ * 记下列定义所属的表头分组。
28
+ * headerGroup 不是非空字符串(没声明、空串、纯空白)时不做任何事,该列按无分组处理。
29
+ * 返回传入的 colDef 本身,方便链式使用。
30
+ */
31
+ export var markHeaderGroup = function markHeaderGroup(colDef, headerGroup) {
32
+ if (typeof headerGroup === 'string' && headerGroup.trim() !== '') {
33
+ headerGroupOf.set(colDef, headerGroup);
34
+ }
35
+ return colDef;
36
+ };
37
+
38
+ /**
39
+ * 把扁平列定义按「相邻且 headerGroup 相同」合并成 AG-Grid 列组。
40
+ *
41
+ * - 相邻同名的列 -> 一个 { headerName, groupId, children } 列组;
42
+ * - 同名但被别的列隔开 -> 各自成组,groupId 各不相同;
43
+ * - 没声明分组的列原样保留(同一个对象);
44
+ * - 一个分组也没有时直接返回传入的数组本身,没用到分组的表格行为零变化。
45
+ *
46
+ * groupId 由分组名派生(同名第 N 次出现追加 _N),同样的输入永远得到同样的 id:
47
+ * columnDefs 因别的原因重建时,AG-Grid 靠 groupId 认出还是那个列组,列组状态不丢。
48
+ *
49
+ * 有意不设 marryChildren:设了以后,任何打破组内相邻的列顺序(用户旧的扁平列方案、
50
+ * 列设置面板里跨组拖动的实时预览)都会被 AG-Grid 整体丢弃并报 error #39;不设则顺序照常生效,
51
+ * 组被隔开时表头显示成多段。
52
+ * openByDefault:列组默认展开(只对配了 columnGroupShow 的可折叠列组有意义)。
53
+ */
54
+ export var groupColumnDefs = function groupColumnDefs(colDefs) {
55
+ if (!colDefs.some(function (colDef) {
56
+ return headerGroupOf.has(colDef);
57
+ })) return colDefs;
58
+ var usedGroupIds = new Set();
59
+ var makeGroupId = function makeGroupId(name) {
60
+ var id = "".concat(GROUP_ID_PREFIX).concat(name);
61
+ for (var n = 2; usedGroupIds.has(id); n++) {
62
+ id = "".concat(GROUP_ID_PREFIX).concat(name, "_").concat(n);
63
+ }
64
+ usedGroupIds.add(id);
65
+ return id;
66
+ };
67
+ var result = [];
68
+ var current = null;
69
+ var _iterator = _createForOfIteratorHelper(colDefs),
70
+ _step;
71
+ try {
72
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
73
+ var colDef = _step.value;
74
+ var name = headerGroupOf.get(colDef);
75
+ if (name === undefined) {
76
+ current = null;
77
+ result.push(colDef);
78
+ } else if (current && current.name === name) {
79
+ current.group.children.push(colDef);
80
+ } else {
81
+ var group = {
82
+ headerName: name,
83
+ groupId: makeGroupId(name),
84
+ openByDefault: true,
85
+ children: [colDef]
86
+ };
87
+ current = {
88
+ name: name,
89
+ group: group
90
+ };
91
+ result.push(group);
92
+ }
93
+ }
94
+ } catch (err) {
95
+ _iterator.e(err);
96
+ } finally {
97
+ _iterator.f();
98
+ }
99
+ return result;
100
+ };
@@ -22,3 +22,13 @@ export declare const useKeyboardNavigation: (ref: RefObject<any>, dataSource: an
22
22
  export declare const useRowDrag: (field: ArrayField) => {
23
23
  handleRowDragMove: (event: any) => void;
24
24
  };
25
+ /**
26
+ * AG-Grid 的 suppressKeyboardEvent:单元格里的输入框按 Ctrl/Cmd+A 时,让浏览器自己全选文字。
27
+ *
28
+ * AG-Grid 把 Ctrl+A 当成「选中所有单元格」并 preventDefault,输入框(文本框、数字框都一样)
29
+ * 就选不中里面的文字。这里只放行这一个组合;方向键等其余按键仍归 handleCellKeyDown 做单元格导航。
30
+ * 复制/粘贴/剪切/撤销 AG-Grid 本来就没拦,不必处理。@author nokecy
31
+ */
32
+ export declare const suppressSelectAllInInput: ({ event }: {
33
+ event: KeyboardEvent;
34
+ }) => boolean;