@switchbot/homebridge-switchbot 5.0.0-beta.109 → 5.0.0-beta.110

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.
Files changed (78) hide show
  1. package/config.schema.json +4 -0
  2. package/dist/device-types.d.ts +18 -2
  3. package/dist/device-types.d.ts.map +1 -1
  4. package/dist/device-types.js +71 -0
  5. package/dist/device-types.js.map +1 -1
  6. package/dist/deviceFactory.d.ts.map +1 -1
  7. package/dist/deviceFactory.js +1 -0
  8. package/dist/deviceFactory.js.map +1 -1
  9. package/dist/homebridge-ui/endpoints/config.d.ts +0 -3
  10. package/dist/homebridge-ui/endpoints/config.d.ts.map +1 -1
  11. package/dist/homebridge-ui/endpoints/config.js +40 -9
  12. package/dist/homebridge-ui/endpoints/config.js.map +1 -1
  13. package/dist/homebridge-ui/endpoints/devices.d.ts.map +1 -1
  14. package/dist/homebridge-ui/endpoints/devices.js +59 -2
  15. package/dist/homebridge-ui/endpoints/devices.js.map +1 -1
  16. package/dist/homebridge-ui/public/css/styles.css +254 -0
  17. package/dist/homebridge-ui/public/index.html +23 -168
  18. package/dist/homebridge-ui/public/js/api.d.ts +4 -0
  19. package/dist/homebridge-ui/public/js/api.d.ts.map +1 -1
  20. package/dist/homebridge-ui/public/js/api.js +14 -0
  21. package/dist/homebridge-ui/public/js/api.js.map +1 -1
  22. package/dist/homebridge-ui/public/js/api.ts +17 -1
  23. package/dist/homebridge-ui/public/js/app.js +556 -44
  24. package/dist/homebridge-ui/public/js/app.js.map +3 -3
  25. package/dist/homebridge-ui/public/js/app.ts +2 -1
  26. package/dist/homebridge-ui/public/js/devices-delete.d.ts +1 -0
  27. package/dist/homebridge-ui/public/js/devices-delete.d.ts.map +1 -1
  28. package/dist/homebridge-ui/public/js/devices-delete.js +108 -1
  29. package/dist/homebridge-ui/public/js/devices-delete.js.map +1 -1
  30. package/dist/homebridge-ui/public/js/devices-delete.ts +124 -1
  31. package/dist/homebridge-ui/public/js/devices.d.ts +1 -0
  32. package/dist/homebridge-ui/public/js/devices.d.ts.map +1 -1
  33. package/dist/homebridge-ui/public/js/devices.js +10 -0
  34. package/dist/homebridge-ui/public/js/devices.js.map +1 -1
  35. package/dist/homebridge-ui/public/js/devices.ts +10 -0
  36. package/dist/homebridge-ui/public/js/discovery.d.ts.map +1 -1
  37. package/dist/homebridge-ui/public/js/discovery.js +130 -4
  38. package/dist/homebridge-ui/public/js/discovery.js.map +1 -1
  39. package/dist/homebridge-ui/public/js/discovery.ts +158 -4
  40. package/dist/homebridge-ui/public/js/modals.d.ts.map +1 -1
  41. package/dist/homebridge-ui/public/js/modals.js +71 -26
  42. package/dist/homebridge-ui/public/js/modals.js.map +1 -1
  43. package/dist/homebridge-ui/public/js/modals.ts +74 -27
  44. package/dist/homebridge-ui/public/js/render.d.ts +57 -0
  45. package/dist/homebridge-ui/public/js/render.d.ts.map +1 -1
  46. package/dist/homebridge-ui/public/js/render.js +286 -13
  47. package/dist/homebridge-ui/public/js/render.js.map +1 -1
  48. package/dist/homebridge-ui/public/js/render.ts +331 -11
  49. package/dist/homebridge-ui/utils/device-migration.d.ts +35 -0
  50. package/dist/homebridge-ui/utils/device-migration.d.ts.map +1 -0
  51. package/dist/homebridge-ui/utils/device-migration.js +111 -0
  52. package/dist/homebridge-ui/utils/device-migration.js.map +1 -0
  53. package/dist/platform.js +2 -2
  54. package/dist/platform.js.map +1 -1
  55. package/docs/variables/default.html +1 -1
  56. package/package.json +1 -1
  57. package/src/device-types.ts +85 -0
  58. package/src/deviceFactory.ts +1 -0
  59. package/src/homebridge-ui/endpoints/config.ts +54 -10
  60. package/src/homebridge-ui/endpoints/devices.ts +62 -3
  61. package/src/homebridge-ui/public/css/styles.css +254 -0
  62. package/src/homebridge-ui/public/index.html +23 -168
  63. package/src/homebridge-ui/public/js/api.ts +17 -1
  64. package/src/homebridge-ui/public/js/app.ts +2 -1
  65. package/src/homebridge-ui/public/js/devices-delete.ts +124 -1
  66. package/src/homebridge-ui/public/js/devices.ts +10 -0
  67. package/src/homebridge-ui/public/js/discovery.ts +158 -4
  68. package/src/homebridge-ui/public/js/modals.ts +74 -27
  69. package/src/homebridge-ui/public/js/render.ts +331 -11
  70. package/src/homebridge-ui/utils/device-migration.ts +144 -0
  71. package/src/platform.ts +2 -2
  72. package/todo/COMPLETED.md +189 -0
  73. package/todo/README.md +59 -0
  74. package/todo/TODO.md +205 -0
  75. package/todo/mockups/filtering-sorting.svg +112 -0
  76. package/todo/mockups/modal-switchbot-theme.svg +66 -0
  77. package/todo/mockups/signal-strength-visualization.svg +94 -0
  78. package/TODO.md +0 -564
