@elastic/charts 46.2.0 → 46.5.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 (32) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/chart_types/flame_chart/flame_chart.js +297 -46
  3. package/dist/chart_types/flame_chart/flame_chart.js.map +1 -1
  4. package/dist/chart_types/flame_chart/render/common.js +3 -2
  5. package/dist/chart_types/flame_chart/render/common.js.map +1 -1
  6. package/dist/chart_types/flame_chart/render/draw_a_frame.js +40 -15
  7. package/dist/chart_types/flame_chart/render/draw_a_frame.js.map +1 -1
  8. package/dist/chart_types/flame_chart/render/draw_canvas.js +24 -12
  9. package/dist/chart_types/flame_chart/render/draw_canvas.js.map +1 -1
  10. package/dist/chart_types/flame_chart/render/draw_webgl.js +1 -1
  11. package/dist/chart_types/flame_chart/render/draw_webgl.js.map +1 -1
  12. package/dist/chart_types/flame_chart/render/ensure_webgl.js +15 -9
  13. package/dist/chart_types/flame_chart/render/ensure_webgl.js.map +1 -1
  14. package/dist/chart_types/flame_chart/shaders.js +1 -1
  15. package/dist/chart_types/flame_chart/shaders.js.map +1 -1
  16. package/dist/chart_types/flame_chart/types.js +5 -1
  17. package/dist/chart_types/flame_chart/types.js.map +1 -1
  18. package/dist/common/default_theme_attributes.d.ts +2 -0
  19. package/dist/common/default_theme_attributes.d.ts.map +1 -0
  20. package/dist/common/default_theme_attributes.js +5 -0
  21. package/dist/common/default_theme_attributes.js.map +1 -0
  22. package/dist/common/kingly.js +90 -76
  23. package/dist/common/kingly.js.map +1 -1
  24. package/dist/common/webgl_constants.d.ts +2 -0
  25. package/dist/common/webgl_constants.d.ts.map +1 -0
  26. package/dist/common/webgl_constants.js +559 -0
  27. package/dist/common/webgl_constants.js.map +1 -0
  28. package/dist/components/chart_container.js +2 -2
  29. package/dist/components/chart_container.js.map +1 -1
  30. package/dist/state/selectors/get_legend_size.js +2 -2
  31. package/dist/state/selectors/get_legend_size.js.map +1 -1
  32. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ # [46.5.0](https://github.com/elastic/elastic-charts/compare/v46.4.0...v46.5.0) (2022-05-26)
