myio-js-library 0.1.559 → 0.1.560

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
@@ -908,7 +908,7 @@ module.exports = __toCommonJS(src_exports);
908
908
  // package.json
909
909
  var package_default = {
910
910
  name: "myio-js-library",
911
- version: "0.1.559",
911
+ version: "0.1.560",
912
912
  description: "A clean, standalone JS SDK for MYIO projects",
913
913
  license: "MIT",
914
914
  repository: "github:gh-myio/myio-js-library",
@@ -53165,6 +53165,14 @@ var AlarmApiClient = class {
53165
53165
  return raw?.data ?? raw;
53166
53166
  }
53167
53167
  // -----------------------------------------------------------------------
53168
+ // Rule name (GCDR GET /rules/:id) — usado p/ alarmes cujo title veio como o UUID da regra
53169
+ // -----------------------------------------------------------------------
53170
+ async getRuleName(rulesApiBase, ruleId) {
53171
+ const raw = await this.request(`${rulesApiBase}/rules/${encodeURIComponent(ruleId)}`);
53172
+ const name = raw?.data?.name ?? raw?.name;
53173
+ return typeof name === "string" && name.trim() ? name.trim() : null;
53174
+ }
53175
+ // -----------------------------------------------------------------------
53168
53176
  // Alarm list (GET /alarms)
53169
53177
  // -----------------------------------------------------------------------
53170
53178
  async getAlarms(params = {}) {
@@ -53367,6 +53375,14 @@ function mapApiTopOffenders(items, deviceNameMap) {
53367
53375
  // computed by caller if needed
53368
53376
  }));
53369
53377
  }
