Skip to content

Commit 09d1284

Browse files
committed
✨ feat: init basic components
1 parent fb5863f commit 09d1284

File tree

196 files changed

+12457
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

196 files changed

+12457
-4
lines changed

package.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,58 @@
5757
"prettier --parser=typescript --write"
5858
]
5959
},
60+
"dependencies": {
61+
"@ant-design/colors": "^7",
62+
"@ant-design/icons": "^5",
63+
"@babel/runtime": "^7",
64+
"@floating-ui/react": "^0",
65+
"@giscus/react": "^2",
66+
"@lobehub/chat-plugin-sdk": "latest",
67+
"@lobehub/emojilib": "latest",
68+
"@react-spring/three": "^9",
69+
"@react-spring/web": "^9",
70+
"@react-three/drei": "^9",
71+
"@react-three/fiber": "^8",
72+
"ahooks": "^3",
73+
"antd": "^5",
74+
"chroma-js": "^2",
75+
"copy-to-clipboard": "^3",
76+
"dayjs": "^1",
77+
"emoji-regex": "^10",
78+
"fast-deep-equal": "^3",
79+
"immer": "^10",
80+
"lodash-es": "^4",
81+
"lucide-react": "^0.288.0",
82+
"polished": "^4",
83+
"prism-react-renderer": "^2",
84+
"rc-footer": "^0",
85+
"re-resizable": "^6",
86+
"react-error-boundary": "^4",
87+
"react-layout-kit": "^1.7.1",
88+
"react-markdown": "^8",
89+
"react-rnd": "^10",
90+
"react-simple-code-editor": "^0",
91+
"rehype-katex": "^6",
92+
"remark-gfm": "^3",
93+
"remark-math": "^5",
94+
"shikiji": "^0",
95+
"swr": "^2",
96+
"three": "^0.150",
97+
"ts-md5": "^1",
98+
"url-join": "^5",
99+
"use-merge-value": "^1",
100+
"zustand": "^4.4.1",
101+
"zustand-utils": "^1.3.1"
102+
},
60103
"devDependencies": {
61104
"@commitlint/cli": "^17",
105+
"@lobehub/ui": "^1",
62106
"@testing-library/react": "^14",
63107
"@types/react": "^18",
64108
"@types/react-dom": "^18",
65109
"@umijs/lint": "^4",
66110
"@vitest/coverage-v8": "latest",
111+
"antd-style": "^3",
67112
"commitlint": "^17",
68113
"commitlint-config-gitmoji": "^2",
69114
"conventional-changelog-gitmoji-config": "^1",
@@ -74,6 +119,7 @@
74119
"father": "^4",
75120
"husky": "^8",
76121
"jsdom": "^22",
122+
"leva": "^0.9.35",
77123
"lint-staged": "^15",
78124
"prettier": "^3",
79125
"prettier-plugin-organize-imports": "^3",
@@ -82,10 +128,15 @@
82128
"react-dom": "^18",
83129
"semantic-release": "^21",
84130
"semantic-release-config-gitmoji": "^1",
131+
"styled-components": "^6.1.0",
85132
"stylelint": "^15",
86133
"typescript": "^5",
87134
"vitest": "latest"
88135
},
136+
"peerDependencies": {
137+
"antd": "^5",
138+
"antd-style": "^3"
139+
},
89140
"publishConfig": {
90141
"access": "public",
91142
"registry": "https://registry.npmjs.org"
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { ActionIcon, ActionIconProps } from '@ant-design/pro-chat';
2+
import { StoryBook, useControls, useCreateStore } from '@lobehub/ui';
3+
import { Settings } from 'lucide-react';
4+
5+
export default () => {
6+
const store = useCreateStore();
7+
const size: ActionIconProps['size'] | any = useControls(
8+
{
9+
blockSize: {
10+
max: 100,
11+
min: 8,
12+
step: 4,
13+
value: 40,
14+
},
15+
borderRadius: {
16+
max: 50,
17+
min: 2,
18+
step: 2,
19+
value: 10,
20+
},
21+
fontSize: {
22+
max: 100,
23+
min: 8,
24+
step: 4,
25+
value: 28,
26+
},
27+
strokeWidth: {
28+
max: 2,
29+
min: 1,
30+
step: 0.5,
31+
value: 2,
32+
},
33+
},
34+
{ store },
35+
);
36+
37+
return (
38+
<StoryBook levaStore={store}>
39+
<ActionIcon active icon={Settings} size={size} />
40+
</StoryBook>
41+
);
42+
};

src/ActionIcon/demos/index.tsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { ActionIcon, ActionIconProps } from '@ant-design/pro-chat';
2+
import { StoryBook, useControls, useCreateStore } from '@lobehub/ui';
3+
import { folder } from 'leva';
4+
import * as LucideIcon from 'lucide-react';
5+
6+
export default () => {
7+
const store = useCreateStore();
8+
const control: ActionIconProps | any = useControls(
9+
{
10+
active: false,
11+
glass: false,
12+
icon: {
13+
options: LucideIcon,
14+
value: LucideIcon.Settings,
15+
},
16+
size: {
17+
options: ['large', 'normal', 'small'],
18+
value: 'large',
19+
},
20+
tooltip: folder({
21+
arrow: false,
22+
loading: false,
23+
placement: {
24+
options: [
25+
'top',
26+
'left',
27+
'right',
28+
'bottom',
29+
'topLeft',
30+
'topRight',
31+
'bottomLeft',
32+
'bottomRight',
33+
'leftTop',
34+
'leftBottom',
35+
'rightTop',
36+
'rightBottom',
37+
],
38+
value: 'top',
39+
},
40+
spotlight: false,
41+
title: '',
42+
}),
43+
},
44+
{ store },
45+
);
46+
47+
return (
48+
<StoryBook levaStore={store}>
49+
<ActionIcon {...control} />
50+
</StoryBook>
51+
);
52+
};

src/ActionIcon/index.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
nav: Components
3+
group:
4+
title: General
5+
order: -1
6+
title: ActionIcon
7+
description: ActionIcon is a component used to render an icon with a block around it
8+
---
9+
10+
## Default
11+
12+
Search icons in [`Lucide Icon`](https://lucide.dev/)
13+
14+
<code src="./demos/index.tsx" nopadding></code>
15+
16+
## CustomSize
17+
18+
<code src="./demos/CustomSize.tsx" nopadding></code>
19+
20+
## APIs
21+
22+
<API></API>

src/ActionIcon/index.tsx

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import { Loader2 } from 'lucide-react';
2+
import { forwardRef, useMemo } from 'react';
3+
4+
import Icon, { type IconProps } from '@/Icon';
5+
import Spotlight from '@/Spotlight';
6+
import Tooltip, { type TooltipProps } from '@/Tooltip';
7+
import { DivProps } from '@/types';
8+
9+
import { useStyles } from './style';
10+
11+
export type ActionIconSize =
12+
| 'large'
13+
| 'normal'
14+
| 'small'
15+
| 'site'
16+
| {
17+
blockSize?: number;
18+
borderRadius?: number;
19+
fontSize?: number;
20+
strokeWidth?: number;
21+
};
22+
23+
const calcSize = (size?: ActionIconSize) => {
24+
let blockSize: number;
25+
let borderRadius: number;
26+
27+
switch (size) {
28+
case 'large': {
29+
blockSize = 44;
30+
borderRadius = 8;
31+
break;
32+
}
33+
case 'normal': {
34+
blockSize = 36;
35+
borderRadius = 5;
36+
break;
37+
}
38+
case 'small': {
39+
blockSize = 24;
40+
borderRadius = 5;
41+
break;
42+
}
43+
case 'site': {
44+
blockSize = 34;
45+
borderRadius = 5;
46+
break;
47+
}
48+
default: {
49+
blockSize = size?.blockSize || 36;
50+
borderRadius = size?.borderRadius || 5;
51+
break;
52+
}
53+
}
54+
55+
return {
56+
blockSize,
57+
borderRadius,
58+
};
59+
};
60+
61+
export interface ActionIconProps extends DivProps {
62+
/**
63+
* @description Whether the icon is active or not
64+
* @default false
65+
*/
66+
active?: boolean;
67+
/**
68+
* @description Change arrow's visible state and change whether the arrow is pointed at the center of target.
69+
* @default false
70+
*/
71+
arrow?: boolean;
72+
color?: IconProps['color'];
73+
fill?: IconProps['fill'];
74+
/**
75+
* @description Glass blur style
76+
* @default 'false'
77+
*/
78+
glass?: boolean;
79+
/**
80+
* @description The icon element to be rendered
81+
* @type LucideIcon
82+
*/
83+
icon?: IconProps['icon'];
84+
/**
85+
* @description Set the loading status of ActionIcon
86+
*/
87+
loading?: boolean;
88+
89+
/**
90+
* @description The position of the tooltip relative to the target
91+
* @enum ["top","left","right","bottom","topLeft","topRight","bottomLeft","bottomRight","leftTop","leftBottom","rightTop","rightBottom"]
92+
* @default "top"
93+
*/
94+
placement?: TooltipProps['placement'];
95+
96+
/**
97+
* @description Size of the icon
98+
* @default 'normal'
99+
*/
100+
size?: ActionIconSize;
101+
/**
102+
* @description Whether add spotlight background
103+
* @default false
104+
*/
105+
spotlight?: boolean;
106+
/**
107+
* @description The text shown in the tooltip
108+
*/
109+
title?: string;
110+
/**
111+
* @description Mouse enter delay of tooltip
112+
* @default 0.5
113+
*/
114+
tooltipDelay?: number;
115+
}
116+
117+
const ActionIcon = forwardRef<HTMLDivElement, ActionIconProps>(
118+
(
119+
{
120+
color,
121+
fill,
122+
className,
123+
active,
124+
icon,
125+
size = 'normal',
126+
style,
127+
glass,
128+
title,
129+
placement,
130+
arrow = false,
131+
spotlight,
132+
onClick,
133+
children,
134+
loading,
135+
tooltipDelay = 0.5,
136+
...props
137+
},
138+
ref,
139+
) => {
140+
const { styles, cx } = useStyles({ active: Boolean(active), glass: Boolean(glass) });
141+
142+
const { blockSize, borderRadius } = useMemo(() => calcSize(size), [size]);
143+
144+
const content = (
145+
<>
146+
{icon && (
147+
<Icon
148+
className={styles.icon}
149+
color={color}
150+
fill={fill}
151+
icon={icon}
152+
size={size === 'site' ? 'normal' : size}
153+
/>
154+
)}
155+
{children}
156+
</>
157+
);
158+
159+
const spin = (
160+
<Icon color={color} icon={Loader2} size={size === 'site' ? 'normal' : size} spin />
161+
);
162+
163+
const actionIconBlock = (
164+
<div
165+
className={cx(styles.block, className)}
166+
onClick={loading ? undefined : onClick}
167+
ref={ref}
168+
style={{ borderRadius, height: blockSize, width: blockSize, ...style }}
169+
{...props}
170+
>
171+
{spotlight && <Spotlight />}
172+
{loading ? spin : content}
173+
</div>
174+
);
175+
176+
if (!title) return actionIconBlock;
177+
178+
return (
179+
<Tooltip
180+
arrow={arrow}
181+
mouseEnterDelay={tooltipDelay}
182+
overlayStyle={{ pointerEvents: 'none' }}
183+
placement={placement}
184+
title={title}
185+
>
186+
{actionIconBlock}
187+
</Tooltip>
188+
);
189+
},
190+
);
191+
192+
export default ActionIcon;

0 commit comments

Comments
 (0)