openalgo-charts 2.5.4 → 2.5.6

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.
@@ -1,9 +1,9 @@
1
- import { AlertDrawingValue, AlertDrawingLevel, PrimitiveRenderContext, Bar, IPrimitive, DataLayer, AlertDrawingInfo, PrimitiveHost, ZOrder, PrimitiveHit } from 'openalgo-charts';
1
+ import { AlertDrawingValue, AlertDrawingLevel, PrimitiveRenderContext, Bar, PriceScaleId, IndicatorApi, IPrimitive, DataLayer, PlotRect, AlertDrawingInfo, PrimitiveHost, ZOrder, PrimitiveHit } from 'openalgo-charts';
2
2
 
3
3
  /**
4
4
  * The per-tool settings schema: what a host may show in a drawing's settings
5
5
  * dialog, expressed as dot paths into the drawing (`style.color`,
6
- * `text.fontSize`, `props.foo`, `zIndex`) with a control kind and a label.
6
+ * `text.fontSize`, `props.foo`, `zIndex`, `space`) with a control kind and a label.
7
7
  *
8
8
  * The rule the whole module exists for: a tool declares only fields its `draw`
9
9
  * actually reads. A schema is not a wish list. A host renders exactly what is
@@ -20,8 +20,8 @@ type FieldGroup = 'line' | 'fill' | 'text' | 'levels' | 'behavior';
20
20
  interface SettingsField {
21
21
  /**
22
22
  * Dot path into the drawing. Two segments under `style`, `text` or `props`
23
- * (`style.lineWidth`), or one of the top-level flags `locked`, `visible`,
24
- * `zIndex`.
23
+ * (`style.lineWidth`), or one of the top-level fields `locked`, `visible`,
24
+ * `zIndex`, `space`.
25
25
  */
26
26
  path: string;
27
27
  label: string;
@@ -63,6 +63,11 @@ declare const TEXT_POSITION_OPTIONS: ReadonlyArray<{
63
63
  value: string;
64
64
  label: string;
65
65
  }>;
66
+ /** The two coordinate spaces, as a host offers them: follow the bars, or stay on screen. */
67
+ declare const SPACE_OPTIONS: ReadonlyArray<{
68
+ value: DrawingSpace;
69
+ label: string;
70
+ }>;
66
71
  /**
67
72
  * Font stacks a host can offer. Values are real CSS stacks, so a drawing's
68
73
  * `text.fontFamily` needs no translation before it reaches `ctx.font`; a host
@@ -79,6 +84,13 @@ declare const LINE_STYLE_FIELD: SettingsField;
79
84
  declare const LINE_FIELDS: readonly SettingsField[];
80
85
  declare const FILL_FIELDS: readonly SettingsField[];
81
86
  declare const EXTEND_FIELDS: readonly SettingsField[];
87
+ /**
88
+ * Where the drawing is anchored: to time and price, or to the screen. Declared
89
+ * only by tools that set `viewport`, since the controller converts nothing
90
+ * else. Writing it converts the anchors at the view on screen, so the drawing
91
+ * keeps its place and only stops (or starts) following the bars.
92
+ */
93
+ declare const SPACE_FIELD: SettingsField;
82
94
  declare const SHOW_LABELS_FIELD: SettingsField;
83
95
  declare const LEVEL_FIELDS: readonly SettingsField[];
84
96
  /**
@@ -153,6 +165,13 @@ declare function applyDrawingSettings(d: Drawing, patch: Record<string, unknown>
153
165
  * {@link DrawingText}, made `levels` a list of {@link FibLevel} rather than bare
154
166
  * ratios, and gave every drawing a `zIndex`. A 1.9.x document is upgraded by
155
167
  * `migrateDrawings` on the way in; nothing downstream sees the old shape.
168
+ *
169
+ * The one exception to data space is a drawing whose `space` is `'viewport'`:
170
+ * a note or a box that belongs to the screen rather than to a bar. Its anchors
171
+ * are {@link ViewportPoint} fractions of its pane's plot, kept in a field of
172
+ * their own so a time or a price never has to mean a pixel. The field is
173
+ * optional and additive, which is why the document stays version 2: a save
174
+ * with no viewport drawing is byte for byte what it was.
156
175
  */
157
176
 
158
177
  /** One anchor, in data space. */
@@ -167,6 +186,30 @@ interface DrawingPoint {
167
186
  */
168
187
  pressure?: number;
169
188
  }
189
+ /**
190
+ * Which coordinates a drawing's anchors are in. `'data'`, the default, is time
191
+ * and price: the drawing moves with the bars when the chart pans or zooms.
192
+ * `'viewport'` pins it to the screen: its anchors are fractions of its pane's
193
+ * plot, so pan and zoom leave it where it is and a resize keeps it in
194
+ * proportion.
195
+ */
196
+ type DrawingSpace = 'data' | 'viewport';
197
+ /**
198
+ * One anchor of a viewport drawing, as a fraction of the plot area of the pane
199
+ * that holds the drawing. Pane-relative, not whole-chart-relative: the pane's
200
+ * layer paints, clips and hit-tests the drawing, so these are the coordinates
201
+ * that follow the pane when it moves, resizes or folds.
202
+ *
203
+ * `x` is 0 at the plot's left edge and 1 at its right edge; the price axes are
204
+ * outside that span. `y` is 0 at the top of the pane and 1 at the bottom of its
205
+ * plot, which on the lowest pane is the top of the time axis. Sizes that a tool
206
+ * sets in pixels (a font size, a wrap width) stay in pixels: a resize moves a
207
+ * note in proportion without scaling its type.
208
+ */
209
+ interface ViewportPoint {
210
+ x: number;
211
+ y: number;
212
+ }
170
213
  /**
171
214
  * How new anchors snap to the bar under the cursor. `weak` snaps only when an
172
215
  * O/H/L/C sits within a few pixels of the pointer, so a click on empty space
@@ -289,7 +332,15 @@ interface Drawing {
289
332
  id: string;
290
333
  /** Registered tool id. */
291
334
  tool: string;
335
+ /** Anchors in time and price. Empty on a viewport drawing, whose anchors are `viewportPoints`. */
292
336
  points: DrawingPoint[];
337
+ /**
338
+ * Which coordinates the anchors are in. Absent means `'data'`. Only a tool
339
+ * that declares {@link DrawingTool.viewport} can be anchored to the viewport.
340
+ */
341
+ space?: DrawingSpace;
342
+ /** The anchors of a viewport drawing, one per handle. Present only when `space` is `'viewport'`. */
343
+ viewportPoints?: ViewportPoint[];
293
344
  style: DrawingStyle;
294
345
  /** The label (or, for the text tool, the whole content). */
295
346
  text?: DrawingText;
@@ -313,9 +364,20 @@ interface Drawing {
313
364
  /**
314
365
  * Paint order. Below zero paints under the series, at or above zero paints
315
366
  * over it. Ties break by array order, so two drawings at 0 paint in the
316
- * order they sit in the list.
367
+ * order they sit in the list. With `stackAbove` it orders the drawings
368
+ * placed above the same entry.
317
369
  */
318
370
  zIndex: number;
371
+ /**
372
+ * Placed inside the series band, directly above one entry of its pane's
373
+ * `chart.seriesStack()`: `'source:primary'` or `'indicator:<id>'`. It paints
374
+ * after that entry's series and before the next entry's. While the entry
375
+ * plots no series on this drawing's pane (a study removed or moved away) it
376
+ * paints by `zIndex` as if absent, and returns when the entry does. Absent
377
+ * means the drawing is not in the series band. See
378
+ * `DrawingController.placeInStack`.
379
+ */
380
+ stackAbove?: string;
319
381
  /** Epoch ms, set by the controller when the drawing is added. */
320
382
  createdAt?: number;
321
383
  }
