@nokecy/qc-ui 1.1.51 → 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.
@@ -14,7 +14,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
14
14
  *
15
15
  * @author nokecy
16
16
  */
17
-
17
+ import dayjs from 'dayjs';
18
18
  /** 从字段 schema / 列 props 里尽量取到 Select 的可选项(value->label 映射用) */
19
19
  var resolveOptions = function resolveOptions(ctx) {
20
20
  var _ref, _ref2, _ref3, _fieldSchema$enum, _fieldSchema$xCompon, _fieldSchema$xCompon2;
@@ -56,9 +56,11 @@ var dateFormatter = function dateFormatter(value, ctx) {
56
56
  var _ref6, _ctx$columnProps$form, _ctx$columnProps, _ctx$fieldSchema;
57
57
  if (value == null || value === '') return '';
58
58
  var fmt = (_ref6 = (_ctx$columnProps$form = (_ctx$columnProps = ctx.columnProps) === null || _ctx$columnProps === void 0 ? void 0 : _ctx$columnProps.format) !== null && _ctx$columnProps$form !== void 0 ? _ctx$columnProps$form : (_ctx$fieldSchema = ctx.fieldSchema) === null || _ctx$fieldSchema === void 0 || (_ctx$fieldSchema = _ctx$fieldSchema['x-component-props']) === null || _ctx$fieldSchema === void 0 ? void 0 : _ctx$fieldSchema.format) !== null && _ref6 !== void 0 ? _ref6 : 'YYYY-MM-DD';
59
- // 值多为 dayjs 对象(有 .format)或已格式化的字符串;不强引 dayjs,保持轻量
60
- if (value && typeof value.format === 'function') return value.format(fmt);
61
- return String(value);
59
+ if (typeof value.format === 'function') return value.format(fmt);
60
+ // 后端回来的多是 ISO 串(2024-10-19T00:00:00)或时间戳:与 Formily readPretty 一致,按 dayjs(value).format(fmt) 显示;
61
+ // 解析不了的文本(如「待定」)原样显示,不吞掉。dayjs 随 antd 传递依赖引入,本库其他模块已直接使用。
62
+ var parsed = dayjs(value);
63
+ return parsed.isValid() ? parsed.format(fmt) : String(value);
62
64
  };
63
65
  var booleanFormatter = function booleanFormatter(value, ctx) {
64
66
  var _ctx$fieldSchema$xCo, _ctx$fieldSchema2, _props$checkedChildre, _props$unCheckedChild;
@@ -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
+ });
@@ -10,14 +10,21 @@ declare const useArrayTableActions: () => ObservableColumnSource[];
10
10
  * 懒挂载单元格渲染器(可编辑列)。
11
11
  *
12
12
  * 已有行的可编辑格被 Editable 装饰器默认转成 readPretty 只读文本态(点击才进编辑),
13
- * 但仍挂着完整 Formily 树——这是行多列多滚动卡的主因。本渲染器:
14
- * - 新增行(_isNew,保持编辑态需即时校验) 或 已被激活(点击/导航进过)的格 -> 挂 AgField 全树;
15
- * - 其余(存量行、没碰过) -> 只渲染廉价纯文本(复用 readOnlyFormatters),不挂 Formily 树。
13
+ * 但仍挂着完整 Formily 树——这是行多列多滚动卡的主因。本渲染器让每个格在两种形态间切换:
14
+ * - 懒挂载文本:只渲染廉价纯文本(复用 readOnlyFormatters),不挂 Formily 树。默认形态。
15
+ * - 挂载态:挂 AgField 全树,可编辑、可校验。
16
16
  *
17
- * 激活态存放在 AG-Grid context.activeCells(Set),由 index.tsx 在点击/键盘导航时写入并 refreshCells。
18
- * 「挂了不卸」:一旦激活保持挂载(直到行被虚拟化销毁),不做失焦退回,避开一堆边界。
17
+ * 何时挂载:
18
+ * 1. 被激活(点击/键盘导航进来):激活态存放在 AG-Grid context.activeCells(Set),
19
+ * 由 index.tsx 写入并 refreshCells;
20
+ * 2. 必填且为空:空的必填格必须是真控件,否则没有字段节点,提交时没人校验它。
21
+ * 不区分新增行、存量行、initialValues 带进来的行——只看「必填且空」。
22
+ * 例外:Editable 装饰器的非新增行,Editable 自己会把它转成只读态,挂了也不校验,留在文本态。
23
+ * 何时卸回文本:焦点离开本格,且该字段校验通过(必填的已填上、没有格式错误)。
24
+ * 必填仍为空或校验有错则留着控件,让用户看见错误——与 Editable 失焦时的判断一致。
25
+ * 卸掉的只是渲染树,Formily 字段节点与值都还在,再次点击会接着用。
19
26
  *
