@tranding-custom-chart/renderer-canvas 0.0.0-stage → 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/README.md +40 -2
  2. package/dist/canvas-engine.d.ts +82 -0
  3. package/dist/canvas-engine.d.ts.map +1 -0
  4. package/dist/canvas-engine.js +594 -0
  5. package/dist/dpi.d.ts +31 -0
  6. package/dist/dpi.d.ts.map +1 -0
  7. package/dist/dpi.js +65 -0
  8. package/dist/index.d.ts +38 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +37 -0
  11. package/dist/renderers/bar-renderer.d.ts +26 -0
  12. package/dist/renderers/bar-renderer.d.ts.map +1 -0
  13. package/dist/renderers/bar-renderer.js +45 -0
  14. package/dist/renderers/baseline-renderer.d.ts +20 -0
  15. package/dist/renderers/baseline-renderer.d.ts.map +1 -0
  16. package/dist/renderers/baseline-renderer.js +101 -0
  17. package/dist/renderers/box-plot-renderer.d.ts +14 -0
  18. package/dist/renderers/box-plot-renderer.d.ts.map +1 -0
  19. package/dist/renderers/box-plot-renderer.js +76 -0
  20. package/dist/renderers/bubble-renderer.d.ts +14 -0
  21. package/dist/renderers/bubble-renderer.d.ts.map +1 -0
  22. package/dist/renderers/bubble-renderer.js +37 -0
  23. package/dist/renderers/candlestick-renderer.d.ts +18 -0
  24. package/dist/renderers/candlestick-renderer.d.ts.map +1 -0
  25. package/dist/renderers/candlestick-renderer.js +87 -0
  26. package/dist/renderers/columns-renderer.d.ts +21 -0
  27. package/dist/renderers/columns-renderer.d.ts.map +1 -0
  28. package/dist/renderers/columns-renderer.js +35 -0
  29. package/dist/renderers/crosshair-renderer.d.ts +19 -0
  30. package/dist/renderers/crosshair-renderer.d.ts.map +1 -0
  31. package/dist/renderers/crosshair-renderer.js +71 -0
  32. package/dist/renderers/curved-line-renderer.d.ts +17 -0
  33. package/dist/renderers/curved-line-renderer.d.ts.map +1 -0
  34. package/dist/renderers/curved-line-renderer.js +46 -0
  35. package/dist/renderers/drawing-renderer.d.ts +19 -0
  36. package/dist/renderers/drawing-renderer.d.ts.map +1 -0
  37. package/dist/renderers/drawing-renderer.js +487 -0
  38. package/dist/renderers/grid-renderer.d.ts +26 -0
  39. package/dist/renderers/grid-renderer.d.ts.map +1 -0
  40. package/dist/renderers/grid-renderer.js +103 -0
  41. package/dist/renderers/heatmap-renderer.d.ts +16 -0
  42. package/dist/renderers/heatmap-renderer.d.ts.map +1 -0
  43. package/dist/renderers/heatmap-renderer.js +80 -0
  44. package/dist/renderers/high-low-renderer.d.ts +19 -0
  45. package/dist/renderers/high-low-renderer.d.ts.map +1 -0
  46. package/dist/renderers/high-low-renderer.js +28 -0
  47. package/dist/renderers/hlc-area-renderer.d.ts +22 -0
  48. package/dist/renderers/hlc-area-renderer.d.ts.map +1 -0
  49. package/dist/renderers/hlc-area-renderer.js +72 -0
  50. package/dist/renderers/hollow-candlestick-renderer.d.ts +26 -0
  51. package/dist/renderers/hollow-candlestick-renderer.d.ts.map +1 -0
  52. package/dist/renderers/hollow-candlestick-renderer.js +71 -0
  53. package/dist/renderers/horizontal-bar-renderer.d.ts +25 -0
  54. package/dist/renderers/horizontal-bar-renderer.d.ts.map +1 -0
  55. package/dist/renderers/horizontal-bar-renderer.js +52 -0
  56. package/dist/renderers/last-price-renderer.d.ts +17 -0
  57. package/dist/renderers/last-price-renderer.d.ts.map +1 -0
  58. package/dist/renderers/last-price-renderer.js +46 -0
  59. package/dist/renderers/line-renderer.d.ts +23 -0
  60. package/dist/renderers/line-renderer.d.ts.map +1 -0
  61. package/dist/renderers/line-renderer.js +80 -0
  62. package/dist/renderers/line-with-markers-renderer.d.ts +13 -0
  63. package/dist/renderers/line-with-markers-renderer.d.ts.map +1 -0
  64. package/dist/renderers/line-with-markers-renderer.js +35 -0
  65. package/dist/renderers/marker-renderer.d.ts +16 -0
  66. package/dist/renderers/marker-renderer.d.ts.map +1 -0
  67. package/dist/renderers/marker-renderer.js +91 -0
  68. package/dist/renderers/mixed-renderer.d.ts +18 -0
  69. package/dist/renderers/mixed-renderer.d.ts.map +1 -0
  70. package/dist/renderers/mixed-renderer.js +123 -0
  71. package/dist/renderers/ohlc-bar-renderer.d.ts +21 -0
  72. package/dist/renderers/ohlc-bar-renderer.d.ts.map +1 -0
  73. package/dist/renderers/ohlc-bar-renderer.js +73 -0
  74. package/dist/renderers/pie-renderer.d.ts +26 -0
  75. package/dist/renderers/pie-renderer.d.ts.map +1 -0
  76. package/dist/renderers/pie-renderer.js +71 -0
  77. package/dist/renderers/polar-area-renderer.d.ts +13 -0
  78. package/dist/renderers/polar-area-renderer.d.ts.map +1 -0
  79. package/dist/renderers/polar-area-renderer.js +44 -0
  80. package/dist/renderers/radar-renderer.d.ts +16 -0
  81. package/dist/renderers/radar-renderer.d.ts.map +1 -0
  82. package/dist/renderers/radar-renderer.js +99 -0
  83. package/dist/renderers/scatter-renderer.d.ts +14 -0
  84. package/dist/renderers/scatter-renderer.d.ts.map +1 -0
  85. package/dist/renderers/scatter-renderer.js +42 -0
  86. package/dist/renderers/stacked-bar-renderer.d.ts +14 -0
  87. package/dist/renderers/stacked-bar-renderer.d.ts.map +1 -0
  88. package/dist/renderers/stacked-bar-renderer.js +52 -0
  89. package/dist/renderers/step-line-renderer.d.ts +19 -0
  90. package/dist/renderers/step-line-renderer.d.ts.map +1 -0
  91. package/dist/renderers/step-line-renderer.js +52 -0
  92. package/dist/renderers/supertrend-renderer.d.ts +18 -0
  93. package/dist/renderers/supertrend-renderer.d.ts.map +1 -0
  94. package/dist/renderers/supertrend-renderer.js +80 -0
  95. package/dist/renderers/volume-profile-renderer.d.ts +25 -0
  96. package/dist/renderers/volume-profile-renderer.d.ts.map +1 -0
  97. package/dist/renderers/volume-profile-renderer.js +83 -0
  98. package/dist/renderers/watermark-renderer.d.ts +15 -0
  99. package/dist/renderers/watermark-renderer.d.ts.map +1 -0
  100. package/dist/renderers/watermark-renderer.js +26 -0
  101. package/dist/scheduler.d.ts +25 -0
  102. package/dist/scheduler.d.ts.map +1 -0
  103. package/dist/scheduler.js +77 -0
  104. package/package.json +33 -4
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/index.ts
3
+ * Main entry point for @tranding-custom-chart/renderer-canvas.
4
+ */
5
+ export * from './dpi.js';
6
+ export * from './scheduler.js';
7
+ export * from './renderers/grid-renderer.js';
8
+ export * from './renderers/candlestick-renderer.js';
9
+ export * from './renderers/line-renderer.js';
10
+ export * from './renderers/bar-renderer.js';
11
+ export * from './renderers/crosshair-renderer.js';
12
+ export * from './renderers/ohlc-bar-renderer.js';
13
+ export * from './renderers/hollow-candlestick-renderer.js';
14
+ export * from './renderers/baseline-renderer.js';
15
+ export * from './renderers/step-line-renderer.js';
16
+ export * from './renderers/high-low-renderer.js';
17
+ export * from './renderers/columns-renderer.js';
18
+ export * from './renderers/line-with-markers-renderer.js';
19
+ export * from './renderers/hlc-area-renderer.js';
20
+ export * from './renderers/watermark-renderer.js';
21
+ export * from './renderers/last-price-renderer.js';
22
+ export * from './renderers/drawing-renderer.js';
23
+ export * from './renderers/pie-renderer.js';
24
+ export * from './renderers/horizontal-bar-renderer.js';
25
+ export * from './renderers/stacked-bar-renderer.js';
26
+ export * from './renderers/curved-line-renderer.js';
27
+ export * from './renderers/radar-renderer.js';
28
+ export * from './renderers/volume-profile-renderer.js';
29
+ export * from './renderers/supertrend-renderer.js';
30
+ export * from './renderers/scatter-renderer.js';
31
+ export * from './renderers/bubble-renderer.js';
32
+ export * from './renderers/polar-area-renderer.js';
33
+ export * from './renderers/box-plot-renderer.js';
34
+ export * from './renderers/heatmap-renderer.js';
35
+ export * from './renderers/mixed-renderer.js';
36
+ export * from './renderers/marker-renderer.js';
37
+ export * from './canvas-engine.js';
38
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,UAAU,CAAC;AACzB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qCAAqC,CAAC;AACpD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,2CAA2C,CAAC;AAC1D,cAAc,kCAAkC,CAAC;AACjD,cAAc,mCAAmC,CAAC;AAClD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wCAAwC,CAAC;AACvD,cAAc,qCAAqC,CAAC;AACpD,cAAc,qCAAqC,CAAC;AACpD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wCAAwC,CAAC;AACvD,cAAc,oCAAoC,CAAC;AACnD,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oCAAoC,CAAC;AACnD,cAAc,kCAAkC,CAAC;AACjD,cAAc,iCAAiC,CAAC;AAChD,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/index.ts
3
+ * Main entry point for @tranding-custom-chart/renderer-canvas.
4
+ */
5
+ export * from './dpi.js';
6
+ export * from './scheduler.js';
7
+ export * from './renderers/grid-renderer.js';
8
+ export * from './renderers/candlestick-renderer.js';
9
+ export * from './renderers/line-renderer.js';
10
+ export * from './renderers/bar-renderer.js';
11
+ export * from './renderers/crosshair-renderer.js';
12
+ export * from './renderers/ohlc-bar-renderer.js';
13
+ export * from './renderers/hollow-candlestick-renderer.js';
14
+ export * from './renderers/baseline-renderer.js';
15
+ export * from './renderers/step-line-renderer.js';
16
+ export * from './renderers/high-low-renderer.js';
17
+ export * from './renderers/columns-renderer.js';
18
+ export * from './renderers/line-with-markers-renderer.js';
19
+ export * from './renderers/hlc-area-renderer.js';
20
+ export * from './renderers/watermark-renderer.js';
21
+ export * from './renderers/last-price-renderer.js';
22
+ export * from './renderers/drawing-renderer.js';
23
+ export * from './renderers/pie-renderer.js';
24
+ export * from './renderers/horizontal-bar-renderer.js';
25
+ export * from './renderers/stacked-bar-renderer.js';
26
+ export * from './renderers/curved-line-renderer.js';
27
+ export * from './renderers/radar-renderer.js';
28
+ export * from './renderers/volume-profile-renderer.js';
29
+ export * from './renderers/supertrend-renderer.js';
30
+ export * from './renderers/scatter-renderer.js';
31
+ export * from './renderers/bubble-renderer.js';
32
+ export * from './renderers/polar-area-renderer.js';
33
+ export * from './renderers/box-plot-renderer.js';
34
+ export * from './renderers/heatmap-renderer.js';
35
+ export * from './renderers/mixed-renderer.js';
36
+ export * from './renderers/marker-renderer.js';
37
+ export * from './canvas-engine.js';
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/bar-renderer.ts
3
+ * Bar chart and volume panel renderer.
4
+ */
5
+ import type { Scale } from '@tranding-custom-chart/core';
6
+ export interface BarItem {
7
+ readonly value: number;
8
+ readonly color?: string | undefined;
9
+ readonly isUp?: boolean | undefined;
10
+ }
11
+ export interface BarRenderOptions {
12
+ readonly ctx: CanvasRenderingContext2D;
13
+ readonly items: readonly (BarItem | null | undefined)[];
14
+ readonly xScale: Scale<number>;
15
+ readonly yScale: Scale<number>;
16
+ readonly baselineY: number;
17
+ readonly dpr: number;
18
+ readonly defaultColor?: string;
19
+ readonly upColor?: string;
20
+ readonly downColor?: string;
21
+ readonly barWidthRatio?: number;
22
+ readonly startIndex?: number;
23
+ readonly endIndex?: number;
24
+ }
25
+ export declare function renderBarSeries(options: BarRenderOptions): void;
26
+ //# sourceMappingURL=bar-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bar-renderer.d.ts","sourceRoot":"","sources":["../../src/renderers/bar-renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAGzD,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,EAAE,wBAAwB,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC;IACxD,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAyD/D"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/bar-renderer.ts
3
+ * Bar chart and volume panel renderer.
4
+ */
5
+ import { snapRect } from '../dpi.js';
6
+ export function renderBarSeries(options) {
7
+ const { ctx, items, xScale, yScale, baselineY, dpr, defaultColor = '#155c45', upColor = 'rgba(22, 121, 76, 0.45)', downColor = 'rgba(180, 35, 24, 0.45)', barWidthRatio = 0.7, startIndex = 0, endIndex = items.length - 1, } = options;
8
+ if (items.length === 0 || startIndex > endIndex)
9
+ return;
10
+ const start = Math.max(0, startIndex);
11
+ const end = Math.min(items.length - 1, endIndex);
12
+ let slotWidth = 8;
13
+ if ('stepWidth' in xScale && typeof xScale.stepWidth === 'number') {
14
+ slotWidth = xScale.stepWidth;
15
+ }
16
+ else if (items.length > 1) {
17
+ const x0 = xScale.scale(0);
18
+ const x1 = xScale.scale(1);
19
+ slotWidth = Math.abs(x1 - x0) || 8;
20
+ }
21
+ const barWidth = slotWidth < 2 ? Math.max(0.5, slotWidth * 0.8) : Math.max(1, slotWidth * barWidthRatio);
22
+ const halfWidth = barWidth / 2;
23
+ ctx.save();
24
+ for (let i = start; i <= end; i++) {
25
+ const item = items[i];
26
+ if (!item || !Number.isFinite(item.value) || item.value <= 0)
27
+ continue;
28
+ const rawX = xScale.scale(i);
29
+ const barTop = yScale.scale(item.value);
30
+ const height = Math.max(1, Math.abs(baselineY - barTop));
31
+ const leftX = snapRect(rawX - halfWidth, dpr);
32
+ const topY = snapRect(Math.min(baselineY, barTop), dpr);
33
+ if (item.color) {
34
+ ctx.fillStyle = item.color;
35
+ }
36
+ else if (item.isUp !== undefined) {
37
+ ctx.fillStyle = item.isUp ? upColor : downColor;
38
+ }
39
+ else {
40
+ ctx.fillStyle = defaultColor;
41
+ }
42
+ ctx.fillRect(leftX, topY, barWidth, height);
43
+ }
44
+ ctx.restore();
45
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/baseline-renderer.ts
3
+ * Two-zone baseline chart splitting returns into bullish (above) and bearish (below) zones.
4
+ */
5
+ import type { Dimension, Padding, Scale } from '@tranding-custom-chart/core';
6
+ export interface BaselineRenderOptions {
7
+ readonly ctx: CanvasRenderingContext2D;
8
+ readonly data: readonly number[];
9
+ readonly xScale: Scale<number>;
10
+ readonly yScale: Scale<number>;
11
+ readonly baselineValue: number;
12
+ readonly bounds: Dimension;
13
+ readonly padding: Padding;
14
+ readonly dpr: number;
15
+ readonly aboveColor?: string | undefined;
16
+ readonly belowColor?: string | undefined;
17
+ readonly lineWidth?: number | undefined;
18
+ }
19
+ export declare function renderBaselineChart(options: BaselineRenderOptions): void;
20
+ //# sourceMappingURL=baseline-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline-renderer.d.ts","sourceRoot":"","sources":["../../src/renderers/baseline-renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAG7E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,GAAG,EAAE,wBAAwB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACzC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAyHxE"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/baseline-renderer.ts
3
+ * Two-zone baseline chart splitting returns into bullish (above) and bearish (below) zones.
4
+ */
5
+ import { snapLine } from '../dpi.js';
6
+ export function renderBaselineChart(options) {
7
+ const { ctx, data, xScale, yScale, baselineValue, bounds, padding, dpr, aboveColor = '#16794c', belowColor = '#b42318', lineWidth = 2, } = options;
8
+ if (data.length === 0)
9
+ return;
10
+ const yBase = snapLine(yScale.scale(baselineValue), dpr);
11
+ const chartLeft = padding.left;
12
+ const chartRight = bounds.width - padding.right;
13
+ const chartTop = padding.top;
14
+ const chartBottom = bounds.height - padding.bottom;
15
+ // Build the continuous polyline points
16
+ const points = [];
17
+ for (let i = 0; i < data.length; i++) {
18
+ const val = data[i];
19
+ if (Number.isFinite(val)) {
20
+ points.push({
21
+ x: xScale.scale(i),
22
+ y: yScale.scale(val),
23
+ });
24
+ }
25
+ }
26
+ if (points.length < 2)
27
+ return;
28
+ ctx.save();
29
+ // 1. Render Upper Zone (Above Baseline)
30
+ ctx.save();
31
+ ctx.beginPath();
32
+ ctx.rect(chartLeft, chartTop, chartRight - chartLeft, Math.max(0, yBase - chartTop));
33
+ ctx.clip();
34
+ // Upper gradient fill
35
+ const upperGrad = ctx.createLinearGradient(0, chartTop, 0, yBase);
36
+ upperGrad.addColorStop(0, 'rgba(22, 121, 76, 0.40)');
37
+ upperGrad.addColorStop(1, 'rgba(22, 121, 76, 0.02)');
38
+ ctx.fillStyle = upperGrad;
39
+ ctx.beginPath();
40
+ ctx.moveTo(points[0].x, yBase);
41
+ for (const pt of points) {
42
+ ctx.lineTo(pt.x, pt.y);
43
+ }
44
+ ctx.lineTo(points[points.length - 1].x, yBase);
45
+ ctx.closePath();
46
+ ctx.fill();
47
+ // Upper stroke
48
+ ctx.strokeStyle = aboveColor;
49
+ ctx.lineWidth = lineWidth;
50
+ ctx.beginPath();
51
+ ctx.moveTo(points[0].x, points[0].y);
52
+ for (let i = 1; i < points.length; i++) {
53
+ ctx.lineTo(points[i].x, points[i].y);
54
+ }
55
+ ctx.stroke();
56
+ ctx.restore();
57
+ // 2. Render Lower Zone (Below Baseline)
58
+ ctx.save();
59
+ ctx.beginPath();
60
+ ctx.rect(chartLeft, yBase, chartRight - chartLeft, Math.max(0, chartBottom - yBase));
61
+ ctx.clip();
62
+ // Lower gradient fill
63
+ const lowerGrad = ctx.createLinearGradient(0, yBase, 0, chartBottom);
64
+ lowerGrad.addColorStop(0, 'rgba(180, 35, 24, 0.02)');
65
+ lowerGrad.addColorStop(1, 'rgba(180, 35, 24, 0.40)');
66
+ ctx.fillStyle = lowerGrad;
67
+ ctx.beginPath();
68
+ ctx.moveTo(points[0].x, yBase);
69
+ for (const pt of points) {
70
+ ctx.lineTo(pt.x, pt.y);
71
+ }
72
+ ctx.lineTo(points[points.length - 1].x, yBase);
73
+ ctx.closePath();
74
+ ctx.fill();
75
+ // Lower stroke
76
+ ctx.strokeStyle = belowColor;
77
+ ctx.lineWidth = lineWidth;
78
+ ctx.beginPath();
79
+ ctx.moveTo(points[0].x, points[0].y);
80
+ for (let i = 1; i < points.length; i++) {
81
+ ctx.lineTo(points[i].x, points[i].y);
82
+ }
83
+ ctx.stroke();
84
+ ctx.restore();
85
+ // 3. Render Baseline Reference Line
86
+ ctx.strokeStyle = 'rgba(255, 255, 255, 0.35)';
87
+ ctx.lineWidth = 1;
88
+ ctx.setLineDash([4, 4]);
89
+ ctx.beginPath();
90
+ ctx.moveTo(chartLeft, yBase);
91
+ ctx.lineTo(chartRight, yBase);
92
+ ctx.stroke();
93
+ // Baseline Badge on Price Axis
94
+ ctx.setLineDash([]);
95
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
96
+ ctx.font = '10px monospace';
97
+ ctx.textAlign = 'left';
98
+ ctx.textBaseline = 'middle';
99
+ ctx.fillText(`Base: ${baselineValue.toFixed(1)}`, chartRight + 4, yBase);
100
+ ctx.restore();
101
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/box-plot-renderer.ts
3
+ * High-performance Canvas 2D statistical box plot (box-and-whisker) renderer.
4
+ */
5
+ import type { BoxPlotDatum, Scale } from '@tranding-custom-chart/core';
6
+ export interface BoxPlotRenderOptions {
7
+ readonly boxWidthRatio?: number | undefined;
8
+ readonly capWidthRatio?: number | undefined;
9
+ readonly defaultColor?: string | undefined;
10
+ readonly strokeWidth?: number | undefined;
11
+ readonly medianColor?: string | undefined;
12
+ }
13
+ export declare function renderBoxPlots(ctx: CanvasRenderingContext2D, data: readonly BoxPlotDatum[], xScale: Scale<number>, yScale: Scale<number>, options?: BoxPlotRenderOptions): void;
14
+ //# sourceMappingURL=box-plot-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box-plot-renderer.d.ts","sourceRoot":"","sources":["../../src/renderers/box-plot-renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEvE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC3C;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,SAAS,YAAY,EAAE,EAC7B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EACrB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EACrB,OAAO,GAAE,oBAAyB,GACjC,IAAI,CAyFN"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/box-plot-renderer.ts
3
+ * High-performance Canvas 2D statistical box plot (box-and-whisker) renderer.
4
+ */
5
+ export function renderBoxPlots(ctx, data, xScale, yScale, options = {}) {
6
+ if (data.length === 0)
7
+ return;
8
+ const { boxWidthRatio = 0.5, capWidthRatio = 0.25, defaultColor = '#3b82f6', strokeWidth = 1.5, medianColor = '#ffffff', } = options;
9
+ ctx.save();
10
+ ctx.lineWidth = strokeWidth;
11
+ const count = data.length;
12
+ // Step width estimate between categories
13
+ let slotWidth = 40;
14
+ if (count > 1) {
15
+ slotWidth = Math.abs(xScale.scale(1) - xScale.scale(0));
16
+ }
17
+ else {
18
+ slotWidth = 60;
19
+ }
20
+ const boxHalfWidth = Math.max(4, (slotWidth * boxWidthRatio) / 2);
21
+ const capHalfWidth = Math.max(3, (slotWidth * capWidthRatio) / 2);
22
+ for (let i = 0; i < count; i++) {
23
+ const datum = data[i];
24
+ const cx = Math.round(xScale.scale(i));
25
+ const yMin = yScale.scale(datum.min);
26
+ const yQ1 = yScale.scale(datum.q1);
27
+ const yMedian = yScale.scale(datum.median);
28
+ const yQ3 = yScale.scale(datum.q3);
29
+ const yMax = yScale.scale(datum.max);
30
+ const baseColor = datum.color ?? defaultColor;
31
+ // 1. Whisker lines (from min to Q1 and Q3 to max)
32
+ ctx.strokeStyle = baseColor;
33
+ ctx.beginPath();
34
+ // Lower whisker
35
+ ctx.moveTo(cx, yMin);
36
+ ctx.lineTo(cx, yQ1);
37
+ // Lower cap
38
+ ctx.moveTo(cx - capHalfWidth, yMin);
39
+ ctx.lineTo(cx + capHalfWidth, yMin);
40
+ // Upper whisker
41
+ ctx.moveTo(cx, yQ3);
42
+ ctx.lineTo(cx, yMax);
43
+ // Upper cap
44
+ ctx.moveTo(cx - capHalfWidth, yMax);
45
+ ctx.lineTo(cx + capHalfWidth, yMax);
46
+ ctx.stroke();
47
+ // 2. Interquartile Range (IQR) Box: [Q3 to Q1] (Note: yQ3 is pixel-top, yQ1 is pixel-bottom)
48
+ const boxTop = Math.min(yQ1, yQ3);
49
+ const boxHeight = Math.max(1, Math.abs(yQ1 - yQ3));
50
+ const boxLeft = cx - boxHalfWidth;
51
+ // Box fill
52
+ ctx.fillStyle = baseColor.startsWith('#') ? `${baseColor}44` : 'rgba(59, 130, 246, 0.25)';
53
+ ctx.fillRect(boxLeft, boxTop, boxHalfWidth * 2, boxHeight);
54
+ // Box outline
55
+ ctx.strokeRect(boxLeft, boxTop, boxHalfWidth * 2, boxHeight);
56
+ // 3. Median Line
57
+ ctx.strokeStyle = medianColor;
58
+ ctx.beginPath();
59
+ ctx.moveTo(boxLeft, yMedian);
60
+ ctx.lineTo(boxLeft + boxHalfWidth * 2, yMedian);
61
+ ctx.stroke();
62
+ // 4. Outlier points (if any)
63
+ if (datum.outliers && datum.outliers.length > 0) {
64
+ ctx.fillStyle = '#ef4444';
65
+ ctx.strokeStyle = '#ffffff';
66
+ for (const outlier of datum.outliers) {
67
+ const yOut = yScale.scale(outlier);
68
+ ctx.beginPath();
69
+ ctx.arc(cx, yOut, 3, 0, Math.PI * 2);
70
+ ctx.fill();
71
+ ctx.stroke();
72
+ }
73
+ }
74
+ }
75
+ ctx.restore();
76
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/bubble-renderer.ts
3
+ * High-performance 2D Canvas renderer for Bubble Charts.
4
+ */
5
+ import type { Scale, BubbleDatum } from '@tranding-custom-chart/core';
6
+ export interface BubbleRenderOptions {
7
+ readonly minRadius?: number;
8
+ readonly maxRadius?: number;
9
+ readonly defaultColor?: string;
10
+ readonly strokeColor?: string;
11
+ readonly strokeWidth?: number;
12
+ }
13
+ export declare function renderBubbles(ctx: CanvasRenderingContext2D, data: readonly BubbleDatum[], xScale: Scale<number>, yScale: Scale<number>, options?: BubbleRenderOptions): void;
14
+ //# sourceMappingURL=bubble-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bubble-renderer.d.ts","sourceRoot":"","sources":["../../src/renderers/bubble-renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,wBAAwB,EAC7B,IAAI,EAAE,SAAS,WAAW,EAAE,EAC5B,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EACrB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EACrB,OAAO,GAAE,mBAAwB,GAChC,IAAI,CAqCN"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/bubble-renderer.ts
3
+ * High-performance 2D Canvas renderer for Bubble Charts.
4
+ */
5
+ export function renderBubbles(ctx, data, xScale, yScale, options = {}) {
6
+ if (!data || data.length === 0)
7
+ return;
8
+ const defaultColor = options.defaultColor ?? 'rgba(59, 130, 246, 0.6)';
9
+ const strokeColor = options.strokeColor ?? 'rgba(59, 130, 246, 0.9)';
10
+ const strokeWidth = options.strokeWidth ?? 1.5;
11
+ const minRadius = options.minRadius ?? 3;
12
+ const maxRadius = options.maxRadius ?? 40;
13
+ ctx.save();
14
+ ctx.lineWidth = strokeWidth;
15
+ for (let i = 0; i < data.length; i++) {
16
+ const d = data[i];
17
+ const px = xScale.scale(d.x);
18
+ const py = yScale.scale(d.y);
19
+ const radius = Math.max(minRadius, Math.min(maxRadius, d.r));
20
+ ctx.beginPath();
21
+ ctx.arc(px, py, radius, 0, Math.PI * 2);
22
+ ctx.fillStyle = d.color ?? defaultColor;
23
+ ctx.strokeStyle = strokeColor;
24
+ ctx.fill();
25
+ if (strokeWidth > 0) {
26
+ ctx.stroke();
27
+ }
28
+ if (d.label) {
29
+ ctx.fillStyle = '#ffffff';
30
+ ctx.font = '10px system-ui, sans-serif';
31
+ ctx.textAlign = 'center';
32
+ ctx.textBaseline = 'middle';
33
+ ctx.fillText(d.label, px, py);
34
+ }
35
+ }
36
+ ctx.restore();
37
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/candlestick-renderer.ts
3
+ * High-performance batched candlestick renderer.
4
+ */
5
+ import type { ChartTheme, OHLCVBar, Scale } from '@tranding-custom-chart/core';
6
+ export interface CandlestickRenderOptions {
7
+ readonly ctx: CanvasRenderingContext2D;
8
+ readonly bars: readonly OHLCVBar[];
9
+ readonly xScale: Scale<number>;
10
+ readonly yScale: Scale<number>;
11
+ readonly theme: ChartTheme;
12
+ readonly dpr: number;
13
+ readonly startIndex?: number;
14
+ readonly endIndex?: number;
15
+ readonly candleWidthRatio?: number;
16
+ }
17
+ export declare function renderCandlesticks(options: CandlestickRenderOptions): void;
18
+ //# sourceMappingURL=candlestick-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candlestick-renderer.d.ts","sourceRoot":"","sources":["../../src/renderers/candlestick-renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAG/E,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,GAAG,EAAE,wBAAwB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI,CAwG1E"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/candlestick-renderer.ts
3
+ * High-performance batched candlestick renderer.
4
+ */
5
+ import { snapLine, snapRect } from '../dpi.js';
6
+ export function renderCandlesticks(options) {
7
+ const { ctx, bars, xScale, yScale, theme, dpr, startIndex = 0, endIndex = bars.length - 1, candleWidthRatio = 0.7, } = options;
8
+ if (bars.length === 0 || startIndex > endIndex)
9
+ return;
10
+ const start = Math.max(0, startIndex);
11
+ const end = Math.min(bars.length - 1, endIndex);
12
+ // Determine bar width from scale
13
+ let slotWidth = 8;
14
+ if ('stepWidth' in xScale && typeof xScale.stepWidth === 'number') {
15
+ slotWidth = xScale.stepWidth;
16
+ }
17
+ else if (bars.length > 1) {
18
+ const x0 = xScale.scale(0);
19
+ const x1 = xScale.scale(1);
20
+ slotWidth = Math.abs(x1 - x0) || 8;
21
+ }
22
+ const candleWidth = slotWidth < 2 ? Math.max(0.5, slotWidth * 0.8) : Math.max(1, slotWidth * candleWidthRatio);
23
+ const halfWidth = candleWidth / 2;
24
+ ctx.save();
25
+ ctx.lineWidth = slotWidth < 2 ? 0.75 : 1;
26
+ // Render Bullish (Up) Candles
27
+ ctx.strokeStyle = theme.upCandle;
28
+ ctx.fillStyle = theme.upCandle;
29
+ ctx.beginPath();
30
+ for (let i = start; i <= end; i++) {
31
+ const b = bars[i];
32
+ if (b.close < b.open)
33
+ continue; // Skip bearish
34
+ const rawX = xScale.scale(i);
35
+ const x = snapLine(rawX, dpr);
36
+ const highY = snapLine(yScale.scale(b.high), dpr);
37
+ const lowY = snapLine(yScale.scale(b.low), dpr);
38
+ // Wick line
39
+ ctx.moveTo(x, highY);
40
+ ctx.lineTo(x, lowY);
41
+ }
42
+ ctx.stroke();
43
+ // Bullish Bodies
44
+ for (let i = start; i <= end; i++) {
45
+ const b = bars[i];
46
+ if (b.close < b.open)
47
+ continue;
48
+ const rawX = xScale.scale(i);
49
+ const openY = yScale.scale(b.open);
50
+ const closeY = yScale.scale(b.close);
51
+ const topY = snapRect(Math.min(openY, closeY), dpr);
52
+ const bodyHeight = Math.max(1.5, Math.abs(closeY - openY));
53
+ const leftX = snapRect(rawX - halfWidth, dpr);
54
+ ctx.fillRect(leftX, topY, candleWidth, bodyHeight);
55
+ }
56
+ // Render Bearish (Down) Candles
57
+ ctx.strokeStyle = theme.downCandle;
58
+ ctx.fillStyle = theme.downCandle;
59
+ ctx.beginPath();
60
+ for (let i = start; i <= end; i++) {
61
+ const b = bars[i];
62
+ if (b.close >= b.open)
63
+ continue; // Skip bullish
64
+ const rawX = xScale.scale(i);
65
+ const x = snapLine(rawX, dpr);
66
+ const highY = snapLine(yScale.scale(b.high), dpr);
67
+ const lowY = snapLine(yScale.scale(b.low), dpr);
68
+ // Wick line
69
+ ctx.moveTo(x, highY);
70
+ ctx.lineTo(x, lowY);
71
+ }
72
+ ctx.stroke();
73
+ // Bearish Bodies
74
+ for (let i = start; i <= end; i++) {
75
+ const b = bars[i];
76
+ if (b.close >= b.open)
77
+ continue;
78
+ const rawX = xScale.scale(i);
79
+ const openY = yScale.scale(b.open);
80
+ const closeY = yScale.scale(b.close);
81
+ const topY = snapRect(Math.min(openY, closeY), dpr);
82
+ const bodyHeight = Math.max(1.5, Math.abs(closeY - openY));
83
+ const leftX = snapRect(rawX - halfWidth, dpr);
84
+ ctx.fillRect(leftX, topY, candleWidth, bodyHeight);
85
+ }
86
+ ctx.restore();
87
+ }
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/columns-renderer.ts
3
+ * Canvas 2D renderer for vertical Columns charts.
4
+ * Draws vertical columns from scale baseline to close price with bullish/bearish color coding.
5
+ */
6
+ import type { ChartTheme, OHLCVBar, Scale } from '@tranding-custom-chart/core';
7
+ export interface ColumnsRenderOptions {
8
+ readonly ctx: CanvasRenderingContext2D;
9
+ readonly bars: readonly OHLCVBar[];
10
+ readonly xScale: Scale<number>;
11
+ readonly yScale: Scale<number>;
12
+ readonly baselineY: number;
13
+ readonly theme?: ChartTheme | undefined;
14
+ readonly upColor?: string | undefined;
15
+ readonly downColor?: string | undefined;
16
+ readonly columnWidthRatio?: number | undefined;
17
+ readonly startIndex?: number | undefined;
18
+ readonly endIndex?: number | undefined;
19
+ }
20
+ export declare function renderColumns(options: ColumnsRenderOptions): void;
21
+ //# sourceMappingURL=columns-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"columns-renderer.d.ts","sourceRoot":"","sources":["../../src/renderers/columns-renderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAG/E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,EAAE,wBAAwB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CA8CjE"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/columns-renderer.ts
3
+ * Canvas 2D renderer for vertical Columns charts.
4
+ * Draws vertical columns from scale baseline to close price with bullish/bearish color coding.
5
+ */
6
+ import { snapRect } from '../dpi.js';
7
+ export function renderColumns(options) {
8
+ const { ctx, bars, xScale, yScale, baselineY, theme, upColor = theme?.upCandle ?? '#16794c', downColor = theme?.downCandle ?? '#b42318', columnWidthRatio = 0.75, startIndex = 0, endIndex = bars.length - 1, } = options;
9
+ if (bars.length === 0 || startIndex > endIndex)
10
+ return;
11
+ const start = Math.max(0, startIndex);
12
+ const end = Math.min(bars.length - 1, endIndex);
13
+ // Approximate slot width from scale difference
14
+ const x0 = xScale.scale(0);
15
+ const x1 = bars.length > 1 ? xScale.scale(1) : x0 + 10;
16
+ const actualSlot = bars.length > 1 ? Math.abs(x1 - x0) : 10;
17
+ const colWidth = actualSlot < 2 ? Math.max(0.5, actualSlot * 0.8) : Math.max(1, Math.round(actualSlot * columnWidthRatio));
18
+ ctx.save();
19
+ for (let i = start; i <= end; i++) {
20
+ const bar = bars[i];
21
+ const cx = xScale.scale(i);
22
+ const cy = yScale.scale(bar.close);
23
+ const isUp = bar.close >= bar.open;
24
+ ctx.fillStyle = isUp ? upColor : downColor;
25
+ const left = cx - colWidth / 2;
26
+ const top = Math.min(cy, baselineY);
27
+ const height = Math.abs(baselineY - cy);
28
+ const rx = snapRect(left);
29
+ const ry = snapRect(top);
30
+ const rw = snapRect(colWidth);
31
+ const rh = snapRect(Math.max(1, height));
32
+ ctx.fillRect(rx, ry, rw, rh);
33
+ }
34
+ ctx.restore();
35
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * @file packages/chart-renderer-canvas/src/renderers/crosshair-renderer.ts
3
+ * Interactive crosshair guidelines, price/time axis badges, and highlight markers.
4
+ */
5
+ import type { ChartTheme, Dimension, Padding } from '@tranding-custom-chart/core';
6
+ export interface CrosshairRenderOptions {
7
+ readonly ctx: CanvasRenderingContext2D;
8
+ readonly bounds: Dimension;
9
+ readonly padding: Padding;
10
+ readonly x: number;
11
+ readonly y: number;
12
+ readonly theme: ChartTheme;
13
+ readonly dpr: number;
14
+ readonly xLabel?: string | undefined;
15
+ readonly yLabel?: string | undefined;
16
+ readonly showHorizontalLine?: boolean | undefined;
17
+ }
18
+ export declare function renderCrosshair(options: CrosshairRenderOptions): void;
19
+ //# sourceMappingURL=crosshair-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crosshair-renderer.d.ts","sourceRoot":"","sources":["../../src/renderers/crosshair-renderer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAGlF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,EAAE,wBAAwB,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACnD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,IAAI,CA6ErE"}