baseui 10.9.0 → 10.9.1

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 (39) hide show
  1. package/data-table/column-numerical.js +355 -307
  2. package/data-table/column-numerical.js.flow +287 -273
  3. package/data-table/constants.js +11 -17
  4. package/data-table/constants.js.flow +8 -11
  5. package/data-table/data-table.js +50 -53
  6. package/data-table/data-table.js.flow +13 -18
  7. package/data-table/filter-shell.js +4 -27
  8. package/data-table/filter-shell.js.flow +9 -33
  9. package/data-table/locale.js +2 -4
  10. package/data-table/locale.js.flow +2 -6
  11. package/data-table/measure-column-widths.js +121 -83
  12. package/data-table/measure-column-widths.js.flow +109 -87
  13. package/es/data-table/column-numerical.js +317 -245
  14. package/es/data-table/constants.js +8 -12
  15. package/es/data-table/data-table.js +16 -18
  16. package/es/data-table/filter-shell.js +4 -26
  17. package/es/data-table/locale.js +2 -4
  18. package/es/data-table/measure-column-widths.js +86 -75
  19. package/es/form-control/form-control.js +58 -7
  20. package/es/form-control/styled-components.js +27 -6
  21. package/es/popover/popover.js +1 -1
  22. package/esm/data-table/column-numerical.js +353 -304
  23. package/esm/data-table/constants.js +8 -12
  24. package/esm/data-table/data-table.js +50 -53
  25. package/esm/data-table/filter-shell.js +4 -26
  26. package/esm/data-table/locale.js +2 -4
  27. package/esm/data-table/measure-column-widths.js +121 -83
  28. package/esm/form-control/form-control.js +60 -9
  29. package/esm/form-control/styled-components.js +23 -3
  30. package/esm/popover/popover.js +1 -1
  31. package/form-control/form-control.js +61 -8
  32. package/form-control/form-control.js.flow +82 -10
  33. package/form-control/index.d.ts +1 -0
  34. package/form-control/styled-components.js +27 -5
  35. package/form-control/styled-components.js.flow +25 -3
  36. package/form-control/types.js.flow +20 -8
  37. package/package.json +1 -2
  38. package/popover/popover.js +1 -1
  39. package/popover/popover.js.flow +1 -1
@@ -6,6 +6,14 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
6
6
 
7
7
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
8
 
9
+ function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
10
+
11
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
12
+
13
+ function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
14
+
15
+ function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
16
+
9
17
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
10
18
 
11
19
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
@@ -29,12 +37,11 @@ import { Button, SIZE } from '../button/index.js';
29
37
  import { ButtonGroup, MODE } from '../button-group/index.js';
30
38
  import { Input, SIZE as INPUT_SIZE } from '../input/index.js';
31
39
  import { useStyletron } from '../styles/index.js';
40
+ import { ParagraphXSmall } from '../typography/index.js';
32
41
  import Column from './column.js';
33
- import { COLUMNS, NUMERICAL_FORMATS, MAX_BIN_COUNT, HISTOGRAM_SIZE } from './constants.js';
42
+ import { COLUMNS, NUMERICAL_FORMATS, NUMERICAL_OPERATIONS } from './constants.js';
34
43
  import FilterShell from './filter-shell.js';
35
44
  import { LocaleContext } from '../locale/index.js';
36
- import { bin, max as maxFunc, extent, scaleLinear, median, bisector } from 'd3';
37
- import { Slider } from '../slider/index.js';
38
45
 
