@jetbrains/ring-ui 7.0.115 → 8.0.0-beta.2

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 (54) hide show
  1. package/components/data-list/data-list.d.ts +4 -4
  2. package/components/data-list/data-list.js +2 -2
  3. package/components/data-list/data-list.mock.d.ts +1 -1
  4. package/components/data-list/item.d.ts +1 -1
  5. package/components/data-list/selection.d.ts +1 -1
  6. package/components/data-list/selection.js +1 -1
  7. package/components/date-picker/month.d.ts +0 -2
  8. package/components/date-picker/month.js +5 -5
  9. package/components/date-picker/months.js +8 -7
  10. package/components/date-picker/years.js +11 -10
  11. package/components/global/intersection-observer-context.d.ts +26 -0
  12. package/components/global/intersection-observer-context.js +72 -0
  13. package/components/{table → legacy-table}/selection.d.ts +2 -2
  14. package/components/{table → legacy-table}/selection.js +1 -1
  15. package/components/legacy-table/table.css +260 -0
  16. package/components/legacy-table/table.d.ts +109 -0
  17. package/components/legacy-table/table.js +191 -0
  18. package/components/table/default-item-renderer.d.ts +25 -0
  19. package/components/table/default-item-renderer.js +64 -0
  20. package/components/table/table-base.d.ts +24 -0
  21. package/components/table/table-base.js +79 -0
  22. package/components/table/table-component.d.ts +53 -0
  23. package/components/table/table-component.js +101 -0
  24. package/components/table/table-const.d.ts +8 -0
  25. package/components/table/table-const.js +8 -0
  26. package/components/table/table-virtualize.d.ts +32 -0
  27. package/components/table/table-virtualize.js +150 -0
  28. package/components/table/table.css +76 -199
  29. package/components/table/table.d.ts +221 -104
  30. package/components/table/table.js +2 -191
  31. package/package.json +1 -1
  32. /package/components/{table → legacy-table}/cell.d.ts +0 -0
  33. /package/components/{table → legacy-table}/cell.js +0 -0
  34. /package/components/{table → legacy-table}/disable-hover-hoc.d.ts +0 -0
  35. /package/components/{table → legacy-table}/disable-hover-hoc.js +0 -0
  36. /package/components/{table → legacy-table}/header-cell.d.ts +0 -0
  37. /package/components/{table → legacy-table}/header-cell.js +0 -0
  38. /package/components/{table → legacy-table}/header.d.ts +0 -0
  39. /package/components/{table → legacy-table}/header.js +0 -0
  40. /package/components/{table → legacy-table}/multitable.d.ts +0 -0
  41. /package/components/{table → legacy-table}/multitable.js +0 -0
  42. /package/components/{table → legacy-table}/row-with-focus-sensor.d.ts +0 -0
  43. /package/components/{table → legacy-table}/row-with-focus-sensor.js +0 -0
  44. /package/components/{table → legacy-table}/row.d.ts +0 -0
  45. /package/components/{table → legacy-table}/row.js +0 -0
  46. /package/components/{table → legacy-table}/selection-adapter.d.ts +0 -0
  47. /package/components/{table → legacy-table}/selection-adapter.js +0 -0
  48. /package/components/{table → legacy-table}/selection-shortcuts-hoc.d.ts +0 -0
  49. /package/components/{table → legacy-table}/selection-shortcuts-hoc.js +0 -0
  50. /package/components/{table → legacy-table}/simple-table.d.ts +0 -0
  51. /package/components/{table → legacy-table}/simple-table.js +0 -0
  52. /package/components/{table → legacy-table}/smart-table.d.ts +0 -0
  53. /package/components/{table → legacy-table}/smart-table.js +0 -0
  54. /package/components/{table → legacy-table}/table.examples2.json +0 -0
