acttrader-charts 1.3.0-beta.30 → 1.3.0-beta.31

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/README.md CHANGED
@@ -1423,6 +1423,16 @@ chart.on('snapshot', ({ dataUrl, action }) => {
1423
1423
  });
1424
1424
  ```
1425
1425
 
1426
+ ### On mobile
1427
+
1428
+ The `'mobile'` header shows the same Layout button when `enableMultipleLayouts: true`, and
1429
+ opens the same preset popover. For apps that draw their own header, the native-UI catalog
1430
+ (`catalog` event / `getCatalog`) carries a `layouts` section — every preset above with its
1431
+ `id`, `label`, `count`, `cols`, `rows`, `areas` and `icon`, plus the five sync toggles with
1432
+ their defaults — and the `layouts` toolbar entry. The app sends `setLayoutPreset(presetId)`,
1433
+ receives `layoutChange`, and mounts that many chart views itself; see the Android and iOS
1434
+ READMEs.
1435
+
1426
1436
  ### Seeding & restoring the popover's sync toggles
1427
1437
 
1428
1438
  The layout popover's five sync toggles (`symbol` / `interval` / `crosshair` / `time` / `dateRange`) default to `DEFAULT_LAYOUT_SYNC`. To open the popover in a different state — e.g. restoring a user's saved preference — pass a **partial** `layoutSync` at construction (omitted keys keep their `DEFAULT_LAYOUT_SYNC` value):
package/dist/index.cjs CHANGED
@@ -8486,9 +8486,11 @@ var IC_SETTINGS2 = (sz = 16) => lucide4(
8486
8486
  1.75
8487
8487
  );
8488
8488
  var MobileHeader = class {
8489
- constructor(onTimeframeChange, toolsController, onAskAiClick, onSettingsClick, onSeriesChange, currentTf, currentSeries, theme, fontFamily, enabledGates = [], showCrosshairBtn = false, initialCrosshairEnabled = true, onCrosshairToggle = null, onReplayClick = null) {
8489
+ constructor(onTimeframeChange, toolsController, onAskAiClick, onSettingsClick, onSeriesChange, currentTf, currentSeries, theme, fontFamily, enabledGates = [], showCrosshairBtn = false, initialCrosshairEnabled = true, onCrosshairToggle = null, onReplayClick = null, onLayoutClick = null) {
8490
8490
  this.replayBtn = null;
8491
8491
  this.replayActive = false;
8492
+ this.layoutBtn = null;
8493
+ this.layoutActive = false;
8492
8494
  this.toolsBtn = null;
8493
8495
  this.tfBtns = /* @__PURE__ */ new Map();
8494
8496
  this.toolsActive = false;
@@ -8504,6 +8506,7 @@ var MobileHeader = class {
8504
8506
  this.onAskAiClick = onAskAiClick;
8505
8507
  this.onSettingsClick = onSettingsClick;
8506
8508
  this.onReplayClick = onReplayClick;
8509
+ this.onLayoutClick = onLayoutClick;
8507
8510
  this.onSeriesChange = onSeriesChange;
8508
8511
  this.currentTf = currentTf;
8509
8512
  this.currentSeries = currentSeries;
@@ -8718,6 +8721,34 @@ var MobileHeader = class {
8718
8721
  this.replayBtn = btn;
8719
8722
  this.el.appendChild(btn);
8720
8723
  }
8724
+ if (this.onLayoutClick) {
8725
+ const btn = document.createElement("button");
8726
+ btn.setAttribute("data-testid", "m-layout-btn");
8727
+ btn.title = "Layout";
8728
+ btn.setAttribute("aria-label", "Layout");
8729
+ btn.innerHTML = ICON_LAYOUT;
8730
+ Object.assign(btn.style, {
8731
+ display: "flex",
8732
+ alignItems: "center",
8733
+ justifyContent: "center",
8734
+ padding: "6px",
8735
+ borderRadius: "4px",
8736
+ border: "none",
8737
+ whiteSpace: "nowrap",
8738
+ flexShrink: "0",
8739
+ cursor: "pointer",
8740
+ outline: "none",
8741
+ background: "transparent",
8742
+ color: this.theme.axisText,
8743
+ transition: "color 0.15s, background 0.15s"
8744
+ });
8745
+ btn.addEventListener("click", (e) => {
8746
+ e.stopPropagation();
8747
+ this.onLayoutClick?.();
8748
+ });
8749
+ this.layoutBtn = btn;
8750
+ this.el.appendChild(btn);
8751
+ }
8721
8752
  if (this.onSettingsClick) {
8722
8753
  const btn = document.createElement("button");
8723
8754
  btn.setAttribute("data-testid", "m-chart-settings-btn");
@@ -8941,6 +8972,7 @@ var MobileHeader = class {
8941
8972
  setTheme(theme) {
8942
8973
  this.theme = theme;
8943
8974
  if (this.replayBtn) this.replayBtn.style.color = this.replayActive ? theme.ui.accent : theme.axisText;
8975
+ if (this.layoutBtn) this.layoutBtn.style.color = this.layoutActive ? theme.ui.accent : theme.axisText;
8944
8976
  this.build();
8945
8977
  this.setDrawingsBtnActive(this.toolsActive);
8946
8978
  this.sheet?.setTheme(theme);
@@ -8993,12 +9025,18 @@ var MobileHeader = class {
8993
9025
  }
8994
9026
  setTfcActive(_enabled) {
8995
9027
  }
8996
- setLayoutPresetIcon(_svgHtml, _active) {
9028
+ /** Shows the picked preset's glyph on the Layout button, tinted while a grid is active. */
9029
+ setLayoutPresetIcon(svgHtml, active) {
9030
+ if (!this.layoutBtn) return;
9031
+ this.layoutBtn.innerHTML = svgHtml;
9032
+ this.setLayoutActive(active === true);
8997
9033
  }
8998
- setLayoutActive(_active) {
9034
+ setLayoutActive(active) {
9035
+ this.layoutActive = active;
9036
+ if (this.layoutBtn) this.layoutBtn.style.color = active ? this.theme.ui.accent : this.theme.axisText;
8999
9037
  }
9000
9038
  getLayoutBtnEl() {
9001
- return null;
9039
+ return this.layoutBtn;
9002
9040
  }
9003
9041
  getSnapshotBtnEl() {
9004
9042
  return null;
@@ -9369,10 +9407,11 @@ var LayoutPopover = class {
9369
9407
  const wasVisible = this.isVisible;
9370
9408
  const rect = anchor.getBoundingClientRect();
9371
9409
  const top = rect.bottom + 6;
9372
- const right = Math.max(8, window.innerWidth - rect.right);
9373
9410
  this.el.style.top = `${top}px`;
9374
- this.el.style.right = `${right}px`;
9375
9411
  this.el.style.display = "block";
9412
+ const wanted = Math.max(8, window.innerWidth - rect.right);
9413
+ const maxRight = Math.max(8, window.innerWidth - this.el.offsetWidth - 8);
9414
+ this.el.style.right = `${Math.min(wanted, maxRight)}px`;
9376
9415
  if (!wasVisible) this.onVisibilityChange?.();
9377
9416
  }
9378
9417
  hide() {
@@ -38670,7 +38709,8 @@ var _ChartEngine = class _ChartEngine {
38670
38709
  (enabled) => {
38671
38710
  this.setCrosshairEnabled(enabled);
38672
38711
  },
38673
- this.replayEnabled ? () => this.toggleReplay() : null
38712
+ this.replayEnabled ? () => this.toggleReplay() : null,
38713
+ showLayoutBtn ? onLayoutBtnClick : null
38674
38714
  );
38675
38715
  this.wrapper.appendChild(this.mobileHeader.el);
38676
38716
  } else if (useCompactHeader) {
@@ -42939,7 +42979,7 @@ var _ChartEngine = class _ChartEngine {
42939
42979
  // ── Multi-layout & snapshot popover wiring ────────────────────────────────
42940
42980
  openLayoutPopover() {
42941
42981
  if (!this.layoutPopover) return;
42942
- const anchor = this.advancedToolbar?.getLayoutBtnEl() ?? this.topBar?.getLayoutBtnEl();
42982
+ const anchor = this.advancedToolbar?.getLayoutBtnEl() ?? this.topBar?.getLayoutBtnEl() ?? this.mobileHeader?.getLayoutBtnEl();
42943
42983
  if (!anchor) return;
42944
42984
  if (this.layoutPopover.isVisible) {
42945
42985
  this.layoutPopover.hide();