@jetbrains/ring-ui 7.0.99 → 7.0.101

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.
@@ -9,8 +9,8 @@ const defaultAriaLabel = 'Dropdown menu';
9
9
  function DropdownAnchorWrapper({ anchor, pinned, active, activeListItemId, listId, ...restProps }) {
10
10
  const anchorAriaProps = {
11
11
  ...(listId ? { 'aria-haspopup': true } : {}),
12
- ...(activeListItemId ? { 'aria-activedescendant': activeListItemId, 'aria-owns': listId } : {}),
13
- ...(active ? { 'aria-expanded': true } : {}),
12
+ ...(activeListItemId ? { 'aria-activedescendant': activeListItemId } : {}),
13
+ ...(active ? { 'aria-expanded': true, 'aria-owns': listId } : {}),
14
14
  };
15
15
  const anchorProps = { active, pinned, ...restProps, ...anchorAriaProps };
16
16
  const anchorComponentProps = { ...anchorProps, pinned: `${anchorProps.pinned}` };
@@ -39,7 +39,7 @@ const DropdownMenu = forwardRef(function DropdownMenu({ id, anchor, ariaLabel, d
39
39
  id: listId,
40
40
  ariaLabel: ariaLabel || defaultAriaLabel,
41
41
  closeOnSelect: true,
42
- activateFirstItem: true,
42
+ activateFirstItem: false,
43
43
  data,
44
44
  onSelect,
45
45
  ...menuProps,
@@ -97,7 +97,7 @@ export class Input extends PureComponent {
97
97
  // Modifiers
98
98
  size, multiline, borderless,
99
99
  // Props
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;
100
+ label, labelType, error, help, className, inputClassName, clearButtonClassName, 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
103
  const classes = classNames(className, styles.outerContainer, size && size !== Size.AUTO && styles[`size${size}`], styles[`height${height}`], {
@@ -129,7 +129,7 @@ export class Input extends PureComponent {
129
129
  {icon && <Icon glyph={icon} className={styles.icon}/>}
130
130
  {beforeInput}
131
131
  {multiline ? (<textarea onChange={this.handleTextareaChange} rows={1} {...commonProps} {...restProps}/>) : (<input onChange={this.handleInputChange} {...commonProps} {...restProps}/>)}
132
- {clearable && !disabled && (<Button title={translations?.clear ?? translate('clear')} data-test='ring-input-clear' className={classNames(styles.clear, this.props.clearButtonClassName)} icon={closeIcon} onClick={this.clear}/>)}
132
+ {clearable && !disabled && (<Button title={translations?.clear ?? translate('clear')} data-test='ring-input-clear' className={classNames(styles.clear, clearButtonClassName)} icon={closeIcon} onClick={this.clear}/>)}
133
133
  {afterInput}
134
134
  </div>
135
135
  {error ? (<div className={styles.errorText}>{error}</div>) : (help && <ControlHelp className={styles.helpText}>{help}</ControlHelp>)}
@@ -1,5 +1,9 @@
1
1
  import { PureComponent, type SyntheticEvent } from 'react';
2
2
  import { type ListDataItemProps } from './consts';
3
+ /**
4
+ * @constructor
5
+ * @extends {ReactComponent}
6
+ */
3
7
  export default class ListItem<T> extends PureComponent<ListDataItemProps<T>> {
4
8
  id: string;
5
9
  stopBubbling: (e: SyntheticEvent) => void;
@@ -13,9 +13,6 @@ import styles from './list.css';
13
13
  * @constructor
14
14
  * @extends {ReactComponent}
15
15
  */
16
- const RING_UNIT = 8;
17
- const DEFAULT_PADDING = 8;
18
- const CHECKBOX_WIDTH = 28;
19
16
  export default class ListItem extends PureComponent {
20
17
  id = getUID('list-item-');
21
18
  stopBubbling = (e) => e.stopPropagation();
@@ -31,10 +28,12 @@ export default class ListItem extends PureComponent {
31
28
  const classes = getListClasses(this.props);
32
29
  const detailsClasses = classNames({
33
30
  [styles.details]: details,
34
- [styles.padded]: icon !== undefined || checkbox !== undefined || glyph !== undefined,
31
+ [styles.padded]: !showCheckbox && hasLeftNodes,
35
32
  }, detailsClassName);
33
+ const levelPadding = `var(--ring-unit) * ${1 + (Number(level) || 0)}`;
34
+ const checkboxPadding = showCheckbox ? ' + var(--ring-list-item-icon-size) + var(--ring-unit)' : '';
36
35
  const style = {
37
- paddingLeft: `${(Number(level) || 0) * RING_UNIT + DEFAULT_PADDING + (showCheckbox ? CHECKBOX_WIDTH : 0)}px`,
36
+ paddingLeft: `calc(${levelPadding}${checkboxPadding})`,
38
37
  };
39
38
  let computedTitle;
40
39
  if (this._isString(title)) {
@@ -74,6 +74,8 @@
74
74
  }
75
75
 
76
76
  .itemContainer {
77
+ --ring-list-item-icon-size: 20px;
78
+
77
79
  position: relative;
78
80
  }
79
81
 
@@ -150,7 +152,7 @@
150
152
  }
151
153
 
152
154
  .padded {
153
- margin-left: 20px;
155
+ margin-left: calc(var(--ring-unit) + var(--ring-list-item-icon-size));
154
156
  }
155
157
 
156
158
  /* Override :last-child */
@@ -194,8 +196,8 @@
194
196
  .icon {
195
197
  display: inline-block;
196
198
 
197
- width: 20px;
198
- height: 20px;
199
+ width: var(--ring-list-item-icon-size);
200
+ height: var(--ring-list-item-icon-size);
199
201
  margin-left: calc(var(--ring-unit) * 2);
200
202
 
201
203
  background-repeat: no-repeat;
@@ -215,7 +217,7 @@
215
217
  .glyph {
216
218
  float: left;
217
219
 
218
- width: 20px;
220
+ width: var(--ring-list-item-icon-size);
219
221
 
220
222
  margin-right: var(--ring-unit);
221
223
 
@@ -227,7 +229,7 @@
227
229
 
228
230
  top: 0;
229
231
 
230
- height: 20px;
232
+ height: var(--ring-list-item-icon-size);
231
233
 
232
234
  object-fit: cover;
233
235
  object-position: center;
@@ -247,8 +249,8 @@
247
249
  top: 7px;
248
250
  left: 19px;
249
251
 
250
- width: 20px;
251
- height: 20px;
252
+ width: var(--ring-list-item-icon-size);
253
+ height: var(--ring-list-item-icon-size);
252
254
  margin-right: var(--ring-unit);
253
255
  }
254
256
 
@@ -342,7 +342,13 @@ export default class List extends Component {
342
342
  else {
343
343
  const itemId = this.getId(this.props.data[activeIndex]);
344
344
  if (itemId) {
345
- document.getElementById(itemId)?.scrollIntoView?.({ block: 'center' });
345
+ // scrollIntoView({container: 'nearest'}) is not yet supported in Firefox and Safari, emulating
346
+ const itemElement = document.getElementById(itemId);
347
+ const scrollerElement = this.inner;
348
+ if (itemElement && scrollerElement) {
349
+ scrollerElement.scrollTop =
350
+ itemElement.offsetTop + itemElement.clientHeight / 2 - scrollerElement.clientHeight / 2;
351
+ }
346
352
  }
347
353
  }
348
354
  };
@@ -65,7 +65,11 @@
65
65
  padding-left: var(--ring-input-padding-end);
66
66
  }
67
67
 
68
- &:hover {
68
+ &.error {
69
+ border-color: var(--ring-error-color);
70
+ }
71
+
72
+ &:hover:not(.error) {
69
73
  transition: none;
70
74
 
71
75
  border-color: var(--ring-border-hover-color);
@@ -45,6 +45,7 @@ export interface TagsInputProps {
45
45
  label?: ReactNode;
46
46
  labelType?: LabelType;
47
47
  id?: string | undefined;
48
+ error?: ReactNode | null | undefined;
48
49
  }
49
50
  interface TagsInputState {
50
51
  tags: TagType[];
@@ -228,7 +228,7 @@ export default class TagsInput extends PureComponent {
228
228
  };
229
229
  render() {
230
230
  const { focused, tags, activeIndex } = this.state;
231
- const { disabled, canNotBeEmpty, allowAddNewTags, filter, size, labelType, height = typeof this.context === 'function' ? this.context() : this.context, label, } = this.props;
231
+ const { disabled, canNotBeEmpty, allowAddNewTags, filter, size, labelType, height = typeof this.context === 'function' ? this.context() : this.context, label, error, } = this.props;
232
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,
@@ -240,8 +240,8 @@ 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} handleClick={this.handleClick} customTagComponent={this.props.customTagComponent}>
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}/>
243
+ <TagsList tags={tags} activeIndex={activeIndex} disabled={disabled} canNotBeEmpty={canNotBeEmpty} handleRemove={this.handleRemove} className={classNames(styles.tagsList, error != null && styles.error)} handleClick={this.handleClick} customTagComponent={this.props.customTagComponent}>
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} error={error}/>
245
245
  </TagsList>
246
246
  </div>);
247
247
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jetbrains/ring-ui",
3
- "version": "7.0.99",
3
+ "version": "7.0.101",
4
4
  "description": "JetBrains UI library",
5
5
  "author": {
6
6
  "name": "JetBrains"
@@ -103,8 +103,8 @@
103
103
  "@babel/eslint-parser": "^7.28.6",
104
104
  "@csstools/css-parser-algorithms": "^4.0.0",
105
105
  "@csstools/stylelint-no-at-nest-rule": "^5.0.0",
106
- "@eslint/compat": "^2.0.2",
107
- "@eslint/eslintrc": "^3.3.4",
106
+ "@eslint/compat": "^2.0.3",
107
+ "@eslint/eslintrc": "^3.3.5",
108
108
  "@eslint/js": "^10.0.1",
109
109
  "@figma/code-connect": "^1.4.1",
110
110
  "@jetbrains/eslint-config": "^6.0.5",
@@ -113,15 +113,15 @@
113
113
  "@jetbrains/stylelint-config": "^4.0.2",
114
114
  "@jetbrains/typescript-plugin-css-modules": "^5.3.1",
115
115
  "@primer/octicons": "^19.22.0",
116
- "@rollup/plugin-babel": "^6.1.0",
116
+ "@rollup/plugin-babel": "^7.0.0",
117
117
  "@rollup/plugin-json": "^6.1.0",
118
118
  "@rollup/plugin-node-resolve": "^16.0.3",
119
119
  "@rollup/plugin-replace": "^6.0.3",
120
- "@storybook/addon-a11y": "10.2.14",
121
- "@storybook/addon-docs": "^10.2.14",
122
- "@storybook/addon-themes": "^10.2.14",
120
+ "@storybook/addon-a11y": "10.2.16",
121
+ "@storybook/addon-docs": "^10.2.16",
122
+ "@storybook/addon-themes": "^10.2.16",
123
123
  "@storybook/csf": "^0.1.13",
124
- "@storybook/react-webpack5": "10.2.14",
124
+ "@storybook/react-webpack5": "10.2.16",
125
125
  "@storybook/test-runner": "^0.24.2",
126
126
  "@testing-library/dom": "^10.4.1",
127
127
  "@testing-library/react": "^16.3.2",
@@ -136,7 +136,7 @@
136
136
  "@vitest/eslint-plugin": "^1.6.9",
137
137
  "acorn": "^8.16.0",
138
138
  "babel-plugin-require-context-hook": "^1.0.0",
139
- "caniuse-lite": "^1.0.30001770",
139
+ "caniuse-lite": "^1.0.30001777",
140
140
  "chai-as-promised": "^8.0.2",
141
141
  "chai-dom": "^1.12.1",
142
142
  "cheerio": "^1.2.0",
@@ -154,7 +154,7 @@
154
154
  "eslint-plugin-prettier": "^5.5.5",
155
155
  "eslint-plugin-react": "^7.37.5",
156
156
  "eslint-plugin-react-hooks": "^7.0.1",
157
- "eslint-plugin-storybook": "^10.2.14",
157
+ "eslint-plugin-storybook": "^10.2.16",
158
158
  "eslint-plugin-unicorn": "^63.0.0",
159
159
  "events": "^3.3.0",
160
160
  "glob": "^13.0.6",
@@ -166,7 +166,7 @@
166
166
  "jest": "~30.2.0",
167
167
  "jest-environment-jsdom": "^30.2.0",
168
168
  "jest-teamcity": "^1.12.0",
169
- "lint-staged": "^16.3.1",
169
+ "lint-staged": "^16.3.2",
170
170
  "markdown-it": "^14.1.1",
171
171
  "merge-options": "^3.0.4",
172
172
  "pinst": "^3.0.0",
@@ -179,18 +179,18 @@
179
179
  "rollup": "^4.59.0",
180
180
  "rollup-plugin-clear": "^2.0.7",
181
181
  "storage-mock": "^2.1.0",
182
- "storybook": "10.2.14",
182
+ "storybook": "10.2.16",
183
183
  "stylelint": "^17.4.0",
184
184
  "stylelint-config-sass-guidelines": "^13.0.0",
185
185
  "svg-inline-loader": "^0.8.2",
186
186
  "teamcity-service-messages": "^0.1.14",
187
- "terser-webpack-plugin": "^5.3.16",
187
+ "terser-webpack-plugin": "^5.3.17",
188
188
  "typed-css-modules": "^0.9.1",
189
189
  "typescript": "~5.9.3",
190
190
  "typescript-eslint": "^8.56.1",
191
191
  "vitest": "^4.0.18",
192
192
  "vitest-teamcity-reporter": "^0.4.1",
193
- "webpack": "^5.105.3",
193
+ "webpack": "^5.105.4",
194
194
  "webpack-cli": "^6.0.1",
195
195
  "xmlappend": "^1.0.4"
196
196
  },
@@ -223,7 +223,7 @@
223
223
  "@types/element-resize-detector": "^1.1.6",
224
224
  "@types/react-virtualized": "9.22.3",
225
225
  "@types/util-deprecate": "^1.0.4",
226
- "babel-loader": "10.0.0",
226
+ "babel-loader": "10.1.0",
227
227
  "babel-plugin-react-compiler": "^1.0.0",
228
228
  "babel-plugin-transform-define": "^2.1.4",
229
229
  "browserslist": "^4.28.1",
@@ -241,7 +241,7 @@
241
241
  "highlight.js": "^10.7.2",
242
242
  "just-debounce-it": "^3.2.0",
243
243
  "memoize-one": "^6.0.0",
244
- "postcss": "^8.5.6",
244
+ "postcss": "^8.5.8",
245
245
  "postcss-calc": "^10.1.1",
246
246
  "postcss-flexbugs-fixes": "^5.0.2",
247
247
  "postcss-font-family-system-ui": "^5.0.0",