20
- * 校验安全:未碰过的存量格本就是 readPretty、本就不参与校验,不挂树校验语义零变化。@author nokecy
27
+ * 校验安全:空的必填格不会卸成文本(见上);其余格卸载前已校验通过。@author nokecy
21
28
  */
22
29
  declare const LazyAgField: (params: any) => React.JSX.Element;
23
30
  /**
@@ -1,13 +1,22 @@
1
- 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); }
2
1
  var _excluded = ["hide", "sort", "sortIndex", "forceAgField", "headerGroup", "defaultHide"];
2
+ 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; }
3
+ 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; }
3
4
  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; }
4
5
  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; }
5
6
  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; }
6
7
  function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
7
8
  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); }
8
- 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; }
9
- 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; }
10
- import React from 'react';
9
+ 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; }
10
+ 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); } }
11
+ 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); }); }; }
12
+ function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
13
+ 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."); }
14
+ 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); }
15
+ 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; }
16
+ 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; } }
17
+ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
18
+ 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); }
19
+ import React, { useReducer, useRef } from 'react';
11
20
  import { theme } from 'antd';
12
21
  import { useField, useFieldSchema, RecursionField, Observer, useExpressionScope } from '@formily/react';
13
22
  import { isArr, lazyMerge } from '@formily/shared';
@@ -15,6 +24,7 @@ import { Schema } from '@formily/json-schema';
15
24
  import ArrayBase from "./arrayBase";
16
25
  import { getReadOnlyFormatter } from "./readOnlyFormatters";
17
26
  import { markHeaderGroup } from "./columnGroup";
27
+ import { CellFocusScope } from "./cellFocusScope";
18
28
  var isColumnComponent = function isColumnComponent(schema) {
19
29
  var _schema$xComponent;
20
30
  return ((_schema$xComponent = schema['x-component']) === null || _schema$xComponent === void 0 ? void 0 : _schema$xComponent.indexOf('Column')) > -1;
@@ -235,21 +245,60 @@ var resolveLazyCellPattern = function resolveLazyCellPattern(arrayField, record,
235
245
  }
236
246
  };
237
247
 
248
+ /**
249
+ * 值算不算「没填」:null/undefined/空串,或成员全是这类值的数组/对象(如 labelInValue 的
250
+ * {value:undefined,label:undefined})。0 和 false 是有效值,不算空。@author nokecy
251
+ */
252
+ var isBlank = function isBlank(value) {
253
+ if (value == null || value === '') return true;
254
+ if (Array.isArray(value)) return value.every(isBlank);
255
+ if (Object.prototype.toString.call(value) === '[object Object]') return Object.values(value).every(isBlank);
256
+ return false;
257
+ };
258
+ var hasRequiredRule = function hasRequiredRule(rule) {
259
+ if (rule == null) return false;
260
+ if (rule === 'required') return true;
261
+ if (Array.isArray(rule)) return rule.some(hasRequiredRule);
262
+ if (_typeof(rule) === 'object') return rule.required != null && rule.required !== false;
263
+ return false;
264
+ };
265
+
266
+ /**
267
+ * 数据字段是否必填(静态判定):字段上写了 required,或 x-validator 里带 required 规则。
268
+ *
269
+ * 判不准(required 写成表达式串)时按必填算:误判必填只是多挂一个控件,
270
+ * 误判非必填会让空的必填格没人校验——与只读判定同样的安全不对称。
271
+ * 靠 x-reactions 动态改必填的列本就整列 eager,不走这里。@author nokecy
272
+ */
273
+ var isRequiredSchema = function isRequiredSchema(fieldSchema) {
274
+ if (!fieldSchema) return false;
275
+ var required = fieldSchema.required;
276
+ if (required === true || typeof required === 'string') return true;
277
+ return hasRequiredRule(fieldSchema['x-validator']);
278
+ };
279
+
238
280
  /**
239
281
  * 懒挂载单元格渲染器(可编辑列)。
240
282
  *
241
283
  * 已有行的可编辑格被 Editable 装饰器默认转成 readPretty 只读文本态(点击才进编辑),
242
- * 但仍挂着完整 Formily 树——这是行多列多滚动卡的主因。本渲染器:
243
- * - 新增行(_isNew,保持编辑态需即时校验) 或 已被激活(点击/导航进过)的格 -> 挂 AgField 全树;
244
- * - 其余(存量行、没碰过) -> 只渲染廉价纯文本(复用 readOnlyFormatters),不挂 Formily 树。
284
+ * 但仍挂着完整 Formily 树——这是行多列多滚动卡的主因。本渲染器让每个格在两种形态间切换:
285
+ * - 懒挂载文本:只渲染廉价纯文本(复用 readOnlyFormatters),不挂 Formily 树。默认形态。
286
+ * - 挂载态:挂 AgField 全树,可编辑、可校验。
245
287
  *
246
- * 激活态存放在 AG-Grid context.activeCells(Set),由 index.tsx 在点击/键盘导航时写入并 refreshCells。
247
- * 「挂了不卸」:一旦激活保持挂载(直到行被虚拟化销毁),不做失焦退回,避开一堆边界。
288
+ * 何时挂载:
289
+ * 1. 被激活(点击/键盘导航进来):激活态存放在 AG-Grid context.activeCells(Set),
290
+ * 由 index.tsx 写入并 refreshCells;
291
+ * 2. 必填且为空:空的必填格必须是真控件,否则没有字段节点,提交时没人校验它。
292
+ * 不区分新增行、存量行、initialValues 带进来的行——只看「必填且空」。
293
+ * 例外:Editable 装饰器的非新增行,Editable 自己会把它转成只读态,挂了也不校验,留在文本态。
294
+ * 何时卸回文本:焦点离开本格,且该字段校验通过(必填的已填上、没有格式错误)。
295
+ * 必填仍为空或校验有错则留着控件,让用户看见错误——与 Editable 失焦时的判断一致。
296
+ * 卸掉的只是渲染树,Formily 字段节点与值都还在,再次点击会接着用。
248
297
  *
249
- * 校验安全:未碰过的存量格本就是 readPretty、本就不参与校验,不挂树校验语义零变化。@author nokecy
298
+ * 校验安全:空的必填格不会卸成文本(见上);其余格卸载前已校验通过。@author nokecy
250
299
  */
