@tendaui/components 1.0.0 → 1.0.2
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/LICENSE +21 -21
- package/README.md +176 -176
- package/alert/Alert.tsx +3 -2
- package/button/_example/base.tsx +10 -0
- package/button/_example/icon.tsx +20 -0
- package/color-picker/ColorPickPanel.tsx +9 -0
- package/color-picker/ColorPicker.tsx +67 -0
- package/color-picker/components/panel/alpha.tsx +32 -0
- package/color-picker/components/panel/format/index.tsx +47 -0
- package/color-picker/components/panel/format/inputs.tsx +119 -0
- package/color-picker/components/panel/header.tsx +37 -0
- package/color-picker/components/panel/hue.tsx +20 -0
- package/color-picker/components/panel/index.tsx +191 -0
- package/color-picker/components/panel/saturation.tsx +81 -0
- package/color-picker/components/panel/slider.tsx +76 -0
- package/color-picker/components/panel/swatches.tsx +84 -0
- package/color-picker/components/trigger.tsx +49 -0
- package/color-picker/defaultProps.ts +7 -0
- package/color-picker/helpers.ts +53 -0
- package/color-picker/hooks/useClassNames.ts +9 -0
- package/color-picker/hooks/useStyles.ts +39 -0
- package/color-picker/index.ts +12 -0
- package/color-picker/style/css.js +1 -0
- package/color-picker/style/index.js +1 -0
- package/color-picker/type.ts +143 -0
- package/color-picker/utils/color-picker/cmyk.ts +89 -0
- package/color-picker/utils/color-picker/color.ts +467 -0
- package/color-picker/utils/color-picker/constants.ts +187 -0
- package/color-picker/utils/color-picker/draggable.ts +100 -0
- package/color-picker/utils/color-picker/format.ts +95 -0
- package/color-picker/utils/color-picker/gradient.ts +243 -0
- package/color-picker/utils/color-picker/index.ts +7 -0
- package/color-picker/utils/color-picker/types.ts +33 -0
- package/common/observe.ts +33 -0
- package/common.ts +20 -0
- package/config-provider/ConfigContext.tsx +4 -1
- package/config-provider/index.ts +1 -1
- package/dialog/DialogCard.tsx +4 -6
- package/dialog/hooks/useDialogPosition.ts +1 -2
- package/dialog/plugin.tsx +3 -2
- package/drawer/Drawer.tsx +264 -0
- package/drawer/defaultProps.ts +19 -0
- package/drawer/hooks/useDrag.ts +98 -0
- package/drawer/hooks/useLockStyle.ts +36 -0
- package/drawer/index.ts +5 -0
- package/drawer/style/css.js +1 -0
- package/drawer/style/index.js +1 -0
- package/drawer/type.ts +193 -0
- package/drawer/utils/index.ts +76 -0
- package/fireworks/Fireworks.tsx +138 -0
- package/fireworks/index.ts +10 -0
- package/fireworks/style/css.js +0 -0
- package/fireworks/style/index.js +0 -0
- package/fireworks/type.ts +72 -0
- package/form/FormItem.tsx +5 -5
- package/form/easing.ts +10 -0
- package/form/scroll.ts +124 -0
- package/form/type.ts +519 -519
- package/global-config/default-config.ts +95 -0
- package/global-config/locale/ar_KW.ts +270 -0
- package/global-config/locale/en_US.ts +280 -0
- package/global-config/locale/it_IT.ts +287 -0
- package/global-config/locale/ja_JP.ts +279 -0
- package/global-config/locale/ko_KR.ts +279 -0
- package/global-config/locale/ru_RU.ts +288 -0
- package/global-config/locale/zh_CN.ts +279 -0
- package/global-config/locale/zh_TW.ts +279 -0
- package/global-config/mobile/default-config.ts +6 -0
- package/global-config/mobile/locale/ar_KW.ts +113 -0
- package/global-config/mobile/locale/en_US.ts +114 -0
- package/global-config/mobile/locale/it_IT.ts +114 -0
- package/global-config/mobile/locale/ja_JP.ts +101 -0
- package/global-config/mobile/locale/ko_KR.ts +101 -0
- package/global-config/mobile/locale/ru_RU.ts +113 -0
- package/global-config/mobile/locale/zh_CN.ts +101 -0
- package/global-config/mobile/locale/zh_TW.ts +101 -0
- package/global-config/t.ts +111 -0
- package/hooks/useControlled.ts +3 -3
- package/hooks/useDeepEffect.ts +32 -0
- package/hooks/useGlobalIcon.ts +10 -3
- package/hooks/useLastest.ts +2 -6
- package/hooks/useResizeObserve.ts +36 -0
- package/index.ts +10 -7
- package/input/Input.tsx +4 -1
- package/input/defaultProps.ts +0 -2
- package/input/type.ts +1 -6
- package/input-number/InputNumber.tsx +124 -0
- package/input-number/defaultProps.ts +17 -0
- package/input-number/index.ts +9 -0
- package/input-number/style/css.js +1 -0
- package/input-number/style/index.js +1 -0
- package/input-number/type.ts +147 -0
- package/input-number/useInputNumber.tsx +270 -0
- package/ip-input/IPInput.tsx +516 -0
- package/ip-input/defaultProps.ts +11 -0
- package/ip-input/index.ts +3 -0
- package/ip-input/style/css.js +1 -0
- package/ip-input/style/index.js +1 -0
- package/ip-input/type.ts +115 -0
- package/ip-input/utils.ts +112 -0
- package/layout/Aside.tsx +38 -0
- package/layout/Layout.tsx +104 -0
- package/layout/defaultProps.ts +9 -0
- package/layout/index.ts +9 -0
- package/layout/style/css.js +1 -0
- package/layout/style/index.js +1 -0
- package/layout/type.ts +43 -0
- package/list/List.tsx +144 -0
- package/list/ListItem.tsx +36 -0
- package/list/ListItemMeta.tsx +40 -0
- package/list/defaultProps.ts +11 -0
- package/list/hooks/useListVirtualScroll.ts +82 -0
- package/list/index.ts +11 -0
- package/list/style/css.js +1 -0
- package/list/style/index.js +1 -0
- package/list/type.ts +93 -0
- package/locale/LocalReceiver.ts +55 -0
- package/locale/ar_KW.ts +7 -0
- package/locale/en_US.ts +7 -0
- package/locale/it_IT.ts +6 -0
- package/locale/ja_JP.ts +6 -0
- package/locale/ko_KR.ts +6 -0
- package/locale/ru_RU.ts +6 -0
- package/locale/zh_CN.ts +5 -0
- package/locale/zh_TW.ts +7 -0
- package/notification/NotifyContainer.tsx +2 -2
- package/notification/NotifyContext.tsx +1 -0
- package/package.json +6 -3
- package/popup/Popup.tsx +34 -10
- package/radio/Radio.tsx +24 -0
- package/radio/RadioGroup.tsx +159 -0
- package/radio/defaultProps.ts +18 -0
- package/radio/index.ts +12 -0
- package/radio/style/css.js +0 -0
- package/radio/style/index.js +1 -0
- package/radio/type.ts +115 -0
- package/radio/useKeyboard.ts +36 -0
- package/select/hooks/useOptions.ts +10 -7
- package/select/hooks/usePanelVirtualScroll.ts +1 -1
- package/select/type.ts +382 -382
- package/select-input/type.ts +280 -280
- package/slider/Slider.tsx +270 -0
- package/slider/SliderHandleButton.tsx +50 -0
- package/slider/defaultProps.ts +15 -0
- package/slider/index.ts +9 -0
- package/slider/style/css.js +1 -0
- package/slider/style/index.js +1 -0
- package/slider/type.ts +77 -0
- package/style/all.js +26 -0
- package/styles/_global.scss +39 -39
- package/styles/_vars.scss +358 -386
- package/styles/components/alert/_index.scss +175 -175
- package/styles/components/alert/_vars.scss +39 -39
- package/styles/components/badge/_index.scss +70 -70
- package/styles/components/badge/_vars.scss +25 -25
- package/styles/components/button/_index.scss +499 -511
- package/styles/components/button/_mixins.scss +39 -39
- package/styles/components/button/_vars.scss +120 -122
- package/styles/components/checkbox/_index.scss +158 -158
- package/styles/components/checkbox/_var.scss +60 -60
- package/styles/components/color-picker/_index.scss +586 -0
- package/styles/components/color-picker/_mixins.scss +0 -0
- package/styles/components/color-picker/_vars.scss +84 -0
- package/styles/components/dialog/_animate.scss +135 -135
- package/styles/components/dialog/_index.scss +311 -311
- package/styles/components/dialog/_vars.scss +59 -59
- package/styles/components/drawer/_index.scss +205 -0
- package/styles/components/drawer/_mixins.scss +1 -0
- package/styles/components/drawer/_var.scss +53 -0
- package/styles/components/fireworks/_index.scss +86 -0
- package/styles/components/fireworks/_vars.scss +4 -0
- package/styles/components/form/_index.scss +174 -174
- package/styles/components/form/_mixins.scss +76 -76
- package/styles/components/form/_vars.scss +100 -100
- package/styles/components/input/_index.scss +349 -349
- package/styles/components/input/_mixins.scss +116 -116
- package/styles/components/input/_vars.scss +134 -134
- package/styles/components/input-number/_index.scss +353 -0
- package/styles/components/input-number/_mixins.scss +0 -0
- package/styles/components/input-number/_vars.scss +65 -0
- package/styles/components/ip-input/_index.scss +280 -0
- package/styles/components/layout/_index.scss +47 -0
- package/styles/components/layout/_mixin.scss +0 -0
- package/styles/components/layout/_vars.scss +18 -0
- package/styles/components/layout/doc.scss +74 -0
- package/styles/components/list/_index.scss +172 -0
- package/styles/components/list/_mixins.scss +0 -0
- package/styles/components/list/_vars.scss +41 -0
- package/styles/components/loading/_index.scss +112 -112
- package/styles/components/loading/_vars.scss +39 -39
- package/styles/components/notification/_index.scss +160 -160
- package/styles/components/notification/_mixins.scss +12 -12
- package/styles/components/notification/_vars.scss +59 -59
- package/styles/components/popup/_index.scss +82 -82
- package/styles/components/popup/_mixin.scss +149 -149
- package/styles/components/popup/_var.scss +31 -31
- package/styles/components/radio/_index.scss +376 -0
- package/styles/components/radio/_mixins.scss +0 -0
- package/styles/components/radio/_var.scss +92 -0
- package/styles/components/select/_index.scss +290 -290
- package/styles/components/select/_var.scss +65 -65
- package/styles/components/select-input/_index.scss +5 -5
- package/styles/components/select-input/_var.scss +3 -3
- package/styles/components/slider/_index.scss +241 -0
- package/styles/components/slider/_mixins.scss +0 -0
- package/styles/components/slider/_vars.scss +50 -0
- package/styles/components/switch/_index.scss +279 -279
- package/styles/components/switch/_vars.scss +61 -61
- package/styles/components/table/_index.scss +193 -0
- package/styles/components/table/_var.scss +52 -0
- package/styles/components/tabs/_index.scss +165 -0
- package/styles/components/tabs/_mixins.scss +11 -0
- package/styles/components/tabs/_vars.scss +71 -0
- package/styles/components/tag/_index.scss +316 -316
- package/styles/components/tag/_var.scss +85 -85
- package/styles/components/tag-input/_index.scss +163 -163
- package/styles/components/tag-input/_vars.scss +16 -16
- package/styles/globals.css +250 -250
- package/styles/mixins/_focus.scss +7 -7
- package/styles/mixins/_layout.scss +32 -32
- package/styles/mixins/_reset.scss +10 -10
- package/styles/mixins/_scrollbar.scss +31 -31
- package/styles/mixins/_text.scss +48 -48
- package/styles/rillple.css +16 -16
- package/styles/scrollbar.css +41 -41
- package/styles/themes/_dark.scss +191 -191
- package/styles/themes/_font.scss +69 -79
- package/styles/themes/_index.scss +5 -5
- package/styles/themes/_light.scss +190 -190
- package/styles/themes/_radius.scss +9 -9
- package/styles/themes/_size.scss +68 -68
- package/styles/themes.css +66 -66
- package/styles/utilities/_animation.scss +57 -57
- package/styles/utilities/_tips.scss +9 -9
- package/tab/TabBar.tsx +85 -0
- package/tab/TabNav.tsx +103 -0
- package/tab/TabNavItem.tsx +80 -0
- package/tab/TabPanel.tsx +42 -0
- package/tab/Tabs.tsx +71 -0
- package/tab/defaultProps.ts +19 -0
- package/tab/index.ts +7 -0
- package/tab/style/index.js +1 -0
- package/tab/type.ts +125 -0
- package/tab/useTabClass.ts +20 -0
- package/table/Cell.tsx +109 -0
- package/table/TBody.tsx +77 -0
- package/table/THead.tsx +63 -0
- package/table/TR.tsx +78 -0
- package/table/Table.tsx +73 -0
- package/table/defaultProps.ts +14 -0
- package/table/hooks/index.ts +4 -0
- package/table/hooks/useTableClassName.ts +63 -0
- package/table/hooks/useTableStyle.ts +93 -0
- package/table/index.ts +7 -0
- package/table/style/css.js +1 -0
- package/table/style/index.js +1 -0
- package/table/type.ts +192 -0
- package/tag/Tag.tsx +1 -1
- package/tag-input/hooks/useTagList.tsx +1 -1
- package/utils/dom.ts +4 -0
- package/utils/forwardRefWithStatics.ts +1 -4
- package/utils/input-number/large-number.ts +423 -0
- package/utils/input-number/number.ts +257 -0
- package/utils/isFragment.ts +6 -6
- package/utils/log/index.ts +3 -0
- package/utils/log/log.ts +30 -0
- package/utils/log/types.ts +12 -0
- package/utils/number.ts +21 -0
- package/utils/scroll.ts +26 -0
- package/utils/style.ts +2 -4
package/list/type.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
|
|
5
|
+
* */
|
|
6
|
+
|
|
7
|
+
import { TNode, TScroll, ScrollToElementParams } from "../common";
|
|
8
|
+
import { MouseEvent, WheelEvent } from "react";
|
|
9
|
+
|
|
10
|
+
export interface TdListProps {
|
|
11
|
+
/**
|
|
12
|
+
* 自定义加载中。值为空不显示加载中,值为 'loading' 显示加载中状态,值为 'load-more' 显示加载更多状态。值类型为函数,则表示自定义加载状态呈现内容
|
|
13
|
+
*/
|
|
14
|
+
asyncLoading?: TNode;
|
|
15
|
+
/**
|
|
16
|
+
* 底部
|
|
17
|
+
*/
|
|
18
|
+
footer?: TNode;
|
|
19
|
+
/**
|
|
20
|
+
* 头部
|
|
21
|
+
*/
|
|
22
|
+
header?: TNode;
|
|
23
|
+
/**
|
|
24
|
+
* 排列方式(待设计稿输出)
|
|
25
|
+
* @default horizontal
|
|
26
|
+
*/
|
|
27
|
+
layout?: "horizontal" | "vertical";
|
|
28
|
+
/**
|
|
29
|
+
* 懒加载和虚拟滚动。为保证组件收益最大化,当数据量小于阈值 `scroll.threshold` 时,无论虚拟滚动的配置是否存在,组件内部都不会开启虚拟滚动,`scroll.threshold` 默认为 `100`
|
|
30
|
+
*/
|
|
31
|
+
scroll?: TScroll;
|
|
32
|
+
/**
|
|
33
|
+
* 尺寸
|
|
34
|
+
* @default medium
|
|
35
|
+
*/
|
|
36
|
+
size?: "small" | "medium" | "large";
|
|
37
|
+
/**
|
|
38
|
+
* 是否展示分割线
|
|
39
|
+
* @default false
|
|
40
|
+
*/
|
|
41
|
+
split?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* 是否展示斑马纹
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
stripe?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 点击加载更多时触发
|
|
49
|
+
*/
|
|
50
|
+
onLoadMore?: (options: { e: MouseEvent<HTMLDivElement> }) => void;
|
|
51
|
+
/**
|
|
52
|
+
* 列表滚动时触发,scrollTop 表示顶部滚动距离,scrollBottom 表示底部滚动距离
|
|
53
|
+
*/
|
|
54
|
+
onScroll?: (options: { e: Event | WheelEvent<HTMLDivElement>; scrollTop: number; scrollBottom: number }) => void;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** 组件实例方法 */
|
|
58
|
+
export interface ListInstanceFunctions {
|
|
59
|
+
/**
|
|
60
|
+
* 虚拟滚动场景下,支持指定滚动到具体的节点
|
|
61
|
+
*/
|
|
62
|
+
scrollTo?: (scrollToParams: ScrollToElementParams) => void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface TdListItemProps {
|
|
66
|
+
/**
|
|
67
|
+
* 操作栏
|
|
68
|
+
*/
|
|
69
|
+
action?: TNode;
|
|
70
|
+
/**
|
|
71
|
+
* 内容,同 content
|
|
72
|
+
*/
|
|
73
|
+
children?: TNode;
|
|
74
|
+
/**
|
|
75
|
+
* 内容
|
|
76
|
+
*/
|
|
77
|
+
content?: TNode;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface TdListItemMetaProps {
|
|
81
|
+
/**
|
|
82
|
+
* 列表项内容
|
|
83
|
+
*/
|
|
84
|
+
description?: TNode;
|
|
85
|
+
/**
|
|
86
|
+
* 列表项图片
|
|
87
|
+
*/
|
|
88
|
+
image?: TNode;
|
|
89
|
+
/**
|
|
90
|
+
* 列表项标题
|
|
91
|
+
*/
|
|
92
|
+
title?: TNode;
|
|
93
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { t as commonT } from "../global-config/t";
|
|
3
|
+
import { ConfigContext, Locale } from "../config-provider";
|
|
4
|
+
|
|
5
|
+
export interface Placement {
|
|
6
|
+
[propName: string]: string | number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type TransformPattern = string | Function | Array<string>;
|
|
10
|
+
|
|
11
|
+
export function useLocaleReceiver<T extends keyof Locale>(componentName: T, defaultLocale?: Locale[T] | Function) {
|
|
12
|
+
const { globalConfig } = React.useContext(ConfigContext);
|
|
13
|
+
|
|
14
|
+
function transformLocale(pattern: TransformPattern, placement?: Placement): string;
|
|
15
|
+
function transformLocale(pattern: TransformPattern, placement?: number, data?: Placement): string;
|
|
16
|
+
function transformLocale(pattern: TransformPattern, ...args: any[]): string | Array<string> {
|
|
17
|
+
const REGEXP = /\{\s*([\w-]+)\s*\}/g;
|
|
18
|
+
const placement = args[0];
|
|
19
|
+
|
|
20
|
+
if (Array.isArray(pattern)) {
|
|
21
|
+
return pattern.map((p, index) => {
|
|
22
|
+
const translated = p.replace(REGEXP, (_: string, key: string) => {
|
|
23
|
+
if (placement) return String(placement[index][key]);
|
|
24
|
+
return "";
|
|
25
|
+
});
|
|
26
|
+
return translated;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
if (typeof pattern === "function") {
|
|
30
|
+
return pattern(placement);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// use commonT for plural
|
|
34
|
+
const data = args[1];
|
|
35
|
+
if (data) {
|
|
36
|
+
return commonT(pattern, placement, data);
|
|
37
|
+
}
|
|
38
|
+
return commonT(pattern, placement);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** @TypeA => 确保此参数是属于 globalConfig[componentName] 下的子属性 */
|
|
42
|
+
const componentLocale = React.useMemo<Locale[T] | Function>(() => {
|
|
43
|
+
const locale = defaultLocale || {};
|
|
44
|
+
const connectLocaleByName = globalConfig[componentName];
|
|
45
|
+
|
|
46
|
+
const localeFromContext = componentName && globalConfig ? connectLocaleByName : {};
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
...(typeof locale === "function" ? (locale as Function)() : locale),
|
|
50
|
+
...(localeFromContext || {})
|
|
51
|
+
};
|
|
52
|
+
}, [componentName, defaultLocale, globalConfig]);
|
|
53
|
+
|
|
54
|
+
return [componentLocale, transformLocale] as [Locale[T], Function];
|
|
55
|
+
}
|
package/locale/ar_KW.ts
ADDED
package/locale/en_US.ts
ADDED
package/locale/it_IT.ts
ADDED
package/locale/ja_JP.ts
ADDED
package/locale/ko_KR.ts
ADDED
package/locale/ru_RU.ts
ADDED
package/locale/zh_CN.ts
ADDED
package/locale/zh_TW.ts
ADDED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useState } from "react";
|
|
2
|
-
import { TdNotificationProps } from "./type";
|
|
2
|
+
import { TdNotificationProps, HeightItem } from "./type";
|
|
3
3
|
import NotificationItem from "./NotifyItem";
|
|
4
4
|
import useConfig from "../hooks/useConfig";
|
|
5
5
|
export const GAP = 14;
|
|
@@ -32,7 +32,7 @@ const NotificationContainer = ({
|
|
|
32
32
|
onHoverEnd();
|
|
33
33
|
}, [onHoverEnd]);
|
|
34
34
|
|
|
35
|
-
const [heights, setHeights] = useState<
|
|
35
|
+
const [heights, setHeights] = useState<HeightItem[]>([]);
|
|
36
36
|
|
|
37
37
|
const { classPrefix: prefix } = useConfig();
|
|
38
38
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { createContext, useState, useRef, useCallback, useContext } from "react";
|
|
2
2
|
import { createPortal } from "react-dom";
|
|
3
3
|
import NotifyContainer from "./NotifyContainer";
|
|
4
|
+
import { TdNotificationProps } from "./type";
|
|
4
5
|
|
|
5
6
|
// 1. 定义类型
|
|
6
7
|
type NotificationType = "success" | "error" | "warning" | "info";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tendaui/components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "TendaUI React Components - Source code",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"module": "index.ts",
|
|
@@ -46,7 +46,10 @@
|
|
|
46
46
|
],
|
|
47
47
|
"sideEffects": [
|
|
48
48
|
"**/*.scss",
|
|
49
|
-
"**/*.css"
|
|
49
|
+
"**/*.css",
|
|
50
|
+
"**/style/index.js",
|
|
51
|
+
"**/style/css.js",
|
|
52
|
+
"**/style/all.js"
|
|
50
53
|
],
|
|
51
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "77c5b16410848a6dfee573581b602633306540cb"
|
|
52
55
|
}
|
package/popup/Popup.tsx
CHANGED
|
@@ -8,7 +8,7 @@ import useDefaultProps from "../hooks/useDefaultProps";
|
|
|
8
8
|
import useMutationObserver from "../hooks/useMutationObserver";
|
|
9
9
|
import useWindowSize from "../hooks/useWindowSize";
|
|
10
10
|
import useTrigger from "./hooks/useTrigger";
|
|
11
|
-
import type { TdPopupProps } from "./type";
|
|
11
|
+
import type { TdPopupProps, PopupVisibleChangeContext } from "./type";
|
|
12
12
|
import usePopper from "../hooks/usePopper";
|
|
13
13
|
import { popupDefaultProps } from "./defaultProps";
|
|
14
14
|
import classNames from "classnames";
|
|
@@ -62,7 +62,28 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
|
|
|
62
62
|
|
|
63
63
|
// 全局配置
|
|
64
64
|
const { height: windowHeight, width: windowWidth } = useWindowSize();
|
|
65
|
-
const
|
|
65
|
+
const handleVisibleChange = (visible: boolean, context: PopupVisibleChangeContext) => {
|
|
66
|
+
props.onVisibleChange?.(visible, context);
|
|
67
|
+
};
|
|
68
|
+
const [visible, onVisibleChangeInternal] = useControlled(props, "visible", handleVisibleChange);
|
|
69
|
+
// 适配 useTrigger 的类型
|
|
70
|
+
const onVisibleChangeForTrigger = (
|
|
71
|
+
visible: boolean,
|
|
72
|
+
context: {
|
|
73
|
+
e?:
|
|
74
|
+
| React.MouseEvent<HTMLElement>
|
|
75
|
+
| React.TouchEvent<HTMLElement>
|
|
76
|
+
| React.FocusEvent<HTMLElement>
|
|
77
|
+
| React.KeyboardEvent<HTMLElement>;
|
|
78
|
+
trigger: string;
|
|
79
|
+
}
|
|
80
|
+
) => {
|
|
81
|
+
const popupContext: PopupVisibleChangeContext = {
|
|
82
|
+
e: context.e as any,
|
|
83
|
+
trigger: context.trigger as any
|
|
84
|
+
};
|
|
85
|
+
onVisibleChangeInternal(visible, popupContext);
|
|
86
|
+
};
|
|
66
87
|
// 记录 popup 元素
|
|
67
88
|
// 如果内容为 null 或 undefined,且 hideEmptyPopup 为 true,则不展示 popup
|
|
68
89
|
const [popupElement, setPopupElement] = useState(null);
|
|
@@ -101,7 +122,7 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
|
|
|
101
122
|
trigger,
|
|
102
123
|
visible,
|
|
103
124
|
delay,
|
|
104
|
-
onVisibleChange
|
|
125
|
+
onVisibleChange: onVisibleChangeForTrigger
|
|
105
126
|
});
|
|
106
127
|
// 传入popperjs 配置选项
|
|
107
128
|
const popperOptions = props.popperOptions as Options;
|
|
@@ -110,7 +131,7 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
|
|
|
110
131
|
void _ignored;
|
|
111
132
|
|
|
112
133
|
// popperRef 表示 popper 实例
|
|
113
|
-
popperRef.current = usePopper(getRefDom(triggerRef), popupElement, {
|
|
134
|
+
popperRef.current = usePopper(getRefDom(triggerRef) as HTMLElement | null, popupElement, {
|
|
114
135
|
placement: popperPlacement as Placement,
|
|
115
136
|
...restPopperOptions
|
|
116
137
|
});
|
|
@@ -125,8 +146,9 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
|
|
|
125
146
|
|
|
126
147
|
const updateTimeRef = useRef(null);
|
|
127
148
|
// 监听 trigger 节点或内容变化动态更新 popup 定位
|
|
128
|
-
useMutationObserver(getRefDom(triggerRef), () => {
|
|
129
|
-
const
|
|
149
|
+
useMutationObserver(getRefDom(triggerRef) as HTMLElement | null, () => {
|
|
150
|
+
const triggerDom = getRefDom(triggerRef) as HTMLElement | null;
|
|
151
|
+
const isDisplayNone = triggerDom ? getCssVarsValue("display", triggerDom) === "none" : true;
|
|
130
152
|
if (visible && !isDisplayNone) {
|
|
131
153
|
clearTimeout(updateTimeRef.current);
|
|
132
154
|
updateTimeRef.current = setTimeout(() => popperRef.current?.update?.(), 0);
|
|
@@ -177,8 +199,9 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
|
|
|
177
199
|
|
|
178
200
|
// 整理浮层样式
|
|
179
201
|
function getOverlayStyle(overlayStyle: TdPopupProps["overlayStyle"]) {
|
|
180
|
-
|
|
181
|
-
|
|
202
|
+
const triggerDom = getRefDom(triggerRef) as HTMLElement | null;
|
|
203
|
+
if (triggerDom && popupRef.current && typeof overlayStyle === "function") {
|
|
204
|
+
return { ...overlayStyle(triggerDom, popupRef.current) };
|
|
182
205
|
}
|
|
183
206
|
return { ...overlayStyle };
|
|
184
207
|
}
|
|
@@ -194,7 +217,7 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
|
|
|
194
217
|
onExited={handleExited}
|
|
195
218
|
classNames={`${classPrefix}-portal`}
|
|
196
219
|
>
|
|
197
|
-
<Portal triggerNode={getRefDom(triggerRef)} attach="body" ref={portalRef}>
|
|
220
|
+
<Portal triggerNode={getRefDom(triggerRef) as HTMLElement | null} attach="body" ref={portalRef}>
|
|
198
221
|
<CSSTransition appear timeout={0} in={visible} nodeRef={popupRef} classNames={`${classPrefix}-popup`}>
|
|
199
222
|
<div
|
|
200
223
|
ref={(node) => {
|
|
@@ -247,7 +270,8 @@ const Popup = forwardRef<PopupRef, PopupProps>((originalProps, ref) => {
|
|
|
247
270
|
getPopupElement: () => popupRef.current,
|
|
248
271
|
getPortalElement: () => portalRef.current,
|
|
249
272
|
getPopupContentElement: () => contentRef.current,
|
|
250
|
-
setVisible: (visible: boolean) =>
|
|
273
|
+
setVisible: (visible: boolean) =>
|
|
274
|
+
onVisibleChangeInternal(visible, { trigger: "document" } as PopupVisibleChangeContext)
|
|
251
275
|
}));
|
|
252
276
|
// 这里使用 React.Fragment 包裹 triggerNode 和 overlay,确保返回一个单一的父节点
|
|
253
277
|
// 这样可以避免在渲染时出现多个根节点的错误
|
package/radio/Radio.tsx
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React, { Ref, forwardRef } from "react";
|
|
2
|
+
import forwardRefWithStatics from "../utils/forwardRefWithStatics";
|
|
3
|
+
import Check, { CheckProps } from "../common/Check";
|
|
4
|
+
import RadioGroup from "./RadioGroup";
|
|
5
|
+
import { radioDefaultProps } from "./defaultProps";
|
|
6
|
+
import useDefaultProps from "../hooks/useDefaultProps";
|
|
7
|
+
|
|
8
|
+
export type RadioProps = Omit<CheckProps, "type">;
|
|
9
|
+
const RadioButton = forwardRef<HTMLLabelElement, RadioProps>((props, ref) => (
|
|
10
|
+
<Check ref={ref} type="radio-button" {...useDefaultProps<RadioProps>(props, radioDefaultProps)} />
|
|
11
|
+
));
|
|
12
|
+
RadioButton.displayName = "RadioButton";
|
|
13
|
+
const Radio = forwardRefWithStatics(
|
|
14
|
+
(props: RadioProps, ref: Ref<HTMLLabelElement>) => (
|
|
15
|
+
<Check ref={ref} type="radio" {...useDefaultProps<RadioProps>(props, radioDefaultProps)} />
|
|
16
|
+
),
|
|
17
|
+
{
|
|
18
|
+
Group: RadioGroup,
|
|
19
|
+
Button: RadioButton
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
Radio.displayName = "Radio";
|
|
23
|
+
|
|
24
|
+
export default Radio;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import React, { CSSProperties, ReactNode, useEffect, useRef, useState } from "react";
|
|
2
|
+
import classNames from "classnames";
|
|
3
|
+
import observe from "../common/observe";
|
|
4
|
+
import { CheckContext, type CheckContextValue } from "../common/Check";
|
|
5
|
+
import useCommonClassName from "../hooks/useCommonClassName";
|
|
6
|
+
|
|
7
|
+
import useConfig from "../hooks/useConfig";
|
|
8
|
+
import useControlled from "../hooks/useControlled";
|
|
9
|
+
import useDefaultProps from "../hooks/useDefaultProps";
|
|
10
|
+
import useMutationObserver from "../hooks/useMutationObserver";
|
|
11
|
+
|
|
12
|
+
import Radio from "./Radio";
|
|
13
|
+
import { radioGroupDefaultProps } from "./defaultProps";
|
|
14
|
+
import useKeyboard from "./useKeyboard";
|
|
15
|
+
|
|
16
|
+
import type { StyledProps } from "../common";
|
|
17
|
+
import type { TdRadioGroupProps } from "./type";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* RadioGroup 组件所接收的属性
|
|
21
|
+
*/
|
|
22
|
+
export interface RadioGroupProps extends TdRadioGroupProps, StyledProps {
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 单选选项组,里面可以嵌套 <Radio />
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
const RadioGroup: React.FC<RadioGroupProps> = (originalProps) => {
|
|
31
|
+
const { classPrefix } = useConfig();
|
|
32
|
+
const props = useDefaultProps<RadioGroupProps>(originalProps, radioGroupDefaultProps);
|
|
33
|
+
const { disabled, readonly, children, onChange, size, variant, options = [], className, style, theme } = props;
|
|
34
|
+
const [internalValue, setInternalValue] = useControlled(props, "value", onChange);
|
|
35
|
+
const [barStyle, setBarStyle] = useState<Partial<CSSProperties> | null>(null);
|
|
36
|
+
|
|
37
|
+
const radioGroupRef = useRef<HTMLDivElement>(null);
|
|
38
|
+
const observerRef = useRef<IntersectionObserver>(null);
|
|
39
|
+
const handleKeyboardChange = (value: any, context: { e: KeyboardEvent }) => {
|
|
40
|
+
setInternalValue(value, { e: context.e as any, name: props.name });
|
|
41
|
+
};
|
|
42
|
+
useKeyboard(radioGroupRef, handleKeyboardChange);
|
|
43
|
+
|
|
44
|
+
const checkedRadioCls = `.${classPrefix}-radio-button.${classPrefix}-is-checked`;
|
|
45
|
+
const { SIZE: sizeMap } = useCommonClassName();
|
|
46
|
+
|
|
47
|
+
const context: CheckContextValue = {
|
|
48
|
+
inject: (checkProps) => {
|
|
49
|
+
if (typeof checkProps.checked !== "undefined") {
|
|
50
|
+
return checkProps;
|
|
51
|
+
}
|
|
52
|
+
const { value: checkValue } = checkProps;
|
|
53
|
+
return {
|
|
54
|
+
...checkProps,
|
|
55
|
+
name: props.name,
|
|
56
|
+
// 有一个允许取消,就可以取消选中
|
|
57
|
+
allowUncheck: checkProps.allowUncheck || props.allowUncheck,
|
|
58
|
+
checked: internalValue === checkProps.value,
|
|
59
|
+
disabled: checkProps.disabled || disabled,
|
|
60
|
+
readonly: checkProps.readonly || readonly,
|
|
61
|
+
onChange(checked, { e }) {
|
|
62
|
+
if (typeof checkProps.onChange === "function") {
|
|
63
|
+
checkProps.onChange(checked, { e });
|
|
64
|
+
}
|
|
65
|
+
setInternalValue(checked ? checkValue : undefined, { e, name: props.name });
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const calcBarStyle = () => {
|
|
72
|
+
if (!variant.includes("filled")) return;
|
|
73
|
+
const checkedRadio = radioGroupRef.current.querySelector?.(checkedRadioCls) as HTMLElement;
|
|
74
|
+
if (!checkedRadio) {
|
|
75
|
+
setBarStyle(null);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const { offsetWidth, offsetHeight, offsetLeft, offsetTop } = checkedRadio;
|
|
79
|
+
setBarStyle({
|
|
80
|
+
width: `${offsetWidth}px`,
|
|
81
|
+
height: `${offsetHeight}px`,
|
|
82
|
+
left: `${offsetLeft}px`,
|
|
83
|
+
top: `${offsetTop}px`
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// 针对子元素更新的场景,包括 value 变化等
|
|
88
|
+
useMutationObserver(radioGroupRef.current, (mutations) => {
|
|
89
|
+
// 排除高亮元素自身的变化,避免重复触发
|
|
90
|
+
const filteredMutations = mutations.filter((mutation) => {
|
|
91
|
+
const target = mutation.target as HTMLElement;
|
|
92
|
+
return !target.classList?.contains(`${classPrefix}-radio-group__bg-block`);
|
|
93
|
+
});
|
|
94
|
+
if (filteredMutations.length > 0) {
|
|
95
|
+
calcBarStyle();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
calcBarStyle();
|
|
101
|
+
if (!radioGroupRef.current) return;
|
|
102
|
+
// 针对父元素初始化时隐藏导致无法正确计算尺寸的问题
|
|
103
|
+
const observer = observe(radioGroupRef.current, null, calcBarStyle, 0);
|
|
104
|
+
observerRef.current = observer;
|
|
105
|
+
return () => {
|
|
106
|
+
observerRef.current?.disconnect();
|
|
107
|
+
observerRef.current = null;
|
|
108
|
+
};
|
|
109
|
+
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
110
|
+
|
|
111
|
+
const renderBlock = () => {
|
|
112
|
+
if (!variant.includes("filled") || !barStyle) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
return <div style={barStyle} className={`${classPrefix}-radio-group__bg-block`}></div>;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const renderOptions = () => {
|
|
119
|
+
const Comp = theme === "button" ? Radio.Button : Radio;
|
|
120
|
+
return options.map((item, index) => {
|
|
121
|
+
let label: ReactNode;
|
|
122
|
+
let value: string | number | boolean;
|
|
123
|
+
let disabled: boolean | undefined;
|
|
124
|
+
if (typeof item === "string" || typeof item === "number") {
|
|
125
|
+
label = item;
|
|
126
|
+
value = item;
|
|
127
|
+
} else {
|
|
128
|
+
label = item.label;
|
|
129
|
+
value = item.value;
|
|
130
|
+
disabled = item.disabled;
|
|
131
|
+
}
|
|
132
|
+
return (
|
|
133
|
+
<Comp value={value} key={index} disabled={disabled}>
|
|
134
|
+
{label}
|
|
135
|
+
</Comp>
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
return (
|
|
140
|
+
<CheckContext.Provider value={context}>
|
|
141
|
+
<div
|
|
142
|
+
ref={radioGroupRef}
|
|
143
|
+
style={style}
|
|
144
|
+
className={classNames(`${classPrefix}-radio-group`, sizeMap[size], className, {
|
|
145
|
+
[`${classPrefix}-radio-group__outline`]: variant === "outline",
|
|
146
|
+
[`${classPrefix}-radio-group--filled`]: variant.includes("filled"),
|
|
147
|
+
[`${classPrefix}-radio-group--primary-filled`]: variant === "primary-filled"
|
|
148
|
+
})}
|
|
149
|
+
>
|
|
150
|
+
{children || renderOptions()}
|
|
151
|
+
{renderBlock()}
|
|
152
|
+
</div>
|
|
153
|
+
</CheckContext.Provider>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
RadioGroup.displayName = "RadioGroup";
|
|
158
|
+
|
|
159
|
+
export default RadioGroup;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { TdRadioProps, TdRadioGroupProps } from "./type";
|
|
2
|
+
|
|
3
|
+
export const radioDefaultProps: TdRadioProps = {
|
|
4
|
+
allowUncheck: false,
|
|
5
|
+
defaultChecked: false,
|
|
6
|
+
disabled: undefined,
|
|
7
|
+
readonly: undefined,
|
|
8
|
+
value: undefined
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export const radioGroupDefaultProps: TdRadioGroupProps = {
|
|
12
|
+
allowUncheck: false,
|
|
13
|
+
disabled: undefined,
|
|
14
|
+
readonly: undefined,
|
|
15
|
+
size: "medium",
|
|
16
|
+
variant: "outline",
|
|
17
|
+
theme: "radio"
|
|
18
|
+
};
|
package/radio/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import _Radio from "./Radio";
|
|
2
|
+
|
|
3
|
+
import "./style/index.js";
|
|
4
|
+
|
|
5
|
+
export type { RadioProps } from "./Radio";
|
|
6
|
+
export type { RadioGroupProps } from "./RadioGroup";
|
|
7
|
+
export * from "./type";
|
|
8
|
+
|
|
9
|
+
export const Radio = _Radio;
|
|
10
|
+
export const RadioGroup = _Radio.Group;
|
|
11
|
+
|
|
12
|
+
export default Radio;
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "../../styles/components/radio/_index.scss";
|