@limetech/lime-elements 40.19.0 → 40.20.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/cjs/keyboard-navigation-VyqkMDKy.js +152 -0
  3. package/dist/cjs/lime-elements.cjs.js +1 -1
  4. package/dist/cjs/{limel-breadcrumbs_6.cjs.entry.js → limel-badge_7.cjs.entry.js} +33 -0
  5. package/dist/cjs/limel-chart.cjs.entry.js +51371 -268
  6. package/dist/cjs/limel-markdown.cjs.entry.js +2 -2
  7. package/dist/cjs/limel-prosemirror-adapter.cjs.entry.js +1 -1
  8. package/dist/cjs/limel-tab-bar.cjs.entry.js +6 -149
  9. package/dist/cjs/loader.cjs.js +1 -1
  10. package/dist/cjs/{markdown-exporter-BWS2EBxq.js → markdown-exporter-CGNfjGr9.js} +80 -897
  11. package/dist/cjs/{markdown-parser-toAp9-Eq.js → markdown-parser-C14XF_G3.js} +994 -38
  12. package/dist/collection/components/chart/chart.css +75 -924
  13. package/dist/collection/components/chart/chart.js +332 -287
  14. package/dist/collection/components/chart/options.js +568 -0
  15. package/dist/collection/components/chart/scale.js +193 -0
  16. package/dist/collection/components/chart/theme.js +145 -0
  17. package/dist/collection/components/scroller/scroller.js +1 -1
  18. package/dist/esm/keyboard-navigation-BF7IKmnG.js +147 -0
  19. package/dist/esm/{keycodes-Bu6-QXrA.js → keycodes-DQ5DmW_Y.js} +1 -1
  20. package/dist/esm/lime-elements.js +1 -1
  21. package/dist/esm/{limel-breadcrumbs_6.entry.js → limel-badge_7.entry.js} +36 -4
  22. package/dist/esm/limel-chart.entry.js +51372 -269
  23. package/dist/esm/limel-chip-set.entry.js +1 -1
  24. package/dist/esm/limel-chip_2.entry.js +1 -1
  25. package/dist/esm/limel-markdown.entry.js +2 -2
  26. package/dist/esm/limel-pagination-jump.entry.js +1 -1
  27. package/dist/esm/limel-picker.entry.js +2 -2
  28. package/dist/esm/limel-popover_2.entry.js +1 -1
  29. package/dist/esm/limel-prosemirror-adapter.entry.js +1 -1
  30. package/dist/esm/limel-resize-handle.entry.js +1 -1
  31. package/dist/esm/limel-select.entry.js +2 -2
  32. package/dist/esm/limel-side-panel.entry.js +1 -1
  33. package/dist/esm/limel-tab-bar.entry.js +2 -145
  34. package/dist/esm/limel-text-editor-link-menu.entry.js +1 -1
  35. package/dist/esm/loader.js +1 -1
  36. package/dist/esm/{markdown-exporter-B2vFxSLw.js → markdown-exporter-DcFcD699.js} +80 -897
  37. package/dist/esm/{markdown-parser-Cw8iW5R9.js → markdown-parser-8aHA9IYo.js} +991 -33
  38. package/dist/esm/{typeahead-DOlnT3wh.js → typeahead-B4PwrlM3.js} +1 -1
  39. package/dist/lime-elements/lime-elements.esm.js +1 -1
  40. package/dist/lime-elements/{p-d4702653.entry.js → p-07f3565b.entry.js} +1 -1
  41. package/dist/lime-elements/p-0887e0df.entry.js +56 -0
  42. package/dist/lime-elements/{p-0910aefc.entry.js → p-22e9e327.entry.js} +1 -1
  43. package/dist/lime-elements/{p-7bf3bf8a.entry.js → p-23067836.entry.js} +1 -1
  44. package/dist/lime-elements/{p-7f0743d6.entry.js → p-56e2fa48.entry.js} +1 -1
  45. package/dist/lime-elements/{p-af7d07fd.entry.js → p-5e408c27.entry.js} +1 -1
  46. package/dist/lime-elements/{p-843886fe.entry.js → p-7fcd48c6.entry.js} +1 -1
  47. package/dist/lime-elements/{p-1d9bc526.entry.js → p-9edd79a8.entry.js} +1 -1
  48. package/dist/lime-elements/p-C9gctvIB.js +1 -0
  49. package/dist/lime-elements/{p-fYs7n6yY.js → p-DNYOwOWu.js} +1 -1
  50. package/dist/lime-elements/{p-Bu6-QXrA.js → p-DQ5DmW_Y.js} +1 -1
  51. package/dist/lime-elements/p-_1yBt1pG.js +1 -0
  52. package/dist/lime-elements/p-a807a45f.entry.js +159 -0
  53. package/dist/lime-elements/{p-c2f993cc.entry.js → p-a891f3e8.entry.js} +1 -1
  54. package/dist/lime-elements/{p-45572e9d.entry.js → p-c8a34cef.entry.js} +1 -1
  55. package/dist/lime-elements/{p-4834e7c1.entry.js → p-cd479c23.entry.js} +1 -1
  56. package/dist/lime-elements/p-cf2d43c7.entry.js +1 -0
  57. package/dist/lime-elements/{p-94ae27e2.entry.js → p-f3b93ce8.entry.js} +2 -2
  58. package/dist/lime-elements/p-kiQd8Ntf.js +7 -0
  59. package/dist/types/components/chart/chart.d.ts +51 -52
  60. package/dist/types/components/chart/chart.types.d.ts +5 -0
  61. package/dist/types/components/chart/options.d.ts +88 -0
  62. package/dist/types/components/chart/scale.d.ts +101 -0
  63. package/dist/types/components/chart/theme.d.ts +52 -0
  64. package/dist/types/components.d.ts +7 -38
  65. package/package.json +4 -3
  66. package/dist/cjs/limel-badge.cjs.entry.js +0 -37
  67. package/dist/esm/limel-badge.entry.js +0 -35
  68. package/dist/lime-elements/p-02aac2c0.entry.js +0 -1
  69. package/dist/lime-elements/p-38ab193f.entry.js +0 -1
  70. package/dist/lime-elements/p-3ca188f6.entry.js +0 -159
  71. package/dist/lime-elements/p-Bd37Vplf.js +0 -7
  72. package/dist/lime-elements/p-CvHpvp0f.js +0 -1
  73. package/dist/lime-elements/p-f7a90228.entry.js +0 -1