2
+
3
+
4
+ ### Features
5
+
6
+ * **flame:** context loss handling ([#1682](https://github.com/elastic/elastic-charts/issues/1682)) ([0e32209](https://github.com/elastic/elastic-charts/commit/0e3220955661348c6cf02d4e379ddec340f0ccfc))
7
+
8
+ # [46.4.0](https://github.com/elastic/elastic-charts/compare/v46.3.0...v46.4.0) (2022-05-24)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **deps:** update dependency @elastic/eui to v58 ([#1677](https://github.com/elastic/elastic-charts/issues/1677)) ([69ad62b](https://github.com/elastic/elastic-charts/commit/69ad62bf57d880f45a5250b8ccfb75da54c8f205))
14
+
15
+
16
+ ### Features
17
+
18
+ * **flame:** minimap pan ([#1678](https://github.com/elastic/elastic-charts/issues/1678)) ([fc81ada](https://github.com/elastic/elastic-charts/commit/fc81ada306c042b751a523588bf0eead43881327))
19
+
20
+ # [46.3.0](https://github.com/elastic/elastic-charts/compare/v46.2.0...v46.3.0) (2022-05-19)
21
+
22
+
23
+ ### Features
24
+
25
+ * **flame:** search and other utilities ([#1676](https://github.com/elastic/elastic-charts/issues/1676)) ([b8eaa1f](https://github.com/elastic/elastic-charts/commit/b8eaa1f6266e150cf7153c30c5d7a1c6e21bbac4))
26
+
1
27
  # [46.2.0](https://github.com/elastic/elastic-charts/compare/v46.1.0...v46.2.0) (2022-05-18)
2
28
 
3
29
 
@@ -52,6 +52,7 @@ var redux_1 = require("redux");
52
52
  var __1 = require("..");
53
53
  var constants_1 = require("../../common/constants");
54
54
  var kingly_1 = require("../../common/kingly");
55
+ var webgl_constants_1 = require("../../common/webgl_constants");
55
56
  var tooltip_1 = require("../../components/tooltip/tooltip");
56
57
  var specs_1 = require("../../specs");
57
58
  var chart_1 = require("../../state/actions/chart");
@@ -68,13 +69,19 @@ var types_1 = require("./types");
68
69
  var PINCH_ZOOM_CHECK_INTERVAL_MS = 100;
69
70
  var SIDE_OVERSHOOT_RATIO = 0.05;
70
71
  var RECURRENCE_ALPHA_PER_MS_X = 0.01;
71
- var RECURRENCE_ALPHA_PER_MS_Y = 0.01;
72
+ var RECURRENCE_ALPHA_PER_MS_Y = 0.0062;
72
73
  var SINGLE_CLICK_EMPTY_FOCUS = true;
73
74
  var IS_META_REQUIRED_FOR_ZOOM = false;
74
75
  var ZOOM_SPEED = 0.0015;
75
76
  var DEEPEST_ZOOM_RATIO = 1e-7;
76
77
  var ZOOM_FROM_EDGE_BAND = 16;
78
+ var ZOOM_FROM_EDGE_BAND_LEFT = ZOOM_FROM_EDGE_BAND + draw_a_frame_1.PADDING_LEFT;
79
+ var ZOOM_FROM_EDGE_BAND_RIGHT = ZOOM_FROM_EDGE_BAND + draw_a_frame_1.PADDING_RIGHT;
80
+ var ZOOM_FROM_EDGE_BAND_TOP = ZOOM_FROM_EDGE_BAND + draw_a_frame_1.PADDING_TOP;
81
+ var ZOOM_FROM_EDGE_BAND_BOTTOM = ZOOM_FROM_EDGE_BAND + draw_a_frame_1.PADDING_BOTTOM;
77
82
  var LEFT_MOUSE_BUTTON = 1;
83
+ var MINIMAP_SIZE_RATIO_X = 3;
84
+ var MINIMAP_SIZE_RATIO_Y = 3;
78
85
  var unitRowPitch = function (position) { return (position.length >= 4 ? position[1] - position[3] : 1); };
79
86
  var initialPixelRowPitch = function () { return 16; };
80
87
  var specValueFormatter = function (d) { return d; };
@@ -93,21 +100,21 @@ var columnToRowPositions = function (_a, i) {
93
100
  y1: position1[i * 2 + 1] + unitRowPitch(position1),
94
101
  });
95
102
  };
96
- var focusRect = function (columnarViewModel, chartHeight, drilldownDatumIndex, drilldownTimestamp) {
97
- var _a = columnToRowPositions(columnarViewModel, drilldownDatumIndex || 0), x0 = _a.x0, x1 = _a.x1, y0 = _a.y0, y1 = _a.y1;
103
+ var focusForArea = function (chartHeight, _a) {
104
+ var x0 = _a.x0, x1 = _a.x1, y0 = _a.y0, y1 = _a.y1;
98
105
  var sideOvershoot = SIDE_OVERSHOOT_RATIO * (x1 - x0);
99
106
  var unitHeight = (chartHeight / initialPixelRowPitch()) * (y1 - y0);
100
107
  var intendedY0 = y1 - unitHeight;
101
108
  var bottomOvershoot = Math.max(0, -intendedY0);
102
109
  var top = Math.min(1, y1 + bottomOvershoot);
103
110
  return {
104
- timestamp: drilldownTimestamp,
105
111
  x0: Math.max(0, x0 - sideOvershoot),
106
112
  x1: Math.min(1, x1 + sideOvershoot),
107
113
  y0: Math.max(0, intendedY0),
108
114
  y1: Math.min(1, top),
109
115
  };
110
116
  };
117
+ var focusRect = function (columnarViewModel, chartHeight, drilldownDatumIndex, drilldownTimestamp) { return (__assign({ timestamp: drilldownTimestamp }, focusForArea(chartHeight, columnToRowPositions(columnarViewModel, drilldownDatumIndex || 0)))); };
111
118
  var getColor = function (c, i) {
112
119
  var r = Math.round(255 * c[4 * i]);
113
120
  var g = Math.round(255 * c[4 * i + 1]);
@@ -119,14 +126,29 @@ var colorToDatumIndex = function (pixel) {
119
126
  var isEmptyArea = pixel[0] + pixel[1] + pixel[2] + pixel[3] < shaders_1.GEOM_INDEX_OFFSET;
120
127
  return isEmptyArea ? NaN : pixel[3] + 256 * (pixel[2] + 256 * (pixel[1] + 256 * pixel[0])) - shaders_1.GEOM_INDEX_OFFSET;
121
128
  };
129
+ var getRegExp = function (searchString) {
130
+ var regex;
131
+ try {
132
+ regex = new RegExp(searchString);
133
+ }
134
+ catch (_a) {
135
+ return new RegExp('iIUiUYIuiGjhG678987gjhgfytr678576');
136
+ }
137
+ return regex;
138
+ };
122
139
  var FlameComponent = (function (_super) {
123
140
  __extends(FlameComponent, _super);
124
141
  function FlameComponent(props) {
125
142
  var _this = _super.call(this, props) || this;
126
143
  _this.startOfDragX = NaN;
127
- _this.startOfDragX0 = NaN;
128
144
  _this.startOfDragY = NaN;
129
- _this.startOfDragY0 = NaN;
145
+ _this.startOfDragFocusLeft = NaN;
146
+ _this.startOfDragFocusTop = NaN;
147
+ _this.currentSearchString = '';
148
+ _this.currentSearchHitCount = 0;
149
+ _this.caseSensitive = false;
150
+ _this.useRegex = false;
151
+ _this.focusedMatchIndex = NaN;
130
152
  _this.setupDevicePixelRatioChangeListener = function () {
131
153
  window.matchMedia("(resolution: " + window.devicePixelRatio + "dppx)").addEventListener('change', function () {
132
154
  _this.setState({});
@@ -151,11 +173,18 @@ var FlameComponent = (function (_super) {
151
173
  _this.setupDevicePixelRatioChangeListener();
152
174
  (_a = _this.props.containerRef().current) === null || _a === void 0 ? void 0 : _a.addEventListener('wheel', _this.preventScroll, { passive: false });
153
175
  };
176
+ _this.ensureTextureAndDraw = function () {
177
+ _this.ensurePickTexture();
178
+ _this.drawCanvas();
179
+ };
154
180
  _this.componentDidUpdate = function () {
155
181
  if (!_this.ctx)
156
182
  _this.tryCanvasContext();
157
- _this.ensurePickTexture();
158
- _this.drawCanvas();
183
+ _this.ensureTextureAndDraw();
184
+ };
185
+ _this.pointerInMinimap = function (x, y) {
186
+ return x === (0, common_1.clamp)(x, _this.getMinimapLeft(), _this.getMinimapLeft() + _this.getMinimapWidth()) &&
187
+ y === (0, common_1.clamp)(y, _this.getMinimapTop(), _this.getMinimapTop() + _this.getMinimapHeight());
159
188
  };
160
189
  _this.datumAtXY = function (x, y) {
161
190
  return _this.glContext ? colorToDatumIndex((0, kingly_1.readPixel)(_this.glContext, x, y)) : NaN;
@@ -198,42 +227,47 @@ var FlameComponent = (function (_super) {
198
227
  e.stopPropagation();
199
228
  _this.updatePointerLocation(e);
200
229
  if (_this.isDragging(e)) {
230
+ var dragInMinimap = _this.pointerInMinimap(_this.startOfDragX, _this.startOfDragY);
231
+ var focusMoveDirection = dragInMinimap ? 1 : -1;
201
232
  var _a = _this.currentFocus, x0 = _a.x0, x1 = _a.x1, y0 = _a.y0, y1 = _a.y1;
202
233
  var focusWidth = x1 - x0;
203
234
  var focusHeight = y1 - y0;
204
- if (Number.isNaN(_this.startOfDragX0))
205
- _this.startOfDragX0 = x0;
206
- if (Number.isNaN(_this.startOfDragY0))
207
- _this.startOfDragY0 = y0;
235
+ if (Number.isNaN(_this.startOfDragFocusLeft))
236
+ _this.startOfDragFocusLeft = x0;
237
+ if (Number.isNaN(_this.startOfDragFocusTop))
238
+ _this.startOfDragFocusTop = y0;
208
239
  var dragDistanceX = _this.getDragDistanceX();
209
240
  var dragDistanceY = _this.getDragDistanceY();
210
241
  var _b = _this.props.chartDimensions, chartWidth = _b.width, chartHeight = _b.height;
211
- var deltaIntentX = (-dragDistanceX / chartWidth) * focusWidth;
212
- var deltaIntentY = (-dragDistanceY / chartHeight) * focusHeight;
242
+ var focusChartWidth = chartWidth - draw_a_frame_1.PADDING_LEFT - draw_a_frame_1.PADDING_RIGHT;
243
+ var focusChartHeight = chartHeight - draw_a_frame_1.PADDING_TOP - draw_a_frame_1.PADDING_BOTTOM;
244
+ var dragSpeedX = (dragInMinimap ? MINIMAP_SIZE_RATIO_X / focusWidth : 1) / focusChartWidth;
245
+ var dragSpeedY = (dragInMinimap ? MINIMAP_SIZE_RATIO_Y / focusHeight : 1) / focusChartHeight;
246
+ var deltaIntentX = focusMoveDirection * dragDistanceX * dragSpeedX * focusWidth;
247
+ var deltaIntentY = focusMoveDirection * dragDistanceY * dragSpeedY * focusHeight;
213
248
  var deltaCorrectionX = deltaIntentX > 0
214
- ? Math.min(0, 1 - (_this.startOfDragX0 + focusWidth + deltaIntentX))
215
- : -Math.min(0, _this.startOfDragX0 + deltaIntentX);
249
+ ? Math.min(0, 1 - (_this.startOfDragFocusLeft + focusWidth + deltaIntentX))
250
+ : -Math.min(0, _this.startOfDragFocusLeft + deltaIntentX);
216
251
  var deltaCorrectionY = deltaIntentY > 0
217
- ? Math.min(0, 1 - (_this.startOfDragY0 + focusHeight + deltaIntentY))
218
- : -Math.min(0, _this.startOfDragY0 + deltaIntentY);
252
+ ? Math.min(0, 1 - (_this.startOfDragFocusTop + focusHeight + deltaIntentY))
253
+ : -Math.min(0, _this.startOfDragFocusTop + deltaIntentY);
219
254
  var deltaX = deltaIntentX + deltaCorrectionX;
220
255
  var deltaY = deltaIntentY + deltaCorrectionY;
221
- var newX0 = (0, common_1.clamp)(_this.startOfDragX0 + deltaX, 0, 1);
222
- var newX1 = (0, common_1.clamp)(_this.startOfDragX0 + focusWidth + deltaX, 0, 1);
223
- var newY0 = (0, common_1.clamp)(_this.startOfDragY0 + deltaY, 0, 1);
224
- var newY1 = (0, common_1.clamp)(_this.startOfDragY0 + focusHeight + deltaY, 0, 1);
256
+ var newX0 = (0, common_1.clamp)(_this.startOfDragFocusLeft + deltaX, 0, 1);
257
+ var newX1 = (0, common_1.clamp)(_this.startOfDragFocusLeft + focusWidth + deltaX, 0, 1);
258
+ var newY0 = (0, common_1.clamp)(_this.startOfDragFocusTop + deltaY, 0, 1);
259
+ var newY1 = (0, common_1.clamp)(_this.startOfDragFocusTop + focusHeight + deltaY, 0, 1);
225
260
  var newFocus = { x0: newX0, x1: newX1, y0: newY0, y1: newY1, timestamp: e.timeStamp };
226
261
  _this.currentFocus = newFocus;
227
262
  _this.targetFocus = newFocus;
228
- _this.hoverIndex = NaN;
229
- _this.setState({});
263
+ _this.smartDraw();
230
264
  }
231
265
  };
232
266
  _this.clearDrag = function () {
233
267
  _this.startOfDragX = NaN;
234
- _this.startOfDragX0 = NaN;
235
268
  _this.startOfDragY = NaN;
236
- _this.startOfDragY0 = NaN;
269
+ _this.startOfDragFocusLeft = NaN;
270
+ _this.startOfDragFocusTop = NaN;
237
271
  };
238
272
  _this.resetDrag = function () {
239
273
  _this.startOfDragX = _this.pointerX;
@@ -241,6 +275,8 @@ var FlameComponent = (function (_super) {
241
275
  };
242
276
  _this.handleMouseDown = function (e) {
243
277
  e.stopPropagation();
278
+ if (Number.isNaN(_this.pointerX + _this.pointerY))
279
+ return;
244
280
  _this.resetDrag();
245
281
  window.addEventListener('mousemove', _this.handleMouseDragMove, { passive: true });
246
282
  window.addEventListener('mouseup', _this.handleMouseUp, { passive: true });
@@ -257,7 +293,7 @@ var FlameComponent = (function (_super) {
257
293
  var isDoubleClick = e.detail > 1;
258
294
  var hasClickedOnRectangle = Number.isFinite(hovered === null || hovered === void 0 ? void 0 : hovered.datumIndex);
259
295
  var mustFocus = SINGLE_CLICK_EMPTY_FOCUS || isDoubleClick !== hasClickedOnRectangle;
260
- if (mustFocus) {
296
+ if (mustFocus && !_this.pointerInMinimap(_this.pointerX, _this.pointerY)) {
261
297
  _this.targetFocus = focusRect(_this.props.columnarViewModel, _this.props.chartDimensions.height, hovered.datumIndex, hovered.timestamp);
262
298
  _this.prevT = NaN;
263
299
  _this.hoverIndex = NaN;
@@ -270,10 +306,7 @@ var FlameComponent = (function (_super) {
270
306
  };
271
307
  _this.handleMouseLeave = function (e) {
272
308
  e.stopPropagation();
273
- if (Number.isFinite(_this.hoverIndex)) {
274
- _this.hoverIndex = NaN;
275
- _this.setState({});
276
- }
309
+ _this.smartDraw();
277
310
  };
278
311
  _this.preventScroll = function (e) { return e.metaKey === IS_META_REQUIRED_FOR_ZOOM && e.preventDefault(); };
279
312
  _this.handleWheel = function (e) {
@@ -286,14 +319,16 @@ var FlameComponent = (function (_super) {
286
319
  var unitX = _this.pointerX / _this.props.chartDimensions.width;
287
320
  var unitY = (_this.props.chartDimensions.height - _this.pointerY) / _this.props.chartDimensions.height;
288
321
  var zoomOut = delta <= 0;
289
- var midX = x0 === 0 && (zoomOut || _this.pointerX < ZOOM_FROM_EDGE_BAND)
322
+ var midX = Math.abs(x0) < draw_a_frame_1.EPSILON && (zoomOut || _this.pointerX < ZOOM_FROM_EDGE_BAND_LEFT)
290
323
  ? 0
291
- : x1 === 1 && (zoomOut || _this.pointerX > _this.props.chartDimensions.width - ZOOM_FROM_EDGE_BAND)
324
+ : Math.abs(x1 - 1) < draw_a_frame_1.EPSILON &&
325
+ (zoomOut || _this.pointerX > _this.props.chartDimensions.width - ZOOM_FROM_EDGE_BAND_RIGHT)
292
326
  ? 1
293
327
  : (0, common_1.clamp)(x0 + unitX * Math.abs(x1 - x0), 0, 1);
294
- var midY = y0 === 0 && (zoomOut || _this.pointerY > _this.props.chartDimensions.height - ZOOM_FROM_EDGE_BAND)
328
+ var midY = Math.abs(y0) < draw_a_frame_1.EPSILON &&
329
+ (zoomOut || _this.pointerY > _this.props.chartDimensions.height - ZOOM_FROM_EDGE_BAND_BOTTOM)
295
330
  ? 0
296
- : y1 === 1 && (zoomOut || _this.pointerY < ZOOM_FROM_EDGE_BAND)
331
+ : Math.abs(y1 - 1) < draw_a_frame_1.EPSILON && (zoomOut || _this.pointerY < ZOOM_FROM_EDGE_BAND_TOP)
297
332
  ? 1
298
333
  : (0, common_1.clamp)(y0 + unitY * Math.abs(y1 - y0), 0, 1);
299
334
  var targetX0 = (0, common_1.clamp)(x0 - delta * (x0 - midX), 0, 1);
@@ -317,9 +352,89 @@ var FlameComponent = (function (_super) {
317
352
  _this.currentFocus = newFocus;
318
353
  _this.targetFocus = newFocus;
319
354
  }
320
- _this.hoverIndex = NaN;
355
+ _this.smartDraw();
356
+ };
357
+ _this.focusOnAllMatches = function () {
358
+ _this.currentSearchHitCount = 0;
359
+ var searchString = _this.currentSearchString;
360
+ var customizedSearchString = _this.caseSensitive ? searchString : searchString.toLowerCase();
361
+ var regex = _this.useRegex && getRegExp(searchString);
362
+ var columns = _this.props.columnarViewModel;
363
+ _this.currentColor = new Float32Array(columns.color);
364
+ var labels = columns.label;
365
+ var size = columns.size1;
366
+ var position = columns.position1;
367
+ var rowHeight = unitRowPitch(position);
368
+ var datumCount = labels.length;
369
+ var x0 = Infinity;
370
+ var x1 = -Infinity;
371
+ var y0 = Infinity;
372
+ var y1 = -Infinity;
373
+ for (var i = 0; i < datumCount; i++) {
374
+ var label = _this.caseSensitive ? labels[i] : labels[i].toLowerCase();
375
+ if (regex ? label.match(regex) : label.includes(customizedSearchString)) {
376
+ _this.currentSearchHitCount++;
377
+ x0 = Math.min(x0, position[2 * i]);
378
+ x1 = Math.max(x1, position[2 * i] + size[i]);
379
+ y0 = Math.min(y0, position[2 * i + 1]);
380
+ y1 = Math.max(y1, position[2 * i + 1] + rowHeight);
381
+ }
382
+ else {
383
+ _this.currentColor[4 * i + 3] *= 0.25;
384
+ }
385
+ }
386
+ if (Number.isFinite(x0)) {
387
+ Object.assign(_this.targetFocus, focusForArea(_this.props.chartDimensions.height, { x0: x0, x1: x1, y0: y0, y1: y1 }));
388
+ }
389
+ };
390
+ _this.uploadSearchColors = function () {
391
+ var colorSetter = _this.glResources.attributes.get('color');
392
+ if (_this.glContext && colorSetter && _this.currentColor.length === _this.props.columnarViewModel.color.length) {
393
+ (0, ensure_webgl_1.uploadToWebgl)(_this.glContext, new Map([['color', colorSetter]]), { color: _this.currentColor });
394
+ }
395
+ };
396
+ _this.searchForText = function (force) {
397
+ var input = _this.searchInputRef.current;
398
+ var searchString = input === null || input === void 0 ? void 0 : input.value;
399
+ if (!input || typeof searchString !== 'string' || (searchString === _this.currentSearchString && !force))
400
+ return;
401
+ _this.currentSearchString = searchString;
402
+ _this.focusOnAllMatches();
403
+ _this.uploadSearchColors();
404
+ _this.focusedMatchIndex = NaN;
321
405
  _this.setState({});
322
406
  };
407
+ _this.handleKeyPress = function (e) {
408
+ e.stopPropagation();
409
+ _this.searchForText(false);
410
+ };
411
+ _this.focusOnHit = function (timestamp) {
412
+ if (Number.isNaN(_this.focusedMatchIndex)) {
413
+ _this.focusOnAllMatches();
414
+ }
415
+ else {
416
+ var datumIndex = NaN;
417
+ var hitEnumerator = -1;
418
+ var searchString = _this.currentSearchString;
419
+ var customizedSearchString = _this.caseSensitive ? searchString : searchString.toLowerCase();
420
+ var regex = _this.useRegex && getRegExp(searchString);
421
+ var labels = _this.props.columnarViewModel.label;
422
+ for (var i = 0; i < labels.length; i++) {
423
+ var label = _this.caseSensitive ? labels[i] : labels[i].toLowerCase();
424
+ if (regex ? label.match(regex) : label.includes(customizedSearchString)) {
425
+ datumIndex = i;
426
+ hitEnumerator++;
427
+ if (hitEnumerator === _this.focusedMatchIndex)
428
+ break;
429
+ }
430
+ }
431
+ if (hitEnumerator >= 0) {
432
+ _this.targetFocus = focusRect(_this.props.columnarViewModel, _this.props.chartDimensions.height, datumIndex, timestamp);
433
+ _this.prevT = NaN;
434
+ _this.hoverIndex = NaN;
435
+ }
436
+ }
437
+ };
323
438
  _this.render = function () {
324
439
  var _a = _this.props, forwardStageRef = _a.forwardStageRef, _b = _a.chartDimensions, requestedWidth = _b.width, requestedHeight = _b.height, a11ySettings = _a.a11ySettings;
325
440
  var width = (0, common_2.roundUpSize)(requestedWidth);
@@ -339,10 +454,100 @@ var FlameComponent = (function (_super) {
339
454
  var canvasWidth = width * dpr;
340
455
  var canvasHeight = height * dpr;
341
456
  var columns = _this.props.columnarViewModel;
457
+ var hitCount = _this.currentSearchHitCount;
342
458
  return (react_1.default.createElement(react_1.default.Fragment, null,
343
459
  react_1.default.createElement("figure", { "aria-labelledby": a11ySettings.labelId, "aria-describedby": a11ySettings.descriptionId },
344
460
  react_1.default.createElement("canvas", { ref: _this.glCanvasRef, className: "echCanvasRenderer", width: canvasWidth, height: canvasHeight, style: style, role: "presentation" }),
345
- react_1.default.createElement("canvas", { ref: forwardStageRef, className: "echCanvasRenderer", width: canvasWidth, height: canvasHeight, onMouseMove: _this.handleMouseHoverMove, onMouseDown: _this.handleMouseDown, onMouseLeave: _this.handleMouseLeave, onWheel: _this.handleWheel, style: style, role: "presentation" })),
461
+ react_1.default.createElement("canvas", { ref: forwardStageRef, tabIndex: 0, className: "echCanvasRenderer", width: canvasWidth, height: canvasHeight, onMouseMove: _this.handleMouseHoverMove, onMouseDown: _this.handleMouseDown, onMouseLeave: _this.handleMouseLeave, onWheel: _this.handleWheel, style: style, role: "presentation" })),
462
+ react_1.default.createElement("div", { style: {
463
+ position: 'absolute',
464
+ transform: "translateY(" + (_this.props.chartDimensions.height - draw_a_frame_1.PADDING_BOTTOM + 4) + "px)",
465
+ } },
466
+ react_1.default.createElement("input", { ref: _this.searchInputRef, title: "Search string or regex pattern", type: "text", tabIndex: 0, placeholder: "Enter search string", onKeyPress: _this.handleKeyPress, onKeyUp: _this.handleKeyPress, style: {
467
+ border: '0px solid lightgray',
468
+ padding: 3,
469
+ outline: 'none',
470
+ background: 'rgba(255,0,255,0)',
471
+ } }),
472
+ react_1.default.createElement("label", { title: "Case sensitivity (highlighted: case sensitive)", style: {
473
+ color: _this.caseSensitive && !_this.useRegex ? 'black' : 'darkgrey',
474
+ backgroundColor: 'rgb(228, 228, 228)',
475
+ fontWeight: 'bolder',
476
+ paddingInline: 4,
477
+ marginInline: 4,
478
+ borderRadius: 4,
479
+ opacity: _this.currentSearchString ? 1 : 0,
480
+ transition: 'opacity 250ms ease-in-out',
481
+ } },
482
+ "Cc",
483
+ react_1.default.createElement("input", { type: "checkbox", tabIndex: 0, onClick: function () {
484
+ if (!_this.currentSearchString)
485
+ return;
486
+ _this.caseSensitive = !_this.caseSensitive;
487
+ _this.searchForText(true);
488
+ }, style: { display: 'none' } })),
489
+ react_1.default.createElement("label", { title: "Regex matching (highlighted: use regex)", style: {
490
+ color: _this.useRegex ? 'black' : 'darkgrey',
491
+ backgroundColor: 'rgb(228, 228, 228)',
492
+ fontWeight: 'bolder',
493
+ paddingInline: 4,
494
+ marginInline: 4,
495
+ borderRadius: 4,
496
+ opacity: _this.currentSearchString ? 1 : 0,
497
+ transition: 'opacity 250ms ease-in-out',
498
+ } },
499
+ ". *",
500
+ react_1.default.createElement("input", { type: "checkbox", tabIndex: 0, onClick: function () {
501
+ if (!_this.currentSearchString)
502
+ return;
503
+ _this.useRegex = !_this.useRegex;
504
+ _this.searchForText(true);
505
+ }, style: { display: 'none' } })),
506
+ react_1.default.createElement("label", { title: "Previous hit", style: {
507
+ color: hitCount ? 'black' : 'darkgrey',
508
+ fontWeight: 'bolder',
509
+ paddingLeft: 16,
510
+ paddingRight: 4,
511
+ opacity: _this.currentSearchString ? 1 : 0,
512
+ transition: 'opacity 250ms ease-in-out',
513
+ } },
514
+ "\u25C0",
515
+ react_1.default.createElement("input", { type: "checkbox", tabIndex: 0, onClick: function (e) {
516
+ if (!_this.currentSearchString)
517
+ return;
518
+ _this.focusedMatchIndex = Number.isNaN(_this.focusedMatchIndex)
519
+ ? hitCount - 1
520
+ : _this.focusedMatchIndex === 0
521
+ ? NaN
522
+ : _this.focusedMatchIndex - 1;
523
+ _this.focusOnHit(e.timeStamp);
524
+ _this.setState({});
525
+ }, style: { display: 'none' } })),
526
+ react_1.default.createElement("label", { title: "Next hit", style: {
527
+ color: hitCount ? 'black' : 'darkgrey',
528
+ fontWeight: 'bolder',
529
+ paddingInline: 4,
530
+ opacity: _this.currentSearchString ? 1 : 0,
531
+ transition: 'opacity 250ms ease-in-out',
532
+ } },
533
+ "\u25B6",
534
+ react_1.default.createElement("input", { type: "checkbox", tabIndex: 0, onClick: function (e) {
535
+ if (!_this.currentSearchString)
536
+ return;
537
+ _this.focusedMatchIndex = _this.focusedMatchIndex = Number.isNaN(_this.focusedMatchIndex)
538
+ ? 0
539
+ : _this.focusedMatchIndex === hitCount - 1
540
+ ? NaN
541
+ : _this.focusedMatchIndex + 1;
542
+ _this.focusOnHit(e.timeStamp);
543
+ _this.setState({});
544
+ }, style: { display: 'none' } })),
545
+ react_1.default.createElement("p", { style: {
546
+ float: 'right',
547
+ padding: 3,
548
+ opacity: _this.currentSearchString ? 1 : 0,
549
+ transition: 'opacity 250ms ease-in-out',
550
+ } }, "Match" + (Number.isNaN(_this.focusedMatchIndex) ? 'es:' : ": " + (_this.focusedMatchIndex + 1) + " /") + " " + hitCount)),
346
551
  react_1.default.createElement(tooltip_1.BasicTooltip, { onPointerMove: function () { return ({ type: mouse_1.ON_POINTER_MOVE, position: { x: NaN, y: NaN }, time: NaN }); }, position: { x: _this.pointerX, y: _this.pointerY, width: 0, height: 0 }, visible: _this.props.tooltipRequired && _this.hoverIndex >= 0, info: {
347
552
  header: null,
348
553
  values: _this.hoverIndex >= 0
@@ -364,7 +569,7 @@ var FlameComponent = (function (_super) {
364
569
  _this.drawCanvas = function () {
365
570
  if (!_this.ctx || !_this.glContext || !_this.pickTexture)
366
571
  return;
367
- var renderFrame = (0, draw_a_frame_1.drawFrame)(_this.ctx, _this.glContext, _this.props.chartDimensions.width, _this.props.chartDimensions.height, window.devicePixelRatio * _this.pinchZoomScale, _this.props.columnarViewModel, _this.pickTexture, _this.glResources.pickTextureRenderer, _this.glResources.roundedRectRenderer, _this.hoverIndex, unitRowPitch(_this.props.columnarViewModel.position1));
572
+ var renderFrame = (0, draw_a_frame_1.drawFrame)(_this.ctx, _this.glContext, _this.props.chartDimensions.width, _this.props.chartDimensions.height, _this.getMinimapWidth(), _this.getMinimapHeight(), _this.getMinimapLeft(), _this.getMinimapTop(), window.devicePixelRatio * _this.pinchZoomScale, _this.props.columnarViewModel, _this.pickTexture, _this.glResources.pickTextureRenderer, _this.glResources.roundedRectRenderer, _this.hoverIndex, unitRowPitch(_this.props.columnarViewModel.position1), _this.currentColor);
368
573
  var anim = function (t) {
369
574
  var msDeltaT = Number.isNaN(_this.prevT) ? 0 : t - _this.prevT;
370
575
  _this.prevT = t;
@@ -376,7 +581,7 @@ var FlameComponent = (function (_super) {
376
581
  var currentExtentY = _this.currentFocus.y1 - _this.currentFocus.y0;
377
582
  var relativeExpansionX = Math.max(1, (currentExtentX + dx1 - dx0) / currentExtentX);
378
583
  var relativeExpansionY = Math.max(1, (currentExtentX + dy1 - dy0) / currentExtentY);
379
- var jointRelativeExpansion = relativeExpansionX * relativeExpansionY;
584
+ var jointRelativeExpansion = (relativeExpansionX + relativeExpansionY) / 2;
380
585
  var convergenceRateX = Math.min(1, msDeltaT * RECURRENCE_ALPHA_PER_MS_X) / jointRelativeExpansion;
381
586
  var convergenceRateY = Math.min(1, msDeltaT * RECURRENCE_ALPHA_PER_MS_Y) / jointRelativeExpansion;
382
587
  _this.currentFocus.x0 += convergenceRateX * dx0;
@@ -385,13 +590,21 @@ var FlameComponent = (function (_super) {
385
590
  _this.currentFocus.y1 += convergenceRateY * dy1;
386
591
  renderFrame([_this.currentFocus.x0, _this.currentFocus.x1, _this.currentFocus.y0, _this.currentFocus.y1]);
387
592
  var maxDiff = Math.max(Math.abs(dx0), Math.abs(dx1), Math.abs(dy0), Math.abs(dy1));
388
- if (maxDiff > 1e-12)
593
+ if (maxDiff > 1e-12) {
389
594
  _this.animationRafId = window.requestAnimationFrame(anim);
595
+ }
596
+ else {
597
+ _this.prevT = NaN;
598
+ }
390
599
  };
391
600
  window.cancelAnimationFrame(_this.animationRafId);
392
601
  _this.animationRafId = window.requestAnimationFrame(anim);
393
602
  _this.props.onRenderChange(true);
394
603
  };
604
+ _this.getMinimapWidth = function () { return _this.props.chartDimensions.width / MINIMAP_SIZE_RATIO_X; };
605
+ _this.getMinimapHeight = function () { return _this.props.chartDimensions.height / MINIMAP_SIZE_RATIO_Y; };
606
+ _this.getMinimapLeft = function () { return _this.props.chartDimensions.width - _this.getMinimapWidth(); };
607
+ _this.getMinimapTop = function () { return _this.props.chartDimensions.height - _this.getMinimapHeight(); };
395
608
  _this.ensurePickTexture = function () {
396
609
  var _a;
397
610
  var _b = _this.props.chartDimensions, width = _b.width, height = _b.height;
@@ -407,20 +620,47 @@ var FlameComponent = (function (_super) {
407
620
  textureIndex: 0,
408
621
  width: textureWidth,
409
622
  height: textureHeight,
410
- internalFormat: _this.glContext.RGBA8,
623
+ internalFormat: webgl_constants_1.GL.RGBA8,
411
624
  data: null,
412
625
  })) !== null && _a !== void 0 ? _a : kingly_1.NullTexture;
413
- (0, kingly_1.bindFramebuffer)(_this.glContext, kingly_1.GL_READ_FRAMEBUFFER, _this.pickTexture.target());
626
+ (0, kingly_1.bindFramebuffer)(_this.glContext, webgl_constants_1.GL.READ_FRAMEBUFFER, _this.pickTexture.target());
414
627
  }
415
628
  };
629
+ _this.initializeGL = function (gl) {
630
+ _this.glResources = (0, ensure_webgl_1.ensureWebgl)(gl, Object.keys(_this.props.columnarViewModel));
631
+ (0, ensure_webgl_1.uploadToWebgl)(gl, _this.glResources.attributes, _this.props.columnarViewModel);
632
+ };
633
+ _this.restoreGL = function (gl) {
634
+ _this.initializeGL(gl);
635
+ _this.pickTexture = kingly_1.NullTexture;
636
+ _this.uploadSearchColors();
637
+ _this.ensureTextureAndDraw();
638
+ };
416
639
  _this.tryCanvasContext = function () {
417
640
  var canvas = _this.props.forwardStageRef.current;
418
641
  var glCanvas = _this.glCanvasRef.current;
419
642
  _this.ctx = canvas && canvas.getContext('2d');
420
643
  _this.glContext = glCanvas && glCanvas.getContext('webgl2');
421
644
  _this.ensurePickTexture();
422
- if (_this.glContext && _this.glResources === types_1.NULL_GL_RESOURCES) {
423
- _this.glResources = (0, ensure_webgl_1.ensureWebgl)(_this.glContext, _this.props.columnarViewModel);
645
+ if (glCanvas && _this.glContext && _this.glResources === types_1.NULL_GL_RESOURCES) {
646
+ glCanvas.addEventListener('webglcontextlost', function (event) {
647
+ window.cancelAnimationFrame(_this.animationRafId);
648
+ event.preventDefault();
649
+ }, false);
650
+ glCanvas.addEventListener('webglcontextrestored', function () {
651
+ if (!glCanvas || !_this.glContext)
652
+ return;
653
+ _this.restoreGL(_this.glContext);
654
+ var widthCss = glCanvas.style.width;
655
+ var widthNum = parseFloat(widthCss);
656
+ glCanvas.style.width = widthNum + 0.1 + "px";
657
+ window.setTimeout(function () {
658
+ glCanvas.style.width = widthCss;
659
+ if (_this.glContext)
660
+ _this.restoreGL(_this.glContext);
661
+ }, 0);
662
+ }, false);
663
+ _this.initializeGL(_this.glContext);
424
664
  }
425
665
  };
426
666
  _this.ctx = null;
@@ -428,16 +668,18 @@ var FlameComponent = (function (_super) {
428
668
  _this.pickTexture = kingly_1.NullTexture;
429
669
  _this.glResources = types_1.NULL_GL_RESOURCES;
430
670
  _this.glCanvasRef = (0, react_1.createRef)();
671
+ _this.searchInputRef = (0, react_1.createRef)();
431
672
  _this.animationRafId = NaN;
432
673
  _this.prevT = NaN;
433
674
  _this.currentFocus = focusRect(_this.props.columnarViewModel, props.chartDimensions.height, 0, -Infinity);
434
675
  _this.targetFocus = __assign({}, _this.currentFocus);
435
676
  _this.hoverIndex = NaN;
436
- _this.pointerX = -10000;
437
- _this.pointerY = -10000;
677
+ _this.pointerX = NaN;
678
+ _this.pointerY = NaN;
438
679
  _this.pinchZoomSetInterval = NaN;
439
680
  _this.pinchZoomScale = browserRootWindow().visualViewport.scale;
440
681
  _this.setupViewportScaleChangeListener();
682
+ _this.currentColor = _this.props.columnarViewModel.color;
441
683
  return _this;
442
684
  }
443
685
  FlameComponent.prototype.componentWillUnmount = function () {
@@ -451,6 +693,15 @@ var FlameComponent = (function (_super) {
451
693
  this.pointerX = e.clientX - box.left;
452
694
  this.pointerY = e.clientY - box.top;
453
695
  };
696
+ FlameComponent.prototype.smartDraw = function () {
697
+ if (Number.isFinite(this.hoverIndex)) {
698
+ this.hoverIndex = NaN;
699
+ this.setState({});
700
+ }
701
+ else {
702
+ this.drawCanvas();
703
+ }
704
+ };
454
705
  FlameComponent.displayName = 'Flame';
455
706
  return FlameComponent;
456
707
  }(react_1.default.Component));