@trdrs/quickcharts 5.1.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +10 -0
- package/dist/{chunk-GFQQSY47.js → chunk-U4W26DXU.js} +2 -2
- package/dist/{chunk-GFQQSY47.js.map → chunk-U4W26DXU.js.map} +1 -1
- package/dist/feature-manifest.json +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +36 -24
- package/dist/index.js.map +1 -1
- package/dist/quickcharts.css +93 -175
- package/dist/{symbols-CHJGWrf-.d.ts → symbols-CCYUK8MU.d.ts} +5 -1
- package/dist/symbols.d.ts +1 -1
- package/dist/symbols.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 5.2.0
|
|
6
|
+
|
|
7
|
+
The chart's right-click menu ends on Settings…, which opens the chart settings dialog, wherever the chart draws its settings door in the top bar.
|
|
8
|
+
|
|
9
|
+
The symbol search and compare dialogs open on their field with no title band, in a box rounded 20px. Every row is one 56px layout in each mode: a 36px mark, the ticker at 16px over its description at 12px with the market's kind as a small tag after it, and the source as a 24px mark at the row's end that names it in its tooltip. The pointer and the keyboard's row wear one rounded plate.
|
|
10
|
+
|
|
11
|
+
`SymbolRow.ticker` is the ticker a viewer reads a row's market by, where the feed writes one apart from its symbol; `symbolNames` and the search rows read it, and a row without it reads the symbol's own ticker.
|
|
12
|
+
|
|
13
|
+
## 5.1.1
|
|
14
|
+
|
|
15
|
+
Range presets reconcile overlapping history pages with streamed bars and preserve a newer navigation while a page is pending.
|
|
16
|
+
|
|
5
17
|
## 5.1.0
|
|
6
18
|
|
|
7
19
|
Charts open live subscriptions alongside history, frame the first arriving data, and retain newer streamed prices when history arrives later. A snapshot with `backfill: true` adds missing history without replacing bars already held.
|
package/README.md
CHANGED
|
@@ -337,6 +337,16 @@ symbolNames({ symbol: 'NASDAQ:AAPL', name: 'Apple Inc', exchange: 'NASDAQ', type
|
|
|
337
337
|
symbolNames('HYPERLIQUID:ETH').mark // 'ETH', before the symbol resolves
|
|
338
338
|
```
|
|
339
339
|
|
|
340
|
+
One exchange prefix comes off a symbol on its own. Where your feed writes a symbol that says more,
|
|
341
|
+
give the row the `ticker` a viewer reads it by, as `SymbolInfo.ticker` states it for the charted
|
|
342
|
+
symbol; the row keeps its `symbol` as the market's identity:
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
import { symbolNames } from '@trdrs/quickcharts'
|
|
346
|
+
|
|
347
|
+
symbolNames({ symbol: 'EXCH:BOOK:NVDA', ticker: 'NVDA', name: 'NVIDIA Corp', exchange: 'EXCH', type: 'stock' }).mark // 'NVDA'
|
|
348
|
+
```
|
|
349
|
+
|
|
340
350
|
`@trdrs/quickcharts/symbols` carries the same rule on its own, `symbolNames` and `bareTicker`, with
|
|
341
351
|
nothing that names a window, a document or a DOM type, so a view of your own with no DOM, a native
|
|
342
352
|
search list among them, names a market exactly as the chart does. `bareTicker` is the ticker inside
|
|
@@ -17,7 +17,7 @@ function pairLabel(ticker, type, currencyCode) {
|
|
|
17
17
|
}
|
|
18
18
|
function factsOf(symbol) {
|
|
19
19
|
if (typeof symbol === "string") return { ticker: symbol, type: "", shortName: "", longName: "", currencyCode: void 0 };
|
|
20
|
-
if ("symbol" in symbol) return { ticker: symbol.symbol, type: symbol.type, shortName: "", longName: symbol.name.trim(), currencyCode: symbol.currencyCode };
|
|
20
|
+
if ("symbol" in symbol) return { ticker: symbol.ticker?.trim() || symbol.symbol, type: symbol.type, shortName: "", longName: symbol.name.trim(), currencyCode: symbol.currencyCode };
|
|
21
21
|
const name = symbol.name.trim();
|
|
22
22
|
const description = symbol.description.trim();
|
|
23
23
|
return { ticker: symbol.ticker, type: symbol.type, shortName: name !== description ? name : "", longName: description, currencyCode: symbol.currencyCode };
|
|
@@ -38,4 +38,4 @@ export {
|
|
|
38
38
|
bareTicker,
|
|
39
39
|
symbolNames
|
|
40
40
|
};
|
|
41
|
-
//# sourceMappingURL=chunk-
|
|
41
|
+
//# sourceMappingURL=chunk-U4W26DXU.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/symbolLabel.ts"],"sourcesContent":["// How a symbol is WRITTEN on screen: one rule, three faces, kept in one file so they cannot drift.\n// The toolbar pill wears the compact mark, the legend wears the title, and a search row wears the\n// mark beside the description. Every face drops the venue prefix, which is feed identity rather\n// than anything a viewer reads, and every surface that names a market, in this package or over it,\n// reads the same faces from `symbolNames`.\nimport type { SymbolRow } from './datafeed'\nimport type { SymbolInfo } from './symbology'\n\n/** The ticker inside a feed symbol. Only a well-formed `VENUE:TICKER` sheds its prefix; a spread\n * expression, or anything else the pattern does not admit, is its own label and passes through. */\nexport function bareTicker(symbol: string): string {\n return /^[A-Za-z][A-Za-z0-9._-]*:([A-Za-z0-9][A-Za-z0-9._!]*)$/.exec(symbol)?.[1] ?? symbol\n}\n\n/** A ticker written as a slash pair (`BTC/USD`): catalog identity that already says what it is\n * priced in. A reciprocal expression (`1/ES`) starts with a digit and is not one. */\nconst SLASH_PAIR = /^[A-Za-z][A-Za-z0-9.]*\\/[A-Za-z][A-Za-z0-9.]*$/\n\n/** Compact presentation of one symbol. Feed identity and spread expressions stay untouched. */\nexport function symbolLabel(symbol: string): string {\n const ticker = bareTicker(symbol)\n return SLASH_PAIR.test(ticker) ? ticker.replace('/', '') : ticker\n}\n\n/** The markets whose symbols ARE a pair: one thing priced in another, where the ticker alone says\n * what is being bought but not what it is priced in. Those read as `BASE / QUOTE`.\n *\n * Every other market is deliberately absent. Nearly every symbol carries a `currencyCode`, so the\n * gate cannot be \"has a currency\": a share quoted in dollars is not a pair, and `AAPL / USD` would\n * claim one that does not exist. */\nconst PAIR_MARKETS = new Set(['crypto', 'forex'])\n\n/** `BASE / QUOTE` for a pair market, or null for anything that is not one.\n *\n * The quote comes from the feed's own currency; a ticker that already carries it as a suffix\n * (`BTCUSDT`, `EURUSD`) sheds it rather than repeating it, and the base is whatever the ticker\n * states, so an inverted quotation reads the way it is written. */\nexport function pairLabel(ticker: string, type: string, currencyCode: string | undefined): string | null {\n const quote = currencyCode?.trim()\n if (!quote || !PAIR_MARKETS.has(type.toLowerCase())) return null\n const bare = bareTicker(ticker)\n const base = bare.length > quote.length && bare.toUpperCase().endsWith(quote.toUpperCase()) ? bare.slice(0, -quote.length) : bare\n return base && base.toUpperCase() !== quote.toUpperCase() ? `${base} / ${quote}` : null\n}\n\n/** The three ways one market is written, from one rule. */\nexport interface SymbolNames {\n /** The compact mark a label wears at a glance: a pair closed up (`BTCUSDC`, `EURUSD`), otherwise\n * the bare ticker (`ES1!`, `AAPL`). A spread expression is its own mark, operators and all. */\n mark: string\n /** The title a reading wears: a pair spaced (`BTC / USDC`), otherwise the feed's short name where\n * it stated one apart from the description, otherwise the bare ticker. */\n title: string\n /** The description beside a mark: a pair spaced, otherwise the feed's long description, otherwise\n * the bare ticker, so a market never repeats its own mark for want of a name. */\n description: string\n}\n\n/** The facts the rule reads, in one shape whatever the surface holds. */\ninterface Facts {\n ticker: string\n type: string\n shortName: string\n longName: string\n currencyCode: string | undefined\n}\n\nfunction factsOf(symbol: SymbolInfo | SymbolRow | string): Facts {\n if (typeof symbol === 'string') return { ticker: symbol, type: '', shortName: '', longName: '', currencyCode: undefined }\n // A search row states one name, the long one; a resolved symbol states a short name beside its\n // description, and a short name that merely repeats the description has not been given.\n if ('symbol' in symbol) return { ticker: symbol.symbol, type: symbol.type, shortName: '', longName: symbol.name.trim(), currencyCode: symbol.currencyCode }\n const name = symbol.name.trim()\n const description = symbol.description.trim()\n return { ticker: symbol.ticker, type: symbol.type, shortName: name !== description ? name : '', longName: description, currencyCode: symbol.currencyCode }\n}\n\n/** How a market is named, from a resolved `SymbolInfo`, a search row, or the feed symbol alone\n * before either has landed.\n *\n * A pair market reads as `BTC / USDC` or `EUR / USD`, both sides in the codes the market itself\n * trades in, never a spelled-out currency name. The quote comes from `currencyCode`, and a ticker\n * written as a slash pair (`BTC/USD`) needs no currency to say so. Before a symbol resolves there\n * is no pair to write, so the bare ticker stands on its own rather than guessing at a quote. A\n * market that is not a pair keeps the feed's own words: the short name as its title, the long\n * description beside its mark. */\nexport function symbolNames(symbol: SymbolInfo | SymbolRow | string): SymbolNames {\n const facts = factsOf(symbol)\n if (facts.type.toLowerCase() === 'spread') return { mark: facts.ticker, title: facts.ticker, description: facts.ticker }\n const bare = bareTicker(facts.ticker)\n const pair = pairLabel(facts.ticker, facts.type, facts.currencyCode) ?? (SLASH_PAIR.test(bare) ? bare.replace('/', ' / ') : null)\n return {\n mark: pair ? pair.replace(' / ', '') : symbolLabel(facts.ticker),\n title: pair ?? (facts.shortName || bare),\n description: pair ?? (facts.longName || bare),\n }\n}\n"],"mappings":";AAUO,SAAS,WAAW,QAAwB;AACjD,SAAO,yDAAyD,KAAK,MAAM,IAAI,CAAC,KAAK;AACvF;AAIA,IAAM,aAAa;AAGZ,SAAS,YAAY,QAAwB;AAClD,QAAM,SAAS,WAAW,MAAM;AAChC,SAAO,WAAW,KAAK,MAAM,IAAI,OAAO,QAAQ,KAAK,EAAE,IAAI;AAC7D;AAQA,IAAM,eAAe,oBAAI,IAAI,CAAC,UAAU,OAAO,CAAC;AAOzC,SAAS,UAAU,QAAgB,MAAc,cAAiD;AACvG,QAAM,QAAQ,cAAc,KAAK;AACjC,MAAI,CAAC,SAAS,CAAC,aAAa,IAAI,KAAK,YAAY,CAAC,EAAG,QAAO;AAC5D,QAAM,OAAO,WAAW,MAAM;AAC9B,QAAM,OAAO,KAAK,SAAS,MAAM,UAAU,KAAK,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC,IAAI,KAAK,MAAM,GAAG,CAAC,MAAM,MAAM,IAAI;AAC7H,SAAO,QAAQ,KAAK,YAAY,MAAM,MAAM,YAAY,IAAI,GAAG,IAAI,MAAM,KAAK,KAAK;AACrF;AAwBA,SAAS,QAAQ,QAAgD;AAC/D,MAAI,OAAO,WAAW,SAAU,QAAO,EAAE,QAAQ,QAAQ,MAAM,IAAI,WAAW,IAAI,UAAU,IAAI,cAAc,OAAU;AAGxH,MAAI,YAAY,OAAQ,QAAO,EAAE,QAAQ,OAAO,QAAQ,MAAM,OAAO,MAAM,WAAW,IAAI,UAAU,OAAO,KAAK,KAAK,GAAG,cAAc,OAAO,aAAa;
|
|
1
|
+
{"version":3,"sources":["../src/symbolLabel.ts"],"sourcesContent":["// How a symbol is WRITTEN on screen: one rule, three faces, kept in one file so they cannot drift.\n// The toolbar pill wears the compact mark, the legend wears the title, and a search row wears the\n// mark beside the description. Every face drops the venue prefix, which is feed identity rather\n// than anything a viewer reads, and every surface that names a market, in this package or over it,\n// reads the same faces from `symbolNames`.\nimport type { SymbolRow } from './datafeed'\nimport type { SymbolInfo } from './symbology'\n\n/** The ticker inside a feed symbol. Only a well-formed `VENUE:TICKER` sheds its prefix; a spread\n * expression, or anything else the pattern does not admit, is its own label and passes through. */\nexport function bareTicker(symbol: string): string {\n return /^[A-Za-z][A-Za-z0-9._-]*:([A-Za-z0-9][A-Za-z0-9._!]*)$/.exec(symbol)?.[1] ?? symbol\n}\n\n/** A ticker written as a slash pair (`BTC/USD`): catalog identity that already says what it is\n * priced in. A reciprocal expression (`1/ES`) starts with a digit and is not one. */\nconst SLASH_PAIR = /^[A-Za-z][A-Za-z0-9.]*\\/[A-Za-z][A-Za-z0-9.]*$/\n\n/** Compact presentation of one symbol. Feed identity and spread expressions stay untouched. */\nexport function symbolLabel(symbol: string): string {\n const ticker = bareTicker(symbol)\n return SLASH_PAIR.test(ticker) ? ticker.replace('/', '') : ticker\n}\n\n/** The markets whose symbols ARE a pair: one thing priced in another, where the ticker alone says\n * what is being bought but not what it is priced in. Those read as `BASE / QUOTE`.\n *\n * Every other market is deliberately absent. Nearly every symbol carries a `currencyCode`, so the\n * gate cannot be \"has a currency\": a share quoted in dollars is not a pair, and `AAPL / USD` would\n * claim one that does not exist. */\nconst PAIR_MARKETS = new Set(['crypto', 'forex'])\n\n/** `BASE / QUOTE` for a pair market, or null for anything that is not one.\n *\n * The quote comes from the feed's own currency; a ticker that already carries it as a suffix\n * (`BTCUSDT`, `EURUSD`) sheds it rather than repeating it, and the base is whatever the ticker\n * states, so an inverted quotation reads the way it is written. */\nexport function pairLabel(ticker: string, type: string, currencyCode: string | undefined): string | null {\n const quote = currencyCode?.trim()\n if (!quote || !PAIR_MARKETS.has(type.toLowerCase())) return null\n const bare = bareTicker(ticker)\n const base = bare.length > quote.length && bare.toUpperCase().endsWith(quote.toUpperCase()) ? bare.slice(0, -quote.length) : bare\n return base && base.toUpperCase() !== quote.toUpperCase() ? `${base} / ${quote}` : null\n}\n\n/** The three ways one market is written, from one rule. */\nexport interface SymbolNames {\n /** The compact mark a label wears at a glance: a pair closed up (`BTCUSDC`, `EURUSD`), otherwise\n * the bare ticker (`ES1!`, `AAPL`). A spread expression is its own mark, operators and all. */\n mark: string\n /** The title a reading wears: a pair spaced (`BTC / USDC`), otherwise the feed's short name where\n * it stated one apart from the description, otherwise the bare ticker. */\n title: string\n /** The description beside a mark: a pair spaced, otherwise the feed's long description, otherwise\n * the bare ticker, so a market never repeats its own mark for want of a name. */\n description: string\n}\n\n/** The facts the rule reads, in one shape whatever the surface holds. */\ninterface Facts {\n ticker: string\n type: string\n shortName: string\n longName: string\n currencyCode: string | undefined\n}\n\nfunction factsOf(symbol: SymbolInfo | SymbolRow | string): Facts {\n if (typeof symbol === 'string') return { ticker: symbol, type: '', shortName: '', longName: '', currencyCode: undefined }\n // A search row states one name, the long one; a resolved symbol states a short name beside its\n // description, and a short name that merely repeats the description has not been given.\n if ('symbol' in symbol) return { ticker: symbol.ticker?.trim() || symbol.symbol, type: symbol.type, shortName: '', longName: symbol.name.trim(), currencyCode: symbol.currencyCode }\n const name = symbol.name.trim()\n const description = symbol.description.trim()\n return { ticker: symbol.ticker, type: symbol.type, shortName: name !== description ? name : '', longName: description, currencyCode: symbol.currencyCode }\n}\n\n/** How a market is named, from a resolved `SymbolInfo`, a search row, or the feed symbol alone\n * before either has landed.\n *\n * A pair market reads as `BTC / USDC` or `EUR / USD`, both sides in the codes the market itself\n * trades in, never a spelled-out currency name. The quote comes from `currencyCode`, and a ticker\n * written as a slash pair (`BTC/USD`) needs no currency to say so. Before a symbol resolves there\n * is no pair to write, so the bare ticker stands on its own rather than guessing at a quote. A\n * market that is not a pair keeps the feed's own words: the short name as its title, the long\n * description beside its mark. */\nexport function symbolNames(symbol: SymbolInfo | SymbolRow | string): SymbolNames {\n const facts = factsOf(symbol)\n if (facts.type.toLowerCase() === 'spread') return { mark: facts.ticker, title: facts.ticker, description: facts.ticker }\n const bare = bareTicker(facts.ticker)\n const pair = pairLabel(facts.ticker, facts.type, facts.currencyCode) ?? (SLASH_PAIR.test(bare) ? bare.replace('/', ' / ') : null)\n return {\n mark: pair ? pair.replace(' / ', '') : symbolLabel(facts.ticker),\n title: pair ?? (facts.shortName || bare),\n description: pair ?? (facts.longName || bare),\n }\n}\n"],"mappings":";AAUO,SAAS,WAAW,QAAwB;AACjD,SAAO,yDAAyD,KAAK,MAAM,IAAI,CAAC,KAAK;AACvF;AAIA,IAAM,aAAa;AAGZ,SAAS,YAAY,QAAwB;AAClD,QAAM,SAAS,WAAW,MAAM;AAChC,SAAO,WAAW,KAAK,MAAM,IAAI,OAAO,QAAQ,KAAK,EAAE,IAAI;AAC7D;AAQA,IAAM,eAAe,oBAAI,IAAI,CAAC,UAAU,OAAO,CAAC;AAOzC,SAAS,UAAU,QAAgB,MAAc,cAAiD;AACvG,QAAM,QAAQ,cAAc,KAAK;AACjC,MAAI,CAAC,SAAS,CAAC,aAAa,IAAI,KAAK,YAAY,CAAC,EAAG,QAAO;AAC5D,QAAM,OAAO,WAAW,MAAM;AAC9B,QAAM,OAAO,KAAK,SAAS,MAAM,UAAU,KAAK,YAAY,EAAE,SAAS,MAAM,YAAY,CAAC,IAAI,KAAK,MAAM,GAAG,CAAC,MAAM,MAAM,IAAI;AAC7H,SAAO,QAAQ,KAAK,YAAY,MAAM,MAAM,YAAY,IAAI,GAAG,IAAI,MAAM,KAAK,KAAK;AACrF;AAwBA,SAAS,QAAQ,QAAgD;AAC/D,MAAI,OAAO,WAAW,SAAU,QAAO,EAAE,QAAQ,QAAQ,MAAM,IAAI,WAAW,IAAI,UAAU,IAAI,cAAc,OAAU;AAGxH,MAAI,YAAY,OAAQ,QAAO,EAAE,QAAQ,OAAO,QAAQ,KAAK,KAAK,OAAO,QAAQ,MAAM,OAAO,MAAM,WAAW,IAAI,UAAU,OAAO,KAAK,KAAK,GAAG,cAAc,OAAO,aAAa;AACnL,QAAM,OAAO,OAAO,KAAK,KAAK;AAC9B,QAAM,cAAc,OAAO,YAAY,KAAK;AAC5C,SAAO,EAAE,QAAQ,OAAO,QAAQ,MAAM,OAAO,MAAM,WAAW,SAAS,cAAc,OAAO,IAAI,UAAU,aAAa,cAAc,OAAO,aAAa;AAC3J;AAWO,SAAS,YAAY,QAAsD;AAChF,QAAM,QAAQ,QAAQ,MAAM;AAC5B,MAAI,MAAM,KAAK,YAAY,MAAM,SAAU,QAAO,EAAE,MAAM,MAAM,QAAQ,OAAO,MAAM,QAAQ,aAAa,MAAM,OAAO;AACvH,QAAM,OAAO,WAAW,MAAM,MAAM;AACpC,QAAM,OAAO,UAAU,MAAM,QAAQ,MAAM,MAAM,MAAM,YAAY,MAAM,WAAW,KAAK,IAAI,IAAI,KAAK,QAAQ,KAAK,KAAK,IAAI;AAC5H,SAAO;AAAA,IACL,MAAM,OAAO,KAAK,QAAQ,OAAO,EAAE,IAAI,YAAY,MAAM,MAAM;AAAA,IAC/D,OAAO,SAAS,MAAM,aAAa;AAAA,IACnC,aAAa,SAAS,MAAM,YAAY;AAAA,EAC1C;AACF;","names":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as ChartDatafeed, M as MarkIconId, F as FeedBar, S as SymbolRow, D as DatafeedSearchOptions, a as SearchPage, b as SearchClassNode } from './symbols-
|
|
2
|
-
export { B as BarMark, c as BarsEvent, d as DatafeedConfig, e as FeedUnavailableError, H as HistoryPage, f as MarkColor, g as MarkColorPair, h as MarkColorRole, i as MarkLine, j as MarkLineStyle, k as MarkPlacement, l as MarkShape, O as OlderPageVerdict, P as PricesHandlers, m as SubscribeHandlers, n as SymbolNames, o as SymbolPrices, T as TimescaleMark, p as olderPageVerdict, s as symbolNames } from './symbols-
|
|
1
|
+
import { C as ChartDatafeed, M as MarkIconId, F as FeedBar, S as SymbolRow, D as DatafeedSearchOptions, a as SearchPage, b as SearchClassNode } from './symbols-CCYUK8MU.js';
|
|
2
|
+
export { B as BarMark, c as BarsEvent, d as DatafeedConfig, e as FeedUnavailableError, H as HistoryPage, f as MarkColor, g as MarkColorPair, h as MarkColorRole, i as MarkLine, j as MarkLineStyle, k as MarkPlacement, l as MarkShape, O as OlderPageVerdict, P as PricesHandlers, m as SubscribeHandlers, n as SymbolNames, o as SymbolPrices, T as TimescaleMark, p as olderPageVerdict, s as symbolNames } from './symbols-CCYUK8MU.js';
|
|
3
3
|
import { ao as en, C as ChartMessageKey, G as GlyphSourcePort, M as MagnetMode, d as CursorMode, Q as TextEditFrame, N as TextDraft, L as LineStyle, I as IDrawing, m as DrawingCounts, D as DrawingStyle, $ as VisibilityPreset, X as ToolPreset, Y as ToolTemplate, S as SerializedDrawing, o as DrawingPreferences, l as DrawingAssetPort } from './assets-DF3nozNV.js';
|
|
4
4
|
import { b as ResourceRef, C as ChartSaveLoadAdapter, q as ChartMeta, t as ChartBody, h as DrawingResourceContext, R as ResourceStore, u as DrawingsMeta, j as DrawingsBody, T as TemplateMeta, a as TemplateBody, v as LayoutMeta, w as LayoutBody, e as DrawingContextKind } from './resources-XglhzzW0.js';
|
|
5
5
|
export { c as ChartLocalDrawingContext, D as DRAWING_CONTEXT_VERSION, d as DRAWING_DOCUMENT_VERSION, f as DrawingEntry, g as DrawingGroup, i as DrawingTombstone, L as LayoutSharedDrawingContext, M as MemoryResourcesOptions, x as ResourceAbortError, S as SymbolGlobalDrawingContext, y as TemplateKind, W as WriteOutcome, k as drawingContextKey, l as emptyDrawingDocument, m as liveDrawingEntries, n as liveDrawingGroups, z as memorySaveLoadAdapter, o as mergeDrawingDocuments, p as parseDrawingDocument, r as reviseDrawingDocument, s as sameDrawingContext } from './resources-XglhzzW0.js';
|
package/dist/index.js
CHANGED
|
@@ -143,7 +143,7 @@ import {
|
|
|
143
143
|
} from "./chunk-QYGSDD2Q.js";
|
|
144
144
|
import {
|
|
145
145
|
symbolNames
|
|
146
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-U4W26DXU.js";
|
|
147
147
|
|
|
148
148
|
// src/datafeed.ts
|
|
149
149
|
function olderPageVerdict(page, askedTo, alreadyHopped) {
|
|
@@ -19643,7 +19643,8 @@ var MENU_COMMAND = {
|
|
|
19643
19643
|
"copy-price": "chart.price.copy",
|
|
19644
19644
|
paste: "chart.drawings.paste",
|
|
19645
19645
|
"remove-indicators": "chart.indicators.removeAll",
|
|
19646
|
-
"remove-drawings": "chart.drawings.removeAll"
|
|
19646
|
+
"remove-drawings": "chart.drawings.removeAll",
|
|
19647
|
+
settings: "chart.settings.open"
|
|
19647
19648
|
};
|
|
19648
19649
|
var PLACE_HORIZONTAL_LINE = "chart.drawings.placeHorizontalLine";
|
|
19649
19650
|
function levelAt(series2, y, step) {
|
|
@@ -19689,12 +19690,11 @@ function attachMenuPlane(deps) {
|
|
|
19689
19690
|
{
|
|
19690
19691
|
priceText,
|
|
19691
19692
|
symbol: deps.symbol(),
|
|
19692
|
-
// The
|
|
19693
|
-
//
|
|
19694
|
-
//
|
|
19695
|
-
// and the chart.drawings.* commands drive.
|
|
19693
|
+
// The paste row is live exactly when the paste command would run (a copied drawing on the
|
|
19694
|
+
// clipboard, the verb permitted), and the settings row wherever the chart offers its
|
|
19695
|
+
// settings door and the command would open the dialog.
|
|
19696
19696
|
canPaste: deps.commands.available("chart.drawings.paste"),
|
|
19697
|
-
canSettings:
|
|
19697
|
+
canSettings: (deps.settingsDoor ?? true) && deps.commands.available(MENU_COMMAND.settings),
|
|
19698
19698
|
indicatorCount: deps.indicatorCount(),
|
|
19699
19699
|
drawingCount: deps.drawingCount(),
|
|
19700
19700
|
...table ? { table } : {}
|
|
@@ -22628,6 +22628,7 @@ function createChartInstance(deps) {
|
|
|
22628
22628
|
drawingCount: () => drawings2.handle?.count() ?? 0,
|
|
22629
22629
|
extensions: () => extensions.host,
|
|
22630
22630
|
shown: (id) => commandShown(deps.access, id),
|
|
22631
|
+
settingsDoor: deps.ui.settingsMenu,
|
|
22631
22632
|
setLevel: (price) => {
|
|
22632
22633
|
menuLevel = price;
|
|
22633
22634
|
},
|
|
@@ -23043,17 +23044,22 @@ function createChartInstance(deps) {
|
|
|
23043
23044
|
if (short <= 0) return;
|
|
23044
23045
|
paging = true;
|
|
23045
23046
|
const myEpoch = epoch;
|
|
23047
|
+
const myNavigation = navigationEpoch;
|
|
23046
23048
|
const oldest = bars[0].t;
|
|
23047
23049
|
void fetchOlder(oldest - 1, short).then(({ olderBars, end }) => {
|
|
23048
23050
|
if (disposed || myEpoch !== epoch) return;
|
|
23049
23051
|
if (end) noMoreHistory = true;
|
|
23050
|
-
const
|
|
23051
|
-
if (
|
|
23052
|
-
|
|
23053
|
-
|
|
23054
|
-
|
|
23055
|
-
|
|
23052
|
+
const merged2 = mergeBarSnapshot(bars, olderBars.filter((bar) => bar.t < oldest), true);
|
|
23053
|
+
if (merged2.length > bars.length) {
|
|
23054
|
+
maintainTimeline(() => {
|
|
23055
|
+
bars = merged2;
|
|
23056
|
+
paintAll();
|
|
23057
|
+
});
|
|
23058
|
+
refreshMarks();
|
|
23059
|
+
}
|
|
23060
|
+
if (myNavigation === navigationEpoch) frameRange(chart, anchor, span, spanTf);
|
|
23056
23061
|
}).catch(() => {
|
|
23062
|
+
if (!disposed && myEpoch === epoch && myNavigation === navigationEpoch) frameRange(chart, anchor, span, spanTf);
|
|
23057
23063
|
}).finally(() => {
|
|
23058
23064
|
if (myEpoch === epoch) paging = false;
|
|
23059
23065
|
});
|
|
@@ -25952,8 +25958,9 @@ function dialogRows(input) {
|
|
|
25952
25958
|
}
|
|
25953
25959
|
return base;
|
|
25954
25960
|
}
|
|
25955
|
-
var ROW_MARK_SIZE2 =
|
|
25956
|
-
var SOURCE_MARK_SIZE =
|
|
25961
|
+
var ROW_MARK_SIZE2 = 36;
|
|
25962
|
+
var SOURCE_MARK_SIZE = 24;
|
|
25963
|
+
var SCOPE_MARK_SIZE = 18;
|
|
25957
25964
|
var picks = 0;
|
|
25958
25965
|
var PREFETCH_MARGIN = 8;
|
|
25959
25966
|
function buildSearchSurface(deps, box2, frame2) {
|
|
@@ -25970,7 +25977,6 @@ function buildSearchSurface(deps, box2, frame2) {
|
|
|
25970
25977
|
let scoped = scopeSession !== null && searchScope?.on !== false;
|
|
25971
25978
|
const session2 = () => scoped && scopeSession ? scopeSession : feedSession;
|
|
25972
25979
|
const search2 = () => session2().controller;
|
|
25973
|
-
if (mode === "search" || mode === "pick") box2.classList.add("qc-search-table");
|
|
25974
25980
|
let query = request.changeFrom ?? "";
|
|
25975
25981
|
const display = deps.display ?? {};
|
|
25976
25982
|
const spreads = display.spreads !== false;
|
|
@@ -26074,7 +26080,7 @@ function buildSearchSurface(deps, box2, frame2) {
|
|
|
26074
26080
|
}
|
|
26075
26081
|
if (searchScope) {
|
|
26076
26082
|
const mark = h("span", { class: "qc-search-scope-mark", "aria-hidden": "true" });
|
|
26077
|
-
const drop = searchScope.mark?.({ host: mark, size:
|
|
26083
|
+
const drop = searchScope.mark?.({ host: mark, size: SCOPE_MARK_SIZE });
|
|
26078
26084
|
if (typeof drop === "function") {
|
|
26079
26085
|
mark.dataset.qcHost = "true";
|
|
26080
26086
|
scopeMarkDisposer = drop;
|
|
@@ -26087,7 +26093,7 @@ function buildSearchSurface(deps, box2, frame2) {
|
|
|
26087
26093
|
const status2 = h("div", { class: "qc-search-status", role: "status", "aria-live": "polite" });
|
|
26088
26094
|
const sentinel = h("div", { class: "qc-search-sentinel qc-muted" }, t("search.loadingMore"));
|
|
26089
26095
|
sentinel.hidden = true;
|
|
26090
|
-
append(box2,
|
|
26096
|
+
append(box2, field, strip, ...narrower.map((n) => n.row), list, status2);
|
|
26091
26097
|
const serverQuery = () => spreads && looksLikeSpread(query) && !isSymbolPair(query) ? spreadSearchQuery(query) : query;
|
|
26092
26098
|
const setQuery = (next) => {
|
|
26093
26099
|
query = next;
|
|
@@ -26154,16 +26160,22 @@ function buildSearchSurface(deps, box2, frame2) {
|
|
|
26154
26160
|
markDisposers.push(dropMark);
|
|
26155
26161
|
} else mark.set(label3.ticker);
|
|
26156
26162
|
option.appendChild(mark.element);
|
|
26157
|
-
option.appendChild(
|
|
26163
|
+
option.appendChild(
|
|
26164
|
+
h(
|
|
26165
|
+
"span",
|
|
26166
|
+
{ class: "qc-search-text" },
|
|
26167
|
+
marked(label3.ticker),
|
|
26168
|
+
h("span", { class: "qc-search-line" }, h("span", { class: "qc-search-name" }, label3.description), r.type ? h("span", { class: "qc-search-kind" }, r.type) : null)
|
|
26169
|
+
)
|
|
26170
|
+
);
|
|
26158
26171
|
if (compare && entry.added) {
|
|
26159
26172
|
const mark2 = h("span", { class: "qc-search-added", title: t("search.addedMark", { symbol: label3.ticker }) });
|
|
26160
26173
|
mark2.appendChild(deps.icons.glyph(ICONS.check, { size: 18 }));
|
|
26161
26174
|
option.appendChild(mark2);
|
|
26162
26175
|
} else {
|
|
26163
26176
|
const source3 = h("span", { class: "qc-search-source" });
|
|
26164
|
-
source3.appendChild(h("span", { class: "qc-search-source-text" }, label3.source ? h("span", { class: "qc-search-source-name" }, label3.source) : null, h("span", { class: "qc-search-kind" }, r.type)));
|
|
26165
26177
|
if (label3.source) {
|
|
26166
|
-
const sourceMark = h("span", { class: "qc-search-mark", "aria-
|
|
26178
|
+
const sourceMark = h("span", { class: "qc-search-mark", role: "img", "aria-label": label3.source, title: label3.source });
|
|
26167
26179
|
const dropSource = r.exchange ? deps.painters.venue?.({ exchange: r.exchange, host: sourceMark, size: SOURCE_MARK_SIZE }) : r.dataSource ? deps.painters.dataSource?.({ dataSource: r.dataSource, host: sourceMark, size: SOURCE_MARK_SIZE }) : void 0;
|
|
26168
26180
|
if (typeof dropSource === "function") {
|
|
26169
26181
|
sourceMark.dataset.qcHost = "true";
|
|
@@ -26286,7 +26298,7 @@ function openSearchDialog(deps) {
|
|
|
26286
26298
|
deps.onClose?.(dialog);
|
|
26287
26299
|
},
|
|
26288
26300
|
build(box2, handle) {
|
|
26289
|
-
surface = buildSearchSurface(deps, box2, {
|
|
26301
|
+
surface = buildSearchSurface(deps, box2, { done: () => handle.close() });
|
|
26290
26302
|
},
|
|
26291
26303
|
initialFocus: (box2) => box2.querySelector(".qc-search-input")
|
|
26292
26304
|
});
|
|
@@ -30920,8 +30932,8 @@ function mountSymbolSearch(options2) {
|
|
|
30920
30932
|
}
|
|
30921
30933
|
},
|
|
30922
30934
|
element,
|
|
30923
|
-
// A card
|
|
30924
|
-
{
|
|
30935
|
+
// A card's done is the page's close.
|
|
30936
|
+
{ done: () => options2.onClose?.() }
|
|
30925
30937
|
);
|
|
30926
30938
|
return {
|
|
30927
30939
|
element,
|