velo-plot 1.15.0 → 2.0.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.
Files changed (104) hide show
  1. package/dist/{ChartCore-BimVvUEg.js → ChartCore-BhQ4j7f5.js} +2213 -1489
  2. package/dist/ChartCore-BhQ4j7f5.js.map +1 -0
  3. package/dist/SciPlot-GJvw7GJo.js +463 -0
  4. package/dist/SciPlot-GJvw7GJo.js.map +1 -0
  5. package/dist/assets/downsample.worker-C70QJ04y.js +2 -0
  6. package/dist/assets/downsample.worker-C70QJ04y.js.map +1 -0
  7. package/dist/assets/indicator.worker-bv0zC4EX.js +2 -0
  8. package/dist/assets/indicator.worker-bv0zC4EX.js.map +1 -0
  9. package/dist/axisFormat-SPX-CD5s.js +200 -0
  10. package/dist/axisFormat-SPX-CD5s.js.map +1 -0
  11. package/dist/core/InteractionManager.d.ts +1 -0
  12. package/dist/core/OverlayRenderer.d.ts +13 -0
  13. package/dist/core/chart/ChartAlerts.d.ts +42 -0
  14. package/dist/core/chart/ChartCore.d.ts +24 -1
  15. package/dist/core/chart/ChartRenderLoop.d.ts +9 -2
  16. package/dist/core/chart/ChartRenderer.d.ts +8 -2
  17. package/dist/core/chart/candlestickMarkers.d.ts +23 -0
  18. package/dist/core/chart/heikinAshi.d.ts +10 -0
  19. package/dist/core/chart/positionLines.d.ts +12 -0
  20. package/dist/core/chart/series/types.d.ts +2 -2
  21. package/dist/core/chart/types.d.ts +9 -0
  22. package/dist/core/format/axisFormat.d.ts +2 -1
  23. package/dist/core/indicator/addIndicator.d.ts +36 -0
  24. package/dist/core/indicator/index.d.ts +2 -0
  25. package/dist/core/indicator/indicatorPresets.d.ts +45 -0
  26. package/dist/core/series/Series.d.ts +3 -0
  27. package/dist/core/stacked/types.d.ts +8 -0
  28. package/dist/core/time/TimeScale.d.ts +31 -0
  29. package/dist/core/time/applyTimeScale.d.ts +10 -0
  30. package/dist/createStackedChart-DJSmqerD.js +706 -0
  31. package/dist/createStackedChart-DJSmqerD.js.map +1 -0
  32. package/dist/gpu/adapter/gpuRenderer.d.ts +21 -0
  33. package/dist/gpu/backends/webgpu/WebGPUBackend.d.ts +2 -1
  34. package/dist/gpuRenderer-BpaMYz-k.js +1848 -0
  35. package/dist/gpuRenderer-BpaMYz-k.js.map +1 -0
  36. package/dist/{index-DjeWClO9.js → index-CWipqOLP.js} +2 -2
  37. package/dist/{index-DjeWClO9.js.map → index-CWipqOLP.js.map} +1 -1
  38. package/dist/index-D7dTq6VB.js +503 -0
  39. package/dist/index-D7dTq6VB.js.map +1 -0
  40. package/dist/{index-Ce2JgkH_.js → index-DoYxf1cV.js} +86 -43
  41. package/dist/{index-Ce2JgkH_.js.map → index-DoYxf1cV.js.map} +1 -1
  42. package/dist/{index.core-C_-CFftD.js → index.core-fpZ1dYN0.js} +3 -3
  43. package/dist/{index.core-C_-CFftD.js.map → index.core-fpZ1dYN0.js.map} +1 -1
  44. package/dist/index.d.ts +17 -4
  45. package/dist/indicators--eJGmVox.js +302 -0
  46. package/dist/indicators--eJGmVox.js.map +1 -0
  47. package/dist/mockDatafeed-Cdg5hKEo.js +511 -0
  48. package/dist/mockDatafeed-Cdg5hKEo.js.map +1 -0
  49. package/dist/plugins/analysis.js +530 -807
  50. package/dist/plugins/analysis.js.map +1 -1
  51. package/dist/plugins/caching.js +26 -21
  52. package/dist/plugins/caching.js.map +1 -1
  53. package/dist/plugins/drawing-tools/index.d.ts +29 -0
  54. package/dist/plugins/drawing-tools/measure.d.ts +21 -0
  55. package/dist/plugins/drawing-tools/snapToCandle.d.ts +21 -0
  56. package/dist/plugins/gpu.js +202 -1895
  57. package/dist/plugins/gpu.js.map +1 -1
  58. package/dist/plugins/index.d.ts +2 -0
  59. package/dist/plugins/keyboard/index.d.ts +1 -7
  60. package/dist/plugins/keyboard.js +1 -1
  61. package/dist/plugins/lazy-load/types.d.ts +7 -0
  62. package/dist/plugins/lazy-load.js +131 -108
  63. package/dist/plugins/lazy-load.js.map +1 -1
  64. package/dist/plugins/replay/index.d.ts +19 -0
  65. package/dist/plugins/tools.js +1 -1
  66. package/dist/plugins/virtualization/types.d.ts +12 -0
  67. package/dist/plugins/virtualization.js +1 -1
  68. package/dist/pool-15HMCNv8.js +88 -0
  69. package/dist/pool-15HMCNv8.js.map +1 -0
  70. package/dist/react.js +5 -5
  71. package/dist/renderer/CandlestickRenderer.d.ts +1 -1
  72. package/dist/renderer/ChartSeriesRenderer.d.ts +6 -0
  73. package/dist/renderer/GpuChartRenderer.d.ts +23 -0
  74. package/dist/renderer/index.d.ts +3 -0
  75. package/dist/renderer/spike/WebGLGridSpike.d.ts +40 -0
  76. package/dist/testing/baselines/v1.15.0.json.d.ts +51 -0
  77. package/dist/testing/gridSpikeBenchmark.d.ts +49 -0
  78. package/dist/testing/index.d.ts +5 -0
  79. package/dist/testing/rendererBenchmark.d.ts +13 -0
  80. package/dist/testing/stage1BrowserBench.d.ts +42 -0
  81. package/dist/trading/datafeed.d.ts +48 -0
  82. package/dist/trading/index.d.ts +29 -0
  83. package/dist/trading/mockDatafeed.d.ts +9 -0
  84. package/dist/trading/ohlcvGenerator.d.ts +25 -0
  85. package/dist/trading.d.ts +1 -0
  86. package/dist/trading.js +95 -0
  87. package/dist/trading.js.map +1 -0
  88. package/dist/types.d.ts +22 -2
  89. package/dist/velo-plot.full.js +1088 -776
  90. package/dist/velo-plot.full.js.map +1 -1
  91. package/dist/velo-plot.js +15 -15
  92. package/dist/workers/downsample.d.ts +38 -0
  93. package/dist/workers/downsampleAsync.d.ts +6 -0
  94. package/dist/workers/indicator.worker.d.ts +32 -0
  95. package/dist/workers/indicatorsAsync.d.ts +26 -0
  96. package/dist/workers/pool.d.ts +36 -0
  97. package/package.json +23 -1
  98. package/dist/ChartCore-BimVvUEg.js.map +0 -1
  99. package/dist/axisFormat-B7o_uIEA.js +0 -127
  100. package/dist/axisFormat-B7o_uIEA.js.map +0 -1
  101. package/dist/createStackedChart-CjsKcOvX.js +0 -1088
  102. package/dist/createStackedChart-CjsKcOvX.js.map +0 -1
  103. package/dist/index-ChgIdk3N.js +0 -229
  104. package/dist/index-ChgIdk3N.js.map +0 -1
