@uipath/apollo-react 3.54.0-pr354.c980c37 → 3.54.0-pr354.f47b811

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.
@@ -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 ListView_ListView = /*#__PURE__*/ (0, external_react_namespaceObject.memo)(function({ items, onItemClick, onItemHover, emptyStateMessage = 'No items found', emptyStateIcon = 'search_off', isLoading = false, enableSections = true }) {
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: import("react").MemoExoticComponent<(<T extends ListItem>({ items, onItemClick, onItemHover, emptyStateMessage, emptyStateIcon, isLoading, enableSections, }: ListViewProps<T>) => import("react/jsx-runtime").JSX.Element)>;
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":"AAUA,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,KAAK,UAAU,CAAC,CAAC,SAAS,QAAQ,IAC9B;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,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,QAAQ;IAClD,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/B,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;AAyGD,UAAU,aAAa,CAAC,CAAC,SAAS,QAAQ;IACxC,KAAK,EAAE,CAAC,EAAE,CAAC;IACX,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;AAED,eAAO,MAAM,QAAQ,wCAA0B,CAAC,SAAS,QAAQ,sGAQ9D,aAAa,CAAC,CAAC,CAAC,8CAkFjB,CAAC"}
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 ListView_ListView = /*#__PURE__*/ memo(function({ items, onItemClick, onItemHover, emptyStateMessage = 'No items found', emptyStateIcon = 'search_off', isLoading = false, enableSections = true }) {
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
- export { ListView_ListView as ListView };
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;;UAe1B,CAAC;AAEF,eAAO,MAAM,aAAa;;;;cAA0B,MAAM;yGAazD,CAAC;AAEF,eAAO,MAAM,UAAU,EAkClB,OAAO,IAAI,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 inputRef = (0, external_react_namespaceObject.useRef)(null);
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;CACtB;AAED,eAAO,MAAM,SAAS,sDAuCpB,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 inputRef = useRef(null);
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,96 @@ 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
+ else {
268
+ const firstIndex = getFirstSelectableIndex(renderedItems);
269
+ if (-1 !== firstIndex) navigateToIndex(firstIndex);
270
+ }
271
+ }
272
+ };
273
+ const navigateUp = ()=>{
274
+ activeIndex <= 0 || -1 === getNextSelectableIndex(renderedItems, activeIndex, -1) ? navigateToIndex(-1) : navigateToIndex(getNextSelectableIndex(renderedItems, activeIndex, -1));
275
+ };
276
+ switch(e.key){
277
+ case 'ArrowDown':
278
+ e.preventDefault();
279
+ navigateDown();
280
+ break;
281
+ case 'ArrowUp':
282
+ e.preventDefault();
283
+ navigateUp();
284
+ break;
285
+ case 'Space':
286
+ case 'Enter':
287
+ if (activeIndex >= 0) {
288
+ const renderItem = renderedItems[activeIndex];
289
+ if (renderItem?.type === 'item') {
290
+ e.preventDefault();
291
+ handleItemSelect(renderItem.item);
292
+ }
293
+ }
294
+ break;
295
+ case 'ArrowRight':
296
+ if (activeIndex >= 0) {
297
+ const renderItem = renderedItems[activeIndex];
298
+ if (renderItem?.type === 'item' && renderItem.item.children) {
299
+ e.preventDefault();
300
+ handleItemSelect(renderItem.item);
301
+ }
302
+ }
303
+ break;
304
+ case 'ArrowLeft':
305
+ if (activeIndex >= 0 && navigationStack.canGoBack) {
306
+ e.preventDefault();
307
+ handleBackTransition();
308
+ }
309
+ break;
310
+ case 'Tab':
311
+ e.preventDefault();
312
+ if (e.shiftKey) navigateUp();
313
+ else navigateDown();
314
+ break;
315
+ case 'Home':
316
+ {
317
+ if (-1 === activeIndex) break;
318
+ e.preventDefault();
319
+ const firstIndex = getFirstSelectableIndex(renderedItems);
320
+ if (-1 !== firstIndex) navigateToIndex(firstIndex);
321
+ break;
322
+ }
323
+ case 'End':
324
+ {
325
+ if (-1 === activeIndex) break;
326
+ e.preventDefault();
327
+ const lastIndex = getLastSelectableIndex(renderedItems);
328
+ if (-1 !== lastIndex) navigateToIndex(lastIndex);
329
+ break;
330
+ }
331
+ }
332
+ }, [
333
+ isTransitioning,
334
+ activeIndex,
335
+ navigationStack.canGoBack,
336
+ navigateToIndex,
337
+ handleItemSelect,
338
+ handleBackTransition
339
+ ]);
209
340
  (0, external_react_namespaceObject.useEffect)(()=>{
210
341
  const handleKeyDown = (e)=>{
211
342
  if ('Escape' === e.key) if (isSearching) {
@@ -251,19 +382,25 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
251
382
  value: search,
252
383
  onChange: handleSearch,
253
384
  clear: clearSearch,
254
- placeholder: "Search"
385
+ placeholder: "Search",
386
+ inputRef: searchInputRef,
387
+ onNavigationKeyDown: handleNavigationKeyDown,
388
+ activeDescendantId: activeDescendantId
255
389
  }),
256
390
  /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Toolbox_styles_cjs_namespaceObject.AnimatedContainer, {
257
391
  children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_Toolbox_styles_cjs_namespaceObject.AnimatedContent, {
258
392
  entering: isTransitioning,
259
393
  direction: animationDirection,
260
394
  children: /*#__PURE__*/ (0, jsx_runtime_namespaceObject.jsx)(external_ListView_cjs_namespaceObject.ListView, {
395
+ ref: listViewRef,
261
396
  isLoading: childrenLoading || searchLoading || loading,
262
- items: isSearching && !isSearchingInitialItems ? searchedItems : items,
397
+ items: displayedItems,
398
+ activeIndex: activeIndex,
399
+ listRef: listRef,
263
400
  emptyStateMessage: isSearching ? 'No matching nodes found' : 'No nodes found',
264
- enableSections: !isSearching,
265
401
  onItemClick: handleItemSelect,
266
- onItemHover: onItemHover
402
+ onItemHover: onItemHover,
403
+ enableSections: !isSearching
267
404
  })
268
405
  })
269
406
  })