39
46
  function roundToFixed(value, precision) {
40
47
  var k = Math.pow(10, precision);
@@ -81,226 +88,291 @@ function validateInput(input) {
81
88
  return Boolean(parseFloat(input)) || input === '' || input === '-';
82
89
  }
83
90
 
84
- var bisect = bisector(function (d) {
85
- return d.x0;
86
- });
87
- var Histogram = /*#__PURE__*/React.memo(function Histogram(_ref) {
88
- var data = _ref.data,
89
- lower = _ref.lower,
90
- upper = _ref.upper,
91
- isRange = _ref.isRange,
92
- exclude = _ref.exclude,
93
- precision = _ref.precision;
94
-
95
- var _useStyletron = useStyletron(),
96
- _useStyletron2 = _slicedToArray(_useStyletron, 2),
97
- css = _useStyletron2[0],
98
- theme = _useStyletron2[1];
99
-
100
- var _React$useMemo = React.useMemo(function () {
101
- var bins = bin().thresholds(Math.min(data.length, MAX_BIN_COUNT))(data);
102
- var xScale = scaleLinear().domain([bins[0].x0, bins[bins.length - 1].x1]).range([0, HISTOGRAM_SIZE.width]).clamp(true);
103
- var yScale = scaleLinear().domain([0, maxFunc(bins, function (d) {
104
- return d.length;
105
- })]).nice().range([HISTOGRAM_SIZE.height, 0]);
106
- return {
107
- bins: bins,
108
- xScale: xScale,
109
- yScale: yScale
110
- };
111
- }, [data]),
112
- bins = _React$useMemo.bins,
113
- xScale = _React$useMemo.xScale,
114
- yScale = _React$useMemo.yScale; // We need to find the index of bar which is nearest to the given single value
115
-
116
-
117
- var singleIndexNearest = React.useMemo(function () {
118
- if (isRange) {
119
- return null;
120
- }
121
-
122
- return bisect.center(bins, lower);
123
- }, [isRange, data, lower, upper]);
124
- return /*#__PURE__*/React.createElement("div", {
125
- className: css({
126
- display: 'flex',
127
- marginTop: theme.sizing.scale600,
128
- marginLeft: theme.sizing.scale200,
129
- marginRight: 0,
130
- marginBottom: theme.sizing.scale400,
131
- justifyContent: 'space-between',
132
- overflow: 'visible'
133
- })
134
- }, /*#__PURE__*/React.createElement("svg", HISTOGRAM_SIZE, bins.map(function (d, index) {
135
- var x = xScale(d.x0) + 1;
136
- var y = yScale(d.length);
137
- var width = Math.max(0, xScale(d.x1) - xScale(d.x0) - 1);
138
- var height = yScale(0) - yScale(d.length);
139
- var included;
140
-
141
- if (singleIndexNearest != null) {
142
- included = index === singleIndexNearest;
91
+ function filterParamsToInitialState(filterParams) {
92
+ if (filterParams) {
93
+ if (filterParams.comparisons.length > 1) {
94
+ if (filterParams.comparisons[0].operation === NUMERICAL_OPERATIONS.LT && filterParams.comparisons[1].operation === NUMERICAL_OPERATIONS.GT) {
95
+ return {
96
+ exclude: !filterParams.exclude,
97
+ comparatorIndex: 0,
98
+ operatorIndex: 4,
99
+ right: filterParams.comparisons[1].value.toString(),
100
+ left: filterParams.comparisons[0].value.toString()
101
+ };
102
+ }
143
103
  } else {
144
- var withinLower = d.x1 > lower;
145
- var withinUpper = d.x0 <= upper;
146
- included = withinLower && withinUpper;
147
- }
148
-
149
- if (exclude) {
150
- included = !included;
104
+ var comparison = filterParams.comparisons[0];
105
+
106
+ if (comparison.operation === NUMERICAL_OPERATIONS.LT) {
107
+ return {
108
+ exclude: filterParams.exclude,
109
+ comparatorIndex: 0,
110
+ operatorIndex: 0,
111
+ left: '',
112
+ right: comparison.value.toString()
113
+ };
114
+ } else if (comparison.operation === NUMERICAL_OPERATIONS.GT) {
115
+ return {
116
+ exclude: filterParams.exclude,
117
+ comparatorIndex: 0,
118
+ operatorIndex: 1,
119
+ left: comparison.value.toString(),
120
+ right: ''
121
+ };
122
+ } else if (comparison.operation === NUMERICAL_OPERATIONS.LTE) {
123
+ return {
124
+ exclude: filterParams.exclude,
125
+ comparatorIndex: 0,
126
+ operatorIndex: 2,
127
+ left: '',
128
+ right: comparison.value.toString()
129
+ };
130
+ } else if (comparison.operation === NUMERICAL_OPERATIONS.GTE) {
131
+ return {
132
+ exclude: filterParams.exclude,
133
+ comparatorIndex: 0,
134
+ operatorIndex: 3,
135
+ left: comparison.value.toString(),
136
+ right: ''
137
+ };
138
+ } else if (comparison.operation === NUMERICAL_OPERATIONS.EQ) {
139
+ return {
140
+ exclude: filterParams.exclude,
141
+ comparatorIndex: 1,
142
+ operatorIndex: 0,
143
+ left: comparison.value.toString(),
144
+ right: ''
145
+ };
146
+ }
151
147
  }
148
+ }
152
149
 
153
- return /*#__PURE__*/React.createElement("rect", {
154
- key: "bar-".concat(index),
155
- fill: included ? theme.colors.primary : theme.colors.mono400,
156
- x: x,
157
- y: y,
158
- width: width,
159
- height: height
160
- });
161
- })));
162
- });
150
+ return {
151
+ exclude: false,
152
+ comparatorIndex: 0,
153
+ operatorIndex: 0,
154
+ left: '',
155
+ right: ''
156
+ };
157
+ }
163
158
 
164
159
  function NumericalFilter(props) {
165
- var _useStyletron3 = useStyletron(),
166
- _useStyletron4 = _slicedToArray(_useStyletron3, 2),
167
- css = _useStyletron4[0],
168
- theme = _useStyletron4[1];
160
+ var _useStyletron = useStyletron(),
161
+ _useStyletron2 = _slicedToArray(_useStyletron, 2),
162
+ css = _useStyletron2[0],
163
+ theme = _useStyletron2[1];
169
164
 
170
165
  var locale = React.useContext(LocaleContext);
171
- var precision = props.options.precision; // The state handling of this component could be refactored and cleaned up if we used useReducer.
172
-
173
- var initialState = React.useMemo(function () {
174
- return props.filterParams || {
175
- exclude: false,
176
- excludeKind: 'range',
177
- comparatorIndex: 0,
178
- lowerValue: null,
179
- upperValue: null
180
- };
181
- }, [props.filterParams]);
166
+ var initialState = filterParamsToInitialState(props.filterParams);
182
167
 
183
168
  var _React$useState = React.useState(initialState.exclude),
184
169
  _React$useState2 = _slicedToArray(_React$useState, 2),
185
170
  exclude = _React$useState2[0],
186
- setExclude = _React$useState2[1]; // the api of our ButtonGroup forces these numerical indexes...
187
- // TODO look into allowing semantic names, similar to the radio component. Tricky part would be backwards compat
171
+ setExclude = _React$useState2[1];
188
172
 
189
-
190
- var _React$useState3 = React.useState(function () {
191
- switch (initialState.excludeKind) {
192
- case 'value':
193
- return 1;
194
-
195
- case 'range':
196
- default:
197
- // fallthrough
198
- return 0;
199
- }
200
- }),
173
+ var _React$useState3 = React.useState(initialState.comparatorIndex),
201
174
  _React$useState4 = _slicedToArray(_React$useState3, 2),
202
175
  comparatorIndex = _React$useState4[0],
203
- setComparatorIndex = _React$useState4[1]; // We use the d3 function to get the extent as it's a little more robust to null, -Infinity, etc.
204
-
176
+ setComparatorIndex = _React$useState4[1];
205
177
 
206
- var _React$useMemo2 = React.useMemo(function () {
207
- return extent(props.data);
208
- }, [props.data]),
209
- _React$useMemo3 = _slicedToArray(_React$useMemo2, 2),
210
- min = _React$useMemo3[0],
211
- max = _React$useMemo3[1];
212
-
213
- var _React$useState5 = React.useState(function () {
214
- return roundToFixed(initialState.lowerValue || min, precision);
215
- }),
178
+ var _React$useState5 = React.useState(initialState.operatorIndex),
216
179
  _React$useState6 = _slicedToArray(_React$useState5, 2),
217
- lv = _React$useState6[0],
218
- setLower = _React$useState6[1];
180
+ operatorIndex = _React$useState6[0],
181
+ setOperatorIndex = _React$useState6[1];
219
182
 
220
- var _React$useState7 = React.useState(function () {
221
- return roundToFixed(initialState.upperValue || max, precision);
222
- }),
183
+ var _React$useState7 = React.useState(initialState.left),
223
184
  _React$useState8 = _slicedToArray(_React$useState7, 2),
224
- uv = _React$useState8[0],
225
- setUpper = _React$useState8[1]; // We keep a separate value for the single select, to give a user the ability to toggle between
226
- // the range and single values without losing their previous input.
227
-
185
+ left = _React$useState8[0],
186
+ setLeft = _React$useState8[1];
228
187
 
229
- var _React$useState9 = React.useState(function () {
230
- return roundToFixed(initialState.lowerValue || median(props.data), precision);
231
- }),
188
+ var _React$useState9 = React.useState(initialState.right),
232
189
  _React$useState10 = _slicedToArray(_React$useState9, 2),
233
- sv = _React$useState10[0],
234
- setSingle = _React$useState10[1]; // This is the only conditional which we want to use to determine
235
- // if we are in range or single value mode.
236
- // Don't derive it via something else, e.g. lowerValue === upperValue, etc.
237
-
190
+ right = _React$useState10[0],
191
+ setRight = _React$useState10[1];
238
192
 
239
193
  var isRange = comparatorIndex === 0;
240
- var excludeKind = isRange ? 'range' : 'value'; // while the user is inputting values, we take their input at face value,
241
- // if we don't do this, a user can't input partial numbers, e.g. "-", or "3."
194
+ var min = React.useMemo(function () {
195
+ return Math.min.apply(Math, _toConsumableArray(props.data));
196
+ }, [props.data]);
197
+ var max = React.useMemo(function () {
198
+ return Math.max.apply(Math, _toConsumableArray(props.data));
199
+ }, [props.data]);
200
+ React.useEffect(function () {
201
+ if (!left) {
202
+ setLeft(min.toString());
203
+ }
242
204
 
243
- var _React$useState11 = React.useState(false),
244
- _React$useState12 = _slicedToArray(_React$useState11, 2),
245
- focused = _React$useState12[0],
246
- setFocus = _React$useState12[1];
205
+ if (!right) {
206
+ setRight(max.toString());
207
+ }
208
+ }, []);
247
209
 
248
- var _React$useMemo4 = React.useMemo(function () {
249
- if (focused) {
250
- return [isRange ? lv : sv, uv];
251
- } // once the user is done inputting.
252
- // we validate then format to the given precision
210
+ var _React$useMemo = React.useMemo(function () {
211
+ if (!isRange) return [false, false];
253
212
 
213
+ switch (operatorIndex) {
214
+ case 4:
215
+ return [false, false];
254
216
 
255
- var l = isRange ? lv : sv;
256
- l = validateInput(l) ? l : min;
257
- var h = validateInput(uv) ? uv : max;
258
- return [roundToFixed(l, precision), roundToFixed(h, precision)];
259
- }, [isRange, focused, sv, lv, uv, precision]),
260
- _React$useMemo5 = _slicedToArray(_React$useMemo4, 2),
261
- inputValueLower = _React$useMemo5[0],
262
- inputValueUpper = _React$useMemo5[1]; // We bound the values within our min and max even if a user enters a huge number
217
+ case 0:
218
+ case 2:
219
+ return [true, false];
263
220
 
221
+ case 1:
222
+ case 3:
223
+ return [false, true];
264
224
 
265
- var sliderValue = isRange ? [Math.max(inputValueLower, min), Math.min(inputValueUpper, max)] : [Math.min(Math.max(inputValueLower, min), max)]; // keep the slider happy by sorting the two values
225
+ default:
226
+ return [true, true];
227
+ }
228
+ }, [operatorIndex, isRange]),
229
+ _React$useMemo2 = _slicedToArray(_React$useMemo, 2),
230
+ leftDisabled = _React$useMemo2[0],
231
+ rightDisabled = _React$useMemo2[1];
232
+
233
+ var leftInputRef = React.useRef(null);
234
+ var rightInputRef = React.useRef(null);
235
+ React.useEffect(function () {
236
+ if (!leftDisabled && leftInputRef.current) {
237
+ leftInputRef.current.focus({
238
+ preventScroll: true
239
+ });
240
+ } else if (!rightDisabled && rightInputRef.current) {
241
+ rightInputRef.current.focus({
242
+ preventScroll: true
243
+ });
244
+ }
245
+ }, [leftDisabled, rightDisabled, comparatorIndex]);
246
+ React.useEffect(function () {
247
+ switch (operatorIndex) {
248
+ case 4:
249
+ default:
250
+ break;
266
251
 
267
- if (isRange && sliderValue[0] > sliderValue[1]) {
268
- sliderValue = [sliderValue[1], sliderValue[0]];
269
- }
252
+ case 1:
253
+ case 3:
254
+ setRight(max.toString());
255
+ break;
270
256
 
257
+ case 0:
258
+ case 2:
259
+ setLeft(min.toString());
260
+ break;
261
+ }
262
+ }, [operatorIndex]);
271
263
  return /*#__PURE__*/React.createElement(FilterShell, {
272
264
  exclude: exclude,
273
265
  onExcludeChange: function onExcludeChange() {
274
266
  return setExclude(!exclude);
275
267
  },
276
- excludeKind: excludeKind,
277
268
  onApply: function onApply() {
278
269
  if (isRange) {
279
- var lowerValue = parseFloat(inputValueLower);
280
- var upperValue = parseFloat(inputValueUpper);
281
- props.setFilter({
282
- description: "\u2265 ".concat(lowerValue, " and \u2264 ").concat(upperValue),
283
- exclude: exclude,
284
- lowerValue: lowerValue,
285
- upperValue: upperValue,
286
- excludeKind: excludeKind
287
- });
270
+ switch (operatorIndex) {
271
+ case 0:
272
+ {
273
+ var _value = parseFloat(right);
274
+
275
+ var operation = NUMERICAL_OPERATIONS.LT;
276
+ props.setFilter({
277
+ comparisons: [{
278
+ value: _value,
279
+ operation: operation
280
+ }],
281
+ description: "< ".concat(_value),
282
+ exclude: exclude
283
+ });
284
+ break;
285
+ }
286
+
287
+ case 1:
288
+ {
289
+ var _value2 = parseFloat(left);
290
+
291
+ var _operation = NUMERICAL_OPERATIONS.GT;
292
+ props.setFilter({
293
+ comparisons: [{
294
+ value: _value2,
295
+ operation: _operation
296
+ }],
297
+ description: "> ".concat(_value2),
298
+ exclude: exclude
299
+ });
300
+ break;
301
+ }
302
+
303
+ case 2:
304
+ {
305
+ var _value3 = parseFloat(right);
306
+
307
+ var _operation2 = NUMERICAL_OPERATIONS.LTE;
308
+ props.setFilter({
309
+ comparisons: [{
310
+ value: _value3,
311
+ operation: _operation2
312
+ }],
313
+ description: "\u2264 ".concat(_value3),
314
+ exclude: exclude
315
+ });
316
+ break;
317
+ }
318
+
319
+ case 3:
320
+ {
321
+ var _value4 = parseFloat(left);
322
+
323
+ var _operation3 = NUMERICAL_OPERATIONS.GTE;
324
+ props.setFilter({
325
+ comparisons: [{
326
+ value: _value4,
327
+ operation: _operation3
328
+ }],
329
+ description: "\u2265 ".concat(_value4),
330
+ exclude: exclude
331
+ });
332
+ break;
333
+ }
334
+
335
+ case 4:
336
+ {
337
+ // 'between' case is interesting since if we want less than 10 plus greater than 5
338
+ // comparators, the filter will include _all_ numbers.
339
+ var leftValue = parseFloat(left);
340
+ var rightValue = parseFloat(right);
341
+ props.setFilter({
342
+ comparisons: [{
343
+ value: leftValue,
344
+ operation: NUMERICAL_OPERATIONS.LT
345
+ }, {
346
+ value: rightValue,
347
+ operation: NUMERICAL_OPERATIONS.GT
348
+ }],
349
+ description: "\u2265 ".concat(leftValue, " & \u2264 ").concat(rightValue),
350
+ exclude: !exclude
351
+ });
352
+ break;
353
+ }
354
+
355
+ default:
356
+ break;
357
+ }
288
358
  } else {
289
- var _value = parseFloat(inputValueLower);
359
+ var _value5 = parseFloat(left);
290
360
 
361
+ var _operation4 = NUMERICAL_OPERATIONS.EQ;
291
362
  props.setFilter({
292
- description: "= ".concat(_value),
293
- exclude: exclude,
294
- lowerValue: inputValueLower,
295
- upperValue: inputValueLower,
296
- excludeKind: excludeKind
363
+ comparisons: [{
364
+ value: _value5,
365
+ operation: _operation4
366
+ }],
367
+ description: "= ".concat(_value5),
368
+ exclude: exclude
297
369
  });
298
370
  }
299
371
 
300
372
  props.close();
301
373
  }
302
374
  }, /*#__PURE__*/React.createElement(ButtonGroup, {
303
- size: SIZE.mini,
375
+ size: SIZE.compact,
304
376
  mode: MODE.radio,
305
377
  selected: comparatorIndex,
306
378
  onClick: function onClick(_, index) {
@@ -308,8 +380,8 @@ function NumericalFilter(props) {
308
380
  },
309
381
  overrides: {
310
382
  Root: {
311
- style: function style(_ref2) {
312
- var $theme = _ref2.$theme;
383
+ style: function style(_ref) {
384
+ var $theme = _ref.$theme;
313
385
  return {
314
386
  marginBottom: $theme.sizing.scale300
315
387
  };
@@ -324,8 +396,7 @@ function NumericalFilter(props) {
324
396
  width: '100%'
325
397
  }
326
398
  }
327
- },
328
- "aria-label": locale.datatable.numericalFilterRange
399
+ }
329
400
  }, locale.datatable.numericalFilterRange), /*#__PURE__*/React.createElement(Button, {
330
401
  type: "button",
331
402
  overrides: {
@@ -334,167 +405,123 @@ function NumericalFilter(props) {
334
405
  width: '100%'
335
406
  }
336
407
  }
337
- },
338
- "aria-label": locale.datatable.numericalFilterSingleValue
339
- }, locale.datatable.numericalFilterSingleValue)), /*#__PURE__*/React.createElement(Histogram, {
340
- data: props.data,
341
- lower: inputValueLower,
342
- upper: inputValueUpper,
343
- isRange: isRange,
344
- exclude: exclude,
345
- precision: props.options.precision
346
- }), /*#__PURE__*/React.createElement("div", {
347
- className: css({
348
- display: 'flex',
349
- justifyContent: 'space-between'
350
- })
351
- }, /*#__PURE__*/React.createElement(Slider // The slider throws errors when switching between single and two values
352
- // when it tries to read getThumbDistance on a thumb which is not there anymore
353
- // if we create a new instance these errors are prevented.
354
- , {
355
- key: isRange.toString(),
356
- min: min,
357
- max: max,
358
- value: sliderValue,
359
- onChange: function onChange(_ref3) {
360
- var value = _ref3.value;
361
-
362
- if (!value) {
363
- return;
364
- }
365
-
366
- if (isRange) {
367
- var _value2 = _slicedToArray(value, 2),
368
- lowerValue = _value2[0],
369
- upperValue = _value2[1];
370
-
371
- setLower(lowerValue);
372
- setUpper(upperValue);
373
- } else {
374
- var _value3 = _slicedToArray(value, 1),
375
- singleValue = _value3[0];
376
-
377
- setSingle(singleValue);
378
- }
408
+ }
409
+ }, locale.datatable.numericalFilterSingleValue)), isRange && /*#__PURE__*/React.createElement(ButtonGroup, {
410
+ size: SIZE.compact,
411
+ mode: MODE.radio,
412
+ selected: operatorIndex,
413
+ onClick: function onClick(_, index) {
414
+ return setOperatorIndex(index);
379
415
  },
380
416
  overrides: {
381
- InnerThumb: function InnerThumb(_ref4) {
382
- var $value = _ref4.$value,
383
- $thumbIndex = _ref4.$thumbIndex;
384
- return /*#__PURE__*/React.createElement(React.Fragment, null, $value[$thumbIndex]);
385
- },
386
- TickBar: function TickBar(_ref5) {
387
- var $min = _ref5.$min,
388
- $max = _ref5.$max;
389
- return null;
390
- },
391
- // we don't want the ticks
392
- ThumbValue: function ThumbValue() {
393
- return null;
394
- },
395
417
  Root: {
396
- style: function style() {
418
+ style: function style(_ref2) {
419
+ var $theme = _ref2.$theme;
397
420
  return {
398
- // Aligns the center of the slider handles with the histogram bars
399
- width: 'calc(100% + 14px)',
400
- margin: '0 -7px'
421
+ marginBottom: $theme.sizing.scale500
401
422
  };
402
423
  }
403
- },
404
- InnerTrack: {
405
- style: function style(_ref6) {
406
- var $theme = _ref6.$theme;
407
-
408
- if (!isRange) {
409
- return {
410
- // For range selection we use the color as is, but when selecting the single value,
411
- // we don't want the track standing out, so mute its color
412
- background: theme.colors.mono400
413
- };
414
- }
424
+ }
425
+ }
426
+ }, /*#__PURE__*/React.createElement(Button, {
427
+ type: "button",
428
+ overrides: {
429
+ BaseButton: {
430
+ style: {
431
+ width: '100%'
415
432
  }
416
- },
417
- Thumb: {
418
- style: function style() {
419
- return {
420
- // Slider handles are small enough to visually be centered within each histogram bar
421
- height: '18px',
422
- width: '18px',
423
- fontSize: '0px'
424
- };
433
+ }
434
+ }
435
+ }, "<"), /*#__PURE__*/React.createElement(Button, {
436
+ type: "button",
437
+ overrides: {
438
+ BaseButton: {
439
+ style: {
440
+ width: '100%'
441
+ }
442
+ }
443
+ }
444
+ }, ">"), /*#__PURE__*/React.createElement(Button, {
445
+ type: "button",
446
+ overrides: {
447
+ BaseButton: {
448
+ style: {
449
+ width: '100%'
450
+ }
451
+ }
452
+ }
453
+ }, "\u2264"), /*#__PURE__*/React.createElement(Button, {
454
+ type: "button",
455
+ overrides: {
456
+ BaseButton: {
457
+ style: {
458
+ width: '100%'
425
459
  }
426
460
  }
427
461
  }
428
- })), /*#__PURE__*/React.createElement("div", {
462
+ }, "\u2265"), /*#__PURE__*/React.createElement(Button, {
463
+ type: "button",
464
+ overrides: {
465
+ BaseButton: {
466
+ style: {
467
+ width: '100%'
468
+ }
469
+ }
470
+ }
471
+ }, "=")), /*#__PURE__*/React.createElement("div", {
472
+ className: css({
473
+ display: 'flex',
474
+ justifyContent: 'space-between',
475
+ marginLeft: theme.sizing.scale300,
476
+ marginRight: theme.sizing.scale300
477
+ })
478
+ }, /*#__PURE__*/React.createElement(ParagraphXSmall, null, format(min, props.options)), ' ', /*#__PURE__*/React.createElement(ParagraphXSmall, null, format(max, props.options))), /*#__PURE__*/React.createElement("div", {
429
479
  className: css({
430
480
  display: 'flex',
431
- marginTop: theme.sizing.scale400,
432
- // This % gap is visually appealing given the filter box width
433
- gap: '30%',
434
481
  justifyContent: 'space-between'
435
482
  })
436
483
  }, /*#__PURE__*/React.createElement(Input, {
437
- min: min,
438
- max: max,
439
- size: INPUT_SIZE.mini,
484
+ size: INPUT_SIZE.compact,
440
485
  overrides: {
441
486
  Root: {
442
487
  style: {
443
- width: '100%'
488
+ width: isRange ? '152px' : '100%'
444
489
  }
445
490
  }
446
491
  },
447
- value: inputValueLower,
492
+ disabled: leftDisabled,
493
+ inputRef: leftInputRef,
494
+ value: left,
448
495
  onChange: function onChange(event) {
449
496
  if (validateInput(event.target.value)) {
450
- isRange ? // $FlowFixMe - we know it is a number by now
451
- setLower(event.target.value) : // $FlowFixMe - we know it is a number by now
452
- setSingle(event.target.value);
497
+ setLeft(event.target.value);
453
498
  }
454
- },
455
- onFocus: function onFocus() {
456
- return setFocus(true);
457
- },
458
- onBlur: function onBlur() {
459
- return setFocus(false);
460
499
  }
461
500
  }), isRange && /*#__PURE__*/React.createElement(Input, {
462
- min: min,
463
- max: max,
464
- size: INPUT_SIZE.mini,
501
+ size: INPUT_SIZE.compact,
465
502
  overrides: {
466
- Input: {
467
- style: {
468
- textAlign: 'right'
469
- }
470
- },
471
503
  Root: {
472
504
  style: {
473
- width: '100%'
505
+ width: '152px'
474
506
  }
475
507
  }
476
508
  },
477
- value: inputValueUpper,
509
+ disabled: rightDisabled,
510
+ inputRef: rightInputRef,
511
+ value: right,
478
512
  onChange: function onChange(event) {
479
513
  if (validateInput(event.target.value)) {
480
- // $FlowFixMe - we know it is a number by now
481
- setUpper(event.target.value);
514
+ setRight(event.target.value);
482
515
  }
483
- },
484
- onFocus: function onFocus() {
485
- return setFocus(true);
486
- },
487
- onBlur: function onBlur() {
488
- return setFocus(false);
489
516
  }
490
517
  })));
491
518
  }
492
519
 
493
520
  function NumericalCell(props) {
494
- var _useStyletron5 = useStyletron(),
495
- _useStyletron6 = _slicedToArray(_useStyletron5, 2),
496
- css = _useStyletron6[0],
497
- theme = _useStyletron6[1];
521
+ var _useStyletron3 = useStyletron(),
522
+ _useStyletron4 = _slicedToArray(_useStyletron3, 2),
523
+ css = _useStyletron4[0],
524
+ theme = _useStyletron4[1];
498
525
 
499
526
  return /*#__PURE__*/React.createElement("div", {
500
527
  className: css(_objectSpread(_objectSpread({}, theme.typography.MonoParagraphXSmall), {}, {
@@ -537,8 +564,30 @@ function NumericalColumn(options) {
537
564
  kind: COLUMNS.NUMERICAL,
538
565
  buildFilter: function buildFilter(params) {
539
566
  return function (data) {
540
- var value = roundToFixed(data, normalizedOptions.precision);
541
- var included = value >= params.lowerValue && value <= params.upperValue;
567
+ var included = params.comparisons.some(function (c) {
568
+ var left = roundToFixed(data, normalizedOptions.precision);
569
+ var right = roundToFixed(c.value, normalizedOptions.precision);
570
+
571
+ switch (c.operation) {
572
+ case NUMERICAL_OPERATIONS.EQ:
573
+ return left === right;
574
+
575
+ case NUMERICAL_OPERATIONS.GT:
576
+ return left > right;
577
+
578
+ case NUMERICAL_OPERATIONS.GTE:
579
+ return left >= right;
580
+
581
+ case NUMERICAL_OPERATIONS.LT:
582
+ return left < right;
583
+
584
+ case NUMERICAL_OPERATIONS.LTE:
585
+ return left <= right;
586
+
587
+ default:
588
+ return true;
589
+ }
590
+ });
542
591
  return params.exclude ? !included : included;
543
592
  };
544
593
  },