@@ -1,18 +1,25 @@
1
- import { h } from "@stencil/core";
1
+ import { h, Host, } from "@stencil/core";
2
+ import { BarChart, GaugeChart, LineChart, PieChart, ScatterChart, } from "echarts/charts";
3
+ import { GridComponent, PolarComponent, TooltipComponent, } from "echarts/components";
4
+ import { init, use } from "echarts/core";
5
+ import { SVGRenderer } from "echarts/renderers";
2
6
  import translate from "../../global/translations";
3
- import { createRandomString } from "../../util/random-string";
4
- const PERCENT = 100;
5
- const DEFAULT_INCREMENT_SIZE = 10;
6
- /**
7
- * Types whose items are parts of one whole. They draw no axis, and an item's
8
- * value or range extent is its share of `maxValue`, or of the combined items.
9
- */
10
- const WHOLE_TYPES = new Set([
11
- 'stacked-bar',
12
- 'pie',
13
- 'doughnut',
14
- 'ring',
15
- ]);
7
+ import { findNavigationTarget, findTabStop, isNavigationKey, NO_NAVIGATION_TARGET, } from "../../util/keyboard-navigation";
8
+ import { drawChart, fitItemTexts, getItemIndex, getItemLabel, locateItem, } from "./options";
9
+ import { formatValue, getAxisRange, MAX_AXIS_STEPS, usesAxisIncrement, } from "./scale";
10
+ import { createThemeReader, watchTheme, } from "./theme";
11
+ const orientations = ['horizontal', 'vertical'];
12
+ const extensions = [
13
+ BarChart,
14
+ GaugeChart,
15
+ LineChart,
16
+ PieChart,
17
+ ScatterChart,
18
+ GridComponent,
19
+ PolarComponent,
20
+ TooltipComponent,
21
+ SVGRenderer,
22
+ ];
16
23
  /**
17
24
  * A chart is a graphical representation of data, in which
18
25
  * visual symbols such as such bars, dots, lines, or slices, represent
@@ -41,7 +48,6 @@ const WHOLE_TYPES = new Set([
41
48
  * @exampleComponent limel-example-chart-accessibility
42
49
  * @exampleComponent limel-example-chart-axis-labels
43
50
  * @exampleComponent limel-example-chart-styling
44
- * @exampleComponent limel-example-chart-creative-styling
45
51
  * @beta
46
52
  */
