myio-js-library 0.1.21 → 0.1.22

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/README.md CHANGED
@@ -945,6 +945,241 @@ The component includes premium MyIO styling with:
945
945
  - Responsive design for mobile and desktop
946
946
  - Portuguese month names and day abbreviations
947
947
 
948
+ ### Premium Date Range Input Component
949
+
950
+ #### `createInputDateRangePickerInsideDIV(params: CreateInputDateRangePickerInsideDIVParams): Promise<DateRangeInputController>`
951
+
952
+ Creates a complete, beautifully styled date range input inside a target DIV container, combining the functionality of `createDateRangePicker` with premium MyIO styling. This component automatically creates the HTML structure, injects styling, and provides a clean API for ThingsBoard widgets and other applications.
953
+
954
+ **Parameters:**
955
+ - `params: CreateInputDateRangePickerInsideDIVParams` - Configuration object:
956
+ - `containerId: string` - The DIV id where the input will be created (required)
957
+ - `inputId: string` - The id to set on the created input (required)
958
+ - `label?: string` - Optional label text (default: "Período de Datas")
959
+ - `placeholder?: string` - Input placeholder (default: "Clique para selecionar período")
960
+ - `pickerOptions?: CreateDateRangePickerOptions` - Pass-through options for createDateRangePicker
961
+ - `classNames?: object` - Custom CSS classes for wrapper, label, input, and helper
962
+ - `injectStyles?: boolean` - Inject premium MyIO styling (default: true)
963
+ - `showHelper?: boolean` - Show helper text with format info (default: true)
964
+
965
+ **Returns:** Promise resolving to `DateRangeInputController` object with:
966
+ - `input: HTMLInputElement` - The created input element
967
+ - `container: HTMLElement` - The target container element
968
+ - `wrapper: HTMLElement` - The wrapper element created by this component
969
+ - `picker: DateRangeControl` - The date range picker instance
970
+ - `getDisplayValue(): string` - Get current display value from input
971
+ - `getDates(): DateRangeResult` - Get current date range data
972
+ - `setDates(startISO: string, endISO: string): void` - Set date range programmatically
973
+ - `setHelperText(text: string, type?: 'default' | 'success' | 'error'): void` - Update helper text
974
+ - `destroy(): void` - Clean up and remove all created elements
975
+
976
+ **Key Features:**
977
+ - **Automatic HTML Creation**: Creates complete styled input structure inside target DIV
978
+ - **Premium MyIO Styling**: Beautiful styling matching demos/energy.html with purple brand colors
979
+ - **Container-Based**: Works with any DIV container, perfect for ThingsBoard widgets
980
+ - **Accessibility Built-in**: ARIA labels, keyboard navigation, screen reader support
981
+ - **Responsive Design**: Mobile-friendly with proper touch targets
982
+ - **Error Handling**: Robust validation and graceful error recovery
983
+ - **Memory Management**: Proper cleanup with destroy() method
984
+
985
+ **Usage Example:**
986
+ ```javascript
987
+ import { createInputDateRangePickerInsideDIV } from 'myio-js-library';
988
+
989
+ const controller = await createInputDateRangePickerInsideDIV({
990
+ containerId: 'date-picker-container',
991
+ inputId: 'energy-date-range',
992
+ label: 'Período de Análise',
993
+ pickerOptions: {
994
+ presetStart: '2025-09-01',
995
+ presetEnd: '2025-09-25',
996
+ onApply: (result) => {
997
+ console.log('Date range selected:', result);
998
+ // result.startISO: "2025-09-01T00:00:00-03:00"
999
+ // result.endISO: "2025-09-25T23:59:59-03:00"
1000
+ loadEnergyData(result.startISO, result.endISO);
1001
+ }
1002
+ }
1003
+ });
1004
+
1005
+ // Get current selection
1006
+ const dates = controller.getDates();
1007
+ console.log('Current range:', dates.startISO, 'to', dates.endISO);
1008
+
1009
+ // Update helper text
1010
+ controller.setHelperText('Período válido selecionado', 'success');
1011
+
1012
+ // Clean up when done
1013
+ controller.destroy();
1014
+ ```
1015
+
1016
+ **ThingsBoard Widget Integration:**
1017
+ ```html
1018
+ <script src="https://unpkg.com/myio-js-library@latest/dist/myio-js-library.umd.min.js"></script>
1019
+ <script>
1020
+ const { createInputDateRangePickerInsideDIV } = MyIOLibrary;
1021
+
1022
+ // In your widget's onInit function
1023
+ self.onInit = async function() {
1024
+ try {
1025
+ // Create date range picker in existing container
1026
+ self.dateRangePicker = await createInputDateRangePickerInsideDIV({
1027
+ containerId: 'widget-date-container',
1028
+ inputId: 'energy-widget-dates',
1029
+ label: 'Período de Datas',
1030
+ placeholder: 'Selecione o período de análise',
1031
+ pickerOptions: {
1032
+ maxRangeDays: 31,
1033
+ onApply: (result) => {
1034
+ // Update widget state and reload data
1035
+ updateWidgetData(result.startISO, result.endISO);
1036
+ }
1037
+ }
1038
+ });
1039
+
1040
+ console.log('[ENERGY] Date range picker initialized successfully');
1041
+ } catch (error) {
1042
+ console.error('[ENERGY] Failed to initialize date picker:', error);
1043
+ // Fallback to legacy implementation
1044
+ initLegacyDatePicker();
1045
+ }
1046
+ };
1047
+
1048
+ // Clean up on widget destroy
1049
+ self.onDestroy = function() {
1050
+ if (self.dateRangePicker) {
1051
+ self.dateRangePicker.destroy();
1052
+ }
1053
+ };
1054
+ </script>
1055
+ ```
1056
+
1057
+ **Premium Styling Features:**
1058
+ - **MyIO Brand Colors**: Purple theme (#4A148C) with hover effects
1059
+ - **Responsive Layout**: Adapts to mobile and desktop with proper spacing
1060
+ - **Accessibility**: High contrast mode support, reduced motion support
1061
+ - **Visual Feedback**: Hover states, focus indicators, success/error states
1062
+ - **Typography**: Roboto font family with proper line heights
1063
+ - **Shadow Effects**: Subtle shadows and smooth transitions
1064
+
1065
+ **Migration from Basic Implementation:**
1066
+ ```javascript
1067
+ // OLD: Manual HTML + basic styling
1068
+ var $inputStart = $('input[name="startDatetimes"]');
1069
+ MyIOLibrary.createDateRangePicker($inputStart[0], options);
1070
+
1071
+ // NEW: Automatic creation + premium styling
1072
+ const controller = await MyIOLibrary.createInputDateRangePickerInsideDIV({
1073
+ containerId: 'date-container',
1074
+ inputId: 'startDatetimes',
1075
+ label: 'Período de Datas',
1076
+ pickerOptions: options
1077
+ });
1078
+ ```
1079
+
1080
+ ### Premium Modal Components
1081
+
1082
+ The library includes four premium modal components for ThingsBoard dashboards that provide comprehensive device analytics and reporting capabilities.
1083
+
1084
+ #### `openDashboardPopupReport(params: OpenDeviceReportParams): ModalHandle`
1085
+
1086
+ Opens a device-specific daily consumption report modal with built-in date range picker, sortable table, and CSV export functionality.
1087
+
1088
+ **Parameters:**
1089
+ - `ingestionId: string` - Data ingestion identifier (required)
1090
+ - `deviceId?: string` - Optional device ID for additional metadata
1091
+ - `identifier?: string` - Device identifier/code (e.g., "ENTRADA-001", "CHILLER-A")
1092
+ - `label?: string` - Human-readable label/name (e.g., "Outback", "Shopping Center Norte")
1093
+ - `ui?: object` - UI configuration (theme, width)
1094
+ - `api: object` - API configuration:
1095
+ - `clientId?: string` - Client ID for data API
1096
+ - `clientSecret?: string` - Client secret for data API
1097
+ - `dataApiBaseUrl?: string` - Data API base URL
1098
+ - `ingestionToken?: string` - Token for data ingestion access
1099
+
1100
+ **Returns:** `ModalHandle` object with:
1101
+ - `close(): void` - Close the modal
1102
+ - `on(event: 'close'|'loaded'|'error', handler: Function): void` - Event listeners
1103
+
1104
+ **Key Features:**
1105
+ - **Built-in Date Range Picker**: No need to specify dates in parameters
1106
+ - **Automatic Data Loading**: Fetches daily consumption data for selected period
1107
+ - **Sortable Table**: Click column headers to sort by date or consumption
1108
+ - **CSV Export**: Download report data with proper Brazilian formatting
1109
+ - **Responsive Design**: Works on desktop and mobile devices
1110
+ - **Error Handling**: Graceful error display and recovery
1111
+
1112
+ **Usage Example:**
1113
+ ```javascript
1114
+ import { openDashboardPopupReport } from 'myio-js-library';
1115
+
1116
+ const modal = openDashboardPopupReport({
1117
+ ingestionId: 'abc123-ingestion-id',
1118
+ deviceId: 'device-uuid',
1119
+ identifier: 'ENTRADA-001',
1120
+ label: 'Outback Shopping',
1121
+ api: {
1122
+ clientId: 'your-client-id',
1123
+ clientSecret: 'your-client-secret',
1124
+ dataApiBaseUrl: 'https://api.data.apps.myio-bas.com',
1125
+ ingestionToken: 'your-ingestion-token'
1126
+ }
1127
+ });
1128
+
1129
+ modal.on('loaded', (data) => {
1130
+ console.log('Report loaded:', data.count, 'days');
1131
+ });
1132
+
1133
+ modal.on('close', () => {
1134
+ console.log('Modal closed');
1135
+ });
1136
+ ```
1137
+
1138
+ **UMD Usage (ThingsBoard widgets):**
1139
+ ```html
1140
+ <script src="https://unpkg.com/myio-js-library@latest/dist/myio-js-library.umd.min.js"></script>
1141
+ <script>
1142
+ const { openDashboardPopupReport } = MyIOLibrary;
1143
+
1144
+ const modal = openDashboardPopupReport({
1145
+ ingestionId: 'demo-ingestion-123',
1146
+ deviceId: 'demo-device-123',
1147
+ identifier: 'ENTRADA-001',
1148
+ label: 'Outback',
1149
+ api: {
1150
+ clientId: 'demo-client',
1151
+ clientSecret: 'demo-secret',
1152
+ dataApiBaseUrl: 'https://api.data.apps.myio-bas.com',
1153
+ ingestionToken: 'demo-ingestion-token'
1154
+ }
1155
+ });
1156
+
1157
+ modal.on('loaded', (data) => {
1158
+ console.log('Device report loaded with', data.count, 'days of data');
1159
+ });
1160
+ </script>
1161
+ ```
1162
+
1163
+ **Migration from Legacy API:**
1164
+ ```javascript
1165
+ // OLD API (deprecated)
1166
+ MyIOLibrary.openDashboardPopupReport({
1167
+ ingestionId: 'demo-ingestion-123',
1168
+ deviceLabel: 'Entrada Subestação', // ❌ Deprecated
1169
+ storeLabel: 'Outback', // ❌ Deprecated
1170
+ date: { start: '2025-09-01', end: '2025-09-25' }, // ❌ Deprecated
1171
+ api: { tbJwtToken: 'jwt-token' } // ❌ Deprecated
1172
+ });
1173
+
1174
+ // NEW API (recommended)
1175
+ MyIOLibrary.openDashboardPopupReport({
1176
+ ingestionId: 'demo-ingestion-123',
1177
+ identifier: 'ENTRADA-001', // ✅ Clear device identifier
1178
+ label: 'Outback', // ✅ Clear human-readable name
1179
+ api: { ingestionToken: 'ingestion-token' } // ✅ Clear token purpose
1180
+ });
1181
+ ```
1182
+
948
1183
  ### MYIO Components - Drag-to-Footer Dock Implementation
949
1184
 
950
1185
  The library includes three main interactive components for building comparative selection interfaces:
package/dist/index.cjs CHANGED
@@ -582,6 +582,7 @@ __export(index_exports, {
582
582
  classifyWaterLabel: () => classifyWaterLabel,
583
583
  classifyWaterLabels: () => classifyWaterLabels,
584
584
  createDateRangePicker: () => createDateRangePicker2,
585
+ createInputDateRangePickerInsideDIV: () => createInputDateRangePickerInsideDIV,
585
586
  decodePayload: () => decodePayload,
586
587
  decodePayloadBase64Xor: () => decodePayloadBase64Xor,
587
588
  detectDeviceType: () => detectDeviceType,
@@ -5414,7 +5415,6 @@ function createDateRangePicker($2, input, opts) {
5414
5415
  helpText.className = "myio-text-muted";
5415
5416
  helpText.style.fontSize = "12px";
5416
5417
  helpText.style.marginTop = "4px";
5417
- helpText.textContent = "Formato: DD/MM/YY HH:mm at\xE9 DD/MM/YY HH:mm";
5418
5418
  input.parentNode?.appendChild(helpText);
5419
5419
  const moment = window.moment;
5420
5420
  const startDate = opts.presetStart ? moment(opts.presetStart).startOf("day") : moment().startOf("month");
@@ -5493,6 +5493,25 @@ var DateRangePickerJQ = {
5493
5493
  };
5494
5494
 
5495
5495
  // src/components/premium-modals/report-device/DeviceReportModal.ts
5496
+ var createDefaultEnergyFetcher = (params) => {
5497
+ return async ({ baseUrl, ingestionId, startISO, endISO }) => {
5498
+ const url = `${baseUrl}/api/v1/telemetry/devices/${ingestionId}/energy?startTime=${encodeURIComponent(startISO)}&endTime=${encodeURIComponent(endISO)}&granularity=1d&page=1&pageSize=1000&deep=0`;
5499
+ const token = params.api.ingestionToken;
5500
+ if (!token) {
5501
+ throw new Error("ingestionToken is required for Data/Ingestion API calls");
5502
+ }
5503
+ const response = await fetch(url, {
5504
+ headers: {
5505
+ "Authorization": `Bearer ${token}`,
5506
+ "Content-Type": "application/json"
5507
+ }
5508
+ });
5509
+ if (!response.ok) {
5510
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
5511
+ }
5512
+ return response.json();
5513
+ };
5514
+ };
5496
5515
  var DeviceReportModal = class {
5497
5516
  constructor(params) {
5498
5517
  this.params = params;
@@ -5501,16 +5520,18 @@ var DeviceReportModal = class {
5501
5520
  clientSecret: params.api.clientSecret,
5502
5521
  base: params.api.dataApiBaseUrl
5503
5522
  });
5523
+ this.energyFetcher = params.fetcher || createDefaultEnergyFetcher(params);
5504
5524
  }
5505
5525
  modal;
5506
5526
  authClient;
5527
+ energyFetcher;
5507
5528
  data = [];
5508
5529
  isLoading = false;
5509
5530
  eventHandlers = {};
5510
5531
  dateRangePicker = null;
5511
5532
  show() {
5512
5533
  this.modal = createModal({
5513
- title: `Relat\xF3rio - ${this.params.deviceLabel || "Dispositivo"}`,
5534
+ title: `Relat\xF3rio - ${this.params.identifier || "SEM IDENTIFICADOR"} - ${this.params.label || "SEM ETIQUETA"}`,
5514
5535
  width: "80vw",
5515
5536
  height: "90vh",
5516
5537
  theme: this.params.ui?.theme || "light"
@@ -5570,8 +5591,8 @@ var DeviceReportModal = class {
5570
5591
  exportBtn?.addEventListener("click", () => this.exportCSV());
5571
5592
  try {
5572
5593
  this.dateRangePicker = await attach(dateRangeInput, {
5573
- presetStart: this.params.date?.start || this.getDefaultStartDate(),
5574
- presetEnd: this.params.date?.end || this.getDefaultEndDate(),
5594
+ presetStart: this.getDefaultStartDate(),
5595
+ presetEnd: this.getDefaultEndDate(),
5575
5596
  maxRangeDays: 31,
5576
5597
  parentEl: this.modal.element,
5577
5598
  onApply: ({ startISO, endISO }) => {
@@ -5605,8 +5626,13 @@ var DeviceReportModal = class {
5605
5626
  const startDate = startISO.split("T")[0];
5606
5627
  const endDate = endISO.split("T")[0];
5607
5628
  const dateRange = rangeDaysInclusive(startDate, endDate);
5608
- const mockData = this.generateMockData(dateRange);
5609
- this.data = mockData;
5629
+ const apiResponse = await this.energyFetcher({
5630
+ baseUrl: this.params.api.dataApiBaseUrl || "https://api.data.apps.myio-bas.com",
5631
+ ingestionId: this.params.ingestionId,
5632
+ startISO,
5633
+ endISO
5634
+ });
5635
+ this.data = this.processApiResponse(apiResponse, dateRange);
5610
5636
  this.renderTable();
5611
5637
  exportBtn.disabled = false;
5612
5638
  this.emit("loaded", {
@@ -5624,6 +5650,28 @@ var DeviceReportModal = class {
5624
5650
  spinner.style.display = "none";
5625
5651
  }
5626
5652
  }
5653
+ processApiResponse(apiResponse, dateRange) {
5654
+ const dataArray = Array.isArray(apiResponse) ? apiResponse : apiResponse.data || [];
5655
+ if (!Array.isArray(dataArray) || dataArray.length === 0) {
5656
+ console.warn("[DeviceReportModal] API returned empty or invalid response, zero-filling date range");
5657
+ return dateRange.map((date) => ({ date, consumption: 0 }));
5658
+ }
5659
+ const deviceData = dataArray[0];
5660
+ const consumption = deviceData.consumption || [];
5661
+ const dailyMap = {};
5662
+ consumption.forEach((item) => {
5663
+ if (item.timestamp && item.value != null) {
5664
+ const date = item.timestamp.slice(0, 10);
5665
+ const value = Number(item.value);
5666
+ if (!dailyMap[date]) dailyMap[date] = 0;
5667
+ dailyMap[date] += value;
5668
+ }
5669
+ });
5670
+ return dateRange.map((date) => ({
5671
+ date,
5672
+ consumption: dailyMap[date] || 0
5673
+ }));
5674
+ }
5627
5675
  generateMockData(dateRange) {
5628
5676
  return dateRange.map((date) => ({
5629
5677
  date,
@@ -5698,14 +5746,14 @@ var DeviceReportModal = class {
5698
5746
  const now = /* @__PURE__ */ new Date();
5699
5747
  const timestamp = now.toLocaleDateString("pt-BR") + " - " + now.toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" });
5700
5748
  const csvData = [
5701
- ["Dispositivo/Loja", this.params.deviceLabel || "N/A", this.params.storeLabel || ""],
5749
+ ["Dispositivo/Loja", this.params.identifier || "N/A", this.params.label || ""],
5702
5750
  ["DATA EMISS\xC3O", timestamp, ""],
5703
5751
  ["Total", fmtPt(total), ""],
5704
5752
  ["Data", "Consumo", ""],
5705
5753
  ...this.data.map((row) => [this.formatDate(row.date), fmtPt(row.consumption)])
5706
5754
  ];
5707
5755
  const csvContent = toCsv(csvData);
5708
- this.downloadCSV(csvContent, `relatorio-${this.params.deviceLabel || "dispositivo"}-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`);
5756
+ this.downloadCSV(csvContent, `relatorio-${this.params.identifier || "dispositivo"}-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.csv`);
5709
5757
  }
5710
5758
  downloadCSV(content, filename) {
5711
5759
  const blob = new Blob([content], { type: "text/csv;charset=utf-8;" });
@@ -6667,8 +6715,8 @@ var AllReportModal = class {
6667
6715
  });
6668
6716
  try {
6669
6717
  this.dateRangePicker = await attach(dateRangeInput, {
6670
- presetStart: this.params.date?.start || this.getDefaultStartDate(),
6671
- presetEnd: this.params.date?.end || this.getDefaultEndDate(),
6718
+ presetStart: this.getDefaultStartDate(),
6719
+ presetEnd: this.getDefaultEndDate(),
6672
6720
  maxRangeDays: 31,
6673
6721
  parentEl: this.modal.element,
6674
6722
  onApply: ({ startISO, endISO }) => {
@@ -7123,6 +7171,268 @@ async function createDateRangePicker2(input, options = {}) {
7123
7171
  };
7124
7172
  return await DateRangePickerJQ.attach(input, defaultOptions);
7125
7173
  }
7174
+
7175
+ // src/components/createInputDateRangePickerInsideDIV.ts
7176
+ var PREMIUM_STYLES = `
7177
+ .myio-daterange-wrapper {
7178
+ font-family: 'Roboto', Arial, sans-serif;
7179
+ background: #f9f9f9;
7180
+ padding: 20px;
7181
+ border-radius: 8px;
7182
+ margin-bottom: 20px;
7183
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
7184
+ transition: all 0.2s ease;
7185
+ }
7186
+
7187
+ .myio-daterange-wrapper:hover {
7188
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
7189
+ }
7190
+
7191
+ .myio-daterange-label {
7192
+ display: block;
7193
+ margin-bottom: 8px;
7194
+ font-weight: 500;
7195
+ color: #333;
7196
+ font-size: 14px;
7197
+ line-height: 1.4;
7198
+ }
7199
+
7200
+ .myio-daterange-input {
7201
+ width: 100%;
7202
+ max-width: 300px;
7203
+ padding: 8px 12px;
7204
+ border: 1px solid #ddd;
7205
+ border-radius: 4px;
7206
+ background: white;
7207
+ font-size: 14px;
7208
+ color: #333;
7209
+ cursor: pointer;
7210
+ transition: all 0.2s ease;
7211
+ font-family: inherit;
7212
+ line-height: 1.4;
7213
+ }
7214
+
7215
+ .myio-daterange-input:hover {
7216
+ border-color: #4A148C;
7217
+ box-shadow: 0 0 0 2px rgba(74, 20, 140, 0.1);
7218
+ }
7219
+
7220
+ .myio-daterange-input:focus {
7221
+ outline: none;
7222
+ border-color: #4A148C;
7223
+ box-shadow: 0 0 0 3px rgba(74, 20, 140, 0.2);
7224
+ }
7225
+
7226
+ .myio-daterange-input::placeholder {
7227
+ color: #999;
7228
+ opacity: 1;
7229
+ }
7230
+
7231
+ .myio-daterange-helper {
7232
+ font-size: 12px;
7233
+ color: #666;
7234
+ margin-top: 4px;
7235
+ line-height: 1.3;
7236
+ transition: color 0.2s ease;
7237
+ }
7238
+
7239
+ .myio-daterange-helper.success {
7240
+ color: #28a745;
7241
+ font-weight: 500;
7242
+ }
7243
+
7244
+ .myio-daterange-helper.error {
7245
+ color: #dc3545;
7246
+ font-weight: 500;
7247
+ }
7248
+
7249
+ /* Responsive design */
7250
+ @media (max-width: 768px) {
7251
+ .myio-daterange-wrapper {
7252
+ padding: 16px;
7253
+ margin-bottom: 16px;
7254
+ }
7255
+
7256
+ .myio-daterange-input {
7257
+ max-width: 100%;
7258
+ font-size: 16px; /* Prevents zoom on iOS */
7259
+ }
7260
+ }
7261
+
7262
+ /* High contrast mode support */
7263
+ @media (prefers-contrast: high) {
7264
+ .myio-daterange-wrapper {
7265
+ border: 2px solid #000;
7266
+ }
7267
+
7268
+ .myio-daterange-input {
7269
+ border: 2px solid #000;
7270
+ }
7271
+ }
7272
+
7273
+ /* Reduced motion support */
7274
+ @media (prefers-reduced-motion: reduce) {
7275
+ .myio-daterange-wrapper,
7276
+ .myio-daterange-input,
7277
+ .myio-daterange-helper {
7278
+ transition: none;
7279
+ }
7280
+ }
7281
+ `;
7282
+ function injectPremiumStyles() {
7283
+ const styleId = "myio-daterange-premium-styles";
7284
+ if (document.getElementById(styleId)) {
7285
+ return;
7286
+ }
7287
+ const styleEl = document.createElement("style");
7288
+ styleEl.id = styleId;
7289
+ styleEl.textContent = PREMIUM_STYLES;
7290
+ document.head.appendChild(styleEl);
7291
+ console.log("[MyIO] Premium date range styles injected");
7292
+ }
7293
+ function validateId(id, context) {
7294
+ if (!id || typeof id !== "string") {
7295
+ throw new Error(`[createInputDateRangePickerInsideDIV] ${context} must be a non-empty string`);
7296
+ }
7297
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(id)) {
7298
+ throw new Error(`[createInputDateRangePickerInsideDIV] ${context} '${id}' is not a valid HTML ID`);
7299
+ }
7300
+ }
7301
+ async function createInputDateRangePickerInsideDIV(params) {
7302
+ const {
7303
+ containerId,
7304
+ inputId,
7305
+ label = "Per\xEDodo de Datas",
7306
+ placeholder = "Clique para selecionar per\xEDodo",
7307
+ pickerOptions = {},
7308
+ classNames = {},
7309
+ injectStyles = true,
7310
+ showHelper = true
7311
+ } = params;
7312
+ validateId(containerId, "containerId");
7313
+ validateId(inputId, "inputId");
7314
+ const container = document.getElementById(containerId);
7315
+ if (!container) {
7316
+ throw new Error(`[createInputDateRangePickerInsideDIV] Container '#${containerId}' not found`);
7317
+ }
7318
+ if (injectStyles) {
7319
+ injectPremiumStyles();
7320
+ }
7321
+ let inputEl = document.getElementById(inputId);
7322
+ if (inputEl && inputEl.tagName.toLowerCase() !== "input") {
7323
+ throw new Error(`[createInputDateRangePickerInsideDIV] Element '#${inputId}' exists but is not an input element`);
7324
+ }
7325
+ const wrapper = document.createElement("div");
7326
+ wrapper.className = classNames.wrapper || "myio-daterange-wrapper";
7327
+ wrapper.setAttribute("data-myio-component", "daterange-input");
7328
+ wrapper.setAttribute("data-version", "1.0.0");
7329
+ let labelEl = null;
7330
+ if (label) {
7331
+ labelEl = document.createElement("label");
7332
+ labelEl.className = classNames.label || "myio-daterange-label";
7333
+ labelEl.textContent = label;
7334
+ labelEl.setAttribute("for", inputId);
7335
+ wrapper.appendChild(labelEl);
7336
+ }
7337
+ if (!inputEl) {
7338
+ inputEl = document.createElement("input");
7339
+ inputEl.type = "text";
7340
+ inputEl.id = inputId;
7341
+ inputEl.name = inputId;
7342
+ }
7343
+ inputEl.className = classNames.input || "myio-daterange-input";
7344
+ inputEl.readOnly = true;
7345
+ inputEl.placeholder = placeholder;
7346
+ inputEl.autocomplete = "off";
7347
+ inputEl.setAttribute("aria-label", label || "Date range selector");
7348
+ if (showHelper) {
7349
+ inputEl.setAttribute("aria-describedby", `${inputId}-helper`);
7350
+ }
7351
+ let helperEl = null;
7352
+ if (showHelper) {
7353
+ helperEl = document.createElement("div");
7354
+ helperEl.id = `${inputId}-helper`;
7355
+ helperEl.className = classNames.helper || "myio-daterange-helper";
7356
+ helperEl.setAttribute("aria-live", "polite");
7357
+ }
7358
+ wrapper.appendChild(inputEl);
7359
+ if (helperEl) {
7360
+ wrapper.appendChild(helperEl);
7361
+ }
7362
+ const existingWrapper = container.querySelector('[data-myio-component="daterange-input"]');
7363
+ if (existingWrapper) {
7364
+ console.warn(`[createInputDateRangePickerInsideDIV] Replacing existing daterange input in container '#${containerId}'`);
7365
+ existingWrapper.remove();
7366
+ }
7367
+ container.appendChild(wrapper);
7368
+ const enhancedOptions = {
7369
+ maxRangeDays: 31,
7370
+ onApply: (result) => {
7371
+ if (helperEl) {
7372
+ const startDate = new Date(result.startISO);
7373
+ const endDate = new Date(result.endISO);
7374
+ const days = Math.ceil((endDate.getTime() - startDate.getTime()) / (1e3 * 60 * 60 * 24)) + 1;
7375
+ helperEl.textContent = `Per\xEDodo selecionado: ${days} dia${days !== 1 ? "s" : ""}`;
7376
+ helperEl.className = (classNames.helper || "myio-daterange-helper") + " success";
7377
+ setTimeout(() => {
7378
+ if (helperEl) {
7379
+ helperEl.className = classNames.helper || "myio-daterange-helper";
7380
+ }
7381
+ }, 3e3);
7382
+ }
7383
+ if (pickerOptions.onApply) {
7384
+ pickerOptions.onApply(result);
7385
+ }
7386
+ },
7387
+ ...pickerOptions
7388
+ };
7389
+ let picker;
7390
+ try {
7391
+ picker = await createDateRangePicker2(inputEl, enhancedOptions);
7392
+ console.log(`[createInputDateRangePickerInsideDIV] Successfully initialized for input '#${inputId}'`);
7393
+ } catch (error) {
7394
+ wrapper.remove();
7395
+ throw new Error(`[createInputDateRangePickerInsideDIV] Failed to initialize date picker: ${error.message}`);
7396
+ }
7397
+ const controller = {
7398
+ input: inputEl,
7399
+ container,
7400
+ wrapper,
7401
+ picker,
7402
+ getDisplayValue: () => inputEl.value,
7403
+ getDates: () => picker.getDates(),
7404
+ setDates: (startISO, endISO) => {
7405
+ try {
7406
+ picker.setDates(startISO, endISO);
7407
+ } catch (error) {
7408
+ console.error(`[createInputDateRangePickerInsideDIV] Error setting dates:`, error);
7409
+ throw error;
7410
+ }
7411
+ },
7412
+ setHelperText: (text, type = "default") => {
7413
+ if (helperEl) {
7414
+ helperEl.textContent = text;
7415
+ const baseClass = classNames.helper || "myio-daterange-helper";
7416
+ helperEl.className = type === "default" ? baseClass : `${baseClass} ${type}`;
7417
+ }
7418
+ },
7419
+ destroy: () => {
7420
+ try {
7421
+ picker.destroy();
7422
+ console.log(`[createInputDateRangePickerInsideDIV] Date picker destroyed for input '#${inputId}'`);
7423
+ } catch (error) {
7424
+ console.warn(`[createInputDateRangePickerInsideDIV] Error destroying picker:`, error);
7425
+ }
7426
+ try {
7427
+ wrapper.remove();
7428
+ console.log(`[createInputDateRangePickerInsideDIV] Wrapper removed for input '#${inputId}'`);
7429
+ } catch (error) {
7430
+ console.warn(`[createInputDateRangePickerInsideDIV] Error removing wrapper:`, error);
7431
+ }
7432
+ }
7433
+ };
7434
+ return controller;
7435
+ }
7126
7436
  // Annotate the CommonJS export names for ESM import in node:
7127
7437
  0 && (module.exports = {
7128
7438
  MyIOChartModal,
@@ -7139,6 +7449,7 @@ async function createDateRangePicker2(input, options = {}) {
7139
7449
  classifyWaterLabel,
7140
7450
  classifyWaterLabels,
7141
7451
  createDateRangePicker,
7452
+ createInputDateRangePickerInsideDIV,
7142
7453
  decodePayload,
7143
7454
  decodePayloadBase64Xor,
7144
7455
  detectDeviceType,