@orbcharts/plugins-basic 3.0.0-alpha.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. package/LICENSE +201 -0
  2. package/package.json +41 -0
  3. package/src/grid/defaults.ts +95 -0
  4. package/src/grid/gridObservables.ts +114 -0
  5. package/src/grid/index.ts +12 -0
  6. package/src/grid/plugins/BarStack.ts +661 -0
  7. package/src/grid/plugins/Bars.ts +604 -0
  8. package/src/grid/plugins/BarsTriangle.ts +594 -0
  9. package/src/grid/plugins/Dots.ts +427 -0
  10. package/src/grid/plugins/GroupArea.ts +636 -0
  11. package/src/grid/plugins/GroupAxis.ts +363 -0
  12. package/src/grid/plugins/Lines.ts +528 -0
  13. package/src/grid/plugins/Ranking.ts +0 -0
  14. package/src/grid/plugins/RankingAxis.ts +0 -0
  15. package/src/grid/plugins/ScalingArea.ts +168 -0
  16. package/src/grid/plugins/ValueAxis.ts +356 -0
  17. package/src/grid/plugins/ValueStackAxis.ts +372 -0
  18. package/src/grid/types.ts +102 -0
  19. package/src/index.ts +7 -0
  20. package/src/multiGrid/index.ts +0 -0
  21. package/src/multiGrid/plugins/Diverging.ts +0 -0
  22. package/src/multiGrid/plugins/DivergingAxes.ts +0 -0
  23. package/src/multiGrid/plugins/TwoScaleAxes.ts +0 -0
  24. package/src/multiGrid/plugins/TwoScales.ts +0 -0
  25. package/src/multiValue/index.ts +0 -0
  26. package/src/multiValue/plugins/Scatter.ts +0 -0
  27. package/src/multiValue/plugins/ScatterAxes.ts +0 -0
  28. package/src/noneData/defaults.ts +47 -0
  29. package/src/noneData/index.ts +4 -0
  30. package/src/noneData/plugins/Container.ts +11 -0
  31. package/src/noneData/plugins/Tooltip.ts +305 -0
  32. package/src/noneData/types.ts +26 -0
  33. package/src/relationship/index.ts +0 -0
  34. package/src/relationship/plugins/Relationship.ts +0 -0
  35. package/src/series/defaults.ts +82 -0
  36. package/src/series/index.ts +6 -0
  37. package/src/series/plugins/Bubbles.ts +553 -0
  38. package/src/series/plugins/Pie.ts +603 -0
  39. package/src/series/plugins/PieEventTexts.ts +194 -0
  40. package/src/series/plugins/PieLabels.ts +289 -0
  41. package/src/series/plugins/Waffle.ts +0 -0
  42. package/src/series/seriesUtils.ts +51 -0
  43. package/src/series/types.ts +53 -0
  44. package/src/tree/index.ts +0 -0
  45. package/src/tree/plugins/TreeMap.ts +0 -0
  46. package/src/utils/commonUtils.ts +22 -0
  47. package/src/utils/d3Graphics.ts +125 -0
  48. package/src/utils/d3Utils.ts +73 -0
  49. package/src/utils/observables.ts +14 -0
  50. package/src/utils/orbchartsUtils.ts +70 -0
  51. package/tsconfig.json +14 -0
  52. package/vite.config.js +45 -0