@@ -21,8 +21,8 @@ const x = {
21
21
  },
22
22
  debug: !1
23
23
  };
24
- function k(y = {}) {
25
- const s = { ...$, ...y };
24
+ function k(p = {}) {
25
+ const s = { ...$, ...p };
26
26
  let f = null;
27
27
  const o = /* @__PURE__ */ new Map(), r = {
28
28
  hits: 0,
@@ -38,7 +38,7 @@ function k(y = {}) {
38
38
  0
39
39
  ) : 100;
40
40
  }
41
- function p(e) {
41
+ function z(e) {
42
42
  if (o.size === 0) return;
43
43
  const t = Array.from(o.entries());
44
44
  s.strategy === "lru" ? t.sort((a, l) => a[1].lastAccess - l[1].lastAccess) : s.strategy === "lfu" && t.sort((a, l) => a[1].hits - l[1].hits);
@@ -60,7 +60,7 @@ function k(y = {}) {
60
60
  o.delete(i);
61
61
  return s.debug && t.length > 0 && console.log(`[Cache] Pruned ${t.length} expired entries`), t.length;
62
62
  }
63
- function z(e) {
63
+ function b(e) {
64
64
  if (!s.enabled) return;
65
65
  const t = o.get(e);
66
66
  if (!t) {
@@ -73,12 +73,12 @@ function k(y = {}) {
73
73
  }
74
74
  return t.lastAccess = Date.now(), t.hits++, r.hits++, s.debug && console.log(`[Cache] HIT: ${e}`), t.value;
75
75
  }
76
- function b(e, t, i = {}) {
76
+ function v(e, t, i = {}) {
77
77
  if (!s.enabled) return;
78
78
  const n = i.size ?? u(t);
79
79
  if (c + n > s.maxSize) {
80
- const T = c + n - s.maxSize;
81
- p(T);
80
+ const A = c + n - s.maxSize;
81
+ z(A);
82
82
  }
83
83
  if (n > s.maxSize) {
84
84
  console.warn(`[Cache] Value too large to cache: ${e} (${n} bytes)`);
@@ -97,7 +97,7 @@ function k(y = {}) {
97
97
  };
98
98
  o.set(e, l), c += n, s.debug && console.log(`[Cache] SET: ${e} (${n} bytes)`);
99
99
  }
100
- function v(e) {
100
+ function T(e) {
101
101
  return o.has(e);
102
102
  }
103
103
  function I(e) {
@@ -112,7 +112,7 @@ function k(y = {}) {
112
112
  timestamp: Date.now()
113
113
  });
114
114
  }
115
- function S(e) {
115
+ function y(e) {
116
116
  const t = [];
117
117
  for (const [i, n] of o.entries())
118
118
  n.tags && n.tags.some((a) => e.includes(a)) && (t.push(i), c -= n.size);
@@ -124,7 +124,7 @@ function k(y = {}) {
124
124
  timestamp: Date.now()
125
125
  }), t.length;
126
126
  }
127
- function w() {
127
+ function C() {
128
128
  const e = r.hits + r.misses;
129
129
  return {
130
130
  hits: r.hits,
@@ -136,26 +136,26 @@ function k(y = {}) {
136
136
  evictions: r.evictions
137
137
  };
138
138
  }
139
- function A() {
139
+ function D() {
140
140
  r.hits = 0, r.misses = 0, r.evictions = 0;
141
141
  }
142
- function C() {
142
+ function S() {
143
143
  return Array.from(o.keys());
144
144
  }
145
- function D() {
145
+ function w() {
146
146
  return o.size;
147
147
  }
148
148
  const m = {
149
- get: z,
150
- set: b,
151
- has: v,
149
+ get: b,
150
+ set: v,
151
+ has: T,
152
152
  delete: I,
153
153
  clear: h,
154
- invalidateByTags: S,
155
- getStats: w,
156
- resetStats: A,
157
- keys: C,
158
- size: D,
154
+ invalidateByTags: y,
155
+ getStats: C,
156
+ resetStats: D,
157
+ keys: S,
158
+ size: w,
159
159
  prune: g,
160
160
  updateConfig(e) {
161
161
  Object.assign(s, e);
@@ -169,6 +169,11 @@ function k(y = {}) {
169
169
  g();
170
170
  }, 6e4);
171
171
  },
172
+ onDataUpdate(e) {
173
+ if (!s.autoInvalidate) return;
174
+ const t = [];
175
+ s.cacheTypes.transforms && t.push("transform"), s.cacheTypes.analysis && t.push("analysis"), s.cacheTypes.bounds && t.push("bounds"), t.length > 0 && y(t);
176
+ },
172
177
  onDestroy(e) {
173
178
  d !== null && clearInterval(d), h(), delete e.chart.caching, f = null;
174
179
  },
@@ -1 +1 @@
1
- {"version":3,"file":"caching.js","sources":["../../src/plugins/caching/index.ts"],"sourcesContent":["/**\n * @fileoverview Advanced caching plugin for performance optimization\n * @module plugins/caching\n */\n\nimport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n} from './types';\nimport type {\n ChartPlugin,\n PluginContext,\n PluginManifest,\n} from '../types';\n\nconst manifest: PluginManifest = {\n name: 'velo-plot-caching',\n version: '1.0.0',\n description: 'Advanced caching system for performance optimization',\n provides: ['caching', 'performance'],\n tags: ['optimization', 'cache', 'memory'],\n};\n\nconst DEFAULT_CONFIG: Required<PluginCachingConfig> = {\n enabled: true,\n maxSize: 50 * 1024 * 1024, // 50MB\n strategy: 'lru',\n defaultTTL: undefined as any,\n autoInvalidate: true,\n cacheTypes: {\n transforms: true,\n analysis: true,\n frames: false,\n bounds: true,\n },\n onInvalidate: () => {},\n debug: false,\n};\n\nexport function PluginCaching(\n userConfig: Partial<PluginCachingConfig> = {}\n): ChartPlugin<PluginCachingConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n\n // Cache storage\n const cache = new Map<string, CacheEntry>();\n \n // Statistics\n const stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n };\n \n let currentSize = 0;\n\n /**\n * Estimate size of value in bytes\n */\n function estimateSize(value: any): number {\n if (value === null || value === undefined) return 0;\n \n const type = typeof value;\n \n if (type === 'boolean') return 4;\n if (type === 'number') return 8;\n if (type === 'string') return value.length * 2;\n \n if (value instanceof Float32Array || value instanceof Float64Array) {\n return value.byteLength;\n }\n \n if (Array.isArray(value)) {\n return value.reduce((sum, item) => sum + estimateSize(item), 0);\n }\n \n if (type === 'object') {\n return Object.keys(value).reduce(\n (sum, key) => sum + key.length * 2 + estimateSize(value[key]),\n 0\n );\n }\n \n return 100; // Default estimate\n }\n\n /**\n * Evict entries based on strategy\n */\n function evict(requiredSpace: number): void {\n if (cache.size === 0) return;\n\n const entries = Array.from(cache.entries());\n \n // Sort based on strategy\n if (config.strategy === 'lru') {\n // Least recently used\n entries.sort((a, b) => a[1].lastAccess - b[1].lastAccess);\n } else if (config.strategy === 'lfu') {\n // Least frequently used\n entries.sort((a, b) => a[1].hits - b[1].hits);\n }\n // FIFO is already in insertion order (Map preserves order)\n \n let freedSpace = 0;\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of entries) {\n if (freedSpace >= requiredSpace) break;\n \n keysToDelete.push(key);\n freedSpace += entry.size;\n currentSize -= entry.size;\n stats.evictions++;\n }\n \n // Delete entries\n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Evicted ${keysToDelete.length} entries, freed ${freedSpace} bytes`);\n }\n }\n\n /**\n * Prune expired entries\n */\n function pruneExpired(): number {\n const now = Date.now();\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.ttl && now - entry.timestamp > entry.ttl) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Pruned ${keysToDelete.length} expired entries`);\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get value from cache\n */\n function get<T>(key: string): T | undefined {\n if (!config.enabled) return undefined;\n \n const entry = cache.get(key);\n \n if (!entry) {\n stats.misses++;\n return undefined;\n }\n \n // Check TTL\n if (entry.ttl) {\n const age = Date.now() - entry.timestamp;\n if (age > entry.ttl) {\n cache.delete(key);\n currentSize -= entry.size;\n stats.misses++;\n return undefined;\n }\n }\n \n // Update access metadata\n entry.lastAccess = Date.now();\n entry.hits++;\n stats.hits++;\n \n if (config.debug) {\n console.log(`[Cache] HIT: ${key}`);\n }\n \n return entry.value as T;\n }\n\n /**\n * Set value in cache\n */\n function set<T>(\n key: string,\n value: T,\n options: { ttl?: number; tags?: string[]; size?: number } = {}\n ): void {\n if (!config.enabled) return;\n \n // Estimate size\n const size = options.size ?? estimateSize(value);\n \n // Check if we need to evict\n if (currentSize + size > config.maxSize) {\n const requiredSpace = currentSize + size - config.maxSize;\n evict(requiredSpace);\n }\n \n // Still too large after eviction?\n if (size > config.maxSize) {\n console.warn(`[Cache] Value too large to cache: ${key} (${size} bytes)`);\n return;\n }\n \n // Remove old entry if exists\n const oldEntry = cache.get(key);\n if (oldEntry) {\n currentSize -= oldEntry.size;\n }\n \n // Create entry\n const entry: CacheEntry<T> = {\n value,\n timestamp: Date.now(),\n lastAccess: Date.now(),\n hits: 0,\n size,\n ttl: options.ttl ?? config.defaultTTL,\n tags: options.tags,\n };\n \n cache.set(key, entry);\n currentSize += size;\n \n if (config.debug) {\n console.log(`[Cache] SET: ${key} (${size} bytes)`);\n }\n }\n\n /**\n * Check if key exists\n */\n function has(key: string): boolean {\n return cache.has(key);\n }\n\n /**\n * Delete specific key\n */\n function deleteKey(key: string): boolean {\n const entry = cache.get(key);\n if (entry) {\n currentSize -= entry.size;\n return cache.delete(key);\n }\n return false;\n }\n\n /**\n * Clear all cache\n */\n function clear(): void {\n const count = cache.size;\n cache.clear();\n currentSize = 0;\n \n if (config.debug) {\n console.log(`[Cache] Cleared ${count} entries`);\n }\n \n if (config.onInvalidate) {\n config.onInvalidate({\n keys: [],\n reason: 'manual',\n timestamp: Date.now(),\n });\n }\n }\n\n /**\n * Invalidate by tags\n */\n function invalidateByTags(tags: string[]): number {\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.tags && entry.tags.some(tag => tags.includes(tag))) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Invalidated ${keysToDelete.length} entries by tags:`, tags);\n }\n \n if (config.onInvalidate && keysToDelete.length > 0) {\n config.onInvalidate({\n keys: keysToDelete,\n reason: 'tag',\n timestamp: Date.now(),\n });\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get cache statistics\n */\n function getStats(): CacheStats {\n const total = stats.hits + stats.misses;\n \n return {\n hits: stats.hits,\n misses: stats.misses,\n hitRatio: total > 0 ? stats.hits / total : 0,\n currentSize,\n maxSize: config.maxSize,\n entryCount: cache.size,\n evictions: stats.evictions,\n };\n }\n\n /**\n * Reset statistics\n */\n function resetStats(): void {\n stats.hits = 0;\n stats.misses = 0;\n stats.evictions = 0;\n }\n\n /**\n * Get all keys\n */\n function keys(): string[] {\n return Array.from(cache.keys());\n }\n\n /**\n * Get cache size\n */\n function size(): number {\n return cache.size;\n }\n\n // API implementation\n const api: CachingAPI & Record<string, unknown> = {\n get,\n set,\n has,\n delete: deleteKey,\n clear,\n invalidateByTags,\n getStats,\n resetStats,\n keys,\n size,\n prune: pruneExpired,\n updateConfig(newConfig: Partial<PluginCachingConfig>) {\n Object.assign(config, newConfig);\n },\n };\n\n // Periodic cleanup\n let cleanupInterval: number | null = null;\n\n return {\n manifest,\n\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n\n // Attach to chart API\n (ctx.chart as any).caching = api;\n\n // Setup periodic cleanup (every 60 seconds)\n cleanupInterval = window.setInterval(() => {\n pruneExpired();\n }, 60000);\n\n // TODO: Auto-invalidate on data changes if enabled\n // Requires 'dataUpdate' event to be added to ChartEventMap\n // if (config.autoInvalidate) {\n // ctx.chart.on?.('dataUpdate', () => {\n // if (config.cacheTypes.transforms) invalidateByTags(['transform']);\n // if (config.cacheTypes.analysis) invalidateByTags(['analysis']);\n // if (config.cacheTypes.bounds) invalidateByTags(['bounds']);\n // });\n // }\n },\n\n onDestroy(pluginCtx: PluginContext) {\n // Clear cleanup interval\n if (cleanupInterval !== null) {\n clearInterval(cleanupInterval);\n }\n\n // Clear cache\n clear();\n\n // Remove from chart API\n delete (pluginCtx.chart as any).caching;\n\n ctx = null;\n },\n\n api,\n };\n}\n\nexport default PluginCaching;\n\n// Type exports\nexport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n CacheStrategy,\n CacheInvalidationEvent,\n} from './types';\n"],"names":["manifest","DEFAULT_CONFIG","PluginCaching","userConfig","config","ctx","cache","stats","currentSize","estimateSize","value","type","sum","item","key","evict","requiredSpace","entries","b","freedSpace","keysToDelete","entry","pruneExpired","now","get","set","options","size","oldEntry","has","deleteKey","clear","count","invalidateByTags","tags","tag","getStats","total","resetStats","keys","api","newConfig","cleanupInterval","pluginCtx"],"mappings":"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"}
1
+ {"version":3,"file":"caching.js","sources":["../../src/plugins/caching/index.ts"],"sourcesContent":["/**\n * @fileoverview Advanced caching plugin for performance optimization\n * @module plugins/caching\n */\n\nimport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n} from './types';\nimport type {\n ChartPlugin,\n PluginContext,\n PluginManifest,\n} from '../types';\n\nconst manifest: PluginManifest = {\n name: 'velo-plot-caching',\n version: '1.0.0',\n description: 'Advanced caching system for performance optimization',\n provides: ['caching', 'performance'],\n tags: ['optimization', 'cache', 'memory'],\n};\n\nconst DEFAULT_CONFIG: Required<PluginCachingConfig> = {\n enabled: true,\n maxSize: 50 * 1024 * 1024, // 50MB\n strategy: 'lru',\n defaultTTL: undefined as any,\n autoInvalidate: true,\n cacheTypes: {\n transforms: true,\n analysis: true,\n frames: false,\n bounds: true,\n },\n onInvalidate: () => {},\n debug: false,\n};\n\nexport function PluginCaching(\n userConfig: Partial<PluginCachingConfig> = {}\n): ChartPlugin<PluginCachingConfig> {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n let ctx: PluginContext | null = null;\n\n // Cache storage\n const cache = new Map<string, CacheEntry>();\n \n // Statistics\n const stats = {\n hits: 0,\n misses: 0,\n evictions: 0,\n };\n \n let currentSize = 0;\n\n /**\n * Estimate size of value in bytes\n */\n function estimateSize(value: any): number {\n if (value === null || value === undefined) return 0;\n \n const type = typeof value;\n \n if (type === 'boolean') return 4;\n if (type === 'number') return 8;\n if (type === 'string') return value.length * 2;\n \n if (value instanceof Float32Array || value instanceof Float64Array) {\n return value.byteLength;\n }\n \n if (Array.isArray(value)) {\n return value.reduce((sum, item) => sum + estimateSize(item), 0);\n }\n \n if (type === 'object') {\n return Object.keys(value).reduce(\n (sum, key) => sum + key.length * 2 + estimateSize(value[key]),\n 0\n );\n }\n \n return 100; // Default estimate\n }\n\n /**\n * Evict entries based on strategy\n */\n function evict(requiredSpace: number): void {\n if (cache.size === 0) return;\n\n const entries = Array.from(cache.entries());\n \n // Sort based on strategy\n if (config.strategy === 'lru') {\n // Least recently used\n entries.sort((a, b) => a[1].lastAccess - b[1].lastAccess);\n } else if (config.strategy === 'lfu') {\n // Least frequently used\n entries.sort((a, b) => a[1].hits - b[1].hits);\n }\n // FIFO is already in insertion order (Map preserves order)\n \n let freedSpace = 0;\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of entries) {\n if (freedSpace >= requiredSpace) break;\n \n keysToDelete.push(key);\n freedSpace += entry.size;\n currentSize -= entry.size;\n stats.evictions++;\n }\n \n // Delete entries\n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Evicted ${keysToDelete.length} entries, freed ${freedSpace} bytes`);\n }\n }\n\n /**\n * Prune expired entries\n */\n function pruneExpired(): number {\n const now = Date.now();\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.ttl && now - entry.timestamp > entry.ttl) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Pruned ${keysToDelete.length} expired entries`);\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get value from cache\n */\n function get<T>(key: string): T | undefined {\n if (!config.enabled) return undefined;\n \n const entry = cache.get(key);\n \n if (!entry) {\n stats.misses++;\n return undefined;\n }\n \n // Check TTL\n if (entry.ttl) {\n const age = Date.now() - entry.timestamp;\n if (age > entry.ttl) {\n cache.delete(key);\n currentSize -= entry.size;\n stats.misses++;\n return undefined;\n }\n }\n \n // Update access metadata\n entry.lastAccess = Date.now();\n entry.hits++;\n stats.hits++;\n \n if (config.debug) {\n console.log(`[Cache] HIT: ${key}`);\n }\n \n return entry.value as T;\n }\n\n /**\n * Set value in cache\n */\n function set<T>(\n key: string,\n value: T,\n options: { ttl?: number; tags?: string[]; size?: number } = {}\n ): void {\n if (!config.enabled) return;\n \n // Estimate size\n const size = options.size ?? estimateSize(value);\n \n // Check if we need to evict\n if (currentSize + size > config.maxSize) {\n const requiredSpace = currentSize + size - config.maxSize;\n evict(requiredSpace);\n }\n \n // Still too large after eviction?\n if (size > config.maxSize) {\n console.warn(`[Cache] Value too large to cache: ${key} (${size} bytes)`);\n return;\n }\n \n // Remove old entry if exists\n const oldEntry = cache.get(key);\n if (oldEntry) {\n currentSize -= oldEntry.size;\n }\n \n // Create entry\n const entry: CacheEntry<T> = {\n value,\n timestamp: Date.now(),\n lastAccess: Date.now(),\n hits: 0,\n size,\n ttl: options.ttl ?? config.defaultTTL,\n tags: options.tags,\n };\n \n cache.set(key, entry);\n currentSize += size;\n \n if (config.debug) {\n console.log(`[Cache] SET: ${key} (${size} bytes)`);\n }\n }\n\n /**\n * Check if key exists\n */\n function has(key: string): boolean {\n return cache.has(key);\n }\n\n /**\n * Delete specific key\n */\n function deleteKey(key: string): boolean {\n const entry = cache.get(key);\n if (entry) {\n currentSize -= entry.size;\n return cache.delete(key);\n }\n return false;\n }\n\n /**\n * Clear all cache\n */\n function clear(): void {\n const count = cache.size;\n cache.clear();\n currentSize = 0;\n \n if (config.debug) {\n console.log(`[Cache] Cleared ${count} entries`);\n }\n \n if (config.onInvalidate) {\n config.onInvalidate({\n keys: [],\n reason: 'manual',\n timestamp: Date.now(),\n });\n }\n }\n\n /**\n * Invalidate by tags\n */\n function invalidateByTags(tags: string[]): number {\n const keysToDelete: string[] = [];\n \n for (const [key, entry] of cache.entries()) {\n if (entry.tags && entry.tags.some(tag => tags.includes(tag))) {\n keysToDelete.push(key);\n currentSize -= entry.size;\n }\n }\n \n for (const key of keysToDelete) {\n cache.delete(key);\n }\n \n if (config.debug && keysToDelete.length > 0) {\n console.log(`[Cache] Invalidated ${keysToDelete.length} entries by tags:`, tags);\n }\n \n if (config.onInvalidate && keysToDelete.length > 0) {\n config.onInvalidate({\n keys: keysToDelete,\n reason: 'tag',\n timestamp: Date.now(),\n });\n }\n \n return keysToDelete.length;\n }\n\n /**\n * Get cache statistics\n */\n function getStats(): CacheStats {\n const total = stats.hits + stats.misses;\n \n return {\n hits: stats.hits,\n misses: stats.misses,\n hitRatio: total > 0 ? stats.hits / total : 0,\n currentSize,\n maxSize: config.maxSize,\n entryCount: cache.size,\n evictions: stats.evictions,\n };\n }\n\n /**\n * Reset statistics\n */\n function resetStats(): void {\n stats.hits = 0;\n stats.misses = 0;\n stats.evictions = 0;\n }\n\n /**\n * Get all keys\n */\n function keys(): string[] {\n return Array.from(cache.keys());\n }\n\n /**\n * Get cache size\n */\n function size(): number {\n return cache.size;\n }\n\n // API implementation\n const api: CachingAPI & Record<string, unknown> = {\n get,\n set,\n has,\n delete: deleteKey,\n clear,\n invalidateByTags,\n getStats,\n resetStats,\n keys,\n size,\n prune: pruneExpired,\n updateConfig(newConfig: Partial<PluginCachingConfig>) {\n Object.assign(config, newConfig);\n },\n };\n\n // Periodic cleanup\n let cleanupInterval: number | null = null;\n\n return {\n manifest,\n\n onInit(pluginCtx: PluginContext) {\n ctx = pluginCtx;\n\n // Attach to chart API\n (ctx.chart as any).caching = api;\n\n // Setup periodic cleanup (every 60 seconds)\n cleanupInterval = window.setInterval(() => {\n pruneExpired();\n }, 60000);\n },\n\n onDataUpdate(_pluginCtx: PluginContext) {\n if (!config.autoInvalidate) return;\n\n const tags: string[] = [];\n if (config.cacheTypes.transforms) tags.push(\"transform\");\n if (config.cacheTypes.analysis) tags.push(\"analysis\");\n if (config.cacheTypes.bounds) tags.push(\"bounds\");\n\n if (tags.length > 0) {\n invalidateByTags(tags);\n }\n },\n\n onDestroy(pluginCtx: PluginContext) {\n // Clear cleanup interval\n if (cleanupInterval !== null) {\n clearInterval(cleanupInterval);\n }\n\n // Clear cache\n clear();\n\n // Remove from chart API\n delete (pluginCtx.chart as any).caching;\n\n ctx = null;\n },\n\n api,\n };\n}\n\nexport default PluginCaching;\n\n// Type exports\nexport type {\n PluginCachingConfig,\n CachingAPI,\n CacheEntry,\n CacheStats,\n CacheStrategy,\n CacheInvalidationEvent,\n} from './types';\n"],"names":["manifest","DEFAULT_CONFIG","PluginCaching","userConfig","config","ctx","cache","stats","currentSize","estimateSize","value","type","sum","item","key","evict","requiredSpace","entries","b","freedSpace","keysToDelete","entry","pruneExpired","now","get","set","options","size","oldEntry","has","deleteKey","clear","count","invalidateByTags","tags","tag","getStats","total","resetStats","keys","api","newConfig","cleanupInterval","pluginCtx","_pluginCtx"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { ChartPlugin } from '../types';
2
+
3
+ export type DrawingMode = "none" | "pan" | "trendline" | "horizontal" | "vertical" | "rectangle" | "fibonacci" | "measure";
4
+ export interface PluginDrawingToolsConfig {
5
+ /** Default stroke color */
6
+ color?: string;
7
+ /** Enable candle magnet by default */
8
+ magnet?: boolean;
9
+ /** Return to pan mode after each completed stroke (default true) */
10
+ autoDeselect?: boolean;
11
+ /** Notified when drawing mode changes (including auto-deselect to none) */
12
+ onModeChange?: (mode: DrawingMode) => void;
13
+ /** Color for upward measurements (default green) */
14
+ measureUpColor?: string;
15
+ /** Color for downward measurements (default red) */
16
+ measureDownColor?: string;
17
+ }
18
+ export interface DrawingToolsAPI {
19
+ setMode(mode: DrawingMode): void;
20
+ getMode(): DrawingMode;
21
+ setMagnet(enabled: boolean): void;
22
+ isMagnet(): boolean;
23
+ undo(): boolean;
24
+ redo(): boolean;
25
+ clear(): void;
26
+ }
27
+ export declare function PluginDrawingTools(config?: PluginDrawingToolsConfig): ChartPlugin<PluginDrawingToolsConfig>;
28
+ export { snapToCandle, findNearestBarIndex } from './snapToCandle';
29
+ export default PluginDrawingTools;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Measurement helper for the price-range / measure tool (TradingView-style).
3
+ */
4
+ export interface MeasurePoint {
5
+ x: number;
6
+ y: number;
7
+ }
8
+ export interface Measurement {
9
+ /** Absolute price change (end - start) */
10
+ change: number;
11
+ /** Percentage change relative to the start price */
12
+ percent: number;
13
+ /** Number of bars spanned (rounded X distance) */
14
+ bars: number;
15
+ /** True when the range moves up (change >= 0) */
16
+ up: boolean;
17
+ }
18
+ export declare function computeMeasurement(a: MeasurePoint, b: MeasurePoint): Measurement;
19
+ export declare function formatMeasurement(m: Measurement): string;
20
+ /** Compact price formatting used for level labels. */
21
+ export declare function formatPrice(value: number): string;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Snap drawing points to nearest candlestick O/H/L/C (TradingView-style magnet).
3
+ */
4
+ export interface CandleSnapInput {
5
+ x: number;
6
+ y: number;
7
+ barX: Float32Array | Float64Array;
8
+ open: Float32Array | Float64Array;
9
+ high: Float32Array | Float64Array;
10
+ low: Float32Array | Float64Array;
11
+ close: Float32Array | Float64Array;
12
+ dataToPixelX: (x: number) => number;
13
+ dataToPixelY: (y: number) => number;
14
+ pixelThreshold?: number;
15
+ enabled?: boolean;
16
+ }
17
+ export declare function findNearestBarIndex(barX: Float32Array | Float64Array, x: number): number;
18
+ export declare function snapToCandle(input: CandleSnapInput): {
19
+ x: number;
20
+ y: number;
21
+ };