@jetbrains/ring-ui 7.0.124 → 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.
Files changed (191) hide show
  1. package/babel.config.js +1 -9
  2. package/components/auth-dialog-service/auth-dialog-service.js +2 -2
  3. package/components/avatar/avatar-info.js +0 -2
  4. package/components/avatar/avatar-size.d.ts +0 -4
  5. package/components/avatar/avatar-size.js +0 -4
  6. package/components/avatar/avatar.js +0 -6
  7. package/components/avatar/fallback-avatar.js +0 -28
  8. package/components/avatar-stack/avatar-stack.js +1 -1
  9. package/components/button/button.css +4 -4
  10. package/components/button/button.d.ts +0 -4
  11. package/components/button/button.js +2 -7
  12. package/components/button-group/button-group.css +23 -23
  13. package/components/button-toolbar/button-toolbar.css +2 -2
  14. package/components/checkbox/checkbox.d.ts +1 -1
  15. package/components/collapse/collapse-content.js +7 -16
  16. package/components/collapse/collapse-context.d.ts +1 -0
  17. package/components/collapse/collapse-context.js +1 -0
  18. package/components/collapse/collapse-control.js +2 -2
  19. package/components/collapse/collapse.css +8 -2
  20. package/components/collapse/collapse.js +10 -2
  21. package/components/collapsible-group/collapsible-group.css +1 -1
  22. package/components/collapsible-group/collapsible-group.d.ts +5 -1
  23. package/components/collapsible-group/collapsible-group.js +13 -22
  24. package/components/confirm-service/confirm-service.js +2 -2
  25. package/components/contenteditable/contenteditable.js +1 -2
  26. package/components/data-list/data-list.d.ts +4 -4
  27. package/components/data-list/data-list.js +2 -2
  28. package/components/data-list/data-list.mock.d.ts +1 -1
  29. package/components/data-list/item.d.ts +1 -1
  30. package/components/data-list/selection.d.ts +1 -1
  31. package/components/data-list/selection.js +1 -1
  32. package/components/date-picker/month.d.ts +0 -2
  33. package/components/date-picker/month.js +5 -5
  34. package/components/date-picker/months.js +8 -7
  35. package/components/date-picker/use-scroll-behavior.js +5 -6
  36. package/components/date-picker/years.js +11 -10
  37. package/components/dialog/dialog.d.ts +2 -2
  38. package/components/dialog/dialog.js +2 -2
  39. package/components/dropdown-menu/dropdown-menu.d.ts +4 -4
  40. package/components/dropdown-menu/dropdown-menu.js +4 -4
  41. package/components/editable-heading/editable-heading.d.ts +1 -2
  42. package/components/editable-heading/editable-heading.js +5 -6
  43. package/components/global/compose-refs.d.ts +2 -1
  44. package/components/global/compose-refs.js +24 -8
  45. package/components/global/configuration.d.ts +0 -5
  46. package/components/global/configuration.js +0 -7
  47. package/components/global/create-stateful-context.js +5 -5
  48. package/components/global/focus-with-temporary-tabindex.d.ts +11 -0
  49. package/components/global/focus-with-temporary-tabindex.js +21 -0
  50. package/components/global/intersection-observer-context.d.ts +46 -0
  51. package/components/global/intersection-observer-context.js +91 -0
  52. package/components/global/is-within-interactive-element.d.ts +6 -0
  53. package/components/global/is-within-interactive-element.js +26 -0
  54. package/components/global/is-within-navigable-element.d.ts +6 -0
  55. package/components/global/is-within-navigable-element.js +27 -0
  56. package/components/global/parse-css-duration.d.ts +5 -0
  57. package/components/global/parse-css-duration.js +13 -0
  58. package/components/global/rerender-hoc.d.ts +4 -2
  59. package/components/global/rerender-hoc.js +4 -4
  60. package/components/global/schedule-with-cleanup.d.ts +12 -0
  61. package/components/global/schedule-with-cleanup.js +34 -0
  62. package/components/{table/selection.d.ts → global/table-selection.d.ts} +15 -15
  63. package/components/{table/selection.js → global/table-selection.js} +3 -3
  64. package/components/global/theme.d.ts +4 -3
  65. package/components/global/theme.js +8 -8
  66. package/components/global/variables.css +0 -10
  67. package/components/global/variables.interface.d.ts +0 -4
  68. package/components/global/variables_dark.css +0 -7
  69. package/components/i18n/i18n-context.js +1 -1
  70. package/components/icon/icon-svg.js +2 -3
  71. package/components/icon/icon.css +0 -27
  72. package/components/icon/icon.d.ts +0 -1
  73. package/components/icon/icon.js +2 -4
  74. package/components/input/input.d.ts +1 -1
  75. package/components/island/adaptive-island-hoc.js +4 -4
  76. package/components/island/content.d.ts +7 -2
  77. package/components/island/content.js +5 -5
  78. package/components/{table → legacy-table}/cell.js +1 -1
  79. package/components/{table → legacy-table}/header-cell.js +1 -1
  80. package/components/{table → legacy-table}/header.js +1 -1
  81. package/components/legacy-table/legacy-table.css +260 -0
  82. package/components/{table → legacy-table}/multitable.d.ts +1 -1
  83. package/components/{table → legacy-table}/row.d.ts +1 -1
  84. package/components/{table → legacy-table}/row.js +1 -1
  85. package/components/legacy-table/selection-adapter.d.ts +6 -0
  86. package/components/{table → legacy-table}/selection-shortcuts-hoc.d.ts +5 -5
  87. package/components/{table → legacy-table}/simple-table.d.ts +2 -2
  88. package/components/{table → legacy-table}/simple-table.js +3 -3
  89. package/components/{table → legacy-table}/smart-table.d.ts +5 -5
  90. package/components/{table → legacy-table}/smart-table.js +3 -3
  91. package/components/legacy-table/table.d.ts +109 -0
  92. package/components/legacy-table/table.js +191 -0
  93. package/components/list/consts.d.ts +0 -1
  94. package/components/list/consts.js +0 -1
  95. package/components/list/list.d.ts +0 -4
  96. package/components/login-dialog/service.js +2 -2
  97. package/components/popup/popup.target.d.ts +3 -2
  98. package/components/popup/popup.target.js +4 -6
  99. package/components/query-assist/query-assist.d.ts +3 -1
  100. package/components/query-assist/query-assist.js +2 -2
  101. package/components/radio/radio-item.d.ts +3 -3
  102. package/components/radio/radio-item.js +3 -4
  103. package/components/radio/radio.d.ts +2 -2
  104. package/components/radio/radio.js +1 -1
  105. package/components/select/select-popup.d.ts +3 -2
  106. package/components/select/select-popup.js +3 -3
  107. package/components/select/select.d.ts +6 -2
  108. package/components/select/select.js +2 -4
  109. package/components/selection-toolbar/selection-toolbar.css +86 -0
  110. package/components/selection-toolbar/selection-toolbar.d.ts +11 -0
  111. package/components/selection-toolbar/selection-toolbar.js +23 -0
  112. package/components/slider/slider.js +4 -5
  113. package/components/tab-trap/tab-trap.d.ts +3 -3
  114. package/components/tab-trap/tab-trap.js +3 -5
  115. package/components/table/default-item-renderer.d.ts +55 -0
  116. package/components/table/default-item-renderer.js +77 -0
  117. package/components/table/internal/reorder-animation-context.d.ts +21 -0
  118. package/components/table/internal/reorder-animation-context.js +60 -0
  119. package/components/table/internal/reorder-handle.d.ts +9 -0
  120. package/components/table/internal/reorder-handle.js +334 -0
  121. package/components/table/internal/reorder-layout-context.d.ts +16 -0
  122. package/components/table/internal/reorder-layout-context.js +69 -0
  123. package/components/table/internal/table-header.d.ts +1 -0
  124. package/components/table/internal/table-header.js +143 -0
  125. package/components/table/internal/virtualization.d.ts +41 -0
  126. package/components/table/internal/virtualization.js +186 -0
  127. package/components/table/item-virtualization.d.ts +37 -0
  128. package/components/table/item-virtualization.js +26 -0
  129. package/components/table/reorder-animation.d.ts +37 -0
  130. package/components/table/reorder-animation.js +11 -0
  131. package/components/table/reorder-item-layout.d.ts +32 -0
  132. package/components/table/reorder-item-layout.js +23 -0
  133. package/components/table/table-const.d.ts +10 -0
  134. package/components/table/table-const.js +10 -0
  135. package/components/table/table-primitives.d.ts +64 -0
  136. package/components/table/table-primitives.js +34 -0
  137. package/components/table/table-props.d.ts +304 -0
  138. package/components/table/table-props.js +1 -0
  139. package/components/table/table.css +156 -167
  140. package/components/table/table.d.ts +231 -107
  141. package/components/table/table.js +319 -183
  142. package/components/tags-input/tags-input.d.ts +3 -1
  143. package/components/tooltip/tooltip.d.ts +2 -1
  144. package/components/tooltip/tooltip.js +6 -5
  145. package/components/upload/upload.d.ts +4 -3
  146. package/components/upload/upload.js +3 -7
  147. package/components/user-agreement/service.js +2 -2
  148. package/components/util-stories.d.ts +26 -0
  149. package/components/util-stories.js +61 -0
  150. package/package.json +45 -48
  151. package/components/content-layout/content-layout.css +0 -109
  152. package/components/content-layout/content-layout.d.ts +0 -20
  153. package/components/content-layout/content-layout.js +0 -40
  154. package/components/content-layout/sidebar.d.ts +0 -26
  155. package/components/content-layout/sidebar.js +0 -71
  156. package/components/date-picker/use-intersection-observer.d.ts +0 -6
  157. package/components/date-picker/use-intersection-observer.js +0 -48
  158. package/components/expand/collapsible-group.css +0 -76
  159. package/components/expand/collapsible-group.d.ts +0 -8
  160. package/components/expand/collapsible-group.js +0 -14
  161. package/components/global/composeRefs.d.ts +0 -6
  162. package/components/global/composeRefs.js +0 -7
  163. package/components/global/use-event-callback.d.ts +0 -4
  164. package/components/global/use-event-callback.js +0 -20
  165. package/components/grid/col.d.ts +0 -16
  166. package/components/grid/col.js +0 -35
  167. package/components/grid/grid.css +0 -920
  168. package/components/grid/grid.d.ts +0 -13
  169. package/components/grid/grid.js +0 -19
  170. package/components/grid/row.d.ts +0 -21
  171. package/components/grid/row.js +0 -41
  172. package/components/old-browsers-message/__mocks__/old-browsers-message.js +0 -1
  173. package/components/old-browsers-message/old-browsers-message-stop.d.ts +0 -1
  174. package/components/old-browsers-message/old-browsers-message-stop.js +0 -2
  175. package/components/old-browsers-message/old-browsers-message.css +0 -26
  176. package/components/old-browsers-message/old-browsers-message.d.ts +0 -5
  177. package/components/old-browsers-message/old-browsers-message.js +0 -86
  178. package/components/old-browsers-message/white-list.d.ts +0 -2
  179. package/components/old-browsers-message/white-list.js +0 -24
  180. package/components/table/selection-adapter.d.ts +0 -6
  181. /package/components/{table → legacy-table}/cell.d.ts +0 -0
  182. /package/components/{table → legacy-table}/disable-hover-hoc.d.ts +0 -0
  183. /package/components/{table → legacy-table}/disable-hover-hoc.js +0 -0
  184. /package/components/{table → legacy-table}/header-cell.d.ts +0 -0
  185. /package/components/{table → legacy-table}/header.d.ts +0 -0
  186. /package/components/{table → legacy-table}/multitable.js +0 -0
  187. /package/components/{table → legacy-table}/row-with-focus-sensor.d.ts +0 -0
  188. /package/components/{table → legacy-table}/row-with-focus-sensor.js +0 -0
  189. /package/components/{table → legacy-table}/selection-adapter.js +0 -0
  190. /package/components/{table → legacy-table}/selection-shortcuts-hoc.js +0 -0
  191. /package/components/{table → legacy-table}/table.examples2.json +0 -0
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @name Table
3
+ */
4
+ import { Component, PureComponent } from 'react';
5
+ import * as React from 'react';
6
+ import classNames from 'classnames';
7
+ import { arrayMove, List } from 'react-movable';
8
+ import focusSensorHOC from '../global/focus-sensor-hoc';
9
+ import getUID from '../global/get-uid';
10
+ import Shortcuts from '../shortcuts/shortcuts';
11
+ import Loader from '../loader/loader';
12
+ import Header from './header';
13
+ import selectionShortcutsHOC from './selection-shortcuts-hoc';
14
+ import disableHoverHOC from './disable-hover-hoc';
15
+ import Row from './row-with-focus-sensor';
16
+ import style from './legacy-table.css';
17
+ /**
18
+ * Interactive table with selection and keyboard navigation support.
19
+ */
20
+ export class Table extends PureComponent {
21
+ static defaultProps = {
22
+ isItemSelectable: () => true,
23
+ loading: false,
24
+ onSort: () => { },
25
+ onReorder: () => { },
26
+ getItemKey: (item) => {
27
+ // Default behavior stays backward compatible: use item's "id" if present
28
+ if ('id' in item) {
29
+ return item.id;
30
+ }
31
+ // If there's no id provided on item and no getKey supplied, fail fast with a clear message
32
+ throw new Error('Table: getItemKey is required when items have no "id" property');
33
+ },
34
+ sortKey: 'id',
35
+ sortOrder: true,
36
+ draggable: false,
37
+ alwaysShowDragHandle: false,
38
+ stickyHeader: true,
39
+ getItemLevel: () => 0,
40
+ getItemClassName: () => null,
41
+ getMetaColumnClassName: () => null,
42
+ getItemDataTest: () => null,
43
+ isItemCollapsible: () => false,
44
+ isParentCollapsible: () => false,
45
+ isItemCollapsed: () => false,
46
+ onItemCollapse: () => { },
47
+ onItemExpand: () => { },
48
+ onItemDoubleClick: () => { },
49
+ onItemClick: () => { },
50
+ remoteSelection: false,
51
+ isDisabledSelectionVisible: () => false,
52
+ getCheckboxTooltip: () => undefined,
53
+ RowComponent: Row,
54
+ wideFirstColumn: false,
55
+ };
56
+ state = {
57
+ shortcutsScope: getUID('ring-table-'),
58
+ userSelectNone: false,
59
+ };
60
+ componentDidMount() {
61
+ document.addEventListener('mouseup', this.onMouseUp);
62
+ }
63
+ componentDidUpdate({ data, selection, onSelect, selectable, remoteSelection }) {
64
+ if (data !== this.props.data && remoteSelection) {
65
+ onSelect(selection.cloneWith({ data: this.props.data }));
66
+ }
67
+ if (!this.props.selectable && this.props.selectable !== selectable) {
68
+ onSelect(selection.resetSelection());
69
+ }
70
+ }
71
+ componentWillUnmount() {
72
+ document.removeEventListener('mouseup', this.onMouseUp);
73
+ }
74
+ onMouseDown = (e) => {
75
+ if (e.shiftKey) {
76
+ this.setState({ userSelectNone: true });
77
+ }
78
+ };
79
+ onMouseUp = () => {
80
+ if (this.state.userSelectNone) {
81
+ this.setState({ userSelectNone: false });
82
+ }
83
+ };
84
+ onRowFocus = (row) => {
85
+ const { selection, onSelect } = this.props;
86
+ onSelect(selection.focus(row));
87
+ };
88
+ onRowSelect = (row, selected) => {
89
+ const { selection, onSelect } = this.props;
90
+ if (selected) {
91
+ onSelect(selection.select(row));
92
+ }
93
+ else {
94
+ onSelect(selection.deselect(row));
95
+ }
96
+ };
97
+ onSortEnd = ({ oldIndex, newIndex }) => {
98
+ const data = arrayMove(this.props.data, oldIndex, newIndex);
99
+ this.props.onReorder({ data, oldIndex, newIndex });
100
+ };
101
+ onCheckboxChange = (e) => {
102
+ const { checked } = e.currentTarget;
103
+ const { selection, onSelect } = this.props;
104
+ if (checked) {
105
+ onSelect(selection.selectAll());
106
+ }
107
+ else {
108
+ onSelect(selection.reset());
109
+ }
110
+ this.restoreFocusWithoutScroll();
111
+ };
112
+ restoreFocusWithoutScroll = () => {
113
+ const { scrollX, scrollY } = window;
114
+ this.props.onFocusRestore();
115
+ window.scrollTo(scrollX, scrollY);
116
+ };
117
+ render() {
118
+ 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, RowComponent, renderLoader, } = this.props;
119
+ // NOTE: Do not construct new object per render because it causes all rows rerendering
120
+ const columnsArray = typeof columns === 'function' ? columns(null) : columns;
121
+ const headerProps = {
122
+ caption,
123
+ selectable,
124
+ draggable,
125
+ columns: columnsArray,
126
+ onSort,
127
+ sortKey,
128
+ sortOrder,
129
+ sticky: stickyHeader,
130
+ topStickOffset: stickyHeaderOffset,
131
+ className: this.props.headerClassName,
132
+ };
133
+ const selectedSize = selection.getSelected().size;
134
+ const allSelectedSize = selection.selectAll().getSelected().size;
135
+ headerProps.checked = selectedSize > 0 && selectedSize === allSelectedSize;
136
+ headerProps.onCheckboxChange = this.onCheckboxChange;
137
+ headerProps.checkboxDisabled = this.props.data.length === 0;
138
+ const wrapperClasses = classNames(style.tableWrapper, this.props.wrapperClassName);
139
+ const classes = classNames(this.props.className, {
140
+ [style.table]: true,
141
+ [style.wideFirstColumn]: this.props.wideFirstColumn,
142
+ [style.userSelectNone]: this.state.userSelectNone,
143
+ [style.disabledHover]: this.props.disabledHover,
144
+ });
145
+ const renderList = ({ children, props }) => {
146
+ const empty = (<tr>
147
+ <td colSpan={columnsArray.length || 1} className={style.tableMessage}>
148
+ {renderEmpty ? renderEmpty() : null}
149
+ </td>
150
+ </tr>);
151
+ const tbody = Array.isArray(children) && children.length > 0 ? children : empty;
152
+ return (<table className={classes} data-test='ring-table'>
153
+ <Header {...headerProps}/>
154
+ <tbody {...props} data-test='ring-table-body'>
155
+ {tbody}
156
+ </tbody>
157
+ </table>);
158
+ };
159
+ const renderItem = ({ value, props = {}, isDragged }) => {
160
+ if (value === null || value === undefined) {
161
+ return null;
162
+ }
163
+ const { ref, ...restProps } = props;
164
+ const row = (<RowComponent 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)} cellClassName={this.props.cellClassName} {...restProps} key={restProps.key ?? getItemKey(value)}/>);
165
+ return isDragged ? (<table style={{ ...props.style }} className={style.draggingTable}>
166
+ <tbody>{row}</tbody>
167
+ </table>) : (row);
168
+ };
169
+ return (<div className={wrapperClasses} data-test='ring-table-wrapper' ref={this.props.innerRef}>
170
+ {focused && <Shortcuts map={this.props.shortcutsMap} scope={this.state.shortcutsScope}/>}
171
+
172
+ {/* Handler detects that user holds Shift key */}
173
+ <div role='presentation' onMouseDown={this.onMouseDown}>
174
+ {draggable ? (<List values={data} renderList={renderList} renderItem={renderItem} onChange={this.onSortEnd}/>) : (renderList({ children: data.map((value, index) => renderItem({ value, index })) }))}
175
+ </div>
176
+
177
+ {loading && (<div className={style.loadingOverlay}>
178
+ {renderLoader ? renderLoader(loaderClassName) : <Loader className={loaderClassName}/>}
179
+ </div>)}
180
+ </div>);
181
+ }
182
+ }
183
+ const getContainer = () => disableHoverHOC(selectionShortcutsHOC(focusSensorHOC(Table)));
184
+ // eslint-disable-next-line react/no-multi-comp
185
+ export default class TableContainer extends Component {
186
+ // https://stackoverflow.com/a/53882322/6304152
187
+ Table = getContainer();
188
+ render() {
189
+ return <this.Table {...this.props}/>;
190
+ }
191
+ }
@@ -9,7 +9,6 @@ export declare enum Type {
9
9
  SEPARATOR = 0,
10
10
  LINK = 1,
11
11
  ITEM = 2,
12
- HINT = 3,// doesn't work, TODO remove in 8.0
13
12
  CUSTOM = 4,
14
13
  TITLE = 5,
15
14
  MARGIN = 6
@@ -6,7 +6,6 @@ export var Type;
6
6
  Type[Type["SEPARATOR"] = 0] = "SEPARATOR";
7
7
  Type[Type["LINK"] = 1] = "LINK";
8
8
  Type[Type["ITEM"] = 2] = "ITEM";
9
- Type[Type["HINT"] = 3] = "HINT";
10
9
  Type[Type["CUSTOM"] = 4] = "CUSTOM";
11
10
  Type[Type["TITLE"] = 5] = "TITLE";
12
11
  Type[Type["MARGIN"] = 6] = "MARGIN";
@@ -43,10 +43,6 @@ export interface ListProps<T = unknown> {
43
43
  maxHeight?: number | null | undefined;
44
44
  activeIndex?: number | null | undefined;
45
45
  useMouseUp?: boolean | null | undefined;
46
- /**
47
- * @deprecated No longer used. Visibility is detected automatically via IntersectionObserver. Will be removed in Ring UI 8.0.
48
- */
49
- visible?: boolean | null | undefined;
50
46
  disableMoveOverflow?: boolean | null | undefined;
51
47
  compact?: boolean | null | undefined;
52
48
  disableScrollToActive?: boolean | null | undefined;
@@ -7,9 +7,9 @@ const reactRoot = createRoot(containerElement);
7
7
  * Renders LoginDialog into virtual node to skip maintaining container
8
8
  */
9
9
  function renderLoginDialog(props) {
10
- reactRoot.render(<ControlsHeightContext.Provider value={getGlobalControlsHeight()}>
10
+ reactRoot.render(<ControlsHeightContext value={getGlobalControlsHeight()}>
11
11
  <LoginDialog {...props}/>
12
- </ControlsHeightContext.Provider>);
12
+ </ControlsHeightContext>);
13
13
  }
14
14
  function noop() { }
15
15
  export default function showAuthDialog(props = { onCancel: noop }) {
@@ -1,13 +1,14 @@
1
- import { type HTMLAttributes, type ReactNode } from 'react';
1
+ import { type HTMLAttributes, type Ref, type ReactNode } from 'react';
2
2
  interface ComplexConfig {
3
3
  target: string | Element | undefined;
4
4
  cssPositioning?: boolean;
5
5
  }
6
6
  export declare const PopupTargetContext: import("react").Context<string | Element | ComplexConfig | undefined>;
7
7
  export interface PopupTargetProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
8
+ ref?: Ref<HTMLDivElement>;
8
9
  id: string;
9
10
  children: ReactNode | ((target: ReactNode) => ReactNode);
10
11
  }
11
12
  export declare function normalizePopupTarget(value: string | Element | undefined | ComplexConfig): string | Element | undefined;
12
- export declare const PopupTarget: import("react").ForwardRefExoticComponent<PopupTargetProps & import("react").RefAttributes<HTMLDivElement>>;
13
+ export declare function PopupTarget({ ref, id, children, ...restProps }: PopupTargetProps): import("react").JSX.Element;
13
14
  export {};
@@ -1,13 +1,11 @@
1
- import { createContext, forwardRef } from 'react';
1
+ import { createContext } from 'react';
2
2
  export const PopupTargetContext = createContext(undefined);
3
3
  export function normalizePopupTarget(value) {
4
4
  return typeof value === 'string' || value instanceof Element ? value : value?.target;
5
5
  }
6
- export const PopupTarget = forwardRef(function PopupTarget({ id, children, ...restProps }, ref) {
6
+ export function PopupTarget({ ref, id, children, ...restProps }) {
7
7
  const target = (<div {...restProps} data-portaltarget={id} ref={ref}>
8
8
  {typeof children !== 'function' && children}
9
9
  </div>);
10
- return (<PopupTargetContext.Provider value={id}>
11
- {typeof children === 'function' ? children(target) : target}
12
- </PopupTargetContext.Provider>);
13
- });
10
+ return (<PopupTargetContext value={id}>{typeof children === 'function' ? children(target) : target}</PopupTargetContext>);
11
+ }
@@ -285,5 +285,7 @@ export default class QueryAssist extends Component<QueryAssistProps> {
285
285
  render(): React.JSX.Element;
286
286
  }
287
287
  export type QueryAssistAttrs = React.JSX.LibraryManagedAttributes<typeof QueryAssist, QueryAssistProps>;
288
- export declare const RerenderableQueryAssist: React.ForwardRefExoticComponent<QueryAssistProps & React.RefAttributes<QueryAssist>>;
288
+ export declare const RerenderableQueryAssist: ({ ref, ...props }: QueryAssistProps & {
289
+ ref?: React.Ref<QueryAssist> | undefined;
290
+ }) => React.JSX.Element;
289
291
  export {};
@@ -733,7 +733,7 @@ export default class QueryAssist extends Component {
733
733
  [styles.hugePlaceholder]: huge,
734
734
  [styles.withoutGlass]: !glass || (!renderLoader && huge),
735
735
  });
736
- return (<ControlsHeightContext.Provider value={ControlsHeight.M}>
736
+ return (<ControlsHeightContext value={ControlsHeight.M}>
737
737
  <I18nContext.Consumer>
738
738
  {({ translate }) => (<div data-test={dataTests('ring-query-assist', dataTest)} className={containerClasses} role='presentation' ref={this.nodeRef}>
739
739
  {this.state.shortcuts && <Shortcuts map={this.shortcutsMap} scope={this.shortcutsScope}/>}
@@ -768,7 +768,7 @@ export default class QueryAssist extends Component {
768
768
  </div>)}
769
769
  </div>)}
770
770
  </I18nContext.Consumer>
771
- </ControlsHeightContext.Provider>);
771
+ </ControlsHeightContext>);
772
772
  }
