@tradecanvas/vue 1.0.15 → 1.2.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 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` (ids, or `{ id, params, position }`), `data` (bars of your own; no stream), `adapter`, `stream` (`false`: no stream of its own), `historyLimit`, `features` (changes apply after mount too), `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:{},stream:{type:Boolean,default:!0},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,d=null,f=e=>e.map(e=>typeof e==`string`?e:{id:e.id,...e.params?{params:{...e.params}}:{},...e.position?{position:e.position}:{}}),p=JSON.stringify(a.features??null);function m(){if(!l)return;if(!a.stream){d!==null&&l.disconnectStream(),d=null;return}if(a.data)return;let e=`${a.symbol}|${a.timeframe}`;if(d===e)return;let n=d!==null;d=e,n&&l.disconnectStream();let r=a.adapter??new t.BinanceAdapter;l.connect({adapter:r,symbol:a.symbol,timeframe:a.timeframe,historyLimit:a.historyLimit}),n&&a.watermarkText&&l.setWatermark(a.watermarkText)}function h(){return l}function g(e){l?.screenshot(e)}function _(){return l?.screenshotDataURL()??null}return r({getChart:h,screenshot:g,screenshotDataURL:_}),(0,e.onMounted)(()=>{c.value&&(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):m(),(0,t.syncIndicators)(l,f(a.indicators),u),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,!a.data,a.stream],m),(0,e.watch)(()=>a.features,e=>{let t=JSON.stringify(e??null);t!==p&&(p=t,e&&l?.setFeatures({...e}))},{deep:!0}),(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=>{l&&(0,t.syncIndicators)(l,f(e),u)},{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
@@ -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":"2iBAyBA,IAAM,EAAQ,EA6BR,EAAO,EAKb,SAAS,EAAa,EAAwC,CAG5D,OAFI,IAAU,OAAe,EAAA,WACzB,IAAU,QAAgB,EAAA,YACvB,EAGT,IAAM,GAAA,EAAA,EAAA,MAAmC,CACrC,EAAsB,KACpB,EAAe,IAAI,IAEzB,SAAS,GAAyB,CAChC,OAAO,EAGT,SAAS,EAAW,EAAyB,CAC3C,GAAO,WAAW,EAAS,CAG7B,SAAS,GAAmC,CAC1C,OAAO,GAAO,mBAAmB,EAAI,YAGvC,EAAa,CAAE,WAAU,aAAY,oBAAmB,CAAC,EAEzD,EAAA,EAAA,eAAgB,CACT,KAAY,MA8BjB,IA5BA,EAAQ,IAAI,EAAA,MAAM,EAAY,MAAO,CACnC,UAAW,EAAM,UACjB,MAAO,EAAa,EAAM,MAAM,CAChC,UAAW,EAAM,UACjB,YAAa,EACb,UAAW,CAAE,KAAM,SAAU,CAC7B,UAAW,EAAM,cACb,CAAE,KAAM,EAAM,cAAe,SAAU,GAAI,MAAO,yBAAyB,CAC3E,IAAA,GACJ,SAAU,CACR,SAAU,GACV,cAAe,GACf,gBAAiB,GACjB,WAAY,GACZ,QAAS,GACT,OAAQ,GACR,OAAQ,GACR,UAAW,GACX,SAAU,GACV,WAAY,GACZ,OAAQ,GACR,aAAc,GACd,SAAU,GACV,UAAW,GACX,GAAG,EAAM,SACV,CACF,CAAC,CAEE,EAAM,KACR,EAAM,QAAQ,EAAM,KAAK,KACpB,CACL,IAAM,EAAU,EAAM,SAAW,IAAI,EAAA,eACrC,EAAM,QAAQ,CAAE,UAAS,OAAQ,EAAM,OAAQ,UAAW,EAAM,UAAW,aAAc,EAAM,aAAc,CAAC,CAMhH,IAAK,IAAM,KAAQ,EAAM,WAAY,CACnC,IAAM,EAAa,EAAM,aAAa,EAAK,CACvC,GAAY,EAAa,IAAI,EAAM,EAAW,CAEhD,EAAM,eAAe,EAAM,iBAAiB,EAAM,cAAc,CAChE,EAAM,mBAAmB,EAAM,qBAAqB,EAAM,kBAAkB,CAC5E,EAAM,YAAY,EAAM,cAAc,EAAM,WAAW,CACvD,EAAM,gBAAgB,EAAM,kBAAkB,EAAM,eAAe,CAEvE,EAAK,QAAS,EAAM,GACpB,EAEF,EAAA,EAAA,iBAAkB,CAChB,AAGE,KAFA,EAAM,kBAAkB,CACxB,EAAM,SAAS,CACP,OAEV,EAEF,EAAA,EAAA,WACQ,CAAC,EAAM,OAAQ,EAAM,UAAU,EACpC,CAAC,EAAW,KAAkB,CAC7B,GAAI,CAAC,GAAS,EAAM,KAAM,OAC1B,EAAM,kBAAkB,CACxB,IAAM,EAAU,EAAM,SAAW,IAAI,EAAA,eACrC,EAAM,QAAQ,CAAE,UAAS,OAAQ,EAAW,UAAW,EAAc,aAAc,EAAM,aAAc,CAAC,CACpG,EAAM,eAAe,EAAM,aAAa,EAAM,cAAc,EAEnE,EAED,EAAA,EAAA,WAAY,EAAM,MAAQ,GAAM,CAAE,GAAO,SAAS,EAAa,EAAE,CAAC,EAAI,EACtE,EAAA,EAAA,WAAY,EAAM,UAAY,GAAO,CAAE,GAAO,aAAa,EAAG,EAAI,EAClE,EAAA,EAAA,WAAY,EAAM,KAAO,GAAM,CAAM,GAAG,GAAO,QAAQ,EAAE,EAAK,CAAE,KAAM,GAAM,CAAC,EAE7E,EAAA,EAAA,WACQ,EAAM,WACX,GAAkB,CACjB,GAAI,CAAC,EAAO,OACZ,IAAM,EAAU,IAAI,IAAI,EAAc,CACtC,IAAK,GAAM,CAAC,EAAM,KAAe,EAC1B,EAAQ,IAAI,EAAK,GACpB,EAAM,gBAAgB,EAAW,CACjC,EAAa,OAAO,EAAK,EAG7B,IAAK,IAAM,KAAQ,EACjB,GAAI,CAAC,EAAa,IAAI,EAAK,CAAE,CAC3B,IAAM,EAAa,EAAM,aAAa,EAAK,CACvC,GAAY,EAAa,IAAI,EAAM,EAAW,GAIxD,CAAE,KAAM,GAAM,CACf,EAED,EAAA,EAAA,WAAY,EAAM,cAAgB,GAAM,CAAM,GAAG,GAAO,iBAAiB,EAAE,EAAK,CAAE,KAAM,GAAM,CAAC,EAC/F,EAAA,EAAA,WAAY,EAAM,kBAAoB,GAAM,CAAM,GAAG,GAAO,qBAAqB,EAAE,EAAK,CAAE,KAAM,GAAM,CAAC,EACvG,EAAA,EAAA,WAAY,EAAM,WAAa,GAAM,CAAM,GAAG,GAAO,cAAc,EAAE,EAAK,CAAE,KAAM,GAAM,CAAC,EACzF,EAAA,EAAA,WAAY,EAAM,eAAiB,GAAM,CAAM,GAAG,GAAO,kBAAkB,EAAE,EAAK,CAAE,KAAM,GAAM,CAAC,oDAtL3B,MAAA,SAA3D,cAAJ,IAAI,EAAe,MAAO,CAAA,MAAA,OAAA,OAAA,OAAiC"}
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 syncIndicators,\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 IndicatorSpec,\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 by id (`'rsi'`), or with their inputs (`{ id: 'ema', params: { period: 50 } }`). */\n indicators?: IndicatorSpec[];\n /** Static bars: the chart shows these, and opens no stream of its own when it has them at mount. */\n data?: OHLCBar[];\n adapter?: DataAdapter;\n /** `false`: no stream until you say so (no Binance by default); the chart waits for `data`. Default `true`. */\n stream?: boolean;\n historyLimit?: number;\n /** What users can do on the chart; changes after mount are applied too (the keys given). */\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 stream: true,\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/** The stream open now (`symbol|timeframe`), or null. */\nlet streamKey: string | null = null;\n\n/** The specs as plain values (not Vue's proxies), for the chart to keep. */\nconst plainSpecs = (specs: readonly IndicatorSpec[]): IndicatorSpec[] =>\n specs.map((spec) => (typeof spec === 'string'\n ? spec\n : { id: spec.id, ...(spec.params ? { params: { ...spec.params } } : {}), ...(spec.position ? { position: spec.position } : {}) }));\n/** The features last applied, as text. */\nlet featuresKey = JSON.stringify(props.features ?? null);\n\n/** A stream of its own while it has no data; `stream: false` closes it. Data given later leaves it be. */\nfunction syncStream(): void {\n if (!chart) return;\n if (!props.stream) {\n if (streamKey !== null) chart.disconnectStream();\n streamKey = null;\n return;\n }\n if (props.data) return;\n const key = `${props.symbol}|${props.timeframe}`;\n if (streamKey === key) return;\n const opened = streamKey !== null;\n streamKey = key;\n if (opened) chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n if (opened && props.watermarkText) chart.setWatermark(props.watermarkText);\n}\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) chart.setData(props.data);\n else syncStream();\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 syncIndicators(chart, plainSpecs(props.indicators), indicatorIds);\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(() => [props.symbol, props.timeframe, !props.data, props.stream] as const, syncStream);\nwatch(() => props.features, (f) => {\n const key = JSON.stringify(f ?? null);\n if (key === featuresKey) return;\n featuresKey = key;\n if (f) chart?.setFeatures({ ...f });\n}, { deep: true });\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 (specs) => { if (chart) syncIndicators(chart, plainSpecs(specs), indicatorIds); },\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 syncIndicators,\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 IndicatorSpec,\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 by id (`'rsi'`), or with their inputs (`{ id: 'ema', params: { period: 50 } }`). */\n indicators?: IndicatorSpec[];\n /** Static bars: the chart shows these, and opens no stream of its own when it has them at mount. */\n data?: OHLCBar[];\n adapter?: DataAdapter;\n /** `false`: no stream until you say so (no Binance by default); the chart waits for `data`. Default `true`. */\n stream?: boolean;\n historyLimit?: number;\n /** What users can do on the chart; changes after mount are applied too (the keys given). */\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 stream: true,\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/** The stream open now (`symbol|timeframe`), or null. */\nlet streamKey: string | null = null;\n\n/** The specs as plain values (not Vue's proxies), for the chart to keep. */\nconst plainSpecs = (specs: readonly IndicatorSpec[]): IndicatorSpec[] =>\n specs.map((spec) => (typeof spec === 'string'\n ? spec\n : { id: spec.id, ...(spec.params ? { params: { ...spec.params } } : {}), ...(spec.position ? { position: spec.position } : {}) }));\n/** The features last applied, as text. */\nlet featuresKey = JSON.stringify(props.features ?? null);\n\n/** A stream of its own while it has no data; `stream: false` closes it. Data given later leaves it be. */\nfunction syncStream(): void {\n if (!chart) return;\n if (!props.stream) {\n if (streamKey !== null) chart.disconnectStream();\n streamKey = null;\n return;\n }\n if (props.data) return;\n const key = `${props.symbol}|${props.timeframe}`;\n if (streamKey === key) return;\n const opened = streamKey !== null;\n streamKey = key;\n if (opened) chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n if (opened && props.watermarkText) chart.setWatermark(props.watermarkText);\n}\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) chart.setData(props.data);\n else syncStream();\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 syncIndicators(chart, plainSpecs(props.indicators), indicatorIds);\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(() => [props.symbol, props.timeframe, !props.data, props.stream] as const, syncStream);\nwatch(() => props.features, (f) => {\n const key = JSON.stringify(f ?? null);\n if (key === featuresKey) return;\n featuresKey = key;\n if (f) chart?.setFeatures({ ...f });\n}, { deep: true });\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 (specs) => { if (chart) syncIndicators(chart, plainSpecs(specs), indicatorIds); },\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,10 +1,12 @@
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';
5
6
  import { DataAdapter } from '@tradecanvas/chart';
