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.
@@ -6,14 +6,6 @@ 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
-
17
9
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
18
10
 
19
11
  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."); }
@@ -37,11 +29,12 @@ import { Button, SIZE } from '../button/index.js';
37
29
  import { ButtonGroup, MODE } from '../button-group/index.js';
38
30
  import { Input, SIZE as INPUT_SIZE } from '../input/index.js';
39
31
  import { useStyletron } from '../styles/index.js';
40
- import { ParagraphXSmall } from '../typography/index.js';
41
32
  import Column from './column.js';
42
- import { COLUMNS, NUMERICAL_FORMATS, NUMERICAL_OPERATIONS } from './constants.js';
33
+ import { COLUMNS, NUMERICAL_FORMATS, MAX_BIN_COUNT, HISTOGRAM_SIZE } from './constants.js';
43
34
  import FilterShell from './filter-shell.js';
44
35
  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';
45
38
 
46
39
  function roundToFixed(value, precision) {
47
40
  var k = Math.pow(10, precision);
@@ -88,291 +81,231 @@ function validateInput(input) {
88
81
  return Boolean(parseFloat(input)) || input === '' || input === '-';
89
82
  }
90
83
 
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
- }
103
- } else {
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
- }
147
- }
148
- }
149
-
150
- return {
151
- exclude: false,
152
- comparatorIndex: 0,
153
- operatorIndex: 0,
154
- left: '',
155
- right: ''
156
- };
157
- }
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;
158
94
 
159
- function NumericalFilter(props) {
160
95
  var _useStyletron = useStyletron(),
161
96
  _useStyletron2 = _slicedToArray(_useStyletron, 2),
162
97
  css = _useStyletron2[0],
163
98
  theme = _useStyletron2[1];
164
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;
143
+ } 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;
151
+ }
152
+
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
+ });
163
+
164
+ function NumericalFilter(props) {
165
+ var _useStyletron3 = useStyletron(),
166
+ _useStyletron4 = _slicedToArray(_useStyletron3, 2),
167
+ css = _useStyletron4[0],
168
+ theme = _useStyletron4[1];
169
+
165
170
  var locale = React.useContext(LocaleContext);
166
- var initialState = filterParamsToInitialState(props.filterParams);
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]);
167
182
 
168
183
  var _React$useState = React.useState(initialState.exclude),
169
184
  _React$useState2 = _slicedToArray(_React$useState, 2),
170
185
  exclude = _React$useState2[0],
171
- setExclude = _React$useState2[1];
172
-
173
- var _React$useState3 = React.useState(initialState.comparatorIndex),
174
- _React$useState4 = _slicedToArray(_React$useState3, 2),
175
- comparatorIndex = _React$useState4[0],
176
- setComparatorIndex = _React$useState4[1];
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
177
188
 
178
- var _React$useState5 = React.useState(initialState.operatorIndex),
179
- _React$useState6 = _slicedToArray(_React$useState5, 2),
180
- operatorIndex = _React$useState6[0],
181
- setOperatorIndex = _React$useState6[1];
182
189
 
183
- var _React$useState7 = React.useState(initialState.left),
184
- _React$useState8 = _slicedToArray(_React$useState7, 2),
185
- left = _React$useState8[0],
186
- setLeft = _React$useState8[1];
187
-
188
- var _React$useState9 = React.useState(initialState.right),
189
- _React$useState10 = _slicedToArray(_React$useState9, 2),
190
- right = _React$useState10[0],
191
- setRight = _React$useState10[1];
190
+ var _React$useState3 = React.useState(function () {
191
+ switch (initialState.excludeKind) {
192
+ case 'value':
193
+ return 1;
192
194
 
193
- var isRange = comparatorIndex === 0;
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());
195
+ case 'range':
196
+ default:
197
+ // fallthrough
198
+ return 0;
203
199
  }
200
+ }),
201
+ _React$useState4 = _slicedToArray(_React$useState3, 2),
202
+ 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
204
 
205
- if (!right) {
206
- setRight(max.toString());
207
- }
208
- }, []);
209
205
 
