@refinitiv-ui/elements 5.1.0 → 5.3.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.
- package/CHANGELOG.md +71 -0
- package/lib/accordion/index.d.ts +1 -1
- package/lib/appstate-bar/index.d.ts +1 -1
- package/lib/autosuggest/helpers/const.d.ts +1 -0
- package/lib/autosuggest/helpers/types.d.ts +22 -0
- package/lib/autosuggest/helpers/utils.d.ts +1 -0
- package/lib/autosuggest/index.d.ts +1 -1
- package/lib/button/index.d.ts +1 -1
- package/lib/button/index.js +31 -31
- package/lib/button/index.js.map +1 -1
- package/lib/button-bar/index.d.ts +1 -1
- package/lib/calendar/index.d.ts +1 -1
- package/lib/calendar/index.js +1 -1
- package/lib/calendar/index.js.map +1 -1
- package/lib/calendar/locales.d.ts +1 -0
- package/lib/calendar/themes/halo/dark/index.js +1 -1
- package/lib/calendar/themes/halo/light/index.js +1 -1
- package/lib/calendar/types.d.ts +1 -0
- package/lib/calendar/utils.d.ts +1 -0
- package/lib/canvas/index.d.ts +1 -1
- package/lib/card/custom-elements.json +18 -8
- package/lib/card/helpers/types.d.ts +1 -0
- package/lib/card/index.d.ts +50 -12
- package/lib/card/index.js +112 -23
- package/lib/card/index.js.map +1 -1
- package/lib/card/themes/halo/dark/index.js +1 -1
- package/lib/card/themes/halo/light/index.js +1 -1
- package/lib/card/themes/solar/charcoal/index.js +1 -1
- package/lib/card/themes/solar/pearl/index.js +1 -1
- package/lib/chart/helpers/index.d.ts +1 -0
- package/lib/chart/helpers/legend.d.ts +1 -0
- package/lib/chart/helpers/merge.d.ts +1 -0
- package/lib/chart/helpers/types.d.ts +1 -0
- package/lib/chart/index.d.ts +8 -3
- package/lib/chart/index.js +20 -4
- package/lib/chart/index.js.map +1 -1
- package/lib/chart/plugins/doughnut-center-label.d.ts +1 -0
- package/lib/checkbox/index.d.ts +1 -1
- package/lib/clock/index.d.ts +1 -1
- package/lib/clock/utils/TickManager.d.ts +1 -0
- package/lib/clock/utils/timestamps.d.ts +1 -0
- package/lib/collapse/index.d.ts +1 -1
- package/lib/color-dialog/elements/color-palettes.d.ts +1 -1
- package/lib/color-dialog/elements/grayscale-palettes.d.ts +1 -1
- package/lib/color-dialog/elements/palettes.d.ts +1 -0
- package/lib/color-dialog/helpers/color-helpers.d.ts +1 -0
- package/lib/color-dialog/helpers/value-model.d.ts +1 -0
- package/lib/color-dialog/index.d.ts +1 -1
- package/lib/combo-box/helpers/filter.d.ts +1 -0
- package/lib/combo-box/helpers/keyboard-event.d.ts +1 -0
- package/lib/combo-box/helpers/types.d.ts +1 -0
- package/lib/combo-box/index.d.ts +1 -1
- package/lib/combo-box/themes/halo/dark/index.js +1 -1
- package/lib/combo-box/themes/halo/light/index.js +1 -1
- package/lib/counter/custom-elements.json +35 -0
- package/lib/counter/index.d.ts +89 -0
- package/lib/counter/index.js +156 -0
- package/lib/counter/index.js.map +1 -0
- package/lib/counter/themes/halo/dark/index.js +3 -0
- package/lib/counter/themes/halo/light/index.js +3 -0
- package/lib/counter/themes/solar/charcoal/index.js +3 -0
- package/lib/counter/themes/solar/pearl/index.js +3 -0
- package/lib/counter/utils.d.ts +14 -0
- package/lib/counter/utils.js +53 -0
- package/lib/counter/utils.js.map +1 -0
- package/lib/datetime-picker/custom-elements.json +1 -1
- package/lib/datetime-picker/index.d.ts +2 -2
- package/lib/datetime-picker/index.js +1 -1
- package/lib/datetime-picker/locales.d.ts +1 -0
- package/lib/datetime-picker/types.d.ts +1 -0
- package/lib/datetime-picker/utils.d.ts +1 -0
- package/lib/dialog/draggable-element.d.ts +1 -0
- package/lib/dialog/index.d.ts +1 -1
- package/lib/email-field/index.d.ts +1 -1
- package/lib/email-field/index.js +1 -0
- package/lib/email-field/index.js.map +1 -1
- package/lib/email-field/themes/halo/dark/index.js +1 -1
- package/lib/email-field/themes/halo/light/index.js +1 -1
- package/lib/email-field/themes/solar/charcoal/index.js +1 -1
- package/lib/email-field/themes/solar/pearl/index.js +1 -1
- package/lib/events.d.ts +1 -0
- package/lib/flag/index.d.ts +1 -1
- package/lib/flag/utils/FlagLoader.d.ts +1 -0
- package/lib/header/index.d.ts +1 -1
- package/lib/heatmap/custom-elements.json +13 -0
- package/lib/heatmap/helpers/color.d.ts +1 -0
- package/lib/heatmap/helpers/text.d.ts +1 -0
- package/lib/heatmap/helpers/track.d.ts +1 -0
- package/lib/heatmap/helpers/types.d.ts +1 -0
- package/lib/heatmap/index.d.ts +18 -6
- package/lib/heatmap/index.js +40 -20
- package/lib/heatmap/index.js.map +1 -1
- package/lib/icon/index.d.ts +1 -1
- package/lib/icon/utils/IconLoader.d.ts +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -1
- package/lib/interactive-chart/helpers/merge.d.ts +1 -0
- package/lib/interactive-chart/helpers/types.d.ts +4 -3
- package/lib/interactive-chart/index.d.ts +1 -1
- package/lib/interactive-chart/index.js +7 -7
- package/lib/interactive-chart/index.js.map +1 -1
- package/lib/item/helpers/types.d.ts +1 -0
- package/lib/item/index.d.ts +1 -1
- package/lib/label/custom-elements.json +7 -16
- package/lib/label/index.d.ts +32 -71
- package/lib/label/index.js +142 -179
- package/lib/label/index.js.map +1 -1
- package/lib/layout/index.d.ts +1 -1
- package/lib/led-gauge/index.d.ts +1 -1
- package/lib/list/extensible-function.d.ts +1 -0
- package/lib/list/helpers/list-renderer.d.ts +1 -0
- package/lib/list/helpers/types.d.ts +1 -0
- package/lib/list/index.d.ts +8 -2
- package/lib/list/index.js +26 -9
- package/lib/list/index.js.map +1 -1
- package/lib/list/renderer.d.ts +1 -0
- package/lib/loader/index.d.ts +1 -1
- package/lib/multi-input/helpers/types.d.ts +1 -0
- package/lib/multi-input/index.d.ts +1 -1
- package/lib/notification/elements/notification-tray.d.ts +1 -1
- package/lib/notification/elements/notification.d.ts +1 -1
- package/lib/notification/helpers/status.d.ts +1 -0
- package/lib/notification/helpers/types.d.ts +1 -0
- package/lib/notification/index.d.ts +1 -0
- package/lib/number-field/index.d.ts +1 -1
- package/lib/number-field/index.js +1 -0
- package/lib/number-field/index.js.map +1 -1
- package/lib/number-field/themes/halo/dark/index.js +1 -1
- package/lib/number-field/themes/halo/light/index.js +1 -1
- package/lib/number-field/themes/solar/charcoal/index.js +1 -1
- package/lib/number-field/themes/solar/pearl/index.js +1 -1
- package/lib/overlay/elements/overlay-backdrop.d.ts +1 -1
- package/lib/overlay/elements/overlay-viewport.d.ts +1 -1
- package/lib/overlay/elements/overlay.d.ts +1 -1
- package/lib/overlay/elements/overlay.js +1 -0
- package/lib/overlay/elements/overlay.js.map +1 -1
- package/lib/overlay/helpers/functions.d.ts +1 -0
- package/lib/overlay/helpers/types.d.ts +1 -0
- package/lib/overlay/index.d.ts +1 -0
- package/lib/overlay/managers/backdrop-manager.d.ts +2 -1
- package/lib/overlay/managers/close-manager.d.ts +2 -1
- package/lib/overlay/managers/focus-manager.d.ts +2 -1
- package/lib/overlay/managers/focus-manager.js +1 -2
- package/lib/overlay/managers/focus-manager.js.map +1 -1
- package/lib/overlay/managers/interaction-lock-manager.d.ts +1 -0
- package/lib/overlay/managers/viewport-manager.d.ts +2 -1
- package/lib/overlay/managers/zindex-manager.d.ts +2 -1
- package/lib/overlay/managers/zindex-manager.js +0 -2
- package/lib/overlay/managers/zindex-manager.js.map +1 -1
- package/lib/overlay-menu/custom-elements.json +64 -0
- package/lib/overlay-menu/helpers/types.d.ts +1 -0
- package/lib/overlay-menu/helpers/uuid.d.ts +1 -0
- package/lib/overlay-menu/index.d.ts +19 -1
- package/lib/overlay-menu/index.js +18 -0
- package/lib/overlay-menu/index.js.map +1 -1
- package/lib/overlay-menu/managers/menu-manager.d.ts +1 -0
- package/lib/pagination/helpers/types.d.ts +1 -0
- package/lib/pagination/index.d.ts +1 -1
- package/lib/panel/index.d.ts +1 -1
- package/lib/password-field/index.d.ts +1 -1
- package/lib/password-field/index.js +1 -0
- package/lib/password-field/index.js.map +1 -1
- package/lib/password-field/themes/halo/dark/index.js +1 -1
- package/lib/password-field/themes/halo/light/index.js +1 -1
- package/lib/password-field/themes/solar/charcoal/index.js +1 -1
- package/lib/password-field/themes/solar/pearl/index.js +1 -1
- package/lib/pill/index.d.ts +1 -1
- package/lib/progress-bar/index.d.ts +1 -1
- package/lib/radio-button/index.d.ts +1 -1
- package/lib/radio-button/radio-button-registry.d.ts +1 -0
- package/lib/rating/index.d.ts +1 -1
- package/lib/search-field/index.d.ts +1 -1
- package/lib/search-field/index.js +1 -0
- package/lib/search-field/index.js.map +1 -1
- package/lib/search-field/themes/halo/dark/index.js +1 -1
- package/lib/search-field/themes/halo/light/index.js +1 -1
- package/lib/search-field/themes/solar/charcoal/index.js +1 -1
- package/lib/search-field/themes/solar/pearl/index.js +1 -1
- package/lib/select/helpers/types.d.ts +1 -0
- package/lib/select/index.d.ts +1 -1
- package/lib/select/themes/halo/dark/index.js +1 -1
- package/lib/select/themes/halo/light/index.js +1 -1
- package/lib/sidebar-layout/index.d.ts +1 -1
- package/lib/slider/index.d.ts +7 -1
- package/lib/slider/index.js +48 -1
- package/lib/slider/index.js.map +1 -1
- package/lib/sparkline/index.d.ts +1 -1
- package/lib/swing-gauge/const.d.ts +23 -0
- package/lib/swing-gauge/const.js +27 -0
- package/lib/swing-gauge/const.js.map +1 -0
- package/lib/swing-gauge/custom-elements.json +47 -20
- package/lib/swing-gauge/helpers.d.ts +9 -0
- package/lib/swing-gauge/helpers.js +106 -0
- package/lib/swing-gauge/helpers.js.map +1 -0
- package/lib/swing-gauge/index.d.ts +207 -70
- package/lib/swing-gauge/index.js +651 -161
- package/lib/swing-gauge/index.js.map +1 -1
- package/lib/swing-gauge/themes/halo/dark/index.js +1 -1
- package/lib/swing-gauge/themes/halo/light/index.js +1 -1
- package/lib/swing-gauge/themes/solar/charcoal/index.js +1 -1
- package/lib/swing-gauge/themes/solar/pearl/index.js +1 -1
- package/lib/swing-gauge/types.d.ts +35 -0
- package/lib/swing-gauge/{helpers/types.js → types.js} +0 -0
- package/lib/swing-gauge/{helpers/types.js.map → types.js.map} +1 -1
- package/lib/tab/custom-elements.json +7 -18
- package/lib/tab/index.d.ts +5 -9
- package/lib/tab/index.js +11 -19
- package/lib/tab/index.js.map +1 -1
- package/lib/tab/themes/halo/dark/index.js +1 -1
- package/lib/tab/themes/halo/light/index.js +1 -1
- package/lib/tab/themes/solar/charcoal/index.js +1 -1
- package/lib/tab/themes/solar/pearl/index.js +1 -1
- package/lib/tab-bar/helpers/animate.d.ts +1 -0
- package/lib/tab-bar/index.d.ts +1 -1
- package/lib/text-field/index.d.ts +1 -1
- package/lib/text-field/index.js +1 -0
- package/lib/text-field/index.js.map +1 -1
- package/lib/text-field/themes/halo/dark/index.js +1 -1
- package/lib/text-field/themes/halo/light/index.js +1 -1
- package/lib/text-field/themes/solar/charcoal/index.js +1 -1
- package/lib/text-field/themes/solar/pearl/index.js +1 -1
- package/lib/time-picker/index.d.ts +1 -1
- package/lib/toggle/index.d.ts +1 -1
- package/lib/tooltip/elements/title-tooltip.d.ts +1 -0
- package/lib/tooltip/elements/tooltip-element.d.ts +2 -2
- package/lib/tooltip/elements/tooltip-element.js +0 -1
- package/lib/tooltip/elements/tooltip-element.js.map +1 -1
- package/lib/tooltip/helpers/overflow-tooltip.d.ts +1 -0
- package/lib/tooltip/helpers/renderer.d.ts +1 -0
- package/lib/tooltip/helpers/types.d.ts +1 -0
- package/lib/tooltip/index.d.ts +2 -2
- package/lib/tooltip/index.js +3 -4
- package/lib/tooltip/index.js.map +1 -1
- package/lib/tooltip/managers/tooltip-manager.d.ts +2 -1
- package/lib/tooltip/managers/tooltip-manager.js +20 -9
- package/lib/tooltip/managers/tooltip-manager.js.map +1 -1
- package/lib/tornado-chart/elements/tornado-chart.d.ts +1 -1
- package/lib/tornado-chart/elements/tornado-item.d.ts +1 -1
- package/lib/tornado-chart/index.d.ts +1 -0
- package/lib/tree/elements/tree-item.d.ts +9 -1
- package/lib/tree/elements/tree-item.js +17 -0
- package/lib/tree/elements/tree-item.js.map +1 -1
- package/lib/tree/elements/tree.d.ts +1 -1
- package/lib/tree/helpers/renderer.d.ts +1 -0
- package/lib/tree/helpers/renderer.js +1 -0
- package/lib/tree/helpers/renderer.js.map +1 -1
- package/lib/tree/helpers/types.d.ts +5 -0
- package/lib/tree/index.d.ts +1 -0
- package/lib/tree/managers/tree-manager.d.ts +1 -0
- package/lib/tree/themes/halo/dark/index.js +1 -1
- package/lib/tree/themes/halo/light/index.js +1 -1
- package/lib/tree/themes/solar/charcoal/index.js +1 -1
- package/lib/tree/themes/solar/pearl/index.js +1 -1
- package/lib/tree-select/custom-elements.json +5 -0
- package/lib/tree-select/helpers/types.d.ts +1 -0
- package/lib/tree-select/index.d.ts +17 -1
- package/lib/tree-select/index.js +49 -5
- package/lib/tree-select/index.js.map +1 -1
- package/lib/tree-select/themes/halo/dark/index.js +2 -1
- package/lib/tree-select/themes/halo/light/index.js +2 -1
- package/lib/tree-select/themes/solar/charcoal/index.js +2 -1
- package/lib/tree-select/themes/solar/pearl/index.js +2 -1
- package/package.json +10 -10
- package/lib/label/helpers/text.d.ts +0 -35
- package/lib/label/helpers/text.js +0 -57
- package/lib/label/helpers/text.js.map +0 -1
- package/lib/swing-gauge/helpers/canvas.d.ts +0 -8
- package/lib/swing-gauge/helpers/canvas.js +0 -115
- package/lib/swing-gauge/helpers/canvas.js.map +0 -1
- package/lib/swing-gauge/helpers/types.d.ts +0 -33
package/lib/swing-gauge/index.js
CHANGED
|
@@ -4,55 +4,116 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { css, customElement, property } from '@refinitiv-ui/core';
|
|
8
|
-
import { helpers as canvasHelper } from './helpers/canvas';
|
|
9
|
-
import { Canvas } from '../canvas';
|
|
7
|
+
import { ResponsiveElement, css, customElement, property, html, styleMap, query, state, WarningNotice } from '@refinitiv-ui/core';
|
|
10
8
|
import { VERSION } from '../';
|
|
9
|
+
import '../canvas';
|
|
10
|
+
import '../label';
|
|
11
|
+
import { helpers as canvasHelper } from './helpers';
|
|
12
|
+
import { DefaultStyle, Segment, TextType } from './const.js';
|
|
13
|
+
/**
|
|
14
|
+
* Constants from swing-gauge default specs
|
|
15
|
+
*/
|
|
16
|
+
const GAUGE_WIDTH_SCALE = 0.4;
|
|
17
|
+
const GAUGE_HEIGHT_SCALE = 0.8;
|
|
18
|
+
const GAUGE_UPPER_BOUND = GAUGE_HEIGHT_SCALE + GAUGE_WIDTH_SCALE / 2;
|
|
19
|
+
const GAUGE_LOWER_BOUND = GAUGE_HEIGHT_SCALE - GAUGE_WIDTH_SCALE / 2;
|
|
20
|
+
const PRIMARY_RADIAN = 1.25;
|
|
21
|
+
const SECONDARY_RADIAN = 1.75;
|
|
22
|
+
const LINE_POINTER_OFFSET = 0.3;
|
|
23
|
+
const POINT_POINTER_OFFSET = 0.1;
|
|
24
|
+
// When either value is below this threshold, the label position changes
|
|
25
|
+
const GAUGE_PERCENTAGE_THRESHOLD = 30;
|
|
26
|
+
const GAUGE_LABEL_FONT_SCALE = 0.14;
|
|
27
|
+
const GAUGE_VALUE_FONT_SCALE = 0.18;
|
|
28
|
+
const MIN_LABEL_FONT_SIZE = 12;
|
|
29
|
+
const MIN_VALUE_FONT_SIZE = 15;
|
|
30
|
+
const MAX_LABEL_LINE = 3;
|
|
31
|
+
const MAX_VALUE_LINE = 1;
|
|
32
|
+
const MAX_LEGEND_LINE = 2;
|
|
11
33
|
/**
|
|
12
34
|
* Data visualisation showing the percentage between two values
|
|
13
35
|
*/
|
|
14
|
-
let SwingGauge = class SwingGauge extends
|
|
36
|
+
let SwingGauge = class SwingGauge extends ResponsiveElement {
|
|
15
37
|
constructor() {
|
|
16
|
-
super();
|
|
38
|
+
super(...arguments);
|
|
39
|
+
this._primaryValue = 0;
|
|
17
40
|
/**
|
|
18
|
-
*
|
|
19
|
-
* @default 50
|
|
41
|
+
* Primary label
|
|
20
42
|
*/
|
|
21
|
-
this.
|
|
43
|
+
this.primaryLabel = '';
|
|
44
|
+
this._secondaryValue = 0;
|
|
22
45
|
/**
|
|
23
|
-
*
|
|
46
|
+
* Secondary label
|
|
24
47
|
*/
|
|
25
|
-
this.
|
|
48
|
+
this.secondaryLabel = '';
|
|
26
49
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @default 50
|
|
50
|
+
* Animation duration in milliseconds
|
|
29
51
|
*/
|
|
30
|
-
this.
|
|
52
|
+
this.duration = 1000;
|
|
31
53
|
/**
|
|
32
|
-
|
|
54
|
+
* Primary value legend
|
|
55
|
+
*/
|
|
56
|
+
this.primaryLegend = '';
|
|
57
|
+
/**
|
|
58
|
+
* Secondary value legend
|
|
59
|
+
*/
|
|
60
|
+
this.secondaryLegend = '';
|
|
61
|
+
/**
|
|
62
|
+
* Custome value formatter
|
|
33
63
|
*/
|
|
34
|
-
this.
|
|
64
|
+
this.valueFormatter = this.defaultValueFormatter;
|
|
35
65
|
/**
|
|
36
|
-
*
|
|
37
|
-
* @default 1000
|
|
66
|
+
* Controls swing gauge animations
|
|
38
67
|
*/
|
|
39
|
-
this.duration = 1000;
|
|
40
|
-
this.w = null;
|
|
41
|
-
this.h = null;
|
|
42
|
-
this.min = null;
|
|
43
|
-
this.max = null;
|
|
44
|
-
this.size = null;
|
|
45
|
-
this.maxFontSize = null;
|
|
46
|
-
this.centerlineOptions = ['solid', 'dotted', 'dashed'];
|
|
47
68
|
this.onFrame = requestAnimationFrame.bind(window);
|
|
48
69
|
this.cancelFrame = cancelAnimationFrame.bind(window);
|
|
49
|
-
this.
|
|
50
|
-
this.
|
|
51
|
-
this.
|
|
70
|
+
this.requestedAnimationID = 0;
|
|
71
|
+
this.gaugeWidthScale = GAUGE_WIDTH_SCALE;
|
|
72
|
+
this.gaugeHeightScale = GAUGE_HEIGHT_SCALE;
|
|
73
|
+
this.gaugeUpperBound = GAUGE_UPPER_BOUND;
|
|
74
|
+
this.gaugeLowerBound = GAUGE_LOWER_BOUND;
|
|
75
|
+
this.linePointerOffset = LINE_POINTER_OFFSET;
|
|
76
|
+
this.pointPointerOffset = POINT_POINTER_OFFSET;
|
|
77
|
+
this.primaryLineRadian = PRIMARY_RADIAN;
|
|
78
|
+
this.secondaryLineRadian = SECONDARY_RADIAN;
|
|
79
|
+
this.linePointerOffsetOverflow = LINE_POINTER_OFFSET;
|
|
80
|
+
/**
|
|
81
|
+
* Data requires to draw swing gauge
|
|
82
|
+
*/
|
|
83
|
+
this.data = null;
|
|
52
84
|
/**
|
|
53
|
-
|
|
85
|
+
* Internal sizes and scales
|
|
86
|
+
*/
|
|
87
|
+
this.width = 0;
|
|
88
|
+
this.height = 0;
|
|
89
|
+
this.size = 0;
|
|
90
|
+
this.lineLength = 50;
|
|
91
|
+
this.scale = 1;
|
|
92
|
+
this.overflowScale = 0.1;
|
|
93
|
+
/**
|
|
94
|
+
* Current fill percentage
|
|
95
|
+
*/
|
|
96
|
+
this.fillPercentage = 0;
|
|
97
|
+
/**
|
|
98
|
+
* Keeps previous percentage calculation to avoid re-rendering the same value
|
|
99
|
+
*/
|
|
100
|
+
this.previousFillPercentage = 0;
|
|
101
|
+
/**
|
|
102
|
+
* Style for primary container
|
|
54
103
|
*/
|
|
55
|
-
this.
|
|
104
|
+
this.primaryContainerStyle = {};
|
|
105
|
+
/**
|
|
106
|
+
* Style for secondary container
|
|
107
|
+
*/
|
|
108
|
+
this.secondaryContainerStyle = {};
|
|
109
|
+
/**
|
|
110
|
+
* Style for label
|
|
111
|
+
*/
|
|
112
|
+
this.labelStyle = {};
|
|
113
|
+
/**
|
|
114
|
+
* Style for both values
|
|
115
|
+
*/
|
|
116
|
+
this.valueStyle = {};
|
|
56
117
|
}
|
|
57
118
|
/**
|
|
58
119
|
* Element version number
|
|
@@ -71,220 +132,649 @@ let SwingGauge = class SwingGauge extends Canvas {
|
|
|
71
132
|
return css `
|
|
72
133
|
:host {
|
|
73
134
|
display: block;
|
|
74
|
-
|
|
135
|
+
height: 200px;
|
|
136
|
+
}
|
|
137
|
+
:host [part=container] {
|
|
138
|
+
display: flex;
|
|
139
|
+
flex-direction: column;
|
|
140
|
+
height: 100%;
|
|
141
|
+
}
|
|
142
|
+
:host [part=canvas-container] {
|
|
75
143
|
position: relative;
|
|
144
|
+
flex: 1;
|
|
76
145
|
}
|
|
77
|
-
:host
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
146
|
+
:host [part=canvas] {
|
|
147
|
+
height: 100%;
|
|
148
|
+
}
|
|
149
|
+
:host [part=primary-legend], [part=secondary-legend] {
|
|
150
|
+
text-align: left;
|
|
151
|
+
display: flex;
|
|
152
|
+
}
|
|
153
|
+
:host [part=primary-label], [part=primary-value] {
|
|
154
|
+
text-align: left;
|
|
155
|
+
}
|
|
156
|
+
:host [part=secondary-label], [part=secondary-value] {
|
|
157
|
+
text-align: right;
|
|
158
|
+
}
|
|
159
|
+
:host [part=legend-container-outer] {
|
|
160
|
+
width: 60%;
|
|
161
|
+
margin: 0 auto;
|
|
162
|
+
text-align: center;
|
|
163
|
+
}
|
|
164
|
+
:host [part=legend-container-inner] {
|
|
165
|
+
max-width: 100%;
|
|
166
|
+
display: inline-block;
|
|
82
167
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
168
|
+
:host [part=primary-legend-symbol], [part=secondary-legend-symbol] {
|
|
169
|
+
display: inline-block;
|
|
170
|
+
flex-shrink: 0;
|
|
171
|
+
}
|
|
172
|
+
:host [part=primary-container] {
|
|
173
|
+
position: absolute;
|
|
174
|
+
text-align: left;
|
|
175
|
+
}
|
|
176
|
+
:host [part=secondary-container] {
|
|
88
177
|
position: absolute;
|
|
178
|
+
text-align: right;
|
|
89
179
|
}
|
|
90
180
|
`;
|
|
91
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* Primary value
|
|
184
|
+
* @param value primary value
|
|
185
|
+
*/
|
|
186
|
+
set primaryValue(value) {
|
|
187
|
+
value = this.validateNumber(value, 'primary-value');
|
|
188
|
+
const oldValue = this._primaryValue;
|
|
189
|
+
if (oldValue !== value) {
|
|
190
|
+
this._primaryValue = value;
|
|
191
|
+
void this.requestUpdate('primaryValue', oldValue);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
get primaryValue() {
|
|
195
|
+
return this._primaryValue;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Secondary value
|
|
199
|
+
* @param value secondary value
|
|
200
|
+
*/
|
|
201
|
+
set secondaryValue(value) {
|
|
202
|
+
value = this.validateNumber(value, 'secondary-value');
|
|
203
|
+
const oldValue = this._secondaryValue;
|
|
204
|
+
if (oldValue !== value) {
|
|
205
|
+
this._secondaryValue = value;
|
|
206
|
+
void this.requestUpdate('secondaryValue', oldValue);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
get secondaryValue() {
|
|
210
|
+
return this._secondaryValue;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get primary percentage
|
|
214
|
+
*/
|
|
215
|
+
get primaryPercentage() {
|
|
216
|
+
return this.getPercentage(this.primaryValue);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get secondary percentage
|
|
220
|
+
*/
|
|
221
|
+
get secondaryPercentage() {
|
|
222
|
+
return this.getPercentage(this.secondaryValue);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Check width and height are valid
|
|
226
|
+
* @returns if size is valid
|
|
227
|
+
*/
|
|
228
|
+
get hasValidSize() {
|
|
229
|
+
return this.offsetWidth > 0 && this.offsetHeight > 0 && this.canvas.width > 0 && this.canvas.height > 0;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get default value format
|
|
233
|
+
* @param value A value on each side of swing gauge
|
|
234
|
+
* @returns default value format
|
|
235
|
+
*/
|
|
236
|
+
defaultValueFormatter(value) {
|
|
237
|
+
return `${value.toFixed(2)}%`;
|
|
238
|
+
}
|
|
92
239
|
/**
|
|
93
240
|
* Getter size of component
|
|
94
|
-
* @returns
|
|
241
|
+
* @returns return size of canvas
|
|
95
242
|
*/
|
|
96
243
|
get canvasSize() {
|
|
97
244
|
return {
|
|
98
|
-
width: this.
|
|
99
|
-
height: this.
|
|
245
|
+
width: this.offsetWidth,
|
|
246
|
+
height: this.offsetHeight
|
|
100
247
|
};
|
|
101
248
|
}
|
|
102
249
|
/**
|
|
103
|
-
*
|
|
104
|
-
* @
|
|
105
|
-
* @param
|
|
250
|
+
* Validate number
|
|
251
|
+
* @protected
|
|
252
|
+
* @param value number that want to validate
|
|
253
|
+
* @param propName name of property
|
|
254
|
+
* @returns {number} valid number
|
|
255
|
+
*/
|
|
256
|
+
validateNumber(value, propName) {
|
|
257
|
+
if (typeof value === 'number' && !isNaN(value) && isFinite(value) && value >= 0) {
|
|
258
|
+
return value;
|
|
259
|
+
}
|
|
260
|
+
new WarningNotice(`${this.localName} : The specified value "${value}" of ${propName} property is not valid. Default value will be used instead.`).show();
|
|
261
|
+
return 0;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* On update lifecycle
|
|
265
|
+
* @param changedProperties changed properties
|
|
106
266
|
* @returns {void}
|
|
107
267
|
*/
|
|
108
|
-
|
|
109
|
-
super.
|
|
110
|
-
|
|
268
|
+
update(changedProperties) {
|
|
269
|
+
super.update(changedProperties);
|
|
270
|
+
if (changedProperties.has('primaryValue') || changedProperties.has('secondaryValue')
|
|
271
|
+
|| (this.primaryValue === 0 && this.secondaryValue === 0)) {
|
|
272
|
+
this.canvas.autoloop = true;
|
|
273
|
+
this.renderCanvas('frame');
|
|
274
|
+
this.animateCanvas();
|
|
275
|
+
}
|
|
276
|
+
if (changedProperties.has('primaryLabel') || changedProperties.has('secondaryLabel')) {
|
|
277
|
+
this.calculateLabelFontSize();
|
|
278
|
+
}
|
|
279
|
+
if (changedProperties.has('valueFormatter')) {
|
|
280
|
+
this.calculateValueFontSize();
|
|
281
|
+
}
|
|
282
|
+
if (changedProperties.has('primaryValue') || changedProperties.has('secondaryValue')
|
|
283
|
+
|| changedProperties.has('primaryLabel') || changedProperties.has('secondaryLabel')
|
|
284
|
+
|| changedProperties.has('valueFormatter')) {
|
|
285
|
+
this.updateGaugePositions();
|
|
286
|
+
}
|
|
111
287
|
}
|
|
112
288
|
/**
|
|
113
|
-
* Handles when
|
|
114
|
-
* @protected
|
|
115
|
-
* @param time timestamp
|
|
289
|
+
* Handles when component disconnected
|
|
116
290
|
* @returns {void}
|
|
117
291
|
*/
|
|
118
|
-
|
|
119
|
-
super.
|
|
120
|
-
this.
|
|
292
|
+
disconnectedCallback() {
|
|
293
|
+
super.disconnectedCallback();
|
|
294
|
+
if (this.requestedAnimationID) {
|
|
295
|
+
this.cancelFrame(this.requestedAnimationID);
|
|
296
|
+
}
|
|
121
297
|
}
|
|
122
298
|
/**
|
|
123
|
-
*
|
|
124
|
-
* @
|
|
125
|
-
* @param
|
|
299
|
+
* Calls easing based on both left and right values
|
|
300
|
+
* @param primaryValue primary value
|
|
301
|
+
* @param secondaryValue secondary value
|
|
126
302
|
* @returns {void}
|
|
127
303
|
*/
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this.
|
|
304
|
+
ease(primaryValue, secondaryValue) {
|
|
305
|
+
let to = 0.5;
|
|
306
|
+
let from = this.fillPercentage;
|
|
307
|
+
if (primaryValue > 0 || secondaryValue > 0) {
|
|
308
|
+
to = primaryValue / (primaryValue + secondaryValue);
|
|
309
|
+
}
|
|
310
|
+
// this for prevent gauge not render when 'to' and 'from' are 0
|
|
311
|
+
if (primaryValue === 0 && from === 0) {
|
|
312
|
+
from = 0.1;
|
|
313
|
+
}
|
|
314
|
+
this.easeTo(to, from, performance.now() + this.duration);
|
|
131
315
|
}
|
|
132
316
|
/**
|
|
133
|
-
*
|
|
134
|
-
* @
|
|
135
|
-
* @param
|
|
317
|
+
* Eases the fill percentage
|
|
318
|
+
* @param to ease to value
|
|
319
|
+
* @param from ease from value
|
|
320
|
+
* @param time ease time
|
|
136
321
|
* @returns {void}
|
|
137
322
|
*/
|
|
138
|
-
|
|
139
|
-
|
|
323
|
+
easeTo(to, from, time) {
|
|
324
|
+
const diff = (this.duration - (time - performance.now())) / this.duration;
|
|
325
|
+
this.fillPercentage = from + (to - from) * canvasHelper.elasticOut(diff > 1 ? 1 : diff < 0 ? 0 : diff) || 0;
|
|
326
|
+
if (this.fillPercentage !== to) {
|
|
327
|
+
this.cancelFrame(this.requestedAnimationID);
|
|
328
|
+
this.requestedAnimationID = this.onFrame(() => this.easeTo(to, from, time));
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
this.canvas.autoloop = false;
|
|
332
|
+
}
|
|
333
|
+
this.renderCanvas('frame', true);
|
|
140
334
|
}
|
|
141
335
|
/**
|
|
142
|
-
*
|
|
143
|
-
* @ignore
|
|
144
|
-
* @param changedProperties changed properties
|
|
336
|
+
* Restart the animation, re-render the canvas
|
|
145
337
|
* @returns {void}
|
|
146
338
|
*/
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.reDrawCanvas();
|
|
339
|
+
animateCanvas() {
|
|
340
|
+
this.ease(this.primaryValue, this.secondaryValue);
|
|
150
341
|
}
|
|
151
342
|
/**
|
|
152
|
-
*
|
|
153
|
-
* @
|
|
343
|
+
* Render chart
|
|
344
|
+
* @param onDraw drawing type
|
|
345
|
+
* @param isFrameUpdated Optional called by on frame event
|
|
154
346
|
* @returns {void}
|
|
155
347
|
*/
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
348
|
+
renderCanvas(onDraw, isFrameUpdated) {
|
|
349
|
+
const percentageChanged = this.previousFillPercentage !== this.fillPercentage;
|
|
350
|
+
const canRender = this.hasValidSize && percentageChanged;
|
|
351
|
+
if ((isFrameUpdated && !canRender) || !this.hasValidSize) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
this.width = this.canvas.width;
|
|
355
|
+
this.height = this.canvas.height;
|
|
356
|
+
const min = this.width > this.height ? this.height : this.width;
|
|
357
|
+
const max = this.width > this.height ? this.width : this.height;
|
|
358
|
+
this.size = Math.floor(max / this.scale < min ? max / this.scale : min);
|
|
359
|
+
const canvasSize = { width: this.width, height: this.height };
|
|
360
|
+
// Prevent draw frame unnecessary recalculate position and draw data
|
|
361
|
+
if (!isFrameUpdated) {
|
|
362
|
+
this.data = this.getData();
|
|
363
|
+
}
|
|
364
|
+
else if (this.data !== null) {
|
|
365
|
+
this.data.fillPercentage = this.fillPercentage;
|
|
161
366
|
}
|
|
367
|
+
const clear = () => {
|
|
368
|
+
if (!this.canvas.ctx) {
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
canvasHelper.clear(canvasSize, this.canvas.ctx);
|
|
372
|
+
};
|
|
373
|
+
this.canvas.addEventListener(onDraw, clear, { once: true });
|
|
374
|
+
const draw = () => {
|
|
375
|
+
if (!this.canvas.ctx) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
canvasHelper.draw(this.data === null ? this.getData() : this.data, this.canvas.ctx, {
|
|
379
|
+
strokeWidth: Math.ceil(this.scale * this.size * 0.005),
|
|
380
|
+
primaryColor: this.getComputedVariable('--primary-color', DefaultStyle.PRIMARY_GAUGE_COLOR),
|
|
381
|
+
secondaryColor: this.getComputedVariable('--secondary-color', DefaultStyle.SECONDARY_GAUGE_COLOR),
|
|
382
|
+
borderColor: this.getComputedVariable('--border-color', DefaultStyle.BOREDER_COLOR),
|
|
383
|
+
centerline: `${this.getComputedVariable('--center-line', DefaultStyle.CENTER_LINE_STYLE)}`.trim(),
|
|
384
|
+
centerlineOpacity: this.getComputedVariable('--center-line-opacity', DefaultStyle.CENTER_LINE_OPACITY),
|
|
385
|
+
centerlineColor: this.getComputedVariable('--center-line-color', DefaultStyle.CENTER_LINE_COLOR)
|
|
386
|
+
});
|
|
387
|
+
};
|
|
388
|
+
this.canvas.addEventListener(onDraw, draw, { once: true });
|
|
389
|
+
// Set this for comparison when deciding if we should paint
|
|
390
|
+
this.previousFillPercentage = this.fillPercentage;
|
|
162
391
|
}
|
|
163
392
|
/**
|
|
164
|
-
*
|
|
165
|
-
* @
|
|
166
|
-
|
|
167
|
-
|
|
393
|
+
* Get computed swing-gauge data for drawing
|
|
394
|
+
* @returns swing-gauge data
|
|
395
|
+
*/
|
|
396
|
+
getData() {
|
|
397
|
+
let primaryPosLine = this.getPositionStyle(Segment.PRIMARY, this.primaryLineRadian, this.linePointerOffset, 0);
|
|
398
|
+
const primaryPosPoint = this.getPositionStyle(Segment.PRIMARY, PRIMARY_RADIAN, this.pointPointerOffset, 0);
|
|
399
|
+
let secondaryPosLine = this.getPositionStyle(Segment.SECONDARY, this.secondaryLineRadian, this.linePointerOffset, 0);
|
|
400
|
+
const secondaryPosPoint = this.getPositionStyle(Segment.SECONDARY, SECONDARY_RADIAN, this.pointPointerOffset, 0);
|
|
401
|
+
// Recalculate radian to prevent container overflow
|
|
402
|
+
let primaryHeight = 0;
|
|
403
|
+
if (this.primaryContainer.children[0]) {
|
|
404
|
+
primaryHeight += this.primaryContainer.children[0].offsetHeight;
|
|
405
|
+
}
|
|
406
|
+
if (this.primaryContainer.children[1]) {
|
|
407
|
+
primaryHeight += this.primaryContainer.children[1].offsetHeight;
|
|
408
|
+
}
|
|
409
|
+
const primarySpace = this.height - this.getValueFromStyle(primaryPosLine.top);
|
|
410
|
+
const primaryOverflow = primarySpace < primaryHeight && this.primaryPercentage >= GAUGE_PERCENTAGE_THRESHOLD && primarySpace > 0 && primaryHeight > 0;
|
|
411
|
+
let secondaryHeight = 0;
|
|
412
|
+
if (this.secondaryContainer.children[0]) {
|
|
413
|
+
secondaryHeight += this.secondaryContainer.children[0].offsetHeight;
|
|
414
|
+
}
|
|
415
|
+
if (this.secondaryContainer.children[1]) {
|
|
416
|
+
secondaryHeight += this.secondaryContainer.children[1].offsetHeight;
|
|
417
|
+
}
|
|
418
|
+
const secondarySpace = this.height - this.getValueFromStyle(secondaryPosLine.top);
|
|
419
|
+
const secondaryOverflow = secondarySpace < secondaryHeight && this.secondaryPercentage >= GAUGE_PERCENTAGE_THRESHOLD && secondarySpace > 0 && secondaryHeight > 0;
|
|
420
|
+
if (primaryOverflow || secondaryOverflow) {
|
|
421
|
+
let containerHeight = primaryHeight;
|
|
422
|
+
let containerHeightOverflow = primarySpace;
|
|
423
|
+
let containerWidth = (this.width / 2) - this.getValueFromStyle(primaryPosLine.left);
|
|
424
|
+
if ((!primaryOverflow && secondaryOverflow)
|
|
425
|
+
|| (primaryOverflow && secondaryOverflow && secondaryHeight > primaryHeight)) {
|
|
426
|
+
containerHeight = secondaryHeight;
|
|
427
|
+
containerHeightOverflow = secondarySpace;
|
|
428
|
+
containerWidth = this.getValueFromStyle(secondaryPosLine.left) - (this.width / 2);
|
|
429
|
+
}
|
|
430
|
+
// Prevents container overflow
|
|
431
|
+
const oldRadius = Math.sqrt(Math.pow(containerHeightOverflow, 2) + Math.pow(containerWidth, 2));
|
|
432
|
+
const newRadius = Math.sqrt(Math.pow(containerHeight, 2) + Math.pow(containerWidth, 2));
|
|
433
|
+
this.linePointerOffset *= Math.pow(2, newRadius / oldRadius);
|
|
434
|
+
this.linePointerOffset = this.linePointerOffset > 4 ? 4 : this.linePointerOffset;
|
|
435
|
+
this.linePointerOffsetOverflow = this.linePointerOffset;
|
|
436
|
+
this.overflowScale = this.scale;
|
|
437
|
+
primaryPosLine = this.getPositionStyle(Segment.PRIMARY, this.primaryLineRadian, this.linePointerOffset, 0);
|
|
438
|
+
secondaryPosLine = this.getPositionStyle(Segment.SECONDARY, this.secondaryLineRadian, this.linePointerOffset, 0);
|
|
439
|
+
}
|
|
440
|
+
return {
|
|
441
|
+
width: this.width,
|
|
442
|
+
height: this.height,
|
|
443
|
+
size: this.size,
|
|
444
|
+
fillPercentage: this.fillPercentage,
|
|
445
|
+
gaugeWidthScale: this.gaugeWidthScale,
|
|
446
|
+
gaugeHeightScale: this.gaugeHeightScale,
|
|
447
|
+
gaugeUpperBound: this.gaugeUpperBound,
|
|
448
|
+
gaugeLowerBound: this.gaugeLowerBound,
|
|
449
|
+
lineLength: this.lineLength,
|
|
450
|
+
offsetLeftPrimaryLine: this.getValueFromStyle(primaryPosLine.left),
|
|
451
|
+
offsetTopPrimaryLine: this.getValueFromStyle(primaryPosLine.top),
|
|
452
|
+
offsetLeftPrimaryPoint: this.getValueFromStyle(primaryPosPoint.left),
|
|
453
|
+
offsetTopPrimaryPoint: this.getValueFromStyle(primaryPosPoint.top),
|
|
454
|
+
offsetLeftSecondaryLine: this.getValueFromStyle(secondaryPosLine.left),
|
|
455
|
+
offsetTopSecondaryLine: this.getValueFromStyle(secondaryPosLine.top),
|
|
456
|
+
offsetLeftSecondaryPoint: this.getValueFromStyle(secondaryPosPoint.left),
|
|
457
|
+
offsetTopSecondaryPoint: this.getValueFromStyle(secondaryPosPoint.top)
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Get number from CSS declaration value
|
|
462
|
+
* @param styleValue value of CSS declaration
|
|
463
|
+
* @returns number without CSS unit
|
|
464
|
+
*/
|
|
465
|
+
getValueFromStyle(styleValue) {
|
|
466
|
+
return Number(styleValue === null || styleValue === void 0 ? void 0 : styleValue.replace('px', ''));
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Compute and update style of containers and labels
|
|
168
470
|
* @returns {void}
|
|
169
471
|
*/
|
|
170
|
-
|
|
171
|
-
if (
|
|
172
|
-
|
|
472
|
+
updateGaugePositions() {
|
|
473
|
+
if (!this.hasValidSize) {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const primaryPosition = this.getPositionStyle(Segment.PRIMARY, this.primaryLineRadian, this.linePointerOffset, -this.lineLength);
|
|
477
|
+
const secondaryPosition = this.getPositionStyle(Segment.SECONDARY, this.secondaryLineRadian, this.linePointerOffset, 0);
|
|
478
|
+
this.primaryContainerStyle = Object.assign({ width: `${this.lineLength}px` }, primaryPosition);
|
|
479
|
+
this.secondaryContainerStyle = Object.assign({ width: `${this.lineLength}px` }, secondaryPosition);
|
|
480
|
+
// position container over line pointer
|
|
481
|
+
if (this.primaryPercentage < GAUGE_PERCENTAGE_THRESHOLD) {
|
|
482
|
+
delete this.primaryContainerStyle.top;
|
|
483
|
+
this.primaryContainerStyle.bottom = '5px';
|
|
173
484
|
}
|
|
174
|
-
|
|
175
|
-
|
|
485
|
+
if (this.secondaryPercentage < GAUGE_PERCENTAGE_THRESHOLD || this.secondaryValue === 0) {
|
|
486
|
+
delete this.secondaryContainerStyle.top;
|
|
487
|
+
this.secondaryContainerStyle.bottom = '5px';
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Compute position style
|
|
492
|
+
* @param segment primary or secondary
|
|
493
|
+
* @param maxRadian max radian
|
|
494
|
+
* @param radiusOffset radius offset from gauge upper bound
|
|
495
|
+
* @param offset line length offset
|
|
496
|
+
* @returns position style
|
|
497
|
+
*/
|
|
498
|
+
getPositionStyle(segment, maxRadian, radiusOffset, offset) {
|
|
499
|
+
let radius = this.size * (1 + radiusOffset) * this.scale;
|
|
500
|
+
let radianValue;
|
|
501
|
+
if (segment === Segment.PRIMARY) {
|
|
502
|
+
radianValue = this.primaryPercentage >= GAUGE_PERCENTAGE_THRESHOLD ? maxRadian : 1;
|
|
176
503
|
}
|
|
177
504
|
else {
|
|
178
|
-
this.
|
|
505
|
+
radianValue = this.secondaryPercentage >= GAUGE_PERCENTAGE_THRESHOLD ? maxRadian : 0;
|
|
506
|
+
}
|
|
507
|
+
// reduce line length when line is on the bottom of canvas
|
|
508
|
+
if ((radianValue === 1 || radianValue === 0) && radiusOffset > 0.1) {
|
|
509
|
+
radius = this.size * (1 + this.pointPointerOffset) * this.scale;
|
|
179
510
|
}
|
|
511
|
+
const radian = radianValue * Math.PI;
|
|
512
|
+
const left = `${Math.round(this.width / 2 + Math.cos(radian) * radius) + offset}px`;
|
|
513
|
+
const top = `${Math.round(this.height + Math.sin(radian) * radius)}px`;
|
|
514
|
+
return { left: left, top: top };
|
|
180
515
|
}
|
|
181
516
|
/**
|
|
182
|
-
*
|
|
183
|
-
* @private
|
|
184
|
-
* @param {number} to ease to value
|
|
185
|
-
* @param {number} from ease from value
|
|
186
|
-
* @param {number} time ease time
|
|
517
|
+
* Scales canvas variables making it responsive before painting
|
|
187
518
|
* @returns {void}
|
|
188
519
|
*/
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
520
|
+
calculateCanvasSize() {
|
|
521
|
+
const lineLength = this.canvas.height * 0.75;
|
|
522
|
+
const bestWidth = 2 * (GAUGE_UPPER_BOUND + LINE_POINTER_OFFSET) * this.canvas.height + 2 * lineLength;
|
|
523
|
+
const ratio = bestWidth / this.canvas.height;
|
|
524
|
+
this.scale = 1;
|
|
525
|
+
if (this.canvas.width < bestWidth) {
|
|
526
|
+
const width = this.canvas.width;
|
|
527
|
+
const bestHeight = width / ratio;
|
|
528
|
+
this.scale = bestHeight / this.canvas.height;
|
|
529
|
+
}
|
|
530
|
+
this.scale = this.scale < 0.1 ? 0.1 : this.scale;
|
|
531
|
+
this.lineLength = this.scale * lineLength < 50 ? 50 : this.scale * lineLength;
|
|
532
|
+
this.gaugeWidthScale = this.scale * GAUGE_WIDTH_SCALE;
|
|
533
|
+
this.gaugeHeightScale = this.scale * GAUGE_HEIGHT_SCALE;
|
|
534
|
+
this.gaugeUpperBound = this.scale * GAUGE_UPPER_BOUND;
|
|
535
|
+
this.gaugeLowerBound = this.scale * GAUGE_LOWER_BOUND;
|
|
536
|
+
this.primaryLineRadian = PRIMARY_RADIAN;
|
|
537
|
+
this.secondaryLineRadian = SECONDARY_RADIAN;
|
|
538
|
+
this.linePointerOffset = LINE_POINTER_OFFSET;
|
|
539
|
+
this.pointPointerOffset = POINT_POINTER_OFFSET;
|
|
540
|
+
if (this.scale < 1) {
|
|
541
|
+
const offset = 0.05 * (1 - this.scale);
|
|
542
|
+
this.primaryLineRadian = PRIMARY_RADIAN + offset;
|
|
543
|
+
this.secondaryLineRadian = SECONDARY_RADIAN - offset;
|
|
544
|
+
this.linePointerOffset = LINE_POINTER_OFFSET + (0.4 * (1 - this.scale));
|
|
545
|
+
if (this.scale <= this.overflowScale) {
|
|
546
|
+
this.linePointerOffset = this.linePointerOffsetOverflow;
|
|
196
547
|
}
|
|
197
|
-
this.frameHandler = this.onFrame(() => this.easeTo(to, from, time));
|
|
198
548
|
}
|
|
549
|
+
this.primaryLineRadian = this.primaryLineRadian > 1.3 ? 1.3 : this.primaryLineRadian;
|
|
550
|
+
this.secondaryLineRadian = this.primaryLineRadian > 1.7 ? 1.7 : this.secondaryLineRadian;
|
|
199
551
|
}
|
|
200
552
|
/**
|
|
201
|
-
*
|
|
202
|
-
* @returns {
|
|
553
|
+
* Calculate and update font sizes on canvas
|
|
554
|
+
* @returns {void}
|
|
203
555
|
*/
|
|
204
|
-
|
|
205
|
-
|
|
556
|
+
updateFontSize() {
|
|
557
|
+
this.calculateLabelFontSize();
|
|
558
|
+
this.calculateValueFontSize();
|
|
206
559
|
}
|
|
207
560
|
/**
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
* @
|
|
561
|
+
* Calculate label or value font size
|
|
562
|
+
* @param ctx canvas context
|
|
563
|
+
* @param textType text type
|
|
564
|
+
* @returns {number} font size
|
|
211
565
|
*/
|
|
212
|
-
|
|
213
|
-
|
|
566
|
+
calculateFontSize(ctx, textType) {
|
|
567
|
+
let maxLine;
|
|
568
|
+
let minFontSize;
|
|
569
|
+
let widthScale;
|
|
570
|
+
let fontSize;
|
|
571
|
+
let longerLabel;
|
|
572
|
+
if (textType === TextType.LABEL) {
|
|
573
|
+
maxLine = MAX_LABEL_LINE;
|
|
574
|
+
minFontSize = MIN_LABEL_FONT_SIZE;
|
|
575
|
+
// buffer for word wrap
|
|
576
|
+
widthScale = 1.1;
|
|
577
|
+
longerLabel = this.primaryLabel.length > this.secondaryLabel.length ? this.primaryLabel : this.secondaryLabel;
|
|
578
|
+
fontSize = Math.ceil(this.scale * this.canvas.height * GAUGE_LABEL_FONT_SCALE);
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
maxLine = MAX_VALUE_LINE;
|
|
582
|
+
minFontSize = MIN_VALUE_FONT_SIZE;
|
|
583
|
+
widthScale = 1;
|
|
584
|
+
const primaryValue = String(this.valueFormatter(this.primaryPercentage, this.primaryValue));
|
|
585
|
+
const secondaryValue = String(this.valueFormatter(this.secondaryPercentage, this.secondaryValue));
|
|
586
|
+
longerLabel = primaryValue.length > secondaryValue.length ? primaryValue : secondaryValue;
|
|
587
|
+
fontSize = Math.ceil(this.scale * this.canvas.height * GAUGE_VALUE_FONT_SCALE);
|
|
588
|
+
}
|
|
589
|
+
let textWidth = canvasHelper.textWidth(ctx, longerLabel, fontSize, getComputedStyle(this).fontFamily);
|
|
590
|
+
let numberOfLines = Math.ceil(textWidth / this.lineLength);
|
|
591
|
+
if (numberOfLines > maxLine) {
|
|
592
|
+
numberOfLines = maxLine;
|
|
593
|
+
}
|
|
594
|
+
do {
|
|
595
|
+
fontSize -= 1;
|
|
596
|
+
if (fontSize < minFontSize) {
|
|
597
|
+
fontSize = minFontSize;
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
textWidth = canvasHelper.textWidth(ctx, longerLabel, fontSize, getComputedStyle(this).fontFamily);
|
|
601
|
+
} while (textWidth * widthScale > this.lineLength * numberOfLines);
|
|
602
|
+
return fontSize;
|
|
214
603
|
}
|
|
215
604
|
/**
|
|
216
|
-
*
|
|
605
|
+
* Update label font size
|
|
217
606
|
* @returns {void}
|
|
218
607
|
*/
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
608
|
+
calculateLabelFontSize() {
|
|
609
|
+
if (!this.canvas.ctx) {
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
this.labelStyle = { maxWidth: `${this.lineLength}px`, fontSize: `${this.calculateFontSize(this.canvas.ctx, TextType.LABEL)}px` };
|
|
222
613
|
}
|
|
223
614
|
/**
|
|
224
|
-
*
|
|
225
|
-
* @param isFrameUpdated Optional called by on frame event
|
|
615
|
+
* Update value font size
|
|
226
616
|
* @returns {void}
|
|
227
617
|
*/
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
if ((isFrameUpdated && !this.canRender()) || !this.dataValid()) {
|
|
618
|
+
calculateValueFontSize() {
|
|
619
|
+
if (!this.canvas.ctx) {
|
|
231
620
|
return;
|
|
232
621
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
622
|
+
this.valueStyle = { maxWidth: `${this.lineLength}px`, fontSize: `${this.calculateFontSize(this.canvas.ctx, TextType.VALUE)}px` };
|
|
623
|
+
}
|
|
624
|
+
/**
|
|
625
|
+
* Compute percentage of value
|
|
626
|
+
* @param value value of primary or secondary
|
|
627
|
+
* @returns percentage of value
|
|
628
|
+
*/
|
|
629
|
+
getPercentage(value) {
|
|
630
|
+
if (value === 0) {
|
|
631
|
+
return 0;
|
|
632
|
+
}
|
|
633
|
+
return 100 * value / (this.primaryValue + this.secondaryValue);
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Handles canvas resize
|
|
637
|
+
* @returns {void}
|
|
638
|
+
*/
|
|
639
|
+
onCanvasResize() {
|
|
640
|
+
this.calculateCanvasSize();
|
|
641
|
+
this.updateFontSize();
|
|
642
|
+
this.renderCanvas('resize');
|
|
643
|
+
this.updateGaugePositions();
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Renders legend container
|
|
647
|
+
* @returns {TemplateResult} Legend template or null
|
|
648
|
+
*/
|
|
649
|
+
get legendTemplate() {
|
|
650
|
+
return this.primaryLegend.length > 0 || this.secondaryLegend.length > 0
|
|
651
|
+
? html `<div part="legend-container-outer">
|
|
652
|
+
<div part="legend-container-inner">
|
|
653
|
+
${this.primaryLegendTemplate}
|
|
654
|
+
${this.secondaryLegendTemplate}
|
|
655
|
+
</div>
|
|
656
|
+
</div>`
|
|
657
|
+
: null;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Renders primary legend if property present
|
|
661
|
+
* @returns {TemplateResult} Primary legend template or null
|
|
662
|
+
*/
|
|
663
|
+
get primaryLegendTemplate() {
|
|
664
|
+
return this.primaryLegend
|
|
665
|
+
? html `<div part="primary-legend">
|
|
666
|
+
<span part="primary-legend-symbol"></span>
|
|
667
|
+
<ef-label max-line="${MAX_LEGEND_LINE}" line-clamp="${MAX_LEGEND_LINE}">${this.primaryLegend}</ef-label>
|
|
668
|
+
</div>`
|
|
669
|
+
: null;
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Renders secondary legend if property present
|
|
673
|
+
* @returns {TemplateResult} Secondary legend template or null
|
|
674
|
+
*/
|
|
675
|
+
get secondaryLegendTemplate() {
|
|
676
|
+
return this.secondaryLegend
|
|
677
|
+
? html `<div part="secondary-legend">
|
|
678
|
+
<span part="secondary-legend-symbol"></span>
|
|
679
|
+
<ef-label max-line="${MAX_LEGEND_LINE}" line-clamp="${MAX_LEGEND_LINE}">${this.secondaryLegend}</ef-label>
|
|
680
|
+
</div>`
|
|
681
|
+
: null;
|
|
682
|
+
}
|
|
683
|
+
render() {
|
|
684
|
+
return html `
|
|
685
|
+
<div part="container">
|
|
686
|
+
${this.legendTemplate}
|
|
687
|
+
<div part="canvas-container">
|
|
688
|
+
<ef-canvas part="canvas" @resize=${this.onCanvasResize}></ef-canvas>
|
|
689
|
+
<div part="primary-container" style=${styleMap(this.primaryContainerStyle)}>
|
|
690
|
+
${this.primaryLabel ? html `
|
|
691
|
+
<ef-label
|
|
692
|
+
part="primary-label"
|
|
693
|
+
max-line="${MAX_LABEL_LINE}"
|
|
694
|
+
line-clamp="${MAX_LABEL_LINE}"
|
|
695
|
+
style=${styleMap(this.labelStyle)}
|
|
696
|
+
>${this.primaryLabel}
|
|
697
|
+
</ef-label><br>`
|
|
698
|
+
: null}
|
|
699
|
+
<ef-label
|
|
700
|
+
part="primary-value"
|
|
701
|
+
truncate=""
|
|
702
|
+
line-clamp="1"
|
|
703
|
+
style=${styleMap(this.valueStyle)}
|
|
704
|
+
>${this.valueFormatter(this.primaryPercentage, this.primaryValue)}</ef-label
|
|
705
|
+
>
|
|
706
|
+
</div>
|
|
707
|
+
<div part="secondary-container" style=${styleMap(this.secondaryContainerStyle)}>
|
|
708
|
+
${this.secondaryLabel ? html `
|
|
709
|
+
<ef-label
|
|
710
|
+
part="secondary-label"
|
|
711
|
+
max-line="${MAX_LABEL_LINE}"
|
|
712
|
+
line-clamp="${MAX_LABEL_LINE}"
|
|
713
|
+
style=${styleMap(this.labelStyle)}
|
|
714
|
+
>${this.secondaryLabel}
|
|
715
|
+
</ef-label><br>`
|
|
716
|
+
: null}
|
|
717
|
+
<ef-label
|
|
718
|
+
part="secondary-value"
|
|
719
|
+
truncate=""
|
|
720
|
+
line-clamp="1"
|
|
721
|
+
style=${styleMap(this.valueStyle)}
|
|
722
|
+
>${this.valueFormatter(this.secondaryPercentage, this.secondaryValue)}</ef-label
|
|
723
|
+
>
|
|
724
|
+
</div>
|
|
725
|
+
</div>
|
|
726
|
+
</div>
|
|
727
|
+
`;
|
|
271
728
|
}
|
|
272
729
|
};
|
|
273
730
|
__decorate([
|
|
274
731
|
property({ attribute: 'primary-value', type: Number })
|
|
275
|
-
], SwingGauge.prototype, "primaryValue",
|
|
732
|
+
], SwingGauge.prototype, "primaryValue", null);
|
|
276
733
|
__decorate([
|
|
277
734
|
property({ attribute: 'primary-label', type: String })
|
|
278
735
|
], SwingGauge.prototype, "primaryLabel", void 0);
|
|
279
736
|
__decorate([
|
|
280
737
|
property({ attribute: 'secondary-value', type: Number })
|
|
281
|
-
], SwingGauge.prototype, "secondaryValue",
|
|
738
|
+
], SwingGauge.prototype, "secondaryValue", null);
|
|
282
739
|
__decorate([
|
|
283
740
|
property({ attribute: 'secondary-label', type: String })
|
|
284
741
|
], SwingGauge.prototype, "secondaryLabel", void 0);
|
|
285
742
|
__decorate([
|
|
286
743
|
property({ type: Number })
|
|
287
744
|
], SwingGauge.prototype, "duration", void 0);
|
|
745
|
+
__decorate([
|
|
746
|
+
property({ type: String, reflect: true, attribute: 'primary-legend' })
|
|
747
|
+
], SwingGauge.prototype, "primaryLegend", void 0);
|
|
748
|
+
__decorate([
|
|
749
|
+
property({ type: String, reflect: true, attribute: 'secondary-legend' })
|
|
750
|
+
], SwingGauge.prototype, "secondaryLegend", void 0);
|
|
751
|
+
__decorate([
|
|
752
|
+
property({ type: Function, attribute: false })
|
|
753
|
+
], SwingGauge.prototype, "valueFormatter", void 0);
|
|
754
|
+
__decorate([
|
|
755
|
+
state()
|
|
756
|
+
], SwingGauge.prototype, "primaryContainerStyle", void 0);
|
|
757
|
+
__decorate([
|
|
758
|
+
state()
|
|
759
|
+
], SwingGauge.prototype, "secondaryContainerStyle", void 0);
|
|
760
|
+
__decorate([
|
|
761
|
+
state()
|
|
762
|
+
], SwingGauge.prototype, "labelStyle", void 0);
|
|
763
|
+
__decorate([
|
|
764
|
+
state()
|
|
765
|
+
], SwingGauge.prototype, "valueStyle", void 0);
|
|
766
|
+
__decorate([
|
|
767
|
+
query('[part=primary-container]', true)
|
|
768
|
+
], SwingGauge.prototype, "primaryContainer", void 0);
|
|
769
|
+
__decorate([
|
|
770
|
+
query('[part=secondary-container]', true)
|
|
771
|
+
], SwingGauge.prototype, "secondaryContainer", void 0);
|
|
772
|
+
__decorate([
|
|
773
|
+
query('[part=legend-container-outer]')
|
|
774
|
+
], SwingGauge.prototype, "legendContainer", void 0);
|
|
775
|
+
__decorate([
|
|
776
|
+
query('[part=canvas]', true)
|
|
777
|
+
], SwingGauge.prototype, "canvas", void 0);
|
|
288
778
|
SwingGauge = __decorate([
|
|
289
779
|
customElement('ef-swing-gauge', {
|
|
290
780
|
alias: 'sapphire-swing-gauge'
|