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 +305 -34
- package/dist/index.d.cts +54 -0
- package/dist/index.js +305 -34
- package/dist/myio-js-library.umd.js +305 -34
- package/dist/myio-js-library.umd.min.js +1 -1
- package/package.json +1 -1
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.
|
|
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-
|
|
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
|
-
/* =====
|
|
136318
|
-
|
|
136319
|
-
|
|
136320
|
-
|
|
136321
|
-
|
|
136322
|
-
|
|
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
|
-
|
|
136330
|
-
|
|
136331
|
-
|
|
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
|
-
|
|
136335
|
-
|
|
136336
|
-
|
|
136337
|
-
|
|
136338
|
-
|
|
136339
|
-
|
|
136340
|
-
|
|
136341
|
-
|
|
136342
|
-
|
|
136343
|
-
|
|
136344
|
-
|
|
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
|
-
|
|
136348
|
-
|
|
136349
|
-
|
|
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.
|
|
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;
|