hyperprop-charting-library 0.1.152 → 0.1.154

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.
@@ -22,6 +22,9 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  CHART_THEMES: () => CHART_THEMES,
24
24
  CHART_THEME_NAMES: () => CHART_THEME_NAMES,
25
+ DRAWING_ICON_STROKE_WIDTH: () => DRAWING_ICON_STROKE_WIDTH,
26
+ DRAWING_ICON_VIEWBOX: () => DRAWING_ICON_VIEWBOX,
27
+ DRAWING_TOOL_ICONS: () => DRAWING_TOOL_ICONS,
25
28
  FIB_DEFAULT_PALETTE: () => FIB_DEFAULT_PALETTE,
26
29
  POSITION_DEFAULT_COLORS: () => POSITION_DEFAULT_COLORS,
27
30
  SCRIPT_SOURCE_INPUT_VALUES: () => SCRIPT_SOURCE_INPUT_VALUES,
@@ -3168,6 +3171,94 @@ var compileScriptIndicator = (definition) => {
3168
3171
  return plugin;
3169
3172
  };
3170
3173
 
3174
+ // src/icons.ts
3175
+ var DRAWING_ICON_VIEWBOX = 28;
3176
+ var DRAWING_ICON_STROKE_WIDTH = 1.6;
3177
+ var dot = (cx, cy) => ({ kind: "circle", cx, cy, r: 2.1 });
3178
+ var path = (d, extra) => ({
3179
+ kind: "path",
3180
+ d,
3181
+ ...extra
3182
+ });
3183
+ var DRAWING_TOOL_ICONS = {
3184
+ "cursor-cross": [path("M14 4v6.5M14 17.5V24M4 14h6.5M17.5 14H24")],
3185
+ "cursor-dot": [{ kind: "circle", cx: 14, cy: 14, r: 2.6, fill: true }],
3186
+ "cursor-arrow": [path("M10 4.5v16.4l4.3-4.1 3 6.7 2.9-1.3-3-6.7h5.9L10 4.5Z")],
3187
+ trendline: [dot(7, 21), dot(21, 7), path("M8.6 19.4 19.4 8.6")],
3188
+ "horizontal-line": [dot(14, 14), path("M3.5 14h8.4M16.1 14h8.4")],
3189
+ "vertical-line": [dot(14, 14), path("M14 3.5v8.4M14 16.1v8.4")],
3190
+ ray: [dot(7.5, 20.5), path("M9 19 24 4")],
3191
+ arrow: [dot(6, 22), path("M7.6 20.4 21.4 6.6"), path("M14.6 6.2h7.2v7.2")],
3192
+ "parallel-channel": [dot(6, 17), dot(17, 6), path("M7.5 15.5 15.5 7.5"), path("M11 23.5 23.5 11")],
3193
+ "fib-retracement": [
3194
+ dot(6, 7),
3195
+ path("M9.6 7h14.9"),
3196
+ path("M3.5 14h21"),
3197
+ dot(6, 21),
3198
+ path("M9.6 21h14.9")
3199
+ ],
3200
+ "fib-extension": [
3201
+ dot(6.5, 21.5),
3202
+ dot(12.5, 6.5),
3203
+ path("M7.5 19.1l4-9.2"),
3204
+ path("M17 7h7.5M17 14h7.5M17 21h7.5")
3205
+ ],
3206
+ // Long/short: three price levels (target, entry, stop) with anchor dots and
3207
+ // a dotted "price path" diagonal running from entry toward the target.
3208
+ "long-position": [
3209
+ dot(5, 6.5),
3210
+ path("M8.6 6.5h15.9"),
3211
+ dot(5, 16),
3212
+ path("M8.6 16h10.3"),
3213
+ dot(21, 16),
3214
+ path("M8.6 22.5h15.9"),
3215
+ dot(5, 22.5),
3216
+ path("M10.5 14 22 7.8", { dash: "2 3.2" })
3217
+ ],
3218
+ "short-position": [
3219
+ dot(5, 21.5),
3220
+ path("M8.6 21.5h15.9"),
3221
+ dot(5, 12),
3222
+ path("M8.6 12h10.3"),
3223
+ dot(21, 12),
3224
+ path("M8.6 5.5h15.9"),
3225
+ dot(5, 5.5),
3226
+ path("M10.5 14 22 20.2", { dash: "2 3.2" })
3227
+ ],
3228
+ "price-range": [
3229
+ path("M8 5h12M8 23h12"),
3230
+ path("M14 7v14"),
3231
+ path("M11.2 9.8 14 7l2.8 2.8M11.2 18.2 14 21l2.8-2.8")
3232
+ ],
3233
+ // Fixed range VP: two vertical range anchors with the profile bars attached
3234
+ // to the left one.
3235
+ "fixed-range-volume-profile": [
3236
+ path("M5 3.5v15.4"),
3237
+ dot(5, 21.5),
3238
+ dot(23, 6.5),
3239
+ path("M23 9.1v15.4"),
3240
+ { kind: "rect", x: 5, y: 6, width: 7, height: 3.2 },
3241
+ { kind: "rect", x: 5, y: 11, width: 10.5, height: 3.2 },
3242
+ { kind: "rect", x: 5, y: 16, width: 4.5, height: 3.2 }
3243
+ ],
3244
+ measure: [
3245
+ path("M4.5 18.5 18.5 4.5l5 5L9.5 23.5Z"),
3246
+ path("m8 15 1.8 1.8M11.5 11.5 14 14M15 8l1.8 1.8")
3247
+ ],
3248
+ rectangle: [
3249
+ dot(6, 8),
3250
+ dot(22, 8),
3251
+ dot(22, 20),
3252
+ dot(6, 20),
3253
+ path("M8.1 8h11.8M8.1 20h11.8M6 10.1v7.8M22 10.1v7.8")
3254
+ ],
3255
+ ellipse: [path("M6.1 14a7.9 6.9 0 1 0 15.8 0 7.9 6.9 0 1 0-15.8 0"), dot(4, 14), dot(24, 14)],
3256
+ brush: [dot(5, 20), path("M6.9 18.4c2.6-6 5-.6 8.4-3.2 3-2.3 5.4-6 8.2-7.9")],
3257
+ text: [path("M7 8.5V6h14v2.5"), path("M14 6v16M11 22h6")],
3258
+ note: [path("M5.5 5h17v11.5l-6 6h-11V5Z"), path("M22.5 16.5h-6v6")],
3259
+ callout: [path("M4.5 6h19v11.5H13L8 22.5v-5H4.5V6Z")]
3260
+ };
3261
+
3171
3262
  // src/themes.ts
