@hi-ui/schema-fields 4.0.0-experimental.1

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 (139) hide show
  1. package/README.md +11 -0
  2. package/lib/cjs/base.js +125 -0
  3. package/lib/cjs/components/image-preview/index.js +63 -0
  4. package/lib/cjs/components/span/index.js +33 -0
  5. package/lib/cjs/components/upload-bridge/index.js +227 -0
  6. package/lib/cjs/components/upload-bridge/utils.js +73 -0
  7. package/lib/cjs/ctx.js +70 -0
  8. package/lib/cjs/editable/ctx.js +45 -0
  9. package/lib/cjs/editable/editable.js +141 -0
  10. package/lib/cjs/editable/index.js +62 -0
  11. package/lib/cjs/editable/readonly.js +36 -0
  12. package/lib/cjs/editable/simple.js +61 -0
  13. package/lib/cjs/editable/use-readonly.js +200 -0
  14. package/lib/cjs/extensible/selectable/index.js +114 -0
  15. package/lib/cjs/extensible/selectable/match-cascader.js +184 -0
  16. package/lib/cjs/fields/basic/cascader/index.js +98 -0
  17. package/lib/cjs/fields/basic/check-cascader/index.js +58 -0
  18. package/lib/cjs/fields/basic/check-select/index.js +89 -0
  19. package/lib/cjs/fields/basic/check-tree-select/index.js +61 -0
  20. package/lib/cjs/fields/basic/checkbox/index.js +84 -0
  21. package/lib/cjs/fields/basic/counter/index.js +40 -0
  22. package/lib/cjs/fields/basic/radio/index.js +44 -0
  23. package/lib/cjs/fields/basic/rating/index.js +40 -0
  24. package/lib/cjs/fields/basic/select/index.js +98 -0
  25. package/lib/cjs/fields/basic/slider/index.js +40 -0
  26. package/lib/cjs/fields/basic/switch/index.js +47 -0
  27. package/lib/cjs/fields/basic/textarea/index.js +40 -0
  28. package/lib/cjs/fields/basic/time-picker/index.js +45 -0
  29. package/lib/cjs/fields/basic/time-picker/index.scss.js +18 -0
  30. package/lib/cjs/fields/basic/tree-select/index.js +61 -0
  31. package/lib/cjs/fields/basic/upload/custom.js +29 -0
  32. package/lib/cjs/fields/basic/upload/index.js +48 -0
  33. package/lib/cjs/fields/enhance/number-range/index.js +39 -0
  34. package/lib/cjs/fields/semantic/date/index.js +82 -0
  35. package/lib/cjs/fields/semantic/image/index.js +65 -0
  36. package/lib/cjs/fields/semantic/image/upload.js +32 -0
  37. package/lib/cjs/fields/semantic/link/index.js +96 -0
  38. package/lib/cjs/fields/semantic/number/index.js +106 -0
  39. package/lib/cjs/fields/semantic/tag/index.js +164 -0
  40. package/lib/cjs/fields/semantic/tag/index.scss.js +18 -0
  41. package/lib/cjs/fields/semantic/text/index.js +61 -0
  42. package/lib/cjs/index.js +145 -0
  43. package/lib/cjs/utils/batch-dep-update.js +40 -0
  44. package/lib/cjs/utils/form-binding.js +40 -0
  45. package/lib/cjs/utils/label.js +34 -0
  46. package/lib/cjs/utils.js +35 -0
  47. package/lib/esm/base.js +111 -0
  48. package/lib/esm/components/image-preview/index.js +49 -0
  49. package/lib/esm/components/span/index.js +20 -0
  50. package/lib/esm/components/upload-bridge/index.js +214 -0
  51. package/lib/esm/components/upload-bridge/utils.js +66 -0
  52. package/lib/esm/ctx.js +55 -0
  53. package/lib/esm/editable/ctx.js +32 -0
  54. package/lib/esm/editable/editable.js +129 -0
  55. package/lib/esm/editable/index.js +44 -0
  56. package/lib/esm/editable/readonly.js +24 -0
  57. package/lib/esm/editable/simple.js +49 -0
  58. package/lib/esm/editable/use-readonly.js +193 -0
  59. package/lib/esm/extensible/selectable/index.js +101 -0
  60. package/lib/esm/extensible/selectable/match-cascader.js +179 -0
  61. package/lib/esm/fields/basic/cascader/index.js +83 -0
  62. package/lib/esm/fields/basic/check-cascader/index.js +44 -0
  63. package/lib/esm/fields/basic/check-select/index.js +75 -0
  64. package/lib/esm/fields/basic/check-tree-select/index.js +47 -0
  65. package/lib/esm/fields/basic/checkbox/index.js +70 -0
  66. package/lib/esm/fields/basic/counter/index.js +26 -0
  67. package/lib/esm/fields/basic/radio/index.js +30 -0
  68. package/lib/esm/fields/basic/rating/index.js +26 -0
  69. package/lib/esm/fields/basic/select/index.js +83 -0
  70. package/lib/esm/fields/basic/slider/index.js +26 -0
  71. package/lib/esm/fields/basic/switch/index.js +33 -0
  72. package/lib/esm/fields/basic/textarea/index.js +26 -0
  73. package/lib/esm/fields/basic/time-picker/index.js +31 -0
  74. package/lib/esm/fields/basic/time-picker/index.scss.js +13 -0
  75. package/lib/esm/fields/basic/tree-select/index.js +47 -0
  76. package/lib/esm/fields/basic/upload/custom.js +16 -0
  77. package/lib/esm/fields/basic/upload/index.js +34 -0
  78. package/lib/esm/fields/enhance/number-range/index.js +26 -0
  79. package/lib/esm/fields/semantic/date/index.js +67 -0
  80. package/lib/esm/fields/semantic/image/index.js +51 -0
  81. package/lib/esm/fields/semantic/image/upload.js +20 -0
  82. package/lib/esm/fields/semantic/link/index.js +82 -0
  83. package/lib/esm/fields/semantic/number/index.js +91 -0
  84. package/lib/esm/fields/semantic/tag/index.js +149 -0
  85. package/lib/esm/fields/semantic/tag/index.scss.js +13 -0
  86. package/lib/esm/fields/semantic/text/index.js +47 -0
  87. package/lib/esm/index.js +85 -0
  88. package/lib/esm/utils/batch-dep-update.js +35 -0
  89. package/lib/esm/utils/form-binding.js +34 -0
  90. package/lib/esm/utils/label.js +21 -0
  91. package/lib/esm/utils.js +27 -0
  92. package/lib/types/base.d.ts +44 -0
  93. package/lib/types/components/async-refill-placeholder/index.d.ts +7 -0
  94. package/lib/types/components/image-preview/index.d.ts +5 -0
  95. package/lib/types/components/span/index.d.ts +8 -0
  96. package/lib/types/components/upload-bridge/index.d.ts +5 -0
  97. package/lib/types/components/upload-bridge/type.d.ts +26 -0
  98. package/lib/types/components/upload-bridge/utils.d.ts +11 -0
  99. package/lib/types/ctx.d.ts +21 -0
  100. package/lib/types/editable/ctx.d.ts +5 -0
  101. package/lib/types/editable/editable.d.ts +18 -0
  102. package/lib/types/editable/index.d.ts +14 -0
  103. package/lib/types/editable/readonly.d.ts +8 -0
  104. package/lib/types/editable/simple.d.ts +8 -0
  105. package/lib/types/editable/type.d.ts +9 -0
  106. package/lib/types/editable/use-readonly.d.ts +26 -0
  107. package/lib/types/extensible/selectable/index.d.ts +31 -0
  108. package/lib/types/extensible/selectable/match-cascader.d.ts +19 -0
  109. package/lib/types/extensible/selectable/type.d.ts +16 -0
  110. package/lib/types/fields/basic/cascader/index.d.ts +10 -0
  111. package/lib/types/fields/basic/check-cascader/index.d.ts +11 -0
  112. package/lib/types/fields/basic/check-select/index.d.ts +34 -0
  113. package/lib/types/fields/basic/check-tree-select/index.d.ts +10 -0
  114. package/lib/types/fields/basic/checkbox/index.d.ts +19 -0
  115. package/lib/types/fields/basic/counter/index.d.ts +7 -0
  116. package/lib/types/fields/basic/radio/index.d.ts +7 -0
  117. package/lib/types/fields/basic/rating/index.d.ts +7 -0
  118. package/lib/types/fields/basic/select/index.d.ts +12 -0
  119. package/lib/types/fields/basic/slider/index.d.ts +7 -0
  120. package/lib/types/fields/basic/switch/index.d.ts +7 -0
  121. package/lib/types/fields/basic/textarea/index.d.ts +7 -0
  122. package/lib/types/fields/basic/time-picker/index.d.ts +8 -0
  123. package/lib/types/fields/basic/tree-select/index.d.ts +11 -0
  124. package/lib/types/fields/basic/upload/custom.d.ts +3 -0
  125. package/lib/types/fields/basic/upload/index.d.ts +8 -0
  126. package/lib/types/fields/enhance/number-range/index.d.ts +7 -0
  127. package/lib/types/fields/semantic/date/index.d.ts +15 -0
  128. package/lib/types/fields/semantic/image/index.d.ts +11 -0
  129. package/lib/types/fields/semantic/image/upload.d.ts +3 -0
  130. package/lib/types/fields/semantic/link/index.d.ts +31 -0
  131. package/lib/types/fields/semantic/number/index.d.ts +21 -0
  132. package/lib/types/fields/semantic/tag/index.d.ts +78 -0
  133. package/lib/types/fields/semantic/text/index.d.ts +13 -0
  134. package/lib/types/index.d.ts +108 -0
  135. package/lib/types/utils/batch-dep-update.d.ts +13 -0
  136. package/lib/types/utils/form-binding.d.ts +11 -0
  137. package/lib/types/utils/label.d.ts +11 -0
  138. package/lib/types/utils.d.ts +15 -0
  139. package/package.json +98 -0
