@akinon/ui-button 0.6.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,gBAAiB,YAAY,sBA0G/C,CAAC;AAEF,mBAAmB,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,gBAAiB,YAAY,sBAmJ/C,CAAC;AAEF,mBAAmB,SAAS,CAAC"}
package/dist/cjs/index.js CHANGED
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Button = void 0;
4
4
  const icons_1 = require("@akinon/icons");
5
5
  const ui_theme_1 = require("@akinon/ui-theme");
6
+ const ui_tooltip_1 = require("@akinon/ui-tooltip");
6
7
  const cssinjs_1 = require("@ant-design/cssinjs");
7
8
  const antd_1 = require("antd");
8
9
  const react_1 = require("react");
@@ -27,8 +28,9 @@ const Button = (buttonProps) => {
27
28
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
29
  theme: theme
29
30
  }, () => {
30
- var _a, _b, _c, _d, _e, _f, _g, _h;
31
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
31
32
  const prefixCls = `:where(.${hashId}).${getPrefixCls()}-btn`;
33
+ const iconPrefixCls = `.${getPrefixCls()}-btn`;
32
34
  // MARK: - Disabled
33
35
  const disabledStyles = {
34
36
  '&:disabled, &-disabled': {
@@ -78,11 +80,47 @@ const Button = (buttonProps) => {
78
80
  [`${prefixCls}-warning`]: Object.assign({ backgroundColor: (_e = buttonToken.colorWarningBg) !== null && _e !== void 0 ? _e : token.colorWarningBg, color: (_f = buttonToken.colorWarningText) !== null && _f !== void 0 ? _f : token.colorWarningText, '&:hover:not(:disabled)': {
79
81
  backgroundColor: (_g = buttonToken.colorWarningHover) !== null && _g !== void 0 ? _g : token.colorWarningHover,
80
82
  borderColor: (_h = buttonToken.colorWarningBorder) !== null && _h !== void 0 ? _h : token.colorWarningBorder
81
- } }, disabledStyles)
83
+ } }, disabledStyles),
82
84
  // END: Warning
85
+ // MARK: Icon
86
+ [`${prefixCls}-icon`]: {
87
+ ['> *']: {
88
+ backgroundColor: 'transparent',
89
+ // Since this button is transparent, we are using success bg color for the icon.
90
+ color: (_j = buttonToken.colorSuccessBg) !== null && _j !== void 0 ? _j : token.colorSuccessBg,
91
+ verticalAlign: 'middle',
92
+ '&:hover:not(:disabled)': {
93
+ color: (_k = buttonToken.colorSuccessBg) !== null && _k !== void 0 ? _k : token.colorSuccessBg
94
+ },
95
+ '&:active': {
96
+ boxShadow: 'none'
97
+ }
98
+ },
99
+ '&:disabled': {
100
+ opacity: 0.4
101
+ },
102
+ [`&${iconPrefixCls}-dangerous > *`]: {
103
+ color: 'red',
104
+ '&:hover:not(:disabled)': {
105
+ color: (_l = buttonToken.colorErrorHover) !== null && _l !== void 0 ? _l : token.colorErrorHover
106
+ }
107
+ }
108
+ }
109
+ // END: Icon
83
110
  };
84
111
  });
85
- // MARK: - Render
86
- return useStyle(react_1.default.createElement(antd_1.Button, Object.assign({}, buttonProps, { icon: react_1.default.createElement(icons_1.Icon, { icon: buttonProps.icon, size: 12, style: { lineHeight: 0 } }) }), buttonProps.children));
112
+ const renderButton = () => {
113
+ var _a;
114
+ return (react_1.default.createElement(antd_1.Button, Object.assign({}, buttonProps, { icon: buttonProps.icon ? (react_1.default.createElement(icons_1.Icon, { icon: buttonProps.icon, size: (_a = buttonProps.iconSize) !== null && _a !== void 0 ? _a : 12, style: { lineHeight: 0 } })) : undefined }), buttonProps.children));
115
+ };
116
+ // If tooltip prop is provided, wrap the button with Tooltip
117
+ if (buttonProps.tooltip) {
118
+ const tooltipProps = typeof buttonProps.tooltip === 'string'
119
+ ? { title: buttonProps.tooltip }
120
+ : buttonProps.tooltip;
121
+ return useStyle(react_1.default.createElement(ui_tooltip_1.Tooltip, Object.assign({}, tooltipProps), renderButton()));
122
+ }
123
+ // If no tooltip, return the button as is
124
+ return useStyle(renderButton());
87
125
  };
88
126
  exports.Button = Button;
