@arco-design/mobile-react 2.35.2 → 2.36.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.
- package/CHANGELOG.md +18 -0
- package/README.en-US.md +2 -2
- package/README.md +2 -2
- package/cjs/_helpers/hooks.d.ts +10 -2
- package/cjs/_helpers/hooks.js +12 -5
- package/cjs/date-picker/index.js +218 -18
- package/cjs/date-picker/style/css/index.css +42 -0
- package/cjs/date-picker/style/index.less +38 -1
- package/cjs/date-picker/type.d.ts +22 -6
- package/cjs/form/linked-container.d.ts +2 -2
- package/cjs/form/linked-container.js +5 -1
- package/cjs/picker/index.js +3 -2
- package/cjs/picker/type.d.ts +5 -0
- package/cjs/search-bar/association.js +2 -2
- package/cjs/search-bar/type.d.ts +1 -1
- package/cjs/stepper/hooks/useValue.js +3 -1
- package/cjs/tabs/index.js +1 -1
- package/cjs/tabs/type.d.ts +2 -2
- package/dist/index.js +272 -38
- package/dist/index.min.js +4 -4
- package/dist/style.css +23 -0
- package/dist/style.min.css +1 -1
- package/esm/_helpers/hooks.d.ts +10 -2
- package/esm/_helpers/hooks.js +12 -5
- package/esm/date-picker/index.js +218 -18
- package/esm/date-picker/style/css/index.css +42 -0
- package/esm/date-picker/style/index.less +38 -1
- package/esm/date-picker/type.d.ts +22 -6
- package/esm/form/linked-container.d.ts +2 -2
- package/esm/form/linked-container.js +5 -1
- package/esm/picker/index.js +3 -2
- package/esm/picker/type.d.ts +5 -0
- package/esm/search-bar/association.js +2 -2
- package/esm/search-bar/type.d.ts +1 -1
- package/esm/stepper/hooks/useValue.js +1 -0
- package/esm/tabs/index.js +1 -1
- package/esm/tabs/type.d.ts +2 -2
- package/esnext/_helpers/hooks.d.ts +10 -2
- package/esnext/_helpers/hooks.js +12 -5
- package/esnext/date-picker/index.js +167 -10
- package/esnext/date-picker/style/css/index.css +42 -0
- package/esnext/date-picker/style/index.less +38 -1
- package/esnext/date-picker/type.d.ts +22 -6
- package/esnext/form/linked-container.d.ts +2 -2
- package/esnext/form/linked-container.js +7 -2
- package/esnext/picker/index.js +2 -1
- package/esnext/picker/type.d.ts +5 -0
- package/esnext/search-bar/association.js +1 -1
- package/esnext/search-bar/type.d.ts +1 -1
- package/esnext/stepper/hooks/useValue.js +1 -0
- package/esnext/tabs/index.js +1 -1
- package/esnext/tabs/type.d.ts +2 -2
- package/package.json +3 -3
- package/tokens/app/arcodesign/default/css-variables.less +10 -0
- package/tokens/app/arcodesign/default/index.d.ts +10 -0
- package/tokens/app/arcodesign/default/index.js +11 -1
- package/tokens/app/arcodesign/default/index.json +108 -0
- package/tokens/app/arcodesign/default/index.less +10 -0
- package/umd/_helpers/hooks.d.ts +10 -2
- package/umd/_helpers/hooks.js +12 -5
- package/umd/date-picker/index.js +218 -18
- package/umd/date-picker/style/css/index.css +42 -0
- package/umd/date-picker/style/index.less +38 -1
- package/umd/date-picker/type.d.ts +22 -6
- package/umd/form/linked-container.d.ts +2 -2
- package/umd/form/linked-container.js +5 -1
- package/umd/picker/index.js +3 -2
- package/umd/picker/type.d.ts +5 -0
- package/umd/search-bar/association.js +2 -2
- package/umd/search-bar/type.d.ts +1 -1
- package/umd/stepper/hooks/useValue.js +5 -5
- package/umd/tabs/index.js +1 -1
- package/umd/tabs/type.d.ts +2 -2
package/esm/tabs/type.d.ts
CHANGED
@@ -561,8 +561,8 @@ export interface TabCellRef {
|
|
561
561
|
*/
|
562
562
|
setCaterpillarAnimate: (ratio?: number) => void;
|
563
563
|
/**
|
564
|
-
*
|
565
|
-
* @en Recalculate underline style
|
564
|
+
* 重新计算下划线样式(仅重算位置,如果 tab cell DOM 被人为改变,请调用 updateLayout)
|
565
|
+
* @en Recalculate underline style (only recalculate position, if the tab cell DOM is changed manually, please call updateLayout)
|
566
566
|
*/
|
567
567
|
resetUnderlineStyle: () => void;
|
568
568
|
/**
|
@@ -4,6 +4,7 @@
|
|
4
4
|
* @name_en General Hooks
|
5
5
|
*/
|
6
6
|
import React from 'react';
|
7
|
+
import type { SystemOptions } from '@arco-design/mobile-utils';
|
7
8
|
import { BezierType } from '../progress';
|
8
9
|
/**
|
9
10
|
* 监听页面resize事件的统一封装
|
@@ -130,15 +131,22 @@ export declare function useLatestRef<T>(variable: T): React.MutableRefObject<T>;
|
|
130
131
|
/**
|
131
132
|
* 从navigator.userAgent中获取当前操作系统,如果无法获取ua,则从ContextProvider传入的system中获取值
|
132
133
|
* @desc {en} Get the current operating system from navigator.userAgent, if ua cannot be obtained, get the value from the system passed in by ContextProvider
|
133
|
-
* @
|
134
|
+
* @param options 配置选项
|
135
|
+
* @param {en} options Configuration options
|
136
|
+
* @param options.detectHarmony 是否识别鸿蒙系统,默认为 false,鸿蒙系统会被识别为 android
|
137
|
+
* @param {en} options.detectHarmony Whether to detect HarmonyOS separately, default is false, HarmonyOS will be recognized as android
|
138
|
+
* @returns 返回当前设备的操作系统,可能的值包括 'android'、'ios'、'harmony' 或 'pc',如果无法获取,则返回空字符串
|
139
|
+
* @returns {en} Returns the operating system of the current device, possible values are 'android', 'ios', 'harmony', or 'pc'. Returns an empty string if it cannot be obtained
|
134
140
|
* @example
|
135
141
|
* ```
|
136
142
|
* import { useSystem } from '@arco-design/mobile-react/esm/_helpers/hooks';
|
137
143
|
*
|
138
144
|
* const system = useSystem();
|
145
|
+
* // Or with options
|
146
|
+
* const systemWithHarmony = useSystem({ detectHarmony: true });
|
139
147
|
* ```
|
140
148
|
*/
|
141
|
-
export declare function useSystem(): "" | "android" | "ios" | "pc";
|
149
|
+
export declare function useSystem(options?: SystemOptions): "" | "android" | "harmony" | "ios" | "pc";
|
142
150
|
/**
|
143
151
|
* 获取页面视口宽高大小,并在页面有resize时更新大小
|
144
152
|
* @desc {en} Get the width and height of the page viewport, and update the size when the page is resized
|
package/esnext/_helpers/hooks.js
CHANGED
@@ -206,20 +206,27 @@ export function useLatestRef(variable) {
|
|
206
206
|
/**
|
207
207
|
* 从navigator.userAgent中获取当前操作系统,如果无法获取ua,则从ContextProvider传入的system中获取值
|
208
208
|
* @desc {en} Get the current operating system from navigator.userAgent, if ua cannot be obtained, get the value from the system passed in by ContextProvider
|
209
|
-
* @
|
209
|
+
* @param options 配置选项
|
210
|
+
* @param {en} options Configuration options
|
211
|
+
* @param options.detectHarmony 是否识别鸿蒙系统,默认为 false,鸿蒙系统会被识别为 android
|
212
|
+
* @param {en} options.detectHarmony Whether to detect HarmonyOS separately, default is false, HarmonyOS will be recognized as android
|
213
|
+
* @returns 返回当前设备的操作系统,可能的值包括 'android'、'ios'、'harmony' 或 'pc',如果无法获取,则返回空字符串
|
214
|
+
* @returns {en} Returns the operating system of the current device, possible values are 'android', 'ios', 'harmony', or 'pc'. Returns an empty string if it cannot be obtained
|
210
215
|
* @example
|
211
216
|
* ```
|
212
217
|
* import { useSystem } from '@arco-design/mobile-react/esm/_helpers/hooks';
|
213
218
|
*
|
214
219
|
* const system = useSystem();
|
220
|
+
* // Or with options
|
221
|
+
* const systemWithHarmony = useSystem({ detectHarmony: true });
|
215
222
|
* ```
|
216
223
|
*/
|
217
|
-
export function useSystem() {
|
224
|
+
export function useSystem(options) {
|
218
225
|
const { system: currentSystem } = useContext(GlobalContext);
|
219
|
-
const [system, setSystem] = useState(() => currentSystem || getSystem());
|
226
|
+
const [system, setSystem] = useState(() => currentSystem || getSystem(options));
|
220
227
|
useEffect(() => {
|
221
|
-
setSystem(currentSystem || getSystem());
|
222
|
-
}, [currentSystem]);
|
228
|
+
setSystem(currentSystem || getSystem(options));
|
229
|
+
}, [currentSystem, options]);
|
223
230
|
return system;
|
224
231
|
}
|
225
232
|
/**
|
@@ -11,15 +11,45 @@ const initMinDate = Date.now() - 10 * YEAR;
|
|
11
11
|
const initMaxDate = Date.now() + 10 * YEAR;
|
12
12
|
const initDate = Date.now();
|
13
13
|
const DatePicker = forwardRef((props, ref) => {
|
14
|
-
const { currentTs: userSetCurrentTs = initDate, className = '', visible = false, onOk, onChange, onValueChange, mode = 'datetime', typeArr = [], minTs = initMinDate, maxTs = initMaxDate, formatter = defaultFormatter, valueFilter = () => true, columnsProcessor, touchToStop, useUTC = false, renderLinkedContainer, ...otherProps } = props;
|
15
|
-
const
|
14
|
+
const { currentTs: userSetCurrentTs = initDate, className = '', visible = false, onOk, onChange, onValueChange, mode = 'datetime', typeArr = [], minTs: userSetMinTs = initMinDate, maxTs: userSetMaxTs = initMaxDate, rangeItemFormat, formatter = defaultFormatter, valueFilter = () => true, columnsProcessor, touchToStop, useUTC = false, renderSeparator, renderLinkedContainer, ...otherProps } = props;
|
15
|
+
const isRange = typeof userSetCurrentTs !== 'number';
|
16
|
+
const [leftTimeValue, setLeftTimeValue] = useState(userSetCurrentTs[0]);
|
17
|
+
const [rightTimeValue, setRightTimeValue] = useState(userSetCurrentTs[1]);
|
18
|
+
const [activeTabIndex, setActiveTabIndex] = useState(0);
|
19
|
+
const [minTs, maxTs] = useMemo(() => {
|
20
|
+
return _updateTimeScope();
|
21
|
+
}, [userSetMinTs, userSetMaxTs, activeTabIndex]);
|
22
|
+
const [currentTs, setCurrentTs] = useState(isRange
|
23
|
+
? Math.min(maxTs, Math.max(minTs, userSetCurrentTs[0]))
|
24
|
+
: Math.min(maxTs, Math.max(minTs, userSetCurrentTs)));
|
16
25
|
const [data, setData] = useState([[]]);
|
17
26
|
const [value, setValue] = useState([]);
|
18
27
|
const currentDateObjRef = useRef(_convertTsToDateObj(currentTs));
|
19
28
|
const minDateObjRef = useRef(_convertTsToDateObj(minTs));
|
20
29
|
const maxDateObjRef = useRef(_convertTsToDateObj(maxTs));
|
21
30
|
const keyOptions = useMemo(() => _getKeyOptions(), [mode, typeArr]);
|
31
|
+
const leftTimeString = useMemo(() => _getRangeItemValue(leftTimeValue), [leftTimeValue]);
|
32
|
+
const rightTimeString = useMemo(() => _getRangeItemValue(rightTimeValue), [rightTimeValue]);
|
22
33
|
const pickerRef = useRef(null);
|
34
|
+
function _updateRangeValue(nowCurrentTs) {
|
35
|
+
const leftMinTs = typeof userSetMinTs !== 'number' ? userSetMinTs.startTs : userSetMinTs;
|
36
|
+
const rightMinTs = typeof userSetMinTs !== 'number' ? userSetMinTs.endTs : userSetMinTs;
|
37
|
+
const leftMaxTs = typeof userSetMaxTs !== 'number' ? userSetMaxTs.startTs : userSetMaxTs;
|
38
|
+
const rightMaxTs = typeof userSetMaxTs !== 'number' ? userSetMaxTs.endTs : userSetMaxTs;
|
39
|
+
if (isRange) {
|
40
|
+
let leftTime, rightTime;
|
41
|
+
if (activeTabIndex === 0) {
|
42
|
+
leftTime = nowCurrentTs;
|
43
|
+
rightTime = Math.min(rightMaxTs, Math.max(Math.max(leftTime, rightMinTs), rightTimeValue));
|
44
|
+
}
|
45
|
+
else {
|
46
|
+
rightTime = nowCurrentTs;
|
47
|
+
leftTime = Math.min(leftMaxTs, Math.max(leftMinTs, leftTimeValue));
|
48
|
+
}
|
49
|
+
setLeftTimeValue(leftTime);
|
50
|
+
setRightTimeValue(rightTime);
|
51
|
+
}
|
52
|
+
}
|
23
53
|
useImperativeHandle(ref, () => ({
|
24
54
|
dom: pickerRef.current ? pickerRef.current.dom : null,
|
25
55
|
}));
|
@@ -34,6 +64,61 @@ const DatePicker = forwardRef((props, ref) => {
|
|
34
64
|
dateObj,
|
35
65
|
};
|
36
66
|
}
|
67
|
+
function _parseFormat(format, timeValue) {
|
68
|
+
const { year, month, date, hour, minute, second } = timeValue;
|
69
|
+
const padZero = (num, targetLength = 2) => {
|
70
|
+
let str = `${num}`;
|
71
|
+
while (str.length < targetLength) {
|
72
|
+
str = `0${str}`;
|
73
|
+
}
|
74
|
+
return str;
|
75
|
+
};
|
76
|
+
const replace = (formatArg, str, num) => {
|
77
|
+
if (formatArg.includes(str)) {
|
78
|
+
return str !== 'Y'
|
79
|
+
? formatArg.replace(str.repeat(2), padZero(num)).replace(str, padZero(num))
|
80
|
+
: formatArg
|
81
|
+
.replace(str.repeat(4), padZero(num))
|
82
|
+
.replace(str.repeat(2), padZero(num))
|
83
|
+
.replace(str, padZero(num));
|
84
|
+
}
|
85
|
+
return formatArg;
|
86
|
+
};
|
87
|
+
return [
|
88
|
+
['Y', year],
|
89
|
+
['M', month],
|
90
|
+
['D', date],
|
91
|
+
['H', hour],
|
92
|
+
['m', minute],
|
93
|
+
['s', second],
|
94
|
+
].reduce((current, item) => {
|
95
|
+
return replace(current, item[0], item[1]);
|
96
|
+
}, format);
|
97
|
+
}
|
98
|
+
function _getRangeItemValue(time) {
|
99
|
+
const timeValue = _convertTsToDateObj(time);
|
100
|
+
if (!isRange) {
|
101
|
+
return;
|
102
|
+
}
|
103
|
+
if (rangeItemFormat) {
|
104
|
+
return _parseFormat(rangeItemFormat, timeValue);
|
105
|
+
}
|
106
|
+
const format = (options, joinString) => {
|
107
|
+
return options
|
108
|
+
.filter(option => {
|
109
|
+
return keyOptions.includes(option);
|
110
|
+
})
|
111
|
+
.map(option => {
|
112
|
+
return timeValue[option] < 10
|
113
|
+
? `0${timeValue[option]}`
|
114
|
+
: `${timeValue[option]}`;
|
115
|
+
})
|
116
|
+
.join(joinString);
|
117
|
+
};
|
118
|
+
const datePart = format(['year', 'month', 'date'], '/');
|
119
|
+
const timePart = format(['hour', 'minute', 'second'], ':');
|
120
|
+
return datePart + (datePart && timePart && ' ') + timePart;
|
121
|
+
}
|
37
122
|
function _getSelectValue(columns) {
|
38
123
|
const val = keyOptions.map((opt, index) => {
|
39
124
|
const curCol = columns[index] || [];
|
@@ -137,7 +222,7 @@ const DatePicker = forwardRef((props, ref) => {
|
|
137
222
|
}
|
138
223
|
function _handlePickerChange(values, index) {
|
139
224
|
const type = keyOptions[index];
|
140
|
-
const nowDateObj =
|
225
|
+
const nowDateObj = currentDateObjRef.current;
|
141
226
|
values.forEach((i, keyIndex) => {
|
142
227
|
nowDateObj[keyOptions[keyIndex]] = i;
|
143
228
|
});
|
@@ -155,16 +240,34 @@ const DatePicker = forwardRef((props, ref) => {
|
|
155
240
|
setData(columns);
|
156
241
|
setValue(val);
|
157
242
|
}
|
243
|
+
setCurrentTs(_convertObjToTs(nowDateObj, currentTs));
|
158
244
|
if (onValueChange) {
|
159
245
|
onValueChange(_convertObjToTs(nowDateObj, currentTs), nowDateObj, index);
|
160
246
|
}
|
161
247
|
}
|
162
248
|
function _handlePickerConfirm(values) {
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
249
|
+
let nowDateObj;
|
250
|
+
let newTs;
|
251
|
+
if (isRange) {
|
252
|
+
const leftTimeObj = _convertTsToDateObj(leftTimeValue);
|
253
|
+
const rightTimeObj = _convertTsToDateObj(rightTimeValue);
|
254
|
+
nowDateObj = keyOptions.reduce((arr, key) => {
|
255
|
+
arr[0][key] = leftTimeObj[key];
|
256
|
+
arr[1][key] = rightTimeObj[key];
|
257
|
+
return arr;
|
258
|
+
}, [{}, {}]);
|
259
|
+
newTs = [
|
260
|
+
_convertObjToTs(nowDateObj[0], currentTs),
|
261
|
+
_convertObjToTs(nowDateObj[1], currentTs),
|
262
|
+
];
|
263
|
+
}
|
264
|
+
else {
|
265
|
+
nowDateObj = {};
|
266
|
+
values.forEach((index, keyIndex) => {
|
267
|
+
nowDateObj[keyOptions[keyIndex]] = index;
|
268
|
+
});
|
269
|
+
newTs = _convertObjToTs(nowDateObj, currentTs);
|
270
|
+
}
|
168
271
|
if (onOk) {
|
169
272
|
onOk(newTs, nowDateObj);
|
170
273
|
}
|
@@ -189,19 +292,73 @@ const DatePicker = forwardRef((props, ref) => {
|
|
189
292
|
}
|
190
293
|
return options;
|
191
294
|
}
|
295
|
+
function _updateTimeScope(isLeft) {
|
296
|
+
let nowMaxTs, nowMinTs;
|
297
|
+
if (isLeft || activeTabIndex === 0) {
|
298
|
+
nowMaxTs = typeof userSetMaxTs === 'number' ? userSetMaxTs : userSetMaxTs.startTs;
|
299
|
+
nowMinTs = Math.min(nowMaxTs, typeof userSetMinTs === 'number' ? userSetMinTs : userSetMinTs.startTs);
|
300
|
+
}
|
301
|
+
else {
|
302
|
+
nowMinTs = Math.max(Math.min(typeof userSetMaxTs === 'number' ? userSetMaxTs : userSetMaxTs.startTs, leftTimeValue), typeof userSetMinTs === 'number' ? userSetMinTs : userSetMinTs.endTs);
|
303
|
+
nowMaxTs = Math.max(nowMinTs, typeof userSetMaxTs === 'number' ? userSetMaxTs : userSetMaxTs.endTs);
|
304
|
+
}
|
305
|
+
return [nowMinTs, nowMaxTs];
|
306
|
+
}
|
307
|
+
function _chooseTimeActive(index) {
|
308
|
+
setActiveTabIndex(index);
|
309
|
+
}
|
192
310
|
useEffect(() => {
|
193
311
|
minDateObjRef.current = _convertTsToDateObj(minTs);
|
194
312
|
currentDateObjRef.current = _convertTsToDateObj(currentTs);
|
195
313
|
maxDateObjRef.current = _convertTsToDateObj(maxTs);
|
196
314
|
_initData();
|
197
315
|
}, [currentTs, minTs, maxTs, useUTC]);
|
316
|
+
useEffect(() => {
|
317
|
+
let nowCurrentTs;
|
318
|
+
if (isRange) {
|
319
|
+
nowCurrentTs = Math.min(maxTs, Math.max(minTs, activeTabIndex === 0 ? leftTimeValue : rightTimeValue));
|
320
|
+
if (currentTs === nowCurrentTs) {
|
321
|
+
_updateRangeValue(currentTs);
|
322
|
+
}
|
323
|
+
}
|
324
|
+
else {
|
325
|
+
nowCurrentTs = Math.min(maxTs, Math.max(minTs, currentTs));
|
326
|
+
}
|
327
|
+
setCurrentTs(nowCurrentTs);
|
328
|
+
}, [minTs, maxTs]);
|
329
|
+
useEffect(() => {
|
330
|
+
_updateRangeValue(currentTs);
|
331
|
+
}, [currentTs]);
|
198
332
|
useEffect(() => {
|
199
333
|
if (visible) {
|
200
|
-
|
334
|
+
// 初始化当前时间
|
335
|
+
if (isRange) {
|
336
|
+
setActiveTabIndex(0);
|
337
|
+
setLeftTimeValue(userSetCurrentTs[0]);
|
338
|
+
setRightTimeValue(userSetCurrentTs[1]);
|
339
|
+
const [nowMinTs, nowMaxTs] = _updateTimeScope(true);
|
340
|
+
const nowCurrentTs = Math.min(nowMaxTs, Math.max(nowMinTs, userSetCurrentTs[0]));
|
341
|
+
setCurrentTs(nowCurrentTs);
|
342
|
+
if (currentTs === nowCurrentTs) {
|
343
|
+
_updateRangeValue(currentTs);
|
344
|
+
}
|
345
|
+
}
|
346
|
+
else {
|
347
|
+
setCurrentTs(Math.min(maxTs, Math.max(minTs, userSetCurrentTs)));
|
348
|
+
}
|
201
349
|
_initData();
|
202
350
|
}
|
203
351
|
}, [visible]);
|
204
|
-
return (React.createElement(ContextLayout, null, ({ prefixCls }) => (React.createElement(Picker, Object.assign({}, otherProps, { ref: pickerRef, visible: visible, className: cls(className, `${prefixCls}-date-picker`), cascade: false, data: data, value: value, onPickerChange: _handlePickerChange, onOk: _handlePickerConfirm, touchToStop: touchToStop,
|
352
|
+
return (React.createElement(ContextLayout, null, ({ prefixCls }) => (React.createElement(Picker, Object.assign({}, otherProps, { ref: pickerRef, visible: visible, className: cls(className, `${prefixCls}-date-picker`), cascade: false, data: data, value: value, onPickerChange: _handlePickerChange, onOk: _handlePickerConfirm, touchToStop: touchToStop, renderExtraHeader: isRange
|
353
|
+
? () => (React.createElement("div", { className: `${prefixCls}-date-picker-show` },
|
354
|
+
React.createElement("span", { className: cls(`${activeTabIndex === 0
|
355
|
+
? `${prefixCls}-date-picker-range-item-active`
|
356
|
+
: ''}`, `${prefixCls}-date-picker-range-item`), onClick: () => _chooseTimeActive(0) }, leftTimeString),
|
357
|
+
renderSeparator ? (renderSeparator()) : (React.createElement("span", { className: `${prefixCls}-date-picker-show-separate` }, "~")),
|
358
|
+
React.createElement("span", { className: cls(`${activeTabIndex === 1
|
359
|
+
? `${prefixCls}-date-picker-range-item-active`
|
360
|
+
: ''}`, `${prefixCls}-date-picker-range-item`), onClick: () => _chooseTimeActive(1) }, rightTimeString)))
|
361
|
+
: undefined, renderLinkedContainer: renderLinkedContainer
|
205
362
|
? () => renderLinkedContainer(isEmptyValue(props.currentTs) ? undefined : currentTs, keyOptions)
|
206
363
|
: undefined })))));
|
207
364
|
});
|
@@ -510,6 +510,41 @@
|
|
510
510
|
* }
|
511
511
|
* ```
|
512
512
|
*/
|
513
|
+
.arco-date-picker-show {
|
514
|
+
display: -webkit-box;
|
515
|
+
display: -webkit-flex;
|
516
|
+
display: flex;
|
517
|
+
font-size: 0.32rem ;
|
518
|
+
padding: 0 0.32rem ;
|
519
|
+
color: #c9cdd4 ;
|
520
|
+
min-height: 0.96rem ;
|
521
|
+
background-color: #FBFCFC ;
|
522
|
+
}
|
523
|
+
.arco-date-picker-show > span {
|
524
|
+
display: -webkit-box;
|
525
|
+
display: -webkit-flex;
|
526
|
+
display: flex;
|
527
|
+
-webkit-box-align: center;
|
528
|
+
-webkit-align-items: center;
|
529
|
+
align-items: center;
|
530
|
+
-webkit-box-pack: center;
|
531
|
+
-webkit-justify-content: center;
|
532
|
+
justify-content: center;
|
533
|
+
}
|
534
|
+
.arco-date-picker-show-separate {
|
535
|
+
-webkit-box-flex: 0;
|
536
|
+
-webkit-flex: 0 1 auto;
|
537
|
+
flex: 0 1 auto;
|
538
|
+
min-width: 0.96rem ;
|
539
|
+
}
|
540
|
+
.arco-date-picker-range-item {
|
541
|
+
-webkit-box-flex: 1;
|
542
|
+
-webkit-flex: 1 0 auto;
|
543
|
+
flex: 1 0 auto;
|
544
|
+
}
|
545
|
+
.arco-date-picker-range-item-active {
|
546
|
+
color: #1d2129 ;
|
547
|
+
}
|
513
548
|
/***************************************************
|
514
549
|
* *
|
515
550
|
* Arco Theme Style *
|
@@ -523,4 +558,11 @@
|
|
523
558
|
background: #2e2e30 ;
|
524
559
|
color: #929293 ;
|
525
560
|
}
|
561
|
+
.arco-theme-dark .arco-date-picker-show {
|
562
|
+
color: #5f5f60 ;
|
563
|
+
background-color: #1E1E1E ;
|
564
|
+
}
|
565
|
+
.arco-theme-dark .arco-date-picker-range-item-active {
|
566
|
+
color: #f6f6f6 ;
|
567
|
+
}
|
526
568
|
/********************* End *************************/
|
@@ -1,7 +1,29 @@
|
|
1
1
|
@import '../../../style/mixin.less';
|
2
2
|
|
3
3
|
.@{prefix}-date-picker {
|
4
|
-
|
4
|
+
&-show {
|
5
|
+
display: flex;
|
6
|
+
.use-var(font-size, date-picker-range-font-size);
|
7
|
+
.use-var(padding, date-picker-range-show-padding);
|
8
|
+
.use-var(color, date-picker-range-disabled-font-color);
|
9
|
+
.use-var(min-height, date-picker-range-show-min-height);
|
10
|
+
.use-var(background-color, date-picker-range-background-color);
|
11
|
+
& > span {
|
12
|
+
display: flex;
|
13
|
+
align-items: center;
|
14
|
+
justify-content: center;
|
15
|
+
}
|
16
|
+
&-separate {
|
17
|
+
flex: 0 1 auto;
|
18
|
+
.use-var(min-width, date-picker-range-separate-min-width);
|
19
|
+
}
|
20
|
+
}
|
21
|
+
&-range-item {
|
22
|
+
flex: 1 0 auto;
|
23
|
+
&-active {
|
24
|
+
.use-var(color, date-picker-range-font-color);
|
25
|
+
}
|
26
|
+
}
|
5
27
|
}
|
6
28
|
|
7
29
|
/***************************************************
|
@@ -26,5 +48,20 @@
|
|
26
48
|
.use-var(color, dark-sub-info-font-color);
|
27
49
|
}
|
28
50
|
}
|
51
|
+
.@{prefix}-date-picker {
|
52
|
+
&-show {
|
53
|
+
@{arco-dark-mode-selector} & {
|
54
|
+
.use-var(color, dark-date-picker-range-disabled-font-color);
|
55
|
+
.use-var(background-color, dark-date-picker-range-background-color);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
&-range-item {
|
59
|
+
&-active {
|
60
|
+
@{arco-dark-mode-selector} & {
|
61
|
+
.use-var(color, dark-date-picker-range-font-color);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
29
66
|
}
|
30
67
|
/********************* End *************************/
|
@@ -40,18 +40,18 @@ export interface DatePickerProps extends Omit<PickerProps, 'data' | 'cascade' |
|
|
40
40
|
* 点击选中时执行的回调
|
41
41
|
* @en Callback when clicking OK
|
42
42
|
*/
|
43
|
-
onOk?: (timestamp: number, obj: IDateObj) => void;
|
43
|
+
onOk?: (timestamp: number | [number, number], obj: IDateObj | [IDateObj, IDateObj]) => void;
|
44
44
|
/**
|
45
45
|
* 当前选中的时间,timestamp
|
46
46
|
* @en The currently selected time, timestamp
|
47
47
|
* @default Date.now()
|
48
48
|
*/
|
49
|
-
currentTs?: number;
|
49
|
+
currentTs?: number | [number, number];
|
50
50
|
/**
|
51
51
|
* 选中后的回调
|
52
52
|
* @en Callback when value is changed
|
53
53
|
*/
|
54
|
-
onChange?: (timestamp: number, obj: IDateObj) => void;
|
54
|
+
onChange?: (timestamp: number | [number, number], obj: IDateObj | [IDateObj, IDateObj]) => void;
|
55
55
|
/**
|
56
56
|
* 每列数据选择变化后的回调函数
|
57
57
|
* @en The callback function after each column data selection changes
|
@@ -75,20 +75,31 @@ export interface DatePickerProps extends Omit<PickerProps, 'data' | 'cascade' |
|
|
75
75
|
* @default 当前时间的前十年
|
76
76
|
* @default_en 10 years ago from the current time
|
77
77
|
*/
|
78
|
-
minTs?: number
|
78
|
+
minTs?: number | {
|
79
|
+
startTs: number;
|
80
|
+
endTs: number;
|
81
|
+
};
|
79
82
|
/**
|
80
83
|
* 最大可选日期,timestamp
|
81
84
|
* @en Maximum selectable date, timestamp
|
82
85
|
* @default 当前时间的后十年
|
83
86
|
* @default_en Next decade from current time
|
84
87
|
*/
|
85
|
-
maxTs?: number
|
88
|
+
maxTs?: number | {
|
89
|
+
startTs: number;
|
90
|
+
endTs: number;
|
91
|
+
};
|
86
92
|
/**
|
87
93
|
* 是否使用 UTC 时间
|
88
94
|
* @en Whether to use UTC
|
89
95
|
* @default false
|
90
96
|
*/
|
91
97
|
useUTC?: boolean;
|
98
|
+
/**
|
99
|
+
* 日期时间范围选择展示格式
|
100
|
+
* @en Time range picker display format
|
101
|
+
*/
|
102
|
+
rangeItemFormat?: string;
|
92
103
|
/**
|
93
104
|
* 各可选项展示的格式化方法,参数type为ItemTypes,参数value为当前行的值,返回展示的文字
|
94
105
|
* @en The formatting method of each optional item, the parameter type is ItemTypes, the parameter value is the value of the current row, and the displayed text is returned.
|
@@ -106,9 +117,14 @@ export interface DatePickerProps extends Omit<PickerProps, 'data' | 'cascade' |
|
|
106
117
|
* @en Selector list item intervention to insert custom options.
|
107
118
|
*/
|
108
119
|
columnsProcessor?: (columns: PickerData[][], currentDateObj: IDateObj) => PickerData[][];
|
120
|
+
/**
|
121
|
+
* 自定义分隔符
|
122
|
+
* @en Defined separator area
|
123
|
+
*/
|
124
|
+
renderSeparator?: () => React.ReactNode;
|
109
125
|
/**
|
110
126
|
* 将选择器的展现隐藏状态及选中值的展示与某个容器关联,传入后将同时渲染该容器和选择器组件,此时选择器组件的 visible 和 onHide 属性可不传,点击该容器会唤起选择器
|
111
127
|
* @en Associate the hidden state of the picker and the display of the selected value with a container. After passing it in, the container and the picker component will be rendered at the same time. At this time, the visible and onHide attributes of the picker component are optional values. Clicking the container will evoke the picker
|
112
128
|
*/
|
113
|
-
renderLinkedContainer?: (currentTs: number | undefined, itemTypes: ItemType[]) => ReactNode;
|
129
|
+
renderLinkedContainer?: (currentTs: number | [number, number] | undefined, itemTypes: ItemType[]) => ReactNode;
|
114
130
|
}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
export declare function DefaultPickerLinkedContainer({ value }: {
|
3
3
|
value: (string | number)[];
|
4
4
|
}): JSX.Element;
|
5
|
-
export declare function DefaultDatePickerLinkedContainer({ ts, types }: {
|
6
|
-
ts: number;
|
5
|
+
export declare function DefaultDatePickerLinkedContainer({ ts, types, }: {
|
6
|
+
ts: number | [number, number];
|
7
7
|
types: string[];
|
8
8
|
}): JSX.Element;
|
@@ -7,10 +7,15 @@ export function DefaultPickerLinkedContainer({ value }) {
|
|
7
7
|
const className = `${prefixCls}-form-picker-link-container`;
|
8
8
|
return (React.createElement("div", { className: className }, value && value.length ? (value.join('-')) : (React.createElement("span", { className: `${className}-placeholder` }, locale?.Form.pickerDefaultHint))));
|
9
9
|
}
|
10
|
-
export function DefaultDatePickerLinkedContainer({ ts, types }) {
|
10
|
+
export function DefaultDatePickerLinkedContainer({ ts, types, }) {
|
11
11
|
const { prefixCls, locale } = useContext(GlobalContext);
|
12
12
|
const className = `${prefixCls}-form-picker-link-container`;
|
13
|
-
const dateTimeStr = useMemo(() =>
|
13
|
+
const dateTimeStr = useMemo(() => {
|
14
|
+
if (typeof ts === 'number') {
|
15
|
+
return formatDateTimeStr(ts, types);
|
16
|
+
}
|
17
|
+
return `${formatDateTimeStr(ts[0], types)} ~ ${formatDateTimeStr(ts[1], types)}`;
|
18
|
+
}, [ts, types]);
|
14
19
|
function formatDateTimeStr(timestamp, itemTypes) {
|
15
20
|
const dateObj = convertTsToDateObj(timestamp);
|
16
21
|
const validDateObj = Object.keys(dateObj).reduce((acc, key) => ({
|
package/esnext/picker/index.js
CHANGED
@@ -7,7 +7,7 @@ import { useLatestRef, useListenResize } from '../_helpers';
|
|
7
7
|
export * from './type';
|
8
8
|
export { MultiPicker, PickerCell, Cascader } from '../picker-view';
|
9
9
|
const Picker = forwardRef((props, ref) => {
|
10
|
-
const { className, itemStyle, cascade = true, cols = 3, rows = 5, data, okText, dismissText, disabled = false, clickable = true, hideEmptyCols = false, title = '', visible: userSetVisible, value, needBottomOffset = false, onDismiss, onOk, onChange, maskClosable = false, onHide, onPickerChange, touchToStop, gestureOutOfControl = true, renderLinkedContainer, ...otherProps } = props;
|
10
|
+
const { className, itemStyle, cascade = true, cols = 3, rows = 5, data, okText, dismissText, disabled = false, clickable = true, hideEmptyCols = false, title = '', visible: userSetVisible, value, needBottomOffset = false, onDismiss, onOk, onChange, maskClosable = false, onHide, onPickerChange, touchToStop, gestureOutOfControl = true, renderLinkedContainer, renderExtraHeader, ...otherProps } = props;
|
11
11
|
const scrollValueRef = useLatestRef(value);
|
12
12
|
const domRef = useRef(null);
|
13
13
|
const pickerViewRef = useRef(null);
|
@@ -79,6 +79,7 @@ const Picker = forwardRef((props, ref) => {
|
|
79
79
|
React.createElement("div", { className: `${prefixCls}-picker-header-btn left`, onClick: handleDismiss }, dismissText || locale?.Picker.cancelText),
|
80
80
|
React.createElement("div", { className: `${prefixCls}-picker-header-title` }, title),
|
81
81
|
React.createElement("div", { className: `${prefixCls}-picker-header-btn right`, onClick: handleConfirm }, okText || locale?.Picker.okText)),
|
82
|
+
renderExtraHeader && renderExtraHeader(),
|
82
83
|
React.createElement(PickerView, { ref: pickerViewRef, data: data, cascade: cascade, cols: cols, rows: rows, disabled: disabled, value: value, onPickerChange: onPickerChange, itemStyle: itemStyle, clickable: clickable, hideEmptyCols: hideEmptyCols, touchToStop: touchToStop })))))));
|
83
84
|
});
|
84
85
|
/**
|
package/esnext/picker/type.d.ts
CHANGED
@@ -128,4 +128,9 @@ export interface PickerProps extends Omit<PopupProps, 'visible' | 'close' | 'chi
|
|
128
128
|
* @en Associate the hidden state of the picker and the display of the selected value with a container. After passing it in, the container and the picker component will be rendered at the same time. At this time, the visible and onHide attributes of the picker component are optional values. Clicking the container will evoke the picker
|
129
129
|
*/
|
130
130
|
renderLinkedContainer?: (value: ValueType[], data: PickerData[]) => ReactNode;
|
131
|
+
/**
|
132
|
+
* 自定义头部扩展区域
|
133
|
+
* @en Define the area of extra header
|
134
|
+
*/
|
135
|
+
renderExtraHeader?: () => ReactNode;
|
131
136
|
}
|
@@ -36,7 +36,7 @@ export function SearchBarAssociation(props) {
|
|
36
36
|
if (renderAssociationItem) {
|
37
37
|
node = renderAssociationItem(item, index, node);
|
38
38
|
}
|
39
|
-
return (React.createElement("div", { key: index, className: `${searchBarAssociationPrefixCls}-item`, onClick:
|
39
|
+
return (React.createElement("div", { key: index, className: `${searchBarAssociationPrefixCls}-item`, onClick: e => onAssociationItemClick?.(item, index, e) }, node));
|
40
40
|
};
|
41
41
|
const renderContent = () => {
|
42
42
|
const associationContent = associationItems.map(renderItem);
|
@@ -57,7 +57,7 @@ export interface SearchBarAssociationProps<Data = Record<string, any>> {
|
|
57
57
|
* 每行搜索结果的点击回调
|
58
58
|
* @en Click callback for each row of search results
|
59
59
|
*/
|
60
|
-
onAssociationItemClick?: (item: SearchAssociationItem<Data>, index: number) => void;
|
60
|
+
onAssociationItemClick?: (item: SearchAssociationItem<Data>, index: number, event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
|
61
61
|
/**
|
62
62
|
* 搜索联想框整体被点击的回调
|
63
63
|
* @en The callback for the overall click of the search association box
|
package/esnext/tabs/index.js
CHANGED
@@ -247,7 +247,7 @@ const Tabs = forwardRef((props, ref) => {
|
|
247
247
|
}
|
248
248
|
function updateLayout() {
|
249
249
|
const { width, height } = getOffset(domRef.current);
|
250
|
-
cellRef.current && cellRef.current.
|
250
|
+
cellRef.current && cellRef.current.updateLayout();
|
251
251
|
setWrapWidth(width || domRef.current?.offsetWidth || 0);
|
252
252
|
setWrapHeight(height || domRef.current?.offsetHeight || 0);
|
253
253
|
paneRef.current && paneRef.current.setCurrentHeight();
|
package/esnext/tabs/type.d.ts
CHANGED
@@ -561,8 +561,8 @@ export interface TabCellRef {
|
|
561
561
|
*/
|
562
562
|
setCaterpillarAnimate: (ratio?: number) => void;
|
563
563
|
/**
|
564
|
-
*
|
565
|
-
* @en Recalculate underline style
|
564
|
+
* 重新计算下划线样式(仅重算位置,如果 tab cell DOM 被人为改变,请调用 updateLayout)
|
565
|
+
* @en Recalculate underline style (only recalculate position, if the tab cell DOM is changed manually, please call updateLayout)
|
566
566
|
*/
|
567
567
|
resetUnderlineStyle: () => void;
|
568
568
|
/**
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arco-design/mobile-react",
|
3
|
-
"version": "2.
|
3
|
+
"version": "2.36.0",
|
4
4
|
"description": "",
|
5
5
|
"main": "cjs/index.js",
|
6
6
|
"module": "esm/index.js",
|
@@ -15,7 +15,7 @@
|
|
15
15
|
"author": "taoyiyue@bytedance.com",
|
16
16
|
"license": "ISC",
|
17
17
|
"dependencies": {
|
18
|
-
"@arco-design/mobile-utils": "2.
|
18
|
+
"@arco-design/mobile-utils": "2.21.0",
|
19
19
|
"@arco-design/transformable": "^1.0.0",
|
20
20
|
"@babel/runtime": "^7",
|
21
21
|
"lodash.throttle": "^4.1.1",
|
@@ -47,5 +47,5 @@
|
|
47
47
|
"publishConfig": {
|
48
48
|
"access": "public"
|
49
49
|
},
|
50
|
-
"gitHead": "
|
50
|
+
"gitHead": "e61b011d31905626ef7082a4a29faf2a03db93cf"
|
51
51
|
}
|
@@ -1093,4 +1093,14 @@
|
|
1093
1093
|
--uploader-disabled-delete-icon-color: var(--disabled-color);
|
1094
1094
|
--dark-uploader-item-text-error-color: var(--dark-danger-color);
|
1095
1095
|
--uploader-item-text-error-color: var(--danger-color);
|
1096
|
+
--date-picker-range-font-size: ~`pxtorem(16)`;
|
1097
|
+
--date-picker-range-background-color: #FBFCFC;
|
1098
|
+
--dark-date-picker-range-background-color: #1E1E1E;
|
1099
|
+
--dark-date-picker-range-font-color: var(--dark-font-color);
|
1100
|
+
--date-picker-range-font-color: var(--font-color);
|
1101
|
+
--dark-date-picker-range-disabled-font-color: var(--dark-disabled-color);
|
1102
|
+
--date-picker-range-disabled-font-color: var(--disabled-color);
|
1103
|
+
--date-picker-range-show-padding: 0 ~`pxtorem(16)`;
|
1104
|
+
--date-picker-range-show-min-height: ~`pxtorem(48)`;
|
1105
|
+
--date-picker-range-separate-min-width: ~`pxtorem(48)`;
|
1096
1106
|
}
|
@@ -1092,6 +1092,16 @@ export interface ArcodesignToken extends Record<string, string> {
|
|
1092
1092
|
'uploader-disabled-delete-icon-color': string;
|
1093
1093
|
'dark-uploader-item-text-error-color': string;
|
1094
1094
|
'uploader-item-text-error-color': string;
|
1095
|
+
'date-picker-range-font-size': string;
|
1096
|
+
'date-picker-range-background-color': string;
|
1097
|
+
'dark-date-picker-range-background-color': string;
|
1098
|
+
'dark-date-picker-range-font-color': string;
|
1099
|
+
'date-picker-range-font-color': string;
|
1100
|
+
'dark-date-picker-range-disabled-font-color': string;
|
1101
|
+
'date-picker-range-disabled-font-color': string;
|
1102
|
+
'date-picker-range-show-padding': string;
|
1103
|
+
'date-picker-range-show-min-height': string;
|
1104
|
+
'date-picker-range-separate-min-width': string;
|
1095
1105
|
}
|
1096
1106
|
declare const tokens: ArcodesignToken;
|
1097
1107
|
export default tokens;
|