@nokecy/qc-ui 1.1.72 → 1.1.74

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.
Files changed (47) hide show
  1. package/dist/cjs/adapters/pagedApiAdapter.d.ts +2 -0
  2. package/dist/cjs/ag-grid-plus/ag-gridPlus.js +5 -3
  3. package/dist/cjs/ag-grid-plus/interface.d.ts +6 -0
  4. package/dist/cjs/ag-grid-plus/utils/aggregation.d.ts +6 -5
  5. package/dist/cjs/ag-grid-plus/utils/aggregation.js +60 -50
  6. package/dist/cjs/ag-grid-plus/utils/columnProcessors.d.ts +2 -1
  7. package/dist/cjs/ag-grid-plus/utils/columnProcessors.js +5 -2
  8. package/dist/cjs/ag-grid-plus/utils/valueEnumColor.d.ts +17 -0
  9. package/dist/cjs/ag-grid-plus/utils/valueEnumColor.js +99 -0
  10. package/dist/cjs/dialogSelect/index.d.ts +29 -0
  11. package/dist/cjs/dialogSelect/index.js +152 -103
  12. package/dist/cjs/dialogSelect/index.less +39 -0
  13. package/dist/cjs/draggableModal/index.js +12 -8
  14. package/dist/cjs/index.d.ts +5 -0
  15. package/dist/cjs/index.js +123 -1
  16. package/dist/cjs/toolBar/index.d.ts +1 -0
  17. package/dist/cjs/toolBar/index.js +44 -10
  18. package/dist/cjs/toolBar/index.less +25 -7
  19. package/dist/cjs/utils/businessDecimal.d.ts +11 -0
  20. package/dist/cjs/utils/businessDecimal.js +53 -0
  21. package/dist/cjs/utils/contrast.d.ts +40 -0
  22. package/dist/cjs/utils/contrast.js +153 -0
  23. package/dist/esm/adapters/pagedApiAdapter.d.ts +2 -0
  24. package/dist/esm/ag-grid-plus/ag-gridPlus.js +5 -3
  25. package/dist/esm/ag-grid-plus/interface.d.ts +6 -0
  26. package/dist/esm/ag-grid-plus/utils/aggregation.d.ts +6 -5
  27. package/dist/esm/ag-grid-plus/utils/aggregation.js +60 -47
  28. package/dist/esm/ag-grid-plus/utils/columnProcessors.d.ts +2 -1
  29. package/dist/esm/ag-grid-plus/utils/columnProcessors.js +5 -2
  30. package/dist/esm/ag-grid-plus/utils/valueEnumColor.d.ts +17 -0
  31. package/dist/esm/ag-grid-plus/utils/valueEnumColor.js +95 -0
  32. package/dist/esm/dialogSelect/index.d.ts +29 -0
  33. package/dist/esm/dialogSelect/index.js +155 -105
  34. package/dist/esm/dialogSelect/index.less +39 -0
  35. package/dist/esm/draggableModal/index.js +12 -8
  36. package/dist/esm/index.d.ts +5 -0
  37. package/dist/esm/index.js +3 -0
  38. package/dist/esm/toolBar/index.d.ts +1 -0
  39. package/dist/esm/toolBar/index.js +43 -10
  40. package/dist/esm/toolBar/index.less +25 -7
  41. package/dist/esm/utils/businessDecimal.d.ts +11 -0
  42. package/dist/esm/utils/businessDecimal.js +47 -0
  43. package/dist/esm/utils/contrast.d.ts +40 -0
  44. package/dist/esm/utils/contrast.js +141 -0
  45. package/dist/umd/qc-ui.min.css +1 -1
  46. package/dist/umd/qc-ui.min.js +1 -1
  47. package/package.json +2 -1
@@ -9,6 +9,7 @@ import { Typography } from 'antd';
9
9
  import { Select } from '@formily/antd-v5';
10
10
  import { isArray } from 'lodash';
11
11
  import { DEFAULT_SEARCH_SORT_ORDER } from "./constants";
12
+ import { toGridTextColor } from "./valueEnumColor";
12
13
  var Text = Typography.Text;
13
14
 
14
15
  /**
@@ -129,10 +130,11 @@ export function mergeInferredColumnType(column, dataType) {
129
130
  *
130
131
  * @param col 原始列定义
131
132
  * @param dataType 数据类型(决定是否右对齐,见 {@link toColumnType})
133
+ * @param background 单元格底色(hex)。传入则把枚举颜色压/提到够读的对比度;不传则 color 原样输出
132
134
  * @returns 处理后的列定义
133
135
  * @author nokecy
134
136
  */