@@ -0,0 +1,127 @@
1
+ import type { IconName } from '@akinon/icons';
2
+ import { DO_NOT_USE_OR_YOU_WILL_BE_FIRED_INTERNAL_STYLE } from '@akinon/ui-theme';
3
+ import { TooltipProps } from '@akinon/ui-tooltip';
4
+
5
+ // TODO: contribute antd to extend the types properly
6
+ export type TButtonType =
7
+ | 'default'
8
+ | 'primary'
9
+ | 'text'
10
+ | 'link'
11
+ | 'success'
12
+ | 'warning'
13
+ | 'icon';
14
+
15
+ type TMergedHTMLAttributes = React.HTMLAttributes<HTMLElement> &
16
+ React.ButtonHTMLAttributes<HTMLButtonElement> &
17
+ React.AnchorHTMLAttributes<HTMLAnchorElement>;
18
+
19
+ // TODO: contribute antd to generate TS docgen with descriptions
20
+ /**
21
+ * The props of the Button component.
22
+ */
23
+
24
+ export interface IButtonProps extends TMergedHTMLAttributes {
25
+ /**
26
+ * The type of the button. Note that this is different from the html type.
27
+ * @default default
28
+ */
29
+ type?: TButtonType;
30
+
31
+ /**
32
+ * The href of the button. If provided, the button will be rendered as an anchor (`<a>`) tag.
33
+ */
34
+ href?: string;
35
+
36
+ /**
37
+ * The HTML type of the button. Note that this is different from the `type`.
38
+ * See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#type
39
+ */
40
+ htmlType?: HTMLButtonElement['type'];
41
+
42
+ /**
43
+ * The size of the button. `middle` is strongly recommended due to the Akinon design system.
44
+ * Do not use this prop except for special cases.
45
+ * @default middle
46
+ */
47
+ size?: 'middle' | 'small';
48
+
49
+ /**
50
+ * onClick handler.
51
+ * @param event
52
+ * @returns
53
+ */
54
+ onClick?: (event: React.MouseEvent) => void;
55
+
56
+ /**
57
+ * The icon name of the button. Only icons from `akinon/icons` are supported.
58
+ * If there is no icon which you want to use, please open an issue.
59
+ */
60
+ icon?: IconName;
61
+
62
+ /**
63
+ * The position of the icon. Only applicable when icon is defined.
64
+ * @default start
65
+ */
66
+ iconPosition?: icon extends IconName ? 'start' | 'end' : never;
67
+
68
+ /**
69
+ * The size of the icon. Only applicable when icon is defined.
70
+ * @default 12
71
+ */
72
+ iconSize?: number;
73
+ /**
74
+ * Whether the button is in disabled state.
75
+ * @default false
76
+ */
77
+ disabled?: boolean;
78
+
79
+ /**
80
+ * Whether the button is in loading state. If delay is provided, the loading state will be shown after the delay in ms.
81
+ * @default false
82
+ */
83
+ loading?:
84
+ | boolean
85
+ | {
86
+ delay?: number;
87
+ };
88
+
89
+ /**
90
+ * Whether the button is ghost.
91
+ * Recommended for use with `icon` prop without text due to the Akinon design system.
92
+ * @default false
93
+ */
94
+ ghost?: boolean;
95
+
96
+ /**
97
+ * Whether the button is danger.
98
+ * @default false
99
+ */
100
+ danger?: boolean;
101
+
102
+ /**
103
+ * Whether the button is block which means it will take the full width of its container.
104
+ * @default false
105
+ */
106
+ block?: boolean;
107
+
108
+ /**
109
+ * The children of the button. `string` is strongly recommended due to the Akinon design system.
110
+ */
111
+ children?: React.ReactNode;
112
+
113
+ /**
114
+ * The data attributes of the button.
115
+ */
116
+ [key: `data-${string}`]: string;
117
+
118
+ /**
119
+ * Never use this prop. Akinon design system does not allow custom styles.
120
+ * @ignore
121
+ */
122
+ style?: DO_NOT_USE_OR_YOU_WILL_BE_FIRED_INTERNAL_STYLE;
123
+ /**
124
+ * The tooltip of the button.
125
+ */
126
+ tooltip?: string | TooltipProps;
127
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,gBAAiB,YAAY,sBA0G/C,CAAC;AAEF,mBAAmB,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,gBAAiB,YAAY,sBAmJ/C,CAAC;AAEF,mBAAmB,SAAS,CAAC"}
package/dist/esm/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Icon } from '@akinon/icons';
2
2
  import { useToken } from '@akinon/ui-theme';
3
+ import { Tooltip } from '@akinon/ui-tooltip';
3
4
  import { useStyleRegister } from '@ant-design/cssinjs';
4
5
  import { Button as AntButton, ConfigProvider } from 'antd';
5
6
  import React from 'react';
