antd-mobile 5.25.1 → 5.26.0

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 (98) hide show
  1. package/2x/bundle/antd-mobile.cjs.development.js +188 -121
  2. package/2x/bundle/antd-mobile.cjs.js +8 -8
  3. package/2x/bundle/antd-mobile.es.development.js +188 -121
  4. package/2x/bundle/antd-mobile.es.js +3936 -3910
  5. package/2x/bundle/antd-mobile.umd.development.js +188 -121
  6. package/2x/bundle/antd-mobile.umd.js +8 -8
  7. package/2x/bundle/style.css +29 -5
  8. package/2x/cjs/components/calendar/calendar.js +9 -1
  9. package/2x/cjs/components/floating-bubble/floating-bubble.d.ts +8 -0
  10. package/2x/cjs/components/floating-bubble/floating-bubble.js +25 -5
  11. package/2x/cjs/components/form/form.d.ts +1 -1
  12. package/2x/cjs/components/image-uploader/image-uploader.css +16 -1
  13. package/2x/cjs/components/image-uploader/image-uploader.d.ts +4 -1
  14. package/2x/cjs/components/image-uploader/image-uploader.js +46 -9
  15. package/2x/cjs/components/image-uploader/preview-item.d.ts +2 -1
  16. package/2x/cjs/components/image-uploader/preview-item.js +5 -7
  17. package/2x/cjs/components/mask/mask.d.ts +1 -1
  18. package/2x/cjs/components/mask/mask.js +6 -2
  19. package/2x/cjs/components/notice-bar/notice-bar.css +13 -4
  20. package/2x/cjs/components/notice-bar/notice-bar.d.ts +10 -8
  21. package/2x/cjs/components/notice-bar/notice-bar.js +5 -2
  22. package/2x/cjs/components/stepper/stepper.d.ts +2 -0
  23. package/2x/cjs/components/stepper/stepper.js +55 -32
  24. package/2x/cjs/components/water-mark/water-mark.d.ts +1 -1
  25. package/2x/cjs/components/water-mark/water-mark.js +5 -1
  26. package/2x/es/components/calendar/calendar.js +9 -1
  27. package/2x/es/components/floating-bubble/floating-bubble.d.ts +8 -0
  28. package/2x/es/components/floating-bubble/floating-bubble.js +26 -6
  29. package/2x/es/components/form/form.d.ts +1 -1
  30. package/2x/es/components/image-uploader/image-uploader.css +16 -1
  31. package/2x/es/components/image-uploader/image-uploader.d.ts +4 -1
  32. package/2x/es/components/image-uploader/image-uploader.js +48 -11
  33. package/2x/es/components/image-uploader/preview-item.d.ts +2 -1
  34. package/2x/es/components/image-uploader/preview-item.js +6 -8
  35. package/2x/es/components/mask/mask.d.ts +1 -1
  36. package/2x/es/components/mask/mask.js +6 -2
  37. package/2x/es/components/notice-bar/notice-bar.css +13 -4
  38. package/2x/es/components/notice-bar/notice-bar.d.ts +10 -8
  39. package/2x/es/components/notice-bar/notice-bar.js +5 -2
  40. package/2x/es/components/stepper/stepper.d.ts +2 -0
  41. package/2x/es/components/stepper/stepper.js +55 -32
  42. package/2x/es/components/water-mark/water-mark.d.ts +1 -1
  43. package/2x/es/components/water-mark/water-mark.js +5 -1
  44. package/2x/package.json +9 -9
  45. package/bundle/antd-mobile.cjs.development.js +188 -121
  46. package/bundle/antd-mobile.cjs.js +8 -8
  47. package/bundle/antd-mobile.compatible.umd.js +1 -1
  48. package/bundle/antd-mobile.es.development.js +188 -121
  49. package/bundle/antd-mobile.es.js +3936 -3910
  50. package/bundle/antd-mobile.umd.development.js +188 -121
  51. package/bundle/antd-mobile.umd.js +8 -8
  52. package/bundle/style.css +1 -1
  53. package/cjs/components/calendar/calendar.js +9 -1
  54. package/cjs/components/floating-bubble/floating-bubble.d.ts +8 -0
  55. package/cjs/components/floating-bubble/floating-bubble.js +25 -5
  56. package/cjs/components/form/form.d.ts +1 -1
  57. package/cjs/components/image-uploader/image-uploader.css +15 -1
  58. package/cjs/components/image-uploader/image-uploader.d.ts +4 -1
  59. package/cjs/components/image-uploader/image-uploader.js +46 -9
  60. package/cjs/components/image-uploader/preview-item.d.ts +2 -1
  61. package/cjs/components/image-uploader/preview-item.js +5 -7
  62. package/cjs/components/mask/mask.d.ts +1 -1
  63. package/cjs/components/mask/mask.js +6 -2
  64. package/cjs/components/notice-bar/notice-bar.css +11 -4
  65. package/cjs/components/notice-bar/notice-bar.d.ts +10 -8
  66. package/cjs/components/notice-bar/notice-bar.js +5 -2
  67. package/cjs/components/stepper/stepper.d.ts +2 -0
  68. package/cjs/components/stepper/stepper.js +55 -32
  69. package/cjs/components/water-mark/water-mark.d.ts +1 -1
  70. package/cjs/components/water-mark/water-mark.js +5 -1
  71. package/es/components/calendar/calendar.js +9 -1
  72. package/es/components/floating-bubble/floating-bubble.d.ts +8 -0
  73. package/es/components/floating-bubble/floating-bubble.js +26 -6
  74. package/es/components/form/form.d.ts +1 -1
  75. package/es/components/image-uploader/image-uploader.css +15 -1
  76. package/es/components/image-uploader/image-uploader.d.ts +4 -1
  77. package/es/components/image-uploader/image-uploader.js +48 -11
  78. package/es/components/image-uploader/preview-item.d.ts +2 -1
  79. package/es/components/image-uploader/preview-item.js +6 -8
  80. package/es/components/mask/mask.d.ts +1 -1
  81. package/es/components/mask/mask.js +6 -2
  82. package/es/components/notice-bar/notice-bar.css +11 -4
  83. package/es/components/notice-bar/notice-bar.d.ts +10 -8
  84. package/es/components/notice-bar/notice-bar.js +5 -2
  85. package/es/components/stepper/stepper.d.ts +2 -0
  86. package/es/components/stepper/stepper.js +55 -32
  87. package/es/components/water-mark/water-mark.d.ts +1 -1
  88. package/es/components/water-mark/water-mark.js +5 -1
  89. package/package.json +9 -9
  90. package/umd/antd-mobile.js +1 -1
  91. package/2x/cjs/components/image/test/image.test.d.ts +0 -1
  92. package/2x/cjs/components/image/test/image.test.js +0 -73
  93. package/2x/es/components/image/test/image.test.d.ts +0 -1
  94. package/2x/es/components/image/test/image.test.js +0 -70
  95. package/cjs/components/image/test/image.test.d.ts +0 -1
  96. package/cjs/components/image/test/image.test.js +0 -73
  97. package/es/components/image/test/image.test.d.ts +0 -1
  98. package/es/components/image/test/image.test.js +0 -70
