@itssumitrai/fin-charter 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -0
- package/dist/api/chart-api.d.ts +173 -0
- package/dist/api/export.d.ts +46 -0
- package/dist/api/indicator-api.d.ts +38 -0
- package/dist/api/options.d.ts +226 -0
- package/dist/api/pane-api.d.ts +28 -0
- package/dist/api/series-api.d.ts +115 -0
- package/dist/core/accessibility.d.ts +90 -0
- package/dist/core/alert-line.d.ts +49 -0
- package/dist/core/chart-state.d.ts +39 -0
- package/dist/core/chart-sync.d.ts +83 -0
- package/dist/core/crosshair.d.ts +28 -0
- package/dist/core/css-theme.d.ts +41 -0
- package/dist/core/custom-indicator.d.ts +70 -0
- package/dist/core/data-feed.d.ts +59 -0
- package/dist/core/data-layer.d.ts +38 -0
- package/dist/core/invalidation.d.ts +24 -0
- package/dist/core/market-session.d.ts +11 -0
- package/dist/core/order-line.d.ts +134 -0
- package/dist/core/pane-divider.d.ts +22 -0
- package/dist/core/pane.d.ts +32 -0
- package/dist/core/periodicity.d.ts +6 -0
- package/dist/core/plugin.d.ts +90 -0
- package/dist/core/price-line.d.ts +17 -0
- package/dist/core/price-scale.d.ts +74 -0
- package/dist/core/replay.d.ts +73 -0
- package/dist/core/rtl.d.ts +22 -0
- package/dist/core/segment-tree.d.ts +38 -0
- package/dist/core/series-markers.d.ts +18 -0
- package/dist/core/storage-adapter.d.ts +50 -0
- package/dist/core/streaming-adapter.d.ts +102 -0
- package/dist/core/symbol-resolver.d.ts +32 -0
- package/dist/core/text-label.d.ts +72 -0
- package/dist/core/time-scale.d.ts +109 -0
- package/dist/core/types.d.ts +144 -0
- package/dist/core/undo-redo.d.ts +46 -0
- package/dist/currency/currency.d.ts +8 -0
- package/dist/currency/index.d.ts +2 -0
- package/dist/drawings/arrow.d.ts +10 -0
- package/dist/drawings/base.d.ts +79 -0
- package/dist/drawings/channel.d.ts +10 -0
- package/dist/drawings/crossline.d.ts +10 -0
- package/dist/drawings/ellipse.d.ts +10 -0
- package/dist/drawings/fib-arc.d.ts +10 -0
- package/dist/drawings/fib-fan.d.ts +12 -0
- package/dist/drawings/fib-projection.d.ts +11 -0
- package/dist/drawings/fibonacci.d.ts +11 -0
- package/dist/drawings/horizontal-line.d.ts +10 -0
- package/dist/drawings/index.d.ts +7 -0
- package/dist/drawings/measurement.d.ts +11 -0
- package/dist/drawings/pitchfork.d.ts +12 -0
- package/dist/drawings/ray.d.ts +12 -0
- package/dist/drawings/rectangle.d.ts +10 -0
- package/dist/drawings/text-annotation.d.ts +11 -0
- package/dist/drawings/trendline.d.ts +10 -0
- package/dist/drawings/vertical-line.d.ts +10 -0
- package/dist/formatting/index.d.ts +5 -0
- package/dist/formatting/price-formatter.d.ts +6 -0
- package/dist/formatting/time-formatter.d.ts +7 -0
- package/dist/formatting/volume-formatter.d.ts +1 -0
- package/dist/i18n/i18n.d.ts +6 -0
- package/dist/i18n/index.d.ts +3 -0
- package/dist/i18n/locales/en.d.ts +3 -0
- package/dist/index.d.ts +63 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index10.js +2 -0
- package/dist/index10.js.map +1 -0
- package/dist/index100.js +2 -0
- package/dist/index100.js.map +1 -0
- package/dist/index101.js +2 -0
- package/dist/index101.js.map +1 -0
- package/dist/index102.js +2 -0
- package/dist/index102.js.map +1 -0
- package/dist/index103.js +2 -0
- package/dist/index103.js.map +1 -0
- package/dist/index104.js +2 -0
- package/dist/index104.js.map +1 -0
- package/dist/index105.js +2 -0
- package/dist/index105.js.map +1 -0
- package/dist/index106.js +2 -0
- package/dist/index106.js.map +1 -0
- package/dist/index107.js +2 -0
- package/dist/index107.js.map +1 -0
- package/dist/index108.js +2 -0
- package/dist/index108.js.map +1 -0
- package/dist/index109.js +2 -0
- package/dist/index109.js.map +1 -0
- package/dist/index11.js +2 -0
- package/dist/index11.js.map +1 -0
- package/dist/index110.js +2 -0
- package/dist/index110.js.map +1 -0
- package/dist/index111.js +2 -0
- package/dist/index111.js.map +1 -0
- package/dist/index112.js +2 -0
- package/dist/index112.js.map +1 -0
- package/dist/index113.js +2 -0
- package/dist/index113.js.map +1 -0
- package/dist/index114.js +2 -0
- package/dist/index114.js.map +1 -0
- package/dist/index115.js +2 -0
- package/dist/index115.js.map +1 -0
- package/dist/index116.js +2 -0
- package/dist/index116.js.map +1 -0
- package/dist/index117.js +2 -0
- package/dist/index117.js.map +1 -0
- package/dist/index118.js +2 -0
- package/dist/index118.js.map +1 -0
- package/dist/index119.js +2 -0
- package/dist/index119.js.map +1 -0
- package/dist/index12.js +2 -0
- package/dist/index12.js.map +1 -0
- package/dist/index120.js +2 -0
- package/dist/index120.js.map +1 -0
- package/dist/index121.js +2 -0
- package/dist/index121.js.map +1 -0
- package/dist/index122.js +2 -0
- package/dist/index122.js.map +1 -0
- package/dist/index123.js +2 -0
- package/dist/index123.js.map +1 -0
- package/dist/index124.js +2 -0
- package/dist/index124.js.map +1 -0
- package/dist/index13.js +2 -0
- package/dist/index13.js.map +1 -0
- package/dist/index14.js +2 -0
- package/dist/index14.js.map +1 -0
- package/dist/index15.js +2 -0
- package/dist/index15.js.map +1 -0
- package/dist/index16.js +2 -0
- package/dist/index16.js.map +1 -0
- package/dist/index17.js +2 -0
- package/dist/index17.js.map +1 -0
- package/dist/index18.js +2 -0
- package/dist/index18.js.map +1 -0
- package/dist/index19.js +2 -0
- package/dist/index19.js.map +1 -0
- package/dist/index2.js +2 -0
- package/dist/index2.js.map +1 -0
- package/dist/index20.js +2 -0
- package/dist/index20.js.map +1 -0
- package/dist/index21.js +2 -0
- package/dist/index21.js.map +1 -0
- package/dist/index22.js +2 -0
- package/dist/index22.js.map +1 -0
- package/dist/index23.js +2 -0
- package/dist/index23.js.map +1 -0
- package/dist/index24.js +2 -0
- package/dist/index24.js.map +1 -0
- package/dist/index25.js +2 -0
- package/dist/index25.js.map +1 -0
- package/dist/index26.js +2 -0
- package/dist/index26.js.map +1 -0
- package/dist/index27.js +2 -0
- package/dist/index27.js.map +1 -0
- package/dist/index28.js +2 -0
- package/dist/index28.js.map +1 -0
- package/dist/index29.js +2 -0
- package/dist/index29.js.map +1 -0
- package/dist/index3.js +2 -0
- package/dist/index3.js.map +1 -0
- package/dist/index30.js +2 -0
- package/dist/index30.js.map +1 -0
- package/dist/index31.js +2 -0
- package/dist/index31.js.map +1 -0
- package/dist/index32.js +2 -0
- package/dist/index32.js.map +1 -0
- package/dist/index33.js +2 -0
- package/dist/index33.js.map +1 -0
- package/dist/index34.js +2 -0
- package/dist/index34.js.map +1 -0
- package/dist/index35.js +2 -0
- package/dist/index35.js.map +1 -0
- package/dist/index36.js +2 -0
- package/dist/index36.js.map +1 -0
- package/dist/index37.js +2 -0
- package/dist/index37.js.map +1 -0
- package/dist/index38.js +2 -0
- package/dist/index38.js.map +1 -0
- package/dist/index39.js +2 -0
- package/dist/index39.js.map +1 -0
- package/dist/index4.js +2 -0
- package/dist/index4.js.map +1 -0
- package/dist/index40.js +2 -0
- package/dist/index40.js.map +1 -0
- package/dist/index41.js +2 -0
- package/dist/index41.js.map +1 -0
- package/dist/index42.js +2 -0
- package/dist/index42.js.map +1 -0
- package/dist/index43.js +2 -0
- package/dist/index43.js.map +1 -0
- package/dist/index44.js +2 -0
- package/dist/index44.js.map +1 -0
- package/dist/index45.js +2 -0
- package/dist/index45.js.map +1 -0
- package/dist/index46.js +2 -0
- package/dist/index46.js.map +1 -0
- package/dist/index47.js +2 -0
- package/dist/index47.js.map +1 -0
- package/dist/index48.js +2 -0
- package/dist/index48.js.map +1 -0
- package/dist/index49.js +2 -0
- package/dist/index49.js.map +1 -0
- package/dist/index5.js +2 -0
- package/dist/index5.js.map +1 -0
- package/dist/index50.js +2 -0
- package/dist/index50.js.map +1 -0
- package/dist/index51.js +2 -0
- package/dist/index51.js.map +1 -0
- package/dist/index52.js +2 -0
- package/dist/index52.js.map +1 -0
- package/dist/index53.js +2 -0
- package/dist/index53.js.map +1 -0
- package/dist/index54.js +2 -0
- package/dist/index54.js.map +1 -0
- package/dist/index55.js +2 -0
- package/dist/index55.js.map +1 -0
- package/dist/index56.js +2 -0
- package/dist/index56.js.map +1 -0
- package/dist/index57.js +2 -0
- package/dist/index57.js.map +1 -0
- package/dist/index58.js +2 -0
- package/dist/index58.js.map +1 -0
- package/dist/index59.js +2 -0
- package/dist/index59.js.map +1 -0
- package/dist/index6.js +2 -0
- package/dist/index6.js.map +1 -0
- package/dist/index60.js +2 -0
- package/dist/index60.js.map +1 -0
- package/dist/index61.js +2 -0
- package/dist/index61.js.map +1 -0
- package/dist/index62.js +2 -0
- package/dist/index62.js.map +1 -0
- package/dist/index63.js +2 -0
- package/dist/index63.js.map +1 -0
- package/dist/index64.js +2 -0
- package/dist/index64.js.map +1 -0
- package/dist/index65.js +3 -0
- package/dist/index65.js.map +1 -0
- package/dist/index66.js +2 -0
- package/dist/index66.js.map +1 -0
- package/dist/index67.js +2 -0
- package/dist/index67.js.map +1 -0
- package/dist/index68.js +2 -0
- package/dist/index68.js.map +1 -0
- package/dist/index69.js +2 -0
- package/dist/index69.js.map +1 -0
- package/dist/index7.js +2 -0
- package/dist/index7.js.map +1 -0
- package/dist/index70.js +2 -0
- package/dist/index70.js.map +1 -0
- package/dist/index71.js +2 -0
- package/dist/index71.js.map +1 -0
- package/dist/index72.js +2 -0
- package/dist/index72.js.map +1 -0
- package/dist/index73.js +2 -0
- package/dist/index73.js.map +1 -0
- package/dist/index74.js +2 -0
- package/dist/index74.js.map +1 -0
- package/dist/index75.js +2 -0
- package/dist/index75.js.map +1 -0
- package/dist/index76.js +2 -0
- package/dist/index76.js.map +1 -0
- package/dist/index77.js +2 -0
- package/dist/index77.js.map +1 -0
- package/dist/index78.js +2 -0
- package/dist/index78.js.map +1 -0
- package/dist/index79.js +2 -0
- package/dist/index79.js.map +1 -0
- package/dist/index8.js +2 -0
- package/dist/index8.js.map +1 -0
- package/dist/index80.js +2 -0
- package/dist/index80.js.map +1 -0
- package/dist/index81.js +2 -0
- package/dist/index81.js.map +1 -0
- package/dist/index82.js +2 -0
- package/dist/index82.js.map +1 -0
- package/dist/index83.js +2 -0
- package/dist/index83.js.map +1 -0
- package/dist/index84.js +2 -0
- package/dist/index84.js.map +1 -0
- package/dist/index85.js +2 -0
- package/dist/index85.js.map +1 -0
- package/dist/index86.js +2 -0
- package/dist/index86.js.map +1 -0
- package/dist/index87.js +2 -0
- package/dist/index87.js.map +1 -0
- package/dist/index88.js +2 -0
- package/dist/index88.js.map +1 -0
- package/dist/index89.js +2 -0
- package/dist/index89.js.map +1 -0
- package/dist/index9.js +2 -0
- package/dist/index9.js.map +1 -0
- package/dist/index90.js +2 -0
- package/dist/index90.js.map +1 -0
- package/dist/index91.js +2 -0
- package/dist/index91.js.map +1 -0
- package/dist/index92.js +2 -0
- package/dist/index92.js.map +1 -0
- package/dist/index93.js +2 -0
- package/dist/index93.js.map +1 -0
- package/dist/index94.js +2 -0
- package/dist/index94.js.map +1 -0
- package/dist/index95.js +2 -0
- package/dist/index95.js.map +1 -0
- package/dist/index96.js +2 -0
- package/dist/index96.js.map +1 -0
- package/dist/index97.js +2 -0
- package/dist/index97.js.map +1 -0
- package/dist/index98.js +2 -0
- package/dist/index98.js.map +1 -0
- package/dist/index99.js +2 -0
- package/dist/index99.js.map +1 -0
- package/dist/indicators/adx.d.ts +6 -0
- package/dist/indicators/aroon.d.ts +5 -0
- package/dist/indicators/atr.d.ts +1 -0
- package/dist/indicators/awesome-oscillator.d.ts +1 -0
- package/dist/indicators/bollinger.d.ts +6 -0
- package/dist/indicators/cci.d.ts +1 -0
- package/dist/indicators/chaikin-mf.d.ts +1 -0
- package/dist/indicators/choppiness.d.ts +1 -0
- package/dist/indicators/coppock.d.ts +1 -0
- package/dist/indicators/donchian.d.ts +6 -0
- package/dist/indicators/elder-force.d.ts +1 -0
- package/dist/indicators/ema.d.ts +1 -0
- package/dist/indicators/ichimoku.d.ts +8 -0
- package/dist/indicators/index.d.ts +31 -0
- package/dist/indicators/keltner.d.ts +6 -0
- package/dist/indicators/linear-regression.d.ts +1 -0
- package/dist/indicators/macd.d.ts +6 -0
- package/dist/indicators/mfi.d.ts +1 -0
- package/dist/indicators/obv.d.ts +1 -0
- package/dist/indicators/parabolic-sar.d.ts +1 -0
- package/dist/indicators/pivot-points.d.ts +10 -0
- package/dist/indicators/roc.d.ts +1 -0
- package/dist/indicators/rsi.d.ts +1 -0
- package/dist/indicators/sma.d.ts +1 -0
- package/dist/indicators/stochastic.d.ts +5 -0
- package/dist/indicators/supertrend.d.ts +5 -0
- package/dist/indicators/trix.d.ts +5 -0
- package/dist/indicators/utils.d.ts +20 -0
- package/dist/indicators/volume-profile.d.ts +37 -0
- package/dist/indicators/volume.d.ts +1 -0
- package/dist/indicators/vwap.d.ts +1 -0
- package/dist/indicators/vwma.d.ts +1 -0
- package/dist/indicators/williams-r.d.ts +1 -0
- package/dist/interactions/axis-drag.d.ts +24 -0
- package/dist/interactions/context-menu-handler.d.ts +42 -0
- package/dist/interactions/crosshair.d.ts +20 -0
- package/dist/interactions/drawing-handler.d.ts +39 -0
- package/dist/interactions/event-router.d.ts +37 -0
- package/dist/interactions/keyboard-nav.d.ts +11 -0
- package/dist/interactions/pan-zoom.d.ts +39 -0
- package/dist/interactions/range-selection.d.ts +103 -0
- package/dist/interactions/touch-gestures.d.ts +36 -0
- package/dist/logo.svg +40 -0
- package/dist/market/exchange-map.d.ts +3 -0
- package/dist/market/index.d.ts +4 -0
- package/dist/market/market-calendar.d.ts +4 -0
- package/dist/market/market-definition.d.ts +22 -0
- package/dist/mockServiceWorker.js +349 -0
- package/dist/renderers/area.d.ts +17 -0
- package/dist/renderers/bar-ohlc.d.ts +17 -0
- package/dist/renderers/baseline-delta-mountain.d.ts +22 -0
- package/dist/renderers/baseline.d.ts +19 -0
- package/dist/renderers/candlestick.d.ts +21 -0
- package/dist/renderers/canvas-renderer.d.ts +28 -0
- package/dist/renderers/colored-line.d.ts +15 -0
- package/dist/renderers/colored-mountain.d.ts +18 -0
- package/dist/renderers/column.d.ts +14 -0
- package/dist/renderers/high-low.d.ts +14 -0
- package/dist/renderers/histogram.d.ts +16 -0
- package/dist/renderers/hlc-area.d.ts +16 -0
- package/dist/renderers/hollow-candle.d.ts +18 -0
- package/dist/renderers/kagi.d.ts +22 -0
- package/dist/renderers/line-break.d.ts +20 -0
- package/dist/renderers/line.d.ts +17 -0
- package/dist/renderers/point-figure.d.ts +20 -0
- package/dist/renderers/renderer.d.ts +59 -0
- package/dist/renderers/renko.d.ts +24 -0
- package/dist/renderers/step-line.d.ts +14 -0
- package/dist/renderers/text-cache.d.ts +23 -0
- package/dist/renderers/volume-candle.d.ts +20 -0
- package/dist/renderers/webgl/area-webgl.d.ts +28 -0
- package/dist/renderers/webgl/candlestick-webgl.d.ts +30 -0
- package/dist/renderers/webgl/index.d.ts +7 -0
- package/dist/renderers/webgl/line-webgl.d.ts +23 -0
- package/dist/renderers/webgl/webgl-utils.d.ts +23 -0
- package/dist/timezone/index.d.ts +2 -0
- package/dist/timezone/timezone.d.ts +12 -0
- package/dist/transforms/aggregate.d.ts +2 -0
- package/dist/transforms/heikin-ashi.d.ts +2 -0
- package/dist/transforms/index.d.ts +2 -0
- package/dist/ui/context-menu.d.ts +14 -0
- package/dist/ui/hud.d.ts +43 -0
- package/dist/ui/settings-popup.d.ts +15 -0
- package/package.json +129 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index38.js","names":[],"sources":["../src/drawings/index.ts"],"sourcesContent":["import type { ISeriesPrimitive } from '../core/types';\nimport type { DrawingFactory, AnchorPoint, DrawingOptions, DrawingPrimitive } from './base';\n\nimport { createHorizontalLine } from './horizontal-line';\nimport { createVerticalLine } from './vertical-line';\nimport { createTrendline } from './trendline';\nimport { createFibonacci } from './fibonacci';\nimport { createRectangle } from './rectangle';\nimport { createTextAnnotation } from './text-annotation';\nimport { createRay } from './ray';\nimport { createArrow } from './arrow';\nimport { createChannel } from './channel';\nimport { createEllipse } from './ellipse';\nimport { createPitchfork } from './pitchfork';\nimport { createFibProjection } from './fib-projection';\nimport { createFibArc } from './fib-arc';\nimport { createFibFan } from './fib-fan';\nimport { createCrossline } from './crossline';\nimport { createMeasurement } from './measurement';\n\n// Re-export public types\nexport type { AnchorPoint, DrawingOptions, DrawingHitTestResult, SerializedDrawing, DrawingPrimitive, DrawingContext, DrawingFactory } from './base';\nexport { distToSegment, pointInRect, HIT_THRESHOLD, BaseDrawing } from './base';\n\n// ─── Registry ─────────────────────────────────────────────────────────────────\n\nexport const DRAWING_REGISTRY = new Map<string, DrawingFactory>();\n\nexport function registerBuiltinDrawings(): void {\n DRAWING_REGISTRY.set('horizontal-line', createHorizontalLine as DrawingFactory);\n DRAWING_REGISTRY.set('vertical-line', createVerticalLine as DrawingFactory);\n DRAWING_REGISTRY.set('trendline', createTrendline as DrawingFactory);\n DRAWING_REGISTRY.set('fibonacci', createFibonacci as DrawingFactory);\n DRAWING_REGISTRY.set('rectangle', createRectangle as DrawingFactory);\n DRAWING_REGISTRY.set('text-annotation', createTextAnnotation as DrawingFactory);\n DRAWING_REGISTRY.set('ray', createRay as DrawingFactory);\n DRAWING_REGISTRY.set('arrow', createArrow as DrawingFactory);\n DRAWING_REGISTRY.set('channel', createChannel as DrawingFactory);\n DRAWING_REGISTRY.set('ellipse', createEllipse as DrawingFactory);\n DRAWING_REGISTRY.set('pitchfork', createPitchfork as DrawingFactory);\n DRAWING_REGISTRY.set('fib-projection', createFibProjection as DrawingFactory);\n DRAWING_REGISTRY.set('fib-arc', createFibArc as DrawingFactory);\n DRAWING_REGISTRY.set('fib-fan', createFibFan as DrawingFactory);\n DRAWING_REGISTRY.set('crossline', createCrossline as DrawingFactory);\n DRAWING_REGISTRY.set('measurement', createMeasurement as DrawingFactory);\n}\n\n// Register built-ins immediately on import\nregisterBuiltinDrawings();\n\nexport function createBuiltinDrawing(\n type: string,\n id: string,\n points: AnchorPoint[],\n options: DrawingOptions,\n): (ISeriesPrimitive & DrawingPrimitive) | null {\n const factory = DRAWING_REGISTRY.get(type);\n if (!factory) return null;\n return factory(id, points, options);\n}\n"],"mappings":"8zBA0BA,IAAa,iBAAmB,IAAI,IAwBpC,SAAgB,EACd,EACA,EACA,EACA,GAEA,MAAM,EAAU,EAAiB,IAAI,GACrC,OAAK,EACE,EAAQ,EAAI,EAAQ,GADN,KA5BrB,EAAiB,IAAI,kBAAmB,GACxC,EAAiB,IAAI,gBAAiB,GACtC,EAAiB,IAAI,YAAa,GAClC,EAAiB,IAAI,YAAa,GAClC,EAAiB,IAAI,YAAa,GAClC,EAAiB,IAAI,kBAAmB,GACxC,EAAiB,IAAI,MAAO,GAC5B,EAAiB,IAAI,QAAS,GAC9B,EAAiB,IAAI,UAAW,GAChC,EAAiB,IAAI,UAAW,GAChC,EAAiB,IAAI,YAAa,GAClC,EAAiB,IAAI,iBAAkB,GACvC,EAAiB,IAAI,UAAW,GAChC,EAAiB,IAAI,UAAW,GAChC,EAAiB,IAAI,YAAa,GAClC,EAAiB,IAAI,cAAe"}
|
package/dist/index39.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{DRAWING_REGISTRY as t}from"./index38.js";var i=class{constructor(t){this._state="IDLE",this._activeToolType=null,this._placingDrawing=null,this._placedPointCount=0,this._nextId=0,this._selectedDrawing=null,this._editHit=null,this._dragStartX=0,this._dragStartY=0,this._dragStartPoints=[],this._callbacks=t}get state(){return this._state}setActiveToolType(t){this._activeToolType=t,t?(this._state="PLACING",this._placingDrawing=null,this._placedPointCount=0):"PLACING"===this._state&&(this._state="IDLE",this._placingDrawing=null)}onPointerDown(t,i,e){if("PLACING"===this._state&&this._activeToolType)return this._handlePlacementClick(t,i);const s=this._hitTestDrawings(t,i);if(s){this._state="EDITING";const e=this._callbacks.getDrawings().find(t=>"drawingType"in t&&"points"in t&&"selected"in t&&"drawingHitTest"in t&&"id"in t&&t.id===s.drawingId);if(e)return this._selectedDrawing&&(this._selectedDrawing.selected=!1),e.selected=!0,this._selectedDrawing=e,this._editHit=s,this._dragStartX=t,this._dragStartY=i,this._dragStartPoints=e.points.map(t=>({...t})),this._callbacks.onDrawingUpdated(),!0}return this._selectedDrawing&&(this._selectedDrawing.selected=!1,this._selectedDrawing=null,this._state="IDLE",this._callbacks.onDrawingUpdated()),!1}onPointerMove(t,i,e){if("PLACING"===this._state&&this._placingDrawing&&this._placedPointCount>=1){const e=this._callbacks.xToTime(t),s=this._callbacks.yToPrice(i),a=this._placingDrawing.points,n=this._placedPointCount;return a.length>n?a[n]={time:e,price:s}:a.push({time:e,price:s}),this._callbacks.onDrawingUpdated(),!0}if("EDITING"===this._state&&this._selectedDrawing&&this._editHit){const e=t-this._dragStartX,s=i-this._dragStartY;return this._applyDrag(e,s),this._callbacks.onDrawingUpdated(this._selectedDrawing),!0}return!1}onPointerUp(t){return"EDITING"===this._state&&(this._editHit=null,this._state=this._selectedDrawing?"SELECTING":"IDLE",!0)}onKeyDown(t,i){if("Escape"===t){if("PLACING"===this._state)return this._activeToolType=null,this._placingDrawing=null,this._state="IDLE",this._callbacks.onDrawingUpdated(),!0;if(this._selectedDrawing)return this._selectedDrawing.selected=!1,this._selectedDrawing=null,this._state="IDLE",this._callbacks.onDrawingUpdated(),!0}return!("Delete"!==t&&"Backspace"!==t||!this._selectedDrawing)&&(this._selectedDrawing.selected=!1,this._selectedDrawing=null,this._state="IDLE",this._callbacks.onDrawingUpdated(),!0)}_handlePlacementClick(i,e){const s=this._activeToolType,a=this._callbacks.xToTime(i),n=this._callbacks.yToPrice(e);if(!this._placingDrawing){const i=t.get(s);if(!i)return!1;const e=i(`interactive-drawing-${Date.now()}-${this._nextId++}`,[{time:a,price:n}],{}),l=this._callbacks.getDrawingContext();return l&&e.setContext(l),this._placingDrawing=e,this._placedPointCount=1,1===e.requiredPoints?(this._callbacks.onDrawingCreated(e),this._placingDrawing=null,this._placedPointCount=0,!0):(e.points.push({time:a,price:n}),this._callbacks.onDrawingCreated(e),!0)}return this._placingDrawing.points[this._placedPointCount]={time:a,price:n},this._placedPointCount++,this._placedPointCount>=this._placingDrawing.requiredPoints&&(this._placingDrawing=null,this._placedPointCount=0,this._callbacks.onDrawingUpdated()),!0}_hitTestDrawings(t,i){const e=this._callbacks.getDrawings();for(let s=e.length-1;s>=0;s--){const a=e[s].drawingHitTest(t,i);if(a)return a}return null}_applyDrag(t,i){if(!this._selectedDrawing||!this._editHit)return;const e=this._callbacks.getDrawingContext();if(!e)return;const s=this._editHit.part,a=this._selectedDrawing.points;if("handle1"===s&&this._dragStartPoints.length>=1){const s=this._dragStartPoints[0],n=e.timeScale.indexToX(s.time),l=e.priceScale.priceToY(s.price);a[0]={time:this._callbacks.xToTime(n+t),price:this._callbacks.yToPrice(l+i)}}else if("handle2"===s&&this._dragStartPoints.length>=2){const s=this._dragStartPoints[1],n=e.timeScale.indexToX(s.time),l=e.priceScale.priceToY(s.price);a[1]={time:this._callbacks.xToTime(n+t),price:this._callbacks.yToPrice(l+i)}}else for(let n=0;n<a.length&&n<this._dragStartPoints.length;n++){const s=this._dragStartPoints[n],l=e.timeScale.indexToX(s.time),r=e.priceScale.priceToY(s.price);a[n]={time:this._callbacks.xToTime(l+t),price:this._callbacks.yToPrice(r+i)}}}};export{i as DrawingHandler};
|
|
2
|
+
//# sourceMappingURL=index39.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index39.js","names":[],"sources":["../src/interactions/drawing-handler.ts"],"sourcesContent":["import type { EventHandler } from './event-router';\nimport type { ISeriesPrimitive } from '../core/types';\nimport type {\n AnchorPoint,\n DrawingOptions,\n DrawingPrimitive,\n DrawingHitTestResult,\n DrawingContext,\n} from '../drawings/base';\nimport { BaseDrawing, HIT_THRESHOLD } from '../drawings/base';\nimport { DRAWING_REGISTRY } from '../drawings/index';\n\n// ─── State machine ───────────────────────────────────────────────────────────\n\nexport type DrawingHandlerState = 'IDLE' | 'SELECTING' | 'PLACING' | 'EDITING';\n\nexport interface DrawingHandlerCallbacks {\n getDrawings(): (ISeriesPrimitive & DrawingPrimitive)[];\n getDrawingContext(): DrawingContext | null;\n onDrawingCreated(drawing: ISeriesPrimitive & DrawingPrimitive): void;\n onDrawingUpdated(drawing?: ISeriesPrimitive & DrawingPrimitive): void;\n xToTime(x: number): number;\n yToPrice(y: number): number;\n}\n\n/**\n * Interaction handler for drawing tools.\n * Manages placement of new drawings and selection/editing of existing drawings.\n */\nexport class DrawingHandler implements EventHandler {\n private _state: DrawingHandlerState = 'IDLE';\n private _activeToolType: string | null = null;\n private _callbacks: DrawingHandlerCallbacks;\n\n // Placement state\n private _placingDrawing: (BaseDrawing & DrawingPrimitive) | null = null;\n private _placedPointCount: number = 0;\n private _nextId: number = 0;\n\n // Editing state\n private _selectedDrawing: (ISeriesPrimitive & DrawingPrimitive) | null = null;\n private _editHit: DrawingHitTestResult | null = null;\n private _dragStartX: number = 0;\n private _dragStartY: number = 0;\n private _dragStartPoints: AnchorPoint[] = [];\n\n constructor(callbacks: DrawingHandlerCallbacks) {\n this._callbacks = callbacks;\n }\n\n get state(): DrawingHandlerState {\n return this._state;\n }\n\n setActiveToolType(type: string | null): void {\n this._activeToolType = type;\n if (type) {\n this._state = 'PLACING';\n this._placingDrawing = null;\n this._placedPointCount = 0;\n } else {\n if (this._state === 'PLACING') {\n this._state = 'IDLE';\n this._placingDrawing = null;\n }\n }\n }\n\n // ── EventHandler ──────────────────────────────────────────────────────────\n\n onPointerDown(x: number, y: number, _pointerId: number): boolean {\n // PLACING mode: set anchor points\n if (this._state === 'PLACING' && this._activeToolType) {\n return this._handlePlacementClick(x, y);\n }\n\n // IDLE/SELECTING: try to select an existing drawing\n const hit = this._hitTestDrawings(x, y);\n if (hit) {\n this._state = 'EDITING';\n const drawings = this._callbacks.getDrawings();\n const drawing = drawings.find(d =>\n 'drawingType' in d && 'points' in d && 'selected' in d && 'drawingHitTest' in d\n && 'id' in d && (d as unknown as { id: string }).id === hit.drawingId\n );\n if (drawing) {\n // Deselect previous\n if (this._selectedDrawing) this._selectedDrawing.selected = false;\n drawing.selected = true;\n this._selectedDrawing = drawing;\n this._editHit = hit;\n this._dragStartX = x;\n this._dragStartY = y;\n this._dragStartPoints = drawing.points.map(p => ({ ...p }));\n this._callbacks.onDrawingUpdated();\n return true; // consume event\n }\n }\n\n // Clicked on nothing: deselect\n if (this._selectedDrawing) {\n this._selectedDrawing.selected = false;\n this._selectedDrawing = null;\n this._state = 'IDLE';\n this._callbacks.onDrawingUpdated();\n }\n\n return false; // let other handlers process\n }\n\n onPointerMove(x: number, y: number, _pointerId: number): boolean {\n // While placing: update the next (preview) point at _placedPointCount index\n if (this._state === 'PLACING' && this._placingDrawing && this._placedPointCount >= 1) {\n const time = this._callbacks.xToTime(x);\n const price = this._callbacks.yToPrice(y);\n const pts = this._placingDrawing.points;\n const previewIdx = this._placedPointCount;\n if (pts.length > previewIdx) {\n pts[previewIdx] = { time, price };\n } else {\n pts.push({ time, price });\n }\n this._callbacks.onDrawingUpdated();\n return true;\n }\n\n // Editing: drag the drawing\n if (this._state === 'EDITING' && this._selectedDrawing && this._editHit) {\n const dx = x - this._dragStartX;\n const dy = y - this._dragStartY;\n this._applyDrag(dx, dy);\n this._callbacks.onDrawingUpdated(this._selectedDrawing);\n return true;\n }\n\n return false;\n }\n\n onPointerUp(_pointerId: number): boolean {\n if (this._state === 'EDITING') {\n this._editHit = null;\n this._state = this._selectedDrawing ? 'SELECTING' : 'IDLE';\n return true;\n }\n return false;\n }\n\n onKeyDown(key: string, _shiftKey: boolean): boolean {\n if (key === 'Escape') {\n if (this._state === 'PLACING') {\n this._activeToolType = null;\n this._placingDrawing = null;\n this._state = 'IDLE';\n this._callbacks.onDrawingUpdated();\n return true;\n }\n if (this._selectedDrawing) {\n this._selectedDrawing.selected = false;\n this._selectedDrawing = null;\n this._state = 'IDLE';\n this._callbacks.onDrawingUpdated();\n return true;\n }\n }\n if (key === 'Delete' || key === 'Backspace') {\n if (this._selectedDrawing) {\n // The chart-api will handle actual removal via the IDrawingApi\n this._selectedDrawing.selected = false;\n this._selectedDrawing = null;\n this._state = 'IDLE';\n this._callbacks.onDrawingUpdated();\n return true;\n }\n }\n return false;\n }\n\n // ── Private ───────────────────────────────────────────────────────────────\n\n private _handlePlacementClick(x: number, y: number): boolean {\n const type = this._activeToolType!;\n const time = this._callbacks.xToTime(x);\n const price = this._callbacks.yToPrice(y);\n\n if (!this._placingDrawing) {\n // Create the drawing with the first point\n const factory = DRAWING_REGISTRY.get(type);\n if (!factory) return false;\n const id = `interactive-drawing-${Date.now()}-${this._nextId++}`;\n const drawing = factory(id, [{ time, price }], {}) as BaseDrawing & DrawingPrimitive;\n const drawingCtx = this._callbacks.getDrawingContext();\n if (drawingCtx) drawing.setContext(drawingCtx);\n this._placingDrawing = drawing;\n this._placedPointCount = 1;\n\n // If only 1 point required, finalize immediately\n if (drawing.requiredPoints === 1) {\n this._callbacks.onDrawingCreated(drawing);\n this._placingDrawing = null;\n this._placedPointCount = 0;\n // Stay in PLACING for the next drawing of the same type\n return true;\n }\n\n // For multi-point drawings, add a preview second point at the same location\n drawing.points.push({ time, price });\n this._callbacks.onDrawingCreated(drawing);\n return true;\n }\n\n // Second click for 2-point drawings: finalize\n this._placingDrawing.points[this._placedPointCount] = { time, price };\n this._placedPointCount++;\n if (this._placedPointCount >= this._placingDrawing.requiredPoints) {\n this._placingDrawing = null;\n this._placedPointCount = 0;\n this._callbacks.onDrawingUpdated();\n // Stay in PLACING for the next drawing\n }\n return true;\n }\n\n private _hitTestDrawings(x: number, y: number): DrawingHitTestResult | null {\n const drawings = this._callbacks.getDrawings();\n // Iterate in reverse (top-most first)\n for (let i = drawings.length - 1; i >= 0; i--) {\n const d = drawings[i];\n const hit = d.drawingHitTest(x, y);\n if (hit) return hit;\n }\n return null;\n }\n\n private _applyDrag(dx: number, dy: number): void {\n if (!this._selectedDrawing || !this._editHit) return;\n const ctx = this._callbacks.getDrawingContext();\n if (!ctx) return;\n\n const part = this._editHit.part;\n const pts = this._selectedDrawing.points;\n\n if (part === 'handle1' && this._dragStartPoints.length >= 1) {\n const orig = this._dragStartPoints[0];\n const origX = ctx.timeScale.indexToX(orig.time);\n const origY = ctx.priceScale.priceToY(orig.price);\n pts[0] = {\n time: this._callbacks.xToTime(origX + dx),\n price: this._callbacks.yToPrice(origY + dy),\n };\n } else if (part === 'handle2' && this._dragStartPoints.length >= 2) {\n const orig = this._dragStartPoints[1];\n const origX = ctx.timeScale.indexToX(orig.time);\n const origY = ctx.priceScale.priceToY(orig.price);\n pts[1] = {\n time: this._callbacks.xToTime(origX + dx),\n price: this._callbacks.yToPrice(origY + dy),\n };\n } else {\n // Move all points\n for (let i = 0; i < pts.length && i < this._dragStartPoints.length; i++) {\n const orig = this._dragStartPoints[i];\n const origX = ctx.timeScale.indexToX(orig.time);\n const origY = ctx.priceScale.priceToY(orig.price);\n pts[i] = {\n time: this._callbacks.xToTime(origX + dx),\n price: this._callbacks.yToPrice(origY + dy),\n };\n }\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/index4.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var i=class{constructor(){this.visible=!1,this.x=0,this.y=0,this.barIndex=-1,this.price=0,this.time=0,this.sourcePaneId="",this._snappedX=void 0}get snappedX(){return this._snappedX??this.x}update(i){this.visible=!0,this.x=i.x,this.y=i.y,this.barIndex=i.barIndex,this.price=i.price,this.time=i.time,this._snappedX=i.snappedX,void 0!==i.sourcePaneId&&(this.sourcePaneId=i.sourcePaneId)}hide(){this.visible=!1}};export{i as Crosshair};
|
|
2
|
+
//# sourceMappingURL=index4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index4.js","names":[],"sources":["../src/core/crosshair.ts"],"sourcesContent":["export interface CrosshairState {\n x: number;\n y: number;\n barIndex: number;\n price: number;\n time: number;\n /** X coordinate snapped to the bar centre (optional — falls back to x). */\n snappedX?: number;\n /** The pane that generated this crosshair event. */\n sourcePaneId?: string;\n}\n\nexport class Crosshair {\n public visible: boolean = false;\n public x: number = 0;\n public y: number = 0;\n public barIndex: number = -1;\n public price: number = 0;\n public time: number = 0;\n /** The ID of the pane the pointer is currently over. */\n public sourcePaneId: string = '';\n private _snappedX: number | undefined = undefined;\n\n /** X coordinate snapped to the bar centre; falls back to x if not provided. */\n get snappedX(): number {\n return this._snappedX ?? this.x;\n }\n\n /** Make the crosshair visible and update all properties. */\n update(state: CrosshairState): void {\n this.visible = true;\n this.x = state.x;\n this.y = state.y;\n this.barIndex = state.barIndex;\n this.price = state.price;\n this.time = state.time;\n this._snappedX = state.snappedX;\n if (state.sourcePaneId !== undefined) {\n this.sourcePaneId = state.sourcePaneId;\n }\n }\n\n /** Hide the crosshair. */\n hide(): void {\n this.visible = false;\n }\n}\n"],"mappings":"AAYA,IAAa,EAAb,kCAC4B,SACP,SACA,iBACO,aACH,YACD,oBAEQ,uBACU,EAGxC,YAAI,GACF,OAAO,KAAK,WAAa,KAAK,EAIhC,MAAA,CAAO,GACL,KAAK,SAAU,EACf,KAAK,EAAI,EAAM,EACf,KAAK,EAAI,EAAM,EACf,KAAK,SAAW,EAAM,SACtB,KAAK,MAAQ,EAAM,MACnB,KAAK,KAAO,EAAM,KAClB,KAAK,UAAY,EAAM,cACI,IAAvB,EAAM,eACR,KAAK,aAAe,EAAM,cAK9B,IAAA,GACE,KAAK,SAAU"}
|
package/dist/index40.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function e(e,t,n,o){const r=document.createElement("div");r.style.cssText=`position:absolute;z-index:30;padding:8px 10px;border-radius:4px;background:${o.bg};color:${o.text};border:1px solid ${o.border};font-size:11px;pointer-events:auto;min-width:160px;box-shadow:0 2px 8px rgba(0,0,0,0.3);`;const p=/* @__PURE__ */new Map;let s=0;for(const c of e){const e=document.createElement("div");e.style.cssText="display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;gap:8px;";const t=`settings-field-${c.key}-${s++}`,n=document.createElement("label");n.textContent=c.label,n.style.cssText="flex-shrink:0;",n.htmlFor=t;const d=document.createElement("input");d.id=t,d.type=c.type,"number"===c.type?(d.style.cssText=`width:60px;background:${o.bg};color:${o.text};border:1px solid ${o.border};border-radius:2px;padding:2px 4px;font-size:11px;`,d.value=String(c.value),void 0!==c.min&&(d.min=String(c.min)),void 0!==c.max&&(d.max=String(c.max)),void 0!==c.step&&(d.step=String(c.step))):(d.style.cssText="width:28px;height:20px;padding:0;border:none;cursor:pointer;",d.value=String(c.value)),p.set(c.key,d),e.appendChild(n),e.appendChild(d),r.appendChild(e)}const d=document.createElement("div");d.style.cssText="display:flex;justify-content:flex-end;gap:6px;margin-top:6px;";const i=document.createElement("button");i.textContent="Cancel",i.style.cssText=`padding:2px 8px;font-size:11px;cursor:pointer;border-radius:2px;background:transparent;color:${o.text};border:1px solid ${o.border};pointer-events:auto;`,i.addEventListener("click",()=>n());const a=document.createElement("button");return a.textContent="Apply",a.style.cssText="padding:2px 8px;font-size:11px;cursor:pointer;border-radius:2px;background:#2962ff;color:#fff;border:none;pointer-events:auto;",a.addEventListener("click",()=>{const n={};for(const t of e){const e=p.get(t.key);"number"===t.type?n[t.key]=parseFloat(e.value):n[t.key]=e.value}t(n)}),d.appendChild(i),d.appendChild(a),r.appendChild(d),r}export{e as createSettingsPopup};
|
|
2
|
+
//# sourceMappingURL=index40.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index40.js","names":[],"sources":["../src/ui/settings-popup.ts"],"sourcesContent":["// ─── Settings Popup ────────────────────────────────────────────────────────\n\nexport interface SettingsField {\n key: string;\n label: string;\n type: 'number' | 'color';\n value: number | string;\n min?: number;\n max?: number;\n step?: number;\n}\n\nexport type OnApply = (values: Record<string, number | string>) => void;\n\nexport function createSettingsPopup(\n fields: SettingsField[],\n onApply: OnApply,\n onCancel: () => void,\n theme: { bg: string; text: string; border: string },\n): HTMLDivElement {\n const popup = document.createElement('div');\n popup.style.cssText =\n `position:absolute;z-index:30;padding:8px 10px;border-radius:4px;` +\n `background:${theme.bg};color:${theme.text};border:1px solid ${theme.border};` +\n `font-size:11px;pointer-events:auto;min-width:160px;box-shadow:0 2px 8px rgba(0,0,0,0.3);`;\n\n const inputs: Map<string, HTMLInputElement> = new Map();\n let fieldIdx = 0;\n\n for (const field of fields) {\n const row = document.createElement('div');\n row.style.cssText = 'display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;gap:8px;';\n\n const inputId = `settings-field-${field.key}-${fieldIdx++}`;\n\n const label = document.createElement('label');\n label.textContent = field.label;\n label.style.cssText = 'flex-shrink:0;';\n label.htmlFor = inputId;\n\n const input = document.createElement('input');\n input.id = inputId;\n input.type = field.type;\n\n if (field.type === 'number') {\n input.style.cssText =\n `width:60px;background:${theme.bg};color:${theme.text};border:1px solid ${theme.border};` +\n `border-radius:2px;padding:2px 4px;font-size:11px;`;\n input.value = String(field.value);\n if (field.min !== undefined) input.min = String(field.min);\n if (field.max !== undefined) input.max = String(field.max);\n if (field.step !== undefined) input.step = String(field.step);\n } else {\n // color input\n input.style.cssText = 'width:28px;height:20px;padding:0;border:none;cursor:pointer;';\n input.value = String(field.value);\n }\n\n inputs.set(field.key, input);\n row.appendChild(label);\n row.appendChild(input);\n popup.appendChild(row);\n }\n\n // Button row\n const btnRow = document.createElement('div');\n btnRow.style.cssText = 'display:flex;justify-content:flex-end;gap:6px;margin-top:6px;';\n\n const cancelBtn = document.createElement('button');\n cancelBtn.textContent = 'Cancel';\n cancelBtn.style.cssText =\n `padding:2px 8px;font-size:11px;cursor:pointer;border-radius:2px;` +\n `background:transparent;color:${theme.text};border:1px solid ${theme.border};pointer-events:auto;`;\n cancelBtn.addEventListener('click', () => onCancel());\n\n const applyBtn = document.createElement('button');\n applyBtn.textContent = 'Apply';\n applyBtn.style.cssText =\n `padding:2px 8px;font-size:11px;cursor:pointer;border-radius:2px;` +\n `background:#2962ff;color:#fff;border:none;pointer-events:auto;`;\n applyBtn.addEventListener('click', () => {\n const values: Record<string, number | string> = {};\n for (const field of fields) {\n const inp = inputs.get(field.key)!;\n if (field.type === 'number') {\n values[field.key] = parseFloat(inp.value);\n } else {\n values[field.key] = inp.value;\n }\n }\n onApply(values);\n });\n\n btnRow.appendChild(cancelBtn);\n btnRow.appendChild(applyBtn);\n popup.appendChild(btnRow);\n\n return popup;\n}\n"],"mappings":"AAcA,SAAgB,EACd,EACA,EACA,EACA,GAEA,MAAM,EAAQ,SAAS,cAAc,OACrC,EAAM,MAAM,QACV,8EACc,EAAM,YAAY,EAAM,yBAAyB,EAAM,kGAGvE,MAAM,iBAAwC,IAAI,IAClD,IAAI,EAAW,EAEf,IAAK,MAAM,KAAS,EAAQ,CAC1B,MAAM,EAAM,SAAS,cAAc,OACnC,EAAI,MAAM,QAAU,2FAEpB,MAAM,EAAU,kBAAkB,EAAM,OAAO,MAEzC,EAAQ,SAAS,cAAc,SACrC,EAAM,YAAc,EAAM,MAC1B,EAAM,MAAM,QAAU,iBACtB,EAAM,QAAU,EAEhB,MAAM,EAAQ,SAAS,cAAc,SACrC,EAAM,GAAK,EACX,EAAM,KAAO,EAAM,KAEA,WAAf,EAAM,MACR,EAAM,MAAM,QACV,yBAAyB,EAAM,YAAY,EAAM,yBAAyB,EAAM,2DAElF,EAAM,MAAQ,OAAO,EAAM,YACT,IAAd,EAAM,MAAmB,EAAM,IAAM,OAAO,EAAM,WACpC,IAAd,EAAM,MAAmB,EAAM,IAAM,OAAO,EAAM,WACnC,IAAf,EAAM,OAAoB,EAAM,KAAO,OAAO,EAAM,SAGxD,EAAM,MAAM,QAAU,+DACtB,EAAM,MAAQ,OAAO,EAAM,QAG7B,EAAO,IAAI,EAAM,IAAK,GACtB,EAAI,YAAY,GAChB,EAAI,YAAY,GAChB,EAAM,YAAY,GAIpB,MAAM,EAAS,SAAS,cAAc,OACtC,EAAO,MAAM,QAAU,gEAEvB,MAAM,EAAY,SAAS,cAAc,UACzC,EAAU,YAAc,SACxB,EAAU,MAAM,QACd,gGACgC,EAAM,yBAAyB,EAAM,8BACvE,EAAU,iBAAiB,QAAA,IAAe,KAE1C,MAAM,EAAW,SAAS,cAAc,UAsBxC,OArBA,EAAS,YAAc,QACvB,EAAS,MAAM,QACb,iIAEF,EAAS,iBAAiB,QAAA,KACxB,MAAM,EAA0C,CAAA,EAChD,IAAK,MAAM,KAAS,EAAQ,CAC1B,MAAM,EAAM,EAAO,IAAI,EAAM,KACV,WAAf,EAAM,KACR,EAAO,EAAM,KAAO,WAAW,EAAI,OAEnC,EAAO,EAAM,KAAO,EAAI,MAG5B,EAAQ,KAGV,EAAO,YAAY,GACnB,EAAO,YAAY,GACnB,EAAM,YAAY,GAEX"}
|
package/dist/index41.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{createSettingsPopup as e}from"./index40.js";function t(e,t=14){const n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("viewBox","0 0 24 24"),n.setAttribute("width",String(t)),n.setAttribute("height",String(t)),n.style.cssText="fill:currentColor;vertical-align:middle;flex-shrink:0;";const l=document.createElementNS("http://www.w3.org/2000/svg","path");return l.setAttribute("d",e),n.appendChild(l),n}var n="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z",l="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z",i=class{constructor(e,n){this._rows=/* @__PURE__ */new Map,this._activePopup=null,this._outsideClickHandler=null,this._pendingRaf=0,this._globalCollapsed=!1,this._onGlobalCollapseToggle=null,this._theme=n,this._container=document.createElement("div"),this._container.style.cssText=`position:absolute;top:4px;left:8px;z-index:10;pointer-events:none;font-size:11px;font-family:${n.fontFamily};color:${n.text};`;const i=document.createElement("div");i.style.cssText="display:flex;align-items:center;gap:4px;height:18px;pointer-events:auto;",this._globalChevron=document.createElement("button"),this._globalChevron.appendChild(t(l,14)),this._globalChevron.title="Collapse legend",this._globalChevron.style.cssText=this._chevronStyle(),this._globalChevron.addEventListener("click",()=>{this.setGlobalCollapsed(!this._globalCollapsed),this._onGlobalCollapseToggle?.()}),i.appendChild(this._globalChevron),this._compactLine=document.createElement("div"),this._compactLine.style.cssText=`color:${n.text};white-space:nowrap;font-size:11px;display:none;cursor:default;`,i.appendChild(this._compactLine),this._container.appendChild(i),this._rowsWrapper=document.createElement("div"),this._container.appendChild(this._rowsWrapper),e.appendChild(this._container)}get isGlobalCollapsed(){return this._globalCollapsed}set onGlobalCollapseToggle(e){this._onGlobalCollapseToggle=e}setGlobalCollapsed(e){this._globalCollapsed!==e&&(this._globalCollapsed=e,this._rowsWrapper.style.display=e?"none":"block",this._compactLine.style.display=e?"block":"none",this._globalChevron.innerHTML="",this._globalChevron.appendChild(t(e?"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z":l,14)),this._globalChevron.title=e?"Expand legend":"Collapse legend")}addRow(e){const l=document.createElement("div");l.style.cssText="margin-bottom:1px;";const i=document.createElement("div");i.style.cssText="display:flex;align-items:center;gap:4px;height:18px;pointer-events:auto;";const s=document.createElement("div");s.style.cssText=`width:10px;height:10px;border-radius:2px;flex-shrink:0;background:${e.color};`,i.appendChild(s);const o=document.createElement("span");o.textContent=e.label,o.style.cssText=`color:${this._theme.text};opacity:0.7;flex-shrink:0;cursor:default;`,i.appendChild(o);const a=document.createElement("div");a.style.cssText="display:inline-flex;align-items:center;gap:2px;margin-left:4px;opacity:0;transition:opacity 0.15s;";const c=document.createElement("button");c.appendChild(t(n,14)),c.title="Toggle visibility",c.style.cssText=this._buttonStyle(),c.addEventListener("click",()=>{const l=e.onToggleVisible();h.visible=l,c.innerHTML="",c.appendChild(t(l?n:"M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z",14)),c.style.opacity=l?"0.7":"0.3"}),a.appendChild(c);const p=document.createElement("button");p.appendChild(t("M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.488.488 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z",14)),p.title="Settings",p.style.cssText=this._buttonStyle(),p.addEventListener("click",()=>{this._openSettings(e,p)}),a.appendChild(p);const r=document.createElement("button");r.appendChild(t("M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z",14)),r.title="Remove",r.style.cssText=this._buttonStyle(),r.addEventListener("click",()=>{e.onRemove()}),a.appendChild(r),i.appendChild(a),l.appendChild(i),l.addEventListener("mouseenter",()=>{a.style.opacity="1"}),l.addEventListener("mouseleave",()=>{a.style.opacity="0"});const d=document.createElement("span");d.style.cssText=`color:${this._theme.text};white-space:nowrap;display:block;padding-left:14px;height:15px;line-height:15px;`,l.appendChild(d),this._rowsWrapper.appendChild(l);const h={config:e,el:l,valuesEl:d,buttonsEl:a,eyeBtn:c,visible:!0};this._rows.set(e.id,h)}removeRow(e){const t=this._rows.get(e);t&&(t.el.remove(),this._rows.delete(e))}updateValues(e){let t="";for(const n of this._rows.values()){const l=n.config.getValues(e);n.valuesEl.textContent=l,t||(t=`${n.config.label} ${l}`)}this._compactLine.textContent=t}triggerSettings(e){const t=this._rows.get(e);t&&t.buttonsEl.children[1]?.click()}destroy(){this._closePopup(),this._container.remove(),this._rows.clear()}_chevronStyle(){return`pointer-events:auto;background:none;border:none;cursor:pointer;color:${this._theme.text};padding:0;line-height:1;opacity:0.5;display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;`}_buttonStyle(){return`pointer-events:auto;background:none;border:none;cursor:pointer;color:${this._theme.text};padding:2px 3px;line-height:1;opacity:0.6;border-radius:3px;display:inline-flex;align-items:center;justify-content:center;`}_openSettings(t,n){this._closePopup();const l=t.getSettingsFields();if(0===l.length)return;const i=e(l,e=>{t.onSettingsApply(e),this._closePopup()},()=>{this._closePopup()},{bg:this._theme.bg,text:this._theme.text,border:this._theme.border}),s=n.getBoundingClientRect(),o=this._container.getBoundingClientRect();i.style.left=s.left-o.left+"px",i.style.top=s.bottom-o.top+4+"px",this._container.appendChild(i),this._activePopup=i,this._pendingRaf=requestAnimationFrame(()=>{this._pendingRaf=0,this._activePopup===i&&(this._outsideClickHandler=e=>{i.contains(e.target)||this._closePopup()},document.addEventListener("mousedown",this._outsideClickHandler,!0))})}_closePopup(){this._pendingRaf&&(cancelAnimationFrame(this._pendingRaf),this._pendingRaf=0),this._activePopup&&(this._activePopup.remove(),this._activePopup=null),this._outsideClickHandler&&(document.removeEventListener("mousedown",this._outsideClickHandler,!0),this._outsideClickHandler=null)}};export{i as HudManager};
|
|
2
|
+
//# sourceMappingURL=index41.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index41.js","names":[],"sources":["../src/ui/hud.ts"],"sourcesContent":["// ─── HUD (Heads-Up Display) Manager ────────────────────────────────────────\n\nimport { createSettingsPopup, type SettingsField, type OnApply } from './settings-popup';\n\n// ── Material Design Icon SVGs (24×24 viewBox, inlined) ──────────────────────\nfunction _svgIcon(pathD: string, size = 14): SVGSVGElement {\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('viewBox', '0 0 24 24');\n svg.setAttribute('width', String(size));\n svg.setAttribute('height', String(size));\n svg.style.cssText = 'fill:currentColor;vertical-align:middle;flex-shrink:0;';\n const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n path.setAttribute('d', pathD);\n svg.appendChild(path);\n return svg;\n}\n\n// Material Design icon paths\nconst MDI_EYE = 'M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z';\nconst MDI_EYE_OFF = 'M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z';\nconst MDI_SETTINGS = 'M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58a.49.49 0 00.12-.61l-1.92-3.32a.488.488 0 00-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.07.62-.07.94s.02.64.07.94l-2.03 1.58a.49.49 0 00-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z';\nconst MDI_CLOSE = 'M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z';\nconst MDI_CHEVRON_DOWN = 'M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6z';\nconst MDI_CHEVRON_RIGHT = 'M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z';\n\nexport interface HudRowConfig {\n id: string;\n label: string;\n color: string;\n getValues: (barIndex: number) => string;\n onToggleVisible: () => boolean; // returns new visibility state\n onRemove: () => void;\n getSettingsFields: () => SettingsField[];\n onSettingsApply: OnApply;\n}\n\ninterface HudRowEntry {\n config: HudRowConfig;\n el: HTMLDivElement;\n valuesEl: HTMLSpanElement;\n buttonsEl: HTMLDivElement;\n eyeBtn: HTMLButtonElement;\n visible: boolean;\n}\n\nexport class HudManager {\n private _container: HTMLDivElement;\n private _rows: Map<string, HudRowEntry> = new Map();\n private _theme: { bg: string; text: string; border: string; fontFamily: string };\n private _activePopup: HTMLDivElement | null = null;\n private _outsideClickHandler: ((e: MouseEvent) => void) | null = null;\n private _pendingRaf: number = 0;\n\n // Global collapse state\n private _globalCollapsed: boolean = false;\n private _compactLine!: HTMLDivElement;\n private _globalChevron!: HTMLButtonElement;\n private _rowsWrapper!: HTMLDivElement;\n private _onGlobalCollapseToggle: (() => void) | null = null;\n\n constructor(\n paneRow: HTMLElement,\n theme: { bg: string; text: string; border: string; fontFamily: string },\n ) {\n this._theme = theme;\n\n this._container = document.createElement('div');\n this._container.style.cssText =\n `position:absolute;top:4px;left:8px;z-index:10;pointer-events:none;` +\n `font-size:11px;font-family:${theme.fontFamily};color:${theme.text};`;\n\n // Global header: chevron + compact summary line\n const header = document.createElement('div');\n header.style.cssText = 'display:flex;align-items:center;gap:4px;height:18px;pointer-events:auto;';\n\n this._globalChevron = document.createElement('button');\n this._globalChevron.appendChild(_svgIcon(MDI_CHEVRON_DOWN, 14));\n this._globalChevron.title = 'Collapse legend';\n this._globalChevron.style.cssText = this._chevronStyle();\n this._globalChevron.addEventListener('click', () => {\n this.setGlobalCollapsed(!this._globalCollapsed);\n this._onGlobalCollapseToggle?.();\n });\n header.appendChild(this._globalChevron);\n\n this._compactLine = document.createElement('div');\n this._compactLine.style.cssText =\n `color:${theme.text};white-space:nowrap;font-size:11px;display:none;cursor:default;`;\n header.appendChild(this._compactLine);\n\n this._container.appendChild(header);\n\n this._rowsWrapper = document.createElement('div');\n this._container.appendChild(this._rowsWrapper);\n\n paneRow.appendChild(this._container);\n }\n\n // ── Global collapse ──────────────────────────────────────────────────────\n\n get isGlobalCollapsed(): boolean { return this._globalCollapsed; }\n\n set onGlobalCollapseToggle(cb: (() => void) | null) { this._onGlobalCollapseToggle = cb; }\n\n setGlobalCollapsed(collapsed: boolean): void {\n if (this._globalCollapsed === collapsed) return;\n this._globalCollapsed = collapsed;\n this._rowsWrapper.style.display = collapsed ? 'none' : 'block';\n this._compactLine.style.display = collapsed ? 'block' : 'none';\n this._globalChevron.innerHTML = '';\n this._globalChevron.appendChild(_svgIcon(collapsed ? MDI_CHEVRON_RIGHT : MDI_CHEVRON_DOWN, 14));\n this._globalChevron.title = collapsed ? 'Expand legend' : 'Collapse legend';\n }\n\n // ── Row management ───────────────────────────────────────────────────────\n\n addRow(config: HudRowConfig): void {\n const row = document.createElement('div');\n row.style.cssText = 'margin-bottom:1px;';\n\n // ── Header line: swatch + label + action buttons ──────\n const headerLine = document.createElement('div');\n headerLine.style.cssText =\n 'display:flex;align-items:center;gap:4px;height:18px;pointer-events:auto;';\n\n // Color swatch\n const swatch = document.createElement('div');\n swatch.style.cssText =\n `width:10px;height:10px;border-radius:2px;flex-shrink:0;background:${config.color};`;\n headerLine.appendChild(swatch);\n\n // Label\n const labelEl = document.createElement('span');\n labelEl.textContent = config.label;\n labelEl.style.cssText = `color:${this._theme.text};opacity:0.7;flex-shrink:0;cursor:default;`;\n headerLine.appendChild(labelEl);\n\n // Action buttons container — always in header, stable position\n const buttonsEl = document.createElement('div');\n buttonsEl.style.cssText =\n 'display:inline-flex;align-items:center;gap:2px;margin-left:4px;opacity:0;transition:opacity 0.15s;';\n\n // Eye toggle\n const eyeBtn = document.createElement('button');\n eyeBtn.appendChild(_svgIcon(MDI_EYE, 14));\n eyeBtn.title = 'Toggle visibility';\n eyeBtn.style.cssText = this._buttonStyle();\n eyeBtn.addEventListener('click', () => {\n const newVis = config.onToggleVisible();\n entry.visible = newVis;\n eyeBtn.innerHTML = '';\n eyeBtn.appendChild(_svgIcon(newVis ? MDI_EYE : MDI_EYE_OFF, 14));\n eyeBtn.style.opacity = newVis ? '0.7' : '0.3';\n });\n buttonsEl.appendChild(eyeBtn);\n\n // Gear settings\n const gearBtn = document.createElement('button');\n gearBtn.appendChild(_svgIcon(MDI_SETTINGS, 14));\n gearBtn.title = 'Settings';\n gearBtn.style.cssText = this._buttonStyle();\n gearBtn.addEventListener('click', () => {\n this._openSettings(config, gearBtn);\n });\n buttonsEl.appendChild(gearBtn);\n\n // X remove\n const removeBtn = document.createElement('button');\n removeBtn.appendChild(_svgIcon(MDI_CLOSE, 14));\n removeBtn.title = 'Remove';\n removeBtn.style.cssText = this._buttonStyle();\n removeBtn.addEventListener('click', () => {\n config.onRemove();\n });\n buttonsEl.appendChild(removeBtn);\n\n headerLine.appendChild(buttonsEl);\n row.appendChild(headerLine);\n\n // Show buttons on hover over entire row\n row.addEventListener('mouseenter', () => {\n buttonsEl.style.opacity = '1';\n });\n row.addEventListener('mouseleave', () => {\n buttonsEl.style.opacity = '0';\n });\n\n // ── Values line (always visible within expanded HUD) ──────────────────\n const valuesEl = document.createElement('span');\n valuesEl.style.cssText =\n `color:${this._theme.text};white-space:nowrap;display:block;` +\n `padding-left:14px;height:15px;line-height:15px;`;\n row.appendChild(valuesEl);\n\n this._rowsWrapper.appendChild(row);\n\n const entry: HudRowEntry = {\n config, el: row, valuesEl, buttonsEl, eyeBtn, visible: true,\n };\n this._rows.set(config.id, entry);\n }\n\n removeRow(id: string): void {\n const entry = this._rows.get(id);\n if (entry) {\n entry.el.remove();\n this._rows.delete(id);\n }\n }\n\n updateValues(barIndex: number): void {\n let firstValues = '';\n for (const entry of this._rows.values()) {\n const vals = entry.config.getValues(barIndex);\n entry.valuesEl.textContent = vals;\n if (!firstValues) {\n firstValues = `${entry.config.label} ${vals}`;\n }\n }\n this._compactLine.textContent = firstValues;\n }\n\n /** Programmatically open the settings popup for a row. */\n triggerSettings(rowId: string): void {\n const entry = this._rows.get(rowId);\n if (entry) {\n // Find the gear button (second button in the buttons container)\n const gearBtn = entry.buttonsEl.children[1] as HTMLButtonElement | undefined;\n gearBtn?.click();\n }\n }\n\n destroy(): void {\n this._closePopup();\n this._container.remove();\n this._rows.clear();\n }\n\n // ── Private ──────────────────────────────────────────────────────────────\n\n private _chevronStyle(): string {\n return (\n `pointer-events:auto;background:none;border:none;cursor:pointer;` +\n `color:${this._theme.text};padding:0;line-height:1;opacity:0.5;` +\n `display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;`\n );\n }\n\n private _buttonStyle(): string {\n return (\n `pointer-events:auto;background:none;border:none;cursor:pointer;` +\n `color:${this._theme.text};padding:2px 3px;line-height:1;opacity:0.6;` +\n `border-radius:3px;display:inline-flex;align-items:center;justify-content:center;`\n );\n }\n\n private _openSettings(config: HudRowConfig, anchor: HTMLButtonElement): void {\n this._closePopup();\n\n const fields = config.getSettingsFields();\n if (fields.length === 0) return;\n\n const popup = createSettingsPopup(\n fields,\n (values) => {\n config.onSettingsApply(values);\n this._closePopup();\n },\n () => {\n this._closePopup();\n },\n { bg: this._theme.bg, text: this._theme.text, border: this._theme.border },\n );\n\n // Position below anchor\n const anchorRect = anchor.getBoundingClientRect();\n const containerRect = this._container.getBoundingClientRect();\n popup.style.left = `${anchorRect.left - containerRect.left}px`;\n popup.style.top = `${anchorRect.bottom - containerRect.top + 4}px`;\n\n this._container.appendChild(popup);\n this._activePopup = popup;\n\n // Close on outside click (delayed to avoid immediate trigger)\n this._pendingRaf = requestAnimationFrame(() => {\n this._pendingRaf = 0;\n if (this._activePopup !== popup) return; // popup was closed before RAF fired\n this._outsideClickHandler = (e: MouseEvent) => {\n if (!popup.contains(e.target as Node)) {\n this._closePopup();\n }\n };\n document.addEventListener('mousedown', this._outsideClickHandler, true);\n });\n }\n\n private _closePopup(): void {\n if (this._pendingRaf) {\n cancelAnimationFrame(this._pendingRaf);\n this._pendingRaf = 0;\n }\n if (this._activePopup) {\n this._activePopup.remove();\n this._activePopup = null;\n }\n if (this._outsideClickHandler) {\n document.removeEventListener('mousedown', this._outsideClickHandler, true);\n this._outsideClickHandler = null;\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/index42.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"#22AB94",downColor:"#F7525F",wickUpColor:"#22AB94",wickDownColor:"#F7525F",borderUpColor:"#22AB94",borderDownColor:"#F7525F"},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}options(){return{...this._options}}draw(o,t,r,l,n,i){const{context:e,pixelRatio:s}=o,{fromIdx:a,toIdx:h}=r;if(a>=h||0===t.length)return;const p=this._options,d=Math.max(1,Math.round(i*s/2)),c=Math.max(1,Math.round(s));e.save();for(let M=a;M<=h&&M<t.length;M++){const o=t.open[M],r=t.close[M],i=t.high[M],a=t.low[M],h=r>=o,u=h?p.upColor:p.downColor,w=h?p.wickUpColor:p.wickDownColor,C=h?p.borderUpColor:p.borderDownColor,x=Math.round(l(M)*s),f=Math.round(n(o)*s),k=Math.round(n(r)*s),m=Math.round(n(i)*s),F=Math.round(n(a)*s);e.fillStyle=w,e.fillRect(x-Math.floor(c/2),m,c,F-m);const _=Math.min(f,k),b=Math.max(1,Math.max(f,k)-_);e.fillStyle=u,e.fillRect(x-d,_,2*d,b),e.strokeStyle=C,e.lineWidth=c,e.strokeRect(x-d+.5,_+.5,2*d-1,b-1)}e.restore()}};export{t as CandlestickRenderer};
|
|
2
|
+
//# sourceMappingURL=index42.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index42.js","names":[],"sources":["../src/renderers/candlestick.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface CandlestickRendererOptions {\n upColor: string;\n downColor: string;\n wickUpColor: string;\n wickDownColor: string;\n borderUpColor: string;\n borderDownColor: string;\n}\n\nconst DEFAULT_OPTIONS: CandlestickRendererOptions = {\n upColor: '#22AB94',\n downColor: '#F7525F',\n wickUpColor: '#22AB94',\n wickDownColor: '#F7525F',\n borderUpColor: '#22AB94',\n borderDownColor: '#F7525F',\n};\n\n/**\n * CandlestickRenderer — draws OHLC candles with body and wick rectangles.\n *\n * All pixel coordinates are multiplied by `target.pixelRatio` and rounded to\n * integers for crisp HiDPI rendering.\n */\nexport class CandlestickRenderer {\n private _options: CandlestickRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<CandlestickRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n options(): CandlestickRendererOptions {\n return { ...this._options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n\n // Physical half-width of the candle body (at least 1 physical pixel).\n const halfBody = Math.max(1, Math.round((barWidth * pr) / 2));\n // Wick width: 1 physical pixel.\n const wickWidth = Math.max(1, Math.round(pr));\n\n ctx.save();\n\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const open = store.open[i];\n const close = store.close[i];\n const high = store.high[i];\n const low = store.low[i];\n const isUp = close >= open;\n\n const bodyColor = isUp ? opts.upColor : opts.downColor;\n const wickColor = isUp ? opts.wickUpColor : opts.wickDownColor;\n const borderColor = isUp ? opts.borderUpColor : opts.borderDownColor;\n\n const cx = Math.round(indexToX(i) * pr);\n const openY = Math.round(priceToY(open) * pr);\n const closeY = Math.round(priceToY(close) * pr);\n const highY = Math.round(priceToY(high) * pr);\n const lowY = Math.round(priceToY(low) * pr);\n\n // ── Wick ──────────────────────────────────────────────────────────────\n ctx.fillStyle = wickColor;\n ctx.fillRect(cx - Math.floor(wickWidth / 2), highY, wickWidth, lowY - highY);\n\n // ── Body ──────────────────────────────────────────────────────────────\n const bodyTop = Math.min(openY, closeY);\n const bodyBottom = Math.max(openY, closeY);\n const bodyHeight = Math.max(1, bodyBottom - bodyTop);\n\n ctx.fillStyle = bodyColor;\n ctx.fillRect(cx - halfBody, bodyTop, halfBody * 2, bodyHeight);\n\n // ── Body border ───────────────────────────────────────────────────────\n ctx.strokeStyle = borderColor;\n ctx.lineWidth = wickWidth;\n ctx.strokeRect(cx - halfBody + 0.5, bodyTop + 0.5, halfBody * 2 - 1, bodyHeight - 1);\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAWA,IAAM,EAA8C,CAClD,QAAS,UACT,UAAW,UACX,YAAa,UACb,cAAe,UACf,cAAe,UACf,gBAAiB,WASN,EAAb,kCACiD,IAAK,GAEpD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,OAAA,GACE,MAAO,IAAK,KAAK,UAGnB,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SAGZ,EAAW,KAAK,IAAI,EAAG,KAAK,MAAO,EAAW,EAAM,IAEpD,EAAY,KAAK,IAAI,EAAG,KAAK,MAAM,IAEzC,EAAI,OAEJ,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAO,EAAM,KAAK,GAClB,EAAQ,EAAM,MAAM,GACpB,EAAO,EAAM,KAAK,GAClB,EAAM,EAAM,IAAI,GAChB,EAAO,GAAS,EAEhB,EAAY,EAAO,EAAK,QAAU,EAAK,UACvC,EAAY,EAAO,EAAK,YAAc,EAAK,cAC3C,EAAc,EAAO,EAAK,cAAgB,EAAK,gBAE/C,EAAK,KAAK,MAAM,EAAS,GAAK,GAC9B,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAS,KAAK,MAAM,EAAS,GAAS,GACtC,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAO,KAAK,MAAM,EAAS,GAAO,GAGxC,EAAI,UAAY,EAChB,EAAI,SAAS,EAAK,KAAK,MAAM,EAAY,GAAI,EAAO,EAAW,EAAO,GAGtE,MAAM,EAAU,KAAK,IAAI,EAAO,GAE1B,EAAa,KAAK,IAAI,EADT,KAAK,IAAI,EAAO,GACS,GAE5C,EAAI,UAAY,EAChB,EAAI,SAAS,EAAK,EAAU,EAAoB,EAAX,EAAc,GAGnD,EAAI,YAAc,EAClB,EAAI,UAAY,EAChB,EAAI,WAAW,EAAK,EAAW,GAAK,EAAU,GAAgB,EAAX,EAAe,EAAG,EAAa,GAGpF,EAAI"}
|
package/dist/index43.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={color:"#2196F3",lineWidth:2},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}options(){return{...this._options}}draw(o,t,n,i,e){const{context:s,pixelRatio:r}=o,{fromIdx:l,toIdx:h}=n;if(l>=h||0===t.length)return;const{color:p,lineWidth:a}=this._options;s.save(),s.strokeStyle=p,s.lineWidth=a*r,s.lineJoin="round",s.lineCap="round",s.setLineDash([]),s.beginPath();let c=!1;for(let d=l;d<=h&&d<t.length;d++){const o=Math.round(i(d)*r),n=Math.round(e(t.close[d])*r);c?s.lineTo(o,n):(s.moveTo(o,n),c=!0)}s.stroke(),s.restore()}};export{t as LineRenderer};
|
|
2
|
+
//# sourceMappingURL=index43.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index43.js","names":[],"sources":["../src/renderers/line.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface LineRendererOptions {\n color: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: LineRendererOptions = {\n color: '#2196F3',\n lineWidth: 2,\n};\n\n/**\n * LineRenderer — draws a close-price polyline over the visible bar range.\n *\n * Coordinates are multiplied by `target.pixelRatio` and rounded to integer\n * pixels so the line remains crisp on HiDPI displays.\n */\nexport class LineRenderer {\n private _options: LineRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<LineRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n options(): LineRendererOptions {\n return { ...this._options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const { color, lineWidth } = this._options;\n\n ctx.save();\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth * pr;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n\n ctx.beginPath();\n\n let started = false;\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const x = Math.round(indexToX(i) * pr);\n const y = Math.round(priceToY(store.close[i]) * pr);\n if (!started) {\n ctx.moveTo(x, y);\n started = true;\n } else {\n ctx.lineTo(x, y);\n }\n }\n\n ctx.stroke();\n ctx.restore();\n }\n}\n"],"mappings":"AAOA,IAAM,EAAuC,CAC3C,MAAO,UACP,UAAW,GASA,EAAb,kCAC0C,IAAK,GAE7C,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,OAAA,GACE,MAAO,IAAK,KAAK,UAGnB,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,MAAE,EAAA,UAAO,GAAc,KAAK,SAElC,EAAI,OACJ,EAAI,YAAc,EAClB,EAAI,UAAY,EAAY,EAC5B,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAEhB,EAAI,YAEJ,IAAI,GAAU,EACd,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAI,KAAK,MAAM,EAAS,GAAK,GAC7B,EAAI,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,GAC3C,EAIH,EAAI,OAAO,EAAG,IAHd,EAAI,OAAO,EAAG,GACd,GAAU,GAMd,EAAI,SACJ,EAAI"}
|
package/dist/index44.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={lineColor:"#2196F3",lineWidth:2,topColor:"rgba(33, 150, 243, 0.4)",bottomColor:"rgba(33, 150, 243, 0)"},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}options(){return{...this._options}}draw(o,t,e,n,i){const{context:l,pixelRatio:r,height:s}=o,{fromIdx:h,toIdx:a}=e;if(h>=a||0===t.length)return;const d=this._options,p=Math.round(s*r),x=[];for(let u=h;u<=a&&u<t.length;u++)x.push({x:Math.round(n(u)*r),y:Math.round(i(t.close[u])*r)});if(0===x.length)return;l.save();const c=x.reduce((o,t)=>Math.min(o,t.y),x[0].y),g=l.createLinearGradient(0,c,0,p);g.addColorStop(0,d.topColor),g.addColorStop(1,d.bottomColor),l.beginPath(),l.moveTo(x[0].x,x[0].y);for(let u=1;u<x.length;u++)l.lineTo(x[u].x,x[u].y);l.lineTo(x[x.length-1].x,p),l.lineTo(x[0].x,p),l.closePath(),l.fillStyle=g,l.fill(),l.beginPath(),l.moveTo(x[0].x,x[0].y);for(let u=1;u<x.length;u++)l.lineTo(x[u].x,x[u].y);l.strokeStyle=d.lineColor,l.lineWidth=d.lineWidth*r,l.lineJoin="round",l.lineCap="round",l.setLineDash([]),l.stroke(),l.restore()}};export{t as AreaRenderer};
|
|
2
|
+
//# sourceMappingURL=index44.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index44.js","names":[],"sources":["../src/renderers/area.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface AreaRendererOptions {\n lineColor: string;\n lineWidth: number;\n topColor: string;\n bottomColor: string;\n}\n\nconst DEFAULT_OPTIONS: AreaRendererOptions = {\n lineColor: '#2196F3',\n lineWidth: 2,\n topColor: 'rgba(33, 150, 243, 0.4)',\n bottomColor: 'rgba(33, 150, 243, 0)',\n};\n\n/**\n * AreaRenderer — draws a close-price line with a gradient fill from the line\n * down to the bottom of the pane.\n */\nexport class AreaRenderer {\n private _options: AreaRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<AreaRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n options(): AreaRendererOptions {\n return { ...this._options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr, height } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const bottomY = Math.round(height * pr);\n\n // Build the close-price polyline.\n const points: Array<{ x: number; y: number }> = [];\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n points.push({\n x: Math.round(indexToX(i) * pr),\n y: Math.round(priceToY(store.close[i]) * pr),\n });\n }\n if (points.length === 0) return;\n\n ctx.save();\n\n // ── Gradient fill ─────────────────────────────────────────────────────\n const minY = points.reduce((m, p) => Math.min(m, p.y), points[0].y);\n const gradient = ctx.createLinearGradient(0, minY, 0, bottomY);\n gradient.addColorStop(0, opts.topColor);\n gradient.addColorStop(1, opts.bottomColor);\n\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i].x, points[i].y);\n }\n // Close the fill path down to the bottom edge.\n ctx.lineTo(points[points.length - 1].x, bottomY);\n ctx.lineTo(points[0].x, bottomY);\n ctx.closePath();\n ctx.fillStyle = gradient;\n ctx.fill();\n\n // ── Line ─────────────────────────────────────────────────────────────\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n for (let i = 1; i < points.length; i++) {\n ctx.lineTo(points[i].x, points[i].y);\n }\n ctx.strokeStyle = opts.lineColor;\n ctx.lineWidth = opts.lineWidth * pr;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n ctx.stroke();\n\n ctx.restore();\n }\n}\n"],"mappings":"AASA,IAAM,EAAuC,CAC3C,UAAW,UACX,UAAW,EACX,SAAU,0BACV,YAAa,yBAOF,EAAb,kCAC0C,IAAK,GAE7C,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,OAAA,GACE,MAAO,IAAK,KAAK,UAGnB,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,EAAA,OAAI,GAAW,GAC3C,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAU,KAAK,MAAM,EAAS,GAG9B,EAA0C,GAChD,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IACpD,EAAO,KAAK,CACV,EAAG,KAAK,MAAM,EAAS,GAAK,GAC5B,EAAG,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,KAG7C,GAAsB,IAAlB,EAAO,OAAc,OAEzB,EAAI,OAGJ,MAAM,EAAO,EAAO,OAAA,CAAQ,EAAG,IAAM,KAAK,IAAI,EAAG,EAAE,GAAI,EAAO,GAAG,GAC3D,EAAW,EAAI,qBAAqB,EAAG,EAAM,EAAG,GACtD,EAAS,aAAa,EAAG,EAAK,UAC9B,EAAS,aAAa,EAAG,EAAK,aAE9B,EAAI,YACJ,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAClC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IACjC,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAGpC,EAAI,OAAO,EAAO,EAAO,OAAS,GAAG,EAAG,GACxC,EAAI,OAAO,EAAO,GAAG,EAAG,GACxB,EAAI,YACJ,EAAI,UAAY,EAChB,EAAI,OAGJ,EAAI,YACJ,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAClC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IACjC,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAEpC,EAAI,YAAc,EAAK,UACvB,EAAI,UAAY,EAAK,UAAY,EACjC,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAChB,EAAI,SAEJ,EAAI"}
|
package/dist/index45.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"#22AB94",downColor:"#F7525F",lineWidth:1},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,n,e,r,i){const{context:h,pixelRatio:s}=o,{fromIdx:a,toIdx:l}=n;if(a>=l||0===t.length)return;const d=this._options,p=Math.max(2,Math.round(i*s/2)),u=Math.max(1,Math.round(d.lineWidth*s));h.save(),h.lineWidth=u;for(let c=a;c<=l&&c<t.length;c++){const o=t.open[c],n=t.close[c],i=t.high[c],a=t.low[c];h.strokeStyle=n>=o?d.upColor:d.downColor;const l=Math.round(e(c)*s),u=Math.round(r(o)*s),M=Math.round(r(n)*s),x=Math.round(r(i)*s),g=Math.round(r(a)*s);h.beginPath(),h.moveTo(l,x),h.lineTo(l,g),h.stroke(),h.beginPath(),h.moveTo(l-p,u),h.lineTo(l,u),h.stroke(),h.beginPath(),h.moveTo(l,M),h.lineTo(l+p,M),h.stroke()}h.restore()}};export{t as BarOHLCRenderer};
|
|
2
|
+
//# sourceMappingURL=index45.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index45.js","names":[],"sources":["../src/renderers/bar-ohlc.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface BarOHLCRendererOptions {\n upColor: string;\n downColor: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: BarOHLCRendererOptions = {\n upColor: '#22AB94',\n downColor: '#F7525F',\n lineWidth: 1,\n};\n\n/**\n * BarOHLCRenderer — draws traditional OHLC bar charts:\n * - Vertical line from high to low\n * - Left horizontal tick for open\n * - Right horizontal tick for close\n */\nexport class BarOHLCRenderer {\n private _options: BarOHLCRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<BarOHLCRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const tickLen = Math.max(2, Math.round((barWidth * pr) / 2));\n const lw = Math.max(1, Math.round(opts.lineWidth * pr));\n\n ctx.save();\n ctx.lineWidth = lw;\n\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const open = store.open[i];\n const close = store.close[i];\n const high = store.high[i];\n const low = store.low[i];\n const isUp = close >= open;\n\n ctx.strokeStyle = isUp ? opts.upColor : opts.downColor;\n\n const cx = Math.round(indexToX(i) * pr);\n const openY = Math.round(priceToY(open) * pr);\n const closeY = Math.round(priceToY(close) * pr);\n const highY = Math.round(priceToY(high) * pr);\n const lowY = Math.round(priceToY(low) * pr);\n\n // Vertical high-low line.\n ctx.beginPath();\n ctx.moveTo(cx, highY);\n ctx.lineTo(cx, lowY);\n ctx.stroke();\n\n // Left open tick.\n ctx.beginPath();\n ctx.moveTo(cx - tickLen, openY);\n ctx.lineTo(cx, openY);\n ctx.stroke();\n\n // Right close tick.\n ctx.beginPath();\n ctx.moveTo(cx, closeY);\n ctx.lineTo(cx + tickLen, closeY);\n ctx.stroke();\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAQA,IAAM,EAA0C,CAC9C,QAAS,UACT,UAAW,UACX,UAAW,GASA,EAAb,kCAC6C,IAAK,GAEhD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAU,KAAK,IAAI,EAAG,KAAK,MAAO,EAAW,EAAM,IACnD,EAAK,KAAK,IAAI,EAAG,KAAK,MAAM,EAAK,UAAY,IAEnD,EAAI,OACJ,EAAI,UAAY,EAEhB,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAO,EAAM,KAAK,GAClB,EAAQ,EAAM,MAAM,GACpB,EAAO,EAAM,KAAK,GAClB,EAAM,EAAM,IAAI,GAGtB,EAAI,YAFS,GAAS,EAEG,EAAK,QAAU,EAAK,UAE7C,MAAM,EAAK,KAAK,MAAM,EAAS,GAAK,GAC9B,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAS,KAAK,MAAM,EAAS,GAAS,GACtC,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAO,KAAK,MAAM,EAAS,GAAO,GAGxC,EAAI,YACJ,EAAI,OAAO,EAAI,GACf,EAAI,OAAO,EAAI,GACf,EAAI,SAGJ,EAAI,YACJ,EAAI,OAAO,EAAK,EAAS,GACzB,EAAI,OAAO,EAAI,GACf,EAAI,SAGJ,EAAI,YACJ,EAAI,OAAO,EAAI,GACf,EAAI,OAAO,EAAK,EAAS,GACzB,EAAI,SAGN,EAAI"}
|
package/dist/index46.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={basePrice:0,topLineColor:"#22AB94",topFillColor:"rgba(34, 171, 148, 0.28)",bottomLineColor:"#F7525F",bottomFillColor:"rgba(247, 82, 95, 0.28)",lineWidth:2},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,e,i,l){const{context:n,pixelRatio:r,width:h}=o,{fromIdx:s,toIdx:a}=e;if(s>=a||0===t.length)return;const c=this._options,p=Math.round(l(c.basePrice)*r),d=Math.max(1,c.lineWidth*r),g=[];for(let u=s;u<=a&&u<t.length;u++)g.push({x:Math.round(i(u)*r),y:Math.round(l(t.close[u])*r)});if(0===g.length)return;n.save();const x=(t,e)=>{n.save(),n.beginPath(),e?n.rect(0,0,h*r,p):n.rect(0,p,h*r,o.height*r-p),n.clip(),n.beginPath(),n.moveTo(g[0].x,g[0].y);for(let o=1;o<g.length;o++)n.lineTo(g[o].x,g[o].y);n.lineTo(g[g.length-1].x,p),n.lineTo(g[0].x,p),n.closePath(),n.fillStyle=t,n.fill(),n.restore()};x(c.topFillColor,!0),x(c.bottomFillColor,!1);const b=(t,e)=>{n.save(),n.beginPath(),e?n.rect(0,0,h*r,p):n.rect(0,p,h*r,o.height*r-p),n.clip(),n.beginPath(),n.moveTo(g[0].x,g[0].y);for(let o=1;o<g.length;o++)n.lineTo(g[o].x,g[o].y);n.strokeStyle=t,n.lineWidth=d,n.lineJoin="round",n.lineCap="round",n.setLineDash([]),n.stroke(),n.restore()};b(c.topLineColor,!0),b(c.bottomLineColor,!1),n.beginPath(),n.moveTo(0,p),n.lineTo(Math.round(h*r),p),n.strokeStyle=c.topLineColor,n.lineWidth=Math.max(1,Math.round(r)),n.setLineDash([4*r,4*r]),n.stroke(),n.restore()}};export{t as BaselineRenderer};
|
|
2
|
+
//# sourceMappingURL=index46.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index46.js","names":[],"sources":["../src/renderers/baseline.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface BaselineRendererOptions {\n basePrice: number;\n topLineColor: string;\n topFillColor: string;\n bottomLineColor: string;\n bottomFillColor: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: BaselineRendererOptions = {\n basePrice: 0,\n topLineColor: '#22AB94',\n topFillColor: 'rgba(34, 171, 148, 0.28)',\n bottomLineColor: '#F7525F',\n bottomFillColor: 'rgba(247, 82, 95, 0.28)',\n lineWidth: 2,\n};\n\n/**\n * BaselineRenderer — draws a close-price line coloured above/below a base price,\n * fills each region with a semi-transparent colour, and renders a dashed\n * horizontal baseline.\n */\nexport class BaselineRenderer {\n private _options: BaselineRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<BaselineRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr, width } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const baselineY = Math.round(priceToY(opts.basePrice) * pr);\n const lw = Math.max(1, opts.lineWidth * pr);\n\n // Build pixel-level point array.\n const points: Array<{ x: number; y: number }> = [];\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n points.push({\n x: Math.round(indexToX(i) * pr),\n y: Math.round(priceToY(store.close[i]) * pr),\n });\n }\n if (points.length === 0) return;\n\n ctx.save();\n\n // ── Helper to clip fill to above or below the baseline ───────────────\n\n const drawFill = (color: string, above: boolean): void => {\n ctx.save();\n ctx.beginPath();\n if (above) {\n ctx.rect(0, 0, width * pr, baselineY);\n } else {\n ctx.rect(0, baselineY, width * pr, target.height * pr - baselineY);\n }\n ctx.clip();\n\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n for (let k = 1; k < points.length; k++) ctx.lineTo(points[k].x, points[k].y);\n ctx.lineTo(points[points.length - 1].x, baselineY);\n ctx.lineTo(points[0].x, baselineY);\n ctx.closePath();\n ctx.fillStyle = color;\n ctx.fill();\n ctx.restore();\n };\n\n drawFill(opts.topFillColor, true);\n drawFill(opts.bottomFillColor, false);\n\n // ── Helper to clip the line stroke to above or below baseline ────────\n\n const drawLine = (color: string, above: boolean): void => {\n ctx.save();\n ctx.beginPath();\n if (above) {\n ctx.rect(0, 0, width * pr, baselineY);\n } else {\n ctx.rect(0, baselineY, width * pr, target.height * pr - baselineY);\n }\n ctx.clip();\n\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n for (let k = 1; k < points.length; k++) ctx.lineTo(points[k].x, points[k].y);\n ctx.strokeStyle = color;\n ctx.lineWidth = lw;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n ctx.stroke();\n ctx.restore();\n };\n\n drawLine(opts.topLineColor, true);\n drawLine(opts.bottomLineColor, false);\n\n // ── Dashed baseline ───────────────────────────────────────────────────\n ctx.beginPath();\n ctx.moveTo(0, baselineY);\n ctx.lineTo(Math.round(width * pr), baselineY);\n ctx.strokeStyle = opts.topLineColor;\n ctx.lineWidth = Math.max(1, Math.round(pr));\n ctx.setLineDash([4 * pr, 4 * pr]);\n ctx.stroke();\n\n ctx.restore();\n }\n}\n"],"mappings":"AAWA,IAAM,EAA2C,CAC/C,UAAW,EACX,aAAc,UACd,aAAc,2BACd,gBAAiB,UACjB,gBAAiB,0BACjB,UAAW,GAQA,EAAb,kCAC8C,IAAK,GAEjD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,EAAA,MAAI,GAAU,GAC1C,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAY,KAAK,MAAM,EAAS,EAAK,WAAa,GAClD,EAAK,KAAK,IAAI,EAAG,EAAK,UAAY,GAGlC,EAA0C,GAChD,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IACpD,EAAO,KAAK,CACV,EAAG,KAAK,MAAM,EAAS,GAAK,GAC5B,EAAG,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,KAG7C,GAAsB,IAAlB,EAAO,OAAc,OAEzB,EAAI,OAIJ,MAAM,EAAA,CAAY,EAAe,KAC/B,EAAI,OACJ,EAAI,YACA,EACF,EAAI,KAAK,EAAG,EAAG,EAAQ,EAAI,GAE3B,EAAI,KAAK,EAAG,EAAW,EAAQ,EAAI,EAAO,OAAS,EAAK,GAE1D,EAAI,OAEJ,EAAI,YACJ,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAClC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAAK,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAC1E,EAAI,OAAO,EAAO,EAAO,OAAS,GAAG,EAAG,GACxC,EAAI,OAAO,EAAO,GAAG,EAAG,GACxB,EAAI,YACJ,EAAI,UAAY,EAChB,EAAI,OACJ,EAAI,WAGN,EAAS,EAAK,cAAc,GAC5B,EAAS,EAAK,iBAAiB,GAI/B,MAAM,EAAA,CAAY,EAAe,KAC/B,EAAI,OACJ,EAAI,YACA,EACF,EAAI,KAAK,EAAG,EAAG,EAAQ,EAAI,GAE3B,EAAI,KAAK,EAAG,EAAW,EAAQ,EAAI,EAAO,OAAS,EAAK,GAE1D,EAAI,OAEJ,EAAI,YACJ,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAClC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAAK,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAC1E,EAAI,YAAc,EAClB,EAAI,UAAY,EAChB,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAChB,EAAI,SACJ,EAAI,WAGN,EAAS,EAAK,cAAc,GAC5B,EAAS,EAAK,iBAAiB,GAG/B,EAAI,YACJ,EAAI,OAAO,EAAG,GACd,EAAI,OAAO,KAAK,MAAM,EAAQ,GAAK,GACnC,EAAI,YAAc,EAAK,aACvB,EAAI,UAAY,KAAK,IAAI,EAAG,KAAK,MAAM,IACvC,EAAI,YAAY,CAAC,EAAI,EAAI,EAAI,IAC7B,EAAI,SAEJ,EAAI"}
|
package/dist/index47.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"#22AB94",downColor:"#F7525F",wickColor:"#737375"},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,r,l,a,n){const{context:h,pixelRatio:i}=o,{fromIdx:e,toIdx:s}=r;if(e>=s||0===t.length)return;const M=this._options,d=Math.max(1,Math.round(n*i/2)),c=Math.max(1,Math.round(i)),p=Math.max(1,Math.round(i));h.save();for(let u=e;u<=s&&u<t.length;u++){const o=t.open[u],r=t.close[u],n=t.high[u],e=t.low[u],s=r>=o,x=s?M.upColor:M.downColor,f=Math.round(l(u)*i),m=Math.round(a(o)*i),w=Math.round(a(r)*i),C=Math.round(a(n)*i),k=Math.round(a(e)*i),y=Math.min(m,w),R=Math.max(1,Math.max(m,w)-y);h.fillStyle=M.wickColor,h.fillRect(f-Math.floor(c/2),C,c,k-C),s?(h.strokeStyle=x,h.lineWidth=p,h.strokeRect(f-d+p/2,y+p/2,2*d-p,R-p)):(h.fillStyle=x,h.fillRect(f-d,y,2*d,R))}h.restore()}};export{t as HollowCandleRenderer};
|
|
2
|
+
//# sourceMappingURL=index47.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index47.js","names":[],"sources":["../src/renderers/hollow-candle.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface HollowCandleRendererOptions {\n upColor: string;\n downColor: string;\n wickColor: string;\n}\n\nconst DEFAULT_OPTIONS: HollowCandleRendererOptions = {\n upColor: '#22AB94',\n downColor: '#F7525F',\n wickColor: '#737375',\n};\n\n/**\n * HollowCandleRenderer — draws candles where:\n * - Up candles (close >= open) are hollow: only the border is drawn (stroke).\n * - Down candles are filled.\n *\n * The wick is always drawn as a thin filled rectangle.\n */\nexport class HollowCandleRenderer {\n private _options: HollowCandleRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<HollowCandleRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const halfBody = Math.max(1, Math.round((barWidth * pr) / 2));\n const wickWidth = Math.max(1, Math.round(pr));\n const borderWidth = Math.max(1, Math.round(pr));\n\n ctx.save();\n\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const open = store.open[i];\n const close = store.close[i];\n const high = store.high[i];\n const low = store.low[i];\n const isUp = close >= open;\n\n const color = isUp ? opts.upColor : opts.downColor;\n\n const cx = Math.round(indexToX(i) * pr);\n const openY = Math.round(priceToY(open) * pr);\n const closeY = Math.round(priceToY(close) * pr);\n const highY = Math.round(priceToY(high) * pr);\n const lowY = Math.round(priceToY(low) * pr);\n\n const bodyTop = Math.min(openY, closeY);\n const bodyBottom = Math.max(openY, closeY);\n const bodyHeight = Math.max(1, bodyBottom - bodyTop);\n\n // ── Wick ──────────────────────────────────────────────────────────────\n ctx.fillStyle = opts.wickColor;\n ctx.fillRect(cx - Math.floor(wickWidth / 2), highY, wickWidth, lowY - highY);\n\n if (isUp) {\n // Hollow: stroke only.\n ctx.strokeStyle = color;\n ctx.lineWidth = borderWidth;\n ctx.strokeRect(\n cx - halfBody + borderWidth / 2,\n bodyTop + borderWidth / 2,\n halfBody * 2 - borderWidth,\n bodyHeight - borderWidth,\n );\n } else {\n // Filled.\n ctx.fillStyle = color;\n ctx.fillRect(cx - halfBody, bodyTop, halfBody * 2, bodyHeight);\n }\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAQA,IAAM,EAA+C,CACnD,QAAS,UACT,UAAW,UACX,UAAW,WAUA,EAAb,kCACkD,IAAK,GAErD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAW,KAAK,IAAI,EAAG,KAAK,MAAO,EAAW,EAAM,IACpD,EAAY,KAAK,IAAI,EAAG,KAAK,MAAM,IACnC,EAAc,KAAK,IAAI,EAAG,KAAK,MAAM,IAE3C,EAAI,OAEJ,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAO,EAAM,KAAK,GAClB,EAAQ,EAAM,MAAM,GACpB,EAAO,EAAM,KAAK,GAClB,EAAM,EAAM,IAAI,GAChB,EAAO,GAAS,EAEhB,EAAQ,EAAO,EAAK,QAAU,EAAK,UAEnC,EAAK,KAAK,MAAM,EAAS,GAAK,GAC9B,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAS,KAAK,MAAM,EAAS,GAAS,GACtC,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAO,KAAK,MAAM,EAAS,GAAO,GAElC,EAAU,KAAK,IAAI,EAAO,GAE1B,EAAa,KAAK,IAAI,EADT,KAAK,IAAI,EAAO,GACS,GAG5C,EAAI,UAAY,EAAK,UACrB,EAAI,SAAS,EAAK,KAAK,MAAM,EAAY,GAAI,EAAO,EAAW,EAAO,GAElE,GAEF,EAAI,YAAc,EAClB,EAAI,UAAY,EAChB,EAAI,WACF,EAAK,EAAW,EAAc,EAC9B,EAAU,EAAc,EACb,EAAX,EAAe,EACf,EAAa,KAIf,EAAI,UAAY,EAChB,EAAI,SAAS,EAAK,EAAU,EAAoB,EAAX,EAAc,IAIvD,EAAI"}
|
package/dist/index48.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"rgba(34, 171, 148, 0.5)",downColor:"rgba(247, 82, 95, 0.5)"},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,n,r,s,a){const{context:l,pixelRatio:e,height:i}=o,{fromIdx:h,toIdx:p}=n;if(h>=p||0===t.length)return;const c=this._options,d=Math.max(1,Math.round(a*e/2)),u=Math.round(i*e);l.save();for(let x=h;x<=p&&x<t.length;x++){const o=t.close[x];l.fillStyle=o>=t.open[x]?c.upColor:c.downColor;const n=Math.round(r(x)*e),a=Math.round(s(o)*e),i=Math.max(1,u-a);l.fillRect(n-d,a,2*d,i)}l.restore()}};export{t as HistogramRenderer};
|
|
2
|
+
//# sourceMappingURL=index48.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index48.js","names":[],"sources":["../src/renderers/histogram.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface HistogramRendererOptions {\n upColor: string;\n downColor: string;\n}\n\nconst DEFAULT_OPTIONS: HistogramRendererOptions = {\n upColor: 'rgba(34, 171, 148, 0.5)',\n downColor: 'rgba(247, 82, 95, 0.5)',\n};\n\n/**\n * HistogramRenderer — draws vertical bars from the bottom of the pane,\n * coloured by whether close >= open (up) or close < open (down).\n *\n * Typical use-case: volume histogram overlay.\n */\nexport class HistogramRenderer {\n private _options: HistogramRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<HistogramRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr, height } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const halfBar = Math.max(1, Math.round((barWidth * pr) / 2));\n const bottomY = Math.round(height * pr);\n\n ctx.save();\n\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const close = store.close[i];\n const open = store.open[i];\n const isUp = close >= open;\n\n ctx.fillStyle = isUp ? opts.upColor : opts.downColor;\n\n const cx = Math.round(indexToX(i) * pr);\n const topY = Math.round(priceToY(close) * pr);\n const barH = Math.max(1, bottomY - topY);\n\n ctx.fillRect(cx - halfBar, topY, halfBar * 2, barH);\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAOA,IAAM,EAA4C,CAChD,QAAS,0BACT,UAAW,0BASA,EAAb,kCAC+C,IAAK,GAElD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,EAAA,OAAI,GAAW,GAC3C,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAU,KAAK,IAAI,EAAG,KAAK,MAAO,EAAW,EAAM,IACnD,EAAU,KAAK,MAAM,EAAS,GAEpC,EAAI,OAEJ,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAQ,EAAM,MAAM,GAI1B,EAAI,UAFS,GADA,EAAM,KAAK,GAGD,EAAK,QAAU,EAAK,UAE3C,MAAM,EAAK,KAAK,MAAM,EAAS,GAAK,GAC9B,EAAO,KAAK,MAAM,EAAS,GAAS,GACpC,EAAO,KAAK,IAAI,EAAG,EAAU,GAEnC,EAAI,SAAS,EAAK,EAAS,EAAgB,EAAV,EAAa,GAGhD,EAAI"}
|
package/dist/index49.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={color:"#2196F3",lineWidth:2},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,n,e,i){const{context:s,pixelRatio:r}=o,{fromIdx:l,toIdx:h}=n;if(l>=h||0===t.length)return;const{color:a,lineWidth:c}=this._options;s.save(),s.strokeStyle=a,s.lineWidth=c*r,s.lineJoin="round",s.lineCap="round",s.setLineDash([]),s.beginPath();let d=!1;for(let p=l;p<=h&&p<t.length;p++){const o=Math.round(e(p)*r),n=Math.round(i(t.close[p])*r);d?(s.lineTo(o,Math.round(i(t.close[p-1])*r)),s.lineTo(o,n)):(s.moveTo(o,n),d=!0)}s.stroke(),s.restore()}};export{t as StepLineRenderer};
|
|
2
|
+
//# sourceMappingURL=index49.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index49.js","names":[],"sources":["../src/renderers/step-line.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface StepLineRendererOptions {\n color: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: StepLineRendererOptions = {\n color: '#2196F3',\n lineWidth: 2,\n};\n\n/**\n * StepLineRenderer — draws a close-price step line (horizontal-then-vertical)\n * over the visible bar range.\n */\nexport class StepLineRenderer {\n private _options: StepLineRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<StepLineRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const { color, lineWidth } = this._options;\n\n ctx.save();\n ctx.strokeStyle = color;\n ctx.lineWidth = lineWidth * pr;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n\n ctx.beginPath();\n\n let started = false;\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const x = Math.round(indexToX(i) * pr);\n const y = Math.round(priceToY(store.close[i]) * pr);\n if (!started) {\n ctx.moveTo(x, y);\n started = true;\n } else {\n // Horizontal to new X at previous Y, then vertical to new Y.\n ctx.lineTo(x, Math.round(priceToY(store.close[i - 1]) * pr));\n ctx.lineTo(x, y);\n }\n }\n\n ctx.stroke();\n ctx.restore();\n }\n}\n"],"mappings":"AAOA,IAAM,EAA2C,CAC/C,MAAO,UACP,UAAW,GAOA,EAAb,kCAC8C,IAAK,GAEjD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,MAAE,EAAA,UAAO,GAAc,KAAK,SAElC,EAAI,OACJ,EAAI,YAAc,EAClB,EAAI,UAAY,EAAY,EAC5B,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAEhB,EAAI,YAEJ,IAAI,GAAU,EACd,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAI,KAAK,MAAM,EAAS,GAAK,GAC7B,EAAI,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,GAC3C,GAKH,EAAI,OAAO,EAAG,KAAK,MAAM,EAAS,EAAM,MAAM,EAAI,IAAM,IACxD,EAAI,OAAO,EAAG,KALd,EAAI,OAAO,EAAG,GACd,GAAU,GAQd,EAAI,SACJ,EAAI"}
|
package/dist/index5.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{InvalidationLevel as e}from"./index2.js";var s=class{constructor(){this._levels=/* @__PURE__ */new Map}addPane(s){this._levels.has(s)||this._levels.set(s,e.None)}removePane(e){this._levels.delete(e)}invalidate(s,t){const l=this._levels.get(s)??e.None;this._levels.set(s,Math.max(l,t))}invalidateAll(e){for(const s of this._levels.keys())this.invalidate(s,e)}level(s){return this._levels.get(s)??e.None}needsRepaint(){for(const s of this._levels.values())if(s>e.None)return!0;return!1}paneIds(){return Array.from(this._levels.keys())}reset(){for(const s of this._levels.keys())this._levels.set(s,e.None)}};export{s as InvalidateMask};
|
|
2
|
+
//# sourceMappingURL=index5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index5.js","names":[],"sources":["../src/core/invalidation.ts"],"sourcesContent":["import { InvalidationLevel, type InvalidationLevelValue } from './types';\n\nexport class InvalidateMask {\n /** Map from pane id → highest invalidation level for that pane. */\n private _levels = new Map<string, InvalidationLevelValue>();\n\n /** Register a pane (starts at None). */\n addPane(id: string): void {\n if (!this._levels.has(id)) {\n this._levels.set(id, InvalidationLevel.None);\n }\n }\n\n /** Remove a pane from tracking. */\n removePane(id: string): void {\n this._levels.delete(id);\n }\n\n /**\n * Set the invalidation level for a pane.\n * Keeps whichever value is higher (existing vs. requested).\n */\n invalidate(paneId: string, level: InvalidationLevelValue): void {\n const current = this._levels.get(paneId) ?? InvalidationLevel.None;\n this._levels.set(paneId, Math.max(current, level) as InvalidationLevelValue);\n }\n\n /** Apply `level` to every tracked pane. */\n invalidateAll(level: InvalidationLevelValue): void {\n for (const id of this._levels.keys()) {\n this.invalidate(id, level);\n }\n }\n\n /** Return the current invalidation level for a pane. */\n level(paneId: string): InvalidationLevelValue {\n return this._levels.get(paneId) ?? InvalidationLevel.None;\n }\n\n /** True if at least one pane has a level above None. */\n needsRepaint(): boolean {\n for (const lvl of this._levels.values()) {\n if (lvl > InvalidationLevel.None) return true;\n }\n return false;\n }\n\n /** Return all tracked pane ids. */\n paneIds(): string[] {\n return Array.from(this._levels.keys());\n }\n\n /** Reset all pane levels back to None. */\n reset(): void {\n for (const id of this._levels.keys()) {\n this._levels.set(id, InvalidationLevel.None);\n }\n }\n}\n"],"mappings":"gDAEA,IAAa,EAAb,gDAEoB,IAAI,IAGtB,OAAA,CAAQ,GACD,KAAK,QAAQ,IAAI,IACpB,KAAK,QAAQ,IAAI,EAAI,EAAkB,MAK3C,UAAA,CAAW,GACT,KAAK,QAAQ,OAAO,GAOtB,UAAA,CAAW,EAAgB,GACzB,MAAM,EAAU,KAAK,QAAQ,IAAI,IAAW,EAAkB,KAC9D,KAAK,QAAQ,IAAI,EAAQ,KAAK,IAAI,EAAS,IAI7C,aAAA,CAAc,GACZ,IAAK,MAAM,KAAM,KAAK,QAAQ,OAC5B,KAAK,WAAW,EAAI,GAKxB,KAAA,CAAM,GACJ,OAAO,KAAK,QAAQ,IAAI,IAAW,EAAkB,KAIvD,YAAA,GACE,IAAK,MAAM,KAAO,KAAK,QAAQ,SAC7B,GAAI,EAAM,EAAkB,KAAM,OAAO,EAE3C,OAAO,EAIT,OAAA,GACE,OAAO,MAAM,KAAK,KAAK,QAAQ,QAIjC,KAAA,GACE,IAAK,MAAM,KAAM,KAAK,QAAQ,OAC5B,KAAK,QAAQ,IAAI,EAAI,EAAkB"}
|
package/dist/index50.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"#22AB94",downColor:"#F7525F",lineWidth:2},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,n,e,s){const{context:i,pixelRatio:r}=o,{fromIdx:l,toIdx:h}=n;if(l>=h||0===t.length)return;const{upColor:a,downColor:d,lineWidth:p}=this._options,c=p*r;i.save(),i.lineWidth=c,i.lineJoin="round",i.lineCap="round",i.setLineDash([]);for(let u=Math.max(l,1);u<=h&&u<t.length;u++){const o=Math.round(e(u-1)*r),n=Math.round(s(t.close[u-1])*r),l=Math.round(e(u)*r),h=Math.round(s(t.close[u])*r);i.beginPath(),i.moveTo(o,n),i.lineTo(l,h),i.strokeStyle=t.close[u]>=t.close[u-1]?a:d,i.stroke()}i.restore()}};export{t as ColoredLineRenderer};
|
|
2
|
+
//# sourceMappingURL=index50.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index50.js","names":[],"sources":["../src/renderers/colored-line.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface ColoredLineRendererOptions {\n upColor: string;\n downColor: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: ColoredLineRendererOptions = {\n upColor: '#22AB94',\n downColor: '#F7525F',\n lineWidth: 2,\n};\n\n/**\n * ColoredLineRenderer — draws a close-price polyline where each segment is\n * coloured green (upColor) when price rises and red (downColor) when it falls.\n */\nexport class ColoredLineRenderer {\n private _options: ColoredLineRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<ColoredLineRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const { upColor, downColor, lineWidth } = this._options;\n const lw = lineWidth * pr;\n\n ctx.save();\n ctx.lineWidth = lw;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n\n for (let i = Math.max(fromIdx, 1); i <= toIdx && i < store.length; i++) {\n const x0 = Math.round(indexToX(i - 1) * pr);\n const y0 = Math.round(priceToY(store.close[i - 1]) * pr);\n const x1 = Math.round(indexToX(i) * pr);\n const y1 = Math.round(priceToY(store.close[i]) * pr);\n\n ctx.beginPath();\n ctx.moveTo(x0, y0);\n ctx.lineTo(x1, y1);\n ctx.strokeStyle = store.close[i] >= store.close[i - 1] ? upColor : downColor;\n ctx.stroke();\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAQA,IAAM,EAA8C,CAClD,QAAS,UACT,UAAW,UACX,UAAW,GAOA,EAAb,kCACiD,IAAK,GAEpD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,QAAE,EAAA,UAAS,EAAA,UAAW,GAAc,KAAK,SACzC,EAAK,EAAY,EAEvB,EAAI,OACJ,EAAI,UAAY,EAChB,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAEhB,IAAK,IAAI,EAAI,KAAK,IAAI,EAAS,GAAI,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACtE,MAAM,EAAK,KAAK,MAAM,EAAS,EAAI,GAAK,GAClC,EAAK,KAAK,MAAM,EAAS,EAAM,MAAM,EAAI,IAAM,GAC/C,EAAK,KAAK,MAAM,EAAS,GAAK,GAC9B,EAAK,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,GAEjD,EAAI,YACJ,EAAI,OAAO,EAAI,GACf,EAAI,OAAO,EAAI,GACf,EAAI,YAAc,EAAM,MAAM,IAAM,EAAM,MAAM,EAAI,GAAK,EAAU,EACnE,EAAI,SAGN,EAAI"}
|
package/dist/index51.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"#22AB94",downColor:"#F7525F",upFillColor:"rgba(34, 171, 148, 0.28)",downFillColor:"rgba(247, 82, 95, 0.28)",lineWidth:2},l=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,l,t,n,e){const{context:i,pixelRatio:r,height:s}=o,{fromIdx:h,toIdx:a}=t;if(h>=a||0===l.length)return;const d=this._options,p=d.lineWidth*r,u=Math.round(s*r);i.save(),i.lineWidth=p,i.lineJoin="round",i.lineCap="round",i.setLineDash([]);for(let c=Math.max(h,1);c<=a&&c<l.length;c++){const o=Math.round(n(c-1)*r),t=Math.round(e(l.close[c-1])*r),s=Math.round(n(c)*r),h=Math.round(e(l.close[c])*r),a=l.close[c]>=l.close[c-1],p=a?d.upFillColor:d.downFillColor,C=a?d.upColor:d.downColor;i.beginPath(),i.moveTo(o,t),i.lineTo(s,h),i.lineTo(s,u),i.lineTo(o,u),i.closePath(),i.fillStyle=p,i.fill(),i.beginPath(),i.moveTo(o,t),i.lineTo(s,h),i.strokeStyle=C,i.stroke()}i.restore()}};export{l as ColoredMountainRenderer};
|
|
2
|
+
//# sourceMappingURL=index51.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index51.js","names":[],"sources":["../src/renderers/colored-mountain.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface ColoredMountainRendererOptions {\n upColor: string;\n downColor: string;\n upFillColor: string;\n downFillColor: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: ColoredMountainRendererOptions = {\n upColor: '#22AB94',\n downColor: '#F7525F',\n upFillColor: 'rgba(34, 171, 148, 0.28)',\n downFillColor: 'rgba(247, 82, 95, 0.28)',\n lineWidth: 2,\n};\n\n/**\n * ColoredMountainRenderer — like AreaRenderer but the line and fill are coloured\n * per-segment based on close-price direction. Up segments use upColor/upFillColor,\n * down segments use downColor/downFillColor.\n */\nexport class ColoredMountainRenderer {\n private _options: ColoredMountainRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<ColoredMountainRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr, height } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const lw = opts.lineWidth * pr;\n const bottomY = Math.round(height * pr);\n\n ctx.save();\n ctx.lineWidth = lw;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n\n for (let i = Math.max(fromIdx, 1); i <= toIdx && i < store.length; i++) {\n const x0 = Math.round(indexToX(i - 1) * pr);\n const y0 = Math.round(priceToY(store.close[i - 1]) * pr);\n const x1 = Math.round(indexToX(i) * pr);\n const y1 = Math.round(priceToY(store.close[i]) * pr);\n\n const isUp = store.close[i] >= store.close[i - 1];\n const fillColor = isUp ? opts.upFillColor : opts.downFillColor;\n const lineColor = isUp ? opts.upColor : opts.downColor;\n\n // Fill between the segment and the chart bottom.\n ctx.beginPath();\n ctx.moveTo(x0, y0);\n ctx.lineTo(x1, y1);\n ctx.lineTo(x1, bottomY);\n ctx.lineTo(x0, bottomY);\n ctx.closePath();\n ctx.fillStyle = fillColor;\n ctx.fill();\n\n // Stroke the line segment.\n ctx.beginPath();\n ctx.moveTo(x0, y0);\n ctx.lineTo(x1, y1);\n ctx.strokeStyle = lineColor;\n ctx.stroke();\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAUA,IAAM,EAAkD,CACtD,QAAS,UACT,UAAW,UACX,YAAa,2BACb,cAAe,0BACf,UAAW,GAQA,EAAb,kCACqD,IAAK,GAExD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,EAAA,OAAI,GAAW,GAC3C,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAK,EAAK,UAAY,EACtB,EAAU,KAAK,MAAM,EAAS,GAEpC,EAAI,OACJ,EAAI,UAAY,EAChB,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAEhB,IAAK,IAAI,EAAI,KAAK,IAAI,EAAS,GAAI,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACtE,MAAM,EAAK,KAAK,MAAM,EAAS,EAAI,GAAK,GAClC,EAAK,KAAK,MAAM,EAAS,EAAM,MAAM,EAAI,IAAM,GAC/C,EAAK,KAAK,MAAM,EAAS,GAAK,GAC9B,EAAK,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,GAE3C,EAAO,EAAM,MAAM,IAAM,EAAM,MAAM,EAAI,GACzC,EAAY,EAAO,EAAK,YAAc,EAAK,cAC3C,EAAY,EAAO,EAAK,QAAU,EAAK,UAG7C,EAAI,YACJ,EAAI,OAAO,EAAI,GACf,EAAI,OAAO,EAAI,GACf,EAAI,OAAO,EAAI,GACf,EAAI,OAAO,EAAI,GACf,EAAI,YACJ,EAAI,UAAY,EAChB,EAAI,OAGJ,EAAI,YACJ,EAAI,OAAO,EAAI,GACf,EAAI,OAAO,EAAI,GACf,EAAI,YAAc,EAClB,EAAI,SAGN,EAAI"}
|
package/dist/index52.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={highLineColor:"#22AB94",lowLineColor:"#F7525F",fillColor:"rgba(33, 150, 243, 0.2)",lineWidth:2},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,e,l,i){const{context:n,pixelRatio:h}=o,{fromIdx:r,toIdx:s}=e;if(r>=s||0===t.length)return;const a=this._options,g=a.lineWidth*h,x=[],y=[];for(let d=r;d<=s&&d<t.length;d++){const o=Math.round(l(d)*h);x.push({x:o,y:Math.round(i(t.high[d])*h)}),y.push({x:o,y:Math.round(i(t.low[d])*h)})}if(0!==x.length){n.save(),n.beginPath(),n.moveTo(x[0].x,x[0].y);for(let o=1;o<x.length;o++)n.lineTo(x[o].x,x[o].y);for(let o=y.length-1;o>=0;o--)n.lineTo(y[o].x,y[o].y);n.closePath(),n.fillStyle=a.fillColor,n.fill(),n.beginPath(),n.moveTo(x[0].x,x[0].y);for(let o=1;o<x.length;o++)n.lineTo(x[o].x,x[o].y);n.strokeStyle=a.highLineColor,n.lineWidth=g,n.lineJoin="round",n.lineCap="round",n.setLineDash([]),n.stroke(),n.beginPath(),n.moveTo(y[0].x,y[0].y);for(let o=1;o<y.length;o++)n.lineTo(y[o].x,y[o].y);n.strokeStyle=a.lowLineColor,n.lineWidth=g,n.stroke(),n.restore()}}};export{t as HLCAreaRenderer};
|
|
2
|
+
//# sourceMappingURL=index52.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index52.js","names":[],"sources":["../src/renderers/hlc-area.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface HLCAreaRendererOptions {\n highLineColor: string;\n lowLineColor: string;\n fillColor: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: HLCAreaRendererOptions = {\n highLineColor: '#22AB94',\n lowLineColor: '#F7525F',\n fillColor: 'rgba(33, 150, 243, 0.2)',\n lineWidth: 2,\n};\n\n/**\n * HLCAreaRenderer — draws two polylines (high and low prices) with a filled\n * area between them.\n */\nexport class HLCAreaRenderer {\n private _options: HLCAreaRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<HLCAreaRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const lw = opts.lineWidth * pr;\n\n // Build pixel-level point arrays for high and low.\n const highPts: Array<{ x: number; y: number }> = [];\n const lowPts: Array<{ x: number; y: number }> = [];\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const x = Math.round(indexToX(i) * pr);\n highPts.push({ x, y: Math.round(priceToY(store.high[i]) * pr) });\n lowPts.push({ x, y: Math.round(priceToY(store.low[i]) * pr) });\n }\n if (highPts.length === 0) return;\n\n ctx.save();\n\n // ── Filled area between high and low ─────────────────────────────────\n ctx.beginPath();\n ctx.moveTo(highPts[0].x, highPts[0].y);\n for (let i = 1; i < highPts.length; i++) {\n ctx.lineTo(highPts[i].x, highPts[i].y);\n }\n // Trace the low line in reverse to close the shape.\n for (let i = lowPts.length - 1; i >= 0; i--) {\n ctx.lineTo(lowPts[i].x, lowPts[i].y);\n }\n ctx.closePath();\n ctx.fillStyle = opts.fillColor;\n ctx.fill();\n\n // ── High line ────────────────────────────────────────────────────────\n ctx.beginPath();\n ctx.moveTo(highPts[0].x, highPts[0].y);\n for (let i = 1; i < highPts.length; i++) {\n ctx.lineTo(highPts[i].x, highPts[i].y);\n }\n ctx.strokeStyle = opts.highLineColor;\n ctx.lineWidth = lw;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n ctx.stroke();\n\n // ── Low line ─────────────────────────────────────────────────────────\n ctx.beginPath();\n ctx.moveTo(lowPts[0].x, lowPts[0].y);\n for (let i = 1; i < lowPts.length; i++) {\n ctx.lineTo(lowPts[i].x, lowPts[i].y);\n }\n ctx.strokeStyle = opts.lowLineColor;\n ctx.lineWidth = lw;\n ctx.stroke();\n\n ctx.restore();\n }\n}\n"],"mappings":"AASA,IAAM,EAA0C,CAC9C,cAAe,UACf,aAAc,UACd,UAAW,0BACX,UAAW,GAOA,EAAb,kCAC6C,IAAK,GAEhD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAK,EAAK,UAAY,EAGtB,EAA2C,GAC3C,EAA0C,GAChD,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAI,KAAK,MAAM,EAAS,GAAK,GACnC,EAAQ,KAAK,CAAE,IAAG,EAAG,KAAK,MAAM,EAAS,EAAM,KAAK,IAAM,KAC1D,EAAO,KAAK,CAAE,IAAG,EAAG,KAAK,MAAM,EAAS,EAAM,IAAI,IAAM,KAE1D,GAAuB,IAAnB,EAAQ,OAAZ,CAEA,EAAI,OAGJ,EAAI,YACJ,EAAI,OAAO,EAAQ,GAAG,EAAG,EAAQ,GAAG,GACpC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAQ,IAClC,EAAI,OAAO,EAAQ,GAAG,EAAG,EAAQ,GAAG,GAGtC,IAAK,IAAI,EAAI,EAAO,OAAS,EAAG,GAAK,EAAG,IACtC,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAEpC,EAAI,YACJ,EAAI,UAAY,EAAK,UACrB,EAAI,OAGJ,EAAI,YACJ,EAAI,OAAO,EAAQ,GAAG,EAAG,EAAQ,GAAG,GACpC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,OAAQ,IAClC,EAAI,OAAO,EAAQ,GAAG,EAAG,EAAQ,GAAG,GAEtC,EAAI,YAAc,EAAK,cACvB,EAAI,UAAY,EAChB,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAChB,EAAI,SAGJ,EAAI,YACJ,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAClC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IACjC,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAEpC,EAAI,YAAc,EAAK,aACvB,EAAI,UAAY,EAChB,EAAI,SAEJ,EAAI,SAzCsB"}
|
package/dist/index53.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var t={color:"#2196F3",lineWidth:1},o=class{constructor(){this._options={...t}}applyOptions(t){this._options={...this._options,...t}}draw(t,o,i,n,e){const{context:s,pixelRatio:r}=t,{fromIdx:h,toIdx:l}=i;if(h>=l||0===o.length)return;const{color:a,lineWidth:p}=this._options,c=p*r;s.save(),s.strokeStyle=a,s.lineWidth=c,s.lineCap="butt",s.setLineDash([]),s.beginPath();for(let d=h;d<=l&&d<o.length;d++){const t=Math.round(n(d)*r),i=Math.round(e(o.high[d])*r),h=Math.round(e(o.low[d])*r);s.moveTo(t,i),s.lineTo(t,h)}s.stroke(),s.restore()}};export{o as HighLowRenderer};
|
|
2
|
+
//# sourceMappingURL=index53.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index53.js","names":[],"sources":["../src/renderers/high-low.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface HighLowRendererOptions {\n color: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: HighLowRendererOptions = {\n color: '#2196F3',\n lineWidth: 1,\n};\n\n/**\n * HighLowRenderer — draws simple vertical lines from high to low for each bar,\n * without open/close tick marks.\n */\nexport class HighLowRenderer {\n private _options: HighLowRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<HighLowRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const { color, lineWidth } = this._options;\n const lw = lineWidth * pr;\n\n ctx.save();\n ctx.strokeStyle = color;\n ctx.lineWidth = lw;\n ctx.lineCap = 'butt';\n ctx.setLineDash([]);\n\n ctx.beginPath();\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const x = Math.round(indexToX(i) * pr);\n const yHigh = Math.round(priceToY(store.high[i]) * pr);\n const yLow = Math.round(priceToY(store.low[i]) * pr);\n ctx.moveTo(x, yHigh);\n ctx.lineTo(x, yLow);\n }\n ctx.stroke();\n\n ctx.restore();\n }\n}\n"],"mappings":"AAOA,IAAM,EAA0C,CAC9C,MAAO,UACP,UAAW,GAOA,EAAb,kCAC6C,IAAK,GAEhD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,MAAE,EAAA,UAAO,GAAc,KAAK,SAC5B,EAAK,EAAY,EAEvB,EAAI,OACJ,EAAI,YAAc,EAClB,EAAI,UAAY,EAChB,EAAI,QAAU,OACd,EAAI,YAAY,IAEhB,EAAI,YACJ,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAI,KAAK,MAAM,EAAS,GAAK,GAC7B,EAAQ,KAAK,MAAM,EAAS,EAAM,KAAK,IAAM,GAC7C,EAAO,KAAK,MAAM,EAAS,EAAM,IAAI,IAAM,GACjD,EAAI,OAAO,EAAG,GACd,EAAI,OAAO,EAAG,GAEhB,EAAI,SAEJ,EAAI"}
|
package/dist/index54.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"#22AB94",downColor:"#F7525F"},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,n,s,r,e){const{context:l,pixelRatio:i,height:h}=o,{fromIdx:a,toIdx:p}=n;if(a>=p||0===t.length)return;const{upColor:c,downColor:d}=this._options,u=Math.round(h*i),x=Math.max(1,Math.round((e??6)*i/2));l.save(),l.setLineDash([]);for(let f=a;f<=p&&f<t.length;f++){const o=Math.round(s(f)*i),n=Math.round(r(t.close[f])*i);l.fillStyle=t.close[f]>=t.open[f]?c:d,l.fillRect(o-x,n,2*x,u-n)}l.restore()}};export{t as ColumnRenderer};
|
|
2
|
+
//# sourceMappingURL=index54.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index54.js","names":[],"sources":["../src/renderers/column.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface ColumnRendererOptions {\n upColor: string;\n downColor: string;\n}\n\nconst DEFAULT_OPTIONS: ColumnRendererOptions = {\n upColor: '#22AB94',\n downColor: '#F7525F',\n};\n\n/**\n * ColumnRenderer — draws vertical bars from the chart bottom up to the close\n * price, coloured by whether close >= open.\n */\nexport class ColumnRenderer {\n private _options: ColumnRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<ColumnRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth?: number,\n ): void {\n const { context: ctx, pixelRatio: pr, height } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const { upColor, downColor } = this._options;\n const bottomY = Math.round(height * pr);\n const halfBar = Math.max(1, Math.round(((barWidth ?? 6) * pr) / 2));\n\n ctx.save();\n ctx.setLineDash([]);\n\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const x = Math.round(indexToX(i) * pr);\n const yClose = Math.round(priceToY(store.close[i]) * pr);\n const isUp = store.close[i] >= store.open[i];\n\n ctx.fillStyle = isUp ? upColor : downColor;\n ctx.fillRect(x - halfBar, yClose, halfBar * 2, bottomY - yClose);\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAOA,IAAM,EAAyC,CAC7C,QAAS,UACT,UAAW,WAOA,EAAb,kCAC4C,IAAK,GAE/C,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,EAAA,OAAI,GAAW,GAC3C,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,QAAE,EAAA,UAAS,GAAc,KAAK,SAC9B,EAAU,KAAK,MAAM,EAAS,GAC9B,EAAU,KAAK,IAAI,EAAG,KAAK,OAAQ,GAAY,GAAK,EAAM,IAEhE,EAAI,OACJ,EAAI,YAAY,IAEhB,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAI,KAAK,MAAM,EAAS,GAAK,GAC7B,EAAS,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,GAGrD,EAAI,UAFS,EAAM,MAAM,IAAM,EAAM,KAAK,GAEnB,EAAU,EACjC,EAAI,SAAS,EAAI,EAAS,EAAkB,EAAV,EAAa,EAAU,GAG3D,EAAI"}
|
package/dist/index55.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={upColor:"#22AB94",downColor:"#F7525F",wickUpColor:"#22AB94",wickDownColor:"#F7525F",maxBarWidthMultiplier:3},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,l,r,i,n){const{context:a,pixelRatio:e}=o,{fromIdx:h,toIdx:s}=l;if(h>=s||0===t.length)return;const p=this._options,u=Math.max(1,Math.round(e));let c=0;for(let M=h;M<=s&&M<t.length;M++)t.volume[M]>c&&(c=t.volume[M]);0===c&&(c=1),a.save();for(let M=h;M<=s&&M<t.length;M++){const o=t.open[M],l=t.close[M],h=t.high[M],s=t.low[M],d=t.volume[M],m=l>=o,x=m?p.upColor:p.downColor,w=m?p.wickUpColor:p.wickDownColor,f=Math.round(r(M)*e),C=Math.round(i(o)*e),v=Math.round(i(l)*e),g=Math.round(i(h)*e),k=Math.round(i(s)*e),B=n*(d/c)*p.maxBarWidthMultiplier,F=Math.max(1,Math.round(B*e/2));a.fillStyle=w,a.fillRect(f-Math.floor(u/2),g,u,k-g);const _=Math.min(C,v),y=Math.max(1,Math.max(C,v)-_);a.fillStyle=x,a.fillRect(f-F,_,2*F,y)}a.restore()}};export{t as VolumeCandleRenderer};
|
|
2
|
+
//# sourceMappingURL=index55.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index55.js","names":[],"sources":["../src/renderers/volume-candle.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface VolumeCandleRendererOptions {\n upColor: string;\n downColor: string;\n wickUpColor: string;\n wickDownColor: string;\n maxBarWidthMultiplier: number;\n}\n\nconst DEFAULT_OPTIONS: VolumeCandleRendererOptions = {\n upColor: '#22AB94',\n downColor: '#F7525F',\n wickUpColor: '#22AB94',\n wickDownColor: '#F7525F',\n maxBarWidthMultiplier: 3,\n};\n\n/**\n * VolumeCandleRenderer — like CandlestickRenderer but the candle body width\n * varies based on volume relative to the maximum volume in the visible range.\n *\n * Width = baseBarWidth * (volume / maxVolume) * maxBarWidthMultiplier,\n * with a minimum of 1 physical pixel. Wicks are always 1px wide.\n */\nexport class VolumeCandleRenderer {\n private _options: VolumeCandleRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<VolumeCandleRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n\n // Wick width: 1 physical pixel.\n const wickWidth = Math.max(1, Math.round(pr));\n\n // Find max volume in visible range.\n let maxVolume = 0;\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n if (store.volume[i] > maxVolume) maxVolume = store.volume[i];\n }\n // Guard against division by zero when all volumes are 0.\n if (maxVolume === 0) maxVolume = 1;\n\n ctx.save();\n\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n const open = store.open[i];\n const close = store.close[i];\n const high = store.high[i];\n const low = store.low[i];\n const volume = store.volume[i];\n const isUp = close >= open;\n\n const bodyColor = isUp ? opts.upColor : opts.downColor;\n const wickColor = isUp ? opts.wickUpColor : opts.wickDownColor;\n\n const cx = Math.round(indexToX(i) * pr);\n const openY = Math.round(priceToY(open) * pr);\n const closeY = Math.round(priceToY(close) * pr);\n const highY = Math.round(priceToY(high) * pr);\n const lowY = Math.round(priceToY(low) * pr);\n\n // Volume-scaled half-body width (at least 1 physical pixel).\n const scaledWidth = barWidth * (volume / maxVolume) * opts.maxBarWidthMultiplier;\n const halfBody = Math.max(1, Math.round((scaledWidth * pr) / 2));\n\n // ── Wick ──────────────────────────────────────────────────────────────\n ctx.fillStyle = wickColor;\n ctx.fillRect(cx - Math.floor(wickWidth / 2), highY, wickWidth, lowY - highY);\n\n // ── Body ──────────────────────────────────────────────────────────────\n const bodyTop = Math.min(openY, closeY);\n const bodyBottom = Math.max(openY, closeY);\n const bodyHeight = Math.max(1, bodyBottom - bodyTop);\n\n ctx.fillStyle = bodyColor;\n ctx.fillRect(cx - halfBody, bodyTop, halfBody * 2, bodyHeight);\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAUA,IAAM,EAA+C,CACnD,QAAS,UACT,UAAW,UACX,YAAa,UACb,cAAe,UACf,sBAAuB,GAUZ,EAAb,kCACkD,IAAK,GAErD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SAGZ,EAAY,KAAK,IAAI,EAAG,KAAK,MAAM,IAGzC,IAAI,EAAY,EAChB,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAChD,EAAM,OAAO,GAAK,IAAW,EAAY,EAAM,OAAO,IAG1C,IAAd,IAAiB,EAAY,GAEjC,EAAI,OAEJ,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IAAK,CACzD,MAAM,EAAO,EAAM,KAAK,GAClB,EAAQ,EAAM,MAAM,GACpB,EAAO,EAAM,KAAK,GAClB,EAAM,EAAM,IAAI,GAChB,EAAS,EAAM,OAAO,GACtB,EAAO,GAAS,EAEhB,EAAY,EAAO,EAAK,QAAU,EAAK,UACvC,EAAY,EAAO,EAAK,YAAc,EAAK,cAE3C,EAAK,KAAK,MAAM,EAAS,GAAK,GAC9B,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAS,KAAK,MAAM,EAAS,GAAS,GACtC,EAAQ,KAAK,MAAM,EAAS,GAAQ,GACpC,EAAO,KAAK,MAAM,EAAS,GAAO,GAGlC,EAAc,GAAY,EAAS,GAAa,EAAK,sBACrD,EAAW,KAAK,IAAI,EAAG,KAAK,MAAO,EAAc,EAAM,IAG7D,EAAI,UAAY,EAChB,EAAI,SAAS,EAAK,KAAK,MAAM,EAAY,GAAI,EAAO,EAAW,EAAO,GAGtE,MAAM,EAAU,KAAK,IAAI,EAAO,GAE1B,EAAa,KAAK,IAAI,EADT,KAAK,IAAI,EAAO,GACS,GAE5C,EAAI,UAAY,EAChB,EAAI,SAAS,EAAK,EAAU,EAAoB,EAAX,EAAc,GAGrD,EAAI"}
|
package/dist/index56.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={basePrice:0,topLineColor:"#22AB94",topFillColor:"rgba(34, 171, 148, 0.56)",bottomLineColor:"#F7525F",bottomFillColor:"rgba(247, 82, 95, 0.56)",lineWidth:2},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}draw(o,t,e,l,i){const{context:r,pixelRatio:n,width:a}=o,{fromIdx:h,toIdx:s}=e;if(h>=s||0===t.length)return;const d=this._options,p=Math.round(i(d.basePrice)*n),c=Math.max(1,d.lineWidth*n),g=[];for(let C=h;C<=s&&C<t.length;C++)g.push({x:Math.round(l(C)*n),y:Math.round(i(t.close[C])*n)});if(0===g.length)return;r.save();const b=(t,e)=>{r.save(),r.beginPath(),e?r.rect(0,0,a*n,p):r.rect(0,p,a*n,o.height*n-p),r.clip();let l=p;for(let o=0;o<g.length;o++)l=e?Math.min(l,g[o].y):Math.max(l,g[o].y);const i=r.createLinearGradient(0,l,0,p);e?(i.addColorStop(0,t),i.addColorStop(1,"rgba(0,0,0,0)")):(i.addColorStop(0,"rgba(0,0,0,0)"),i.addColorStop(1,t)),r.beginPath(),r.moveTo(g[0].x,g[0].y);for(let o=1;o<g.length;o++)r.lineTo(g[o].x,g[o].y);r.lineTo(g[g.length-1].x,p),r.lineTo(g[0].x,p),r.closePath(),r.fillStyle=i,r.fill(),r.restore()};b(d.topFillColor,!0),b(d.bottomFillColor,!1);const x=(t,e)=>{r.save(),r.beginPath(),e?r.rect(0,0,a*n,p):r.rect(0,p,a*n,o.height*n-p),r.clip(),r.beginPath(),r.moveTo(g[0].x,g[0].y);for(let o=1;o<g.length;o++)r.lineTo(g[o].x,g[o].y);r.strokeStyle=t,r.lineWidth=c,r.lineJoin="round",r.lineCap="round",r.setLineDash([]),r.stroke(),r.restore()};x(d.topLineColor,!0),x(d.bottomLineColor,!1),r.beginPath(),r.moveTo(0,p),r.lineTo(Math.round(a*n),p),r.strokeStyle=d.topLineColor,r.lineWidth=Math.max(1,Math.round(n)),r.setLineDash([4*n,4*n]),r.stroke(),r.restore()}};export{t as BaselineDeltaMountainRenderer};
|
|
2
|
+
//# sourceMappingURL=index56.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index56.js","names":[],"sources":["../src/renderers/baseline-delta-mountain.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface BaselineDeltaMountainRendererOptions {\n basePrice: number;\n topLineColor: string;\n topFillColor: string;\n bottomLineColor: string;\n bottomFillColor: string;\n lineWidth: number;\n}\n\nconst DEFAULT_OPTIONS: BaselineDeltaMountainRendererOptions = {\n basePrice: 0,\n topLineColor: '#22AB94',\n topFillColor: 'rgba(34, 171, 148, 0.56)',\n bottomLineColor: '#F7525F',\n bottomFillColor: 'rgba(247, 82, 95, 0.56)',\n lineWidth: 2,\n};\n\n/**\n * BaselineDeltaMountainRenderer — like BaselineRenderer but with solid gradient\n * fills instead of flat semi-transparent colour.\n *\n * Above baseline: gradient from topFillColor (at the line) fading to transparent\n * at the baseline. Below baseline: gradient from transparent at the baseline\n * fading to bottomFillColor at the line.\n */\nexport class BaselineDeltaMountainRenderer {\n private _options: BaselineDeltaMountainRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<BaselineDeltaMountainRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n ): void {\n const { context: ctx, pixelRatio: pr, width } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const baselineY = Math.round(priceToY(opts.basePrice) * pr);\n const lw = Math.max(1, opts.lineWidth * pr);\n\n // Build pixel-level point array.\n const points: Array<{ x: number; y: number }> = [];\n for (let i = fromIdx; i <= toIdx && i < store.length; i++) {\n points.push({\n x: Math.round(indexToX(i) * pr),\n y: Math.round(priceToY(store.close[i]) * pr),\n });\n }\n if (points.length === 0) return;\n\n ctx.save();\n\n // ── Helper to draw gradient fill clipped above or below the baseline ──\n\n const drawGradientFill = (fillColor: string, above: boolean): void => {\n ctx.save();\n\n // Clip to the region above or below the baseline.\n ctx.beginPath();\n if (above) {\n ctx.rect(0, 0, width * pr, baselineY);\n } else {\n ctx.rect(0, baselineY, width * pr, target.height * pr - baselineY);\n }\n ctx.clip();\n\n // Find the extreme Y in this region for the gradient range.\n let extremeY = baselineY;\n for (let k = 0; k < points.length; k++) {\n if (above) {\n extremeY = Math.min(extremeY, points[k].y);\n } else {\n extremeY = Math.max(extremeY, points[k].y);\n }\n }\n\n // Build gradient: colour at the line, transparent at the baseline.\n const gradient = ctx.createLinearGradient(0, extremeY, 0, baselineY);\n if (above) {\n gradient.addColorStop(0, fillColor);\n gradient.addColorStop(1, 'rgba(0,0,0,0)');\n } else {\n gradient.addColorStop(0, 'rgba(0,0,0,0)');\n gradient.addColorStop(1, fillColor);\n }\n\n // Trace the close-price path, then close back along the baseline.\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n for (let k = 1; k < points.length; k++) ctx.lineTo(points[k].x, points[k].y);\n ctx.lineTo(points[points.length - 1].x, baselineY);\n ctx.lineTo(points[0].x, baselineY);\n ctx.closePath();\n ctx.fillStyle = gradient;\n ctx.fill();\n\n ctx.restore();\n };\n\n drawGradientFill(opts.topFillColor, true);\n drawGradientFill(opts.bottomFillColor, false);\n\n // ── Helper to clip the line stroke to above or below the baseline ────\n\n const drawLine = (color: string, above: boolean): void => {\n ctx.save();\n ctx.beginPath();\n if (above) {\n ctx.rect(0, 0, width * pr, baselineY);\n } else {\n ctx.rect(0, baselineY, width * pr, target.height * pr - baselineY);\n }\n ctx.clip();\n\n ctx.beginPath();\n ctx.moveTo(points[0].x, points[0].y);\n for (let k = 1; k < points.length; k++) ctx.lineTo(points[k].x, points[k].y);\n ctx.strokeStyle = color;\n ctx.lineWidth = lw;\n ctx.lineJoin = 'round';\n ctx.lineCap = 'round';\n ctx.setLineDash([]);\n ctx.stroke();\n ctx.restore();\n };\n\n drawLine(opts.topLineColor, true);\n drawLine(opts.bottomLineColor, false);\n\n // ── Dashed baseline ──────────────────────────────────────────────────\n ctx.beginPath();\n ctx.moveTo(0, baselineY);\n ctx.lineTo(Math.round(width * pr), baselineY);\n ctx.strokeStyle = opts.topLineColor;\n ctx.lineWidth = Math.max(1, Math.round(pr));\n ctx.setLineDash([4 * pr, 4 * pr]);\n ctx.stroke();\n\n ctx.restore();\n }\n}\n"],"mappings":"AAWA,IAAM,EAAwD,CAC5D,UAAW,EACX,aAAc,UACd,aAAc,2BACd,gBAAiB,UACjB,gBAAiB,0BACjB,UAAW,GAWA,EAAb,kCAC2D,IAAK,GAE9D,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,IAAA,CACE,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,EAAA,MAAI,GAAU,GAC1C,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAY,KAAK,MAAM,EAAS,EAAK,WAAa,GAClD,EAAK,KAAK,IAAI,EAAG,EAAK,UAAY,GAGlC,EAA0C,GAChD,IAAK,IAAI,EAAI,EAAS,GAAK,GAAS,EAAI,EAAM,OAAQ,IACpD,EAAO,KAAK,CACV,EAAG,KAAK,MAAM,EAAS,GAAK,GAC5B,EAAG,KAAK,MAAM,EAAS,EAAM,MAAM,IAAM,KAG7C,GAAsB,IAAlB,EAAO,OAAc,OAEzB,EAAI,OAIJ,MAAM,EAAA,CAAoB,EAAmB,KAC3C,EAAI,OAGJ,EAAI,YACA,EACF,EAAI,KAAK,EAAG,EAAG,EAAQ,EAAI,GAE3B,EAAI,KAAK,EAAG,EAAW,EAAQ,EAAI,EAAO,OAAS,EAAK,GAE1D,EAAI,OAGJ,IAAI,EAAW,EACf,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAE/B,EADE,EACS,KAAK,IAAI,EAAU,EAAO,GAAG,GAE7B,KAAK,IAAI,EAAU,EAAO,GAAG,GAK5C,MAAM,EAAW,EAAI,qBAAqB,EAAG,EAAU,EAAG,GACtD,GACF,EAAS,aAAa,EAAG,GACzB,EAAS,aAAa,EAAG,mBAEzB,EAAS,aAAa,EAAG,iBACzB,EAAS,aAAa,EAAG,IAI3B,EAAI,YACJ,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAClC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAAK,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAC1E,EAAI,OAAO,EAAO,EAAO,OAAS,GAAG,EAAG,GACxC,EAAI,OAAO,EAAO,GAAG,EAAG,GACxB,EAAI,YACJ,EAAI,UAAY,EAChB,EAAI,OAEJ,EAAI,WAGN,EAAiB,EAAK,cAAc,GACpC,EAAiB,EAAK,iBAAiB,GAIvC,MAAM,EAAA,CAAY,EAAe,KAC/B,EAAI,OACJ,EAAI,YACA,EACF,EAAI,KAAK,EAAG,EAAG,EAAQ,EAAI,GAE3B,EAAI,KAAK,EAAG,EAAW,EAAQ,EAAI,EAAO,OAAS,EAAK,GAE1D,EAAI,OAEJ,EAAI,YACJ,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAClC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAAK,EAAI,OAAO,EAAO,GAAG,EAAG,EAAO,GAAG,GAC1E,EAAI,YAAc,EAClB,EAAI,UAAY,EAChB,EAAI,SAAW,QACf,EAAI,QAAU,QACd,EAAI,YAAY,IAChB,EAAI,SACJ,EAAI,WAGN,EAAS,EAAK,cAAc,GAC5B,EAAS,EAAK,iBAAiB,GAG/B,EAAI,YACJ,EAAI,OAAO,EAAG,GACd,EAAI,OAAO,KAAK,MAAM,EAAQ,GAAK,GACnC,EAAI,YAAc,EAAK,aACvB,EAAI,UAAY,KAAK,IAAI,EAAG,KAAK,MAAM,IACvC,EAAI,YAAY,CAAC,EAAI,EAAI,EAAI,IAC7B,EAAI,SAEJ,EAAI"}
|
package/dist/index57.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={boxSize:1,upColor:"#22AB94",downColor:"#F7525F"},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}_buildBricks(o,t,s){const{boxSize:e}=this._options;if(e<=0)return[];const n=[],r=Math.min(s,o.length-1);if(t>r)return n;let i=Math.floor(o.close[t]/e)*e,l=null;for(let p=t;p<=r;p++){const t=o.close[p]-i,s=Math.floor(Math.abs(t)/e);if(0===s)continue;const r=t>0;if(null===l){l=r?"up":"down";for(let o=0;o<s;o++)if(r){const t=i+o*e;n.push({sourceIndex:p,bottom:t,top:t+e,isUp:!0})}else{const t=i-o*e;n.push({sourceIndex:p,bottom:t-e,top:t,isUp:!1})}i+=(r?s:-s)*e}else if("up"===l&&r||"down"===l&&!r){for(let o=0;o<s;o++)if(r){const t=i+o*e;n.push({sourceIndex:p,bottom:t,top:t+e,isUp:!0})}else{const t=i-o*e;n.push({sourceIndex:p,bottom:t-e,top:t,isUp:!1})}i+=(r?s:-s)*e}else if(s>=2){l=r?"up":"down";for(let o=0;o<s;o++)if(r){const t=i+o*e;n.push({sourceIndex:p,bottom:t,top:t+e,isUp:!0})}else{const t=i-o*e;n.push({sourceIndex:p,bottom:t-e,top:t,isUp:!1})}i+=(r?s:-s)*e}}return n}draw(o,t,s,e,n,r){const{context:i,pixelRatio:l}=o,{fromIdx:p,toIdx:u}=s;if(p>=u||0===t.length)return;const c=this._options,h=this._buildBricks(t,p,u);if(0===h.length)return;const d=Math.max(1,Math.round(r*l/2));i.save();for(let a=0;a<h.length;a++){const o=h[a],t=Math.round(e(o.sourceIndex)*l),s=Math.round(n(o.top)*l),r=Math.round(n(o.bottom)*l),p=Math.max(1,r-s);i.fillStyle=o.isUp?c.upColor:c.downColor,i.fillRect(t-d,s,2*d,p),i.strokeStyle=o.isUp?c.upColor:c.downColor,i.lineWidth=Math.max(1,Math.round(l)),i.strokeRect(t-d+.5,s+.5,2*d-1,p-1)}i.restore()}};export{t as RenkoRenderer};
|
|
2
|
+
//# sourceMappingURL=index57.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index57.js","names":[],"sources":["../src/renderers/renko.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface RenkoRendererOptions {\n boxSize: number;\n upColor: string;\n downColor: string;\n}\n\nconst DEFAULT_OPTIONS: RenkoRendererOptions = {\n boxSize: 1,\n upColor: '#22AB94',\n downColor: '#F7525F',\n};\n\ninterface RenkoBrick {\n /** The bar index in the source data that triggered this brick. */\n sourceIndex: number;\n /** Bottom price of the brick. */\n bottom: number;\n /** Top price of the brick. */\n top: number;\n /** True = up brick, false = down brick. */\n isUp: boolean;\n}\n\n/**\n * RenkoRenderer — builds Renko bricks from close prices and draws them.\n *\n * Renko charts filter out noise by only drawing a new brick when price moves\n * by at least `boxSize` in one direction. Up bricks are filled with `upColor`,\n * down bricks with `downColor`.\n */\nexport class RenkoRenderer {\n private _options: RenkoRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<RenkoRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n /**\n * Build Renko bricks from the close prices in the store for the given range.\n * We walk from `fromIdx` to `toIdx` and emit bricks whenever the close price\n * departs from the current brick level by at least `boxSize`.\n */\n private _buildBricks(store: ColumnStore, fromIdx: number, toIdx: number): RenkoBrick[] {\n const { boxSize } = this._options;\n if (boxSize <= 0) return [];\n\n const bricks: RenkoBrick[] = [];\n const end = Math.min(toIdx, store.length - 1);\n if (fromIdx > end) return bricks;\n\n // Anchor the first brick base to the nearest boxSize multiple below the first close.\n let basePrice = Math.floor(store.close[fromIdx] / boxSize) * boxSize;\n let direction: 'up' | 'down' | null = null;\n\n for (let i = fromIdx; i <= end; i++) {\n const close = store.close[i];\n\n // How many full boxes has price moved from basePrice?\n const delta = close - basePrice;\n const boxes = Math.floor(Math.abs(delta) / boxSize);\n\n if (boxes === 0) continue;\n\n const movingUp = delta > 0;\n\n if (direction === null) {\n // First movement establishes direction.\n direction = movingUp ? 'up' : 'down';\n for (let b = 0; b < boxes; b++) {\n if (movingUp) {\n const bottom = basePrice + b * boxSize;\n bricks.push({ sourceIndex: i, bottom, top: bottom + boxSize, isUp: true });\n } else {\n const top = basePrice - b * boxSize;\n bricks.push({ sourceIndex: i, bottom: top - boxSize, top, isUp: false });\n }\n }\n basePrice += (movingUp ? boxes : -boxes) * boxSize;\n } else if ((direction === 'up' && movingUp) || (direction === 'down' && !movingUp)) {\n // Continuation in same direction.\n for (let b = 0; b < boxes; b++) {\n if (movingUp) {\n const bottom = basePrice + b * boxSize;\n bricks.push({ sourceIndex: i, bottom, top: bottom + boxSize, isUp: true });\n } else {\n const top = basePrice - b * boxSize;\n bricks.push({ sourceIndex: i, bottom: top - boxSize, top, isUp: false });\n }\n }\n basePrice += (movingUp ? boxes : -boxes) * boxSize;\n } else {\n // Reversal — need at least 2 boxes in opposite direction to reverse\n // (standard Renko rule: reversal needs to exceed the previous brick).\n if (boxes >= 2) {\n direction = movingUp ? 'up' : 'down';\n // Reversal bricks start from the current base level. The first brick\n // overlaps the previous brick's base, which is standard Renko behavior.\n for (let b = 0; b < boxes; b++) {\n if (movingUp) {\n const bottom = basePrice + b * boxSize;\n bricks.push({ sourceIndex: i, bottom, top: bottom + boxSize, isUp: true });\n } else {\n const top = basePrice - b * boxSize;\n bricks.push({ sourceIndex: i, bottom: top - boxSize, top, isUp: false });\n }\n }\n basePrice += (movingUp ? boxes : -boxes) * boxSize;\n }\n }\n }\n\n return bricks;\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const bricks = this._buildBricks(store, fromIdx, toIdx);\n if (bricks.length === 0) return;\n\n const halfBody = Math.max(1, Math.round((barWidth * pr) / 2));\n\n ctx.save();\n\n for (let b = 0; b < bricks.length; b++) {\n const brick = bricks[b];\n const cx = Math.round(indexToX(brick.sourceIndex) * pr);\n const topY = Math.round(priceToY(brick.top) * pr);\n const bottomY = Math.round(priceToY(brick.bottom) * pr);\n const height = Math.max(1, bottomY - topY);\n\n ctx.fillStyle = brick.isUp ? opts.upColor : opts.downColor;\n ctx.fillRect(cx - halfBody, topY, halfBody * 2, height);\n\n // Thin border for definition.\n ctx.strokeStyle = brick.isUp ? opts.upColor : opts.downColor;\n ctx.lineWidth = Math.max(1, Math.round(pr));\n ctx.strokeRect(cx - halfBody + 0.5, topY + 0.5, halfBody * 2 - 1, height - 1);\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"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"}
|
package/dist/index58.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var t={reversalAmount:1,yangColor:"#22AB94",yinColor:"#F7525F",yangWidth:3,yinWidth:1},n=class{constructor(){this._options={...t}}applyOptions(t){this._options={...this._options,...t}}_buildSegments(t,n,e){const{reversalAmount:o}=this._options,i=Math.min(e,t.length-1);if(n>i)return[];if(o<=0)return[];const s=[];let r=0,a=t.close[n],d=n,l=a,h=a,c=a,g=!0;for(let u=n+1;u<=i;u++){const n=t.close[u];if(0===r){const t=n-a;Math.abs(t)>=o&&(r=t>0?1:-1,g=r>0,s.push({startIndex:d,endIndex:u,startPrice:l,endPrice:n,isYang:g}),d=u,l=n,a=n,r>0?h=n:c=n);continue}const e=n-a;if(r>0&&e>0||r<0&&e<0){if(a=n,r>0?n>h&&(h=n,g=!0):n<c&&(c=n,g=!1),s.length>0){const t=s[s.length-1];t.endIndex=u,t.endPrice=n,t.isYang=g}}else Math.abs(e)>=o&&(r>0?h=a:c=a,r=-r,r>0&&n>h?(g=!0,h=n):r<0&&n<c&&(g=!1,c=n),s.push({startIndex:d,endIndex:u,startPrice:l,endPrice:n,isYang:g}),d=u,l=n,a=n)}return s}draw(t,n,e,o,i,s){const{context:r,pixelRatio:a}=t,{fromIdx:d,toIdx:l}=e;if(d>=l||0===n.length)return;const h=this._options,c=this._buildSegments(n,d,l);if(0!==c.length){r.save(),r.lineCap="square",r.lineJoin="miter";for(let t=0;t<c.length;t++){const n=c[t],e=n.isYang?h.yangColor:h.yinColor,s=(n.isYang?h.yangWidth:h.yinWidth)*a;r.strokeStyle=e,r.lineWidth=s,Math.round(o(n.startIndex)*a);const d=Math.round(o(n.endIndex)*a),l=Math.round(i(n.startPrice)*a),g=Math.round(i(n.endPrice)*a);if(r.beginPath(),t>0){const n=c[t-1],e=Math.round(o(n.endIndex)*a);r.moveTo(e,l),r.lineTo(d,l)}else r.moveTo(d,l);r.lineTo(d,g),r.stroke()}r.restore()}}};export{n as KagiRenderer};
|
|
2
|
+
//# sourceMappingURL=index58.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index58.js","names":[],"sources":["../src/renderers/kagi.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface KagiRendererOptions {\n reversalAmount: number;\n yangColor: string;\n yinColor: string;\n yangWidth: number;\n yinWidth: number;\n}\n\nconst DEFAULT_OPTIONS: KagiRendererOptions = {\n reversalAmount: 1,\n yangColor: '#22AB94',\n yinColor: '#F7525F',\n yangWidth: 3,\n yinWidth: 1,\n};\n\n/** A single vertical segment of the Kagi chart. */\ninterface KagiSegment {\n /** Source bar index where this segment starts. */\n startIndex: number;\n /** Source bar index where this segment ends. */\n endIndex: number;\n /** Price at the start of the segment. */\n startPrice: number;\n /** Price at the end of the segment. */\n endPrice: number;\n /** True if yang (thick/bullish), false if yin (thin/bearish). */\n isYang: boolean;\n}\n\n/**\n * KagiRenderer — draws Kagi chart vertical lines with yang/yin thickness.\n *\n * Kagi charts emphasize trend direction using line thickness:\n * - Yang (thick, green) lines when price exceeds a previous high\n * - Yin (thin, red) lines when price drops below a previous low\n * - Horizontal connectors join segments on direction changes\n */\nexport class KagiRenderer {\n private _options: KagiRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<KagiRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n private _buildSegments(store: ColumnStore, fromIdx: number, toIdx: number): KagiSegment[] {\n const { reversalAmount } = this._options;\n const end = Math.min(toIdx, store.length - 1);\n if (fromIdx > end) return [];\n if (reversalAmount <= 0) return [];\n\n const segments: KagiSegment[] = [];\n\n // Track current direction: 1 = up, -1 = down\n let direction = 0;\n let currentPrice = store.close[fromIdx];\n let segStartIndex = fromIdx;\n let segStartPrice = currentPrice;\n\n // Track shoulder (previous high) and waist (previous low) for yang/yin transitions.\n let prevHigh = currentPrice;\n let prevLow = currentPrice;\n let isYang = true;\n\n for (let i = fromIdx + 1; i <= end; i++) {\n const close = store.close[i];\n\n if (direction === 0) {\n // Establish initial direction.\n const diff = close - currentPrice;\n if (Math.abs(diff) >= reversalAmount) {\n direction = diff > 0 ? 1 : -1;\n isYang = direction > 0;\n segments.push({\n startIndex: segStartIndex,\n endIndex: i,\n startPrice: segStartPrice,\n endPrice: close,\n isYang,\n });\n segStartIndex = i;\n segStartPrice = close;\n currentPrice = close;\n if (direction > 0) {\n prevHigh = close;\n } else {\n prevLow = close;\n }\n }\n continue;\n }\n\n const delta = close - currentPrice;\n const sameDirection = (direction > 0 && delta > 0) || (direction < 0 && delta < 0);\n\n if (sameDirection) {\n // Extend in same direction — update the current segment endpoint.\n currentPrice = close;\n // Update shoulder/waist.\n if (direction > 0) {\n if (close > prevHigh) {\n prevHigh = close;\n isYang = true; // broke above previous high -> yang\n }\n } else {\n if (close < prevLow) {\n prevLow = close;\n isYang = false; // broke below previous low -> yin\n }\n }\n // Update the last segment's endpoint instead of adding a new one.\n if (segments.length > 0) {\n const last = segments[segments.length - 1];\n last.endIndex = i;\n last.endPrice = close;\n last.isYang = isYang;\n }\n } else if (Math.abs(delta) >= reversalAmount) {\n // Reversal detected.\n // Record shoulder or waist from the current segment before reversing.\n if (direction > 0) {\n prevHigh = currentPrice;\n } else {\n prevLow = currentPrice;\n }\n\n direction = -direction;\n\n // Check yang/yin transition on reversal.\n if (direction > 0 && close > prevHigh) {\n isYang = true;\n prevHigh = close;\n } else if (direction < 0 && close < prevLow) {\n isYang = false;\n prevLow = close;\n }\n\n segments.push({\n startIndex: segStartIndex,\n endIndex: i,\n startPrice: segStartPrice,\n endPrice: close,\n isYang,\n });\n\n segStartIndex = i;\n segStartPrice = close;\n currentPrice = close;\n }\n // If reversal amount not reached, ignore this bar.\n }\n\n return segments;\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n _barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const segments = this._buildSegments(store, fromIdx, toIdx);\n if (segments.length === 0) return;\n\n ctx.save();\n ctx.lineCap = 'square';\n ctx.lineJoin = 'miter';\n\n for (let s = 0; s < segments.length; s++) {\n const seg = segments[s];\n const color = seg.isYang ? opts.yangColor : opts.yinColor;\n const width = (seg.isYang ? opts.yangWidth : opts.yinWidth) * pr;\n\n ctx.strokeStyle = color;\n ctx.lineWidth = width;\n\n const x1 = Math.round(indexToX(seg.startIndex) * pr);\n const x2 = Math.round(indexToX(seg.endIndex) * pr);\n const y1 = Math.round(priceToY(seg.startPrice) * pr);\n const y2 = Math.round(priceToY(seg.endPrice) * pr);\n\n ctx.beginPath();\n\n // Kagi: each segment is a vertical line at the segment's end X position.\n // A horizontal connector bridges from the previous segment's X to this one.\n if (s > 0) {\n const prevSeg = segments[s - 1];\n const prevX = Math.round(indexToX(prevSeg.endIndex) * pr);\n // Horizontal connector at the start price level.\n ctx.moveTo(prevX, y1);\n ctx.lineTo(x2, y1);\n } else {\n ctx.moveTo(x2, y1);\n }\n\n // Vertical line from startPrice to endPrice at a single X.\n ctx.lineTo(x2, y2);\n ctx.stroke();\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAUA,IAAM,EAAuC,CAC3C,eAAgB,EAChB,UAAW,UACX,SAAU,UACV,UAAW,EACX,SAAU,GAyBC,EAAb,kCAC0C,IAAK,GAE7C,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,cAAA,CAAuB,EAAoB,EAAiB,GAC1D,MAAM,eAAE,GAAmB,KAAK,SAC1B,EAAM,KAAK,IAAI,EAAO,EAAM,OAAS,GAC3C,GAAI,EAAU,EAAK,MAAO,GAC1B,GAAI,GAAkB,EAAG,MAAO,GAEhC,MAAM,EAA0B,GAGhC,IAAI,EAAY,EACZ,EAAe,EAAM,MAAM,GAC3B,EAAgB,EAChB,EAAgB,EAGhB,EAAW,EACX,EAAU,EACV,GAAS,EAEb,IAAK,IAAI,EAAI,EAAU,EAAG,GAAK,EAAK,IAAK,CACvC,MAAM,EAAQ,EAAM,MAAM,GAE1B,GAAkB,IAAd,EAAiB,CAEnB,MAAM,EAAO,EAAQ,EACjB,KAAK,IAAI,IAAS,IACpB,EAAY,EAAO,EAAI,GAAI,EAC3B,EAAS,EAAY,EACrB,EAAS,KAAK,CACZ,WAAY,EACZ,SAAU,EACV,WAAY,EACZ,SAAU,EACV,WAEF,EAAgB,EAChB,EAAgB,EAChB,EAAe,EACX,EAAY,EACd,EAAW,EAEX,EAAU,GAGd,SAGF,MAAM,EAAQ,EAAQ,EAGtB,GAFuB,EAAY,GAAK,EAAQ,GAAO,EAAY,GAAK,EAAQ,GAkB9E,GAdA,EAAe,EAEX,EAAY,EACV,EAAQ,IACV,EAAW,EACX,GAAS,GAGP,EAAQ,IACV,EAAU,EACV,GAAS,GAIT,EAAS,OAAS,EAAG,CACvB,MAAM,EAAO,EAAS,EAAS,OAAS,GACxC,EAAK,SAAW,EAChB,EAAK,SAAW,EAChB,EAAK,OAAS,QAEP,KAAK,IAAI,IAAU,IAGxB,EAAY,EACd,EAAW,EAEX,EAAU,EAGZ,GAAa,EAGT,EAAY,GAAK,EAAQ,GAC3B,GAAS,EACT,EAAW,GACF,EAAY,GAAK,EAAQ,IAClC,GAAS,EACT,EAAU,GAGZ,EAAS,KAAK,CACZ,WAAY,EACZ,SAAU,EACV,WAAY,EACZ,SAAU,EACV,WAGF,EAAgB,EAChB,EAAgB,EAChB,EAAe,GAKnB,OAAO,EAGT,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAW,KAAK,eAAe,EAAO,EAAS,GACrD,GAAwB,IAApB,EAAS,OAAb,CAEA,EAAI,OACJ,EAAI,QAAU,SACd,EAAI,SAAW,QAEf,IAAK,IAAI,EAAI,EAAG,EAAI,EAAS,OAAQ,IAAK,CACxC,MAAM,EAAM,EAAS,GACf,EAAQ,EAAI,OAAS,EAAK,UAAY,EAAK,SAC3C,GAAS,EAAI,OAAS,EAAK,UAAY,EAAK,UAAY,EAE9D,EAAI,YAAc,EAClB,EAAI,UAAY,EAEL,KAAK,MAAM,EAAS,EAAI,YAAc,GACjD,MAAM,EAAK,KAAK,MAAM,EAAS,EAAI,UAAY,GACzC,EAAK,KAAK,MAAM,EAAS,EAAI,YAAc,GAC3C,EAAK,KAAK,MAAM,EAAS,EAAI,UAAY,GAM/C,GAJA,EAAI,YAIA,EAAI,EAAG,CACT,MAAM,EAAU,EAAS,EAAI,GACvB,EAAQ,KAAK,MAAM,EAAS,EAAQ,UAAY,GAEtD,EAAI,OAAO,EAAO,GAClB,EAAI,OAAO,EAAI,QAEf,EAAI,OAAO,EAAI,GAIjB,EAAI,OAAO,EAAI,GACf,EAAI,SAGN,EAAI,SAtCuB"}
|
package/dist/index59.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var o={breakCount:3,upColor:"#22AB94",downColor:"#F7525F"},t=class{constructor(){this._options={...o}}applyOptions(o){this._options={...this._options,...o}}_buildBlocks(t,e,n){const s=Number.isFinite(this._options.breakCount)?Math.max(1,Math.floor(this._options.breakCount)):o.breakCount,r=Math.min(n,t.length-1);if(e>r)return[];const i=[];if(e===r)return i;let l=t.close[e];for(let o=e+1;o<=r;o++){const e=t.close[o];if(e===l)continue;if(0===i.length){i.push({sourceIndex:o,open:l,close:e,isUp:e>l}),l=e;continue}const n=Math.min(s,i.length);let r=-1/0,h=1/0;for(let o=i.length-n;o<i.length;o++){const t=i[o],e=Math.max(t.open,t.close),n=Math.min(t.open,t.close);e>r&&(r=e),n<h&&(h=n)}i[i.length-1].isUp?e>r?(i.push({sourceIndex:o,open:l,close:e,isUp:!0}),l=e):e<h&&(i.push({sourceIndex:o,open:l,close:e,isUp:!1}),l=e):e<h?(i.push({sourceIndex:o,open:l,close:e,isUp:!1}),l=e):e>r&&(i.push({sourceIndex:o,open:l,close:e,isUp:!0}),l=e)}return i}draw(o,t,e,n,s,r){const{context:i,pixelRatio:l}=o,{fromIdx:h,toIdx:c}=e;if(h>=c||0===t.length)return;const p=this._options,u=this._buildBlocks(t,h,c);if(0===u.length)return;const a=Math.max(1,Math.round(r*l/2)),d=Math.max(1,Math.round(l));i.save();for(let x=0;x<u.length;x++){const o=u[x],t=Math.round(n(o.sourceIndex)*l),e=Math.round(s(o.open)*l),r=Math.round(s(o.close)*l),h=Math.min(e,r),c=Math.max(1,Math.max(e,r)-h);i.fillStyle=o.isUp?p.upColor:p.downColor,i.fillRect(t-a,h,2*a,c),i.strokeStyle=o.isUp?p.upColor:p.downColor,i.lineWidth=d,i.strokeRect(t-a+.5,h+.5,2*a-1,c-1)}i.restore()}};export{t as LineBreakRenderer};
|
|
2
|
+
//# sourceMappingURL=index59.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index59.js","names":[],"sources":["../src/renderers/line-break.ts"],"sourcesContent":["import type { ColumnStore, IRenderTarget, VisibleRange } from '../core/types';\n\nexport interface LineBreakRendererOptions {\n breakCount: number;\n upColor: string;\n downColor: string;\n}\n\nconst DEFAULT_OPTIONS: LineBreakRendererOptions = {\n breakCount: 3,\n upColor: '#22AB94',\n downColor: '#F7525F',\n};\n\ninterface LineBreakBlock {\n /** Source bar index that generated this block. */\n sourceIndex: number;\n /** Open price (previous block's close). */\n open: number;\n /** Close price (current close). */\n close: number;\n /** True = up block, false = down block. */\n isUp: boolean;\n}\n\n/**\n * LineBreakRenderer — draws Three Line Break (or N-Line Break) chart.\n *\n * Each block opens at the previous close and closes at the current close.\n * A new block is only drawn when the current close breaks above the highest\n * high or below the lowest low of the last N blocks. This filters out minor\n * price fluctuations.\n */\nexport class LineBreakRenderer {\n private _options: LineBreakRendererOptions = { ...DEFAULT_OPTIONS };\n\n applyOptions(options: Partial<LineBreakRendererOptions>): void {\n this._options = { ...this._options, ...options };\n }\n\n private _buildBlocks(store: ColumnStore, fromIdx: number, toIdx: number): LineBreakBlock[] {\n const breakCount = Number.isFinite(this._options.breakCount)\n ? Math.max(1, Math.floor(this._options.breakCount))\n : DEFAULT_OPTIONS.breakCount;\n const end = Math.min(toIdx, store.length - 1);\n if (fromIdx > end) return [];\n\n const blocks: LineBreakBlock[] = [];\n\n // The first block is always created from the first two bars.\n if (fromIdx === end) return blocks;\n\n let prevClose = store.close[fromIdx];\n\n for (let i = fromIdx + 1; i <= end; i++) {\n const close = store.close[i];\n if (close === prevClose) continue; // No movement, skip.\n\n if (blocks.length === 0) {\n // Always create the first block.\n blocks.push({\n sourceIndex: i,\n open: prevClose,\n close,\n isUp: close > prevClose,\n });\n prevClose = close;\n continue;\n }\n\n // Determine the highest high and lowest low of the last N blocks.\n const lookback = Math.min(breakCount, blocks.length);\n let highestHigh = -Infinity;\n let lowestLow = Infinity;\n\n for (let b = blocks.length - lookback; b < blocks.length; b++) {\n const block = blocks[b];\n const blockHigh = Math.max(block.open, block.close);\n const blockLow = Math.min(block.open, block.close);\n if (blockHigh > highestHigh) highestHigh = blockHigh;\n if (blockLow < lowestLow) lowestLow = blockLow;\n }\n\n const lastBlock = blocks[blocks.length - 1];\n\n if (lastBlock.isUp) {\n // In an up trend:\n // - Continue up if close > highest high of last N\n // - Reverse down if close < lowest low of last N\n if (close > highestHigh) {\n blocks.push({\n sourceIndex: i,\n open: prevClose,\n close,\n isUp: true,\n });\n prevClose = close;\n } else if (close < lowestLow) {\n blocks.push({\n sourceIndex: i,\n open: prevClose,\n close,\n isUp: false,\n });\n prevClose = close;\n }\n // Otherwise, no block drawn (close is within the range).\n } else {\n // In a down trend:\n // - Continue down if close < lowest low of last N\n // - Reverse up if close > highest high of last N\n if (close < lowestLow) {\n blocks.push({\n sourceIndex: i,\n open: prevClose,\n close,\n isUp: false,\n });\n prevClose = close;\n } else if (close > highestHigh) {\n blocks.push({\n sourceIndex: i,\n open: prevClose,\n close,\n isUp: true,\n });\n prevClose = close;\n }\n }\n }\n\n return blocks;\n }\n\n draw(\n target: IRenderTarget,\n store: ColumnStore,\n range: VisibleRange,\n indexToX: (i: number) => number,\n priceToY: (price: number) => number,\n barWidth: number,\n ): void {\n const { context: ctx, pixelRatio: pr } = target;\n const { fromIdx, toIdx } = range;\n\n if (fromIdx >= toIdx || store.length === 0) return;\n\n const opts = this._options;\n const blocks = this._buildBlocks(store, fromIdx, toIdx);\n if (blocks.length === 0) return;\n\n const halfBody = Math.max(1, Math.round((barWidth * pr) / 2));\n const borderWidth = Math.max(1, Math.round(pr));\n\n ctx.save();\n\n for (let b = 0; b < blocks.length; b++) {\n const block = blocks[b];\n const cx = Math.round(indexToX(block.sourceIndex) * pr);\n const openY = Math.round(priceToY(block.open) * pr);\n const closeY = Math.round(priceToY(block.close) * pr);\n\n const top = Math.min(openY, closeY);\n const bottom = Math.max(openY, closeY);\n const height = Math.max(1, bottom - top);\n\n // Fill the block body (no wicks, unlike candlesticks).\n ctx.fillStyle = block.isUp ? opts.upColor : opts.downColor;\n ctx.fillRect(cx - halfBody, top, halfBody * 2, height);\n\n // Border for definition.\n ctx.strokeStyle = block.isUp ? opts.upColor : opts.downColor;\n ctx.lineWidth = borderWidth;\n ctx.strokeRect(cx - halfBody + 0.5, top + 0.5, halfBody * 2 - 1, height - 1);\n }\n\n ctx.restore();\n }\n}\n"],"mappings":"AAQA,IAAM,EAA4C,CAChD,WAAY,EACZ,QAAS,UACT,UAAW,WAsBA,EAAb,kCAC+C,IAAK,GAElD,YAAA,CAAa,GACX,KAAK,SAAW,IAAK,KAAK,YAAa,GAGzC,YAAA,CAAqB,EAAoB,EAAiB,GACxD,MAAM,EAAa,OAAO,SAAS,KAAK,SAAS,YAC7C,KAAK,IAAI,EAAG,KAAK,MAAM,KAAK,SAAS,aACrC,EAAgB,WACd,EAAM,KAAK,IAAI,EAAO,EAAM,OAAS,GAC3C,GAAI,EAAU,EAAK,MAAO,GAE1B,MAAM,EAA2B,GAGjC,GAAI,IAAY,EAAK,OAAO,EAE5B,IAAI,EAAY,EAAM,MAAM,GAE5B,IAAK,IAAI,EAAI,EAAU,EAAG,GAAK,EAAK,IAAK,CACvC,MAAM,EAAQ,EAAM,MAAM,GAC1B,GAAI,IAAU,EAAW,SAEzB,GAAsB,IAAlB,EAAO,OAAc,CAEvB,EAAO,KAAK,CACV,YAAa,EACb,KAAM,EACN,QACA,KAAM,EAAQ,IAEhB,EAAY,EACZ,SAIF,MAAM,EAAW,KAAK,IAAI,EAAY,EAAO,QAC7C,IAAI,GAAc,IACd,EAAY,IAEhB,IAAK,IAAI,EAAI,EAAO,OAAS,EAAU,EAAI,EAAO,OAAQ,IAAK,CAC7D,MAAM,EAAQ,EAAO,GACf,EAAY,KAAK,IAAI,EAAM,KAAM,EAAM,OACvC,EAAW,KAAK,IAAI,EAAM,KAAM,EAAM,OACxC,EAAY,IAAa,EAAc,GACvC,EAAW,IAAW,EAAY,GAGtB,EAAO,EAAO,OAAS,GAE3B,KAIR,EAAQ,GACV,EAAO,KAAK,CACV,YAAa,EACb,KAAM,EACN,QACA,MAAM,IAER,EAAY,GACH,EAAQ,IACjB,EAAO,KAAK,CACV,YAAa,EACb,KAAM,EACN,QACA,MAAM,IAER,EAAY,GAOV,EAAQ,GACV,EAAO,KAAK,CACV,YAAa,EACb,KAAM,EACN,QACA,MAAM,IAER,EAAY,GACH,EAAQ,IACjB,EAAO,KAAK,CACV,YAAa,EACb,KAAM,EACN,QACA,MAAM,IAER,EAAY,GAKlB,OAAO,EAGT,IAAA,CACE,EACA,EACA,EACA,EACA,EACA,GAEA,MAAQ,QAAS,EAAK,WAAY,GAAO,GACnC,QAAE,EAAA,MAAS,GAAU,EAE3B,GAAI,GAAW,GAA0B,IAAjB,EAAM,OAAc,OAE5C,MAAM,EAAO,KAAK,SACZ,EAAS,KAAK,aAAa,EAAO,EAAS,GACjD,GAAsB,IAAlB,EAAO,OAAc,OAEzB,MAAM,EAAW,KAAK,IAAI,EAAG,KAAK,MAAO,EAAW,EAAM,IACpD,EAAc,KAAK,IAAI,EAAG,KAAK,MAAM,IAE3C,EAAI,OAEJ,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAAK,CACtC,MAAM,EAAQ,EAAO,GACf,EAAK,KAAK,MAAM,EAAS,EAAM,aAAe,GAC9C,EAAQ,KAAK,MAAM,EAAS,EAAM,MAAQ,GAC1C,EAAS,KAAK,MAAM,EAAS,EAAM,OAAS,GAE5C,EAAM,KAAK,IAAI,EAAO,GAEtB,EAAS,KAAK,IAAI,EADT,KAAK,IAAI,EAAO,GACK,GAGpC,EAAI,UAAY,EAAM,KAAO,EAAK,QAAU,EAAK,UACjD,EAAI,SAAS,EAAK,EAAU,EAAgB,EAAX,EAAc,GAG/C,EAAI,YAAc,EAAM,KAAO,EAAK,QAAU,EAAK,UACnD,EAAI,UAAY,EAChB,EAAI,WAAW,EAAK,EAAW,GAAK,EAAM,GAAgB,EAAX,EAAe,EAAG,EAAS,GAG5E,EAAI"}
|
package/dist/index6.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var i=class{constructor(i){this._size=e(Math.max(i,1)),this._minTree=new Float64Array(2*this._size).fill(1/0),this._maxTree=new Float64Array(2*this._size).fill(-1/0),this._n=0}get length(){return this._n}build(i,t,s){this._n=s,s>this._size&&(this._size=e(s),this._minTree=new Float64Array(2*this._size).fill(1/0),this._maxTree=new Float64Array(2*this._size).fill(-1/0));const h=this._size;for(let e=0;e<s;e++)this._minTree[h+e]=t[e],this._maxTree[h+e]=i[e];for(let e=s;e<this._size;e++)this._minTree[h+e]=1/0,this._maxTree[h+e]=-1/0;for(let e=h-1;e>=1;e--)this._minTree[e]=Math.min(this._minTree[2*e],this._minTree[2*e+1]),this._maxTree[e]=Math.max(this._maxTree[2*e],this._maxTree[2*e+1])}update(i,e,t){let s=this._size+i;for(this._minTree[s]=t,this._maxTree[s]=e,s>>=1;s>=1;)this._minTree[s]=Math.min(this._minTree[2*s],this._minTree[2*s+1]),this._maxTree[s]=Math.max(this._maxTree[2*s],this._maxTree[2*s+1]),s>>=1}append(i,e){this._n>=this._size&&this._grow(),this._minTree[this._size+this._n]=e,this._maxTree[this._size+this._n]=i,this._n++;let t=this._size+this._n-1>>1;for(;t>=1;)this._minTree[t]=Math.min(this._minTree[2*t],this._minTree[2*t+1]),this._maxTree[t]=Math.max(this._maxTree[2*t],this._maxTree[2*t+1]),t>>=1}query(i,e){if(i>e||i>=this._n||e<0)return{min:1/0,max:-1/0};i=Math.max(0,i),e=Math.min(this._n-1,e);let t=i+this._size,s=e+this._size,h=1/0,r=-1/0;for(;t<=s;)1&t&&(h=Math.min(h,this._minTree[t]),r=Math.max(r,this._maxTree[t]),t++),1&s||(h=Math.min(h,this._minTree[s]),r=Math.max(r,this._maxTree[s]),s--),t>>=1,s>>=1;return{min:h,max:r}}_grow(){const i=2*this._size,e=new Float64Array(2*i).fill(1/0),t=new Float64Array(2*i).fill(-1/0);for(let s=0;s<this._n;s++)e[i+s]=this._minTree[this._size+s],t[i+s]=this._maxTree[this._size+s];this._size=i,this._minTree=e,this._maxTree=t;for(let s=i-1;s>=1;s--)this._minTree[s]=Math.min(this._minTree[2*s],this._minTree[2*s+1]),this._maxTree[s]=Math.max(this._maxTree[2*s],this._maxTree[2*s+1])}};function e(i){let e=1;for(;e<i;)e<<=1;return e}export{i as MinMaxSegmentTree};
|
|
2
|
+
//# sourceMappingURL=index6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index6.js","names":[],"sources":["../src/core/segment-tree.ts"],"sourcesContent":["/**\n * SegmentTree for O(log n) range min/max queries on Float64Array data.\n *\n * Supports incremental updates: when new data is appended, only the\n * affected tree nodes are rebuilt — no full reconstruction needed.\n */\nexport class MinMaxSegmentTree {\n private _minTree: Float64Array;\n private _maxTree: Float64Array;\n private _size: number; // number of leaves (rounded up to power of 2)\n private _n: number; // actual data length\n\n constructor(capacity: number) {\n this._size = nextPow2(Math.max(capacity, 1));\n this._minTree = new Float64Array(this._size * 2).fill(Infinity);\n this._maxTree = new Float64Array(this._size * 2).fill(-Infinity);\n this._n = 0;\n }\n\n get length(): number {\n return this._n;\n }\n\n /**\n * Build the tree from the given high/low arrays.\n * O(n) time.\n */\n build(high: Float64Array, low: Float64Array, length: number): void {\n this._n = length;\n\n // Ensure capacity\n if (length > this._size) {\n this._size = nextPow2(length);\n this._minTree = new Float64Array(this._size * 2).fill(Infinity);\n this._maxTree = new Float64Array(this._size * 2).fill(-Infinity);\n }\n\n // Fill leaves\n const offset = this._size;\n for (let i = 0; i < length; i++) {\n this._minTree[offset + i] = low[i];\n this._maxTree[offset + i] = high[i];\n }\n // Clear remaining leaves\n for (let i = length; i < this._size; i++) {\n this._minTree[offset + i] = Infinity;\n this._maxTree[offset + i] = -Infinity;\n }\n\n // Build internal nodes bottom-up\n for (let i = offset - 1; i >= 1; i--) {\n this._minTree[i] = Math.min(this._minTree[2 * i], this._minTree[2 * i + 1]);\n this._maxTree[i] = Math.max(this._maxTree[2 * i], this._maxTree[2 * i + 1]);\n }\n }\n\n /**\n * Update a single index (e.g., when the last bar is modified).\n * O(log n) time.\n */\n update(index: number, high: number, low: number): void {\n let pos = this._size + index;\n this._minTree[pos] = low;\n this._maxTree[pos] = high;\n pos >>= 1;\n while (pos >= 1) {\n this._minTree[pos] = Math.min(this._minTree[2 * pos], this._minTree[2 * pos + 1]);\n this._maxTree[pos] = Math.max(this._maxTree[2 * pos], this._maxTree[2 * pos + 1]);\n pos >>= 1;\n }\n }\n\n /**\n * Append a new value (for streaming data).\n * O(log n) time.\n */\n append(high: number, low: number): void {\n if (this._n >= this._size) {\n this._grow();\n }\n this._minTree[this._size + this._n] = low;\n this._maxTree[this._size + this._n] = high;\n this._n++;\n\n // Update ancestors\n let pos = (this._size + this._n - 1) >> 1;\n while (pos >= 1) {\n this._minTree[pos] = Math.min(this._minTree[2 * pos], this._minTree[2 * pos + 1]);\n this._maxTree[pos] = Math.max(this._maxTree[2 * pos], this._maxTree[2 * pos + 1]);\n pos >>= 1;\n }\n }\n\n /**\n * Query the min low and max high in the range [from, to] (inclusive).\n * O(log n) time.\n */\n query(from: number, to: number): { min: number; max: number } {\n if (from > to || from >= this._n || to < 0) {\n return { min: Infinity, max: -Infinity };\n }\n from = Math.max(0, from);\n to = Math.min(this._n - 1, to);\n\n let lo = from + this._size;\n let hi = to + this._size;\n let minVal = Infinity;\n let maxVal = -Infinity;\n\n while (lo <= hi) {\n if (lo & 1) {\n minVal = Math.min(minVal, this._minTree[lo]);\n maxVal = Math.max(maxVal, this._maxTree[lo]);\n lo++;\n }\n if (!(hi & 1)) {\n minVal = Math.min(minVal, this._minTree[hi]);\n maxVal = Math.max(maxVal, this._maxTree[hi]);\n hi--;\n }\n lo >>= 1;\n hi >>= 1;\n }\n\n return { min: minVal, max: maxVal };\n }\n\n private _grow(): void {\n const newSize = this._size * 2;\n const newMin = new Float64Array(newSize * 2).fill(Infinity);\n const newMax = new Float64Array(newSize * 2).fill(-Infinity);\n\n // Copy leaves\n for (let i = 0; i < this._n; i++) {\n newMin[newSize + i] = this._minTree[this._size + i];\n newMax[newSize + i] = this._maxTree[this._size + i];\n }\n\n this._size = newSize;\n this._minTree = newMin;\n this._maxTree = newMax;\n\n // Rebuild internal nodes\n for (let i = newSize - 1; i >= 1; i--) {\n this._minTree[i] = Math.min(this._minTree[2 * i], this._minTree[2 * i + 1]);\n this._maxTree[i] = Math.max(this._maxTree[2 * i], this._maxTree[2 * i + 1]);\n }\n }\n}\n\nfunction nextPow2(n: number): number {\n let p = 1;\n while (p < n) p <<= 1;\n return p;\n}\n"],"mappings":"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"}
|