@uipath/apollo-react 3.55.1 → 3.56.0-pr364.24cd059
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/AddNodePanel/AddNodePanel.cjs +1 -1
- package/dist/canvas/components/AddNodePanel/AddNodePanel.js +1 -1
- package/dist/canvas/components/StageNode/StageNode.cjs +1 -0
- package/dist/canvas/components/StageNode/StageNode.d.ts.map +1 -1
- package/dist/canvas/components/StageNode/StageNode.js +1 -0
- 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 +143 -4
- package/dist/canvas/components/Toolbox/Toolbox.d.ts.map +1 -1
- package/dist/canvas/components/Toolbox/Toolbox.js +143 -4
- package/package.json +1 -1
|
@@ -69,7 +69,7 @@ const AddNodePanel_AddNodePanel = /*#__PURE__*/ (0, external_react_namespaceObje
|
|
|
69
69
|
onNodeSelect
|
|
70
70
|
]);
|
|
71
71
|
return /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Toolbox_index_cjs_namespaceObject.Toolbox, {
|
|
72
|
-
title: title ?? 'Add
|
|
72
|
+
title: title ?? 'Add node',
|
|
73
73
|
initialItems: nodeListOptions,
|
|
74
74
|
loading: loading,
|
|
75
75
|
onItemSelect: handleNodeListItemSelect,
|
|
@@ -41,7 +41,7 @@ const AddNodePanel_AddNodePanel = /*#__PURE__*/ memo(function({ onNodeSelect, on
|
|
|
41
41
|
onNodeSelect
|
|
42
42
|
]);
|
|
43
43
|
return /*#__PURE__*/ jsx(Toolbox, {
|
|
44
|
-
title: title ?? 'Add
|
|
44
|
+
title: title ?? 'Add node',
|
|
45
45
|
initialItems: nodeListOptions,
|
|
46
46
|
loading: loading,
|
|
47
47
|
onItemSelect: handleNodeListItemSelect,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StageNode.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/StageNode/StageNode.tsx"],"names":[],"mappings":"AAqDA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"StageNode.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/StageNode/StageNode.tsx"],"names":[],"mappings":"AAqDA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAmpBxD,eAAO,MAAM,SAAS,8CAzoBa,cAAc,6CAyoBA,CAAC"}
|
|
@@ -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,11 +30,13 @@ 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");
|
|
36
37
|
const external_Toolbox_styles_cjs_namespaceObject = require("./Toolbox.styles.cjs");
|
|
37
38
|
const TRANSITION_DURATION = 150;
|
|
39
|
+
const SEARCH_BAR_INDEX = -1;
|
|
38
40
|
function findItemById(items, id) {
|
|
39
41
|
const queue = [
|
|
40
42
|
...items
|
|
@@ -52,6 +54,23 @@ function findItemById(items, id) {
|
|
|
52
54
|
}
|
|
53
55
|
return null;
|
|
54
56
|
}
|
|
57
|
+
function getNextSelectableIndex(renderedItems, currentIndex, direction) {
|
|
58
|
+
const numericDirection = 'up' === direction ? -1 : 1;
|
|
59
|
+
let next = currentIndex + numericDirection;
|
|
60
|
+
while(next >= 0 && next < renderedItems.length){
|
|
61
|
+
if (renderedItems[next]?.type === 'item') return next;
|
|
62
|
+
next += numericDirection;
|
|
63
|
+
}
|
|
64
|
+
return SEARCH_BAR_INDEX;
|
|
65
|
+
}
|
|
66
|
+
function getFirstSelectableIndex(renderedItems) {
|
|
67
|
+
for(let i = 0; i < renderedItems.length; i++)if (renderedItems[i]?.type === 'item') return i;
|
|
68
|
+
return SEARCH_BAR_INDEX;
|
|
69
|
+
}
|
|
70
|
+
function getLastSelectableIndex(renderedItems) {
|
|
71
|
+
for(let i = renderedItems.length - 1; i >= 0; i--)if (renderedItems[i]?.type === 'item') return i;
|
|
72
|
+
return SEARCH_BAR_INDEX;
|
|
73
|
+
}
|
|
55
74
|
function searchLeafItems(items, query) {
|
|
56
75
|
const results = [];
|
|
57
76
|
for (const item of items)if ('function' != typeof item.children) {
|
|
@@ -71,13 +90,23 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
71
90
|
const [isTransitioning, setIsTransitioning] = (0, external_react_namespaceObject.useState)(false);
|
|
72
91
|
const [animationDirection, setAnimationDirection] = (0, external_react_namespaceObject.useState)('forward');
|
|
73
92
|
const navigationStack = (0, index_cjs_namespaceObject.useNavigationStack)();
|
|
93
|
+
const [activeIndex, setActiveIndex] = (0, external_react_namespaceObject.useState)(SEARCH_BAR_INDEX);
|
|
74
94
|
const containerRef = (0, external_react_namespaceObject.useRef)(null);
|
|
75
95
|
const transitionTimeoutRef = (0, external_react_namespaceObject.useRef)(void 0);
|
|
76
96
|
const searchIdRef = (0, external_react_namespaceObject.useRef)(0);
|
|
77
97
|
const initialItemsRef = (0, external_react_namespaceObject.useRef)(initialItems);
|
|
98
|
+
const listRef = (0, external_react_window_namespaceObject.useListRef)(null);
|
|
99
|
+
const listViewRef = (0, external_react_namespaceObject.useRef)(null);
|
|
100
|
+
const searchInputRef = (0, external_react_namespaceObject.useRef)(null);
|
|
78
101
|
const isSearching = (0, external_react_namespaceObject.useMemo)(()=>search.length > 0, [
|
|
79
102
|
search
|
|
80
103
|
]);
|
|
104
|
+
const displayedItems = (0, external_react_namespaceObject.useMemo)(()=>isSearching && !isSearchingInitialItems ? searchedItems : items, [
|
|
105
|
+
isSearching,
|
|
106
|
+
isSearchingInitialItems,
|
|
107
|
+
searchedItems,
|
|
108
|
+
items
|
|
109
|
+
]);
|
|
81
110
|
const startTransition = (0, external_react_namespaceObject.useCallback)((direction)=>{
|
|
82
111
|
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
83
112
|
setIsTransitioning(true);
|
|
@@ -86,11 +115,22 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
86
115
|
setIsTransitioning(false);
|
|
87
116
|
}, TRANSITION_DURATION);
|
|
88
117
|
}, []);
|
|
118
|
+
const navigateToIndex = (0, external_react_namespaceObject.useCallback)((index)=>{
|
|
119
|
+
setActiveIndex(index);
|
|
120
|
+
if (index === SEARCH_BAR_INDEX) return void searchInputRef.current?.focus();
|
|
121
|
+
listRef.current?.scrollToRow({
|
|
122
|
+
index,
|
|
123
|
+
align: 'auto'
|
|
124
|
+
});
|
|
125
|
+
}, [
|
|
126
|
+
listRef
|
|
127
|
+
]);
|
|
89
128
|
const clearSearch = (0, external_react_namespaceObject.useCallback)(()=>{
|
|
90
129
|
setSearch('');
|
|
91
130
|
setSearchedItems([]);
|
|
92
131
|
setSearchLoading(false);
|
|
93
132
|
setIsSearchingInitialItems(true);
|
|
133
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
94
134
|
}, []);
|
|
95
135
|
const handleSearch = (0, external_react_namespaceObject.useCallback)(async (query)=>{
|
|
96
136
|
if (!query.trim()) {
|
|
@@ -101,6 +141,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
101
141
|
return;
|
|
102
142
|
}
|
|
103
143
|
setSearch(query);
|
|
144
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
104
145
|
searchIdRef.current += 1;
|
|
105
146
|
const currentRequestId = searchIdRef.current;
|
|
106
147
|
setSearchLoading(true);
|
|
@@ -121,6 +162,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
121
162
|
]);
|
|
122
163
|
const handleBackTransition = (0, external_react_namespaceObject.useCallback)(()=>{
|
|
123
164
|
startTransition('back');
|
|
165
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
124
166
|
const previousState = navigationStack.pop();
|
|
125
167
|
if (previousState) {
|
|
126
168
|
setItems(previousState.data.items);
|
|
@@ -149,6 +191,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
149
191
|
setItems(nestedItems);
|
|
150
192
|
setCurrentParentItem(item);
|
|
151
193
|
clearSearch();
|
|
194
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
152
195
|
startTransition('forward');
|
|
153
196
|
setChildrenLoading(false);
|
|
154
197
|
}, [
|
|
@@ -206,6 +249,96 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
206
249
|
}, [
|
|
207
250
|
items
|
|
208
251
|
]);
|
|
252
|
+
const activeDescendantId = (0, external_react_namespaceObject.useMemo)(()=>{
|
|
253
|
+
if (activeIndex < 0) return;
|
|
254
|
+
const renderItem = listViewRef.current?.renderedItems[activeIndex];
|
|
255
|
+
if (renderItem?.type === 'item') return `toolbox-item-${renderItem.item.id}`;
|
|
256
|
+
}, [
|
|
257
|
+
activeIndex
|
|
258
|
+
]);
|
|
259
|
+
const handleNavigationKeyDown = (0, external_react_namespaceObject.useCallback)((e)=>{
|
|
260
|
+
if (isTransitioning) return;
|
|
261
|
+
const renderedItems = listViewRef.current?.renderedItems ?? [];
|
|
262
|
+
const navigateDown = ()=>{
|
|
263
|
+
if (activeIndex === SEARCH_BAR_INDEX) {
|
|
264
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
265
|
+
if (firstIndex !== SEARCH_BAR_INDEX) navigateToIndex(firstIndex);
|
|
266
|
+
} else {
|
|
267
|
+
const nextIndex = getNextSelectableIndex(renderedItems, activeIndex, 'down');
|
|
268
|
+
if (nextIndex !== SEARCH_BAR_INDEX) navigateToIndex(nextIndex);
|
|
269
|
+
else {
|
|
270
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
271
|
+
if (firstIndex !== SEARCH_BAR_INDEX) navigateToIndex(firstIndex);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
const navigateUp = ()=>{
|
|
276
|
+
navigateToIndex(getNextSelectableIndex(renderedItems, activeIndex, 'up'));
|
|
277
|
+
};
|
|
278
|
+
switch(e.key){
|
|
279
|
+
case 'ArrowDown':
|
|
280
|
+
e.preventDefault();
|
|
281
|
+
navigateDown();
|
|
282
|
+
break;
|
|
283
|
+
case 'ArrowUp':
|
|
284
|
+
e.preventDefault();
|
|
285
|
+
navigateUp();
|
|
286
|
+
break;
|
|
287
|
+
case 'Enter':
|
|
288
|
+
{
|
|
289
|
+
if (activeIndex === SEARCH_BAR_INDEX) break;
|
|
290
|
+
const renderItem = renderedItems[activeIndex];
|
|
291
|
+
if (renderItem?.type === 'item') {
|
|
292
|
+
e.preventDefault();
|
|
293
|
+
handleItemSelect(renderItem.item);
|
|
294
|
+
}
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
case 'ArrowRight':
|
|
298
|
+
{
|
|
299
|
+
const renderItem = renderedItems[activeIndex];
|
|
300
|
+
if (renderItem?.type === 'item' && renderItem.item.children) {
|
|
301
|
+
e.preventDefault();
|
|
302
|
+
handleItemSelect(renderItem.item);
|
|
303
|
+
}
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
case 'ArrowLeft':
|
|
307
|
+
if (!navigationStack.canGoBack || activeIndex === SEARCH_BAR_INDEX && search.length > 0) return;
|
|
308
|
+
e.preventDefault();
|
|
309
|
+
handleBackTransition();
|
|
310
|
+
break;
|
|
311
|
+
case 'Tab':
|
|
312
|
+
e.preventDefault();
|
|
313
|
+
if (e.shiftKey) navigateUp();
|
|
314
|
+
else navigateDown();
|
|
315
|
+
break;
|
|
316
|
+
case 'Home':
|
|
317
|
+
{
|
|
318
|
+
if (activeIndex === SEARCH_BAR_INDEX) break;
|
|
319
|
+
e.preventDefault();
|
|
320
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
321
|
+
if (firstIndex !== SEARCH_BAR_INDEX) navigateToIndex(firstIndex);
|
|
322
|
+
break;
|
|
323
|
+
}
|
|
324
|
+
case 'End':
|
|
325
|
+
{
|
|
326
|
+
if (activeIndex === SEARCH_BAR_INDEX) break;
|
|
327
|
+
e.preventDefault();
|
|
328
|
+
const lastIndex = getLastSelectableIndex(renderedItems);
|
|
329
|
+
if (lastIndex !== SEARCH_BAR_INDEX) navigateToIndex(lastIndex);
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}, [
|
|
334
|
+
search,
|
|
335
|
+
isTransitioning,
|
|
336
|
+
activeIndex,
|
|
337
|
+
navigationStack.canGoBack,
|
|
338
|
+
navigateToIndex,
|
|
339
|
+
handleItemSelect,
|
|
340
|
+
handleBackTransition
|
|
341
|
+
]);
|
|
209
342
|
(0, external_react_namespaceObject.useEffect)(()=>{
|
|
210
343
|
const handleKeyDown = (e)=>{
|
|
211
344
|
if ('Escape' === e.key) if (isSearching) {
|
|
@@ -251,19 +384,25 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
251
384
|
value: search,
|
|
252
385
|
onChange: handleSearch,
|
|
253
386
|
clear: clearSearch,
|
|
254
|
-
placeholder: "Search"
|
|
387
|
+
placeholder: "Search",
|
|
388
|
+
inputRef: searchInputRef,
|
|
389
|
+
onNavigationKeyDown: handleNavigationKeyDown,
|
|
390
|
+
activeDescendantId: activeDescendantId
|
|
255
391
|
}),
|
|
256
392
|
/*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Toolbox_styles_cjs_namespaceObject.AnimatedContainer, {
|
|
257
393
|
children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Toolbox_styles_cjs_namespaceObject.AnimatedContent, {
|
|
258
394
|
entering: isTransitioning,
|
|
259
395
|
direction: animationDirection,
|
|
260
396
|
children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_ListView_cjs_namespaceObject.ListView, {
|
|
397
|
+
ref: listViewRef,
|
|
261
398
|
isLoading: childrenLoading || searchLoading || loading,
|
|
262
|
-
items:
|
|
399
|
+
items: displayedItems,
|
|
400
|
+
activeIndex: activeIndex,
|
|
401
|
+
listRef: listRef,
|
|
263
402
|
emptyStateMessage: isSearching ? 'No matching nodes found' : 'No nodes found',
|
|
264
|
-
enableSections: !isSearching,
|
|
265
403
|
onItemClick: handleItemSelect,
|
|
266
|
-
onItemHover: onItemHover
|
|
404
|
+
onItemHover: onItemHover,
|
|
405
|
+
enableSections: !isSearching
|
|
267
406
|
})
|
|
268
407
|
})
|
|
269
408
|
})
|
|
@@ -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;AAwC3F,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;AAgDD,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,2CAsZjB"}
|
|
@@ -2,11 +2,13 @@ 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";
|
|
8
9
|
import { AnimatedContainer, AnimatedContent } from "./Toolbox.styles.js";
|
|
9
10
|
const TRANSITION_DURATION = 150;
|
|
11
|
+
const SEARCH_BAR_INDEX = -1;
|
|
10
12
|
function findItemById(items, id) {
|
|
11
13
|
const queue = [
|
|
12
14
|
...items
|
|
@@ -24,6 +26,23 @@ function findItemById(items, id) {
|
|
|
24
26
|
}
|
|
25
27
|
return null;
|
|
26
28
|
}
|
|
29
|
+
function getNextSelectableIndex(renderedItems, currentIndex, direction) {
|
|
30
|
+
const numericDirection = 'up' === direction ? -1 : 1;
|
|
31
|
+
let next = currentIndex + numericDirection;
|
|
32
|
+
while(next >= 0 && next < renderedItems.length){
|
|
33
|
+
if (renderedItems[next]?.type === 'item') return next;
|
|
34
|
+
next += numericDirection;
|
|
35
|
+
}
|
|
36
|
+
return SEARCH_BAR_INDEX;
|
|
37
|
+
}
|
|
38
|
+
function getFirstSelectableIndex(renderedItems) {
|
|
39
|
+
for(let i = 0; i < renderedItems.length; i++)if (renderedItems[i]?.type === 'item') return i;
|
|
40
|
+
return SEARCH_BAR_INDEX;
|
|
41
|
+
}
|
|
42
|
+
function getLastSelectableIndex(renderedItems) {
|
|
43
|
+
for(let i = renderedItems.length - 1; i >= 0; i--)if (renderedItems[i]?.type === 'item') return i;
|
|
44
|
+
return SEARCH_BAR_INDEX;
|
|
45
|
+
}
|
|
27
46
|
function searchLeafItems(items, query) {
|
|
28
47
|
const results = [];
|
|
29
48
|
for (const item of items)if ('function' != typeof item.children) {
|
|
@@ -43,13 +62,23 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
43
62
|
const [isTransitioning, setIsTransitioning] = useState(false);
|
|
44
63
|
const [animationDirection, setAnimationDirection] = useState('forward');
|
|
45
64
|
const navigationStack = useNavigationStack();
|
|
65
|
+
const [activeIndex, setActiveIndex] = useState(SEARCH_BAR_INDEX);
|
|
46
66
|
const containerRef = useRef(null);
|
|
47
67
|
const transitionTimeoutRef = useRef(void 0);
|
|
48
68
|
const searchIdRef = useRef(0);
|
|
49
69
|
const initialItemsRef = useRef(initialItems);
|
|
70
|
+
const listRef = useListRef(null);
|
|
71
|
+
const listViewRef = useRef(null);
|
|
72
|
+
const searchInputRef = useRef(null);
|
|
50
73
|
const isSearching = useMemo(()=>search.length > 0, [
|
|
51
74
|
search
|
|
52
75
|
]);
|
|
76
|
+
const displayedItems = useMemo(()=>isSearching && !isSearchingInitialItems ? searchedItems : items, [
|
|
77
|
+
isSearching,
|
|
78
|
+
isSearchingInitialItems,
|
|
79
|
+
searchedItems,
|
|
80
|
+
items
|
|
81
|
+
]);
|
|
53
82
|
const startTransition = useCallback((direction)=>{
|
|
54
83
|
if (transitionTimeoutRef.current) clearTimeout(transitionTimeoutRef.current);
|
|
55
84
|
setIsTransitioning(true);
|
|
@@ -58,11 +87,22 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
58
87
|
setIsTransitioning(false);
|
|
59
88
|
}, TRANSITION_DURATION);
|
|
60
89
|
}, []);
|
|
90
|
+
const navigateToIndex = useCallback((index)=>{
|
|
91
|
+
setActiveIndex(index);
|
|
92
|
+
if (index === SEARCH_BAR_INDEX) return void searchInputRef.current?.focus();
|
|
93
|
+
listRef.current?.scrollToRow({
|
|
94
|
+
index,
|
|
95
|
+
align: 'auto'
|
|
96
|
+
});
|
|
97
|
+
}, [
|
|
98
|
+
listRef
|
|
99
|
+
]);
|
|
61
100
|
const clearSearch = useCallback(()=>{
|
|
62
101
|
setSearch('');
|
|
63
102
|
setSearchedItems([]);
|
|
64
103
|
setSearchLoading(false);
|
|
65
104
|
setIsSearchingInitialItems(true);
|
|
105
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
66
106
|
}, []);
|
|
67
107
|
const handleSearch = useCallback(async (query)=>{
|
|
68
108
|
if (!query.trim()) {
|
|
@@ -73,6 +113,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
73
113
|
return;
|
|
74
114
|
}
|
|
75
115
|
setSearch(query);
|
|
116
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
76
117
|
searchIdRef.current += 1;
|
|
77
118
|
const currentRequestId = searchIdRef.current;
|
|
78
119
|
setSearchLoading(true);
|
|
@@ -93,6 +134,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
93
134
|
]);
|
|
94
135
|
const handleBackTransition = useCallback(()=>{
|
|
95
136
|
startTransition('back');
|
|
137
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
96
138
|
const previousState = navigationStack.pop();
|
|
97
139
|
if (previousState) {
|
|
98
140
|
setItems(previousState.data.items);
|
|
@@ -121,6 +163,7 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
121
163
|
setItems(nestedItems);
|
|
122
164
|
setCurrentParentItem(item);
|
|
123
165
|
clearSearch();
|
|
166
|
+
setActiveIndex(SEARCH_BAR_INDEX);
|
|
124
167
|
startTransition('forward');
|
|
125
168
|
setChildrenLoading(false);
|
|
126
169
|
}, [
|
|
@@ -178,6 +221,96 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
178
221
|
}, [
|
|
179
222
|
items
|
|
180
223
|
]);
|
|
224
|
+
const activeDescendantId = useMemo(()=>{
|
|
225
|
+
if (activeIndex < 0) return;
|
|
226
|
+
const renderItem = listViewRef.current?.renderedItems[activeIndex];
|
|
227
|
+
if (renderItem?.type === 'item') return `toolbox-item-${renderItem.item.id}`;
|
|
228
|
+
}, [
|
|
229
|
+
activeIndex
|
|
230
|
+
]);
|
|
231
|
+
const handleNavigationKeyDown = useCallback((e)=>{
|
|
232
|
+
if (isTransitioning) return;
|
|
233
|
+
const renderedItems = listViewRef.current?.renderedItems ?? [];
|
|
234
|
+
const navigateDown = ()=>{
|
|
235
|
+
if (activeIndex === SEARCH_BAR_INDEX) {
|
|
236
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
237
|
+
if (firstIndex !== SEARCH_BAR_INDEX) navigateToIndex(firstIndex);
|
|
238
|
+
} else {
|
|
239
|
+
const nextIndex = getNextSelectableIndex(renderedItems, activeIndex, 'down');
|
|
240
|
+
if (nextIndex !== SEARCH_BAR_INDEX) navigateToIndex(nextIndex);
|
|
241
|
+
else {
|
|
242
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
243
|
+
if (firstIndex !== SEARCH_BAR_INDEX) navigateToIndex(firstIndex);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
const navigateUp = ()=>{
|
|
248
|
+
navigateToIndex(getNextSelectableIndex(renderedItems, activeIndex, 'up'));
|
|
249
|
+
};
|
|
250
|
+
switch(e.key){
|
|
251
|
+
case 'ArrowDown':
|
|
252
|
+
e.preventDefault();
|
|
253
|
+
navigateDown();
|
|
254
|
+
break;
|
|
255
|
+
case 'ArrowUp':
|
|
256
|
+
e.preventDefault();
|
|
257
|
+
navigateUp();
|
|
258
|
+
break;
|
|
259
|
+
case 'Enter':
|
|
260
|
+
{
|
|
261
|
+
if (activeIndex === SEARCH_BAR_INDEX) break;
|
|
262
|
+
const renderItem = renderedItems[activeIndex];
|
|
263
|
+
if (renderItem?.type === 'item') {
|
|
264
|
+
e.preventDefault();
|
|
265
|
+
handleItemSelect(renderItem.item);
|
|
266
|
+
}
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
case 'ArrowRight':
|
|
270
|
+
{
|
|
271
|
+
const renderItem = renderedItems[activeIndex];
|
|
272
|
+
if (renderItem?.type === 'item' && renderItem.item.children) {
|
|
273
|
+
e.preventDefault();
|
|
274
|
+
handleItemSelect(renderItem.item);
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
case 'ArrowLeft':
|
|
279
|
+
if (!navigationStack.canGoBack || activeIndex === SEARCH_BAR_INDEX && search.length > 0) return;
|
|
280
|
+
e.preventDefault();
|
|
281
|
+
handleBackTransition();
|
|
282
|
+
break;
|
|
283
|
+
case 'Tab':
|
|
284
|
+
e.preventDefault();
|
|
285
|
+
if (e.shiftKey) navigateUp();
|
|
286
|
+
else navigateDown();
|
|
287
|
+
break;
|
|
288
|
+
case 'Home':
|
|
289
|
+
{
|
|
290
|
+
if (activeIndex === SEARCH_BAR_INDEX) break;
|
|
291
|
+
e.preventDefault();
|
|
292
|
+
const firstIndex = getFirstSelectableIndex(renderedItems);
|
|
293
|
+
if (firstIndex !== SEARCH_BAR_INDEX) navigateToIndex(firstIndex);
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
case 'End':
|
|
297
|
+
{
|
|
298
|
+
if (activeIndex === SEARCH_BAR_INDEX) break;
|
|
299
|
+
e.preventDefault();
|
|
300
|
+
const lastIndex = getLastSelectableIndex(renderedItems);
|
|
301
|
+
if (lastIndex !== SEARCH_BAR_INDEX) navigateToIndex(lastIndex);
|
|
302
|
+
break;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}, [
|
|
306
|
+
search,
|
|
307
|
+
isTransitioning,
|
|
308
|
+
activeIndex,
|
|
309
|
+
navigationStack.canGoBack,
|
|
310
|
+
navigateToIndex,
|
|
311
|
+
handleItemSelect,
|
|
312
|
+
handleBackTransition
|
|
313
|
+
]);
|
|
181
314
|
useEffect(()=>{
|
|
182
315
|
const handleKeyDown = (e)=>{
|
|
183
316
|
if ('Escape' === e.key) if (isSearching) {
|
|
@@ -223,19 +356,25 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
|
|
|
223
356
|
value: search,
|
|
224
357
|
onChange: handleSearch,
|
|
225
358
|
clear: clearSearch,
|
|
226
|
-
placeholder: "Search"
|
|
359
|
+
placeholder: "Search",
|
|
360
|
+
inputRef: searchInputRef,
|
|
361
|
+
onNavigationKeyDown: handleNavigationKeyDown,
|
|
362
|
+
activeDescendantId: activeDescendantId
|
|
227
363
|
}),
|
|
228
364
|
/*#__PURE__*/ jsx(AnimatedContainer, {
|
|
229
365
|
children: /*#__PURE__*/ jsx(AnimatedContent, {
|
|
230
366
|
entering: isTransitioning,
|
|
231
367
|
direction: animationDirection,
|
|
232
368
|
children: /*#__PURE__*/ jsx(ListView, {
|
|
369
|
+
ref: listViewRef,
|
|
233
370
|
isLoading: childrenLoading || searchLoading || loading,
|
|
234
|
-
items:
|
|
371
|
+
items: displayedItems,
|
|
372
|
+
activeIndex: activeIndex,
|
|
373
|
+
listRef: listRef,
|
|
235
374
|
emptyStateMessage: isSearching ? 'No matching nodes found' : 'No nodes found',
|
|
236
|
-
enableSections: !isSearching,
|
|
237
375
|
onItemClick: handleItemSelect,
|
|
238
|
-
onItemHover: onItemHover
|
|
376
|
+
onItemHover: onItemHover,
|
|
377
|
+
enableSections: !isSearching
|
|
239
378
|
})
|
|
240
379
|
})
|
|
241
380
|
})
|