@luxalgo/vela 0.8.1 → 0.8.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.
Files changed (49) hide show
  1. package/README.md +1 -1
  2. package/dist/{DataProvider-DwFIoV4r.d.ts → DataProvider-oH78tYXL.d.ts} +1 -1
  3. package/dist/{DataProvider-BrlxntPN.d.cts → DataProvider-wbtJ3-Sa.d.cts} +1 -1
  4. package/dist/{chunk-DBDXKZUF.js → chunk-2IPXYM4B.js} +306 -177
  5. package/dist/{chunk-NELQJCGK.js → chunk-G7B7ZCBF.js} +167 -10
  6. package/dist/{chunk-ATGTCWHJ.js → chunk-HMHA733L.js} +473 -196
  7. package/dist/{chunk-EZ5FWVLA.js → chunk-KWI3YDBW.js} +343 -17
  8. package/dist/{chunk-LMBYEGUR.js → chunk-TO3GIK7Z.js} +71 -6
  9. package/dist/{chunk-BZQM2XO7.js → chunk-VHGACEHO.js} +62 -1
  10. package/dist/{contributions-tjNExo1o.d.ts → contributions-BhOBRenr.d.cts} +79 -12
  11. package/dist/{contributions-CtlptxR8.d.cts → contributions-HGqnNb_P.d.ts} +79 -12
  12. package/dist/index.cjs +733 -113
  13. package/dist/index.d.cts +34 -14
  14. package/dist/index.d.ts +34 -14
  15. package/dist/index.js +5 -5
  16. package/dist/{options-BnEPUuVV.d.ts → options-lMUwmRwh.d.cts} +69 -4
  17. package/dist/{options-BnEPUuVV.d.cts → options-lMUwmRwh.d.ts} +69 -4
  18. package/dist/{plugin-e2WUEtiI.d.ts → plugin-Cr2Pj8q8.d.ts} +4 -4
  19. package/dist/{plugin-BWxJRKzS.d.cts → plugin-Do5J5xuF.d.cts} +4 -4
  20. package/dist/plugin.cjs +38 -6
  21. package/dist/plugin.d.cts +5 -5
  22. package/dist/plugin.d.ts +5 -5
  23. package/dist/plugin.js +3 -3
  24. package/dist/providers/binance.d.cts +2 -2
  25. package/dist/providers/binance.d.ts +2 -2
  26. package/dist/providers/coinbase.d.cts +2 -2
  27. package/dist/providers/coinbase.d.ts +2 -2
  28. package/dist/providers/hyperliquid.d.cts +2 -2
  29. package/dist/providers/hyperliquid.d.ts +2 -2
  30. package/dist/{side-panel-HF0IAzwf.d.cts → side-panel-_2UK1gSm.d.cts} +58 -3
  31. package/dist/{side-panel-HF0IAzwf.d.ts → side-panel-_2UK1gSm.d.ts} +58 -3
  32. package/dist/{statusline-model-DFY7tuHj.d.cts → statusline-model-B-2xGlB_.d.cts} +3 -3
  33. package/dist/{statusline-model-zKXtGIjj.d.ts → statusline-model-CY1wzxHg.d.ts} +3 -3
  34. package/dist/ui.cjs +298 -13
  35. package/dist/ui.d.cts +132 -74
  36. package/dist/ui.d.ts +132 -74
  37. package/dist/ui.js +3 -3
  38. package/dist/vela.global.js +734 -114
  39. package/dist/vela.global.min.js +86 -52
  40. package/dist/widget.cjs +1227 -211
  41. package/dist/widget.d.cts +36 -12
  42. package/dist/widget.d.ts +36 -12
  43. package/dist/widget.js +7 -7
  44. package/dist/workspace.cjs +1226 -211
  45. package/dist/workspace.d.cts +47 -20
  46. package/dist/workspace.d.ts +47 -20
  47. package/dist/workspace.js +6 -6
  48. package/package.json +2 -2
  49. /package/dist/{chunk-JU4CWEBF.js → chunk-W5YPYZ2P.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { overlayScrollbarCss, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, injectStyles, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-BZQM2XO7.js';
1
+ import { overlayScrollbarCss, isDarkColor, mix, HIGHLIGHT, ACCENT_BRIGHT, ACCENT, withAlpha, injectStyles, announceSurface, holdForExit, iconAt, iconEl, BULLISH, BEARISH, WARNING, NEUTRAL } from './chunk-VHGACEHO.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';
@@ -226,6 +226,35 @@ var MENU_CSS = `
226
226
  color: var(--vela-fg-bright);
227
227
  }
228
228
  .vela-menu-item[data-checkmark] { color: var(--vela-fg-bright); }
229
+ /* Badge mode (iconBadges): the row icon sits in a rounded tile and the row grows to fit
230
+ it. An icon-less row of the same level keeps an invisible slot, so labels align. */
231
+ .vela-menu[data-badges] > .vela-menu-item { padding: 5px 10px 5px 6px; }
232
+ .vela-menu-item .vela-menu-badge {
233
+ width: 24px;
234
+ height: 24px;
235
+ padding: 3px;
236
+ flex: none;
237
+ box-sizing: border-box;
238
+ display: inline-flex;
239
+ align-items: center;
240
+ justify-content: center;
241
+ border-radius: var(--vela-radius-md);
242
+ background: var(--vela-hover);
243
+ border: 1px solid var(--vela-border);
244
+ color: var(--vela-fg-muted);
245
+ transition: background var(--vela-dur-fast) var(--vela-ease), border-color var(--vela-dur-fast) var(--vela-ease), color var(--vela-dur-fast) var(--vela-ease);
246
+ }
247
+ .vela-menu-item .vela-menu-badge:empty { background: transparent; border-color: transparent; }
248
+ .vela-menu-item .vela-menu-badge .vela-icon { color: inherit; }
249
+ .vela-menu-item[data-highlighted] .vela-menu-badge:not(:empty) { color: var(--vela-fg-bright); }
250
+ /* The selected tile inverts: a bright fill under the surface-colored glyph. After the
251
+ hover rule, so a selected row keeps its tile while highlighted. */
252
+ .vela-menu-item[data-checked] .vela-menu-badge:not(:empty),
253
+ .vela-menu-item[data-checkmark] .vela-menu-badge:not(:empty) {
254
+ background: color-mix(in srgb, var(--vela-fg-bright) 83%, var(--vela-surface));
255
+ border-color: color-mix(in srgb, var(--vela-fg-bright) 40%, transparent);
256
+ color: var(--vela-surface);
257
+ }
229
258
  /* Switch rows (boolean settings in a dropdown): a right-aligned toggle pill \u2014 the
230
259
  same control language as the settings dialog's toggles. */
231
260
  .vela-menu-switch {
@@ -290,11 +319,16 @@ var Surface = class _Surface {
290
319
  /** Trigger rect captured when this level opened — the list stays put if the
291
320
  * trigger then moves (favorite chips shifting the caret). */
292
321
  this.pinnedAnchor = null;
322
+ /** The open state last announced — see {@link announce}. */
323
+ this.shown = false;
324
+ /** The list's exit animation after a close; a reopen cancels it. */
325
+ this.exit = null;
293
326
  this.doc = doc;
294
327
  this.host = opts.host;
295
328
  this.onSelect = opts.onSelect;
296
329
  this.onFavorite = opts.onFavorite;
297
330
  this.checkmarks = opts.checkmarks === true;
331
+ this.iconBadges = opts.iconBadges === true;
298
332
  this.positioner = doc.createElement("div");
299
333
  this.positioner.className = "vela-ui-layer";
300
334
  this.list = doc.createElement("ul");
@@ -303,6 +337,7 @@ var Surface = class _Surface {
303
337
  this.positioner.appendChild(this.list);
304
338
  this.host.appendChild(this.positioner);
305
339
  const trigger = opts.trigger;
340
+ this.opener = trigger ?? opts.opener ?? null;
306
341
  this.ctrl = menuController({
307
342
  items: [],
308
343
  id: opts.id,
@@ -324,15 +359,37 @@ var Surface = class _Surface {
324
359
  if (opts.triggerId && trigger) trigger.id = opts.triggerId;
325
360
  this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => {
326
361
  const api = this.ctrl.connect(service);
362
+ const closing = this.shown && !api.open;
363
+ if (closing) this.announce(false);
364
+ if (api.open && this.exit) {
365
+ this.exit.cancel();
366
+ this.exit = null;
367
+ }
327
368
  if (trigger) spreadProps(trigger, api.getTriggerProps(), this.mid);
328
369
  spreadProps(this.positioner, api.getPositionerProps(), this.mid);
329
370
  spreadProps(this.list, api.getContentProps(), this.mid);
330
371
  this.project(api);
372
+ if (closing) this.holdExit();
373
+ if (api.open && !this.shown) this.announce(true);
374
+ });
375
+ }
376
+ /** Keep the just-closed list up through its exit animation. `spreadProps` re-applies
377
+ * `hidden` only when the machine's value for it changes, so the list stays shown until
378
+ * the exit ends — or until a reopen, which projects `hidden: false` itself. */
379
+ holdExit() {
380
+ this.list.hidden = false;
381
+ this.exit = holdForExit(this.list, () => {
382
+ this.exit = null;
383
+ if (!this.shown) this.list.hidden = true;
331
384
  });
332
385
  }
333
386
  get api() {
334
387
  return this.ctrl.connect(this.handle.service);
335
388
  }
389
+ announce(open2) {
390
+ this.shown = open2;
391
+ announceSurface(this.list, open2, "menu", this.opener);
392
+ }
336
393
  setItems(items) {
337
394
  this.items = items;
338
395
  for (const sub of this.subs.values()) sub.destroy();
@@ -349,7 +406,9 @@ var Surface = class _Surface {
349
406
  destroy() {
350
407
  for (const sub of this.subs.values()) sub.destroy();
351
408
  this.subs.clear();
409
+ this.exit?.finish();
352
410
  this.handle.stop();
411
+ if (this.shown) this.announce(false);
353
412
  this.positioner.remove();
354
413
  }
355
414
  byId(id) {
@@ -374,6 +433,10 @@ var Surface = class _Surface {
374
433
  const doc = this.doc;
375
434
  this.list.replaceChildren();
376
435
  const markable = this.checkmarks && this.items.some((i) => !(i.submenu && i.submenu.length > 0) && !i.toggle && i.checked !== void 0);
436
+ const iconic = this.items.some((i) => !!i.icon);
437
+ const badged = this.iconBadges && iconic;
438
+ if (badged) this.list.dataset.badges = "1";
439
+ else delete this.list.dataset.badges;
377
440
  for (const item of this.items) {
378
441
  if (item.separatorBefore) {
379
442
  const sep = doc.createElement("li");
@@ -399,7 +462,16 @@ var Surface = class _Surface {
399
462
  } else if (!branch && !item.toggle && item.checked) {
400
463
  li.dataset.checked = "1";
401
464
  }
402
- if (item.icon) li.appendChild(iconEl(item.icon, doc));
465
+ if (badged) {
466
+ const badge = doc.createElement("span");
467
+ badge.className = "vela-menu-badge";
468
+ if (item.icon) badge.appendChild(iconEl(item.icon, doc));
469
+ li.appendChild(badge);
470
+ } else if (item.icon) {
471
+ li.appendChild(iconEl(item.icon, doc));
472
+ } else if (iconic) {
473
+ li.appendChild(iconEl("", doc));
474
+ }
403
475
  const label = doc.createElement("span");
404
476
  label.className = "vela-menu-label";
405
477
  label.textContent = item.label;
@@ -443,9 +515,11 @@ var Surface = class _Surface {
443
515
  const sub = new _Surface(doc, {
444
516
  host: this.host,
445
517
  placement: "right-start",
518
+ opener: li,
446
519
  onSelect: this.onSelect,
447
520
  onFavorite: this.onFavorite,
448
521
  checkmarks: this.checkmarks,
522
+ iconBadges: this.iconBadges,
449
523
  id: `${this.mid}--${item.id}`
450
524
  });
451
525
  sub.setItems(item.submenu ?? []);
@@ -471,7 +545,8 @@ var Menu = class {
471
545
  id: opts.id,
472
546
  minWidth: opts.minWidth,
473
547
  onFavorite: opts.onFavorite,
474
- checkmarks: opts.checkmarks
548
+ checkmarks: opts.checkmarks,
549
+ iconBadges: opts.iconBadges
475
550
  });
476
551
  this.root.setItems(opts.items);
477
552
  }
@@ -575,6 +650,7 @@ var POPOVER_CSS = `
575
650
 
576
651
  // src/ui/components/popover/view.ts
577
652
  var open = null;
653
+ var leaving = /* @__PURE__ */ new Set();
578
654
  function closeOpenPopovers() {
579
655
  open?.hide();
580
656
  }
@@ -602,6 +678,8 @@ var Popover = class {
602
678
  this.shown = false;
603
679
  /** The pending removal of a fading-out shell; a show() that reuses the shell cancels it. */
604
680
  this.leaveTimer = null;
681
+ /** The shell's exit animation before it leaves the DOM; a show() that reuses the shell cancels it. */
682
+ this.exit = null;
605
683
  const doc = opts.trigger.ownerDocument;
606
684
  injectStyles(POPOVER_STYLE_ID, POPOVER_CSS, doc);
607
685
  this.trigger = opts.trigger;
@@ -638,6 +716,10 @@ var Popover = class {
638
716
  clearTimeout(this.leaveTimer);
639
717
  this.leaveTimer = null;
640
718
  }
719
+ this.exit?.cancel();
720
+ this.exit = null;
721
+ leaving.delete(this);
722
+ for (const p of [...leaving]) if (p.trigger === this.trigger) p.exit?.finish();
641
723
  ensureUIHost(this.el, this.inheritsTokens ? void 0 : this.theme);
642
724
  if (this.fadeMs > 0) {
643
725
  this.el.style.transition = `opacity ${this.fadeMs}ms ease`;
@@ -662,16 +744,21 @@ var Popover = class {
662
744
  this.hide();
663
745
  };
664
746
  const onReflow = () => this.place();
665
- setTimeout(() => document.addEventListener("pointerdown", onOutside, true), 0);
747
+ setTimeout(() => {
748
+ if (this.onOutside === onOutside) document.addEventListener("pointerdown", onOutside, true);
749
+ }, 0);
666
750
  document.addEventListener("keydown", onKey, true);
667
751
  window.addEventListener("resize", onReflow, true);
668
752
  document.addEventListener("scroll", onReflow, true);
669
753
  this.onOutside = onOutside;
670
754
  this.onKey = onKey;
671
755
  this.onReflow = onReflow;
756
+ announceSurface(this.el, true, "popover", this.trigger);
672
757
  }
673
758
  hide() {
674
759
  if (!this.shown) return;
760
+ this.shown = false;
761
+ announceSurface(this.el, false, "popover", this.trigger);
675
762
  if (this.onOutside) document.removeEventListener("pointerdown", this.onOutside, true);
676
763
  if (this.onKey) document.removeEventListener("keydown", this.onKey, true);
677
764
  if (this.onReflow) {
@@ -689,9 +776,13 @@ var Popover = class {
689
776
  this.el.remove();
690
777
  }, this.fadeMs);
691
778
  } else {
692
- this.el.remove();
779
+ this.exit = holdForExit(this.el, () => {
780
+ this.exit = null;
781
+ leaving.delete(this);
782
+ this.el.remove();
783
+ });
784
+ if (this.exit) leaving.add(this);
693
785
  }
694
- this.shown = false;
695
786
  if (open === this) open = null;
696
787
  this.ctrl.onClose?.();
697
788
  }
@@ -702,6 +793,7 @@ var Popover = class {
702
793
  }
703
794
  destroy() {
704
795
  this.hide();
796
+ this.exit?.finish();
705
797
  }
706
798
  reposition() {
707
799
  if (this.shown) this.place();
@@ -1377,6 +1469,11 @@ ${overlayScrollbarCss(".vela-dialog *")}
1377
1469
  `;
1378
1470
  var Dialog = class {
1379
1471
  constructor(opts = {}) {
1472
+ this.opener = null;
1473
+ this.wasOpen = false;
1474
+ /** The panel and scrim's exit animation after a close; a reopen cancels it. */
1475
+ this.exit = null;
1476
+ this.destroyed = false;
1380
1477
  const doc = (opts.host ?? document.body).ownerDocument;
1381
1478
  injectStyles(DIALOG_STYLE_ID, DIALOG_CSS, doc);
1382
1479
  const host = opts.host ?? doc.body;
@@ -1473,19 +1570,73 @@ var Dialog = class {
1473
1570
  const mid = String(this.ctrl.props.id);
1474
1571
  this.handle = runMachine(this.ctrl.machine, this.ctrl.props, (service) => {
1475
1572
  const api = this.ctrl.connect(service);
1573
+ const closing = this.wasOpen && !api.open;
1574
+ if (closing) this.announce(false);
1476
1575
  spreadProps(this.backdrop, api.getBackdropProps(), mid);
1477
1576
  spreadProps(this.positioner, api.getPositionerProps(), mid);
1478
1577
  spreadProps(this.panel, api.getContentProps(), mid);
1479
1578
  spreadProps(title, api.getTitleProps(), mid);
1480
1579
  spreadProps(close, api.getCloseTriggerProps(), mid);
1481
- this.backdrop.style.display = api.open ? "" : "none";
1482
- this.positioner.style.display = api.open ? "" : "none";
1580
+ if (api.open) {
1581
+ this.exit?.cancel();
1582
+ this.exit = null;
1583
+ this.setShown(true);
1584
+ } else if (closing) {
1585
+ this.holdExit();
1586
+ } else if (!this.exit) {
1587
+ this.setShown(false);
1588
+ }
1589
+ if (api.open && !this.wasOpen) this.announce(true);
1590
+ if (this.wasOpen && !api.open) this.restoreOpener();
1591
+ this.wasOpen = api.open;
1483
1592
  });
1484
1593
  }
1594
+ setShown(shown) {
1595
+ this.backdrop.style.display = shown ? "" : "none";
1596
+ this.positioner.style.display = shown ? "" : "none";
1597
+ }
1598
+ /** Keep the just-closed dialog up through its exit animation, then hide it — or
1599
+ * remove it, when it was destroyed meanwhile. `spreadProps` re-applies the close
1600
+ * props' `hidden` only when its value changes, so lifting it keeps the panel and
1601
+ * scrim up until the exit ends. The positioner spans the viewport: inert, it lets
1602
+ * clicks through to the page while the panel animates out. */
1603
+ holdExit() {
1604
+ const held = [this.panel, this.backdrop];
1605
+ for (const el of held) el.hidden = false;
1606
+ this.exit = holdForExit(
1607
+ held,
1608
+ () => {
1609
+ this.exit = null;
1610
+ if (this.destroyed) {
1611
+ this.detach();
1612
+ } else if (!this.open) {
1613
+ for (const el of held) el.hidden = true;
1614
+ this.setShown(false);
1615
+ }
1616
+ },
1617
+ { inert: [this.positioner] }
1618
+ );
1619
+ }
1620
+ detach() {
1621
+ this.backdrop.remove();
1622
+ this.positioner.remove();
1623
+ }
1624
+ /** Closing hands focus back to whatever opened it (Escape, the ✕, hide(), or a
1625
+ * teardown that outruns the machine's close notification). */
1626
+ restoreOpener() {
1627
+ const opener = this.opener;
1628
+ this.opener = null;
1629
+ if (opener?.isConnected) opener.focus({ preventScroll: true });
1630
+ }
1631
+ announce(open2) {
1632
+ const opener = this.opener === this.panel.ownerDocument.body ? null : this.opener;
1633
+ announceSurface(this.panel, open2, "dialog", opener);
1634
+ }
1485
1635
  get open() {
1486
1636
  return this.ctrl.connect(this.handle.service).open;
1487
1637
  }
1488
1638
  show() {
1639
+ this.opener = this.panel.ownerDocument.activeElement;
1489
1640
  this.ctrl.connect(this.handle.service).setOpen(true);
1490
1641
  }
1491
1642
  hide() {
@@ -1498,10 +1649,16 @@ var Dialog = class {
1498
1649
  return el?.closest(".vela-popover, .vela-menu") != null;
1499
1650
  }
1500
1651
  destroy() {
1652
+ if (this.wasOpen && !this.open) this.handle.flush();
1501
1653
  if (this.open) this.hide();
1502
1654
  this.handle.stop();
1503
- this.backdrop.remove();
1504
- this.positioner.remove();
1655
+ this.destroyed = true;
1656
+ if (this.wasOpen) {
1657
+ this.wasOpen = false;
1658
+ this.announce(false);
1659
+ }
1660
+ this.restoreOpener();
1661
+ if (!this.exit) this.detach();
1505
1662
  }
1506
1663
  };
1507
1664