@tradecanvas/vue 1.0.14 → 1.1.0
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.
- package/README.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Streams live Binance data by default. Pass `:data="bars"` for static OHLC, or `:
|
|
|
39
39
|
|
|
40
40
|
## Props & events
|
|
41
41
|
|
|
42
|
-
Props: `symbol`, `timeframe`, `theme`, `chartType`, `indicators`, `data`, `adapter`, `historyLimit`, `features`, `autoScale`, `signalMarkers`, `signalMarkerStyle`, `tradeZones`, `tradeZoneStyle`, `watermarkText`.
|
|
42
|
+
Props: `symbol`, `timeframe`, `theme`, `chartType`, `indicators`, `data`, `adapter`, `historyLimit`, `features`, `autoScale`, `signalMarkers`, `signalMarkerStyle`, `tradeZones`, `tradeZoneStyle`, `overrides` (style overrides by key, all of your app's), `watermarkText`.
|
|
43
43
|
|
|
44
44
|
Events: `@ready="(chart) => …"`, `@crosshairMove="(payload) => …"`.
|
|
45
45
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`vue`),t=require(`@tradecanvas/chart`);var n=(0,e.defineComponent)({__name:`TradeCanvas`,props:{symbol:{default:`BTCUSDT`},timeframe:{default:`5m`},theme:{default:`dark`},chartType:{default:`candlestick`},indicators:{default:()=>[]},data:{},adapter:{},historyLimit:{default:500},features:{},autoScale:{type:Boolean,default:!0},signalMarkers:{},signalMarkerStyle:{},tradeZones:{},tradeZoneStyle:{},watermarkText:{}},emits:[`ready`,`crosshairMove`],setup(n,{expose:r,emit:i}){let a=n,o=i;function s(e){return e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:e}let c=(0,e.ref)(),l=null,u=new Map;function d(){return l}function f(e){l?.screenshot(e)}function p(){return l?.screenshotDataURL()??null}return r({getChart:d,screenshot:f,screenshotDataURL:p}),(0,e.onMounted)(()=>{if(c.value){if(l=new t.Chart(c.value,{chartType:a.chartType,theme:s(a.theme),autoScale:a.autoScale,rightMargin:5,crosshair:{mode:`magnet`},watermark:a.watermarkText?{text:a.watermarkText,fontSize:48,color:`rgba(255,255,255,0.03)`}:void 0,features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:!0,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0,...a.features}}),a.data)l.setData(a.data);else{let e=a.adapter??new t.BinanceAdapter;l.connect({adapter:e,symbol:a.symbol,timeframe:a.timeframe,historyLimit:a.historyLimit})}for(let e of a.indicators){let t=l.addIndicator(e);t&&u.set(e,t)}a.signalMarkers&&l.setSignalMarkers(a.signalMarkers),a.signalMarkerStyle&&l.setSignalMarkerStyle(a.signalMarkerStyle),a.tradeZones&&l.setTradeZones(a.tradeZones),a.tradeZoneStyle&&l.setTradeZoneStyle(a.tradeZoneStyle),o(`ready`,l)}}),(0,e.onUnmounted)(()=>{l&&=(l.disconnectStream(),l.destroy(),null)}),(0,e.watch)(()=>[a.symbol,a.timeframe],([e,n])=>{if(!l||a.data)return;l.disconnectStream();let r=a.adapter??new t.BinanceAdapter;l.connect({adapter:r,symbol:e,timeframe:n,historyLimit:a.historyLimit}),a.watermarkText&&l.setWatermark(a.watermarkText)}),(0,e.watch)(()=>a.theme,e=>{l?.setTheme(s(e))}),(0,e.watch)(()=>a.chartType,e=>{l?.setChartType(e)}),(0,e.watch)(()=>a.data,e=>{e&&l?.setData(e)},{deep:!0}),(0,e.watch)(()=>a.indicators,e=>{if(!l)return;let t=new Set(e);for(let[e,n]of u)t.has(e)||(l.removeIndicator(n),u.delete(e));for(let t of e)if(!u.has(t)){let e=l.addIndicator(t);e&&u.set(t,e)}},{deep:!0}),(0,e.watch)(()=>a.signalMarkers,e=>{e&&l?.setSignalMarkers(e)},{deep:!0}),(0,e.watch)(()=>a.signalMarkerStyle,e=>{e&&l?.setSignalMarkerStyle(e)},{deep:!0}),(0,e.watch)(()=>a.tradeZones,e=>{e&&l?.setTradeZones(e)},{deep:!0}),(0,e.watch)(()=>a.tradeZoneStyle,e=>{e&&l?.setTradeZoneStyle(e)},{deep:!0}),(t,n)=>((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{ref_key:`containerEl`,ref:c,style:{width:`100%`,height:`100%`}},null,512))}});exports.TradeCanvas=n;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require(`vue`),t=require(`@tradecanvas/chart`);var n=(0,e.defineComponent)({__name:`TradeCanvas`,props:{symbol:{default:`BTCUSDT`},timeframe:{default:`5m`},theme:{default:`dark`},chartType:{default:`candlestick`},indicators:{default:()=>[]},data:{},adapter:{},historyLimit:{default:500},features:{},autoScale:{type:Boolean,default:!0},signalMarkers:{},signalMarkerStyle:{},tradeZones:{},tradeZoneStyle:{},overrides:{},watermarkText:{}},emits:[`ready`,`crosshairMove`],setup(n,{expose:r,emit:i}){let a=n,o=i;function s(e){return e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:e}let c=(0,e.ref)(),l=null,u=new Map;function d(){return l}function f(e){l?.screenshot(e)}function p(){return l?.screenshotDataURL()??null}return r({getChart:d,screenshot:f,screenshotDataURL:p}),(0,e.onMounted)(()=>{if(c.value){if(l=new t.Chart(c.value,{chartType:a.chartType,theme:s(a.theme),autoScale:a.autoScale,rightMargin:5,crosshair:{mode:`magnet`},watermark:a.watermarkText?{text:a.watermarkText,fontSize:48,color:`rgba(255,255,255,0.03)`}:void 0,features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:!0,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0,...a.features}}),a.data)l.setData(a.data);else{let e=a.adapter??new t.BinanceAdapter;l.connect({adapter:e,symbol:a.symbol,timeframe:a.timeframe,historyLimit:a.historyLimit})}for(let e of a.indicators){let t=l.addIndicator(e);t&&u.set(e,t)}a.signalMarkers&&l.setSignalMarkers(a.signalMarkers),a.signalMarkerStyle&&l.setSignalMarkerStyle(a.signalMarkerStyle),a.tradeZones&&l.setTradeZones(a.tradeZones),a.tradeZoneStyle&&l.setTradeZoneStyle(a.tradeZoneStyle),a.overrides&&l.setOverrides(a.overrides),o(`ready`,l)}}),(0,e.onUnmounted)(()=>{l&&=(l.disconnectStream(),l.destroy(),null)}),(0,e.watch)(()=>[a.symbol,a.timeframe],([e,n])=>{if(!l||a.data)return;l.disconnectStream();let r=a.adapter??new t.BinanceAdapter;l.connect({adapter:r,symbol:e,timeframe:n,historyLimit:a.historyLimit}),a.watermarkText&&l.setWatermark(a.watermarkText)}),(0,e.watch)(()=>a.theme,e=>{l?.setTheme(s(e))}),(0,e.watch)(()=>a.chartType,e=>{l?.setChartType(e)}),(0,e.watch)(()=>a.data,e=>{e&&l?.setData(e)},{deep:!0}),(0,e.watch)(()=>a.indicators,e=>{if(!l)return;let t=new Set(e);for(let[e,n]of u)t.has(e)||(l.removeIndicator(n),u.delete(e));for(let t of e)if(!u.has(t)){let e=l.addIndicator(t);e&&u.set(t,e)}},{deep:!0}),(0,e.watch)(()=>a.signalMarkers,e=>{e&&l?.setSignalMarkers(e)},{deep:!0}),(0,e.watch)(()=>a.signalMarkerStyle,e=>{e&&l?.setSignalMarkerStyle(e)},{deep:!0}),(0,e.watch)(()=>a.tradeZones,e=>{e&&l?.setTradeZones(e)},{deep:!0}),(0,e.watch)(()=>a.tradeZoneStyle,e=>{e&&l?.setTradeZoneStyle(e)},{deep:!0}),(0,e.watch)(()=>a.overrides,e=>{l?.setOverrides({...e})},{deep:!0}),(t,n)=>((0,e.openBlock)(),(0,e.createElementBlock)(`div`,{ref_key:`containerEl`,ref:c,style:{width:`100%`,height:`100%`}},null,512))}});exports.TradeCanvas=n;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/TradeCanvas.vue","../src/TradeCanvas.vue"],"sourcesContent":["<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n</script>\n","<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../src/TradeCanvas.vue","../src/TradeCanvas.vue"],"sourcesContent":["<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n ChartStyleOverrides,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n /** Style overrides, by key: all of your app's (`chart.setOverrides`). */\n overrides?: ChartStyleOverrides;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n if (props.overrides) chart.setOverrides(props.overrides);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n// All of the host's overrides: keys left out of the prop are taken away.\nwatch(() => props.overrides, (o) => { chart?.setOverrides({ ...o }); }, { deep: true });\n</script>\n","<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n ChartStyleOverrides,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n /** Style overrides, by key: all of your app's (`chart.setOverrides`). */\n overrides?: ChartStyleOverrides;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n if (props.overrides) chart.setOverrides(props.overrides);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n// All of the host's overrides: keys left out of the prop are taken away.\nwatch(() => props.overrides, (o) => { chart?.setOverrides({ ...o }); }, { deep: true });\n</script>\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Chart } from '@tradecanvas/chart';
|
|
2
|
+
import { ChartStyleOverrides } from '@tradecanvas/chart';
|
|
2
3
|
import { ChartType } from '@tradecanvas/chart';
|
|
3
4
|
import { ComponentOptionsMixin } from 'vue';
|
|
4
5
|
import { ComponentProvideOptions } from 'vue';
|
|
@@ -29,6 +30,8 @@ declare type __VLS_Props = {
|
|
|
29
30
|
signalMarkerStyle?: SignalMarkerStyle;
|
|
30
31
|
tradeZones?: TradeZone[];
|
|
31
32
|
tradeZoneStyle?: TradeZoneStyle;
|
|
33
|
+
/** Style overrides, by key: all of your app's (`chart.setOverrides`). */
|
|
34
|
+
overrides?: ChartStyleOverrides;
|
|
32
35
|
watermarkText?: string;
|
|
33
36
|
};
|
|
34
37
|
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var d = /* @__PURE__ */ t({
|
|
|
22
22
|
signalMarkerStyle: {},
|
|
23
23
|
tradeZones: {},
|
|
24
24
|
tradeZoneStyle: {},
|
|
25
|
+
overrides: {},
|
|
25
26
|
watermarkText: {}
|
|
26
27
|
},
|
|
27
28
|
emits: ["ready", "crosshairMove"],
|
|
@@ -88,7 +89,7 @@ var d = /* @__PURE__ */ t({
|
|
|
88
89
|
let t = _.addIndicator(e);
|
|
89
90
|
t && v.set(e, t);
|
|
90
91
|
}
|
|
91
|
-
p.signalMarkers && _.setSignalMarkers(p.signalMarkers), p.signalMarkerStyle && _.setSignalMarkerStyle(p.signalMarkerStyle), p.tradeZones && _.setTradeZones(p.tradeZones), p.tradeZoneStyle && _.setTradeZoneStyle(p.tradeZoneStyle), m("ready", _);
|
|
92
|
+
p.signalMarkers && _.setSignalMarkers(p.signalMarkers), p.signalMarkerStyle && _.setSignalMarkerStyle(p.signalMarkerStyle), p.tradeZones && _.setTradeZones(p.tradeZones), p.tradeZoneStyle && _.setTradeZoneStyle(p.tradeZoneStyle), p.overrides && _.setOverrides(p.overrides), m("ready", _);
|
|
92
93
|
}
|
|
93
94
|
}), r(() => {
|
|
94
95
|
_ &&= (_.disconnectStream(), _.destroy(), null);
|
|
@@ -124,6 +125,8 @@ var d = /* @__PURE__ */ t({
|
|
|
124
125
|
e && _?.setTradeZones(e);
|
|
125
126
|
}, { deep: !0 }), o(() => p.tradeZoneStyle, (e) => {
|
|
126
127
|
e && _?.setTradeZoneStyle(e);
|
|
128
|
+
}, { deep: !0 }), o(() => p.overrides, (e) => {
|
|
129
|
+
_?.setOverrides({ ...e });
|
|
127
130
|
}, { deep: !0 }), (t, n) => (i(), e("div", {
|
|
128
131
|
ref_key: "containerEl",
|
|
129
132
|
ref: g,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/TradeCanvas.vue","../src/TradeCanvas.vue"],"sourcesContent":["<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n</script>\n","<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n</script>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/TradeCanvas.vue","../src/TradeCanvas.vue"],"sourcesContent":["<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n ChartStyleOverrides,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n /** Style overrides, by key: all of your app's (`chart.setOverrides`). */\n overrides?: ChartStyleOverrides;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n if (props.overrides) chart.setOverrides(props.overrides);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n// All of the host's overrides: keys left out of the prop are taken away.\nwatch(() => props.overrides, (o) => { chart?.setOverrides({ ...o }); }, { deep: true });\n</script>\n","<template>\n <div ref=\"containerEl\" :style=\"{ width: '100%', height: '100%' }\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, onMounted, onUnmounted, watch } from 'vue';\nimport {\n Chart,\n BinanceAdapter,\n DARK_THEME,\n LIGHT_THEME,\n} from '@tradecanvas/chart';\nimport type {\n ChartType,\n TimeFrame,\n FeaturesConfig,\n Theme,\n OHLCBar,\n SignalMarker,\n TradeZone,\n SignalMarkerStyle,\n TradeZoneStyle,\n DataAdapter,\n ChartStyleOverrides,\n} from '@tradecanvas/chart';\n\nconst props = withDefaults(\n defineProps<{\n symbol?: string;\n timeframe?: TimeFrame;\n theme?: 'dark' | 'light' | Theme;\n chartType?: ChartType;\n indicators?: string[];\n data?: OHLCBar[];\n adapter?: DataAdapter;\n historyLimit?: number;\n features?: FeaturesConfig;\n autoScale?: boolean;\n signalMarkers?: SignalMarker[];\n signalMarkerStyle?: SignalMarkerStyle;\n tradeZones?: TradeZone[];\n tradeZoneStyle?: TradeZoneStyle;\n /** Style overrides, by key: all of your app's (`chart.setOverrides`). */\n overrides?: ChartStyleOverrides;\n watermarkText?: string;\n }>(),\n {\n symbol: 'BTCUSDT',\n timeframe: '5m' as TimeFrame,\n theme: 'dark',\n chartType: 'candlestick' as ChartType,\n indicators: () => [],\n historyLimit: 500,\n autoScale: true,\n },\n);\n\nconst emit = defineEmits<{\n ready: [chart: Chart];\n crosshairMove: [payload: unknown];\n}>();\n\nfunction resolveTheme(theme: 'dark' | 'light' | Theme): Theme {\n if (theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n return theme as Theme;\n}\n\nconst containerEl = ref<HTMLDivElement>();\nlet chart: Chart | null = null;\nconst indicatorIds = new Map<string, string>();\n\nfunction getChart(): Chart | null {\n return chart;\n}\n\nfunction screenshot(filename?: string): void {\n chart?.screenshot(filename);\n}\n\nfunction screenshotDataURL(): string | null {\n return chart?.screenshotDataURL() ?? null;\n}\n\ndefineExpose({ getChart, screenshot, screenshotDataURL });\n\nonMounted(() => {\n if (!containerEl.value) return;\n\n chart = new Chart(containerEl.value, {\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n rightMargin: 5,\n crosshair: { mode: 'magnet' },\n watermark: props.watermarkText\n ? { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' }\n : undefined,\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: true,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...props.features,\n },\n });\n\n if (props.data) {\n chart.setData(props.data);\n } else {\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n }\n\n // Apply initial reactive collections not covered by the constructor options.\n // Vue's watches aren't immediate, so without this the first render of\n // indicators / signal markers / trade zones would be dropped.\n for (const name of props.indicators) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n if (props.signalMarkers) chart.setSignalMarkers(props.signalMarkers);\n if (props.signalMarkerStyle) chart.setSignalMarkerStyle(props.signalMarkerStyle);\n if (props.tradeZones) chart.setTradeZones(props.tradeZones);\n if (props.tradeZoneStyle) chart.setTradeZoneStyle(props.tradeZoneStyle);\n if (props.overrides) chart.setOverrides(props.overrides);\n\n emit('ready', chart);\n});\n\nonUnmounted(() => {\n if (chart) {\n chart.disconnectStream();\n chart.destroy();\n chart = null;\n }\n});\n\nwatch(\n () => [props.symbol, props.timeframe] as const,\n ([newSymbol, newTimeframe]) => {\n if (!chart || props.data) return;\n chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: newSymbol, timeframe: newTimeframe, historyLimit: props.historyLimit });\n if (props.watermarkText) chart.setWatermark(props.watermarkText);\n },\n);\n\nwatch(() => props.theme, (t) => { chart?.setTheme(resolveTheme(t)); });\nwatch(() => props.chartType, (ct) => { chart?.setChartType(ct); });\nwatch(() => props.data, (d) => { if (d) chart?.setData(d); }, { deep: true });\n\nwatch(\n () => props.indicators,\n (newIndicators) => {\n if (!chart) return;\n const desired = new Set(newIndicators);\n for (const [name, instanceId] of indicatorIds) {\n if (!desired.has(name)) {\n chart.removeIndicator(instanceId);\n indicatorIds.delete(name);\n }\n }\n for (const name of newIndicators) {\n if (!indicatorIds.has(name)) {\n const instanceId = chart.addIndicator(name);\n if (instanceId) indicatorIds.set(name, instanceId);\n }\n }\n },\n { deep: true },\n);\n\nwatch(() => props.signalMarkers, (m) => { if (m) chart?.setSignalMarkers(m); }, { deep: true });\nwatch(() => props.signalMarkerStyle, (s) => { if (s) chart?.setSignalMarkerStyle(s); }, { deep: true });\nwatch(() => props.tradeZones, (z) => { if (z) chart?.setTradeZones(z); }, { deep: true });\nwatch(() => props.tradeZoneStyle, (s) => { if (s) chart?.setTradeZoneStyle(s); }, { deep: true });\n// All of the host's overrides: keys left out of the prop are taken away.\nwatch(() => props.overrides, (o) => { chart?.setOverrides({ ...o }); }, { deep: true });\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA0BA,IAAM,IAAQ,GA+BR,IAAO;EAKb,SAAS,EAAa,GAAwC;AAG5D,UAFI,MAAU,SAAe,IACzB,MAAU,UAAgB,IACvB;;EAGT,IAAM,IAAc,GAAqB,EACrC,IAAsB,MACpB,oBAAe,IAAI,KAAqB;EAE9C,SAAS,IAAyB;AAChC,UAAO;;EAGT,SAAS,EAAW,GAAyB;AAC3C,MAAO,WAAW,EAAS;;EAG7B,SAAS,IAAmC;AAC1C,UAAO,GAAO,mBAAmB,IAAI;;SAGvC,EAAa;GAAE;GAAU;GAAY;GAAmB,CAAC,EAEzD,QAAgB;AACT,SAAY,OA8BjB;QA5BA,IAAQ,IAAI,EAAM,EAAY,OAAO;KACnC,WAAW,EAAM;KACjB,OAAO,EAAa,EAAM,MAAM;KAChC,WAAW,EAAM;KACjB,aAAa;KACb,WAAW,EAAE,MAAM,UAAU;KAC7B,WAAW,EAAM,gBACb;MAAE,MAAM,EAAM;MAAe,UAAU;MAAI,OAAO;MAAyB,GAC3E,KAAA;KACJ,UAAU;MACR,UAAU;MACV,eAAe;MACf,iBAAiB;MACjB,YAAY;MACZ,SAAS;MACT,QAAQ;MACR,QAAQ;MACR,WAAW;MACX,UAAU;MACV,YAAY;MACZ,QAAQ;MACR,cAAc;MACd,UAAU;MACV,WAAW;MACX,GAAG,EAAM;MACV;KACF,CAAC,EAEE,EAAM,KACR,GAAM,QAAQ,EAAM,KAAK;SACpB;KACL,IAAM,IAAU,EAAM,WAAW,IAAI,GAAgB;AACrD,OAAM,QAAQ;MAAE;MAAS,QAAQ,EAAM;MAAQ,WAAW,EAAM;MAAW,cAAc,EAAM;MAAc,CAAC;;AAMhH,SAAK,IAAM,KAAQ,EAAM,YAAY;KACnC,IAAM,IAAa,EAAM,aAAa,EAAK;AAC3C,KAAI,KAAY,EAAa,IAAI,GAAM,EAAW;;AAQpD,IANI,EAAM,iBAAe,EAAM,iBAAiB,EAAM,cAAc,EAChE,EAAM,qBAAmB,EAAM,qBAAqB,EAAM,kBAAkB,EAC5E,EAAM,cAAY,EAAM,cAAc,EAAM,WAAW,EACvD,EAAM,kBAAgB,EAAM,kBAAkB,EAAM,eAAe,EACnE,EAAM,aAAW,EAAM,aAAa,EAAM,UAAU,EAExD,EAAK,SAAS,EAAM;;IACpB,EAEF,QAAkB;AAChB,GAGE,OAFA,EAAM,kBAAkB,EACxB,EAAM,SAAS,EACP;IAEV,EAEF,QACQ,CAAC,EAAM,QAAQ,EAAM,UAAU,GACpC,CAAC,GAAW,OAAkB;AAC7B,OAAI,CAAC,KAAS,EAAM,KAAM;AAC1B,KAAM,kBAAkB;GACxB,IAAM,IAAU,EAAM,WAAW,IAAI,GAAgB;AAErD,GADA,EAAM,QAAQ;IAAE;IAAS,QAAQ;IAAW,WAAW;IAAc,cAAc,EAAM;IAAc,CAAC,EACpG,EAAM,iBAAe,EAAM,aAAa,EAAM,cAAc;IAEnE,EAED,QAAY,EAAM,QAAQ,MAAM;AAAE,MAAO,SAAS,EAAa,EAAE,CAAC;IAAI,EACtE,QAAY,EAAM,YAAY,MAAO;AAAE,MAAO,aAAa,EAAG;IAAI,EAClE,QAAY,EAAM,OAAO,MAAM;AAAE,GAAI,KAAG,GAAO,QAAQ,EAAE;KAAK,EAAE,MAAM,IAAM,CAAC,EAE7E,QACQ,EAAM,aACX,MAAkB;AACjB,OAAI,CAAC,EAAO;GACZ,IAAM,IAAU,IAAI,IAAI,EAAc;AACtC,QAAK,IAAM,CAAC,GAAM,MAAe,EAC/B,CAAK,EAAQ,IAAI,EAAK,KACpB,EAAM,gBAAgB,EAAW,EACjC,EAAa,OAAO,EAAK;AAG7B,QAAK,IAAM,KAAQ,EACjB,KAAI,CAAC,EAAa,IAAI,EAAK,EAAE;IAC3B,IAAM,IAAa,EAAM,aAAa,EAAK;AAC3C,IAAI,KAAY,EAAa,IAAI,GAAM,EAAW;;KAIxD,EAAE,MAAM,IAAM,CACf,EAED,QAAY,EAAM,gBAAgB,MAAM;AAAE,GAAI,KAAG,GAAO,iBAAiB,EAAE;KAAK,EAAE,MAAM,IAAM,CAAC,EAC/F,QAAY,EAAM,oBAAoB,MAAM;AAAE,GAAI,KAAG,GAAO,qBAAqB,EAAE;KAAK,EAAE,MAAM,IAAM,CAAC,EACvG,QAAY,EAAM,aAAa,MAAM;AAAE,GAAI,KAAG,GAAO,cAAc,EAAE;KAAK,EAAE,MAAM,IAAM,CAAC,EACzF,QAAY,EAAM,iBAAiB,MAAM;AAAE,GAAI,KAAG,GAAO,kBAAkB,EAAE;KAAK,EAAE,MAAM,IAAM,CAAC,EAEjG,QAAY,EAAM,YAAY,MAAM;AAAE,MAAO,aAAa,EAAE,GAAG,GAAG,CAAC;KAAK,EAAE,MAAM,IAAM,CAAC,kBA5LrF,EAAoE,OAAA;YAA3D;GAAJ,KAAI;GAAe,OAAO;IAAA,OAAA;IAAA,QAAA;IAAiC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradecanvas/vue",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vue 3 component for @tradecanvas/chart — reactive props, template ref, zero boilerplate.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"README.md"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@tradecanvas/chart": "1.
|
|
37
|
+
"@tradecanvas/chart": "1.13.0"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"vue": ">=3.3.0"
|