6
7
  import { DefineComponent } from 'vue';
7
8
  import { FeaturesConfig } from '@tradecanvas/chart';
9
+ import { IndicatorSpec } from '@tradecanvas/chart';
8
10
  import { OHLCBar } from '@tradecanvas/chart';
9
11
  import { PublicProps } from 'vue';
10
12
  import { SignalMarker } from '@tradecanvas/chart';
@@ -19,16 +21,23 @@ declare type __VLS_Props = {
19
21
  timeframe?: TimeFrame;
20
22
  theme?: 'dark' | 'light' | Theme;
21
23
  chartType?: ChartType;
22
- indicators?: string[];
24
+ /** Indicators by id (`'rsi'`), or with their inputs (`{ id: 'ema', params: { period: 50 } }`). */
25
+ indicators?: IndicatorSpec[];
26
+ /** Static bars: the chart shows these, and opens no stream of its own when it has them at mount. */
23
27
  data?: OHLCBar[];
24
28
  adapter?: DataAdapter;
29
+ /** `false`: no stream until you say so (no Binance by default); the chart waits for `data`. Default `true`. */
30
+ stream?: boolean;
25
31
  historyLimit?: number;
32
+ /** What users can do on the chart; changes after mount are applied too (the keys given). */
26
33
  features?: FeaturesConfig;
27
34
  autoScale?: boolean;
28
35
  signalMarkers?: SignalMarker[];
29
36
  signalMarkerStyle?: SignalMarkerStyle;
30
37
  tradeZones?: TradeZone[];
31
38
  tradeZoneStyle?: TradeZoneStyle;
39
+ /** Style overrides, by key: all of your app's (`chart.setOverrides`). */
40
+ overrides?: ChartStyleOverrides;
32
41
  watermarkText?: string;
33
42
  };