@@ -16,51 +16,82 @@ export async function editDevice(device) {
16
16
  const modal = document.createElement('div');
17
17
  modal.style.background = getComputedStyle(document.body).backgroundColor;
18
18
  modal.style.color = getComputedStyle(document.body).color;
19
- modal.style.padding = '24px';
20
- modal.style.borderRadius = '8px';
21
- modal.style.minWidth = '400px';
22
- modal.style.boxShadow = '0 10px 40px rgba(0,0,0,0.3)';
19
+ modal.style.padding = '0';
20
+ modal.style.borderRadius = '10px';
21
+ modal.style.minWidth = '440px';
22
+ modal.style.maxWidth = '90vw';
23
+ modal.style.boxShadow = '0 8px 32px rgba(0,0,0,0.35)';
24
+ modal.style.overflow = 'hidden';
25
+ modal.style.borderTop = '3px solid var(--switchbot-red, #ef4444)';
23
26
  const title = document.createElement('h3');
24
27
  title.textContent = 'Edit Device';
25
28
  title.style.marginTop = '0';
29
+ title.style.marginBottom = '16px';
30
+ title.style.padding = '20px 20px 0';
31
+ title.style.fontSize = '18px';
32
+ title.style.fontWeight = '600';
33
+ title.style.color = 'var(--switchbot-red, #ef4444)';
34
+ title.style.letterSpacing = '-0.02em';
35
+ const contentDiv = document.createElement('div');
36
+ contentDiv.style.padding = '0 20px 20px';
26
37
  const nameLabel = document.createElement('label');
27
38
  nameLabel.textContent = 'Device Name';
28
39
  nameLabel.style.display = 'block';
29
- nameLabel.style.marginBottom = '8px';
40
+ nameLabel.style.marginBottom = '6px';
30
41
  nameLabel.style.fontWeight = '500';
42
+ nameLabel.style.fontSize = '12px';
43
+ nameLabel.style.color = '#6b7280';
31
44
  const nameInput = document.createElement('input');
32
45
  nameInput.type = 'text';
33
46
  nameInput.value = device.name || device.id;
34
47
  nameInput.style.width = '100%';
35
- nameInput.style.marginBottom = '16px';
48
+ nameInput.style.marginBottom = '12px';
49
+ nameInput.style.padding = '8px 10px';
50
+ nameInput.style.borderRadius = '6px';
51
+ nameInput.style.fontSize = '14px';
52
+ nameInput.style.boxSizing = 'border-box';
53
+ nameInput.style.transition = 'border-color 0.2s ease';
36
54
  // Read-only API device type field
37
55
  const apiTypeLabel = document.createElement('label');
38
56
  apiTypeLabel.textContent = 'Device Type (API - Read Only)';
39
57
  apiTypeLabel.style.display = 'block';
40
- apiTypeLabel.style.marginBottom = '8px';
58
+ apiTypeLabel.style.marginBottom = '6px';
41
59
  apiTypeLabel.style.fontWeight = '500';
60
+ apiTypeLabel.style.fontSize = '12px';
61
+ apiTypeLabel.style.color = '#6b7280';
42
62
  const apiTypeInput = document.createElement('input');
43
63
  apiTypeInput.type = 'text';
44
64
  apiTypeInput.value = device.deviceType || device.type || 'Unknown';
45
65
  apiTypeInput.readOnly = true;
46
66
  apiTypeInput.style.width = '100%';
47
- apiTypeInput.style.marginBottom = '16px';
67
+ apiTypeInput.style.marginBottom = '12px';
68
+ apiTypeInput.style.padding = '8px 10px';
69
+ apiTypeInput.style.borderRadius = '6px';
70
+ apiTypeInput.style.fontSize = '13px';
48
71
  apiTypeInput.style.opacity = '0.6';
49
72
  apiTypeInput.style.cursor = 'not-allowed';
73
+ apiTypeInput.style.boxSizing = 'border-box';
74
+ apiTypeInput.style.backgroundColor = '#f9fafb';
50
75
  // Editable config device type dropdown
51
76
  const typeLabel = document.createElement('label');
52
77
  typeLabel.textContent = 'Config Device Type (Override)';
53
78
  typeLabel.style.display = 'block';
54
- typeLabel.style.marginBottom = '8px';
79
+ typeLabel.style.marginBottom = '6px';
55
80
  typeLabel.style.fontWeight = '500';
81
+ typeLabel.style.fontSize = '12px';
82
+ typeLabel.style.color = '#6b7280';
56
83
  const typeSelect = document.createElement('select');
57
84
  typeSelect.style.width = '100%';
58
- typeSelect.style.padding = '8px';
59
- typeSelect.style.marginBottom = '16px';
60
- typeSelect.style.borderRadius = '4px';
85
+ typeSelect.style.padding = '8px 10px';
86
+ typeSelect.style.marginBottom = '12px';
87
+ typeSelect.style.borderRadius = '6px';
88
+ typeSelect.style.fontSize = '14px';
61
89
  typeSelect.style.background = getComputedStyle(nameInput).background;
62
90
  typeSelect.style.color = getComputedStyle(nameInput).color;
63
91
  typeSelect.style.border = getComputedStyle(nameInput).border;
92
+ typeSelect.style.boxSizing = 'border-box';
93
+ typeSelect.style.cursor = 'pointer';
94
+ typeSelect.style.transition = 'border-color 0.2s ease';
64
95
  // Add option groups with all API device types
65
96
  Object.keys(DEVICE_TYPES).forEach((categoryName) => {
66
97
  const optgroup = document.createElement('optgroup');
@@ -76,21 +107,34 @@ export async function editDevice(device) {
76
107
  });
77
108
  typeSelect.appendChild(optgroup);
78
109
  });
