@coderyo/ui-shell 1.0.2 → 1.0.3
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/dist/index.d.ts +70 -5
- package/dist/index.js +387 -57
- package/dist/index.js.map +1 -1
- package/package.json +9 -8
package/dist/index.js
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
// src/top-bar.ts
|
|
2
2
|
import { DEFAULT_INTERVALS } from "@coderyo/data";
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
// src/logo-slot.ts
|
|
5
|
+
function mountLogoSlot(parent, opts = {}) {
|
|
6
|
+
const slot = document.createElement("div");
|
|
7
|
+
slot.className = "tv-logo-slot";
|
|
8
|
+
slot.style.cssText = "display:flex;align-items:center;gap:8px;margin-right:12px;flex-shrink:0;font-weight:600;font-size:13px;color:var(--tv-fg,#e6edf3);";
|
|
9
|
+
const label = opts.label ?? "TradView";
|
|
10
|
+
const text = document.createElement("span");
|
|
11
|
+
text.textContent = label;
|
|
12
|
+
const children = [];
|
|
13
|
+
if (opts.imageSrc) {
|
|
14
|
+
const img = document.createElement("img");
|
|
15
|
+
img.src = opts.imageSrc;
|
|
16
|
+
img.alt = label;
|
|
17
|
+
img.style.cssText = "height:22px;width:auto;display:block;";
|
|
18
|
+
children.push(img);
|
|
19
|
+
}
|
|
20
|
+
children.push(text);
|
|
21
|
+
if (opts.href) {
|
|
22
|
+
const link = document.createElement("a");
|
|
23
|
+
link.href = opts.href;
|
|
24
|
+
link.style.cssText = "color:inherit;text-decoration:none;display:flex;align-items:center;gap:8px;";
|
|
25
|
+
link.append(...children);
|
|
26
|
+
slot.appendChild(link);
|
|
27
|
+
} else {
|
|
28
|
+
slot.append(...children);
|
|
29
|
+
}
|
|
30
|
+
parent.appendChild(slot);
|
|
31
|
+
return slot;
|
|
32
|
+
}
|
|
4
33
|
|
|
5
34
|
// src/user-preferences.ts
|
|
6
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
defaultChartStorage,
|
|
37
|
+
loadIndicatorConfig as loadIndicatorConfigFromCore,
|
|
38
|
+
saveIndicatorConfig as saveIndicatorConfigToCore
|
|
39
|
+
} from "@coderyo/core";
|
|
7
40
|
var GRID_SETTING_KEY = "tradview:settings:showGrid";
|
|
8
41
|
var RETURN_CURSOR_KEY = "tradview:settings:returnToCursorAfterDraw";
|
|
9
42
|
function loadShowGridPreference() {
|
|
@@ -33,30 +66,21 @@ function saveReturnToCursorPreference(v) {
|
|
|
33
66
|
}
|
|
34
67
|
}
|
|
35
68
|
function loadIndicatorConfig(symbol, interval) {
|
|
36
|
-
|
|
37
|
-
const raw = localStorage.getItem(indicatorConfigStorageKey(symbol, interval));
|
|
38
|
-
if (!raw) return { ...DEFAULT_INDICATOR_CONFIG };
|
|
39
|
-
return { ...DEFAULT_INDICATOR_CONFIG, ...JSON.parse(raw) };
|
|
40
|
-
} catch {
|
|
41
|
-
return { ...DEFAULT_INDICATOR_CONFIG };
|
|
42
|
-
}
|
|
69
|
+
return loadIndicatorConfigFromCore(defaultChartStorage, symbol, interval);
|
|
43
70
|
}
|
|
44
71
|
function saveIndicatorConfig(symbol, interval, config) {
|
|
45
|
-
|
|
46
|
-
localStorage.setItem(indicatorConfigStorageKey(symbol, interval), JSON.stringify(config));
|
|
47
|
-
} catch {
|
|
48
|
-
}
|
|
72
|
+
saveIndicatorConfigToCore(defaultChartStorage, symbol, interval, config);
|
|
49
73
|
}
|
|
50
74
|
|
|
51
75
|
// src/settings-panel.ts
|
|
52
|
-
import { DEFAULT_INDICATOR_CONFIG
|
|
76
|
+
import { DEFAULT_INDICATOR_CONFIG } from "@coderyo/indicators";
|
|
53
77
|
import { t } from "@coderyo/i18n";
|
|
54
78
|
function mountSettingsPanel(parent, opts = {}) {
|
|
55
79
|
let open = false;
|
|
56
80
|
let tab = "chart";
|
|
57
81
|
let showGrid = opts.showGrid ?? loadShowGridPreference();
|
|
58
82
|
let returnToCursor = opts.returnToCursorAfterDraw ?? loadReturnToCursorPreference();
|
|
59
|
-
let indicatorConfig = { ...opts.indicatorConfig ??
|
|
83
|
+
let indicatorConfig = { ...opts.indicatorConfig ?? DEFAULT_INDICATOR_CONFIG };
|
|
60
84
|
const wrap = document.createElement("div");
|
|
61
85
|
wrap.style.cssText = "position:relative;";
|
|
62
86
|
const btn = document.createElement("button");
|
|
@@ -101,6 +125,17 @@ function mountSettingsPanel(parent, opts = {}) {
|
|
|
101
125
|
row.append(input, document.createTextNode(label));
|
|
102
126
|
return row;
|
|
103
127
|
};
|
|
128
|
+
const actionButton = (label, onClick) => {
|
|
129
|
+
const btn2 = document.createElement("button");
|
|
130
|
+
btn2.type = "button";
|
|
131
|
+
btn2.textContent = label;
|
|
132
|
+
btn2.style.cssText = "display:block;width:100%;margin-top:10px;padding:6px 10px;border-radius:4px;border:1px solid #f85149;background:#21262d;color:#f85149;cursor:pointer;font-size:12px;";
|
|
133
|
+
btn2.onclick = (e) => {
|
|
134
|
+
e.stopPropagation();
|
|
135
|
+
onClick();
|
|
136
|
+
};
|
|
137
|
+
return btn2;
|
|
138
|
+
};
|
|
104
139
|
const numberField = (label, value, onChange) => {
|
|
105
140
|
const row = document.createElement("label");
|
|
106
141
|
row.style.cssText = "display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;";
|
|
@@ -131,6 +166,14 @@ function mountSettingsPanel(parent, opts = {}) {
|
|
|
131
166
|
opts.onReturnToCursorChange?.(v);
|
|
132
167
|
})
|
|
133
168
|
);
|
|
169
|
+
if (opts.onClearAllDrawings) {
|
|
170
|
+
content.appendChild(
|
|
171
|
+
actionButton(t("settings.drawing.clearAll", "\u6E05\u9664\u6240\u6709\u756B\u7DDA"), () => {
|
|
172
|
+
opts.onClearAllDrawings?.();
|
|
173
|
+
renderContent();
|
|
174
|
+
})
|
|
175
|
+
);
|
|
176
|
+
}
|
|
134
177
|
} else {
|
|
135
178
|
content.appendChild(
|
|
136
179
|
checkbox(t("settings.ind.macd", "MACD \u7A97\u683C"), indicatorConfig.showMacd, (v) => {
|
|
@@ -222,6 +265,15 @@ function mountSettingsPanel(parent, opts = {}) {
|
|
|
222
265
|
opts.onIndicatorConfigChange?.(indicatorConfig);
|
|
223
266
|
})
|
|
224
267
|
);
|
|
268
|
+
if (opts.onClearAllIndicators) {
|
|
269
|
+
content.appendChild(
|
|
270
|
+
actionButton(t("settings.ind.clearAll", "\u6E05\u7A7A\u6240\u6709\u6307\u6A19"), () => {
|
|
271
|
+
opts.onClearAllIndicators?.();
|
|
272
|
+
if (opts.indicatorConfig) indicatorConfig = { ...opts.indicatorConfig };
|
|
273
|
+
renderContent();
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
}
|
|
225
277
|
}
|
|
226
278
|
};
|
|
227
279
|
renderTabs();
|
|
@@ -230,6 +282,10 @@ function mountSettingsPanel(parent, opts = {}) {
|
|
|
230
282
|
btn.onclick = (e) => {
|
|
231
283
|
e.stopPropagation();
|
|
232
284
|
open = !open;
|
|
285
|
+
if (open) {
|
|
286
|
+
if (opts.indicatorConfig) indicatorConfig = { ...opts.indicatorConfig };
|
|
287
|
+
renderContent();
|
|
288
|
+
}
|
|
233
289
|
panel.style.display = open ? "block" : "none";
|
|
234
290
|
};
|
|
235
291
|
const close = () => {
|
|
@@ -243,6 +299,108 @@ function mountSettingsPanel(parent, opts = {}) {
|
|
|
243
299
|
return wrap;
|
|
244
300
|
}
|
|
245
301
|
|
|
302
|
+
// src/symbol-search-dialog.ts
|
|
303
|
+
function createSymbolSearchDialog(opts) {
|
|
304
|
+
const i18n = opts.i18n;
|
|
305
|
+
const backdrop = document.createElement("div");
|
|
306
|
+
backdrop.className = "tv-symbol-dialog-backdrop";
|
|
307
|
+
backdrop.style.cssText = "display:none;position:fixed;inset:0;z-index:1000;background:rgba(0,0,0,0.55);align-items:flex-start;justify-content:center;padding:12vh 16px 16px;";
|
|
308
|
+
const panel = document.createElement("div");
|
|
309
|
+
panel.className = "tv-symbol-dialog";
|
|
310
|
+
panel.style.cssText = "width:min(420px,100%);background:var(--tv-surface,#161b22);border:1px solid var(--tv-border,#30363d);border-radius:8px;padding:12px;box-shadow:0 8px 24px rgba(0,0,0,0.4);";
|
|
311
|
+
const title = document.createElement("div");
|
|
312
|
+
title.textContent = i18n?.t("symbol.search", "\u641C\u5C0B\u5546\u54C1") ?? "\u641C\u5C0B\u5546\u54C1";
|
|
313
|
+
title.style.cssText = "font-size:13px;font-weight:600;color:var(--tv-fg,#e6edf3);margin-bottom:8px;";
|
|
314
|
+
const input = document.createElement("input");
|
|
315
|
+
input.type = "search";
|
|
316
|
+
input.placeholder = i18n?.t("symbol.search", "\u641C\u5C0B\u5546\u54C1") ?? "\u641C\u5C0B\u5546\u54C1";
|
|
317
|
+
input.value = opts.initialSymbol ?? "";
|
|
318
|
+
input.style.cssText = "width:100%;box-sizing:border-box;padding:8px 10px;border-radius:4px;border:1px solid var(--tv-border,#30363d);background:var(--tv-bg,#0d1117);color:var(--tv-fg,#e6edf3);font-size:13px;";
|
|
319
|
+
const list = document.createElement("div");
|
|
320
|
+
list.style.cssText = "margin-top:8px;max-height:240px;overflow:auto;";
|
|
321
|
+
panel.append(title, input, list);
|
|
322
|
+
backdrop.appendChild(panel);
|
|
323
|
+
let timer;
|
|
324
|
+
let mounted = false;
|
|
325
|
+
const renderHits = (hits) => {
|
|
326
|
+
list.replaceChildren();
|
|
327
|
+
if (hits.length === 0) {
|
|
328
|
+
const empty = document.createElement("div");
|
|
329
|
+
empty.textContent = "\u2014";
|
|
330
|
+
empty.style.cssText = "padding:8px;color:var(--tv-muted,#8b949e);font-size:12px;";
|
|
331
|
+
list.appendChild(empty);
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
for (const hit of hits) {
|
|
335
|
+
const row = document.createElement("button");
|
|
336
|
+
row.type = "button";
|
|
337
|
+
row.textContent = hit.exchange ? `${hit.symbol} \xB7 ${hit.exchange}` : hit.symbol;
|
|
338
|
+
row.style.cssText = "display:block;width:100%;text-align:left;padding:8px 10px;border:none;background:transparent;color:var(--tv-fg,#e6edf3);cursor:pointer;font-size:12px;border-radius:4px;";
|
|
339
|
+
row.onmouseenter = () => {
|
|
340
|
+
row.style.background = "var(--tv-btn-bg,#21262d)";
|
|
341
|
+
};
|
|
342
|
+
row.onmouseleave = () => {
|
|
343
|
+
row.style.background = "transparent";
|
|
344
|
+
};
|
|
345
|
+
row.onclick = () => {
|
|
346
|
+
opts.onSelect(hit.symbol);
|
|
347
|
+
close();
|
|
348
|
+
};
|
|
349
|
+
list.appendChild(row);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
const runSearch = () => {
|
|
353
|
+
const q = input.value.trim();
|
|
354
|
+
if (q.length < 1) {
|
|
355
|
+
list.replaceChildren();
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
void opts.onSearch(q).then(renderHits).catch(() => list.replaceChildren());
|
|
359
|
+
};
|
|
360
|
+
input.addEventListener("input", () => {
|
|
361
|
+
clearTimeout(timer);
|
|
362
|
+
timer = setTimeout(runSearch, 200);
|
|
363
|
+
});
|
|
364
|
+
input.addEventListener("keydown", (e) => {
|
|
365
|
+
if (e.key === "Escape") close();
|
|
366
|
+
if (e.key === "Enter") runSearch();
|
|
367
|
+
});
|
|
368
|
+
backdrop.addEventListener("click", (e) => {
|
|
369
|
+
if (e.target === backdrop) close();
|
|
370
|
+
});
|
|
371
|
+
const open = () => {
|
|
372
|
+
if (!mounted) {
|
|
373
|
+
document.body.appendChild(backdrop);
|
|
374
|
+
mounted = true;
|
|
375
|
+
}
|
|
376
|
+
backdrop.style.display = "flex";
|
|
377
|
+
input.focus();
|
|
378
|
+
input.select();
|
|
379
|
+
runSearch();
|
|
380
|
+
};
|
|
381
|
+
const close = () => {
|
|
382
|
+
backdrop.style.display = "none";
|
|
383
|
+
};
|
|
384
|
+
const destroy = () => {
|
|
385
|
+
clearTimeout(timer);
|
|
386
|
+
backdrop.remove();
|
|
387
|
+
mounted = false;
|
|
388
|
+
};
|
|
389
|
+
return { open, close, destroy };
|
|
390
|
+
}
|
|
391
|
+
function mountSymbolSearchDialogTrigger(parent, dialog, opts) {
|
|
392
|
+
const wrap = document.createElement("div");
|
|
393
|
+
wrap.style.cssText = "display:flex;align-items:center;margin-right:8px;flex-shrink:0;";
|
|
394
|
+
const btn = document.createElement("button");
|
|
395
|
+
btn.type = "button";
|
|
396
|
+
btn.textContent = opts.initialSymbol ?? (opts.i18n?.t("symbol.search", "\u641C\u5C0B\u5546\u54C1") ?? "\u641C\u5C0B\u5546\u54C1");
|
|
397
|
+
btn.style.cssText = "min-width:140px;text-align:left;background:var(--tv-bg,#0d1117);color:var(--tv-fg,#e6edf3);border:1px solid var(--tv-border,#30363d);border-radius:4px;padding:4px 10px;cursor:pointer;font-size:12px;";
|
|
398
|
+
btn.onclick = () => dialog.open();
|
|
399
|
+
wrap.appendChild(btn);
|
|
400
|
+
parent.appendChild(wrap);
|
|
401
|
+
return wrap;
|
|
402
|
+
}
|
|
403
|
+
|
|
246
404
|
// src/symbol-search.ts
|
|
247
405
|
import { t as t2 } from "@coderyo/i18n";
|
|
248
406
|
function mountSymbolSearch(parent, opts) {
|
|
@@ -306,13 +464,32 @@ function mountSymbolSearch(parent, opts) {
|
|
|
306
464
|
return wrap;
|
|
307
465
|
}
|
|
308
466
|
|
|
467
|
+
// src/theme-toggle.ts
|
|
468
|
+
function mountThemeToggle(parent, opts) {
|
|
469
|
+
const i18n = opts.i18n;
|
|
470
|
+
const btn = document.createElement("button");
|
|
471
|
+
btn.type = "button";
|
|
472
|
+
btn.className = "tv-theme-toggle";
|
|
473
|
+
btn.style.cssText = "background:var(--tv-btn-bg,#21262d);color:var(--tv-fg,#e6edf3);border:1px solid var(--tv-border,#30363d);border-radius:4px;padding:4px 10px;cursor:pointer;font-size:12px;flex-shrink:0;";
|
|
474
|
+
const paint = (theme) => {
|
|
475
|
+
btn.textContent = theme === "dark" ? i18n?.t("theme.dark", "\u6DF1\u8272") ?? "\u6DF1\u8272" : i18n?.t("theme.light", "\u6DFA\u8272") ?? "\u6DFA\u8272";
|
|
476
|
+
};
|
|
477
|
+
btn.onclick = () => {
|
|
478
|
+
const next = opts.themeProvider.toggle();
|
|
479
|
+
opts.onThemeChange?.(next);
|
|
480
|
+
};
|
|
481
|
+
opts.themeProvider.subscribe((theme) => paint(theme));
|
|
482
|
+
parent.appendChild(btn);
|
|
483
|
+
return btn;
|
|
484
|
+
}
|
|
485
|
+
|
|
309
486
|
// src/top-bar.ts
|
|
310
487
|
function mountManualSymbolInput(parent, opts) {
|
|
311
488
|
const wrap = document.createElement("div");
|
|
312
489
|
wrap.style.cssText = "display:flex;align-items:center;gap:4px;margin-right:8px;";
|
|
313
490
|
const input = document.createElement("input");
|
|
314
491
|
input.type = "text";
|
|
315
|
-
input.placeholder =
|
|
492
|
+
input.placeholder = opts.i18n?.t("symbol.search", "Symbol") ?? "Symbol";
|
|
316
493
|
input.value = opts.initialSymbol ?? "";
|
|
317
494
|
input.style.cssText = "width:140px;background:#0d1117;color:#e6edf3;border:1px solid #30363d;border-radius:4px;padding:4px 8px;font-size:12px;";
|
|
318
495
|
const apply = () => {
|
|
@@ -332,9 +509,14 @@ function mountManualSymbolInput(parent, opts) {
|
|
|
332
509
|
parent.appendChild(wrap);
|
|
333
510
|
}
|
|
334
511
|
function mountTopBar(parent, opts = {}) {
|
|
512
|
+
const i18n = opts.i18n;
|
|
513
|
+
const tKey = (key, fallback) => i18n?.t(key, fallback) ?? fallback;
|
|
335
514
|
const bar = document.createElement("div");
|
|
336
515
|
bar.className = "tv-topbar";
|
|
337
|
-
bar.style.cssText = "display:flex;gap:8px;padding:8px 12px;align-items:center;border-bottom:1px solid
|
|
516
|
+
bar.style.cssText = "display:flex;gap:8px;padding:8px 12px;align-items:center;border-bottom:1px solid var(--tv-border,#30363d);background:var(--tv-surface,#161b22);flex-shrink:0;box-sizing:border-box;width:100%;min-width:0;overflow-x:auto;overflow-y:visible;position:relative;";
|
|
517
|
+
if (opts.logo !== false) {
|
|
518
|
+
mountLogoSlot(bar, opts.logo ?? { label: "TradView" });
|
|
519
|
+
}
|
|
338
520
|
const symbolMode = opts.symbolInput ?? "manual";
|
|
339
521
|
if (symbolMode === "search" && opts.onSymbolSearch && opts.onSymbolSelect) {
|
|
340
522
|
mountSymbolSearch(bar, {
|
|
@@ -342,10 +524,22 @@ function mountTopBar(parent, opts = {}) {
|
|
|
342
524
|
onSearch: opts.onSymbolSearch,
|
|
343
525
|
onSelect: opts.onSymbolSelect
|
|
344
526
|
});
|
|
527
|
+
} else if (symbolMode === "dialog" && opts.onSymbolSearch && opts.onSymbolSelect) {
|
|
528
|
+
const dialog = createSymbolSearchDialog({
|
|
529
|
+
initialSymbol: opts.initialSymbol,
|
|
530
|
+
onSearch: opts.onSymbolSearch,
|
|
531
|
+
onSelect: opts.onSymbolSelect,
|
|
532
|
+
i18n
|
|
533
|
+
});
|
|
534
|
+
mountSymbolSearchDialogTrigger(bar, dialog, {
|
|
535
|
+
initialSymbol: opts.initialSymbol,
|
|
536
|
+
i18n
|
|
537
|
+
});
|
|
345
538
|
} else if (symbolMode === "manual" && opts.onSymbolSelect) {
|
|
346
539
|
mountManualSymbolInput(bar, {
|
|
347
540
|
initialSymbol: opts.initialSymbol,
|
|
348
|
-
onSymbolSelect: opts.onSymbolSelect
|
|
541
|
+
onSymbolSelect: opts.onSymbolSelect,
|
|
542
|
+
i18n
|
|
349
543
|
});
|
|
350
544
|
}
|
|
351
545
|
const intervals = opts.intervals ?? DEFAULT_INTERVALS;
|
|
@@ -364,7 +558,7 @@ function mountTopBar(parent, opts = {}) {
|
|
|
364
558
|
for (const iv of intervals) {
|
|
365
559
|
const btn = document.createElement("button");
|
|
366
560
|
btn.type = "button";
|
|
367
|
-
btn.textContent =
|
|
561
|
+
btn.textContent = tKey(`interval.${iv}`, iv);
|
|
368
562
|
btn.style.cssText = btnStyle;
|
|
369
563
|
btn.onclick = () => {
|
|
370
564
|
if (activeInterval === iv) return;
|
|
@@ -388,7 +582,15 @@ function mountTopBar(parent, opts = {}) {
|
|
|
388
582
|
b.onclick = () => fn?.();
|
|
389
583
|
return b;
|
|
390
584
|
};
|
|
391
|
-
|
|
585
|
+
if (opts.themeProvider) {
|
|
586
|
+
mountThemeToggle(bar, {
|
|
587
|
+
themeProvider: opts.themeProvider,
|
|
588
|
+
i18n,
|
|
589
|
+
onThemeChange: opts.onThemeChange
|
|
590
|
+
});
|
|
591
|
+
} else {
|
|
592
|
+
bar.appendChild(mkBtn(tKey("theme.dark", "\u4E3B\u984C"), opts.onThemeToggle));
|
|
593
|
+
}
|
|
392
594
|
if (opts.showSettings && opts.settings) mountSettingsPanel(bar, opts.settings);
|
|
393
595
|
bar.appendChild(mkBtn("\u26F6", opts.onFullscreen));
|
|
394
596
|
bar.appendChild(mkBtn("\u{1F4F7}", opts.onScreenshot));
|
|
@@ -403,8 +605,116 @@ function mountTopBar(parent, opts = {}) {
|
|
|
403
605
|
};
|
|
404
606
|
}
|
|
405
607
|
|
|
608
|
+
// src/theme-provider.ts
|
|
609
|
+
var THEME_STORAGE_KEY = "tradview:theme";
|
|
610
|
+
var THEME_VARS = {
|
|
611
|
+
dark: {
|
|
612
|
+
"--tv-bg": "#0d1117",
|
|
613
|
+
"--tv-surface": "#161b22",
|
|
614
|
+
"--tv-border": "#30363d",
|
|
615
|
+
"--tv-fg": "#e6edf3",
|
|
616
|
+
"--tv-muted": "#8b949e",
|
|
617
|
+
"--tv-accent": "#388bfd",
|
|
618
|
+
"--tv-btn-bg": "#21262d"
|
|
619
|
+
},
|
|
620
|
+
light: {
|
|
621
|
+
"--tv-bg": "#ffffff",
|
|
622
|
+
"--tv-surface": "#f6f8fa",
|
|
623
|
+
"--tv-border": "#d0d7de",
|
|
624
|
+
"--tv-fg": "#24292f",
|
|
625
|
+
"--tv-muted": "#656d76",
|
|
626
|
+
"--tv-accent": "#0969da",
|
|
627
|
+
"--tv-btn-bg": "#f6f8fa"
|
|
628
|
+
}
|
|
629
|
+
};
|
|
630
|
+
function loadTheme() {
|
|
631
|
+
try {
|
|
632
|
+
const v = localStorage.getItem(THEME_STORAGE_KEY);
|
|
633
|
+
return v === "light" ? "light" : "dark";
|
|
634
|
+
} catch {
|
|
635
|
+
return "dark";
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function saveTheme(theme) {
|
|
639
|
+
try {
|
|
640
|
+
localStorage.setItem(THEME_STORAGE_KEY, theme);
|
|
641
|
+
} catch {
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
function applyThemeToDocument(theme, root = document.documentElement) {
|
|
645
|
+
const vars = THEME_VARS[theme];
|
|
646
|
+
for (const [k, v] of Object.entries(vars)) root.style.setProperty(k, v);
|
|
647
|
+
root.dataset.tradviewTheme = theme;
|
|
648
|
+
}
|
|
649
|
+
function createThemeProvider(initial) {
|
|
650
|
+
let theme = initial ?? loadTheme();
|
|
651
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
652
|
+
const notify = () => {
|
|
653
|
+
applyThemeToDocument(theme);
|
|
654
|
+
for (const l of listeners) l(theme);
|
|
655
|
+
};
|
|
656
|
+
applyThemeToDocument(theme);
|
|
657
|
+
return {
|
|
658
|
+
getTheme: () => theme,
|
|
659
|
+
setTheme: (next) => {
|
|
660
|
+
if (next === theme) return;
|
|
661
|
+
theme = next;
|
|
662
|
+
saveTheme(theme);
|
|
663
|
+
notify();
|
|
664
|
+
},
|
|
665
|
+
toggle: () => {
|
|
666
|
+
theme = theme === "dark" ? "light" : "dark";
|
|
667
|
+
saveTheme(theme);
|
|
668
|
+
notify();
|
|
669
|
+
return theme;
|
|
670
|
+
},
|
|
671
|
+
subscribe: (listener) => {
|
|
672
|
+
listeners.add(listener);
|
|
673
|
+
listener(theme);
|
|
674
|
+
return () => listeners.delete(listener);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
// src/i18n-provider.ts
|
|
680
|
+
import {
|
|
681
|
+
getLocale,
|
|
682
|
+
registerLocale,
|
|
683
|
+
setLocale,
|
|
684
|
+
t as i18nT
|
|
685
|
+
} from "@coderyo/i18n";
|
|
686
|
+
function interpolate(text, params) {
|
|
687
|
+
if (!params) return text;
|
|
688
|
+
return text.replace(/\{(\w+)\}/g, (_, key) => String(params[key] ?? `{${key}}`));
|
|
689
|
+
}
|
|
690
|
+
function createI18nProvider(defaultLocale = "zh-TW") {
|
|
691
|
+
setLocale(defaultLocale);
|
|
692
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
693
|
+
return {
|
|
694
|
+
t(key, fallback, params) {
|
|
695
|
+
return interpolate(i18nT(key, fallback), params);
|
|
696
|
+
},
|
|
697
|
+
getLocale,
|
|
698
|
+
setLocale(locale) {
|
|
699
|
+
setLocale(locale);
|
|
700
|
+
for (const l of listeners) l(locale);
|
|
701
|
+
},
|
|
702
|
+
registerLocale(loc, dictionary) {
|
|
703
|
+
registerLocale(loc, dictionary);
|
|
704
|
+
if (getLocale() === loc) {
|
|
705
|
+
for (const l of listeners) l(loc);
|
|
706
|
+
}
|
|
707
|
+
},
|
|
708
|
+
subscribe(listener) {
|
|
709
|
+
listeners.add(listener);
|
|
710
|
+
listener(getLocale());
|
|
711
|
+
return () => listeners.delete(listener);
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
|
|
406
716
|
// src/context-menu.ts
|
|
407
|
-
import { t as
|
|
717
|
+
import { t as t3 } from "@coderyo/i18n";
|
|
408
718
|
function attachChartContextMenu(chartHost, opts = {}) {
|
|
409
719
|
let menu = null;
|
|
410
720
|
const close = () => {
|
|
@@ -418,7 +728,7 @@ function attachChartContextMenu(chartHost, opts = {}) {
|
|
|
418
728
|
const actions = opts.actions ?? [
|
|
419
729
|
{
|
|
420
730
|
id: "fit",
|
|
421
|
-
label:
|
|
731
|
+
label: t3("context.fitContent", "\u9069\u914D\u756B\u9762"),
|
|
422
732
|
onClick: () => {
|
|
423
733
|
}
|
|
424
734
|
}
|
|
@@ -497,13 +807,13 @@ O ${fmt2(o?.o)} H ${fmt2(o?.h)} L ${fmt2(o?.l)} C ${fmt2(o?.c)}`;
|
|
|
497
807
|
}
|
|
498
808
|
|
|
499
809
|
// src/drawing-properties-panel.ts
|
|
500
|
-
import { t as
|
|
810
|
+
import { t as t4 } from "@coderyo/i18n";
|
|
501
811
|
function mountDrawingPropertiesPanel(parent, opts = {}) {
|
|
502
812
|
const panel = document.createElement("aside");
|
|
503
813
|
panel.className = "tv-drawing-props";
|
|
504
814
|
panel.style.cssText = "display:none;width:220px;flex-shrink:0;border-left:1px solid #30363d;background:#161b22;padding:10px 12px;font-size:12px;color:#e6edf3;overflow:auto;";
|
|
505
815
|
const title = document.createElement("div");
|
|
506
|
-
title.textContent =
|
|
816
|
+
title.textContent = t4("drawing.props.title", "\u7E6A\u5716\u5C6C\u6027");
|
|
507
817
|
title.style.cssText = "font-weight:600;margin-bottom:10px;";
|
|
508
818
|
const typeEl = document.createElement("div");
|
|
509
819
|
typeEl.style.color = "#8b949e";
|
|
@@ -517,26 +827,26 @@ function mountDrawingPropertiesPanel(parent, opts = {}) {
|
|
|
517
827
|
row.appendChild(span);
|
|
518
828
|
return row;
|
|
519
829
|
};
|
|
520
|
-
const colorRow = mkRow(
|
|
830
|
+
const colorRow = mkRow(t4("drawing.props.color", "\u984F\u8272"));
|
|
521
831
|
const colorInput = document.createElement("input");
|
|
522
832
|
colorInput.type = "color";
|
|
523
833
|
colorInput.style.cssText = "width:100%;height:28px;border:none;background:transparent;cursor:pointer;";
|
|
524
834
|
colorRow.appendChild(colorInput);
|
|
525
|
-
const widthRow = mkRow(
|
|
835
|
+
const widthRow = mkRow(t4("drawing.props.lineWidth", "\u7DDA\u5BEC"));
|
|
526
836
|
const widthInput = document.createElement("input");
|
|
527
837
|
widthInput.type = "range";
|
|
528
838
|
widthInput.min = "1";
|
|
529
839
|
widthInput.max = "6";
|
|
530
840
|
widthInput.style.width = "100%";
|
|
531
841
|
widthRow.appendChild(widthInput);
|
|
532
|
-
const textRow = mkRow(
|
|
842
|
+
const textRow = mkRow(t4("drawing.props.text", "\u6587\u5B57"));
|
|
533
843
|
const textInput = document.createElement("input");
|
|
534
844
|
textInput.type = "text";
|
|
535
845
|
textInput.style.cssText = "padding:4px 8px;border-radius:4px;border:1px solid #30363d;background:#0d1117;color:#e6edf3;";
|
|
536
846
|
textRow.appendChild(textInput);
|
|
537
847
|
const lockedHint = document.createElement("div");
|
|
538
848
|
lockedHint.style.cssText = "color:#f78166;font-size:11px;margin-top:6px;display:none;";
|
|
539
|
-
lockedHint.textContent =
|
|
849
|
+
lockedHint.textContent = t4("drawing.props.locked", "\u5DF2\u9396\u5B9A \u2014 \u89E3\u9396\u5F8C\u53EF\u7DE8\u8F2F");
|
|
540
850
|
panel.append(title, typeEl, colorRow, widthRow, textRow, lockedHint);
|
|
541
851
|
parent.appendChild(panel);
|
|
542
852
|
const emit = () => {
|
|
@@ -555,7 +865,7 @@ function mountDrawingPropertiesPanel(parent, opts = {}) {
|
|
|
555
865
|
return;
|
|
556
866
|
}
|
|
557
867
|
panel.style.display = "block";
|
|
558
|
-
typeEl.textContent = `${
|
|
868
|
+
typeEl.textContent = `${t4("drawing.props.type", "\u985E\u578B")}: ${drawing.type}`;
|
|
559
869
|
const meta = drawing.meta ?? {};
|
|
560
870
|
colorInput.value = String(meta.color ?? "#58a6ff");
|
|
561
871
|
widthInput.value = String(meta.lineWidth ?? 2);
|
|
@@ -639,7 +949,7 @@ function createDemoLayoutOptions(partial = {}) {
|
|
|
639
949
|
}
|
|
640
950
|
|
|
641
951
|
// src/status-bar.ts
|
|
642
|
-
import { getLocale, setLocale, t as
|
|
952
|
+
import { getLocale as getLocale2, setLocale as setLocale2, t as t5 } from "@coderyo/i18n";
|
|
643
953
|
function fmt(n, digits = 2) {
|
|
644
954
|
if (n == null || Number.isNaN(n)) return "\u2014";
|
|
645
955
|
return n.toLocaleString(void 0, { maximumFractionDigits: digits });
|
|
@@ -656,7 +966,7 @@ function mountStatusBar(parent, opts = {}) {
|
|
|
656
966
|
const localeWrap = document.createElement("label");
|
|
657
967
|
localeWrap.style.cssText = "display:flex;align-items:center;gap:4px;margin-left:auto;";
|
|
658
968
|
const localeLabel = document.createElement("span");
|
|
659
|
-
localeLabel.textContent =
|
|
969
|
+
localeLabel.textContent = t5("status.locale", "\u8A9E\u7CFB");
|
|
660
970
|
const localeSelect = document.createElement("select");
|
|
661
971
|
localeSelect.style.cssText = "background:#0d1117;color:#e6edf3;border:1px solid #30363d;border-radius:4px;font-size:11px;padding:2px 4px;";
|
|
662
972
|
for (const loc of ["zh-TW", "en"]) {
|
|
@@ -665,11 +975,11 @@ function mountStatusBar(parent, opts = {}) {
|
|
|
665
975
|
opt.textContent = loc;
|
|
666
976
|
localeSelect.appendChild(opt);
|
|
667
977
|
}
|
|
668
|
-
localeSelect.value = opts.locale ??
|
|
978
|
+
localeSelect.value = opts.locale ?? getLocale2();
|
|
669
979
|
localeSelect.onchange = () => {
|
|
670
|
-
|
|
980
|
+
setLocale2(localeSelect.value);
|
|
671
981
|
opts.onLocaleChange?.(localeSelect.value);
|
|
672
|
-
localeLabel.textContent =
|
|
982
|
+
localeLabel.textContent = t5("status.locale", "\u8A9E\u7CFB");
|
|
673
983
|
render(opts);
|
|
674
984
|
};
|
|
675
985
|
localeWrap.append(localeLabel, localeSelect);
|
|
@@ -677,14 +987,14 @@ function mountStatusBar(parent, opts = {}) {
|
|
|
677
987
|
parent.appendChild(bar);
|
|
678
988
|
const render = (state) => {
|
|
679
989
|
const merged = { ...opts, ...state };
|
|
680
|
-
conn.textContent = `${
|
|
990
|
+
conn.textContent = `${t5("status.connection", "\u9023\u7DDA")}\uFF1A${merged.connection ?? "\u2014"}`;
|
|
681
991
|
const parts = [merged.symbol, merged.interval].filter(Boolean);
|
|
682
992
|
sym.textContent = parts.length ? parts.join(" \xB7 ") : "";
|
|
683
993
|
const o = merged.ohlcv;
|
|
684
994
|
if (o && (o.o != null || o.c != null)) {
|
|
685
995
|
ohlcv.textContent = `O ${fmt(o.o)} H ${fmt(o.h)} L ${fmt(o.l)} C ${fmt(o.c)} V ${fmt(o.v, 0)}`;
|
|
686
996
|
} else {
|
|
687
|
-
ohlcv.textContent =
|
|
997
|
+
ohlcv.textContent = t5("status.ohlcvHint", "\u79FB\u52D5\u5341\u5B57\u7DDA\u67E5\u770B OHLCV");
|
|
688
998
|
}
|
|
689
999
|
};
|
|
690
1000
|
render(opts);
|
|
@@ -698,7 +1008,7 @@ function mountStatusBar(parent, opts = {}) {
|
|
|
698
1008
|
}
|
|
699
1009
|
|
|
700
1010
|
// src/shortcuts-modal.ts
|
|
701
|
-
import { t as
|
|
1011
|
+
import { t as t6 } from "@coderyo/i18n";
|
|
702
1012
|
var SHORTCUTS = [
|
|
703
1013
|
{ key: "\u2196 / Esc", desc: "\u6E38\u6A19\uFF08\u9078\u53D6/\u7DE8\u8F2F\u7E6A\u5716\uFF09" },
|
|
704
1014
|
{ key: "Delete", desc: "\u522A\u9664\u9078\u4E2D\u7E6A\u5716" },
|
|
@@ -727,7 +1037,7 @@ function openShortcutsModal() {
|
|
|
727
1037
|
const box = document.createElement("div");
|
|
728
1038
|
box.style.cssText = "min-width:320px;max-width:90vw;padding:16px 20px;background:#161b22;border:1px solid #30363d;border-radius:8px;color:#e6edf3;";
|
|
729
1039
|
const h = document.createElement("h2");
|
|
730
|
-
h.textContent =
|
|
1040
|
+
h.textContent = t6("shortcuts.title", "\u5FEB\u6377\u9375");
|
|
731
1041
|
h.style.cssText = "font-size:16px;margin:0 0 12px;";
|
|
732
1042
|
const list = document.createElement("div");
|
|
733
1043
|
list.style.cssText = "font-size:13px;line-height:1.8;";
|
|
@@ -738,7 +1048,7 @@ function openShortcutsModal() {
|
|
|
738
1048
|
}
|
|
739
1049
|
const closeBtn = document.createElement("button");
|
|
740
1050
|
closeBtn.type = "button";
|
|
741
|
-
closeBtn.textContent =
|
|
1051
|
+
closeBtn.textContent = t6("shortcuts.close", "\u95DC\u9589");
|
|
742
1052
|
closeBtn.style.cssText = "margin-top:14px;padding:6px 14px;background:#21262d;color:#e6edf3;border:1px solid #30363d;border-radius:4px;cursor:pointer;";
|
|
743
1053
|
const close = () => backdrop.remove();
|
|
744
1054
|
closeBtn.onclick = close;
|
|
@@ -792,7 +1102,11 @@ function mountChartLayout(root, opts = {}) {
|
|
|
792
1102
|
root.style.minWidth = "0";
|
|
793
1103
|
root.style.boxSizing = "border-box";
|
|
794
1104
|
root.style.overflow = "visible";
|
|
795
|
-
|
|
1105
|
+
const themeProvider = opts.themeProvider ?? createThemeProvider();
|
|
1106
|
+
const i18nProvider = opts.i18n ?? createI18nProvider();
|
|
1107
|
+
themeProvider.subscribe((theme) => {
|
|
1108
|
+
root.style.background = theme === "dark" ? "#0d1117" : "#f6f8fa";
|
|
1109
|
+
});
|
|
796
1110
|
let activeTool = opts.activeDrawingTool ?? "cursor";
|
|
797
1111
|
let setActiveDesktop = null;
|
|
798
1112
|
let setActiveMobile = null;
|
|
@@ -870,7 +1184,13 @@ function mountChartLayout(root, opts = {}) {
|
|
|
870
1184
|
headerSlot,
|
|
871
1185
|
Object.assign(opts, {
|
|
872
1186
|
symbolInput: f.symbolInput,
|
|
873
|
-
showSettings: f.showSettings
|
|
1187
|
+
showSettings: f.showSettings,
|
|
1188
|
+
themeProvider: opts.themeProvider ?? themeProvider,
|
|
1189
|
+
i18n: opts.i18n ?? i18nProvider,
|
|
1190
|
+
onThemeChange: (theme) => {
|
|
1191
|
+
opts.onThemeChange?.(theme);
|
|
1192
|
+
if (!opts.onThemeChange) opts.onThemeToggle?.();
|
|
1193
|
+
}
|
|
874
1194
|
})
|
|
875
1195
|
);
|
|
876
1196
|
topBar = mounted.el;
|
|
@@ -916,7 +1236,7 @@ function mountChartLayout(root, opts = {}) {
|
|
|
916
1236
|
}
|
|
917
1237
|
|
|
918
1238
|
// src/drawing-context-menu.ts
|
|
919
|
-
import { t as
|
|
1239
|
+
import { t as t7 } from "@coderyo/i18n";
|
|
920
1240
|
function openDrawingContextMenu(clientX, clientY, drawing, handlers) {
|
|
921
1241
|
const menu = document.createElement("div");
|
|
922
1242
|
menu.style.cssText = "position:fixed;z-index:60;min-width:168px;padding:4px 0;background:#161b22;border:1px solid #30363d;border-radius:6px;box-shadow:0 8px 24px #01040988;";
|
|
@@ -938,16 +1258,16 @@ function openDrawingContextMenu(clientX, clientY, drawing, handlers) {
|
|
|
938
1258
|
};
|
|
939
1259
|
if (drawing) {
|
|
940
1260
|
const locked = Boolean(drawing.meta?.locked);
|
|
941
|
-
add(
|
|
942
|
-
add(
|
|
1261
|
+
add(t7("drawing.ctx.delete", "\u522A\u9664"), handlers.onDelete);
|
|
1262
|
+
add(t7("drawing.ctx.copy", "\u8907\u88FD"), handlers.onCopy);
|
|
943
1263
|
add(
|
|
944
|
-
locked ?
|
|
1264
|
+
locked ? t7("drawing.ctx.unlock", "\u89E3\u9396") : t7("drawing.ctx.lock", "\u9396\u5B9A"),
|
|
945
1265
|
handlers.onToggleLock
|
|
946
1266
|
);
|
|
947
1267
|
if (drawing.type === "text") {
|
|
948
|
-
add(
|
|
1268
|
+
add(t7("drawing.ctx.editText", "\u7DE8\u8F2F\u6587\u5B57"), handlers.onEditText);
|
|
949
1269
|
}
|
|
950
|
-
add(
|
|
1270
|
+
add(t7("drawing.ctx.deselect", "\u53D6\u6D88\u9078\u53D6"), handlers.onDeselect);
|
|
951
1271
|
}
|
|
952
1272
|
document.body.appendChild(menu);
|
|
953
1273
|
const close = () => {
|
|
@@ -999,7 +1319,7 @@ import {
|
|
|
999
1319
|
lineNumbers,
|
|
1000
1320
|
placeholder
|
|
1001
1321
|
} from "@codemirror/view";
|
|
1002
|
-
import { t as
|
|
1322
|
+
import { t as t8 } from "@coderyo/i18n";
|
|
1003
1323
|
|
|
1004
1324
|
// src/pine-language.ts
|
|
1005
1325
|
import { StreamLanguage } from "@codemirror/language";
|
|
@@ -1059,10 +1379,10 @@ function createPineLinter(onStatus) {
|
|
|
1059
1379
|
const src = view.state.doc.toString();
|
|
1060
1380
|
const result = compilePineLite(src);
|
|
1061
1381
|
if (result.ok) {
|
|
1062
|
-
onStatus?.(
|
|
1382
|
+
onStatus?.(t8("pine.status.ok", "\u8A9E\u6CD5\u6B63\u78BA"), true);
|
|
1063
1383
|
return [];
|
|
1064
1384
|
}
|
|
1065
|
-
onStatus?.(result.errors[0] ??
|
|
1385
|
+
onStatus?.(result.errors[0] ?? t8("pine.status.error", "\u8A9E\u6CD5\u932F\u8AA4"), false);
|
|
1066
1386
|
return pineDiagnosticsToCm(src, result.diagnostics ?? []);
|
|
1067
1387
|
});
|
|
1068
1388
|
}
|
|
@@ -1091,16 +1411,16 @@ function mountPineEditorPanel(parent, opts = {}) {
|
|
|
1091
1411
|
wrap.open = true;
|
|
1092
1412
|
wrap.style.cssText = "flex-shrink:0;border-top:1px solid #30363d;background:#161b22;max-height:220px;display:flex;flex-direction:column;";
|
|
1093
1413
|
const summary = document.createElement("summary");
|
|
1094
|
-
summary.textContent =
|
|
1414
|
+
summary.textContent = t8("pine.editor.title", "Pine \u8173\u672C\u7DE8\u8F2F\u5668");
|
|
1095
1415
|
summary.style.cssText = "cursor:pointer;color:#58a6ff;user-select:none;padding:6px 12px;font-size:12px;flex-shrink:0;";
|
|
1096
1416
|
const toolbar = document.createElement("div");
|
|
1097
1417
|
toolbar.style.cssText = "display:flex;align-items:center;gap:8px;padding:0 12px 6px;flex-shrink:0;";
|
|
1098
1418
|
const status = document.createElement("span");
|
|
1099
1419
|
status.style.cssText = "font-size:11px;color:#8b949e;flex:1;";
|
|
1100
|
-
status.textContent =
|
|
1420
|
+
status.textContent = t8("pine.status.idle", "\u5C31\u7DD2");
|
|
1101
1421
|
const applyBtn = document.createElement("button");
|
|
1102
1422
|
applyBtn.type = "button";
|
|
1103
|
-
applyBtn.textContent =
|
|
1423
|
+
applyBtn.textContent = t8("pine.apply", "\u5957\u7528\u81F3\u5716\u8868");
|
|
1104
1424
|
applyBtn.style.cssText = "padding:4px 10px;background:#238636;color:#fff;border:1px solid #2ea043;border-radius:4px;cursor:pointer;font-size:11px;";
|
|
1105
1425
|
const host = document.createElement("div");
|
|
1106
1426
|
host.style.cssText = "flex:1;min-height:120px;max-height:160px;overflow:hidden;border-top:1px solid #30363d;";
|
|
@@ -1115,10 +1435,10 @@ function mountPineEditorPanel(parent, opts = {}) {
|
|
|
1115
1435
|
savePineScriptPreference(src);
|
|
1116
1436
|
if (r.ok) {
|
|
1117
1437
|
status.style.color = "#3fb950";
|
|
1118
|
-
status.textContent =
|
|
1438
|
+
status.textContent = t8("pine.status.ok", "\u8A9E\u6CD5\u6B63\u78BA");
|
|
1119
1439
|
} else {
|
|
1120
1440
|
status.style.color = "#f85149";
|
|
1121
|
-
status.textContent = r.errors[0] ??
|
|
1441
|
+
status.textContent = r.errors[0] ?? t8("pine.status.error", "\u8A9E\u6CD5\u932F\u8AA4");
|
|
1122
1442
|
}
|
|
1123
1443
|
};
|
|
1124
1444
|
const extensions = [
|
|
@@ -1136,7 +1456,7 @@ function mountPineEditorPanel(parent, opts = {}) {
|
|
|
1136
1456
|
status.textContent = msg;
|
|
1137
1457
|
}),
|
|
1138
1458
|
keymap.of([...defaultKeymap, ...historyKeymap]),
|
|
1139
|
-
placeholder(
|
|
1459
|
+
placeholder(t8("pine.placeholder", "// plot(sma(close, 20))")),
|
|
1140
1460
|
EditorView.updateListener.of((u) => {
|
|
1141
1461
|
if (!u.docChanged) return;
|
|
1142
1462
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
@@ -1169,23 +1489,32 @@ export {
|
|
|
1169
1489
|
GRID_SETTING_KEY,
|
|
1170
1490
|
PINE_SCRIPT_STORAGE_KEY,
|
|
1171
1491
|
RETURN_CURSOR_KEY,
|
|
1492
|
+
THEME_STORAGE_KEY,
|
|
1493
|
+
applyThemeToDocument,
|
|
1172
1494
|
attachChartContextMenu,
|
|
1173
1495
|
bindShortcutsModal,
|
|
1174
1496
|
createDemoLayoutOptions,
|
|
1497
|
+
createI18nProvider,
|
|
1498
|
+
createSymbolSearchDialog,
|
|
1499
|
+
createThemeProvider,
|
|
1175
1500
|
loadIndicatorConfig,
|
|
1176
1501
|
loadPineScriptPreference,
|
|
1177
1502
|
loadReturnToCursorPreference,
|
|
1178
1503
|
loadShowGridPreference,
|
|
1504
|
+
loadTheme,
|
|
1179
1505
|
mergeLayoutFeatures,
|
|
1180
1506
|
mountChartLayout,
|
|
1181
1507
|
mountCodeSnippetPanel,
|
|
1182
1508
|
mountCrosshairLegend,
|
|
1183
1509
|
mountDrawingPropertiesPanel,
|
|
1510
|
+
mountLogoSlot,
|
|
1184
1511
|
mountPineEditorPanel,
|
|
1185
1512
|
mountSettingsPanel as mountSettingsMenu,
|
|
1186
1513
|
mountSettingsPanel,
|
|
1187
1514
|
mountStatusBar,
|
|
1188
1515
|
mountSymbolSearch,
|
|
1516
|
+
mountSymbolSearchDialogTrigger,
|
|
1517
|
+
mountThemeToggle,
|
|
1189
1518
|
mountTopBar,
|
|
1190
1519
|
openDrawingContextMenu,
|
|
1191
1520
|
openShortcutsModal,
|
|
@@ -1194,6 +1523,7 @@ export {
|
|
|
1194
1523
|
saveIndicatorConfig,
|
|
1195
1524
|
savePineScriptPreference,
|
|
1196
1525
|
saveReturnToCursorPreference,
|
|
1197
|
-
saveShowGridPreference
|
|
1526
|
+
saveShowGridPreference,
|
|
1527
|
+
saveTheme
|
|
1198
1528
|
};
|
|
1199
1529
|
//# sourceMappingURL=index.js.map
|