baseui 10.9.2 → 10.10.0
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.
- package/data-table/column-numerical.js +320 -362
- package/data-table/column-numerical.js.flow +285 -287
- package/data-table/constants.js +17 -11
- package/data-table/constants.js.flow +11 -8
- package/data-table/data-table.js +53 -50
- package/data-table/data-table.js.flow +18 -13
- package/data-table/filter-shell.js +27 -4
- package/data-table/filter-shell.js.flow +33 -9
- package/data-table/locale.js +4 -2
- package/data-table/locale.js.flow +6 -2
- package/data-table/measure-column-widths.js +83 -119
- package/data-table/measure-column-widths.js.flow +87 -107
- package/es/data-table/column-numerical.js +252 -320
- package/es/data-table/constants.js +12 -8
- package/es/data-table/data-table.js +18 -16
- package/es/data-table/filter-shell.js +26 -4
- package/es/data-table/locale.js +4 -2
- package/es/data-table/measure-column-widths.js +75 -84
- package/es/timezonepicker/timezone-picker.js +1 -1
- package/esm/data-table/column-numerical.js +317 -360
- package/esm/data-table/constants.js +12 -8
- package/esm/data-table/data-table.js +53 -50
- package/esm/data-table/filter-shell.js +26 -4
- package/esm/data-table/locale.js +4 -2
- package/esm/data-table/measure-column-widths.js +83 -119
- package/esm/timezonepicker/timezone-picker.js +1 -1
- package/package.json +2 -1
- package/timezonepicker/timezone-picker.js +1 -1
- package/timezonepicker/timezone-picker.js.flow +1 -1
|
@@ -17,6 +17,8 @@ import { LocaleContext } from '../locale/index.js'; // consider pulling this out
|
|
|
17
17
|
|
|
18
18
|
const HEADER_ROW_HEIGHT = 48;
|
|
19
19
|
|
|
20
|
+
const sum = ns => ns.reduce((s, n) => s + n, 0);
|
|
21
|
+
|
|
20
22
|
function CellPlacement({
|
|
21
23
|
columnIndex,
|
|
22
24
|
rowIndex,
|
|
@@ -255,7 +257,7 @@ function Header(props) {
|
|
|
255
257
|
}))));
|
|
256
258
|
}
|
|
257
259
|
|
|
258
|
-
function Headers(
|
|
260
|
+
function Headers() {
|
|
259
261
|
const [css, theme] = useStyletron();
|
|
260
262
|
const locale = React.useContext(LocaleContext);
|
|
261
263
|
const ctx = React.useContext(HeaderContext);
|
|
@@ -265,7 +267,7 @@ function Headers(props) {
|
|
|
265
267
|
position: 'sticky',
|
|
266
268
|
top: 0,
|
|
267
269
|
left: 0,
|
|
268
|
-
width: `${ctx.widths
|
|
270
|
+
width: `${sum(ctx.widths)}px`,
|
|
269
271
|
height: `${HEADER_ROW_HEIGHT}px`,
|
|
270
272
|
display: 'flex',
|
|
271
273
|
// this feels bad.. the absolutely positioned children elements
|
|
@@ -467,8 +469,10 @@ export function DataTable({
|
|
|
467
469
|
}
|
|
468
470
|
|
|
469
471
|
return rowHeight;
|
|
470
|
-
}, [rowHeight]);
|
|
471
|
-
|
|
472
|
+
}, [rowHeight]); // We use state for our ref, to allow hooks to update when the ref changes.
|
|
473
|
+
// eslint-disable-next-line flowtype/no-weak-types
|
|
474
|
+
|
|
475
|
+
const [gridRef, setGridRef] = React.useState(null);
|
|
472
476
|
const [measuredWidths, setMeasuredWidths] = React.useState(columns.map(() => 0));
|
|
473
477
|
const [resizeDeltas, setResizeDeltas] = React.useState(columns.map(() => 0));
|
|
474
478
|
React.useEffect(() => {
|
|
@@ -480,11 +484,11 @@ export function DataTable({
|
|
|
480
484
|
});
|
|
481
485
|
}, [columns]);
|
|
482
486
|
const resetAfterColumnIndex = React.useCallback(columnIndex => {
|
|
483
|
-
if (gridRef
|
|
487
|
+
if (gridRef) {
|
|
484
488
|
// $FlowFixMe trigger react-window to layout the elements again
|
|
485
|
-
gridRef.
|
|
489
|
+
gridRef.resetAfterColumnIndex(columnIndex, true);
|
|
486
490
|
}
|
|
487
|
-
}, [gridRef
|
|
491
|
+
}, [gridRef]);
|
|
488
492
|
const handleWidthsChange = React.useCallback(nextWidths => {
|
|
489
493
|
setMeasuredWidths(nextWidths);
|
|
490
494
|
resetAfterColumnIndex(0);
|
|
@@ -594,13 +598,10 @@ export function DataTable({
|
|
|
594
598
|
}, [sortedIndices, filteredIndices, onIncludedRowsChange, allRows]);
|
|
595
599
|
const [browserScrollbarWidth, setBrowserScrollbarWidth] = React.useState(0);
|
|
596
600
|
const normalizedWidths = React.useMemo(() => {
|
|
597
|
-
const sum = ns => ns.reduce((s, n) => s + n, 0);
|
|
598
|
-
|
|
599
601
|
const resizedWidths = measuredWidths.map((w, i) => Math.floor(w) + Math.floor(resizeDeltas[i]));
|
|
600
602
|
|
|
601
|
-
if (gridRef
|
|
602
|
-
|
|
603
|
-
const gridProps = gridRef.current.props;
|
|
603
|
+
if (gridRef) {
|
|
604
|
+
const gridProps = gridRef.props;
|
|
604
605
|
let isContentTallerThanContainer = false;
|
|
605
606
|
let visibleRowHeight = 0;
|
|
606
607
|
|
|
@@ -635,7 +636,7 @@ export function DataTable({
|
|
|
635
636
|
}
|
|
636
637
|
|
|
637
638
|
return resizedWidths;
|
|
638
|
-
}, [measuredWidths, resizeDeltas, browserScrollbarWidth, rows.length, columns]);
|
|
639
|
+
}, [gridRef, measuredWidths, resizeDeltas, browserScrollbarWidth, rows.length, columns]);
|
|
639
640
|
const isSelectable = batchActions ? !!batchActions.length : false;
|
|
640
641
|
const isSelectedAll = React.useMemo(() => {
|
|
641
642
|
if (!selectedRowIds) {
|
|
@@ -684,10 +685,10 @@ export function DataTable({
|
|
|
684
685
|
function handleRowHighlightIndexChange(nextIndex) {
|
|
685
686
|
setRowHighlightIndex(nextIndex);
|
|
686
687
|
|
|
687
|
-
if (gridRef
|
|
688
|
+
if (gridRef) {
|
|
688
689
|
if (nextIndex >= 0) {
|
|
689
690
|
// $FlowFixMe - unable to get react-window types
|
|
690
|
-
gridRef.
|
|
691
|
+
gridRef.scrollToItem({
|
|
691
692
|
rowIndex: nextIndex
|
|
692
693
|
});
|
|
693
694
|
}
|
|
@@ -776,8 +777,9 @@ export function DataTable({
|
|
|
776
777
|
}
|
|
777
778
|
}, /*#__PURE__*/React.createElement(VariableSizeGrid // eslint-disable-next-line flowtype/no-weak-types
|
|
778
779
|
, {
|
|
779
|
-
ref:
|
|
780
|
+
ref: setGridRef,
|
|
780
781
|
overscanRowCount: 10,
|
|
782
|
+
overscanColumnCount: 5,
|
|
781
783
|
innerElementType: InnerTableElement,
|
|
782
784
|
columnCount: columns.length,
|
|
783
785
|
columnWidth: columnIndex => normalizedWidths[columnIndex],
|
|
@@ -9,10 +9,26 @@ import { Button, SIZE as BUTTON_SIZE } from '../button/index.js';
|
|
|
9
9
|
import { Checkbox, STYLE_TYPE } from '../checkbox/index.js';
|
|
10
10
|
import { useStyletron } from '../styles/index.js';
|
|
11
11
|
import { LocaleContext } from '../locale/index.js';
|
|
12
|
+
import { FILTER_SHELL_WIDTH } from './constants.js';
|
|
12
13
|
|
|
13
14
|
function FilterShell(props) {
|
|
14
15
|
const [css, theme] = useStyletron();
|
|
15
16
|
const locale = React.useContext(LocaleContext);
|
|
17
|
+
let excludeText;
|
|
18
|
+
|
|
19
|
+
switch (props.excludeKind) {
|
|
20
|
+
case 'value':
|
|
21
|
+
excludeText = locale.datatable.filterExcludeValue;
|
|
22
|
+
break;
|
|
23
|
+
|
|
24
|
+
case 'range':
|
|
25
|
+
excludeText = locale.datatable.filterExcludeRange;
|
|
26
|
+
break;
|
|
27
|
+
|
|
28
|
+
default:
|
|
29
|
+
excludeText = locale.datatable.filterExclude;
|
|
30
|
+
}
|
|
31
|
+
|
|
16
32
|
return /*#__PURE__*/React.createElement("form", {
|
|
17
33
|
className: css({
|
|
18
34
|
backgroundColor: theme.colors.backgroundPrimary,
|
|
@@ -20,7 +36,7 @@ function FilterShell(props) {
|
|
|
20
36
|
paddingRight: theme.sizing.scale600,
|
|
21
37
|
paddingBottom: theme.sizing.scale600,
|
|
22
38
|
paddingLeft: theme.sizing.scale600,
|
|
23
|
-
width:
|
|
39
|
+
width: FILTER_SHELL_WIDTH
|
|
24
40
|
}),
|
|
25
41
|
onSubmit: event => {
|
|
26
42
|
event.preventDefault();
|
|
@@ -28,17 +44,23 @@ function FilterShell(props) {
|
|
|
28
44
|
}
|
|
29
45
|
}, props.children, /*#__PURE__*/React.createElement("div", {
|
|
30
46
|
className: css({
|
|
31
|
-
alignItems: 'center',
|
|
32
47
|
display: 'flex',
|
|
48
|
+
flexDirection: 'column',
|
|
33
49
|
justifyContent: 'space-between',
|
|
34
|
-
|
|
50
|
+
alignItems: 'flex-end',
|
|
51
|
+
marginTop: theme.sizing.scale600,
|
|
52
|
+
gap: theme.sizing.scale200
|
|
53
|
+
})
|
|
54
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
55
|
+
className: css({
|
|
56
|
+
alignSelf: 'flex-start'
|
|
35
57
|
})
|
|
36
58
|
}, /*#__PURE__*/React.createElement(Checkbox, {
|
|
37
59
|
checked: props.exclude,
|
|
38
60
|
onChange: props.onExcludeChange,
|
|
39
61
|
checkmarkType: STYLE_TYPE.toggle_round,
|
|
40
62
|
labelPlacement: "right"
|
|
41
|
-
},
|
|
63
|
+
}, excludeText)), /*#__PURE__*/React.createElement(Button, {
|
|
42
64
|
size: BUTTON_SIZE.compact,
|
|
43
65
|
type: "submit"
|
|
44
66
|
}, locale.datatable.filterApply)));
|
package/es/data-table/locale.js
CHANGED
|
@@ -6,18 +6,20 @@ LICENSE file in the root directory of this source tree.
|
|
|
6
6
|
*/
|
|
7
7
|
const locale = {
|
|
8
8
|
emptyState: 'No rows match the filter criteria defined. Please remove one or more filters to view more data.',
|
|
9
|
-
loadingState: 'Loading
|
|
9
|
+
loadingState: 'Loading rows.',
|
|
10
10
|
searchAriaLabel: 'Search by text',
|
|
11
11
|
filterAdd: 'Add Filter',
|
|
12
12
|
filterExclude: 'Exclude',
|
|
13
13
|
filterApply: 'Apply',
|
|
14
|
+
filterExcludeRange: 'Exclude range',
|
|
15
|
+
filterExcludeValue: 'Exclude value',
|
|
14
16
|
filterAppliedTo: 'filter applied to',
|
|
15
17
|
optionsLabel: 'Select column to filter by',
|
|
16
18
|
optionsSearch: 'Search for a column to filter by...',
|
|
17
19
|
optionsEmpty: 'No columns available.',
|
|
18
20
|
categoricalFilterSelectAll: 'Select All',
|
|
19
21
|
categoricalFilterSelectClear: 'Clear',
|
|
20
|
-
categoricalFilterEmpty: 'No
|
|
22
|
+
categoricalFilterEmpty: 'No categories found',
|
|
21
23
|
datetimeFilterRange: 'Range',
|
|
22
24
|
datetimeFilterRangeDatetime: 'Date, Time',
|
|
23
25
|
datetimeFilterRangeDate: 'Date',
|
|
@@ -7,40 +7,61 @@ LICENSE file in the root directory of this source tree.
|
|
|
7
7
|
import * as React from 'react';
|
|
8
8
|
import { useStyletron } from '../styles/index.js';
|
|
9
9
|
import HeaderCell from './header-cell.js';
|
|
10
|
+
import { useRef } from 'react'; // Measures the column header + sampled data
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
function MeasureColumn({
|
|
13
|
+
sampleIndexes,
|
|
14
|
+
column,
|
|
15
|
+
columnIndex,
|
|
16
|
+
rows,
|
|
17
|
+
isSelectable,
|
|
18
|
+
onLayout
|
|
19
|
+
}) {
|
|
20
|
+
const [css] = useStyletron();
|
|
21
|
+
const ref = useRef();
|
|
18
22
|
React.useEffect(() => {
|
|
19
23
|
if (typeof document !== 'undefined') {
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
setDimensions(node.getBoundingClientRect());
|
|
23
|
-
});
|
|
24
|
+
if (ref.current) {
|
|
25
|
+
onLayout(columnIndex, ref.current.getBoundingClientRect());
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
|
-
}, [
|
|
27
|
-
return
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
}, []);
|
|
29
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
30
|
+
ref: ref,
|
|
31
|
+
className: css({
|
|
32
|
+
display: 'flex',
|
|
33
|
+
flexDirection: 'column',
|
|
34
|
+
width: 'fit-content'
|
|
35
|
+
})
|
|
36
|
+
}, /*#__PURE__*/React.createElement(HeaderCell, {
|
|
37
|
+
index: columnIndex,
|
|
38
|
+
isHovered: true,
|
|
39
|
+
isMeasured: true,
|
|
40
|
+
isSelectedAll: false,
|
|
41
|
+
isSelectedIndeterminate: false,
|
|
42
|
+
onMouseEnter: () => {},
|
|
43
|
+
onMouseLeave: () => {},
|
|
44
|
+
onSelectAll: () => {},
|
|
45
|
+
onSelectNone: () => {},
|
|
46
|
+
onSort: i => {},
|
|
47
|
+
sortable: column.sortable,
|
|
48
|
+
sortDirection: null,
|
|
49
|
+
title: column.title,
|
|
50
|
+
isSelectable: isSelectable
|
|
51
|
+
}), sampleIndexes.map((rowIndex, i) => {
|
|
52
|
+
const Cell = column.renderCell;
|
|
53
|
+
return /*#__PURE__*/React.createElement(Cell, {
|
|
54
|
+
key: `measure-${i}`,
|
|
55
|
+
value: column.mapDataToValue(rows[rowIndex].data),
|
|
56
|
+
isSelectable: isSelectable,
|
|
57
|
+
isMeasured: true,
|
|
58
|
+
sortable: column.sortable,
|
|
59
|
+
x: 0,
|
|
60
|
+
y: rowIndex
|
|
61
|
+
});
|
|
62
|
+
}));
|
|
41
63
|
}
|
|
42
64
|
|
|
43
|
-
// sample size could likely be generated based on row count, to have higher confidence
|
|
44
65
|
const MAX_SAMPLE_SIZE = 50;
|
|
45
66
|
|
|
46
67
|
function generateSampleIndices(inputMin, inputMax, maxSamples) {
|
|
@@ -77,43 +98,35 @@ export default function MeasureColumnWidths({
|
|
|
77
98
|
onWidthsChange
|
|
78
99
|
}) {
|
|
79
100
|
const [css] = useStyletron();
|
|
80
|
-
const
|
|
81
|
-
|
|
101
|
+
const widthMap = React.useMemo(() => {
|
|
102
|
+
return new Map();
|
|
103
|
+
}, []);
|
|
82
104
|
const sampleSize = rows.length < MAX_SAMPLE_SIZE ? rows.length : MAX_SAMPLE_SIZE;
|
|
83
105
|
const finishedMeasurementCount = (sampleSize + 1) * columns.length;
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
dimensionsCache.current = widths;
|
|
87
|
-
const indices = generateSampleIndices(0, rows.length - 1, sampleSize);
|
|
88
|
-
return columns.map(() => indices);
|
|
106
|
+
const sampleIndexes = React.useMemo(() => {
|
|
107
|
+
return generateSampleIndices(0, rows.length - 1, sampleSize);
|
|
89
108
|
}, [columns, rows, widths, sampleSize]);
|
|
90
|
-
const handleDimensionsChange = React.useCallback((columnIndex,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (columns[columnIndex] === undefined || dimensionsCache.current[columnIndex] === undefined) {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
measurementCount.current += 1;
|
|
98
|
-
const nextWidth = Math.min(Math.max(columns[columnIndex].minWidth || 0, dimensionsCache.current[columnIndex], dimensions.width + 1), columns[columnIndex].maxWidth || Infinity);
|
|
109
|
+
const handleDimensionsChange = React.useCallback((columnIndex, dimensions) => {
|
|
110
|
+
const nextWidth = Math.min(Math.max(columns[columnIndex].minWidth || 0, widthMap.get(columnIndex) || 0, dimensions.width + 1), columns[columnIndex].maxWidth || Infinity);
|
|
99
111
|
|
|
100
|
-
if (nextWidth !==
|
|
101
|
-
|
|
102
|
-
nextWidths[columnIndex] = nextWidth;
|
|
103
|
-
dimensionsCache.current = nextWidths;
|
|
112
|
+
if (nextWidth !== widthMap.get(columnIndex)) {
|
|
113
|
+
widthMap.set(columnIndex, nextWidth);
|
|
104
114
|
}
|
|
105
115
|
|
|
106
|
-
if (
|
|
107
|
-
|
|
116
|
+
if ( // Refresh at 100% of done
|
|
117
|
+
widthMap.size === columns.length || // ...50%
|
|
118
|
+
widthMap.size === Math.floor(columns.length / 2) || // ...25%
|
|
119
|
+
widthMap.size === Math.floor(columns.length / 4)) {
|
|
120
|
+
onWidthsChange(Array.from(widthMap.values()));
|
|
108
121
|
}
|
|
109
122
|
}, [columns, finishedMeasurementCount, onWidthsChange]);
|
|
110
123
|
const hiddenStyle = css({
|
|
111
124
|
position: 'absolute',
|
|
112
125
|
overflow: 'hidden',
|
|
113
126
|
height: 0
|
|
114
|
-
});
|
|
127
|
+
}); // Remove the measurement nodes after we are done updating our column width
|
|
115
128
|
|
|
116
|
-
if (
|
|
129
|
+
if (widthMap.size === columns.length) {
|
|
117
130
|
return null;
|
|
118
131
|
}
|
|
119
132
|
|
|
@@ -124,38 +137,16 @@ export default function MeasureColumnWidths({
|
|
|
124
137
|
className: hiddenStyle,
|
|
125
138
|
"aria-hidden": true,
|
|
126
139
|
role: "none"
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
})
|
|
139
|
-
}));
|
|
140
|
-
}), columns.map((column, columnIndex) => /*#__PURE__*/React.createElement(ElementMeasurer, {
|
|
141
|
-
key: `measure-column-${columnIndex}`,
|
|
142
|
-
onDimensionsChange: dimensions => handleDimensionsChange(columnIndex, -1, dimensions),
|
|
143
|
-
item: /*#__PURE__*/React.createElement(HeaderCell, {
|
|
144
|
-
index: columnIndex,
|
|
145
|
-
isHovered: true,
|
|
146
|
-
isMeasured: true,
|
|
147
|
-
isSelectable: isSelectable && columnIndex === 0,
|
|
148
|
-
isSelectedAll: false,
|
|
149
|
-
isSelectedIndeterminate: false,
|
|
150
|
-
onMouseEnter: () => {},
|
|
151
|
-
onMouseLeave: () => {},
|
|
152
|
-
onSelectAll: () => {},
|
|
153
|
-
onSelectNone: () => {},
|
|
154
|
-
onSort: i => {},
|
|
155
|
-
sortable: column.sortable,
|
|
156
|
-
sortDirection: null,
|
|
157
|
-
title: column.title
|
|
158
|
-
})
|
|
159
|
-
})))
|
|
140
|
+
}, columns.map((column, i) => {
|
|
141
|
+
return /*#__PURE__*/React.createElement(MeasureColumn, {
|
|
142
|
+
key: column.title + i,
|
|
143
|
+
column: column,
|
|
144
|
+
rows: rows,
|
|
145
|
+
isSelectable: isSelectable,
|
|
146
|
+
onLayout: handleDimensionsChange,
|
|
147
|
+
columnIndex: i,
|
|
148
|
+
sampleIndexes: sampleIndexes
|
|
149
|
+
});
|
|
150
|
+
}))
|
|
160
151
|
);
|
|
161
152
|
}
|
|
@@ -32,7 +32,7 @@ class TimezonePicker extends React.Component {
|
|
|
32
32
|
try {
|
|
33
33
|
const offset = getTimezoneOffset(zoneName, compareDate) / 3_600_000;
|
|
34
34
|
const offsetFormatted = `${offset >= 0 ? '+' : '-'}${Math.abs(offset)}`;
|
|
35
|
-
let label = `(GMT${offsetFormatted}) ${zoneName.replace(
|
|
35
|
+
let label = `(GMT${offsetFormatted}) ${zoneName.replace(/_/g, ' ')}`;
|
|
36
36
|
|
|
37
37
|
if (this.props.includeAbbreviations) {
|
|
38
38
|
const abbreviation = format(compareDate, 'zzz', {
|