@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.
@@ -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
- return (<div className={classNames(styles.avatarStack, className, styles[`size${size}`], {
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
- const dayInWeek = getDayNumInWeek(locale, getDay(day)) + 1;
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, styles[`Day${dayInWeek}`], {
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 className={styles.trayItem}>{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;
@@ -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}>
@@ -7,7 +7,7 @@ declare function noop(): void;
7
7
  * @name Input
8
8
  */
9
9
  declare enum Size {
10
- AUTO = "Auto",
10
+ AUTO = "AUTO",
11
11
  S = "S",
12
12
  M = "M",
13
13
  L = "L",
@@ -17,7 +17,7 @@ function noop() { }
17
17
  */
18
18
  var Size;
19
19
  (function (Size) {
20
- Size["AUTO"] = "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, [styles[`size${size}`]], [styles[`height${height}`]], {
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
- const containerClasses = classNames(className, inputStyles[`size${huge ? Size.FULL : size}`], {
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, styles.loader, {
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(styles.rightSearchIcon, this.props.searchButtonClassName)} title={translations?.searchTitle ?? translate('searchTitle')} onClick={this.handleApply} ref={this.glassRef} data-test='query-assist-search-icon'/>
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 classes = classNames(styles.select, 'ring-js-shortcuts', this.props.className, styles[`height${this.getHeight()}`], {
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 className={style.subHeader} data-test='ring-table-header-row'>
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={classNames(styles.moreButton, styles.title)}>
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.props.id || String(index);
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
- getTabTitle: (child: ReactElement<TabProps>, i: number) => React.JSX.Element;
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
- getTabTitle = (child, i) => {
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 { selected, onSelect } = this.props;
18
- const { title, titleProps, id, disabled, href, className, activeClassName } = child.props;
19
- const key = id || String(i);
20
- const isSelected = key === selected;
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={selected}>
41
+ {autoCollapse === true ? (<CollapsibleTabs {...restProps} onSelect={onSelect ? this.handleSelect : undefined} selected={selectedKey}>
32
42
  {childrenArray}
33
- </CollapsibleTabs>) : (<div className={styles.titles}>{childrenArray.map(this.getTabTitle)}</div>)}
34
- <div className={classNames(tabContainerClassName)}>
35
- {childrenArray.find(({ props }, i) => (props.id || String(i)) === selected)}
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}>{renderedTitle}</span>
11
- <span className={styles.hiddenBold}>{renderedTitle}</span>
12
- <span className={styles.hiddenRegular}>{renderedTitle}</span>
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,3 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { TabProps } from './tab';
3
+ export declare const getTabId: (tab: ReactElement<TabProps> | undefined, index: number) => string;
@@ -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} tagClassName={styles.tag} handleClick={this.handleClick} customTagComponent={this.props.customTagComponent}>
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.93",
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 && tsc --project tsconfig-build.json && cpy './**/*' '!**/*.stories.*' '!**/*.figma.*' '!**/*.ts' '!**/*.tsx' '!**/test-helpers/mocks/**' ../components --parents --cwd=src/",
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": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig-build.json",
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",
package/typings.d.ts CHANGED
@@ -1,8 +1,3 @@
1
- declare module '*.css' {
2
- const styles: Record<string, string>;
3
- export default styles;
4
- }
5
-
6
1
  declare module '*.svg' {
7
2
  const source: string;
8
3
  export default source;