@trdrs/quickcharts 2.3.0 → 3.0.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 +34 -0
- package/README.md +139 -7
- package/dist/{ar-KSXQ2USS.js → ar-HLKX6L6O.js} +2 -1
- package/dist/ar-HLKX6L6O.js.map +1 -0
- package/dist/{assets-M5emOz5c.d.ts → assets-C1VjN7DP.d.ts} +1 -0
- package/dist/{ca_ES-JG4FM55E.js → ca_ES-3ALUJ2FI.js} +2 -1
- package/dist/ca_ES-3ALUJ2FI.js.map +1 -0
- package/dist/{chunk-YR7NT5ZW.js → chunk-DBJQXHLQ.js} +8 -2
- package/dist/{chunk-YR7NT5ZW.js.map → chunk-DBJQXHLQ.js.map} +1 -1
- package/dist/{de-VSW2LHNF.js → de-GXKOZYHP.js} +2 -1
- package/dist/de-GXKOZYHP.js.map +1 -0
- package/dist/drawings.d.ts +2 -2
- package/dist/drawings.js +1 -1
- package/dist/{es-5ZXIPVOB.js → es-R7WSUWO2.js} +2 -1
- package/dist/es-R7WSUWO2.js.map +1 -0
- package/dist/feature-manifest.json +45 -1
- package/dist/{fr-4F6DAWGD.js → fr-EBUMQLPT.js} +2 -1
- package/dist/fr-EBUMQLPT.js.map +1 -0
- package/dist/{he_IL-B7PBQUEV.js → he_IL-GCAXKEWB.js} +2 -1
- package/dist/{he_IL-B7PBQUEV.js.map → he_IL-GCAXKEWB.js.map} +1 -1
- package/dist/{id_ID-CYJRMXPC.js → id_ID-6JYEEKEA.js} +2 -1
- package/dist/id_ID-6JYEEKEA.js.map +1 -0
- package/dist/index.d.ts +98 -14
- package/dist/index.js +1697 -1440
- package/dist/index.js.map +1 -1
- package/dist/{it-KTX4SG5P.js → it-IMLHI5VO.js} +2 -1
- package/dist/it-IMLHI5VO.js.map +1 -0
- package/dist/{ja-V7OURU5D.js → ja-QDEQ2EYA.js} +2 -1
- package/dist/ja-QDEQ2EYA.js.map +1 -0
- package/dist/{ko-2RNEBYVE.js → ko-MTA7BZI3.js} +2 -1
- package/dist/ko-MTA7BZI3.js.map +1 -0
- package/dist/{ms_MY-EY235E7Q.js → ms_MY-K4EAHE5J.js} +2 -1
- package/dist/ms_MY-K4EAHE5J.js.map +1 -0
- package/dist/{pl-ADNVRP55.js → pl-CIIDQ3SB.js} +2 -1
- package/dist/pl-CIIDQ3SB.js.map +1 -0
- package/dist/{pt-OL2DR3DO.js → pt-3HA2PDUN.js} +2 -1
- package/dist/pt-3HA2PDUN.js.map +1 -0
- package/dist/quickcharts.css +254 -116
- package/dist/{ru-V6YFEPAF.js → ru-2F2VGHMW.js} +2 -1
- package/dist/ru-2F2VGHMW.js.map +1 -0
- package/dist/{sv-TORXQVE7.js → sv-HCBRKFRZ.js} +2 -1
- package/dist/sv-HCBRKFRZ.js.map +1 -0
- package/dist/{symbols-BL1fD4CS.d.ts → symbols-6V22WaRX.d.ts} +1 -1
- package/dist/symbols.d.ts +1 -1
- package/dist/{th-K6SJSYSY.js → th-WWPM2QKB.js} +2 -1
- package/dist/th-WWPM2QKB.js.map +1 -0
- package/dist/theme-manifest.json +56 -2
- package/dist/{tr-4AEM66KW.js → tr-M57AMCWK.js} +2 -1
- package/dist/tr-M57AMCWK.js.map +1 -0
- package/dist/{vi-YU5XCEUU.js → vi-YJHN2OK7.js} +2 -1
- package/dist/vi-YJHN2OK7.js.map +1 -0
- package/dist/{zh-QXKRYHU5.js → zh-AIFC65OE.js} +2 -1
- package/dist/zh-AIFC65OE.js.map +1 -0
- package/dist/{zh_TW-AYPDKG4Q.js → zh_TW-2LLLW4H6.js} +2 -1
- package/dist/zh_TW-2LLLW4H6.js.map +1 -0
- package/package.json +1 -1
- package/dist/ar-KSXQ2USS.js.map +0 -1
- package/dist/ca_ES-JG4FM55E.js.map +0 -1
- package/dist/de-VSW2LHNF.js.map +0 -1
- package/dist/es-5ZXIPVOB.js.map +0 -1
- package/dist/fr-4F6DAWGD.js.map +0 -1
- package/dist/id_ID-CYJRMXPC.js.map +0 -1
- package/dist/it-KTX4SG5P.js.map +0 -1
- package/dist/ja-V7OURU5D.js.map +0 -1
- package/dist/ko-2RNEBYVE.js.map +0 -1
- package/dist/ms_MY-EY235E7Q.js.map +0 -1
- package/dist/pl-ADNVRP55.js.map +0 -1
- package/dist/pt-OL2DR3DO.js.map +0 -1
- package/dist/ru-V6YFEPAF.js.map +0 -1
- package/dist/sv-TORXQVE7.js.map +0 -1
- package/dist/th-K6SJSYSY.js.map +0 -1
- package/dist/tr-4AEM66KW.js.map +0 -1
- package/dist/vi-YU5XCEUU.js.map +0 -1
- package/dist/zh-QXKRYHU5.js.map +0 -1
- package/dist/zh_TW-AYPDKG4Q.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -82,7 +82,7 @@ import {
|
|
|
82
82
|
viewportOf,
|
|
83
83
|
visibilityPreset,
|
|
84
84
|
withAlpha
|
|
85
|
-
} from "./chunk-
|
|
85
|
+
} from "./chunk-DBJQXHLQ.js";
|
|
86
86
|
import {
|
|
87
87
|
ResourceAbortError,
|
|
88
88
|
memorySaveLoadAdapter
|
|
@@ -1267,6 +1267,9 @@ var search = {
|
|
|
1267
1267
|
// The asset-class filter strip: the chip for every class, and the strip's own name.
|
|
1268
1268
|
"search.allClasses": "All",
|
|
1269
1269
|
"search.classFilter": "Asset class",
|
|
1270
|
+
/** The scope chip's accessible name: what pressing it does. `{scope}` is the host's name for the
|
|
1271
|
+
* scope, which the chip shows; whether the limit stands is the chip's pressed state. */
|
|
1272
|
+
"search.limitToScope": "Limit search to {scope}",
|
|
1270
1273
|
// The spread operators' names, each for the arithmetic it inserts, and the strip's toggle.
|
|
1271
1274
|
"search.opDivision": "Division",
|
|
1272
1275
|
"search.opSubtraction": "Subtraction",
|
|
@@ -1904,26 +1907,26 @@ function readingDirection(i18n) {
|
|
|
1904
1907
|
return BUILT_IN_LOCALES.find((l) => l.code === i18n.locale())?.dir ?? "ltr";
|
|
1905
1908
|
}
|
|
1906
1909
|
var chartDictionaries = createDictionaryLoader(en, {
|
|
1907
|
-
de: () => import("./de-
|
|
1908
|
-
fr: () => import("./fr-
|
|
1909
|
-
es: () => import("./es-
|
|
1910
|
-
it: () => import("./it-
|
|
1911
|
-
ca_ES: () => import("./ca_ES-
|
|
1912
|
-
pl: () => import("./pl-
|
|
1913
|
-
sv: () => import("./sv-
|
|
1914
|
-
tr: () => import("./tr-
|
|
1915
|
-
ru: () => import("./ru-
|
|
1916
|
-
pt: () => import("./pt-
|
|
1917
|
-
id_ID: () => import("./id_ID-
|
|
1918
|
-
ms_MY: () => import("./ms_MY-
|
|
1919
|
-
th: () => import("./th-
|
|
1920
|
-
vi: () => import("./vi-
|
|
1921
|
-
ja: () => import("./ja-
|
|
1922
|
-
ko: () => import("./ko-
|
|
1923
|
-
zh: () => import("./zh-
|
|
1924
|
-
zh_TW: () => import("./zh_TW-
|
|
1925
|
-
ar: () => import("./ar-
|
|
1926
|
-
he_IL: () => import("./he_IL-
|
|
1910
|
+
de: () => import("./de-GXKOZYHP.js"),
|
|
1911
|
+
fr: () => import("./fr-EBUMQLPT.js"),
|
|
1912
|
+
es: () => import("./es-R7WSUWO2.js"),
|
|
1913
|
+
it: () => import("./it-IMLHI5VO.js"),
|
|
1914
|
+
ca_ES: () => import("./ca_ES-3ALUJ2FI.js"),
|
|
1915
|
+
pl: () => import("./pl-CIIDQ3SB.js"),
|
|
1916
|
+
sv: () => import("./sv-HCBRKFRZ.js"),
|
|
1917
|
+
tr: () => import("./tr-M57AMCWK.js"),
|
|
1918
|
+
ru: () => import("./ru-2F2VGHMW.js"),
|
|
1919
|
+
pt: () => import("./pt-3HA2PDUN.js"),
|
|
1920
|
+
id_ID: () => import("./id_ID-6JYEEKEA.js"),
|
|
1921
|
+
ms_MY: () => import("./ms_MY-K4EAHE5J.js"),
|
|
1922
|
+
th: () => import("./th-WWPM2QKB.js"),
|
|
1923
|
+
vi: () => import("./vi-YJHN2OK7.js"),
|
|
1924
|
+
ja: () => import("./ja-QDEQ2EYA.js"),
|
|
1925
|
+
ko: () => import("./ko-MTA7BZI3.js"),
|
|
1926
|
+
zh: () => import("./zh-AIFC65OE.js"),
|
|
1927
|
+
zh_TW: () => import("./zh_TW-2LLLW4H6.js"),
|
|
1928
|
+
ar: () => import("./ar-HLKX6L6O.js"),
|
|
1929
|
+
he_IL: () => import("./he_IL-GCAXKEWB.js")
|
|
1927
1930
|
});
|
|
1928
1931
|
var dynamic = (t) => t;
|
|
1929
1932
|
var source = null;
|
|
@@ -2060,6 +2063,10 @@ var LIGHT_THEME = {
|
|
|
2060
2063
|
"control.offHover": "#8c8c8c",
|
|
2061
2064
|
"control.offPressed": "#b8b8b8",
|
|
2062
2065
|
"control.mark": "#ffffff",
|
|
2066
|
+
"control.fieldEdge": "#dbdbdb",
|
|
2067
|
+
"control.fieldEdgeHover": "#a8a8a8",
|
|
2068
|
+
"control.fieldInvalid": "#f23645",
|
|
2069
|
+
"control.fieldFill": "#f2f2f2",
|
|
2063
2070
|
"status.positive": "#067a67",
|
|
2064
2071
|
"status.negative": "#cc2f3c",
|
|
2065
2072
|
"status.warning": "#8a5a00",
|
|
@@ -2150,6 +2157,10 @@ var DARK_THEME = {
|
|
|
2150
2157
|
"control.offHover": "#707070",
|
|
2151
2158
|
"control.offPressed": "#636363",
|
|
2152
2159
|
"control.mark": "#2e2e2e",
|
|
2160
|
+
"control.fieldEdge": "#575757",
|
|
2161
|
+
"control.fieldEdgeHover": "#707070",
|
|
2162
|
+
"control.fieldInvalid": "#f23645",
|
|
2163
|
+
"control.fieldFill": "#2e2e2e",
|
|
2153
2164
|
"status.positive": "#089981",
|
|
2154
2165
|
"status.negative": "#f7525f",
|
|
2155
2166
|
"status.warning": "#f5a623",
|
|
@@ -2272,7 +2283,7 @@ var THEME_ROLES = [
|
|
|
2272
2283
|
{ id: "chrome.surfaceRaised", family: "chrome", kind: "color", description: "The fill of a control sitting on a chrome surface, such as a button or field." },
|
|
2273
2284
|
{ id: "chrome.border", family: "chrome", kind: "color", description: "The ordinary border of a control or panel." },
|
|
2274
2285
|
{ id: "chrome.borderStrong", family: "chrome", kind: "color", description: "A border or divider that must stay visible at a glance.", contrast: [{ over: "chrome.surface", min: 3 }] },
|
|
2275
|
-
{ id: "chrome.fieldBorder", family: "chrome", kind: "color", description: "The outline of
|
|
2286
|
+
{ id: "chrome.fieldBorder", family: "chrome", kind: "color", description: "The outline of the symbol search field. The field's mark and prompt name it, so the outline is not its only sign." },
|
|
2276
2287
|
{ id: "chrome.caret", family: "chrome", kind: "color", description: "The ink of the arrow that opens a control's menu or flyout.", contrast: [{ over: "chrome.surface", min: 3 }] },
|
|
2277
2288
|
{ id: "chrome.grip", family: "chrome", kind: "color", description: "The dots of a drag handle on a floating toolbar." },
|
|
2278
2289
|
// No contrast rule: the thumb says where a list is, and the wheel, the drag and the keyboard
|
|
@@ -2323,7 +2334,7 @@ var THEME_ROLES = [
|
|
|
2323
2334
|
contrast: [{ over: "state.accent", min: 4.5 }]
|
|
2324
2335
|
},
|
|
2325
2336
|
{ id: "state.selection", family: "state", kind: "color", description: "The tint over selected content." },
|
|
2326
|
-
// ── control: switches, checkboxes, and
|
|
2337
|
+
// ── control: switches, checkboxes, radios, and fields ───────────────────────────────────────
|
|
2327
2338
|
// The emphasis fill is neutral in both modes, the strong end of the grey ramp: a control that is on,
|
|
2328
2339
|
// a chosen row, a held mode and the primary action all wear it. The mark a control carries is cut
|
|
2329
2340
|
// from the surface end of the ramp.
|
|
@@ -2353,6 +2364,24 @@ var THEME_ROLES = [
|
|
|
2353
2364
|
{ over: "control.onPressed", min: 3 }
|
|
2354
2365
|
]
|
|
2355
2366
|
},
|
|
2367
|
+
// A field is a box of its own: a text field, a select, a number field or a color well. Its edge
|
|
2368
|
+
// declares no contrast rule, as `chrome.fieldBorder` declares none: the field's label names it, so
|
|
2369
|
+
// the edge is not what identifies it. The invalid edge is how a refused value shows, so it reads
|
|
2370
|
+
// as a non-text indicator on both surfaces a field stands on. The ring a focused field wears is
|
|
2371
|
+
// `state.focusRing`.
|
|
2372
|
+
{ id: "control.fieldEdge", family: "control", kind: "color", description: "The edge of a text field, a select, a number field or a color well at rest." },
|
|
2373
|
+
{ id: "control.fieldEdgeHover", family: "control", kind: "color", description: "The edge of a field under the pointer." },
|
|
2374
|
+
{
|
|
2375
|
+
id: "control.fieldInvalid",
|
|
2376
|
+
family: "control",
|
|
2377
|
+
kind: "color",
|
|
2378
|
+
description: "The edge and the focus ring of a field holding a value it refuses.",
|
|
2379
|
+
contrast: [
|
|
2380
|
+
{ over: "overlay.surface", min: 3 },
|
|
2381
|
+
{ over: "chrome.surface", min: 3 }
|
|
2382
|
+
]
|
|
2383
|
+
},
|
|
2384
|
+
{ id: "control.fieldFill", family: "control", kind: "color", description: "The fill of a field that is read-only or disabled." },
|
|
2356
2385
|
// ── status: feedback, including market session status ───────────────────────────────────────
|
|
2357
2386
|
{ id: "status.positive", family: "status", kind: "color", description: "A positive value or a successful outcome in chart chrome.", contrast: [{ over: "chrome.surface", min: 4.5 }] },
|
|
2358
2387
|
{ id: "status.negative", family: "status", kind: "color", description: "A negative value or a failed outcome in chart chrome.", contrast: [{ over: "chrome.surface", min: 4.5 }] },
|
|
@@ -2935,6 +2964,44 @@ function searchSession(datafeed, options, cache, onDispose) {
|
|
|
2935
2964
|
inflight.set(k, ask);
|
|
2936
2965
|
return ask;
|
|
2937
2966
|
};
|
|
2967
|
+
const searchFor = (query, asked, immediate) => {
|
|
2968
|
+
if (disposed) return;
|
|
2969
|
+
const cls = settleFilter(asked);
|
|
2970
|
+
clearTimeout(timer);
|
|
2971
|
+
const nextKey = keyOf(query, cls, pageSize);
|
|
2972
|
+
const unchanged = key === nextKey;
|
|
2973
|
+
if (!unchanged) {
|
|
2974
|
+
cancelPending();
|
|
2975
|
+
}
|
|
2976
|
+
key = nextKey;
|
|
2977
|
+
filter = cls;
|
|
2978
|
+
const mine = key;
|
|
2979
|
+
const epoch = generation;
|
|
2980
|
+
const retained = cache.get(key);
|
|
2981
|
+
const cached = unchanged && current ? current : retained;
|
|
2982
|
+
current = cached;
|
|
2983
|
+
if (cached) {
|
|
2984
|
+
emit({ query, ...classState(cls), hits: cached.hits, hasMore: cached.hasMore, loading: false, failed: false });
|
|
2985
|
+
if (cached.pages > 1) return;
|
|
2986
|
+
} else {
|
|
2987
|
+
emit({ query, ...classState(cls), loading: true, failed: false });
|
|
2988
|
+
}
|
|
2989
|
+
if (disposed || generation !== epoch || key !== mine) return;
|
|
2990
|
+
const run = () => {
|
|
2991
|
+
if (disposed || generation !== epoch || key !== mine) return;
|
|
2992
|
+
load(mine, query, cls).then((loaded) => {
|
|
2993
|
+
if (disposed || generation !== epoch || key !== mine) return;
|
|
2994
|
+
current = current && current.pages > loaded.pages ? current : loaded;
|
|
2995
|
+
emit({ hits: current.hits, hasMore: current.hasMore, loading: false, failed: false });
|
|
2996
|
+
}).catch(() => {
|
|
2997
|
+
if (disposed || generation !== epoch || key !== mine) return;
|
|
2998
|
+
if (current) emit({ loading: false });
|
|
2999
|
+
else emit({ hits: [], hasMore: false, loading: false, failed: true });
|
|
3000
|
+
});
|
|
3001
|
+
};
|
|
3002
|
+
if (immediate || inflight.has(mine)) run();
|
|
3003
|
+
else timer = setTimeout(run, debounceMs);
|
|
3004
|
+
};
|
|
2938
3005
|
const controller = {
|
|
2939
3006
|
state: () => state,
|
|
2940
3007
|
subscribe(listener) {
|
|
@@ -2946,42 +3013,7 @@ function searchSession(datafeed, options, cache, onDispose) {
|
|
|
2946
3013
|
};
|
|
2947
3014
|
},
|
|
2948
3015
|
search(query, asked = "") {
|
|
2949
|
-
|
|
2950
|
-
const cls = settleFilter(asked);
|
|
2951
|
-
clearTimeout(timer);
|
|
2952
|
-
const nextKey = keyOf(query, cls, pageSize);
|
|
2953
|
-
const unchanged = key === nextKey;
|
|
2954
|
-
if (!unchanged) {
|
|
2955
|
-
cancelPending();
|
|
2956
|
-
}
|
|
2957
|
-
key = nextKey;
|
|
2958
|
-
filter = cls;
|
|
2959
|
-
const mine = key;
|
|
2960
|
-
const epoch = generation;
|
|
2961
|
-
const retained = cache.get(key);
|
|
2962
|
-
const cached = unchanged && current ? current : retained;
|
|
2963
|
-
current = cached;
|
|
2964
|
-
if (cached) {
|
|
2965
|
-
emit({ query, ...classState(cls), hits: cached.hits, hasMore: cached.hasMore, loading: false, failed: false });
|
|
2966
|
-
if (cached.pages > 1) return;
|
|
2967
|
-
} else {
|
|
2968
|
-
emit({ query, ...classState(cls), loading: true, failed: false });
|
|
2969
|
-
}
|
|
2970
|
-
if (disposed || generation !== epoch || key !== mine) return;
|
|
2971
|
-
const run = () => {
|
|
2972
|
-
if (disposed || generation !== epoch || key !== mine) return;
|
|
2973
|
-
load(mine, query, cls).then((loaded) => {
|
|
2974
|
-
if (disposed || generation !== epoch || key !== mine) return;
|
|
2975
|
-
current = current && current.pages > loaded.pages ? current : loaded;
|
|
2976
|
-
emit({ hits: current.hits, hasMore: current.hasMore, loading: false, failed: false });
|
|
2977
|
-
}).catch(() => {
|
|
2978
|
-
if (disposed || generation !== epoch || key !== mine) return;
|
|
2979
|
-
if (current) emit({ loading: false });
|
|
2980
|
-
else emit({ hits: [], hasMore: false, loading: false, failed: true });
|
|
2981
|
-
});
|
|
2982
|
-
};
|
|
2983
|
-
if (inflight.has(mine)) run();
|
|
2984
|
-
else timer = setTimeout(run, debounceMs);
|
|
3016
|
+
searchFor(query, asked, false);
|
|
2985
3017
|
},
|
|
2986
3018
|
loadMore() {
|
|
2987
3019
|
if (disposed || state.loading) return;
|
|
@@ -3022,7 +3054,11 @@ function searchSession(datafeed, options, cache, onDispose) {
|
|
|
3022
3054
|
onDispose();
|
|
3023
3055
|
}
|
|
3024
3056
|
};
|
|
3025
|
-
|
|
3057
|
+
const over = (source3) => {
|
|
3058
|
+
const own = completedCache();
|
|
3059
|
+
return searchSession(source3, options, own, () => own.clear());
|
|
3060
|
+
};
|
|
3061
|
+
return { controller, cancelPending, searchNow: (query, asked = "") => searchFor(query, asked, true), over };
|
|
3026
3062
|
}
|
|
3027
3063
|
var RECENT_SYMBOLS_CAP = 10;
|
|
3028
3064
|
function promoteRecent(list, pick, cap = RECENT_SYMBOLS_CAP) {
|
|
@@ -3082,7 +3118,8 @@ var FEATURE_KEYS = {
|
|
|
3082
3118
|
replay: "flag",
|
|
3083
3119
|
history: "flag",
|
|
3084
3120
|
sessions: "flag",
|
|
3085
|
-
crosshair: "flag"
|
|
3121
|
+
crosshair: "flag",
|
|
3122
|
+
navigation: "flag"
|
|
3086
3123
|
};
|
|
3087
3124
|
var TOP_BAR_KEYS = {
|
|
3088
3125
|
symbol: "flag",
|
|
@@ -3111,7 +3148,9 @@ var UI_KEYS = {
|
|
|
3111
3148
|
toasts: "flag",
|
|
3112
3149
|
symbolSearch: "flag",
|
|
3113
3150
|
indicatorPicker: "flag",
|
|
3114
|
-
indicatorSettings: "flag"
|
|
3151
|
+
indicatorSettings: "flag",
|
|
3152
|
+
priceScale: "flag",
|
|
3153
|
+
crosshair: { horizontal: "flag", labels: "flag", solid: "flag" }
|
|
3115
3154
|
};
|
|
3116
3155
|
function checkKeys(path, value, keys) {
|
|
3117
3156
|
if (value === void 0) return;
|
|
@@ -3139,7 +3178,8 @@ function resolveFeatures(config) {
|
|
|
3139
3178
|
replay: on(config?.replay),
|
|
3140
3179
|
history: on(config?.history),
|
|
3141
3180
|
sessions: on(config?.sessions),
|
|
3142
|
-
crosshair: on(config?.crosshair)
|
|
3181
|
+
crosshair: on(config?.crosshair),
|
|
3182
|
+
navigation: on(config?.navigation)
|
|
3143
3183
|
};
|
|
3144
3184
|
}
|
|
3145
3185
|
var shown = (value) => value !== false;
|
|
@@ -3155,6 +3195,9 @@ function resolveUi(config, features, offered = {}) {
|
|
|
3155
3195
|
const inLegend = (key) => legend2 && (typeof legendConfig !== "object" || shown(legendConfig[key]));
|
|
3156
3196
|
const symbolSearch = shown(config?.symbolSearch);
|
|
3157
3197
|
const indicatorPicker = shown(config?.indicatorPicker);
|
|
3198
|
+
const crosshairConfig = config?.crosshair;
|
|
3199
|
+
const crosshair = features.crosshair && shown(crosshairConfig);
|
|
3200
|
+
const inCrosshair = (key) => crosshair && (typeof crosshairConfig !== "object" || shown(crosshairConfig[key]));
|
|
3158
3201
|
return {
|
|
3159
3202
|
topBar,
|
|
3160
3203
|
symbolPill: inBar("symbol") && symbolSearch,
|
|
@@ -3178,13 +3221,19 @@ function resolveUi(config, features, offered = {}) {
|
|
|
3178
3221
|
legend: legend2,
|
|
3179
3222
|
legendValues: inLegend("values"),
|
|
3180
3223
|
marketStatus: inLegend("marketStatus"),
|
|
3181
|
-
navigation: shown(config?.navigation),
|
|
3224
|
+
navigation: features.navigation && shown(config?.navigation),
|
|
3182
3225
|
contextMenu: shown(config?.contextMenu),
|
|
3183
3226
|
replayTransport: features.replay && shown(config?.replayTransport),
|
|
3184
3227
|
toasts: shown(config?.toasts),
|
|
3185
3228
|
symbolSearch,
|
|
3186
3229
|
indicatorPicker,
|
|
3187
|
-
indicatorSettings: shown(config?.indicatorSettings)
|
|
3230
|
+
indicatorSettings: shown(config?.indicatorSettings),
|
|
3231
|
+
priceScale: shown(config?.priceScale),
|
|
3232
|
+
crosshair,
|
|
3233
|
+
crosshairHorizontal: inCrosshair("horizontal"),
|
|
3234
|
+
crosshairLabels: inCrosshair("labels"),
|
|
3235
|
+
// Solid is the one part that is off unless named: a crosshair is dashed by default.
|
|
3236
|
+
crosshairSolid: crosshair && typeof crosshairConfig === "object" && crosshairConfig.solid === true
|
|
3188
3237
|
};
|
|
3189
3238
|
}
|
|
3190
3239
|
function canCopyImage() {
|
|
@@ -3313,6 +3362,29 @@ function styleOptions(style, paint) {
|
|
|
3313
3362
|
return candleOptions(paint);
|
|
3314
3363
|
}
|
|
3315
3364
|
}
|
|
3365
|
+
function fadedStyleOptions(style, paint, alpha) {
|
|
3366
|
+
const a = Math.min(1, Math.max(0, alpha));
|
|
3367
|
+
const up = paint.appearance.upColor;
|
|
3368
|
+
const down = paint.appearance.downColor;
|
|
3369
|
+
switch (style) {
|
|
3370
|
+
case "line":
|
|
3371
|
+
case "stepline":
|
|
3372
|
+
return { color: withAlpha2(paint.canvas.neutral, a) };
|
|
3373
|
+
case "area":
|
|
3374
|
+
return { lineColor: withAlpha2(up, a), topColor: withAlpha2(up, 0.28 * a), bottomColor: withAlpha2(up, 0.04 * a) };
|
|
3375
|
+
case "baseline":
|
|
3376
|
+
return {
|
|
3377
|
+
topLineColor: withAlpha2(up, a),
|
|
3378
|
+
bottomLineColor: withAlpha2(down, a),
|
|
3379
|
+
topFillColor1: withAlpha2(up, 0.28 * a),
|
|
3380
|
+
topFillColor2: withAlpha2(up, 0.04 * a),
|
|
3381
|
+
bottomFillColor1: withAlpha2(down, 0.04 * a),
|
|
3382
|
+
bottomFillColor2: withAlpha2(down, 0.28 * a)
|
|
3383
|
+
};
|
|
3384
|
+
default:
|
|
3385
|
+
return styleOptions(style, paint);
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3316
3388
|
function lineOptions(paint) {
|
|
3317
3389
|
return { color: paint.canvas.neutral, lineWidth: 2 };
|
|
3318
3390
|
}
|
|
@@ -4963,6 +5035,7 @@ import {
|
|
|
4963
5035
|
createChart as createRenderer,
|
|
4964
5036
|
HistogramSeries as HistogramSeries2,
|
|
4965
5037
|
LineSeries as LineSeries4,
|
|
5038
|
+
LineStyle as LineStyle3,
|
|
4966
5039
|
TrackingModeExitMode
|
|
4967
5040
|
} from "lightweight-charts";
|
|
4968
5041
|
|
|
@@ -5017,6 +5090,59 @@ function coerceScaleMode(raw) {
|
|
|
5017
5090
|
return SCALE_MODES.includes(raw ?? "") ? raw : "normal";
|
|
5018
5091
|
}
|
|
5019
5092
|
|
|
5093
|
+
// src/widget/styleMorph.ts
|
|
5094
|
+
var STYLE_MORPH_MS = 500;
|
|
5095
|
+
function morphEase(t) {
|
|
5096
|
+
const clamped = Math.min(1, Math.max(0, t));
|
|
5097
|
+
return (1 - Math.cos(Math.PI * clamped)) / 2;
|
|
5098
|
+
}
|
|
5099
|
+
function foldBar(bar, fold) {
|
|
5100
|
+
const keep = 1 - Math.min(1, Math.max(0, fold));
|
|
5101
|
+
return {
|
|
5102
|
+
time: bar.t,
|
|
5103
|
+
open: bar.c + (bar.o - bar.c) * keep,
|
|
5104
|
+
high: bar.c + (bar.h - bar.c) * keep,
|
|
5105
|
+
low: bar.c + (bar.l - bar.c) * keep,
|
|
5106
|
+
close: bar.c
|
|
5107
|
+
};
|
|
5108
|
+
}
|
|
5109
|
+
function startStyleMorph(deps) {
|
|
5110
|
+
const frame = deps.frame ?? ((tick2) => requestAnimationFrame(tick2));
|
|
5111
|
+
const cancel = deps.cancelFrame ?? ((handle2) => cancelAnimationFrame(handle2));
|
|
5112
|
+
const now = deps.now ?? (() => performance.now());
|
|
5113
|
+
const start = now();
|
|
5114
|
+
let handle = null;
|
|
5115
|
+
let ended = false;
|
|
5116
|
+
const draw = (t) => {
|
|
5117
|
+
const p = morphEase(t);
|
|
5118
|
+
const fold = deps.direction === "fold" ? p : 1 - p;
|
|
5119
|
+
deps.bars.setData(deps.shown().map((bar) => foldBar(bar, fold)));
|
|
5120
|
+
deps.fadeLine(fold);
|
|
5121
|
+
};
|
|
5122
|
+
const finish = () => {
|
|
5123
|
+
if (ended) return;
|
|
5124
|
+
ended = true;
|
|
5125
|
+
if (handle !== null) cancel(handle);
|
|
5126
|
+
handle = null;
|
|
5127
|
+
draw(1);
|
|
5128
|
+
deps.done();
|
|
5129
|
+
};
|
|
5130
|
+
const tick = () => {
|
|
5131
|
+
handle = null;
|
|
5132
|
+
if (ended) return;
|
|
5133
|
+
const t = (now() - start) / STYLE_MORPH_MS;
|
|
5134
|
+
if (t >= 1) {
|
|
5135
|
+
finish();
|
|
5136
|
+
return;
|
|
5137
|
+
}
|
|
5138
|
+
draw(t);
|
|
5139
|
+
handle = frame(tick);
|
|
5140
|
+
};
|
|
5141
|
+
draw(0);
|
|
5142
|
+
handle = frame(tick);
|
|
5143
|
+
return { running: () => !ended, finish };
|
|
5144
|
+
}
|
|
5145
|
+
|
|
5020
5146
|
// src/widget/baselineLevel.ts
|
|
5021
5147
|
var BASELINE_SCREEN_PERCENT = 50;
|
|
5022
5148
|
var BASELINE_DRIFT_PX = 0.5;
|
|
@@ -5710,8 +5836,8 @@ function bundledGlyphSource(glyph2) {
|
|
|
5710
5836
|
}
|
|
5711
5837
|
|
|
5712
5838
|
// src/pointerInput.ts
|
|
5713
|
-
function pointerLock(locked) {
|
|
5714
|
-
const on = !locked;
|
|
5839
|
+
function pointerLock(locked, navigable = true) {
|
|
5840
|
+
const on = !locked && navigable;
|
|
5715
5841
|
return {
|
|
5716
5842
|
handleScroll: on,
|
|
5717
5843
|
handleScale: { mouseWheel: on, pinch: false, axisPressedMouseMove: on, axisDoubleClickReset: on },
|
|
@@ -6825,7 +6951,7 @@ function attachDrawings(options) {
|
|
|
6825
6951
|
const locked = () => allLocked || workflow().allLocked === true;
|
|
6826
6952
|
const changed = () => events.onChange?.();
|
|
6827
6953
|
const lockPointer = (locked2) => {
|
|
6828
|
-
const lock = pointerLock(locked2);
|
|
6954
|
+
const lock = pointerLock(locked2, options.navigable ?? true);
|
|
6829
6955
|
chart.applyOptions({ handleScroll: lock.handleScroll, handleScale: lock.handleScale });
|
|
6830
6956
|
container.style.touchAction = lock.touchAction;
|
|
6831
6957
|
};
|
|
@@ -7485,6 +7611,21 @@ function refreshOverlays(within) {
|
|
|
7485
7611
|
}
|
|
7486
7612
|
}
|
|
7487
7613
|
|
|
7614
|
+
// src/ui/controls/select.ts
|
|
7615
|
+
function selectChevron(icons) {
|
|
7616
|
+
const slot = document.createElement("span");
|
|
7617
|
+
slot.className = "qc-select-chevron";
|
|
7618
|
+
slot.setAttribute("aria-hidden", "true");
|
|
7619
|
+
slot.appendChild(icons.icon("chevronDown18", 18));
|
|
7620
|
+
return slot;
|
|
7621
|
+
}
|
|
7622
|
+
function selectField(select, icons) {
|
|
7623
|
+
const box = document.createElement("span");
|
|
7624
|
+
box.className = "qc-select";
|
|
7625
|
+
box.append(select, selectChevron(icons));
|
|
7626
|
+
return box;
|
|
7627
|
+
}
|
|
7628
|
+
|
|
7488
7629
|
// src/ui/drawings/fields.ts
|
|
7489
7630
|
function row(label2, ...controls) {
|
|
7490
7631
|
const cell2 = el("div", { class: "qc-drawing-row-controls" }, ...controls);
|
|
@@ -7503,12 +7644,12 @@ function checkbox(label2, value, onChange) {
|
|
|
7503
7644
|
input.addEventListener("change", () => onChange(input.checked));
|
|
7504
7645
|
return input;
|
|
7505
7646
|
}
|
|
7506
|
-
function dropdown(label2, options, value, labels, onChange) {
|
|
7647
|
+
function dropdown(icons, label2, options, value, labels, onChange) {
|
|
7507
7648
|
const select = el("select", { class: "qc-field qc-drawing-select", "aria-label": label2 });
|
|
7508
7649
|
for (const option of options) select.appendChild(el("option", { value: option, text: labels(option) }));
|
|
7509
7650
|
select.value = value;
|
|
7510
7651
|
select.addEventListener("change", () => onChange(select.value));
|
|
7511
|
-
return select;
|
|
7652
|
+
return selectField(select, icons);
|
|
7512
7653
|
}
|
|
7513
7654
|
function numberInput(t, icons, props) {
|
|
7514
7655
|
const input = el("input", { type: "number", class: "qc-field qc-drawing-number", "aria-label": props.label });
|
|
@@ -7660,6 +7801,7 @@ function strokeRows(t, content, options) {
|
|
|
7660
7801
|
function lineEndButton(t, icons, box, side, value, onChange) {
|
|
7661
7802
|
const face = (v) => icons.icon(v === "normal" ? "lineEndNormal" : "lineEndArrow");
|
|
7662
7803
|
const b = button({ class: "qc-field qc-drawing-line-end", label: t(side === "left" ? "drawing.leftEnd" : "drawing.rightEnd"), icon: face(value) });
|
|
7804
|
+
b.appendChild(selectChevron(icons));
|
|
7663
7805
|
b.dataset.qcEnd = side;
|
|
7664
7806
|
b.setAttribute("aria-haspopup", "listbox");
|
|
7665
7807
|
b.setAttribute("aria-expanded", "false");
|
|
@@ -8941,7 +9083,7 @@ function openNameDialog(options) {
|
|
|
8941
9083
|
append(
|
|
8942
9084
|
box,
|
|
8943
9085
|
...promptHead(t, options.icons, options.title, () => dialog.close()),
|
|
8944
|
-
h("label", { class: "qc-name-field" }, h("span", { class: "qc-name-label" }, options.label), h("span", { class: "qc-name-box" }, field)),
|
|
9086
|
+
h("label", { class: "qc-name-field" }, h("span", { class: "qc-name-label" }, options.label), h("span", { class: "qc-field qc-name-box" }, field)),
|
|
8945
9087
|
h("div", { class: "qc-prompt-actions" }, button2({ label: t("layouts.cancel"), text: t("layouts.cancel"), className: "qc-button--secondary", onClick: () => dialog.close() }), verb)
|
|
8946
9088
|
);
|
|
8947
9089
|
},
|
|
@@ -9530,29 +9672,30 @@ function mountTextEditor(session2, deps) {
|
|
|
9530
9672
|
|
|
9531
9673
|
// src/ui/drawings/dialog.ts
|
|
9532
9674
|
function dragBy(header, box) {
|
|
9533
|
-
let
|
|
9675
|
+
let stop = null;
|
|
9534
9676
|
header.addEventListener("pointerdown", (event) => {
|
|
9535
9677
|
if (event.target.closest("button")) return;
|
|
9678
|
+
stop?.();
|
|
9536
9679
|
const rect = box.getBoundingClientRect();
|
|
9537
|
-
|
|
9680
|
+
const dx = event.clientX - rect.left;
|
|
9681
|
+
const dy = event.clientY - rect.top;
|
|
9682
|
+
stop = dragUntilRelease(
|
|
9683
|
+
(move) => {
|
|
9684
|
+
const x = Math.max(0, Math.min(move.clientX - dx, window.innerWidth - box.offsetWidth));
|
|
9685
|
+
const y = Math.max(0, Math.min(move.clientY - dy, window.innerHeight - box.offsetHeight));
|
|
9686
|
+
box.style.position = "fixed";
|
|
9687
|
+
box.style.left = `${Math.round(x)}px`;
|
|
9688
|
+
box.style.top = `${Math.round(y)}px`;
|
|
9689
|
+
},
|
|
9690
|
+
() => {
|
|
9691
|
+
stop = null;
|
|
9692
|
+
}
|
|
9693
|
+
);
|
|
9538
9694
|
event.preventDefault();
|
|
9539
9695
|
});
|
|
9540
|
-
const onMove = (event) => {
|
|
9541
|
-
if (!dragging) return;
|
|
9542
|
-
const x = Math.max(0, Math.min(event.clientX - dragging.dx, window.innerWidth - box.offsetWidth));
|
|
9543
|
-
const y = Math.max(0, Math.min(event.clientY - dragging.dy, window.innerHeight - box.offsetHeight));
|
|
9544
|
-
box.style.position = "fixed";
|
|
9545
|
-
box.style.left = `${Math.round(x)}px`;
|
|
9546
|
-
box.style.top = `${Math.round(y)}px`;
|
|
9547
|
-
};
|
|
9548
|
-
const onUp = () => {
|
|
9549
|
-
dragging = null;
|
|
9550
|
-
};
|
|
9551
|
-
window.addEventListener("pointermove", onMove);
|
|
9552
|
-
window.addEventListener("pointerup", onUp);
|
|
9553
9696
|
return () => {
|
|
9554
|
-
|
|
9555
|
-
|
|
9697
|
+
stop?.();
|
|
9698
|
+
stop = null;
|
|
9556
9699
|
};
|
|
9557
9700
|
}
|
|
9558
9701
|
function openDialog2(options) {
|
|
@@ -9771,7 +9914,7 @@ function styleRows(ctx) {
|
|
|
9771
9914
|
const inertKeys = new Set(INERT_PROPS[type] ?? []);
|
|
9772
9915
|
const sect = (key) => key in props && !inertKeys.has(key) && (inputKeys.has(key) ? tab === "Inputs" : tab === "Style");
|
|
9773
9916
|
const out = [];
|
|
9774
|
-
const fontSize = () => dropdown(t("drawing.fontSize"), FONT_SIZES2, String(style.fontSize), (v) => v, (v) => ctx.patchStyle({ fontSize: Number(v) }));
|
|
9917
|
+
const fontSize = () => dropdown(ctx.icons, t("drawing.fontSize"), FONT_SIZES2, String(style.fontSize), (v) => v, (v) => ctx.patchStyle({ fontSize: Number(v) }));
|
|
9775
9918
|
const toggle = (key, text2) => {
|
|
9776
9919
|
if (sect(key)) out.push(toggleRow(t(text2), !!props[key], (v) => ctx.patchProps({ [key]: v })));
|
|
9777
9920
|
};
|
|
@@ -9802,7 +9945,7 @@ function styleRows(ctx) {
|
|
|
9802
9945
|
}
|
|
9803
9946
|
if ("extendLeft" in props && sect("extendLeft")) {
|
|
9804
9947
|
const value = props.extendLeft && props.extendRight ? "Both" : props.extendLeft ? "Left" : props.extendRight ? "Right" : "None";
|
|
9805
|
-
out.push(row(t("drawing.extend"), dropdown(t("drawing.extend"), ["None", "Left", "Right", "Both"], value, label(t, EXTEND_LABEL), (v) => ctx.patchProps({ extendLeft: v === "Left" || v === "Both", extendRight: v === "Right" || v === "Both" }))));
|
|
9948
|
+
out.push(row(t("drawing.extend"), dropdown(ctx.icons, t("drawing.extend"), ["None", "Left", "Right", "Both"], value, label(t, EXTEND_LABEL), (v) => ctx.patchProps({ extendLeft: v === "Left" || v === "Both", extendRight: v === "Right" || v === "Both" }))));
|
|
9806
9949
|
}
|
|
9807
9950
|
toggle("middlePoint", "drawing.middlePoint");
|
|
9808
9951
|
toggle("showPriceLabels", "drawing.priceLabels");
|
|
@@ -9810,7 +9953,7 @@ function styleRows(ctx) {
|
|
|
9810
9953
|
toggle("showTime", "drawing.timeLabel");
|
|
9811
9954
|
toggle("middleLine", "drawing.middleLine");
|
|
9812
9955
|
if (sect("variant")) {
|
|
9813
|
-
out.push(row(t("drawing.rowStyle"), dropdown(t("drawing.rowStyle"), ["original", "schiff", "modified_schiff", "inside"], props.variant, label(t, VARIANT_LABEL), (v) => ctx.patchProps({ variant: v }))));
|
|
9956
|
+
out.push(row(t("drawing.rowStyle"), dropdown(ctx.icons, t("drawing.rowStyle"), ["original", "schiff", "modified_schiff", "inside"], props.variant, label(t, VARIANT_LABEL), (v) => ctx.patchProps({ variant: v }))));
|
|
9814
9957
|
}
|
|
9815
9958
|
if (sect("showPriceDelta")) {
|
|
9816
9959
|
out.push(el("div", { class: "qc-dialog-heading", text: t("drawing.sectionStats") }));
|
|
@@ -9834,10 +9977,10 @@ function styleRows(ctx) {
|
|
|
9834
9977
|
toggleRow(t("drawing.barsRange"), !!props.showBarsRange, (v) => ctx.patchProps({ showBarsRange: v })),
|
|
9835
9978
|
toggleRow(t("drawing.dateTimeRange"), !!props.showDateTimeRange, (v) => ctx.patchProps({ showDateTimeRange: v })),
|
|
9836
9979
|
toggleRow(t("drawing.angle"), !!props.showAngle, (v) => ctx.patchProps({ showAngle: v })),
|
|
9837
|
-
row(t("drawing.statsPosition"), dropdown(t("drawing.statsPosition"), ["left", "center", "right"], props.statsPosition, label(t, SIDE_LABEL), (v) => ctx.patchProps({ statsPosition: v })))
|
|
9980
|
+
row(t("drawing.statsPosition"), dropdown(ctx.icons, t("drawing.statsPosition"), ["left", "center", "right"], props.statsPosition, label(t, SIDE_LABEL), (v) => ctx.patchProps({ statsPosition: v })))
|
|
9838
9981
|
);
|
|
9839
9982
|
}
|
|
9840
|
-
if (sect("direction")) out.push(row(t("drawing.direction"), dropdown(t("drawing.direction"), ["up", "down"], props.direction, label(t, UPDOWN_LABEL), (v) => ctx.patchProps({ direction: v }))));
|
|
9983
|
+
if (sect("direction")) out.push(row(t("drawing.direction"), dropdown(ctx.icons, t("drawing.direction"), ["up", "down"], props.direction, label(t, UPDOWN_LABEL), (v) => ctx.patchProps({ direction: v }))));
|
|
9841
9984
|
toggle("showPrices", "drawing.prices");
|
|
9842
9985
|
toggle("showLevels", "drawing.levels");
|
|
9843
9986
|
toggle("reverse", "drawing.reverse");
|
|
@@ -9886,9 +10029,9 @@ function styleRows(ctx) {
|
|
|
9886
10029
|
if (sect("url")) out.push(row(t("drawing.link"), textField(String(props.url ?? ""), t("drawing.link"), (v) => ctx.patchQuiet({ url: v }), { wide: true })));
|
|
9887
10030
|
if (sect("rowsLayout")) {
|
|
9888
10031
|
out.push(
|
|
9889
|
-
row(t("drawing.rowsLayout"), dropdown(t("drawing.rowsLayout"), ["number", "ticks"], props.rowsLayout, label(t, ROWS_LAYOUT_LABEL), (v) => ctx.patchProps({ rowsLayout: v }))),
|
|
10032
|
+
row(t("drawing.rowsLayout"), dropdown(ctx.icons, t("drawing.rowsLayout"), ["number", "ticks"], props.rowsLayout, label(t, ROWS_LAYOUT_LABEL), (v) => ctx.patchProps({ rowsLayout: v }))),
|
|
9890
10033
|
row(t("drawing.rowSize"), numberInput(t, ctx.icons, { label: t("drawing.rowSize"), value: Number(props.rowSize), min: 1, max: 400, step: 1, onChange: (v) => ctx.patchProps({ rowSize: v }) })),
|
|
9891
|
-
row(t("drawing.volume"), dropdown(t("drawing.volume"), ["updown", "total", "delta"], props.volume, label(t, PROFILE_VOLUME_LABEL), (v) => ctx.patchProps({ volume: v }))),
|
|
10034
|
+
row(t("drawing.volume"), dropdown(ctx.icons, t("drawing.volume"), ["updown", "total", "delta"], props.volume, label(t, PROFILE_VOLUME_LABEL), (v) => ctx.patchProps({ volume: v }))),
|
|
9892
10035
|
row(t("drawing.valueAreaVolume"), numberInput(t, ctx.icons, { label: t("drawing.valueAreaVolume"), value: Number(props.valueAreaVolume), min: 0, max: 95, step: 5, onChange: (v) => ctx.patchProps({ valueAreaVolume: v }) }))
|
|
9893
10036
|
);
|
|
9894
10037
|
if ("extendRight" in props) out.push(toggleRow(t("drawing.extendRight"), !!props.extendRight, (v) => ctx.patchProps({ extendRight: v })));
|
|
@@ -9896,7 +10039,7 @@ function styleRows(ctx) {
|
|
|
9896
10039
|
if ("rowsLayout" in props && tab === "Style") {
|
|
9897
10040
|
out.push(
|
|
9898
10041
|
row(t("drawing.widthPercent"), numberInput(t, ctx.icons, { label: t("drawing.widthPercent"), value: Number(props.widthPercent), min: 5, max: 100, step: 5, onChange: (v) => ctx.patchProps({ widthPercent: v }) })),
|
|
9899
|
-
row(t("drawing.placement"), dropdown(t("drawing.placement"), ["left", "right"], props.placement, label(t, SIDE_LABEL), (v) => ctx.patchProps({ placement: v }))),
|
|
10042
|
+
row(t("drawing.placement"), dropdown(ctx.icons, t("drawing.placement"), ["left", "right"], props.placement, label(t, SIDE_LABEL), (v) => ctx.patchProps({ placement: v }))),
|
|
9900
10043
|
row(t("drawing.upDownVolume"), swatch("upColor"), swatch("downColor")),
|
|
9901
10044
|
row(t("drawing.valueAreaUpDown"), swatch("valueAreaUpColor"), swatch("valueAreaDownColor"))
|
|
9902
10045
|
);
|
|
@@ -9906,17 +10049,17 @@ function styleRows(ctx) {
|
|
|
9906
10049
|
t(level.label),
|
|
9907
10050
|
checkbox(t("drawing.rowVisible", { name: t(level.label) }), !!props[`${level.key}Visible`], (v) => ctx.patchProps({ [`${level.key}Visible`]: v })),
|
|
9908
10051
|
swatch(`${level.key}Color`),
|
|
9909
|
-
dropdown(t("drawing.thickness"), ["1", "2", "3", "4"], String(Math.min(4, Number(props[`${level.key}Width`]) || 1)), (v) => `${v}px`, (v) => ctx.patchProps({ [`${level.key}Width`]: Number(v) })),
|
|
9910
|
-
dropdown(t("drawing.lineStyle"), ["solid", "dashed", "dotted"], props[`${level.key}Style`], (v) => t(v === "solid" ? "drawing.lineSolid" : v === "dashed" ? "drawing.lineDashed" : "drawing.lineDotted"), (v) => ctx.patchProps({ [`${level.key}Style`]: v }))
|
|
10052
|
+
dropdown(ctx.icons, t("drawing.thickness"), ["1", "2", "3", "4"], String(Math.min(4, Number(props[`${level.key}Width`]) || 1)), (v) => `${v}px`, (v) => ctx.patchProps({ [`${level.key}Width`]: Number(v) })),
|
|
10053
|
+
dropdown(ctx.icons, t("drawing.lineStyle"), ["solid", "dashed", "dotted"], props[`${level.key}Style`], (v) => t(v === "solid" ? "drawing.lineSolid" : v === "dashed" ? "drawing.lineDashed" : "drawing.lineDotted"), (v) => ctx.patchProps({ [`${level.key}Style`]: v }))
|
|
9911
10054
|
)
|
|
9912
10055
|
);
|
|
9913
10056
|
}
|
|
9914
10057
|
out.push(toggleRow(t("drawing.developingPoc"), !!props.developingPoc, (v) => ctx.patchProps({ developingPoc: v })), toggleRow(t("drawing.developingVa"), !!props.developingVa, (v) => ctx.patchProps({ developingVa: v })));
|
|
9915
10058
|
}
|
|
9916
10059
|
if (sect("source")) {
|
|
9917
|
-
out.push(row(t("drawing.source"), dropdown(t("drawing.source"), ["close", "open", "hl2", "hlc3"], props.source, (v) => v, (v) => ctx.patchProps({ source: v }))));
|
|
10060
|
+
out.push(row(t("drawing.source"), dropdown(ctx.icons, t("drawing.source"), ["close", "open", "hl2", "hlc3"], props.source, (v) => v, (v) => ctx.patchProps({ source: v }))));
|
|
9918
10061
|
}
|
|
9919
|
-
if (sect("mode")) out.push(row(t("drawing.mode"), dropdown(t("drawing.mode"), ["bars", "open", "high", "low", "close", "hl2"], props.mode, label(t, MODE_LABEL), (v) => ctx.patchProps({ mode: v }))));
|
|
10062
|
+
if (sect("mode")) out.push(row(t("drawing.mode"), dropdown(ctx.icons, t("drawing.mode"), ["bars", "open", "high", "low", "close", "hl2"], props.mode, label(t, MODE_LABEL), (v) => ctx.patchProps({ mode: v }))));
|
|
9920
10063
|
toggle("mirrored", "drawing.mirrored");
|
|
9921
10064
|
toggle("flipped", "drawing.flipped");
|
|
9922
10065
|
if (sect("successBackColor")) {
|
|
@@ -9955,7 +10098,7 @@ function styleRows(ctx) {
|
|
|
9955
10098
|
row(
|
|
9956
10099
|
t("drawing.risk"),
|
|
9957
10100
|
numberInput(t, ctx.icons, { label: t("drawing.risk"), value: Number(props.risk), onChange: (v) => ctx.patchProps({ risk: v }) }),
|
|
9958
|
-
dropdown(t("drawing.risk"), ["percent", "money"], props.riskDisplay, (v) => v === "percent" ? "%" : "$", (v) => ctx.patchProps({ riskDisplay: v }))
|
|
10101
|
+
dropdown(ctx.icons, t("drawing.risk"), ["percent", "money"], props.riskDisplay, (v) => v === "percent" ? "%" : "$", (v) => ctx.patchProps({ riskDisplay: v }))
|
|
9959
10102
|
),
|
|
9960
10103
|
row(t("drawing.lotSize"), numberInput(t, ctx.icons, { label: t("drawing.lotSize"), value: Number(props.lotSize), min: 0, step: 0.01, onChange: (v) => ctx.patchProps({ lotSize: v }) })),
|
|
9961
10104
|
row(t("drawing.leverage"), numberInput(t, ctx.icons, { label: t("drawing.leverage"), value: Number(props.leverage), min: 1, max: 500, step: 1, onChange: (v) => ctx.patchProps({ leverage: v }) })),
|
|
@@ -10016,11 +10159,11 @@ function textRows(ctx) {
|
|
|
10016
10159
|
const alpha = alphaOf(style.textColor);
|
|
10017
10160
|
ctx.patchStyle({ textColor: alpha < 1 ? withAlpha(c, alpha) : c });
|
|
10018
10161
|
}, opacity: alphaOf(style.textColor), onOpacity: (v) => ctx.patchStyle({ textColor: withAlpha(style.textColor, v) }) })),
|
|
10019
|
-
row(t("drawing.size"), dropdown(t("drawing.size"), FONT_SIZES2, String(style.fontSize), (v) => v, (v) => ctx.patchStyle({ fontSize: Number(v) }))),
|
|
10162
|
+
row(t("drawing.size"), dropdown(ctx.icons, t("drawing.size"), FONT_SIZES2, String(style.fontSize), (v) => v, (v) => ctx.patchStyle({ fontSize: Number(v) }))),
|
|
10020
10163
|
row(t("drawing.weight"), weight(style.bold, "B", t("drawing.bold"), () => ctx.patchStyle({ bold: !style.bold })), weight(style.italic, "I", t("drawing.italic"), () => ctx.patchStyle({ italic: !style.italic }))),
|
|
10021
10164
|
area
|
|
10022
10165
|
];
|
|
10023
|
-
if ("align" in props) out.push(row(t("drawing.alignment"), dropdown(t("drawing.alignment"), ["left", "center"], props.align, label(t, SIDE_LABEL), (v) => ctx.patchProps({ align: v }))));
|
|
10166
|
+
if ("align" in props) out.push(row(t("drawing.alignment"), dropdown(ctx.icons, t("drawing.alignment"), ["left", "center"], props.align, label(t, SIDE_LABEL), (v) => ctx.patchProps({ align: v }))));
|
|
10024
10167
|
if (NO_STYLE_TAB.has(drawing2.type)) {
|
|
10025
10168
|
out.push(row(t("drawing.background"), swatchButton(t, box, { label: t("drawing.background"), value: style.fillColor, onPick: (c) => ctx.patchStyle({ fillColor: c, ...style.fillOpacity === 0 ? { fillOpacity: 0.95 } : {} }), opacity: style.fillOpacity, onOpacity: (v) => ctx.patchStyle({ fillOpacity: v }) })));
|
|
10026
10169
|
if (drawing2.type !== "text") {
|
|
@@ -10339,6 +10482,7 @@ function attachDrawingsPlane(deps) {
|
|
|
10339
10482
|
const handle = attachDrawings({
|
|
10340
10483
|
chart: deps.chart,
|
|
10341
10484
|
series: deps.series,
|
|
10485
|
+
navigable: deps.navigable,
|
|
10342
10486
|
container: deps.container,
|
|
10343
10487
|
symbol: deps.symbol,
|
|
10344
10488
|
timeframe: deps.timeframe,
|
|
@@ -12754,6 +12898,7 @@ function composeFormingBar(parent, subs, k) {
|
|
|
12754
12898
|
}
|
|
12755
12899
|
|
|
12756
12900
|
// src/widget/replay.ts
|
|
12901
|
+
var START_HOLD_MS = 250;
|
|
12757
12902
|
function coerceReplaySpeed(raw) {
|
|
12758
12903
|
const n = Number(raw);
|
|
12759
12904
|
return REPLAY_SPEEDS.includes(n) ? n : 10;
|
|
@@ -12772,6 +12917,13 @@ function attachReplayPlane(deps) {
|
|
|
12772
12917
|
let stepping = null;
|
|
12773
12918
|
let generation = 0;
|
|
12774
12919
|
let destroyed = false;
|
|
12920
|
+
let glide = null;
|
|
12921
|
+
const stopGlide = () => {
|
|
12922
|
+
if (glide) {
|
|
12923
|
+
clearTimeout(glide);
|
|
12924
|
+
glide = null;
|
|
12925
|
+
}
|
|
12926
|
+
};
|
|
12775
12927
|
const invalidateStep = () => {
|
|
12776
12928
|
generation += 1;
|
|
12777
12929
|
stepping = null;
|
|
@@ -12792,15 +12944,34 @@ function attachReplayPlane(deps) {
|
|
|
12792
12944
|
const currentGrain = () => autoGrain ? "auto" : manualGrain ?? "auto";
|
|
12793
12945
|
const paintCursor = () => {
|
|
12794
12946
|
if (!master) return;
|
|
12947
|
+
stopGlide();
|
|
12795
12948
|
deps.paint(master.slice(0, cursor));
|
|
12796
12949
|
deps.chart.timeScale().scrollToRealTime();
|
|
12797
12950
|
};
|
|
12798
12951
|
const paintForming = () => {
|
|
12799
12952
|
if (!master || !subs) return;
|
|
12953
|
+
stopGlide();
|
|
12800
12954
|
const parent = master[cursor - 1];
|
|
12801
12955
|
deps.paint([...master.slice(0, cursor - 1), composeFormingBar(parent, subs, formK)]);
|
|
12802
12956
|
deps.chart.timeScale().scrollToRealTime();
|
|
12803
12957
|
};
|
|
12958
|
+
const paintStart = () => {
|
|
12959
|
+
if (!master) return;
|
|
12960
|
+
const scale = deps.chart.timeScale();
|
|
12961
|
+
const shown2 = scale.getVisibleRange();
|
|
12962
|
+
const view = scale.getVisibleLogicalRange();
|
|
12963
|
+
const chosen = master[cursor - 1].t;
|
|
12964
|
+
const from = shown2?.from;
|
|
12965
|
+
const to = shown2?.to;
|
|
12966
|
+
if (!view || typeof from !== "number" || typeof to !== "number" || chosen < from || chosen > to) return paintCursor();
|
|
12967
|
+
stopGlide();
|
|
12968
|
+
deps.paint(master.slice(0, cursor));
|
|
12969
|
+
scale.setVisibleLogicalRange(view);
|
|
12970
|
+
glide = setTimeout(() => {
|
|
12971
|
+
glide = null;
|
|
12972
|
+
if (master && !destroyed && !deps.disposed()) scale.scrollToRealTime();
|
|
12973
|
+
}, START_HOLD_MS);
|
|
12974
|
+
};
|
|
12804
12975
|
const stopTimer = () => {
|
|
12805
12976
|
if (timer) {
|
|
12806
12977
|
clearInterval(timer);
|
|
@@ -12884,6 +13055,7 @@ function attachReplayPlane(deps) {
|
|
|
12884
13055
|
};
|
|
12885
13056
|
function abandon() {
|
|
12886
13057
|
invalidateStep();
|
|
13058
|
+
stopGlide();
|
|
12887
13059
|
if (!master) return;
|
|
12888
13060
|
stopTimer();
|
|
12889
13061
|
playing = false;
|
|
@@ -12911,7 +13083,7 @@ function attachReplayPlane(deps) {
|
|
|
12911
13083
|
const idx = master.findIndex((b) => b.t >= atSec);
|
|
12912
13084
|
cursor = Math.max(2, (idx === -1 ? master.length - 1 : idx) + 1);
|
|
12913
13085
|
deps.setHeader(true);
|
|
12914
|
-
|
|
13086
|
+
paintStart();
|
|
12915
13087
|
sync();
|
|
12916
13088
|
},
|
|
12917
13089
|
exit() {
|
|
@@ -13434,7 +13606,7 @@ function attachExtensionsPlane(deps) {
|
|
|
13434
13606
|
},
|
|
13435
13607
|
lockPanZoom: (locked) => {
|
|
13436
13608
|
if (deps.disposed()) return;
|
|
13437
|
-
const state = pointerLock(locked);
|
|
13609
|
+
const state = pointerLock(locked, deps.navigable);
|
|
13438
13610
|
deps.chart.applyOptions({ handleScroll: state.handleScroll, handleScale: state.handleScale });
|
|
13439
13611
|
deps.setTouchAction(state.touchAction);
|
|
13440
13612
|
}
|
|
@@ -13974,1353 +14146,1358 @@ function mountChartLegend(container, strings, controls) {
|
|
|
13974
14146
|
};
|
|
13975
14147
|
}
|
|
13976
14148
|
|
|
13977
|
-
// src/
|
|
13978
|
-
var
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
const o = document.createElement("option");
|
|
13993
|
-
o.value = String(i);
|
|
13994
|
-
o.textContent = label2;
|
|
13995
|
-
select.appendChild(o);
|
|
13996
|
-
});
|
|
13997
|
-
select.value = String(current[key] ?? spec.default);
|
|
13998
|
-
fields.set(key, select);
|
|
13999
|
-
row2.appendChild(select);
|
|
14000
|
-
} else {
|
|
14001
|
-
const input = document.createElement("input");
|
|
14002
|
-
input.type = "number";
|
|
14003
|
-
input.className = "qc-field qc-inputs-field";
|
|
14004
|
-
if (spec.min !== void 0) input.min = String(spec.min);
|
|
14005
|
-
if (spec.max !== void 0) input.max = String(spec.max);
|
|
14006
|
-
input.step = spec.kind === "int" ? "1" : "any";
|
|
14007
|
-
input.value = String(current[key] ?? spec.default);
|
|
14008
|
-
fields.set(key, input);
|
|
14009
|
-
row2.appendChild(input);
|
|
14010
|
-
}
|
|
14011
|
-
rows2.push(row2);
|
|
14149
|
+
// src/ui/icons/draw.ts
|
|
14150
|
+
var SVG_NS2 = "http://www.w3.org/2000/svg";
|
|
14151
|
+
var answered = /* @__PURE__ */ new WeakSet();
|
|
14152
|
+
var isSvg = (node) => typeof node === "object" && node !== null && node.nodeType === 1 && node.namespaceURI === SVG_NS2 && node.localName === "svg";
|
|
14153
|
+
var FAILURE_TEXT = {
|
|
14154
|
+
threw: "the factory threw",
|
|
14155
|
+
"not-svg": "the factory answered something other than an <svg> element",
|
|
14156
|
+
"in-use": "the factory answered an element already in a document or answered before"
|
|
14157
|
+
};
|
|
14158
|
+
function drawHostIcon(factory, context) {
|
|
14159
|
+
let node;
|
|
14160
|
+
try {
|
|
14161
|
+
node = factory(context);
|
|
14162
|
+
} catch {
|
|
14163
|
+
return { failure: "threw" };
|
|
14012
14164
|
}
|
|
14165
|
+
if (!isSvg(node)) return { failure: "not-svg" };
|
|
14166
|
+
if (node.parentNode !== null || answered.has(node)) return { failure: "in-use" };
|
|
14167
|
+
answered.add(node);
|
|
14168
|
+
node.setAttribute("width", String(context.width));
|
|
14169
|
+
node.setAttribute("height", String(context.height));
|
|
14170
|
+
node.setAttribute("aria-hidden", "true");
|
|
14171
|
+
node.setAttribute("focusable", "false");
|
|
14172
|
+
return { element: node };
|
|
14173
|
+
}
|
|
14174
|
+
function createIconDiagnostics() {
|
|
14175
|
+
const seen = /* @__PURE__ */ new Map();
|
|
14013
14176
|
return {
|
|
14014
|
-
|
|
14015
|
-
|
|
14016
|
-
const patch = {};
|
|
14017
|
-
for (const [key, field] of fields) {
|
|
14018
|
-
const spec = inputs2[key];
|
|
14019
|
-
let value = Number(field.value);
|
|
14020
|
-
if (!Number.isFinite(value)) continue;
|
|
14021
|
-
if (spec.kind === "int" || spec.kind === "enum") value = Math.round(value);
|
|
14022
|
-
if (spec.min !== void 0) value = Math.max(spec.min, value);
|
|
14023
|
-
if (spec.max !== void 0) value = Math.min(spec.max, value);
|
|
14024
|
-
patch[key] = value;
|
|
14025
|
-
}
|
|
14026
|
-
return patch;
|
|
14177
|
+
report(icon, failure) {
|
|
14178
|
+
if (!seen.has(icon)) seen.set(icon, { icon, code: failure, message: `${icon}: ${FAILURE_TEXT[failure]}` });
|
|
14027
14179
|
},
|
|
14028
|
-
|
|
14029
|
-
};
|
|
14030
|
-
}
|
|
14031
|
-
function openInputsEditor(container, rect, inputs2, current, onApply, strings = createChartI18n()) {
|
|
14032
|
-
const host2 = container.getBoundingClientRect();
|
|
14033
|
-
const el2 = document.createElement("div");
|
|
14034
|
-
el2.className = "qc-overlay qc-inputs";
|
|
14035
|
-
el2.setAttribute("role", "dialog");
|
|
14036
|
-
el2.setAttribute("aria-label", strings.t("legend.indicatorSettings"));
|
|
14037
|
-
el2.style.left = `${Math.max(4, rect.x - host2.left)}px`;
|
|
14038
|
-
el2.style.top = `${Math.max(4, rect.y - host2.top + rect.h + 4)}px`;
|
|
14039
|
-
for (const type of ["pointerdown", "pointerup", "pointermove"]) el2.addEventListener(type, (e) => e.stopPropagation());
|
|
14040
|
-
const dismiss = () => {
|
|
14041
|
-
unsubscribe();
|
|
14042
|
-
el2.remove();
|
|
14043
|
-
};
|
|
14044
|
-
const fields = buildInputFields(inputs2, current);
|
|
14045
|
-
for (const row2 of fields.rows) el2.appendChild(row2);
|
|
14046
|
-
const apply = () => {
|
|
14047
|
-
onApply(fields.read());
|
|
14048
|
-
dismiss();
|
|
14049
|
-
};
|
|
14050
|
-
const buttons = document.createElement("div");
|
|
14051
|
-
buttons.className = "qc-inputs-actions";
|
|
14052
|
-
const mkButton = (label2, onClick, primary = false) => {
|
|
14053
|
-
const b = document.createElement("button");
|
|
14054
|
-
b.type = "button";
|
|
14055
|
-
b.className = primary ? "qc-button qc-button--primary" : "qc-button";
|
|
14056
|
-
b.textContent = label2;
|
|
14057
|
-
b.addEventListener("click", onClick);
|
|
14058
|
-
buttons.appendChild(b);
|
|
14059
|
-
return b;
|
|
14180
|
+
list: () => [...seen.values()]
|
|
14060
14181
|
};
|
|
14061
|
-
const cancelButton = mkButton(strings.t("inputs.cancel"), () => dismiss());
|
|
14062
|
-
const applyButton = mkButton(strings.t("inputs.apply"), apply, true);
|
|
14063
|
-
el2.appendChild(buttons);
|
|
14064
|
-
const unsubscribe = strings.onChange(() => {
|
|
14065
|
-
cancelButton.textContent = strings.t("inputs.cancel");
|
|
14066
|
-
applyButton.textContent = strings.t("inputs.apply");
|
|
14067
|
-
el2.setAttribute("aria-label", strings.t("legend.indicatorSettings"));
|
|
14068
|
-
});
|
|
14069
|
-
el2.addEventListener("keydown", (e) => {
|
|
14070
|
-
e.stopPropagation();
|
|
14071
|
-
if (e.key === "Enter") apply();
|
|
14072
|
-
else if (e.key === "Escape") dismiss();
|
|
14073
|
-
});
|
|
14074
|
-
container.appendChild(el2);
|
|
14075
|
-
fields.first()?.focus?.();
|
|
14076
14182
|
}
|
|
14077
14183
|
|
|
14078
|
-
// src/ui/
|
|
14079
|
-
var
|
|
14080
|
-
|
|
14081
|
-
|
|
14082
|
-
|
|
14083
|
-
|
|
14084
|
-
|
|
14085
|
-
|
|
14086
|
-
|
|
14087
|
-
|
|
14088
|
-
|
|
14089
|
-
|
|
14090
|
-
|
|
14091
|
-
|
|
14092
|
-
|
|
14093
|
-
|
|
14094
|
-
|
|
14095
|
-
|
|
14096
|
-
|
|
14097
|
-
|
|
14098
|
-
|
|
14099
|
-
|
|
14100
|
-
|
|
14101
|
-
|
|
14102
|
-
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
|
|
14107
|
-
|
|
14108
|
-
|
|
14109
|
-
|
|
14110
|
-
|
|
14111
|
-
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14122
|
-
|
|
14123
|
-
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14127
|
-
|
|
14128
|
-
|
|
14129
|
-
|
|
14130
|
-
|
|
14131
|
-
|
|
14132
|
-
|
|
14133
|
-
|
|
14134
|
-
|
|
14135
|
-
|
|
14136
|
-
|
|
14137
|
-
|
|
14138
|
-
|
|
14139
|
-
|
|
14140
|
-
|
|
14141
|
-
|
|
14142
|
-
|
|
14143
|
-
|
|
14144
|
-
|
|
14145
|
-
|
|
14146
|
-
|
|
14147
|
-
|
|
14148
|
-
|
|
14149
|
-
|
|
14150
|
-
|
|
14151
|
-
|
|
14152
|
-
|
|
14153
|
-
|
|
14154
|
-
|
|
14155
|
-
|
|
14156
|
-
|
|
14157
|
-
|
|
14158
|
-
|
|
14159
|
-
|
|
14160
|
-
|
|
14161
|
-
|
|
14162
|
-
|
|
14163
|
-
|
|
14164
|
-
|
|
14165
|
-
|
|
14166
|
-
|
|
14167
|
-
element,
|
|
14168
|
-
close,
|
|
14169
|
-
open: () => isOpen,
|
|
14170
|
-
refresh() {
|
|
14171
|
-
if (!isOpen) return;
|
|
14172
|
-
const current = items(element).indexOf(document.activeElement);
|
|
14173
|
-
body.replaceChildren();
|
|
14174
|
-
options.build(body, handle);
|
|
14175
|
-
if (footer && options.footer) {
|
|
14176
|
-
footer.replaceChildren();
|
|
14177
|
-
options.footer(footer, handle);
|
|
14178
|
-
}
|
|
14179
|
-
const list2 = items(element);
|
|
14180
|
-
if (list2.length === 0) return;
|
|
14181
|
-
if (current >= 0 && document.activeElement && !element.contains(document.activeElement)) return;
|
|
14182
|
-
armRoving(element, Math.max(0, Math.min(current, list2.length - 1)));
|
|
14183
|
-
if (current >= 0) list2[Math.min(current, list2.length - 1)]?.focus();
|
|
14184
|
-
reposition();
|
|
14185
|
-
},
|
|
14186
|
-
reposition
|
|
14187
|
-
};
|
|
14188
|
-
byAnchor.set(anchor, handle);
|
|
14189
|
-
previous?.close();
|
|
14190
|
-
if (!isOpen || byAnchor.get(anchor) !== handle) return handle;
|
|
14191
|
-
options.build(body, handle);
|
|
14192
|
-
if (footer && options.footer) options.footer(footer, handle);
|
|
14193
|
-
if (!isOpen || byAnchor.get(anchor) !== handle) return handle;
|
|
14194
|
-
host2.appendChild(element);
|
|
14195
|
-
untrack = trackOverlay(host2, close, () => handle.refresh());
|
|
14196
|
-
anchor.setAttribute("aria-expanded", "true");
|
|
14197
|
-
reposition();
|
|
14198
|
-
const list = items(element);
|
|
14199
|
-
const first = Math.max(0, Math.min(options.initialIndex ?? 0, list.length - 1));
|
|
14200
|
-
if (list.length > 0) {
|
|
14201
|
-
armRoving(element, first);
|
|
14202
|
-
focusItem(list, first);
|
|
14203
|
-
list[first]?.scrollIntoView?.({ block: "nearest" });
|
|
14204
|
-
} else {
|
|
14205
|
-
const focusable = element.querySelector('input, button, select, textarea, [tabindex="0"]');
|
|
14206
|
-
focusable?.focus();
|
|
14207
|
-
}
|
|
14208
|
-
document.addEventListener("pointerdown", onOutside, true);
|
|
14209
|
-
document.addEventListener("keydown", onDocumentKey, true);
|
|
14210
|
-
window.addEventListener("resize", reposition);
|
|
14211
|
-
return handle;
|
|
14212
|
-
}
|
|
14213
|
-
function menuItem(options) {
|
|
14214
|
-
const role = options.role ?? "menuitem";
|
|
14215
|
-
const row2 = h("button", {
|
|
14216
|
-
type: "button",
|
|
14217
|
-
class: `qc-menu-row${options.className ? ` ${options.className}` : ""}`,
|
|
14218
|
-
role,
|
|
14219
|
-
"data-qc-item": "",
|
|
14220
|
-
tabindex: "-1",
|
|
14221
|
-
...options.label ? { "aria-label": options.label } : options.keys ? { "aria-label": options.text } : {},
|
|
14222
|
-
...options.keys ? { "aria-keyshortcuts": options.keys } : {},
|
|
14223
|
-
...role === "menuitemradio" || role === "menuitemcheckbox" ? { "aria-checked": String(options.checked === true) } : {},
|
|
14224
|
-
...role === "option" ? { "aria-selected": String(options.checked === true) } : {}
|
|
14225
|
-
});
|
|
14226
|
-
if (options.disabled) {
|
|
14227
|
-
row2.disabled = true;
|
|
14228
|
-
row2.setAttribute("aria-disabled", "true");
|
|
14229
|
-
}
|
|
14230
|
-
const cell2 = h("span", { class: "qc-menu-icon" });
|
|
14231
|
-
if (options.icon) {
|
|
14232
|
-
row2.classList.add("qc-menu-row--marked");
|
|
14233
|
-
cell2.appendChild(options.icon);
|
|
14234
|
-
}
|
|
14235
|
-
row2.appendChild(cell2);
|
|
14236
|
-
const label2 = h("span", { class: "qc-menu-label" }, options.text);
|
|
14237
|
-
row2.appendChild(options.description === void 0 ? label2 : h("span", { class: "qc-menu-text" }, label2, h("span", { class: "qc-menu-description" }, options.description)));
|
|
14238
|
-
if (options.hint !== void 0) row2.appendChild(h("span", { class: "qc-menu-hint", ...options.keys ? { "aria-hidden": "true" } : {} }, options.hint));
|
|
14239
|
-
if (options.onSelect) row2.addEventListener("click", () => options.onSelect?.());
|
|
14240
|
-
return row2;
|
|
14241
|
-
}
|
|
14242
|
-
function menuHeading(text2) {
|
|
14243
|
-
return h("div", { class: "qc-menu-heading", role: "presentation" }, text2);
|
|
14244
|
-
}
|
|
14245
|
-
function menuSeparator() {
|
|
14246
|
-
return h("div", { class: "qc-separator", role: "separator" });
|
|
14247
|
-
}
|
|
14184
|
+
// src/ui/drawings/toolIcons.ts
|
|
14185
|
+
var TOOL_ICONS = {
|
|
14186
|
+
trend_line: '<path d="M7.3 20.7 20.7 7.3" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14187
|
+
ray: '<path d="M8.3 19.7 12.7 15.3 M16.3 11.7 24.4 3.6" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="21.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="13.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14188
|
+
info_line: '<path d="M7.3 20.7 20.7 7.3" stroke="currentColor" stroke-width="1.2"/><rect x="16.5" y="17.5" width="9" height="7" rx="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14189
|
+
extended: '<path d="M4.4 25.4 9.3 20.5 M12.4 17.4 17.4 12.4 M20.4 9.4 25.4 4.4" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14190
|
+
trend_angle: '<path d="M7.3 20.7 20.7 7.3 M7.5 22.5H24 M15.5 22.5A8 8 0 0 0 13.2 16.8" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14191
|
+
horizontal_line: '<path d="M4 14.5h8.4 M16.6 14.5H25" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14192
|
+
horizontal_ray: '<path d="M8.9 14.5H25" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14193
|
+
vertical_line: '<path d="M14.5 4v8.4 M14.5 16.6V25" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14194
|
+
cross_line: '<path d="M4 14.5h8.4 M16.6 14.5H25 M14.5 4v8.4 M14.5 16.6V25" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14195
|
+
parallel_channel: '<path d="M8.3 18.3 18.3 8.3 M12.4 25.3 17.3 20.4 M20.4 17.3 25.3 12.4" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="19.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.85" cy="18.85" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14196
|
+
regression_trend: '<path d="M5.5 12 22.5 3 M5.5 25 22.5 16 M7.6 18 20.7 11.1" stroke="currentColor" stroke-width="1.2"/><path d="M5.5 12v4.4 M5.5 20.6V25 M22.5 3v4.4 M22.5 11.6V16" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="9.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14197
|
+
flat_top_bottom: '<path d="M7.7 12.6 20.3 7.4 M7.5 22.5h13" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="13.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14198
|
+
disjoint_channel: '<path d="M7.3 9.3 20.6 4.6 M7.5 17.7 20.7 22.4" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="4.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="16.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14199
|
+
pitchfork: '<path d="M7.3 21.4 19.9 8.9 M6.7 13.4 14.6 21.3 M7.1 10.6 14.2 3.5 M18.1 21.6 25.2 14.5" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="11.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="16.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14200
|
+
schiff_pitchfork: '<path d="M6.5 22.5H16.5 M10.3 20.4 21.9 8.9 M8.3 13 17 21.7 M9.1 10.6 16.2 3.5 M20.1 21.6 27.2 14.5" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="7.5" cy="11.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14201
|
+
schiff_pitchfork_modified: '<path d="M7.9 22.9 21.9 8.9 M5.5 22.5H16.5 M8.3 13 17 21.7 M9.1 10.6 16.2 3.5 M20.1 21.6 27.2 14.5" stroke="currentColor" stroke-width="1.2"/><circle cx="7.5" cy="11.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14202
|
+
inside_pitchfork: '<path d="M6.5 22.5H18.5 M8.4 22.7 10.4 16.6 M11.6 12.7 14.7 3.1 M16 18.7 19.7 7.1 M21.6 20.7 24.7 11.1 M11.8 16.2 18.6 21.6" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="20.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14203
|
+
fib_retracement: '<path d="M3 4.5h22 M3 10.5h19.4 M3 16.5h22 M6 22.5h19" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14204
|
+
fib_trend_ext: '<path d="M6.6 16.5H26 M4 20.5h22 M4 24.5h22 M4.5 11.6v2.9 M6.6 9.3 16.6 5.7" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="9.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="16.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="4.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14205
|
+
fib_channel: '<path d="M7.5 12 21 4.9 M7.3 18.5 23.2 10.1 M5.3 26 23.2 16.7" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="3.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14206
|
+
fib_timezone: '<path d="M5.5 4v4.4 M5.5 12.6V25 M14.5 4v13.4 M14.5 21.6V25 M19.5 4v21 M24.5 4v21" stroke="currentColor" stroke-width="1.2"/><path d="M7.2 12.2l1 1 M9 14.5l1.5 1.5 M11.4 16.9l1.2 1.2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14207
|
+
fib_speed_resist_fan: '<path d="M4.5 2v19.4 M4.5 10.5H15 M17.5 12.6v10.9 M6.5 23.5H26" stroke="currentColor" stroke-width="1.2"/><path d="M6.3 22.4 16.4 12.3 M19.3 9.4 25.9 2.9 M6.6 23.4 25.7 17.5 M5.6 21.7 11.5 2.7" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14208
|
+
fib_trend_time: '<path d="M16.5 2v19.4 M20.5 2v22 M24.5 2v22 M4.7 11.5 8.4 21.8 M11.5 23.5h3" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="9.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="9.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="16.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14209
|
+
fib_circles: '<circle cx="14.5" cy="14.5" r="5" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="14.5" r="8" stroke="currentColor" stroke-width="1.2"/><path d="M24.1 8.5A11.3 11.3 0 0 1 8.5 24.1 M4.9 20.5A11.3 11.3 0 0 1 20.5 4.9" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14210
|
+
fib_spiral: '<path d="M15.6 13.2a1.7 1.7 0 1 0-3.4 0 3 3 0 0 0 6 0 5.2 5.2 0 1 0-10.4 0 7.6 7.6 0 0 0 14.9 2.4" stroke="currentColor" stroke-width="1.2"/><path d="M15 15.7 18.7 12 M21 9.7 24.2 6.5" stroke="currentColor" stroke-width="1.2"/><circle cx="13.5" cy="16.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="19.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14211
|
+
fib_speed_resist_arcs: '<path d="M8.5 9.5A5 5 0 0 0 18.5 9.5 M0.5 9.5A13 13 0 0 0 26.5 9.5 M4.5 9.5A9 9 0 0 0 11 18.2 M16 18.2A9 9 0 0 0 22.5 9.5" stroke="currentColor" stroke-width="1.2"/><circle cx="13.5" cy="9.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="13.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14212
|
+
fib_wedge: '<path d="M5.5 8v13 M8 23.5H21" stroke="currentColor" stroke-width="1.2"/><path d="M5.5 17.5A6 6 0 0 1 11.5 23.5 M5.5 13.5A10 10 0 0 1 15.5 23.5 M5.5 9.5A14 14 0 0 1 19.5 23.5" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14213
|
+
pitchfan: '<path d="M7.4 21.4 24.4 4.4 M7.3 22.7 16.9 21.2 M20.3 20.7 24.8 19.9 M7.3 22.1 23 13.8 M6.7 21.2 15.1 5.5 M6.3 20.8 7.8 11.4 M8.3 7.8 9 3.3 M9.3 10.6 17.5 18.8" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="7.5" cy="9.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="20.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14214
|
+
gannbox: '<path d="M22.5 3.5H3.5V22 M5.5 24.5H24.5V5.5" stroke="currentColor" stroke-width="1.2"/><path d="M3.5 10.5h21 M3.5 17.5h21 M10.5 3.5v21 M17.5 3.5v21" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="24.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="3.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14215
|
+
gannbox_fixed: '<path d="M5.5 23.5H24.5V2.5H3.5V21.5 M4 9.5h20 M3.5 18.5h5 M12.5 18.5h12 M17.5 3v20 M10.5 2.5v12 M10.5 18.5v5" stroke="currentColor" stroke-width="1.2"/><path d="M4.9 22.1 9.1 17.9 M12 15 24 3 M5.4 23 24.5 17 M4.1 21.6 10 2.5 M24.5 23.5A21 21 0 0 0 3.5 2.5" stroke="currentColor" stroke-width="1.2"/>',
|
|
14216
|
+
gannbox_square: '<path d="M22.5 3.5H3.5V22 M5.5 24.5H24.5V5.5" stroke="currentColor" stroke-width="1.2"/><path d="M5.3 23.4 23.5 5.2 M5.6 24.4 24.7 18.5 M4.6 22.7 10.5 3.7 M24.5 6.5A21 21 0 0 1 6.5 24.5" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="24.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="3.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14217
|
+
gannbox_fan: '<path d="M7.4 21.4 14.5 14.3 M17.3 11.5 24.4 4.4 M7.5 22.1 23.3 14.4 M7.5 22.7 24.8 19.9 M6.8 21 14.5 5.2 M6.3 20.7 9.1 3.3" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="15.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14218
|
+
xabcd_pattern: '<path d="M6.3 20.7 8.6 7.6 M9 7.5 11 11 M11 13.8 6.2 20.6 M14.4 11.7 19.2 8.1 M20.4 8.5 22.6 17.6 M13.9 14 21.6 18.9" stroke="currentColor" stroke-width="1.2"/><circle cx="8.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="12.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="20.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14219
|
+
cypher_pattern: '<path d="M6.3 20.7 8.6 7.6 M9 7.5 11 11 M11 13.8 6.2 20.6 M14.4 11.7 19.2 8.1 M20.4 8.5 22.6 17.6 M13.9 14 21.6 18.9" stroke="currentColor" stroke-width="1.2"/><circle cx="8.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="12.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="20.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="14.3" y="24.4" text-anchor="middle" font-size="7.5" fill="currentColor">C</text>',
|
|
14220
|
+
abcd_pattern: '<path d="M9.5 6.7 21.5 5.2 M6.6 9.4 4.4 20.4 M6.5 22.7 18.6 21.2 M21.4 18.6 23.6 7.6 M8.5 9.2 18.8 19.5" stroke="currentColor" stroke-width="1.2"/><circle cx="7.5" cy="7.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="20.5" cy="20.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14221
|
+
triangle_pattern: '<path d="M2.5 1.5V20.8 M2.6 1.9 7.4 4.1 M11.1 5.9 16.4 8.3 M20.1 8.1 26.8 11.1 M4.1 21.2 9.5 18.8 M13.3 17.7 26.8 11.6" stroke="currentColor" stroke-width="1.2"/><path d="M3.7 20.8 9.2 6.6 M9.3 6.4 10.7 16.6 M13.1 17.2 17.8 10.4" stroke="currentColor" stroke-width="1.2"/><circle cx="9.5" cy="4.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="11.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="8.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14222
|
+
three_drives: '<path d="M0.3 4.7 1.4 5.2 M5.1 6.8 8.5 8.2 M12.1 9.8 15.5 11.2 M19.2 12.8 25.1 15.3 M0.3 17.7 1.4 18.2 M5.1 19.8 8.5 21.2 M12.1 22.8 15.5 24.2 M19.2 25.8 20.8 26.5" stroke="currentColor" stroke-width="1.2"/><path d="M3.5 7.5V16.4 M4.3 16.5 8.9 9.9 M10.5 10.5V19.5 M11.3 19.5 15.9 12.9 M17.5 13.5V22.5 M17.7 22.5 24.3 5.2" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="8.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="21.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="11.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="24.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14223
|
+
head_and_shoulders: '<path d="M4.4 21.7 6.5 12.6 M7.8 12 10 16.5 M10.6 16.4 13.5 6.3 M15.5 6.2 18.4 16.5 M18.9 16.5 21.1 12.1 M23.4 12.3 25.5 21.4" stroke="currentColor" stroke-width="1.2"/><path d="M1 18.5h7.5 M12.5 18.5h4 M20.5 18.5h6.5" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="4.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="21.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="25.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14224
|
+
elliott_impulse_wave: '<path d="M5.2 18.5 9.4 14.3 M11.9 13.9 16.1 18.1 M18.6 17.7 22.7 13.5" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="10.8" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">1</text><text x="24.6" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">5</text>',
|
|
14225
|
+
elliott_correction: '<path d="M5.2 18.5 9.4 14.3 M11.9 13.9 16.1 18.1 M18.6 17.7 22.7 13.5" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="10.8" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">A</text><text x="24.6" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">C</text>',
|
|
14226
|
+
elliott_triangle_wave: '<path d="M5.2 18.5 9.4 14.3 M11.9 13.9 16.1 18.1 M18.6 17.7 22.7 13.5" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="10.8" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">A</text><text x="24.6" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">E</text>',
|
|
14227
|
+
elliott_double_combo: '<path d="M5.2 18.5 9.4 14.3 M11.9 13.9 16.1 18.1 M18.6 17.7 22.7 13.5" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="10.8" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">W</text><text x="24.6" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">Y</text>',
|
|
14228
|
+
elliott_triple_combo: '<path d="M5.2 18.5 9.4 14.3 M11.9 13.9 16.1 18.1 M18.6 17.7 22.7 13.5" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="17.5" cy="19.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="10.8" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">W</text><text x="24.6" y="7" text-anchor="middle" font-size="7.5" fill="currentColor">Z</text>',
|
|
14229
|
+
cyclic_lines: '<path d="M5.5 4v8.4 M5.5 16.6V25 M11.5 4v8.4 M11.5 16.6V25 M17.5 4v21 M23.5 4v21" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="11.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14230
|
+
time_cycles: '<path d="M-2.5 15A5.5 5.5 0 0 1 8.5 15 M8.5 15A5.5 5.5 0 0 1 19.5 15 M19.5 15A5.5 5.5 0 0 1 30.5 15" stroke="currentColor" stroke-width="1.2"/><circle cx="8.5" cy="17.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="19.5" cy="17.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14231
|
+
sine_line: '<path d="M5.2 14.1C5.2 11.4 6 8.9 7.5 8 M11.1 8.6C12.7 9.9 13.3 12.1 14.1 14.6C15 17.4 15.9 20 17.7 21.3 M21.5 21.5C23 20.9 24 19.1 24.6 17.2C24.9 16.2 25.3 15.1 25.4 14.2" stroke="currentColor" stroke-width="1.2"/><circle cx="9.5" cy="7.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="19.5" cy="21.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14232
|
+
long_position: '<path d="M8 6.5H25 M5 17.5h20 M8 22.5H25" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="15.5" y="14.5" text-anchor="middle" font-size="7.5" fill="currentColor">L</text>',
|
|
14233
|
+
short_position: '<path d="M8 6.5H25 M5 11.5h20 M8 22.5H25" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><text x="15.7" y="19" text-anchor="middle" font-size="7.5" fill="currentColor">S</text>',
|
|
14234
|
+
forecast: '<path d="M7.5 6v6 M7.5 19.5V22 M14.5 5v5 M14.5 18v3 M21.5 5v6" stroke="currentColor" stroke-width="1.2"/><rect x="6.5" y="12.5" width="2" height="7" stroke="currentColor" stroke-width="1.2"/><rect x="13.5" y="10.5" width="2" height="7.5" stroke="currentColor" stroke-width="1.2"/><path d="M19 11h5l-2.5 3z" fill="currentColor"/><circle cx="21.5" cy="16.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14235
|
+
bars_pattern: '<path d="M6.5 6v6.5 M6.5 19.5V22 M11.5 11v2.5 M11.5 16.5V24 M16.5 5v5.5 M16.5 18.5V21 M21.5 7v4.5 M21.5 16.5V19" stroke="currentColor" stroke-width="1.2"/><rect x="5.5" y="12.5" width="2" height="7" stroke="currentColor" stroke-width="1.2"/><rect x="10.5" y="13.5" width="2" height="3" stroke="currentColor" stroke-width="1.2"/><rect x="15.5" y="10.5" width="2" height="8" stroke="currentColor" stroke-width="1.2"/><rect x="20.5" y="11.5" width="2" height="5" stroke="currentColor" stroke-width="1.2"/>',
|
|
14236
|
+
ghost_feed: '<path d="M4.5 18 7.7 16.7 M9.7 15.9 12.7 14.7 M14.7 13.9 17.7 12.7 M19.7 11.8 22.8 10.5" stroke="currentColor" stroke-width="1.2"/><path d="M8.5 9v4.5 M8.5 18.5v2.5 M13.5 6v5 M13.5 15v5 M18.5 3v5.5 M18.5 16.5v2.5" stroke="currentColor" stroke-width="1.2"/><rect x="7.5" y="13.5" width="2" height="5" stroke="currentColor" stroke-width="1.2"/><rect x="12.5" y="11" width="2" height="4" stroke="currentColor" stroke-width="1.2"/><rect x="17.5" y="8.5" width="2" height="8" stroke="currentColor" stroke-width="1.2"/>',
|
|
14237
|
+
sector: '<path d="M5.5 8v13 M8 23.5H21 M7.6 5.1A18.4 18.4 0 0 1 23.9 21.4" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14238
|
+
anchored_vwap: '<path d="M10.5 5v4.5 M10.5 21.5V25 M17.5 2v5.5 M17.5 17.5V23" stroke="currentColor" stroke-width="1.2"/><rect x="8.5" y="9.5" width="4" height="12" stroke="currentColor" stroke-width="1.2"/><rect x="15.5" y="7.5" width="4" height="10" stroke="currentColor" stroke-width="1.2"/><path d="M5.6 15.8 7.5 14.4 14.2 15.9 25 9.7" stroke="currentColor" stroke-width="1.2"/><circle cx="4" cy="17" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14239
|
+
fixed_range_volume_profile: '<path d="M3.5 3v16 M23.5 8v16" stroke="currentColor" stroke-width="1.2"/><rect x="3.5" y="6.5" width="6" height="3" stroke="currentColor" stroke-width="1.2"/><rect x="3.5" y="9.5" width="9" height="3" stroke="currentColor" stroke-width="1.2"/><rect x="3.5" y="12.5" width="4" height="3" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="21.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14240
|
+
anchored_volume_profile: '<path d="M23.5 3v21 M9 13.5h5.5" stroke="currentColor" stroke-width="1.2"/><rect x="17.5" y="7.5" width="6" height="3" stroke="currentColor" stroke-width="1.2"/><rect x="12.5" y="10.5" width="11" height="3" stroke="currentColor" stroke-width="1.2"/><rect x="14.5" y="14.5" width="9" height="3" stroke="currentColor" stroke-width="1.2"/><rect x="20.5" y="17.5" width="3" height="3" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="13.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14241
|
+
price_range: '<path d="M4 4.5h16.5 M8.5 24.5H25 M14.5 9v14" stroke="currentColor" stroke-width="1.2"/><path d="M14.5 6l2.5 3h-5z" fill="currentColor"/><circle cx="22.5" cy="4.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="24.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14242
|
+
date_range: '<path d="M4.5 4v16.5 M24.5 8.5V25 M6 14.5h14" stroke="currentColor" stroke-width="1.2"/><path d="M20 12v5l3-2.5z" fill="currentColor"/><circle cx="4.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14243
|
+
date_and_price_range: '<path d="M4 4.5h17.5 M4.5 4v17.5 M6.5 23.5H24 M23.5 6.5V24" stroke="currentColor" stroke-width="1.2"/><path d="M13.5 9v13 M6 14.5h13" stroke="currentColor" stroke-width="1.2"/><path d="M13.5 6l2.5 3h-5z M19 12v5l3-2.5z" fill="currentColor"/><circle cx="4.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="4.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14244
|
+
brush: '<path d="M3.5 22.5c2.4-2.6 3.6-5.3 4.5-8 1.2-3.4 5.6-4.2 8.2-1.2 2.8 3.3-.3 9.2-5.5 9.2z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/><path d="M18.2 6.4 16.8 7.7c-1 .9-1 2.4-.1 3.4l1.9 1.9c1 1 2.5.9 3.4 0l5.5-5.7" stroke="currentColor" stroke-width="1.2"/>',
|
|
14245
|
+
highlighter: '<path d="M15 2.7 26 13.7 19.3 20.4 14.7 21.9a1.2 1.2 0 0 1-1.2-.3l-5.9-6a1.2 1.2 0 0 1-.3-1.2L8.4 9.3z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/><path d="M8.9 10.5 18.2 19.8" stroke="currentColor" stroke-width="1.2"/><path d="M7.9 16.9l4.2 4.2-2.6 2.6-6.1-2.4z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>',
|
|
14246
|
+
arrow_marker: '<path d="M22.7 4.6a.8.8 0 0 1 1 1l-2.5 8.3c-.2.7-1.1.8-1.5.2l-.9-1.7-12.6 10a.8.8 0 0 1-1.1-1.1l10-12.6-1.7-.9c-.6-.4-.5-1.3.2-1.5z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>',
|
|
14247
|
+
arrow: '<path d="M7.3 20.7 15 13" stroke="currentColor" stroke-width="1.2"/><path d="M21 7l-8 3 5 5z" fill="currentColor"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14248
|
+
arrow_up: '<path d="M10.5 16.5H4.8L14 5.5l9.2 11h-5.7v6h-7z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>',
|
|
14249
|
+
arrow_down: '<path d="M10.5 11.5H4.8L14 22.5l9.2-11h-5.7v-6h-7z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>',
|
|
14250
|
+
rectangle: '<path d="M7.5 5.5h13 M7.5 22.5h13 M5.5 7.5v13 M22.5 7.5v13" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14251
|
+
rotated_rectangle: '<path d="M14.7 3.6 10.5 7.8 M7.7 10.6 3.5 14.8 M3.5 18.2l6.2 6.2 M13.2 24.5l4.2-4.2 M20.2 17.5l4.2-4.2 M24.4 9.7 18.2 3.5" stroke="currentColor" stroke-width="1.2"/><circle cx="16.5" cy="2.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="9.5" cy="9.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="2.5" cy="16.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="11.5" cy="25.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="18.5" cy="18.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="25.5" cy="11.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14252
|
+
path: '<path d="M2 18.6 7.7 12.6 M11.3 12.3 14.7 15.7 M18.3 15.7 25.6 8.4 M21 7.5h5.5 M26.5 7.5V13" stroke="currentColor" stroke-width="1.2"/><circle cx="9.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="16.5" cy="17.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14253
|
+
circle: '<path d="M23.7 16.4A10 10 0 1 1 23.7 11.6" stroke="currentColor" stroke-width="1.2"/><circle cx="14" cy="14" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="24" cy="14" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14254
|
+
ellipse: '<path d="M17 6.8A11 8 0 0 1 25 12.2 M25 16.8A11 8 0 0 1 17 22.2 M12 22.2A11 8 0 0 1 4 16.8 M4 12.2A11 8 0 0 1 12 6.8" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="25.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="3.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14255
|
+
polyline: '<path d="M8.3 11.6 13.4 7.1 M16.5 5.5h4 M22.5 7.5v5 M20.5 14.5h-4 M14.5 16.5v4 M12.5 22.5h-4 M6.5 20.5v-6" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="12.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="14.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="14.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14256
|
+
triangle: '<path d="M8.5 22.5h11 M6.5 8.5v12 M7.5 8.3 19.8 21.4" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="21.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14257
|
+
arc: '<path d="M8.2 21.4 21.5 7.3" stroke="currentColor" stroke-width="1.2"/><path d="M8 23.9C12.5 26 17.8 26 21.5 23.4 M24 20C26 16 25.7 11 23.9 7.1" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="21.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14258
|
+
curve: '<path d="M6.3 20.7C6.9 17.2 8 14.3 9.7 12.1 M12.2 9.7C14.7 7.9 17.7 6.8 20.7 6.3" stroke="currentColor" stroke-width="1.2"/><circle cx="5.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="10.5" cy="10.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="22.5" cy="5.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14259
|
+
double_curve: '<path d="M6 24.9C9.8 26.5 13.3 26.5 15.7 23.6 M17.6 19.6C17.9 17.3 17 16 14.3 13.6C11.9 11.5 11.1 10.3 11.4 8.5 M12.9 5.1C15 2.6 18.1 2.5 21.6 4.1" stroke="currentColor" stroke-width="1.2"/><circle cx="4.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="16.5" cy="21.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="11.5" cy="6.5" r="2" stroke="currentColor" stroke-width="1.2"/><circle cx="23.5" cy="4.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14260
|
+
text: '<path d="M7.5 9V5.5h13V9 M14 5.5v17 M11 22.5h6" stroke="currentColor" stroke-width="1.2"/>',
|
|
14261
|
+
note: '<rect x="4.5" y="2.5" width="18" height="14" rx="1" stroke="currentColor" stroke-width="1.2"/><path d="M9.5 8V6h9v2 M14 6v7 M12 13h4 M13.5 16.5v4.5" stroke="currentColor" stroke-width="1.2"/><circle cx="13.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14262
|
+
price_note: '<rect x="4.5" y="2.5" width="18" height="14" rx="1" stroke="currentColor" stroke-width="1.2"/><path d="M13.5 16.5v4.5" stroke="currentColor" stroke-width="1.2"/><text x="14" y="13" text-anchor="middle" font-size="10" fill="currentColor">$</text><circle cx="13.5" cy="23.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14263
|
+
table: '<rect x="3.5" y="5.5" width="21" height="18" rx="1" stroke="currentColor" stroke-width="1.2"/><path d="M3.5 11.5h21 M3.5 17.5h21 M9.5 5.5v18" stroke="currentColor" stroke-width="1.2"/>',
|
|
14264
|
+
callout: '<path d="M9.6 18.5 5.5 23.5V6.5a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>',
|
|
14265
|
+
comment: '<path d="M5.5 14a7 7 0 0 1 7-7h5a7 7 0 1 1 0 14H6.5a1 1 0 0 1-1-1z" stroke="currentColor" stroke-width="1.2"/>',
|
|
14266
|
+
price_label: '<path d="M5.5 20.5v-14a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v11a1 1 0 0 1-1 1H12.6l-3.2 3.2" stroke="currentColor" stroke-width="1.2"/><circle cx="6.5" cy="22.5" r="2" stroke="currentColor" stroke-width="1.2"/>',
|
|
14267
|
+
signpost: '<circle cx="14" cy="11.5" r="9" stroke="currentColor" stroke-width="1.2"/><path d="M14 20.5V27" stroke="currentColor" stroke-width="1.2"/><path d="M14 6.2l1.5 3.1 3.4.4-2.5 2.3.6 3.4-3-1.7-3 1.7.6-3.4-2.5-2.3 3.4-.4z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>',
|
|
14268
|
+
flag: '<path d="M5.5 23V5.5h16.7l-4.6 5.25 4.6 5.25H5.5" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>',
|
|
14269
|
+
image: '<rect x="3.5" y="4.5" width="21" height="19" rx="3.5" stroke="currentColor" stroke-width="1.2"/><circle cx="10" cy="10" r="1.5" stroke="currentColor" stroke-width="1.2"/><path d="M4.2 21.5 9.3 15.1l3.3 4 M12.9 17.4 18 10.7l5.9 7.7" stroke="currentColor" stroke-width="1.2"/>',
|
|
14270
|
+
content_card: '<rect x="4.5" y="5.5" width="19" height="17" rx="2" stroke="currentColor" stroke-width="1.2"/><path d="M4.5 11.5h19 M8 15.5h9 M8 18.5h6" stroke="currentColor" stroke-width="1.2"/>',
|
|
14271
|
+
pin: '<path d="M14 3.5a7.5 7.5 0 0 1 7.5 7.5c0 4.2-4.2 8.9-7.5 12.6C10.7 19.9 6.5 15.2 6.5 11A7.5 7.5 0 0 1 14 3.5Z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/><circle cx="14" cy="11" r="3" stroke="currentColor" stroke-width="1.2"/>'
|
|
14272
|
+
};
|
|
14248
14273
|
|
|
14249
|
-
// src/ui/chrome/
|
|
14250
|
-
var
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14254
|
-
|
|
14255
|
-
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
|
|
14259
|
-
|
|
14260
|
-
|
|
14261
|
-
}
|
|
14262
|
-
|
|
14263
|
-
}
|
|
14264
|
-
|
|
14265
|
-
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
}
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
}
|
|
14279
|
-
|
|
14280
|
-
|
|
14281
|
-
|
|
14282
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
14285
|
-
|
|
14286
|
-
|
|
14287
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
14296
|
-
|
|
14297
|
-
|
|
14298
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
14301
|
-
|
|
14302
|
-
|
|
14303
|
-
|
|
14304
|
-
|
|
14305
|
-
|
|
14306
|
-
|
|
14307
|
-
if (labels.length > 0) {
|
|
14308
|
-
const row2 = h("div", { class: "qc-status-labels", "aria-hidden": "true" });
|
|
14309
|
-
for (const l of labels) {
|
|
14310
|
-
const label2 = h("span", { class: "qc-status-label qc-muted" }, l.text);
|
|
14311
|
-
label2.style.insetInlineStart = `${l.mins / 1440 * 100}%`;
|
|
14312
|
-
row2.appendChild(label2);
|
|
14313
|
-
}
|
|
14314
|
-
body.appendChild(row2);
|
|
14315
|
-
}
|
|
14316
|
-
body.appendChild(h("div", { class: "qc-status-footer qc-muted" }, exchangeTimezoneText(t, tl.timezone, new Date(nowSecs * 1e3))));
|
|
14317
|
-
},
|
|
14318
|
-
onClose() {
|
|
14319
|
-
stopUpdates();
|
|
14320
|
-
deps.onClose?.();
|
|
14321
|
-
}
|
|
14322
|
-
});
|
|
14323
|
-
timer = setInterval(() => menu2.refresh(), 6e4);
|
|
14324
|
-
offLocale = deps.i18n.onChange(() => menu2.refresh());
|
|
14325
|
-
if (!menu2.open()) stopUpdates();
|
|
14326
|
-
return menu2;
|
|
14327
|
-
}
|
|
14274
|
+
// src/ui/chrome/arrangementGlyphs.ts
|
|
14275
|
+
var ARRANGEMENT_ICONS = {
|
|
14276
|
+
"s": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" d="M2.5 1C1.67 1 1 1.67 1 2.5v12c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5h-14ZM0 2.5A2.5 2.5 0 0 1 2.5 0h14A2.5 2.5 0 0 1 19 2.5v12a2.5 2.5 0 0 1-2.5 2.5h-14A2.5 2.5 0 0 1 0 14.5v-12Z"></path>' },
|
|
14277
|
+
"2h": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v15H2.5A1.5 1.5 0 0 1 1 14.5v-12ZM10 16h6.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5H10v15ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14278
|
+
"2v": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V8H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5V9H1Zm1.5-9A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14279
|
+
"3h": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H6v15H2.5A1.5 1.5 0 0 1 1 14.5v-12ZM7 16h5V1H7v15Zm6-15v15h3.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5H13ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14280
|
+
"3v": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V5H1V2.5ZM1 6v5h17V6H1Zm17 6H1v2.5c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5V12ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14281
|
+
"3s": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v15H2.5A1.5 1.5 0 0 1 1 14.5v-12ZM10 16h6.5c.83 0 1.5-.67 1.5-1.5V9h-8v7Zm8-8V2.5c0-.83-.67-1.5-1.5-1.5H10v7h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14282
|
+
"3r": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v7H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H9V9H1Zm9 7h6.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5H10v15ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14283
|
+
"2-1": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v7H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5V9H1Zm17-1V2.5c0-.83-.67-1.5-1.5-1.5H10v7h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14284
|
+
"1-2": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V8H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H9V9H1Zm9 7h6.5c.83 0 1.5-.67 1.5-1.5V9h-8v7ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14285
|
+
"4": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v7H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H9V9H1Zm9 7h6.5c.83 0 1.5-.67 1.5-1.5V9h-8v7Zm8-8V2.5c0-.83-.67-1.5-1.5-1.5H10v7h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14286
|
+
"4v": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V4H1V2.5ZM1 5v3h17V5H1Zm17 4H1v3h17V9Zm0 4H1v1.5c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5V13ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14287
|
+
"4h": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H4v15H2.5A1.5 1.5 0 0 1 1 14.5v-12ZM5 16h4V1H5v15Zm5-15v15h4V1h-4Zm5 0v15h1.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5H15ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14288
|
+
"4s": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v15H2.5A1.5 1.5 0 0 1 1 14.5v-12ZM10 16h6.5c.83 0 1.5-.67 1.5-1.5V12h-8v4Zm8-5V6h-8v5h8Zm0-6V2.5c0-.83-.67-1.5-1.5-1.5H10v4h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14289
|
+
"4s-l": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M2 3.5C2 2.67 2.67 2 3.5 2H11v4H2V3.5ZM2 7v5h9V7H2Zm0 6v2.5c0 .83.67 1.5 1.5 1.5H11v-4H2Zm10 4h5.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5H12v15ZM3.5 1A2.5 2.5 0 0 0 1 3.5v12A2.5 2.5 0 0 0 3.5 18h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 17.5 1h-14Z"></path>' },
|
|
14290
|
+
"1-3": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V8H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H6V9H1Zm6 7h5V9H7v7Zm6 0h3.5c.83 0 1.5-.67 1.5-1.5V9h-5v7ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14291
|
+
"3-1": { viewBox: "-1 -1 21 19", body: '<g transform="matrix(1,0,0,-1,0,0)"><path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V8H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H6V9H1Zm6 7h5V9H7v7Zm6 0h3.5c.83 0 1.5-.67 1.5-1.5V9h-5v7ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path></g>' },
|
|
14292
|
+
"2-2-l": { viewBox: "0 0 19 17", body: '<path fill="currentColor" fill-rule="evenodd" d="M2.5 1C1.67 1 1 1.67 1 2.5v12c0 .83.67 1.5 1.5 1.5H5V1zM10 16H6V1h4v15m1 0h5.5c.83 0 1.5-.67 1.5-1.5V9h-7zm7-8V2.5c0-.83-.67-1.5-1.5-1.5H11v7zM0 2.5A2.5 2.5 0 0 1 2.5 0h14A2.5 2.5 0 0 1 19 2.5v12a2.5 2.5 0 0 1-2.5 2.5h-14A2.5 2.5 0 0 1 0 14.5z"></path>' },
|
|
14293
|
+
"2-2-r": { viewBox: "0 0 19 17", body: '<path fill="currentColor" fill-rule="evenodd" d="M16.5 1H14v15h2.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5M9 1h4v15H9V1M8 1H2.5C1.67 1 1 1.67 1 2.5V8h7zM1 9v5.5c0 .83.67 1.5 1.5 1.5H8V9zm1.5-9A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0z"></path>' },
|
|
14294
|
+
"2-2": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v7H1V2.5ZM1 9v3h17V9H1Zm17-1V2.5c0-.83-.67-1.5-1.5-1.5H10v7h8Zm0 5H1v1.5c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5V13ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14295
|
+
"1-4": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V8H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H4V9H1Zm4 7h4V9H5v7Zm5 0h4V9h-4v7Zm5 0h1.5c.83 0 1.5-.67 1.5-1.5V9h-3v7ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14296
|
+
"5h": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M19 3.5c0-.83-.67-1.5-1.5-1.5H17v15h.5c.83 0 1.5-.67 1.5-1.5v-12Zm-17 12c0 .83.67 1.5 1.5 1.5H4V2h-.5C2.67 2 2 2.67 2 3.5v12ZM1.01 3.24A2.5 2.5 0 0 1 3.5 1h14A2.5 2.5 0 0 1 20 3.5v12a2.5 2.5 0 0 1-2.5 2.5h-14A2.5 2.5 0 0 1 1 15.5v-12l.01-.26ZM5 17h3V2H5v15Zm11 0h-3V2h3v15ZM12 2v15H9V2h3Z"></path>' },
|
|
14297
|
+
"5v": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 3.5A2.5 2.5 0 0 1 3.5 1h14A2.5 2.5 0 0 1 20 3.5v12a2.5 2.5 0 0 1-2.5 2.5h-14A2.5 2.5 0 0 1 1 15.5v-12ZM3.5 2h14c.83 0 1.5.67 1.5 1.5V4H2v-.5C2 2.67 2.67 2 3.5 2ZM2 5v2h17V5H2Zm17 3H2v3h17V8Zm0 4H2v2h17v-2Zm0 3H2v.5c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5V15Z"></path>' },
|
|
14298
|
+
"5s": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v15H2.5A1.5 1.5 0 0 1 1 14.5v-12ZM10 16h6.5c.83 0 1.5-.67 1.5-1.5V13h-8v3Zm8-4V9h-8v3h8Zm0-4V5h-8v3h8Zm0-4V2.5c0-.83-.67-1.5-1.5-1.5H10v3h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14299
|
+
"5s-l": { viewBox: "-1 -1 21 19", body: '<g transform="matrix(-1,0,0,-1,0,0)"><path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v15H2.5A1.5 1.5 0 0 1 1 14.5v-12ZM10 16h6.5c.83 0 1.5-.67 1.5-1.5V13h-8v3Zm8-4V9h-8v3h8Zm0-4V5h-8v3h8Zm0-4V2.5c0-.83-.67-1.5-1.5-1.5H10v3h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path></g>' },
|
|
14300
|
+
"2-3": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v7H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H6V9H1Zm6 7h5V9H7v7Zm6 0h3.5c.83 0 1.5-.67 1.5-1.5V9h-5v7Zm5-8V2.5c0-.83-.67-1.5-1.5-1.5H10v7h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14301
|
+
"3-2": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M2 3.5C2 2.67 2.67 2 3.5 2H7v7H2V3.5ZM2 10v5.5c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5V10h-8v7h-1v-7H2Zm17-1V3.5c0-.83-.67-1.5-1.5-1.5H14v7h5Zm-6-7H8v7h5V2ZM3.5 1A2.5 2.5 0 0 0 1 3.5v12A2.5 2.5 0 0 0 3.5 18h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 17.5 1h-14Z"></path>' },
|
|
14302
|
+
"4-1": { viewBox: "-1 -1 21 19", body: '<g transform="matrix(-1,0,0,-1,0,0)"><path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1h14c.83 0 1.5.67 1.5 1.5V8H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H4V9H1Zm4 7h4V9H5v7Zm5 0h4V9h-4v7Zm5 0h1.5c.83 0 1.5-.67 1.5-1.5V9h-3v7ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path></g>' },
|
|
14303
|
+
"2-3-l": { viewBox: "0 0 19 17", body: '<path fill="currentColor" fill-rule="evenodd" d="M10 1H6v15h4V1m1 0v4h7V2.5c0-.83-.67-1.5-1.5-1.5zm7 5h-7v5h7zm0 6h-7v4h5.5c.83 0 1.5-.67 1.5-1.5zM2.5 1H5v15H2.5A1.5 1.5 0 0 1 1 14.5v-12C1 1.67 1.67 1 2.5 1m0-1A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0z"></path>' },
|
|
14304
|
+
"2-3-r": { viewBox: "0 0 19 17", body: '<path fill="currentColor" fill-rule="evenodd" d="M16.5 1H14v15h2.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5M9 1h4v15H9V1M8 1H2.5C1.67 1 1 1.67 1 2.5V5h7zM1 6v5h7V6zm0 6v2.5c0 .83.67 1.5 1.5 1.5H8v-4zM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0z"></path>' },
|
|
14305
|
+
"6": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H6v7H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H6V9H1Zm6 7h5V9H7v7Zm6 0h3.5c.83 0 1.5-.67 1.5-1.5V9h-5v7Zm5-8V2.5c0-.83-.67-1.5-1.5-1.5H13v7h5Zm-6-7H7v7h5V1ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14306
|
+
"6h": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M2 3.5C2 2.67 2.67 2 3.5 2H4v15h-.5A1.5 1.5 0 0 1 2 15.5v-12ZM5 17h2V2H5v15ZM8 2v15h2V2H8Zm3 0v15h2V2h-2Zm3 0v15h2V2h-2Zm3 0v15h.5c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5H17ZM3.5 1A2.5 2.5 0 0 0 1 3.5v12A2.5 2.5 0 0 0 3.5 18h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 17.5 1h-14Z"></path>' },
|
|
14307
|
+
"6v": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M1.5 4h18v1h-18V4Z"></path><path fill="currentColor" d="M2 7h18v1H2V7Z" opacity=".65"></path><path fill="currentColor" d="M1.5 10h18v1h-18v-1Z" opacity=".25"></path><path fill="currentColor" d="M1.5 13h18v1h-18v-1Z" opacity=".05"></path></g>' },
|
|
14308
|
+
"6c": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v4H1V2.5ZM1 6v5h8V6H1Zm0 6v2.5c0 .83.67 1.5 1.5 1.5H9v-4H1Zm9 4h6.5c.83 0 1.5-.67 1.5-1.5V12h-8v4Zm8-5V6h-8v5h8Zm0-6V2.5c0-.83-.67-1.5-1.5-1.5H10v4h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14309
|
+
"2-4": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 3.5A2.5 2.5 0 0 1 3.5 1h14A2.5 2.5 0 0 1 20 3.5v12a2.5 2.5 0 0 1-2.5 2.5h-14A2.5 2.5 0 0 1 1 15.5v-12ZM11 2h6.5c.83 0 1.5.67 1.5 1.5V9h-8V2Zm-1 0H3.5C2.67 2 2 2.67 2 3.5V9h8V2Zm-8 8v5.5c0 .83.67 1.5 1.5 1.5H5v-7H2Zm4 7h4v-7H6v7Zm5 0h4v-7h-4v7Zm5 0h1.5c.83 0 1.5-.67 1.5-1.5V10h-3v7Z"></path>' },
|
|
14310
|
+
"4-2": { viewBox: "0 0 19 17", body: '<path fill="currentColor" fill-rule="evenodd" d="M15 1h1.5c.83 0 1.5.67 1.5 1.5v5h-3zm-1 0h-4v6.5h4zM9 1H5v6.5h4zM4 1H2.5C1.67 1 1 1.67 1 2.5v5h3zM1 8.5v6c0 .83.67 1.5 1.5 1.5H9V8.5H1m9 7.5h6.5c.83 0 1.5-.67 1.5-1.5v-6h-8zM0 2.5A2.5 2.5 0 0 1 2.5 0h14A2.5 2.5 0 0 1 19 2.5v12a2.5 2.5 0 0 1-2.5 2.5h-14A2.5 2.5 0 0 1 0 14.5z"></path>' },
|
|
14311
|
+
"4-3": { viewBox: "0 0 19 17", body: '<path fill="currentColor" fill-rule="evenodd" d="M14 1h-4v7h4zm1 8h-2v7h3.5c.83 0 1.5-.67 1.5-1.5V9zm-3 7V9H7v7zM5 9h1v7H2.5A1.5 1.5 0 0 1 1 14.5V9h4m13-1V2.5c0-.83-.67-1.5-1.5-1.5H15v7zM1 8h3V1H2.5C1.67 1 1 1.67 1 2.5zm4 0h4V1H5zM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0z"></path>' },
|
|
14312
|
+
"7h": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M4 17V2h1v15H4Z"></path><path fill="currentColor" d="M7 17V2h1v15H7Z" opacity=".85"></path><path fill="currentColor" d="M10 17V2h1v15h-1Z" opacity=".65"></path><path fill="currentColor" d="M13 17V2h1v15h-1Z" opacity=".25"></path><path fill="currentColor" d="M16 17V2h1v15h-1Z" opacity=".05"></path></g>' },
|
|
14313
|
+
"7s": { viewBox: "0 0 19 17", body: '<g fill="currentColor"><path fill-rule="evenodd" d="M16.5 1h-14C1.67 1 1 1.67 1 2.5v12c0 .83.67 1.5 1.5 1.5h14c.83 0 1.5-.67 1.5-1.5v-12c0-.83-.67-1.5-1.5-1.5m-14-1A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0z"></path><path d="M9 3h9v1H9z"></path><path d="M9 17V1h1v16z"></path><path d="M9 6h9v1H9z" opacity=".65"></path><path d="M9 9h9v1H9z" opacity=".25"></path><path d="M9 12h9v1H9z" opacity=".05"></path></g>' },
|
|
14314
|
+
"8": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H4v7H1V2.5ZM1 9v5.5c0 .83.67 1.5 1.5 1.5H4V9H1Zm4 7h4V9H5v7Zm5 0h4V9h-4v7Zm5 0h1.5c.83 0 1.5-.67 1.5-1.5V9h-3v7Zm3-8V2.5c0-.83-.67-1.5-1.5-1.5H15v7h3Zm-4-7h-4v7h4V1ZM9 1H5v7h4V1ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14315
|
+
"8c": { viewBox: "-1 -1 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M1 2.5C1 1.67 1.67 1 2.5 1H9v3H1V2.5ZM1 5v3h8V5H1Zm0 4v3h8V9H1Zm0 4v1.5c0 .83.67 1.5 1.5 1.5H9v-3H1Zm9 3h6.5c.83 0 1.5-.67 1.5-1.5V13h-8v3Zm8-4V9h-8v3h8Zm0-4V5h-8v3h8Zm0-4V2.5c0-.83-.67-1.5-1.5-1.5H10v3h8ZM2.5 0A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0h-14Z"></path>' },
|
|
14316
|
+
"8h": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M4 17V2h1v15H4Z"></path><path fill="currentColor" d="M7 17V2h1v15H7Z" opacity=".85"></path><path fill="currentColor" d="M10 17V2h1v15h-1Z" opacity=".65"></path><path fill="currentColor" d="M13 17V2h1v15h-1Z" opacity=".25"></path><path fill="currentColor" d="M16 17V2h1v15h-1Z" opacity=".05"></path></g>' },
|
|
14317
|
+
"8v": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M1.5 4h18v1h-18V4Z"></path><path fill="currentColor" d="M2 7h18v1H2V7Z" opacity=".65"></path><path fill="currentColor" d="M1.5 10h18v1h-18v-1Z" opacity=".25"></path><path fill="currentColor" d="M1.5 13h18v1h-18v-1Z" opacity=".05"></path></g>' },
|
|
14318
|
+
"9s": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M3.5 1A2.5 2.5 0 0 0 1 3.5v12A2.5 2.5 0 0 0 3.5 18h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 17.5 1h-14ZM7 2H3.5C2.67 2 2 2.67 2 3.5V6h5V2Zm1 0v4h5V2H8Zm0 5h5v5H8V7Zm-1 5V7H2v5h5Zm-5 1h5v4H3.5A1.5 1.5 0 0 1 2 15.5V13Zm6 0h5v4H8v-4Zm6 0v4h3.5c.83 0 1.5-.67 1.5-1.5V13h-5Zm5-1V7h-5v5h5ZM14 2v4h5V3.5c0-.83-.67-1.5-1.5-1.5H14Z"></path>' },
|
|
14319
|
+
"5-4": { viewBox: "0 0 19 17", body: '<path fill="currentColor" fill-rule="evenodd" d="M7 1H4v7h3zm1 0v7h3V1zm4 0v7h3V1zm0 8h-2v7h4V9zm3 0h3v5.5c0 .83-.67 1.5-1.5 1.5H15zm1-8v7h2V2.5c0-.83-.67-1.5-1.5-1.5zM8 9H5v7h4V9zM2.5 1H3v7H1V2.5C1 1.67 1.67 1 2.5 1M1 9h3v7H2.5A1.5 1.5 0 0 1 1 14.5zm1.5-9A2.5 2.5 0 0 0 0 2.5v12A2.5 2.5 0 0 0 2.5 17h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 16.5 0z"></path>' },
|
|
14320
|
+
"9h": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M4 17V2h1v15H4Z"></path><path fill="currentColor" d="M7 17V2h1v15H7Z" opacity=".85"></path><path fill="currentColor" d="M10 17V2h1v15h-1Z" opacity=".65"></path><path fill="currentColor" d="M13 17V2h1v15h-1Z" opacity=".25"></path><path fill="currentColor" d="M16 17V2h1v15h-1Z" opacity=".05"></path></g>' },
|
|
14321
|
+
"9v": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M1.5 4h18v1h-18V4Z"></path><path fill="currentColor" d="M2 7h18v1H2V7Z" opacity=".65"></path><path fill="currentColor" d="M1.5 10h18v1h-18v-1Z" opacity=".25"></path><path fill="currentColor" d="M1.5 13h18v1h-18v-1Z" opacity=".05"></path></g>' },
|
|
14322
|
+
"10c5": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M2 3.5C2 2.67 2.67 2 3.5 2H4v7H2V3.5ZM2 10v5.5c0 .83.67 1.5 1.5 1.5H4v-7H2Zm3 7h3v-7H5v7Zm4 0h3v-7H9v7Zm4 0h3v-7h-3v7Zm4 0h.5c.83 0 1.5-.67 1.5-1.5V10h-2v7Zm2-8V3.5c0-.83-.67-1.5-1.5-1.5H17v7h2Zm-3-7h-3v7h3V2Zm-4 0H9v7h3V2ZM8 2H5v7h3V2ZM3.5 1A2.5 2.5 0 0 0 1 3.5v12A2.5 2.5 0 0 0 3.5 18h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 17.5 1h-14Z"></path>' },
|
|
14323
|
+
"10h": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M4 17V2h1v15H4Z"></path><path fill="currentColor" d="M7 17V2h1v15H7Z" opacity=".85"></path><path fill="currentColor" d="M10 17V2h1v15h-1Z" opacity=".65"></path><path fill="currentColor" d="M13 17V2h1v15h-1Z" opacity=".25"></path><path fill="currentColor" d="M16 17V2h1v15h-1Z" opacity=".05"></path></g>' },
|
|
14324
|
+
"10v": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M1.5 4h18v1h-18V4Z"></path><path fill="currentColor" d="M2 7h18v1H2V7Z" opacity=".65"></path><path fill="currentColor" d="M1.5 10h18v1h-18v-1Z" opacity=".25"></path><path fill="currentColor" d="M1.5 13h18v1h-18v-1Z" opacity=".05"></path></g>' },
|
|
14325
|
+
"12c6": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M2 3.5C2 2.67 2.67 2 3.5 2H4v7H2V3.5ZM2 10v5.5c0 .83.67 1.5 1.5 1.5H4v-7H2Zm3 7h2v-7H5v7Zm3 0h2v-7H8v7Zm3 0h2v-7h-2v7Zm3 0h2v-7h-2v7Zm3 0h.5c.83 0 1.5-.67 1.5-1.5V10h-2v7Zm2-8V3.5c0-.83-.67-1.5-1.5-1.5H17v7h2Zm-3-7h-2v7h2V2Zm-3 0h-2v7h2V2Zm-3 0H8v7h2V2ZM7 2H5v7h2V2ZM3.5 1A2.5 2.5 0 0 0 1 3.5v12A2.5 2.5 0 0 0 3.5 18h14a2.5 2.5 0 0 0 2.5-2.5v-12A2.5 2.5 0 0 0 17.5 1h-14Z"></path>' },
|
|
14326
|
+
"12c4": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M2 3.5C2 2.67 2.67 2 3.5 2H7v3H2v1h5v3H2v1h5v3H2v1h5v3H3.5A1.5 1.5 0 0 1 2 15.5v-12ZM8 14v3h5v-3H8Zm6 0v3h3.5c.83 0 1.5-.67 1.5-1.5V14h-5Zm5-1h-5v-3h5v3Zm-6 0H8v-3h5v3ZM8 9h5V6H8v3Zm6 0h5V6h-5v3Zm-1-4H8V2h5v3Zm1 13H3.5A2.5 2.5 0 0 1 1 15.5v-12A2.5 2.5 0 0 1 3.5 1h14A2.5 2.5 0 0 1 20 3.5v12a2.5 2.5 0 0 1-2.5 2.5H14Zm0-13V2h3.5c.83 0 1.5.67 1.5 1.5V5h-5Z"></path>' },
|
|
14327
|
+
"12h": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M4 17V2h1v15H4Z"></path><path fill="currentColor" d="M7 17V2h1v15H7Z" opacity=".85"></path><path fill="currentColor" d="M10 17V2h1v15h-1Z" opacity=".65"></path><path fill="currentColor" d="M13 17V2h1v15h-1Z" opacity=".25"></path><path fill="currentColor" d="M16 17V2h1v15h-1Z" opacity=".05"></path></g>' },
|
|
14328
|
+
"14c7": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M19 10H2V9h17v1Z"></path><path fill="currentColor" d="M4 17V2h1v15H4Z"></path><path fill="currentColor" d="M7 17V2h1v15H7Z" opacity=".85"></path><path fill="currentColor" d="M10 17V2h1v15h-1Z" opacity=".65"></path><path fill="currentColor" d="M13 17V2h1v15h-1Z" opacity=".25"></path><path fill="currentColor" d="M16 18V2h1v16h-1Z" opacity=".05"></path></g>' },
|
|
14329
|
+
"16c8": { viewBox: "0 0 21 19", body: '<g fill="none"><rect width="18" height="16" stroke="currentColor" rx="2" x="1.5" y="1.5"></rect><path fill="currentColor" d="M19 10H2V9h17v1Z"></path><path fill="currentColor" d="M4 17V2h1v15H4Z"></path><path fill="currentColor" d="M7 17V2h1v15H7Z" opacity=".85"></path><path fill="currentColor" d="M10 17V2h1v15h-1Z" opacity=".65"></path><path fill="currentColor" d="M13 17V2h1v15h-1Z" opacity=".25"></path><path fill="currentColor" d="M16 18V2h1v16h-1Z" opacity=".05"></path></g>' },
|
|
14330
|
+
"16c4": { viewBox: "0 0 21 19", body: '<path fill="currentColor" fill-rule="evenodd" d="M3.5 2C2.67 2 2 2.67 2 3.5v12c0 .83.67 1.5 1.5 1.5H5v-3H2v-1h3v-3H2V9h3V6H2V5h3V2H3.5ZM6 14v3h4v-3H6Zm4-1H6v-3h4v3Zm1 1v3h4v-3h-4Zm4-1h-4v-3h4v3Zm1 1v3h1.5c.83 0 1.5-.67 1.5-1.5V14h-3Zm3-1h-3v-3h3v3Zm-8-4h4V6h-4v3Zm5-3v3h3V6h-3ZM6 9h4V6H6v3Zm0-4h4V2H6v3Zm10 13H3.5A2.5 2.5 0 0 1 1 15.5v-12A2.5 2.5 0 0 1 3.5 1h14A2.5 2.5 0 0 1 20 3.5v12a2.5 2.5 0 0 1-2.5 2.5H16Zm0-13V2h1.5c.83 0 1.5.67 1.5 1.5V5h-3Zm-1-3h-4v3h4V2Z"></path>' }
|
|
14331
|
+
};
|
|
14328
14332
|
|
|
14329
|
-
// src/
|
|
14330
|
-
var
|
|
14331
|
-
var
|
|
14332
|
-
|
|
14333
|
-
|
|
14334
|
-
|
|
14335
|
-
|
|
14336
|
-
|
|
14337
|
-
|
|
14338
|
-
|
|
14339
|
-
|
|
14340
|
-
|
|
14341
|
-
|
|
14342
|
-
|
|
14333
|
+
// src/ui/icons/catalog.ts
|
|
14334
|
+
var byMeaning = (table) => table;
|
|
14335
|
+
var CONTROL_ICONS = byMeaning({
|
|
14336
|
+
// The top bar and the widget's menus.
|
|
14337
|
+
compare: [ICONS.comparePlus],
|
|
14338
|
+
indicators: [ICONS.indicators],
|
|
14339
|
+
replay: [ICONS.replay],
|
|
14340
|
+
undo: [ICONS.undo],
|
|
14341
|
+
redo: [ICONS.redo],
|
|
14342
|
+
settings: [ICONS.settings, ICONS.gear, ICONS.legendSettings],
|
|
14343
|
+
fullscreen: [ICONS.fullscreen],
|
|
14344
|
+
fullscreenExit: [ICONS.exitFullscreen],
|
|
14345
|
+
image: [ICONS.camera],
|
|
14346
|
+
download: [ICONS.download],
|
|
14347
|
+
copy: [ICONS.copy],
|
|
14348
|
+
caret: [ICONS.menuArrowWide],
|
|
14349
|
+
info: [ICONS.info],
|
|
14350
|
+
// The legend.
|
|
14351
|
+
visible: [ICONS.legendEye],
|
|
14352
|
+
hidden: [ICONS.legendEyeOff],
|
|
14353
|
+
collapse: [ICONS.legendChevron],
|
|
14354
|
+
paneCollapse: [ICONS.paneCollapse],
|
|
14355
|
+
paneRestore: [ICONS.paneRestore],
|
|
14356
|
+
paneMaximize: [ICONS.paneMaximize],
|
|
14357
|
+
marketStatus: [ICONS.marketStatus],
|
|
14358
|
+
replayStatus: [ICONS.replayStatus],
|
|
14359
|
+
replayMark: [ICONS.replayMark],
|
|
14360
|
+
replayCut: [ICONS.replayCut],
|
|
14361
|
+
// The navigation cluster.
|
|
14362
|
+
zoomIn: [ICONS.navZoomIn],
|
|
14363
|
+
zoomOut: [ICONS.navZoomOut],
|
|
14364
|
+
scroll: [ICONS.navScroll],
|
|
14365
|
+
reset: [ICONS.navReset],
|
|
14366
|
+
tileMaximize: [ICONS.tileMaximize],
|
|
14367
|
+
tileRestore: [ICONS.tileRestore],
|
|
14368
|
+
// Rows, lists and dialogs.
|
|
14369
|
+
check: [ICONS.check],
|
|
14370
|
+
close: [ICONS.close, ICONS.closeThin, ICONS.dialogClose],
|
|
14371
|
+
remove: [ICONS.close18, ICONS.removeRow],
|
|
14372
|
+
delete: [ICONS.trash, ICONS.trash28],
|
|
14373
|
+
add: [ICONS.plus, ICONS.plusThin, ICONS.plus24],
|
|
14374
|
+
search: [ICONS.search, ICONS.search24],
|
|
14375
|
+
clear: [ICONS.clear],
|
|
14376
|
+
open: [ICONS.folder],
|
|
14377
|
+
rename: [ICONS.pencil],
|
|
14378
|
+
duplicate: [ICONS.clone],
|
|
14379
|
+
favorite: [ICONS.star, ICONS.pickerStar],
|
|
14380
|
+
favorited: [ICONS.starFilled, ICONS.pickerStarFilled],
|
|
14381
|
+
sortAscending: [ICONS.sortUp, ICONS.sortUpRow],
|
|
14382
|
+
sortDescending: [ICONS.sortDown, ICONS.sortDownRow],
|
|
14383
|
+
chevronUp: [ICONS.chevronUp],
|
|
14384
|
+
chevronDown: [ICONS.chevronDown, ICONS.chevronDown18],
|
|
14385
|
+
chevronLeft: [ICONS.chevronLeft],
|
|
14386
|
+
chevronRight: [ICONS.chevronRight],
|
|
14387
|
+
// The drawing toolbar's arrow, pointing where the flyout it opens will stand.
|
|
14388
|
+
flyout: [ICONS.chevronRight16],
|
|
14389
|
+
submenu: [ICONS.submenuArrow],
|
|
14390
|
+
more: [ICONS.kebab],
|
|
14391
|
+
grip: [ICONS.grip],
|
|
14392
|
+
emptySearch: [SEARCH_EMPTY_MARK],
|
|
14393
|
+
emptyCompare: [COMPARE_EMPTY_MARK],
|
|
14394
|
+
// The symbol search's spread builder.
|
|
14395
|
+
operatorsShow: [ICONS.spreadOpsShow],
|
|
14396
|
+
operatorsHide: [ICONS.spreadOpsHide],
|
|
14397
|
+
operatorAdd: [OPERATOR_GLYPHS.addition],
|
|
14398
|
+
operatorSubtract: [OPERATOR_GLYPHS.subtraction],
|
|
14399
|
+
operatorMultiply: [OPERATOR_GLYPHS.multiplication],
|
|
14400
|
+
operatorDivide: [OPERATOR_GLYPHS.division],
|
|
14401
|
+
operatorPower: [OPERATOR_GLYPHS.exponentiation],
|
|
14402
|
+
operatorReciprocal: [OPERATOR_GLYPHS.reciprocal],
|
|
14403
|
+
// The replay transport.
|
|
14404
|
+
play: [ICONS.play],
|
|
14405
|
+
pause: [ICONS.pause],
|
|
14406
|
+
stepForward: [ICONS.stepForward],
|
|
14407
|
+
stepBack: [ICONS.stepBack],
|
|
14408
|
+
goLive: [ICONS.goLive],
|
|
14409
|
+
selectBar: [ICONS.selectBar],
|
|
14410
|
+
selectDate: [ICONS.calendar],
|
|
14411
|
+
firstAvailable: [ICONS.firstAvailable],
|
|
14412
|
+
randomBar: [ICONS.randomBar],
|
|
14413
|
+
// The drawing toolbar, its menus, the favorites bar and the drawing settings.
|
|
14414
|
+
cursorCross: [ICONS.cursorCross],
|
|
14415
|
+
cursorDot: [ICONS.cursorDot],
|
|
14416
|
+
cursorArrow: [ICONS.cursorArrow],
|
|
14417
|
+
eraser: [ICONS.eraser],
|
|
14418
|
+
measure: [ICONS.ruler],
|
|
14419
|
+
zoomTool: [ICONS.zoomIn],
|
|
14420
|
+
magnet: [ICONS.magnet],
|
|
14421
|
+
magnetStrong: [ICONS.magnetStrong],
|
|
14422
|
+
stayInMode: [ICONS.pin],
|
|
14423
|
+
stayInModeOn: [ICONS.pinOn],
|
|
14424
|
+
locked: [ICONS.lockClosed],
|
|
14425
|
+
unlocked: [ICONS.lockOpen],
|
|
14426
|
+
drawingsShown: [ICONS.drawingsShown],
|
|
14427
|
+
drawingsHidden: [ICONS.drawingsHidden],
|
|
14428
|
+
indicatorsShown: [ICONS.indicatorsShown],
|
|
14429
|
+
indicatorsHidden: [ICONS.indicatorsHidden],
|
|
14430
|
+
allShown: [ICONS.allShown],
|
|
14431
|
+
allHidden: [ICONS.allHidden],
|
|
14432
|
+
hide: [ICONS.eyeCrossed],
|
|
14433
|
+
sync: [ICONS.sync],
|
|
14434
|
+
glyphTools: [ICONS.groupGlyphs],
|
|
14435
|
+
favoritesBar: [ICONS.favoritesBar],
|
|
14436
|
+
template: [ICONS.template],
|
|
14437
|
+
visualOrder: [ICONS.layers],
|
|
14438
|
+
lineColor: [ICONS.pencil16],
|
|
14439
|
+
fillColor: [ICONS.bucket],
|
|
14440
|
+
textColor: [ICONS.textTee],
|
|
14441
|
+
lineSolid: [ICONS.lineSolid],
|
|
14442
|
+
lineDashed: [ICONS.lineDashed],
|
|
14443
|
+
lineDotted: [ICONS.lineDotted],
|
|
14444
|
+
lineThickness1: [ICONS.lineThickness1],
|
|
14445
|
+
lineThickness2: [ICONS.lineThickness2],
|
|
14446
|
+
lineThickness3: [ICONS.lineThickness3],
|
|
14447
|
+
lineThickness4: [ICONS.lineThickness4],
|
|
14448
|
+
// Drawn for a line's left end; the right end wears the same drawing mirrored.
|
|
14449
|
+
lineEndNormal: [ICONS.lineEndNormal],
|
|
14450
|
+
lineEndArrow: [ICONS.lineEndArrow]
|
|
14451
|
+
});
|
|
14452
|
+
var MIRRORED_ICONS = /* @__PURE__ */ new Set(["flyout"]);
|
|
14453
|
+
var MINIATURE_TOOLS = Object.keys(TOOL_ICONS);
|
|
14454
|
+
var ARRANGEMENT_CODES = Object.keys(ARRANGEMENT_ICONS);
|
|
14455
|
+
var toolGlyphs = new Map(MINIATURE_TOOLS.map((type) => [type, { viewBox: "0 0 28 28", body: TOOL_ICONS[type] }]));
|
|
14456
|
+
var arrangementGlyphs = new Map(ARRANGEMENT_CODES.map((code) => [code, { viewBox: ARRANGEMENT_ICONS[code].viewBox, body: ARRANGEMENT_ICONS[code].body }]));
|
|
14457
|
+
var toolGlyph = (type) => toolGlyphs.get(type);
|
|
14458
|
+
var arrangementGlyphOf = (code) => arrangementGlyphs.get(code);
|
|
14459
|
+
var CHART_ICON_IDS = [
|
|
14460
|
+
...Object.keys(CONTROL_ICONS),
|
|
14461
|
+
...CHART_STYLES.map((style) => `style.${style}`),
|
|
14462
|
+
...MINIATURE_TOOLS.map((type) => `tool.${type}`),
|
|
14463
|
+
...ARRANGEMENT_CODES.map((code) => `layout.${code}`)
|
|
14464
|
+
];
|
|
14465
|
+
var PUBLISHED = new Set(CHART_ICON_IDS);
|
|
14466
|
+
var ICON_OF = /* @__PURE__ */ new WeakMap();
|
|
14467
|
+
for (const [id, glyphs] of Object.entries(CONTROL_ICONS)) for (const mark of glyphs) ICON_OF.set(mark, id);
|
|
14468
|
+
for (const style of CHART_STYLES) ICON_OF.set(STYLE_ICONS[style], `style.${style}`);
|
|
14469
|
+
for (const type of MINIATURE_TOOLS) ICON_OF.set(toolGlyphs.get(type), `tool.${type}`);
|
|
14470
|
+
for (const code of ARRANGEMENT_CODES) ICON_OF.set(arrangementGlyphs.get(code), `layout.${code}`);
|
|
14471
|
+
var iconOf = (mark) => ICON_OF.get(mark);
|
|
14472
|
+
var GLYPHS_OF = new Map([
|
|
14473
|
+
...Object.entries(CONTROL_ICONS),
|
|
14474
|
+
...CHART_STYLES.map((style) => [`style.${style}`, [STYLE_ICONS[style]]]),
|
|
14475
|
+
...MINIATURE_TOOLS.map((type) => [`tool.${type}`, [toolGlyphs.get(type)]]),
|
|
14476
|
+
...ARRANGEMENT_CODES.map((code) => [`layout.${code}`, [arrangementGlyphs.get(code)]])
|
|
14477
|
+
]);
|
|
14478
|
+
var standsAlone = (mark) => !/var\(--|class=/.test(mark.body);
|
|
14479
|
+
function chartIconArtwork(id) {
|
|
14480
|
+
const glyphs = GLYPHS_OF.get(id) ?? [];
|
|
14481
|
+
if (!glyphs.every(standsAlone)) return [];
|
|
14482
|
+
return glyphs.map((mark) => ({
|
|
14483
|
+
viewBox: mark.viewBox,
|
|
14484
|
+
body: mark.body,
|
|
14485
|
+
svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${mark.viewBox}" fill="none">${mark.body}</svg>`
|
|
14486
|
+
}));
|
|
14343
14487
|
}
|
|
14344
|
-
|
|
14345
|
-
|
|
14346
|
-
|
|
14347
|
-
|
|
14348
|
-
|
|
14349
|
-
|
|
14488
|
+
function checkIcons(icons) {
|
|
14489
|
+
if (icons === void 0) return;
|
|
14490
|
+
if (typeof icons !== "object" || icons === null || Array.isArray(icons)) throw new TypeError("icons must be an object");
|
|
14491
|
+
for (const [id, factory] of Object.entries(icons)) {
|
|
14492
|
+
if (!PUBLISHED.has(id)) throw new TypeError(`icons.${id} is not an icon the chart draws; CHART_ICON_IDS lists every one`);
|
|
14493
|
+
if (factory !== void 0 && typeof factory !== "function") throw new TypeError(`icons.${id} must be a function that draws the icon`);
|
|
14350
14494
|
}
|
|
14351
|
-
const points = Math.round(fraction * 1e4) / 100;
|
|
14352
|
-
return `${points > 0 ? "+" : ""}${writer.format(points)}`;
|
|
14353
14495
|
}
|
|
14354
|
-
|
|
14355
|
-
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
|
|
14359
|
-
|
|
14360
|
-
|
|
14361
|
-
|
|
14362
|
-
|
|
14363
|
-
|
|
14364
|
-
|
|
14365
|
-
|
|
14366
|
-
|
|
14367
|
-
const paneKeys = () => {
|
|
14368
|
-
const keys = { 0: "main" };
|
|
14369
|
-
for (const [id, pane] of Object.entries(deps.indicators.renderer.paneOf())) if (pane > 0) keys[pane] = `indicator:${id}`;
|
|
14370
|
-
for (const entry of deps.compare?.api.list() ?? []) {
|
|
14371
|
-
const pane = deps.compare.handle.paneIndexOf(entry.symbol);
|
|
14372
|
-
if (pane !== null && pane > 0) keys[pane] = `compare:${entry.symbol}`;
|
|
14496
|
+
|
|
14497
|
+
// src/ui/icons/resolver.ts
|
|
14498
|
+
function createIconResolver(deps) {
|
|
14499
|
+
checkIcons(deps.icons);
|
|
14500
|
+
const icons = deps.icons ?? {};
|
|
14501
|
+
const standing = /* @__PURE__ */ new Set();
|
|
14502
|
+
const forget = new FinalizationRegistry((record3) => standing.delete(record3));
|
|
14503
|
+
const draw = (factory, box, icon) => {
|
|
14504
|
+
const direction = deps.direction();
|
|
14505
|
+
const drawn = drawHostIcon(factory, { document: deps.document, width: box.width, height: box.height, direction });
|
|
14506
|
+
if ("failure" in drawn) {
|
|
14507
|
+
deps.diagnostics.report(icon, drawn.failure);
|
|
14508
|
+
return null;
|
|
14373
14509
|
}
|
|
14374
|
-
|
|
14510
|
+
const record3 = { element: new WeakRef(drawn.element), factory, box, icon, direction };
|
|
14511
|
+
standing.add(record3);
|
|
14512
|
+
forget.register(drawn.element, record3, record3);
|
|
14513
|
+
return drawn.element;
|
|
14375
14514
|
};
|
|
14376
|
-
|
|
14377
|
-
|
|
14378
|
-
|
|
14379
|
-
|
|
14380
|
-
|
|
14381
|
-
|
|
14382
|
-
|
|
14383
|
-
|
|
14384
|
-
|
|
14385
|
-
if (
|
|
14386
|
-
|
|
14387
|
-
|
|
14388
|
-
if (entry) deps.commands.execute("chart.compare.setVisible", { symbol, visible: !entry.visible });
|
|
14389
|
-
return;
|
|
14390
|
-
}
|
|
14391
|
-
deps.commands.execute(deps.indicators.isHidden(id) ? "chart.indicators.show" : "chart.indicators.hide", id);
|
|
14392
|
-
},
|
|
14393
|
-
onTitle: (id) => {
|
|
14394
|
-
if (id.startsWith(COMPARE_ROW_PREFIX)) deps.commands.execute("chart.compare.changeSymbol", id.slice(COMPARE_ROW_PREFIX.length));
|
|
14395
|
-
},
|
|
14396
|
-
onRemove: (id) => {
|
|
14397
|
-
if (id.startsWith(COMPARE_ROW_PREFIX)) deps.commands.execute("chart.compare.remove", id.slice(COMPARE_ROW_PREFIX.length));
|
|
14398
|
-
else deps.commands.execute("chart.indicators.remove", id);
|
|
14399
|
-
},
|
|
14400
|
-
...deps.symbolSearch ? { onSymbol: () => deps.openSearch() } : {},
|
|
14401
|
-
painters: deps.painters,
|
|
14402
|
-
icons: deps.icons,
|
|
14403
|
-
...deps.marketStatus ? {
|
|
14404
|
-
onStatus: (anchor) => {
|
|
14405
|
-
if (status2) {
|
|
14406
|
-
status2.close();
|
|
14407
|
-
return;
|
|
14408
|
-
}
|
|
14409
|
-
status2 = openMarketStatus(anchor, {
|
|
14410
|
-
host: deps.chrome,
|
|
14411
|
-
i18n: deps.i18n,
|
|
14412
|
-
model: deps.sessionModel,
|
|
14413
|
-
status: deps.status,
|
|
14414
|
-
onClose: () => {
|
|
14415
|
-
status2 = null;
|
|
14416
|
-
}
|
|
14417
|
-
});
|
|
14418
|
-
}
|
|
14419
|
-
} : {},
|
|
14420
|
-
onSettings: (id, rect) => {
|
|
14421
|
-
const host2 = hostRows.get(id);
|
|
14422
|
-
if (host2) {
|
|
14423
|
-
host2.onSettings?.();
|
|
14424
|
-
return;
|
|
14425
|
-
}
|
|
14426
|
-
if (deps.openIndicatorSettings(id)) return;
|
|
14427
|
-
const inst = deps.indicators.list().find((i) => i.id === id);
|
|
14428
|
-
if (!inst) return;
|
|
14429
|
-
openInputsEditor(
|
|
14430
|
-
deps.chrome,
|
|
14431
|
-
rect,
|
|
14432
|
-
inst.definition.manifest.inputs ?? {},
|
|
14433
|
-
{ ...manifestInputDefaults(inst.definition.manifest), ...inst.inputs },
|
|
14434
|
-
(patch) => deps.indicators.patchInputs(id, patch),
|
|
14435
|
-
deps.i18n
|
|
14436
|
-
);
|
|
14437
|
-
},
|
|
14438
|
-
onPaneOp: (id, op) => {
|
|
14439
|
-
const paneIdx = deps.indicators.renderer.paneOf()[id];
|
|
14440
|
-
if (paneIdx === void 0 || paneIdx === 0) return;
|
|
14441
|
-
const panes = deps.chart.panes();
|
|
14442
|
-
const heights = {};
|
|
14443
|
-
panes.forEach((p, i) => heights[i] = p.getHeight());
|
|
14444
|
-
const keys = paneKeys();
|
|
14445
|
-
const remembered = {};
|
|
14446
|
-
for (const [index, key] of Object.entries(keys)) {
|
|
14447
|
-
const height = paneRemembered.get(key);
|
|
14448
|
-
if (height !== void 0) remembered[Number(index)] = height;
|
|
14449
|
-
}
|
|
14450
|
-
const plan = planPaneOp({ heights, remembered }, { kind: op, pane: paneIdx });
|
|
14451
|
-
paneRemembered.clear();
|
|
14452
|
-
for (const [index, height] of Object.entries(plan.remembered)) {
|
|
14453
|
-
const key = keys[Number(index)];
|
|
14454
|
-
if (key) paneRemembered.set(key, height);
|
|
14455
|
-
}
|
|
14456
|
-
for (const [i, h2] of Object.entries(plan.apply)) {
|
|
14457
|
-
const index = Number(i);
|
|
14458
|
-
panes[index]?.setHeight(h2);
|
|
14459
|
-
if (index > 0) deps.indicators.setPaneCollapsed(index, h2 <= COLLAPSED_H);
|
|
14515
|
+
const host2 = (id, box) => {
|
|
14516
|
+
const factory = icons[id];
|
|
14517
|
+
return factory ? draw(factory, box, id) : null;
|
|
14518
|
+
};
|
|
14519
|
+
const redraw = () => {
|
|
14520
|
+
const direction = deps.direction();
|
|
14521
|
+
for (const record3 of [...standing]) {
|
|
14522
|
+
if (record3.direction === direction) continue;
|
|
14523
|
+
const element = record3.element.deref();
|
|
14524
|
+
if (!element) {
|
|
14525
|
+
standing.delete(record3);
|
|
14526
|
+
continue;
|
|
14460
14527
|
}
|
|
14461
|
-
|
|
14528
|
+
if (!element.parentNode) continue;
|
|
14529
|
+
const fresh = draw(record3.factory, record3.box, record3.icon);
|
|
14530
|
+
if (!fresh) continue;
|
|
14531
|
+
element.replaceWith(fresh);
|
|
14532
|
+
standing.delete(record3);
|
|
14533
|
+
forget.unregister(record3);
|
|
14462
14534
|
}
|
|
14463
|
-
}
|
|
14464
|
-
|
|
14465
|
-
const
|
|
14466
|
-
|
|
14467
|
-
|
|
14468
|
-
|
|
14469
|
-
|
|
14470
|
-
|
|
14471
|
-
|
|
14472
|
-
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
high: format2.format(bar.h),
|
|
14476
|
-
low: format2.format(bar.l),
|
|
14477
|
-
close: format2.format(bar.c),
|
|
14478
|
-
change: change === null ? null : `${change > 0 ? "+" : ""}${format2.format(change)}`,
|
|
14479
|
-
percent: fraction === null ? null : percentText(fraction, deps.i18n.tag()),
|
|
14480
|
-
direction: change === null || change === 0 ? "flat" : change > 0 ? "up" : "down"
|
|
14481
|
-
};
|
|
14482
|
-
}
|
|
14483
|
-
const paint = () => {
|
|
14484
|
-
if (destroyed) return;
|
|
14485
|
-
const alive = new Set(Object.values(paneKeys()));
|
|
14486
|
-
for (const key of paneRemembered.keys()) if (!alive.has(key)) paneRemembered.delete(key);
|
|
14487
|
-
legend2?.setValueShaped(deps.valueShaped());
|
|
14488
|
-
legend2?.setQuote(deps.legendValues ? reading() : null);
|
|
14489
|
-
const paneOf = deps.indicators.renderer.paneOf();
|
|
14490
|
-
const shown2 = (command2) => deps.shown?.(command2) ?? true;
|
|
14491
|
-
legend2?.setChips([
|
|
14492
|
-
...deps.indicators.chipsAt(hovered).map((row2) => {
|
|
14493
|
-
const paneIndex = paneOf[row2.id] ?? 0;
|
|
14494
|
-
const remembered = paneRemembered.get(`indicator:${row2.id}`);
|
|
14495
|
-
return {
|
|
14496
|
-
...row2,
|
|
14497
|
-
paneIndex,
|
|
14498
|
-
maximized: remembered !== void 0 && !row2.collapsed && (deps.chart.panes()[paneIndex]?.getHeight() ?? 0) > remembered,
|
|
14499
|
-
...shown2(row2.hidden ? "chart.indicators.show" : "chart.indicators.hide") ? {} : { hideable: false },
|
|
14500
|
-
...shown2("chart.indicators.remove") ? {} : { removable: false }
|
|
14501
|
-
};
|
|
14502
|
-
}),
|
|
14503
|
-
...(deps.compare?.chips(hovered) ?? []).map((row2) => ({
|
|
14504
|
-
...row2,
|
|
14505
|
-
paneIndex: deps.compare.handle.paneIndexOf(row2.id.slice(COMPARE_ROW_PREFIX.length)) ?? 0,
|
|
14506
|
-
...shown2("chart.compare.setVisible") ? {} : { hideable: false },
|
|
14507
|
-
...shown2("chart.compare.remove") ? {} : { removable: false }
|
|
14508
|
-
})),
|
|
14509
|
-
...[...hostRows].map(([id, row2]) => ({
|
|
14510
|
-
id,
|
|
14511
|
-
title: row2.title,
|
|
14512
|
-
inputs: row2.inputs,
|
|
14513
|
-
value: null,
|
|
14514
|
-
note: row2.status,
|
|
14515
|
-
description: row2.description,
|
|
14516
|
-
settingsLabel: row2.settingsLabel,
|
|
14517
|
-
hidden: false,
|
|
14518
|
-
hideable: false,
|
|
14519
|
-
removable: false,
|
|
14520
|
-
hasInputs: !!row2.onSettings,
|
|
14521
|
-
paneIndex: 0
|
|
14522
|
-
}))
|
|
14523
|
-
]);
|
|
14524
|
-
const tops = {};
|
|
14525
|
-
let top = 0;
|
|
14526
|
-
const panes = deps.chart.panes();
|
|
14527
|
-
const first = panes[0]?.getHTMLElement()?.getBoundingClientRect();
|
|
14528
|
-
for (const [index, pane] of panes.entries()) {
|
|
14529
|
-
const element = pane.getHTMLElement();
|
|
14530
|
-
const rect = element?.getBoundingClientRect();
|
|
14531
|
-
tops[index] = rect && first && rect.height > 0 ? rect.top - first.top : top;
|
|
14532
|
-
top += pane.getHeight();
|
|
14533
|
-
if (element && !observed.has(element)) {
|
|
14534
|
-
observed.add(element);
|
|
14535
|
-
resize?.observe(element);
|
|
14535
|
+
};
|
|
14536
|
+
const glyph2 = (mark, options = {}) => {
|
|
14537
|
+
const id = iconOf(mark);
|
|
14538
|
+
if (id) {
|
|
14539
|
+
const width = options.size ?? mark.size ?? 28;
|
|
14540
|
+
const drawn = host2(id, { width, height: options.height ?? width });
|
|
14541
|
+
if (drawn) {
|
|
14542
|
+
const span = deps.document.createElement("span");
|
|
14543
|
+
span.className = `qc-icon${options.className ? ` ${options.className}` : ""}`;
|
|
14544
|
+
span.setAttribute("aria-hidden", "true");
|
|
14545
|
+
span.append(drawn);
|
|
14546
|
+
return span;
|
|
14536
14547
|
}
|
|
14537
14548
|
}
|
|
14538
|
-
|
|
14539
|
-
for (const element of observed) if (!current.has(element)) {
|
|
14540
|
-
resize?.unobserve(element);
|
|
14541
|
-
observed.delete(element);
|
|
14542
|
-
}
|
|
14543
|
-
legend2?.setPaneTops(tops);
|
|
14544
|
-
try {
|
|
14545
|
-
const start = deps.chart.priceScale("left").width();
|
|
14546
|
-
const end = deps.chart.priceScale("right").width();
|
|
14547
|
-
legend2?.setScaleInsets(start, end, deps.chart.timeScale().height());
|
|
14548
|
-
deps.chrome.style.setProperty("--qcp-plot-start", `${start}px`);
|
|
14549
|
-
deps.chrome.style.setProperty("--qcp-plot-end", `${end}px`);
|
|
14550
|
-
} catch {
|
|
14551
|
-
}
|
|
14549
|
+
return glyph(mark, options);
|
|
14552
14550
|
};
|
|
14553
|
-
const
|
|
14554
|
-
const
|
|
14555
|
-
|
|
14556
|
-
|
|
14557
|
-
|
|
14558
|
-
|
|
14559
|
-
|
|
14560
|
-
|
|
14561
|
-
|
|
14551
|
+
const widthFor = (mark, height) => mark.aspect === void 0 ? height : Math.round(height * mark.aspect * 1e3) / 1e3;
|
|
14552
|
+
const ownSvg = (mark, width, height) => {
|
|
14553
|
+
const holder = deps.document.createElement("span");
|
|
14554
|
+
holder.innerHTML = `<svg width="${width}" height="${height}" viewBox="${mark.viewBox}" fill="none" aria-hidden="true">${mark.body}</svg>`;
|
|
14555
|
+
return holder.firstElementChild;
|
|
14556
|
+
};
|
|
14557
|
+
const bare = (mark, width, height) => {
|
|
14558
|
+
const id = iconOf(mark);
|
|
14559
|
+
return (id ? host2(id, { width, height }) : null) ?? ownSvg(mark, width, height);
|
|
14562
14560
|
};
|
|
14563
|
-
deps.chart.subscribeCrosshairMove(onCrosshair);
|
|
14564
14561
|
return {
|
|
14565
|
-
|
|
14566
|
-
|
|
14567
|
-
|
|
14568
|
-
|
|
14569
|
-
|
|
14570
|
-
},
|
|
14571
|
-
push() {
|
|
14572
|
-
paint();
|
|
14573
|
-
},
|
|
14574
|
-
setHeader(symbol, tf) {
|
|
14575
|
-
if (symbol !== named || deps.replayPhase() !== "off") {
|
|
14576
|
-
status2?.close();
|
|
14577
|
-
status2 = null;
|
|
14578
|
-
}
|
|
14579
|
-
legend2?.setReplay(deps.replayPhase());
|
|
14580
|
-
if (symbol !== named || tf !== namedTimeframe) {
|
|
14581
|
-
named = symbol;
|
|
14582
|
-
namedTimeframe = tf;
|
|
14583
|
-
hovered = null;
|
|
14584
|
-
}
|
|
14585
|
-
const info = deps.symbolInfo();
|
|
14586
|
-
const label2 = symbolNames(info ?? symbol).title;
|
|
14587
|
-
legend2?.setIdentity({ name: label2, symbol, timeframe: tf, exchange: info?.exchange ?? "" });
|
|
14562
|
+
glyph: glyph2,
|
|
14563
|
+
icon(name2, requested) {
|
|
14564
|
+
const mark = ICONS[name2];
|
|
14565
|
+
const height = requested ?? mark.size ?? 28;
|
|
14566
|
+
return bare(mark, widthFor(mark, height), height);
|
|
14588
14567
|
},
|
|
14589
|
-
|
|
14590
|
-
const
|
|
14591
|
-
|
|
14592
|
-
status2?.refresh();
|
|
14568
|
+
tool(type, size = 28) {
|
|
14569
|
+
const mark = toolGlyph(type);
|
|
14570
|
+
return mark ? bare(mark, size, size) : null;
|
|
14593
14571
|
},
|
|
14594
|
-
|
|
14595
|
-
|
|
14596
|
-
|
|
14597
|
-
resize?.disconnect();
|
|
14598
|
-
observed.clear();
|
|
14599
|
-
deps.chart.unsubscribeCrosshairMove(onCrosshair);
|
|
14600
|
-
status2?.close();
|
|
14601
|
-
status2 = null;
|
|
14602
|
-
legend2?.destroy();
|
|
14603
|
-
legend2 = null;
|
|
14604
|
-
}
|
|
14572
|
+
host: host2,
|
|
14573
|
+
draw,
|
|
14574
|
+
redraw
|
|
14605
14575
|
};
|
|
14606
14576
|
}
|
|
14607
14577
|
|
|
14608
|
-
// src/
|
|
14609
|
-
|
|
14610
|
-
|
|
14611
|
-
|
|
14612
|
-
|
|
14613
|
-
|
|
14614
|
-
|
|
14615
|
-
|
|
14616
|
-
|
|
14617
|
-
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
14625
|
-
|
|
14626
|
-
|
|
14627
|
-
|
|
14628
|
-
|
|
14629
|
-
|
|
14630
|
-
|
|
14631
|
-
|
|
14632
|
-
const
|
|
14633
|
-
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14578
|
+
// src/inputsEditor.ts
|
|
14579
|
+
var titleOf = (key, titles) => titles?.[key] ?? key.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
14580
|
+
function buildInputFields(icons, inputs2, current, titles) {
|
|
14581
|
+
const fields = /* @__PURE__ */ new Map();
|
|
14582
|
+
const rows2 = [];
|
|
14583
|
+
for (const [key, spec] of Object.entries(inputs2)) {
|
|
14584
|
+
const row2 = document.createElement("label");
|
|
14585
|
+
row2.className = "qc-inputs-row";
|
|
14586
|
+
const name2 = document.createElement("span");
|
|
14587
|
+
name2.textContent = titleOf(key, titles);
|
|
14588
|
+
row2.appendChild(name2);
|
|
14589
|
+
if (spec.kind === "enum") {
|
|
14590
|
+
const select = document.createElement("select");
|
|
14591
|
+
select.className = "qc-field qc-inputs-select";
|
|
14592
|
+
(spec.options ?? []).forEach((label2, i) => {
|
|
14593
|
+
const o = document.createElement("option");
|
|
14594
|
+
o.value = String(i);
|
|
14595
|
+
o.textContent = label2;
|
|
14596
|
+
select.appendChild(o);
|
|
14597
|
+
});
|
|
14598
|
+
select.value = String(current[key] ?? spec.default);
|
|
14599
|
+
fields.set(key, select);
|
|
14600
|
+
row2.appendChild(selectField(select, icons));
|
|
14601
|
+
} else {
|
|
14602
|
+
const input = document.createElement("input");
|
|
14603
|
+
input.type = "number";
|
|
14604
|
+
input.className = "qc-field qc-inputs-field";
|
|
14605
|
+
if (spec.min !== void 0) input.min = String(spec.min);
|
|
14606
|
+
if (spec.max !== void 0) input.max = String(spec.max);
|
|
14607
|
+
input.step = spec.kind === "int" ? "1" : "any";
|
|
14608
|
+
input.value = String(current[key] ?? spec.default);
|
|
14609
|
+
fields.set(key, input);
|
|
14610
|
+
row2.appendChild(input);
|
|
14611
|
+
}
|
|
14612
|
+
rows2.push(row2);
|
|
14613
|
+
}
|
|
14614
|
+
return {
|
|
14615
|
+
rows: rows2,
|
|
14616
|
+
read() {
|
|
14617
|
+
const patch = {};
|
|
14618
|
+
for (const [key, field] of fields) {
|
|
14619
|
+
const spec = inputs2[key];
|
|
14620
|
+
let value = Number(field.value);
|
|
14621
|
+
if (!Number.isFinite(value)) continue;
|
|
14622
|
+
if (spec.kind === "int" || spec.kind === "enum") value = Math.round(value);
|
|
14623
|
+
if (spec.min !== void 0) value = Math.max(spec.min, value);
|
|
14624
|
+
if (spec.max !== void 0) value = Math.min(spec.max, value);
|
|
14625
|
+
patch[key] = value;
|
|
14640
14626
|
}
|
|
14641
|
-
|
|
14642
|
-
}
|
|
14643
|
-
|
|
14644
|
-
};
|
|
14645
|
-
const onStart = (event) => {
|
|
14646
|
-
stop();
|
|
14647
|
-
samples = [];
|
|
14648
|
-
movedAt = null;
|
|
14649
|
-
oneFinger = event.touches.length === 1;
|
|
14650
|
-
if (oneFinger) record3(performance.now());
|
|
14651
|
-
};
|
|
14652
|
-
const onMove = (event) => {
|
|
14653
|
-
if (event.touches.length !== 1) oneFinger = false;
|
|
14654
|
-
if (!oneFinger) return;
|
|
14655
|
-
if (movedAt !== null) record3(movedAt);
|
|
14656
|
-
movedAt = performance.now();
|
|
14627
|
+
return patch;
|
|
14628
|
+
},
|
|
14629
|
+
first: () => fields.values().next().value ?? null
|
|
14657
14630
|
};
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
|
|
14661
|
-
|
|
14662
|
-
|
|
14663
|
-
|
|
14664
|
-
|
|
14665
|
-
|
|
14666
|
-
|
|
14667
|
-
|
|
14631
|
+
}
|
|
14632
|
+
function openInputsEditor(container, rect, inputs2, current, onApply, strings = createChartI18n()) {
|
|
14633
|
+
const icons = createIconResolver({ document: container.ownerDocument, direction: () => readingDirection(strings), diagnostics: createIconDiagnostics() });
|
|
14634
|
+
mountInputsEditor(container, rect, inputs2, current, onApply, strings, icons);
|
|
14635
|
+
}
|
|
14636
|
+
function mountInputsEditor(container, rect, inputs2, current, onApply, strings, icons) {
|
|
14637
|
+
const host2 = container.getBoundingClientRect();
|
|
14638
|
+
const el2 = document.createElement("div");
|
|
14639
|
+
el2.className = "qc-overlay qc-inputs";
|
|
14640
|
+
el2.setAttribute("role", "dialog");
|
|
14641
|
+
el2.setAttribute("aria-label", strings.t("legend.indicatorSettings"));
|
|
14642
|
+
el2.style.left = `${Math.max(4, rect.x - host2.left)}px`;
|
|
14643
|
+
el2.style.top = `${Math.max(4, rect.y - host2.top + rect.h + 4)}px`;
|
|
14644
|
+
for (const type of ["pointerdown", "pointerup", "pointermove"]) el2.addEventListener(type, (e) => e.stopPropagation());
|
|
14645
|
+
const dismiss = () => {
|
|
14646
|
+
unsubscribe();
|
|
14647
|
+
el2.remove();
|
|
14668
14648
|
};
|
|
14669
|
-
const
|
|
14670
|
-
|
|
14671
|
-
|
|
14672
|
-
|
|
14649
|
+
const fields = buildInputFields(icons, inputs2, current);
|
|
14650
|
+
for (const row2 of fields.rows) el2.appendChild(row2);
|
|
14651
|
+
const apply = () => {
|
|
14652
|
+
onApply(fields.read());
|
|
14653
|
+
dismiss();
|
|
14673
14654
|
};
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
|
|
14679
|
-
|
|
14680
|
-
|
|
14681
|
-
|
|
14682
|
-
|
|
14683
|
-
|
|
14684
|
-
deps.target.removeEventListener("touchend", onEnd);
|
|
14685
|
-
deps.target.removeEventListener("touchcancel", onCancel);
|
|
14686
|
-
}
|
|
14655
|
+
const buttons = document.createElement("div");
|
|
14656
|
+
buttons.className = "qc-inputs-actions";
|
|
14657
|
+
const mkButton = (label2, onClick, primary = false) => {
|
|
14658
|
+
const b = document.createElement("button");
|
|
14659
|
+
b.type = "button";
|
|
14660
|
+
b.className = primary ? "qc-button qc-button--primary" : "qc-button";
|
|
14661
|
+
b.textContent = label2;
|
|
14662
|
+
b.addEventListener("click", onClick);
|
|
14663
|
+
buttons.appendChild(b);
|
|
14664
|
+
return b;
|
|
14687
14665
|
};
|
|
14666
|
+
const cancelButton = mkButton(strings.t("inputs.cancel"), () => dismiss());
|
|
14667
|
+
const applyButton = mkButton(strings.t("inputs.apply"), apply, true);
|
|
14668
|
+
el2.appendChild(buttons);
|
|
14669
|
+
const unsubscribe = strings.onChange(() => {
|
|
14670
|
+
cancelButton.textContent = strings.t("inputs.cancel");
|
|
14671
|
+
applyButton.textContent = strings.t("inputs.apply");
|
|
14672
|
+
el2.setAttribute("aria-label", strings.t("legend.indicatorSettings"));
|
|
14673
|
+
});
|
|
14674
|
+
el2.addEventListener("keydown", (e) => {
|
|
14675
|
+
e.stopPropagation();
|
|
14676
|
+
if (e.key === "Enter") apply();
|
|
14677
|
+
else if (e.key === "Escape") dismiss();
|
|
14678
|
+
});
|
|
14679
|
+
container.appendChild(el2);
|
|
14680
|
+
fields.first()?.focus?.();
|
|
14688
14681
|
}
|
|
14689
14682
|
|
|
14690
|
-
// src/
|
|
14691
|
-
|
|
14692
|
-
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
14696
|
-
|
|
14697
|
-
const b = touches[1];
|
|
14698
|
-
const left = deps.chart.chartElement().getBoundingClientRect().left + deps.chart.priceScale("left").width();
|
|
14699
|
-
return { distance: Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY), x: (a.clientX + b.clientX) / 2 - left };
|
|
14700
|
-
};
|
|
14701
|
-
const begin = (event) => {
|
|
14702
|
-
pinch = null;
|
|
14703
|
-
if (event.touches.length === 1) panned = false;
|
|
14704
|
-
if (event.touches.length !== 2 || panned || !scalingOpen(deps.chart.options().handleScale)) return;
|
|
14705
|
-
const range2 = scale().getVisibleLogicalRange();
|
|
14706
|
-
if (range2 === null) return;
|
|
14707
|
-
const { distance, x } = read(event.touches);
|
|
14708
|
-
pinch = pinchStart(range2, scale().width(), x, distance);
|
|
14709
|
-
};
|
|
14710
|
-
const move = (event) => {
|
|
14711
|
-
if (event.touches.length === 1 && pinch === null) panned = true;
|
|
14712
|
-
if (pinch === null || event.touches.length !== 2) return;
|
|
14713
|
-
if (!scalingOpen(deps.chart.options().handleScale)) {
|
|
14714
|
-
pinch = null;
|
|
14715
|
-
return;
|
|
14716
|
-
}
|
|
14717
|
-
const { distance, x } = read(event.touches);
|
|
14718
|
-
const s = scale();
|
|
14719
|
-
const width = s.width();
|
|
14720
|
-
const options = s.options();
|
|
14721
|
-
const plot = { width, minSpacing: options.minBarSpacing, maxSpacing: options.maxBarSpacing > 0 ? options.maxBarSpacing : width / 2 };
|
|
14722
|
-
s.setVisibleLogicalRange(pinchRange(pinch, x, distance, plot));
|
|
14723
|
-
};
|
|
14724
|
-
const end = (event) => {
|
|
14725
|
-
if (event.touches.length === 1) panned = false;
|
|
14726
|
-
if (event.touches.length === 2) begin(event);
|
|
14727
|
-
else pinch = null;
|
|
14728
|
-
};
|
|
14729
|
-
deps.target.addEventListener("touchstart", begin, { passive: true });
|
|
14730
|
-
deps.target.addEventListener("touchmove", move, { passive: true });
|
|
14731
|
-
deps.target.addEventListener("touchend", end, { passive: true });
|
|
14732
|
-
deps.target.addEventListener("touchcancel", end, { passive: true });
|
|
14733
|
-
return {
|
|
14734
|
-
destroy() {
|
|
14735
|
-
pinch = null;
|
|
14736
|
-
deps.target.removeEventListener("touchstart", begin);
|
|
14737
|
-
deps.target.removeEventListener("touchmove", move);
|
|
14738
|
-
deps.target.removeEventListener("touchend", end);
|
|
14739
|
-
deps.target.removeEventListener("touchcancel", end);
|
|
14740
|
-
}
|
|
14741
|
-
};
|
|
14683
|
+
// src/ui/chrome/menu.ts
|
|
14684
|
+
var HOST_MARGIN = 8;
|
|
14685
|
+
var byAnchor = /* @__PURE__ */ new WeakMap();
|
|
14686
|
+
function toggleMenu(anchor, open2) {
|
|
14687
|
+
const current = byAnchor.get(anchor);
|
|
14688
|
+
if (current?.open()) current.close();
|
|
14689
|
+
else open2();
|
|
14742
14690
|
}
|
|
14743
|
-
|
|
14744
|
-
|
|
14745
|
-
|
|
14746
|
-
|
|
14747
|
-
const
|
|
14748
|
-
|
|
14749
|
-
|
|
14750
|
-
|
|
14751
|
-
|
|
14752
|
-
|
|
14753
|
-
|
|
14754
|
-
|
|
14755
|
-
|
|
14756
|
-
const
|
|
14757
|
-
|
|
14758
|
-
|
|
14759
|
-
|
|
14760
|
-
|
|
14761
|
-
|
|
14762
|
-
|
|
14763
|
-
|
|
14764
|
-
|
|
14765
|
-
|
|
14766
|
-
|
|
14767
|
-
|
|
14768
|
-
const
|
|
14769
|
-
if (
|
|
14770
|
-
|
|
14771
|
-
|
|
14772
|
-
|
|
14773
|
-
|
|
14774
|
-
|
|
14775
|
-
|
|
14776
|
-
|
|
14777
|
-
if (
|
|
14778
|
-
|
|
14779
|
-
|
|
14780
|
-
landed = null;
|
|
14691
|
+
function openMenu(options) {
|
|
14692
|
+
const { anchor, host: host2 } = options;
|
|
14693
|
+
const previous = byAnchor.get(anchor);
|
|
14694
|
+
const rtl = isRtl(anchor);
|
|
14695
|
+
const role = options.role ?? "menu";
|
|
14696
|
+
const element = h("div", {
|
|
14697
|
+
class: `qc-overlay qc-menu-panel${options.className ? ` ${options.className}` : ""}`,
|
|
14698
|
+
role,
|
|
14699
|
+
"aria-label": options.label,
|
|
14700
|
+
...role === "dialog" ? { "aria-modal": "false" } : {}
|
|
14701
|
+
});
|
|
14702
|
+
if (options.width) element.style.width = `${options.width}px`;
|
|
14703
|
+
stopPointer(element);
|
|
14704
|
+
const body = h("div", { class: "qc-menu-body" });
|
|
14705
|
+
element.appendChild(body);
|
|
14706
|
+
const footer = options.footer ? h("div", { class: "qc-menu-footer" }) : null;
|
|
14707
|
+
if (footer) element.appendChild(footer);
|
|
14708
|
+
let isOpen = true;
|
|
14709
|
+
const previouslyFocused = document.activeElement;
|
|
14710
|
+
const escape = pushEscapeOwner();
|
|
14711
|
+
let untrack = () => void 0;
|
|
14712
|
+
const close = () => {
|
|
14713
|
+
if (!isOpen) return;
|
|
14714
|
+
isOpen = false;
|
|
14715
|
+
escape.release();
|
|
14716
|
+
const ownedAnchor = byAnchor.get(anchor) === handle;
|
|
14717
|
+
if (ownedAnchor) byAnchor.delete(anchor);
|
|
14718
|
+
untrack();
|
|
14719
|
+
document.removeEventListener("pointerdown", onOutside, true);
|
|
14720
|
+
document.removeEventListener("keydown", onDocumentKey, true);
|
|
14721
|
+
window.removeEventListener("resize", reposition);
|
|
14722
|
+
if (ownedAnchor) anchor.setAttribute("aria-expanded", "false");
|
|
14723
|
+
element.remove();
|
|
14724
|
+
options.onClose?.();
|
|
14725
|
+
if (byAnchor.get(anchor)?.open()) return;
|
|
14726
|
+
const target = document.activeElement === document.body || document.activeElement === null || element.contains(document.activeElement) ? anchor : previouslyFocused;
|
|
14727
|
+
target?.focus();
|
|
14781
14728
|
};
|
|
14782
|
-
|
|
14783
|
-
|
|
14784
|
-
|
|
14785
|
-
|
|
14786
|
-
|
|
14787
|
-
|
|
14788
|
-
|
|
14789
|
-
|
|
14790
|
-
|
|
14791
|
-
|
|
14792
|
-
|
|
14793
|
-
|
|
14729
|
+
const reposition = () => {
|
|
14730
|
+
if (!isOpen) return;
|
|
14731
|
+
const a = anchor.getBoundingClientRect();
|
|
14732
|
+
const bounds = host2.getBoundingClientRect();
|
|
14733
|
+
const below = (options.placement ?? "down") === "down";
|
|
14734
|
+
if (!below) element.style.maxHeight = `${Math.max(0, Math.floor(a.top - bounds.top - HOST_MARGIN - 2))}px`;
|
|
14735
|
+
element.style.left = "0px";
|
|
14736
|
+
element.style.top = "0px";
|
|
14737
|
+
const box = element.getBoundingClientRect();
|
|
14738
|
+
const alignEnd = (options.align ?? "start") === (rtl ? "start" : "end");
|
|
14739
|
+
let left = (alignEnd ? a.right - box.width : a.left) - bounds.left;
|
|
14740
|
+
left = Math.max(HOST_MARGIN, Math.min(left, Math.max(HOST_MARGIN, bounds.width - box.width - HOST_MARGIN)));
|
|
14741
|
+
let top = (below ? a.bottom + 2 : a.top - box.height - 2) - bounds.top;
|
|
14742
|
+
top = Math.max(HOST_MARGIN, Math.min(top, Math.max(HOST_MARGIN, bounds.height - box.height - HOST_MARGIN)));
|
|
14743
|
+
element.style.left = `${Math.round(left)}px`;
|
|
14744
|
+
element.style.top = `${Math.round(top)}px`;
|
|
14794
14745
|
};
|
|
14795
|
-
|
|
14796
|
-
|
|
14797
|
-
|
|
14798
|
-
|
|
14799
|
-
const row2 = chart.panes()[0]?.getHTMLElement();
|
|
14800
|
-
if (!row2) return null;
|
|
14801
|
-
const size = chart.paneSize(0);
|
|
14802
|
-
if (!(size.width > 0) || !(size.height > 0)) return null;
|
|
14803
|
-
const outer = host2.getBoundingClientRect();
|
|
14804
|
-
const top = row2.getBoundingClientRect().top;
|
|
14805
|
-
const left = chart.chartElement().getBoundingClientRect().left + chart.priceScale("left").width();
|
|
14806
|
-
const round = (n) => Math.round(n * 100) / 100;
|
|
14807
|
-
return {
|
|
14808
|
-
top: round(top - outer.top),
|
|
14809
|
-
right: round(outer.right - (left + size.width)),
|
|
14810
|
-
bottom: round(outer.bottom - (top + size.height)),
|
|
14811
|
-
left: round(left - outer.left),
|
|
14812
|
-
width: round(size.width),
|
|
14813
|
-
height: round(size.height)
|
|
14746
|
+
const onOutside = (event) => {
|
|
14747
|
+
const target = event.target;
|
|
14748
|
+
if (!target || element.contains(target) || anchor.contains(target)) return;
|
|
14749
|
+
close();
|
|
14814
14750
|
};
|
|
14815
|
-
|
|
14816
|
-
|
|
14817
|
-
|
|
14818
|
-
|
|
14819
|
-
|
|
14820
|
-
let destroyed = false;
|
|
14821
|
-
let row2 = null;
|
|
14822
|
-
const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => schedule());
|
|
14823
|
-
const measure2 = () => {
|
|
14824
|
-
frame = null;
|
|
14825
|
-
if (destroyed) return;
|
|
14826
|
-
const nextRow = deps.chart.panes()[0]?.getHTMLElement() ?? null;
|
|
14827
|
-
if (nextRow !== row2) {
|
|
14828
|
-
if (row2) resize?.unobserve(row2);
|
|
14829
|
-
if (nextRow) resize?.observe(nextRow);
|
|
14830
|
-
row2 = nextRow;
|
|
14751
|
+
const onDocumentKey = (event) => {
|
|
14752
|
+
if (event.key === "Escape" && ownsEscape(escape.token)) {
|
|
14753
|
+
event.stopPropagation();
|
|
14754
|
+
event.preventDefault();
|
|
14755
|
+
close();
|
|
14831
14756
|
}
|
|
14832
|
-
const next = measurePlotArea(deps.chart, deps.host);
|
|
14833
|
-
if (next === null || sameArea(next, area)) return;
|
|
14834
|
-
area = next;
|
|
14835
|
-
deps.changed(next);
|
|
14836
14757
|
};
|
|
14837
|
-
|
|
14838
|
-
if (
|
|
14839
|
-
|
|
14840
|
-
measure2();
|
|
14758
|
+
element.addEventListener("keydown", (event) => {
|
|
14759
|
+
if (event.key === "Tab") {
|
|
14760
|
+
close();
|
|
14841
14761
|
return;
|
|
14842
14762
|
}
|
|
14843
|
-
|
|
14844
|
-
|
|
14845
|
-
|
|
14846
|
-
|
|
14847
|
-
|
|
14848
|
-
|
|
14849
|
-
return {
|
|
14850
|
-
current() {
|
|
14851
|
-
if (destroyed) return null;
|
|
14852
|
-
return area ?? measurePlotArea(deps.chart, deps.host);
|
|
14853
|
-
},
|
|
14854
|
-
destroy() {
|
|
14855
|
-
if (destroyed) return;
|
|
14856
|
-
destroyed = true;
|
|
14857
|
-
if (frame !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frame);
|
|
14858
|
-
frame = null;
|
|
14859
|
-
resize?.disconnect();
|
|
14860
|
-
try {
|
|
14861
|
-
deps.chart.timeScale().unsubscribeSizeChange(schedule);
|
|
14862
|
-
} catch {
|
|
14863
|
-
}
|
|
14763
|
+
const target = event.target;
|
|
14764
|
+
const typing = target instanceof HTMLInputElement && target.type !== "checkbox" && target.type !== "radio";
|
|
14765
|
+
if (typing && (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Home" || event.key === "End")) return;
|
|
14766
|
+
if (roveFocus(element, event, "both")) {
|
|
14767
|
+
event.preventDefault();
|
|
14768
|
+
event.stopPropagation();
|
|
14864
14769
|
}
|
|
14770
|
+
});
|
|
14771
|
+
const handle = {
|
|
14772
|
+
element,
|
|
14773
|
+
close,
|
|
14774
|
+
open: () => isOpen,
|
|
14775
|
+
refresh() {
|
|
14776
|
+
if (!isOpen) return;
|
|
14777
|
+
const current = items(element).indexOf(document.activeElement);
|
|
14778
|
+
body.replaceChildren();
|
|
14779
|
+
options.build(body, handle);
|
|
14780
|
+
if (footer && options.footer) {
|
|
14781
|
+
footer.replaceChildren();
|
|
14782
|
+
options.footer(footer, handle);
|
|
14783
|
+
}
|
|
14784
|
+
const list2 = items(element);
|
|
14785
|
+
if (list2.length === 0) return;
|
|
14786
|
+
if (current >= 0 && document.activeElement && !element.contains(document.activeElement)) return;
|
|
14787
|
+
armRoving(element, Math.max(0, Math.min(current, list2.length - 1)));
|
|
14788
|
+
if (current >= 0) list2[Math.min(current, list2.length - 1)]?.focus();
|
|
14789
|
+
reposition();
|
|
14790
|
+
},
|
|
14791
|
+
reposition
|
|
14865
14792
|
};
|
|
14793
|
+
byAnchor.set(anchor, handle);
|
|
14794
|
+
previous?.close();
|
|
14795
|
+
if (!isOpen || byAnchor.get(anchor) !== handle) return handle;
|
|
14796
|
+
options.build(body, handle);
|
|
14797
|
+
if (footer && options.footer) options.footer(footer, handle);
|
|
14798
|
+
if (!isOpen || byAnchor.get(anchor) !== handle) return handle;
|
|
14799
|
+
host2.appendChild(element);
|
|
14800
|
+
untrack = trackOverlay(host2, close, () => handle.refresh());
|
|
14801
|
+
anchor.setAttribute("aria-expanded", "true");
|
|
14802
|
+
reposition();
|
|
14803
|
+
const list = items(element);
|
|
14804
|
+
const first = Math.max(0, Math.min(options.initialIndex ?? 0, list.length - 1));
|
|
14805
|
+
if (list.length > 0) {
|
|
14806
|
+
armRoving(element, first);
|
|
14807
|
+
focusItem(list, first);
|
|
14808
|
+
list[first]?.scrollIntoView?.({ block: "nearest" });
|
|
14809
|
+
} else {
|
|
14810
|
+
const focusable = element.querySelector('input, button, select, textarea, [tabindex="0"]');
|
|
14811
|
+
focusable?.focus();
|
|
14812
|
+
}
|
|
14813
|
+
document.addEventListener("pointerdown", onOutside, true);
|
|
14814
|
+
document.addEventListener("keydown", onDocumentKey, true);
|
|
14815
|
+
window.addEventListener("resize", reposition);
|
|
14816
|
+
return handle;
|
|
14866
14817
|
}
|
|
14867
|
-
|
|
14868
|
-
|
|
14869
|
-
|
|
14870
|
-
|
|
14871
|
-
|
|
14872
|
-
|
|
14873
|
-
|
|
14874
|
-
|
|
14875
|
-
|
|
14876
|
-
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14880
|
-
|
|
14881
|
-
|
|
14882
|
-
|
|
14883
|
-
|
|
14884
|
-
const
|
|
14885
|
-
|
|
14886
|
-
|
|
14887
|
-
|
|
14888
|
-
}
|
|
14889
|
-
|
|
14890
|
-
}
|
|
14891
|
-
|
|
14892
|
-
|
|
14893
|
-
|
|
14894
|
-
|
|
14895
|
-
|
|
14896
|
-
|
|
14897
|
-
|
|
14898
|
-
|
|
14899
|
-
|
|
14900
|
-
|
|
14901
|
-
|
|
14902
|
-
|
|
14903
|
-
|
|
14904
|
-
|
|
14905
|
-
|
|
14906
|
-
|
|
14907
|
-
|
|
14908
|
-
|
|
14909
|
-
|
|
14910
|
-
|
|
14911
|
-
|
|
14912
|
-
|
|
14913
|
-
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
14917
|
-
|
|
14918
|
-
|
|
14919
|
-
|
|
14920
|
-
|
|
14921
|
-
|
|
14922
|
-
|
|
14923
|
-
|
|
14924
|
-
|
|
14925
|
-
|
|
14926
|
-
|
|
14927
|
-
|
|
14928
|
-
}
|
|
14929
|
-
|
|
14930
|
-
|
|
14931
|
-
|
|
14932
|
-
|
|
14933
|
-
|
|
14934
|
-
|
|
14935
|
-
|
|
14936
|
-
|
|
14937
|
-
|
|
14938
|
-
|
|
14939
|
-
|
|
14940
|
-
|
|
14941
|
-
|
|
14942
|
-
|
|
14943
|
-
|
|
14944
|
-
|
|
14945
|
-
|
|
14946
|
-
|
|
14947
|
-
|
|
14948
|
-
|
|
14949
|
-
|
|
14950
|
-
|
|
14951
|
-
|
|
14952
|
-
|
|
14953
|
-
|
|
14954
|
-
|
|
14955
|
-
|
|
14956
|
-
|
|
14957
|
-
|
|
14958
|
-
|
|
14959
|
-
|
|
14960
|
-
|
|
14961
|
-
|
|
14962
|
-
|
|
14963
|
-
|
|
14964
|
-
|
|
14965
|
-
|
|
14966
|
-
|
|
14967
|
-
|
|
14968
|
-
|
|
14969
|
-
|
|
14970
|
-
|
|
14971
|
-
|
|
14972
|
-
|
|
14973
|
-
|
|
14974
|
-
|
|
14975
|
-
|
|
14976
|
-
|
|
14977
|
-
|
|
14978
|
-
|
|
14979
|
-
|
|
14980
|
-
|
|
14981
|
-
|
|
14982
|
-
|
|
14983
|
-
|
|
14984
|
-
|
|
14985
|
-
|
|
14986
|
-
|
|
14987
|
-
|
|
14988
|
-
|
|
14989
|
-
|
|
14990
|
-
|
|
14991
|
-
|
|
14992
|
-
|
|
14993
|
-
|
|
14994
|
-
|
|
14995
|
-
|
|
14996
|
-
|
|
14997
|
-
|
|
14998
|
-
|
|
14999
|
-
|
|
15000
|
-
|
|
15001
|
-
|
|
15002
|
-
|
|
15003
|
-
|
|
15004
|
-
|
|
15005
|
-
|
|
15006
|
-
|
|
15007
|
-
|
|
15008
|
-
|
|
15009
|
-
|
|
15010
|
-
|
|
15011
|
-
|
|
15012
|
-
|
|
15013
|
-
|
|
15014
|
-
|
|
15015
|
-
|
|
15016
|
-
|
|
15017
|
-
|
|
15018
|
-
|
|
15019
|
-
|
|
15020
|
-
|
|
15021
|
-
|
|
15022
|
-
|
|
15023
|
-
|
|
15024
|
-
|
|
15025
|
-
|
|
15026
|
-
|
|
15027
|
-
|
|
15028
|
-
|
|
15029
|
-
|
|
15030
|
-
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
|
|
15042
|
-
|
|
15043
|
-
|
|
15044
|
-
|
|
15045
|
-
|
|
15046
|
-
|
|
15047
|
-
|
|
15048
|
-
|
|
15049
|
-
|
|
15050
|
-
|
|
15051
|
-
|
|
15052
|
-
|
|
15053
|
-
|
|
15054
|
-
|
|
15055
|
-
|
|
15056
|
-
|
|
15057
|
-
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
|
|
15061
|
-
|
|
15062
|
-
|
|
15063
|
-
|
|
15064
|
-
|
|
15065
|
-
|
|
15066
|
-
|
|
15067
|
-
|
|
15068
|
-
|
|
15069
|
-
|
|
15070
|
-
|
|
15071
|
-
|
|
15072
|
-
|
|
15073
|
-
|
|
15074
|
-
|
|
15075
|
-
|
|
15076
|
-
|
|
15077
|
-
|
|
15078
|
-
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15088
|
-
|
|
15089
|
-
|
|
15090
|
-
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
15112
|
-
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15131
|
-
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
|
|
15137
|
-
grip: [ICONS.grip],
|
|
15138
|
-
emptySearch: [SEARCH_EMPTY_MARK],
|
|
15139
|
-
emptyCompare: [COMPARE_EMPTY_MARK],
|
|
15140
|
-
// The symbol search's spread builder.
|
|
15141
|
-
operatorsShow: [ICONS.spreadOpsShow],
|
|
15142
|
-
operatorsHide: [ICONS.spreadOpsHide],
|
|
15143
|
-
operatorAdd: [OPERATOR_GLYPHS.addition],
|
|
15144
|
-
operatorSubtract: [OPERATOR_GLYPHS.subtraction],
|
|
15145
|
-
operatorMultiply: [OPERATOR_GLYPHS.multiplication],
|
|
15146
|
-
operatorDivide: [OPERATOR_GLYPHS.division],
|
|
15147
|
-
operatorPower: [OPERATOR_GLYPHS.exponentiation],
|
|
15148
|
-
operatorReciprocal: [OPERATOR_GLYPHS.reciprocal],
|
|
15149
|
-
// The replay transport.
|
|
15150
|
-
play: [ICONS.play],
|
|
15151
|
-
pause: [ICONS.pause],
|
|
15152
|
-
stepForward: [ICONS.stepForward],
|
|
15153
|
-
stepBack: [ICONS.stepBack],
|
|
15154
|
-
goLive: [ICONS.goLive],
|
|
15155
|
-
selectBar: [ICONS.selectBar],
|
|
15156
|
-
selectDate: [ICONS.calendar],
|
|
15157
|
-
firstAvailable: [ICONS.firstAvailable],
|
|
15158
|
-
randomBar: [ICONS.randomBar],
|
|
15159
|
-
// The drawing toolbar, its menus, the favorites bar and the drawing settings.
|
|
15160
|
-
cursorCross: [ICONS.cursorCross],
|
|
15161
|
-
cursorDot: [ICONS.cursorDot],
|
|
15162
|
-
cursorArrow: [ICONS.cursorArrow],
|
|
15163
|
-
eraser: [ICONS.eraser],
|
|
15164
|
-
measure: [ICONS.ruler],
|
|
15165
|
-
zoomTool: [ICONS.zoomIn],
|
|
15166
|
-
magnet: [ICONS.magnet],
|
|
15167
|
-
magnetStrong: [ICONS.magnetStrong],
|
|
15168
|
-
stayInMode: [ICONS.pin],
|
|
15169
|
-
stayInModeOn: [ICONS.pinOn],
|
|
15170
|
-
locked: [ICONS.lockClosed],
|
|
15171
|
-
unlocked: [ICONS.lockOpen],
|
|
15172
|
-
drawingsShown: [ICONS.drawingsShown],
|
|
15173
|
-
drawingsHidden: [ICONS.drawingsHidden],
|
|
15174
|
-
indicatorsShown: [ICONS.indicatorsShown],
|
|
15175
|
-
indicatorsHidden: [ICONS.indicatorsHidden],
|
|
15176
|
-
allShown: [ICONS.allShown],
|
|
15177
|
-
allHidden: [ICONS.allHidden],
|
|
15178
|
-
hide: [ICONS.eyeCrossed],
|
|
15179
|
-
sync: [ICONS.sync],
|
|
15180
|
-
glyphTools: [ICONS.groupGlyphs],
|
|
15181
|
-
favoritesBar: [ICONS.favoritesBar],
|
|
15182
|
-
template: [ICONS.template],
|
|
15183
|
-
visualOrder: [ICONS.layers],
|
|
15184
|
-
lineColor: [ICONS.pencil16],
|
|
15185
|
-
fillColor: [ICONS.bucket],
|
|
15186
|
-
textColor: [ICONS.textTee],
|
|
15187
|
-
lineSolid: [ICONS.lineSolid],
|
|
15188
|
-
lineDashed: [ICONS.lineDashed],
|
|
15189
|
-
lineDotted: [ICONS.lineDotted],
|
|
15190
|
-
lineThickness1: [ICONS.lineThickness1],
|
|
15191
|
-
lineThickness2: [ICONS.lineThickness2],
|
|
15192
|
-
lineThickness3: [ICONS.lineThickness3],
|
|
15193
|
-
lineThickness4: [ICONS.lineThickness4],
|
|
15194
|
-
// Drawn for a line's left end; the right end wears the same drawing mirrored.
|
|
15195
|
-
lineEndNormal: [ICONS.lineEndNormal],
|
|
15196
|
-
lineEndArrow: [ICONS.lineEndArrow]
|
|
15197
|
-
});
|
|
15198
|
-
var MIRRORED_ICONS = /* @__PURE__ */ new Set(["flyout"]);
|
|
15199
|
-
var MINIATURE_TOOLS = Object.keys(TOOL_ICONS);
|
|
15200
|
-
var ARRANGEMENT_CODES = Object.keys(ARRANGEMENT_ICONS);
|
|
15201
|
-
var toolGlyphs = new Map(MINIATURE_TOOLS.map((type) => [type, { viewBox: "0 0 28 28", body: TOOL_ICONS[type] }]));
|
|
15202
|
-
var arrangementGlyphs = new Map(ARRANGEMENT_CODES.map((code) => [code, { viewBox: ARRANGEMENT_ICONS[code].viewBox, body: ARRANGEMENT_ICONS[code].body }]));
|
|
15203
|
-
var toolGlyph = (type) => toolGlyphs.get(type);
|
|
15204
|
-
var arrangementGlyphOf = (code) => arrangementGlyphs.get(code);
|
|
15205
|
-
var CHART_ICON_IDS = [
|
|
15206
|
-
...Object.keys(CONTROL_ICONS),
|
|
15207
|
-
...CHART_STYLES.map((style) => `style.${style}`),
|
|
15208
|
-
...MINIATURE_TOOLS.map((type) => `tool.${type}`),
|
|
15209
|
-
...ARRANGEMENT_CODES.map((code) => `layout.${code}`)
|
|
15210
|
-
];
|
|
15211
|
-
var PUBLISHED = new Set(CHART_ICON_IDS);
|
|
15212
|
-
var ICON_OF = /* @__PURE__ */ new WeakMap();
|
|
15213
|
-
for (const [id, glyphs] of Object.entries(CONTROL_ICONS)) for (const mark of glyphs) ICON_OF.set(mark, id);
|
|
15214
|
-
for (const style of CHART_STYLES) ICON_OF.set(STYLE_ICONS[style], `style.${style}`);
|
|
15215
|
-
for (const type of MINIATURE_TOOLS) ICON_OF.set(toolGlyphs.get(type), `tool.${type}`);
|
|
15216
|
-
for (const code of ARRANGEMENT_CODES) ICON_OF.set(arrangementGlyphs.get(code), `layout.${code}`);
|
|
15217
|
-
var iconOf = (mark) => ICON_OF.get(mark);
|
|
15218
|
-
var GLYPHS_OF = new Map([
|
|
15219
|
-
...Object.entries(CONTROL_ICONS),
|
|
15220
|
-
...CHART_STYLES.map((style) => [`style.${style}`, [STYLE_ICONS[style]]]),
|
|
15221
|
-
...MINIATURE_TOOLS.map((type) => [`tool.${type}`, [toolGlyphs.get(type)]]),
|
|
15222
|
-
...ARRANGEMENT_CODES.map((code) => [`layout.${code}`, [arrangementGlyphs.get(code)]])
|
|
15223
|
-
]);
|
|
15224
|
-
var standsAlone = (mark) => !/var\(--|class=/.test(mark.body);
|
|
15225
|
-
function chartIconArtwork(id) {
|
|
15226
|
-
const glyphs = GLYPHS_OF.get(id) ?? [];
|
|
15227
|
-
if (!glyphs.every(standsAlone)) return [];
|
|
15228
|
-
return glyphs.map((mark) => ({
|
|
15229
|
-
viewBox: mark.viewBox,
|
|
15230
|
-
body: mark.body,
|
|
15231
|
-
svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="${mark.viewBox}" fill="none">${mark.body}</svg>`
|
|
15232
|
-
}));
|
|
15233
|
-
}
|
|
15234
|
-
function checkIcons(icons) {
|
|
15235
|
-
if (icons === void 0) return;
|
|
15236
|
-
if (typeof icons !== "object" || icons === null || Array.isArray(icons)) throw new TypeError("icons must be an object");
|
|
15237
|
-
for (const [id, factory] of Object.entries(icons)) {
|
|
15238
|
-
if (!PUBLISHED.has(id)) throw new TypeError(`icons.${id} is not an icon the chart draws; CHART_ICON_IDS lists every one`);
|
|
15239
|
-
if (factory !== void 0 && typeof factory !== "function") throw new TypeError(`icons.${id} must be a function that draws the icon`);
|
|
14818
|
+
function menuItem(options) {
|
|
14819
|
+
const role = options.role ?? "menuitem";
|
|
14820
|
+
const row2 = h("button", {
|
|
14821
|
+
type: "button",
|
|
14822
|
+
class: `qc-menu-row${options.className ? ` ${options.className}` : ""}`,
|
|
14823
|
+
role,
|
|
14824
|
+
"data-qc-item": "",
|
|
14825
|
+
tabindex: "-1",
|
|
14826
|
+
...options.label ? { "aria-label": options.label } : options.keys ? { "aria-label": options.text } : {},
|
|
14827
|
+
...options.keys ? { "aria-keyshortcuts": options.keys } : {},
|
|
14828
|
+
...role === "menuitemradio" || role === "menuitemcheckbox" ? { "aria-checked": String(options.checked === true) } : {},
|
|
14829
|
+
...role === "option" ? { "aria-selected": String(options.checked === true) } : {}
|
|
14830
|
+
});
|
|
14831
|
+
if (options.disabled) {
|
|
14832
|
+
row2.disabled = true;
|
|
14833
|
+
row2.setAttribute("aria-disabled", "true");
|
|
14834
|
+
}
|
|
14835
|
+
const cell2 = h("span", { class: "qc-menu-icon" });
|
|
14836
|
+
if (options.icon) {
|
|
14837
|
+
row2.classList.add("qc-menu-row--marked");
|
|
14838
|
+
cell2.appendChild(options.icon);
|
|
14839
|
+
}
|
|
14840
|
+
row2.appendChild(cell2);
|
|
14841
|
+
const label2 = h("span", { class: "qc-menu-label" }, options.text);
|
|
14842
|
+
row2.appendChild(options.description === void 0 ? label2 : h("span", { class: "qc-menu-text" }, label2, h("span", { class: "qc-menu-description" }, options.description)));
|
|
14843
|
+
if (options.hint !== void 0) row2.appendChild(h("span", { class: "qc-menu-hint", ...options.keys ? { "aria-hidden": "true" } : {} }, options.hint));
|
|
14844
|
+
if (options.onSelect) row2.addEventListener("click", () => options.onSelect?.());
|
|
14845
|
+
return row2;
|
|
14846
|
+
}
|
|
14847
|
+
function menuHeading(text2) {
|
|
14848
|
+
return h("div", { class: "qc-menu-heading", role: "presentation" }, text2);
|
|
14849
|
+
}
|
|
14850
|
+
function menuSeparator() {
|
|
14851
|
+
return h("div", { class: "qc-separator", role: "separator" });
|
|
14852
|
+
}
|
|
14853
|
+
|
|
14854
|
+
// src/ui/chrome/marketStatus.ts
|
|
14855
|
+
var clock = (mins) => `${String(Math.floor(mins / 60) % 24).padStart(2, "0")}:${String(mins % 60).padStart(2, "0")}`;
|
|
14856
|
+
function timelineLabels(starts) {
|
|
14857
|
+
const sorted = [...new Set(starts.filter((m) => m > 0))].sort((a, b) => a - b);
|
|
14858
|
+
const out = [];
|
|
14859
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
14860
|
+
const a = sorted[i];
|
|
14861
|
+
const b = sorted[i + 1];
|
|
14862
|
+
if (b !== void 0 && b - a <= 90) {
|
|
14863
|
+
out.push({ mins: (a + b) / 2, text: `${clock(a)} ${clock(b)}` });
|
|
14864
|
+
i++;
|
|
14865
|
+
} else out.push({ mins: a, text: clock(a) });
|
|
14866
|
+
}
|
|
14867
|
+
return out;
|
|
14868
|
+
}
|
|
14869
|
+
function openMarketStatus(anchor, deps) {
|
|
14870
|
+
const t = deps.i18n.t;
|
|
14871
|
+
const now = () => Math.floor(Date.now() / 1e3);
|
|
14872
|
+
let timer = null;
|
|
14873
|
+
let offLocale = () => void 0;
|
|
14874
|
+
const stopUpdates = () => {
|
|
14875
|
+
if (timer) clearInterval(timer);
|
|
14876
|
+
timer = null;
|
|
14877
|
+
offLocale();
|
|
14878
|
+
offLocale = () => void 0;
|
|
14879
|
+
};
|
|
14880
|
+
const titleRow = (state, text2) => {
|
|
14881
|
+
const dot = h("span", { class: "qc-session-dot qc-status-dot", ...state ? { "data-qc-session": state } : {} });
|
|
14882
|
+
return h("div", { class: "qc-status-title" }, dot, h("span", { class: "qc-title" }, text2));
|
|
14883
|
+
};
|
|
14884
|
+
const menu2 = openMenu({
|
|
14885
|
+
host: deps.host,
|
|
14886
|
+
anchor,
|
|
14887
|
+
label: t("status.title"),
|
|
14888
|
+
role: "dialog",
|
|
14889
|
+
className: "qc-status-popup",
|
|
14890
|
+
width: 300,
|
|
14891
|
+
build(body) {
|
|
14892
|
+
const model = deps.model();
|
|
14893
|
+
const nowSecs = now();
|
|
14894
|
+
const status2 = model ? deps.status(nowSecs) : null;
|
|
14895
|
+
if (!model || !status2) {
|
|
14896
|
+
body.append(titleRow(null, t("status.unknownTitle")), h("p", { class: "qc-status-text qc-secondary" }, t("status.unknown")));
|
|
14897
|
+
return;
|
|
14898
|
+
}
|
|
14899
|
+
body.append(titleRow(sessionStateAt(model, nowSecs), marketStatusTitle(t, status2)), h("p", { class: "qc-status-text qc-secondary" }, marketStatusText(t, status2, nowSecs)));
|
|
14900
|
+
const tl = sessionTimeline(model, nowSecs, deps.i18n.tag());
|
|
14901
|
+
const bar = h("div", { class: "qc-status-bar", "aria-hidden": "true" });
|
|
14902
|
+
for (const s of tl.segments) {
|
|
14903
|
+
const segment = h("div", { class: "qc-status-segment", "data-qc-session": s.state });
|
|
14904
|
+
segment.style.width = `${(s.end - s.start) / 1440 * 100}%`;
|
|
14905
|
+
bar.appendChild(segment);
|
|
14906
|
+
}
|
|
14907
|
+
const marker = h("div", { class: "qc-status-now" });
|
|
14908
|
+
marker.style.insetInlineStart = `${tl.nowMins / 1440 * 100}%`;
|
|
14909
|
+
const track = h("div", { class: "qc-status-track" }, bar, marker);
|
|
14910
|
+
body.appendChild(h("div", { class: "qc-status-timeline" }, h("span", { class: "qc-status-day qc-muted" }, tl.dayLabel), track));
|
|
14911
|
+
const labels = timelineLabels(tl.segments.map((s) => s.start));
|
|
14912
|
+
if (labels.length > 0) {
|
|
14913
|
+
const row2 = h("div", { class: "qc-status-labels", "aria-hidden": "true" });
|
|
14914
|
+
for (const l of labels) {
|
|
14915
|
+
const label2 = h("span", { class: "qc-status-label qc-muted" }, l.text);
|
|
14916
|
+
label2.style.insetInlineStart = `${l.mins / 1440 * 100}%`;
|
|
14917
|
+
row2.appendChild(label2);
|
|
14918
|
+
}
|
|
14919
|
+
body.appendChild(row2);
|
|
14920
|
+
}
|
|
14921
|
+
body.appendChild(h("div", { class: "qc-status-footer qc-muted" }, exchangeTimezoneText(t, tl.timezone, new Date(nowSecs * 1e3))));
|
|
14922
|
+
},
|
|
14923
|
+
onClose() {
|
|
14924
|
+
stopUpdates();
|
|
14925
|
+
deps.onClose?.();
|
|
14926
|
+
}
|
|
14927
|
+
});
|
|
14928
|
+
timer = setInterval(() => menu2.refresh(), 6e4);
|
|
14929
|
+
offLocale = deps.i18n.onChange(() => menu2.refresh());
|
|
14930
|
+
if (!menu2.open()) stopUpdates();
|
|
14931
|
+
return menu2;
|
|
14932
|
+
}
|
|
14933
|
+
|
|
14934
|
+
// src/widget/legend.ts
|
|
14935
|
+
var COMPARE_ROW_PREFIX = "cmp:";
|
|
14936
|
+
var HOST_ROW_PREFIX = "host:";
|
|
14937
|
+
function barIndexAt(bars, time) {
|
|
14938
|
+
if (bars.length === 0) return -1;
|
|
14939
|
+
if (time === null) return bars.length - 1;
|
|
14940
|
+
let lo = 0;
|
|
14941
|
+
let hi = bars.length - 1;
|
|
14942
|
+
while (lo < hi) {
|
|
14943
|
+
const mid = lo + hi + 1 >> 1;
|
|
14944
|
+
if (bars[mid].t <= time) lo = mid;
|
|
14945
|
+
else hi = mid - 1;
|
|
14946
|
+
}
|
|
14947
|
+
return lo;
|
|
14948
|
+
}
|
|
14949
|
+
var percentWriters = /* @__PURE__ */ new Map();
|
|
14950
|
+
function percentText(fraction, tag) {
|
|
14951
|
+
let writer = percentWriters.get(tag);
|
|
14952
|
+
if (!writer) {
|
|
14953
|
+
writer = new Intl.NumberFormat(tag);
|
|
14954
|
+
percentWriters.set(tag, writer);
|
|
14955
|
+
}
|
|
14956
|
+
const points = Math.round(fraction * 1e4) / 100;
|
|
14957
|
+
return `${points > 0 ? "+" : ""}${writer.format(points)}`;
|
|
14958
|
+
}
|
|
14959
|
+
function attachLegendPlane(deps) {
|
|
14960
|
+
if (!deps.enabled) {
|
|
14961
|
+
return {
|
|
14962
|
+
push: () => void 0,
|
|
14963
|
+
setHeader: () => void 0,
|
|
14964
|
+
setDot: () => void 0,
|
|
14965
|
+
setHostRows: () => void 0,
|
|
14966
|
+
destroy: () => void 0
|
|
14967
|
+
};
|
|
14968
|
+
}
|
|
14969
|
+
let destroyed = false;
|
|
14970
|
+
const hostRows = /* @__PURE__ */ new Map();
|
|
14971
|
+
const paneRemembered = /* @__PURE__ */ new Map();
|
|
14972
|
+
const paneKeys = () => {
|
|
14973
|
+
const keys = { 0: "main" };
|
|
14974
|
+
for (const [id, pane] of Object.entries(deps.indicators.renderer.paneOf())) if (pane > 0) keys[pane] = `indicator:${id}`;
|
|
14975
|
+
for (const entry of deps.compare?.api.list() ?? []) {
|
|
14976
|
+
const pane = deps.compare.handle.paneIndexOf(entry.symbol);
|
|
14977
|
+
if (pane !== null && pane > 0) keys[pane] = `compare:${entry.symbol}`;
|
|
14978
|
+
}
|
|
14979
|
+
return keys;
|
|
14980
|
+
};
|
|
14981
|
+
let legend2 = null;
|
|
14982
|
+
let status2 = null;
|
|
14983
|
+
let hovered = null;
|
|
14984
|
+
let named = null;
|
|
14985
|
+
let namedTimeframe = null;
|
|
14986
|
+
legend2 = mountChartLegend(deps.chrome, deps.i18n, {
|
|
14987
|
+
// Every row control is a COMMAND. The legend states an intent by id and the registry decides
|
|
14988
|
+
// whether it may run, so a verb the host forbade cannot be reached by clicking either.
|
|
14989
|
+
onToggleEye: (id) => {
|
|
14990
|
+
if (id.startsWith(COMPARE_ROW_PREFIX)) {
|
|
14991
|
+
const symbol = id.slice(COMPARE_ROW_PREFIX.length);
|
|
14992
|
+
const entry = deps.compare?.api.list().find((e) => e.symbol === symbol);
|
|
14993
|
+
if (entry) deps.commands.execute("chart.compare.setVisible", { symbol, visible: !entry.visible });
|
|
14994
|
+
return;
|
|
14995
|
+
}
|
|
14996
|
+
deps.commands.execute(deps.indicators.isHidden(id) ? "chart.indicators.show" : "chart.indicators.hide", id);
|
|
14997
|
+
},
|
|
14998
|
+
onTitle: (id) => {
|
|
14999
|
+
if (id.startsWith(COMPARE_ROW_PREFIX)) deps.commands.execute("chart.compare.changeSymbol", id.slice(COMPARE_ROW_PREFIX.length));
|
|
15000
|
+
},
|
|
15001
|
+
onRemove: (id) => {
|
|
15002
|
+
if (id.startsWith(COMPARE_ROW_PREFIX)) deps.commands.execute("chart.compare.remove", id.slice(COMPARE_ROW_PREFIX.length));
|
|
15003
|
+
else deps.commands.execute("chart.indicators.remove", id);
|
|
15004
|
+
},
|
|
15005
|
+
...deps.symbolSearch ? { onSymbol: () => deps.openSearch() } : {},
|
|
15006
|
+
painters: deps.painters,
|
|
15007
|
+
icons: deps.icons,
|
|
15008
|
+
...deps.marketStatus ? {
|
|
15009
|
+
onStatus: (anchor) => {
|
|
15010
|
+
if (status2) {
|
|
15011
|
+
status2.close();
|
|
15012
|
+
return;
|
|
15013
|
+
}
|
|
15014
|
+
status2 = openMarketStatus(anchor, {
|
|
15015
|
+
host: deps.chrome,
|
|
15016
|
+
i18n: deps.i18n,
|
|
15017
|
+
model: deps.sessionModel,
|
|
15018
|
+
status: deps.status,
|
|
15019
|
+
onClose: () => {
|
|
15020
|
+
status2 = null;
|
|
15021
|
+
}
|
|
15022
|
+
});
|
|
15023
|
+
}
|
|
15024
|
+
} : {},
|
|
15025
|
+
onSettings: (id, rect) => {
|
|
15026
|
+
const host2 = hostRows.get(id);
|
|
15027
|
+
if (host2) {
|
|
15028
|
+
host2.onSettings?.();
|
|
15029
|
+
return;
|
|
15030
|
+
}
|
|
15031
|
+
if (deps.openIndicatorSettings(id)) return;
|
|
15032
|
+
const inst = deps.indicators.list().find((i) => i.id === id);
|
|
15033
|
+
if (!inst) return;
|
|
15034
|
+
mountInputsEditor(
|
|
15035
|
+
deps.chrome,
|
|
15036
|
+
rect,
|
|
15037
|
+
inst.definition.manifest.inputs ?? {},
|
|
15038
|
+
{ ...manifestInputDefaults(inst.definition.manifest), ...inst.inputs },
|
|
15039
|
+
(patch) => deps.indicators.patchInputs(id, patch),
|
|
15040
|
+
deps.i18n,
|
|
15041
|
+
deps.icons
|
|
15042
|
+
);
|
|
15043
|
+
},
|
|
15044
|
+
onPaneOp: (id, op) => {
|
|
15045
|
+
const paneIdx = deps.indicators.renderer.paneOf()[id];
|
|
15046
|
+
if (paneIdx === void 0 || paneIdx === 0) return;
|
|
15047
|
+
const panes = deps.chart.panes();
|
|
15048
|
+
const heights = {};
|
|
15049
|
+
panes.forEach((p, i) => heights[i] = p.getHeight());
|
|
15050
|
+
const keys = paneKeys();
|
|
15051
|
+
const remembered = {};
|
|
15052
|
+
for (const [index, key] of Object.entries(keys)) {
|
|
15053
|
+
const height = paneRemembered.get(key);
|
|
15054
|
+
if (height !== void 0) remembered[Number(index)] = height;
|
|
15055
|
+
}
|
|
15056
|
+
const plan = planPaneOp({ heights, remembered }, { kind: op, pane: paneIdx });
|
|
15057
|
+
paneRemembered.clear();
|
|
15058
|
+
for (const [index, height] of Object.entries(plan.remembered)) {
|
|
15059
|
+
const key = keys[Number(index)];
|
|
15060
|
+
if (key) paneRemembered.set(key, height);
|
|
15061
|
+
}
|
|
15062
|
+
for (const [i, h2] of Object.entries(plan.apply)) {
|
|
15063
|
+
const index = Number(i);
|
|
15064
|
+
panes[index]?.setHeight(h2);
|
|
15065
|
+
if (index > 0) deps.indicators.setPaneCollapsed(index, h2 <= COLLAPSED_H);
|
|
15066
|
+
}
|
|
15067
|
+
deps.indicators.recompute();
|
|
15068
|
+
}
|
|
15069
|
+
});
|
|
15070
|
+
function reading() {
|
|
15071
|
+
const bars = deps.bars();
|
|
15072
|
+
const index = barIndexAt(bars, hovered);
|
|
15073
|
+
const bar = index < 0 ? void 0 : bars[index];
|
|
15074
|
+
if (!bar) return null;
|
|
15075
|
+
const previous = index > 0 ? bars[index - 1] : void 0;
|
|
15076
|
+
const format2 = deps.formatter();
|
|
15077
|
+
const change = previous ? bar.c - previous.c : null;
|
|
15078
|
+
const fraction = change !== null && previous && previous.c !== 0 ? change / previous.c : null;
|
|
15079
|
+
return {
|
|
15080
|
+
open: format2.format(bar.o),
|
|
15081
|
+
high: format2.format(bar.h),
|
|
15082
|
+
low: format2.format(bar.l),
|
|
15083
|
+
close: format2.format(bar.c),
|
|
15084
|
+
change: change === null ? null : `${change > 0 ? "+" : ""}${format2.format(change)}`,
|
|
15085
|
+
percent: fraction === null ? null : percentText(fraction, deps.i18n.tag()),
|
|
15086
|
+
direction: change === null || change === 0 ? "flat" : change > 0 ? "up" : "down"
|
|
15087
|
+
};
|
|
15240
15088
|
}
|
|
15089
|
+
const paint = () => {
|
|
15090
|
+
if (destroyed) return;
|
|
15091
|
+
const alive = new Set(Object.values(paneKeys()));
|
|
15092
|
+
for (const key of paneRemembered.keys()) if (!alive.has(key)) paneRemembered.delete(key);
|
|
15093
|
+
legend2?.setValueShaped(deps.valueShaped());
|
|
15094
|
+
legend2?.setQuote(deps.legendValues ? reading() : null);
|
|
15095
|
+
const paneOf = deps.indicators.renderer.paneOf();
|
|
15096
|
+
const shown2 = (command2) => deps.shown?.(command2) ?? true;
|
|
15097
|
+
legend2?.setChips([
|
|
15098
|
+
...deps.indicators.chipsAt(hovered).map((row2) => {
|
|
15099
|
+
const paneIndex = paneOf[row2.id] ?? 0;
|
|
15100
|
+
const remembered = paneRemembered.get(`indicator:${row2.id}`);
|
|
15101
|
+
return {
|
|
15102
|
+
...row2,
|
|
15103
|
+
paneIndex,
|
|
15104
|
+
maximized: remembered !== void 0 && !row2.collapsed && (deps.chart.panes()[paneIndex]?.getHeight() ?? 0) > remembered,
|
|
15105
|
+
...shown2(row2.hidden ? "chart.indicators.show" : "chart.indicators.hide") ? {} : { hideable: false },
|
|
15106
|
+
...shown2("chart.indicators.remove") ? {} : { removable: false }
|
|
15107
|
+
};
|
|
15108
|
+
}),
|
|
15109
|
+
...(deps.compare?.chips(hovered) ?? []).map((row2) => ({
|
|
15110
|
+
...row2,
|
|
15111
|
+
paneIndex: deps.compare.handle.paneIndexOf(row2.id.slice(COMPARE_ROW_PREFIX.length)) ?? 0,
|
|
15112
|
+
...shown2("chart.compare.setVisible") ? {} : { hideable: false },
|
|
15113
|
+
...shown2("chart.compare.remove") ? {} : { removable: false }
|
|
15114
|
+
})),
|
|
15115
|
+
...[...hostRows].map(([id, row2]) => ({
|
|
15116
|
+
id,
|
|
15117
|
+
title: row2.title,
|
|
15118
|
+
inputs: row2.inputs,
|
|
15119
|
+
value: null,
|
|
15120
|
+
note: row2.status,
|
|
15121
|
+
description: row2.description,
|
|
15122
|
+
settingsLabel: row2.settingsLabel,
|
|
15123
|
+
hidden: false,
|
|
15124
|
+
hideable: false,
|
|
15125
|
+
removable: false,
|
|
15126
|
+
hasInputs: !!row2.onSettings,
|
|
15127
|
+
paneIndex: 0
|
|
15128
|
+
}))
|
|
15129
|
+
]);
|
|
15130
|
+
const tops = {};
|
|
15131
|
+
let top = 0;
|
|
15132
|
+
const panes = deps.chart.panes();
|
|
15133
|
+
const first = panes[0]?.getHTMLElement()?.getBoundingClientRect();
|
|
15134
|
+
for (const [index, pane] of panes.entries()) {
|
|
15135
|
+
const element = pane.getHTMLElement();
|
|
15136
|
+
const rect = element?.getBoundingClientRect();
|
|
15137
|
+
tops[index] = rect && first && rect.height > 0 ? rect.top - first.top : top;
|
|
15138
|
+
top += pane.getHeight();
|
|
15139
|
+
if (element && !observed.has(element)) {
|
|
15140
|
+
observed.add(element);
|
|
15141
|
+
resize?.observe(element);
|
|
15142
|
+
}
|
|
15143
|
+
}
|
|
15144
|
+
const current = new Set(panes.map((pane) => pane.getHTMLElement()));
|
|
15145
|
+
for (const element of observed) if (!current.has(element)) {
|
|
15146
|
+
resize?.unobserve(element);
|
|
15147
|
+
observed.delete(element);
|
|
15148
|
+
}
|
|
15149
|
+
legend2?.setPaneTops(tops);
|
|
15150
|
+
try {
|
|
15151
|
+
const start = deps.chart.priceScale("left").width();
|
|
15152
|
+
const end = deps.chart.priceScale("right").width();
|
|
15153
|
+
legend2?.setScaleInsets(start, end, deps.chart.timeScale().height());
|
|
15154
|
+
deps.chrome.style.setProperty("--qcp-plot-start", `${start}px`);
|
|
15155
|
+
deps.chrome.style.setProperty("--qcp-plot-end", `${end}px`);
|
|
15156
|
+
} catch {
|
|
15157
|
+
}
|
|
15158
|
+
};
|
|
15159
|
+
const observed = /* @__PURE__ */ new Set();
|
|
15160
|
+
const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => paint());
|
|
15161
|
+
const onCrosshair = (param) => {
|
|
15162
|
+
if (deps.replayPhase() === "arming")
|
|
15163
|
+
legend2?.setReplayGuide(param.point ? { x: param.point.x, y: param.point.y } : null, deps.chart.timeScale().height());
|
|
15164
|
+
const next = typeof param.time === "number" && Number.isFinite(param.time) ? param.time : null;
|
|
15165
|
+
if (next === hovered) return;
|
|
15166
|
+
hovered = next;
|
|
15167
|
+
paint();
|
|
15168
|
+
};
|
|
15169
|
+
deps.chart.subscribeCrosshairMove(onCrosshair);
|
|
15170
|
+
return {
|
|
15171
|
+
setHostRows(rows2) {
|
|
15172
|
+
if (destroyed) return;
|
|
15173
|
+
hostRows.clear();
|
|
15174
|
+
for (const row2 of rows2) hostRows.set(`${HOST_ROW_PREFIX}${row2.id}`, { ...row2 });
|
|
15175
|
+
paint();
|
|
15176
|
+
},
|
|
15177
|
+
push() {
|
|
15178
|
+
paint();
|
|
15179
|
+
},
|
|
15180
|
+
setHeader(symbol, tf) {
|
|
15181
|
+
if (symbol !== named || deps.replayPhase() !== "off") {
|
|
15182
|
+
status2?.close();
|
|
15183
|
+
status2 = null;
|
|
15184
|
+
}
|
|
15185
|
+
legend2?.setReplay(deps.replayPhase());
|
|
15186
|
+
if (symbol !== named || tf !== namedTimeframe) {
|
|
15187
|
+
named = symbol;
|
|
15188
|
+
namedTimeframe = tf;
|
|
15189
|
+
hovered = null;
|
|
15190
|
+
}
|
|
15191
|
+
const info = deps.symbolInfo();
|
|
15192
|
+
const label2 = symbolNames(info ?? symbol).title;
|
|
15193
|
+
legend2?.setIdentity({ name: label2, symbol, timeframe: tf, exchange: info?.exchange ?? "" });
|
|
15194
|
+
},
|
|
15195
|
+
setDot(state) {
|
|
15196
|
+
const current = deps.status(Math.floor(Date.now() / 1e3));
|
|
15197
|
+
legend2?.setDot(state, current ? marketStatusTitle(deps.i18n.t, current) : deps.i18n.t("status.unknownTitle"));
|
|
15198
|
+
status2?.refresh();
|
|
15199
|
+
},
|
|
15200
|
+
destroy() {
|
|
15201
|
+
destroyed = true;
|
|
15202
|
+
hostRows.clear();
|
|
15203
|
+
resize?.disconnect();
|
|
15204
|
+
observed.clear();
|
|
15205
|
+
deps.chart.unsubscribeCrosshairMove(onCrosshair);
|
|
15206
|
+
status2?.close();
|
|
15207
|
+
status2 = null;
|
|
15208
|
+
legend2?.destroy();
|
|
15209
|
+
legend2 = null;
|
|
15210
|
+
}
|
|
15211
|
+
};
|
|
15212
|
+
}
|
|
15213
|
+
|
|
15214
|
+
// src/widget/fling.ts
|
|
15215
|
+
function attachFling(deps) {
|
|
15216
|
+
const scale = () => deps.chart.timeScale();
|
|
15217
|
+
let samples = [];
|
|
15218
|
+
let movedAt = null;
|
|
15219
|
+
let oneFinger = false;
|
|
15220
|
+
let frame = null;
|
|
15221
|
+
const stop = () => {
|
|
15222
|
+
if (frame !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frame);
|
|
15223
|
+
frame = null;
|
|
15224
|
+
};
|
|
15225
|
+
const record3 = (t) => {
|
|
15226
|
+
samples.push({ t, position: scale().scrollPosition() });
|
|
15227
|
+
while (samples.length > 2 && samples[0].t < t - 2 * FLING_SAMPLE_MS) samples.shift();
|
|
15228
|
+
};
|
|
15229
|
+
const coast = (speed) => {
|
|
15230
|
+
if (typeof requestAnimationFrame !== "function") return;
|
|
15231
|
+
let last = performance.now();
|
|
15232
|
+
let travelling = speed;
|
|
15233
|
+
let position = null;
|
|
15234
|
+
const step = (now) => {
|
|
15235
|
+
if (frame === null) return;
|
|
15236
|
+
const s = scale();
|
|
15237
|
+
position ??= s.scrollPosition();
|
|
15238
|
+
const next = flingStep(travelling, Math.max(0, now - last));
|
|
15239
|
+
last = now;
|
|
15240
|
+
travelling = next.speed;
|
|
15241
|
+
position += next.moved;
|
|
15242
|
+
s.scrollToPosition(position, false);
|
|
15243
|
+
if (Math.abs(travelling) * s.options().barSpacing < FLING_REST_PX_PER_MS) {
|
|
15244
|
+
frame = null;
|
|
15245
|
+
return;
|
|
15246
|
+
}
|
|
15247
|
+
frame = requestAnimationFrame(step);
|
|
15248
|
+
};
|
|
15249
|
+
frame = requestAnimationFrame(step);
|
|
15250
|
+
};
|
|
15251
|
+
const onStart = (event) => {
|
|
15252
|
+
stop();
|
|
15253
|
+
samples = [];
|
|
15254
|
+
movedAt = null;
|
|
15255
|
+
oneFinger = event.touches.length === 1;
|
|
15256
|
+
if (oneFinger) record3(performance.now());
|
|
15257
|
+
};
|
|
15258
|
+
const onMove = (event) => {
|
|
15259
|
+
if (event.touches.length !== 1) oneFinger = false;
|
|
15260
|
+
if (!oneFinger) return;
|
|
15261
|
+
if (movedAt !== null) record3(movedAt);
|
|
15262
|
+
movedAt = performance.now();
|
|
15263
|
+
};
|
|
15264
|
+
const onEnd = (event) => {
|
|
15265
|
+
const thrown = oneFinger && event.touches.length === 0;
|
|
15266
|
+
oneFinger = false;
|
|
15267
|
+
if (!thrown) return;
|
|
15268
|
+
if (movedAt !== null) record3(movedAt);
|
|
15269
|
+
const spacing = scale().options().barSpacing;
|
|
15270
|
+
const speed = flingSpeed(samples, performance.now(), spacing);
|
|
15271
|
+
samples = [];
|
|
15272
|
+
movedAt = null;
|
|
15273
|
+
if (Math.abs(speed) * spacing >= FLING_REST_PX_PER_MS) coast(speed);
|
|
15274
|
+
};
|
|
15275
|
+
const onCancel = () => {
|
|
15276
|
+
oneFinger = false;
|
|
15277
|
+
samples = [];
|
|
15278
|
+
movedAt = null;
|
|
15279
|
+
};
|
|
15280
|
+
deps.target.addEventListener("touchstart", onStart, { passive: true });
|
|
15281
|
+
deps.target.addEventListener("touchmove", onMove, { passive: true });
|
|
15282
|
+
deps.target.addEventListener("touchend", onEnd, { passive: true });
|
|
15283
|
+
deps.target.addEventListener("touchcancel", onCancel, { passive: true });
|
|
15284
|
+
return {
|
|
15285
|
+
stop,
|
|
15286
|
+
destroy() {
|
|
15287
|
+
stop();
|
|
15288
|
+
deps.target.removeEventListener("touchstart", onStart);
|
|
15289
|
+
deps.target.removeEventListener("touchmove", onMove);
|
|
15290
|
+
deps.target.removeEventListener("touchend", onEnd);
|
|
15291
|
+
deps.target.removeEventListener("touchcancel", onCancel);
|
|
15292
|
+
}
|
|
15293
|
+
};
|
|
15294
|
+
}
|
|
15295
|
+
|
|
15296
|
+
// src/widget/pinch.ts
|
|
15297
|
+
function attachPinch(deps) {
|
|
15298
|
+
const scale = () => deps.chart.timeScale();
|
|
15299
|
+
let pinch = null;
|
|
15300
|
+
let panned = false;
|
|
15301
|
+
const read = (touches) => {
|
|
15302
|
+
const a = touches[0];
|
|
15303
|
+
const b = touches[1];
|
|
15304
|
+
const left = deps.chart.chartElement().getBoundingClientRect().left + deps.chart.priceScale("left").width();
|
|
15305
|
+
return { distance: Math.hypot(a.clientX - b.clientX, a.clientY - b.clientY), x: (a.clientX + b.clientX) / 2 - left };
|
|
15306
|
+
};
|
|
15307
|
+
const begin = (event) => {
|
|
15308
|
+
pinch = null;
|
|
15309
|
+
if (event.touches.length === 1) panned = false;
|
|
15310
|
+
if (event.touches.length !== 2 || panned || !scalingOpen(deps.chart.options().handleScale)) return;
|
|
15311
|
+
const range2 = scale().getVisibleLogicalRange();
|
|
15312
|
+
if (range2 === null) return;
|
|
15313
|
+
const { distance, x } = read(event.touches);
|
|
15314
|
+
pinch = pinchStart(range2, scale().width(), x, distance);
|
|
15315
|
+
};
|
|
15316
|
+
const move = (event) => {
|
|
15317
|
+
if (event.touches.length === 1 && pinch === null) panned = true;
|
|
15318
|
+
if (pinch === null || event.touches.length !== 2) return;
|
|
15319
|
+
if (!scalingOpen(deps.chart.options().handleScale)) {
|
|
15320
|
+
pinch = null;
|
|
15321
|
+
return;
|
|
15322
|
+
}
|
|
15323
|
+
const { distance, x } = read(event.touches);
|
|
15324
|
+
const s = scale();
|
|
15325
|
+
const width = s.width();
|
|
15326
|
+
const options = s.options();
|
|
15327
|
+
const plot = { width, minSpacing: options.minBarSpacing, maxSpacing: options.maxBarSpacing > 0 ? options.maxBarSpacing : width / 2 };
|
|
15328
|
+
s.setVisibleLogicalRange(pinchRange(pinch, x, distance, plot));
|
|
15329
|
+
};
|
|
15330
|
+
const end = (event) => {
|
|
15331
|
+
if (event.touches.length === 1) panned = false;
|
|
15332
|
+
if (event.touches.length === 2) begin(event);
|
|
15333
|
+
else pinch = null;
|
|
15334
|
+
};
|
|
15335
|
+
deps.target.addEventListener("touchstart", begin, { passive: true });
|
|
15336
|
+
deps.target.addEventListener("touchmove", move, { passive: true });
|
|
15337
|
+
deps.target.addEventListener("touchend", end, { passive: true });
|
|
15338
|
+
deps.target.addEventListener("touchcancel", end, { passive: true });
|
|
15339
|
+
return {
|
|
15340
|
+
destroy() {
|
|
15341
|
+
pinch = null;
|
|
15342
|
+
deps.target.removeEventListener("touchstart", begin);
|
|
15343
|
+
deps.target.removeEventListener("touchmove", move);
|
|
15344
|
+
deps.target.removeEventListener("touchend", end);
|
|
15345
|
+
deps.target.removeEventListener("touchcancel", end);
|
|
15346
|
+
}
|
|
15347
|
+
};
|
|
15241
15348
|
}
|
|
15242
15349
|
|
|
15243
|
-
// src/
|
|
15244
|
-
function
|
|
15245
|
-
|
|
15246
|
-
const
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
const drawn = drawHostIcon(factory, { document: deps.document, width: box.width, height: box.height, direction });
|
|
15252
|
-
if ("failure" in drawn) {
|
|
15253
|
-
deps.diagnostics.report(icon, drawn.failure);
|
|
15254
|
-
return null;
|
|
15255
|
-
}
|
|
15256
|
-
const record3 = { element: new WeakRef(drawn.element), factory, box, icon, direction };
|
|
15257
|
-
standing.add(record3);
|
|
15258
|
-
forget.register(drawn.element, record3, record3);
|
|
15259
|
-
return drawn.element;
|
|
15350
|
+
// src/widget/freePan.ts
|
|
15351
|
+
function attachFreePan(deps) {
|
|
15352
|
+
let landed = null;
|
|
15353
|
+
const onPlot = (clientX, clientY) => {
|
|
15354
|
+
const box = deps.chart.chartElement().getBoundingClientRect();
|
|
15355
|
+
const left = box.left + deps.chart.priceScale("left").width();
|
|
15356
|
+
const right = left + deps.chart.timeScale().width();
|
|
15357
|
+
return clientX >= left && clientX <= right && clientY >= box.top && clientY <= box.bottom - deps.chart.timeScale().height();
|
|
15260
15358
|
};
|
|
15261
|
-
const
|
|
15262
|
-
|
|
15263
|
-
return factory ? draw(factory, box, id) : null;
|
|
15359
|
+
const release = () => {
|
|
15360
|
+
if (deps.framing()) deps.release();
|
|
15264
15361
|
};
|
|
15265
|
-
const
|
|
15266
|
-
|
|
15267
|
-
|
|
15268
|
-
if (
|
|
15269
|
-
|
|
15270
|
-
if (!element) {
|
|
15271
|
-
standing.delete(record3);
|
|
15272
|
-
continue;
|
|
15273
|
-
}
|
|
15274
|
-
if (!element.parentNode) continue;
|
|
15275
|
-
const fresh = draw(record3.factory, record3.box, record3.icon);
|
|
15276
|
-
if (!fresh) continue;
|
|
15277
|
-
element.replaceWith(fresh);
|
|
15278
|
-
standing.delete(record3);
|
|
15279
|
-
forget.unregister(record3);
|
|
15362
|
+
const onStart = (event) => {
|
|
15363
|
+
landed = null;
|
|
15364
|
+
if (event.touches.length === 2) {
|
|
15365
|
+
if (scalingOpen(deps.chart.options().handleScale)) release();
|
|
15366
|
+
return;
|
|
15280
15367
|
}
|
|
15368
|
+
const touch = event.touches[0];
|
|
15369
|
+
if (event.touches.length !== 1 || !touch || !onPlot(touch.clientX, touch.clientY)) return;
|
|
15370
|
+
landed = { x: touch.clientX, y: touch.clientY, at: performance.now() };
|
|
15281
15371
|
};
|
|
15282
|
-
const
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
const span = deps.document.createElement("span");
|
|
15289
|
-
span.className = `qc-icon${options.className ? ` ${options.className}` : ""}`;
|
|
15290
|
-
span.setAttribute("aria-hidden", "true");
|
|
15291
|
-
span.append(drawn);
|
|
15292
|
-
return span;
|
|
15293
|
-
}
|
|
15372
|
+
const onMove = (event) => {
|
|
15373
|
+
if (landed === null) return;
|
|
15374
|
+
const touch = event.touches[0];
|
|
15375
|
+
if (event.touches.length !== 1 || !touch) {
|
|
15376
|
+
landed = null;
|
|
15377
|
+
return;
|
|
15294
15378
|
}
|
|
15295
|
-
|
|
15379
|
+
if (Math.abs(touch.clientX - landed.x) + Math.abs(touch.clientY - landed.y) < RENDERER_DRAG_START_PX) return;
|
|
15380
|
+
const started = landed;
|
|
15381
|
+
landed = null;
|
|
15382
|
+
if (performance.now() - started.at >= RENDERER_LONG_TAP_MS) return;
|
|
15383
|
+
if (scrollOpen(deps.chart.options().handleScroll)) release();
|
|
15296
15384
|
};
|
|
15297
|
-
const
|
|
15298
|
-
|
|
15299
|
-
const holder = deps.document.createElement("span");
|
|
15300
|
-
holder.innerHTML = `<svg width="${width}" height="${height}" viewBox="${mark.viewBox}" fill="none" aria-hidden="true">${mark.body}</svg>`;
|
|
15301
|
-
return holder.firstElementChild;
|
|
15385
|
+
const onEnd = () => {
|
|
15386
|
+
landed = null;
|
|
15302
15387
|
};
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15388
|
+
deps.target.addEventListener("touchstart", onStart, { passive: true });
|
|
15389
|
+
deps.target.addEventListener("touchmove", onMove, { passive: true });
|
|
15390
|
+
deps.target.addEventListener("touchend", onEnd, { passive: true });
|
|
15391
|
+
deps.target.addEventListener("touchcancel", onEnd, { passive: true });
|
|
15392
|
+
return {
|
|
15393
|
+
destroy() {
|
|
15394
|
+
landed = null;
|
|
15395
|
+
deps.target.removeEventListener("touchstart", onStart);
|
|
15396
|
+
deps.target.removeEventListener("touchmove", onMove);
|
|
15397
|
+
deps.target.removeEventListener("touchend", onEnd);
|
|
15398
|
+
deps.target.removeEventListener("touchcancel", onEnd);
|
|
15399
|
+
}
|
|
15400
|
+
};
|
|
15401
|
+
}
|
|
15402
|
+
|
|
15403
|
+
// src/widget/plotArea.ts
|
|
15404
|
+
function measurePlotArea(chart, host2) {
|
|
15405
|
+
const row2 = chart.panes()[0]?.getHTMLElement();
|
|
15406
|
+
if (!row2) return null;
|
|
15407
|
+
const size = chart.paneSize(0);
|
|
15408
|
+
if (!(size.width > 0) || !(size.height > 0)) return null;
|
|
15409
|
+
const outer = host2.getBoundingClientRect();
|
|
15410
|
+
const top = row2.getBoundingClientRect().top;
|
|
15411
|
+
const left = chart.chartElement().getBoundingClientRect().left + chart.priceScale("left").width();
|
|
15412
|
+
const round = (n) => Math.round(n * 100) / 100;
|
|
15413
|
+
return {
|
|
15414
|
+
top: round(top - outer.top),
|
|
15415
|
+
right: round(outer.right - (left + size.width)),
|
|
15416
|
+
bottom: round(outer.bottom - (top + size.height)),
|
|
15417
|
+
left: round(left - outer.left),
|
|
15418
|
+
width: round(size.width),
|
|
15419
|
+
height: round(size.height)
|
|
15420
|
+
};
|
|
15421
|
+
}
|
|
15422
|
+
var sameArea = (a, b) => b !== null && a.top === b.top && a.right === b.right && a.bottom === b.bottom && a.left === b.left && a.width === b.width && a.height === b.height;
|
|
15423
|
+
function watchPlotArea(deps) {
|
|
15424
|
+
let area = null;
|
|
15425
|
+
let frame = null;
|
|
15426
|
+
let destroyed = false;
|
|
15427
|
+
let row2 = null;
|
|
15428
|
+
const resize = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(() => schedule());
|
|
15429
|
+
const measure2 = () => {
|
|
15430
|
+
frame = null;
|
|
15431
|
+
if (destroyed) return;
|
|
15432
|
+
const nextRow = deps.chart.panes()[0]?.getHTMLElement() ?? null;
|
|
15433
|
+
if (nextRow !== row2) {
|
|
15434
|
+
if (row2) resize?.unobserve(row2);
|
|
15435
|
+
if (nextRow) resize?.observe(nextRow);
|
|
15436
|
+
row2 = nextRow;
|
|
15437
|
+
}
|
|
15438
|
+
const next = measurePlotArea(deps.chart, deps.host);
|
|
15439
|
+
if (next === null || sameArea(next, area)) return;
|
|
15440
|
+
area = next;
|
|
15441
|
+
deps.changed(next);
|
|
15306
15442
|
};
|
|
15443
|
+
function schedule() {
|
|
15444
|
+
if (destroyed || frame !== null) return;
|
|
15445
|
+
if (typeof requestAnimationFrame !== "function") {
|
|
15446
|
+
measure2();
|
|
15447
|
+
return;
|
|
15448
|
+
}
|
|
15449
|
+
frame = requestAnimationFrame(measure2);
|
|
15450
|
+
}
|
|
15451
|
+
deps.chart.timeScale().subscribeSizeChange(schedule);
|
|
15452
|
+
resize?.observe(deps.host);
|
|
15453
|
+
resize?.observe(deps.chart.chartElement());
|
|
15454
|
+
schedule();
|
|
15307
15455
|
return {
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
const height = requested ?? mark.size ?? 28;
|
|
15312
|
-
return bare(mark, widthFor(mark, height), height);
|
|
15313
|
-
},
|
|
15314
|
-
tool(type, size = 28) {
|
|
15315
|
-
const mark = toolGlyph(type);
|
|
15316
|
-
return mark ? bare(mark, size, size) : null;
|
|
15456
|
+
current() {
|
|
15457
|
+
if (destroyed) return null;
|
|
15458
|
+
return area ?? measurePlotArea(deps.chart, deps.host);
|
|
15317
15459
|
},
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15460
|
+
destroy() {
|
|
15461
|
+
if (destroyed) return;
|
|
15462
|
+
destroyed = true;
|
|
15463
|
+
if (frame !== null && typeof cancelAnimationFrame === "function") cancelAnimationFrame(frame);
|
|
15464
|
+
frame = null;
|
|
15465
|
+
resize?.disconnect();
|
|
15466
|
+
try {
|
|
15467
|
+
deps.chart.timeScale().unsubscribeSizeChange(schedule);
|
|
15468
|
+
} catch {
|
|
15469
|
+
}
|
|
15470
|
+
}
|
|
15321
15471
|
};
|
|
15322
15472
|
}
|
|
15323
15473
|
|
|
15474
|
+
// src/contextMenu.ts
|
|
15475
|
+
function chartContextMenuGroups(c) {
|
|
15476
|
+
const t = c.t ?? englishChartStrings();
|
|
15477
|
+
const clipboard2 = [{ kind: "item", id: "copy-price", label: t("menu.copyPrice", { price: c.priceText }) }];
|
|
15478
|
+
if (c.canPaste !== false) clipboard2.push({ kind: "item", id: "paste", label: t("menu.paste"), shortcut: t("drawing.hintPaste", { modifier: t(isApplePlatform() ? "drawing.modifierCommand" : "drawing.modifierControl") }) });
|
|
15479
|
+
const remove = [];
|
|
15480
|
+
if (c.indicatorCount > 0) remove.push({ kind: "item", id: "remove-indicators", label: t("menu.removeIndicators", { count: c.indicatorCount }) });
|
|
15481
|
+
if (c.drawingCount > 0) remove.push({ kind: "item", id: "remove-drawings", label: t("menu.removeDrawings", { count: c.drawingCount }) });
|
|
15482
|
+
return [
|
|
15483
|
+
{ slot: "view", rows: [{ kind: "item", id: "reset-view", label: t("menu.resetView"), shortcut: "Alt + R", icon: "reset" }] },
|
|
15484
|
+
{ slot: "clipboard", rows: clipboard2 },
|
|
15485
|
+
{ slot: "remove", rows: remove },
|
|
15486
|
+
{ slot: "settings", rows: c.canSettings !== false ? [{ kind: "item", id: "settings", label: t("menu.settings"), icon: "settings" }] : [] }
|
|
15487
|
+
];
|
|
15488
|
+
}
|
|
15489
|
+
function flattenMenuGroups(groups) {
|
|
15490
|
+
const rows2 = [];
|
|
15491
|
+
for (const g of groups.filter((g2) => g2.length > 0)) {
|
|
15492
|
+
if (rows2.length) rows2.push({ kind: "separator" });
|
|
15493
|
+
rows2.push(...g);
|
|
15494
|
+
}
|
|
15495
|
+
return rows2;
|
|
15496
|
+
}
|
|
15497
|
+
function chartContextMenu(c) {
|
|
15498
|
+
return flattenMenuGroups(chartContextMenuGroups(c).map((g) => g.rows));
|
|
15499
|
+
}
|
|
15500
|
+
|
|
15324
15501
|
// src/contextMenuUi.ts
|
|
15325
15502
|
var MENU_W = 327;
|
|
15326
15503
|
var ICONS2 = {
|
|
@@ -15943,10 +16120,11 @@ function registerChartCommands(deps) {
|
|
|
15943
16120
|
});
|
|
15944
16121
|
add({ id: "chart.view.reset", scope: "chart", label: "command.viewReset", shortcut: "Alt+KeyR", available: always, execute: () => handle.reset() });
|
|
15945
16122
|
add({ id: "chart.view.goLive", scope: "chart", label: "command.viewGoLive", shortcut: "Alt+KeyL", available: always, execute: () => handle.goLive() });
|
|
15946
|
-
|
|
15947
|
-
add({ id: "chart.view.
|
|
15948
|
-
add({ id: "chart.view.
|
|
15949
|
-
add({ id: "chart.view.
|
|
16123
|
+
const navigable = () => features.navigation;
|
|
16124
|
+
add({ id: "chart.view.zoomIn", scope: "chart", label: "command.viewZoomIn", shortcut: "Equal", available: navigable, execute: () => deps.zoom("in") });
|
|
16125
|
+
add({ id: "chart.view.zoomOut", scope: "chart", label: "command.viewZoomOut", shortcut: "Minus", available: navigable, execute: () => deps.zoom("out") });
|
|
16126
|
+
add({ id: "chart.view.scrollLeft", scope: "chart", label: "command.viewScrollLeft", shortcut: "ArrowLeft", available: navigable, execute: () => deps.scroll("left") });
|
|
16127
|
+
add({ id: "chart.view.scrollRight", scope: "chart", label: "command.viewScrollRight", shortcut: "ArrowRight", available: navigable, execute: () => deps.scroll("right") });
|
|
15950
16128
|
add({
|
|
15951
16129
|
id: "chart.data.download",
|
|
15952
16130
|
scope: "chart",
|
|
@@ -16750,14 +16928,21 @@ function createChartInstance(deps) {
|
|
|
16750
16928
|
vertLines: { color: canvas().grid, visible: eff.appearance.grid },
|
|
16751
16929
|
horzLines: { color: canvas().grid, visible: eff.appearance.grid }
|
|
16752
16930
|
},
|
|
16753
|
-
crosshair: {
|
|
16931
|
+
crosshair: {
|
|
16932
|
+
mode: deps.ui.crosshair ? CrosshairMode.Normal : CrosshairMode.Hidden,
|
|
16933
|
+
vertLine: { labelVisible: deps.ui.crosshairLabels, ...deps.ui.crosshairSolid ? { style: LineStyle3.Solid } : {} },
|
|
16934
|
+
horzLine: { visible: deps.ui.crosshairHorizontal, labelVisible: deps.ui.crosshairLabels, ...deps.ui.crosshairSolid ? { style: LineStyle3.Solid } : {} }
|
|
16935
|
+
},
|
|
16754
16936
|
// A finger held on the plot scrubs the crosshair for as long as it stays down, and lifting it
|
|
16755
16937
|
// takes the crosshair away, so the next one-finger drag pans: the way a native chart reads.
|
|
16756
16938
|
trackingMode: { exitMode: TrackingModeExitMode.OnTouchEnd },
|
|
16757
16939
|
// The renderer's own momentum throws a flick as fast as seven pixels a millisecond and coasts
|
|
16758
16940
|
// it thousands of pixels; the chart coasts a flick itself, calmly.
|
|
16759
16941
|
kineticScroll: { touch: false, mouse: false },
|
|
16760
|
-
|
|
16942
|
+
// A chart that holds its view takes no drag, wheel, pinch or scale gesture from the renderer.
|
|
16943
|
+
handleScroll: deps.features.navigation,
|
|
16944
|
+
handleScale: deps.features.navigation,
|
|
16945
|
+
rightPriceScale: { visible: deps.ui.priceScale, borderVisible: false, scaleMargins: { top: 0.08, bottom: 0.08 } },
|
|
16761
16946
|
timeScale: { borderVisible: false, timeVisible: true, secondsVisible: false, rightOffset: 4, barSpacing: 8, minBarSpacing: 0.5 }
|
|
16762
16947
|
});
|
|
16763
16948
|
const anchor = chart.addSeries(LineSeries4, {
|
|
@@ -16766,7 +16951,13 @@ function createChartInstance(deps) {
|
|
|
16766
16951
|
priceLineVisible: false,
|
|
16767
16952
|
crosshairMarkerVisible: false
|
|
16768
16953
|
});
|
|
16769
|
-
|
|
16954
|
+
const addMainSeries = (id) => {
|
|
16955
|
+
const added = addStyleSeries(chart, id, paint());
|
|
16956
|
+
if (!deps.ui.priceScale) added.applyOptions({ priceLineVisible: false, lastValueVisible: false });
|
|
16957
|
+
return added;
|
|
16958
|
+
};
|
|
16959
|
+
let series2 = addMainSeries(style);
|
|
16960
|
+
let morph = null;
|
|
16770
16961
|
const baselineLevel = createBaselineLevel({ paneHeight: () => chart.paneSize().height });
|
|
16771
16962
|
if (style === "baseline") baselineLevel.follow(series2);
|
|
16772
16963
|
const volume2 = chart.addSeries(HistogramSeries2, {
|
|
@@ -16897,15 +17088,17 @@ function createChartInstance(deps) {
|
|
|
16897
17088
|
const crosshairSubs = /* @__PURE__ */ new Set();
|
|
16898
17089
|
const timeClickSubs = /* @__PURE__ */ new Set();
|
|
16899
17090
|
const rangeSubs = /* @__PURE__ */ new Set();
|
|
17091
|
+
const reducedMotion = () => gestures.ownerDocument.defaultView?.matchMedia?.("(prefers-reduced-motion: reduce)").matches ?? false;
|
|
16900
17092
|
const ranges = createRangeApi({
|
|
16901
17093
|
chart,
|
|
16902
17094
|
disposed: disposedFn,
|
|
16903
17095
|
muted,
|
|
16904
17096
|
mirrored,
|
|
16905
17097
|
onGlide: () => followLiveEdge(),
|
|
16906
|
-
reducedMotion
|
|
17098
|
+
reducedMotion
|
|
16907
17099
|
});
|
|
16908
|
-
const
|
|
17100
|
+
const still = { stop: () => void 0, destroy: () => void 0 };
|
|
17101
|
+
const fling = deps.features.navigation ? attachFling({ chart, target: gestures }) : still;
|
|
16909
17102
|
let unregisterRangeMirror = () => void 0;
|
|
16910
17103
|
function applyTimezone() {
|
|
16911
17104
|
if (disposed) return;
|
|
@@ -17013,6 +17206,7 @@ function createChartInstance(deps) {
|
|
|
17013
17206
|
const drawings2 = attachDrawingsPlane({
|
|
17014
17207
|
chart,
|
|
17015
17208
|
series: anchor,
|
|
17209
|
+
navigable: deps.features.navigation,
|
|
17016
17210
|
container: gestures,
|
|
17017
17211
|
chrome: chrome2,
|
|
17018
17212
|
chartId: deps.id,
|
|
@@ -17086,7 +17280,7 @@ function createChartInstance(deps) {
|
|
|
17086
17280
|
setHeader: () => legend2.setHeader(symbol, tf),
|
|
17087
17281
|
// A chart whose crosshair the host switched OFF keeps it off: replay may take the crosshair
|
|
17088
17282
|
// away for the length of a question, never hand one back that was never there.
|
|
17089
|
-
setCrosshair: (visible) => chart.applyOptions({ crosshair: { mode: visible && deps.
|
|
17283
|
+
setCrosshair: (visible) => chart.applyOptions({ crosshair: { mode: visible && deps.ui.crosshair ? CrosshairMode.Normal : CrosshairMode.Hidden } }),
|
|
17090
17284
|
// The feed's own grains: a chart never offers, or fetches, a timeframe its feed cannot serve.
|
|
17091
17285
|
resolutions: () => deps.capabilities().resolutions,
|
|
17092
17286
|
persist: (key, value) => storage.set(key === "speed" ? REPLAY_SPEED_KEY : REPLAY_TIMEFRAME_KEY, value),
|
|
@@ -17120,6 +17314,7 @@ function createChartInstance(deps) {
|
|
|
17120
17314
|
const extensions = attachExtensionsPlane({
|
|
17121
17315
|
chartId: deps.id,
|
|
17122
17316
|
chart,
|
|
17317
|
+
navigable: deps.features.navigation,
|
|
17123
17318
|
series: () => anchor,
|
|
17124
17319
|
visible: () => series2,
|
|
17125
17320
|
gestures,
|
|
@@ -17227,8 +17422,8 @@ function createChartInstance(deps) {
|
|
|
17227
17422
|
navigationRoot.addEventListener("mouseup", onNativeDragEnd, { passive: true });
|
|
17228
17423
|
navigationRoot.addEventListener("pointerup", onNativeDragEnd, { passive: true });
|
|
17229
17424
|
navigationRoot.addEventListener("pointercancel", onNativeDragEnd, { passive: true });
|
|
17230
|
-
const pinch = attachPinch({ chart, target: gestures });
|
|
17231
|
-
const freePan = deps.freePan ? attachFreePan({
|
|
17425
|
+
const pinch = deps.features.navigation ? attachPinch({ chart, target: gestures }) : null;
|
|
17426
|
+
const freePan = deps.freePan && deps.features.navigation ? attachFreePan({
|
|
17232
17427
|
chart,
|
|
17233
17428
|
target: gestures,
|
|
17234
17429
|
framing: () => priceAxisPolicy() === "auto",
|
|
@@ -17252,9 +17447,11 @@ function createChartInstance(deps) {
|
|
|
17252
17447
|
const painted = shownBars();
|
|
17253
17448
|
const values = painted.map((b) => ({ time: b.t, value: b.c }));
|
|
17254
17449
|
anchor.setData(values);
|
|
17255
|
-
series2
|
|
17256
|
-
|
|
17257
|
-
|
|
17450
|
+
if (morph?.bars !== series2) {
|
|
17451
|
+
series2.setData(
|
|
17452
|
+
shaped ? values : painted.map((b) => ({ time: b.t, open: b.o, high: b.h, low: b.l, close: b.c }))
|
|
17453
|
+
);
|
|
17454
|
+
}
|
|
17258
17455
|
if (volumeInstance()) paintVolume();
|
|
17259
17456
|
indicators2.recompute();
|
|
17260
17457
|
compare?.sync();
|
|
@@ -17580,20 +17777,48 @@ function createChartInstance(deps) {
|
|
|
17580
17777
|
function setStyle(next) {
|
|
17581
17778
|
if (disposed || next === style || !deps.styles.includes(next)) return;
|
|
17582
17779
|
const keep = chart.timeScale().getVisibleLogicalRange();
|
|
17780
|
+
morph?.run.finish();
|
|
17583
17781
|
const previous = series2;
|
|
17782
|
+
const previousStyle = style;
|
|
17584
17783
|
style = next;
|
|
17585
17784
|
storage.set(STYLE_KEY, next);
|
|
17586
|
-
series2 =
|
|
17785
|
+
series2 = addMainSeries(next);
|
|
17587
17786
|
baselineLevel.follow(next === "baseline" ? series2 : null);
|
|
17588
17787
|
countdown?.seriesChanged(previous);
|
|
17589
17788
|
extensions.visibleSeriesReplaced();
|
|
17590
17789
|
applyPriceFormat();
|
|
17591
|
-
|
|
17592
|
-
|
|
17593
|
-
|
|
17594
|
-
|
|
17790
|
+
const remove = (leaving) => {
|
|
17791
|
+
try {
|
|
17792
|
+
chart.removeSeries(leaving);
|
|
17793
|
+
} catch {
|
|
17794
|
+
}
|
|
17795
|
+
};
|
|
17796
|
+
const folding = valueShaped(next) && !valueShaped(previousStyle);
|
|
17797
|
+
const unfolding = !valueShaped(next) && valueShaped(previousStyle);
|
|
17798
|
+
const morphing = !!deps.styleMorph && (folding || unfolding) && !reducedMotion();
|
|
17799
|
+
if (!morphing) remove(previous);
|
|
17595
17800
|
paintAll();
|
|
17596
17801
|
if (keep) chart.timeScale().setVisibleLogicalRange(keep);
|
|
17802
|
+
if (morphing) {
|
|
17803
|
+
const bars2 = folding ? previous : series2;
|
|
17804
|
+
const line2 = folding ? series2 : previous;
|
|
17805
|
+
const lineStyle2 = folding ? next : previousStyle;
|
|
17806
|
+
const entry = {
|
|
17807
|
+
bars: bars2,
|
|
17808
|
+
run: startStyleMorph({
|
|
17809
|
+
bars: bars2,
|
|
17810
|
+
fadeLine: (alpha) => line2.applyOptions(fadedStyleOptions(lineStyle2, paint(), alpha)),
|
|
17811
|
+
shown: shownBars,
|
|
17812
|
+
direction: folding ? "fold" : "unfold",
|
|
17813
|
+
done: () => {
|
|
17814
|
+
if (morph === entry) morph = null;
|
|
17815
|
+
remove(previous);
|
|
17816
|
+
if (folding) line2.applyOptions(styleOptions(lineStyle2, paint()));
|
|
17817
|
+
}
|
|
17818
|
+
})
|
|
17819
|
+
};
|
|
17820
|
+
morph = entry;
|
|
17821
|
+
}
|
|
17597
17822
|
events.emit("style", next);
|
|
17598
17823
|
}
|
|
17599
17824
|
function content() {
|
|
@@ -18005,8 +18230,9 @@ function createChartInstance(deps) {
|
|
|
18005
18230
|
countdownClock.destroy();
|
|
18006
18231
|
pointer?.destroy();
|
|
18007
18232
|
ranges.stopGlide();
|
|
18233
|
+
morph?.run.finish();
|
|
18008
18234
|
fling.destroy();
|
|
18009
|
-
pinch
|
|
18235
|
+
pinch?.destroy();
|
|
18010
18236
|
freePan?.destroy();
|
|
18011
18237
|
plotArea.destroy();
|
|
18012
18238
|
extensions.destroy();
|
|
@@ -19492,7 +19718,7 @@ function openIndicatorSettings(deps) {
|
|
|
19492
19718
|
const overrides = cloneOverrides(instance.overrides);
|
|
19493
19719
|
let hidden = chart.indicators.hidden().includes(instance.id);
|
|
19494
19720
|
const inputs2 = manifest2.inputs ?? {};
|
|
19495
|
-
const fields = buildInputFields(inputs2, { ...manifestInputDefaults(manifest2), ...instance.inputs }, builtIn.inputTitles);
|
|
19721
|
+
const fields = buildInputFields(deps.icons, inputs2, { ...manifestInputDefaults(manifest2), ...instance.inputs }, builtIn.inputTitles);
|
|
19496
19722
|
const tabs = [...Object.keys(inputs2).length > 0 ? [{ id: "inputs", label: t("settings.tabInputs") }] : [], { id: "style", label: t("settings.tabStyle") }, { id: "visibility", label: t("settings.tabVisibility") }];
|
|
19497
19723
|
let tab = tabs[0].id;
|
|
19498
19724
|
const plotOverride = (key) => (overrides.plots ??= {})[key] ??= {};
|
|
@@ -19519,7 +19745,7 @@ function openIndicatorSettings(deps) {
|
|
|
19519
19745
|
const el2 = h("select", { class: "qc-field", "aria-label": label2 });
|
|
19520
19746
|
for (const o of options) el2.appendChild(h("option", { value: o.value, selected: o.value === current }, o.text));
|
|
19521
19747
|
el2.addEventListener("change", () => onChange(el2.value));
|
|
19522
|
-
return el2;
|
|
19748
|
+
return selectField(el2, deps.icons);
|
|
19523
19749
|
};
|
|
19524
19750
|
const lineStyleOptions = () => [
|
|
19525
19751
|
{ value: "solid", text: t("settings.lineStyleSolid") },
|
|
@@ -20126,7 +20352,12 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20126
20352
|
const chart = request.chart ?? null;
|
|
20127
20353
|
const scope = chart ? chart.id : `pick-${picks += 1}`;
|
|
20128
20354
|
const listId = `qc-search-${scope}-list`;
|
|
20129
|
-
const
|
|
20355
|
+
const searchScope = compare || mode === "change-symbol" ? null : deps.scope?.() ?? null;
|
|
20356
|
+
const feedSession = deps.search;
|
|
20357
|
+
const scopeSession = searchScope ? feedSession.over(searchScope) : null;
|
|
20358
|
+
let scoped = scopeSession !== null && searchScope?.on !== false;
|
|
20359
|
+
const session2 = () => scoped && scopeSession ? scopeSession : feedSession;
|
|
20360
|
+
const search2 = () => session2().controller;
|
|
20130
20361
|
if (mode === "search" || mode === "pick") box.classList.add("qc-search-table");
|
|
20131
20362
|
let query = request.changeFrom ?? "";
|
|
20132
20363
|
const display = deps.display ?? {};
|
|
@@ -20195,7 +20426,7 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20195
20426
|
for (const { row: row2, top } of narrower) row2.hidden = !selection.has(top);
|
|
20196
20427
|
cls = selection.filter();
|
|
20197
20428
|
active = -1;
|
|
20198
|
-
search2.search(serverQuery(), cls);
|
|
20429
|
+
search2().search(serverQuery(), cls);
|
|
20199
20430
|
render();
|
|
20200
20431
|
};
|
|
20201
20432
|
const classChip = (label2, pressed, pick) => {
|
|
@@ -20203,18 +20434,31 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20203
20434
|
chips.push({ chip, pressed });
|
|
20204
20435
|
return chip;
|
|
20205
20436
|
};
|
|
20206
|
-
|
|
20437
|
+
let scopeChip = null;
|
|
20438
|
+
const setScoped = (on) => {
|
|
20439
|
+
if (on === scoped) return;
|
|
20440
|
+
session2().cancelPending();
|
|
20441
|
+
scoped = on;
|
|
20442
|
+
scopeChip?.setAttribute("aria-pressed", String(on));
|
|
20443
|
+
active = -1;
|
|
20444
|
+
search2().search(serverQuery(), cls);
|
|
20445
|
+
render();
|
|
20446
|
+
};
|
|
20207
20447
|
if (branches.length > 0 || searchScope) {
|
|
20208
|
-
strip = h("div", { class: "qc-search-classes"
|
|
20209
|
-
if (
|
|
20210
|
-
|
|
20211
|
-
|
|
20212
|
-
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
|
|
20216
|
-
|
|
20217
|
-
|
|
20448
|
+
strip = h("div", { class: "qc-search-classes" });
|
|
20449
|
+
if (branches.length > 0) {
|
|
20450
|
+
const group = h("div", { class: "qc-search-class-group", role: "group", "aria-label": t("search.classFilter") });
|
|
20451
|
+
if (allShown) group.appendChild(classChip(allLabel, () => selection.isAll(), () => selection.clear()));
|
|
20452
|
+
for (const branch of branches) {
|
|
20453
|
+
group.appendChild(classChip(labelOf(branch.id), () => selection.has(branch.id), () => selection.pickTop(branch.id)));
|
|
20454
|
+
if (branch.children.length === 0) continue;
|
|
20455
|
+
const row2 = h("div", { class: "qc-search-classes qc-search-subclasses", role: "group", "aria-label": labelOf(branch.id) });
|
|
20456
|
+
row2.appendChild(classChip(allLabel, () => selection.has(branch.id) && !selection.narrowed(branch.id), () => selection.clearChildren(branch.id)));
|
|
20457
|
+
for (const child of branch.children) row2.appendChild(classChip(labelOf(child), () => selection.hasChild(branch.id, child), () => selection.pickChild(branch.id, child)));
|
|
20458
|
+
row2.hidden = !selection.has(branch.id);
|
|
20459
|
+
narrower.push({ row: row2, top: branch.id });
|
|
20460
|
+
}
|
|
20461
|
+
strip.appendChild(group);
|
|
20218
20462
|
}
|
|
20219
20463
|
if (searchScope) {
|
|
20220
20464
|
const mark = h("span", { class: "qc-search-scope-mark", "aria-hidden": "true" });
|
|
@@ -20223,7 +20467,8 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20223
20467
|
mark.dataset.qcHost = "true";
|
|
20224
20468
|
scopeMarkDisposer = drop;
|
|
20225
20469
|
} else if (mark.childNodes.length === 0) mark.textContent = searchScope.label.charAt(0).toUpperCase();
|
|
20226
|
-
|
|
20470
|
+
scopeChip = button2({ label: t("search.limitToScope", { scope: searchScope.label }), text: searchScope.label, icon: mark, className: "qc-chip qc-search-scope", pressed: scoped, onClick: () => setScoped(!scoped) });
|
|
20471
|
+
strip.appendChild(scopeChip);
|
|
20227
20472
|
}
|
|
20228
20473
|
}
|
|
20229
20474
|
const list = h("div", { class: "qc-search-list", role: "listbox", id: listId, "aria-label": t("search.results") });
|
|
@@ -20237,11 +20482,16 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20237
20482
|
input.value = next;
|
|
20238
20483
|
showClear(next !== "");
|
|
20239
20484
|
active = -1;
|
|
20240
|
-
if (compare && next.trim() === "")
|
|
20241
|
-
else search2.search(serverQuery(), cls);
|
|
20485
|
+
if (compare && next.trim() === "") session2().cancelPending();
|
|
20486
|
+
else search2().search(serverQuery(), cls);
|
|
20242
20487
|
render();
|
|
20243
20488
|
};
|
|
20244
|
-
const
|
|
20489
|
+
const recentRows = () => scoped ? searchScope?.recents?.list() ?? [] : deps.recents.list();
|
|
20490
|
+
const remember = (row2) => {
|
|
20491
|
+
deps.recents.promote(row2);
|
|
20492
|
+
const own = scoped ? searchScope?.recents : void 0;
|
|
20493
|
+
if (own && own !== deps.recents) own.promote(row2);
|
|
20494
|
+
};
|
|
20245
20495
|
const act = (entry, placement = "same-percent") => {
|
|
20246
20496
|
const row2 = entry.row;
|
|
20247
20497
|
if (compare) {
|
|
@@ -20271,9 +20521,9 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20271
20521
|
};
|
|
20272
20522
|
const render = () => {
|
|
20273
20523
|
releaseMarks();
|
|
20274
|
-
const state = search2.state();
|
|
20524
|
+
const state = search2().state();
|
|
20275
20525
|
const settled = state.query.trim() === serverQuery().trim();
|
|
20276
|
-
rows2 = dialogRows({ mode, query, hits: settled ? state.hits : [], loading: state.loading || !settled, recents:
|
|
20526
|
+
rows2 = dialogRows({ mode, query, hits: settled ? state.hits : [], loading: state.loading || !settled, recents: recentRows(), curated: deps.curated ?? [], added: chart?.compare.list() ?? [], spreads });
|
|
20277
20527
|
active = Math.min(active, rows2.length - 1);
|
|
20278
20528
|
const emptyStack = compare && query.trim() === "";
|
|
20279
20529
|
const addedCount = emptyStack ? chart?.compare.list().length ?? 0 : 0;
|
|
@@ -20373,7 +20623,7 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20373
20623
|
if (e.key === "ArrowDown") {
|
|
20374
20624
|
e.preventDefault();
|
|
20375
20625
|
if (rows2.length === 0) return;
|
|
20376
|
-
if (search2.state().hasMore && active >= rows2.length - PREFETCH_MARGIN) search2.loadMore();
|
|
20626
|
+
if (search2().state().hasMore && active >= rows2.length - PREFETCH_MARGIN) search2().loadMore();
|
|
20377
20627
|
setActive(Math.min(active + 1, rows2.length - 1));
|
|
20378
20628
|
} else if (e.key === "ArrowUp") {
|
|
20379
20629
|
e.preventDefault();
|
|
@@ -20384,10 +20634,15 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20384
20634
|
if (entry) act(entry);
|
|
20385
20635
|
}
|
|
20386
20636
|
});
|
|
20387
|
-
observer = typeof IntersectionObserver === "function" ? new IntersectionObserver((entries) => entries.some((en2) => en2.isIntersecting) && search2.loadMore(), { root: list }) : null;
|
|
20388
|
-
|
|
20637
|
+
observer = typeof IntersectionObserver === "function" ? new IntersectionObserver((entries) => entries.some((en2) => en2.isIntersecting) && search2().loadMore(), { root: list }) : null;
|
|
20638
|
+
for (const own of [feedSession, scopeSession]) own?.controller.subscribe(() => {
|
|
20639
|
+
if (session2() === own) render();
|
|
20640
|
+
});
|
|
20389
20641
|
render();
|
|
20390
|
-
if (!compare || query.trim() !== "")
|
|
20642
|
+
if (!compare || query.trim() !== "") {
|
|
20643
|
+
if (scoped) session2().searchNow(serverQuery(), cls);
|
|
20644
|
+
else search2().search(serverQuery(), cls);
|
|
20645
|
+
}
|
|
20391
20646
|
if (request.changeFrom) input.select();
|
|
20392
20647
|
setDisabled(clear, false);
|
|
20393
20648
|
return {
|
|
@@ -20395,7 +20650,8 @@ function buildSearchSurface(deps, box, frame) {
|
|
|
20395
20650
|
scopeMarkDisposer?.();
|
|
20396
20651
|
scopeMarkDisposer = null;
|
|
20397
20652
|
releaseMarks();
|
|
20398
|
-
|
|
20653
|
+
feedSession.controller.dispose();
|
|
20654
|
+
scopeSession?.controller.dispose();
|
|
20399
20655
|
observer?.disconnect();
|
|
20400
20656
|
}
|
|
20401
20657
|
};
|
|
@@ -23100,6 +23356,7 @@ function createChart(options) {
|
|
|
23100
23356
|
container: element,
|
|
23101
23357
|
hostContainer: options.container,
|
|
23102
23358
|
freePan: options.touch?.freePan === true,
|
|
23359
|
+
styleMorph: options.transitions?.style === true,
|
|
23103
23360
|
layer,
|
|
23104
23361
|
datafeed: options.datafeed,
|
|
23105
23362
|
externalDrawingToolbar: !!options.drawingToolbarContainer,
|