@tradecanvas/vue 1.2.6 → 1.3.1
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/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
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:{},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
|
|
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:{},options:{}},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,{rightMargin:5,crosshair:{mode:`magnet`},...a.options,chartType:a.chartType,theme:s(a.theme),autoScale:a.autoScale,...a.watermarkText?{watermark:{text:a.watermarkText,fontSize:48,color:`rgba(255,255,255,0.03)`}}:{},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.options?.features,...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
|
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 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":"ylBA4BA,IAAM,EAAQ,EAqCR,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,IAErB,EAA2B,KAGzB,EAAc,GAClB,EAAM,IAAK,GAAU,OAAO,GAAS,SACjC,EACA,CAAE,GAAI,EAAK,GAAI,GAAI,EAAK,OAAS,CAAE,OAAQ,CAAE,GAAG,EAAK,OAAQ,CAAE,CAAG,EAAE,CAAG,GAAI,EAAK,SAAW,CAAE,SAAU,EAAK,SAAU,CAAG,EAAE,CAAG,CAAE,CAElI,EAAc,KAAK,UAAU,EAAM,UAAY,KAAK,CAGxD,SAAS,GAAmB,CAC1B,GAAI,CAAC,EAAO,OACZ,GAAI,CAAC,EAAM,OAAQ,CACb,IAAc,MAAM,EAAM,kBAAkB,CAChD,EAAY,KACZ,OAEF,GAAI,EAAM,KAAM,OAChB,IAAM,EAAM,GAAG,EAAM,OAAO,GAAG,EAAM,YACrC,GAAI,IAAc,EAAK,OACvB,IAAM,EAAS,IAAc,KAC7B,EAAY,EACR,GAAQ,EAAM,kBAAkB,CACpC,IAAM,EAAU,EAAM,SAAW,IAAI,EAAA,eACrC,EAAM,QAAQ,CAAE,UAAS,OAAQ,EAAM,OAAQ,UAAW,EAAM,UAAW,aAAc,EAAM,aAAc,CAAC,CAC1G,GAAU,EAAM,eAAe,EAAM,aAAa,EAAM,cAAc,CAG5E,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,EAAY,QAEjB,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,KAAM,EAAM,QAAQ,EAAM,KAAK,CACpC,GAAY,EAKjB,EAAA,EAAA,gBAAe,EAAO,EAAW,EAAM,WAAW,CAAE,EAAa,CAC7D,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,CACnE,EAAM,WAAW,EAAM,aAAa,EAAM,UAAU,CAExD,EAAK,QAAS,EAAM,GACpB,EAEF,EAAA,EAAA,iBAAkB,CAChB,AAGE,KAFA,EAAM,kBAAkB,CACxB,EAAM,SAAS,CACP,OAEV,EAEF,EAAA,EAAA,WAAY,CAAC,EAAM,OAAQ,EAAM,UAAW,CAAC,EAAM,KAAM,EAAM,OAAO,CAAW,EAAW,EAC5F,EAAA,EAAA,WAAY,EAAM,SAAW,GAAM,CACjC,IAAM,EAAM,KAAK,UAAU,GAAK,KAAK,CACjC,IAAQ,IACZ,EAAc,EACV,GAAG,GAAO,YAAY,CAAE,GAAG,EAAG,CAAC,GAClC,CAAE,KAAM,GAAM,CAAC,EAElB,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,GAAU,CAAM,IAAO,EAAA,EAAA,gBAAe,EAAO,EAAW,EAAM,CAAE,EAAa,EAC9E,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,EAEjG,EAAA,EAAA,WAAY,EAAM,UAAY,GAAM,CAAE,GAAO,aAAa,CAAE,GAAG,EAAG,CAAC,EAAK,CAAE,KAAM,GAAM,CAAC,oDAxMjB,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 ChartOptions,\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 * Chart options the props don't cover (`maxBarSpacing`, `rightMargin`,\n * `renderer`…), merged over the component's defaults at mount; later\n * changes are not applied. `chartType`, `theme` and `autoScale` always come\n * from their props.\n */\n options?: Partial<ChartOptions>;\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 rightMargin: 5,\n crosshair: { mode: 'magnet' },\n ...props.options,\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n ...(props.watermarkText\n ? { watermark: { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' } }\n : {}),\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.options?.features,\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 ChartOptions,\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 * Chart options the props don't cover (`maxBarSpacing`, `rightMargin`,\n * `renderer`…), merged over the component's defaults at mount; later\n * changes are not applied. `chartType`, `theme` and `autoScale` always come\n * from their props.\n */\n options?: Partial<ChartOptions>;\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 rightMargin: 5,\n crosshair: { mode: 'magnet' },\n ...props.options,\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n ...(props.watermarkText\n ? { watermark: { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' } }\n : {}),\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.options?.features,\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,4 +1,5 @@
|
|
|
1
1
|
import { Chart } from '@tradecanvas/chart';
|
|
2
|
+
import { ChartOptions } from '@tradecanvas/chart';
|
|
2
3
|
import { ChartStyleOverrides } from '@tradecanvas/chart';
|
|
3
4
|
import { ChartType } from '@tradecanvas/chart';
|
|
4
5
|
import { ComponentOptionsMixin } from 'vue';
|
|
@@ -39,6 +40,13 @@ declare type __VLS_Props = {
|
|
|
39
40
|
/** Style overrides, by key: all of your app's (`chart.setOverrides`). */
|
|
40
41
|
overrides?: ChartStyleOverrides;
|
|
41
42
|
watermarkText?: string;
|
|
43
|
+
/**
|
|
44
|
+
* Chart options the props don't cover (`maxBarSpacing`, `rightMargin`,
|
|
45
|
+
* `renderer`…), merged over the component's defaults at mount; later
|
|
46
|
+
* changes are not applied. `chartType`, `theme` and `autoScale` always come
|
|
47
|
+
* from their props.
|
|
48
|
+
*/
|
|
49
|
+
options?: Partial<ChartOptions>;
|
|
42
50
|
};
|
|
43
51
|
|
|
44
52
|
declare function getChart(): Chart | null;
|
package/dist/index.js
CHANGED
|
@@ -27,7 +27,8 @@ var f = /* @__PURE__ */ t({
|
|
|
27
27
|
tradeZones: {},
|
|
28
28
|
tradeZoneStyle: {},
|
|
29
29
|
overrides: {},
|
|
30
|
-
watermarkText: {}
|
|
30
|
+
watermarkText: {},
|
|
31
|
+
options: {}
|
|
31
32
|
},
|
|
32
33
|
emits: ["ready", "crosshairMove"],
|
|
33
34
|
setup(t, { expose: f, emit: p }) {
|
|
@@ -74,16 +75,17 @@ var f = /* @__PURE__ */ t({
|
|
|
74
75
|
screenshotDataURL: E
|
|
75
76
|
}), n(() => {
|
|
76
77
|
_.value && (v = new c(_.value, {
|
|
78
|
+
rightMargin: 5,
|
|
79
|
+
crosshair: { mode: "magnet" },
|
|
80
|
+
...m.options,
|
|
77
81
|
chartType: m.chartType,
|
|
78
82
|
theme: g(m.theme),
|
|
79
83
|
autoScale: m.autoScale,
|
|
80
|
-
|
|
81
|
-
crosshair: { mode: "magnet" },
|
|
82
|
-
watermark: m.watermarkText ? {
|
|
84
|
+
...m.watermarkText ? { watermark: {
|
|
83
85
|
text: m.watermarkText,
|
|
84
86
|
fontSize: 48,
|
|
85
87
|
color: "rgba(255,255,255,0.03)"
|
|
86
|
-
} :
|
|
88
|
+
} } : {},
|
|
87
89
|
features: {
|
|
88
90
|
drawings: !0,
|
|
89
91
|
drawingMagnet: !0,
|
|
@@ -99,6 +101,7 @@ var f = /* @__PURE__ */ t({
|
|
|
99
101
|
barCountdown: !0,
|
|
100
102
|
logScale: !0,
|
|
101
103
|
watermark: !0,
|
|
104
|
+
...m.options?.features,
|
|
102
105
|
...m.features
|
|
103
106
|
}
|
|
104
107
|
}), 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));
|
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 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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"}
|
|
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 ChartOptions,\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 * Chart options the props don't cover (`maxBarSpacing`, `rightMargin`,\n * `renderer`…), merged over the component's defaults at mount; later\n * changes are not applied. `chartType`, `theme` and `autoScale` always come\n * from their props.\n */\n options?: Partial<ChartOptions>;\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 rightMargin: 5,\n crosshair: { mode: 'magnet' },\n ...props.options,\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n ...(props.watermarkText\n ? { watermark: { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' } }\n : {}),\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.options?.features,\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 ChartOptions,\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 * Chart options the props don't cover (`maxBarSpacing`, `rightMargin`,\n * `renderer`…), merged over the component's defaults at mount; later\n * changes are not applied. `chartType`, `theme` and `autoScale` always come\n * from their props.\n */\n options?: Partial<ChartOptions>;\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 rightMargin: 5,\n crosshair: { mode: 'magnet' },\n ...props.options,\n chartType: props.chartType,\n theme: resolveTheme(props.theme),\n autoScale: props.autoScale,\n ...(props.watermarkText\n ? { watermark: { text: props.watermarkText, fontSize: 48, color: 'rgba(255,255,255,0.03)' } }\n : {}),\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.options?.features,\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,9 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradecanvas/vue",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Vue 3 component for @tradecanvas/chart — reactive props, template ref, zero boilerplate.",
|
|
6
6
|
"license": "MIT",
|
|
7
|
+
"funding": {
|
|
8
|
+
"type": "github",
|
|
9
|
+
"url": "https://github.com/sponsors/bonguynvan"
|
|
10
|
+
},
|
|
7
11
|
"repository": {
|
|
8
12
|
"type": "git",
|
|
9
13
|
"url": "https://github.com/bonguynvan/tradecanvas.git",
|
|
@@ -34,7 +38,7 @@
|
|
|
34
38
|
"README.md"
|
|
35
39
|
],
|
|
36
40
|
"dependencies": {
|
|
37
|
-
"@tradecanvas/chart": "1.
|
|
41
|
+
"@tradecanvas/chart": "1.19.1"
|
|
38
42
|
},
|
|
39
43
|
"peerDependencies": {
|
|
40
44
|
"vue": ">=3.3.0"
|