135
- export function processEnumColumn(col, dataType) {
137
+ export function processEnumColumn(col, dataType, background) {
136
138
  var _defaultItems$0$value, _defaultItems$;
137
139
  var valueEnum = col === null || col === void 0 ? void 0 : col.valueEnum;
138
140
  if (!valueEnum || !Array.isArray(valueEnum)) {
@@ -165,7 +167,8 @@ export function processEnumColumn(col, dataType) {
165
167
  // 没配颜色的枚举项曾经默认成 '#ffffff'——白底白字,那一列直接看不见。
166
168
  // 消费端为此在 global.less 里加了一整套 [style*="color: white"] → 紫色 的覆盖来擦屁股,
167
169
  // 顺带把别的颜色也一起改了。这里改成 inherit,跟着单元格的正文色走。@author nokecy
168
- var color = match.color || 'inherit';
170
+ // 传了 background 才启用对比度适配(AgGridPlus 的 valueEnumContrast);否则 color 按 CSS 原样输出。@author nokecy
171
+ var color = background ? toGridTextColor(match.color, background) : match.color || 'inherit';
169
172
  return /*#__PURE__*/React.createElement("span", {
170
173
  style: {
171
174
  color: color,
@@ -0,0 +1,17 @@
1
+ /** antd Tag 语义档名。 */
2
+ export type SemanticPreset = 'default' | 'processing' | 'success' | 'warning' | 'error';
3
+ /** 语义档名 → 表格文字色(白底实测 ≥4.5:1)。 */
4
+ export declare const semanticTextColors: Record<SemanticPreset, string>;
5
+ /**
6
+ * 把任意 valueEnum.color 收成表格可用的 CSS 色。
7
+ *
8
+ * @param color 枚举项上的 color(语义档、预设名、hex 或缺省)
9
+ * @param background 单元格底色(hex);不传按白底。深色底提亮、浅色底压暗
10
+ */
11
+ export declare const toGridTextColor: (color?: string, background?: string) => string;
12
+ /** 把枚举转成 `valueEnum` 可用的副本(color 一定是当前底色可读的 CSS 色值),不修改源数组。 */
13
+ export declare const gridValueEnum: <T extends {
14
+ color?: string | undefined;
15
+ }>(items: readonly T[], background?: string) => (T & {
16
+ color: string;
17
+ })[];
@@ -0,0 +1,95 @@
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
+ 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; }
3
+ 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; }
4
+ 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; }
5
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
6
+ 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); }
7
+ /**
8
+ * `valueEnum.color` 的表格文字色适配。
9
+ *
10
+ * 同一份状态/类别枚举有两个消费方,对 `color` 的要求不同:
11
+ * - antd `<Tag color>` 接受语义档名(`'success'` / `'warning'` …)和预设色名(`'cyan'`);
12
+ * - AgGridPlus 的 `valueEnum` 把 `color` 直接当 **CSS color** 渲染表格文字。
13
+ *
14
+ * 直接透传会让这几类取值在表格里「字看不见」:语义档名与预设名不是合法 CSS
15
+ * (`'cyan'` 是 `#00ffff`,`'default'` 根本不合法);hex 太浅(`#d9d9d9` 白底 1.3:1、`#52c41a` 2.3:1)。
16
+ * 这里把任意 color 收成当前底色上够读(WCAG 正文 4.5:1)的 CSS 色,缺省/无法解析写成 `inherit`,
17
+ * 跟随单元格正文色。已经够读的 hex 原样返回,所以重复调用是幂等的。
18
+ *
19
+ * 语义档色值经 `contrastRatio` 实测:白底均 ≥4.5:1(green-7/orange-7 只有 3.4~3.6:1,不能想当然)。
20
+ *
21
+ * @author nokecy
22
+ */
23
+ import { contrastRatio, darkenUntilContrast, lightenUntilContrast, relativeLuminance } from "../../utils/contrast";
24
+
25
+ /** antd Tag 语义档名。 */
26
+
27
+ var WHITE = '#ffffff';
28
+
29
+ /** 语义档名 → 表格文字色(白底实测 ≥4.5:1)。 */
30
+ export var semanticTextColors = {
31
+ default: '#595959',
32
+ processing: '#0958d9',
33
+ success: '#237804',
34
+ warning: '#ad4e00',
35
+ error: '#cf1322'
36
+ };
37
+
38
+ /** antd Tag 预设名 / 常见 CSS 色名 → 起始 hex,再交给对比度压色。 */
39
+ var namedColorHex = {
40
+ cyan: '#00ffff',
41
+ aqua: '#00ffff',
42
+ geekblue: '#2f54eb',
43
+ blue: '#0000ff',
44
+ orange: '#ffa500',
45
+ gold: '#ffd700',
46
+ lime: '#00ff00',
47
+ volcano: '#fa541c',
48
+ magenta: '#ff00ff',
49
+ fuchsia: '#ff00ff',
50
+ purple: '#800080',
51
+ red: '#ff0000',
52
+ green: '#008000',
53
+ pink: '#ffc0cb',
54
+ yellow: '#ffff00',
55
+ white: '#ffffff',
56
+ silver: '#c0c0c0'
57
+ };
58
+ var parseHex = function parseHex(color) {
59
+ var raw = color.trim();
60
+ if (!/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(raw)) return undefined;
61
+ return raw.length === 4 ? "#".concat(raw[1]).concat(raw[1]).concat(raw[2]).concat(raw[2]).concat(raw[3]).concat(raw[3]).toLowerCase() : raw.toLowerCase();
62
+ };
63
+
64
+ /** 底色是否为深色表面。 */
65
+ var isDarkSurface = function isDarkSurface(background) {
66
+ return relativeLuminance(background) < 0.18;
67
+ };
68
+
69
+ /**
70
+ * 把任意 valueEnum.color 收成表格可用的 CSS 色。
71
+ *
72
+ * @param color 枚举项上的 color(语义档、预设名、hex 或缺省)
73
+ * @param background 单元格底色(hex);不传按白底。深色底提亮、浅色底压暗
74
+ */
75
+ export var toGridTextColor = function toGridTextColor(color, background) {
76
+ if (!color) return 'inherit';
77
+ var hex = semanticTextColors[color] || namedColorHex[color.toLowerCase()] || parseHex(color);
78
+ if (!hex) return 'inherit';
79
+ var surface = background && parseHex(background) ? background : WHITE;
80
+ if (isDarkSurface(surface)) return lightenUntilContrast(hex, {
81
+ against: surface
82
+ });
83
+ return contrastRatio(hex, surface) >= 4.5 ? hex : darkenUntilContrast(hex, {
84
+ against: surface
85
+ });
86
+ };
87
+
88
+ /** 把枚举转成 `valueEnum` 可用的副本(color 一定是当前底色可读的 CSS 色值),不修改源数组。 */
89
+ export var gridValueEnum = function gridValueEnum(items, background) {
90
+ return items.map(function (item) {
91
+ return _objectSpread(_objectSpread({}, item), {}, {
92
+ color: toGridTextColor(item.color, background)
93
+ });
94
+ });
95
+ };
@@ -2,7 +2,11 @@ import { SelectProps } from 'antd/lib/select';
2
2
  import React from 'react';
3
3
  import { ColDef, ColGroupDef } from 'ag-grid-community';
4
4
  import type { PagedApiAdapter } from '../adapters';
5
+ import './index.less';
6
+ /** 选择窗口的行选择模式。 */
7
+ type DialogSelectionMode = 'single' | 'multiple';
5
8
  interface IDialogSelectProps extends SelectProps<any> {
9
+ /** 隐藏选择窗口入口(输入框内的后缀图标),只保留输入与下拉。 */
6
10
  hideBtn?: boolean;
7
11
  request?: any;
8
12
  columnDefs?: (ColDef | ColGroupDef)[] | null;
@@ -13,6 +17,31 @@ interface IDialogSelectProps extends SelectProps<any> {
13
17
  useAutoComplete?: boolean;
14
18
  /** 分页 API 适配器(默认 ABP)。@author nokecy */
15
19
  pagedApiAdapter?: PagedApiAdapter;
20
+ /** 选择窗口宽度,默认 960。 */
21
+ modalWidth?: number | string;
22
+ /** 选择窗口层级,默认 9999(高于抽屉、其他弹窗)。 */
23
+ dialogZIndex?: number;
24
+ /** 选择窗口中的行选择模式;缺省按 `mode` 推断,外层 Select 仍可保持单值。 */
25
+ dialogMode?: DialogSelectionMode;
26
+ /** 选择窗口表格的初始分页大小;不影响外层 Select。 */
27
+ dialogPageSize?: number;
28
+ /** 选择窗口表格可选分页大小。 */
29
+ dialogPageSizeOptions?: number[];
30
+ /** 选择窗口表格的列方案标识。 */
31
+ dialogGridKey?: string;
32
+ /** 已由业务限定范围的本地候选;传入后不再请求接口,表格直接筛选完整候选集且不分页。 */
33
+ dialogDataSource?: any[];
34
+ /** 业务限制下不可带入的行;单击、确认和双击共用该条件。 */
35
+ dialogIsRowSelectable?: (row: any) => boolean;
36
+ /** 自定义选择窗口内容;确认时回传所选行。传入后不再渲染内置的表格窗口。 */
37
+ dialogRenderer?: (context: {
38
+ open: boolean;
39
+ mode: DialogSelectionMode;
40
+ onCancel: () => void;
41
+ onConfirm: (rows: any[]) => void;
42
+ }) => React.ReactNode;
43
+ /** 选择窗口里使用的表格组件,默认 `AgGridPlus`;宿主可注入自己封装过的表格基座。 */
44
+ gridComponent?: React.ComponentType<any>;
16
45
  }
17
46
  declare const DialogSelect: (props: IDialogSelectProps) => React.JSX.Element;
18
47
  export { IDialogSelectProps };
@@ -1,4 +1,4 @@
1
- var _excluded = ["request", "columnDefs", "value", "labelField", "valueField", "onChangeItem"];
1
+ var _excluded = ["request", "columnDefs", "value", "labelField", "valueField", "onChangeItem", "hideBtn", "useAutoComplete", "queryFun", "pagedApiAdapter", "modalWidth", "dialogZIndex", "dialogMode", "dialogPageSize", "dialogPageSizeOptions", "dialogGridKey", "dialogDataSource", "dialogIsRowSelectable", "dialogRenderer", "gridComponent"];
2
2
  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; }
3
3
  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); } }
