box-ui-elements 23.4.0-beta.6 → 23.4.0-beta.7
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/DEVELOPING.md +13 -29
- package/cypress.config.ts +1 -1
- package/dist/explorer.js +1 -1
- package/dist/preview.js +1 -1
- package/dist/sidebar.js +1 -1
- package/es/components/context-menu/ContextMenu.stories.js +3 -3
- package/es/components/context-menu/ContextMenu.stories.js.map +1 -1
- package/es/components/context-menu/ContextMenuExample.scss +4 -0
- package/es/components/context-menu/ContextMenuWithSubmenuExample.js +43 -0
- package/es/components/context-menu/ContextMenuWithSubmenuExample.js.map +1 -0
- package/es/components/selector-dropdown/SelectorDropdown.stories.js +2 -2
- package/es/components/selector-dropdown/SelectorDropdown.stories.js.flow +2 -2
- package/es/components/selector-dropdown/SelectorDropdown.stories.js.map +1 -1
- package/es/components/selector-dropdown/SelectorDropdownExample.js +126 -0
- package/es/components/selector-dropdown/SelectorDropdownExample.js.map +1 -0
- package/es/elements/content-sidebar/BoxAISidebarContent.js +6 -1
- package/es/elements/content-sidebar/BoxAISidebarContent.js.map +1 -1
- package/es/src/components/context-menu/ContextMenu.stories.d.ts +1 -1
- package/es/src/components/context-menu/ContextMenuWithSubmenuExample.d.ts +9 -0
- package/es/src/components/selector-dropdown/SelectorDropdownExample.d.ts +3 -0
- package/es/src/elements/content-sidebar/BoxAISidebarContent.d.ts +2 -0
- package/es/types.d.ts +0 -1
- package/eslint.config.js +0 -1
- package/i18n/pl-PL.js +2 -2
- package/i18n/pl-PL.properties +2 -2
- package/package.json +9 -16
- package/src/components/context-menu/ContextMenu.stories.tsx +3 -3
- package/src/components/context-menu/ContextMenuExample.scss +4 -0
- package/src/components/context-menu/ContextMenuWithSubmenuExample.tsx +61 -0
- package/src/components/progress-bar/README.md +1 -11
- package/src/components/selector-dropdown/SelectorDropdown.stories.js +2 -2
- package/src/components/selector-dropdown/SelectorDropdownExample.tsx +140 -0
- package/src/elements/content-sidebar/BoxAISidebarContent.tsx +13 -2
- package/src/elements/content-sidebar/__tests__/BoxAISidebar.test.tsx +21 -0
- package/types.ts +0 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import { Menu, SubmenuItem, MenuItem } from '../menu';
|
|
4
|
+
import ContextMenu from './ContextMenu';
|
|
5
|
+
|
|
6
|
+
class ContextMenuWithSubmenuExample extends React.Component {
|
|
7
|
+
state = {
|
|
8
|
+
rightBoundaryElement: undefined,
|
|
9
|
+
bottomBoundaryElement: undefined,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
render() {
|
|
13
|
+
return (
|
|
14
|
+
<ContextMenu>
|
|
15
|
+
<div
|
|
16
|
+
ref={ref => {
|
|
17
|
+
if (!this.state.rightBoundaryElement) {
|
|
18
|
+
this.setState({
|
|
19
|
+
rightBoundaryElement: ref,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}}
|
|
23
|
+
className="context-menu-example-target"
|
|
24
|
+
style={{
|
|
25
|
+
height: 200,
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
Target Component - right click me
|
|
29
|
+
</div>
|
|
30
|
+
<Menu
|
|
31
|
+
setRef={(ref: React.RefObject<HTMLDivElement>) => {
|
|
32
|
+
if (!this.state.bottomBoundaryElement) {
|
|
33
|
+
this.setState({
|
|
34
|
+
bottomBoundaryElement: ref,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
<MenuItem>View Profile</MenuItem>
|
|
40
|
+
<MenuItem>View Profile</MenuItem>
|
|
41
|
+
{this.state.rightBoundaryElement && (
|
|
42
|
+
<SubmenuItem
|
|
43
|
+
bottomBoundaryElement={this.state.bottomBoundaryElement}
|
|
44
|
+
rightBoundaryElement={this.state.rightBoundaryElement}
|
|
45
|
+
>
|
|
46
|
+
Submenu
|
|
47
|
+
<Menu>
|
|
48
|
+
<MenuItem>View Profile</MenuItem>
|
|
49
|
+
<MenuItem>View Profile</MenuItem>
|
|
50
|
+
<MenuItem>View Profile</MenuItem>
|
|
51
|
+
</Menu>
|
|
52
|
+
</SubmenuItem>
|
|
53
|
+
)}
|
|
54
|
+
<MenuItem>Help</MenuItem>
|
|
55
|
+
</Menu>
|
|
56
|
+
</ContextMenu>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default ContextMenuWithSubmenuExample;
|
|
@@ -6,14 +6,4 @@ Renders a progress bar similar to the ones used on Youtube.
|
|
|
6
6
|
<ProgressBar
|
|
7
7
|
progress={ 75 }
|
|
8
8
|
/>
|
|
9
|
-
```
|
|
10
|
-
**Demo**
|
|
11
|
-
```
|
|
12
|
-
// @NOTE: As recommended by styleguidist, if you need a more complex demo
|
|
13
|
-
// it’s often a good idea to define it in a separate JavaScript file and require
|
|
14
|
-
// it in Markdown
|
|
15
|
-
|
|
16
|
-
const ProgressBarExamples = require('examples').ProgressBarExamples;
|
|
17
|
-
|
|
18
|
-
<ProgressBarExamples />
|
|
19
|
-
```
|
|
9
|
+
```
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// @flow
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import SelectorDropdownExample from './SelectorDropdownExample';
|
|
5
5
|
import SelectorDropdown from './SelectorDropdown';
|
|
6
6
|
import notes from './SelectorDropdown.stories.md';
|
|
7
7
|
|
|
8
|
-
export const basic = () => <
|
|
8
|
+
export const basic = () => <SelectorDropdownExample />;
|
|
9
9
|
|
|
10
10
|
export default {
|
|
11
11
|
title: 'Components/SelectorDropdown',
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import React, { Children, Component } from 'react';
|
|
2
|
+
|
|
3
|
+
import DatalistItem from '../datalist-item';
|
|
4
|
+
import SelectorDropdown from './SelectorDropdown';
|
|
5
|
+
import TextInput, { TextInputProps } from '../text-input';
|
|
6
|
+
|
|
7
|
+
interface InputContainerProps extends Omit<TextInputProps, 'onInput'> {
|
|
8
|
+
inputProps?: Partial<TextInputProps>;
|
|
9
|
+
onInput: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const InputContainer: React.FC<InputContainerProps> = ({ inputProps = {}, ...rest }) => (
|
|
13
|
+
<TextInput {...inputProps} {...rest} />
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
interface SelectorDropdownContainerProps {
|
|
17
|
+
initialItems: string[];
|
|
18
|
+
placeholder: string;
|
|
19
|
+
title: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SelectorDropdownContainerState {
|
|
23
|
+
filterText: string;
|
|
24
|
+
items: string[];
|
|
25
|
+
showTitle: boolean;
|
|
26
|
+
remainOpen: boolean;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
class SelectorDropdownContainer extends Component<SelectorDropdownContainerProps, SelectorDropdownContainerState> {
|
|
30
|
+
constructor(props: SelectorDropdownContainerProps) {
|
|
31
|
+
super(props);
|
|
32
|
+
this.state = {
|
|
33
|
+
filterText: '',
|
|
34
|
+
items: props.initialItems,
|
|
35
|
+
showTitle: false,
|
|
36
|
+
remainOpen: false,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
handleShowTitle = () => {
|
|
41
|
+
this.setState({ showTitle: !this.state.showTitle });
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
handleRemainOpen = () => {
|
|
45
|
+
this.setState({ remainOpen: !this.state.remainOpen });
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
handleUserInput = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
49
|
+
this.filterByItem(event.target.value);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
handleItemSelection = (i: number) => {
|
|
53
|
+
this.setState({ filterText: this.state.items[i] });
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
filterByItem(item: string) {
|
|
57
|
+
this.setState({ filterText: item });
|
|
58
|
+
this.filterItems(item);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
filterItems(filterText: string) {
|
|
62
|
+
const { initialItems } = this.props;
|
|
63
|
+
const filterTextLowerCase = filterText.toLowerCase();
|
|
64
|
+
const items = initialItems.filter(item => item.toLowerCase().includes(filterTextLowerCase));
|
|
65
|
+
this.setState({ items });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
render() {
|
|
69
|
+
const { placeholder, title } = this.props;
|
|
70
|
+
const { filterText, items, showTitle, remainOpen } = this.state;
|
|
71
|
+
const dropdownTitle = <div>This is a Title</div>;
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<div style={{ paddingBottom: '330px' }}>
|
|
75
|
+
<label htmlFor="title-check">
|
|
76
|
+
<input
|
|
77
|
+
type="checkbox"
|
|
78
|
+
name="title-check"
|
|
79
|
+
id="title-check"
|
|
80
|
+
checked={showTitle}
|
|
81
|
+
onChange={this.handleShowTitle}
|
|
82
|
+
/>
|
|
83
|
+
<span style={{ paddingLeft: '4px' }}>Add title to overlay</span>
|
|
84
|
+
</label>
|
|
85
|
+
<br />
|
|
86
|
+
<label htmlFor="remain-open-check">
|
|
87
|
+
<input
|
|
88
|
+
type="checkbox"
|
|
89
|
+
name="remain-open-check"
|
|
90
|
+
id="remain-open-check"
|
|
91
|
+
checked={remainOpen}
|
|
92
|
+
onChange={this.handleRemainOpen}
|
|
93
|
+
/>
|
|
94
|
+
<span style={{ paddingLeft: '4px' }}>Overlay should remain open</span>
|
|
95
|
+
</label>
|
|
96
|
+
<hr />
|
|
97
|
+
<SelectorDropdown
|
|
98
|
+
isAlwaysOpen={remainOpen}
|
|
99
|
+
onSelect={this.handleItemSelection}
|
|
100
|
+
selector={
|
|
101
|
+
<InputContainer
|
|
102
|
+
label={title}
|
|
103
|
+
name="selectorDropdownInput"
|
|
104
|
+
onInput={this.handleUserInput}
|
|
105
|
+
placeholder={placeholder}
|
|
106
|
+
type="text"
|
|
107
|
+
value={filterText}
|
|
108
|
+
/>
|
|
109
|
+
}
|
|
110
|
+
title={showTitle ? dropdownTitle : undefined}
|
|
111
|
+
>
|
|
112
|
+
{Children.map(items, item => (
|
|
113
|
+
<DatalistItem key={item}>{item}</DatalistItem>
|
|
114
|
+
))}
|
|
115
|
+
</SelectorDropdown>
|
|
116
|
+
</div>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const SelectorDropdownExample: React.FC = () => (
|
|
122
|
+
<SelectorDropdownContainer
|
|
123
|
+
initialItems={[
|
|
124
|
+
'Illmatic',
|
|
125
|
+
'The Marshall Mathers LP',
|
|
126
|
+
'All Eyez on Me',
|
|
127
|
+
'Ready To Die',
|
|
128
|
+
'Enter the Wu-Tang',
|
|
129
|
+
'The Eminem Show',
|
|
130
|
+
'The Chronic',
|
|
131
|
+
'Straight Outta Compton',
|
|
132
|
+
'Reasonable Doubt',
|
|
133
|
+
'Super long name that should be truncated, we should see the dots at the very end, adding some more text here, should truncate at any second now, please truncate soon',
|
|
134
|
+
]}
|
|
135
|
+
placeholder="Select an album"
|
|
136
|
+
title="Album"
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
export default SelectorDropdownExample;
|
|
@@ -6,7 +6,7 @@ import * as React from 'react';
|
|
|
6
6
|
import flow from 'lodash/flow';
|
|
7
7
|
import { useIntl } from 'react-intl';
|
|
8
8
|
import classNames from 'classnames';
|
|
9
|
-
import { BoxAiAgentSelectorWithApi, useAgents } from '@box/box-ai-agent-selector';
|
|
9
|
+
import { BoxAiAgentSelectorWithApi, useAgents, type AgentType } from '@box/box-ai-agent-selector';
|
|
10
10
|
import { IconButton, Tooltip } from '@box/blueprint-web';
|
|
11
11
|
import { ArrowsExpand } from '@box/blueprint-web-assets/icons/Fill';
|
|
12
12
|
import {
|
|
@@ -34,11 +34,17 @@ const MARK_NAME_JS_READY: string = `${ORIGIN_BOXAI_SIDEBAR}_${EVENT_JS_READY}`;
|
|
|
34
34
|
|
|
35
35
|
mark(MARK_NAME_JS_READY);
|
|
36
36
|
|
|
37
|
-
function BoxAISidebarContent(
|
|
37
|
+
function BoxAISidebarContent(
|
|
38
|
+
props: ApiWrapperWithInjectedProps & {
|
|
39
|
+
onSelectedAgentCallback: (selectedAgent: AgentType) => void;
|
|
40
|
+
shouldShowLandingPage: boolean;
|
|
41
|
+
},
|
|
42
|
+
) {
|
|
38
43
|
const {
|
|
39
44
|
createSession,
|
|
40
45
|
encodedSession,
|
|
41
46
|
onClearAction,
|
|
47
|
+
onSelectedAgentCallback,
|
|
42
48
|
getAIStudioAgents,
|
|
43
49
|
hasRequestInProgress,
|
|
44
50
|
hostAppName,
|
|
@@ -155,6 +161,11 @@ function BoxAISidebarContent(props: ApiWrapperWithInjectedProps & { shouldShowLa
|
|
|
155
161
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
156
162
|
}, [encodedSession]);
|
|
157
163
|
|
|
164
|
+
React.useEffect(() => {
|
|
165
|
+
onSelectedAgentCallback?.(selectedAgent);
|
|
166
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
167
|
+
}, [selectedAgent?.id]);
|
|
168
|
+
|
|
158
169
|
const renderBoxAISidebarTitle = () => {
|
|
159
170
|
return (
|
|
160
171
|
<div className="bcs-BoxAISidebar-title-part">
|
|
@@ -4,11 +4,15 @@ import { render, screen } from '../../../test-utils/testing-library';
|
|
|
4
4
|
import BoxAISidebar, { BoxAISidebarProps } from '../BoxAISidebar';
|
|
5
5
|
|
|
6
6
|
let MockBoxAiAgentSelectorWithApi: jest.Mock;
|
|
7
|
+
let mockUseAgents: jest.Mock;
|
|
8
|
+
|
|
7
9
|
jest.mock('@box/box-ai-agent-selector', () => {
|
|
8
10
|
MockBoxAiAgentSelectorWithApi = jest.fn();
|
|
11
|
+
mockUseAgents = jest.fn();
|
|
9
12
|
return {
|
|
10
13
|
...jest.requireActual('@box/box-ai-agent-selector'),
|
|
11
14
|
BoxAiAgentSelectorWithApi: MockBoxAiAgentSelectorWithApi,
|
|
15
|
+
useAgents: mockUseAgents,
|
|
12
16
|
};
|
|
13
17
|
});
|
|
14
18
|
|
|
@@ -39,6 +43,7 @@ jest.mock('@box/box-ai-content-answers', () => ({
|
|
|
39
43
|
onClearAction={mockOnClearAction}
|
|
40
44
|
onCloseModal={jest.fn()}
|
|
41
45
|
onSelectAgent={jest.fn()}
|
|
46
|
+
onSelectedAgentCallback={props.onSelectedAgentCallback}
|
|
42
47
|
onSuggestedQuestionsFetched={props.onSuggestedQuestionsFetched}
|
|
43
48
|
onAgentEditorToggle={jest.fn()}
|
|
44
49
|
questions={props.restoredQuestions}
|
|
@@ -145,6 +150,12 @@ describe('elements/content-sidebar/BoxAISidebar', () => {
|
|
|
145
150
|
|
|
146
151
|
beforeEach(() => {
|
|
147
152
|
MockBoxAiAgentSelectorWithApi.mockImplementation(() => <div data-testid="sidebar-agent-selector" />);
|
|
153
|
+
mockUseAgents.mockReturnValue({
|
|
154
|
+
agents: [],
|
|
155
|
+
selectedAgent: { id: '1', config: {}, name: 'Test Agent' },
|
|
156
|
+
setSelectedAgent: jest.fn(),
|
|
157
|
+
requestState: 'success',
|
|
158
|
+
});
|
|
148
159
|
});
|
|
149
160
|
|
|
150
161
|
afterEach(() => {
|
|
@@ -465,4 +476,14 @@ describe('elements/content-sidebar/BoxAISidebar', () => {
|
|
|
465
476
|
|
|
466
477
|
expect(mockProps.onUserInteraction).toHaveBeenCalled();
|
|
467
478
|
});
|
|
479
|
+
|
|
480
|
+
test('Should call onSelectedAgentCallback on agent selected change', async () => {
|
|
481
|
+
const mockOnSelectedAgentCallback = jest.fn();
|
|
482
|
+
|
|
483
|
+
await renderComponent({
|
|
484
|
+
onSelectedAgentCallback: mockOnSelectedAgentCallback,
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
expect(mockOnSelectedAgentCallback).toHaveBeenCalled();
|
|
488
|
+
});
|
|
468
489
|
});
|
package/types.ts
CHANGED