@@ -24,8 +25,9 @@ export const Button = (buttonProps) => {
24
25
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
26
  theme: theme
26
27
  }, () => {
27
- var _a, _b, _c, _d, _e, _f, _g, _h;
28
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
28
29
  const prefixCls = `:where(.${hashId}).${getPrefixCls()}-btn`;
30
+ const iconPrefixCls = `.${getPrefixCls()}-btn`;
29
31
  // MARK: - Disabled
30
32
  const disabledStyles = {
31
33
  '&:disabled, &-disabled': {
@@ -75,10 +77,46 @@ export const Button = (buttonProps) => {
75
77
  [`${prefixCls}-warning`]: Object.assign({ backgroundColor: (_e = buttonToken.colorWarningBg) !== null && _e !== void 0 ? _e : token.colorWarningBg, color: (_f = buttonToken.colorWarningText) !== null && _f !== void 0 ? _f : token.colorWarningText, '&:hover:not(:disabled)': {
76
78
  backgroundColor: (_g = buttonToken.colorWarningHover) !== null && _g !== void 0 ? _g : token.colorWarningHover,
77
79
  borderColor: (_h = buttonToken.colorWarningBorder) !== null && _h !== void 0 ? _h : token.colorWarningBorder
78
- } }, disabledStyles)
80
+ } }, disabledStyles),
79
81
  // END: Warning
82
+ // MARK: Icon
83
+ [`${prefixCls}-icon`]: {
84
+ ['> *']: {
85
+ backgroundColor: 'transparent',
86
+ // Since this button is transparent, we are using success bg color for the icon.
87
+ color: (_j = buttonToken.colorSuccessBg) !== null && _j !== void 0 ? _j : token.colorSuccessBg,
88
+ verticalAlign: 'middle',
89
+ '&:hover:not(:disabled)': {
90
+ color: (_k = buttonToken.colorSuccessBg) !== null && _k !== void 0 ? _k : token.colorSuccessBg
91
+ },
92
+ '&:active': {
93
+ boxShadow: 'none'
94
+ }
95
+ },
96
+ '&:disabled': {
97
+ opacity: 0.4
98
+ },
99
+ [`&${iconPrefixCls}-dangerous > *`]: {
100
+ color: 'red',
101
+ '&:hover:not(:disabled)': {
102
+ color: (_l = buttonToken.colorErrorHover) !== null && _l !== void 0 ? _l : token.colorErrorHover
103
+ }
104
+ }
105
+ }
106
+ // END: Icon
80
107
  };
81
108
  });
82
- // MARK: - Render
83
- return useStyle(React.createElement(AntButton, Object.assign({}, buttonProps, { icon: React.createElement(Icon, { icon: buttonProps.icon, size: 12, style: { lineHeight: 0 } }) }), buttonProps.children));
109
+ const renderButton = () => {
110
+ var _a;
111
+ return (React.createElement(AntButton, Object.assign({}, buttonProps, { icon: buttonProps.icon ? (React.createElement(Icon, { icon: buttonProps.icon, size: (_a = buttonProps.iconSize) !== null && _a !== void 0 ? _a : 12, style: { lineHeight: 0 } })) : undefined }), buttonProps.children));
112
+ };
113
+ // If tooltip prop is provided, wrap the button with Tooltip
114
+ if (buttonProps.tooltip) {
115
+ const tooltipProps = typeof buttonProps.tooltip === 'string'
116
+ ? { title: buttonProps.tooltip }
117
+ : buttonProps.tooltip;
118
+ return useStyle(React.createElement(Tooltip, Object.assign({}, tooltipProps), renderButton()));
119
+ }
120
+ // If no tooltip, return the button as is
121
+ return useStyle(renderButton());
84
122
  };