@@ -1 +1 @@
1
- {"version":3,"file":"Toolbox.d.ts","sourceRoot":"","sources":["../../../../src/canvas/components/Toolbox/Toolbox.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,YAAY,CAAC;AAuCrD,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;AAoBD,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,2CAoQjB"}
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,2CA2ZjB"}
@@ -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,96 @@ 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
+ else {
240
+ const firstIndex = getFirstSelectableIndex(renderedItems);
241
+ if (-1 !== firstIndex) navigateToIndex(firstIndex);
242
+ }
243
+ }
244
+ };
245
+ const navigateUp = ()=>{
246
+ activeIndex <= 0 || -1 === getNextSelectableIndex(renderedItems, activeIndex, -1) ? navigateToIndex(-1) : navigateToIndex(getNextSelectableIndex(renderedItems, activeIndex, -1));
247
+ };
248
+ switch(e.key){
249
+ case 'ArrowDown':
250
+ e.preventDefault();
251
+ navigateDown();
252
+ break;
253
+ case 'ArrowUp':
254
+ e.preventDefault();
255
+ navigateUp();
256
+ break;
257
+ case 'Space':
258
+ case 'Enter':
259
+ if (activeIndex >= 0) {
260
+ const renderItem = renderedItems[activeIndex];
261
+ if (renderItem?.type === 'item') {
262
+ e.preventDefault();
263
+ handleItemSelect(renderItem.item);
264
+ }
265
+ }
266
+ break;
267
+ case 'ArrowRight':
268
+ if (activeIndex >= 0) {
269
+ const renderItem = renderedItems[activeIndex];
270
+ if (renderItem?.type === 'item' && renderItem.item.children) {
271
+ e.preventDefault();
272
+ handleItemSelect(renderItem.item);
273
+ }
274
+ }
275
+ break;
276
+ case 'ArrowLeft':
277
+ if (activeIndex >= 0 && navigationStack.canGoBack) {
278
+ e.preventDefault();
279
+ handleBackTransition();
280
+ }
281
+ break;
282
+ case 'Tab':
283
+ e.preventDefault();
284
+ if (e.shiftKey) navigateUp();
285
+ else navigateDown();
286
+ break;
287
+ case 'Home':
288
+ {
289
+ if (-1 === activeIndex) break;
290
+ e.preventDefault();
291
+ const firstIndex = getFirstSelectableIndex(renderedItems);
292
+ if (-1 !== firstIndex) navigateToIndex(firstIndex);
293
+ break;
294
+ }
295
+ case 'End':
296
+ {
297
+ if (-1 === activeIndex) break;
298
+ e.preventDefault();
299
+ const lastIndex = getLastSelectableIndex(renderedItems);
300
+ if (-1 !== lastIndex) navigateToIndex(lastIndex);
301
+ break;
302
+ }
303
+ }
304
+ }, [
305
+ isTransitioning,
306
+ activeIndex,
307
+ navigationStack.canGoBack,
308
+ navigateToIndex,
309
+ handleItemSelect,
310
+ handleBackTransition
311
+ ]);
181
312
  useEffect(()=>{
182
313
  const handleKeyDown = (e)=>{
183
314
  if ('Escape' === e.key) if (isSearching) {
@@ -223,19 +354,25 @@ function Toolbox({ onClose, onBack, onItemSelect, onSearch, onItemHover, title,
223
354
  value: search,
224
355
  onChange: handleSearch,
225
356
  clear: clearSearch,
226
- placeholder: "Search"
357
+ placeholder: "Search",
358
+ inputRef: searchInputRef,
359
+ onNavigationKeyDown: handleNavigationKeyDown,
360
+ activeDescendantId: activeDescendantId
227
361
  }),
228
362
  /*#__PURE__*/ jsx(AnimatedContainer, {
229
363
  children: /*#__PURE__*/ jsx(AnimatedContent, {
230
364
  entering: isTransitioning,
231
365
  direction: animationDirection,
232
366
  children: /*#__PURE__*/ jsx(ListView, {
367
+ ref: listViewRef,
233
368
  isLoading: childrenLoading || searchLoading || loading,
234
- items: isSearching && !isSearchingInitialItems ? searchedItems : items,
369
+ items: displayedItems,
370
+ activeIndex: activeIndex,
371
+ listRef: listRef,
235
372
  emptyStateMessage: isSearching ? 'No matching nodes found' : 'No nodes found',
236
- enableSections: !isSearching,
237
373
  onItemClick: handleItemSelect,
238
- onItemHover: onItemHover
374
+ onItemHover: onItemHover,
375
+ enableSections: !isSearching
239
376
  })
240
377
  })
241
378
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uipath/apollo-react",
3
- "version": "3.54.0-pr354.c980c37",
3
+ "version": "3.54.0-pr354.f47b811",
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.14.0"
204
+ "@uipath/apollo-wind": "0.15.0"
205
205
  },
206
206
  "devDependencies": {
207
207
  "@lingui/cli": "^5.6.1",