superdesk-ui-framework 3.0.66 → 3.0.68
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/app/styles/components/_list-item.scss +22 -11
- package/app-typescript/components/Autocomplete.tsx +9 -3
- package/app-typescript/components/Badge.tsx +16 -2
- package/app-typescript/components/Dropdown.tsx +3 -1
- package/app-typescript/components/DropdownFirst.tsx +14 -2
- package/app-typescript/components/DurationInput.tsx +19 -4
- package/app-typescript/components/EmptyState.tsx +11 -2
- package/app-typescript/components/Layouts/Panel.tsx +12 -1
- package/app-typescript/components/Lists/ContentList.tsx +5 -1
- package/app-typescript/components/Modal.tsx +10 -1
- package/app-typescript/components/Navigation/BottomNav.tsx +9 -2
- package/app-typescript/components/Navigation/QuickNavBar.tsx +10 -2
- package/app-typescript/components/Navigation/SideBarMenu.tsx +9 -4
- package/app-typescript/components/SidebarMenu.tsx +8 -1
- package/app-typescript/components/TabList.tsx +5 -1
- package/app-typescript/components/TagInput.tsx +4 -1
- package/app-typescript/components/ThemeSelector.tsx +13 -2
- package/app-typescript/components/TreeMenu.tsx +127 -122
- package/app-typescript/components/TreeSelect/TreeSelect.tsx +157 -141
- package/app-typescript/components/WithPortal.tsx +49 -0
- package/app-typescript/components/avatar/avatar-image.tsx +2 -0
- package/app-typescript/components/avatar/avatar.tsx +2 -1
- package/dist/examples.bundle.js +1446 -1318
- package/dist/playgrounds/planning.html +121 -43
- package/dist/playgrounds/react-playgrounds/CoreLayout.tsx +398 -385
- package/dist/playgrounds/react-playgrounds/EditorTest.tsx +359 -365
- package/dist/playgrounds/react-playgrounds/FirstPlayground.tsx +33 -33
- package/dist/playgrounds/react-playgrounds/Multiedit.tsx +227 -231
- package/dist/playgrounds/react-playgrounds/PageLayoutTest.tsx +41 -38
- package/dist/playgrounds/react-playgrounds/PersonalProfile.tsx +76 -96
- package/dist/playgrounds/react-playgrounds/RundownEditor.tsx +73 -101
- package/dist/playgrounds/react-playgrounds/Rundowns.tsx +788 -729
- package/dist/playgrounds/react-playgrounds/SamsPlayground.tsx +35 -26
- package/dist/playgrounds/react-playgrounds/TestGround.tsx +99 -128
- package/dist/playgrounds/react-playgrounds/UiPlayground.tsx +40 -25
- package/dist/playgrounds/react-playgrounds/components/GraphicButton.tsx +6 -5
- package/dist/playgrounds/react-playgrounds/components/Layout.tsx +0 -2
- package/dist/playgrounds/react-playgrounds/components/SearchBar.tsx +16 -9
- package/dist/playgrounds/react-playgrounds/tsconfig.json +4 -0
- package/dist/superdesk-ui.bundle.css +24 -14
- package/dist/superdesk-ui.bundle.js +830 -727
- package/dist/vendor.bundle.js +14 -14
- package/examples/pages/playgrounds/planning.html +121 -43
- package/examples/pages/playgrounds/react-playgrounds/CoreLayout.tsx +398 -385
- package/examples/pages/playgrounds/react-playgrounds/EditorTest.tsx +359 -365
- package/examples/pages/playgrounds/react-playgrounds/FirstPlayground.tsx +33 -33
- package/examples/pages/playgrounds/react-playgrounds/Multiedit.tsx +227 -231
- package/examples/pages/playgrounds/react-playgrounds/PageLayoutTest.tsx +41 -38
- package/examples/pages/playgrounds/react-playgrounds/PersonalProfile.tsx +76 -96
- package/examples/pages/playgrounds/react-playgrounds/RundownEditor.tsx +73 -101
- package/examples/pages/playgrounds/react-playgrounds/Rundowns.tsx +788 -729
- package/examples/pages/playgrounds/react-playgrounds/SamsPlayground.tsx +35 -26
- package/examples/pages/playgrounds/react-playgrounds/TestGround.tsx +99 -128
- package/examples/pages/playgrounds/react-playgrounds/UiPlayground.tsx +40 -25
- package/examples/pages/playgrounds/react-playgrounds/components/GraphicButton.tsx +6 -5
- package/examples/pages/playgrounds/react-playgrounds/components/Layout.tsx +0 -2
- package/examples/pages/playgrounds/react-playgrounds/components/SearchBar.tsx +16 -9
- package/examples/pages/playgrounds/react-playgrounds/tsconfig.json +4 -0
- package/package.json +3 -2
- package/react/components/Autocomplete.js +2 -2
- package/react/components/Badge.js +1 -1
- package/react/components/Dropdown.js +3 -1
- package/react/components/DropdownFirst.js +6 -2
- package/react/components/DurationInput.js +5 -1
- package/react/components/EmptyState.js +2 -1
- package/react/components/Lists/ContentList.js +1 -1
- package/react/components/Navigation/BottomNav.js +4 -1
- package/react/components/Navigation/QuickNavBar.js +2 -1
- package/react/components/Navigation/SideBarMenu.js +3 -1
- package/react/components/TabList.js +2 -1
- package/react/components/TagInput.js +1 -1
- package/react/components/TreeSelect/TreeSelect.d.ts +3 -2
- package/react/components/TreeSelect/TreeSelect.js +81 -73
- package/react/components/WithPortal.d.ts +14 -0
- package/react/components/WithPortal.js +69 -0
- package/react/components/avatar/avatar.js +2 -1
- /package/dist/playgrounds/dummy-data/{items.js → items.ts} +0 -0
- /package/examples/pages/playgrounds/dummy-data/{items.js → items.ts} +0 -0
@@ -12,7 +12,7 @@ import {SelectPreview} from '../SelectPreview';
|
|
12
12
|
import {TreeSelectPill} from './TreeSelectPill';
|
13
13
|
import {getPrefixedItemId, TreeSelectItem} from './TreeSelectItem';
|
14
14
|
import {keyboardNavigation} from './KeyboardNavigation';
|
15
|
-
import {
|
15
|
+
import {WithPortal} from '../WithPortal';
|
16
16
|
|
17
17
|
interface IState<T> {
|
18
18
|
value: Array<T>;
|
@@ -35,7 +35,7 @@ interface IPropsBase<T> extends IInputWrapper {
|
|
35
35
|
value?: Array<T>;
|
36
36
|
selectBranchWithChildren?: boolean;
|
37
37
|
readOnly?: boolean;
|
38
|
-
|
38
|
+
width?: 'medium' | 'match-input';
|
39
39
|
inputWidth?: '100%';
|
40
40
|
allowMultiple?: boolean;
|
41
41
|
loading?: boolean;
|
@@ -43,6 +43,7 @@ interface IPropsBase<T> extends IInputWrapper {
|
|
43
43
|
placeholder?: string;
|
44
44
|
searchPlaceholder?: string;
|
45
45
|
zIndex?: number;
|
46
|
+
'data-test-id'?: string;
|
46
47
|
getLabel(item: T): string;
|
47
48
|
getId(item: T): string;
|
48
49
|
getBackgroundColor?(item: T): string;
|
@@ -50,7 +51,6 @@ interface IPropsBase<T> extends IInputWrapper {
|
|
50
51
|
optionTemplate?(item: T): React.ComponentType<T> | JSX.Element;
|
51
52
|
valueTemplate?(item: T, Wrapper: React.ElementType): React.ComponentType<T> | JSX.Element;
|
52
53
|
onChange(e: Array<T>): void;
|
53
|
-
'data-test-id'?: string;
|
54
54
|
}
|
55
55
|
|
56
56
|
interface IPropsSync<T> extends IPropsBase<T> {
|
@@ -111,6 +111,8 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
111
111
|
this.toggleMenu = this.toggleMenu.bind(this);
|
112
112
|
this.onMouseDown = this.onMouseDown.bind(this);
|
113
113
|
this.onKeyDown = this.onKeyDown.bind(this);
|
114
|
+
this.onPressEsc = this.onPressEsc.bind(this);
|
115
|
+
|
114
116
|
this.dropdownRef = React.createRef();
|
115
117
|
this.ref = React.createRef();
|
116
118
|
this.inputRef = React.createRef();
|
@@ -139,7 +141,10 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
139
141
|
&& (this.treeSelectRef.current?.contains(event.target as HTMLElement) !== true)
|
140
142
|
&& this.state.openDropdown
|
141
143
|
) {
|
142
|
-
this.setState({
|
144
|
+
this.setState({
|
145
|
+
openDropdown: false,
|
146
|
+
searchFieldValue: '',
|
147
|
+
});
|
143
148
|
}
|
144
149
|
}
|
145
150
|
|
@@ -165,16 +170,27 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
165
170
|
}
|
166
171
|
}
|
167
172
|
|
173
|
+
onPressEsc = (event: KeyboardEvent) => {
|
174
|
+
if (event.key === 'Escape' && this.state.openDropdown) {
|
175
|
+
this.setState({
|
176
|
+
openDropdown: false,
|
177
|
+
searchFieldValue: '',
|
178
|
+
});
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
168
182
|
componentDidMount = () => {
|
169
183
|
this.recursion(this.state.options);
|
170
184
|
|
171
185
|
document.addEventListener("mousedown", this.onMouseDown);
|
172
186
|
document.addEventListener("keydown", this.onKeyDown);
|
187
|
+
document.addEventListener("keydown", this.onPressEsc);
|
173
188
|
}
|
174
189
|
|
175
190
|
componentWillUnmount(): void {
|
176
191
|
document.removeEventListener("mousedown", this.onMouseDown);
|
177
192
|
document.removeEventListener("keydown", this.onKeyDown);
|
193
|
+
document.addEventListener("keydown", this.onPressEsc);
|
178
194
|
}
|
179
195
|
|
180
196
|
componentDidUpdate(prevProps: Readonly<IProps<T>>, prevState: Readonly<IState<T>>): void {
|
@@ -203,17 +219,9 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
203
219
|
|
204
220
|
toggleMenu() {
|
205
221
|
if (this.state.openDropdown) {
|
206
|
-
if (this.
|
207
|
-
this.popperInstance = createPopper(this.
|
222
|
+
if (this.treeSelectRef.current && this.dropdownRef.current) {
|
223
|
+
this.popperInstance = createPopper(this.treeSelectRef.current, this.dropdownRef.current, {
|
208
224
|
placement: 'bottom-start',
|
209
|
-
modifiers: [
|
210
|
-
{
|
211
|
-
name: 'offset',
|
212
|
-
options: {
|
213
|
-
offset: [-4, 4],
|
214
|
-
},
|
215
|
-
},
|
216
|
-
],
|
217
225
|
});
|
218
226
|
}
|
219
227
|
|
@@ -632,7 +640,10 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
632
640
|
data-test-id={this.props['data-test-id']}
|
633
641
|
>
|
634
642
|
<div
|
635
|
-
className={`
|
643
|
+
className={`
|
644
|
+
tags-input sd-input__input
|
645
|
+
tags-input--${this.props.allowMultiple ? 'multi-select' : 'single-select'}`
|
646
|
+
}
|
636
647
|
ref={this.treeSelectRef}
|
637
648
|
data-test-id={this.props.allowMultiple ? undefined : 'open-popover'}
|
638
649
|
>
|
@@ -641,12 +652,18 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
641
652
|
{this.props.readOnly
|
642
653
|
|| <button
|
643
654
|
ref={this.openDropdownRef}
|
644
|
-
className={`
|
655
|
+
className={`
|
656
|
+
tags-input__add-button
|
657
|
+
${this.props.disabled ? 'tags-input__add-button--disabled' : ''}`
|
658
|
+
}
|
645
659
|
onClick={(e) => {
|
646
660
|
e.stopPropagation();
|
647
661
|
|
648
662
|
if (!this.props.disabled) {
|
649
|
-
this.setState({
|
663
|
+
this.setState({
|
664
|
+
openDropdown: !this.state.openDropdown,
|
665
|
+
searchFieldValue: '',
|
666
|
+
});
|
650
667
|
}
|
651
668
|
}}
|
652
669
|
data-test-id="open-popover"
|
@@ -760,7 +777,10 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
760
777
|
|
761
778
|
{
|
762
779
|
(this.props.readOnly !== true && this.props.required !== true) && (
|
763
|
-
<span
|
780
|
+
<span
|
781
|
+
className="tags-input__remove-button"
|
782
|
+
data-test-id="clear-value"
|
783
|
+
>
|
764
784
|
<Icon name='remove-sign'></Icon>
|
765
785
|
</span>
|
766
786
|
)
|
@@ -784,136 +804,132 @@ export class TreeSelect<T> extends React.Component<IProps<T>, IState<T>> {
|
|
784
804
|
}
|
785
805
|
</div>
|
786
806
|
|
787
|
-
{
|
788
|
-
|
789
|
-
|
807
|
+
<WithPortal active={this.state.openDropdown} data-test-id="tree-select-popover">
|
808
|
+
<div
|
809
|
+
className={
|
810
|
+
"autocomplete autocomplete--multi-select"
|
811
|
+
+ (this.props.width === 'medium' ? ' autocomplete--fixed-width' : '')
|
812
|
+
}
|
813
|
+
style={{
|
814
|
+
zIndex: this.props.zIndex,
|
815
|
+
width: this.treeSelectRef.current?.offsetWidth,
|
816
|
+
}}
|
817
|
+
ref={this.dropdownRef}
|
818
|
+
>
|
819
|
+
<div className='autocomplete__header'>
|
790
820
|
<div
|
791
|
-
className=
|
792
|
-
|
793
|
-
|
794
|
-
}
|
795
|
-
style={{
|
796
|
-
zIndex: this.props.zIndex,
|
797
|
-
width: this.treeSelectRef.current?.offsetWidth,
|
821
|
+
className="autocomplete__icon"
|
822
|
+
onClick={() => {
|
823
|
+
this.backButton();
|
798
824
|
}}
|
799
|
-
ref={this.dropdownRef}
|
800
825
|
>
|
801
|
-
<
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
816
|
-
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
826
|
+
<Icon name="search" className="search"></Icon>
|
827
|
+
</div>
|
828
|
+
|
829
|
+
<div className='autocomplete__filter'>
|
830
|
+
<input
|
831
|
+
className="autocomplete__input"
|
832
|
+
type="text"
|
833
|
+
placeholder={this.props.searchPlaceholder}
|
834
|
+
ref={this.inputRef}
|
835
|
+
value={this.state.searchFieldValue}
|
836
|
+
onChange={(event) => {
|
837
|
+
if (this.props.kind === 'synchronous') {
|
838
|
+
this.setState({searchFieldValue: event.target.value});
|
839
|
+
this.popperInstance?.update();
|
840
|
+
} else if (this.props.kind === 'asynchronous') {
|
841
|
+
if (this.ICancelFn) {
|
842
|
+
this.ICancelFn();
|
843
|
+
}
|
844
|
+
|
845
|
+
this.setState({searchFieldValue: event.target.value, options: []});
|
846
|
+
this.popperInstance?.update();
|
847
|
+
this.debounceFn();
|
848
|
+
} else {
|
849
|
+
return;
|
850
|
+
}
|
851
|
+
}}
|
852
|
+
data-test-id="filter-input"
|
853
|
+
/>
|
854
|
+
</div>
|
855
|
+
</div>
|
856
|
+
|
857
|
+
{(this.state.activeTree.length > 0 && this.state.buttonValue != null)
|
858
|
+
&& <div className='autocomplete__category-header'>
|
859
|
+
<div
|
860
|
+
className="autocomplete__icon"
|
861
|
+
onClick={() => {
|
862
|
+
this.backButton();
|
863
|
+
}}
|
864
|
+
>
|
865
|
+
<Icon name="arrow-left" className="arrow-left"></Icon>
|
837
866
|
</div>
|
838
867
|
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
>
|
847
|
-
<Icon name="arrow-left" className="arrow-left"></Icon>
|
848
|
-
</div>
|
849
|
-
|
850
|
-
<div className='autocomplete__filter'>
|
851
|
-
<button className='autocomplete__category-title'>
|
852
|
-
{this.props.optionTemplate
|
853
|
-
? this.props.optionTemplate(this.state.buttonValue.value)
|
854
|
-
: this.props.getLabel(this.state.buttonValue.value)
|
855
|
-
}
|
856
|
-
</button>
|
868
|
+
<div className='autocomplete__filter'>
|
869
|
+
<button className='autocomplete__category-title'>
|
870
|
+
{this.props.optionTemplate
|
871
|
+
? this.props.optionTemplate(this.state.buttonValue.value)
|
872
|
+
: this.props.getLabel(this.state.buttonValue.value)
|
873
|
+
}
|
874
|
+
</button>
|
857
875
|
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
</div>
|
863
|
-
}
|
864
|
-
|
865
|
-
{this.state.loading
|
866
|
-
? <ul className="suggestion-list--loader"><Loader overlay={true}></Loader></ul>
|
867
|
-
: this.state.searchFieldValue === ''
|
868
|
-
? this.props.getOptions
|
869
|
-
? <ul
|
870
|
-
className="suggestion-list suggestion-list--multi-select"
|
871
|
-
ref={this.ref}
|
872
|
-
data-test-id="options"
|
873
|
-
>
|
874
|
-
{this.state.options.map((option, i: React.Key | undefined) => {
|
875
|
-
let selectedItem = this.state.value.some((obj) =>
|
876
|
-
this.props.getId(obj) === this.props.getId(option.value),
|
877
|
-
);
|
878
|
-
|
879
|
-
return (
|
880
|
-
<TreeSelectItem
|
881
|
-
key={i}
|
882
|
-
option={option}
|
883
|
-
handleTree={this.handleTree}
|
884
|
-
selectedItem={selectedItem}
|
885
|
-
allowMultiple={this.props.allowMultiple}
|
886
|
-
getBorderColor={this.props.getBorderColor}
|
887
|
-
getBackgroundColor={this.props.getBackgroundColor}
|
888
|
-
getId={this.props.getId}
|
889
|
-
optionTemplate={this.props.optionTemplate}
|
890
|
-
getLabel={this.props.getLabel}
|
891
|
-
onKeyDown={() => this.setState({
|
892
|
-
buttonTarget: [
|
893
|
-
...this.state.buttonTarget,
|
894
|
-
this.props.getId(option.value),
|
895
|
-
],
|
896
|
-
})}
|
897
|
-
/>
|
898
|
-
);
|
899
|
-
})}
|
900
|
-
</ul>
|
901
|
-
: null
|
902
|
-
: <ul
|
903
|
-
className="suggestion-list suggestion-list--multi-select"
|
904
|
-
ref={this.ref}
|
905
|
-
>
|
906
|
-
{this.filteredItem(
|
907
|
-
this.props.singleLevelSearch
|
908
|
-
? this.state.options
|
909
|
-
: this.state.filterArr,
|
910
|
-
)}
|
911
|
-
</ul>
|
912
|
-
}
|
876
|
+
{this.props.selectBranchWithChildren
|
877
|
+
&& this.branchButton(this.state.buttonValue)
|
878
|
+
}
|
879
|
+
</div>
|
913
880
|
</div>
|
914
|
-
|
915
|
-
|
916
|
-
|
881
|
+
}
|
882
|
+
|
883
|
+
{this.state.loading
|
884
|
+
? <ul className="suggestion-list--loader"><Loader overlay={true}></Loader></ul>
|
885
|
+
: this.state.searchFieldValue === ''
|
886
|
+
? this.props.getOptions
|
887
|
+
? <ul
|
888
|
+
className="suggestion-list suggestion-list--multi-select"
|
889
|
+
ref={this.ref}
|
890
|
+
data-test-id="options"
|
891
|
+
>
|
892
|
+
{this.state.options.map((option, i: React.Key | undefined) => {
|
893
|
+
let selectedItem = this.state.value.some((obj) =>
|
894
|
+
this.props.getId(obj) === this.props.getId(option.value),
|
895
|
+
);
|
896
|
+
|
897
|
+
return (
|
898
|
+
<TreeSelectItem
|
899
|
+
key={i}
|
900
|
+
option={option}
|
901
|
+
handleTree={this.handleTree}
|
902
|
+
selectedItem={selectedItem}
|
903
|
+
allowMultiple={this.props.allowMultiple}
|
904
|
+
getBorderColor={this.props.getBorderColor}
|
905
|
+
getBackgroundColor={this.props.getBackgroundColor}
|
906
|
+
getId={this.props.getId}
|
907
|
+
optionTemplate={this.props.optionTemplate}
|
908
|
+
getLabel={this.props.getLabel}
|
909
|
+
onKeyDown={() => this.setState({
|
910
|
+
buttonTarget: [
|
911
|
+
...this.state.buttonTarget,
|
912
|
+
this.props.getId(option.value),
|
913
|
+
],
|
914
|
+
})}
|
915
|
+
/>
|
916
|
+
);
|
917
|
+
})}
|
918
|
+
</ul>
|
919
|
+
: null
|
920
|
+
: <ul
|
921
|
+
className="suggestion-list suggestion-list--multi-select"
|
922
|
+
ref={this.ref}
|
923
|
+
>
|
924
|
+
{this.filteredItem(
|
925
|
+
this.props.singleLevelSearch
|
926
|
+
? this.state.options
|
927
|
+
: this.state.filterArr,
|
928
|
+
)}
|
929
|
+
</ul>
|
930
|
+
}
|
931
|
+
</div>
|
932
|
+
</WithPortal>
|
917
933
|
</InputWrapper>
|
918
934
|
);
|
919
935
|
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import * as React from "react";
|
2
|
+
import {createPortal} from 'react-dom';
|
3
|
+
|
4
|
+
interface IProps {
|
5
|
+
active: boolean;
|
6
|
+
'data-test-id'?: string;
|
7
|
+
}
|
8
|
+
|
9
|
+
export function findParent(
|
10
|
+
element: HTMLElement | null,
|
11
|
+
) {
|
12
|
+
let dataTheme = element;
|
13
|
+
|
14
|
+
while (dataTheme != null && dataTheme?.getAttribute('data-theme') == null) {
|
15
|
+
dataTheme = dataTheme.parentElement ?? null;
|
16
|
+
}
|
17
|
+
|
18
|
+
return dataTheme;
|
19
|
+
}
|
20
|
+
|
21
|
+
export class WithPortal extends React.Component<IProps> {
|
22
|
+
private ref: React.RefObject<HTMLDivElement>;
|
23
|
+
private dataTheme: string | undefined;
|
24
|
+
|
25
|
+
constructor(props: IProps) {
|
26
|
+
super(props);
|
27
|
+
|
28
|
+
this.ref = React.createRef();
|
29
|
+
}
|
30
|
+
|
31
|
+
componentDidMount(): void {
|
32
|
+
this.dataTheme = findParent(this.ref.current)?.getAttribute('data-theme') ?? undefined;
|
33
|
+
}
|
34
|
+
|
35
|
+
render() {
|
36
|
+
return (
|
37
|
+
<div ref={this.ref}>
|
38
|
+
{this.props.active && (
|
39
|
+
createPortal(
|
40
|
+
<div data-theme={this.dataTheme} data-test-id={this.props['data-test-id']}>
|
41
|
+
{this.props.children}
|
42
|
+
</div>,
|
43
|
+
document.body,
|
44
|
+
)
|
45
|
+
)}
|
46
|
+
</div>
|
47
|
+
);
|
48
|
+
}
|
49
|
+
}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import * as React from 'react';
|
2
2
|
import {IPropsBase} from './interfaces';
|
3
|
+
// tslint:disable-next-line:max-line-length
|
3
4
|
|
4
5
|
interface IPropsImageAvatar extends IPropsBase {
|
5
6
|
imageUrl?: string | null; // defaults to a placeholder image
|
@@ -24,6 +25,7 @@ export class AvatarContentImage extends React.PureComponent<IPropsImageAvatar> {
|
|
24
25
|
>
|
25
26
|
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
26
27
|
<circle cx="100" cy="100" r="100" fill="white" fillOpacity="0.01"/>
|
28
|
+
{/* tslint:disable-next-line:max-line-length */}
|
27
29
|
<path fillRule="evenodd" clipRule="evenodd" d="M40 153V145.384C40 141.557 41.16 137.981 43.16 135C49.14 126.057 66.24 119.711 77.14 118C82.74 117.115 90.16 116.538 100 116.538C109.84 116.538 117.26 117.115 122.86 118C133.76 119.711 150.86 126.057 156.84 135C158.84 137.981 160 141.557 160 145.384V153C150 165 130 180 100 180C70 180 50 165 40 153ZM100 30C122.08 30 140 47.2307 140 68.4614C140 89.6922 122.08 106.923 100 106.923C77.92 106.923 60 89.6922 60 68.4614C60 47.2307 77.92 30 100 30Z" fill="var(--sd-colour-avatar-dummy)" fillOpacity="1"/>
|
28
30
|
</svg>
|
29
31
|
</span>);
|
@@ -46,7 +46,8 @@ export class Avatar extends React.PureComponent<IPropsAvatar> {
|
|
46
46
|
customContent,
|
47
47
|
} = this.props;
|
48
48
|
|
49
|
-
const tooltipCombined = [displayName, this.props.tooltip]
|
49
|
+
const tooltipCombined = [displayName, this.props.tooltip]
|
50
|
+
.filter((str) => (str ?? '').trim().length > 0).join('\n');
|
50
51
|
|
51
52
|
return (
|
52
53
|
<AvatarWrapper
|