@@ -0,0 +1,141 @@
1
+ /** @LICENSE
2
+ * @hi-ui/schema-fields
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/schema/schema-fields#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var React = require('react');
17
+ var classname = require('@hi-ui/classname');
18
+ var schemaUtils = require('@hi-ui/schema-utils');
19
+ function _interopDefaultCompat(e) {
20
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
21
+ 'default': e
22
+ };
23
+ }
24
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
25
+ function EditableCase(props) {
26
+ var _a, _b, _c;
27
+ var field = props.field,
28
+ ctx = props.ctx,
29
+ value = props.value;
30
+ var fieldRenderer = new props.FieldClass();
31
+ // 控制是否显示实际的表单组件
32
+ var _useState = React.useState(function () {
33
+ return props.defaultActive || false;
34
+ }),
35
+ isActive = _useState[0],
36
+ _setIsActive = _useState[1];
37
+ // 启用 defaultActive 时,isActive始终为 true
38
+ var setIsActive = function setIsActive(value) {
39
+ return _setIsActive(props.defaultActive || value);
40
+ };
41
+ var handleActivate = function handleActivate() {
42
+ setIsActive(true);
43
+ };
44
+ var handleBlur = function handleBlur(event) {
45
+ // 如果配置了失焦时保持激活状态,则直接跳过
46
+ if (props.keepActiveOnBlur) return;
47
+ if (!event) return;
48
+ var currentTarget = event.currentTarget,
49
+ relatedTarget = event.relatedTarget;
50
+ // 检查是否在当前容器内
51
+ if (relatedTarget && currentTarget.contains(relatedTarget)) return;
52
+ // // 检查是否在HiUI的Portal中
53
+ if (relatedTarget instanceof Element) {
54
+ var portalElement = relatedTarget.closest("[class^=\"" + classname.getPrefixCls('portal') + "-\"]");
55
+ if (portalElement) return;
56
+ }
57
+ // 延迟一小会儿再设置为非激活状态
58
+ // 避免在失焦时,订阅状态还没有更新,导致只读的文本闪烁
59
+ schemaUtils.Schedular.nextMacro(function () {
60
+ setIsActive(false);
61
+ }, 20); // 20*16 = 320ms // 是个经验值,不合适可以修改
62
+ };
63
+ // 可编辑但未激活时显示占位 Input
64
+ if (!isActive) {
65
+ var editableCtx = {
66
+ field: field,
67
+ rowData: ctx.rowData,
68
+ rawData: ctx.rawData,
69
+ formBinding: ctx.formBinding,
70
+ formRef: ctx.formRef,
71
+ onActivate: handleActivate,
72
+ onDeactivate: handleBlur,
73
+ rowIndex: ctx.rowIndex,
74
+ dataKey: ctx.dataKey
75
+ };
76
+ var renderEditable = ((_a = field.renderer) === null || _a === void 0 ? void 0 : _a.renderEditable) ||
77
+ // renderEditable
78
+ fieldRenderer.renderEditable.bind(fieldRenderer);
79
+ var dom = renderEditable(value, editableCtx);
80
+ var enhancedRenderers = (_b = field.extra) === null || _b === void 0 ? void 0 : _b.enhancedRenderers;
81
+ if (enhancedRenderers === null || enhancedRenderers === void 0 ? void 0 : enhancedRenderers.renderEditable) {
82
+ var finalDom = enhancedRenderers.renderEditable(dom, {
83
+ data: value,
84
+ render: fieldRenderer,
85
+ renderCtx: editableCtx
86
+ });
87
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, finalDom);
88
+ }
89
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, renderEditable(value, editableCtx));
90
+ }
91
+ // TODO 这里打个补丁,待后续表格支持全局的焦点管理能力后移除
92
+ // 单选和单选级联在值变化时,直接触发失焦
93
+ var patchedOnBlur = function patchedOnBlur() {
94
+ var _b2;
95
+ var _a, _b;
96
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
97
+ args[_key] = arguments[_key];
98
+ }
99
+ if (field.valueType === 'select' || field.valueType === 'cascader') {
100
+ handleBlur.apply(void 0, args);
101
+ }
102
+ (_b = (_a = ctx.formBinding).onBlur) === null || _b === void 0 ? void 0 : (_b2 = _b).call.apply(_b2, [_a].concat(args));
103
+ };
104
+ var nextCtx = Object.assign(Object.assign({}, ctx), {
105
+ formBinding: Object.assign(Object.assign({}, ctx.formBinding), {
106
+ onBlur: patchedOnBlur
107
+ })
108
+ });
109
+ // 激活编辑态时显示实际的表单组件
110
+ var renderFormItem = ((_c = field.renderer) === null || _c === void 0 ? void 0 : _c.renderFormItem) ||
111
+ // renderFormItem
112
+ fieldRenderer.renderFormItem.bind(fieldRenderer);
113
+ return /*#__PURE__*/React__default["default"].createElement("div", {
114
+ "data-case": "editing",
115
+ onBlur: handleBlur
116
+ }, renderFormItem(null, nextCtx));
117
+ }
118
+ // 实测不处理这个失焦问题,体验反而更好
119
+ // 把处理的逻辑留在这里,如有需要再考虑启用吧
120
+ // export function EditableCase(props: EditableCaseProps) {
121
+ // // ~~一个已知问题是,表单项的组件需要彻底激活后失焦,才会触发 onBlur
122
+ // // ~~如果仅仅是聚焦到占位元素,进入active 状态,但不使用表单项,就无法正确回到 unActive 状态
123
+ // // ~~也就会一直处于 active 状态,渲染真实的表单项
124
+ // // 下面一段代码用来解决这个问题 ↑↑↑↑↑
125
+ // const editingWrapperRef = React.useRef<HTMLDivElement>(null)
126
+ // React.useEffect(() => {
127
+ // if (isActive && editingWrapperRef.current) {
128
+ // editingWrapperRef.current.focus()
129
+ // }
130
+ // }, [isActive])
131
+ // // 激活编辑态时显示实际的表单组件
132
+ // return (
133
+ // <div
134
+ // // 下面两个属性允许 div 获取焦点
135
+ // ref={editingWrapperRef}
136
+ // tabIndex={-1} // 只能通过代码(focus()方法)聚焦,不能通过Tab键聚焦
137
+ // ></div>
138
+ // )
139
+ // }
140
+
141
+ exports.EditableCase = EditableCase;
@@ -0,0 +1,62 @@
1
+ /** @LICENSE
2
+ * @hi-ui/schema-fields
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/schema/schema-fields#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var React = require('react');
17
+ var ctx$1 = require('../ctx.js');
18
+ var useReadonly = require('./use-readonly.js');
19
+ var simple = require('./simple.js');
20
+ var readonly = require('./readonly.js');
21
+ var editable = require('./editable.js');
22
+ function _interopDefaultCompat(e) {
23
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
24
+ 'default': e
25
+ };
26
+ }
27
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
28
+ function EditableField(props) {
29
+ var field = props.field,
30
+ ctx = props.ctx,
31
+ value = props.value,
32
+ _props$usedBy = props.usedBy,
33
+ usedBy = _props$usedBy === void 0 ? 'other' : _props$usedBy;
34
+ // 获取字段渲染器
35
+ var FieldClass = ctx$1.useMatchFieldClass({
36
+ name: 'EditableFieldWrapper',
37
+ field: field,
38
+ fieldMap: props.fieldMap
39
+ });
40
+ var readonly$1 = useReadonly.useReadonly(field, props.runtimeEditable);
41
+ // 简单字段且无自定义渲染,使用 SimpleCase
42
+ if (simple.isSimpleCase(field)) return /*#__PURE__*/React__default["default"].createElement(simple.SimpleCase, {
43
+ value: value
44
+ });
45
+ var passedProps = {
46
+ field: field,
47
+ ctx: ctx,
48
+ value: value,
49
+ FieldClass: FieldClass
50
+ };
51
+ if (readonly$1) return /*#__PURE__*/React__default["default"].createElement(readonly.ReadonlyCase, Object.assign({}, passedProps, {
52
+ usedBy: usedBy
53
+ }));else return /*#__PURE__*/React__default["default"].createElement(editable.EditableCase, Object.assign({}, passedProps));
54
+ }
55
+ exports.isReadonly = useReadonly.isReadonly;
56
+ exports.runDynamicEditable = useReadonly.runDynamicEditable;
57
+ exports.useReadonly = useReadonly.useReadonly;
58
+ exports.SimpleCase = simple.SimpleCase;
59
+ exports.isSimpleCase = simple.isSimpleCase;
60
+ exports.ReadonlyCase = readonly.ReadonlyCase;
61
+ exports.EditableCase = editable.EditableCase;
62
+ exports.EditableField = EditableField;
@@ -0,0 +1,36 @@
1
+ /** @LICENSE
2
+ * @hi-ui/schema-fields
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/schema/schema-fields#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var React = require('react');
17
+ function _interopDefaultCompat(e) {
18
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
19
+ 'default': e
20
+ };
21
+ }
22
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
23
+ function ReadonlyCase(props) {
24
+ var _a, _b, _c;
25
+ var field = props.field,
26
+ ctx = props.ctx,
27
+ value = props.value,
28
+ _props$usedBy = props.usedBy,
29
+ usedBy = _props$usedBy === void 0 ? 'other' : _props$usedBy;
30
+ var fieldRenderer = new props.FieldClass();
31
+ // 只读态时直接渲染只读视图
32
+ // 此处实际上是 render | renderCell 的联合类型,收敛至 render 类型,避免 Any 缺少检查
33
+ var render = usedBy === 'table' ? ((_a = field.renderer) === null || _a === void 0 ? void 0 : _a.renderCell) || ((_b = field.renderer) === null || _b === void 0 ? void 0 : _b.render) || fieldRenderer.renderCell.bind(fieldRenderer) : ((_c = field.renderer) === null || _c === void 0 ? void 0 : _c.render) || fieldRenderer.render.bind(fieldRenderer);
34
+ return /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, render(value, ctx));
35
+ }
36
+ exports.ReadonlyCase = ReadonlyCase;
@@ -0,0 +1,61 @@
1
+ /** @LICENSE
2
+ * @hi-ui/schema-fields
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/schema/schema-fields#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var React = require('react');
17
+ function _interopDefaultCompat(e) {
18
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
19
+ 'default': e
20
+ };
21
+ }
22
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
23
+
24
+ /**
25
+ * 简单字段且无自定义渲染,使用 SimpleCase
26
+ */
27
+ function isSimpleCase(field) {
28
+ var _a;
29
+ var customRender = field === null || field === void 0 ? void 0 : field.renderer;
30
+ if ((customRender === null || customRender === void 0 ? void 0 : customRender.renderCell) || (customRender === null || customRender === void 0 ? void 0 : customRender.render)) return false;
31
+ return (_a = field.control) === null || _a === void 0 ? void 0 : _a.simple;
32
+ }
33
+ function SimpleCase(props) {
34
+ var value = props.value;
35
+ // NOTE:此处 SimpleCase 的结构和样式说明
36
+ // 简单场景时,实际上可以使用 :not(:has(*)) 来直接选中这种仅包含文本的单元格
37
+ // 但是 :not(:has(*)) 的兼容性不好,所以此处使用 span[data-case='simple'] 来选中
38
+ // 若后续 :has 的兼容性提升,则可以考虑删除此处的 span 标签,进一步降低渲染成本
39
+ // 此处注释在样式位置中也有相同的一份~
40
+ if (value === undefined || value === null || value === '') return /*#__PURE__*/React__default["default"].createElement("span", {
41
+ "data-case": "simple"
42
+ }, "-");
43
+ // 如果 value 是对象,则直接显示 JSON 字符串
44
+ if (_typeof(value) === 'object') {
45
+ try {
46
+ return /*#__PURE__*/React__default["default"].createElement("span", {
47
+ "data-case": "simple"
48
+ }, JSON.stringify(value));
49
+ } catch (error) {
50
+ console.error('SimpleCase Failed to stringify object', error);
51
+ return /*#__PURE__*/React__default["default"].createElement("span", {
52
+ "data-case": "simple"
53
+ }, "[Object Unknown]");
54
+ }
55
+ }
56
+ return /*#__PURE__*/React__default["default"].createElement("span", {
57
+ "data-case": "simple"
58
+ }, value);
59
+ }
60
+ exports.SimpleCase = SimpleCase;
61
+ exports.isSimpleCase = isSimpleCase;
@@ -0,0 +1,200 @@
1
+ /** @LICENSE
2
+ * @hi-ui/schema-fields
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/schema/schema-fields#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ Object.defineProperty(exports, '__esModule', {
13
+ value: true
14
+ });
15
+ var ctx = require('./ctx.js');
16
+
17
+ /**
18
+ * 判断字段是否只读
19
+ * @param field 字段配置
20
+ * @param runtimeEditable 运行时的可编辑状态(可选)
21
+ */
22
+ function useReadonly(field, runtimeEditable) {
23
+ var component = ctx.useEditableControlCtx();
24
+ return isReadonly({
25
+ component: component,
26
+ field: field.control || {},
27
+ runtimeEditable: runtimeEditable
28
+ });
29
+ }
30
+ // 是否只读的判断逻辑:
31
+ // - 影响这个值的有四个属性 组件层级的 'editable' | 'readonly' 和字段层级的 'editable' | 'readonly'
32
+ // - 先看外部的配置,再看内部的配置,内部的优先级更高
33
+ // - 这四个值,是 undefined 的直接忽略
34
+ // - 默认是可编辑的,只有在 readonly 为 true 或者 editable 为 false 时 才会不可编辑
35
+ // - 如果 readonly 和 editable 有冲突,editable 的优先级更高
36
+ // NOTE 其实完全可以使用一个值来表示,但是为了方便写代码,还是分开两个字段来控制
37
+ /**
38
+ * 判断是否只读的工具函数
39
+ */
40
+ function isReadonly(ctx) {
41
+ var component = ctx.component,
42
+ field = ctx.field,
43
+ runtimeEditable = ctx.runtimeEditable;
44
+ // 检查字段级别的 editable
45
+ if (field.editable !== undefined) {
46
+ return !field.editable;
47
+ }
48
+ // 检查字段级别的 readonly
49
+ if (field.readonly !== undefined) {
50
+ return field.readonly;
51
+ }
52
+ // 检查运行时配置
53
+ if (runtimeEditable !== undefined) {
54
+ return !runtimeEditable;
55
+ }
56
+ // 检查组件级别的 editable
57
+ if (component.editable !== undefined) {
58
+ return !component.editable;
59
+ }
60
+ // 检查组件级别的 readonly
61
+ if (component.readonly !== undefined) {
62
+ return component.readonly;
63
+ }
64
+ // 默认可编辑
65
+ return false;
66
+ }
67
+ /**
68
+ * 运行动态可编辑函数
69
+ * - 会在字段内部完成【只读/可编辑/运行时可编辑】的判断后执行
70
+ * - 仅在上述判断为【可编辑】时,才会调用本函数
71
+ * - 本函数返回真值时,字段开启编辑,否则改为只读
72
+ */
73
+ function runDynamicEditable(field, readonly, getCtx) {
74
+ var _a;
75
+ // 只读直接返回false
76
+ if (readonly) return false;
77
+ // 以下字段是可编辑的
78
+ // 再检查 dynamicEditable 函数
79
+ var dynamicEditable = (_a = field.control) === null || _a === void 0 ? void 0 : _a.dynamicEditable;
80
+ // 不存在,就保持可编辑
81
+ if (!dynamicEditable) return true;
82
+ try {
83
+ // 存在,就调用函数
84
+ var ctx = getCtx();
85
+ return !!dynamicEditable(ctx);
86
+ } catch (error) {
87
+ console.warn('runDynamicEditable', error);
88
+ // 如果函数抛出错误,就保持可编辑
89
+ return true;
90
+ }
91
+ }
92
+ // NOTE 以下是 isReadonly 的测试代码
93
+ // // 创建测试上下文的辅助函数
94
+ // const createCtx = (config: {
95
+ // componentEditable?: boolean
96
+ // componentReadonly?: boolean
97
+ // fieldEditable?: boolean
98
+ // fieldReadonly?: boolean
99
+ // runtimeEditable?: boolean
100
+ // }) => {
101
+ // return {
102
+ // component: { editable: config.componentEditable, readonly: config.componentReadonly },
103
+ // field: { editable: config.fieldEditable, readonly: config.fieldReadonly },
104
+ // runtimeEditable: config.runtimeEditable,
105
+ // }
106
+ // }
107
+ // // 测试辅助函数
108
+ // function runTest(description: string, ctx: ReadonlyCtxType, expectedResult: boolean) {
109
+ // const actualResult = isReadonly(ctx)
110
+ // const passed = actualResult === expectedResult
111
+ // console.log(
112
+ // `${passed ? '✅' : '❌'} ${description}\n`,
113
+ // ` 预期结果: ${expectedResult}\n`,
114
+ // ` 实际结果: ${actualResult}\n`
115
+ // )
116
+ // }
117
+ // console.log('=== isReadOnly 函数测试 ===\n')
118
+ // // 默认行为测试
119
+ // console.log('📋 测试组:默认行为\n')
120
+ // runTest('所有配置都是undefined时应该可编辑', createCtx({}), false)
121
+ // // 运行时配置测试
122
+ // console.log('\n📋 测试组:运行时配置\n')
123
+ // runTest('runtimeEditable=false 时应该只读', createCtx({ runtimeEditable: false }), true)
124
+ // runTest('runtimeEditable=true 时应该可编辑', createCtx({ runtimeEditable: true }), false)
125
+ // // 组件级别配置测试
126
+ // console.log('\n📋 测试组:组件级别配置\n')
127
+ // runTest('componentEditable=false 时应该只读', createCtx({ componentEditable: false }), true)
128
+ // runTest('componentEditable=true 时应该可编辑', createCtx({ componentEditable: true }), false)
129
+ // runTest('componentReadonly=true 时应该只读', createCtx({ componentReadonly: true }), true)
130
+ // runTest('componentReadonly=false 时应该可编辑', createCtx({ componentReadonly: false }), false)
131
+ // runTest(
132
+ // 'componentEditable=false 且 componentReadonly=false 时应该只读(editable优先)',
133
+ // createCtx({ componentEditable: false, componentReadonly: false }),
134
+ // true
135
+ // )
136
+ // // 字段级别配置测试
137
+ // console.log('\n📋 测试组:字段级别配置\n')
138
+ // runTest('fieldEditable=false 时应该只读', createCtx({ fieldEditable: false }), true)
139
+ // runTest('fieldEditable=true 时应该可编辑', createCtx({ fieldEditable: true }), false)
140
+ // runTest('fieldReadonly=true 时应该只读', createCtx({ fieldReadonly: true }), true)
141
+ // runTest('fieldReadonly=false 时应该可编辑', createCtx({ fieldReadonly: false }), false)
142
+ // // 运行时与字段配置组合测试
143
+ // console.log('\n📋 测试组:运行时与字段配置组合\n')
144
+ // runTest(
145
+ // '字段 editable=false 时 runtimeEditable=true 不应生效',
146
+ // createCtx({ fieldEditable: false, runtimeEditable: true }),
147
+ // true
148
+ // )
149
+ // runTest(
150
+ // '字段 readonly=true 时 runtimeEditable=true 不应生效',
151
+ // createCtx({ fieldReadonly: true, runtimeEditable: true }),
152
+ // true
153
+ // )
154
+ // // 运行时与组件配置组合测试
155
+ // console.log('\n📋 测试组:运行时与组件配置组合\n')
156
+ // runTest(
157
+ // 'runtimeEditable=false 应覆盖组件 editable=true',
158
+ // createCtx({ componentEditable: true, runtimeEditable: false }),
159
+ // true
160
+ // )
161
+ // runTest(
162
+ // 'runtimeEditable=true 应覆盖组件 readonly=true',
163
+ // createCtx({ componentReadonly: true, runtimeEditable: true }),
164
+ // false
165
+ // )
166
+ // // 复杂组合场景测试
167
+ // console.log('\n📋 测试组:复杂组合场景\n')
168
+ // runTest(
169
+ // '字段配置优先:字段readonly=true时其他配置都不生效',
170
+ // createCtx({
171
+ // fieldReadonly: true,
172
+ // runtimeEditable: true,
173
+ // componentEditable: true,
174
+ // }),
175
+ // true
176
+ // )
177
+ // runTest(
178
+ // 'runtime配置次之:无字段配置时runtime覆盖组件配置',
179
+ // createCtx({
180
+ // runtimeEditable: true,
181
+ // componentReadonly: true,
182
+ // }),
183
+ // false
184
+ // )
185
+ // runTest(
186
+ // '字段级editable优先级最高:fieldEditable=true时覆盖其他所有配置',
187
+ // createCtx({
188
+ // fieldEditable: true,
189
+ // fieldReadonly: true,
190
+ // runtimeEditable: false,
191
+ // componentEditable: false,
192
+ // componentReadonly: true,
193
+ // }),
194
+ // false
195
+ // )
196
+ // console.log('\n=== 测试结束 ===')
197
+
198
+ exports.isReadonly = isReadonly;
199
+ exports.runDynamicEditable = runDynamicEditable;
200
+ exports.useReadonly = useReadonly;
@@ -0,0 +1,114 @@
1
+ /** @LICENSE
2
+ * @hi-ui/schema-fields
3
+ * https://github.com/XiaoMi/hiui/tree/master/packages/schema/schema-fields#readme
4
+ *
5
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
6
+ *
7
+ * This source code is licensed under the MIT license found in the
8
+ * LICENSE file in the root directory of this source tree.
9
+ */
10
+ 'use strict';
11
+
12
+ var _typeof = require("@babel/runtime/helpers/typeof");
13
+ Object.defineProperty(exports, '__esModule', {
14
+ value: true
15
+ });
16
+ var _inheritsLoose = require('@babel/runtime/helpers/inheritsLoose');
17
+ var React = require('react');
18
+ var icons = require('@hi-ui/icons');
19
+ var classname = require('@hi-ui/classname');
20
+ var schemaOptionInjector = require('@hi-ui/schema-option-injector');
21
+ var schemaCore = require('@hi-ui/schema-core');
22
+ var schemaUtils = require('@hi-ui/schema-utils');
23
+ var base = require('../../base.js');
24
+ function _interopDefaultCompat(e) {
25
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
26
+ 'default': e
27
+ };
28
+ }
29
+ var _inheritsLoose__default = /*#__PURE__*/_interopDefaultCompat(_inheritsLoose);
30
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
31
+ var ProSelectableField = /*#__PURE__*/function (_ProField) {
32
+ _inheritsLoose__default["default"](ProSelectableField, _ProField);
33
+ function ProSelectableField() {
34
+ var _this;
35
+ _this = _ProField.apply(this, arguments) || this;
36
+ _this.suffixEl = /*#__PURE__*/React__default["default"].createElement(icons.DownOutlined, {
37
+ size: 16,
38
+ color: "var(" + classname.getPrefixStyleVar('color-gray-500') + ", #929aa6)"
39
+ });
40
+ return _this;
41
+ }
42
+ /**
43
+ * 过滤掉原始参数中的自引用属性
44
+ * - 防止 immer 在处理数据时出现崩溃
45
+ * - 主要用在级联及树形选择组件中
46
+ */
47
+ var _proto = ProSelectableField.prototype;
48
+ _proto.hookedSetSelectedRawOption = function hookedSetSelectedRawOption(ctx, args) {
49
+ var _a;
50
+ if ((_a = ctx.field.payload) === null || _a === void 0 ? void 0 : _a.setSelectedRawOption) {
51
+ var nextArgs = schemaUtils.filterCascaderSelfReferenceOpts.apply(void 0, args);
52
+ ctx.field.payload.setSelectedRawOption(nextArgs);
53
+ }
54
+ };
55
+ _proto.getOptionTitle = function getOptionTitle(ctx, dataKey) {
56
+ var rowData = ctx.rowData,
57
+ _ctx$field = ctx.field,
58
+ valueType = _ctx$field.valueType,
59
+ dataIndex = _ctx$field.dataIndex;
60
+ var fieldKey = dataKey || dataIndex;
61
+ // 内部会区分组件类型,返回对应的标题
62
+ return schemaOptionInjector.getSelectedOptionTitle(rowData, valueType, fieldKey);
63
+ };
64
+ _proto.getDftPlaceholder = function getDftPlaceholder(ctx) {
65
+ var titleText = ctx.field._titleText;
66
+ if (titleText) return "\u8BF7\u9009\u62E9" + titleText;
67
+ }
68
+ /**
69
+ * 渲染字符串类型的已选结果
70
+ * - 用在单选、单选级联
71
+ */;
72
+ _proto.renderEditableForStringSelected = function renderEditableForStringSelected(data, ctx) {
73
+ var dataKey = ctx.dataKey;
74
+ // 如果数据为无效值,则不渲染 // null/undefined/空串/空数组
75
+ if (schemaUtils.isInvalidValue(data)) return null;
76
+ // 尝试获取已选中的标题
77
+ // SELECTED_OPTION_RAW 来自可编辑表,原始数据中没有的直接跳过这里的逻辑
78
+ if (schemaCore.SELECTED_OPTION_RAW in ctx.rawData) {
79
+ var selectedTitle = this.getOptionTitle(ctx, dataKey);
80
+ if (selectedTitle) {
81
+ return _ProField.prototype.renderEditable.call(this, selectedTitle, ctx, {
82
+ suffix: this.suffixEl
83
+ });
84
+ }
85
+ }
86
+ return null;
87
+ }
88
+ /**
89
+ * 渲染字符串类型的首次回显元素
90
+ * - 用在单选、单选级联
91
+ */;
92
+ _proto.renderEditableForStringFirstRefill = function renderEditableForStringFirstRefill(data, ctx, extra) {
93
+ var _a;
94
+ // 如果数据为无效值,则不渲染 // null/undefined/空串/空数组
95
+ if (!schemaUtils.isInvalidValue(data)) {
96
+ var RefillComponent = extra.RefillComponent,
97
+ dftRender = extra.dftRender;
98
+ var fieldProps = this.getFieldProps({}, ctx);
99
+ return /*#__PURE__*/React__default["default"].createElement(schemaOptionInjector.AsyncOptsDataGetter, Object.assign({}, fieldProps, {
100
+ renderCtx: ctx
101
+ }), /*#__PURE__*/React__default["default"].createElement(RefillComponent, {
102
+ value: data,
103
+ data: [],
104
+ ctx: ctx,
105
+ instance: this,
106
+ dftRender: dftRender,
107
+ fieldNames: (_a = fieldProps.fieldNames) !== null && _a !== void 0 ? _a : {}
108
+ }));
109
+ }
110
+ return null;
111
+ };
112
+ return ProSelectableField;
113
+ }(base.ProField);
114
+ exports.ProSelectableField = ProSelectableField;