@@ -0,0 +1,150 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
+ import useEventCallback from '../global/use-event-callback';
3
+ import { useIntersectionObserverHandle } from '../global/intersection-observer-context';
4
+ import styles from './table.css';
5
+ /**
6
+ * RAF is somewhat too frequent. Most updates happen on virtualization boundaries
7
+ * within the invisible overscroll area, so they don't require such a high update rate.
8
+ * Therefore, we throttle with a custom delay.
9
+ */
10
+ const virtualizationThrottleDelay = 50;
11
+ export function useTableVirtualize({ enabled, length, scrollerRef, tableRef, estimateHeight, lookaheadPx, retentionMarginPx, minScrollAndResizeDeltaPx, }) {
12
+ const itemsMaterialization = useRef([]);
13
+ const [virtualItems, setVirtualItems] = useState(() => [
14
+ {
15
+ type: 'spacer',
16
+ from: 0,
17
+ to: length,
18
+ height: Array.from({ length }, (_, i) => estimateHeight(i)).reduce((a, b) => a + b, 0),
19
+ key: `${styles.spacerRow}-0`,
20
+ },
21
+ ]);
22
+ const materializeVisibleSpacerItems = useEventCallback(() => {
23
+ if (!tableRef.current)
24
+ return;
25
+ const containerHeight = scrollerRef?.current?.clientHeight ?? window.innerHeight;
26
+ for (const spacerRow of tableRef.current.querySelectorAll(`.${styles.spacerRow}`)) {
27
+ const rect = spacerRow.getBoundingClientRect();
28
+ const spacerIntersectsLookaheadArea = rect.top < containerHeight + lookaheadPx && rect.bottom > -lookaheadPx;
29
+ if (!spacerIntersectsLookaheadArea) {
30
+ continue;
31
+ }
32
+ const visibleOffsetStart = Math.max(0, -rect.top);
33
+ const visibleOffsetEnd = Math.min(rect.height, containerHeight - rect.top);
34
+ const materializeOffsetStart = visibleOffsetStart - lookaheadPx;
35
+ const materializeOffsetEnd = visibleOffsetEnd + lookaheadPx;
36
+ let offsetInSpacer = 0;
37
+ const from = Number(spacerRow.dataset.from);
38
+ const to = Number(spacerRow.dataset.to);
39
+ for (let i = from; i < to; i++) {
40
+ const itemMaterialization = itemsMaterialization.current[i];
41
+ const itemHeight = typeof itemMaterialization === 'number' ? itemMaterialization : estimateHeight(i);
42
+ const itemOffsetStart = offsetInSpacer;
43
+ const itemOffsetEnd = offsetInSpacer + itemHeight;
44
+ if (itemOffsetStart < materializeOffsetEnd && itemOffsetEnd > materializeOffsetStart) {
45
+ itemsMaterialization.current[i] = true;
46
+ }
47
+ else if (itemOffsetStart > materializeOffsetEnd) {
48
+ break;
49
+ }
50
+ offsetInSpacer += itemHeight;
51
+ }
52
+ }
53
+ });
54
+ const recomputeVirtualItems = useEventCallback(() => {
55
+ const newVirtualItems = [];
56
+ let spacerCounter = 0;
57
+ for (let i = 0; i < length; i++) {
58
+ const itemMaterialization = itemsMaterialization.current[i];
59
+ if (itemMaterialization === true) {
60
+ newVirtualItems.push({ type: 'rendered', index: i });
61
+ }
62
+ else {
63
+ const lastItemOrSpacer = newVirtualItems[newVirtualItems.length - 1];
64
+ const lastSpacer = lastItemOrSpacer?.type === 'spacer' ? lastItemOrSpacer : undefined;
65
+ const height = typeof itemMaterialization === 'number' ? itemMaterialization : estimateHeight(i);
66
+ if (lastSpacer) {
67
+ lastSpacer.to = i + 1;
68
+ lastSpacer.height += height;
69
+ }
70
+ else {
71
+ newVirtualItems.push({
72
+ type: 'spacer',
73
+ from: i,
74
+ to: i + 1,
75
+ height,
76
+ key: `${styles.spacerRow}-${spacerCounter++}`,
77
+ });
78
+ }
79
+ }
80
+ }
81
+ setVirtualItems(newVirtualItems);
82
+ });
83
+ const timerIdRef = useRef(null);
84
+ const callbacksRef = useRef(null);
85
+ const throttle = useEventCallback((...callbacks) => {
86
+ if (timerIdRef.current != null) {
87
+ callbacks.forEach(cb => {
88
+ callbacksRef.current.delete(cb);
89
+ callbacksRef.current.add(cb);
90
+ });
91
+ return;
92
+ }
93
+ callbacksRef.current = new Set(callbacks);
94
+ timerIdRef.current = window.setTimeout(() => {
95
+ callbacksRef.current.forEach(cb => cb());
96
+ timerIdRef.current = null;
97
+ callbacksRef.current = null;
98
+ }, virtualizationThrottleDelay);
99
+ });
100
+ useEffect(() => {
101
+ if (!enabled)
102
+ return;
103
+ const scroller = scrollerRef?.current;
104
+ let lastHandledScrollTop = -Infinity;
105
+ let lastHandledHeight = -Infinity;
106
+ let lastHandledWidth = -Infinity;
107
+ function handleViewportChange() {
108
+ const scrollTop = scroller ? scroller.scrollTop : window.scrollY;
109
+ const height = scroller ? scroller.clientHeight : window.innerHeight;
110
+ const width = scroller ? scroller.clientWidth : window.innerWidth;
111
+ if (Math.abs(scrollTop - lastHandledScrollTop) >= minScrollAndResizeDeltaPx ||
112
+ Math.abs(height - lastHandledHeight) >= minScrollAndResizeDeltaPx ||
113
+ Math.abs(width - lastHandledWidth) >= minScrollAndResizeDeltaPx) {
114
+ lastHandledScrollTop = scrollTop;
115
+ lastHandledHeight = height;
116
+ lastHandledWidth = width;
117
+ throttle(materializeVisibleSpacerItems, recomputeVirtualItems);
118
+ }
119
+ }
120
+ const scrollTarget = scroller ?? window;
121
+ scrollTarget.addEventListener('scroll', handleViewportChange, { passive: true });
122
+ const resizeObserver = new ResizeObserver(handleViewportChange);
123
+ const resizeTarget = scroller ?? document.documentElement;
124
+ resizeObserver.observe(resizeTarget);
125
+ handleViewportChange();
126
+ return () => {
127
+ scrollTarget.removeEventListener('scroll', handleViewportChange);
128
+ resizeObserver.unobserve(resizeTarget);
129
+ resizeObserver.disconnect();
130
+ };
131
+ }, [enabled, materializeVisibleSpacerItems, minScrollAndResizeDeltaPx, recomputeVirtualItems, scrollerRef, throttle]);
132
+ const intersectionObserverHandle = useIntersectionObserverHandle(scrollerRef, scrollerRef ? retentionMarginPx : undefined, !scrollerRef ? retentionMarginPx : undefined);
133
+ const collapseItemIntoSpacer = useEventCallback((index, height) => {
134
+ if (!enabled)
135
+ return;
136
+ itemsMaterialization.current[index] = height;
137
+ throttle(recomputeVirtualItems);
138
+ });
139
+ const allVisibleVirtualItems = useMemo(() => Array.from({ length: enabled ? 0 : length }, (_, index) => ({ type: 'rendered', index })), [enabled, length]);
140
+ return {
141
+ virtualItems: enabled ? virtualItems : allVisibleVirtualItems,
142
+ intersectionObserverHandle,
143
+ collapseItemIntoSpacer,
144
+ };
145
+ }
146
+ export function SpacerRow({ spacer: { from, to, height }, colSpan }) {
147
+ return (<tr className={styles.spacerRow} data-from={from} data-to={to}>
148
+ <td className={styles.spacerCell} colSpan={colSpan} style={{ height }}/>
149
+ </tr>);
150
+ }
@@ -1,260 +1,137 @@
1
1
  @import '../global/variables.css';