@@ -332,8 +394,28 @@ type DrawingInput = Omit<Drawing, 'id' | 'zIndex' | 'createdAt'> & {
332
394
  /**
333
395
  * The fields `DrawingController.update` and `updateMany` can change. `policy`
334
396
  * merges flag by flag, the way `style` does.
397
+ *
398
+ * `space` on its own converts the anchors at the view on screen, so the
399
+ * drawing stays exactly where it is and only stops (or starts) following the
400
+ * bars. With the new space's anchors in the same patch (`viewportPoints` for
401
+ * the viewport, `points` for data) they are taken as given. A conversion the
402
+ * controller cannot make (a tool without viewport support, a pane with no
403
+ * place on screen) is left out of the patch and the rest of it applies, and
404
+ * `DrawingController.update` returns false.
405
+ */
406
+ type DrawingPatch = Partial<Pick<Drawing, 'points' | 'style' | 'text' | 'props' | 'locked' | 'visible' | 'zIndex' | 'policy' | 'space' | 'viewportPoints'>> & {
407
+ /** A series-band entry to paint directly above, or null to leave the series band. */
408
+ stackAbove?: string | null;
409
+ };
410
+ /**
411
+ * What `DrawingController.placeInStack` puts a drawing next to: another
412
+ * drawing of its pane, or an entry of its pane's series band.
335
413
  */
336
- type DrawingPatch = Partial<Pick<Drawing, 'points' | 'style' | 'text' | 'props' | 'locked' | 'visible' | 'zIndex' | 'policy'>>;
414
+ type DrawingStackTarget = {
415
+ drawing: string;
416
+ } | {
417
+ entry: string;
418
+ };
337
419
  /** The persisted shape's version; bumped when {@link Drawing} changes. */
338
420
  declare const DRAWING_STATE_VERSION = 2;
339
421
  /**
@@ -428,6 +510,33 @@ interface DrawingTool {
428
510
  * not what Shift means there.
429
511
  */
430
512
  angleLock?: boolean;
513
+ /**
514
+ * The tool can be anchored to the viewport (`Drawing.space`). Declare it
515
+ * only when `draw` and `distance` read the screen anchors (`pts`) and never
516
+ * `drawing.points`, which is empty in that space, and when nothing the tool
517
+ * prints is a price or a time: a label that reads the axis under a pinned
518
+ * shape would change every time the chart panned. `expand`, `constrain` and
519
+ * `alertValue` apply to data space only.
520
+ */
521
+ viewport?: boolean;
522
+ /**
523
+ * The box the drawing covers at `pts`, its anchors in media px (the space
524
+ * of {@link HitContext}). A drawing anchored to the viewport is always
525
+ * painted, hit-tested and moved with this box inside its pane's plot, so it
526
+ * can be seen and grabbed at every edge and after the chart resizes, and no
527
+ * drag, nudge or handle can take it out. Declare it on a `viewport` tool
528
+ * that paints beyond its anchors, as the text note and the table do from
529
+ * their one corner, and the rectangle and the ellipse do for a label above
530
+ * them or wider than they are; without it the box is the anchors' own
531
+ * bounds. A handle dragged toward an edge the box reaches first stops short
532
+ * of it, so the other anchors stay where they are.
533
+ */
534
+ bounds?(pts: readonly ScreenPoint[], drawing: Drawing): {
535
+ x0: number;
536
+ y0: number;
537
+ x1: number;
538
+ y1: number;
539
+ };
431
540
  /**
432
541
  * Turn the anchors actually clicked into the full anchor set. Lets a tool drop
433
542
  * a complete, immediately editable default from fewer clicks: the position
@@ -567,6 +676,13 @@ declare function fixedRangeVolumeProfileAnalysis(bars: readonly Bar[], fromTime:
567
676
  * The payload body is a drawings document (`DrawingsDocument`), so a copy made
568
677
  * by a 1.9.x build (a version 1 body carrying the old style-bag text fields)
569
678
  * is upgraded by the same migration a saved layout goes through.
679
+ *
680
+ * A `paneIndex` in the payload counts the price pane as 0 and the study panes
681
+ * after it in their order, whatever slot the price pane holds on the chart it
682
+ * came from: `DrawingController` converts on copy and on paste, so a drawing
683
+ * copied beside the candles pastes beside the candles on a chart that keeps
684
+ * its price pane below its studies. On a chart with the price pane on top,
685
+ * the default, that is the chart's own slot, as it always was.
570
686
  */
571
687
 
572
688
  /**
@@ -664,6 +780,33 @@ declare class DrawingClipboard {
664
780
  read(): Promise<Omit<Drawing, 'id'>[] | null>;
665
781
  }
666
782
 
783
+ /** Where a study's price input is picked and anchored: a pane, and a scale on it. */
784
+ interface StudyInputTarget {
785
+ paneIndex: number;
786
+ priceScaleId: PriceScaleId;
787
+ }
788
+ /**
789
+ * One anchor move as an undo step, walked by the drawing history or by the
790
+ * host's timeline it was handed to (`DrawingController.delegateInputAnchorSteps`).
791
+ * Each call writes the other side's point, and is false, writing nothing, once
792
+ * the study no longer holds the point it starts from.
793
+ */
794
+ interface InputAnchorStep {
795
+ undo(): boolean;
796
+ redo(): boolean;
797
+ }
798
+ /**
799
+ * The pane and scale a study's `price` input is picked on and anchored to,
800
+ * or null when that cannot be told. An explicit `pick` target with both
801
+ * halves is used as given. Otherwise the study's own plots decide: the price
802
+ * belongs where they are drawn, which must be one scale on one pane (and
803
+ * inside any half the descriptor did name), since a price read off the wrong
804
+ * scale is a different number.
805
+ */
806
+ declare function studyInputTarget(chart: {
807
+ panes?(): readonly unknown[];
808
+ }, study: IndicatorApi, key: string): StudyInputTarget | null;
809
+
667
810
  /**
668
811
  * Drawing controller: the interaction and persistence layer over
669
812
  * `DrawingLayer`. It is **headless**: no DOM, no toolbar. A host sets the
@@ -728,6 +871,23 @@ interface DrawingChartHost {
728
871
  */
729
872
  timeToCoordinate?(time: number): number;
730
873
  coordinateToTime?(x: number): number;
874
+ /**
875
+ * Optional, for drawings anchored to the viewport (`space: 'viewport'`):
876
+ * the time axis, which turns a data anchor's time into a place on the plot
877
+ * and back when a drawing is pinned or unpinned.
878
+ */
879
+ readonly timeScale?: {
880
+ indexToX(index: number): number;
881
+ xToIndex(x: number): number;
882
+ };
883
+ /**
884
+ * Optional, for drawings anchored to the viewport: a pane's plot in
885
+ * container px, as `Chart.plotRect` reports it, which is what a viewport
886
+ * anchor is a fraction of. A host without it still paints them, since the
887
+ * layer reads the plot size from its render context, but cannot place,
888
+ * move or convert them.
889
+ */
890
+ plotRect?(paneIndex: number): PlotRect | null;
731
891
  /**
732
892
  * Optional. It keeps a paste from a chart with more panes than this one
733
893
  * landing on a pane the user cannot see: adding a primitive creates the pane
@@ -737,6 +897,20 @@ interface DrawingChartHost {
737
897
  * pane the chart maps no price for, one collapsed to its header strip.
738
898
  */
739
899
  panes?(): readonly unknown[];
900
+ /**
901
+ * Optional. Slot of the price pane, the one pane whose drawings the magnet
902
+ * snaps to candle prices and a drawing link shares. It moves when a host
903
+ * puts the price pane below its studies; without it the price pane is slot 0.
904
+ */
905
+ primaryPaneIndex?(): number;
906
+ /**
907
+ * Optional, both: a pane's series band, back to front, and the call that
908
+ * paints a layer directly above one of its entries. Without them no drawing
909
+ * can be placed in the series band, and one saved there paints by its
910
+ * `zIndex`.
911
+ */
912
+ seriesStack?(paneIndex: number): readonly string[];
913
+ setPrimitiveStackAbove?(primitive: IPrimitive, above: string | null): boolean;
740
914
  }
741
915
  interface DrawingControllerOptions {
742
916
  /**
@@ -778,9 +952,46 @@ interface DrawingControllerOptions {
778
952
  */
779
953
  pasteOffsetBars?: number;
780
954
  pasteOffsetPixels?: number;
955
+ /**
956
+ * Draw the anchor of every study input that declares one (a `price` input
957
+ * with a `timeKey` and `anchor: true`): a handle at the point the pair
958
+ * names that drags both as one settings change and one step of this undo
959
+ * history. Default true; false draws none, and the inputs are still edited
960
+ * in settings and picked with `Chart.beginPick('point')`.
961
+ */
962
+ inputAnchors?: boolean;
781
963
  }
782
- /** What `drawing:change` reports happened to the listed ids. */
964
+ /** How `DrawingController.setTool` arms a tool. */
965
+ interface DrawingPlacementOptions {
966
+ /**
967
+ * The space the placed drawing is anchored in. `'viewport'` pins it to the
968
+ * screen: the anchors are placed where they are clicked, as usual, and kept
969
+ * as fractions of the pane's plot from then on. Only a tool that declares
970
+ * `viewport` accepts it. Default `'data'`.
971
+ */
972
+ space?: DrawingSpace;
973
+ }
974
+ /**
975
+ * What `drawing:change` reports happened to the listed ids. The list is empty
976
+ * for a step of the undo history that changed no drawing, a study input
977
+ * anchor's drag and its undo or redo, so a control showing whether Undo is
978
+ * available still refreshes.
979
+ */
783
980
  type DrawingChangeKind = 'add' | 'update' | 'remove' | 'reorder' | 'undo' | 'redo';