251
300
  var LazyAgField = function LazyAgField(params) {
252
- var _context$activeCells, _context$activeCells$, _fieldSchema$name;
301
+ var _context$activeCells, _fieldSchema$name;
253
302
  var value = params.value,
254
303
  record = params.data,
255
304
  dataSource = params.dataSource,
@@ -260,32 +309,105 @@ var LazyAgField = function LazyAgField(params) {
260
309
  context = params.context,
261
310
  formatter = params.formatter,
262
311
  columnProps = params.columnProps,
263
- fieldSchema = params.fieldSchema;
312
+ fieldSchema = params.fieldSchema,
313
+ required = params.required;
264
314
  // hook 必须在下面的条件 return 之前调用
265
315
  var _theme$useToken = theme.useToken(),
266
316
  token = _theme$useToken.token;
267
317
  var scope = useExpressionScope();
318
+ var _useReducer = useReducer(function (n) {
319
+ return n + 1;
320
+ }, 0),
321
+ _useReducer2 = _slicedToArray(_useReducer, 2),
322
+ rerender = _useReducer2[1];
323
+ var localCells = useRef(new Set());
324
+ var activeCells = (_context$activeCells = context === null || context === void 0 ? void 0 : context.activeCells) !== null && _context$activeCells !== void 0 ? _context$activeCells : localCells.current;
268
325
  var key = "".concat(node === null || node === void 0 ? void 0 : node.id, ":").concat(colDef === null || colDef === void 0 ? void 0 : colDef.field);
269
- 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;
270
- if (activated) {
271
- return /*#__PURE__*/React.createElement(AgField, {
272
- value: value,
273
- data: record,
274
- dataSource: dataSource,
275
- schema: schema,
276
- field: field,
277
- node: node
278
- });
279
- }
326
+ // 内层字段名:Column key 与它可能不一致(设计器形态),取值/找字段节点都按它
327
+ 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;
328
+
329
+ /** 焦点离开本格:校验通过才卸回懒挂载文本。isStale 为真说明校验期间焦点又回来了或格子已销毁 */
330
+ var handleLeave = /*#__PURE__*/function () {
331
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(isStale) {
332
+ var _field$value$indexOf3, _field$value3, _field$value3$indexOf, _field$form;
333
+ var index, cellField;
334
+ return _regeneratorRuntime().wrap(function _callee$(_context) {
335
+ while (1) switch (_context.prev = _context.next) {
336
+ case 0:
337
+ 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 容器);从没挂载过就没有节点,无需校验
338
+ 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;
339
+ if (!cellField) {
340
+ _context.next = 11;
341
+ break;
342
+ }
343
+ _context.prev = 3;
344
+ _context.next = 6;
345
+ return cellField.validate();
346
+ case 6:
347
+ _context.next = 11;
348
+ break;
349
+ case 8:
350
+ _context.prev = 8;
351
+ _context.t0 = _context["catch"](3);
352
+ return _context.abrupt("return");
353
+ case 11:
354
+ if (!isStale()) {
355
+ _context.next = 13;
356
+ break;
357
+ }
358
+ return _context.abrupt("return");
359
+ case 13:
360
+ if (!(required && isBlank(dataKey != null ? readByFieldPath(record, dataKey) : undefined))) {
361
+ _context.next = 15;
362
+ break;
363
+ }
364
+ return _context.abrupt("return");
365
+ case 15:
366
+ activeCells.delete(key);
367
+ rerender();
368
+ case 17:
369
+ case "end":
370
+ return _context.stop();
371
+ }
372
+ }, _callee, null, [[3, 8]]);
373
+ }));
374
+ return function handleLeave(_x) {
375
+ return _ref3.apply(this, arguments);
376
+ };
377
+ }();
280
378
 