53378
+ var RULE_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
53379
+ function resolveRulesApiBase(explicit, alarmsBase) {
53380
+ let base = explicit || globalThis?.MyIOUtils?.gcdrApiBaseUrl || "";
53381
+ if (!base && alarmsBase.includes("alarms-api")) base = alarmsBase.replace("alarms-api", "gcdr-api");
53382
+ if (!base) return "";
53383
+ base = String(base).replace(/\/+$/, "").replace(/\/api\/v1$/, "");
53384
+ return `${base}/api/v1`;
53385
+ }
53370
53386
  var AlarmServiceClass = class {
53371
53387
  client = new AlarmApiClient();
53372
53388
  cacheTtlMs = 3 * 60 * 1e3;
@@ -53375,6 +53391,10 @@ var AlarmServiceClass = class {
53375
53391
  alarmsCache = /* @__PURE__ */ new Map();
53376
53392
  statsCache = /* @__PURE__ */ new Map();
53377
53393
  trendCache = /* @__PURE__ */ new Map();
53394
+ // ruleId → nome da regra (null = não encontrada); sobrevive ao clearCache — nomes de regra quase não mudam
53395
+ ruleNameCache = /* @__PURE__ */ new Map();
53396
+ alarmsBaseUrl = "";
53397
+ rulesBaseUrl = "";
53378
53398
  // -----------------------------------------------------------------------
53379
53399
  // Availability (MTBF / MTTR per device)
53380
53400
  // -----------------------------------------------------------------------
@@ -53414,8 +53434,13 @@ var AlarmServiceClass = class {
53414
53434
  let summary;
53415
53435
  let totalPages = 1;
53416
53436
  let page = 1;
53437
+ const titleByRuleId = /* @__PURE__ */ new Map();
53417
53438
  while (page <= totalPages) {
53418
53439
  const response = await this.client.getAlarms({ ...params, page });
53440
+ for (const a of response.data || []) {
53441
+ const rid = a.metadata?.ruleId;
53442
+ if (rid && a.title && !RULE_ID_RE.test(a.title)) titleByRuleId.set(String(rid), a.title);
53443
+ }
53419
53444
  const pageData = (response.data || []).map((a) => mapApiAlarm(a, customerMap));
53420
53445
  allData = allData.concat(pageData);
53421
53446
  if (page === 1) {
@@ -53424,6 +53449,7 @@ var AlarmServiceClass = class {
53424
53449
  }
53425
53450
  page++;
53426
53451
  }
53452
+ await this.resolveRuleIdTitles(allData, titleByRuleId);
53427
53453
  const result = { data: allData, summary };
53428
53454
  this.alarmsCache.set(cacheKey, { data: result, timestamp: Date.now() });
53429
53455
  return result;
@@ -53534,11 +53560,47 @@ var AlarmServiceClass = class {
53534
53560
  * Set the Alarms API base URL (e.g. from MAIN_VIEW orchestrator settings).
53535
53561
  * Clears the cache so subsequent calls use the new endpoint.
53536
53562
  */
53537
- configure(baseUrl, cacheTtlMs, apiKey) {
53563
+ configure(baseUrl, cacheTtlMs, apiKey, rulesBaseUrl) {
53538
53564
  this.client.configure(baseUrl ?? "", apiKey);
53565
+ if (baseUrl) this.alarmsBaseUrl = baseUrl;
53566
+ if (rulesBaseUrl) this.rulesBaseUrl = rulesBaseUrl;
53539
53567
  if (cacheTtlMs && cacheTtlMs > 0) this.cacheTtlMs = cacheTtlMs;
53540
53568
  this.clearCache();
53541
53569
  }
53570
+ /**
53571
+ * Alarmes com title = UUID da regra recebem o nome legível: primeiro o título de
53572
+ * outro alarme da mesma regra; senão o nome da regra no GCDR (GET /rules/:id, cacheado).
53573
+ * Falha de lookup mantém o UUID (nunca quebra a listagem).
53574
+ */
53575
+ async resolveRuleIdTitles(alarms, titleByRuleId) {
53576
+ const pending = alarms.filter((a) => a.title && RULE_ID_RE.test(a.title));
53577
+ if (!pending.length) return;
53578
+ const rulesBase = resolveRulesApiBase(this.rulesBaseUrl, this.alarmsBaseUrl);
53579
+ const toFetch = [
53580
+ ...new Set(pending.map((a) => a.title).filter((rid) => !titleByRuleId.has(rid) && !this.ruleNameCache.has(rid)))
53581
+ ];
53582
+ if (rulesBase && toFetch.length) {
53583
+ const CONCURRENCY = 6;
53584
+ for (let i = 0; i < toFetch.length; i += CONCURRENCY) {
53585
+ await Promise.all(
53586
+ toFetch.slice(i, i + CONCURRENCY).map(async (rid) => {
53587
+ try {
53588
+ this.ruleNameCache.set(rid, await this.client.getRuleName(rulesBase, rid));
53589
+ } catch {
53590
+ this.ruleNameCache.set(rid, null);
53591
+ }
53592
+ })
53593
+ );
53594
+ }
53595
+ }
53596
+ for (const alarm of pending) {
53597
+ const rid = alarm.title;
53598
+ const name = titleByRuleId.get(rid) || this.ruleNameCache.get(rid);
53599
+ if (!name) continue;
53600
+ alarm.title = name;
53601
+ if (alarm.tags?.alarmType === rid) alarm.tags.alarmType = name;
53602
+ }
53603
+ }
53542
53604
  // -----------------------------------------------------------------------
53543
53605
  // Cache management
53544
53606
  // -----------------------------------------------------------------------
@@ -55150,6 +55212,14 @@ var ALARMS_NOTIFICATIONS_PANEL_STYLES = `
55150
55212
  animation: afmSlideUp 0.2s ease;
55151
55213
  }
55152
55214
 
55215
+ .afm-modal.afm-modal--max {
55216
+ width: 100vw;
55217
+ max-width: 100vw;
55218
+ height: 100vh;
55219
+ max-height: 100vh;
55220
+ border-radius: 0;
55221
+ }
55222
+
55153
55223
  @keyframes afmSlideUp {
55154
55224
  from { transform: translateY(16px); opacity: 0.6; }
55155
55225
  to { transform: translateY(0); opacity: 1; }
@@ -58767,7 +58837,7 @@ var ALARMS_NOTIFICATIONS_PANEL_STYLES = `
58767
58837
  background: #fff;
58768
58838
  border-radius: 14px;
58769
58839
  width: 92%;
58770
- max-width: 380px;
58840
+ max-width: 480px; /* espa\xE7o p/ o footer premium (holding \xB7 hora \xB7 vers\xE3o) */
58771
58841
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
58772
58842
  transform: translateY(-12px) scale(0.97);
58773
58843
  transition: transform 0.2s ease;
@@ -59251,7 +59321,7 @@ var ALARMS_NOTIFICATIONS_PANEL_STYLES = `
59251
59321
  background: #fff;
59252
59322
  border-radius: 14px;
59253
59323
  width: 92%;
59254
- max-width: 360px;
59324
+ max-width: 480px; /* espa\xE7o p/ o footer premium (holding \xB7 hora \xB7 vers\xE3o) */
59255
59325
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.25);
59256
59326
  transform: translateY(-10px) scale(0.97);
59257
59327
  transition: transform 0.2s ease;
@@ -69612,8 +69682,9 @@ var WelcomeModalView = class _WelcomeModalView {
69612
69682
  align-items: center;
69613
69683
  justify-content: center;
69614
69684
  padding: 12px 20px;
69615
- background: #5B2EBC;
69616
- border-top: 1px solid rgba(122, 47, 247, 0.3);
69685
+ /* paleta do tema do dashboard (createMyIOTheme \u2192 --myio-brand-700); roxo MYIO sem tema */
69686
+ background: var(--myio-brand-700, #5B2EBC);
69687
+ border-top: 1px solid color-mix(in srgb, var(--myio-brand-700, #7A2FF7) 30%, transparent);
69617
69688
  }
69618
69689
 
69619
69690
  .myio-welcome-footer-text {
@@ -69906,8 +69977,8 @@ var WelcomeModalView = class _WelcomeModalView {
69906
69977
  }
69907
69978
 
69908
69979
  .myio-welcome-modal--light .myio-welcome-footer {
69909
- background: #5B2EBC;
69910
- border-top-color: rgba(122, 47, 247, 0.3);
69980
+ background: var(--myio-brand-700, #5B2EBC);
69981
+ border-top-color: color-mix(in srgb, var(--myio-brand-700, #7A2FF7) 30%, transparent);
69911
69982
  }
69912
69983
 
69913
69984
  .myio-welcome-modal--light .myio-welcome-footer-text {
@@ -75035,10 +75106,12 @@ function openOperationalComparisonModal(params) {
75035
75106
  endDate: params.endDate,
75036
75107
  devices: params.devices || []
75037
75108
  };
75038
- render2(wrapper, modalId, state6);
75039
- bindEvents3(wrapper, modalId, state6, params.onClose);
75109
+ const ref = { chrome: null };
75110
+ mount2(wrapper, modalId, state6, ref, params.onClose);
75040
75111
  return {
75041
75112
  destroy: () => {
75113
+ ref.chrome?.destroy();
75114
+ ref.chrome = null;
75042
75115
  wrapper.remove();
75043
75116
  params.onClose?.();
75044
75117
  }
@@ -75441,30 +75514,39 @@ function getThemeColors3(theme) {
75441
75514
  accent: "#7c3aed"
75442
75515
  };
75443
75516
  }
75444
- function bindEvents3(container, modalId, state6, onClose) {
75445
- const closeBtn = container.querySelector(`#${modalId}-close`);
75446
- const themeBtn = container.querySelector(`#${modalId}-theme`);
75447
- const maxBtn = container.querySelector(`#${modalId}-max`);
75517
+ function mount2(container, modalId, state6, ref, onClose) {
75518
+ ref.chrome?.destroy();
75519
+ render2(container, modalId, state6);
75520
+ const content = container.querySelector(".myio-op-compare-content");
75448
75521
  const overlay = container.querySelector(".myio-op-compare-overlay");
75449
75522
  const close = () => {
75523
+ ref.chrome?.destroy();
75524
+ ref.chrome = null;
75450
75525
  container.remove();
75451
75526
  onClose?.();
75452
75527
  };
75453
- closeBtn?.addEventListener("click", close);
75454
- if (overlay) {
75455
- overlay.addEventListener("click", (e) => {
75456
- if (e.target === overlay) close();
75457
- });
75458
- }
75459
- themeBtn?.addEventListener("click", () => {
75460
- state6.theme = state6.theme === "dark" ? "light" : "dark";
75461
- render2(container, modalId, state6);
75462
- bindEvents3(container, modalId, state6, onClose);
75528
+ ref.chrome = createPremiumModalChrome({
75529
+ modalId: `${modalId}-chrome`,
75530
+ icon: "\u{1F4CA}",
75531
+ title: `Compara\xE7\xE3o Operacional (${state6.devices.length} equipamentos)`,
75532
+ modalEl: content,
75533
+ headerSlot: content.querySelector(".myio-op-compare-header"),
75534
+ theme: state6.theme,
75535
+ showThemeToggle: true,
75536
+ maximized: state6.isMaximized,
75537
+ maximizedClass: "maximized",
75538
+ headerRadius: "12px 12px 0 0",
75539
+ onClose: close,
75540
+ onThemeChange: (t) => {
75541
+ state6.theme = t;
75542
+ mount2(container, modalId, state6, ref, onClose);
75543
+ },
75544
+ onMaximizeChange: (m) => {
75545
+ state6.isMaximized = m;
75546
+ }
75463
75547
  });
75464
- maxBtn?.addEventListener("click", () => {
75465
- state6.isMaximized = !state6.isMaximized;
75466
- render2(container, modalId, state6);
75467
- bindEvents3(container, modalId, state6, onClose);
75548
+ overlay?.addEventListener("click", (e) => {
75549
+ if (e.target === overlay) close();
75468
75550
  });
75469
75551
  }
75470
75552
 
@@ -79939,7 +80021,7 @@ function openGoalsPanel(params) {
79939
80021
  state6.conflictVersion = null;
79940
80022
  render3();
79941
80023
  }
79942
- function mount2() {
80024
+ function mount3() {
79943
80025
  const existing = document.getElementById(ROOT_ID2);
79944
80026
  if (existing) existing.remove();
79945
80027
  rootEl = document.createElement("div");
@@ -81014,7 +81096,7 @@ ${state6.year}-03-15T08,15`)}">${esc4(state6.csv)}</textarea>
81014
81096
  }
81015
81097
  };
81016
81098
  }
81017
- mount2();
81099
+ mount3();
81018
81100
  return instance;
81019
81101
  }
81020
81102
 
@@ -118275,6 +118357,10 @@ var MenuView = class {
118275
118357
  // Tab being previewed in modal
118276
118358
  // Filter Modal (RFC-0121 ModalHeader controller pattern)
118277
118359
  filterModalHeaderController = null;
118360
+ /** Footer premium (holding · hora · versão) da modal Filtro de Shoppings — criado a cada abertura */
118361
+ filterModalFooter = null;
118362
+ /** Idem para a modal "Selecione a visualização" */
118363
+ unifiedModalFooter = null;
118278
118364
  // Unified Navigation Modal (RFC-0121 ModalHeader controller pattern)
118279
118365
  unifiedModalHeaderController = null;
118280
118366
  // RFC-0126: State for unified modal when controller fails (same as filter modal)
@@ -119867,7 +119953,10 @@ var MenuView = class {
119867
119953
  modalId: "menuUnified",
119868
119954
  theme: "dark",
119869
119955
  isMaximized: false,
119870
- showThemeToggle: true,
119956
+ primaryColor: MYIO_ACCENT,
119957
+ // padrão das modais premium: acento do tema do dashboard
119958
+ showThemeToggle: false,
119959
+ // corpo é sempre claro — o toggle só trocava a cor do header
119871
119960
  showMaximize: true,
119872
119961
  showClose: true,
119873
119962
  borderRadius: "16px 16px 0 0"
@@ -120167,7 +120256,10 @@ var MenuView = class {
120167
120256
  modalId: "menuFilter",
120168
120257
  theme: this.getFilterModalDefaultTheme(),
120169
120258
  isMaximized: false,
120170
- showThemeToggle: true,
120259
+ primaryColor: MYIO_ACCENT,
120260
+ // padrão das modais premium: acento do tema do dashboard
120261
+ showThemeToggle: false,
120262
+ // a modal não tem estilos escuros — o toggle só trocava a cor do header
120171
120263
  showMaximize: true,
120172
120264
  showClose: true,
120173
120265
  borderRadius: "12px 12px 0 0"
@@ -120506,6 +120598,9 @@ var MenuView = class {
120506
120598
  modal.classList.add("is-open");
120507
120599
  btn?.setAttribute("aria-expanded", "true");
120508
120600
  this.updateUnifiedModalActiveStates();
120601
+ const content = modal.querySelector(".myio-unified-modal-content");
120602
+ this.unifiedModalFooter?.destroy();
120603
+ this.unifiedModalFooter = content ? this.createPremiumFooter(content) : null;
120509
120604
  this.bindUnifiedModalButtonsFallback();
120510
120605
  if (this.configTemplate.enableDebugMode) {
120511
120606
  console.log("[MenuView] Unified modal opened");
@@ -120521,6 +120616,8 @@ var MenuView = class {
120521
120616
  if (modal) {
120522
120617
  modal.classList.remove("is-open");
120523
120618
  btn?.setAttribute("aria-expanded", "false");
120619
+ this.unifiedModalFooter?.destroy();
120620
+ this.unifiedModalFooter = null;
120524
120621
  this.unifiedModalHeaderController?.reset();
120525
120622
  if (this.unifiedModalHeaderController) {
120526
120623
  this.applyUnifiedModalTheme(this.unifiedModalHeaderController.getTheme());
@@ -120786,6 +120883,7 @@ var MenuView = class {
120786
120883
  if (modal) {
120787
120884
  modal.classList.add("is-open");
120788
120885
  this.renderFilterList();
120886
+ this.mountFilterModalFooter();
120789
120887
  requestAnimationFrame(() => {
120790
120888
  this.ensureFilterModalHeaderController();
120791
120889
  this.bindFilterModalButtonsFallback();
@@ -120804,12 +120902,32 @@ var MenuView = class {
120804
120902
  if (modal) {
120805
120903
  modal.classList.remove("is-open");
120806
120904
  }
120905
+ this.filterModalFooter?.destroy();
120906
+ this.filterModalFooter = null;
120807
120907
  this.filterModalHeaderController?.reset();
120808
120908
  if (this.filterModalHeaderController) {
120809
120909
  this.applyFilterModalTheme(this.filterModalHeaderController.getTheme());
120810
120910
  this.applyFilterModalMaximize(this.filterModalHeaderController.isMaximized());
120811
120911
  }
120812
120912
  }
120913
+ /** Footer premium padrão (holding · hora · versão | Powered by MYIO) anexado ao fim do card. */
120914
+ createPremiumFooter(card) {
120915
+ const footer = createModalFooter({
120916
+ customerName: resolveDashboardCustomerName(),
120917
+ libVersion: { current: window.MyIOLibrary?.version },
120918
+ themeMode: "light"
120919
+ });
120920
+ footer.element.style.flexShrink = "0";
120921
+ card.appendChild(footer.element);
120922
+ return footer;
120923
+ }
120924
+ /** Footer premium no fim do card (abaixo dos botões Cancelar/Aplicar). */
120925
+ mountFilterModalFooter() {
120926
+ const card = this.root.querySelector(".myio-menu-filter-modal-card");
120927
+ if (!card) return;
120928
+ this.filterModalFooter?.destroy();
120929
+ this.filterModalFooter = this.createPremiumFooter(card);
120930
+ }
120813
120931
  getFilterModalDefaultTheme() {
120814
120932
  return "dark";
120815
120933
  }
@@ -143784,7 +143902,9 @@ var AlarmsNotificationsPanelView = class {
143784
143902
  eventHandlers = /* @__PURE__ */ new Map();
143785
143903
  debug;
143786
143904
  // Bulk-selection state
143787
- selectedTitles = /* @__PURE__ */ new Set();
143905
+ // Chave = id do card (único por card em todo modo de agrupamento). Por título, cards
143906
+ // distintos com o mesmo tipo de alarme eram selecionados juntos.
143907
+ selectedIds = /* @__PURE__ */ new Set();
143788
143908
  groupedAlarms = [];
143789
143909
  // View mode: 'card' (default) or 'list' (table)
143790
143910
  viewMode = "card";
@@ -143914,7 +144034,7 @@ var AlarmsNotificationsPanelView = class {
143914
144034
  * Build compact inline list header (filters + bulk actions button)
143915
144035
  */
143916
144036
  buildListHeaderTemplate(state6) {
143917
- const sel = this.selectedTitles.size;
144037
+ const sel = this.selectedIds.size;
143918
144038
  const isCard = this.viewMode === "card";
143919
144039
  const isList = this.viewMode === "list";
143920
144040
  const isConsol = this.groupMode === "consolidado";
@@ -144027,7 +144147,7 @@ var AlarmsNotificationsPanelView = class {
144027
144147
  const mode = btn.getAttribute("data-group-mode");
144028
144148
  if (mode === this.groupMode) return;
144029
144149
  this.groupMode = mode;
144030
- this.selectedTitles.clear();
144150
+ this.selectedIds.clear();
144031
144151
  this.root?.querySelectorAll(".alarms-group-btn").forEach((b) => {
144032
144152
  b.classList.toggle("is-active", b.getAttribute("data-group-mode") === mode);
144033
144153
  });
@@ -144040,7 +144160,7 @@ var AlarmsNotificationsPanelView = class {
144040
144160
  const mode = btn.getAttribute("data-hierarchy-mode");
144041
144161
  if (mode === this.hierarchyMode) return;
144042
144162
  this.hierarchyMode = mode;
144043
- this.selectedTitles.clear();
144163
+ this.selectedIds.clear();
144044
144164
  this.root?.querySelectorAll(".alarms-hierarchy-btn").forEach((b) => {
144045
144165
  b.classList.toggle("is-active", b.getAttribute("data-hierarchy-mode") === mode);
144046
144166
  });
@@ -144091,10 +144211,10 @@ var AlarmsNotificationsPanelView = class {
144091
144211
  this.root.addEventListener("change", (e) => {
144092
144212
  const input = e.target;
144093
144213
  if (input.type !== "checkbox" || !input.classList.contains("alarm-card-select")) return;
144094
- const title = input.dataset.alarmTitle;
144095
- if (!title) return;
144096
- if (input.checked) this.selectedTitles.add(title);
144097
- else this.selectedTitles.delete(title);
144214
+ const id = input.dataset.alarmId;
144215
+ if (!id) return;
144216
+ if (input.checked) this.selectedIds.add(id);
144217
+ else this.selectedIds.delete(id);
144098
144218
  const card = input.closest(".alarm-card");
144099
144219
  if (card) card.classList.toggle("alarm-card--selected", input.checked);
144100
144220
  const row = input.closest(".atbl-row");
@@ -144105,9 +144225,9 @@ var AlarmsNotificationsPanelView = class {
144105
144225
  const input = e.target;
144106
144226
  if (input.id !== "tblSelectAll") return;
144107
144227
  if (input.checked) {
144108
- this.groupedAlarms.forEach((a) => this.selectedTitles.add(a.title));
144228
+ this.groupedAlarms.forEach((a) => this.selectedIds.add(a.id));
144109
144229
  } else {
144110
- this.groupedAlarms.forEach((a) => this.selectedTitles.delete(a.title));
144230
+ this.groupedAlarms.forEach((a) => this.selectedIds.delete(a.id));
144111
144231
  }
144112
144232
  this.root?.querySelectorAll(".alarm-card-select").forEach((cb) => {
144113
144233
  cb.checked = input.checked;
@@ -144317,7 +144437,7 @@ var AlarmsNotificationsPanelView = class {
144317
144437
  onMore: (id, e) => this.handleMore(id, e),
144318
144438
  themeMode: state6.themeMode,
144319
144439
  showCustomerName: this.params.showCustomerName ?? true,
144320
- selected: this.selectedTitles.has(alarm.title),
144440
+ selected: this.selectedIds.has(alarm.id),
144321
144441
  showDeviceBadge: isSeparado,
144322
144442
  // separado: show device badge in header
144323
144443
  alarmTypes: isPorDispositivo ? alarm._alarmTypes ?? [] : void 0,
@@ -144389,11 +144509,11 @@ var AlarmsNotificationsPanelView = class {
144389
144509
  // =====================================================================
144390
144510
  // Bulk Selection
144391
144511
  // =====================================================================
144392
- handleAlarmSelect(title, selected) {
144512
+ handleAlarmSelect(id, selected) {
144393
144513
  if (selected) {
144394
- this.selectedTitles.add(title);
144514
+ this.selectedIds.add(id);
144395
144515
  } else {
144396
- this.selectedTitles.delete(title);
144516
+ this.selectedIds.delete(id);
144397
144517
  }
144398
144518
  this.updateBulkButton();
144399
144519
  }
@@ -144402,7 +144522,7 @@ var AlarmsNotificationsPanelView = class {
144402
144522
  const btn = this.root.querySelector("#bulkActionsBtn");
144403
144523
  const count = this.root.querySelector("#bulkCount");
144404
144524
  if (!btn || !count) return;
144405
- const sel = this.selectedTitles.size;
144525
+ const sel = this.selectedIds.size;
144406
144526
  btn.disabled = sel === 0;
144407
144527
  count.textContent = String(sel);
144408
144528
  count.style.display = sel === 0 ? "none" : "";
@@ -144471,6 +144591,24 @@ var AlarmsNotificationsPanelView = class {
144471
144591
  if (v) el2.style.setProperty(n, v);
144472
144592
  });
144473
144593
  }
144594
+ /**
144595
+ * Moldura padrão das modais premium: troca o header próprio pelo header no acento
144596
+ * do tema (maximizar opcional + fechar) e anexa o footer premium (holding · hora · versão).
144597
+ */
144598
+ mountModalChrome(modal, opts) {
144599
+ return createPremiumModalChrome({
144600
+ modalId: opts.id,
144601
+ icon: opts.icon,
144602
+ title: opts.title,
144603
+ modalEl: modal,
144604
+ headerSlot: modal.firstElementChild,
144605
+ theme: this.controller.getState().themeMode === "dark" ? "dark" : "light",
144606
+ showMaximize: !!opts.maximizedClass,
144607
+ maximizedClass: opts.maximizedClass,
144608
+ headerRadius: `${opts.radius} ${opts.radius} 0 0`,
144609
+ onClose: opts.onClose
144610
+ });
144611
+ }
144474
144612
  openFilterModal() {
144475
144613
  const state6 = this.controller.getState();
144476
144614
  const filters = state6.filters;
@@ -144588,7 +144726,11 @@ var AlarmsNotificationsPanelView = class {
144588
144726
  </div>
144589
144727
  </div>
144590
144728
  `;
144591
- const close = () => overlay.remove();
144729
+ let chrome = null;
144730
+ const close = () => {
144731
+ chrome?.destroy();
144732
+ overlay.remove();
144733
+ };
144592
144734
  overlay.addEventListener("click", (e) => {
144593
144735
  const tabBtn = e.target.closest("[data-afm-tab]");
144594
144736
  if (!tabBtn) return;
@@ -144622,7 +144764,6 @@ var AlarmsNotificationsPanelView = class {
144622
144764
  item.style.display = label.includes(q) ? "" : "none";
144623
144765
  });
144624
144766
  });
144625
- overlay.querySelector(".afm-close").addEventListener("click", close);
144626
144767
  overlay.querySelector("#afmCancelBtn").addEventListener("click", close);
144627
144768
  overlay.addEventListener("click", (e) => {
144628
144769
  if (e.target === overlay) close();
@@ -144650,6 +144791,14 @@ var AlarmsNotificationsPanelView = class {
144650
144791
  close();
144651
144792
  });
144652
144793
  this._applyCssVars(overlay);
144794
+ chrome = this.mountModalChrome(overlay.querySelector(".afm-modal"), {
144795
+ id: "afmChrome",
144796
+ icon: "\u{1F50D}",
144797
+ title: "Filtrar Alarmes",
144798
+ radius: "14px",
144799
+ maximizedClass: "afm-modal--max",
144800
+ onClose: close
144801
+ });
144653
144802
  document.body.appendChild(overlay);
144654
144803
  }
144655
144804
  // =====================================================================
@@ -144701,7 +144850,7 @@ var AlarmsNotificationsPanelView = class {
144701
144850
  const sev = SEVERITY_CONFIG[alarm.severity];
144702
144851
  const st = STATE_CONFIG[alarm.state];
144703
144852
  const isActive = alarm.state !== "CLOSED";
144704
- const sel = this.selectedTitles.has(alarm.title);
144853
+ const sel = this.selectedIds.has(alarm.id);
144705
144854
  const escTitle = this.esc(alarm.title);
144706
144855
  const escCustomer = this.esc(alarm.customerName || "-");
144707
144856
  const escSource = this.esc(alarm.source || "-");
@@ -144737,7 +144886,7 @@ var AlarmsNotificationsPanelView = class {
144737
144886
  <td class="atbl-cell atbl-cell--actions">${actionBtns}</td>
144738
144887
  </tr>`;
144739
144888
  }).join("");
144740
- const allSelected = alarms.length > 0 && alarms.every((a) => this.selectedTitles.has(a.title));
144889
+ const allSelected = alarms.length > 0 && alarms.every((a) => this.selectedIds.has(a.id));
144741
144890
  return `
144742
144891
  <table class="alarms-table" aria-label="Lista de alarmes">
144743
144892
  <thead>
@@ -144801,9 +144950,17 @@ var AlarmsNotificationsPanelView = class {
144801
144950
  </div>
144802
144951
  `;
144803
144952
  this._applyCssVars(overlay);
144953
+ const chrome = this.mountModalChrome(overlay.querySelector(".aex-modal"), {
144954
+ id: "aexChrome",
144955
+ icon: "\u{1F4E4}",
144956
+ title: "Exportar Alarmes",
144957
+ radius: "14px",
144958
+ onClose: () => close()
144959
+ });
144804
144960
  document.body.appendChild(overlay);
144805
144961
  requestAnimationFrame(() => overlay.classList.add("aex-overlay--visible"));
144806
144962
  const close = () => {
144963
+ chrome.destroy();
144807
144964
  overlay.classList.remove("aex-overlay--visible");
144808
144965
  setTimeout(() => overlay.remove(), 220);
144809
144966
  document.removeEventListener("keydown", onKey);
@@ -145135,8 +145292,8 @@ var AlarmsNotificationsPanelView = class {
145135
145292
  }, 500);
145136
145293
  }
145137
145294
  openBulkActionPicker() {
145138
- if (this.selectedTitles.size === 0) return;
145139
- const selected = this.groupedAlarms.filter((a) => this.selectedTitles.has(a.title));
145295
+ if (this.selectedIds.size === 0) return;
145296
+ const selected = this.groupedAlarms.filter((a) => this.selectedIds.has(a.id));
145140
145297
  const count = selected.length;
145141
145298
  const listHtml = selected.slice(0, 5).map((a) => `<li class="abm-alarm-item">${this.esc(a.title)}</li>`).join("");
145142
145299
  const moreHtml = count > 5 ? `<li class="abm-alarm-item abm-alarm-more">+${count - 5} mais...</li>` : "";
@@ -145173,9 +145330,17 @@ var AlarmsNotificationsPanelView = class {
145173
145330
  </div>
145174
145331
  `;
145175
145332
  this._applyCssVars(overlay);
145333
+ const chrome = this.mountModalChrome(overlay.querySelector(".abm-modal"), {
145334
+ id: "abmChrome",
145335
+ icon: "\u26A1",
145336
+ title: "A\xE7\xF5es em Lote",
145337
+ radius: "14px",
145338
+ onClose: () => close()
145339
+ });
145176
145340
  document.body.appendChild(overlay);
145177
145341
  requestAnimationFrame(() => overlay.classList.add("abm-overlay--visible"));
145178
145342
  const close = () => {
145343
+ chrome.destroy();
145179
145344
  overlay.classList.remove("abm-overlay--visible");
145180
145345
  setTimeout(() => overlay.remove(), 220);
145181
145346
  document.removeEventListener("keydown", onKey);
@@ -145273,6 +145438,13 @@ var AlarmsNotificationsPanelView = class {
145273
145438
  </div>
145274
145439
  `;
145275
145440
  this._applyCssVars(overlay);
145441
+ const chrome = this.mountModalChrome(overlay.querySelector(".alarm-action-modal"), {
145442
+ id: "aamBulkChrome",
145443
+ icon: cfg.icon,
145444
+ title: cfg.title,
145445
+ radius: "16px",
145446
+ onClose: () => close()
145447
+ });
145276
145448
  document.body.appendChild(overlay);
145277
145449
  requestAnimationFrame(() => overlay.classList.add("alarm-action-modal-overlay--visible"));
145278
145450
  const textarea = overlay.querySelector("#aamText");
@@ -145286,6 +145458,7 @@ var AlarmsNotificationsPanelView = class {
145286
145458
  if (cfg.textRequired) confirmBtn.disabled = len === 0;
145287
145459
  });
145288
145460
  const close = () => {
145461
+ chrome.destroy();
145289
145462
  overlay.classList.remove("alarm-action-modal-overlay--visible");
145290
145463
  setTimeout(() => overlay.remove(), 220);
145291
145464
  document.removeEventListener("keydown", onKey);
@@ -145312,7 +145485,7 @@ var AlarmsNotificationsPanelView = class {
145312
145485
  const until = new Date(Date.now() + minutes * 60 * 1e3).toISOString();
145313
145486
  this.controller.handleSnooze(ids, until);
145314
145487
  }
145315
- this.selectedTitles.clear();
145488
+ this.selectedIds.clear();
145316
145489
  this.updateBulkButton();
145317
145490
  close();
145318
145491
  this.emit(`alarm-${type}`, selectedAlarms.map((a) => a.id));
@@ -145776,6 +145949,13 @@ var AlarmsNotificationsPanelView = class {
145776
145949
  </div>
145777
145950
  `;
145778
145951
  this._applyCssVars(overlay);
145952
+ const chrome = this.mountModalChrome(overlay.querySelector(".alarm-action-modal"), {
145953
+ id: "aamChrome",
145954
+ icon: cfg.icon,
145955
+ title: cfg.title,
145956
+ radius: "16px",
145957
+ onClose: () => closeModal2()
145958
+ });
145779
145959
  document.body.appendChild(overlay);
145780
145960
  requestAnimationFrame(() => overlay.classList.add("alarm-action-modal-overlay--visible"));
145781
145961
  const textarea = overlay.querySelector("#aamText");
@@ -145789,6 +145969,7 @@ var AlarmsNotificationsPanelView = class {
145789
145969
  if (cfg.textRequired) confirmBtn.disabled = len === 0;
145790
145970
  });
145791
145971
  const closeModal2 = () => {
145972
+ chrome.destroy();
145792
145973
  overlay.classList.remove("alarm-action-modal-overlay--visible");
145793
145974
  setTimeout(() => overlay.remove(), 220);
145794
145975
  document.removeEventListener("keydown", onKeyDown);
@@ -165622,7 +165803,7 @@ function statusStyle(status) {
165622
165803
  }
165623
165804
  function createPresetupGateway(opts) {
165624
165805
  const {
165625
- mount: mount2,
165806
+ mount: mount3,
165626
165807
  gatewayId,
165627
165808
  clientId,
165628
165809
  clientSecret,
@@ -165645,9 +165826,9 @@ function createPresetupGateway(opts) {
165645
165826
  });
165646
165827
  const ingestion = new IngestionApiClient(ingestionApiUrl, auth);
165647
165828
  const provisioning = new ProvisioningApiClient(provisioningApiUrl);
165648
- mount2.innerHTML = "";
165829
+ mount3.innerHTML = "";
165649
165830
  const root = el("div", S.root);
165650
- mount2.appendChild(root);
165831
+ mount3.appendChild(root);
165651
165832
  const header = el("div", S.header);
165652
165833
  const titleEl = el("span", "font-weight:600;font-size:15px;");
165653
165834
  titleEl.textContent = "PresetupGateway";
@@ -165957,7 +166138,7 @@ function createPresetupGateway(opts) {
165957
166138
  await load();
165958
166139
  },
165959
166140
  destroy() {
165960
- mount2.innerHTML = "";
166141
+ mount3.innerHTML = "";
165961
166142
  }
165962
166143
  };
165963
166144
  }