@@ -0,0 +1,636 @@
1
+ import * as d3 from 'd3'
2
+ import {
3
+ // of,
4
+ iif,
5
+ EMPTY,
6
+ combineLatest,
7
+ switchMap,
8
+ map,
9
+ filter,
10
+ first,
11
+ takeUntil,
12
+ distinctUntilChanged,
13
+ Subject,
14
+ Observable } from 'rxjs'
15
+ import {
16
+ defineGridPlugin } from '@orbcharts/core'
17
+ import type {
18
+ TransformData,
19
+ ChartParams } from '@orbcharts/core'
20
+ import { DEFAULT_GROUP_AREA_PLUGIN_PARAMS } from '../defaults'
21
+ import { parseTickFormatValue } from '../../utils/d3Utils'
22
+ import { measureTextWidth } from '../../utils/commonUtils'
23
+ import { getColor, getClassName, getUniID } from '../../utils/orbchartsUtils'
24
+ import { d3EventObservable } from '../../utils/observables'
25
+ import { gridGroupPositionFnObservable } from '../gridObservables'
26
+ import { createAxisPointScale } from '@orbcharts/core'
27
+ import type { GroupAreaPluginParams } from '../types'
28
+
29
+ interface LineDatum {
30
+ id: string
31
+ x1: number
32
+ x2: number
33
+ y1: number
34
+ y2: number
35
+ }
36
+
37
+ interface LabelDatum {
38
+ id: string
39
+ text: string
40
+ x: number
41
+ y: number
42
+ }
43
+
44
+ const pluginName = 'GroupArea'
45
+ const labelClassName = getClassName(pluginName, 'label-box')
46
+
47
+ function createLineData ({ groupLabel, axisX, axisHeight, fullParams }: {
48
+ groupLabel: string
49
+ axisX: number
50
+ axisHeight: number
51
+ fullParams: GroupAreaPluginParams
52
+ }): LineDatum[] {
53
+ return fullParams.showLine && groupLabel
54
+ ? [{
55
+ id: groupLabel,
56
+ x1: axisX,
57
+ x2: axisX,
58
+ y1: 0,
59
+ y2: axisHeight
60
+ }]
61
+ : []
62
+ }
63
+
64
+ function renderLine ({ selection, pluginName, lineData, fullParams, fullChartParams }: {
65
+ selection: d3.Selection<any, unknown, any, unknown>
66
+ pluginName: string
67
+ lineData: LineDatum[]
68
+ fullParams: GroupAreaPluginParams
69
+ fullChartParams: ChartParams
70
+ }) {
71
+ const gClassName = getClassName(pluginName, 'auxline')
72
+ const update = selection
73
+ .selectAll<SVGLineElement, LineDatum>(`line.${gClassName}`)
74
+ .data(lineData)
75
+ const enter = update
76
+ .enter()
77
+ .append('line')
78
+ .classed(gClassName, true)
79
+ // .style('stroke', '#E4E7ED')
80
+ .style('stroke', d => getColor(fullParams.lineColorType, fullChartParams))
81
+ .style('stroke-width', 1)
82
+ .style('stroke-dasharray', fullParams.lineDashArray ?? 'none')
83
+ .style('pointer-events', 'none')
84
+ // .attr('opacity', 0)
85
+ const auxLineSelection = update.merge(enter)
86
+ // .attr('opacity', (d) => {
87
+ // return d.active == true ? 1 : 0
88
+ // })
89
+ update.exit().remove()
90
+ enter
91
+ .attr('x1', d => d.x1)
92
+ .attr('y1', d => d.y1)
93
+ .attr('x2', d => d.x2)
94
+ .attr('y2', d => d.y2)
95
+ update
96
+ .transition()
97
+ .duration(50)
98
+ .attr('x1', d => d.x1)
99
+ .attr('y1', d => d.y1)
100
+ .attr('x2', d => d.x2)
101
+ .attr('y2', d => d.y2)
102
+
103
+ return auxLineSelection
104
+ }
105
+
106
+ function removeLine (selection: d3.Selection<any, unknown, any, unknown>) {
107
+ const update = selection
108
+ .selectAll<SVGLineElement, LineDatum>('line')
109
+ .data([])
110
+
111
+ update.exit().remove()
112
+ }
113
+
114
+ function createLabelData ({ groupLabel, axisX, fullParams }: {
115
+ groupLabel: string
116
+ axisX: number
117
+ fullParams: GroupAreaPluginParams
118
+ }) {
119
+ return fullParams.showLabel && groupLabel
120
+ ? [{
121
+ id: groupLabel,
122
+ x: axisX,
123
+ y: - fullParams.labelPadding,
124
+ text: parseTickFormatValue(groupLabel, fullParams.labelTextFormat)
125
+ }]
126
+ : []
127
+ }
128
+
129
+ function renderLabel ({ selection, labelData, fullParams, fullChartParams, gridAxesOppositeTransformValue }: {
130
+ selection: d3.Selection<any, unknown, any, unknown>
131
+ labelData: LabelDatum[]
132
+ fullParams: GroupAreaPluginParams
133
+ fullChartParams: ChartParams
134
+ gridAxesOppositeTransformValue: string
135
+ }) {
136
+ const rectHeight = fullChartParams.styles.textSize + 4
137
+
138
+ const gUpdate = selection
139
+ .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
140
+ .data(labelData)
141
+ const gEnter = gUpdate
142
+ .enter()
143
+ .append('g')
144
+ .classed(labelClassName, true)
145
+ .style('cursor', 'pointer')
146
+ const axisLabelSelection = gEnter.merge(gUpdate)
147
+ gEnter
148
+ .attr("transform", (d, i) => {
149
+ return `translate(${d.x}, ${d.y})`
150
+ })
151
+ gUpdate
152
+ .transition()
153
+ .duration(50)
154
+ .attr("transform", (d, i) => {
155
+ return `translate(${d.x}, ${d.y})`
156
+ })
157
+ gUpdate.exit().remove()
158
+
159
+ axisLabelSelection.each((datum, i, n) => {
160
+ const rectWidth = measureTextWidth(datum.text, fullChartParams.styles.textSize) + 12
161
+ const rectX = - rectWidth / 2
162
+
163
+ const rectUpdate = d3.select(n[i])
164
+ .selectAll<SVGRectElement, LabelDatum>('rect')
165
+ .data([datum])
166
+ const rectEnter = rectUpdate
167
+ .enter()
168
+ .append('rect')
169
+ .attr('height', `${rectHeight}px`)
170
+ .attr('fill', d => getColor(fullParams.labelColorType, fullChartParams))
171
+ .attr('x', rectX)
172
+ .attr('y', -2)
173
+ .attr('rx', 5)
174
+ .attr('ry', 5)
175
+ .style('cursor', 'pointer')
176
+ // .style('pointer-events', 'none')
177
+ const rect = rectUpdate.merge(rectEnter)
178
+ .attr('width', d => `${rectWidth}px`)
179
+ .style('transform', gridAxesOppositeTransformValue)
180
+ rectUpdate.exit().remove()
181
+
182
+ const textUpdate = d3.select(n[i])
183
+ .selectAll<SVGTextElement, LabelDatum>('text')
184
+ .data([datum])
185
+ const textEnter = textUpdate
186
+ .enter()
187
+ .append('text')
188
+ .style('dominant-baseline', 'hanging')
189
+ .style('cursor', 'pointer')
190
+ // .style('pointer-events', 'none')
191
+ const text = textUpdate.merge(textEnter)
192
+ .text(d => d.text)
193
+ .style('transform', gridAxesOppositeTransformValue)
194
+ .attr('fill', d => getColor(fullParams.labelTextColorType, fullChartParams))
195
+ .attr('font-size', fullChartParams.styles.textSize)
196
+ .attr('x', rectX + 6)
197
+ textUpdate.exit().remove()
198
+ })
199
+
200
+ return axisLabelSelection
201
+ }
202
+
203
+ function removeLabel (selection: d3.Selection<any, unknown, any, unknown>) {
204
+ const gUpdate = selection
205
+ .selectAll<SVGGElement, LabelDatum>(`g.${labelClassName}`)
206
+ .data([])
207
+
208
+ gUpdate.exit().remove()
209
+ }
210
+
211
+ export const GroupArea = defineGridPlugin(pluginName, DEFAULT_GROUP_AREA_PLUGIN_PARAMS)(({ selection, rootSelection, name, subject, observer }) => {
212
+ const destroy$ = new Subject()
213
+
214
+ const rootRectSelection: d3.Selection<SVGRectElement, any, any, any> = rootSelection
215
+ .insert('rect', 'g')
216
+ .classed(getClassName(pluginName, 'rect'), true)
217
+ .attr('opacity', 0)
218
+
219
+ const axisSelection: d3.Selection<SVGGElement, any, any, any> = selection
220
+ .append('g')
221
+
222
+ observer.layout$.pipe(
223
+ takeUntil(destroy$),
224
+ ).subscribe(d => {
225
+ rootRectSelection
226
+ .attr('width', d.rootWidth)
227
+ .attr('height', d.rootHeight)
228
+ })
229
+
230
+ observer.gridAxesTransform$
231
+ .pipe(
232
+ takeUntil(destroy$),
233
+ map(d => d.value),
234
+ distinctUntilChanged()
235
+ ).subscribe(d => {
236
+ axisSelection
237
+ .style('transform', d)
238
+ })
239
+
240
+ // const visibleComputedData$ = observer.computedData$.pipe(
241
+ // takeUntil(destroy$),
242
+ // map(data => {
243
+ // const visibleComputedData = data
244
+ // .map(d => {
245
+ // return d.filter(_d => {
246
+ // return _d.visible == true
247
+ // })
248
+ // })
249
+ // .filter(d => d.length)
250
+ // // console.log('visibleComputedData', visibleComputedData)
251
+ // return visibleComputedData
252
+ // })
253
+ // )
254
+
255
+ // const SeriesDataMap$ = visibleComputedData$.pipe(
256
+ // map(d => makeGridSeriesDataMap(d))
257
+ // )
258
+
259
+ // const GroupDataMap$ = visibleComputedData$.pipe(
260
+ // map(d => makeGridGroupDataMap(d))
261
+ // )
262
+
263
+ // const contentTransform$: Observable<string> = new Observable(subscriber => {
264
+ // combineLatest({
265
+ // fullParams: observer.fullParams$,
266
+ // gridAxesTransform: observer.gridAxesTransform$
267
+ // }).pipe(
268
+ // takeUntil(destroy$),
269
+ // // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
270
+ // switchMap(async (d) => d),
271
+ // ).subscribe(data => {
272
+
273
+ // const transformData = Object.assign({}, data.gridAxesTransform)
274
+
275
+ // // const value = getAxesTransformValue({
276
+ // // translate: [0, 0],
277
+ // // scale: [transformData.scale[0] * -1, transformData.scale[1] * -1],
278
+ // // rotate: transformData.rotate * -1,
279
+ // // rotateX: transformData.rotateX * -1,
280
+ // // rotateY: transformData.rotateY * -1
281
+ // // })
282
+
283
+ // subscriber.next(transformData.value)
284
+ // })
285
+ // })
286
+ // const oppositeTransform$: Observable<TransformData> = observer.gridAxesTransform$.pipe(
287
+ // takeUntil(destroy$),
288
+ // map(d => {
289
+ // const translate: [number, number] = [d.translate[0] * -1, d.translate[1] * -1]
290
+ // const scale: [number, number] = [d.scale[0] * -1, d.scale[1] * -1]
291
+ // const rotate = d.rotate * -1
292
+ // const rotateX = d.rotateX * -1
293
+ // const rotateY = d.rotateY * -1
294
+ // return {
295
+ // translate,
296
+ // scale,
297
+ // rotate,
298
+ // rotateX,
299
+ // rotateY,
300
+ // value: ''
301
+ // }
302
+ // }),
303
+ // )
304
+ // const contentTransform$ = combineLatest({
305
+ // fullParams: observer.fullParams$,
306
+ // oppositeTransform: oppositeTransform$
307
+ // }).pipe(
308
+ // takeUntil(destroy$),
309
+ // switchMap(async data => {
310
+ // const translate = [0, 0]
311
+ // return `translate(${translate[0]}px, ${translate[1]}px) rotate(${data.oppositeTransform.rotate}deg) rotateX(${data.oppositeTransform.rotateX}deg) rotateY(${data.oppositeTransform.rotateY}deg)`
312
+ // }),
313
+ // distinctUntilChanged()
314
+ // )
315
+
316
+ const groupScale$: Observable<d3.ScalePoint<string>> = new Observable(subscriber => {
317
+ combineLatest({
318
+ fullDataFormatter: observer.fullDataFormatter$,
319
+ gridAxesSize: observer.gridAxesSize$,
320
+ computedData: observer.computedData$
321
+ }).pipe(
322
+ takeUntil(destroy$),
323
+ switchMap(async (d) => d),
324
+ ).subscribe(data => {
325
+ const groupMin = 0
326
+ const groupMax = data.computedData[0] ? data.computedData[0].length - 1 : 0
327
+ const groupScaleDomainMin = data.fullDataFormatter.groupAxis.scaleDomain[0] === 'auto'
328
+ ? groupMin - data.fullDataFormatter.groupAxis.scalePadding
329
+ : data.fullDataFormatter.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.groupAxis.scalePadding
330
+ const groupScaleDomainMax = data.fullDataFormatter.groupAxis.scaleDomain[1] === 'auto'
331
+ ? groupMax + data.fullDataFormatter.groupAxis.scalePadding
332
+ : data.fullDataFormatter.groupAxis.scaleDomain[1] as number + data.fullDataFormatter.groupAxis.scalePadding
333
+
334
+ const groupingLength = data.computedData[0]
335
+ ? data.computedData[0].length
336
+ : 0
337
+
338
+ let _labels = data.fullDataFormatter.grid.seriesType === 'row'
339
+ // ? data.fullDataFormatter.grid.columnLabels
340
+ // : data.fullDataFormatter.grid.rowLabels
341
+ ? (data.computedData[0] ?? []).map(d => d.groupLabel)
342
+ : data.computedData.map(d => d[0].groupLabel)
343
+
344
+ const axisLabels = new Array(groupingLength).fill(0)
345
+ .map((d, i) => {
346
+ return _labels[i] != null
347
+ ? _labels[i]
348
+ : String(i) // 沒有label則用序列號填充
349
+ })
350
+ .filter((d, i) => {
351
+ return i >= groupScaleDomainMin && i <= groupScaleDomainMax
352
+ })
353
+
354
+
355
+ const padding = data.fullDataFormatter.groupAxis.scalePadding
356
+
357
+ const groupScale = createAxisPointScale({
358
+ axisLabels,
359
+ axisWidth: data.gridAxesSize.width,
360
+ padding
361
+ })
362
+
363
+ subscriber.next(groupScale)
364
+ })
365
+ })
366
+
367
+ // 取得事件座標的group資料
368
+ const gridGroupPositionFn$ = gridGroupPositionFnObservable({
369
+ fullDataFormatter$: observer.fullDataFormatter$,
370
+ gridAxesSize$: observer.gridAxesSize$,
371
+ computedData$: observer.computedData$,
372
+ fullChartParams$: observer.fullChartParams$,
373
+ })
374
+
375
+ const highlightTarget$ = observer.fullChartParams$.pipe(
376
+ takeUntil(destroy$),
377
+ map(d => d.highlightTarget),
378
+ distinctUntilChanged()
379
+ )
380
+
381
+ combineLatest({
382
+ computedData: observer.computedData$,
383
+ gridAxesSize: observer.gridAxesSize$,
384
+ fullParams: observer.fullParams$,
385
+ fullChartParams: observer.fullChartParams$,
386
+ highlightTarget: highlightTarget$,
387
+ SeriesDataMap: observer.SeriesDataMap$,
388
+ GroupDataMap: observer.GroupDataMap$,
389
+ gridGroupPositionFn: gridGroupPositionFn$,
390
+ groupScale: groupScale$,
391
+ }).pipe(
392
+ takeUntil(destroy$),
393
+ // 轉換後會退訂前一個未完成的訂閱事件,因此可以取到「同時間」最後一次的訂閱事件
394
+ switchMap(async (d) => d),
395
+ ).subscribe(data => {
396
+
397
+ // store.selection
398
+ rootSelection
399
+ .on('mouseover', (event, datum) => {
400
+ // event.stopPropagation()
401
+
402
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
403
+
404
+ subject.event$.next({
405
+ type: 'grid',
406
+ pluginName: name,
407
+ eventName: 'mouseover',
408
+ highlightTarget: data.highlightTarget,
409
+ datum: null,
410
+ series: [],
411
+ seriesIndex: -1,
412
+ seriesLabel: '',
413
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
414
+ groupIndex,
415
+ groupLabel,
416
+ event,
417
+ data: data.computedData
418
+ })
419
+ })
420
+ .on('mousemove', (event, datum) => {
421
+ // event.stopPropagation()
422
+
423
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
424
+
425
+ subject.event$.next({
426
+ type: 'grid',
427
+ pluginName: name,
428
+ eventName: 'mousemove',
429
+ highlightTarget: data.highlightTarget,
430
+ datum: null,
431
+ series: [],
432
+ seriesIndex: -1,
433
+ seriesLabel: '',
434
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
435
+ groupIndex,
436
+ groupLabel,
437
+ event,
438
+ data: data.computedData
439
+ })
440
+ })
441
+ .on('mouseout', (event, datum) => {
442
+ // event.stopPropagation()
443
+
444
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
445
+
446
+ subject.event$.next({
447
+ type: 'grid',
448
+ pluginName: name,
449
+ eventName: 'mouseout',
450
+ highlightTarget: data.highlightTarget,
451
+ datum: null,
452
+ series: [],
453
+ seriesIndex: -1,
454
+ seriesLabel: '',
455
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
456
+ groupIndex,
457
+ groupLabel,
458
+ event,
459
+ data: data.computedData
460
+ })
461
+ })
462
+ .on('click', (event, datum) => {
463
+ event.stopPropagation()
464
+
465
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
466
+
467
+ subject.event$.next({
468
+ type: 'grid',
469
+ pluginName: name,
470
+ eventName: 'click',
471
+ highlightTarget: data.highlightTarget,
472
+ datum: null,
473
+ series: [],
474
+ seriesIndex: -1,
475
+ seriesLabel: '',
476
+ groups: data.GroupDataMap.get(groupLabel) ?? [],
477
+ groupIndex,
478
+ groupLabel,
479
+ event,
480
+ data: data.computedData
481
+ })
482
+ })
483
+
484
+ // barSelection$.next(barSelection!)
485
+ })
486
+
487
+ // -- highlight(無論highlightTarget設定為何,一律依從groupLabel來顯示) --
488
+ combineLatest({
489
+ // highlight: highlight$,
490
+ event: subject.event$.pipe(
491
+ filter(d => d.eventName === 'mouseover' || d.eventName === 'mousemove')
492
+ ),
493
+ computedData: observer.computedData$,
494
+ groupScale: groupScale$,
495
+ gridAxesSize: observer.gridAxesSize$,
496
+ fullParams: observer.fullParams$,
497
+ fullChartParams: observer.fullChartParams$,
498
+ highlightTarget: highlightTarget$,
499
+ gridAxesOppositeTransform: observer.gridAxesOppositeTransform$,
500
+ GroupDataMap: observer.GroupDataMap$,
501
+ gridGroupPositionFn: gridGroupPositionFn$,
502
+ }).pipe(
503
+ takeUntil(destroy$),
504
+ switchMap(async d => d)
505
+ ).subscribe(data => {
506
+ // const groups = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
507
+ // ? data.event.groups
508
+ // : []
509
+
510
+ // const groupLabel = data.event.eventName === 'mouseover' || data.event.eventName === 'mousemove'
511
+ // ? data.event.groupLabel
512
+ // : ''
513
+ const axisX = data.groupScale(data.event.groupLabel) ?? 0
514
+
515
+ const lineData = createLineData({
516
+ groupLabel: data.event.groupLabel,
517
+ axisX,
518
+ axisHeight: data.gridAxesSize.height,
519
+ fullParams: data.fullParams,
520
+ })
521
+ renderLine({
522
+ selection: axisSelection,
523
+ pluginName: name,
524
+ lineData,
525
+ fullParams: data.fullParams,
526
+ fullChartParams: data.fullChartParams
527
+ })
528
+ const labelData = createLabelData({
529
+ groupLabel: data.event.groupLabel,
530
+ axisX,
531
+ fullParams: data.fullParams
532
+ })
533
+ const labelSelection = renderLabel({
534
+ selection: axisSelection,
535
+ labelData,
536
+ fullParams: data.fullParams,
537
+ fullChartParams: data.fullChartParams,
538
+ gridAxesOppositeTransformValue: data.gridAxesOppositeTransform.value
539
+ })
540
+
541
+ // label的事件
542
+ labelSelection
543
+ .on('mouseover', (event, datum) => {
544
+
545
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
546
+
547
+ subject.event$.next({
548
+ type: 'grid',
549
+ pluginName: name,
550
+ eventName: 'mouseover',
551
+ highlightTarget: data.highlightTarget,
552
+ datum: null,
553
+ series: [],
554
+ seriesIndex: -1,
555
+ seriesLabel: '',
556
+ groups: data.event.groups,
557
+ groupIndex,
558
+ groupLabel,
559
+ event,
560
+ data: data.computedData
561
+ })
562
+ })
563
+ .on('mousemove', (event, datum) => {
564
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
565
+
566
+ subject.event$.next({
567
+ type: 'grid',
568
+ pluginName: name,
569
+ eventName: 'mousemove',
570
+ highlightTarget: data.highlightTarget,
571
+ datum: null,
572
+ series: [],
573
+ seriesIndex: -1,
574
+ seriesLabel: '',
575
+ groups: data.event.groups,
576
+ groupIndex,
577
+ groupLabel,
578
+ event,
579
+ data: data.computedData
580
+ })
581
+ })
582
+ .on('mouseout', (event, datum) => {
583
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
584
+
585
+ subject.event$.next({
586
+ type: 'grid',
587
+ pluginName: name,
588
+ eventName: 'mouseout',
589
+ highlightTarget: data.highlightTarget,
590
+ datum: null,
591
+ series: [],
592
+ seriesIndex: -1,
593
+ seriesLabel: '',
594
+ groups: data.event.groups,
595
+ groupIndex,
596
+ groupLabel,
597
+ event,
598
+ data: data.computedData
599
+ })
600
+ })
601
+ .on('click', (event, datum) => {
602
+ const { groupIndex, groupLabel } = data.gridGroupPositionFn(event)
603
+
604
+ subject.event$.next({
605
+ type: 'grid',
606
+ pluginName: name,
607
+ eventName: 'click',
608
+ highlightTarget: data.highlightTarget,
609
+ datum: null,
610
+ series: [],
611
+ seriesIndex: -1,
612
+ seriesLabel: '',
613
+ groups: data.event.groups,
614
+ groupIndex,
615
+ groupLabel,
616
+ event,
617
+ data: data.computedData
618
+ })
619
+ })
620
+ })
621
+
622
+ const rootMouseout$ = d3EventObservable(rootRectSelection, 'mouseout').pipe(
623
+ takeUntil(destroy$),
624
+ )
625
+
626
+ rootMouseout$.subscribe(event => {
627
+ console.log('rootMouseout')
628
+ removeLine(axisSelection)
629
+ removeLabel(axisSelection)
630
+ })
631
+
632
+ return () => {
633
+ destroy$.next(undefined)
634
+ rootRectSelection.remove()
635
+ }
636
+ })