@particle-network/ui-native 0.1.4-beta.1 → 0.1.4-beta.3
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/dist/components/UXCheckbox/checkbox.js +31 -17
- package/dist/components/UXCheckbox/icons.d.ts +14 -0
- package/dist/components/UXCheckbox/icons.js +41 -0
- package/dist/components/UXCheckbox/types.d.ts +2 -2
- package/dist/components/date-picker/date-picker.js +16 -12
- package/dist/components/date-picker/date-range-picker.js +20 -15
- package/dist/components/date-picker/types.d.ts +8 -0
- package/dist/components/date-picker/useFormat.d.ts +10 -0
- package/dist/components/date-picker/useFormat.js +26 -0
- package/dist/components/date-picker/utils.d.ts +33 -3
- package/dist/components/date-picker/utils.js +77 -2
- package/dist/icons/index.js +0 -31
- package/dist/icons/types.d.ts +1 -1
- package/dist/locales/en.d.ts +6 -0
- package/dist/locales/en.js +7 -1
- package/dist/locales/index.d.ts +18 -0
- package/dist/locales/zh.js +7 -1
- package/package.json +3 -3
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useMemo, useState } from "react";
|
|
3
3
|
import { useMs } from "../../hooks/index.js";
|
|
4
|
-
import { Icon } from "../../icons/index.js";
|
|
5
4
|
import { disabledOpacity } from "../../theme/index.js";
|
|
6
5
|
import { Flex } from "../layout/Flex/index.js";
|
|
7
6
|
import { Text } from "../Text/index.js";
|
|
8
7
|
import { UXPressable } from "../UXPressable/index.js";
|
|
9
8
|
import { useCheckboxGroup } from "./context.js";
|
|
10
|
-
|
|
9
|
+
import { CheckboxOffIcon, CheckboxOnIcon } from "./icons.js";
|
|
10
|
+
const UXCheckbox = ({ size, color, defaultSelected = false, isSelected, children, value, onValueChange, isDisabled, labelPlacement = 'right', ...props })=>{
|
|
11
11
|
const { ms } = useMs();
|
|
12
12
|
const [internalSelected, setInternalSelected] = useState(defaultSelected ?? isSelected);
|
|
13
13
|
const groupContext = useCheckboxGroup();
|
|
@@ -21,6 +21,19 @@ const UXCheckbox = ({ size, color, defaultSelected = false, isSelected, children
|
|
|
21
21
|
defaultSelected
|
|
22
22
|
]);
|
|
23
23
|
const checkboxColor = color || groupContext?.color || 'primary';
|
|
24
|
+
const displayLabelPlacement = labelPlacement || groupContext?.labelPlacement || 'right';
|
|
25
|
+
const bgColor = useMemo(()=>{
|
|
26
|
+
if ('secondary' === checkboxColor) return 'tertiary';
|
|
27
|
+
return checkboxColor;
|
|
28
|
+
}, [
|
|
29
|
+
checkboxColor
|
|
30
|
+
]);
|
|
31
|
+
const foregroundColor = useMemo(()=>{
|
|
32
|
+
if ('secondary' === checkboxColor) return 'foreground';
|
|
33
|
+
return 'white';
|
|
34
|
+
}, [
|
|
35
|
+
checkboxColor
|
|
36
|
+
]);
|
|
24
37
|
const checkboxIsDisabled = isDisabled || groupContext?.isDisabled;
|
|
25
38
|
const checkboxSize = size || groupContext?.size || 'md';
|
|
26
39
|
const handleSelectChange = ()=>{
|
|
@@ -32,23 +45,24 @@ const UXCheckbox = ({ size, color, defaultSelected = false, isSelected, children
|
|
|
32
45
|
};
|
|
33
46
|
const iconSize = useMemo(()=>{
|
|
34
47
|
if ('sm' === checkboxSize) return ms(14);
|
|
35
|
-
if ('lg' === checkboxSize) return ms(
|
|
48
|
+
if ('lg' === checkboxSize) return ms(18);
|
|
36
49
|
return ms(16);
|
|
37
50
|
}, [
|
|
38
|
-
checkboxSize
|
|
51
|
+
checkboxSize,
|
|
52
|
+
ms
|
|
39
53
|
]);
|
|
40
54
|
const labelVariant = useMemo(()=>{
|
|
41
|
-
if ('sm' === checkboxSize) return '
|
|
42
|
-
if ('lg' === checkboxSize) return '
|
|
43
|
-
return '
|
|
55
|
+
if ('sm' === checkboxSize) return 'body3';
|
|
56
|
+
if ('lg' === checkboxSize) return 'body1';
|
|
57
|
+
return 'body2';
|
|
44
58
|
}, [
|
|
45
59
|
checkboxSize
|
|
46
60
|
]);
|
|
47
|
-
const
|
|
48
|
-
if ('
|
|
49
|
-
return
|
|
61
|
+
const flexDirection = useMemo(()=>{
|
|
62
|
+
if ('left' === displayLabelPlacement) return 'row-reverse';
|
|
63
|
+
return 'row';
|
|
50
64
|
}, [
|
|
51
|
-
|
|
65
|
+
displayLabelPlacement
|
|
52
66
|
]);
|
|
53
67
|
return /*#__PURE__*/ jsx(UXPressable, {
|
|
54
68
|
disabled: checkboxIsDisabled,
|
|
@@ -57,16 +71,16 @@ const UXCheckbox = ({ size, color, defaultSelected = false, isSelected, children
|
|
|
57
71
|
},
|
|
58
72
|
onPress: handleSelectChange,
|
|
59
73
|
children: /*#__PURE__*/ jsxs(Flex, {
|
|
60
|
-
|
|
74
|
+
direction: flexDirection,
|
|
75
|
+
gap: 8,
|
|
61
76
|
items: "center",
|
|
62
77
|
...props,
|
|
63
78
|
children: [
|
|
64
|
-
internalSelected ? /*#__PURE__*/ jsx(
|
|
65
|
-
|
|
66
|
-
|
|
79
|
+
internalSelected ? /*#__PURE__*/ jsx(CheckboxOnIcon, {
|
|
80
|
+
color1: bgColor,
|
|
81
|
+
color2: foregroundColor,
|
|
67
82
|
size: iconSize
|
|
68
|
-
}) : /*#__PURE__*/ jsx(
|
|
69
|
-
name: "checkboxOff",
|
|
83
|
+
}) : /*#__PURE__*/ jsx(CheckboxOffIcon, {
|
|
70
84
|
color: "secondary",
|
|
71
85
|
size: iconSize
|
|
72
86
|
}),
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { UXColor } from '@particle-network/ui-shared';
|
|
3
|
+
interface CheckboxOnIconProps {
|
|
4
|
+
size?: number;
|
|
5
|
+
color1?: UXColor;
|
|
6
|
+
color2?: UXColor;
|
|
7
|
+
}
|
|
8
|
+
interface CheckboxOffIconProps {
|
|
9
|
+
size?: number;
|
|
10
|
+
color?: UXColor;
|
|
11
|
+
}
|
|
12
|
+
export declare const CheckboxOnIcon: ({ size, color1, color2 }: CheckboxOnIconProps) => React.JSX.Element;
|
|
13
|
+
export declare const CheckboxOffIcon: ({ size, color }: CheckboxOffIconProps) => React.JSX.Element;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import "react";
|
|
3
|
+
import react_native_svg, { Path } from "react-native-svg";
|
|
4
|
+
import { useColors } from "../../hooks/index.js";
|
|
5
|
+
const CheckboxOnIcon = ({ size = 16, color1 = 'default', color2 = 'white' })=>{
|
|
6
|
+
const { getColor } = useColors();
|
|
7
|
+
const color1Value = getColor(color1);
|
|
8
|
+
const color2Value = getColor(color2);
|
|
9
|
+
return /*#__PURE__*/ jsxs(react_native_svg, {
|
|
10
|
+
fill: "none",
|
|
11
|
+
viewBox: "0 0 16 16",
|
|
12
|
+
width: size,
|
|
13
|
+
height: size,
|
|
14
|
+
children: [
|
|
15
|
+
/*#__PURE__*/ jsx(Path, {
|
|
16
|
+
d: "M2.46154 16H13.5385C14.8979 16 16 14.8979 16 13.5385V2.46154C16 1.10207 14.8979 0 13.5385 0H2.46154C1.10207 0 0 1.10207 0 2.46154V13.5385C0 14.8979 1.10207 16 2.46154 16Z",
|
|
17
|
+
fill: color1Value
|
|
18
|
+
}),
|
|
19
|
+
/*#__PURE__*/ jsx(Path, {
|
|
20
|
+
d: "M6.75547 9.24601L4.84436 7.3349C4.68139 7.17193 4.47399 7.09045 4.22214 7.09045C3.97028 7.09045 3.76288 7.17193 3.59991 7.3349C3.43695 7.49786 3.35547 7.70527 3.35547 7.95712C3.35547 8.20897 3.43695 8.41638 3.59991 8.57934L6.13325 11.1127C6.31102 11.2905 6.51843 11.3793 6.75547 11.3793C6.99251 11.3793 7.19991 11.2905 7.37769 11.1127L12.3999 6.09045C12.5629 5.92749 12.6444 5.72008 12.6444 5.46823C12.6444 5.21638 12.5629 5.00897 12.3999 4.84601C12.237 4.68304 12.0295 4.60156 11.7777 4.60156C11.5258 4.60156 11.3184 4.68304 11.1555 4.84601L6.75547 9.24601Z",
|
|
21
|
+
fill: color2Value
|
|
22
|
+
})
|
|
23
|
+
]
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
const CheckboxOffIcon = ({ size = 16, color = 'default' })=>{
|
|
27
|
+
const { getColor } = useColors();
|
|
28
|
+
const colorValue = getColor(color);
|
|
29
|
+
return /*#__PURE__*/ jsx(react_native_svg, {
|
|
30
|
+
fill: "none",
|
|
31
|
+
viewBox: "0 0 16 16",
|
|
32
|
+
width: size,
|
|
33
|
+
height: size,
|
|
34
|
+
children: /*#__PURE__*/ jsx(Path, {
|
|
35
|
+
d: "M2.46191 0.615234H13.5381C14.5577 0.615234 15.3848 1.44231 15.3848 2.46191V13.5381C15.3848 14.5577 14.5577 15.3848 13.5381 15.3848H2.46191C1.44231 15.3848 0.615234 14.5577 0.615234 13.5381V2.46191C0.615234 1.44231 1.44231 0.615234 2.46191 0.615234Z",
|
|
36
|
+
stroke: colorValue,
|
|
37
|
+
strokeWidth: 1.23077
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
export { CheckboxOffIcon, CheckboxOnIcon };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { UXForegroundColor } from '@particle-network/ui-shared';
|
|
2
1
|
export interface UXCheckboxCommonProps {
|
|
3
|
-
color?:
|
|
2
|
+
color?: 'secondary' | 'primary' | 'success' | 'danger' | 'alert' | 'warning' | 'gold' | 'bullish' | 'bearish';
|
|
4
3
|
size?: 'sm' | 'md' | 'lg';
|
|
5
4
|
isDisabled?: boolean;
|
|
5
|
+
labelPlacement?: 'left' | 'right';
|
|
6
6
|
}
|
|
@@ -11,27 +11,31 @@ import { UXPressable } from "../UXPressable/index.js";
|
|
|
11
11
|
import date_button from "./date-button.js";
|
|
12
12
|
import { DateWheelPicker } from "./date-wheel-picker.js";
|
|
13
13
|
import { TimeWheelPicker } from "./time-wheel-picker.js";
|
|
14
|
-
import
|
|
15
|
-
|
|
14
|
+
import useFormat from "./useFormat.js";
|
|
15
|
+
import { hasTimeOnly } from "./utils.js";
|
|
16
|
+
const UXDatePicker = ({ title, value, defaultValue, onConfirm = ()=>null, format = 'YYYY/MM/DD', minDate, maxDate, placeholder, isDisabled = false, isReadOnly = false, ...uxPressableProps })=>{
|
|
16
17
|
const [isOpen, setIsOpen] = useState(false);
|
|
17
18
|
const [pickerType, setPickerType] = useState('date');
|
|
18
19
|
const [internalValue, setInternalValue] = useState(value || defaultValue || new Date());
|
|
19
20
|
const i18n = useI18n();
|
|
20
|
-
const [dateFormat, timeFormat] = format.split(' ');
|
|
21
|
-
const showTimePicker = hasTimeInFormat(format);
|
|
22
21
|
const displayPlaceholder = placeholder ?? format;
|
|
22
|
+
const { dateFormat, timeFormat, displayTitle } = useFormat({
|
|
23
|
+
format,
|
|
24
|
+
title
|
|
25
|
+
});
|
|
23
26
|
useEffect(()=>{
|
|
24
27
|
if (void 0 !== value) setInternalValue(value);
|
|
25
28
|
}, [
|
|
26
29
|
value
|
|
27
30
|
]);
|
|
28
|
-
const handleOpenModal = useCallback((
|
|
31
|
+
const handleOpenModal = useCallback(()=>{
|
|
29
32
|
if (isDisabled || isReadOnly) return;
|
|
30
|
-
setPickerType(
|
|
33
|
+
setPickerType(hasTimeOnly(format) ? 'time' : 'date');
|
|
31
34
|
setIsOpen(true);
|
|
32
35
|
}, [
|
|
33
36
|
isDisabled,
|
|
34
|
-
isReadOnly
|
|
37
|
+
isReadOnly,
|
|
38
|
+
format
|
|
35
39
|
]);
|
|
36
40
|
const handleConfirm = useCallback(()=>{
|
|
37
41
|
onConfirm(internalValue);
|
|
@@ -46,7 +50,7 @@ const UXDatePicker = ({ value, defaultValue, onConfirm = ()=>null, format = 'YYY
|
|
|
46
50
|
return /*#__PURE__*/ jsxs(Fragment, {
|
|
47
51
|
children: [
|
|
48
52
|
/*#__PURE__*/ jsx(UXPressable, {
|
|
49
|
-
onPress: ()=>handleOpenModal(
|
|
53
|
+
onPress: ()=>handleOpenModal(),
|
|
50
54
|
...uxPressableProps,
|
|
51
55
|
children: /*#__PURE__*/ jsx(UXInput, {
|
|
52
56
|
containerStyle: {
|
|
@@ -57,7 +61,7 @@ const UXDatePicker = ({ value, defaultValue, onConfirm = ()=>null, format = 'YYY
|
|
|
57
61
|
isReadOnly: isReadOnly,
|
|
58
62
|
placeholder: displayPlaceholder,
|
|
59
63
|
pointerEvents: "none",
|
|
60
|
-
value: value ? dayjs(value).format(format) :
|
|
64
|
+
value: value ? dayjs(value).format(format) : void 0
|
|
61
65
|
})
|
|
62
66
|
}),
|
|
63
67
|
/*#__PURE__*/ jsx(UXModal, {
|
|
@@ -74,7 +78,7 @@ const UXDatePicker = ({ value, defaultValue, onConfirm = ()=>null, format = 'YYY
|
|
|
74
78
|
scrollViewProps: {
|
|
75
79
|
scrollEnabled: false
|
|
76
80
|
},
|
|
77
|
-
title:
|
|
81
|
+
title: displayTitle,
|
|
78
82
|
onClose: handleClose,
|
|
79
83
|
children: /*#__PURE__*/ jsxs(VStack, {
|
|
80
84
|
fullWidth: true,
|
|
@@ -85,12 +89,12 @@ const UXDatePicker = ({ value, defaultValue, onConfirm = ()=>null, format = 'YYY
|
|
|
85
89
|
items: "center",
|
|
86
90
|
gap: 8,
|
|
87
91
|
children: [
|
|
88
|
-
/*#__PURE__*/ jsx(date_button, {
|
|
92
|
+
dateFormat && /*#__PURE__*/ jsx(date_button, {
|
|
89
93
|
isSelected: 'date' === pickerType,
|
|
90
94
|
text: dayjs(internalValue).format(dateFormat),
|
|
91
95
|
onPress: ()=>setPickerType('date')
|
|
92
96
|
}),
|
|
93
|
-
|
|
97
|
+
timeFormat && /*#__PURE__*/ jsx(date_button, {
|
|
94
98
|
isSelected: 'time' === pickerType,
|
|
95
99
|
text: dayjs(internalValue).format(timeFormat),
|
|
96
100
|
onPress: ()=>setPickerType('time')
|
|
@@ -13,8 +13,9 @@ import { UXPressable } from "../UXPressable/index.js";
|
|
|
13
13
|
import date_button from "./date-button.js";
|
|
14
14
|
import { DateWheelPicker } from "./date-wheel-picker.js";
|
|
15
15
|
import { TimeWheelPicker } from "./time-wheel-picker.js";
|
|
16
|
-
import
|
|
17
|
-
|
|
16
|
+
import useFormat from "./useFormat.js";
|
|
17
|
+
import { hasTimeOnly } from "./utils.js";
|
|
18
|
+
const UXDateRangePicker = ({ title, value, defaultValue, onConfirm = ()=>null, format = 'YYYY/MM/DD', minDate, maxDate, startPlaceholder, endPlaceholder, isDisabled = false, isReadOnly = false, ...hStackProps })=>{
|
|
18
19
|
const [isOpen, setIsOpen] = useState(false);
|
|
19
20
|
const [currentEditType, setCurrentEditType] = useState('start');
|
|
20
21
|
const [pickerType, setPickerType] = useState('date');
|
|
@@ -22,10 +23,13 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
22
23
|
const [internalEnd, setInternalEnd] = useState(value?.end || defaultValue?.end || new Date());
|
|
23
24
|
const [error, setError] = useState('');
|
|
24
25
|
const i18n = useI18n();
|
|
25
|
-
const [dateFormat, timeFormat] = format.split(' ');
|
|
26
|
-
const showTimePicker = hasTimeInFormat(format);
|
|
27
26
|
const displayStartPlaceholder = startPlaceholder ?? format;
|
|
28
27
|
const displayEndPlaceholder = endPlaceholder ?? format;
|
|
28
|
+
const { dateFormat, timeFormat, displayTitle } = useFormat({
|
|
29
|
+
format,
|
|
30
|
+
title,
|
|
31
|
+
rangeMode: true
|
|
32
|
+
});
|
|
29
33
|
useEffect(()=>{
|
|
30
34
|
if (value?.start !== void 0) setInternalStart(value?.start);
|
|
31
35
|
if (value?.end !== void 0) setInternalEnd(value?.end);
|
|
@@ -35,12 +39,13 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
35
39
|
const handleOpenModal = useCallback((type, picker)=>{
|
|
36
40
|
if (isDisabled || isReadOnly) return;
|
|
37
41
|
setCurrentEditType(type);
|
|
38
|
-
setPickerType(picker);
|
|
42
|
+
setPickerType(picker || (hasTimeOnly(format) ? 'time' : 'date'));
|
|
39
43
|
setError('');
|
|
40
44
|
setIsOpen(true);
|
|
41
45
|
}, [
|
|
42
46
|
isDisabled,
|
|
43
|
-
isReadOnly
|
|
47
|
+
isReadOnly,
|
|
48
|
+
format
|
|
44
49
|
]);
|
|
45
50
|
const handleConfirm = useCallback(()=>{
|
|
46
51
|
if (!internalStart || !internalEnd) return void setError(i18n.datePicker.errorBothRequired);
|
|
@@ -68,7 +73,7 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
68
73
|
children: [
|
|
69
74
|
/*#__PURE__*/ jsx(UXPressable, {
|
|
70
75
|
fill: true,
|
|
71
|
-
onPress: ()=>handleOpenModal('start'
|
|
76
|
+
onPress: ()=>handleOpenModal('start'),
|
|
72
77
|
children: /*#__PURE__*/ jsx(UXInput, {
|
|
73
78
|
containerStyle: {
|
|
74
79
|
flex: 1
|
|
@@ -78,7 +83,7 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
78
83
|
isReadOnly: isReadOnly,
|
|
79
84
|
placeholder: displayStartPlaceholder,
|
|
80
85
|
pointerEvents: "none",
|
|
81
|
-
value: value?.start ? dayjs(value?.start).format(format) :
|
|
86
|
+
value: value?.start ? dayjs(value?.start).format(format) : void 0
|
|
82
87
|
})
|
|
83
88
|
}),
|
|
84
89
|
/*#__PURE__*/ jsx(Icon, {
|
|
@@ -88,7 +93,7 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
88
93
|
}),
|
|
89
94
|
/*#__PURE__*/ jsx(UXPressable, {
|
|
90
95
|
fill: true,
|
|
91
|
-
onPress: ()=>handleOpenModal('end'
|
|
96
|
+
onPress: ()=>handleOpenModal('end'),
|
|
92
97
|
children: /*#__PURE__*/ jsx(UXInput, {
|
|
93
98
|
containerStyle: {
|
|
94
99
|
flex: 1
|
|
@@ -98,7 +103,7 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
98
103
|
isReadOnly: isReadOnly,
|
|
99
104
|
placeholder: displayEndPlaceholder,
|
|
100
105
|
pointerEvents: "none",
|
|
101
|
-
value: value?.end ? dayjs(value?.end).format(format) :
|
|
106
|
+
value: value?.end ? dayjs(value?.end).format(format) : void 0
|
|
102
107
|
})
|
|
103
108
|
})
|
|
104
109
|
]
|
|
@@ -127,7 +132,7 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
127
132
|
scrollViewProps: {
|
|
128
133
|
scrollEnabled: false
|
|
129
134
|
},
|
|
130
|
-
title:
|
|
135
|
+
title: displayTitle,
|
|
131
136
|
onClose: handleClose,
|
|
132
137
|
children: /*#__PURE__*/ jsxs(VStack, {
|
|
133
138
|
fullWidth: true,
|
|
@@ -138,12 +143,12 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
138
143
|
items: "center",
|
|
139
144
|
gap: 8,
|
|
140
145
|
children: [
|
|
141
|
-
/*#__PURE__*/ jsx(date_button, {
|
|
146
|
+
dateFormat && /*#__PURE__*/ jsx(date_button, {
|
|
142
147
|
isSelected: 'start' === currentEditType && 'date' === pickerType,
|
|
143
148
|
text: dayjs(internalStart).format(dateFormat),
|
|
144
149
|
onPress: ()=>handleOpenModal('start', 'date')
|
|
145
150
|
}),
|
|
146
|
-
|
|
151
|
+
timeFormat && /*#__PURE__*/ jsx(date_button, {
|
|
147
152
|
isSelected: 'start' === currentEditType && 'time' === pickerType,
|
|
148
153
|
text: dayjs(internalStart).format(timeFormat),
|
|
149
154
|
onPress: ()=>handleOpenModal('start', 'time')
|
|
@@ -153,12 +158,12 @@ const UXDateRangePicker = ({ value, defaultValue, onConfirm = ()=>null, format =
|
|
|
153
158
|
color: "tertiary",
|
|
154
159
|
size: 16
|
|
155
160
|
}),
|
|
156
|
-
/*#__PURE__*/ jsx(date_button, {
|
|
161
|
+
dateFormat && /*#__PURE__*/ jsx(date_button, {
|
|
157
162
|
isSelected: 'end' === currentEditType && 'date' === pickerType,
|
|
158
163
|
text: dayjs(internalEnd).format(dateFormat),
|
|
159
164
|
onPress: ()=>handleOpenModal('end', 'date')
|
|
160
165
|
}),
|
|
161
|
-
|
|
166
|
+
timeFormat && /*#__PURE__*/ jsx(date_button, {
|
|
162
167
|
isSelected: 'end' === currentEditType && 'time' === pickerType,
|
|
163
168
|
text: dayjs(internalEnd).format(timeFormat),
|
|
164
169
|
onPress: ()=>handleOpenModal('end', 'time')
|
|
@@ -37,6 +37,10 @@ export interface UXDatePickerProps extends Omit<UXPressableProps, 'children'> {
|
|
|
37
37
|
* 是否只读
|
|
38
38
|
*/
|
|
39
39
|
isReadOnly?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* 弹窗标题
|
|
42
|
+
*/
|
|
43
|
+
title?: string;
|
|
40
44
|
}
|
|
41
45
|
export interface UXDateRangePickerProps extends Omit<HStackProps, 'children'> {
|
|
42
46
|
/**
|
|
@@ -79,6 +83,10 @@ export interface UXDateRangePickerProps extends Omit<HStackProps, 'children'> {
|
|
|
79
83
|
* 是否只读
|
|
80
84
|
*/
|
|
81
85
|
isReadOnly?: boolean;
|
|
86
|
+
/**
|
|
87
|
+
* 弹窗标题
|
|
88
|
+
*/
|
|
89
|
+
title?: string;
|
|
82
90
|
}
|
|
83
91
|
export interface DateRangeValue {
|
|
84
92
|
start?: Date;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useMemo } from "react";
|
|
2
|
+
import { useI18n } from "../../hooks/index.js";
|
|
3
|
+
import { getDateFormat, getTimeFormat, hasDateOnly, hasTimeOnly } from "./utils.js";
|
|
4
|
+
const useFormat = ({ format, title, rangeMode = false })=>{
|
|
5
|
+
const i18n = useI18n();
|
|
6
|
+
const dateFormat = getDateFormat(format);
|
|
7
|
+
const timeFormat = getTimeFormat(format);
|
|
8
|
+
const displayTitle = useMemo(()=>{
|
|
9
|
+
if (title) return title;
|
|
10
|
+
if (hasDateOnly(format)) return rangeMode ? i18n.datePicker.selectDateRange : i18n.datePicker.selectDate;
|
|
11
|
+
if (hasTimeOnly(format)) return rangeMode ? i18n.datePicker.selectTimeRange : i18n.datePicker.selectTime;
|
|
12
|
+
return rangeMode ? i18n.datePicker.selectDateAndTimeRange : i18n.datePicker.selectDateAndTime;
|
|
13
|
+
}, [
|
|
14
|
+
format,
|
|
15
|
+
title,
|
|
16
|
+
i18n,
|
|
17
|
+
rangeMode
|
|
18
|
+
]);
|
|
19
|
+
return {
|
|
20
|
+
dateFormat,
|
|
21
|
+
timeFormat,
|
|
22
|
+
displayTitle
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
const date_picker_useFormat = useFormat;
|
|
26
|
+
export { date_picker_useFormat as default };
|
|
@@ -1,6 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 判断格式字符串是否包含日期部分
|
|
3
|
+
* @param {string} format - 时间格式字符串
|
|
4
|
+
* @returns {boolean} - 是否包含日期
|
|
5
|
+
*/
|
|
6
|
+
export declare function hasDateInFormat(format: string): boolean;
|
|
1
7
|
/**
|
|
2
8
|
* 判断格式字符串是否包含时间部分
|
|
3
|
-
* @param format
|
|
4
|
-
* @returns 是否包含时间
|
|
9
|
+
* @param {string} format - 时间格式字符串
|
|
10
|
+
* @returns {boolean} - 是否包含时间
|
|
11
|
+
*/
|
|
12
|
+
export declare function hasTimeInFormat(format: string): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* 判断格式字符串是否只包含日期(不含时间)
|
|
15
|
+
* @param {string} format - 时间格式字符串
|
|
16
|
+
* @returns {boolean} - 是否只有日期
|
|
17
|
+
*/
|
|
18
|
+
export declare function hasDateOnly(format: string): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* 判断格式字符串是否只包含时间(不含日期)
|
|
21
|
+
* @param {string} format - 时间格式字符串
|
|
22
|
+
* @returns {boolean} - 是否只有时间
|
|
23
|
+
*/
|
|
24
|
+
export declare function hasTimeOnly(format: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* 提取格式字符串中的日期部分
|
|
27
|
+
* @param {string} format - 时间格式字符串
|
|
28
|
+
* @returns {string|null} - 日期格式字符串,如果不包含日期则返回 null
|
|
29
|
+
*/
|
|
30
|
+
export declare function getDateFormat(format: string): string | null;
|
|
31
|
+
/**
|
|
32
|
+
* 提取格式字符串中的时间部分
|
|
33
|
+
* @param {string} format - 时间格式字符串
|
|
34
|
+
* @returns {string|null} - 时间格式字符串,如果不包含时间则返回 null
|
|
5
35
|
*/
|
|
6
|
-
export declare
|
|
36
|
+
export declare function getTimeFormat(format: string): string | null;
|
|
@@ -1,2 +1,77 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
function hasDateInFormat(format) {
|
|
2
|
+
const datePatterns = [
|
|
3
|
+
/Y{2,4}/,
|
|
4
|
+
/M{1,2}/,
|
|
5
|
+
/D{1,2}/
|
|
6
|
+
];
|
|
7
|
+
return datePatterns.some((pattern)=>pattern.test(format));
|
|
8
|
+
}
|
|
9
|
+
function hasTimeInFormat(format) {
|
|
10
|
+
const timePatterns = [
|
|
11
|
+
/H{1,2}/,
|
|
12
|
+
/h{1,2}/,
|
|
13
|
+
/m{1,2}/,
|
|
14
|
+
/s{1,2}/,
|
|
15
|
+
/A/i
|
|
16
|
+
];
|
|
17
|
+
return timePatterns.some((pattern)=>pattern.test(format));
|
|
18
|
+
}
|
|
19
|
+
function hasDateOnly(format) {
|
|
20
|
+
return hasDateInFormat(format) && !hasTimeInFormat(format);
|
|
21
|
+
}
|
|
22
|
+
function hasTimeOnly(format) {
|
|
23
|
+
return hasTimeInFormat(format) && !hasDateInFormat(format);
|
|
24
|
+
}
|
|
25
|
+
function getDateFormat(format) {
|
|
26
|
+
if (!hasDateInFormat(format)) return null;
|
|
27
|
+
if (hasDateOnly(format)) return format.trim();
|
|
28
|
+
const separators = [
|
|
29
|
+
' ',
|
|
30
|
+
'T',
|
|
31
|
+
',',
|
|
32
|
+
'\t'
|
|
33
|
+
];
|
|
34
|
+
for (const sep of separators)if (format.includes(sep)) {
|
|
35
|
+
const parts = format.split(sep);
|
|
36
|
+
for (const part of parts)if (hasDateInFormat(part) && !hasTimeInFormat(part)) return part.trim();
|
|
37
|
+
}
|
|
38
|
+
const datePatterns = [
|
|
39
|
+
/Y{2,4}[/-]M{1,2}[/-]D{1,2}/,
|
|
40
|
+
/Y{2,4}M{1,2}D{1,2}/,
|
|
41
|
+
/D{1,2}[/-]M{1,2}[/-]Y{2,4}/,
|
|
42
|
+
/M{1,2}[/-]D{1,2}[/-]Y{2,4}/
|
|
43
|
+
];
|
|
44
|
+
for (const pattern of datePatterns){
|
|
45
|
+
const match = format.match(pattern);
|
|
46
|
+
if (match) return match[0];
|
|
47
|
+
}
|
|
48
|
+
return format.trim();
|
|
49
|
+
}
|
|
50
|
+
function getTimeFormat(format) {
|
|
51
|
+
if (!hasTimeInFormat(format)) return null;
|
|
52
|
+
if (hasTimeOnly(format)) return format.trim();
|
|
53
|
+
const separators = [
|
|
54
|
+
' ',
|
|
55
|
+
'T',
|
|
56
|
+
',',
|
|
57
|
+
'\t'
|
|
58
|
+
];
|
|
59
|
+
for (const sep of separators)if (format.includes(sep)) {
|
|
60
|
+
const parts = format.split(sep);
|
|
61
|
+
const timeParts = [];
|
|
62
|
+
for (const part of parts)if (hasTimeInFormat(part) || /AM|PM|am|pm/i.test(part)) timeParts.push(part.trim());
|
|
63
|
+
if (timeParts.length > 0) return timeParts.join(' ');
|
|
64
|
+
}
|
|
65
|
+
const timePatterns = [
|
|
66
|
+
/[Hh]{1,2}:[m]{1,2}:[s]{1,2}\s*(?:AM|PM|am|pm)?/,
|
|
67
|
+
/[Hh]{1,2}:[m]{1,2}\s*(?:AM|PM|am|pm)?/,
|
|
68
|
+
/[Hh]{1,2}[m]{1,2}[s]{1,2}\s*(?:AM|PM|am|pm)?/,
|
|
69
|
+
/[Hh]{1,2}[m]{1,2}\s*(?:AM|PM|am|pm)?/
|
|
70
|
+
];
|
|
71
|
+
for (const pattern of timePatterns){
|
|
72
|
+
const match = format.match(pattern);
|
|
73
|
+
if (match) return match[0].trim();
|
|
74
|
+
}
|
|
75
|
+
return format.trim();
|
|
76
|
+
}
|
|
77
|
+
export { getDateFormat, getTimeFormat, hasDateInFormat, hasDateOnly, hasTimeInFormat, hasTimeOnly };
|
package/dist/icons/index.js
CHANGED
|
@@ -6,37 +6,6 @@ const Icon = ({ name, size = 16, color = 'default', ...props })=>{
|
|
|
6
6
|
const { getColor } = useColors();
|
|
7
7
|
const colorValue = getColor(color);
|
|
8
8
|
switch(name){
|
|
9
|
-
case 'checkboxOff':
|
|
10
|
-
return /*#__PURE__*/ jsx(react_native_svg, {
|
|
11
|
-
fill: "none",
|
|
12
|
-
height: size,
|
|
13
|
-
viewBox: "0 0 16 16",
|
|
14
|
-
width: size,
|
|
15
|
-
...props,
|
|
16
|
-
children: /*#__PURE__*/ jsx(Path, {
|
|
17
|
-
d: "M2.46191 0.615234H13.5381C14.5577 0.615234 15.3848 1.44231 15.3848 2.46191V13.5381C15.3848 14.5577 14.5577 15.3848 13.5381 15.3848H2.46191C1.44231 15.3848 0.615234 14.5577 0.615234 13.5381V2.46191C0.615234 1.44231 1.44231 0.615234 2.46191 0.615234Z",
|
|
18
|
-
stroke: colorValue,
|
|
19
|
-
strokeWidth: 1.23077
|
|
20
|
-
})
|
|
21
|
-
});
|
|
22
|
-
case 'checkboxOn':
|
|
23
|
-
return /*#__PURE__*/ jsxs(react_native_svg, {
|
|
24
|
-
fill: "none",
|
|
25
|
-
height: size,
|
|
26
|
-
viewBox: "0 0 16 16",
|
|
27
|
-
width: size,
|
|
28
|
-
...props,
|
|
29
|
-
children: [
|
|
30
|
-
/*#__PURE__*/ jsx(Path, {
|
|
31
|
-
d: "M2.46154 16H13.5385C14.8979 16 16 14.8979 16 13.5385V2.46154C16 1.10207 14.8979 0 13.5385 0H2.46154C1.10207 0 0 1.10207 0 2.46154V13.5385C0 14.8979 1.10207 16 2.46154 16Z",
|
|
32
|
-
fill: colorValue
|
|
33
|
-
}),
|
|
34
|
-
/*#__PURE__*/ jsx(Path, {
|
|
35
|
-
d: "M6.75547 9.24601L4.84436 7.3349C4.68139 7.17193 4.47399 7.09045 4.22214 7.09045C3.97028 7.09045 3.76288 7.17193 3.59991 7.3349C3.43695 7.49786 3.35547 7.70527 3.35547 7.95712C3.35547 8.20897 3.43695 8.41638 3.59991 8.57934L6.13325 11.1127C6.31102 11.2905 6.51843 11.3793 6.75547 11.3793C6.99251 11.3793 7.19991 11.2905 7.37769 11.1127L12.3999 6.09045C12.5629 5.92749 12.6444 5.72008 12.6444 5.46823C12.6444 5.21638 12.5629 5.00897 12.3999 4.84601C12.237 4.68304 12.0295 4.60156 11.7777 4.60156C11.5258 4.60156 11.3184 4.68304 11.1555 4.84601L6.75547 9.24601Z",
|
|
36
|
-
fill: "#ffffff"
|
|
37
|
-
})
|
|
38
|
-
]
|
|
39
|
-
});
|
|
40
9
|
case 'check':
|
|
41
10
|
return /*#__PURE__*/ jsx(react_native_svg, {
|
|
42
11
|
width: size,
|
package/dist/icons/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { SvgProps } from 'react-native-svg';
|
|
2
2
|
import type { UXForegroundColor } from '@particle-network/ui-shared';
|
|
3
3
|
export type IconProps = SvgProps & {
|
|
4
|
-
name: '
|
|
4
|
+
name: 'check' | 'close' | 'dot' | 'radioOff' | 'radioOn' | 'question' | 'arrow-right';
|
|
5
5
|
size?: number;
|
|
6
6
|
color?: UXForegroundColor;
|
|
7
7
|
};
|
package/dist/locales/en.d.ts
CHANGED
|
@@ -10,6 +10,12 @@ export declare const en: {
|
|
|
10
10
|
cancel: string;
|
|
11
11
|
errorBothRequired: string;
|
|
12
12
|
errorStartBeforeEnd: string;
|
|
13
|
+
selectDate: string;
|
|
14
|
+
selectTime: string;
|
|
15
|
+
selectDateAndTime: string;
|
|
16
|
+
selectDateRange: string;
|
|
17
|
+
selectTimeRange: string;
|
|
18
|
+
selectDateAndTimeRange: string;
|
|
13
19
|
};
|
|
14
20
|
modal: {
|
|
15
21
|
confirm: string;
|
package/dist/locales/en.js
CHANGED
|
@@ -9,7 +9,13 @@ const en = {
|
|
|
9
9
|
confirm: 'Confirm',
|
|
10
10
|
cancel: 'Cancel',
|
|
11
11
|
errorBothRequired: 'Both start and end dates are required',
|
|
12
|
-
errorStartBeforeEnd: 'Start date can not be after end date'
|
|
12
|
+
errorStartBeforeEnd: 'Start date can not be after end date',
|
|
13
|
+
selectDate: 'Select Date',
|
|
14
|
+
selectTime: 'Select Time',
|
|
15
|
+
selectDateAndTime: 'Select Date and Time',
|
|
16
|
+
selectDateRange: 'Select Date Range',
|
|
17
|
+
selectTimeRange: 'Select Time Range',
|
|
18
|
+
selectDateAndTimeRange: 'Select Date and Time Range'
|
|
13
19
|
},
|
|
14
20
|
modal: {
|
|
15
21
|
confirm: 'Confirm',
|
package/dist/locales/index.d.ts
CHANGED
|
@@ -14,6 +14,12 @@ export declare const locales: {
|
|
|
14
14
|
cancel: string;
|
|
15
15
|
errorBothRequired: string;
|
|
16
16
|
errorStartBeforeEnd: string;
|
|
17
|
+
selectDate: string;
|
|
18
|
+
selectTime: string;
|
|
19
|
+
selectDateAndTime: string;
|
|
20
|
+
selectDateRange: string;
|
|
21
|
+
selectTimeRange: string;
|
|
22
|
+
selectDateAndTimeRange: string;
|
|
17
23
|
};
|
|
18
24
|
modal: {
|
|
19
25
|
confirm: string;
|
|
@@ -48,6 +54,12 @@ export declare const locales: {
|
|
|
48
54
|
cancel: string;
|
|
49
55
|
errorBothRequired: string;
|
|
50
56
|
errorStartBeforeEnd: string;
|
|
57
|
+
selectDate: string;
|
|
58
|
+
selectTime: string;
|
|
59
|
+
selectDateAndTime: string;
|
|
60
|
+
selectDateRange: string;
|
|
61
|
+
selectTimeRange: string;
|
|
62
|
+
selectDateAndTimeRange: string;
|
|
51
63
|
};
|
|
52
64
|
modal: {
|
|
53
65
|
confirm: string;
|
|
@@ -83,6 +95,12 @@ export declare function getLocaleText(locale: Locale): {
|
|
|
83
95
|
cancel: string;
|
|
84
96
|
errorBothRequired: string;
|
|
85
97
|
errorStartBeforeEnd: string;
|
|
98
|
+
selectDate: string;
|
|
99
|
+
selectTime: string;
|
|
100
|
+
selectDateAndTime: string;
|
|
101
|
+
selectDateRange: string;
|
|
102
|
+
selectTimeRange: string;
|
|
103
|
+
selectDateAndTimeRange: string;
|
|
86
104
|
};
|
|
87
105
|
modal: {
|
|
88
106
|
confirm: string;
|
package/dist/locales/zh.js
CHANGED
|
@@ -9,7 +9,13 @@ const zh = {
|
|
|
9
9
|
confirm: '确认',
|
|
10
10
|
cancel: '取消',
|
|
11
11
|
errorBothRequired: '请输入开始和结束日期',
|
|
12
|
-
errorStartBeforeEnd: '开始日期不能晚于结束日期'
|
|
12
|
+
errorStartBeforeEnd: '开始日期不能晚于结束日期',
|
|
13
|
+
selectDate: '选择日期',
|
|
14
|
+
selectTime: '选择时间',
|
|
15
|
+
selectDateAndTime: '选择日期和时间',
|
|
16
|
+
selectDateRange: '选择起止日期',
|
|
17
|
+
selectTimeRange: '选择起止时间',
|
|
18
|
+
selectDateAndTimeRange: '选择起止日期和时间'
|
|
13
19
|
},
|
|
14
20
|
modal: {
|
|
15
21
|
confirm: '确认',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@particle-network/ui-native",
|
|
3
|
-
"version": "0.1.4-beta.
|
|
3
|
+
"version": "0.1.4-beta.3",
|
|
4
4
|
"main": "./entry.js",
|
|
5
5
|
"react-native": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -90,9 +90,9 @@
|
|
|
90
90
|
"unfetch": "^4.2.0",
|
|
91
91
|
"vite": "^6.3.5",
|
|
92
92
|
"zustand": "^5.0.8",
|
|
93
|
-
"@particle-network/
|
|
93
|
+
"@particle-network/lintstaged-config": "0.1.0",
|
|
94
94
|
"@particle-network/eslint-config": "0.3.0",
|
|
95
|
-
"@particle-network/
|
|
95
|
+
"@particle-network/icons": "0.1.3-beta.3"
|
|
96
96
|
},
|
|
97
97
|
"overrides": {
|
|
98
98
|
"react-docgen-typescript": "2.2.2",
|