myio-js-library 0.1.180 → 0.1.182

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
@@ -583,6 +583,7 @@ __export(index_exports, {
583
583
  EXPORT_DOMAIN_ICONS: () => EXPORT_DOMAIN_ICONS,
584
584
  EXPORT_DOMAIN_LABELS: () => EXPORT_DOMAIN_LABELS,
585
585
  EXPORT_DOMAIN_UNITS: () => EXPORT_DOMAIN_UNITS,
586
+ EnergyRangeTooltip: () => EnergyRangeTooltip,
586
587
  MyIOChartModal: () => MyIOChartModal,
587
588
  MyIODraggableCard: () => MyIODraggableCard,
588
589
  MyIOSelectionStore: () => MyIOSelectionStore,
@@ -591,6 +592,7 @@ __export(index_exports, {
591
592
  POWER_LIMITS_DEVICE_TYPES: () => DEVICE_TYPES,
592
593
  POWER_LIMITS_STATUS_CONFIG: () => STATUS_CONFIG,
593
594
  POWER_LIMITS_TELEMETRY_TYPES: () => TELEMETRY_TYPES2,
595
+ TempRangeTooltip: () => TempRangeTooltip,
594
596
  addDetectionContext: () => addDetectionContext,
595
597
  addNamespace: () => addNamespace,
596
598
  aggregateByDay: () => aggregateByDay,
@@ -6064,214 +6066,283 @@ function createLogHelper(debugActive = false) {
6064
6066
  }
6065
6067
  var LogHelper = createLogHelper(false);
6066
6068
 
6067
- // src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
6068
- var LABEL_CHAR_LIMIT = 18;
6069
- var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
6070
- var CSS_TAG = "head-office-card-v1";
6071
- function ensureCss() {
6072
- if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
6073
- const style = document.createElement("style");
6074
- style.setAttribute("data-myio-css", CSS_TAG);
6075
- style.textContent = CSS_STRING;
6076
- document.head.appendChild(style);
6077
- }
6069
+ // src/utils/TempRangeTooltip.ts
6070
+ var TOOLTIP_STYLES = `
6071
+ .temp-range-tooltip {
6072
+ position: fixed;
6073
+ z-index: 99999;
6074
+ pointer-events: none;
6075
+ opacity: 0;
6076
+ transition: opacity 0.2s ease, transform 0.2s ease;
6077
+ transform: translateY(5px);
6078
6078
  }
6079
- function normalizeParams(params) {
6080
- if (!params || !params.entityObject) {
6081
- throw new Error("renderCardCompenteHeadOffice: entityObject is required");
6082
- }
6083
- const LogHelper2 = createLogHelper(params.debugActive ?? false);
6084
- const entityObject = params.entityObject;
6085
- if (!entityObject.entityId) {
6086
- LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
6087
- entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
6088
- }
6089
- if (!params.delayTimeConnectionInMins) {
6090
- LogHelper2.warn(
6091
- `[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
6092
- );
6093
- }
6094
- return {
6095
- entityObject,
6096
- i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
6097
- enableSelection: Boolean(params.enableSelection),
6098
- enableDragDrop: Boolean(params.enableDragDrop),
6099
- useNewComponents: Boolean(params.useNewComponents),
6100
- // RFC-0091: Configurable delay time for connection status check (default 15 minutes)
6101
- delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
6102
- // Debug options
6103
- debugActive: params.debugActive ?? false,
6104
- activeTooltipDebug: params.activeTooltipDebug ?? false,
6105
- // LogHelper instance for this card
6106
- LogHelper: LogHelper2,
6107
- callbacks: {
6108
- handleActionDashboard: params.handleActionDashboard,
6109
- handleActionReport: params.handleActionReport,
6110
- handleActionSettings: params.handleActionSettings,
6111
- handleSelect: params.handleSelect,
6112
- handInfo: params.handInfo,
6113
- handleClickCard: params.handleClickCard
6114
- }
6115
- };
6079
+
6080
+ .temp-range-tooltip.visible {
6081
+ opacity: 1;
6082
+ pointer-events: auto;
6083
+ transform: translateY(0);
6116
6084
  }
6117
- function getIconSvg(deviceType, domain) {
6118
- if (domain === "water") {
6119
- return Icons.waterDrop;
6120
- }
6121
- if (domain === "temperature") {
6122
- return Icons.thermometer;
6123
- }
6124
- return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
6085
+
6086
+ .temp-range-tooltip__content {
6087
+ background: #ffffff;
6088
+ border: 1px solid #e2e8f0;
6089
+ border-radius: 12px;
6090
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
6091
+ min-width: 280px;
6092
+ max-width: 320px;
6093
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
6094
+ font-size: 12px;
6095
+ color: #1e293b;
6096
+ overflow: hidden;
6125
6097
  }
6126
- function formatPower(valueInWatts) {
6127
- if (valueInWatts === null || valueInWatts === void 0 || isNaN(valueInWatts)) {
6128
- return { num: "-", unit: "" };
6129
- }
6130
- const val = Number(valueInWatts);
6131
- if (val >= 1e3) {
6132
- const kw = Math.ceil(val / 1e3 * 100) / 100;
6133
- return { num: kw.toFixed(2), unit: "kW" };
6134
- } else {
6135
- const w = Math.ceil(val);
6136
- return { num: w.toString(), unit: "W" };
6137
- }
6098
+
6099
+ .temp-range-tooltip__header {
6100
+ display: flex;
6101
+ align-items: center;
6102
+ gap: 8px;
6103
+ padding: 12px 16px;
6104
+ background: linear-gradient(90deg, #fff7ed 0%, #fed7aa 100%);
6105
+ border-bottom: 1px solid #fdba74;
6138
6106
  }
6139
- function formatValueByDomain(value, domain) {
6140
- if (domain === "water") {
6141
- return formatWaterVolumeM3(value);
6142
- }
6143
- if (domain === "temperature") {
6144
- return formatTemperature(value, 0);
6145
- }
6146
- return formatEnergy(value);
6107
+
6108
+ .temp-range-tooltip__icon {
6109
+ font-size: 18px;
6147
6110
  }
6148
- function formatRelativeTime2(timestamp) {
6149
- if (!timestamp || isNaN(timestamp)) return "\u2014";
6150
- const date = new Date(timestamp);
6151
- const hours = String(date.getHours()).padStart(2, "0");
6152
- const minutes = String(date.getMinutes()).padStart(2, "0");
6153
- const day = String(date.getDate()).padStart(2, "0");
6154
- const month = String(date.getMonth() + 1).padStart(2, "0");
6155
- const year = date.getFullYear();
6156
- return `${hours}:${minutes} ${day}/${month}/${year}`;
6111
+
6112
+ .temp-range-tooltip__title {
6113
+ font-weight: 700;
6114
+ font-size: 13px;
6115
+ color: #c2410c;
6157
6116
  }
6158
- function calculateConsumptionPercentage(target, consumption) {
6159
- const numericTarget = Number(target);
6160
- const numericConsumption = Number(consumption);
6161
- if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
6162
- return 0;
6163
- }
6164
- const percentage = numericConsumption / numericTarget * 100;
6165
- return percentage;
6117
+
6118
+ .temp-range-tooltip__body {
6119
+ padding: 16px;
6166
6120
  }
6167
- function getStatusInfo(deviceStatus, i18n, domain) {
6168
- switch (deviceStatus) {
6169
- // --- Novos Status de Temperatura ---
6170
- case "normal":
6171
- return { chipClass: "chip--ok", label: "Normal" };
6172
- case "cold":
6173
- return { chipClass: "chip--standby", label: "Frio" };
6174
- case "hot":
6175
- return { chipClass: "chip--alert", label: "Quente" };
6176
- // --- Status Existentes (aligned with getCardStateClass) ---
6177
- case DeviceStatusType.POWER_ON:
6178
- if (domain === "water") {
6179
- return { chipClass: "chip--power-on", label: i18n.in_operation_water };
6180
- }
6181
- return { chipClass: "chip--power-on", label: i18n.in_operation };
6182
- case DeviceStatusType.STANDBY:
6183
- return { chipClass: "chip--standby", label: i18n.standby };
6184
- case DeviceStatusType.WARNING:
6185
- return { chipClass: "chip--warning", label: i18n.alert };
6186
- case DeviceStatusType.MAINTENANCE:
6187
- return { chipClass: "chip--maintenance", label: i18n.maintenance };
6188
- case DeviceStatusType.FAILURE:
6189
- return { chipClass: "chip--failure", label: i18n.failure };
6190
- case DeviceStatusType.POWER_OFF:
6191
- return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
6192
- case DeviceStatusType.OFFLINE:
6193
- return { chipClass: "chip--offline", label: i18n.offline };
6194
- case DeviceStatusType.NO_INFO:
6195
- return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
6196
- case DeviceStatusType.NOT_INSTALLED:
6197
- return { chipClass: "chip--not-installed", label: i18n.not_installed };
6198
- default:
6199
- return { chipClass: "chip--offline", label: i18n.offline };
6200
- }
6121
+
6122
+ .temp-range-tooltip__value-row {
6123
+ display: flex;
6124
+ justify-content: space-between;
6125
+ align-items: center;
6126
+ margin-bottom: 16px;
6201
6127
  }
6202
- function getCardStateClass(deviceStatus) {
6203
- switch (deviceStatus) {
6204
- case DeviceStatusType.POWER_ON:
6205
- return "is-power-on";
6206
- // Blue border
6207
- case DeviceStatusType.STANDBY:
6208
- return "is-standby";
6209
- // Green border
6210
- case DeviceStatusType.WARNING:
6211
- return "is-warning";
6212
- // Yellow border
6213
- case DeviceStatusType.MAINTENANCE:
6214
- return "is-maintenance";
6215
- // Yellow border
6216
- case DeviceStatusType.FAILURE:
6217
- return "is-failure";
6218
- // Dark Red border
6219
- case DeviceStatusType.POWER_OFF:
6220
- return "is-power-off";
6221
- // Light Red border
6222
- case DeviceStatusType.OFFLINE:
6223
- return "is-offline";
6224
- // Dark Gray border
6225
- case DeviceStatusType.NO_INFO:
6226
- return "is-no-info";
6227
- // Dark Orange border
6228
- case DeviceStatusType.NOT_INSTALLED:
6229
- return "is-not-installed";
6230
- // Purple border
6231
- default:
6232
- return "";
6233
- }
6128
+
6129
+ .temp-range-tooltip__current {
6130
+ font-size: 28px;
6131
+ font-weight: 700;
6132
+ color: #1e293b;
6234
6133
  }
6235
- function getTempRangeClass(entityObject) {
6236
- if (entityObject.domain !== "temperature") return "";
6237
- const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
6238
- const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
6239
- const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
6240
- if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
6241
- return "";
6242
- }
6243
- if (currentTemp > tempMax) return "is-temp-hot";
6244
- if (currentTemp < tempMin) return "is-temp-cold";
6245
- return "is-temp-ok";
6134
+
6135
+ .temp-range-tooltip__current sup {
6136
+ font-size: 14px;
6137
+ color: #64748b;
6246
6138
  }
6247
- var TempRangeTooltip = {
6248
- containerId: "myio-temp-range-tooltip",
6249
- /**
6250
- * Create or get the tooltip container
6251
- */
6252
- getContainer() {
6253
- let container = document.getElementById(this.containerId);
6254
- if (!container) {
6255
- container = document.createElement("div");
6256
- container.id = this.containerId;
6257
- container.className = "temp-range-tooltip";
6258
- document.body.appendChild(container);
6259
- }
6260
- return container;
6261
- },
6262
- /**
6263
- * Calculate temperature status and deviation
6264
- */
6265
- calculateStatus(currentTemp, tempMin, tempMax) {
6266
- if (tempMin == null || tempMax == null) {
6267
- return { status: "unknown", deviation: null, deviationPercent: null };
6268
- }
6269
- const rangeSize = tempMax - tempMin;
6270
- const midPoint = (tempMin + tempMax) / 2;
6271
- if (currentTemp < tempMin) {
6272
- const deviation = tempMin - currentTemp;
6273
- const deviationPercent = rangeSize > 0 ? deviation / rangeSize * 100 : 0;
6274
- return { status: "cold", deviation: -deviation, deviationPercent: -deviationPercent };
6139
+
6140
+ .temp-range-tooltip__deviation {
6141
+ text-align: right;
6142
+ }
6143
+
6144
+ .temp-range-tooltip__deviation-value {
6145
+ font-size: 16px;
6146
+ font-weight: 700;
6147
+ }
6148
+
6149
+ .temp-range-tooltip__deviation-value.cold {
6150
+ color: #2563eb;
6151
+ }
6152
+
6153
+ .temp-range-tooltip__deviation-value.ok {
6154
+ color: #16a34a;
6155
+ }
6156
+
6157
+ .temp-range-tooltip__deviation-value.hot {
6158
+ color: #dc2626;
6159
+ }
6160
+
6161
+ .temp-range-tooltip__deviation-label {
6162
+ font-size: 10px;
6163
+ color: #64748b;
6164
+ text-transform: uppercase;
6165
+ letter-spacing: 0.5px;
6166
+ }
6167
+
6168
+ .temp-range-tooltip__ruler {
6169
+ position: relative;
6170
+ height: 32px;
6171
+ margin: 12px 0;
6172
+ border-radius: 8px;
6173
+ overflow: visible;
6174
+ }
6175
+
6176
+ .temp-range-tooltip__ruler-track {
6177
+ position: absolute;
6178
+ top: 12px;
6179
+ left: 0;
6180
+ right: 0;
6181
+ height: 8px;
6182
+ background: linear-gradient(90deg, #dbeafe 0%, #dcfce7 50%, #fee2e2 100%);
6183
+ border-radius: 4px;
6184
+ border: 1px solid #e2e8f0;
6185
+ }
6186
+
6187
+ .temp-range-tooltip__ruler-range {
6188
+ position: absolute;
6189
+ top: 12px;
6190
+ height: 8px;
6191
+ background: #22c55e;
6192
+ border-radius: 4px;
6193
+ opacity: 0.6;
6194
+ }
6195
+
6196
+ .temp-range-tooltip__ruler-marker {
6197
+ position: absolute;
6198
+ top: 4px;
6199
+ width: 4px;
6200
+ height: 24px;
6201
+ background: #1e293b;
6202
+ border-radius: 2px;
6203
+ transform: translateX(-50%);
6204
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6205
+ }
6206
+
6207
+ .temp-range-tooltip__ruler-marker::after {
6208
+ content: '';
6209
+ position: absolute;
6210
+ top: -4px;
6211
+ left: 50%;
6212
+ transform: translateX(-50%);
6213
+ width: 12px;
6214
+ height: 12px;
6215
+ background: #1e293b;
6216
+ border-radius: 50%;
6217
+ border: 2px solid #fff;
6218
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6219
+ }
6220
+
6221
+ .temp-range-tooltip__ruler-labels {
6222
+ display: flex;
6223
+ justify-content: space-between;
6224
+ margin-top: 8px;
6225
+ font-size: 10px;
6226
+ color: #64748b;
6227
+ }
6228
+
6229
+ .temp-range-tooltip__ruler-min,
6230
+ .temp-range-tooltip__ruler-max {
6231
+ font-weight: 600;
6232
+ }
6233
+
6234
+ .temp-range-tooltip__range-info {
6235
+ display: flex;
6236
+ justify-content: space-between;
6237
+ padding: 10px 12px;
6238
+ background: #f8fafc;
6239
+ border-radius: 8px;
6240
+ margin-top: 12px;
6241
+ }
6242
+
6243
+ .temp-range-tooltip__range-item {
6244
+ text-align: center;
6245
+ }
6246
+
6247
+ .temp-range-tooltip__range-label {
6248
+ font-size: 10px;
6249
+ color: #64748b;
6250
+ text-transform: uppercase;
6251
+ letter-spacing: 0.3px;
6252
+ margin-bottom: 2px;
6253
+ }
6254
+
6255
+ .temp-range-tooltip__range-value {
6256
+ font-size: 14px;
6257
+ font-weight: 600;
6258
+ color: #334155;
6259
+ }
6260
+
6261
+ .temp-range-tooltip__status {
6262
+ display: flex;
6263
+ align-items: center;
6264
+ justify-content: center;
6265
+ gap: 6px;
6266
+ margin-top: 12px;
6267
+ padding: 8px 12px;
6268
+ border-radius: 6px;
6269
+ font-size: 11px;
6270
+ font-weight: 600;
6271
+ }
6272
+
6273
+ .temp-range-tooltip__status.cold {
6274
+ background: #dbeafe;
6275
+ color: #1d4ed8;
6276
+ border: 1px solid #93c5fd;
6277
+ }
6278
+
6279
+ .temp-range-tooltip__status.ok {
6280
+ background: #dcfce7;
6281
+ color: #15803d;
6282
+ border: 1px solid #86efac;
6283
+ }
6284
+
6285
+ .temp-range-tooltip__status.hot {
6286
+ background: #fee2e2;
6287
+ color: #b91c1c;
6288
+ border: 1px solid #fca5a5;
6289
+ }
6290
+
6291
+ .temp-range-tooltip__status.unknown {
6292
+ background: #f3f4f6;
6293
+ color: #6b7280;
6294
+ border: 1px solid #d1d5db;
6295
+ }
6296
+ `;
6297
+ function injectStyles() {
6298
+ if (typeof document === "undefined") return;
6299
+ const styleId = "myio-temp-range-tooltip-styles";
6300
+ if (document.getElementById(styleId)) return;
6301
+ const style = document.createElement("style");
6302
+ style.id = styleId;
6303
+ style.textContent = TOOLTIP_STYLES;
6304
+ document.head.appendChild(style);
6305
+ }
6306
+ function extractTemperature(entityData) {
6307
+ return Number(entityData.val ?? entityData.currentTemperature ?? entityData.temperature) || 0;
6308
+ }
6309
+ function extractRange(entityData) {
6310
+ const tempMin = entityData.temperatureMin ?? entityData.minTemperature ?? null;
6311
+ const tempMax = entityData.temperatureMax ?? entityData.maxTemperature ?? null;
6312
+ return { tempMin, tempMax };
6313
+ }
6314
+ function extractLabel(entityData) {
6315
+ return entityData.labelOrName || entityData.name || entityData.label || "Sensor";
6316
+ }
6317
+ var TempRangeTooltip = {
6318
+ containerId: "myio-temp-range-tooltip",
6319
+ /**
6320
+ * Create or get the tooltip container
6321
+ */
6322
+ getContainer() {
6323
+ injectStyles();
6324
+ let container = document.getElementById(this.containerId);
6325
+ if (!container) {
6326
+ container = document.createElement("div");
6327
+ container.id = this.containerId;
6328
+ container.className = "temp-range-tooltip";
6329
+ document.body.appendChild(container);
6330
+ }
6331
+ return container;
6332
+ },
6333
+ /**
6334
+ * Calculate temperature status and deviation
6335
+ */
6336
+ calculateStatus(currentTemp, tempMin, tempMax) {
6337
+ if (tempMin == null || tempMax == null) {
6338
+ return { status: "unknown", deviation: null, deviationPercent: null };
6339
+ }
6340
+ const rangeSize = tempMax - tempMin;
6341
+ const midPoint = (tempMin + tempMax) / 2;
6342
+ if (currentTemp < tempMin) {
6343
+ const deviation = tempMin - currentTemp;
6344
+ const deviationPercent = rangeSize > 0 ? deviation / rangeSize * 100 : 0;
6345
+ return { status: "cold", deviation: -deviation, deviationPercent: -deviationPercent };
6275
6346
  } else if (currentTemp > tempMax) {
6276
6347
  const deviation = currentTemp - tempMax;
6277
6348
  const deviationPercent = rangeSize > 0 ? deviation / rangeSize * 100 : 0;
@@ -6299,20 +6370,20 @@ var TempRangeTooltip = {
6299
6370
  },
6300
6371
  /**
6301
6372
  * Show tooltip for a temperature card
6302
- * @param {HTMLElement} triggerElement - The card element
6303
- * @param {Object} entityObject - Entity data
6304
- * @param {MouseEvent} event - Mouse event for cursor position
6373
+ * @param triggerElement - The card element
6374
+ * @param entityData - Entity data with temperature info
6375
+ * @param event - Mouse event for cursor position
6305
6376
  */
6306
- show(triggerElement, entityObject, event) {
6377
+ show(triggerElement, entityData, event) {
6307
6378
  const container = this.getContainer();
6308
- const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
6309
- const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
6310
- const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
6379
+ const currentTemp = extractTemperature(entityData);
6380
+ const { tempMin, tempMax } = extractRange(entityData);
6381
+ const label = extractLabel(entityData);
6311
6382
  const hasRange = tempMin != null && tempMax != null;
6312
- const { status, deviation, deviationPercent } = this.calculateStatus(currentTemp, tempMin, tempMax);
6383
+ const { status, deviationPercent } = this.calculateStatus(currentTemp, tempMin, tempMax);
6313
6384
  const markerPos = this.calculateMarkerPosition(currentTemp, tempMin, tempMax);
6314
6385
  let rangeLeft = 0, rangeWidth = 100;
6315
- if (hasRange) {
6386
+ if (hasRange && tempMin != null && tempMax != null) {
6316
6387
  const rangeSize = tempMax - tempMin;
6317
6388
  const extension = rangeSize * 0.3;
6318
6389
  const visibleMin = tempMin - extension;
@@ -6321,28 +6392,23 @@ var TempRangeTooltip = {
6321
6392
  rangeLeft = (tempMin - visibleMin) / visibleRange * 100;
6322
6393
  rangeWidth = rangeSize / visibleRange * 100;
6323
6394
  }
6324
- let deviationText = "";
6325
- let deviationClass = status;
6326
- if (status === "cold") {
6327
- deviationText = `${Math.abs(deviation).toFixed(1)}\xB0C abaixo`;
6328
- } else if (status === "hot") {
6329
- deviationText = `+${deviation.toFixed(1)}\xB0C acima`;
6330
- } else if (status === "ok") {
6331
- deviationText = "Na faixa ideal";
6332
- } else {
6333
- deviationText = "Faixa n\xE3o configurada";
6334
- }
6335
6395
  const statusLabels = {
6336
6396
  cold: "\u2744\uFE0F Abaixo da Faixa Ideal",
6337
6397
  ok: "\u2714\uFE0F Dentro da Faixa Ideal",
6338
6398
  hot: "\u{1F525} Acima da Faixa Ideal",
6339
6399
  unknown: "\u2753 Faixa N\xE3o Configurada"
6340
6400
  };
6401
+ const statusColors = {
6402
+ cold: "#2563eb",
6403
+ ok: "#16a34a",
6404
+ hot: "#dc2626",
6405
+ unknown: "#64748b"
6406
+ };
6341
6407
  container.innerHTML = `
6342
6408
  <div class="temp-range-tooltip__content">
6343
6409
  <div class="temp-range-tooltip__header">
6344
6410
  <span class="temp-range-tooltip__icon">\u{1F321}\uFE0F</span>
6345
- <span class="temp-range-tooltip__title">${entityObject.labelOrName || entityObject.name || "Sensor"}</span>
6411
+ <span class="temp-range-tooltip__title">${label}</span>
6346
6412
  </div>
6347
6413
  <div class="temp-range-tooltip__body">
6348
6414
  <div class="temp-range-tooltip__value-row">
@@ -6350,7 +6416,7 @@ var TempRangeTooltip = {
6350
6416
  ${currentTemp.toFixed(1)}<sup>\xB0C</sup>
6351
6417
  </div>
6352
6418
  <div class="temp-range-tooltip__deviation">
6353
- <div class="temp-range-tooltip__deviation-value ${deviationClass}">
6419
+ <div class="temp-range-tooltip__deviation-value ${status}">
6354
6420
  ${status === "ok" ? "\u2713" : status === "cold" ? "\u2193" : status === "hot" ? "\u2191" : "?"} ${Math.abs(deviationPercent || 0).toFixed(0)}%
6355
6421
  </div>
6356
6422
  <div class="temp-range-tooltip__deviation-label">Desvio</div>
@@ -6377,7 +6443,7 @@ var TempRangeTooltip = {
6377
6443
  </div>
6378
6444
  <div class="temp-range-tooltip__range-item">
6379
6445
  <div class="temp-range-tooltip__range-label">Atual</div>
6380
- <div class="temp-range-tooltip__range-value" style="color: ${status === "ok" ? "#16a34a" : status === "cold" ? "#2563eb" : "#dc2626"}">${currentTemp.toFixed(1)}\xB0C</div>
6446
+ <div class="temp-range-tooltip__range-value" style="color: ${statusColors[status]}">${currentTemp.toFixed(1)}\xB0C</div>
6381
6447
  </div>
6382
6448
  <div class="temp-range-tooltip__range-item">
6383
6449
  <div class="temp-range-tooltip__range-label">M\xE1ximo</div>
@@ -6422,7 +6488,320 @@ var TempRangeTooltip = {
6422
6488
  if (container) {
6423
6489
  container.classList.remove("visible");
6424
6490
  }
6491
+ },
6492
+ /**
6493
+ * Attach tooltip to an element
6494
+ * Returns cleanup function
6495
+ */
6496
+ attach(element, entityData) {
6497
+ const showHandler = (e) => this.show(element, entityData, e);
6498
+ const hideHandler = () => this.hide();
6499
+ element.style.cursor = "help";
6500
+ element.addEventListener("mouseenter", showHandler);
6501
+ element.addEventListener("mouseleave", hideHandler);
6502
+ return () => {
6503
+ element.removeEventListener("mouseenter", showHandler);
6504
+ element.removeEventListener("mouseleave", hideHandler);
6505
+ element.style.cursor = "";
6506
+ this.hide();
6507
+ };
6508
+ }
6509
+ };
6510
+
6511
+ // src/utils/EnergyRangeTooltip.ts
6512
+ var ENERGY_RANGE_TOOLTIP_CSS = `
6513
+ /* ============================================
6514
+ Energy Range Tooltip (for domain=energy)
6515
+ Shows power ruler with current position and status ranges
6516
+ ============================================ */
6517
+ .energy-range-tooltip {
6518
+ position: fixed;
6519
+ z-index: 99999;
6520
+ pointer-events: none;
6521
+ opacity: 0;
6522
+ transition: opacity 0.2s ease, transform 0.2s ease;
6523
+ transform: translateY(5px);
6524
+ }
6525
+
6526
+ .energy-range-tooltip.visible {
6527
+ opacity: 1;
6528
+ pointer-events: auto;
6529
+ transform: translateY(0);
6530
+ }
6531
+
6532
+ .energy-range-tooltip__content {
6533
+ background: #ffffff;
6534
+ border: 1px solid #e2e8f0;
6535
+ border-radius: 12px;
6536
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
6537
+ min-width: 300px;
6538
+ max-width: 360px;
6539
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
6540
+ font-size: 12px;
6541
+ color: #1e293b;
6542
+ overflow: hidden;
6543
+ }
6544
+
6545
+ .energy-range-tooltip__header {
6546
+ display: flex;
6547
+ align-items: center;
6548
+ gap: 8px;
6549
+ padding: 12px 16px;
6550
+ background: linear-gradient(90deg, #ecfdf5 0%, #d1fae5 100%);
6551
+ border-bottom: 1px solid #6ee7b7;
6552
+ }
6553
+
6554
+ .energy-range-tooltip__icon {
6555
+ font-size: 18px;
6556
+ }
6557
+
6558
+ .energy-range-tooltip__title {
6559
+ font-weight: 700;
6560
+ font-size: 13px;
6561
+ color: #047857;
6562
+ }
6563
+
6564
+ .energy-range-tooltip__body {
6565
+ padding: 16px;
6566
+ }
6567
+
6568
+ /* Power value display */
6569
+ .energy-range-tooltip__value-row {
6570
+ display: flex;
6571
+ justify-content: space-between;
6572
+ align-items: center;
6573
+ margin-bottom: 16px;
6574
+ }
6575
+
6576
+ .energy-range-tooltip__current {
6577
+ font-size: 28px;
6578
+ font-weight: 700;
6579
+ color: #1e293b;
6580
+ }
6581
+
6582
+ .energy-range-tooltip__current sup {
6583
+ font-size: 14px;
6584
+ color: #64748b;
6585
+ }
6586
+
6587
+ .energy-range-tooltip__status-badge {
6588
+ text-align: right;
6589
+ }
6590
+
6591
+ .energy-range-tooltip__status-value {
6592
+ font-size: 14px;
6593
+ font-weight: 700;
6594
+ padding: 4px 10px;
6595
+ border-radius: 6px;
6596
+ }
6597
+
6598
+ .energy-range-tooltip__status-value.standby {
6599
+ background: #dbeafe;
6600
+ color: #1d4ed8;
6601
+ }
6602
+
6603
+ .energy-range-tooltip__status-value.normal {
6604
+ background: #dcfce7;
6605
+ color: #15803d;
6606
+ }
6607
+
6608
+ .energy-range-tooltip__status-value.alert {
6609
+ background: #fef3c7;
6610
+ color: #b45309;
6611
+ }
6612
+
6613
+ .energy-range-tooltip__status-value.failure {
6614
+ background: #fee2e2;
6615
+ color: #b91c1c;
6616
+ }
6617
+
6618
+ .energy-range-tooltip__status-value.offline {
6619
+ background: #f3f4f6;
6620
+ color: #6b7280;
6621
+ }
6622
+
6623
+ /* Power ruler/gauge */
6624
+ .energy-range-tooltip__ruler {
6625
+ position: relative;
6626
+ height: 40px;
6627
+ margin: 12px 0;
6628
+ border-radius: 8px;
6629
+ overflow: visible;
6630
+ }
6631
+
6632
+ .energy-range-tooltip__ruler-track {
6633
+ position: absolute;
6634
+ top: 16px;
6635
+ left: 0;
6636
+ right: 0;
6637
+ height: 8px;
6638
+ display: flex;
6639
+ border-radius: 4px;
6640
+ overflow: hidden;
6641
+ border: 1px solid #e2e8f0;
6642
+ }
6643
+
6644
+ .energy-range-tooltip__ruler-segment {
6645
+ height: 100%;
6646
+ }
6647
+
6648
+ .energy-range-tooltip__ruler-segment.standby {
6649
+ background: #dbeafe;
6650
+ }
6651
+
6652
+ .energy-range-tooltip__ruler-segment.normal {
6653
+ background: #dcfce7;
6654
+ }
6655
+
6656
+ .energy-range-tooltip__ruler-segment.alert {
6657
+ background: #fef3c7;
6658
+ }
6659
+
6660
+ .energy-range-tooltip__ruler-segment.failure {
6661
+ background: #fee2e2;
6662
+ }
6663
+
6664
+ .energy-range-tooltip__ruler-marker {
6665
+ position: absolute;
6666
+ top: 8px;
6667
+ width: 4px;
6668
+ height: 24px;
6669
+ background: #1e293b;
6670
+ border-radius: 2px;
6671
+ transform: translateX(-50%);
6672
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6673
+ }
6674
+
6675
+ .energy-range-tooltip__ruler-marker::after {
6676
+ content: '';
6677
+ position: absolute;
6678
+ top: -4px;
6679
+ left: 50%;
6680
+ transform: translateX(-50%);
6681
+ width: 12px;
6682
+ height: 12px;
6683
+ background: #1e293b;
6684
+ border-radius: 50%;
6685
+ border: 2px solid #fff;
6686
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6687
+ }
6688
+
6689
+ /* Range info grid */
6690
+ .energy-range-tooltip__ranges {
6691
+ display: grid;
6692
+ grid-template-columns: repeat(4, 1fr);
6693
+ gap: 8px;
6694
+ margin-top: 16px;
6695
+ }
6696
+
6697
+ .energy-range-tooltip__range-item {
6698
+ text-align: center;
6699
+ padding: 8px 4px;
6700
+ border-radius: 6px;
6701
+ background: #f8fafc;
6702
+ }
6703
+
6704
+ .energy-range-tooltip__range-item.standby {
6705
+ border-left: 3px solid #3b82f6;
6706
+ }
6707
+
6708
+ .energy-range-tooltip__range-item.normal {
6709
+ border-left: 3px solid #22c55e;
6710
+ }
6711
+
6712
+ .energy-range-tooltip__range-item.alert {
6713
+ border-left: 3px solid #f59e0b;
6714
+ }
6715
+
6716
+ .energy-range-tooltip__range-item.failure {
6717
+ border-left: 3px solid #ef4444;
6718
+ }
6719
+
6720
+ .energy-range-tooltip__range-label {
6721
+ font-size: 9px;
6722
+ color: #64748b;
6723
+ text-transform: uppercase;
6724
+ letter-spacing: 0.3px;
6725
+ margin-bottom: 2px;
6726
+ }
6727
+
6728
+ .energy-range-tooltip__range-value {
6729
+ font-size: 11px;
6730
+ font-weight: 600;
6731
+ color: #334155;
6732
+ }
6733
+
6734
+ /* Status info */
6735
+ .energy-range-tooltip__status-info {
6736
+ display: flex;
6737
+ align-items: center;
6738
+ justify-content: center;
6739
+ gap: 6px;
6740
+ margin-top: 12px;
6741
+ padding: 8px 12px;
6742
+ border-radius: 6px;
6743
+ font-size: 11px;
6744
+ font-weight: 600;
6745
+ }
6746
+
6747
+ .energy-range-tooltip__status-info.standby {
6748
+ background: #dbeafe;
6749
+ color: #1d4ed8;
6750
+ border: 1px solid #93c5fd;
6751
+ }
6752
+
6753
+ .energy-range-tooltip__status-info.normal {
6754
+ background: #dcfce7;
6755
+ color: #15803d;
6756
+ border: 1px solid #86efac;
6757
+ }
6758
+
6759
+ .energy-range-tooltip__status-info.alert {
6760
+ background: #fef3c7;
6761
+ color: #b45309;
6762
+ border: 1px solid #fcd34d;
6763
+ }
6764
+
6765
+ .energy-range-tooltip__status-info.failure {
6766
+ background: #fee2e2;
6767
+ color: #b91c1c;
6768
+ border: 1px solid #fca5a5;
6769
+ }
6770
+
6771
+ .energy-range-tooltip__status-info.offline {
6772
+ background: #f3f4f6;
6773
+ color: #6b7280;
6774
+ border: 1px solid #d1d5db;
6775
+ }
6776
+ `;
6777
+ var cssInjected = false;
6778
+ function injectCSS() {
6779
+ if (cssInjected) return;
6780
+ if (typeof document === "undefined") return;
6781
+ const styleId = "myio-energy-range-tooltip-styles";
6782
+ if (document.getElementById(styleId)) {
6783
+ cssInjected = true;
6784
+ return;
6425
6785
  }
6786
+ const style = document.createElement("style");
6787
+ style.id = styleId;
6788
+ style.textContent = ENERGY_RANGE_TOOLTIP_CSS;
6789
+ document.head.appendChild(style);
6790
+ cssInjected = true;
6791
+ }
6792
+ var STATUS_LABELS = {
6793
+ standby: "Standby",
6794
+ normal: "Operacao Normal",
6795
+ alert: "Alerta",
6796
+ failure: "Falha",
6797
+ offline: "Fora da faixa"
6798
+ };
6799
+ var STATUS_INFO_LABELS = {
6800
+ standby: "\u{1F535} Standby",
6801
+ normal: "\u2705 Operacao Normal",
6802
+ alert: "\u26A0\uFE0F Alerta",
6803
+ failure: "\u{1F534} Falha",
6804
+ offline: "\u26AB Offline / Sem dados"
6426
6805
  };
6427
6806
  var EnergyRangeTooltip = {
6428
6807
  containerId: "myio-energy-range-tooltip",
@@ -6430,6 +6809,7 @@ var EnergyRangeTooltip = {
6430
6809
  * Create or get the tooltip container
6431
6810
  */
6432
6811
  getContainer() {
6812
+ injectCSS();
6433
6813
  let container = document.getElementById(this.containerId);
6434
6814
  if (!container) {
6435
6815
  container = document.createElement("div");
@@ -6449,18 +6829,18 @@ var EnergyRangeTooltip = {
6449
6829
  const power = Number(powerValue) || 0;
6450
6830
  const { standbyRange, normalRange, alertRange, failureRange } = ranges;
6451
6831
  if (standbyRange && power >= standbyRange.down && power <= standbyRange.up) {
6452
- return { status: "standby", label: "Standby" };
6832
+ return { status: "standby", label: STATUS_LABELS.standby };
6453
6833
  }
6454
6834
  if (normalRange && power >= normalRange.down && power <= normalRange.up) {
6455
- return { status: "normal", label: "Normal" };
6835
+ return { status: "normal", label: STATUS_LABELS.normal };
6456
6836
  }
6457
6837
  if (alertRange && power >= alertRange.down && power <= alertRange.up) {
6458
- return { status: "alert", label: "Alerta" };
6838
+ return { status: "alert", label: STATUS_LABELS.alert };
6459
6839
  }
6460
6840
  if (failureRange && power >= failureRange.down && power <= failureRange.up) {
6461
- return { status: "failure", label: "Falha" };
6841
+ return { status: "failure", label: STATUS_LABELS.failure };
6462
6842
  }
6463
- return { status: "offline", label: "Fora da faixa" };
6843
+ return { status: "offline", label: STATUS_LABELS.offline };
6464
6844
  },
6465
6845
  /**
6466
6846
  * Calculate marker position on ruler (0-100%)
@@ -6491,7 +6871,7 @@ var EnergyRangeTooltip = {
6491
6871
  * Format power value for display
6492
6872
  */
6493
6873
  formatPower(value) {
6494
- if (value == null || isNaN(value)) return "-";
6874
+ if (value == null || isNaN(Number(value))) return "-";
6495
6875
  const num = Number(value);
6496
6876
  if (num >= 1e3) {
6497
6877
  return `${(num / 1e3).toFixed(2)} kW`;
@@ -6509,13 +6889,40 @@ var EnergyRangeTooltip = {
6509
6889
  const { status, label } = this.calculateStatus(powerValue, ranges);
6510
6890
  const markerPos = this.calculateMarkerPosition(powerValue, ranges);
6511
6891
  const segmentWidths = this.calculateSegmentWidths(ranges);
6512
- const statusLabels = {
6513
- standby: "\u{1F535} Standby",
6514
- normal: "\u2705 Opera\xE7\xE3o Normal",
6515
- alert: "\u26A0\uFE0F Alerta",
6516
- failure: "\u{1F534} Falha",
6517
- offline: "\u26AB Offline / Sem dados"
6518
- };
6892
+ const rangesHtml = hasRanges && ranges ? `
6893
+ <div class="energy-range-tooltip__ruler">
6894
+ <div class="energy-range-tooltip__ruler-track">
6895
+ <div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
6896
+ <div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
6897
+ <div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
6898
+ <div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
6899
+ </div>
6900
+ <div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
6901
+ </div>
6902
+
6903
+ <div class="energy-range-tooltip__ranges">
6904
+ <div class="energy-range-tooltip__range-item standby">
6905
+ <div class="energy-range-tooltip__range-label">Standby</div>
6906
+ <div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
6907
+ </div>
6908
+ <div class="energy-range-tooltip__range-item normal">
6909
+ <div class="energy-range-tooltip__range-label">Normal</div>
6910
+ <div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
6911
+ </div>
6912
+ <div class="energy-range-tooltip__range-item alert">
6913
+ <div class="energy-range-tooltip__range-label">Alerta</div>
6914
+ <div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
6915
+ </div>
6916
+ <div class="energy-range-tooltip__range-item failure">
6917
+ <div class="energy-range-tooltip__range-label">Falha</div>
6918
+ <div class="energy-range-tooltip__range-value">&gt;${ranges.failureRange?.down || 0}W</div>
6919
+ </div>
6920
+ </div>
6921
+ ` : `
6922
+ <div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
6923
+ Ranges de potencia nao configurados
6924
+ </div>
6925
+ `;
6519
6926
  container.innerHTML = `
6520
6927
  <div class="energy-range-tooltip__content">
6521
6928
  <div class="energy-range-tooltip__header">
@@ -6532,51 +6939,18 @@ var EnergyRangeTooltip = {
6532
6939
  </div>
6533
6940
  </div>
6534
6941
 
6535
- ${hasRanges ? `
6536
- <div class="energy-range-tooltip__ruler">
6537
- <div class="energy-range-tooltip__ruler-track">
6538
- <div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
6539
- <div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
6540
- <div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
6541
- <div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
6542
- </div>
6543
- <div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
6544
- </div>
6545
-
6546
- <div class="energy-range-tooltip__ranges">
6547
- <div class="energy-range-tooltip__range-item standby">
6548
- <div class="energy-range-tooltip__range-label">Standby</div>
6549
- <div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
6550
- </div>
6551
- <div class="energy-range-tooltip__range-item normal">
6552
- <div class="energy-range-tooltip__range-label">Normal</div>
6553
- <div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
6554
- </div>
6555
- <div class="energy-range-tooltip__range-item alert">
6556
- <div class="energy-range-tooltip__range-label">Alerta</div>
6557
- <div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
6558
- </div>
6559
- <div class="energy-range-tooltip__range-item failure">
6560
- <div class="energy-range-tooltip__range-label">Falha</div>
6561
- <div class="energy-range-tooltip__range-value">&gt;${ranges.failureRange?.down || 0}W</div>
6562
- </div>
6563
- </div>
6564
- ` : `
6565
- <div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
6566
- Ranges de pot\xEAncia n\xE3o configurados
6567
- </div>
6568
- `}
6942
+ ${rangesHtml}
6569
6943
 
6570
6944
  <div class="energy-range-tooltip__status-info ${status}">
6571
- ${statusLabels[status] || statusLabels.offline}
6945
+ ${STATUS_INFO_LABELS[status] || STATUS_INFO_LABELS.offline}
6572
6946
  </div>
6573
6947
  </div>
6574
6948
  </div>
6575
6949
  `;
6576
6950
  let left, top;
6577
6951
  if (event && event.clientX && event.clientY) {
6578
- left = event.clientX + 15;
6579
- top = event.clientY + 15;
6952
+ left = event.clientX + 8;
6953
+ top = event.clientY + 8;
6580
6954
  } else {
6581
6955
  const rect = triggerElement.getBoundingClientRect();
6582
6956
  left = rect.left + rect.width / 2 - 150;
@@ -6585,11 +6959,11 @@ var EnergyRangeTooltip = {
6585
6959
  const tooltipWidth = 320;
6586
6960
  const tooltipHeight = 380;
6587
6961
  if (left + tooltipWidth > window.innerWidth - 10) {
6588
- left = (event?.clientX || left) - tooltipWidth - 15;
6962
+ left = (event?.clientX || left) - tooltipWidth - 8;
6589
6963
  }
6590
6964
  if (left < 10) left = 10;
6591
6965
  if (top + tooltipHeight > window.innerHeight - 10) {
6592
- top = (event?.clientY || top) - tooltipHeight - 15;
6966
+ top = (event?.clientY || top) - tooltipHeight - 8;
6593
6967
  }
6594
6968
  if (top < 10) top = 10;
6595
6969
  container.style.left = left + "px";
@@ -6604,8 +6978,229 @@ var EnergyRangeTooltip = {
6604
6978
  if (container) {
6605
6979
  container.classList.remove("visible");
6606
6980
  }
6981
+ },
6982
+ /**
6983
+ * Attach tooltip to an element with automatic show/hide on hover
6984
+ * Returns cleanup function to remove event listeners
6985
+ */
6986
+ attach(element, entityData) {
6987
+ const handleMouseEnter = (e) => {
6988
+ this.show(element, entityData, e);
6989
+ };
6990
+ const handleMouseLeave = () => {
6991
+ this.hide();
6992
+ };
6993
+ const handleMouseMove = (e) => {
6994
+ const container = document.getElementById(this.containerId);
6995
+ if (container && container.classList.contains("visible")) {
6996
+ let left = e.clientX + 8;
6997
+ let top = e.clientY + 8;
6998
+ const tooltipWidth = 320;
6999
+ const tooltipHeight = 380;
7000
+ if (left + tooltipWidth > window.innerWidth - 10) {
7001
+ left = e.clientX - tooltipWidth - 8;
7002
+ }
7003
+ if (left < 10) left = 10;
7004
+ if (top + tooltipHeight > window.innerHeight - 10) {
7005
+ top = e.clientY - tooltipHeight - 8;
7006
+ }
7007
+ if (top < 10) top = 10;
7008
+ container.style.left = left + "px";
7009
+ container.style.top = top + "px";
7010
+ }
7011
+ };
7012
+ element.addEventListener("mouseenter", handleMouseEnter);
7013
+ element.addEventListener("mouseleave", handleMouseLeave);
7014
+ element.addEventListener("mousemove", handleMouseMove);
7015
+ return () => {
7016
+ element.removeEventListener("mouseenter", handleMouseEnter);
7017
+ element.removeEventListener("mouseleave", handleMouseLeave);
7018
+ element.removeEventListener("mousemove", handleMouseMove);
7019
+ this.hide();
7020
+ };
6607
7021
  }
6608
7022
  };
7023
+
7024
+ // src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
7025
+ var LABEL_CHAR_LIMIT = 18;
7026
+ var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
7027
+ var CSS_TAG = "head-office-card-v1";
7028
+ function ensureCss() {
7029
+ if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
7030
+ const style = document.createElement("style");
7031
+ style.setAttribute("data-myio-css", CSS_TAG);
7032
+ style.textContent = CSS_STRING;
7033
+ document.head.appendChild(style);
7034
+ }
7035
+ }
7036
+ function normalizeParams(params) {
7037
+ if (!params || !params.entityObject) {
7038
+ throw new Error("renderCardCompenteHeadOffice: entityObject is required");
7039
+ }
7040
+ const LogHelper2 = createLogHelper(params.debugActive ?? false);
7041
+ const entityObject = params.entityObject;
7042
+ if (!entityObject.entityId) {
7043
+ LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
7044
+ entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
7045
+ }
7046
+ if (!params.delayTimeConnectionInMins) {
7047
+ LogHelper2.warn(
7048
+ `[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
7049
+ );
7050
+ }
7051
+ return {
7052
+ entityObject,
7053
+ i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
7054
+ enableSelection: Boolean(params.enableSelection),
7055
+ enableDragDrop: Boolean(params.enableDragDrop),
7056
+ useNewComponents: Boolean(params.useNewComponents),
7057
+ // RFC-0091: Configurable delay time for connection status check (default 15 minutes)
7058
+ delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
7059
+ // Debug options
7060
+ debugActive: params.debugActive ?? false,
7061
+ activeTooltipDebug: params.activeTooltipDebug ?? false,
7062
+ // LogHelper instance for this card
7063
+ LogHelper: LogHelper2,
7064
+ callbacks: {
7065
+ handleActionDashboard: params.handleActionDashboard,
7066
+ handleActionReport: params.handleActionReport,
7067
+ handleActionSettings: params.handleActionSettings,
7068
+ handleSelect: params.handleSelect,
7069
+ handInfo: params.handInfo,
7070
+ handleClickCard: params.handleClickCard
7071
+ }
7072
+ };
7073
+ }
7074
+ function getIconSvg(deviceType, domain) {
7075
+ if (domain === "water") {
7076
+ return Icons.waterDrop;
7077
+ }
7078
+ if (domain === "temperature") {
7079
+ return Icons.thermometer;
7080
+ }
7081
+ return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
7082
+ }
7083
+ function formatPower(valueInWatts) {
7084
+ if (valueInWatts === null || valueInWatts === void 0 || isNaN(valueInWatts)) {
7085
+ return { num: "-", unit: "" };
7086
+ }
7087
+ const val = Number(valueInWatts);
7088
+ if (val >= 1e3) {
7089
+ const kw = Math.ceil(val / 1e3 * 100) / 100;
7090
+ return { num: kw.toFixed(2), unit: "kW" };
7091
+ } else {
7092
+ const w = Math.ceil(val);
7093
+ return { num: w.toString(), unit: "W" };
7094
+ }
7095
+ }
7096
+ function formatValueByDomain(value, domain) {
7097
+ if (domain === "water") {
7098
+ return formatWaterVolumeM3(value);
7099
+ }
7100
+ if (domain === "temperature") {
7101
+ return formatTemperature(value, 0);
7102
+ }
7103
+ return formatEnergy(value);
7104
+ }
7105
+ function formatRelativeTime2(timestamp) {
7106
+ if (!timestamp || isNaN(timestamp)) return "\u2014";
7107
+ const date = new Date(timestamp);
7108
+ const hours = String(date.getHours()).padStart(2, "0");
7109
+ const minutes = String(date.getMinutes()).padStart(2, "0");
7110
+ const day = String(date.getDate()).padStart(2, "0");
7111
+ const month = String(date.getMonth() + 1).padStart(2, "0");
7112
+ const year = date.getFullYear();
7113
+ return `${hours}:${minutes} ${day}/${month}/${year}`;
7114
+ }
7115
+ function calculateConsumptionPercentage(target, consumption) {
7116
+ const numericTarget = Number(target);
7117
+ const numericConsumption = Number(consumption);
7118
+ if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
7119
+ return 0;
7120
+ }
7121
+ const percentage = numericConsumption / numericTarget * 100;
7122
+ return percentage;
7123
+ }
7124
+ function getStatusInfo(deviceStatus, i18n, domain) {
7125
+ switch (deviceStatus) {
7126
+ // --- Novos Status de Temperatura ---
7127
+ case "normal":
7128
+ return { chipClass: "chip--ok", label: "Normal" };
7129
+ case "cold":
7130
+ return { chipClass: "chip--standby", label: "Frio" };
7131
+ case "hot":
7132
+ return { chipClass: "chip--alert", label: "Quente" };
7133
+ // --- Status Existentes (aligned with getCardStateClass) ---
7134
+ case DeviceStatusType.POWER_ON:
7135
+ if (domain === "water") {
7136
+ return { chipClass: "chip--power-on", label: i18n.in_operation_water };
7137
+ }
7138
+ return { chipClass: "chip--power-on", label: i18n.in_operation };
7139
+ case DeviceStatusType.STANDBY:
7140
+ return { chipClass: "chip--standby", label: i18n.standby };
7141
+ case DeviceStatusType.WARNING:
7142
+ return { chipClass: "chip--warning", label: i18n.alert };
7143
+ case DeviceStatusType.MAINTENANCE:
7144
+ return { chipClass: "chip--maintenance", label: i18n.maintenance };
7145
+ case DeviceStatusType.FAILURE:
7146
+ return { chipClass: "chip--failure", label: i18n.failure };
7147
+ case DeviceStatusType.POWER_OFF:
7148
+ return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
7149
+ case DeviceStatusType.OFFLINE:
7150
+ return { chipClass: "chip--offline", label: i18n.offline };
7151
+ case DeviceStatusType.NO_INFO:
7152
+ return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
7153
+ case DeviceStatusType.NOT_INSTALLED:
7154
+ return { chipClass: "chip--not-installed", label: i18n.not_installed };
7155
+ default:
7156
+ return { chipClass: "chip--offline", label: i18n.offline };
7157
+ }
7158
+ }
7159
+ function getCardStateClass(deviceStatus) {
7160
+ switch (deviceStatus) {
7161
+ case DeviceStatusType.POWER_ON:
7162
+ return "is-power-on";
7163
+ // Blue border
7164
+ case DeviceStatusType.STANDBY:
7165
+ return "is-standby";
7166
+ // Green border
7167
+ case DeviceStatusType.WARNING:
7168
+ return "is-warning";
7169
+ // Yellow border
7170
+ case DeviceStatusType.MAINTENANCE:
7171
+ return "is-maintenance";
7172
+ // Yellow border
7173
+ case DeviceStatusType.FAILURE:
7174
+ return "is-failure";
7175
+ // Dark Red border
7176
+ case DeviceStatusType.POWER_OFF:
7177
+ return "is-power-off";
7178
+ // Light Red border
7179
+ case DeviceStatusType.OFFLINE:
7180
+ return "is-offline";
7181
+ // Dark Gray border
7182
+ case DeviceStatusType.NO_INFO:
7183
+ return "is-no-info";
7184
+ // Dark Orange border
7185
+ case DeviceStatusType.NOT_INSTALLED:
7186
+ return "is-not-installed";
7187
+ // Purple border
7188
+ default:
7189
+ return "";
7190
+ }
7191
+ }
7192
+ function getTempRangeClass(entityObject) {
7193
+ if (entityObject.domain !== "temperature") return "";
7194
+ const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
7195
+ const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
7196
+ const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
7197
+ if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
7198
+ return "";
7199
+ }
7200
+ if (currentTemp > tempMax) return "is-temp-hot";
7201
+ if (currentTemp < tempMin) return "is-temp-cold";
7202
+ return "is-temp-ok";
7203
+ }
6609
7204
  function getStatusDotClass(deviceStatus) {
6610
7205
  switch (deviceStatus) {
6611
7206
  // --- Novos Status de Temperatura ---
@@ -7131,29 +7726,34 @@ function bindEvents(root, state, callbacks) {
7131
7726
  MyIOSelectionStore2.on("selection:change", onSelectionChange);
7132
7727
  root._selectionListener = onSelectionChange;
7133
7728
  }
7134
- if (entityObject.domain === "temperature") {
7729
+ const valueElement = root.querySelector(".myio-ho-card__value");
7730
+ if (entityObject.domain === "temperature" && valueElement) {
7135
7731
  const showTooltip = (e) => {
7136
7732
  TempRangeTooltip.show(root, state.entityObject, e);
7137
7733
  };
7138
7734
  const hideTooltip = () => {
7139
7735
  TempRangeTooltip.hide();
7140
7736
  };
7141
- root.addEventListener("mouseenter", showTooltip);
7142
- root.addEventListener("mouseleave", hideTooltip);
7737
+ valueElement.style.cursor = "help";
7738
+ valueElement.addEventListener("mouseenter", showTooltip);
7739
+ valueElement.addEventListener("mouseleave", hideTooltip);
7143
7740
  root._tempTooltipShowFn = showTooltip;
7144
7741
  root._tempTooltipHideFn = hideTooltip;
7742
+ root._tooltipElement = valueElement;
7145
7743
  }
7146
- if (entityObject.domain === "energy") {
7744
+ if (entityObject.domain === "energy" && valueElement) {
7147
7745
  const showEnergyTooltip = (e) => {
7148
7746
  EnergyRangeTooltip.show(root, state.entityObject, e);
7149
7747
  };
7150
7748
  const hideEnergyTooltip = () => {
7151
7749
  EnergyRangeTooltip.hide();
7152
7750
  };
7153
- root.addEventListener("mouseenter", showEnergyTooltip);
7154
- root.addEventListener("mouseleave", hideEnergyTooltip);
7751
+ valueElement.style.cursor = "help";
7752
+ valueElement.addEventListener("mouseenter", showEnergyTooltip);
7753
+ valueElement.addEventListener("mouseleave", hideEnergyTooltip);
7155
7754
  root._energyTooltipShowFn = showEnergyTooltip;
7156
7755
  root._energyTooltipHideFn = hideEnergyTooltip;
7756
+ root._tooltipElement = valueElement;
7157
7757
  }
7158
7758
  root._cleanup = () => {
7159
7759
  document.removeEventListener("click", closeMenu);
@@ -7161,14 +7761,14 @@ function bindEvents(root, state, callbacks) {
7161
7761
  if (MyIOSelectionStore2 && root._selectionListener) {
7162
7762
  MyIOSelectionStore2.off("selection:change", root._selectionListener);
7163
7763
  }
7164
- if (root._tempTooltipShowFn) {
7165
- root.removeEventListener("mouseenter", root._tempTooltipShowFn);
7166
- root.removeEventListener("mouseleave", root._tempTooltipHideFn);
7764
+ if (root._tempTooltipShowFn && root._tooltipElement) {
7765
+ root._tooltipElement.removeEventListener("mouseenter", root._tempTooltipShowFn);
7766
+ root._tooltipElement.removeEventListener("mouseleave", root._tempTooltipHideFn);
7167
7767
  TempRangeTooltip.hide();
7168
7768
  }
7169
- if (root._energyTooltipShowFn) {
7170
- root.removeEventListener("mouseenter", root._energyTooltipShowFn);
7171
- root.removeEventListener("mouseleave", root._energyTooltipHideFn);
7769
+ if (root._energyTooltipShowFn && root._tooltipElement) {
7770
+ root._tooltipElement.removeEventListener("mouseenter", root._energyTooltipShowFn);
7771
+ root._tooltipElement.removeEventListener("mouseleave", root._energyTooltipHideFn);
7172
7772
  EnergyRangeTooltip.hide();
7173
7773
  }
7174
7774
  };
@@ -7721,6 +8321,7 @@ function renderCardComponentV5({
7721
8321
  };
7722
8322
  const isTankDevice = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
7723
8323
  const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
8324
+ const isEnergyDeviceFlag = isEnergyDevice(deviceType);
7724
8325
  const percentageForDisplay = isTankDevice ? (waterPercentage || 0) * 100 : perc;
7725
8326
  const calculateTempStatus = () => {
7726
8327
  if (temperatureStatus) return temperatureStatus;
@@ -7737,33 +8338,6 @@ function renderCardComponentV5({
7737
8338
  tempStatus,
7738
8339
  isOffline
7739
8340
  });
7740
- const getTemperatureTooltip = () => {
7741
- if (!isTermostatoDevice) return "";
7742
- const currentTemp = Number(val) || 0;
7743
- const hasRange = temperatureMin !== void 0 && temperatureMax !== void 0 && temperatureMin !== null && temperatureMax !== null;
7744
- if (isOffline) {
7745
- return "Dispositivo offline";
7746
- }
7747
- if (!hasRange) {
7748
- return `Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7749
- Faixa n\xE3o configurada`;
7750
- }
7751
- const rangeText = `Faixa ideal: ${temperatureMin}\xB0C a ${temperatureMax}\xB0C`;
7752
- if (tempStatus === "above") {
7753
- return `ACIMA da faixa ideal
7754
- Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7755
- ${rangeText}`;
7756
- } else if (tempStatus === "below") {
7757
- return `ABAIXO da faixa ideal
7758
- Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7759
- ${rangeText}`;
7760
- } else {
7761
- return `DENTRO da faixa ideal
7762
- Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7763
- ${rangeText}`;
7764
- }
7765
- };
7766
- const temperatureTooltip = getTemperatureTooltip();
7767
8341
  const cardHTML = `
7768
8342
  <div class="device-card-centered clickable ${cardEntity.status === "offline" ? "offline" : ""}"
7769
8343
  data-entity-id="${entityId}"
@@ -7789,7 +8363,7 @@ ${rangeText}`;
7789
8363
  ` : ""}
7790
8364
  </div>
7791
8365
 
7792
- <img class="device-image" src="${deviceImageUrl}" alt="${deviceType}" ${isTermostatoDevice && temperatureTooltip ? `title="${temperatureTooltip}"` : ""} style="${isTermostatoDevice ? "cursor: help;" : ""}" />
8366
+ <img class="device-image ${isTermostatoDevice ? "temp-tooltip-trigger" : ""}${isEnergyDeviceFlag ? " energy-tooltip-trigger" : ""}" src="${deviceImageUrl}" alt="${deviceType}" style="${isTermostatoDevice || isEnergyDeviceFlag ? "cursor: help;" : ""}" />
7793
8367
 
7794
8368
 
7795
8369
  ${customerName && String(customerName).trim() !== "" ? `
@@ -8353,6 +8927,33 @@ ${rangeText}`;
8353
8927
  }
8354
8928
  });
8355
8929
  }
8930
+ const tempTooltipTrigger = enhancedCardElement.querySelector(".temp-tooltip-trigger");
8931
+ let tempTooltipCleanup = null;
8932
+ if (tempTooltipTrigger && isTermostatoDevice) {
8933
+ const tooltipEntityData = {
8934
+ val,
8935
+ temperatureMin,
8936
+ temperatureMax,
8937
+ labelOrName: cardEntity.name,
8938
+ name: cardEntity.name
8939
+ };
8940
+ tempTooltipCleanup = TempRangeTooltip.attach(tempTooltipTrigger, tooltipEntityData);
8941
+ }
8942
+ const energyTooltipTrigger = enhancedCardElement.querySelector(".energy-tooltip-trigger");
8943
+ let energyTooltipCleanup = null;
8944
+ if (energyTooltipTrigger && isEnergyDeviceFlag) {
8945
+ const energyTooltipData = {
8946
+ labelOrName: cardEntity.name,
8947
+ name: cardEntity.name,
8948
+ instantaneousPower: entityObject.instantaneousPower ?? entityObject.consumption_power ?? val,
8949
+ powerRanges: entityObject.powerRanges || entityObject.ranges
8950
+ };
8951
+ energyTooltipCleanup = EnergyRangeTooltip.attach(energyTooltipTrigger, energyTooltipData);
8952
+ }
8953
+ container._cleanup = () => {
8954
+ if (tempTooltipCleanup) tempTooltipCleanup();
8955
+ if (energyTooltipCleanup) energyTooltipCleanup();
8956
+ };
8356
8957
  const jQueryLikeObject = {
8357
8958
  get: (index) => index === 0 ? container : void 0,
8358
8959
  0: container,
@@ -11337,7 +11938,7 @@ var chartJsLoaded = false;
11337
11938
  var zoomPluginLoaded = false;
11338
11939
  var jsPdfLoaded = false;
11339
11940
  var _jspdfPromise = null;
11340
- var cssInjected = false;
11941
+ var cssInjected2 = false;
11341
11942
  var STRINGS2 = {
11342
11943
  "pt-BR": {
11343
11944
  title: "Demanda",
@@ -11513,8 +12114,8 @@ function ensureRoom(doc, nextY, minRoom = 40) {
11513
12114
  }
11514
12115
  return nextY;
11515
12116
  }
11516
- function injectCSS(styles) {
11517
- if (cssInjected) return;
12117
+ function injectCSS2(styles) {
12118
+ if (cssInjected2) return;
11518
12119
  const css = `
11519
12120
  .myio-demand-modal-overlay {
11520
12121
  position: fixed;
@@ -11909,7 +12510,7 @@ function injectCSS(styles) {
11909
12510
  const style = document.createElement("style");
11910
12511
  style.textContent = css;
11911
12512
  document.head.appendChild(style);
11912
- cssInjected = true;
12513
+ cssInjected2 = true;
11913
12514
  }
11914
12515
  function formatDate2(date, locale) {
11915
12516
  return date.toLocaleDateString(locale, {
@@ -12091,7 +12692,7 @@ async function openDemandModal(params) {
12091
12692
  const locale = params.locale || "pt-BR";
12092
12693
  const strings = STRINGS2[locale] || STRINGS2["pt-BR"];
12093
12694
  await loadExternalLibraries();
12094
- injectCSS(styles);
12695
+ injectCSS2(styles);
12095
12696
  const container = typeof params.container === "string" ? document.querySelector(params.container) : params.container || document.body;
12096
12697
  if (!container) {
12097
12698
  throw new Error("Container element not found");
@@ -21740,7 +22341,7 @@ async function createInputDateRangePickerInsideDIV(params) {
21740
22341
  placeholder = "Clique para selecionar per\xEDodo",
21741
22342
  pickerOptions = {},
21742
22343
  classNames = {},
21743
- injectStyles = true,
22344
+ injectStyles: injectStyles2 = true,
21744
22345
  showHelper = true
21745
22346
  } = params;
21746
22347
  validateId(containerId, "containerId");
@@ -21749,7 +22350,7 @@ async function createInputDateRangePickerInsideDIV(params) {
21749
22350
  if (!container) {
21750
22351
  throw new Error(`[createInputDateRangePickerInsideDIV] Container '#${containerId}' not found`);
21751
22352
  }
21752
- if (injectStyles) {
22353
+ if (injectStyles2) {
21753
22354
  injectPremiumStyles();
21754
22355
  }
21755
22356
  let inputEl = document.getElementById(inputId);
@@ -21944,7 +22545,7 @@ function openGoalsPanel(params) {
21944
22545
  modal.setAttribute("aria-labelledby", "goals-modal-title");
21945
22546
  modal.innerHTML = generateModalHTML();
21946
22547
  document.body.appendChild(modal);
21947
- injectStyles();
22548
+ injectStyles2();
21948
22549
  attachEventListeners();
21949
22550
  trapFocus(modal);
21950
22551
  renderTabContent();
@@ -22697,7 +23298,7 @@ function openGoalsPanel(params) {
22697
23298
  maximumFractionDigits: 2
22698
23299
  }).format(value);
22699
23300
  }
22700
- function injectStyles() {
23301
+ function injectStyles2() {
22701
23302
  const styleId = "myio-goals-panel-styles";
22702
23303
  if (document.getElementById(styleId)) return;
22703
23304
  const style = document.createElement("style");
@@ -24954,7 +25555,7 @@ var LIGHT_THEME2 = {
24954
25555
  function getColors(theme) {
24955
25556
  return theme === "dark" ? DARK_THEME2 : LIGHT_THEME2;
24956
25557
  }
24957
- async function fetchCustomerAttributes(customerId, token) {
25558
+ async function fetchCustomerAttributes(customerId, token, onError) {
24958
25559
  const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/values/attributes/SERVER_SCOPE`;
24959
25560
  const response = await fetch(url, {
24960
25561
  method: "GET",
@@ -24967,6 +25568,10 @@ async function fetchCustomerAttributes(customerId, token) {
24967
25568
  if (response.status === 404 || response.status === 400) {
24968
25569
  return { minTemperature: null, maxTemperature: null };
24969
25570
  }
25571
+ if (onError) {
25572
+ onError({ status: response.status, message: `Failed to fetch attributes: ${response.status}` });
25573
+ return { minTemperature: null, maxTemperature: null };
25574
+ }
24970
25575
  throw new Error(`Failed to fetch attributes: ${response.status}`);
24971
25576
  }
24972
25577
  const attributes = await response.json();
@@ -24983,7 +25588,7 @@ async function fetchCustomerAttributes(customerId, token) {
24983
25588
  }
24984
25589
  return { minTemperature, maxTemperature };
24985
25590
  }
24986
- async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature) {
25591
+ async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature, onError) {
24987
25592
  const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/SERVER_SCOPE`;
24988
25593
  const attributes = {
24989
25594
  minTemperature,
@@ -24998,6 +25603,10 @@ async function saveCustomerAttributes(customerId, token, minTemperature, maxTemp
24998
25603
  body: JSON.stringify(attributes)
24999
25604
  });
25000
25605
  if (!response.ok) {
25606
+ if (onError) {
25607
+ onError({ status: response.status, message: `Failed to save attributes: ${response.status}` });
25608
+ return;
25609
+ }
25001
25610
  throw new Error(`Failed to save attributes: ${response.status}`);
25002
25611
  }
25003
25612
  }
@@ -25414,7 +26023,7 @@ function openTemperatureSettingsModal(params) {
25414
26023
  state.successMessage = null;
25415
26024
  renderModal3(container, state, modalId, destroy, handleSave);
25416
26025
  try {
25417
- await saveCustomerAttributes(state.customerId, state.token, min, max);
26026
+ await saveCustomerAttributes(state.customerId, state.token, min, max, params.onError);
25418
26027
  state.minTemperature = min;
25419
26028
  state.maxTemperature = max;
25420
26029
  state.isSaving = false;
@@ -25431,7 +26040,7 @@ function openTemperatureSettingsModal(params) {
25431
26040
  }
25432
26041
  };
25433
26042
  renderModal3(container, state, modalId, destroy, handleSave);
25434
- fetchCustomerAttributes(state.customerId, state.token).then(({ minTemperature, maxTemperature }) => {
26043
+ fetchCustomerAttributes(state.customerId, state.token, params.onError).then(({ minTemperature, maxTemperature }) => {
25435
26044
  state.minTemperature = minTemperature;
25436
26045
  state.maxTemperature = maxTemperature;
25437
26046
  state.isLoading = false;
@@ -27592,7 +28201,7 @@ function createConsumptionChartWidget(config) {
27592
28201
  </div>
27593
28202
  `;
27594
28203
  }
27595
- function injectStyles() {
28204
+ function injectStyles2() {
27596
28205
  if (styleElement) return;
27597
28206
  styleElement = document.createElement("style");
27598
28207
  styleElement.id = `${widgetId}-styles`;
@@ -28074,7 +28683,7 @@ function createConsumptionChartWidget(config) {
28074
28683
  console.error(`[ConsumptionWidget] Container #${config.containerId} not found`);
28075
28684
  return;
28076
28685
  }
28077
- injectStyles();
28686
+ injectStyles2();
28078
28687
  containerElement.innerHTML = renderHTML();
28079
28688
  setupListeners();
28080
28689
  setLoading(true);
@@ -29214,6 +29823,7 @@ function createDistributionChartWidget(config) {
29214
29823
  EXPORT_DOMAIN_ICONS,
29215
29824
  EXPORT_DOMAIN_LABELS,
29216
29825
  EXPORT_DOMAIN_UNITS,
29826
+ EnergyRangeTooltip,
29217
29827
  MyIOChartModal,
29218
29828
  MyIODraggableCard,
29219
29829
  MyIOSelectionStore,
@@ -29222,6 +29832,7 @@ function createDistributionChartWidget(config) {
29222
29832
  POWER_LIMITS_DEVICE_TYPES,
29223
29833
  POWER_LIMITS_STATUS_CONFIG,
29224
29834
  POWER_LIMITS_TELEMETRY_TYPES,
29835
+ TempRangeTooltip,
29225
29836
  addDetectionContext,
29226
29837
  addNamespace,
29227
29838
  aggregateByDay,