myio-js-library 0.1.516 → 0.1.517

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.cjs CHANGED
@@ -1208,7 +1208,7 @@ module.exports = __toCommonJS(index_exports);
1208
1208
  // package.json
1209
1209
  var package_default = {
1210
1210
  name: "myio-js-library",
1211
- version: "0.1.516",
1211
+ version: "0.1.517",
1212
1212
  description: "A clean, standalone JS SDK for MYIO projects",
1213
1213
  license: "MIT",
1214
1214
  repository: "github:gh-myio/myio-js-library",
@@ -20627,6 +20627,35 @@ var PANEL_CSS2 = `
20627
20627
  background: #ffffff;
20628
20628
  color: #2F5848;
20629
20629
  }
20630
+
20631
+ /* \u2500\u2500 Accordion (opt-in via options.collapsible) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
20632
+ The header (.myio-hp, from HeaderPanelComponent) becomes clickable and an
20633
+ arrow is shown before its title. Collapsed hides the body (.myio-cgp__grid)
20634
+ and lets the panel shrink to header height. Arrow uses CSS escapes
20635
+ (ASCII only) to stay safe across strict CSS parsers (e.g. ThingsBoard). */
20636
+ .myio-cgp--collapsible > .myio-hp {
20637
+ cursor: pointer;
20638
+ user-select: none;
20639
+ }
20640
+ .myio-cgp--collapsible > .myio-hp .myio-hp__title::before {
20641
+ content: "\\25BE";
20642
+ display: inline-block;
20643
+ margin-right: 6px;
20644
+ font-size: 0.7em;
20645
+ opacity: 0.65;
20646
+ }
20647
+ .myio-cgp--collapsed > .myio-hp .myio-hp__title::before {
20648
+ content: "\\25B8";
20649
+ }
20650
+ .myio-cgp--collapsed > .myio-cgp__grid,
20651
+ .myio-cgp--collapsed > .myio-cgp__tabs-wrapper,
20652
+ .myio-cgp--collapsed > .myio-cgp__content {
20653
+ display: none !important;
20654
+ }
20655
+ .myio-cgp--collapsed {
20656
+ height: auto !important;
20657
+ flex: 0 0 auto !important;
20658
+ }
20630
20659
  `;
20631
20660
  function injectStyles5() {
20632
20661
  if (document.getElementById(CSS_ID3)) return;
@@ -20643,9 +20672,13 @@ var CardGridPanel = class {
20643
20672
  headerComponent = null;
20644
20673
  searchText = "";
20645
20674
  tabsContainer = null;
20675
+ collapsible = false;
20676
+ collapsed = false;
20677
+ headerClickBound = false;
20646
20678
  constructor(options) {
20647
20679
  injectStyles5();
20648
20680
  this.options = options;
20681
+ this.collapsible = !!options.collapsible;
20649
20682
  this.root = document.createElement("div");
20650
20683
  this.root.className = "myio-cgp";
20651
20684
  if (options.panelBackground) {
@@ -20795,6 +20828,46 @@ var CardGridPanel = class {
20795
20828
  this.root.appendChild(grid);
20796
20829
  this.renderTabs();
20797
20830
  this.renderGrid();
20831
+ this.applyCollapsibleState();
20832
+ }
20833
+ // ── Accordion / collapse (opt-in via options.collapsible) ──
20834
+ /** Enable/disable collapsible behavior at runtime. */
20835
+ setCollapsible(value) {
20836
+ this.collapsible = value;
20837
+ if (!value) this.collapsed = false;
20838
+ this.applyCollapsibleState();
20839
+ }
20840
+ /** Collapse or expand the panel body programmatically. */
20841
+ setCollapsed(value) {
20842
+ if (!this.collapsible) return;
20843
+ this.collapsed = value;
20844
+ this.root.classList.toggle("myio-cgp--collapsed", this.collapsed);
20845
+ }
20846
+ /** Toggle collapsed state. */
20847
+ toggleCollapsed() {
20848
+ this.setCollapsed(!this.collapsed);
20849
+ }
20850
+ /** Returns whether the panel is currently collapsed. */
20851
+ isCollapsed() {
20852
+ return this.collapsed;
20853
+ }
20854
+ /** Reflects collapsible/collapsed state on the DOM and wires the header click once. */
20855
+ applyCollapsibleState() {
20856
+ this.root.classList.toggle("myio-cgp--collapsible", this.collapsible);
20857
+ if (!this.collapsible) this.collapsed = false;
20858
+ this.root.classList.toggle("myio-cgp--collapsed", this.collapsible && this.collapsed);
20859
+ if (this.collapsible && !this.headerClickBound) {
20860
+ const header = this.headerComponent?.getElement();
20861
+ if (header) {
20862
+ this.headerClickBound = true;
20863
+ header.addEventListener("click", (e) => {
20864
+ if (!this.collapsible) return;
20865
+ const target = e.target;
20866
+ if (target.closest && target.closest('button, a, input, select, svg, [role="button"]')) return;
20867
+ this.toggleCollapsed();
20868
+ });
20869
+ }
20870
+ }
20798
20871
  }
20799
20872
  renderGrid() {
20800
20873
  const grid = this.root.querySelector(".myio-cgp__grid");
@@ -23768,7 +23841,7 @@ var CDN_RESOURCES = [
23768
23841
  {
23769
23842
  id: "daterangepicker-3.1.0",
23770
23843
  src: "https://cdn.jsdelivr.net/npm/daterangepicker@3.1.0/daterangepicker.min.js",
23771
- integrity: "sha384-IbJFThFkdkMvvxP0U8wOffxBHPYEJE65UtA/l25/jJQUt/hft6OdAuKLxGjtOVnL",
23844
+ integrity: "sha384-AH0fqcXzNOQHHyIMQOXM5qhbfCgavCM3rZSoGBBJJtS55if0BfFSI2dip/UVHCfA",
23772
23845
  crossorigin: "anonymous"
23773
23846
  }
23774
23847
  ];
@@ -79971,6 +80044,21 @@ function getWidgetStyles(theme, primaryColor, headerStyles) {
79971
80044
  flex-wrap: wrap;
79972
80045
  }
79973
80046
 
80047
+ /* Accordion (opt-in via config.collapsible): header clicavel; recolhido
80048
+ esconde o corpo + footer, deixando so a barra do header. */
80049
+ .myio-chart-widget--collapsible .myio-chart-widget-header {
80050
+ cursor: pointer;
80051
+ user-select: none;
80052
+ }
80053
+ .myio-chart-widget--collapsed .myio-chart-widget-body,
80054
+ .myio-chart-widget--collapsed .myio-chart-widget-footer {
80055
+ display: none !important;
80056
+ }
80057
+ .myio-chart-widget--collapsed {
80058
+ height: auto !important;
80059
+ flex: 0 0 auto !important;
80060
+ }
80061
+
79974
80062
  .myio-chart-widget-stat {
79975
80063
  display: flex;
79976
80064
  flex-direction: column;
@@ -80326,6 +80414,9 @@ function createConsumptionChartWidget(config) {
80326
80414
  let currentVizMode = config.defaultVizMode ?? "total";
80327
80415
  let currentPeriod = config.defaultPeriod ?? 7;
80328
80416
  let currentIdealRange = config.idealRange ?? null;
80417
+ let isCollapsible = !!config.collapsible;
80418
+ let isCollapsed = false;
80419
+ let collapseWired = false;
80329
80420
  let isLoading = false;
80330
80421
  let tempPeriod = currentPeriod;
80331
80422
  let tempChartType = currentChartType;
@@ -81086,6 +81177,26 @@ function createConsumptionChartWidget(config) {
81086
81177
  }
81087
81178
  });
81088
81179
  }
81180
+ function applyCollapseState() {
81181
+ const widget = document.getElementById(widgetId);
81182
+ if (!widget) return;
81183
+ widget.classList.toggle("myio-chart-widget--collapsible", isCollapsible);
81184
+ if (!isCollapsible) isCollapsed = false;
81185
+ widget.classList.toggle("myio-chart-widget--collapsed", isCollapsible && isCollapsed);
81186
+ if (isCollapsible && !collapseWired) {
81187
+ const header = widget.querySelector(".myio-chart-widget-header");
81188
+ if (header) {
81189
+ collapseWired = true;
81190
+ header.addEventListener("click", (e) => {
81191
+ if (!isCollapsible) return;
81192
+ const target = e.target;
81193
+ if (target.closest && target.closest('button, a, input, select, svg, [role="button"], [class*="-tab"]')) return;
81194
+ isCollapsed = !isCollapsed;
81195
+ applyCollapseState();
81196
+ });
81197
+ }
81198
+ }
81199
+ }
81089
81200
  const instance = {
81090
81201
  async render() {
81091
81202
  containerElement = document.getElementById(config.containerId);
@@ -81096,6 +81207,7 @@ function createConsumptionChartWidget(config) {
81096
81207
  injectStyles16();
81097
81208
  containerElement.innerHTML = renderHTML();
81098
81209
  setupListeners();
81210
+ applyCollapseState();
81099
81211
  setLoading(true);
81100
81212
  chartInstance = createConsumption7DaysChart({
81101
81213
  ...config,
@@ -81186,6 +81298,21 @@ function createConsumptionChartWidget(config) {
81186
81298
  exportCSV(filename) {
81187
81299
  chartInstance?.exportCSV(filename);
81188
81300
  },
81301
+ setCollapsible(value) {
81302
+ isCollapsible = value;
81303
+ if (!value) isCollapsed = false;
81304
+ applyCollapseState();
81305
+ },
81306
+ setCollapsed(value) {
81307
+ if (!isCollapsible) return;
81308
+ isCollapsed = value;
81309
+ applyCollapseState();
81310
+ },
81311
+ toggleCollapsed() {
81312
+ if (!isCollapsible) return;
81313
+ isCollapsed = !isCollapsed;
81314
+ applyCollapseState();
81315
+ },
81189
81316
  destroy() {
81190
81317
  chartInstance?.destroy();
81191
81318
  chartInstance = null;
@@ -136314,40 +136441,94 @@ function injectSidebarMenuStyles() {
136314
136441
  background: #6b7280;
136315
136442
  }
136316
136443
 
136317
- /* ===== Responsive ===== */
136318
- @media (max-width: 768px) {
136319
- .${SIDEBAR_MENU_CSS_PREFIX} {
136320
- position: fixed;
136321
- left: 0;
136322
- top: 0;
136323
- height: 100vh;
136324
- transform: translateX(-100%);
136325
- box-shadow: none;
136326
- z-index: 1000;
136327
- }
136444
+ /* ===== Mobile mode (JS-driven via .--mobile, NOT @media) =====
136445
+ The host measures its real element width and calls setMobileMode();
136446
+ in ThingsBoard the widget element width != viewport, so @media is
136447
+ unreliable. In mobile mode the sidebar becomes an off-canvas drawer
136448
+ opened by a persistent top bar (hamburger); the drawer keeps its
136449
+ footer/logout. */
136328
136450
 
136329
- .${SIDEBAR_MENU_CSS_PREFIX}.mobile-open {
136330
- transform: translateX(0);
136331
- box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);
136332
- }
136451
+ /* Persistent top bar with the hamburger \u2014 hidden until mobile */
136452
+ .${SIDEBAR_MENU_CSS_PREFIX}__mobile-topbar {
136453
+ display: none;
136454
+ }
136455
+ .${SIDEBAR_MENU_CSS_PREFIX}__mobile-topbar.is-mobile {
136456
+ display: flex;
136457
+ align-items: center;
136458
+ gap: 12px;
136459
+ width: 100%;
136460
+ height: 56px;
136461
+ padding: 0 12px;
136462
+ box-sizing: border-box;
136463
+ background: linear-gradient(135deg, var(--sidebar-primary) 0%, var(--sidebar-primary-light) 100%);
136464
+ color: #ffffff;
136465
+ z-index: 900;
136466
+ }
136467
+ .${SIDEBAR_MENU_CSS_PREFIX}__mobile-hamburger {
136468
+ display: inline-flex;
136469
+ align-items: center;
136470
+ justify-content: center;
136471
+ width: 40px;
136472
+ height: 40px;
136473
+ padding: 0;
136474
+ border: none;
136475
+ border-radius: 8px;
136476
+ background: rgba(255, 255, 255, 0.14);
136477
+ color: #ffffff;
136478
+ cursor: pointer;
136479
+ transition: background 0.2s ease;
136480
+ }
136481
+ .${SIDEBAR_MENU_CSS_PREFIX}__mobile-hamburger:hover {
136482
+ background: rgba(255, 255, 255, 0.26);
136483
+ }
136484
+ .${SIDEBAR_MENU_CSS_PREFIX}__mobile-hamburger svg {
136485
+ width: 22px;
136486
+ height: 22px;
136487
+ }
136488
+ .${SIDEBAR_MENU_CSS_PREFIX}__mobile-topbar-title {
136489
+ font-size: 15px;
136490
+ font-weight: 700;
136491
+ letter-spacing: 0.2px;
136492
+ }
136333
136493
 
136334
- .${SIDEBAR_MENU_CSS_PREFIX}__backdrop {
136335
- position: fixed;
136336
- top: 0;
136337
- left: 0;
136338
- right: 0;
136339
- bottom: 0;
136340
- background: rgba(0, 0, 0, 0.5);
136341
- opacity: 0;
136342
- visibility: hidden;
136343
- transition: opacity 0.3s ease, visibility 0.3s ease;
136344
- z-index: 999;
136345
- }
136494
+ /* Sidebar becomes an off-canvas drawer */
136495
+ .${SIDEBAR_MENU_CSS_PREFIX}--mobile {
136496
+ position: fixed;
136497
+ left: 0;
136498
+ top: 0;
136499
+ height: 100vh;
136500
+ width: var(--sidebar-expanded-width);
136501
+ max-width: 86vw;
136502
+ transform: translateX(-100%);
136503
+ box-shadow: none;
136504
+ z-index: 1000;
136505
+ transition: transform var(--sidebar-transition);
136506
+ }
136507
+ .${SIDEBAR_MENU_CSS_PREFIX}--mobile.mobile-open {
136508
+ transform: translateX(0);
136509
+ box-shadow: 4px 0 20px rgba(0, 0, 0, 0.15);
136510
+ }
136346
136511
 
136347
- .${SIDEBAR_MENU_CSS_PREFIX}.mobile-open + .${SIDEBAR_MENU_CSS_PREFIX}__backdrop {
136348
- opacity: 1;
136349
- visibility: visible;
136350
- }
136512
+ /* Backdrop \u2014 only present/active in mobile mode */
136513
+ .${SIDEBAR_MENU_CSS_PREFIX}__backdrop {
136514
+ display: none;
136515
+ position: fixed;
136516
+ top: 0;
136517
+ left: 0;
136518
+ right: 0;
136519
+ bottom: 0;
136520
+ background: rgba(0, 0, 0, 0.5);
136521
+ opacity: 0;
136522
+ visibility: hidden;
136523
+ transition: opacity 0.3s ease, visibility 0.3s ease;
136524
+ z-index: 999;
136525
+ }
136526
+ .${SIDEBAR_MENU_CSS_PREFIX}__backdrop.is-mobile {
136527
+ display: block;
136528
+ }
136529
+ .${SIDEBAR_MENU_CSS_PREFIX}__backdrop.is-open {
136530
+ opacity: 1;
136531
+ visibility: visible;
136351
136532
  }
136352
136533
  `;
136353
136534
  document.head.appendChild(style);
@@ -136424,8 +136605,15 @@ var SidebarMenuView = class {
136424
136605
  activeItemId = null;
136425
136606
  collapsedSections = /* @__PURE__ */ new Set();
136426
136607
  tooltip = null;
136608
+ container;
136609
+ // Mobile mode (JS-driven; NOT @media — the host measures its real width)
136610
+ mobile = false;
136611
+ drawerOpen = false;
136612
+ mobileTopbar = null;
136613
+ backdrop = null;
136427
136614
  constructor(container, config) {
136428
136615
  injectSidebarMenuStyles();
136616
+ this.container = container;
136429
136617
  this.config = { ...DEFAULT_SIDEBAR_CONFIG, ...config };
136430
136618
  this.state = this.config.initialState || "expanded";
136431
136619
  this.themeMode = this.config.themeMode || "light";
@@ -136666,7 +136854,11 @@ var SidebarMenuView = class {
136666
136854
  const target = e.target;
136667
136855
  const action = target.closest("[data-action]")?.getAttribute("data-action");
136668
136856
  if (action === "toggle") {
136669
- this.toggle();
136857
+ if (this.mobile) {
136858
+ this.closeDrawer();
136859
+ } else {
136860
+ this.toggle();
136861
+ }
136670
136862
  } else if (action === "theme-toggle") {
136671
136863
  this.handleThemeToggle();
136672
136864
  } else if (action === "logout") {
@@ -136686,6 +136878,7 @@ var SidebarMenuView = class {
136686
136878
  const sectionId = itemEl.getAttribute("data-section-id");
136687
136879
  if (itemId && sectionId) {
136688
136880
  this.handleItemClick(itemId, sectionId);
136881
+ if (this.mobile) this.closeDrawer();
136689
136882
  }
136690
136883
  }
136691
136884
  }
@@ -136834,6 +137027,71 @@ var SidebarMenuView = class {
136834
137027
  getState() {
136835
137028
  return this.state;
136836
137029
  }
137030
+ /**
137031
+ * Toggle mobile mode. Driven by the host (it measures its real width),
137032
+ * NOT by @media — the widget element width != viewport in ThingsBoard.
137033
+ * In mobile mode the sidebar becomes an off-canvas drawer and a persistent
137034
+ * top bar (hamburger) is shown to open it; the drawer keeps its footer/logout.
137035
+ */
137036
+ setMobileMode(on) {
137037
+ if (this.mobile === on) return;
137038
+ this.mobile = on;
137039
+ if (on) {
137040
+ this.ensureMobileChrome();
137041
+ this.root.classList.add(`${SIDEBAR_MENU_CSS_PREFIX}--mobile`);
137042
+ this.root.classList.remove("collapsed");
137043
+ if (this.mobileTopbar) this.mobileTopbar.classList.add("is-mobile");
137044
+ if (this.backdrop) this.backdrop.classList.add("is-mobile");
137045
+ this.closeDrawer();
137046
+ } else {
137047
+ this.closeDrawer();
137048
+ this.root.classList.remove(`${SIDEBAR_MENU_CSS_PREFIX}--mobile`);
137049
+ if (this.mobileTopbar) this.mobileTopbar.classList.remove("is-mobile");
137050
+ if (this.backdrop) this.backdrop.classList.remove("is-mobile");
137051
+ if (this.state === "collapsed") this.root.classList.add("collapsed");
137052
+ }
137053
+ }
137054
+ /** Lazily create the persistent mobile top bar (hamburger) + backdrop. */
137055
+ ensureMobileChrome() {
137056
+ if (!this.mobileTopbar) {
137057
+ const header = this.config.header || {};
137058
+ const title = header.title || "Menu";
137059
+ const bar = document.createElement("div");
137060
+ bar.className = `${SIDEBAR_MENU_CSS_PREFIX}__mobile-topbar`;
137061
+ bar.innerHTML = `
137062
+ <button
137063
+ class="${SIDEBAR_MENU_CSS_PREFIX}__mobile-hamburger"
137064
+ data-action="mobile-open"
137065
+ aria-label="Abrir menu"
137066
+ >${SIDEBAR_ICONS.menu}</button>
137067
+ <span class="${SIDEBAR_MENU_CSS_PREFIX}__mobile-topbar-title">${title}</span>
137068
+ `;
137069
+ bar.querySelector('[data-action="mobile-open"]')?.addEventListener("click", () => this.openDrawer());
137070
+ this.container.insertBefore(bar, this.root);
137071
+ this.mobileTopbar = bar;
137072
+ }
137073
+ if (!this.backdrop) {
137074
+ const bd = document.createElement("div");
137075
+ bd.className = `${SIDEBAR_MENU_CSS_PREFIX}__backdrop`;
137076
+ bd.addEventListener("click", () => this.closeDrawer());
137077
+ this.container.insertBefore(bd, this.root.nextSibling);
137078
+ this.backdrop = bd;
137079
+ }
137080
+ }
137081
+ openDrawer() {
137082
+ if (!this.mobile) return;
137083
+ this.drawerOpen = true;
137084
+ this.root.classList.add("mobile-open");
137085
+ this.backdrop?.classList.add("is-open");
137086
+ }
137087
+ closeDrawer() {
137088
+ this.drawerOpen = false;
137089
+ this.root.classList.remove("mobile-open");
137090
+ this.backdrop?.classList.remove("is-open");
137091
+ }
137092
+ isMobile() {
137093
+ return this.mobile;
137094
+ }
136837
137095
  setThemeMode(mode) {
136838
137096
  this.themeMode = mode;
136839
137097
  this.root.classList.remove("light", "dark");
@@ -136959,6 +137217,19 @@ var SidebarMenuController = class {
136959
137217
  toggle() {
136960
137218
  this.view.toggle();
136961
137219
  }
137220
+ /** Enable/disable mobile mode (hamburger top bar + off-canvas drawer). */
137221
+ setMobileMode(on) {
137222
+ this.view.setMobileMode(on);
137223
+ }
137224
+ openDrawer() {
137225
+ this.view.openDrawer();
137226
+ }
137227
+ closeDrawer() {
137228
+ this.view.closeDrawer();
137229
+ }
137230
+ isMobile() {
137231
+ return this.view.isMobile();
137232
+ }
136962
137233
  getState() {
136963
137234
  return this.view.getState();
136964
137235
  }
package/dist/index.d.cts CHANGED
@@ -3177,6 +3177,13 @@ interface CardGridPanelOptions {
3177
3177
  tabs?: TabItem[];
3178
3178
  /** Callback when tab selection changes (receives the newly selected tab) */
3179
3179
  onTabChange?: (tab: TabItem) => void;
3180
+ /**
3181
+ * When true, the panel becomes an accordion item: clicking the header
3182
+ * (anywhere except its buttons) collapses/expands the body. A small arrow
3183
+ * indicator is shown before the title. Default: false (fully backward-compatible).
3184
+ * Can be toggled at runtime via setCollapsible().
3185
+ */
3186
+ collapsible?: boolean;
3180
3187
  }
3181
3188
  declare class CardGridPanel {
3182
3189
  private root;
@@ -3184,6 +3191,9 @@ declare class CardGridPanel {
3184
3191
  private headerComponent;
3185
3192
  private searchText;
3186
3193
  private tabsContainer;
3194
+ private collapsible;
3195
+ private collapsed;
3196
+ private headerClickBound;
3187
3197
  constructor(options: CardGridPanelOptions);
3188
3198
  getElement(): HTMLElement;
3189
3199
  /** Replace items and re-render grid */
@@ -3210,6 +3220,16 @@ declare class CardGridPanel {
3210
3220
  setCardCustomStyle(style: CardGridCustomStyle | undefined): void;
3211
3221
  destroy(): void;
3212
3222
  private render;
3223
+ /** Enable/disable collapsible behavior at runtime. */
3224
+ setCollapsible(value: boolean): void;
3225
+ /** Collapse or expand the panel body programmatically. */
3226
+ setCollapsed(value: boolean): void;
3227
+ /** Toggle collapsed state. */
3228
+ toggleCollapsed(): void;
3229
+ /** Returns whether the panel is currently collapsed. */
3230
+ isCollapsed(): boolean;
3231
+ /** Reflects collapsible/collapsed state on the DOM and wires the header click once. */
3232
+ private applyCollapsibleState;
3213
3233
  private renderGrid;
3214
3234
  private renderTabs;
3215
3235
  }
@@ -9518,6 +9538,12 @@ interface ConsumptionWidgetConfig extends Omit<Consumption7DaysConfig, 'containe
9518
9538
  onMaximizeClick?: () => void;
9519
9539
  /** Custom CSS class for the widget container */
9520
9540
  className?: string;
9541
+ /**
9542
+ * When true, the widget becomes an accordion item: clicking the header
9543
+ * (except its buttons/tabs) collapses/expands the chart body, leaving only
9544
+ * the header bar. Default: false. Toggle at runtime via setCollapsible().
9545
+ */
9546
+ collapsible?: boolean;
9521
9547
  /**
9522
9548
  * Custom header styles for compact layouts
9523
9549
  * @example { padding: '8px 12px', fontSize: '12px', titleFontSize: '12px', tabPadding: '4px 10px', tabFontSize: '11px' }
@@ -9566,6 +9592,12 @@ interface ConsumptionWidgetInstance {
9566
9592
  };
9567
9593
  /** Exports data to CSV */
9568
9594
  exportCSV: (filename?: string) => void;
9595
+ /** Enable/disable collapsible (accordion) behavior at runtime. */
9596
+ setCollapsible: (value: boolean) => void;
9597
+ /** Collapse/expand the chart body, keeping only the header bar. */
9598
+ setCollapsed: (value: boolean) => void;
9599
+ /** Toggle collapsed state. */
9600
+ toggleCollapsed: () => void;
9569
9601
  /** Destroys the widget */
9570
9602
  destroy: () => void;
9571
9603
  }
@@ -18445,6 +18477,11 @@ declare class SidebarMenuController implements SidebarMenuInstance {
18445
18477
  expand(): void;
18446
18478
  collapse(): void;
18447
18479
  toggle(): void;
18480
+ /** Enable/disable mobile mode (hamburger top bar + off-canvas drawer). */
18481
+ setMobileMode(on: boolean): void;
18482
+ openDrawer(): void;
18483
+ closeDrawer(): void;
18484
+ isMobile(): boolean;
18448
18485
  getState(): SidebarState;
18449
18486
  setThemeMode(mode: SidebarThemeMode): void;
18450
18487
  updateSections(sections: SidebarMenuSection[]): void;
@@ -18473,6 +18510,11 @@ declare class SidebarMenuView {
18473
18510
  private activeItemId;
18474
18511
  private collapsedSections;
18475
18512
  private tooltip;
18513
+ private container;
18514
+ private mobile;
18515
+ private drawerOpen;
18516
+ private mobileTopbar;
18517
+ private backdrop;
18476
18518
  constructor(container: HTMLElement, config: SidebarMenuConfig);
18477
18519
  private createSidebar;
18478
18520
  private renderHeader;
@@ -18493,6 +18535,18 @@ declare class SidebarMenuView {
18493
18535
  collapse(): void;
18494
18536
  toggle(): void;
18495
18537
  getState(): SidebarState;
18538
+ /**
18539
+ * Toggle mobile mode. Driven by the host (it measures its real width),
18540
+ * NOT by @media — the widget element width != viewport in ThingsBoard.
18541
+ * In mobile mode the sidebar becomes an off-canvas drawer and a persistent
18542
+ * top bar (hamburger) is shown to open it; the drawer keeps its footer/logout.
18543
+ */
18544
+ setMobileMode(on: boolean): void;
18545
+ /** Lazily create the persistent mobile top bar (hamburger) + backdrop. */
18546
+ private ensureMobileChrome;
18547
+ openDrawer(): void;
18548
+ closeDrawer(): void;
18549
+ isMobile(): boolean;
18496
18550
  setThemeMode(mode: SidebarThemeMode): void;
18497
18551
  updateSections(sections: SidebarMenuSection[]): void;
18498
18552
  updateItemBadge(itemId: string, badge: number | string | null): void;