superdesk-ui-framework 3.0.21 → 3.0.24
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/_avatar.scss +12 -1
- package/app/styles/_icon-font.scss +4 -1
- package/app-typescript/components/Icon.tsx +1 -1
- package/app-typescript/components/ShowPopup.tsx +1 -1
- package/app-typescript/components/avatar/avatar-group.tsx +115 -30
- package/app-typescript/components/avatar/avatar.tsx +4 -4
- package/dist/examples.bundle.css +766 -0
- package/dist/examples.bundle.js +3898 -3893
- package/dist/react/Avatar.tsx +75 -120
- package/dist/superdesk-ui.bundle.css +2309 -1
- package/dist/superdesk-ui.bundle.js +17974 -17946
- package/examples/pages/react/Avatar.tsx +75 -120
- package/package.json +1 -1
- package/react/components/Icon.d.ts +1 -1
- package/react/components/ShowPopup.js +1 -1
- package/react/components/avatar/avatar-group.d.ts +2 -0
- package/react/components/avatar/avatar-group.js +32 -4
- package/react/components/avatar/avatar.d.ts +1 -1
- package/react/components/avatar/avatar.js +3 -3
package/app/styles/_avatar.scss
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
.sd-avatar {
|
2
|
-
display:
|
2
|
+
display: block;
|
3
3
|
position: relative; // required for absolutely positioned indicators
|
4
4
|
|
5
5
|
&.sd-avatar--indicator-status--offline {
|
@@ -339,3 +339,14 @@
|
|
339
339
|
gap: $sd-base-increment * 1.5;
|
340
340
|
}
|
341
341
|
}
|
342
|
+
|
343
|
+
.avatar-popup {
|
344
|
+
background-color: var(--color-dropdown-menu-Bg);
|
345
|
+
border-radius: 5px;
|
346
|
+
padding: 1.5rem;
|
347
|
+
box-shadow: var(--sd-shadow__dropdown);
|
348
|
+
display: flex;
|
349
|
+
flex-direction: column;
|
350
|
+
gap: 4px;
|
351
|
+
overflow: auto;
|
352
|
+
}
|
@@ -5,7 +5,7 @@ interface IProps {
|
|
5
5
|
size?: 'small' | 'big'; // defaults to 'small'
|
6
6
|
type?: 'default' | 'primary' | 'success' | 'warning' | 'alert' | 'highlight' | 'light' | 'white';
|
7
7
|
className?: string;
|
8
|
-
scale?: '2x' | '3x' | '4x';
|
8
|
+
scale?: '1.5x' | '2x' | '3x' | '4x';
|
9
9
|
ariaHidden?: boolean;
|
10
10
|
color?: string;
|
11
11
|
}
|
@@ -123,7 +123,7 @@ class PopupPositioner extends React.PureComponent<IPropsPopupPositioner> {
|
|
123
123
|
ref={(el) => {
|
124
124
|
this.wrapperEl = el;
|
125
125
|
}}
|
126
|
-
style={{zIndex: this.props.zIndex ?? 1, position: 'absolute', left: '-100vw'}}
|
126
|
+
style={{zIndex: this.props.zIndex ?? 1, position: 'absolute', left: '-100vw', display: 'flex'}}
|
127
127
|
>
|
128
128
|
{this.props.children}
|
129
129
|
</div>
|
@@ -4,6 +4,8 @@ import {Avatar, IPropsAvatar} from './avatar';
|
|
4
4
|
import {AvatarWrapper} from './avatar-wrapper';
|
5
5
|
import {AvatarContentNumber} from './avatar-number';
|
6
6
|
import {AvatarPlaceholder, IPropsAvatarPlaceholder} from './avatar-placeholder';
|
7
|
+
import { Spacer } from '../Spacer';
|
8
|
+
import {WithPopover} from '../WithPopover';
|
7
9
|
|
8
10
|
export type IAvatarInGroup = Omit<IPropsAvatar, 'size'>;
|
9
11
|
export type IAvatarPlaceholderInGroup = Omit<IPropsAvatarPlaceholder, 'size'>;
|
@@ -21,6 +23,13 @@ export interface IPropsAvatarGroup {
|
|
21
23
|
* if exceeded, "+1"/"+2"/"+n" button will be shown
|
22
24
|
*/
|
23
25
|
max?: number | 'show-all';
|
26
|
+
|
27
|
+
zIndex?: number;
|
28
|
+
|
29
|
+
// unless a custom onClick handler is passed
|
30
|
+
// a popover would get shown when maximum number
|
31
|
+
// of avatars is exceeded.
|
32
|
+
onClick?(): void;
|
24
33
|
}
|
25
34
|
|
26
35
|
function isAvatar(item: IAvatarInGroup | IAvatarPlaceholderInGroup): item is IAvatarInGroup {
|
@@ -46,41 +55,117 @@ export class AvatarGroup extends React.PureComponent<IPropsAvatarGroup> {
|
|
46
55
|
})();
|
47
56
|
const itemsOverLimit = items.length - max;
|
48
57
|
|
58
|
+
const PlusButtonWrapper: React.ComponentType<{onToggle(event: HTMLElement): void}> = ({children, onToggle}) => {
|
59
|
+
if (this.props.onClick == null) {
|
60
|
+
return (
|
61
|
+
<button
|
62
|
+
style={{padding: 0}}
|
63
|
+
onClick={(event) => {
|
64
|
+
if (this.props.onClick == null) {
|
65
|
+
onToggle(event.target as HTMLElement);
|
66
|
+
}
|
67
|
+
}}
|
68
|
+
>
|
69
|
+
{children}
|
70
|
+
</button>
|
71
|
+
);
|
72
|
+
} else {
|
73
|
+
return <>{children}</>;
|
74
|
+
}
|
75
|
+
};
|
76
|
+
|
77
|
+
const someHaveDisplayName = this.props.items.some((item) => isAvatar(item) && item.displayName.length > 0);
|
78
|
+
|
49
79
|
return (
|
50
|
-
<
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
role='group'
|
57
|
-
>
|
58
|
-
{
|
59
|
-
items.slice(0, max).map((item, index) => {
|
60
|
-
if (isAvatar(item)) {
|
80
|
+
<WithPopover
|
81
|
+
zIndex={this.props.zIndex ?? 101}
|
82
|
+
placement='bottom-end'
|
83
|
+
component={() => (
|
84
|
+
<div className="avatar-popup">
|
85
|
+
{this.props.items.map((item, index) => {
|
61
86
|
return (
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
87
|
+
someHaveDisplayName
|
88
|
+
? <Spacer h alignItems='center' gap='16' noGrow key={index}>
|
89
|
+
{
|
90
|
+
isAvatar(item)
|
91
|
+
&& item.displayName
|
92
|
+
}
|
93
|
+
|
94
|
+
{
|
95
|
+
isAvatar(item)
|
96
|
+
? (
|
97
|
+
<Avatar
|
98
|
+
size='small'
|
99
|
+
imageUrl={item.imageUrl}
|
100
|
+
initials={item.initials}
|
101
|
+
displayName={item.displayName}
|
102
|
+
icon={item.icon}
|
103
|
+
/>
|
104
|
+
)
|
105
|
+
: (
|
106
|
+
<AvatarPlaceholder
|
107
|
+
kind='plus-button'
|
108
|
+
size='small'
|
109
|
+
icon={item.icon}
|
110
|
+
onClick={item.onClick}
|
111
|
+
/>
|
112
|
+
)
|
113
|
+
}
|
114
|
+
</Spacer>
|
115
|
+
: <div>
|
116
|
+
<AvatarPlaceholder
|
117
|
+
kind='plus-button'
|
118
|
+
size='small'
|
119
|
+
icon={item.icon}
|
120
|
+
onClick={isAvatar(item) ? undefined : item.onClick}
|
121
|
+
key={index}
|
122
|
+
/>
|
123
|
+
</div>
|
71
124
|
);
|
125
|
+
})}
|
126
|
+
</div>
|
127
|
+
)}
|
128
|
+
>
|
129
|
+
{(onToggle) => (
|
130
|
+
<div
|
131
|
+
className={classNames(
|
132
|
+
'sd-avatar-group',
|
133
|
+
'sd-avatar-group--stacked',
|
134
|
+
`sd-avatar-group--stacked--gap-${gap}`,
|
135
|
+
)}
|
136
|
+
role='group'
|
137
|
+
onClick={this.props.onClick}
|
138
|
+
>
|
139
|
+
{
|
140
|
+
items.slice(0, max).map((item, index) => {
|
141
|
+
if (isAvatar(item)) {
|
142
|
+
return (
|
143
|
+
<Avatar {...item} key={index} size={size} />
|
144
|
+
);
|
145
|
+
} else {
|
146
|
+
return (
|
147
|
+
<AvatarPlaceholder
|
148
|
+
{...item}
|
149
|
+
key={index}
|
150
|
+
size={this.props.size}
|
151
|
+
/>
|
152
|
+
);
|
153
|
+
}
|
154
|
+
})
|
72
155
|
}
|
73
|
-
})
|
74
|
-
}
|
75
156
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
157
|
+
{
|
158
|
+
itemsOverLimit > 0 && (
|
159
|
+
<PlusButtonWrapper onToggle={onToggle}>
|
160
|
+
<AvatarWrapper size={size} isEmpty={false}>
|
161
|
+
<AvatarContentNumber number={`${itemsOverLimit}`} />
|
162
|
+
</AvatarWrapper>
|
163
|
+
</PlusButtonWrapper>
|
164
|
+
)
|
165
|
+
}
|
166
|
+
</div>
|
167
|
+
)}
|
168
|
+
</WithPopover>
|
84
169
|
);
|
85
170
|
}
|
86
171
|
}
|
@@ -5,7 +5,7 @@ import {AvatarContentText} from './avatar-text';
|
|
5
5
|
|
6
6
|
export interface IPropsAvatar {
|
7
7
|
imageUrl: string | null; // nullable, but mandatory to communicate importance
|
8
|
-
|
8
|
+
displayName: string;
|
9
9
|
|
10
10
|
/** 3 letters max */
|
11
11
|
initials: string | null; // nullable, but mandatory to communicate importance
|
@@ -22,7 +22,7 @@ export interface IPropsAvatar {
|
|
22
22
|
|
23
23
|
export class Avatar extends React.PureComponent<IPropsAvatar> {
|
24
24
|
render() {
|
25
|
-
const {imageUrl, initials, size, statusIndicator, administratorIndicator, icon,
|
25
|
+
const {imageUrl, initials, size, statusIndicator, administratorIndicator, icon, displayName} = this.props;
|
26
26
|
|
27
27
|
return (
|
28
28
|
<AvatarWrapper
|
@@ -35,10 +35,10 @@ export class Avatar extends React.PureComponent<IPropsAvatar> {
|
|
35
35
|
{
|
36
36
|
imageUrl != null || initials == null
|
37
37
|
? (
|
38
|
-
<AvatarContentImage imageUrl={imageUrl} tooltipText={
|
38
|
+
<AvatarContentImage imageUrl={imageUrl} tooltipText={displayName} />
|
39
39
|
)
|
40
40
|
: (
|
41
|
-
<AvatarContentText text={initials} tooltipText={
|
41
|
+
<AvatarContentText text={initials} tooltipText={displayName} />
|
42
42
|
)
|
43
43
|
}
|
44
44
|
|