myio-js-library 0.1.162 → 0.1.163

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
@@ -605,6 +605,7 @@ __export(index_exports, {
605
605
  clearAllAuthCaches: () => clearAllAuthCaches,
606
606
  connectionStatusIcons: () => connectionStatusIcons,
607
607
  createConsumption7DaysChart: () => createConsumption7DaysChart,
608
+ createConsumptionChartWidget: () => createConsumptionChartWidget,
608
609
  createConsumptionModal: () => createConsumptionModal,
609
610
  createDateRangePicker: () => createDateRangePicker2,
610
611
  createInputDateRangePickerInsideDIV: () => createInputDateRangePickerInsideDIV,
@@ -23278,7 +23279,7 @@ function createConsumption7DaysChart(config) {
23278
23279
  const isTemperature = config.domain === "temperature";
23279
23280
  let datasets;
23280
23281
  if (currentVizMode === "separate" && data.shoppingData && data.shoppingNames) {
23281
- const shoppingColors = [
23282
+ const shoppingColors = colors.shoppingColors || [
23282
23283
  "#2563eb",
23283
23284
  "#16a34a",
23284
23285
  "#ea580c",
@@ -23963,8 +23964,1275 @@ function createConsumptionModal(config) {
23963
23964
  return instance;
23964
23965
  }
23965
23966
 
23967
+ // src/components/Consumption7DaysChart/createConsumptionChartWidget.ts
23968
+ var DOMAIN_CONFIG4 = {
23969
+ energy: {
23970
+ name: "Energia",
23971
+ icon: "\u26A1",
23972
+ color: "#6c2fbf",
23973
+ colors: ["#2563eb", "#16a34a", "#8b5cf6", "#ea580c", "#dc2626"]
23974
+ },
23975
+ water: {
23976
+ name: "\xC1gua",
23977
+ icon: "\u{1F4A7}",
23978
+ color: "#0288d1",
23979
+ colors: ["#0288d1", "#06b6d4", "#0891b2", "#22d3ee", "#67e8f9"]
23980
+ },
23981
+ gas: {
23982
+ name: "G\xE1s",
23983
+ icon: "\u{1F525}",
23984
+ color: "#ea580c",
23985
+ colors: ["#ea580c", "#f97316", "#fb923c", "#fdba74", "#fed7aa"]
23986
+ },
23987
+ temperature: {
23988
+ name: "Temperatura",
23989
+ icon: "\u{1F321}\uFE0F",
23990
+ color: "#e65100",
23991
+ colors: ["#dc2626", "#059669", "#0ea5e9", "#f59e0b", "#8b5cf6"]
23992
+ }
23993
+ };
23994
+ function getWidgetStyles(theme, primaryColor) {
23995
+ const colors = THEME_COLORS[theme];
23996
+ return `
23997
+ .myio-chart-widget {
23998
+ font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif;
23999
+ background: ${colors.chartBackground};
24000
+ border: 1px solid ${colors.border};
24001
+ border-radius: 16px;
24002
+ overflow: hidden;
24003
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
24004
+ }
24005
+
24006
+ .myio-chart-widget.dark {
24007
+ background: ${THEME_COLORS.dark.chartBackground};
24008
+ border-color: ${THEME_COLORS.dark.border};
24009
+ }
24010
+
24011
+ .myio-chart-widget-header {
24012
+ display: flex;
24013
+ justify-content: space-between;
24014
+ align-items: center;
24015
+ padding: 16px 20px;
24016
+ border-bottom: 1px solid ${colors.border};
24017
+ flex-wrap: wrap;
24018
+ gap: 12px;
24019
+ }
24020
+
24021
+ .myio-chart-widget-title-group {
24022
+ display: flex;
24023
+ align-items: center;
24024
+ gap: 10px;
24025
+ }
24026
+
24027
+ .myio-chart-widget-title {
24028
+ margin: 0;
24029
+ font-size: 16px;
24030
+ font-weight: 600;
24031
+ color: ${colors.text};
24032
+ }
24033
+
24034
+ .myio-chart-widget-controls {
24035
+ display: flex;
24036
+ align-items: center;
24037
+ gap: 12px;
24038
+ flex-wrap: wrap;
24039
+ }
24040
+
24041
+ .myio-chart-widget-tabs {
24042
+ display: flex;
24043
+ gap: 2px;
24044
+ background: ${theme === "dark" ? "#374151" : "#f3f4f6"};
24045
+ padding: 3px;
24046
+ border-radius: 8px;
24047
+ }
24048
+
24049
+ .myio-chart-widget-tab {
24050
+ padding: 6px 14px;
24051
+ font-size: 12px;
24052
+ font-weight: 500;
24053
+ border: none;
24054
+ background: transparent;
24055
+ color: ${colors.textMuted};
24056
+ cursor: pointer;
24057
+ border-radius: 6px;
24058
+ transition: all 0.2s;
24059
+ white-space: nowrap;
24060
+ }
24061
+
24062
+ .myio-chart-widget-tab:hover {
24063
+ color: ${colors.text};
24064
+ background: ${theme === "dark" ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.05)"};
24065
+ }
24066
+
24067
+ .myio-chart-widget-tab.active {
24068
+ background: ${primaryColor};
24069
+ color: white;
24070
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
24071
+ }
24072
+
24073
+ .myio-chart-widget-btn {
24074
+ background: transparent;
24075
+ border: 1px solid ${colors.border};
24076
+ font-size: 16px;
24077
+ cursor: pointer;
24078
+ padding: 6px 10px;
24079
+ border-radius: 6px;
24080
+ transition: all 0.2s;
24081
+ color: ${colors.text};
24082
+ }
24083
+
24084
+ .myio-chart-widget-btn:hover {
24085
+ background: ${primaryColor};
24086
+ border-color: ${primaryColor};
24087
+ color: white;
24088
+ }
24089
+
24090
+ .myio-chart-widget-body {
24091
+ position: relative;
24092
+ padding: 16px 20px;
24093
+ }
24094
+
24095
+ .myio-chart-widget-canvas-container {
24096
+ position: relative;
24097
+ width: 100%;
24098
+ }
24099
+
24100
+ .myio-chart-widget-loading {
24101
+ position: absolute;
24102
+ top: 0;
24103
+ left: 0;
24104
+ right: 0;
24105
+ bottom: 0;
24106
+ background: rgba(255, 255, 255, 0.9);
24107
+ display: flex;
24108
+ align-items: center;
24109
+ justify-content: center;
24110
+ z-index: 10;
24111
+ border-radius: 8px;
24112
+ }
24113
+
24114
+ .myio-chart-widget.dark .myio-chart-widget-loading {
24115
+ background: rgba(31, 41, 55, 0.9);
24116
+ }
24117
+
24118
+ .myio-chart-widget-spinner {
24119
+ width: 32px;
24120
+ height: 32px;
24121
+ border: 3px solid ${colors.border};
24122
+ border-top-color: ${primaryColor};
24123
+ border-radius: 50%;
24124
+ animation: myio-spin 1s linear infinite;
24125
+ }
24126
+
24127
+ @keyframes myio-spin {
24128
+ to { transform: rotate(360deg); }
24129
+ }
24130
+
24131
+ .myio-chart-widget-footer {
24132
+ display: flex;
24133
+ justify-content: space-around;
24134
+ padding: 16px 20px;
24135
+ border-top: 1px solid ${colors.border};
24136
+ gap: 16px;
24137
+ flex-wrap: wrap;
24138
+ }
24139
+
24140
+ .myio-chart-widget-stat {
24141
+ display: flex;
24142
+ flex-direction: column;
24143
+ align-items: center;
24144
+ text-align: center;
24145
+ min-width: 100px;
24146
+ }
24147
+
24148
+ .myio-chart-widget-stat-label {
24149
+ font-size: 11px;
24150
+ font-weight: 500;
24151
+ color: ${colors.textMuted};
24152
+ text-transform: uppercase;
24153
+ letter-spacing: 0.5px;
24154
+ margin-bottom: 4px;
24155
+ }
24156
+
24157
+ .myio-chart-widget-stat-value {
24158
+ font-size: 20px;
24159
+ font-weight: 700;
24160
+ color: ${colors.text};
24161
+ }
24162
+
24163
+ .myio-chart-widget-stat-value.primary {
24164
+ color: ${primaryColor};
24165
+ }
24166
+
24167
+ .myio-chart-widget-stat-sub {
24168
+ font-size: 11px;
24169
+ color: ${colors.textMuted};
24170
+ margin-top: 2px;
24171
+ }
24172
+
24173
+ /* Settings Modal Overlay */
24174
+ .myio-settings-overlay {
24175
+ position: fixed;
24176
+ inset: 0;
24177
+ background: rgba(0, 0, 0, 0.6);
24178
+ display: flex;
24179
+ align-items: center;
24180
+ justify-content: center;
24181
+ z-index: 99999;
24182
+ backdrop-filter: blur(4px);
24183
+ }
24184
+
24185
+ .myio-settings-overlay.hidden {
24186
+ display: none;
24187
+ }
24188
+
24189
+ .myio-settings-card {
24190
+ background: ${colors.chartBackground};
24191
+ border-radius: 10px;
24192
+ width: 90%;
24193
+ max-width: 600px;
24194
+ max-height: 90vh;
24195
+ display: flex;
24196
+ flex-direction: column;
24197
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
24198
+ overflow: hidden;
24199
+ }
24200
+
24201
+ .myio-settings-card .myio-modal-header {
24202
+ border-radius: 10px 10px 0 0;
24203
+ }
24204
+
24205
+ .myio-settings-body {
24206
+ padding: 20px;
24207
+ overflow-y: auto;
24208
+ display: flex;
24209
+ flex-direction: column;
24210
+ gap: 20px;
24211
+ }
24212
+
24213
+ .myio-settings-section {
24214
+ background: ${theme === "dark" ? "rgba(255,255,255,0.05)" : "#f8fafc"};
24215
+ border-radius: 10px;
24216
+ padding: 16px;
24217
+ border: 1px solid ${theme === "dark" ? "rgba(255,255,255,0.1)" : "#e2e8f0"};
24218
+ }
24219
+
24220
+ .myio-settings-section-label {
24221
+ font-size: 13px;
24222
+ font-weight: 600;
24223
+ color: ${colors.text};
24224
+ margin-bottom: 12px;
24225
+ display: flex;
24226
+ align-items: center;
24227
+ gap: 8px;
24228
+ }
24229
+
24230
+ .myio-settings-row {
24231
+ display: flex;
24232
+ gap: 16px;
24233
+ flex-wrap: wrap;
24234
+ align-items: flex-end;
24235
+ }
24236
+
24237
+ .myio-settings-field {
24238
+ display: flex;
24239
+ flex-direction: column;
24240
+ gap: 6px;
24241
+ flex: 1;
24242
+ min-width: 120px;
24243
+ }
24244
+
24245
+ .myio-settings-field-label {
24246
+ font-size: 12px;
24247
+ font-weight: 500;
24248
+ color: ${colors.textMuted};
24249
+ }
24250
+
24251
+ .myio-settings-input,
24252
+ .myio-settings-select {
24253
+ padding: 10px 14px;
24254
+ border: 1px solid ${colors.border};
24255
+ border-radius: 8px;
24256
+ font-size: 14px;
24257
+ background: ${colors.chartBackground};
24258
+ color: ${colors.text};
24259
+ width: 100%;
24260
+ }
24261
+
24262
+ .myio-settings-input:focus,
24263
+ .myio-settings-select:focus {
24264
+ outline: 2px solid ${primaryColor};
24265
+ outline-offset: 1px;
24266
+ }
24267
+
24268
+ .myio-settings-tabs {
24269
+ display: flex;
24270
+ gap: 2px;
24271
+ background: ${theme === "dark" ? "#374151" : "#e5e7eb"};
24272
+ padding: 3px;
24273
+ border-radius: 8px;
24274
+ }
24275
+
24276
+ .myio-settings-tab {
24277
+ flex: 1;
24278
+ padding: 8px 12px;
24279
+ font-size: 12px;
24280
+ font-weight: 500;
24281
+ border: none;
24282
+ background: transparent;
24283
+ color: ${colors.textMuted};
24284
+ cursor: pointer;
24285
+ border-radius: 6px;
24286
+ transition: all 0.2s;
24287
+ white-space: nowrap;
24288
+ }
24289
+
24290
+ .myio-settings-tab:hover {
24291
+ color: ${colors.text};
24292
+ background: ${theme === "dark" ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.05)"};
24293
+ }
24294
+
24295
+ .myio-settings-tab.active {
24296
+ background: ${primaryColor};
24297
+ color: white;
24298
+ }
24299
+
24300
+ .myio-settings-footer {
24301
+ display: flex;
24302
+ gap: 12px;
24303
+ justify-content: flex-end;
24304
+ padding: 16px 20px;
24305
+ border-top: 1px solid ${colors.border};
24306
+ background: ${theme === "dark" ? "rgba(0,0,0,0.2)" : "#fafafa"};
24307
+ }
24308
+
24309
+ .myio-settings-btn {
24310
+ padding: 10px 20px;
24311
+ border-radius: 8px;
24312
+ font-size: 14px;
24313
+ font-weight: 500;
24314
+ cursor: pointer;
24315
+ transition: all 0.2s;
24316
+ }
24317
+
24318
+ .myio-settings-btn-secondary {
24319
+ background: transparent;
24320
+ border: 1px solid ${colors.border};
24321
+ color: ${colors.text};
24322
+ }
24323
+
24324
+ .myio-settings-btn-secondary:hover {
24325
+ background: ${theme === "dark" ? "rgba(255,255,255,0.1)" : "#f3f4f6"};
24326
+ }
24327
+
24328
+ .myio-settings-btn-primary {
24329
+ background: ${primaryColor};
24330
+ border: none;
24331
+ color: white;
24332
+ }
24333
+
24334
+ .myio-settings-btn-primary:hover {
24335
+ filter: brightness(1.1);
24336
+ }
24337
+
24338
+ .myio-settings-hint {
24339
+ font-size: 11px;
24340
+ color: ${colors.textMuted};
24341
+ font-weight: normal;
24342
+ }
24343
+
24344
+ .myio-settings-context-group {
24345
+ margin-bottom: 8px;
24346
+ }
24347
+
24348
+ .myio-settings-context-group:last-child {
24349
+ margin-bottom: 0;
24350
+ }
24351
+
24352
+ /* Dropdown styles */
24353
+ .myio-settings-dropdown-container {
24354
+ position: relative;
24355
+ }
24356
+
24357
+ .myio-settings-dropdown-btn {
24358
+ padding: 10px 14px;
24359
+ border: 1px solid ${colors.border};
24360
+ border-radius: 8px;
24361
+ font-size: 14px;
24362
+ background: ${colors.chartBackground};
24363
+ color: ${colors.text};
24364
+ cursor: pointer;
24365
+ min-width: 180px;
24366
+ display: flex;
24367
+ align-items: center;
24368
+ justify-content: space-between;
24369
+ gap: 8px;
24370
+ width: 100%;
24371
+ }
24372
+
24373
+ .myio-settings-dropdown-btn:hover {
24374
+ border-color: ${primaryColor};
24375
+ }
24376
+
24377
+ .myio-settings-dropdown-arrow {
24378
+ font-size: 10px;
24379
+ color: ${colors.textMuted};
24380
+ }
24381
+
24382
+ .myio-settings-dropdown {
24383
+ position: absolute;
24384
+ top: calc(100% + 4px);
24385
+ left: 0;
24386
+ z-index: 100001;
24387
+ background: ${colors.chartBackground};
24388
+ border: 1px solid ${colors.border};
24389
+ border-radius: 8px;
24390
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
24391
+ min-width: 220px;
24392
+ padding: 8px 0;
24393
+ }
24394
+
24395
+ .myio-settings-dropdown.hidden {
24396
+ display: none;
24397
+ }
24398
+
24399
+ .myio-settings-dropdown-option {
24400
+ display: flex;
24401
+ align-items: center;
24402
+ gap: 10px;
24403
+ padding: 10px 14px;
24404
+ cursor: pointer;
24405
+ font-size: 13px;
24406
+ color: ${colors.text};
24407
+ transition: background 0.15s;
24408
+ }
24409
+
24410
+ .myio-settings-dropdown-option:hover {
24411
+ background: ${theme === "dark" ? "rgba(255,255,255,0.1)" : "#f3f4f6"};
24412
+ }
24413
+
24414
+ .myio-settings-dropdown-option input {
24415
+ width: 16px;
24416
+ height: 16px;
24417
+ cursor: pointer;
24418
+ accent-color: ${primaryColor};
24419
+ }
24420
+
24421
+ .myio-settings-dropdown-actions {
24422
+ border-top: 1px solid ${colors.border};
24423
+ margin-top: 8px;
24424
+ padding: 8px;
24425
+ display: flex;
24426
+ flex-direction: column;
24427
+ gap: 6px;
24428
+ }
24429
+
24430
+ .myio-settings-dropdown-actions button {
24431
+ width: 100%;
24432
+ padding: 8px;
24433
+ background: ${theme === "dark" ? "rgba(255,255,255,0.1)" : "#f3f4f6"};
24434
+ border: none;
24435
+ border-radius: 6px;
24436
+ cursor: pointer;
24437
+ font-size: 12px;
24438
+ color: ${colors.text};
24439
+ transition: background 0.15s;
24440
+ }
24441
+
24442
+ .myio-settings-dropdown-actions button:hover {
24443
+ background: ${theme === "dark" ? "rgba(255,255,255,0.15)" : "#e5e7eb"};
24444
+ }
24445
+
24446
+ /* Suggestion icon styles */
24447
+ .myio-settings-section-label span[id$="-settings-suggestion"] {
24448
+ transition: opacity 0.2s, transform 0.2s;
24449
+ }
24450
+
24451
+ .myio-settings-section-label span[id$="-settings-suggestion"]:hover {
24452
+ opacity: 1 !important;
24453
+ transform: scale(1.2);
24454
+ }
24455
+ `;
24456
+ }
24457
+ function createConsumptionChartWidget(config) {
24458
+ const widgetId = `myio-widget-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
24459
+ let containerElement = null;
24460
+ let chartInstance = null;
24461
+ let styleElement = null;
24462
+ let settingsModalElement = null;
24463
+ let settingsHeaderInstance = null;
24464
+ let currentTheme = config.theme ?? "light";
24465
+ let currentChartType = config.defaultChartType ?? "line";
24466
+ let currentVizMode = config.defaultVizMode ?? "total";
24467
+ let currentPeriod = config.defaultPeriod ?? 7;
24468
+ let currentIdealRange = config.idealRange ?? null;
24469
+ let isLoading = false;
24470
+ let tempPeriod = currentPeriod;
24471
+ let tempChartType = currentChartType;
24472
+ let tempVizMode = currentVizMode;
24473
+ let tempTheme = currentTheme;
24474
+ let tempIdealRange = currentIdealRange;
24475
+ let currentSuggestion = null;
24476
+ const domainCfg = DOMAIN_CONFIG4[config.domain] || DOMAIN_CONFIG4.energy;
24477
+ const primaryColor = config.colors?.primary || domainCfg.color;
24478
+ const domainColors = config.colors?.shoppingColors || domainCfg.colors;
24479
+ const showSettingsButton = config.showSettingsButton ?? true;
24480
+ const showMaximizeButton = config.showMaximizeButton ?? true;
24481
+ const showVizModeTabs = config.showVizModeTabs ?? true;
24482
+ const showChartTypeTabs = config.showChartTypeTabs ?? true;
24483
+ const chartHeight = typeof config.chartHeight === "number" ? `${config.chartHeight}px` : config.chartHeight ?? "300px";
24484
+ function getTitle() {
24485
+ if (config.title) return config.title;
24486
+ const domainName = config.domain === "temperature" ? "Temperatura" : "Consumo";
24487
+ return `${domainName} dos \xFAltimos ${currentPeriod} dias`;
24488
+ }
24489
+ function renderHTML() {
24490
+ return `
24491
+ <div id="${widgetId}" class="myio-chart-widget ${currentTheme === "dark" ? "dark" : ""} ${config.className || ""}">
24492
+ <div class="myio-chart-widget-header">
24493
+ <div class="myio-chart-widget-title-group">
24494
+ ${showSettingsButton ? `
24495
+ <button id="${widgetId}-settings-btn" class="myio-chart-widget-btn" title="Configura\xE7\xF5es">\u2699\uFE0F</button>
24496
+ ` : ""}
24497
+ <h4 id="${widgetId}-title" class="myio-chart-widget-title">${getTitle()}</h4>
24498
+ </div>
24499
+ <div class="myio-chart-widget-controls">
24500
+ ${showVizModeTabs ? `
24501
+ <div class="myio-chart-widget-tabs" id="${widgetId}-viz-tabs">
24502
+ <button class="myio-chart-widget-tab ${currentVizMode === "total" ? "active" : ""}" data-viz="total">Consolidado</button>
24503
+ <button class="myio-chart-widget-tab ${currentVizMode === "separate" ? "active" : ""}" data-viz="separate">Por Shopping</button>
24504
+ </div>
24505
+ ` : ""}
24506
+ ${showChartTypeTabs ? `
24507
+ <div class="myio-chart-widget-tabs" id="${widgetId}-type-tabs">
24508
+ <button class="myio-chart-widget-tab ${currentChartType === "line" ? "active" : ""}" data-type="line">Linhas</button>
24509
+ <button class="myio-chart-widget-tab ${currentChartType === "bar" ? "active" : ""}" data-type="bar">Barras</button>
24510
+ </div>
24511
+ ` : ""}
24512
+ ${showMaximizeButton ? `
24513
+ <button id="${widgetId}-maximize-btn" class="myio-chart-widget-btn" title="Maximizar">\u26F6</button>
24514
+ ` : ""}
24515
+ </div>
24516
+ </div>
24517
+ <div class="myio-chart-widget-body">
24518
+ <div id="${widgetId}-loading" class="myio-chart-widget-loading" style="display: none;">
24519
+ <div class="myio-chart-widget-spinner"></div>
24520
+ </div>
24521
+ <div class="myio-chart-widget-canvas-container" style="height: ${chartHeight};">
24522
+ <canvas id="${widgetId}-canvas"></canvas>
24523
+ </div>
24524
+ </div>
24525
+ <div class="myio-chart-widget-footer" id="${widgetId}-footer">
24526
+ <div class="myio-chart-widget-stat">
24527
+ <span class="myio-chart-widget-stat-label">Total Per\xEDodo</span>
24528
+ <span id="${widgetId}-stat-total" class="myio-chart-widget-stat-value primary">--</span>
24529
+ </div>
24530
+ <div class="myio-chart-widget-stat">
24531
+ <span class="myio-chart-widget-stat-label">M\xE9dia Di\xE1ria</span>
24532
+ <span id="${widgetId}-stat-avg" class="myio-chart-widget-stat-value">--</span>
24533
+ </div>
24534
+ <div class="myio-chart-widget-stat">
24535
+ <span class="myio-chart-widget-stat-label">Dia de Pico</span>
24536
+ <span id="${widgetId}-stat-peak" class="myio-chart-widget-stat-value">--</span>
24537
+ <span id="${widgetId}-stat-peak-date" class="myio-chart-widget-stat-sub"></span>
24538
+ </div>
24539
+ </div>
24540
+ </div>
24541
+ `;
24542
+ }
24543
+ function renderSettingsModal() {
24544
+ const unit = config.unit ?? "";
24545
+ const isTemperature = config.domain === "temperature";
24546
+ settingsHeaderInstance = createModalHeader({
24547
+ id: `${widgetId}-settings`,
24548
+ title: "Configura\xE7\xF5es",
24549
+ icon: "\u2699\uFE0F",
24550
+ theme: tempTheme,
24551
+ backgroundColor: primaryColor,
24552
+ showThemeToggle: false,
24553
+ showMaximize: false,
24554
+ showClose: true,
24555
+ onClose: () => closeSettingsModal()
24556
+ });
24557
+ return `
24558
+ <div id="${widgetId}-settings-overlay" class="myio-settings-overlay hidden">
24559
+ <div class="myio-settings-card">
24560
+ ${settingsHeaderInstance.render()}
24561
+ <div class="myio-settings-body">
24562
+ <!-- CONTEXT 1: Per\xEDodo e Dados -->
24563
+ <div class="myio-settings-context-group">
24564
+ <!-- Per\xEDodo -->
24565
+ <div class="myio-settings-section">
24566
+ <div class="myio-settings-section-label">\u{1F4C5} Per\xEDodo</div>
24567
+ <div class="myio-settings-row">
24568
+ <div class="myio-settings-field" style="flex: 1;">
24569
+ <select id="${widgetId}-settings-period" class="myio-settings-select">
24570
+ <option value="7" ${tempPeriod === 7 ? "selected" : ""}>\xDAltimos 7 dias</option>
24571
+ <option value="14" ${tempPeriod === 14 ? "selected" : ""}>\xDAltimos 14 dias</option>
24572
+ <option value="30" ${tempPeriod === 30 ? "selected" : ""}>\xDAltimos 30 dias</option>
24573
+ <option value="60" ${tempPeriod === 60 ? "selected" : ""}>\xDAltimos 60 dias</option>
24574
+ <option value="90" ${tempPeriod === 90 ? "selected" : ""}>\xDAltimos 90 dias</option>
24575
+ </select>
24576
+ </div>
24577
+ </div>
24578
+ </div>
24579
+
24580
+ <!-- Dados -->
24581
+ <div class="myio-settings-section">
24582
+ <div class="myio-settings-section-label">\u{1F4CA} Dados</div>
24583
+ <div class="myio-settings-row">
24584
+ <!-- Granularity Select -->
24585
+ <div class="myio-settings-field">
24586
+ <label class="myio-settings-field-label">Granularidade</label>
24587
+ <select id="${widgetId}-settings-granularity" class="myio-settings-select">
24588
+ <option value="1d" selected>\u{1F4C6} Por Dia</option>
24589
+ <option value="1h">\u{1F550} Por Hora</option>
24590
+ </select>
24591
+ </div>
24592
+
24593
+ <!-- Weekday Filter -->
24594
+ <div class="myio-settings-field">
24595
+ <label class="myio-settings-field-label">Dias da Semana</label>
24596
+ <div class="myio-settings-dropdown-container">
24597
+ <button type="button" id="${widgetId}-settings-weekday-btn" class="myio-settings-dropdown-btn">
24598
+ <span id="${widgetId}-settings-weekday-label">Todos os dias</span>
24599
+ <span class="myio-settings-dropdown-arrow">\u25BC</span>
24600
+ </button>
24601
+ <div id="${widgetId}-settings-weekday-dropdown" class="myio-settings-dropdown hidden">
24602
+ <label class="myio-settings-dropdown-option">
24603
+ <input type="checkbox" name="${widgetId}-weekday" value="dom" checked /> Domingo
24604
+ </label>
24605
+ <label class="myio-settings-dropdown-option">
24606
+ <input type="checkbox" name="${widgetId}-weekday" value="seg" checked /> Segunda-feira
24607
+ </label>
24608
+ <label class="myio-settings-dropdown-option">
24609
+ <input type="checkbox" name="${widgetId}-weekday" value="ter" checked /> Ter\xE7a-feira
24610
+ </label>
24611
+ <label class="myio-settings-dropdown-option">
24612
+ <input type="checkbox" name="${widgetId}-weekday" value="qua" checked /> Quarta-feira
24613
+ </label>
24614
+ <label class="myio-settings-dropdown-option">
24615
+ <input type="checkbox" name="${widgetId}-weekday" value="qui" checked /> Quinta-feira
24616
+ </label>
24617
+ <label class="myio-settings-dropdown-option">
24618
+ <input type="checkbox" name="${widgetId}-weekday" value="sex" checked /> Sexta-feira
24619
+ </label>
24620
+ <label class="myio-settings-dropdown-option">
24621
+ <input type="checkbox" name="${widgetId}-weekday" value="sab" checked /> S\xE1bado
24622
+ </label>
24623
+ <div class="myio-settings-dropdown-actions">
24624
+ <button type="button" id="${widgetId}-settings-weekday-all">Selecionar Todos</button>
24625
+ <button type="button" id="${widgetId}-settings-weekday-clear">Limpar</button>
24626
+ </div>
24627
+ </div>
24628
+ </div>
24629
+ </div>
24630
+
24631
+ <!-- Day Period Filter (only visible when hourly) -->
24632
+ <div class="myio-settings-field" id="${widgetId}-settings-dayperiod-field" style="display: none;">
24633
+ <label class="myio-settings-field-label">Per\xEDodos do Dia</label>
24634
+ <div class="myio-settings-dropdown-container">
24635
+ <button type="button" id="${widgetId}-settings-dayperiod-btn" class="myio-settings-dropdown-btn">
24636
+ <span id="${widgetId}-settings-dayperiod-label">Todos os per\xEDodos</span>
24637
+ <span class="myio-settings-dropdown-arrow">\u25BC</span>
24638
+ </button>
24639
+ <div id="${widgetId}-settings-dayperiod-dropdown" class="myio-settings-dropdown hidden">
24640
+ <label class="myio-settings-dropdown-option">
24641
+ <input type="checkbox" name="${widgetId}-dayperiod" value="madrugada" checked /> Madrugada (00h-06h)
24642
+ </label>
24643
+ <label class="myio-settings-dropdown-option">
24644
+ <input type="checkbox" name="${widgetId}-dayperiod" value="manha" checked /> Manh\xE3 (06h-12h)
24645
+ </label>
24646
+ <label class="myio-settings-dropdown-option">
24647
+ <input type="checkbox" name="${widgetId}-dayperiod" value="tarde" checked /> Tarde (12h-18h)
24648
+ </label>
24649
+ <label class="myio-settings-dropdown-option">
24650
+ <input type="checkbox" name="${widgetId}-dayperiod" value="noite" checked /> Noite (18h-24h)
24651
+ </label>
24652
+ <div class="myio-settings-dropdown-actions">
24653
+ <button type="button" id="${widgetId}-settings-dayperiod-all">Selecionar Todos</button>
24654
+ <button type="button" id="${widgetId}-settings-dayperiod-clear">Limpar</button>
24655
+ </div>
24656
+ </div>
24657
+ </div>
24658
+ </div>
24659
+ </div>
24660
+ </div>
24661
+ </div>
24662
+
24663
+ <!-- CONTEXT 2: Faixa Ideal -->
24664
+ <div class="myio-settings-context-group">
24665
+ <div class="myio-settings-section">
24666
+ <div class="myio-settings-section-label">
24667
+ \u{1F3AF} Faixa Ideal
24668
+ <span class="myio-settings-hint" id="${widgetId}-settings-range-hint">(opcional - deixe zerado para n\xE3o exibir)</span>
24669
+ <span
24670
+ id="${widgetId}-settings-suggestion"
24671
+ title=""
24672
+ style="cursor: pointer; font-size: 16px; opacity: 0.7; transition: opacity 0.2s; margin-left: 4px;"
24673
+ >\u{1F4A1}</span>
24674
+ </div>
24675
+ <div class="myio-settings-row">
24676
+ <div class="myio-settings-field" style="min-width: 100px;">
24677
+ <label class="myio-settings-field-label">M\xEDnimo (${unit})</label>
24678
+ <input type="number" id="${widgetId}-settings-range-min" class="myio-settings-input"
24679
+ value="${tempIdealRange?.min ?? ""}" placeholder="0" step="0.1">
24680
+ </div>
24681
+ <div class="myio-settings-field" style="min-width: 100px;">
24682
+ <label class="myio-settings-field-label">M\xE1ximo (${unit})</label>
24683
+ <input type="number" id="${widgetId}-settings-range-max" class="myio-settings-input"
24684
+ value="${tempIdealRange?.max ?? ""}" placeholder="0" step="0.1">
24685
+ </div>
24686
+ <div class="myio-settings-field" style="flex: 1;">
24687
+ <label class="myio-settings-field-label">R\xF3tulo</label>
24688
+ <input type="text" id="${widgetId}-settings-range-label" class="myio-settings-input"
24689
+ value="${tempIdealRange?.label ?? ""}" placeholder="${isTemperature ? "Faixa Ideal" : "Meta de Consumo"}">
24690
+ </div>
24691
+ </div>
24692
+ </div>
24693
+ </div>
24694
+
24695
+ <!-- CONTEXT 3: Visualiza\xE7\xE3o -->
24696
+ <div class="myio-settings-context-group">
24697
+ <div class="myio-settings-section">
24698
+ <div class="myio-settings-section-label">\u{1F3A8} Visualiza\xE7\xE3o</div>
24699
+ <div class="myio-settings-row" style="gap: 20px; flex-wrap: wrap;">
24700
+ <!-- Chart Type -->
24701
+ <div class="myio-settings-field" style="flex: 1; min-width: 180px;">
24702
+ <label class="myio-settings-field-label">Tipo de Gr\xE1fico</label>
24703
+ <div class="myio-settings-tabs" id="${widgetId}-settings-chart-type">
24704
+ <button class="myio-settings-tab ${tempChartType === "line" ? "active" : ""}" data-type="line">\u{1F4C8} Linhas</button>
24705
+ <button class="myio-settings-tab ${tempChartType === "bar" ? "active" : ""}" data-type="bar">\u{1F4CA} Barras</button>
24706
+ </div>
24707
+ </div>
24708
+
24709
+ <!-- Viz Mode -->
24710
+ <div class="myio-settings-field" style="flex: 1; min-width: 200px;">
24711
+ <label class="myio-settings-field-label">Agrupamento</label>
24712
+ <div class="myio-settings-tabs" id="${widgetId}-settings-viz-mode">
24713
+ <button class="myio-settings-tab ${tempVizMode === "total" ? "active" : ""}" data-viz="total">\u{1F517} Consolidado</button>
24714
+ <button class="myio-settings-tab ${tempVizMode === "separate" ? "active" : ""}" data-viz="separate">\u{1F3EC} Por Shopping</button>
24715
+ </div>
24716
+ </div>
24717
+
24718
+ <!-- Theme -->
24719
+ <div class="myio-settings-field" style="flex: 1; min-width: 160px;">
24720
+ <label class="myio-settings-field-label">Tema</label>
24721
+ <div class="myio-settings-tabs" id="${widgetId}-settings-theme">
24722
+ <button class="myio-settings-tab ${tempTheme === "light" ? "active" : ""}" data-theme="light">\u2600\uFE0F Light</button>
24723
+ <button class="myio-settings-tab ${tempTheme === "dark" ? "active" : ""}" data-theme="dark">\u{1F319} Dark</button>
24724
+ </div>
24725
+ </div>
24726
+ </div>
24727
+ </div>
24728
+ </div>
24729
+ </div>
24730
+ <div class="myio-settings-footer">
24731
+ <button id="${widgetId}-settings-reset" class="myio-settings-btn myio-settings-btn-secondary">Resetar</button>
24732
+ <button id="${widgetId}-settings-apply" class="myio-settings-btn myio-settings-btn-primary">Carregar</button>
24733
+ </div>
24734
+ </div>
24735
+ </div>
24736
+ `;
24737
+ }
24738
+ function injectStyles() {
24739
+ if (styleElement) return;
24740
+ styleElement = document.createElement("style");
24741
+ styleElement.id = `${widgetId}-styles`;
24742
+ styleElement.textContent = getWidgetStyles(currentTheme, primaryColor);
24743
+ document.head.appendChild(styleElement);
24744
+ }
24745
+ function updateStyles() {
24746
+ if (styleElement) {
24747
+ styleElement.textContent = getWidgetStyles(currentTheme, primaryColor);
24748
+ }
24749
+ }
24750
+ function setupListeners() {
24751
+ if (showSettingsButton) {
24752
+ document.getElementById(`${widgetId}-settings-btn`)?.addEventListener("click", () => {
24753
+ openSettingsModal();
24754
+ config.onSettingsClick?.();
24755
+ });
24756
+ }
24757
+ if (showMaximizeButton && config.onMaximizeClick) {
24758
+ document.getElementById(`${widgetId}-maximize-btn`)?.addEventListener("click", () => {
24759
+ config.onMaximizeClick?.();
24760
+ });
24761
+ }
24762
+ if (showVizModeTabs) {
24763
+ document.getElementById(`${widgetId}-viz-tabs`)?.addEventListener("click", (e) => {
24764
+ const target = e.target;
24765
+ if (target.classList.contains("myio-chart-widget-tab")) {
24766
+ const mode = target.dataset.viz;
24767
+ if (mode) {
24768
+ instance.setVizMode(mode);
24769
+ }
24770
+ }
24771
+ });
24772
+ }
24773
+ if (showChartTypeTabs) {
24774
+ document.getElementById(`${widgetId}-type-tabs`)?.addEventListener("click", (e) => {
24775
+ const target = e.target;
24776
+ if (target.classList.contains("myio-chart-widget-tab")) {
24777
+ const type = target.dataset.type;
24778
+ if (type) {
24779
+ instance.setChartType(type);
24780
+ }
24781
+ }
24782
+ });
24783
+ }
24784
+ }
24785
+ function updateTabStates() {
24786
+ document.querySelectorAll(`#${widgetId}-viz-tabs .myio-chart-widget-tab`).forEach((tab) => {
24787
+ const btn = tab;
24788
+ btn.classList.toggle("active", btn.dataset.viz === currentVizMode);
24789
+ });
24790
+ document.querySelectorAll(`#${widgetId}-type-tabs .myio-chart-widget-tab`).forEach((tab) => {
24791
+ const btn = tab;
24792
+ btn.classList.toggle("active", btn.dataset.type === currentChartType);
24793
+ });
24794
+ }
24795
+ function updateTitle() {
24796
+ const titleEl = document.getElementById(`${widgetId}-title`);
24797
+ if (titleEl) {
24798
+ titleEl.textContent = getTitle();
24799
+ }
24800
+ }
24801
+ function setLoading(loading) {
24802
+ isLoading = loading;
24803
+ const loadingEl = document.getElementById(`${widgetId}-loading`);
24804
+ if (loadingEl) {
24805
+ loadingEl.style.display = loading ? "flex" : "none";
24806
+ }
24807
+ }
24808
+ function formatValue(value) {
24809
+ const unit = config.unit ?? "";
24810
+ const unitLarge = config.unitLarge;
24811
+ const threshold = config.thresholdForLargeUnit ?? 1e3;
24812
+ if (unitLarge && Math.abs(value) >= threshold) {
24813
+ return `${(value / threshold).toFixed(2)} ${unitLarge}`;
24814
+ }
24815
+ return `${value.toFixed(2)} ${unit}`;
24816
+ }
24817
+ function updateFooterStats(data) {
24818
+ const totalEl = document.getElementById(`${widgetId}-stat-total`);
24819
+ const avgEl = document.getElementById(`${widgetId}-stat-avg`);
24820
+ const peakEl = document.getElementById(`${widgetId}-stat-peak`);
24821
+ const peakDateEl = document.getElementById(`${widgetId}-stat-peak-date`);
24822
+ if (!data.dailyTotals || data.dailyTotals.length === 0) {
24823
+ if (totalEl) totalEl.textContent = "--";
24824
+ if (avgEl) avgEl.textContent = "--";
24825
+ if (peakEl) peakEl.textContent = "--";
24826
+ if (peakDateEl) peakDateEl.textContent = "";
24827
+ return;
24828
+ }
24829
+ const isTemperature = config.domain === "temperature";
24830
+ const totals = data.dailyTotals;
24831
+ const labels = data.labels ?? [];
24832
+ const total = totals.reduce((a, b) => a + b, 0);
24833
+ const avg = total / totals.length;
24834
+ const peakValue = Math.max(...totals);
24835
+ const peakIndex = totals.indexOf(peakValue);
24836
+ const peakDate = labels[peakIndex] ?? "";
24837
+ if (totalEl) {
24838
+ if (isTemperature) {
24839
+ totalEl.textContent = formatValue(avg);
24840
+ const labelEl = totalEl.previousElementSibling;
24841
+ if (labelEl) labelEl.textContent = "M\xE9dia Per\xEDodo";
24842
+ } else {
24843
+ totalEl.textContent = formatValue(total);
24844
+ }
24845
+ }
24846
+ if (avgEl) {
24847
+ avgEl.textContent = formatValue(avg);
24848
+ }
24849
+ if (peakEl) {
24850
+ peakEl.textContent = formatValue(peakValue);
24851
+ }
24852
+ if (peakDateEl) {
24853
+ peakDateEl.textContent = peakDate;
24854
+ }
24855
+ }
24856
+ function openSettingsModal() {
24857
+ tempPeriod = currentPeriod;
24858
+ tempChartType = currentChartType;
24859
+ tempVizMode = currentVizMode;
24860
+ tempTheme = currentTheme;
24861
+ tempIdealRange = currentIdealRange ? { ...currentIdealRange } : null;
24862
+ if (!settingsModalElement) {
24863
+ settingsModalElement = document.createElement("div");
24864
+ settingsModalElement.innerHTML = renderSettingsModal();
24865
+ document.body.appendChild(settingsModalElement.firstElementChild);
24866
+ settingsModalElement = document.getElementById(`${widgetId}-settings-overlay`);
24867
+ setupSettingsModalListeners();
24868
+ }
24869
+ updateSettingsModalValues();
24870
+ updateIdealRangeSuggestionTooltip();
24871
+ settingsModalElement?.classList.remove("hidden");
24872
+ }
24873
+ function closeSettingsModal() {
24874
+ settingsModalElement?.classList.add("hidden");
24875
+ }
24876
+ function updateSettingsModalValues() {
24877
+ const periodSelect = document.getElementById(`${widgetId}-settings-period`);
24878
+ if (periodSelect) periodSelect.value = String(tempPeriod);
24879
+ const minInput = document.getElementById(`${widgetId}-settings-range-min`);
24880
+ const maxInput = document.getElementById(`${widgetId}-settings-range-max`);
24881
+ const labelInput = document.getElementById(`${widgetId}-settings-range-label`);
24882
+ if (minInput) minInput.value = tempIdealRange?.min?.toString() ?? "";
24883
+ if (maxInput) maxInput.value = tempIdealRange?.max?.toString() ?? "";
24884
+ if (labelInput) labelInput.value = tempIdealRange?.label ?? "";
24885
+ updateSettingsModalTabs();
24886
+ }
24887
+ function updateSettingsModalTabs() {
24888
+ document.querySelectorAll(`#${widgetId}-settings-chart-type .myio-settings-tab`).forEach((tab) => {
24889
+ const btn = tab;
24890
+ btn.classList.toggle("active", btn.dataset.type === tempChartType);
24891
+ });
24892
+ document.querySelectorAll(`#${widgetId}-settings-viz-mode .myio-settings-tab`).forEach((tab) => {
24893
+ const btn = tab;
24894
+ btn.classList.toggle("active", btn.dataset.viz === tempVizMode);
24895
+ });
24896
+ document.querySelectorAll(`#${widgetId}-settings-theme .myio-settings-tab`).forEach((tab) => {
24897
+ const btn = tab;
24898
+ btn.classList.toggle("active", btn.dataset.theme === tempTheme);
24899
+ });
24900
+ }
24901
+ function updateWeekdayLabel() {
24902
+ const checkboxes = document.querySelectorAll(`input[name="${widgetId}-weekday"]`);
24903
+ const checked = Array.from(checkboxes).filter((cb) => cb.checked);
24904
+ const label = document.getElementById(`${widgetId}-settings-weekday-label`);
24905
+ if (label) {
24906
+ if (checked.length === 0) {
24907
+ label.textContent = "Nenhum dia";
24908
+ } else if (checked.length === checkboxes.length) {
24909
+ label.textContent = "Todos os dias";
24910
+ } else {
24911
+ label.textContent = `${checked.length} dias selecionados`;
24912
+ }
24913
+ }
24914
+ }
24915
+ function updateDayPeriodLabel() {
24916
+ const checkboxes = document.querySelectorAll(`input[name="${widgetId}-dayperiod"]`);
24917
+ const checked = Array.from(checkboxes).filter((cb) => cb.checked);
24918
+ const label = document.getElementById(`${widgetId}-settings-dayperiod-label`);
24919
+ if (label) {
24920
+ if (checked.length === 0) {
24921
+ label.textContent = "Nenhum per\xEDodo";
24922
+ } else if (checked.length === checkboxes.length) {
24923
+ label.textContent = "Todos os per\xEDodos";
24924
+ } else {
24925
+ label.textContent = `${checked.length} per\xEDodos selecionados`;
24926
+ }
24927
+ }
24928
+ }
24929
+ function calculateIdealRangeSuggestion() {
24930
+ const data = chartInstance?.getCachedData();
24931
+ if (!data || !data.dailyTotals || data.dailyTotals.length === 0) {
24932
+ return { min: 0, max: 0, avg: 0 };
24933
+ }
24934
+ const total = data.dailyTotals.reduce((a, b) => a + b, 0);
24935
+ const avg = total / data.dailyTotals.length;
24936
+ const min = avg * 0.85;
24937
+ const max = avg * 1.15;
24938
+ return {
24939
+ min: Math.round(min * 10) / 10,
24940
+ max: Math.round(max * 10) / 10,
24941
+ avg: Math.round(avg * 10) / 10
24942
+ };
24943
+ }
24944
+ function updateIdealRangeSuggestionTooltip() {
24945
+ const suggestion = calculateIdealRangeSuggestion();
24946
+ const suggestionEl = document.getElementById(`${widgetId}-settings-suggestion`);
24947
+ const hintEl = document.getElementById(`${widgetId}-settings-range-hint`);
24948
+ const unit = config.unit ?? "";
24949
+ const isTemperature = config.domain === "temperature";
24950
+ currentSuggestion = suggestion;
24951
+ if (hintEl) {
24952
+ if (isTemperature) {
24953
+ hintEl.textContent = "(valores carregados do cliente)";
24954
+ } else {
24955
+ hintEl.textContent = "(opcional - deixe zerado para n\xE3o exibir)";
24956
+ }
24957
+ }
24958
+ if (suggestionEl) {
24959
+ if (suggestion.avg > 0) {
24960
+ const tooltipText = `Sugest\xE3o: ${suggestion.min} - ${suggestion.max} ${unit} (m\xE9dia \xB115%). Clique para aplicar.`;
24961
+ suggestionEl.title = tooltipText;
24962
+ suggestionEl.style.display = "inline";
24963
+ } else {
24964
+ suggestionEl.style.display = "none";
24965
+ }
24966
+ }
24967
+ }
24968
+ function applyIdealRangeSuggestion() {
24969
+ if (!currentSuggestion || currentSuggestion.min === 0 && currentSuggestion.max === 0) {
24970
+ return;
24971
+ }
24972
+ const minInput = document.getElementById(`${widgetId}-settings-range-min`);
24973
+ const maxInput = document.getElementById(`${widgetId}-settings-range-max`);
24974
+ const labelInput = document.getElementById(`${widgetId}-settings-range-label`);
24975
+ if (minInput) minInput.value = String(currentSuggestion.min);
24976
+ if (maxInput) maxInput.value = String(currentSuggestion.max);
24977
+ if (labelInput) labelInput.value = "Faixa Sugerida";
24978
+ tempIdealRange = {
24979
+ min: currentSuggestion.min,
24980
+ max: currentSuggestion.max,
24981
+ label: "Faixa Sugerida"
24982
+ };
24983
+ }
24984
+ function setupSettingsModalListeners() {
24985
+ settingsHeaderInstance?.attachListeners();
24986
+ document.getElementById(`${widgetId}-settings-overlay`)?.addEventListener("click", (e) => {
24987
+ if (e.target.classList.contains("myio-settings-overlay")) {
24988
+ closeSettingsModal();
24989
+ }
24990
+ });
24991
+ document.getElementById(`${widgetId}-settings-granularity`)?.addEventListener("change", (e) => {
24992
+ const select = e.target;
24993
+ const dayPeriodField = document.getElementById(`${widgetId}-settings-dayperiod-field`);
24994
+ if (dayPeriodField) {
24995
+ dayPeriodField.style.display = select.value === "1h" ? "block" : "none";
24996
+ }
24997
+ });
24998
+ document.getElementById(`${widgetId}-settings-suggestion`)?.addEventListener("click", () => {
24999
+ applyIdealRangeSuggestion();
25000
+ });
25001
+ document.getElementById(`${widgetId}-settings-weekday-btn`)?.addEventListener("click", (e) => {
25002
+ e.stopPropagation();
25003
+ const dropdown = document.getElementById(`${widgetId}-settings-weekday-dropdown`);
25004
+ dropdown?.classList.toggle("hidden");
25005
+ });
25006
+ document.querySelectorAll(`input[name="${widgetId}-weekday"]`).forEach((cb) => {
25007
+ cb.addEventListener("change", updateWeekdayLabel);
25008
+ });
25009
+ document.getElementById(`${widgetId}-settings-weekday-all`)?.addEventListener("click", () => {
25010
+ document.querySelectorAll(`input[name="${widgetId}-weekday"]`).forEach((cb) => {
25011
+ cb.checked = true;
25012
+ });
25013
+ updateWeekdayLabel();
25014
+ });
25015
+ document.getElementById(`${widgetId}-settings-weekday-clear`)?.addEventListener("click", () => {
25016
+ document.querySelectorAll(`input[name="${widgetId}-weekday"]`).forEach((cb) => {
25017
+ cb.checked = false;
25018
+ });
25019
+ updateWeekdayLabel();
25020
+ });
25021
+ document.getElementById(`${widgetId}-settings-dayperiod-btn`)?.addEventListener("click", (e) => {
25022
+ e.stopPropagation();
25023
+ const dropdown = document.getElementById(`${widgetId}-settings-dayperiod-dropdown`);
25024
+ dropdown?.classList.toggle("hidden");
25025
+ });
25026
+ document.querySelectorAll(`input[name="${widgetId}-dayperiod"]`).forEach((cb) => {
25027
+ cb.addEventListener("change", updateDayPeriodLabel);
25028
+ });
25029
+ document.getElementById(`${widgetId}-settings-dayperiod-all`)?.addEventListener("click", () => {
25030
+ document.querySelectorAll(`input[name="${widgetId}-dayperiod"]`).forEach((cb) => {
25031
+ cb.checked = true;
25032
+ });
25033
+ updateDayPeriodLabel();
25034
+ });
25035
+ document.getElementById(`${widgetId}-settings-dayperiod-clear`)?.addEventListener("click", () => {
25036
+ document.querySelectorAll(`input[name="${widgetId}-dayperiod"]`).forEach((cb) => {
25037
+ cb.checked = false;
25038
+ });
25039
+ updateDayPeriodLabel();
25040
+ });
25041
+ document.addEventListener("click", (e) => {
25042
+ const target = e.target;
25043
+ const weekdayDropdown = document.getElementById(`${widgetId}-settings-weekday-dropdown`);
25044
+ const dayperiodDropdown = document.getElementById(`${widgetId}-settings-dayperiod-dropdown`);
25045
+ if (weekdayDropdown && !target.closest(`#${widgetId}-settings-weekday-btn`) && !target.closest(`#${widgetId}-settings-weekday-dropdown`)) {
25046
+ weekdayDropdown.classList.add("hidden");
25047
+ }
25048
+ if (dayperiodDropdown && !target.closest(`#${widgetId}-settings-dayperiod-btn`) && !target.closest(`#${widgetId}-settings-dayperiod-dropdown`)) {
25049
+ dayperiodDropdown.classList.add("hidden");
25050
+ }
25051
+ });
25052
+ document.getElementById(`${widgetId}-settings-chart-type`)?.addEventListener("click", (e) => {
25053
+ const target = e.target;
25054
+ if (target.classList.contains("myio-settings-tab")) {
25055
+ tempChartType = target.dataset.type;
25056
+ updateSettingsModalTabs();
25057
+ }
25058
+ });
25059
+ document.getElementById(`${widgetId}-settings-viz-mode`)?.addEventListener("click", (e) => {
25060
+ const target = e.target;
25061
+ if (target.classList.contains("myio-settings-tab")) {
25062
+ tempVizMode = target.dataset.viz;
25063
+ updateSettingsModalTabs();
25064
+ }
25065
+ });
25066
+ document.getElementById(`${widgetId}-settings-theme`)?.addEventListener("click", (e) => {
25067
+ const target = e.target;
25068
+ if (target.classList.contains("myio-settings-tab")) {
25069
+ tempTheme = target.dataset.theme;
25070
+ updateSettingsModalTabs();
25071
+ }
25072
+ });
25073
+ document.getElementById(`${widgetId}-settings-reset`)?.addEventListener("click", () => {
25074
+ tempPeriod = config.defaultPeriod ?? 7;
25075
+ tempChartType = config.defaultChartType ?? "line";
25076
+ tempVizMode = config.defaultVizMode ?? "total";
25077
+ tempTheme = config.theme ?? "light";
25078
+ tempIdealRange = config.idealRange ?? null;
25079
+ const granularitySelect = document.getElementById(`${widgetId}-settings-granularity`);
25080
+ if (granularitySelect) granularitySelect.value = "1d";
25081
+ const dayPeriodField = document.getElementById(`${widgetId}-settings-dayperiod-field`);
25082
+ if (dayPeriodField) dayPeriodField.style.display = "none";
25083
+ document.querySelectorAll(`input[name="${widgetId}-weekday"]`).forEach((cb) => {
25084
+ cb.checked = true;
25085
+ });
25086
+ updateWeekdayLabel();
25087
+ document.querySelectorAll(`input[name="${widgetId}-dayperiod"]`).forEach((cb) => {
25088
+ cb.checked = true;
25089
+ });
25090
+ updateDayPeriodLabel();
25091
+ updateSettingsModalValues();
25092
+ });
25093
+ document.getElementById(`${widgetId}-settings-apply`)?.addEventListener("click", async () => {
25094
+ const minInput = document.getElementById(`${widgetId}-settings-range-min`);
25095
+ const maxInput = document.getElementById(`${widgetId}-settings-range-max`);
25096
+ const labelInput = document.getElementById(`${widgetId}-settings-range-label`);
25097
+ const periodSelect = document.getElementById(`${widgetId}-settings-period`);
25098
+ const min = parseFloat(minInput?.value || "0");
25099
+ const max = parseFloat(maxInput?.value || "0");
25100
+ const label = labelInput?.value || "";
25101
+ tempPeriod = parseInt(periodSelect?.value || "7", 10);
25102
+ if (min > 0 || max > 0) {
25103
+ tempIdealRange = { min, max, label };
25104
+ } else {
25105
+ tempIdealRange = null;
25106
+ }
25107
+ closeSettingsModal();
25108
+ if (tempTheme !== currentTheme) {
25109
+ instance.setTheme(tempTheme);
25110
+ }
25111
+ if (tempChartType !== currentChartType) {
25112
+ instance.setChartType(tempChartType);
25113
+ }
25114
+ if (tempVizMode !== currentVizMode) {
25115
+ instance.setVizMode(tempVizMode);
25116
+ }
25117
+ if (JSON.stringify(tempIdealRange) !== JSON.stringify(currentIdealRange)) {
25118
+ instance.setIdealRange(tempIdealRange);
25119
+ }
25120
+ if (tempPeriod !== currentPeriod) {
25121
+ await instance.setPeriod(tempPeriod);
25122
+ }
25123
+ });
25124
+ }
25125
+ const instance = {
25126
+ async render() {
25127
+ containerElement = document.getElementById(config.containerId);
25128
+ if (!containerElement) {
25129
+ console.error(`[ConsumptionWidget] Container #${config.containerId} not found`);
25130
+ return;
25131
+ }
25132
+ injectStyles();
25133
+ containerElement.innerHTML = renderHTML();
25134
+ setupListeners();
25135
+ setLoading(true);
25136
+ chartInstance = createConsumption7DaysChart({
25137
+ ...config,
25138
+ containerId: `${widgetId}-canvas`,
25139
+ theme: currentTheme,
25140
+ defaultChartType: currentChartType,
25141
+ defaultVizMode: currentVizMode,
25142
+ defaultPeriod: currentPeriod,
25143
+ idealRange: currentIdealRange,
25144
+ colors: {
25145
+ primary: primaryColor,
25146
+ background: `${primaryColor}20`,
25147
+ shoppingColors: domainColors,
25148
+ ...config.colors
25149
+ },
25150
+ onDataLoaded: (data) => {
25151
+ setLoading(false);
25152
+ updateFooterStats(data);
25153
+ config.onDataLoaded?.(data);
25154
+ },
25155
+ onError: (error) => {
25156
+ setLoading(false);
25157
+ config.onError?.(error);
25158
+ }
25159
+ });
25160
+ await chartInstance.render();
25161
+ setLoading(false);
25162
+ },
25163
+ async refresh(forceRefresh = false) {
25164
+ if (!chartInstance) return;
25165
+ setLoading(true);
25166
+ await chartInstance.refresh(forceRefresh);
25167
+ setLoading(false);
25168
+ },
25169
+ setChartType(type) {
25170
+ if (currentChartType === type) return;
25171
+ currentChartType = type;
25172
+ chartInstance?.setChartType(type);
25173
+ updateTabStates();
25174
+ },
25175
+ setVizMode(mode) {
25176
+ if (currentVizMode === mode) return;
25177
+ currentVizMode = mode;
25178
+ chartInstance?.setVizMode(mode);
25179
+ updateTabStates();
25180
+ },
25181
+ setTheme(theme) {
25182
+ if (currentTheme === theme) return;
25183
+ currentTheme = theme;
25184
+ chartInstance?.setTheme(theme);
25185
+ const widget = document.getElementById(widgetId);
25186
+ if (widget) {
25187
+ widget.classList.toggle("dark", theme === "dark");
25188
+ }
25189
+ updateStyles();
25190
+ },
25191
+ async setPeriod(days) {
25192
+ if (currentPeriod === days) return;
25193
+ currentPeriod = days;
25194
+ updateTitle();
25195
+ setLoading(true);
25196
+ await chartInstance?.setPeriod(days);
25197
+ setLoading(false);
25198
+ },
25199
+ setIdealRange(range) {
25200
+ currentIdealRange = range;
25201
+ chartInstance?.setIdealRange(range);
25202
+ },
25203
+ getChart() {
25204
+ return chartInstance;
25205
+ },
25206
+ getCachedData() {
25207
+ return chartInstance?.getCachedData() ?? null;
25208
+ },
25209
+ exportCSV(filename) {
25210
+ chartInstance?.exportCSV(filename);
25211
+ },
25212
+ destroy() {
25213
+ chartInstance?.destroy();
25214
+ chartInstance = null;
25215
+ if (styleElement) {
25216
+ styleElement.remove();
25217
+ styleElement = null;
25218
+ }
25219
+ settingsHeaderInstance?.destroy();
25220
+ settingsHeaderInstance = null;
25221
+ if (settingsModalElement) {
25222
+ settingsModalElement.remove();
25223
+ settingsModalElement = null;
25224
+ }
25225
+ if (containerElement) {
25226
+ containerElement.innerHTML = "";
25227
+ containerElement = null;
25228
+ }
25229
+ }
25230
+ };
25231
+ return instance;
25232
+ }
25233
+
23966
25234
  // src/components/ExportData/index.ts
23967
- var DEFAULT_COLORS3 = {
25235
+ var DEFAULT_COLORS4 = {
23968
25236
  primary: "#3e1a7d",
23969
25237
  // MyIO purple
23970
25238
  secondary: "#6b4c9a",
@@ -24292,9 +25560,9 @@ function buildTemplateExport(params) {
24292
25560
  footerText
24293
25561
  } = params;
24294
25562
  const colors = {
24295
- ...DEFAULT_COLORS3,
25563
+ ...DEFAULT_COLORS4,
24296
25564
  ...colorsPallet,
24297
- chartColors: colorsPallet?.chartColors || DEFAULT_COLORS3.chartColors
25565
+ chartColors: colorsPallet?.chartColors || DEFAULT_COLORS4.chartColors
24298
25566
  };
24299
25567
  return {
24300
25568
  domain,
@@ -24397,7 +25665,7 @@ function myioExportData(data, config, options) {
24397
25665
  }
24398
25666
  return instance;
24399
25667
  }
24400
- var EXPORT_DEFAULT_COLORS = DEFAULT_COLORS3;
25668
+ var EXPORT_DEFAULT_COLORS = DEFAULT_COLORS4;
24401
25669
  var EXPORT_DOMAIN_ICONS = DOMAIN_ICONS;
24402
25670
  var EXPORT_DOMAIN_LABELS = DOMAIN_LABELS;
24403
25671
  var EXPORT_DOMAIN_UNITS = DOMAIN_UNITS;
@@ -24440,6 +25708,7 @@ var EXPORT_DOMAIN_UNITS = DOMAIN_UNITS;
24440
25708
  clearAllAuthCaches,
24441
25709
  connectionStatusIcons,
24442
25710
  createConsumption7DaysChart,
25711
+ createConsumptionChartWidget,
24443
25712
  createConsumptionModal,
24444
25713
  createDateRangePicker,
24445
25714
  createInputDateRangePickerInsideDIV,