@seamapi/react 0.10.0 → 0.11.0

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 (224) hide show
  1. package/index.css +243 -105
  2. package/index.css.map +1 -1
  3. package/index.min.css +1 -1
  4. package/index.min.css.map +1 -1
  5. package/lib/{provider.d.ts → SeamProvider.d.ts} +1 -0
  6. package/lib/{provider.js → SeamProvider.js} +9 -2
  7. package/lib/SeamProvider.js.map +1 -0
  8. package/lib/icons/AccessCodeKey.d.ts +2 -0
  9. package/lib/icons/AccessCodeKey.js +3 -0
  10. package/lib/icons/AccessCodeKey.js.map +1 -0
  11. package/lib/icons/ArrowBack.d.ts +2 -0
  12. package/lib/icons/ArrowBack.js +5 -0
  13. package/lib/icons/ArrowBack.js.map +1 -0
  14. package/lib/icons/BatteryLevelCritical.d.ts +2 -0
  15. package/lib/icons/BatteryLevelCritical.js +3 -0
  16. package/lib/icons/BatteryLevelCritical.js.map +1 -0
  17. package/lib/icons/BatteryLevelFull.d.ts +2 -0
  18. package/lib/icons/BatteryLevelFull.js +3 -0
  19. package/lib/icons/BatteryLevelFull.js.map +1 -0
  20. package/lib/icons/BatteryLevelHigh.d.ts +2 -0
  21. package/lib/icons/BatteryLevelHigh.js +3 -0
  22. package/lib/icons/BatteryLevelHigh.js.map +1 -0
  23. package/lib/icons/BatteryLevelLow.d.ts +2 -0
  24. package/lib/icons/BatteryLevelLow.js +3 -0
  25. package/lib/icons/BatteryLevelLow.js.map +1 -0
  26. package/lib/icons/BatteryLevelWired.d.ts +2 -0
  27. package/lib/icons/BatteryLevelWired.js +5 -0
  28. package/lib/icons/BatteryLevelWired.js.map +1 -0
  29. package/lib/icons/ChevronRight.d.ts +2 -0
  30. package/lib/icons/ChevronRight.js +5 -0
  31. package/lib/icons/ChevronRight.js.map +1 -0
  32. package/lib/icons/DotsEllipsisMore.d.ts +2 -0
  33. package/lib/icons/DotsEllipsisMore.js +5 -0
  34. package/lib/icons/DotsEllipsisMore.js.map +1 -0
  35. package/lib/icons/OnlineStatusAccountOffline.d.ts +2 -0
  36. package/lib/icons/OnlineStatusAccountOffline.js +5 -0
  37. package/lib/icons/OnlineStatusAccountOffline.js.map +1 -0
  38. package/lib/icons/OnlineStatusDeviceOffline.d.ts +2 -0
  39. package/lib/icons/OnlineStatusDeviceOffline.js +3 -0
  40. package/lib/icons/OnlineStatusDeviceOffline.js.map +1 -0
  41. package/lib/icons/OnlineStatusOnline.d.ts +2 -0
  42. package/lib/icons/OnlineStatusOnline.js +3 -0
  43. package/lib/icons/OnlineStatusOnline.js.map +1 -0
  44. package/lib/icons/index.d.ts +12 -0
  45. package/lib/icons/index.js +12 -0
  46. package/lib/icons/index.js.map +1 -1
  47. package/lib/index.d.ts +3 -3
  48. package/lib/index.js +3 -3
  49. package/lib/index.js.map +1 -1
  50. package/lib/seam/devices/index.d.ts +1 -0
  51. package/lib/seam/devices/index.js +2 -0
  52. package/lib/seam/devices/index.js.map +1 -0
  53. package/lib/{hooks → seam/devices}/use-devices.js +3 -3
  54. package/lib/seam/devices/use-devices.js.map +1 -0
  55. package/lib/seam/index.d.ts +2 -0
  56. package/lib/seam/index.js +3 -0
  57. package/lib/seam/index.js.map +1 -0
  58. package/lib/{hooks/use-seam.d.ts → seam/use-seam-client.d.ts} +1 -1
  59. package/lib/{hooks/use-seam.js → seam/use-seam-client.js} +4 -5
  60. package/lib/seam/use-seam-client.js.map +1 -0
  61. package/lib/ui/AccessCodeTable/AccessCodeTable.d.ts +5 -0
  62. package/lib/ui/AccessCodeTable/AccessCodeTable.js +15 -0
  63. package/lib/ui/AccessCodeTable/AccessCodeTable.js.map +1 -0
  64. package/lib/ui/AccessCodeTable/CodeDetails.d.ts +4 -0
  65. package/lib/ui/AccessCodeTable/CodeDetails.js +28 -0
  66. package/lib/ui/AccessCodeTable/CodeDetails.js.map +1 -0
  67. package/lib/ui/AccessCodeTable/index.d.ts +2 -0
  68. package/lib/ui/AccessCodeTable/index.js +3 -0
  69. package/lib/ui/AccessCodeTable/index.js.map +1 -0
  70. package/lib/ui/DeviceDetails/BatteryStatus.d.ts +4 -0
  71. package/lib/ui/DeviceDetails/BatteryStatus.js +41 -0
  72. package/lib/ui/DeviceDetails/BatteryStatus.js.map +1 -0
  73. package/lib/ui/DeviceDetails/DeviceDetails.d.ts +4 -0
  74. package/lib/ui/DeviceDetails/DeviceDetails.js +38 -0
  75. package/lib/ui/DeviceDetails/DeviceDetails.js.map +1 -0
  76. package/lib/ui/DeviceDetails/DeviceImage.d.ts +4 -0
  77. package/lib/ui/DeviceDetails/DeviceImage.js +8 -0
  78. package/lib/ui/DeviceDetails/DeviceImage.js.map +1 -0
  79. package/lib/ui/DeviceDetails/ModelStatus.d.ts +4 -0
  80. package/lib/ui/DeviceDetails/ModelStatus.js +15 -0
  81. package/lib/ui/DeviceDetails/ModelStatus.js.map +1 -0
  82. package/lib/ui/DeviceDetails/OnlineStatus.d.ts +4 -0
  83. package/lib/ui/DeviceDetails/OnlineStatus.js +21 -0
  84. package/lib/ui/DeviceDetails/OnlineStatus.js.map +1 -0
  85. package/lib/ui/DeviceDetails/index.d.ts +5 -0
  86. package/lib/ui/DeviceDetails/index.js +6 -0
  87. package/lib/ui/DeviceDetails/index.js.map +1 -0
  88. package/lib/{components → ui}/DeviceManager/DeviceManager.d.ts +1 -1
  89. package/lib/{components → ui}/DeviceManager/DeviceManager.js +1 -1
  90. package/lib/ui/DeviceManager/DeviceManager.js.map +1 -0
  91. package/lib/ui/DeviceManager/index.d.ts +1 -0
  92. package/lib/ui/DeviceManager/index.js +2 -0
  93. package/lib/ui/DeviceManager/index.js.map +1 -0
  94. package/lib/ui/IconButton.d.ts +2 -0
  95. package/lib/ui/IconButton.js +5 -0
  96. package/lib/ui/IconButton.js.map +1 -0
  97. package/lib/ui/Table/TableBody.d.ts +4 -0
  98. package/lib/ui/Table/TableBody.js +5 -0
  99. package/lib/ui/Table/TableBody.js.map +1 -0
  100. package/lib/ui/Table/TableCell.d.ts +2 -0
  101. package/lib/ui/Table/TableCell.js +6 -0
  102. package/lib/ui/Table/TableCell.js.map +1 -0
  103. package/lib/ui/Table/TableHeader.d.ts +4 -0
  104. package/lib/ui/Table/TableHeader.js +5 -0
  105. package/lib/ui/Table/TableHeader.js.map +1 -0
  106. package/lib/ui/Table/TableRow.d.ts +2 -0
  107. package/lib/ui/Table/TableRow.js +5 -0
  108. package/lib/ui/Table/TableRow.js.map +1 -0
  109. package/lib/ui/Table/TableTitle.d.ts +4 -0
  110. package/lib/ui/Table/TableTitle.js +5 -0
  111. package/lib/ui/Table/TableTitle.js.map +1 -0
  112. package/lib/ui/Table/index.d.ts +5 -0
  113. package/lib/ui/Table/index.js +6 -0
  114. package/lib/ui/Table/index.js.map +1 -0
  115. package/lib/ui/TextField/SearchTextField.d.ts +2 -0
  116. package/lib/ui/TextField/SearchTextField.js +7 -0
  117. package/lib/ui/TextField/SearchTextField.js.map +1 -0
  118. package/lib/ui/TextField/TextField.d.ts +7 -0
  119. package/lib/ui/TextField/TextField.js +10 -0
  120. package/lib/ui/TextField/TextField.js.map +1 -0
  121. package/lib/ui/TextField/index.d.ts +2 -0
  122. package/lib/ui/TextField/index.js +3 -0
  123. package/lib/ui/TextField/index.js.map +1 -0
  124. package/lib/ui/index.js.map +1 -0
  125. package/lib/ui/layout/ContentHeader.d.ts +4 -0
  126. package/lib/ui/layout/ContentHeader.js +12 -0
  127. package/lib/ui/layout/ContentHeader.js.map +1 -0
  128. package/lib/ui/layout/DotDivider.d.ts +1 -0
  129. package/lib/ui/layout/DotDivider.js +5 -0
  130. package/lib/ui/layout/DotDivider.js.map +1 -0
  131. package/lib/ui/types.d.ts +3 -0
  132. package/lib/ui/types.js +2 -0
  133. package/lib/ui/types.js.map +1 -0
  134. package/lib/ui/typography/Caption.d.ts +4 -0
  135. package/lib/ui/typography/Caption.js +5 -0
  136. package/lib/ui/typography/Caption.js.map +1 -0
  137. package/lib/ui/typography/Title.d.ts +4 -0
  138. package/lib/ui/typography/Title.js +5 -0
  139. package/lib/ui/typography/Title.js.map +1 -0
  140. package/lib/use-toggle.d.ts +5 -0
  141. package/lib/use-toggle.js +14 -0
  142. package/lib/use-toggle.js.map +1 -0
  143. package/package.json +8 -1
  144. package/src/icons/access-code-key.svg +3 -0
  145. package/src/icons/arrow-back.svg +8 -0
  146. package/src/icons/battery-level-critical.svg +4 -0
  147. package/src/icons/battery-level-full.svg +4 -0
  148. package/src/icons/battery-level-high.svg +4 -0
  149. package/src/icons/battery-level-low.svg +4 -0
  150. package/src/icons/battery-level-wired.svg +8 -0
  151. package/src/icons/chevron-right.svg +8 -0
  152. package/src/icons/dots-ellipsis-more.svg +8 -0
  153. package/src/icons/online-status-account-offline.svg +8 -0
  154. package/src/icons/online-status-device-offline.svg +4 -0
  155. package/src/icons/online-status-online.svg +4 -0
  156. package/src/index.scss +1 -2
  157. package/src/lib/{provider.tsx → SeamProvider.tsx} +16 -1
  158. package/src/lib/icons/AccessCodeKey.tsx +19 -0
  159. package/src/lib/icons/ArrowBack.tsx +30 -0
  160. package/src/lib/icons/BatteryLevelCritical.tsx +27 -0
  161. package/src/lib/icons/BatteryLevelFull.tsx +20 -0
  162. package/src/lib/icons/BatteryLevelHigh.tsx +27 -0
  163. package/src/lib/icons/BatteryLevelLow.tsx +27 -0
  164. package/src/lib/icons/BatteryLevelWired.tsx +34 -0
  165. package/src/lib/icons/ChevronRight.tsx +32 -0
  166. package/src/lib/icons/DotsEllipsisMore.tsx +32 -0
  167. package/src/lib/icons/OnlineStatusAccountOffline.tsx +32 -0
  168. package/src/lib/icons/OnlineStatusDeviceOffline.tsx +23 -0
  169. package/src/lib/icons/OnlineStatusOnline.tsx +21 -0
  170. package/src/lib/icons/index.ts +12 -0
  171. package/src/lib/index.ts +3 -3
  172. package/src/lib/seam/devices/index.ts +1 -0
  173. package/src/lib/{hooks → seam/devices}/use-devices.ts +3 -3
  174. package/src/lib/seam/index.ts +2 -0
  175. package/src/lib/{hooks/use-seam.ts → seam/use-seam-client.ts} +3 -5
  176. package/src/lib/ui/AccessCodeTable/AccessCodeTable.tsx +57 -0
  177. package/src/lib/ui/AccessCodeTable/CodeDetails.tsx +51 -0
  178. package/src/lib/ui/AccessCodeTable/index.ts +2 -0
  179. package/src/lib/ui/DeviceDetails/BatteryStatus.tsx +81 -0
  180. package/src/lib/ui/DeviceDetails/DeviceDetails.tsx +99 -0
  181. package/src/lib/ui/DeviceDetails/DeviceImage.tsx +12 -0
  182. package/src/lib/ui/DeviceDetails/ModelStatus.tsx +27 -0
  183. package/src/lib/ui/DeviceDetails/OnlineStatus.tsx +44 -0
  184. package/src/lib/ui/DeviceDetails/index.ts +5 -0
  185. package/src/lib/{components → ui}/DeviceManager/DeviceManager.tsx +4 -1
  186. package/src/lib/ui/DeviceManager/index.ts +1 -0
  187. package/src/lib/ui/IconButton.tsx +5 -0
  188. package/src/lib/ui/Table/TableBody.tsx +5 -0
  189. package/src/lib/ui/Table/TableCell.tsx +9 -0
  190. package/src/lib/ui/Table/TableHeader.tsx +5 -0
  191. package/src/lib/ui/Table/TableRow.tsx +5 -0
  192. package/src/lib/ui/Table/TableTitle.tsx +5 -0
  193. package/src/lib/ui/Table/index.ts +5 -0
  194. package/src/lib/ui/TextField/SearchTextField.tsx +12 -0
  195. package/src/lib/ui/TextField/TextField.tsx +26 -0
  196. package/src/lib/ui/TextField/index.ts +2 -0
  197. package/src/lib/ui/layout/ContentHeader.tsx +21 -0
  198. package/src/lib/ui/layout/DotDivider.tsx +3 -0
  199. package/src/lib/ui/types.ts +4 -0
  200. package/src/lib/ui/typography/Caption.tsx +5 -0
  201. package/src/lib/ui/typography/Title.tsx +5 -0
  202. package/src/lib/use-toggle.ts +18 -0
  203. package/src/styles/access-code-table.scss +52 -0
  204. package/src/styles/buttons.scss +15 -0
  205. package/src/styles/content-header.scss +21 -0
  206. package/src/styles/device-details.scss +134 -0
  207. package/src/styles/inputs.scss +6 -0
  208. package/src/styles/main.scss +28 -0
  209. package/src/styles/tables.scss +36 -0
  210. package/src/styles/typography.scss +16 -0
  211. package/lib/components/DeviceManager/DeviceManager.js.map +0 -1
  212. package/lib/components/index.js.map +0 -1
  213. package/lib/hooks/index.d.ts +0 -1
  214. package/lib/hooks/index.js +0 -2
  215. package/lib/hooks/index.js.map +0 -1
  216. package/lib/hooks/use-devices.js.map +0 -1
  217. package/lib/hooks/use-seam.js.map +0 -1
  218. package/lib/provider.js.map +0 -1
  219. package/src/lib/hooks/index.ts +0 -1
  220. package/src/styles/_main.scss +0 -10
  221. /package/lib/{hooks → seam/devices}/use-devices.d.ts +0 -0
  222. /package/lib/{components → ui}/index.d.ts +0 -0
  223. /package/lib/{components → ui}/index.js +0 -0
  224. /package/src/lib/{components → ui}/index.ts +0 -0
