hyperprop-charting-library 0.1.72 → 0.1.74

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.
@@ -21,9 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  FIB_DEFAULT_PALETTE: () => FIB_DEFAULT_PALETTE,
24
+ POSITION_DEFAULT_COLORS: () => POSITION_DEFAULT_COLORS,
24
25
  createChart: () => createChart
25
26
  });
26
27
  module.exports = __toCommonJS(index_exports);
28
+ var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
27
29
  var FIB_DEFAULT_PALETTE = [
28
30
  "#787b86",
29
31
  "#f23645",
@@ -982,6 +984,7 @@ function createChart(element, options = {}) {
982
984
  let drawingSelectHandler = null;
983
985
  let drawingHoverHandler = null;
984
986
  let lastHoveredDrawingId = null;
987
+ let selectedDrawingId = null;
985
988
  const drawingToolDefaults = /* @__PURE__ */ new Map();
986
989
  const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
987
990
  const emitDrawingsChange = () => {
@@ -2160,6 +2163,12 @@ function createChart(element, options = {}) {
2160
2163
  if (!drawing.visible) {
2161
2164
  return;
2162
2165
  }
2166
+ const isSelected = draft || drawing.id === selectedDrawingId;
2167
+ const handleAt = (hx, hy, _color) => {
2168
+ if (isSelected) {
2169
+ drawDrawingHandle(hx, hy, drawing.color);
2170
+ }
2171
+ };
2163
2172
  ctx.save();
2164
2173
  ctx.strokeStyle = drawing.color;
2165
2174
  ctx.lineWidth = drawing.width;
@@ -2178,7 +2187,7 @@ function createChart(element, options = {}) {
2178
2187
  ctx.moveTo(crisp(chartLeft), crisp(y));
2179
2188
  ctx.lineTo(crisp(chartRight), crisp(y));
2180
2189
  ctx.stroke();
2181
- drawDrawingHandle(handleX, y, drawing.color);
2190
+ handleAt(handleX, y, drawing.color);
2182
2191
  if (drawing.label) {
2183
2192
  const midX = (chartLeft + chartRight) / 2;
2184
2193
  drawDrawingLabel(drawing.label, midX, y, drawing.color);
@@ -2193,7 +2202,7 @@ function createChart(element, options = {}) {
2193
2202
  ctx.lineTo(crisp(x), crisp(chartBottom));
2194
2203
  ctx.stroke();
2195
2204
  const handleY = (chartTop + chartBottom) / 2;
2196
- drawDrawingHandle(x, handleY, drawing.color);
2205
+ handleAt(x, handleY, drawing.color);
2197
2206
  if (drawing.label) {
2198
2207
  drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
2199
2208
  }
@@ -2210,8 +2219,8 @@ function createChart(element, options = {}) {
2210
2219
  ctx.moveTo(firstX, firstY);
2211
2220
  ctx.lineTo(secondX, secondY);
2212
2221
  ctx.stroke();
2213
- drawDrawingHandle(firstX, firstY, drawing.color);
2214
- drawDrawingHandle(secondX, secondY, drawing.color);
2222
+ handleAt(firstX, firstY, drawing.color);
2223
+ handleAt(secondX, secondY, drawing.color);
2215
2224
  if (drawing.label) {
2216
2225
  const midX = (firstX + secondX) / 2;
2217
2226
  const midY = (firstY + secondY) / 2;
@@ -2240,8 +2249,8 @@ function createChart(element, options = {}) {
2240
2249
  ctx.moveTo(firstX, firstY);
2241
2250
  ctx.lineTo(endX, endY);
2242
2251
  ctx.stroke();
2243
- drawDrawingHandle(firstX, firstY, drawing.color);
2244
- drawDrawingHandle(secondX, secondY, drawing.color);
2252
+ handleAt(firstX, firstY, drawing.color);
2253
+ handleAt(secondX, secondY, drawing.color);
2245
2254
  if (drawing.label) {
2246
2255
  const midX = (firstX + secondX) / 2;
2247
2256
  const midY = (firstY + secondY) / 2;
@@ -2295,8 +2304,8 @@ function createChart(element, options = {}) {
2295
2304
  ctx.lineTo(secondX, secondY);
2296
2305
  ctx.stroke();
2297
2306
  ctx.restore();
2298
- drawDrawingHandle(firstX, firstY, drawing.color);
2299
- drawDrawingHandle(secondX, secondY, drawing.color);
2307
+ handleAt(firstX, firstY, drawing.color);
2308
+ handleAt(secondX, secondY, drawing.color);
2300
2309
  const prevFont = ctx.font;
2301
2310
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2302
2311
  levelLines.forEach((level, index) => {
@@ -2335,12 +2344,12 @@ function createChart(element, options = {}) {
2335
2344
  }
2336
2345
  ctx.stroke();
2337
2346
  ctx.restore();
2338
- drawDrawingHandle(x0, y0, drawing.color);
2339
- drawDrawingHandle(x1, y1, drawing.color);
2347
+ handleAt(x0, y0, drawing.color);
2348
+ handleAt(x1, y1, drawing.color);
2340
2349
  if (p2) {
2341
2350
  const x2 = xFromDrawingPoint(p2);
2342
2351
  const y2 = yFromPrice(p2.price);
2343
- drawDrawingHandle(x2, y2, drawing.color);
2352
+ handleAt(x2, y2, drawing.color);
2344
2353
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
2345
2354
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
2346
2355
  const move = p1.price - p0.price;
@@ -2405,10 +2414,14 @@ function createChart(element, options = {}) {
2405
2414
  const entryY = yFromPrice(entry.price);
2406
2415
  const targetY = yFromPrice(target.price);
2407
2416
  const stopY = yFromPrice(stop.price);
2408
- const profitFill = "rgba(38,166,154,0.16)";
2409
- const lossFill = "rgba(239,83,80,0.16)";
2410
- const profitLine = "rgba(38,166,154,0.9)";
2411
- const lossLine = "rgba(239,83,80,0.9)";
2417
+ const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
2418
+ const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
2419
+ const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
2420
+ const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
2421
+ const profitFill = hexToRgba(profitColor, 0.16);
2422
+ const lossFill = hexToRgba(lossColor, 0.16);
2423
+ const profitLine = profitColor;
2424
+ const lossLine = lossColor;
2412
2425
  ctx.save();
2413
2426
  ctx.globalAlpha = draft ? 0.6 : 1;
2414
2427
  ctx.fillStyle = profitFill;
@@ -2416,61 +2429,63 @@ function createChart(element, options = {}) {
2416
2429
  ctx.fillStyle = lossFill;
2417
2430
  ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
2418
2431
  ctx.restore();
2419
- ctx.save();
2420
- ctx.setLineDash([]);
2421
- ctx.lineWidth = Math.max(1, drawing.width);
2422
- ctx.strokeStyle = profitLine;
2423
- ctx.beginPath();
2424
- ctx.moveTo(crisp(boxX0), crisp(targetY));
2425
- ctx.lineTo(crisp(boxX1), crisp(targetY));
2426
- ctx.stroke();
2427
- ctx.strokeStyle = lossLine;
2428
- ctx.beginPath();
2429
- ctx.moveTo(crisp(boxX0), crisp(stopY));
2430
- ctx.lineTo(crisp(boxX1), crisp(stopY));
2431
- ctx.stroke();
2432
- ctx.strokeStyle = drawing.color;
2433
- ctx.beginPath();
2434
- ctx.moveTo(crisp(boxX0), crisp(entryY));
2435
- ctx.lineTo(crisp(boxX1), crisp(entryY));
2436
- ctx.stroke();
2437
- ctx.restore();
2438
- drawDrawingHandle(leftX, targetY, drawing.color);
2439
- drawDrawingHandle(leftX, entryY, drawing.color);
2440
- drawDrawingHandle(leftX, stopY, drawing.color);
2441
- drawDrawingHandle(rightX, entryY, drawing.color);
2442
- const tick = getConfiguredTickSize();
2443
- const pctOf = (price) => {
2444
- if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2445
- return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2446
- };
2447
- const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2448
- const targetDist = Math.abs(target.price - entry.price);
2449
- const stopDist = Math.abs(entry.price - stop.price);
2450
- const rr = stopDist > 0 ? targetDist / stopDist : 0;
2451
- const cx = (boxX0 + boxX1) / 2;
2452
- const drawPositionPill = (text, centerX, centerY, bg) => {
2453
- const prevFont = ctx.font;
2454
- ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2455
- const padding = 6;
2456
- const textW = ctx.measureText(text).width;
2457
- const pillW = textW + padding * 2;
2458
- const pillH = 18;
2459
- const pillX = centerX - pillW / 2;
2460
- const pillY = centerY - pillH / 2;
2461
- ctx.fillStyle = bg;
2462
- fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2463
- ctx.fillStyle = "#ffffff";
2464
- ctx.textAlign = "center";
2465
- ctx.textBaseline = "middle";
2466
- ctx.fillText(text, centerX, pillY + pillH / 2);
2467
- ctx.font = prevFont;
2468
- };
2469
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2470
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2471
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2472
- if (drawing.label) {
2473
- drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2432
+ if (isSelected) {
2433
+ ctx.save();
2434
+ ctx.setLineDash([]);
2435
+ ctx.lineWidth = Math.max(1, drawing.width);
2436
+ ctx.strokeStyle = profitLine;
2437
+ ctx.beginPath();
2438
+ ctx.moveTo(crisp(boxX0), crisp(targetY));
2439
+ ctx.lineTo(crisp(boxX1), crisp(targetY));
2440
+ ctx.stroke();
2441
+ ctx.strokeStyle = lossLine;
2442
+ ctx.beginPath();
2443
+ ctx.moveTo(crisp(boxX0), crisp(stopY));
2444
+ ctx.lineTo(crisp(boxX1), crisp(stopY));
2445
+ ctx.stroke();
2446
+ ctx.strokeStyle = drawing.color;
2447
+ ctx.beginPath();
2448
+ ctx.moveTo(crisp(boxX0), crisp(entryY));
2449
+ ctx.lineTo(crisp(boxX1), crisp(entryY));
2450
+ ctx.stroke();
2451
+ ctx.restore();
2452
+ handleAt(leftX, targetY, drawing.color);
2453
+ handleAt(leftX, entryY, drawing.color);
2454
+ handleAt(leftX, stopY, drawing.color);
2455
+ handleAt(rightX, entryY, drawing.color);
2456
+ const tick = getConfiguredTickSize();
2457
+ const pctOf = (price) => {
2458
+ if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2459
+ return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2460
+ };
2461
+ const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2462
+ const targetDist = Math.abs(target.price - entry.price);
2463
+ const stopDist = Math.abs(entry.price - stop.price);
2464
+ const rr = stopDist > 0 ? targetDist / stopDist : 0;
2465
+ const cx = (boxX0 + boxX1) / 2;
2466
+ const drawPositionPill = (text, centerX, centerY, bg) => {
2467
+ const prevFont = ctx.font;
2468
+ ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2469
+ const padding = 6;
2470
+ const textW = ctx.measureText(text).width;
2471
+ const pillW = textW + padding * 2;
2472
+ const pillH = 18;
2473
+ const pillX = centerX - pillW / 2;
2474
+ const pillY = centerY - pillH / 2;
2475
+ ctx.fillStyle = bg;
2476
+ fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2477
+ ctx.fillStyle = labelTextColor;
2478
+ ctx.textAlign = "center";
2479
+ ctx.textBaseline = "middle";
2480
+ ctx.fillText(text, centerX, pillY + pillH / 2);
2481
+ ctx.font = prevFont;
2482
+ };
2483
+ drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2484
+ drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2485
+ drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2486
+ if (drawing.label) {
2487
+ drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2488
+ }
2474
2489
  }
2475
2490
  }
2476
2491
  }
@@ -3909,7 +3924,8 @@ function createChart(element, options = {}) {
3909
3924
  normalizeDrawingPoint(point.index, stopPrice),
3910
3925
  normalizeDrawingPoint(point.index + width2, entryPrice)
3911
3926
  ],
3912
- color: defaults.color ?? "#2563eb",
3927
+ color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3928
+ colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3913
3929
  style: defaults.style ?? "solid",
3914
3930
  width: defaults.width ?? 1
3915
3931
  })
@@ -3927,6 +3943,13 @@ function createChart(element, options = {}) {
3927
3943
  }
3928
3944
  drawingToolDefaults.set(tool, { ...defaults });
3929
3945
  };
3946
+ const setSelectedDrawing = (id) => {
3947
+ if (selectedDrawingId === id) {
3948
+ return;
3949
+ }
3950
+ selectedDrawingId = id;
3951
+ draw();
3952
+ };
3930
3953
  const updateDrawingDrag = (x, y) => {
3931
3954
  if (!drawingDragState) {
3932
3955
  return false;
@@ -4839,6 +4862,7 @@ function createChart(element, options = {}) {
4839
4862
  clearDrawings,
4840
4863
  onDrawingsChange,
4841
4864
  onDrawingSelect,
4865
+ setSelectedDrawing,
4842
4866
  onDrawingHover,
4843
4867
  setDrawingDefaults,
4844
4868
  setDoubleClickEnabled,
@@ -4858,5 +4882,6 @@ function createChart(element, options = {}) {
4858
4882
  // Annotate the CommonJS export names for ESM import in node:
4859
4883
  0 && (module.exports = {
4860
4884
  FIB_DEFAULT_PALETTE,
4885
+ POSITION_DEFAULT_COLORS,
4861
4886
  createChart
4862
4887
  });
@@ -67,6 +67,8 @@ interface DrawingObjectOptions {
67
67
  label?: string;
68
68
  locked?: boolean;
69
69
  }
70
+ /** Default colors for position tools: [profit, loss, label text]. */
71
+ declare const POSITION_DEFAULT_COLORS: string[];
70
72
  /** Default multi-color palette for fib-retracement levels. */
71
73
  declare const FIB_DEFAULT_PALETTE: string[];
72
74
  interface DrawingSelectEvent {
@@ -420,6 +422,7 @@ interface ChartInstance {
420
422
  onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
421
423
  onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
422
424
  setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
425
+ setSelectedDrawing: (id: string | null) => void;
423
426
  setDoubleClickEnabled: (enabled: boolean) => void;
424
427
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
425
428
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -455,4 +458,4 @@ interface ViewportState {
455
458
  }
456
459
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
457
460
 
458
- export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
461
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
@@ -1,4 +1,5 @@
1
1
  // src/index.ts
2
+ var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
2
3
  var FIB_DEFAULT_PALETTE = [
3
4
  "#787b86",
4
5
  "#f23645",
@@ -957,6 +958,7 @@ function createChart(element, options = {}) {
957
958
  let drawingSelectHandler = null;
958
959
  let drawingHoverHandler = null;
959
960
  let lastHoveredDrawingId = null;
961
+ let selectedDrawingId = null;
960
962
  const drawingToolDefaults = /* @__PURE__ */ new Map();
961
963
  const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
962
964
  const emitDrawingsChange = () => {
@@ -2135,6 +2137,12 @@ function createChart(element, options = {}) {
2135
2137
  if (!drawing.visible) {
2136
2138
  return;
2137
2139
  }
2140
+ const isSelected = draft || drawing.id === selectedDrawingId;
2141
+ const handleAt = (hx, hy, _color) => {
2142
+ if (isSelected) {
2143
+ drawDrawingHandle(hx, hy, drawing.color);
2144
+ }
2145
+ };
2138
2146
  ctx.save();
2139
2147
  ctx.strokeStyle = drawing.color;
2140
2148
  ctx.lineWidth = drawing.width;
@@ -2153,7 +2161,7 @@ function createChart(element, options = {}) {
2153
2161
  ctx.moveTo(crisp(chartLeft), crisp(y));
2154
2162
  ctx.lineTo(crisp(chartRight), crisp(y));
2155
2163
  ctx.stroke();
2156
- drawDrawingHandle(handleX, y, drawing.color);
2164
+ handleAt(handleX, y, drawing.color);
2157
2165
  if (drawing.label) {
2158
2166
  const midX = (chartLeft + chartRight) / 2;
2159
2167
  drawDrawingLabel(drawing.label, midX, y, drawing.color);
@@ -2168,7 +2176,7 @@ function createChart(element, options = {}) {
2168
2176
  ctx.lineTo(crisp(x), crisp(chartBottom));
2169
2177
  ctx.stroke();
2170
2178
  const handleY = (chartTop + chartBottom) / 2;
2171
- drawDrawingHandle(x, handleY, drawing.color);
2179
+ handleAt(x, handleY, drawing.color);
2172
2180
  if (drawing.label) {
2173
2181
  drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
2174
2182
  }
@@ -2185,8 +2193,8 @@ function createChart(element, options = {}) {
2185
2193
  ctx.moveTo(firstX, firstY);
2186
2194
  ctx.lineTo(secondX, secondY);
2187
2195
  ctx.stroke();
2188
- drawDrawingHandle(firstX, firstY, drawing.color);
2189
- drawDrawingHandle(secondX, secondY, drawing.color);
2196
+ handleAt(firstX, firstY, drawing.color);
2197
+ handleAt(secondX, secondY, drawing.color);
2190
2198
  if (drawing.label) {
2191
2199
  const midX = (firstX + secondX) / 2;
2192
2200
  const midY = (firstY + secondY) / 2;
@@ -2215,8 +2223,8 @@ function createChart(element, options = {}) {
2215
2223
  ctx.moveTo(firstX, firstY);
2216
2224
  ctx.lineTo(endX, endY);
2217
2225
  ctx.stroke();
2218
- drawDrawingHandle(firstX, firstY, drawing.color);
2219
- drawDrawingHandle(secondX, secondY, drawing.color);
2226
+ handleAt(firstX, firstY, drawing.color);
2227
+ handleAt(secondX, secondY, drawing.color);
2220
2228
  if (drawing.label) {
2221
2229
  const midX = (firstX + secondX) / 2;
2222
2230
  const midY = (firstY + secondY) / 2;
@@ -2270,8 +2278,8 @@ function createChart(element, options = {}) {
2270
2278
  ctx.lineTo(secondX, secondY);
2271
2279
  ctx.stroke();
2272
2280
  ctx.restore();
2273
- drawDrawingHandle(firstX, firstY, drawing.color);
2274
- drawDrawingHandle(secondX, secondY, drawing.color);
2281
+ handleAt(firstX, firstY, drawing.color);
2282
+ handleAt(secondX, secondY, drawing.color);
2275
2283
  const prevFont = ctx.font;
2276
2284
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2277
2285
  levelLines.forEach((level, index) => {
@@ -2310,12 +2318,12 @@ function createChart(element, options = {}) {
2310
2318
  }
2311
2319
  ctx.stroke();
2312
2320
  ctx.restore();
2313
- drawDrawingHandle(x0, y0, drawing.color);
2314
- drawDrawingHandle(x1, y1, drawing.color);
2321
+ handleAt(x0, y0, drawing.color);
2322
+ handleAt(x1, y1, drawing.color);
2315
2323
  if (p2) {
2316
2324
  const x2 = xFromDrawingPoint(p2);
2317
2325
  const y2 = yFromPrice(p2.price);
2318
- drawDrawingHandle(x2, y2, drawing.color);
2326
+ handleAt(x2, y2, drawing.color);
2319
2327
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
2320
2328
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
2321
2329
  const move = p1.price - p0.price;
@@ -2380,10 +2388,14 @@ function createChart(element, options = {}) {
2380
2388
  const entryY = yFromPrice(entry.price);
2381
2389
  const targetY = yFromPrice(target.price);
2382
2390
  const stopY = yFromPrice(stop.price);
2383
- const profitFill = "rgba(38,166,154,0.16)";
2384
- const lossFill = "rgba(239,83,80,0.16)";
2385
- const profitLine = "rgba(38,166,154,0.9)";
2386
- const lossLine = "rgba(239,83,80,0.9)";
2391
+ const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
2392
+ const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
2393
+ const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
2394
+ const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
2395
+ const profitFill = hexToRgba(profitColor, 0.16);
2396
+ const lossFill = hexToRgba(lossColor, 0.16);
2397
+ const profitLine = profitColor;
2398
+ const lossLine = lossColor;
2387
2399
  ctx.save();
2388
2400
  ctx.globalAlpha = draft ? 0.6 : 1;
2389
2401
  ctx.fillStyle = profitFill;
@@ -2391,61 +2403,63 @@ function createChart(element, options = {}) {
2391
2403
  ctx.fillStyle = lossFill;
2392
2404
  ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
2393
2405
  ctx.restore();
2394
- ctx.save();
2395
- ctx.setLineDash([]);
2396
- ctx.lineWidth = Math.max(1, drawing.width);
2397
- ctx.strokeStyle = profitLine;
2398
- ctx.beginPath();
2399
- ctx.moveTo(crisp(boxX0), crisp(targetY));
2400
- ctx.lineTo(crisp(boxX1), crisp(targetY));
2401
- ctx.stroke();
2402
- ctx.strokeStyle = lossLine;
2403
- ctx.beginPath();
2404
- ctx.moveTo(crisp(boxX0), crisp(stopY));
2405
- ctx.lineTo(crisp(boxX1), crisp(stopY));
2406
- ctx.stroke();
2407
- ctx.strokeStyle = drawing.color;
2408
- ctx.beginPath();
2409
- ctx.moveTo(crisp(boxX0), crisp(entryY));
2410
- ctx.lineTo(crisp(boxX1), crisp(entryY));
2411
- ctx.stroke();
2412
- ctx.restore();
2413
- drawDrawingHandle(leftX, targetY, drawing.color);
2414
- drawDrawingHandle(leftX, entryY, drawing.color);
2415
- drawDrawingHandle(leftX, stopY, drawing.color);
2416
- drawDrawingHandle(rightX, entryY, drawing.color);
2417
- const tick = getConfiguredTickSize();
2418
- const pctOf = (price) => {
2419
- if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2420
- return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2421
- };
2422
- const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2423
- const targetDist = Math.abs(target.price - entry.price);
2424
- const stopDist = Math.abs(entry.price - stop.price);
2425
- const rr = stopDist > 0 ? targetDist / stopDist : 0;
2426
- const cx = (boxX0 + boxX1) / 2;
2427
- const drawPositionPill = (text, centerX, centerY, bg) => {
2428
- const prevFont = ctx.font;
2429
- ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2430
- const padding = 6;
2431
- const textW = ctx.measureText(text).width;
2432
- const pillW = textW + padding * 2;
2433
- const pillH = 18;
2434
- const pillX = centerX - pillW / 2;
2435
- const pillY = centerY - pillH / 2;
2436
- ctx.fillStyle = bg;
2437
- fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2438
- ctx.fillStyle = "#ffffff";
2439
- ctx.textAlign = "center";
2440
- ctx.textBaseline = "middle";
2441
- ctx.fillText(text, centerX, pillY + pillH / 2);
2442
- ctx.font = prevFont;
2443
- };
2444
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2445
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2446
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2447
- if (drawing.label) {
2448
- drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2406
+ if (isSelected) {
2407
+ ctx.save();
2408
+ ctx.setLineDash([]);
2409
+ ctx.lineWidth = Math.max(1, drawing.width);
2410
+ ctx.strokeStyle = profitLine;
2411
+ ctx.beginPath();
2412
+ ctx.moveTo(crisp(boxX0), crisp(targetY));
2413
+ ctx.lineTo(crisp(boxX1), crisp(targetY));
2414
+ ctx.stroke();
2415
+ ctx.strokeStyle = lossLine;
2416
+ ctx.beginPath();
2417
+ ctx.moveTo(crisp(boxX0), crisp(stopY));
2418
+ ctx.lineTo(crisp(boxX1), crisp(stopY));
2419
+ ctx.stroke();
2420
+ ctx.strokeStyle = drawing.color;
2421
+ ctx.beginPath();
2422
+ ctx.moveTo(crisp(boxX0), crisp(entryY));
2423
+ ctx.lineTo(crisp(boxX1), crisp(entryY));
2424
+ ctx.stroke();
2425
+ ctx.restore();
2426
+ handleAt(leftX, targetY, drawing.color);
2427
+ handleAt(leftX, entryY, drawing.color);
2428
+ handleAt(leftX, stopY, drawing.color);
2429
+ handleAt(rightX, entryY, drawing.color);
2430
+ const tick = getConfiguredTickSize();
2431
+ const pctOf = (price) => {
2432
+ if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2433
+ return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2434
+ };
2435
+ const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2436
+ const targetDist = Math.abs(target.price - entry.price);
2437
+ const stopDist = Math.abs(entry.price - stop.price);
2438
+ const rr = stopDist > 0 ? targetDist / stopDist : 0;
2439
+ const cx = (boxX0 + boxX1) / 2;
2440
+ const drawPositionPill = (text, centerX, centerY, bg) => {
2441
+ const prevFont = ctx.font;
2442
+ ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2443
+ const padding = 6;
2444
+ const textW = ctx.measureText(text).width;
2445
+ const pillW = textW + padding * 2;
2446
+ const pillH = 18;
2447
+ const pillX = centerX - pillW / 2;
2448
+ const pillY = centerY - pillH / 2;
2449
+ ctx.fillStyle = bg;
2450
+ fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2451
+ ctx.fillStyle = labelTextColor;
2452
+ ctx.textAlign = "center";
2453
+ ctx.textBaseline = "middle";
2454
+ ctx.fillText(text, centerX, pillY + pillH / 2);
2455
+ ctx.font = prevFont;
2456
+ };
2457
+ drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2458
+ drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2459
+ drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2460
+ if (drawing.label) {
2461
+ drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2462
+ }
2449
2463
  }
2450
2464
  }
2451
2465
  }
@@ -3884,7 +3898,8 @@ function createChart(element, options = {}) {
3884
3898
  normalizeDrawingPoint(point.index, stopPrice),
3885
3899
  normalizeDrawingPoint(point.index + width2, entryPrice)
3886
3900
  ],
3887
- color: defaults.color ?? "#2563eb",
3901
+ color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3902
+ colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3888
3903
  style: defaults.style ?? "solid",
3889
3904
  width: defaults.width ?? 1
3890
3905
  })
@@ -3902,6 +3917,13 @@ function createChart(element, options = {}) {
3902
3917
  }
3903
3918
  drawingToolDefaults.set(tool, { ...defaults });
3904
3919
  };
3920
+ const setSelectedDrawing = (id) => {
3921
+ if (selectedDrawingId === id) {
3922
+ return;
3923
+ }
3924
+ selectedDrawingId = id;
3925
+ draw();
3926
+ };
3905
3927
  const updateDrawingDrag = (x, y) => {
3906
3928
  if (!drawingDragState) {
3907
3929
  return false;
@@ -4814,6 +4836,7 @@ function createChart(element, options = {}) {
4814
4836
  clearDrawings,
4815
4837
  onDrawingsChange,
4816
4838
  onDrawingSelect,
4839
+ setSelectedDrawing,
4817
4840
  onDrawingHover,
4818
4841
  setDrawingDefaults,
4819
4842
  setDoubleClickEnabled,
@@ -4832,5 +4855,6 @@ function createChart(element, options = {}) {
4832
4855
  }
4833
4856
  export {
4834
4857
  FIB_DEFAULT_PALETTE,
4858
+ POSITION_DEFAULT_COLORS,
4835
4859
  createChart
4836
4860
  };
package/dist/index.cjs CHANGED
@@ -21,9 +21,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  FIB_DEFAULT_PALETTE: () => FIB_DEFAULT_PALETTE,
24
+ POSITION_DEFAULT_COLORS: () => POSITION_DEFAULT_COLORS,
24
25
  createChart: () => createChart
25
26
  });
26
27
  module.exports = __toCommonJS(index_exports);
28
+ var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
27
29
  var FIB_DEFAULT_PALETTE = [
28
30
  "#787b86",
29
31
  "#f23645",
@@ -982,6 +984,7 @@ function createChart(element, options = {}) {
982
984
  let drawingSelectHandler = null;
983
985
  let drawingHoverHandler = null;
984
986
  let lastHoveredDrawingId = null;
987
+ let selectedDrawingId = null;
985
988
  const drawingToolDefaults = /* @__PURE__ */ new Map();
986
989
  const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
987
990
  const emitDrawingsChange = () => {
@@ -2160,6 +2163,12 @@ function createChart(element, options = {}) {
2160
2163
  if (!drawing.visible) {
2161
2164
  return;
2162
2165
  }
2166
+ const isSelected = draft || drawing.id === selectedDrawingId;
2167
+ const handleAt = (hx, hy, _color) => {
2168
+ if (isSelected) {
2169
+ drawDrawingHandle(hx, hy, drawing.color);
2170
+ }
2171
+ };
2163
2172
  ctx.save();
2164
2173
  ctx.strokeStyle = drawing.color;
2165
2174
  ctx.lineWidth = drawing.width;
@@ -2178,7 +2187,7 @@ function createChart(element, options = {}) {
2178
2187
  ctx.moveTo(crisp(chartLeft), crisp(y));
2179
2188
  ctx.lineTo(crisp(chartRight), crisp(y));
2180
2189
  ctx.stroke();
2181
- drawDrawingHandle(handleX, y, drawing.color);
2190
+ handleAt(handleX, y, drawing.color);
2182
2191
  if (drawing.label) {
2183
2192
  const midX = (chartLeft + chartRight) / 2;
2184
2193
  drawDrawingLabel(drawing.label, midX, y, drawing.color);
@@ -2193,7 +2202,7 @@ function createChart(element, options = {}) {
2193
2202
  ctx.lineTo(crisp(x), crisp(chartBottom));
2194
2203
  ctx.stroke();
2195
2204
  const handleY = (chartTop + chartBottom) / 2;
2196
- drawDrawingHandle(x, handleY, drawing.color);
2205
+ handleAt(x, handleY, drawing.color);
2197
2206
  if (drawing.label) {
2198
2207
  drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
2199
2208
  }
@@ -2210,8 +2219,8 @@ function createChart(element, options = {}) {
2210
2219
  ctx.moveTo(firstX, firstY);
2211
2220
  ctx.lineTo(secondX, secondY);
2212
2221
  ctx.stroke();
2213
- drawDrawingHandle(firstX, firstY, drawing.color);
2214
- drawDrawingHandle(secondX, secondY, drawing.color);
2222
+ handleAt(firstX, firstY, drawing.color);
2223
+ handleAt(secondX, secondY, drawing.color);
2215
2224
  if (drawing.label) {
2216
2225
  const midX = (firstX + secondX) / 2;
2217
2226
  const midY = (firstY + secondY) / 2;
@@ -2240,8 +2249,8 @@ function createChart(element, options = {}) {
2240
2249
  ctx.moveTo(firstX, firstY);
2241
2250
  ctx.lineTo(endX, endY);
2242
2251
  ctx.stroke();
2243
- drawDrawingHandle(firstX, firstY, drawing.color);
2244
- drawDrawingHandle(secondX, secondY, drawing.color);
2252
+ handleAt(firstX, firstY, drawing.color);
2253
+ handleAt(secondX, secondY, drawing.color);
2245
2254
  if (drawing.label) {
2246
2255
  const midX = (firstX + secondX) / 2;
2247
2256
  const midY = (firstY + secondY) / 2;
@@ -2295,8 +2304,8 @@ function createChart(element, options = {}) {
2295
2304
  ctx.lineTo(secondX, secondY);
2296
2305
  ctx.stroke();
2297
2306
  ctx.restore();
2298
- drawDrawingHandle(firstX, firstY, drawing.color);
2299
- drawDrawingHandle(secondX, secondY, drawing.color);
2307
+ handleAt(firstX, firstY, drawing.color);
2308
+ handleAt(secondX, secondY, drawing.color);
2300
2309
  const prevFont = ctx.font;
2301
2310
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2302
2311
  levelLines.forEach((level, index) => {
@@ -2335,12 +2344,12 @@ function createChart(element, options = {}) {
2335
2344
  }
2336
2345
  ctx.stroke();
2337
2346
  ctx.restore();
2338
- drawDrawingHandle(x0, y0, drawing.color);
2339
- drawDrawingHandle(x1, y1, drawing.color);
2347
+ handleAt(x0, y0, drawing.color);
2348
+ handleAt(x1, y1, drawing.color);
2340
2349
  if (p2) {
2341
2350
  const x2 = xFromDrawingPoint(p2);
2342
2351
  const y2 = yFromPrice(p2.price);
2343
- drawDrawingHandle(x2, y2, drawing.color);
2352
+ handleAt(x2, y2, drawing.color);
2344
2353
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
2345
2354
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
2346
2355
  const move = p1.price - p0.price;
@@ -2405,10 +2414,14 @@ function createChart(element, options = {}) {
2405
2414
  const entryY = yFromPrice(entry.price);
2406
2415
  const targetY = yFromPrice(target.price);
2407
2416
  const stopY = yFromPrice(stop.price);
2408
- const profitFill = "rgba(38,166,154,0.16)";
2409
- const lossFill = "rgba(239,83,80,0.16)";
2410
- const profitLine = "rgba(38,166,154,0.9)";
2411
- const lossLine = "rgba(239,83,80,0.9)";
2417
+ const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
2418
+ const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
2419
+ const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
2420
+ const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
2421
+ const profitFill = hexToRgba(profitColor, 0.16);
2422
+ const lossFill = hexToRgba(lossColor, 0.16);
2423
+ const profitLine = profitColor;
2424
+ const lossLine = lossColor;
2412
2425
  ctx.save();
2413
2426
  ctx.globalAlpha = draft ? 0.6 : 1;
2414
2427
  ctx.fillStyle = profitFill;
@@ -2416,61 +2429,63 @@ function createChart(element, options = {}) {
2416
2429
  ctx.fillStyle = lossFill;
2417
2430
  ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
2418
2431
  ctx.restore();
2419
- ctx.save();
2420
- ctx.setLineDash([]);
2421
- ctx.lineWidth = Math.max(1, drawing.width);
2422
- ctx.strokeStyle = profitLine;
2423
- ctx.beginPath();
2424
- ctx.moveTo(crisp(boxX0), crisp(targetY));
2425
- ctx.lineTo(crisp(boxX1), crisp(targetY));
2426
- ctx.stroke();
2427
- ctx.strokeStyle = lossLine;
2428
- ctx.beginPath();
2429
- ctx.moveTo(crisp(boxX0), crisp(stopY));
2430
- ctx.lineTo(crisp(boxX1), crisp(stopY));
2431
- ctx.stroke();
2432
- ctx.strokeStyle = drawing.color;
2433
- ctx.beginPath();
2434
- ctx.moveTo(crisp(boxX0), crisp(entryY));
2435
- ctx.lineTo(crisp(boxX1), crisp(entryY));
2436
- ctx.stroke();
2437
- ctx.restore();
2438
- drawDrawingHandle(leftX, targetY, drawing.color);
2439
- drawDrawingHandle(leftX, entryY, drawing.color);
2440
- drawDrawingHandle(leftX, stopY, drawing.color);
2441
- drawDrawingHandle(rightX, entryY, drawing.color);
2442
- const tick = getConfiguredTickSize();
2443
- const pctOf = (price) => {
2444
- if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2445
- return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2446
- };
2447
- const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2448
- const targetDist = Math.abs(target.price - entry.price);
2449
- const stopDist = Math.abs(entry.price - stop.price);
2450
- const rr = stopDist > 0 ? targetDist / stopDist : 0;
2451
- const cx = (boxX0 + boxX1) / 2;
2452
- const drawPositionPill = (text, centerX, centerY, bg) => {
2453
- const prevFont = ctx.font;
2454
- ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2455
- const padding = 6;
2456
- const textW = ctx.measureText(text).width;
2457
- const pillW = textW + padding * 2;
2458
- const pillH = 18;
2459
- const pillX = centerX - pillW / 2;
2460
- const pillY = centerY - pillH / 2;
2461
- ctx.fillStyle = bg;
2462
- fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2463
- ctx.fillStyle = "#ffffff";
2464
- ctx.textAlign = "center";
2465
- ctx.textBaseline = "middle";
2466
- ctx.fillText(text, centerX, pillY + pillH / 2);
2467
- ctx.font = prevFont;
2468
- };
2469
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2470
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2471
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2472
- if (drawing.label) {
2473
- drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2432
+ if (isSelected) {
2433
+ ctx.save();
2434
+ ctx.setLineDash([]);
2435
+ ctx.lineWidth = Math.max(1, drawing.width);
2436
+ ctx.strokeStyle = profitLine;
2437
+ ctx.beginPath();
2438
+ ctx.moveTo(crisp(boxX0), crisp(targetY));
2439
+ ctx.lineTo(crisp(boxX1), crisp(targetY));
2440
+ ctx.stroke();
2441
+ ctx.strokeStyle = lossLine;
2442
+ ctx.beginPath();
2443
+ ctx.moveTo(crisp(boxX0), crisp(stopY));
2444
+ ctx.lineTo(crisp(boxX1), crisp(stopY));
2445
+ ctx.stroke();
2446
+ ctx.strokeStyle = drawing.color;
2447
+ ctx.beginPath();
2448
+ ctx.moveTo(crisp(boxX0), crisp(entryY));
2449
+ ctx.lineTo(crisp(boxX1), crisp(entryY));
2450
+ ctx.stroke();
2451
+ ctx.restore();
2452
+ handleAt(leftX, targetY, drawing.color);
2453
+ handleAt(leftX, entryY, drawing.color);
2454
+ handleAt(leftX, stopY, drawing.color);
2455
+ handleAt(rightX, entryY, drawing.color);
2456
+ const tick = getConfiguredTickSize();
2457
+ const pctOf = (price) => {
2458
+ if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2459
+ return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2460
+ };
2461
+ const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2462
+ const targetDist = Math.abs(target.price - entry.price);
2463
+ const stopDist = Math.abs(entry.price - stop.price);
2464
+ const rr = stopDist > 0 ? targetDist / stopDist : 0;
2465
+ const cx = (boxX0 + boxX1) / 2;
2466
+ const drawPositionPill = (text, centerX, centerY, bg) => {
2467
+ const prevFont = ctx.font;
2468
+ ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2469
+ const padding = 6;
2470
+ const textW = ctx.measureText(text).width;
2471
+ const pillW = textW + padding * 2;
2472
+ const pillH = 18;
2473
+ const pillX = centerX - pillW / 2;
2474
+ const pillY = centerY - pillH / 2;
2475
+ ctx.fillStyle = bg;
2476
+ fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2477
+ ctx.fillStyle = labelTextColor;
2478
+ ctx.textAlign = "center";
2479
+ ctx.textBaseline = "middle";
2480
+ ctx.fillText(text, centerX, pillY + pillH / 2);
2481
+ ctx.font = prevFont;
2482
+ };
2483
+ drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2484
+ drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2485
+ drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2486
+ if (drawing.label) {
2487
+ drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2488
+ }
2474
2489
  }
2475
2490
  }
2476
2491
  }
@@ -3909,7 +3924,8 @@ function createChart(element, options = {}) {
3909
3924
  normalizeDrawingPoint(point.index, stopPrice),
3910
3925
  normalizeDrawingPoint(point.index + width2, entryPrice)
3911
3926
  ],
3912
- color: defaults.color ?? "#2563eb",
3927
+ color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3928
+ colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3913
3929
  style: defaults.style ?? "solid",
3914
3930
  width: defaults.width ?? 1
3915
3931
  })
@@ -3927,6 +3943,13 @@ function createChart(element, options = {}) {
3927
3943
  }
3928
3944
  drawingToolDefaults.set(tool, { ...defaults });
3929
3945
  };
3946
+ const setSelectedDrawing = (id) => {
3947
+ if (selectedDrawingId === id) {
3948
+ return;
3949
+ }
3950
+ selectedDrawingId = id;
3951
+ draw();
3952
+ };
3930
3953
  const updateDrawingDrag = (x, y) => {
3931
3954
  if (!drawingDragState) {
3932
3955
  return false;
@@ -4839,6 +4862,7 @@ function createChart(element, options = {}) {
4839
4862
  clearDrawings,
4840
4863
  onDrawingsChange,
4841
4864
  onDrawingSelect,
4865
+ setSelectedDrawing,
4842
4866
  onDrawingHover,
4843
4867
  setDrawingDefaults,
4844
4868
  setDoubleClickEnabled,
@@ -4858,5 +4882,6 @@ function createChart(element, options = {}) {
4858
4882
  // Annotate the CommonJS export names for ESM import in node:
4859
4883
  0 && (module.exports = {
4860
4884
  FIB_DEFAULT_PALETTE,
4885
+ POSITION_DEFAULT_COLORS,
4861
4886
  createChart
4862
4887
  });
package/dist/index.d.cts CHANGED
@@ -67,6 +67,8 @@ interface DrawingObjectOptions {
67
67
  label?: string;
68
68
  locked?: boolean;
69
69
  }
70
+ /** Default colors for position tools: [profit, loss, label text]. */
71
+ declare const POSITION_DEFAULT_COLORS: string[];
70
72
  /** Default multi-color palette for fib-retracement levels. */
71
73
  declare const FIB_DEFAULT_PALETTE: string[];
72
74
  interface DrawingSelectEvent {
@@ -420,6 +422,7 @@ interface ChartInstance {
420
422
  onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
421
423
  onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
422
424
  setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
425
+ setSelectedDrawing: (id: string | null) => void;
423
426
  setDoubleClickEnabled: (enabled: boolean) => void;
424
427
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
425
428
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -455,4 +458,4 @@ interface ViewportState {
455
458
  }
456
459
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
457
460
 
458
- export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
461
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
package/dist/index.d.ts CHANGED
@@ -67,6 +67,8 @@ interface DrawingObjectOptions {
67
67
  label?: string;
68
68
  locked?: boolean;
69
69
  }
70
+ /** Default colors for position tools: [profit, loss, label text]. */
71
+ declare const POSITION_DEFAULT_COLORS: string[];
70
72
  /** Default multi-color palette for fib-retracement levels. */
71
73
  declare const FIB_DEFAULT_PALETTE: string[];
72
74
  interface DrawingSelectEvent {
@@ -420,6 +422,7 @@ interface ChartInstance {
420
422
  onDrawingSelect: (handler: ((event: DrawingSelectEvent) => void) | null) => void;
421
423
  onDrawingHover: (handler: ((event: DrawingHoverEvent) => void) | null) => void;
422
424
  setDrawingDefaults: (tool: DrawingToolType, defaults: DrawingDefaults | null) => void;
425
+ setSelectedDrawing: (id: string | null) => void;
423
426
  setDoubleClickEnabled: (enabled: boolean) => void;
424
427
  setDoubleClickAction: (action: "reset" | "placeLimitOrder") => void;
425
428
  registerIndicator: (plugin: IndicatorPlugin<any>) => void;
@@ -455,4 +458,4 @@ interface ViewportState {
455
458
  }
456
459
  declare function createChart(element: HTMLElement, options?: ChartOptions): ChartInstance;
457
460
 
458
- export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
461
+ export { type AxisOptions, type BuiltInIndicatorInfo, type ChartClickEvent, type ChartInstance, type ChartOptions, type CrosshairMoveEvent, type CrosshairOptions, type CrosshairPriceActionEvent, type DashPatternOptions, type DrawingDefaults, type DrawingHoverEvent, type DrawingObjectOptions, type DrawingPoint, type DrawingSelectEvent, type DrawingToolType, FIB_DEFAULT_PALETTE, type GridOptions, type IndicatorInstanceOptions, type IndicatorPane, type IndicatorPaneAxisOptions, type IndicatorPaneGuideLine, type IndicatorPaneRenderInfo, type IndicatorPaneValue, type IndicatorPaneValueLabel, type IndicatorPlugin, type IndicatorRenderContext, type LabelsOptions, type OhlcDataPoint, type OrderActionButton, type OrderActionEvent, type OrderLineOptions, POSITION_DEFAULT_COLORS, type PriceLineOptions, type TickerLineOptions, type ViewportState, type WatermarkOptions, createChart };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/index.ts
2
+ var POSITION_DEFAULT_COLORS = ["#26a69a", "#ef5350", "#ffffff"];
2
3
  var FIB_DEFAULT_PALETTE = [
3
4
  "#787b86",
4
5
  "#f23645",
@@ -957,6 +958,7 @@ function createChart(element, options = {}) {
957
958
  let drawingSelectHandler = null;
958
959
  let drawingHoverHandler = null;
959
960
  let lastHoveredDrawingId = null;
961
+ let selectedDrawingId = null;
960
962
  const drawingToolDefaults = /* @__PURE__ */ new Map();
961
963
  const getDrawingToolDefaults = (tool) => drawingToolDefaults.get(tool) ?? {};
962
964
  const emitDrawingsChange = () => {
@@ -2135,6 +2137,12 @@ function createChart(element, options = {}) {
2135
2137
  if (!drawing.visible) {
2136
2138
  return;
2137
2139
  }
2140
+ const isSelected = draft || drawing.id === selectedDrawingId;
2141
+ const handleAt = (hx, hy, _color) => {
2142
+ if (isSelected) {
2143
+ drawDrawingHandle(hx, hy, drawing.color);
2144
+ }
2145
+ };
2138
2146
  ctx.save();
2139
2147
  ctx.strokeStyle = drawing.color;
2140
2148
  ctx.lineWidth = drawing.width;
@@ -2153,7 +2161,7 @@ function createChart(element, options = {}) {
2153
2161
  ctx.moveTo(crisp(chartLeft), crisp(y));
2154
2162
  ctx.lineTo(crisp(chartRight), crisp(y));
2155
2163
  ctx.stroke();
2156
- drawDrawingHandle(handleX, y, drawing.color);
2164
+ handleAt(handleX, y, drawing.color);
2157
2165
  if (drawing.label) {
2158
2166
  const midX = (chartLeft + chartRight) / 2;
2159
2167
  drawDrawingLabel(drawing.label, midX, y, drawing.color);
@@ -2168,7 +2176,7 @@ function createChart(element, options = {}) {
2168
2176
  ctx.lineTo(crisp(x), crisp(chartBottom));
2169
2177
  ctx.stroke();
2170
2178
  const handleY = (chartTop + chartBottom) / 2;
2171
- drawDrawingHandle(x, handleY, drawing.color);
2179
+ handleAt(x, handleY, drawing.color);
2172
2180
  if (drawing.label) {
2173
2181
  drawDrawingLabel(drawing.label, x, chartTop + 16, drawing.color);
2174
2182
  }
@@ -2185,8 +2193,8 @@ function createChart(element, options = {}) {
2185
2193
  ctx.moveTo(firstX, firstY);
2186
2194
  ctx.lineTo(secondX, secondY);
2187
2195
  ctx.stroke();
2188
- drawDrawingHandle(firstX, firstY, drawing.color);
2189
- drawDrawingHandle(secondX, secondY, drawing.color);
2196
+ handleAt(firstX, firstY, drawing.color);
2197
+ handleAt(secondX, secondY, drawing.color);
2190
2198
  if (drawing.label) {
2191
2199
  const midX = (firstX + secondX) / 2;
2192
2200
  const midY = (firstY + secondY) / 2;
@@ -2215,8 +2223,8 @@ function createChart(element, options = {}) {
2215
2223
  ctx.moveTo(firstX, firstY);
2216
2224
  ctx.lineTo(endX, endY);
2217
2225
  ctx.stroke();
2218
- drawDrawingHandle(firstX, firstY, drawing.color);
2219
- drawDrawingHandle(secondX, secondY, drawing.color);
2226
+ handleAt(firstX, firstY, drawing.color);
2227
+ handleAt(secondX, secondY, drawing.color);
2220
2228
  if (drawing.label) {
2221
2229
  const midX = (firstX + secondX) / 2;
2222
2230
  const midY = (firstY + secondY) / 2;
@@ -2270,8 +2278,8 @@ function createChart(element, options = {}) {
2270
2278
  ctx.lineTo(secondX, secondY);
2271
2279
  ctx.stroke();
2272
2280
  ctx.restore();
2273
- drawDrawingHandle(firstX, firstY, drawing.color);
2274
- drawDrawingHandle(secondX, secondY, drawing.color);
2281
+ handleAt(firstX, firstY, drawing.color);
2282
+ handleAt(secondX, secondY, drawing.color);
2275
2283
  const prevFont = ctx.font;
2276
2284
  ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2277
2285
  levelLines.forEach((level, index) => {
@@ -2310,12 +2318,12 @@ function createChart(element, options = {}) {
2310
2318
  }
2311
2319
  ctx.stroke();
2312
2320
  ctx.restore();
2313
- drawDrawingHandle(x0, y0, drawing.color);
2314
- drawDrawingHandle(x1, y1, drawing.color);
2321
+ handleAt(x0, y0, drawing.color);
2322
+ handleAt(x1, y1, drawing.color);
2315
2323
  if (p2) {
2316
2324
  const x2 = xFromDrawingPoint(p2);
2317
2325
  const y2 = yFromPrice(p2.price);
2318
- drawDrawingHandle(x2, y2, drawing.color);
2326
+ handleAt(x2, y2, drawing.color);
2319
2327
  const palette = drawing.colors.length > 0 ? drawing.colors : null;
2320
2328
  const levelColorAt = (index) => palette ? palette[index % palette.length] : drawing.color;
2321
2329
  const move = p1.price - p0.price;
@@ -2380,10 +2388,14 @@ function createChart(element, options = {}) {
2380
2388
  const entryY = yFromPrice(entry.price);
2381
2389
  const targetY = yFromPrice(target.price);
2382
2390
  const stopY = yFromPrice(stop.price);
2383
- const profitFill = "rgba(38,166,154,0.16)";
2384
- const lossFill = "rgba(239,83,80,0.16)";
2385
- const profitLine = "rgba(38,166,154,0.9)";
2386
- const lossLine = "rgba(239,83,80,0.9)";
2391
+ const isHex6 = (value) => !!value && /^#[0-9a-fA-F]{6}$/.test(value);
2392
+ const profitColor = isHex6(drawing.colors[0]) ? drawing.colors[0] : "#26a69a";
2393
+ const lossColor = isHex6(drawing.colors[1]) ? drawing.colors[1] : "#ef5350";
2394
+ const labelTextColor = isHex6(drawing.colors[2]) ? drawing.colors[2] : "#ffffff";
2395
+ const profitFill = hexToRgba(profitColor, 0.16);
2396
+ const lossFill = hexToRgba(lossColor, 0.16);
2397
+ const profitLine = profitColor;
2398
+ const lossLine = lossColor;
2387
2399
  ctx.save();
2388
2400
  ctx.globalAlpha = draft ? 0.6 : 1;
2389
2401
  ctx.fillStyle = profitFill;
@@ -2391,61 +2403,63 @@ function createChart(element, options = {}) {
2391
2403
  ctx.fillStyle = lossFill;
2392
2404
  ctx.fillRect(boxX0, Math.min(entryY, stopY), boxW, Math.abs(stopY - entryY));
2393
2405
  ctx.restore();
2394
- ctx.save();
2395
- ctx.setLineDash([]);
2396
- ctx.lineWidth = Math.max(1, drawing.width);
2397
- ctx.strokeStyle = profitLine;
2398
- ctx.beginPath();
2399
- ctx.moveTo(crisp(boxX0), crisp(targetY));
2400
- ctx.lineTo(crisp(boxX1), crisp(targetY));
2401
- ctx.stroke();
2402
- ctx.strokeStyle = lossLine;
2403
- ctx.beginPath();
2404
- ctx.moveTo(crisp(boxX0), crisp(stopY));
2405
- ctx.lineTo(crisp(boxX1), crisp(stopY));
2406
- ctx.stroke();
2407
- ctx.strokeStyle = drawing.color;
2408
- ctx.beginPath();
2409
- ctx.moveTo(crisp(boxX0), crisp(entryY));
2410
- ctx.lineTo(crisp(boxX1), crisp(entryY));
2411
- ctx.stroke();
2412
- ctx.restore();
2413
- drawDrawingHandle(leftX, targetY, drawing.color);
2414
- drawDrawingHandle(leftX, entryY, drawing.color);
2415
- drawDrawingHandle(leftX, stopY, drawing.color);
2416
- drawDrawingHandle(rightX, entryY, drawing.color);
2417
- const tick = getConfiguredTickSize();
2418
- const pctOf = (price) => {
2419
- if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2420
- return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2421
- };
2422
- const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2423
- const targetDist = Math.abs(target.price - entry.price);
2424
- const stopDist = Math.abs(entry.price - stop.price);
2425
- const rr = stopDist > 0 ? targetDist / stopDist : 0;
2426
- const cx = (boxX0 + boxX1) / 2;
2427
- const drawPositionPill = (text, centerX, centerY, bg) => {
2428
- const prevFont = ctx.font;
2429
- ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2430
- const padding = 6;
2431
- const textW = ctx.measureText(text).width;
2432
- const pillW = textW + padding * 2;
2433
- const pillH = 18;
2434
- const pillX = centerX - pillW / 2;
2435
- const pillY = centerY - pillH / 2;
2436
- ctx.fillStyle = bg;
2437
- fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2438
- ctx.fillStyle = "#ffffff";
2439
- ctx.textAlign = "center";
2440
- ctx.textBaseline = "middle";
2441
- ctx.fillText(text, centerX, pillY + pillH / 2);
2442
- ctx.font = prevFont;
2443
- };
2444
- drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2445
- drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2446
- drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2447
- if (drawing.label) {
2448
- drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2406
+ if (isSelected) {
2407
+ ctx.save();
2408
+ ctx.setLineDash([]);
2409
+ ctx.lineWidth = Math.max(1, drawing.width);
2410
+ ctx.strokeStyle = profitLine;
2411
+ ctx.beginPath();
2412
+ ctx.moveTo(crisp(boxX0), crisp(targetY));
2413
+ ctx.lineTo(crisp(boxX1), crisp(targetY));
2414
+ ctx.stroke();
2415
+ ctx.strokeStyle = lossLine;
2416
+ ctx.beginPath();
2417
+ ctx.moveTo(crisp(boxX0), crisp(stopY));
2418
+ ctx.lineTo(crisp(boxX1), crisp(stopY));
2419
+ ctx.stroke();
2420
+ ctx.strokeStyle = drawing.color;
2421
+ ctx.beginPath();
2422
+ ctx.moveTo(crisp(boxX0), crisp(entryY));
2423
+ ctx.lineTo(crisp(boxX1), crisp(entryY));
2424
+ ctx.stroke();
2425
+ ctx.restore();
2426
+ handleAt(leftX, targetY, drawing.color);
2427
+ handleAt(leftX, entryY, drawing.color);
2428
+ handleAt(leftX, stopY, drawing.color);
2429
+ handleAt(rightX, entryY, drawing.color);
2430
+ const tick = getConfiguredTickSize();
2431
+ const pctOf = (price) => {
2432
+ if (!Number.isFinite(entry.price) || entry.price === 0) return "0.00%";
2433
+ return `${((price - entry.price) / Math.abs(entry.price) * 100).toFixed(2)}%`;
2434
+ };
2435
+ const ticksOf = (price) => tick > 0 ? ` ${Math.round(Math.abs(price - entry.price) / tick)}t` : "";
2436
+ const targetDist = Math.abs(target.price - entry.price);
2437
+ const stopDist = Math.abs(entry.price - stop.price);
2438
+ const rr = stopDist > 0 ? targetDist / stopDist : 0;
2439
+ const cx = (boxX0 + boxX1) / 2;
2440
+ const drawPositionPill = (text, centerX, centerY, bg) => {
2441
+ const prevFont = ctx.font;
2442
+ ctx.font = `500 11px ${mergedOptions.fontFamily}`;
2443
+ const padding = 6;
2444
+ const textW = ctx.measureText(text).width;
2445
+ const pillW = textW + padding * 2;
2446
+ const pillH = 18;
2447
+ const pillX = centerX - pillW / 2;
2448
+ const pillY = centerY - pillH / 2;
2449
+ ctx.fillStyle = bg;
2450
+ fillRoundedRect(pillX, pillY, pillW, pillH, 4);
2451
+ ctx.fillStyle = labelTextColor;
2452
+ ctx.textAlign = "center";
2453
+ ctx.textBaseline = "middle";
2454
+ ctx.fillText(text, centerX, pillY + pillH / 2);
2455
+ ctx.font = prevFont;
2456
+ };
2457
+ drawPositionPill(`Target ${formatPrice(target.price)} (${pctOf(target.price)})${ticksOf(target.price)}`, cx, targetY, profitLine);
2458
+ drawPositionPill(`Stop ${formatPrice(stop.price)} (${pctOf(stop.price)})${ticksOf(stop.price)}`, cx, stopY, lossLine);
2459
+ drawPositionPill(`Entry ${formatPrice(entry.price)} RR ${rr.toFixed(2)}`, cx, entryY, hexToRgba(drawing.color, 0.92));
2460
+ if (drawing.label) {
2461
+ drawDrawingLabel(drawing.label, cx, Math.min(targetY, stopY) - 4, drawing.color);
2462
+ }
2449
2463
  }
2450
2464
  }
2451
2465
  }
@@ -3884,7 +3898,8 @@ function createChart(element, options = {}) {
3884
3898
  normalizeDrawingPoint(point.index, stopPrice),
3885
3899
  normalizeDrawingPoint(point.index + width2, entryPrice)
3886
3900
  ],
3887
- color: defaults.color ?? "#2563eb",
3901
+ color: defaults.color ?? (isLong ? "#26a69a" : "#ef5350"),
3902
+ colors: defaults.colors ?? POSITION_DEFAULT_COLORS,
3888
3903
  style: defaults.style ?? "solid",
3889
3904
  width: defaults.width ?? 1
3890
3905
  })
@@ -3902,6 +3917,13 @@ function createChart(element, options = {}) {
3902
3917
  }
3903
3918
  drawingToolDefaults.set(tool, { ...defaults });
3904
3919
  };
3920
+ const setSelectedDrawing = (id) => {
3921
+ if (selectedDrawingId === id) {
3922
+ return;
3923
+ }
3924
+ selectedDrawingId = id;
3925
+ draw();
3926
+ };
3905
3927
  const updateDrawingDrag = (x, y) => {
3906
3928
  if (!drawingDragState) {
3907
3929
  return false;
@@ -4814,6 +4836,7 @@ function createChart(element, options = {}) {
4814
4836
  clearDrawings,
4815
4837
  onDrawingsChange,
4816
4838
  onDrawingSelect,
4839
+ setSelectedDrawing,
4817
4840
  onDrawingHover,
4818
4841
  setDrawingDefaults,
4819
4842
  setDoubleClickEnabled,
@@ -4832,5 +4855,6 @@ function createChart(element, options = {}) {
4832
4855
  }
4833
4856
  export {
4834
4857
  FIB_DEFAULT_PALETTE,
4858
+ POSITION_DEFAULT_COLORS,
4835
4859
  createChart
4836
4860
  };
package/docs/API.md CHANGED
@@ -422,7 +422,7 @@ Drawings are user-created chart tools, separate from indicators. They are intera
422
422
  - `ray`: two-point line that extends infinitely past the second point
423
423
  - `fib-retracement`: two-point retracement with levels/bands
424
424
  - `fib-extension`: trend-based three-point extension (click trend start, trend end, then the projection origin); levels project from the third point by the first→second move
425
- - `long-position` / `short-position`: risk/reward forecasting box (single click drops a default box). Points are `[entry, target, stop, rightEdge]`; anchors are target/entry/stop on the left and a time-width handle on the right. Labels show price, % move, ticks, and risk/reward ratio.
425
+ - `long-position` / `short-position`: risk/reward forecasting box (single click drops a default box). Points are `[entry, target, stop, rightEdge]`; anchors are target/entry/stop on the left and a time-width handle on the right. Labels show price, % move, ticks, and risk/reward ratio. `color` sets the entry line; `colors` is `[profitColor, lossColor, labelTextColor]` (defaults `POSITION_DEFAULT_COLORS`).
426
426
  - `points: DrawingPoint[]`
427
427
  - `visible?: boolean`
428
428
  - `color?: string`
@@ -481,6 +481,7 @@ Use `getDrawings()` / `setDrawings()` for persistence.
481
481
  - `panY(priceDelta: number): void` (positive = move viewport up)
482
482
  - `fitContent(): void` (x-only fit, keeps y zoom)
483
483
  - `resetViewport(): void` (fit x + reset y auto-scale)
484
+ - `setSelectedDrawing(id: string | null): void` (marks a drawing selected; only the selected/drafted drawing renders its handles, and position tools render their lines/labels only while selected)
484
485
  - `setActiveDrawingTool(tool: DrawingToolType | null): void` (`DrawingToolType` = `"horizontal-line" | "vertical-line" | "trendline" | "ray" | "fib-retracement"`)
485
486
  - `getActiveDrawingTool(): DrawingToolType | null`
486
487
  - `setDrawings(drawings: DrawingObjectOptions[]): void`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hyperprop-charting-library",
3
- "version": "0.1.72",
3
+ "version": "0.1.74",
4
4
  "description": "Lightweight TypeScript charting core",
5
5
  "type": "module",
6
6
  "main": "./dist/hyperprop-charting-library.cjs",