773
773
  }
774
774
  export const RerenderableQueryAssist = rerenderHOC(QueryAssist);
@@ -1,4 +1,4 @@
1
- import { Component, type InputHTMLAttributes, type ReactNode } from 'react';
1
+ import { Component, type Ref, type InputHTMLAttributes, type ReactNode } from 'react';
2
2
  export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'> {
3
3
  value?: string | undefined;
4
4
  onChange?: ((value: string) => void) | null | undefined;
@@ -17,7 +17,7 @@ export declare class RadioItemInner extends Component<RadioItemInnerProps> {
17
17
  render(): import("react").JSX.Element;
18
18
  }
19
19
  export interface RadioItemProps extends RadioItemInnerProps {
20
+ ref?: Ref<RadioItemInner>;
20
21
  value: string;
21
22
  }
22
- declare const RadioItem: import("react").ForwardRefExoticComponent<RadioItemProps & import("react").RefAttributes<RadioItemInner>>;
23
- export default RadioItem;
23
+ export default function RadioItem({ ref, ...props }: RadioItemProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- import { Component, createContext, forwardRef } from 'react';
1
+ import { Component, createContext } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import getUID from '../global/get-uid';
4
4
  import ControlHelp from '../control-help/control-help';
@@ -28,9 +28,8 @@ export class RadioItemInner extends Component {
28
28
  </label>);
29
29
  }
