@trdrs/quickcharts 2.2.0 → 2.3.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 +6 -0
- package/README.md +12 -0
- package/dist/chunk-GFQQSY47.js +41 -0
- package/dist/chunk-GFQQSY47.js.map +1 -0
- package/dist/feature-manifest.json +1 -1
- package/dist/format.d.ts +37 -1
- package/dist/index.d.ts +7 -219
- package/dist/index.js +3 -36
- package/dist/index.js.map +1 -1
- package/dist/{format-ConXazzy.d.ts → symbology-D3SLclrU.d.ts} +1 -34
- package/dist/symbols-BL1fD4CS.d.ts +222 -0
- package/dist/symbols.d.ts +2 -0
- package/dist/symbols.js +9 -0
- package/dist/symbols.js.map +1 -0
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @trdrs/quickcharts
|
|
2
2
|
|
|
3
|
+
## 2.3.0
|
|
4
|
+
|
|
5
|
+
The symbol naming rule for hosts that name markets in views of their own. No public name changes.
|
|
6
|
+
|
|
7
|
+
`@trdrs/quickcharts/symbols` carries the symbol naming rule on its own, free of any DOM name: `symbolNames`, with its `SymbolNames` type, and `bareTicker`, so a view of the host's own with no DOM names a market as the chart's pill, legend and search rows do.
|
|
8
|
+
|
|
3
9
|
## 2.2.0
|
|
4
10
|
|
|
5
11
|
The way back to the live edge and the plot a host control floats over, touch that follows the hand, and the formatter, the glyph lists and the icon artwork for hosts that draw their own. No public name changes.
|
package/README.md
CHANGED
|
@@ -314,6 +314,18 @@ symbolNames({ symbol: 'NASDAQ:AAPL', name: 'Apple Inc', exchange: 'NASDAQ', type
|
|
|
314
314
|
symbolNames('HYPERLIQUID:ETH').mark // 'ETH', before the symbol resolves
|
|
315
315
|
```
|
|
316
316
|
|
|
317
|
+
`@trdrs/quickcharts/symbols` carries the same rule on its own, `symbolNames` and `bareTicker`, with
|
|
318
|
+
nothing that names a window, a document or a DOM type, so a view of your own with no DOM, a native
|
|
319
|
+
search list among them, names a market exactly as the chart does. `bareTicker` is the ticker inside
|
|
320
|
+
a feed symbol, its venue prefix shed:
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
import { bareTicker, symbolNames } from '@trdrs/quickcharts/symbols'
|
|
324
|
+
|
|
325
|
+
symbolNames({ symbol: 'HYPERLIQUID:BTC', name: 'Bitcoin perpetual', exchange: 'Hyperliquid', type: 'crypto', currencyCode: 'USDC' }).title // 'BTC / USDC'
|
|
326
|
+
bareTicker('CME:ES1!') // 'ES1!'
|
|
327
|
+
```
|
|
328
|
+
|
|
317
329
|
Symbology is display truth: how the chart writes a market's prices. Execution facts, such as lot
|
|
318
330
|
size and pip value, stay with your trading integration, and its execution grid can differ from the
|
|
319
331
|
chart's display grid.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/symbolLabel.ts
|
|
2
|
+
function bareTicker(symbol) {
|
|
3
|
+
return /^[A-Za-z][A-Za-z0-9._-]*:([A-Za-z0-9][A-Za-z0-9._!]*)$/.exec(symbol)?.[1] ?? symbol;
|
|
4
|
+
}
|
|
5
|
+
var SLASH_PAIR = /^[A-Za-z][A-Za-z0-9.]*\/[A-Za-z][A-Za-z0-9.]*$/;
|
|
6
|
+
function symbolLabel(symbol) {
|
|
7
|
+
const ticker = bareTicker(symbol);
|
|
8
|
+
return SLASH_PAIR.test(ticker) ? ticker.replace("/", "") : ticker;
|
|
9
|
+
}
|
|
10
|
+
var PAIR_MARKETS = /* @__PURE__ */ new Set(["crypto", "forex"]);
|
|
11
|
+
function pairLabel(ticker, type, currencyCode) {
|
|
12
|
+
const quote = currencyCode?.trim();
|
|
13
|
+
if (!quote || !PAIR_MARKETS.has(type.toLowerCase())) return null;
|
|
14
|
+
const bare = bareTicker(ticker);
|
|
15
|
+
const base = bare.length > quote.length && bare.toUpperCase().endsWith(quote.toUpperCase()) ? bare.slice(0, -quote.length) : bare;
|
|
16
|
+
return base && base.toUpperCase() !== quote.toUpperCase() ? `${base} / ${quote}` : null;
|
|
17
|
+
}
|
|
18
|
+
function factsOf(symbol) {
|
|
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 };
|
|
21
|
+
const name = symbol.name.trim();
|
|
22
|
+
const description = symbol.description.trim();
|
|
23
|
+
return { ticker: symbol.ticker, type: symbol.type, shortName: name !== description ? name : "", longName: description, currencyCode: symbol.currencyCode };
|
|
24
|
+
}
|
|
25
|
+
function symbolNames(symbol) {
|
|
26
|
+
const facts = factsOf(symbol);
|
|
27
|
+
if (facts.type.toLowerCase() === "spread") return { mark: facts.ticker, title: facts.ticker, description: facts.ticker };
|
|
28
|
+
const bare = bareTicker(facts.ticker);
|
|
29
|
+
const pair = pairLabel(facts.ticker, facts.type, facts.currencyCode) ?? (SLASH_PAIR.test(bare) ? bare.replace("/", " / ") : null);
|
|
30
|
+
return {
|
|
31
|
+
mark: pair ? pair.replace(" / ", "") : symbolLabel(facts.ticker),
|
|
32
|
+
title: pair ?? (facts.shortName || bare),
|
|
33
|
+
description: pair ?? (facts.longName || bare)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export {
|
|
38
|
+
bareTicker,
|
|
39
|
+
symbolNames
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=chunk-GFQQSY47.js.map
|
|
@@ -0,0 +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;AAC1J,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/format.d.ts
CHANGED
|
@@ -1 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
import { P as PriceFormat } from './symbology-D3SLclrU.js';
|
|
2
|
+
export { T as TickBand } from './symbology-D3SLclrU.js';
|
|
3
|
+
|
|
4
|
+
/** How a formatted price is punctuated. A price localizes the decimal sign only, so
|
|
5
|
+
* `groupSign` defaults to '' (no thousands separator) and a host that wants grouping asks for it
|
|
6
|
+
* explicitly. */
|
|
7
|
+
interface NumericPunctuation {
|
|
8
|
+
/** What separates the whole part from the decimals. Default '.', or the locale's sign when a
|
|
9
|
+
* `locale` is given. */
|
|
10
|
+
decimalSign?: string;
|
|
11
|
+
/** What separates thousands in the whole part. Default '': a price is written ungrouped, because
|
|
12
|
+
* a grouped price is harder to compare against the axis beside it. */
|
|
13
|
+
groupSign?: string;
|
|
14
|
+
}
|
|
15
|
+
interface PriceFormatterOptions {
|
|
16
|
+
/** A BCP 47 tag used ONCE, at construction, to derive the decimal sign. Anything explicit in
|
|
17
|
+
* `numericPunctuation` wins over it. */
|
|
18
|
+
locale?: string;
|
|
19
|
+
numericPunctuation?: NumericPunctuation;
|
|
20
|
+
}
|
|
21
|
+
/** A resolved formatter for one symbol. `format` and `parse` are exact inverses over every price
|
|
22
|
+
* that lands on the symbol's own grid. */
|
|
23
|
+
interface PriceFormatter {
|
|
24
|
+
/** The price as the symbol writes it. */
|
|
25
|
+
format(price: number): string;
|
|
26
|
+
/** The number a viewer typed, or null when the text is not a price in this symbol's format. */
|
|
27
|
+
parse(text: string): number | null;
|
|
28
|
+
/** How many digits `format` writes after the decimal sign. 0 for a fractional format, which
|
|
29
|
+
* writes none; the widest band's width for a variable-tick format, so a column sized from it
|
|
30
|
+
* never has to reflow. */
|
|
31
|
+
precision(): number;
|
|
32
|
+
}
|
|
33
|
+
/** Build the formatter for one symbol's price format. The result is stateless and reusable; a host
|
|
34
|
+
* resolves a symbol once and keeps its formatter for as long as the symbol is on screen. */
|
|
35
|
+
declare function createPriceFormatter(format: PriceFormat, options?: PriceFormatterOptions): PriceFormatter;
|
|
36
|
+
|
|
37
|
+
export { type NumericPunctuation, PriceFormat, type PriceFormatter, type PriceFormatterOptions, createPriceFormatter };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,202 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { C as ChartDatafeed, F as FeedBar, S as SymbolRow, a as SearchClassNode } from './symbols-BL1fD4CS.js';
|
|
2
|
+
export { B as BarMark, b as BarsEvent, D as DatafeedConfig, c as DatafeedSearchOptions, d as FeedUnavailableError, H as HistoryPage, M as MarkColorRole, e as MarkPlacement, f as MarkShape, O as OlderPageVerdict, g as SearchPage, h as SubscribeHandlers, i as SymbolNames, T as TimescaleMark, o as olderPageVerdict, s as symbolNames } from './symbols-BL1fD4CS.js';
|
|
3
3
|
import { al as en, C as ChartMessageKey, G as GlyphSourcePort, M as MagnetMode, d as CursorMode, L as LineStyle, I as IDrawing, m as DrawingCounts, D as DrawingStyle, Y as VisibilityPreset, U as ToolPreset, V as ToolTemplate, S as SerializedDrawing, o as DrawingPreferences, l as DrawingAssetPort } from './assets-M5emOz5c.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-C0cYryO9.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-C0cYryO9.js';
|
|
6
6
|
import { LineData, UTCTimestamp, HistogramData, WhitespaceData, IChartApi, ISeriesApi, CreatePriceLineOptions, PriceLineOptions, ISeriesPrimitive, Time, PriceScaleMode, SeriesType, SeriesAttachedParameter, TickMarkType } from 'lightweight-charts';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
/** Where a bar mark sits relative to its bar. */
|
|
12
|
-
type MarkPlacement = 'above' | 'below';
|
|
13
|
-
/** The glyph a bar mark draws. */
|
|
14
|
-
type MarkShape = 'circle' | 'square' | 'arrowUp' | 'arrowDown';
|
|
15
|
-
/** One mark on a bar. */
|
|
16
|
-
interface BarMark {
|
|
17
|
-
/** Stable within one symbol and window, so a refetch replaces rather than duplicates. */
|
|
18
|
-
id: string;
|
|
19
|
-
/** Epoch SECONDS at the bar's bucket open, the same clock every bar uses. */
|
|
20
|
-
time: number;
|
|
21
|
-
color: MarkColorRole;
|
|
22
|
-
/** The letter or two the glyph carries. */
|
|
23
|
-
text?: string;
|
|
24
|
-
/** The longer words a host would show beside the mark. Carried, never drawn by the chart. */
|
|
25
|
-
label?: string;
|
|
26
|
-
shape?: MarkShape;
|
|
27
|
-
placement?: MarkPlacement;
|
|
28
|
-
}
|
|
29
|
-
/** One mark under the time scale. */
|
|
30
|
-
interface TimescaleMark {
|
|
31
|
-
id: string;
|
|
32
|
-
/** Epoch SECONDS. */
|
|
33
|
-
time: number;
|
|
34
|
-
color: MarkColorRole;
|
|
35
|
-
label?: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** One OHLCV bar on the wire: `t` = epoch SECONDS at bucket open (never milliseconds, never an
|
|
39
|
-
* update's wall time), strictly ascending within any batch, one bar per timestamp. */
|
|
40
|
-
interface FeedBar {
|
|
41
|
-
t: number;
|
|
42
|
-
o: number;
|
|
43
|
-
h: number;
|
|
44
|
-
l: number;
|
|
45
|
-
c: number;
|
|
46
|
-
v: number;
|
|
47
|
-
}
|
|
48
|
-
/** A symbol-search result row. `exchange` names the venue the market lists on. `dataSource` names
|
|
49
|
-
* where the market's data comes from, and a row names one only when that source publishes the
|
|
50
|
-
* symbol's data. The row's source cell shows the venue, or the data source for a row with none. */
|
|
51
|
-
interface SymbolRow {
|
|
52
|
-
symbol: string;
|
|
53
|
-
name: string;
|
|
54
|
-
exchange: string;
|
|
55
|
-
type: string;
|
|
56
|
-
dataSource?: string | null;
|
|
57
|
-
/** What the market is priced in, when the feed knows it here. A PAIR market writes itself as
|
|
58
|
-
* `BASE / QUOTE` wherever it is named, and a ticker alone cannot say what the quote is; a row
|
|
59
|
-
* without it keeps the name the feed sent instead. `resolve()` states the same fact for the
|
|
60
|
-
* charted symbol, so a row and the legend that follows it agree. */
|
|
61
|
-
currencyCode?: string;
|
|
62
|
-
}
|
|
63
|
-
interface SearchPage {
|
|
64
|
-
hits: SymbolRow[];
|
|
65
|
-
/** Exact: another page exists at offset + hits.length (never a guess at a page boundary). */
|
|
66
|
-
hasMore: boolean;
|
|
67
|
-
}
|
|
68
|
-
interface HistoryPage {
|
|
69
|
-
bars: FeedBar[];
|
|
70
|
-
/** True when a countBack ask found NOTHING — the "no more history, stop scrolling back" signal.
|
|
71
|
-
* Plain from/to asks never set it (an empty window can be a mid-history gap). */
|
|
72
|
-
noData: boolean;
|
|
73
|
-
/** OPTIONAL gap hint on an EMPTY page that is not the end of history: the epoch-seconds time of
|
|
74
|
-
* the closest bar older than the asked window (a market holiday between `to` and the data).
|
|
75
|
-
* A consumer may retry ONCE with `to = nextTime` to jump the gap instead of dead-ending —
|
|
76
|
-
* {@link olderPageVerdict} is that rule. Feeds without the concept simply never set it. */
|
|
77
|
-
nextTime?: number;
|
|
78
|
-
}
|
|
79
|
-
type OlderPageVerdict = {
|
|
80
|
-
kind: 'bars';
|
|
81
|
-
} | {
|
|
82
|
-
kind: 'hop';
|
|
83
|
-
to: number;
|
|
84
|
-
} | {
|
|
85
|
-
kind: 'end';
|
|
86
|
-
} | {
|
|
87
|
-
kind: 'stop';
|
|
88
|
-
};
|
|
89
|
-
/** The one scroll-back rule for an older-history page, shared by every paging consumer so the gap
|
|
90
|
-
* semantics can't drift between them:
|
|
91
|
-
* - `bars` — the page has data; prepend it (bars are never discarded, whatever flags ride along).
|
|
92
|
-
* - `hop` — empty but `nextTime` points strictly older and this ask wasn't already a hop: re-ask
|
|
93
|
-
* once anchored there (the session-gap answer). One hop per gap keeps a lying feed bounded —
|
|
94
|
-
* an honest hint names a real bar, so the hop can't come back empty.
|
|
95
|
-
* - `end` — empty, `noData`, and no hint: feed inception, the one verdict that seals scroll-back.
|
|
96
|
-
* - `stop` — every other empty page (a transient, or an unusable hint): end this flight WITHOUT
|
|
97
|
-
* sealing; the next gesture asks again. */
|
|
98
|
-
declare function olderPageVerdict(page: HistoryPage, askedTo: number, alreadyHopped: boolean): OlderPageVerdict;
|
|
99
|
-
/** Push events from a live bar subscription. A `snapshot` REPLACES the recent window (delivered on
|
|
100
|
-
* connect and on every transport reconnect — the feed's self-healing re-sync); a `bar` mutates the
|
|
101
|
-
* last bar or appends the next one (bucket-open time). */
|
|
102
|
-
type BarsEvent = {
|
|
103
|
-
kind: 'snapshot';
|
|
104
|
-
bars: FeedBar[];
|
|
105
|
-
} | {
|
|
106
|
-
kind: 'bar';
|
|
107
|
-
bar: FeedBar;
|
|
108
|
-
};
|
|
109
|
-
interface SubscribeHandlers {
|
|
110
|
-
onBars(e: BarsEvent): void;
|
|
111
|
-
/** Feed status codes: 'live' | 'no-data' | server codes ('not_entitled', 'feed_down', …). */
|
|
112
|
-
onStatus?(status: string): void;
|
|
113
|
-
}
|
|
114
|
-
/** Thrown by `history` when the backend has NO feed configured for the symbol — a TERMINAL state
|
|
115
|
-
* (the chart shows "market data unavailable" and closes the live subscription), unlike a transient
|
|
116
|
-
* fetch failure which is retried. */
|
|
117
|
-
declare class FeedUnavailableError extends Error {
|
|
118
|
-
/** The server's typed refusal (e.g. not_entitled / feed_down),
|
|
119
|
-
* when it sent one — lets the host name the actual cause instead of a generic "unavailable". */
|
|
120
|
-
readonly code: string | null;
|
|
121
|
-
constructor(message?: string,
|
|
122
|
-
/** The server's typed refusal (e.g. not_entitled / feed_down),
|
|
123
|
-
* when it sent one — lets the host name the actual cause instead of a generic "unavailable". */
|
|
124
|
-
code?: string | null);
|
|
125
|
-
}
|
|
126
|
-
/** One class in a feed's catalog that holds narrower classes: a `spot` class over its `usdc` and
|
|
127
|
-
* `usdt` quotes, say. `id` is the token the feed is searched with, as a plain string entry is, and
|
|
128
|
-
* `children` are the narrower classes, as tokens or nodes of their own. The search renders two
|
|
129
|
-
* levels, a top-level class and its children: a child's own `children` are not offered, and the
|
|
130
|
-
* child narrows by its `id` alone. */
|
|
131
|
-
interface SearchClassNode {
|
|
132
|
-
readonly id: string;
|
|
133
|
-
readonly children?: readonly (string | SearchClassNode)[];
|
|
134
|
-
}
|
|
135
|
-
/** What a feed's `search` is asked with. `cls` and `classes` say which classes to narrow to; both
|
|
136
|
-
* absent is every class. */
|
|
137
|
-
interface DatafeedSearchOptions {
|
|
138
|
-
/** One class to narrow to. When the viewer may select several classes it is set only while
|
|
139
|
-
* exactly one is selected, so a feed that reads `cls` alone still narrows a single chip. */
|
|
140
|
-
cls?: string;
|
|
141
|
-
/** Every class to narrow to, sent only when the search lets the viewer select several classes at
|
|
142
|
-
* once: a row matches when it is in any of them. A feed may ignore it and read `cls` alone. */
|
|
143
|
-
classes?: readonly string[];
|
|
144
|
-
limit?: number;
|
|
145
|
-
offset?: number;
|
|
146
|
-
}
|
|
147
|
-
/** A feed's coarse, feed-LEVEL capability declaration. Everything optional and the method itself
|
|
148
|
-
* optional: an ABSENT declaration means unconstrained, and a feed must only
|
|
149
|
-
* declare what is true — a finite `resolutions` list from a feed that serves any timeframe would
|
|
150
|
-
* be a lie the chart then enforces. Symbol-level truth (price format, resolutions, session) stays
|
|
151
|
-
* on {@link SymbolInfo}. */
|
|
152
|
-
interface DatafeedConfig {
|
|
153
|
-
/** The wire timeframe tokens this feed can serve ('1m', '4h', '1d', …). Absent = any. */
|
|
154
|
-
resolutions?: readonly string[];
|
|
155
|
-
/** Asset-class tokens the catalog carries, in the order the search offers them. An entry is a
|
|
156
|
-
* token, or a {@link SearchClassNode} whose children the search offers beneath it once it is
|
|
157
|
-
* selected. Absent = unspecified. */
|
|
158
|
-
classes?: readonly (string | SearchClassNode)[];
|
|
159
|
-
}
|
|
160
|
-
/** The datafeed a chart consumes. Implementations must follow the bar rules on {@link FeedBar} and
|
|
161
|
-
* {@link BarsEvent}; everything else (transport, caching, auth) is the implementation's business. */
|
|
162
|
-
interface ChartDatafeed {
|
|
163
|
-
/** OPTIONAL capability negotiation, read once at mount: the widget constrains itself to what the
|
|
164
|
-
* feed declares (e.g. its initial timeframe must be servable). Omit it entirely when the feed
|
|
165
|
-
* has no fixed capability set. */
|
|
166
|
-
config?(): Promise<DatafeedConfig>;
|
|
167
|
-
/** Server-side symbol search, paged. `cls` narrows to one asset class ('' / absent = all), and
|
|
168
|
-
* `classes`, when present, to any of several (see {@link DatafeedSearchOptions}). */
|
|
169
|
-
search(q: string, opts?: DatafeedSearchOptions): Promise<SearchPage>;
|
|
170
|
-
/** Resolve one symbol's metadata; null when the symbol is unknown to the feed's catalogs. */
|
|
171
|
-
resolve(symbol: string): Promise<SymbolInfo | null>;
|
|
172
|
-
/** Historical sealed bars: a [from,to] window (epoch seconds, INCLUSIVE of both ends — the chart
|
|
173
|
-
* pages with `to = oldest − 1` and never re-requests a bar it holds), or `countBack` = the LAST
|
|
174
|
-
* N bars at/before `to` (outranks `from`; the count is an obligation — reach across closures).
|
|
175
|
-
* No range = the feed's default recent window. Throws {@link FeedUnavailableError} when no feed
|
|
176
|
-
* serves the symbol. */
|
|
177
|
-
history(symbol: string, tf: string, range?: {
|
|
178
|
-
from?: number;
|
|
179
|
-
to?: number;
|
|
180
|
-
countBack?: number;
|
|
181
|
-
}): Promise<HistoryPage>;
|
|
182
|
-
/** Live bar push for one (symbol, timeframe). Returns the unsubscribe. The transport owns
|
|
183
|
-
* reconnection and re-syncs by emitting a fresh `snapshot`. */
|
|
184
|
-
subscribeBars(symbol: string, tf: string, handlers: SubscribeHandlers): () => void;
|
|
185
|
-
/** Server clock (epoch seconds) — countdown skew correction. Optional: a feed without one leaves
|
|
186
|
-
* the chart on the client clock. */
|
|
187
|
-
serverTime?(): Promise<number>;
|
|
188
|
-
/** OPTIONAL depth of history for a symbol: the epoch seconds of its earliest available bar, or
|
|
189
|
-
* null when the feed does not know. The range presets read it (a listing from last year offers
|
|
190
|
-
* no five-year range); the chart never probes for it. Omit it entirely when the feed cannot
|
|
191
|
-
* say, and every preset is offered. */
|
|
192
|
-
earliestBar?(symbol: string): Promise<number | null>;
|
|
193
|
-
/** OPTIONAL neutral bar marks over a window (epoch seconds, inclusive of both ends). A mark is a
|
|
194
|
-
* note about a moment: its color is a theme role, its words are the host's, and the chart
|
|
195
|
-
* draws it as given. Omit it entirely when the feed serves none. */
|
|
196
|
-
marks?(symbol: string, from: number, to: number, resolution: string): Promise<readonly BarMark[]>;
|
|
197
|
-
/** OPTIONAL neutral time-scale marks over the same window. */
|
|
198
|
-
timescaleMarks?(symbol: string, from: number, to: number, resolution: string): Promise<readonly TimescaleMark[]>;
|
|
199
|
-
}
|
|
7
|
+
import { D as DataStatus, S as SymbolInfo, P as PriceFormat } from './symbology-D3SLclrU.js';
|
|
8
|
+
export { a as Subsession, b as SubsessionId, T as TickBand, p as parseTickBands, t as tickBandFor } from './symbology-D3SLclrU.js';
|
|
9
|
+
import { PriceFormatter } from './format.js';
|
|
10
|
+
export { NumericPunctuation, PriceFormatterOptions, createPriceFormatter } from './format.js';
|
|
200
11
|
|
|
201
12
|
/** A feed that answers coarser grains than the one it wraps.
|
|
202
13
|
*
|
|
@@ -5459,29 +5270,6 @@ declare function openInputsEditor(container: HTMLElement, rect: {
|
|
|
5459
5270
|
* field's name and an enum's options are the manifest's own vocabulary and are not translated. */
|
|
5460
5271
|
strings?: ChartI18n): void;
|
|
5461
5272
|
|
|
5462
|
-
/** The three ways one market is written, from one rule. */
|
|
5463
|
-
interface SymbolNames {
|
|
5464
|
-
/** The compact mark a label wears at a glance: a pair closed up (`BTCUSDC`, `EURUSD`), otherwise
|
|
5465
|
-
* the bare ticker (`ES1!`, `AAPL`). A spread expression is its own mark, operators and all. */
|
|
5466
|
-
mark: string;
|
|
5467
|
-
/** The title a reading wears: a pair spaced (`BTC / USDC`), otherwise the feed's short name where
|
|
5468
|
-
* it stated one apart from the description, otherwise the bare ticker. */
|
|
5469
|
-
title: string;
|
|
5470
|
-
/** The description beside a mark: a pair spaced, otherwise the feed's long description, otherwise
|
|
5471
|
-
* the bare ticker, so a market never repeats its own mark for want of a name. */
|
|
5472
|
-
description: string;
|
|
5473
|
-
}
|
|
5474
|
-
/** How a market is named, from a resolved `SymbolInfo`, a search row, or the feed symbol alone
|
|
5475
|
-
* before either has landed.
|
|
5476
|
-
*
|
|
5477
|
-
* A pair market reads as `BTC / USDC` or `EUR / USD`, both sides in the codes the market itself
|
|
5478
|
-
* trades in, never a spelled-out currency name. The quote comes from `currencyCode`, and a ticker
|
|
5479
|
-
* written as a slash pair (`BTC/USD`) needs no currency to say so. Before a symbol resolves there
|
|
5480
|
-
* is no pair to write, so the bare ticker stands on its own rather than guessing at a quote. A
|
|
5481
|
-
* market that is not a pair keeps the feed's own words: the short name as its title, the long
|
|
5482
|
-
* description beside its mark. */
|
|
5483
|
-
declare function symbolNames(symbol: SymbolInfo | SymbolRow | string): SymbolNames;
|
|
5484
|
-
|
|
5485
5273
|
/** The `/symbols` fields this mapping reads. A server may send more; anything not listed here has
|
|
5486
5274
|
* no place in symbology. */
|
|
5487
5275
|
interface UdfSymbolResponse {
|
|
@@ -5806,4 +5594,4 @@ declare function mountTimeframePicker(options: TimeframePickerOptions & {
|
|
|
5806
5594
|
container: HTMLElement;
|
|
5807
5595
|
}): MountedTimeframePicker;
|
|
5808
5596
|
|
|
5809
|
-
export { ARRANGEMENTS, type AccessPolicy, type ActiveSubsession, type Arrangement, type AttachDrawingsOptions, BRAND_DOWN, BRAND_UP, BUILT_IN_INDICATORS, BUILT_IN_LOCALES, type
|
|
5597
|
+
export { ARRANGEMENTS, type AccessPolicy, type ActiveSubsession, type Arrangement, type AttachDrawingsOptions, BRAND_DOWN, BRAND_UP, BUILT_IN_INDICATORS, BUILT_IN_LOCALES, type BuiltInIndicator, CHART_ICON_IDS, CHART_STYLES, COLLAPSED_H, COMPARE_COLORS, type CanvasTheme, type Capabilities, ChartBody, type ChartChrome, type ChartCompareApi, type ChartCustomLocale, ChartDatafeed, type ChartDictionary, type ChartDrawingsApi, type ChartEvents, type ChartExtension, type ChartExtensionChart, type ChartExtensionCommand, type ChartExtensionContext, type ChartExtensionHandle, type ChartExtensionIcon, type ChartExtensionIconPath, type ChartExtensionMenuBuilder, type ChartExtensionMenuContext, type ChartExtensionMenuItem, type ChartExtensionPane, type ChartExtensionPriceLine, type ChartExtensionReplayState, type ChartExtensionScope, type ChartExtensionSeries, type ChartHandle, type ChartHistoryApi, type ChartI18n, type ChartI18nOptions, type ChartIconArtwork, type ChartIconContext, type ChartIconDiagnostic, type ChartIconFactory, type ChartIconFailure, type ChartIconId, type ChartIcons, type ChartLegendRow, type ChartLocale, type ChartLocaleCode, type ChartMenuAction, type ChartMenuContext, type ChartMenuIcon, type ChartMenuRow, ChartMessageKey, ChartMeta, type ChartOverrides, type ChartPaneSyncApi, type ChartPreferences, type ChartPriceFormatter, type ChartReplayApi, ChartSaveLoadAdapter, type ChartSaveLoadApi, type ChartStorage, type ChartStyleId, type ChartTimezone, type ChartTranslate, type ChartWidget, type ChartWidgetOptions, type CommandRegistry, type CommandResult, type CommandScope, type CommandSpec, type CompareDeps, type CompareEntry, type CompareHandle, type ComparePlacement, type CompareSnapshot, type CompareSymbol, type ContextMenuHandle, type CustomThemes, DEFAULT_OVERRIDES, DEFAULT_SUBSESSION, DEFAULT_TIMEZONE, type DataSourceMarkPainter, DataStatus, type DrawingApplyOutcome, DrawingAssetPort, DrawingContextKind, type DrawingDocumentApi, type DrawingDocumentPort, type DrawingDocumentRefusal, type DrawingEvent, type DrawingOwner, DrawingPreferences, type DrawingPresets, type DrawingReadOutcome, type DrawingRejection, type DrawingRejectionReason, DrawingResourceContext, DrawingsBody, type DrawingsEvents, type DrawingsHandle, DrawingsMeta, type DrawingsWorkflow, EXCHANGE_TIMEZONE, type FeatureConfig, FeedBar, type FetchLike, FillBetweenPrimitive, type FullscreenApi, type FullscreenOptions, type HistoryChange, type HistoryEventState, IMAGE_HEADER_H, type ImageApi, type ImageEvent, type ImageHeader, type ImageOptions, type ImageTextRun, type ImageTile, type IndicatorCategory, type IndicatorDefinition, type IndicatorEvent, type IndicatorFill, type IndicatorInstance, type IndicatorLevel, type IndicatorManifest, type IndicatorOverrides, type IndicatorPickerAction, type IndicatorPickerBuiltInState, type IndicatorPickerCollection, type IndicatorPickerItem, type IndicatorPickerSource, type IndicatorPlot, type IndicatorPlots, type IndicatorsApi, type IndicatorsRenderer, LAYOUT_MENU_ROWS, type LayoutApi, LayoutBody, type LayoutEvent, LayoutMeta, type LayoutOptions, type LayoutSaveLoadApi, type LayoutSyncFlags, type LegendUi, type LogicalRange, MAIN_MIN_H, MIN_BAR_SPACING, MIRRORED_ICONS, type ManifestFill, type ManifestInput, type ManifestLevel, type ManifestPlot, type ManifestRun, type MarkPainters, type MarketStatus, type MatchSegment, type MountedSymbolSearch, type MountedTimeframePicker, type OpenResource, PRICE_SCALE_MODE, type PaneOp, type PanePlan, type PaneRect, type PaneState, type PartialOverrides, type PlacedImage, type PlotArea, type PlotPoint, PriceFormat, PriceFormatter, RANGE_PRESETS, RECENT_SYMBOLS_CAP, REPLAY_SPEEDS, type RangeFrameTarget, type RangePreset, type RangeSpan, type RecentsPort, type ReplayEventState, type ReplaySpeed, type ResourceLoadOutcome, ResourceRef, type ResourceRemoveOutcome, type ResourceSaveOutcome, ResourceStore, SCALE_MODES, SCALE_MODE_OPTIONS, SCROLL_STEP_BARS, SESSION_DOT, SESSION_LABEL, SESSION_STATE_TITLE, SPREAD_OPERATORS, type SaveConflictInfo, type ScaleMode, type SearchClassFilter, SearchClassNode, type SearchController, type SearchControllerOptions, type SearchDisplayOptions, type SearchScope, type SearchState, type SelectedDrawing, type SemanticTheme, type SessionBandsPrimitive, type SessionModel, type SessionSchedule, type SessionSegment, type SessionSource, type SessionState, type SessionTimeline, type SettingsMenuUi, ShadePrimitive, type SpreadOperator, type SpreadOperatorId, type SubsessionSource, SymbolInfo, type SymbolMarkPainter, type SymbolPriceFormat, SymbolRow, type SymbolSearchCache, type SymbolSearchHandle, type SymbolSearchOptions, THEME_ROLES, TIMEFRAME_MAX, TIMEFRAME_PRESETS, TIMEFRAME_PRESET_TOKENS, TIMEFRAME_UNITS, TIMEFRAME_UNIT_NAME, TIMEFRAME_UNIT_SECONDS, TIMEZONES, TOP_BAR_SLOTS, TemplateBody, TemplateMeta, type TextEditSession, type ThemeChangeListener, type ThemeController, type ThemeControllerOptions, type ThemeDeclaration, type ThemeDiagnostic, type ThemeDiagnosticCode, type ThemeMode, type ThemeOptions, type ThemeRole, type ThemeRoleFamily, type ThemeRoleId, type ThemeRoleKind, type ThemeRootStyle, type TimeRange, type Timeframe, type TimeframeGroup, type TimeframePickerHandle, type TimeframePickerOptions, type TimeframeRestrictions, type TimeframeUnit, type TimezoneRow, type ToolbarButton, type ToolbarButtonOptions, type ToolbarButtonState, type TopBarSlot, type TopBarUi, type TouchOptions, type UdfDatafeedOptions, type UdfSymbolResponse, type UiConfig, type VenueMarkPainter, type WidgetEvents, ZOOM_FACTOR, type ZoneClock, allowedTimeframes, applyBar, applyPlotOverrides, arrangementName, arrangementOf, attachCompare, attachDrawings, attachIndicators, autoTimeframeFor, buildManifestPlots, canvasTheme, canvasToBlob, chartContextMenu, chartDictionaries, chartIconArtwork, clipToWindow, coerceChartStyle, coerceScaleMode, compareTimeframes, composeFormingBar, composeImage, createChart, createChartI18n, createSearchController, createSessionBands, createSymbolSearchCache, createThemeController, createUdfDatafeed, effectivePlotColor, exchangeTimezoneText, formatClock, formatDuration, formatTimeframe, frameRange, hasExtendedHours, imageFileName, imageHeaderRuns, imageLayoutHeaderRuns, imageTileRuns, indicatorHidden, isChartStyle, isCollapsed, isIntradayTimeframe, isSymbolPair, isTimezoneChoice, latestPlotValue, layerOverrides, looksLikeSpread, makeCrosshairTimeFormatter, makeTickMarkFormatter, manifestInputDefaults, marketStatus, marketStatusFor, marketStatusText, marketStatusTitle, matchSegments, memoryChartStorage, memoryRecents, mergeOverrides, mountContextMenu, mountSymbolSearch, mountTimeframePicker, nextSessionChange, openInputsEditor, openSymbolSearch, openTimeframePicker, overriddenManifest, parseSessionModel, parseTimeframe, pickCompareColor, placeableByWidget, planPaneOp, promoteRecent, rangeAvailable, rangePresetTip, rangeSpanSeconds, resolveDisplayTimezone, resolveInitialTf, scrolledPosition, seriesTargetOf, sessionStateAt, sessionTimeline, spreadExpression, spreadSearchQuery, subTimeframesFor, subsessionBarFilter, tfSeconds, tfToUdfResolution, timeframeAllowed, timeframeGroupUnit, timeframeLabel, timeframeOrder, timeframeSeconds, timezoneCity, timezoneLabel, timezoneListing, toolName, tzOffsetLabel, tzOffsetMinutes, udfPriceFormat, udfResolutionToTf, udfSymbolInfo, valueShaped, withFoldedHistory, zoneClock, zoomedBarSpacing };
|
package/dist/index.js
CHANGED
|
@@ -110,6 +110,9 @@ import {
|
|
|
110
110
|
ICON_CATEGORIES,
|
|
111
111
|
isEmojiGlyph
|
|
112
112
|
} from "./chunk-QYGSDD2Q.js";
|
|
113
|
+
import {
|
|
114
|
+
symbolNames
|
|
115
|
+
} from "./chunk-GFQQSY47.js";
|
|
113
116
|
|
|
114
117
|
// src/datafeed.ts
|
|
115
118
|
function olderPageVerdict(page, askedTo, alreadyHopped) {
|
|
@@ -12584,42 +12587,6 @@ function attachCompare(chart, deps) {
|
|
|
12584
12587
|
return handle;
|
|
12585
12588
|
}
|
|
12586
12589
|
|
|
12587
|
-
// src/symbolLabel.ts
|
|
12588
|
-
function bareTicker(symbol) {
|
|
12589
|
-
return /^[A-Za-z][A-Za-z0-9._-]*:([A-Za-z0-9][A-Za-z0-9._!]*)$/.exec(symbol)?.[1] ?? symbol;
|
|
12590
|
-
}
|
|
12591
|
-
var SLASH_PAIR = /^[A-Za-z][A-Za-z0-9.]*\/[A-Za-z][A-Za-z0-9.]*$/;
|
|
12592
|
-
function symbolLabel(symbol) {
|
|
12593
|
-
const ticker = bareTicker(symbol);
|
|
12594
|
-
return SLASH_PAIR.test(ticker) ? ticker.replace("/", "") : ticker;
|
|
12595
|
-
}
|
|
12596
|
-
var PAIR_MARKETS = /* @__PURE__ */ new Set(["crypto", "forex"]);
|
|
12597
|
-
function pairLabel(ticker, type, currencyCode) {
|
|
12598
|
-
const quote = currencyCode?.trim();
|
|
12599
|
-
if (!quote || !PAIR_MARKETS.has(type.toLowerCase())) return null;
|
|
12600
|
-
const bare = bareTicker(ticker);
|
|
12601
|
-
const base = bare.length > quote.length && bare.toUpperCase().endsWith(quote.toUpperCase()) ? bare.slice(0, -quote.length) : bare;
|
|
12602
|
-
return base && base.toUpperCase() !== quote.toUpperCase() ? `${base} / ${quote}` : null;
|
|
12603
|
-
}
|
|
12604
|
-
function factsOf(symbol) {
|
|
12605
|
-
if (typeof symbol === "string") return { ticker: symbol, type: "", shortName: "", longName: "", currencyCode: void 0 };
|
|
12606
|
-
if ("symbol" in symbol) return { ticker: symbol.symbol, type: symbol.type, shortName: "", longName: symbol.name.trim(), currencyCode: symbol.currencyCode };
|
|
12607
|
-
const name2 = symbol.name.trim();
|
|
12608
|
-
const description = symbol.description.trim();
|
|
12609
|
-
return { ticker: symbol.ticker, type: symbol.type, shortName: name2 !== description ? name2 : "", longName: description, currencyCode: symbol.currencyCode };
|
|
12610
|
-
}
|
|
12611
|
-
function symbolNames(symbol) {
|
|
12612
|
-
const facts = factsOf(symbol);
|
|
12613
|
-
if (facts.type.toLowerCase() === "spread") return { mark: facts.ticker, title: facts.ticker, description: facts.ticker };
|
|
12614
|
-
const bare = bareTicker(facts.ticker);
|
|
12615
|
-
const pair = pairLabel(facts.ticker, facts.type, facts.currencyCode) ?? (SLASH_PAIR.test(bare) ? bare.replace("/", " / ") : null);
|
|
12616
|
-
return {
|
|
12617
|
-
mark: pair ? pair.replace(" / ", "") : symbolLabel(facts.ticker),
|
|
12618
|
-
title: pair ?? (facts.shortName || bare),
|
|
12619
|
-
description: pair ?? (facts.longName || bare)
|
|
12620
|
-
};
|
|
12621
|
-
}
|
|
12622
|
-
|
|
12623
12590
|
// src/widget/compare.ts
|
|
12624
12591
|
var CHIP_THROTTLE_MS = 250;
|
|
12625
12592
|
function attachComparePlane(deps) {
|