34
43
 
@@ -53,7 +62,8 @@ symbol: string;
53
62
  timeframe: TimeFrame;
54
63
  theme: "dark" | "light" | Theme;
55
64
  chartType: ChartType;
56
- indicators: string[];
65
+ indicators: IndicatorSpec[];
66
+ stream: boolean;
57
67
  historyLimit: number;
58
68
  autoScale: boolean;
59
69
  }, {}, {}, {}, string, ComponentProvideOptions, false, {
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createElementBlock as e, defineComponent as t, onMounted as n, onUnmounted as r, openBlock as i, ref as a, watch as o } from "vue";
2
- import { BinanceAdapter as s, Chart as c, DARK_THEME as l, LIGHT_THEME as u } from "@tradecanvas/chart";
2
+ import { BinanceAdapter as s, Chart as c, DARK_THEME as l, LIGHT_THEME as u, syncIndicators as d } from "@tradecanvas/chart";
3
3
  //#endregion
4
4
  //#region src/TradeCanvas.vue
5
- var d = /* @__PURE__ */ t({
5
+ var f = /* @__PURE__ */ t({
6
6
  __name: "TradeCanvas",
7
7
  props: {
8
8
  symbol: { default: "BTCUSDT" },
@@ -12,6 +12,10 @@ var d = /* @__PURE__ */ t({
12
12
  indicators: { default: () => [] },
13
13
  data: {},
14
14
  adapter: {},
15
+ stream: {
16
+ type: Boolean,
17
+ default: !0
18
+ },
15
19
  historyLimit: { default: 500 },
16
20
  features: {},
17
21
  autoScale: {
@@ -22,111 +26,113 @@ var d = /* @__PURE__ */ t({
22
26
  signalMarkerStyle: {},
23
27
  tradeZones: {},
24
28
  tradeZoneStyle: {},
29
+ overrides: {},
25
30
  watermarkText: {}
26
31
  },
27
32
  emits: ["ready", "crosshairMove"],
28
- setup(t, { expose: d, emit: f }) {
29
- let p = t, m = f;
30
- function h(e) {
33
+ setup(t, { expose: f, emit: p }) {
34
+ let m = t, h = p;
35
+ function g(e) {
31
36
  return e === "dark" ? l : e === "light" ? u : e;
32
37
  }
33
- let g = a(), _ = null, v = /* @__PURE__ */ new Map();
34
- function y() {
35
- return _;
38
+ let _ = a(), v = null, y = /* @__PURE__ */ new Map(), b = null, x = (e) => e.map((e) => typeof e == "string" ? e : {
39
+ id: e.id,
40
+ ...e.params ? { params: { ...e.params } } : {},
41
+ ...e.position ? { position: e.position } : {}
42
+ }), S = JSON.stringify(m.features ?? null);
43
+ function C() {
44
+ if (!v) return;
45
+ if (!m.stream) {
46
+ b !== null && v.disconnectStream(), b = null;
47
+ return;
48
+ }
49
+ if (m.data) return;
50
+ let e = `${m.symbol}|${m.timeframe}`;
51
+ if (b === e) return;
52
+ let t = b !== null;
53
+ b = e, t && v.disconnectStream();
54
+ let n = m.adapter ?? new s();
55
+ v.connect({
56
+ adapter: n,
57
+ symbol: m.symbol,
58
+ timeframe: m.timeframe,
59
+ historyLimit: m.historyLimit
60
+ }), t && m.watermarkText && v.setWatermark(m.watermarkText);
61
+ }
62
+ function w() {
63
+ return v;
36
64
  }
37
- function b(e) {
38
- _?.screenshot(e);
65
+ function T(e) {
66
+ v?.screenshot(e);
39
67
  }
40
- function x() {
41
- return _?.screenshotDataURL() ?? null;
68
+ function E() {
69
+ return v?.screenshotDataURL() ?? null;
42
70
  }
43
- return d({
44
- getChart: y,
45
- screenshot: b,
46
- screenshotDataURL: x
71
+ return f({
72
+ getChart: w,
73
+ screenshot: T,
74
+ screenshotDataURL: E
47
75
  }), n(() => {
48
- if (g.value) {
49
- if (_ = new c(g.value, {
50
- chartType: p.chartType,
51
- theme: h(p.theme),
52
- autoScale: p.autoScale,
53
- rightMargin: 5,
54
- crosshair: { mode: "magnet" },
55
- watermark: p.watermarkText ? {
56
- text: p.watermarkText,
57
- fontSize: 48,
58
- color: "rgba(255,255,255,0.03)"
59
- } : void 0,
60
- features: {
61
- drawings: !0,
62
- drawingMagnet: !0,
63
- drawingUndoRedo: !0,
64
- indicators: !0,
65
- trading: !0,
66
- volume: !0,
67
- legend: !0,
68
- crosshair: !0,
69
- keyboard: !0,
70
- screenshot: !0,
71
- alerts: !0,
72
- barCountdown: !0,
73
- logScale: !0,
74
- watermark: !0,
75
- ...p.features
76
- }
77
- }), p.data) _.setData(p.data);
78
- else {
79
- let e = p.adapter ?? new s();
80
- _.connect({
81
- adapter: e,
82
- symbol: p.symbol,
83
- timeframe: p.timeframe,
84
- historyLimit: p.historyLimit
85
- });
86
- }
87
- for (let e of p.indicators) {
88
- let t = _.addIndicator(e);
89
- t && v.set(e, t);
76
+ _.value && (v = new c(_.value, {
77
+ chartType: m.chartType,
78
+ theme: g(m.theme),
79
+ autoScale: m.autoScale,
80
+ rightMargin: 5,
81
+ crosshair: { mode: "magnet" },
82
+ watermark: m.watermarkText ? {
83
+ text: m.watermarkText,
84
+ fontSize: 48,
85
+ color: "rgba(255,255,255,0.03)"
86
+ } : void 0,
87
+ features: {
88
+ drawings: !0,
89
+ drawingMagnet: !0,
90
+ drawingUndoRedo: !0,
91
+ indicators: !0,
92
+ trading: !0,
93
+ volume: !0,
94
+ legend: !0,
95
+ crosshair: !0,
96
+ keyboard: !0,
97
+ screenshot: !0,
98
+ alerts: !0,
99
+ barCountdown: !0,
100
+ logScale: !0,
101
+ watermark: !0,
102
+ ...m.features
90
103
  }
91
- p.signalMarkers && _.setSignalMarkers(p.signalMarkers), p.signalMarkerStyle && _.setSignalMarkerStyle(p.signalMarkerStyle), p.tradeZones && _.setTradeZones(p.tradeZones), p.tradeZoneStyle && _.setTradeZoneStyle(p.tradeZoneStyle), m("ready", _);
92
- }
104
+ }), m.data ? v.setData(m.data) : C(), d(v, x(m.indicators), y), m.signalMarkers && v.setSignalMarkers(m.signalMarkers), m.signalMarkerStyle && v.setSignalMarkerStyle(m.signalMarkerStyle), m.tradeZones && v.setTradeZones(m.tradeZones), m.tradeZoneStyle && v.setTradeZoneStyle(m.tradeZoneStyle), m.overrides && v.setOverrides(m.overrides), h("ready", v));
93
105
  }), r(() => {
94
- _ &&= (_.disconnectStream(), _.destroy(), null);
95
- }), o(() => [p.symbol, p.timeframe], ([e, t]) => {
96
- if (!_ || p.data) return;
97
- _.disconnectStream();
98
- let n = p.adapter ?? new s();
99
- _.connect({
100
- adapter: n,
101
- symbol: e,
102
- timeframe: t,
103
- historyLimit: p.historyLimit
104
- }), p.watermarkText && _.setWatermark(p.watermarkText);
105
- }), o(() => p.theme, (e) => {
106
- _?.setTheme(h(e));
107
- }), o(() => p.chartType, (e) => {
108
- _?.setChartType(e);
109
- }), o(() => p.data, (e) => {
110
- e && _?.setData(e);
111
- }, { deep: !0 }), o(() => p.indicators, (e) => {
112
- if (!_) return;
113
- let t = new Set(e);
114
- for (let [e, n] of v) t.has(e) || (_.removeIndicator(n), v.delete(e));
115
- for (let t of e) if (!v.has(t)) {
116
- let e = _.addIndicator(t);
117
- e && v.set(t, e);
118
- }
119
- }, { deep: !0 }), o(() => p.signalMarkers, (e) => {
120
- e && _?.setSignalMarkers(e);
121
- }, { deep: !0 }), o(() => p.signalMarkerStyle, (e) => {
122
- e && _?.setSignalMarkerStyle(e);
123
- }, { deep: !0 }), o(() => p.tradeZones, (e) => {
124
- e && _?.setTradeZones(e);
125
- }, { deep: !0 }), o(() => p.tradeZoneStyle, (e) => {
126
- e && _?.setTradeZoneStyle(e);
106
+ v &&= (v.disconnectStream(), v.destroy(), null);
107
+ }), o(() => [
108
+ m.symbol,
109
+ m.timeframe,
110
+ !m.data,
111
+ m.stream
112
+ ], C), o(() => m.features, (e) => {
113
+ let t = JSON.stringify(e ?? null);
114
+ t !== S && (S = t, e && v?.setFeatures({ ...e }));
115
+ }, { deep: !0 }), o(() => m.theme, (e) => {
116
+ v?.setTheme(g(e));
117
+ }), o(() => m.chartType, (e) => {
118
+ v?.setChartType(e);
119
+ }), o(() => m.data, (e) => {
120
+ e && v?.setData(e);
121
+ }, { deep: !0 }), o(() => m.indicators, (e) => {
122
+ v && d(v, x(e), y);
123
+ }, { deep: !0 }), o(() => m.signalMarkers, (e) => {
124
+ e && v?.setSignalMarkers(e);
125
+ }, { deep: !0 }), o(() => m.signalMarkerStyle, (e) => {
126
+ e && v?.setSignalMarkerStyle(e);
127
+ }, { deep: !0 }), o(() => m.tradeZones, (e) => {
128
+ e && v?.setTradeZones(e);
129
+ }, { deep: !0 }), o(() => m.tradeZoneStyle, (e) => {
130
+ e && v?.setTradeZoneStyle(e);
131
+ }, { deep: !0 }), o(() => m.overrides, (e) => {
132
+ v?.setOverrides({ ...e });
127
133
  }, { deep: !0 }), (t, n) => (i(), e("div", {
128
134
  ref_key: "containerEl",
129
- ref: g,
135
+ ref: _,
130
136
  style: {
131
137
  width: "100%",
132
138
  height: "100%"
@@ -135,6 +141,6 @@ var d = /* @__PURE__ */ t({
135
141
  }
136
142
  });
137
143
  //#endregion
138
- export { d as TradeCanvas };
144
+ export { f as TradeCanvas };
139
145
 
140
146
  //# sourceMappingURL=index.js.map
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 syncIndicators,\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 IndicatorSpec,\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 by id (`'rsi'`), or with their inputs (`{ id: 'ema', params: { period: 50 } }`). */\n indicators?: IndicatorSpec[];\n /** Static bars: the chart shows these, and opens no stream of its own when it has them at mount. */\n data?: OHLCBar[];\n adapter?: DataAdapter;\n /** `false`: no stream until you say so (no Binance by default); the chart waits for `data`. Default `true`. */\n stream?: boolean;\n historyLimit?: number;\n /** What users can do on the chart; changes after mount are applied too (the keys given). */\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 stream: true,\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/** The stream open now (`symbol|timeframe`), or null. */\nlet streamKey: string | null = null;\n\n/** The specs as plain values (not Vue's proxies), for the chart to keep. */\nconst plainSpecs = (specs: readonly IndicatorSpec[]): IndicatorSpec[] =>\n specs.map((spec) => (typeof spec === 'string'\n ? spec\n : { id: spec.id, ...(spec.params ? { params: { ...spec.params } } : {}), ...(spec.position ? { position: spec.position } : {}) }));\n/** The features last applied, as text. */\nlet featuresKey = JSON.stringify(props.features ?? null);\n\n/** A stream of its own while it has no data; `stream: false` closes it. Data given later leaves it be. */\nfunction syncStream(): void {\n if (!chart) return;\n if (!props.stream) {\n if (streamKey !== null) chart.disconnectStream();\n streamKey = null;\n return;\n }\n if (props.data) return;\n const key = `${props.symbol}|${props.timeframe}`;\n if (streamKey === key) return;\n const opened = streamKey !== null;\n streamKey = key;\n if (opened) chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n if (opened && props.watermarkText) chart.setWatermark(props.watermarkText);\n}\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) chart.setData(props.data);\n else syncStream();\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 syncIndicators(chart, plainSpecs(props.indicators), indicatorIds);\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(() => [props.symbol, props.timeframe, !props.data, props.stream] as const, syncStream);\nwatch(() => props.features, (f) => {\n const key = JSON.stringify(f ?? null);\n if (key === featuresKey) return;\n featuresKey = key;\n if (f) chart?.setFeatures({ ...f });\n}, { deep: true });\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 (specs) => { if (chart) syncIndicators(chart, plainSpecs(specs), indicatorIds); },\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 syncIndicators,\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 IndicatorSpec,\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 by id (`'rsi'`), or with their inputs (`{ id: 'ema', params: { period: 50 } }`). */\n indicators?: IndicatorSpec[];\n /** Static bars: the chart shows these, and opens no stream of its own when it has them at mount. */\n data?: OHLCBar[];\n adapter?: DataAdapter;\n /** `false`: no stream until you say so (no Binance by default); the chart waits for `data`. Default `true`. */\n stream?: boolean;\n historyLimit?: number;\n /** What users can do on the chart; changes after mount are applied too (the keys given). */\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 stream: true,\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/** The stream open now (`symbol|timeframe`), or null. */\nlet streamKey: string | null = null;\n\n/** The specs as plain values (not Vue's proxies), for the chart to keep. */\nconst plainSpecs = (specs: readonly IndicatorSpec[]): IndicatorSpec[] =>\n specs.map((spec) => (typeof spec === 'string'\n ? spec\n : { id: spec.id, ...(spec.params ? { params: { ...spec.params } } : {}), ...(spec.position ? { position: spec.position } : {}) }));\n/** The features last applied, as text. */\nlet featuresKey = JSON.stringify(props.features ?? null);\n\n/** A stream of its own while it has no data; `stream: false` closes it. Data given later leaves it be. */\nfunction syncStream(): void {\n if (!chart) return;\n if (!props.stream) {\n if (streamKey !== null) chart.disconnectStream();\n streamKey = null;\n return;\n }\n if (props.data) return;\n const key = `${props.symbol}|${props.timeframe}`;\n if (streamKey === key) return;\n const opened = streamKey !== null;\n streamKey = key;\n if (opened) chart.disconnectStream();\n const adapter = props.adapter ?? new BinanceAdapter();\n chart.connect({ adapter, symbol: props.symbol, timeframe: props.timeframe, historyLimit: props.historyLimit });\n if (opened && props.watermarkText) chart.setWatermark(props.watermarkText);\n}\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) chart.setData(props.data);\n else syncStream();\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 syncIndicators(chart, plainSpecs(props.indicators), indicatorIds);\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(() => [props.symbol, props.timeframe, !props.data, props.stream] as const, syncStream);\nwatch(() => props.features, (f) => {\n const key = JSON.stringify(f ?? null);\n if (key === featuresKey) return;\n featuresKey = key;\n if (f) chart?.setFeatures({ ...f });\n}, { deep: true });\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 (specs) => { if (chart) syncIndicators(chart, plainSpecs(specs), indicatorIds); },\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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tradecanvas/vue",
3
- "version": "1.0.15",
3
+ "version": "1.2.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.12.0"
37
+ "@tradecanvas/chart": "1.14.0"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "vue": ">=3.3.0"