baseui 10.8.0 → 10.9.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.
Files changed (170) hide show
  1. package/a11y/a11y.js +2 -2
  2. package/a11y/a11y.js.flow +3 -3
  3. package/button/styled-components.js +47 -18
  4. package/button/styled-components.js.flow +25 -5
  5. package/combobox/combobox.js +6 -3
  6. package/combobox/combobox.js.flow +4 -2
  7. package/combobox/types.js.flow +2 -0
  8. package/data-table/column-categorical.js +1 -1
  9. package/data-table/column-categorical.js.flow +2 -2
  10. package/data-table/column-numerical.js +307 -355
  11. package/data-table/column-numerical.js.flow +273 -287
  12. package/data-table/constants.js +17 -11
  13. package/data-table/constants.js.flow +11 -8
  14. package/data-table/data-table.js +53 -50
  15. package/data-table/data-table.js.flow +18 -13
  16. package/data-table/filter-shell.js +27 -4
  17. package/data-table/filter-shell.js.flow +33 -9
  18. package/data-table/locale.js +4 -2
  19. package/data-table/locale.js.flow +6 -2
  20. package/data-table/measure-column-widths.js +83 -121
  21. package/data-table/measure-column-widths.js.flow +87 -109
  22. package/datepicker/styled-components.js +1 -1
  23. package/datepicker/styled-components.js.flow +4 -1
  24. package/drawer/drawer.js +3 -1
  25. package/drawer/drawer.js.flow +7 -1
  26. package/es/a11y/a11y.js +2 -2
  27. package/es/button/styled-components.js +32 -2
  28. package/es/combobox/combobox.js +6 -3
  29. package/es/data-table/column-categorical.js +2 -2
  30. package/es/data-table/column-numerical.js +245 -317
  31. package/es/data-table/constants.js +12 -8
  32. package/es/data-table/data-table.js +18 -16
  33. package/es/data-table/filter-shell.js +26 -4
  34. package/es/data-table/locale.js +4 -2
  35. package/es/data-table/measure-column-widths.js +75 -86
  36. package/es/datepicker/styled-components.js +1 -1
  37. package/es/drawer/drawer.js +3 -1
  38. package/es/index.js +1 -1
  39. package/es/map-marker/badge-enhancer.js +61 -0
  40. package/es/map-marker/constants.js +146 -2
  41. package/es/map-marker/drag-shadow.js +32 -0
  42. package/es/map-marker/fixed-marker.js +54 -48
  43. package/es/map-marker/floating-marker.js +21 -12
  44. package/es/map-marker/index.js +1 -1
  45. package/es/map-marker/label-enhancer.js +39 -0
  46. package/es/map-marker/needle.js +26 -0
  47. package/es/map-marker/pin-head.js +42 -40
  48. package/es/map-marker/styled-components.js +177 -32
  49. package/es/map-marker/types.js +1 -1
  50. package/es/menu/maybe-child-menu.js +0 -2
  51. package/es/menu/nested-menus.js +49 -3
  52. package/es/menu/stateful-container.js +13 -12
  53. package/es/modal/modal.js +3 -1
  54. package/es/popover/popover.js +3 -1
  55. package/es/progress-bar/index.js +1 -1
  56. package/es/progress-bar/progressbar.js +25 -10
  57. package/es/progress-bar/styled-components.js +9 -5
  58. package/es/select/select-component.js +2 -10
  59. package/es/spinner/styled-components.js +34 -16
  60. package/es/table/filter.js +3 -1
  61. package/es/themes/dark-theme/color-component-tokens.js +4 -0
  62. package/es/themes/light-theme/color-component-tokens.js +4 -0
  63. package/es/timezonepicker/timezone-picker.js +53 -36
  64. package/es/timezonepicker/tzdata.js +2 -0
  65. package/es/timezonepicker/update-tzdata.js +69 -0
  66. package/esm/a11y/a11y.js +3 -3
  67. package/esm/button/styled-components.js +47 -18
  68. package/esm/combobox/combobox.js +6 -3
  69. package/esm/data-table/column-categorical.js +2 -2
  70. package/esm/data-table/column-numerical.js +304 -353
  71. package/esm/data-table/constants.js +12 -8
  72. package/esm/data-table/data-table.js +53 -50
  73. package/esm/data-table/filter-shell.js +26 -4
  74. package/esm/data-table/locale.js +4 -2
  75. package/esm/data-table/measure-column-widths.js +83 -121
  76. package/esm/datepicker/styled-components.js +1 -1
  77. package/esm/drawer/drawer.js +3 -1
  78. package/esm/index.js +1 -1
  79. package/esm/map-marker/badge-enhancer.js +79 -0
  80. package/esm/map-marker/constants.js +94 -4
  81. package/esm/map-marker/drag-shadow.js +53 -0
  82. package/esm/map-marker/fixed-marker.js +84 -80
  83. package/esm/map-marker/floating-marker.js +22 -13
  84. package/esm/map-marker/index.js +1 -1
  85. package/esm/map-marker/label-enhancer.js +60 -0
  86. package/esm/map-marker/needle.js +43 -0
  87. package/esm/map-marker/pin-head.js +77 -66
  88. package/esm/map-marker/styled-components.js +182 -51
  89. package/esm/map-marker/types.js +1 -1
  90. package/esm/menu/maybe-child-menu.js +0 -2
  91. package/esm/menu/nested-menus.js +66 -5
  92. package/esm/menu/stateful-container.js +15 -13
  93. package/esm/modal/modal.js +3 -1
  94. package/esm/popover/popover.js +3 -1
  95. package/esm/progress-bar/index.js +1 -1
  96. package/esm/progress-bar/progressbar.js +32 -10
  97. package/esm/progress-bar/styled-components.js +9 -4
  98. package/esm/select/select-component.js +2 -11
  99. package/esm/spinner/styled-components.js +35 -16
  100. package/esm/table/filter.js +3 -1
  101. package/esm/themes/dark-theme/color-component-tokens.js +4 -0
  102. package/esm/themes/light-theme/color-component-tokens.js +4 -0
  103. package/esm/timezonepicker/timezone-picker.js +64 -36
  104. package/esm/timezonepicker/tzdata.js +2 -0
  105. package/esm/timezonepicker/update-tzdata.js +160 -0
  106. package/index.js +6 -0
  107. package/index.js.flow +1 -1
  108. package/map-marker/badge-enhancer.js +90 -0
  109. package/map-marker/badge-enhancer.js.flow +86 -0
  110. package/map-marker/constants.js +103 -5
  111. package/map-marker/constants.js.flow +152 -0
  112. package/map-marker/drag-shadow.js +64 -0
  113. package/map-marker/drag-shadow.js.flow +52 -0
  114. package/map-marker/fixed-marker.js +84 -78
  115. package/map-marker/fixed-marker.js.flow +78 -66
  116. package/map-marker/floating-marker.js +22 -13
  117. package/map-marker/floating-marker.js.flow +30 -17
  118. package/map-marker/index.d.ts +125 -24
  119. package/map-marker/index.js +18 -0
  120. package/map-marker/index.js.flow +3 -0
  121. package/map-marker/label-enhancer.js +71 -0
  122. package/map-marker/label-enhancer.js.flow +63 -0
  123. package/map-marker/needle.js +54 -0
  124. package/map-marker/needle.js.flow +29 -0
  125. package/map-marker/pin-head.js +80 -69
  126. package/map-marker/pin-head.js.flow +122 -84
  127. package/map-marker/styled-components.js +200 -62
  128. package/map-marker/styled-components.js.flow +172 -22
  129. package/map-marker/types.js.flow +69 -20
  130. package/menu/index.d.ts +9 -4
  131. package/menu/maybe-child-menu.js +0 -2
  132. package/menu/maybe-child-menu.js.flow +0 -2
  133. package/menu/nested-menus.js +66 -5
  134. package/menu/nested-menus.js.flow +50 -5
  135. package/menu/stateful-container.js +15 -13
  136. package/menu/stateful-container.js.flow +19 -13
  137. package/menu/types.js.flow +7 -1
  138. package/modal/modal.js +3 -1
  139. package/modal/modal.js.flow +2 -0
  140. package/package.json +5 -4
  141. package/popover/popover.js +3 -1
  142. package/popover/popover.js.flow +2 -0
  143. package/progress-bar/index.d.ts +2 -0
  144. package/progress-bar/index.js +6 -0
  145. package/progress-bar/index.js.flow +1 -0
  146. package/progress-bar/progressbar.js +32 -10
  147. package/progress-bar/progressbar.js.flow +35 -9
  148. package/progress-bar/styled-components.js +9 -4
  149. package/progress-bar/styled-components.js.flow +15 -4
  150. package/progress-bar/types.js.flow +12 -2
  151. package/select/select-component.js +2 -11
  152. package/select/select-component.js.flow +5 -7
  153. package/spinner/styled-components.js +35 -16
  154. package/spinner/styled-components.js.flow +37 -19
  155. package/spinner/types.js.flow +10 -0
  156. package/styles/index.js.flow +1 -1
  157. package/table/filter.js +3 -1
  158. package/table/filter.js.flow +5 -1
  159. package/themes/dark-theme/color-component-tokens.js +4 -0
  160. package/themes/dark-theme/color-component-tokens.js.flow +4 -0
  161. package/themes/light-theme/color-component-tokens.js +4 -0
  162. package/themes/light-theme/color-component-tokens.js.flow +4 -0
  163. package/themes/types.js.flow +4 -0
  164. package/timezonepicker/timezone-picker.js +69 -41
  165. package/timezonepicker/timezone-picker.js.flow +52 -46
  166. package/timezonepicker/types.js.flow +1 -1
  167. package/timezonepicker/tzdata.js +10 -0
  168. package/timezonepicker/tzdata.js.flow +347 -0
  169. package/timezonepicker/update-tzdata.js +164 -0
  170. package/timezonepicker/update-tzdata.js.flow +70 -0