30
30
  }
31
- const RadioItem = forwardRef(function RadioItem(props, ref) {
31
+ export default function RadioItem({ ref, ...props }) {
32
32
  return (<RadioContext.Consumer>
33
33
  {({ value, onChange, ...restContext }) => (<RadioItemInner ref={ref} {...restContext} checked={value !== undefined ? value === props.value : undefined} onChange={onChange ? () => onChange(props.value) : undefined} {...props}/>)}
34
34
  </RadioContext.Consumer>);
35
- });
36
- export default RadioItem;
35
+ }
@@ -1,10 +1,10 @@
1
1
  import { Component } from 'react';
2
- import { type RadioProps } from './radio-item';
2
+ import RadioItem, { type RadioProps } from './radio-item';
3
3
  /**
4
4
  * @name Radio
5
5
  */
6
6
  export default class Radio extends Component<RadioProps> {
7
- static Item: import("react").ForwardRefExoticComponent<import("./radio-item").RadioItemProps & import("react").RefAttributes<import("./radio-item").RadioItemInner>>;
7
+ static Item: typeof RadioItem;
8
8
  uid: string;
9
9
  render(): import("react").JSX.Element;
10
10
  }
@@ -8,6 +8,6 @@ export default class Radio extends Component {
8
8
  static Item = RadioItem;
9
9
  uid = getUID('ring-radio-');
10
10
  render() {
11
- return <RadioContext.Provider value={{ name: this.uid, ...this.props }}>{this.props.children}</RadioContext.Provider>;
11
+ return <RadioContext value={{ name: this.uid, ...this.props }}>{this.props.children}</RadioContext>;
12
12
  }
13
13
  }
