@operato/chart 8.0.0-beta.0 → 8.0.0-beta.2

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 (40) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +6 -6
  3. package/.editorconfig +0 -29
  4. package/.storybook/main.js +0 -3
  5. package/.storybook/preview.js +0 -52
  6. package/.storybook/server.mjs +0 -8
  7. package/demo/index.html +0 -33
  8. package/src/chartjs/config-converter.ts +0 -341
  9. package/src/chartjs/ox-chart-js.ts +0 -207
  10. package/src/editors/configurer.ts +0 -336
  11. package/src/editors/index.ts +0 -8
  12. package/src/editors/input-chart-abstract.ts +0 -202
  13. package/src/editors/input-chart-styles.ts +0 -206
  14. package/src/editors/ox-input-chart-hbar.ts +0 -157
  15. package/src/editors/ox-input-chart-mixed.ts +0 -241
  16. package/src/editors/ox-input-chart-pie.ts +0 -69
  17. package/src/editors/ox-input-chart-radar.ts +0 -56
  18. package/src/editors/ox-input-chart-timeseries.ts +0 -279
  19. package/src/editors/ox-property-editor-chart.ts +0 -72
  20. package/src/editors/templates/annotations.ts +0 -295
  21. package/src/editors/templates/display-value.ts +0 -111
  22. package/src/editors/templates/series.ts +0 -316
  23. package/src/global.d.ts +0 -1
  24. package/src/index.ts +0 -0
  25. package/src/progress/ox-progress-circle.ts +0 -133
  26. package/src/scichart/ox-scichart.ts +0 -151
  27. package/src/scichart/scichart-builder.ts +0 -508
  28. package/src/types.d.ts +0 -124
  29. package/stories/common.ts +0 -87
  30. package/stories/ox-input-chart-bar.stories.ts +0 -188
  31. package/stories/ox-input-chart-doughnut.stories.ts +0 -130
  32. package/stories/ox-input-chart-hbar.stories.ts +0 -188
  33. package/stories/ox-input-chart-line.stories.ts +0 -198
  34. package/stories/ox-input-chart-pie.stories.ts +0 -130
  35. package/stories/ox-input-chart-polar-area.stories.ts +0 -130
  36. package/stories/ox-input-chart-radar.stories.ts +0 -141
  37. package/stories/ox-input-chart-timeseries.stories.ts +0 -268
  38. package/tsconfig.json +0 -25
  39. package/web-dev-server.config.mjs +0 -27
  40. package/web-test-runner.config.mjs +0 -41