@@ -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 { Paragraph4 } 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,226 @@ 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
- }
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;
149
94
 
150
- return {
151
- exclude: false,
152
- comparatorIndex: 0,
153
- operatorIndex: 0,
154
- left: '',
155
- right: ''
156
- };
157
- }
158
-
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];
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
172
188
 
173
- var _React$useState3 = React.useState(initialState.comparatorIndex),
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
+ }),
174
201
  _React$useState4 = _slicedToArray(_React$useState3, 2),
175
202
  comparatorIndex = _React$useState4[0],
176
- setComparatorIndex = _React$useState4[1];
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
+
177
205
 
178
- var _React$useState5 = React.useState(initialState.operatorIndex),
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
+ }),
179
216
  _React$useState6 = _slicedToArray(_React$useState5, 2),
180
- operatorIndex = _React$useState6[0],
181
- setOperatorIndex = _React$useState6[1];
217
+ lv = _React$useState6[0],
218
+ setLower = _React$useState6[1];
182
219
 
183
- var _React$useState7 = React.useState(initialState.left),
220
+ var _React$useState7 = React.useState(function () {
221
+ return roundToFixed(initialState.upperValue || max, precision);
222
+ }),
184
223
  _React$useState8 = _slicedToArray(_React$useState7, 2),
185
- left = _React$useState8[0],
186
- setLeft = _React$useState8[1];
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
+
187
228
 