79
- const buttons = document.createElement('div');
80
- buttons.style.display = 'flex';
81
- buttons.style.gap = '8px';
82
- buttons.style.justifyContent = 'flex-end';
83
110
  const errorMessage = document.createElement('div');
84
- errorMessage.style.color = '#ef4444';
111
+ errorMessage.style.color = 'var(--switchbot-red, #ef4444)';
85
112
  errorMessage.style.marginBottom = '12px';
86
113
  errorMessage.style.fontSize = '12px';
87
114
  errorMessage.style.display = 'none';
115
+ errorMessage.style.padding = '8px 10px';
116
+ errorMessage.style.background = 'var(--switchbot-red-light, #fee2e2)';
117
+ errorMessage.style.borderRadius = '6px';
118
+ errorMessage.style.fontWeight = '500';
119
+ const buttons = document.createElement('div');
120
+ buttons.style.display = 'flex';
121
+ buttons.style.gap = '10px';
122
+ buttons.style.justifyContent = 'flex-end';
123
+ buttons.style.marginTop = '18px';
124
+ buttons.style.paddingTop = '18px';
125
+ buttons.style.borderTop = '1px solid rgba(0, 0, 0, 0.08)';
88
126
  const cancelBtn = document.createElement('button');
89
127
  cancelBtn.textContent = 'Cancel';
