@luxalgo/vela 0.6.14 → 0.6.16

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.
Files changed (51) hide show
  1. package/NOTICE +28 -28
  2. package/README.md +9 -2
  3. package/dist/{DataProvider-DhzstpQb.d.ts → DataProvider-XLdJB86x.d.ts} +1 -1
  4. package/dist/{DataProvider-DlMtrwqM.d.cts → DataProvider-xH2VBcFT.d.cts} +1 -1
  5. package/dist/{chunk-KG4YT3TI.js → chunk-6DPAYEGO.js} +8 -1
  6. package/dist/chunk-FE6V2YAQ.js +1 -0
  7. package/dist/{chunk-N2Q5EEFH.js → chunk-GIJYO4LO.js} +2596 -242
  8. package/dist/{chunk-F4M24ANM.js → chunk-I77F2SVE.js} +80 -4
  9. package/dist/{chunk-MHY7MVXH.js → chunk-MGU3USTP.js} +29 -16
  10. package/dist/{chunk-G77Y7LK2.js → chunk-Q3TFJNJW.js} +2 -2
  11. package/dist/{chunk-64TF7JAJ.js → chunk-SEOO6YG7.js} +408 -184
  12. package/dist/{contributions-lPojhTxI.d.cts → contributions-BEkxwA5F.d.cts} +40 -13
  13. package/dist/{contributions-37nni40G.d.ts → contributions-CoAX7_SF.d.ts} +40 -13
  14. package/dist/index.cjs +2755 -380
  15. package/dist/index.d.cts +20 -12
  16. package/dist/index.d.ts +20 -12
  17. package/dist/index.js +5 -5
  18. package/dist/{options-CYS5Wmlx.d.ts → options-bdSAtp7y.d.cts} +5 -0
  19. package/dist/{options-CYS5Wmlx.d.cts → options-bdSAtp7y.d.ts} +5 -0
  20. package/dist/{plugin-DHyaoMjW.d.ts → plugin-CNUgbRNq.d.ts} +11 -8
  21. package/dist/{plugin-Cwikpz1m.d.cts → plugin-Dxyq35Zf.d.cts} +11 -8
  22. package/dist/plugin.cjs +8 -0
  23. package/dist/plugin.d.cts +5 -5
  24. package/dist/plugin.d.ts +5 -5
  25. package/dist/plugin.js +3 -3
  26. package/dist/providers/binance.d.cts +2 -2
  27. package/dist/providers/binance.d.ts +2 -2
  28. package/dist/providers/coinbase.d.cts +2 -2
  29. package/dist/providers/coinbase.d.ts +2 -2
  30. package/dist/providers/hyperliquid.d.cts +2 -2
  31. package/dist/providers/hyperliquid.d.ts +2 -2
  32. package/dist/{side-panel-CT9ZwIGz.d.cts → side-panel-HF0IAzwf.d.cts} +17 -0
  33. package/dist/{side-panel-CT9ZwIGz.d.ts → side-panel-HF0IAzwf.d.ts} +17 -0
  34. package/dist/{statusline-model-D-q_OOx9.d.ts → statusline-model-CbPza-Wc.d.cts} +6 -4
  35. package/dist/{statusline-model-CiJm-riV.d.cts → statusline-model-D7cWkw8A.d.ts} +6 -4
  36. package/dist/ui.cjs +34 -15
  37. package/dist/ui.d.cts +1 -1
  38. package/dist/ui.d.ts +1 -1
  39. package/dist/ui.js +3 -3
  40. package/dist/vela.global.js +2675 -300
  41. package/dist/vela.global.min.js +58 -52
  42. package/dist/widget.cjs +3296 -622
  43. package/dist/widget.d.cts +15 -11
  44. package/dist/widget.d.ts +15 -11
  45. package/dist/widget.js +7 -7
  46. package/dist/workspace.cjs +3296 -622
  47. package/dist/workspace.d.cts +49 -19
  48. package/dist/workspace.d.ts +49 -19
  49. package/dist/workspace.js +6 -6
  50. package/package.json +1 -1
  51. package/dist/chunk-H26BEHF4.js +0 -7
@@ -1,4 +1,4 @@
1
- import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl } from './chunk-KG4YT3TI.js';
1
+ import { svg24, NEUTRAL, BEARISH, WARNING, BULLISH, INFO, ACCENT_BRIGHT, VALID, INVALID, MARKER, ACCENT, injectStyles, iconEl } from './chunk-6DPAYEGO.js';
2
2
 
