@fibery/ui-kit 1.25.0 → 1.25.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fibery/ui-kit",
|
|
3
|
-
"version": "1.25.
|
|
3
|
+
"version": "1.25.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"src/antd/styles.ts",
|
|
@@ -103,8 +103,8 @@
|
|
|
103
103
|
"svgo": "2.8.0",
|
|
104
104
|
"typescript": "5.1.6",
|
|
105
105
|
"unist-util-reduce": "0.2.2",
|
|
106
|
-
"@fibery/
|
|
107
|
-
"@fibery/
|
|
106
|
+
"@fibery/eslint-config": "8.5.0",
|
|
107
|
+
"@fibery/babel-preset": "7.3.0"
|
|
108
108
|
},
|
|
109
109
|
"jest": {
|
|
110
110
|
"testEnvironment": "jsdom",
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {ForwardedRef, forwardRef, HTMLAttributes, PropsWithChildren, ReactNode} from "react";
|
|
1
|
+
import {ForwardedRef, forwardRef, HTMLAttributes, PropsWithChildren, ReactNode, useId} from "react";
|
|
2
2
|
import {border, colors, layout, lineHeight, space, textStyles, themeVars} from "../design-system";
|
|
3
3
|
import {css, cx} from "@linaria/core";
|
|
4
4
|
import {ActionsMenuItemProps} from "../actions-menu/actions-menu-item";
|
|
5
5
|
import {useActionsMenuContext} from "../actions-menu";
|
|
6
6
|
import {stopPropagation} from "@fibery/react/src/stop-propagation";
|
|
7
|
-
import {useSetActiveDangerousRow} from "../actions-menu/contexts/actions-menu-dangerous-rows";
|
|
7
|
+
import {useActiveDangerousRow, useSetActiveDangerousRow} from "../actions-menu/contexts/actions-menu-dangerous-rows";
|
|
8
8
|
import _ from "lodash";
|
|
9
|
+
import {useCallbackRef} from "@fibery/react/src/use-callback-ref";
|
|
9
10
|
|
|
10
11
|
interface ListRowSurfaceBase extends HTMLAttributes<HTMLDivElement> {
|
|
11
12
|
testId?: string;
|
|
@@ -19,11 +20,7 @@ export interface ListRowSurfaceProps extends ListRowSurfaceBase {
|
|
|
19
20
|
}
|
|
20
21
|
interface ActionMenuItemSurfaceProps
|
|
21
22
|
extends Omit<ActionsMenuItemProps, "description">,
|
|
22
|
-
Omit<ListRowSurfaceProps, "children" | "darker" | "onSelect"> {
|
|
23
|
-
id?: string;
|
|
24
|
-
showWarning?: boolean;
|
|
25
|
-
onSelect?: (e: Event) => void;
|
|
26
|
-
}
|
|
23
|
+
Omit<ListRowSurfaceProps, "children" | "darker" | "onSelect" | "id"> {}
|
|
27
24
|
export const NATUAL_HOVER_CLASS = "natural-hover";
|
|
28
25
|
export const NATUAL_FOCUS_CLASS = "natural-focus";
|
|
29
26
|
export const NATURAL_HOVER = `&.${NATUAL_HOVER_CLASS}:hover`;
|
|
@@ -227,27 +224,14 @@ export const ListRowSurface = forwardRef<HTMLDivElement, ListRowSurfaceProps>(
|
|
|
227
224
|
}
|
|
228
225
|
);
|
|
229
226
|
export const ActionMenuItemSurface = forwardRef<HTMLDivElement, ActionMenuItemSurfaceProps>(
|
|
230
|
-
(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
id,
|
|
236
|
-
selected,
|
|
237
|
-
hovered,
|
|
238
|
-
focused,
|
|
239
|
-
title,
|
|
240
|
-
disabled,
|
|
241
|
-
children,
|
|
242
|
-
dangerous,
|
|
243
|
-
showWarning,
|
|
244
|
-
onSelect = _.noop,
|
|
245
|
-
},
|
|
246
|
-
ref
|
|
247
|
-
) => {
|
|
227
|
+
({testId, className, loading, selected, hovered, focused, title, disabled, children, dangerous, ...props}, ref) => {
|
|
228
|
+
const id = useId();
|
|
229
|
+
const activeDangerousRow = useActiveDangerousRow();
|
|
230
|
+
const showWarning = activeDangerousRow === id;
|
|
231
|
+
const onSelect = useCallbackRef(props.onSelect || _.noop);
|
|
248
232
|
const {MenuPrimitive} = useActionsMenuContext();
|
|
249
233
|
const setActiveDangerousRow = useSetActiveDangerousRow();
|
|
250
|
-
const handleSelect =
|
|
234
|
+
const handleSelect = (e: Event) => {
|
|
251
235
|
e.stopPropagation();
|
|
252
236
|
|
|
253
237
|
if (loading || !id) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {GroupHeadingProps, GroupProps, MenuListProps} from "react-select";
|
|
2
2
|
import {ItemContent, Virtuoso, VirtuosoHandle} from "react-virtuoso";
|
|
3
|
-
import {Children, ComponentType, ReactNode, useContext, useEffect, useRef} from "react";
|
|
3
|
+
import {Children, ComponentType, ReactNode, useContext, useEffect, useRef, useState} from "react";
|
|
4
4
|
import {GroupBase, ReactSelectRefContext} from "../util";
|
|
5
5
|
import {layout} from "../../../src/design-system";
|
|
6
6
|
import _, {isFunction, isObject} from "lodash";
|
|
@@ -89,11 +89,17 @@ export function MenuListVirtualized<
|
|
|
89
89
|
) : null;
|
|
90
90
|
};
|
|
91
91
|
const select = useContext(ReactSelectRefContext);
|
|
92
|
+
const [initialFocusedOption, setInitialFocusedOption] = useState<Option | null>(null);
|
|
92
93
|
|
|
93
94
|
const flattenChildren = flattenGroupChildren(children, renderGroup);
|
|
94
95
|
//fix for select not having focused option when open. if no focused item present, at least first option must be focused.
|
|
95
|
-
|
|
96
|
-
|
|
96
|
+
//Unfortunately, we can not rely on select focusedOption to determine option that should be focused initially:
|
|
97
|
+
//to mark selected option react-select uses value field of Option object.
|
|
98
|
+
//to define initially focused option react select uses whole Option object reference equality which is not always the case
|
|
99
|
+
//if select value is not exactly same object as option, we end up having initially focusedOption being just first option.
|
|
100
|
+
//fix below ensures that initial focusedOption is always selectedOption in cost of one more rerender
|
|
101
|
+
if (select.current && flattenChildren.length && !initialFocusedOption) {
|
|
102
|
+
let firstExistingOption: unknown;
|
|
97
103
|
let selectedOption: unknown;
|
|
98
104
|
//if an options exists, but there is no focused option, looking for first selected / existing option
|
|
99
105
|
for (let i = 0; i < flattenChildren.length; i++) {
|
|
@@ -113,23 +119,25 @@ export function MenuListVirtualized<
|
|
|
113
119
|
selectedOption = child.props.data;
|
|
114
120
|
break;
|
|
115
121
|
}
|
|
116
|
-
if (!
|
|
117
|
-
|
|
122
|
+
if (!firstExistingOption) {
|
|
123
|
+
firstExistingOption = child.props.data;
|
|
118
124
|
}
|
|
119
125
|
}
|
|
120
126
|
}
|
|
121
127
|
}
|
|
122
128
|
if (selectedOption) {
|
|
129
|
+
setInitialFocusedOption(selectedOption as Option);
|
|
123
130
|
select.current.setState({focusedOption: selectedOption});
|
|
124
|
-
} else if (
|
|
125
|
-
|
|
131
|
+
} else if (firstExistingOption) {
|
|
132
|
+
setInitialFocusedOption(firstExistingOption as Option);
|
|
133
|
+
select.current.setState({focusedOption: firstExistingOption});
|
|
126
134
|
}
|
|
127
135
|
}
|
|
128
136
|
const menuHeight = Math.min(flattenChildren.length * layout.menuItemHeight, maxHeight);
|
|
129
137
|
//scrolling to focused option
|
|
130
138
|
useEffect(() => {
|
|
131
139
|
let to: ReturnType<typeof setTimeout> | undefined;
|
|
132
|
-
if (focusedOption && virtuoso.current) {
|
|
140
|
+
if (initialFocusedOption && focusedOption && virtuoso.current) {
|
|
133
141
|
const index = flattenChildren.findIndex((child) => {
|
|
134
142
|
if (isObject(child) && "props" in child) {
|
|
135
143
|
if (isObject(child.props) && "data" in child.props) {
|
|
@@ -167,7 +175,7 @@ export function MenuListVirtualized<
|
|
|
167
175
|
return () => {
|
|
168
176
|
clearTimeout(to);
|
|
169
177
|
};
|
|
170
|
-
}, [focusedOption, flattenChildren, menuHeight, virtuoso]);
|
|
178
|
+
}, [focusedOption, flattenChildren, menuHeight, initialFocusedOption, virtuoso]);
|
|
171
179
|
return (
|
|
172
180
|
// Needed for correct display inside portals and etc.
|
|
173
181
|
<div>
|
|
@@ -10,11 +10,11 @@ const noOptionMessageClass = css`
|
|
|
10
10
|
`;
|
|
11
11
|
const noOptionMessageContentClass = css`
|
|
12
12
|
padding: 0 ${space.s6}px;
|
|
13
|
-
line-height: ${layout.menuItemHeight}px;
|
|
14
13
|
white-space: nowrap;
|
|
15
14
|
overflow: hidden;
|
|
16
15
|
text-overflow: ellipsis;
|
|
17
16
|
${{...textStyles.regular}}
|
|
17
|
+
line-height: ${layout.menuItemHeight}px;
|
|
18
18
|
`;
|
|
19
19
|
|
|
20
20
|
export const NoOptionsMessage = ({children}: {children: ReactNode}) => {
|
package/src/error-alert.tsx
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import {css} from "@linaria/core";
|
|
2
|
-
import {layout, border, space, textStyles, themeVars} from "./design-system";
|
|
3
|
-
import {Button} from "./button/button";
|
|
4
|
-
import CloseIcon from "./icons/react/Close";
|
|
5
|
-
import {useTheme} from "./theme-provider";
|
|
6
|
-
|
|
7
|
-
const errorAlert = css`
|
|
8
|
-
background-color: ${themeVars.errorBgColor};
|
|
9
|
-
padding: ${space.s8}px ${space.s12}px;
|
|
10
|
-
min-height: ${layout.itemHeight}px;
|
|
11
|
-
border-radius: ${border.radius6}px;
|
|
12
|
-
display: flex;
|
|
13
|
-
gap: ${space.s6}px;
|
|
14
|
-
align-items: center;
|
|
15
|
-
`;
|
|
16
|
-
|
|
17
|
-
const messageStyle = css`
|
|
18
|
-
${textStyles.heading5};
|
|
19
|
-
color: ${themeVars.errorTextColor};
|
|
20
|
-
`;
|
|
21
|
-
|
|
22
|
-
const descriptionStyle = css`
|
|
23
|
-
${textStyles.regular};
|
|
24
|
-
color: ${themeVars.errorTextColor};
|
|
25
|
-
`;
|
|
26
|
-
|
|
27
|
-
export function ErrorAlert({
|
|
28
|
-
message,
|
|
29
|
-
description,
|
|
30
|
-
closable,
|
|
31
|
-
onClose,
|
|
32
|
-
}: {
|
|
33
|
-
message: string;
|
|
34
|
-
description?: React.ReactNode;
|
|
35
|
-
closable?: boolean;
|
|
36
|
-
onClose?: () => void;
|
|
37
|
-
}): JSX.Element {
|
|
38
|
-
const theme = useTheme();
|
|
39
|
-
const buttonColor = theme.errorButtonColor;
|
|
40
|
-
return (
|
|
41
|
-
<div className={errorAlert}>
|
|
42
|
-
<div
|
|
43
|
-
className={css`
|
|
44
|
-
flex-grow: 2;
|
|
45
|
-
`}
|
|
46
|
-
>
|
|
47
|
-
<div className={messageStyle}>{message}</div>
|
|
48
|
-
{description ? <div className={descriptionStyle}>{description}</div> : null}
|
|
49
|
-
</div>
|
|
50
|
-
{closable && onClose ? (
|
|
51
|
-
<div>
|
|
52
|
-
<Button borderless onClick={onClose} color={buttonColor} Icon={CloseIcon} width={24} />
|
|
53
|
-
</div>
|
|
54
|
-
) : null}
|
|
55
|
-
</div>
|
|
56
|
-
);
|
|
57
|
-
}
|