@@ -4,7 +4,7 @@
4
4
  import { type ComponentType, type CSSProperties, PureComponent, type ReactNode, type Ref, type SyntheticEvent } from 'react';
5
5
  import * as React from 'react';
6
6
  import { type IconType } from '../icon/icon';
7
- import Popup from '../popup/popup';
7
+ import Popup, { type PopupAttrs } from '../popup/popup';
8
8
  import { type Directions } from '../popup/position';
9
9
  import List, { type SelectHandlerParams } from '../list/list';
10
10
  import Caret from '../caret/caret';
@@ -60,6 +60,7 @@ export interface SelectPopupProps<T = unknown> {
60
60
  ringPopupTarget: string | null;
61
61
  onSelectAll: (isSelectAll: boolean) => void;
62
62
  onEmptyPopupEnter: (e: KeyboardEvent) => void;
63
+ popupProps?: Partial<PopupAttrs> | undefined;
63
64
  className?: string | null | undefined;
64
65
  compact?: boolean | null | undefined;
65
66
  dir?: 'ltr' | 'rtl' | undefined;
@@ -127,7 +128,7 @@ export default class SelectPopup<T = unknown> extends PureComponent<SelectPopupP
127
128
  list?: List<T> | null;
128
129
  listRef: (el: List<T> | null) => void;
129
130
  filterRef: (el: HTMLInputElement | null) => void;
130
- composedFilterRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T_1 | null) => void>;
131
+ composedFilterRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T_1 | null) => () => void>;
131
132
  shortcutsScope: string;
