@mp-consulting/homebridge-daikin-cloud 1.3.6 → 1.3.8

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 (291) hide show
  1. package/LICENSE +39 -1
  2. package/README.md +3 -1
  3. package/dist/src/accessories/air-conditioning-accessory.d.ts +2 -2
  4. package/dist/src/accessories/air-conditioning-accessory.d.ts.map +1 -1
  5. package/dist/src/accessories/air-conditioning-accessory.js.map +1 -1
  6. package/dist/src/accessories/altherma-accessory.d.ts +2 -2
  7. package/dist/src/accessories/altherma-accessory.d.ts.map +1 -1
  8. package/dist/src/accessories/altherma-accessory.js.map +1 -1
  9. package/dist/src/accessories/base-accessory.d.ts +5 -5
  10. package/dist/src/accessories/base-accessory.d.ts.map +1 -1
  11. package/dist/src/accessories/base-accessory.js +7 -4
  12. package/dist/src/accessories/base-accessory.js.map +1 -1
  13. package/dist/src/api/daikin-api.d.ts +25 -25
  14. package/dist/src/api/daikin-api.d.ts.map +1 -1
  15. package/dist/src/api/daikin-api.js +41 -31
  16. package/dist/src/api/daikin-api.js.map +1 -1
  17. package/dist/src/api/daikin-cloud.repository.d.ts.map +1 -1
  18. package/dist/src/api/daikin-cloud.repository.js.map +1 -1
  19. package/dist/src/api/daikin-controller.d.ts +41 -42
  20. package/dist/src/api/daikin-controller.d.ts.map +1 -1
  21. package/dist/src/api/daikin-controller.js +39 -39
  22. package/dist/src/api/daikin-controller.js.map +1 -1
  23. package/dist/src/api/daikin-device.d.ts +33 -31
  24. package/dist/src/api/daikin-device.d.ts.map +1 -1
  25. package/dist/src/api/daikin-device.js +40 -29
  26. package/dist/src/api/daikin-device.js.map +1 -1
  27. package/dist/src/api/daikin-mobile-oauth.d.ts +16 -16
  28. package/dist/src/api/daikin-mobile-oauth.d.ts.map +1 -1
  29. package/dist/src/api/daikin-mobile-oauth.js +32 -22
  30. package/dist/src/api/daikin-mobile-oauth.js.map +1 -1
  31. package/dist/src/api/daikin-oauth.d.ts +29 -29
  32. package/dist/src/api/daikin-oauth.d.ts.map +1 -1
  33. package/dist/src/api/daikin-oauth.js +45 -35
  34. package/dist/src/api/daikin-oauth.js.map +1 -1
  35. package/dist/src/api/daikin-schemas.d.ts +4 -4
  36. package/dist/src/api/daikin-schemas.js +3 -3
  37. package/dist/src/api/daikin-schemas.js.map +1 -1
  38. package/dist/src/api/daikin-types.js.map +1 -1
  39. package/dist/src/api/daikin-websocket.d.ts +31 -32
  40. package/dist/src/api/daikin-websocket.d.ts.map +1 -1
  41. package/dist/src/api/daikin-websocket.js +30 -30
  42. package/dist/src/api/daikin-websocket.js.map +1 -1
  43. package/dist/src/api/index.d.ts +1 -1
  44. package/dist/src/api/index.d.ts.map +1 -1
  45. package/dist/src/api/index.js +2 -1
  46. package/dist/src/api/index.js.map +1 -1
  47. package/dist/src/api/token-storage.d.ts +1 -1
  48. package/dist/src/api/token-storage.d.ts.map +1 -1
  49. package/dist/src/api/token-storage.js +20 -11
  50. package/dist/src/api/token-storage.js.map +1 -1
  51. package/dist/src/config/config-manager.d.ts +33 -33
  52. package/dist/src/config/config-manager.d.ts.map +1 -1
  53. package/dist/src/config/config-manager.js +33 -33
  54. package/dist/src/config/config-manager.js.map +1 -1
  55. package/dist/src/constants/api.constants.js.map +1 -1
  56. package/dist/src/device/accessory-factory.d.ts +10 -10
  57. package/dist/src/device/accessory-factory.d.ts.map +1 -1
  58. package/dist/src/device/accessory-factory.js +6 -6
  59. package/dist/src/device/accessory-factory.js.map +1 -1
  60. package/dist/src/device/capability-detector.d.ts +8 -8
  61. package/dist/src/device/capability-detector.d.ts.map +1 -1
  62. package/dist/src/device/capability-detector.js +6 -6
  63. package/dist/src/device/capability-detector.js.map +1 -1
  64. package/dist/src/device/capability-docs.d.ts +1 -1
  65. package/dist/src/device/capability-docs.d.ts.map +1 -1
  66. package/dist/src/device/capability-docs.js +1 -2
  67. package/dist/src/device/capability-docs.js.map +1 -1
  68. package/dist/src/device/profiles/device-profile.d.ts +1 -1
  69. package/dist/src/device/profiles/device-profile.d.ts.map +1 -1
  70. package/dist/src/device/profiles/device-profile.js +4 -4
  71. package/dist/src/device/profiles/device-profile.js.map +1 -1
  72. package/dist/src/features/base-feature.d.ts +2 -2
  73. package/dist/src/features/base-feature.d.ts.map +1 -1
  74. package/dist/src/features/base-feature.js +2 -3
  75. package/dist/src/features/base-feature.js.map +1 -1
  76. package/dist/src/features/feature-manager.d.ts +8 -8
  77. package/dist/src/features/feature-manager.d.ts.map +1 -1
  78. package/dist/src/features/feature-manager.js +5 -5
  79. package/dist/src/features/feature-manager.js.map +1 -1
  80. package/dist/src/features/modes/dry-operation-mode.feature.d.ts +1 -1
  81. package/dist/src/features/modes/dry-operation-mode.feature.d.ts.map +1 -1
  82. package/dist/src/features/modes/dry-operation-mode.feature.js.map +1 -1
  83. package/dist/src/features/modes/econo-mode.feature.d.ts +1 -1
  84. package/dist/src/features/modes/econo-mode.feature.d.ts.map +1 -1
  85. package/dist/src/features/modes/econo-mode.feature.js.map +1 -1
  86. package/dist/src/features/modes/fan-only-operation-mode.feature.d.ts +1 -1
  87. package/dist/src/features/modes/fan-only-operation-mode.feature.d.ts.map +1 -1
  88. package/dist/src/features/modes/fan-only-operation-mode.feature.js.map +1 -1
  89. package/dist/src/features/modes/indoor-silent-mode.feature.d.ts +1 -1
  90. package/dist/src/features/modes/indoor-silent-mode.feature.d.ts.map +1 -1
  91. package/dist/src/features/modes/indoor-silent-mode.feature.js.map +1 -1
  92. package/dist/src/features/modes/outdoor-silent-mode.feature.d.ts +1 -1
  93. package/dist/src/features/modes/outdoor-silent-mode.feature.d.ts.map +1 -1
  94. package/dist/src/features/modes/outdoor-silent-mode.feature.js.map +1 -1
  95. package/dist/src/features/modes/powerful-mode.feature.d.ts +1 -1
  96. package/dist/src/features/modes/powerful-mode.feature.d.ts.map +1 -1
  97. package/dist/src/features/modes/powerful-mode.feature.js.map +1 -1
  98. package/dist/src/features/modes/streamer-mode.feature.d.ts +1 -1
  99. package/dist/src/features/modes/streamer-mode.feature.d.ts.map +1 -1
  100. package/dist/src/features/modes/streamer-mode.feature.js.map +1 -1
  101. package/dist/src/index.d.ts +1 -1
  102. package/dist/src/index.d.ts.map +1 -1
  103. package/dist/src/index.js.map +1 -1
  104. package/dist/src/platform.d.ts +6 -5
  105. package/dist/src/platform.d.ts.map +1 -1
  106. package/dist/src/platform.js +2 -2
  107. package/dist/src/platform.js.map +1 -1
  108. package/dist/src/services/climate-control.service.d.ts +8 -2
  109. package/dist/src/services/climate-control.service.d.ts.map +1 -1
  110. package/dist/src/services/climate-control.service.js +53 -59
  111. package/dist/src/services/climate-control.service.js.map +1 -1
  112. package/dist/src/services/hot-water-tank.service.d.ts +6 -2
  113. package/dist/src/services/hot-water-tank.service.d.ts.map +1 -1
  114. package/dist/src/services/hot-water-tank.service.js +31 -34
  115. package/dist/src/services/hot-water-tank.service.js.map +1 -1
  116. package/dist/src/types/daikin-enums.js +12 -12
  117. package/dist/src/types/daikin-enums.js.map +1 -1
  118. package/dist/src/types/device-capabilities.d.ts +1 -1
  119. package/dist/src/types/device-capabilities.d.ts.map +1 -1
  120. package/dist/src/utils/log-context.d.ts +23 -23
  121. package/dist/src/utils/log-context.d.ts.map +1 -1
  122. package/dist/src/utils/log-context.js +28 -28
  123. package/dist/src/utils/log-context.js.map +1 -1
  124. package/dist/src/utils/strings.d.ts.map +1 -1
  125. package/dist/src/utils/strings.js.map +1 -1
  126. package/dist/src/utils/update-mapper.d.ts +16 -16
  127. package/dist/src/utils/update-mapper.d.ts.map +1 -1
  128. package/dist/src/utils/update-mapper.js +14 -14
  129. package/dist/src/utils/update-mapper.js.map +1 -1
  130. package/homebridge-ui/public/index.html +24 -24
  131. package/homebridge-ui/public/lib/kit.css +253 -0
  132. package/homebridge-ui/public/lib/kit.js +133 -0
  133. package/homebridge-ui/public/script.js +957 -898
  134. package/homebridge-ui/public/styles.css +0 -1
  135. package/homebridge-ui/server.js +739 -695
  136. package/package.json +30 -25
  137. package/.claude/settings.json +0 -3
  138. package/.claude/settings.local.json +0 -24
  139. package/CHANGELOG.md +0 -114
  140. package/CLAUDE.md +0 -269
  141. package/config.md +0 -2
  142. package/docs/ARCHITECTURE.md +0 -645
  143. package/docs/IMPLEMENTATION_GUIDE.md +0 -899
  144. package/docs/IMPROVEMENTS_SUMMARY.md +0 -415
  145. package/docs/NEXT_STEPS.md +0 -368
  146. package/docs/Screenshot 2024-07-04 at 18.41.28.png +0 -0
  147. package/docs/TROUBLESHOOTING.md +0 -475
  148. package/docs/api-response-for-BRP069A8x.json +0 -520
  149. package/docs/api-response-for-BRP069C4x-2.json +0 -881
  150. package/docs/api-response-for-BRP069C4x.json +0 -916
  151. package/docs/api-response-for-altherma.json +0 -759
  152. package/docs/api-response-for-altherma2.json +0 -2735
  153. package/docs/api-response-with-multiple-devices-incl-heatpump.json +0 -2544
  154. package/docs/cr-insance-altherma-id-0.json +0 -834
  155. package/docs/mock-air-to-air-dx23.json +0 -759
  156. package/docs/mock-air-to-air-dx4.json +0 -1134
  157. package/docs/mock-airpurifier-with-humidifier.json +0 -732
  158. package/docs/mock-airpurifier.json +0 -450
  159. package/docs/mock-altherma-air-to-water-lan.json +0 -845
  160. package/docs/mock-altherma-air-to-water-wlan.json +0 -845
  161. package/docs/mock-d2cnd-gas-boiler.json +0 -649
  162. package/docs/setpointmode-vs-controlmode-vs-setpoints-vs-sensorydata.txt +0 -6
  163. package/images/fan-speed.jpeg +0 -0
  164. package/images/homekit-controls.jpeg +0 -0
  165. package/images/homekit-settings.jpeg +0 -0
  166. package/images/swing-mode.png +0 -0
  167. package/jest.config.ts +0 -21
  168. package/test/fixtures/altherma-crSense-2.ts +0 -834
  169. package/test/fixtures/altherma-fraction.ts +0 -718
  170. package/test/fixtures/altherma-heat-pump-2.ts +0 -479
  171. package/test/fixtures/altherma-heat-pump.ts +0 -757
  172. package/test/fixtures/altherma-miladcerkic-off.ts +0 -524
  173. package/test/fixtures/altherma-miladcerkic.ts +0 -524
  174. package/test/fixtures/altherma-v1ckoeln.ts +0 -644
  175. package/test/fixtures/altherma-with-embedded-id-zero.ts +0 -834
  176. package/test/fixtures/dx23-airco-2.ts +0 -343
  177. package/test/fixtures/dx23-airco.ts +0 -518
  178. package/test/fixtures/dx4-airco.ts +0 -914
  179. package/test/fixtures/unknown-jan.ts +0 -488
  180. package/test/fixtures/unknown-kitchen-guests.ts +0 -488
  181. package/test/hbConfig/.daikin-mobile-tokenset +0 -8
  182. package/test/hbConfig/.uix-dashboard.json +0 -1
  183. package/test/hbConfig/.uix-secrets +0 -1
  184. package/test/hbConfig/accessories/.cachedAccessories.bak +0 -1
  185. package/test/hbConfig/accessories/cachedAccessories +0 -1
  186. package/test/hbConfig/accessories/uiAccessoriesLayout.json +0 -1
  187. package/test/hbConfig/auth.json +0 -10
  188. package/test/hbConfig/backups/config-backups/config.json.1767953686461 +0 -25
  189. package/test/hbConfig/backups/config-backups/config.json.1767953695236 +0 -29
  190. package/test/hbConfig/backups/config-backups/config.json.1767953814763 +0 -29
  191. package/test/hbConfig/backups/config-backups/config.json.1767953823101 +0 -29
  192. package/test/hbConfig/backups/config-backups/config.json.1767954822835 +0 -29
  193. package/test/hbConfig/backups/config-backups/config.json.1767954859218 +0 -29
  194. package/test/hbConfig/backups/config-backups/config.json.1767960145503 +0 -33
  195. package/test/hbConfig/backups/config-backups/config.json.1767960168068 +0 -44
  196. package/test/hbConfig/backups/config-backups/config.json.1767960170333 +0 -46
  197. package/test/hbConfig/backups/config-backups/config.json.1767960172731 +0 -44
  198. package/test/hbConfig/backups/config-backups/config.json.1767960179323 +0 -44
  199. package/test/hbConfig/backups/config-backups/config.json.1767960182114 +0 -44
  200. package/test/hbConfig/backups/config-backups/config.json.1767960189302 +0 -44
  201. package/test/hbConfig/backups/config-backups/config.json.1767960195194 +0 -44
  202. package/test/hbConfig/backups/config-backups/config.json.1767960197301 +0 -44
  203. package/test/hbConfig/backups/config-backups/config.json.1767960199151 +0 -44
  204. package/test/hbConfig/backups/config-backups/config.json.1767960199667 +0 -44
  205. package/test/hbConfig/backups/config-backups/config.json.1767960329839 +0 -44
  206. package/test/hbConfig/backups/config-backups/config.json.1767960334503 +0 -44
  207. package/test/hbConfig/backups/config-backups/config.json.1767960336208 +0 -44
  208. package/test/hbConfig/backups/config-backups/config.json.1767960338537 +0 -44
  209. package/test/hbConfig/backups/config-backups/config.json.1767963223953 +0 -44
  210. package/test/hbConfig/backups/config-backups/config.json.1767963241753 +0 -44
  211. package/test/hbConfig/backups/config-backups/config.json.1767963252785 +0 -44
  212. package/test/hbConfig/backups/config-backups/config.json.1767963463944 +0 -44
  213. package/test/hbConfig/backups/config-backups/config.json.1767963834475 +0 -44
  214. package/test/hbConfig/backups/config-backups/config.json.1767963838474 +0 -44
  215. package/test/hbConfig/backups/config-backups/config.json.1767963843066 +0 -44
  216. package/test/hbConfig/backups/config-backups/config.json.1767965217715 +0 -44
  217. package/test/hbConfig/backups/config-backups/config.json.1767965419624 +0 -25
  218. package/test/hbConfig/backups/config-backups/config.json.1767965870934 +0 -32
  219. package/test/hbConfig/backups/config-backups/config.json.1767977675045 +0 -32
  220. package/test/hbConfig/backups/config-backups/config.json.1767977677222 +0 -33
  221. package/test/hbConfig/backups/config-backups/config.json.1767977710226 +0 -33
  222. package/test/hbConfig/backups/config-backups/config.json.1767977741397 +0 -33
  223. package/test/hbConfig/backups/config-backups/config.json.1767977977093 +0 -35
  224. package/test/hbConfig/backups/config-backups/config.json.1767977981773 +0 -35
  225. package/test/hbConfig/backups/config-backups/config.json.1767977986514 +0 -35
  226. package/test/hbConfig/backups/config-backups/config.json.1767977991174 +0 -35
  227. package/test/hbConfig/backups/config-backups/config.json.1767979424487 +0 -35
  228. package/test/hbConfig/backups/config-backups/config.json.1767979424987 +0 -35
  229. package/test/hbConfig/backups/config-backups/config.json.1767979432646 +0 -47
  230. package/test/hbConfig/backups/config-backups/config.json.1767979433150 +0 -47
  231. package/test/hbConfig/backups/config-backups/config.json.1767979436933 +0 -47
  232. package/test/hbConfig/backups/config-backups/config.json.1767979437438 +0 -47
  233. package/test/hbConfig/backups/config-backups/config.json.1767979441676 +0 -47
  234. package/test/hbConfig/backups/config-backups/config.json.1767979442180 +0 -47
  235. package/test/hbConfig/backups/config-backups/config.json.1767979466735 +0 -47
  236. package/test/hbConfig/backups/config-backups/config.json.1767979903636 +0 -47
  237. package/test/hbConfig/backups/config-backups/config.json.1767979904135 +0 -47
  238. package/test/hbConfig/backups/config-backups/config.json.1767979906606 +0 -47
  239. package/test/hbConfig/backups/config-backups/config.json.1767979907108 +0 -47
  240. package/test/hbConfig/backups/config-backups/config.json.1767988702341 +0 -47
  241. package/test/hbConfig/backups/config-backups/config.json.1767988702837 +0 -47
  242. package/test/hbConfig/backups/config-backups/config.json.1767988713159 +0 -47
  243. package/test/hbConfig/backups/config-backups/config.json.1767988713664 +0 -47
  244. package/test/hbConfig/backups/config-backups/config.json.1767988918139 +0 -47
  245. package/test/hbConfig/backups/config-backups/config.json.1767988918639 +0 -47
  246. package/test/hbConfig/backups/config-backups/config.json.1767988921120 +0 -47
  247. package/test/hbConfig/backups/config-backups/config.json.1767988921624 +0 -47
  248. package/test/hbConfig/backups/config-backups/config.json.1767988930307 +0 -47
  249. package/test/hbConfig/backups/config-backups/config.json.1767988935070 +0 -47
  250. package/test/hbConfig/backups/config-backups/config.json.1767988935574 +0 -47
  251. package/test/hbConfig/backups/config-backups/config.json.1767989710262 +0 -47
  252. package/test/hbConfig/backups/config-backups/config.json.1767989710760 +0 -47
  253. package/test/hbConfig/backups/config-backups/config.json.1767989729668 +0 -47
  254. package/test/hbConfig/backups/config-backups/config.json.1767990295225 +0 -47
  255. package/test/hbConfig/backups/config-backups/config.json.1767990479921 +0 -47
  256. package/test/hbConfig/backups/config-backups/config.json.1767990481702 +0 -49
  257. package/test/hbConfig/backups/instance-backups/homebridge-backup-1E4A432551BA.1768010187391.tar.gz +0 -0
  258. package/test/hbConfig/backups/instance-backups/homebridge-backup-1E4A432551BA.1768096587387.tar.gz +0 -0
  259. package/test/hbConfig/backups/instance-backups/homebridge-backup-1E4A432551BA.1768182987404.tar.gz +0 -0
  260. package/test/hbConfig/config.json +0 -47
  261. package/test/hbConfig/daikin-cloud-certs/server.crt +0 -22
  262. package/test/hbConfig/daikin-cloud-certs/server.key +0 -28
  263. package/test/hbConfig/persist/AccessoryInfo.1E4A432551BA.json +0 -1
  264. package/test/hbConfig/persist/IdentifierCache.1E4A432551BA.json +0 -1
  265. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14758 +0 -1
  266. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14759 +0 -1
  267. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14760 +0 -1
  268. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14761 +0 -1
  269. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14762 +0 -1
  270. package/test/hbConfig/tmp/daikin_request/api.onecta.daikineurope.com_01-09-2026-23-29-52/request_14764 +0 -1
  271. package/test/helpers/test-isolation.ts +0 -228
  272. package/test/integration/air-conditioning.test.ts +0 -396
  273. package/test/integration/altherma.test.ts +0 -279
  274. package/test/integration/platform.test.ts +0 -118
  275. package/test/mobile-tokens.json +0 -8
  276. package/test/mocks/index.ts +0 -27
  277. package/test/test-gigya-auth.js +0 -443
  278. package/test/test-mobile-oauth.js +0 -175
  279. package/test/test-websocket-mobile.js +0 -123
  280. package/test/test-websocket.js +0 -116
  281. package/test/unit/api/__snapshots__/daikinCloud.test.ts.snap +0 -1320
  282. package/test/unit/api/daikin-api.test.ts +0 -442
  283. package/test/unit/api/daikin-cloud-repository.test.ts +0 -107
  284. package/test/unit/api/daikin-oauth.test.ts +0 -214
  285. package/test/unit/api/daikinCloud.test.ts +0 -12
  286. package/test/unit/api/token-storage.test.ts +0 -90
  287. package/test/unit/config/config-manager.test.ts +0 -271
  288. package/test/unit/device/daikin-device.test.ts +0 -73
  289. package/test/unit/services/hot-water-tank.service.test.ts +0 -123
  290. package/test/unit/utils/log-context.test.ts +0 -271
  291. package/test/unit/utils/update-mapper.test.ts +0 -404