@@ -0,0 +1,127 @@
1
+ import type { IconName } from '@akinon/icons';
2
+ import { DO_NOT_USE_OR_YOU_WILL_BE_FIRED_INTERNAL_STYLE } from '@akinon/ui-theme';
3
+ import { TooltipProps } from '@akinon/ui-tooltip';
4
+
5
+ // TODO: contribute antd to extend the types properly
6
+ export type TButtonType =
7
+ | 'default'
8
+ | 'primary'
9
+ | 'text'
10
+ | 'link'
11
+ | 'success'
12
+ | 'warning'
13
+ | 'icon';
14
+
15
+ type TMergedHTMLAttributes = React.HTMLAttributes<HTMLElement> &
16
+ React.ButtonHTMLAttributes<HTMLButtonElement> &
17
+ React.AnchorHTMLAttributes<HTMLAnchorElement>;
18
+
19
+ // TODO: contribute antd to generate TS docgen with descriptions
20
+ /**
21
+ * The props of the Button component.
22
+ */
23
+
24
+ export interface IButtonProps extends TMergedHTMLAttributes {
25
+ /**
26
+ * The type of the button. Note that this is different from the html type.
27
+ * @default default
28
+ */
29
+ type?: TButtonType;
30
+
31
+ /**
32
+ * The href of the button. If provided, the button will be rendered as an anchor (`<a>`) tag.
33
+ */
34
+ href?: string;
35
+
36
+ /**
37
+ * The HTML type of the button. Note that this is different from the `type`.
38
+ * See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#type
39
+ */
40
+ htmlType?: HTMLButtonElement['type'];
41
+
42
+ /**
43
+ * The size of the button. `middle` is strongly recommended due to the Akinon design system.
44
+ * Do not use this prop except for special cases.
45
+ * @default middle
46
+ */
47
+ size?: 'middle' | 'small';
48
+
49
+ /**
50
+ * onClick handler.
51
+ * @param event
52
+ * @returns
53
+ */
54
+ onClick?: (event: React.MouseEvent) => void;
55
+
56
+ /**
57
+ * The icon name of the button. Only icons from `akinon/icons` are supported.
58
+ * If there is no icon which you want to use, please open an issue.
59
+ */
60
+ icon?: IconName;
61
+
62
+ /**
63
+ * The position of the icon. Only applicable when icon is defined.
64
+ * @default start
65
+ */
66
+ iconPosition?: icon extends IconName ? 'start' | 'end' : never;
67
+
68
+ /**
69
+ * The size of the icon. Only applicable when icon is defined.
70
+ * @default 12
71
+ */
72
+ iconSize?: number;
73
+ /**
74
+ * Whether the button is in disabled state.
75
+ * @default false
76
+ */
77
+ disabled?: boolean;
78
+
79
+ /**
80
+ * Whether the button is in loading state. If delay is provided, the loading state will be shown after the delay in ms.
81
+ * @default false
82
+ */
83
+ loading?:
84
+ | boolean
85
+ | {
86
+ delay?: number;
87
+ };
88
+
89
+ /**
90
+ * Whether the button is ghost.
91
+ * Recommended for use with `icon` prop without text due to the Akinon design system.
92
+ * @default false
93
+ */
94
+ ghost?: boolean;
95
+
96
+ /**
97
+ * Whether the button is danger.
98
+ * @default false
99
+ */
100
+ danger?: boolean;
101
+
102
+ /**
103
+ * Whether the button is block which means it will take the full width of its container.
104
+ * @default false
105
+ */
106
+ block?: boolean;
107
+
108
+ /**
109
+ * The children of the button. `string` is strongly recommended due to the Akinon design system.
110
+ */
111
+ children?: React.ReactNode;
112
+
113
+ /**
114
+ * The data attributes of the button.
115
+ */
116
+ [key: `data-${string}`]: string;
117
+
118
+ /**
119
+ * Never use this prop. Akinon design system does not allow custom styles.
120
+ * @ignore
121
+ */
122
+ style?: DO_NOT_USE_OR_YOU_WILL_BE_FIRED_INTERNAL_STYLE;
123
+ /**
124
+ * The tooltip of the button.
125
+ */
126
+ tooltip?: string | TooltipProps;
127
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akinon/ui-button",
3
- "version": "0.6.0",
3
+ "version": "1.0.0",
4
4
  "private": false,
5
5
  "description": "A basic button react component.",
6
6
  "type": "module",
@@ -10,16 +10,17 @@
10
10
  "dist"
11
11
  ],
12
12
  "dependencies": {
13
- "antd": "5.17.0",
14
- "@akinon/ui-theme": "0.6.0",
15
- "@akinon/icons": "0.5.0"
13
+ "antd": "5.22.6",
14
+ "@akinon/icons": "1.0.0",
15
+ "@akinon/ui-tooltip": "1.0.0",
16
+ "@akinon/ui-theme": "1.0.0"
16
17
  },
17
18
  "devDependencies": {
18
19
  "clean-package": "2.2.0",
19
20
  "copyfiles": "^2.4.1",
20
21
  "rimraf": "^5.0.5",
21
- "typescript": "^5.2.2",
22
- "@akinon/typescript-config": "0.3.0"
22
+ "typescript": "*",
23
+ "@akinon/typescript-config": "1.0.0"
23
24
  },
24
25
  "peerDependencies": {
25
26
  "react": ">=18",
@@ -39,7 +40,7 @@
39
40
  "build": "pnpm run build:esm && pnpm run build:commonjs && pnpm run copy:files",
40
41
  "build:esm": "tsc --outDir dist/esm",
41
42
  "build:commonjs": "tsc --module commonjs --outDir dist/cjs",
42
- "copy:files": "copyfiles -u 1 src/**/*.css dist/esm && copyfiles -u 1 src/**/*.css dist/cjs",
43
+ "copy:files": "copyfiles -u 1 \"src/**/*.!(ts|tsx)\" dist/esm && copyfiles -u 1 \"src/**/*.!(ts|tsx)\" dist/cjs",
43
44
  "clean": "rimraf dist/",
44
45
  "typecheck": "tsc --noEmit"
45
46
  }