@operato/chart 7.0.12 → 7.0.13

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 (42) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/src/editors/configurer.d.ts +10 -1
  3. package/dist/src/editors/configurer.js +62 -2
  4. package/dist/src/editors/configurer.js.map +1 -1
  5. package/dist/src/editors/input-chart-abstract.d.ts +18 -0
  6. package/dist/src/editors/input-chart-abstract.js +438 -1
  7. package/dist/src/editors/input-chart-abstract.js.map +1 -1
  8. package/dist/src/editors/input-chart-styles.js +18 -9
  9. package/dist/src/editors/input-chart-styles.js.map +1 -1
  10. package/dist/src/editors/ox-input-chart-hbar.d.ts +2 -2
  11. package/dist/src/editors/ox-input-chart-hbar.js +10 -10
  12. package/dist/src/editors/ox-input-chart-hbar.js.map +1 -1
  13. package/dist/src/editors/ox-input-chart-mixed.d.ts +2 -2
  14. package/dist/src/editors/ox-input-chart-mixed.js +3 -3
  15. package/dist/src/editors/ox-input-chart-mixed.js.map +1 -1
  16. package/dist/src/editors/ox-input-chart-radar.d.ts +2 -2
  17. package/dist/src/editors/ox-input-chart-radar.js +3 -3
  18. package/dist/src/editors/ox-input-chart-radar.js.map +1 -1
  19. package/dist/src/editors/ox-input-chart-timeseries.d.ts +2 -2
  20. package/dist/src/editors/ox-input-chart-timeseries.js +6 -4
  21. package/dist/src/editors/ox-input-chart-timeseries.js.map +1 -1
  22. package/dist/src/scichart/scichart-builder.js +65 -5
  23. package/dist/src/scichart/scichart-builder.js.map +1 -1
  24. package/dist/stories/ox-input-chart-timeseries.stories.js +0 -4
  25. package/dist/stories/ox-input-chart-timeseries.stories.js.map +1 -1
  26. package/dist/tsconfig.tsbuildinfo +1 -1
  27. package/package.json +2 -2
  28. package/src/editors/configurer.ts +73 -2
  29. package/src/editors/input-chart-abstract.ts +459 -2
  30. package/src/editors/input-chart-styles.ts +18 -9
  31. package/src/editors/ox-input-chart-hbar.ts +10 -10
  32. package/src/editors/ox-input-chart-mixed.ts +3 -3
  33. package/src/editors/ox-input-chart-radar.ts +3 -3
  34. package/src/editors/ox-input-chart-timeseries.ts +6 -4
  35. package/src/scichart/scichart-builder.ts +74 -4
  36. package/src/types.d.ts +19 -0
  37. package/stories/ox-input-chart-timeseries.stories.ts +0 -4
  38. package/translations/ko.json +7 -0
  39. package/dist/src/editors/input-chart-multi-series-abstract.d.ts +0 -17
  40. package/dist/src/editors/input-chart-multi-series-abstract.js +0 -419
  41. package/dist/src/editors/input-chart-multi-series-abstract.js.map +0 -1
  42. package/src/editors/input-chart-multi-series-abstract.ts +0 -430
