@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,40 @@
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
+
16
+ // TODO 待完善类型定义
17
+ function wrapFormBinding(formBinding, fieldProps) {
18
+ return Object.assign(Object.assign({}, formBinding), {
19
+ value: formBinding.value,
20
+ onChange: function onChange() {
21
+ var _a2;
22
+ var _a;
23
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
24
+ args[_key] = arguments[_key];
25
+ }
26
+ formBinding.onChange.apply(formBinding, args);
27
+ (_a = fieldProps.onChange) === null || _a === void 0 ? void 0 : (_a2 = _a).call.apply(_a2, [fieldProps].concat(args));
28
+ },
29
+ onBlur: function onBlur() {
30
+ var _a3;
31
+ var _a;
32
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
33
+ args[_key2] = arguments[_key2];
34
+ }
35
+ formBinding.onBlur.apply(formBinding, args);
36
+ (_a = fieldProps.onBlur) === null || _a === void 0 ? void 0 : (_a3 = _a).call.apply(_a3, [fieldProps].concat(args));
37
+ }
38
+ });
39
+ }
40
+ exports.wrapFormBinding = wrapFormBinding;
@@ -0,0 +1,34 @@
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 EllipsisTooltip = require('@hi-ui/ellipsis-tooltip');
18
+ function _interopDefaultCompat(e) {
19
+ return e && _typeof(e) === 'object' && 'default' in e ? e : {
20
+ 'default': e
21
+ };
22
+ }
23
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
24
+ var EllipsisTooltip__default = /*#__PURE__*/_interopDefaultCompat(EllipsisTooltip);
25
+ function getLabel(field, ctx) {
26
+ var _a, _b, _c;
27
+ // 在组中时,不需要显示 label
28
+ if ((_a = field.extra) === null || _a === void 0 ? void 0 : _a.mustInGroup) return undefined;
29
+ if (typeof ((_b = field.extra) === null || _b === void 0 ? void 0 : _b.customLabel) === 'function') {
30
+ return (_c = field.extra) === null || _c === void 0 ? void 0 : _c.customLabel(ctx);
31
+ }
32
+ return typeof field.title === 'string' ? ( /*#__PURE__*/React__default["default"].createElement(EllipsisTooltip__default["default"], null, field.title)) : field.title;
33
+ }
34
+ exports.getLabel = getLabel;
@@ -0,0 +1,35 @@
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 schemaUtils = require('@hi-ui/schema-utils');
16
+ var formBinding = require('./utils/form-binding.js');
17
+ require('react');
18
+ require('@hi-ui/ellipsis-tooltip');
19
+ require('lodash-es');
20
+ function getFieldProps(dftProps, ctx) {
21
+ var fieldProps = schemaUtils.getPipeGetterValue(dftProps, ctx.field.fieldProps);
22
+ // formBinding 本质是 Form 注入给 field 的属性,因此在此处统一处理
23
+ var formBindingProps = ctx.formBinding ? formBinding.wrapFormBinding(ctx.formBinding, fieldProps) : {};
24
+ return schemaUtils.mergeProps(fieldProps, formBindingProps);
25
+ }
26
+ function getWrapperProps(dftProps, ctx) {
27
+ return schemaUtils.getPipeGetterValue(dftProps, ctx.field.wrapperProps);
28
+ }
29
+ function getFormItemProps(dftProps, ctx) {
30
+ return schemaUtils.getPipeGetterValue(dftProps, ctx.field.formItemProps);
31
+ }
32
+ exports.wrapFormBinding = formBinding.wrapFormBinding;
33
+ exports.getFieldProps = getFieldProps;
34
+ exports.getFormItemProps = getFormItemProps;
35
+ exports.getWrapperProps = getWrapperProps;
@@ -0,0 +1,111 @@
1
+ import _typeof from "@babel/runtime/helpers/esm/typeof";
2
+ /** @LICENSE
3
+ * @hi-ui/schema-fields
4
+ * https://github.com/XiaoMi/hiui/tree/master/packages/schema/schema-fields#readme
5
+ *
6
+ * Copyright (c) HiUI <mi-hiui@xiaomi.com>.
7
+ *
8
+ * This source code is licensed under the MIT license found in the
9
+ * LICENSE file in the root directory of this source tree.
10
+ */
11
+ import _inheritsLoose from '@babel/runtime/helpers/esm/inheritsLoose';
12
+ import React from 'react';
13
+ import { isNil } from 'lodash-es';
14
+ import Input from '@hi-ui/input';
15
+ import EllipsisTooltip from '@hi-ui/ellipsis-tooltip';
16
+ import { AbstractProField } from '@hi-ui/schema-core';
17
+ import { ReadonlyWrapper } from './components/span/index.js';
18
+ import { getFieldProps, getWrapperProps, getFormItemProps } from './utils.js';
19
+ var ProField = /*#__PURE__*/function (_AbstractProField) {
20
+ _inheritsLoose(ProField, _AbstractProField);
21
+ function ProField() {
22
+ var _this;
23
+ _this = _AbstractProField.apply(this, arguments) || this;
24
+ _this.dftDom = /*#__PURE__*/React.createElement("span", {
25
+ "data-case": "default"
26
+ }, "-");
27
+ return _this;
28
+ }
29
+ var _proto = ProField.prototype;
30
+ _proto.getFieldProps = function getFieldProps$1(dftProps, ctx) {
31
+ return getFieldProps(dftProps, ctx);
32
+ };
33
+ _proto.getWrapperProps = function getWrapperProps$1(dftProps, ctx) {
34
+ return getWrapperProps(dftProps, ctx);
35
+ };
36
+ _proto.getFormItemProps = function getFormItemProps$1(dftProps, ctx) {
37
+ return getFormItemProps(dftProps, ctx);
38
+ }
39
+ /**
40
+ * 渲染字符串的内部方法
41
+ * @desc 很多类型的字段最终渲染时都是文本,因此提取一个公共方法到此处
42
+ * @desc 封装了 EllipsisTooltip 的逻辑 */;
43
+ _proto.renderString = function renderString(text, ctx) {
44
+ var fieldProps = this.getFieldProps({
45
+ numberOfLines: 1
46
+ }, ctx);
47
+ return /*#__PURE__*/React.createElement(ReadonlyWrapper, null, /*#__PURE__*/React.createElement(EllipsisTooltip, {
48
+ className: fieldProps.tooltipClassName,
49
+ numberOfLines: fieldProps.numberOfLines
50
+ }, text));
51
+ }
52
+ /** 只读模式的渲染逻辑 */;
53
+ _proto.render = function render(data, ctx) {
54
+ if (isNil(data)) return this.dftDom;
55
+ if (Array.isArray(data)) {
56
+ if (data.length === 0) return this.dftDom;
57
+ return this.renderString(data.join(', '), ctx);
58
+ }
59
+ if (_typeof(data) === 'object') {
60
+ return this.renderString(JSON.stringify(data), ctx);
61
+ }
62
+ return this.renderString(String(data), ctx);
63
+ }
64
+ /**
65
+ * 表格单元格渲染逻辑
66
+ * @desc 默认直接使用 render 的逻辑 */;
67
+ _proto.renderCell = function renderCell(data, ctx) {
68
+ return this.render(data, ctx);
69
+ }
70
+ /**
71
+ * 表格 Footer 单元格渲染逻辑
72
+ * @desc 没有默认逻辑,需由字段自行实现 */;
73
+ _proto.renderFooterCell = function renderFooterCell(ctx) {
74
+ console.log(ctx); // 仅用于规避定义未使用检查
75
+ return null;
76
+ };
77
+ _proto.renderFormItem = function renderFormItem(data, ctx) {
78
+ console.log(data, ctx); // 仅用于规避定义未使用检查
79
+ throw new Error('ProField.renderFormItem not implemented');
80
+ };
81
+ _proto.getEditablePlaceholder = function getEditablePlaceholder(data, ctx) {
82
+ if (isNil(data)) return '';
83
+ if (typeof data === 'string') return data;
84
+ if (typeof data === 'number') return String(data);
85
+ if (typeof data === 'boolean') return data ? 'true' : 'false';
86
+ if (Array.isArray(data)) return data.join(' / ');
87
+ if (_typeof(data) === 'object') return JSON.stringify(data);
88
+ return '';
89
+ }
90
+ /** 编辑模式的渲染逻辑,在只读与可编辑之间切换 */;
91
+ _proto.renderEditable = function renderEditable(data, ctx, extraProps) {
92
+ var _a;
93
+ var fieldProps = this.getFieldProps({
94
+ placeholder: this.getDftPlaceholder(ctx)
95
+ }, ctx);
96
+ return /*#__PURE__*/React.createElement(Input, Object.assign({
97
+ value: this.getEditablePlaceholder(data, ctx),
98
+ readOnly: true,
99
+ disabled: (_a = ctx.field.control) === null || _a === void 0 ? void 0 : _a.disabled,
100
+ onDoubleClick: ctx.onActivate,
101
+ onFocus: ctx.onActivate,
102
+ placeholder: fieldProps.placeholder
103
+ }, extraProps));
104
+ };
105
+ _proto.getDftPlaceholder = function getDftPlaceholder(ctx) {
106
+ var titleText = ctx.field._titleText;
107
+ if (titleText) return "\u8BF7\u8F93\u5165" + titleText;
108
+ };
109
+ return ProField;
110
+ }(AbstractProField);
111
+ export { ProField };
@@ -0,0 +1,49 @@
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
+ import React from 'react';
11
+ import Preview from '@hi-ui/preview';
12
+ import Space from '@hi-ui/space';
13
+ function ImagePreview(props) {
14
+ var images = props.images;
15
+ var _React$useState = React.useState(false),
16
+ visible = _React$useState[0],
17
+ setVisible = _React$useState[1];
18
+ var _React$useState2 = React.useState(0),
19
+ current = _React$useState2[0],
20
+ setCurrent = _React$useState2[1];
21
+ return /*#__PURE__*/React.createElement("div", {
22
+ className: "image-preview"
23
+ }, /*#__PURE__*/React.createElement(Preview, {
24
+ title: current + 1 + "/" + images.length,
25
+ src: images,
26
+ current: current,
27
+ onPreviewChange: setCurrent,
28
+ visible: visible,
29
+ onClose: function onClose() {
30
+ setVisible(false);
31
+ }
32
+ }), /*#__PURE__*/React.createElement(Space, null, images.map(function (url, index) {
33
+ return /*#__PURE__*/React.createElement("div", {
34
+ key: index,
35
+ className: "image-preview__item-wrapper"
36
+ }, /*#__PURE__*/React.createElement("img", {
37
+ src: url,
38
+ style: {
39
+ width: '100%',
40
+ cursor: 'pointer'
41
+ },
42
+ onClick: function onClick() {
43
+ setCurrent(index);
44
+ setVisible(true);
45
+ }
46
+ }));
47
+ })));
48
+ }
49
+ export { ImagePreview };
@@ -0,0 +1,20 @@
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
+ import React from 'react';
11
+ import { getDataSet } from '@hi-ui/schema-utils';
12
+ function ReadonlyWrapper(props) {
13
+ var dataSet = getDataSet(props.dataSet);
14
+ return /*#__PURE__*/React.createElement("span", Object.assign({
15
+ "data-case": "readonly"
16
+ }, dataSet, {
17
+ style: props.style
18
+ }), props.children);
19
+ }
20
+ export { ReadonlyWrapper, ReadonlyWrapper as Span };
@@ -0,0 +1,214 @@
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
+ import _regeneratorRuntime from '@babel/runtime/regenerator';
11
+ import { __rest, __awaiter } from 'tslib';
12
+ import React, { useMemo, useEffect } from 'react';
13
+ import { omit } from 'lodash-es';
14
+ import { useControllableValue } from 'ahooks';
15
+ import { message } from '@hi-ui/message';
16
+ import { useReadonlyRef } from '@hi-ui/schema-hooks';
17
+ import { mergeProps } from '@hi-ui/schema-utils';
18
+ import { toFileList, sliceToMaxCount, genFileIdentifier } from './utils.js';
19
+ var noopOnChange = function noopOnChange() {
20
+ // noopOnChange
21
+ };
22
+ function normalizeProps(props) {
23
+ var value = props.value;
24
+ // value 为字符传时转换为数组;undefined 保持 undefined
25
+ var nextValue = Array.isArray(value) ? value : typeof value === 'string' ? [value] : undefined;
26
+ // 存在 request 方法时,默认使用 json 模式
27
+ var nextMode = props.mode || (props.request ? 'json' : 'formData');
28
+ // maxCount 大于 1 时,默认使用 multiple 模式
29
+ var nextMultiple = props.multiple || (props.maxCount || 0) > 1;
30
+ // 没开启 multiple,也没传 maxCount,则默认限制为 1
31
+ var nextMaxCount = props.maxCount || (!props.multiple ? 1 : undefined);
32
+ return Object.assign(Object.assign({}, props), {
33
+ value: nextValue,
34
+ mode: nextMode,
35
+ multiple: nextMultiple,
36
+ maxCount: nextMaxCount
37
+ });
38
+ }
39
+ function UploadBridge(props) {
40
+ var _this = this;
41
+ var children = props.children,
42
+ restProps = __rest(props, ["children"]);
43
+ var normalizedProps = normalizeProps(restProps);
44
+ var _useControllableValue = useControllableValue(normalizedProps),
45
+ _useControllableValue2 = _useControllableValue[0],
46
+ value = _useControllableValue2 === void 0 ? [] : _useControllableValue2,
47
+ _setValue = _useControllableValue[1];
48
+ var _useMemo = useMemo(function () {
49
+ return toFileList(value);
50
+ }, [value]),
51
+ fileList = _useMemo.fileList,
52
+ fileIdSet = _useMemo.fileIdSet;
53
+ var setValue = function setValue(value) {
54
+ // 只保留<maxCount>个文件
55
+ var sliced = sliceToMaxCount(value, normalizedProps.maxCount, 0);
56
+ var transformed = sliced.map(function (file) {
57
+ if (typeof file === 'string') return {
58
+ url: file,
59
+ fileId: file,
60
+ name: ''
61
+ };else return file;
62
+ });
63
+ _setValue(transformed);
64
+ };
65
+ // 此处的 Set 是给组件卸载的清理阶段有的
66
+ var fileUrlSetRef = useReadonlyRef(function () {
67
+ return new Set();
68
+ });
69
+ if (normalizedProps.mode === 'formData') {
70
+ fileList === null || fileList === void 0 ? void 0 : fileList.forEach(function (_ref) {
71
+ var url = _ref.url;
72
+ return fileUrlSetRef.current.add(url);
73
+ });
74
+ }
75
+ useEffect(function () {
76
+ return function () {
77
+ // 组件卸载时清理所有创建的URL
78
+ // 此处忽略掉这条规则,因为就是需要最新的 fileUrlSetRef
79
+ // eslint-disable-next-line react-hooks/exhaustive-deps
80
+ fileUrlSetRef.current.forEach(function (url) {
81
+ if (url) {
82
+ // url 预期是 blob 协议的本地文件地址
83
+ // 若是外部传入的 http 协议的文件也没事
84
+ // revokeObjectURL 会直接忽略
85
+ URL.revokeObjectURL(url);
86
+ }
87
+ });
88
+ };
89
+ }, [fileUrlSetRef]);
90
+ var customUpload = function customUpload(fileList) {
91
+ return __awaiter(_this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
92
+ var files, uniqueFiles, maxSize, maxSizeInBytes, oversizedFiles, sliced, urls, nextFiles, msg;
93
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
94
+ while (1) {
95
+ switch (_context.prev = _context.next) {
96
+ case 0:
97
+ if (fileList) {
98
+ _context.next = 2;
99
+ break;
100
+ }
101
+ return _context.abrupt("return");
102
+ case 2:
103
+ files = Array.from(fileList); // 1. 文件去重
104
+ // 直接使用已计算的fileList中的fileId
105
+ uniqueFiles = files.filter(function (file) {
106
+ return !(fileIdSet === null || fileIdSet === void 0 ? void 0 : fileIdSet.has(genFileIdentifier(file)));
107
+ });
108
+ if (!(uniqueFiles.length === 0)) {
109
+ _context.next = 7;
110
+ break;
111
+ }
112
+ message.open({
113
+ type: 'warning',
114
+ title: '所选文件已存在'
115
+ });
116
+ return _context.abrupt("return");
117
+ case 7:
118
+ // 2. 检查文件大小 (maxSize单位为KB,需要转换为bytes进行比较)
119
+ maxSize = normalizedProps.maxSize || Infinity;
120
+ maxSizeInBytes = maxSize * 1024;
121
+ oversizedFiles = uniqueFiles.filter(function (file) {
122
+ return file.size > maxSizeInBytes;
123
+ });
124
+ if (!(oversizedFiles.length > 0)) {
125
+ _context.next = 13;
126
+ break;
127
+ }
128
+ message.open({
129
+ type: 'warning',
130
+ title: "\u6587\u4EF6\u5927\u5C0F\u8D85\u51FA" + maxSize + "KB\u9650\u5236"
131
+ });
132
+ return _context.abrupt("return");
133
+ case 13:
134
+ _context.prev = 13;
135
+ if (!(normalizedProps.mode === 'json')) {
136
+ _context.next = 27;
137
+ break;
138
+ }
139
+ if (normalizedProps.request) {
140
+ _context.next = 17;
141
+ break;
142
+ }
143
+ throw new Error('JSON 模式下必须提供 request 方法');
144
+ case 17:
145
+ // 只保留<maxCount - curLength>个文件
146
+ sliced = sliceToMaxCount(uniqueFiles, normalizedProps.maxCount, value.length); // 上传文件并获取URL
147
+ _context.next = 20;
148
+ return normalizedProps.request(sliced);
149
+ case 20:
150
+ urls = _context.sent;
151
+ if (!(!urls || urls.length === 0)) {
152
+ _context.next = 23;
153
+ break;
154
+ }
155
+ return _context.abrupt("return");
156
+ case 23:
157
+ nextFiles = urls.map(function (url, index) {
158
+ var fileId = genFileIdentifier(uniqueFiles[index]);
159
+ if (typeof url === 'string') return {
160
+ url: url,
161
+ fileId: fileId,
162
+ name: ''
163
+ };else return Object.assign(Object.assign({}, url), {
164
+ fileId: fileId
165
+ });
166
+ }); // 更新value
167
+ setValue([].concat(value || [], nextFiles));
168
+ _context.next = 28;
169
+ break;
170
+ case 27:
171
+ // formData模式直接返回File数组
172
+ setValue([].concat(value || [], uniqueFiles));
173
+ case 28:
174
+ _context.next = 35;
175
+ break;
176
+ case 30:
177
+ _context.prev = 30;
178
+ _context.t0 = _context["catch"](13);
179
+ console.log('UploadBridge customUpload request', _context.t0);
180
+ msg = '文件上传失败: ' + (_context.t0 instanceof Error ? _context.t0.message : '未知错误');
181
+ message.open({
182
+ type: 'error',
183
+ title: msg
184
+ });
185
+ case 35:
186
+ case "end":
187
+ return _context.stop();
188
+ }
189
+ }
190
+ }, _callee, null, [[13, 30]]);
191
+ }));
192
+ };
193
+ var handleRemove = function handleRemove(_1, _2, index) {
194
+ // 获取要删除的文件的URL
195
+ var fileToRemove = fileList === null || fileList === void 0 ? void 0 : fileList[index];
196
+ if (fileToRemove === null || fileToRemove === void 0 ? void 0 : fileToRemove.url) URL.revokeObjectURL(fileToRemove.url);
197
+ setValue(value.filter(function (_, idx) {
198
+ return idx !== index;
199
+ }));
200
+ return true;
201
+ };
202
+ var finalProps = mergeProps({
203
+ type: 'default'
204
+ }, omit(normalizedProps, [
205
+ // 移除无关的属性
206
+ 'value', 'defaultValue', 'onChange', 'mode', 'request']));
207
+ return /*#__PURE__*/React.cloneElement(children, Object.assign(Object.assign({}, finalProps), {
208
+ customUpload: customUpload,
209
+ fileList: fileList,
210
+ onChange: noopOnChange,
211
+ onRemove: handleRemove
212
+ }));
213
+ }
214
+ export { UploadBridge };
@@ -0,0 +1,66 @@
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
+ import { extractFileInfo } from '@hi-ui/schema-utils';
11
+ function toFileList(file) {
12
+ if (!file) return {};
13
+ var fileIdSet = new Set();
14
+ var files = Array.isArray(file) ? file : [file];
15
+ var fileList = files.map(function (file) {
16
+ var normalizedFile = typeof file === 'string' ? {
17
+ symbol: file,
18
+ fileId: file,
19
+ url: file
20
+ } : file instanceof File ? {
21
+ symbol: file.name,
22
+ name: file.name,
23
+ fileId: file.name + "-" + file.size + "-" + file.lastModified,
24
+ url: URL.createObjectURL(file)
25
+ } : {
26
+ symbol: file.url,
27
+ name: file.name,
28
+ fileId: file.name + "-" + file.url,
29
+ url: file.url
30
+ };
31
+ var info = extractFileInfo(normalizedFile.symbol);
32
+ // 添加到 fileIdSet
33
+ fileIdSet.add(normalizedFile.fileId);
34
+ return {
35
+ name: normalizedFile.name || info.fullName,
36
+ fileId: normalizedFile.fileId,
37
+ fileType: info.ext,
38
+ uploadState: 'success',
39
+ url: normalizedFile.url
40
+ };
41
+ });
42
+ return {
43
+ fileIdSet: fileIdSet,
44
+ fileList: fileList
45
+ };
46
+ }
47
+ // 文件唯一标识生成函数
48
+ function genFileIdentifier(file) {
49
+ if (file instanceof File) {
50
+ return file.name + "-" + file.size + "-" + file.lastModified;
51
+ } else if (typeof file === 'string') {
52
+ return file;
53
+ } else {
54
+ return file.name + "-" + file.url;
55
+ }
56
+ }
57
+ function sliceToMaxCount(value, maxCount, curCount) {
58
+ if (curCount === void 0) {
59
+ curCount = 0;
60
+ }
61
+ // maxCount 存在时,计算需要保留的文件数量
62
+ var _maxCount = typeof maxCount === 'number' ? maxCount - curCount : undefined;
63
+ var sliceStart = Math.max(value.length - (_maxCount || 0), 0);
64
+ return value.slice(sliceStart);
65
+ }
66
+ export { genFileIdentifier, sliceToMaxCount, toFileList };
package/lib/esm/ctx.js ADDED
@@ -0,0 +1,55 @@
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
+ import React from 'react';
11
+ import { ProText } from './fields/semantic/text/index.js';
12
+ var FieldMapCtx = /*#__PURE__*/React.createContext(null);
13
+ function FieldMapProvider(props) {
14
+ var children = props.children,
15
+ fields = props.fields;
16
+ return /*#__PURE__*/React.createElement(FieldMapCtx.Provider, {
17
+ value: fields
18
+ }, children);
19
+ }
20
+ function useFieldMap(opts) {
21
+ if (opts === void 0) {
22
+ opts = {};
23
+ }
24
+ var ctx = React.useContext(FieldMapCtx);
25
+ var _opts = opts,
26
+ fieldMap = _opts.fieldMap;
27
+ if (fieldMap) return fieldMap;
28
+ if (!ctx) {
29
+ console.warn("SchemaComponents: \u672A\u627E\u5230 FieldsContext\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u7684 Text \u6E32\u67D3\u5668");
30
+ return {
31
+ text: ProText
32
+ };
33
+ }
34
+ return ctx;
35
+ }
36
+ function matchFieldClass(opts) {
37
+ var field = opts.field,
38
+ fieldMap = opts.fieldMap;
39
+ var matchedFieldClass = fieldMap[field.valueType];
40
+ var FieldClass = matchedFieldClass || ProText;
41
+ if (!matchedFieldClass && field.valueType !== 'custom') {
42
+ var _name = opts.name || 'matchFieldClass';
43
+ var _type = field.valueType;
44
+ console.warn(_name + ": \u672A\u627E\u5230 ValueType \"" + _type + "\" \u5BF9\u5E94\u7684\u6E32\u67D3\u5668\uFF0C\u5C06\u4F7F\u7528\u9ED8\u8BA4\u7684 Text \u6E32\u67D3\u5668\n");
45
+ }
46
+ return FieldClass;
47
+ }
48
+ function useMatchFieldClass(opts) {
49
+ // 获取字段渲染器
50
+ var fieldMap = useFieldMap(opts);
51
+ return matchFieldClass(Object.assign(Object.assign({}, opts), {
52
+ fieldMap: fieldMap
53
+ }));
54
+ }
55
+ export { FieldMapProvider, matchFieldClass, useFieldMap, useMatchFieldClass };
@@ -0,0 +1,32 @@
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
+ import React from 'react';
11
+ var EditableControlContext = /*#__PURE__*/React.createContext({
12
+ editable: undefined,
13
+ // 默认可编辑
14
+ readonly: undefined // 默认非只读
15
+ });
16
+
17
+ function EditableControlProvider(props) {
18
+ // 只是用来保持引用不变
19
+ var value = React.useMemo(function () {
20
+ return {
21
+ editable: props.editable,
22
+ readonly: props.readonly
23
+ };
24
+ }, [props.editable, props.readonly]);
25
+ return /*#__PURE__*/React.createElement(EditableControlContext.Provider, {
26
+ value: value
27
+ }, props.children);
28
+ }
29
+ function useEditableControlCtx() {
30
+ return React.useContext(EditableControlContext);
31
+ }
32
+ export { EditableControlProvider, useEditableControlCtx };