@aloudata/aloudata-design 0.1.0-beta1
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/.editorconfig +16 -0
- package/.eslintrc.js +43 -0
- package/.fatherrc.ts +16 -0
- package/.prettierignore +7 -0
- package/.prettierrc.js +1 -0
- package/.stylelintrc.json +36 -0
- package/.umirc.ts +15 -0
- package/README.md +82 -0
- package/commitlint.config.js +21 -0
- package/docs/index.md +21 -0
- package/jest/setupTests.js +1 -0
- package/lib/Button/demo/Icon/index.d.ts +3 -0
- package/lib/Button/demo/Icon/index.js +82 -0
- package/lib/Button/demo/Icon/index.less +6 -0
- package/lib/Button/demo/basic/index.d.ts +4 -0
- package/lib/Button/demo/basic/index.js +73 -0
- package/lib/Button/demo/basic/index.less +7 -0
- package/lib/Button/demo/disable/index.d.ts +3 -0
- package/lib/Button/demo/disable/index.js +37 -0
- package/lib/Button/demo/disable/index.less +0 -0
- package/lib/Button/demo/href/index.d.ts +2 -0
- package/lib/Button/demo/href/index.js +30 -0
- package/lib/Button/demo/loading/index.d.ts +3 -0
- package/lib/Button/demo/loading/index.js +51 -0
- package/lib/Button/demo/loading/index.less +6 -0
- package/lib/Button/index.d.ts +50 -0
- package/lib/Button/index.js +124 -0
- package/lib/Button/style/index.d.ts +2 -0
- package/lib/Button/style/index.js +5 -0
- package/lib/Button/style/index.less +255 -0
- package/lib/Dropdown/Button.d.ts +69 -0
- package/lib/Dropdown/Button.js +52 -0
- package/lib/Dropdown/demo/basic/index.d.ts +4 -0
- package/lib/Dropdown/demo/basic/index.js +35 -0
- package/lib/Dropdown/demo/button/index.d.ts +3 -0
- package/lib/Dropdown/demo/button/index.js +182 -0
- package/lib/Dropdown/demo/button/index.less +9 -0
- package/lib/Dropdown/demo/placement/index.d.ts +2 -0
- package/lib/Dropdown/demo/placement/index.js +56 -0
- package/lib/Dropdown/demo/subMenu/index.d.ts +2 -0
- package/lib/Dropdown/demo/subMenu/index.js +59 -0
- package/lib/Dropdown/demo/trigger/index.d.ts +2 -0
- package/lib/Dropdown/demo/trigger/index.js +32 -0
- package/lib/Dropdown/index.d.ts +59 -0
- package/lib/Dropdown/index.js +47 -0
- package/lib/Dropdown/style/index.d.ts +2 -0
- package/lib/Dropdown/style/index.js +5 -0
- package/lib/Dropdown/style/index.less +40 -0
- package/lib/Icon/iconfont/demo.css +539 -0
- package/lib/Icon/iconfont/demo_index.html +628 -0
- package/lib/Icon/iconfont/iconfont.css +93 -0
- package/lib/Icon/iconfont/iconfont.js +48 -0
- package/lib/Icon/iconfont/iconfont.json +142 -0
- package/lib/Icon/iconfont/iconfont.ttf +0 -0
- package/lib/Icon/iconfont/iconfont.woff +0 -0
- package/lib/Icon/iconfont/iconfont.woff2 +0 -0
- package/lib/Icon/index.d.ts +11 -0
- package/lib/Icon/index.js +54 -0
- package/lib/Icon/index.less +32 -0
- package/lib/Input/components/Group/index.d.ts +15 -0
- package/lib/Input/components/Group/index.js +24 -0
- package/lib/Input/components/Password/index.d.ts +10 -0
- package/lib/Input/components/Password/index.js +33 -0
- package/lib/Input/components/TextArea/index.d.ts +52 -0
- package/lib/Input/components/TextArea/index.js +26 -0
- package/lib/Input/demo/allowClear/index.d.ts +3 -0
- package/lib/Input/demo/allowClear/index.js +25 -0
- package/lib/Input/demo/allowClear/index.less +0 -0
- package/lib/Input/demo/basic/index.d.ts +4 -0
- package/lib/Input/demo/basic/index.js +80 -0
- package/lib/Input/demo/basic/index.less +6 -0
- package/lib/Input/demo/gourp/index.d.ts +2 -0
- package/lib/Input/demo/gourp/index.js +81 -0
- package/lib/Input/demo/password/index.d.ts +3 -0
- package/lib/Input/demo/password/index.js +35 -0
- package/lib/Input/demo/password/index.less +0 -0
- package/lib/Input/demo/prefix/index.d.ts +3 -0
- package/lib/Input/demo/prefix/index.js +32 -0
- package/lib/Input/demo/prefix/index.less +0 -0
- package/lib/Input/demo/showCount/index.d.ts +3 -0
- package/lib/Input/demo/showCount/index.js +31 -0
- package/lib/Input/demo/showCount/index.less +0 -0
- package/lib/Input/demo/textArea/autoSize.d.ts +2 -0
- package/lib/Input/demo/textArea/autoSize.js +63 -0
- package/lib/Input/index.d.ts +65 -0
- package/lib/Input/index.js +63 -0
- package/lib/Input/style/index.d.ts +2 -0
- package/lib/Input/style/index.js +5 -0
- package/lib/Input/style/index.less +62 -0
- package/lib/Menu/Divider.d.ts +5 -0
- package/lib/Menu/Divider.js +28 -0
- package/lib/Menu/MenuItem.d.ts +17 -0
- package/lib/Menu/MenuItem.js +28 -0
- package/lib/Menu/SubMenu.d.ts +26 -0
- package/lib/Menu/SubMenu.js +44 -0
- package/lib/Menu/index.d.ts +20 -0
- package/lib/Menu/index.js +49 -0
- package/lib/Menu/style/index.d.ts +2 -0
- package/lib/Menu/style/index.js +5 -0
- package/lib/Menu/style/index.less +33 -0
- package/lib/Select/BaseSelect.d.ts +5 -0
- package/lib/Select/BaseSelect.js +433 -0
- package/lib/Select/OptionsList/OptGroup.d.ts +7 -0
- package/lib/Select/OptionsList/OptGroup.js +14 -0
- package/lib/Select/OptionsList/OptionItem.d.ts +35 -0
- package/lib/Select/OptionsList/OptionItem.js +185 -0
- package/lib/Select/OptionsList/Options.d.ts +7 -0
- package/lib/Select/OptionsList/Options.js +14 -0
- package/lib/Select/OptionsList/index.d.ts +4 -0
- package/lib/Select/OptionsList/index.js +207 -0
- package/lib/Select/Selector/index.d.ts +4 -0
- package/lib/Select/Selector/index.js +273 -0
- package/lib/Select/VirtualList.d.ts +5 -0
- package/lib/Select/VirtualList.js +42 -0
- package/lib/Select/demo/disabled/index.d.ts +2 -0
- package/lib/Select/demo/disabled/index.js +64 -0
- package/lib/Select/demo/multiple/index.d.ts +2 -0
- package/lib/Select/demo/multiple/index.js +154 -0
- package/lib/Select/demo/options/index.d.ts +2 -0
- package/lib/Select/demo/options/index.js +69 -0
- package/lib/Select/demo/single/index.d.ts +2 -0
- package/lib/Select/demo/single/index.js +99 -0
- package/lib/Select/hooks/useCacheOption.d.ts +9 -0
- package/lib/Select/hooks/useCacheOption.js +113 -0
- package/lib/Select/index.d.ts +12 -0
- package/lib/Select/index.js +34 -0
- package/lib/Select/interface.d.ts +221 -0
- package/lib/Select/interface.js +5 -0
- package/lib/Select/style/index.d.ts +2 -0
- package/lib/Select/style/index.js +5 -0
- package/lib/Select/style/index.less +539 -0
- package/lib/Select/utils.d.ts +21 -0
- package/lib/Select/utils.js +233 -0
- package/lib/Tabs/TabPane.d.ts +21 -0
- package/lib/Tabs/TabPane.js +24 -0
- package/lib/Tabs/demo/adaptHeight/index.d.ts +3 -0
- package/lib/Tabs/demo/adaptHeight/index.js +34 -0
- package/lib/Tabs/demo/adaptHeight/index.less +3 -0
- package/lib/Tabs/demo/basic/index.d.ts +4 -0
- package/lib/Tabs/demo/basic/index.js +67 -0
- package/lib/Tabs/demo/basic/index.less +5 -0
- package/lib/Tabs/demo/horizontalScroll/index.d.ts +3 -0
- package/lib/Tabs/demo/horizontalScroll/index.js +45 -0
- package/lib/Tabs/demo/horizontalScroll/index.less +3 -0
- package/lib/Tabs/index.d.ts +41 -0
- package/lib/Tabs/index.js +58 -0
- package/lib/Tabs/style/index.d.ts +2 -0
- package/lib/Tabs/style/index.js +5 -0
- package/lib/Tabs/style/index.less +61 -0
- package/lib/Tooltip/demo/basic/index.d.ts +2 -0
- package/lib/Tooltip/demo/basic/index.js +20 -0
- package/lib/Tooltip/demo/overflow/index.d.ts +2 -0
- package/lib/Tooltip/demo/overflow/index.js +20 -0
- package/lib/Tooltip/demo/placement/index.d.ts +6 -0
- package/lib/Tooltip/demo/placement/index.js +86 -0
- package/lib/Tooltip/demo/placement/index.less +7 -0
- package/lib/Tooltip/demo/trigger/index.d.ts +3 -0
- package/lib/Tooltip/demo/trigger/index.js +34 -0
- package/lib/Tooltip/demo/trigger/index.less +5 -0
- package/lib/Tooltip/index.d.ts +63 -0
- package/lib/Tooltip/index.js +44 -0
- package/lib/Tooltip/style/index.d.ts +2 -0
- package/lib/Tooltip/style/index.js +5 -0
- package/lib/Tooltip/style/index.less +14 -0
- package/lib/_utils/hooks/useControlledState.d.ts +2 -0
- package/lib/_utils/hooks/useControlledState.js +63 -0
- package/lib/_utils/hooks/usePrefixCls.d.ts +2 -0
- package/lib/_utils/hooks/usePrefixCls.js +27 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +63 -0
- package/lib/style/index.d.ts +2 -0
- package/lib/style/index.js +5 -0
- package/lib/style/index.less +3 -0
- package/lib/style/mixins/index.less +0 -0
- package/lib/style/themes/default/index.less +36 -0
- package/lib/style/themes/default/themeColor.less +259 -0
- package/package.json +83 -0
- package/public/favicon.ico +0 -0
- package/src/Button/demo/Icon/index.less +6 -0
- package/src/Button/demo/Icon/index.tsx +41 -0
- package/src/Button/demo/basic/index.less +7 -0
- package/src/Button/demo/basic/index.tsx +26 -0
- package/src/Button/demo/disable/index.less +0 -0
- package/src/Button/demo/disable/index.tsx +16 -0
- package/src/Button/demo/href/index.tsx +14 -0
- package/src/Button/demo/loading/index.less +6 -0
- package/src/Button/demo/loading/index.tsx +21 -0
- package/src/Button/index.md +25 -0
- package/src/Button/index.test.tsx +58 -0
- package/src/Button/index.tsx +136 -0
- package/src/Button/style/index.less +255 -0
- package/src/Button/style/index.ts +2 -0
- package/src/Dropdown/Button.tsx +93 -0
- package/src/Dropdown/demo/basic/index.tsx +20 -0
- package/src/Dropdown/demo/button/index.less +9 -0
- package/src/Dropdown/demo/button/index.tsx +98 -0
- package/src/Dropdown/demo/placement/index.tsx +47 -0
- package/src/Dropdown/demo/subMenu/index.tsx +35 -0
- package/src/Dropdown/demo/trigger/index.tsx +19 -0
- package/src/Dropdown/index.md +35 -0
- package/src/Dropdown/index.test.tsx +185 -0
- package/src/Dropdown/index.tsx +71 -0
- package/src/Dropdown/style/index.less +40 -0
- package/src/Dropdown/style/index.ts +2 -0
- package/src/Icon/iconfont/demo.css +539 -0
- package/src/Icon/iconfont/demo_index.html +628 -0
- package/src/Icon/iconfont/iconfont.css +93 -0
- package/src/Icon/iconfont/iconfont.js +1 -0
- package/src/Icon/iconfont/iconfont.json +142 -0
- package/src/Icon/iconfont/iconfont.ttf +0 -0
- package/src/Icon/iconfont/iconfont.woff +0 -0
- package/src/Icon/iconfont/iconfont.woff2 +0 -0
- package/src/Icon/index.less +32 -0
- package/src/Icon/index.tsx +38 -0
- package/src/Input/components/Group/index.tsx +21 -0
- package/src/Input/components/Password/index.tsx +23 -0
- package/src/Input/components/TextArea/index.tsx +57 -0
- package/src/Input/demo/allowClear/index.less +0 -0
- package/src/Input/demo/allowClear/index.tsx +10 -0
- package/src/Input/demo/basic/index.less +6 -0
- package/src/Input/demo/basic/index.tsx +25 -0
- package/src/Input/demo/gourp/index.tsx +30 -0
- package/src/Input/demo/password/index.less +0 -0
- package/src/Input/demo/password/index.tsx +11 -0
- package/src/Input/demo/prefix/index.less +0 -0
- package/src/Input/demo/prefix/index.tsx +13 -0
- package/src/Input/demo/showCount/index.less +0 -0
- package/src/Input/demo/showCount/index.tsx +16 -0
- package/src/Input/demo/textArea/autoSize.tsx +21 -0
- package/src/Input/index.md +37 -0
- package/src/Input/index.test.tsx +78 -0
- package/src/Input/index.tsx +91 -0
- package/src/Input/style/index.less +62 -0
- package/src/Input/style/index.ts +2 -0
- package/src/Menu/Divider.tsx +12 -0
- package/src/Menu/MenuItem.tsx +24 -0
- package/src/Menu/SubMenu.tsx +37 -0
- package/src/Menu/index.md +36 -0
- package/src/Menu/index.test.tsx +144 -0
- package/src/Menu/index.tsx +27 -0
- package/src/Menu/style/index.less +33 -0
- package/src/Menu/style/index.ts +2 -0
- package/src/Select/BaseSelect.tsx +321 -0
- package/src/Select/OptionsList/OptGroup.tsx +9 -0
- package/src/Select/OptionsList/OptionItem.tsx +151 -0
- package/src/Select/OptionsList/Options.tsx +11 -0
- package/src/Select/OptionsList/index.tsx +169 -0
- package/src/Select/Selector/index.tsx +211 -0
- package/src/Select/VirtualList.tsx +36 -0
- package/src/Select/demo/disabled/index.tsx +44 -0
- package/src/Select/demo/multiple/index.tsx +77 -0
- package/src/Select/demo/options/index.tsx +63 -0
- package/src/Select/demo/single/index.tsx +50 -0
- package/src/Select/hooks/useCacheOption.ts +67 -0
- package/src/Select/index.md +72 -0
- package/src/Select/index.tsx +23 -0
- package/src/Select/interface.ts +231 -0
- package/src/Select/style/index.less +539 -0
- package/src/Select/style/index.ts +2 -0
- package/src/Select/utils.tsx +133 -0
- package/src/Tabs/TabPane.tsx +28 -0
- package/src/Tabs/demo/adaptHeight/index.less +3 -0
- package/src/Tabs/demo/adaptHeight/index.tsx +33 -0
- package/src/Tabs/demo/basic/index.less +5 -0
- package/src/Tabs/demo/basic/index.tsx +30 -0
- package/src/Tabs/demo/horizontalScroll/index.less +3 -0
- package/src/Tabs/demo/horizontalScroll/index.tsx +36 -0
- package/src/Tabs/index.md +30 -0
- package/src/Tabs/index.test.tsx +100 -0
- package/src/Tabs/index.tsx +64 -0
- package/src/Tabs/style/index.less +61 -0
- package/src/Tabs/style/index.ts +2 -0
- package/src/Tooltip/demo/basic/index.tsx +10 -0
- package/src/Tooltip/demo/overflow/index.tsx +10 -0
- package/src/Tooltip/demo/placement/index.less +7 -0
- package/src/Tooltip/demo/placement/index.tsx +60 -0
- package/src/Tooltip/demo/trigger/index.less +5 -0
- package/src/Tooltip/demo/trigger/index.tsx +22 -0
- package/src/Tooltip/index.md +28 -0
- package/src/Tooltip/index.test.tsx +152 -0
- package/src/Tooltip/index.tsx +113 -0
- package/src/Tooltip/style/index.less +14 -0
- package/src/Tooltip/style/index.ts +2 -0
- package/src/_utils/hooks/useControlledState.ts +39 -0
- package/src/_utils/hooks/usePrefixCls.ts +11 -0
- package/src/index.ts +8 -0
- package/src/style/index.less +3 -0
- package/src/style/index.ts +2 -0
- package/src/style/mixins/index.less +0 -0
- package/src/style/themes/default/index.less +36 -0
- package/src/style/themes/default/themeColor.less +259 -0
- package/tsconfig.json +13 -0
- package/typings.d.ts +3 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
4
|
+
import Input from './index';
|
|
5
|
+
import _ from 'lodash';
|
|
6
|
+
|
|
7
|
+
describe('Input', () => {
|
|
8
|
+
it('Input large size with value', () => {
|
|
9
|
+
const text = 'Input large size with value';
|
|
10
|
+
render(<Input className="ald-input" size="large" value={text} />);
|
|
11
|
+
expect(document.querySelector('.ald-input')).not.toBeNull();
|
|
12
|
+
expect(document.querySelector('.ald-input')).toHaveClass('ant-input-lg');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('Input native default props placeholder', () => {
|
|
16
|
+
render(<Input placeholder="placeholder" />);
|
|
17
|
+
expect(screen.queryByPlaceholderText('placeholder')).not.toBeNull();
|
|
18
|
+
});
|
|
19
|
+
it('input disable', () => {
|
|
20
|
+
render(<Input disabled />);
|
|
21
|
+
expect(screen.queryByRole('textbox')).toHaveAttribute('disabled');
|
|
22
|
+
});
|
|
23
|
+
it('input allowClear', () => {
|
|
24
|
+
render(<Input allowClear />);
|
|
25
|
+
expect(screen.queryByRole('button', { name: /close-circle/i })).not.toBeNull();
|
|
26
|
+
});
|
|
27
|
+
it('input prefix', () => {
|
|
28
|
+
render(<Input prefix={<span>prefix</span>} />);
|
|
29
|
+
expect(screen.queryByText('prefix')).not.toBeNull();
|
|
30
|
+
});
|
|
31
|
+
it('input showCount', () => {
|
|
32
|
+
const maxLength = 10;
|
|
33
|
+
const collection = ['abc', 'a', 'bcd'];
|
|
34
|
+
const value = _.sample(collection);
|
|
35
|
+
render(<Input showCount maxLength={maxLength} value={value} />);
|
|
36
|
+
expect(screen.queryByText(`${value.length} / ${maxLength}`)).not.toBeNull();
|
|
37
|
+
render(<Input
|
|
38
|
+
showCount={{ formatter: ({ count: number }) => {
|
|
39
|
+
return `长度为:${number}`;
|
|
40
|
+
} }}
|
|
41
|
+
value={value}
|
|
42
|
+
/>);
|
|
43
|
+
expect(screen.queryByText(`长度为:${value.length}`)).not.toBeNull();
|
|
44
|
+
});
|
|
45
|
+
it('input onChange', () => {
|
|
46
|
+
const onChange = jest.fn();
|
|
47
|
+
render(<Input onChange={onChange} />);
|
|
48
|
+
const input = screen.queryByRole('textbox');
|
|
49
|
+
fireEvent.change(input!, { target: { value: 'change' } });
|
|
50
|
+
expect(onChange).toBeCalled();
|
|
51
|
+
});
|
|
52
|
+
it('input onPressEnter', () => {
|
|
53
|
+
const onPressEnter = jest.fn();
|
|
54
|
+
render(<Input onPressEnter={onPressEnter} />);
|
|
55
|
+
const input = screen.queryByRole('textbox');
|
|
56
|
+
fireEvent.keyDown(input!, { key: 'Enter', keyCode: 13, which: 13 });
|
|
57
|
+
expect(onPressEnter).toBeCalled();
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
describe('Input.textArea', () => {
|
|
61
|
+
it('Input.textArea showCount', () => {
|
|
62
|
+
const maxLength = 10;
|
|
63
|
+
render(<Input.TextArea showCount maxLength={maxLength} />);
|
|
64
|
+
const textArea = screen.queryByRole('textbox');
|
|
65
|
+
const textAreaParent = textArea!.parentElement;
|
|
66
|
+
expect(textAreaParent).toHaveAttribute('data-count');
|
|
67
|
+
});
|
|
68
|
+
it('Input.textArea onPressEnter', () => {
|
|
69
|
+
const onPressEnter = jest.fn();
|
|
70
|
+
render(<Input.TextArea onPressEnter={onPressEnter} />);
|
|
71
|
+
const textArea = screen.queryByRole('textbox');
|
|
72
|
+
fireEvent.keyDown(textArea!, { key: 'Enter', keyCode: 13, which: 13 });
|
|
73
|
+
expect(onPressEnter).toBeCalled();
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('Input.group', () => {
|
|
77
|
+
it('', () => {});
|
|
78
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import {Input as AntdInput} from 'antd';
|
|
3
|
+
import type { ShowCountProps, InputProps } from 'antd/lib/input/Input';
|
|
4
|
+
import { SizeType } from 'antd/lib/config-provider/SizeContext';
|
|
5
|
+
import TextArea from './components/TextArea';
|
|
6
|
+
import Password from './components/Password';
|
|
7
|
+
import Group from './components/Group';
|
|
8
|
+
import './style';
|
|
9
|
+
type TSize = 'small' | 'default' | 'large';
|
|
10
|
+
|
|
11
|
+
type ChangeEventHandler = (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
12
|
+
export interface IInputProps extends Omit<InputProps, 'size' | 'id' | 'prefix' | 'allowClear' |
|
|
13
|
+
'disabled' | 'showCount' | 'maxLength' |
|
|
14
|
+
'value' | 'defaultValue' | 'onPressEnter' | 'onChange'> {
|
|
15
|
+
/**
|
|
16
|
+
* @description 输入框尺寸
|
|
17
|
+
* @default default
|
|
18
|
+
* @type 'small' | 'default' | 'large';
|
|
19
|
+
*/
|
|
20
|
+
size?: TSize;
|
|
21
|
+
/**
|
|
22
|
+
* @description 输入框id
|
|
23
|
+
*/
|
|
24
|
+
id?: string;
|
|
25
|
+
/**
|
|
26
|
+
* @description 提示文字
|
|
27
|
+
*/
|
|
28
|
+
prefix?: ReactNode;
|
|
29
|
+
/**
|
|
30
|
+
* @description 带标签的 input,设置前置标签
|
|
31
|
+
*/
|
|
32
|
+
allowClear?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* @description 可以点击清除图标删除内容
|
|
35
|
+
* @default true
|
|
36
|
+
*/
|
|
37
|
+
disabled?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* @description 提示文字
|
|
40
|
+
* @default false
|
|
41
|
+
* @type boolean | { formatter: (args: { count: number; maxLength?: number; }) => string; };
|
|
42
|
+
*/
|
|
43
|
+
showCount?: boolean | ShowCountProps;
|
|
44
|
+
/**
|
|
45
|
+
* @description 最大长度
|
|
46
|
+
*/
|
|
47
|
+
maxLength?: number;
|
|
48
|
+
/**
|
|
49
|
+
* @description 输入框内容
|
|
50
|
+
*/
|
|
51
|
+
value?: string;
|
|
52
|
+
/**
|
|
53
|
+
* @description 输入框默认内容
|
|
54
|
+
*/
|
|
55
|
+
defaultValue?: string;
|
|
56
|
+
/**
|
|
57
|
+
* @description 按下回车的回调
|
|
58
|
+
* @type (e) => void
|
|
59
|
+
*/
|
|
60
|
+
onPressEnter?: React.KeyboardEventHandler<HTMLInputElement>;
|
|
61
|
+
/**
|
|
62
|
+
* @description 输入框内容变化时的回调
|
|
63
|
+
* @type (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
64
|
+
*/
|
|
65
|
+
onChange?: ChangeEventHandler;
|
|
66
|
+
}
|
|
67
|
+
// IInputProps 和 InputProps 类型合并,并去除InputProps中的重复属性
|
|
68
|
+
function Input(props: IInputProps) {
|
|
69
|
+
const { size = 'default', ...rest } = props;
|
|
70
|
+
const getInputSize = (inputSize: TSize): SizeType => {
|
|
71
|
+
if (inputSize === 'small' || inputSize === 'large') {
|
|
72
|
+
return inputSize;
|
|
73
|
+
}
|
|
74
|
+
return 'middle';
|
|
75
|
+
};
|
|
76
|
+
return (
|
|
77
|
+
<AntdInput
|
|
78
|
+
{...rest}
|
|
79
|
+
size={getInputSize(size)}
|
|
80
|
+
bordered
|
|
81
|
+
addonAfter={null}
|
|
82
|
+
addonBefore={null}
|
|
83
|
+
suffix={null}
|
|
84
|
+
/>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
Input.TextArea = TextArea;
|
|
88
|
+
Input.Group = Group;
|
|
89
|
+
Input.Password = Password;
|
|
90
|
+
|
|
91
|
+
export default Input;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
@import '../../style/index.less';
|
|
2
|
+
@import '../../Icon/index.less';
|
|
3
|
+
|
|
4
|
+
@ald-prefix:ant;
|
|
5
|
+
|
|
6
|
+
@ald-iconfont-css-prefix:anticon;
|
|
7
|
+
.@{ald-prefix}-input {
|
|
8
|
+
color: @NL0;
|
|
9
|
+
border-radius: @border-radius-base;
|
|
10
|
+
&::placeholder {
|
|
11
|
+
color: @NL50;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
&-prefix {
|
|
15
|
+
color: @NL30;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
&-suffix {
|
|
19
|
+
color: @NL60;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
&:focus,
|
|
23
|
+
&-focused {
|
|
24
|
+
border-color: @B40;
|
|
25
|
+
box-shadow: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&[disabled] {
|
|
29
|
+
border-color: @NL90;
|
|
30
|
+
background-color: @NL95;
|
|
31
|
+
color: @NL80;
|
|
32
|
+
|
|
33
|
+
&::placeholder {
|
|
34
|
+
color: @NL80;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&-sm {
|
|
39
|
+
border-radius: @border-radius-sm;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&-affix-wrapper {
|
|
43
|
+
border-radius: @border-radius-base;
|
|
44
|
+
&-hover,
|
|
45
|
+
&-focused,
|
|
46
|
+
&:hover {
|
|
47
|
+
box-shadow: unset;
|
|
48
|
+
}
|
|
49
|
+
.@{ald-prefix}-input {
|
|
50
|
+
border-radius: 0;
|
|
51
|
+
caret-color: @B40;
|
|
52
|
+
}
|
|
53
|
+
&-sm {
|
|
54
|
+
border-radius: @border-radius-sm;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
.@{ald-iconfont-css-prefix} {
|
|
59
|
+
&.@{ald-iconfont-css-prefix}-close-circle, &.@{ald-prefix}-clear-icon {
|
|
60
|
+
.ald-iconfont('\e616');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Menu as AntdMenu } from 'antd';
|
|
3
|
+
import './style';
|
|
4
|
+
|
|
5
|
+
export interface IMenuDividerProps {
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const AntdMenuDivider = AntdMenu.Divider;
|
|
9
|
+
|
|
10
|
+
export default function Menu(props: IMenuDividerProps) {
|
|
11
|
+
return <AntdMenuDivider {...props} />;
|
|
12
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Menu as AntdMenu } from 'antd';
|
|
3
|
+
import './style';
|
|
4
|
+
|
|
5
|
+
export interface IMenuItemProps {
|
|
6
|
+
/**
|
|
7
|
+
* @description 唯一标志
|
|
8
|
+
* @type string | number
|
|
9
|
+
* @default -
|
|
10
|
+
*/
|
|
11
|
+
key: React.Key;
|
|
12
|
+
/**
|
|
13
|
+
* @description 是否禁用
|
|
14
|
+
* @default false
|
|
15
|
+
*/
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const AntdMenuItem = AntdMenu.Item;
|
|
21
|
+
|
|
22
|
+
export default function Menu(props: IMenuItemProps) {
|
|
23
|
+
return <AntdMenuItem {...props} />;
|
|
24
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Menu as AntdMenu } from 'antd';
|
|
4
|
+
import './style';
|
|
5
|
+
|
|
6
|
+
export interface ISubMenuProps {
|
|
7
|
+
/**
|
|
8
|
+
* @description 唯一标志
|
|
9
|
+
* @type string | number
|
|
10
|
+
* @default -
|
|
11
|
+
*/
|
|
12
|
+
key: React.Key;
|
|
13
|
+
/**
|
|
14
|
+
* @description 是否禁用
|
|
15
|
+
* @default false
|
|
16
|
+
*/
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* @description 子菜单样式
|
|
20
|
+
* @default -
|
|
21
|
+
*/
|
|
22
|
+
popupClassName?: string;
|
|
23
|
+
/**
|
|
24
|
+
* @description 子菜单项值
|
|
25
|
+
*/
|
|
26
|
+
title?: React.ReactNode;
|
|
27
|
+
children?: React.ReactNode | React.ReactNode[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const AntdSubMenu = AntdMenu.SubMenu;
|
|
31
|
+
|
|
32
|
+
export default function SubMenu(props: ISubMenuProps) {
|
|
33
|
+
const { popupClassName, ...otherProps } = props;
|
|
34
|
+
const OFFSET_WIDTH = 4;
|
|
35
|
+
const OFFSET_HEIGHT = 0;
|
|
36
|
+
return <AntdSubMenu popupClassName={classNames(popupClassName, 'ald-submenu')} popupOffset={[OFFSET_WIDTH, OFFSET_HEIGHT]} {...otherProps} />;
|
|
37
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
# nav:
|
|
3
|
+
# title: 组件
|
|
4
|
+
# path: /components
|
|
5
|
+
title: Menu 导航菜单
|
|
6
|
+
group:
|
|
7
|
+
title: 组件
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Menu 导航菜单
|
|
11
|
+
|
|
12
|
+
导航的菜单列表
|
|
13
|
+
|
|
14
|
+
## 代码演示
|
|
15
|
+
|
|
16
|
+
<code src="../Dropdown/demo/subMenu" title="下拉多级菜单" description="传入的菜单有多个层级">
|
|
17
|
+
|
|
18
|
+
## API
|
|
19
|
+
|
|
20
|
+
### Menu
|
|
21
|
+
|
|
22
|
+
<API exports='["default"]' hideTitle />
|
|
23
|
+
|
|
24
|
+
### Menu.Item
|
|
25
|
+
|
|
26
|
+
<API exports='["default.Item"]' hideTitle />
|
|
27
|
+
|
|
28
|
+
### Menu.SubMenu
|
|
29
|
+
|
|
30
|
+
<API exports='["default.SubMenu"]' hideTitle />
|
|
31
|
+
|
|
32
|
+
## 注意
|
|
33
|
+
|
|
34
|
+
* Menu 元素为 ul,因而仅支持 li 以及 script-supporting 子元素。因而你的子节点元素应该都在 Menu.Item 内使用。
|
|
35
|
+
|
|
36
|
+
* Menu 需要计算节点结构,因而其子元素仅支持 Menu.* 以及对此进行封装的 HOC 组件。
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
2
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { act } from 'react-dom/test-utils';
|
|
5
|
+
import Dropdown from '../Dropdown';
|
|
6
|
+
import Menu from './index';
|
|
7
|
+
|
|
8
|
+
describe('Menu', () => {
|
|
9
|
+
it('onClick', async () => {
|
|
10
|
+
let testKey = '';
|
|
11
|
+
const onClick = ({ key }: { key: string }) => { testKey = key; };
|
|
12
|
+
const menuItemText = '1st menu item';
|
|
13
|
+
const menu = (
|
|
14
|
+
<Menu onClick={onClick}>
|
|
15
|
+
<Menu.Item key="1"><span>{menuItemText}</span></Menu.Item>
|
|
16
|
+
<Menu.Item key="2">2st menu item</Menu.Item>
|
|
17
|
+
</Menu>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
await act(async () => {
|
|
21
|
+
render(<Dropdown overlay={menu} visible><span>trigger</span></Dropdown>);
|
|
22
|
+
await waitFor(() => {
|
|
23
|
+
return screen.getByText(menuItemText);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
fireEvent.click(screen.getByText(menuItemText));
|
|
28
|
+
expect(testKey).toEqual('1');
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('MenuItem.disabled', async () => {
|
|
32
|
+
const onClick = jest.fn();
|
|
33
|
+
const menuItemText = '1st menu item';
|
|
34
|
+
const menu = (
|
|
35
|
+
<Menu onClick={onClick}>
|
|
36
|
+
<Menu.Item key="1" disabled><span>{menuItemText}</span></Menu.Item>
|
|
37
|
+
<Menu.Item key="2">2st menu item</Menu.Item>
|
|
38
|
+
</Menu>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
await act(async () => {
|
|
42
|
+
render(<Dropdown overlay={menu} visible><span>trigger</span></Dropdown>);
|
|
43
|
+
await waitFor(() => {
|
|
44
|
+
return screen.getByText(menuItemText);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
fireEvent.click(screen.getByText(menuItemText));
|
|
49
|
+
expect(onClick).not.toBeCalled();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('SubMenu hover', async () => {
|
|
53
|
+
const subMenuTitle = 'subMenuTitle';
|
|
54
|
+
const menuItemText = '1st menu item';
|
|
55
|
+
const menu = (
|
|
56
|
+
<Menu>
|
|
57
|
+
<Menu.SubMenu key="0" title={subMenuTitle}>
|
|
58
|
+
<Menu.Item key="1"><span>{menuItemText}</span></Menu.Item>
|
|
59
|
+
<Menu.Item key="2">2st menu item</Menu.Item>
|
|
60
|
+
</Menu.SubMenu>
|
|
61
|
+
</Menu>
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
await act(async () => {
|
|
65
|
+
render(<Dropdown overlay={menu} visible><span>trigger</span></Dropdown>);
|
|
66
|
+
await waitFor(() => {
|
|
67
|
+
return screen.getByText(subMenuTitle);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
await act(async () => {
|
|
72
|
+
fireEvent.mouseEnter(screen.getByText(subMenuTitle));
|
|
73
|
+
await waitFor(() => {
|
|
74
|
+
return screen.getByText(menuItemText);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
expect(screen.getByText(menuItemText)).not.toBeNull();
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('SubMenu disabled', async () => {
|
|
81
|
+
jest.useFakeTimers();
|
|
82
|
+
|
|
83
|
+
const subMenuTitle = 'subMenuTitle';
|
|
84
|
+
const menuItemText = '1st menu item';
|
|
85
|
+
const menu = (
|
|
86
|
+
<Menu>
|
|
87
|
+
<Menu.SubMenu key="0" title={subMenuTitle} disabled>
|
|
88
|
+
<Menu.Item key="1"><span>{menuItemText}</span></Menu.Item>
|
|
89
|
+
<Menu.Item key="2">2st menu item</Menu.Item>
|
|
90
|
+
</Menu.SubMenu>
|
|
91
|
+
</Menu>
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
await act(async () => {
|
|
95
|
+
render(<Dropdown overlay={menu} visible><span>trigger</span></Dropdown>);
|
|
96
|
+
await waitFor(() => {
|
|
97
|
+
return screen.getByText(subMenuTitle);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
act(() => {
|
|
102
|
+
fireEvent.mouseEnter(screen.getByText(subMenuTitle));
|
|
103
|
+
});
|
|
104
|
+
// 等待一段时间,确保 mouseEnterDelay 时间过去
|
|
105
|
+
const DELAY_TIME = 1000;
|
|
106
|
+
jest.advanceTimersByTime(DELAY_TIME);
|
|
107
|
+
|
|
108
|
+
// 期待二级子菜单不出现
|
|
109
|
+
expect(screen.queryByText(menuItemText)).toBeNull();
|
|
110
|
+
|
|
111
|
+
jest.runOnlyPendingTimers();
|
|
112
|
+
jest.useRealTimers();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('SubMenu popupClassName', async () => {
|
|
116
|
+
const subMenuTitle = 'subMenuTitle';
|
|
117
|
+
const menuItemText = '1st menu item';
|
|
118
|
+
const popupClassName = 'popupClassName';
|
|
119
|
+
const menu = (
|
|
120
|
+
<Menu>
|
|
121
|
+
<Menu.SubMenu key="0" title={subMenuTitle} popupClassName={popupClassName}>
|
|
122
|
+
<Menu.Item key="1"><span>{menuItemText}</span></Menu.Item>
|
|
123
|
+
<Menu.Item key="2">2st menu item</Menu.Item>
|
|
124
|
+
</Menu.SubMenu>
|
|
125
|
+
</Menu>
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
await act(async () => {
|
|
129
|
+
render(<Dropdown overlay={menu} visible><span>trigger</span></Dropdown>);
|
|
130
|
+
await waitFor(() => {
|
|
131
|
+
return screen.getByText(subMenuTitle);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
await act(async () => {
|
|
136
|
+
fireEvent.mouseEnter(screen.getByText(subMenuTitle));
|
|
137
|
+
await waitFor(() => {
|
|
138
|
+
return screen.getByText(menuItemText);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(document.querySelector(`.${popupClassName}`)).not.toBeNull();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Menu as AntdMenu} from 'antd';
|
|
4
|
+
import MenuItem from './MenuItem';
|
|
5
|
+
import Divider from './Divider';
|
|
6
|
+
import SubMenu from './SubMenu';
|
|
7
|
+
import type { MenuClickEventHandler } from 'rc-menu/lib/interface';
|
|
8
|
+
import './style';
|
|
9
|
+
|
|
10
|
+
export interface IMenuProps {
|
|
11
|
+
/**
|
|
12
|
+
* @description 点击 MenuItem 调用此函数
|
|
13
|
+
* @default -
|
|
14
|
+
*/
|
|
15
|
+
onClick?: MenuClickEventHandler;
|
|
16
|
+
className?: string;
|
|
17
|
+
children?: React.ReactNode | React.ReactNode[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function Menu(props: IMenuProps) {
|
|
21
|
+
const { className, ...otherProps } = props;
|
|
22
|
+
return <AntdMenu className={classNames(className, 'ald-menu')} {...otherProps} />;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
Menu.Item = MenuItem;
|
|
26
|
+
Menu.Divider = Divider;
|
|
27
|
+
Menu.SubMenu = SubMenu;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
@import '../../style/index.less';
|
|
2
|
+
@import '../../Icon/index.less';
|
|
3
|
+
|
|
4
|
+
.menu-popup {
|
|
5
|
+
border: 1px solid @NL95;
|
|
6
|
+
box-shadow: @shadow-actionsheet;
|
|
7
|
+
border-radius: @border-radius-base;
|
|
8
|
+
background: @BG100;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.ald-menu,
|
|
12
|
+
.ald-submenu {
|
|
13
|
+
.menu-popup();
|
|
14
|
+
|
|
15
|
+
.ant-dropdown-menu-item-divider,
|
|
16
|
+
.ant-dropdown-menu-submenu-title-divider {
|
|
17
|
+
background-color: @NL90;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.ald-iconfont {
|
|
21
|
+
font-family: @icon-font !important;
|
|
22
|
+
font-size: 16px;
|
|
23
|
+
font-style: normal;
|
|
24
|
+
-webkit-font-smoothing: antialiased;
|
|
25
|
+
-moz-osx-font-smoothing: grayscale;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 替换二级菜单箭头icon
|
|
29
|
+
.ant-dropdown-menu-item .ant-dropdown-menu-submenu-expand-icon .ant-dropdown-menu-submenu-arrow-icon,
|
|
30
|
+
.ant-dropdown-menu-submenu-title .ant-dropdown-menu-submenu-expand-icon .ant-dropdown-menu-submenu-arrow-icon {
|
|
31
|
+
.ald-iconfont('\e691');
|
|
32
|
+
}
|
|
33
|
+
}
|