@@ -0,0 +1,32 @@
1
+ import type { SVGProps } from 'react'
2
+ export const OnlineStatusAccountOfflineIcon = (
3
+ props: SVGProps<SVGSVGElement>
4
+ ): JSX.Element => (
5
+ <svg
6
+ xmlns='http://www.w3.org/2000/svg'
7
+ width={24}
8
+ height={25}
9
+ fill='none'
10
+ {...props}
11
+ >
12
+ <mask
13
+ id='online-status-account-offline_svg__a'
14
+ width={24}
15
+ height={25}
16
+ x={0}
17
+ y={0}
18
+ maskUnits='userSpaceOnUse'
19
+ style={{
20
+ maskType: 'alpha',
21
+ }}
22
+ >
23
+ <path fill='#D9D9D9' d='M0 .733h24v24H0z' />
24
+ </mask>
25
+ <g mask='url(#online-status-account-offline_svg__a)'>
26
+ <path
27
+ fill='#E36857'
28
+ d='m19.8 23.333-2.65-2.6H6.5c-1.533 0-2.833-.534-3.9-1.6-1.067-1.067-1.6-2.367-1.6-3.9 0-1.284.396-2.425 1.188-3.425A5.286 5.286 0 0 1 5.25 9.883c.05-.134.1-.263.15-.388.05-.125.1-.262.15-.412L1.4 4.933l1.4-1.4 18.4 18.4-1.4 1.4Zm-13.3-4.6h8.65l-8.05-8.05a6.626 6.626 0 0 0-.075.525 5.28 5.28 0 0 0-.025.525h-.5c-.967 0-1.792.341-2.475 1.025A3.372 3.372 0 0 0 3 15.233c0 .966.342 1.791 1.025 2.475A3.372 3.372 0 0 0 6.5 18.733Zm15.1.75-1.45-1.4c.283-.234.496-.505.638-.813.141-.308.212-.654.212-1.037 0-.7-.242-1.292-.725-1.775-.483-.484-1.075-.725-1.775-.725H17v-2c0-1.384-.488-2.563-1.463-3.538-.975-.975-2.154-1.462-3.537-1.462-.45 0-.883.054-1.3.162-.417.109-.817.28-1.2.513l-1.45-1.45a7.028 7.028 0 0 1 1.862-.913A6.878 6.878 0 0 1 12 4.733c1.95 0 3.604.679 4.962 2.037C18.322 8.13 19 9.783 19 11.733c1.15.133 2.104.629 2.863 1.487A4.407 4.407 0 0 1 23 16.233a4.384 4.384 0 0 1-1.4 3.25Z'
29
+ />
30
+ </g>
31
+ </svg>
32
+ )
@@ -0,0 +1,23 @@
1
+ import type { SVGProps } from 'react'
2
+ export const OnlineStatusDeviceOfflineIcon = (
3
+ props: SVGProps<SVGSVGElement>
4
+ ): JSX.Element => (
5
+ <svg
6
+ xmlns='http://www.w3.org/2000/svg'
7
+ width={24}
8
+ height={25}
9
+ fill='none'
10
+ {...props}
11
+ >
12
+ <path
13
+ fill='#E36857'
14
+ d='m1.411 4.931 1.373-1.373 18.432 18.431-1.373 1.373z'
15
+ />
16
+ <path
17
+ fill='#E36857'
18
+ fillRule='evenodd'
19
+ d='M12 23.362c-1.95 0-3.604-.679-4.963-2.037C5.68 19.967 5 18.312 5 16.362v-8c0-.799.114-1.548.342-2.248L7.028 7.8c-.019.184-.028.371-.028.562v8c0 1.384.487 2.563 1.463 3.538.975.975 2.154 1.462 3.537 1.462s2.563-.487 3.537-1.462c.664-.664 1.102-1.423 1.314-2.276l1.58 1.58a6.913 6.913 0 0 1-1.469 2.12c-1.358 1.36-3.012 2.038-4.962 2.038Zm6.975-6.36c.017-.21.025-.423.025-.64v-8c0-1.95-.68-3.604-2.038-4.962C15.604 2.04 13.95 1.362 12 1.362c-1.95 0-3.604.68-4.963 2.038a7.413 7.413 0 0 0-.767.897l1.452 1.451c.204-.325.45-.633.74-.923.976-.975 2.155-1.463 3.538-1.463s2.563.488 3.537 1.463C16.512 5.8 17 6.979 17 8.362v6.664l1.975 1.975ZM15 12.361c.283 0 .52-.095.713-.287a.968.968 0 0 0 .287-.713.968.968 0 0 0-.287-.712.968.968 0 0 0-.713-.288.968.968 0 0 0-.713.288.968.968 0 0 0-.287.712c0 .284.096.521.287.713.192.192.43.287.713.287Zm-6 3c.283 0 .52-.095.713-.287a.968.968 0 0 0 .287-.713.968.968 0 0 0-.287-.712.967.967 0 0 0-.713-.288.967.967 0 0 0-.713.288.968.968 0 0 0-.287.712c0 .284.096.521.287.713.192.192.43.287.713.287Zm0 3c.283 0 .52-.095.713-.287a.968.968 0 0 0 .287-.713.968.968 0 0 0-.287-.712.967.967 0 0 0-.713-.288.967.967 0 0 0-.713.288.968.968 0 0 0-.287.712c0 .284.096.521.287.713.192.192.43.287.713.287Zm3 0c.283 0 .52-.095.713-.287a.968.968 0 0 0 .287-.713.968.968 0 0 0-.287-.712.968.968 0 0 0-.713-.288.968.968 0 0 0-.713.288.968.968 0 0 0-.287.712c0 .284.096.521.287.713.192.192.43.287.713.287Zm3.713-9.287a.968.968 0 0 1-.713.287.968.968 0 0 1-.713-.287.967.967 0 0 1-.287-.713c0-.283.096-.52.287-.712A.968.968 0 0 1 15 7.362c.283 0 .52.096.713.288.191.191.287.429.287.712 0 .284-.096.521-.287.713Zm-3.749.287c.283 0 .52-.096.713-.287a.967.967 0 0 0 .287-.713.967.967 0 0 0-.287-.712.968.968 0 0 0-.713-.288.968.968 0 0 0-.712.288.967.967 0 0 0-.288.712c0 .284.096.521.288.713.191.191.429.287.712.287Z'
20
+ clipRule='evenodd'
21
+ />
22
+ </svg>
23
+ )
@@ -0,0 +1,21 @@
1
+ import type { SVGProps } from 'react'
2
+ export const OnlineStatusOnlineIcon = (
3
+ props: SVGProps<SVGSVGElement>
4
+ ): JSX.Element => (
5
+ <svg
6
+ xmlns='http://www.w3.org/2000/svg'
7
+ width={24}
8
+ height={24}
9
+ fill='none'
10
+ {...props}
11
+ >
12
+ <path
13
+ fill='#9DA1A9'
14
+ d='M6.5 20c-1.517 0-2.813-.525-3.888-1.575C1.537 17.375 1 16.092 1 14.575c0-1.3.392-2.458 1.175-3.475S3.983 9.433 5.25 9.15c.417-1.533 1.25-2.775 2.5-3.725C9 4.475 10.417 4 12 4c1.95 0 3.604.68 4.962 2.037C18.322 7.396 19 9.05 19 11c1.15.133 2.104.63 2.863 1.488A4.407 4.407 0 0 1 23 15.5c0 1.25-.438 2.313-1.313 3.188S19.75 20 18.5 20h-12Zm0-2h12c.7 0 1.292-.242 1.775-.725.483-.483.725-1.075.725-1.775s-.242-1.292-.725-1.775C19.792 13.242 19.2 13 18.5 13H17v-2c0-1.383-.488-2.563-1.463-3.537C14.563 6.487 13.383 6 12 6s-2.563.487-3.537 1.463C7.488 8.437 7 9.617 7 11h-.5c-.967 0-1.792.342-2.475 1.025A3.372 3.372 0 0 0 3 14.5c0 .967.342 1.792 1.025 2.475A3.372 3.372 0 0 0 6.5 18Z'
15
+ />
16
+ <path
17
+ fill='#27AE60'
18
+ d='M16 11.35 10.35 17 6.8 13.45l1.425-1.425 2.1 2.1L14.55 9.9 16 11.35Z'
19
+ />
20
+ </svg>
21
+ )
@@ -1 +1,13 @@
1
+ export { AccessCodeKeyIcon } from './AccessCodeKey.js'
2
+ export { ArrowBackIcon } from './ArrowBack.js'
3
+ export { BatteryLevelCriticalIcon } from './BatteryLevelCritical.js'
4
+ export { BatteryLevelFullIcon } from './BatteryLevelFull.js'
5
+ export { BatteryLevelHighIcon } from './BatteryLevelHigh.js'
6
+ export { BatteryLevelLowIcon } from './BatteryLevelLow.js'
7
+ export { BatteryLevelWiredIcon } from './BatteryLevelWired.js'
8
+ export { ChevronRightIcon } from './ChevronRight.js'
9
+ export { DotsEllipsisMoreIcon } from './DotsEllipsisMore.js'
10
+ export { OnlineStatusAccountOfflineIcon } from './OnlineStatusAccountOffline.js'
11
+ export { OnlineStatusDeviceOfflineIcon } from './OnlineStatusDeviceOffline.js'
12
+ export { OnlineStatusOnlineIcon } from './OnlineStatusOnline.js'
1
13
  export { SeamIcon } from './Seam.js'
