@progress/kendo-charts 2.7.2-develop.3 → 2.7.3-develop.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ import { CHART_POINT_ROLE_DESCRIPTION, CHART_POINT_CLASSNAME, CHART_POINT_ROLE,
6
6
 
7
7
  import hasGradientOverlay from '../utils/has-gradient-overlay';
8
8
 
9
- import { ChartElement, createPatternFill, Point } from '../../core';
9
+ import { ChartElement, createPatternFill, Point, Box } from '../../core';
10
10
 
11
11
  import PointEventsMixin from '../mixins/point-events-mixin';
12
12
  import NoteMixin from '../mixins/note-mixin';
@@ -14,6 +14,7 @@ import AccessibilityAttributesMixin from '../mixins/accessibility-attributes-mix
14
14
 
15
15
  import { WHITE, LEFT, RIGHT, BOTTOM, TOP } from '../../common/constants';
16
16
  import { alignPathToPixel, deepExtend, defined, getTemplate, valueOrDefault } from '../../common';
17
+ import unclipBox from '../utils/unclip-box';
17
18
 
18
19
  const BAR_ALIGN_MIN_WIDTH = 6;
19
20
 
@@ -272,6 +273,20 @@ class Bar extends ChartElement {
272
273
  return this.box.overlaps(box);
273
274
  }
274
275
 
276
+ unclipBox() {
277
+ const label = this.label && this.label.textBox;
278
+ return unclipBox(this.box.clone(), [label, this.note]);
279
+ }
280
+
281
+ labelBox() {
282
+ const label = this.label && this.label.textBox;
283
+ return label ? label.box : new Box();
284
+ }
285
+
286
+ noteBox() {
287
+ return this.note ? this.note.box : new Box();
288
+ }
289
+
275
290
  pointData() {
276
291
  return {
277
292
  dataItem: this.dataItem,
@@ -2,6 +2,7 @@ import { drawing as draw } from '@progress/kendo-drawing';
2
2
  import { alignPathToPixel } from '../common';
3
3
 
4
4
  import { ChartElement } from '../core';
5
+ import { Box } from '../core';
5
6
 
6
7
  class ChartContainer extends ChartElement {
7
8
  constructor(options, pane) {
@@ -49,31 +50,75 @@ class ChartContainer extends ChartElement {
49
50
  const { children: charts, clipBox } = this;
50
51
 
51
52
  for (let i = 0; i < charts.length; i++) {
52
- const points = charts[i].points || {};
53
+ const points = charts[i].points || [];
53
54
  const length = points.length;
54
55
 
55
56
  for (let j = 0; j < length; j++) {
56
57
  const point = points[j];
57
- if (point && point.visible !== false && point.overlapsBox && point.overlapsBox(clipBox)) {
58
- if (point.unclipElements) {
59
- point.unclipElements();
60
- } else {
61
- const { label, note } = point;
62
-
63
- if (label && label.options.visible) {
64
- if (label.alignToClipBox) {
65
- label.alignToClipBox(clipBox);
58
+ if (point && point.visible !== false && point.overlapsBox) {
59
+ if (point.overlapsBox(clipBox)) {
60
+ if (point.unclipElements) {
61
+ point.unclipElements();
62
+ } else {
63
+ const { label, note } = point;
64
+
65
+ if (label && label.options.visible) {
66
+ if (label.alignToClipBox) {
67
+ label.alignToClipBox(clipBox);
68
+ }
69
+ label.options.noclip = true;
70
+ }
71
+
72
+ if (note && note.options.visible) {
73
+ note.options.noclip = true;
66
74
  }
67
- label.options.noclip = true;
68
75
  }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ unclipBox() {
83
+ const { children: charts } = this;
84
+ const clipBox = this._clipBox();
85
+ const box = clipBox.clone();
86
+
87
+ for (let i = 0; i < charts.length; i++) {
88
+ const points = charts[i].points || [];
89
+ const length = points.length;
69
90
 
70
- if (note && note.options.visible) {
71
- note.options.noclip = true;
91
+ for (let j = 0; j < length; j++) {
92
+ const point = points[j];
93
+
94
+ if (point && point.unclipBox && point.overlapsBox && point.visible !== false) {
95
+ if (!point.overlapsBox(clipBox)) {
96
+ // Hide points outside of the viewport (clipBox)
97
+ if (point.clipElements) {
98
+ point.clipElements();
72
99
  }
100
+
101
+ continue;
102
+ }
103
+
104
+ // Extend viewport to include all point elements, including labels
105
+ const unclipBox = point.unclipBox();
106
+ if (box.overlaps(unclipBox)) {
107
+ const labelBox = point.labelBox ? point.labelBox() : new Box();
108
+ const noteBox = point.noteBox ? point.noteBox() : new Box();
109
+
110
+ const heightLimit = Math.max(labelBox.height(), noteBox.height());
111
+ const widthLimit = Math.max(labelBox.width(), noteBox.width());
112
+
113
+ // Limit the size change of the viewport to the label and note boxes dimensions
114
+ // to avoid extending it too much.
115
+ box.wrapLimit(unclipBox, widthLimit, heightLimit);
73
116
  }
74
117
  }
75
118
  }
76
119
  }
120
+
121
+ return box;
77
122
  }
78
123
 
79
124
  destroy() {
@@ -85,4 +130,4 @@ class ChartContainer extends ChartElement {
85
130
 
86
131
  ChartContainer.prototype.isStackRoot = true;
87
132
 
88
- export default ChartContainer;
133
+ export default ChartContainer;
@@ -9,13 +9,14 @@ import { LINE_MARKER_SIZE, FADEIN, INITIAL_ANIMATION_DURATION, BORDER_BRIGHTNESS
9
9
  import { WHITE, CIRCLE, CENTER, TOP, BOTTOM, LEFT, HIGHLIGHT_ZINDEX } from '../../common/constants';
10
10
  import { deepExtend, defined, getTemplate, getAriaTemplate, valueOrDefault, getSpacing } from '../../common';
11
11
  import guid from '../../core/utils/guid';
12
+ import unclipBox from '../utils/unclip-box';
12
13
 
13
14
  class LinePoint extends ChartElement {
14
15
  constructor(value, options) {
15
16
  super();
16
17
 
17
18
  this.value = value;
18
- this.options = options;
19
+ this.options = Object.assign({}, options);
19
20
  this.aboveAxis = valueOrDefault(this.options.aboveAxis, true);
20
21
  this.tooltipTracking = true;
21
22
  this._id = guid();
@@ -103,7 +104,7 @@ class LinePoint extends ChartElement {
103
104
  return border;
104
105
  }
105
106
 
106
- createVisual() {}
107
+ createVisual() { }
107
108
 
108
109
  createMarker() {
109
110
  const options = this.options.markers;
@@ -242,7 +243,7 @@ class LinePoint extends ChartElement {
242
243
  const size = this.options.markers.size;
243
244
  const halfSize = size / 2;
244
245
  const center = this.box.center();
245
- rect = new geom.Rect([ center.x - halfSize, center.y - halfSize ], [ size, size ]);
246
+ rect = new geom.Rect([center.x - halfSize, center.y - halfSize], [size, size]);
246
247
  }
247
248
 
248
249
  return {
@@ -311,6 +312,10 @@ class LinePoint extends ChartElement {
311
312
  return markerBox.overlaps(box);
312
313
  }
313
314
 
315
+ clipElements() {
316
+ this.options.visible = false;
317
+ }
318
+
314
319
  unclipElements() {
315
320
  if (this.label) {
316
321
  this.label.options.noclip = true;
@@ -321,6 +326,18 @@ class LinePoint extends ChartElement {
321
326
  }
322
327
  }
323
328
 
329
+ unclipBox() {
330
+ return unclipBox(this.markerBox().clone(), [this.label, this.note]);
331
+ }
332
+
333
+ labelBox() {
334
+ return this.label ? this.label.box : new Box();
335
+ }
336
+
337
+ noteBox() {
338
+ return this.note ? this.note.box : new Box();
339
+ }
340
+
324
341
  pointData() {
325
342
  return {
326
343
  dataItem: this.dataItem,
@@ -99,6 +99,11 @@ class Pane extends BoxElement {
99
99
  }
100
100
  }
101
101
 
102
+ // This is the box for the charts in the pane _and_ all the overflowing ("unclipped") labels.
103
+ unclipBox() {
104
+ return this.chartContainer.unclipBox();
105
+ }
106
+
102
107
  visualStyle() {
103
108
  const style = super.visualStyle();
104
109
  style.zIndex = -10;
@@ -7,8 +7,10 @@ import { hasValue } from '../utils';
7
7
  import SeriesBinder from '../series-binder';
8
8
 
9
9
  import { WHITE, BLACK, X, Y, COORD_PRECISION, TOP, BOTTOM, LEFT, RIGHT, START, END, INHERIT } from '../../common/constants';
10
- import { append, deepExtend, defined, getSpacing, getTemplate, inArray, isFunction, isString,
11
- limitValue, round, setDefaultOptions, last, cycleIndex } from '../../common';
10
+ import {
11
+ append, deepExtend, defined, getSpacing, getTemplate, inArray, isFunction, isString,
12
+ limitValue, round, setDefaultOptions, last, cycleIndex
13
+ } from '../../common';
12
14
  import { TRENDLINE_SERIES } from '../constants';
13
15
 
14
16
  const visiblePoint = (point) => point.options.visible !== false;
@@ -291,7 +293,7 @@ class PlotAreaBase extends ChartElement {
291
293
  if (seriesByPane[pane]) {
292
294
  seriesByPane[pane].push(currentSeries);
293
295
  } else {
294
- seriesByPane[pane] = [ currentSeries ];
296
+ seriesByPane[pane] = [currentSeries];
295
297
  }
296
298
  }
297
299
 
@@ -317,6 +319,15 @@ class PlotAreaBase extends ChartElement {
317
319
  const margin = getSpacing(options.margin);
318
320
 
319
321
  this.box = targetBox.clone().unpad(margin);
322
+
323
+ this.reflowArea(panes);
324
+
325
+ if (this.ensureLabelsFit(panes)) {
326
+ this.reflowArea(panes);
327
+ }
328
+ }
329
+
330
+ reflowArea(panes) {
320
331
  this.reflowPanes();
321
332
 
322
333
  this.detachLabels();
@@ -324,6 +335,42 @@ class PlotAreaBase extends ChartElement {
324
335
  this.reflowCharts(panes);
325
336
  }
326
337
 
338
+ ensureLabelsFit(panes) {
339
+ let change = false;
340
+
341
+ panes.forEach((pane) => {
342
+ const unclipBox = pane.unclipBox();
343
+ const clipBox = pane.chartContainer._clipBox();
344
+ const padding = getSpacing(pane.options.padding || {});
345
+
346
+ if (unclipBox.y1 < clipBox.y1 + padding.top) {
347
+ change = true;
348
+ padding.top = clipBox.y1 - unclipBox.y1 + padding.top;
349
+ }
350
+
351
+ if (unclipBox.y2 > clipBox.y2 - padding.bottom) {
352
+ change = true;
353
+ padding.bottom = unclipBox.y2 - clipBox.y2 + padding.bottom;
354
+ }
355
+
356
+ if (unclipBox.x1 < clipBox.x1 + padding.left) {
357
+ change = true;
358
+ padding.left = clipBox.x1 - unclipBox.x1 + padding.left;
359
+ }
360
+
361
+ if (unclipBox.x2 > clipBox.x2 - padding.right) {
362
+ change = true;
363
+ padding.right = unclipBox.x2 - clipBox.x2 + padding.right;
364
+ }
365
+
366
+ if (change) {
367
+ pane.options.padding = padding;
368
+ }
369
+ });
370
+
371
+ return change;
372
+ }
373
+
327
374
  redraw(panes) {
328
375
  const panesArray = [].concat(panes);
329
376
  this.initSeries();
@@ -0,0 +1,10 @@
1
+ export default function unclipBox(box, elements) {
2
+ elements.forEach(element => {
3
+ const options = element && element.options;
4
+ const elBox = element && (element.box || element.wrapperBox);
5
+ if (options && elBox && options.noclip !== false && options.visible !== false) {
6
+ box.wrap(elBox);
7
+ }
8
+ });
9
+ return box;
10
+ }
@@ -15,3 +15,4 @@ export { default as isDateAxis } from './utils/is-date-axis';
15
15
  export { default as segmentVisible } from './utils/segment-visible';
16
16
  export { default as singleItemOrArray } from './utils/single-item-or-array';
17
17
  export { default as createOutOfRangePoints } from './utils/create-out-of-range-points';
18
+ export { default as unclipBox } from './utils/unclip-box';
@@ -13,8 +13,8 @@ function detectOS(ua) {
13
13
  wp: /(Windows Phone(?: OS)?)\s(\d+)\.(\d+(\.\d+)?)/,
14
14
  fire: /(Silk)\/(\d+)\.(\d+(\.\d+)?)/,
15
15
  android: /(Android|Android.*(?:Opera|Firefox).*?\/)\s*(\d+)\.?(\d+(\.\d+)?)?/,
16
- iphone: /(iPhone|iPod).*OS\s+(\d+)[\._]([\d\._]+)/,
17
- ipad: /(iPad).*OS\s+(\d+)[\._]([\d_]+)/,
16
+ iphone: /(iPhone|iPod).*OS\s+(\d+)[._]([\d._]+)/,
17
+ ipad: /(iPad).*OS\s+(\d+)[._]([\d_]+)/,
18
18
  playbook: /(PlayBook).*?Tablet\s*OS\s*(\d+)\.(\d+(\.\d+)?)/,
19
19
  windows: /(MSIE)\s+(\d+)\.(\d+(\.\d+)?)/,
20
20
  tizen: /(tizen).*?Version\/(\d+)\.(\d+(\.\d+)?)/i,
@@ -63,6 +63,15 @@ class Box extends Class {
63
63
  return this;
64
64
  }
65
65
 
66
+ wrapLimit(targetBox, widthLimit, heightLimit) {
67
+ this.x1 = Math.min(this.x1, Math.max(this.x1 - widthLimit, targetBox.x1));
68
+ this.y1 = Math.min(this.y1, Math.max(this.y1 - heightLimit, targetBox.y1));
69
+ this.x2 = Math.max(this.x2, Math.min(this.x2 + widthLimit, targetBox.x2));
70
+ this.y2 = Math.max(this.y2, Math.min(this.y2 + heightLimit, targetBox.y2));
71
+
72
+ return this;
73
+ }
74
+
66
75
  wrapPoint(point) {
67
76
  const arrayPoint = isArray(point);
68
77
  const x = arrayPoint ? point[0] : point.x;
@@ -6,7 +6,7 @@ import { CHART_POINT_ROLE_DESCRIPTION, CHART_POINT_CLASSNAME, CHART_POINT_ROLE,
6
6
 
7
7
  import hasGradientOverlay from '../utils/has-gradient-overlay';
8
8
 
9
- import { ChartElement, createPatternFill, Point } from '../../core';
9
+ import { ChartElement, createPatternFill, Point, Box } from '../../core';
10
10
 
11
11
  import PointEventsMixin from '../mixins/point-events-mixin';
12
12
  import NoteMixin from '../mixins/note-mixin';
@@ -14,6 +14,7 @@ import AccessibilityAttributesMixin from '../mixins/accessibility-attributes-mix
14
14
 
15
15
  import { WHITE, LEFT, RIGHT, BOTTOM, TOP } from '../../common/constants';
16
16
  import { alignPathToPixel, deepExtend, defined, getTemplate, valueOrDefault } from '../../common';
17
+ import unclipBox from '../utils/unclip-box';
17
18
 
18
19
  const BAR_ALIGN_MIN_WIDTH = 6;
19
20
 
@@ -272,6 +273,20 @@ class Bar extends ChartElement {
272
273
  return this.box.overlaps(box);
273
274
  }
274
275
 
276
+ unclipBox() {
277
+ const label = this.label && this.label.textBox;
278
+ return unclipBox(this.box.clone(), [label, this.note]);
279
+ }
280
+
281
+ labelBox() {
282
+ const label = this.label && this.label.textBox;
283
+ return label ? label.box : new Box();
284
+ }
285
+
286
+ noteBox() {
287
+ return this.note ? this.note.box : new Box();
288
+ }
289
+
275
290
  pointData() {
276
291
  return {
277
292
  dataItem: this.dataItem,
@@ -2,6 +2,7 @@ import { drawing as draw } from '@progress/kendo-drawing';
2
2
  import { alignPathToPixel } from '../common';
3
3
 
4
4
  import { ChartElement } from '../core';
5
+ import { Box } from '../core';
5
6
 
6
7
  class ChartContainer extends ChartElement {
7
8
  constructor(options, pane) {
@@ -49,31 +50,75 @@ class ChartContainer extends ChartElement {
49
50
  const { children: charts, clipBox } = this;
50
51
 
51
52
  for (let i = 0; i < charts.length; i++) {
52
- const points = charts[i].points || {};
53
+ const points = charts[i].points || [];
53
54
  const length = points.length;
54
55
 
55
56
  for (let j = 0; j < length; j++) {
56
57
  const point = points[j];
57
- if (point && point.visible !== false && point.overlapsBox && point.overlapsBox(clipBox)) {
58
- if (point.unclipElements) {
59
- point.unclipElements();
60
- } else {
61
- const { label, note } = point;
62
-
63
- if (label && label.options.visible) {
64
- if (label.alignToClipBox) {
65
- label.alignToClipBox(clipBox);
58
+ if (point && point.visible !== false && point.overlapsBox) {
59
+ if (point.overlapsBox(clipBox)) {
60
+ if (point.unclipElements) {
61
+ point.unclipElements();
62
+ } else {
63
+ const { label, note } = point;
64
+
65
+ if (label && label.options.visible) {
66
+ if (label.alignToClipBox) {
67
+ label.alignToClipBox(clipBox);
68
+ }
69
+ label.options.noclip = true;
70
+ }
71
+
72
+ if (note && note.options.visible) {
73
+ note.options.noclip = true;
66
74
  }
67
- label.options.noclip = true;
68
75
  }
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ unclipBox() {
83
+ const { children: charts } = this;
84
+ const clipBox = this._clipBox();
85
+ const box = clipBox.clone();
86
+
87
+ for (let i = 0; i < charts.length; i++) {
88
+ const points = charts[i].points || [];
89
+ const length = points.length;
69
90
 
70
- if (note && note.options.visible) {
71
- note.options.noclip = true;
91
+ for (let j = 0; j < length; j++) {
92
+ const point = points[j];
93
+
94
+ if (point && point.unclipBox && point.overlapsBox && point.visible !== false) {
95
+ if (!point.overlapsBox(clipBox)) {
96
+ // Hide points outside of the viewport (clipBox)
97
+ if (point.clipElements) {
98
+ point.clipElements();
72
99
  }
100
+
101
+ continue;
102
+ }
103
+
104
+ // Extend viewport to include all point elements, including labels
105
+ const unclipBox = point.unclipBox();
106
+ if (box.overlaps(unclipBox)) {
107
+ const labelBox = point.labelBox ? point.labelBox() : new Box();
108
+ const noteBox = point.noteBox ? point.noteBox() : new Box();
109
+
110
+ const heightLimit = Math.max(labelBox.height(), noteBox.height());
111
+ const widthLimit = Math.max(labelBox.width(), noteBox.width());
112
+
113
+ // Limit the size change of the viewport to the label and note boxes dimensions
114
+ // to avoid extending it too much.
115
+ box.wrapLimit(unclipBox, widthLimit, heightLimit);
73
116
  }
74
117
  }
75
118
  }
76
119
  }
120
+
121
+ return box;
77
122
  }
78
123
 
79
124
  destroy() {
@@ -85,4 +130,4 @@ class ChartContainer extends ChartElement {
85
130
 
86
131
  ChartContainer.prototype.isStackRoot = true;
87
132
 
88
- export default ChartContainer;
133
+ export default ChartContainer;
@@ -9,13 +9,14 @@ import { LINE_MARKER_SIZE, FADEIN, INITIAL_ANIMATION_DURATION, BORDER_BRIGHTNESS
9
9
  import { WHITE, CIRCLE, CENTER, TOP, BOTTOM, LEFT, HIGHLIGHT_ZINDEX } from '../../common/constants';
10
10
  import { deepExtend, defined, getTemplate, getAriaTemplate, valueOrDefault, getSpacing } from '../../common';
11
11
  import guid from '../../core/utils/guid';
12
+ import unclipBox from '../utils/unclip-box';
12
13
 
13
14
  class LinePoint extends ChartElement {
14
15
  constructor(value, options) {
15
16
  super();
16
17
 
17
18
  this.value = value;
18
- this.options = options;
19
+ this.options = Object.assign({}, options);
19
20
  this.aboveAxis = valueOrDefault(this.options.aboveAxis, true);
20
21
  this.tooltipTracking = true;
21
22
  this._id = guid();
@@ -103,7 +104,7 @@ class LinePoint extends ChartElement {
103
104
  return border;
104
105
  }
105
106
 
106
- createVisual() {}
107
+ createVisual() { }
107
108
 
108
109
  createMarker() {
109
110
  const options = this.options.markers;
@@ -242,7 +243,7 @@ class LinePoint extends ChartElement {
242
243
  const size = this.options.markers.size;
243
244
  const halfSize = size / 2;
244
245
  const center = this.box.center();
245
- rect = new geom.Rect([ center.x - halfSize, center.y - halfSize ], [ size, size ]);
246
+ rect = new geom.Rect([center.x - halfSize, center.y - halfSize], [size, size]);
246
247
  }
247
248
 
248
249
  return {
@@ -311,6 +312,10 @@ class LinePoint extends ChartElement {
311
312
  return markerBox.overlaps(box);
312
313
  }
313
314
 
315
+ clipElements() {
316
+ this.options.visible = false;
317
+ }
318
+
314
319
  unclipElements() {
315
320
  if (this.label) {
316
321
  this.label.options.noclip = true;
@@ -321,6 +326,18 @@ class LinePoint extends ChartElement {
321
326
  }
322
327
  }
323
328
 
329
+ unclipBox() {
330
+ return unclipBox(this.markerBox().clone(), [this.label, this.note]);
331
+ }
332
+
333
+ labelBox() {
334
+ return this.label ? this.label.box : new Box();
335
+ }
336
+
337
+ noteBox() {
338
+ return this.note ? this.note.box : new Box();
339
+ }
340
+
324
341
  pointData() {
325
342
  return {
326
343
  dataItem: this.dataItem,
@@ -99,6 +99,11 @@ class Pane extends BoxElement {
99
99
  }
100
100
  }
101
101
 
102
+ // This is the box for the charts in the pane _and_ all the overflowing ("unclipped") labels.
103
+ unclipBox() {
104
+ return this.chartContainer.unclipBox();
105
+ }
106
+
102
107
  visualStyle() {
103
108
  const style = super.visualStyle();
104
109
  style.zIndex = -10;
@@ -7,8 +7,10 @@ import { hasValue } from '../utils';
7
7
  import SeriesBinder from '../series-binder';
8
8
 
9
9
  import { WHITE, BLACK, X, Y, COORD_PRECISION, TOP, BOTTOM, LEFT, RIGHT, START, END, INHERIT } from '../../common/constants';
10
- import { append, deepExtend, defined, getSpacing, getTemplate, inArray, isFunction, isString,
11
- limitValue, round, setDefaultOptions, last, cycleIndex } from '../../common';
10
+ import {
11
+ append, deepExtend, defined, getSpacing, getTemplate, inArray, isFunction, isString,
12
+ limitValue, round, setDefaultOptions, last, cycleIndex
13
+ } from '../../common';
12
14
  import { TRENDLINE_SERIES } from '../constants';
13
15
 
14
16
  const visiblePoint = (point) => point.options.visible !== false;
@@ -291,7 +293,7 @@ class PlotAreaBase extends ChartElement {
291
293
  if (seriesByPane[pane]) {
292
294
  seriesByPane[pane].push(currentSeries);
293
295
  } else {
294
- seriesByPane[pane] = [ currentSeries ];
296
+ seriesByPane[pane] = [currentSeries];
295
297
  }
296
298
  }
297
299
 
@@ -317,6 +319,15 @@ class PlotAreaBase extends ChartElement {
317
319
  const margin = getSpacing(options.margin);
318
320
 
319
321
  this.box = targetBox.clone().unpad(margin);
322
+
323
+ this.reflowArea(panes);
324
+
325
+ if (this.ensureLabelsFit(panes)) {
326
+ this.reflowArea(panes);
327
+ }
328
+ }
329
+
330
+ reflowArea(panes) {
320
331
  this.reflowPanes();
321
332
 
322
333
  this.detachLabels();
@@ -324,6 +335,42 @@ class PlotAreaBase extends ChartElement {
324
335
  this.reflowCharts(panes);
325
336
  }
326
337
 
338
+ ensureLabelsFit(panes) {
339
+ let change = false;
340
+
341
+ panes.forEach((pane) => {
342
+ const unclipBox = pane.unclipBox();
343
+ const clipBox = pane.chartContainer._clipBox();
344
+ const padding = getSpacing(pane.options.padding || {});
345
+
346
+ if (unclipBox.y1 < clipBox.y1 + padding.top) {
347
+ change = true;
348
+ padding.top = clipBox.y1 - unclipBox.y1 + padding.top;
349
+ }
350
+
351
+ if (unclipBox.y2 > clipBox.y2 - padding.bottom) {
352
+ change = true;
353
+ padding.bottom = unclipBox.y2 - clipBox.y2 + padding.bottom;
354
+ }
355
+
356
+ if (unclipBox.x1 < clipBox.x1 + padding.left) {
357
+ change = true;
358
+ padding.left = clipBox.x1 - unclipBox.x1 + padding.left;
359
+ }
360
+
361
+ if (unclipBox.x2 > clipBox.x2 - padding.right) {
362
+ change = true;
363
+ padding.right = unclipBox.x2 - clipBox.x2 + padding.right;
364
+ }
365
+
366
+ if (change) {
367
+ pane.options.padding = padding;
368
+ }
369
+ });
370
+
371
+ return change;
372
+ }
373
+
327
374
  redraw(panes) {
328
375
  const panesArray = [].concat(panes);
329
376
  this.initSeries();
@@ -0,0 +1,10 @@
1
+ export default function unclipBox(box, elements) {
2
+ elements.forEach(element => {
3
+ const options = element && element.options;
4
+ const elBox = element && (element.box || element.wrapperBox);
5
+ if (options && elBox && options.noclip !== false && options.visible !== false) {
6
+ box.wrap(elBox);
7
+ }
8
+ });
9
+ return box;
10
+ }
@@ -15,3 +15,4 @@ export { default as isDateAxis } from './utils/is-date-axis';
15
15
  export { default as segmentVisible } from './utils/segment-visible';
16
16
  export { default as singleItemOrArray } from './utils/single-item-or-array';
17
17
  export { default as createOutOfRangePoints } from './utils/create-out-of-range-points';
18
+ export { default as unclipBox } from './utils/unclip-box';
@@ -13,8 +13,8 @@ function detectOS(ua) {
13
13
  wp: /(Windows Phone(?: OS)?)\s(\d+)\.(\d+(\.\d+)?)/,
14
14
  fire: /(Silk)\/(\d+)\.(\d+(\.\d+)?)/,
15
15
  android: /(Android|Android.*(?:Opera|Firefox).*?\/)\s*(\d+)\.?(\d+(\.\d+)?)?/,
16
- iphone: /(iPhone|iPod).*OS\s+(\d+)[\._]([\d\._]+)/,
17
- ipad: /(iPad).*OS\s+(\d+)[\._]([\d_]+)/,
16
+ iphone: /(iPhone|iPod).*OS\s+(\d+)[._]([\d._]+)/,
17
+ ipad: /(iPad).*OS\s+(\d+)[._]([\d_]+)/,
18
18
  playbook: /(PlayBook).*?Tablet\s*OS\s*(\d+)\.(\d+(\.\d+)?)/,
19
19
  windows: /(MSIE)\s+(\d+)\.(\d+(\.\d+)?)/,
20
20
  tizen: /(tizen).*?Version\/(\d+)\.(\d+(\.\d+)?)/i,