@rainbow-oh/yee-c 0.9.2 → 0.11.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/dist/cjs/Button/demo/icon.js +1 -1
- package/dist/cjs/Input/style/index.less +1 -0
- package/dist/cjs/Table/demo/resizable.d.ts +3 -0
- package/dist/cjs/Table/demo/resizable.js +143 -0
- package/dist/cjs/Table/hooks/useColumnResize.d.ts +30 -0
- package/dist/cjs/Table/hooks/useColumnResize.js +217 -0
- package/dist/cjs/Table/hooks/useColumns.d.ts +3 -1
- package/dist/cjs/Table/hooks/useColumns.js +14 -3
- package/dist/cjs/Table/interface.d.ts +49 -0
- package/dist/cjs/Table/style/index.less +42 -0
- package/dist/cjs/Table/table.js +62 -9
- package/dist/cjs/Table/theader/cell.js +46 -4
- package/dist/cjs/Table/util/index.d.ts +19 -1
- package/dist/cjs/Table/util/index.js +22 -0
- package/dist/cjs/Tabs/demo/overflow-center.d.ts +3 -0
- package/dist/cjs/Tabs/demo/overflow-center.js +54 -0
- package/dist/cjs/Tabs/hooks/useNavListMove.d.ts +2 -1
- package/dist/cjs/Tabs/hooks/useNavListMove.js +51 -16
- package/dist/cjs/Tabs/hooks/useTabScroll.d.ts +1 -0
- package/dist/cjs/Tabs/hooks/useTabScroll.js +5 -1
- package/dist/cjs/Tabs/interface.d.ts +10 -1
- package/dist/cjs/Tabs/style/index.less +5 -0
- package/dist/cjs/Tabs/tab-header/index.d.ts +1 -0
- package/dist/cjs/Tabs/tab-header/index.js +11 -3
- package/dist/cjs/Tabs/tabs.js +4 -1
- package/dist/cjs/Upload/demo/auto-upload.d.ts +3 -0
- package/dist/cjs/Upload/demo/auto-upload.js +65 -0
- package/dist/cjs/Upload/demo/basic.js +5 -10
- package/dist/cjs/Upload/demo/controlled.js +4 -4
- package/dist/cjs/Upload/demo/pictureWall.js +14 -13
- package/dist/cjs/Upload/dragger.d.ts +2 -1
- package/dist/cjs/Upload/dragger.js +32 -21
- package/dist/cjs/Upload/index.d.ts +1 -1
- package/dist/cjs/Upload/interface.d.ts +67 -120
- package/dist/cjs/Upload/style/index.less +40 -13
- package/dist/cjs/Upload/upload.d.ts +2 -2
- package/dist/cjs/Upload/upload.js +435 -185
- package/dist/cjs/Upload/uploaded-list/index.d.ts +2 -1
- package/dist/cjs/Upload/uploaded-list/index.js +6 -3
- package/dist/cjs/Upload/uploaded-list/uploaded-item.d.ts +6 -3
- package/dist/cjs/Upload/uploaded-list/uploaded-item.js +127 -138
- package/dist/cjs/locale/interface.d.ts +1 -0
- package/dist/cjs/locale/lang/en_US.js +2 -1
- package/dist/cjs/locale/lang/ja_JP.js +2 -1
- package/dist/cjs/locale/lang/zh_CN.js +2 -1
- package/dist/cjs/locale/lang/zh_TW.js +2 -1
- package/dist/cjs/style/size.css +2 -1
- package/dist/cjs/style/themes.css +1 -1
- package/dist/cjs/style/variables.css +3 -2
- package/dist/cjs/utils/ax/core.d.ts +3 -1
- package/dist/cjs/utils/ax/core.js +24 -37
- package/dist/cjs/utils/ax/index.d.ts +3 -1
- package/dist/cjs/utils/folder-scanner.d.ts +1 -1
- package/dist/cjs/utils/folder-scanner.js +43 -34
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/Button/demo/icon.js +7 -4
- package/dist/esm/Input/style/index.less +1 -0
- package/dist/esm/Table/demo/resizable.d.ts +3 -0
- package/dist/esm/Table/demo/resizable.js +110 -0
- package/dist/esm/Table/hooks/useColumnResize.d.ts +30 -0
- package/dist/esm/Table/hooks/useColumnResize.js +206 -0
- package/dist/esm/Table/hooks/useColumns.d.ts +3 -1
- package/dist/esm/Table/hooks/useColumns.js +9 -4
- package/dist/esm/Table/interface.d.ts +49 -0
- package/dist/esm/Table/style/index.less +42 -0
- package/dist/esm/Table/table.js +83 -13
- package/dist/esm/Table/theader/cell.js +38 -3
- package/dist/esm/Table/util/index.d.ts +19 -1
- package/dist/esm/Table/util/index.js +37 -0
- package/dist/esm/Tabs/demo/overflow-center.d.ts +3 -0
- package/dist/esm/Tabs/demo/overflow-center.js +61 -0
- package/dist/esm/Tabs/hooks/useNavListMove.d.ts +2 -1
- package/dist/esm/Tabs/hooks/useNavListMove.js +62 -25
- package/dist/esm/Tabs/hooks/useTabScroll.d.ts +1 -0
- package/dist/esm/Tabs/hooks/useTabScroll.js +9 -0
- package/dist/esm/Tabs/interface.d.ts +10 -1
- package/dist/esm/Tabs/style/index.less +5 -0
- package/dist/esm/Tabs/tab-header/index.d.ts +1 -0
- package/dist/esm/Tabs/tab-header/index.js +15 -3
- package/dist/esm/Tabs/tabs.js +4 -2
- package/dist/esm/Upload/demo/auto-upload.d.ts +3 -0
- package/dist/esm/Upload/demo/auto-upload.js +42 -0
- package/dist/esm/Upload/demo/basic.js +5 -11
- package/dist/esm/Upload/demo/controlled.js +8 -6
- package/dist/esm/Upload/demo/pictureWall.js +17 -14
- package/dist/esm/Upload/dragger.d.ts +2 -1
- package/dist/esm/Upload/dragger.js +10 -5
- package/dist/esm/Upload/index.d.ts +1 -1
- package/dist/esm/Upload/interface.d.ts +67 -120
- package/dist/esm/Upload/style/index.less +40 -13
- package/dist/esm/Upload/upload.d.ts +2 -2
- package/dist/esm/Upload/upload.js +573 -271
- package/dist/esm/Upload/uploaded-list/index.d.ts +2 -1
- package/dist/esm/Upload/uploaded-list/index.js +9 -4
- package/dist/esm/Upload/uploaded-list/uploaded-item.d.ts +6 -3
- package/dist/esm/Upload/uploaded-list/uploaded-item.js +145 -150
- package/dist/esm/locale/interface.d.ts +1 -0
- package/dist/esm/locale/lang/en_US.js +2 -1
- package/dist/esm/locale/lang/ja_JP.js +2 -1
- package/dist/esm/locale/lang/zh_CN.js +2 -1
- package/dist/esm/locale/lang/zh_TW.js +2 -1
- package/dist/esm/style/size.css +2 -1
- package/dist/esm/style/themes.css +1 -1
- package/dist/esm/style/variables.css +3 -2
- package/dist/esm/utils/ax/core.d.ts +3 -1
- package/dist/esm/utils/ax/core.js +32 -40
- package/dist/esm/utils/ax/index.d.ts +3 -1
- package/dist/esm/utils/folder-scanner.d.ts +1 -1
- package/dist/esm/utils/folder-scanner.js +76 -75
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/umd/yee-c.min.css +2 -2
- package/dist/umd/yee-c.min.js +1 -1
- package/package.json +1 -1
- package/src/Button/demo/icon.tsx +5 -3
- package/src/Input/style/index.less +1 -0
- package/src/Table/demo/resizable.tsx +106 -0
- package/src/Table/hooks/useColumnResize.ts +224 -0
- package/src/Table/hooks/useColumns.ts +18 -3
- package/src/Table/index.en-US.md +7 -0
- package/src/Table/index.zh-CN.md +7 -0
- package/src/Table/interface.ts +52 -0
- package/src/Table/style/index.less +42 -0
- package/src/Table/table-resize.test.tsx +234 -0
- package/src/Table/table.tsx +90 -13
- package/src/Table/theader/cell.tsx +52 -2
- package/src/Table/util/index.ts +44 -1
- package/src/Tabs/demo/overflow-center.tsx +35 -0
- package/src/Tabs/hooks/useNavListMove.ts +60 -18
- package/src/Tabs/hooks/useTabScroll.ts +7 -1
- package/src/Tabs/index.en-US.md +33 -31
- package/src/Tabs/index.zh-CN.md +33 -31
- package/src/Tabs/interface.ts +10 -1
- package/src/Tabs/style/index.less +5 -0
- package/src/Tabs/tab-header/index.tsx +14 -3
- package/src/Tabs/tabs.tsx +2 -0
- package/src/Upload/demo/auto-upload.tsx +35 -0
- package/src/Upload/demo/basic.tsx +7 -11
- package/src/Upload/demo/controlled.tsx +12 -8
- package/src/Upload/demo/directory.tsx +3 -4
- package/src/Upload/demo/drag.tsx +5 -12
- package/src/Upload/demo/multiple.tsx +3 -4
- package/src/Upload/demo/pictureWall.tsx +22 -21
- package/src/Upload/dragger.tsx +47 -34
- package/src/Upload/index.en-US.md +63 -43
- package/src/Upload/index.ts +8 -1
- package/src/Upload/index.zh-CN.md +62 -42
- package/src/Upload/interface.ts +68 -120
- package/src/Upload/style/index.less +40 -13
- package/src/Upload/upload.tsx +546 -215
- package/src/Upload/uploaded-list/index.tsx +9 -5
- package/src/Upload/uploaded-list/uploaded-item.tsx +199 -228
- package/src/locale/interface.ts +1 -0
- package/src/locale/lang/en_US.ts +1 -0
- package/src/locale/lang/ja_JP.ts +1 -0
- package/src/locale/lang/zh_CN.ts +1 -0
- package/src/locale/lang/zh_TW.ts +1 -0
- package/src/style/size.css +2 -1
- package/src/utils/ax/core.ts +28 -41
- package/src/utils/folder-scanner.ts +51 -37
- package/src/version.ts +1 -1
|
@@ -9,6 +9,7 @@ interface UseNavListMoveOptions {
|
|
|
9
9
|
direction: 'horizontal' | 'vertical';
|
|
10
10
|
activeKey: string | number;
|
|
11
11
|
enabled: boolean;
|
|
12
|
+
align?: 'auto' | 'center';
|
|
12
13
|
activetab: React.RefObject<HTMLElement | null>;
|
|
13
14
|
navList: React.RefObject<HTMLDivElement | null>;
|
|
14
15
|
navContainer: React.RefObject<HTMLDivElement | null>;
|
|
@@ -19,6 +20,7 @@ export function useNavListMove({
|
|
|
19
20
|
direction,
|
|
20
21
|
activeKey,
|
|
21
22
|
enabled,
|
|
23
|
+
align = 'auto',
|
|
22
24
|
activetab,
|
|
23
25
|
navList,
|
|
24
26
|
navContainer,
|
|
@@ -33,29 +35,64 @@ export function useNavListMove({
|
|
|
33
35
|
return;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
// 'auto': keep as-is when the active tab is already fully visible.
|
|
39
|
+
// 'center': always re-center, even for tabs already visible on the header.
|
|
40
|
+
if (align !== 'center') {
|
|
41
|
+
const [isVisible] = isInContainer(direction, tab, list, container);
|
|
42
|
+
if (isVisible) return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let moved = false;
|
|
38
46
|
|
|
39
47
|
if (direction === 'horizontal') {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
if (align === 'center') {
|
|
49
|
+
const containerWidth = container.clientWidth;
|
|
50
|
+
const maxOffset = list.scrollWidth - containerWidth;
|
|
51
|
+
const tabCenter = tab.offsetLeft + tab.offsetWidth / 2;
|
|
44
52
|
|
|
45
|
-
|
|
53
|
+
let newX = Math.round(containerWidth / 2 - tabCenter);
|
|
54
|
+
newX = Math.max(-maxOffset, Math.min(0, newX));
|
|
46
55
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
+
const [x] = getEleTranslate(list);
|
|
57
|
+
if (Math.abs(newX - x) > 0.5) {
|
|
58
|
+
setEleTranslate(list, newX);
|
|
59
|
+
moved = true;
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
const [x] = getEleTranslate(list);
|
|
63
|
+
const tabLeft = tab.offsetLeft;
|
|
64
|
+
const tabWidth = tab.offsetWidth;
|
|
65
|
+
const containerWidth = container.clientWidth;
|
|
66
|
+
|
|
67
|
+
let newX = x;
|
|
68
|
+
|
|
69
|
+
// Tab overflows on the right side
|
|
70
|
+
if (tabLeft + tabWidth - Math.abs(x) > containerWidth) {
|
|
71
|
+
const overflow = tabLeft + tabWidth - Math.abs(x) - containerWidth;
|
|
72
|
+
newX = x - overflow;
|
|
73
|
+
}
|
|
74
|
+
// Tab overflows on the left side
|
|
75
|
+
else if (tabLeft < Math.abs(x)) {
|
|
76
|
+
const overflow = Math.abs(x) - tabLeft;
|
|
77
|
+
newX = x + overflow;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
setEleTranslate(list, newX);
|
|
81
|
+
moved = true;
|
|
56
82
|
}
|
|
83
|
+
} else if (align === 'center') {
|
|
84
|
+
const containerHeight = container.clientHeight;
|
|
85
|
+
const maxOffset = container.scrollHeight - containerHeight;
|
|
86
|
+
const tabCenter = tab.offsetTop + tab.offsetHeight / 2;
|
|
57
87
|
|
|
58
|
-
|
|
88
|
+
const newScrollTop = Math.max(
|
|
89
|
+
0,
|
|
90
|
+
Math.min(maxOffset, Math.round(tabCenter - containerHeight / 2)),
|
|
91
|
+
);
|
|
92
|
+
if (Math.abs(newScrollTop - container.scrollTop) > 0.5) {
|
|
93
|
+
container.scrollTop = newScrollTop;
|
|
94
|
+
moved = true;
|
|
95
|
+
}
|
|
59
96
|
} else {
|
|
60
97
|
const tabTop = tab.offsetTop;
|
|
61
98
|
const tabHeight = tab.offsetHeight;
|
|
@@ -66,19 +103,24 @@ export function useNavListMove({
|
|
|
66
103
|
if (tabTop + tabHeight - scrollTop >= containerHeight) {
|
|
67
104
|
const overflow = tabTop + tabHeight - scrollTop - containerHeight;
|
|
68
105
|
container.scrollTop = scrollTop + overflow;
|
|
106
|
+
moved = true;
|
|
69
107
|
}
|
|
70
108
|
// Tab overflows above
|
|
71
109
|
else if (tabTop < scrollTop) {
|
|
72
110
|
const overflow = scrollTop - tabTop;
|
|
73
111
|
container.scrollTop = scrollTop - overflow;
|
|
112
|
+
moved = true;
|
|
74
113
|
}
|
|
75
114
|
}
|
|
76
115
|
|
|
77
|
-
|
|
116
|
+
if (moved) {
|
|
117
|
+
onMoved?.();
|
|
118
|
+
}
|
|
78
119
|
}, [
|
|
79
120
|
activeKey,
|
|
80
121
|
enabled,
|
|
81
122
|
direction,
|
|
123
|
+
align,
|
|
82
124
|
activetab,
|
|
83
125
|
navList,
|
|
84
126
|
navContainer,
|
|
@@ -43,6 +43,12 @@ export function useTabScroll({
|
|
|
43
43
|
|
|
44
44
|
const debouncedUpdateShadow = useDebounceFunction(updateShadow, 200);
|
|
45
45
|
|
|
46
|
+
// Refresh dropdown range and shadows after the nav list is moved programmatically
|
|
47
|
+
const refresh = useCallback(() => {
|
|
48
|
+
setRefreshKey((prev) => prev + 1);
|
|
49
|
+
debouncedUpdateShadow();
|
|
50
|
+
}, [debouncedUpdateShadow]);
|
|
51
|
+
|
|
46
52
|
useEffect(() => {
|
|
47
53
|
const container = navContainer.current;
|
|
48
54
|
const list = navList.current;
|
|
@@ -99,5 +105,5 @@ export function useTabScroll({
|
|
|
99
105
|
updateShadow,
|
|
100
106
|
]);
|
|
101
107
|
|
|
102
|
-
return { refreshKey, updateShadow: debouncedUpdateShadow };
|
|
108
|
+
return { refreshKey, refresh, updateShadow: debouncedUpdateShadow };
|
|
103
109
|
}
|
package/src/Tabs/index.en-US.md
CHANGED
|
@@ -19,43 +19,45 @@ Tabs make it easy to switch between different views.
|
|
|
19
19
|
<code src="./demo/type.tsx" title="Type" description="Different types of tabs"></code>
|
|
20
20
|
<code src="./demo/editable.tsx" title="Editable" description="Add and remove tabs"></code>
|
|
21
21
|
<code src="./demo/extra.tsx" title="Extra Content" description="Extra content in tabs"></code>
|
|
22
|
+
<code src="./demo/overflow-center.tsx" title="Center Active Tab on Overflow" description="When tabs overflow into a dropdown, activeAlign="center" scrolls the tab selected from the dropdown to the middle of the header"></code>
|
|
22
23
|
<code src="./demo/controlled.tsx" title="Controlled" description="Controlled tabs"></code>
|
|
23
24
|
|
|
24
25
|
## API
|
|
25
26
|
|
|
26
27
|
### TabsProps
|
|
27
28
|
|
|
28
|
-
| Property
|
|
29
|
-
|
|
|
30
|
-
| prefixCls
|
|
31
|
-
| className
|
|
32
|
-
| style
|
|
33
|
-
| classNames
|
|
34
|
-
| styles
|
|
35
|
-
| type
|
|
36
|
-
| activeKey
|
|
37
|
-
| defaultActiveKey | `string \| number`
|
|
38
|
-
| items
|
|
39
|
-
| position
|
|
40
|
-
| headerExtra
|
|
41
|
-
| children
|
|
42
|
-
| lazy
|
|
43
|
-
| fixedHeader
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
29
|
+
| Property | Type | Description | Default |
|
|
30
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------- |
|
|
31
|
+
| prefixCls | `string` | Custom class name prefix | - |
|
|
32
|
+
| className | `string` | Custom root class name | - |
|
|
33
|
+
| style | `React.CSSProperties` | Custom root style | - |
|
|
34
|
+
| classNames | `Partial<Record<SemanticDOM, string>>` | Custom structure class names | - |
|
|
35
|
+
| styles | `Partial<Record<SemanticDOM, React.CSSProperties>>` | Custom structure styles | - |
|
|
36
|
+
| type | `'card' \| 'editable-card'` | Tab style | - |
|
|
37
|
+
| activeKey | `string \| number` | Current active tab key | - |
|
|
38
|
+
| defaultActiveKey | `string \| number` | Default active tab key | - |
|
|
39
|
+
| items | `Array<TabItemType>` | Tab items | - |
|
|
40
|
+
| position | `'top' \| 'bottom' \| 'left' \| 'right'` | Tab position | `top` |
|
|
41
|
+
| headerExtra | `{ prefix?: React.ReactNode \| (() => React.ReactNode); suffix?: React.ReactNode \| (() => React.ReactNode) }` | Extra content in tab bar | - |
|
|
42
|
+
| children | `Array<React.ReactElement>` | Children elements | - |
|
|
43
|
+
| lazy | `boolean` | Lazy load content | - |
|
|
44
|
+
| fixedHeader | `boolean` | Whether to fix header area | `false` |
|
|
45
|
+
| activeAlign | `'auto' \| 'center'` | How the active tab is aligned when the tab list overflows: `auto` scrolls minimally to the edge (no scrolling when already fully visible); `center` always scrolls it to the middle of the header, including tabs clicked directly on the header | `auto` |
|
|
46
|
+
| onEdit | `(type: 'add' \| 'remove', key?: number \| string) => void` | Edit callback | - |
|
|
47
|
+
| onChange | `(key: string \| number) => void` | Change callback | - |
|
|
48
|
+
| onTabClick | `(key: string \| number) => void \| boolean` | Tab click callback | - |
|
|
49
|
+
| data-\* | `string` | - | Supports all data-\* attributes, forwarded to root DOM element |
|
|
48
50
|
|
|
49
51
|
### TabItemType
|
|
50
52
|
|
|
51
|
-
| Property | Type
|
|
52
|
-
|
|
|
53
|
-
| key
|
|
54
|
-
| label
|
|
55
|
-
| icon
|
|
56
|
-
| disabled | `boolean`
|
|
57
|
-
| closable | `boolean`
|
|
58
|
-
| badge
|
|
59
|
-
| items
|
|
60
|
-
| children | `React.ReactNode`
|
|
61
|
-
| data
|
|
53
|
+
| Property | Type | Description | Default |
|
|
54
|
+
| -------- | -------------------- | ------------------------------------------------------ | -------------------------------------------------------------- |
|
|
55
|
+
| key | `string \| number` | Unique key | - |
|
|
56
|
+
| label | `React.ReactNode` | Tab label | - |
|
|
57
|
+
| icon | `React.ReactNode` | Tab icon | - |
|
|
58
|
+
| disabled | `boolean` | Disabled state | - |
|
|
59
|
+
| closable | `boolean` | Whether closable (effective when type="editable-card") | `true` |
|
|
60
|
+
| badge | `number` | Badge number | - |
|
|
61
|
+
| items | `Array<TabItemType>` | Sub tabs | - |
|
|
62
|
+
| children | `React.ReactNode` | Tab content | - |
|
|
63
|
+
| data-\* | `string` | - | Supports all data-\* attributes, forwarded to root DOM element |
|
package/src/Tabs/index.zh-CN.md
CHANGED
|
@@ -19,43 +19,45 @@ toc: 'content'
|
|
|
19
19
|
<code src="./demo/type.tsx" title="类型" description="不同类型的标签页"></code>
|
|
20
20
|
<code src="./demo/editable.tsx" title="可编辑" description="可添加和删除标签页"></code>
|
|
21
21
|
<code src="./demo/extra.tsx" title="额外内容" description="标签页中的额外内容"></code>
|
|
22
|
+
<code src="./demo/overflow-center.tsx" title="溢出时激活Tab居中" description="Tab较多出现下拉时,activeAlign="center" 让从下拉选中的Tab滚动到Header中间"></code>
|
|
22
23
|
<code src="./demo/controlled.tsx" title="受控" description="受控的标签页"></code>
|
|
23
24
|
|
|
24
25
|
## API
|
|
25
26
|
|
|
26
27
|
### TabsProps
|
|
27
28
|
|
|
28
|
-
| 属性名
|
|
29
|
-
|
|
|
30
|
-
| prefixCls
|
|
31
|
-
| className
|
|
32
|
-
| style
|
|
33
|
-
| classNames
|
|
34
|
-
| styles
|
|
35
|
-
| type
|
|
36
|
-
| activeKey
|
|
37
|
-
| defaultActiveKey | `string \| number`
|
|
38
|
-
| items
|
|
39
|
-
| position
|
|
40
|
-
| headerExtra
|
|
41
|
-
| children
|
|
42
|
-
| lazy
|
|
43
|
-
| fixedHeader
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
29
|
+
| 属性名 | 类型 | 描述 | 默认值 |
|
|
30
|
+
| ---------------- | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------- |
|
|
31
|
+
| prefixCls | `string` | 自定义类名前缀 | - |
|
|
32
|
+
| className | `string` | 自定义根类名 | - |
|
|
33
|
+
| style | `React.CSSProperties` | 自定义根行内样式 | - |
|
|
34
|
+
| classNames | `Partial<Record<SemanticDOM, string>>` | 自定义结构化类名 | - |
|
|
35
|
+
| styles | `Partial<Record<SemanticDOM, React.CSSProperties>>` | 自定义结构化样式 | - |
|
|
36
|
+
| type | `'card' \| 'editable-card'` | 页签样式 | - |
|
|
37
|
+
| activeKey | `string \| number` | 当前激活tab面板的key | - |
|
|
38
|
+
| defaultActiveKey | `string \| number` | 默认激活的tab面板的key | - |
|
|
39
|
+
| items | `Array<TabItemType>` | tab选项卡内容 | - |
|
|
40
|
+
| position | `'top' \| 'bottom' \| 'left' \| 'right'` | 页签位置 | `top` |
|
|
41
|
+
| headerExtra | `{ prefix?: React.ReactNode \| (() => React.ReactNode); suffix?: React.ReactNode \| (() => React.ReactNode) }` | tab额外内容 | - |
|
|
42
|
+
| children | `Array<React.ReactElement>` | 子元素 | - |
|
|
43
|
+
| lazy | `boolean` | 是否懒加载,只有当切换到该tab时才将对应的content加载到dom中 | - |
|
|
44
|
+
| fixedHeader | `boolean` | 是否固定Header区域 | `false` |
|
|
45
|
+
| activeAlign | `'auto' \| 'center'` | Tab溢出时激活tab的对齐方式:`auto` 贴边最小滚动(完全可见时不滚动);`center` 始终滚动到header中间居中,包括直接点击header上可见的tab | `auto` |
|
|
46
|
+
| onEdit | `(type: 'add' \| 'remove', key?: number \| string) => void` | 编辑Tab时的回调 | - |
|
|
47
|
+
| onChange | `(key: string \| number) => void` | Tab改变时的回调 | - |
|
|
48
|
+
| onTabClick | `(key: string \| number) => void \| boolean` | 点击Tab时的回调,当返回false时,不会切换Tab, 不会触发onChange | - |
|
|
49
|
+
| data-\* | `string` | - | 支持所有 data-\* 属性,透传到组件根 DOM 元素 |
|
|
48
50
|
|
|
49
51
|
### TabItemType
|
|
50
52
|
|
|
51
|
-
| 属性名
|
|
52
|
-
|
|
|
53
|
-
| key
|
|
54
|
-
| label
|
|
55
|
-
| icon
|
|
56
|
-
| disabled | `boolean`
|
|
57
|
-
| closable | `boolean`
|
|
58
|
-
| badge
|
|
59
|
-
| items
|
|
60
|
-
| children | `React.ReactNode`
|
|
61
|
-
| data
|
|
53
|
+
| 属性名 | 类型 | 描述 | 默认值 |
|
|
54
|
+
| -------- | -------------------- | ---------------------------------------- | -------------------------------------------- |
|
|
55
|
+
| key | `string \| number` | 唯一key对应activeKey | - |
|
|
56
|
+
| label | `React.ReactNode` | 选项卡显示内容 | - |
|
|
57
|
+
| icon | `React.ReactNode` | 选项卡显示图标 | - |
|
|
58
|
+
| disabled | `boolean` | 是否禁用 | - |
|
|
59
|
+
| closable | `boolean` | 是否可关闭,当type="editable-card"时生效 | `true` |
|
|
60
|
+
| badge | `number` | 角标 | - |
|
|
61
|
+
| items | `Array<TabItemType>` | 子tab | - |
|
|
62
|
+
| children | `React.ReactNode` | 显示内容 | - |
|
|
63
|
+
| data-\* | `string` | - | 支持所有 data-\* 属性,透传到组件根 DOM 元素 |
|
package/src/Tabs/interface.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DataAttributeProps } from '../utils/types';
|
|
2
2
|
|
|
3
|
-
type SemanticDOM = 'header' | 'content' | 'track' | 'list' | 'activeBar';
|
|
3
|
+
type SemanticDOM = 'header' | 'content' | 'track' | 'list' | 'activeBar' | 'more';
|
|
4
4
|
|
|
5
5
|
export type TabItemType = {
|
|
6
6
|
/**
|
|
@@ -124,4 +124,13 @@ export interface TabsProps extends DataAttributeProps {
|
|
|
124
124
|
* @default false
|
|
125
125
|
*/
|
|
126
126
|
fixedHeader?: boolean;
|
|
127
|
+
/**
|
|
128
|
+
* How the active tab is aligned when the tab list overflows
|
|
129
|
+
* - 'auto': scroll minimally so the active tab is visible at the edge;
|
|
130
|
+
* no scrolling when it is already fully visible
|
|
131
|
+
* - 'center': always scroll so the active tab is centered in the header,
|
|
132
|
+
* including tabs clicked directly on the header
|
|
133
|
+
* @default 'auto'
|
|
134
|
+
*/
|
|
135
|
+
activeAlign?: 'auto' | 'center';
|
|
127
136
|
}
|
|
@@ -439,6 +439,10 @@
|
|
|
439
439
|
height: var(--yee-tabs-nav-operations-height);
|
|
440
440
|
}
|
|
441
441
|
|
|
442
|
+
@{pls}-nav-more {
|
|
443
|
+
margin-left: 4px;
|
|
444
|
+
}
|
|
445
|
+
|
|
442
446
|
// 下拉框
|
|
443
447
|
@{pls}-operation-container {
|
|
444
448
|
max-height: var(--yee-tabs-operation-container-max-height);
|
|
@@ -452,6 +456,7 @@
|
|
|
452
456
|
|
|
453
457
|
@{pls}-tab {
|
|
454
458
|
height: var(--yee-tabs-operation-tab-height);
|
|
459
|
+
margin: 0;
|
|
455
460
|
padding: var(--yee-tabs-operation-tab-padding);
|
|
456
461
|
cursor: pointer;
|
|
457
462
|
|
|
@@ -38,6 +38,7 @@ export interface TabHeaderProps {
|
|
|
38
38
|
prefixCls: string;
|
|
39
39
|
type?: 'card' | 'editable-card';
|
|
40
40
|
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
41
|
+
activeAlign?: 'auto' | 'center';
|
|
41
42
|
headerExtra?: {
|
|
42
43
|
prefix?: React.ReactNode | (() => React.ReactNode);
|
|
43
44
|
suffix?: React.ReactNode | (() => React.ReactNode);
|
|
@@ -53,6 +54,7 @@ const TabHeader: React.FC<TabHeaderProps> = (props) => {
|
|
|
53
54
|
prefixCls,
|
|
54
55
|
type,
|
|
55
56
|
position = 'top',
|
|
57
|
+
activeAlign = 'auto',
|
|
56
58
|
headerExtra,
|
|
57
59
|
classNames,
|
|
58
60
|
styles,
|
|
@@ -80,7 +82,7 @@ const TabHeader: React.FC<TabHeaderProps> = (props) => {
|
|
|
80
82
|
});
|
|
81
83
|
|
|
82
84
|
// Scroll handling
|
|
83
|
-
const { refreshKey } = useTabScroll({
|
|
85
|
+
const { refreshKey, refresh: refreshNav } = useTabScroll({
|
|
84
86
|
direction,
|
|
85
87
|
navContainer,
|
|
86
88
|
navList,
|
|
@@ -97,15 +99,22 @@ const TabHeader: React.FC<TabHeaderProps> = (props) => {
|
|
|
97
99
|
enabled: !type, // Only show active bar for non-card types
|
|
98
100
|
});
|
|
99
101
|
|
|
102
|
+
// Recompute dropdown visibility, dropdown range and shadows after the list is moved
|
|
103
|
+
const handleNavMoved = useCallback(() => {
|
|
104
|
+
checkVisibility();
|
|
105
|
+
refreshNav();
|
|
106
|
+
}, [checkVisibility, refreshNav]);
|
|
107
|
+
|
|
100
108
|
// Navigation list movement
|
|
101
109
|
useNavListMove({
|
|
102
110
|
direction,
|
|
103
111
|
activeKey,
|
|
104
112
|
enabled: moreOpen,
|
|
113
|
+
align: activeAlign,
|
|
105
114
|
activetab,
|
|
106
115
|
navList,
|
|
107
116
|
navContainer,
|
|
108
|
-
onMoved:
|
|
117
|
+
onMoved: handleNavMoved,
|
|
109
118
|
});
|
|
110
119
|
|
|
111
120
|
// Listen for container size changes
|
|
@@ -212,7 +221,9 @@ const TabHeader: React.FC<TabHeaderProps> = (props) => {
|
|
|
212
221
|
{moreOpen && (
|
|
213
222
|
<DropDownTabs visible={moreOpen} items={items || []} range={range}>
|
|
214
223
|
<Button
|
|
215
|
-
className={`${prefixCls}-nav-more
|
|
224
|
+
className={clsx(`${prefixCls}-nav-more`, classNames?.more)}
|
|
225
|
+
style={styles?.more}
|
|
226
|
+
size="small"
|
|
216
227
|
icon={<Ellipsis size={14} strokeWidth={1.5} />}
|
|
217
228
|
type="text"
|
|
218
229
|
aria-label="More tabs"
|
package/src/Tabs/tabs.tsx
CHANGED
|
@@ -39,6 +39,7 @@ const Tabs: FC<TabsProps> = (baseprops) => {
|
|
|
39
39
|
activeKey,
|
|
40
40
|
defaultActiveKey,
|
|
41
41
|
fixedHeader,
|
|
42
|
+
activeAlign,
|
|
42
43
|
onChange,
|
|
43
44
|
onEdit,
|
|
44
45
|
onTabClick,
|
|
@@ -117,6 +118,7 @@ const Tabs: FC<TabsProps> = (baseprops) => {
|
|
|
117
118
|
<TabHeader
|
|
118
119
|
{...omit(props, ['children', 'className', 'style'])}
|
|
119
120
|
prefixCls={prefixCls}
|
|
121
|
+
activeAlign={activeAlign}
|
|
120
122
|
/>
|
|
121
123
|
<TabContent
|
|
122
124
|
prefixCls={prefixCls}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Upload,
|
|
4
|
+
type UploadFile,
|
|
5
|
+
type UploadInstance,
|
|
6
|
+
} from '@rainbow-oh/yee-c';
|
|
7
|
+
import React, { useRef, useState } from 'react';
|
|
8
|
+
|
|
9
|
+
export default () => {
|
|
10
|
+
const uploadRef = useRef<UploadInstance>(null);
|
|
11
|
+
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
|
12
|
+
const readyCount = fileList.filter((file) => file.status === 'ready').length;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
|
|
16
|
+
<Upload
|
|
17
|
+
ref={uploadRef}
|
|
18
|
+
autoUpload={false}
|
|
19
|
+
multiple
|
|
20
|
+
action="https://www.mocky.io/v2/5cc8019d300000980a055e76"
|
|
21
|
+
fileList={fileList}
|
|
22
|
+
onChange={({ fileList: nextFileList }) => setFileList(nextFileList)}
|
|
23
|
+
/>
|
|
24
|
+
<div>
|
|
25
|
+
<Button
|
|
26
|
+
type="primary"
|
|
27
|
+
disabled={readyCount === 0}
|
|
28
|
+
onClick={() => uploadRef.current?.upload()}
|
|
29
|
+
>
|
|
30
|
+
Start upload ({readyCount})
|
|
31
|
+
</Button>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { Button, Upload } from '@rainbow-oh/yee-c';
|
|
1
|
+
import { Button, Upload, type UploadProps } from '@rainbow-oh/yee-c';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import type { UploadFile } from '../interface';
|
|
4
3
|
|
|
5
4
|
export default () => {
|
|
6
|
-
const props = {
|
|
5
|
+
const props: UploadProps = {
|
|
7
6
|
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
|
|
8
|
-
onChange({ file, fileList }
|
|
7
|
+
onChange({ file, fileList }) {
|
|
9
8
|
if (file.status !== 'uploading') {
|
|
10
9
|
console.log(file, fileList);
|
|
11
10
|
}
|
|
@@ -14,26 +13,23 @@ export default () => {
|
|
|
14
13
|
{
|
|
15
14
|
uid: '1',
|
|
16
15
|
name: 'xxx.png',
|
|
17
|
-
status: '
|
|
18
|
-
raw: {} as File,
|
|
16
|
+
status: 'success',
|
|
19
17
|
size: 123,
|
|
20
|
-
percent:
|
|
18
|
+
percent: 100,
|
|
21
19
|
type: 'image/png',
|
|
22
20
|
},
|
|
23
21
|
{
|
|
24
22
|
uid: '2',
|
|
25
23
|
name: 'yyy.png',
|
|
26
|
-
status: '
|
|
27
|
-
raw: {} as File,
|
|
24
|
+
status: 'success',
|
|
28
25
|
size: 123,
|
|
29
|
-
percent:
|
|
26
|
+
percent: 100,
|
|
30
27
|
type: 'image/png',
|
|
31
28
|
},
|
|
32
29
|
],
|
|
33
30
|
};
|
|
34
31
|
|
|
35
32
|
return (
|
|
36
|
-
// @ts-ignore
|
|
37
33
|
<Upload {...props}>
|
|
38
34
|
<Button>Upload</Button>
|
|
39
35
|
</Upload>
|
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Button,
|
|
3
|
+
Upload,
|
|
4
|
+
type UploadFile,
|
|
5
|
+
type UploadProps,
|
|
6
|
+
} from '@rainbow-oh/yee-c';
|
|
2
7
|
import React, { useState } from 'react';
|
|
3
|
-
import type { UploadFile } from '../interface';
|
|
4
8
|
|
|
5
9
|
export default () => {
|
|
6
10
|
const [fileList, setFileList] = useState<UploadFile[]>([]);
|
|
7
11
|
|
|
8
|
-
const props = {
|
|
12
|
+
const props: UploadProps = {
|
|
9
13
|
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
|
|
10
14
|
fileList,
|
|
11
|
-
onChange({ file, fileList
|
|
12
|
-
setFileList(
|
|
15
|
+
onChange({ file, fileList: nextFileList }) {
|
|
16
|
+
setFileList(nextFileList);
|
|
13
17
|
if (file.status !== 'uploading') {
|
|
14
|
-
console.log(file,
|
|
18
|
+
console.log(file, nextFileList);
|
|
15
19
|
}
|
|
16
20
|
},
|
|
17
|
-
onRemove(file
|
|
18
|
-
setFileList(
|
|
21
|
+
onRemove(file) {
|
|
22
|
+
setFileList((current) => current.filter((item) => item.uid !== file.uid));
|
|
19
23
|
return true;
|
|
20
24
|
},
|
|
21
25
|
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { Button, Upload } from '@rainbow-oh/yee-c';
|
|
1
|
+
import { Button, Upload, type UploadProps } from '@rainbow-oh/yee-c';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import type { UploadFile } from '../interface';
|
|
4
3
|
|
|
5
4
|
export default () => {
|
|
6
|
-
const props = {
|
|
5
|
+
const props: UploadProps = {
|
|
7
6
|
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
|
|
8
7
|
directory: true,
|
|
9
|
-
onChange({ file, fileList }
|
|
8
|
+
onChange({ file, fileList }) {
|
|
10
9
|
if (file.status !== 'uploading') {
|
|
11
10
|
console.log(file, fileList);
|
|
12
11
|
}
|
package/src/Upload/demo/drag.tsx
CHANGED
|
@@ -1,23 +1,16 @@
|
|
|
1
|
-
import { Upload } from '@rainbow-oh/yee-c';
|
|
1
|
+
import { Upload, type UploadProps } from '@rainbow-oh/yee-c';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import type { UploadFile } from '../interface';
|
|
4
3
|
|
|
5
4
|
export default () => {
|
|
6
|
-
const props = {
|
|
5
|
+
const props: UploadProps = {
|
|
7
6
|
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
|
|
8
|
-
type: 'drag'
|
|
9
|
-
onChange({ file, fileList }
|
|
7
|
+
type: 'drag',
|
|
8
|
+
onChange({ file, fileList }) {
|
|
10
9
|
if (file.status !== 'uploading') {
|
|
11
10
|
console.log(file, fileList);
|
|
12
11
|
}
|
|
13
12
|
},
|
|
14
13
|
};
|
|
15
14
|
|
|
16
|
-
return
|
|
17
|
-
<Upload.Dragger {...props}>
|
|
18
|
-
{/* <div style={{ padding: '20px', border: '1px dashed #ccc' }}>
|
|
19
|
-
<p>Click or drag file to this area to upload</p>
|
|
20
|
-
</div> */}
|
|
21
|
-
</Upload.Dragger>
|
|
22
|
-
);
|
|
15
|
+
return <Upload.Dragger {...props} />;
|
|
23
16
|
};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { Button, Upload } from '@rainbow-oh/yee-c';
|
|
1
|
+
import { Button, Upload, type UploadProps } from '@rainbow-oh/yee-c';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import type { UploadFile } from '../interface';
|
|
4
3
|
|
|
5
4
|
export default () => {
|
|
6
|
-
const props = {
|
|
5
|
+
const props: UploadProps = {
|
|
7
6
|
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76',
|
|
8
7
|
multiple: true,
|
|
9
|
-
onChange({ file, fileList }
|
|
8
|
+
onChange({ file, fileList }) {
|
|
10
9
|
if (file.status !== 'uploading') {
|
|
11
10
|
console.log(file, fileList);
|
|
12
11
|
}
|