From 092aecd7f371e1e2d9d6426bcd8df9f5de5447f7 Mon Sep 17 00:00:00 2001 From: trash-and-fire <69399722+trash-and-fire@users.noreply.github.com> Date: Wed, 25 May 2022 02:34:51 +0300 Subject: [PATCH 1/7] apply series defaults --- packages/lib/src/internal/series.ts | 36 ++++++++++++++++------- packages/lib/src/internal/utils.ts | 45 +++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 10 deletions(-) diff --git a/packages/lib/src/internal/series.ts b/packages/lib/src/internal/series.ts index 4f35ba1..072023b 100644 --- a/packages/lib/src/internal/series.ts +++ b/packages/lib/src/internal/series.ts @@ -8,9 +8,10 @@ import { HistogramSeriesPartialOptions, LineSeriesPartialOptions, BaselineSeriesPartialOptions, + SeriesOptionsMap, } from 'lightweight-charts'; -import {ActionResult} from './utils'; +import {ActionResult, clone, merge} from './utils'; import {ChartActionResult} from './chart'; export interface AreaSeriesParams extends AreaSeriesPartialOptions { @@ -60,7 +61,7 @@ export type SeriesActionParams = export type SeriesActionResult = ActionResult & { subject(): ISeriesApi; alive(): boolean } export function series(target: ChartActionResult, params: T): SeriesActionResult { - let subject = createSeries(target.subject(), params); + let [subject, defaults] = createSeries(target.subject(), params); let data = params.reactive ? params.data : null; let destroyed = false; @@ -83,7 +84,7 @@ export function series(target: ChartActionResult, throw new TypeError('Can not change type of series in runtime. Report a bug please'); } - subject.applyOptions(nextOptions); + subject.applyOptions(merge(clone(defaults), nextOptions)); if (!nextReactive) { data = null; @@ -106,37 +107,52 @@ export function series(target: ChartActionResult, function createSeries( chart: IChartApi, params: SeriesActionParams -): ISeriesApi { +): [ + series: ISeriesApi, + defaults: SeriesOptionsMap[T['type']] +] { switch (params.type) { case 'Area': { const series = chart.addAreaSeries(omit(params)); + const defaults = series.options(); + series.applyOptions(omit(params)); series.setData(params.data); - return series; + return [series, defaults as SeriesOptionsMap[T['type']]]; } case 'Bar': { const series = chart.addBarSeries(omit(params)); + const defaults = series.options(); + series.applyOptions(omit(params)); series.setData(params.data); - return series; + return [series, defaults as SeriesOptionsMap[T['type']]]; } case 'Candlestick': { const series = chart.addCandlestickSeries(omit(params)); + const defaults = series.options(); + series.applyOptions(omit(params)); series.setData(params.data); - return series; + return [series, defaults as SeriesOptionsMap[T['type']]]; } case 'Histogram': { const series = chart.addHistogramSeries(omit(params)); + const defaults = series.options(); + series.applyOptions(omit(params)); series.setData(params.data); - return series; + return [series, defaults as SeriesOptionsMap[T['type']]]; } case 'Line': { const series = chart.addLineSeries(omit(params)); + const defaults = series.options(); + series.applyOptions(omit(params)); series.setData(params.data); - return series; + return [series, defaults as SeriesOptionsMap[T['type']]]; } case 'Baseline': { const series = chart.addBaselineSeries(omit(params)); + const defaults = series.options(); + series.applyOptions(omit(params)); series.setData(params.data); - return series; + return [series, defaults as SeriesOptionsMap[T['type']]]; } } } diff --git a/packages/lib/src/internal/utils.ts b/packages/lib/src/internal/utils.ts index 23c2e14..dc00fe1 100644 --- a/packages/lib/src/internal/utils.ts +++ b/packages/lib/src/internal/utils.ts @@ -5,6 +5,51 @@ export function ensure(value: T | null | undefined): T { return value; } +export function clone(object: T): T { + const source = object as any; + + if (source === null || typeof source !== 'object') { + return source; + } + + const result: any = Array.isArray(source) ? [] : {}; + + for (let key in source) { + if (!source.hasOwnProperty(key)) { + continue; + } + const value = source[key]; + + if (value !== null && typeof value === 'object') { + result[key] = clone(value); + } else { + result[key] = value; + } + } + + return result; +} + +export function merge(dest: Record, source: Record): Record { + for (const key in source) { + if (!source.hasOwnProperty(key)) { + continue + } + if (source[key] === undefined) { + continue; + } + + if (dest[key] === undefined || typeof source[key] !== 'object') { + dest[key] = source[key]; + } else { + merge(dest[key], source[key]); + } + } + + return dest; +} + + export interface ActionResult { update(params: T): void; destroy(): void; From ec3f92a842cee80be08c62da5abf06d5ae1f221f Mon Sep 17 00:00:00 2001 From: trash-and-fire <69399722+trash-and-fire@users.noreply.github.com> Date: Wed, 25 May 2022 03:32:30 +0300 Subject: [PATCH 2/7] area series options panel --- packages/demo/src/app.tsx | 2 +- .../controlled-area-series.tsx} | 273 ++++++++++-------- .../src/{ => terminal}/terminal.module.css | 0 packages/demo/src/terminal/terminal.tsx | 61 ++++ 4 files changed, 220 insertions(+), 116 deletions(-) rename packages/demo/src/{terminal.tsx => terminal/controlled-area-series.tsx} (51%) rename packages/demo/src/{ => terminal}/terminal.module.css (100%) create mode 100644 packages/demo/src/terminal/terminal.tsx diff --git a/packages/demo/src/app.tsx b/packages/demo/src/app.tsx index 32e28ec..283a226 100644 --- a/packages/demo/src/app.tsx +++ b/packages/demo/src/app.tsx @@ -1,6 +1,6 @@ import {BrowserRouter, Route, Routes} from 'react-router-dom'; import {Gallery} from './gallery'; -import {Terminal} from './terminal'; +import {Terminal} from './terminal/terminal'; function App() { return ( diff --git a/packages/demo/src/terminal.tsx b/packages/demo/src/terminal/controlled-area-series.tsx similarity index 51% rename from packages/demo/src/terminal.tsx rename to packages/demo/src/terminal/controlled-area-series.tsx index ad33496..dc26441 100644 --- a/packages/demo/src/terminal.tsx +++ b/packages/demo/src/terminal/controlled-area-series.tsx @@ -1,49 +1,140 @@ -import React, {useLayoutEffect} from 'react'; +import {folder, LevaInputs, useControls} from 'leva'; import {LastPriceAnimationMode, LineStyle, LineType, LineWidth, PriceLineSource} from 'lightweight-charts'; -import {Link} from 'react-router-dom'; -import {AreaSeries, Chart, PriceLine, PriceScale, TimeScale} from 'lightweight-charts-react-wrapper'; -import {folder, Leva, LevaInputs, useControls} from 'leva'; +import {ReactNode} from 'react'; +import {AreaSeries, AreaSeriesProps} from 'lightweight-charts-react-wrapper'; -import styles from './terminal.module.css'; - -export function Terminal() { - useLayoutEffect(() => { - document.documentElement.classList.add(styles['app-mode']); - return () => document.documentElement.classList.remove(styles['app-mode']); - },[]); - - const chart = useControls('Chart', { - width: 600, - height: 300, - }); +export interface ControlledAreaSeriesProps { + data: AreaSeriesProps['data']; + children?: ReactNode; +} +export function ControlledAreaSeries(props: ControlledAreaSeriesProps): JSX.Element { const {top, bottom, ...series} = useControls('Series', { - lastValueVisible: true, + visible: { + value: true, + label: 'Visible', + }, title: { type: LevaInputs.STRING, value: '', + label: 'Title', + }, + lastValueVisible: { + value: true, + label: 'Show last value', + }, + + priceScaleId: { + value: 'right', + label: 'Price scale', + }, + + topColor: { + type: LevaInputs.COLOR, + value: '#FF0000', + label: 'Top color', + disabled: true, + optional: true, + }, + bottomColor: { + type: LevaInputs.COLOR, + value: '#FF0000', + label: 'Bottom color', + disabled: true, + optional: true, + }, + lineColor: { + type: LevaInputs.COLOR, + value: '#FF0000', + label: 'Line color', + disabled: true, + optional: true, + }, + + lineWidth: { + type: LevaInputs.SELECT, + value: 3 as LineWidth, + label: 'Line width', + options: [1,2,3,4] as LineWidth[], + disabled: true, + optional: true, + }, + lineType: { + type: LevaInputs.SELECT, + value: LineType.Simple, + label: 'Line type', + options: { + Simple: LineType.Simple, + 'With steps': LineType.WithSteps, + }, disabled: true, optional: true, }, - priceScaleId: 'right', - visible: true, - priceLineVisible: false, + lineStyle: { + type: LevaInputs.SELECT, + value: LineStyle.Solid, + label: 'Line style', + options: { + Solid: LineStyle.Solid, + Dashed: LineStyle.Dashed, + 'Large dashed': LineStyle.LargeDashed, + Dotted: LineStyle.Dotted, + 'Sparse dotted': LineStyle.SparseDotted, + }, + disabled: true, + optional: true, + }, + + lastPriceAnimation: { + type: LevaInputs.SELECT, + value: LastPriceAnimationMode.Disabled, + label: 'Last price animation', + options: { + Disabled: LastPriceAnimationMode.Disabled, + Continuous: LastPriceAnimationMode.Continuous, + 'On data update': LastPriceAnimationMode.OnDataUpdate, + }, + optional: true, + disabled: true, + }, + + priceLineVisible: { + value: false, + label: 'Show price line:', + }, + priceLineSource: { type: LevaInputs.SELECT, value: PriceLineSource.LastBar, - options: [PriceLineSource.LastBar, PriceLineSource.LastVisible], + label: '-- source', + options: { + 'Last bar': PriceLineSource.LastBar, + 'Last visible': PriceLineSource.LastVisible, + }, + disabled: true, + optional: true, render: (get) => get('Series.priceLineVisible'), }, priceLineWidth: { type: LevaInputs.SELECT, value: 1 as LineWidth, + label: '-- width', options: [1,2,3,4] as LineWidth[], + disabled: true, + optional: true, render: (get) => get('Series.priceLineVisible'), }, priceLineStyle: { type: LevaInputs.SELECT, value: LineStyle.Solid, - options: [LineStyle.Solid, LineStyle.Dashed, LineStyle.LargeDashed, LineStyle.Dotted, LineStyle.SparseDotted], + label: '-- style', + options: { + Solid: LineStyle.Solid, + Dashed: LineStyle.Dashed, + 'Large dashed': LineStyle.LargeDashed, + Dotted: LineStyle.Dotted, + 'Sparse dotted': LineStyle.SparseDotted, + }, disabled: true, optional: true, render: (get) => get('Series.priceLineVisible'), @@ -51,14 +142,20 @@ export function Terminal() { priceLineColor: { type: LevaInputs.COLOR, value: '#FF0000', + label: '-- color', disabled: true, optional: true, render: (get) => get('Series.priceLineVisible'), }, - baseLineVisible: false, + + baseLineVisible: { + value: false, + label: 'Show base line:' + }, baseLineColor: { type: LevaInputs.COLOR, value: '#FF0000', + label: '-- color', disabled: true, optional: true, render: (get) => get('Series.baseLineVisible'), @@ -66,72 +163,42 @@ export function Terminal() { baseLineWidth: { type: LevaInputs.SELECT, value: 1 as LineWidth, + label: '-- width', options: [1,2,3,4] as LineWidth[], - render: (get) => get('Series.baseLineVisible'), - }, - baseLineStyle: { - type: LevaInputs.SELECT, - value: LineStyle.Solid, - options: [LineStyle.Solid, LineStyle.Dashed, LineStyle.LargeDashed, LineStyle.Dotted, LineStyle.SparseDotted], disabled: true, optional: true, render: (get) => get('Series.baseLineVisible'), }, - topColor: { - type: LevaInputs.COLOR, - value: '#FF0000', - disabled: true, - optional: true, - }, - bottomColor: { - type: LevaInputs.COLOR, - value: '#FF0000', - disabled: true, - optional: true, - }, - lineColor: { - type: LevaInputs.COLOR, - value: '#FF0000', - disabled: true, - optional: true, - }, - scaleMargins: folder({ - top: { - min: 0, - max: 1, - value: 0.1, - }, - bottom: { - min: 0, - max: 1, - value: 0.1, - }, - }), - lineStyle: { + baseLineStyle: { type: LevaInputs.SELECT, value: LineStyle.Solid, - options: [LineStyle.Solid, LineStyle.Dashed, LineStyle.LargeDashed, LineStyle.Dotted, LineStyle.SparseDotted], + label: '-- style', + options: { + Solid: LineStyle.Solid, + Dashed: LineStyle.Dashed, + 'Large dashed': LineStyle.LargeDashed, + Dotted: LineStyle.Dotted, + 'Sparse dotted': LineStyle.SparseDotted, + }, disabled: true, optional: true, + render: (get) => get('Series.baseLineVisible'), }, - lineWidth: { - type: LevaInputs.SELECT, - value: 3 as LineWidth, - options: [1,2,3,4] as LineWidth[], - }, - lineType: { - type: LevaInputs.SELECT, - value: LineType.Simple, - options: [LineType.Simple, LineType.WithSteps], + crosshairMarkerVisible: { + value: true, + label: 'Show crosshair marker:', }, - crosshairMarkerVisible: true, crosshairMarkerRadius: { value: 4, + label: '-- radius', + optional: true, + disabled: true, render: (get) => get('Series.crosshairMarkerVisible'), }, crosshairMarkerBorderColor: { type: LevaInputs.COLOR, value: '#FFFFFF', + label: '-- color', optional: true, disabled: true, render: (get) => get('Series.crosshairMarkerVisible'), @@ -139,55 +206,31 @@ export function Terminal() { crosshairMarkerBackgroundColor: { type: LevaInputs.COLOR, value: '#FFFFFF', + label: '-- background color', optional: true, disabled: true, render: (get) => get('Series.crosshairMarkerVisible'), }, - lastPriceAnimation: { - type: LevaInputs.SELECT, - value: LastPriceAnimationMode.Disabled, - options: [LastPriceAnimationMode.Disabled, LastPriceAnimationMode.Continuous, LastPriceAnimationMode.OnDataUpdate], - }, + + 'Scale margins (deprecated)': folder({ + top: { + min: 0, + max: 1, + value: 0.1, + }, + bottom: { + min: 0, + max: 1, + value: 0.1, + }, + }, { collapsed: true }), }); return ( -
-
- - Gallery - - - - - - - - -
-
- -
-
- ); + + ) } diff --git a/packages/demo/src/terminal.module.css b/packages/demo/src/terminal/terminal.module.css similarity index 100% rename from packages/demo/src/terminal.module.css rename to packages/demo/src/terminal/terminal.module.css diff --git a/packages/demo/src/terminal/terminal.tsx b/packages/demo/src/terminal/terminal.tsx new file mode 100644 index 0000000..3f88e25 --- /dev/null +++ b/packages/demo/src/terminal/terminal.tsx @@ -0,0 +1,61 @@ +import React, {useLayoutEffect} from 'react'; +import {LastPriceAnimationMode, LineStyle, LineType, LineWidth, PriceLineSource} from 'lightweight-charts'; +import {Link} from 'react-router-dom'; +import {AreaSeries, Chart, PriceLine, PriceScale, TimeScale} from 'lightweight-charts-react-wrapper'; +import {folder, Leva, LevaInputs, useControls} from 'leva'; + +import styles from './terminal.module.css'; +import {ControlledAreaSeries} from './controlled-area-series'; + +export function Terminal() { + useLayoutEffect(() => { + document.documentElement.classList.add(styles['app-mode']); + return () => document.documentElement.classList.remove(styles['app-mode']); + },[]); + + const chart = useControls('Chart', { + width: 600, + height: 300, + }); + + + + return ( +
+
+ + Gallery + + + + + + + + +
+
+ +
+
+ ); +} From 806f814f42e334aa91acfe112785a2e832944d6f Mon Sep 17 00:00:00 2001 From: trash-and-fire <69399722+trash-and-fire@users.noreply.github.com> Date: Wed, 25 May 2022 03:34:04 +0300 Subject: [PATCH 3/7] remove code --- packages/demo/src/terminal/terminal.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/demo/src/terminal/terminal.tsx b/packages/demo/src/terminal/terminal.tsx index 3f88e25..57d2711 100644 --- a/packages/demo/src/terminal/terminal.tsx +++ b/packages/demo/src/terminal/terminal.tsx @@ -1,12 +1,13 @@ import React, {useLayoutEffect} from 'react'; -import {LastPriceAnimationMode, LineStyle, LineType, LineWidth, PriceLineSource} from 'lightweight-charts'; +import {LineStyle} from 'lightweight-charts'; import {Link} from 'react-router-dom'; -import {AreaSeries, Chart, PriceLine, PriceScale, TimeScale} from 'lightweight-charts-react-wrapper'; -import {folder, Leva, LevaInputs, useControls} from 'leva'; +import {Chart, PriceLine, PriceScale, TimeScale} from 'lightweight-charts-react-wrapper'; +import {Leva, useControls} from 'leva'; -import styles from './terminal.module.css'; import {ControlledAreaSeries} from './controlled-area-series'; +import styles from './terminal.module.css'; + export function Terminal() { useLayoutEffect(() => { document.documentElement.classList.add(styles['app-mode']); From a4adee952b964536575eb5971184a19b26063fd0 Mon Sep 17 00:00:00 2001 From: trash-and-fire <69399722+trash-and-fire@users.noreply.github.com> Date: Thu, 26 May 2022 20:32:40 +0300 Subject: [PATCH 4/7] apply defaults for chart --- packages/lib/src/internal/chart.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/lib/src/internal/chart.ts b/packages/lib/src/internal/chart.ts index f7c3eaa..668f1b9 100644 --- a/packages/lib/src/internal/chart.ts +++ b/packages/lib/src/internal/chart.ts @@ -4,7 +4,7 @@ import { IChartApi, MouseEventHandler, } from 'lightweight-charts'; -import {ActionResult} from './utils'; +import {ActionResult, clone, merge} from './utils'; import {createChart} from 'lightweight-charts'; @@ -29,7 +29,11 @@ export function chart( let height = options?.height ?? 0; let destroyed = false; - const chart = createChart(node, options); + const chart = createChart(node); + // TODO: write an issue. Chart returns live collection of options. + const defaults = clone(chart.options()); + + chart.applyOptions(options); if (onClick) { chart.subscribeClick(onClick); @@ -54,7 +58,7 @@ export function chart( } = nextParams; if (nextOptions) { - chart.applyOptions(nextOptions); + chart.applyOptions(merge(clone(defaults), nextOptions)); if (nextOptions.width !== undefined && nextOptions.width !== width || nextOptions.height !== undefined && nextOptions.height !== height From 22bd1d2d1b91d811faa5e4e0b36b20af35c787af Mon Sep 17 00:00:00 2001 From: trash-and-fire <69399722+trash-and-fire@users.noreply.github.com> Date: Thu, 26 May 2022 20:33:18 +0300 Subject: [PATCH 5/7] chart control panel --- .../demo/src/terminal/controlled-chart.tsx | 572 ++++++++++++++++++ packages/demo/src/terminal/terminal.tsx | 16 +- 2 files changed, 577 insertions(+), 11 deletions(-) create mode 100644 packages/demo/src/terminal/controlled-chart.tsx diff --git a/packages/demo/src/terminal/controlled-chart.tsx b/packages/demo/src/terminal/controlled-chart.tsx new file mode 100644 index 0000000..d06646f --- /dev/null +++ b/packages/demo/src/terminal/controlled-chart.tsx @@ -0,0 +1,572 @@ +import {ReactNode} from 'react'; +import {useControls} from 'leva'; +import {Chart} from 'lightweight-charts-react-wrapper'; +import { + ColorType, + CrosshairMode, + HorzAlign, + LineStyle, + LineWidth, + TrackingModeExitMode, + VertAlign +} from 'lightweight-charts'; + +export interface ControlledChartProps { + children?: ReactNode; +} + +export function ControlledChart(props: ControlledChartProps): JSX.Element { + const size = useControls('Size', { + width: 600, + height: 300, + }); + + const watermark = useControls('Watermark', { + visible: { + value: false, + label: 'Visible', + }, + text: { + value: '', + label: 'Text', + render: (get) => get('Watermark.visible'), + }, + color: { + value: 'rgba(0, 0, 0, 0.5)', + label: '-- color', + optional: true, + disabled: true, + render: (get) => get('Watermark.visible'), + }, + fontSize: { + value: 48, label: '-- font size', + optional: true, + disabled: true, + render: (get) => get('Watermark.visible'), + }, + fontFamily: { + value: `'Trebuchet MS', Roboto, Ubuntu, sans-serif`, + label: '-- font family', + optional: true, + disabled: true, + render: (get) => get('Watermark.visible'), + + }, + fontStyle: { + value: '', + label: '-- font style', + optional: true, + disabled: true, + render: (get) => get('Watermark.visible'), + }, + horzAlign: { + value: 'center' as const, + label: '-- horizontal align', + options: ['left', 'right', 'center'] as const, + optional: true, + disabled: true, + render: (get) => get('Watermark.visible'), + }, + vertAlign: { + value: 'center' as const, + label: '-- vertical align', + options: ['left', 'right', 'center'] as const, + optional: true, + disabled: true, + render: (get) => get('Watermark.visible'), + }, + }) + + const { + backgroundType, + backgroundBottomColor, + backgroundTopColor, + backgroundColor, + ...layout + } = useControls('Layout', { + backgroundType: { + label: 'Background:', + value: ColorType.Solid, + options: { + 'Solid': ColorType.Solid, + 'Vertical gradient': ColorType.VerticalGradient, + } + }, + backgroundColor: { + label: '-- color', + value: '#FFFFFF', + render: (get) => get('Layout.backgroundType') === ColorType.Solid, + }, + backgroundTopColor: { + label: '-- top color', + value: '#FFFFFF', + render: (get) => get('Layout.backgroundType') === ColorType.VerticalGradient, + }, + backgroundBottomColor: { + label: '-- bottom color', + value: '#FFFFFF', + render: (get) => get('Layout.backgroundType') === ColorType.VerticalGradient, + }, + textColor: { + label: 'Text color', + value: '#292929', + optional: true, + disabled: true, + }, + fontSize: { + label: 'Font size', + value: 10, + optional: true, + disabled: true, + }, + fontFamily: { + label: 'Font family', + value: `'Trebuchet MS', Roboto, Ubuntu, sans-serif`, + optional: true, + disabled: true, + }, + }); + const background = backgroundType === ColorType.Solid ? { + type: ColorType.Solid, + color: backgroundColor, + } : { + type: ColorType.VerticalGradient, + topColor: backgroundTopColor, + bottomColor: backgroundBottomColor, + }; + // + // const leftPriceScale = useControls({ + // /** + // * Autoscaling is a feature that automatically adjusts a price scale to fit the visible range of data. + // * Note that overlay price scales are always auto-scaled. + // * + // * @defaultValue `true` + // */ + // autoScale: boolean, + // /** + // * Price scale mode. + // * + // * @defaultValue {@link PriceScaleMode.Normal} + // */ + // mode: PriceScaleMode, + // /** + // * Invert the price scale, so that a upwards trend is shown as a downwards trend and vice versa. + // * Affects both the price scale and the data on the chart. + // * + // * @defaultValue `false` + // */ + // invertScale: boolean, + // /** + // * Align price scale labels to prevent them from overlapping. + // * + // * @defaultValue `true` + // */ + // alignLabels: boolean, + // /** + // * Price scale margins. + // * + // * @defaultValue `{ bottom: 0.1, top: 0.2 }` + // * @example + // * ```js + // * chart.priceScale('right').applyOptions({ + // * scaleMargins: { + // * top: 0.8, + // * bottom: 0, + // * }, + // * }), + // * ``` + // */ + // scaleMargins: PriceScaleMargins, + // /** + // * Set true to draw a border between the price scale and the chart area. + // * + // * @defaultValue `true` + // */ + // borderVisible: boolean, + // /** + // * Price scale border color. + // * + // * @defaultValue `'#2B2B43'` + // */ + // borderColor: string, + // /** + // * Show top and bottom corner labels only if entire text is visible. + // * + // * @defaultValue `false` + // */ + // entireTextOnly: boolean, + // /** + // * Indicates if this price scale visible. Ignored by overlay price scales. + // * + // * @defaultValue `true` for the right price scale and `false` for the left + // */ + // visible: boolean, + // /** + // * Draw small horizontal line on price axis labels. + // * + // * @defaultValue `true` + // */ + // drawTicks: boolean, + // }) + // + // const timeScale = useControls({ + // /** + // * The margin space in bars from the right side of the chart. + // * + // * @defaultValue `0` + // */ + // rightOffset: number, + // /** + // * The space between bars in pixels. + // * + // * @defaultValue `6` + // */ + // barSpacing: number, + // /** + // * The minimum space between bars in pixels. + // * + // * @defaultValue `0.5` + // */ + // minBarSpacing: number, + // /** + // * Prevent scrolling to the left of the first bar. + // * + // * @defaultValue `false` + // */ + // fixLeftEdge: boolean, + // /** + // * Prevent scrolling to the right of the most recent bar. + // * + // * @defaultValue `false` + // */ + // fixRightEdge: boolean, + // /** + // * Prevent changing the visible time range during chart resizing. + // * + // * @defaultValue `false` + // */ + // lockVisibleTimeRangeOnResize: boolean, + // /** + // * Prevent the hovered bar from moving when scrolling. + // * + // * @defaultValue `false` + // */ + // rightBarStaysOnScroll: boolean, + // /** + // * Show the time scale border. + // * + // * @defaultValue `true` + // */ + // borderVisible: boolean, + // /** + // * The time scale border color. + // * + // * @defaultValue `'#2B2B43'` + // */ + // borderColor: string, + // /** + // * Show the time scale. + // * + // * @defaultValue `true` + // */ + // visible: boolean, + // /** + // * Show the time, not just the date, in the time scale and vertical crosshair label. + // * + // * @defaultValue `false` + // */ + // timeVisible: boolean, + // /** + // * Show seconds in the time scale and vertical crosshair label in `hh:mm:ss` format for intraday data. + // * + // * @defaultValue `true` + // */ + // secondsVisible: boolean, + // /** + // * Shift the visible range to the right (into the future) by the number of new bars when new data is added. + // * + // * Note that this only applies when the last bar is visible. + // * + // * @defaultValue `true` + // */ + // shiftVisibleRangeOnNewBar: boolean, + // /** + // * Tick marks formatter can be used to customize tick marks labels on the time axis. + // * + // * @defaultValue `undefined` + // */ + // tickMarkFormatter?: TickMarkFormatter, + // }) + // + const { + vertLineVisible, + vertLineColor, + vertLineStyle, + vertLineWidth, + vertLineLabelVisible, + vertLineLabelBackgroundColor, + horzLineVisible, + horzLineColor, + horzLineStyle, + horzLineWidth, + horzLineLabelVisible, + horzLineLabelBackgroundColor, + ...crosshair + } = useControls('Crosshair', { + mode: { + label: 'Mode', + value: CrosshairMode.Magnet, + options: { + 'Magnet': CrosshairMode.Magnet, + 'Normal': CrosshairMode.Normal, + }, + optional: true, + disabled: true, + }, + vertLineVisible: { + label: 'Show vertical line', + value: true, + }, + vertLineColor: { + label: '-- color', + value: '#FF0000', + optional: true, + disabled: true, + }, + vertLineStyle: { + label: '-- style', + value: LineStyle.Solid, + options: { + Solid: LineStyle.Solid, + Dashed: LineStyle.Dashed, + 'Large dashed': LineStyle.LargeDashed, + Dotted: LineStyle.Dotted, + 'Sparse dotted': LineStyle.SparseDotted, + }, + disabled: true, + optional: true, + render: (get) => get('Crosshair.vertLineVisible'), + }, + vertLineWidth: { + value: 1 as LineWidth, + label: '-- width', + options: [1,2,3,4] as LineWidth[], + disabled: true, + optional: true, + render: (get) => get('Crosshair.vertLineVisible'), + }, + vertLineLabelVisible: { + label: '-- show label', + value: true, + render: (get) => get('Crosshair.vertLineVisible'), + }, + vertLineLabelBackgroundColor: { + label: '-- label background', + value: '#FF0000', + optional: true, + disabled: true, + render: (get) => get('Crosshair.vertLineVisible'), + }, + horzLineVisible: { + label: 'Show horizontal line', + value: true, + }, + horzLineColor: { + label: '-- color', + value: '#FF0000', + optional: true, + disabled: true, + }, + horzLineStyle: { + label: '-- style', + value: LineStyle.Solid, + options: { + Solid: LineStyle.Solid, + Dashed: LineStyle.Dashed, + 'Large dashed': LineStyle.LargeDashed, + Dotted: LineStyle.Dotted, + 'Sparse dotted': LineStyle.SparseDotted, + }, + disabled: true, + optional: true, + render: (get) => get('Crosshair.horzLineVisible'), + }, + horzLineWidth: { + value: 1 as LineWidth, + label: '-- width', + options: [1,2,3,4] as LineWidth[], + disabled: true, + optional: true, + render: (get) => get('Crosshair.horzLineVisible'), + }, + horzLineLabelVisible: { + label: '-- show label', + value: true, + render: (get) => get('Crosshair.horzLineVisible'), + }, + horzLineLabelBackgroundColor: { + label: '-- label background', + value: '#FF0000', + optional: true, + disabled: true, + render: (get) => get('Crosshair.horzLineVisible'), + }, + }) + + const vertLine = { + visible: vertLineVisible, + color: vertLineColor, + style: vertLineStyle, + width: vertLineWidth, + labelVisible: vertLineLabelVisible, + labelBackgroundColor: vertLineLabelBackgroundColor, + }; + + const horzLine = { + visible: horzLineVisible, + color: horzLineColor, + style: horzLineStyle, + width: horzLineWidth, + labelVisible: horzLineLabelVisible, + labelBackgroundColor: horzLineLabelBackgroundColor, + }; + // + // const grid = useControls({ + // /** + // * Vertical grid line options. + // */ + // vertLines: GridLineOptions, + // /** + // * Horizontal grid line options. + // */ + // horzLines: GridLineOptions, + // }) + // + // const localization = useControls({ + // /** + // * Current locale used to format dates. Uses the browser's language settings by default. + // * + // * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation + // * @defaultValue `navigator.language` + // */ + // locale: string, + // /** + // * Override formatting of the price scale crosshair label. Can be used for cases that can't be covered with built-in price formats. + // * + // * @see {@link PriceFormatCustom} + // * @defaultValue `undefined` + // */ + // priceFormatter?: PriceFormatterFn, + // /** + // * Override formatting of the time scale crosshair label. + // * + // * @defaultValue `undefined` + // */ + // timeFormatter?: TimeFormatterFn, + // /** + // * Date formatting string. + // * + // * Can contain `yyyy`, `yy`, `MMMM`, `MMM`, `MM` and `dd` literals which will be replaced with corresponding date's value. + // * + // * Ignored if {@link timeFormatter} has been specified. + // * + // * @defaultValue `'dd MMM \'yy'` + // */ + // dateFormat: string, + // }) + // + // const handleScroll = useControls({ + // /** + // * Enable scrolling with the mouse wheel. + // * + // * @defaultValue `true` + // */ + // mouseWheel: boolean, + // /** + // * Enable scrolling by holding down the left mouse button and moving the mouse. + // * + // * @defaultValue `true` + // */ + // pressedMouseMove: boolean, + // /** + // * Enable horizontal touch scrolling. + // * + // * When enabled the chart handles touch gestures that would normally scroll the webpage horizontally. + // * + // * @defaultValue `true` + // */ + // horzTouchDrag: boolean, + // /** + // * Enable vertical touch scrolling. + // * + // * When enabled the chart handles touch gestures that would normally scroll the webpage vertically. + // * + // * @defaultValue `true` + // */ + // vertTouchDrag: boolean, + // }) + // + // const handleScale = useControls({ + // /** + // * Enable scaling with the mouse wheel. + // * + // * @defaultValue `true` + // */ + // mouseWheel: boolean, + // /** + // * Enable scaling with pinch/zoom gestures. + // * + // * @defaultValue `true` + // */ + // pinch: boolean, + // /** + // * Enable scaling the price and/or time scales by holding down the left mouse button and moving the mouse. + // */ + // axisPressedMouseMove: AxisPressedMouseMoveOptions | boolean, + // /** + // * Enable resetting scaling by double-clicking the left mouse button. + // * + // * @defaultValue `true` + // */ + // axisDoubleClickReset: boolean, + // }) + // + // const kineticScroll = useControls({ + // /** + // * Enable kinetic scroll with touch gestures. + // * + // * @defaultValue `true` + // */ + // touch: boolean, + // /** + // * Enable kinetic scroll with the mouse. + // * + // * @defaultValue `false` + // */ + // mouse: boolean, + // }) + // + const trackingMode = useControls('Tracking Mode', { + exitMode: { + label: 'Exit mode', + value: TrackingModeExitMode.OnNextTap, + options: { + 'On next tap': TrackingModeExitMode.OnNextTap, + 'On touch end': TrackingModeExitMode.OnTouchEnd, + }, + optional: true, + disabled: true, + }, + }) + + return ( + + ); +} diff --git a/packages/demo/src/terminal/terminal.tsx b/packages/demo/src/terminal/terminal.tsx index 57d2711..68d2dd0 100644 --- a/packages/demo/src/terminal/terminal.tsx +++ b/packages/demo/src/terminal/terminal.tsx @@ -1,10 +1,11 @@ import React, {useLayoutEffect} from 'react'; import {LineStyle} from 'lightweight-charts'; import {Link} from 'react-router-dom'; -import {Chart, PriceLine, PriceScale, TimeScale} from 'lightweight-charts-react-wrapper'; -import {Leva, useControls} from 'leva'; +import {PriceLine, PriceScale, TimeScale} from 'lightweight-charts-react-wrapper'; +import {Leva} from 'leva'; import {ControlledAreaSeries} from './controlled-area-series'; +import {ControlledChart} from './controlled-chart'; import styles from './terminal.module.css'; @@ -14,20 +15,13 @@ export function Terminal() { return () => document.documentElement.classList.remove(styles['app-mode']); },[]); - const chart = useControls('Chart', { - width: 600, - height: 300, - }); - - - return (
Gallery - + - +
From 50e1a05b1fdeb08f338c17149955bfd1139304ac Mon Sep 17 00:00:00 2001 From: trash-and-fire <69399722+trash-and-fire@users.noreply.github.com> Date: Thu, 26 May 2022 20:44:56 +0300 Subject: [PATCH 6/7] add more data --- packages/demo/src/terminal/data/line-data.ts | 152 +++++++++++++++++++ packages/demo/src/terminal/terminal.tsx | 16 +- 2 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 packages/demo/src/terminal/data/line-data.ts diff --git a/packages/demo/src/terminal/data/line-data.ts b/packages/demo/src/terminal/data/line-data.ts new file mode 100644 index 0000000..8960eef --- /dev/null +++ b/packages/demo/src/terminal/data/line-data.ts @@ -0,0 +1,152 @@ +export const data = [ + {time: '2018-10-19', value: 26.19}, + {time: '2018-10-22', value: 25.87}, + {time: '2018-10-23', value: 25.83}, + {time: '2018-10-24', value: 25.78}, + {time: '2018-10-25', value: 25.82}, + {time: '2018-10-26', value: 25.81}, + {time: '2018-10-29', value: 25.82}, + {time: '2018-10-30', value: 25.71}, + {time: '2018-10-31', value: 25.82}, + {time: '2018-11-01', value: 25.72}, + {time: '2018-11-02', value: 25.74}, + {time: '2018-11-05', value: 25.81}, + {time: '2018-11-06', value: 25.75}, + {time: '2018-11-07', value: 25.73}, + {time: '2018-11-08', value: 25.75}, + {time: '2018-11-09', value: 25.75}, + {time: '2018-11-12', value: 25.76}, + {time: '2018-11-13', value: 25.80}, + {time: '2018-11-14', value: 25.77}, + {time: '2018-11-15', value: 25.75}, + {time: '2018-11-16', value: 25.75}, + {time: '2018-11-19', value: 25.75}, + {time: '2018-11-20', value: 25.72}, + {time: '2018-11-21', value: 25.78}, + {time: '2018-11-23', value: 25.72}, + {time: '2018-11-26', value: 25.78}, + {time: '2018-11-27', value: 25.85}, + {time: '2018-11-28', value: 25.85}, + {time: '2018-11-29', value: 25.55}, + {time: '2018-11-30', value: 25.41}, + {time: '2018-12-03', value: 25.41}, + {time: '2018-12-04', value: 25.42}, + {time: '2018-12-06', value: 25.33}, + {time: '2018-12-07', value: 25.39}, + {time: '2018-12-10', value: 25.32}, + {time: '2018-12-11', value: 25.48}, + {time: '2018-12-12', value: 25.39}, + {time: '2018-12-13', value: 25.45}, + {time: '2018-12-14', value: 25.52}, + {time: '2018-12-17', value: 25.38}, + {time: '2018-12-18', value: 25.36}, + {time: '2018-12-19', value: 25.65}, + {time: '2018-12-20', value: 25.70}, + {time: '2018-12-21', value: 25.66}, + {time: '2018-12-24', value: 25.66}, + {time: '2018-12-26', value: 25.65}, + {time: '2018-12-27', value: 25.66}, + {time: '2018-12-28', value: 25.68}, + {time: '2018-12-31', value: 25.77}, + {time: '2019-01-02', value: 25.72}, + {time: '2019-01-03', value: 25.69}, + {time: '2019-01-04', value: 25.71}, + {time: '2019-01-07', value: 25.72}, + {time: '2019-01-08', value: 25.72}, + {time: '2019-01-09', value: 25.66}, + {time: '2019-01-10', value: 25.85}, + {time: '2019-01-11', value: 25.92}, + {time: '2019-01-14', value: 25.94}, + {time: '2019-01-15', value: 25.95}, + {time: '2019-01-16', value: 26.00}, + {time: '2019-01-17', value: 25.99}, + {time: '2019-01-18', value: 25.60}, + {time: '2019-01-22', value: 25.81}, + {time: '2019-01-23', value: 25.70}, + {time: '2019-01-24', value: 25.74}, + {time: '2019-01-25', value: 25.80}, + {time: '2019-01-28', value: 25.83}, + {time: '2019-01-29', value: 25.70}, + {time: '2019-01-30', value: 25.78}, + {time: '2019-01-31', value: 25.35}, + {time: '2019-02-01', value: 25.60}, + {time: '2019-02-04', value: 25.65}, + {time: '2019-02-05', value: 25.73}, + {time: '2019-02-06', value: 25.71}, + {time: '2019-02-07', value: 25.71}, + {time: '2019-02-08', value: 25.72}, + {time: '2019-02-11', value: 25.76}, + {time: '2019-02-12', value: 25.84}, + {time: '2019-02-13', value: 25.85}, + {time: '2019-02-14', value: 25.87}, + {time: '2019-02-15', value: 25.89}, + {time: '2019-02-19', value: 25.90}, + {time: '2019-02-20', value: 25.92}, + {time: '2019-02-21', value: 25.96}, + {time: '2019-02-22', value: 26.00}, + {time: '2019-02-25', value: 25.93}, + {time: '2019-02-26', value: 25.92}, + {time: '2019-02-27', value: 25.67}, + {time: '2019-02-28', value: 25.79}, + {time: '2019-03-01', value: 25.86}, + {time: '2019-03-04', value: 25.94}, + {time: '2019-03-05', value: 26.02}, + {time: '2019-03-06', value: 25.95}, + {time: '2019-03-07', value: 25.89}, + {time: '2019-03-08', value: 25.94}, + {time: '2019-03-11', value: 25.91}, + {time: '2019-03-12', value: 25.92}, + {time: '2019-03-13', value: 26.00}, + {time: '2019-03-14', value: 26.05}, + {time: '2019-03-15', value: 26.11}, + {time: '2019-03-18', value: 26.10}, + {time: '2019-03-19', value: 25.98}, + {time: '2019-03-20', value: 26.11}, + {time: '2019-03-21', value: 26.12}, + {time: '2019-03-22', value: 25.88}, + {time: '2019-03-25', value: 25.85}, + {time: '2019-03-26', value: 25.72}, + {time: '2019-03-27', value: 25.73}, + {time: '2019-03-28', value: 25.80}, + {time: '2019-03-29', value: 25.77}, + {time: '2019-04-01', value: 26.06}, + {time: '2019-04-02', value: 25.93}, + {time: '2019-04-03', value: 25.95}, + {time: '2019-04-04', value: 26.06}, + {time: '2019-04-05', value: 26.16}, + {time: '2019-04-08', value: 26.12}, + {time: '2019-04-09', value: 26.07}, + {time: '2019-04-10', value: 26.13}, + {time: '2019-04-11', value: 26.04}, + {time: '2019-04-12', value: 26.04}, + {time: '2019-04-15', value: 26.05}, + {time: '2019-04-16', value: 26.01}, + {time: '2019-04-17', value: 26.09}, + {time: '2019-04-18', value: 26.00}, + {time: '2019-04-22', value: 26.00}, + {time: '2019-04-23', value: 26.06}, + {time: '2019-04-24', value: 26.00}, + {time: '2019-04-25', value: 25.81}, + {time: '2019-04-26', value: 25.88}, + {time: '2019-04-29', value: 25.91}, + {time: '2019-04-30', value: 25.90}, + {time: '2019-05-01', value: 26.02}, + {time: '2019-05-02', value: 25.97}, + {time: '2019-05-03', value: 26.02}, + {time: '2019-05-06', value: 26.03}, + {time: '2019-05-07', value: 26.04}, + {time: '2019-05-08', value: 26.05}, + {time: '2019-05-09', value: 26.05}, + {time: '2019-05-10', value: 26.08}, + {time: '2019-05-13', value: 26.05}, + {time: '2019-05-14', value: 26.01}, + {time: '2019-05-15', value: 26.03}, + {time: '2019-05-16', value: 26.14}, + {time: '2019-05-17', value: 26.09}, + {time: '2019-05-20', value: 26.01}, + {time: '2019-05-21', value: 26.12}, + {time: '2019-05-22', value: 26.15}, + {time: '2019-05-23', value: 26.18}, + {time: '2019-05-24', value: 26.16}, + {time: '2019-05-28', value: 26.23}, +]; diff --git a/packages/demo/src/terminal/terminal.tsx b/packages/demo/src/terminal/terminal.tsx index 68d2dd0..5ecfa7d 100644 --- a/packages/demo/src/terminal/terminal.tsx +++ b/packages/demo/src/terminal/terminal.tsx @@ -6,6 +6,7 @@ import {Leva} from 'leva'; import {ControlledAreaSeries} from './controlled-area-series'; import {ControlledChart} from './controlled-chart'; +import {data} from './data/line-data'; import styles from './terminal.module.css'; @@ -24,21 +25,10 @@ export function Terminal() { - + Date: Thu, 26 May 2022 22:53:05 +0300 Subject: [PATCH 7/7] more chart controls --- .../demo/src/terminal/controlled-chart.tsx | 595 ++++++++++-------- 1 file changed, 336 insertions(+), 259 deletions(-) diff --git a/packages/demo/src/terminal/controlled-chart.tsx b/packages/demo/src/terminal/controlled-chart.tsx index d06646f..1a2141e 100644 --- a/packages/demo/src/terminal/controlled-chart.tsx +++ b/packages/demo/src/terminal/controlled-chart.tsx @@ -8,7 +8,7 @@ import { LineStyle, LineWidth, TrackingModeExitMode, - VertAlign + VertAlign, } from 'lightweight-charts'; export interface ControlledChartProps { @@ -16,124 +16,10 @@ export interface ControlledChartProps { } export function ControlledChart(props: ControlledChartProps): JSX.Element { - const size = useControls('Size', { - width: 600, - height: 300, - }); - - const watermark = useControls('Watermark', { - visible: { - value: false, - label: 'Visible', - }, - text: { - value: '', - label: 'Text', - render: (get) => get('Watermark.visible'), - }, - color: { - value: 'rgba(0, 0, 0, 0.5)', - label: '-- color', - optional: true, - disabled: true, - render: (get) => get('Watermark.visible'), - }, - fontSize: { - value: 48, label: '-- font size', - optional: true, - disabled: true, - render: (get) => get('Watermark.visible'), - }, - fontFamily: { - value: `'Trebuchet MS', Roboto, Ubuntu, sans-serif`, - label: '-- font family', - optional: true, - disabled: true, - render: (get) => get('Watermark.visible'), - - }, - fontStyle: { - value: '', - label: '-- font style', - optional: true, - disabled: true, - render: (get) => get('Watermark.visible'), - }, - horzAlign: { - value: 'center' as const, - label: '-- horizontal align', - options: ['left', 'right', 'center'] as const, - optional: true, - disabled: true, - render: (get) => get('Watermark.visible'), - }, - vertAlign: { - value: 'center' as const, - label: '-- vertical align', - options: ['left', 'right', 'center'] as const, - optional: true, - disabled: true, - render: (get) => get('Watermark.visible'), - }, - }) - - const { - backgroundType, - backgroundBottomColor, - backgroundTopColor, - backgroundColor, - ...layout - } = useControls('Layout', { - backgroundType: { - label: 'Background:', - value: ColorType.Solid, - options: { - 'Solid': ColorType.Solid, - 'Vertical gradient': ColorType.VerticalGradient, - } - }, - backgroundColor: { - label: '-- color', - value: '#FFFFFF', - render: (get) => get('Layout.backgroundType') === ColorType.Solid, - }, - backgroundTopColor: { - label: '-- top color', - value: '#FFFFFF', - render: (get) => get('Layout.backgroundType') === ColorType.VerticalGradient, - }, - backgroundBottomColor: { - label: '-- bottom color', - value: '#FFFFFF', - render: (get) => get('Layout.backgroundType') === ColorType.VerticalGradient, - }, - textColor: { - label: 'Text color', - value: '#292929', - optional: true, - disabled: true, - }, - fontSize: { - label: 'Font size', - value: 10, - optional: true, - disabled: true, - }, - fontFamily: { - label: 'Font family', - value: `'Trebuchet MS', Roboto, Ubuntu, sans-serif`, - optional: true, - disabled: true, - }, - }); - const background = backgroundType === ColorType.Solid ? { - type: ColorType.Solid, - color: backgroundColor, - } : { - type: ColorType.VerticalGradient, - topColor: backgroundTopColor, - bottomColor: backgroundBottomColor, - }; + const size = useSizeControls('Size'); + const watermark = useWatermarkControls('Watermark'); + const layout = useLayoutControls('Layout'); + const crosshair = useCrosshairControls('Crosshair'); // // const leftPriceScale = useControls({ // /** @@ -298,6 +184,161 @@ export function ControlledChart(props: ControlledChartProps): JSX.Element { // tickMarkFormatter?: TickMarkFormatter, // }) // + + const grid = useGridControls('Grid'); + const localization = useLocalizationControls('Localization'); + const handleScroll = useHandleScrollControls('Handle scroll'); + const handleScale = useHandleScaleControls('Handle scale'); + const kineticScroll = useKineticScrollControls('Kinetic scroll'); + const trackingMode = useTrackingModeControls('Tracking mode'); + + return ( + + ); +} + +function useSizeControls(name: string) { + return useControls(name, { + width: 600, + height: 300, + }); +} + +function useWatermarkControls(name: string) { + const watermark = useControls(name, { + visible: { + value: false, + label: 'Visible', + }, + text: { + value: '', + label: 'Text', + render: (get) => get(`${name}.visible`), + }, + color: { + value: 'rgba(0, 0, 0, 0.5)', + label: '-- color', + optional: true, + disabled: true, + render: (get) => get(`${name}.visible`), + }, + fontSize: { + value: 48, label: '-- font size', + optional: true, + disabled: true, + render: (get) => get(`${name}.visible`), + }, + fontFamily: { + value: `'Trebuchet MS', Roboto, Ubuntu, sans-serif`, + label: '-- font family', + optional: true, + disabled: true, + render: (get) => get(`${name}.visible`), + + }, + fontStyle: { + value: '', + label: '-- font style', + optional: true, + disabled: true, + render: (get) => get(`${name}.visible`), + }, + horzAlign: { + value: 'center' as const, + label: '-- horizontal align', + options: ['left', 'right', 'center'] as const, + optional: true, + disabled: true, + render: (get) => get(`${name}.visible`), + }, + vertAlign: { + value: 'center' as const, + label: '-- vertical align', + options: ['left', 'right', 'center'] as const, + optional: true, + disabled: true, + render: (get) => get(`${name}.visible`), + }, + }); + + return {...watermark, vertAlign: watermark.vertAlign as VertAlign, horzAlign: watermark.horzAlign as HorzAlign}; +} + +function useLayoutControls(name: string) { + const { + backgroundType, + backgroundBottomColor, + backgroundTopColor, + backgroundColor, + ...layout + } = useControls(name, { + backgroundType: { + label: 'Background:', + value: ColorType.Solid, + options: { + 'Solid': ColorType.Solid, + 'Vertical gradient': ColorType.VerticalGradient, + } + }, + backgroundColor: { + label: '-- color', + value: '#FFFFFF', + render: (get) => get(`${name}.backgroundType`) === ColorType.Solid, + }, + backgroundTopColor: { + label: '-- top color', + value: '#FFFFFF', + render: (get) => get(`${name}.backgroundType`) === ColorType.VerticalGradient, + }, + backgroundBottomColor: { + label: '-- bottom color', + value: '#FFFFFF', + render: (get) => get(`${name}.backgroundType`) === ColorType.VerticalGradient, + }, + textColor: { + label: 'Text color', + value: '#292929', + optional: true, + disabled: true, + }, + fontSize: { + label: 'Font size', + value: 10, + optional: true, + disabled: true, + }, + fontFamily: { + label: 'Font family', + value: `'Trebuchet MS', Roboto, Ubuntu, sans-serif`, + optional: true, + disabled: true, + }, + }); + const background = backgroundType === ColorType.Solid ? { + type: ColorType.Solid, + color: backgroundColor, + } : { + type: ColorType.VerticalGradient, + topColor: backgroundTopColor, + bottomColor: backgroundBottomColor, + }; + + return {...layout, background}; +} + +function useCrosshairControls(name: string) { const { vertLineVisible, vertLineColor, @@ -312,7 +353,7 @@ export function ControlledChart(props: ControlledChartProps): JSX.Element { horzLineLabelVisible, horzLineLabelBackgroundColor, ...crosshair - } = useControls('Crosshair', { + } = useControls(name, { mode: { label: 'Mode', value: CrosshairMode.Magnet, @@ -345,27 +386,27 @@ export function ControlledChart(props: ControlledChartProps): JSX.Element { }, disabled: true, optional: true, - render: (get) => get('Crosshair.vertLineVisible'), + render: (get) => get(`${name}.vertLineVisible`), }, vertLineWidth: { value: 1 as LineWidth, label: '-- width', - options: [1,2,3,4] as LineWidth[], + options: [1, 2, 3, 4] as LineWidth[], disabled: true, optional: true, - render: (get) => get('Crosshair.vertLineVisible'), + render: (get) => get(`${name}.vertLineVisible`), }, vertLineLabelVisible: { label: '-- show label', value: true, - render: (get) => get('Crosshair.vertLineVisible'), + render: (get) => get(`${name}.vertLineVisible`), }, vertLineLabelBackgroundColor: { label: '-- label background', value: '#FF0000', optional: true, disabled: true, - render: (get) => get('Crosshair.vertLineVisible'), + render: (get) => get(`${name}.vertLineVisible`), }, horzLineVisible: { label: 'Show horizontal line', @@ -389,30 +430,30 @@ export function ControlledChart(props: ControlledChartProps): JSX.Element { }, disabled: true, optional: true, - render: (get) => get('Crosshair.horzLineVisible'), + render: (get) => get(`${name}.horzLineVisible`), }, horzLineWidth: { value: 1 as LineWidth, label: '-- width', - options: [1,2,3,4] as LineWidth[], + options: [1, 2, 3, 4] as LineWidth[], disabled: true, optional: true, - render: (get) => get('Crosshair.horzLineVisible'), + render: (get) => get(`${name}.horzLineVisible`), }, horzLineLabelVisible: { label: '-- show label', value: true, - render: (get) => get('Crosshair.horzLineVisible'), + render: (get) => get(`${name}.horzLineVisible`), }, horzLineLabelBackgroundColor: { label: '-- label background', value: '#FF0000', optional: true, disabled: true, - render: (get) => get('Crosshair.horzLineVisible'), + render: (get) => get(`${name}.horzLineVisible`), }, }) - + const vertLine = { visible: vertLineVisible, color: vertLineColor, @@ -421,7 +462,7 @@ export function ControlledChart(props: ControlledChartProps): JSX.Element { labelVisible: vertLineLabelVisible, labelBackgroundColor: vertLineLabelBackgroundColor, }; - + const horzLine = { visible: horzLineVisible, color: horzLineColor, @@ -430,123 +471,12 @@ export function ControlledChart(props: ControlledChartProps): JSX.Element { labelVisible: horzLineLabelVisible, labelBackgroundColor: horzLineLabelBackgroundColor, }; - // - // const grid = useControls({ - // /** - // * Vertical grid line options. - // */ - // vertLines: GridLineOptions, - // /** - // * Horizontal grid line options. - // */ - // horzLines: GridLineOptions, - // }) - // - // const localization = useControls({ - // /** - // * Current locale used to format dates. Uses the browser's language settings by default. - // * - // * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation - // * @defaultValue `navigator.language` - // */ - // locale: string, - // /** - // * Override formatting of the price scale crosshair label. Can be used for cases that can't be covered with built-in price formats. - // * - // * @see {@link PriceFormatCustom} - // * @defaultValue `undefined` - // */ - // priceFormatter?: PriceFormatterFn, - // /** - // * Override formatting of the time scale crosshair label. - // * - // * @defaultValue `undefined` - // */ - // timeFormatter?: TimeFormatterFn, - // /** - // * Date formatting string. - // * - // * Can contain `yyyy`, `yy`, `MMMM`, `MMM`, `MM` and `dd` literals which will be replaced with corresponding date's value. - // * - // * Ignored if {@link timeFormatter} has been specified. - // * - // * @defaultValue `'dd MMM \'yy'` - // */ - // dateFormat: string, - // }) - // - // const handleScroll = useControls({ - // /** - // * Enable scrolling with the mouse wheel. - // * - // * @defaultValue `true` - // */ - // mouseWheel: boolean, - // /** - // * Enable scrolling by holding down the left mouse button and moving the mouse. - // * - // * @defaultValue `true` - // */ - // pressedMouseMove: boolean, - // /** - // * Enable horizontal touch scrolling. - // * - // * When enabled the chart handles touch gestures that would normally scroll the webpage horizontally. - // * - // * @defaultValue `true` - // */ - // horzTouchDrag: boolean, - // /** - // * Enable vertical touch scrolling. - // * - // * When enabled the chart handles touch gestures that would normally scroll the webpage vertically. - // * - // * @defaultValue `true` - // */ - // vertTouchDrag: boolean, - // }) - // - // const handleScale = useControls({ - // /** - // * Enable scaling with the mouse wheel. - // * - // * @defaultValue `true` - // */ - // mouseWheel: boolean, - // /** - // * Enable scaling with pinch/zoom gestures. - // * - // * @defaultValue `true` - // */ - // pinch: boolean, - // /** - // * Enable scaling the price and/or time scales by holding down the left mouse button and moving the mouse. - // */ - // axisPressedMouseMove: AxisPressedMouseMoveOptions | boolean, - // /** - // * Enable resetting scaling by double-clicking the left mouse button. - // * - // * @defaultValue `true` - // */ - // axisDoubleClickReset: boolean, - // }) - // - // const kineticScroll = useControls({ - // /** - // * Enable kinetic scroll with touch gestures. - // * - // * @defaultValue `true` - // */ - // touch: boolean, - // /** - // * Enable kinetic scroll with the mouse. - // * - // * @defaultValue `false` - // */ - // mouse: boolean, - // }) - // - const trackingMode = useControls('Tracking Mode', { + + return {...crosshair, vertLine, horzLine}; +} + +function useTrackingModeControls(name: string) { + return useControls(name, { exitMode: { label: 'Exit mode', value: TrackingModeExitMode.OnNextTap, @@ -558,15 +488,162 @@ export function ControlledChart(props: ControlledChartProps): JSX.Element { disabled: true, }, }) +} - return ( - - ); +function useGridControls(name: string) { + const grid = useControls(name, { + vertLinesVisible: { + label: 'Show vertical lines:', + value: true, + }, + vertLinesColor: { + label: '-- color', + value: '#FF0000', + optional: true, + disabled: true, + render: (get) => get(`${name}.vertLinesVisible`), + }, + vertLinesStyle: { + label: '-- style', + value: LineStyle.Dashed, + options: { + Solid: LineStyle.Solid, + Dashed: LineStyle.Dashed, + 'Large dashed': LineStyle.LargeDashed, + Dotted: LineStyle.Dotted, + 'Sparse dotted': LineStyle.SparseDotted, + }, + disabled: true, + optional: true, + render: (get) => get(`${name}.vertLinesVisible`), + }, + + horzLinesVisible: { + label: 'Show horizontal lines:', + value: true, + }, + horzLinesColor: { + label: '-- color', + value: '#FF0000', + optional: true, + disabled: true, + render: (get) => get(`${name}.horzLinesVisible`), + }, + horzLinesStyle: { + label: '-- style', + value: LineStyle.Dashed, + options: { + Solid: LineStyle.Solid, + Dashed: LineStyle.Dashed, + 'Large dashed': LineStyle.LargeDashed, + Dotted: LineStyle.Dotted, + 'Sparse dotted': LineStyle.SparseDotted, + }, + disabled: true, + optional: true, + render: (get) => get(`${name}.horzLinesVisible`), + }, + }); + + return { + vertLines: { + visible: grid.vertLinesVisible, + style: grid.vertLinesStyle, + color: grid.vertLinesColor, + }, + horzLines: { + visible: grid.horzLinesVisible, + style: grid.horzLinesStyle, + color: grid.horzLinesColor, + }, + }; +} + +function useKineticScrollControls(name: string) { + return useControls(name, { + touch: { + label: 'Touch', + value: true, + }, + mouse: { + label: 'Mouse', + value: false, + }, + }); +} + +function useHandleScaleControls(name: string) { + const { + axisPressedMouseMoveTime, + axisPressedMouseMovePrice, + ...handleScale + } = useControls(name, { + mouseWheel: { + label: 'Mouse wheel', + value: true, + }, + pinch: { + label: 'Pinch', + value: true, + }, + axisPressedMouseMoveTime: { + label: 'Axis pressed mouse move time', + value: true, + }, + axisPressedMouseMovePrice: { + label: 'Axis pressed mouse move price', + value: true, + }, + axisDoubleClickReset: { + label: 'Axis double click reset', + value: true, + }, + }); + + return { + ...handleScale, + axisPressedMouseMove: { + time: axisPressedMouseMoveTime, + price: axisPressedMouseMovePrice, + }, + }; +} + +function useHandleScrollControls(name: string) { + return useControls(name, { + mouseWheel: { + label: 'Mouse wheel', + value: true, + }, + pressedMouseMove: { + label: 'Pressed mouse move', + value: true, + }, + horzTouchDrag: { + label: 'Horizontal touch drag', + value: true, + }, + vertTouchDrag: { + label: 'Vertical touch drag', + value: true, + }, + }); +} + +function useLocalizationControls(name: string) { + return useControls(name, { + locale: { + label: 'Locale', + value: 'de-DE', + optional: true, + disabled: true, + }, + + dateFormat: { + label: 'Date format', + value: `'dd MMM \'yyyy'`, + optional: true, + disabled: true, + }, + }); }