@luxalgo/vela 0.7.0 → 0.7.2
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/{DataProvider-Bu9E5Zh5.d.ts → DataProvider-BALR0qPq.d.ts} +1 -1
- package/dist/{DataProvider-Ck2qyS_9.d.cts → DataProvider-D5uMiJYz.d.cts} +1 -1
- package/dist/{chunk-IFJJPXSV.js → chunk-BFA32GOU.js} +44 -16
- package/dist/{chunk-CZRNTHD6.js → chunk-BKHSQ4YM.js} +129 -125
- package/dist/{chunk-A4G64KVF.js → chunk-PTNO3YK2.js} +311 -111
- package/dist/{chunk-A347YL2P.js → chunk-QBWLINWL.js} +67 -9
- package/dist/{chunk-UHXG5J7C.js → chunk-ZADTVRUO.js} +1 -1
- package/dist/{contributions-BjQ7hyIx.d.ts → contributions-BbhbZd3c.d.ts} +31 -9
- package/dist/{contributions-Cv2Mutvn.d.cts → contributions-CcBFe-91.d.cts} +31 -9
- package/dist/index.cjs +391 -157
- package/dist/index.d.cts +52 -17
- package/dist/index.d.ts +52 -17
- package/dist/index.js +4 -4
- package/dist/{options-ex2_gtKp.d.ts → options-C7b_Qssu.d.cts} +42 -1
- package/dist/{options-ex2_gtKp.d.cts → options-C7b_Qssu.d.ts} +42 -1
- package/dist/{plugin-CiyhU7pi.d.ts → plugin-Cnix5ZBh.d.ts} +6 -4
- package/dist/{plugin-absNH7Yn.d.cts → plugin-D6MlX4--.d.cts} +6 -4
- package/dist/plugin.cjs +39 -15
- package/dist/plugin.d.cts +4 -4
- package/dist/plugin.d.ts +4 -4
- package/dist/plugin.js +2 -2
- package/dist/providers/binance.d.cts +2 -2
- package/dist/providers/binance.d.ts +2 -2
- package/dist/providers/coinbase.d.cts +2 -2
- package/dist/providers/coinbase.d.ts +2 -2
- package/dist/providers/hyperliquid.d.cts +2 -2
- package/dist/providers/hyperliquid.d.ts +2 -2
- package/dist/{statusline-model-BXoU4Kua.d.ts → statusline-model-D8NL7o4L.d.ts} +3 -3
- package/dist/{statusline-model-cRhPBLPO.d.cts → statusline-model-DUKt7_TQ.d.cts} +3 -3
- package/dist/ui.cjs +8 -4
- package/dist/ui.d.cts +10 -7
- package/dist/ui.d.ts +10 -7
- package/dist/ui.js +2 -2
- package/dist/vela.global.js +391 -157
- package/dist/vela.global.min.js +70 -70
- package/dist/widget.cjs +418 -128
- package/dist/widget.d.cts +6 -6
- package/dist/widget.d.ts +6 -6
- package/dist/widget.js +6 -6
- package/dist/workspace.cjs +418 -128
- package/dist/workspace.d.cts +39 -6
- package/dist/workspace.d.ts +39 -6
- package/dist/workspace.js +5 -5
- package/package.json +1 -1
- /package/dist/{chunk-FE6V2YAQ.js → chunk-JU4CWEBF.js} +0 -0
|
@@ -1,6 +1,21 @@
|
|
|
1
1
|
import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl } from './chunk-CAFCLMPF.js';
|
|
2
2
|
|
|
3
|
+
// src/core/model/series.ts
|
|
4
|
+
function isLineLikeSeries(spec) {
|
|
5
|
+
return spec.kind !== "candle" && spec.kind !== "bar" && spec.kind !== "markers";
|
|
6
|
+
}
|
|
7
|
+
function seriesShownOn(spec, surface) {
|
|
8
|
+
if (spec.display) return spec.display[surface] !== false;
|
|
9
|
+
return spec.visible !== false;
|
|
10
|
+
}
|
|
11
|
+
function seriesInScale(spec) {
|
|
12
|
+
return seriesShownOn(spec, "pane") || seriesShownOn(spec, "priceScale");
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
// src/core/native-indicators/NativeIndicator.ts
|
|
16
|
+
function nativeInstanceChannel(type, instanceId) {
|
|
17
|
+
return `${type}#${instanceId}`;
|
|
18
|
+
}
|
|
4
19
|
var REGISTRY = /* @__PURE__ */ new Map();
|
|
5
20
|
function registerNativeIndicator(descriptor) {
|
|
6
21
|
REGISTRY.set(descriptor.type, descriptor);
|
|
@@ -1837,16 +1852,18 @@ var Pitchfork = class extends SegmentDrawing {
|
|
|
1837
1852
|
geometry(proj) {
|
|
1838
1853
|
const a = this.anchors[0];
|
|
1839
1854
|
const b = this.anchors[1];
|
|
1840
|
-
|
|
1841
|
-
if (!a || !b || !c) return null;
|
|
1855
|
+
if (!a || !b) return null;
|
|
1842
1856
|
const px = (p) => {
|
|
1843
1857
|
const y = proj.yOf(p.price, this.paneId);
|
|
1844
1858
|
return y == null ? null : [proj.xOf(p.time), y];
|
|
1845
1859
|
};
|
|
1846
1860
|
const P0 = px(a);
|
|
1847
1861
|
const P1 = px(b);
|
|
1862
|
+
if (!P0 || !P1) return null;
|
|
1863
|
+
const c = this.anchors[2];
|
|
1864
|
+
if (!c) return { segments: [[P0[0], P0[1], P1[0], P1[1]]], fill: null };
|
|
1848
1865
|
const P2 = px(c);
|
|
1849
|
-
if (!
|
|
1866
|
+
if (!P2) return null;
|
|
1850
1867
|
const mx = (P1[0] + P2[0]) / 2;
|
|
1851
1868
|
const my = (P1[1] + P2[1]) / 2;
|
|
1852
1869
|
const dx = mx - P0[0];
|
|
@@ -1893,16 +1910,19 @@ var PitchforkVariant = class extends SegmentDrawing {
|
|
|
1893
1910
|
geometry(proj) {
|
|
1894
1911
|
const a = this.anchors[0];
|
|
1895
1912
|
const b = this.anchors[1];
|
|
1896
|
-
|
|
1897
|
-
if (!a || !b || !c) return null;
|
|
1913
|
+
if (!a || !b) return null;
|
|
1898
1914
|
const px = (p) => {
|
|
1899
1915
|
const y = proj.yOf(p.price, this.paneId);
|
|
1900
1916
|
return y == null ? null : [proj.xOf(p.time), y];
|
|
1901
1917
|
};
|
|
1902
|
-
const
|
|
1918
|
+
const P0 = px(a);
|
|
1903
1919
|
const P1 = px(b);
|
|
1920
|
+
if (!P0 || !P1) return null;
|
|
1921
|
+
const c = this.anchors[2];
|
|
1922
|
+
if (!c) return { segments: [[P0[0], P0[1], P1[0], P1[1]]], fill: null };
|
|
1923
|
+
const S = px(this.medianStart(a, b, c));
|
|
1904
1924
|
const P2 = px(c);
|
|
1905
|
-
if (!S || !
|
|
1925
|
+
if (!S || !P2) return null;
|
|
1906
1926
|
const mx = (P1[0] + P2[0]) / 2;
|
|
1907
1927
|
const my = (P1[1] + P2[1]) / 2;
|
|
1908
1928
|
const dx = mx - S[0];
|
|
@@ -1917,8 +1937,12 @@ var PitchforkVariant = class extends SegmentDrawing {
|
|
|
1917
1937
|
// upper tine
|
|
1918
1938
|
extendRay(P2[0], P2[1], P2[0] + dx, P2[1] + dy, "right", w, h),
|
|
1919
1939
|
// lower tine
|
|
1920
|
-
[P1[0], P1[1], P2[0], P2[1]]
|
|
1940
|
+
[P1[0], P1[1], P2[0], P2[1]],
|
|
1921
1941
|
// base line
|
|
1942
|
+
// The median leaves from the shifted origin, not the pivot — without this construction
|
|
1943
|
+
// line the pivot handle would float unattached to the shape it defines.
|
|
1944
|
+
[P0[0], P0[1], P1[0], P1[1]]
|
|
1945
|
+
// pivot → first tine anchor
|
|
1922
1946
|
],
|
|
1923
1947
|
fill: null
|
|
1924
1948
|
};
|
|
@@ -1975,17 +1999,19 @@ var InsidePitchfork = class extends SegmentDrawing {
|
|
|
1975
1999
|
geometry(proj) {
|
|
1976
2000
|
const a = this.anchors[0];
|
|
1977
2001
|
const b = this.anchors[1];
|
|
1978
|
-
|
|
1979
|
-
if (!a || !b || !c) return null;
|
|
2002
|
+
if (!a || !b) return null;
|
|
1980
2003
|
const px = (p) => {
|
|
1981
2004
|
const y = proj.yOf(p.price, this.paneId);
|
|
1982
2005
|
return y == null ? null : [proj.xOf(p.time), y];
|
|
1983
2006
|
};
|
|
1984
|
-
const B = px({ time: (a.time + b.time) / 2, price: (a.price + b.price) / 2 });
|
|
1985
2007
|
const P0 = px(a);
|
|
1986
2008
|
const P1 = px(b);
|
|
2009
|
+
if (!P0 || !P1) return null;
|
|
2010
|
+
const c = this.anchors[2];
|
|
2011
|
+
if (!c) return { segments: [[P0[0], P0[1], P1[0], P1[1]]], fill: null };
|
|
2012
|
+
const B = px({ time: (a.time + b.time) / 2, price: (a.price + b.price) / 2 });
|
|
1987
2013
|
const P2 = px(c);
|
|
1988
|
-
if (!B || !
|
|
2014
|
+
if (!B || !P2) return null;
|
|
1989
2015
|
const mx = (P1[0] + P2[0]) / 2;
|
|
1990
2016
|
const my = (P1[1] + P2[1]) / 2;
|
|
1991
2017
|
const dx = P2[0] - B[0];
|
|
@@ -2156,16 +2182,18 @@ var Triangle = class extends SegmentDrawing {
|
|
|
2156
2182
|
geometry(proj) {
|
|
2157
2183
|
const a = this.anchors[0];
|
|
2158
2184
|
const b = this.anchors[1];
|
|
2159
|
-
|
|
2160
|
-
if (!a || !b || !c) return null;
|
|
2185
|
+
if (!a || !b) return null;
|
|
2161
2186
|
const px = (p) => {
|
|
2162
2187
|
const y = proj.yOf(p.price, this.paneId);
|
|
2163
2188
|
return y == null ? null : [proj.xOf(p.time), y];
|
|
2164
2189
|
};
|
|
2165
2190
|
const A = px(a);
|
|
2166
2191
|
const B = px(b);
|
|
2192
|
+
if (!A || !B) return null;
|
|
2193
|
+
const c = this.anchors[2];
|
|
2194
|
+
if (!c) return { segments: [[A[0], A[1], B[0], B[1]]], fill: null };
|
|
2167
2195
|
const C = px(c);
|
|
2168
|
-
if (!
|
|
2196
|
+
if (!C) return null;
|
|
2169
2197
|
return {
|
|
2170
2198
|
segments: [
|
|
2171
2199
|
[A[0], A[1], B[0], B[1]],
|
|
@@ -6365,4 +6393,4 @@ var SidePanel = class {
|
|
|
6365
6393
|
}
|
|
6366
6394
|
};
|
|
6367
6395
|
|
|
6368
|
-
export { AnchoredVwap, ArrowMark, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, nativeIndicatorDescriptors, nativeIndicatorTypes, normalizeSettingsRow, pinnedTopbarActionIds, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTopbarComposition, settingsRowValueKeys, settingsRowVisible, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
|
|
6396
|
+
export { AnchoredVwap, ArrowMark, Callout, CalloutBase, Comment, DEDEKIND_CURVATURE_OPTIONS, DEFAULT_DRAWING_COLOR, DEFAULT_PANEL_MAX_WIDTH, DEFAULT_PANEL_MIN_WIDTH, DEFAULT_PANEL_ORDER, DEFAULT_PANEL_WIDTH, DIRECTION_OPTIONS, DedekindTessellation, Drawing, FibRatios, FibSpiral, FixedRangeVolumeProfile, GANN_SQUARE_ARCS, GLYPH_OPTIONS, GannSquare, GlyphStamp, LINE_STYLE_OPTIONS, MACH_NUMBER_OPTIONS, MACH_WAVE_COUNT_OPTIONS, MAGNIFIER_TIMEFRAME_OPTIONS, MachFigure, Magnifier, MeasureBox, Note, OVERRIDABLE_TOPBAR_IDS, PatternDrawing, PositionTool, PriceLabel, PriceNote, RadialFib, RegressionChannel, STAMP_SIZE_OPTIONS, SegmentDrawing, SidePanel, Signpost, TEXT_SIZE_OPTIONS, TOPBAR_BUILTIN_IDS, TOPBAR_DEFAULT_LEFT, TOPBAR_DEFAULT_RIGHT, TextLabel, chartType, chartTypes, clampPanelWidth, createDrawing, deserializeDrawing, drawingTypes, foldBaseModulation, formatDuration, getDrawingType, getNativeIndicator, inputDeltas, inputVisible, isLineLikeSeries, legendActions, legendActionsProviderFor, legendCallouts, legendCalloutsProviderFor, lineSegmentIntersection, magnifierTimeframeLabel, nativeIndicatorDescriptors, nativeIndicatorTypes, nativeInstanceChannel, normalizeSettingsRow, pinnedTopbarActionIds, registerChartType, registerDefaultEngine, registerDrawingType, registerLegendAction, registerLegendCallout, registerNativeIndicator, registerRendererDefaults, registerRendererLayer, registerSidePanel, registerStatePersistence, registerSymbolRanking, registerWidgetAction, registerWidgetAttachment, rendererDefaults, rendererLayers, resetDrawingSettings, resolveEngines, resolveTopbarComposition, seriesInScale, seriesShownOn, settingsRowValueKeys, settingsRowVisible, sidePanels, stableSeriesId, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { overlayScrollbarCss,
|
|
1
|
+
import { overlayScrollbarCss, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, injectStyles, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-CAFCLMPF.js';
|
|
2
2
|
import { VanillaMachine, normalizeProps, spreadProps } from '@zag-js/vanilla';
|
|
3
3
|
export { normalizeProps, spreadProps } from '@zag-js/vanilla';
|
|
4
4
|
import * as menu from '@zag-js/menu';
|
|
@@ -22,6 +22,129 @@ var uid = 0;
|
|
|
22
22
|
function nextUid(prefix) {
|
|
23
23
|
return `${prefix}-${++uid}`;
|
|
24
24
|
}
|
|
25
|
+
|
|
26
|
+
// src/core/tokens.ts
|
|
27
|
+
var STATIC_TOKENS = {
|
|
28
|
+
"--vela-space-1": "4px",
|
|
29
|
+
"--vela-space-2": "8px",
|
|
30
|
+
"--vela-space-3": "12px",
|
|
31
|
+
"--vela-space-4": "16px",
|
|
32
|
+
"--vela-radius-sm": "4px",
|
|
33
|
+
"--vela-radius-md": "6px",
|
|
34
|
+
"--vela-radius-lg": "10px",
|
|
35
|
+
"--vela-z-tooltip": "60",
|
|
36
|
+
"--vela-z-menu": "50",
|
|
37
|
+
"--vela-z-dialog": "40",
|
|
38
|
+
// Form popovers portal to <body> (or a chart host) and must sit above a dialog
|
|
39
|
+
// whose own stacking context may be nested inside the chart container.
|
|
40
|
+
"--vela-z-popover": "6000",
|
|
41
|
+
"--vela-ease": "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
42
|
+
"--vela-dur-fast": "90ms",
|
|
43
|
+
"--vela-dur-med": "160ms",
|
|
44
|
+
"--vela-font-size-sm": "11px",
|
|
45
|
+
"--vela-font-size-md": "12px",
|
|
46
|
+
"--vela-font-size-lg": "14px"
|
|
47
|
+
};
|
|
48
|
+
function themeTokens(t) {
|
|
49
|
+
const dark = isDarkColor(t.background);
|
|
50
|
+
const wash = (a) => dark ? `rgba(255,255,255,${a})` : withAlpha(t.textColor, a + 0.02);
|
|
51
|
+
const elevated = mix(t.background, dark ? "#ffffff" : t.textColor, dark ? 0.03 : 0.05);
|
|
52
|
+
return {
|
|
53
|
+
"--vela-font": t.fontFamily,
|
|
54
|
+
"--vela-bg": t.background,
|
|
55
|
+
// Chrome text is slightly brighter than the chart's own axis text, which is
|
|
56
|
+
// deliberately recessive; the chart keeps using `t.textColor` directly.
|
|
57
|
+
"--vela-fg": dark ? "#d1d4dc" : t.textColor,
|
|
58
|
+
"--vela-fg-muted": dark ? "#868a96" : withAlpha(t.textColor, 0.62),
|
|
59
|
+
"--vela-fg-faint": withAlpha(t.textColor, 0.35),
|
|
60
|
+
"--vela-fg-bright": dark ? "#f0f3fa" : "#000000",
|
|
61
|
+
"--vela-surface": t.background,
|
|
62
|
+
// Panels and menus float ABOVE the chart, so their surface is the wash flattened onto
|
|
63
|
+
// the chart background — opaque, or candles read through the panel.
|
|
64
|
+
"--vela-surface-elev": elevated,
|
|
65
|
+
"--vela-surface-overlay": elevated,
|
|
66
|
+
// Recessed fields (inputs, selects) read as cut INTO their panel, so they fall back
|
|
67
|
+
// to the chart surface and are separated from the panel by their border alone.
|
|
68
|
+
"--vela-surface-sunken": t.background,
|
|
69
|
+
"--vela-border": t.borderColor,
|
|
70
|
+
"--vela-border-strong": dark ? "#34353b" : withAlpha(t.textColor, 0.28),
|
|
71
|
+
"--vela-border-soft": t.borderColor,
|
|
72
|
+
// Barely-there rules INSIDE a panel (row separators), where a full border would
|
|
73
|
+
// chop the list into boxes.
|
|
74
|
+
"--vela-border-faint": withAlpha(t.textColor, 0.08),
|
|
75
|
+
"--vela-hover": wash(0.06),
|
|
76
|
+
"--vela-active": wash(0.1),
|
|
77
|
+
// A deliberately stronger hover for rows inside an already-tinted surface (menu
|
|
78
|
+
// items in an active flyout), where the normal wash would not separate from it.
|
|
79
|
+
"--vela-hover-strong": wash(0.16),
|
|
80
|
+
"--vela-focus": withAlpha(t.textColor, 0.5),
|
|
81
|
+
"--vela-focus-soft": withAlpha(t.textColor, 0.12),
|
|
82
|
+
// Separator hover — the SAME wash the chart's pane separators paint on hover
|
|
83
|
+
// (soft full-thickness band + solid 2px center line), so DOM-drawn dividers
|
|
84
|
+
// (the workspace grid) and canvas-drawn ones read as one family.
|
|
85
|
+
"--vela-separator-hover-band": withAlpha(t.textColor, 0.1),
|
|
86
|
+
"--vela-separator-hover-line": withAlpha(t.textColor, 0.55),
|
|
87
|
+
"--vela-scroll": withAlpha(t.textColor, 0.3),
|
|
88
|
+
"--vela-accent": ACCENT,
|
|
89
|
+
"--vela-accent-bright": ACCENT_BRIGHT,
|
|
90
|
+
"--vela-highlight": HIGHLIGHT,
|
|
91
|
+
// The inverse chip: a filled selected state (active tab, ticked checkbox). Its ink
|
|
92
|
+
// must contrast the fill, so the pair flips together with the theme.
|
|
93
|
+
"--vela-selected-bg": dark ? "#f0f3fa" : t.textColor,
|
|
94
|
+
"--vela-selected-fg": dark ? t.background : "#ffffff",
|
|
95
|
+
// Fixed ink for saturated fills (accent buttons, categorical avatars) — those fills
|
|
96
|
+
// are theme-independent, so their ink is too.
|
|
97
|
+
"--vela-fg-on-fill": "#ffffff",
|
|
98
|
+
"--vela-up": t.upColor,
|
|
99
|
+
"--vela-down": t.downColor,
|
|
100
|
+
"--vela-danger": t.downColor,
|
|
101
|
+
"--vela-shadow": "0 8px 30px rgba(0,0,0,0.5)",
|
|
102
|
+
"--vela-shadow-dialog": "0 20px 60px rgba(0,0,0,0.5)",
|
|
103
|
+
"--vela-backdrop": "rgba(0,0,0,0.45)"
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/ui/tokens.ts
|
|
108
|
+
var STATIC_ID = "vela-ui-tokens";
|
|
109
|
+
var STATIC_DECLS = Object.entries(STATIC_TOKENS).map(([k, v]) => ` ${k}: ${v};`).join("\n");
|
|
110
|
+
var STATIC_CSS = `
|
|
111
|
+
.vela-ui, .vela-ui-layer {
|
|
112
|
+
${STATIC_DECLS}
|
|
113
|
+
font-family: var(--vela-font, -apple-system, system-ui, sans-serif);
|
|
114
|
+
box-sizing: border-box;
|
|
115
|
+
/* Chrome text (titles, buttons, menus, readouts) is UI, not copy \u2014 never selectable. */
|
|
116
|
+
user-select: none;
|
|
117
|
+
-webkit-user-select: none;
|
|
118
|
+
}
|
|
119
|
+
.vela-ui *, .vela-ui-layer * { box-sizing: border-box; }
|
|
120
|
+
/* Text ENTRY is the one exception: selection is part of editing. */
|
|
121
|
+
.vela-ui :is(input, textarea), .vela-ui-layer :is(input, textarea) { user-select: text; -webkit-user-select: text; }
|
|
122
|
+
/* iOS Safari zooms the page when a focused field is under 16px, and often
|
|
123
|
+
keeps that zoom after the field blurs or a dialog closes. The shell's
|
|
124
|
+
mobile size class is the honest gate \u2014 not a media query \u2014 so an embedded
|
|
125
|
+
chart on a wide desktop still gets the rule when it is in the phone layout.
|
|
126
|
+
Scoped to the kit root so a host page's own [data-layout] is never touched. */
|
|
127
|
+
.vela-ui[data-layout='mobile'] :is(input, textarea, select) { font-size: 16px; }
|
|
128
|
+
.vela-icon { display: inline-flex; align-items: center; flex: none; }
|
|
129
|
+
.vela-icon svg { display: block; }
|
|
130
|
+
`;
|
|
131
|
+
function applyThemeTokens(el, t) {
|
|
132
|
+
const tokens = themeTokens(t);
|
|
133
|
+
for (const key in tokens) el.style.setProperty(key, tokens[key]);
|
|
134
|
+
}
|
|
135
|
+
function applyPlotOverlayTokens(host, base, config) {
|
|
136
|
+
const layout = config?.layout;
|
|
137
|
+
const t = layout?.background && layout.textColor ? { ...base, background: layout.background, textColor: layout.textColor } : base;
|
|
138
|
+
applyThemeTokens(host, t);
|
|
139
|
+
}
|
|
140
|
+
function floatingLayerHost(from, fallback) {
|
|
141
|
+
return from.closest(".vela-ui") ?? fallback ?? from;
|
|
142
|
+
}
|
|
143
|
+
function ensureUIHost(el, theme) {
|
|
144
|
+
injectStyles(STATIC_ID, STATIC_CSS, el.getRootNode());
|
|
145
|
+
el.classList.add("vela-ui");
|
|
146
|
+
if (theme) applyThemeTokens(el, theme);
|
|
147
|
+
}
|
|
25
148
|
function menuController(opts) {
|
|
26
149
|
return {
|
|
27
150
|
machine: menu.machine,
|
|
@@ -46,7 +169,7 @@ var MENU_CSS = `
|
|
|
46
169
|
/* The list is a <ul>: without this, block rows (the separator) paint a ::marker dot. */
|
|
47
170
|
list-style: none;
|
|
48
171
|
margin: 0;
|
|
49
|
-
background: var(--vela-surface
|
|
172
|
+
background: var(--vela-surface);
|
|
50
173
|
color: var(--vela-fg);
|
|
51
174
|
border: 1px solid var(--vela-border-strong);
|
|
52
175
|
border-radius: 6px;
|
|
@@ -337,7 +460,7 @@ var Menu = class {
|
|
|
337
460
|
const anchor = opts.trigger ?? opts.host ?? document.body;
|
|
338
461
|
const doc = anchor.ownerDocument;
|
|
339
462
|
injectStyles(MENU_STYLE_ID, MENU_CSS, doc);
|
|
340
|
-
const host = opts.host ?? anchor
|
|
463
|
+
const host = floatingLayerHost(opts.host ?? anchor, doc.body);
|
|
341
464
|
this.root = new Surface(doc, {
|
|
342
465
|
host,
|
|
343
466
|
placement: opts.placement,
|
|
@@ -376,126 +499,6 @@ var Menu = class {
|
|
|
376
499
|
}
|
|
377
500
|
};
|
|
378
501
|
|
|
379
|
-
// src/core/tokens.ts
|
|
380
|
-
var STATIC_TOKENS = {
|
|
381
|
-
"--vela-space-1": "4px",
|
|
382
|
-
"--vela-space-2": "8px",
|
|
383
|
-
"--vela-space-3": "12px",
|
|
384
|
-
"--vela-space-4": "16px",
|
|
385
|
-
"--vela-radius-sm": "4px",
|
|
386
|
-
"--vela-radius-md": "6px",
|
|
387
|
-
"--vela-radius-lg": "10px",
|
|
388
|
-
"--vela-z-tooltip": "60",
|
|
389
|
-
"--vela-z-menu": "50",
|
|
390
|
-
"--vela-z-dialog": "40",
|
|
391
|
-
// Form popovers portal to <body> (or a chart host) and must sit above a dialog
|
|
392
|
-
// whose own stacking context may be nested inside the chart container.
|
|
393
|
-
"--vela-z-popover": "6000",
|
|
394
|
-
"--vela-ease": "cubic-bezier(0.22, 1, 0.36, 1)",
|
|
395
|
-
"--vela-dur-fast": "90ms",
|
|
396
|
-
"--vela-dur-med": "160ms",
|
|
397
|
-
"--vela-font-size-sm": "11px",
|
|
398
|
-
"--vela-font-size-md": "12px",
|
|
399
|
-
"--vela-font-size-lg": "14px"
|
|
400
|
-
};
|
|
401
|
-
function themeTokens(t) {
|
|
402
|
-
const dark = isDarkColor(t.background);
|
|
403
|
-
const wash = (a) => dark ? `rgba(255,255,255,${a})` : withAlpha(t.textColor, a + 0.02);
|
|
404
|
-
const elevated = mix(t.background, dark ? "#ffffff" : t.textColor, dark ? 0.03 : 0.05);
|
|
405
|
-
return {
|
|
406
|
-
"--vela-font": t.fontFamily,
|
|
407
|
-
"--vela-bg": t.background,
|
|
408
|
-
// Chrome text is slightly brighter than the chart's own axis text, which is
|
|
409
|
-
// deliberately recessive; the chart keeps using `t.textColor` directly.
|
|
410
|
-
"--vela-fg": dark ? "#d1d4dc" : t.textColor,
|
|
411
|
-
"--vela-fg-muted": dark ? "#868a96" : withAlpha(t.textColor, 0.62),
|
|
412
|
-
"--vela-fg-faint": withAlpha(t.textColor, 0.35),
|
|
413
|
-
"--vela-fg-bright": dark ? "#f0f3fa" : "#000000",
|
|
414
|
-
"--vela-surface": t.background,
|
|
415
|
-
// Panels and menus float ABOVE the chart, so their surface is the wash flattened onto
|
|
416
|
-
// the chart background — opaque, or candles read through the panel.
|
|
417
|
-
"--vela-surface-elev": elevated,
|
|
418
|
-
"--vela-surface-overlay": elevated,
|
|
419
|
-
// Recessed fields (inputs, selects) read as cut INTO their panel, so they fall back
|
|
420
|
-
// to the chart surface and are separated from the panel by their border alone.
|
|
421
|
-
"--vela-surface-sunken": t.background,
|
|
422
|
-
"--vela-border": t.borderColor,
|
|
423
|
-
"--vela-border-strong": dark ? "#34353b" : withAlpha(t.textColor, 0.28),
|
|
424
|
-
"--vela-border-soft": t.borderColor,
|
|
425
|
-
// Barely-there rules INSIDE a panel (row separators), where a full border would
|
|
426
|
-
// chop the list into boxes.
|
|
427
|
-
"--vela-border-faint": withAlpha(t.textColor, 0.08),
|
|
428
|
-
"--vela-hover": wash(0.06),
|
|
429
|
-
"--vela-active": wash(0.1),
|
|
430
|
-
// A deliberately stronger hover for rows inside an already-tinted surface (menu
|
|
431
|
-
// items in an active flyout), where the normal wash would not separate from it.
|
|
432
|
-
"--vela-hover-strong": wash(0.16),
|
|
433
|
-
"--vela-focus": withAlpha(t.textColor, 0.5),
|
|
434
|
-
"--vela-focus-soft": withAlpha(t.textColor, 0.12),
|
|
435
|
-
// Separator hover — the SAME wash the chart's pane separators paint on hover
|
|
436
|
-
// (soft full-thickness band + solid 2px center line), so DOM-drawn dividers
|
|
437
|
-
// (the workspace grid) and canvas-drawn ones read as one family.
|
|
438
|
-
"--vela-separator-hover-band": withAlpha(t.textColor, 0.1),
|
|
439
|
-
"--vela-separator-hover-line": withAlpha(t.textColor, 0.55),
|
|
440
|
-
"--vela-scroll": withAlpha(t.textColor, 0.3),
|
|
441
|
-
"--vela-accent": ACCENT,
|
|
442
|
-
"--vela-accent-bright": ACCENT_BRIGHT,
|
|
443
|
-
"--vela-highlight": HIGHLIGHT,
|
|
444
|
-
// The inverse chip: a filled selected state (active tab, ticked checkbox). Its ink
|
|
445
|
-
// must contrast the fill, so the pair flips together with the theme.
|
|
446
|
-
"--vela-selected-bg": dark ? "#f0f3fa" : t.textColor,
|
|
447
|
-
"--vela-selected-fg": dark ? t.background : "#ffffff",
|
|
448
|
-
// Fixed ink for saturated fills (accent buttons, categorical avatars) — those fills
|
|
449
|
-
// are theme-independent, so their ink is too.
|
|
450
|
-
"--vela-fg-on-fill": "#ffffff",
|
|
451
|
-
"--vela-up": t.upColor,
|
|
452
|
-
"--vela-down": t.downColor,
|
|
453
|
-
"--vela-danger": t.downColor,
|
|
454
|
-
"--vela-shadow": "0 8px 30px rgba(0,0,0,0.5)",
|
|
455
|
-
"--vela-shadow-dialog": "0 20px 60px rgba(0,0,0,0.5)",
|
|
456
|
-
"--vela-backdrop": "rgba(0,0,0,0.45)"
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
// src/ui/tokens.ts
|
|
461
|
-
var STATIC_ID = "vela-ui-tokens";
|
|
462
|
-
var STATIC_DECLS = Object.entries(STATIC_TOKENS).map(([k, v]) => ` ${k}: ${v};`).join("\n");
|
|
463
|
-
var STATIC_CSS = `
|
|
464
|
-
.vela-ui, .vela-ui-layer {
|
|
465
|
-
${STATIC_DECLS}
|
|
466
|
-
font-family: var(--vela-font, -apple-system, system-ui, sans-serif);
|
|
467
|
-
box-sizing: border-box;
|
|
468
|
-
/* Chrome text (titles, buttons, menus, readouts) is UI, not copy \u2014 never selectable. */
|
|
469
|
-
user-select: none;
|
|
470
|
-
-webkit-user-select: none;
|
|
471
|
-
}
|
|
472
|
-
.vela-ui *, .vela-ui-layer * { box-sizing: border-box; }
|
|
473
|
-
/* Text ENTRY is the one exception: selection is part of editing. */
|
|
474
|
-
.vela-ui :is(input, textarea), .vela-ui-layer :is(input, textarea) { user-select: text; -webkit-user-select: text; }
|
|
475
|
-
/* iOS Safari zooms the page when a focused field is under 16px, and often
|
|
476
|
-
keeps that zoom after the field blurs or a dialog closes. The shell's
|
|
477
|
-
mobile size class is the honest gate \u2014 not a media query \u2014 so an embedded
|
|
478
|
-
chart on a wide desktop still gets the rule when it is in the phone layout.
|
|
479
|
-
Scoped to the kit root so a host page's own [data-layout] is never touched. */
|
|
480
|
-
.vela-ui[data-layout='mobile'] :is(input, textarea, select) { font-size: 16px; }
|
|
481
|
-
.vela-icon { display: inline-flex; align-items: center; flex: none; }
|
|
482
|
-
.vela-icon svg { display: block; }
|
|
483
|
-
`;
|
|
484
|
-
function applyThemeTokens(el, t) {
|
|
485
|
-
const tokens = themeTokens(t);
|
|
486
|
-
for (const key in tokens) el.style.setProperty(key, tokens[key]);
|
|
487
|
-
}
|
|
488
|
-
function applyPlotOverlayTokens(host, base, config) {
|
|
489
|
-
const layout = config?.layout;
|
|
490
|
-
const t = layout?.background && layout.textColor ? { ...base, background: layout.background, textColor: layout.textColor } : base;
|
|
491
|
-
applyThemeTokens(host, t);
|
|
492
|
-
}
|
|
493
|
-
function ensureUIHost(el, theme) {
|
|
494
|
-
injectStyles(STATIC_ID, STATIC_CSS, el.getRootNode());
|
|
495
|
-
el.classList.add("vela-ui");
|
|
496
|
-
if (theme) applyThemeTokens(el, theme);
|
|
497
|
-
}
|
|
498
|
-
|
|
499
502
|
// src/ui/components/popover/controller.ts
|
|
500
503
|
function insetRect(r, inset) {
|
|
501
504
|
return {
|
|
@@ -602,7 +605,8 @@ var Popover = class {
|
|
|
602
605
|
const doc = opts.trigger.ownerDocument;
|
|
603
606
|
injectStyles(POPOVER_STYLE_ID, POPOVER_CSS, doc);
|
|
604
607
|
this.trigger = opts.trigger;
|
|
605
|
-
this.host = opts.host ?? doc.body;
|
|
608
|
+
this.host = opts.host ?? floatingLayerHost(opts.trigger, doc.body);
|
|
609
|
+
this.inheritsTokens = !opts.host && this.host !== doc.body;
|
|
606
610
|
this.ctrl = popoverController(opts);
|
|
607
611
|
this.boundary = opts.boundary ?? "viewport";
|
|
608
612
|
this.theme = opts.theme;
|
|
@@ -634,7 +638,7 @@ var Popover = class {
|
|
|
634
638
|
clearTimeout(this.leaveTimer);
|
|
635
639
|
this.leaveTimer = null;
|
|
636
640
|
}
|
|
637
|
-
ensureUIHost(this.el, this.theme);
|
|
641
|
+
ensureUIHost(this.el, this.inheritsTokens ? void 0 : this.theme);
|
|
638
642
|
if (this.fadeMs > 0) {
|
|
639
643
|
this.el.style.transition = `opacity ${this.fadeMs}ms ease`;
|
|
640
644
|
this.el.style.opacity = "0";
|