@fibery/ui-kit 1.4.1 → 1.7.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/index.ts +0 -1
- package/package.json +39 -23
- package/src/Item.tsx +8 -2
- package/src/Pallete.ts +191 -191
- package/src/Select/components.tsx +22 -21
- package/src/Select/index.tsx +98 -30
- package/src/Select/select-control-settings-context.tsx +20 -0
- package/src/Select/select-in-popover.tsx +333 -0
- package/src/Select/styles.ts +27 -1
- package/src/ThemeProvider.tsx +1 -1
- package/src/antd/styles.ts +5 -7
- package/src/designSystem.ts +129 -91
- package/src/error-alert.tsx +2 -2
- package/src/icons/Icon.tsx +17 -12
- package/src/icons/ast/AddGroup.ts +8 -0
- package/src/icons/ast/AiAssistant.ts +8 -0
- package/src/icons/ast/AiAvatar.ts +8 -0
- package/src/icons/ast/ArrowBottom.ts +1 -1
- package/src/icons/ast/ArrowCollapse.ts +1 -1
- package/src/icons/ast/ArrowCollapseVertical.ts +1 -1
- package/src/icons/ast/ArrowLeft.ts +1 -1
- package/src/icons/ast/ArrowRight.ts +1 -1
- package/src/icons/ast/ArrowTop.ts +1 -1
- package/src/icons/ast/Atom.ts +8 -0
- package/src/icons/ast/Copy.ts +8 -0
- package/src/icons/ast/DynamicFilterValue.ts +8 -0
- package/src/icons/ast/ExtensionAssignments.ts +1 -1
- package/src/icons/ast/FileUpload.ts +8 -0
- package/src/icons/ast/FormWithCover.ts +8 -0
- package/src/icons/ast/FormWithoutCover.ts +8 -0
- package/src/icons/ast/Github.ts +3 -27
- package/src/icons/ast/Gitlab.ts +3 -25
- package/src/icons/ast/Hint.ts +1 -1
- package/src/icons/ast/Jira.ts +8 -0
- package/src/icons/ast/Markdown.ts +8 -0
- package/src/icons/ast/Minus.ts +8 -0
- package/src/icons/ast/MoreCompact.ts +1 -1
- package/src/icons/ast/RicheditorBlockFile.ts +8 -0
- package/src/icons/ast/RicheditorBlockH4.ts +1 -1
- package/src/icons/ast/SimpleCompass.ts +8 -0
- package/src/icons/ast/Templates.ts +8 -0
- package/src/icons/ast/TypeLocation.ts +8 -0
- package/src/icons/ast/ViewForm.ts +8 -0
- package/src/icons/ast/ViewMap.ts +8 -0
- package/src/icons/ast/index.tsx +199 -181
- package/src/icons/react/AddGroup.tsx +12 -0
- package/src/icons/react/AiAssistant.tsx +12 -0
- package/src/icons/react/AiAvatar.tsx +12 -0
- package/src/icons/react/Atom.tsx +12 -0
- package/src/icons/react/Copy.tsx +12 -0
- package/src/icons/react/DynamicFilterValue.tsx +12 -0
- package/src/icons/react/FileUpload.tsx +12 -0
- package/src/icons/react/FormWithCover.tsx +12 -0
- package/src/icons/react/FormWithoutCover.tsx +12 -0
- package/src/icons/react/Github.tsx +8 -6
- package/src/icons/react/Gitlab.tsx +8 -6
- package/src/icons/react/Jira.tsx +12 -0
- package/src/icons/react/Markdown.tsx +12 -0
- package/src/icons/react/Minus.tsx +12 -0
- package/src/icons/react/RicheditorBlockFile.tsx +12 -0
- package/src/icons/react/SimpleCompass.tsx +12 -0
- package/src/icons/react/Templates.tsx +12 -0
- package/src/icons/react/TypeLocation.tsx +12 -0
- package/src/icons/react/ViewForm.tsx +12 -0
- package/src/icons/react/ViewMap.tsx +12 -0
- package/src/icons/react/index.tsx +199 -181
- package/src/tooltip.tsx +132 -152
- package/src/Button.d.ts +0 -26
- package/src/Button.js +0 -360
- package/src/antd/ant-tooltip.tsx +0 -5
- package/src/icons/IconAsBackground.tsx +0 -15
package/src/tooltip.tsx
CHANGED
|
@@ -1,184 +1,164 @@
|
|
|
1
|
-
import {css} from "@linaria/core";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {css, cx} from "@linaria/core";
|
|
2
|
+
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
|
3
|
+
import type {ReactNode, SyntheticEvent} from "react";
|
|
4
|
+
import {border, lineHeight, space, themeVars, tooltipDelay} from "./designSystem";
|
|
5
|
+
|
|
6
|
+
const preventDefaultAndStopPropagation = (e: SyntheticEvent) => {
|
|
7
|
+
e.preventDefault();
|
|
8
|
+
e.stopPropagation();
|
|
9
|
+
};
|
|
7
10
|
|
|
8
11
|
const titleStyle = css`
|
|
9
|
-
${
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
opacity: opacity.opacity90,
|
|
13
|
-
}}
|
|
12
|
+
color: ${themeVars.whiteColor};
|
|
13
|
+
line-height: ${lineHeight.heading};
|
|
14
|
+
font-weight: 500;
|
|
14
15
|
`;
|
|
15
16
|
|
|
16
17
|
const descriptionStyle = css`
|
|
17
|
-
${
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}}
|
|
18
|
+
color: ${themeVars.shortcutTextColor};
|
|
19
|
+
line-height: ${lineHeight.heading};
|
|
20
|
+
font-weight: 400;
|
|
21
21
|
`;
|
|
22
22
|
|
|
23
23
|
const tooltipStyle = css`
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
24
|
+
font-size: 13px;
|
|
25
|
+
color: ${themeVars.whiteColor};
|
|
26
|
+
z-index: 100000;
|
|
27
|
+
min-height: 30px;
|
|
28
|
+
max-width: 300px;
|
|
29
|
+
background-color: ${themeVars.tooltipBgColor};
|
|
30
|
+
padding: ${space.s}px ${space.m}px;
|
|
31
|
+
border-radius: ${border.radius6}px;
|
|
32
|
+
box-shadow: ${themeVars.actionMenuShadow};
|
|
33
|
+
|
|
34
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
35
|
+
@keyframes zoomIn {
|
|
36
|
+
from {
|
|
37
|
+
opacity: 0;
|
|
38
|
+
transform: scale(0.8);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
to {
|
|
42
|
+
opacity: 1;
|
|
43
|
+
transform: scale(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@keyframes zoomOut {
|
|
48
|
+
from {
|
|
49
|
+
transform: scale(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
to {
|
|
53
|
+
opacity: 0;
|
|
54
|
+
transform: scale(0.8);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
will-change: transform, opacity;
|
|
59
|
+
transform-origin: var(--radix-tooltip-content-transform-origin);
|
|
60
|
+
animation-duration: 0.1s;
|
|
61
|
+
|
|
62
|
+
&[data-state="delayed-open"] {
|
|
63
|
+
animation-name: zoomIn;
|
|
64
|
+
animation-timing-function: ease-out;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
40
67
|
`;
|
|
41
68
|
|
|
42
69
|
const whiteBgStyle = css`
|
|
43
|
-
${
|
|
44
|
-
|
|
45
|
-
backgroundColor: themeVars.actionMenuInnerBg,
|
|
46
|
-
color: themeVars.textColor,
|
|
47
|
-
},
|
|
48
|
-
}}
|
|
70
|
+
background-color: ${themeVars.actionMenuInnerBg};
|
|
71
|
+
color: ${themeVars.textColor};
|
|
49
72
|
`;
|
|
50
73
|
|
|
51
|
-
type AlignPoint = string;
|
|
52
|
-
|
|
53
|
-
export interface AlignType {
|
|
54
|
-
/**
|
|
55
|
-
* move point of source node to align with point of target node.
|
|
56
|
-
* Such as ['tr','cc'], align top right point of source node with center point of target node.
|
|
57
|
-
* Point can be 't'(top), 'b'(bottom), 'c'(center), 'l'(left), 'r'(right) */
|
|
58
|
-
points?: AlignPoint[];
|
|
59
|
-
/**
|
|
60
|
-
* offset source node by offset[0] in x and offset[1] in y.
|
|
61
|
-
* If offset contains percentage string value, it is relative to sourceNode region.
|
|
62
|
-
*/
|
|
63
|
-
offset?: number[];
|
|
64
|
-
/**
|
|
65
|
-
* offset target node by offset[0] in x and offset[1] in y.
|
|
66
|
-
* If targetOffset contains percentage string value, it is relative to targetNode region.
|
|
67
|
-
*/
|
|
68
|
-
targetOffset?: number[];
|
|
69
|
-
/**
|
|
70
|
-
* If adjustX field is true, will adjust source node in x direction if source node is invisible.
|
|
71
|
-
* If adjustY field is true, will adjust source node in y direction if source node is invisible.
|
|
72
|
-
*/
|
|
73
|
-
overflow?: {
|
|
74
|
-
adjustX?: boolean | number;
|
|
75
|
-
adjustY?: boolean | number;
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Whether use css right instead of left to position
|
|
79
|
-
*/
|
|
80
|
-
useCssRight?: boolean;
|
|
81
|
-
/**
|
|
82
|
-
* Whether use css bottom instead of top to position
|
|
83
|
-
*/
|
|
84
|
-
useCssBottom?: boolean;
|
|
85
|
-
/**
|
|
86
|
-
* Whether use css transform instead of left/top/right/bottom to position if browser supports.
|
|
87
|
-
* Defaults to false.
|
|
88
|
-
*/
|
|
89
|
-
useCssTransform?: boolean;
|
|
90
|
-
ignoreShake?: boolean;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const alignByPlacement = {
|
|
94
|
-
bottom: {offset: [0, -2] as [number, number]},
|
|
95
|
-
};
|
|
96
|
-
|
|
97
74
|
export const TooltipTitle = ({children}: {children: ReactNode}) => <div className={titleStyle}>{children}</div>;
|
|
98
75
|
export const TooltipDescription = ({children}: {children: ReactNode}) => (
|
|
99
76
|
<div className={descriptionStyle}>{children}</div>
|
|
100
77
|
);
|
|
101
78
|
|
|
102
|
-
export
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
);
|
|
115
|
-
}
|
|
79
|
+
export const TooltipContent = ({title, shortcut}: {title: string; shortcut?: string}) => (
|
|
80
|
+
<div
|
|
81
|
+
className={css`
|
|
82
|
+
display: flex;
|
|
83
|
+
flex-direction: column;
|
|
84
|
+
align-items: center;
|
|
85
|
+
`}
|
|
86
|
+
>
|
|
87
|
+
<TooltipTitle>{title}</TooltipTitle>
|
|
88
|
+
{shortcut ? <TooltipDescription>{shortcut}</TooltipDescription> : null}
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
116
91
|
|
|
117
|
-
|
|
92
|
+
export const TooltipProvider: React.FC<TooltipPrimitive.TooltipProviderProps> = (props) => (
|
|
93
|
+
<TooltipPrimitive.Provider disableHoverableContent skipDelayDuration={150} {...props} />
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
export type TooltipProps = {
|
|
118
97
|
title?: ReactNode;
|
|
119
98
|
description?: ReactNode;
|
|
120
99
|
content?: ReactNode;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
100
|
+
side?: TooltipPrimitive.TooltipContentProps["side"];
|
|
101
|
+
sideOffset?: TooltipPrimitive.TooltipContentProps["sideOffset"];
|
|
102
|
+
align?: TooltipPrimitive.TooltipContentProps["align"];
|
|
103
|
+
alignOffset?: TooltipPrimitive.TooltipContentProps["alignOffset"];
|
|
125
104
|
instant?: boolean;
|
|
126
|
-
|
|
127
|
-
children: JSX.Element | string;
|
|
105
|
+
children: ReactNode;
|
|
128
106
|
whiteBg?: boolean;
|
|
107
|
+
visible?: boolean;
|
|
129
108
|
onVisibleChange?: (visible: boolean) => void;
|
|
130
|
-
|
|
131
|
-
|
|
109
|
+
disabled?: boolean;
|
|
110
|
+
/** should keep tooltip visible after click */
|
|
111
|
+
keepOnClick?: boolean;
|
|
132
112
|
};
|
|
133
113
|
|
|
134
|
-
export
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
114
|
+
export const Tooltip: React.FC<TooltipProps> = ({
|
|
115
|
+
title,
|
|
116
|
+
description,
|
|
117
|
+
content = (title || description) && (
|
|
118
|
+
<>
|
|
119
|
+
<TooltipTitle>{title}</TooltipTitle>
|
|
120
|
+
<TooltipDescription>{description}</TooltipDescription>
|
|
121
|
+
</>
|
|
122
|
+
),
|
|
123
|
+
side,
|
|
124
|
+
sideOffset = space.xs,
|
|
125
|
+
align,
|
|
126
|
+
alignOffset,
|
|
127
|
+
instant,
|
|
128
|
+
children,
|
|
129
|
+
whiteBg,
|
|
130
|
+
visible,
|
|
131
|
+
onVisibleChange,
|
|
132
|
+
keepOnClick,
|
|
133
|
+
disabled,
|
|
134
|
+
}) => {
|
|
135
|
+
const triggerProps = keepOnClick
|
|
136
|
+
? {
|
|
137
|
+
onPointerDown: preventDefaultAndStopPropagation,
|
|
138
|
+
onClick: preventDefaultAndStopPropagation,
|
|
139
|
+
}
|
|
140
|
+
: null;
|
|
157
141
|
|
|
158
142
|
return (
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
placement={placement}
|
|
164
|
-
mouseEnterDelay={mouseEnterDelay || (instant ? 0 : tooltipDelay.enter)}
|
|
165
|
-
mouseLeaveDelay={instant ? 0 : tooltipDelay.leave}
|
|
166
|
-
overlayClassName={cx(tooltipStyle, {[whiteBgStyle]: whiteBg})}
|
|
167
|
-
align={align || (placement === "bottom" ? alignByPlacement.bottom : undefined)}
|
|
168
|
-
onVisibleChange={onVisibleChange}
|
|
169
|
-
destroyTooltipOnHide={destroyTooltipOnHide}
|
|
170
|
-
getPopupContainer={getPopupContainer}
|
|
143
|
+
<TooltipPrimitive.Root
|
|
144
|
+
delayDuration={instant ? 0 : tooltipDelay.enter}
|
|
145
|
+
open={disabled ? false : Boolean(content) && visible}
|
|
146
|
+
onOpenChange={onVisibleChange}
|
|
171
147
|
>
|
|
172
|
-
{
|
|
173
|
-
|
|
148
|
+
<TooltipPrimitive.Trigger {...triggerProps} asChild>
|
|
149
|
+
{children}
|
|
150
|
+
</TooltipPrimitive.Trigger>
|
|
151
|
+
<TooltipPrimitive.Portal>
|
|
152
|
+
<TooltipPrimitive.Content
|
|
153
|
+
side={side}
|
|
154
|
+
sideOffset={sideOffset}
|
|
155
|
+
align={align}
|
|
156
|
+
alignOffset={alignOffset}
|
|
157
|
+
className={cx(tooltipStyle, whiteBg && whiteBgStyle)}
|
|
158
|
+
>
|
|
159
|
+
{content}
|
|
160
|
+
</TooltipPrimitive.Content>
|
|
161
|
+
</TooltipPrimitive.Portal>
|
|
162
|
+
</TooltipPrimitive.Root>
|
|
174
163
|
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
Tooltip.propTypes = {
|
|
178
|
-
title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
179
|
-
description: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
|
180
|
-
content: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
|
181
|
-
placement: PropTypes.string,
|
|
182
|
-
visible: PropTypes.bool,
|
|
183
|
-
instant: PropTypes.bool,
|
|
184
164
|
};
|
package/src/Button.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type {ComponentPropsWithRef, FunctionComponent} from "react";
|
|
2
|
-
import {IconBaseProps} from "./icons/types";
|
|
3
|
-
type Size = ":button-size/super-small" | ":button-size/small" | ":button-size/normal" | ":button-size/big";
|
|
4
|
-
type Props = {
|
|
5
|
-
size?: Size;
|
|
6
|
-
borderless?: boolean;
|
|
7
|
-
Icon?: ((props: IconBaseProps) => JSX.Element) | null;
|
|
8
|
-
color?: string;
|
|
9
|
-
primary?: boolean;
|
|
10
|
-
pending?: boolean;
|
|
11
|
-
width?: string | number;
|
|
12
|
-
height?: string | number;
|
|
13
|
-
} & Omit<ComponentPropsWithRef<"button">, "size" | "width" | "height">;
|
|
14
|
-
|
|
15
|
-
export const Button: FunctionComponent<Props>;
|
|
16
|
-
export const buttonClassName: string;
|
|
17
|
-
|
|
18
|
-
export const ActionsButton: FunctionComponent<{
|
|
19
|
-
inverted?: boolean;
|
|
20
|
-
label?: string;
|
|
21
|
-
color?: string;
|
|
22
|
-
onClick?: Props["onClick"];
|
|
23
|
-
}>;
|
|
24
|
-
export const ActionsButtonCompact: FunctionComponent<
|
|
25
|
-
{inverted?: boolean} & Omit<Props, "color" | "borderless" | "Icon" | "size">
|
|
26
|
-
>;
|
package/src/Button.js
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
import {hasNonEmptyChild} from "@fibery/react/src/has-non-empty-child";
|
|
2
|
-
import {css} from "@linaria/core";
|
|
3
|
-
import {styled} from "@linaria/react";
|
|
4
|
-
import cx from "classnames";
|
|
5
|
-
import _ from "lodash";
|
|
6
|
-
import PropTypes from "prop-types";
|
|
7
|
-
import {forwardRef} from "react";
|
|
8
|
-
import {border, colors, fontWeight, getDarkenColor, getOpacities, opacity, textStyles, themeVars} from "./designSystem";
|
|
9
|
-
import MoreIcon from "./icons/react/More";
|
|
10
|
-
import MoreCompactIcon from "./icons/react/MoreCompact";
|
|
11
|
-
import {Item} from "./Item";
|
|
12
|
-
import {Spinner} from "./loaders";
|
|
13
|
-
import {useTheme} from "./ThemeProvider";
|
|
14
|
-
|
|
15
|
-
const baseSize = 14;
|
|
16
|
-
|
|
17
|
-
const fontSizes = {
|
|
18
|
-
":button-size/super-small": baseSize - 4,
|
|
19
|
-
":button-size/small": baseSize - 2,
|
|
20
|
-
":button-size/normal": baseSize,
|
|
21
|
-
":button-size/big": baseSize + 2,
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const sizeShifts = {
|
|
25
|
-
":button-size/super-small": -2,
|
|
26
|
-
":button-size/small": -1,
|
|
27
|
-
":button-size/normal": 0,
|
|
28
|
-
":button-size/big": 1,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
const buttonBorderWidth = 1;
|
|
32
|
-
|
|
33
|
-
const staticButtonStyle = css`
|
|
34
|
-
${{
|
|
35
|
-
boxSizing: "border-box",
|
|
36
|
-
display: "flex",
|
|
37
|
-
justifyContent: "center",
|
|
38
|
-
alignItems: "center",
|
|
39
|
-
verticalAlign: "middle",
|
|
40
|
-
fontWeight: fontWeight.bold,
|
|
41
|
-
lineHeight: 1,
|
|
42
|
-
margin: 0,
|
|
43
|
-
borderRadius: border.radius6,
|
|
44
|
-
borderWidth: buttonBorderWidth,
|
|
45
|
-
borderStyle: "solid",
|
|
46
|
-
outline: "none",
|
|
47
|
-
position: "relative",
|
|
48
|
-
}}
|
|
49
|
-
`;
|
|
50
|
-
|
|
51
|
-
const ordersInGroup = {
|
|
52
|
-
first: css`
|
|
53
|
-
&.${staticButtonStyle} {
|
|
54
|
-
${{
|
|
55
|
-
display: "inline-flex",
|
|
56
|
-
borderRadius: `${border.radius6}px 0 0 ${border.radius6}px`,
|
|
57
|
-
marginRight: -1,
|
|
58
|
-
}}
|
|
59
|
-
}
|
|
60
|
-
`,
|
|
61
|
-
middle: css`
|
|
62
|
-
&.${staticButtonStyle} {
|
|
63
|
-
${{
|
|
64
|
-
display: "inline-flex",
|
|
65
|
-
borderRadius: border.radius0,
|
|
66
|
-
marginRight: -1,
|
|
67
|
-
}}
|
|
68
|
-
}
|
|
69
|
-
`,
|
|
70
|
-
last: css`
|
|
71
|
-
&.${staticButtonStyle} {
|
|
72
|
-
${{
|
|
73
|
-
display: "inline-flex",
|
|
74
|
-
borderRadius: `0 ${border.radius6}px ${border.radius6}px 0`,
|
|
75
|
-
}}
|
|
76
|
-
}
|
|
77
|
-
`,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const getMainColor = ({color, dangerous, theme}) => {
|
|
81
|
-
if (color) {
|
|
82
|
-
return color;
|
|
83
|
-
}
|
|
84
|
-
if (dangerous) {
|
|
85
|
-
return theme.danger;
|
|
86
|
-
}
|
|
87
|
-
if (!theme) {
|
|
88
|
-
return colors.primary;
|
|
89
|
-
}
|
|
90
|
-
return theme.buttonColor;
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
const getBorderColor = ({mainColor, borderless, primary}) => {
|
|
94
|
-
if (borderless) {
|
|
95
|
-
return colors.transparent;
|
|
96
|
-
}
|
|
97
|
-
if (primary) {
|
|
98
|
-
return mainColor;
|
|
99
|
-
}
|
|
100
|
-
return getOpacities(mainColor).opacity15;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const getHoverBorderColor = ({mainColor, borderless, primary, hoverBgColor}) => {
|
|
104
|
-
if (borderless) {
|
|
105
|
-
return colors.transparent;
|
|
106
|
-
}
|
|
107
|
-
if (primary) {
|
|
108
|
-
return hoverBgColor;
|
|
109
|
-
}
|
|
110
|
-
return mainColor;
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const getTextColor = ({mainColor, primary, theme}) => {
|
|
114
|
-
if (primary) {
|
|
115
|
-
return theme.buttonPrimaryTextColor;
|
|
116
|
-
}
|
|
117
|
-
return mainColor;
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
const getBgColor = ({mainColor, primary}) => {
|
|
121
|
-
if (primary) {
|
|
122
|
-
return mainColor;
|
|
123
|
-
}
|
|
124
|
-
return colors.transparent;
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
const getHoverBgColor = ({mainColor, borderless, primary}) => {
|
|
128
|
-
if (primary) {
|
|
129
|
-
return getDarkenColor(mainColor);
|
|
130
|
-
}
|
|
131
|
-
if (borderless) {
|
|
132
|
-
return getOpacities(mainColor).opacity15;
|
|
133
|
-
}
|
|
134
|
-
return colors.transparent;
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const getSpinnerColor = ({mainColor, primary}) => {
|
|
138
|
-
if (primary) {
|
|
139
|
-
return colors.inversedTextColor;
|
|
140
|
-
}
|
|
141
|
-
return mainColor;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const getButtonMagicConstants = _.memoize((size) => {
|
|
145
|
-
const sizeShift = sizeShifts[size];
|
|
146
|
-
|
|
147
|
-
const fontSize = fontSizes[size];
|
|
148
|
-
const minSize = fontSize * 2;
|
|
149
|
-
const horizontalPadding = baseSize - 2 + sizeShift * 4;
|
|
150
|
-
|
|
151
|
-
return {fontSize, minSize, horizontalPadding};
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
const getIconMagicConstants = _.memoize((size) => {
|
|
155
|
-
const sizeShift = sizeShifts[size];
|
|
156
|
-
|
|
157
|
-
const iconSize = baseSize + 2 + sizeShift * 2;
|
|
158
|
-
const leftContainerSize = 8;
|
|
159
|
-
const leftContainerMarginRight = iconSize - leftContainerSize;
|
|
160
|
-
|
|
161
|
-
return {iconSize, leftContainerSize, leftContainerMarginRight};
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
const StyledButton = styled.button`
|
|
165
|
-
font-size: ${({buttonSize}) => getButtonMagicConstants(buttonSize).fontSize}px;
|
|
166
|
-
min-height: ${({buttonSize}) => getButtonMagicConstants(buttonSize).minSize}px;
|
|
167
|
-
min-width: ${({buttonSize}) => getButtonMagicConstants(buttonSize).minSize}px;
|
|
168
|
-
padding-top: 0;
|
|
169
|
-
padding-bottom: 0;
|
|
170
|
-
padding-left: ${({buttonSize}) => getButtonMagicConstants(buttonSize).horizontalPadding}px;
|
|
171
|
-
padding-right: ${({buttonSize}) => getButtonMagicConstants(buttonSize).horizontalPadding}px;
|
|
172
|
-
opacity: ${({disabled}) => (disabled ? opacity.regular : 1)};
|
|
173
|
-
width: ${({buttonWidth = "auto"}) => (typeof buttonWidth === "string" ? buttonWidth : `${buttonWidth}px`)};
|
|
174
|
-
height: ${({buttonHeight = "auto"}) => (typeof buttonHeight === "string" ? buttonHeight : `${buttonHeight}px`)};
|
|
175
|
-
color: ${({textColor}) => textColor};
|
|
176
|
-
background-color: ${({bgColor}) => bgColor};
|
|
177
|
-
border-color: ${({borderColor}) => borderColor};
|
|
178
|
-
cursor: ${({clickable}) => (clickable ? "pointer" : "default")};
|
|
179
|
-
transition: all 150ms ease-out;
|
|
180
|
-
|
|
181
|
-
&:focus {
|
|
182
|
-
box-shadow: ${({borderColor, activeStyle}) =>
|
|
183
|
-
activeStyle ? `0 0 0 3px ${getOpacities(borderColor).light}` : "none"};
|
|
184
|
-
background-color: ${({hoverBgColor}) => hoverBgColor};
|
|
185
|
-
border-color: ${({hoverBorderColor}) => hoverBorderColor};
|
|
186
|
-
transition: all 150ms ease-out;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
&:focus:not(:focus-visible) {
|
|
190
|
-
box-shadow: none;
|
|
191
|
-
background-color: ${({bgColor}) => bgColor};
|
|
192
|
-
border-color: ${({borderColor}) => borderColor};
|
|
193
|
-
transition: none;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
&:focus-visible {
|
|
197
|
-
box-shadow: ${({borderColor, activeStyle}) =>
|
|
198
|
-
activeStyle ? `0 0 0 3px ${getOpacities(borderColor).light}` : "none"};
|
|
199
|
-
background-color: ${({hoverBgColor}) => hoverBgColor};
|
|
200
|
-
border-color: ${({hoverBorderColor}) => hoverBorderColor};
|
|
201
|
-
transition: all 150ms ease-out;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
&:hover,
|
|
205
|
-
&:focus:hover:not(:focus-visible) {
|
|
206
|
-
background-color: ${({hoverBgColor}) => hoverBgColor};
|
|
207
|
-
border-color: ${({hoverBorderColor}) => hoverBorderColor};
|
|
208
|
-
transition: all 150ms ease-out;
|
|
209
|
-
}
|
|
210
|
-
`;
|
|
211
|
-
|
|
212
|
-
export const buttonClassName = StyledButton;
|
|
213
|
-
|
|
214
|
-
const shortcutStyle = css`
|
|
215
|
-
${{
|
|
216
|
-
...textStyles.small,
|
|
217
|
-
color: themeVars.whiteColor,
|
|
218
|
-
border: "solid 1px",
|
|
219
|
-
borderRadius: border.radius4,
|
|
220
|
-
paddingLeft: 4,
|
|
221
|
-
paddingRight: 4,
|
|
222
|
-
marginLeft: 4,
|
|
223
|
-
opacity: 0.7,
|
|
224
|
-
}}
|
|
225
|
-
`;
|
|
226
|
-
|
|
227
|
-
const leftContainerMarginRightVar = "--fibery-button-left-container-margin-right";
|
|
228
|
-
|
|
229
|
-
const leftContainerClassName = css`
|
|
230
|
-
margin-right: var(${leftContainerMarginRightVar});
|
|
231
|
-
`;
|
|
232
|
-
|
|
233
|
-
export const Button = forwardRef(
|
|
234
|
-
(
|
|
235
|
-
{
|
|
236
|
-
children,
|
|
237
|
-
color,
|
|
238
|
-
dangerous,
|
|
239
|
-
borderless,
|
|
240
|
-
primary,
|
|
241
|
-
pending,
|
|
242
|
-
icon,
|
|
243
|
-
Icon,
|
|
244
|
-
size = ":button-size/normal",
|
|
245
|
-
type = "button",
|
|
246
|
-
disabled,
|
|
247
|
-
width,
|
|
248
|
-
height,
|
|
249
|
-
inGroup,
|
|
250
|
-
onClick,
|
|
251
|
-
className,
|
|
252
|
-
shortcut,
|
|
253
|
-
noOverflow = true,
|
|
254
|
-
...rest
|
|
255
|
-
},
|
|
256
|
-
forwardedRef
|
|
257
|
-
) => {
|
|
258
|
-
const theme = useTheme();
|
|
259
|
-
const mainColor = getMainColor({color, dangerous, theme});
|
|
260
|
-
const textColor = getTextColor({mainColor, primary, theme});
|
|
261
|
-
const spinnerBgColor = getOpacities(textColor).light;
|
|
262
|
-
const spinnerColor = getSpinnerColor({mainColor, primary});
|
|
263
|
-
const bgColor = getBgColor({mainColor, primary});
|
|
264
|
-
const hoverBgColor = getHoverBgColor({mainColor, borderless, primary});
|
|
265
|
-
const borderColor = getBorderColor({mainColor, borderless, primary});
|
|
266
|
-
const hoverBorderColor = getHoverBorderColor({
|
|
267
|
-
mainColor,
|
|
268
|
-
borderless,
|
|
269
|
-
primary,
|
|
270
|
-
hoverBgColor,
|
|
271
|
-
});
|
|
272
|
-
if (icon) {
|
|
273
|
-
// eslint-disable-next-line no-console
|
|
274
|
-
console.warn("'icon' props doesn't support anymore. Please use 'Icon' prop with explicit Icon Component");
|
|
275
|
-
}
|
|
276
|
-
const {iconSize, leftContainerSize, leftContainerMarginRight} = getIconMagicConstants(size);
|
|
277
|
-
|
|
278
|
-
const leftContainer = pending ? (
|
|
279
|
-
<Spinner
|
|
280
|
-
backgroundColor={spinnerBgColor}
|
|
281
|
-
color={spinnerColor}
|
|
282
|
-
size={iconSize}
|
|
283
|
-
containerSize={leftContainerSize}
|
|
284
|
-
/>
|
|
285
|
-
) : Icon ? (
|
|
286
|
-
<Icon color={textColor} size={iconSize} containerSize={leftContainerSize} />
|
|
287
|
-
) : null;
|
|
288
|
-
const styleVariable = {
|
|
289
|
-
buttonSize: size,
|
|
290
|
-
disabled,
|
|
291
|
-
pending,
|
|
292
|
-
buttonWidth: width,
|
|
293
|
-
buttonHeight: height,
|
|
294
|
-
textColor,
|
|
295
|
-
clickable: !disabled && !pending,
|
|
296
|
-
hoverBgColor: !disabled && !pending ? hoverBgColor : bgColor,
|
|
297
|
-
hoverBorderColor: !disabled && !pending ? hoverBorderColor : borderColor,
|
|
298
|
-
borderColor,
|
|
299
|
-
bgColor,
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
return (
|
|
303
|
-
<StyledButton
|
|
304
|
-
{...styleVariable}
|
|
305
|
-
ref={forwardedRef}
|
|
306
|
-
type={type}
|
|
307
|
-
onClick={!disabled && !pending && onClick ? onClick : _.noop}
|
|
308
|
-
disabled={disabled}
|
|
309
|
-
className={cx(className, staticButtonStyle, ordersInGroup[inGroup])}
|
|
310
|
-
{...rest}
|
|
311
|
-
>
|
|
312
|
-
<Item
|
|
313
|
-
leftContainer={leftContainer}
|
|
314
|
-
style={{
|
|
315
|
-
[leftContainerMarginRightVar]: `${leftContainerMarginRight}px`,
|
|
316
|
-
}}
|
|
317
|
-
containerClassName={cx({[leftContainerClassName]: leftContainer && hasNonEmptyChild(children)})}
|
|
318
|
-
rightContainer={shortcut && <span className={cx(shortcutStyle)}>{shortcut}</span>}
|
|
319
|
-
noOverflow={noOverflow}
|
|
320
|
-
>
|
|
321
|
-
{children}
|
|
322
|
-
</Item>
|
|
323
|
-
</StyledButton>
|
|
324
|
-
);
|
|
325
|
-
}
|
|
326
|
-
);
|
|
327
|
-
|
|
328
|
-
Button.propTypes = {
|
|
329
|
-
size: PropTypes.oneOf(Object.keys(fontSizes)),
|
|
330
|
-
type: PropTypes.string,
|
|
331
|
-
primary: PropTypes.bool,
|
|
332
|
-
dangerous: PropTypes.bool,
|
|
333
|
-
disabled: PropTypes.bool,
|
|
334
|
-
pending: PropTypes.bool,
|
|
335
|
-
borderless: PropTypes.bool,
|
|
336
|
-
icon: PropTypes.string,
|
|
337
|
-
color: PropTypes.string,
|
|
338
|
-
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
339
|
-
onClick: PropTypes.func,
|
|
340
|
-
inGroup: PropTypes.oneOf(Object.keys(ordersInGroup)),
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
// TODO can be inlined
|
|
344
|
-
export function ActionsButton({onClick, label = ``, disabled}) {
|
|
345
|
-
return <Button Icon={MoreIcon} onClick={onClick} borderless aria-label={label} disabled={disabled} />;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
export const ActionsButtonCompact = forwardRef(({inverted, ...rest}, ref) => {
|
|
349
|
-
const theme = useTheme();
|
|
350
|
-
return (
|
|
351
|
-
<Button
|
|
352
|
-
ref={ref}
|
|
353
|
-
size={":button-size/small"}
|
|
354
|
-
Icon={MoreCompactIcon}
|
|
355
|
-
color={inverted ? colors.inversedTextColor : theme.buttonColor}
|
|
356
|
-
borderless
|
|
357
|
-
{...rest}
|
|
358
|
-
/>
|
|
359
|
-
);
|
|
360
|
-
});
|