132
133
  shortcutsMap: {
133
134
  tab: (event: Event) => void;
@@ -323,8 +323,8 @@ export default class SelectPopup extends PureComponent {
323
323
  right: event => this.handleNavigation(event),
324
324
  };
325
325
  render() {
326
- const { toolbar, topbar, className, multiple, hidden, isInputMode, anchorElement, minWidth, onCloseAttempt, onOutsideClick, directions, top, left, offset, style, dir, filter, } = this.props;
327
- const classes = classNames(styles.popup, className);
326
+ const { toolbar, topbar, className, multiple, hidden, isInputMode, anchorElement, minWidth, onCloseAttempt, onOutsideClick, directions, top, left, offset, style, dir, filter, popupProps, } = this.props;
327
+ const classes = classNames(styles.popup, className, popupProps?.className);
328
328
  return (<PopupTargetContext.Consumer>
329
329
  {ringPopupTarget => {
330
330
  const filterWithTags = this.getFilterWithTags();
@@ -332,7 +332,7 @@ export default class SelectPopup extends PureComponent {
332
332
  const list = this.getList(this.props.ringPopupTarget || normalizePopupTarget(ringPopupTarget));
333
333
  const bottomLine = this.getBottomLine();
334
334
  const hasContent = filterWithTags || selectAll || list || bottomLine || toolbar || topbar;
335
- return (<Popup trapFocus={false} ref={this.popupRef} hidden={hidden || !hasContent} attached={isInputMode} className={classes} dontCloseOnAnchorClick anchorElement={anchorElement} minWidth={minWidth} onCloseAttempt={onCloseAttempt} onOutsideClick={onOutsideClick} directions={directions} top={top} left={left} offset={offset} onMouseDown={this.mouseDownHandler} target={this.props.ringPopupTarget} autoCorrectTopOverflow={false} style={style} largeBorderRadius>
335
+ return (<Popup {...popupProps} trapFocus={false} ref={this.popupRef} hidden={hidden || !hasContent} attached={isInputMode} className={classes} dontCloseOnAnchorClick anchorElement={anchorElement} minWidth={minWidth} onCloseAttempt={onCloseAttempt} onOutsideClick={onOutsideClick} directions={directions} top={top} left={left} offset={offset} onMouseDown={this.mouseDownHandler} target={this.props.ringPopupTarget} autoCorrectTopOverflow={false} style={{ ...popupProps?.style, ...style }} largeBorderRadius>
336
336
  <div dir={dir}>
337
337
  {!hidden && filter && <Shortcuts map={this.shortcutsMap} scope={this.shortcutsScope}/>}
338
338
  {topbar}
@@ -1,5 +1,6 @@
1
1
  import { type ButtonHTMLAttributes, Component, type ComponentType, type CSSProperties, type HTMLAttributes, type ReactNode, type Ref, type RefCallback, type SyntheticEvent } from 'react';
2
2
  import * as React from 'react';
3
+ import { type PopupAttrs } from '../popup/popup';
3
4
  import { type SelectHandlerParams } from '../list/list';
4
5
  import { Size } from '../input/input';
5
6
  import { type LabelType } from '../control-label/control-label';
@@ -99,6 +100,7 @@ export interface BaseSelectProps<T = unknown> {
99
100
  getInitial?: (() => string) | null | undefined;
100
101
  minWidth?: number | undefined;
101
102
  popupClassName?: string | null | undefined;
103
+ popupProps?: Partial<PopupAttrs> | undefined;
102
104
  popupStyle?: CSSProperties | undefined;
103
105
  top?: number | undefined;
104
106
  left?: number | undefined;
@@ -264,7 +266,7 @@ export default class Select<T = unknown> extends Component<SelectProps<T>, Selec
264
266
  private _getAvatar;
265
267
  filter?: HTMLInputElement | null;
266
268
  filterRef: (el: HTMLInputElement | null) => void;
267
- composedFilterRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T_1 | null) => void>;
269
+ composedFilterRef: import("memoize-one").MemoizedFn<(...refs: (Ref<HTMLInputElement> | undefined)[]) => (value: T_1 | null) => () => void>;
268
270
  getShortcutsMap(): {
269
271
  enter: () => true | undefined;
270
272
  esc: (event: KeyboardEvent) => boolean | undefined;
@@ -282,5 +284,7 @@ export default class Select<T = unknown> extends Component<SelectProps<T>, Selec
282
284
  export type SingleSelectAttrs<T = unknown> = React.JSX.LibraryManagedAttributes<typeof Select, SingleSelectProps<T>>;
283
285
  export type MultipleSelectAttrs<T = unknown> = React.JSX.LibraryManagedAttributes<typeof Select, MultipleSelectProps<T>>;
284
286
  export type SelectAttrs<T = unknown> = React.JSX.LibraryManagedAttributes<typeof Select, SelectProps<T>>;
285
- export declare const RerenderableSelect: React.ForwardRefExoticComponent<Omit<any, "ref"> & React.RefAttributes<any>>;
287
+ export declare const RerenderableSelect: ({ ref, ...props }: Omit<any, "ref"> & {
288
+ ref?: Ref<any> | undefined;
289
+ }) => React.JSX.Element;
286
290
  export {};
@@ -47,9 +47,7 @@ const getStyle = memoize((iconsLength) => ({
47
47
  }));
48
48
  const isInputMode = (type) => type === Type.INPUT || type === Type.INPUT_WITHOUT_CONTROLS;
49
49
  function getLowerCaseLabel(item) {
50
- if (List.isItemType(List.ListProps.Type.SEPARATOR, item) ||
51
- List.isItemType(List.ListProps.Type.HINT, item) ||
52
- typeof item.label !== 'string') {
50
+ if (List.isItemType(List.ListProps.Type.SEPARATOR, item) || typeof item.label !== 'string') {
53
51
  return null;
54
52
  }
55
53
  return item.label.toLowerCase();
@@ -456,7 +454,7 @@ export default class Select extends Component {
456
454
  else if (!shownData.length) {
457
455
  message = this.props.notFoundMessage ?? translate('noOptionsFound');
458
456
  }
459
- return (<SelectPopup data={_shownData} message={message} toolbar={showPopup && this.getToolbar()} topbar={this.getTopbar()} loading={this.props.loading} activeIndex={activeIndex} hidden={!showPopup} ref={this.popupRef} maxHeight={this.props.maxHeight} minWidth={this.props.minWidth} directions={this.props.directions} className={this.props.popupClassName} style={this.props.popupStyle} top={this.props.top} left={this.props.left} offset={this.props.offset} filter={this.isInputMode() ? false : this.props.filter} // disable popup filter in INPUT mode
457
+ return (<SelectPopup data={_shownData} message={message} toolbar={showPopup && this.getToolbar()} topbar={this.getTopbar()} loading={this.props.loading} activeIndex={activeIndex} hidden={!showPopup} ref={this.popupRef} maxHeight={this.props.maxHeight} minWidth={this.props.minWidth} directions={this.props.directions} popupProps={this.props.popupProps} className={this.props.popupClassName} style={this.props.popupStyle} top={this.props.top} left={this.props.left} offset={this.props.offset} filter={this.isInputMode() ? false : this.props.filter} // disable popup filter in INPUT mode
460
458
  filterIcon={this.props.filterIcon} filterRef={this.props.filterRef} multiple={this.props.multiple} filterValue={this.state.filterValue} anchorElement={anchorElement} onCloseAttempt={this._onCloseAttempt} onOutsideClick={this.props.onOutsideClick} onSelect={this._listSelectHandler} onSelectAll={this._listSelectAllHandler} onFilter={this._filterChangeHandler} onClear={this.clearFilter} onLoadMore={this.props.onLoadMore} isInputMode={this.isInputMode()} selected={this.state.selected} tags={this.props.tags} compact={this.props.compact} renderOptimization={this.props.renderOptimization} ringPopupTarget={this.props.ringPopupTarget} disableMoveOverflow={this.props.disableMoveOverflow} disableScrollToActive={this.props.disableScrollToActive} dir={this.props.dir} onEmptyPopupEnter={this.onEmptyPopupEnter} listId={this.listId} preventListOverscroll={this.props.preventListOverscroll}/>);
461
459
  }}
462
460
  </I18nContext.Consumer>);
@@ -0,0 +1,86 @@
1
+ @import '../global/variables.css';
2
+
3
+ .toolbar {
4
+ display: inline-flex;
5
+ align-items: center;
6
+
7
+ box-sizing: border-box;
8
+ max-width: 100%;
9
+ height: calc(var(--ring-unit) * 5);
10
+ padding: 10px calc(var(--ring-unit) * 2);
11
+
12
+ pointer-events: auto;
13
+
14
+ color: var(--ring-white-text-color);
15
+ border-radius: var(--ring-border-radius-large);
16
+ background-color: var(--ring-sidebar-background-color);
17
+ box-shadow:
18
+ 0 2px 8px rgb(0 28 54 / 10%),
19
+ 0 1px 2px rgb(0 28 54 / 4%);
20
+
21
+ line-height: var(--ring-line-height);
22
+ gap: calc(var(--ring-unit) * 2);
23
+ }
24
+
25
+ .content {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: calc(var(--ring-unit) * 3);
29
+ }
30
+
31
+ .selectAll {
32
+ flex: none;
33
+ }
34
+
35
+ .actions {
36
+ display: flex;
37
+ align-items: center;
38
+ gap: calc(var(--ring-unit) * 2);
39
+
40
+ min-width: 0;
41
+ }
42
+
43
+ .closeAction {
44
+ flex: none;
45
+ }
46
+
47
+ .separator {
48
+ flex: none;
49
+
50
+ width: 1px;
51
+ height: calc(var(--ring-unit) * 2);
52
+ margin-inline: var(--ring-unit);
53
+
54
+ background-color: var(--ring-line-color);
55
+ }
56
+
57
+ .compact {
58
+ min-width: 0;
59
+ max-width: 100%;
60
+ padding-inline: 12px;
61
+ }
62
+
63
+ .compact .content {
64
+ min-width: 0;
65
+ gap: var(--ring-unit);
66
+ }
67
+
68
+ .compact .label {
69
+ overflow: hidden;
70
+
71
+ flex: 1 1 auto;
72
+
73
+ min-width: 0;
74
+
75
+ white-space: nowrap;
76
+
77
+ text-overflow: ellipsis;
78
+ }
79
+
80
+ .compact .actions {
81
+ flex-shrink: 1;
82
+ }
83
+
84
+ .compact .separator {
85
+ margin-inline: 2px;
86
+ }
@@ -0,0 +1,11 @@
1
+ import { type ComponentPropsWithRef, type ReactNode } from 'react';
2
+ export interface SelectionToolbarProps extends ComponentPropsWithRef<'div'> {
3
+ label: ReactNode;
4
+ selectAll?: ReactNode;
5
+ closeAction: ReactNode;
6
+ compact?: boolean;
7
+ 'data-test'?: string | null;
8
+ }
9
+ export declare function SelectionToolbar({ ref, label, selectAll, closeAction, compact, className, children, 'data-test': dataTest, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...restProps }: SelectionToolbarProps): import("react").JSX.Element;
10
+ export declare function SelectionToolbarSeparator(): import("react").JSX.Element;
11
+ export default SelectionToolbar;
@@ -0,0 +1,23 @@
1
+ import { useId } from 'react';
2
+ import classNames from 'classnames';
3
+ import dataTests from '../global/data-tests';
4
+ import Theme, { ThemeProvider } from '../global/theme';
5
+ import styles from './selection-toolbar.css';
6
+ export function SelectionToolbar({ ref, label, selectAll, closeAction, compact, className, children, 'data-test': dataTest, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...restProps }) {
7
+ const labelId = useId();
8
+ const hasSelectAll = selectAll != null;
9
+ return (<ThemeProvider {...restProps} ref={ref} theme={Theme.DARK} role='group' aria-label={ariaLabel} aria-labelledby={ariaLabelledBy ?? (ariaLabel == null ? labelId : undefined)} data-test={dataTests('ring-selection-toolbar', dataTest)} className={classNames(styles.toolbar, { [styles.compact]: compact }, className)}>
10
+ <div className={styles.content}>
11
+ <span id={labelId} className={styles.label}>
12
+ {label}
13
+ </span>
14
+ {hasSelectAll && <span className={styles.selectAll}>{selectAll}</span>}
15
+ <div className={styles.actions}>{children}</div>
16
+ </div>
17
+ <div className={styles.closeAction}>{closeAction}</div>
18
+ </ThemeProvider>);
19
+ }
20
+ export function SelectionToolbarSeparator() {
21
+ return <span role='separator' aria-orientation='vertical' className={styles.separator}/>;
22
+ }
23
+ export default SelectionToolbar;
@@ -1,11 +1,10 @@
1
- import { Fragment, useEffect, useRef, useState } from 'react';
1
+ import { Fragment, useEffect, useEffectEvent, useRef, useState } from 'react';
2
2
  import * as React from 'react';
3
3
  import classNames from 'classnames';
4
4
  import { isArray } from '../global/typescript-utils';
5
5
  import Shortcuts from '../shortcuts/shortcuts';
6
6
  import getUID from '../global/get-uid';
7
7
  import { adjustValues, calculateMarks, calculateValue, HUNDRED, toPercent, toRange, validateValue } from './slider.utils';
8
- import useEventCallback from '../global/use-event-callback';
9
8
  import styles from './slider.css';
10
9
  export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1, disabled, marks, showTicks, showTag, className, renderTag, onChange, }) => {
11
10
  const ref = useRef(null);
@@ -86,7 +85,7 @@ export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1,
86
85
  setIsDragging(true);
87
86
  previouslyDragged.current = false;
88
87
  };
89
- const handleMouseUp = useEventCallback(({ pageX }) => {
88
+ const handleMouseUp = useEffectEvent(({ pageX }) => {
90
89
  const nextValues = adjustValues(validValues, ref, draggedIndex, pageX, max, min, validStep);
91
90
  if (nextValues[0] > nextValues[1]) {
92
91
  nextValues.reverse();
@@ -96,7 +95,7 @@ export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1,
96
95
  setIsDragging(false);
97
96
  previouslyDragged.current = true;
98
97
  });
99
- const handleMouseMove = useEventCallback(({ pageX }) => {
98
+ const handleMouseMove = useEffectEvent(({ pageX }) => {
100
99
  const nextValues = adjustValues(validValues, ref, draggedIndex, pageX, max, min, validStep);
101
100
  if (nextValues[0] > nextValues[1]) {
102
101
  nextValues.reverse();
@@ -120,7 +119,7 @@ export const Slider = ({ defaultValue, value, min = 0, max = HUNDRED, step = 1,
120
119
  window.removeEventListener('mousemove', handleMouseMove);
121
120
  window.removeEventListener('mouseup', handleMouseUp);
122
121
  };
123
- }, [isDragging, disabled, handleMouseMove, handleMouseUp]);
122
+ }, [isDragging, disabled]);
124
123
  return (<div ref={ref} role='presentation' // contains interactive elements
125
124
  className={classNames(styles.slider, className, {
126
125
  [styles.disabled]: disabled,
@@ -2,6 +2,7 @@ import { type HTMLAttributes, type ReactNode } from 'react';
2
2
  import * as React from 'react';
3
3
  export declare const FOCUSABLE_ELEMENTS = "input, button, select, textarea, a[href], *[tabindex]:not([data-trap-button]):not([data-scrollable-container])";
4
4
  export interface TabTrapProps extends HTMLAttributes<HTMLElement> {
5
+ ref?: React.Ref<TabTrapObject>;
5
6
  children: ReactNode;
6
7
  trapDisabled?: boolean;
7
8
  autoFocusFirst?: boolean;
@@ -11,8 +12,7 @@ export interface TabTrapProps extends HTMLAttributes<HTMLElement> {
11
12
  /**
12
13
  * @name TabTrap
13
14
  */
14
- interface TabTrap {
15
+ export interface TabTrapObject {
15
16
  node: HTMLElement | null;
16
17
  }
17
- declare const TabTrap: React.ForwardRefExoticComponent<TabTrapProps & React.RefAttributes<TabTrap>>;
18
- export default TabTrap;
18
+ export default function TabTrap({ ref, children, trapDisabled, autoFocusFirst, focusBackOnClose, focusBackOnExit, ...restProps }: TabTrapProps): React.JSX.Element;