@jetbrains/ring-ui 7.0.103 → 7.0.105
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/components/auth/auth-core.js +1 -1
- package/components/avatar/avatar.css +0 -6
- package/components/avatar/avatar.js +2 -2
- package/components/header/profile.js +0 -1
- package/components/list/list.d.ts +5 -0
- package/components/list/list.js +14 -0
- package/components/tab-trap/tab-trap.js +19 -11
- package/package.json +2 -3
- package/postcss.config.js +0 -1
- package/components/avatar/avatar-shadow-filter.svg +0 -18
|
@@ -45,7 +45,7 @@ const DEFAULT_CONFIG = {
|
|
|
45
45
|
defaultExpiresIn: DEFAULT_EXPIRES_TIMEOUT,
|
|
46
46
|
waitForRedirectTimeout: DEFAULT_WAIT_FOR_REDIRECT_TIMEOUT,
|
|
47
47
|
tokenRefreshRetryDelays: TOKEN_REFRESH_RETRY_DELAYS,
|
|
48
|
-
rpInitiatedLogout:
|
|
48
|
+
rpInitiatedLogout: false,
|
|
49
49
|
translations: null,
|
|
50
50
|
};
|
|
51
51
|
class Auth {
|
|
@@ -12,12 +12,6 @@
|
|
|
12
12
|
border-radius: 50%;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
.avatarShadow {
|
|
16
|
-
/* See https://stackoverflow.com/questions/21414925/why-doesnt-inset-box-shadow-work-over-images */
|
|
17
|
-
|
|
18
|
-
filter: url('avatar-shadow-filter.svg#inset-shadow');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
15
|
.avatarInfo {
|
|
22
16
|
display: flex;
|
|
23
17
|
align-items: center;
|
|
@@ -75,10 +75,10 @@ export default class Avatar extends PureComponent {
|
|
|
75
75
|
};
|
|
76
76
|
subavatarSrc = skipParams ? subavatar : encodeURL(urlStart, queryParams);
|
|
77
77
|
return (<div>
|
|
78
|
-
<img {...restProps} onError={this.handleError} onLoad={this.handleSuccess} className={
|
|
78
|
+
<img {...restProps} onError={this.handleError} onLoad={this.handleSuccess} className={classes} style={styleObj} src={src} alt='User avatar'/>
|
|
79
79
|
<img {...restProps} data-test='avatar' onError={this.handleError} onLoad={this.handleSuccess} className={classNames(styles.subavatar)} style={styleObjGroup} src={subavatarSrc} alt='Subavatar'/>
|
|
80
80
|
</div>);
|
|
81
81
|
}
|
|
82
|
-
return (<img {...restProps} data-test='avatar' onError={this.handleError} onLoad={this.handleSuccess} className={
|
|
82
|
+
return (<img {...restProps} data-test='avatar' onError={this.handleError} onLoad={this.handleSuccess} className={classes} style={styleObj} src={src} alt='User avatar'/>);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
@@ -43,6 +43,9 @@ export interface ListProps<T = unknown> {
|
|
|
43
43
|
maxHeight?: number | null | undefined;
|
|
44
44
|
activeIndex?: number | null | undefined;
|
|
45
45
|
useMouseUp?: boolean | null | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* @deprecated No longer used. Visibility is detected automatically via IntersectionObserver. Will be removed in Ring UI 8.0.
|
|
48
|
+
*/
|
|
46
49
|
visible?: boolean | null | undefined;
|
|
47
50
|
disableMoveOverflow?: boolean | null | undefined;
|
|
48
51
|
compact?: boolean | null | undefined;
|
|
@@ -130,6 +133,8 @@ export default class List<T = unknown> extends Component<ListProps<T>, ListState
|
|
|
130
133
|
virtualizedList?: VirtualizedList | null;
|
|
131
134
|
unmounted?: boolean;
|
|
132
135
|
container?: HTMLElement | null;
|
|
136
|
+
private intersectionObserver?;
|
|
137
|
+
private wasVisible;
|
|
133
138
|
private _bufferSize;
|
|
134
139
|
sizeCacheKey: (index: number) => string | Type.ITEM | Type.MARGIN;
|
|
135
140
|
private _cache;
|
package/components/list/list.js
CHANGED
|
@@ -122,6 +122,17 @@ export default class List extends Component {
|
|
|
122
122
|
if (!this.props.renderOptimization) {
|
|
123
123
|
this.scrollToActive();
|
|
124
124
|
}
|
|
125
|
+
if (this.props.renderOptimization && this.container && typeof IntersectionObserver !== 'undefined') {
|
|
126
|
+
this.intersectionObserver = new IntersectionObserver(entries => {
|
|
127
|
+
for (const entry of entries) {
|
|
128
|
+
if (entry.isIntersecting && !this.wasVisible && this.virtualizedList) {
|
|
129
|
+
this.virtualizedList.recomputeRowHeights();
|
|
130
|
+
}
|
|
131
|
+
this.wasVisible = entry.isIntersecting;
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
this.intersectionObserver.observe(this.container);
|
|
135
|
+
}
|
|
125
136
|
}
|
|
126
137
|
shouldComponentUpdate(nextProps, nextState) {
|
|
127
138
|
return (Object.keys(nextProps).some(key => !Object.is(nextProps[key], this.props[key])) ||
|
|
@@ -145,6 +156,7 @@ export default class List extends Component {
|
|
|
145
156
|
this.checkOverflow();
|
|
146
157
|
}
|
|
147
158
|
componentWillUnmount() {
|
|
159
|
+
this.intersectionObserver?.disconnect();
|
|
148
160
|
this.unmounted = true;
|
|
149
161
|
}
|
|
150
162
|
scheduleScrollListener = scheduleRAF();
|
|
@@ -157,6 +169,8 @@ export default class List extends Component {
|
|
|
157
169
|
virtualizedList;
|
|
158
170
|
unmounted;
|
|
159
171
|
container;
|
|
172
|
+
intersectionObserver;
|
|
173
|
+
wasVisible = false;
|
|
160
174
|
// eslint-disable-next-line no-magic-numbers
|
|
161
175
|
_bufferSize = 10; // keep X items above and below of the visible area
|
|
162
176
|
// reuse size cache for similar items
|
|
@@ -9,7 +9,7 @@ const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, au
|
|
|
9
9
|
const trapButtonNodeRef = useRef(null);
|
|
10
10
|
const previousFocusedNodeRef = useRef(null);
|
|
11
11
|
const trapWithoutFocusRef = useRef(false);
|
|
12
|
-
const mountedRef = useRef(
|
|
12
|
+
const mountedRef = useRef(undefined);
|
|
13
13
|
// It's the same approach as in focus-trap-react:
|
|
14
14
|
// https://github.com/focus-trap/focus-trap-react/commit/3b22fca9eebeb883edc89548850fe5a5b9d6d50e
|
|
15
15
|
// We can't do it in useEffect because it's too late, some children might have already
|
|
@@ -18,16 +18,16 @@ const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, au
|
|
|
18
18
|
previousFocusedNodeRef.current = document.activeElement;
|
|
19
19
|
}
|
|
20
20
|
useImperativeHandle(ref, () => ({ node: nodeRef.current }), []);
|
|
21
|
-
function
|
|
21
|
+
function restoreFocusIfUnmounted(orElse) {
|
|
22
22
|
const previousFocusedNode = previousFocusedNodeRef.current;
|
|
23
23
|
if (previousFocusedNode instanceof HTMLElement &&
|
|
24
24
|
previousFocusedNode.focus &&
|
|
25
|
-
isNodeInVisiblePartOfPage(previousFocusedNode)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
isNodeInVisiblePartOfPage(previousFocusedNode) &&
|
|
26
|
+
mountedRef.current === false) {
|
|
27
|
+
previousFocusedNode.focus({ preventScroll: true });
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
orElse?.();
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
function focusElement(first = true) {
|
|
@@ -65,7 +65,7 @@ const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, au
|
|
|
65
65
|
}
|
|
66
66
|
return () => {
|
|
67
67
|
if (focusBackOnClose) {
|
|
68
|
-
|
|
68
|
+
restoreFocusIfUnmounted();
|
|
69
69
|
}
|
|
70
70
|
};
|
|
71
71
|
}, [autoFocusFirst, trapDisabled, focusBackOnClose, focusFirst]);
|
|
@@ -76,7 +76,7 @@ const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, au
|
|
|
76
76
|
if (focusBackOnExit) {
|
|
77
77
|
const prevFocused = event.nativeEvent.relatedTarget;
|
|
78
78
|
if (prevFocused && nodeRef.current && prevFocused instanceof Element && nodeRef.current.contains(prevFocused)) {
|
|
79
|
-
|
|
79
|
+
restoreFocusIfUnmounted(focusLast);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
else {
|
|
@@ -97,6 +97,14 @@ const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, au
|
|
|
97
97
|
}
|
|
98
98
|
focusLast();
|
|
99
99
|
}
|
|
100
|
+
function restoreFocusOrFocusFirst() {
|
|
101
|
+
if (focusBackOnExit) {
|
|
102
|
+
restoreFocusIfUnmounted(focusFirst);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
focusFirst();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
100
108
|
if (trapDisabled) {
|
|
101
109
|
return (<div ref={nodeRef} {...restProps}>
|
|
102
110
|
{children}
|
|
@@ -111,7 +119,7 @@ const TabTrap = forwardRef(function TabTrap({ children, trapDisabled = false, au
|
|
|
111
119
|
<div
|
|
112
120
|
// It never actually stays focused
|
|
113
121
|
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
114
|
-
tabIndex={0} onFocus={
|
|
122
|
+
tabIndex={0} onFocus={restoreFocusOrFocusFirst} data-trap-button/>
|
|
115
123
|
</div>);
|
|
116
124
|
});
|
|
117
125
|
export default TabTrap;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetbrains/ring-ui",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.105",
|
|
4
4
|
"description": "JetBrains UI library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "JetBrains"
|
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"vitest": "^4.0.18",
|
|
192
192
|
"vitest-teamcity-reporter": "^0.4.1",
|
|
193
193
|
"webpack": "^5.105.4",
|
|
194
|
-
"webpack-cli": "^
|
|
194
|
+
"webpack-cli": "^7.0.0",
|
|
195
195
|
"xmlappend": "^1.0.4"
|
|
196
196
|
},
|
|
197
197
|
"peerDependencies": {
|
|
@@ -243,7 +243,6 @@
|
|
|
243
243
|
"memoize-one": "^6.0.0",
|
|
244
244
|
"postcss": "^8.5.8",
|
|
245
245
|
"postcss-calc": "^10.1.1",
|
|
246
|
-
"postcss-flexbugs-fixes": "^5.0.2",
|
|
247
246
|
"postcss-font-family-system-ui": "^5.0.0",
|
|
248
247
|
"postcss-loader": "^8.2.1",
|
|
249
248
|
"postcss-modules-values-replace": "^4.2.2",
|
package/postcss.config.js
CHANGED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
|
|
2
|
-
<defs>
|
|
3
|
-
<filter id="inset-shadow" x="-50%" y="-50%" width="200%" height="200%">
|
|
4
|
-
<feComponentTransfer in="SourceAlpha">
|
|
5
|
-
<feFuncA type="table" tableValues="1 0" />
|
|
6
|
-
</feComponentTransfer>
|
|
7
|
-
<feGaussianBlur stdDeviation="4"/>
|
|
8
|
-
<feOffset dx="0" dy="0" result="offsetblur"/>
|
|
9
|
-
<feFlood flood-color="rgba(0, 0, 0, 0.07)"/>
|
|
10
|
-
<feComposite in2="offsetblur" operator="in"/>
|
|
11
|
-
<feComposite in="SourceAlpha" operator="in" />
|
|
12
|
-
<feMerge>
|
|
13
|
-
<feMergeNode in="SourceGraphic" />
|
|
14
|
-
<feMergeNode />
|
|
15
|
-
</feMerge>
|
|
16
|
-
</filter>
|
|
17
|
-
</defs>
|
|
18
|
-
</svg>
|