From 59bb59de01fa02f9c9cfb106b4971bece78225ba Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Sat, 29 Oct 2022 12:24:10 +0900 Subject: [PATCH 1/6] feat: add rangeSelection option to LineType, Column Chart - selection with line type series using zoom logic - prototyping with using options in state - convert to rangeSelection from zoom with Line Chart - add rangeSelectable on column chart - add stories --- apps/chart/src/charts/areaChart.ts | 5 +- apps/chart/src/charts/columnChart.ts | 2 + apps/chart/src/charts/lineAreaChart.ts | 4 +- apps/chart/src/charts/lineChart.ts | 4 +- apps/chart/src/charts/lineScatterChart.ts | 4 +- apps/chart/src/component/component.ts | 4 +- .../component/{zoom.ts => rangeSelection.ts} | 38 ++++++++++---- apps/chart/src/store/legend.ts | 51 ++++++++++++++----- apps/chart/src/store/seriesData.ts | 21 ++++++++ apps/chart/stories/area.stories.ts | 20 ++++++++ apps/chart/stories/column.stories.ts | 14 +++++ apps/chart/stories/line.stories.ts | 21 ++++++++ .../types/components/rangeSelection.d.ts | 3 ++ apps/chart/types/eventEmitter.d.ts | 3 +- apps/chart/types/options.d.ts | 4 +- apps/chart/types/store/store.d.ts | 1 + 16 files changed, 164 insertions(+), 35 deletions(-) rename apps/chart/src/component/{zoom.ts => rangeSelection.ts} (84%) create mode 100644 apps/chart/types/components/rangeSelection.d.ts diff --git a/apps/chart/src/charts/areaChart.ts b/apps/chart/src/charts/areaChart.ts index ebe2c3560c..4000726618 100644 --- a/apps/chart/src/charts/areaChart.ts +++ b/apps/chart/src/charts/areaChart.ts @@ -17,7 +17,7 @@ import AxisTitle from '@src/component/axisTitle'; import ExportMenu from '@src/component/exportMenu'; import ResetButton from '@src/component/resetButton'; import Legend from '@src/component/legend'; -import Zoom from '@src/component/zoom'; +import RangeSelection from '@src/component/rangeSelection'; import SelectedSeries from '@src/component/selectedSeries'; import Background from '@src/component/background'; import NoDataText from '@src/component/noDataText'; @@ -67,6 +67,7 @@ import { AreaChartProps, SelectSeriesInfo } from '@t/charts'; * @param {boolean} [props.options.series.showDot=false] - Whether to show dot or not. * @param {boolean} [props.options.series.spline=false] - Whether to make spline chart or not. * @param {boolean} [props.options.series.zoomable=false] - Whether to use zoom feature or not. + * @param {boolean} [props.options.series.rangeSelectable=false] - Whether to use range selection feature or not. * @param {string} [props.options.series.eventDetectType] - Event detect type. 'near', 'nearest', 'grouped', 'point' is available. * @param {boolean} [props.options.series.shift=false] - Whether to use shift when addData or not. * @param {Object} [props.options.series.dataLabels] - Set the visibility, location, and formatting of dataLabel. For specific information, refer to the {@link https://github.com/nhn/tui.chart|DataLabels guide} on github. @@ -158,8 +159,8 @@ export default class AreaChart extends Chart { this.componentManager.add(HoveredSeries); this.componentManager.add(SelectedSeries); this.componentManager.add(Tooltip, { chartEl: this.el }); - this.componentManager.add(Zoom); this.componentManager.add(ResetButton); + this.componentManager.add(RangeSelection); this.componentManager.add(NoDataText); this.painter.addGroups([ diff --git a/apps/chart/src/charts/columnChart.ts b/apps/chart/src/charts/columnChart.ts index fcad4c877e..e696509168 100644 --- a/apps/chart/src/charts/columnChart.ts +++ b/apps/chart/src/charts/columnChart.ts @@ -21,6 +21,7 @@ import HoveredSeries from '@src/component/hoveredSeries'; import SelectedSeries from '@src/component/selectedSeries'; import Background from '@src/component/background'; import NoDataText from '@src/component/noDataText'; +import RangeSelection from '@src/component/rangeSelection'; import * as basicBrush from '@src/brushes/basic'; import * as axisBrush from '@src/brushes/axis'; @@ -153,6 +154,7 @@ export default class ColumnChart extends Chart { this.componentManager.add(DataLabels); this.componentManager.add(Tooltip, { chartEl: this.el }); this.componentManager.add(NoDataText); + this.componentManager.add(RangeSelection); this.painter.addGroups([ basicBrush, diff --git a/apps/chart/src/charts/lineAreaChart.ts b/apps/chart/src/charts/lineAreaChart.ts index 89dfe97dc2..dbcbf51f1a 100644 --- a/apps/chart/src/charts/lineAreaChart.ts +++ b/apps/chart/src/charts/lineAreaChart.ts @@ -18,7 +18,7 @@ import Title from '@src/component/title'; import ExportMenu from '@src/component/exportMenu'; import SelectedSeries from '@src/component/selectedSeries'; import HoveredSeries from '@src/component/hoveredSeries'; -import Zoom from '@src/component/zoom'; +import RangeSelection from '@src/component/rangeSelection'; import ResetButton from '@src/component/resetButton'; import Background from '@src/component/background'; import NoDataText from '@src/component/noDataText'; @@ -160,7 +160,7 @@ export default class LineAreaChart extends Chart { this.componentManager.add(HoveredSeries); this.componentManager.add(SelectedSeries); this.componentManager.add(Tooltip, { chartEl: this.el }); - this.componentManager.add(Zoom); + this.componentManager.add(RangeSelection); this.componentManager.add(ResetButton); this.componentManager.add(NoDataText); diff --git a/apps/chart/src/charts/lineChart.ts b/apps/chart/src/charts/lineChart.ts index 7a4a243e2b..78894068ec 100644 --- a/apps/chart/src/charts/lineChart.ts +++ b/apps/chart/src/charts/lineChart.ts @@ -15,7 +15,7 @@ import AxisTitle from '@src/component/axisTitle'; import Title from '@src/component/title'; import ExportMenu from '@src/component/exportMenu'; import HoveredSeries from '@src/component/hoveredSeries'; -import Zoom from '@src/component/zoom'; +import RangeSelection from '@src/component/rangeSelection'; import ResetButton from '@src/component/resetButton'; import SelectedSeries from '@src/component/selectedSeries'; import Background from '@src/component/background'; @@ -156,7 +156,7 @@ export default class LineChart extends Chart { this.componentManager.add(HoveredSeries); this.componentManager.add(SelectedSeries); this.componentManager.add(Tooltip, { chartEl: this.el }); - this.componentManager.add(Zoom); + this.componentManager.add(RangeSelection); this.componentManager.add(ResetButton); this.componentManager.add(NoDataText); diff --git a/apps/chart/src/charts/lineScatterChart.ts b/apps/chart/src/charts/lineScatterChart.ts index 03e055dce2..7330027215 100644 --- a/apps/chart/src/charts/lineScatterChart.ts +++ b/apps/chart/src/charts/lineScatterChart.ts @@ -17,7 +17,7 @@ import Title from '@src/component/title'; import ExportMenu from '@src/component/exportMenu'; import SelectedSeries from '@src/component/selectedSeries'; import HoveredSeries from '@src/component/hoveredSeries'; -import Zoom from '@src/component/zoom'; +import RangeSelection from '@src/component/rangeSelection'; import Background from '@src/component/background'; import NoDataText from '@src/component/noDataText'; @@ -146,7 +146,7 @@ export default class LineScatterChart extends Chart { this.componentManager.add(HoveredSeries); this.componentManager.add(SelectedSeries); this.componentManager.add(Tooltip, { chartEl: this.el }); - this.componentManager.add(Zoom); + this.componentManager.add(RangeSelection); this.componentManager.add(NoDataText); this.painter.addGroups([ diff --git a/apps/chart/src/component/component.ts b/apps/chart/src/component/component.ts index a2dbca274e..b928254d5d 100644 --- a/apps/chart/src/component/component.ts +++ b/apps/chart/src/component/component.ts @@ -56,10 +56,10 @@ export type ComponentType = | 'exportMenu' | 'resetButton' | 'zeroAxis' - | 'zoom' | 'backButton' | 'background' - | 'noDataText'; + | 'noDataText' + | 'rangeSelection'; type ComponentModels = | AxisModels diff --git a/apps/chart/src/component/zoom.ts b/apps/chart/src/component/rangeSelection.ts similarity index 84% rename from apps/chart/src/component/zoom.ts rename to apps/chart/src/component/rangeSelection.ts index d16fcab228..b991353626 100644 --- a/apps/chart/src/component/zoom.ts +++ b/apps/chart/src/component/rangeSelection.ts @@ -3,8 +3,15 @@ import { AxisData, ChartState, LabelAxisData, Options, Scale, Series } from '@t/ import { RectResponderModel, RectModel } from '@t/components/series'; import { isNull, range } from '@src/helpers/utils'; import { sortNumber } from '@src/helpers/utils'; -import { ZoomModels } from '@t/components/zoom'; -import { AreaSeriesType, CoordinateDataType, LineSeriesType, Point } from '@t/options'; +import { RangeSelectionModels } from '@t/components/rangeSelection'; +import { + AreaSeriesType, + BoxSeriesOptions, + CoordinateDataType, + LineSeriesType, + LineTypeSeriesOptions, + Point, +} from '@t/options'; import { makeObservableObjectToNormal } from '@src/store/reactive'; import { getCoordinateDataIndex, @@ -19,10 +26,11 @@ import { const DRAG_MIN_WIDTH = 15; -type ZoomableSeries = Pick; +type RangeSelectableSeries = Pick; +type RangeSelectableSeriesOptions = BoxSeriesOptions | LineTypeSeriesOptions; -export default class Zoom extends Component { - models: ZoomModels = { selectionArea: [] }; +export default class RangeSelection extends Component { + models: RangeSelectionModels = { selectionArea: [] }; responders!: RectResponderModel[]; @@ -35,13 +43,14 @@ export default class Zoom extends Component { private isDragging = false; initialize() { - this.type = 'zoom'; + this.type = 'rangeSelection'; } render(state: ChartState, computed) { - if (!state.zoomRange) { + if (!state.selectionRange && !state.zoomRange) { return; } + this.resetSelectionArea(); const { viewRange } = computed; const { layout, axes, series, scale } = state; @@ -65,7 +74,7 @@ export default class Zoom extends Component { } getRectResponderInfoForCoordinateType( - series: ZoomableSeries, + series: RangeSelectableSeries, scale: Scale, axisData: LabelAxisData, categories: string[] @@ -123,8 +132,17 @@ export default class Zoom extends Component { .sort((a, b) => a.index! - b.index!) .map((m) => m.data?.value); - this.store.dispatch('zoom', dragRange); - this.eventBus.emit('zoom', makeObservableObjectToNormal(dragRange)); + const { series, options } = this.store.state; + const { series: seriesOptions } = options; + + if (!series.column && (seriesOptions as LineTypeSeriesOptions)?.zoomable) { + this.store.dispatch('zoom', dragRange); + this.eventBus.emit('zoom', makeObservableObjectToNormal(dragRange)); + } + + if ((seriesOptions as RangeSelectableSeriesOptions)?.rangeSelectable) { + this.eventBus.emit('rangeSelection', dragRange); + } this.eventBus.emit('resetHoveredSeries'); this.eventBus.emit('hideTooltip'); diff --git a/apps/chart/src/store/legend.ts b/apps/chart/src/store/legend.ts index 7324bfc2a4..b66c9001fd 100644 --- a/apps/chart/src/store/legend.ts +++ b/apps/chart/src/store/legend.ts @@ -75,6 +75,15 @@ type LegendSizeParams = { chart: Size; }; +type LegendInfoToSetIndexParams = { + legendData: LegendDataList; + rowCount: number; + columnCount: number; + legendCount: number; + verticalAlign: boolean; + itemHeight: number; +}; + const INITIAL_LEGEND_WIDTH = 100; const INITIAL_CIRCLE_LEGEND_WIDTH = 150; const COMPONENT_HEIGHT_EXCEPT_Y_AXIS = 100; @@ -84,18 +93,24 @@ const NUMBER_OF_BOTH_SIDES = 2; function recalculateLegendWhenHeightOverflows(params: LegendSizeParams, legendHeight: number) { const { legendWidths, itemHeight } = params; - const totalHeight = legendWidths.length * itemHeight; - const columnCount = Math.ceil(totalHeight / legendHeight); - const rowCount = legendWidths.length / columnCount; + const maxCountByColumn = Math.floor(legendHeight / itemHeight); + const columnCount = Math.ceil(legendWidths.length / maxCountByColumn); let legendWidth = 0; range(0, columnCount).forEach((count) => { - legendWidth += Math.max(...legendWidths.slice(count * rowCount, (count + 1) * rowCount)); + legendWidth += Math.max( + ...legendWidths.slice(count * maxCountByColumn, (count + 1) * maxCountByColumn) + ); }); legendWidth += LEGEND_ITEM_MARGIN_X * (columnCount - 1); - return { legendWidth, legendHeight: rowCount * itemHeight + padding.Y, columnCount, rowCount }; + return { + legendWidth, + legendHeight: maxCountByColumn * itemHeight + padding.Y, + columnCount, + rowCount: maxCountByColumn, + }; } function recalculateLegendWhenWidthOverflows(params: LegendSizeParams, prevLegendWidth: number) { @@ -446,13 +461,16 @@ function getNextColumnRowIndex(params: { return [rowIndex, columnIndex]; } -function setIndexToLegendData( - legendData: LegendDataList, - rowCount: number, - columnCount: number, - legendCount: number, - verticalAlign: boolean -) { +function setIndexToLegendData(legendInfoParams: LegendInfoToSetIndexParams) { + const { + legendData, + rowCount, + columnCount, + legendCount, + verticalAlign, + itemHeight, + } = legendInfoParams; + let columnIndex = 0; let rowIndex = 0; @@ -550,7 +568,14 @@ const legend: StoreModule = { circleLegendVisible, }); - setIndexToLegendData(legendData, rowCount, columnCount, legendWidths.length, verticalAlign); + setIndexToLegendData({ + legendData, + rowCount, + columnCount, + verticalAlign, + itemHeight, + legendCount: legendWidths.length, + }); extend(state.legend, { visible, diff --git a/apps/chart/src/store/seriesData.ts b/apps/chart/src/store/seriesData.ts index 9a461039b0..0d8972e6f7 100644 --- a/apps/chart/src/store/seriesData.ts +++ b/apps/chart/src/store/seriesData.ts @@ -43,6 +43,17 @@ function initRange(series: RawSeries, categories?: Categories): RangeDataType + rawCategories.findIndex((category) => category === rangeCategory) + ) as RangeDataType; + + this.notify(state, 'selectionRange'); + }, zoom({ state }, rangeCategories: string[]) { const rawCategories = state.rawCategories as string[]; diff --git a/apps/chart/stories/area.stories.ts b/apps/chart/stories/area.stories.ts index a8cb4d9a21..49c50aaa9f 100644 --- a/apps/chart/stories/area.stories.ts +++ b/apps/chart/stories/area.stories.ts @@ -268,6 +268,26 @@ export const zoomable = () => { return el; }; +export const rangeSelectable = () => { + const { el, chart } = createChart(avgTemperatureData, { + series: { + rangeSelectable: true, + dataLabels: { + visible: true, + }, + }, + xAxis: { + pointOnColumn: false, + }, + }); + + chart.on('rangeSelection', (selectedRange) => { + console.log(selectedRange); + }); + + return el; +}; + export const selectable = () => { const { el } = createChart(avgTemperatureData, { chart: { title: 'Average Temperature' }, diff --git a/apps/chart/stories/column.stories.ts b/apps/chart/stories/column.stories.ts index fe49dde7ac..eb10571110 100644 --- a/apps/chart/stories/column.stories.ts +++ b/apps/chart/stories/column.stories.ts @@ -216,6 +216,20 @@ export const responsive = () => { }); }; +export const rangeSelectable = () => { + const { el, chart } = createChart(budgetData, { + series: { + rangeSelectable: true, + }, + }); + + chart.on('rangeSelection', (selectedRange) => { + console.log(selectedRange); + }); + + return el; +}; + export const theme = () => { const { el } = createChart(budgetData, { series: { diff --git a/apps/chart/stories/line.stories.ts b/apps/chart/stories/line.stories.ts index ae6b4f6b2e..013ede07ee 100644 --- a/apps/chart/stories/line.stories.ts +++ b/apps/chart/stories/line.stories.ts @@ -290,6 +290,27 @@ export const coordinateZoomable = () => { return el; }; +export const rangeSelectable = () => { + const { el, chart } = createChart(randomData(30), { + series: { + zoomable: false, + rangeSelectable: true, + dataLabels: { + visible: true, + }, + }, + xAxis: { + pointOnColumn: false, + }, + }); + + chart.on('rangeSelection', (selectedRange) => { + console.log(selectedRange); + }); + + return el; +}; + export const animationDuration = () => { const { el } = createChart(temperatureData, { chart: { diff --git a/apps/chart/types/components/rangeSelection.d.ts b/apps/chart/types/components/rangeSelection.d.ts new file mode 100644 index 0000000000..d91a41e2d4 --- /dev/null +++ b/apps/chart/types/components/rangeSelection.d.ts @@ -0,0 +1,3 @@ +import { RectModel } from './series'; + +export type RangeSelectionModels = { selectionArea: RectModel[] }; diff --git a/apps/chart/types/eventEmitter.d.ts b/apps/chart/types/eventEmitter.d.ts index 852997fdb9..6f3bf2d75f 100644 --- a/apps/chart/types/eventEmitter.d.ts +++ b/apps/chart/types/eventEmitter.d.ts @@ -6,6 +6,7 @@ export type CustomEventType = | 'hoverSeries' | 'unhoverSeries' | 'zoom' - | 'resetZoom'; + | 'resetZoom' + | 'rangeSelection'; export type EventListener = (evt: any) => void; diff --git a/apps/chart/types/options.d.ts b/apps/chart/types/options.d.ts index 2e21e81f8d..be1228b02d 100644 --- a/apps/chart/types/options.d.ts +++ b/apps/chart/types/options.d.ts @@ -372,6 +372,7 @@ interface LineTypeSeriesOptions extends BaseSeriesOptions { showDot?: boolean; spline?: boolean; zoomable?: boolean; + rangeSelectable?: boolean; eventDetectType?: LineTypeEventDetectType; shift?: boolean; dataLabels?: Omit; @@ -425,6 +426,7 @@ type LineAreaChartSeriesOptions = { line?: Pick & BaseSeriesOptions; area?: Pick & BaseSeriesOptions; zoomable?: boolean; + rangeSelectable?: boolean; showDot?: boolean; spline?: boolean; shift?: boolean; @@ -485,7 +487,7 @@ export interface BarChartOptions extends BaseOptions { } export interface ColumnChartOptions extends BaseOptions { - series?: BoxSeriesOptions & { shift?: boolean }; + series?: BoxSeriesOptions & { shift?: boolean; rangeSelectable?: boolean }; yAxis?: BothSidesYAxisOptions; plot?: PlotOptions; legend?: NormalLegendOptions; diff --git a/apps/chart/types/store/store.d.ts b/apps/chart/types/store/store.d.ts index 86b729bcd5..a2e156c05b 100644 --- a/apps/chart/types/store/store.d.ts +++ b/apps/chart/types/store/store.d.ts @@ -407,6 +407,7 @@ export interface ChartState { scale: Scale; disabledSeries: string[]; series: Series; + selectionRange?: RangeDataType; zoomRange?: RangeDataType; shiftRange?: RangeDataType; axes: Axes; From 72d0075ed235ca21010b85ed5334dc845aefda2c Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Tue, 15 Nov 2022 09:41:01 +0900 Subject: [PATCH 2/6] feat: add rangeSelection to columnLineChart --- apps/chart/src/charts/columnLineChart.ts | 2 ++ apps/chart/types/options.d.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/apps/chart/src/charts/columnLineChart.ts b/apps/chart/src/charts/columnLineChart.ts index 75d4dbb8a9..c0d8c6f394 100644 --- a/apps/chart/src/charts/columnLineChart.ts +++ b/apps/chart/src/charts/columnLineChart.ts @@ -30,6 +30,7 @@ import HoveredSeries from '@src/component/hoveredSeries'; import DataLabels from '@src/component/dataLabels'; import Tooltip from '@src/component/tooltip'; import Background from '@src/component/background'; +import RangeSelection from '@src/component/rangeSelection'; import NoDataText from '@src/component/noDataText'; import * as basicBrush from '@src/brushes/basic'; @@ -171,6 +172,7 @@ export default class ColumnLineChart extends Chart { this.componentManager.add(HoveredSeries); this.componentManager.add(SelectedSeries); this.componentManager.add(DataLabels); + this.componentManager.add(RangeSelection); this.componentManager.add(Tooltip, { chartEl: this.el }); this.componentManager.add(NoDataText); diff --git a/apps/chart/types/options.d.ts b/apps/chart/types/options.d.ts index be1228b02d..7fbe227425 100644 --- a/apps/chart/types/options.d.ts +++ b/apps/chart/types/options.d.ts @@ -656,6 +656,7 @@ type ColumnLineChartSeriesOptions = { shift?: boolean; dataLabels?: DataLabelOptions; eventDetectType?: BoxTypeEventDetectType; + rangeSelectable?: boolean; } & BaseSeriesOptions; export interface ColumnLineChartOptions extends BaseOptions { From 339d29bcaac00f439cd3f4a84ae19701571343c0 Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Tue, 15 Nov 2022 09:41:11 +0900 Subject: [PATCH 3/6] feat: add rangeSelection on jsdoc --- apps/chart/src/charts/columnChart.ts | 3 ++- apps/chart/src/charts/lineAreaChart.ts | 1 + apps/chart/src/charts/lineChart.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/chart/src/charts/columnChart.ts b/apps/chart/src/charts/columnChart.ts index e696509168..3c34bf20b8 100644 --- a/apps/chart/src/charts/columnChart.ts +++ b/apps/chart/src/charts/columnChart.ts @@ -61,7 +61,8 @@ import { ColumnChartProps, SelectSeriesInfo } from '@t/charts'; * @param {number|string} [props.options.chart.width] - Chart width. 'auto' or if not write, the width of the parent container is followed. 'auto' or if not created, the width of the parent container is followed. * @param {number|string} [props.options.chart.height] - Chart height. 'auto' or if not write, the width of the parent container is followed. 'auto' or if not created, the height of the parent container is followed. * @param {Object} [props.options.series] - * @param {boolean} [props.options.series.selectable=false] - Whether to make selectable series or not. + * @param {boolean} [props.options.series.selectable=false] + * @param {boolean} [props.options.series.rangeSelectable=false] - Whether to use range selection feature or not. * @param {number} [props.options.series.barWidth] - Bar width. * @param {boolean} [props.options.series.diverging] - Whether to use diverging chart or not. * @param {Object} [props.options.series.stack] - Option to use the stack chart or, if so, what type of stack to use. diff --git a/apps/chart/src/charts/lineAreaChart.ts b/apps/chart/src/charts/lineAreaChart.ts index dbcbf51f1a..294c585de2 100644 --- a/apps/chart/src/charts/lineAreaChart.ts +++ b/apps/chart/src/charts/lineAreaChart.ts @@ -69,6 +69,7 @@ import { LineAreaChartProps, AddSeriesDataInfo, SelectSeriesInfo } from '@t/char * @param {Object} [props.options.series.line] - Options to be applied to the line chart. 'spline', 'showDot', 'dataLabels' is available. For specific information, refer to the {@link https://github.com/nhn/tui.chart|Line Chart guide} on github. * @param {Object} [props.options.series.area] - Options to be applied to the area chart. 'stack', 'spline', 'showDot', 'dataLabels' is available. For specific information, refer to the {@link https://github.com/nhn/tui.chart|Area Chart guide} on github. * @param {boolean} [props.options.series.zoomable=false] - Whether to use zoom feature or not. + * @param {boolean} [props.options.series.rangeSelectable=false] - Whether to use range selection feature or not. * @param {boolean} [props.options.series.showDot=false] - Whether to show dot or not. * @param {boolean} [props.options.series.spline=false] - Whether to make spline chart or not. * @param {boolean} [props.options.series.selectable=false] - Whether to make selectable series or not. diff --git a/apps/chart/src/charts/lineChart.ts b/apps/chart/src/charts/lineChart.ts index 78894068ec..90250ac06e 100644 --- a/apps/chart/src/charts/lineChart.ts +++ b/apps/chart/src/charts/lineChart.ts @@ -66,6 +66,7 @@ import { LineChartProps, SelectSeriesInfo } from '@t/charts'; * @param {boolean} [props.options.series.showDot=false] - Whether to show dot or not. * @param {boolean} [props.options.series.spline=false] - Whether to make spline chart or not. * @param {boolean} [props.options.series.zoomable=false] - Whether to use zoom feature or not. + * @param {boolean} [props.options.series.rangeSelectable=false] - Whether to use range selection feature or not. * @param {string} [props.options.series.eventDetectType] - Event detect type. 'near', 'nearest', 'grouped', 'point' is available. * @param {boolean} [props.options.series.shift=false] - Whether to use shift when addData or not. * @param {Object} [props.options.series.dataLabels] - Set the visibility, location, and formatting of dataLabel. For specific information, refer to the {@link https://github.com/nhn/tui.chart|DataLabels guide} on github. From 5ec8020d7d7a46c2b2075fed614592cdb577fa27 Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Tue, 15 Nov 2022 09:57:17 +0900 Subject: [PATCH 4/6] fix: type error --- apps/chart/src/component/rangeSelection.ts | 4 ++-- apps/chart/types/options.d.ts | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/chart/src/component/rangeSelection.ts b/apps/chart/src/component/rangeSelection.ts index b991353626..98d9079b00 100644 --- a/apps/chart/src/component/rangeSelection.ts +++ b/apps/chart/src/component/rangeSelection.ts @@ -6,7 +6,7 @@ import { sortNumber } from '@src/helpers/utils'; import { RangeSelectionModels } from '@t/components/rangeSelection'; import { AreaSeriesType, - BoxSeriesOptions, + ColumnChartBoxSeriesOptions, CoordinateDataType, LineSeriesType, LineTypeSeriesOptions, @@ -27,7 +27,7 @@ import { const DRAG_MIN_WIDTH = 15; type RangeSelectableSeries = Pick; -type RangeSelectableSeriesOptions = BoxSeriesOptions | LineTypeSeriesOptions; +type RangeSelectableSeriesOptions = ColumnChartBoxSeriesOptions | LineTypeSeriesOptions; export default class RangeSelection extends Component { models: RangeSelectionModels = { selectionArea: [] }; diff --git a/apps/chart/types/options.d.ts b/apps/chart/types/options.d.ts index 7fbe227425..5d689849e2 100644 --- a/apps/chart/types/options.d.ts +++ b/apps/chart/types/options.d.ts @@ -486,8 +486,13 @@ export interface BarChartOptions extends BaseOptions { theme?: BoxChartThemeOptions; } +export type ColumnChartBoxSeriesOptions = BoxSeriesOptions & { + shift?: boolean; + rangeSelectable?: boolean; +}; + export interface ColumnChartOptions extends BaseOptions { - series?: BoxSeriesOptions & { shift?: boolean; rangeSelectable?: boolean }; + series?: ColumnChartBoxSeriesOptions; yAxis?: BothSidesYAxisOptions; plot?: PlotOptions; legend?: NormalLegendOptions; From 0f3e626e1d45533a722b973b12d199d63bcc81c6 Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Tue, 15 Nov 2022 13:45:44 +0900 Subject: [PATCH 5/6] fix: apply review --- apps/chart/src/charts/columnChart.ts | 2 +- apps/chart/src/charts/columnLineChart.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/chart/src/charts/columnChart.ts b/apps/chart/src/charts/columnChart.ts index 3c34bf20b8..b86a944a90 100644 --- a/apps/chart/src/charts/columnChart.ts +++ b/apps/chart/src/charts/columnChart.ts @@ -61,7 +61,7 @@ import { ColumnChartProps, SelectSeriesInfo } from '@t/charts'; * @param {number|string} [props.options.chart.width] - Chart width. 'auto' or if not write, the width of the parent container is followed. 'auto' or if not created, the width of the parent container is followed. * @param {number|string} [props.options.chart.height] - Chart height. 'auto' or if not write, the width of the parent container is followed. 'auto' or if not created, the height of the parent container is followed. * @param {Object} [props.options.series] - * @param {boolean} [props.options.series.selectable=false] + * @param {boolean} [props.options.series.selectable=false] - Whether to make selectable series or not. * @param {boolean} [props.options.series.rangeSelectable=false] - Whether to use range selection feature or not. * @param {number} [props.options.series.barWidth] - Bar width. * @param {boolean} [props.options.series.diverging] - Whether to use diverging chart or not. diff --git a/apps/chart/src/charts/columnLineChart.ts b/apps/chart/src/charts/columnLineChart.ts index c0d8c6f394..bbc55bc2c7 100644 --- a/apps/chart/src/charts/columnLineChart.ts +++ b/apps/chart/src/charts/columnLineChart.ts @@ -82,6 +82,7 @@ function hasColumnLineUsingPointEventType(respondersModel: RespondersModel) { * @param {Object} [props.options.series.line] - Options to be applied to the line chart. 'spline', 'showDot', 'dataLabels' is available. For specific information, refer to the {@link https://github.com/nhn/tui.chart|Line Chart guide} on github. * @param {Object} [props.options.series.column] - Options to be applied to the column chart. 'barWidth', 'stack', 'dataLabels' is available. For specific information, refer to the {@link https://github.com/nhn/tui.chart|Column Chart guide} on github. * @param {boolean} [props.options.series.selectable=false] - Whether to make selectable series or not. + * @param {boolean} [props.options.series.rangeSelectable=false] - Whether to use range selection feature or not. * @param {string} [props.options.series.eventDetectType] - Event detect type. 'near', 'nearest', 'grouped', 'point' is available. * @param {boolean} [props.options.series.shift=false] - Whether to use shift when addData or not. * @param {Object} [props.options.series.dataLabels] - Set the visibility, location, and formatting of dataLabel. For specific information, refer to the {@link https://github.com/nhn/tui.chart|DataLabels guide} on github. From 45784374f3ea2679ce6339cad9a596c5cf17435d Mon Sep 17 00:00:00 2001 From: jinwoo-lee Date: Tue, 15 Nov 2022 15:59:01 +0900 Subject: [PATCH 6/6] fix: revert store/legend to wrong commit --- apps/chart/src/store/legend.ts | 51 +++++++++------------------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/apps/chart/src/store/legend.ts b/apps/chart/src/store/legend.ts index b66c9001fd..7324bfc2a4 100644 --- a/apps/chart/src/store/legend.ts +++ b/apps/chart/src/store/legend.ts @@ -75,15 +75,6 @@ type LegendSizeParams = { chart: Size; }; -type LegendInfoToSetIndexParams = { - legendData: LegendDataList; - rowCount: number; - columnCount: number; - legendCount: number; - verticalAlign: boolean; - itemHeight: number; -}; - const INITIAL_LEGEND_WIDTH = 100; const INITIAL_CIRCLE_LEGEND_WIDTH = 150; const COMPONENT_HEIGHT_EXCEPT_Y_AXIS = 100; @@ -93,24 +84,18 @@ const NUMBER_OF_BOTH_SIDES = 2; function recalculateLegendWhenHeightOverflows(params: LegendSizeParams, legendHeight: number) { const { legendWidths, itemHeight } = params; - const maxCountByColumn = Math.floor(legendHeight / itemHeight); - const columnCount = Math.ceil(legendWidths.length / maxCountByColumn); + const totalHeight = legendWidths.length * itemHeight; + const columnCount = Math.ceil(totalHeight / legendHeight); + const rowCount = legendWidths.length / columnCount; let legendWidth = 0; range(0, columnCount).forEach((count) => { - legendWidth += Math.max( - ...legendWidths.slice(count * maxCountByColumn, (count + 1) * maxCountByColumn) - ); + legendWidth += Math.max(...legendWidths.slice(count * rowCount, (count + 1) * rowCount)); }); legendWidth += LEGEND_ITEM_MARGIN_X * (columnCount - 1); - return { - legendWidth, - legendHeight: maxCountByColumn * itemHeight + padding.Y, - columnCount, - rowCount: maxCountByColumn, - }; + return { legendWidth, legendHeight: rowCount * itemHeight + padding.Y, columnCount, rowCount }; } function recalculateLegendWhenWidthOverflows(params: LegendSizeParams, prevLegendWidth: number) { @@ -461,16 +446,13 @@ function getNextColumnRowIndex(params: { return [rowIndex, columnIndex]; } -function setIndexToLegendData(legendInfoParams: LegendInfoToSetIndexParams) { - const { - legendData, - rowCount, - columnCount, - legendCount, - verticalAlign, - itemHeight, - } = legendInfoParams; - +function setIndexToLegendData( + legendData: LegendDataList, + rowCount: number, + columnCount: number, + legendCount: number, + verticalAlign: boolean +) { let columnIndex = 0; let rowIndex = 0; @@ -568,14 +550,7 @@ const legend: StoreModule = { circleLegendVisible, }); - setIndexToLegendData({ - legendData, - rowCount, - columnCount, - verticalAlign, - itemHeight, - legendCount: legendWidths.length, - }); + setIndexToLegendData(legendData, rowCount, columnCount, legendWidths.length, verticalAlign); extend(state.legend, { visible,