From 9dc04574a59d97d61f390080183f1bc79f8200e4 Mon Sep 17 00:00:00 2001 From: Tomi Virkki Date: Fri, 24 Jan 2025 10:46:39 +0200 Subject: [PATCH] experiment: add LitElement based charts --- packages/charts/package.json | 1 + packages/charts/src/vaadin-chart-mixin.js | 26 ++++++-- .../charts/src/vaadin-chart-series-mixin.js | 25 ++++++-- .../charts/src/vaadin-lit-chart-series.d.ts | 11 ++++ .../charts/src/vaadin-lit-chart-series.js | 34 +++++++++++ packages/charts/src/vaadin-lit-chart.d.ts | 11 ++++ packages/charts/src/vaadin-lit-chart.js | 61 +++++++++++++++++++ packages/charts/test/chart-properties.test.js | 5 +- packages/charts/test/chart-series.test.js | 3 +- packages/charts/test/exporting.test.js | 2 +- .../charts/theme/lumo/vaadin-lit-chart.js | 2 + .../charts/theme/material/vaadin-lit-chart.js | 2 + packages/charts/vaadin-lit-chart-series.d.ts | 1 + packages/charts/vaadin-lit-chart-series.js | 1 + packages/charts/vaadin-lit-chart.d.ts | 1 + packages/charts/vaadin-lit-chart.js | 2 + scripts/generateLitTests.js | 2 +- 17 files changed, 175 insertions(+), 15 deletions(-) create mode 100644 packages/charts/src/vaadin-lit-chart-series.d.ts create mode 100644 packages/charts/src/vaadin-lit-chart-series.js create mode 100644 packages/charts/src/vaadin-lit-chart.d.ts create mode 100644 packages/charts/src/vaadin-lit-chart.js create mode 100644 packages/charts/theme/lumo/vaadin-lit-chart.js create mode 100644 packages/charts/theme/material/vaadin-lit-chart.js create mode 100644 packages/charts/vaadin-lit-chart-series.d.ts create mode 100644 packages/charts/vaadin-lit-chart-series.js create mode 100644 packages/charts/vaadin-lit-chart.d.ts create mode 100644 packages/charts/vaadin-lit-chart.js diff --git a/packages/charts/package.json b/packages/charts/package.json index a3310980dc2..06a1a7c5757 100644 --- a/packages/charts/package.json +++ b/packages/charts/package.json @@ -35,6 +35,7 @@ "polymer" ], "dependencies": { + "lit": "^3.0.0", "@open-wc/dedupe-mixin": "^1.3.0", "@polymer/polymer": "^3.0.0", "@vaadin/component-base": "24.7.0-alpha7", diff --git a/packages/charts/src/vaadin-chart-mixin.js b/packages/charts/src/vaadin-chart-mixin.js index 81e65b4445c..6d807dd82fe 100644 --- a/packages/charts/src/vaadin-chart-mixin.js +++ b/packages/charts/src/vaadin-chart-mixin.js @@ -101,7 +101,10 @@ export const ChartMixin = (superClass) => * For detailed documentation of available API check the [API site](http://api.highcharts.com/class-reference/classes.list) * @type {!Highcharts.Chart | undefined} */ - configuration: Object, + configuration: { + type: Object, + sync: true, + }, /** * If categories are present names are used instead of numbers for the category axis. @@ -112,6 +115,7 @@ export const ChartMixin = (superClass) => categories: { type: Object, reflectToAttribute: true, + sync: true, }, /** @@ -121,6 +125,7 @@ export const ChartMixin = (superClass) => categoryMax: { type: Number, reflectToAttribute: true, + sync: true, }, /** @@ -130,6 +135,7 @@ export const ChartMixin = (superClass) => categoryMin: { type: Number, reflectToAttribute: true, + sync: true, }, /** @@ -146,6 +152,7 @@ export const ChartMixin = (superClass) => categoryPosition: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -156,6 +163,7 @@ export const ChartMixin = (superClass) => noLegend: { type: Boolean, reflectToAttribute: true, + sync: true, }, /** @@ -169,6 +177,7 @@ export const ChartMixin = (superClass) => stacking: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -178,6 +187,7 @@ export const ChartMixin = (superClass) => timeline: { type: Boolean, reflectToAttribute: true, + sync: true, }, /** @@ -187,6 +197,7 @@ export const ChartMixin = (superClass) => title: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -195,6 +206,7 @@ export const ChartMixin = (superClass) => tooltip: { type: Boolean, reflectToAttribute: true, + sync: true, }, /** @@ -204,6 +216,7 @@ export const ChartMixin = (superClass) => type: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -213,6 +226,7 @@ export const ChartMixin = (superClass) => subtitle: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -226,6 +240,7 @@ export const ChartMixin = (superClass) => chart3d: { type: Boolean, reflectToAttribute: true, + sync: true, }, /** @@ -236,6 +251,7 @@ export const ChartMixin = (superClass) => emptyText: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -245,6 +261,7 @@ export const ChartMixin = (superClass) => additionalOptions: { type: Object, reflectToAttribute: true, + sync: true, }, /** @@ -254,6 +271,7 @@ export const ChartMixin = (superClass) => polar: { type: Boolean, reflectToAttribute: true, + sync: true, }, }; } @@ -273,7 +291,7 @@ export const ChartMixin = (superClass) => '__updateSubtitle(subtitle, configuration)', '__updateTitle(title, configuration)', '__updateType(type, configuration)', - '__updateAdditionalOptions(additionalOptions.*)', + '__updateAdditionalOptions(additionalOptions)', ]; } @@ -1445,8 +1463,8 @@ export const ChartMixin = (superClass) => /** @private */ __updateAdditionalOptions(options) { - if (this.configuration && options.base) { - this.updateConfiguration(options.base); + if (this.configuration && options) { + this.updateConfiguration(options); } } diff --git a/packages/charts/src/vaadin-chart-series-mixin.js b/packages/charts/src/vaadin-chart-series-mixin.js index 14db82553ee..b3ed9d76bf4 100644 --- a/packages/charts/src/vaadin-chart-series-mixin.js +++ b/packages/charts/src/vaadin-chart-series-mixin.js @@ -34,6 +34,7 @@ export const ChartSeriesMixin = (superClass) => values: { type: Array, value: () => [], + sync: true, }, /** @@ -46,6 +47,7 @@ export const ChartSeriesMixin = (superClass) => valueMin: { type: Number, reflectToAttribute: true, + sync: true, }, /** @@ -56,6 +58,7 @@ export const ChartSeriesMixin = (superClass) => valueMax: { type: Number, reflectToAttribute: true, + sync: true, }, /** @@ -66,6 +69,7 @@ export const ChartSeriesMixin = (superClass) => type: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -75,6 +79,7 @@ export const ChartSeriesMixin = (superClass) => title: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -88,6 +93,7 @@ export const ChartSeriesMixin = (superClass) => markers: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -98,6 +104,7 @@ export const ChartSeriesMixin = (superClass) => unit: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -109,6 +116,7 @@ export const ChartSeriesMixin = (superClass) => stack: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -121,6 +129,7 @@ export const ChartSeriesMixin = (superClass) => neckPosition: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -133,6 +142,7 @@ export const ChartSeriesMixin = (superClass) => neckWidth: { type: String, reflectToAttribute: true, + sync: true, }, /** @@ -142,6 +152,7 @@ export const ChartSeriesMixin = (superClass) => */ options: { type: Object, + sync: true, }, /** @@ -151,6 +162,7 @@ export const ChartSeriesMixin = (superClass) => additionalOptions: { type: Object, reflectToAttribute: true, + sync: true, }, /** @@ -159,13 +171,14 @@ export const ChartSeriesMixin = (superClass) => */ _series: { type: Object, + sync: true, }, }; } static get observers() { return [ - '__additionalOptionsObserver(additionalOptions.*, _series)', + '__additionalOptionsObserver(additionalOptions, _series)', '__markersObserver(markers, _series)', '__neckPositionObserver(neckPosition, _series)', '__neckWidthObserver(neckWidth, _series)', @@ -175,7 +188,7 @@ export const ChartSeriesMixin = (superClass) => '__unitObserver(unit, valueMin, valueMax, _series)', '__valueMinObserver(valueMin, _series)', '__valueMaxObserver(valueMax, _series)', - '__valuesObserver(values.splices, _series)', + '__valuesObserver(values, _series)', ]; } @@ -256,16 +269,16 @@ export const ChartSeriesMixin = (superClass) => } /** @private */ - __valuesObserver(_splices, series) { + __valuesObserver(values, series) { if (series) { - series.setData(this.values); + series.setData(values); } } /** @private */ __additionalOptionsObserver(additionalOptions, series) { - if (series && additionalOptions.base) { - series.update(additionalOptions.base); + if (series && additionalOptions) { + series.update(additionalOptions); } } diff --git a/packages/charts/src/vaadin-lit-chart-series.d.ts b/packages/charts/src/vaadin-lit-chart-series.d.ts new file mode 100644 index 00000000000..99656ddd776 --- /dev/null +++ b/packages/charts/src/vaadin-lit-chart-series.d.ts @@ -0,0 +1,11 @@ +/** + * @license + * Copyright (c) 2000 - 2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * + * See https://vaadin.com/commercial-license-and-service-terms for the full + * license. + */ +export * from './vaadin-chart-series.js'; diff --git a/packages/charts/src/vaadin-lit-chart-series.js b/packages/charts/src/vaadin-lit-chart-series.js new file mode 100644 index 00000000000..7967f768b10 --- /dev/null +++ b/packages/charts/src/vaadin-lit-chart-series.js @@ -0,0 +1,34 @@ +/** + * @license + * Copyright (c) 2000 - 2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * + * See https://vaadin.com/commercial-license-and-service-terms for the full + * license. + */ +import './vaadin-lit-chart.js'; +import { LitElement } from 'lit'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { ChartSeriesMixin } from './vaadin-chart-series-mixin.js'; + +/** + * LitElement based version of `` web component. + * + * ## Disclaimer + * + * This component is an experiment and not yet a part of Vaadin platform. + * There is no ETA regarding specific Vaadin version where it'll land. + * Feel free to try this code in your apps as per Apache 2.0 license. + */ +class ChartSeries extends ChartSeriesMixin(PolylitMixin(LitElement)) { + static get is() { + return 'vaadin-chart-series'; + } +} + +defineCustomElement(ChartSeries); + +export { ChartSeries }; diff --git a/packages/charts/src/vaadin-lit-chart.d.ts b/packages/charts/src/vaadin-lit-chart.d.ts new file mode 100644 index 00000000000..762e58290a2 --- /dev/null +++ b/packages/charts/src/vaadin-lit-chart.d.ts @@ -0,0 +1,11 @@ +/** + * @license + * Copyright (c) 2000 - 2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * + * See https://vaadin.com/commercial-license-and-service-terms for the full + * license. + */ +export * from './vaadin-chart.js'; diff --git a/packages/charts/src/vaadin-lit-chart.js b/packages/charts/src/vaadin-lit-chart.js new file mode 100644 index 00000000000..b865b4f0ba9 --- /dev/null +++ b/packages/charts/src/vaadin-lit-chart.js @@ -0,0 +1,61 @@ +/** + * @license + * Copyright (c) 2000 - 2025 Vaadin Ltd. + * + * This program is available under Vaadin Commercial License and Service Terms. + * + * + * See https://vaadin.com/commercial-license-and-service-terms for the full + * license. + */ +import './vaadin-lit-chart-series.js'; +import { css, html, LitElement } from 'lit'; +import { defineCustomElement } from '@vaadin/component-base/src/define.js'; +import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js'; +import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js'; +import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js'; +import { ChartMixin } from './vaadin-chart-mixin.js'; + +/** + * LitElement based version of `` web component. + * + * ## Disclaimer + * + * This component is an experiment and not yet a part of Vaadin platform. + * There is no ETA regarding specific Vaadin version where it'll land. + */ +class Chart extends ChartMixin(ThemableMixin(ElementMixin(PolylitMixin(LitElement)))) { + static get styles() { + return css` + :host { + display: block; + width: 100%; + overflow: hidden; + } + + :host([hidden]) { + display: none !important; + } + `; + } + + /** @protected */ + render() { + return html` +
+ + `; + } + + static get is() { + return 'vaadin-chart'; + } + + static get cvdlName() { + return 'vaadin-chart'; + } +} + +defineCustomElement(Chart); + +export { Chart }; diff --git a/packages/charts/test/chart-properties.test.js b/packages/charts/test/chart-properties.test.js index 4d38136b416..e09f1ce1e0d 100644 --- a/packages/charts/test/chart-properties.test.js +++ b/packages/charts/test/chart-properties.test.js @@ -134,7 +134,8 @@ describe('vaadin-chart properties', () => { }); it('should react to additionalOptions sub property change', async () => { - chart.set('additionalOptions.title.text', 'Reindeer statistics'); + chart.additionalOptions.title.text = 'Reindeer statistics'; + chart.additionalOptions = { ...chart.additionalOptions }; await oneEvent(chart, 'chart-redraw'); expect(chartContainer.querySelector('.highcharts-title').textContent).to.be.equal('Reindeer statistics'); }); @@ -239,7 +240,7 @@ describe('vaadin-chart properties', () => { }); it('should have tooltips when tooltip is set using additionalOptions', async () => { - chart.set('additionalOptions', { tooltip: { enabled: true, pointFormat: 'custom' } }); + chart.additionalOptions = { tooltip: { enabled: true, pointFormat: 'custom' } }; await aTimeout(50); expect(chart.configuration.tooltip.options.enabled).to.be.true; }); diff --git a/packages/charts/test/chart-series.test.js b/packages/charts/test/chart-series.test.js index eb7ea01c25a..aa9d490655c 100644 --- a/packages/charts/test/chart-series.test.js +++ b/packages/charts/test/chart-series.test.js @@ -256,7 +256,8 @@ describe('vaadin-chart-series', () => { }); it('should react to additionalOptions sub property change', () => { - series.set('additionalOptions.type', 'line'); + series.additionalOptions.type = 'line'; + series.additionalOptions = { ...series.additionalOptions }; expect(chart.configuration.series[0].type).to.be.equal('line'); }); }); diff --git a/packages/charts/test/exporting.test.js b/packages/charts/test/exporting.test.js index b38ea121b39..7f0f308f505 100644 --- a/packages/charts/test/exporting.test.js +++ b/packages/charts/test/exporting.test.js @@ -64,7 +64,7 @@ describe('vaadin-chart exporting', () => { beforeEach(async () => { wrapper = fixtureSync(''); chart = wrapper.$.chart; - chart.set('additionalOptions', { exporting: { enabled: true } }); + chart.additionalOptions = { exporting: { enabled: true } }; await oneEvent(chart, 'chart-add-series'); chartContainer = chart.$.chart; }); diff --git a/packages/charts/theme/lumo/vaadin-lit-chart.js b/packages/charts/theme/lumo/vaadin-lit-chart.js new file mode 100644 index 00000000000..30b439e42f9 --- /dev/null +++ b/packages/charts/theme/lumo/vaadin-lit-chart.js @@ -0,0 +1,2 @@ +import './vaadin-chart-styles.js'; +import '../../src/vaadin-lit-chart.js'; diff --git a/packages/charts/theme/material/vaadin-lit-chart.js b/packages/charts/theme/material/vaadin-lit-chart.js new file mode 100644 index 00000000000..30b439e42f9 --- /dev/null +++ b/packages/charts/theme/material/vaadin-lit-chart.js @@ -0,0 +1,2 @@ +import './vaadin-chart-styles.js'; +import '../../src/vaadin-lit-chart.js'; diff --git a/packages/charts/vaadin-lit-chart-series.d.ts b/packages/charts/vaadin-lit-chart-series.d.ts new file mode 100644 index 00000000000..e81a7b0d5cb --- /dev/null +++ b/packages/charts/vaadin-lit-chart-series.d.ts @@ -0,0 +1 @@ +export * from './vaadin-chart-series.js'; diff --git a/packages/charts/vaadin-lit-chart-series.js b/packages/charts/vaadin-lit-chart-series.js new file mode 100644 index 00000000000..9cdaf6a28e1 --- /dev/null +++ b/packages/charts/vaadin-lit-chart-series.js @@ -0,0 +1 @@ +export * from './src/vaadin-lit-chart-series.js'; diff --git a/packages/charts/vaadin-lit-chart.d.ts b/packages/charts/vaadin-lit-chart.d.ts new file mode 100644 index 00000000000..ba1ab331de7 --- /dev/null +++ b/packages/charts/vaadin-lit-chart.d.ts @@ -0,0 +1 @@ +export * from './vaadin-chart.js'; diff --git a/packages/charts/vaadin-lit-chart.js b/packages/charts/vaadin-lit-chart.js new file mode 100644 index 00000000000..9027325782b --- /dev/null +++ b/packages/charts/vaadin-lit-chart.js @@ -0,0 +1,2 @@ +import './theme/lumo/vaadin-lit-chart.js'; +export * from './src/vaadin-lit-chart.js'; diff --git a/scripts/generateLitTests.js b/scripts/generateLitTests.js index 4b4e0daed52..24f2ad4c409 100644 --- a/scripts/generateLitTests.js +++ b/scripts/generateLitTests.js @@ -5,7 +5,7 @@ const packages = fs.readdirSync('packages'); packages .filter((pkg) => { - return fs.existsSync(`packages/${pkg}/vaadin-lit-${pkg}.js`); + return glob.sync(`packages/${pkg}/vaadin-lit-*`).length > 0; }) .flatMap((pkg) => { return glob.sync(`packages/${pkg}/test/*.test.{js,ts}`);