3
3
  // src/core/native-indicators/NativeIndicator.ts
4
4
  var REGISTRY = /* @__PURE__ */ new Map();
@@ -5890,6 +5890,12 @@ function rendererLayers() {
5890
5890
  return [...registry2.values()];
5891
5891
  }
5892
5892
 
5893
+ // src/core/model/identity.ts
5894
+ function stableSeriesId(parts) {
5895
+ const normTitle = parts.title.trim().toLowerCase().replace(/\s+/g, "-");
5896
+ return `${parts.instanceId}:${parts.kind}:${normTitle}#${parts.ordinal}`;
5897
+ }
5898
+
5893
5899
  // src/widget/topbar-composition.ts
5894
5900
  var TOPBAR_BUILTIN_IDS = ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo", "alerts", "panels", "screenshot"];
5895
5901
  var TOPBAR_DEFAULT_LEFT = ["symbol", "timeframes", "style", "layout", "indicators", "actions", "undo-redo"];
@@ -6124,6 +6130,22 @@ var CSS = `
6124
6130
  }
6125
6131
  .vela-panel-close .vela-icon { width: 16px; height: 16px; }
6126
6132
  .vela-panel-close:hover { background: var(--vela-hover); color: var(--vela-fg-bright); }
6133
+ /* The pin: same footprint as the close button it sits beside; filled + bright once pinned. */
6134
+ .vela-panel-pin {
6135
+ all: unset;
6136
+ cursor: pointer;
6137
+ width: 26px;
6138
+ height: 26px;
6139
+ flex: none;
6140
+ display: inline-flex;
6141
+ align-items: center;
6142
+ justify-content: center;
6143
+ border-radius: 4px;
6144
+ color: var(--vela-fg-muted);
6145
+ }
6146
+ .vela-panel-pin .vela-icon { width: 15px; height: 15px; }
6147
+ .vela-panel-pin:hover { background: var(--vela-hover); color: var(--vela-fg-bright); }
6148
+ .vela-panel-pin[data-on='1'] { color: var(--vela-fg-bright); }
6127
6149
  .vela-panel-body { flex: 1; overflow: auto; padding: 8px; }
6128
6150
  .vela-panel-body::-webkit-scrollbar { width: 8px; }
6129
6151
  .vela-panel-body::-webkit-scrollbar-thumb { background: var(--vela-scroll); border-radius: 4px; border: 2px solid transparent; background-clip: padding-box; }
@@ -6148,8 +6170,23 @@ var CSS = `
6148
6170
  width: 1px;
6149
6171
  background: transparent;
6150
6172
  }
6173
+ /* The same hover ink as the workspace grid splitters and the canvas pane separators, so
6174
+ every draggable seam in the shell reads as one family. */
6151
6175
  .vela-panel-resizer:hover::after,
6152
- .vela-panel-resizer[data-dragging]::after { background: var(--vela-accent); }
6176
+ .vela-panel-resizer[data-dragging]::after { background: var(--vela-separator-hover-line); }
6177
+ /* An OVERLAY panel floats over the chart's right edge instead of taking a column: the
6178
+ chart keeps its width and layout (the dock host is position:relative \u2014 the anchoring the
6179
+ mobile rule below relies on too). Same z-order as that mobile overlay, above the chart's
6180
+ own DOM overlays; the shadow separates it from the plot it covers. */
6181
+ .vela-panel[data-overlay] {
6182
+ position: absolute;
6183
+ top: 0;
6184
+ right: 0;
6185
+ bottom: 0;
6186
+ max-width: 100%;
6187
+ z-index: 25;
6188
+ box-shadow: var(--vela-shadow);
6189
+ }
6153
6190
  /* Mobile: a 280px column would crush a phone-width chart \u2014 the panel overlays the
6154
6191
  chart area instead (its flex parent is position:relative), full-bleed, closed by
6155
6192
  the same header \u2715. Width dragging is a pointer affordance; off on mobile. */