2
2
 
3
- .tableWrapper {
4
- --ring-table-compensate: 2px;
5
- --ring-table-compensated: calc(calc(4 * var(--ring-unit)) - var(--ring-table-compensate));
6
- --ring-table-top: -3px;
7
-
8
- position: relative;
9
- font-variant-numeric: var(--ring-font-variant-numeric);
10
- }
11
-
12
3
  .table {
13
4
  width: 100%;
14
5
 
15
- border-spacing: 0;
6
+ border-collapse: collapse;
7
+ border-style: none;
16
8
  }
17
9
 
18
- .userSelectNone {
19
- user-select: none;
10
+ .headerRow {
11
+ border-bottom: 1px solid var(--ring-line-color);
20
12
  }
21
13
 
22
14
  .headerCell {
23
- composes: font-smaller-lower from '../global/global.css';
15
+ position: relative;
24
16
 
25
- box-sizing: border-box;
26
- height: calc(var(--ring-unit) * 3);
27
- padding-right: calc(var(--ring-unit) * 5);
17
+ padding: calc(var(--ring-unit) * 0.75) var(--ring-unit);
18
+
19
+ transition: background-color var(--ring-fast-ease), border-color var(--ring-fast-ease);
28
20
 
29
21
  text-align: left;
30
- white-space: nowrap;
31
22
 
32
23
  color: var(--ring-secondary-color);
24
+ border-left: 1px solid transparent;
33
25
 
26
+ font-size: var(--ring-font-size-smaller);
34
27
  font-weight: normal;
35
- }
36
-
37
- .headerCell:first-child {
38
- padding-left: calc(var(--ring-unit) * 4);
39
- }
40
-
41
- .headerCell:last-child {
42
- width: 100%;
43
- padding-right: calc(var(--ring-unit) * 4);
44
- }
45
-
46
- .headerCell:first-child:only-child {
47
- width: initial;
48
- max-width: none;
49
- }
50
-
51
- .headerCell.headerCellSorted {
52
- font-weight: var(--ring-font-weight-bold);
53
- }
54
28
 
55
- .headerCell.headerCellSortable {
56
- cursor: pointer;
57
- }
29
+ &:last-child {
30
+ border-right: 1px solid transparent;
31
+ }
58
32
 
59
- .headerCell .sorter {
60
- position: absolute;
61
- top: 5px;
33
+ &:hover {
34
+ border-left-color: var(--ring-line-color);
35
+ background-color: var(--ring-grey-container-light-color);
62
36
 
63
- display: none;
37
+ &:last-child {
38
+ border-right-color: var(--ring-line-color);
39
+ }
64
40
 
65
- margin-left: 5px;
66
-
67
- user-select: none;
41
+ & + .headerCell {
42
+ border-left-color: var(--ring-line-color);
43
+ }
44
+ }
68
45
  }
69
46
 
70
- .headerCell.headerCellSortable .sorter {
71
- display: inline-block;
72
- }
73
-
74
- .sortedUp .icon {
75
- transform: rotate(180deg);
76
- transform-origin: center 44%;
77
- }
78
-
79
- .caption {
80
- padding-top: var(--ring-unit);
81
- padding-bottom: 6px;
82
-
83
- color: var(--ring-text-color);
84
- border-bottom: 0;
85
-
86
- font-size: var(--ring-font-size);
87
- font-weight: var(--ring-font-weight-bold);
88
- line-height: var(--ring-line-height-lower);
89
- }
90
-
91
- .tableHead::after {
92
- position: absolute;
93
-
94
- width: 100%;
95
-
96
- height: 1px;
97
-
98
- content: '';
47
+ .spacerRow {
48
+ margin: 0;
49
+ padding: 0;
99
50
 
100
- background-color: var(--ring-line-color);
51
+ border: 0;
101
52
  }
102
53
 
103
- .subHeaderSticky {
104
- position: sticky;
105
-
106
- z-index: var(--ring-fixed-z-index);
107
- top: 0;
54
+ .spacerCell {
55
+ margin: 0;
56
+ padding: 0;
108
57
 
109
- background-color: rgba(var(--ring-content-background-components), 0.9);
58
+ border: 0;
110
59
  }
111
60
 
112
61
  .row {
113
- outline: none;
62
+ border-bottom: 1px solid var(--ring-line-color);
114
63
 
115
- line-height: var(--ring-table-compensated);
64
+ &:focus {
65
+ border-radius: var(--ring-border-radius);
66
+ outline: 2px solid var(--ring-button-focus-border-color);
67
+ }
116
68
  }
117
69
 
118
- /* stylelint-disable-next-line selector-max-specificity */
119
- .table:not(.disabledHover) .row:hover {
120
- background-color: var(--ring-hover-background-color);
121
- }
70
+ .clickableRow {
71
+ cursor: pointer;
122
72
 
123
- .rowSelected {
124
- background-color: var(--ring-selected-background-color);
125
- }
73
+ transition: background-color var(--ring-fast-ease);
126
74
 
127
- .rowFocused {
128
- background-color: var(--ring-hover-background-color);
129
- }
130
- /* stylelint-disable-next-line selector-max-specificity */
131
- .rowFocused .cell:nth-child(1) {
132
- box-shadow: inset 2px 0 var(--ring-main-color);
75
+ &:not(.selectedRow):hover {
76
+ background-color: var(--ring-hover-background-color);
77
+ }
133
78
  }
134
79
 
135
- .loadingOverlay {
136
- position: absolute;
137
- top: 0;
138
- right: 0;
139
- bottom: 0;
140
- left: 0;
141
-
142
- display: flex;
143
- align-items: center;
144
- justify-content: center;
145
-
146
- background-color: var(--ring-table-loader-background-color);
80
+ .selectedRow {
81
+ background-color: var(--ring-selected-background-color);
147
82
  }
148
83
 
149
84
  .cell {
150
- composes: ellipsis from '../global/global.css';
151
-
152
- box-sizing: content-box;
153
-
154
- min-width: 0;
155
-
156
- height: calc(4 * var(--ring-unit));
157
- padding: 0;
158
- padding-right: calc(var(--ring-unit) * 5);
159
-
160
- color: var(--ring-text-color);
161
- }
162
-
163
- .cell:first-child {
164
- padding-left: calc(var(--ring-unit) * 4);
85
+ padding: var(--ring-unit);
165
86
  }
166
87
 
167
- .cell:last-child {
168
- width: 100%;
169
-
170
- /* Markup hack, allows cell to have content which is wider than cell and collapses it */
171
-
172
- max-width: 0;
173
- padding-right: calc(var(--ring-unit) * 4);
174
- }
175
-
176
- .wideFirstColumn .cell:first-child {
177
- min-width: calc(var(--ring-unit) * 37);
178
- max-width: calc(var(--ring-unit) * 77);
179
- }
180
-
181
- .cell:first-child:only-child {
182
- width: initial;
183
- max-width: none;
184
- }
88
+ .headerButton {
89
+ margin: unset;
90
+ padding: unset;
185
91
 
186
- .cellUnlimited {
187
- width: 100%;
188
- }
189
-
190
- .cellRight {
191
- text-align: right;
192
- }
193
-
194
- .metaColumn {
195
- position: relative;
196
-
197
- float: left;
198
-
199
- height: 16px;
200
- padding-right: var(--ring-table-compensate);
201
- }
202
-
203
- .metaColumn.headerMetaColumn {
204
- padding-top: 1px;
205
- }
206
-
207
- .dragHandle {
208
- top: var(--ring-table-top);
209
- left: calc(-2 * var(--ring-unit));
92
+ cursor: pointer;
210
93
 
211
- cursor: grab;
94
+ transition: color var(--ring-fast-ease);
95
+ text-align: unset;
212
96
 
213
- opacity: 0;
214
- }
97
+ color: unset;
98
+ border: unset;
99
+ background: unset;
215
100
 
216
- /* override button */
217
- .dragHandle.dragHandle {
218
- position: absolute;
101
+ font: unset;
219
102
 
220
- height: calc(calc(4 * var(--ring-unit)) - var(--ring-table-top));
221
- padding: 0;
222
- }
103
+ &:hover {
104
+ color: var(--ring-main-hover-color);
105
+ }
223
106
 
224
- .dragHandle.visibleDragHandle,
225
- .row:hover .dragHandle {
226
- opacity: 1;
107
+ &:focus-visible {
108
+ border-radius: 2px;
109
+ outline: 2px solid var(--ring-button-focus-border-color);
110
+ }
227
111
  }
228
112
 
229
- .rowCollapseExpandButton {
230
- padding-right: calc(var(--ring-unit) / 2);
231
- padding-left: 7px;
232
- }
113
+ .deleteColumnButton {
114
+ float: right;
233
115
 
234
- .draggingRow {
235
- z-index: var(--ring-overlay-z-index);
116
+ pointer-events: none;
236
117
 
237
- background-color: var(--ring-hover-background-color);
238
- }
239
-
240
- .draggingRow .dragHandle {
241
- cursor: grabbing;
118
+ color: transparent;
242
119
 
243
- opacity: 1;
244
120
  }
245
121
 
246
- .draggingRow .dragHandle svg {
247
- color: var(--ring-main-color);
248
- }
122
+ .headerCell:hover .deleteColumnButton {
123
+ pointer-events: all;
249
124
 
250
- .draggingTable {
251
- z-index: var(--ring-overlay-z-index);
125
+ color: unset;
252
126
 
253
- border-spacing: 0;
127
+ /* stylelint-disable-next-line selector-max-specificity */
128
+ &:hover {
129
+ color: var(--ring-main-hover-color);
130
+ }
254
131
  }
255
132
 
256
- .tableMessage {
257
- padding: calc(var(--ring-unit) * 2) calc(var(--ring-unit) * 4);
133
+ .deleteColumnButton:focus-within {
134
+ pointer-events: all;
258
135
 
259
- color: var(--ring-secondary-color);
136
+ color: var(--ring-main-hover-color);
260
137
  }