3172
3263
  var CHART_THEMES = {
3173
3264
  midnight: {
@@ -4690,9 +4781,9 @@ function createChart(element, options = {}) {
4690
4781
  const groupThousands = (value, decimals) => {
4691
4782
  const negative = value < 0;
4692
4783
  const fixed = Math.abs(value).toFixed(decimals);
4693
- const dot = fixed.indexOf(".");
4694
- const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
4695
- const decPart = dot === -1 ? "" : fixed.slice(dot);
4784
+ const dot2 = fixed.indexOf(".");
4785
+ const intPart = dot2 === -1 ? fixed : fixed.slice(0, dot2);
4786
+ const decPart = dot2 === -1 ? "" : fixed.slice(dot2);
4696
4787
  const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
4697
4788
  return `${negative ? "-" : ""}${grouped}${decPart}`;
4698
4789
  };
@@ -6289,6 +6380,8 @@ function createChart(element, options = {}) {
6289
6380
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
6290
6381
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
6291
6382
  const move = p1.price - p0.price;
6383
+ const lineLeft = Math.min(x0, x1, x2);
6384
+ const lineRight = Math.max(x0, x1, x2);
6292
6385
  const levelLines = FIB_EXT_RATIOS.map((ratio) => {
6293
6386
  const price = p2.price + move * ratio;
6294
6387
  return { ratio, price, y: yFromPrice(price) };
@@ -6301,7 +6394,7 @@ function createChart(element, options = {}) {
6301
6394
  ctx.save();
6302
6395
  ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
6303
6396
  ctx.globalAlpha = draft ? 0.5 : 1;
6304
- ctx.fillRect(chartLeft, bandTop, chartRight - chartLeft, bandBottom - bandTop);
6397
+ ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
6305
6398
  ctx.restore();
6306
6399
  }
6307
6400
  ctx.save();
@@ -6310,8 +6403,8 @@ function createChart(element, options = {}) {
6310
6403
  levelLines.forEach((level, index) => {
6311
6404
  ctx.strokeStyle = levelColorAt(index);
6312
6405
  ctx.beginPath();
6313
- ctx.moveTo(crisp(chartLeft), crisp(level.y));
6314
- ctx.lineTo(crisp(chartRight), crisp(level.y));
6406
+ ctx.moveTo(crisp(lineLeft), crisp(level.y));
6407
+ ctx.lineTo(crisp(lineRight), crisp(level.y));
6315
6408
  ctx.stroke();
6316
6409
  });
6317
6410
  ctx.restore();
@@ -6321,7 +6414,7 @@ function createChart(element, options = {}) {
6321
6414
  const labelText = `${level.ratio} (${formatPrice(level.price)})`;
6322
6415
  const textWidth = measureTextWidth(labelText);
6323
6416
  const padding = 4;
6324
- const bgX = chartLeft + 4;
6417
+ const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
6325
6418
  const bgY = level.y - 9;
6326
6419
  ctx.fillStyle = mergedOptions.backgroundColor;
6327
6420
  fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
@@ -7270,12 +7363,12 @@ function createChart(element, options = {}) {
7270
7363
  const upColumns = new Path2D();
7271
7364
  const downColumns = new Path2D();
7272
7365
  for (const column of seriesColumns) {
7273
- const path = column.close >= column.open ? upColumns : downColumns;
7366
+ const path2 = column.close >= column.open ? upColumns : downColumns;
7274
7367
  const x = column.x + 0.5;
7275
7368
  const top = crisp(yFromPrice(column.high));
7276
7369
  const bottom = crisp(yFromPrice(column.low));
7277
- path.moveTo(x, top);
7278
- path.lineTo(x, bottom === top ? bottom + 1 : bottom);
7370
+ path2.moveTo(x, top);
7371
+ path2.lineTo(x, bottom === top ? bottom + 1 : bottom);
7279
7372
  }
7280
7373
  ctx.lineWidth = 1;
7281
7374
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7418,16 +7511,16 @@ function createChart(element, options = {}) {
7418
7511
  const displayLow = isLastCandle && actualDirection === "down" ? Math.min(point.l, displayClose) : point.l;
7419
7512
  const roundedCenterX = Math.round(chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth);
7420
7513
  const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
7421
- const path = direction === "up" ? upBars : downBars;
7514
+ const path2 = direction === "up" ? upBars : downBars;
7422
7515
  const centerX = roundedCenterX + 0.5;
7423
- path.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7424
- path.lineTo(centerX, crisp(yFromPrice(displayLow)));
7516
+ path2.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7517
+ path2.lineTo(centerX, crisp(yFromPrice(displayLow)));
7425
7518
  const openY = crisp(yFromPrice(point.o));
7426
7519
  const closeY = crisp(yFromPrice(displayClose));
7427
- path.moveTo(centerX - tickLength, openY);
7428
- path.lineTo(centerX, openY);
7429
- path.moveTo(centerX, closeY);
7430
- path.lineTo(centerX + tickLength, closeY);
7520
+ path2.moveTo(centerX - tickLength, openY);
7521
+ path2.lineTo(centerX, openY);
7522
+ path2.moveTo(centerX, closeY);
7523
+ path2.lineTo(centerX + tickLength, closeY);
7431
7524
  }
7432
7525
  ctx.lineWidth = Math.max(1, candleWickWidth);
7433
7526
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7495,7 +7588,7 @@ function createChart(element, options = {}) {
7495
7588
  for (const plan of comparePlans) {
7496
7589
  const color = plan.state.options.color ?? "#f59e0b";
7497
7590
  const lineWidth = Math.max(1, plan.state.options.lineWidth ?? 1.5);
7498
- const path = new Path2D();
7591
+ const path2 = new Path2D();
7499
7592
  let started = false;
7500
7593
  let firstX = 0;
7501
7594
  let lastX = 0;
@@ -7503,11 +7596,11 @@ function createChart(element, options = {}) {
7503
7596
  let lastPrice = Number.NaN;
7504
7597
  const emit = (x, y) => {
7505
7598
  if (!started) {
7506
- path.moveTo(x, y);
7599
+ path2.moveTo(x, y);
7507
7600
  firstX = x;
7508
7601
  started = true;
7509
7602
  } else {
7510
- path.lineTo(x, y);
7603
+ path2.lineTo(x, y);
7511
7604
  }
7512
7605
  lastX = x;
7513
7606
  lastY = y;
@@ -7565,7 +7658,7 @@ function createChart(element, options = {}) {
7565
7658
  }
7566
7659
  if (!started) continue;
7567
7660
  if (plan.state.options.style === "area") {
7568
- const fillPath = new Path2D(path);
7661
+ const fillPath = new Path2D(path2);
7569
7662
  fillPath.lineTo(lastX, chartBottom);
7570
7663
  fillPath.lineTo(firstX, chartBottom);
7571
7664
  fillPath.closePath();
@@ -7579,7 +7672,7 @@ function createChart(element, options = {}) {
7579
7672
  ctx.strokeStyle = color;
7580
7673
  ctx.lineWidth = lineWidth;
7581
7674
  ctx.lineJoin = "round";
7582
- ctx.stroke(path);
7675
+ ctx.stroke(path2);
7583
7676
  ctx.restore();
7584
7677
  if (Number.isFinite(lastPrice)) {
7585
7678
  const label = plan.state.options.label ?? plan.state.options.id;
@@ -9387,12 +9480,16 @@ function createChart(element, options = {}) {
9387
9480
  if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
9388
9481
  return { drawing, target: "handle", pointIndex: 1 };
9389
9482
  }
9390
- const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9391
- for (const ratio of fibRatios) {
9392
- const price = first.price + (second.price - first.price) * (1 - ratio);
9393
- const lineY = canvasYFromDrawingPrice(price);
9394
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9395
- return { drawing, target: "line" };
9483
+ const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
9484
+ const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
9485
+ if (x >= fibLeft && x <= fibRight) {
9486
+ const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9487
+ for (const ratio of fibRatios) {
9488
+ const price = first.price + (second.price - first.price) * (1 - ratio);
9489
+ const lineY = canvasYFromDrawingPrice(price);
9490
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9491
+ return { drawing, target: "line" };
9492
+ }
9396
9493
  }
9397
9494
  }
9398
9495
  } else if (drawing.type === "fib-extension") {
@@ -9417,11 +9514,15 @@ function createChart(element, options = {}) {
9417
9514
  return { drawing, target: "handle", pointIndex: 2 };
9418
9515
  }
9419
9516
  const move = p1.price - p0.price;
9420
- const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9421
- for (const ratio of fibExtRatios) {
9422
- const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9423
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9424
- return { drawing, target: "line" };
9517
+ const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
9518
+ const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
9519
+ if (x >= extLeft && x <= extRight) {
9520
+ const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9521
+ for (const ratio of fibExtRatios) {
9522
+ const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9523
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9524
+ return { drawing, target: "line" };
9525
+ }
9425
9526
  }
9426
9527
  }
9427
9528
  if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
@@ -12376,6 +12477,9 @@ function createChart(element, options = {}) {
12376
12477
  0 && (module.exports = {
12377
12478
  CHART_THEMES,
12378
12479
  CHART_THEME_NAMES,
12480
+ DRAWING_ICON_STROKE_WIDTH,
12481
+ DRAWING_ICON_VIEWBOX,
12482
+ DRAWING_TOOL_ICONS,
12379
12483
  FIB_DEFAULT_PALETTE,
12380
12484
  POSITION_DEFAULT_COLORS,
12381
12485
  SCRIPT_SOURCE_INPUT_VALUES,
@@ -1441,6 +1441,45 @@ declare const validateScriptSource: (source: string) => string | null;
1441
1441
  */
1442
1442
  declare const compileScriptIndicator: (definition: ScriptIndicatorDefinition) => IndicatorPlugin;
1443
1443
 
1444
+ /**
1445
+ * Hyperprop drawing-tool icon pack — framework-agnostic geometry.
1446
+ *
1447
+ * Original artwork drawn in the visual language traders know from desktop
1448
+ * charting platforms: a 28x28 grid, thin round-capped outlines, and hollow
1449
+ * "anchor" dots on anything line-based (a dot marks a draggable point of the
1450
+ * tool). The data here is plain shape descriptions so every consumer renders
1451
+ * the identical set: the web terminal maps it to DOM `<svg>` elements and the
1452
+ * mobile app to react-native-svg components.
1453
+ *
1454
+ * Design rules when adding icons:
1455
+ * - viewBox 0 0 28 28, strokeWidth 1.6, round caps/joins, no fill (except
1456
+ * shapes marked `fill: true`).
1457
+ * - Anchor dots are hollow circles r=2.1; lines stop ~1.5px short of them.
1458
+ * - Keep 3.5px padding to the edges so glyphs optically match.
1459
+ */
1460
+ type DrawingIconShape = {
1461
+ kind: "path";
1462
+ d: string;
1463
+ dash?: string;
1464
+ fill?: boolean;
1465
+ } | {
1466
+ kind: "circle";
1467
+ cx: number;
1468
+ cy: number;
1469
+ r: number;
1470
+ fill?: boolean;
1471
+ } | {
1472
+ kind: "rect";
1473
+ x: number;
1474
+ y: number;
1475
+ width: number;
1476
+ height: number;
1477
+ };
1478
+ type DrawingIconName = "cursor-cross" | "cursor-dot" | "cursor-arrow" | "trendline" | "horizontal-line" | "vertical-line" | "ray" | "arrow" | "parallel-channel" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range" | "fixed-range-volume-profile" | "measure" | "rectangle" | "ellipse" | "brush" | "text" | "note" | "callout";
1479
+ declare const DRAWING_ICON_VIEWBOX = 28;
1480
+ declare const DRAWING_ICON_STROKE_WIDTH = 1.6;
1481
+ declare const DRAWING_TOOL_ICONS: Record<DrawingIconName, DrawingIconShape[]>;
1482
+
1444
1483
  /**
1445
1484
  * Built-in palettes.
1446
1485
  *
@@ -1465,4 +1504,4 @@ declare const SESSION_PRESETS: Record<SessionPresetName, SessionSpec>;
1465
1504
 
1466
1505
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
1467
1506
 
1468
- export { type AccessibilityOptions, type AlertActionEvent, type AlertCondition, type AlertOptions, type AlertTriggerEvent, type AnimationOptions, type AxisOptions, type BarMarkOptions, type BuiltInIndicatorInfo, CHART_THEMES, CHART_THEME_NAMES, type ChartClickEvent, type ChartContextMenuEvent, type ChartContextMenuRegion, type ChartDatafeed, type ChartInstance, type ChartKeyboardAction, type ChartKeyboardShortcutEvent, type ChartLongPressEvent, type ChartOptions, type ChartSavedState, type ChartTheme, type ChartThemeName, type ChartTimezone, type ChartType, type CompareSeriesOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DataLineOptions, type DatafeedBarsRequest, type DatafeedOptions, type DownsamplingOptions, type DrawingBounds, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingSelectionChangeEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type HistoryOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneActionEvent, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneHeightChangeEvent, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type IndicatorUpdateOptions, type KeyboardOptions, type LabelsOptions, type MarkClickEvent, type MarkHoverEvent, type MarkShape, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type PriceScaleMode, type PriceScaleOptions, type ReplayStartOptions, type ReplayState, SCRIPT_SOURCE_INPUT_VALUES, SESSION_PRESETS, type ScriptComputeResult, type ScriptIndicatorDefinition, type ScriptIndicatorInputDef, type ScriptInputHelper, type ScriptInputOptions, type ScriptPlotSpec, type SessionOptions, type SessionPresetName, type SessionSegment, type SessionSpec, type TickerLineOptions, type TimeFormat, type TimescaleMarkOptions, type TouchOptions, type TradeMarkerOptions, type UndoRedoState, type ViewportState, type WatermarkOptions, compileScriptIndicator, createChart, extractScriptInputs, isValidTimeZone, validateScriptSource };
1507
+ export { type AccessibilityOptions, type AlertActionEvent, type AlertCondition, type AlertOptions, type AlertTriggerEvent, type AnimationOptions, type AxisOptions, type BarMarkOptions, type BuiltInIndicatorInfo, CHART_THEMES, CHART_THEME_NAMES, type ChartClickEvent, type ChartContextMenuEvent, type ChartContextMenuRegion, type ChartDatafeed, type ChartInstance, type ChartKeyboardAction, type ChartKeyboardShortcutEvent, type ChartLongPressEvent, type ChartOptions, type ChartSavedState, type ChartTheme, type ChartThemeName, type ChartTimezone, type ChartType, type CompareSeriesOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, DRAWING_ICON_STROKE_WIDTH, DRAWING_ICON_VIEWBOX, DRAWING_TOOL_ICONS, type DashPatternOptions, type DataLineOptions, type DatafeedBarsRequest, type DatafeedOptions, type DownsamplingOptions, type DrawingBounds, type DrawingDefaults, type DrawingHoverEvent, type DrawingIconName, type DrawingIconShape, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingSelectionChangeEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type HistoryOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneActionEvent, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneHeightChangeEvent, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type IndicatorUpdateOptions, type KeyboardOptions, type LabelsOptions, type MarkClickEvent, type MarkHoverEvent, type MarkShape, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type PriceScaleMode, type PriceScaleOptions, type ReplayStartOptions, type ReplayState, SCRIPT_SOURCE_INPUT_VALUES, SESSION_PRESETS, type ScriptComputeResult, type ScriptIndicatorDefinition, type ScriptIndicatorInputDef, type ScriptInputHelper, type ScriptInputOptions, type ScriptPlotSpec, type SessionOptions, type SessionPresetName, type SessionSegment, type SessionSpec, type TickerLineOptions, type TimeFormat, type TimescaleMarkOptions, type TouchOptions, type TradeMarkerOptions, type UndoRedoState, type ViewportState, type WatermarkOptions, compileScriptIndicator, createChart, extractScriptInputs, isValidTimeZone, validateScriptSource };
@@ -3132,6 +3132,94 @@ var compileScriptIndicator = (definition) => {
3132
3132
  return plugin;
3133
3133
  };
3134
3134
 
3135
+ // src/icons.ts
3136
+ var DRAWING_ICON_VIEWBOX = 28;
3137
+ var DRAWING_ICON_STROKE_WIDTH = 1.6;
3138
+ var dot = (cx, cy) => ({ kind: "circle", cx, cy, r: 2.1 });
3139
+ var path = (d, extra) => ({
3140
+ kind: "path",
3141
+ d,
3142
+ ...extra
3143
+ });
3144
+ var DRAWING_TOOL_ICONS = {
3145
+ "cursor-cross": [path("M14 4v6.5M14 17.5V24M4 14h6.5M17.5 14H24")],
3146
+ "cursor-dot": [{ kind: "circle", cx: 14, cy: 14, r: 2.6, fill: true }],
3147
+ "cursor-arrow": [path("M10 4.5v16.4l4.3-4.1 3 6.7 2.9-1.3-3-6.7h5.9L10 4.5Z")],
3148
+ trendline: [dot(7, 21), dot(21, 7), path("M8.6 19.4 19.4 8.6")],
3149
+ "horizontal-line": [dot(14, 14), path("M3.5 14h8.4M16.1 14h8.4")],
3150
+ "vertical-line": [dot(14, 14), path("M14 3.5v8.4M14 16.1v8.4")],
3151
+ ray: [dot(7.5, 20.5), path("M9 19 24 4")],
3152
+ arrow: [dot(6, 22), path("M7.6 20.4 21.4 6.6"), path("M14.6 6.2h7.2v7.2")],
3153
+ "parallel-channel": [dot(6, 17), dot(17, 6), path("M7.5 15.5 15.5 7.5"), path("M11 23.5 23.5 11")],
3154
+ "fib-retracement": [
3155
+ dot(6, 7),
3156
+ path("M9.6 7h14.9"),
3157
+ path("M3.5 14h21"),
3158
+ dot(6, 21),
3159
+ path("M9.6 21h14.9")
3160
+ ],
3161
+ "fib-extension": [
3162
+ dot(6.5, 21.5),
3163
+ dot(12.5, 6.5),
3164
+ path("M7.5 19.1l4-9.2"),
3165
+ path("M17 7h7.5M17 14h7.5M17 21h7.5")
3166
+ ],
3167
+ // Long/short: three price levels (target, entry, stop) with anchor dots and
3168
+ // a dotted "price path" diagonal running from entry toward the target.
3169
+ "long-position": [
3170
+ dot(5, 6.5),
3171
+ path("M8.6 6.5h15.9"),
3172
+ dot(5, 16),
3173
+ path("M8.6 16h10.3"),
3174
+ dot(21, 16),
3175
+ path("M8.6 22.5h15.9"),
3176
+ dot(5, 22.5),
3177
+ path("M10.5 14 22 7.8", { dash: "2 3.2" })
3178
+ ],
3179
+ "short-position": [
3180
+ dot(5, 21.5),
3181
+ path("M8.6 21.5h15.9"),
3182
+ dot(5, 12),
3183
+ path("M8.6 12h10.3"),
3184
+ dot(21, 12),
3185
+ path("M8.6 5.5h15.9"),
3186
+ dot(5, 5.5),
3187
+ path("M10.5 14 22 20.2", { dash: "2 3.2" })
3188
+ ],
3189
+ "price-range": [
3190
+ path("M8 5h12M8 23h12"),
3191
+ path("M14 7v14"),
3192
+ path("M11.2 9.8 14 7l2.8 2.8M11.2 18.2 14 21l2.8-2.8")
3193
+ ],
3194
+ // Fixed range VP: two vertical range anchors with the profile bars attached
3195
+ // to the left one.
3196
+ "fixed-range-volume-profile": [
3197
+ path("M5 3.5v15.4"),
3198
+ dot(5, 21.5),
3199
+ dot(23, 6.5),
3200
+ path("M23 9.1v15.4"),
3201
+ { kind: "rect", x: 5, y: 6, width: 7, height: 3.2 },
3202
+ { kind: "rect", x: 5, y: 11, width: 10.5, height: 3.2 },
3203
+ { kind: "rect", x: 5, y: 16, width: 4.5, height: 3.2 }
3204
+ ],
3205
+ measure: [
3206
+ path("M4.5 18.5 18.5 4.5l5 5L9.5 23.5Z"),
3207
+ path("m8 15 1.8 1.8M11.5 11.5 14 14M15 8l1.8 1.8")
3208
+ ],
3209
+ rectangle: [
3210
+ dot(6, 8),
3211
+ dot(22, 8),
3212
+ dot(22, 20),
3213
+ dot(6, 20),
3214
+ path("M8.1 8h11.8M8.1 20h11.8M6 10.1v7.8M22 10.1v7.8")
3215
+ ],
3216
+ ellipse: [path("M6.1 14a7.9 6.9 0 1 0 15.8 0 7.9 6.9 0 1 0-15.8 0"), dot(4, 14), dot(24, 14)],
3217
+ brush: [dot(5, 20), path("M6.9 18.4c2.6-6 5-.6 8.4-3.2 3-2.3 5.4-6 8.2-7.9")],
3218
+ text: [path("M7 8.5V6h14v2.5"), path("M14 6v16M11 22h6")],
3219
+ note: [path("M5.5 5h17v11.5l-6 6h-11V5Z"), path("M22.5 16.5h-6v6")],
3220
+ callout: [path("M4.5 6h19v11.5H13L8 22.5v-5H4.5V6Z")]
3221
+ };
3222
+
3135
3223
  // src/themes.ts
3136
3224
  var CHART_THEMES = {
3137
3225
  midnight: {
@@ -4654,9 +4742,9 @@ function createChart(element, options = {}) {
4654
4742
  const groupThousands = (value, decimals) => {
4655
4743
  const negative = value < 0;
4656
4744
  const fixed = Math.abs(value).toFixed(decimals);
4657
- const dot = fixed.indexOf(".");
4658
- const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
4659
- const decPart = dot === -1 ? "" : fixed.slice(dot);
4745
+ const dot2 = fixed.indexOf(".");
4746
+ const intPart = dot2 === -1 ? fixed : fixed.slice(0, dot2);
4747
+ const decPart = dot2 === -1 ? "" : fixed.slice(dot2);
4660
4748
  const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
4661
4749
  return `${negative ? "-" : ""}${grouped}${decPart}`;
4662
4750
  };
@@ -6253,6 +6341,8 @@ function createChart(element, options = {}) {
6253
6341
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
6254
6342
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
6255
6343
  const move = p1.price - p0.price;
6344
+ const lineLeft = Math.min(x0, x1, x2);
6345
+ const lineRight = Math.max(x0, x1, x2);
6256
6346
  const levelLines = FIB_EXT_RATIOS.map((ratio) => {
6257
6347
  const price = p2.price + move * ratio;
6258
6348
  return { ratio, price, y: yFromPrice(price) };
@@ -6265,7 +6355,7 @@ function createChart(element, options = {}) {
6265
6355
  ctx.save();
6266
6356
  ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
6267
6357
  ctx.globalAlpha = draft ? 0.5 : 1;
6268
- ctx.fillRect(chartLeft, bandTop, chartRight - chartLeft, bandBottom - bandTop);
6358
+ ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
6269
6359
  ctx.restore();
6270
6360
  }
6271
6361
  ctx.save();
@@ -6274,8 +6364,8 @@ function createChart(element, options = {}) {
6274
6364
  levelLines.forEach((level, index) => {
6275
6365
  ctx.strokeStyle = levelColorAt(index);
6276
6366
  ctx.beginPath();
6277
- ctx.moveTo(crisp(chartLeft), crisp(level.y));
6278
- ctx.lineTo(crisp(chartRight), crisp(level.y));
6367
+ ctx.moveTo(crisp(lineLeft), crisp(level.y));
6368
+ ctx.lineTo(crisp(lineRight), crisp(level.y));
6279
6369
  ctx.stroke();
6280
6370
  });
6281
6371
  ctx.restore();
@@ -6285,7 +6375,7 @@ function createChart(element, options = {}) {
6285
6375
  const labelText = `${level.ratio} (${formatPrice(level.price)})`;
6286
6376
  const textWidth = measureTextWidth(labelText);
6287
6377
  const padding = 4;
6288
- const bgX = chartLeft + 4;
6378
+ const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
6289
6379
  const bgY = level.y - 9;
6290
6380
  ctx.fillStyle = mergedOptions.backgroundColor;
6291
6381
  fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
@@ -7234,12 +7324,12 @@ function createChart(element, options = {}) {
7234
7324
  const upColumns = new Path2D();
7235
7325
  const downColumns = new Path2D();
7236
7326
  for (const column of seriesColumns) {
7237
- const path = column.close >= column.open ? upColumns : downColumns;
7327
+ const path2 = column.close >= column.open ? upColumns : downColumns;
7238
7328
  const x = column.x + 0.5;
7239
7329
  const top = crisp(yFromPrice(column.high));
7240
7330
  const bottom = crisp(yFromPrice(column.low));
7241
- path.moveTo(x, top);
7242
- path.lineTo(x, bottom === top ? bottom + 1 : bottom);
7331
+ path2.moveTo(x, top);
7332
+ path2.lineTo(x, bottom === top ? bottom + 1 : bottom);
7243
7333
  }
7244
7334
  ctx.lineWidth = 1;
7245
7335
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7382,16 +7472,16 @@ function createChart(element, options = {}) {
7382
7472
  const displayLow = isLastCandle && actualDirection === "down" ? Math.min(point.l, displayClose) : point.l;
7383
7473
  const roundedCenterX = Math.round(chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth);
7384
7474
  const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
7385
- const path = direction === "up" ? upBars : downBars;
7475
+ const path2 = direction === "up" ? upBars : downBars;
7386
7476
  const centerX = roundedCenterX + 0.5;
7387
- path.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7388
- path.lineTo(centerX, crisp(yFromPrice(displayLow)));
7477
+ path2.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7478
+ path2.lineTo(centerX, crisp(yFromPrice(displayLow)));
7389
7479
  const openY = crisp(yFromPrice(point.o));
7390
7480
  const closeY = crisp(yFromPrice(displayClose));
7391
- path.moveTo(centerX - tickLength, openY);
7392
- path.lineTo(centerX, openY);
7393
- path.moveTo(centerX, closeY);
7394
- path.lineTo(centerX + tickLength, closeY);
7481
+ path2.moveTo(centerX - tickLength, openY);
7482
+ path2.lineTo(centerX, openY);
7483
+ path2.moveTo(centerX, closeY);
7484
+ path2.lineTo(centerX + tickLength, closeY);
7395
7485
  }
7396
7486
  ctx.lineWidth = Math.max(1, candleWickWidth);
7397
7487
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7459,7 +7549,7 @@ function createChart(element, options = {}) {
7459
7549
  for (const plan of comparePlans) {
7460
7550
  const color = plan.state.options.color ?? "#f59e0b";
7461
7551
  const lineWidth = Math.max(1, plan.state.options.lineWidth ?? 1.5);
7462
- const path = new Path2D();
7552
+ const path2 = new Path2D();
7463
7553
  let started = false;
7464
7554
  let firstX = 0;
7465
7555
  let lastX = 0;
@@ -7467,11 +7557,11 @@ function createChart(element, options = {}) {
7467
7557
  let lastPrice = Number.NaN;
7468
7558
  const emit = (x, y) => {
7469
7559
  if (!started) {
7470
- path.moveTo(x, y);
7560
+ path2.moveTo(x, y);
7471
7561
  firstX = x;
7472
7562
  started = true;
7473
7563
  } else {
7474
- path.lineTo(x, y);
7564
+ path2.lineTo(x, y);
7475
7565
  }
7476
7566
  lastX = x;
7477
7567
  lastY = y;
@@ -7529,7 +7619,7 @@ function createChart(element, options = {}) {
7529
7619
  }
7530
7620
  if (!started) continue;
7531
7621
  if (plan.state.options.style === "area") {
7532
- const fillPath = new Path2D(path);
7622
+ const fillPath = new Path2D(path2);
7533
7623
  fillPath.lineTo(lastX, chartBottom);
7534
7624
  fillPath.lineTo(firstX, chartBottom);
7535
7625
  fillPath.closePath();
@@ -7543,7 +7633,7 @@ function createChart(element, options = {}) {
7543
7633
  ctx.strokeStyle = color;
7544
7634
  ctx.lineWidth = lineWidth;
7545
7635
  ctx.lineJoin = "round";
7546
- ctx.stroke(path);
7636
+ ctx.stroke(path2);
7547
7637
  ctx.restore();
7548
7638
  if (Number.isFinite(lastPrice)) {
7549
7639
  const label = plan.state.options.label ?? plan.state.options.id;
@@ -9351,12 +9441,16 @@ function createChart(element, options = {}) {
9351
9441
  if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
9352
9442
  return { drawing, target: "handle", pointIndex: 1 };
9353
9443
  }
9354
- const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9355
- for (const ratio of fibRatios) {
9356
- const price = first.price + (second.price - first.price) * (1 - ratio);
9357
- const lineY = canvasYFromDrawingPrice(price);
9358
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9359
- return { drawing, target: "line" };
9444
+ const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
9445
+ const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
9446
+ if (x >= fibLeft && x <= fibRight) {
9447
+ const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9448
+ for (const ratio of fibRatios) {
9449
+ const price = first.price + (second.price - first.price) * (1 - ratio);
9450
+ const lineY = canvasYFromDrawingPrice(price);
9451
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9452
+ return { drawing, target: "line" };
9453
+ }
9360
9454
  }
9361
9455
  }
9362
9456
  } else if (drawing.type === "fib-extension") {
@@ -9381,11 +9475,15 @@ function createChart(element, options = {}) {
9381
9475
  return { drawing, target: "handle", pointIndex: 2 };
9382
9476
  }
9383
9477
  const move = p1.price - p0.price;
9384
- const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9385
- for (const ratio of fibExtRatios) {
9386
- const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9387
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9388
- return { drawing, target: "line" };
9478
+ const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
9479
+ const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
9480
+ if (x >= extLeft && x <= extRight) {
9481
+ const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9482
+ for (const ratio of fibExtRatios) {
9483
+ const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9484
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9485
+ return { drawing, target: "line" };
9486
+ }
9389
9487
  }
9390
9488
  }
9391
9489
  if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
@@ -12339,6 +12437,9 @@ function createChart(element, options = {}) {
12339
12437
  export {
12340
12438
  CHART_THEMES,
12341
12439
  CHART_THEME_NAMES,
12440
+ DRAWING_ICON_STROKE_WIDTH,
12441
+ DRAWING_ICON_VIEWBOX,
12442
+ DRAWING_TOOL_ICONS,
12342
12443
  FIB_DEFAULT_PALETTE,
12343
12444
  POSITION_DEFAULT_COLORS,
12344
12445
  SCRIPT_SOURCE_INPUT_VALUES,
package/dist/index.cjs CHANGED
@@ -22,6 +22,9 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  CHART_THEMES: () => CHART_THEMES,
24
24
  CHART_THEME_NAMES: () => CHART_THEME_NAMES,
25
+ DRAWING_ICON_STROKE_WIDTH: () => DRAWING_ICON_STROKE_WIDTH,
26
+ DRAWING_ICON_VIEWBOX: () => DRAWING_ICON_VIEWBOX,
27
+ DRAWING_TOOL_ICONS: () => DRAWING_TOOL_ICONS,
25
28
  FIB_DEFAULT_PALETTE: () => FIB_DEFAULT_PALETTE,
26
29
  POSITION_DEFAULT_COLORS: () => POSITION_DEFAULT_COLORS,
27
30
  SCRIPT_SOURCE_INPUT_VALUES: () => SCRIPT_SOURCE_INPUT_VALUES,
@@ -3168,6 +3171,94 @@ var compileScriptIndicator = (definition) => {
3168
3171
  return plugin;
3169
3172
  };
3170
3173
 
3174
+ // src/icons.ts
3175
+ var DRAWING_ICON_VIEWBOX = 28;
3176
+ var DRAWING_ICON_STROKE_WIDTH = 1.6;
3177
+ var dot = (cx, cy) => ({ kind: "circle", cx, cy, r: 2.1 });
3178
+ var path = (d, extra) => ({
3179
+ kind: "path",
3180
+ d,
3181
+ ...extra
3182
+ });
3183
+ var DRAWING_TOOL_ICONS = {
3184
+ "cursor-cross": [path("M14 4v6.5M14 17.5V24M4 14h6.5M17.5 14H24")],
3185
+ "cursor-dot": [{ kind: "circle", cx: 14, cy: 14, r: 2.6, fill: true }],
3186
+ "cursor-arrow": [path("M10 4.5v16.4l4.3-4.1 3 6.7 2.9-1.3-3-6.7h5.9L10 4.5Z")],
3187
+ trendline: [dot(7, 21), dot(21, 7), path("M8.6 19.4 19.4 8.6")],
3188
+ "horizontal-line": [dot(14, 14), path("M3.5 14h8.4M16.1 14h8.4")],
3189
+ "vertical-line": [dot(14, 14), path("M14 3.5v8.4M14 16.1v8.4")],
3190
+ ray: [dot(7.5, 20.5), path("M9 19 24 4")],
3191
+ arrow: [dot(6, 22), path("M7.6 20.4 21.4 6.6"), path("M14.6 6.2h7.2v7.2")],
3192
+ "parallel-channel": [dot(6, 17), dot(17, 6), path("M7.5 15.5 15.5 7.5"), path("M11 23.5 23.5 11")],
3193
+ "fib-retracement": [
3194
+ dot(6, 7),
3195
+ path("M9.6 7h14.9"),
3196
+ path("M3.5 14h21"),
3197
+ dot(6, 21),
3198
+ path("M9.6 21h14.9")
3199
+ ],
3200
+ "fib-extension": [
3201
+ dot(6.5, 21.5),
3202
+ dot(12.5, 6.5),
3203
+ path("M7.5 19.1l4-9.2"),
3204
+ path("M17 7h7.5M17 14h7.5M17 21h7.5")
3205
+ ],
3206
+ // Long/short: three price levels (target, entry, stop) with anchor dots and
3207
+ // a dotted "price path" diagonal running from entry toward the target.
3208
+ "long-position": [
3209
+ dot(5, 6.5),
3210
+ path("M8.6 6.5h15.9"),
3211
+ dot(5, 16),
3212
+ path("M8.6 16h10.3"),
3213
+ dot(21, 16),
3214
+ path("M8.6 22.5h15.9"),
3215
+ dot(5, 22.5),
3216
+ path("M10.5 14 22 7.8", { dash: "2 3.2" })
3217
+ ],
3218
+ "short-position": [
3219
+ dot(5, 21.5),
3220
+ path("M8.6 21.5h15.9"),
3221
+ dot(5, 12),
3222
+ path("M8.6 12h10.3"),
3223
+ dot(21, 12),
3224
+ path("M8.6 5.5h15.9"),
3225
+ dot(5, 5.5),
3226
+ path("M10.5 14 22 20.2", { dash: "2 3.2" })
3227
+ ],
3228
+ "price-range": [
3229
+ path("M8 5h12M8 23h12"),
3230
+ path("M14 7v14"),
3231
+ path("M11.2 9.8 14 7l2.8 2.8M11.2 18.2 14 21l2.8-2.8")
3232
+ ],
3233
+ // Fixed range VP: two vertical range anchors with the profile bars attached
3234
+ // to the left one.
3235
+ "fixed-range-volume-profile": [
3236
+ path("M5 3.5v15.4"),
3237
+ dot(5, 21.5),
3238
+ dot(23, 6.5),
3239
+ path("M23 9.1v15.4"),
3240
+ { kind: "rect", x: 5, y: 6, width: 7, height: 3.2 },
3241
+ { kind: "rect", x: 5, y: 11, width: 10.5, height: 3.2 },
3242
+ { kind: "rect", x: 5, y: 16, width: 4.5, height: 3.2 }
3243
+ ],
3244
+ measure: [
3245
+ path("M4.5 18.5 18.5 4.5l5 5L9.5 23.5Z"),
3246
+ path("m8 15 1.8 1.8M11.5 11.5 14 14M15 8l1.8 1.8")
3247
+ ],
3248
+ rectangle: [
3249
+ dot(6, 8),
3250
+ dot(22, 8),
3251
+ dot(22, 20),
3252
+ dot(6, 20),
3253
+ path("M8.1 8h11.8M8.1 20h11.8M6 10.1v7.8M22 10.1v7.8")
3254
+ ],
3255
+ ellipse: [path("M6.1 14a7.9 6.9 0 1 0 15.8 0 7.9 6.9 0 1 0-15.8 0"), dot(4, 14), dot(24, 14)],
3256
+ brush: [dot(5, 20), path("M6.9 18.4c2.6-6 5-.6 8.4-3.2 3-2.3 5.4-6 8.2-7.9")],
3257
+ text: [path("M7 8.5V6h14v2.5"), path("M14 6v16M11 22h6")],
3258
+ note: [path("M5.5 5h17v11.5l-6 6h-11V5Z"), path("M22.5 16.5h-6v6")],
3259
+ callout: [path("M4.5 6h19v11.5H13L8 22.5v-5H4.5V6Z")]
3260
+ };
3261
+
3171
3262
  // src/themes.ts
3172
3263
  var CHART_THEMES = {
3173
3264
  midnight: {
@@ -4690,9 +4781,9 @@ function createChart(element, options = {}) {
4690
4781
  const groupThousands = (value, decimals) => {
4691
4782
  const negative = value < 0;
4692
4783
  const fixed = Math.abs(value).toFixed(decimals);
4693
- const dot = fixed.indexOf(".");
4694
- const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
4695
- const decPart = dot === -1 ? "" : fixed.slice(dot);
4784
+ const dot2 = fixed.indexOf(".");
4785
+ const intPart = dot2 === -1 ? fixed : fixed.slice(0, dot2);
4786
+ const decPart = dot2 === -1 ? "" : fixed.slice(dot2);
4696
4787
  const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
4697
4788
  return `${negative ? "-" : ""}${grouped}${decPart}`;
4698
4789
  };
@@ -6289,6 +6380,8 @@ function createChart(element, options = {}) {
6289
6380
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
6290
6381
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
6291
6382
  const move = p1.price - p0.price;
6383
+ const lineLeft = Math.min(x0, x1, x2);
6384
+ const lineRight = Math.max(x0, x1, x2);
6292
6385
  const levelLines = FIB_EXT_RATIOS.map((ratio) => {
6293
6386
  const price = p2.price + move * ratio;
6294
6387
  return { ratio, price, y: yFromPrice(price) };
@@ -6301,7 +6394,7 @@ function createChart(element, options = {}) {
6301
6394
  ctx.save();
6302
6395
  ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
6303
6396
  ctx.globalAlpha = draft ? 0.5 : 1;
6304
- ctx.fillRect(chartLeft, bandTop, chartRight - chartLeft, bandBottom - bandTop);
6397
+ ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
6305
6398
  ctx.restore();
6306
6399
  }
6307
6400
  ctx.save();
@@ -6310,8 +6403,8 @@ function createChart(element, options = {}) {
6310
6403
  levelLines.forEach((level, index) => {
6311
6404
  ctx.strokeStyle = levelColorAt(index);
6312
6405
  ctx.beginPath();
6313
- ctx.moveTo(crisp(chartLeft), crisp(level.y));
6314
- ctx.lineTo(crisp(chartRight), crisp(level.y));
6406
+ ctx.moveTo(crisp(lineLeft), crisp(level.y));
6407
+ ctx.lineTo(crisp(lineRight), crisp(level.y));
6315
6408
  ctx.stroke();
6316
6409
  });
6317
6410
  ctx.restore();
@@ -6321,7 +6414,7 @@ function createChart(element, options = {}) {
6321
6414
  const labelText = `${level.ratio} (${formatPrice(level.price)})`;
6322
6415
  const textWidth = measureTextWidth(labelText);
6323
6416
  const padding = 4;
6324
- const bgX = chartLeft + 4;
6417
+ const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
6325
6418
  const bgY = level.y - 9;
6326
6419
  ctx.fillStyle = mergedOptions.backgroundColor;
6327
6420
  fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
@@ -7270,12 +7363,12 @@ function createChart(element, options = {}) {
7270
7363
  const upColumns = new Path2D();
7271
7364
  const downColumns = new Path2D();
7272
7365
  for (const column of seriesColumns) {
7273
- const path = column.close >= column.open ? upColumns : downColumns;
7366
+ const path2 = column.close >= column.open ? upColumns : downColumns;
7274
7367
  const x = column.x + 0.5;
7275
7368
  const top = crisp(yFromPrice(column.high));
7276
7369
  const bottom = crisp(yFromPrice(column.low));
7277
- path.moveTo(x, top);
7278
- path.lineTo(x, bottom === top ? bottom + 1 : bottom);
7370
+ path2.moveTo(x, top);
7371
+ path2.lineTo(x, bottom === top ? bottom + 1 : bottom);
7279
7372
  }
7280
7373
  ctx.lineWidth = 1;
7281
7374
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7418,16 +7511,16 @@ function createChart(element, options = {}) {
7418
7511
  const displayLow = isLastCandle && actualDirection === "down" ? Math.min(point.l, displayClose) : point.l;
7419
7512
  const roundedCenterX = Math.round(chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth);
7420
7513
  const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
7421
- const path = direction === "up" ? upBars : downBars;
7514
+ const path2 = direction === "up" ? upBars : downBars;
7422
7515
  const centerX = roundedCenterX + 0.5;
7423
- path.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7424
- path.lineTo(centerX, crisp(yFromPrice(displayLow)));
7516
+ path2.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7517
+ path2.lineTo(centerX, crisp(yFromPrice(displayLow)));
7425
7518
  const openY = crisp(yFromPrice(point.o));
7426
7519
  const closeY = crisp(yFromPrice(displayClose));
7427
- path.moveTo(centerX - tickLength, openY);
7428
- path.lineTo(centerX, openY);
7429
- path.moveTo(centerX, closeY);
7430
- path.lineTo(centerX + tickLength, closeY);
7520
+ path2.moveTo(centerX - tickLength, openY);
7521
+ path2.lineTo(centerX, openY);
7522
+ path2.moveTo(centerX, closeY);
7523
+ path2.lineTo(centerX + tickLength, closeY);
7431
7524
  }
7432
7525
  ctx.lineWidth = Math.max(1, candleWickWidth);
7433
7526
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7495,7 +7588,7 @@ function createChart(element, options = {}) {
7495
7588
  for (const plan of comparePlans) {
7496
7589
  const color = plan.state.options.color ?? "#f59e0b";
7497
7590
  const lineWidth = Math.max(1, plan.state.options.lineWidth ?? 1.5);
7498
- const path = new Path2D();
7591
+ const path2 = new Path2D();
7499
7592
  let started = false;
7500
7593
  let firstX = 0;
7501
7594
  let lastX = 0;
@@ -7503,11 +7596,11 @@ function createChart(element, options = {}) {
7503
7596
  let lastPrice = Number.NaN;
7504
7597
  const emit = (x, y) => {
7505
7598
  if (!started) {
7506
- path.moveTo(x, y);
7599
+ path2.moveTo(x, y);
7507
7600
  firstX = x;
7508
7601
  started = true;
7509
7602
  } else {
7510
- path.lineTo(x, y);
7603
+ path2.lineTo(x, y);
7511
7604
  }
7512
7605
  lastX = x;
7513
7606
  lastY = y;
@@ -7565,7 +7658,7 @@ function createChart(element, options = {}) {
7565
7658
  }
7566
7659
  if (!started) continue;
7567
7660
  if (plan.state.options.style === "area") {
7568
- const fillPath = new Path2D(path);
7661
+ const fillPath = new Path2D(path2);
7569
7662
  fillPath.lineTo(lastX, chartBottom);
7570
7663
  fillPath.lineTo(firstX, chartBottom);
7571
7664
  fillPath.closePath();
@@ -7579,7 +7672,7 @@ function createChart(element, options = {}) {
7579
7672
  ctx.strokeStyle = color;
7580
7673
  ctx.lineWidth = lineWidth;
7581
7674
  ctx.lineJoin = "round";
7582
- ctx.stroke(path);
7675
+ ctx.stroke(path2);
7583
7676
  ctx.restore();
7584
7677
  if (Number.isFinite(lastPrice)) {
7585
7678
  const label = plan.state.options.label ?? plan.state.options.id;
@@ -9387,12 +9480,16 @@ function createChart(element, options = {}) {
9387
9480
  if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
9388
9481
  return { drawing, target: "handle", pointIndex: 1 };
9389
9482
  }
9390
- const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9391
- for (const ratio of fibRatios) {
9392
- const price = first.price + (second.price - first.price) * (1 - ratio);
9393
- const lineY = canvasYFromDrawingPrice(price);
9394
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9395
- return { drawing, target: "line" };
9483
+ const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
9484
+ const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
9485
+ if (x >= fibLeft && x <= fibRight) {
9486
+ const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9487
+ for (const ratio of fibRatios) {
9488
+ const price = first.price + (second.price - first.price) * (1 - ratio);
9489
+ const lineY = canvasYFromDrawingPrice(price);
9490
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9491
+ return { drawing, target: "line" };
9492
+ }
9396
9493
  }
9397
9494
  }
9398
9495
  } else if (drawing.type === "fib-extension") {
@@ -9417,11 +9514,15 @@ function createChart(element, options = {}) {
9417
9514
  return { drawing, target: "handle", pointIndex: 2 };
9418
9515
  }
9419
9516
  const move = p1.price - p0.price;
9420
- const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9421
- for (const ratio of fibExtRatios) {
9422
- const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9423
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9424
- return { drawing, target: "line" };
9517
+ const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
9518
+ const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
9519
+ if (x >= extLeft && x <= extRight) {
9520
+ const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9521
+ for (const ratio of fibExtRatios) {
9522
+ const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9523
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9524
+ return { drawing, target: "line" };
9525
+ }
9425
9526
  }
9426
9527
  }
9427
9528
  if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
@@ -12376,6 +12477,9 @@ function createChart(element, options = {}) {
12376
12477
  0 && (module.exports = {
12377
12478
  CHART_THEMES,
12378
12479
  CHART_THEME_NAMES,
12480
+ DRAWING_ICON_STROKE_WIDTH,
12481
+ DRAWING_ICON_VIEWBOX,
12482
+ DRAWING_TOOL_ICONS,
12379
12483
  FIB_DEFAULT_PALETTE,
12380
12484
  POSITION_DEFAULT_COLORS,
12381
12485
  SCRIPT_SOURCE_INPUT_VALUES,
package/dist/index.d.cts CHANGED
@@ -1441,6 +1441,45 @@ declare const validateScriptSource: (source: string) => string | null;
1441
1441
  */
1442
1442
  declare const compileScriptIndicator: (definition: ScriptIndicatorDefinition) => IndicatorPlugin;
1443
1443
 
1444
+ /**
1445
+ * Hyperprop drawing-tool icon pack — framework-agnostic geometry.
1446
+ *
1447
+ * Original artwork drawn in the visual language traders know from desktop
1448
+ * charting platforms: a 28x28 grid, thin round-capped outlines, and hollow
1449
+ * "anchor" dots on anything line-based (a dot marks a draggable point of the
1450
+ * tool). The data here is plain shape descriptions so every consumer renders
1451
+ * the identical set: the web terminal maps it to DOM `<svg>` elements and the
1452
+ * mobile app to react-native-svg components.
1453
+ *
1454
+ * Design rules when adding icons:
1455
+ * - viewBox 0 0 28 28, strokeWidth 1.6, round caps/joins, no fill (except
1456
+ * shapes marked `fill: true`).
1457
+ * - Anchor dots are hollow circles r=2.1; lines stop ~1.5px short of them.
1458
+ * - Keep 3.5px padding to the edges so glyphs optically match.
1459
+ */
1460
+ type DrawingIconShape = {
1461
+ kind: "path";
1462
+ d: string;
1463
+ dash?: string;
1464
+ fill?: boolean;
1465
+ } | {
1466
+ kind: "circle";
1467
+ cx: number;
1468
+ cy: number;
1469
+ r: number;
1470
+ fill?: boolean;
1471
+ } | {
1472
+ kind: "rect";
1473
+ x: number;
1474
+ y: number;
1475
+ width: number;
1476
+ height: number;
1477
+ };
1478
+ type DrawingIconName = "cursor-cross" | "cursor-dot" | "cursor-arrow" | "trendline" | "horizontal-line" | "vertical-line" | "ray" | "arrow" | "parallel-channel" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range" | "fixed-range-volume-profile" | "measure" | "rectangle" | "ellipse" | "brush" | "text" | "note" | "callout";
1479
+ declare const DRAWING_ICON_VIEWBOX = 28;
1480
+ declare const DRAWING_ICON_STROKE_WIDTH = 1.6;
1481
+ declare const DRAWING_TOOL_ICONS: Record<DrawingIconName, DrawingIconShape[]>;
1482
+
1444
1483
  /**
1445
1484
  * Built-in palettes.
1446
1485
  *
@@ -1465,4 +1504,4 @@ declare const SESSION_PRESETS: Record<SessionPresetName, SessionSpec>;
1465
1504
 
1466
1505
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
1467
1506
 
1468
- export { type AccessibilityOptions, type AlertActionEvent, type AlertCondition, type AlertOptions, type AlertTriggerEvent, type AnimationOptions, type AxisOptions, type BarMarkOptions, type BuiltInIndicatorInfo, CHART_THEMES, CHART_THEME_NAMES, type ChartClickEvent, type ChartContextMenuEvent, type ChartContextMenuRegion, type ChartDatafeed, type ChartInstance, type ChartKeyboardAction, type ChartKeyboardShortcutEvent, type ChartLongPressEvent, type ChartOptions, type ChartSavedState, type ChartTheme, type ChartThemeName, type ChartTimezone, type ChartType, type CompareSeriesOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DataLineOptions, type DatafeedBarsRequest, type DatafeedOptions, type DownsamplingOptions, type DrawingBounds, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingSelectionChangeEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type HistoryOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneActionEvent, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneHeightChangeEvent, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type IndicatorUpdateOptions, type KeyboardOptions, type LabelsOptions, type MarkClickEvent, type MarkHoverEvent, type MarkShape, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type PriceScaleMode, type PriceScaleOptions, type ReplayStartOptions, type ReplayState, SCRIPT_SOURCE_INPUT_VALUES, SESSION_PRESETS, type ScriptComputeResult, type ScriptIndicatorDefinition, type ScriptIndicatorInputDef, type ScriptInputHelper, type ScriptInputOptions, type ScriptPlotSpec, type SessionOptions, type SessionPresetName, type SessionSegment, type SessionSpec, type TickerLineOptions, type TimeFormat, type TimescaleMarkOptions, type TouchOptions, type TradeMarkerOptions, type UndoRedoState, type ViewportState, type WatermarkOptions, compileScriptIndicator, createChart, extractScriptInputs, isValidTimeZone, validateScriptSource };
1507
+ export { type AccessibilityOptions, type AlertActionEvent, type AlertCondition, type AlertOptions, type AlertTriggerEvent, type AnimationOptions, type AxisOptions, type BarMarkOptions, type BuiltInIndicatorInfo, CHART_THEMES, CHART_THEME_NAMES, type ChartClickEvent, type ChartContextMenuEvent, type ChartContextMenuRegion, type ChartDatafeed, type ChartInstance, type ChartKeyboardAction, type ChartKeyboardShortcutEvent, type ChartLongPressEvent, type ChartOptions, type ChartSavedState, type ChartTheme, type ChartThemeName, type ChartTimezone, type ChartType, type CompareSeriesOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, DRAWING_ICON_STROKE_WIDTH, DRAWING_ICON_VIEWBOX, DRAWING_TOOL_ICONS, type DashPatternOptions, type DataLineOptions, type DatafeedBarsRequest, type DatafeedOptions, type DownsamplingOptions, type DrawingBounds, type DrawingDefaults, type DrawingHoverEvent, type DrawingIconName, type DrawingIconShape, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingSelectionChangeEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type HistoryOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneActionEvent, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneHeightChangeEvent, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type IndicatorUpdateOptions, type KeyboardOptions, type LabelsOptions, type MarkClickEvent, type MarkHoverEvent, type MarkShape, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type PriceScaleMode, type PriceScaleOptions, type ReplayStartOptions, type ReplayState, SCRIPT_SOURCE_INPUT_VALUES, SESSION_PRESETS, type ScriptComputeResult, type ScriptIndicatorDefinition, type ScriptIndicatorInputDef, type ScriptInputHelper, type ScriptInputOptions, type ScriptPlotSpec, type SessionOptions, type SessionPresetName, type SessionSegment, type SessionSpec, type TickerLineOptions, type TimeFormat, type TimescaleMarkOptions, type TouchOptions, type TradeMarkerOptions, type UndoRedoState, type ViewportState, type WatermarkOptions, compileScriptIndicator, createChart, extractScriptInputs, isValidTimeZone, validateScriptSource };
package/dist/index.d.ts CHANGED
@@ -1441,6 +1441,45 @@ declare const validateScriptSource: (source: string) => string | null;
1441
1441
  */
1442
1442
  declare const compileScriptIndicator: (definition: ScriptIndicatorDefinition) => IndicatorPlugin;
1443
1443
 
1444
+ /**
1445
+ * Hyperprop drawing-tool icon pack — framework-agnostic geometry.
1446
+ *
1447
+ * Original artwork drawn in the visual language traders know from desktop
1448
+ * charting platforms: a 28x28 grid, thin round-capped outlines, and hollow
1449
+ * "anchor" dots on anything line-based (a dot marks a draggable point of the
1450
+ * tool). The data here is plain shape descriptions so every consumer renders
1451
+ * the identical set: the web terminal maps it to DOM `<svg>` elements and the
1452
+ * mobile app to react-native-svg components.
1453
+ *
1454
+ * Design rules when adding icons:
1455
+ * - viewBox 0 0 28 28, strokeWidth 1.6, round caps/joins, no fill (except
1456
+ * shapes marked `fill: true`).
1457
+ * - Anchor dots are hollow circles r=2.1; lines stop ~1.5px short of them.
1458
+ * - Keep 3.5px padding to the edges so glyphs optically match.
1459
+ */
1460
+ type DrawingIconShape = {
1461
+ kind: "path";
1462
+ d: string;
1463
+ dash?: string;
1464
+ fill?: boolean;
1465
+ } | {
1466
+ kind: "circle";
1467
+ cx: number;
1468
+ cy: number;
1469
+ r: number;
1470
+ fill?: boolean;
1471
+ } | {
1472
+ kind: "rect";
1473
+ x: number;
1474
+ y: number;
1475
+ width: number;
1476
+ height: number;
1477
+ };
1478
+ type DrawingIconName = "cursor-cross" | "cursor-dot" | "cursor-arrow" | "trendline" | "horizontal-line" | "vertical-line" | "ray" | "arrow" | "parallel-channel" | "fib-retracement" | "fib-extension" | "long-position" | "short-position" | "price-range" | "fixed-range-volume-profile" | "measure" | "rectangle" | "ellipse" | "brush" | "text" | "note" | "callout";
1479
+ declare const DRAWING_ICON_VIEWBOX = 28;
1480
+ declare const DRAWING_ICON_STROKE_WIDTH = 1.6;
1481
+ declare const DRAWING_TOOL_ICONS: Record<DrawingIconName, DrawingIconShape[]>;
1482
+
1444
1483
  /**
1445
1484
  * Built-in palettes.
1446
1485
  *
@@ -1465,4 +1504,4 @@ declare const SESSION_PRESETS: Record<SessionPresetName, SessionSpec>;
1465
1504
 
1466
1505
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
1467
1506
 
1468
- export { type AccessibilityOptions, type AlertActionEvent, type AlertCondition, type AlertOptions, type AlertTriggerEvent, type AnimationOptions, type AxisOptions, type BarMarkOptions, type BuiltInIndicatorInfo, CHART_THEMES, CHART_THEME_NAMES, type ChartClickEvent, type ChartContextMenuEvent, type ChartContextMenuRegion, type ChartDatafeed, type ChartInstance, type ChartKeyboardAction, type ChartKeyboardShortcutEvent, type ChartLongPressEvent, type ChartOptions, type ChartSavedState, type ChartTheme, type ChartThemeName, type ChartTimezone, type ChartType, type CompareSeriesOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DataLineOptions, type DatafeedBarsRequest, type DatafeedOptions, type DownsamplingOptions, type DrawingBounds, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingSelectionChangeEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type HistoryOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneActionEvent, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneHeightChangeEvent, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type IndicatorUpdateOptions, type KeyboardOptions, type LabelsOptions, type MarkClickEvent, type MarkHoverEvent, type MarkShape, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type PriceScaleMode, type PriceScaleOptions, type ReplayStartOptions, type ReplayState, SCRIPT_SOURCE_INPUT_VALUES, SESSION_PRESETS, type ScriptComputeResult, type ScriptIndicatorDefinition, type ScriptIndicatorInputDef, type ScriptInputHelper, type ScriptInputOptions, type ScriptPlotSpec, type SessionOptions, type SessionPresetName, type SessionSegment, type SessionSpec, type TickerLineOptions, type TimeFormat, type TimescaleMarkOptions, type TouchOptions, type TradeMarkerOptions, type UndoRedoState, type ViewportState, type WatermarkOptions, compileScriptIndicator, createChart, extractScriptInputs, isValidTimeZone, validateScriptSource };
1507
+ export { type AccessibilityOptions, type AlertActionEvent, type AlertCondition, type AlertOptions, type AlertTriggerEvent, type AnimationOptions, type AxisOptions, type BarMarkOptions, type BuiltInIndicatorInfo, CHART_THEMES, CHART_THEME_NAMES, type ChartClickEvent, type ChartContextMenuEvent, type ChartContextMenuRegion, type ChartDatafeed, type ChartInstance, type ChartKeyboardAction, type ChartKeyboardShortcutEvent, type ChartLongPressEvent, type ChartOptions, type ChartSavedState, type ChartTheme, type ChartThemeName, type ChartTimezone, type ChartType, type CompareSeriesOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, DRAWING_ICON_STROKE_WIDTH, DRAWING_ICON_VIEWBOX, DRAWING_TOOL_ICONS, type DashPatternOptions, type DataLineOptions, type DatafeedBarsRequest, type DatafeedOptions, type DownsamplingOptions, type DrawingBounds, type DrawingDefaults, type DrawingHoverEvent, type DrawingIconName, type DrawingIconShape, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingSelectionChangeEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type HistoryOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneActionEvent, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneHeightChangeEvent, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type IndicatorUpdateOptions, type KeyboardOptions, type LabelsOptions, type MarkClickEvent, type MarkHoverEvent, type MarkShape, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type PriceScaleMode, type PriceScaleOptions, type ReplayStartOptions, type ReplayState, SCRIPT_SOURCE_INPUT_VALUES, SESSION_PRESETS, type ScriptComputeResult, type ScriptIndicatorDefinition, type ScriptIndicatorInputDef, type ScriptInputHelper, type ScriptInputOptions, type ScriptPlotSpec, type SessionOptions, type SessionPresetName, type SessionSegment, type SessionSpec, type TickerLineOptions, type TimeFormat, type TimescaleMarkOptions, type TouchOptions, type TradeMarkerOptions, type UndoRedoState, type ViewportState, type WatermarkOptions, compileScriptIndicator, createChart, extractScriptInputs, isValidTimeZone, validateScriptSource };
package/dist/index.js CHANGED
@@ -3132,6 +3132,94 @@ var compileScriptIndicator = (definition) => {
3132
3132
  return plugin;
3133
3133
  };
3134
3134
 
3135
+ // src/icons.ts
3136
+ var DRAWING_ICON_VIEWBOX = 28;
3137
+ var DRAWING_ICON_STROKE_WIDTH = 1.6;
3138
+ var dot = (cx, cy) => ({ kind: "circle", cx, cy, r: 2.1 });
3139
+ var path = (d, extra) => ({
3140
+ kind: "path",
3141
+ d,
3142
+ ...extra
3143
+ });
3144
+ var DRAWING_TOOL_ICONS = {
3145
+ "cursor-cross": [path("M14 4v6.5M14 17.5V24M4 14h6.5M17.5 14H24")],
3146
+ "cursor-dot": [{ kind: "circle", cx: 14, cy: 14, r: 2.6, fill: true }],
3147
+ "cursor-arrow": [path("M10 4.5v16.4l4.3-4.1 3 6.7 2.9-1.3-3-6.7h5.9L10 4.5Z")],
3148
+ trendline: [dot(7, 21), dot(21, 7), path("M8.6 19.4 19.4 8.6")],
3149
+ "horizontal-line": [dot(14, 14), path("M3.5 14h8.4M16.1 14h8.4")],
3150
+ "vertical-line": [dot(14, 14), path("M14 3.5v8.4M14 16.1v8.4")],
3151
+ ray: [dot(7.5, 20.5), path("M9 19 24 4")],
3152
+ arrow: [dot(6, 22), path("M7.6 20.4 21.4 6.6"), path("M14.6 6.2h7.2v7.2")],
3153
+ "parallel-channel": [dot(6, 17), dot(17, 6), path("M7.5 15.5 15.5 7.5"), path("M11 23.5 23.5 11")],
3154
+ "fib-retracement": [
3155
+ dot(6, 7),
3156
+ path("M9.6 7h14.9"),
3157
+ path("M3.5 14h21"),
3158
+ dot(6, 21),
3159
+ path("M9.6 21h14.9")
3160
+ ],
3161
+ "fib-extension": [
3162
+ dot(6.5, 21.5),
3163
+ dot(12.5, 6.5),
3164
+ path("M7.5 19.1l4-9.2"),
3165
+ path("M17 7h7.5M17 14h7.5M17 21h7.5")
3166
+ ],
3167
+ // Long/short: three price levels (target, entry, stop) with anchor dots and
3168
+ // a dotted "price path" diagonal running from entry toward the target.
3169
+ "long-position": [
3170
+ dot(5, 6.5),
3171
+ path("M8.6 6.5h15.9"),
3172
+ dot(5, 16),
3173
+ path("M8.6 16h10.3"),
3174
+ dot(21, 16),
3175
+ path("M8.6 22.5h15.9"),
3176
+ dot(5, 22.5),
3177
+ path("M10.5 14 22 7.8", { dash: "2 3.2" })
3178
+ ],
3179
+ "short-position": [
3180
+ dot(5, 21.5),
3181
+ path("M8.6 21.5h15.9"),
3182
+ dot(5, 12),
3183
+ path("M8.6 12h10.3"),
3184
+ dot(21, 12),
3185
+ path("M8.6 5.5h15.9"),
3186
+ dot(5, 5.5),
3187
+ path("M10.5 14 22 20.2", { dash: "2 3.2" })
3188
+ ],
3189
+ "price-range": [
3190
+ path("M8 5h12M8 23h12"),
3191
+ path("M14 7v14"),
3192
+ path("M11.2 9.8 14 7l2.8 2.8M11.2 18.2 14 21l2.8-2.8")
3193
+ ],
3194
+ // Fixed range VP: two vertical range anchors with the profile bars attached
3195
+ // to the left one.
3196
+ "fixed-range-volume-profile": [
3197
+ path("M5 3.5v15.4"),
3198
+ dot(5, 21.5),
3199
+ dot(23, 6.5),
3200
+ path("M23 9.1v15.4"),
3201
+ { kind: "rect", x: 5, y: 6, width: 7, height: 3.2 },
3202
+ { kind: "rect", x: 5, y: 11, width: 10.5, height: 3.2 },
3203
+ { kind: "rect", x: 5, y: 16, width: 4.5, height: 3.2 }
3204
+ ],
3205
+ measure: [
3206
+ path("M4.5 18.5 18.5 4.5l5 5L9.5 23.5Z"),
3207
+ path("m8 15 1.8 1.8M11.5 11.5 14 14M15 8l1.8 1.8")
3208
+ ],
3209
+ rectangle: [
3210
+ dot(6, 8),
3211
+ dot(22, 8),
3212
+ dot(22, 20),
3213
+ dot(6, 20),
3214
+ path("M8.1 8h11.8M8.1 20h11.8M6 10.1v7.8M22 10.1v7.8")
3215
+ ],
3216
+ ellipse: [path("M6.1 14a7.9 6.9 0 1 0 15.8 0 7.9 6.9 0 1 0-15.8 0"), dot(4, 14), dot(24, 14)],
3217
+ brush: [dot(5, 20), path("M6.9 18.4c2.6-6 5-.6 8.4-3.2 3-2.3 5.4-6 8.2-7.9")],
3218
+ text: [path("M7 8.5V6h14v2.5"), path("M14 6v16M11 22h6")],
3219
+ note: [path("M5.5 5h17v11.5l-6 6h-11V5Z"), path("M22.5 16.5h-6v6")],
3220
+ callout: [path("M4.5 6h19v11.5H13L8 22.5v-5H4.5V6Z")]
3221
+ };
3222
+
3135
3223
  // src/themes.ts
3136
3224
  var CHART_THEMES = {
3137
3225
  midnight: {
@@ -4654,9 +4742,9 @@ function createChart(element, options = {}) {
4654
4742
  const groupThousands = (value, decimals) => {
4655
4743
  const negative = value < 0;
4656
4744
  const fixed = Math.abs(value).toFixed(decimals);
4657
- const dot = fixed.indexOf(".");
4658
- const intPart = dot === -1 ? fixed : fixed.slice(0, dot);
4659
- const decPart = dot === -1 ? "" : fixed.slice(dot);
4745
+ const dot2 = fixed.indexOf(".");
4746
+ const intPart = dot2 === -1 ? fixed : fixed.slice(0, dot2);
4747
+ const decPart = dot2 === -1 ? "" : fixed.slice(dot2);
4660
4748
  const grouped = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
4661
4749
  return `${negative ? "-" : ""}${grouped}${decPart}`;
4662
4750
  };
@@ -6253,6 +6341,8 @@ function createChart(element, options = {}) {
6253
6341
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
6254
6342
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
6255
6343
  const move = p1.price - p0.price;
6344
+ const lineLeft = Math.min(x0, x1, x2);
6345
+ const lineRight = Math.max(x0, x1, x2);
6256
6346
  const levelLines = FIB_EXT_RATIOS.map((ratio) => {
6257
6347
  const price = p2.price + move * ratio;
6258
6348
  return { ratio, price, y: yFromPrice(price) };
@@ -6265,7 +6355,7 @@ function createChart(element, options = {}) {
6265
6355
  ctx.save();
6266
6356
  ctx.fillStyle = hexToRgba(levelColorAt(index), 0.1);
6267
6357
  ctx.globalAlpha = draft ? 0.5 : 1;
6268
- ctx.fillRect(chartLeft, bandTop, chartRight - chartLeft, bandBottom - bandTop);
6358
+ ctx.fillRect(lineLeft, bandTop, lineRight - lineLeft, bandBottom - bandTop);
6269
6359
  ctx.restore();
6270
6360
  }
6271
6361
  ctx.save();
@@ -6274,8 +6364,8 @@ function createChart(element, options = {}) {
6274
6364
  levelLines.forEach((level, index) => {
6275
6365
  ctx.strokeStyle = levelColorAt(index);
6276
6366
  ctx.beginPath();
6277
- ctx.moveTo(crisp(chartLeft), crisp(level.y));
6278
- ctx.lineTo(crisp(chartRight), crisp(level.y));
6367
+ ctx.moveTo(crisp(lineLeft), crisp(level.y));
6368
+ ctx.lineTo(crisp(lineRight), crisp(level.y));
6279
6369
  ctx.stroke();
6280
6370
  });
6281
6371
  ctx.restore();
@@ -6285,7 +6375,7 @@ function createChart(element, options = {}) {
6285
6375
  const labelText = `${level.ratio} (${formatPrice(level.price)})`;
6286
6376
  const textWidth = measureTextWidth(labelText);
6287
6377
  const padding = 4;
6288
- const bgX = chartLeft + 4;
6378
+ const bgX = Math.max(chartLeft + 2, lineLeft - textWidth - padding * 2 - 4);
6289
6379
  const bgY = level.y - 9;
6290
6380
  ctx.fillStyle = mergedOptions.backgroundColor;
6291
6381
  fillRoundedRect(bgX, bgY, textWidth + padding * 2, 16, 3);
@@ -7234,12 +7324,12 @@ function createChart(element, options = {}) {
7234
7324
  const upColumns = new Path2D();
7235
7325
  const downColumns = new Path2D();
7236
7326
  for (const column of seriesColumns) {
7237
- const path = column.close >= column.open ? upColumns : downColumns;
7327
+ const path2 = column.close >= column.open ? upColumns : downColumns;
7238
7328
  const x = column.x + 0.5;
7239
7329
  const top = crisp(yFromPrice(column.high));
7240
7330
  const bottom = crisp(yFromPrice(column.low));
7241
- path.moveTo(x, top);
7242
- path.lineTo(x, bottom === top ? bottom + 1 : bottom);
7331
+ path2.moveTo(x, top);
7332
+ path2.lineTo(x, bottom === top ? bottom + 1 : bottom);
7243
7333
  }
7244
7334
  ctx.lineWidth = 1;
7245
7335
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7382,16 +7472,16 @@ function createChart(element, options = {}) {
7382
7472
  const displayLow = isLastCandle && actualDirection === "down" ? Math.min(point.l, displayClose) : point.l;
7383
7473
  const roundedCenterX = Math.round(chartLeft + (index + 0.5 - xStart) / xSpan * chartWidth);
7384
7474
  const direction = isLastCandle ? actualDirection : getCandleDirectionByIndex(index);
7385
- const path = direction === "up" ? upBars : downBars;
7475
+ const path2 = direction === "up" ? upBars : downBars;
7386
7476
  const centerX = roundedCenterX + 0.5;
7387
- path.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7388
- path.lineTo(centerX, crisp(yFromPrice(displayLow)));
7477
+ path2.moveTo(centerX, crisp(yFromPrice(displayHigh)));
7478
+ path2.lineTo(centerX, crisp(yFromPrice(displayLow)));
7389
7479
  const openY = crisp(yFromPrice(point.o));
7390
7480
  const closeY = crisp(yFromPrice(displayClose));
7391
- path.moveTo(centerX - tickLength, openY);
7392
- path.lineTo(centerX, openY);
7393
- path.moveTo(centerX, closeY);
7394
- path.lineTo(centerX + tickLength, closeY);
7481
+ path2.moveTo(centerX - tickLength, openY);
7482
+ path2.lineTo(centerX, openY);
7483
+ path2.moveTo(centerX, closeY);
7484
+ path2.lineTo(centerX + tickLength, closeY);
7395
7485
  }
7396
7486
  ctx.lineWidth = Math.max(1, candleWickWidth);
7397
7487
  ctx.strokeStyle = mergedOptions.upColor;
@@ -7459,7 +7549,7 @@ function createChart(element, options = {}) {
7459
7549
  for (const plan of comparePlans) {
7460
7550
  const color = plan.state.options.color ?? "#f59e0b";
7461
7551
  const lineWidth = Math.max(1, plan.state.options.lineWidth ?? 1.5);
7462
- const path = new Path2D();
7552
+ const path2 = new Path2D();
7463
7553
  let started = false;
7464
7554
  let firstX = 0;
7465
7555
  let lastX = 0;
@@ -7467,11 +7557,11 @@ function createChart(element, options = {}) {
7467
7557
  let lastPrice = Number.NaN;
7468
7558
  const emit = (x, y) => {
7469
7559
  if (!started) {
7470
- path.moveTo(x, y);
7560
+ path2.moveTo(x, y);
7471
7561
  firstX = x;
7472
7562
  started = true;
7473
7563
  } else {
7474
- path.lineTo(x, y);
7564
+ path2.lineTo(x, y);
7475
7565
  }
7476
7566
  lastX = x;
7477
7567
  lastY = y;
@@ -7529,7 +7619,7 @@ function createChart(element, options = {}) {
7529
7619
  }
7530
7620
  if (!started) continue;
7531
7621
  if (plan.state.options.style === "area") {
7532
- const fillPath = new Path2D(path);
7622
+ const fillPath = new Path2D(path2);
7533
7623
  fillPath.lineTo(lastX, chartBottom);
7534
7624
  fillPath.lineTo(firstX, chartBottom);
7535
7625
  fillPath.closePath();
@@ -7543,7 +7633,7 @@ function createChart(element, options = {}) {
7543
7633
  ctx.strokeStyle = color;
7544
7634
  ctx.lineWidth = lineWidth;
7545
7635
  ctx.lineJoin = "round";
7546
- ctx.stroke(path);
7636
+ ctx.stroke(path2);
7547
7637
  ctx.restore();
7548
7638
  if (Number.isFinite(lastPrice)) {
7549
7639
  const label = plan.state.options.label ?? plan.state.options.id;
@@ -9351,12 +9441,16 @@ function createChart(element, options = {}) {
9351
9441
  if (Math.hypot(x - x2, y - y2) <= 9 * hitTolerance) {
9352
9442
  return { drawing, target: "handle", pointIndex: 1 };
9353
9443
  }
9354
- const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9355
- for (const ratio of fibRatios) {
9356
- const price = first.price + (second.price - first.price) * (1 - ratio);
9357
- const lineY = canvasYFromDrawingPrice(price);
9358
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9359
- return { drawing, target: "line" };
9444
+ const fibLeft = Math.min(x1, x2) - 5 * hitTolerance;
9445
+ const fibRight = Math.max(x1, x2) + 5 * hitTolerance;
9446
+ if (x >= fibLeft && x <= fibRight) {
9447
+ const fibRatios = [0, 0.236, 0.382, 0.5, 0.618, 0.786, 1, 1.618];
9448
+ for (const ratio of fibRatios) {
9449
+ const price = first.price + (second.price - first.price) * (1 - ratio);
9450
+ const lineY = canvasYFromDrawingPrice(price);
9451
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9452
+ return { drawing, target: "line" };
9453
+ }
9360
9454
  }
9361
9455
  }
9362
9456
  } else if (drawing.type === "fib-extension") {
@@ -9381,11 +9475,15 @@ function createChart(element, options = {}) {
9381
9475
  return { drawing, target: "handle", pointIndex: 2 };
9382
9476
  }
9383
9477
  const move = p1.price - p0.price;
9384
- const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9385
- for (const ratio of fibExtRatios) {
9386
- const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9387
- if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9388
- return { drawing, target: "line" };
9478
+ const extLeft = Math.min(x0, x1, x2) - 5 * hitTolerance;
9479
+ const extRight = Math.max(x0, x1, x2) + 5 * hitTolerance;
9480
+ if (x >= extLeft && x <= extRight) {
9481
+ const fibExtRatios = [0, 0.382, 0.5, 0.618, 1, 1.272, 1.618, 2.618];
9482
+ for (const ratio of fibExtRatios) {
9483
+ const lineY = canvasYFromDrawingPrice(p2.price + move * ratio);
9484
+ if (Math.abs(y - lineY) <= 5 * hitTolerance) {
9485
+ return { drawing, target: "line" };
9486
+ }
9389
9487
  }
9390
9488
  }
9391
9489
  if (distanceToSegment(x, y, x0, y0, x1, y1) <= 6 * hitTolerance || distanceToSegment(x, y, x1, y1, x2, y2) <= 6 * hitTolerance) {
@@ -12339,6 +12437,9 @@ function createChart(element, options = {}) {
12339
12437
  export {
12340
12438
  CHART_THEMES,
12341
12439
  CHART_THEME_NAMES,
12440
+ DRAWING_ICON_STROKE_WIDTH,
12441
+ DRAWING_ICON_VIEWBOX,
12442
+ DRAWING_TOOL_ICONS,
12342
12443
  FIB_DEFAULT_PALETTE,
12343
12444
  POSITION_DEFAULT_COLORS,
12344
12445
  SCRIPT_SOURCE_INPUT_VALUES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.152",
3
+ "version": "0.1.154",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",