@@ -6180,6 +6217,10 @@ var SidePanel = class {
6180
6217
  /** Notified when the USER settles a new width (drag release, or double-click reset) — never on
6181
6218
  * a programmatic {@link setWidth}, so restoring a persisted width raises no change. */
6182
6219
  this.onWidthChange = null;
6220
+ /** Notified when the USER pins or unpins a floating panel (`overlay` is the NEW placement) —
6221
+ * never on a programmatic {@link setOverlay}, for the same reason as widths. */
6222
+ this.onPlacementChange = null;
6223
+ this.pin = null;
6183
6224
  const doc = host.ownerDocument;
6184
6225
  injectStyles(STYLE_ID, CSS, doc);
6185
6226
  this.minWidth = opts.resizable ? opts.minWidth ?? DEFAULT_PANEL_MIN_WIDTH : 1;
@@ -6189,6 +6230,9 @@ var SidePanel = class {
6189
6230
  this.el = doc.createElement("div");
6190
6231
  this.el.className = `vela-panel ${modifier}`;
6191
6232
  this.el.hidden = true;
6233
+ this.floatable = opts.overlay === true;
6234
+ this.overlayOn = this.floatable;
6235
+ if (this.overlayOn) this.el.dataset.overlay = "1";
6192
6236
  this.el.style.setProperty("--vela-panel-w", `${this.widthPx}px`);
6193
6237
  const header = doc.createElement("div");
6194
6238
  header.className = "vela-panel-header";
@@ -6202,7 +6246,16 @@ var SidePanel = class {
6202
6246
  close.appendChild(iconEl("close", doc));
6203
6247
  close.title = "Close";
6204
6248
  close.addEventListener("click", () => this.toggle(false));
6205
- header.append(this.heading, this.slot, close);
6249
+ if (this.floatable) {
6250
+ this.pin = doc.createElement("button");
6251
+ this.pin.className = "vela-panel-pin";
6252
+ this.pin.addEventListener("click", () => {
6253
+ this.setOverlay(!this.overlayOn);
6254
+ this.onPlacementChange?.(this.overlayOn);
6255
+ });
6256
+ this.refreshPin();
6257
+ }
6258
+ header.append(this.heading, this.slot, ...this.pin ? [this.pin] : [], close);
6206
6259
  this.body = doc.createElement("div");
6207
6260
  this.body.className = "vela-panel-body";
6208
6261
  this.el.append(header, this.body);
@@ -6244,6 +6297,29 @@ var SidePanel = class {
6244
6297
  this.widthPx = next;
6245
6298
  this.el.style.setProperty("--vela-panel-w", `${next}px`);
6246
6299
  }
6300
+ /** Whether the panel floats over the chart right now (false for every docked panel). */
6301
+ get overlay() {
6302
+ return this.overlayOn;
6303
+ }
6304
+ /** Float or dock the panel. Only a panel declared `overlay` can float — on any other this is
6305
+ * a no-op. Silent — {@link onPlacementChange} reports the user's pin clicks only. */
6306
+ setOverlay(overlay) {
6307
+ if (!this.floatable || overlay === this.overlayOn) return;
6308
+ this.overlayOn = overlay;
6309
+ if (overlay) this.el.dataset.overlay = "1";
6310
+ else delete this.el.dataset.overlay;
6311
+ this.refreshPin();
6312
+ }
6313
+ refreshPin() {
6314
+ if (!this.pin) return;
6315
+ const pinned = !this.overlayOn;
6316
+ const doc = this.pin.ownerDocument;
6317
+ this.pin.replaceChildren(iconEl(pinned ? "pin-filled" : "pin", doc));
6318
+ this.pin.dataset.on = pinned ? "1" : "0";
6319
+ this.pin.title = pinned ? "Unpin \u2014 float over the chart" : "Pin beside the chart";
6320
+ this.pin.setAttribute("aria-label", this.pin.title);
6321
+ this.pin.setAttribute("aria-pressed", pinned ? "true" : "false");
6322
+ }
6247
6323
  destroy() {
6248
6324
  this.el.remove();
6249
6325
  }
@@ -6289,4 +6365,4 @@ var SidePanel = class {
6289
6365
  }
6290
6366
  };
6291
6367
 
6292
- 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, statePersistenceHandlers, symbolRanking, tickerModifierIds, topbarActionOverride, topbarHas, unregisterChartType, unregisterDefaultEngine, unregisterLegendAction, unregisterLegendCallout, unregisterNativeIndicator, unregisterRendererDefaults, unregisterRendererLayer, unregisterSidePanel, unregisterStatePersistence, unregisterWidgetAction, unregisterWidgetAttachment, widgetActions, widgetAttachments };
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 };
@@ -1,4 +1,4 @@
1
- import { overlayScrollbarCss, injectStyles, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-KG4YT3TI.js';
1
+ import { overlayScrollbarCss, injectStyles, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-6DPAYEGO.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';
@@ -472,6 +472,12 @@ ${STATIC_DECLS}
472
472
  .vela-ui *, .vela-ui-layer * { box-sizing: border-box; }
473
473
  /* Text ENTRY is the one exception: selection is part of editing. */
474
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; }
475
481
  .vela-icon { display: inline-flex; align-items: center; flex: none; }
476
482
  .vela-icon svg { display: block; }
477
483
  `;
@@ -2179,8 +2185,21 @@ function buildColorPicker(color, theme, onChange) {
2179
2185
  };
2180
2186
  const recentRow = document.createElement("div");
2181
2187
  recentRow.style.cssText = "display:flex;align-items:center;gap:5px;flex-wrap:wrap;border-top:1px solid var(--vela-border);padding-top:9px;";
2188
+ const recentSwatches = document.createElement("div");
2189
+ recentSwatches.style.cssText = "display:contents;";
2190
+ const add = document.createElement("label");
2191
+ add.style.cssText = `width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px dashed var(--vela-border-strong);cursor:pointer;display:flex;align-items:center;justify-content:center;color:${theme.textColor};font:14px ${theme.fontFamily};position:relative;`;
2192
+ add.textContent = "+";
2193
+ const customInput = document.createElement("input");
2194
+ customInput.type = "color";
2195
+ customInput.value = curHex;
2196
+ customInput.style.cssText = "position:absolute;inset:0;opacity:0;cursor:pointer;";
2197
+ customInput.addEventListener("input", () => previewHex(customInput.value));
2198
+ customInput.addEventListener("change", () => pickHex(customInput.value, true));
2199
+ add.appendChild(customInput);
2200
+ recentRow.append(recentSwatches, add);
2182
2201
  const renderRecents = () => {
2183
- recentRow.replaceChildren();
2202
+ recentSwatches.replaceChildren();
2184
2203
  for (const c of recents) {
2185
2204
  const sw = document.createElement("button");
2186
2205
  sw.type = "button";
@@ -2189,18 +2208,8 @@ function buildColorPicker(color, theme, onChange) {
2189
2208
  e.stopPropagation();
2190
2209
  pickHex(c);
2191
2210
  });
2192
- recentRow.appendChild(sw);
2211
+ recentSwatches.appendChild(sw);
2193
2212
  }
2194
- const add = document.createElement("label");
2195
- add.style.cssText = `width:17px;height:17px;border-radius:var(--vela-radius-sm);border:1px dashed var(--vela-border-strong);cursor:pointer;display:flex;align-items:center;justify-content:center;color:${theme.textColor};font:14px ${theme.fontFamily};position:relative;`;
2196
- add.textContent = "+";
2197
- const input = document.createElement("input");
2198
- input.type = "color";
2199
- input.value = curHex;
2200
- input.style.cssText = "position:absolute;inset:0;opacity:0;cursor:pointer;";
2201
- input.addEventListener("input", () => pickHex(input.value, true));
2202
- add.appendChild(input);
2203
- recentRow.appendChild(add);
2204
2213
  };
2205
2214
  const opLabel = document.createElement("div");
2206
2215
  opLabel.textContent = "Opacity";
@@ -2240,14 +2249,18 @@ function buildColorPicker(color, theme, onChange) {
2240
2249
  function emit() {
2241
2250
  onChange(combineColor(curHex, curAlpha));
2242
2251
  }
2243
- function pickHex(hex, custom = false) {
2252
+ function previewHex(hex) {
2244
2253
  curHex = splitColor(hex).hex6;
2245
- addRecent(curHex);
2246
2254
  paintSelection();
2247
2255
  paintOpacity();
2248
- if (custom) renderRecents();
2249
2256
  emit();
2250
2257
  }
2258
+ function pickHex(hex, custom = false) {
2259
+ previewHex(hex);
2260
+ addRecent(curHex);
2261
+ customInput.value = curHex;
2262
+ if (custom) renderRecents();
2263
+ }
2251
2264
  renderRecents();
2252
2265
  paintSelection();
2253
2266
  paintOpacity();
@@ -1,5 +1,5 @@
1
- import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-MHY7MVXH.js';
2
- import { injectStyles } from './chunk-KG4YT3TI.js';
1
+ import { normalizeProps, nextUid, runMachine, spreadProps } from './chunk-MGU3USTP.js';
2
+ import { injectStyles } from './chunk-6DPAYEGO.js';
3
3
  import * as tooltip from '@zag-js/tooltip';
4
4
  import * as dialog from '@zag-js/dialog';
5
5