@@ -0,0 +1,253 @@
1
+ /* @mp-consulting/homebridge-ui-kit v1.0.0 */
2
+
3
+ /* ── Design tokens ──────────────────────────────────────────────────────────
4
+ CSS custom properties used throughout the design system.
5
+ Override these in your plugin's styles.css to customize per-plugin.
6
+ ────────────────────────────────────────────────────────────────────────── */
7
+
8
+ :root {
9
+ /* Brand */
10
+ --mp-primary: #4f46e5;
11
+ --mp-primary-rgb: 79, 70, 229;
12
+ --mp-primary-hover: #4338ca;
13
+ --mp-primary-subtle: rgba(79, 70, 229, 0.12);
14
+
15
+ /* Status */
16
+ --mp-status-online: #10b981;
17
+ --mp-status-online-glow: rgba(16, 185, 129, 0.35);
18
+ --mp-status-offline: #ef4444;
19
+ --mp-status-checking: #94a3b8;
20
+
21
+ /* Surfaces */
22
+ --mp-surface: rgba(255, 255, 255, 0.03);
23
+ --mp-border: rgba(255, 255, 255, 0.08);
24
+
25
+ /* Shape */
26
+ --mp-radius: 0.5rem;
27
+ --mp-shadow-hover: 0 0.5rem 1rem rgba(0, 0, 0, 0.3);
28
+ }
29
+
30
+ /* ── Bootstrap 5 overrides ──────────────────────────────────────────────────
31
+ Remap Bootstrap components to use brand tokens.
32
+ ────────────────────────────────────────────────────────────────────────── */
33
+
34
+ /* Primary button */
35
+ .btn-primary {
36
+ --bs-btn-bg: var(--mp-primary);
37
+ --bs-btn-border-color: var(--mp-primary);
38
+ --bs-btn-hover-bg: var(--mp-primary-hover);
39
+ --bs-btn-hover-border-color: var(--mp-primary-hover);
40
+ --bs-btn-active-bg: var(--mp-primary-hover);
41
+ --bs-btn-active-border-color: var(--mp-primary-hover);
42
+ --bs-btn-focus-shadow-rgb: var(--mp-primary-rgb);
43
+ }
44
+
45
+ /* Primary spinner */
46
+ .spinner-border.text-primary,
47
+ .spinner-grow.text-primary {
48
+ color: var(--mp-primary) !important;
49
+ }
50
+
51
+ /* ── Components ─────────────────────────────────────────────────────────────
52
+ Reusable UI components used across all Homebridge plugins.
53
+ ────────────────────────────────────────────────────────────────────────── */
54
+
55
+ /* ── Plugin header ──────────────────────────────────────── */
56
+
57
+ .mp-header {
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 0.875rem;
61
+ margin-bottom: 0.5rem;
62
+ }
63
+
64
+ .mp-header-icon {
65
+ font-size: 2rem;
66
+ flex-shrink: 0;
67
+ line-height: 1;
68
+ }
69
+
70
+ .mp-header-title {
71
+ font-size: 1.375rem;
72
+ font-weight: 600;
73
+ margin: 0;
74
+ line-height: 1.3;
75
+ }
76
+
77
+ .mp-header-subtitle {
78
+ font-size: 0.875rem;
79
+ color: var(--bs-secondary-color);
80
+ margin: 0;
81
+ }
82
+
83
+ /* ── Status indicator dot ───────────────────────────────── */
84
+
85
+ .mp-status {
86
+ width: 8px;
87
+ height: 8px;
88
+ border-radius: 50%;
89
+ display: inline-block;
90
+ flex-shrink: 0;
91
+ vertical-align: middle;
92
+ }
93
+
94
+ .mp-status-online {
95
+ background-color: var(--mp-status-online);
96
+ box-shadow: 0 0 5px var(--mp-status-online-glow);
97
+ }
98
+
99
+ .mp-status-offline {
100
+ background-color: var(--mp-status-offline);
101
+ }
102
+
103
+ .mp-status-checking {
104
+ background-color: var(--mp-status-checking);
105
+ animation: mp-pulse 1.5s ease-in-out infinite;
106
+ }
107
+
108
+ @keyframes mp-pulse {
109
+ 0%, 100% { opacity: 1; }
110
+ 50% { opacity: 0.35; }
111
+ }
112
+
113
+ /* ── Device card ────────────────────────────────────────── */
114
+
115
+ .mp-device-card {
116
+ transition: transform 0.15s ease, box-shadow 0.15s ease;
117
+ cursor: pointer;
118
+ }
119
+
120
+ .mp-device-card:hover {
121
+ transform: translateY(-1px);
122
+ box-shadow: var(--mp-shadow-hover) !important;
123
+ }
124
+
125
+ /* ── Settings surface card ──────────────────────────────── */
126
+
127
+ .mp-settings-card {
128
+ background: var(--mp-surface);
129
+ border: 1px solid var(--mp-border) !important;
130
+ border-radius: var(--mp-radius);
131
+ }
132
+
133
+ /* ── Empty state ────────────────────────────────────────── */
134
+
135
+ .mp-empty-state {
136
+ display: flex;
137
+ flex-direction: column;
138
+ align-items: center;
139
+ justify-content: center;
140
+ padding: 3rem 1.5rem;
141
+ text-align: center;
142
+ }
143
+
144
+ .mp-empty-state-icon {
145
+ font-size: 2.5rem;
146
+ color: var(--bs-secondary-color);
147
+ margin-bottom: 0.75rem;
148
+ line-height: 1;
149
+ }
150
+
151
+ .mp-empty-state-title {
152
+ font-size: 0.9375rem;
153
+ font-weight: 500;
154
+ color: var(--bs-secondary-color);
155
+ margin: 0 0 0.25rem;
156
+ }
157
+
158
+ .mp-empty-state-hint {
159
+ font-size: 0.8125rem;
160
+ color: var(--bs-secondary-color);
161
+ margin: 0;
162
+ opacity: 0.7;
163
+ }
164
+
165
+ /* ── Loading state ──────────────────────────────────────── */
166
+
167
+ .mp-loading {
168
+ display: flex;
169
+ flex-direction: column;
170
+ align-items: center;
171
+ justify-content: center;
172
+ padding: 2.5rem 1.5rem;
173
+ gap: 0.75rem;
174
+ color: var(--bs-secondary-color);
175
+ font-size: 0.875rem;
176
+ }
177
+
178
+ /* ── Nav tabs ───────────────────────────────────────────── */
179
+
180
+ .mp-tabs {
181
+ border-bottom: 1px solid var(--mp-border);
182
+ }
183
+
184
+ .mp-tabs .nav-link {
185
+ color: var(--bs-secondary-color);
186
+ border: none;
187
+ padding: 0.75rem 1.25rem;
188
+ font-weight: 500;
189
+ }
190
+
191
+ .mp-tabs .nav-link:hover {
192
+ color: var(--bs-body-color);
193
+ border: none;
194
+ }
195
+
196
+ .mp-tabs .nav-link.active {
197
+ color: var(--mp-primary);
198
+ background: transparent;
199
+ border: none;
200
+ border-bottom: 2px solid var(--mp-primary);
201
+ }
202
+
203
+ /* ── Metadata label ─────────────────────────────────────── */
204
+
205
+ .mp-label {
206
+ font-size: 0.75rem;
207
+ text-transform: uppercase;
208
+ letter-spacing: 0.5px;
209
+ color: var(--bs-secondary-color);
210
+ }
211
+
212
+ /* ── View toggling ──────────────────────────────────────── */
213
+
214
+ .mp-view {
215
+ display: none;
216
+ }
217
+
218
+ .mp-view.active {
219
+ display: block;
220
+ }
221
+
222
+ /* ── Support footer ─────────────────────────────────────── */
223
+
224
+ .mp-footer {
225
+ display: flex;
226
+ align-items: center;
227
+ justify-content: center;
228
+ flex-wrap: wrap;
229
+ gap: 0.75rem 1rem;
230
+ padding-top: 1.5rem;
231
+ margin-top: 2rem;
232
+ border-top: 1px solid var(--mp-border);
233
+ font-size: 0.8125rem;
234
+ color: var(--bs-secondary-color);
235
+ }
236
+
237
+ .mp-footer a {
238
+ color: var(--bs-secondary-color);
239
+ text-decoration: none;
240
+ display: inline-flex;
241
+ align-items: center;
242
+ gap: 0.3rem;
243
+ transition: color 0.15s ease;
244
+ }
245
+
246
+ .mp-footer a:hover {
247
+ color: var(--mp-primary);
248
+ }
249
+
250
+ .mp-footer-sep {
251
+ color: var(--mp-border);
252
+ user-select: none;
253
+ }
@@ -0,0 +1,133 @@
1
+ /* @mp-consulting/homebridge-ui-kit v1.0.0
2
+ Brand design system for Homebridge plugins
3
+ https://github.com/mp-consulting/homebridge-ui-kit */
4
+
5
+ (function (global) {
6
+ 'use strict';
7
+
8
+ var MpKit = {
9
+
10
+ /**
11
+ * StatusBadge — returns inline HTML for device status badges.
12
+ *
13
+ * MpKit.StatusBadge.online() → green dot + "Online"
14
+ * MpKit.StatusBadge.offline() → red dot + "Offline"
15
+ * MpKit.StatusBadge.checking() → animated dot + "Checking..."
16
+ * MpKit.StatusBadge.disabled() → grey badge + "Disabled"
17
+ */
18
+ StatusBadge: {
19
+ online: function (label) {
20
+ label = label || 'Online';
21
+ return '<span class="badge bg-success-subtle text-success">'
22
+ + '<span class="mp-status mp-status-online me-1"></span>'
23
+ + label + '</span>';
24
+ },
25
+ offline: function (label) {
26
+ label = label || 'Offline';
27
+ return '<span class="badge bg-danger-subtle text-danger">'
28
+ + '<span class="mp-status mp-status-offline me-1"></span>'
29
+ + label + '</span>';
30
+ },
31
+ checking: function (label) {
32
+ label = label || 'Checking...';
33
+ return '<span class="badge bg-secondary-subtle text-secondary">'
34
+ + '<span class="mp-status mp-status-checking me-1"></span>'
35
+ + label + '</span>';
36
+ },
37
+ disabled: function (label) {
38
+ label = label || 'Disabled';
39
+ return '<span class="badge bg-secondary">' + label + '</span>';
40
+ },
41
+ },
42
+
43
+ /**
44
+ * EmptyState — returns HTML for an empty list placeholder.
45
+ *
46
+ * MpKit.EmptyState.render({
47
+ * iconClass: 'bi bi-lightbulb',
48
+ * title: 'No devices found',
49
+ * hint: 'Click Discover to scan your network',
50
+ * })
51
+ */
52
+ EmptyState: {
53
+ render: function (opts) {
54
+ opts = opts || {};
55
+ var icon = opts.iconClass || 'bi bi-inbox';
56
+ var title = opts.title || 'No items';
57
+ var hint = opts.hint || '';
58
+ return '<div class="mp-empty-state">'
59
+ + '<i class="' + icon + ' mp-empty-state-icon"></i>'
60
+ + '<p class="mp-empty-state-title">' + title + '</p>'
61
+ + (hint ? '<p class="mp-empty-state-hint">' + hint + '</p>' : '')
62
+ + '</div>';
63
+ },
64
+ },
65
+
66
+ /**
67
+ * Loading — returns HTML for a centred loading spinner with message.
68
+ *
69
+ * MpKit.Loading.render('Loading device information...')
70
+ */
71
+ Loading: {
72
+ render: function (message) {
73
+ message = message || 'Loading...';
74
+ return '<div class="mp-loading">'
75
+ + '<div class="spinner-border spinner-border-sm text-secondary" role="status" aria-hidden="true"></div>'
76
+ + '<span>' + message + '</span>'
77
+ + '</div>';
78
+ },
79
+ },
80
+
81
+ /**
82
+ * View — controls which .mp-view element is visible.
83
+ *
84
+ * MpKit.View.show('listView') → shows #listView, hides all others
85
+ * MpKit.View.show('settingsView') → shows #settingsView, hides all others
86
+ */
87
+ View: {
88
+ show: function (id) {
89
+ document.querySelectorAll('.mp-view').forEach(function (v) {
90
+ v.classList.remove('active');
91
+ });
92
+ var el = document.getElementById(id);
93
+ if (el) { el.classList.add('active'); }
94
+ },
95
+ },
96
+
97
+ /**
98
+ * Footer — renders support links into a .mp-footer element.
99
+ *
100
+ * MpKit.Footer.render({
101
+ * github: 'https://github.com/mp-consulting/homebridge-...',
102
+ * npm: 'https://www.npmjs.com/package/@mp-consulting/...',
103
+ * changelog: 'https://github.com/.../blob/main/CHANGELOG.md',
104
+ * })
105
+ */
106
+ Footer: {
107
+ render: function (opts) {
108
+ opts = opts || {};
109
+ var target = opts.target || '.mp-footer';
110
+ var el = typeof target === 'string' ? document.querySelector(target) : target;
111
+ if (!el) { return; }
112
+ var links = [];
113
+ if (opts.github) {
114
+ links.push('<a href="' + opts.github + '" target="_blank" rel="noopener">'
115
+ + '<i class="bi bi-github"></i>GitHub</a>');
116
+ }
117
+ if (opts.npm) {
118
+ links.push('<a href="' + opts.npm + '" target="_blank" rel="noopener">'
119
+ + '<i class="bi bi-box-seam"></i>npm</a>');
120
+ }
121
+ if (opts.changelog) {
122
+ links.push('<a href="' + opts.changelog + '" target="_blank" rel="noopener">'
123
+ + '<i class="bi bi-clock-history"></i>Changelog</a>');
124
+ }
125
+ el.innerHTML = links.join('<span class="mp-footer-sep">|</span>');
126
+ },
127
+ },
128
+
129
+ };
130
+
131
+ global.MpKit = MpKit;
132
+
133
+ })(window);