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.
@@ -5910,185 +5910,253 @@
5910
5910
  };
5911
5911
  }
5912
5912
 
5913
- // src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
5914
- var LABEL_CHAR_LIMIT = 18;
5915
- var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
5916
- var CSS_TAG = "head-office-card-v1";
5917
- function ensureCss() {
5918
- if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
5919
- const style = document.createElement("style");
5920
- style.setAttribute("data-myio-css", CSS_TAG);
5921
- style.textContent = CSS_STRING;
5922
- document.head.appendChild(style);
5923
- }
5924
- }
5925
- function normalizeParams(params) {
5926
- if (!params || !params.entityObject) {
5927
- throw new Error("renderCardCompenteHeadOffice: entityObject is required");
5928
- }
5929
- const LogHelper2 = createLogHelper(params.debugActive ?? false);
5930
- const entityObject = params.entityObject;
5931
- if (!entityObject.entityId) {
5932
- LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
5933
- entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
5934
- }
5935
- if (!params.delayTimeConnectionInMins) {
5936
- LogHelper2.warn(
5937
- `[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
5938
- );
5939
- }
5940
- return {
5941
- entityObject,
5942
- i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
5943
- enableSelection: Boolean(params.enableSelection),
5944
- enableDragDrop: Boolean(params.enableDragDrop),
5945
- useNewComponents: Boolean(params.useNewComponents),
5946
- // RFC-0091: Configurable delay time for connection status check (default 15 minutes)
5947
- delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
5948
- // Debug options
5949
- debugActive: params.debugActive ?? false,
5950
- activeTooltipDebug: params.activeTooltipDebug ?? false,
5951
- // LogHelper instance for this card
5952
- LogHelper: LogHelper2,
5953
- callbacks: {
5954
- handleActionDashboard: params.handleActionDashboard,
5955
- handleActionReport: params.handleActionReport,
5956
- handleActionSettings: params.handleActionSettings,
5957
- handleSelect: params.handleSelect,
5958
- handInfo: params.handInfo,
5959
- handleClickCard: params.handleClickCard
5960
- }
5961
- };
5962
- }
5963
- function getIconSvg(deviceType, domain) {
5964
- if (domain === "water") {
5965
- return Icons.waterDrop;
5966
- }
5967
- if (domain === "temperature") {
5968
- return Icons.thermometer;
5969
- }
5970
- return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
5971
- }
5972
- function formatPower(valueInWatts) {
5973
- if (valueInWatts === null || valueInWatts === void 0 || isNaN(valueInWatts)) {
5974
- return { num: "-", unit: "" };
5975
- }
5976
- const val = Number(valueInWatts);
5977
- if (val >= 1e3) {
5978
- const kw = Math.ceil(val / 1e3 * 100) / 100;
5979
- return { num: kw.toFixed(2), unit: "kW" };
5980
- } else {
5981
- const w = Math.ceil(val);
5982
- return { num: w.toString(), unit: "W" };
5983
- }
5984
- }
5985
- function formatValueByDomain(value, domain) {
5986
- if (domain === "water") {
5987
- return formatWaterVolumeM3(value);
5988
- }
5989
- if (domain === "temperature") {
5990
- return formatTemperature(value, 0);
5991
- }
5992
- return formatEnergy(value);
5993
- }
5994
- function formatRelativeTime2(timestamp) {
5995
- if (!timestamp || isNaN(timestamp)) return "\u2014";
5996
- const date = new Date(timestamp);
5997
- const hours = String(date.getHours()).padStart(2, "0");
5998
- const minutes = String(date.getMinutes()).padStart(2, "0");
5999
- const day = String(date.getDate()).padStart(2, "0");
6000
- const month = String(date.getMonth() + 1).padStart(2, "0");
6001
- const year = date.getFullYear();
6002
- return `${hours}:${minutes} ${day}/${month}/${year}`;
6003
- }
6004
- function calculateConsumptionPercentage(target, consumption) {
6005
- const numericTarget = Number(target);
6006
- const numericConsumption = Number(consumption);
6007
- if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
6008
- return 0;
6009
- }
6010
- const percentage = numericConsumption / numericTarget * 100;
6011
- return percentage;
5913
+ // src/utils/TempRangeTooltip.ts
5914
+ var TOOLTIP_STYLES = `
5915
+ .temp-range-tooltip {
5916
+ position: fixed;
5917
+ z-index: 99999;
5918
+ pointer-events: none;
5919
+ opacity: 0;
5920
+ transition: opacity 0.2s ease, transform 0.2s ease;
5921
+ transform: translateY(5px);
5922
+ }
5923
+
5924
+ .temp-range-tooltip.visible {
5925
+ opacity: 1;
5926
+ pointer-events: auto;
5927
+ transform: translateY(0);
5928
+ }
5929
+
5930
+ .temp-range-tooltip__content {
5931
+ background: #ffffff;
5932
+ border: 1px solid #e2e8f0;
5933
+ border-radius: 12px;
5934
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
5935
+ min-width: 280px;
5936
+ max-width: 320px;
5937
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
5938
+ font-size: 12px;
5939
+ color: #1e293b;
5940
+ overflow: hidden;
5941
+ }
5942
+
5943
+ .temp-range-tooltip__header {
5944
+ display: flex;
5945
+ align-items: center;
5946
+ gap: 8px;
5947
+ padding: 12px 16px;
5948
+ background: linear-gradient(90deg, #fff7ed 0%, #fed7aa 100%);
5949
+ border-bottom: 1px solid #fdba74;
5950
+ }
5951
+
5952
+ .temp-range-tooltip__icon {
5953
+ font-size: 18px;
5954
+ }
5955
+
5956
+ .temp-range-tooltip__title {
5957
+ font-weight: 700;
5958
+ font-size: 13px;
5959
+ color: #c2410c;
5960
+ }
5961
+
5962
+ .temp-range-tooltip__body {
5963
+ padding: 16px;
5964
+ }
5965
+
5966
+ .temp-range-tooltip__value-row {
5967
+ display: flex;
5968
+ justify-content: space-between;
5969
+ align-items: center;
5970
+ margin-bottom: 16px;
5971
+ }
5972
+
5973
+ .temp-range-tooltip__current {
5974
+ font-size: 28px;
5975
+ font-weight: 700;
5976
+ color: #1e293b;
5977
+ }
5978
+
5979
+ .temp-range-tooltip__current sup {
5980
+ font-size: 14px;
5981
+ color: #64748b;
5982
+ }
5983
+
5984
+ .temp-range-tooltip__deviation {
5985
+ text-align: right;
5986
+ }
5987
+
5988
+ .temp-range-tooltip__deviation-value {
5989
+ font-size: 16px;
5990
+ font-weight: 700;
5991
+ }
5992
+
5993
+ .temp-range-tooltip__deviation-value.cold {
5994
+ color: #2563eb;
5995
+ }
5996
+
5997
+ .temp-range-tooltip__deviation-value.ok {
5998
+ color: #16a34a;
5999
+ }
6000
+
6001
+ .temp-range-tooltip__deviation-value.hot {
6002
+ color: #dc2626;
6003
+ }
6004
+
6005
+ .temp-range-tooltip__deviation-label {
6006
+ font-size: 10px;
6007
+ color: #64748b;
6008
+ text-transform: uppercase;
6009
+ letter-spacing: 0.5px;
6010
+ }
6011
+
6012
+ .temp-range-tooltip__ruler {
6013
+ position: relative;
6014
+ height: 32px;
6015
+ margin: 12px 0;
6016
+ border-radius: 8px;
6017
+ overflow: visible;
6018
+ }
6019
+
6020
+ .temp-range-tooltip__ruler-track {
6021
+ position: absolute;
6022
+ top: 12px;
6023
+ left: 0;
6024
+ right: 0;
6025
+ height: 8px;
6026
+ background: linear-gradient(90deg, #dbeafe 0%, #dcfce7 50%, #fee2e2 100%);
6027
+ border-radius: 4px;
6028
+ border: 1px solid #e2e8f0;
6029
+ }
6030
+
6031
+ .temp-range-tooltip__ruler-range {
6032
+ position: absolute;
6033
+ top: 12px;
6034
+ height: 8px;
6035
+ background: #22c55e;
6036
+ border-radius: 4px;
6037
+ opacity: 0.6;
6038
+ }
6039
+
6040
+ .temp-range-tooltip__ruler-marker {
6041
+ position: absolute;
6042
+ top: 4px;
6043
+ width: 4px;
6044
+ height: 24px;
6045
+ background: #1e293b;
6046
+ border-radius: 2px;
6047
+ transform: translateX(-50%);
6048
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6049
+ }
6050
+
6051
+ .temp-range-tooltip__ruler-marker::after {
6052
+ content: '';
6053
+ position: absolute;
6054
+ top: -4px;
6055
+ left: 50%;
6056
+ transform: translateX(-50%);
6057
+ width: 12px;
6058
+ height: 12px;
6059
+ background: #1e293b;
6060
+ border-radius: 50%;
6061
+ border: 2px solid #fff;
6062
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6063
+ }
6064
+
6065
+ .temp-range-tooltip__ruler-labels {
6066
+ display: flex;
6067
+ justify-content: space-between;
6068
+ margin-top: 8px;
6069
+ font-size: 10px;
6070
+ color: #64748b;
6071
+ }
6072
+
6073
+ .temp-range-tooltip__ruler-min,
6074
+ .temp-range-tooltip__ruler-max {
6075
+ font-weight: 600;
6076
+ }
6077
+
6078
+ .temp-range-tooltip__range-info {
6079
+ display: flex;
6080
+ justify-content: space-between;
6081
+ padding: 10px 12px;
6082
+ background: #f8fafc;
6083
+ border-radius: 8px;
6084
+ margin-top: 12px;
6085
+ }
6086
+
6087
+ .temp-range-tooltip__range-item {
6088
+ text-align: center;
6089
+ }
6090
+
6091
+ .temp-range-tooltip__range-label {
6092
+ font-size: 10px;
6093
+ color: #64748b;
6094
+ text-transform: uppercase;
6095
+ letter-spacing: 0.3px;
6096
+ margin-bottom: 2px;
6097
+ }
6098
+
6099
+ .temp-range-tooltip__range-value {
6100
+ font-size: 14px;
6101
+ font-weight: 600;
6102
+ color: #334155;
6103
+ }
6104
+
6105
+ .temp-range-tooltip__status {
6106
+ display: flex;
6107
+ align-items: center;
6108
+ justify-content: center;
6109
+ gap: 6px;
6110
+ margin-top: 12px;
6111
+ padding: 8px 12px;
6112
+ border-radius: 6px;
6113
+ font-size: 11px;
6114
+ font-weight: 600;
6115
+ }
6116
+
6117
+ .temp-range-tooltip__status.cold {
6118
+ background: #dbeafe;
6119
+ color: #1d4ed8;
6120
+ border: 1px solid #93c5fd;
6121
+ }
6122
+
6123
+ .temp-range-tooltip__status.ok {
6124
+ background: #dcfce7;
6125
+ color: #15803d;
6126
+ border: 1px solid #86efac;
6127
+ }
6128
+
6129
+ .temp-range-tooltip__status.hot {
6130
+ background: #fee2e2;
6131
+ color: #b91c1c;
6132
+ border: 1px solid #fca5a5;
6133
+ }
6134
+
6135
+ .temp-range-tooltip__status.unknown {
6136
+ background: #f3f4f6;
6137
+ color: #6b7280;
6138
+ border: 1px solid #d1d5db;
6139
+ }
6140
+ `;
6141
+ function injectStyles() {
6142
+ if (typeof document === "undefined") return;
6143
+ const styleId = "myio-temp-range-tooltip-styles";
6144
+ if (document.getElementById(styleId)) return;
6145
+ const style = document.createElement("style");
6146
+ style.id = styleId;
6147
+ style.textContent = TOOLTIP_STYLES;
6148
+ document.head.appendChild(style);
6012
6149
  }
6013
- function getStatusInfo(deviceStatus, i18n, domain) {
6014
- switch (deviceStatus) {
6015
- // --- Novos Status de Temperatura ---
6016
- case "normal":
6017
- return { chipClass: "chip--ok", label: "Normal" };
6018
- case "cold":
6019
- return { chipClass: "chip--standby", label: "Frio" };
6020
- case "hot":
6021
- return { chipClass: "chip--alert", label: "Quente" };
6022
- // --- Status Existentes (aligned with getCardStateClass) ---
6023
- case DeviceStatusType.POWER_ON:
6024
- if (domain === "water") {
6025
- return { chipClass: "chip--power-on", label: i18n.in_operation_water };
6026
- }
6027
- return { chipClass: "chip--power-on", label: i18n.in_operation };
6028
- case DeviceStatusType.STANDBY:
6029
- return { chipClass: "chip--standby", label: i18n.standby };
6030
- case DeviceStatusType.WARNING:
6031
- return { chipClass: "chip--warning", label: i18n.alert };
6032
- case DeviceStatusType.MAINTENANCE:
6033
- return { chipClass: "chip--maintenance", label: i18n.maintenance };
6034
- case DeviceStatusType.FAILURE:
6035
- return { chipClass: "chip--failure", label: i18n.failure };
6036
- case DeviceStatusType.POWER_OFF:
6037
- return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
6038
- case DeviceStatusType.OFFLINE:
6039
- return { chipClass: "chip--offline", label: i18n.offline };
6040
- case DeviceStatusType.NO_INFO:
6041
- return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
6042
- case DeviceStatusType.NOT_INSTALLED:
6043
- return { chipClass: "chip--not-installed", label: i18n.not_installed };
6044
- default:
6045
- return { chipClass: "chip--offline", label: i18n.offline };
6046
- }
6150
+ function extractTemperature(entityData) {
6151
+ return Number(entityData.val ?? entityData.currentTemperature ?? entityData.temperature) || 0;
6047
6152
  }
6048
- function getCardStateClass(deviceStatus) {
6049
- switch (deviceStatus) {
6050
- case DeviceStatusType.POWER_ON:
6051
- return "is-power-on";
6052
- // Blue border
6053
- case DeviceStatusType.STANDBY:
6054
- return "is-standby";
6055
- // Green border
6056
- case DeviceStatusType.WARNING:
6057
- return "is-warning";
6058
- // Yellow border
6059
- case DeviceStatusType.MAINTENANCE:
6060
- return "is-maintenance";
6061
- // Yellow border
6062
- case DeviceStatusType.FAILURE:
6063
- return "is-failure";
6064
- // Dark Red border
6065
- case DeviceStatusType.POWER_OFF:
6066
- return "is-power-off";
6067
- // Light Red border
6068
- case DeviceStatusType.OFFLINE:
6069
- return "is-offline";
6070
- // Dark Gray border
6071
- case DeviceStatusType.NO_INFO:
6072
- return "is-no-info";
6073
- // Dark Orange border
6074
- case DeviceStatusType.NOT_INSTALLED:
6075
- return "is-not-installed";
6076
- // Purple border
6077
- default:
6078
- return "";
6079
- }
6153
+ function extractRange(entityData) {
6154
+ const tempMin = entityData.temperatureMin ?? entityData.minTemperature ?? null;
6155
+ const tempMax = entityData.temperatureMax ?? entityData.maxTemperature ?? null;
6156
+ return { tempMin, tempMax };
6080
6157
  }
6081
- function getTempRangeClass(entityObject) {
6082
- if (entityObject.domain !== "temperature") return "";
6083
- const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
6084
- const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
6085
- const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
6086
- if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
6087
- return "";
6088
- }
6089
- if (currentTemp > tempMax) return "is-temp-hot";
6090
- if (currentTemp < tempMin) return "is-temp-cold";
6091
- return "is-temp-ok";
6158
+ function extractLabel(entityData) {
6159
+ return entityData.labelOrName || entityData.name || entityData.label || "Sensor";
6092
6160
  }
6093
6161
  var TempRangeTooltip = {
6094
6162
  containerId: "myio-temp-range-tooltip",
@@ -6096,6 +6164,7 @@
6096
6164
  * Create or get the tooltip container
6097
6165
  */
6098
6166
  getContainer() {
6167
+ injectStyles();
6099
6168
  let container = document.getElementById(this.containerId);
6100
6169
  if (!container) {
6101
6170
  container = document.createElement("div");
@@ -6143,20 +6212,20 @@
6143
6212
  },
6144
6213
  /**
6145
6214
  * Show tooltip for a temperature card
6146
- * @param {HTMLElement} triggerElement - The card element
6147
- * @param {Object} entityObject - Entity data
6148
- * @param {MouseEvent} event - Mouse event for cursor position
6215
+ * @param triggerElement - The card element
6216
+ * @param entityData - Entity data with temperature info
6217
+ * @param event - Mouse event for cursor position
6149
6218
  */
6150
- show(triggerElement, entityObject, event) {
6219
+ show(triggerElement, entityData, event) {
6151
6220
  const container = this.getContainer();
6152
- const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
6153
- const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
6154
- const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
6221
+ const currentTemp = extractTemperature(entityData);
6222
+ const { tempMin, tempMax } = extractRange(entityData);
6223
+ const label = extractLabel(entityData);
6155
6224
  const hasRange = tempMin != null && tempMax != null;
6156
- const { status, deviation, deviationPercent } = this.calculateStatus(currentTemp, tempMin, tempMax);
6225
+ const { status, deviationPercent } = this.calculateStatus(currentTemp, tempMin, tempMax);
6157
6226
  const markerPos = this.calculateMarkerPosition(currentTemp, tempMin, tempMax);
6158
6227
  let rangeLeft = 0, rangeWidth = 100;
6159
- if (hasRange) {
6228
+ if (hasRange && tempMin != null && tempMax != null) {
6160
6229
  const rangeSize = tempMax - tempMin;
6161
6230
  const extension = rangeSize * 0.3;
6162
6231
  const visibleMin = tempMin - extension;
@@ -6165,23 +6234,23 @@
6165
6234
  rangeLeft = (tempMin - visibleMin) / visibleRange * 100;
6166
6235
  rangeWidth = rangeSize / visibleRange * 100;
6167
6236
  }
6168
- let deviationClass = status;
6169
- if (status === "cold") {
6170
- `${Math.abs(deviation).toFixed(1)}\xB0C abaixo`;
6171
- } else if (status === "hot") {
6172
- `+${deviation.toFixed(1)}\xB0C acima`;
6173
- } else ;
6174
6237
  const statusLabels = {
6175
6238
  cold: "\u2744\uFE0F Abaixo da Faixa Ideal",
6176
6239
  ok: "\u2714\uFE0F Dentro da Faixa Ideal",
6177
6240
  hot: "\u{1F525} Acima da Faixa Ideal",
6178
6241
  unknown: "\u2753 Faixa N\xE3o Configurada"
6179
6242
  };
6243
+ const statusColors = {
6244
+ cold: "#2563eb",
6245
+ ok: "#16a34a",
6246
+ hot: "#dc2626",
6247
+ unknown: "#64748b"
6248
+ };
6180
6249
  container.innerHTML = `
6181
6250
  <div class="temp-range-tooltip__content">
6182
6251
  <div class="temp-range-tooltip__header">
6183
6252
  <span class="temp-range-tooltip__icon">\u{1F321}\uFE0F</span>
6184
- <span class="temp-range-tooltip__title">${entityObject.labelOrName || entityObject.name || "Sensor"}</span>
6253
+ <span class="temp-range-tooltip__title">${label}</span>
6185
6254
  </div>
6186
6255
  <div class="temp-range-tooltip__body">
6187
6256
  <div class="temp-range-tooltip__value-row">
@@ -6189,79 +6258,392 @@
6189
6258
  ${currentTemp.toFixed(1)}<sup>\xB0C</sup>
6190
6259
  </div>
6191
6260
  <div class="temp-range-tooltip__deviation">
6192
- <div class="temp-range-tooltip__deviation-value ${deviationClass}">
6261
+ <div class="temp-range-tooltip__deviation-value ${status}">
6193
6262
  ${status === "ok" ? "\u2713" : status === "cold" ? "\u2193" : status === "hot" ? "\u2191" : "?"} ${Math.abs(deviationPercent || 0).toFixed(0)}%
6194
6263
  </div>
6195
6264
  <div class="temp-range-tooltip__deviation-label">Desvio</div>
6196
6265
  </div>
6197
6266
  </div>
6198
6267
 
6199
- ${hasRange ? `
6200
- <div class="temp-range-tooltip__ruler">
6201
- <div class="temp-range-tooltip__ruler-track"></div>
6202
- <div class="temp-range-tooltip__ruler-range" style="left: ${rangeLeft}%; width: ${rangeWidth}%;"></div>
6203
- <div class="temp-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
6204
- </div>
6205
- <div class="temp-range-tooltip__ruler-labels">
6206
- <span class="temp-range-tooltip__ruler-min">${tempMin}\xB0C</span>
6207
- <span style="color: #22c55e; font-weight: 600;">Faixa Ideal</span>
6208
- <span class="temp-range-tooltip__ruler-max">${tempMax}\xB0C</span>
6209
- </div>
6210
- ` : ""}
6268
+ ${hasRange ? `
6269
+ <div class="temp-range-tooltip__ruler">
6270
+ <div class="temp-range-tooltip__ruler-track"></div>
6271
+ <div class="temp-range-tooltip__ruler-range" style="left: ${rangeLeft}%; width: ${rangeWidth}%;"></div>
6272
+ <div class="temp-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
6273
+ </div>
6274
+ <div class="temp-range-tooltip__ruler-labels">
6275
+ <span class="temp-range-tooltip__ruler-min">${tempMin}\xB0C</span>
6276
+ <span style="color: #22c55e; font-weight: 600;">Faixa Ideal</span>
6277
+ <span class="temp-range-tooltip__ruler-max">${tempMax}\xB0C</span>
6278
+ </div>
6279
+ ` : ""}
6280
+
6281
+ <div class="temp-range-tooltip__range-info">
6282
+ <div class="temp-range-tooltip__range-item">
6283
+ <div class="temp-range-tooltip__range-label">M\xEDnimo</div>
6284
+ <div class="temp-range-tooltip__range-value">${hasRange ? tempMin + "\xB0C" : "--"}</div>
6285
+ </div>
6286
+ <div class="temp-range-tooltip__range-item">
6287
+ <div class="temp-range-tooltip__range-label">Atual</div>
6288
+ <div class="temp-range-tooltip__range-value" style="color: ${statusColors[status]}">${currentTemp.toFixed(1)}\xB0C</div>
6289
+ </div>
6290
+ <div class="temp-range-tooltip__range-item">
6291
+ <div class="temp-range-tooltip__range-label">M\xE1ximo</div>
6292
+ <div class="temp-range-tooltip__range-value">${hasRange ? tempMax + "\xB0C" : "--"}</div>
6293
+ </div>
6294
+ </div>
6295
+
6296
+ <div class="temp-range-tooltip__status ${status}">
6297
+ ${statusLabels[status]}
6298
+ </div>
6299
+ </div>
6300
+ </div>
6301
+ `;
6302
+ let left, top;
6303
+ if (event && event.clientX && event.clientY) {
6304
+ left = event.clientX + 15;
6305
+ top = event.clientY + 15;
6306
+ } else {
6307
+ const rect = triggerElement.getBoundingClientRect();
6308
+ left = rect.left + rect.width / 2 - 150;
6309
+ top = rect.bottom + 8;
6310
+ }
6311
+ const tooltipWidth = 300;
6312
+ const tooltipHeight = 350;
6313
+ if (left + tooltipWidth > window.innerWidth - 10) {
6314
+ left = (event?.clientX || left) - tooltipWidth - 15;
6315
+ }
6316
+ if (left < 10) left = 10;
6317
+ if (top + tooltipHeight > window.innerHeight - 10) {
6318
+ top = (event?.clientY || top) - tooltipHeight - 15;
6319
+ }
6320
+ if (top < 10) top = 10;
6321
+ container.style.left = left + "px";
6322
+ container.style.top = top + "px";
6323
+ container.classList.add("visible");
6324
+ },
6325
+ /**
6326
+ * Hide tooltip
6327
+ */
6328
+ hide() {
6329
+ const container = document.getElementById(this.containerId);
6330
+ if (container) {
6331
+ container.classList.remove("visible");
6332
+ }
6333
+ },
6334
+ /**
6335
+ * Attach tooltip to an element
6336
+ * Returns cleanup function
6337
+ */
6338
+ attach(element, entityData) {
6339
+ const showHandler = (e) => this.show(element, entityData, e);
6340
+ const hideHandler = () => this.hide();
6341
+ element.style.cursor = "help";
6342
+ element.addEventListener("mouseenter", showHandler);
6343
+ element.addEventListener("mouseleave", hideHandler);
6344
+ return () => {
6345
+ element.removeEventListener("mouseenter", showHandler);
6346
+ element.removeEventListener("mouseleave", hideHandler);
6347
+ element.style.cursor = "";
6348
+ this.hide();
6349
+ };
6350
+ }
6351
+ };
6352
+
6353
+ // src/utils/EnergyRangeTooltip.ts
6354
+ var ENERGY_RANGE_TOOLTIP_CSS = `
6355
+ /* ============================================
6356
+ Energy Range Tooltip (for domain=energy)
6357
+ Shows power ruler with current position and status ranges
6358
+ ============================================ */
6359
+ .energy-range-tooltip {
6360
+ position: fixed;
6361
+ z-index: 99999;
6362
+ pointer-events: none;
6363
+ opacity: 0;
6364
+ transition: opacity 0.2s ease, transform 0.2s ease;
6365
+ transform: translateY(5px);
6366
+ }
6367
+
6368
+ .energy-range-tooltip.visible {
6369
+ opacity: 1;
6370
+ pointer-events: auto;
6371
+ transform: translateY(0);
6372
+ }
6373
+
6374
+ .energy-range-tooltip__content {
6375
+ background: #ffffff;
6376
+ border: 1px solid #e2e8f0;
6377
+ border-radius: 12px;
6378
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15), 0 2px 10px rgba(0, 0, 0, 0.08);
6379
+ min-width: 300px;
6380
+ max-width: 360px;
6381
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
6382
+ font-size: 12px;
6383
+ color: #1e293b;
6384
+ overflow: hidden;
6385
+ }
6386
+
6387
+ .energy-range-tooltip__header {
6388
+ display: flex;
6389
+ align-items: center;
6390
+ gap: 8px;
6391
+ padding: 12px 16px;
6392
+ background: linear-gradient(90deg, #ecfdf5 0%, #d1fae5 100%);
6393
+ border-bottom: 1px solid #6ee7b7;
6394
+ }
6395
+
6396
+ .energy-range-tooltip__icon {
6397
+ font-size: 18px;
6398
+ }
6399
+
6400
+ .energy-range-tooltip__title {
6401
+ font-weight: 700;
6402
+ font-size: 13px;
6403
+ color: #047857;
6404
+ }
6405
+
6406
+ .energy-range-tooltip__body {
6407
+ padding: 16px;
6408
+ }
6409
+
6410
+ /* Power value display */
6411
+ .energy-range-tooltip__value-row {
6412
+ display: flex;
6413
+ justify-content: space-between;
6414
+ align-items: center;
6415
+ margin-bottom: 16px;
6416
+ }
6417
+
6418
+ .energy-range-tooltip__current {
6419
+ font-size: 28px;
6420
+ font-weight: 700;
6421
+ color: #1e293b;
6422
+ }
6211
6423
 
6212
- <div class="temp-range-tooltip__range-info">
6213
- <div class="temp-range-tooltip__range-item">
6214
- <div class="temp-range-tooltip__range-label">M\xEDnimo</div>
6215
- <div class="temp-range-tooltip__range-value">${hasRange ? tempMin + "\xB0C" : "--"}</div>
6216
- </div>
6217
- <div class="temp-range-tooltip__range-item">
6218
- <div class="temp-range-tooltip__range-label">Atual</div>
6219
- <div class="temp-range-tooltip__range-value" style="color: ${status === "ok" ? "#16a34a" : status === "cold" ? "#2563eb" : "#dc2626"}">${currentTemp.toFixed(1)}\xB0C</div>
6220
- </div>
6221
- <div class="temp-range-tooltip__range-item">
6222
- <div class="temp-range-tooltip__range-label">M\xE1ximo</div>
6223
- <div class="temp-range-tooltip__range-value">${hasRange ? tempMax + "\xB0C" : "--"}</div>
6224
- </div>
6225
- </div>
6424
+ .energy-range-tooltip__current sup {
6425
+ font-size: 14px;
6426
+ color: #64748b;
6427
+ }
6226
6428
 
6227
- <div class="temp-range-tooltip__status ${status}">
6228
- ${statusLabels[status]}
6229
- </div>
6230
- </div>
6231
- </div>
6232
- `;
6233
- let left, top;
6234
- if (event && event.clientX && event.clientY) {
6235
- left = event.clientX + 15;
6236
- top = event.clientY + 15;
6237
- } else {
6238
- const rect = triggerElement.getBoundingClientRect();
6239
- left = rect.left + rect.width / 2 - 150;
6240
- top = rect.bottom + 8;
6241
- }
6242
- const tooltipWidth = 300;
6243
- const tooltipHeight = 350;
6244
- if (left + tooltipWidth > window.innerWidth - 10) {
6245
- left = (event?.clientX || left) - tooltipWidth - 15;
6246
- }
6247
- if (left < 10) left = 10;
6248
- if (top + tooltipHeight > window.innerHeight - 10) {
6249
- top = (event?.clientY || top) - tooltipHeight - 15;
6250
- }
6251
- if (top < 10) top = 10;
6252
- container.style.left = left + "px";
6253
- container.style.top = top + "px";
6254
- container.classList.add("visible");
6255
- },
6256
- /**
6257
- * Hide tooltip
6258
- */
6259
- hide() {
6260
- const container = document.getElementById(this.containerId);
6261
- if (container) {
6262
- container.classList.remove("visible");
6263
- }
6429
+ .energy-range-tooltip__status-badge {
6430
+ text-align: right;
6431
+ }
6432
+
6433
+ .energy-range-tooltip__status-value {
6434
+ font-size: 14px;
6435
+ font-weight: 700;
6436
+ padding: 4px 10px;
6437
+ border-radius: 6px;
6438
+ }
6439
+
6440
+ .energy-range-tooltip__status-value.standby {
6441
+ background: #dbeafe;
6442
+ color: #1d4ed8;
6443
+ }
6444
+
6445
+ .energy-range-tooltip__status-value.normal {
6446
+ background: #dcfce7;
6447
+ color: #15803d;
6448
+ }
6449
+
6450
+ .energy-range-tooltip__status-value.alert {
6451
+ background: #fef3c7;
6452
+ color: #b45309;
6453
+ }
6454
+
6455
+ .energy-range-tooltip__status-value.failure {
6456
+ background: #fee2e2;
6457
+ color: #b91c1c;
6458
+ }
6459
+
6460
+ .energy-range-tooltip__status-value.offline {
6461
+ background: #f3f4f6;
6462
+ color: #6b7280;
6463
+ }
6464
+
6465
+ /* Power ruler/gauge */
6466
+ .energy-range-tooltip__ruler {
6467
+ position: relative;
6468
+ height: 40px;
6469
+ margin: 12px 0;
6470
+ border-radius: 8px;
6471
+ overflow: visible;
6472
+ }
6473
+
6474
+ .energy-range-tooltip__ruler-track {
6475
+ position: absolute;
6476
+ top: 16px;
6477
+ left: 0;
6478
+ right: 0;
6479
+ height: 8px;
6480
+ display: flex;
6481
+ border-radius: 4px;
6482
+ overflow: hidden;
6483
+ border: 1px solid #e2e8f0;
6484
+ }
6485
+
6486
+ .energy-range-tooltip__ruler-segment {
6487
+ height: 100%;
6488
+ }
6489
+
6490
+ .energy-range-tooltip__ruler-segment.standby {
6491
+ background: #dbeafe;
6492
+ }
6493
+
6494
+ .energy-range-tooltip__ruler-segment.normal {
6495
+ background: #dcfce7;
6496
+ }
6497
+
6498
+ .energy-range-tooltip__ruler-segment.alert {
6499
+ background: #fef3c7;
6500
+ }
6501
+
6502
+ .energy-range-tooltip__ruler-segment.failure {
6503
+ background: #fee2e2;
6504
+ }
6505
+
6506
+ .energy-range-tooltip__ruler-marker {
6507
+ position: absolute;
6508
+ top: 8px;
6509
+ width: 4px;
6510
+ height: 24px;
6511
+ background: #1e293b;
6512
+ border-radius: 2px;
6513
+ transform: translateX(-50%);
6514
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6515
+ }
6516
+
6517
+ .energy-range-tooltip__ruler-marker::after {
6518
+ content: '';
6519
+ position: absolute;
6520
+ top: -4px;
6521
+ left: 50%;
6522
+ transform: translateX(-50%);
6523
+ width: 12px;
6524
+ height: 12px;
6525
+ background: #1e293b;
6526
+ border-radius: 50%;
6527
+ border: 2px solid #fff;
6528
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
6529
+ }
6530
+
6531
+ /* Range info grid */
6532
+ .energy-range-tooltip__ranges {
6533
+ display: grid;
6534
+ grid-template-columns: repeat(4, 1fr);
6535
+ gap: 8px;
6536
+ margin-top: 16px;
6537
+ }
6538
+
6539
+ .energy-range-tooltip__range-item {
6540
+ text-align: center;
6541
+ padding: 8px 4px;
6542
+ border-radius: 6px;
6543
+ background: #f8fafc;
6544
+ }
6545
+
6546
+ .energy-range-tooltip__range-item.standby {
6547
+ border-left: 3px solid #3b82f6;
6548
+ }
6549
+
6550
+ .energy-range-tooltip__range-item.normal {
6551
+ border-left: 3px solid #22c55e;
6552
+ }
6553
+
6554
+ .energy-range-tooltip__range-item.alert {
6555
+ border-left: 3px solid #f59e0b;
6556
+ }
6557
+
6558
+ .energy-range-tooltip__range-item.failure {
6559
+ border-left: 3px solid #ef4444;
6560
+ }
6561
+
6562
+ .energy-range-tooltip__range-label {
6563
+ font-size: 9px;
6564
+ color: #64748b;
6565
+ text-transform: uppercase;
6566
+ letter-spacing: 0.3px;
6567
+ margin-bottom: 2px;
6568
+ }
6569
+
6570
+ .energy-range-tooltip__range-value {
6571
+ font-size: 11px;
6572
+ font-weight: 600;
6573
+ color: #334155;
6574
+ }
6575
+
6576
+ /* Status info */
6577
+ .energy-range-tooltip__status-info {
6578
+ display: flex;
6579
+ align-items: center;
6580
+ justify-content: center;
6581
+ gap: 6px;
6582
+ margin-top: 12px;
6583
+ padding: 8px 12px;
6584
+ border-radius: 6px;
6585
+ font-size: 11px;
6586
+ font-weight: 600;
6587
+ }
6588
+
6589
+ .energy-range-tooltip__status-info.standby {
6590
+ background: #dbeafe;
6591
+ color: #1d4ed8;
6592
+ border: 1px solid #93c5fd;
6593
+ }
6594
+
6595
+ .energy-range-tooltip__status-info.normal {
6596
+ background: #dcfce7;
6597
+ color: #15803d;
6598
+ border: 1px solid #86efac;
6599
+ }
6600
+
6601
+ .energy-range-tooltip__status-info.alert {
6602
+ background: #fef3c7;
6603
+ color: #b45309;
6604
+ border: 1px solid #fcd34d;
6605
+ }
6606
+
6607
+ .energy-range-tooltip__status-info.failure {
6608
+ background: #fee2e2;
6609
+ color: #b91c1c;
6610
+ border: 1px solid #fca5a5;
6611
+ }
6612
+
6613
+ .energy-range-tooltip__status-info.offline {
6614
+ background: #f3f4f6;
6615
+ color: #6b7280;
6616
+ border: 1px solid #d1d5db;
6617
+ }
6618
+ `;
6619
+ var cssInjected = false;
6620
+ function injectCSS() {
6621
+ if (cssInjected) return;
6622
+ if (typeof document === "undefined") return;
6623
+ const styleId = "myio-energy-range-tooltip-styles";
6624
+ if (document.getElementById(styleId)) {
6625
+ cssInjected = true;
6626
+ return;
6264
6627
  }
6628
+ const style = document.createElement("style");
6629
+ style.id = styleId;
6630
+ style.textContent = ENERGY_RANGE_TOOLTIP_CSS;
6631
+ document.head.appendChild(style);
6632
+ cssInjected = true;
6633
+ }
6634
+ var STATUS_LABELS = {
6635
+ standby: "Standby",
6636
+ normal: "Operacao Normal",
6637
+ alert: "Alerta",
6638
+ failure: "Falha",
6639
+ offline: "Fora da faixa"
6640
+ };
6641
+ var STATUS_INFO_LABELS = {
6642
+ standby: "\u{1F535} Standby",
6643
+ normal: "\u2705 Operacao Normal",
6644
+ alert: "\u26A0\uFE0F Alerta",
6645
+ failure: "\u{1F534} Falha",
6646
+ offline: "\u26AB Offline / Sem dados"
6265
6647
  };
6266
6648
  var EnergyRangeTooltip = {
6267
6649
  containerId: "myio-energy-range-tooltip",
@@ -6269,6 +6651,7 @@
6269
6651
  * Create or get the tooltip container
6270
6652
  */
6271
6653
  getContainer() {
6654
+ injectCSS();
6272
6655
  let container = document.getElementById(this.containerId);
6273
6656
  if (!container) {
6274
6657
  container = document.createElement("div");
@@ -6288,18 +6671,18 @@
6288
6671
  const power = Number(powerValue) || 0;
6289
6672
  const { standbyRange, normalRange, alertRange, failureRange } = ranges;
6290
6673
  if (standbyRange && power >= standbyRange.down && power <= standbyRange.up) {
6291
- return { status: "standby", label: "Standby" };
6674
+ return { status: "standby", label: STATUS_LABELS.standby };
6292
6675
  }
6293
6676
  if (normalRange && power >= normalRange.down && power <= normalRange.up) {
6294
- return { status: "normal", label: "Normal" };
6677
+ return { status: "normal", label: STATUS_LABELS.normal };
6295
6678
  }
6296
6679
  if (alertRange && power >= alertRange.down && power <= alertRange.up) {
6297
- return { status: "alert", label: "Alerta" };
6680
+ return { status: "alert", label: STATUS_LABELS.alert };
6298
6681
  }
6299
6682
  if (failureRange && power >= failureRange.down && power <= failureRange.up) {
6300
- return { status: "failure", label: "Falha" };
6683
+ return { status: "failure", label: STATUS_LABELS.failure };
6301
6684
  }
6302
- return { status: "offline", label: "Fora da faixa" };
6685
+ return { status: "offline", label: STATUS_LABELS.offline };
6303
6686
  },
6304
6687
  /**
6305
6688
  * Calculate marker position on ruler (0-100%)
@@ -6330,7 +6713,7 @@
6330
6713
  * Format power value for display
6331
6714
  */
6332
6715
  formatPower(value) {
6333
- if (value == null || isNaN(value)) return "-";
6716
+ if (value == null || isNaN(Number(value))) return "-";
6334
6717
  const num = Number(value);
6335
6718
  if (num >= 1e3) {
6336
6719
  return `${(num / 1e3).toFixed(2)} kW`;
@@ -6348,13 +6731,40 @@
6348
6731
  const { status, label } = this.calculateStatus(powerValue, ranges);
6349
6732
  const markerPos = this.calculateMarkerPosition(powerValue, ranges);
6350
6733
  const segmentWidths = this.calculateSegmentWidths(ranges);
6351
- const statusLabels = {
6352
- standby: "\u{1F535} Standby",
6353
- normal: "\u2705 Opera\xE7\xE3o Normal",
6354
- alert: "\u26A0\uFE0F Alerta",
6355
- failure: "\u{1F534} Falha",
6356
- offline: "\u26AB Offline / Sem dados"
6357
- };
6734
+ const rangesHtml = hasRanges && ranges ? `
6735
+ <div class="energy-range-tooltip__ruler">
6736
+ <div class="energy-range-tooltip__ruler-track">
6737
+ <div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
6738
+ <div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
6739
+ <div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
6740
+ <div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
6741
+ </div>
6742
+ <div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
6743
+ </div>
6744
+
6745
+ <div class="energy-range-tooltip__ranges">
6746
+ <div class="energy-range-tooltip__range-item standby">
6747
+ <div class="energy-range-tooltip__range-label">Standby</div>
6748
+ <div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
6749
+ </div>
6750
+ <div class="energy-range-tooltip__range-item normal">
6751
+ <div class="energy-range-tooltip__range-label">Normal</div>
6752
+ <div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
6753
+ </div>
6754
+ <div class="energy-range-tooltip__range-item alert">
6755
+ <div class="energy-range-tooltip__range-label">Alerta</div>
6756
+ <div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
6757
+ </div>
6758
+ <div class="energy-range-tooltip__range-item failure">
6759
+ <div class="energy-range-tooltip__range-label">Falha</div>
6760
+ <div class="energy-range-tooltip__range-value">&gt;${ranges.failureRange?.down || 0}W</div>
6761
+ </div>
6762
+ </div>
6763
+ ` : `
6764
+ <div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
6765
+ Ranges de potencia nao configurados
6766
+ </div>
6767
+ `;
6358
6768
  container.innerHTML = `
6359
6769
  <div class="energy-range-tooltip__content">
6360
6770
  <div class="energy-range-tooltip__header">
@@ -6371,51 +6781,18 @@
6371
6781
  </div>
6372
6782
  </div>
6373
6783
 
6374
- ${hasRanges ? `
6375
- <div class="energy-range-tooltip__ruler">
6376
- <div class="energy-range-tooltip__ruler-track">
6377
- <div class="energy-range-tooltip__ruler-segment standby" style="width: ${segmentWidths.standby}%"></div>
6378
- <div class="energy-range-tooltip__ruler-segment normal" style="width: ${segmentWidths.normal}%"></div>
6379
- <div class="energy-range-tooltip__ruler-segment alert" style="width: ${segmentWidths.alert}%"></div>
6380
- <div class="energy-range-tooltip__ruler-segment failure" style="width: ${segmentWidths.failure}%"></div>
6381
- </div>
6382
- <div class="energy-range-tooltip__ruler-marker" style="left: ${markerPos}%;"></div>
6383
- </div>
6384
-
6385
- <div class="energy-range-tooltip__ranges">
6386
- <div class="energy-range-tooltip__range-item standby">
6387
- <div class="energy-range-tooltip__range-label">Standby</div>
6388
- <div class="energy-range-tooltip__range-value">${ranges.standbyRange?.down || 0}-${ranges.standbyRange?.up || 0}W</div>
6389
- </div>
6390
- <div class="energy-range-tooltip__range-item normal">
6391
- <div class="energy-range-tooltip__range-label">Normal</div>
6392
- <div class="energy-range-tooltip__range-value">${ranges.normalRange?.down || 0}-${ranges.normalRange?.up || 0}W</div>
6393
- </div>
6394
- <div class="energy-range-tooltip__range-item alert">
6395
- <div class="energy-range-tooltip__range-label">Alerta</div>
6396
- <div class="energy-range-tooltip__range-value">${ranges.alertRange?.down || 0}-${ranges.alertRange?.up || 0}W</div>
6397
- </div>
6398
- <div class="energy-range-tooltip__range-item failure">
6399
- <div class="energy-range-tooltip__range-label">Falha</div>
6400
- <div class="energy-range-tooltip__range-value">&gt;${ranges.failureRange?.down || 0}W</div>
6401
- </div>
6402
- </div>
6403
- ` : `
6404
- <div style="text-align: center; padding: 16px; color: #64748b; font-size: 12px;">
6405
- Ranges de pot\xEAncia n\xE3o configurados
6406
- </div>
6407
- `}
6784
+ ${rangesHtml}
6408
6785
 
6409
6786
  <div class="energy-range-tooltip__status-info ${status}">
6410
- ${statusLabels[status] || statusLabels.offline}
6787
+ ${STATUS_INFO_LABELS[status] || STATUS_INFO_LABELS.offline}
6411
6788
  </div>
6412
6789
  </div>
6413
6790
  </div>
6414
6791
  `;
6415
6792
  let left, top;
6416
6793
  if (event && event.clientX && event.clientY) {
6417
- left = event.clientX + 15;
6418
- top = event.clientY + 15;
6794
+ left = event.clientX + 8;
6795
+ top = event.clientY + 8;
6419
6796
  } else {
6420
6797
  const rect = triggerElement.getBoundingClientRect();
6421
6798
  left = rect.left + rect.width / 2 - 150;
@@ -6424,11 +6801,11 @@
6424
6801
  const tooltipWidth = 320;
6425
6802
  const tooltipHeight = 380;
6426
6803
  if (left + tooltipWidth > window.innerWidth - 10) {
6427
- left = (event?.clientX || left) - tooltipWidth - 15;
6804
+ left = (event?.clientX || left) - tooltipWidth - 8;
6428
6805
  }
6429
6806
  if (left < 10) left = 10;
6430
6807
  if (top + tooltipHeight > window.innerHeight - 10) {
6431
- top = (event?.clientY || top) - tooltipHeight - 15;
6808
+ top = (event?.clientY || top) - tooltipHeight - 8;
6432
6809
  }
6433
6810
  if (top < 10) top = 10;
6434
6811
  container.style.left = left + "px";
@@ -6443,8 +6820,229 @@
6443
6820
  if (container) {
6444
6821
  container.classList.remove("visible");
6445
6822
  }
6823
+ },
6824
+ /**
6825
+ * Attach tooltip to an element with automatic show/hide on hover
6826
+ * Returns cleanup function to remove event listeners
6827
+ */
6828
+ attach(element, entityData) {
6829
+ const handleMouseEnter = (e) => {
6830
+ this.show(element, entityData, e);
6831
+ };
6832
+ const handleMouseLeave = () => {
6833
+ this.hide();
6834
+ };
6835
+ const handleMouseMove = (e) => {
6836
+ const container = document.getElementById(this.containerId);
6837
+ if (container && container.classList.contains("visible")) {
6838
+ let left = e.clientX + 8;
6839
+ let top = e.clientY + 8;
6840
+ const tooltipWidth = 320;
6841
+ const tooltipHeight = 380;
6842
+ if (left + tooltipWidth > window.innerWidth - 10) {
6843
+ left = e.clientX - tooltipWidth - 8;
6844
+ }
6845
+ if (left < 10) left = 10;
6846
+ if (top + tooltipHeight > window.innerHeight - 10) {
6847
+ top = e.clientY - tooltipHeight - 8;
6848
+ }
6849
+ if (top < 10) top = 10;
6850
+ container.style.left = left + "px";
6851
+ container.style.top = top + "px";
6852
+ }
6853
+ };
6854
+ element.addEventListener("mouseenter", handleMouseEnter);
6855
+ element.addEventListener("mouseleave", handleMouseLeave);
6856
+ element.addEventListener("mousemove", handleMouseMove);
6857
+ return () => {
6858
+ element.removeEventListener("mouseenter", handleMouseEnter);
6859
+ element.removeEventListener("mouseleave", handleMouseLeave);
6860
+ element.removeEventListener("mousemove", handleMouseMove);
6861
+ this.hide();
6862
+ };
6446
6863
  }
6447
6864
  };
6865
+
6866
+ // src/thingsboard/main-dashboard-shopping/v-4.0.0/card/head-office/card-head-office.js
6867
+ var LABEL_CHAR_LIMIT = 18;
6868
+ var DEFAUL_DELAY_TIME_CONNECTION_IN_MINS = 1440;
6869
+ var CSS_TAG = "head-office-card-v1";
6870
+ function ensureCss() {
6871
+ if (!document.querySelector(`style[data-myio-css="${CSS_TAG}"]`)) {
6872
+ const style = document.createElement("style");
6873
+ style.setAttribute("data-myio-css", CSS_TAG);
6874
+ style.textContent = CSS_STRING;
6875
+ document.head.appendChild(style);
6876
+ }
6877
+ }
6878
+ function normalizeParams(params) {
6879
+ if (!params || !params.entityObject) {
6880
+ throw new Error("renderCardCompenteHeadOffice: entityObject is required");
6881
+ }
6882
+ const LogHelper2 = createLogHelper(params.debugActive ?? false);
6883
+ const entityObject = params.entityObject;
6884
+ if (!entityObject.entityId) {
6885
+ LogHelper2.warn("[CardHeadOffice] entityId is missing, generating temporary ID");
6886
+ entityObject.entityId = `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
6887
+ }
6888
+ if (!params.delayTimeConnectionInMins) {
6889
+ LogHelper2.warn(
6890
+ `[CardHeadOffice] delayTimeConnectionInMins is missing, defaulting to ${DEFAUL_DELAY_TIME_CONNECTION_IN_MINS} mins`
6891
+ );
6892
+ }
6893
+ return {
6894
+ entityObject,
6895
+ i18n: { ...DEFAULT_I18N, ...params.i18n || {} },
6896
+ enableSelection: Boolean(params.enableSelection),
6897
+ enableDragDrop: Boolean(params.enableDragDrop),
6898
+ useNewComponents: Boolean(params.useNewComponents),
6899
+ // RFC-0091: Configurable delay time for connection status check (default 15 minutes)
6900
+ delayTimeConnectionInMins: params.delayTimeConnectionInMins ?? DEFAUL_DELAY_TIME_CONNECTION_IN_MINS,
6901
+ // Debug options
6902
+ debugActive: params.debugActive ?? false,
6903
+ activeTooltipDebug: params.activeTooltipDebug ?? false,
6904
+ // LogHelper instance for this card
6905
+ LogHelper: LogHelper2,
6906
+ callbacks: {
6907
+ handleActionDashboard: params.handleActionDashboard,
6908
+ handleActionReport: params.handleActionReport,
6909
+ handleActionSettings: params.handleActionSettings,
6910
+ handleSelect: params.handleSelect,
6911
+ handInfo: params.handInfo,
6912
+ handleClickCard: params.handleClickCard
6913
+ }
6914
+ };
6915
+ }
6916
+ function getIconSvg(deviceType, domain) {
6917
+ if (domain === "water") {
6918
+ return Icons.waterDrop;
6919
+ }
6920
+ if (domain === "temperature") {
6921
+ return Icons.thermometer;
6922
+ }
6923
+ return ICON_MAP[deviceType] || ICON_MAP.DEFAULT;
6924
+ }
6925
+ function formatPower(valueInWatts) {
6926
+ if (valueInWatts === null || valueInWatts === void 0 || isNaN(valueInWatts)) {
6927
+ return { num: "-", unit: "" };
6928
+ }
6929
+ const val = Number(valueInWatts);
6930
+ if (val >= 1e3) {
6931
+ const kw = Math.ceil(val / 1e3 * 100) / 100;
6932
+ return { num: kw.toFixed(2), unit: "kW" };
6933
+ } else {
6934
+ const w = Math.ceil(val);
6935
+ return { num: w.toString(), unit: "W" };
6936
+ }
6937
+ }
6938
+ function formatValueByDomain(value, domain) {
6939
+ if (domain === "water") {
6940
+ return formatWaterVolumeM3(value);
6941
+ }
6942
+ if (domain === "temperature") {
6943
+ return formatTemperature(value, 0);
6944
+ }
6945
+ return formatEnergy(value);
6946
+ }
6947
+ function formatRelativeTime2(timestamp) {
6948
+ if (!timestamp || isNaN(timestamp)) return "\u2014";
6949
+ const date = new Date(timestamp);
6950
+ const hours = String(date.getHours()).padStart(2, "0");
6951
+ const minutes = String(date.getMinutes()).padStart(2, "0");
6952
+ const day = String(date.getDate()).padStart(2, "0");
6953
+ const month = String(date.getMonth() + 1).padStart(2, "0");
6954
+ const year = date.getFullYear();
6955
+ return `${hours}:${minutes} ${day}/${month}/${year}`;
6956
+ }
6957
+ function calculateConsumptionPercentage(target, consumption) {
6958
+ const numericTarget = Number(target);
6959
+ const numericConsumption = Number(consumption);
6960
+ if (isNaN(numericTarget) || isNaN(numericConsumption) || numericTarget <= 0) {
6961
+ return 0;
6962
+ }
6963
+ const percentage = numericConsumption / numericTarget * 100;
6964
+ return percentage;
6965
+ }
6966
+ function getStatusInfo(deviceStatus, i18n, domain) {
6967
+ switch (deviceStatus) {
6968
+ // --- Novos Status de Temperatura ---
6969
+ case "normal":
6970
+ return { chipClass: "chip--ok", label: "Normal" };
6971
+ case "cold":
6972
+ return { chipClass: "chip--standby", label: "Frio" };
6973
+ case "hot":
6974
+ return { chipClass: "chip--alert", label: "Quente" };
6975
+ // --- Status Existentes (aligned with getCardStateClass) ---
6976
+ case DeviceStatusType.POWER_ON:
6977
+ if (domain === "water") {
6978
+ return { chipClass: "chip--power-on", label: i18n.in_operation_water };
6979
+ }
6980
+ return { chipClass: "chip--power-on", label: i18n.in_operation };
6981
+ case DeviceStatusType.STANDBY:
6982
+ return { chipClass: "chip--standby", label: i18n.standby };
6983
+ case DeviceStatusType.WARNING:
6984
+ return { chipClass: "chip--warning", label: i18n.alert };
6985
+ case DeviceStatusType.MAINTENANCE:
6986
+ return { chipClass: "chip--maintenance", label: i18n.maintenance };
6987
+ case DeviceStatusType.FAILURE:
6988
+ return { chipClass: "chip--failure", label: i18n.failure };
6989
+ case DeviceStatusType.POWER_OFF:
6990
+ return { chipClass: "chip--power-off", label: i18n.power_off || i18n.failure };
6991
+ case DeviceStatusType.OFFLINE:
6992
+ return { chipClass: "chip--offline", label: i18n.offline };
6993
+ case DeviceStatusType.NO_INFO:
6994
+ return { chipClass: "chip--no-info", label: i18n.no_info || i18n.offline };
6995
+ case DeviceStatusType.NOT_INSTALLED:
6996
+ return { chipClass: "chip--not-installed", label: i18n.not_installed };
6997
+ default:
6998
+ return { chipClass: "chip--offline", label: i18n.offline };
6999
+ }
7000
+ }
7001
+ function getCardStateClass(deviceStatus) {
7002
+ switch (deviceStatus) {
7003
+ case DeviceStatusType.POWER_ON:
7004
+ return "is-power-on";
7005
+ // Blue border
7006
+ case DeviceStatusType.STANDBY:
7007
+ return "is-standby";
7008
+ // Green border
7009
+ case DeviceStatusType.WARNING:
7010
+ return "is-warning";
7011
+ // Yellow border
7012
+ case DeviceStatusType.MAINTENANCE:
7013
+ return "is-maintenance";
7014
+ // Yellow border
7015
+ case DeviceStatusType.FAILURE:
7016
+ return "is-failure";
7017
+ // Dark Red border
7018
+ case DeviceStatusType.POWER_OFF:
7019
+ return "is-power-off";
7020
+ // Light Red border
7021
+ case DeviceStatusType.OFFLINE:
7022
+ return "is-offline";
7023
+ // Dark Gray border
7024
+ case DeviceStatusType.NO_INFO:
7025
+ return "is-no-info";
7026
+ // Dark Orange border
7027
+ case DeviceStatusType.NOT_INSTALLED:
7028
+ return "is-not-installed";
7029
+ // Purple border
7030
+ default:
7031
+ return "";
7032
+ }
7033
+ }
7034
+ function getTempRangeClass(entityObject) {
7035
+ if (entityObject.domain !== "temperature") return "";
7036
+ const currentTemp = Number(entityObject.val ?? entityObject.currentTemperature ?? entityObject.temperature) || 0;
7037
+ const tempMin = entityObject.temperatureMin ?? entityObject.minTemperature;
7038
+ const tempMax = entityObject.temperatureMax ?? entityObject.maxTemperature;
7039
+ if (tempMin === void 0 || tempMax === void 0 || tempMin === null || tempMax === null) {
7040
+ return "";
7041
+ }
7042
+ if (currentTemp > tempMax) return "is-temp-hot";
7043
+ if (currentTemp < tempMin) return "is-temp-cold";
7044
+ return "is-temp-ok";
7045
+ }
6448
7046
  function getStatusDotClass(deviceStatus) {
6449
7047
  switch (deviceStatus) {
6450
7048
  // --- Novos Status de Temperatura ---
@@ -6970,29 +7568,34 @@
6970
7568
  MyIOSelectionStore2.on("selection:change", onSelectionChange);
6971
7569
  root._selectionListener = onSelectionChange;
6972
7570
  }
6973
- if (entityObject.domain === "temperature") {
7571
+ const valueElement = root.querySelector(".myio-ho-card__value");
7572
+ if (entityObject.domain === "temperature" && valueElement) {
6974
7573
  const showTooltip = (e) => {
6975
7574
  TempRangeTooltip.show(root, state.entityObject, e);
6976
7575
  };
6977
7576
  const hideTooltip = () => {
6978
7577
  TempRangeTooltip.hide();
6979
7578
  };
6980
- root.addEventListener("mouseenter", showTooltip);
6981
- root.addEventListener("mouseleave", hideTooltip);
7579
+ valueElement.style.cursor = "help";
7580
+ valueElement.addEventListener("mouseenter", showTooltip);
7581
+ valueElement.addEventListener("mouseleave", hideTooltip);
6982
7582
  root._tempTooltipShowFn = showTooltip;
6983
7583
  root._tempTooltipHideFn = hideTooltip;
7584
+ root._tooltipElement = valueElement;
6984
7585
  }
6985
- if (entityObject.domain === "energy") {
7586
+ if (entityObject.domain === "energy" && valueElement) {
6986
7587
  const showEnergyTooltip = (e) => {
6987
7588
  EnergyRangeTooltip.show(root, state.entityObject, e);
6988
7589
  };
6989
7590
  const hideEnergyTooltip = () => {
6990
7591
  EnergyRangeTooltip.hide();
6991
7592
  };
6992
- root.addEventListener("mouseenter", showEnergyTooltip);
6993
- root.addEventListener("mouseleave", hideEnergyTooltip);
7593
+ valueElement.style.cursor = "help";
7594
+ valueElement.addEventListener("mouseenter", showEnergyTooltip);
7595
+ valueElement.addEventListener("mouseleave", hideEnergyTooltip);
6994
7596
  root._energyTooltipShowFn = showEnergyTooltip;
6995
7597
  root._energyTooltipHideFn = hideEnergyTooltip;
7598
+ root._tooltipElement = valueElement;
6996
7599
  }
6997
7600
  root._cleanup = () => {
6998
7601
  document.removeEventListener("click", closeMenu);
@@ -7000,14 +7603,14 @@
7000
7603
  if (MyIOSelectionStore2 && root._selectionListener) {
7001
7604
  MyIOSelectionStore2.off("selection:change", root._selectionListener);
7002
7605
  }
7003
- if (root._tempTooltipShowFn) {
7004
- root.removeEventListener("mouseenter", root._tempTooltipShowFn);
7005
- root.removeEventListener("mouseleave", root._tempTooltipHideFn);
7606
+ if (root._tempTooltipShowFn && root._tooltipElement) {
7607
+ root._tooltipElement.removeEventListener("mouseenter", root._tempTooltipShowFn);
7608
+ root._tooltipElement.removeEventListener("mouseleave", root._tempTooltipHideFn);
7006
7609
  TempRangeTooltip.hide();
7007
7610
  }
7008
- if (root._energyTooltipShowFn) {
7009
- root.removeEventListener("mouseenter", root._energyTooltipShowFn);
7010
- root.removeEventListener("mouseleave", root._energyTooltipHideFn);
7611
+ if (root._energyTooltipShowFn && root._tooltipElement) {
7612
+ root._tooltipElement.removeEventListener("mouseenter", root._energyTooltipShowFn);
7613
+ root._tooltipElement.removeEventListener("mouseleave", root._energyTooltipHideFn);
7011
7614
  EnergyRangeTooltip.hide();
7012
7615
  }
7013
7616
  };
@@ -7560,6 +8163,7 @@
7560
8163
  };
7561
8164
  const isTankDevice = deviceType === "TANK" || deviceType === "CAIXA_DAGUA";
7562
8165
  const isTermostatoDevice = deviceType?.toUpperCase() === "TERMOSTATO";
8166
+ const isEnergyDeviceFlag = isEnergyDevice(deviceType);
7563
8167
  const percentageForDisplay = isTankDevice ? (waterPercentage || 0) * 100 : perc;
7564
8168
  const calculateTempStatus = () => {
7565
8169
  if (temperatureStatus) return temperatureStatus;
@@ -7576,33 +8180,6 @@
7576
8180
  tempStatus,
7577
8181
  isOffline
7578
8182
  });
7579
- const getTemperatureTooltip = () => {
7580
- if (!isTermostatoDevice) return "";
7581
- const currentTemp = Number(val) || 0;
7582
- const hasRange = temperatureMin !== void 0 && temperatureMax !== void 0 && temperatureMin !== null && temperatureMax !== null;
7583
- if (isOffline) {
7584
- return "Dispositivo offline";
7585
- }
7586
- if (!hasRange) {
7587
- return `Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7588
- Faixa n\xE3o configurada`;
7589
- }
7590
- const rangeText = `Faixa ideal: ${temperatureMin}\xB0C a ${temperatureMax}\xB0C`;
7591
- if (tempStatus === "above") {
7592
- return `ACIMA da faixa ideal
7593
- Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7594
- ${rangeText}`;
7595
- } else if (tempStatus === "below") {
7596
- return `ABAIXO da faixa ideal
7597
- Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7598
- ${rangeText}`;
7599
- } else {
7600
- return `DENTRO da faixa ideal
7601
- Temperatura atual: ${currentTemp.toFixed(1)}\xB0C
7602
- ${rangeText}`;
7603
- }
7604
- };
7605
- const temperatureTooltip = getTemperatureTooltip();
7606
8183
  const cardHTML = `
7607
8184
  <div class="device-card-centered clickable ${cardEntity.status === "offline" ? "offline" : ""}"
7608
8185
  data-entity-id="${entityId}"
@@ -7628,7 +8205,7 @@ ${rangeText}`;
7628
8205
  ` : ""}
7629
8206
  </div>
7630
8207
 
7631
- <img class="device-image" src="${deviceImageUrl}" alt="${deviceType}" ${isTermostatoDevice && temperatureTooltip ? `title="${temperatureTooltip}"` : ""} style="${isTermostatoDevice ? "cursor: help;" : ""}" />
8208
+ <img class="device-image ${isTermostatoDevice ? "temp-tooltip-trigger" : ""}${isEnergyDeviceFlag ? " energy-tooltip-trigger" : ""}" src="${deviceImageUrl}" alt="${deviceType}" style="${isTermostatoDevice || isEnergyDeviceFlag ? "cursor: help;" : ""}" />
7632
8209
 
7633
8210
 
7634
8211
  ${customerName && String(customerName).trim() !== "" ? `
@@ -8192,6 +8769,33 @@ ${rangeText}`;
8192
8769
  }
8193
8770
  });
8194
8771
  }
8772
+ const tempTooltipTrigger = enhancedCardElement.querySelector(".temp-tooltip-trigger");
8773
+ let tempTooltipCleanup = null;
8774
+ if (tempTooltipTrigger && isTermostatoDevice) {
8775
+ const tooltipEntityData = {
8776
+ val,
8777
+ temperatureMin,
8778
+ temperatureMax,
8779
+ labelOrName: cardEntity.name,
8780
+ name: cardEntity.name
8781
+ };
8782
+ tempTooltipCleanup = TempRangeTooltip.attach(tempTooltipTrigger, tooltipEntityData);
8783
+ }
8784
+ const energyTooltipTrigger = enhancedCardElement.querySelector(".energy-tooltip-trigger");
8785
+ let energyTooltipCleanup = null;
8786
+ if (energyTooltipTrigger && isEnergyDeviceFlag) {
8787
+ const energyTooltipData = {
8788
+ labelOrName: cardEntity.name,
8789
+ name: cardEntity.name,
8790
+ instantaneousPower: entityObject.instantaneousPower ?? entityObject.consumption_power ?? val,
8791
+ powerRanges: entityObject.powerRanges || entityObject.ranges
8792
+ };
8793
+ energyTooltipCleanup = EnergyRangeTooltip.attach(energyTooltipTrigger, energyTooltipData);
8794
+ }
8795
+ container._cleanup = () => {
8796
+ if (tempTooltipCleanup) tempTooltipCleanup();
8797
+ if (energyTooltipCleanup) energyTooltipCleanup();
8798
+ };
8195
8799
  const jQueryLikeObject = {
8196
8800
  get: (index) => index === 0 ? container : void 0,
8197
8801
  0: container,
@@ -11173,7 +11777,7 @@ ${rangeText}`;
11173
11777
  var zoomPluginLoaded = false;
11174
11778
  var jsPdfLoaded = false;
11175
11779
  var _jspdfPromise = null;
11176
- var cssInjected = false;
11780
+ var cssInjected2 = false;
11177
11781
  var STRINGS2 = {
11178
11782
  "pt-BR": {
11179
11783
  title: "Demanda",
@@ -11349,8 +11953,8 @@ ${rangeText}`;
11349
11953
  }
11350
11954
  return nextY;
11351
11955
  }
11352
- function injectCSS(styles) {
11353
- if (cssInjected) return;
11956
+ function injectCSS2(styles) {
11957
+ if (cssInjected2) return;
11354
11958
  const css = `
11355
11959
  .myio-demand-modal-overlay {
11356
11960
  position: fixed;
@@ -11745,7 +12349,7 @@ ${rangeText}`;
11745
12349
  const style = document.createElement("style");
11746
12350
  style.textContent = css;
11747
12351
  document.head.appendChild(style);
11748
- cssInjected = true;
12352
+ cssInjected2 = true;
11749
12353
  }
11750
12354
  function formatDate2(date, locale) {
11751
12355
  return date.toLocaleDateString(locale, {
@@ -11927,7 +12531,7 @@ ${rangeText}`;
11927
12531
  const locale = params.locale || "pt-BR";
11928
12532
  const strings = STRINGS2[locale] || STRINGS2["pt-BR"];
11929
12533
  await loadExternalLibraries();
11930
- injectCSS(styles);
12534
+ injectCSS2(styles);
11931
12535
  const container = typeof params.container === "string" ? document.querySelector(params.container) : params.container || document.body;
11932
12536
  if (!container) {
11933
12537
  throw new Error("Container element not found");
@@ -21405,7 +22009,7 @@ ${rangeText}`;
21405
22009
  placeholder = "Clique para selecionar per\xEDodo",
21406
22010
  pickerOptions = {},
21407
22011
  classNames = {},
21408
- injectStyles = true,
22012
+ injectStyles: injectStyles2 = true,
21409
22013
  showHelper = true
21410
22014
  } = params;
21411
22015
  validateId(containerId, "containerId");
@@ -21414,7 +22018,7 @@ ${rangeText}`;
21414
22018
  if (!container) {
21415
22019
  throw new Error(`[createInputDateRangePickerInsideDIV] Container '#${containerId}' not found`);
21416
22020
  }
21417
- if (injectStyles) {
22021
+ if (injectStyles2) {
21418
22022
  injectPremiumStyles();
21419
22023
  }
21420
22024
  let inputEl = document.getElementById(inputId);
@@ -21609,7 +22213,7 @@ ${rangeText}`;
21609
22213
  modal.setAttribute("aria-labelledby", "goals-modal-title");
21610
22214
  modal.innerHTML = generateModalHTML();
21611
22215
  document.body.appendChild(modal);
21612
- injectStyles();
22216
+ injectStyles2();
21613
22217
  attachEventListeners();
21614
22218
  trapFocus(modal);
21615
22219
  renderTabContent();
@@ -22362,7 +22966,7 @@ ${rangeText}`;
22362
22966
  maximumFractionDigits: 2
22363
22967
  }).format(value);
22364
22968
  }
22365
- function injectStyles() {
22969
+ function injectStyles2() {
22366
22970
  const styleId = "myio-goals-panel-styles";
22367
22971
  if (document.getElementById(styleId)) return;
22368
22972
  const style = document.createElement("style");
@@ -24619,7 +25223,7 @@ ${rangeText}`;
24619
25223
  function getColors(theme) {
24620
25224
  return theme === "dark" ? DARK_THEME2 : LIGHT_THEME2;
24621
25225
  }
24622
- async function fetchCustomerAttributes(customerId, token) {
25226
+ async function fetchCustomerAttributes(customerId, token, onError) {
24623
25227
  const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/values/attributes/SERVER_SCOPE`;
24624
25228
  const response = await fetch(url, {
24625
25229
  method: "GET",
@@ -24632,6 +25236,10 @@ ${rangeText}`;
24632
25236
  if (response.status === 404 || response.status === 400) {
24633
25237
  return { minTemperature: null, maxTemperature: null };
24634
25238
  }
25239
+ if (onError) {
25240
+ onError({ status: response.status, message: `Failed to fetch attributes: ${response.status}` });
25241
+ return { minTemperature: null, maxTemperature: null };
25242
+ }
24635
25243
  throw new Error(`Failed to fetch attributes: ${response.status}`);
24636
25244
  }
24637
25245
  const attributes = await response.json();
@@ -24648,7 +25256,7 @@ ${rangeText}`;
24648
25256
  }
24649
25257
  return { minTemperature, maxTemperature };
24650
25258
  }
24651
- async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature) {
25259
+ async function saveCustomerAttributes(customerId, token, minTemperature, maxTemperature, onError) {
24652
25260
  const url = `/api/plugins/telemetry/CUSTOMER/${customerId}/SERVER_SCOPE`;
24653
25261
  const attributes = {
24654
25262
  minTemperature,
@@ -24663,6 +25271,10 @@ ${rangeText}`;
24663
25271
  body: JSON.stringify(attributes)
24664
25272
  });
24665
25273
  if (!response.ok) {
25274
+ if (onError) {
25275
+ onError({ status: response.status, message: `Failed to save attributes: ${response.status}` });
25276
+ return;
25277
+ }
24666
25278
  throw new Error(`Failed to save attributes: ${response.status}`);
24667
25279
  }
24668
25280
  }
@@ -25079,7 +25691,7 @@ ${rangeText}`;
25079
25691
  state.successMessage = null;
25080
25692
  renderModal3(container, state, modalId, destroy, handleSave);
25081
25693
  try {
25082
- await saveCustomerAttributes(state.customerId, state.token, min, max);
25694
+ await saveCustomerAttributes(state.customerId, state.token, min, max, params.onError);
25083
25695
  state.minTemperature = min;
25084
25696
  state.maxTemperature = max;
25085
25697
  state.isSaving = false;
@@ -25096,7 +25708,7 @@ ${rangeText}`;
25096
25708
  }
25097
25709
  };
25098
25710
  renderModal3(container, state, modalId, destroy, handleSave);
25099
- fetchCustomerAttributes(state.customerId, state.token).then(({ minTemperature, maxTemperature }) => {
25711
+ fetchCustomerAttributes(state.customerId, state.token, params.onError).then(({ minTemperature, maxTemperature }) => {
25100
25712
  state.minTemperature = minTemperature;
25101
25713
  state.maxTemperature = maxTemperature;
25102
25714
  state.isLoading = false;
@@ -27255,7 +27867,7 @@ ${rangeText}`;
27255
27867
  </div>
27256
27868
  `;
27257
27869
  }
27258
- function injectStyles() {
27870
+ function injectStyles2() {
27259
27871
  if (styleElement) return;
27260
27872
  styleElement = document.createElement("style");
27261
27873
  styleElement.id = `${widgetId}-styles`;
@@ -27736,7 +28348,7 @@ ${rangeText}`;
27736
28348
  console.error(`[ConsumptionWidget] Container #${config.containerId} not found`);
27737
28349
  return;
27738
28350
  }
27739
- injectStyles();
28351
+ injectStyles2();
27740
28352
  containerElement.innerHTML = renderHTML();
27741
28353
  setupListeners();
27742
28354
  setLoading(true);
@@ -28873,6 +29485,7 @@ ${rangeText}`;
28873
29485
  exports.EXPORT_DOMAIN_ICONS = EXPORT_DOMAIN_ICONS;
28874
29486
  exports.EXPORT_DOMAIN_LABELS = EXPORT_DOMAIN_LABELS;
28875
29487
  exports.EXPORT_DOMAIN_UNITS = EXPORT_DOMAIN_UNITS;
29488
+ exports.EnergyRangeTooltip = EnergyRangeTooltip;
28876
29489
  exports.MyIOChartModal = MyIOChartModal;
28877
29490
  exports.MyIODraggableCard = MyIODraggableCard;
28878
29491
  exports.MyIOSelectionStoreClass = MyIOSelectionStoreClass;
@@ -28880,6 +29493,7 @@ ${rangeText}`;
28880
29493
  exports.POWER_LIMITS_DEVICE_TYPES = DEVICE_TYPES;
28881
29494
  exports.POWER_LIMITS_STATUS_CONFIG = STATUS_CONFIG;
28882
29495
  exports.POWER_LIMITS_TELEMETRY_TYPES = TELEMETRY_TYPES2;
29496
+ exports.TempRangeTooltip = TempRangeTooltip;
28883
29497
  exports.addDetectionContext = addDetectionContext;
28884
29498
  exports.addNamespace = addNamespace;
28885
29499
  exports.aggregateByDay = aggregateByDay;