47
53
  export class Chart {
@@ -90,8 +96,42 @@ export class Chart {
90
96
  * Indicates whether the chart is in a loading state.
91
97
  */
92
98
  this.loading = false;
99
+ /**
100
+ * The item that last had focus, which is the one that Tab returns to.
101
+ */
102
+ this.focusedIndex = 0;
103
+ this.themeMayHaveChanged = false;
104
+ this.invalidColors = new Set();
105
+ this.setPlot = (element) => {
106
+ this.plot = element;
107
+ };
108
+ this.handleResize = () => {
109
+ this.draw();
110
+ };
111
+ this.handleThemeChange = () => {
112
+ this.themeMayHaveChanged = true;
113
+ this.draw();
114
+ };
115
+ this.handleChartClick = (event) => {
116
+ var _a, _b;
117
+ if (!this.drawing) {
118
+ return;
119
+ }
120
+ const item = this.getClickableItem(getItemIndex(this.drawing, event));
121
+ if (!item) {
122
+ return;
123
+ }
124
+ (_b = (_a = event.event) === null || _a === void 0 ? void 0 : _a.event) === null || _b === void 0 ? void 0 : _b.stopPropagation();
125
+ this.interact.emit(item);
126
+ };
127
+ this.handleChartOver = (event) => {
128
+ this.highlightItemAt(event, true);
129
+ };
130
+ this.handleChartOut = (event) => {
131
+ this.highlightItemAt(event, false);
132
+ };
93
133
  this.handleClick = (event) => {
94
- const item = this.getClickableItem(event.currentTarget);
134
+ const item = this.getClickableItem(this.getRowIndex(event));
95
135
  if (!item) {
96
136
  return;
97
137
  }
@@ -99,27 +139,79 @@ export class Chart {
99
139
  this.interact.emit(item);
100
140
  };
101
141
  this.handleKeyDown = (event) => {
142
+ const orientation = orientations.find((option) => isNavigationKey(event, { orientation: option }));
143
+ if (orientation) {
144
+ event.preventDefault();
145
+ this.focusItem(findNavigationTarget(this.items, event.key, this.getRowIndex(event), { orientation: orientation }));
146
+ return;
147
+ }
102
148
  if (event.key !== 'Enter' && event.key !== ' ') {
103
149
  return;
104
150
  }
105
- const item = this.getClickableItem(event.currentTarget);
151
+ const item = this.getClickableItem(this.getRowIndex(event));
106
152
  if (!item) {
107
153
  return;
108
154
  }
109
155
  event.preventDefault();
110
156
  this.interact.emit(item);
111
157
  };
158
+ this.handleFocus = (event) => {
159
+ const row = event.currentTarget;
160
+ this.focusedIndex = Number(row.dataset.index);
161
+ this.showItem(row, true);
162
+ };
163
+ this.handleBlur = (event) => {
164
+ this.showItem(event.currentTarget, false);
165
+ };
112
166
  }
113
167
  componentWillLoad() {
114
- this.recalculateRangeData();
168
+ this.warnAboutAxisIncrement();
169
+ }
170
+ connectedCallback() {
171
+ this.draw();
172
+ }
173
+ componentDidRender() {
174
+ this.draw();
175
+ }
176
+ disconnectedCallback() {
177
+ var _a, _b, _c;
178
+ this.disposeChart();
179
+ (_a = this.resizeObserver) === null || _a === void 0 ? void 0 : _a.disconnect();
180
+ this.resizeObserver = undefined;
181
+ (_b = this.stopWatchingTheme) === null || _b === void 0 ? void 0 : _b.call(this);
182
+ this.stopWatchingTheme = undefined;
183
+ (_c = this.themeReader) === null || _c === void 0 ? void 0 : _c.dispose();
184
+ this.themeReader = undefined;
185
+ }
186
+ warnAboutAxisIncrement() {
187
+ const warning = this.getAxisIncrementWarning();
188
+ if (warning && warning !== this.axisIncrementWarning) {
189
+ console.warn(warning);
190
+ }
191
+ this.axisIncrementWarning = warning;
192
+ }
193
+ getAxisIncrementWarning() {
194
+ var _a;
195
+ const increment = this.axisIncrement;
196
+ if (increment === undefined || increment === null) {
197
+ return;
198
+ }
199
+ if (increment <= 0 || Number.isNaN(increment)) {
200
+ return `limel-chart: \`axisIncrement\` must be above 0, but was ${increment}. Working out a step from the values instead.`;
201
+ }
202
+ if (!usesAxisIncrement(this.type)) {
203
+ return;
204
+ }
205
+ const range = getAxisRange((_a = this.items) !== null && _a !== void 0 ? _a : [], this.maxValue, increment);
206
+ if (range.increment !== increment) {
207
+ return `limel-chart: \`axisIncrement\` ${increment} would divide the axis into more than ${MAX_AXIS_STEPS} steps. Working out a step from the values instead.`;
208
+ }
115
209
  }
116
210
  render() {
117
211
  if (this.loading) {
118
212
  return h("limel-spinner", { limeBranded: false });
119
213
  }
120
- return (h("table", { "aria-busy": this.loading ? 'true' : 'false', "aria-live": "polite", style: {
121
- '--limel-chart-number-of-items': this.items.length.toString(),
122
- } }, this.renderCaption(), this.renderTableHeader(), this.renderAxises(), h("tbody", { class: "chart" }, this.renderItems())));
214
+ return (h(Host, null, h("div", { class: "plot", "aria-hidden": "true", ref: this.setPlot }), h("table", { "aria-live": "polite" }, this.renderCaption(), this.renderTableHeader(), h("tbody", null, this.renderItems()))));
123
215
  }
124
216
  renderCaption() {
125
217
  if (!this.accessibleLabel) {
@@ -128,300 +220,240 @@ export class Chart {
128
220
  return h("caption", null, this.accessibleLabel);
129
221
  }
130
222
  renderTableHeader() {
131
- var _a, _b;
132
- return (h("thead", null, h("tr", null, h("th", { scope: "col" }, (_a = this.accessibleItemsLabel) !== null && _a !== void 0 ? _a : translate.get('items', this.language)), h("th", { scope: "col" }, (_b = this.accessibleValuesLabel) !== null && _b !== void 0 ? _b : translate.get('value', this.language)))));
223
+ return (h("thead", null, h("tr", null, h("th", { scope: "col" }, this.itemsLabel), h("th", { scope: "col" }, this.valuesLabel))));
133
224
  }
134
- renderAxises() {
135
- if (!['bar', 'dot', 'area', 'line', 'scatter'].includes(this.type)) {
225
+ get itemsLabel() {
226
+ var _a;
227
+ return ((_a = this.accessibleItemsLabel) !== null && _a !== void 0 ? _a : translate.get('items', this.language));
228
+ }
229
+ get valuesLabel() {
230
+ var _a;
231
+ return ((_a = this.accessibleValuesLabel) !== null && _a !== void 0 ? _a : translate.get('value', this.language));
232
+ }
233
+ renderItems() {
234
+ var _a, _b;
235
+ const tabStop = findTabStop((_a = this.items) !== null && _a !== void 0 ? _a : [], this.focusedIndex);
236
+ return (_b = this.items) === null || _b === void 0 ? void 0 : _b.map((item, index) => (h("tr", { "data-index": index, "aria-description": this.getRowDescription(index), tabIndex: index === tabStop ? 0 : -1, role: item.clickable ? 'button' : null, onClick: this.handleClick, onKeyDown: this.handleKeyDown, onFocus: this.handleFocus, onBlur: this.handleBlur }, h("td", null, item.text), h("td", null, formatValue(item, this.type)))));
237
+ }
238
+ getRowDescription(index) {
239
+ const label = getItemLabel({
240
+ items: this.items,
241
+ type: this.type,
242
+ maxValue: this.maxValue,
243
+ displayItemPercentage: this.displayItemPercentage,
244
+ }, index);
245
+ return label === this.items[index].text ? undefined : label;
246
+ }
247
+ draw() {
248
+ var _a;
249
+ if (!((_a = this.plot) === null || _a === void 0 ? void 0 : _a.isConnected)) {
250
+ this.disposeChart();
136
251
  return;
137
252
  }
138
- if (this.type === 'scatter') {
139
- return this.renderScatterAxises();
253
+ this.observeSize();
254
+ const { clientWidth: width, clientHeight: height } = this.plot;
255
+ if (width && !height) {
256
+ this.host.toggleAttribute('data-fallback-height', true);
140
257
  }
141
- return this.renderAxisLines(this.range);
142
- }
143
- // Two value axes, so a full grid: horizontal lines for the vertical axis,
144
- // vertical lines for the horizontal one. Which range maps to which flips
145
- // with `orientation`, like the points.
146
- renderScatterAxises() {
147
- const portrait = this.orientation === 'portrait';
148
- const horizontalLines = portrait ? this.secondaryAxisRange : this.range;
149
- const verticalLines = portrait ? this.range : this.secondaryAxisRange;
150
- return [
151
- this.renderAxisLines(horizontalLines, 'horizontal-lines'),
152
- this.renderAxisLines(verticalLines, 'vertical-lines'),
153
- ];
154
- }
155
- renderAxisLines(range, direction) {
156
- const { minValue, maxValue, increment } = range;
157
- const lines = [];
158
- for (let value = minValue; value <= maxValue; value += increment) {
159
- lines.push(h("div", { class: {
160
- 'axis-line': true,
161
- 'zero-line': value === 0,
162
- }, role: "presentation" }, h("limel-badge", { label: value })));
258
+ if (!width || !height) {
259
+ return;
163
260
  }
164
- const cssClass = { axises: true };
165
- if (direction) {
166
- cssClass[direction] = true;
261
+ this.createChart();
262
+ if (width !== this.chart.getWidth() ||
263
+ height !== this.chart.getHeight()) {
264
+ this.chart.resize();
167
265
  }
168
- return (h("div", { class: cssClass, role: "presentation", key: direction }, lines));
266
+ this.updateChart();
267
+ this.fitItemTextsToSize();
169
268
  }
170
- renderItems() {
269
+ createChart() {
171
270
  var _a;
172
- if (!((_a = this.items) === null || _a === void 0 ? void 0 : _a.length)) {
271
+ if (((_a = this.chart) === null || _a === void 0 ? void 0 : _a.getDom()) === this.plot) {
173
272
  return;
174
273
  }
175
- let cumulativeOffset = 0;
176
- return this.items.map((item, index) => {
177
- const itemId = createRandomString();
178
- const sizeAndOffset = this.calculateSizeAndOffset(item);
179
- const size = sizeAndOffset.size;
180
- let offset = sizeAndOffset.offset;
181
- if (this.type === 'pie' || this.type === 'doughnut') {
182
- offset = cumulativeOffset;
183
- cumulativeOffset += size;
184
- }
185
- return (h("tr", { style: this.getItemStyle(item, index, size, offset), class: this.getItemClass(item), key: itemId, id: itemId, "data-index": index, tabIndex: 0, role: item.clickable ? 'button' : null, onClick: this.handleClick, onKeyDown: this.handleKeyDown }, h("td", { class: "text" }, this.getItemText(item)), h("td", { class: "value" }, this.getFormattedValue(item)), this.renderTooltip(item, itemId, size)));
186
- });
274
+ this.disposeChart();
275
+ /*!
276
+ * Apache ECharts
277
+ * Copyright 2017-2026 The Apache Software Foundation
278
+ *
279
+ * This product includes software developed at
280
+ * The Apache Software Foundation (https://www.apache.org/).
281
+ *
282
+ * Licensed under the Apache License, Version 2.0
283
+ * (https://www.apache.org/licenses/LICENSE-2.0).
284
+ *
285
+ *
286
+ * ZRender
287
+ * Copyright (c) 2017, Baidu Inc.
288
+ * All rights reserved.
289
+ *
290
+ * Redistribution and use in source and binary forms, with or without
291
+ * modification, are permitted provided that the following conditions are met:
292
+ *
293
+ * * Redistributions of source code must retain the above copyright notice, this
294
+ * list of conditions and the following disclaimer.
295
+ *
296
+ * * Redistributions in binary form must reproduce the above copyright notice,
297
+ * this list of conditions and the following disclaimer in the documentation
298
+ * and/or other materials provided with the distribution.
299
+ *
300
+ * * Neither the name of the copyright holder nor the names of its
301
+ * contributors may be used to endorse or promote products derived from
302
+ * this software without specific prior written permission.
303
+ *
304
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
305
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
306
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
307
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
308
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
309
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
310
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
311
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
312
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
313
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
314
+ */
315
+ use(extensions);
316
+ this.chart = init(this.plot, null, { renderer: 'svg' });
317
+ this.chart.on('click', this.handleChartClick);
318
+ this.chart.on('mouseover', this.handleChartOver);
319
+ this.chart.on('mouseout', this.handleChartOut);
187
320
  }
188
- getItemStyle(item, index, size, offset) {
189
- if (this.type === 'scatter') {
190
- return this.getScatterItemStyle(item, index);
321
+ updateChart() {
322
+ var _a, _b;
323
+ const settings = this.getSettings();
324
+ const drawnSettings = JSON.stringify(settings);
325
+ if (drawnSettings === this.drawnSettings && !this.themeMayHaveChanged) {
326
+ return;
191
327
  }
192
- const style = {
193
- '--limel-chart-item-offset': `${offset}`,
194
- '--limel-chart-item-size': `${size}`,
195
- '--limel-chart-item-index': `${index}`,
196
- '--limel-chart-item-value': `${item.value}`,
197
- };
198
- if (item.color) {
199
- style['--limel-chart-item-color'] = item.color;
328
+ this.themeMayHaveChanged = false;
329
+ (_a = this.themeReader) !== null && _a !== void 0 ? _a : (this.themeReader = createThemeReader(this.host.shadowRoot));
330
+ (_b = this.stopWatchingTheme) !== null && _b !== void 0 ? _b : (this.stopWatchingTheme = watchTheme(this.host, this.handleThemeChange));
331
+ const theme = this.themeReader.theme();
332
+ const coloredSettings = this.withItemColors(settings, theme);
333
+ const drawnTheme = JSON.stringify({
334
+ theme: theme,
335
+ itemColors: coloredSettings.items.map((item) => item.color),
336
+ });
337
+ if (drawnSettings === this.drawnSettings &&
338
+ drawnTheme === this.drawnTheme) {
339
+ return;
200
340
  }
201
- if (this.type === 'line' || this.type === 'area') {
202
- const nextItem = this.calculateSizeAndOffset(this.items[index + 1]);
203
- style['--limel-chart-next-item-size'] = `${nextItem.size}`;
204
- style['--limel-chart-next-item-offset'] = `${nextItem.offset}`;
341
+ this.drawnSettings = drawnSettings;
342
+ this.drawnTheme = drawnTheme;
343
+ this.drawing = drawChart(coloredSettings, theme, this.itemSpace);
344
+ this.chart.setOption(this.drawing.option, { notMerge: true });
345
+ const focusedRow = this.host.shadowRoot.activeElement;
346
+ if (focusedRow instanceof HTMLElement && focusedRow.dataset.index) {
347
+ this.showItem(focusedRow, true);
205
348
  }
206
- return style;
207
349
  }
208
- getScatterItemStyle(item, index) {
209
- const style = {
210
- '--limel-chart-item-offset-x': `${this.normalize(this.getXValue(item), this.secondaryAxisRange)}`,
211
- '--limel-chart-item-offset-y': `${this.normalize(this.getYValue(item), this.range)}`,
212
- '--limel-chart-item-index': `${index}`,
213
- };
214
- if (item.color) {
215
- style['--limel-chart-item-color'] = item.color;
350
+ fitItemTextsToSize() {
351
+ var _a;
352
+ const axis = (_a = this.drawing) === null || _a === void 0 ? void 0 : _a.itemTextAxis;
353
+ if (!axis) {
354
+ return;
216
355
  }
217
- return style;
356
+ const finder = { [`${axis}Index`]: 0 };
357
+ const itemSpace = Math.floor(Math.abs(this.chart.convertToPixel(finder, 1) -
358
+ this.chart.convertToPixel(finder, 0)));
359
+ if (itemSpace === this.itemSpace) {
360
+ return;
361
+ }
362
+ this.itemSpace = itemSpace;
363
+ this.chart.setOption(fitItemTexts(this.drawing, itemSpace));
218
364
  }
219
- getItemClass(item) {
365
+ getSettings() {
366
+ var _a;
220
367
  return {
221
- item: true,
222
- 'has-start-value': this.type !== 'scatter' && Array.isArray(item.value),
223
- 'has-negative-value-only': this.getMaximumValue(item) < 0 && !this.isRangeItem(item),
224
- // Scatter coordinates are independent values, so "value is zero"
225
- // (which hides the value label elsewhere) must not apply.
226
- 'has-value-zero': this.type !== 'scatter' && this.getMaximumValue(item) === 0,
368
+ items: ((_a = this.items) !== null && _a !== void 0 ? _a : []).map((item) => ({
369
+ text: item.text,
370
+ value: item.value,
371
+ formattedValue: item.formattedValue,
372
+ color: item.color,
373
+ clickable: item.clickable,
374
+ })),
375
+ type: this.type,
376
+ orientation: this.orientation,
377
+ maxValue: this.maxValue,
378
+ axisIncrement: this.axisIncrement,
379
+ displayAxisLabels: this.displayAxisLabels,
380
+ itemsLabel: this.itemsLabel,
381
+ valuesLabel: this.valuesLabel,
382
+ displayItemText: this.displayItemText,
383
+ displayItemValue: this.displayItemValue,
384
+ displayItemPercentage: this.displayItemPercentage,
227
385
  };
228
386
  }
229
- calculateSizeAndOffset(item) {
230
- const { minValue, totalRange } = this.range;
231
- if (!item) {
232
- return {
233
- size: 0,
234
- offset: 0,
235
- };
236
- }
237
- if (this.isPartOfWhole()) {
238
- return {
239
- size: (this.getValueSpan(item) / totalRange) * PERCENT,
240
- offset: 0,
241
- };
242
- }
243
- let startValue = 0;
244
- if (this.isRangeItem(item)) {
245
- startValue = this.getMinimumValue(item);
246
- }
247
- const normalizedStart = ((startValue - minValue) / totalRange) * PERCENT;
248
- const normalizedEnd = ((this.getMaximumValue(item) - minValue) / totalRange) * PERCENT;
249
- return {
250
- size: normalizedEnd - normalizedStart,
251
- offset: normalizedStart,
252
- };
387
+ withItemColors(settings, theme) {
388
+ return Object.assign(Object.assign({}, settings), { items: settings.items.map((item) => (Object.assign(Object.assign({}, item), { color: this.getItemColor(item, theme) }))) });
253
389
  }
254
- getFormattedValue(item) {
255
- const { value, formattedValue } = item;
256
- if (formattedValue) {
257
- return formattedValue;
390
+ getItemColor(item, theme) {
391
+ if (!item.color) {
392
+ return theme.itemColor;
258
393
  }
259
- if (Array.isArray(value)) {
260
- if (this.type === 'scatter') {
261
- return `(${value[0]}, ${value[1]})`;
262
- }
263
- return `${value[0]} — ${value[1]}`;
394
+ const color = this.themeReader.color(item.color);
395
+ if (color) {
396
+ return color;
264
397
  }
265
- return `${value}`;
266
- }
267
- getItemText(item) {
268
- return item.text;
269
- }
270
- renderTooltip(item, itemId, size) {
271
- const text = this.getItemText(item);
272
- const PERCENT_DECIMAL = 2;
273
- const formattedValue = this.getFormattedValue(item);
274
- const tooltipProps = {
275
- label: text,
276
- helperLabel: formattedValue,
277
- elementId: itemId,
278
- };
279
- if (this.displayItemPercentage && this.isPartOfWhole()) {
280
- tooltipProps.label = `${text} (${size.toFixed(PERCENT_DECIMAL)}%)`;
398
+ if (!this.invalidColors.has(item.color)) {
399
+ this.invalidColors.add(item.color);
400
+ const hint = item.color.includes('var(')
401
+ ? ' Check that its variables are set, and that they make a color.'
402
+ : '';
403
+ console.warn(`limel-chart: the color of an item must be a CSS color, but was \`${item.color}\`.${hint} Using the default item color instead.`);
281
404
  }
282
- return (h("limel-tooltip", Object.assign({}, tooltipProps, { openDirection: this.orientation === 'portrait' ? 'right' : 'top' })));
405
+ return theme.itemColor;
283
406
  }
284
- calculateRange() {
285
- var _a;
286
- if (this.range) {
287
- return this.range;
288
- }
289
- if (this.isPartOfWhole()) {
290
- return this.calculateWholeRange();
291
- }
292
- const minRange = Math.min(0, ...this.items.map(this.getMinimumValue));
293
- const maxRange = Math.max(...this.items.map(this.getMaximumValue));
294
- const finalMaxRange = (_a = this.maxValue) !== null && _a !== void 0 ? _a : maxRange;
295
- if (!this.axisIncrement) {
296
- this.axisIncrement = this.calculateAxisIncrement(this.items.map(this.getMaximumValue));
407
+ observeSize() {
408
+ if (this.resizeObserver || typeof ResizeObserver === 'undefined') {
409
+ return;
297
410
  }
298
- const visualMaxValue = Math.ceil(finalMaxRange / this.axisIncrement) * this.axisIncrement;
299
- const visualMinValue = Math.floor(minRange / this.axisIncrement) * this.axisIncrement;
300
- const totalRange = visualMaxValue - visualMinValue;
301
- return {
302
- minValue: visualMinValue,
303
- maxValue: visualMaxValue,
304
- totalRange: totalRange,
305
- increment: this.axisIncrement,
306
- };
411
+ this.resizeObserver = new ResizeObserver(this.handleResize);
412
+ this.resizeObserver.observe(this.host);
307
413
  }
308
- /**
309
- * The range of a chart whose items are parts of one whole: `maxValue`
310
- * when set, otherwise the combined item values or range extents. The value
311
- * is a scale, not a cap, so the combined size can exceed it. The whole is
312
- * not rounded to an axis step, since these types draw no axis and an item's
313
- * size has to be its exact share.
314
- */
315
- calculateWholeRange() {
414
+ disposeChart() {
316
415
  var _a;
317
- const sum = this.items.reduce((total, item) => total + this.getValueSpan(item), 0);
318
- const inferredWhole = sum > 0 ? sum : 1;
319
- // An explicit zero also falls back to 1, so normalization stays finite.
320
- const whole = ((_a = this.maxValue) !== null && _a !== void 0 ? _a : inferredWhole) || 1;
321
- return {
322
- minValue: 0,
323
- maxValue: whole,
324
- totalRange: whole,
325
- increment: whole,
326
- };
327
- }
328
- isPartOfWhole() {
329
- return WHOLE_TYPES.has(this.type);
330
- }
331
- calculateAxisIncrement(values, steps = DEFAULT_INCREMENT_SIZE) {
332
- return this.calculateNiceStep(Math.max(...values), steps);
333
- }
334
- // A "nice" step (…× 10ⁿ) dividing `span` into ~`steps` intervals. Takes the
335
- // axis length, not a raw max, so it's sign-safe (a negative max would make
336
- // `Math.log10` return `NaN`).
337
- calculateNiceStep(span, steps = DEFAULT_INCREMENT_SIZE) {
338
- if (span <= 0) {
339
- // Every value is identical (e.g. all zero); any positive step works.
340
- return 1;
416
+ (_a = this.chart) === null || _a === void 0 ? void 0 : _a.dispose();
417
+ this.chart = undefined;
418
+ this.drawing = undefined;
419
+ this.drawnSettings = undefined;
420
+ this.drawnTheme = undefined;
421
+ this.itemSpace = undefined;
422
+ }
423
+ highlightItemAt(event, highlight) {
424
+ if (!this.drawing) {
425
+ return;
341
426
  }
342
- const roughStep = span / steps;
343
- const magnitude = 10 ** Math.floor(Math.log10(roughStep));
344
- return Math.ceil(roughStep / magnitude) * magnitude;
345
- }
346
- // Axis length measured through zero, so the origin is always included.
347
- axisSpan(values) {
348
- return Math.max(0, ...values) - Math.min(0, ...values);
349
- }
350
- // A "nice" rounded range for one scatter axis. Both bounds include zero, so
351
- // a fully-negative axis still shows its origin (and zero line).
352
- calculateAxisRange(values, increment) {
353
- const minValue = Math.floor(Math.min(0, ...values) / increment) * increment;
354
- const maxValue = Math.ceil(Math.max(0, ...values) / increment) * increment;
355
- return {
356
- minValue: minValue,
357
- maxValue: maxValue,
358
- totalRange: maxValue - minValue,
359
- increment: increment,
360
- };
361
- }
362
- normalize(value, range) {
363
- if (range.totalRange === 0) {
364
- // Degenerate axis (every value is zero): center the point so it
365
- // stays visible instead of dividing by zero.
366
- return PERCENT / 2;
427
+ const location = locateItem(this.drawing, getItemIndex(this.drawing, event));
428
+ if (location.seriesIndex === event.seriesIndex) {
429
+ return;
367
430
  }
368
- return ((value - range.minValue) / range.totalRange) * PERCENT;
431
+ this.chart.dispatchAction(Object.assign({ type: highlight ? 'highlight' : 'downplay' }, location));
369
432
  }
370
- getXValue(item) {
371
- return Array.isArray(item.value) ? item.value[0] : item.value;
372
- }
373
- getYValue(item) {
374
- return Array.isArray(item.value) ? item.value[1] : item.value;
375
- }
376
- getMinimumValue(item) {
377
- const value = item.value;
378
- return Array.isArray(value) ? Math.min(...value) : value;
379
- }
380
- getMaximumValue(item) {
381
- const value = item.value;
382
- return Array.isArray(value) ? Math.max(...value) : value;
383
- }
384
- getValueSpan(item) {
385
- const startValue = this.isRangeItem(item)
386
- ? this.getMinimumValue(item)
387
- : 0;
388
- return this.getMaximumValue(item) - startValue;
389
- }
390
- isRangeItem(item) {
391
- return Array.isArray(item.value);
392
- }
393
- handleChange() {
394
- this.range = null;
395
- this.secondaryAxisRange = null;
396
- this.recalculateRangeData();
397
- }
398
- recalculateRangeData() {
399
- if (this.type === 'scatter') {
400
- this.recalculateScatterRanges();
433
+ getClickableItem(index) {
434
+ const item = this.items[index];
435
+ if (!(item === null || item === void 0 ? void 0 : item.clickable)) {
401
436
  return;
402
437
  }
403
- this.range = this.calculateRange();
404
- }
405
- // Each axis derives its own range and step from its own zero-anchored span
406
- // (positive, negative, and zero-crossing data all grid sensibly). The single
407
- // `axisIncrement` prop can't describe two independent axes, so scatter
408
- // ignores it and auto-derives both, like it does `maxValue`.
409
- recalculateScatterRanges() {
410
- const xValues = this.items.map((item) => this.getXValue(item));
411
- const yValues = this.items.map((item) => this.getYValue(item));
412
- this.range = this.calculateAxisRange(yValues, this.calculateNiceStep(this.axisSpan(yValues)));
413
- this.secondaryAxisRange = this.calculateAxisRange(xValues, this.calculateNiceStep(this.axisSpan(xValues)));
414
- }
415
- getClickableItem(target) {
416
- const index = target.dataset.index;
417
- if (index === undefined) {
438
+ return item;
439
+ }
440
+ getRowIndex(event) {
441
+ return Number(event.currentTarget.dataset.index);
442
+ }
443
+ focusItem(index) {
444
+ if (index === NO_NAVIGATION_TARGET) {
418
445
  return;
419
446
  }
420
- const item = this.items[Number(index)];
421
- if (!item.clickable) {
447
+ const rows = this.host.shadowRoot.querySelectorAll('tbody tr');
448
+ rows[index].focus();
449
+ }
450
+ showItem(row, show) {
451
+ if (!this.chart || !this.drawing) {
422
452
  return;
423
453
  }
424
- return item;
454
+ const location = locateItem(this.drawing, Number(row.dataset.index));
455
+ this.chart.dispatchAction(Object.assign({ type: show ? 'highlight' : 'downplay' }, location));
456
+ this.chart.dispatchAction(Object.assign({ type: show ? 'showTip' : 'hideTip' }, location));
425
457
  }
426
458
  static get is() { return "limel-chart"; }
427
459
  static get encapsulation() { return "shadow"; }
@@ -629,9 +661,16 @@ export class Chart {
629
661
  "type": "string",
630
662
  "mutable": false,
631
663
  "complexType": {
632
- "original": "| 'area'\n | 'bar'\n | 'doughnut'\n | 'line'\n | 'nps'\n | 'pie'\n | 'ring'\n | 'dot'\n | 'scatter'\n | 'stacked-bar'",
664
+ "original": "ChartType",
633
665
  "resolved": "\"area\" | \"bar\" | \"dot\" | \"doughnut\" | \"line\" | \"nps\" | \"pie\" | \"ring\" | \"scatter\" | \"stacked-bar\"",
634
- "references": {}
666
+ "references": {
667
+ "ChartType": {
668
+ "location": "import",
669
+ "path": "./chart.types",
670
+ "id": "src/components/chart/chart.types.ts::ChartType",
671
+ "referenceLocation": "ChartType"
672
+ }
673
+ }
635
674
  },
636
675
  "required": false,
637
676
  "optional": true,
@@ -696,7 +735,7 @@ export class Chart {
696
735
  "optional": true,
697
736
  "docs": {
698
737
  "tags": [],
699
- "text": "Sets the axis increment for `bar`, `dot`, `area`, and `line` charts.\nHas no effect on other chart types."
738
+ "text": "Sets the axis increment for `bar`, `dot`, `area`, and `line` charts.\nWhen it is not set, or not above zero, the chart works out a step\nfrom the values. It also does that when the step would divide the\naxis into more than 100 parts, so that it does not draw too many lines.\nHas no effect on other chart types."
700
739
  },
701
740
  "getter": false,
702
741
  "setter": false,
@@ -725,6 +764,11 @@ export class Chart {
725
764
  }
726
765
  };
727
766
  }
767
+ static get states() {
768
+ return {
769
+ "focusedIndex": {}
770
+ };
771
+ }
728
772
  static get events() {
729
773
  return [{
730
774
  "method": "interact",
@@ -750,19 +794,20 @@ export class Chart {
750
794
  }
751
795
  }];
752
796
  }
797
+ static get elementRef() { return "host"; }
753
798
  static get watchers() {
754
799
  return [{
755
- "propName": "items",
756
- "methodName": "handleChange"
757
- }, {
758
800
  "propName": "axisIncrement",
759
- "methodName": "handleChange"
801
+ "methodName": "warnAboutAxisIncrement"
802
+ }, {
803
+ "propName": "items",
804
+ "methodName": "warnAboutAxisIncrement"
760
805
  }, {
761
806
  "propName": "maxValue",
762
- "methodName": "handleChange"
807
+ "methodName": "warnAboutAxisIncrement"
763
808
  }, {
764
809
  "propName": "type",
765
- "methodName": "handleChange"
810
+ "methodName": "warnAboutAxisIncrement"
766
811
  }];
767
812
  }
768
813
  }