@orbcharts/plugins-basic 3.0.7 → 3.0.9

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 (121) hide show
  1. package/LICENSE +200 -200
  2. package/dist/orbcharts-plugins-basic.es.js +6837 -6656
  3. package/dist/orbcharts-plugins-basic.umd.js +45 -45
  4. package/dist/src/base/BaseStackedBars.d.ts +2 -0
  5. package/dist/src/series/defaults.d.ts +2 -1
  6. package/dist/src/series/index.d.ts +1 -0
  7. package/dist/src/series/plugins/Indicator.d.ts +3 -0
  8. package/lib/core-types.ts +7 -7
  9. package/lib/core.ts +6 -6
  10. package/lib/gridObservables.ts +6 -6
  11. package/lib/plugins-basic-types.ts +6 -6
  12. package/package.json +48 -48
  13. package/src/base/BaseBars.ts +765 -765
  14. package/src/base/BaseBarsTriangle.ts +676 -676
  15. package/src/base/BaseDots.ts +464 -464
  16. package/src/base/BaseGroupAxis.ts +691 -691
  17. package/src/base/BaseLegend.ts +684 -684
  18. package/src/base/BaseLineAreas.ts +629 -629
  19. package/src/base/BaseLines.ts +706 -706
  20. package/src/base/BaseOrdinalBubbles.ts +729 -729
  21. package/src/base/BaseRacingBars.ts +582 -582
  22. package/src/base/BaseRacingLabels.ts +404 -404
  23. package/src/base/BaseRacingValueLabels.ts +403 -403
  24. package/src/base/BaseStackedBars.ts +793 -782
  25. package/src/base/BaseTooltip.ts +408 -408
  26. package/src/base/BaseValueAxis.ts +600 -600
  27. package/src/base/BaseXAxis.ts +427 -427
  28. package/src/base/BaseXZoom.ts +241 -241
  29. package/src/base/BaseYAxis.ts +389 -389
  30. package/src/base/types.ts +2 -2
  31. package/src/const.ts +30 -30
  32. package/src/grid/defaults.ts +213 -213
  33. package/src/grid/gridObservables.ts +635 -635
  34. package/src/grid/index.ts +16 -16
  35. package/src/grid/plugins/Bars.ts +69 -69
  36. package/src/grid/plugins/BarsPN.ts +66 -66
  37. package/src/grid/plugins/BarsTriangle.ts +73 -73
  38. package/src/grid/plugins/Dots.ts +68 -68
  39. package/src/grid/plugins/GridLegend.ts +107 -107
  40. package/src/grid/plugins/GridTooltip.ts +66 -66
  41. package/src/grid/plugins/GroupAux.ts +1095 -1095
  42. package/src/grid/plugins/GroupAxis.ts +73 -73
  43. package/src/grid/plugins/GroupZoom.ts +218 -218
  44. package/src/grid/plugins/LineAreas.ts +65 -65
  45. package/src/grid/plugins/Lines.ts +59 -59
  46. package/src/grid/plugins/StackedBars.ts +66 -64
  47. package/src/grid/plugins/StackedValueAxis.ts +97 -96
  48. package/src/grid/plugins/ValueAxis.ts +94 -94
  49. package/src/index.ts +6 -6
  50. package/src/multiGrid/defaults.ts +244 -244
  51. package/src/multiGrid/index.ts +14 -14
  52. package/src/multiGrid/multiGridObservables.ts +50 -50
  53. package/src/multiGrid/plugins/MultiBars.ts +108 -108
  54. package/src/multiGrid/plugins/MultiBarsTriangle.ts +114 -114
  55. package/src/multiGrid/plugins/MultiDots.ts +102 -102
  56. package/src/multiGrid/plugins/MultiGridLegend.ts +169 -169
  57. package/src/multiGrid/plugins/MultiGridTooltip.ts +66 -66
  58. package/src/multiGrid/plugins/MultiGroupAxis.ts +137 -137
  59. package/src/multiGrid/plugins/MultiLineAreas.ts +107 -107
  60. package/src/multiGrid/plugins/MultiLines.ts +101 -101
  61. package/src/multiGrid/plugins/MultiStackedBars.ts +109 -106
  62. package/src/multiGrid/plugins/MultiStackedValueAxis.ts +135 -134
  63. package/src/multiGrid/plugins/MultiValueAxis.ts +134 -134
  64. package/src/multiGrid/plugins/OverlappingStackedValueAxes.ts +300 -300
  65. package/src/multiGrid/plugins/OverlappingValueAxes.ts +300 -300
  66. package/src/multiValue/defaults.ts +523 -523
  67. package/src/multiValue/index.ts +16 -16
  68. package/src/multiValue/multiValueObservables.ts +781 -781
  69. package/src/multiValue/plugins/MultiValueLegend.ts +107 -107
  70. package/src/multiValue/plugins/MultiValueTooltip.ts +66 -66
  71. package/src/multiValue/plugins/OrdinalAux.ts +660 -660
  72. package/src/multiValue/plugins/OrdinalAxis.ts +524 -524
  73. package/src/multiValue/plugins/OrdinalBubbles.ts +226 -226
  74. package/src/multiValue/plugins/OrdinalZoom.ts +57 -57
  75. package/src/multiValue/plugins/RacingBars.ts +375 -375
  76. package/src/multiValue/plugins/RacingCounterTexts.ts +300 -300
  77. package/src/multiValue/plugins/RacingValueAxis.ts +114 -114
  78. package/src/multiValue/plugins/Scatter.ts +486 -486
  79. package/src/multiValue/plugins/ScatterBubbles.ts +635 -635
  80. package/src/multiValue/plugins/XAxis.ts +107 -107
  81. package/src/multiValue/plugins/XYAux.ts +683 -683
  82. package/src/multiValue/plugins/XYAxes.ts +194 -194
  83. package/src/multiValue/plugins/XYAxes_legacy.ts +683 -683
  84. package/src/multiValue/plugins/XZoom.ts +40 -40
  85. package/src/noneData/defaults.ts +102 -102
  86. package/src/noneData/index.ts +3 -3
  87. package/src/noneData/plugins/Container.ts +27 -27
  88. package/src/noneData/plugins/Tooltip.ts +373 -373
  89. package/src/relationship/defaults.ts +221 -221
  90. package/src/relationship/index.ts +5 -5
  91. package/src/relationship/plugins/ForceDirected.ts +1056 -1056
  92. package/src/relationship/plugins/ForceDirectedBubbles.ts +1294 -1294
  93. package/src/relationship/plugins/RelationshipLegend.ts +100 -100
  94. package/src/relationship/plugins/RelationshipTooltip.ts +66 -66
  95. package/src/relationship/relationshipObservables.ts +49 -49
  96. package/src/series/defaults.ts +236 -224
  97. package/src/series/index.ts +10 -9
  98. package/src/series/plugins/Bubbles.ts +784 -784
  99. package/src/series/plugins/Indicator.ts +292 -0
  100. package/src/series/plugins/Pie.ts +622 -622
  101. package/src/series/plugins/PieEventTexts.ts +283 -283
  102. package/src/series/plugins/PieLabels.ts +639 -639
  103. package/src/series/plugins/Rose.ts +515 -515
  104. package/src/series/plugins/RoseLabels.ts +599 -599
  105. package/src/series/plugins/SeriesLegend.ts +107 -107
  106. package/src/series/plugins/SeriesTooltip.ts +66 -66
  107. package/src/series/seriesObservables.ts +168 -168
  108. package/src/series/seriesUtils.ts +51 -51
  109. package/src/tree/defaults.ts +102 -102
  110. package/src/tree/index.ts +4 -4
  111. package/src/tree/plugins/TreeLegend.ts +100 -100
  112. package/src/tree/plugins/TreeMap.ts +341 -341
  113. package/src/tree/plugins/TreeTooltip.ts +66 -66
  114. package/src/utils/commonUtils.ts +31 -31
  115. package/src/utils/d3Graphics.ts +176 -176
  116. package/src/utils/d3Utils.ts +92 -92
  117. package/src/utils/observables.ts +14 -14
  118. package/src/utils/orbchartsUtils.ts +129 -129
  119. package/tsconfig.base.json +13 -13
  120. package/tsconfig.json +2 -2
  121. package/vite.config.js +22 -22
