@jetbrains/ring-ui 8.0.0-beta.10 → 8.0.0-beta.11
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-dialog-service/auth-dialog-service.js +3 -0
- package/components/confirm/confirm.js +12 -8
- package/components/confirm-service/confirm-service.js +3 -0
- package/components/dialog/dialog-controls.d.ts +13 -0
- package/components/dialog/dialog-controls.js +17 -0
- package/components/dialog/dialog-geometry.d.ts +31 -0
- package/components/dialog/dialog-geometry.js +48 -0
- package/components/dialog/dialog.css +166 -27
- package/components/dialog/dialog.d.ts +13 -5
- package/components/dialog/dialog.js +108 -27
- package/components/global/get-viewport-size.d.ts +5 -0
- package/components/global/get-viewport-size.js +5 -0
- package/components/http/http.js +4 -15
- package/components/island/header.js +1 -1
- package/components/login-dialog/service.js +3 -0
- package/components/panel/panel.css +1 -1
- package/components/user-agreement/service.js +3 -0
- package/components/user-agreement/user-agreement.css +2 -8
- package/components/user-agreement/user-agreement.js +8 -10
- package/package.json +5 -5
|
@@ -10,6 +10,9 @@ export const reactRoot = createRoot(containerElement);
|
|
|
10
10
|
* Renders AuthDialog into virtual node to skip maintaining container
|
|
11
11
|
*/
|
|
12
12
|
function renderAuthDialog(props) {
|
|
13
|
+
if (!containerElement.isConnected) {
|
|
14
|
+
document.body.appendChild(containerElement);
|
|
15
|
+
}
|
|
13
16
|
reactRoot.render(<ControlsHeightContext value={getGlobalControlsHeight()}>
|
|
14
17
|
<AuthDialog {...props}/>
|
|
15
18
|
</ControlsHeightContext>);
|
|
@@ -27,17 +27,21 @@ export default class Confirm extends PureComponent {
|
|
|
27
27
|
};
|
|
28
28
|
render() {
|
|
29
29
|
const { show, className, inProgress, cancelIsDefault, text, description, confirmLabel, rejectLabel, onConfirm, onReject, native, } = this.props;
|
|
30
|
+
const actions = [
|
|
31
|
+
<Button key='reject' data-test='confirm-reject-button' onClick={onReject} disabled={inProgress} primary={cancelIsDefault}>
|
|
32
|
+
{rejectLabel}
|
|
33
|
+
</Button>,
|
|
34
|
+
<Button key='confirm' data-test='confirm-ok-button' primary={!cancelIsDefault} loader={inProgress} disabled={inProgress} onClick={onConfirm}>
|
|
35
|
+
{confirmLabel}
|
|
36
|
+
</Button>,
|
|
37
|
+
];
|
|
38
|
+
if (cancelIsDefault) {
|
|
39
|
+
actions.reverse();
|
|
40
|
+
}
|
|
30
41
|
return (<Dialog label={text || (typeof description === 'string' ? description : undefined)} className={className} onEscPress={this.onEscPress} show={show} trapFocus data-test='ring-confirm' native={native}>
|
|
31
42
|
{text && <Header>{text}</Header>}
|
|
32
43
|
{description && <Content>{description}</Content>}
|
|
33
|
-
<Panel>
|
|
34
|
-
<Button data-test='confirm-ok-button' primary={!cancelIsDefault} loader={inProgress} disabled={inProgress} onClick={onConfirm}>
|
|
35
|
-
{confirmLabel}
|
|
36
|
-
</Button>
|
|
37
|
-
<Button data-test='confirm-reject-button' onClick={onReject} disabled={inProgress} primary={cancelIsDefault}>
|
|
38
|
-
{rejectLabel}
|
|
39
|
-
</Button>
|
|
40
|
-
</Panel>
|
|
44
|
+
<Panel>{actions}</Panel>
|
|
41
45
|
</Dialog>);
|
|
42
46
|
}
|
|
43
47
|
}
|
|
@@ -7,6 +7,9 @@ export const reactRoot = createRoot(containerElement);
|
|
|
7
7
|
* Renders Confirm into virtual node to skip maintaining container
|
|
8
8
|
*/
|
|
9
9
|
function renderConfirm(props) {
|
|
10
|
+
if (!containerElement.isConnected) {
|
|
11
|
+
document.body.appendChild(containerElement);
|
|
12
|
+
}
|
|
10
13
|
const { buttonsHeight = getGlobalControlsHeight(), ...restProps } = props;
|
|
11
14
|
reactRoot.render(<ControlsHeightContext value={buttonsHeight}>
|
|
12
15
|
<Confirm {...restProps}/>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { InteractionDirection } from './dialog-geometry';
|
|
3
|
+
interface DialogControlsProps {
|
|
4
|
+
movable: boolean | undefined;
|
|
5
|
+
resizable: boolean | undefined;
|
|
6
|
+
showCloseButton: boolean;
|
|
7
|
+
closeButtonTitle: string | undefined;
|
|
8
|
+
onCloseClick: React.MouseEventHandler<HTMLElement>;
|
|
9
|
+
onStartInteraction: (event: React.PointerEvent<HTMLElement>, direction: InteractionDirection) => void;
|
|
10
|
+
onStopInteraction: React.PointerEventHandler<HTMLElement>;
|
|
11
|
+
}
|
|
12
|
+
export default function DialogControls({ movable, resizable, showCloseButton, closeButtonTitle, onCloseClick, onStartInteraction, onStopInteraction, }: DialogControlsProps): React.JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import closeIcon from '@jetbrains/icons/close';
|
|
3
|
+
import resizeIcon from '@jetbrains/icons/resize-corner-12px';
|
|
4
|
+
import Button from '../button/button';
|
|
5
|
+
import Icon from '../icon/icon';
|
|
6
|
+
import styles from './dialog.css';
|
|
7
|
+
const resizeDirections = ['n', 'ne', 'e', 's', 'sw', 'w', 'nw', 'se'];
|
|
8
|
+
export default function DialogControls({ movable, resizable, showCloseButton, closeButtonTitle, onCloseClick, onStartInteraction, onStopInteraction, }) {
|
|
9
|
+
return (<>
|
|
10
|
+
{movable && (<div aria-hidden='true' className={styles.moveHandle} data-ring-dialog-move-handle='' data-test='ring-dialog-move-handle' onLostPointerCapture={onStopInteraction}/>)}
|
|
11
|
+
{showCloseButton && (<Button icon={closeIcon} data-test='ring-dialog-close-button' className={styles.closeButton} iconClassName={styles.closeIcon} onClick={onCloseClick} title={closeButtonTitle} aria-label={closeButtonTitle || 'close dialog'}/>)}
|
|
12
|
+
{resizable && (<>
|
|
13
|
+
{resizeDirections.map(direction => (<div aria-hidden='true' className={styles.resizeHandle} data-resize-direction={direction} data-test={`ring-dialog-resize-handle-${direction}`} key={direction} onPointerDown={event => onStartInteraction(event, direction)} onPointerUp={onStopInteraction} onPointerCancel={onStopInteraction} onLostPointerCapture={onStopInteraction}/>))}
|
|
14
|
+
<Icon aria-hidden='true' className={styles.resizeMarker} data-test='ring-dialog-resize-marker' glyph={resizeIcon}/>
|
|
15
|
+
</>)}
|
|
16
|
+
</>);
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type ResizeDirection = 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw';
|
|
2
|
+
export type InteractionDirection = 'move' | ResizeDirection;
|
|
3
|
+
export interface Geometry {
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
export interface DialogState {
|
|
10
|
+
shortcutsScope: string;
|
|
11
|
+
geometry: Geometry | null;
|
|
12
|
+
resized: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface Interaction {
|
|
15
|
+
pointerId: number;
|
|
16
|
+
direction: InteractionDirection;
|
|
17
|
+
startX: number;
|
|
18
|
+
startY: number;
|
|
19
|
+
minWidth: number;
|
|
20
|
+
minHeight: number;
|
|
21
|
+
geometry: Geometry;
|
|
22
|
+
}
|
|
23
|
+
export declare const getNativeTabIndex: (autoFocusFirst: boolean | undefined) => -1 | undefined;
|
|
24
|
+
export declare const getTrapDisabled: (trapFocus: boolean, trapDisabled: boolean | undefined) => boolean;
|
|
25
|
+
export declare const getResizeMinimum: (element: Element) => {
|
|
26
|
+
minWidth: number;
|
|
27
|
+
minHeight: number;
|
|
28
|
+
};
|
|
29
|
+
export declare const moveGeometry: (start: Geometry, dx: number, dy: number, viewportWidth: number, viewportHeight: number) => Geometry;
|
|
30
|
+
export declare const fitGeometry: (geometry: Geometry, viewportWidth: number, viewportHeight: number) => Geometry;
|
|
31
|
+
export declare const resizeGeometry: ({ geometry: start, direction, minWidth, minHeight }: Interaction, dx: number, dy: number, viewportWidth: number, viewportHeight: number) => Geometry;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const MIN_WIDTH = 256;
|
|
2
|
+
const MIN_HEIGHT = 160;
|
|
3
|
+
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
4
|
+
export const getNativeTabIndex = (autoFocusFirst) => (autoFocusFirst ? undefined : -1);
|
|
5
|
+
export const getTrapDisabled = (trapFocus, trapDisabled) => trapDisabled ?? !trapFocus;
|
|
6
|
+
export const getResizeMinimum = (element) => {
|
|
7
|
+
const { minWidth, minHeight } = getComputedStyle(element);
|
|
8
|
+
const parsedWidth = parseFloat(minWidth);
|
|
9
|
+
const parsedHeight = parseFloat(minHeight);
|
|
10
|
+
return {
|
|
11
|
+
minWidth: Number.isNaN(parsedWidth) ? MIN_WIDTH : parsedWidth,
|
|
12
|
+
minHeight: Number.isNaN(parsedHeight) ? MIN_HEIGHT : parsedHeight,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export const moveGeometry = (start, dx, dy, viewportWidth, viewportHeight) => ({
|
|
16
|
+
...start,
|
|
17
|
+
left: clamp(start.left + dx, 0, Math.max(0, viewportWidth - start.width)),
|
|
18
|
+
top: clamp(start.top + dy, 0, Math.max(0, viewportHeight - start.height)),
|
|
19
|
+
});
|
|
20
|
+
export const fitGeometry = (geometry, viewportWidth, viewportHeight) => {
|
|
21
|
+
const width = Math.min(geometry.width, viewportWidth);
|
|
22
|
+
const height = Math.min(geometry.height, viewportHeight);
|
|
23
|
+
return {
|
|
24
|
+
left: clamp(geometry.left, 0, Math.max(0, viewportWidth - width)),
|
|
25
|
+
top: clamp(geometry.top, 0, Math.max(0, viewportHeight - height)),
|
|
26
|
+
width,
|
|
27
|
+
height,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export const resizeGeometry = ({ geometry: start, direction, minWidth, minHeight }, dx, dy, viewportWidth, viewportHeight) => {
|
|
31
|
+
let left = start.left;
|
|
32
|
+
let right = start.left + start.width;
|
|
33
|
+
let top = start.top;
|
|
34
|
+
let bottom = start.top + start.height;
|
|
35
|
+
if (direction.includes('w')) {
|
|
36
|
+
left = clamp(start.left + dx, 0, right - Math.min(minWidth, right));
|
|
37
|
+
}
|
|
38
|
+
else if (direction.includes('e')) {
|
|
39
|
+
right = clamp(right + dx, left + Math.min(minWidth, viewportWidth - left), viewportWidth);
|
|
40
|
+
}
|
|
41
|
+
if (direction.includes('n')) {
|
|
42
|
+
top = clamp(start.top + dy, 0, bottom - Math.min(minHeight, bottom));
|
|
43
|
+
}
|
|
44
|
+
else if (direction.includes('s')) {
|
|
45
|
+
bottom = clamp(bottom + dy, top + Math.min(minHeight, viewportHeight - top), viewportHeight);
|
|
46
|
+
}
|
|
47
|
+
return { left, top, width: right - left, height: bottom - top };
|
|
48
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@import '../global/variables.css';
|
|
2
2
|
|
|
3
|
-
@value header, scrollableWrapper from '../island/island.css';
|
|
3
|
+
@value content as islandContent, header, title as islandTitle, scrollableWrapper from '../island/island.css';
|
|
4
4
|
@value panel from '../panel/panel.css';
|
|
5
5
|
|
|
6
6
|
.container {
|
|
@@ -41,40 +41,58 @@
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
.content {
|
|
44
|
+
--dialog-padding: calc(var(--ring-unit) * 2.5);
|
|
45
|
+
|
|
44
46
|
position: relative;
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
width: calc(var(--ring-unit) * 57.5);
|
|
50
|
+
min-width: var(--ring-dialog-min-width, calc(var(--ring-unit) * 32));
|
|
51
|
+
min-height: var(--ring-dialog-min-height, calc(var(--ring-unit) * 20));
|
|
48
52
|
margin: auto;
|
|
53
|
+
padding: var(--dialog-padding);
|
|
49
54
|
|
|
50
55
|
cursor: default;
|
|
51
56
|
overflow-wrap: break-word;
|
|
52
57
|
|
|
53
58
|
& .scrollableWrapper {
|
|
54
|
-
padding
|
|
59
|
+
padding: var(--ring-unit) var(--dialog-padding) 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
& .islandContent {
|
|
63
|
+
width: calc(100% + var(--dialog-padding) * 2);
|
|
64
|
+
min-height: calc(var(--ring-unit) * 5);
|
|
65
|
+
margin-inline: calc(var(--dialog-padding) * -1);
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
& .panel {
|
|
58
|
-
margin-top:
|
|
59
|
-
padding: calc(var(--ring-unit) *
|
|
69
|
+
margin-top: auto;
|
|
70
|
+
padding: calc(var(--ring-unit) * 3) 0 0;
|
|
60
71
|
|
|
61
|
-
|
|
72
|
+
text-align: end;
|
|
62
73
|
|
|
74
|
+
border-top: 0;
|
|
63
75
|
background-color: transparent;
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
/* stylelint-disable-next-line selector-max-specificity */
|
|
67
79
|
& .panel > button:not(:last-child) {
|
|
68
|
-
margin-
|
|
80
|
+
margin-inline-end: var(--ring-unit);
|
|
69
81
|
}
|
|
70
82
|
}
|
|
71
83
|
|
|
72
|
-
.
|
|
73
|
-
max-width: calc(100dvw - var(--ring-unit) *
|
|
84
|
+
.content {
|
|
85
|
+
max-width: calc(100dvw - var(--ring-unit) * 4);
|
|
86
|
+
max-height: calc(100dvh - var(--ring-unit) * 8);
|
|
74
87
|
}
|
|
75
88
|
|
|
76
|
-
.
|
|
77
|
-
|
|
89
|
+
.resized .content.content {
|
|
90
|
+
width: 100%;
|
|
91
|
+
min-width: 0;
|
|
92
|
+
max-width: none;
|
|
93
|
+
height: 100%;
|
|
94
|
+
min-height: 0;
|
|
95
|
+
max-height: none;
|
|
78
96
|
}
|
|
79
97
|
|
|
80
98
|
.content.content {
|
|
@@ -91,10 +109,6 @@
|
|
|
91
109
|
cursor: pointer;
|
|
92
110
|
}
|
|
93
111
|
|
|
94
|
-
.closeIconOutside.closeIconOutside {
|
|
95
|
-
color: var(--ring-icon-hover-color);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
112
|
.clickableOverlay:hover + * .closeIcon {
|
|
99
113
|
color: var(--ring-link-hover-color);
|
|
100
114
|
}
|
|
@@ -105,18 +119,132 @@
|
|
|
105
119
|
|
|
106
120
|
.closeButton.closeButton {
|
|
107
121
|
position: absolute;
|
|
122
|
+
z-index: var(--ring-fixed-z-index);
|
|
123
|
+
inset-block-start: calc(var(--ring-unit) * 2);
|
|
124
|
+
inset-inline-end: calc(var(--ring-unit) * 2);
|
|
108
125
|
|
|
109
126
|
line-height: calc(var(--ring-unit) * 2);
|
|
110
127
|
}
|
|
111
128
|
|
|
112
|
-
.
|
|
129
|
+
.moveHandle {
|
|
130
|
+
position: absolute;
|
|
131
|
+
z-index: var(--ring-fixed-z-index);
|
|
132
|
+
top: 0;
|
|
133
|
+
right: 0;
|
|
134
|
+
left: 0;
|
|
135
|
+
|
|
136
|
+
height: var(--dialog-padding);
|
|
137
|
+
|
|
138
|
+
cursor: move;
|
|
139
|
+
touch-action: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.movable .header {
|
|
143
|
+
cursor: move;
|
|
144
|
+
touch-action: none;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.resizeHandle {
|
|
148
|
+
position: absolute;
|
|
149
|
+
z-index: var(--ring-fixed-z-index);
|
|
150
|
+
|
|
151
|
+
touch-action: none;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.resizeHandle[data-resize-direction='n'],
|
|
155
|
+
.resizeHandle[data-resize-direction='s'] {
|
|
156
|
+
right: var(--ring-unit);
|
|
157
|
+
left: var(--ring-unit);
|
|
158
|
+
|
|
159
|
+
height: var(--ring-unit);
|
|
160
|
+
|
|
161
|
+
cursor: ns-resize;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.resizeHandle[data-resize-direction='n'] {
|
|
165
|
+
top: calc(var(--ring-unit) * -0.5);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.resizeHandle[data-resize-direction='s'] {
|
|
169
|
+
bottom: calc(var(--ring-unit) * -0.5);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.resizeHandle[data-resize-direction='e'],
|
|
173
|
+
.resizeHandle[data-resize-direction='w'] {
|
|
113
174
|
top: var(--ring-unit);
|
|
114
|
-
|
|
175
|
+
bottom: var(--ring-unit);
|
|
176
|
+
|
|
177
|
+
width: var(--ring-unit);
|
|
178
|
+
|
|
179
|
+
cursor: ew-resize;
|
|
115
180
|
}
|
|
116
181
|
|
|
117
|
-
.
|
|
118
|
-
|
|
119
|
-
|
|
182
|
+
.resizeHandle[data-resize-direction='e'] {
|
|
183
|
+
right: calc(var(--ring-unit) * -0.5);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.resizeHandle[data-resize-direction='w'] {
|
|
187
|
+
left: calc(var(--ring-unit) * -0.5);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.resizeHandle[data-resize-direction='ne'],
|
|
191
|
+
.resizeHandle[data-resize-direction='se'],
|
|
192
|
+
.resizeHandle[data-resize-direction='sw'],
|
|
193
|
+
.resizeHandle[data-resize-direction='nw'] {
|
|
194
|
+
width: calc(var(--ring-unit) * 1.5);
|
|
195
|
+
height: calc(var(--ring-unit) * 1.5);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.resizeHandle[data-resize-direction='ne'] {
|
|
199
|
+
top: calc(var(--ring-unit) * -0.5);
|
|
200
|
+
right: calc(var(--ring-unit) * -0.5);
|
|
201
|
+
|
|
202
|
+
cursor: nesw-resize;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.resizeHandle[data-resize-direction='se'] {
|
|
206
|
+
right: calc(var(--ring-unit) * -0.5);
|
|
207
|
+
bottom: calc(var(--ring-unit) * -0.5);
|
|
208
|
+
|
|
209
|
+
width: calc(var(--ring-unit) * 2.5);
|
|
210
|
+
height: calc(var(--ring-unit) * 2.5);
|
|
211
|
+
|
|
212
|
+
cursor: nwse-resize;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.resizeHandle[data-resize-direction='sw'] {
|
|
216
|
+
bottom: calc(var(--ring-unit) * -0.5);
|
|
217
|
+
left: calc(var(--ring-unit) * -0.5);
|
|
218
|
+
|
|
219
|
+
cursor: nesw-resize;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.resizeHandle[data-resize-direction='nw'] {
|
|
223
|
+
top: calc(var(--ring-unit) * -0.5);
|
|
224
|
+
left: calc(var(--ring-unit) * -0.5);
|
|
225
|
+
|
|
226
|
+
cursor: nwse-resize;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.resizeMarker {
|
|
230
|
+
position: absolute;
|
|
231
|
+
bottom: calc(var(--ring-unit) * 0.5);
|
|
232
|
+
inset-inline-end: calc(var(--ring-unit) * 0.5);
|
|
233
|
+
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: center;
|
|
236
|
+
justify-content: center;
|
|
237
|
+
|
|
238
|
+
width: calc(var(--ring-unit) * 1.5);
|
|
239
|
+
height: calc(var(--ring-unit) * 1.5);
|
|
240
|
+
|
|
241
|
+
pointer-events: none;
|
|
242
|
+
|
|
243
|
+
color: var(--ring-secondary-color);
|
|
244
|
+
|
|
245
|
+
&:dir(rtl) {
|
|
246
|
+
transform: scaleX(-1);
|
|
247
|
+
}
|
|
120
248
|
}
|
|
121
249
|
|
|
122
250
|
.documentWithoutScroll {
|
|
@@ -141,16 +269,27 @@
|
|
|
141
269
|
}
|
|
142
270
|
|
|
143
271
|
.innerContainer .header {
|
|
144
|
-
|
|
272
|
+
width: calc(100% + var(--dialog-padding) * 2);
|
|
273
|
+
margin-inline: calc(var(--dialog-padding) * -1);
|
|
145
274
|
|
|
146
|
-
|
|
147
|
-
|
|
275
|
+
padding-block: 0;
|
|
276
|
+
padding-inline: var(--dialog-padding) calc(var(--dialog-padding) + var(--ring-unit) * 3);
|
|
277
|
+
padding-block-start: 0 !important;
|
|
278
|
+
|
|
279
|
+
font-size: calc(var(--ring-unit) * 2.5);
|
|
280
|
+
line-height: calc(var(--ring-unit) * 3);
|
|
148
281
|
}
|
|
149
282
|
|
|
150
|
-
.
|
|
151
|
-
|
|
283
|
+
.innerContainer .islandTitle {
|
|
284
|
+
float: none;
|
|
285
|
+
|
|
286
|
+
text-align: start;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.dense {
|
|
290
|
+
--dialog-padding: calc(var(--ring-unit) * 2);
|
|
152
291
|
}
|
|
153
292
|
|
|
154
293
|
.dense .panel {
|
|
155
|
-
padding-
|
|
294
|
+
padding-top: calc(var(--ring-unit) * 2);
|
|
156
295
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PureComponent } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { type TabTrapObject, type TabTrapProps } from '../tab-trap/tab-trap';
|
|
4
|
+
import { type DialogState, type Interaction, type InteractionDirection } from './dialog-geometry';
|
|
4
5
|
import type { ShortcutsScopeOptions } from '../shortcuts/core';
|
|
5
6
|
export interface DialogProps extends Partial<TabTrapProps> {
|
|
6
7
|
show: boolean;
|
|
@@ -11,8 +12,9 @@ export interface DialogProps extends Partial<TabTrapProps> {
|
|
|
11
12
|
onCloseAttempt: (event: React.MouseEvent<HTMLElement> | KeyboardEvent) => void;
|
|
12
13
|
showCloseButton: boolean;
|
|
13
14
|
shortcutOptions: ShortcutsScopeOptions;
|
|
14
|
-
closeButtonInside: boolean;
|
|
15
15
|
closeButtonTitle?: string;
|
|
16
|
+
movable?: boolean;
|
|
17
|
+
resizable?: boolean;
|
|
16
18
|
trapFocus: boolean;
|
|
17
19
|
contentClassName?: string | null | undefined;
|
|
18
20
|
portalTarget?: Element | null | undefined;
|
|
@@ -22,11 +24,9 @@ export interface DialogProps extends Partial<TabTrapProps> {
|
|
|
22
24
|
modal?: boolean;
|
|
23
25
|
preventBodyScroll?: boolean;
|
|
24
26
|
}
|
|
25
|
-
export default class Dialog extends PureComponent<DialogProps> {
|
|
27
|
+
export default class Dialog extends PureComponent<DialogProps, DialogState> {
|
|
26
28
|
static defaultProps: Partial<DialogProps>;
|
|
27
|
-
state:
|
|
28
|
-
shortcutsScope: string;
|
|
29
|
-
};
|
|
29
|
+
state: DialogState;
|
|
30
30
|
componentDidMount(): void;
|
|
31
31
|
componentDidUpdate(prevProps: DialogProps): void;
|
|
32
32
|
componentWillUnmount(): void;
|
|
@@ -45,6 +45,14 @@ export default class Dialog extends PureComponent<DialogProps> {
|
|
|
45
45
|
dialog?: HTMLElement | null;
|
|
46
46
|
dialogRef: (tabTrapObj: TabTrapObject | null) => void;
|
|
47
47
|
nativeDialog: React.RefObject<HTMLDialogElement | null>;
|
|
48
|
+
innerContainer: React.RefObject<HTMLDivElement | null>;
|
|
49
|
+
interaction: Interaction | null;
|
|
50
|
+
resizeMinimum: Pick<Interaction, 'minWidth' | 'minHeight'> | null;
|
|
51
|
+
fitGeometryToViewport: () => void;
|
|
52
|
+
startInteraction: (event: React.PointerEvent<HTMLElement>, direction: InteractionDirection) => void;
|
|
53
|
+
continueInteraction: (event: React.PointerEvent<HTMLElement>) => void;
|
|
54
|
+
stopInteraction: (event: React.PointerEvent<HTMLElement>) => void;
|
|
55
|
+
startMove: (event: React.PointerEvent<HTMLElement>) => void;
|
|
48
56
|
render(): false | React.JSX.Element;
|
|
49
57
|
}
|
|
50
58
|
export type DialogAttrs = React.JSX.LibraryManagedAttributes<typeof Dialog, DialogProps>;
|
|
@@ -2,20 +2,19 @@ import { createRef, PureComponent } from 'react';
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
|
-
import closeIcon from '@jetbrains/icons/close';
|
|
6
5
|
import { AdaptiveIsland } from '../island/island';
|
|
7
6
|
import getUID from '../global/get-uid';
|
|
8
7
|
import dataTests from '../global/data-tests';
|
|
9
8
|
import Shortcuts from '../shortcuts/shortcuts';
|
|
10
9
|
import TabTrap from '../tab-trap/tab-trap';
|
|
11
|
-
import Button from '../button/button';
|
|
12
10
|
import { normalizePopupTarget, PopupTarget, PopupTargetContext } from '../popup/popup.target';
|
|
13
11
|
import { getPopupContainer } from '../popup/popup';
|
|
12
|
+
import getViewportSize from '../global/get-viewport-size';
|
|
14
13
|
import { preventerFactory as scrollPreventerFactory } from './dialog-body-scroll-preventer';
|
|
14
|
+
import DialogControls from './dialog-controls';
|
|
15
|
+
import { fitGeometry, getNativeTabIndex, getResizeMinimum, getTrapDisabled, moveGeometry, resizeGeometry, } from './dialog-geometry';
|
|
15
16
|
import styles from './dialog.css';
|
|
16
|
-
/**
|
|
17
|
-
* @name Dialog
|
|
18
|
-
*/
|
|
17
|
+
/** @name Dialog */
|
|
19
18
|
function noop() { }
|
|
20
19
|
export default class Dialog extends PureComponent {
|
|
21
20
|
static defaultProps = {
|
|
@@ -25,21 +24,22 @@ export default class Dialog extends PureComponent {
|
|
|
25
24
|
onCloseClick: noop,
|
|
26
25
|
onCloseAttempt: noop,
|
|
27
26
|
showCloseButton: false,
|
|
28
|
-
|
|
27
|
+
movable: true,
|
|
28
|
+
resizable: true,
|
|
29
29
|
shortcutOptions: { modal: false },
|
|
30
30
|
trapFocus: false,
|
|
31
31
|
autoFocusFirst: true,
|
|
32
|
+
native: true,
|
|
32
33
|
modal: true,
|
|
33
34
|
preventBodyScroll: true,
|
|
34
35
|
};
|
|
35
|
-
state = {
|
|
36
|
-
shortcutsScope: getUID('ring-dialog-'),
|
|
37
|
-
};
|
|
36
|
+
state = { shortcutsScope: getUID('ring-dialog-'), geometry: null, resized: false };
|
|
38
37
|
componentDidMount() {
|
|
39
38
|
const { show, native } = this.props;
|
|
40
39
|
if (native && show) {
|
|
41
40
|
this.toggleNativeDialog();
|
|
42
41
|
}
|
|
42
|
+
window.addEventListener('resize', this.fitGeometryToViewport);
|
|
43
43
|
this.toggleScrollPreventer();
|
|
44
44
|
}
|
|
45
45
|
componentDidUpdate(prevProps) {
|
|
@@ -49,15 +49,23 @@ export default class Dialog extends PureComponent {
|
|
|
49
49
|
}
|
|
50
50
|
if (prevProps.show !== this.props.show) {
|
|
51
51
|
this.toggleScrollPreventer();
|
|
52
|
+
if (show) {
|
|
53
|
+
this.fitGeometryToViewport();
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
this.interaction = null;
|
|
57
|
+
}
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
60
|
componentWillUnmount() {
|
|
61
|
+
window.removeEventListener('resize', this.fitGeometryToViewport);
|
|
62
|
+
this.interaction = null;
|
|
55
63
|
this.scrollPreventer.reset();
|
|
56
64
|
}
|
|
57
65
|
scrollPreventer = scrollPreventerFactory(getUID('preventer-'));
|
|
58
66
|
uid = getUID('dialog-');
|
|
59
67
|
toggleNativeDialog() {
|
|
60
|
-
const { show, modal } = this.props;
|
|
68
|
+
const { show, modal, autoFocusFirst } = this.props;
|
|
61
69
|
if (this.nativeDialog.current) {
|
|
62
70
|
if (show) {
|
|
63
71
|
this.nativeDialog.current.removeAttribute('open');
|
|
@@ -67,6 +75,9 @@ export default class Dialog extends PureComponent {
|
|
|
67
75
|
else {
|
|
68
76
|
this.nativeDialog.current.show();
|
|
69
77
|
}
|
|
78
|
+
if (!autoFocusFirst && !this.nativeDialog.current.querySelector('[autofocus]')) {
|
|
79
|
+
this.nativeDialog.current.focus();
|
|
80
|
+
}
|
|
70
81
|
}
|
|
71
82
|
else {
|
|
72
83
|
this.nativeDialog.current.close();
|
|
@@ -99,42 +110,112 @@ export default class Dialog extends PureComponent {
|
|
|
99
110
|
this.props.onCloseAttempt(event);
|
|
100
111
|
}
|
|
101
112
|
};
|
|
102
|
-
return {
|
|
103
|
-
esc: onEscape,
|
|
104
|
-
};
|
|
113
|
+
return { esc: onEscape };
|
|
105
114
|
};
|
|
106
115
|
dialog;
|
|
107
116
|
dialogRef = (tabTrapObj) => {
|
|
108
117
|
this.dialog = tabTrapObj && tabTrapObj.node;
|
|
109
118
|
};
|
|
110
119
|
nativeDialog = createRef();
|
|
120
|
+
innerContainer = createRef();
|
|
121
|
+
interaction = null;
|
|
122
|
+
resizeMinimum = null;
|
|
123
|
+
fitGeometryToViewport = () => {
|
|
124
|
+
this.setState(({ geometry }) => {
|
|
125
|
+
if (!geometry) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
const { width, height } = getViewportSize();
|
|
129
|
+
return { geometry: fitGeometry(geometry, width, height) };
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
startInteraction = (event, direction) => {
|
|
133
|
+
if ((event.button ?? 0) !== 0 || !this.innerContainer.current) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
const { left, top, width, height } = this.innerContainer.current.getBoundingClientRect();
|
|
137
|
+
const resizeMinimum = this.resizeMinimum ?? getResizeMinimum(this.innerContainer.current.firstElementChild);
|
|
138
|
+
if (direction !== 'move') {
|
|
139
|
+
this.resizeMinimum = resizeMinimum;
|
|
140
|
+
}
|
|
141
|
+
this.interaction = {
|
|
142
|
+
pointerId: event.pointerId,
|
|
143
|
+
direction,
|
|
144
|
+
startX: event.clientX,
|
|
145
|
+
startY: event.clientY,
|
|
146
|
+
...resizeMinimum,
|
|
147
|
+
geometry: { left, top, width, height },
|
|
148
|
+
};
|
|
149
|
+
this.setState(({ resized }) => ({ geometry: { left, top, width, height }, resized: resized || direction !== 'move' }));
|
|
150
|
+
event.currentTarget.setPointerCapture?.(event.pointerId);
|
|
151
|
+
event.preventDefault();
|
|
152
|
+
};
|
|
153
|
+
continueInteraction = (event) => {
|
|
154
|
+
const interaction = this.interaction;
|
|
155
|
+
if (!interaction || interaction.pointerId !== event.pointerId) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const dx = event.clientX - interaction.startX;
|
|
159
|
+
const dy = event.clientY - interaction.startY;
|
|
160
|
+
const { width: viewportWidth, height: viewportHeight } = getViewportSize();
|
|
161
|
+
const start = interaction.geometry;
|
|
162
|
+
if (interaction.direction === 'move') {
|
|
163
|
+
this.setState({ geometry: moveGeometry(start, dx, dy, viewportWidth, viewportHeight) });
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this.setState({
|
|
167
|
+
geometry: resizeGeometry(interaction, dx, dy, viewportWidth, viewportHeight),
|
|
168
|
+
resized: true,
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
stopInteraction = (event) => {
|
|
172
|
+
if (this.interaction?.pointerId !== event.pointerId) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
this.interaction = null;
|
|
176
|
+
if (event.currentTarget.hasPointerCapture?.(event.pointerId)) {
|
|
177
|
+
event.currentTarget.releasePointerCapture?.(event.pointerId);
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
startMove = (event) => {
|
|
181
|
+
const target = event.target;
|
|
182
|
+
if (!this.props.movable || !(target instanceof Element)) {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const handle = target.closest('[data-ring-dialog-move-handle], [data-ring-island-header]');
|
|
186
|
+
if (handle?.parentElement === event.currentTarget) {
|
|
187
|
+
this.startInteraction(event, 'move');
|
|
188
|
+
}
|
|
189
|
+
};
|
|
111
190
|
render() {
|
|
112
|
-
const { show, showCloseButton, onOverlayClick, onCloseAttempt, onEscPress, onCloseClick, children, className, contentClassName, trapFocus, 'data-test': dataTest,
|
|
191
|
+
const { show, showCloseButton, onOverlayClick, onCloseAttempt, onEscPress, onCloseClick, children, className, contentClassName, trapFocus, 'data-test': dataTest, portalTarget, label, closeButtonTitle, dense, shortcutOptions, native, modal, preventBodyScroll, movable, resizable, autoFocusFirst, focusBackOnClose, focusBackOnExit, trapDisabled, ...restProps } = this.props;
|
|
113
192
|
const classes = classNames(styles.container, className);
|
|
114
193
|
const shortcutsMap = this.getShortcutsMap();
|
|
115
194
|
const content = (<>
|
|
116
|
-
<Shortcuts map={shortcutsMap} scope={this.state.shortcutsScope} options={
|
|
195
|
+
<Shortcuts disabled={!show} map={shortcutsMap} scope={this.state.shortcutsScope} options={shortcutOptions}/>
|
|
117
196
|
{(onOverlayClick !== noop || onCloseAttempt !== noop) && (<div
|
|
118
197
|
// click handler is duplicated in close button
|
|
119
198
|
role='presentation' className={styles.clickableOverlay} onClick={this.handleClick} data-test='ring-dialog-overlay'/>)}
|
|
120
|
-
<div className={styles.innerContainer}
|
|
199
|
+
<div ref={this.innerContainer} data-test='ring-dialog-inner-container' className={classNames(styles.innerContainer, { [styles.resized]: this.state.resized })} style={this.state.geometry
|
|
200
|
+
? {
|
|
201
|
+
position: 'fixed',
|
|
202
|
+
left: this.state.geometry.left,
|
|
203
|
+
top: this.state.geometry.top,
|
|
204
|
+
width: this.state.resized ? this.state.geometry.width : undefined,
|
|
205
|
+
height: this.state.resized ? this.state.geometry.height : undefined,
|
|
206
|
+
}
|
|
207
|
+
: undefined}>
|
|
121
208
|
<AdaptiveIsland className={classNames(styles.content, contentClassName, {
|
|
122
209
|
[styles.dense]: dense,
|
|
123
|
-
[styles.
|
|
124
|
-
|
|
125
|
-
})} data-test='ring-dialog' role='dialog' aria-label={label}>
|
|
210
|
+
[styles.movable]: movable,
|
|
211
|
+
})} data-test='ring-dialog' role={native ? undefined : 'dialog'} aria-label={native ? undefined : label} onPointerDown={this.startMove} onPointerMove={this.continueInteraction} onPointerUp={this.stopInteraction} onPointerCancel={this.stopInteraction} onLostPointerCapture={this.stopInteraction}>
|
|
126
212
|
{children}
|
|
127
|
-
{
|
|
128
|
-
[styles.closeButtonOutside]: !closeButtonInside,
|
|
129
|
-
[styles.closeButtonInside]: closeButtonInside,
|
|
130
|
-
})} iconClassName={classNames(styles.closeIcon, {
|
|
131
|
-
[styles.closeIconOutside]: !closeButtonInside,
|
|
132
|
-
})} onClick={this.onCloseClick} title={closeButtonTitle} aria-label={closeButtonTitle || 'close dialog'}/>)}
|
|
213
|
+
<DialogControls movable={movable} resizable={resizable} showCloseButton={showCloseButton} closeButtonTitle={closeButtonTitle} onCloseClick={this.onCloseClick} onStartInteraction={this.startInteraction} onStopInteraction={this.stopInteraction}/>
|
|
133
214
|
</AdaptiveIsland>
|
|
134
215
|
</div>
|
|
135
216
|
</>);
|
|
136
217
|
if (native) {
|
|
137
|
-
return (<dialog className={classNames(styles.nativeDialog, className)} ref={this.nativeDialog} data-rg-modal-dialog-container={modal ? '' : undefined}>
|
|
218
|
+
return (<dialog {...restProps} aria-label={label} className={classNames(styles.nativeDialog, className)} data-test={dataTests('ring-dialog-container', dataTest)} ref={this.nativeDialog} tabIndex={getNativeTabIndex(autoFocusFirst)} onCancel={event => event.preventDefault()} data-rg-modal-dialog-container={modal ? '' : undefined}>
|
|
138
219
|
<PopupTarget id={this.uid} className={styles.popupTarget}>
|
|
139
220
|
{target => (<>
|
|
140
221
|
{content}
|
|
@@ -157,7 +238,7 @@ export default class Dialog extends PureComponent {
|
|
|
157
238
|
}
|
|
158
239
|
}
|
|
159
240
|
return createPortal(<PopupTarget id={this.uid} className={styles.popupTarget}>
|
|
160
|
-
{target => (<TabTrap trapDisabled={
|
|
241
|
+
{target => (<TabTrap trapDisabled={getTrapDisabled(trapFocus, trapDisabled)} autoFocusFirst={autoFocusFirst} focusBackOnClose={focusBackOnClose} focusBackOnExit={focusBackOnExit} data-test={dataTests('ring-dialog-container', dataTest)} data-rg-modal-dialog-container='' ref={this.dialogRef} className={classes} role='presentation' {...restProps}>
|
|
161
242
|
{content}
|
|
162
243
|
{target}
|
|
163
244
|
</TabTrap>)}
|
package/components/http/http.js
CHANGED
|
@@ -97,23 +97,12 @@ export default class HTTP {
|
|
|
97
97
|
const contentType = response.headers.get('content-type');
|
|
98
98
|
const isJson = contentType && contentType.indexOf('application/json') !== -1;
|
|
99
99
|
if (!response.ok) {
|
|
100
|
-
|
|
101
|
-
try {
|
|
102
|
-
resJson = await (isJson ? response.json() : response.text());
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
// noop
|
|
106
|
-
}
|
|
100
|
+
const resJson = await (isJson ? response.json() : response.text());
|
|
107
101
|
throw new HTTPError(response, resJson);
|
|
108
102
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return parsedResponse;
|
|
113
|
-
}
|
|
114
|
-
catch (err) {
|
|
115
|
-
return response;
|
|
116
|
-
}
|
|
103
|
+
const parsedResponse = await (isJson ? response.json() : { data: await response.text() });
|
|
104
|
+
this._storeRequestMeta(parsedResponse, response);
|
|
105
|
+
return parsedResponse;
|
|
117
106
|
}
|
|
118
107
|
fetch = async (url, params = {}) => {
|
|
119
108
|
const { body, query = {}, ...fetchConfig } = params;
|
|
@@ -56,7 +56,7 @@ class Header extends Component {
|
|
|
56
56
|
}
|
|
57
57
|
: undefined;
|
|
58
58
|
const titleStyle = this.getTitleStyle(phase);
|
|
59
|
-
return (<div {...restProps} data-test='ring-island-header' className={classes} style={headerStyle}>
|
|
59
|
+
return (<div {...restProps} data-ring-island-header='' data-test='ring-island-header' className={classes} style={headerStyle}>
|
|
60
60
|
{wrapWithTitle && (<h2 className={styles.title} style={titleStyle}>
|
|
61
61
|
{children}
|
|
62
62
|
</h2>)}
|
|
@@ -7,6 +7,9 @@ const reactRoot = createRoot(containerElement);
|
|
|
7
7
|
* Renders LoginDialog into virtual node to skip maintaining container
|
|
8
8
|
*/
|
|
9
9
|
function renderLoginDialog(props) {
|
|
10
|
+
if (!containerElement.isConnected) {
|
|
11
|
+
document.body.appendChild(containerElement);
|
|
12
|
+
}
|
|
10
13
|
reactRoot.render(<ControlsHeightContext value={getGlobalControlsHeight()}>
|
|
11
14
|
<LoginDialog {...props}/>
|
|
12
15
|
</ControlsHeightContext>);
|
|
@@ -188,6 +188,9 @@ export default class UserAgreementService {
|
|
|
188
188
|
preview,
|
|
189
189
|
...restOptions,
|
|
190
190
|
};
|
|
191
|
+
if (!this.container.isConnected) {
|
|
192
|
+
document.body.appendChild(this.container);
|
|
193
|
+
}
|
|
191
194
|
this.reactRoot.render(<ControlsHeightContext value={getGlobalControlsHeight()}>
|
|
192
195
|
<UserAgreement {...props}/>
|
|
193
196
|
</ControlsHeightContext>);
|
|
@@ -2,10 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
@value extra-small-screen-media from '../global/global.css';
|
|
4
4
|
|
|
5
|
-
.agreementDialog {
|
|
6
|
-
padding-bottom: 80px;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
5
|
.dialogContent {
|
|
10
6
|
width: 600px;
|
|
11
7
|
|
|
@@ -17,13 +13,11 @@
|
|
|
17
13
|
}
|
|
18
14
|
|
|
19
15
|
.suggestion {
|
|
16
|
+
margin-inline-end: var(--ring-unit);
|
|
17
|
+
|
|
20
18
|
padding-bottom: var(--ring-unit);
|
|
21
19
|
|
|
22
20
|
white-space: nowrap;
|
|
23
21
|
|
|
24
22
|
font-size: 12px;
|
|
25
23
|
}
|
|
26
|
-
|
|
27
|
-
.remindLaterButton {
|
|
28
|
-
float: right;
|
|
29
|
-
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
* @name User Agreement
|
|
3
3
|
*/
|
|
4
4
|
import { PureComponent } from 'react';
|
|
5
|
-
import classNames from 'classnames';
|
|
6
5
|
import Dialog from '../dialog/dialog';
|
|
7
6
|
import { Content, Header } from '../island/island';
|
|
8
7
|
import Panel from '../panel/panel';
|
|
@@ -29,26 +28,25 @@ export default class UserAgreement extends PureComponent {
|
|
|
29
28
|
const { translations, onAccept, onDecline, onClose, onRemindLater, children, show, preview, className } = this.props;
|
|
30
29
|
return (<I18nContext.Consumer>
|
|
31
30
|
{/* eslint-disable-next-line complexity */}
|
|
32
|
-
{({ translate }) => (<Dialog label={translations?.userAgreement ?? translate('userAgreement')} show={show} className={
|
|
31
|
+
{({ translate }) => (<Dialog label={translations?.userAgreement ?? translate('userAgreement')} show={show} className={className ?? undefined} contentClassName={style.dialogContent} trapFocus autoFocusFirst={false} data-test='user-agreement'>
|
|
33
32
|
<Header>{translations?.userAgreement ?? translate('userAgreement')}</Header>
|
|
34
33
|
<Content tabIndex={0} fade onScrollToBottom={this.onScrollToBottom}>
|
|
35
34
|
{children}
|
|
36
35
|
</Content>
|
|
37
36
|
{!preview && (<Panel>
|
|
38
37
|
{onRemindLater && !scrolledDown && (<div className={style.suggestion}>{translations?.scrollToAccept ?? translate('scrollToAccept')}</div>)}
|
|
39
|
-
<Button primary disabled={!scrolledDown} onClick={onAccept} data-test='accept'>
|
|
40
|
-
{translations?.accept ?? translate('accept')}
|
|
41
|
-
</Button>
|
|
42
|
-
<Button onClick={onDecline} autoFocus data-test='decline'>
|
|
43
|
-
{translations?.decline ?? translate('decline')}
|
|
44
|
-
</Button>
|
|
45
|
-
|
|
46
38
|
{!onRemindLater && !scrolledDown && (<span className={style.suggestion}>
|
|
47
39
|
{translations?.scrollToAccept ?? translate('scrollToAccept')}
|
|
48
40
|
</span>)}
|
|
49
|
-
|
|
41
|
+
<Button onClick={onDecline} autoFocus data-test='decline'>
|
|
42
|
+
{translations?.decline ?? translate('decline')}
|
|
43
|
+
</Button>
|
|
44
|
+
{onRemindLater && (<Button onClick={onRemindLater} data-test='later'>
|
|
50
45
|
{translations?.remindLater ?? translate('remindLater')}
|
|
51
46
|
</Button>)}
|
|
47
|
+
<Button primary disabled={!scrolledDown} onClick={onAccept} data-test='accept'>
|
|
48
|
+
{translations?.accept ?? translate('accept')}
|
|
49
|
+
</Button>
|
|
52
50
|
</Panel>)}
|
|
53
51
|
{preview && (<Panel>
|
|
54
52
|
<Button onClick={onClose} autoFocus data-test='close'>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetbrains/ring-ui",
|
|
3
|
-
"version": "8.0.0-beta.
|
|
3
|
+
"version": "8.0.0-beta.11",
|
|
4
4
|
"description": "JetBrains UI library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "JetBrains"
|
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
"@babel/core": "^7.29.7",
|
|
219
219
|
"@babel/preset-typescript": "^8.0.1",
|
|
220
220
|
"@jetbrains/babel-preset-jetbrains": "^2.4.0",
|
|
221
|
-
"@jetbrains/icons": "^5.23.
|
|
221
|
+
"@jetbrains/icons": "^5.23.3",
|
|
222
222
|
"@jetbrains/postcss-require-hover": "^0.2.0",
|
|
223
223
|
"@types/combokeys": "^2.4.9",
|
|
224
224
|
"@types/element-resize-detector": "^1.1.6",
|
|
@@ -240,8 +240,8 @@
|
|
|
240
240
|
"highlight.js": "^10.7.2",
|
|
241
241
|
"just-debounce-it": "^3.2.0",
|
|
242
242
|
"memoize-one": "^6.0.0",
|
|
243
|
-
"postcss": "^8.5.
|
|
244
|
-
"postcss-calc": "^
|
|
243
|
+
"postcss": "^8.5.25",
|
|
244
|
+
"postcss-calc": "^11.0.1",
|
|
245
245
|
"postcss-font-family-system-ui": "^5.0.0",
|
|
246
246
|
"postcss-loader": "^8.2.1",
|
|
247
247
|
"postcss-modules-values-replace": "^4.2.2",
|
|
@@ -258,7 +258,7 @@
|
|
|
258
258
|
"util-deprecate": "^1.0.2"
|
|
259
259
|
},
|
|
260
260
|
"engines": {
|
|
261
|
-
"node": ">=
|
|
261
|
+
"node": "^22.22.3 || ^24.15 || >=26.0",
|
|
262
262
|
"npm": ">=6.0.0"
|
|
263
263
|
},
|
|
264
264
|
"bugs": {
|