@@ -32,35 +32,45 @@ const Stepper = p => {
32
32
  step,
33
33
  max,
34
34
  min,
35
- inputReadOnly
35
+ inputReadOnly,
36
+ digits,
37
+ formatter,
38
+ parser
36
39
  } = props;
37
40
  const {
38
41
  locale
39
42
  } = (0, _configProvider.useConfig)();
43
+ // ========================== Parse / Format ==========================
44
+ const parseValue = text => {
45
+ if (text === '') return null;
46
+ return parser ? parser(text) : parseFloat(text);
47
+ };
48
+ const formatValue = value => {
49
+ if (value === null) return '';
50
+ if (formatter) {
51
+ return formatter(value);
52
+ } else if (digits !== undefined) {
53
+ return value.toFixed(digits);
54
+ } else {
55
+ return value.toString();
56
+ }
57
+ };
58
+ // ======================== Value & InputValue ========================
40
59
  const [value, setValue] = (0, _usePropsValue.usePropsValue)(props);
41
- const [inputValue, setInputValue] = (0, _react.useState)(() => convertValueToText(value, props.digits));
60
+ const [inputValue, setInputValue] = (0, _react.useState)(() => formatValue(value));
61
+ // >>>>> Value
42
62
  function setValueWithCheck(v) {
43
63
  if (isNaN(v)) return;
44
64
  let target = (0, _bound.bound)(v, props.min, props.max);
45
- if (props.digits !== undefined) {
46
- target = parseFloat(target.toFixed(props.digits));
65
+ if (digits !== undefined) {
66
+ target = parseFloat(target.toFixed(digits));
47
67
  }
48
68
  setValue(target);
49
69
  }
50
- const [hasFocus, setHasFocus] = (0, _react.useState)(false);
51
- (0, _react.useEffect)(() => {
52
- if (!hasFocus) {
53
- setInputValue(convertValueToText(value, props.digits));
54
- }
55
- }, [hasFocus]);
56
- (0, _react.useEffect)(() => {
57
- if (!hasFocus) {
58
- setInputValue(convertValueToText(value, props.digits));
59
- }
60
- }, [value, props.digits]);
70
+ // >>>>> Input
61
71
  const handleInputChange = v => {
62
72
  setInputValue(v);
63
- const value = convertTextToValue(v);
73
+ const value = parseValue(v);
64
74
  if (value === null) {
65
75
  if (props.allowEmpty) {
66
76
  setValue(null);
@@ -71,6 +81,29 @@ const Stepper = p => {
71
81
  setValueWithCheck(value);
72
82
  }
73
83
  };
84
+ // ============================== Focus ===============================
85
+ const [focused, setFocused] = (0, _react.useState)(false);
86
+ const inputRef = _react.default.useRef(null);
87
+ function triggerFocus(nextFocus) {
88
+ setFocused(nextFocus);
89
+ // We will convert value to original text when focus
90
+ if (nextFocus) {
91
+ setInputValue(typeof value === 'number' ? String(value) : '');
92
+ }
93
+ }
94
+ (0, _react.useEffect)(() => {
95
+ var _a, _b, _c;
96
+ if (focused) {
97
+ (_c = (_b = (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.nativeElement) === null || _b === void 0 ? void 0 : _b.select) === null || _c === void 0 ? void 0 : _c.call(_b);
98
+ }
99
+ }, [focused]);
100
+ // Focus change to format value
101
+ (0, _react.useEffect)(() => {
102
+ if (!focused) {
103
+ setInputValue(formatValue(value));
104
+ }
105
+ }, [focused, value, digits]);
106
+ // ============================ Operations ============================
74
107
  const handleMinus = () => {
75
108
  setValueWithCheck((0, _big.default)(value !== null && value !== void 0 ? value : 0).minus(step).toNumber());
76
109
  };
@@ -93,9 +126,10 @@ const Stepper = p => {
93
126
  }
94
127
  return false;
95
128
  };
129
+ // ============================== Render ==============================
96
130
  return (0, _nativeProps.withNativeProps)(props, _react.default.createElement("div", {
97
131
  className: (0, _classnames.default)(classPrefix, {
98
- [`${classPrefix}-active`]: hasFocus
132
+ [`${classPrefix}-active`]: focused
99
133
  })
100
134
  }, _react.default.createElement(_button.default, {
101
135
  className: `${classPrefix}-minus`,
@@ -108,10 +142,11 @@ const Stepper = p => {
108
142
  }, _react.default.createElement(_antdMobileIcons.MinusOutline, null)), _react.default.createElement("div", {
109
143
  className: `${classPrefix}-middle`
110
144
  }, _react.default.createElement(_input.default, {
145
+ ref: inputRef,
111
146
  className: `${classPrefix}-input`,
112
147
  onFocus: e => {
113
148
  var _a;
114
- setHasFocus(true);
149
+ triggerFocus(true);
115
150
  (_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, e);
116
151
  },
117
152
  value: inputValue,
@@ -121,7 +156,7 @@ const Stepper = p => {
121
156
  disabled: disabled,
122
157
  onBlur: e => {
123
158
  var _a;
124
- setHasFocus(false);
159
+ triggerFocus(false);
125
160
  (_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, e);
126
161
  },
127
162
  readOnly: inputReadOnly,
@@ -140,16 +175,4 @@ const Stepper = p => {
140
175
  "aria-label": locale.Stepper.increase
141
176
  }, _react.default.createElement(_antdMobileIcons.AddOutline, null))));
142
177
  };
143
- exports.Stepper = Stepper;
144
- function convertValueToText(value, digits) {
145
- if (value === null) return '';
146
- if (digits !== undefined) {
147
- return value.toFixed(digits);
148
- } else {
149
- return value.toString();
150
- }
151
- }
152
- function convertTextToValue(text) {
153
- if (text === '') return null;
154
- return parseFloat(text);
155
- }
178
+ exports.Stepper = Stepper;
@@ -10,7 +10,7 @@ export declare type WaterMarkProps = {
10
10
  image?: string;
11
11
  imageWidth?: number;
12
12
  imageHeight?: number;
13
- content?: string;
13
+ content?: string | string[];
14
14
  fontColor?: string;
15
15
  fontStyle?: 'none' | 'normal' | 'italic' | 'oblique';
16
16
  fontFamily?: string;
@@ -67,7 +67,11 @@ const WaterMark = p => {
67
67
  const markSize = Number(fontSize) * ratio;
68
68
  ctx.font = `${fontStyle} normal ${fontWeight} ${markSize}px/${markHeight}px ${fontFamily}`;
69
69
  ctx.fillStyle = fontColor;
70
- ctx.fillText(content, 0, 0);
70
+ if (Array.isArray(content)) {
71
+ content.forEach((item, index) => ctx.fillText(item, 0, index * markSize));
72
+ } else {
73
+ ctx.fillText(content, 0, 0);
74
+ }
71
75
  ctx.restore();
72
76
  setBase64Url(canvas.toDataURL());
73
77
  }
@@ -122,11 +122,17 @@ export const Calendar = forwardRef((p, ref) => {
122
122
  let isSelect = false;
123
123
  let isBegin = false;
124
124
  let isEnd = false;
125
+ let isSelectRowBegin = false;
126
+ let isSelectRowEnd = false;
125
127
  if (dateRange) {
126
128
  const [begin, end] = dateRange;
127
129
  isBegin = d.isSame(begin, 'day');
128
130
  isEnd = d.isSame(end, 'day');
129
131
  isSelect = isBegin || isEnd || d.isAfter(begin, 'day') && d.isBefore(end, 'day');
132
+ if (isSelect) {
133
+ isSelectRowBegin = (cells.length % 7 === 0 || d.isSame(d.startOf('month'), 'day')) && !isBegin;
134
+ isSelectRowEnd = (cells.length % 7 === 6 || d.isSame(d.endOf('month'), 'day')) && !isEnd;
135
+ }
130
136
  }
131
137
  const inThisMonth = d.month() === current.month();
132
138
  const disabled = props.shouldDisableDate ? props.shouldDisableDate(d.toDate()) : maxDay && d.isAfter(maxDay, 'day') || minDay && d.isBefore(minDay, 'day');
@@ -136,7 +142,9 @@ export const Calendar = forwardRef((p, ref) => {
136
142
  [`${classPrefix}-cell-today`]: d.isSame(today, 'day'),
137
143
  [`${classPrefix}-cell-selected`]: isSelect,
138
144
  [`${classPrefix}-cell-selected-begin`]: isBegin,
139
- [`${classPrefix}-cell-selected-end`]: isEnd
145
+ [`${classPrefix}-cell-selected-end`]: isEnd,
146
+ [`${classPrefix}-cell-selected-row-begin`]: isSelectRowBegin,
147
+ [`${classPrefix}-cell-selected-row-end`]: isSelectRowEnd
140
148
  }),
141
149
  onClick: () => {
142
150
  if (!props.selectionMode) return;
@@ -1,9 +1,17 @@
1
1
  import React, { FC } from 'react';
2
2
  import { NativeProps } from '../../utils/native-props';
3
+ declare type Offset = {
4
+ x: number;
5
+ y: number;
6
+ };
3
7
  export declare type FloatingBubbleProps = {
4
8
  onClick?: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
5
9
  axis?: 'x' | 'y' | 'xy' | 'lock';
6
10
  magnetic?: 'x' | 'y';
7
11
  children?: React.ReactNode;
12
+ offset?: Offset;
13
+ defaultOffset?: Offset;
14
+ onOffsetChange?: (offset: Offset) => void;
8
15
  } & NativeProps<'--initial-position-left' | '--initial-position-right' | '--initial-position-top' | '--initial-position-bottom' | '--z-index' | '--edge-distance' | '--size' | '--border-radius' | '--background'>;
9
16
  export declare const FloatingBubble: FC<FloatingBubbleProps>;
17
+ export {};
@@ -1,16 +1,28 @@
1
- import React, { useRef } from 'react';
1
+ import React, { useRef, useEffect, useState } from 'react';
2
2
  import { useSpring, animated, to } from '@react-spring/web';
3
3
  import { useDrag } from '@use-gesture/react';
4
4
  import { mergeProps } from '../../utils/with-default-props';
5
5
  import { withNativeProps } from '../../utils/native-props';
6
6
  const classPrefix = `adm-floating-bubble`;
7
7
  const defaultProps = {
8
- axis: 'y'
8
+ axis: 'y',
9
+ defaultOffset: {
10
+ x: 0,
11
+ y: 0
12
+ }
9
13
  };
10
14
  export const FloatingBubble = p => {
11
15
  const props = mergeProps(defaultProps, p);
12
16
  const boundaryRef = useRef(null);
13
17
  const buttonRef = useRef(null);
18
+ const [innerValue, setInnerValue] = useState(props.offset === undefined ? props.defaultOffset : props.offset);
19
+ useEffect(() => {
20
+ if (props.offset === undefined) return;
21
+ api.start({
22
+ x: props.offset.x,
23
+ y: props.offset.y
24
+ });
25
+ }, [props.offset]);
14
26
  /**
15
27
  * memoize the `to` function
16
28
  * inside a component that renders frequently
@@ -21,11 +33,12 @@ export const FloatingBubble = p => {
21
33
  y,
22
34
  opacity
23
35
  }, api] = useSpring(() => ({
24
- x: 0,
25
- y: 0,
36
+ x: innerValue.x,
37
+ y: innerValue.y,
26
38
  opacity: 1
27
39
  }));
28
40
  const bind = useDrag(state => {
41
+ var _a;
29
42
  let nextX = state.offset[0];
30
43
  let nextY = state.offset[1];
31
44
  if (state.last && props.magnetic) {
@@ -54,10 +67,17 @@ export const FloatingBubble = p => {
54
67
  }
55
68
  }
56
69
  }
57
- api.start({
70
+ const nextOffest = {
58
71
  x: nextX,
59
72
  y: nextY
60
- });
73
+ };
74
+ if (props.offset === undefined) {
75
+ // Uncontrolled mode
76
+ api.start(nextOffest);
77
+ } else {
78
+ setInnerValue(nextOffest);
79
+ }
80
+ (_a = props.onOffsetChange) === null || _a === void 0 ? void 0 : _a.call(props, nextOffest);
61
81
  // active status
62
82
  api.start({
63
83
  opacity: state.active ? 0.8 : 1
@@ -3,7 +3,7 @@ import { NativeProps } from '../../utils/native-props';
3
3
  import { ListProps } from '../list';
4
4
  import type { FormProps as RcFormProps, FormInstance as RCFormInstance } from 'rc-field-form';
5
5
  import { FormContextType } from './context';
6
- export declare type FormInstance = Pick<RCFormInstance, 'getFieldValue' | 'getFieldsValue' | 'getFieldError' | 'getFieldsError' | 'isFieldTouched' | 'isFieldsTouched' | 'resetFields' | 'setFields' | 'setFieldsValue' | 'submit' | 'validateFields'>;
6
+ export declare type FormInstance = Pick<RCFormInstance, 'getFieldValue' | 'getFieldsValue' | 'getFieldError' | 'getFieldsError' | 'isFieldTouched' | 'isFieldsTouched' | 'resetFields' | 'setFields' | 'setFieldValue' | 'setFieldsValue' | 'submit' | 'validateFields'>;
7
7
  export declare type FormProps = Pick<RcFormProps, 'form' | 'initialValues' | 'name' | 'preserve' | 'validateMessages' | 'validateTrigger' | 'onFieldsChange' | 'onFinish' | 'onFinishFailed' | 'onValuesChange' | 'children'> & NativeProps<'--border-inner' | '--border-top' | '--border-bottom' | '--prefix-width'> & Partial<FormContextType> & {
8
8
  footer?: ReactNode;
9
9
  mode?: ListProps['mode'];
@@ -1,9 +1,16 @@
1
1
  .adm-image-uploader {
2
2
  --cell-size: 160px;
3
+ --gap: 24px;
4
+ ---gap: var(--gap);
5
+ ---gap-horizontal: var(--gap-horizontal, var(--gap));
6
+ ---gap-vertical: var(--gap-vertical, var(--gap));
3
7
  }
4
8
 
9
+ .adm-image-uploader-grid,
5
10
  .adm-image-uploader-space {
6
- --gap: 24px;
11
+ --gap: var(---gap);
12
+ --gap-horizontal: var(---gap-horizontal);
13
+ --gap-vertical: var(---gap-vertical);
7
14
  }
8
15
 
9
16
  .adm-image-uploader-cell {
@@ -94,4 +101,12 @@
94
101
  width: 100%;
95
102
  height: 100%;
96
103
  border-radius: 8px;
104
+ }
105
+
106
+ .adm-image-uploader .adm-image-uploader-gap-measure {
107
+ position: absolute;
108
+ left: 0;
109
+ top: 0;
110
+ height: var(--gap-horizontal);
111
+ width: 0;
97
112
  }
@@ -1,6 +1,7 @@
1
1
  import React, { FC, InputHTMLAttributes } from 'react';
2
2
  import { NativeProps } from '../../utils/native-props';
3
3
  import type { ImageProps } from '../image';
4
+ import { GridProps } from '../grid';
4
5
  export declare type TaskStatus = 'pending' | 'fail' | 'success';
5
6
  export interface ImageUploadItem {
6
7
  key?: string | number;
@@ -18,6 +19,7 @@ export declare type UploadTask = Pick<Task, 'id' | 'status'>;
18
19
  export declare type ImageUploaderProps = {
19
20
  defaultValue?: ImageUploadItem[];
20
21
  value?: ImageUploadItem[];
22
+ columns?: GridProps['columns'];
21
23
  onChange?: (items: ImageUploadItem[]) => void;
22
24
  onUploadQueueChange?: (tasks: UploadTask[]) => void;
23
25
  accept?: string;
@@ -27,6 +29,7 @@ export declare type ImageUploaderProps = {
27
29
  disableUpload?: boolean;
28
30
  showUpload?: boolean;
29
31
  deletable?: boolean;
32
+ deleteIcon?: React.ReactNode;
30
33
  capture?: InputHTMLAttributes<unknown>['capture'];
31
34
  onPreview?: (index: number, item: ImageUploadItem) => void;
32
35
  beforeUpload?: (file: File, files: File[]) => Promise<File | null> | File | null;
@@ -37,6 +40,6 @@ export declare type ImageUploaderProps = {
37
40
  imageFit?: ImageProps['fit'];
38
41
  children?: React.ReactNode;
39
42
  renderItem?: (originNode: React.ReactElement, file: ImageUploadItem, fileList: ImageUploadItem[]) => React.ReactNode;
40
- } & NativeProps<'--cell-size'>;
43
+ } & NativeProps<'--cell-size' | '--gap' | '--gap-vertical' | '--gap-horizontal'>;
41
44
  export declare const ImageUploader: FC<ImageUploaderProps>;
42
45
  export {};
@@ -1,18 +1,23 @@
1
1
  import { __awaiter } from "tslib";
2
2
  import React, { useRef, useState } from 'react';
3
- import { AddOutline } from 'antd-mobile-icons';
3
+ import { AddOutline, CloseOutline } from 'antd-mobile-icons';
4
4
  import { mergeProps } from '../../utils/with-default-props';
5
5
  import ImageViewer from '../image-viewer';
6
6
  import PreviewItem from './preview-item';
7
7
  import { usePropsValue } from '../../utils/use-props-value';
8
- import { useIsomorphicLayoutEffect, useUnmount } from 'ahooks';
8
+ import { useIsomorphicLayoutEffect, useUnmount, useSize } from 'ahooks';
9
9
  import Space from '../space';
10
10
  import { withNativeProps } from '../../utils/native-props';
11
+ import { measureCSSLength } from '../../utils/measure-css-length';
11
12
  import { useConfig } from '../config-provider';
13
+ import Grid from '../grid';
12
14
  const classPrefix = `adm-image-uploader`;
13
15
  const defaultProps = {
14
16
  disableUpload: false,
15
17
  deletable: true,
18
+ deleteIcon: React.createElement(CloseOutline, {
19
+ className: `${classPrefix}-cell-delete-icon`
20
+ }),
16
21
  showUpload: true,
17
22
  multiple: false,
18
23
  maxCount: 0,
@@ -27,8 +32,26 @@ export const ImageUploader = p => {
27
32
  locale
28
33
  } = useConfig();
29
34
  const props = mergeProps(defaultProps, p);
35
+ const {
36
+ columns
37
+ } = props;
30
38
  const [value, setValue] = usePropsValue(props);
31
39
  const [tasks, setTasks] = useState([]);
40
+ const containerRef = useRef(null);
41
+ const containerSize = useSize(containerRef);
42
+ const gapMeasureRef = useRef(null);
43
+ const [cellSize, setCellSize] = useState(80);
44
+ useIsomorphicLayoutEffect(() => {
45
+ const gapMeasure = gapMeasureRef.current;
46
+ if (columns && containerSize && gapMeasure) {
47
+ const width = containerSize.width;
48
+ const gap = measureCSSLength(window.getComputedStyle(gapMeasure).getPropertyValue('height'));
49
+ setCellSize((width - gap * (columns - 1)) / columns);
50
+ }
51
+ }, [containerSize === null || containerSize === void 0 ? void 0 : containerSize.width]);
52
+ const style = {
53
+ '--cell-size': cellSize + 'px'
54
+ };
32
55
  useIsomorphicLayoutEffect(() => {
33
56
  setTasks(prev => prev.filter(task => {
34
57
  if (task.url === undefined) return true;
@@ -152,6 +175,7 @@ export const ImageUploader = p => {
152
175
  key: (_a = fileItem.key) !== null && _a !== void 0 ? _a : index,
153
176
  url: (_b = fileItem.thumbnailUrl) !== null && _b !== void 0 ? _b : fileItem.url,
154
177
  deletable: props.deletable,
178
+ deleteIcon: props.deleteIcon,
155
179
  imageFit: props.imageFit,
156
180
  onClick: () => {
157
181
  if (props.preview) {
@@ -169,21 +193,19 @@ export const ImageUploader = p => {
169
193
  return renderItem ? renderItem(originNode, fileItem, value) : originNode;
170
194
  });
171
195
  };
172
- return withNativeProps(props, React.createElement("div", {
173
- className: classPrefix
174
- }, React.createElement(Space, {
175
- className: `${classPrefix}-space`,
176
- wrap: true,
177
- block: true
178
- }, renderImages(), finalTasks.map(task => {
196
+ const contentNode = React.createElement(React.Fragment, null, renderImages(), tasks.map(task => {
197
+ if (!props.showFailed && task.status === 'fail') {
198
+ return null;
199
+ }
179
200
  return React.createElement(PreviewItem, {
180
201
  key: task.id,
181
202
  file: task.file,
182
203
  deletable: task.status !== 'pending',
204
+ deleteIcon: props.deleteIcon,
183
205
  status: task.status,
184
206
  imageFit: props.imageFit,
185
207
  onDelete: () => {
186
- setTasks(prev => prev.filter(x => x.id !== task.id));
208
+ setTasks(tasks.filter(x => x.id !== task.id));
187
209
  }
188
210
  });
189
211
  }), showUpload && React.createElement("div", {
@@ -202,5 +224,20 @@ export const ImageUploader = p => {
202
224
  className: `${classPrefix}-input`,
203
225
  onChange: onChange,
204
226
  "aria-hidden": true
205
- })))));
227
+ })));
228
+ return withNativeProps(props, React.createElement("div", {
229
+ className: classPrefix,
230
+ ref: containerRef
231
+ }, columns ? React.createElement(Grid, {
232
+ className: `${classPrefix}-grid`,
233
+ columns: columns,
234
+ style: style
235
+ }, React.createElement("div", {
236
+ className: `${classPrefix}-gap-measure`,
237
+ ref: gapMeasureRef
238
+ }), contentNode.props.children) : React.createElement(Space, {
239
+ className: `${classPrefix}-space`,
240
+ wrap: true,
241
+ block: true
242
+ }, contentNode.props.children)));
206
243
  };
@@ -1,10 +1,11 @@
1
- import { FC } from 'react';
1
+ import React, { FC } from 'react';
2
2
  import { TaskStatus } from './image-uploader';
3
3
  import type { ImageProps } from '../image';
4
4
  declare type Props = {
5
5
  onClick?: () => void;
6
6
  onDelete?: () => void;
7
7
  deletable: boolean;
8
+ deleteIcon: React.ReactNode;
8
9
  url?: string;
9
10
  file?: File;
10
11
  status?: TaskStatus;
@@ -1,5 +1,4 @@
1
- import React, { useLayoutEffect, useMemo } from 'react';
2
- import { CloseOutline } from 'antd-mobile-icons';
1
+ import React, { useEffect, useMemo } from 'react';
3
2
  import classNames from 'classnames';
4
3
  import Image from '../image';
5
4
  import SpinLoading from '../spin-loading';
@@ -13,6 +12,7 @@ const PreviewItem = props => {
13
12
  url,
14
13
  file,
15
14
  deletable,
15
+ deleteIcon,
16
16
  onDelete,
17
17
  imageFit
18
18
  } = props;
@@ -25,11 +25,11 @@ const PreviewItem = props => {
25
25
  }
26
26
  return '';
27
27
  }, [url, file]);
28
- useLayoutEffect(() => {
28
+ useEffect(() => {
29
29
  return () => {
30
- URL.revokeObjectURL(src);
30
+ if (file) URL.revokeObjectURL(src);
31
31
  };
32
- }, [src]);
32
+ }, [src, file]);
33
33
  function renderLoading() {
34
34
  return props.status === 'pending' && React.createElement("div", {
35
35
  className: `${classPrefix}-cell-mask`
@@ -45,9 +45,7 @@ const PreviewItem = props => {
45
45
  return deletable && React.createElement("span", {
46
46
  className: `${classPrefix}-cell-delete`,
47
47
  onClick: onDelete
48
- }, React.createElement(CloseOutline, {
49
- className: `${classPrefix}-cell-delete-icon`
50
- }));
48
+ }, deleteIcon);
51
49
  }
52
50
  return React.createElement("div", {
53
51
  className: classNames(`${classPrefix}-cell`, props.status === 'fail' && `${classPrefix}-cell-fail`)
@@ -8,7 +8,7 @@ export declare type MaskProps = {
8
8
  destroyOnClose?: boolean;
9
9
  forceRender?: boolean;
10
10
  disableBodyScroll?: boolean;
11
- color?: 'black' | 'white';
11
+ color?: 'white' | 'black' | (string & {});
12
12
  opacity?: 'default' | 'thin' | 'thick' | number;
13
13
  getContainer?: GetContainer;
14
14
  afterShow?: () => void;
@@ -14,6 +14,10 @@ const opacityRecord = {
14
14
  thin: 0.35,
15
15
  thick: 0.75
16
16
  };
17
+ const colorRecord = {
18
+ black: '0, 0, 0',
19
+ white: '255, 255, 255'
20
+ };
17
21
  const defaultProps = {
18
22
  visible: true,
19
23
  destroyOnClose: false,
@@ -34,8 +38,8 @@ export const Mask = p => {
34
38
  const background = useMemo(() => {
35
39
  var _a;
36
40
  const opacity = (_a = opacityRecord[props.opacity]) !== null && _a !== void 0 ? _a : props.opacity;
37
- const rgb = props.color === 'white' ? '255, 255, 255' : '0, 0, 0';
38
- return `rgba(${rgb}, ${opacity})`;
41
+ const rgb = colorRecord[props.color];
42
+ return rgb ? `rgba(${rgb}, ${opacity})` : props.color;
39
43
  }, [props.color, props.opacity]);
40
44
  const [active, setActive] = useState(props.visible);
41
45
  const unmountedRef = useUnmountedRef();
@@ -4,11 +4,10 @@
4
4
  --text-color: var(--adm-color-white);
5
5
  --font-size: var(--adm-font-size-7);
6
6
  --icon-font-size: var(--adm-font-size-10);
7
- --height: 76px;
7
+ --height: 80px;
8
8
  height: var(--height);
9
9
  box-sizing: border-box;
10
10
  font-size: var(--font-size);
11
- line-height: var(--height);
12
11
  padding: 0 24px;
13
12
  display: flex;
14
13
  align-items: center;
@@ -46,7 +45,6 @@
46
45
  flex-shrink: 0;
47
46
  margin-right: 16px;
48
47
  font-size: var(--icon-font-size);
49
- line-height: var(--height);
50
48
  }
51
49
 
52
50
  .adm-notice-bar .adm-notice-bar-content {
@@ -61,10 +59,13 @@
61
59
  .adm-notice-bar .adm-notice-bar-content .adm-notice-bar-content-inner {
62
60
  width: auto;
63
61
  transition-timing-function: linear;
64
- position: absolute;
65
62
  white-space: nowrap;
66
63
  }
67
64
 
65
+ .adm-notice-bar-wrap.adm-notice-bar .adm-notice-bar-content .adm-notice-bar-content-inner {
66
+ white-space: normal;
67
+ }
68
+
68
69
  .adm-notice-bar .adm-notice-bar-right {
69
70
  flex-shrink: 0;
70
71
  margin-left: 24px;
@@ -81,4 +82,12 @@
81
82
 
82
83
  .adm-notice-bar-close-icon {
83
84
  font-size: var(--adm-font-size-10);
85
+ }
86
+
87
+ .adm-notice-bar-wrap {
88
+ height: auto;
89
+ align-items: flex-start;
90
+ padding-top: 16px;
91
+ padding-bottom: 16px;
92
+ line-height: 44px;
84
93
  }
@@ -1,21 +1,23 @@
1
1
  import React from 'react';
2
2
  import { NativeProps } from '../../utils/native-props';
3
3
  export declare type NoticeBarProps = {
4
- /** 通告栏的类型 */
4
+ /** The type of the NoticeBar */
5
5
  color?: 'default' | 'alert' | 'error' | 'info';
6
- /** 开始滚动的延迟,单位 ms */
6
+ /** TDelay to start scrolling, unit ms */
7
7
  delay?: number;
8
- /** 滚动速度,单位 px/s */
8
+ /** Scroll speed, unit px/s */
9
9
  speed?: number;
10
- /** 公告内容 */
10
+ /** The content of the NoticeBar */
11
11
  content: React.ReactNode;
12
- /** 是否可关闭 */
12
+ /** Whether it can be closed */
13
13
  closeable?: boolean;
14
- /** 关闭时的回调 */
14
+ /** Callback when closed */
15
15
  onClose?: () => void;
16
- /** 额外操作区域,显示在关闭按钮左侧 */
16
+ /** Additional operating area, displayed to the left of the close button */
17
17
  extra?: React.ReactNode;
18
- /** 左侧广播图标 */
18
+ /** Radio icon on the left */
19
19
  icon?: React.ReactNode;
20
+ /** Whether to display multiple lines */
21
+ wrap?: boolean;
20
22
  } & NativeProps<'--background-color' | '--border-color' | '--text-color' | '--font-size' | '--icon-font-size' | '--height'>;
21
23
  export declare const NoticeBar: React.NamedExoticComponent<NoticeBarProps>;
@@ -11,6 +11,7 @@ const defaultProps = {
11
11
  color: 'default',
12
12
  delay: 2000,
13
13
  speed: 50,
14
+ wrap: false,
14
15
  icon: React.createElement(SoundOutline, null)
15
16
  };
16
17
  export const NoticeBar = memo(p => {
@@ -22,7 +23,7 @@ export const NoticeBar = memo(p => {
22
23
  const delayLockRef = useRef(true);
23
24
  const animatingRef = useRef(false);
24
25
  function start() {
25
- if (delayLockRef.current) return;
26
+ if (delayLockRef.current || props.wrap) return;
26
27
  const container = containerRef.current;
27
28
  const text = textRef.current;
28
29
  if (!container || !text) return;
@@ -61,7 +62,9 @@ export const NoticeBar = memo(p => {
61
62
  });
62
63
  if (!visible) return null;
63
64
  return withNativeProps(props, React.createElement("div", {
64
- className: classNames(classPrefix, `${classPrefix}-${props.color}`)
65
+ className: classNames(classPrefix, `${classPrefix}-${props.color}`, {
66
+ [`${classPrefix}-wrap`]: props.wrap
67
+ })
65
68
  }, props.icon && React.createElement("span", {
66
69
  className: `${classPrefix}-left`
67
70
  }, props.icon), React.createElement("span", {
@@ -20,6 +20,8 @@ export declare type StepperProps = Pick<InputProps, 'onFocus' | 'onBlur'> & (Val
20
20
  digits?: number;
21
21
  disabled?: boolean;
22
22
  inputReadOnly?: boolean;
23
+ parser?: (text: string) => number;
24
+ formatter?: (value?: number) => string;
23
25
  } & NativeProps<'--height' | '--input-width' | '--input-font-size' | '--input-background-color' | '--border-radius' | '--border' | '--border-inner' | '--active-border' | '--button-font-size' | '--button-background-color' | '--button-width' | '--input-font-color' | '--button-text-color'>;
24
26
  export declare const Stepper: FC<StepperProps>;
25
27
  export {};