188
- var _React$useState9 = React.useState(initialState.right),
229
+ var _React$useState9 = React.useState(function () {
230
+ return roundToFixed(initialState.lowerValue || median(props.data), precision);
231
+ }),
189
232
  _React$useState10 = _slicedToArray(_React$useState9, 2),
190
- right = _React$useState10[0],
191
- setRight = _React$useState10[1];
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
+
192
238
 
193
239
  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());
203
- }
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."
204
242
 
205
- if (!right) {
206
- setRight(max.toString());
207
- }
208
- }, []);
243
+ var _React$useState11 = React.useState(false),
244
+ _React$useState12 = _slicedToArray(_React$useState11, 2),
245
+ focused = _React$useState12[0],
246
+ setFocus = _React$useState12[1];
209
247
 
210
- var _React$useMemo = React.useMemo(function () {
211
- if (!isRange) return [false, false];
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
212
253
 
213
- switch (operatorIndex) {
214
- case 4:
215
- return [false, false];
216
254
 
217
- case 0:
218
- case 2:
219
- return [true, false];
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
220
263
 
221
- case 1:
222
- case 3:
223
- return [false, true];
224
264
 
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;
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
251
266
 
252
- case 1:
253
- case 3:
254
- setRight(max.toString());
255
- break;
267
+ if (isRange && sliderValue[0] > sliderValue[1]) {
268
+ sliderValue = [sliderValue[1], sliderValue[0]];
269
+ }
256
270
 
257
- case 0:
258
- case 2:
259
- setLeft(min.toString());
260
- break;
261
- }
262
- }, [operatorIndex]);
263
271
  return /*#__PURE__*/React.createElement(FilterShell, {
264
272
  exclude: exclude,
265
273
  onExcludeChange: function onExcludeChange() {
266
274
  return setExclude(!exclude);
267
275
  },
276
+ excludeKind: excludeKind,
268
277
  onApply: function onApply() {
269
278
  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
- }
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
+ });
358
288
  } else {
359
- var _value5 = parseFloat(left);
289
+ var _value = parseFloat(inputValueLower);
360
290
 
361
- var _operation4 = NUMERICAL_OPERATIONS.EQ;
362
291
  props.setFilter({
363
- comparisons: [{
364
- value: _value5,
365
- operation: _operation4
366
- }],
367
- description: "= ".concat(_value5),
368
- exclude: exclude
292
+ description: "= ".concat(_value),
293
+ exclude: exclude,
294
+ lowerValue: inputValueLower,
295
+ upperValue: inputValueLower,
296
+ excludeKind: excludeKind
369
297
  });
370
298
  }
