@fjyueke/arco-mcp 1.0.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/README.md +85 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +244 -0
- package/metaData/components/action-sheet/doc.md +102 -0
- package/metaData/components/action-sheet/example/index.tsx +199 -0
- package/metaData/components/action-sheet/example/methods.tsx +6 -0
- package/metaData/components/avatar/doc.md +57 -0
- package/metaData/components/avatar/example/group.tsx +69 -0
- package/metaData/components/avatar/example/index.tsx +196 -0
- package/metaData/components/badge/doc.md +28 -0
- package/metaData/components/badge/example/index.tsx +128 -0
- package/metaData/components/button/doc.md +45 -0
- package/metaData/components/button/example/index.tsx +264 -0
- package/metaData/components/carousel/doc.md +89 -0
- package/metaData/components/carousel/example/index.tsx +1481 -0
- package/metaData/components/cell/doc.md +68 -0
- package/metaData/components/cell/example/arrow.tsx +13 -0
- package/metaData/components/cell/example/cell.tsx +71 -0
- package/metaData/components/cell/example/group.tsx +63 -0
- package/metaData/components/cell/example/index.tsx +19 -0
- package/metaData/components/checkbox/doc.md +91 -0
- package/metaData/components/checkbox/example/checkbox.tsx +158 -0
- package/metaData/components/checkbox/example/group.tsx +103 -0
- package/metaData/components/checkbox/example/index.tsx +25 -0
- package/metaData/components/circle-progress/doc.md +40 -0
- package/metaData/components/circle-progress/example/index.tsx +323 -0
- package/metaData/components/collapse/doc.md +74 -0
- package/metaData/components/collapse/example/collapse.tsx +183 -0
- package/metaData/components/collapse/example/group.tsx +136 -0
- package/metaData/components/collapse/example/index.tsx +16 -0
- package/metaData/components/collapse/example/utils.tsx +20 -0
- package/metaData/components/context-provider/doc.md +44 -0
- package/metaData/components/context-provider/example/index.tsx +208 -0
- package/metaData/components/count-down/doc.md +40 -0
- package/metaData/components/count-down/example/hooks.tsx +118 -0
- package/metaData/components/count-down/example/index.tsx +63 -0
- package/metaData/components/date-picker/doc.md +102 -0
- package/metaData/components/date-picker/example/index.tsx +545 -0
- package/metaData/components/dialog/doc.md +200 -0
- package/metaData/components/dialog/example/index.tsx +328 -0
- package/metaData/components/dialog/example/methods.tsx +56 -0
- package/metaData/components/divider/doc.md +25 -0
- package/metaData/components/divider/example/index.tsx +87 -0
- package/metaData/components/dropdown/doc.md +80 -0
- package/metaData/components/dropdown/example/dropdown.tsx +308 -0
- package/metaData/components/dropdown/example/index.tsx +19 -0
- package/metaData/components/dropdown/example/options.tsx +103 -0
- package/metaData/components/dropdown-menu/doc.md +91 -0
- package/metaData/components/dropdown-menu/example/dropdown-menu.tsx +270 -0
- package/metaData/components/dropdown-menu/example/index.tsx +16 -0
- package/metaData/components/ellipsis/doc.md +33 -0
- package/metaData/components/ellipsis/example/index.tsx +93 -0
- package/metaData/components/ellipsis/example/js-ellipsis.tsx +229 -0
- package/metaData/components/ellipsis/example/native-ellipsis.tsx +48 -0
- package/metaData/components/form/doc.md +90 -0
- package/metaData/components/form/example/form-item-context.tsx +8 -0
- package/metaData/components/form/example/form-item.tsx +378 -0
- package/metaData/components/form/example/index.tsx +87 -0
- package/metaData/components/form/example/linked-container.tsx +66 -0
- package/metaData/components/grid/doc.md +39 -0
- package/metaData/components/grid/example/index.tsx +252 -0
- package/metaData/components/icon/doc.md +15 -0
- package/metaData/components/icon/example/index.tsx +32 -0
- package/metaData/components/image/doc.md +62 -0
- package/metaData/components/image/example/index.tsx +528 -0
- package/metaData/components/image-picker/doc.md +116 -0
- package/metaData/components/image-picker/example/add-icon.tsx +14 -0
- package/metaData/components/image-picker/example/index.tsx +175 -0
- package/metaData/components/image-preview/doc.md +119 -0
- package/metaData/components/image-preview/example/index.tsx +1290 -0
- package/metaData/components/image-preview/example/methods.tsx +72 -0
- package/metaData/components/index-bar/doc.md +83 -0
- package/metaData/components/index-bar/example/group.tsx +93 -0
- package/metaData/components/index-bar/example/index.tsx +271 -0
- package/metaData/components/index-bar/example/side-bar.tsx +82 -0
- package/metaData/components/input/doc.md +60 -0
- package/metaData/components/input/example/hooks.tsx +259 -0
- package/metaData/components/input/example/index.tsx +134 -0
- package/metaData/components/input/example/props.tsx +183 -0
- package/metaData/components/keyboard/doc.md +73 -0
- package/metaData/components/keyboard/example/index.tsx +238 -0
- package/metaData/components/load-more/doc.md +48 -0
- package/metaData/components/load-more/example/index.tsx +395 -0
- package/metaData/components/loading/doc.md +34 -0
- package/metaData/components/loading/example/index.tsx +312 -0
- package/metaData/components/masking/doc.md +93 -0
- package/metaData/components/masking/example/index.tsx +410 -0
- package/metaData/components/masking/example/methods.tsx +88 -0
- package/metaData/components/nav-bar/doc.md +40 -0
- package/metaData/components/nav-bar/example/back-icon.tsx +28 -0
- package/metaData/components/nav-bar/example/index.tsx +305 -0
- package/metaData/components/notice-bar/doc.md +34 -0
- package/metaData/components/notice-bar/example/index.tsx +294 -0
- package/metaData/components/notify/doc.md +81 -0
- package/metaData/components/notify/example/index.tsx +171 -0
- package/metaData/components/notify/example/methods.tsx +83 -0
- package/metaData/components/pagination/doc.md +41 -0
- package/metaData/components/pagination/example/arrow.tsx +14 -0
- package/metaData/components/pagination/example/index.tsx +292 -0
- package/metaData/components/picker/doc.md +89 -0
- package/metaData/components/picker/example/index.tsx +217 -0
- package/metaData/components/picker-view/doc.md +57 -0
- package/metaData/components/picker-view/example/cascader.tsx +141 -0
- package/metaData/components/picker-view/example/index.tsx +297 -0
- package/metaData/components/picker-view/example/multi-picker.tsx +66 -0
- package/metaData/components/picker-view/example/picker-cell.tsx +416 -0
- package/metaData/components/popover/doc.md +144 -0
- package/metaData/components/popover/example/index.tsx +23 -0
- package/metaData/components/popover/example/menu.tsx +145 -0
- package/metaData/components/popover/example/popover-inner.tsx +147 -0
- package/metaData/components/popover/example/popover.tsx +268 -0
- package/metaData/components/popup/doc.md +101 -0
- package/metaData/components/popup/example/index.tsx +125 -0
- package/metaData/components/popup/example/methods.tsx +6 -0
- package/metaData/components/popup-swiper/doc.md +108 -0
- package/metaData/components/popup-swiper/example/index.tsx +332 -0
- package/metaData/components/popup-swiper/example/methods.tsx +6 -0
- package/metaData/components/portal/doc.md +14 -0
- package/metaData/components/portal/example/index.tsx +35 -0
- package/metaData/components/progress/doc.md +42 -0
- package/metaData/components/progress/example/index.tsx +256 -0
- package/metaData/components/pull-refresh/doc.md +37 -0
- package/metaData/components/pull-refresh/example/android-pull-refresh.tsx +260 -0
- package/metaData/components/pull-refresh/example/index.tsx +44 -0
- package/metaData/components/pull-refresh/example/ios-pull-refresh.tsx +216 -0
- package/metaData/components/radio/doc.md +89 -0
- package/metaData/components/radio/example/group.tsx +92 -0
- package/metaData/components/radio/example/index.tsx +25 -0
- package/metaData/components/radio/example/radio.tsx +22 -0
- package/metaData/components/rate/doc.md +33 -0
- package/metaData/components/rate/example/index.tsx +281 -0
- package/metaData/components/search-bar/doc.md +97 -0
- package/metaData/components/search-bar/example/association.tsx +89 -0
- package/metaData/components/search-bar/example/cancel-button.tsx +34 -0
- package/metaData/components/search-bar/example/highlight.tsx +66 -0
- package/metaData/components/search-bar/example/index.tsx +251 -0
- package/metaData/components/show-monitor/doc.md +34 -0
- package/metaData/components/show-monitor/example/index.tsx +646 -0
- package/metaData/components/skeleton/doc.md +101 -0
- package/metaData/components/skeleton/example/elements.tsx +290 -0
- package/metaData/components/skeleton/example/index.tsx +96 -0
- package/metaData/components/skeleton/example/skeleton-context.tsx +7 -0
- package/metaData/components/slider/doc.md +42 -0
- package/metaData/components/slider/example/index.tsx +326 -0
- package/metaData/components/slider/example/marks.tsx +50 -0
- package/metaData/components/slider/example/popover.tsx +38 -0
- package/metaData/components/slider/example/thumb.tsx +48 -0
- package/metaData/components/slider/example/useSliderIcon.tsx +38 -0
- package/metaData/components/slider/example/useSliderInit.tsx +170 -0
- package/metaData/components/stepper/doc.md +46 -0
- package/metaData/components/stepper/example/index.tsx +166 -0
- package/metaData/components/stepper/example/useButtonClick.tsx +74 -0
- package/metaData/components/stepper/example/useInputEvent.tsx +65 -0
- package/metaData/components/stepper/example/useValue.tsx +43 -0
- package/metaData/components/steps/doc.md +57 -0
- package/metaData/components/steps/example/index.tsx +123 -0
- package/metaData/components/steps/example/step.tsx +126 -0
- package/metaData/components/sticky/doc.md +45 -0
- package/metaData/components/sticky/example/index.tsx +430 -0
- package/metaData/components/swipe-action/doc.md +44 -0
- package/metaData/components/swipe-action/example/index.tsx +338 -0
- package/metaData/components/swipe-action/example/item.tsx +40 -0
- package/metaData/components/swipe-load/doc.md +43 -0
- package/metaData/components/swipe-load/example/index.tsx +339 -0
- package/metaData/components/swipe-load/example/type.tsx +153 -0
- package/metaData/components/switch/doc.md +38 -0
- package/metaData/components/switch/example/index.tsx +237 -0
- package/metaData/components/tab-bar/doc.md +57 -0
- package/metaData/components/tab-bar/example/index.tsx +18 -0
- package/metaData/components/tab-bar/example/item.tsx +74 -0
- package/metaData/components/tab-bar/example/tab-bar.tsx +105 -0
- package/metaData/components/tabs/doc.md +187 -0
- package/metaData/components/tabs/example/index.tsx +514 -0
- package/metaData/components/tabs/example/tab-cell-underline.tsx +320 -0
- package/metaData/components/tabs/example/tab-cell.tsx +433 -0
- package/metaData/components/tabs/example/tab-pane.tsx +349 -0
- package/metaData/components/tag/doc.md +80 -0
- package/metaData/components/tag/example/index.tsx +23 -0
- package/metaData/components/tag/example/list.tsx +97 -0
- package/metaData/components/tag/example/tag.tsx +85 -0
- package/metaData/components/textarea/doc.md +67 -0
- package/metaData/components/textarea/example/index.tsx +258 -0
- package/metaData/components/toast/doc.md +90 -0
- package/metaData/components/toast/example/index.tsx +335 -0
- package/metaData/components/toast/example/methods.tsx +87 -0
- package/metaData/components/transition/doc.md +19 -0
- package/metaData/components/transition/example/index.tsx +113 -0
- package/metaData/components/uploader/doc.md +82 -0
- package/metaData/components/uploader/example/index.tsx +208 -0
- package/metaData/components-index.json +242 -0
- package/package.json +56 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
forwardRef,
|
|
3
|
+
Ref,
|
|
4
|
+
useContext,
|
|
5
|
+
useEffect,
|
|
6
|
+
useImperativeHandle,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import { cls } from '@arco-design/mobile-utils';
|
|
11
|
+
import { Collapse } from './collapse';
|
|
12
|
+
import { defaultContextKey, getCollapseContext, CollapseKeyContext } from './utils';
|
|
13
|
+
import { GlobalContext } from '../context-provider';
|
|
14
|
+
import {
|
|
15
|
+
CollapseItemContent,
|
|
16
|
+
CollapseProps,
|
|
17
|
+
CollapseRef,
|
|
18
|
+
CollapseGroupProps,
|
|
19
|
+
CollapseGroupRef,
|
|
20
|
+
} from './type';
|
|
21
|
+
|
|
22
|
+
export function componentGenerator<
|
|
23
|
+
P extends CollapseItemContent = CollapseProps,
|
|
24
|
+
R extends CollapseRef = CollapseRef,
|
|
25
|
+
>(Comp: React.ForwardRefExoticComponent<P & React.RefAttributes<R>>) {
|
|
26
|
+
return forwardRef((props: CollapseGroupProps<P>, ref: Ref<CollapseGroupRef | null>) => {
|
|
27
|
+
const {
|
|
28
|
+
items = [],
|
|
29
|
+
className = '',
|
|
30
|
+
style = {},
|
|
31
|
+
defaultActiveItems = [],
|
|
32
|
+
useAccordion = false,
|
|
33
|
+
disabled = false,
|
|
34
|
+
children,
|
|
35
|
+
groupKey,
|
|
36
|
+
} = props;
|
|
37
|
+
const [innerActiveItems, setInnerActiveItems] = useState<boolean[]>([]);
|
|
38
|
+
const [activeItems, setActiveItems] = useState<boolean[]>([]);
|
|
39
|
+
/** 用于children模式下的active管理 */
|
|
40
|
+
const [childActiveItems, setChildActiveItems] = useState<string[]>([]);
|
|
41
|
+
const contextKey = groupKey || defaultContextKey;
|
|
42
|
+
const CollapseContext = getCollapseContext(contextKey);
|
|
43
|
+
const domRef = useRef<HTMLDivElement | null>(null);
|
|
44
|
+
const { prefixCls } = useContext(GlobalContext);
|
|
45
|
+
|
|
46
|
+
const formatArray = (input: string[]) => {
|
|
47
|
+
const arr = input;
|
|
48
|
+
return items.map(item => arr.indexOf(item.value) > -1);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const handleChange = (value: string) => {
|
|
52
|
+
if (disabled) return;
|
|
53
|
+
if (props.onCollapse) {
|
|
54
|
+
props.onCollapse(value);
|
|
55
|
+
}
|
|
56
|
+
if (props.activeItems !== void 0) {
|
|
57
|
+
setInnerActiveItems(formatArray(props.activeItems));
|
|
58
|
+
setChildActiveItems(props.activeItems);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (!children) {
|
|
62
|
+
const temp = items.findIndex(item => item.value === value);
|
|
63
|
+
if (temp < 0 || items[temp].disabled) return;
|
|
64
|
+
const tempActiveItems = innerActiveItems.map((activeItem, index) =>
|
|
65
|
+
index === temp ? !activeItem : !useAccordion && activeItem,
|
|
66
|
+
);
|
|
67
|
+
setInnerActiveItems(tempActiveItems);
|
|
68
|
+
} else {
|
|
69
|
+
const tempValue = childActiveItems.includes(value);
|
|
70
|
+
setChildActiveItems(
|
|
71
|
+
tempValue
|
|
72
|
+
? childActiveItems.filter(item => item !== value)
|
|
73
|
+
: useAccordion // 手风琴模式只有一个展开项
|
|
74
|
+
? [value]
|
|
75
|
+
: [...childActiveItems, value],
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
setInnerActiveItems(formatArray(defaultActiveItems));
|
|
82
|
+
setChildActiveItems(defaultActiveItems);
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
setActiveItems(
|
|
87
|
+
props.activeItems === void 0 ? innerActiveItems : formatArray(props.activeItems),
|
|
88
|
+
);
|
|
89
|
+
if (children && props.activeItems) {
|
|
90
|
+
setChildActiveItems(props.activeItems);
|
|
91
|
+
}
|
|
92
|
+
}, [props.activeItems, innerActiveItems]);
|
|
93
|
+
|
|
94
|
+
useImperativeHandle(ref, () => ({
|
|
95
|
+
dom: domRef.current,
|
|
96
|
+
}));
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<div
|
|
100
|
+
className={cls(`${prefixCls}-collapse-group`, className)}
|
|
101
|
+
style={style}
|
|
102
|
+
ref={domRef}
|
|
103
|
+
>
|
|
104
|
+
<CollapseKeyContext.Provider value={{ key: contextKey }}>
|
|
105
|
+
<CollapseContext.Provider
|
|
106
|
+
value={{
|
|
107
|
+
isGroup: true,
|
|
108
|
+
onCollapse: handleChange,
|
|
109
|
+
disabled,
|
|
110
|
+
value: children ? childActiveItems : void 0,
|
|
111
|
+
}}
|
|
112
|
+
>
|
|
113
|
+
{children || (
|
|
114
|
+
<>
|
|
115
|
+
{items.map((item, index) => {
|
|
116
|
+
const compProps = {
|
|
117
|
+
active: activeItems[index],
|
|
118
|
+
disabled: disabled || item.disabled,
|
|
119
|
+
defaultActive: formatArray(defaultActiveItems)[index],
|
|
120
|
+
...item,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
return <Comp key={item.value} {...compProps} />;
|
|
124
|
+
})}
|
|
125
|
+
</>
|
|
126
|
+
)}
|
|
127
|
+
</CollapseContext.Provider>
|
|
128
|
+
</CollapseKeyContext.Provider>
|
|
129
|
+
</div>
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export const Group = componentGenerator(Collapse);
|
|
135
|
+
|
|
136
|
+
export default Group;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { componentWrapper } from '@arco-design/mobile-utils';
|
|
2
|
+
import { Collapse } from './collapse';
|
|
3
|
+
import Group from './group';
|
|
4
|
+
|
|
5
|
+
export * from './collapse';
|
|
6
|
+
export * from './type';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 折叠面板组件,支持手风琴模式。
|
|
10
|
+
* @en Collapse supports accordion mode.
|
|
11
|
+
* @type 信息展示
|
|
12
|
+
* @type_en Data Display
|
|
13
|
+
* @name 折叠面板
|
|
14
|
+
* @name_en Collapse
|
|
15
|
+
*/
|
|
16
|
+
export default componentWrapper(Collapse, { Group });
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React, { Context } from 'react';
|
|
2
|
+
import { GroupContextParams } from './type';
|
|
3
|
+
|
|
4
|
+
export const defaultContextKey = '__COLLAPSE_CONTEXT__';
|
|
5
|
+
export const allContexts: Record<string, Context<GroupContextParams>> = {};
|
|
6
|
+
|
|
7
|
+
export function getCollapseContext(key: string) {
|
|
8
|
+
if (!allContexts[key]) {
|
|
9
|
+
allContexts[key] = React.createContext<GroupContextParams>({
|
|
10
|
+
isGroup: false,
|
|
11
|
+
value: [],
|
|
12
|
+
onCollapse: () => {},
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return allContexts[key];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const CollapseKeyContext = React.createContext<{ key: string }>({
|
|
19
|
+
key: defaultContextKey,
|
|
20
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
### 其他
|
|
2
|
+
|
|
3
|
+
# 全局配置 ContextProvider
|
|
4
|
+
|
|
5
|
+
全局数据控制组件,用于替换全局数据。
|
|
6
|
+
|
|
7
|
+
======
|
|
8
|
+
|
|
9
|
+
> 属性/Props
|
|
10
|
+
|
|
11
|
+
|参数|描述|类型|默认值|
|
|
12
|
+
|----------|-------------|------|------|
|
|
13
|
+
|prefixCls|组件类名前缀|string|"arco"|
|
|
14
|
+
|system|手动控制当前所在系统,传入后将直接使用传入的值,ssr场景需指定系统初始值时适用|"" \| "pc" \| "android" \| "ios"|""|
|
|
15
|
+
|useDarkMode|是否监听系统原生的暗黑模式变化(prefers\-color\-scheme: dark)以判断是否切为暗黑模式|boolean|false|
|
|
16
|
+
|isDarkMode|是否处于暗黑模式,指定后以指定的值为准|boolean|false|
|
|
17
|
+
|darkModeSelector|当处于暗黑模式时,body上挂载的类名,为空值时不挂载类名|string|"arco-theme-dark"|
|
|
18
|
+
|theme|主题变量,传入后将在线替换css变量,需设置less变量 @use\-css\-vars: 1|Record\<string, string\>|-|
|
|
19
|
+
|locale|国际化语言包配置|ILocale|-|
|
|
20
|
+
|useRtl|是否使用Rtl模式|boolean|false|
|
|
21
|
+
|onDarkModeChange|当系统原生暗黑模式发生变化时触发,useDarkMode=true 时有效|(isDark: boolean) =\> void|-|
|
|
22
|
+
|createRoot|React19 修改了 createRoot 的引入路径,导致组件内部无法直接引入(低react版本会找不到模块)。因此使用 react 19 的用户需从外部传入 createRoot 方法|CreateRootFnType|-|
|
|
23
|
+
|
|
24
|
+
> ILocale
|
|
25
|
+
|
|
26
|
+
|参数|描述|类型|
|
|
27
|
+
|----------|-------------|------|
|
|
28
|
+
|locale|语言类型|string|
|
|
29
|
+
|LoadMore|-|\{ loadMoreText: string; loadingText: string; noDataText: string; failLoadText: string; prepareScrollText: string; prepareClickText: string; \}|
|
|
30
|
+
|Picker|-|\{ okText: string; cancelText: string; \}|
|
|
31
|
+
|Tag|-|\{ addTag: string; \}|
|
|
32
|
+
|Dialog|-|\{ okText: string; cancelText: string; \}|
|
|
33
|
+
|SwipeLoad|-|\{ normalText: string; activeText: string; \}|
|
|
34
|
+
|PullRefresh|-|\{ loadingText: string; pullingText: string; finishText: string; loosingText: string; \}|
|
|
35
|
+
|DropdownMenu|-|\{ select: string; \}|
|
|
36
|
+
|Pagination|-|\{ previousPage: string; nextPage: string; \}|
|
|
37
|
+
|Image|-|\{ loadError: string; \}|
|
|
38
|
+
|ImagePicker|-|\{ loadError: string; \}|
|
|
39
|
+
|SearchBar|-|\{ placeholder: string; cancelBtn: string; \}|
|
|
40
|
+
|Stepper|-|\{ minusButtonName: string; addButtonName: string; \}|
|
|
41
|
+
|Keyboard|-|\{ confirm: string; \}|
|
|
42
|
+
|Form|-|\{ required: string; type: \{ email: string; url: string; string: string; number: string; array: string; object: string; boolean: string; \}; number: \{ min: string; max: string; equal: string; range: string; positive: string; negative: string; \}; \.\.\. 4 more \.\.\.; pickerDefaultHint: string; \}|
|
|
43
|
+
|NavBar|-|\{ backBtnAriaLabel: string; \}|
|
|
44
|
+
|Uploader|-|\{ uploadBtn: string; retryUpload: string; \}|
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useState,
|
|
4
|
+
useEffect,
|
|
5
|
+
useCallback,
|
|
6
|
+
useMemo,
|
|
7
|
+
useRef,
|
|
8
|
+
Attributes,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import { addCssRules, removeCssStyleDom, defaultLocale, ILocale } from '@arco-design/mobile-utils';
|
|
11
|
+
import { CreateRootFnType } from '../_helpers';
|
|
12
|
+
|
|
13
|
+
export interface GlobalContextParams {
|
|
14
|
+
/**
|
|
15
|
+
* 组件类名前缀
|
|
16
|
+
* @en Component classname prefix
|
|
17
|
+
* @default "arco"
|
|
18
|
+
*/
|
|
19
|
+
prefixCls?: string;
|
|
20
|
+
/**
|
|
21
|
+
* 手动控制当前所在系统,传入后将直接使用传入的值,ssr场景需指定系统初始值时适用
|
|
22
|
+
* @en Manually control the current system, and the incoming value will be used directly after being passed in. It is applicable when the initial value of the system needs to be specified in the ssr scenario.
|
|
23
|
+
* @default ""
|
|
24
|
+
*/
|
|
25
|
+
system?: 'pc' | 'android' | 'ios' | '';
|
|
26
|
+
/**
|
|
27
|
+
* 是否监听系统原生的暗黑模式变化(prefers-color-scheme: dark)以判断是否切为暗黑模式
|
|
28
|
+
* @en Whether to monitor the system's native dark mode changes (prefers-color-scheme: dark) to determine whether to switch to dark mode
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
useDarkMode?: boolean;
|
|
32
|
+
/**
|
|
33
|
+
* 是否处于暗黑模式,指定后以指定的值为准
|
|
34
|
+
* @en Whether it is in dark mode, the value shall prevail after being specified
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
isDarkMode?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 当处于暗黑模式时,body上挂载的类名,为空值时不挂载类名
|
|
40
|
+
* @en When in dark mode, the class name mounted on the body, if it is empty, the class name will not be mounted
|
|
41
|
+
* @default "arco-theme-dark"
|
|
42
|
+
*/
|
|
43
|
+
darkModeSelector?: string;
|
|
44
|
+
/**
|
|
45
|
+
* 主题变量,传入后将在线替换css变量,需设置less变量 @use-css-vars: 1
|
|
46
|
+
* @en Theme variable. The css variable will be replaced online after input. The less variable needs to be set @use-css-vars: 1
|
|
47
|
+
*/
|
|
48
|
+
theme?: Record<string, string>;
|
|
49
|
+
/**
|
|
50
|
+
* 国际化语言包配置
|
|
51
|
+
* @en Internationalized language configuration
|
|
52
|
+
*/
|
|
53
|
+
locale?: ILocale;
|
|
54
|
+
/**
|
|
55
|
+
* 是否使用Rtl模式
|
|
56
|
+
* @en Whether to use rtl
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
useRtl?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* 当系统原生暗黑模式发生变化时触发,useDarkMode=true 时有效
|
|
62
|
+
* @en Triggered when the system's native dark mode changes, valid when useDarkMode=true
|
|
63
|
+
*/
|
|
64
|
+
onDarkModeChange?: (isDark: boolean) => void;
|
|
65
|
+
/**
|
|
66
|
+
* React19 修改了 createRoot 的引入路径,导致组件内部无法直接引入(低react版本会找不到模块)。因此使用 react 19 的用户需从外部传入 createRoot 方法
|
|
67
|
+
* @en Users using react 19 need to pass in the createRoot method from outside
|
|
68
|
+
*/
|
|
69
|
+
createRoot?: CreateRootFnType;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const DEFAULT_DARK_MODE_SELECTOR = 'arco-theme-dark';
|
|
73
|
+
|
|
74
|
+
export const defaultContext: GlobalContextParams = {
|
|
75
|
+
prefixCls: 'arco',
|
|
76
|
+
system: '',
|
|
77
|
+
useDarkMode: false,
|
|
78
|
+
darkModeSelector: DEFAULT_DARK_MODE_SELECTOR,
|
|
79
|
+
locale: defaultLocale,
|
|
80
|
+
useRtl: false,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const GlobalContext = createContext<GlobalContextParams>(defaultContext);
|
|
84
|
+
|
|
85
|
+
export interface ContextProviderProps extends GlobalContextParams {
|
|
86
|
+
children: React.ReactNode;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export type WithGlobalContext<T> = T & { context?: GlobalContextParams };
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* 全局数据控制组件,用于替换全局数据。
|
|
93
|
+
* @en Global data control component, used to replace global data.
|
|
94
|
+
* @type 其他
|
|
95
|
+
* @type_en Others
|
|
96
|
+
* @name 全局配置
|
|
97
|
+
* @name_en ContextProvider
|
|
98
|
+
*/
|
|
99
|
+
export default function ContextProvider(props: ContextProviderProps) {
|
|
100
|
+
const {
|
|
101
|
+
children,
|
|
102
|
+
useDarkMode,
|
|
103
|
+
isDarkMode: userSetIsDarkMode,
|
|
104
|
+
darkModeSelector = DEFAULT_DARK_MODE_SELECTOR,
|
|
105
|
+
theme,
|
|
106
|
+
locale = defaultLocale,
|
|
107
|
+
onDarkModeChange,
|
|
108
|
+
...restProps
|
|
109
|
+
} = props;
|
|
110
|
+
|
|
111
|
+
const [isDarkModeState, setIsDarkModeState] = useState<boolean>(() => {
|
|
112
|
+
if (typeof window !== 'undefined' && useDarkMode) {
|
|
113
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
});
|
|
117
|
+
const mountedRef = useRef(false);
|
|
118
|
+
|
|
119
|
+
const setDarkModeState = (isDark: boolean, needChange = true) => {
|
|
120
|
+
setIsDarkModeState(isDark);
|
|
121
|
+
needChange && onDarkModeChange && onDarkModeChange(isDark);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const isDarkMode = useMemo(() => {
|
|
125
|
+
// 如果未开启暗黑模式则不对body做操作
|
|
126
|
+
// @en If dark mode is not turned on, no operation will be performed on the body
|
|
127
|
+
if (userSetIsDarkMode === void 0 && !useDarkMode) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
const value = Boolean(userSetIsDarkMode !== void 0 ? userSetIsDarkMode : isDarkModeState);
|
|
131
|
+
const needUpdateBody = darkModeSelector && typeof document !== 'undefined';
|
|
132
|
+
if (value) {
|
|
133
|
+
needUpdateBody && document.body.classList.add(darkModeSelector);
|
|
134
|
+
} else {
|
|
135
|
+
needUpdateBody && document.body.classList.remove(darkModeSelector);
|
|
136
|
+
}
|
|
137
|
+
return value;
|
|
138
|
+
}, [userSetIsDarkMode, isDarkModeState, darkModeSelector, useDarkMode]);
|
|
139
|
+
|
|
140
|
+
const changeDarkMode = useCallback(
|
|
141
|
+
(res: MediaQueryListEvent) => setDarkModeState(res.matches),
|
|
142
|
+
[],
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
useEffect(() => {
|
|
146
|
+
const matchMedia = window.matchMedia('(prefers-color-scheme: dark)');
|
|
147
|
+
if (useDarkMode) {
|
|
148
|
+
const dark = matchMedia.matches;
|
|
149
|
+
setDarkModeState(dark, mountedRef.current);
|
|
150
|
+
if (typeof matchMedia.addEventListener === 'function') {
|
|
151
|
+
matchMedia.addEventListener('change', changeDarkMode);
|
|
152
|
+
} else if (typeof matchMedia.addListener === 'function') {
|
|
153
|
+
matchMedia.addListener(changeDarkMode);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
mountedRef.current = true;
|
|
157
|
+
return () => {
|
|
158
|
+
if (useDarkMode) {
|
|
159
|
+
if (typeof matchMedia.removeEventListener === 'function') {
|
|
160
|
+
matchMedia.removeEventListener('change', changeDarkMode);
|
|
161
|
+
} else if (typeof matchMedia.removeListener === 'function') {
|
|
162
|
+
matchMedia.removeListener(changeDarkMode);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}, [useDarkMode]);
|
|
167
|
+
|
|
168
|
+
useEffect(() => {
|
|
169
|
+
if (!theme) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
addCssRules('arcoCustomTheme', theme);
|
|
173
|
+
return () => {
|
|
174
|
+
removeCssStyleDom('arcoCustomTheme');
|
|
175
|
+
};
|
|
176
|
+
}, [theme]);
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<GlobalContext.Provider
|
|
180
|
+
value={{
|
|
181
|
+
...defaultContext,
|
|
182
|
+
...restProps,
|
|
183
|
+
isDarkMode,
|
|
184
|
+
useDarkMode,
|
|
185
|
+
locale: locale || defaultLocale,
|
|
186
|
+
}}
|
|
187
|
+
>
|
|
188
|
+
{children}
|
|
189
|
+
</GlobalContext.Provider>
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export const ContextLayout = GlobalContext.Consumer;
|
|
194
|
+
|
|
195
|
+
export function CompWithGlobalContext<P extends Attributes>(Component: React.FunctionComponent<P>) {
|
|
196
|
+
return function (props: WithGlobalContext<P>) {
|
|
197
|
+
const { context: propsContext, ...others } = props;
|
|
198
|
+
return (
|
|
199
|
+
<ContextLayout>
|
|
200
|
+
{context => (
|
|
201
|
+
<ContextProvider {...{ ...context, ...propsContext }}>
|
|
202
|
+
<Component {...(others as P)} />
|
|
203
|
+
</ContextProvider>
|
|
204
|
+
)}
|
|
205
|
+
</ContextLayout>
|
|
206
|
+
);
|
|
207
|
+
};
|
|
208
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
### 信息展示
|
|
2
|
+
|
|
3
|
+
# 倒计时 CountDown
|
|
4
|
+
|
|
5
|
+
倒计时组件
|
|
6
|
+
|
|
7
|
+
======
|
|
8
|
+
|
|
9
|
+
> 属性/Props
|
|
10
|
+
|
|
11
|
+
|参数|描述|类型|默认值|
|
|
12
|
+
|----------|-------------|------|------|
|
|
13
|
+
|className|自定义类名|string|-|
|
|
14
|
+
|style|自定义样式|CSSProperties|-|
|
|
15
|
+
|time|倒计时时长,单位毫秒|number \| TimeDataType|0|
|
|
16
|
+
|format|自定义格式 D:天数 DD:天数(个位数补0) H:小时 HH:小时(个位数补0) m:分钟 mm:分钟(个位数补0) s:秒数 ss:秒数(个位数补0) S:毫秒(1 位)SS:毫秒(2 位)SSS:毫秒(3 位)|string|HH:mm:ss|
|
|
17
|
+
|autoStart|是否自动开始倒计时|boolean|true|
|
|
18
|
+
|millisecond|是否开启毫秒级渲染|boolean|false|
|
|
19
|
+
|onFinish|倒计时结束时触发|() =\> void|-|
|
|
20
|
+
|onChange|倒计时变化时触发|(val: TimeDataType, ts: number) =\> void|-|
|
|
21
|
+
|renderChild|自定义内容|(val: TimeDataType) =\> ReactNode|-|
|
|
22
|
+
|
|
23
|
+
> 引用/Refs
|
|
24
|
+
|
|
25
|
+
|参数|描述|类型|
|
|
26
|
+
|----------|-------------|------|
|
|
27
|
+
|dom|最外层元素 DOM|HTMLDivElement|
|
|
28
|
+
|start|开始|() =\> void|
|
|
29
|
+
|pause|暂停|() =\> void|
|
|
30
|
+
|reset|重置|() =\> void|
|
|
31
|
+
|
|
32
|
+
> TimeDataType
|
|
33
|
+
|
|
34
|
+
|参数|描述|类型|
|
|
35
|
+
|----------|-------------|------|
|
|
36
|
+
|days|天数|number|
|
|
37
|
+
|hours|小时|number|
|
|
38
|
+
|minutes|分钟|number|
|
|
39
|
+
|seconds|秒数|number|
|
|
40
|
+
|milliseconds|毫秒|number|
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from 'react';
|
|
2
|
+
import { useRefState } from '../_helpers';
|
|
3
|
+
import { startTask, stopTask } from './singleton';
|
|
4
|
+
import { CountDownProps, TimeDataType } from './type';
|
|
5
|
+
import { parseTime } from './util';
|
|
6
|
+
|
|
7
|
+
export type UseCountDownOptions = {
|
|
8
|
+
time: number;
|
|
9
|
+
} & Pick<CountDownProps, 'millisecond' | 'autoStart' | 'onChange' | 'onFinish'>;
|
|
10
|
+
|
|
11
|
+
export const useCountDown = (options: UseCountDownOptions) => {
|
|
12
|
+
const taskIdRef = useRef<number>(0);
|
|
13
|
+
const endTimeRef = useRef<number | undefined>(undefined);
|
|
14
|
+
const countingRef = useRef<boolean | undefined>(undefined);
|
|
15
|
+
const [remain, remainRef, setRemain] = useRefState(options.time);
|
|
16
|
+
const [current, setCurrent] = useState<TimeDataType>(parseTime(options.time));
|
|
17
|
+
const taskType = options.millisecond ? 'micro' : 'macro';
|
|
18
|
+
|
|
19
|
+
// 暂停
|
|
20
|
+
// @en Pause
|
|
21
|
+
const pause = () => {
|
|
22
|
+
countingRef.current = false;
|
|
23
|
+
stopTask(taskType, taskIdRef.current);
|
|
24
|
+
};
|
|
25
|
+
// 计算当前剩余时间,以毫秒为单位
|
|
26
|
+
// @en Calculate the current remaining time in milliseconds
|
|
27
|
+
const getCurrentRemain = () => {
|
|
28
|
+
const leftTime = Math.max((endTimeRef.current as number) - Date.now(), 0);
|
|
29
|
+
if (options.millisecond) {
|
|
30
|
+
return leftTime;
|
|
31
|
+
}
|
|
32
|
+
return Math.round(leftTime / 1000) * 1000;
|
|
33
|
+
};
|
|
34
|
+
const setRemainCallback = (value: number) => {
|
|
35
|
+
setRemain(value);
|
|
36
|
+
const time: TimeDataType = parseTime(value);
|
|
37
|
+
if (options.onChange && value !== options.time) {
|
|
38
|
+
options.onChange(time, value);
|
|
39
|
+
}
|
|
40
|
+
if (value === 0) {
|
|
41
|
+
setCurrent(time);
|
|
42
|
+
pause();
|
|
43
|
+
options.onFinish?.();
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
// 开启任务
|
|
47
|
+
// @en start tasks
|
|
48
|
+
const tick = () => {
|
|
49
|
+
taskIdRef.current = startTask(taskType, () => {
|
|
50
|
+
if (countingRef.current) {
|
|
51
|
+
setRemainCallback(getCurrentRemain());
|
|
52
|
+
return remainRef.current > 0;
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
// 开始
|
|
58
|
+
// @en Start
|
|
59
|
+
const start = (reStart = false) => {
|
|
60
|
+
if (!countingRef.current) {
|
|
61
|
+
if (reStart) {
|
|
62
|
+
endTimeRef.current = Date.now() + options.time;
|
|
63
|
+
} else {
|
|
64
|
+
endTimeRef.current = Date.now() + remainRef.current;
|
|
65
|
+
}
|
|
66
|
+
countingRef.current = true;
|
|
67
|
+
tick();
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
// 重置
|
|
71
|
+
// @en Reset
|
|
72
|
+
const reset = () => {
|
|
73
|
+
const totalTime = options.time;
|
|
74
|
+
endTimeRef.current = Date.now() + totalTime;
|
|
75
|
+
pause();
|
|
76
|
+
setRemainCallback(totalTime);
|
|
77
|
+
if (options.autoStart) {
|
|
78
|
+
start(true);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
// ummounted时如果正在运行倒计时则暂停
|
|
84
|
+
// @en Pause if the countdown is running when ummounted
|
|
85
|
+
return () => {
|
|
86
|
+
if (countingRef.current) {
|
|
87
|
+
pause();
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
}, []);
|
|
91
|
+
|
|
92
|
+
// 设置自动开始倒计时时自动启动
|
|
93
|
+
// @en Set to start automatically when the countdown starts automatically
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
if (options.autoStart) {
|
|
96
|
+
start();
|
|
97
|
+
}
|
|
98
|
+
}, [options.autoStart]);
|
|
99
|
+
|
|
100
|
+
// 倒计时设置变化时重新计时
|
|
101
|
+
// @en Re-time when countdown settings change
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
reset();
|
|
104
|
+
}, [options.time]);
|
|
105
|
+
|
|
106
|
+
// remain变化时同步current 即把毫秒转化为TimeDataType类型
|
|
107
|
+
// @en Synchronize current when remain changes, that is, convert milliseconds to TimeDataType
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
setCurrent(parseTime(remain));
|
|
110
|
+
}, [remain]);
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
start,
|
|
114
|
+
pause,
|
|
115
|
+
reset,
|
|
116
|
+
current,
|
|
117
|
+
};
|
|
118
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React, { useRef, forwardRef, Ref, useImperativeHandle, useMemo } from 'react';
|
|
2
|
+
import { unParseTime, parseFormat } from './util';
|
|
3
|
+
import { useCountDown } from './hooks';
|
|
4
|
+
import { ContextLayout } from '../context-provider';
|
|
5
|
+
import { CountDownProps, CountDownRef } from './type';
|
|
6
|
+
|
|
7
|
+
export * from './type';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 倒计时组件
|
|
11
|
+
* @en Countdown Component
|
|
12
|
+
* @name 倒计时
|
|
13
|
+
* @name_en CountDown
|
|
14
|
+
* @type 信息展示
|
|
15
|
+
* @type_en Data Display
|
|
16
|
+
*/
|
|
17
|
+
const CountDown = forwardRef((props: CountDownProps, ref: Ref<CountDownRef>) => {
|
|
18
|
+
const {
|
|
19
|
+
className = '',
|
|
20
|
+
style = {},
|
|
21
|
+
time = 0,
|
|
22
|
+
format = 'HH:mm:ss',
|
|
23
|
+
autoStart = true,
|
|
24
|
+
millisecond = false,
|
|
25
|
+
onFinish,
|
|
26
|
+
onChange,
|
|
27
|
+
renderChild,
|
|
28
|
+
} = props;
|
|
29
|
+
const domRef = useRef<HTMLDivElement>(null);
|
|
30
|
+
|
|
31
|
+
// 传入倒计时等变量得到开始暂停启动三个方法以及目前所剩时间current(TimeDataType格式)
|
|
32
|
+
// @en get start, pause, reset methods and the current remaining time —— current (TimeDataType format) by inputing variables such as countdown
|
|
33
|
+
const { start, pause, reset, current } = useCountDown({
|
|
34
|
+
time: typeof time === 'number' ? time : unParseTime(time),
|
|
35
|
+
millisecond,
|
|
36
|
+
onChange,
|
|
37
|
+
onFinish,
|
|
38
|
+
autoStart,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// 导出dom以及start,pause,reset三个方法
|
|
42
|
+
// @en Export dom and three methods of start, pause and reset
|
|
43
|
+
useImperativeHandle(ref, () => ({
|
|
44
|
+
dom: domRef.current,
|
|
45
|
+
start,
|
|
46
|
+
pause,
|
|
47
|
+
reset,
|
|
48
|
+
}));
|
|
49
|
+
|
|
50
|
+
const currentStr = useMemo(() => parseFormat(format, current), [format, current]);
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<ContextLayout>
|
|
54
|
+
{({ prefixCls }) => (
|
|
55
|
+
<div className={`${prefixCls}-count-down ${className}`} style={style} ref={domRef}>
|
|
56
|
+
{renderChild ? renderChild(current) : currentStr}
|
|
57
|
+
</div>
|
|
58
|
+
)}
|
|
59
|
+
</ContextLayout>
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
export default CountDown;
|