@@ -1,316 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
-
3
- import { LitElement, html, PropertyValues, nothing } from 'lit'
4
- import { customElement, property, query } from 'lit/decorators.js'
5
- import { keyed } from 'lit/directives/keyed.js'
6
- import { MdIcon } from '@material/web/icon/icon.js'
7
- import { random as randomColor, TinyColor } from '@ctrl/tinycolor'
8
-
9
- import { Configurer } from '../configurer'
10
- import './display-value'
11
-
12
- @customElement('ox-chart-series')
13
- export class MultipleSeriesTemplate extends LitElement {
14
- createRenderRoot() {
15
- return this
16
- }
17
-
18
- @property({ type: Object }) configurer!: Configurer
19
- @property({ type: String }) chartType?: OperatoChart.ChartType
20
-
21
- @query('#series-tabs') seriesTabs!: HTMLElement
22
- @query('#series-tab-nav-left-button') seriesTabNavLeftButton!: MdIcon
23
- @query('#series-tab-nav-right-button') seriesTabNavRightButton!: MdIcon
24
-
25
- protected updated(_changedProperties: PropertyValues): void {
26
- if (_changedProperties.has('configurer') || _changedProperties.has('chartType')) {
27
- this.requestUpdate()
28
- }
29
- }
30
-
31
- get value() {
32
- return this.configurer.datasets
33
- }
34
-
35
- render() {
36
- return keyed(
37
- this.configurer.currentSeriesIndex,
38
- html`
39
- <div id="series-properties-container" fullwidth>
40
- <div id="series-tab-header" @wheel=${this._onWheelScroll}>
41
- <md-icon id="series-tab-nav-left-button" @click=${this._scrollLeft}>chevron_left</md-icon>
42
- <div id="series-tabs" active-tab-index=${this.configurer.currentSeriesIndex} fit-container>
43
- ${this._renderTabs()}
44
- </div>
45
- <md-icon id="series-tab-nav-right-button" @click=${this._scrollRight}>chevron_right</md-icon>
46
- </div>
47
- <div id="add-series-button-container">
48
- <md-icon id="add-series-button" @click=${this._addSeries}>add</md-icon>
49
- </div>
50
- ${this._renderSeriesForm()}
51
- </div>
52
- `
53
- )
54
- }
55
-
56
- private _renderTabs() {
57
- return this.configurer.datasets.map(
58
- (dataset: OperatoChart.Dataset, index: number) => html`
59
- <div
60
- data-series=${index + 1}
61
- data-tab-index=${index}
62
- tab
63
- ?selected=${index === this.configurer.currentSeriesIndex}
64
- @click=${() => this._selectTab(index)}
65
- >
66
- ${index + 1}
67
- ${this.configurer.datasets.length > 1 && this.configurer.currentSeriesIndex === index
68
- ? html`<md-icon @click=${() => this._removeSeries(index)}>close</md-icon>`
69
- : html``}
70
- </div>
71
- `
72
- )
73
- }
74
-
75
- private _renderSeriesForm() {
76
- const configurer = this.configurer
77
- const chartType = this.chartType
78
-
79
- return html`
80
- <div class="tab-content">
81
- <label for="data-key"> <ox-i18n msgid="label.data-key">Data Key</ox-i18n> </label>
82
- <input id="data-key" type="text" value-key="dataKey" .value=${configurer.dataKey || ''} />
83
-
84
- ${chartType == 'horizontalBar' ||
85
- chartType === 'doughnut' ||
86
- chartType === 'pie' ||
87
- chartType == 'radar' ||
88
- chartType == 'polarArea'
89
- ? nothing
90
- : html`
91
- <label for="series-type"> <ox-i18n msgid="label.series-type">Type</ox-i18n> </label>
92
- <select
93
- id="series-type"
94
- class="select-content"
95
- value-key="series.type"
96
- .value=${configurer.series.type || ''}
97
- >
98
- <option value="bar" selected>Bar</option>
99
- <option value="line">Line</option>
100
- </select>
101
- `}
102
-
103
- <label for="series-label"> <ox-i18n msgid="label.label">Label</ox-i18n> </label>
104
- <input id="series-label" type="text" value-key="series.label" .value=${configurer.series.label || ''} />
105
-
106
- ${configurer.series.type === 'line'
107
- ? html`
108
- <label for="series-line-tension"> <ox-i18n msgid="label.line-tension">Line Tension</ox-i18n> </label>
109
- <select
110
- id="series-line-tension"
111
- class="select-content"
112
- value-key="series.lineTension"
113
- .value=${String(configurer.series.lineTension || 0)}
114
- >
115
- <option value="0.4">Smooth</option>
116
- <option value="0">Angled</option>
117
- </select>
118
- `
119
- : html``}
120
- ${configurer.series.type === 'line'
121
- ? html`
122
- <label for="series-border-width"> <ox-i18n msgid="label.border-width">Border Width</ox-i18n> </label>
123
- <input
124
- id="series-border-width"
125
- type="number"
126
- value-key="series.borderWidth"
127
- .value=${String(configurer.series.borderWidth || 0)}
128
- />
129
- `
130
- : html``}
131
-
132
- <label for="series-color"> <ox-i18n msgid="label.color">Color</ox-i18n> </label>
133
- <ox-input-color id="series-color" value-key="color" .value=${configurer.color}></ox-input-color>
134
-
135
- ${configurer.series.type === 'line'
136
- ? html`
137
- <label for="series-point-style"> <ox-i18n msgid="label.point-shape">Point Shape</ox-i18n> </label>
138
- <select
139
- id="series-point-style"
140
- class="select-content"
141
- value-key="series.pointStyle"
142
- .value=${configurer.series.pointStyle || ''}
143
- >
144
- <option value="">&nbsp;</option>
145
- <option value="circle">⚬</option>
146
- <option value="triangle">▵</option>
147
- <option value="rect">□</option>
148
- <option value="rectRot">◇</option>
149
- <option value="cross">+</option>
150
- <option value="crossRot">⨉</option>
151
- <option value="star">✱</option>
152
- <option value="line">―</option>
153
- <option value="dash">┄</option>
154
- </select>
155
-
156
- <label for="series-point-radius"> <ox-i18n msgid="label.point-size">Point Size</ox-i18n> </label>
157
- <input
158
- id="series-point-radius"
159
- type="number"
160
- value-key="series.pointRadius"
161
- .value=${String(configurer.series.pointRadius || 0)}
162
- />
163
- `
164
- : html``}
165
-
166
- <label for="series-stack"> <ox-i18n msgid="label.stack-group">Stack group</ox-i18n> </label>
167
- <input id="series-stack" type="text" value-key="series.stack" .value=${configurer.series.stack || ''} />
168
-
169
- ${configurer.series.type === 'line'
170
- ? html`
171
- <input id="series-fill" type="checkbox" value-key="series.fill" ?checked=${configurer.series.fill} />
172
- <label for="series-fill"> <ox-i18n msgid="label.fill">Fill</ox-i18n> </label>
173
- `
174
- : html``}
175
- ${configurer.multiAxis && configurer.series.type !== 'horizontalBar'
176
- ? html`
177
- <label for="series-y-axis-id"> <ox-i18n msgid="label.target-axis">Target Axis</ox-i18n> </label>
178
- <select
179
- id="series-y-axis-id"
180
- class="select-content"
181
- value-key="series.yAxisID"
182
- .value=${configurer.series.yAxisID || ''}
183
- >
184
- <option value="left">Left</option>
185
- <option value="right">Right</option>
186
- </select>
187
- `
188
- : html``}
189
-
190
- <label></label>
191
- <ox-chart-display-value .configurer=${configurer} fullwidth></ox-chart-display-value>
192
- </div>
193
- `
194
- }
195
-
196
- _getSeriesModel({
197
- chartType,
198
- datasetsLength,
199
- lastSeriesColor
200
- }: {
201
- chartType: string
202
- datasetsLength: number
203
- lastSeriesColor: TinyColor
204
- }) {
205
- const addSeriesOption: any = {
206
- label: `series ${datasetsLength + 1}`,
207
- data: [],
208
- borderWidth: 1,
209
- dataKey: '',
210
- yAxisID: 'left',
211
- color: randomColor({
212
- hue: lastSeriesColor.toHsv().h
213
- }).toRgbString(),
214
- stack: ''
215
- }
216
-
217
- addSeriesOption.type = addSeriesOption.chartType = chartType
218
- return addSeriesOption
219
- }
220
-
221
- private _selectTab(index: number) {
222
- this.configurer.setCurrentSeriesIndex(index)
223
- this.requestUpdate()
224
- }
225
-
226
- private _removeSeries(index: number) {
227
- this.configurer.removeSeries(index)
228
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
229
-
230
- this.requestUpdate()
231
- }
232
-
233
- private _addSeries() {
234
- const configurer = this.configurer
235
-
236
- if (!configurer.config.data.datasets) {
237
- return
238
- }
239
-
240
- const lastSeriesIndex = configurer.config.data.datasets.length
241
- const chartType = configurer.series.type || configurer.config.type
242
- const color = configurer.datasets[lastSeriesIndex - 1]?.backgroundColor
243
- const lastSeriesColor = new TinyColor(Array.isArray(color) ? color[0] : color)
244
-
245
- const seriesModel = this._getSeriesModel({
246
- chartType: chartType!,
247
- datasetsLength: lastSeriesIndex,
248
- lastSeriesColor
249
- })
250
-
251
- this.configurer.addSeries(seriesModel)
252
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
253
-
254
- this.requestUpdate()
255
- }
256
-
257
- private _onWheelScroll(event: WheelEvent) {
258
- const tabContainer = this.seriesTabs
259
- if (tabContainer) {
260
- event.preventDefault()
261
-
262
- tabContainer.scrollLeft += event.deltaY
263
-
264
- this._onTabScroll()
265
- }
266
- }
267
-
268
- private _scrollLeft() {
269
- this._scrollTabContainer(-1)
270
- }
271
-
272
- private _scrollRight() {
273
- this._scrollTabContainer(1)
274
- }
275
-
276
- private _scrollTabContainer(direction: number) {
277
- const tabContainer = this.renderRoot!.querySelector<HTMLElement>('#series-tabs')
278
- if (tabContainer) {
279
- tabContainer.style.scrollBehavior = 'smooth'
280
- tabContainer.scrollLeft += direction * tabContainer.clientWidth
281
- }
282
-
283
- setTimeout(() => {
284
- tabContainer!.style.scrollBehavior = 'auto'
285
- this._onTabScroll()
286
- }, 300)
287
- }
288
-
289
- private _onTabScroll() {
290
- let tabContainer: HTMLElement | null | undefined
291
- let tabNavLeftButton: MdIcon
292
- let tabNavRightButton: MdIcon
293
-
294
- tabContainer = this.seriesTabs
295
- tabNavLeftButton = this.seriesTabNavLeftButton
296
- tabNavRightButton = this.seriesTabNavRightButton
297
-
298
- if (!tabContainer) {
299
- return
300
- }
301
-
302
- if (tabContainer.clientWidth == tabContainer.scrollWidth) {
303
- tabNavLeftButton.setAttribute('disabled', '')
304
- tabNavRightButton.setAttribute('disabled', '')
305
- } else if (tabContainer.scrollLeft <= 0) {
306
- tabNavLeftButton.setAttribute('disabled', '')
307
- tabNavRightButton.removeAttribute('disabled')
308
- } else if (tabContainer.scrollLeft + tabContainer.clientWidth >= tabContainer.scrollWidth) {
309
- tabNavLeftButton.removeAttribute('disabled')
310
- tabNavRightButton.setAttribute('disabled', '')
311
- } else {
312
- tabNavLeftButton.removeAttribute('disabled')
313
- tabNavRightButton.removeAttribute('disabled')
314
- }
315
- }
316
- }
package/src/global.d.ts DELETED
@@ -1 +0,0 @@
1
- declare const SciChart: any
package/src/index.ts DELETED
File without changes
@@ -1,133 +0,0 @@
1
- /**
2
- * @license Copyright © HatioLab Inc. All rights reserved.
3
- */
4
-
5
- import { PropertyValues, LitElement, css, html } from 'lit'
6
- import { customElement, property, query } from 'lit/decorators.js'
7
- import { ScrollbarStyles } from '@operato/styles'
8
-
9
- /**
10
- A lightweight progress-circle WebComponent
11
-
12
- Example:
13
- <ox-progress-circle
14
- .value=${70}
15
- titleText="전체"
16
- suffix="%"
17
- fontSize="29px"
18
- fontColor="#4E5055"
19
- borderStyle="none"
20
- innerCircleSize="28%"
21
- circleColor="#0595E5"
22
- shadow="#00000026 4px 4px 4px"
23
- background="#eaf5fd"
24
- ></ox-progress-circle>
25
- */
26
- @customElement('ox-progress-circle')
27
- export class OxProgressCircle extends LitElement {
28
- static styles = [
29
- ScrollbarStyles,
30
- css`
31
- :host {
32
- display: flex;
33
- }
34
-
35
- div[circle] {
36
- font-size: 29px;
37
- font-weight: bold;
38
- width: 100%;
39
- aspect-ratio: 1;
40
- display: flex;
41
- border-radius: 50%;
42
- border: 1px solid #353b48;
43
- position: relative;
44
- background: conic-gradient(yellowgreen 0deg, white 0deg);
45
- box-shadow: #00000026 5px 5px 5px;
46
- }
47
- div[inner-circle] {
48
- width: 90%;
49
- aspect-ratio: 1;
50
- border-radius: inherit;
51
- background-color: #353b48;
52
- margin: auto;
53
- display: flex;
54
- flex-direction: column;
55
- align-items: center;
56
- color: white;
57
- justify-content: center;
58
- box-shadow: inset #00000026 -2px 2px 8px;
59
- }
60
-
61
- div[inner-circle] span {
62
- display: flex;
63
- align-items: center;
64
- }
65
-
66
- span[progress-title] {
67
- font-size: 0.65em;
68
- margin-bottom: -5%;
69
- }
70
- `
71
- ]
72
-
73
- @property({ type: Number }) value: number = 0
74
- @property({ type: String }) suffix: string = ''
75
- @property({ type: String }) titleText: string = ''
76
- @property({ type: String }) fontSize: string = '10px'
77
- @property({ type: String }) fontColor: string = ''
78
- @property({ type: String }) borderStyle: string = ''
79
- @property({ type: String }) innerCircleSize: string = '10%'
80
- @property({ type: String }) shadow: string = ''
81
- @property({ type: String }) circleColor: string = 'yellowgreen'
82
- @property({ type: String }) background: string = ''
83
-
84
- @query('div[circle]') circle!: HTMLDivElement
85
- @query('div[inner-circle]') innerCircle!: HTMLDivElement
86
- @query('span[progress-title]') progressTitle?: HTMLSpanElement
87
-
88
- firstUpdated() {
89
- if (this.fontSize) {
90
- this.circle.style.fontSize = this.fontSize
91
- }
92
- if (this.fontColor) {
93
- this.innerCircle.style.color = this.fontColor
94
- }
95
- if (this.borderStyle) {
96
- this.circle.style.border = this.borderStyle
97
- }
98
- if (this.innerCircleSize) {
99
- this.innerCircle.style.width = `calc(100% - ${this.innerCircleSize})`
100
- }
101
- if (this.shadow) {
102
- this.circle.style.boxShadow = this.shadow
103
- }
104
- if (this.background) {
105
- this.innerCircle.style.background = this.background
106
- }
107
- if (this.progressTitle && this.circleColor) {
108
- this.progressTitle.style.color = this.circleColor
109
- }
110
- }
111
-
112
- updated(changes: PropertyValues<this>) {
113
- if (changes.has('value')) {
114
- this.updateCircleBackground()
115
- }
116
- }
117
-
118
- updateCircleBackground() {
119
- const position = this.value * 3.6 // 360 = 100%
120
- this.circle.style.background = `conic-gradient(${this.circleColor} ${position}deg, ${this.background} 0deg)`
121
- }
122
-
123
- render() {
124
- return html`
125
- <div circle>
126
- <div inner-circle>
127
- ${this.titleText ? html`<span progress-title>${this.titleText}</span>` : ''}
128
- <span>${this.value}${this.suffix}</span>
129
- </div>
130
- </div>
131
- `
132
- }
133
- }
@@ -1,151 +0,0 @@
1
- import { LitElement, html, css } from 'lit'
2
- import { property, query, customElement } from 'lit/decorators.js'
3
- import { buildSciChart } from './scichart-builder'
4
-
5
- declare global {
6
- interface Window {
7
- sciChartLoaded: boolean
8
- sciChartLoadingPromise: Promise<void>
9
- }
10
- }
11
-
12
- @customElement('ox-scichart')
13
- class OxSciChart extends LitElement {
14
- @property({ type: Object }) config: OperatoChart.ChartConfig | null = null
15
- @property({ type: Array }) data: { [attr: string]: any }[] = []
16
-
17
- private chart: any = null
18
- private dataSeries: any[] = []
19
-
20
- @query('div#container') container!: HTMLDivElement
21
-
22
- static styles = css`
23
- :host {
24
- display: block;
25
- width: 100%;
26
- height: 100%;
27
- }
28
-
29
- .chart-container {
30
- display: flex;
31
- width: 100%;
32
- height: 100%;
33
- }
34
-
35
- .chart-content {
36
- flex: 1;
37
- position: relative;
38
- }
39
- `
40
-
41
- firstUpdated() {
42
- this.loadSciChart()
43
- }
44
-
45
- async loadSciChart() {
46
- if (!window.sciChartLoaded) {
47
- if (!window.sciChartLoadingPromise) {
48
- window.sciChartLoadingPromise = new Promise<void>(resolve => {
49
- const script = document.createElement('script')
50
- script.src = 'https://cdn.jsdelivr.net/npm/scichart/index.min.js'
51
- script.crossOrigin = 'anonymous'
52
- script.onload = () => {
53
- window.sciChartLoaded = true
54
-
55
- SciChart.SciChartSurface.UseCommunityLicense()
56
-
57
- resolve()
58
- }
59
- document.head.appendChild(script)
60
- })
61
- }
62
-
63
- await window.sciChartLoadingPromise
64
- }
65
-
66
- this.initializeSciChart()
67
- }
68
-
69
- async initializeSciChart() {
70
- const { chart, dataSeries } = (await buildSciChart(this.config, this.container, {})) || {}
71
-
72
- this.chart = chart
73
- this.dataSeries = dataSeries!
74
-
75
- this.updateDataSeries()
76
- }
77
-
78
- async updated(changedProperties: Map<string | number | symbol, unknown>) {
79
- if (changedProperties.has('config') && this.config) {
80
- await this.initializeSciChart()
81
- }
82
-
83
- if (changedProperties.has('data')) {
84
- this.updateDataSeries()
85
- this.chart?.sciChartSurface.zoomExtents()
86
- }
87
- }
88
-
89
- async appendData(appendum: { [attr: string]: any }[]) {}
90
-
91
- updateDataSeries() {
92
- if (!this.dataSeries?.length) return
93
-
94
- this.dataSeries.forEach(ds => ds.clear())
95
- const newData = this.dataSet
96
-
97
- newData.forEach((data, index) => {
98
- const filteredData = data.filter(d => typeof d.yValue === 'number')
99
-
100
- if (filteredData.length > 0) {
101
- this.dataSeries[index].appendRange(
102
- filteredData.map(d => d.xValue),
103
- filteredData.map(d => d.yValue)
104
- )
105
- }
106
- })
107
-
108
- this.chart?.sciChartSurface.zoomExtents()
109
- this.chart?.sciChartSurface.invalidateElement()
110
- }
111
-
112
- get dataSet(): { xValue: number; yValue: number }[][] {
113
- const { config, data } = this
114
- const { datasets = [], labelDataKey: attrX } = config?.data || {}
115
-
116
- if (!(data instanceof Array) || !attrX) {
117
- return []
118
- }
119
-
120
- return datasets.map(dataset => {
121
- return data
122
- .map(item => {
123
- if (!item || typeof item !== 'object') {
124
- return
125
- }
126
-
127
- const xValue = new Date(item[attrX])
128
- if (isNaN(xValue.getTime())) {
129
- console.error('Invalid date:', item[attrX])
130
- return
131
- }
132
-
133
- return {
134
- xValue: xValue.getTime() / 1000,
135
- yValue: item[dataset.dataKey!]
136
- }
137
- })
138
- .filter(Boolean) as { xValue: number; yValue: number }[]
139
- })
140
- }
141
-
142
- render() {
143
- return html` <div id="container" class="chart-container"></div> `
144
- }
145
- }
146
-
147
- declare global {
148
- interface HTMLElementTagNameMap {
149
- 'ox-scichart': OxSciChart
150
- }
151
- }