4
4
  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); }); }; }
@@ -17,185 +17,235 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
17
17
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
18
18
  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; }
19
19
  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; }
20
- import { Button, AutoComplete } from 'antd';
20
+ import { AutoComplete, theme } from 'antd';
21
21
  import { Select } from '@formily/antd-v5';
22
- import { DashOutlined } from '@ant-design/icons';
22
+ import { SearchOutlined } from '@ant-design/icons';
23
23
  import React, { useState } from 'react';
24
24
  import { AgGridPlus } from "../ag-grid-plus";
25
25
  import { useBoolean, useControllableValue } from 'ahooks';
26
26
  import DraggableModal from "../draggableModal";
27
27
  import { abpPagedApiAdapter } from "../adapters";
28
+ import "./index.less";
29
+
30
+ /** 选择窗口的行选择模式。 */
31
+
28
32
  var DialogSelect = function DialogSelect(props) {
33
+ var _selectRows$length;
34
+ // 这些是本组件自己的属性,不能透传给 Select(否则会落到 DOM 上触发未知属性告警)。
29
35
  var request = props.request,
30
36
  columnDefs = props.columnDefs,
31
37
  value = props.value,
32
38
  labelField = props.labelField,
33
39
  valueField = props.valueField,
34
40
  onChangeItem = props.onChangeItem,
41
+ hideBtn = props.hideBtn,
42
+ useAutoComplete = props.useAutoComplete,
43
+ queryFun = props.queryFun,
44
+ pagedApiAdapter = props.pagedApiAdapter,
45
+ _props$modalWidth = props.modalWidth,
46
+ modalWidth = _props$modalWidth === void 0 ? 960 : _props$modalWidth,
47
+ _props$dialogZIndex = props.dialogZIndex,
48
+ dialogZIndex = _props$dialogZIndex === void 0 ? 9999 : _props$dialogZIndex,
49
+ dialogMode = props.dialogMode,
50
+ dialogPageSize = props.dialogPageSize,
51
+ dialogPageSizeOptions = props.dialogPageSizeOptions,
52
+ dialogGridKey = props.dialogGridKey,
53
+ dialogDataSource = props.dialogDataSource,
54
+ dialogIsRowSelectable = props.dialogIsRowSelectable,
55
+ dialogRenderer = props.dialogRenderer,
56
+ gridComponent = props.gridComponent,
35
57
  rest = _objectWithoutProperties(props, _excluded);
58
+ var Grid = gridComponent !== null && gridComponent !== void 0 ? gridComponent : AgGridPlus;
36
59
  var _useControllableValue = useControllableValue(props),
37
60
  _useControllableValue2 = _slicedToArray(_useControllableValue, 2),
38
61
  state = _useControllableValue2[0],
39
62
  setState = _useControllableValue2[1];
40
- var _useState = useState(),
41
- _useState2 = _slicedToArray(_useState, 2),
42
- gridApi = _useState2[0],
43
- setGridApi = _useState2[1];
44
63
  var _useBoolean = useBoolean(false),
45
64
  _useBoolean2 = _slicedToArray(_useBoolean, 2),
46
65
  visible = _useBoolean2[0],
47
66
  _useBoolean2$ = _useBoolean2[1],
48
67
  setTrue = _useBoolean2$.setTrue,
49
68
  setFalse = _useBoolean2$.setFalse;
50
- var _useState3 = useState(undefined),
51
- _useState4 = _slicedToArray(_useState3, 2),
52
- selectRows = _useState4[0],
53
- setSelectRows = _useState4[1];
54
- var _useState5 = useState([]),
55
- _useState6 = _slicedToArray(_useState5, 2),
56
- items = _useState6[0],
57
- setItems = _useState6[1];
58
- var getValue = function getValue(selectRows) {
59
- var mode = props.mode,
60
- labelInValue = props.labelInValue,
61
- valueField = props.valueField,
62
- labelField = props.labelField;
63
- var selectRow = selectRows[0];
64
- var value = selectRow[valueField !== null && valueField !== void 0 ? valueField : 'id'];
65
- var label = selectRow[labelField !== null && labelField !== void 0 ? labelField : 'name'];
66
- if (props.mode === 'multiple' || props.mode === 'tags') {
67
- return labelInValue ? selectRows.map(function (it) {
69
+ var _useState = useState(undefined),
70
+ _useState2 = _slicedToArray(_useState, 2),
71
+ selectRows = _useState2[0],
72
+ setSelectRows = _useState2[1];
73
+ var _theme$useToken = theme.useToken(),
74
+ token = _theme$useToken.token;
75
+ var isMultipleValue = props.mode === 'multiple' || props.mode === 'tags';
76
+ var selectionMode = dialogMode !== null && dialogMode !== void 0 ? dialogMode : isMultipleValue ? 'multiple' : 'single';
77
+ var key = valueField !== null && valueField !== void 0 ? valueField : 'id';
78
+ var localData = Array.isArray(dialogDataSource);
79
+ var getValue = function getValue(rows) {
80
+ var row = rows[0];
81
+ var labelKey = labelField !== null && labelField !== void 0 ? labelField : 'name';
82
+ if (isMultipleValue) {
83
+ return props.labelInValue ? rows.map(function (it) {
68
84
  return {
69
- value: it[valueField !== null && valueField !== void 0 ? valueField : 'id'],
70
- label: it[labelField !== null && labelField !== void 0 ? labelField : 'name'],
85
+ value: it[key],
86
+ label: it[labelKey],
71
87
  key: it === null || it === void 0 ? void 0 : it.id
72
88
  };
73
- }) : selectRows.map(function (it) {
74
- return it[valueField !== null && valueField !== void 0 ? valueField : 'id'];
89
+ }) : rows.map(function (it) {
90
+ return it[key];
75
91
  });
76
- } else {
77
- return labelInValue ? {
78
- value: value,
79
- label: label
80
- } : value;
81
92
  }
93
+ return props.labelInValue ? {
94
+ value: row[key],
95
+ label: row[labelKey]
96
+ } : row[key];
82
97
  };
83
- var handleOk = function handleOk() {
84
- var selectRow = selectRows[0];
85
- setState(getValue(selectRows));
98
+ var close = function close() {
86
99
  setFalse();
87
- if (onChangeItem) onChangeItem(props.mode ? selectRows : selectRow);
100
+ setSelectRows(undefined);
101
+ };
102
+ var confirmRows = function confirmRows(rows) {
103
+ if (!(rows !== null && rows !== void 0 && rows.length)) return;
104
+ if (dialogIsRowSelectable && rows.some(function (row) {
105
+ return !dialogIsRowSelectable(row);
106
+ })) return;
107
+ setState(getValue(rows));
108
+ close();
109
+ // 回传完整数据行,供调用方回填关联字段。
110
+ onChangeItem === null || onChangeItem === void 0 || onChangeItem(selectionMode === 'multiple' ? rows : rows[0]);
88
111
  };
89
112
  var onSelectionChanged = function onSelectionChanged(e) {
90
- var selectedRows = e.api.getSelectedRows();
91
- setSelectRows(selectedRows);
113
+ setSelectRows(e.api.getSelectedRows());
92
114
  };
93
- return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
94
- style: {
95
- display: 'flex',
96
- flexDirection: 'row'
115
+
116
+ // 入口做成输入框内的后缀图标:不占右侧宽度,禁用/只读时不出现。@author nokecy
117
+ var canOpen = !props.disabled && !hideBtn;
118
+ var trigger = canOpen ? /*#__PURE__*/React.createElement("span", {
119
+ className: "qc-dialog-select-trigger",
120
+ role: "button",
121
+ "aria-label": "\u6253\u5F00\u9009\u62E9\u7A97\u53E3",
122
+ title: "\u9009\u62E9"
123
+ // 阻止冒泡:点图标只开选择窗口,不展开下拉也不抢走输入框焦点。
124
+ ,
125
+ onMouseDown: function onMouseDown(e) {
126
+ e.preventDefault();
127
+ e.stopPropagation();
128
+ },
129
+ onClick: function onClick(e) {
130
+ e.stopPropagation();
131
+ setSelectRows(undefined);
132
+ setTrue();
97
133
  }
98
- }, props.useAutoComplete && !props.labelInValue ? /*#__PURE__*/React.createElement(AutoComplete, _extends({}, rest, {
134
+ }, /*#__PURE__*/React.createElement(SearchOutlined, null)) : undefined;
135
+ var mergedClassName = ['qc-dialog-select', rest.className].filter(Boolean).join(' ');
136
+ var triggerStyle = {
137
+ '--qc-dialog-select-trigger-color': token.colorTextTertiary,
138
+ '--qc-dialog-select-trigger-hover': token.colorPrimary
139
+ };
140
+ var commonProps = _objectSpread(_objectSpread({}, rest), {}, {
141
+ className: mergedClassName,
99
142
  value: state,
100
- style: _objectSpread(_objectSpread({}, rest === null || rest === void 0 ? void 0 : rest.style), {}, {
101
- width: "calc(100% - 0px)",
102
- marginRight: !props.hideBtn ? 5 : 0
103
- })
104
- })) : /*#__PURE__*/React.createElement(Select, _extends({
143
+ style: _objectSpread(_objectSpread({}, triggerStyle), rest.style || {})
144
+ }, trigger ? {
145
+ suffixIcon: trigger
146
+ } : {});
147
+ return /*#__PURE__*/React.createElement(React.Fragment, null, useAutoComplete && !props.labelInValue ? /*#__PURE__*/React.createElement(AutoComplete, commonProps) : /*#__PURE__*/React.createElement(Select, _extends({
105
148
  maxTagCount: 'responsive',
106
149
  filterOption: false
107
- }, rest, {
108
- value: state,
109
- style: _objectSpread({
110
- width: "calc(100% - 0px)",
111
- marginRight: !props.hideBtn ? 5 : 0
112
- }, rest.style || {})
113
- })), !props.disabled && !props.hideBtn ? /*#__PURE__*/React.createElement(Button, {
114
- icon: /*#__PURE__*/React.createElement(DashOutlined, null),
115
- onClick: function onClick() {
116
- setTrue();
117
- },
118
- disabled: rest.disabled
119
- }) : null), /*#__PURE__*/React.createElement(DraggableModal, {
120
- width: 960,
150
+ }, commonProps)), dialogRenderer ? dialogRenderer({
151
+ open: visible,
152
+ mode: selectionMode,
153
+ onCancel: close,
154
+ onConfirm: confirmRows
155
+ }) : /*#__PURE__*/React.createElement(DraggableModal, {
156
+ width: modalWidth,
121
157
  title: "\u9009\u62E9",
122
- style: {
123
- zIndex: 9999
124
- },
158
+ zIndex: dialogZIndex,
125
159
  destroyOnClose: true,
126
160
  open: visible,
127
- onOk: handleOk,
128
- onCancel: setFalse
129
- }, /*#__PURE__*/React.createElement(AgGridPlus, {
161
+ onOk: function onOk() {
162
+ return confirmRows(selectRows || []);
163
+ },
164
+ onCancel: close,
165
+ okButtonProps: {
166
+ disabled: !(selectRows !== null && selectRows !== void 0 && selectRows.length)
167
+ }
168
+ }, selectionMode === 'multiple' && /*#__PURE__*/React.createElement("div", {
169
+ style: {
170
+ marginBottom: 8,
171
+ textAlign: 'right'
172
+ }
173
+ }, "\u5DF2\u9009 ", (_selectRows$length = selectRows === null || selectRows === void 0 ? void 0 : selectRows.length) !== null && _selectRows$length !== void 0 ? _selectRows$length : 0, " \u9879"), /*#__PURE__*/React.createElement(Grid, _extends({
174
+ gridKey: dialogGridKey,
175
+ dataSource: dialogDataSource,
176
+ hidePagination: localData
177
+ }, localData ? {
178
+ getRowId: function getRowId(_ref) {
179
+ var data = _ref.data;
180
+ return String(data[key]);
181
+ }
182
+ } : {}, {
130
183
  style: {
131
184
  height: 450
132
185
  },
133
- onGridReady: function onGridReady(gridReadEvent) {
134
- setGridApi(gridReadEvent.api);
135
- },
136
- onFirstDataRendered: function onFirstDataRendered(_ref) {
137
- var api = _ref.api;
138
- // 多选时重开弹窗要把已经选中的行勾回来,否则用户会以为之前的选择丢了。
186
+ pageSize: dialogPageSize,
187
+ pageSizeOptions: dialogPageSizeOptions,
188
+ onFirstDataRendered: function onFirstDataRendered(_ref2) {
189
+ var api = _ref2.api;
190
+ // 重开弹窗要把已经选中的行勾回来,否则用户会以为之前的选择丢了。
139
191
  // 放在首屏数据渲染完成时做:弹窗是 destroyOnClose,打开的那一刻表格还没有数据。@author nokecy
140
- if (!Array.isArray(state) || state.length === 0) return;
141
- var key = valueField !== null && valueField !== void 0 ? valueField : 'id';
142
- var selected = state.map(function (it) {
192
+ var current = Array.isArray(state) ? state : state == null ? [] : [state];
193
+ var selected = current.map(function (it) {
143
194
  return it && _typeof(it) === 'object' ? it.value : it;
144
195
  });
196
+ if (!selected.length) return;
145
197
  api.forEachNode(function (node) {
146
- if (node.data && selected.includes(node.data[key])) {
147
- node.setSelected(true);
148
- }
198
+ if (node.data && selected.includes(node.data[key])) node.setSelected(true);
149
199
  });
150
200
  },
151
- search: (columnDefs === null || columnDefs === void 0 ? void 0 : columnDefs.filter(function (i) {
201
+ search: !localData && (columnDefs === null || columnDefs === void 0 ? void 0 : columnDefs.filter(function (i) {
152
202
  return !i.hideInSearch;
153
203
  }).length) !== 0,
154
204
  onSelectionChanged: onSelectionChanged,
155
- rowSelection: props.mode === 'multiple' ? props.mode : 'single',
156
- onRowDoubleClicked: function onRowDoubleClicked(_ref2) {
157
- var data = _ref2.data;
158
- setFalse();
159
- setState(getValue([data]));
160
- // 回传完整数据行:原来这里硬编码成 { label: data.name, value: data.code },
161
- // 与「确定」按钮走的 handleOk 口径不一致,且对没有 name/code 字段的实体直接取到 undefined。@author nokecy
162
- if (onChangeItem) onChangeItem(props.mode === 'multiple' ? [data] : data);
205
+ rowSelection: dialogIsRowSelectable ? {
206
+ mode: selectionMode === 'multiple' ? 'multiRow' : 'singleRow',
207
+ isRowSelectable: function isRowSelectable(node) {
208
+ return !!node.data && dialogIsRowSelectable(node.data);
209
+ }
210
+ } : selectionMode === 'multiple' ? 'multiple' : 'single',
211
+ onRowDoubleClicked: function onRowDoubleClicked(_ref3) {
212
+ var data = _ref3.data;
213
+ if (dialogIsRowSelectable && !dialogIsRowSelectable(data)) return;
214
+ confirmRows([data]);
163
215
  },
164
- request: ( /*#__PURE__*/function () {
165
- var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(params, _, record) {
166
- var _props$pagedApiAdapte;
167
- var adapter, data, requestData;
216
+ request: localData ? undefined : ( /*#__PURE__*/function () {
217
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(params, _, record) {
218
+ var adapter, data;
168
219
  return _regeneratorRuntime().wrap(function _callee$(_context) {
169
220
  while (1) switch (_context.prev = _context.next) {
170
221
  case 0:
171
- adapter = (_props$pagedApiAdapte = props.pagedApiAdapter) !== null && _props$pagedApiAdapte !== void 0 ? _props$pagedApiAdapte : abpPagedApiAdapter;
222
+ adapter = pagedApiAdapter !== null && pagedApiAdapter !== void 0 ? pagedApiAdapter : abpPagedApiAdapter;
172
223
  _context.next = 3;
173
224
  return request(adapter.toRequest({
174
- filter: props !== null && props !== void 0 && props.queryFun ? props === null || props === void 0 ? void 0 : props.queryFun(params === null || params === void 0 ? void 0 : params.filter) : params === null || params === void 0 ? void 0 : params.filter,
225
+ filter: queryFun ? queryFun(params === null || params === void 0 ? void 0 : params.filter) : params === null || params === void 0 ? void 0 : params.filter,
175
226
  sorter: params === null || params === void 0 ? void 0 : params.sorter,
176
227
  skipCount: params === null || params === void 0 ? void 0 : params.skipCount,
177
- maxResultCount: params === null || params === void 0 ? void 0 : params.maxResultCount
228
+ maxResultCount: params === null || params === void 0 ? void 0 : params.maxResultCount,
229
+ record: record
178
230
  }), record);
179
231
  case 3:
180
232
  data = _context.sent;
181
- requestData = {
233
+ return _context.abrupt("return", {
182
234
  success: true,
183
235
  data: adapter.getItems(data),
184
236
  total: adapter.getTotal(data)
185
- };
186
- setItems(adapter.getItems(data));
187
- return _context.abrupt("return", requestData);
188
- case 7:
237
+ });
238
+ case 5:
189
239
  case "end":
190
240
  return _context.stop();
191
241
  }
192
242
  }, _callee);
193
243
  }));
194
244
  return function (_x, _x2, _x3) {
195
- return _ref3.apply(this, arguments);
245
+ return _ref4.apply(this, arguments);
196
246
  };
197
247
  }()),
198
248
  columnDefs: columnDefs
199
- })));
249
+ }))));
200
250
  };
201
251
  export default DialogSelect;
@@ -0,0 +1,39 @@
1
+ // 选择窗口入口放在输入框内部(后缀图标),不再在右侧另占一个按钮的宽度。@author nokecy
2
+ .qc-dialog-select {
3
+ width: 100%;
4
+
5
+ // 后缀图标可点;antd 默认给后缀 pointer-events: none。
6
+ .qc-dialog-select-trigger {
7
+ display: inline-flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ width: 100%;
11
+ height: 100%;
12
+ cursor: pointer;
13
+ pointer-events: auto;
14
+ color: var(--qc-dialog-select-trigger-color, rgba(0, 0, 0, 0.45));
15
+ transition: color 0.2s;
16
+
17
+ &:hover {
18
+ color: var(--qc-dialog-select-trigger-hover, #1677ff);
19
+ }
20
+ }
21
+
22
+ // 悬停时 antd 会把后缀淡出、换成清除图标;这里让入口始终可见,清除图标左移一格并排。
23
+ &.ant-select.ant-select:hover .ant-select-arrow:not(:last-child) {
24
+ opacity: 1;
25
+ }
26
+
27
+ &.ant-select-allow-clear .ant-select-clear {
28
+ inset-inline-end: 31px;
29
+ }
30
+
31
+ &.ant-select-allow-clear .ant-select-selection-item,
32
+ &.ant-select-allow-clear .ant-select-selection-placeholder {
33
+ padding-inline-end: 36px;
34
+ }
35
+
36
+ &.ant-select-multiple .ant-select-selector {
37
+ padding-inline-end: 38px;
38
+ }
39
+ }
@@ -67,14 +67,18 @@ var DraggableModal = function DraggableModal(props) {
67
67
  // 修复 AgGrid 等组件在 Modal 中高度不展开的问题
68
68
  // 当 Modal 打开时触发 window resize 事件
69
69
  useEffect(function () {
70
- if (open) {
71
- // 使用 requestAnimationFrame 和 setTimeout 确保 DOM 完全渲染
72
- requestAnimationFrame(function () {
73
- setTimeout(function () {
74
- window.dispatchEvent(new Event('resize'));
75
- }, 100);
76
- });
77
- }
70
+ if (!open) return;
71
+ // 使用 requestAnimationFrame 和 setTimeout 确保 DOM 完全渲染;卸载或关闭时取消,避免对已销毁的环境派发事件
72
+ var timer;
73
+ var frame = requestAnimationFrame(function () {
74
+ timer = setTimeout(function () {
75
+ window.dispatchEvent(new Event('resize'));
76
+ }, 100);
77
+ });
78
+ return function () {
79
+ cancelAnimationFrame(frame);
80
+ if (timer !== undefined) clearTimeout(timer);
81
+ };
78
82
  }, [open]);
79
83
  var _onStart = function onStart(_event, uiData) {
80
84
  var _draggleRef$current;
@@ -31,4 +31,9 @@ export type * from "./RuleBuilder";
31
31
  export type { ColumnConfig } from "./array-table/columnHelper";
32
32
  export type { CentralizedColumnScheme, QueryScheme, SchemeStorageAdapter, SchemeSyncDataDto, CurrentSchemeDto, SchemeStorageConfig, LocalStorageAdapterConfig, BackendApiAdapterConfig, UseSchemeManagerConfig, GridPlusContextValue, GlobalConfigPermissions, } from "./ag-grid-plus";
33
33
  export * from './adapters';
34
+ export { semanticTextColors, toGridTextColor, gridValueEnum } from "./ag-grid-plus/utils/valueEnumColor";
35
+ export type { SemanticPreset } from "./ag-grid-plus/utils/valueEnumColor";
36
+ export { contrastRatio, relativeLuminance, darkenUntilContrast, lightenUntilContrast, toRgb, toHsl, fromHsl } from "./utils/contrast";
37
+ export { BusinessDecimal, decimal, decimalText, nonNegativeDecimal, roundDecimal, sumDecimals, formatDecimal } from "./utils/businessDecimal";
38
+ export type { DecimalValue } from "./utils/businessDecimal";
34
39
  export type { ParseResult as RegexParseResult, ValidationResult as RegexValidationResult, RegexError, ComplexityMetrics, ASTNode, AstRegExp, RegexTemplate, TestResult as RegexTestResult, CodeMirrorWrapperProps, RegexEditorProps, RegexFlags, MatchResult, RegexTesterProps, FlagsSelectorProps, MatchItemProps, RegexRailroadDiagramProps, } from "./components/RegexEditor";