@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
@@ -1,191 +1,327 @@
1
- /**
2
- * @name Table
3
- */
4
- import { Component, PureComponent } from 'react';
5
- import * as React from 'react';
1
+ import React, { Fragment, useRef } from 'react';
6
2
  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 './table.css';
3
+ import { SpacerRow, useVirtualItems, VirtualizationContext } from './internal/virtualization';
4
+ import { DefaultItemRenderer } from './default-item-renderer';
5
+ import { defaultRowHeight, TablePropsContext } from './table-const';
6
+ import { focusWithTemporaryTabIndex } from '../global/focus-with-temporary-tabindex';
7
+ import { ReorderAnimationContext, useReorderAnimationContextValue } from './internal/reorder-animation-context';
8
+ import { useComposedRef } from '../global/compose-refs';
9
+ import { TableHeader } from './internal/table-header';
10
+ import { keyboardFocusableAttrName } from './table-primitives';
11
+ import { isWithinNavigableElement } from '../global/is-within-navigable-element';
12
+ import { ReorderLayoutContext, useReorderLayoutContextValue } from './internal/reorder-layout-context';
13
+ import styles from './table.css';
17
14
  /**
18
- * Interactive table with selection and keyboard navigation support.
15
+ * Table component replacing the tables in the `legacy-table` folder.
16
+ *
17
+ * This documentation provides an overview of the most common usage patterns.
18
+ * See individual props and exported components for detailed behavior.
19
+ *
20
+ * ## Minimal usage
21
+ *
22
+ * You need the following props:
23
+ * - `data`
24
+ * - `getKey`
25
+ * - `columns`
26
+ * - `key`
27
+ * - `name` (optional but needed in most cases)
28
+ * - `renderCell` (optional but needed in most cases)
29
+ *
30
+ * ## Item rendering
31
+ *
32
+ * If `renderItem` is not specified, each item is rendered using
33
+ * `DefaultItemRenderer` (from `table/default-item-renderer`)
34
+ * as if the following code were used:
35
+ *
36
+ * ```tsx
37
+ * <Table
38
+ * renderItem={(_item, index, _items) => (
39
+ * <DefaultItemRenderer index={index} />
40
+ * )}
41
+ * />
42
+ * ```
43
+ *
44
+ * `DefaultItemRenderer` renders a table row using the column definitions
45
+ * (`Column.renderCell`) and provides built-in support for features such as
46
+ * selection, keyboard navigation, and virtualization. It also accepts all
47
+ * standard `tr` attributes, including `ref`.
48
+ *
49
+ * Use `renderItem` to configure `DefaultItemRenderer` for each item:
50
+ *
51
+ * ```tsx
52
+ * <Table
53
+ * renderItem={(item, index, items) => (
54
+ * <DefaultItemRenderer
55
+ * index={index}
56
+ * keyboardFocusable
57
+ * className='my-item'
58
+ * onClick={e => handleClick(e, item, items)}
59
+ * />
60
+ * )}
61
+ * />
62
+ * ```
63
+ *
64
+ * If you need complete control over rendering, `renderItem` can instead
65
+ * return your own table rows. See "Custom item rendering" below.
66
+ *
67
+ * ## Selection
68
+ *
69
+ * Selection is typically implemented using the following props
70
+ * of the `DefaultItemRenderer`:
71
+ *
72
+ * - `clickable`
73
+ * - `selected`
74
+ * - `onClick` or `onPointerUp`, etc.
75
+ *
76
+ * The following utilities (from `global`) may come in handy:
77
+ *
78
+ * - `TableSelection` class to manage selection state
79
+ * - An alternative approach is to keep a `selected` field on each item
80
+ * - `isWithinInteractiveElement()` to check if a click was made on a control
81
+ * or on "empty space"
82
+ *
83
+ * ```tsx
84
+ * <Table
85
+ * renderItem={(item, index) => (
86
+ * <DefaultItemRenderer
87
+ * index={index}
88
+ * clickable
89
+ * selected={selection.isSelected(item)}
90
+ * onClick={e => {
91
+ * if (!isWithinInteractiveElement(e)) {
92
+ * setSelection(selection.toggleSelection(item));
93
+ * }
94
+ * }}
95
+ * />
96
+ * )}
97
+ * />
98
+ * ```
99
+ *
100
+ * Note that for accessibility reasons, you should have a cell with a checkbox
101
+ * to display and toggle item selection.
102
+ *
103
+ * ## Row focus
104
+ *
105
+ * The table implements the ["roving tabindex"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Guides/Keyboard-navigable_JavaScript_widgets#technique_1_roving_tabindex)
106
+ * technique to focus rows with the up/down arrow keys.
107
+ * Rows can also be focused on click or other pointer events.
108
+ * To support it, use the following props of the `DefaultItemRenderer`:
109
+ *
110
+ * - `keyboardFocusable`
111
+ * - `clickable`, if you want to react to hover
112
+ * - `onClick`, if you want to focus on click
113
+ *
114
+ * Useful utils:
115
+ * - `focusWithTemporaryTabIndex()` from `global` to focus a row temporarily
116
+ * patching its `tabindex`.
117
+ *
118
+ * ```tsx
119
+ * <Table
120
+ * renderItem={(item, index) => (
121
+ * <DefaultItemRenderer
122
+ * index={index}
123
+ * clickable
124
+ * keyboardFocusable
125
+ * onClick={e => {
126
+ * if (!isWithinInteractiveElement(e)) {
127
+ * focusWithTemporaryTabIndex(e.currentTarget);
128
+ * }
129
+ * }}
130
+ * />
131
+ * )}
132
+ * />
133
+ * ```
134
+ *
135
+ * Note that the table does not implement standard accessibility patterns such
136
+ * as `grid` or `treegrid`, so row focus is not announced by screen readers.
137
+ * Make sure all essential actions remain available without row focus, for
138
+ * example via standard Tab navigation.
139
+ *
140
+ * ## Sorting
141
+ *
142
+ * You need the following to support sorting:
143
+ *
144
+ * - Set `Column.sortOrder` to `'none'`, `'ascending'` or `'descending'`
145
+ * to render the sort button, `aria-sort`, and indicate the current
146
+ * sort order.
147
+ * - Handle `TableProps.onSort` callback in the client code.
148
+ *
149
+ * ## Deleting columns
150
+ *
151
+ * You need the following to support deleting columns:
152
+ *
153
+ * - Set `Column.deletable` to `true`. This will render a delete button in the
154
+ * column header.
155
+ * - Make sure the `column` has a proper `name` or `key` prop, which will be
156
+ * automatically included in the aria-label of the column delete button.
157
+ * - Handle `TableProps.onColumnDelete` callback in the client code. It is
158
+ * expected to update `columns` by removing the corresponding column.
159
+ *
160
+ * ## Moving columns
161
+ *
162
+ * - Set `Column.canReorder` to `true` or to predicate specifying possible
163
+ * insertion targets.
164
+ * This will render a reorder button in the column header.
165
+ * - Make sure the `column` has a proper `name` or `key` prop, which will be
166
+ * automatically included in the aria-label of the column reorder button.
167
+ * - Handle `TableProps.onColumnReorder` callback in the client code. It is
168
+ * expected to update `columns` by moving the corresponding column to the
169
+ * new position.
170
+ *
171
+ * ## Item reorder
172
+ *
173
+ * To allow the user to reorder rows by dragging:
174
+ *
175
+ * - Place `ItemReorderHandle` (from `table/table-primitives`) anywhere inside
176
+ * a cell. It renders a drag icon button the user can grab to reorder the row.
177
+ * - Handle `TableProps.onItemReorder`. It is expected to update `data` by
178
+ * moving the item to the new position.
179
+ * - Optionally, set `TableProps.canReorderItem` to restrict which positions
180
+ * an item may be dropped into.
181
+ *
182
+ * By default, dragging shows a drag frame (a border around the dragged row)
183
+ * and an insertion indicator (a line between rows showing where the item will
184
+ * land). To implement fully custom drag visuals, set `noDragFrame` and
185
+ * `noHandleTranslate` on `ItemReorderHandle` and use its `onUserDrag` callback
186
+ * to track the drag lifecycle.
187
+ *
188
+ * ## Row virtualization
189
+ *
190
+ * To render only rows near the viewport while replacing off-screen rows with
191
+ * spacers, use:
192
+ *
193
+ * - `virtualizeRows` prop set to `true`
194
+ * - `scrollerRef` — required when the scrollable container is not the whole
195
+ * document
196
+ * - `estimateHeight` — recommended when rows are expected to be taller than
197
+ * the default height (e.g. multiline or custom content)
198
+ * - Fine-tuning props: `lookaheadPx`, `retentionMarginPx`,
199
+ * `minScrollAndResizeDeltaPx`
200
+ *
201
+ * ## Custom item rendering
202
+ *
203
+ * Use the `renderItem` prop to render an item in a completely custom way.
204
+ * The prop is expected to return one or more table rows for the item.
205
+ * Use `TableRow` and `TableCell` from `table/table-primitives` to apply
206
+ * the default row and cell styles.
207
+ *
208
+ * ### Focus
209
+ *
210
+ * Just like `DefaultItemRenderer`, `TableRow` accepts the
211
+ * `keyboardFocusable` prop.
212
+ *
213
+ * Focusable rows rendered by either component form a single keyboard
214
+ * navigation sequence.
215
+ *
216
+ * ### Virtualization
217
+ *
218
+ * If `Table.virtualizeRows` is set to `true`, you need to handle visibility
219
+ * for your custom-rendered component yourself with the
220
+ * `useItemVirtualization()` hook (from `table/item-virtualization`). The hook
221
+ * allows observing the intersection of one or multiple elements rendered for
222
+ * the item, and, based on their intersection status, reporting the item as
223
+ * eligible for virtualization.
224
+ *
225
+ * If you use `DefaultItemRenderer` as part of your custom row renderer,
226
+ * set the `noItemVirtualization` prop to `true`, otherwise it will also try
227
+ * to control the virtualization, possibly reporting incorrect item height.
228
+ *
229
+ * ### Item reorder
230
+ *
231
+ * If `TableProps.onItemReorder` is set and your item spans multiple rows, call
232
+ * `useReorderItemLayout()` (from `table/reorder-item-layout`) to register the
233
+ * item's boundaries so the insertion indicator and insertion point calculation
234
+ * are correct. If `DefaultItemRenderer` is included inside your custom renderer,
235
+ * set its `noReorderLayout` prop to `true` to prevent double registration.
236
+ *
237
+ * ### Reorder animation
238
+ *
239
+ * After a column or item is reordered, the table briefly highlights the moved
240
+ * element. To apply the same animation in your custom-rendered rows, use
241
+ * `useReorderAnimation()` (from `table/reorder-animation`) to get information
242
+ * about the currently animated column or item.
19
243
  */
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 }));
244
+ export default function Table(props) {
245
+ const { data, columns, getKey, noHeader, stickyHeader, onSort, onColumnDelete, onColumnReorder, noColumnReorderAnimation, canReorderItem, onItemReorder, noItemReorderAnimation, renderItem, virtualizeRows = false, scrollerRef, estimateHeight = () => defaultRowHeight,
246
+ // eslint-disable-next-line no-magic-numbers
247
+ lookaheadPx = 400,
248
+ // eslint-disable-next-line no-magic-numbers
249
+ retentionMarginPx = 450,
250
+ // eslint-disable-next-line no-magic-numbers
251
+ minScrollAndResizeDeltaPx = 50, columnEditing, onColumnEditingRequest, columnEditButton, theadClassName, theadTrClassName, tbodyClassName, ref: userRef, className, ...restProps } = props;
252
+ const localRef = useRef(null);
253
+ const reorderAnimationContextValue = useReorderAnimationContextValue({
254
+ noColumnReorderAnimation,
255
+ noItemReorderAnimation,
256
+ tableRef: localRef,
257
+ data,
258
+ columns,
259
+ });
260
+ function handleRowNavigation(e) {
261
+ if (e.defaultPrevented || isWithinNavigableElement(e.target))
262
+ return;
263
+ const arrowUp = e.key === 'ArrowUp';
264
+ const arrowDown = e.key === 'ArrowDown';
265
+ if (!arrowUp && !arrowDown)
266
+ return;
267
+ const currentRow = e.target.closest('tr');
268
+ if (currentRow?.parentElement?.parentElement !== localRef.current) {
269
+ return;
66
270
  }
67
- if (!this.props.selectable && this.props.selectable !== selectable) {
68
- onSelect(selection.resetSelection());
271
+ let candidate = currentRow;
272
+ while (candidate) {
273
+ candidate = (arrowUp ? candidate.previousElementSibling : candidate.nextElementSibling);
274
+ if (candidate?.hasAttribute(keyboardFocusableAttrName)) {
275
+ focusWithTemporaryTabIndex(candidate);
276
+ e.preventDefault();
277
+ return;
278
+ }
69
279
  }
70
280
  }
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;
281
+ const { virtualItems, virtualizationContextValue } = useVirtualItems({
282
+ enabled: virtualizeRows,
283
+ data,
284
+ scrollerRef,
285
+ tableRef: localRef,
286
+ estimateHeight,
287
+ lookaheadPx,
288
+ retentionMarginPx,
289
+ minScrollAndResizeDeltaPx,
290
+ });
291
+ const itemReorderLayoutContextValue = useReorderLayoutContextValue();
292
+ return (<TablePropsContext value={props}>
293
+ <ReorderAnimationContext value={reorderAnimationContextValue}>
294
+ <table className={classNames(styles.table, className)} ref={useComposedRef(userRef, localRef)} {...restProps}>
295
+ <TableHeader />
296
+ {/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions */}
297
+ <tbody className={tbodyClassName} onKeyDown={handleRowNavigation}>
298
+ <VirtualizationContext value={virtualizationContextValue}>
299
+ <ReorderLayoutContext value={itemReorderLayoutContextValue}>
300
+ {(virtualizeRows ? virtualItems : data).map((item, index) => {
301
+ let dataItem;
302
+ let dataItemIndex;
303
+ if (virtualizeRows) {
304
+ const virtualItem = item;
305
+ if (virtualItem.type === 'spacer') {
306
+ return <SpacerRow key={virtualItem.key} spacer={virtualItem} colSpan={columns.length}/>;
307
+ }
308
+ dataItemIndex = virtualItem.index;
309
+ if (dataItemIndex < 0 || dataItemIndex >= data.length)
310
+ return null;
311
+ dataItem = data[dataItemIndex];
162
312
  }
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
- }
313
+ else {
314
+ dataItem = item;
315
+ dataItemIndex = index;
316
+ }
317
+ return (<Fragment key={getKey(dataItem, dataItemIndex, data)}>
318
+ {renderItem ? (renderItem(dataItem, dataItemIndex, data)) : (<DefaultItemRenderer index={dataItemIndex}/>)}
319
+ </Fragment>);
320
+ })}
321
+ </ReorderLayoutContext>
322
+ </VirtualizationContext>
323
+ </tbody>
324
+ </table>
325
+ </ReorderAnimationContext>
326
+ </TablePropsContext>);
191
327
  }