210
- var _React$useMemo = React.useMemo(function () {
211
- if (!isRange) return [false, false];
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
212
 
213
- switch (operatorIndex) {
214
- case 4:
215
- return [false, false];
213
+ var _React$useState5 = React.useState(function () {
214
+ return roundToFixed(initialState.lowerValue || min, precision);
215
+ }),
216
+ _React$useState6 = _slicedToArray(_React$useState5, 2),
217
+ lv = _React$useState6[0],
218
+ setLower = _React$useState6[1];
216
219
 
217
- case 0:
218
- case 2:
219
- return [true, false];
220
+ var _React$useState7 = React.useState(function () {
221
+ return roundToFixed(initialState.upperValue || max, precision);
222
+ }),
223
+ _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.
220
227
 
221
- case 1:
222
- case 3:
223
- return [false, true];
224
228
 
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;
229
+ var _React$useState9 = React.useState(function () {
230
+ return roundToFixed(initialState.lowerValue || median(props.data), precision);
231
+ }),
232
+ _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.
251
237
 
252
- case 1:
253
- case 3:
254
- setRight(max.toString());
255
- break;
256
238
 
257
- case 0:
258
- case 2:
259
- setLeft(min.toString());
260
- break;
261
- }
262
- }, [operatorIndex]);
239
+ 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."
242
+
243
+ var _React$useState11 = React.useState(false),
244
+ _React$useState12 = _slicedToArray(_React$useState11, 2),
245
+ focused = _React$useState12[0],
246
+ setFocus = _React$useState12[1];
247
+
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
253
+
254
+
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 have our slider values range from 1 to the bin size, so we have a scale which
263
+ // takes in the data driven range and maps it to values the scale can always handle
264
+
265
+
266
+ var sliderScale = React.useMemo(function () {
267
+ return scaleLinear().domain([min, max]).rangeRound([1, MAX_BIN_COUNT]) // We clamp the values within our min and max even if a user enters a huge number
268
+ .clamp(true);
269
+ }, [min, max]);
270
+ var sliderValue = isRange ? [sliderScale(inputValueLower), sliderScale(inputValueUpper)] : [sliderScale(inputValueLower)]; // keep the slider happy by sorting the two values
271
+
272
+ if (isRange && sliderValue[0] > sliderValue[1]) {
273
+ sliderValue = [sliderValue[1], sliderValue[0]];
274
+ }
275
+
263
276
  return /*#__PURE__*/React.createElement(FilterShell, {
264
277
  exclude: exclude,
265
278
  onExcludeChange: function onExcludeChange() {
266
279
  return setExclude(!exclude);
267
280
  },
281
+ excludeKind: excludeKind,
268
282
  onApply: function onApply() {
269
283
  if (isRange) {
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
- }
284
+ var lowerValue = parseFloat(inputValueLower);
285
+ var upperValue = parseFloat(inputValueUpper);
286
+ props.setFilter({
287
+ description: "\u2265 ".concat(lowerValue, " and \u2264 ").concat(upperValue),
288
+ exclude: exclude,
289
+ lowerValue: lowerValue,
290
+ upperValue: upperValue,
291
+ excludeKind: excludeKind
292
+ });
358
293
  } else {
359
- var _value5 = parseFloat(left);
294
+ var _value = parseFloat(inputValueLower);
360
295
 
361
- var _operation4 = NUMERICAL_OPERATIONS.EQ;
362
296
  props.setFilter({
363
- comparisons: [{
364
- value: _value5,
365
- operation: _operation4
366
- }],
367
- description: "= ".concat(_value5),
368
- exclude: exclude
297
+ description: "= ".concat(_value),
298
+ exclude: exclude,
299
+ lowerValue: inputValueLower,
300
+ upperValue: inputValueLower,
301
+ excludeKind: excludeKind
369
302
  });
370
303
  }
371
304
 
372
305
  props.close();
373
306
  }
374
307
  }, /*#__PURE__*/React.createElement(ButtonGroup, {
375
- size: SIZE.compact,
308
+ size: SIZE.mini,
376
309
  mode: MODE.radio,
377
310
  selected: comparatorIndex,
378
311
  onClick: function onClick(_, index) {
@@ -380,8 +313,8 @@ function NumericalFilter(props) {
380
313
  },
381
314
  overrides: {
382
315
  Root: {
383
- style: function style(_ref) {
384
- var $theme = _ref.$theme;
316
+ style: function style(_ref2) {
317
+ var $theme = _ref2.$theme;
385
318
  return {
386
319
  marginBottom: $theme.sizing.scale300
387
320
  };
@@ -396,7 +329,8 @@ function NumericalFilter(props) {
396
329
  width: '100%'
397
330
  }
398
331
  }
399
- }
332
+ },
333
+ "aria-label": locale.datatable.numericalFilterRange
400
334
  }, locale.datatable.numericalFilterRange), /*#__PURE__*/React.createElement(Button, {
401
335
  type: "button",
402
336
  overrides: {
@@ -405,123 +339,168 @@ function NumericalFilter(props) {
405
339
  width: '100%'
406
340
  }
407
341
  }
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);
342
+ },
343
+ "aria-label": locale.datatable.numericalFilterSingleValue
344
+ }, locale.datatable.numericalFilterSingleValue)), /*#__PURE__*/React.createElement(Histogram, {
345
+ data: props.data,
346
+ lower: inputValueLower,
347
+ upper: inputValueUpper,
348
+ isRange: isRange,
349
+ exclude: exclude,
350
+ precision: props.options.precision
351
+ }), /*#__PURE__*/React.createElement("div", {
352
+ className: css({
353
+ display: 'flex',
354
+ justifyContent: 'space-between'
355
+ })
356
+ }, /*#__PURE__*/React.createElement(Slider // The slider throws errors when switching between single and two values
357
+ // when it tries to read getThumbDistance on a thumb which is not there anymore
358
+ // if we create a new instance these errors are prevented.
359
+ , {
360
+ key: isRange.toString(),
361
+ min: 1,
362
+ max: MAX_BIN_COUNT,
363
+ value: sliderValue,
364
+ onChange: function onChange(_ref3) {
365
+ var value = _ref3.value;
366
+
367
+ if (!value) {
368
+ return;
369
+ } // we convert back from the slider scale to the actual data's scale
370
+
371
+
372
+ if (isRange) {
373
+ var _value2 = _slicedToArray(value, 2),
374
+ lowerValue = _value2[0],
375
+ upperValue = _value2[1];
376
+
377
+ setLower(sliderScale.invert(lowerValue));
378
+ setUpper(sliderScale.invert(upperValue));
379
+ } else {
380
+ var _value3 = _slicedToArray(value, 1),
381
+ singleValue = _value3[0];
382
+
383
+ setSingle(sliderScale.invert(singleValue));
384
+ }
415
385
  },
416
386
  overrides: {
387
+ InnerThumb: function InnerThumb(_ref4) {
388
+ var $value = _ref4.$value,
389
+ $thumbIndex = _ref4.$thumbIndex;
390
+ return /*#__PURE__*/React.createElement(React.Fragment, null, $value[$thumbIndex]);
391
+ },
392
+ TickBar: function TickBar(_ref5) {
393
+ var $min = _ref5.$min,
394
+ $max = _ref5.$max;
395
+ return null;
396
+ },
397
+ // we don't want the ticks
398
+ ThumbValue: function ThumbValue() {
399
+ return null;
400
+ },
417
401
  Root: {
418
- style: function style(_ref2) {
419
- var $theme = _ref2.$theme;
402
+ style: function style() {
420
403
  return {
421
- marginBottom: $theme.sizing.scale500
404
+ // Aligns the center of the slider handles with the histogram bars
405
+ width: 'calc(100% + 14px)',
406
+ margin: '0 -7px'
422
407
  };
423
408
  }
424
- }
425
- }
426
- }, /*#__PURE__*/React.createElement(Button, {
427
- type: "button",
428
- overrides: {
429
- BaseButton: {
430
- style: {
431
- width: '100%'
432
- }
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%'
409
+ },
410
+ InnerTrack: {
411
+ style: function style(_ref6) {
412
+ var $theme = _ref6.$theme;
413
+
414
+ if (!isRange) {
415
+ return {
416
+ // For range selection we use the color as is, but when selecting the single value,
417
+ // we don't want the track standing out, so mute its color
418
+ background: theme.colors.mono400
419
+ };
420
+ }
459
421
  }
460
- }
461
- }
462
- }, "\u2265"), /*#__PURE__*/React.createElement(Button, {
463
- type: "button",
464
- overrides: {
465
- BaseButton: {
466
- style: {
467
- width: '100%'
422
+ },
423
+ Thumb: {
424
+ style: function style() {
425
+ return {
426
+ // Slider handles are small enough to visually be centered within each histogram bar
427
+ height: '18px',
428
+ width: '18px',
429
+ fontSize: '0px'
430
+ };
468
431
  }
469
432
  }
470
433
  }
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", {
434
+ })), /*#__PURE__*/React.createElement("div", {
479
435
  className: css({
480
436
  display: 'flex',
437
+ marginTop: theme.sizing.scale400,
438
+ // This % gap is visually appealing given the filter box width
439
+ gap: '30%',
481
440
  justifyContent: 'space-between'
482
441
  })
483
442
  }, /*#__PURE__*/React.createElement(Input, {
484
- size: INPUT_SIZE.compact,
443
+ min: min,
444
+ max: max,
445
+ size: INPUT_SIZE.mini,
485
446
  overrides: {
486
447
  Root: {
487
448
  style: {
488
- width: isRange ? '152px' : '100%'
449
+ width: '100%'
489
450
  }
490
451
  }
491
452
  },
492
- disabled: leftDisabled,
493
- inputRef: leftInputRef,
494
- value: left,
453
+ value: inputValueLower,
495
454
  onChange: function onChange(event) {
496
455
  if (validateInput(event.target.value)) {
497
- setLeft(event.target.value);
456
+ isRange ? // $FlowFixMe - we know it is a number by now
457
+ setLower(event.target.value) : // $FlowFixMe - we know it is a number by now
458
+ setSingle(event.target.value);
498
459
  }
460
+ },
461
+ onFocus: function onFocus() {
462
+ return setFocus(true);
463
+ },
464
+ onBlur: function onBlur() {
465
+ return setFocus(false);
499
466
  }
500
467
  }), isRange && /*#__PURE__*/React.createElement(Input, {
501
- size: INPUT_SIZE.compact,
468
+ min: min,
469
+ max: max,
470
+ size: INPUT_SIZE.mini,
502
471
  overrides: {
472
+ Input: {
473
+ style: {
474
+ textAlign: 'right'
475
+ }
476
+ },
503
477
  Root: {
504
478
  style: {
505
- width: '152px'
479
+ width: '100%'
506
480
  }
507
481
  }
508
482
  },
509
- disabled: rightDisabled,
510
- inputRef: rightInputRef,
511
- value: right,
483
+ value: inputValueUpper,
512
484
  onChange: function onChange(event) {
513
485
  if (validateInput(event.target.value)) {
514
- setRight(event.target.value);
486
+ // $FlowFixMe - we know it is a number by now
487
+ setUpper(event.target.value);
515
488
  }
489
+ },
490
+ onFocus: function onFocus() {
491
+ return setFocus(true);
492
+ },
493
+ onBlur: function onBlur() {
494
+ return setFocus(false);
516
495
  }
517
496
  })));
518
497
  }
519
498
 
520
499
  function NumericalCell(props) {
521
- var _useStyletron3 = useStyletron(),
522
- _useStyletron4 = _slicedToArray(_useStyletron3, 2),
523
- css = _useStyletron4[0],
524
- theme = _useStyletron4[1];
500
+ var _useStyletron5 = useStyletron(),
501
+ _useStyletron6 = _slicedToArray(_useStyletron5, 2),
502
+ css = _useStyletron6[0],
503
+ theme = _useStyletron6[1];
525
504
 
526
505
  return /*#__PURE__*/React.createElement("div", {
527
506
  className: css(_objectSpread(_objectSpread({}, theme.typography.MonoParagraphXSmall), {}, {
@@ -564,30 +543,8 @@ function NumericalColumn(options) {
564
543
  kind: COLUMNS.NUMERICAL,
565
544
  buildFilter: function buildFilter(params) {
566
545
  return function (data) {
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
- });
546
+ var value = roundToFixed(data, normalizedOptions.precision);
547
+ var included = value >= params.lowerValue && value <= params.upperValue;
591
548
  return params.exclude ? !included : included;
592
549
  };
593
550
  },