package/src/lib/index.ts CHANGED
@@ -1,3 +1,3 @@
1
- export * from './components/index.js'
2
- export * from './hooks/index.js'
3
- export * from './provider.js'
1
+ export * from './seam/index.js'
2
+ export * from './SeamProvider.js'
3
+ export * from './ui/index.js'
@@ -0,0 +1 @@
1
+ export * from './use-devices.js'
@@ -5,7 +5,7 @@ import type {
5
5
  SeamError,
6
6
  } from 'seamapi'
7
7
 
8
- import { useSeam } from './use-seam.js'
8
+ import { useSeamClient } from 'lib/seam/use-seam-client.js'
9
9
 
10
10
  export type UseDevicesParams = DevicesListRequest
11
11
  export type UseDevicesData = DevicesListResponse['devices']
@@ -15,11 +15,11 @@ type Result = UseQueryResult<UseDevicesData, SeamError>
15
15
  type UseDevicesResult = Omit<Result, 'data'> & { devices: Result['data'] }
16
16
 
17
17
  export function useDevices(params: DevicesListRequest): UseDevicesResult {
18
- const { client } = useSeam()
18
+ const { client } = useSeamClient()
19
19
  const { data, ...rest } = useQuery<DevicesListResponse['devices'], SeamError>(
20
20
  {
21
21
  enabled: client != null,
22
- queryKey: ['list', 'devices', params],
22
+ queryKey: ['devices', 'list', params],
23
23
  queryFn: async () => {
24
24
  if (client == null) return []
25
25
  return await client?.devices.list(params)
@@ -0,0 +1,2 @@
1
+ export * from './devices/index.js'
2
+ export * from './use-seam-client.js'
@@ -1,18 +1,16 @@
1
1
  import { useQuery } from '@tanstack/react-query'
2
- import { useContext } from 'react'
3
2
  import { type ClientSession, Seam } from 'seamapi'
4
3
  import { v4 as uuidv4 } from 'uuid'
5
4
 
6
- import { seamContext } from 'lib/provider.js'
5
+ import { useSeamContext } from 'lib/SeamProvider.js'
7
6
 
8
- export function useSeam(): {
7
+ export function useSeamClient(): {
9
8
  client: Seam | null
10
9
  isLoading: boolean
11
10
  isError: boolean
12
11
  error: unknown
13
12
  } {
14
- const { client, clientOptions, publishableKey, ...context } =
15
- useContext(seamContext)
13
+ const { client, clientOptions, publishableKey, ...context } = useSeamContext()
16
14
  const [clientSession, setClientSession] = useClientSession()
17
15
  const userIdentifierKey = useUserIdentifierKey(context.userIdentifierKey)
18
16
 
@@ -0,0 +1,57 @@
1
+ import type { AccessCode } from 'seamapi'
2
+
3
+ import {
4
+ TableBody,
5
+ TableCell,
6
+ TableHeader,
7
+ TableRow,
8
+ TableTitle,
9
+ } from 'lib/ui/Table/index.js'
10
+
11
+ import { AccessCodeKeyIcon } from 'lib/icons/AccessCodeKey.js'
12
+ import { CodeDetails } from 'lib/ui/AccessCodeTable/CodeDetails.js'
13
+ import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
14
+ import { Caption } from 'lib/ui/typography/Caption.js'
15
+ import { Title } from 'lib/ui/typography/Title.js'
16
+
17
+ export function AccessCodeTable(props: {
18
+ accessCodes: AccessCode[]
19
+ onClickBack?: () => void
20
+ }) {
21
+ const { accessCodes, onClickBack } = props
22
+
23
+ return (
24
+ <div className='seam-access-code-table'>
25
+ <ContentHeader onClickBack={onClickBack} />
26
+ <TableHeader>
27
+ <TableTitle>
28
+ {t.accessCodes} <Caption>({accessCodes.length})</Caption>
29
+ </TableTitle>
30
+ </TableHeader>
31
+ <TableBody>
32
+ {accessCodes.map((code) => (
33
+ <TableRow key={code.access_code_id}>
34
+ <TableCell className='seam-icon-cell'>
35
+ <div>
36
+ <AccessCodeKeyIcon />
37
+ </div>
38
+ </TableCell>
39
+ <TableCell className='seam-name-cell'>
40
+ <Title>{code.name}</Title>
41
+ <CodeDetails accessCode={code} />
42
+ </TableCell>
43
+ <TableCell className='seam-action-cell'>
44
+ {/* <IconButton>
45
+ <DotsEllipsisMoreIcon />
46
+ </IconButton> */}
47
+ </TableCell>
48
+ </TableRow>
49
+ ))}
50
+ </TableBody>
51
+ </div>
52
+ )
53
+ }
54
+
55
+ const t = {
56
+ accessCodes: 'Access Codes',
57
+ }
@@ -0,0 +1,51 @@
1
+ import dayjs from 'dayjs'
2
+ import type { AccessCode } from 'seamapi'
3
+
4
+ import { DotDivider } from 'lib/ui/layout/DotDivider.js'
5
+
6
+ export function CodeDetails(props: { accessCode: AccessCode }) {
7
+ const { accessCode } = props
8
+
9
+ return (
10
+ <div className='seam-access-code-details'>
11
+ Unit 110
12
+ <DotDivider />
13
+ <Duration accessCode={accessCode} />
14
+ <DotDivider />
15
+ {t.code}: {accessCode.code}
16
+ </div>
17
+ )
18
+ }
19
+
20
+ function Duration(props: { accessCode: AccessCode }) {
21
+ const { accessCode } = props
22
+ if (accessCode.type === 'ongoing') {
23
+ return <span>{t.ends}: Never</span>
24
+ }
25
+
26
+ const hasStarted = new Date(accessCode.starts_at).valueOf() < Date.now()
27
+ if (hasStarted) {
28
+ return (
29
+ <span>
30
+ {t.ends}: {formatDate(accessCode.ends_at)}{' '}
31
+ </span>
32
+ )
33
+ }
34
+
35
+ // is in future
36
+ return (
37
+ <span>
38
+ {t.starts}: {formatDate(accessCode.starts_at)}
39
+ </span>
40
+ )
41
+ }
42
+
43
+ function formatDate(date: string) {
44
+ return dayjs(date).format('MMM D')
45
+ }
46
+
47
+ const t = {
48
+ code: 'Code',
49
+ starts: 'Starts',
50
+ ends: 'Ends',
51
+ }
@@ -0,0 +1,2 @@
1
+ export * from './AccessCodeTable.js'
2
+ export * from './CodeDetails.js'
@@ -0,0 +1,81 @@
1
+ import type { LockDevice } from 'seamapi'
2
+
3
+ import { BatteryLevelCriticalIcon } from 'lib/icons/BatteryLevelCritical.js'
4
+ import { BatteryLevelFullIcon } from 'lib/icons/BatteryLevelFull.js'
5
+ import { BatteryLevelHighIcon } from 'lib/icons/BatteryLevelHigh.js'
6
+ import { BatteryLevelLowIcon } from 'lib/icons/BatteryLevelLow.js'
7
+
8
+ /**
9
+ * Thresholds to determine the battery status
10
+ */
11
+ const BATTERY_LEVEL = {
12
+ FULL: 0.85,
13
+ HIGH: 0.6,
14
+ LOW: 0.3,
15
+ }
16
+ export function BatteryStatus(props: { device: LockDevice }) {
17
+ const {
18
+ device: {
19
+ properties: { battery_level: batteryLevel },
20
+ },
21
+ } = props
22
+
23
+ if (batteryLevel === undefined) {
24
+ return null
25
+ }
26
+
27
+ return (
28
+ <>
29
+ <span className='seam-label'>{t.power}:</span>{' '}
30
+ <div className='seam-battery-status'>
31
+ <Status batteryLevel={batteryLevel} />
32
+ </div>
33
+ </>
34
+ )
35
+ }
36
+
37
+ function Status(props: { batteryLevel: number }) {
38
+ const { batteryLevel } = props
39
+
40
+ if (batteryLevel > BATTERY_LEVEL.FULL) {
41
+ return (
42
+ <>
43
+ <BatteryLevelFullIcon />
44
+ <span className='seam-status-text'>{t.full}</span>
45
+ </>
46
+ )
47
+ }
48
+
49
+ if (batteryLevel > BATTERY_LEVEL.HIGH) {
50
+ return (
51
+ <>
52
+ <BatteryLevelHighIcon />
53
+ <span className='seam-status-text'>{t.high}</span>
54
+ </>
55
+ )
56
+ }
57
+
58
+ if (batteryLevel > BATTERY_LEVEL.LOW) {
59
+ return (
60
+ <>
61
+ <BatteryLevelLowIcon />
62
+ <span className='seam-status-text'>{t.low}</span>
63
+ </>
64
+ )
65
+ }
66
+
67
+ return (
68
+ <>
69
+ <BatteryLevelCriticalIcon />
70
+ <span className='seam-text-danger'>{t.critical}</span>
71
+ </>
72
+ )
73
+ }
74
+
75
+ const t = {
76
+ power: 'Power',
77
+ full: 'Good',
78
+ high: 'Good',
79
+ low: 'Low',
80
+ critical: 'Low!',
81
+ }
@@ -0,0 +1,99 @@
1
+ import { type AccessCode, type LockDevice } from 'seamapi'
2
+
3
+ import { ChevronRightIcon } from 'lib/icons/ChevronRight.js'
4
+ import { AccessCodeTable } from 'lib/ui/AccessCodeTable/AccessCodeTable.js'
5
+ import { BatteryStatus } from 'lib/ui/DeviceDetails/BatteryStatus.js'
6
+ import { DeviceImage } from 'lib/ui/DeviceDetails/DeviceImage.js'
7
+ import { ModelStatus } from 'lib/ui/DeviceDetails/ModelStatus.js'
8
+ import { OnlineStatus } from 'lib/ui/DeviceDetails/OnlineStatus.js'
9
+ import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
10
+ import useToggle from 'lib/use-toggle.js'
11
+
12
+ export function DeviceDetails(props: { device: LockDevice }) {
13
+ const { device } = props
14
+
15
+ const lockStatus = device.properties.locked ? t.locked : t.unlocked
16
+
17
+ const accessCodeLength =
18
+ device.properties?.schlage_metadata?.access_code_length ?? null
19
+
20
+ // TODO : Fetch access codes
21
+ const accessCodes: AccessCode[] = []
22
+
23
+ const [showingAccessCodes, toggleAccessCodes] = useToggle()
24
+
25
+ if (showingAccessCodes) {
26
+ return (
27
+ <AccessCodeTable
28
+ accessCodes={accessCodes}
29
+ onClickBack={toggleAccessCodes}
30
+ />
31
+ )
32
+ }
33
+
34
+ return (
35
+ <div className='seam-device-details'>
36
+ <ContentHeader title='Device' />
37
+ <div className='seam-body'>
38
+ <div className='seam-summary'>
39
+ <div className='seam-content'>
40
+ <div className='seam-image'>
41
+ <DeviceImage device={device} />
42
+ </div>
43
+
44
+ <div className='seam-info'>
45
+ <h4 className='seam-device-name'>{device.properties.name}</h4>
46
+ <div className='seam-properties'>
47
+ <OnlineStatus device={device} />
48
+ <BatteryStatus device={device} />
49
+ <ModelStatus device={device} />
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </div>
54
+ <div className='seam-box'>
55
+ <div
56
+ className='seam-content seam-access-codes'
57
+ onClick={toggleAccessCodes}
58
+ >
59
+ <span className='seam-value'>49 {t.accessCodes}</span>
60
+ <ChevronRightIcon />
61
+ </div>
62
+ </div>
63
+
64
+ <div className='seam-box'>
65
+ <div className='seam-content'>
66
+ <span className='seam-label'>{t.lockStatus}</span>
67
+ <span className='seam-value'>{lockStatus}</span>
68
+ </div>
69
+ <AccessCodeLength accessCodeLength={accessCodeLength} />
70
+ </div>
71
+ </div>
72
+ </div>
73
+ )
74
+ }
75
+
76
+ function AccessCodeLength(props: { accessCodeLength: number | null }) {
77
+ const { accessCodeLength } = props
78
+ if (accessCodeLength === null) {
79
+ return null
80
+ }
81
+
82
+ return (
83
+ <div className='seam-content seam-access-code-length'>
84
+ <span className='seam-label'>{t.codeLength}</span>
85
+ <span className='seam-value'>
86
+ {accessCodeLength} {t.digits}
87
+ </span>
88
+ </div>
89
+ )
90
+ }
91
+
92
+ const t = {
93
+ locked: 'Locked',
94
+ unlocked: 'Unlocked',
95
+ accessCodes: 'access codes',
96
+ codeLength: 'Code length',
97
+ digits: 'digits',
98
+ lockStatus: 'lockStatus',
99
+ }
@@ -0,0 +1,12 @@
1
+ import type { LockDevice } from 'seamapi'
2
+
3
+ const FALLBACK_IMAGE_URL =
4
+ 'https://connect.getseam.com/assets/images/devices/unknown-lock.png'
5
+
6
+ export function DeviceImage(props: { device: LockDevice }) {
7
+ const { device } = props
8
+
9
+ const url = device.properties.image_url ?? FALLBACK_IMAGE_URL
10
+
11
+ return <img src={url} alt={device.properties.name} />
12
+ }
@@ -0,0 +1,27 @@
1
+ import type { LockDevice } from 'seamapi'
2
+
3
+ export function ModelStatus(props: { device: LockDevice }) {
4
+ const {
5
+ device: { properties },
6
+ } = props
7
+
8
+ const model =
9
+ properties?.august_metadata?.model ??
10
+ properties?.schlage_metadata?.model ??
11
+ null
12
+
13
+ if (model === null) {
14
+ return null
15
+ }
16
+
17
+ return (
18
+ <>
19
+ <span className='seam-label'>{t.model}:</span>{' '}
20
+ <div className='seam-device-model'>{model}</div>
21
+ </>
22
+ )
23
+ }
24
+
25
+ const t = {
26
+ model: 'Model',
27
+ }
@@ -0,0 +1,44 @@
1
+ import type { LockDevice } from 'seamapi'
2
+
3
+ import { OnlineStatusDeviceOfflineIcon } from 'lib/icons/OnlineStatusDeviceOffline.js'
4
+ import { OnlineStatusOnlineIcon } from 'lib/icons/OnlineStatusOnline.js'
5
+
6
+ export function OnlineStatus(props: { device: LockDevice }) {
7
+ const { device } = props
8
+ return (
9
+ <>
10
+ <span className='seam-label'>{t.status}:</span>{' '}
11
+ <div className='seam-online-status'>
12
+ <Status isOnline={device.properties.online} />
13
+ </div>
14
+ </>
15
+ )
16
+ }
17
+
18
+ function Status(props: { isOnline: boolean }) {
19
+ const { isOnline } = props
20
+
21
+ if (isOnline) {
22
+ return (
23
+ <>
24
+ <OnlineStatusOnlineIcon />
25
+ <span className='seam-status-text'>{t.online}</span>
26
+ </>
27
+ )
28
+ }
29
+
30
+ // TODO: Check for Account Offline status
31
+
32
+ return (
33
+ <>
34
+ <OnlineStatusDeviceOfflineIcon />
35
+ <span className='seam-text-danger'>{t.deviceOffline}</span>
36
+ </>
37
+ )
38
+ }
39
+
40
+ const t = {
41
+ status: 'Status',
42
+ online: 'Online',
43
+ deviceOffline: 'Device Offline',
44
+ }
@@ -0,0 +1,5 @@
1
+ export * from './BatteryStatus.js'
2
+ export * from './DeviceDetails.js'
3
+ export * from './DeviceImage.js'
4
+ export * from './ModelStatus.js'
5
+ export * from './OnlineStatus.js'
@@ -1,6 +1,9 @@
1
1
  import type { CommonDeviceProperties, Device } from 'seamapi'
2
2
 
3
- import { useDevices, type UseDevicesParams } from 'lib/hooks/use-devices.js'
3
+ import {
4
+ useDevices,
5
+ type UseDevicesParams,
6
+ } from 'lib/seam/devices/use-devices.js'
4
7
 
5
8
  export type DeviceManagerProps = UseDevicesParams
6
9
 
@@ -0,0 +1 @@
1
+ export * from './DeviceManager.js'
@@ -0,0 +1,5 @@
1
+ import type { ButtonProps } from 'lib/ui/types.js'
2
+
3
+ export function IconButton(props: ButtonProps) {
4
+ return <button {...props} className='seam-button seam-icon-button' />
5
+ }
@@ -0,0 +1,5 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ export function TableBody(props: { children: ReactNode }) {
4
+ return <div className='seam-table-body'>{props.children}</div>
5
+ }
@@ -0,0 +1,9 @@
1
+ import classNames from 'classnames'
2
+
3
+ import type { DivProps } from 'lib/ui/types.js'
4
+
5
+ export function TableCell({ className, ...otherProps }: DivProps) {
6
+ return (
7
+ <div className={classNames('seam-table-cell', className)} {...otherProps} />
8
+ )
9
+ }
@@ -0,0 +1,5 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ export function TableHeader(props: { children: ReactNode }) {
4
+ return <div className='seam-table-header'>{props.children}</div>
5
+ }
@@ -0,0 +1,5 @@
1
+ import type { DivProps } from 'lib/ui/types.js'
2
+
3
+ export function TableRow(props: DivProps) {
4
+ return <div className='seam-table-row'>{props.children}</div>
5
+ }
@@ -0,0 +1,5 @@
1
+ import type { ReactNode } from 'react'
2
+
3
+ export function TableTitle(props: { children: ReactNode }) {
4
+ return <h5 className='seam-table-title'>{props.children}</h5>
5
+ }
@@ -0,0 +1,5 @@
1
+ export * from './TableBody.js'
2
+ export * from './TableCell.js'
3
+ export * from './TableHeader.js'
4
+ export * from './TableRow.js'
5
+ export * from './TableTitle.js'
@@ -0,0 +1,12 @@
1
+ import classNames from 'classnames'
2
+
3
+ import { TextField, type TextFieldProps } from 'lib/ui/TextField/index.js'
4
+
5
+ export function SearchTextField({ className, ...otherProps }: TextFieldProps) {
6
+ return (
7
+ <TextField
8
+ {...otherProps}
9
+ className={classNames(className, 'seam-search-text-field')}
10
+ />
11
+ )
12
+ }
@@ -0,0 +1,26 @@
1
+ import classNames from 'classnames'
2
+ import type { ChangeEvent, InputHTMLAttributes } from 'react'
3
+
4
+ export type TextFieldProps = {
5
+ value?: string
6
+ onChange: (value: string) => void
7
+ } & Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'>
8
+
9
+ export function TextField(props: TextFieldProps) {
10
+ const { value, onChange, className, ...inputProps } = props
11
+ return (
12
+ <input
13
+ className={classNames('seam-text-field', className)}
14
+ value={value}
15
+ onChange={handleString(onChange)}
16
+ type='text'
17
+ {...inputProps}
18
+ />
19
+ )
20
+ }
21
+
22
+ export const handleString =
23
+ (setter: (v: string) => void) =>
24
+ (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>): void => {
25
+ setter(e.currentTarget.value)
26
+ }
@@ -0,0 +1,2 @@
1
+ export * from './SearchTextField.js'
2
+ export * from './TextField.js'