981
+ /** The `drawing:change` payload. */
982
+ interface DrawingChangeEvent {
983
+ ids: string[];
984
+ kind: DrawingChangeKind;
985
+ /** Set on a change another chart's link applied; it records no step here. */
986
+ linked?: true;
987
+ /**
988
+ * The undo step this change was recorded as, on the change that closes it.
989
+ * Absent for everything the history does not hold: a host's forced edit, a
990
+ * linked commit, a restore, and a move along the branches (`undo`, `redo`).
991
+ * {@link DrawingController.historySteps} lists the step by this number.
992
+ */
993
+ step?: number;
994
+ }
784
995
  /** Options for a call that changes, groups or deletes drawings. */
785
996
  interface DrawingEditOptions {
786
997
  /**
@@ -818,6 +1029,8 @@ declare class DrawingController {
818
1029
  private readonly _linkedPreviews;
819
1030
  private _destroyed;
820
1031
  private _tool;
1032
+ /** The space the armed tool places in; data whenever no tool is armed. */
1033
+ private _toolSpace;
821
1034
  private _pending;
822
1035
  private _pendingPane;
823
1036
  /** Selected ids, in the order they were picked. The first is the primary. */
@@ -831,6 +1044,8 @@ declare class DrawingController {
831
1044
  * a drag that follows the hand and one that stutters through the candles.
832
1045
  */
833
1046
  private readonly _lifted;
1047
+ /** The slots the series-band drawings were last listed in; see `_slotSignature`. */
1048
+ private _slotKey;
834
1049
  /** Shift as of the last pointer report: what angle lock reads mid-preview. */
835
1050
  private _shift;
836
1051
  /** The device behind the last pointer report, for target sizing. */
@@ -839,6 +1054,9 @@ declare class DrawingController {
839
1054
  private _undo;
840
1055
  private _redo;
841
1056
  private _pendingHistory;
1057
+ /** Depth of `untracked` runs, and the drawings as they were before the host's edit in progress. */
1058
+ private _untracked;
1059
+ private _hostEdit;
842
1060
  /** The host's patches the recorded steps have yet to take, merged per drawing. */
843
1061
  private readonly _hostPatches;
844
1062
  /**
@@ -848,6 +1066,9 @@ declare class DrawingController {
848
1066
  */
849
1067
  private _dragStart;
850
1068
  private readonly _off;
1069
+ private _anchors;
1070
+ /** The host's timeline an anchor step goes to instead of this history; see `delegateInputAnchorSteps`. */
1071
+ private _anchorSteps;
851
1072
  private _lastCursor;
852
1073
  /**
853
1074
  * Bar under the cursor, carried by the crosshair event, with the time the
@@ -856,8 +1077,16 @@ declare class DrawingController {
856
1077
  */
857
1078
  private _lastBar;
858
1079
  constructor(chart: DrawingChartHost, options?: DrawingControllerOptions);
859
- /** Arm a tool for placement, or pass null to return to the cursor. */
860
- setTool(toolId: string | null): void;
1080
+ /**
1081
+ * Arm a tool for placement, or pass null to return to the cursor. With
1082
+ * `options.space` set to `'viewport'` the drawing it places is pinned to the
1083
+ * screen; a tool that cannot be (see `DrawingTool.viewport`) throws.
1084
+ */
1085
+ setTool(toolId: string | null, options?: DrawingPlacementOptions): void;
1086
+ /** The space the armed tool places in: `'data'` unless it was armed for the viewport. */
1087
+ activeToolSpace(): DrawingSpace;
1088
+ /** `draw:tool`, carrying the space only when it is not the default, as the payload always has. */
1089
+ private _emitTool;
861
1090
  /**
862
1091
  * Ask the chart to stop panning and report gestures as anchor placement.
863
1092
  * Guarded so a base bundle predating `setPlacementMode` still loads the tier.
@@ -902,8 +1131,33 @@ declare class DrawingController {
902
1131
  private _regroup;
903
1132
  /** The live group `id`, unless it holds a read-only drawing and the call is not forced. */
904
1133
  private _group;
905
- /** Move one step through the rendered stack, preserving the side of the series. */
1134
+ /**
1135
+ * Move one step through the rendered stack, within the slot it paints in:
1136
+ * its side of the series, or the entry it is placed above. `placeInStack`
1137
+ * moves it between slots.
1138
+ */
906
1139
  reorder(id: string, direction: -1 | 1): boolean;
1140
+ /**
1141
+ * Move a drawing directly above or below `target` in its pane's paint
1142
+ * order, as one undo step. Next to another drawing it joins the slot that
1143
+ * drawing paints in; above a series-band entry (`chart.seriesStack`) it is
1144
+ * placed on that entry, under the drawings already there; below one it goes
1145
+ * on top of the slot under that entry, the drawings behind the series when
1146
+ * the entry is the first. A slot's drawings are renumbered, below the series
1147
+ * up to -1 and elsewhere from 0. False, with nothing recorded, for a target
1148
+ * on another pane, one the host cannot report, or a move that changes nothing.
1149
+ * Like `reorder`, it is outside a drawing's policy.
1150
+ */
1151
+ placeInStack(id: string, target: DrawingStackTarget, where: 'above' | 'below'): boolean;
1152
+ /** A pane's series band as the chart reports it, or none on a host that cannot. */
1153
+ private _entries;
1154
+ /**
1155
+ * The slot a drawing paints in: `entry:<id>` while the entry it is placed
1156
+ * above is in its pane's series band, else its side of the series by `zIndex`.
1157
+ */
1158
+ private _slotOf;
1159
+ /** The drawings of one slot of a pane, in paint order. */
1160
+ private _slotMembers;
907
1161
  private _remapPanes;
908
1162
  drawings(): readonly Drawing[];
909
1163
  get(id: string): Drawing | undefined;
@@ -934,6 +1188,12 @@ declare class DrawingController {
934
1188
  * Patch one drawing. False when there is no such drawing, or when it is
935
1189
  * read-only to the user and `options.force` is not set. A patch that
936
1190
  * carries `policy` is the host's, and like a forced one records no step.
1191
+ *
1192
+ * Also false when the patch asks for a `space` the drawing could not be
1193
+ * moved to (a tool without viewport support, or a pane with no place on
1194
+ * screen, folded or hidden behind a maximized pane): the rest of the patch
1195
+ * still applies, and the false tells a host that the drawing is not in the
1196
+ * space it asked for, which a control showing that space has to say.
937
1197
  */
938
1198
  update(id: string, patch: DrawingPatch, options?: DrawingEditOptions): boolean;
939
1199
  /**
@@ -947,6 +1207,14 @@ declare class DrawingController {
947
1207
  id: string;
948
1208
  patch: DrawingPatch;
949
1209
  }>, options?: DrawingEditOptions): void;
1210
+ /**
1211
+ * A patch as it applies to `d`. A change of space comes out complete, with
1212
+ * the anchors of the new space (converted at the view on screen unless the
1213
+ * patch gives them), or is left out when it cannot be made; anchors of the
1214
+ * space the drawing will not be in are left out too, so one drawing never
1215
+ * carries two positions.
1216
+ */
1217
+ private _spacePatch;
950
1218
  private _applyPatch;
951
1219
  /** Delete one drawing. A read-only one goes only with `options.force`. */
952
1220
  remove(id: string, options?: DrawingEditOptions): boolean;
@@ -977,15 +1245,22 @@ declare class DrawingController {
977
1245
  private _setSelection;
978
1246
  private _emitChange;
979
1247
  setZIndex(id: string, z: number): void;
980
- /** In front of every other drawing on its pane. Stays on its side of the series. */
1248
+ /** In front of every other drawing in its slot: its side of the series, or the entry it is placed above. */
981
1249
  bringToFront(id: string): void;
982
- /** Behind every other drawing on its pane. Stays on its side of the series. */
1250
+ /** Behind every other drawing in its slot: its side of the series, or the entry it is placed above. */
983
1251
  sendToBack(id: string): void;
984
- /** Under the series (`zIndex` -1). A no-op for a drawing already there. */
1252
+ /**
1253
+ * Under the series (`zIndex` -1), out of the series band when it was placed
1254
+ * in it. A no-op for a drawing already there.
1255
+ */
985
1256
  sendBehindSeries(id: string): void;
986
- /** Over the series (`zIndex` 0). A no-op for a drawing already there. */
1257
+ /**
1258
+ * Over the series (`zIndex` 0), out of the series band when it was placed
1259
+ * in it. A no-op for a drawing already there.
1260
+ */
987
1261
  bringAboveSeries(id: string): void;
988
- /** The other drawings sharing `d`'s pane and side of the series. */
1262
+ private _crossSeries;
1263
+ /** The other drawings sharing `d`'s pane and slot. */
989
1264
  private _band;
990
1265
  private _reorder;
991
1266
  /**
@@ -1029,8 +1304,30 @@ declare class DrawingController {
1029
1304
  paste(): Promise<Drawing[]>;
1030
1305
  /** Resolve an id list to live drawings; defaults to the selection. */
1031
1306
  private _targets;
1032
- /** Fold a pane index from another chart onto a pane this one actually has. */
1307
+ /** The slot this chart keeps its price pane in, read at each use because a host can move it. */
1308
+ private _pricePane;
1309
+ /**
1310
+ * Drawings as the clipboard carries them: panes counted price pane first,
1311
+ * the study panes after it in their order, the way a portable template
1312
+ * counts them. A price pane at the top, where every build before the move
1313
+ * kept it, is written exactly as before, and a drawing copied beside the
1314
+ * candles pastes beside the candles on any chart in any arrangement.
1315
+ */
1316
+ private _portable;
1317
+ /**
1318
+ * Fold a clipboard pane onto a pane this chart actually has: clamped to the
1319
+ * pane count in clipboard order, so a study drawing from a taller stack
1320
+ * lands on the last study pane rather than on the price pane, then put in
1321
+ * this chart's own slots around its price pane.
1322
+ */
1033
1323
  private _clampPane;
1324
+ /**
1325
+ * A copy's anchors, offset from the original's in its own space. A viewport
1326
+ * copy moves the paste offset in pixels on both axes, as a fraction of the
1327
+ * pane it lands on, so it reads the same on a chart of any size, and stays
1328
+ * on that pane's plot when the original sits at its edge.
1329
+ */
1330
+ private _offsetAnchors;
1034
1331
  /** Nudge every anchor so a pasted copy is not hidden under its original. */
1035
1332
  private _offsetPoints;
1036
1333
  /**
@@ -1041,6 +1338,40 @@ declare class DrawingController {
1041
1338
  private _offsetPrice;
1042
1339
  /** Move a time right along the screen by `px`. */
1043
1340
  private _offsetTime;
1341
+ /**
1342
+ * Move a study's input anchor (a price input declared with `timeKey` and
1343
+ * `anchor: true`) to `point` as the user, the way dragging its handle does:
1344
+ * the time snaps to the bar under it, both halves stay inside the bounds the
1345
+ * inputs declare, a study the user may not configure refuses it, and the move
1346
+ * is one undo step in this history. For a host control that sets the point
1347
+ * another way, such as a point pick on the chart, so Undo takes it back like
1348
+ * a drag. A point written through the study's settings instead (a settings
1349
+ * dialog's Pick point) is one step of this history as well, unless it is
1350
+ * written inside `untracked` or forced on a study the user may not
1351
+ * configure, which are the host's own. False when the study has no anchor for `key` (or the controller was
1352
+ * built without input anchors), the study refuses, or it already holds the point.
1353
+ */
1354
+ moveInputAnchor(studyId: string, key: string, point: {
1355
+ time: number;
1356
+ price: number;
1357
+ }): boolean;
1358
+ /**
1359
+ * Hand the step each study input anchor move makes (a handle dragged, a
1360
+ * `moveInputAnchor`) to a timeline of the host's instead of this history,
1361
+ * until the returned function gives them back. For a host keeping one undo
1362
+ * history for the whole chart that already records the settings patch the
1363
+ * move writes, as the widget's `ChartHistory` does: held here as well, one
1364
+ * move would be taken back twice, and a press here would reach a step the
1365
+ * other timeline had already taken back. `record` is called once the patch
1366
+ * is written, in the same turn, with the step's own `undo` and `redo`
1367
+ * (each false once the settings have moved on from it); this history
1368
+ * records nothing for it and emits no `drawing:change`. A move made inside
1369
+ * `untracked` is the host's own and reaches neither. A later call takes
1370
+ * the steps from an earlier one. A point written to the settings some other
1371
+ * way, which this history otherwise holds as a step of its own, is not
1372
+ * handed over: the host's timeline sees that write itself.
1373
+ */
1374
+ delegateInputAnchorSteps(record: (step: InputAnchorStep) => void): () => void;
1044
1375
  undo(): boolean;
1045
1376
  redo(): boolean;
1046
1377
  /**
@@ -1052,6 +1383,29 @@ declare class DrawingController {
1052
1383
  private _pruneSelection;
1053
1384
  canUndo(): boolean;
1054
1385
  canRedo(): boolean;
1386
+ /**
1387
+ * The steps each branch holds, oldest first, by the number `drawing:change`
1388
+ * reported them under. For a host that keeps one timeline across drawings
1389
+ * and its own edits: a step missing from both branches has been taken away
1390
+ * (a reset, a trim, a host edit that left it nothing to do), and pressing
1391
+ * undo for it would reach an older step instead. A step still being
1392
+ * recorded, a drag in progress, is not listed until its change closes it.
1393
+ */
1394
+ historySteps(): {
1395
+ undo: number[];
1396
+ redo: number[];
1397
+ };
1398
+ /**
1399
+ * Run `fn` as the host's own act. An edit it makes records no undo step and
1400
+ * leaves both branches as they are, and every step already recorded takes
1401
+ * it in, the way a forced call does, so no later undo or redo reverses it.
1402
+ * Unlike `force` it reaches no read-only drawing, and `undo` or `redo`
1403
+ * inside it still moves along the branches. For a host keeping one timeline
1404
+ * across drawings and its own changes, whose own changes are never steps.
1405
+ */
1406
+ untracked<T>(fn: () => T): T;
1407
+ /** Give every recorded step the host's edit, drawing by drawing and group by group. */
1408
+ private _takeInHostEdit;
1055
1409
  /**
1056
1410
  * Serialisable document, the same shape `ChartState.drawings` carries.
1057
1411
  * Transient drawings (`policy.persistent` false) are left out, and so is
@@ -1069,6 +1423,8 @@ declare class DrawingController {
1069
1423
  */
1070
1424
  fromJSON(data: unknown): void;
1071
1425
  destroy(): void;
1426
+ /** Every layer of every pane. */
1427
+ private _allLayers;
1072
1428
  private _onCrosshair;
1073
1429
  /** The chart's hit-test answer for the pointer position, whenever it changes. */
1074
1430
  private _onHover;
@@ -1177,6 +1533,67 @@ declare class DrawingController {
1177
1533
  private _toPixel;
1178
1534
  /** The inverse of `_toPixel`. */
1179
1535
  private _fromPixel;
1536
+ /**
1537
+ * The drawing's anchors in container media px, the space `timeToCoordinate`
1538
+ * and `priceToCoordinate` answer in, whichever space it is anchored in. What
1539
+ * a host places an overlay by (an inline editor, a popover). Null for an
1540
+ * unknown id, or when the drawing's pane has no place on screen (folded to
1541
+ * a strip, or hidden behind a maximized pane).
1542
+ */
1543
+ screenPoints(id: string): ScreenPoint[] | null;
1544
+ /** A pane's price projection, when the host exposes one. */
1545
+ private _pane;
1546
+ /**
1547
+ * Where a pane's plot is and how big, or null when it has none on screen
1548
+ * (folded to a strip, or hidden behind a maximized pane): a fraction of
1549
+ * either would be a fraction of nothing. It needs a pane projection too,
1550
+ * since every gesture reads its y back through one.
1551
+ */
1552
+ private _plotFrame;
1553
+ /**
1554
+ * A gesture's position on its pane's plot, in media px. y reads the price
1555
+ * back through the pane's readout scale, the exact inverse of how the chart
1556
+ * read it; x is the pointer's container x less the plot's left edge, or,
1557
+ * for a payload without one, the time through the time axis.
1558
+ */
1559
+ private _gesturePlot;
1560
+ /**
1561
+ * Where a drag was pressed, on its pane's plot. Read from the press's time
1562
+ * and price when the chart reports them, so the first move is measured from
1563
+ * the press and not from itself; a chart with fewer than two bars has no
1564
+ * time axis to read a position back from, so it measures from the first move.
1565
+ */
1566
+ private _dragOrigin;
1567
+ /**
1568
+ * Data anchors as fractions of their pane's plot at the view on screen, or
1569
+ * null when it has none. What is on screen stays where it is; a drawing part
1570
+ * way or wholly off the plot comes onto it, since once pinned no pan could
1571
+ * bring it back. One that fits moves in whole. One wider or taller than the
1572
+ * plot is cut to it on that axis instead, so every handle of a pinned box
1573
+ * is on screen to be grabbed.
1574
+ */
1575
+ private _toViewport;
1576
+ /**
1577
+ * The inverse of `_toViewport`: fractions back to time and price at the view
1578
+ * on screen, from where the drawing is painted, so it does not move.
1579
+ */
1580
+ private _fromViewport;
1581
+ /**
1582
+ * Anchors in plot px as the fractions a pinned drawing stores, moved first
1583
+ * so its box lies inside the plot. Every gesture ends here, so what is
1584
+ * stored is what is painted, and no drag can leave the box where the
1585
+ * pointer cannot reach it.
1586
+ */
1587
+ private _pinPlot;
1588
+ /**
1589
+ * Pinned anchors moved by a screen distance in media px, from where the
1590
+ * drawing is painted rather than from what it stores: a note the layer
1591
+ * holds in from a stored place off the plot (a host's value, a larger
1592
+ * chart) moves at once, with no dead travel before it starts.
1593
+ */
1594
+ private _shiftPinned;
1595
+ /** Put a drawing's anchors back as a gesture found them. */
1596
+ private _restoreAnchors;
1180
1597
  /**
1181
1598
  * `free` projected onto the nearest 45 degree ray from `anchor`, all in
1182
1599
  * screen space: the angle the eye reads is the one on the canvas, and a log
@@ -1193,10 +1610,24 @@ declare class DrawingController {
1193
1610
  * adopts it so handles and hit-tests come from one place.
1194
1611
  */
1195
1612
  private _layerFor;
1196
- /** Whether a drawing paints on the top layer: over the series, or lifted for a drag. */
1613
+ /**
1614
+ * Whether a drawing paints on the top layer: over the series and outside
1615
+ * the series band, or lifted for a drag.
1616
+ */
1197
1617
  private _onTop;
1198
1618
  /** Push the current list into each pane's layers and into the chart state. */
1199
1619
  private _sync;
1620
+ /** Each drawing placed in the series band, with the slot it resolves to now. */
1621
+ private _slotSignature;
1622
+ /** List every drawing on the layer of the slot it paints in. */
1623
+ private _syncLayers;
1624
+ /**
1625
+ * One series-band layer per entry a drawing on this pane is placed above,
1626
+ * made on first use and dropped when its last drawing leaves, each painted
1627
+ * by the chart right after its entry. The top layer answers for them,
1628
+ * front to back, then for the layer under the series.
1629
+ */
1630
+ private _syncSeriesLayers;
1200
1631
  /**
1201
1632
  * The per-frame half of a drag: only the top layers of the panes the
1202
1633
  * gesture touches are re-listed, so the repaint stays on the cursor tier.
@@ -1219,6 +1650,21 @@ declare class DrawingController {
1219
1650
  * Angle lock bypasses the magnet, so it hides the ring too.
1220
1651
  */
1221
1652
  private _syncSnapRing;
1653
+ /**
1654
+ * Record a step that is not a drawing edit, a study anchor's move, in the
1655
+ * same history, so Undo walks it and the drawings in the order they were
1656
+ * made. Like any new edit it clears the redo branch. An `outside` move was
1657
+ * written to the settings by someone else (a settings dialog's Pick point):
1658
+ * it ends no drawing drag, and a host timeline the steps are handed to saw
1659
+ * that write itself, so only this history takes it.
1660
+ */
1661
+ private _recordStep;
1662
+ /**
1663
+ * Announce a move of the history that changed no drawing, with no ids, so
1664
+ * a host's Undo and Redo controls, which refresh on `drawing:change`,
1665
+ * follow it. Passes `applied` through.
1666
+ */
1667
+ private _external;
1222
1668
  private _pushUndo;
1223
1669
  /**
1224
1670
  * Open an edit: recorded, or, for a change the history does not hold (a
@@ -1250,7 +1696,7 @@ type DrawingLinkContextSource = DrawingLinkContext | (() => DrawingLinkContext |
1250
1696
  interface DrawingLinkOptions {
1251
1697
  enabled?: boolean;
1252
1698
  }
1253
- interface DrawingLinkChart extends Pick<DrawingChartHost, 'on'> {
1699
+ interface DrawingLinkChart extends Pick<DrawingChartHost, 'on' | 'primaryPaneIndex'> {
1254
1700
  readonly isDestroyed?: boolean;
1255
1701
  getDataContext?(): Readonly<DrawingLinkContext> | undefined;
1256
1702
  }
@@ -1258,6 +1704,14 @@ interface DrawingLinkChart extends Pick<DrawingChartHost, 'on'> {
1258
1704
  * Existing local drawings stay local until `share` is called. Persisted shared
1259
1705
  * lineage reconnects across restores. Only price-pane drawings participate; time anchors
1260
1706
  * cross the boundary unchanged so each interval uses its own coordinate map.
1707
+ *
1708
+ * The price pane is each chart's own, in whatever slot that chart keeps it: one
1709
+ * chart can hold it at the top and another below its studies. A shared drawing
1710
+ * is therefore kept on slot 0 and put on each member's price pane as it is
1711
+ * applied there, never copied across by slot.
1712
+ *
1713
+ * A drawing pinned to the viewport never participates, and pinning a shared one
1714
+ * takes it out of the link on that chart alone: the other charts keep their copy.
1261
1715
  */
1262
1716
  declare class DrawingLinkGroup {
1263
1717
  private readonly _members;
@@ -1276,10 +1730,32 @@ declare class DrawingLinkGroup {
1276
1730
  /** Committed drawings remain on peers; transient previews are discarded. */
1277
1731
  remove(chart: DrawingLinkChart): void;
1278
1732
  destroy(): void;
1733
+ /** The slot this member keeps its price pane in, read at each use because it moves. */
1734
+ private _pricePane;
1735
+ /** A shared drawing as it lands on one member: on that member's own price pane. */
1736
+ private _onPricePane;
1279
1737
  private _eligible;
1280
1738
  private _create;
1281
1739
  private _reconnect;
1282
1740
  private _change;
1741
+ /**
1742
+ * A shared drawing pinned to the screen leaves the link on this chart. Its
1743
+ * lineage mark goes too, or a restore would find the peers' copy by it and
1744
+ * pull the drawing back to where they keep it.
1745
+ */
1746
+ private _unlink;
1747
+ /**
1748
+ * An unbound drawing that carries this chart's lineage mark, while a peer
1749
+ * still holds that lineage, is one that left the link by being pinned and
1750
+ * came back by undo: the undo put the mark back but no binding. It joins
1751
+ * again, as the newest edit, so its state goes to the peers the way any
1752
+ * other undo on a linked drawing does. If the peers have since deleted
1753
+ * their copies it stays on this chart alone and loses the mark, since an
1754
+ * edit never brings back another chart's deletion, and a later restore
1755
+ * must not apply that deletion here. A mark no peer holds is left for a
1756
+ * peer that has yet to join, as after any restore.
1757
+ */
1758
+ private _rejoin;
1283
1759
  private _commit;
1284
1760
  private _preview;
1285
1761
  private _syncOrder;
@@ -1599,16 +2075,23 @@ declare const DEFAULT_FIB_TIME_ZONE: readonly FibLevel[];
1599
2075
  * result read as sixty icons rather than as one set, however carefully any
1600
2076
  * single glyph was made. A shipped set is worth more than a better glyph.
1601
2077
  *
1602
- * # Two tiers, one weight
2078
+ * # Two tiers, one line
1603
2079
  *
1604
2080
  * Tool glyphs live on a 24-unit grid and are shown at 24px in the rail. Host
1605
2081
  * chrome (undo, close, the settings tab rail) is shown at 16px beside them, and
1606
2082
  * a 24-grid glyph scaled to 16 lands its 2-unit stroke on 1.33 pixels, blurred
1607
2083
  * across two rows on every edge. So chrome has its own registry drawn on a
1608
- * 16-unit grid with a 1.5 stroke. The two strokes are deliberately not in exact
1609
- * proportion: a small glyph needs a slightly heavier relative stroke than a
1610
- * large one to read as the same weight, and `tests/draw-icons.test.ts` holds
1611
- * the chrome tier inside that band rather than at parity.
2084
+ * 16-unit grid. Both tiers draw a 2-unit stroke, and since each is shown at its
2085
+ * grid size, that is the same 2px line on screen in both rails: a lock under
2086
+ * the tools reads as part of the same set, only smaller.
2087
+ *
2088
+ * The chrome stroke was 1.5 through 2.5.5, chosen to match the tool weight as a
2089
+ * fraction of the box. On integer coordinates a 1.5 stroke covers 0.75 of two
2090
+ * pixel rows, so no edge was ever solid (0.18 of its inked pixels, against 0.59
2091
+ * for the tools). A 1px stroke on half-unit coordinates was tried as well: as
2092
+ * crisp on straight edges, but faint on every curve and visibly lighter than
2093
+ * the tool rail beside it, on both themes. Two it is, with the few glyphs that
2094
+ * were too dense for it redrawn with more air.
1612
2095
  *
1613
2096
  * # The grid
1614
2097
  *
@@ -1618,16 +2101,21 @@ declare const DEFAULT_FIB_TIME_ZONE: readonly FibLevel[];
1618
2101
  *
1619
2102
  * - **One viewBox per tier.** 24 by 24 for tools, 16 by 16 for chrome, so a
1620
2103
  * host sets the size once per surface.
1621
- * - **A margin all round.** Live area 2 to 22 on the tool grid, 1 to 15 on the
1622
- * chrome grid. Without it, glyphs that happen to reach the edge look larger
1623
- * than their neighbours and the rail reads as ragged.
1624
- * - **Integer coordinates.** With `STROKE` of 2, an orthogonal edge centred on
2104
+ * - **A margin all round.** Live area 2 to 22 on the tool grid, 2 to 14 on the
2105
+ * chrome grid, so the ink stops a pixel short of the box. Without it,
2106
+ * glyphs that happen to reach the edge look larger than their neighbours
2107
+ * and the rail reads as ragged.
2108
+ * - **Integer coordinates.** With a stroke of 2, an orthogonal edge centred on
1625
2109
  * an integer covers exactly two device pixels at 1:1, which is what makes it
1626
- * crisp. Half-unit coordinates were the previous set's crispness bug: at a
1627
- * 1.5 stroke on integers, nothing landed on a pixel boundary at any size.
1628
- * - **One stroke weight per tier.** Three different weights across identically
1629
- * sized boxes is the single most visible tell of a set assembled rather than
1630
- * drawn.
2110
+ * crisp.
2111
+ * - **One stroke weight.** Different weights across identically sized boxes
2112
+ * is the single most visible tell of a set assembled rather than drawn.
2113
+ * - **The whole glyph in its path.** The marks that tell siblings apart (a
2114
+ * segment ends in two dots, a ray starts at one, a path ends in a head)
2115
+ * are small closed shapes drawn in the path itself, so a host that renders
2116
+ * the path data and nothing else still gets every one of them. An accent
2117
+ * registry repeats those marks for a fill on top: a dot then paints solid
2118
+ * rather than as a ring, which adds weight, never identity.
1631
2119
  *
1632
2120
  * # Rendering
1633
2121
  *
@@ -1671,9 +2159,23 @@ declare const ICON_ATTRS: {
1671
2159
  *
1672
2160
  * Values are the `d` attribute of one `<path>`. Multiple subpaths are joined
1673
2161
  * into the same string rather than split across elements, so a host renders one
1674
- * node per glyph.
2162
+ * node per glyph, and that node is the whole glyph: its dots and heads are in
2163
+ * the string as outlines. `DRAWING_TOOL_ACCENTS` repeats those marks for a
2164
+ * host that also wants them filled.
1675
2165
  */
1676
2166
  declare const DRAWING_TOOL_ICONS: Readonly<Record<string, string>>;
2167
+ /**
2168
+ * The fills of the tool glyphs' marks, by tool id: anchor dots, pole caps and
2169
+ * arrowheads. Optional: most glyphs have none.
2170
+ *
2171
+ * Every mark here is also drawn, as an outline, in the glyph's own path, so a
2172
+ * host that renders only `DRAWING_TOOL_ICONS` still shows each one. This adds
2173
+ * the fill: a second `<path>` painted in `currentColor` with no stroke of its
2174
+ * own, after the glyph's path. The markup builders in `icon-svg.ts` add it; a
2175
+ * host wrapping the path data itself adds
2176
+ * `<path d="..." fill="currentColor" stroke="none"/>` for the same result.
2177
+ */
2178
+ declare const DRAWING_TOOL_ACCENTS: Readonly<Record<string, string>>;
1677
2179
  /**
1678
2180
  * The glyph for a tool, or `undefined` when it has none.
1679
2181
  *
@@ -1681,29 +2183,40 @@ declare const DRAWING_TOOL_ICONS: Readonly<Record<string, string>>;
1681
2183
  * visible gap to fix, while one handed a question mark ships it.
1682
2184
  */
1683
2185
  declare function drawingToolIcon(toolId: string): string | undefined;
2186
+ /** The filled accent for a tool glyph, or `undefined` when it has none. */
2187
+ declare function drawingToolAccent(toolId: string): string | undefined;
1684
2188
  /** Every id this set covers, for a host building a palette from it. */
1685
2189
  declare function drawingToolIconIds(): string[];
1686
2190
  /** The viewBox every chrome glyph is authored in. */
1687
2191
  declare const CHROME_ICON_VIEWBOX = "0 0 16 16";
1688
2192
  /**
1689
- * Chrome stroke width in viewBox units. Not the tool stroke scaled (that would
1690
- * be 1.33): at 16px a glyph needs a touch more relative weight than at 24px to
1691
- * read as the same line, and 1.5 is where the two rails match by eye.
2193
+ * Chrome stroke width in viewBox units. The same 2 as the tool tier, which at
2194
+ * the two native sizes is the same 2px line on screen. It was 1.5 through 2.5.5:
2195
+ * matched to the tool weight as a fraction of the box, and never crisp, since
2196
+ * a 1.5 stroke on whole units puts every edge three quarters of the way
2197
+ * across a pixel. See the file comment for the 1px alternative and why it
2198
+ * lost.
1692
2199
  */
1693
- declare const CHROME_ICON_STROKE = 1.5;
2200
+ declare const CHROME_ICON_STROKE = 2;
1694
2201
  /** Attributes a host should apply to the `<svg>` around a chrome glyph. */
1695
2202
  declare const CHROME_ICON_ATTRS: {
1696
2203
  readonly viewBox: "0 0 16 16";
1697
2204
  readonly fill: "none";
1698
2205
  readonly stroke: "currentColor";
1699
- readonly strokeWidth: 1.5;
2206
+ readonly strokeWidth: 2;
1700
2207
  readonly strokeLinecap: "round";
1701
2208
  readonly strokeLinejoin: "round";
1702
2209
  };
1703
2210
  /**
1704
2211
  * Path data for host chrome: the buttons around the chart rather than the
1705
- * tools in it. Same rules as the tool tier (one path per glyph, no presentation
1706
- * attributes, integer coordinates) on the 16 grid with a 1..15 live area.
2212
+ * tools in it. Same rules as the tool tier (the whole glyph in one path, its
2213
+ * marks included; no presentation attributes; integer coordinates) on the 16
2214
+ * grid with a 2..14 live area.
2215
+ *
2216
+ * At a 2px line a 16px glyph has room for about four parallel strokes with a
2217
+ * pixel between them, so the dense glyphs are drawn with that in mind: two
2218
+ * sliders rather than three, a lens and a pupil as small solid dots rather
2219
+ * than rings, and no plus squeezed inside a square.
1707
2220
  *
1708
2221
  * The pair `cursor` / `magnet` / `text` also exist in the tool registry, at 24.
1709
2222
  * They are drawn twice on purpose: a rail button and a toolbar button are
@@ -1711,6 +2224,13 @@ declare const CHROME_ICON_ATTRS: {
1711
2224
  * drawing to both.
1712
2225
  */
1713
2226
  declare const CHROME_ICONS: Readonly<Record<string, string>>;
2227
+ /**
2228
+ * The fills of the chrome glyphs' marks, as `DRAWING_TOOL_ACCENTS` is for the
2229
+ * tools: each mark is outlined in the glyph's path, and this paints it solid.
2230
+ * At 16px a ring of a 2px line is mostly line already, so the fill matters
2231
+ * most for the slider knobs.
2232
+ */
2233
+ declare const CHROME_ICON_ACCENTS: Readonly<Record<string, string>>;
1714
2234
  /**
1715
2235
  * Chrome glyphs meant to be painted solid. Paths carry no presentation
1716
2236
  * attributes, so the fill is applied by the wrapper (`chromeIconSvg` does it,
@@ -1719,6 +2239,8 @@ declare const CHROME_ICONS: Readonly<Record<string, string>>;
1719
2239
  declare const CHROME_ICON_FILLED: ReadonlySet<string>;
1720
2240
  /** The chrome glyph for an id, or `undefined` when there is none. */
1721
2241
  declare function chromeIcon(id: string): string | undefined;
2242
+ /** The filled accent for a chrome glyph, or `undefined` when it has none. */
2243
+ declare function chromeIconAccent(id: string): string | undefined;
1722
2244
  /** Every id the chrome tier covers. */
1723
2245
  declare function chromeIconIds(): string[];
1724
2246
 
@@ -1771,8 +2293,10 @@ declare function chromeIconSvg(id: string, opts?: IconSvgOptions): string;
1771
2293
  /**
1772
2294
  * One hidden `<svg>` of `<symbol>`s, for a host that shows many glyphs and
1773
2295
  * wants each path in the document once. Inject it once, then place glyphs with
1774
- * `iconUse`. Symbols carry the path and viewBox only; stroke and fill inherit
1775
- * from the `<svg>` around each `<use>`, so one sprite serves every weight.
2296
+ * `iconUse`. Symbols carry the paths and viewBox, and no stroke: the weight
2297
+ * inherits from the `<svg>` around each `<use>`, so one sprite serves every
2298
+ * weight. An accent carries its fill, the one attribute it cannot inherit,
2299
+ * and no stroke, since the glyph's own path outlines it.
1776
2300
  *
1777
2301
  * Default: every tool glyph. Repeated ids collapse to one symbol, since a
1778
2302
  * duplicate element id is an invalid document.
@@ -1782,12 +2306,12 @@ declare function iconSprite(ids?: readonly string[]): string;
1782
2306
  declare function iconUse(id: string, opts?: IconSvgOptions): string;
1783
2307
  /**
1784
2308
  * A CSS `cursor` value carrying the tool's glyph, for the canvas while that
1785
- * tool is armed.
2309
+ * tool is the active one.
1786
2310
  *
1787
2311
  * The glyph is drawn twice: once in `halo`, one pixel wider on each side, and
1788
- * once in `color` on top, so it reads on a light chart and a dark one without
1789
- * the host choosing per theme. The value is `url("data:image/svg+xml,...") x y,
1790
- * fallback`, ready for `canvas.style.cursor`.
2312
+ * once in `color` on top with its marks filled, so it reads on a light chart
2313
+ * and a dark one without the host choosing per theme. The value is
2314
+ * `url("data:image/svg+xml,...") x y, fallback`, ready for `canvas.style.cursor`.
1791
2315
  */
1792
2316
  declare function toolCursor(id: string, opts?: ToolCursorOptions): string;
1793
2317
 
@@ -1798,15 +2322,25 @@ declare function toolCursor(id: string, opts?: ToolCursorOptions): string;
1798
2322
  * between bars (inside a collapsed weekend) or past the last one (a forward
1799
2323
  * projection), and whole-index lookups have nothing to return there.
1800
2324
  *
1801
- * Each pane carries **two** layers, one at z-order `bottom` for drawings with a
1802
- * negative `zIndex` (under the series) and one at `top` for the rest. The top
1803
- * one takes over handles and hit-testing for the pair through `setBelow`, so a
1804
- * shape parked under the candles still shows its grab handles above them and
1805
- * a click lands on whatever the eye sees on top.
2325
+ * Each pane carries a `bottom` layer for drawings with a negative `zIndex`
2326
+ * (under the series), a `top` one for the rest, and a `series` layer for each
2327
+ * series-band entry a drawing is placed above (`stackAbove`), which the chart
2328
+ * paints right after that entry's series. The top one takes over handles and
2329
+ * hit-testing for the others through `setBelow`, so a shape parked under the
2330
+ * candles still shows its grab handles above them and a click lands on
2331
+ * whatever the eye sees on top: the top layer's bodies first, then each layer
2332
+ * under it in the order they paint, front to back.
1806
2333
  *
1807
2334
  * Hit ids are `draw:<id>` for the body and `draw:<id>#<n>` for anchor `n`, so
1808
2335
  * the controller can tell "move the whole shape" from "move this handle".
1809
2336
  *
2337
+ * A viewport drawing (`space: 'viewport'`) skips the time and price mapping:
2338
+ * its anchors are fractions of this pane's plot and scale by the plot size in
2339
+ * the render context, which is all that pan and zoom never touch. The one step
2340
+ * added is keeping its box inside the plot. Everything after the projection
2341
+ * (paint, handles, hit-testing) is shared, so the two spaces cannot drift
2342
+ * apart in how they are grabbed.
2343
+ *
1810
2344
  * The hover ring, the magnet ring and the hover handles are all overlay
1811
2345
  * state: they change on every pointer move, so they must only ever cost the
1812
2346
  * top canvas. The layer that paints them is the one whose `requestUpdate`
@@ -1814,8 +2348,11 @@ declare function toolCursor(id: string, opts?: ToolCursorOptions): string;
1814
2348
  * stores that state and asks for nothing.
1815
2349
  */
1816
2350
 
1817
- /** Which side of the series a layer paints on. */
1818
- type DrawingLayerOrder = 'bottom' | 'top';
2351
+ /**
2352
+ * Where a layer paints: under the series, in the series band (placed above an
2353
+ * entry by the controller, and over the series while it is not), or on top.
2354
+ */
2355
+ type DrawingLayerOrder = 'bottom' | 'series' | 'top';
1819
2356
  /** The pointer kinds the layer sizes its targets for. */
1820
2357
  type DrawingPointerKind = 'mouse' | 'touch' | 'pen';
1821
2358
  /**
@@ -1835,7 +2372,7 @@ declare class DrawingLayer implements IPrimitive {
1835
2372
  private _snap;
1836
2373
  /** Anchors of the in-progress drawing, plus the live cursor point. */
1837
2374
  private _preview;
1838
- /** The layer under this one, whose handles and hits this layer answers for. */
2375
+ /** The layers under this one, front to back, whose handles and hits this layer answers for. */
1839
2376
  private _below;
1840
2377
  /** The layer that has taken over this one's handles and hit-testing. */
1841
2378
  private _above;
@@ -1873,13 +2410,14 @@ declare class DrawingLayer implements IPrimitive {
1873
2410
  setPointerType(kind: DrawingPointerKind | null | undefined): void;
1874
2411
  setPreview(drawing: Drawing | null): void;
1875
2412
  /**
1876
- * Adopt the layer under this one. From then on this layer paints the handles
1877
- * of both and answers `hitTest` for both, and the adopted layer paints bodies
2413
+ * Adopt the layers under this one, front to back: the order they paint in,
2414
+ * reversed. From then on this layer paints the handles of all of them and
2415
+ * answers `hitTest` for all of them, and the adopted layers paint bodies
1878
2416
  * only. Handles have to live up here: a selected drawing under the series
1879
2417
  * would otherwise have its handles buried under the candles, and a handle
1880
2418
  * you cannot see is a handle you cannot grab. Pass null to release.
1881
2419
  */
1882
- setBelow(layer: DrawingLayer | null): void;
2420
+ setBelow(layer: DrawingLayer | readonly DrawingLayer[] | null): void;
1883
2421
  /** Repaint for overlay-only state, from the layer that paints it. */
1884
2422
  private _requestOverlay;
1885
2423
  /** Whether targets are sized for a fingertip on this call. */
@@ -2008,6 +2546,11 @@ declare function keyToDrawingAction(e: DrawingKeyEvent, ctx: DrawingKeyContext):
2008
2546
  * - An unregistered tool is not a reason to drop anything: a plugin tool may
2009
2547
  * register after the layout is restored. This module never consults the
2010
2548
  * registry, which also keeps it pure.
2549
+ * - A viewport drawing keeps its `viewportPoints` and carries no data
2550
+ * anchors; one without usable viewport anchors is dropped, since falling
2551
+ * back to its data anchors would put it somewhere it never was. Data is the
2552
+ * default space and is never written out, so a document with no viewport
2553
+ * drawing comes back exactly as it went in.
2011
2554
  * - Garbage yields an empty document. This runs on the load path, where an
2012
2555
  * exception would take the whole chart down with it.
2013
2556
  *
@@ -2117,4 +2660,4 @@ declare const PATTERN_DRAWING_TOOLS: readonly DrawingTool[];
2117
2660
 
2118
2661
  declare const DRAW_TIER: "draw";
2119
2662
 
2120
- export { ADVANCED_GEOMETRY_TOOLS, ADVANCED_LINE_TOOLS, ALIGN_OPTIONS, ANCHORED_VWAP, ARC, ARROW, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, type AnalysisProfileRow, type AnalysisStatus, type AnchoredVwapOptions, type AnchoredVwapPoint, type AnchoredVwapResult, type AnchoredVwapSource, BALLOON, BRUSH, BUILTIN_DRAWING_TOOLS, CALLOUT, CHROME_ICONS, CHROME_ICON_ATTRS, CHROME_ICON_FILLED, CHROME_ICON_STROKE, CHROME_ICON_VIEWBOX, CIRCLE, COLOR_FIELD, COMMENT, CROSS_LINE, CURVE, CYCLE_PALETTE, CYCLIC_LINES, type ClipboardPort, DATE_RANGE, DEFAULT_FIB, DEFAULT_FIB_FAN, DEFAULT_FIB_TIME_ZONE, DEFAULT_GANN_BOX, DEFAULT_GANN_FAN, DOUBLE_CURVE, DRAWING_CLIPBOARD_KEY, DRAWING_CLIPBOARD_VERSION, DRAWING_STATE_VERSION, DRAWING_TOOL_ICONS, DRAW_TIER, type DrawContext, type Drawing, type DrawingChangeKind, type DrawingChartHost, DrawingClipboard, type DrawingClipboardOptions, DrawingController, type DrawingControllerOptions, type DrawingEditOptions, type DrawingGroup, type DrawingInput, type DrawingKeyAction, type DrawingKeyContext, type DrawingKeyEvent, DrawingLayer, type DrawingLayerOrder, type DrawingLinkChart, type DrawingLinkContext, type DrawingLinkContextSource, DrawingLinkGroup, type DrawingLinkOptions, type DrawingPatch, type DrawingPoint, type DrawingPointerKind, type DrawingPolicy, type DrawingStyle, type DrawingText, type DrawingTool, type DrawingValueContext, type DrawingsDocument, ELLIPSE, EXTENDED_LINE, EXTEND_FIELDS, type ExpandContext, FIB_CHANNEL, FIB_EXTENSION, FIB_FAN, FIB_RETRACEMENT, FIB_TIME_ZONE, FILL_FIELDS, FIXED_RANGE_VOLUME_PROFILE, FLAG_MARK, FONT_FIELDS, FONT_OPTIONS, FORECAST, type FibLevel, type FieldGroup, type FieldKind, type FixedRangeVolumeProfileOptions, type FixedRangeVolumeProfileResult, GANN_BOX, GANN_FAN, HIGHLIGHTER, HORIZONTAL_LINE, HORIZONTAL_RAY, type HitContext, ICON_ATTRS, ICON_STROKE, ICON_SYMBOL_PREFIX, ICON_VIEWBOX, type IconAttrs, type IconSvgOptions, LEVEL_FIELDS, LEVEL_NEUTRAL, LINE_FIELDS, LINE_STYLE_FIELD, LINE_STYLE_OPTIONS, LINE_WIDTH_FIELD, LONG_POSITION, MEASURE, type MagnetMode, NOTE, NUDGE_STEP_PX, NUDGE_STEP_SHIFT_PX, PARALLEL_CHANNEL, PATH, PATTERN_DRAWING_TOOLS, PLATE_TEXT_FIELDS, POLYLINE, PRICE_LABEL, PRICE_NOTE, PRICE_RANGE, RAY, RECTANGLE, ROTATED_RECTANGLE, SHAPE_TEXT_FIELDS, SHORT_POSITION, SHOW_LABELS_FIELD, SIGNPOST, SINE_LINE, type ScreenPoint, type SettingsField, type SettingsSchema, type ShortcutEvent, TABLE, TEXT, TEXT_FIELDS, TEXT_POSITION_OPTIONS, TEXT_VALUE_FIELD, TIME_CYCLES, TREND_LINE, TRIANGLE, type ToolCursorOptions, VALIGN_OPTIONS, VERTICAL_LINE, anchoredVwapAnalysis, applyDrawingSettings, boundsOf, catmullRom, chromeIcon, chromeIconIds, chromeIconSvg, clearMemoryClipboard, cloneDrawing, cloneLevels, coerceSettingValue, composeSettings, createDrawingLinkGroup, cycleColor, decodeClipboardPayload, distToEllipse, distToLine, distToPolyline, distToRect, distToSegment, drawingSettingsSchema, drawingShortcuts, drawingToolIcon, drawingToolIconIds, encodeClipboardPayload, extendSegment, fixedRangeVolumeProfileAnalysis, formatRatio, gannLabel, getDrawingTool, hasDrawingTool, iconSprite, iconSvg, iconUse, keyToDrawingAction, levelColor, matchDrawingShortcut, migrateDrawings, pressureWidth, rdpSimplify, readDrawingSetting, readDrawingSettings, rectOf, registerBuiltinDrawingTools, registerDrawingTool, registeredDrawingTools, sanitizeDrawing, sortByZIndex, systemClipboard, toolCursor };
2663
+ export { ADVANCED_GEOMETRY_TOOLS, ADVANCED_LINE_TOOLS, ALIGN_OPTIONS, ANCHORED_VWAP, ARC, ARROW, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT, ARROW_UP, type AnalysisProfileRow, type AnalysisStatus, type AnchoredVwapOptions, type AnchoredVwapPoint, type AnchoredVwapResult, type AnchoredVwapSource, BALLOON, BRUSH, BUILTIN_DRAWING_TOOLS, CALLOUT, CHROME_ICONS, CHROME_ICON_ACCENTS, CHROME_ICON_ATTRS, CHROME_ICON_FILLED, CHROME_ICON_STROKE, CHROME_ICON_VIEWBOX, CIRCLE, COLOR_FIELD, COMMENT, CROSS_LINE, CURVE, CYCLE_PALETTE, CYCLIC_LINES, type ClipboardPort, DATE_RANGE, DEFAULT_FIB, DEFAULT_FIB_FAN, DEFAULT_FIB_TIME_ZONE, DEFAULT_GANN_BOX, DEFAULT_GANN_FAN, DOUBLE_CURVE, DRAWING_CLIPBOARD_KEY, DRAWING_CLIPBOARD_VERSION, DRAWING_STATE_VERSION, DRAWING_TOOL_ACCENTS, DRAWING_TOOL_ICONS, DRAW_TIER, type DrawContext, type Drawing, type DrawingChangeEvent, type DrawingChangeKind, type DrawingChartHost, DrawingClipboard, type DrawingClipboardOptions, DrawingController, type DrawingControllerOptions, type DrawingEditOptions, type DrawingGroup, type DrawingInput, type DrawingKeyAction, type DrawingKeyContext, type DrawingKeyEvent, DrawingLayer, type DrawingLayerOrder, type DrawingLinkChart, type DrawingLinkContext, type DrawingLinkContextSource, DrawingLinkGroup, type DrawingLinkOptions, type DrawingPatch, type DrawingPlacementOptions, type DrawingPoint, type DrawingPointerKind, type DrawingPolicy, type DrawingSpace, type DrawingStackTarget, type DrawingStyle, type DrawingText, type DrawingTool, type DrawingValueContext, type DrawingsDocument, ELLIPSE, EXTENDED_LINE, EXTEND_FIELDS, type ExpandContext, FIB_CHANNEL, FIB_EXTENSION, FIB_FAN, FIB_RETRACEMENT, FIB_TIME_ZONE, FILL_FIELDS, FIXED_RANGE_VOLUME_PROFILE, FLAG_MARK, FONT_FIELDS, FONT_OPTIONS, FORECAST, type FibLevel, type FieldGroup, type FieldKind, type FixedRangeVolumeProfileOptions, type FixedRangeVolumeProfileResult, GANN_BOX, GANN_FAN, HIGHLIGHTER, HORIZONTAL_LINE, HORIZONTAL_RAY, type HitContext, ICON_ATTRS, ICON_STROKE, ICON_SYMBOL_PREFIX, ICON_VIEWBOX, type IconAttrs, type IconSvgOptions, type InputAnchorStep, LEVEL_FIELDS, LEVEL_NEUTRAL, LINE_FIELDS, LINE_STYLE_FIELD, LINE_STYLE_OPTIONS, LINE_WIDTH_FIELD, LONG_POSITION, MEASURE, type MagnetMode, NOTE, NUDGE_STEP_PX, NUDGE_STEP_SHIFT_PX, PARALLEL_CHANNEL, PATH, PATTERN_DRAWING_TOOLS, PLATE_TEXT_FIELDS, POLYLINE, PRICE_LABEL, PRICE_NOTE, PRICE_RANGE, RAY, RECTANGLE, ROTATED_RECTANGLE, SHAPE_TEXT_FIELDS, SHORT_POSITION, SHOW_LABELS_FIELD, SIGNPOST, SINE_LINE, SPACE_FIELD, SPACE_OPTIONS, type ScreenPoint, type SettingsField, type SettingsSchema, type ShortcutEvent, type StudyInputTarget, TABLE, TEXT, TEXT_FIELDS, TEXT_POSITION_OPTIONS, TEXT_VALUE_FIELD, TIME_CYCLES, TREND_LINE, TRIANGLE, type ToolCursorOptions, VALIGN_OPTIONS, VERTICAL_LINE, type ViewportPoint, anchoredVwapAnalysis, applyDrawingSettings, boundsOf, catmullRom, chromeIcon, chromeIconAccent, chromeIconIds, chromeIconSvg, clearMemoryClipboard, cloneDrawing, cloneLevels, coerceSettingValue, composeSettings, createDrawingLinkGroup, cycleColor, decodeClipboardPayload, distToEllipse, distToLine, distToPolyline, distToRect, distToSegment, drawingSettingsSchema, drawingShortcuts, drawingToolAccent, drawingToolIcon, drawingToolIconIds, encodeClipboardPayload, extendSegment, fixedRangeVolumeProfileAnalysis, formatRatio, gannLabel, getDrawingTool, hasDrawingTool, iconSprite, iconSvg, iconUse, keyToDrawingAction, levelColor, matchDrawingShortcut, migrateDrawings, pressureWidth, rdpSimplify, readDrawingSetting, readDrawingSettings, rectOf, registerBuiltinDrawingTools, registerDrawingTool, registeredDrawingTools, sanitizeDrawing, sortByZIndex, studyInputTarget, systemClipboard, toolCursor };