@@ -110,6 +110,8 @@ export default class TagsInput extends PureComponent<TagsInputProps, TagsInputSt
110
110
  selectRef: (el: Select | null) => void;
111
111
  render(): React.JSX.Element;
112
112
  }
113
- export declare const RerenderableTagsInput: React.ForwardRefExoticComponent<TagsInputProps & React.RefAttributes<TagsInput>>;
113
+ export declare const RerenderableTagsInput: ({ ref, ...props }: TagsInputProps & {
114
+ ref?: React.Ref<TagsInput> | undefined;
115
+ }) => React.JSX.Element;
114
116
  export type TagsInputAttrs = React.JSX.LibraryManagedAttributes<typeof TagsInput, TagsInputProps>;
115
117
  export {};
@@ -8,7 +8,8 @@ interface Context {
8
8
  onNestedTooltipHide: () => void;
9
9
  }
10
10
  declare const TooltipContext: React.Context<Context | undefined>;
11
- export interface TooltipProps extends Omit<AllHTMLAttributes<HTMLSpanElement>, 'title'> {
11
+ export interface TooltipProps extends Omit<AllHTMLAttributes<HTMLElement>, 'title'> {
12
+ TagName?: 'span' | 'div' | null | undefined;
12
13
  delay?: number | null | undefined;
13
14
  selfOverflowOnly?: boolean | null | undefined;
14
15
  popupProps?: Partial<PopupAttrs> | null | undefined;
@@ -129,19 +129,20 @@ export default class Tooltip extends Component {
129
129
  this.setState({ showNestedPopup: false });
130
130
  };
131
131
  render() {
132
- const { children, 'data-test': dataTest, title, delay, theme, selfOverflowOnly, popupProps, long, hide, ...restProps } = this.props;
132
+ const { children, TagName, 'data-test': dataTest, title, delay, theme, selfOverflowOnly, popupProps, long, hide, ...restProps } = this.props;
133
133
  const ariaProps = typeof title === 'string' && Tooltip.isShow({ title, hide }) ? { 'aria-label': title, role: 'tooltip' } : {};
134
134
  const { onNestedTooltipShow, onNestedTooltipHide } = this;
135
+ const WrapperElement = TagName || 'span';
135
136
  const popup = (<Popup trapFocus={false} anchorElement={this.containerNode} hidden={!this.state.showPopup || this.state.showNestedPopup} onCloseAttempt={this.hidePopup} maxHeight={400} attached={false} onMouseOut={this.hideIfMovedOutsidePopup} top={4} dontCloseOnAnchorClick ref={this.popupRef} {...popupProps} className={classNames(styles.tooltip, { [styles.long]: long, [styles.inheritedTheme]: theme === 'inherit' }, popupProps?.className)}>
136
137
  {title}
137
138
  </Popup>);
138
- return (<TooltipContext.Provider value={{ onNestedTooltipShow, onNestedTooltipHide }}>
139
- <span {...ariaProps} {...restProps} ref={this.containerRef} data-test={dataTests('ring-tooltip', dataTest)} data-test-title={typeof title === 'string' ? title : undefined}>
139
+ return (<TooltipContext value={{ onNestedTooltipShow, onNestedTooltipHide }}>
140
+ <WrapperElement {...ariaProps} {...restProps} ref={this.containerRef} data-test={dataTests('ring-tooltip', dataTest)} data-test-title={typeof title === 'string' ? title : undefined}>
140
141
  {children}
141
142
  {theme === 'inherit' ? (popup) : (<ThemeProvider theme={theme} passToPopups WrapperComponent={props => <span {...props}/>}>
142
143
  {popup}
143
144
  </ThemeProvider>)}
144
- </span>
145
- </TooltipContext.Provider>);
145
+ </WrapperElement>
146
+ </TooltipContext>);
146
147
  }
147
148
  }
@@ -1,4 +1,4 @@
1
- import { type ReactNode } from 'react';
1
+ import { type ReactNode, type Ref } from 'react';
2
2
  export type UploadVariant = 'empty' | 'error' | 'success';
3
3
  interface Props {
4
4
  className?: string;
@@ -10,10 +10,11 @@ interface Props {
10
10
  accept?: HTMLInputElement['accept'];
11
11
  disabled?: boolean;
12
12
  variant?: UploadVariant;
13
+ ref?: Ref<UploadHandle>;
13
14
  children?: ReactNode;
14
15
  }
15
16
  export interface UploadHandle {
16
17
  openFilePicker: () => void;
17
18
  }
18
- export declare const Upload: import("react").ForwardRefExoticComponent<Props & import("react").RefAttributes<UploadHandle>>;
19
- export default Upload;
19
+ export default function UploadInner({ children, className, onFilesSelected, onFilesRejected, validate, variant, multiple, renderIcon, accept, disabled, ref, }: Props): import("react").JSX.Element;
20
+ export {};
@@ -1,13 +1,13 @@
1
- import { forwardRef, useImperativeHandle, useRef, useState, } from 'react';
1
+ import { useImperativeHandle, useRef, useState } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import attachmentIcon from '@jetbrains/icons/attachment';
4
4
  import Icon from '../icon';
5
5
  import styles from './upload.css';
6
6
  const defaultRenderIcon = () => <Icon className={styles.attachmentIcon} glyph={attachmentIcon}/>;
7
- function UploadInner({ children, className, onFilesSelected, onFilesRejected, validate = () => true, variant = 'empty', multiple, renderIcon = defaultRenderIcon, accept, disabled, forwardedRef, }) {
7
+ export default function UploadInner({ children, className, onFilesSelected, onFilesRejected, validate = () => true, variant = 'empty', multiple, renderIcon = defaultRenderIcon, accept, disabled, ref, }) {
8
8
  const fileInputRef = useRef(null);
9
9
  const [dragOver, setDragOver] = useState(false);
10
- useImperativeHandle(forwardedRef, () => ({ openFilePicker: () => fileInputRef.current?.click() }), []);
10
+ useImperativeHandle(ref, () => ({ openFilePicker: () => fileInputRef.current?.click() }), []);
11
11
  const handleSelectedFiles = (files) => {
12
12
  if (!files.length) {
13
13
  return;
@@ -39,7 +39,3 @@ function UploadInner({ children, className, onFilesSelected, onFilesRejected, va
39
39
  {children}
40
40
  </div>);
41
41
  }
42
- export const Upload = forwardRef(function Upload(props, ref) {
43
- return <UploadInner {...props} forwardedRef={ref}/>;
44
- });
45
- export default Upload;
@@ -188,9 +188,9 @@ export default class UserAgreementService {
188
188
  preview,
189
189
  ...restOptions,
190
190
  };
191
- this.reactRoot.render(<ControlsHeightContext.Provider value={getGlobalControlsHeight()}>
191
+ this.reactRoot.render(<ControlsHeightContext value={getGlobalControlsHeight()}>
192
192
  <UserAgreement {...props}/>
193
- </ControlsHeightContext.Provider>);
193
+ </ControlsHeightContext>);
194
194
  if (onDialogShow) {
195
195
  onDialogShow();
196
196
  }
@@ -1 +1,27 @@
1
1
  export declare const hideAddonsPanelParam = "hideAddonsPanel";
2
+ export declare function createRandom(seed: bigint): {
3
+ /**
4
+ * Fractional in [0, 1)
5
+ */
6
+ (): number;
7
+ /**
8
+ * Integer in [0, to)
9
+ */
10
+ (to: number): number;
11
+ /**
12
+ * Integer in [from, to)
13
+ */
14
+ (from: number, to: number): number;
15
+ /**
16
+ * Date in [from, to)
17
+ */
18
+ (from: Date, to: Date): Date;
19
+ /**
20
+ * Up to random n items (in random order) from the array
21
+ */
22
+ <T>(array: readonly T[], n: number): T[];
23
+ /**
24
+ * Random item from the array
25
+ */
26
+ <T>(array: readonly T[]): T;
27
+ };