@trdrs/quickcharts 1.3.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/README.md +209 -200
- package/THIRD-PARTY-NOTICES.md +4 -4
- package/dist/adapters/rest.d.ts +3 -3
- package/dist/adapters/rest.js +2 -2
- package/dist/adapters/rest.js.map +1 -1
- package/dist/{ar-G7MVXRE4.js → ar-KSXQ2USS.js} +20 -20
- package/dist/ar-KSXQ2USS.js.map +1 -0
- package/dist/{assets-ySndlUS3.d.ts → assets-DOuBBsOp.d.ts} +50 -50
- package/dist/{ca_ES-EUSRU4VG.js → ca_ES-JG4FM55E.js} +20 -20
- package/dist/ca_ES-JG4FM55E.js.map +1 -0
- package/dist/{chunk-KFBQSPNA.js → chunk-D3S26ARP.js} +2 -2
- package/dist/chunk-D3S26ARP.js.map +1 -0
- package/dist/{chunk-AKXIFHQN.js → chunk-KLPTCWA2.js} +1 -1
- package/dist/{chunk-AKXIFHQN.js.map → chunk-KLPTCWA2.js.map} +1 -1
- package/dist/{chunk-AA7XKXH4.js → chunk-YR7NT5ZW.js} +67 -33
- package/dist/chunk-YR7NT5ZW.js.map +1 -0
- package/dist/{de-2SVTG25S.js → de-VSW2LHNF.js} +20 -20
- package/dist/de-VSW2LHNF.js.map +1 -0
- package/dist/drawings.d.ts +16 -16
- package/dist/drawings.js +12 -12
- package/dist/{es-UDHZM4W7.js → es-5ZXIPVOB.js} +20 -20
- package/dist/es-5ZXIPVOB.js.map +1 -0
- package/dist/feature-manifest.json +3 -3
- package/dist/{fr-35VN4G4S.js → fr-4F6DAWGD.js} +20 -20
- package/dist/fr-4F6DAWGD.js.map +1 -0
- package/dist/{he_IL-JPZMCURP.js → he_IL-B7PBQUEV.js} +20 -20
- package/dist/he_IL-B7PBQUEV.js.map +1 -0
- package/dist/{id_ID-XSTFHHJQ.js → id_ID-CYJRMXPC.js} +20 -20
- package/dist/id_ID-CYJRMXPC.js.map +1 -0
- package/dist/index.d.ts +167 -163
- package/dist/index.js +342 -268
- package/dist/index.js.map +1 -1
- package/dist/{it-EIY6JESQ.js → it-KTX4SG5P.js} +20 -20
- package/dist/it-KTX4SG5P.js.map +1 -0
- package/dist/{ja-42N4XRCW.js → ja-V7OURU5D.js} +20 -20
- package/dist/ja-V7OURU5D.js.map +1 -0
- package/dist/{ko-3VRPTIP3.js → ko-2RNEBYVE.js} +20 -20
- package/dist/ko-2RNEBYVE.js.map +1 -0
- package/dist/{ms_MY-SKN7O6M5.js → ms_MY-EY235E7Q.js} +20 -20
- package/dist/ms_MY-EY235E7Q.js.map +1 -0
- package/dist/{pl-TYARHCLT.js → pl-ADNVRP55.js} +20 -20
- package/dist/pl-ADNVRP55.js.map +1 -0
- package/dist/{pt-72IIFLL4.js → pt-OL2DR3DO.js} +20 -20
- package/dist/pt-OL2DR3DO.js.map +1 -0
- package/dist/quickcharts.css +97 -96
- package/dist/{resources-Ch8eA1Mw.d.ts → resources-Le6flcEn.d.ts} +3 -3
- package/dist/rest-openapi.json +11 -11
- package/dist/{ru-TPH4F7IB.js → ru-V6YFEPAF.js} +20 -20
- package/dist/ru-V6YFEPAF.js.map +1 -0
- package/dist/{sv-DC5RS67Z.js → sv-TORXQVE7.js} +20 -20
- package/dist/sv-TORXQVE7.js.map +1 -0
- package/dist/{th-I6H6AOZ3.js → th-K6SJSYSY.js} +20 -20
- package/dist/th-K6SJSYSY.js.map +1 -0
- package/dist/theme-manifest.json +10 -10
- package/dist/{tr-7FSUVCNW.js → tr-4AEM66KW.js} +20 -20
- package/dist/tr-4AEM66KW.js.map +1 -0
- package/dist/{vi-DLRPHLLH.js → vi-YU5XCEUU.js} +20 -20
- package/dist/vi-YU5XCEUU.js.map +1 -0
- package/dist/{zh-ZXIQBBEP.js → zh-QXKRYHU5.js} +20 -20
- package/dist/zh-QXKRYHU5.js.map +1 -0
- package/dist/{zh_TW-TYNUJU7U.js → zh_TW-AYPDKG4Q.js} +20 -20
- package/dist/zh_TW-AYPDKG4Q.js.map +1 -0
- package/package.json +2 -2
- package/dist/ar-G7MVXRE4.js.map +0 -1
- package/dist/ca_ES-EUSRU4VG.js.map +0 -1
- package/dist/chunk-AA7XKXH4.js.map +0 -1
- package/dist/chunk-KFBQSPNA.js.map +0 -1
- package/dist/de-2SVTG25S.js.map +0 -1
- package/dist/es-UDHZM4W7.js.map +0 -1
- package/dist/fr-35VN4G4S.js.map +0 -1
- package/dist/he_IL-JPZMCURP.js.map +0 -1
- package/dist/id_ID-XSTFHHJQ.js.map +0 -1
- package/dist/it-EIY6JESQ.js.map +0 -1
- package/dist/ja-42N4XRCW.js.map +0 -1
- package/dist/ko-3VRPTIP3.js.map +0 -1
- package/dist/ms_MY-SKN7O6M5.js.map +0 -1
- package/dist/pl-TYARHCLT.js.map +0 -1
- package/dist/pt-72IIFLL4.js.map +0 -1
- package/dist/ru-TPH4F7IB.js.map +0 -1
- package/dist/sv-DC5RS67Z.js.map +0 -1
- package/dist/th-I6H6AOZ3.js.map +0 -1
- package/dist/tr-7FSUVCNW.js.map +0 -1
- package/dist/vi-DLRPHLLH.js.map +0 -1
- package/dist/zh-ZXIQBBEP.js.map +0 -1
- package/dist/zh_TW-TYNUJU7U.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# @trdrs/quickcharts
|
|
2
2
|
|
|
3
|
-
Quick Charts is a charting library
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
or hosting: the host supplies data and storage, and the chart draws.
|
|
3
|
+
Quick Charts is a datafeed-driven charting library with drawings, indicators, layouts and replay.
|
|
4
|
+
It draws over the datafeed and the storage you supply: the chart consumes the `ChartDatafeed`
|
|
5
|
+
interface, so your feed drives it without a change to the chart.
|
|
7
6
|
|
|
8
7
|
## Install
|
|
9
8
|
|
|
@@ -21,8 +20,8 @@ runtime. Use default peer resolution; do not suppress peer checks.
|
|
|
21
20
|
Quick Charts is licensed under the Apache License 2.0: see `LICENSE` and `NOTICE`. Because the
|
|
22
21
|
renderer is *your* dependency, its own Apache-2.0 NOTICE
|
|
23
22
|
obligations attach to **your** bundle: `THIRD-PARTY-NOTICES.md` in this package spells out exactly
|
|
24
|
-
what to carry and how.
|
|
25
|
-
|
|
23
|
+
what to carry and how. An application composes its own features on the chart through the extension
|
|
24
|
+
seam below.
|
|
26
25
|
|
|
27
26
|
Quickstart, the smallest working chart (see [The widget](#the-widget) for the full options). The
|
|
28
27
|
stylesheet import is not optional: it carries the chart's layout as well as its look, and without it
|
|
@@ -44,9 +43,8 @@ await widget.ready()
|
|
|
44
43
|
Implement `ChartDatafeed` (see `datafeed.ts`). Required methods: `search`, `resolve`, `history`,
|
|
45
44
|
`subscribeBars`. Optional: `serverTime` (countdown skew correction) and `config` (a feed-level
|
|
46
45
|
capability declaration, described [below](#capability-declaration-config-optional)). The datafeed serves
|
|
47
|
-
symbol metadata, bars and bar updates
|
|
48
|
-
|
|
49
|
-
source.
|
|
46
|
+
symbol metadata, bars and bar updates; your host serves quotes (last, change, volume, the top of
|
|
47
|
+
book) to its own consumers from its own source.
|
|
50
48
|
|
|
51
49
|
When `appearance.countdown` is enabled, a live streaming time bar replaces the native last-value
|
|
52
50
|
label with one price-and-time label. The price uses the resolved symbol formatter. Replay, stale,
|
|
@@ -176,8 +174,8 @@ export const feed: ChartDatafeed = {
|
|
|
176
174
|
```
|
|
177
175
|
|
|
178
176
|
Declare only what is **true**. Absent method / absent field / empty list = unconstrained, so a feed that
|
|
179
|
-
serves any
|
|
180
|
-
The UDF adapter declares automatically from the server's own `/config` (and only ever declares
|
|
177
|
+
serves any timeframe must not declare a finite `resolutions` list, because the widget then enforces
|
|
178
|
+
it. The UDF adapter declares automatically from the server's own `/config` (and only ever declares
|
|
181
179
|
timeframes it would actually serve).
|
|
182
180
|
|
|
183
181
|
## The UDF on-ramp
|
|
@@ -213,10 +211,11 @@ What the adapter honors of the protocol:
|
|
|
213
211
|
|
|
214
212
|
Symbology is the set of display facts that decide how a market's prices are written. Your datafeed
|
|
215
213
|
owns them (`resolve` answers with `SymbolInfo`), and one package formatter uses them everywhere a
|
|
216
|
-
price appears: the price scale, the crosshair and last-price labels, the legend, the
|
|
217
|
-
every drawing label,
|
|
218
|
-
from the size of the price, so the same market reads at the same width on every surface.
|
|
219
|
-
that declares its own precision keeps it; every other value writes through the symbol
|
|
214
|
+
price appears: the price scale, the crosshair and last-price labels, the legend, the context menu,
|
|
215
|
+
every drawing label, indicator scales, and the extension seam. Precision comes from the symbol,
|
|
216
|
+
never from the size of the price, so the same market reads at the same width on every surface. An
|
|
217
|
+
indicator that declares its own precision keeps it; every other value writes through the symbol
|
|
218
|
+
formatter.
|
|
220
219
|
|
|
221
220
|
`PriceFormat` expresses every supported form in five facts:
|
|
222
221
|
|
|
@@ -303,8 +302,8 @@ symbolNames({ symbol: 'NASDAQ:AAPL', name: 'Apple Inc', exchange: 'NASDAQ', type
|
|
|
303
302
|
symbolNames('HYPERLIQUID:ETH').mark // 'ETH', before the symbol resolves
|
|
304
303
|
```
|
|
305
304
|
|
|
306
|
-
Symbology is display truth
|
|
307
|
-
|
|
305
|
+
Symbology is display truth: how the chart writes a market's prices. Execution facts, such as lot
|
|
306
|
+
size and pip value, stay with your trading integration, and its execution grid can differ from the
|
|
308
307
|
chart's display grid.
|
|
309
308
|
|
|
310
309
|
If your data comes from a UDF server, map its `/symbols` answer without collapsing the facts:
|
|
@@ -322,14 +321,14 @@ info?.dataStatus // 'streaming'
|
|
|
322
321
|
|
|
323
322
|
Quick Charts persists two different kinds of thing, and the difference decides where each one lives.
|
|
324
323
|
|
|
325
|
-
Saved charts, layouts, drawing documents and templates are **entities**: a
|
|
324
|
+
Saved charts, layouts, drawing documents and templates are **entities**: a viewer names them, opens
|
|
326
325
|
them in two tabs, and can lose them. They have identity and versions, and they live on the
|
|
327
326
|
save/load adapter you supply. Viewer preferences (the last symbol and timeframe, the scale mode, the
|
|
328
327
|
replay speed) are **flat settings**: they need no identity, and they live on the small `ChartStorage`
|
|
329
328
|
port beside it.
|
|
330
329
|
|
|
331
330
|
The chart never writes on its own. It tells you when a save would be worth making, through the
|
|
332
|
-
`saveNeeded` event, and it runs a write only when a
|
|
331
|
+
`saveNeeded` event, and it runs a write only when a viewer asks for one through the built-in UI or
|
|
333
332
|
when you call a save method yourself.
|
|
334
333
|
|
|
335
334
|
### What a saved entity carries
|
|
@@ -367,7 +366,7 @@ changes, and a menu with Save, an Autosave switch, Make a copy, Rename, Download
|
|
|
367
366
|
new layout, the layouts used most recently, and Open layout: the Layouts dialog, with search, a sort
|
|
368
367
|
by name or by date modified, a star that keeps a layout at the top, and delete behind a
|
|
369
368
|
confirmation. The sort and the stars are the viewer's, kept in the widget's `ChartStorage`. Each
|
|
370
|
-
saved layout is listed by the market and
|
|
369
|
+
saved layout is listed by the market and timeframe its active chart showed when
|
|
371
370
|
it was saved, or by its age where the store kept neither.
|
|
372
371
|
|
|
373
372
|
Every row runs a command (`widget.layout.save`, `rename`, `load`, `open`, `delete`, `create`, `autosave`,
|
|
@@ -417,7 +416,7 @@ const adapter = memorySaveLoadAdapter()
|
|
|
417
416
|
const controller = new AbortController()
|
|
418
417
|
|
|
419
418
|
await adapter.layouts.list(controller.signal)
|
|
420
|
-
await adapter.templates('
|
|
419
|
+
await adapter.templates('indicator').list()
|
|
421
420
|
const context = { version: 1, kind: 'symbol-global', symbol: 'ESZ2026' } as const
|
|
422
421
|
await adapter.drawings(context).create(emptyDrawingDocument(context))
|
|
423
422
|
|
|
@@ -428,8 +427,9 @@ outcome.kind // 'not-found'
|
|
|
428
427
|
|
|
429
428
|
An aborted call rejects with an error named `AbortError` and changes nothing.
|
|
430
429
|
|
|
431
|
-
`memorySaveLoadAdapter`
|
|
432
|
-
ephemeral embed, and implement the same contract over your
|
|
430
|
+
`memorySaveLoadAdapter` keeps everything in memory for the life of the page. Use it for tests,
|
|
431
|
+
server rendering and an intentionally ephemeral embed, and implement the same contract over your
|
|
432
|
+
own backend for durable storage.
|
|
433
433
|
|
|
434
434
|
### The REST adapter and its wire contract
|
|
435
435
|
|
|
@@ -447,10 +447,11 @@ const restSaves = createRestSaveLoadAdapter({
|
|
|
447
447
|
await restSaves.layouts.list()
|
|
448
448
|
```
|
|
449
449
|
|
|
450
|
-
You supply two values
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
450
|
+
You supply two values. `baseUrl` is where you mounted the routes, and `request` is how a request is
|
|
451
|
+
made. Authorization, cookies, CORS, retries, timeouts and tenancy stay in your request function,
|
|
452
|
+
because their consequences are yours: the adapter builds each request from `baseUrl` and hands it to
|
|
453
|
+
your function, which adds the credentials and headers your service needs, and it makes a request
|
|
454
|
+
only when you call a verb.
|
|
454
455
|
|
|
455
456
|
Your service serves four collections under that base URL. Every path below is relative to it.
|
|
456
457
|
|
|
@@ -532,8 +533,8 @@ remain in step while the menu is open; transient tile maximize does not change t
|
|
|
532
533
|
names.
|
|
533
534
|
|
|
534
535
|
Growing a layout keeps every existing chart instance and initializes each new tile from pane 0's
|
|
535
|
-
safe presentation: symbol, timeframe, style,
|
|
536
|
-
is copied per tile; replay, session state and saved-chart identity are not copied.
|
|
536
|
+
safe presentation: symbol, timeframe, style, indicators and comparisons. Mutable indicator
|
|
537
|
+
configuration is copied per tile; replay, session state and saved-chart identity are not copied.
|
|
537
538
|
|
|
538
539
|
`load` answers rather than rejecting. Five kinds, told apart without reading a message:
|
|
539
540
|
|
|
@@ -587,13 +588,13 @@ switch (opened.kind) {
|
|
|
587
588
|
A load that a later load supersedes is `cancelled`, with no signal of your own involved, and only
|
|
588
589
|
the later load binds. This includes a later load begun synchronously by a chart callback during
|
|
589
590
|
application. A widget disposed while the store is still answering answers the same way. That is
|
|
590
|
-
what keeps a slow answer for the chart a
|
|
591
|
+
what keeps a slow answer for the chart a viewer has left from landing on the chart they are looking
|
|
591
592
|
at.
|
|
592
593
|
|
|
593
594
|
Where a body fails after part of it has been applied, the chart puts back the content it held. If
|
|
594
595
|
that fails too the chart is holding neither, and it stops saving: `saveLoad.notSaving()` reports it,
|
|
595
596
|
`save` answers `not-saving` and writes nothing, the built-in layouts menu says so on the toolbar and
|
|
596
|
-
stands its Save and its autosave down, and the sentence for the
|
|
597
|
+
stands its Save and its autosave down, and the sentence for the viewer arrives on `saveConflict`.
|
|
597
598
|
|
|
598
599
|
Saving starts again when a load lands, and only then: a whole content out of the store, applied in
|
|
599
600
|
full, under the resource it came from. `save(name, { asNew: true })` stays available throughout, and
|
|
@@ -623,7 +624,7 @@ Complete recovery requires every typed appearance leaf with a valid concrete col
|
|
|
623
624
|
in combined mode, a drawings array. Separate-mode chart content does not need that array.
|
|
624
625
|
|
|
625
626
|
Hydration and rollback do not emit `saveNeeded` for their own storage writes. An event already
|
|
626
|
-
queued by a
|
|
627
|
+
queued by a viewer's edit is preserved. A late save result does not replace a newer load's binding;
|
|
627
628
|
the built-in commands announce a saved layout only while that result is still current.
|
|
628
629
|
|
|
629
630
|
### Drawings: combined or separate
|
|
@@ -676,18 +677,18 @@ tile.
|
|
|
676
677
|
|
|
677
678
|
### Templates
|
|
678
679
|
|
|
679
|
-
`adapter.templates(kind)` is a store per kind: `'
|
|
680
|
-
drawing tool's look, and `'palette'` for chart appearance. A drawing template carries the `tool`
|
|
681
|
-
belongs to, because a trend-line template means nothing on a rectangle. Their content is opaque,
|
|
680
|
+
`adapter.templates(kind)` is a store per kind: `'indicator'` for indicator settings, `'drawing'` for
|
|
681
|
+
a drawing tool's look, and `'palette'` for chart appearance. A drawing template carries the `tool`
|
|
682
|
+
it belongs to, because a trend-line template means nothing on a rectangle. Their content is opaque,
|
|
682
683
|
like a chart's.
|
|
683
684
|
|
|
684
|
-
###
|
|
685
|
+
### Viewer settings
|
|
685
686
|
|
|
686
687
|
The widget keeps the viewer's flat preferences in a `ChartStorage`. Every key is an opaque string in
|
|
687
688
|
the `quickcharts.` namespace, and every value is an opaque string; a store routes or scopes them and
|
|
688
|
-
|
|
689
|
-
per device or per
|
|
690
|
-
|
|
689
|
+
treats both as opaque. The default is an in-memory store that lasts the page; supply your own to
|
|
690
|
+
keep them per device or per viewer. A browser store is a few lines you write and own, so where
|
|
691
|
+
preferences live stays your decision:
|
|
691
692
|
|
|
692
693
|
```ts
|
|
693
694
|
import { memoryChartStorage, type ChartStorage } from '@trdrs/quickcharts'
|
|
@@ -710,7 +711,7 @@ live on the saved-resource adapter above, never here.
|
|
|
710
711
|
A conflict means someone else wrote the same entity after the copy on screen was read. The chart
|
|
711
712
|
never resolves that by overwriting. It reports the case with a sentence from its own catalog and the
|
|
712
713
|
ref that stands now, and leaves the decision to you: reload and lose the local edit, save a copy
|
|
713
|
-
under a new name, or show the
|
|
714
|
+
under a new name, or show the viewer both.
|
|
714
715
|
|
|
715
716
|
Reach the report in two places. A verb you called answers a typed `conflict` outcome. A write the
|
|
716
717
|
widget made for the viewer, through the built-in UI or its own drawing sync, arrives on the
|
|
@@ -863,7 +864,7 @@ widget.dispose() // teardown; every handle and subscription is inert afterwards
|
|
|
863
864
|
The widget paints the main series and volume, applies live updates by the bar rules above, pages
|
|
864
865
|
older history in as the viewer scrolls left (stopping at the feed's `noData`), persists the viewer's
|
|
865
866
|
preferences through `ChartStorage`, runs configured indicator instances through the manifest
|
|
866
|
-
pipeline, and mounts the drawing layer, the legend and the
|
|
867
|
+
pipeline, and mounts the drawing layer, the legend and the context menu.
|
|
867
868
|
|
|
868
869
|
When older main or comparison history extends the renderer's shared timeline, the chart retains
|
|
869
870
|
the latest fractional logical window, spacing and permitted off-data padding. Its compensating
|
|
@@ -875,7 +876,7 @@ the maintenance span or either endpoint. Public range methods and built-in navig
|
|
|
875
876
|
enter that same epoch, so every supported navigation door has the same precedence.
|
|
876
877
|
|
|
877
878
|
`toolbarContainer` optionally supplies a separate element for the top toolbar, such as a space
|
|
878
|
-
between a host's navigation and
|
|
879
|
+
between a host's navigation and its other controls. The widget appends one package-owned, themed
|
|
879
880
|
child there; it never clears or styles the supplied element. The toolbar follows the widget's
|
|
880
881
|
theme, language and active chart, and its child is removed at disposal. The toolbar's menus and
|
|
881
882
|
dialogs open in the widget's layer on the document body, at viewport coordinates, so each menu
|
|
@@ -885,12 +886,13 @@ toolbar available in fullscreen. Without `toolbarContainer`, the toolbar sits ab
|
|
|
885
886
|
part of the default composition. When horizontal space is limited, the toolbar scrolls without
|
|
886
887
|
dropping controls from the keyboard order.
|
|
887
888
|
|
|
888
|
-
`drawingToolbarContainer` supplies separate host space for a single drawing
|
|
889
|
+
`drawingToolbarContainer` supplies separate host space for a single drawing toolbar. The package
|
|
889
890
|
fills that space's height with its own themed child, follows the active chart when a layout
|
|
890
|
-
changes, and removes the child on disposal. An external
|
|
891
|
-
canvas; without the option, each chart keeps its internal
|
|
892
|
-
Drawing flyouts stay beside the external
|
|
893
|
-
pane. Switching charts closes an open flyout before the
|
|
891
|
+
changes, and removes the child on disposal. An external drawing toolbar leaves the full chart width
|
|
892
|
+
for the canvas; without the option, each chart keeps its internal drawing toolbar and reserved
|
|
893
|
+
leading column. Drawing flyouts stay beside the external drawing toolbar within the widget's bounds
|
|
894
|
+
regardless of the active pane. Switching charts closes an open flyout before the drawing toolbar
|
|
895
|
+
targets the newly active chart.
|
|
894
896
|
Include this container in the custom fullscreen target alongside the chart and top toolbar.
|
|
895
897
|
|
|
896
898
|
### Widget and chart
|
|
@@ -982,7 +984,7 @@ delete, and there is no custom-timeframe composer. The viewer's saved chips show
|
|
|
982
984
|
them. When you list none of them, the chips are your five smallest timeframes, and the viewer's
|
|
983
985
|
stored chips stay stored for a chart that offers them. With one timeframe offered the picker is not
|
|
984
986
|
shown. `ui.topBar.timeframes: false` hides the picker on its own terms. A range preset whose
|
|
985
|
-
|
|
987
|
+
timeframe you leave out reads its span at your nearest coarser timeframe, or at your largest when
|
|
986
988
|
none is coarser. Within what you offer, the feed's `resolutions` and the symbol's
|
|
987
989
|
`supportedResolutions` still apply: a chip the feed or the symbol does not serve is disabled, and
|
|
988
990
|
the picker's list leaves its row out.
|
|
@@ -1052,7 +1054,7 @@ picture or as data.
|
|
|
1052
1054
|
By default a chart offers every drawing tool. `drawingTools` names the tools you offer, by the type
|
|
1053
1055
|
`access.drawingTool` and the `tool.<type>` icon ids use: a type `drawingTools.all()` lists (from
|
|
1054
1056
|
`@trdrs/quickcharts/drawings`), `zoom` or `eraser`. The order you give does not matter, because the
|
|
1055
|
-
|
|
1057
|
+
drawing toolbar keeps its own groups and sections:
|
|
1056
1058
|
|
|
1057
1059
|
```ts
|
|
1058
1060
|
import { createChart, type ChartDatafeed } from '@trdrs/quickcharts'
|
|
@@ -1068,14 +1070,14 @@ createChart({ container, datafeed, drawingTools: ['eraser'] })
|
|
|
1068
1070
|
|
|
1069
1071
|
A tool you leave out is not drawn anywhere a tool is chosen: not in its group's flyout, not as a
|
|
1070
1072
|
group's face, which wears the first tool the group offers, not on the favorites bar, and not on the
|
|
1071
|
-
|
|
1072
|
-
are the `emoji`, `sticker` and `icon` tools, so a kind you leave out has no tab, and
|
|
1073
|
-
three removes the glyph group. Every door that would arm it refuses:
|
|
1074
|
-
`denied`, and `armTool`, `placeImage` and an image pasted over the
|
|
1075
|
-
new drawing, so a drawing of a tool you leave out is not copied
|
|
1076
|
-
and `chart.drawings.paste` are unavailable for it, `clone` and
|
|
1077
|
-
Control- or Command-drag moves the drawing instead of duplicating it.
|
|
1078
|
-
not refused, so it pastes on a chart that offers its tool.
|
|
1073
|
+
drawing toolbar for `measure` and `zoom`. A section or group it empties goes with it. The glyph
|
|
1074
|
+
picker's kinds are the `emoji`, `sticker` and `icon` tools, so a kind you leave out has no tab, and
|
|
1075
|
+
leaving out all three removes the glyph group. Every door that would arm it refuses:
|
|
1076
|
+
`chart.drawings.arm` answers `denied`, and `armTool`, `placeImage` and an image pasted over the
|
|
1077
|
+
chart place nothing. A copy is a new drawing, so a drawing of a tool you leave out is not copied
|
|
1078
|
+
into another: `chart.drawings.clone` and `chart.drawings.paste` are unavailable for it, `clone` and
|
|
1079
|
+
`paste` make nothing, and a Control- or Command-drag moves the drawing instead of duplicating it.
|
|
1080
|
+
Copying it to the clipboard is not refused, so it pastes on a chart that offers its tool.
|
|
1079
1081
|
|
|
1080
1082
|
Drawings of a tool you leave out that are already on the chart, from a saved chart or layout, a
|
|
1081
1083
|
drawings document or another host, render and stay fully editable. They select, restyle through the
|
|
@@ -1095,7 +1097,7 @@ that names no tool and a repeated type are setup errors that `createChart` throw
|
|
|
1095
1097
|
|
|
1096
1098
|
By default a chart offers every built-in indicator. `builtInIndicators` names the built-ins you
|
|
1097
1099
|
offer, by the definition id `access.indicator` receives: an id `BUILT_IN_INDICATORS` lists, such as
|
|
1098
|
-
`sma`. The order you give does not matter, because the indicator
|
|
1100
|
+
`sma`. The order you give does not matter, because the indicator picker keeps its own:
|
|
1099
1101
|
|
|
1100
1102
|
```ts
|
|
1101
1103
|
import { BUILT_IN_INDICATORS, createChart, type ChartDatafeed } from '@trdrs/quickcharts'
|
|
@@ -1105,16 +1107,16 @@ declare const datafeed: ChartDatafeed
|
|
|
1105
1107
|
// Moving averages and RSI only.
|
|
1106
1108
|
createChart({ container, datafeed, builtInIndicators: ['sma', 'ema', 'rsi'] })
|
|
1107
1109
|
|
|
1108
|
-
// A chart that opens with
|
|
1110
|
+
// A chart that opens with an indicator it offers.
|
|
1109
1111
|
const sma = BUILT_IN_INDICATORS.find((definition) => definition.id === 'sma')!
|
|
1110
1112
|
createChart({ container, datafeed, builtInIndicators: ['sma'], indicators: [{ id: 'sma-1', definition: sma }] })
|
|
1111
1113
|
```
|
|
1112
1114
|
|
|
1113
|
-
A built-in you leave out is not listed in the indicator
|
|
1115
|
+
A built-in you leave out is not listed in the indicator picker: not among the built-ins, not
|
|
1114
1116
|
among the favorites, and not in search results. Every door that would add one refuses:
|
|
1115
|
-
`chart.indicators.add` (from the
|
|
1117
|
+
`chart.indicators.add` (from the picker, the keyboard or your own control) answers `denied`,
|
|
1116
1118
|
`indicators.add` adds nothing, `indicators.set` leaves out an instance of it the chart does not
|
|
1117
|
-
already hold, and a new pane that a re-tile adds copies the first chart's
|
|
1119
|
+
already hold, and a new pane that a re-tile adds copies the first chart's indicators without it. The
|
|
1118
1120
|
chart has no verb that duplicates an indicator, so a second instance is an add like any other.
|
|
1119
1121
|
|
|
1120
1122
|
Instances of a built-in you leave out that are already on the chart, from a saved chart or layout,
|
|
@@ -1154,7 +1156,7 @@ A preset you leave out has no `chart.range.<key>` command, so no menu, shortcut
|
|
|
1154
1156
|
reaches it, `chart.range.set` ignores its key, and the bottom bar draws no button for it. An empty
|
|
1155
1157
|
list offers none, which is how you keep the rest of the bottom bar without range buttons;
|
|
1156
1158
|
`ui.bottomBar: false` removes the whole bar. `chart.range.set` still takes an explicit
|
|
1157
|
-
`{ from, to }` window either way. A preset whose
|
|
1159
|
+
`{ from, to }` window either way. A preset whose timeframe your `timeframes` leave out reads its
|
|
1158
1160
|
span at your nearest coarser timeframe, as it does without a list. A non-list, a key that names no
|
|
1159
1161
|
preset and a repeated key are setup errors that `createChart` throws.
|
|
1160
1162
|
|
|
@@ -1270,10 +1272,10 @@ over it is absent. A control you hide in `ui` is the only thing that changes. Th
|
|
|
1270
1272
|
Two presentation flags also close the one command whose only job is opening their dialog.
|
|
1271
1273
|
`ui.symbolSearch: false` removes the search dialog and `chart.symbol.search`, while
|
|
1272
1274
|
`chart.symbol.set` still changes the symbol. `ui.indicatorPicker: false` removes the indicator
|
|
1273
|
-
|
|
1275
|
+
picker and `chart.indicators.open`, while `chart.indicators.add` still adds an indicator.
|
|
1274
1276
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
+
Authorization belongs to `access`: a hidden control's command still answers to it, and a flag
|
|
1278
|
+
reaches only what the datafeed can do, so a feed with no search keeps every search door closed.
|
|
1277
1279
|
|
|
1278
1280
|
```ts
|
|
1279
1281
|
import { createChart, createUdfDatafeed } from '@trdrs/quickcharts'
|
|
@@ -1320,11 +1322,11 @@ createChart({
|
|
|
1320
1322
|
With `'hide'`, a refused drawing tool is not in its group's flyout, on the favorites bar or in the
|
|
1321
1323
|
glyph picker; a section, a group or a favorites bar it leaves empty goes with it, and a group's face
|
|
1322
1324
|
that would wear a refused tool wears the first one the group still offers. A refused indicator is
|
|
1323
|
-
not in the indicator
|
|
1325
|
+
not in the indicator picker. A control or menu row whose command the policy refuses is not drawn
|
|
1324
1326
|
(top bar, bottom bar, menus, the drawing toolbar and the selection's bar, the navigation cluster,
|
|
1325
|
-
the replay transport, legend row controls and the
|
|
1326
|
-
goes too. A picker always keeps its current choice: the chosen style, timeframe, timezone or
|
|
1327
|
-
is listed even when its command is refused.
|
|
1327
|
+
the replay transport, legend row controls and the context menu), and a rule left with nothing beside
|
|
1328
|
+
it goes too. A picker always keeps its current choice: the chosen style, timeframe, timezone or
|
|
1329
|
+
scale is listed even when its command is refused.
|
|
1328
1330
|
|
|
1329
1331
|
Only a refusal hides. A permitted command that cannot run now (nothing to undo, no bars loaded,
|
|
1330
1332
|
nothing selected) is drawn disabled as before. The policy is asked whenever the chrome syncs (a
|
|
@@ -1344,11 +1346,11 @@ without them. An indicator whose definition `access.indicator` refuses, once on
|
|
|
1344
1346
|
before the policy changed, or put back by a restore), renders and stays fully editable and
|
|
1345
1347
|
removable:
|
|
1346
1348
|
`indicators.set`, `chart.indicators.update` and the settings dialog edit it, an edit of any other
|
|
1347
|
-
|
|
1348
|
-
that
|
|
1349
|
-
drawing whose tool `access.drawingTool` refuses selects, restyles, locks, hides and
|
|
1350
|
-
drawing does; a copy is a new drawing, so it is not cloned, pasted or duplicated by a
|
|
1351
|
-
Command-drag, while copying it to the clipboard is not refused.
|
|
1349
|
+
indicator keeps it, and an edit that would move it, or another indicator, onto a refused definition
|
|
1350
|
+
leaves that indicator as it stands. A new instance of a refused definition is still left out by
|
|
1351
|
+
every door. A drawing whose tool `access.drawingTool` refuses selects, restyles, locks, hides and
|
|
1352
|
+
deletes as any drawing does; a copy is a new drawing, so it is not cloned, pasted or duplicated by a
|
|
1353
|
+
Control- or Command-drag, while copying it to the clipboard is not refused.
|
|
1352
1354
|
|
|
1353
1355
|
### A policy that changes
|
|
1354
1356
|
|
|
@@ -1379,7 +1381,7 @@ Every surface that reads the policy reads it again at once: the top and bottom b
|
|
|
1379
1381
|
controls, the drawing toolbar's tools and groups, the favorites bar, the selection's bar, the
|
|
1380
1382
|
navigation cluster, the replay transport and the legend's row controls, shown or left out as
|
|
1381
1383
|
`access.refused` says and enabled or disabled. A menu, flyout or dialog that is open reads it too:
|
|
1382
|
-
the bars' menus, the
|
|
1384
|
+
the bars' menus, the context menu, the indicator picker and the saved layouts dialog rebuild their
|
|
1383
1385
|
rows in place, and a drawing toolbar flyout (the glyph picker among them) or a selection bar panel
|
|
1384
1386
|
opens again from its control, or closes when that control is now left out or disabled. Listeners of `widget.commands.onChange`
|
|
1385
1387
|
hear it as well, so a control of your own can read `commands.available` again. Nothing stored
|
|
@@ -1430,14 +1432,15 @@ The chart's own dialogs still open from their commands while its bars are hidden
|
|
|
1430
1432
|
them in the widget's layer on the document, and `widget.layout.save` asks a layout that was never
|
|
1431
1433
|
saved for its name. Hide a dialog in `ui` when your interface provides its own.
|
|
1432
1434
|
|
|
1433
|
-
The library
|
|
1434
|
-
|
|
1435
|
+
The library draws its own controls over its own renderer and keeps its internal components to
|
|
1436
|
+
itself. The class names under the widget's root are private, apart from the styling hooks listed
|
|
1435
1437
|
under Theme.
|
|
1436
1438
|
|
|
1437
1439
|
### Fullscreen and image
|
|
1438
1440
|
|
|
1439
|
-
Chart-root fullscreen fills the screen with the widget's own element
|
|
1440
|
-
|
|
1441
|
+
Chart-root fullscreen fills the screen with the widget's own element, or with the
|
|
1442
|
+
`fullscreen.target` you name; your application shell and any fit-to-container layout stay in your
|
|
1443
|
+
CSS.
|
|
1441
1444
|
|
|
1442
1445
|
```ts
|
|
1443
1446
|
import { type ChartWidget } from '@trdrs/quickcharts'
|
|
@@ -1456,24 +1459,24 @@ async function shareable(widget: ChartWidget): Promise<void> {
|
|
|
1456
1459
|
identity and the attribution you configured through `image`. Nothing is uploaded, shared or stored:
|
|
1457
1460
|
you receive a blob and decide.
|
|
1458
1461
|
|
|
1459
|
-
### Indicator
|
|
1462
|
+
### Indicator picker content
|
|
1460
1463
|
|
|
1461
|
-
The Indicators button and `commands.execute('chart.indicators.open')` open the same
|
|
1464
|
+
The Indicators button and `commands.execute('chart.indicators.open')` open the same picker.
|
|
1462
1465
|
Pass `{ collection: 'saved' }` as the command argument to open a declared host collection directly.
|
|
1463
|
-
An unknown collection falls back to the shipped catalog. Reopening an already open
|
|
1466
|
+
An unknown collection falls back to the shipped catalog. Reopening an already open picker keeps its current selection and query.
|
|
1464
1467
|
It lists the 23 shipped definitions, with search and Favorites. Add creates a new instance on the
|
|
1465
|
-
currently active chart and keeps the
|
|
1468
|
+
currently active chart and keeps the picker open. Favorites use your `ChartStorage` port.
|
|
1466
1469
|
|
|
1467
1470
|
Supply `ChartWidgetOptions.indicatorPicker` to include additional localized collections and rows
|
|
1468
|
-
in that
|
|
1471
|
+
in that picker. You supply data and opaque actions, not DOM, indicator definitions, or a renderer.
|
|
1469
1472
|
Built-in annotations can add favorite state, counts and actions; they cannot replace a definition,
|
|
1470
|
-
its name, or Add. Without a source, the
|
|
1473
|
+
its name, or Add. Without a source, the picker has only shipped built-ins and Favorites.
|
|
1471
1474
|
|
|
1472
1475
|
```ts
|
|
1473
1476
|
import type { IndicatorPickerSource } from '@trdrs/quickcharts'
|
|
1474
1477
|
|
|
1475
1478
|
const indicatorPicker: IndicatorPickerSource = {
|
|
1476
|
-
collections: [{ id: 'saved', label: 'Saved
|
|
1479
|
+
collections: [{ id: 'saved', label: 'Saved indicators' }],
|
|
1477
1480
|
async list({ collection, query, builtInIds }, signal) {
|
|
1478
1481
|
if (signal.aborted) return { kind: 'unavailable', message: 'Content unavailable.' }
|
|
1479
1482
|
return {
|
|
@@ -1492,10 +1495,10 @@ const indicatorPicker: IndicatorPickerSource = {
|
|
|
1492
1495
|
}
|
|
1493
1496
|
```
|
|
1494
1497
|
|
|
1495
|
-
The source receives the collection, query and the shipped definition ids the
|
|
1498
|
+
The source receives the collection, query and the shipped definition ids the picker lists (only
|
|
1496
1499
|
those `builtInIndicators` offers, when you name a list). Its own collections and rows are never
|
|
1497
|
-
filtered by that list. It owns filtering and any
|
|
1498
|
-
service limits; the
|
|
1500
|
+
filtered by that list. It owns filtering, paging and any
|
|
1501
|
+
service limits; the picker lists what it answers.
|
|
1499
1502
|
Collection ids `builtin` and `favorites`, and action ids `add` and `favorite`, are reserved.
|
|
1500
1503
|
Item ids cannot collide with shipped definition ids or these reserved ids. Duplicate ids,
|
|
1501
1504
|
malformed rows and missing primary actions refuse the response; the shipped catalog remains usable.
|
|
@@ -1504,7 +1507,7 @@ name a localized navigation group and use `layout: 'list'` for name/secondary-ac
|
|
|
1504
1507
|
An absent count stays blank. Omit `favorite` to omit that action on a contributed item.
|
|
1505
1508
|
|
|
1506
1509
|
A favorite action receives the requested next boolean. Successful actions refresh the current
|
|
1507
|
-
collection unless they return `close: true`. Refusals and exceptions keep the
|
|
1510
|
+
collection unless they return `close: true`. Refusals and exceptions keep the picker open with
|
|
1508
1511
|
plain text, never rendered markup. Icons reuse `ChartExtensionIcon`; invalid icons draw no glyph.
|
|
1509
1512
|
The host localizes contributed labels and messages; the chart localizes its own controls.
|
|
1510
1513
|
|
|
@@ -1520,7 +1523,7 @@ chrome is painted from it and renders nothing without it.
|
|
|
1520
1523
|
- **The top bar.** The symbol pill opens the symbol search for the active chart; the compare door
|
|
1521
1524
|
opens it in compare mode. The timeframe picker shows the saved timeframes as chips and a list of
|
|
1522
1525
|
the timeframes the chart offers (by default the 26 presets in five groups), each row savable as a
|
|
1523
|
-
chip, with a composer for a custom
|
|
1526
|
+
chip, with a composer for a custom timeframe under the unit's ceiling while custom timeframes are
|
|
1524
1527
|
offered. The style picker lists the styles the chart offers. Indicators opens the picker
|
|
1525
1528
|
over the 23 built-in definitions, and the legend's gear opens the settings dialog for an instance
|
|
1526
1529
|
(inputs, style, visibility). Bar replay enters and leaves replay for the active chart; entering
|
|
@@ -1555,7 +1558,7 @@ chrome is painted from it and renders nothing without it.
|
|
|
1555
1558
|
replay entry can claim the row. Chart notices report a feed that cannot serve the symbol, an
|
|
1556
1559
|
image that could not be copied, or a save the store refused.
|
|
1557
1560
|
|
|
1558
|
-
Undo and redo step through the chart's own content: the symbol, the
|
|
1561
|
+
Undo and redo step through the chart's own content: the symbol, the timeframe, the style, the price
|
|
1559
1562
|
scale and whether it frames itself, the appearance a viewer authored, the comparisons, the
|
|
1560
1563
|
indicators and the drawings. A step is one reading of that content, so a step back puts the whole
|
|
1561
1564
|
reading back rather than reversing a single verb, and the two controls name the change they would
|
|
@@ -1694,8 +1697,8 @@ is a factory that returns a fresh `<svg>` element. An id you leave out keeps the
|
|
|
1694
1697
|
as a `TypeError` when the widget is created.
|
|
1695
1698
|
|
|
1696
1699
|
An id names what a glyph means, not one control. `settings` is the top bar's settings button, a
|
|
1697
|
-
|
|
1698
|
-
Drawing tools take `tool.<type>`, chart styles `style.<style>` and layout arrangements
|
|
1700
|
+
indicator's gear in the legend and the drawing settings bar's gear, so one drawing stands in all
|
|
1701
|
+
three. Drawing tools take `tool.<type>`, chart styles `style.<style>` and layout arrangements
|
|
1699
1702
|
`layout.<code>`, from the registries the rest of the API uses.
|
|
1700
1703
|
|
|
1701
1704
|
```ts
|
|
@@ -1745,15 +1748,16 @@ before costs that one glyph its artwork. The control draws the chart's own glyph
|
|
|
1745
1748
|
|
|
1746
1749
|
`icons` covers the chart's own controls. The emoji, sticker and icon glyphs a drawing places come
|
|
1747
1750
|
through the asset port, and a chart extension draws its rows and layers from the
|
|
1748
|
-
`ChartExtensionIcon` descriptors it contributes. The product's mark in the plot's corner is
|
|
1749
|
-
|
|
1750
|
-
`mountTimeframePicker` take the same `icons` for a menu, search or picker
|
|
1751
|
+
`ChartExtensionIcon` descriptors it contributes. The product's mark in the plot's corner is the
|
|
1752
|
+
chart's own artwork, outside `icons`. `mountContextMenu`, `openSymbolSearch`, `mountSymbolSearch`,
|
|
1753
|
+
`openTimeframePicker` and `mountTimeframePicker` take the same `icons` for a menu, search or picker
|
|
1754
|
+
you mount without a widget.
|
|
1751
1755
|
|
|
1752
1756
|
### Neutral marks
|
|
1753
1757
|
|
|
1754
1758
|
Serve `marks` and `timescaleMarks` from your datafeed and the chart draws them. A mark is a note
|
|
1755
1759
|
about a moment: its color is a semantic theme role rather than a literal, its words are yours, and
|
|
1756
|
-
the chart
|
|
1760
|
+
the chart draws it as given.
|
|
1757
1761
|
|
|
1758
1762
|
```ts
|
|
1759
1763
|
import { type BarMark, type ChartDatafeed } from '@trdrs/quickcharts'
|
|
@@ -1791,13 +1795,13 @@ void withMarks
|
|
|
1791
1795
|
display name, venue, timeframe, OHLC and change against the previous painted close. Prices use
|
|
1792
1796
|
the symbol's formatter. Hover selects a bar; leaving restores the latest painted reading. Replay
|
|
1793
1797
|
does not expose bars beyond its cursor. Missing metadata leaves the supplied symbol unchanged.
|
|
1794
|
-
Legend and search
|
|
1795
|
-
|
|
1796
|
-
focus during value updates.
|
|
1797
|
-
symbol formatter; Volume reads bar volume using resolved volume precision. The row-list
|
|
1798
|
-
|
|
1799
|
-
across pane removal. The status control opens session details, retains an unknown-session
|
|
1800
|
-
and is hidden during replay. Price-scale chips use the same commands as `setScaleMode`.
|
|
1798
|
+
Legend and search rows wear your `symbolMark`, or a decorative monogram without one.
|
|
1799
|
+
Indicator and separate-pane comparison rows follow their renderer panes. Stable row controls
|
|
1800
|
+
retain focus during value updates. Indicator values read the first plot, using declared precision
|
|
1801
|
+
or the symbol formatter; Volume reads bar volume using resolved volume precision. The row-list
|
|
1802
|
+
toggle, indicator eye and pane collapse are independent controls. Pane restore remembers indicator
|
|
1803
|
+
identity across pane removal. The status control opens session details, retains an unknown-session
|
|
1804
|
+
state and is hidden during replay. Price-scale chips use the same commands as `setScaleMode`.
|
|
1801
1805
|
- **An interface language** (`locale`, English by default), one of the 21 the package ships.
|
|
1802
1806
|
`BUILT_IN_LOCALES` lists them for a picker: each carries its stable code, its canonical BCP 47
|
|
1803
1807
|
`tag`, its reading direction (`ar` and `he_IL` are `rtl`), and its endonym. The chart's own chrome
|
|
@@ -1889,9 +1893,9 @@ theme.resetCustom()
|
|
|
1889
1893
|
stop()
|
|
1890
1894
|
```
|
|
1891
1895
|
|
|
1892
|
-
Switching modes keeps the symbol, timeframe, visible range, drawings and
|
|
1893
|
-
has. A palette you supply is a tint rather than a replacement: a role you do not name keeps
|
|
1894
|
-
built-in value for that mode.
|
|
1896
|
+
Switching modes keeps the symbol, timeframe, visible range, drawings and indicators the chart
|
|
1897
|
+
already has. A palette you supply is a tint rather than a replacement: a role you do not name keeps
|
|
1898
|
+
its built-in value for that mode.
|
|
1895
1899
|
|
|
1896
1900
|
### Roles
|
|
1897
1901
|
|
|
@@ -1912,19 +1916,22 @@ same values:
|
|
|
1912
1916
|
| `motion.durationBase` | `150ms` | A modal dialog and its backdrop opening and closing, and the replay row entering and leaving. |
|
|
1913
1917
|
| `motion.durationModerate` | `250ms` | A control moving to its new state, such as a switch knob sliding. |
|
|
1914
1918
|
| `motion.durationSlow` | `350ms` | A small mark settling, such as a disclosure caret turning or a checkbox filling. |
|
|
1915
|
-
| `motion.durationSlower` | `500ms` | A larger mark turning, such as the drawing
|
|
1919
|
+
| `motion.durationSlower` | `500ms` | A larger mark turning, such as the drawing toolbar's chevron. |
|
|
1916
1920
|
| `motion.easingStandard` | `ease` | A modal dialog box, the replay row, a caret dip, a checkbox fill. |
|
|
1917
1921
|
| `motion.easingOut` | `ease-out` | A modal backdrop fading, a switch knob sliding. |
|
|
1918
1922
|
| `motion.easingLinear` | `linear` | A color or opacity change under the pointer. |
|
|
1919
1923
|
| `motion.easingSpring` | `cubic-bezier(0.175, 0.885, 0.32, 1.275)` | A caret or chevron turning with a slight overshoot. |
|
|
1920
1924
|
| `motion.scaleEnter` | `0.97` | The scale a modal dialog box grows from as it opens. |
|
|
1921
1925
|
|
|
1922
|
-
|
|
1926
|
+
Every modal dialog the chart opens (the symbol search, chart settings, the indicator browser and
|
|
1927
|
+
indicator settings, the saved-layouts browser, the name and confirm prompts, go to date, and the
|
|
1928
|
+
drawing settings, image picker and template prompts) opens with its backdrop fading in over
|
|
1923
1929
|
`motion.durationBase` on `motion.easingOut`, and its box fading in and growing from
|
|
1924
1930
|
`motion.scaleEnter` to full size over `motion.durationBase` on `motion.easingStandard`. It closes
|
|
1925
1931
|
with the same motion reversed. A closing dialog stops taking input and returns focus at once, and the
|
|
1926
1932
|
chart removes it when the same `motion.durationBase` has elapsed, so a duration you set times both
|
|
1927
|
-
the transition and the removal.
|
|
1933
|
+
the transition and the removal. A dialog opened over another moves on its own and closes first, and
|
|
1934
|
+
a dialog the chart replaces or tears down goes at once.
|
|
1928
1935
|
|
|
1929
1936
|
A duration takes a CSS duration such as `200ms` or `0.2s`; an easing takes any CSS timing function,
|
|
1930
1937
|
such as `ease-in-out`, `steps(4)` or `cubic-bezier(0.2, 0, 0, 1)`; a scale takes a unitless factor
|
|
@@ -1949,23 +1956,23 @@ once.
|
|
|
1949
1956
|
### Cascade layers
|
|
1950
1957
|
|
|
1951
1958
|
The stylesheet declares two cascade layers and puts everything it contains in them: the built-in
|
|
1952
|
-
palettes in `
|
|
1953
|
-
declaration `!important` only where a later layer or an inline palette must not undo it:
|
|
1954
|
-
element's `hidden` attribute, the zero motion durations under a reduced-motion preference, and
|
|
1955
|
-
missing focus ring of a search field, which shows its focus by its caret. Your first stylesheet
|
|
1956
|
-
declare the complete order before any product stylesheet loads, because a layer's position is
|
|
1957
|
-
by the first statement that names it:
|
|
1959
|
+
palettes in `quickcharts.tokens`, every recipe in `quickcharts.chart`. Nothing in it is unlayered.
|
|
1960
|
+
It marks a declaration `!important` only where a later layer or an inline palette must not undo it:
|
|
1961
|
+
an element's `hidden` attribute, the zero motion durations under a reduced-motion preference, and
|
|
1962
|
+
the missing focus ring of a search field, which shows its focus by its caret. Your first stylesheet
|
|
1963
|
+
must declare the complete order before any product stylesheet loads, because a layer's position is
|
|
1964
|
+
fixed by the first statement that names it:
|
|
1958
1965
|
|
|
1959
1966
|
```css
|
|
1960
|
-
@layer reset,
|
|
1967
|
+
@layer reset, quickcharts.tokens, quickcharts.chart, host;
|
|
1961
1968
|
```
|
|
1962
1969
|
|
|
1963
1970
|
Put your reset in `reset`. A reset left unlayered outranks every layered rule and strips the
|
|
1964
1971
|
chart's controls of their borders and grounds. Put an intentional override of a supported hook in
|
|
1965
|
-
`host`, or leave it unlayered; either wins over the chart's recipe.
|
|
1966
|
-
`
|
|
1967
|
-
|
|
1968
|
-
|
|
1972
|
+
`host`, or leave it unlayered; either wins over the chart's recipe. Layers of your own product go
|
|
1973
|
+
between `quickcharts.chart` and `host`. Inline styles the chart writes for measured geometry
|
|
1974
|
+
outrank any stylesheet rule, and a rule marked `!important` reverses layer order, so neither is a
|
|
1975
|
+
way to restyle the chart.
|
|
1969
1976
|
|
|
1970
1977
|
### Supported styling hooks
|
|
1971
1978
|
|
|
@@ -1977,9 +1984,9 @@ applying in any release. Removing a hook, a state or a customization is a breaki
|
|
|
1977
1984
|
| Hook | Purpose | States | Customization |
|
|
1978
1985
|
|---|---|---|---|
|
|
1979
1986
|
| `.qc-topbar` | The top toolbar: symbol search, timeframe, chart style, indicators, layouts, replay and the widget menus. | | background-color, border, padding, gap, box-shadow |
|
|
1980
|
-
| `.qc-drawing-toolbar` | The drawing
|
|
1987
|
+
| `.qc-drawing-toolbar` | The drawing toolbar beside the plot. | `aria-orientation`: vertical beside the plot, horizontal in a host row. | background-color, border, padding, gap, box-shadow |
|
|
1981
1988
|
| `.qc-bottombar` | The bottom bar: range shortcuts, the session clock and the timezone. | | background-color, border, padding, gap, box-shadow |
|
|
1982
|
-
| `.qc-legend` | The legend over the plot: the symbol, its reading and each
|
|
1989
|
+
| `.qc-legend` | The legend over the plot: the symbol, its reading and each indicator row. | | background-color, border, border-radius, padding, box-shadow, inset |
|
|
1983
1990
|
| `.qc-menu-panel` | A floating menu opened from a toolbar control. | `hidden`: present while the menu is closed. | background-color, border, border-radius, padding, box-shadow |
|
|
1984
1991
|
| `.qc-dialog` | A modal dialog: settings, search, layouts and the drawing editors. | `data-role`: which dialog this is, in the chart's own vocabulary. | background-color, border, border-radius, padding, box-shadow, max-width |
|
|
1985
1992
|
|
|
@@ -2011,8 +2018,8 @@ problem. Configuration errors never reach a render.
|
|
|
2011
2018
|
### Theme and appearance are two ladders
|
|
2012
2019
|
|
|
2013
2020
|
The theme palette is the broad brand surface. Chart appearance is the specific one: series colors,
|
|
2014
|
-
candle anatomy, grid visibility and
|
|
2015
|
-
affect the same pixel, appearance wins.
|
|
2021
|
+
candle anatomy, grid visibility and indicator visuals in `ChartOverrides.appearance`. Where both
|
|
2022
|
+
could affect the same pixel, appearance wins.
|
|
2016
2023
|
|
|
2017
2024
|
Theme palette precedence, lowest first:
|
|
2018
2025
|
|
|
@@ -2023,7 +2030,7 @@ Chart appearance precedence, lowest first:
|
|
|
2023
2030
|
|
|
2024
2031
|
1. the built-in appearance for the selected mode;
|
|
2025
2032
|
2. the constructor's `appearance` partial;
|
|
2026
|
-
3. restored
|
|
2033
|
+
3. restored viewer appearance;
|
|
2027
2034
|
4. runtime `chart.applyAppearance` patches.
|
|
2028
2035
|
|
|
2029
2036
|
Resetting custom palettes returns the chart to the built-in mode and leaves saved chart appearance
|
|
@@ -2035,23 +2042,24 @@ opens in those colors on any theme.
|
|
|
2035
2042
|
|
|
2036
2043
|
## Compare
|
|
2037
2044
|
|
|
2038
|
-
|
|
2039
|
-
placements, persisted in the chart content blob. `same-percent`
|
|
2040
|
-
main price scale and flips it to percent while any such
|
|
2041
|
-
back when the last one leaves); `new-scale` binds the LEFT scale with absolute
|
|
2042
|
-
axis exists only while such a
|
|
2043
|
-
clip to the main series window, so a
|
|
2044
|
-
a curated quick-add list for the compare dialog;
|
|
2045
|
+
Compare draws OTHER symbols beside a chart's own. Each comparison is managed like an indicator:
|
|
2046
|
+
from the legend, at one of three placements, persisted in the chart content blob. `same-percent`
|
|
2047
|
+
shares the main price scale and flips it to percent while any such comparison lives (the prior
|
|
2048
|
+
scale mode comes back when the last one leaves); `new-scale` binds the LEFT scale with absolute
|
|
2049
|
+
prices (the left axis exists only while such a comparison does); `new-pane` takes a pane of its
|
|
2050
|
+
own. Compared bars clip to the main series window, so a comparison never extends the time axis.
|
|
2051
|
+
`features.compareSymbols` supplies a curated quick-add list for the compare dialog;
|
|
2052
|
+
`compare.symbols()` reads it back.
|
|
2045
2053
|
|
|
2046
2054
|
The widget's standard Compare door lives in the top bar, and `ui: { topBar: { compare: false } }`
|
|
2047
2055
|
hides it. The legend header does not duplicate that door. Commands and comparison-row actions remain
|
|
2048
|
-
available when the top-bar door is hidden, and `features: { compare: false }` removes
|
|
2049
|
-
altogether. The built-in dialog's search rows add at any of the three placements, curated
|
|
2050
|
-
above results, and the ADDED section removes. Each
|
|
2051
|
-
the dialog in change-symbol mode (the pick re-keys the
|
|
2052
|
-
beside the value (% under `same-percent`, the last close
|
|
2053
|
-
each chart
|
|
2054
|
-
that chart's content.
|
|
2056
|
+
available when the top-bar door is hidden, and `features: { compare: false }` removes compare
|
|
2057
|
+
altogether. The built-in dialog's search rows add at any of the three placements, curated
|
|
2058
|
+
`compareSymbols` rows sit above results, and the ADDED section removes. Each comparison takes a
|
|
2059
|
+
legend row whose title reopens the dialog in change-symbol mode (the pick re-keys the comparison in
|
|
2060
|
+
place), with an eye and a remove beside the value (% under `same-percent`, the last close
|
|
2061
|
+
otherwise). In a layout, each chart holds its own comparisons (`widget.activeChart().compare`), and
|
|
2062
|
+
they ride the layout blob with the rest of that chart's content.
|
|
2055
2063
|
|
|
2056
2064
|
```ts
|
|
2057
2065
|
import { createChart, createUdfDatafeed } from '@trdrs/quickcharts'
|
|
@@ -2067,15 +2075,15 @@ compare.add('CL', { placement: 'new-pane' })
|
|
|
2067
2075
|
compare.setVisible('CL', false)
|
|
2068
2076
|
const active = compare.list() // [{ symbol, placement, color, visible }]
|
|
2069
2077
|
note(`NQ last: ${compare.latest('NQ') ?? '-'}`)
|
|
2070
|
-
compare.remove('NQ') // the scale mode the
|
|
2078
|
+
compare.remove('NQ') // the scale mode the viewer held comes back
|
|
2071
2079
|
```
|
|
2072
2080
|
|
|
2073
2081
|
## Timeframes
|
|
2074
2082
|
|
|
2075
|
-
A timeframe token names
|
|
2076
|
-
units are ticks (`t`), seconds (`s`), minutes (`m`), hours (`h`), days (`d`), weeks (`w`) and
|
|
2077
|
-
months (`mo`), and each unit has a ceiling (`TIMEFRAME_MAX`). A token outside the grammar parses
|
|
2078
|
-
|
|
2083
|
+
A timeframe token names how much one bar spans: a count and a unit, `1m`, `4h`, `1d`, `3mo`, `500t`.
|
|
2084
|
+
The units are ticks (`t`), seconds (`s`), minutes (`m`), hours (`h`), days (`d`), weeks (`w`) and
|
|
2085
|
+
months (`mo`), and each unit has a ceiling (`TIMEFRAME_MAX`). A token outside the grammar parses as
|
|
2086
|
+
null, and the chart never asks a feed for it.
|
|
2079
2087
|
|
|
2080
2088
|
```ts
|
|
2081
2089
|
import { formatTimeframe, isIntradayTimeframe, parseTimeframe, timeframeSeconds } from '@trdrs/quickcharts'
|
|
@@ -2183,7 +2191,7 @@ if (equity) {
|
|
|
2183
2191
|
|
|
2184
2192
|
## Ranges
|
|
2185
2193
|
|
|
2186
|
-
`RANGE_PRESETS` lists the nine range presets, each a visible span and the
|
|
2194
|
+
`RANGE_PRESETS` lists the nine range presets, each a visible span and the timeframe it reads best
|
|
2187
2195
|
at: `1D` over one-minute bars through `All` over monthly bars. `rangeAvailable` withholds a preset
|
|
2188
2196
|
deeper than the history a symbol has, and `frameRange` sets a pane's visible window for a span,
|
|
2189
2197
|
anchored on the last real bar so a future whitespace horizon never frames as empty space. The
|
|
@@ -2211,7 +2219,7 @@ host's own search surface subscribes to the same state.
|
|
|
2211
2219
|
The widget prefetches the default catalog and reuses completed pages across search, compare and
|
|
2212
2220
|
change-symbol dialogs. Each opening owns its query, class filter and pending work. Closing it
|
|
2213
2221
|
discards late results without clearing completed pages. Locale changes and widget disposal clear
|
|
2214
|
-
the widget cache. A replacement widget
|
|
2222
|
+
the widget cache. A replacement widget starts with a cache of its own.
|
|
2215
2223
|
|
|
2216
2224
|
Completed reuse holds at most 32 queries and 5,000 rows, evicting least-recent entries. Retained
|
|
2217
2225
|
multi-page results reopen without a first-page refetch. Eviction does not truncate an active
|
|
@@ -2371,9 +2379,9 @@ catalog.dispose()
|
|
|
2371
2379
|
|
|
2372
2380
|
### The timeframe picker, away from a chart
|
|
2373
2381
|
|
|
2374
|
-
A page that asks for
|
|
2375
|
-
|
|
2376
|
-
custom composer, built by the same code, so
|
|
2382
|
+
A page that asks for a timeframe where no chart is mounted (a backtest's timeframe, an alert's
|
|
2383
|
+
timeframe) opens the list the chart's timeframe caret drops: the same unit groups, rows, labels and
|
|
2384
|
+
custom composer, built by the same code, so a timeframe reads there exactly as it reads on a chart.
|
|
2377
2385
|
`openTimeframePicker` drops it from a control you own, which gets `aria-expanded` while it is open
|
|
2378
2386
|
and focus back when it closes; `mountTimeframePicker` builds it bare into a box you own and
|
|
2379
2387
|
position, as a card on a phone. Picking a row, or composing a custom timeframe, hands the token to
|
|
@@ -2390,7 +2398,7 @@ do not serve is left out, and the composer does not offer one. `theme`, `locale`
|
|
|
2390
2398
|
reaches it outside any chart in either mode.
|
|
2391
2399
|
|
|
2392
2400
|
It carries no saved chips and no stars, and keeps nothing: the chips are a chart's quick-select row,
|
|
2393
|
-
stored with the chart's preferences, and a field that asks for one
|
|
2401
|
+
stored with the chart's preferences, and a field that asks for one timeframe has no row to put them
|
|
2394
2402
|
in. A composed timeframe is handed back and not added to any list. The drop-down takes the keyboard
|
|
2395
2403
|
as the chart's does (arrow keys, Home and End rove the rows; Escape and a press outside close
|
|
2396
2404
|
it) and moves as every menu does.
|
|
@@ -2398,13 +2406,13 @@ it) and moves as every menu does.
|
|
|
2398
2406
|
```ts
|
|
2399
2407
|
import { mountTimeframePicker, openTimeframePicker } from '@trdrs/quickcharts'
|
|
2400
2408
|
|
|
2401
|
-
declare const
|
|
2402
|
-
declare const
|
|
2409
|
+
declare const timeframeField: HTMLButtonElement
|
|
2410
|
+
declare const timeframeBox: HTMLElement
|
|
2403
2411
|
declare const backtest: { timeframe: string; setTimeframe(timeframe: string): void }
|
|
2404
2412
|
|
|
2405
|
-
|
|
2413
|
+
timeframeField.addEventListener('click', () => {
|
|
2406
2414
|
const picker = openTimeframePicker({
|
|
2407
|
-
anchor:
|
|
2415
|
+
anchor: timeframeField,
|
|
2408
2416
|
timeframe: backtest.timeframe,
|
|
2409
2417
|
resolutions: ['1m', '5m', '15m', '1h', '4h', '1d'], // what the feed serves
|
|
2410
2418
|
theme: { mode: 'light' },
|
|
@@ -2414,18 +2422,18 @@ intervalField.addEventListener('click', () => {
|
|
|
2414
2422
|
})
|
|
2415
2423
|
|
|
2416
2424
|
const card = mountTimeframePicker({
|
|
2417
|
-
container:
|
|
2425
|
+
container: timeframeBox,
|
|
2418
2426
|
timeframes: ['5m', '15m', '1h', '4h', '1d'],
|
|
2419
2427
|
timeframe: '1h',
|
|
2420
2428
|
onPick: (timeframe) => backtest.setTimeframe(timeframe),
|
|
2421
|
-
onClose: () =>
|
|
2429
|
+
onClose: () => timeframeBox.remove(),
|
|
2422
2430
|
})
|
|
2423
2431
|
card.focus()
|
|
2424
2432
|
```
|
|
2425
2433
|
|
|
2426
2434
|
### The legend
|
|
2427
2435
|
|
|
2428
|
-
Every chart carries its own legend over its plot: an identity row naming the market, the
|
|
2436
|
+
Every chart carries its own legend over its plot: an identity row naming the market, the timeframe
|
|
2429
2437
|
and the venue, and a values row carrying the hovered bar's O H L C and its move against the previous
|
|
2430
2438
|
close. The numbers are written through that chart's own formatter, so a level in the legend is the
|
|
2431
2439
|
level its price axis writes, and they follow the pointer while the crosshair is on the plot and the
|
|
@@ -2441,10 +2449,10 @@ The `size` is the chart's, not a suggestion: the box is already laid out, and pa
|
|
|
2441
2449
|
you were given is what lines the marks up down a list. The chart ships no artwork and fetches none,
|
|
2442
2450
|
so without this every mark is the neutral monogram it draws itself.
|
|
2443
2451
|
|
|
2444
|
-
`venueMark` and `
|
|
2445
|
-
the same way: the venue a market lists on, or the data
|
|
2446
|
-
receives the name the row writes (`exchange` or `
|
|
2447
|
-
a disposer. Without them a source wears its initial on a neutral disc.
|
|
2452
|
+
`venueMark` and `dataSourceMark` paint the source at the end of every symbol search and compare
|
|
2453
|
+
row the same way: the venue a market lists on, or the data source where a row names no venue. Each
|
|
2454
|
+
receives the name the row writes (`exchange` or `dataSource`), the element and the size, and
|
|
2455
|
+
returns a disposer. Without them a source wears its initial on a neutral disc.
|
|
2448
2456
|
|
|
2449
2457
|
```ts
|
|
2450
2458
|
import { createChart, createUdfDatafeed } from '@trdrs/quickcharts'
|
|
@@ -2488,7 +2496,7 @@ re-tile, a restore. Pointing your own surface at a chart moves no chart's symbol
|
|
|
2488
2496
|
concepts stay separate: each chart keeps charting what it charts, and one of them is the one you are
|
|
2489
2497
|
looking at.
|
|
2490
2498
|
|
|
2491
|
-
Five sync toggles fan changes across the charts: `symbol`, `
|
|
2499
|
+
Five sync toggles fan changes across the charts: `symbol`, `timeframe` and `dateRange` replay a
|
|
2492
2500
|
change onto every chart, `crosshair` mirrors continuously by time, and `time` centers every chart on
|
|
2493
2501
|
a clicked moment. The whole layout serializes as ONE opaque content blob (arrangement, sync flags,
|
|
2494
2502
|
durable chart-entity identities, active chart, every chart's own content), so a saved multi-chart
|
|
@@ -2565,9 +2573,9 @@ const saved = drawings?.export() // the persistence wire format (SerializedDrawi
|
|
|
2565
2573
|
note(`${selected?.type ?? 'nothing'} selected, ${saved?.length ?? 0} drawings`)
|
|
2566
2574
|
```
|
|
2567
2575
|
|
|
2568
|
-
### The toolbar
|
|
2576
|
+
### The drawing toolbar
|
|
2569
2577
|
|
|
2570
|
-
The toolbar
|
|
2578
|
+
The drawing toolbar runs down the chart's leading edge. Its buttons are the cursor with its three
|
|
2571
2579
|
pointer modes and the eraser; seven tool groups, each opening a flyout of the group's sections
|
|
2572
2580
|
with a star on every row that lands the tool on the favorites bar; Measure and Zoom; the magnet
|
|
2573
2581
|
with its weak and strong strengths; stay in drawing mode; lock all; the eye that hides drawings,
|
|
@@ -2596,7 +2604,7 @@ chosen.
|
|
|
2596
2604
|
Selecting a drawing shows the settings bar: templates, the stroke color with its opacity, the
|
|
2597
2605
|
background for tools that have one, the text color and font size for text tools, thickness and
|
|
2598
2606
|
line style, the settings gear, lock, delete, and a More menu with the stacking moves, the
|
|
2599
|
-
per-
|
|
2607
|
+
per-timeframe visibility presets, clone, copy and hide. Every edit persists at once and becomes the
|
|
2600
2608
|
tool's default for the next drawing of that type. The settings dialog opens from the gear with
|
|
2601
2609
|
Inputs, Style, Text, Table, Coordinates and Visibility pages as the tool has them; its edits apply
|
|
2602
2610
|
live, Cancel restores the drawing, and Ok commits the session as one edit.
|
|
@@ -2605,7 +2613,7 @@ Text-bearing tools open an inline editor where the text sits, in the drawing's o
|
|
|
2605
2613
|
placement committed empty is removed; an existing note committed empty is blanked. Ctrl or Cmd
|
|
2606
2614
|
with Enter commits, Escape cancels, and a press on the chart commits.
|
|
2607
2615
|
|
|
2608
|
-
Templates are named setups a
|
|
2616
|
+
Templates are named setups a viewer saves from either surface and applies on demand. They and
|
|
2609
2617
|
the remembered defaults ride `ChartSaveLoadAdapter.templates('drawing')`, so a host that keeps
|
|
2610
2618
|
saved charts on a server keeps these there too. Same-tool default changes are written in issue
|
|
2611
2619
|
order, and a delayed read or failed write does not replace the newest local choice. Store work is
|
|
@@ -2644,14 +2652,14 @@ Everything about drawings a host builds its own UI from is one subpath. A host t
|
|
|
2644
2652
|
never imports any of it.
|
|
2645
2653
|
|
|
2646
2654
|
```ts
|
|
2647
|
-
import {
|
|
2655
|
+
import { buildDrawingToolbarGroups, drawingTools, parseDrawingsStore, restoreDrawings, serializeDrawingsStore } from '@trdrs/quickcharts/drawings'
|
|
2648
2656
|
|
|
2649
2657
|
// The catalog: 90 tools in 14 categories, read-only.
|
|
2650
2658
|
const trendLine = drawingTools.get('trend_line')
|
|
2651
2659
|
const fibs = drawingTools.byCategory('fibonacci')
|
|
2652
2660
|
|
|
2653
|
-
// The
|
|
2654
|
-
for (const group of
|
|
2661
|
+
// The drawing toolbar as data: seven groups, their sections, and a catalog key per heading.
|
|
2662
|
+
for (const group of buildDrawingToolbarGroups()) {
|
|
2655
2663
|
for (const section of group.sections) note(`${group.id}/${section.label}: ${section.tools.length}`)
|
|
2656
2664
|
}
|
|
2657
2665
|
|
|
@@ -2661,10 +2669,10 @@ const drawings = restoreDrawings(store['ES'] ?? [])
|
|
|
2661
2669
|
localStorage.setItem('acme.chart.drawings', serializeDrawingsStore(store))
|
|
2662
2670
|
```
|
|
2663
2671
|
|
|
2664
|
-
The subpath carries the workflow models too: what the
|
|
2665
|
-
chart-owned drawings and indicators and nothing else), the cursor modes and the two
|
|
2666
|
-
tools, the magnet policy over `magnetSnap`, the remove menu, favorites over a
|
|
2667
|
-
standing preference record, and per-tool defaults and named templates over
|
|
2672
|
+
The subpath carries the workflow models too: what the drawing toolbar's eye blanks (`HideMode`,
|
|
2673
|
+
which reaches chart-owned drawings and indicators and nothing else), the cursor modes and the two
|
|
2674
|
+
transient tools, the magnet policy over `magnetSnap`, the remove menu, favorites over a
|
|
2675
|
+
`FavoritesPort`, the standing preference record, and per-tool defaults and named templates over
|
|
2668
2676
|
`ChartSaveLoadAdapter.templates('drawing')`. Each is a pure function or a plain record, so a host
|
|
2669
2677
|
builds its own controls without reimplementing the decisions behind them.
|
|
2670
2678
|
|
|
@@ -2672,7 +2680,7 @@ What a lock refuses is the library's own. A host locks and unlocks through the d
|
|
|
2672
2680
|
reads what they answer: `chart.drawings.lock` holds one drawing where it stands,
|
|
2673
2681
|
`chart.drawings.lockAll` suspends the whole chart, and every editing command answers `ok` or
|
|
2674
2682
|
`unavailable` for the state the chart is actually in, so a control built on those outcomes says
|
|
2675
|
-
exactly what the chart will accept. The gesture list below is what a
|
|
2683
|
+
exactly what the chart will accept. The gesture list below is what a viewer meets.
|
|
2676
2684
|
|
|
2677
2685
|
```ts
|
|
2678
2686
|
import { blanks, chooseHideMode, DEFAULT_HIDE_STATE, DrawingTemplates } from '@trdrs/quickcharts/drawings'
|
|
@@ -2707,9 +2715,9 @@ note(IMAGE_ACCEPT)
|
|
|
2707
2715
|
|
|
2708
2716
|
What to know:
|
|
2709
2717
|
|
|
2710
|
-
- **The subpath is a subset
|
|
2711
|
-
mutable registry stay inside the library.
|
|
2712
|
-
|
|
2718
|
+
- **The subpath is a deliberate subset.** The drawing classes, the model store and the
|
|
2719
|
+
mutable registry stay inside the library. A host chooses among the catalog's tools through
|
|
2720
|
+
`drawingTools` and the access policy.
|
|
2713
2721
|
- **Every tool places.** Fixed-anchor tools place by press-drag-release or click then click; an
|
|
2714
2722
|
instant tool (the position tools) lands whole from one press; a multipoint tool adds a point per
|
|
2715
2723
|
click until a double-click ends the run; a freehand tool captures the drag as a stroke; a
|
|
@@ -2730,13 +2738,13 @@ What to know:
|
|
|
2730
2738
|
so anchors never drift apart); grab an anchor handle to reshape; hold Shift to constrain a
|
|
2731
2739
|
two-point placement or an anchor drag to 45 degree rays; Ctrl-drag duplicates; the magnet pulls
|
|
2732
2740
|
a placed or dragged anchor onto the bar's own open, high, low or close; a locked drawing
|
|
2733
|
-
selects, takes the Delete and Clone a
|
|
2741
|
+
selects, takes the Delete and Clone a viewer asks for by name, and refuses a move, a resize, a
|
|
2734
2742
|
text edit, the eraser and a Ctrl-drag copy; lock all suspends every edit, Delete and Clone
|
|
2735
2743
|
included, until it is released.
|
|
2736
2744
|
|
|
2737
2745
|
## Extensions
|
|
2738
2746
|
|
|
2739
|
-
An extension is host code that draws on the chart, adds rows to its
|
|
2747
|
+
An extension is host code that draws on the chart, adds rows to its context menu, offers commands,
|
|
2740
2748
|
and stores viewer state in the chart's own save blob. The chart attaches it at mount, pushes its
|
|
2741
2749
|
changes at it, and takes it down at teardown, along with everything it drew.
|
|
2742
2750
|
|
|
@@ -2790,9 +2798,9 @@ What to know:
|
|
|
2790
2798
|
layer on the document body, painted with the widget's theme: a menu or an editor mounted there at
|
|
2791
2799
|
viewport coordinates stands over every pane and over whatever the page stacks around the widget,
|
|
2792
2800
|
which the pane's own overlay cannot promise. `ctx.symbolTitle()` is the name symbology gives the
|
|
2793
|
-
charted market, the name the legend and the
|
|
2801
|
+
charted market, the name the legend and the context menu print; `ctx.chart.symbol()` stays the
|
|
2794
2802
|
ticker an action is sent for. `ctx.painters` carries the mark painters you supplied as `.symbol`,
|
|
2795
|
-
`.venue` and `.
|
|
2803
|
+
`.venue` and `.dataSource`, so a surface that names a market paints it with the same mark the
|
|
2796
2804
|
legend and the search rows wear rather than shipping artwork of its own; a painter you did not
|
|
2797
2805
|
supply is `null`, and the surface writes the name alone.
|
|
2798
2806
|
- **A contributed row may bring its own glyph.** `ChartExtensionMenuItem.icon` is a
|
|
@@ -2807,19 +2815,20 @@ What to know:
|
|
|
2807
2815
|
default), an action on the price the pointer landed on, placed under Copy price and Paste; or
|
|
2808
2816
|
`view`, a switch over what the chart shows, placed under the remove rows. Rows keep the order
|
|
2809
2817
|
they were contributed in within their group.
|
|
2810
|
-
- **A drawn layer can join the
|
|
2811
|
-
lists the layer in the eye's menu after the
|
|
2812
|
-
"Hide all", which blanks it with them. `label`
|
|
2813
|
-
the two marks the eye wears while the layer is
|
|
2814
|
-
the current state at contribution and on every
|
|
2815
|
-
`setHidden()` through the same eye the
|
|
2818
|
+
- **A drawn layer can join the drawing toolbar's eye.**
|
|
2819
|
+
`ctx.contributeHideLayer({ id, label, icon, apply })` lists the layer in the eye's menu after the
|
|
2820
|
+
chart's own drawings and indicators and before "Hide all", which blanks it with them. `label`
|
|
2821
|
+
carries the row's wording in both states, `icon` the two marks the eye wears while the layer is
|
|
2822
|
+
its subject, and `apply(hidden)` is called with the current state at contribution and on every
|
|
2823
|
+
change. The handle reads `hidden()`, flips `setHidden()` through the same eye the drawing toolbar
|
|
2824
|
+
drives, and `remove()` withdraws the layer.
|
|
2816
2825
|
- **A printed chord is a real binding.** `ChartExtensionMenuItem.shortcut` prints on the row and
|
|
2817
2826
|
answers to the key. The chart's dispatcher offers a press no built-in verb claims to the rows your
|
|
2818
|
-
|
|
2819
|
-
the click makes. The press acts on the tile the pointer is inside, active or
|
|
2820
|
-
tile, on a point with no readable level, while the viewer is typing, or while
|
|
2821
|
-
keyboard, the key is left to your page. A row your
|
|
2822
|
-
carries one chord.
|
|
2827
|
+
`contributeContextMenu` callback returns for the level under the pointer and runs that row's own
|
|
2828
|
+
`run`, the same call the click makes. The press acts on the tile the pointer is inside, active or
|
|
2829
|
+
not; outside every tile, on a point with no readable level, while the viewer is typing, or while
|
|
2830
|
+
a modal holds the keyboard, the key is left to your page. A row your callback withholds claims no
|
|
2831
|
+
key, and a row carries one chord.
|
|
2823
2832
|
- **A glyph is bounded, and a refusal is free.** Up to 8 shapes, each up to 2048 characters of path
|
|
2824
2833
|
data with every number in it finite, and an `outline` stroke width above 0 and up to 8. A shape
|
|
2825
2834
|
outside that is dropped and the rest of the glyph still draws; a descriptor outside it draws
|
|
@@ -2842,7 +2851,7 @@ What to know:
|
|
|
2842
2851
|
re-attaches it on every switch, so a market-scoped overlay cannot carry one market's drawing onto
|
|
2843
2852
|
another's bars.
|
|
2844
2853
|
- **A failing extension is its own problem.** A throw in `attach` drops that extension and the
|
|
2845
|
-
chart still mounts; a throw in a subscriber, a menu
|
|
2854
|
+
chart still mounts; a throw in a subscriber, a menu builder, a command or a teardown is
|
|
2846
2855
|
contained.
|
|
2847
2856
|
- **Layouts attach per chart.** A widget hands its shared options to every chart it tiles, so each
|
|
2848
2857
|
chart gets its own attachment, its own context and its own state slot.
|
|
@@ -2870,7 +2879,7 @@ Every claim in this document maps to a test or a generated artifact in the packa
|
|
|
2870
2879
|
and the tarball, and the third-party notices are held by the boundary tests and
|
|
2871
2880
|
`THIRD-PARTY-NOTICES.md`.
|
|
2872
2881
|
|
|
2873
|
-
## Versioning
|
|
2882
|
+
## Versioning
|
|
2874
2883
|
|
|
2875
2884
|
- **SemVer, enforced at the gate.** The public surface is pinned by an API-surface test (every
|
|
2876
2885
|
exported name and its runtime kind), the shipped type declarations are compiled against by a
|
|
@@ -2882,8 +2891,8 @@ Every claim in this document maps to a test or a generated artifact in the packa
|
|
|
2882
2891
|
and fields (`config` and `serverTime` are the pattern): an existing
|
|
2883
2892
|
implementation keeps compiling, and the widget treats absence as "unconstrained / not supported".
|
|
2884
2893
|
Your integration never breaks by standing still within a major.
|
|
2885
|
-
- **
|
|
2886
|
-
|
|
2887
|
-
|
|
2894
|
+
- **A major version may rename or remove public names.** Its upgrading guide in
|
|
2895
|
+
[CHANGELOG.md](CHANGELOG.md) lists each one, old to new, with how saved state carries over: what
|
|
2896
|
+
the previous major saved still opens, and the next save writes the current names.
|
|
2888
2897
|
- **The wire timeframe grammar is stable vocabulary.** `<N><unit>` with units `t s m h d w mo`.
|
|
2889
2898
|
Extensions may add units; an existing token never changes meaning.
|