@@ -1,6 +1,9 @@
1
+ import { ChartConfiguration } from 'chart.js'
2
+
1
3
  export class Configurer {
2
4
  public value: OperatoChart.ChartConfig
3
5
  public currentSeriesIndex: number = 0
6
+ public currentAnnotationIndex: number = 0
4
7
  public initializer: () => OperatoChart.ChartConfig
5
8
 
6
9
  constructor(value: OperatoChart.ChartConfig | null, initializer: () => OperatoChart.ChartConfig) {
@@ -13,6 +16,11 @@ export class Configurer {
13
16
  this.series = this.datasets[this.currentSeriesIndex]!
14
17
  }
15
18
 
19
+ setCurrentAnnotationIndex(currentAnnotationIndex: number) {
20
+ this.currentAnnotationIndex = currentAnnotationIndex
21
+ this.series = this.datasets[this.currentAnnotationIndex]!
22
+ }
23
+
16
24
  get series() {
17
25
  return this.datasets[this.currentSeriesIndex]! || {}
18
26
  }
@@ -25,6 +33,18 @@ export class Configurer {
25
33
  }
26
34
  }
27
35
 
36
+ get annotation() {
37
+ return this.annotations[this.currentAnnotationIndex]! || {}
38
+ }
39
+
40
+ set annotation(annotation) {
41
+ if (!this.annotations) {
42
+ this.annotations = [annotation]
43
+ } else {
44
+ this.annotations[this.currentAnnotationIndex] = annotation
45
+ }
46
+ }
47
+
28
48
  get config() {
29
49
  if (!this.value) {
30
50
  this.value = this.initializer.call(this)
@@ -48,7 +68,7 @@ export class Configurer {
48
68
  }
49
69
 
50
70
  set datasets(datasets) {
51
- this.datasets = datasets
71
+ this.data.datasets = datasets
52
72
  }
53
73
 
54
74
  set dataKey(key) {
@@ -205,6 +225,9 @@ export class Configurer {
205
225
  }
206
226
 
207
227
  set yAxes1(yAxes1) {
228
+ if (!this.scales!.yAxes![1]) {
229
+ this.scales!.yAxes![1] = {}
230
+ }
208
231
  this.scales!.yAxes![1] = yAxes1
209
232
  }
210
233
 
@@ -213,6 +236,12 @@ export class Configurer {
213
236
  }
214
237
 
215
238
  set multiAxis(multiAxis) {
239
+ if (!multiAxis) {
240
+ this.scales!.yAxes = [this.yAxes0]
241
+ } else if (!this.yAxes1) {
242
+ this.yAxes1 = {}
243
+ }
244
+
216
245
  this.config.options!.multiAxis = multiAxis
217
246
  }
218
247
 
@@ -232,7 +261,7 @@ export class Configurer {
232
261
  this.series.valueSuffix = valueSuffix
233
262
  }
234
263
 
235
- get valueForamt() {
264
+ get valueFormat() {
236
265
  return this.series.valueFormat
237
266
  }
238
267
 
@@ -247,4 +276,46 @@ export class Configurer {
247
276
  set displayValue(displayValue) {
248
277
  this.series.displayValue = displayValue
249
278
  }
279
+
280
+ get annotations(): OperatoChart.Annotation[] {
281
+ if (!this.config.options) {
282
+ this.config.options = {}
283
+ }
284
+ if (!this.config.options.annotations) {
285
+ this.config.options.annotations = []
286
+ }
287
+
288
+ return this.config.options.annotations!
289
+ }
290
+
291
+ set annotations(annotations) {
292
+ if (!this.config.options) {
293
+ this.config.options = {}
294
+ }
295
+ if (!this.config.options.annotations) {
296
+ this.config.options.annotations = []
297
+ }
298
+ this.config.options.annotations = annotations
299
+ }
300
+
301
+ get currentAnnotation() {
302
+ return this.annotations[this.currentAnnotationIndex]
303
+ }
304
+
305
+ addAnnotation(annotation: OperatoChart.Annotation) {
306
+ if (!this.config.options) {
307
+ this.config.options = {}
308
+ }
309
+ if (!this.config.options.annotations) {
310
+ this.config.options.annotations = []
311
+ }
312
+
313
+ this.config.options.annotations!.push(annotation)
314
+ }
315
+
316
+ removeAnnotation(index: number) {
317
+ if (this.config.options && this.config.options.annotations) {
318
+ this.config.options.annotations.splice(index, 1)
319
+ }
320
+ }
250
321
  }
@@ -1,8 +1,9 @@
1
1
  import '@operato/i18n/ox-i18n.js'
2
2
 
3
- import { html } from 'lit'
4
- import { property } from 'lit/decorators.js'
3
+ import { html, PropertyValues } from 'lit'
4
+ import { property, query } from 'lit/decorators.js'
5
5
  import { random as randomColor, TinyColor } from '@ctrl/tinycolor'
6
+ import { MdIcon } from '@material/web/icon/icon.js'
6
7
 
7
8
  import { InputChartStyles } from './input-chart-styles'
8
9
  import { Configurer } from './configurer'
@@ -14,6 +15,14 @@ export class InputChartAbstract extends OxFormField {
14
15
  @property({ type: Object }) value: OperatoChart.ChartConfig | null = null
15
16
  @property({ type: String, attribute: 'chart-type' }) chartType: OperatoChart.ChartType
16
17
 
18
+ @query('#annotations-tabs') annotationsTabs!: HTMLElement
19
+ @query('#annotations-tab-nav-left-button') annotationsTabNavLeftButton!: MdIcon
20
+ @query('#annotations-tab-nav-right-button') annotationsTabNavRightButton!: MdIcon
21
+
22
+ @query('#series-tabs') seriesTabs!: HTMLElement
23
+ @query('#series-tab-nav-left-button') seriesTabNavLeftButton!: MdIcon
24
+ @query('#series-tab-nav-right-button') seriesTabNavRightButton!: MdIcon
25
+
17
26
  private _configurer?: Configurer
18
27
 
19
28
  get configurer() {
@@ -71,6 +80,24 @@ export class InputChartAbstract extends OxFormField {
71
80
  this.renderRoot.addEventListener('change', this.onValuesChanged.bind(this))
72
81
  }
73
82
 
83
+ protected firstUpdated(_changedProperties: PropertyValues): void {
84
+ this.seriesTabContainer?.addEventListener('scroll', e => {
85
+ this._onTabScroll(e, 'series')
86
+ })
87
+
88
+ this.annotationsTabContainer?.addEventListener('scroll', e => {
89
+ this._onTabScroll(e, 'annotations')
90
+ })
91
+ }
92
+
93
+ get seriesTabContainer(): HTMLElement | null | undefined {
94
+ return this.seriesTabs
95
+ }
96
+
97
+ get annotationsTabContainer(): HTMLElement | null | undefined {
98
+ return this.annotationsTabs
99
+ }
100
+
74
101
  displayValueTemplate() {
75
102
  const configurer = this.configurer
76
103
 
@@ -290,6 +317,33 @@ export class InputChartAbstract extends OxFormField {
290
317
  this.requestUpdate()
291
318
  }
292
319
 
320
+ onTapAddAnnotation(e: Event) {
321
+ const configurer = this.configurer
322
+
323
+ const lastAnnotationIndex = configurer.annotations.length
324
+ configurer.annotations.push({ type: 'line', x1: 0, y1: 0 })
325
+
326
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
327
+ configurer.currentAnnotationIndex = lastAnnotationIndex
328
+
329
+ this.value = { ...this.configurer.value }
330
+ }
331
+
332
+ onTapRemoveCurrentAnnotation(index: number) {
333
+ const configurer = this.configurer
334
+
335
+ if (!configurer.config.data.datasets) {
336
+ return
337
+ }
338
+
339
+ this.configurer.data.datasets.splice(index, 1)
340
+
341
+ this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true }))
342
+ configurer.currentSeriesIndex = Math.max(0, configurer.currentSeriesIndex - 1)
343
+
344
+ this.requestUpdate()
345
+ }
346
+
293
347
  _getSeriesModel({
294
348
  chartType,
295
349
  datasetsLength,
@@ -330,4 +384,407 @@ export class InputChartAbstract extends OxFormField {
330
384
  return (element as any).value
331
385
  }
332
386
  }
387
+
388
+ annotationsTabTemplate() {
389
+ const configurer = this.configurer
390
+ const currentAnnotation = configurer.annotations[configurer.currentAnnotationIndex] || {}
391
+
392
+ return html`
393
+ <div id="annotations-properties-container" fullwidth>
394
+ <div id="annotations-tab-header">
395
+ <md-icon
396
+ id="annotations-tab-nav-left-button"
397
+ @tap=${(e: Event) => {
398
+ this._onTabScrollNavLeft(e, 'annotations')
399
+ }}
400
+ disabled
401
+ >chevron_left</md-icon
402
+ >
403
+ <div
404
+ id="annotations-tabs"
405
+ @change=${(e: Event) => {
406
+ configurer.currentAnnotationIndex = (e.target as any).activeTabIndex
407
+ }}
408
+ active-tab-index=${configurer.currentAnnotationIndex}
409
+ fit-container
410
+ >
411
+ ${configurer.annotations!.map(
412
+ (annotation: any, index: number) => html`
413
+ <div
414
+ data-annotation=${index + 1}
415
+ data-tab-index=${index}
416
+ tab
417
+ ?selected=${index == configurer.currentAnnotationIndex}
418
+ @click=${(e: Event) => {
419
+ const target = e.target as HTMLDivElement
420
+ this.configurer.setCurrentAnnotationIndex(Number(target.getAttribute('data-tab-index')))
421
+ this.value = { ...this.configurer.value }
422
+ }}
423
+ >
424
+ ${index + 1}
425
+ ${!configurer.annotations ||
426
+ (configurer.annotations.length != 1 && configurer.currentAnnotationIndex == index)
427
+ ? html` <md-icon @tap=${(e: Event) => this.onTapRemoveCurrentAnnotation(index)}> close </md-icon> `
428
+ : html``}
429
+ </div>
430
+ `
431
+ )}
432
+ </div>
433
+ <md-icon
434
+ id="annotations-tab-nav-right-button"
435
+ @click=${(e: Event) => {
436
+ this._onTabScrollNavRight(e, 'annotations')
437
+ }}
438
+ disabled
439
+ >chevron_right</md-icon
440
+ >
441
+ </div>
442
+ <div id="add-annotation-button-container">
443
+ <md-icon id="add-annotation-button" @tap=${(e: Event) => this.onTapAddAnnotation(e)}>add</md-icon>
444
+ </div>
445
+
446
+ <div class="tab-content">
447
+ <label for="annotation-type"> <ox-i18n msgid="label.chart-annotation-type">Type</ox-i18n> </label>
448
+ <select
449
+ id="annotation-type"
450
+ class="select-content"
451
+ value-key="annotation.type"
452
+ .value=${currentAnnotation.type || ''}
453
+ >
454
+ <option value="line">Line</option>
455
+ <option value="text">Text</option>
456
+ <option value="box">Box</option>
457
+ <option value="horizontalLine">Horizontal Line</option>
458
+ <option value="verticalLine">Vertical Line</option>
459
+ <option value="custom">Custom</option>
460
+ </select>
461
+
462
+ <label for="annotation-x1">X1</label>
463
+ <input
464
+ id="annotation-x1"
465
+ type="number"
466
+ value-key="annotation.x1"
467
+ .value=${String(currentAnnotation.x1 || 0)}
468
+ />
469
+
470
+ <label for="annotation-y1">Y1</label>
471
+ <input
472
+ id="annotation-y1"
473
+ type="number"
474
+ value-key="annotation.y1"
475
+ .value=${String(currentAnnotation.y1 || 0)}
476
+ />
477
+
478
+ <label for="annotation-x2">X2</label>
479
+ <input
480
+ id="annotation-x2"
481
+ type="number"
482
+ value-key="annotation.x2"
483
+ .value=${String(currentAnnotation.x2 || 0)}
484
+ />
485
+
486
+ <label for="annotation-y2">Y2</label>
487
+ <input
488
+ id="annotation-y2"
489
+ type="number"
490
+ value-key="annotation.y2"
491
+ .value=${String(currentAnnotation.y2 || 0)}
492
+ />
493
+
494
+ <label for="annotation-stroke"> <ox-i18n msgid="label.stroke-style">Stroke Style</ox-i18n> </label>
495
+ <ox-input-color
496
+ id="annotation-stroke"
497
+ value-key="annotation.stroke"
498
+ .value=${currentAnnotation.stroke}
499
+ ></ox-input-color>
500
+
501
+ <label for="annotation-stroke-thickness">
502
+ <ox-i18n msgid="label.stroke-thickness">Stroke Thickness</ox-i18n>
503
+ </label>
504
+ <input
505
+ id="annotation-stroke-thickness"
506
+ type="number"
507
+ value-key="annotation.strokeThickness"
508
+ .value=${String(currentAnnotation.strokeThickness || 1)}
509
+ />
510
+
511
+ <label for="annotation-fill"> <ox-i18n msgid="label.fill">Fill</ox-i18n> </label>
512
+ <ox-input-color
513
+ id="annotation-fill"
514
+ value-key="annotation.fill"
515
+ .value=${currentAnnotation.fill}
516
+ ></ox-input-color>
517
+
518
+ <label for="annotation-text"> <ox-i18n msgid="label.annotation-text">Text</ox-i18n> </label>
519
+ <input id="annotation-text" type="text" value-key="annotation.text" .value=${currentAnnotation.text || ''} />
520
+
521
+ <label for="annotation-horizontal-anchor">
522
+ <ox-i18n msgid="label.horizontal-anchor">Horizontal Anchor</ox-i18n>
523
+ </label>
524
+ <select
525
+ id="annotation-horizontal-anchor"
526
+ class="select-content"
527
+ value-key="annotation.horizontalAnchorPoint"
528
+ .value=${currentAnnotation.horizontalAnchorPoint || ''}
529
+ >
530
+ <option value="Left">Left</option>
531
+ <option value="Center">Center</option>
532
+ <option value="Right">Right</option>
533
+ </select>
534
+
535
+ <label for="annotation-vertical-anchor">
536
+ <ox-i18n msgid="label.vertical-anchor">Vertical Anchor</ox-i18n>
537
+ </label>
538
+ <select
539
+ id="annotation-vertical-anchor"
540
+ class="select-content"
541
+ value-key="annotation.verticalAnchorPoint"
542
+ .value=${currentAnnotation.verticalAnchorPoint || ''}
543
+ >
544
+ <option value="Top">Top</option>
545
+ <option value="Center">Center</option>
546
+ <option value="Bottom">Bottom</option>
547
+ </select>
548
+ </div>
549
+ </div>
550
+ `
551
+ }
552
+
553
+ multiSeriesTabTemplate() {
554
+ const configurer = this.configurer
555
+
556
+ return html`
557
+ <div id="series-properties-container" fullwidth>
558
+ <div id="series-tab-header">
559
+ <md-icon
560
+ id="series-tab-nav-left-button"
561
+ @tap=${(e: Event) => {
562
+ this._onTabScrollNavLeft(e, 'series')
563
+ }}
564
+ disabled
565
+ >chevron_left</md-icon
566
+ >
567
+ <div
568
+ id="series-tabs"
569
+ @change=${(e: Event) => {
570
+ configurer.currentSeriesIndex = (e.target as any).activeTabIndex
571
+ }}
572
+ active-tab-index=${configurer.currentSeriesIndex}
573
+ fit-container
574
+ >
575
+ ${configurer.datasets.map(
576
+ (dataset: any, index: number) => html`
577
+ <div
578
+ data-series=${index + 1}
579
+ data-tab-index=${index}
580
+ tab
581
+ ?selected=${index == configurer.currentSeriesIndex}
582
+ @click=${(e: Event) => {
583
+ const target = e.target as HTMLDivElement
584
+ this.configurer.setCurrentSeriesIndex(Number(target.getAttribute('data-tab-index')))
585
+ this.value = { ...this.configurer.value }
586
+ }}
587
+ >
588
+ ${index + 1}
589
+ ${!configurer.datasets || (configurer.datasets.length != 1 && configurer.currentSeriesIndex == index)
590
+ ? html` <md-icon @tap=${(e: Event) => this.onTapRemoveCurrentTab(index)}> close </md-icon> `
591
+ : html``}
592
+ </div>
593
+ `
594
+ )}
595
+ </div>
596
+ <md-icon
597
+ id="series-tab-nav-right-button"
598
+ @click=${(e: Event) => {
599
+ this._onTabScrollNavRight(e, 'series')
600
+ }}
601
+ disabled
602
+ >chevron_right</md-icon
603
+ >
604
+ </div>
605
+ <div id="add-series-button-container">
606
+ <md-icon id="add-series-button" @tap=${(e: Event) => this.onTapAddTab(e)}>add</md-icon>
607
+ </div>
608
+
609
+ <div class="tab-content">
610
+ <label for="data-key"> <ox-i18n msgid="label.data-key">Data Key</ox-i18n> </label>
611
+ <input id="data-key" type="text" value-key="dataKey" .value=${configurer.dataKey || ''} />
612
+
613
+ ${this.chartType == 'line' || this.chartType == 'bar'
614
+ ? html`
615
+ <label for="series-type"> <ox-i18n msgid="label.series-type">Type</ox-i18n> </label>
616
+ <select
617
+ id="series-type"
618
+ class="select-content"
619
+ value-key="series.type"
620
+ .value=${configurer.series.type || ''}
621
+ >
622
+ <option value="bar" selected>Bar</option>
623
+ <option value="line">Line</option>
624
+ </select>
625
+ `
626
+ : html``}
627
+
628
+ <label for="series-label"> <ox-i18n msgid="label.label">Label</ox-i18n> </label>
629
+ <input id="series-label" type="text" value-key="series.label" .value=${configurer.series.label || ''} />
630
+
631
+ ${configurer.series.type == 'line'
632
+ ? html`
633
+ <label for="series-line-tension"> <ox-i18n msgid="label.line-tension">Line Tension</ox-i18n> </label>
634
+ <select
635
+ id="series-line-tension"
636
+ class="select-content"
637
+ value-key="series.lineTension"
638
+ .value=${String(configurer.series.lineTension || 0)}
639
+ >
640
+ <option value="0.4">Smooth</option>
641
+ <option value="0">Angled</option>
642
+ </select>
643
+ `
644
+ : html``}
645
+ ${configurer.series.type == 'line'
646
+ ? html`
647
+ <label for="series-border-width"> <ox-i18n msgid="label.border-width">Border Width</ox-i18n> </label>
648
+ <input
649
+ id="series-border-width"
650
+ type="number"
651
+ value-key="series.borderWidth"
652
+ .value=${String(configurer.series.borderWidth || 0)}
653
+ />
654
+ `
655
+ : html``}
656
+
657
+ <label for="series-color"> <ox-i18n msgid="label.color">Color</ox-i18n> </label>
658
+ <ox-input-color id="series-color" value-key="color" .value=${configurer.color}></ox-input-color>
659
+
660
+ ${configurer.series.type == 'line'
661
+ ? html`
662
+ <label for="series-point-style"> <ox-i18n msgid="label.point-shape">Point Shape</ox-i18n> </label>
663
+ <select
664
+ id="series-point-style"
665
+ class="select-content"
666
+ value-key="series.pointStyle"
667
+ .value=${configurer.series.pointStyle || ''}
668
+ >
669
+ <option value="">&nbsp;</option>
670
+ <option value="circle">⚬</option>
671
+ <option value="triangle">▵</option>
672
+ <option value="rect">□</option>
673
+ <option value="rectRot">◇</option>
674
+ <option value="cross">+</option>
675
+ <option value="crossRot">⨉</option>
676
+ <option value="star">✱</option>
677
+ <option value="line">―</option>
678
+ <option value="dash">┄</option>
679
+ </select>
680
+
681
+ <label for="series-point-radius"> <ox-i18n msgid="label.point-size">Point Size</ox-i18n> </label>
682
+ <input
683
+ id="series-point-radius"
684
+ type="number"
685
+ value-key="series.pointRadius"
686
+ .value=${String(configurer.series.pointRadius || 0)}
687
+ />
688
+ `
689
+ : html``} <label for="series-stack"> <ox-i18n msgid="label.stack-group">Stack group</ox-i18n> </label>
690
+ <input id="series-stack" type="text" value-key="series.stack" .value=${configurer.series.stack || ''} />
691
+ ${configurer.series.type == 'line'
692
+ ? html`
693
+ <input id="seires-fill" type="checkbox" value-key="series.fill" ?checked=${configurer.series.fill} />
694
+ <label for="seires-fill"> <ox-i18n msgid="label.fill">Fill</ox-i18n> </label>
695
+ `
696
+ : html``}
697
+ ${configurer.multiAxis
698
+ ? html`
699
+ <label for="series-y-axis-id"> <ox-i18n msgid="label.target-axis">Target Axis</ox-i18n> </label>
700
+ <select
701
+ id="series-y-axis-id"
702
+ class="select-content"
703
+ value-key="series.yAxisID"
704
+ .value=${configurer.series.yAxisID || ''}
705
+ >
706
+ <option value="left">Left</option>
707
+ <option value="right">Right</option>
708
+ </select>
709
+ `
710
+ : html``}
711
+ ${this.displayValueTemplate()}
712
+ </div>
713
+ </div>
714
+ `
715
+ }
716
+
717
+ _onTabScroll(e: Event, type: 'series' | 'annotations') {
718
+ let tabContainer: HTMLElement | null | undefined
719
+ let tabNavLeftButton: MdIcon
720
+ let tabNavRightButton: MdIcon
721
+
722
+ if (type === 'series') {
723
+ tabContainer = this.seriesTabContainer
724
+ tabNavLeftButton = this.seriesTabNavLeftButton
725
+ tabNavRightButton = this.seriesTabNavRightButton
726
+ } else {
727
+ tabContainer = this.annotationsTabContainer
728
+ tabNavLeftButton = this.annotationsTabNavLeftButton
729
+ tabNavRightButton = this.annotationsTabNavRightButton
730
+ }
731
+
732
+ if (!tabContainer) {
733
+ return
734
+ }
735
+
736
+ if (tabContainer.clientWidth == tabContainer.scrollWidth) {
737
+ tabNavLeftButton.setAttribute('disabled', '')
738
+ tabNavRightButton.setAttribute('disabled', '')
739
+ }
740
+ // left-end
741
+ else if (tabContainer.scrollLeft == 0) {
742
+ tabNavLeftButton.setAttribute('disabled', '')
743
+ tabNavRightButton.removeAttribute('disabled')
744
+ }
745
+ // right-end
746
+ else if (tabContainer.scrollLeft + tabContainer.clientWidth >= tabContainer.scrollWidth) {
747
+ tabNavLeftButton.removeAttribute('disabled')
748
+ tabNavRightButton.setAttribute('disabled', '')
749
+ } else {
750
+ tabNavLeftButton.removeAttribute('disabled')
751
+ tabNavRightButton.removeAttribute('disabled')
752
+ }
753
+ }
754
+
755
+ _onTabScrollNavLeft(e: Event, type: 'series' | 'annotations') {
756
+ let tabContainer: HTMLElement | null | undefined
757
+
758
+ if (type === 'series') {
759
+ tabContainer = this.seriesTabContainer
760
+ } else {
761
+ tabContainer = this.annotationsTabContainer
762
+ }
763
+
764
+ if (!tabContainer) {
765
+ return
766
+ }
767
+
768
+ tabContainer.style.scrollBehavior = 'smooth'
769
+ tabContainer.scrollLeft -= tabContainer.clientWidth
770
+ tabContainer.style.scrollBehavior = 'auto'
771
+ }
772
+
773
+ _onTabScrollNavRight(e: Event, type: 'series' | 'annotations') {
774
+ let tabContainer: HTMLElement | null | undefined
775
+
776
+ if (type === 'series') {
777
+ tabContainer = this.seriesTabContainer
778
+ } else {
779
+ tabContainer = this.annotationsTabContainer
780
+ }
781
+
782
+ if (!tabContainer) {
783
+ return
784
+ }
785
+
786
+ tabContainer.style.scrollBehavior = 'smooth'
787
+ tabContainer.scrollLeft += tabContainer.clientWidth
788
+ tabContainer.style.scrollBehavior = 'auto'
789
+ }
333
790
  }
@@ -28,18 +28,21 @@ export const InputChartStyles = css`
28
28
  text-transform: capitalize;
29
29
  }
30
30
 
31
- #series-properties-container {
31
+ #series-properties-container,
32
+ #annotations-properties-container {
32
33
  display: grid;
33
34
  grid-template-columns: 1fr 25px;
34
35
  align-items: center;
35
36
  justify-content: center;
36
37
  }
37
38
 
38
- #series-properties-container > [tab-content] {
39
+ #series-properties-container > [tab-content],
40
+ #annotations-properties-container > [tab-content] {
39
41
  grid-column: span 2;
40
42
  }
41
43
 
42
- #tab-header {
44
+ #series-tab-header,
45
+ #annotations-tab-header {
43
46
  display: grid;
44
47
  grid-template-columns: 25px 1fr 25px;
45
48
  grid-gap: 5px;
@@ -53,20 +56,24 @@ export const InputChartStyles = css`
53
56
  align-items: center;
54
57
  }
55
58
 
56
- #tab-header > div {
59
+ #series-tab-header > div,
60
+ #annotations-tab-header > div {
57
61
  height: 25px;
58
62
  }
59
63
 
60
- #tab-header md-icon[disabled] {
64
+ #series-tab-header md-icon[disabled],
65
+ #annotations-tab-header md-icon[disabled] {
61
66
  opacity: 0.1;
62
67
  }
63
68
 
64
- #tabs {
69
+ #series-tabs,
70
+ #annotations-tabs {
65
71
  display: flex;
66
72
  overflow: hidden;
67
73
  }
68
74
 
69
- #tab-header #tabs [tab] md-icon {
75
+ #series-tab-header #series-tabs [tab] md-icon,
76
+ #annotations-tab-header #annotations-tabs [tab] md-icon {
70
77
  margin-left: auto;
71
78
  padding: 2px;
72
79
  color: var(--md-sys-color-on-surface);
@@ -74,7 +81,8 @@ export const InputChartStyles = css`
74
81
  --md-icon-size: 12px;
75
82
  }
76
83
 
77
- #add-series-button-container {
84
+ #add-series-button-container,
85
+ #add-annotation-button-container {
78
86
  height: 100%;
79
87
  box-sizing: border-box;
80
88
  align-items: center;
@@ -84,7 +92,8 @@ export const InputChartStyles = css`
84
92
  border-bottom: rgba(0, 0, 0, 0.2) 1px solid;
85
93
  }
86
94
 
87
- #add-series-button {
95
+ #add-series-button,
96
+ #add-annotation-button {
88
97
  width: 20px;
89
98
  height: 20px;
90
99
  padding: 0;