@uipath/apollo-react 3.54.0-pr354.c980c37 → 3.54.0-pr354.f799733
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/dist/canvas/components/Toolbox/ListView.cjs +54 -34
- package/dist/canvas/components/Toolbox/ListView.d.ts +12 -2
- package/dist/canvas/components/Toolbox/ListView.d.ts.map +1 -1
- package/dist/canvas/components/Toolbox/ListView.js +51 -34
- package/dist/canvas/components/Toolbox/ListView.styles.cjs +7 -1
- package/dist/canvas/components/Toolbox/ListView.styles.d.ts.map +1 -1
- package/dist/canvas/components/Toolbox/ListView.styles.js +7 -1
- package/dist/canvas/components/Toolbox/SearchBox.cjs +12 -4
- package/dist/canvas/components/Toolbox/SearchBox.d.ts +3 -0
- package/dist/canvas/components/Toolbox/SearchBox.d.ts.map +1 -1
- package/dist/canvas/components/Toolbox/SearchBox.js +12 -4
- package/dist/canvas/components/Toolbox/Toolbox.cjs +136 -4
- package/dist/canvas/components/Toolbox/Toolbox.d.ts.map +1 -1
- package/dist/canvas/components/Toolbox/Toolbox.js +136 -4
- package/package.json +2 -2
|
@@ -24,7 +24,8 @@ var __webpack_require__ = {};
|
|
|
24
24
|
var __webpack_exports__ = {};
|
|
25
25
|
__webpack_require__.r(__webpack_exports__);
|
|
26
26
|
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
-
ListView: ()=>ListView_ListView
|
|
27
|
+
ListView: ()=>ListView_ListView,
|
|
28
|
+
buildRenderedItems: ()=>buildRenderedItems
|
|
28
29
|
});
|
|
29
30
|
const jsx_runtime_namespaceObject = require("react/jsx-runtime");
|
|
30
31
|
const apollo_core_namespaceObject = require("@uipath/apollo-core");
|
|
@@ -35,8 +36,37 @@ const components_index_cjs_namespaceObject = require("../../../material/componen
|
|
|
35
36
|
const external_react_namespaceObject = require("react");
|
|
36
37
|
const CanvasThemeContext_cjs_namespaceObject = require("../BaseCanvas/CanvasThemeContext.cjs");
|
|
37
38
|
const external_ListView_styles_cjs_namespaceObject = require("./ListView.styles.cjs");
|
|
39
|
+
function buildRenderedItems(items, enableSections) {
|
|
40
|
+
const result = [];
|
|
41
|
+
if (0 === items.length) return result;
|
|
42
|
+
if (!enableSections) {
|
|
43
|
+
for (const item of items)result.push({
|
|
44
|
+
type: 'item',
|
|
45
|
+
item
|
|
46
|
+
});
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
const [itemsWithSection, itemsWithoutSection] = (0, external_utils_index_cjs_namespaceObject.partition)(items, (item)=>!!item.section);
|
|
50
|
+
for (const item of itemsWithoutSection)result.push({
|
|
51
|
+
type: 'item',
|
|
52
|
+
item
|
|
53
|
+
});
|
|
54
|
+
if (0 === itemsWithSection.length) return result;
|
|
55
|
+
const sections = Array.from(new Set(itemsWithSection.map((item)=>item.section)));
|
|
56
|
+
for (const section of sections){
|
|
57
|
+
result.push({
|
|
58
|
+
type: 'section',
|
|
59
|
+
sectionName: section
|
|
60
|
+
});
|
|
61
|
+
for (const item of itemsWithSection.filter((item)=>item.section === section))result.push({
|
|
62
|
+
type: 'item',
|
|
63
|
+
item
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
38
68
|
const IconContainerMemoized = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(external_ListView_styles_cjs_namespaceObject.IconContainer);
|
|
39
|
-
const ListViewRow = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(({ index, style, ariaAttributes, renderedItems, isLoading, isDarkMode, onItemClick, onItemHover })=>{
|
|
69
|
+
const ListViewRow = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(({ index, style, ariaAttributes, renderedItems, activeIndex, isLoading, isDarkMode, onItemClick, onItemHover })=>{
|
|
40
70
|
const renderItem = renderedItems[index];
|
|
41
71
|
const buttonStyle = (0, external_react_namespaceObject.useMemo)(()=>({
|
|
42
72
|
...style,
|
|
@@ -74,12 +104,17 @@ const ListViewRow = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(({ in
|
|
|
74
104
|
});
|
|
75
105
|
const item = renderItem.item;
|
|
76
106
|
const bgColor = isDarkMode ? item.colorDark ?? item.color : item.color;
|
|
107
|
+
const isActive = index === activeIndex;
|
|
77
108
|
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(external_ListView_styles_cjs_namespaceObject.ListItemButton, {
|
|
78
109
|
...ariaAttributes,
|
|
110
|
+
tabIndex: -1,
|
|
111
|
+
id: `toolbox-item-${item.id}`,
|
|
112
|
+
role: "option",
|
|
113
|
+
"aria-selected": isActive,
|
|
79
114
|
style: buttonStyle,
|
|
80
115
|
onClick: handleButtonClick,
|
|
81
116
|
onHoverStart: handleButtonHover,
|
|
82
|
-
className: isLoading ? 'loading' : ''
|
|
117
|
+
className: `${isLoading ? 'loading' : ''} ${isActive ? 'active' : ''}`,
|
|
83
118
|
disabled: isLoading,
|
|
84
119
|
children: [
|
|
85
120
|
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsxs)(IconContainerMemoized, {
|
|
@@ -134,48 +169,27 @@ const ListViewRow = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(({ in
|
|
|
134
169
|
]
|
|
135
170
|
});
|
|
136
171
|
});
|
|
137
|
-
const
|
|
172
|
+
const ListViewInner = /*#__PURE__*/ (0, external_react_namespaceObject.forwardRef)(function({ items, activeIndex = -1, listRef, onItemClick, onItemHover, emptyStateMessage = 'No items found', emptyStateIcon = 'search_off', isLoading = false, enableSections = true }, ref) {
|
|
138
173
|
const { isDarkMode } = (0, CanvasThemeContext_cjs_namespaceObject.useCanvasTheme)();
|
|
139
|
-
const renderedItems = (0, external_react_namespaceObject.useMemo)(()=>
|
|
140
|
-
const result = [];
|
|
141
|
-
if (0 === items.length) return result;
|
|
142
|
-
if (!enableSections) {
|
|
143
|
-
for (const item of items)result.push({
|
|
144
|
-
type: 'item',
|
|
145
|
-
item
|
|
146
|
-
});
|
|
147
|
-
return result;
|
|
148
|
-
}
|
|
149
|
-
const [itemsWithSection, itemsWithoutSection] = (0, external_utils_index_cjs_namespaceObject.partition)(items, (item)=>!!item.section);
|
|
150
|
-
for (const item of itemsWithoutSection)result.push({
|
|
151
|
-
type: 'item',
|
|
152
|
-
item
|
|
153
|
-
});
|
|
154
|
-
if (0 === itemsWithSection.length) return result;
|
|
155
|
-
const sections = Array.from(new Set(itemsWithSection.map((item)=>item.section)));
|
|
156
|
-
for (const section of sections){
|
|
157
|
-
result.push({
|
|
158
|
-
type: 'section',
|
|
159
|
-
sectionName: section
|
|
160
|
-
});
|
|
161
|
-
for (const item of itemsWithSection.filter((item)=>item.section === section))result.push({
|
|
162
|
-
type: 'item',
|
|
163
|
-
item
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
return result;
|
|
167
|
-
}, [
|
|
174
|
+
const renderedItems = (0, external_react_namespaceObject.useMemo)(()=>buildRenderedItems(items, enableSections), [
|
|
168
175
|
items,
|
|
169
176
|
enableSections
|
|
170
177
|
]);
|
|
178
|
+
(0, external_react_namespaceObject.useImperativeHandle)(ref, ()=>({
|
|
179
|
+
renderedItems
|
|
180
|
+
}), [
|
|
181
|
+
renderedItems
|
|
182
|
+
]);
|
|
171
183
|
const rowProps = (0, external_react_namespaceObject.useMemo)(()=>({
|
|
172
184
|
renderedItems,
|
|
185
|
+
activeIndex,
|
|
173
186
|
isLoading,
|
|
174
187
|
isDarkMode,
|
|
175
188
|
onItemClick,
|
|
176
189
|
onItemHover
|
|
177
190
|
}), [
|
|
178
191
|
renderedItems,
|
|
192
|
+
activeIndex,
|
|
179
193
|
isLoading,
|
|
180
194
|
isDarkMode,
|
|
181
195
|
onItemClick,
|
|
@@ -215,6 +229,9 @@ const ListView_ListView = /*#__PURE__*/ (0, external_react_namespaceObject.memo)
|
|
|
215
229
|
]
|
|
216
230
|
});
|
|
217
231
|
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_ListView_styles_cjs_namespaceObject.StyledList, {
|
|
232
|
+
id: "toolbox-listbox",
|
|
233
|
+
role: "listbox",
|
|
234
|
+
listRef: listRef,
|
|
218
235
|
rowProps: rowProps,
|
|
219
236
|
rowComponent: ListViewRow,
|
|
220
237
|
rowCount: renderedItems.length,
|
|
@@ -222,9 +239,12 @@ const ListView_ListView = /*#__PURE__*/ (0, external_react_namespaceObject.memo)
|
|
|
222
239
|
overscanCount: 20
|
|
223
240
|
});
|
|
224
241
|
});
|
|
242
|
+
const ListView_ListView = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(ListViewInner);
|
|
225
243
|
exports.ListView = __webpack_exports__.ListView;
|
|
244
|
+
exports.buildRenderedItems = __webpack_exports__.buildRenderedItems;
|
|
226
245
|
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
227
|
-
"ListView"
|
|
246
|
+
"ListView",
|
|
247
|
+
"buildRenderedItems"
|
|
228
248
|
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
229
249
|
Object.defineProperty(exports, '__esModule', {
|
|
230
250
|
value: true
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ListImperativeAPI } from 'react-window';
|
|
1
2
|
export interface ListItemIcon {
|
|
2
3
|
name?: string;
|
|
3
4
|
url?: string;
|
|
@@ -14,22 +15,29 @@ export type ListItem<T = any> = {
|
|
|
14
15
|
colorDark?: string;
|
|
15
16
|
children?: ListItem<T>[] | ((id: string, name: string) => Promise<ListItem<T>[]>);
|
|
16
17
|
};
|
|
17
|
-
type RenderItem<T extends ListItem> = {
|
|
18
|
+
export type RenderItem<T extends ListItem> = {
|
|
18
19
|
type: 'section';
|
|
19
20
|
sectionName: string;
|
|
20
21
|
} | {
|
|
21
22
|
type: 'item';
|
|
22
23
|
item: T;
|
|
23
24
|
};
|
|
25
|
+
export declare function buildRenderedItems<T extends ListItem>(items: T[], enableSections: boolean): RenderItem<T>[];
|
|
24
26
|
export interface ListViewRowProps<T extends ListItem> {
|
|
25
27
|
renderedItems: RenderItem<T>[];
|
|
28
|
+
activeIndex: number;
|
|
26
29
|
isLoading?: boolean;
|
|
27
30
|
isDarkMode?: boolean;
|
|
28
31
|
onItemClick: (item: T) => void;
|
|
29
32
|
onItemHover?: (item: T) => void;
|
|
30
33
|
}
|
|
34
|
+
export interface ListViewHandle<T extends ListItem = ListItem> {
|
|
35
|
+
renderedItems: RenderItem<T>[];
|
|
36
|
+
}
|
|
31
37
|
interface ListViewProps<T extends ListItem> {
|
|
32
38
|
items: T[];
|
|
39
|
+
activeIndex?: number;
|
|
40
|
+
listRef?: React.RefObject<ListImperativeAPI | null>;
|
|
33
41
|
onItemClick: (item: T) => void;
|
|
34
42
|
onItemHover?: (item: T) => void;
|
|
35
43
|
emptyStateMessage?: string;
|
|
@@ -37,6 +45,8 @@ interface ListViewProps<T extends ListItem> {
|
|
|
37
45
|
isLoading?: boolean;
|
|
38
46
|
enableSections?: boolean;
|
|
39
47
|
}
|
|
40
|
-
export declare const ListView:
|
|
48
|
+
export declare const ListView: <T extends ListItem>(props: ListViewProps<T> & {
|
|
49
|
+
ref?: React.Ref<ListViewHandle<T>>;
|
|
50
|
+
}) => React.ReactElement | null;
|
|
41
51
|
export {};
|
|
42
52
|
//# sourceMappingURL=ListView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListView.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/ListView.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ListView.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/ListView.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAqB,MAAM,cAAc,CAAC;AAIzE,MAAM,WAAW,YAAY;IAI3B,IAAI,CAAC,EAAE,MAAM,CAAC;IAId,GAAG,CAAC,EAAE,MAAM,CAAC;IAIb,SAAS,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CACjC;AAED,MAAM,MAAM,QAAQ,CAAC,CAAC,GAAG,GAAG,IAAI;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,CAAC,CAAC;IACR,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACnF,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,QAAQ,IACrC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,CAAC;AAE9B,wBAAgB,kBAAkB,CAAC,CAAC,SAAS,QAAQ,EACnD,KAAK,EAAE,CAAC,EAAE,EACV,cAAc,EAAE,OAAO,GACtB,UAAU,CAAC,CAAC,CAAC,EAAE,CAqCjB;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,QAAQ;IAClD,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;CACjC;AAgHD,MAAM,WAAW,cAAc,CAAC,CAAC,SAAS,QAAQ,GAAG,QAAQ;IAC3D,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;CAChC;AAED,UAAU,aAAa,CAAC,CAAC,SAAS,QAAQ;IACxC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACpD,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAC/B,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;IAChC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAsED,eAAO,MAAM,QAAQ,EAA0B,CAAC,CAAC,SAAS,QAAQ,EAChE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAA;CAAE,KAC7D,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC"}
|
|
@@ -4,11 +4,40 @@ import { Column } from "../../layouts/index.js";
|
|
|
4
4
|
import { NodeIcon, partition } from "../../utils/index.js";
|
|
5
5
|
import { ApSkeleton, ApTypography } from "../../../material/index.js";
|
|
6
6
|
import { ApIcon, ApTooltip } from "../../../material/components/index.js";
|
|
7
|
-
import { memo, useCallback, useMemo } from "react";
|
|
7
|
+
import { forwardRef, memo, useCallback, useImperativeHandle, useMemo } from "react";
|
|
8
8
|
import { useCanvasTheme } from "../BaseCanvas/CanvasThemeContext.js";
|
|
9
9
|
import { IconContainer, ListItemButton, SectionHeader, StyledList } from "./ListView.styles.js";
|
|
10
|
+
function buildRenderedItems(items, enableSections) {
|
|
11
|
+
const result = [];
|
|
12
|
+
if (0 === items.length) return result;
|
|
13
|
+
if (!enableSections) {
|
|
14
|
+
for (const item of items)result.push({
|
|
15
|
+
type: 'item',
|
|
16
|
+
item
|
|
17
|
+
});
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
const [itemsWithSection, itemsWithoutSection] = partition(items, (item)=>!!item.section);
|
|
21
|
+
for (const item of itemsWithoutSection)result.push({
|
|
22
|
+
type: 'item',
|
|
23
|
+
item
|
|
24
|
+
});
|
|
25
|
+
if (0 === itemsWithSection.length) return result;
|
|
26
|
+
const sections = Array.from(new Set(itemsWithSection.map((item)=>item.section)));
|
|
27
|
+
for (const section of sections){
|
|
28
|
+
result.push({
|
|
29
|
+
type: 'section',
|
|
30
|
+
sectionName: section
|
|
31
|
+
});
|
|
32
|
+
for (const item of itemsWithSection.filter((item)=>item.section === section))result.push({
|
|
33
|
+
type: 'item',
|
|
34
|
+
item
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
10
39
|
const IconContainerMemoized = /*#__PURE__*/ memo(IconContainer);
|
|
11
|
-
const ListViewRow = /*#__PURE__*/ memo(({ index, style, ariaAttributes, renderedItems, isLoading, isDarkMode, onItemClick, onItemHover })=>{
|
|
40
|
+
const ListViewRow = /*#__PURE__*/ memo(({ index, style, ariaAttributes, renderedItems, activeIndex, isLoading, isDarkMode, onItemClick, onItemHover })=>{
|
|
12
41
|
const renderItem = renderedItems[index];
|
|
13
42
|
const buttonStyle = useMemo(()=>({
|
|
14
43
|
...style,
|
|
@@ -46,12 +75,17 @@ const ListViewRow = /*#__PURE__*/ memo(({ index, style, ariaAttributes, rendered
|
|
|
46
75
|
});
|
|
47
76
|
const item = renderItem.item;
|
|
48
77
|
const bgColor = isDarkMode ? item.colorDark ?? item.color : item.color;
|
|
78
|
+
const isActive = index === activeIndex;
|
|
49
79
|
return /*#__PURE__*/ jsxs(ListItemButton, {
|
|
50
80
|
...ariaAttributes,
|
|
81
|
+
tabIndex: -1,
|
|
82
|
+
id: `toolbox-item-${item.id}`,
|
|
83
|
+
role: "option",
|
|
84
|
+
"aria-selected": isActive,
|
|
51
85
|
style: buttonStyle,
|
|
52
86
|
onClick: handleButtonClick,
|
|
53
87
|
onHoverStart: handleButtonHover,
|
|
54
|
-
className: isLoading ? 'loading' : ''
|
|
88
|
+
className: `${isLoading ? 'loading' : ''} ${isActive ? 'active' : ''}`,
|
|
55
89
|
disabled: isLoading,
|
|
56
90
|
children: [
|
|
57
91
|
/*#__PURE__*/ jsxs(IconContainerMemoized, {
|
|
@@ -106,48 +140,27 @@ const ListViewRow = /*#__PURE__*/ memo(({ index, style, ariaAttributes, rendered
|
|
|
106
140
|
]
|
|
107
141
|
});
|
|
108
142
|
});
|
|
109
|
-
const
|
|
143
|
+
const ListViewInner = /*#__PURE__*/ forwardRef(function({ items, activeIndex = -1, listRef, onItemClick, onItemHover, emptyStateMessage = 'No items found', emptyStateIcon = 'search_off', isLoading = false, enableSections = true }, ref) {
|
|
110
144
|
const { isDarkMode } = useCanvasTheme();
|
|
111
|
-
const renderedItems = useMemo(()=>
|
|
112
|
-
const result = [];
|
|
113
|
-
if (0 === items.length) return result;
|
|
114
|
-
if (!enableSections) {
|
|
115
|
-
for (const item of items)result.push({
|
|
116
|
-
type: 'item',
|
|
117
|
-
item
|
|
118
|
-
});
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
|
-
const [itemsWithSection, itemsWithoutSection] = partition(items, (item)=>!!item.section);
|
|
122
|
-
for (const item of itemsWithoutSection)result.push({
|
|
123
|
-
type: 'item',
|
|
124
|
-
item
|
|
125
|
-
});
|
|
126
|
-
if (0 === itemsWithSection.length) return result;
|
|
127
|
-
const sections = Array.from(new Set(itemsWithSection.map((item)=>item.section)));
|
|
128
|
-
for (const section of sections){
|
|
129
|
-
result.push({
|
|
130
|
-
type: 'section',
|
|
131
|
-
sectionName: section
|
|
132
|
-
});
|
|
133
|
-
for (const item of itemsWithSection.filter((item)=>item.section === section))result.push({
|
|
134
|
-
type: 'item',
|
|
135
|
-
item
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return result;
|
|
139
|
-
}, [
|
|
145
|
+
const renderedItems = useMemo(()=>buildRenderedItems(items, enableSections), [
|
|
140
146
|
items,
|
|
141
147
|
enableSections
|
|
142
148
|
]);
|
|
149
|
+
useImperativeHandle(ref, ()=>({
|
|
150
|
+
renderedItems
|
|
151
|
+
}), [
|
|
152
|
+
renderedItems
|
|
153
|
+
]);
|
|
143
154
|
const rowProps = useMemo(()=>({
|
|
144
155
|
renderedItems,
|
|
156
|
+
activeIndex,
|
|
145
157
|
isLoading,
|
|
146
158
|
isDarkMode,
|
|
147
159
|
onItemClick,
|
|
148
160
|
onItemHover
|
|
149
161
|
}), [
|
|
150
162
|
renderedItems,
|
|
163
|
+
activeIndex,
|
|
151
164
|
isLoading,
|
|
152
165
|
isDarkMode,
|
|
153
166
|
onItemClick,
|
|
@@ -187,6 +200,9 @@ const ListView_ListView = /*#__PURE__*/ memo(function({ items, onItemClick, onIt
|
|
|
187
200
|
]
|
|
188
201
|
});
|
|
189
202
|
return /*#__PURE__*/ jsx(StyledList, {
|
|
203
|
+
id: "toolbox-listbox",
|
|
204
|
+
role: "listbox",
|
|
205
|
+
listRef: listRef,
|
|
190
206
|
rowProps: rowProps,
|
|
191
207
|
rowComponent: ListViewRow,
|
|
192
208
|
rowCount: renderedItems.length,
|
|
@@ -194,4 +210,5 @@ const ListView_ListView = /*#__PURE__*/ memo(function({ items, onItemClick, onIt
|
|
|
194
210
|
overscanCount: 20
|
|
195
211
|
});
|
|
196
212
|
});
|
|
197
|
-
|
|
213
|
+
const ListView_ListView = /*#__PURE__*/ memo(ListViewInner);
|
|
214
|
+
export { ListView_ListView as ListView, buildRenderedItems };
|
|
@@ -68,9 +68,15 @@ const ListItemButton = styled_default()(react_namespaceObject.motion.button)`
|
|
|
68
68
|
width: 100%;
|
|
69
69
|
transition: all 0.15s ease;
|
|
70
70
|
|
|
71
|
-
&:hover
|
|
71
|
+
&:hover,
|
|
72
|
+
&.active {
|
|
72
73
|
background: var(--uix-canvas-background-hover);
|
|
73
74
|
}
|
|
75
|
+
|
|
76
|
+
&.active {
|
|
77
|
+
outline: 1px solid var(--uix-canvas-primary);
|
|
78
|
+
outline-offset: -1px;
|
|
79
|
+
}
|
|
74
80
|
`;
|
|
75
81
|
const IconContainer = styled_default().div`
|
|
76
82
|
width: 32px;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListView.styles.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/ListView.styles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,eAAO,MAAM,aAAa;;;yGAazB,CAAC;AAEF,eAAO,MAAM,cAAc;;
|
|
1
|
+
{"version":3,"file":"ListView.styles.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/ListView.styles.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,eAAO,MAAM,aAAa;;;yGAazB,CAAC;AAEF,eAAO,MAAM,cAAc;;UAqB1B,CAAC;AAEF,eAAO,MAAM,aAAa;;;;cAA0B,MAAM;yGAazD,CAAC;AAEF,eAAO,MAAM,UAAU,EAkClB,OAAO,IAAI,CAAC"}
|
|
@@ -27,9 +27,15 @@ const ListItemButton = styled(motion.button)`
|
|
|
27
27
|
width: 100%;
|
|
28
28
|
transition: all 0.15s ease;
|
|
29
29
|
|
|
30
|
-
&:hover
|
|
30
|
+
&:hover,
|
|
31
|
+
&.active {
|
|
31
32
|
background: var(--uix-canvas-background-hover);
|
|
32
33
|
}
|
|
34
|
+
|
|
35
|
+
&.active {
|
|
36
|
+
outline: 1px solid var(--uix-canvas-primary);
|
|
37
|
+
outline-offset: -1px;
|
|
38
|
+
}
|
|
33
39
|
`;
|
|
34
40
|
const IconContainer = styled.div`
|
|
35
41
|
width: 32px;
|
|
@@ -31,11 +31,14 @@ const index_cjs_namespaceObject = require("../../utils/index.cjs");
|
|
|
31
31
|
const components_index_cjs_namespaceObject = require("../../../material/components/index.cjs");
|
|
32
32
|
const external_react_namespaceObject = require("react");
|
|
33
33
|
const external_SearchBox_styles_cjs_namespaceObject = require("./SearchBox.styles.cjs");
|
|
34
|
-
const SearchBox_SearchBox = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(function({ value, onChange, clear, placeholder = 'Search...' }) {
|
|
35
|
-
const
|
|
34
|
+
const SearchBox_SearchBox = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(function({ value, onChange, clear, placeholder = 'Search...', inputRef: externalInputRef, onNavigationKeyDown, activeDescendantId }) {
|
|
35
|
+
const internalRef = (0, external_react_namespaceObject.useRef)(null);
|
|
36
|
+
const inputRef = externalInputRef ?? internalRef;
|
|
36
37
|
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
37
38
|
inputRef.current?.focus();
|
|
38
|
-
}, [
|
|
39
|
+
}, [
|
|
40
|
+
inputRef
|
|
41
|
+
]);
|
|
39
42
|
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_SearchBox_styles_cjs_namespaceObject.StyledSearchForm, {
|
|
40
43
|
autoComplete: "off",
|
|
41
44
|
className: "searchbox-form",
|
|
@@ -56,10 +59,15 @@ const SearchBox_SearchBox = /*#__PURE__*/ (0, external_react_namespaceObject.mem
|
|
|
56
59
|
ref: inputRef,
|
|
57
60
|
autoComplete: "off",
|
|
58
61
|
type: "text",
|
|
62
|
+
role: "combobox",
|
|
63
|
+
"aria-controls": "toolbox-listbox",
|
|
64
|
+
"aria-expanded": true,
|
|
59
65
|
className: "searchbox-input",
|
|
60
66
|
placeholder: placeholder,
|
|
61
67
|
value: value,
|
|
62
|
-
onChange: (e)=>onChange(e.target.value)
|
|
68
|
+
onChange: (e)=>onChange(e.target.value),
|
|
69
|
+
onKeyDown: onNavigationKeyDown,
|
|
70
|
+
"aria-activedescendant": activeDescendantId
|
|
63
71
|
}),
|
|
64
72
|
value && /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)("button", {
|
|
65
73
|
type: "button",
|
|
@@ -3,6 +3,9 @@ interface SearchBoxProps {
|
|
|
3
3
|
onChange: (value: string) => void;
|
|
4
4
|
clear: () => void;
|
|
5
5
|
placeholder?: string;
|
|
6
|
+
inputRef?: React.RefObject<HTMLInputElement | null>;
|
|
7
|
+
onNavigationKeyDown?: (e: React.KeyboardEvent) => void;
|
|
8
|
+
activeDescendantId?: string;
|
|
6
9
|
}
|
|
7
10
|
export declare const SearchBox: import("react").NamedExoticComponent<SearchBoxProps>;
|
|
8
11
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBox.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/SearchBox.tsx"],"names":[],"mappings":"AAKA,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"SearchBox.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/SearchBox.tsx"],"names":[],"mappings":"AAKA,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;IACvD,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,eAAO,MAAM,SAAS,sDAgDpB,CAAC"}
|
|
@@ -3,11 +3,14 @@ import { cx } from "../../utils/index.js";
|
|
|
3
3
|
import { ApIcon } from "../../../material/components/index.js";
|
|
4
4
|
import { memo, useEffect, useRef } from "react";
|
|
5
5
|
import { StyledSearchForm } from "./SearchBox.styles.js";
|
|
6
|
-
const SearchBox_SearchBox = /*#__PURE__*/ memo(function({ value, onChange, clear, placeholder = 'Search...' }) {
|
|
7
|
-
const
|
|
6
|
+
const SearchBox_SearchBox = /*#__PURE__*/ memo(function({ value, onChange, clear, placeholder = 'Search...', inputRef: externalInputRef, onNavigationKeyDown, activeDescendantId }) {
|
|
7
|
+
const internalRef = useRef(null);
|
|
8
|
+
const inputRef = externalInputRef ?? internalRef;
|
|
8
9
|
useEffect(()=>{
|
|
9
10
|
inputRef.current?.focus();
|
|
10
|
-
}, [
|
|
11
|
+
}, [
|
|
12
|
+
inputRef
|
|
13
|
+
]);
|
|
11
14
|
return /*#__PURE__*/ jsx(StyledSearchForm, {
|
|
12
15
|
autoComplete: "off",
|
|
13
16
|
className: "searchbox-form",
|
|
@@ -28,10 +31,15 @@ const SearchBox_SearchBox = /*#__PURE__*/ memo(function({ value, onChange, clear
|
|
|
28
31
|
ref: inputRef,
|
|
29
32
|
autoComplete: "off",
|
|
30
33
|
type: "text",
|
|
34
|
+
role: "combobox",
|
|
35
|
+
"aria-controls": "toolbox-listbox",
|
|
36
|
+
"aria-expanded": true,
|
|
31
37
|
className: "searchbox-input",
|
|
32
38
|
placeholder: placeholder,
|
|
33
39
|
value: value,
|
|
34
|
-
onChange: (e)=>onChange(e.target.value)
|
|
40
|
+
onChange: (e)=>onChange(e.target.value),
|
|
41
|
+
onKeyDown: onNavigationKeyDown,
|
|
42
|
+
"aria-activedescendant": activeDescendantId
|
|
35
43
|
}),
|
|
36
44
|
value && /*#__PURE__*/ jsx("button", {
|
|
37
45
|
type: "button",
|
|
@@ -30,6 +30,7 @@ const jsx_runtime_namespaceObject = require("react/jsx-runtime");
|
|
|
30
30
|
const index_cjs_namespaceObject = require("../../hooks/index.cjs");
|
|
31
31
|
const external_layouts_index_cjs_namespaceObject = require("../../layouts/index.cjs");
|
|
32
32
|
const external_react_namespaceObject = require("react");
|
|
33
|
+
const external_react_window_namespaceObject = require("react-window");
|
|
33
34
|
const external_Header_cjs_namespaceObject = require("./Header.cjs");
|
|
34
35
|
const external_ListView_cjs_namespaceObject = require("./ListView.cjs");
|
|
35
36
|
const external_SearchBox_cjs_namespaceObject = require("./SearchBox.cjs");
|
|
@@ -52,6 +53,22 @@ function findItemById(items, id) {
|
|
|
52
53
|
}
|
|
53
54
|
return null;
|
|
54
55
|
}
|
|
56
|
+
function getNextSelectableIndex(renderedItems, currentIndex, direction) {
|
|
57
|
+
let next = currentIndex + direction;
|
|
58
|
+
while(next >= 0 && next < renderedItems.length){
|
|
59
|
+
if (renderedItems[next]?.type === 'item') return next;
|
|
60
|
+
next += direction;
|
|
61
|
+
}
|
|
62
|
+
return -1;
|
|
63
|
+
}
|
|
64
|
+
function getFirstSelectableIndex(renderedItems) {
|
|
65
|
+
for(let i = 0; i < renderedItems.length; i++)if (renderedItems[i]?.type === 'item') return i;
|
|
66
|
+
return -1;
|
|
67
|
+
}
|
|
68
|
+
function getLastSelectableIndex(renderedItems) {
|
|
69
|
+
for(let i = renderedItems.length - 1; i >= 0; i--)if (renderedItems[i]?.type === 'item') return i;
|
|
70
|
+
return -1;
|
|
71
|
+
}
|
|
55
72
|
function searchLeafItems(items, query) {
|
|
56
73
|
const results = [];
|
|
57
74
|
for (const item of items)if ('function' != typeof item.children) {
|
|
@@ -71,13 +88,23 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
71
88
|
const [isTransitioning, setIsTransitioning] = (0, external_react_namespaceObject.useState)(false);
|
|
72
89
|
const [animationDirection, setAnimationDirection] = (0, external_react_namespaceObject.useState)('forward');
|
|
73
90
|
const navigationStack = (0, index_cjs_namespaceObject.useNavigationStack)();
|
|
91
|
+
const [activeIndex, setActiveIndex] = (0, external_react_namespaceObject.useState)(-1);
|
|
74
92
|
const containerRef = (0, external_react_namespaceObject.useRef)(null);
|
|
75
93
|
const transitionTimeoutRef = (0, external_react_namespaceObject.useRef)(void 0);
|
|
76
94
|
const searchIdRef = (0, external_react_namespaceObject.useRef)(0);
|
|
77
95
|
const initialItemsRef = (0, external_react_namespaceObject.useRef)(initialItems);
|
|
96
|
+
const listRef = (0, external_react_window_namespaceObject.useListRef)(null);
|
|
97
|
+
const listViewRef = (0, external_react_namespaceObject.useRef)(null);
|
|
98
|
+
const searchInputRef = (0, external_react_namespaceObject.useRef)(null);
|
|
78
99
|
const isSearching = (0, external_react_namespaceObject.useMemo)(()=>search.length > 0, [
|
|
79
100
|
search
|
|
80
101
|
]);
|
|
102
|
+
const displayedItems = (0, external_react_namespaceObject.useMemo)(()=>isSearching && !isSearchingInitialItems ? searchedItems : items, [
|
|
103
|
+
isSearching,
|
|
104
|
+
isSearchingInitialItems,
|
|
105
|
+
searchedItems,
|
|
106
|
+
items
|
|
107
|
+
]);
|
|
81
108
|
const startTransition = (0, external_react_namespaceObject.useCallback)((direction)=>{
|
|
82
109
|
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
83
110
|
setIsTransitioning(true);
|
|
@@ -86,11 +113,22 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
86
113
|
setIsTransitioning(false);
|
|
87
114
|
}, TRANSITION_DURATION);
|
|
88
115
|
}, []);
|
|
116
|
+
const navigateToIndex = (0, external_react_namespaceObject.useCallback)((index)=>{
|
|
117
|
+
setActiveIndex(index);
|
|
118
|
+
if (-1 === index) return void searchInputRef.current?.focus();
|
|
119
|
+
listRef.current?.scrollToRow({
|
|
120
|
+
index,
|
|
121
|
+
align: 'auto'
|
|
122
|
+
});
|
|
123
|
+
}, [
|
|
124
|
+
listRef
|
|
125
|
+
]);
|
|
89
126
|
const clearSearch = (0, external_react_namespaceObject.useCallback)(()=>{
|
|
90
127
|
setSearch('');
|
|
91
128
|
setSearchedItems([]);
|
|
92
129
|
setSearchLoading(false);
|
|
93
130
|
setIsSearchingInitialItems(true);
|
|
131
|
+
setActiveIndex(-1);
|
|
94
132
|
}, []);
|
|
95
133
|
const handleSearch = (0, external_react_namespaceObject.useCallback)(async (query)=>{
|
|
96
134
|
if (!query.trim()) {
|
|
@@ -101,6 +139,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
101
139
|
return;
|
|
102
140
|
}
|
|
103
141
|
setSearch(query);
|
|
142
|
+
setActiveIndex(-1);
|
|
104
143
|
searchIdRef.current += 1;
|
|
105
144
|
const currentRequestId = searchIdRef.current;
|
|
106
145
|
setSearchLoading(true);
|
|
@@ -121,6 +160,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
121
160
|
]);
|
|
122
161
|
const handleBackTransition = (0, external_react_namespaceObject.useCallback)(()=>{
|
|
123
162
|
startTransition('back');
|
|
163
|
+
setActiveIndex(-1);
|
|
124
164
|
const previousState = navigationStack.pop();
|
|
125
165
|
if (previousState) {
|
|
126
166
|
setItems(previousState.data.items);
|
|
@@ -149,6 +189,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
149
189
|
setItems(nestedItems);
|
|
150
190
|
setCurrentParentItem(item);
|
|
151
191
|
clearSearch();
|
|
192
|
+
setActiveIndex(-1);
|
|
152
193
|
startTransition('forward');
|
|
153
194
|
setChildrenLoading(false);
|
|
154
195
|
}, [
|
|
@@ -206,6 +247,91 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
206
247
|
}, [
|
|
207
248
|
items
|
|
208
249
|
]);
|
|
250
|
+
const activeDescendantId = (0, external_react_namespaceObject.useMemo)(()=>{
|
|
251
|
+
if (activeIndex < 0) return;
|
|
252
|
+
const renderItem = listViewRef.current?.renderedItems[activeIndex];
|
|
253
|
+
if (renderItem?.type === 'item') return `toolbox-item-${renderItem.item.id}`;
|
|
254
|
+
}, [
|
|
255
|
+
activeIndex
|
|
256
|
+
]);
|
|
257
|
+
const handleNavigationKeyDown = (0, external_react_namespaceObject.useCallback)((e)=>{
|
|
258
|
+
if (isTransitioning) return;
|
|
259
|
+
const renderedItems = listViewRef.current?.renderedItems ?? [];
|
|
260
|
+
const navigateDown = ()=>{
|
|
261
|
+
if (-1 === activeIndex) {
|
|
262
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
263
|
+
if (-1 !== firstIndex) navigateToIndex(firstIndex);
|
|
264
|
+
} else {
|
|
265
|
+
const nextIndex = getNextSelectableIndex(renderedItems, activeIndex, 1);
|
|
266
|
+
if (-1 !== nextIndex) navigateToIndex(nextIndex);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
const navigateUp = ()=>{
|
|
270
|
+
activeIndex <= 0 || -1 === getNextSelectableIndex(renderedItems, activeIndex, -1) ? navigateToIndex(-1) : navigateToIndex(getNextSelectableIndex(renderedItems, activeIndex, -1));
|
|
271
|
+
};
|
|
272
|
+
switch(e.key){
|
|
273
|
+
case 'ArrowDown':
|
|
274
|
+
e.preventDefault();
|
|
275
|
+
navigateDown();
|
|
276
|
+
break;
|
|
277
|
+
case 'ArrowUp':
|
|
278
|
+
e.preventDefault();
|
|
279
|
+
navigateUp();
|
|
280
|
+
break;
|
|
281
|
+
case 'Enter':
|
|
282
|
+
if (activeIndex >= 0) {
|
|
283
|
+
const renderItem = renderedItems[activeIndex];
|
|
284
|
+
if (renderItem?.type === 'item') {
|
|
285
|
+
e.preventDefault();
|
|
286
|
+
handleItemSelect(renderItem.item);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
break;
|
|
290
|
+
case 'ArrowRight':
|
|
291
|
+
if (activeIndex >= 0) {
|
|
292
|
+
const renderItem = renderedItems[activeIndex];
|
|
293
|
+
if (renderItem?.type === 'item' && renderItem.item.children) {
|
|
294
|
+
e.preventDefault();
|
|
295
|
+
handleItemSelect(renderItem.item);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
case 'ArrowLeft':
|
|
300
|
+
if (activeIndex >= 0 && navigationStack.canGoBack) {
|
|
301
|
+
e.preventDefault();
|
|
302
|
+
handleBackTransition();
|
|
303
|
+
}
|
|
304
|
+
break;
|
|
305
|
+
case 'Tab':
|
|
306
|
+
e.preventDefault();
|
|
307
|
+
if (e.shiftKey) navigateUp();
|
|
308
|
+
else navigateDown();
|
|
309
|
+
break;
|
|
310
|
+
case 'Home':
|
|
311
|
+
{
|
|
312
|
+
if (-1 === activeIndex) break;
|
|
313
|
+
e.preventDefault();
|
|
314
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
315
|
+
if (-1 !== firstIndex) navigateToIndex(firstIndex);
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
case 'End':
|
|
319
|
+
{
|
|
320
|
+
if (-1 === activeIndex) break;
|
|
321
|
+
e.preventDefault();
|
|
322
|
+
const lastIndex = getLastSelectableIndex(renderedItems);
|
|
323
|
+
if (-1 !== lastIndex) navigateToIndex(lastIndex);
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}, [
|
|
328
|
+
isTransitioning,
|
|
329
|
+
activeIndex,
|
|
330
|
+
navigationStack.canGoBack,
|
|
331
|
+
navigateToIndex,
|
|
332
|
+
handleItemSelect,
|
|
333
|
+
handleBackTransition
|
|
334
|
+
]);
|
|
209
335
|
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
210
336
|
const handleKeyDown = (e)=>{
|
|
211
337
|
if ('Escape' === e.key) if (isSearching) {
|
|
@@ -251,19 +377,25 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
251
377
|
value: search,
|
|
252
378
|
onChange: handleSearch,
|
|
253
379
|
clear: clearSearch,
|
|
254
|
-
placeholder: "Search"
|
|
380
|
+
placeholder: "Search",
|
|
381
|
+
inputRef: searchInputRef,
|
|
382
|
+
onNavigationKeyDown: handleNavigationKeyDown,
|
|
383
|
+
activeDescendantId: activeDescendantId
|
|
255
384
|
}),
|
|
256
385
|
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Toolbox_styles_cjs_namespaceObject.AnimatedContainer, {
|
|
257
386
|
children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Toolbox_styles_cjs_namespaceObject.AnimatedContent, {
|
|
258
387
|
entering: isTransitioning,
|
|
259
388
|
direction: animationDirection,
|
|
260
389
|
children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_ListView_cjs_namespaceObject.ListView, {
|
|
390
|
+
ref: listViewRef,
|
|
261
391
|
isLoading: childrenLoading || searchLoading || loading,
|
|
262
|
-
items:
|
|
392
|
+
items: displayedItems,
|
|
393
|
+
activeIndex: activeIndex,
|
|
394
|
+
listRef: listRef,
|
|
263
395
|
emptyStateMessage: isSearching ? 'No matching nodes found' : 'No nodes found',
|
|
264
|
-
enableSections: !isSearching,
|
|
265
396
|
onItemClick: handleItemSelect,
|
|
266
|
-
onItemHover: onItemHover
|
|
397
|
+
onItemHover: onItemHover,
|
|
398
|
+
enableSections: !isSearching
|
|
267
399
|
})
|
|
268
400
|
})
|
|
269
401
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toolbox.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/Toolbox.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Toolbox.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/Toolbox.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,QAAQ,EAAkD,MAAM,YAAY,CAAC;AAuC3F,MAAM,MAAM,oBAAoB,CAAC,CAAC,GAAG,GAAG,IAAI,CAC1C,KAAK,EAAE,MAAM,EACb,gBAAgB,EAAE,OAAO,EACzB,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE;IAAE,YAAY,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAC5E,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAE5B,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC1D,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,oBAAoB,CAAC,CAAC,CAAC,CAAC;CACpC;AA+CD,wBAAgB,OAAO,CAAC,CAAC,EAAE,EACzB,OAAO,EACP,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,WAAW,EACX,KAAK,EACL,YAAY,EACZ,OAAO,GACR,EAAE,YAAY,CAAC,CAAC,CAAC,2CAqZjB"}
|
|
@@ -2,6 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useNavigationStack } from "../../hooks/index.js";
|
|
3
3
|
import { Column } from "../../layouts/index.js";
|
|
4
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { useListRef } from "react-window";
|
|
5
6
|
import { Header } from "./Header.js";
|
|
6
7
|
import { ListView } from "./ListView.js";
|
|
7
8
|
import { SearchBox } from "./SearchBox.js";
|
|
@@ -24,6 +25,22 @@ function findItemById(items, id) {
|
|
|
24
25
|
}
|
|
25
26
|
return null;
|
|
26
27
|
}
|
|
28
|
+
function getNextSelectableIndex(renderedItems, currentIndex, direction) {
|
|
29
|
+
let next = currentIndex + direction;
|
|
30
|
+
while(next >= 0 && next < renderedItems.length){
|
|
31
|
+
if (renderedItems[next]?.type === 'item') return next;
|
|
32
|
+
next += direction;
|
|
33
|
+
}
|
|
34
|
+
return -1;
|
|
35
|
+
}
|
|
36
|
+
function getFirstSelectableIndex(renderedItems) {
|
|
37
|
+
for(let i = 0; i < renderedItems.length; i++)if (renderedItems[i]?.type === 'item') return i;
|
|
38
|
+
return -1;
|
|
39
|
+
}
|
|
40
|
+
function getLastSelectableIndex(renderedItems) {
|
|
41
|
+
for(let i = renderedItems.length - 1; i >= 0; i--)if (renderedItems[i]?.type === 'item') return i;
|
|
42
|
+
return -1;
|
|
43
|
+
}
|
|
27
44
|
function searchLeafItems(items, query) {
|
|
28
45
|
const results = [];
|
|
29
46
|
for (const item of items)if ('function' != typeof item.children) {
|
|
@@ -43,13 +60,23 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
43
60
|
const [isTransitioning, setIsTransitioning] = useState(false);
|
|
44
61
|
const [animationDirection, setAnimationDirection] = useState('forward');
|
|
45
62
|
const navigationStack = useNavigationStack();
|
|
63
|
+
const [activeIndex, setActiveIndex] = useState(-1);
|
|
46
64
|
const containerRef = useRef(null);
|
|
47
65
|
const transitionTimeoutRef = useRef(void 0);
|
|
48
66
|
const searchIdRef = useRef(0);
|
|
49
67
|
const initialItemsRef = useRef(initialItems);
|
|
68
|
+
const listRef = useListRef(null);
|
|
69
|
+
const listViewRef = useRef(null);
|
|
70
|
+
const searchInputRef = useRef(null);
|
|
50
71
|
const isSearching = useMemo(()=>search.length > 0, [
|
|
51
72
|
search
|
|
52
73
|
]);
|
|
74
|
+
const displayedItems = useMemo(()=>isSearching && !isSearchingInitialItems ? searchedItems : items, [
|
|
75
|
+
isSearching,
|
|
76
|
+
isSearchingInitialItems,
|
|
77
|
+
searchedItems,
|
|
78
|
+
items
|
|
79
|
+
]);
|
|
53
80
|
const startTransition = useCallback((direction)=>{
|
|
54
81
|
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
55
82
|
setIsTransitioning(true);
|
|
@@ -58,11 +85,22 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
58
85
|
setIsTransitioning(false);
|
|
59
86
|
}, TRANSITION_DURATION);
|
|
60
87
|
}, []);
|
|
88
|
+
const navigateToIndex = useCallback((index)=>{
|
|
89
|
+
setActiveIndex(index);
|
|
90
|
+
if (-1 === index) return void searchInputRef.current?.focus();
|
|
91
|
+
listRef.current?.scrollToRow({
|
|
92
|
+
index,
|
|
93
|
+
align: 'auto'
|
|
94
|
+
});
|
|
95
|
+
}, [
|
|
96
|
+
listRef
|
|
97
|
+
]);
|
|
61
98
|
const clearSearch = useCallback(()=>{
|
|
62
99
|
setSearch('');
|
|
63
100
|
setSearchedItems([]);
|
|
64
101
|
setSearchLoading(false);
|
|
65
102
|
setIsSearchingInitialItems(true);
|
|
103
|
+
setActiveIndex(-1);
|
|
66
104
|
}, []);
|
|
67
105
|
const handleSearch = useCallback(async (query)=>{
|
|
68
106
|
if (!query.trim()) {
|
|
@@ -73,6 +111,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
73
111
|
return;
|
|
74
112
|
}
|
|
75
113
|
setSearch(query);
|
|
114
|
+
setActiveIndex(-1);
|
|
76
115
|
searchIdRef.current += 1;
|
|
77
116
|
const currentRequestId = searchIdRef.current;
|
|
78
117
|
setSearchLoading(true);
|
|
@@ -93,6 +132,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
93
132
|
]);
|
|
94
133
|
const handleBackTransition = useCallback(()=>{
|
|
95
134
|
startTransition('back');
|
|
135
|
+
setActiveIndex(-1);
|
|
96
136
|
const previousState = navigationStack.pop();
|
|
97
137
|
if (previousState) {
|
|
98
138
|
setItems(previousState.data.items);
|
|
@@ -121,6 +161,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
121
161
|
setItems(nestedItems);
|
|
122
162
|
setCurrentParentItem(item);
|
|
123
163
|
clearSearch();
|
|
164
|
+
setActiveIndex(-1);
|
|
124
165
|
startTransition('forward');
|
|
125
166
|
setChildrenLoading(false);
|
|
126
167
|
}, [
|
|
@@ -178,6 +219,91 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
178
219
|
}, [
|
|
179
220
|
items
|
|
180
221
|
]);
|
|
222
|
+
const activeDescendantId = useMemo(()=>{
|
|
223
|
+
if (activeIndex < 0) return;
|
|
224
|
+
const renderItem = listViewRef.current?.renderedItems[activeIndex];
|
|
225
|
+
if (renderItem?.type === 'item') return `toolbox-item-${renderItem.item.id}`;
|
|
226
|
+
}, [
|
|
227
|
+
activeIndex
|
|
228
|
+
]);
|
|
229
|
+
const handleNavigationKeyDown = useCallback((e)=>{
|
|
230
|
+
if (isTransitioning) return;
|
|
231
|
+
const renderedItems = listViewRef.current?.renderedItems ?? [];
|
|
232
|
+
const navigateDown = ()=>{
|
|
233
|
+
if (-1 === activeIndex) {
|
|
234
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
235
|
+
if (-1 !== firstIndex) navigateToIndex(firstIndex);
|
|
236
|
+
} else {
|
|
237
|
+
const nextIndex = getNextSelectableIndex(renderedItems, activeIndex, 1);
|
|
238
|
+
if (-1 !== nextIndex) navigateToIndex(nextIndex);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
const navigateUp = ()=>{
|
|
242
|
+
activeIndex <= 0 || -1 === getNextSelectableIndex(renderedItems, activeIndex, -1) ? navigateToIndex(-1) : navigateToIndex(getNextSelectableIndex(renderedItems, activeIndex, -1));
|
|
243
|
+
};
|
|
244
|
+
switch(e.key){
|
|
245
|
+
case 'ArrowDown':
|
|
246
|
+
e.preventDefault();
|
|
247
|
+
navigateDown();
|
|
248
|
+
break;
|
|
249
|
+
case 'ArrowUp':
|
|
250
|
+
e.preventDefault();
|
|
251
|
+
navigateUp();
|
|
252
|
+
break;
|
|
253
|
+
case 'Enter':
|
|
254
|
+
if (activeIndex >= 0) {
|
|
255
|
+
const renderItem = renderedItems[activeIndex];
|
|
256
|
+
if (renderItem?.type === 'item') {
|
|
257
|
+
e.preventDefault();
|
|
258
|
+
handleItemSelect(renderItem.item);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
case 'ArrowRight':
|
|
263
|
+
if (activeIndex >= 0) {
|
|
264
|
+
const renderItem = renderedItems[activeIndex];
|
|
265
|
+
if (renderItem?.type === 'item' && renderItem.item.children) {
|
|
266
|
+
e.preventDefault();
|
|
267
|
+
handleItemSelect(renderItem.item);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
break;
|
|
271
|
+
case 'ArrowLeft':
|
|
272
|
+
if (activeIndex >= 0 && navigationStack.canGoBack) {
|
|
273
|
+
e.preventDefault();
|
|
274
|
+
handleBackTransition();
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
case 'Tab':
|
|
278
|
+
e.preventDefault();
|
|
279
|
+
if (e.shiftKey) navigateUp();
|
|
280
|
+
else navigateDown();
|
|
281
|
+
break;
|
|
282
|
+
case 'Home':
|
|
283
|
+
{
|
|
284
|
+
if (-1 === activeIndex) break;
|
|
285
|
+
e.preventDefault();
|
|
286
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
287
|
+
if (-1 !== firstIndex) navigateToIndex(firstIndex);
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
case 'End':
|
|
291
|
+
{
|
|
292
|
+
if (-1 === activeIndex) break;
|
|
293
|
+
e.preventDefault();
|
|
294
|
+
const lastIndex = getLastSelectableIndex(renderedItems);
|
|
295
|
+
if (-1 !== lastIndex) navigateToIndex(lastIndex);
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}, [
|
|
300
|
+
isTransitioning,
|
|
301
|
+
activeIndex,
|
|
302
|
+
navigationStack.canGoBack,
|
|
303
|
+
navigateToIndex,
|
|
304
|
+
handleItemSelect,
|
|
305
|
+
handleBackTransition
|
|
306
|
+
]);
|
|
181
307
|
useEffect(()=>{
|
|
182
308
|
const handleKeyDown = (e)=>{
|
|
183
309
|
if ('Escape' === e.key) if (isSearching) {
|
|
@@ -223,19 +349,25 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
223
349
|
value: search,
|
|
224
350
|
onChange: handleSearch,
|
|
225
351
|
clear: clearSearch,
|
|
226
|
-
placeholder: "Search"
|
|
352
|
+
placeholder: "Search",
|
|
353
|
+
inputRef: searchInputRef,
|
|
354
|
+
onNavigationKeyDown: handleNavigationKeyDown,
|
|
355
|
+
activeDescendantId: activeDescendantId
|
|
227
356
|
}),
|
|
228
357
|
/*#__PURE__*/ jsx(AnimatedContainer, {
|
|
229
358
|
children: /*#__PURE__*/ jsx(AnimatedContent, {
|
|
230
359
|
entering: isTransitioning,
|
|
231
360
|
direction: animationDirection,
|
|
232
361
|
children: /*#__PURE__*/ jsx(ListView, {
|
|
362
|
+
ref: listViewRef,
|
|
233
363
|
isLoading: childrenLoading || searchLoading || loading,
|
|
234
|
-
items:
|
|
364
|
+
items: displayedItems,
|
|
365
|
+
activeIndex: activeIndex,
|
|
366
|
+
listRef: listRef,
|
|
235
367
|
emptyStateMessage: isSearching ? 'No matching nodes found' : 'No nodes found',
|
|
236
|
-
enableSections: !isSearching,
|
|
237
368
|
onItemClick: handleItemSelect,
|
|
238
|
-
onItemHover: onItemHover
|
|
369
|
+
onItemHover: onItemHover,
|
|
370
|
+
enableSections: !isSearching
|
|
239
371
|
})
|
|
240
372
|
})
|
|
241
373
|
})
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/apollo-react",
|
|
3
|
-
"version": "3.54.0-pr354.
|
|
3
|
+
"version": "3.54.0-pr354.f799733",
|
|
4
4
|
"description": "Apollo Design System - React component library with Material UI theming",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
"zod": "^4.3.5",
|
|
202
202
|
"zustand": "^5.0.9",
|
|
203
203
|
"@uipath/apollo-core": "5.7.1",
|
|
204
|
-
"@uipath/apollo-wind": "0.
|
|
204
|
+
"@uipath/apollo-wind": "0.15.0"
|
|
205
205
|
},
|
|
206
206
|
"devDependencies": {
|
|
207
207
|
"@lingui/cli": "^5.6.1",
|