@jetbrains/ring-ui 6.0.28 → 6.0.29

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.
@@ -10,6 +10,7 @@ export interface Column<T = never> {
10
10
  title?: ReactNode;
11
11
  getValue?: ((item: T, column: Column) => ReactNode) | null | undefined;
12
12
  getDataTest?: ((item: T, column: Column) => string) | null | undefined;
13
+ colSpan?: number;
13
14
  }
14
15
  export interface SortParams {
15
16
  column: Column;
@@ -14,6 +14,7 @@ export interface HeaderProps {
14
14
  sortOrder: boolean;
15
15
  caption?: string | null | undefined;
16
16
  checkboxDisabled?: boolean | undefined;
17
+ maxColSpan?: number;
17
18
  }
18
19
  declare module 'react-waypoint' {
19
20
  namespace Waypoint {
@@ -50,7 +51,7 @@ export default class Header extends PureComponent<HeaderProps> {
50
51
  };
51
52
  id: string;
52
53
  onCheckboxFocus: (event: SyntheticEvent<HTMLElement>) => void;
53
- createCells(widths?: never[]): React.JSX.Element[];
54
+ createCells(widths?: never[]): (React.JSX.Element | null)[];
54
55
  render(): React.JSX.Element;
55
56
  }
56
57
  export type HeaderAttrs = JSX.LibraryManagedAttributes<typeof Header, HeaderProps>;
@@ -42,10 +42,15 @@ export default class Header extends PureComponent {
42
42
  {selectable &&
43
43
  (<Checkbox aria-labelledby={this.id} disabled={checkboxDisabled} checked={checked} onChange={onCheckboxChange} onFocus={this.onCheckboxFocus}/>)}
44
44
  </div>);
45
+ let colSpan = 0;
45
46
  return columns.map((column, index) => {
46
47
  const columnStyle = widths[index] ? { width: widths[index] } : undefined;
47
48
  const props = { column, onSort, sortKey, sortOrder, style: columnStyle };
48
- return (<HeaderCell key={column.id} data-test={column.id} {...props}>
49
+ colSpan += column.colSpan || 1;
50
+ if (colSpan > (this.props.maxColSpan || Infinity)) {
51
+ return null;
52
+ }
53
+ return (<HeaderCell key={column.id} data-test={column.id} colSpan={column.colSpan} {...props}>
49
54
  {index === 0 && (draggable || selectable) && metaColumn}
50
55
  </HeaderCell>);
51
56
  });
@@ -4,7 +4,8 @@ import { Column } from './header-cell';
4
4
  import { SelectionItem } from './selection';
5
5
  export interface RowProps<T extends SelectionItem> extends Omit<HTMLAttributes<HTMLTableRowElement>, 'onClick' | 'onDoubleClick' | 'onSelect'>, FocusSensorAddProps<HTMLTableRowElement> {
6
6
  item: T;
7
- columns: readonly Column<T>[];
7
+ columns: readonly Column<T>[] | ((item: T) => readonly Column<T>[]);
8
+ maxColSpan?: number;
8
9
  selectable: boolean;
9
10
  showFocus: boolean;
10
11
  draggable: boolean;
@@ -73,7 +73,7 @@ export default class Row extends PureComponent {
73
73
  this.row = el;
74
74
  };
75
75
  render() {
76
- const { item, columns, selectable, selected, showFocus, draggable, alwaysShowDragHandle, dragHandleTitle, level, collapsible, parentCollapsible, collapsed, onCollapse, onExpand, showDisabledSelection, onSelect, checkboxTooltip, innerRef, focused, autofocus, onFocusReset, onFocusRestore, onHover, className, metaColumnClassName, 'data-test': dataTest, ...restProps } = this.props;
76
+ const { item, columns: columnProps, selectable, selected, showFocus, draggable, alwaysShowDragHandle, dragHandleTitle, level, collapsible, parentCollapsible, collapsed, maxColSpan, onCollapse, onExpand, showDisabledSelection, onSelect, checkboxTooltip, innerRef, focused, autofocus, onFocusReset, onFocusRestore, onHover, className, metaColumnClassName, 'data-test': dataTest, ...restProps } = this.props;
77
77
  const classes = classNames(className, {
78
78
  [style.row]: true,
79
79
  [style.rowFocused]: showFocus,
@@ -109,13 +109,19 @@ export default class Row extends PureComponent {
109
109
  {collapsible && !collapsed &&
110
110
  (<Button className={style.rowCollapseExpandButton} icon={chevronDownIcon} onClick={() => onCollapse(item)}/>)}
111
111
  </div>);
112
+ const columns = typeof columnProps === 'function' ? columnProps(item) : columnProps;
113
+ let colSpan = 0;
112
114
  const cells = columns.map((column, index) => {
113
115
  const getValue = column.getValue || (() => item[column.id]);
114
116
  const getDataTest = column.getDataTest || (() => column.id);
115
117
  const value = getValue(item, column);
116
118
  const cellClasses = classNames({ [style.cellRight]: column.rightAlign }, column.className);
117
119
  const showMetaColumn = draggable || selectable || collapsible || showDisabledSelection || !!level;
118
- return (<Cell key={column.id} className={cellClasses} data-test={getDataTest(item, column)}>
120
+ colSpan += column.colSpan || 1;
121
+ if (colSpan > (maxColSpan || Infinity)) {
122
+ return null;
123
+ }
124
+ return (<Cell colSpan={column.colSpan} key={column.id} className={cellClasses} data-test={getDataTest(item, column)}>
119
125
  {index === 0 && (showMetaColumn) && metaColumn}
120
126
  {value}
121
127
  </Cell>);
@@ -127,7 +133,7 @@ Row.propTypes = {
127
133
  className: PropTypes.string,
128
134
  metaColumnClassName: PropTypes.string,
129
135
  item: PropTypes.object.isRequired,
130
- columns: PropTypes.array.isRequired,
136
+ columns: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired,
131
137
  selectable: PropTypes.bool,
132
138
  showFocus: PropTypes.bool,
133
139
  draggable: PropTypes.bool,
@@ -15,7 +15,7 @@ declare class SmartTable<T extends SelectionItem> extends PureComponent<SmartTab
15
15
  data?: React.Validator<readonly SelectionItem[]> | undefined;
16
16
  loading?: React.Validator<boolean | null | undefined> | undefined;
17
17
  draggable?: React.Validator<boolean | null | undefined> | undefined;
18
- columns?: React.Validator<readonly import("./header-cell").Column<SelectionItem>[]> | undefined;
18
+ columns?: React.Validator<readonly import("./header-cell").Column<SelectionItem>[] | ((item: SelectionItem | null) => readonly import("./header-cell").Column<SelectionItem>[])> | undefined;
19
19
  focused?: React.Validator<boolean | null | undefined> | undefined;
20
20
  isItemSelectable: PropTypes.Requireable<(...args: any[]) => any> | React.Validator<((item: SelectionItem) => boolean) | null | undefined>;
21
21
  innerRef?: React.Validator<React.Ref<HTMLTableRowElement> | undefined> | undefined;
@@ -26,6 +26,7 @@ declare class SmartTable<T extends SelectionItem> extends PureComponent<SmartTab
26
26
  onSort?: React.Validator<((params: import("./header-cell").SortParams) => void) | null | undefined> | undefined;
27
27
  sortKey?: React.Validator<string | null | undefined> | undefined;
28
28
  sortOrder?: React.Validator<boolean | null | undefined> | undefined;
29
+ maxColSpan?: React.Validator<number | null | undefined> | undefined;
29
30
  alwaysShowDragHandle?: React.Validator<boolean | null | undefined> | undefined;
30
31
  dragHandleTitle?: React.Validator<string | null | undefined> | undefined;
31
32
  onReorder?: React.Validator<((params: import("./table").ReorderParams<SelectionItem>) => void) | null | undefined> | undefined;
@@ -15,7 +15,8 @@ export interface ReorderParams<T> {
15
15
  }
16
16
  export interface TableProps<T extends SelectionItem> extends FocusSensorAddProps<HTMLTableRowElement>, SelectionShortcutsAddProps<T>, DisableHoverAddProps {
17
17
  data: readonly T[];
18
- columns: readonly Column<T>[];
18
+ columns: readonly Column<T>[] | ((item: T | null) => readonly Column<T>[]);
19
+ maxColSpan?: number;
19
20
  isItemSelectable: (item: T) => boolean;
20
21
  loading: boolean;
21
22
  onSort: (params: SortParams) => void;
@@ -107,13 +107,13 @@ export class Table extends PureComponent {
107
107
  window.scrollTo(scrollX, scrollY);
108
108
  };
109
109
  render() {
110
- const { data, selection, columns, caption, getItemKey, selectable, focused, isItemSelectable, getItemLevel, getItemClassName, getMetaColumnClassName, getItemDataTest, draggable, alwaysShowDragHandle, dragHandleTitle, loading, onSort, sortKey, sortOrder, loaderClassName, stickyHeader, stickyHeaderOffset, isItemCollapsible, isParentCollapsible, isItemCollapsed, onItemCollapse, onItemExpand, isDisabledSelectionVisible, getCheckboxTooltip, onItemDoubleClick, onItemClick, renderEmpty } = this.props;
110
+ const { data, selection, columns, caption, getItemKey, selectable, focused, isItemSelectable, getItemLevel, getItemClassName, getMetaColumnClassName, getItemDataTest, draggable, alwaysShowDragHandle, dragHandleTitle, loading, onSort, sortKey, sortOrder, loaderClassName, stickyHeader, stickyHeaderOffset, isItemCollapsible, isParentCollapsible, isItemCollapsed, onItemCollapse, onItemExpand, isDisabledSelectionVisible, getCheckboxTooltip, onItemDoubleClick, onItemClick, renderEmpty, maxColSpan } = this.props;
111
111
  // NOTE: Do not construct new object per render because it causes all rows rerendering
112
112
  const headerProps = {
113
113
  caption, selectable, draggable,
114
- columns, onSort, sortKey, sortOrder,
114
+ columns: typeof columns === 'function' ? columns(null) : columns, onSort, sortKey, sortOrder,
115
115
  sticky: stickyHeader,
116
- topStickOffset: stickyHeaderOffset
116
+ topStickOffset: stickyHeaderOffset, maxColSpan: this.props.maxColSpan
117
117
  };
118
118
  const selectedSize = selection.getSelected().size;
119
119
  const allSelectedSize = selection.selectAll().getSelected().size;
@@ -151,7 +151,7 @@ export class Table extends PureComponent {
151
151
  return null;
152
152
  }
153
153
  const { ref, ...restProps } = props;
154
- const row = (<Row innerRef={ref} level={getItemLevel(value)} item={value} showFocus={selection.isFocused(value)} autofocus={selection.isFocused(value)} focused={focused && selection.isFocused(value)} selectable={selectable && isItemSelectable(value)} selected={selectable && selection.isSelected(value)} onFocus={this.onRowFocus} onSelect={this.onRowSelect} onDoubleClick={onItemDoubleClick} onClick={onItemClick} collapsible={isItemCollapsible(value)} parentCollapsible={isParentCollapsible(value)} collapsed={isItemCollapsed(value)} onCollapse={onItemCollapse} onExpand={onItemExpand} showDisabledSelection={isDisabledSelectionVisible(value)} checkboxTooltip={getCheckboxTooltip(value)} className={classNames(getItemClassName(value), { [style.draggingRow]: isDragged })} metaColumnClassName={getMetaColumnClassName(value)} draggable={draggable} alwaysShowDragHandle={alwaysShowDragHandle} dragHandleTitle={dragHandleTitle} columns={columns} data-test={getItemDataTest(value)} {...restProps} key={restProps.key ?? getItemKey(value)}/>);
154
+ const row = (<Row innerRef={ref} level={getItemLevel(value)} item={value} showFocus={selection.isFocused(value)} autofocus={selection.isFocused(value)} focused={focused && selection.isFocused(value)} selectable={selectable && isItemSelectable(value)} selected={selectable && selection.isSelected(value)} onFocus={this.onRowFocus} onSelect={this.onRowSelect} onDoubleClick={onItemDoubleClick} onClick={onItemClick} collapsible={isItemCollapsible(value)} parentCollapsible={isParentCollapsible(value)} collapsed={isItemCollapsed(value)} onCollapse={onItemCollapse} onExpand={onItemExpand} showDisabledSelection={isDisabledSelectionVisible(value)} checkboxTooltip={getCheckboxTooltip(value)} className={classNames(getItemClassName(value), { [style.draggingRow]: isDragged })} metaColumnClassName={getMetaColumnClassName(value)} draggable={draggable} alwaysShowDragHandle={alwaysShowDragHandle} dragHandleTitle={dragHandleTitle} columns={columns} data-test={getItemDataTest(value)} maxColSpan={maxColSpan} {...restProps} key={restProps.key ?? getItemKey(value)}/>);
155
155
  return isDragged
156
156
  ? (<table style={{ ...props.style }} className={style.draggingTable}>
157
157
  <tbody>{row}</tbody>
@@ -179,7 +179,7 @@ Table.propTypes = {
179
179
  className: PropTypes.string,
180
180
  loaderClassName: PropTypes.string,
181
181
  data: PropTypes.array.isRequired,
182
- columns: PropTypes.array.isRequired,
182
+ columns: PropTypes.oneOfType([PropTypes.array, PropTypes.func]).isRequired,
183
183
  caption: PropTypes.string,
184
184
  isItemSelectable: PropTypes.func,
185
185
  stickyHeader: PropTypes.bool,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jetbrains/ring-ui",
3
- "version": "6.0.28",
3
+ "version": "6.0.29",
4
4
  "description": "JetBrains UI library",
5
5
  "author": "JetBrains",
6
6
  "license": "Apache-2.0",
@@ -88,16 +88,16 @@
88
88
  "@rollup/plugin-json": "^6.1.0",
89
89
  "@rollup/plugin-node-resolve": "^15.2.3",
90
90
  "@rollup/plugin-replace": "^5.0.5",
91
- "@storybook/addon-a11y": "8.0.10",
92
- "@storybook/addon-docs": "8.0.10",
93
- "@storybook/addon-essentials": "8.0.10",
94
- "@storybook/components": "8.0.10",
95
- "@storybook/manager-api": "8.0.10",
96
- "@storybook/preview-api": "8.0.10",
97
- "@storybook/react": "8.0.10",
98
- "@storybook/react-webpack5": "8.0.10",
91
+ "@storybook/addon-a11y": "8.1.0",
92
+ "@storybook/addon-docs": "8.1.0",
93
+ "@storybook/addon-essentials": "8.1.0",
94
+ "@storybook/components": "8.1.0",
95
+ "@storybook/manager-api": "8.1.0",
96
+ "@storybook/preview-api": "8.1.0",
97
+ "@storybook/react": "8.1.0",
98
+ "@storybook/react-webpack5": "8.1.0",
99
99
  "@storybook/test-runner": "^0.18.0",
100
- "@storybook/theming": "8.0.10",
100
+ "@storybook/theming": "8.1.0",
101
101
  "@testing-library/react": "^15.0.7",
102
102
  "@testing-library/user-event": "^14.5.2",
103
103
  "@types/chai": "^4.3.16",
@@ -110,19 +110,19 @@
110
110
  "@types/react-dom": "^18.3.0",
111
111
  "@types/sinon": "^17.0.3",
112
112
  "@types/sinon-chai": "^3.2.12",
113
- "@typescript-eslint/eslint-plugin": "^7.8.0",
114
- "@typescript-eslint/parser": "^7.8.0",
113
+ "@typescript-eslint/eslint-plugin": "^7.9.0",
114
+ "@typescript-eslint/parser": "^7.9.0",
115
115
  "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
116
116
  "acorn": "^8.11.3",
117
117
  "axe-playwright": "^2.0.1",
118
118
  "babel-plugin-require-context-hook": "^1.0.0",
119
- "caniuse-lite": "^1.0.30001617",
119
+ "caniuse-lite": "^1.0.30001618",
120
120
  "chai": "^5.1.1",
121
121
  "chai-as-promised": "^7.1.2",
122
122
  "chai-dom": "^1.10.0",
123
123
  "chai-enzyme": "1.0.0-beta.1",
124
124
  "cheerio": "^1.0.0-rc.12",
125
- "core-js": "^3.37.0",
125
+ "core-js": "^3.37.1",
126
126
  "cpy-cli": "^3.1.1",
127
127
  "enzyme": "^3.11.0",
128
128
  "eslint": "^8.57.0",
@@ -167,7 +167,7 @@
167
167
  "sinon": "^17.0.2",
168
168
  "sinon-chai": "^3.7.0",
169
169
  "storage-mock": "^2.1.0",
170
- "storybook": "8.0.10",
170
+ "storybook": "8.1.0",
171
171
  "storybook-addon-themes": "^6.1.0",
172
172
  "stylelint": "^16.5.0",
173
173
  "svg-inline-loader": "^0.8.2",
@@ -237,7 +237,7 @@
237
237
  "postcss-font-family-system-ui": "^5.0.0",
238
238
  "postcss-loader": "^8.1.1",
239
239
  "postcss-modules-values-replace": "^4.2.0",
240
- "postcss-preset-env": "^9.5.12",
240
+ "postcss-preset-env": "^9.5.13",
241
241
  "prop-types": "^15.8.1",
242
242
  "react-movable": "^3.2.0",
243
243
  "react-virtualized": "^9.22.5",