371
299
 
372
300
  props.close();
373
301
  }
374
302
  }, /*#__PURE__*/React.createElement(ButtonGroup, {
375
- size: SIZE.compact,
303
+ size: SIZE.mini,
376
304
  mode: MODE.radio,
377
305
  selected: comparatorIndex,
378
306
  onClick: function onClick(_, index) {
@@ -380,8 +308,8 @@ function NumericalFilter(props) {
380
308
  },
381
309
  overrides: {
382
310
  Root: {
383
- style: function style(_ref) {
384
- var $theme = _ref.$theme;
311
+ style: function style(_ref2) {
312
+ var $theme = _ref2.$theme;
385
313
  return {
386
314
  marginBottom: $theme.sizing.scale300
387
315
  };
@@ -396,7 +324,8 @@ function NumericalFilter(props) {
396
324
  width: '100%'
397
325
  }
398
326
  }
399
- }
327
+ },
328
+ "aria-label": locale.datatable.numericalFilterRange
400
329
  }, locale.datatable.numericalFilterRange), /*#__PURE__*/React.createElement(Button, {
401
330
  type: "button",
402
331
  overrides: {
@@ -405,123 +334,167 @@ function NumericalFilter(props) {
405
334
  width: '100%'
406
335
  }
407
336
  }
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);
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
+ }
415
379
  },
416
380
  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
+ },
417
395
  Root: {
418
- style: function style(_ref2) {
419
- var $theme = _ref2.$theme;
396
+ style: function style() {
420
397
  return {
421
- marginBottom: $theme.sizing.scale500
398
+ // Aligns the center of the slider handles with the histogram bars
399
+ width: 'calc(100% + 14px)',
400
+ margin: '0 -7px'
422
401
  };
423
402
  }
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%'
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
+ }
459
415
  }