281
- // Observer 包裹纯文本:让未激活的廉价文本格反应式跟随内层 Formily 字段值。
379
+ // Observer 让本格反应式跟随内层 Formily 字段值。
282
380
  // record 即 field.value[index] 的可观察对象;在 Observer 里按内层字段名直接读 record[dataKey]
283
381
  // (而非 AG-Grid 渲染时快照的 params.value)建立依赖后,onFieldValueChange/setValuesIn 程序化原地
284
382
  // 改值(行引用不变 → AG-Grid 不刷新该格、外层 observer 也不重渲)时,本格能自行重渲刷新——
285
383
  // 免去调用方加 forceAgField 逃生阀。字段名缺失才回退 params.value。@author nokecy
286
- 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;
287
384
  return /*#__PURE__*/React.createElement(Observer, null, function () {
288
- var liveValue = dataKey != null && record ? readByFieldPath(record, dataKey) : value;
385
+ var activated = activeCells.has(key);
386
+ // 已挂载时不读值:挂载后每敲一个字都会变,追踪它会让整棵字段树跟着重渲
387
+ var liveValue = activated ? undefined : dataKey != null && record ? readByFieldPath(record, dataKey) : value;
388
+ // Editable 装饰器会把非新增行的格转成只读态、不参与校验(见 editable/index.tsx),
389
+ // 这时挂了没用,还会把灰色「请输入」占位换成只读态的「N/A」,所以留在文本态
390
+ var editableWillReadPretty = (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema['x-decorator']) === 'Editable' && (record === null || record === void 0 ? void 0 : record._isNew) !== true;
391
+ if (!activated && required && !editableWillReadPretty && isBlank(liveValue)) {
392
+ var _pattern = resolveLazyCellPattern(field, record, dataKey, fieldSchema, scope);
393
+ if (_pattern == null || _pattern === 'editable') {
394
+ // 记进激活集合:用户填了第一个字后值不再为空,但格子仍在编辑,要挂到失焦为止
395
+ activeCells.add(key);
396
+ activated = true;
397
+ }
398
+ }
399
+ if (activated) {
400
+ return /*#__PURE__*/React.createElement(CellFocusScope, {
401
+ onLeave: handleLeave
402
+ }, /*#__PURE__*/React.createElement(AgField, {
403
+ value: value,
404
+ data: record,
405
+ dataSource: dataSource,
406
+ schema: schema,
407
+ field: field,
408
+ node: node
409
+ }));
410
+ }
289
411
  var text = formatter ? formatter(liveValue, {
290
412
  columnProps: columnProps,
291
413
  fieldSchema: fieldSchema
@@ -396,14 +518,35 @@ var isColumnReadOnlyEligible = function isColumnReadOnlyEligible(arrayPattern, d
396
518
  return false;
397
519
  };
398
520
 
521
+ /** 明细单元格里的数字输入组件(antd InputNumber 及其 Formily 封装) */
522
+ var NUMBER_INPUT_COMPONENTS = new Set(['NumberPicker', 'InputNumber']);
523
+
524
+ /**
525
+ * 明细单元格里的数字输入默认去掉上下步进:不显示上下按钮、不响应方向键步进。
526
+ *
527
+ * 上下按钮会压住右对齐数字的末尾;方向键步进则与单元格间的方向键导航冲突——
528
+ * 在数字格里按 ↑/↓,导航到别的格的同时,被离开的那格数值也被悄悄 +1/-1。
529
+ * 字段的 x-component-props 里显式写了 controls/keyboard 的以使用方为准。
530
+ * 只对会挂真控件的列调用(只读快路径没有输入框)。幂等。@author nokecy
531
+ */
532
+ var applyNumberInputDefaults = function applyNumberInputDefaults(dataField) {
533
+ if (!dataField || !NUMBER_INPUT_COMPONENTS.has(dataField['x-component'])) return;
534
+ var props = dataField['x-component-props'];
535
+ if (props != null && _typeof(props) !== 'object') return; // 整个 props 写成了表达式串,不动
536
+ dataField['x-component-props'] = _objectSpread({
537
+ controls: false,
538
+ keyboard: false
539
+ }, props);
540
+ };
541
+
399
542
  // 重命名自 useArrayTableColumns:内部无任何 Hook 调用,use 前缀违反 Hook 命名约定且曾在 useMemo 内被调用 @author nokecy
400
543
  var buildArrayTableColumns = function buildArrayTableColumns(dataSource, field, sources) {
401
544
  var arrayPattern = field === null || field === void 0 ? void 0 : field.pattern;
402
- return sources.reduce(function (buf, _ref3, key) {
403
- var name = _ref3.name,
404
- columnProps = _ref3.columnProps,
405
- schema = _ref3.schema,
406
- display = _ref3.display;
545
+ return sources.reduce(function (buf, _ref4, key) {
546
+ var name = _ref4.name,
547
+ columnProps = _ref4.columnProps,
548
+ schema = _ref4.schema,
549
+ display = _ref4.display;
407
550
  if (display && display !== 'visible') return buf;
408
551
  if (!isColumnComponent(schema)) return buf;
409
552
 
@@ -438,13 +581,14 @@ var buildArrayTableColumns = function buildArrayTableColumns(dataSource, field,
438
581
  // 三分流渲染策略:@author nokecy
439
582
  // ① 只读纯文本(永不可编辑):只读列 + 有格式化器 -> valueFormatter,不挂 Formily 树。
440
583
  // ② 可编辑懒挂载:可编辑列 + 有格式化器 + 无 reactions + 未强制 eager -> LazyAgField,
441
- // 存量格先出廉价文本、点击/导航才挂全树(挂了不卸)。
584
+ // 格子先出廉价文本、点击/导航(或必填且为空)才挂全树,焦点离开且校验通过再卸回文本。
442
585
  // ③ 兜底全树:其余(无格式化器/带 reactions/forceAgField/复杂字段名/只读但无格式化器) -> AgField。
443
586
  var dataField = findDataFieldSchema(schema, name);
444
587
  var component = dataField === null || dataField === void 0 ? void 0 : dataField['x-component'];
445
588
  var formatter = getReadOnlyFormatter(component);
446
589
  var readOnly = isColumnReadOnlyEligible(arrayPattern, dataField, columnProps);
447
590
  var hasReactions = !!(dataField && dataField['x-reactions']);
591
+ if (!readOnly) applyNumberInputDefaults(dataField);
448
592
  var forceEager = (columnProps === null || columnProps === void 0 ? void 0 : columnProps.forceAgField) === true;
449
593
  // Switch/Checkbox 是「单击直控」组件:可编辑态本就该常驻渲染真控件(优化前即如此)。
450
594
  // 懒挂载会把它降成「是/否」纯文本(点击才挂出开关),用户会以为开关消失。故可编辑态强制 eager。
@@ -507,7 +651,9 @@ var buildArrayTableColumns = function buildArrayTableColumns(dataSource, field,
507
651
  formatter: formatter,
508
652
  columnProps: columnProps,
509
653
  fieldSchema: dataField,
510
- lazyEditable: true // 供 index.tsx 识别懒列(激活/导航用)
654
+ lazyEditable: true,
655
+ // 供 index.tsx 识别懒列(激活/导航用)
656
+ required: isRequiredSchema(dataField) // 必填且为空的格必须挂真控件,见 LazyAgField
511
657
  }
512
658
  }));
513
659
  }