@jetbrains/ring-ui 7.0.93 → 7.0.94
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/avatar-stack/avatar-stack.js +2 -1
- package/components/button/button.classes.js +1 -1
- package/components/data-list/data-list.js +0 -1
- package/components/date-picker/date-input.js +1 -1
- package/components/date-picker/date-picker.js +1 -1
- package/components/date-picker/day.js +5 -2
- package/components/dialog/dialog.js +0 -1
- package/components/editable-heading/editable-heading.js +4 -4
- package/components/header/profile.js +0 -3
- package/components/header/tray.js +1 -1
- package/components/icon/icon.js +1 -2
- package/components/input/input.d.ts +1 -1
- package/components/input/input.js +2 -2
- package/components/query-assist/query-assist.js +13 -6
- package/components/select/select.js +3 -2
- package/components/table/header.js +1 -3
- package/components/table/table.js +1 -5
- package/components/tabs/collapsible-more.js +1 -1
- package/components/tabs/collapsible-tab.js +2 -1
- package/components/tabs/dumb-tabs.d.ts +5 -1
- package/components/tabs/dumb-tabs.js +21 -11
- package/components/tabs/tab-link.js +10 -4
- package/components/tabs/tabs.utils.d.ts +3 -0
- package/components/tabs/tabs.utils.js +1 -0
- package/components/tags-input/tags-input.js +2 -2
- package/package.json +10 -3
- package/typings.d.ts +0 -5
|
@@ -6,7 +6,8 @@ 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
|
-
|
|
9
|
+
const sizeClass = size !== Size.Size16 && size !== Size.Size18 && size !== Size.Size48 ? styles[`size${size}`] : undefined;
|
|
10
|
+
return (<div className={classNames(styles.avatarStack, className, sizeClass, {
|
|
10
11
|
[styles.hovered]: dropdownOpen,
|
|
11
12
|
})} {...restProps} style={{ height: size, ...restProps.style }}>
|
|
12
13
|
{Children.map(children, (child, index) => (<div className={styles.item} style={{ '--ring-avatar-stack-index': index }}>
|
|
@@ -4,7 +4,7 @@ export function getButtonClasses({ className, active, disabled, loader, primary,
|
|
|
4
4
|
const iconOnly = (icon || iconRight) && !children;
|
|
5
5
|
const primaryBlock = primary && !inline;
|
|
6
6
|
const withNormalIcon = iconOnly && inline && !active && !danger && !primary && !disabled;
|
|
7
|
-
return classNames(styles.button, className, styles[`height${height}`], inline ? styles.inline : styles.block, {
|
|
7
|
+
return classNames(styles.button, className, height && styles[`height${height}`], inline ? styles.inline : styles.block, {
|
|
8
8
|
[styles.active]: active,
|
|
9
9
|
[styles.danger]: danger,
|
|
10
10
|
[styles.delayed]: delayed,
|
|
@@ -64,7 +64,6 @@ class DataList extends PureComponent {
|
|
|
64
64
|
const classes = classNames(className, {
|
|
65
65
|
[styles.dataList]: true,
|
|
66
66
|
[styles.disabledHover]: disabledHover,
|
|
67
|
-
[styles.multiSelection]: selection.getSelected().size > 0,
|
|
68
67
|
});
|
|
69
68
|
return (<div className={styles.dataListWrapper} data-test='ring-data-list' ref={innerRef}>
|
|
70
69
|
{focused && <Shortcuts map={shortcutsMap} scope={this.shortcutsScope}/>}
|
|
@@ -75,7 +75,7 @@ export default class DateInput extends React.PureComponent {
|
|
|
75
75
|
.replace('{{name}}', name);
|
|
76
76
|
}
|
|
77
77
|
})();
|
|
78
|
-
const classes = classNames(styles.filter, styles[`${name}Input`], divider && styles[`${name}InputWithDivider`], 'ring-js-shortcuts');
|
|
78
|
+
const classes = classNames(styles.filter, name !== 'time' && styles[`${name}Input`], divider && (name === 'from' || name === 'time') && styles[`${name}InputWithDivider`], 'ring-js-shortcuts');
|
|
79
79
|
return (<Input autoComplete='off' borderless height={ControlsHeight.L} data-name={name} inputRef={this.inputRef} className={classes} value={displayText} onChange={this.handleChange} onFocus={onActivate} onKeyDown={this.handleKeyDown} onClear={onClear} placeholder={placeholder}/>);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -151,7 +151,7 @@ export default class DatePicker extends PureComponent {
|
|
|
151
151
|
<Icon glyph={chevronDownIcon} className={styles.chevronDownIcon}/>
|
|
152
152
|
</div>);
|
|
153
153
|
const { className, popupClassName, clear, inline, dropdownProps, translations, ...datePopupProps } = this.props;
|
|
154
|
-
const classes = classNames(styles.datePicker, className, styles[`size${this.props.size}`], {
|
|
154
|
+
const classes = classNames(styles.datePicker, className, this.props.size && styles[`size${this.props.size}`], {
|
|
155
155
|
[styles.inline]: inline,
|
|
156
156
|
});
|
|
157
157
|
return (<Dropdown className={classes} disabled={this.props.disabled} data-test='ring-date-picker' anchor={inline ? (<Link data-test-ring-dropdown-anchor className={styles.anchor} disabled={this.props.disabled ?? false} pseudo>
|
|
@@ -43,7 +43,10 @@ export default class Day extends Component {
|
|
|
43
43
|
render() {
|
|
44
44
|
const { day, from, currentRange, activeRange, empty, locale } = this.props;
|
|
45
45
|
const reverse = activeRange && activeRange[1] === from;
|
|
46
|
-
|
|
46
|
+
// eslint-disable-next-line no-magic-numbers
|
|
47
|
+
const dayInWeek = (getDayNumInWeek(locale, getDay(day)) + 1);
|
|
48
|
+
// eslint-disable-next-line no-magic-numbers
|
|
49
|
+
const dayInWeekClass = dayInWeek !== 3 && dayInWeek !== 4 && styles[`Day${dayInWeek}`];
|
|
47
50
|
function makeSpreadRange(range) {
|
|
48
51
|
return range && [range[0], addDays(range[1], 1)];
|
|
49
52
|
}
|
|
@@ -52,7 +55,7 @@ export default class Day extends Component {
|
|
|
52
55
|
const activeSpreadRange = makeSpreadRange(activeRange);
|
|
53
56
|
return (
|
|
54
57
|
// TODO make keyboard navigation actually work
|
|
55
|
-
<button type='button' className={classNames(styles.day,
|
|
58
|
+
<button type='button' className={classNames(styles.day, dayInWeekClass, {
|
|
56
59
|
[styles.current]: ['date', 'from', 'to'].some(this.is),
|
|
57
60
|
[styles.active]: !disabled && this.is('activeDate'),
|
|
58
61
|
[styles.weekend]: [weekdays.SA, weekdays.SU].includes(getDay(day)),
|
|
@@ -127,7 +127,6 @@ export default class Dialog extends PureComponent {
|
|
|
127
127
|
[styles.closeButtonInside]: closeButtonInside,
|
|
128
128
|
})} iconClassName={classNames(styles.closeIcon, {
|
|
129
129
|
[styles.closeIconOutside]: !closeButtonInside,
|
|
130
|
-
[styles.closeIconInside]: closeButtonInside,
|
|
131
130
|
})} onClick={this.onCloseClick} title={closeButtonTitle} aria-label={closeButtonTitle || 'close dialog'}/>)}
|
|
132
131
|
</AdaptiveIsland>
|
|
133
132
|
</div>
|
|
@@ -44,8 +44,8 @@ export const EditableHeading = (props) => {
|
|
|
44
44
|
[styles.multiline]: multiline,
|
|
45
45
|
[styles.selectionMode]: isInSelectionMode,
|
|
46
46
|
});
|
|
47
|
-
const headingClasses = classNames(styles.heading, headingClassName, styles[`size${size}`]);
|
|
48
|
-
const inputClasses = classNames('ring-js-shortcuts', styles.input, styles.textarea, { [styles.textareaNotOverflow]: !isOverflow }, inputStyles[`size${size}`], styles[`level${level}`], inputClassName);
|
|
47
|
+
const headingClasses = classNames(styles.heading, headingClassName, size !== Size.AUTO && styles[`size${size}`]);
|
|
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
49
|
const stretch = (el) => {
|
|
50
50
|
if (!el || !el.style) {
|
|
51
51
|
return;
|
|
@@ -114,7 +114,7 @@ export const EditableHeading = (props) => {
|
|
|
114
114
|
{!disabled && isEditing ? (<>
|
|
115
115
|
<Shortcuts map={shortcutsMap} scope={shortcutsScope} disabled={isShortcutsDisabled}/>
|
|
116
116
|
|
|
117
|
-
{!multiline ? (<input className={inputClasses} value={children} autoFocus={autoFocus} data-test={dataTest} disabled={isSaving} onChange={onChange} {...restProps} onFocus={onInputFocus} onBlur={onInputBlur}/>) : (<div className={classNames(styles.textareaWrapper, inputStyles[`size${size}`])}>
|
|
117
|
+
{!multiline ? (<input className={inputClasses} value={children} autoFocus={autoFocus} data-test={dataTest} disabled={isSaving} onChange={onChange} {...restProps} onFocus={onInputFocus} onBlur={onInputBlur}/>) : (<div className={classNames(styles.textareaWrapper, size !== Size.AUTO && inputStyles[`size${size}`])}>
|
|
118
118
|
<textarea ref={textAreaRef} className={inputClasses} value={children} autoFocus={autoFocus} data-test={dataTest} disabled={isSaving} onChange={onInputChange} {...restProps} onFocus={onInputFocus} onBlur={onInputBlur} onScroll={onInputScroll} style={{ maxHeight: maxInputRows ? `${maxInputRows}lh` : '' }}/>
|
|
119
119
|
{!isScrolledToBottom && <div className={styles.textareaFade}/>}
|
|
120
120
|
</div>)}
|
|
@@ -137,7 +137,7 @@ export const EditableHeading = (props) => {
|
|
|
137
137
|
</>)}
|
|
138
138
|
</div>
|
|
139
139
|
|
|
140
|
-
{isEditing && error && <div className={classNames(styles.errorText, inputStyles[`size${size}`])}>{error}</div>}
|
|
140
|
+
{isEditing && error && (<div className={classNames(styles.errorText, size !== Size.AUTO && inputStyles[`size${size}`])}>{error}</div>)}
|
|
141
141
|
</>);
|
|
142
142
|
};
|
|
143
143
|
export default React.memo(EditableHeading);
|
|
@@ -48,13 +48,11 @@ export default class Profile extends PureComponent {
|
|
|
48
48
|
showApplyChangedUser && {
|
|
49
49
|
rgItemType,
|
|
50
50
|
label: translations?.applyChangedUser ?? translate('applyChangedUser'),
|
|
51
|
-
className: styles.profileMenuItem,
|
|
52
51
|
onClick: onRevertPostponement,
|
|
53
52
|
},
|
|
54
53
|
showLogIn && {
|
|
55
54
|
rgItemType,
|
|
56
55
|
label: translations?.login ?? translate('login'),
|
|
57
|
-
className: styles.profileMenuItem,
|
|
58
56
|
onClick: onRevertPostponement,
|
|
59
57
|
},
|
|
60
58
|
{
|
|
@@ -67,7 +65,6 @@ export default class Profile extends PureComponent {
|
|
|
67
65
|
showSwitchUser && {
|
|
68
66
|
rgItemType,
|
|
69
67
|
label: translations?.switchUser ?? translate('switchUser'),
|
|
70
|
-
className: styles.profileMenuItem,
|
|
71
68
|
onClick: onSwitchUser,
|
|
72
69
|
},
|
|
73
70
|
showLogOut && {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Children, Component } from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import styles from './header.css';
|
|
4
|
-
const wrapChild = (child) => child && <div
|
|
4
|
+
const wrapChild = (child) => child && <div>{child}</div>;
|
|
5
5
|
export default class Tray extends Component {
|
|
6
6
|
render() {
|
|
7
7
|
const { children, className, ...restProps } = this.props;
|
package/components/icon/icon.js
CHANGED
|
@@ -47,8 +47,7 @@ export default class Icon extends PureComponent {
|
|
|
47
47
|
if (!Glyph) {
|
|
48
48
|
return null;
|
|
49
49
|
}
|
|
50
|
-
const classes = classNames(styles.icon, {
|
|
51
|
-
[styles[color]]: !!color,
|
|
50
|
+
const classes = classNames(styles.icon, color && styles[color], {
|
|
52
51
|
[styles.loading]: loading,
|
|
53
52
|
}, className);
|
|
54
53
|
return (<span data-test='ring-icon' {...restProps} className={classes}>
|
|
@@ -17,7 +17,7 @@ function noop() { }
|
|
|
17
17
|
*/
|
|
18
18
|
var Size;
|
|
19
19
|
(function (Size) {
|
|
20
|
-
Size["AUTO"] = "
|
|
20
|
+
Size["AUTO"] = "AUTO";
|
|
21
21
|
Size["S"] = "S";
|
|
22
22
|
Size["M"] = "M";
|
|
23
23
|
Size["L"] = "L";
|
|
@@ -100,7 +100,7 @@ export class Input extends PureComponent {
|
|
|
100
100
|
label, labelType, error, help, className, inputClassName, children, value, onClear, disabled, inputRef, onChange, enableShortcuts, id, placeholder, icon, translations, height = typeof this.context === 'function' ? this.context() : this.context, beforeInput, afterInput, autogrow, ...restProps } = this.props;
|
|
101
101
|
const { empty } = this.state;
|
|
102
102
|
const clearable = !!onClear;
|
|
103
|
-
const classes = classNames(className, styles.outerContainer,
|
|
103
|
+
const classes = classNames(className, styles.outerContainer, size && size !== Size.AUTO && styles[`size${size}`], styles[`height${height}`], {
|
|
104
104
|
'ring-js-shortcuts': enableShortcuts === true,
|
|
105
105
|
[styles.error]: error !== null && error !== undefined,
|
|
106
106
|
[styles.empty]: empty,
|
|
@@ -691,16 +691,23 @@ export default class QueryAssist extends Component {
|
|
|
691
691
|
const renderLoader = this.props.loader !== false && this.state.loading;
|
|
692
692
|
const renderGlass = glass && !renderLoader;
|
|
693
693
|
const actions = this.renderActions();
|
|
694
|
-
|
|
694
|
+
let sizeClass;
|
|
695
|
+
if (huge) {
|
|
696
|
+
sizeClass = inputStyles[`size${Size.FULL}`];
|
|
697
|
+
}
|
|
698
|
+
else if (size !== Size.AUTO) {
|
|
699
|
+
sizeClass = inputStyles[`size${size}`];
|
|
700
|
+
}
|
|
701
|
+
else {
|
|
702
|
+
sizeClass = undefined;
|
|
703
|
+
}
|
|
704
|
+
const containerClasses = classNames(className, sizeClass, {
|
|
695
705
|
[styles.queryAssist]: true,
|
|
696
|
-
[styles.withIcon]: (renderGlass && !huge) || renderLoader,
|
|
697
706
|
[styles.huge]: huge,
|
|
698
707
|
[styles.queryAssistDisabled]: this.props.disabled,
|
|
699
708
|
});
|
|
700
709
|
const inputClasses = classNames(this.props.inputClassName, {
|
|
701
710
|
[`${styles.input} ring-js-shortcuts`]: true,
|
|
702
|
-
[styles.inputGap]: actions.length || (this.isRenderingGlassOrLoader() && !glass),
|
|
703
|
-
[styles.inputGap2]: actions.length === 2, // TODO: replace with flex-box layout
|
|
704
711
|
[styles.inputRevertOrder]: !glass || huge,
|
|
705
712
|
});
|
|
706
713
|
const placeholderStyles = classNames({
|
|
@@ -715,7 +722,7 @@ export default class QueryAssist extends Component {
|
|
|
715
722
|
|
|
716
723
|
{renderGlass && !huge && (<Icon glyph={searchIcon} className={classNames(styles.icon, this.props.searchButtonClassName)} title={translations?.searchTitle ?? translate('searchTitle')} ref={this.glassRef} data-test='query-assist-search-icon'/>)}
|
|
717
724
|
|
|
718
|
-
{renderLoader && (<div className={classNames(styles.icon,
|
|
725
|
+
{renderLoader && (<div className={classNames(styles.icon, {
|
|
719
726
|
[styles.loaderOnTheRight]: !glass && !huge,
|
|
720
727
|
[styles.loaderActive]: renderLoader,
|
|
721
728
|
})} ref={this.loaderRef}>
|
|
@@ -739,7 +746,7 @@ export default class QueryAssist extends Component {
|
|
|
739
746
|
<PopupMenu hidden={!this.state.showPopup} onCloseAttempt={this.closePopup} ref={this.popupRef} anchorElement={this.node} keepMounted attached className={this.props.popupClassName} directions={[PopupMenu.PopupProps.Directions.BOTTOM_RIGHT, PopupMenu.PopupProps.Directions.BOTTOM_LEFT]} data={useCustomItemRender ? this.state.suggestions : this.renderSuggestions()} data-test='ring-query-assist-popup' hint={this.props.hint} shortcutsMap={this.listShortcutsMap} hintOnSelection={this.props.hintOnSelection} left={this.getPopupOffset(this.state.suggestions)} maxHeight={PopupMenu.PopupProps.MaxHeight.SCREEN} onMouseDown={this.trackPopupMouseState} onMouseUp={this.trackPopupMouseState} onSelect={item => this.handleComplete(item)} {...this.props.menuProps}/>
|
|
740
747
|
|
|
741
748
|
{glass && huge && (<div className={styles.rightSearchButton} data-test='query-assist-search-button'>
|
|
742
|
-
<Icon glyph={searchIcon} className={classNames(
|
|
749
|
+
<Icon glyph={searchIcon} className={classNames(this.props.searchButtonClassName)} title={translations?.searchTitle ?? translate('searchTitle')} onClick={this.handleApply} ref={this.glassRef} data-test='query-assist-search-icon'/>
|
|
743
750
|
</div>)}
|
|
744
751
|
</div>)}
|
|
745
752
|
</I18nContext.Consumer>
|
|
@@ -801,7 +801,8 @@ export default class Select extends Component {
|
|
|
801
801
|
const dataTest = this.props['data-test'];
|
|
802
802
|
const { selectedLabel } = this.props;
|
|
803
803
|
const { shortcutsEnabled } = this.state;
|
|
804
|
-
const
|
|
804
|
+
const height = this.getHeight();
|
|
805
|
+
const classes = classNames(styles.select, 'ring-js-shortcuts', this.props.className, height !== ControlsHeight.M && styles[`height${height}`], {
|
|
805
806
|
[styles[`size${this.props.size}`]]: this.props.type !== Type.INLINE,
|
|
806
807
|
[styles.disabled]: this.props.disabled,
|
|
807
808
|
});
|
|
@@ -836,7 +837,7 @@ export default class Select extends Component {
|
|
|
836
837
|
: undefined} icon={this.props.filterIcon} afterInput={iconsNode}/>
|
|
837
838
|
{this._renderPopup()}
|
|
838
839
|
</div>
|
|
839
|
-
{this.props.error && (<div className={classNames(inputStyles.errorText, inputStyles[`size${this.props.size}`])}>
|
|
840
|
+
{this.props.error && (<div className={classNames(inputStyles.errorText, this.props.size !== Size.AUTO && inputStyles[`size${this.props.size}`])}>
|
|
840
841
|
{this.props.error}
|
|
841
842
|
</div>)}
|
|
842
843
|
</>);
|
|
@@ -47,9 +47,7 @@ export default class Header extends PureComponent {
|
|
|
47
47
|
</th>
|
|
48
48
|
</tr>)}
|
|
49
49
|
|
|
50
|
-
<tr
|
|
51
|
-
{regularCells}
|
|
52
|
-
</tr>
|
|
50
|
+
<tr data-test='ring-table-header-row'>{regularCells}</tr>
|
|
53
51
|
</thead>);
|
|
54
52
|
}
|
|
55
53
|
}
|
|
@@ -135,14 +135,10 @@ export class Table extends PureComponent {
|
|
|
135
135
|
headerProps.checked = selectedSize > 0 && selectedSize === allSelectedSize;
|
|
136
136
|
headerProps.onCheckboxChange = this.onCheckboxChange;
|
|
137
137
|
headerProps.checkboxDisabled = this.props.data.length === 0;
|
|
138
|
-
const wrapperClasses = classNames(
|
|
139
|
-
[style.tableWrapper]: true,
|
|
140
|
-
[style.loading]: loading,
|
|
141
|
-
}, this.props.wrapperClassName);
|
|
138
|
+
const wrapperClasses = classNames(style.tableWrapper, this.props.wrapperClassName);
|
|
142
139
|
const classes = classNames(this.props.className, {
|
|
143
140
|
[style.table]: true,
|
|
144
141
|
[style.wideFirstColumn]: this.props.wideFirstColumn,
|
|
145
|
-
[style.multiSelection]: selection.getSelected().size > 0,
|
|
146
142
|
[style.userSelectNone]: this.state.userSelectNone,
|
|
147
143
|
[style.disabledHover]: this.props.disabledHover,
|
|
148
144
|
});
|
|
@@ -61,7 +61,7 @@ export const MoreButton = memo(({ items, selected, onSelect, moreClassName, more
|
|
|
61
61
|
</div>);
|
|
62
62
|
});
|
|
63
63
|
MoreButton.displayName = 'MoreButton';
|
|
64
|
-
export const FakeMoreButton = memo(({ moreClassName, moreActiveClassName, hasActiveChildren }) => (<div className={
|
|
64
|
+
export const FakeMoreButton = memo(({ moreClassName, moreActiveClassName, hasActiveChildren }) => (<div className={styles.title}>
|
|
65
65
|
<AnchorLink moreClassName={moreClassName} moreActiveClassName={moreActiveClassName} hasActiveChildren={hasActiveChildren} tabIndex={-1} disabled/>
|
|
66
66
|
</div>));
|
|
67
67
|
FakeMoreButton.displayName = 'FakeMoreButton';
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import TabLink from './tab-link';
|
|
4
4
|
import { CustomItem } from './custom-item';
|
|
5
|
+
import { getTabId } from './tabs.utils';
|
|
5
6
|
import styles from './tabs.css';
|
|
6
7
|
const TabTitle = React.memo(function TabTitle({ selected, child, handleSelect, collapsed = false, tabIndex, }) {
|
|
7
8
|
if (child === null || typeof child !== 'object' || child.type === CustomItem) {
|
|
@@ -15,7 +16,7 @@ const TabTitle = React.memo(function TabTitle({ selected, child, handleSelect, c
|
|
|
15
16
|
return (<TabLink title={title} isSelected={selected} active href={href} className={titleClasses} disabled={disabled} onPlainLeftClick={handleSelect} tabIndex={tabIndex} collapsed={collapsed} {...titleProps}/>);
|
|
16
17
|
});
|
|
17
18
|
const getTabTitles = ({ items, selected = '0', collapsed, onSelect = () => undefined, ...props }) => items.map((tab, index) => {
|
|
18
|
-
const key = tab
|
|
19
|
+
const key = getTabId(tab, index);
|
|
19
20
|
const isSelected = selected === key;
|
|
20
21
|
return (<TabTitle key={key} handleSelect={onSelect(key)} selected={isSelected} child={tab} collapsed={collapsed} {...props}/>);
|
|
21
22
|
});
|
|
@@ -16,7 +16,11 @@ export interface TabsProps extends Omit<CollapsibleTabsProps, 'onSelect' | 'chil
|
|
|
16
16
|
}
|
|
17
17
|
declare class Tabs extends PureComponent<TabsProps> {
|
|
18
18
|
handleSelect: (arg: string) => () => void | undefined;
|
|
19
|
-
|
|
19
|
+
getSelectedItem(): {
|
|
20
|
+
selectedItem: ReactElement<TabProps, string | React.JSXElementConstructor<any>>;
|
|
21
|
+
selectedKey: string;
|
|
22
|
+
};
|
|
23
|
+
getTabTitle(selectedKey: string, child: ReactElement<TabProps>, i: number): React.JSX.Element;
|
|
20
24
|
render(): React.JSX.Element;
|
|
21
25
|
}
|
|
22
26
|
export type TabsAttrs = React.JSX.LibraryManagedAttributes<typeof Tabs, TabsProps>;
|
|
@@ -6,34 +6,44 @@ import dataTests from '../global/data-tests';
|
|
|
6
6
|
import TabLink from './tab-link';
|
|
7
7
|
import CollapsibleTabs from './collapsible-tabs';
|
|
8
8
|
import { CustomItem } from './custom-item';
|
|
9
|
+
import { getTabId } from './tabs.utils';
|
|
9
10
|
import styles from './tabs.css';
|
|
10
11
|
export { CustomItem };
|
|
11
12
|
class Tabs extends PureComponent {
|
|
12
13
|
handleSelect = memoize((key) => () => this.props.onSelect?.(key));
|
|
13
|
-
|
|
14
|
+
getSelectedItem() {
|
|
15
|
+
const { selected, children } = this.props;
|
|
16
|
+
const childrenArray = React.Children.toArray(children).filter(Boolean);
|
|
17
|
+
const selectedIndex = childrenArray.findIndex((tab, i) => getTabId(tab, i) === selected);
|
|
18
|
+
const actualSelectedIndex = selectedIndex === -1 ? 0 : selectedIndex;
|
|
19
|
+
const selectedItem = childrenArray[actualSelectedIndex];
|
|
20
|
+
return { selectedItem, selectedKey: getTabId(selectedItem, actualSelectedIndex) };
|
|
21
|
+
}
|
|
22
|
+
getTabTitle(selectedKey, child, i) {
|
|
14
23
|
if (child === null || typeof child !== 'object' || child.type === CustomItem) {
|
|
15
24
|
return child;
|
|
16
25
|
}
|
|
17
|
-
const {
|
|
18
|
-
const { title, titleProps,
|
|
19
|
-
const key =
|
|
20
|
-
const isSelected = key ===
|
|
26
|
+
const { onSelect } = this.props;
|
|
27
|
+
const { title, titleProps, disabled, href, className, activeClassName } = child.props;
|
|
28
|
+
const key = getTabId(child, i);
|
|
29
|
+
const isSelected = key === selectedKey;
|
|
21
30
|
const titleClasses = classNames(styles.title, className, isSelected && activeClassName, {
|
|
22
31
|
[styles.selected]: isSelected,
|
|
23
32
|
});
|
|
24
33
|
return (<TabLink title={title} isSelected={isSelected} key={key} href={href} className={titleClasses} disabled={disabled} onPlainLeftClick={onSelect ? this.handleSelect(key) : undefined} {...titleProps}/>);
|
|
25
|
-
}
|
|
34
|
+
}
|
|
26
35
|
render() {
|
|
27
36
|
const { className, tabContainerClassName, children, selected, autoCollapse, 'data-test': dataTest, onSelect, ...restProps } = this.props;
|
|
28
37
|
const classes = classNames(styles.tabs, className);
|
|
29
38
|
const childrenArray = React.Children.toArray(children).filter(Boolean);
|
|
39
|
+
const { selectedItem, selectedKey } = this.getSelectedItem();
|
|
30
40
|
return (<div className={classes} data-test={dataTests('ring-dumb-tabs', dataTest)}>
|
|
31
|
-
{autoCollapse === true ? (<CollapsibleTabs {...restProps} onSelect={onSelect ? this.handleSelect : undefined} selected={
|
|
41
|
+
{autoCollapse === true ? (<CollapsibleTabs {...restProps} onSelect={onSelect ? this.handleSelect : undefined} selected={selectedKey}>
|
|
32
42
|
{childrenArray}
|
|
33
|
-
</CollapsibleTabs>) : (<div className={styles.titles}>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
</div>
|
|
43
|
+
</CollapsibleTabs>) : (<div className={styles.titles}>
|
|
44
|
+
{childrenArray.map((tab, index) => this.getTabTitle(selectedKey, tab, index))}
|
|
45
|
+
</div>)}
|
|
46
|
+
<div className={classNames(tabContainerClassName)}>{selectedItem}</div>
|
|
37
47
|
</div>);
|
|
38
48
|
}
|
|
39
49
|
}
|
|
@@ -3,13 +3,19 @@ import Link from '../link/link';
|
|
|
3
3
|
import styles from './tabs.css';
|
|
4
4
|
function TabLink({ isSelected, title, collapsed, ...restProps }) {
|
|
5
5
|
const renderedTitle = typeof title === 'function' ? title(isSelected, collapsed) : title;
|
|
6
|
-
return (<Link {...restProps}>
|
|
6
|
+
return (<Link {...restProps} data-test-selected={isSelected}>
|
|
7
7
|
<div className={styles.container}>
|
|
8
8
|
<span className={styles.visible}>{renderedTitle}</span>
|
|
9
9
|
{/* hack for preserving constant tab width*/}
|
|
10
|
-
<span className={styles.hidden}>
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
<span aria-hidden className={styles.hidden}>
|
|
11
|
+
{renderedTitle}
|
|
12
|
+
</span>
|
|
13
|
+
<span aria-hidden className={styles.hiddenBold}>
|
|
14
|
+
{renderedTitle}
|
|
15
|
+
</span>
|
|
16
|
+
<span aria-hidden className={styles.hiddenRegular}>
|
|
17
|
+
{renderedTitle}
|
|
18
|
+
</span>
|
|
13
19
|
</div>
|
|
14
20
|
</Link>);
|
|
15
21
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const getTabId = (tab, index) => tab?.props.id || String(index);
|
|
@@ -229,7 +229,7 @@ export default class TagsInput extends PureComponent {
|
|
|
229
229
|
render() {
|
|
230
230
|
const { focused, tags, activeIndex } = this.state;
|
|
231
231
|
const { disabled, canNotBeEmpty, allowAddNewTags, filter, size, labelType, height = typeof this.context === 'function' ? this.context() : this.context, label, } = this.props;
|
|
232
|
-
const classes = classNames(styles.tagsInput, [inputStyles[`size${size}`]], [inputStyles[`height${height}`]], {
|
|
232
|
+
const classes = classNames(styles.tagsInput, size !== Size.AUTO && [inputStyles[`size${size}`]], [inputStyles[`height${height}`]], {
|
|
233
233
|
[styles.tagsInputDisabled]: disabled,
|
|
234
234
|
[styles.tagsInputFocused]: focused,
|
|
235
235
|
}, this.props.className);
|
|
@@ -240,7 +240,7 @@ export default class TagsInput extends PureComponent {
|
|
|
240
240
|
{label}
|
|
241
241
|
</ControlLabel>)}
|
|
242
242
|
|
|
243
|
-
<TagsList tags={tags} activeIndex={activeIndex} disabled={disabled} canNotBeEmpty={canNotBeEmpty} handleRemove={this.handleRemove} className={styles.tagsList}
|
|
243
|
+
<TagsList tags={tags} activeIndex={activeIndex} disabled={disabled} canNotBeEmpty={canNotBeEmpty} handleRemove={this.handleRemove} className={styles.tagsList} handleClick={this.handleClick} customTagComponent={this.props.customTagComponent}>
|
|
244
244
|
<Select id={this.id} ref={this.selectRef} size={Select.Size.AUTO} type={Select.Type.INPUT_WITHOUT_CONTROLS} inputPlaceholder={this.props.placeholder} data={this.state.suggestions} className={classNames(styles.tagsSelect)} onSelect={this.addTag} onFocus={this._focusHandler} onBlur={this._blurHandler} renderOptimization={this.props.renderOptimization} add={allowAddNewTags ? { prefix: 'Add new tag' } : undefined} onAdd={allowAddNewTags ? this.handleTagCreation : undefined} filter={filter} maxHeight={this.props.maxPopupHeight} minWidth={this.props.minPopupWidth} top={POPUP_VERTICAL_SHIFT} loading={this.state.loading} onFilter={this.loadSuggestions} onBeforeOpen={this.loadSuggestions} onKeyDown={this.handleKeyDown} disabled={this.props.disabled} loadingMessage={this.props.loadingMessage} notFoundMessage={this.props.notFoundMessage} hint={this.props.hint}/>
|
|
245
245
|
</TagsList>
|
|
246
246
|
</div>);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jetbrains/ring-ui",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.94",
|
|
4
4
|
"description": "JetBrains UI library",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "JetBrains"
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
"postpublish": "pinst --enable",
|
|
64
64
|
"postrelease-ci": "git push --follow-tags",
|
|
65
65
|
"prea11y-audit": "playwright install",
|
|
66
|
-
"prebuild": "rimraf components &&
|
|
66
|
+
"prebuild": "rimraf components && npm run prebuild:tsc && cpy './**/*' '!**/*.stories.*' '!**/*.figma.*' '!**/*.ts' '!**/*.tsx' '!**/test-helpers/mocks/**' ../components --parents --cwd=src/",
|
|
67
|
+
"prebuild:tsc": "(npm run type-check:create-d-ts && tsc --project tsconfig-build.json) ; npm run type-check:cleanup-d-ts",
|
|
67
68
|
"prepare": "webpack -c .storybook/custom-header/webpack.config.js",
|
|
68
69
|
"prepublishOnly": "pinst --disable",
|
|
69
70
|
"prerelease-built-ci": "node scripts/prepare-built-package.js",
|
|
@@ -79,7 +80,11 @@
|
|
|
79
80
|
"storybook-debug": "node --inspect-brk node_modules/@storybook/react/bin -p 9999",
|
|
80
81
|
"stylelint": "stylelint --ignore-path .stylelintignore '**/*.css'",
|
|
81
82
|
"test": "vitest src",
|
|
82
|
-
"type-check": "
|
|
83
|
+
"type-check": "(npm run type-check:create-d-ts && npm run type-check:main && npm run type-check:build) ; npm run type-check:cleanup-d-ts",
|
|
84
|
+
"type-check:create-d-ts": "npx tcm src && npx tcm .storybook",
|
|
85
|
+
"type-check:main": "tsc --noEmit -p tsconfig.json",
|
|
86
|
+
"type-check:build": "tsc --noEmit -p tsconfig-build.json",
|
|
87
|
+
"type-check:cleanup-d-ts": "rimraf src/**/*.css.d.ts .storybook/*.css.d.ts .storybook/**/*.css.d.ts",
|
|
83
88
|
"update-styles": "node scripts/update-styles.mjs",
|
|
84
89
|
"validate-tc-config": "mvn --file .teamcity/pom.xml org.jetbrains.teamcity:teamcity-configs-maven-plugin:generate -e"
|
|
85
90
|
},
|
|
@@ -101,6 +106,7 @@
|
|
|
101
106
|
"@jetbrains/logos": "3.0.0-canary.734b213.0",
|
|
102
107
|
"@jetbrains/rollup-css-plugin": "./packages/rollup-css-plugin",
|
|
103
108
|
"@jetbrains/stylelint-config": "^4.0.2",
|
|
109
|
+
"@jetbrains/typescript-plugin-css-modules": "^5.3.1",
|
|
104
110
|
"@primer/octicons": "^19.22.0",
|
|
105
111
|
"@rollup/plugin-babel": "^6.1.0",
|
|
106
112
|
"@rollup/plugin-json": "^6.1.0",
|
|
@@ -173,6 +179,7 @@
|
|
|
173
179
|
"svg-inline-loader": "^0.8.2",
|
|
174
180
|
"teamcity-service-messages": "^0.1.14",
|
|
175
181
|
"terser-webpack-plugin": "^5.3.16",
|
|
182
|
+
"typed-css-modules": "^0.9.1",
|
|
176
183
|
"typescript": "~5.9.3",
|
|
177
184
|
"typescript-eslint": "^8.55.0",
|
|
178
185
|
"vitest": "^4.0.18",
|