460
- }
461
- }
462
- }, "\u2265"), /*#__PURE__*/React.createElement(Button, {
463
- type: "button",
464
- overrides: {
465
- BaseButton: {
466
- style: {
467
- width: '100%'
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
+ };
468
425
  }
469
426
  }
470
427
  }
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(Paragraph4, null, format(min, props.options)), ' ', /*#__PURE__*/React.createElement(Paragraph4, null, format(max, props.options))), /*#__PURE__*/React.createElement("div", {
428
+ })), /*#__PURE__*/React.createElement("div", {
479
429
  className: css({
480
430
  display: 'flex',
431
+ marginTop: theme.sizing.scale400,
432
+ // This % gap is visually appealing given the filter box width
433
+ gap: '30%',
481
434
  justifyContent: 'space-between'
482
435
  })
483
436
  }, /*#__PURE__*/React.createElement(Input, {
484
- size: INPUT_SIZE.compact,
437
+ min: min,
438
+ max: max,
439
+ size: INPUT_SIZE.mini,
485
440
  overrides: {
486
441
  Root: {
487
442
  style: {
488
- width: isRange ? '152px' : '100%'
443
+ width: '100%'
489
444
  }
490
445
  }
491
446
  },
492
- disabled: leftDisabled,
493
- inputRef: leftInputRef,
494
- value: left,
447
+ value: inputValueLower,
495
448
  onChange: function onChange(event) {
496
449
  if (validateInput(event.target.value)) {
497
- setLeft(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);
498
453
  }
454
+ },
455
+ onFocus: function onFocus() {
456
+ return setFocus(true);
457
+ },
458
+ onBlur: function onBlur() {
459
+ return setFocus(false);
499
460
  }
500
461
  }), isRange && /*#__PURE__*/React.createElement(Input, {
501
- size: INPUT_SIZE.compact,
462
+ min: min,
463
+ max: max,
464
+ size: INPUT_SIZE.mini,
502
465
  overrides: {
466
+ Input: {
467
+ style: {
468
+ textAlign: 'right'
469
+ }
470
+ },
503
471
  Root: {
504
472
  style: {
505
- width: '152px'
473
+ width: '100%'
506
474
  }
507
475
  }
508
476
  },
509
- disabled: rightDisabled,
510
- inputRef: rightInputRef,
511
- value: right,
477
+ value: inputValueUpper,
512
478
  onChange: function onChange(event) {
513
479
  if (validateInput(event.target.value)) {
514
- setRight(event.target.value);
480
+ // $FlowFixMe - we know it is a number by now
481
+ setUpper(event.target.value);
515
482
  }
483
+ },
484
+ onFocus: function onFocus() {
485
+ return setFocus(true);
486
+ },
487
+ onBlur: function onBlur() {
488
+ return setFocus(false);
516
489
  }
517
490
  })));
518
491
  }
519
492
 
520
493
  function NumericalCell(props) {
521
- var _useStyletron3 = useStyletron(),
522
- _useStyletron4 = _slicedToArray(_useStyletron3, 2),
523
- css = _useStyletron4[0],
524
- theme = _useStyletron4[1];
494
+ var _useStyletron5 = useStyletron(),
495
+ _useStyletron6 = _slicedToArray(_useStyletron5, 2),
496
+ css = _useStyletron6[0],
497
+ theme = _useStyletron6[1];
525
498
 
526
499
  return /*#__PURE__*/React.createElement("div", {
527
500
  className: css(_objectSpread(_objectSpread({}, theme.typography.MonoParagraphXSmall), {}, {
@@ -564,30 +537,8 @@ function NumericalColumn(options) {
564
537
  kind: COLUMNS.NUMERICAL,
565
538
  buildFilter: function buildFilter(params) {
566
539
  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
- });
540
+ var value = roundToFixed(data, normalizedOptions.precision);
541
+ var included = value >= params.lowerValue && value <= params.upperValue;
591
542
  return params.exclude ? !included : included;
592
543
  };
593
544
  },