@@ -1,525 +1,525 @@
1
- import * as d3 from 'd3'
2
- import {
3
- Observable,
4
- Subject,
5
- combineLatest,
6
- takeUntil,
7
- of,
8
- map,
9
- distinctUntilChanged,
10
- switchMap,
11
- shareReplay
12
- } from 'rxjs'
13
- import type {
14
- ContainerSize,
15
- ChartParams,
16
- ComputedDatumMultiValue,
17
- DataFormatterMultiValue,
18
- DefinePluginConfig,
19
- Layout
20
- } from '../../../lib/core-types'
21
- import type { OrdinalAxisParams } from '../../../lib/plugins-basic-types'
22
- import {
23
- defineMultiValuePlugin,
24
- createDefaultValueLabel
25
- } from '../../../lib/core'
26
- import { DEFAULT_ORDINAL_AXIS_PARAMS } from '../defaults'
27
- import { LAYER_INDEX_OF_AXIS } from '../../const'
28
- // import { createBaseXAxis } from '../../base/BaseXAxis'
29
- import { getColor, getDatumColor, getClassName, getUniID } from '../../utils/orbchartsUtils'
30
- import { multiValueContainerSelectionsObservable } from '../multiValueObservables'
31
- import { renderTspansOnAxis } from '../../utils/d3Graphics'
32
- import { parseTickFormatValue } from '../../utils/d3Utils'
33
-
34
- type ClipPathDatum = {
35
- id: string;
36
- // x: number;
37
- // y: number;
38
- width: number;
39
- height: number;
40
- }
41
-
42
- // interface TextAlign {
43
- // textAnchor: "start" | "middle" | "end"
44
- // dominantBaseline: "middle" | "auto" | "hanging"
45
- // }
46
-
47
- interface ValueLabelData {
48
- text: string
49
- textArr: string[]
50
- }
51
-
52
- const pluginName = 'OrdinalAxis'
53
-
54
- const defaultTickSize = 6
55
- const xAxisLabelAnchor = 'start'
56
- const xAxisLabelDominantBaseline = 'auto'
57
-
58
- const pluginConfig: DefinePluginConfig<typeof pluginName, typeof DEFAULT_ORDINAL_AXIS_PARAMS> = {
59
- name: pluginName,
60
- defaultParams: DEFAULT_ORDINAL_AXIS_PARAMS,
61
- layerIndex: LAYER_INDEX_OF_AXIS,
62
- validator: (params, { validateColumns }) => {
63
- const result = validateColumns(params, {
64
- labelOffset: {
65
- toBe: '[number, number]',
66
- test: (value: any) => {
67
- return Array.isArray(value)
68
- && value.length === 2
69
- && typeof value[0] === 'number'
70
- && typeof value[1] === 'number'
71
- }
72
- },
73
- labelColorType: {
74
- toBeOption: 'ColorType',
75
- },
76
- axisLineVisible: {
77
- toBeTypes: ['boolean']
78
- },
79
- axisLineColorType: {
80
- toBeOption: 'ColorType',
81
- },
82
- ticks: {
83
- toBeTypes: ['number', 'null']
84
- },
85
- tickFormat: {
86
- toBeTypes: ['string', 'Function']
87
- },
88
- tickLineVisible: {
89
- toBeTypes: ['boolean']
90
- },
91
- tickPadding: {
92
- toBeTypes: ['number']
93
- },
94
- tickFullLine: {
95
- toBeTypes: ['boolean']
96
- },
97
- tickFullLineDasharray: {
98
- toBeTypes: ['string']
99
- },
100
- tickColorType: {
101
- toBeOption: 'ColorType',
102
- },
103
- tickTextRotate: {
104
- toBeTypes: ['number']
105
- },
106
- tickTextColorType: {
107
- toBeOption: 'ColorType',
108
- }
109
- })
110
- if (result.status === 'error') {
111
- return result
112
- }
113
- return result
114
- }
115
- }
116
-
117
- function createValueLabelData (groupLabels: string[], tickFormat: string | ((text: any) => string | d3.NumberValue)): ValueLabelData[] {
118
- return groupLabels.map((_text, i) => {
119
- const text = parseTickFormatValue(_text, tickFormat)
120
- const textArr = typeof text === 'string' ? text.split('\n') : [text]
121
-
122
- return {
123
- text,
124
- textArr
125
- }
126
- })
127
- }
128
-
129
- function renderAxisLabel ({ selection, axisLabelClassName, fullParams, containerSize, fullDataFormatter, fullChartParams }: {
130
- selection: d3.Selection<SVGGElement, any, any, any>,
131
- axisLabelClassName: string
132
- fullParams: OrdinalAxisParams
133
- // axisLabelAlign: TextAlign
134
- containerSize: ContainerSize
135
- fullDataFormatter: DataFormatterMultiValue,
136
- fullChartParams: ChartParams
137
- // textReverseTransform: string,
138
- }) {
139
- const offsetX = fullParams.tickPadding + fullParams.labelOffset[0]
140
- // const offsetY = fullParams.tickPadding + fullParams.labelOffset[1]
141
- let labelX = offsetX
142
-
143
-
144
- let y: number // = position === 'top' ? 0 : layout.height
145
- let offsetY
146
- // if (position === 'top') {
147
- y = 0
148
- offsetY = -fullParams.tickPadding - fullParams.labelOffset[1]
149
- // } else {
150
- // y = containerSize.height
151
- // offsetY = fullParams.tickPadding + fullParams.labelOffset[1]
152
- // }
153
-
154
- let labelY = offsetY
155
-
156
- const axisLabelSelection = selection
157
- .selectAll<SVGGElement, OrdinalAxisParams>(`g.${axisLabelClassName}`)
158
- .data([fullParams])
159
- .join('g')
160
- .classed(axisLabelClassName, true)
161
- .each((d, i, g) => {
162
- const text = d3.select(g[i])
163
- .selectAll<SVGTextElement, OrdinalAxisParams>(`text`)
164
- .data([d])
165
- .join(
166
- enter => {
167
- return enter
168
- .append('text')
169
- .style('font-weight', 'bold')
170
- },
171
- update => update,
172
- exit => exit.remove()
173
- )
174
- .attr('text-anchor', xAxisLabelAnchor)
175
- .attr('dominant-baseline', xAxisLabelDominantBaseline)
176
- .attr('font-size', fullChartParams.styles.textSize)
177
- .style('fill', getColor(fullParams.labelColorType, fullChartParams))
178
- // .style('transform', textReverseTransform)
179
- // 偏移使用 x, y 而非 transform 才不會受到外層 scale 變形影響
180
- .attr('x', labelX)
181
- .attr('y', labelY)
182
- .text(d => fullDataFormatter.xAxis.label)
183
- })
184
- .attr('transform', d => `translate(${containerSize.width}, ${y})`)
185
- }
186
-
187
- function renderAxis ({ selection, ordinalXAxisClassName, fullParams, containerSize, fullDataFormatter, fullChartParams, ordinalScale, ordinalScaleDomain, valueLabelData, textRotateTransform, textSizePx, ordinalPadding }: {
188
- selection: d3.Selection<SVGGElement, any, any, any>,
189
- ordinalXAxisClassName: string
190
- fullParams: OrdinalAxisParams
191
- // tickTextAlign: TextAlign
192
- containerSize: ContainerSize
193
- fullDataFormatter: DataFormatterMultiValue,
194
- fullChartParams: ChartParams
195
- ordinalScale: d3.ScaleLinear<number, number>
196
- ordinalScaleDomain: number[]
197
- // groupLabels: string[]
198
- valueLabelData: ValueLabelData[]
199
- // textReverseTransformWithRotate: string
200
- textRotateTransform: string
201
- textSizePx: number
202
- ordinalPadding: number
203
- }) {
204
-
205
- const textAnchor = fullParams.tickTextRotate
206
- ? 'start'
207
- : 'middle'
208
- const dominantBaseline = 'auto'
209
-
210
- const xAxisSelection = selection
211
- .selectAll<SVGGElement, OrdinalAxisParams>(`g.${ordinalXAxisClassName}`)
212
- .data([fullParams])
213
- .join('g')
214
- .classed(ordinalXAxisClassName, true)
215
- .attr('transform', `translate(${ordinalPadding}, 0)`)
216
-
217
- // 計算所有範圍內groupLabels數量(顯示所有刻度)
218
- const allTicksAmount = Math.floor(ordinalScaleDomain[1]) - Math.ceil(ordinalScaleDomain[0]) + 1
219
-
220
- // 刻度文字偏移
221
- let tickPadding = 0
222
- let textX = 0
223
- // if (fullDataFormatter.groupAxis.position === 'left') {
224
- // tickPadding = 0
225
- // textX = - fullParams.tickPadding
226
- // } else if (fullDataFormatter.groupAxis.position === 'right') {
227
- // tickPadding = 0
228
- // textX = fullParams.tickPadding
229
- // } else if (fullDataFormatter.groupAxis.position === 'bottom') {
230
- // if (fullParams.tickFullLine == true) {
231
- // tickPadding = - fullParams.tickPadding
232
- // } else {
233
- // tickPadding = - fullParams.tickPadding - defaultTickSize
234
- // }
235
- // textX = 0
236
- // } else if (fullDataFormatter.groupAxis.position === 'top') {
237
- if (fullParams.tickFullLine == true) {
238
- tickPadding = fullParams.tickPadding
239
- } else {
240
- tickPadding = fullParams.tickPadding - defaultTickSize
241
- }
242
- textX = - 0
243
- // }
244
-
245
- // 設定X軸刻度
246
- const xAxis = d3.axisTop(ordinalScale)
247
- .scale(ordinalScale)
248
- .ticks(fullParams.ticks === 'all'
249
- ? allTicksAmount
250
- : fullParams.ticks > allTicksAmount
251
- // 不顯示超過groupLabels數量的刻度
252
- ? allTicksAmount - 1 // 不知為何設剛好一樣的數字會多一個刻度,所以 -1 強制避免這個狀況
253
- : fullParams.ticks)
254
- .tickSize(fullParams.tickFullLine == true
255
- ? - containerSize.height
256
- : defaultTickSize)
257
- .tickSizeOuter(0)
258
- .tickFormat((valueIndex: number, i) => {
259
- // 用index對應到groupLabel
260
- // const groupLabel = groupLabels[valueIndex ] ?? '' // 非整數index不顯示
261
- // return parseTickFormatValue(groupLabel, fullParams.tickFormat)
262
- return valueLabelData[valueIndex]?.text ?? ''
263
- })
264
- .tickPadding(tickPadding)
265
-
266
- const xAxisEl = xAxisSelection
267
- .transition()
268
- .duration(100)
269
- .ease(d3.easeLinear) // 線性的 - 當托曳或快速變動的時候比較滑順
270
- .call(xAxis)
271
-
272
- .on('end', (self, t) => {
273
- // 先等transition結束再處理文字,否則會被原本的文字覆蓋
274
- xAxisSelection
275
- .selectAll('.tick text')
276
- .each((valueIndex: number, i, n) => {
277
- // const groupLabel = groupLabels[valueIndex ] ?? '' // 非整數index不顯示
278
- // const groupLabelText = parseTickFormatValue(groupLabel, fullParams.tickFormat)
279
- // console.log(valueIndex)
280
- const textArr = valueLabelData[valueIndex]?.textArr ?? []
281
- // 將原本單行文字改為多行文字
282
- renderTspansOnAxis(d3.select(n[i]), {
283
- textArr,
284
- textSizePx,
285
- groupAxisPosition: 'top',
286
- isContainerRotated: true
287
- })
288
- })
289
- })
290
-
291
- xAxisEl.selectAll('line')
292
- .style('fill', 'none')
293
- .style('stroke', fullParams.tickLineVisible == true ? getColor(fullParams.tickColorType, fullChartParams) : 'none')
294
- .style('stroke-dasharray', fullParams.tickFullLineDasharray)
295
- .style('vector-effect', 'non-scaling-stroke') // 避免 scale 導致線條變形
296
- .attr('pointer-events', 'none')
297
-
298
- xAxisEl.selectAll('path')
299
- .style('fill', 'none')
300
- .style('stroke', fullParams.axisLineVisible == true ? getColor(fullParams.axisLineColorType, fullChartParams) : 'none')
301
- .style('shape-rendering', 'crispEdges')
302
-
303
- const xText = xAxisSelection.selectAll<SVGTextElement, OrdinalAxisParams>('text')
304
- // .style('font-family', 'sans-serif')
305
- .attr('font-size', fullChartParams.styles.textSize)
306
- // .style('font-weight', 'bold')
307
- .attr('fill', getColor(fullParams.tickTextColorType, fullChartParams))
308
- .attr('text-anchor', textAnchor)
309
- .attr('dominant-baseline', dominantBaseline)
310
- .attr('x', textX)
311
- .style('transform', textRotateTransform)
312
-
313
- // 抵消掉預設的偏移
314
- // if (fullDataFormatter.groupAxis.position === 'left' || fullDataFormatter.groupAxis.position === 'right') {
315
- xText.attr('dy', 0)
316
- // }
317
-
318
- return xAxisSelection
319
- }
320
-
321
-
322
- function renderClipPath ({ defsSelection, clipPathData }: {
323
- defsSelection: d3.Selection<SVGDefsElement, any, any, any>
324
- clipPathData: ClipPathDatum[]
325
- // textReverseTransform: string
326
- }) {
327
- const clipPath = defsSelection
328
- .selectAll<SVGClipPathElement, Layout>('clipPath')
329
- .data(clipPathData)
330
- .join(
331
- enter => {
332
- return enter
333
- .append('clipPath')
334
- },
335
- update => update,
336
- exit => exit.remove()
337
- )
338
- .attr('id', d => d.id)
339
- // .attr('transform', textReverseTransform)
340
- .each((d, i, g) => {
341
- const rect = d3.select(g[i])
342
- .selectAll<SVGRectElement, typeof d>('rect')
343
- .data([d])
344
- .join(
345
- enter => {
346
- return enter
347
- .append('rect')
348
- },
349
- update => update,
350
- exit => exit.remove()
351
- )
352
- .attr('x', _d => - _d.width)
353
- .attr('y', 0)
354
- .attr('width', _d => _d.width * 2)
355
- .attr('height', _d => _d.height)
356
- })
357
- }
358
-
359
- export const OrdinalAxis = defineMultiValuePlugin(pluginConfig)(({ selection, name, observer, subject }) => {
360
-
361
- const destroy$ = new Subject()
362
-
363
- const xAxisGClassName = getClassName(pluginName, 'xAxisG')
364
- const ordinalXAxisClassName = getClassName(pluginName, 'axis')
365
- const axisLabelClassName = getClassName(pluginName, 'axis-label')
366
- const clipPathID = getUniID(pluginName, 'clipPath-box')
367
-
368
- const containerSelection$ = multiValueContainerSelectionsObservable({
369
- selection,
370
- pluginName,
371
- clipPathID: null,
372
- computedData$: observer.computedData$,
373
- containerPosition$: observer.containerPosition$,
374
- isCategorySeprate$: observer.isCategorySeprate$,
375
- }).pipe(
376
- takeUntil(destroy$),
377
- )
378
-
379
- observer.containerSize$.subscribe(data => {
380
- const defsSelection = selection.selectAll<SVGDefsElement, any>('defs')
381
- .data([clipPathID])
382
- .join('defs')
383
- const clipPathData = [{
384
- id: clipPathID,
385
- width: data.width,
386
- height: data.height
387
- }]
388
- renderClipPath({
389
- defsSelection: defsSelection,
390
- clipPathData,
391
- // textReverseTransform: data.textReverseTransform
392
- })
393
- })
394
-
395
- const axisSelection$ = containerSelection$.pipe(
396
- takeUntil(destroy$),
397
- map((containerSelection, i) => {
398
- return containerSelection
399
- .selectAll<SVGGElement, ComputedDatumMultiValue[]>(`g.${xAxisGClassName}`)
400
- .data([xAxisGClassName])
401
- .join('g')
402
- .classed(xAxisGClassName, true)
403
- })
404
- )
405
-
406
- const valueLabelData$ = combineLatest({
407
- valueLabels: observer.valueLabels$,
408
- fullParams: observer.fullParams$,
409
- }).pipe(
410
- takeUntil(destroy$),
411
- switchMap(async (d) => d),
412
- map(data => {
413
- return createValueLabelData(data.valueLabels, data.fullParams.tickFormat)
414
- }),
415
- shareReplay(1)
416
- )
417
-
418
- // const tickTextAlign$: Observable<TextAlign> = observer.fullParams$.pipe(
419
- // takeUntil(destroy$),
420
- // map(data => {
421
- // let textAnchor: 'start' | 'middle' | 'end' = 'middle'
422
- // let dominantBaseline: 'auto' | 'middle' | 'hanging' = 'hanging'
423
-
424
- // textAnchor = data.tickTextRotate
425
- // ? 'start'
426
- // : 'middle'
427
- // dominantBaseline = 'auto'
428
-
429
- // return {
430
- // textAnchor,
431
- // dominantBaseline
432
- // }
433
- // })
434
- // )
435
-
436
- const ordinalScaleDomain$ = combineLatest({
437
- valueLabelData: valueLabelData$,
438
- fullDataFormatter: observer.fullDataFormatter$,
439
- }).pipe(
440
- takeUntil(destroy$),
441
- switchMap(async (d) => d),
442
- map(data => {
443
- const groupMin = 0//- 0.5
444
- const groupMax = data.valueLabelData.length - 1//0.5
445
- // const groupScaleDomainMin = data.fullDataFormatter.groupAxis.scaleDomain[0] === 'auto'
446
- // ? groupMin - data.fullDataFormatter.groupAxis.scalePadding
447
- // : data.fullDataFormatter.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.groupAxis.scalePadding
448
- const groupScaleDomainMin = data.fullDataFormatter.xAxis.scaleDomain[0] === 'min' || data.fullDataFormatter.xAxis.scaleDomain[0] === 'auto'
449
- ? groupMin
450
- : data.fullDataFormatter.xAxis.scaleDomain[0] as number// - 0.5
451
- const groupScaleDomainMax = data.fullDataFormatter.xAxis.scaleDomain[1] === 'max' || data.fullDataFormatter.xAxis.scaleDomain[1] === 'auto'
452
- ? groupMax
453
- : data.fullDataFormatter.xAxis.scaleDomain[1] as number// - 0.5
454
-
455
- return [groupScaleDomainMin, groupScaleDomainMax]
456
- }),
457
- shareReplay(1)
458
- )
459
-
460
- const textRotateTransform$ = observer.fullParams$.pipe(
461
- takeUntil(destroy$),
462
- map(data => {
463
- return data.tickTextRotate
464
- ? `rotate(${data.tickTextRotate})`
465
- : ''
466
- })
467
- )
468
-
469
- combineLatest({
470
- axisSelection: axisSelection$,
471
- fullParams: observer.fullParams$,
472
- // tickTextAlign: tickTextAlign$,
473
- // axisLabelAlign: axisLabelAlign$,
474
- containerSize: observer.containerSize$,
475
- fullDataFormatter: observer.fullDataFormatter$,
476
- fullChartParams: observer.fullChartParams$,
477
- ordinalScale: observer.ordinalScale$,
478
- ordinalScaleDomain: ordinalScaleDomain$,
479
- // groupLabels: groupLabels$,
480
- valueLabelData: valueLabelData$,
481
- // textReverseTransform: textReverseTransform$,
482
- // textReverseTransformWithRotate: textReverseTransformWithRotate$,
483
- textRotateTransform: textRotateTransform$,
484
- textSizePx: observer.textSizePx$,
485
- // tickTextFormatter: tickTextFormatter$
486
- ordinalPadding: observer.ordinalPadding$
487
- }).pipe(
488
- takeUntil(destroy$),
489
- switchMap(async (d) => d),
490
- ).subscribe(data => {
491
-
492
- renderAxis({
493
- selection: data.axisSelection,
494
- ordinalXAxisClassName,
495
- fullParams: data.fullParams,
496
- // tickTextAlign: data.tickTextAlign,
497
- containerSize: data.containerSize,
498
- fullDataFormatter: data.fullDataFormatter,
499
- fullChartParams: data.fullChartParams,
500
- ordinalScale: data.ordinalScale,
501
- ordinalScaleDomain: data.ordinalScaleDomain,
502
- // groupLabels: data.groupLabels,
503
- valueLabelData: data.valueLabelData,
504
- // textReverseTransformWithRotate: data.textReverseTransformWithRotate,
505
- textRotateTransform: data.textRotateTransform,
506
- textSizePx: data.textSizePx,
507
- ordinalPadding: data.ordinalPadding
508
- })
509
-
510
- renderAxisLabel({
511
- selection: data.axisSelection,
512
- axisLabelClassName,
513
- fullParams: data.fullParams,
514
- // axisLabelAlign: data.axisLabelAlign,
515
- containerSize: data.containerSize,
516
- fullDataFormatter: data.fullDataFormatter,
517
- fullChartParams: data.fullChartParams,
518
- // textReverseTransform: data.textReverseTransform,
519
- })
520
- })
521
-
522
- return () => {
523
- destroy$.next(undefined)
524
- }
1
+ import * as d3 from 'd3'
2
+ import {
3
+ Observable,
4
+ Subject,
5
+ combineLatest,
6
+ takeUntil,
7
+ of,
8
+ map,
9
+ distinctUntilChanged,
10
+ switchMap,
11
+ shareReplay
12
+ } from 'rxjs'
13
+ import type {
14
+ ContainerSize,
15
+ ChartParams,
16
+ ComputedDatumMultiValue,
17
+ DataFormatterMultiValue,
18
+ DefinePluginConfig,
19
+ Layout
20
+ } from '../../../lib/core-types'
21
+ import type { OrdinalAxisParams } from '../../../lib/plugins-basic-types'
22
+ import {
23
+ defineMultiValuePlugin,
24
+ createDefaultValueLabel
25
+ } from '../../../lib/core'
26
+ import { DEFAULT_ORDINAL_AXIS_PARAMS } from '../defaults'
27
+ import { LAYER_INDEX_OF_AXIS } from '../../const'
28
+ // import { createBaseXAxis } from '../../base/BaseXAxis'
29
+ import { getColor, getDatumColor, getClassName, getUniID } from '../../utils/orbchartsUtils'
30
+ import { multiValueContainerSelectionsObservable } from '../multiValueObservables'
31
+ import { renderTspansOnAxis } from '../../utils/d3Graphics'
32
+ import { parseTickFormatValue } from '../../utils/d3Utils'
33
+
34
+ type ClipPathDatum = {
35
+ id: string;
36
+ // x: number;
37
+ // y: number;
38
+ width: number;
39
+ height: number;
40
+ }
41
+
42
+ // interface TextAlign {
43
+ // textAnchor: "start" | "middle" | "end"
44
+ // dominantBaseline: "middle" | "auto" | "hanging"
45
+ // }
46
+
47
+ interface ValueLabelData {
48
+ text: string
49
+ textArr: string[]
50
+ }
51
+
52
+ const pluginName = 'OrdinalAxis'
53
+
54
+ const defaultTickSize = 6
55
+ const xAxisLabelAnchor = 'start'
56
+ const xAxisLabelDominantBaseline = 'auto'
57
+
58
+ const pluginConfig: DefinePluginConfig<typeof pluginName, typeof DEFAULT_ORDINAL_AXIS_PARAMS> = {
59
+ name: pluginName,
60
+ defaultParams: DEFAULT_ORDINAL_AXIS_PARAMS,
61
+ layerIndex: LAYER_INDEX_OF_AXIS,
62
+ validator: (params, { validateColumns }) => {
63
+ const result = validateColumns(params, {
64
+ labelOffset: {
65
+ toBe: '[number, number]',
66
+ test: (value: any) => {
67
+ return Array.isArray(value)
68
+ && value.length === 2
69
+ && typeof value[0] === 'number'
70
+ && typeof value[1] === 'number'
71
+ }
72
+ },
73
+ labelColorType: {
74
+ toBeOption: 'ColorType',
75
+ },
76
+ axisLineVisible: {
77
+ toBeTypes: ['boolean']
78
+ },
79
+ axisLineColorType: {
80
+ toBeOption: 'ColorType',
81
+ },
82
+ ticks: {
83
+ toBeTypes: ['number', 'null']
84
+ },
85
+ tickFormat: {
86
+ toBeTypes: ['string', 'Function']
87
+ },
88
+ tickLineVisible: {
89
+ toBeTypes: ['boolean']
90
+ },
91
+ tickPadding: {
92
+ toBeTypes: ['number']
93
+ },
94
+ tickFullLine: {
95
+ toBeTypes: ['boolean']
96
+ },
97
+ tickFullLineDasharray: {
98
+ toBeTypes: ['string']
99
+ },
100
+ tickColorType: {
101
+ toBeOption: 'ColorType',
102
+ },
103
+ tickTextRotate: {
104
+ toBeTypes: ['number']
105
+ },
106
+ tickTextColorType: {
107
+ toBeOption: 'ColorType',
108
+ }
109
+ })
110
+ if (result.status === 'error') {
111
+ return result
112
+ }
113
+ return result
114
+ }
115
+ }
116
+
117
+ function createValueLabelData (groupLabels: string[], tickFormat: string | ((text: any) => string | d3.NumberValue)): ValueLabelData[] {
118
+ return groupLabels.map((_text, i) => {
119
+ const text = parseTickFormatValue(_text, tickFormat)
120
+ const textArr = typeof text === 'string' ? text.split('\n') : [text]
121
+
122
+ return {
123
+ text,
124
+ textArr
125
+ }
126
+ })
127
+ }
128
+
129
+ function renderAxisLabel ({ selection, axisLabelClassName, fullParams, containerSize, fullDataFormatter, fullChartParams }: {
130
+ selection: d3.Selection<SVGGElement, any, any, any>,
131
+ axisLabelClassName: string
132
+ fullParams: OrdinalAxisParams
133
+ // axisLabelAlign: TextAlign
134
+ containerSize: ContainerSize
135
+ fullDataFormatter: DataFormatterMultiValue,
136
+ fullChartParams: ChartParams
137
+ // textReverseTransform: string,
138
+ }) {
139
+ const offsetX = fullParams.tickPadding + fullParams.labelOffset[0]
140
+ // const offsetY = fullParams.tickPadding + fullParams.labelOffset[1]
141
+ let labelX = offsetX
142
+
143
+
144
+ let y: number // = position === 'top' ? 0 : layout.height
145
+ let offsetY
146
+ // if (position === 'top') {
147
+ y = 0
148
+ offsetY = -fullParams.tickPadding - fullParams.labelOffset[1]
149
+ // } else {
150
+ // y = containerSize.height
151
+ // offsetY = fullParams.tickPadding + fullParams.labelOffset[1]
152
+ // }
153
+
154
+ let labelY = offsetY
155
+
156
+ const axisLabelSelection = selection
157
+ .selectAll<SVGGElement, OrdinalAxisParams>(`g.${axisLabelClassName}`)
158
+ .data([fullParams])
159
+ .join('g')
160
+ .classed(axisLabelClassName, true)
161
+ .each((d, i, g) => {
162
+ const text = d3.select(g[i])
163
+ .selectAll<SVGTextElement, OrdinalAxisParams>(`text`)
164
+ .data([d])
165
+ .join(
166
+ enter => {
167
+ return enter
168
+ .append('text')
169
+ .style('font-weight', 'bold')
170
+ },
171
+ update => update,
172
+ exit => exit.remove()
173
+ )
174
+ .attr('text-anchor', xAxisLabelAnchor)
175
+ .attr('dominant-baseline', xAxisLabelDominantBaseline)
176
+ .attr('font-size', fullChartParams.styles.textSize)
177
+ .style('fill', getColor(fullParams.labelColorType, fullChartParams))
178
+ // .style('transform', textReverseTransform)
179
+ // 偏移使用 x, y 而非 transform 才不會受到外層 scale 變形影響
180
+ .attr('x', labelX)
181
+ .attr('y', labelY)
182
+ .text(d => fullDataFormatter.xAxis.label)
183
+ })
184
+ .attr('transform', d => `translate(${containerSize.width}, ${y})`)
185
+ }
186
+
187
+ function renderAxis ({ selection, ordinalXAxisClassName, fullParams, containerSize, fullDataFormatter, fullChartParams, ordinalScale, ordinalScaleDomain, valueLabelData, textRotateTransform, textSizePx, ordinalPadding }: {
188
+ selection: d3.Selection<SVGGElement, any, any, any>,
189
+ ordinalXAxisClassName: string
190
+ fullParams: OrdinalAxisParams
191
+ // tickTextAlign: TextAlign
192
+ containerSize: ContainerSize
193
+ fullDataFormatter: DataFormatterMultiValue,
194
+ fullChartParams: ChartParams
195
+ ordinalScale: d3.ScaleLinear<number, number>
196
+ ordinalScaleDomain: number[]
197
+ // groupLabels: string[]
198
+ valueLabelData: ValueLabelData[]
199
+ // textReverseTransformWithRotate: string
200
+ textRotateTransform: string
201
+ textSizePx: number
202
+ ordinalPadding: number
203
+ }) {
204
+
205
+ const textAnchor = fullParams.tickTextRotate
206
+ ? 'start'
207
+ : 'middle'
208
+ const dominantBaseline = 'auto'
209
+
210
+ const xAxisSelection = selection
211
+ .selectAll<SVGGElement, OrdinalAxisParams>(`g.${ordinalXAxisClassName}`)
212
+ .data([fullParams])
213
+ .join('g')
214
+ .classed(ordinalXAxisClassName, true)
215
+ .attr('transform', `translate(${ordinalPadding}, 0)`)
216
+
217
+ // 計算所有範圍內groupLabels數量(顯示所有刻度)
218
+ const allTicksAmount = Math.floor(ordinalScaleDomain[1]) - Math.ceil(ordinalScaleDomain[0]) + 1
219
+
220
+ // 刻度文字偏移
221
+ let tickPadding = 0
222
+ let textX = 0
223
+ // if (fullDataFormatter.groupAxis.position === 'left') {
224
+ // tickPadding = 0
225
+ // textX = - fullParams.tickPadding
226
+ // } else if (fullDataFormatter.groupAxis.position === 'right') {
227
+ // tickPadding = 0
228
+ // textX = fullParams.tickPadding
229
+ // } else if (fullDataFormatter.groupAxis.position === 'bottom') {
230
+ // if (fullParams.tickFullLine == true) {
231
+ // tickPadding = - fullParams.tickPadding
232
+ // } else {
233
+ // tickPadding = - fullParams.tickPadding - defaultTickSize
234
+ // }
235
+ // textX = 0
236
+ // } else if (fullDataFormatter.groupAxis.position === 'top') {
237
+ if (fullParams.tickFullLine == true) {
238
+ tickPadding = fullParams.tickPadding
239
+ } else {
240
+ tickPadding = fullParams.tickPadding - defaultTickSize
241
+ }
242
+ textX = - 0
243
+ // }
244
+
245
+ // 設定X軸刻度
246
+ const xAxis = d3.axisTop(ordinalScale)
247
+ .scale(ordinalScale)
248
+ .ticks(fullParams.ticks === 'all'
249
+ ? allTicksAmount
250
+ : fullParams.ticks > allTicksAmount
251
+ // 不顯示超過groupLabels數量的刻度
252
+ ? allTicksAmount - 1 // 不知為何設剛好一樣的數字會多一個刻度,所以 -1 強制避免這個狀況
253
+ : fullParams.ticks)
254
+ .tickSize(fullParams.tickFullLine == true
255
+ ? - containerSize.height
256
+ : defaultTickSize)
257
+ .tickSizeOuter(0)
258
+ .tickFormat((valueIndex: number, i) => {
259
+ // 用index對應到groupLabel
260
+ // const groupLabel = groupLabels[valueIndex ] ?? '' // 非整數index不顯示
261
+ // return parseTickFormatValue(groupLabel, fullParams.tickFormat)
262
+ return valueLabelData[valueIndex]?.text ?? ''
263
+ })
264
+ .tickPadding(tickPadding)
265
+
266
+ const xAxisEl = xAxisSelection
267
+ .transition()
268
+ .duration(100)
269
+ .ease(d3.easeLinear) // 線性的 - 當托曳或快速變動的時候比較滑順
270
+ .call(xAxis)
271
+
272
+ .on('end', (self, t) => {
273
+ // 先等transition結束再處理文字,否則會被原本的文字覆蓋
274
+ xAxisSelection
275
+ .selectAll('.tick text')
276
+ .each((valueIndex: number, i, n) => {
277
+ // const groupLabel = groupLabels[valueIndex ] ?? '' // 非整數index不顯示
278
+ // const groupLabelText = parseTickFormatValue(groupLabel, fullParams.tickFormat)
279
+ // console.log(valueIndex)
280
+ const textArr = valueLabelData[valueIndex]?.textArr ?? []
281
+ // 將原本單行文字改為多行文字
282
+ renderTspansOnAxis(d3.select(n[i]), {
283
+ textArr,
284
+ textSizePx,
285
+ groupAxisPosition: 'top',
286
+ isContainerRotated: true
287
+ })
288
+ })
289
+ })
290
+
291
+ xAxisEl.selectAll('line')
292
+ .style('fill', 'none')
293
+ .style('stroke', fullParams.tickLineVisible == true ? getColor(fullParams.tickColorType, fullChartParams) : 'none')
294
+ .style('stroke-dasharray', fullParams.tickFullLineDasharray)
295
+ .style('vector-effect', 'non-scaling-stroke') // 避免 scale 導致線條變形
296
+ .attr('pointer-events', 'none')
297
+
298
+ xAxisEl.selectAll('path')
299
+ .style('fill', 'none')
300
+ .style('stroke', fullParams.axisLineVisible == true ? getColor(fullParams.axisLineColorType, fullChartParams) : 'none')
301
+ .style('shape-rendering', 'crispEdges')
302
+
303
+ const xText = xAxisSelection.selectAll<SVGTextElement, OrdinalAxisParams>('text')
304
+ // .style('font-family', 'sans-serif')
305
+ .attr('font-size', fullChartParams.styles.textSize)
306
+ // .style('font-weight', 'bold')
307
+ .attr('fill', getColor(fullParams.tickTextColorType, fullChartParams))
308
+ .attr('text-anchor', textAnchor)
309
+ .attr('dominant-baseline', dominantBaseline)
310
+ .attr('x', textX)
311
+ .style('transform', textRotateTransform)
312
+
313
+ // 抵消掉預設的偏移
314
+ // if (fullDataFormatter.groupAxis.position === 'left' || fullDataFormatter.groupAxis.position === 'right') {
315
+ xText.attr('dy', 0)
316
+ // }
317
+
318
+ return xAxisSelection
319
+ }
320
+
321
+
322
+ function renderClipPath ({ defsSelection, clipPathData }: {
323
+ defsSelection: d3.Selection<SVGDefsElement, any, any, any>
324
+ clipPathData: ClipPathDatum[]
325
+ // textReverseTransform: string
326
+ }) {
327
+ const clipPath = defsSelection
328
+ .selectAll<SVGClipPathElement, Layout>('clipPath')
329
+ .data(clipPathData)
330
+ .join(
331
+ enter => {
332
+ return enter
333
+ .append('clipPath')
334
+ },
335
+ update => update,
336
+ exit => exit.remove()
337
+ )
338
+ .attr('id', d => d.id)
339
+ // .attr('transform', textReverseTransform)
340
+ .each((d, i, g) => {
341
+ const rect = d3.select(g[i])
342
+ .selectAll<SVGRectElement, typeof d>('rect')
343
+ .data([d])
344
+ .join(
345
+ enter => {
346
+ return enter
347
+ .append('rect')
348
+ },
349
+ update => update,
350
+ exit => exit.remove()
351
+ )
352
+ .attr('x', _d => - _d.width)
353
+ .attr('y', 0)
354
+ .attr('width', _d => _d.width * 2)
355
+ .attr('height', _d => _d.height)
356
+ })
357
+ }
358
+
359
+ export const OrdinalAxis = defineMultiValuePlugin(pluginConfig)(({ selection, name, observer, subject }) => {
360
+
361
+ const destroy$ = new Subject()
362
+
363
+ const xAxisGClassName = getClassName(pluginName, 'xAxisG')
364
+ const ordinalXAxisClassName = getClassName(pluginName, 'axis')
365
+ const axisLabelClassName = getClassName(pluginName, 'axis-label')
366
+ const clipPathID = getUniID(pluginName, 'clipPath-box')
367
+
368
+ const containerSelection$ = multiValueContainerSelectionsObservable({
369
+ selection,
370
+ pluginName,
371
+ clipPathID: null,
372
+ computedData$: observer.computedData$,
373
+ containerPosition$: observer.containerPosition$,
374
+ isCategorySeprate$: observer.isCategorySeprate$,
375
+ }).pipe(
376
+ takeUntil(destroy$),
377
+ )
378
+
379
+ observer.containerSize$.subscribe(data => {
380
+ const defsSelection = selection.selectAll<SVGDefsElement, any>('defs')
381
+ .data([clipPathID])
382
+ .join('defs')
383
+ const clipPathData = [{
384
+ id: clipPathID,
385
+ width: data.width,
386
+ height: data.height
387
+ }]
388
+ renderClipPath({
389
+ defsSelection: defsSelection,
390
+ clipPathData,
391
+ // textReverseTransform: data.textReverseTransform
392
+ })
393
+ })
394
+
395
+ const axisSelection$ = containerSelection$.pipe(
396
+ takeUntil(destroy$),
397
+ map((containerSelection, i) => {
398
+ return containerSelection
399
+ .selectAll<SVGGElement, ComputedDatumMultiValue[]>(`g.${xAxisGClassName}`)
400
+ .data([xAxisGClassName])
401
+ .join('g')
402
+ .classed(xAxisGClassName, true)
403
+ })
404
+ )
405
+
406
+ const valueLabelData$ = combineLatest({
407
+ valueLabels: observer.valueLabels$,
408
+ fullParams: observer.fullParams$,
409
+ }).pipe(
410
+ takeUntil(destroy$),
411
+ switchMap(async (d) => d),
412
+ map(data => {
413
+ return createValueLabelData(data.valueLabels, data.fullParams.tickFormat)
414
+ }),
415
+ shareReplay(1)
416
+ )
417
+
418
+ // const tickTextAlign$: Observable<TextAlign> = observer.fullParams$.pipe(
419
+ // takeUntil(destroy$),
420
+ // map(data => {
421
+ // let textAnchor: 'start' | 'middle' | 'end' = 'middle'
422
+ // let dominantBaseline: 'auto' | 'middle' | 'hanging' = 'hanging'
423
+
424
+ // textAnchor = data.tickTextRotate
425
+ // ? 'start'
426
+ // : 'middle'
427
+ // dominantBaseline = 'auto'
428
+
429
+ // return {
430
+ // textAnchor,
431
+ // dominantBaseline
432
+ // }
433
+ // })
434
+ // )
435
+
436
+ const ordinalScaleDomain$ = combineLatest({
437
+ valueLabelData: valueLabelData$,
438
+ fullDataFormatter: observer.fullDataFormatter$,
439
+ }).pipe(
440
+ takeUntil(destroy$),
441
+ switchMap(async (d) => d),
442
+ map(data => {
443
+ const groupMin = 0//- 0.5
444
+ const groupMax = data.valueLabelData.length - 1//0.5
445
+ // const groupScaleDomainMin = data.fullDataFormatter.groupAxis.scaleDomain[0] === 'auto'
446
+ // ? groupMin - data.fullDataFormatter.groupAxis.scalePadding
447
+ // : data.fullDataFormatter.groupAxis.scaleDomain[0] as number - data.fullDataFormatter.groupAxis.scalePadding
448
+ const groupScaleDomainMin = data.fullDataFormatter.xAxis.scaleDomain[0] === 'min' || data.fullDataFormatter.xAxis.scaleDomain[0] === 'auto'
449
+ ? groupMin
450
+ : data.fullDataFormatter.xAxis.scaleDomain[0] as number// - 0.5
451
+ const groupScaleDomainMax = data.fullDataFormatter.xAxis.scaleDomain[1] === 'max' || data.fullDataFormatter.xAxis.scaleDomain[1] === 'auto'
452
+ ? groupMax
453
+ : data.fullDataFormatter.xAxis.scaleDomain[1] as number// - 0.5
454
+
455
+ return [groupScaleDomainMin, groupScaleDomainMax]
456
+ }),
457
+ shareReplay(1)
458
+ )
459
+
460
+ const textRotateTransform$ = observer.fullParams$.pipe(
461
+ takeUntil(destroy$),
462
+ map(data => {
463
+ return data.tickTextRotate
464
+ ? `rotate(${data.tickTextRotate})`
465
+ : ''
466
+ })
467
+ )
468
+
469
+ combineLatest({
470
+ axisSelection: axisSelection$,
471
+ fullParams: observer.fullParams$,
472
+ // tickTextAlign: tickTextAlign$,
473
+ // axisLabelAlign: axisLabelAlign$,
474
+ containerSize: observer.containerSize$,
475
+ fullDataFormatter: observer.fullDataFormatter$,
476
+ fullChartParams: observer.fullChartParams$,
477
+ ordinalScale: observer.ordinalScale$,
478
+ ordinalScaleDomain: ordinalScaleDomain$,
479
+ // groupLabels: groupLabels$,
480
+ valueLabelData: valueLabelData$,
481
+ // textReverseTransform: textReverseTransform$,
482
+ // textReverseTransformWithRotate: textReverseTransformWithRotate$,
483
+ textRotateTransform: textRotateTransform$,
484
+ textSizePx: observer.textSizePx$,
485
+ // tickTextFormatter: tickTextFormatter$
486
+ ordinalPadding: observer.ordinalPadding$
487
+ }).pipe(
488
+ takeUntil(destroy$),
489
+ switchMap(async (d) => d),
490
+ ).subscribe(data => {
491
+
492
+ renderAxis({
493
+ selection: data.axisSelection,
494
+ ordinalXAxisClassName,
495
+ fullParams: data.fullParams,
496
+ // tickTextAlign: data.tickTextAlign,
497
+ containerSize: data.containerSize,
498
+ fullDataFormatter: data.fullDataFormatter,
499
+ fullChartParams: data.fullChartParams,
500
+ ordinalScale: data.ordinalScale,
501
+ ordinalScaleDomain: data.ordinalScaleDomain,
502
+ // groupLabels: data.groupLabels,
503
+ valueLabelData: data.valueLabelData,
504
+ // textReverseTransformWithRotate: data.textReverseTransformWithRotate,
505
+ textRotateTransform: data.textRotateTransform,
506
+ textSizePx: data.textSizePx,
507
+ ordinalPadding: data.ordinalPadding
508
+ })
509
+
510
+ renderAxisLabel({
511
+ selection: data.axisSelection,
512
+ axisLabelClassName,
513
+ fullParams: data.fullParams,
514
+ // axisLabelAlign: data.axisLabelAlign,
515
+ containerSize: data.containerSize,
516
+ fullDataFormatter: data.fullDataFormatter,
517
+ fullChartParams: data.fullChartParams,
518
+ // textReverseTransform: data.textReverseTransform,
519
+ })
520
+ })
521
+
522
+ return () => {
523
+ destroy$.next(undefined)
524
+ }
525
525
  })