@jetbrains/ring-ui 7.0.115 → 7.0.117
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/collapsible-group/collapsible-group.css +138 -0
- package/components/collapsible-group/collapsible-group.d.ts +16 -0
- package/components/collapsible-group/collapsible-group.js +73 -0
- package/components/editable-heading/editable-heading.js +14 -14
- package/components/expand/collapsible-group.css +23 -89
- package/components/expand/collapsible-group.d.ts +8 -16
- package/components/expand/collapsible-group.js +13 -72
- package/components/global/use-event-callback.d.ts +3 -0
- package/components/global/use-event-callback.js +6 -1
- package/components/popup/popup.d.ts +2 -0
- package/components/popup/popup.js +2 -2
- package/package.json +30 -30
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
@import '../global/variables.css';
|
|
2
|
+
|
|
3
|
+
.expand .collapseRoot {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.expand {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
|
|
12
|
+
box-sizing: border-box;
|
|
13
|
+
|
|
14
|
+
border: 1px solid var(--ring-line-color);
|
|
15
|
+
border-radius: var(--ring-border-radius-large);
|
|
16
|
+
outline: none;
|
|
17
|
+
background: var(--ring-content-background-color);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.hovered {
|
|
21
|
+
box-shadow: var(--ring-popup-shadow);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.expanded {
|
|
25
|
+
box-shadow: var(--ring-popup-shadow);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.focused {
|
|
29
|
+
box-shadow: 0 0 0 2px var(--ring-border-hover-color), var(--ring-popup-shadow);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.header {
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: calc(var(--ring-unit) * 1.5);
|
|
36
|
+
|
|
37
|
+
height: 28px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.headerButton {
|
|
41
|
+
display: block;
|
|
42
|
+
|
|
43
|
+
box-sizing: border-box;
|
|
44
|
+
width: 100%;
|
|
45
|
+
padding: calc(var(--ring-unit) * 1.5);
|
|
46
|
+
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
text-align: left;
|
|
49
|
+
|
|
50
|
+
color: inherit;
|
|
51
|
+
|
|
52
|
+
border: 0;
|
|
53
|
+
background: transparent;
|
|
54
|
+
|
|
55
|
+
font: inherit;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.headerButton:focus-visible {
|
|
59
|
+
outline: none;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.headerStatic {
|
|
63
|
+
display: block;
|
|
64
|
+
|
|
65
|
+
padding: calc(var(--ring-unit) * 1.5);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.headerContent {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
gap: var(--ring-unit);
|
|
72
|
+
|
|
73
|
+
flex: 1;
|
|
74
|
+
|
|
75
|
+
min-width: 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.avatarGroup {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: var(--ring-unit);
|
|
82
|
+
|
|
83
|
+
flex-shrink: 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.title {
|
|
87
|
+
color: var(--ring-text-color);
|
|
88
|
+
|
|
89
|
+
font-size: var(--ring-font-size);
|
|
90
|
+
font-weight: var(--ring-font-weight-bold);
|
|
91
|
+
line-height: var(--ring-line-height);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.subtitleGroup {
|
|
95
|
+
display: flex;
|
|
96
|
+
align-items: center;
|
|
97
|
+
gap: var(--ring-unit);
|
|
98
|
+
|
|
99
|
+
min-width: 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.subtitle {
|
|
103
|
+
color: var(--ring-secondary-color);
|
|
104
|
+
|
|
105
|
+
font-size: var(--ring-font-size);
|
|
106
|
+
line-height: var(--ring-line-height);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.subtitleChevron {
|
|
110
|
+
color: var(--ring-secondary-color);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.toggle {
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
|
|
117
|
+
flex-shrink: 0;
|
|
118
|
+
justify-content: center;
|
|
119
|
+
|
|
120
|
+
width: calc(var(--ring-unit) * 3);
|
|
121
|
+
height: calc(var(--ring-unit) * 3);
|
|
122
|
+
|
|
123
|
+
border-radius: calc(var(--ring-unit) / 2);
|
|
124
|
+
background: var(--ring-secondary-background-color);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.toggleIcon {
|
|
128
|
+
color: var(--ring-secondary-color);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.body {
|
|
132
|
+
padding: 0 calc(var(--ring-unit) * 2) calc(var(--ring-unit) * 1.5);
|
|
133
|
+
|
|
134
|
+
color: var(--ring-text-color);
|
|
135
|
+
|
|
136
|
+
font-size: var(--ring-font-size);
|
|
137
|
+
line-height: var(--ring-line-height);
|
|
138
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface CollapsibleGroupProps {
|
|
3
|
+
avatar?: React.ReactNode;
|
|
4
|
+
title: React.ReactNode;
|
|
5
|
+
subtitle?: React.ReactNode;
|
|
6
|
+
children?: React.ReactNode;
|
|
7
|
+
className?: string | null | undefined;
|
|
8
|
+
defaultExpanded?: boolean;
|
|
9
|
+
expanded?: boolean | null | undefined;
|
|
10
|
+
onChange?: (expanded: boolean) => void;
|
|
11
|
+
disableAnimation?: boolean;
|
|
12
|
+
interactive?: boolean;
|
|
13
|
+
'data-test'?: string | null | undefined;
|
|
14
|
+
}
|
|
15
|
+
declare const CollapsibleGroup: React.ForwardRefExoticComponent<CollapsibleGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
16
|
+
export default CollapsibleGroup;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { forwardRef, useContext, useState } from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import chevronRightIcon from '@jetbrains/icons/chevron-12px-right';
|
|
4
|
+
import chevronDownIcon from '@jetbrains/icons/chevron-12px-down';
|
|
5
|
+
import Icon from '../icon/icon';
|
|
6
|
+
import Collapse from '../collapse/collapse';
|
|
7
|
+
import CollapseContent from '../collapse/collapse-content';
|
|
8
|
+
import { CollapseContext } from '../collapse/collapse-context';
|
|
9
|
+
import styles from './collapsible-group.css';
|
|
10
|
+
function CollapsibleGroupHeaderContent({ avatar, titleContent, subtitle }) {
|
|
11
|
+
const { collapsed } = useContext(CollapseContext);
|
|
12
|
+
return (<span className={styles.header}>
|
|
13
|
+
<span className={styles.headerContent}>
|
|
14
|
+
<span className={styles.avatarGroup}>
|
|
15
|
+
{avatar}
|
|
16
|
+
<span className={styles.title}>{titleContent}</span>
|
|
17
|
+
</span>
|
|
18
|
+
{subtitle ? (<span className={styles.subtitleGroup}>
|
|
19
|
+
<Icon className={styles.subtitleChevron} glyph={chevronRightIcon} aria-hidden/>
|
|
20
|
+
<span className={styles.subtitle}>{subtitle}</span>
|
|
21
|
+
</span>) : null}
|
|
22
|
+
</span>
|
|
23
|
+
<span className={styles.toggle} aria-hidden>
|
|
24
|
+
<Icon className={styles.toggleIcon} glyph={collapsed ? chevronRightIcon : chevronDownIcon}/>
|
|
25
|
+
</span>
|
|
26
|
+
</span>);
|
|
27
|
+
}
|
|
28
|
+
function CollapsibleGroupHeader({ avatar, titleContent, subtitle, ...buttonProps }) {
|
|
29
|
+
const { setCollapsed, collapsed, id } = useContext(CollapseContext);
|
|
30
|
+
return (<button type='button' {...buttonProps} className={styles.headerButton} onClick={setCollapsed} aria-controls={`collapse-content-${id}`} aria-expanded={!collapsed}>
|
|
31
|
+
<CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
|
|
32
|
+
</button>);
|
|
33
|
+
}
|
|
34
|
+
function CollapsibleGroupHeaderStatic({ avatar, titleContent, subtitle }) {
|
|
35
|
+
return (<span className={styles.headerStatic}>
|
|
36
|
+
<CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
|
|
37
|
+
</span>);
|
|
38
|
+
}
|
|
39
|
+
const CollapsibleGroup = forwardRef(({ avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, 'data-test': dataTest, }, ref) => {
|
|
40
|
+
const [innerExpanded, setInnerExpanded] = useState(defaultExpanded);
|
|
41
|
+
const [hovered, setHovered] = useState(false);
|
|
42
|
+
const [focused, setFocused] = useState(false);
|
|
43
|
+
const isExpanded = expanded ?? innerExpanded;
|
|
44
|
+
const handleChange = (collapsed) => {
|
|
45
|
+
const nextExpanded = !collapsed;
|
|
46
|
+
if (expanded == null) {
|
|
47
|
+
setInnerExpanded(nextExpanded);
|
|
48
|
+
}
|
|
49
|
+
onChange(nextExpanded);
|
|
50
|
+
};
|
|
51
|
+
const onBlur = (event) => {
|
|
52
|
+
const nextTarget = event.relatedTarget;
|
|
53
|
+
if (nextTarget instanceof Node && event.currentTarget.contains(nextTarget)) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
setFocused(false);
|
|
57
|
+
};
|
|
58
|
+
const classes = classNames(styles.expand, className, {
|
|
59
|
+
[styles.hovered]: hovered,
|
|
60
|
+
[styles.expanded]: isExpanded,
|
|
61
|
+
[styles.focused]: focused,
|
|
62
|
+
});
|
|
63
|
+
return (<div ref={ref} className={classes} data-test={dataTest}>
|
|
64
|
+
<Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} className={styles.collapseRoot}>
|
|
65
|
+
{interactive ? (<CollapsibleGroupHeader avatar={avatar} titleContent={title} subtitle={subtitle} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} onFocus={() => setFocused(true)} onBlur={onBlur}/>) : (<CollapsibleGroupHeaderStatic avatar={avatar} titleContent={title} subtitle={subtitle}/>)}
|
|
66
|
+
<CollapseContent>
|
|
67
|
+
<div className={styles.body}>{children}</div>
|
|
68
|
+
</CollapseContent>
|
|
69
|
+
</Collapse>
|
|
70
|
+
</div>);
|
|
71
|
+
});
|
|
72
|
+
CollapsibleGroup.displayName = 'CollapsibleGroup';
|
|
73
|
+
export default CollapsibleGroup;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useLayoutEffect } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import Heading, { Levels } from '../heading/heading';
|
|
@@ -46,26 +46,20 @@ export const EditableHeading = (props) => {
|
|
|
46
46
|
});
|
|
47
47
|
const headingClasses = classNames(styles.heading, headingClassName, size !== Size.AUTO && styles[`size${size}`]);
|
|
48
48
|
const inputClasses = classNames('ring-js-shortcuts', styles.input, styles.textarea, { [styles.textareaNotOverflow]: !isOverflow }, size !== Size.AUTO && inputStyles[`size${size}`], level !== Levels.H4 && styles[`level${level}`], inputClassName);
|
|
49
|
-
const
|
|
50
|
-
if (!el || !el.style) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
el.style.height = '0';
|
|
54
|
-
const { paddingTop, paddingBottom } = window.getComputedStyle(el);
|
|
55
|
-
el.style.height = `${el.scrollHeight - parseFloat(paddingTop) - parseFloat(paddingBottom)}px`;
|
|
56
|
-
};
|
|
57
|
-
const checkValue = (el) => {
|
|
49
|
+
const checkValue = React.useCallback((el) => {
|
|
58
50
|
if (multiline && el && el.scrollHeight >= el.clientHeight) {
|
|
59
|
-
|
|
51
|
+
el.style.height = '0';
|
|
52
|
+
const { paddingTop, paddingBottom } = window.getComputedStyle(el);
|
|
53
|
+
el.style.height = `${el.scrollHeight - parseFloat(paddingTop) - parseFloat(paddingBottom)}px`;
|
|
60
54
|
}
|
|
61
|
-
};
|
|
62
|
-
const checkOverflow = (el) => {
|
|
55
|
+
}, [multiline]);
|
|
56
|
+
const checkOverflow = React.useCallback((el) => {
|
|
63
57
|
const scrollHeight = el.scrollHeight || 0;
|
|
64
58
|
const clientHeight = el.clientHeight || 0;
|
|
65
59
|
const scrollTop = el.scrollTop || 0;
|
|
66
60
|
setIsScrolledToBottom(scrollHeight - clientHeight <= scrollTop);
|
|
67
61
|
setIsOverflow(scrollHeight > clientHeight);
|
|
68
|
-
};
|
|
62
|
+
}, []);
|
|
69
63
|
const onHeadingMouseDown = () => {
|
|
70
64
|
setIsMouseDown(true);
|
|
71
65
|
};
|
|
@@ -101,6 +95,12 @@ export const EditableHeading = (props) => {
|
|
|
101
95
|
setIsInFocus(false);
|
|
102
96
|
onBlur?.(e);
|
|
103
97
|
};
|
|
98
|
+
useLayoutEffect(() => {
|
|
99
|
+
if (multiline && isEditing && textAreaRef.current) {
|
|
100
|
+
checkValue(textAreaRef.current);
|
|
101
|
+
checkOverflow(textAreaRef.current);
|
|
102
|
+
}
|
|
103
|
+
}, [checkOverflow, checkValue, isEditing, multiline]);
|
|
104
104
|
useEffect(() => {
|
|
105
105
|
window.addEventListener('mousemove', onMouseMove);
|
|
106
106
|
window.addEventListener('mouseup', onMouseUp);
|
|
@@ -1,138 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
flex-direction: column;
|
|
6
|
-
}
|
|
1
|
+
/* Deprecated alias of `../collapsible-group/collapsible-group.css` (removed in Ring UI 8.0).
|
|
2
|
+
Class names are forwarded via `composes` so the canonical stylesheet stays the single source of
|
|
3
|
+
the actual rules, while `import styles from '.../components/expand/collapsible-group.css'` keeps
|
|
4
|
+
returning the full token map. */
|
|
7
5
|
|
|
8
6
|
.expand {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
box-sizing: border-box;
|
|
7
|
+
composes: expand from '../collapsible-group/collapsible-group.css';
|
|
8
|
+
}
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
outline: none;
|
|
17
|
-
background: var(--ring-content-background-color);
|
|
10
|
+
.collapseRoot {
|
|
11
|
+
composes: collapseRoot from '../collapsible-group/collapsible-group.css';
|
|
18
12
|
}
|
|
19
13
|
|
|
20
14
|
.hovered {
|
|
21
|
-
|
|
15
|
+
composes: hovered from '../collapsible-group/collapsible-group.css';
|
|
22
16
|
}
|
|
23
17
|
|
|
24
18
|
.expanded {
|
|
25
|
-
|
|
19
|
+
composes: expanded from '../collapsible-group/collapsible-group.css';
|
|
26
20
|
}
|
|
27
21
|
|
|
28
22
|
.focused {
|
|
29
|
-
|
|
23
|
+
composes: focused from '../collapsible-group/collapsible-group.css';
|
|
30
24
|
}
|
|
31
25
|
|
|
32
26
|
.header {
|
|
33
|
-
|
|
34
|
-
align-items: center;
|
|
35
|
-
gap: calc(var(--ring-unit) * 1.5);
|
|
36
|
-
|
|
37
|
-
height: 28px;
|
|
27
|
+
composes: header from '../collapsible-group/collapsible-group.css';
|
|
38
28
|
}
|
|
39
29
|
|
|
40
30
|
.headerButton {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
box-sizing: border-box;
|
|
44
|
-
width: 100%;
|
|
45
|
-
padding: calc(var(--ring-unit) * 1.5);
|
|
46
|
-
|
|
47
|
-
cursor: pointer;
|
|
48
|
-
text-align: left;
|
|
49
|
-
|
|
50
|
-
color: inherit;
|
|
51
|
-
|
|
52
|
-
border: 0;
|
|
53
|
-
background: transparent;
|
|
54
|
-
|
|
55
|
-
font: inherit;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.headerButton:focus-visible {
|
|
59
|
-
outline: none;
|
|
31
|
+
composes: headerButton from '../collapsible-group/collapsible-group.css';
|
|
60
32
|
}
|
|
61
33
|
|
|
62
34
|
.headerStatic {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
padding: calc(var(--ring-unit) * 1.5);
|
|
35
|
+
composes: headerStatic from '../collapsible-group/collapsible-group.css';
|
|
66
36
|
}
|
|
67
37
|
|
|
68
38
|
.headerContent {
|
|
69
|
-
|
|
70
|
-
align-items: center;
|
|
71
|
-
gap: var(--ring-unit);
|
|
72
|
-
|
|
73
|
-
flex: 1;
|
|
74
|
-
|
|
75
|
-
min-width: 0;
|
|
39
|
+
composes: headerContent from '../collapsible-group/collapsible-group.css';
|
|
76
40
|
}
|
|
77
41
|
|
|
78
42
|
.avatarGroup {
|
|
79
|
-
|
|
80
|
-
align-items: center;
|
|
81
|
-
gap: var(--ring-unit);
|
|
82
|
-
|
|
83
|
-
flex-shrink: 0;
|
|
43
|
+
composes: avatarGroup from '../collapsible-group/collapsible-group.css';
|
|
84
44
|
}
|
|
85
45
|
|
|
86
46
|
.title {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
font-size: var(--ring-font-size);
|
|
90
|
-
font-weight: var(--ring-font-weight-bold);
|
|
91
|
-
line-height: var(--ring-line-height);
|
|
47
|
+
composes: title from '../collapsible-group/collapsible-group.css';
|
|
92
48
|
}
|
|
93
49
|
|
|
94
50
|
.subtitleGroup {
|
|
95
|
-
|
|
96
|
-
align-items: center;
|
|
97
|
-
gap: var(--ring-unit);
|
|
98
|
-
|
|
99
|
-
min-width: 0;
|
|
51
|
+
composes: subtitleGroup from '../collapsible-group/collapsible-group.css';
|
|
100
52
|
}
|
|
101
53
|
|
|
102
54
|
.subtitle {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
font-size: var(--ring-font-size);
|
|
106
|
-
line-height: var(--ring-line-height);
|
|
55
|
+
composes: subtitle from '../collapsible-group/collapsible-group.css';
|
|
107
56
|
}
|
|
108
57
|
|
|
109
58
|
.subtitleChevron {
|
|
110
|
-
|
|
59
|
+
composes: subtitleChevron from '../collapsible-group/collapsible-group.css';
|
|
111
60
|
}
|
|
112
61
|
|
|
113
62
|
.toggle {
|
|
114
|
-
|
|
115
|
-
align-items: center;
|
|
116
|
-
|
|
117
|
-
flex-shrink: 0;
|
|
118
|
-
justify-content: center;
|
|
119
|
-
|
|
120
|
-
width: calc(var(--ring-unit) * 3);
|
|
121
|
-
height: calc(var(--ring-unit) * 3);
|
|
122
|
-
|
|
123
|
-
border-radius: calc(var(--ring-unit) / 2);
|
|
124
|
-
background: var(--ring-secondary-background-color);
|
|
63
|
+
composes: toggle from '../collapsible-group/collapsible-group.css';
|
|
125
64
|
}
|
|
126
65
|
|
|
127
66
|
.toggleIcon {
|
|
128
|
-
|
|
67
|
+
composes: toggleIcon from '../collapsible-group/collapsible-group.css';
|
|
129
68
|
}
|
|
130
69
|
|
|
131
70
|
.body {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
color: var(--ring-text-color);
|
|
135
|
-
|
|
136
|
-
font-size: var(--ring-font-size);
|
|
137
|
-
line-height: var(--ring-line-height);
|
|
71
|
+
composes: body from '../collapsible-group/collapsible-group.css';
|
|
138
72
|
}
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
expanded?: boolean | null | undefined;
|
|
10
|
-
onChange?: (expanded: boolean) => void;
|
|
11
|
-
disableAnimation?: boolean;
|
|
12
|
-
interactive?: boolean;
|
|
13
|
-
'data-test'?: string | null | undefined;
|
|
14
|
-
}
|
|
15
|
-
declare const CollapsibleGroup: React.ForwardRefExoticComponent<CollapsibleGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
16
|
-
export default CollapsibleGroup;
|
|
1
|
+
import { type CollapsibleGroupProps } from '../collapsible-group/collapsible-group';
|
|
2
|
+
/**
|
|
3
|
+
* @deprecated The `expand` module has been renamed to `collapsible-group`. This re-export will be removed in
|
|
4
|
+
* Ring UI 8.0. Use `CollapsibleGroup` from `@jetbrains/ring-ui/components/collapsible-group/collapsible-group` instead.
|
|
5
|
+
*/
|
|
6
|
+
declare const DeprecatedCollapsibleGroup: import("react").ForwardRefExoticComponent<CollapsibleGroupProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
7
|
+
export type { CollapsibleGroupProps };
|
|
8
|
+
export default DeprecatedCollapsibleGroup;
|
|
@@ -1,73 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
return (<span className={styles.header}>
|
|
13
|
-
<span className={styles.headerContent}>
|
|
14
|
-
<span className={styles.avatarGroup}>
|
|
15
|
-
{avatar}
|
|
16
|
-
<span className={styles.title}>{titleContent}</span>
|
|
17
|
-
</span>
|
|
18
|
-
{subtitle ? (<span className={styles.subtitleGroup}>
|
|
19
|
-
<Icon className={styles.subtitleChevron} glyph={chevronRightIcon} aria-hidden/>
|
|
20
|
-
<span className={styles.subtitle}>{subtitle}</span>
|
|
21
|
-
</span>) : null}
|
|
22
|
-
</span>
|
|
23
|
-
<span className={styles.toggle} aria-hidden>
|
|
24
|
-
<Icon className={styles.toggleIcon} glyph={collapsed ? chevronRightIcon : chevronDownIcon}/>
|
|
25
|
-
</span>
|
|
26
|
-
</span>);
|
|
27
|
-
}
|
|
28
|
-
function CollapsibleGroupHeader({ avatar, titleContent, subtitle, ...buttonProps }) {
|
|
29
|
-
const { setCollapsed, collapsed, id } = useContext(CollapseContext);
|
|
30
|
-
return (<button type='button' {...buttonProps} className={styles.headerButton} onClick={setCollapsed} aria-controls={`collapse-content-${id}`} aria-expanded={!collapsed}>
|
|
31
|
-
<CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
|
|
32
|
-
</button>);
|
|
33
|
-
}
|
|
34
|
-
function CollapsibleGroupHeaderStatic({ avatar, titleContent, subtitle }) {
|
|
35
|
-
return (<span className={styles.headerStatic}>
|
|
36
|
-
<CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
|
|
37
|
-
</span>);
|
|
38
|
-
}
|
|
39
|
-
const CollapsibleGroup = forwardRef(({ avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, 'data-test': dataTest, }, ref) => {
|
|
40
|
-
const [innerExpanded, setInnerExpanded] = useState(defaultExpanded);
|
|
41
|
-
const [hovered, setHovered] = useState(false);
|
|
42
|
-
const [focused, setFocused] = useState(false);
|
|
43
|
-
const isExpanded = expanded ?? innerExpanded;
|
|
44
|
-
const handleChange = (collapsed) => {
|
|
45
|
-
const nextExpanded = !collapsed;
|
|
46
|
-
if (expanded == null) {
|
|
47
|
-
setInnerExpanded(nextExpanded);
|
|
48
|
-
}
|
|
49
|
-
onChange(nextExpanded);
|
|
50
|
-
};
|
|
51
|
-
const onBlur = (event) => {
|
|
52
|
-
const nextTarget = event.relatedTarget;
|
|
53
|
-
if (nextTarget instanceof Node && event.currentTarget.contains(nextTarget)) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
setFocused(false);
|
|
57
|
-
};
|
|
58
|
-
const classes = classNames(styles.expand, className, {
|
|
59
|
-
[styles.hovered]: hovered,
|
|
60
|
-
[styles.expanded]: isExpanded,
|
|
61
|
-
[styles.focused]: focused,
|
|
62
|
-
});
|
|
63
|
-
return (<div ref={ref} className={classes} data-test={dataTest}>
|
|
64
|
-
<Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} className={styles.collapseRoot}>
|
|
65
|
-
{interactive ? (<CollapsibleGroupHeader avatar={avatar} titleContent={title} subtitle={subtitle} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} onFocus={() => setFocused(true)} onBlur={onBlur}/>) : (<CollapsibleGroupHeaderStatic avatar={avatar} titleContent={title} subtitle={subtitle}/>)}
|
|
66
|
-
<CollapseContent>
|
|
67
|
-
<div className={styles.body}>{children}</div>
|
|
68
|
-
</CollapseContent>
|
|
69
|
-
</Collapse>
|
|
70
|
-
</div>);
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
import deprecate from 'util-deprecate';
|
|
3
|
+
import CollapsibleGroup from '../collapsible-group/collapsible-group';
|
|
4
|
+
const warnDeprecation = deprecate(() => { }, '`CollapsibleGroup` from `@jetbrains/ring-ui/components/expand/collapsible-group` is deprecated and will be removed in Ring UI 8.0. Import it from `@jetbrains/ring-ui/components/collapsible-group/collapsible-group` instead.');
|
|
5
|
+
/**
|
|
6
|
+
* @deprecated The `expand` module has been renamed to `collapsible-group`. This re-export will be removed in
|
|
7
|
+
* Ring UI 8.0. Use `CollapsibleGroup` from `@jetbrains/ring-ui/components/collapsible-group/collapsible-group` instead.
|
|
8
|
+
*/
|
|
9
|
+
const DeprecatedCollapsibleGroup = forwardRef((props, ref) => {
|
|
10
|
+
warnDeprecation();
|
|
11
|
+
return <CollapsibleGroup ref={ref} {...props}/>;
|
|
71
12
|
});
|
|
72
|
-
|
|
73
|
-
export default
|
|
13
|
+
DeprecatedCollapsibleGroup.displayName = 'CollapsibleGroup';
|
|
14
|
+
export default DeprecatedCollapsibleGroup;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { useCallback, useLayoutEffect, useRef } from 'react';
|
|
2
|
-
|
|
2
|
+
import deprecate from 'util-deprecate';
|
|
3
|
+
const warnDeprecation = deprecate(() => { }, '`useEventCallback()` is deprecated and will be removed in Ring UI 8.0. Use `useEffectEvent()` instead.');
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated This hook will be removed in Ring UI 8.0. Use `useEffectEvent()` instead.
|
|
6
|
+
*/
|
|
3
7
|
export default function useEventCallback(fn) {
|
|
8
|
+
warnDeprecation();
|
|
4
9
|
const ref = useRef(null);
|
|
5
10
|
useLayoutEffect(() => {
|
|
6
11
|
ref.current = fn;
|
|
@@ -45,6 +45,8 @@ export interface BasePopupProps {
|
|
|
45
45
|
onMouseUp?: ((e: React.MouseEvent<HTMLElement>) => void) | undefined;
|
|
46
46
|
onMouseOver?: ((e: React.SyntheticEvent<HTMLElement>) => void) | undefined;
|
|
47
47
|
onMouseOut?: ((e: React.SyntheticEvent<HTMLElement>) => void) | undefined;
|
|
48
|
+
onMouseEnter?: ((e: React.MouseEvent<HTMLElement>) => void) | undefined;
|
|
49
|
+
onMouseLeave?: ((e: React.MouseEvent<HTMLElement>) => void) | undefined;
|
|
48
50
|
onContextMenu?: ((e: React.MouseEvent<HTMLElement>) => void) | undefined;
|
|
49
51
|
onDirectionChange?: ((direction: Directions) => void) | null | undefined;
|
|
50
52
|
onShow?: (() => void) | null | undefined;
|
|
@@ -282,7 +282,7 @@ export default class Popup extends PureComponent {
|
|
|
282
282
|
esc: this._onEscPress,
|
|
283
283
|
};
|
|
284
284
|
render() {
|
|
285
|
-
const { className, style, hidden, attached, keepMounted, client, onMouseDown, onMouseUp, onMouseOver, onMouseOut, onContextMenu, 'data-test': dataTest, largeBorderRadius, } = this.props;
|
|
285
|
+
const { className, style, hidden, attached, keepMounted, client, onMouseDown, onMouseUp, onMouseOver, onMouseOut, onMouseEnter, onMouseLeave, onContextMenu, 'data-test': dataTest, largeBorderRadius, } = this.props;
|
|
286
286
|
const showing = this.state.display === Display.SHOWING;
|
|
287
287
|
const direction = (this.state.direction || '').toLowerCase().replace(/[_]/g, '-');
|
|
288
288
|
return (<ThemeContext.Consumer>
|
|
@@ -305,7 +305,7 @@ export default class Popup extends PureComponent {
|
|
|
305
305
|
|
|
306
306
|
{client !== false &&
|
|
307
307
|
(keepMounted || !hidden) &&
|
|
308
|
-
createPortal(<PopupTarget id={this.uid} ref={this.containerRef} onMouseOver={onMouseOver} onFocus={onMouseOver} onMouseOut={onMouseOut} onBlur={onMouseOut} onContextMenu={onContextMenu}>
|
|
308
|
+
createPortal(<PopupTarget id={this.uid} ref={this.containerRef} onMouseOver={onMouseOver} onFocus={onMouseOver} onMouseOut={onMouseOut} onBlur={onMouseOut} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave} onContextMenu={onContextMenu}>
|
|
309
309
|
<div data-test={dataTests('ring-popup', dataTest)} data-test-shown={!hidden && !showing} data-test-direction={direction} ref={this.popupRef} className={classes} style={style} onMouseDown={onMouseDown} onMouseUp={onMouseUp}
|
|
310
310
|
// mouse handlers are used to track clicking on inner elements
|
|
311
311
|
role='presentation'>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetbrains/ring-ui",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.117",
|
|
4
4
|
"description": "JetBrains UI library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "JetBrains"
|
|
@@ -99,29 +99,29 @@
|
|
|
99
99
|
},
|
|
100
100
|
"readmeFilename": "README.md",
|
|
101
101
|
"devDependencies": {
|
|
102
|
-
"@babel/cli": "^7.
|
|
103
|
-
"@babel/eslint-parser": "^7.
|
|
102
|
+
"@babel/cli": "^7.29.7",
|
|
103
|
+
"@babel/eslint-parser": "^7.29.7",
|
|
104
104
|
"@csstools/css-parser-algorithms": "^4.0.0",
|
|
105
105
|
"@csstools/stylelint-no-at-nest-rule": "^5.0.0",
|
|
106
106
|
"@eslint/compat": "^2.1.0",
|
|
107
107
|
"@eslint/eslintrc": "^3.3.5",
|
|
108
108
|
"@eslint/js": "^10.0.1",
|
|
109
|
-
"@figma/code-connect": "^1.4.
|
|
109
|
+
"@figma/code-connect": "^1.4.7",
|
|
110
110
|
"@jetbrains/eslint-config": "^6.0.5",
|
|
111
111
|
"@jetbrains/logos": "3.0.0-canary.734b213.0",
|
|
112
112
|
"@jetbrains/rollup-css-plugin": "./packages/rollup-css-plugin",
|
|
113
113
|
"@jetbrains/stylelint-config": "^4.0.2",
|
|
114
114
|
"@jetbrains/typescript-plugin-css-modules": "^5.3.1",
|
|
115
|
-
"@primer/octicons": "^19.
|
|
116
|
-
"@rollup/plugin-babel": "^7.
|
|
115
|
+
"@primer/octicons": "^19.28.1",
|
|
116
|
+
"@rollup/plugin-babel": "^7.1.0",
|
|
117
117
|
"@rollup/plugin-json": "^6.1.0",
|
|
118
118
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
119
119
|
"@rollup/plugin-replace": "^6.0.3",
|
|
120
|
-
"@storybook/addon-a11y": "10.4.
|
|
121
|
-
"@storybook/addon-docs": "^10.4.
|
|
122
|
-
"@storybook/addon-themes": "^10.4.
|
|
120
|
+
"@storybook/addon-a11y": "10.4.2",
|
|
121
|
+
"@storybook/addon-docs": "^10.4.2",
|
|
122
|
+
"@storybook/addon-themes": "^10.4.2",
|
|
123
123
|
"@storybook/csf": "^0.1.13",
|
|
124
|
-
"@storybook/react-webpack5": "10.4.
|
|
124
|
+
"@storybook/react-webpack5": "10.4.2",
|
|
125
125
|
"@storybook/test-runner": "^0.24.4",
|
|
126
126
|
"@testing-library/dom": "^10.4.1",
|
|
127
127
|
"@testing-library/react": "^16.3.2",
|
|
@@ -129,14 +129,14 @@
|
|
|
129
129
|
"@types/chai-as-promised": "^8.0.2",
|
|
130
130
|
"@types/chai-dom": "1.11.3",
|
|
131
131
|
"@types/markdown-it": "^14.1.2",
|
|
132
|
-
"@types/react": "^19.2.
|
|
132
|
+
"@types/react": "^19.2.17",
|
|
133
133
|
"@types/react-dom": "^19.2.3",
|
|
134
134
|
"@types/webpack-env": "^1.18.8",
|
|
135
135
|
"@vitejs/plugin-react": "^6.0.2",
|
|
136
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
136
|
+
"@vitest/eslint-plugin": "^1.6.19",
|
|
137
137
|
"acorn": "^8.16.0",
|
|
138
138
|
"babel-plugin-require-context-hook": "^1.0.0",
|
|
139
|
-
"caniuse-lite": "^1.0.
|
|
139
|
+
"caniuse-lite": "^1.0.30001797",
|
|
140
140
|
"chai-as-promised": "^8.0.2",
|
|
141
141
|
"chai-dom": "^1.12.1",
|
|
142
142
|
"cheerio": "^1.2.0",
|
|
@@ -147,14 +147,14 @@
|
|
|
147
147
|
"eslint-config-prettier": "^10.1.8",
|
|
148
148
|
"eslint-formatter-jslint-xml": "^9.0.1",
|
|
149
149
|
"eslint-import-resolver-exports": "^1.0.0-beta.5",
|
|
150
|
-
"eslint-import-resolver-typescript": "^4.4.
|
|
150
|
+
"eslint-import-resolver-typescript": "^4.4.5",
|
|
151
151
|
"eslint-import-resolver-webpack": "^0.13.11",
|
|
152
152
|
"eslint-plugin-import": "^2.32.0",
|
|
153
153
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
154
|
-
"eslint-plugin-prettier": "^5.5.
|
|
154
|
+
"eslint-plugin-prettier": "^5.5.6",
|
|
155
155
|
"eslint-plugin-react": "^7.37.5",
|
|
156
156
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
157
|
-
"eslint-plugin-storybook": "^10.4.
|
|
157
|
+
"eslint-plugin-storybook": "^10.4.2",
|
|
158
158
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
159
159
|
"events": "^3.3.0",
|
|
160
160
|
"glob": "^13.0.6",
|
|
@@ -166,33 +166,33 @@
|
|
|
166
166
|
"jest": "~30.4.2",
|
|
167
167
|
"jest-environment-jsdom": "^30.4.1",
|
|
168
168
|
"jest-teamcity": "^1.12.0",
|
|
169
|
-
"lint-staged": "^17.0.
|
|
169
|
+
"lint-staged": "^17.0.6",
|
|
170
170
|
"markdown-it": "^14.2.0",
|
|
171
171
|
"merge-options": "^3.0.4",
|
|
172
172
|
"pinst": "^3.0.0",
|
|
173
173
|
"prettier": "^3.8.3",
|
|
174
174
|
"raw-loader": "^4.0.2",
|
|
175
|
-
"react": "^19.2.
|
|
176
|
-
"react-dom": "^19.2.
|
|
175
|
+
"react": "^19.2.7",
|
|
176
|
+
"react-dom": "^19.2.7",
|
|
177
177
|
"regenerator-runtime": "^0.14.1",
|
|
178
178
|
"rimraf": "^6.1.3",
|
|
179
|
-
"rollup": "^4.
|
|
179
|
+
"rollup": "^4.61.1",
|
|
180
180
|
"rollup-plugin-clear": "^2.0.7",
|
|
181
181
|
"storage-mock": "^2.1.0",
|
|
182
|
-
"storybook": "10.4.
|
|
183
|
-
"stylelint": "^17.
|
|
182
|
+
"storybook": "10.4.4",
|
|
183
|
+
"stylelint": "^17.13.0",
|
|
184
184
|
"stylelint-config-sass-guidelines": "^13.0.0",
|
|
185
185
|
"svg-inline-loader": "^0.8.2",
|
|
186
186
|
"teamcity-service-messages": "^0.1.14",
|
|
187
|
-
"terser-webpack-plugin": "^5.6.
|
|
187
|
+
"terser-webpack-plugin": "^5.6.1",
|
|
188
188
|
"typed-css-modules": "^0.9.1",
|
|
189
189
|
"typescript": "~6.0.3",
|
|
190
190
|
"typescript-eslint": "^8.60.0",
|
|
191
|
-
"vite": "^8.0.
|
|
192
|
-
"vitest": "^4.1.
|
|
191
|
+
"vite": "^8.0.16",
|
|
192
|
+
"vitest": "^4.1.8",
|
|
193
193
|
"vitest-teamcity-reporter": "^0.4.1",
|
|
194
|
-
"webpack": "^5.107.
|
|
195
|
-
"webpack-cli": "^7.0.
|
|
194
|
+
"webpack": "^5.107.2",
|
|
195
|
+
"webpack-cli": "^7.0.3",
|
|
196
196
|
"xmlappend": "^1.0.4"
|
|
197
197
|
},
|
|
198
198
|
"peerDependencies": {
|
|
@@ -215,8 +215,8 @@
|
|
|
215
215
|
}
|
|
216
216
|
},
|
|
217
217
|
"dependencies": {
|
|
218
|
-
"@babel/core": "^7.29.
|
|
219
|
-
"@babel/preset-typescript": "^7.
|
|
218
|
+
"@babel/core": "^7.29.7",
|
|
219
|
+
"@babel/preset-typescript": "^7.29.7",
|
|
220
220
|
"@jetbrains/babel-preset-jetbrains": "^2.4.0",
|
|
221
221
|
"@jetbrains/icons": "^5.22.0",
|
|
222
222
|
"@jetbrains/postcss-require-hover": "^0.2.0",
|
|
@@ -233,7 +233,7 @@
|
|
|
233
233
|
"combokeys": "^3.0.1",
|
|
234
234
|
"css-loader": "^7.1.4",
|
|
235
235
|
"csstype": "^3.2.1",
|
|
236
|
-
"date-fns": "^4.
|
|
236
|
+
"date-fns": "^4.4.0",
|
|
237
237
|
"dequal": "^2.0.3",
|
|
238
238
|
"element-resize-detector": "^1.2.4",
|
|
239
239
|
"fastdom": "^1.0.12",
|