@jetbrains/ring-ui 8.0.0-beta.1 → 8.0.0-beta.10
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/babel.config.js +1 -9
- package/components/alert/alert-actions.d.ts +4 -0
- package/components/alert/alert-actions.js +5 -0
- package/components/alert/alert-heading.d.ts +4 -0
- package/components/alert/alert-heading.js +6 -0
- package/components/alert/alert.css +63 -22
- package/components/alert/alert.d.ts +14 -1
- package/components/alert/alert.js +34 -19
- package/components/alert/container.css +1 -2
- package/components/alert-service/alert-service.d.ts +2 -1
- package/components/alert-service/alert-service.js +8 -4
- package/components/auth/auth-core.d.ts +5 -9
- package/components/auth/auth-core.js +56 -15
- package/components/auth-dialog-service/auth-dialog-service.js +2 -2
- package/components/avatar/avatar-info.js +0 -2
- package/components/avatar/avatar-size.d.ts +0 -4
- package/components/avatar/avatar-size.js +0 -4
- package/components/avatar/avatar.js +0 -6
- package/components/avatar/fallback-avatar.js +0 -28
- package/components/avatar-stack/avatar-stack.js +1 -1
- package/components/banner/banner.css +3 -3
- package/components/button/button.css +4 -4
- package/components/button/button.d.ts +0 -4
- package/components/button/button.js +2 -7
- package/components/button-group/button-group.css +5 -5
- package/components/checkbox/checkbox.d.ts +1 -1
- package/components/collapse/collapse-content.d.ts +7 -0
- package/components/collapse/collapse-content.js +44 -11
- package/components/collapse/collapse-context.d.ts +2 -0
- package/components/collapse/collapse-context.js +2 -0
- package/components/collapse/collapse-control.js +2 -2
- package/components/collapse/collapse.css +8 -2
- package/components/collapse/collapse.d.ts +9 -0
- package/components/collapse/collapse.js +12 -3
- package/components/{expand → collapsible-group}/collapsible-group.css +7 -1
- package/components/collapsible-group/collapsible-group.d.ts +33 -0
- package/components/{expand → collapsible-group}/collapsible-group.js +13 -21
- package/components/confirm-service/confirm-service.js +2 -2
- package/components/data-list/data-list.d.ts +1 -1
- package/components/data-list/data-list.mock.d.ts +1 -1
- package/components/data-list/item.d.ts +1 -1
- package/components/data-list/selection.d.ts +1 -1
- package/components/data-list/selection.js +1 -1
- package/components/date-picker/consts.d.ts +1 -0
- package/components/date-picker/date-input.js +6 -2
- package/components/date-picker/months.js +2 -2
- package/components/date-picker/use-scroll-behavior.js +5 -6
- package/components/date-picker/years.js +2 -2
- package/components/dialog/dialog.d.ts +2 -2
- package/components/dialog/dialog.js +2 -2
- package/components/dropdown-menu/dropdown-menu.d.ts +4 -4
- package/components/dropdown-menu/dropdown-menu.js +4 -4
- package/components/editable-heading/editable-heading.d.ts +1 -2
- package/components/editable-heading/editable-heading.js +18 -19
- package/components/global/compose-refs.d.ts +2 -1
- package/components/global/compose-refs.js +24 -8
- package/components/global/create-stateful-context.js +5 -5
- package/components/global/focus-with-temporary-tabindex.d.ts +11 -0
- package/components/global/focus-with-temporary-tabindex.js +21 -0
- package/components/global/intersection-observer-context.d.ts +31 -11
- package/components/global/intersection-observer-context.js +47 -28
- package/components/global/is-within-interactive-element.d.ts +6 -0
- package/components/global/is-within-interactive-element.js +26 -0
- package/components/global/is-within-navigable-element.d.ts +6 -0
- package/components/global/is-within-navigable-element.js +27 -0
- package/components/global/parse-css-duration.d.ts +5 -0
- package/components/global/parse-css-duration.js +13 -0
- package/components/global/rerender-hoc.d.ts +4 -2
- package/components/global/rerender-hoc.js +4 -4
- package/components/global/schedule-with-cleanup.d.ts +12 -0
- package/components/global/schedule-with-cleanup.js +34 -0
- package/components/{legacy-table/selection.d.ts → global/table-selection.d.ts} +14 -14
- package/components/{legacy-table/selection.js → global/table-selection.js} +2 -2
- package/components/global/theme.d.ts +4 -3
- package/components/global/theme.js +8 -8
- package/components/global/variables.css +18 -28
- package/components/global/variables.interface.d.ts +0 -4
- package/components/global/variables_dark.css +18 -25
- package/components/header/header.css +3 -3
- package/components/http/http.d.ts +2 -2
- package/components/http/http.js +2 -2
- package/components/i18n/i18n-context.js +1 -1
- package/components/i18n/i18n.d.ts +1 -0
- package/components/i18n/messages.json +1 -0
- package/components/icon/icon.css +0 -27
- package/components/icon/icon.d.ts +0 -1
- package/components/icon/icon.js +2 -4
- package/components/input/input.d.ts +1 -1
- package/components/island/adaptive-island-hoc.js +4 -4
- package/components/island/content.d.ts +7 -2
- package/components/island/content.js +5 -5
- package/components/legacy-table/cell.js +1 -1
- package/components/legacy-table/header-cell.js +1 -1
- package/components/legacy-table/header.js +1 -1
- package/components/legacy-table/multitable.d.ts +1 -1
- package/components/legacy-table/row.d.ts +1 -1
- package/components/legacy-table/row.js +1 -1
- package/components/legacy-table/selection-adapter.d.ts +3 -3
- package/components/legacy-table/selection-shortcuts-hoc.d.ts +5 -5
- package/components/legacy-table/simple-table.d.ts +2 -2
- package/components/legacy-table/simple-table.js +3 -3
- package/components/legacy-table/smart-table.d.ts +5 -5
- package/components/legacy-table/smart-table.js +3 -3
- package/components/legacy-table/table.js +1 -1
- package/components/list/consts.d.ts +0 -1
- package/components/list/consts.js +0 -1
- package/components/list/list.d.ts +0 -4
- package/components/login-dialog/service.js +2 -2
- package/components/popup/popup.d.ts +2 -0
- package/components/popup/popup.js +2 -2
- package/components/popup/popup.target.d.ts +3 -2
- package/components/popup/popup.target.js +4 -6
- package/components/query-assist/query-assist.d.ts +3 -1
- package/components/query-assist/query-assist.js +2 -2
- package/components/radio/radio-item.d.ts +3 -3
- package/components/radio/radio-item.js +3 -4
- package/components/radio/radio.d.ts +2 -2
- package/components/radio/radio.js +1 -1
- package/components/select/select-popup.d.ts +3 -2
- package/components/select/select-popup.js +3 -3
- package/components/select/select.d.ts +6 -2
- package/components/select/select.js +2 -4
- package/components/selection-toolbar/selection-toolbar.css +86 -0
- package/components/selection-toolbar/selection-toolbar.d.ts +11 -0
- package/components/selection-toolbar/selection-toolbar.js +23 -0
- package/components/slider/slider.js +4 -5
- package/components/tab-trap/tab-trap.d.ts +3 -3
- package/components/tab-trap/tab-trap.js +3 -5
- package/components/table/default-item-renderer.d.ts +41 -11
- package/components/table/default-item-renderer.js +60 -47
- package/components/table/internal/reorder-animation-context.d.ts +21 -0
- package/components/table/internal/reorder-animation-context.js +60 -0
- package/components/table/internal/reorder-handle.d.ts +9 -0
- package/components/table/internal/reorder-handle.js +334 -0
- package/components/table/internal/reorder-layout-context.d.ts +16 -0
- package/components/table/internal/reorder-layout-context.js +69 -0
- package/components/table/internal/table-header.d.ts +1 -0
- package/components/table/internal/table-header.js +143 -0
- package/components/table/internal/virtualization.d.ts +41 -0
- package/components/table/{table-virtualize.js → internal/virtualization.js} +82 -46
- package/components/table/item-virtualization.d.ts +37 -0
- package/components/table/item-virtualization.js +26 -0
- package/components/table/reorder-animation.d.ts +37 -0
- package/components/table/reorder-animation.js +11 -0
- package/components/table/reorder-item-layout.d.ts +32 -0
- package/components/table/reorder-item-layout.js +23 -0
- package/components/table/table-const.d.ts +8 -6
- package/components/table/table-const.js +7 -5
- package/components/table/table-primitives.d.ts +64 -0
- package/components/table/table-primitives.js +34 -0
- package/components/table/table-props.d.ts +304 -0
- package/components/table/table-props.js +1 -0
- package/components/table/table.css +179 -67
- package/components/table/table.d.ts +231 -224
- package/components/table/table.js +327 -2
- package/components/tag/tag.css +3 -3
- package/components/tags-input/tags-input.d.ts +3 -1
- package/components/tooltip/tooltip.d.ts +2 -1
- package/components/tooltip/tooltip.js +6 -5
- package/components/upload/upload.d.ts +4 -3
- package/components/upload/upload.js +3 -7
- package/components/user-agreement/service.js +2 -2
- package/components/user-card/smart-user-card-tooltip.d.ts +1 -1
- package/components/util-stories.d.ts +26 -0
- package/components/util-stories.js +61 -0
- package/package.json +44 -47
- package/components/content-layout/content-layout.css +0 -109
- package/components/content-layout/content-layout.d.ts +0 -20
- package/components/content-layout/content-layout.js +0 -40
- package/components/content-layout/sidebar.d.ts +0 -26
- package/components/content-layout/sidebar.js +0 -71
- package/components/date-picker/use-intersection-observer.d.ts +0 -6
- package/components/date-picker/use-intersection-observer.js +0 -48
- package/components/expand/collapsible-group.d.ts +0 -16
- package/components/global/composeRefs.d.ts +0 -6
- package/components/global/composeRefs.js +0 -7
- package/components/global/use-event-callback.d.ts +0 -1
- package/components/global/use-event-callback.js +0 -15
- package/components/grid/col.d.ts +0 -16
- package/components/grid/col.js +0 -35
- package/components/grid/grid.css +0 -920
- package/components/grid/grid.d.ts +0 -13
- package/components/grid/grid.js +0 -19
- package/components/grid/row.d.ts +0 -21
- package/components/grid/row.js +0 -41
- package/components/old-browsers-message/__mocks__/old-browsers-message.js +0 -1
- package/components/old-browsers-message/old-browsers-message-stop.d.ts +0 -1
- package/components/old-browsers-message/old-browsers-message-stop.js +0 -2
- package/components/old-browsers-message/old-browsers-message.css +0 -26
- package/components/old-browsers-message/old-browsers-message.d.ts +0 -5
- package/components/old-browsers-message/old-browsers-message.js +0 -86
- package/components/old-browsers-message/white-list.d.ts +0 -2
- package/components/old-browsers-message/white-list.js +0 -24
- package/components/table/table-base.d.ts +0 -24
- package/components/table/table-base.js +0 -79
- package/components/table/table-component.d.ts +0 -53
- package/components/table/table-component.js +0 -101
- package/components/table/table-virtualize.d.ts +0 -32
- /package/components/legacy-table/{table.css → legacy-table.css} +0 -0
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { PureComponent } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
-
import deprecate from 'util-deprecate';
|
|
4
3
|
import { encodeURL, isDataURI, parseQueryString } from '../global/url';
|
|
5
4
|
import { getPixelRatio } from '../global/dom';
|
|
6
|
-
import memoize from '../global/memoize';
|
|
7
5
|
import FallbackAvatar from './fallback-avatar';
|
|
8
6
|
import { Size } from './avatar-size';
|
|
9
7
|
import AvatarInfo from './avatar-info';
|
|
10
8
|
import styles from './avatar.css';
|
|
11
9
|
export { Size };
|
|
12
|
-
const warnSize = memoize((size) => deprecate(() => { }, `Avatar: Size${size} is deprecated and will be removed in 8.0. The supported sizes are: Size20, Size24, Size28, Size32, Size40.`));
|
|
13
10
|
export default class Avatar extends PureComponent {
|
|
14
11
|
static defaultProps = {
|
|
15
12
|
dpr: getPixelRatio(),
|
|
@@ -28,9 +25,6 @@ export default class Avatar extends PureComponent {
|
|
|
28
25
|
};
|
|
29
26
|
render() {
|
|
30
27
|
const { size, url, dpr, style, round, subavatar, subavatarSize, username, info, skipParams, ...restProps } = this.props;
|
|
31
|
-
if ([Size.Size18, Size.Size48].includes(size)) {
|
|
32
|
-
warnSize(size)();
|
|
33
|
-
}
|
|
34
28
|
const sizeString = `${size}px`;
|
|
35
29
|
const subavatarSizeString = `${subavatarSize}px`;
|
|
36
30
|
const styleObj = {
|
|
@@ -31,12 +31,6 @@ const SizesSquare = {
|
|
|
31
31
|
fontSize: '8px',
|
|
32
32
|
textAnchor: 'middle',
|
|
33
33
|
},
|
|
34
|
-
[Size.Size18]: {
|
|
35
|
-
radius: 4,
|
|
36
|
-
text: { x: 9, y: 13 },
|
|
37
|
-
fontSize: '11px',
|
|
38
|
-
textAnchor: 'middle',
|
|
39
|
-
},
|
|
40
34
|
[Size.Size20]: {
|
|
41
35
|
radius: 4,
|
|
42
36
|
text: { x: 2, y: 10 },
|
|
@@ -69,13 +63,6 @@ const SizesSquare = {
|
|
|
69
63
|
letterSpacing: 1,
|
|
70
64
|
underscore: { x: 5, y: 32, width: 15, height: 2.5 },
|
|
71
65
|
},
|
|
72
|
-
[Size.Size48]: {
|
|
73
|
-
radius: 4,
|
|
74
|
-
text: { x: 3, y: 21 },
|
|
75
|
-
fontSize: '19px',
|
|
76
|
-
letterSpacing: 1,
|
|
77
|
-
underscore: { x: 5, y: 32, width: 15, height: 2.5 },
|
|
78
|
-
},
|
|
79
66
|
[Size.Size56]: {
|
|
80
67
|
radius: 4,
|
|
81
68
|
text: { x: 4, y: 28 },
|
|
@@ -92,13 +79,6 @@ const SizesRound = {
|
|
|
92
79
|
textAnchor: 'middle',
|
|
93
80
|
dominantBaseline: 'middle',
|
|
94
81
|
},
|
|
95
|
-
[Size.Size18]: {
|
|
96
|
-
radius: 4,
|
|
97
|
-
fontSize: '11px',
|
|
98
|
-
text: { x: '50%', y: '54%' },
|
|
99
|
-
textAnchor: 'middle',
|
|
100
|
-
dominantBaseline: 'middle',
|
|
101
|
-
},
|
|
102
82
|
[Size.Size20]: {
|
|
103
83
|
radius: 4,
|
|
104
84
|
fontSize: '9px',
|
|
@@ -136,14 +116,6 @@ const SizesRound = {
|
|
|
136
116
|
textAnchor: 'middle',
|
|
137
117
|
dominantBaseline: 'middle',
|
|
138
118
|
},
|
|
139
|
-
[Size.Size48]: {
|
|
140
|
-
radius: 4,
|
|
141
|
-
fontSize: '19px',
|
|
142
|
-
letterSpacing: 1,
|
|
143
|
-
text: { x: '50%', y: '54%' },
|
|
144
|
-
textAnchor: 'middle',
|
|
145
|
-
dominantBaseline: 'middle',
|
|
146
|
-
},
|
|
147
119
|
[Size.Size56]: {
|
|
148
120
|
radius: 4,
|
|
149
121
|
fontSize: '26px',
|
|
@@ -6,7 +6,7 @@ import { fontSizes } from '../avatar/avatar-info';
|
|
|
6
6
|
import styles from './avatar-stack.css';
|
|
7
7
|
export default function AvatarStack({ children, className, size = Size.Size20, extraItems, dropdownMenuProps, ...restProps }) {
|
|
8
8
|
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
9
|
-
const sizeClass = size !== Size.Size16
|
|
9
|
+
const sizeClass = size !== Size.Size16 ? styles[`size${size}`] : undefined;
|
|
10
10
|
return (<div className={classNames(styles.avatarStack, className, sizeClass, {
|
|
11
11
|
[styles.hovered]: dropdownOpen,
|
|
12
12
|
})} {...restProps} style={{ height: size, ...restProps.style }}>
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
background-color: var(--ring-error-container-light-color);
|
|
33
33
|
|
|
34
34
|
.icon {
|
|
35
|
-
color: var(--ring-
|
|
35
|
+
color: var(--ring-icon-error-color);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
background-color: var(--ring-success-container-light-color);
|
|
42
42
|
|
|
43
43
|
.icon {
|
|
44
|
-
color: var(--ring-
|
|
44
|
+
color: var(--ring-icon-success-color);
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
background-color: var(--ring-warning-container-light-color);
|
|
51
51
|
|
|
52
52
|
.icon {
|
|
53
|
-
color: var(--ring-
|
|
53
|
+
color: var(--ring-icon-warning-color);
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -235,12 +235,12 @@
|
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
.primaryBlock {
|
|
238
|
-
--ring-button-default-background-color: var(--ring-
|
|
238
|
+
--ring-button-default-background-color: var(--ring-main-color);
|
|
239
239
|
--ring-button-hover-background-color: var(--ring-main-hover-color);
|
|
240
|
-
--ring-button-pressed-background-color: var(--ring-
|
|
241
|
-
--ring-button-active-background-color: var(--ring-
|
|
240
|
+
--ring-button-pressed-background-color: var(--ring-main-color);
|
|
241
|
+
--ring-button-active-background-color: var(--ring-main-color);
|
|
242
242
|
--ring-button-active-hover-background-color: var(--ring-main-hover-color);
|
|
243
|
-
--ring-button-active-pressed-background-color: var(--ring-
|
|
243
|
+
--ring-button-active-pressed-background-color: var(--ring-main-color);
|
|
244
244
|
--ring-button-disabled-background-color: var(--ring-border-hover-color);
|
|
245
245
|
--ring-button-pressed-border-color: var(--ring-button-primary-border-color);
|
|
246
246
|
--ring-button-active-border-color: var(--ring-button-primary-border-color);
|
|
@@ -15,10 +15,6 @@ export interface ButtonBaseProps {
|
|
|
15
15
|
secondary?: boolean | null | undefined;
|
|
16
16
|
ghost?: boolean | null | undefined;
|
|
17
17
|
short?: boolean | null | undefined;
|
|
18
|
-
/**
|
|
19
|
-
* @deprecated Use inline instead
|
|
20
|
-
*/
|
|
21
|
-
text?: boolean | null | undefined;
|
|
22
18
|
inline?: boolean | null | undefined;
|
|
23
19
|
dropdown?: boolean | null | undefined;
|
|
24
20
|
disabled?: boolean | undefined;
|
|
@@ -3,13 +3,11 @@ import * as React from 'react';
|
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import chevronDown from '@jetbrains/icons/chevron-down';
|
|
5
5
|
import chevron12pxDown from '@jetbrains/icons/chevron-12px-down';
|
|
6
|
-
import deprecate from 'util-deprecate';
|
|
7
6
|
import Icon, { Size } from '../icon/icon';
|
|
8
7
|
import ClickableLink from '../link/clickable-link';
|
|
9
8
|
import { ControlsHeightContext } from '../global/controls-height';
|
|
10
9
|
import { getButtonClasses } from './button.classes';
|
|
11
10
|
import styles from './button.css';
|
|
12
|
-
const warnText = deprecate(() => { }, 'Button: "text" prop is deprecated and will be removed in 8.0. Use inline instead.');
|
|
13
11
|
function removeLinkProps(props) {
|
|
14
12
|
const { download, href, hrefLang, media, ping, target, type, referrerPolicy, onConditionalClick, onPlainLeftClick, activeClassName, ...restProps } = props;
|
|
15
13
|
return restProps;
|
|
@@ -30,13 +28,10 @@ export class Button extends PureComponent {
|
|
|
30
28
|
render() {
|
|
31
29
|
const {
|
|
32
30
|
// Modifiers
|
|
33
|
-
active, danger, delayed, loader, primary, success, error, secondary, ghost, short,
|
|
31
|
+
active, danger, delayed, loader, primary, success, error, secondary, ghost, short, dropdown, height,
|
|
34
32
|
// Props
|
|
35
33
|
icon, iconRight, iconSize, iconClassName, iconRightClassName, iconSuppressSizeWarning, className, children, inline, disabled, ...props } = this.props;
|
|
36
|
-
const isInline = inline ??
|
|
37
|
-
if (text) {
|
|
38
|
-
warnText();
|
|
39
|
-
}
|
|
34
|
+
const isInline = inline ?? !!icon;
|
|
40
35
|
const classes = getButtonClasses({
|
|
41
36
|
...this.props,
|
|
42
37
|
inline: isInline,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@import '../global/variables.css';
|
|
2
2
|
|
|
3
|
-
@value button, active, flat from '../button/button.css';
|
|
3
|
+
@value button, active as buttonActive, flat from '../button/button.css';
|
|
4
4
|
|
|
5
5
|
:root,
|
|
6
6
|
:host {
|
|
@@ -133,14 +133,14 @@
|
|
|
133
133
|
0 0 0 1px var(--ring-border-hover-color);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
.buttonGroup .button.button.
|
|
136
|
+
.buttonGroup .button.button.buttonActive {
|
|
137
137
|
--ring-button-border-radius-left: var(--ring-border-radius);
|
|
138
138
|
--ring-button-border-radius-right: var(--ring-border-radius);
|
|
139
139
|
|
|
140
140
|
box-shadow: var(--ring-button-shadow) var(--ring-button-border-color);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
.buttonGroup .button:focus-visible.
|
|
143
|
+
.buttonGroup .button:focus-visible.buttonActive {
|
|
144
144
|
--ring-button-border-radius-left: var(--ring-border-radius);
|
|
145
145
|
--ring-button-border-radius-right: var(--ring-border-radius);
|
|
146
146
|
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
0 0 0 1px var(--ring-border-hover-color);
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
.buttonGroup .button.
|
|
152
|
+
.buttonGroup .button.buttonActive[disabled] {
|
|
153
153
|
box-shadow: var(--ring-button-shadow) var(--ring-border-hover-color);
|
|
154
154
|
}
|
|
155
155
|
/* stylelint-enable */
|
|
@@ -240,7 +240,7 @@
|
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
& .
|
|
243
|
+
& .buttonActive {
|
|
244
244
|
z-index: var(--ring-button-group-active-z-index);
|
|
245
245
|
|
|
246
246
|
&[disabled] {
|
|
@@ -24,6 +24,6 @@ export default class Checkbox extends PureComponent<CheckboxProps> {
|
|
|
24
24
|
componentDidUpdate(prevProps: CheckboxProps): void;
|
|
25
25
|
input?: HTMLInputElement | null;
|
|
26
26
|
inputRef: (el: HTMLInputElement | null) => void;
|
|
27
|
-
composedInputRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T | null) => void>;
|
|
27
|
+
composedInputRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T | null) => () => void>;
|
|
28
28
|
render(): import("react").JSX.Element;
|
|
29
29
|
}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import React, { type PropsWithChildren } from 'react';
|
|
2
2
|
interface Props {
|
|
3
|
+
/**
|
|
4
|
+
* Height of the always-visible preview of the collapsed content.
|
|
5
|
+
* The collapsed subtree is inert until expanded, matching `aria-expanded`.
|
|
6
|
+
* The preview is only a visual clip of that subtree, so it is inert too and
|
|
7
|
+
* assistive technology will not perceive it — if the preview carries essential
|
|
8
|
+
* information, expose an accessible summary outside the collapsed content.
|
|
9
|
+
*/
|
|
3
10
|
minHeight?: number;
|
|
4
11
|
className?: string;
|
|
5
12
|
'data-test'?: string | null | undefined;
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef,
|
|
1
|
+
import React, { useState, useEffect, useRef, use } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import dataTests from '../global/data-tests';
|
|
4
4
|
import { getRect } from '../global/dom';
|
|
5
|
+
import { parseCssDuration } from '../global/parse-css-duration';
|
|
5
6
|
import { toPx } from './utils';
|
|
6
7
|
import CollapseContext from './collapse-context';
|
|
7
8
|
import { COLLAPSE_CONTENT_TEST_ID, COLLAPSE_CONTENT_CONTAINER_TEST_ID } from './consts';
|
|
8
9
|
import styles from './collapse.css';
|
|
9
|
-
const DURATION_FACTOR = 0.5;
|
|
10
10
|
const DEFAULT_HEIGHT = 0;
|
|
11
11
|
const VISIBLE = 1;
|
|
12
12
|
const HIDDEN = 0;
|
|
13
|
+
// margin for the hide fallback timer, so it fires only if transitionend never did
|
|
14
|
+
const HIDE_FALLBACK_EXTRA_DELAY = 100;
|
|
15
|
+
const isFullyCollapsed = (collapsed, initialContentHeight) => collapsed && initialContentHeight <= DEFAULT_HEIGHT;
|
|
13
16
|
/**
|
|
14
17
|
* @name CollapseContent
|
|
15
18
|
*/
|
|
16
19
|
export const CollapseContent = ({ children, minHeight = DEFAULT_HEIGHT, 'data-test': dataTest, }) => {
|
|
17
|
-
const { collapsed, duration, id, disableAnimation } =
|
|
20
|
+
const { collapsed, duration, id, animate, disableAnimation, keepMounted } = use(CollapseContext);
|
|
18
21
|
const containerRef = useRef(null);
|
|
19
22
|
const contentRef = useRef(null);
|
|
20
23
|
const [initialContentHeight] = useState(minHeight);
|
|
@@ -23,20 +26,41 @@ export const CollapseContent = ({ children, minHeight = DEFAULT_HEIGHT, 'data-te
|
|
|
23
26
|
const height = toPx(nextHeight);
|
|
24
27
|
const [shouldHideContent, setShouldHideContent] = useState(collapsed && minHeight <= DEFAULT_HEIGHT);
|
|
25
28
|
useEffect(() => {
|
|
26
|
-
|
|
29
|
+
const container = containerRef.current;
|
|
30
|
+
function finalizeCollapse() {
|
|
27
31
|
if (initialContentHeight <= DEFAULT_HEIGHT) {
|
|
28
32
|
setShouldHideContent(collapsed);
|
|
29
33
|
}
|
|
30
34
|
}
|
|
31
|
-
|
|
35
|
+
function onTransitionEnd(event) {
|
|
36
|
+
// transitionend bubbles: only the container's own height transition finalizes the collapse
|
|
37
|
+
if (event.target === container && event.propertyName === 'height') {
|
|
38
|
+
finalizeCollapse();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
32
41
|
container?.addEventListener('transitionend', onTransitionEnd);
|
|
42
|
+
// fallback for suppressed or cancelled transitions (e.g. `transition: none` overrides),
|
|
43
|
+
// which emit no transitionend and would otherwise leave the content interactive forever.
|
|
44
|
+
// Armed once per collapse toggle from the --duration committed to the DOM — the value
|
|
45
|
+
// the running transition actually uses — so it can neither undercut a transition started
|
|
46
|
+
// from a stale height nor be restarted by content resizes or duration changes mid-collapse
|
|
47
|
+
const cssDuration = parseCssDuration(container?.style.getPropertyValue('--duration') || '');
|
|
48
|
+
const fallbackTimeout = window.setTimeout(finalizeCollapse, cssDuration + HIDE_FALLBACK_EXTRA_DELAY);
|
|
33
49
|
return () => {
|
|
34
50
|
container?.removeEventListener('transitionend', onTransitionEnd);
|
|
51
|
+
window.clearTimeout(fallbackTimeout);
|
|
35
52
|
};
|
|
36
53
|
}, [collapsed, initialContentHeight]);
|
|
54
|
+
// render-phase state adjustments (not effects): the React Compiler lint forbids
|
|
55
|
+
// setState-in-effect, and https://react.dev/learn/you-might-not-need-an-effect
|
|
56
|
+
// documents this pattern for resetting state when props change
|
|
37
57
|
if (!collapsed && shouldHideContent) {
|
|
38
58
|
setShouldHideContent(false);
|
|
39
59
|
}
|
|
60
|
+
// without a transition there is no transitionend to wait for, so hide immediately
|
|
61
|
+
if (disableAnimation && !shouldHideContent && isFullyCollapsed(collapsed, initialContentHeight)) {
|
|
62
|
+
setShouldHideContent(true);
|
|
63
|
+
}
|
|
40
64
|
useEffect(() => {
|
|
41
65
|
if (contentRef.current) {
|
|
42
66
|
const observer = new ResizeObserver(() => {
|
|
@@ -45,17 +69,26 @@ export const CollapseContent = ({ children, minHeight = DEFAULT_HEIGHT, 'data-te
|
|
|
45
69
|
observer.observe(contentRef.current);
|
|
46
70
|
}
|
|
47
71
|
}, []);
|
|
48
|
-
const calculatedDuration = duration + contentHeight * DURATION_FACTOR;
|
|
49
72
|
const style = {
|
|
50
|
-
'--duration': `${
|
|
73
|
+
'--duration': `${duration}ms`,
|
|
51
74
|
height,
|
|
52
75
|
opacity: collapsed && !minHeight ? HIDDEN : VISIBLE,
|
|
53
76
|
};
|
|
54
77
|
const fadeShouldBeVisible = Boolean(minHeight && collapsed);
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
78
|
+
const contentVisible = !shouldHideContent;
|
|
79
|
+
const contentHidden = Boolean(keepMounted) && !contentVisible;
|
|
80
|
+
// interaction is blocked as soon as the panel collapses (matching aria-expanded), while
|
|
81
|
+
// visibility waits for the animation to finish so the content stays painted meanwhile.
|
|
82
|
+
// This includes a minHeight preview: content clipped below it must not take focus,
|
|
83
|
+
// and inert cannot be applied any more granularly than to the whole subtree
|
|
84
|
+
const contentInert = collapsed;
|
|
85
|
+
return (<div ref={containerRef} id={`collapse-content-${id}`} data-test={dataTests(COLLAPSE_CONTENT_CONTAINER_TEST_ID)} className={classNames(styles.container, { [styles.transition]: animate && !disableAnimation })} style={style}>
|
|
86
|
+
<div ref={contentRef} data-test={dataTests(COLLAPSE_CONTENT_TEST_ID, dataTest)}
|
|
87
|
+
// visibility: hidden removes the fully collapsed content from the tab order and accessibility
|
|
88
|
+
// tree, but descendants can override it with visibility: visible — inert cannot be escaped.
|
|
89
|
+
// Both are rendered in JSX so server-rendered collapsed markup is protected before hydration.
|
|
90
|
+
style={contentHidden ? { visibility: 'hidden' } : undefined} inert={contentInert}>
|
|
91
|
+
{keepMounted || contentVisible ? children : null}
|
|
59
92
|
</div>
|
|
60
93
|
{fadeShouldBeVisible && <div className={styles.fade}/>}
|
|
61
94
|
</div>);
|
|
@@ -3,7 +3,9 @@ import { BASE_ANIMATION_DURATION } from './consts';
|
|
|
3
3
|
export const CollapseContext = createContext({
|
|
4
4
|
collapsed: true,
|
|
5
5
|
duration: BASE_ANIMATION_DURATION,
|
|
6
|
+
animate: false,
|
|
6
7
|
disableAnimation: false,
|
|
8
|
+
keepMounted: false,
|
|
7
9
|
setCollapsed: () => { },
|
|
8
10
|
id: '',
|
|
9
11
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { use, cloneElement } from 'react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import dataTests from '../global/data-tests';
|
|
4
4
|
import { CollapseContext } from './collapse-context';
|
|
@@ -7,7 +7,7 @@ import { COLLAPSE_CONTROL_TEST_ID } from './consts';
|
|
|
7
7
|
* @name CollapseControl
|
|
8
8
|
*/
|
|
9
9
|
export const CollapseControl = ({ children, 'data-test': dataTest }) => {
|
|
10
|
-
const { setCollapsed, collapsed, id } =
|
|
10
|
+
const { setCollapsed, collapsed, id } = use(CollapseContext);
|
|
11
11
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
12
|
const child = typeof children === 'function' ? children(collapsed) : children;
|
|
13
13
|
return (<p data-test={dataTests(COLLAPSE_CONTROL_TEST_ID, dataTest)}>
|
|
@@ -7,8 +7,14 @@
|
|
|
7
7
|
|
|
8
8
|
.transition {
|
|
9
9
|
transition:
|
|
10
|
-
height var(--duration)
|
|
11
|
-
opacity var(--duration)
|
|
10
|
+
height var(--duration) cubic-bezier(0.2, 0, 0, 1) 0s,
|
|
11
|
+
opacity var(--duration) cubic-bezier(0.2, 0, 0, 1) 0s;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@media (prefers-reduced-motion: reduce) {
|
|
15
|
+
.transition {
|
|
16
|
+
transition: none;
|
|
17
|
+
}
|
|
12
18
|
}
|
|
13
19
|
|
|
14
20
|
.summary {
|
|
@@ -4,6 +4,15 @@ interface Props {
|
|
|
4
4
|
onChange?: (collapsed: boolean) => void;
|
|
5
5
|
duration?: number;
|
|
6
6
|
disableAnimation?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Keep children mounted while collapsed (hidden via `visibility: hidden`
|
|
9
|
+
* and the `inert` attribute) instead of unmounting them, preserving their state.
|
|
10
|
+
* Note: hidden form controls still participate in form validation
|
|
11
|
+
* and submission — disable them while collapsed if needed.
|
|
12
|
+
* Content rendered through portals (e.g. Popup) escapes the hidden
|
|
13
|
+
* wrapper and is not hidden — close overlays on collapse.
|
|
14
|
+
*/
|
|
15
|
+
keepMounted?: boolean;
|
|
7
16
|
className?: string;
|
|
8
17
|
defaultCollapsed?: boolean;
|
|
9
18
|
collapsed?: boolean | null;
|
|
@@ -5,24 +5,33 @@ import { BASE_ANIMATION_DURATION } from './consts';
|
|
|
5
5
|
/**
|
|
6
6
|
* @name Collapse
|
|
7
7
|
*/
|
|
8
|
-
export const Collapse = ({ children, duration = BASE_ANIMATION_DURATION, disableAnimation = false, className = '', onChange = () => { }, defaultCollapsed = true, collapsed = null, }) => {
|
|
8
|
+
export const Collapse = ({ children, duration = BASE_ANIMATION_DURATION, disableAnimation = false, keepMounted = false, className = '', onChange = () => { }, defaultCollapsed = true, collapsed = null, }) => {
|
|
9
9
|
const [innerCollapsed, setInnerCollapsed] = useState(defaultCollapsed);
|
|
10
10
|
const id = useId();
|
|
11
11
|
const finalCollapsedValue = collapsed ?? innerCollapsed;
|
|
12
|
+
const [previousCollapsedValue, setPreviousCollapsedValue] = useState(finalCollapsedValue);
|
|
13
|
+
const [animate, setAnimate] = useState(false);
|
|
14
|
+
if (previousCollapsedValue !== finalCollapsedValue) {
|
|
15
|
+
setPreviousCollapsedValue(finalCollapsedValue);
|
|
16
|
+
setAnimate(true);
|
|
17
|
+
}
|
|
12
18
|
const setCollapsed = () => {
|
|
19
|
+
setAnimate(true);
|
|
13
20
|
setInnerCollapsed(!finalCollapsedValue);
|
|
14
21
|
onChange(!finalCollapsedValue);
|
|
15
22
|
};
|
|
16
23
|
return (<div className={className}>
|
|
17
|
-
<CollapseContext
|
|
24
|
+
<CollapseContext value={{
|
|
18
25
|
collapsed: finalCollapsedValue,
|
|
19
26
|
setCollapsed,
|
|
20
27
|
duration,
|
|
28
|
+
animate,
|
|
21
29
|
disableAnimation,
|
|
30
|
+
keepMounted,
|
|
22
31
|
id,
|
|
23
32
|
}}>
|
|
24
33
|
{children}
|
|
25
|
-
</CollapseContext
|
|
34
|
+
</CollapseContext>
|
|
26
35
|
</div>);
|
|
27
36
|
};
|
|
28
37
|
export default Collapse;
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
box-shadow: var(--ring-popup-shadow);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
.
|
|
28
|
+
.expand:has(.headerButton:focus-visible) {
|
|
29
29
|
box-shadow: 0 0 0 2px var(--ring-border-hover-color), var(--ring-popup-shadow);
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -37,6 +37,12 @@
|
|
|
37
37
|
height: 28px;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
.heading {
|
|
41
|
+
margin: 0;
|
|
42
|
+
|
|
43
|
+
font: inherit;
|
|
44
|
+
}
|
|
45
|
+
|
|
40
46
|
.headerButton {
|
|
41
47
|
display: block;
|
|
42
48
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface CollapsibleGroupProps {
|
|
3
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
4
|
+
avatar?: React.ReactNode;
|
|
5
|
+
title: React.ReactNode;
|
|
6
|
+
subtitle?: React.ReactNode;
|
|
7
|
+
children?: React.ReactNode;
|
|
8
|
+
className?: string | null | undefined;
|
|
9
|
+
defaultExpanded?: boolean;
|
|
10
|
+
expanded?: boolean | null | undefined;
|
|
11
|
+
onChange?: (expanded: boolean) => void;
|
|
12
|
+
disableAnimation?: boolean;
|
|
13
|
+
interactive?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Keep children mounted while collapsed (hidden via `visibility: hidden`
|
|
16
|
+
* and the `inert` attribute) instead of unmounting them, preserving their state.
|
|
17
|
+
* Note: hidden form controls still participate in form validation
|
|
18
|
+
* and submission — disable them while collapsed if needed.
|
|
19
|
+
* Content rendered through portals (e.g. Popup) escapes the hidden
|
|
20
|
+
* wrapper and is not hidden — close overlays on collapse.
|
|
21
|
+
*/
|
|
22
|
+
keepMounted?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Wraps the header in an <h2>–<h6> to keep the document outline.
|
|
25
|
+
*/
|
|
26
|
+
headingLevel?: 2 | 3 | 4 | 5 | 6;
|
|
27
|
+
'data-test'?: string | null | undefined;
|
|
28
|
+
}
|
|
29
|
+
declare const CollapsibleGroup: {
|
|
30
|
+
({ ref, avatar, title, subtitle, children, className, defaultExpanded, expanded, onChange, disableAnimation, interactive, keepMounted, headingLevel, "data-test": dataTest, }: CollapsibleGroupProps): React.JSX.Element;
|
|
31
|
+
displayName: string;
|
|
32
|
+
};
|
|
33
|
+
export default CollapsibleGroup;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { use, useState } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import chevronRightIcon from '@jetbrains/icons/chevron-12px-right';
|
|
4
4
|
import chevronDownIcon from '@jetbrains/icons/chevron-12px-down';
|
|
@@ -8,7 +8,7 @@ import CollapseContent from '../collapse/collapse-content';
|
|
|
8
8
|
import { CollapseContext } from '../collapse/collapse-context';
|
|
9
9
|
import styles from './collapsible-group.css';
|
|
10
10
|
function CollapsibleGroupHeaderContent({ avatar, titleContent, subtitle }) {
|
|
11
|
-
const { collapsed } =
|
|
11
|
+
const { collapsed } = use(CollapseContext);
|
|
12
12
|
return (<span className={styles.header}>
|
|
13
13
|
<span className={styles.headerContent}>
|
|
14
14
|
<span className={styles.avatarGroup}>
|
|
@@ -26,7 +26,7 @@ function CollapsibleGroupHeaderContent({ avatar, titleContent, subtitle }) {
|
|
|
26
26
|
</span>);
|
|
27
27
|
}
|
|
28
28
|
function CollapsibleGroupHeader({ avatar, titleContent, subtitle, ...buttonProps }) {
|
|
29
|
-
const { setCollapsed, collapsed, id } =
|
|
29
|
+
const { setCollapsed, collapsed, id } = use(CollapseContext);
|
|
30
30
|
return (<button type='button' {...buttonProps} className={styles.headerButton} onClick={setCollapsed} aria-controls={`collapse-content-${id}`} aria-expanded={!collapsed}>
|
|
31
31
|
<CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
|
|
32
32
|
</button>);
|
|
@@ -36,10 +36,9 @@ function CollapsibleGroupHeaderStatic({ avatar, titleContent, subtitle }) {
|
|
|
36
36
|
<CollapsibleGroupHeaderContent avatar={avatar} titleContent={titleContent} subtitle={subtitle}/>
|
|
37
37
|
</span>);
|
|
38
38
|
}
|
|
39
|
-
const CollapsibleGroup =
|
|
39
|
+
const CollapsibleGroup = ({ ref, avatar, title, subtitle, children, className, defaultExpanded = false, expanded = null, onChange = () => { }, disableAnimation = false, interactive = true, keepMounted = false, headingLevel, 'data-test': dataTest, }) => {
|
|
40
40
|
const [innerExpanded, setInnerExpanded] = useState(defaultExpanded);
|
|
41
41
|
const [hovered, setHovered] = useState(false);
|
|
42
|
-
const [focused, setFocused] = useState(false);
|
|
43
42
|
const isExpanded = expanded ?? innerExpanded;
|
|
44
43
|
const handleChange = (collapsed) => {
|
|
45
44
|
const nextExpanded = !collapsed;
|
|
@@ -48,26 +47,19 @@ const CollapsibleGroup = forwardRef(({ avatar, title, subtitle, children, classN
|
|
|
48
47
|
}
|
|
49
48
|
onChange(nextExpanded);
|
|
50
49
|
};
|
|
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
50
|
const classes = classNames(styles.expand, className, {
|
|
59
51
|
[styles.hovered]: hovered,
|
|
60
52
|
[styles.expanded]: isExpanded,
|
|
61
|
-
[styles.focused]: focused,
|
|
62
53
|
});
|
|
54
|
+
const header = interactive ? (<CollapsibleGroupHeader avatar={avatar} titleContent={title} subtitle={subtitle} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}/>) : (<CollapsibleGroupHeaderStatic avatar={avatar} titleContent={title} subtitle={subtitle}/>);
|
|
63
55
|
return (<div ref={ref} className={classes} data-test={dataTest}>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
56
|
+
<Collapse defaultCollapsed={!defaultExpanded} collapsed={expanded == null ? null : !expanded} onChange={handleChange} disableAnimation={disableAnimation} keepMounted={keepMounted} className={styles.collapseRoot}>
|
|
57
|
+
{headingLevel != null ? React.createElement(`h${headingLevel}`, { className: styles.heading }, header) : header}
|
|
58
|
+
<CollapseContent>
|
|
59
|
+
<div className={styles.body}>{children}</div>
|
|
60
|
+
</CollapseContent>
|
|
61
|
+
</Collapse>
|
|
62
|
+
</div>);
|
|
63
|
+
};
|
|
72
64
|
CollapsibleGroup.displayName = 'CollapsibleGroup';
|
|
73
65
|
export default CollapsibleGroup;
|
|
@@ -8,9 +8,9 @@ export const reactRoot = createRoot(containerElement);
|
|
|
8
8
|
*/
|
|
9
9
|
function renderConfirm(props) {
|
|
10
10
|
const { buttonsHeight = getGlobalControlsHeight(), ...restProps } = props;
|
|
11
|
-
reactRoot.render(<ControlsHeightContext
|
|
11
|
+
reactRoot.render(<ControlsHeightContext value={buttonsHeight}>
|
|
12
12
|
<Confirm {...restProps}/>
|
|
13
|
-
</ControlsHeightContext
|
|
13
|
+
</ControlsHeightContext>);
|
|
14
14
|
}
|
|
15
15
|
export default function confirm({ text, description, confirmLabel = 'OK', rejectLabel = 'Cancel', cancelIsDefault, onBeforeConfirm, buttonsHeight, }) {
|
|
16
16
|
return new Promise((resolve, reject) => {
|
|
@@ -5,7 +5,7 @@ import { Component } from 'react';
|
|
|
5
5
|
import { type FocusSensorOuterProps } from '../global/focus-sensor-hoc';
|
|
6
6
|
import { type SelectionShortcutsAddProps, type SelectionShortcutsOuterProps } from '../legacy-table/selection-shortcuts-hoc';
|
|
7
7
|
import { type DisableHoverAddProps } from '../legacy-table/disable-hover-hoc';
|
|
8
|
-
import { type SelectionItem } from '../
|
|
8
|
+
import { type SelectionItem } from '../global/table-selection';
|
|
9
9
|
import { type FormattedItem, moreLessButtonStates } from './item';
|
|
10
10
|
export interface DataListBaseProps<T extends SelectionItem> {
|
|
11
11
|
data: readonly T[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PureComponent, type ReactNode } from 'react';
|
|
2
|
-
import { type SelectionItem } from '../
|
|
2
|
+
import { type SelectionItem } from '../global/table-selection';
|
|
3
3
|
import type Selection from './selection';
|
|
4
4
|
export declare enum moreLessButtonStates {
|
|
5
5
|
UNUSED = 0,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import TableSelection, { type CloneWithConfig, type SelectionItem, type TableSelectionConfig } from '../
|
|
1
|
+
import TableSelection, { type CloneWithConfig, type SelectionItem, type TableSelectionConfig } from '../global/table-selection';
|
|
2
2
|
interface DataListSelectionConfig<T extends SelectionItem> extends TableSelectionConfig<T> {
|
|
3
3
|
partialSelected?: Set<T> | undefined;
|
|
4
4
|
}
|