90
- cancelBtn.style.background = '#666';
128
+ cancelBtn.className = 'secondary';
129
+ cancelBtn.style.background = '#6b7280';
130
+ cancelBtn.style.padding = '8px 16px';
131
+ cancelBtn.style.fontSize = '13px';
91
132
  cancelBtn.onclick = () => div.remove();
92
133
  const saveBtn = document.createElement('button');
93
134
  saveBtn.textContent = 'Save';
135
+ saveBtn.style.background = 'var(--switchbot-red, #ef4444)';
136
+ saveBtn.style.padding = '8px 20px';
137
+ saveBtn.style.fontSize = '13px';
94
138
  saveBtn.onclick = async () => {
95
139
  try {
96
140
  const { updateDevice, syncParentPluginConfigFromDisk, fetchDevices } = await import('./api.js');
@@ -116,15 +160,16 @@ export async function editDevice(device) {
116
160
  };
117
161
  buttons.appendChild(cancelBtn);
118
162
  buttons.appendChild(saveBtn);
163
+ contentDiv.appendChild(nameLabel);
164
+ contentDiv.appendChild(nameInput);
165
+ contentDiv.appendChild(apiTypeLabel);
166
+ contentDiv.appendChild(apiTypeInput);
167
+ contentDiv.appendChild(typeLabel);
168
+ contentDiv.appendChild(typeSelect);
169
+ contentDiv.appendChild(errorMessage);
170
+ contentDiv.appendChild(buttons);
119
171
  modal.appendChild(title);
120
- modal.appendChild(nameLabel);
121
- modal.appendChild(nameInput);
122
- modal.appendChild(apiTypeLabel);
123
- modal.appendChild(apiTypeInput);
124
- modal.appendChild(typeLabel);
125
- modal.appendChild(typeSelect);
126
- modal.appendChild(errorMessage);
127
- modal.appendChild(buttons);
172
+ modal.appendChild(contentDiv);
128
173
  div.appendChild(modal);
129
174
  document.body.appendChild(div);
130
175
  nameInput.focus();
@@ -1 +1 @@
1
- {"version":3,"file":"modals.js","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/modals.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"modals.js","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/modals.ts"],"names":[],"mappings":"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"}
@@ -18,58 +18,90 @@ export async function editDevice(device: any): Promise<void> {
18
18
  const modal = document.createElement('div')
19
19
  modal.style.background = getComputedStyle(document.body).backgroundColor
20
20
  modal.style.color = getComputedStyle(document.body).color
21
- modal.style.padding = '24px'
22
- modal.style.borderRadius = '8px'
23
- modal.style.minWidth = '400px'
24
- modal.style.boxShadow = '0 10px 40px rgba(0,0,0,0.3)'
21
+ modal.style.padding = '0'
22
+ modal.style.borderRadius = '10px'
23
+ modal.style.minWidth = '440px'
24
+ modal.style.maxWidth = '90vw'
25
+ modal.style.boxShadow = '0 8px 32px rgba(0,0,0,0.35)'
26
+ modal.style.overflow = 'hidden'
27
+ modal.style.borderTop = '3px solid var(--switchbot-red, #ef4444)'
25
28
 
26
29
  const title = document.createElement('h3')
27
30
  title.textContent = 'Edit Device'
28
31
  title.style.marginTop = '0'
32
+ title.style.marginBottom = '16px'
33
+ title.style.padding = '20px 20px 0'
34
+ title.style.fontSize = '18px'
35
+ title.style.fontWeight = '600'
36
+ title.style.color = 'var(--switchbot-red, #ef4444)'
37
+ title.style.letterSpacing = '-0.02em'
38
+
39
+ const contentDiv = document.createElement('div')
40
+ contentDiv.style.padding = '0 20px 20px'
29
41
 
30
42
  const nameLabel = document.createElement('label')
31
43
  nameLabel.textContent = 'Device Name'
32
44
  nameLabel.style.display = 'block'
33
- nameLabel.style.marginBottom = '8px'
45
+ nameLabel.style.marginBottom = '6px'
34
46
  nameLabel.style.fontWeight = '500'
47
+ nameLabel.style.fontSize = '12px'
48
+ nameLabel.style.color = '#6b7280'
35
49
 
36
50
  const nameInput = document.createElement('input')
37
51
  nameInput.type = 'text'
38
52
  nameInput.value = device.name || device.id
39
53
  nameInput.style.width = '100%'
40
- nameInput.style.marginBottom = '16px'
54
+ nameInput.style.marginBottom = '12px'
55
+ nameInput.style.padding = '8px 10px'
56
+ nameInput.style.borderRadius = '6px'
57
+ nameInput.style.fontSize = '14px'
58
+ nameInput.style.boxSizing = 'border-box'
59
+ nameInput.style.transition = 'border-color 0.2s ease'
41
60
 
42
61
  // Read-only API device type field
43
62
  const apiTypeLabel = document.createElement('label')
44
63
  apiTypeLabel.textContent = 'Device Type (API - Read Only)'
45
64
  apiTypeLabel.style.display = 'block'
46
- apiTypeLabel.style.marginBottom = '8px'
65
+ apiTypeLabel.style.marginBottom = '6px'
47
66
  apiTypeLabel.style.fontWeight = '500'
67
+ apiTypeLabel.style.fontSize = '12px'
68
+ apiTypeLabel.style.color = '#6b7280'
48
69
 
49
70
  const apiTypeInput = document.createElement('input')
50
71
  apiTypeInput.type = 'text'
51
72
  apiTypeInput.value = device.deviceType || device.type || 'Unknown'
52
73
  apiTypeInput.readOnly = true
53
74
  apiTypeInput.style.width = '100%'
54
- apiTypeInput.style.marginBottom = '16px'
75
+ apiTypeInput.style.marginBottom = '12px'
76
+ apiTypeInput.style.padding = '8px 10px'
77
+ apiTypeInput.style.borderRadius = '6px'
78
+ apiTypeInput.style.fontSize = '13px'
55
79
  apiTypeInput.style.opacity = '0.6'
56
80
  apiTypeInput.style.cursor = 'not-allowed'
81
+ apiTypeInput.style.boxSizing = 'border-box'
82
+ apiTypeInput.style.backgroundColor = '#f9fafb'
57
83
 
58
84
  // Editable config device type dropdown
59
85
  const typeLabel = document.createElement('label')
60
86
  typeLabel.textContent = 'Config Device Type (Override)'
61
87
  typeLabel.style.display = 'block'
62
- typeLabel.style.marginBottom = '8px'
88
+ typeLabel.style.marginBottom = '6px'
63
89
  typeLabel.style.fontWeight = '500'
90
+ typeLabel.style.fontSize = '12px'
91
+ typeLabel.style.color = '#6b7280'
64
92
 
65
93
  const typeSelect = document.createElement('select')
66
94
  typeSelect.style.width = '100%'
67
- typeSelect.style.padding = '8px'
68
- typeSelect.style.marginBottom = '16px'
69
- typeSelect.style.borderRadius = '4px'
95
+ typeSelect.style.padding = '8px 10px'
96
+ typeSelect.style.marginBottom = '12px'
97
+ typeSelect.style.borderRadius = '6px'
98
+ typeSelect.style.fontSize = '14px'
70
99
  typeSelect.style.background = getComputedStyle(nameInput).background
71
100
  typeSelect.style.color = getComputedStyle(nameInput).color
72
101
  typeSelect.style.border = getComputedStyle(nameInput).border
102
+ typeSelect.style.boxSizing = 'border-box'
103
+ typeSelect.style.cursor = 'pointer'
104
+ typeSelect.style.transition = 'border-color 0.2s ease'
73
105
 
74
106
  // Add option groups with all API device types
75
107
  Object.keys(DEVICE_TYPES).forEach((categoryName) => {
@@ -90,24 +122,37 @@ export async function editDevice(device: any): Promise<void> {
90
122
  typeSelect.appendChild(optgroup)
91
123
  })
92
124
 
93
- const buttons = document.createElement('div')
94
- buttons.style.display = 'flex'
95
- buttons.style.gap = '8px'
96
- buttons.style.justifyContent = 'flex-end'
97
-
98
125
  const errorMessage = document.createElement('div')
99
- errorMessage.style.color = '#ef4444'
126
+ errorMessage.style.color = 'var(--switchbot-red, #ef4444)'
100
127
  errorMessage.style.marginBottom = '12px'
101
128
  errorMessage.style.fontSize = '12px'
102
129
  errorMessage.style.display = 'none'
130
+ errorMessage.style.padding = '8px 10px'
131
+ errorMessage.style.background = 'var(--switchbot-red-light, #fee2e2)'
132
+ errorMessage.style.borderRadius = '6px'
133
+ errorMessage.style.fontWeight = '500'
134
+
135
+ const buttons = document.createElement('div')
136
+ buttons.style.display = 'flex'
137
+ buttons.style.gap = '10px'
138
+ buttons.style.justifyContent = 'flex-end'
139
+ buttons.style.marginTop = '18px'
140
+ buttons.style.paddingTop = '18px'
141
+ buttons.style.borderTop = '1px solid rgba(0, 0, 0, 0.08)'
103
142
 
104
143
  const cancelBtn = document.createElement('button')
105
144
  cancelBtn.textContent = 'Cancel'
106
- cancelBtn.style.background = '#666'
145
+ cancelBtn.className = 'secondary'
146
+ cancelBtn.style.background = '#6b7280'
147
+ cancelBtn.style.padding = '8px 16px'
148
+ cancelBtn.style.fontSize = '13px'
107
149
  cancelBtn.onclick = () => div.remove()
108
150
 
109
151
  const saveBtn = document.createElement('button')
110
152
  saveBtn.textContent = 'Save'
153
+ saveBtn.style.background = 'var(--switchbot-red, #ef4444)'
154
+ saveBtn.style.padding = '8px 20px'
155
+ saveBtn.style.fontSize = '13px'
111
156
  saveBtn.onclick = async () => {
112
157
  try {
113
158
  const { updateDevice, syncParentPluginConfigFromDisk, fetchDevices } = await import('./api.js')
@@ -137,15 +182,17 @@ export async function editDevice(device: any): Promise<void> {
137
182
  buttons.appendChild(cancelBtn)
138
183
  buttons.appendChild(saveBtn)
139
184
 
185
+ contentDiv.appendChild(nameLabel)
186
+ contentDiv.appendChild(nameInput)
187
+ contentDiv.appendChild(apiTypeLabel)
188
+ contentDiv.appendChild(apiTypeInput)
189
+ contentDiv.appendChild(typeLabel)
190
+ contentDiv.appendChild(typeSelect)
191
+ contentDiv.appendChild(errorMessage)
192
+ contentDiv.appendChild(buttons)
193
+
140
194
  modal.appendChild(title)
141
- modal.appendChild(nameLabel)
142
- modal.appendChild(nameInput)
143
- modal.appendChild(apiTypeLabel)
144
- modal.appendChild(apiTypeInput)
145
- modal.appendChild(typeLabel)
146
- modal.appendChild(typeSelect)
147
- modal.appendChild(errorMessage)
148
- modal.appendChild(buttons)
195
+ modal.appendChild(contentDiv)
149
196
 
150
197
  div.appendChild(modal)
151
198
  document.body.appendChild(div)
@@ -1,6 +1,63 @@
1
+ /**
2
+ * Get RSSI signal quality level and color based on dBm value
3
+ * @param rssi Signal strength in dBm (typically -30 to -90)
4
+ * @returns Object with quality level, color, and description
5
+ */
6
+ export declare function getRssiSignalQuality(rssi: number | undefined): {
7
+ level: 'excellent' | 'good' | 'fair' | 'poor' | 'unknown';
8
+ color: string;
9
+ bgColor: string;
10
+ description: string;
11
+ bars: number;
12
+ };
13
+ /**
14
+ * Create visual signal strength indicator bars
15
+ * @param rssi Signal strength in dBm
16
+ * @returns HTML element showing filled bars
17
+ */
18
+ export declare function renderSignalBars(rssi: number | undefined): HTMLElement;
19
+ /**
20
+ * Create signal quality badge with color
21
+ * @param rssi Signal strength in dBm
22
+ * @returns HTML element showing quality level
23
+ */
24
+ export declare function renderSignalQualityBadge(rssi: number | undefined): HTMLElement;
1
25
  export declare function renderBadge(text: string, style: string): HTMLElement;
2
26
  export declare function renderConnectionBadge(connectionType: string): HTMLElement | null;
3
27
  export declare function renderIRBadge(): HTMLElement;
4
28
  export declare function renderDiscoveredDevices(devices: any[]): Promise<HTMLElement>;
29
+ /**
30
+ * Filter devices by connection type and search query
31
+ * @param devices Discovered devices array
32
+ * @param connectionType Filter: 'all' | 'ble' | 'api' | 'both' | 'ir'
33
+ * @param searchQuery Search term to match against name/id/type
34
+ * @returns Filtered devices array
35
+ */
36
+ export declare function filterDevices(devices: any[], connectionType?: 'all' | 'ble' | 'api' | 'both' | 'ir', searchQuery?: string): any[];
37
+ /**
38
+ * Sort devices by specified criteria
39
+ * @param devices Devices array to sort
40
+ * @param sortBy Sort criterion: 'name' | 'signal' | 'type' | 'connection'
41
+ * @returns Sorted devices array
42
+ */
43
+ export declare function sortDevices(devices: any[], sortBy?: 'name' | 'signal' | 'type' | 'connection'): any[];
44
+ /**
45
+ * Get filter/sort preferences from localStorage
46
+ * @returns Object with current filter and sort preferences
47
+ */
48
+ export declare function getDiscoveryPreferences(): {
49
+ connectionType: 'all' | 'ble' | 'api' | 'both' | 'ir';
50
+ sortBy: 'name' | 'signal' | 'type' | 'connection';
51
+ searchQuery: string;
52
+ };
53
+ /**
54
+ * Save filter/sort preferences to localStorage
55
+ * @param preferences Preferences object to save
56
+ */
57
+ export declare function setDiscoveryPreferences(preferences: {
58
+ connectionType: 'all' | 'ble' | 'api' | 'both' | 'ir';
59
+ sortBy: 'name' | 'signal' | 'type' | 'connection';
60
+ searchQuery: string;
61
+ }): void;
5
62
  export declare function renderDeviceList(list: any[]): void;
6
63
  //# sourceMappingURL=render.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/render.ts"],"names":[],"mappings":"AAEA,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAKpE;AAED,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAiBhF;AAED,wBAAgB,aAAa,IAAI,WAAW,CAK3C;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAyDlF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CA+FlD"}
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../../src/homebridge-ui/public/js/render.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG;IAC9D,KAAK,EAAE,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;CACb,CA8CA;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CA+BtE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAiB9E;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,WAAW,CAKpE;AAED,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAiBhF;AAED,wBAAgB,aAAa,IAAI,WAAW,CAK3C;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAsFlF;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,GAAG,EAAE,EACd,cAAc,GAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,IAAY,EAC7D,WAAW,SAAK,GACf,GAAG,EAAE,CAmCP;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,GAAG,EAAE,EACd,MAAM,GAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAqB,GACzD,GAAG,EAAE,CA8CP;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI;IACzC,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,CAAA;IACrD,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAA;IACjD,WAAW,EAAE,MAAM,CAAA;CACpB,CAeA;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE;IACnD,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,IAAI,CAAA;IACrD,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAA;IACjD,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,IAAI,CAMP;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,IAAI,CAuHlD"}