@flamingo-stack/openframe-frontend-core 0.0.710 → 0.0.712

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 (534) hide show
  1. package/dist/chunk-2NASBO7O.js +1137 -0
  2. package/dist/{chunk-RQRX4YC3.cjs → chunk-2RKFMUNW.cjs} +46 -46
  3. package/dist/chunk-2Y7QZAB2.cjs +158 -0
  4. package/dist/chunk-34I6XI3N.js +136 -0
  5. package/dist/chunk-3K5ZLZE7.js +292 -0
  6. package/dist/chunk-3LU4UFPS.cjs +14 -0
  7. package/dist/{chunk-YBUT4AMG.cjs → chunk-3RKBJT6K.cjs} +8 -6
  8. package/dist/{chunk-LNW45N2C.js → chunk-3SEEGNRE.js} +35 -27
  9. package/dist/{chunk-L6Y6OOKG.cjs → chunk-3UAJLO5U.cjs} +41 -39
  10. package/dist/chunk-4HJRHEXD.cjs +1612 -0
  11. package/dist/{chunk-JPG7OHEG.js → chunk-4QFWGLZO.js} +1 -1
  12. package/dist/chunk-4R2L3DSA.js +14 -0
  13. package/dist/{chunk-36BCTE7D.js → chunk-4UYKNOZG.js} +12 -10
  14. package/dist/{chunk-DA5UDTLG.js → chunk-5SDELRH3.js} +5 -5
  15. package/dist/{chunk-CZSZSDD4.js → chunk-5Y72YQEK.js} +22 -113
  16. package/dist/{chunk-KUC673HM.js → chunk-6T3BTD6Q.js} +204 -982
  17. package/dist/{chunk-F57ECE2I.js → chunk-6YPTUHM7.js} +4 -4
  18. package/dist/{chunk-TDYIREDJ.js → chunk-7HNYYNKE.js} +28 -22
  19. package/dist/{chunk-2G7UYK35.cjs → chunk-7NSU5EQD.cjs} +57 -148
  20. package/dist/chunk-AAYNCJMW.cjs +48 -0
  21. package/dist/{chunk-FXJ3WWUB.js → chunk-ADBE7QF3.js} +5 -252
  22. package/dist/chunk-AECTRMGQ.cjs +334 -0
  23. package/dist/chunk-AGVXKD4K.js +334 -0
  24. package/dist/chunk-AL2GUHAJ.cjs +18 -0
  25. package/dist/{chunk-WMX26HB5.js → chunk-APJZBDQN.js} +12 -12
  26. package/dist/chunk-AUMKE74M.cjs +16 -0
  27. package/dist/chunk-B4NCVYEQ.cjs +292 -0
  28. package/dist/{chunk-2RNB5DTN.cjs → chunk-BXSRTBLU.cjs} +82 -54
  29. package/dist/chunk-CMGFZHCN.js +233 -0
  30. package/dist/chunk-CMZ3QTFQ.js +1207 -0
  31. package/dist/chunk-CPA2CKRZ.cjs +125 -0
  32. package/dist/{chunk-B73373AG.cjs → chunk-CSCJU6YC.cjs} +35 -33
  33. package/dist/chunk-CYUUHFXL.js +41 -0
  34. package/dist/chunk-DC4RTYWK.cjs +1122 -0
  35. package/dist/{chunk-6YKAT7NV.js → chunk-DDWFCWOE.js} +5 -7
  36. package/dist/{chunk-F5FF4DME.js → chunk-EFNKS5W4.js} +322 -428
  37. package/dist/{chunk-2KXTOP6G.cjs → chunk-EOKSKJSS.cjs} +25 -83
  38. package/dist/{chunk-6NTPY5QA.cjs → chunk-ETYLOZOB.cjs} +978 -2413
  39. package/dist/chunk-F5BPGWGT.cjs +931 -0
  40. package/dist/{chunk-4L6XCMOU.js → chunk-FCAVAEHF.js} +8277 -9990
  41. package/dist/chunk-FFT56TYB.cjs +401 -0
  42. package/dist/chunk-FYEJTF5Y.js +125 -0
  43. package/dist/chunk-G3GRYDMS.js +16 -0
  44. package/dist/{chunk-MR3A4MZV.js → chunk-G3OMVCID.js} +13 -7
  45. package/dist/chunk-G6OHIX5C.cjs +100 -0
  46. package/dist/{chunk-UDFRUKLC.cjs → chunk-GEDY7HQI.cjs} +2 -2
  47. package/dist/chunk-GQ7JJUIT.cjs +1207 -0
  48. package/dist/chunk-H3PKYE4N.js +18 -0
  49. package/dist/{chunk-CNWOMQQJ.js → chunk-H5R7U2D2.js} +206 -5
  50. package/dist/{chunk-SEXWHIMS.cjs → chunk-HETQETPV.cjs} +9648 -9680
  51. package/dist/{chunk-Y2GSOUCS.cjs → chunk-HWVUR735.cjs} +2 -2
  52. package/dist/chunk-II4QMH26.cjs +35 -0
  53. package/dist/chunk-ILNN6QRW.js +1612 -0
  54. package/dist/chunk-IYVFSLWJ.js +931 -0
  55. package/dist/{chunk-3AHTOSXJ.cjs → chunk-JGCFRTND.cjs} +23 -17
  56. package/dist/chunk-JHQ334WS.js +655 -0
  57. package/dist/{chunk-WCVZCGK5.cjs → chunk-JO5TLJPM.cjs} +129 -907
  58. package/dist/{chunk-JRU2CXLB.cjs → chunk-JVCAK4W3.cjs} +210 -9
  59. package/dist/chunk-KBJJQFYU.js +1122 -0
  60. package/dist/chunk-KEKCQENI.js +48 -0
  61. package/dist/chunk-KHXZFLIN.cjs +41 -0
  62. package/dist/chunk-KT3U3ZRP.cjs +1137 -0
  63. package/dist/chunk-L2VUINHN.js +35 -0
  64. package/dist/{chunk-P42V6N34.cjs → chunk-L6ZQGWCX.cjs} +4521 -6234
  65. package/dist/{chunk-PLYEKV3N.cjs → chunk-MA4Q5RBP.cjs} +6 -6
  66. package/dist/{chunk-SS5MBHDP.js → chunk-N67XG5GY.js} +10 -8
  67. package/dist/chunk-NPAQSMRY.js +2087 -0
  68. package/dist/{chunk-I3ST4PLM.js → chunk-NQWJAOHO.js} +6 -4
  69. package/dist/{chunk-QAOFMK2A.cjs → chunk-OBZJICEA.cjs} +8 -8
  70. package/dist/{chunk-6IW7TWPV.js → chunk-OPYODNV2.js} +3 -3
  71. package/dist/chunk-P3JMAMHP.js +401 -0
  72. package/dist/chunk-PPXR22YC.cjs +2087 -0
  73. package/dist/chunk-PSVSEN4J.cjs +655 -0
  74. package/dist/{chunk-4UM2ETLM.js → chunk-RBYVFPER.js} +74 -46
  75. package/dist/{chunk-PO33GZVY.js → chunk-ROBQ5TR7.js} +10549 -10581
  76. package/dist/{chunk-ZCLBYT2V.cjs → chunk-T3CLXR43.cjs} +114 -220
  77. package/dist/{chunk-FI6GMDO7.js → chunk-TTVOLEUS.js} +3605 -5040
  78. package/dist/{chunk-LM7TXMLU.cjs → chunk-ULWVKHSI.cjs} +8 -255
  79. package/dist/{chunk-6I4ZAFO2.cjs → chunk-UT3ODMBU.cjs} +15 -15
  80. package/dist/chunk-WANCBTUE.js +71 -0
  81. package/dist/{chunk-BIZNSF3U.cjs → chunk-WBNAEYTQ.cjs} +2 -51
  82. package/dist/chunk-WFPCCBOM.cjs +71 -0
  83. package/dist/chunk-WI6FHKD7.js +158 -0
  84. package/dist/chunk-WMNCVLES.js +100 -0
  85. package/dist/{chunk-UT4YHQZW.js → chunk-WSDT7LYL.js} +0 -49
  86. package/dist/chunk-WVOTC7HW.cjs +136 -0
  87. package/dist/{chunk-AOWDNSTM.cjs → chunk-WWJG4GVG.cjs} +93 -87
  88. package/dist/chunk-XXBLN4BP.cjs +233 -0
  89. package/dist/{chunk-4IBPRIQH.js → chunk-YBQQNDC7.js} +1 -1
  90. package/dist/{chunk-LFFB6EMB.js → chunk-YBS5QGON.js} +70 -128
  91. package/dist/{chunk-NSGXARGJ.cjs → chunk-Z5SWJW5Q.cjs} +125 -117
  92. package/dist/{chunk-OJLR5MEO.cjs → chunk-ZX7SCPLO.cjs} +6 -8
  93. package/dist/cloud-tenants-KZUZGD4A.cjs +117 -0
  94. package/dist/cloud-tenants-OGLVVQ7X.js +117 -0
  95. package/dist/components/case-studies/index.cjs +45 -29
  96. package/dist/components/case-studies/index.js +32 -16
  97. package/dist/components/chat/ask-prompts.d.ts +64 -0
  98. package/dist/components/chat/ask-prompts.d.ts.map +1 -0
  99. package/dist/components/chat/entity-cards/case-study-card.d.ts +6 -3
  100. package/dist/components/chat/entity-cards/case-study-card.d.ts.map +1 -1
  101. package/dist/components/chat/hooks/use-chat-dialog-manager.d.ts +4 -1
  102. package/dist/components/chat/hooks/use-chat-dialog-manager.d.ts.map +1 -1
  103. package/dist/components/chat/hooks/use-unified-chat.d.ts.map +1 -1
  104. package/dist/components/chat/index.cjs +27 -8
  105. package/dist/components/chat/index.d.ts +1 -0
  106. package/dist/components/chat/index.d.ts.map +1 -1
  107. package/dist/components/chat/index.js +57 -38
  108. package/dist/components/chat/quick-action-chip.d.ts +7 -3
  109. package/dist/components/chat/quick-action-chip.d.ts.map +1 -1
  110. package/dist/components/chat/types/component.types.d.ts +4 -0
  111. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  112. package/dist/components/chat/types/unified-chat-state.types.d.ts +12 -0
  113. package/dist/components/chat/types/unified-chat-state.types.d.ts.map +1 -1
  114. package/dist/components/contact/index.cjs +29 -13
  115. package/dist/components/contact/index.js +28 -12
  116. package/dist/components/docs/index.cjs +33 -16
  117. package/dist/components/docs/index.js +33 -16
  118. package/dist/components/docs/use-scroll-spy.d.ts +23 -1
  119. package/dist/components/docs/use-scroll-spy.d.ts.map +1 -1
  120. package/dist/components/embeds/index.cjs +29 -13
  121. package/dist/components/embeds/index.js +28 -12
  122. package/dist/components/faq/faq-section.d.ts +8 -1
  123. package/dist/components/faq/faq-section.d.ts.map +1 -1
  124. package/dist/components/faq/index.cjs +30 -14
  125. package/dist/components/faq/index.js +29 -13
  126. package/dist/components/features/array-entry-manager.d.ts +5 -1
  127. package/dist/components/features/array-entry-manager.d.ts.map +1 -1
  128. package/dist/components/features/board/board.d.ts +2 -0
  129. package/dist/components/features/board/board.d.ts.map +1 -1
  130. package/dist/components/features/board/ticket-card.d.ts.map +1 -1
  131. package/dist/components/features/board/touch-board.d.ts +1 -1
  132. package/dist/components/features/board/touch-board.d.ts.map +1 -1
  133. package/dist/components/features/board/types.d.ts +3 -0
  134. package/dist/components/features/board/types.d.ts.map +1 -1
  135. package/dist/components/features/board/use-board-collapse.d.ts +6 -1
  136. package/dist/components/features/board/use-board-collapse.d.ts.map +1 -1
  137. package/dist/components/features/capability-explorer.d.ts +94 -0
  138. package/dist/components/features/capability-explorer.d.ts.map +1 -0
  139. package/dist/components/features/cloud-tenants/index.d.ts +14 -0
  140. package/dist/components/features/cloud-tenants/index.d.ts.map +1 -0
  141. package/dist/components/features/cloud-tenants/tenant-access-cell.d.ts +9 -0
  142. package/dist/components/features/cloud-tenants/tenant-access-cell.d.ts.map +1 -0
  143. package/dist/components/features/cloud-tenants/tenant-cell.d.ts +8 -0
  144. package/dist/components/features/cloud-tenants/tenant-cell.d.ts.map +1 -0
  145. package/dist/components/features/cloud-tenants/tenant-customer-cell.d.ts +9 -0
  146. package/dist/components/features/cloud-tenants/tenant-customer-cell.d.ts.map +1 -0
  147. package/dist/components/features/cloud-tenants/tenant-presentation.d.ts +42 -0
  148. package/dist/components/features/cloud-tenants/tenant-presentation.d.ts.map +1 -0
  149. package/dist/components/features/cloud-tenants/tenant-row.d.ts +22 -0
  150. package/dist/components/features/cloud-tenants/tenant-row.d.ts.map +1 -0
  151. package/dist/components/features/cloud-tenants/tenants-table-columns.d.ts +42 -0
  152. package/dist/components/features/cloud-tenants/tenants-table-columns.d.ts.map +1 -0
  153. package/dist/components/features/cloud-tenants/tenants-table-view.d.ts +26 -0
  154. package/dist/components/features/cloud-tenants/tenants-table-view.d.ts.map +1 -0
  155. package/dist/components/features/devices/device-last-online.d.ts +3 -0
  156. package/dist/components/features/devices/device-last-online.d.ts.map +1 -0
  157. package/dist/components/features/devices/device-name.d.ts +42 -0
  158. package/dist/components/features/devices/device-name.d.ts.map +1 -0
  159. package/dist/components/features/devices/device-selector/device-selection-mode-radio.d.ts +26 -0
  160. package/dist/components/features/devices/device-selector/device-selection-mode-radio.d.ts.map +1 -0
  161. package/dist/components/features/devices/device-selector/device-selector-skeleton.d.ts +25 -0
  162. package/dist/components/features/devices/device-selector/device-selector-skeleton.d.ts.map +1 -0
  163. package/dist/components/features/devices/device-selector/device-selector.d.ts +38 -0
  164. package/dist/components/features/devices/device-selector/device-selector.d.ts.map +1 -0
  165. package/dist/components/features/devices/device-selector/device-selector.types.d.ts +133 -0
  166. package/dist/components/features/devices/device-selector/device-selector.types.d.ts.map +1 -0
  167. package/dist/components/features/devices/device-selector/narrowing.d.ts +13 -0
  168. package/dist/components/features/devices/device-selector/narrowing.d.ts.map +1 -0
  169. package/dist/components/features/devices/device-selector/use-device-selector.d.ts +17 -0
  170. package/dist/components/features/devices/device-selector/use-device-selector.d.ts.map +1 -0
  171. package/dist/components/features/devices/device-status.d.ts +23 -0
  172. package/dist/components/features/devices/device-status.d.ts.map +1 -0
  173. package/dist/components/features/devices/device-statuses.d.ts +40 -0
  174. package/dist/components/features/devices/device-statuses.d.ts.map +1 -0
  175. package/dist/components/features/devices/device-tags-filter-button.d.ts +22 -0
  176. package/dist/components/features/devices/device-tags-filter-button.d.ts.map +1 -0
  177. package/dist/components/features/devices/device-type-icon.d.ts +11 -0
  178. package/dist/components/features/devices/device-type-icon.d.ts.map +1 -0
  179. package/dist/components/features/devices/device-type-tile.d.ts +9 -0
  180. package/dist/components/features/devices/device-type-tile.d.ts.map +1 -0
  181. package/dist/components/features/devices/devices-filter-toolbar.d.ts +46 -0
  182. package/dist/components/features/devices/devices-filter-toolbar.d.ts.map +1 -0
  183. package/dist/components/features/devices/devices-grid-filters.d.ts +25 -0
  184. package/dist/components/features/devices/devices-grid-filters.d.ts.map +1 -0
  185. package/dist/components/features/devices/devices-grid.d.ts +12 -0
  186. package/dist/components/features/devices/devices-grid.d.ts.map +1 -0
  187. package/dist/components/features/devices/devices-list.d.ts +131 -0
  188. package/dist/components/features/devices/devices-list.d.ts.map +1 -0
  189. package/dist/components/features/devices/devices-panel-header.d.ts +46 -0
  190. package/dist/components/features/devices/devices-panel-header.d.ts.map +1 -0
  191. package/dist/components/features/devices/devices-panel-view.d.ts +79 -0
  192. package/dist/components/features/devices/devices-panel-view.d.ts.map +1 -0
  193. package/dist/components/features/devices/devices-table-columns.d.ts +76 -0
  194. package/dist/components/features/devices/devices-table-columns.d.ts.map +1 -0
  195. package/dist/components/features/devices/devices-view-config.d.ts +25 -0
  196. package/dist/components/features/devices/devices-view-config.d.ts.map +1 -0
  197. package/dist/components/features/devices/index.d.ts +24 -0
  198. package/dist/components/features/devices/index.d.ts.map +1 -0
  199. package/dist/components/features/devices/types.d.ts +68 -0
  200. package/dist/components/features/devices/types.d.ts.map +1 -0
  201. package/dist/components/features/devices/use-tag-filter-modal.d.ts +50 -0
  202. package/dist/components/features/devices/use-tag-filter-modal.d.ts.map +1 -0
  203. package/dist/components/features/index.cjs +227 -12
  204. package/dist/components/features/index.d.ts +7 -0
  205. package/dist/components/features/index.d.ts.map +1 -1
  206. package/dist/components/features/index.js +266 -51
  207. package/dist/components/features/knowledge-base/index.d.ts +7 -0
  208. package/dist/components/features/knowledge-base/index.d.ts.map +1 -0
  209. package/dist/components/features/knowledge-base/knowledge-base-article-view.d.ts +44 -0
  210. package/dist/components/features/knowledge-base/knowledge-base-article-view.d.ts.map +1 -0
  211. package/dist/components/features/knowledge-base/knowledge-base-item-icon.d.ts +13 -0
  212. package/dist/components/features/knowledge-base/knowledge-base-item-icon.d.ts.map +1 -0
  213. package/dist/components/features/knowledge-base/knowledge-base-status.d.ts +8 -0
  214. package/dist/components/features/knowledge-base/knowledge-base-status.d.ts.map +1 -0
  215. package/dist/components/features/knowledge-base/knowledge-base-table.d.ts +52 -0
  216. package/dist/components/features/knowledge-base/knowledge-base-table.d.ts.map +1 -0
  217. package/dist/components/features/logs/index.d.ts +12 -0
  218. package/dist/components/features/logs/index.d.ts.map +1 -0
  219. package/dist/components/features/logs/log-drawer.d.ts +29 -0
  220. package/dist/components/features/logs/log-drawer.d.ts.map +1 -0
  221. package/dist/components/features/logs/log-source-labels.d.ts +11 -0
  222. package/dist/components/features/logs/log-source-labels.d.ts.map +1 -0
  223. package/dist/components/features/logs/logs-page-view.d.ts +32 -0
  224. package/dist/components/features/logs/logs-page-view.d.ts.map +1 -0
  225. package/dist/components/features/logs/logs-table-columns.d.ts +15 -0
  226. package/dist/components/features/logs/logs-table-columns.d.ts.map +1 -0
  227. package/dist/components/features/logs/logs-table-view.d.ts +64 -0
  228. package/dist/components/features/logs/logs-table-view.d.ts.map +1 -0
  229. package/dist/components/features/logs/types.d.ts +52 -0
  230. package/dist/components/features/logs/types.d.ts.map +1 -0
  231. package/dist/components/features/policies/compute-policy-summary.d.ts +37 -0
  232. package/dist/components/features/policies/compute-policy-summary.d.ts.map +1 -0
  233. package/dist/components/features/policies/index.d.ts +8 -0
  234. package/dist/components/features/policies/index.d.ts.map +1 -0
  235. package/dist/components/features/policies/policies-table.d.ts +34 -0
  236. package/dist/components/features/policies/policies-table.d.ts.map +1 -0
  237. package/dist/components/features/policies/policy-summary-cards.d.ts +17 -0
  238. package/dist/components/features/policies/policy-summary-cards.d.ts.map +1 -0
  239. package/dist/components/features/policies/policy-table-row.d.ts +37 -0
  240. package/dist/components/features/policies/policy-table-row.d.ts.map +1 -0
  241. package/dist/components/features/remote-session/index.d.ts +8 -0
  242. package/dist/components/features/remote-session/index.d.ts.map +1 -1
  243. package/dist/components/features/remote-session/remote-desktop-chat-message-row.d.ts +21 -0
  244. package/dist/components/features/remote-session/remote-desktop-chat-message-row.d.ts.map +1 -0
  245. package/dist/components/features/remote-session/remote-desktop-chat-panel.d.ts +31 -0
  246. package/dist/components/features/remote-session/remote-desktop-chat-panel.d.ts.map +1 -0
  247. package/dist/components/features/remote-session/remote-desktop-fullscreen-toolbar.d.ts +21 -0
  248. package/dist/components/features/remote-session/remote-desktop-fullscreen-toolbar.d.ts.map +1 -0
  249. package/dist/components/features/remote-session/remote-desktop-view.d.ts +50 -0
  250. package/dist/components/features/remote-session/remote-desktop-view.d.ts.map +1 -0
  251. package/dist/components/features/software/index.d.ts +8 -0
  252. package/dist/components/features/software/index.d.ts.map +1 -0
  253. package/dist/components/features/software/package-managers.d.ts +30 -0
  254. package/dist/components/features/software/package-managers.d.ts.map +1 -0
  255. package/dist/components/features/software/package-search-field-placeholder.d.ts +7 -0
  256. package/dist/components/features/software/package-search-field-placeholder.d.ts.map +1 -0
  257. package/dist/components/features/software/schedule-fields.d.ts +34 -0
  258. package/dist/components/features/software/schedule-fields.d.ts.map +1 -0
  259. package/dist/components/features/software/software-action-copy.d.ts +25 -0
  260. package/dist/components/features/software/software-action-copy.d.ts.map +1 -0
  261. package/dist/components/features/software/software-action-form.d.ts +71 -0
  262. package/dist/components/features/software/software-action-form.d.ts.map +1 -0
  263. package/dist/components/features/software/software-row-fields.d.ts +23 -0
  264. package/dist/components/features/software/software-row-fields.d.ts.map +1 -0
  265. package/dist/components/features/software/software-row.d.ts +18 -0
  266. package/dist/components/features/software/software-row.d.ts.map +1 -0
  267. package/dist/components/features/sortable-list/index.d.ts +1 -0
  268. package/dist/components/features/sortable-list/index.d.ts.map +1 -1
  269. package/dist/components/features/sortable-list/sortable-drag-handle.d.ts +21 -0
  270. package/dist/components/features/sortable-list/sortable-drag-handle.d.ts.map +1 -0
  271. package/dist/components/help-center-pages/index.cjs +133 -114
  272. package/dist/components/help-center-pages/index.js +58 -39
  273. package/dist/components/index.cjs +320 -82
  274. package/dist/components/index.js +451 -213
  275. package/dist/components/layout/page-heading.d.ts +12 -3
  276. package/dist/components/layout/page-heading.d.ts.map +1 -1
  277. package/dist/components/meeting-scheduler/index.cjs +120 -98
  278. package/dist/components/meeting-scheduler/index.js +50 -28
  279. package/dist/components/navigation/index.cjs +36 -17
  280. package/dist/components/navigation/index.d.ts +3 -0
  281. package/dist/components/navigation/index.d.ts.map +1 -1
  282. package/dist/components/navigation/index.js +36 -17
  283. package/dist/components/navigation/mingo-ai-button.d.ts +23 -10
  284. package/dist/components/navigation/mingo-ai-button.d.ts.map +1 -1
  285. package/dist/components/navigation/sticky-section-nav.d.ts +14 -1
  286. package/dist/components/navigation/sticky-section-nav.d.ts.map +1 -1
  287. package/dist/components/onboarding-guides/index.cjs +32 -16
  288. package/dist/components/onboarding-guides/index.js +31 -15
  289. package/dist/components/product-demo/cast.d.ts +58 -0
  290. package/dist/components/product-demo/cast.d.ts.map +1 -0
  291. package/dist/components/product-demo/fixtures/cloud-tenants.d.ts +10 -0
  292. package/dist/components/product-demo/fixtures/cloud-tenants.d.ts.map +1 -0
  293. package/dist/components/product-demo/fixtures/devices.d.ts +14 -0
  294. package/dist/components/product-demo/fixtures/devices.d.ts.map +1 -0
  295. package/dist/components/product-demo/fixtures/knowledge.d.ts +14 -0
  296. package/dist/components/product-demo/fixtures/knowledge.d.ts.map +1 -0
  297. package/dist/components/product-demo/fixtures/logs.d.ts +15 -0
  298. package/dist/components/product-demo/fixtures/logs.d.ts.map +1 -0
  299. package/dist/components/product-demo/fixtures/policies.d.ts +13 -0
  300. package/dist/components/product-demo/fixtures/policies.d.ts.map +1 -0
  301. package/dist/components/product-demo/fixtures/remote-session.d.ts +20 -0
  302. package/dist/components/product-demo/fixtures/remote-session.d.ts.map +1 -0
  303. package/dist/components/product-demo/fixtures/shared.d.ts +156 -0
  304. package/dist/components/product-demo/fixtures/shared.d.ts.map +1 -0
  305. package/dist/components/product-demo/fixtures/software-update.d.ts +19 -0
  306. package/dist/components/product-demo/fixtures/software-update.d.ts.map +1 -0
  307. package/dist/components/product-demo/fixtures/tickets-board.d.ts +8 -0
  308. package/dist/components/product-demo/fixtures/tickets-board.d.ts.map +1 -0
  309. package/dist/components/product-demo/index.cjs +112 -0
  310. package/dist/components/product-demo/index.d.ts +6 -0
  311. package/dist/components/product-demo/index.d.ts.map +1 -0
  312. package/dist/components/product-demo/index.js +112 -0
  313. package/dist/components/product-demo/product-screen.d.ts +22 -0
  314. package/dist/components/product-demo/product-screen.d.ts.map +1 -0
  315. package/dist/components/product-demo/registry.d.ts +13 -0
  316. package/dist/components/product-demo/registry.d.ts.map +1 -0
  317. package/dist/components/product-demo/screen-keys.cjs +25 -0
  318. package/dist/components/product-demo/screen-keys.d.ts +27 -0
  319. package/dist/components/product-demo/screen-keys.d.ts.map +1 -0
  320. package/dist/components/product-demo/screen-keys.js +20 -0
  321. package/dist/components/product-demo/screens/cloud-tenants.d.ts +8 -0
  322. package/dist/components/product-demo/screens/cloud-tenants.d.ts.map +1 -0
  323. package/dist/components/product-demo/screens/devices.d.ts +10 -0
  324. package/dist/components/product-demo/screens/devices.d.ts.map +1 -0
  325. package/dist/components/product-demo/screens/knowledge.d.ts +9 -0
  326. package/dist/components/product-demo/screens/knowledge.d.ts.map +1 -0
  327. package/dist/components/product-demo/screens/logs.d.ts +4 -0
  328. package/dist/components/product-demo/screens/logs.d.ts.map +1 -0
  329. package/dist/components/product-demo/screens/policies.d.ts +8 -0
  330. package/dist/components/product-demo/screens/policies.d.ts.map +1 -0
  331. package/dist/components/product-demo/screens/remote-desktop-picture.d.ts +11 -0
  332. package/dist/components/product-demo/screens/remote-desktop-picture.d.ts.map +1 -0
  333. package/dist/components/product-demo/screens/remote-session.d.ts +8 -0
  334. package/dist/components/product-demo/screens/remote-session.d.ts.map +1 -0
  335. package/dist/components/product-demo/screens/software-update.d.ts +12 -0
  336. package/dist/components/product-demo/screens/software-update.d.ts.map +1 -0
  337. package/dist/components/product-demo/screens/tickets-board.d.ts +4 -0
  338. package/dist/components/product-demo/screens/tickets-board.d.ts.map +1 -0
  339. package/dist/components/product-demo/types.d.ts +9 -0
  340. package/dist/components/product-demo/types.d.ts.map +1 -0
  341. package/dist/components/related-content/index.cjs +14 -8
  342. package/dist/components/related-content/index.js +13 -7
  343. package/dist/components/tickets/index.cjs +36 -20
  344. package/dist/components/tickets/index.js +35 -19
  345. package/dist/components/ui/file-manager/index.cjs +38 -34
  346. package/dist/components/ui/file-manager/index.js +8 -4
  347. package/dist/components/ui/index.cjs +57 -17
  348. package/dist/components/ui/index.d.ts +1 -0
  349. package/dist/components/ui/index.d.ts.map +1 -1
  350. package/dist/components/ui/index.js +141 -101
  351. package/dist/components/ui/product-screen-frame.d.ts +45 -0
  352. package/dist/components/ui/product-screen-frame.d.ts.map +1 -0
  353. package/dist/components/ui/radio-group.d.ts +5 -0
  354. package/dist/components/ui/radio-group.d.ts.map +1 -1
  355. package/dist/components/ui/snap-carousel.d.ts +11 -1
  356. package/dist/components/ui/snap-carousel.d.ts.map +1 -1
  357. package/dist/components/ui/tag.d.ts +1 -1
  358. package/dist/components/ui/tag.d.ts.map +1 -1
  359. package/dist/devices-LBMG42K6.js +81 -0
  360. package/dist/devices-YGYJIXQY.cjs +81 -0
  361. package/dist/hooks/index.cjs +17 -8
  362. package/dist/hooks/index.js +32 -23
  363. package/dist/hooks/ui/index.d.ts +1 -0
  364. package/dist/hooks/ui/index.d.ts.map +1 -1
  365. package/dist/hooks/ui/use-header-height.d.ts +12 -0
  366. package/dist/hooks/ui/use-header-height.d.ts.map +1 -1
  367. package/dist/hooks/ui/use-sticky-toolbar.d.ts +29 -0
  368. package/dist/hooks/ui/use-sticky-toolbar.d.ts.map +1 -0
  369. package/dist/hooks/use-location-hash.d.ts +2 -2
  370. package/dist/hooks/use-location-hash.d.ts.map +1 -1
  371. package/dist/hooks/use-scroll-to-hash.d.ts +7 -0
  372. package/dist/hooks/use-scroll-to-hash.d.ts.map +1 -1
  373. package/dist/index.cjs +276 -25
  374. package/dist/index.js +729 -478
  375. package/dist/knowledge-H5BIWJVI.js +108 -0
  376. package/dist/knowledge-KTCVJIWN.cjs +108 -0
  377. package/dist/logs-DB5Z7M5Q.js +216 -0
  378. package/dist/logs-RVCC2UQW.cjs +216 -0
  379. package/dist/policies-EWUULFBR.js +121 -0
  380. package/dist/policies-HV4IQCBV.cjs +121 -0
  381. package/dist/remote-session-GSGZOFDX.js +196 -0
  382. package/dist/remote-session-R6VAFESR.cjs +196 -0
  383. package/dist/software-update-6PXKRKBT.js +179 -0
  384. package/dist/software-update-D4OVSWSG.cjs +179 -0
  385. package/dist/tickets-board-BHLPAVNJ.cjs +137 -0
  386. package/dist/tickets-board-PYDNELSK.js +137 -0
  387. package/dist/types/case-study.d.ts +15 -1
  388. package/dist/types/case-study.d.ts.map +1 -1
  389. package/dist/utils/date-utils.d.ts +5 -0
  390. package/dist/utils/date-utils.d.ts.map +1 -1
  391. package/dist/utils/index.cjs +45 -2
  392. package/dist/utils/index.d.ts +2 -1
  393. package/dist/utils/index.d.ts.map +1 -1
  394. package/dist/utils/index.js +41 -3
  395. package/dist/utils/open-in-new-tab.d.ts +7 -0
  396. package/dist/utils/open-in-new-tab.d.ts.map +1 -0
  397. package/dist/utils/same-page-hash-nav.d.ts +31 -0
  398. package/dist/utils/same-page-hash-nav.d.ts.map +1 -1
  399. package/dist/utils/scroll-into-view.d.ts +14 -1
  400. package/dist/utils/scroll-into-view.d.ts.map +1 -1
  401. package/package.json +13 -1
  402. package/src/components/chat/ask-prompts.tsx +226 -0
  403. package/src/components/chat/embeddable-chat.tsx +38 -2
  404. package/src/components/chat/entity-cards/case-study-card.tsx +122 -46
  405. package/src/components/chat/hooks/use-chat-dialog-manager.ts +22 -4
  406. package/src/components/chat/hooks/use-unified-chat.ts +1 -0
  407. package/src/components/chat/index.ts +1 -0
  408. package/src/components/chat/quick-action-chip.tsx +33 -9
  409. package/src/components/chat/types/component.types.ts +4 -0
  410. package/src/components/chat/types/unified-chat-state.types.ts +13 -0
  411. package/src/components/docs/use-scroll-spy.ts +93 -18
  412. package/src/components/faq/faq-section.tsx +82 -43
  413. package/src/components/features/array-entry-manager.tsx +10 -1
  414. package/src/components/features/board/board.tsx +4 -1
  415. package/src/components/features/board/ticket-card.tsx +11 -1
  416. package/src/components/features/board/touch-board.tsx +2 -1
  417. package/src/components/features/board/types.ts +3 -0
  418. package/src/components/features/board/use-board-collapse.ts +7 -2
  419. package/src/components/features/capability-explorer.tsx +412 -0
  420. package/src/components/features/cloud-tenants/index.ts +28 -0
  421. package/src/components/features/cloud-tenants/tenant-access-cell.tsx +24 -0
  422. package/src/components/features/cloud-tenants/tenant-cell.tsx +26 -0
  423. package/src/components/features/cloud-tenants/tenant-customer-cell.tsx +27 -0
  424. package/src/components/features/cloud-tenants/tenant-presentation.ts +111 -0
  425. package/src/components/features/cloud-tenants/tenant-row.ts +21 -0
  426. package/src/components/features/cloud-tenants/tenants-table-columns.ts +30 -0
  427. package/src/components/features/cloud-tenants/tenants-table-view.tsx +142 -0
  428. package/src/components/features/devices/device-last-online.ts +6 -0
  429. package/src/components/features/devices/device-name.ts +51 -0
  430. package/src/components/features/devices/device-selector/device-selection-mode-radio.tsx +107 -0
  431. package/src/components/features/devices/device-selector/device-selector-skeleton.tsx +32 -0
  432. package/src/components/features/devices/device-selector/device-selector.tsx +799 -0
  433. package/src/components/features/devices/device-selector/device-selector.types.ts +138 -0
  434. package/src/components/features/devices/device-selector/narrowing.ts +33 -0
  435. package/src/components/features/devices/device-selector/use-device-selector.ts +51 -0
  436. package/src/components/features/devices/device-status.ts +102 -0
  437. package/src/components/features/devices/device-statuses.ts +88 -0
  438. package/src/components/features/devices/device-tags-filter-button.tsx +49 -0
  439. package/src/components/features/devices/device-type-icon.tsx +29 -0
  440. package/src/components/features/devices/device-type-tile.tsx +17 -0
  441. package/src/components/features/devices/devices-filter-toolbar.tsx +114 -0
  442. package/src/components/features/devices/devices-grid-filters.tsx +99 -0
  443. package/src/components/features/devices/devices-grid.tsx +86 -0
  444. package/src/components/features/devices/devices-list.tsx +357 -0
  445. package/src/components/features/devices/devices-panel-header.tsx +97 -0
  446. package/src/components/features/devices/devices-panel-view.tsx +261 -0
  447. package/src/components/features/devices/devices-table-columns.tsx +356 -0
  448. package/src/components/features/devices/devices-view-config.tsx +38 -0
  449. package/src/components/features/devices/index.ts +89 -0
  450. package/src/components/features/devices/types.ts +74 -0
  451. package/src/components/features/devices/use-tag-filter-modal.ts +109 -0
  452. package/src/components/features/index.ts +9 -0
  453. package/src/components/features/knowledge-base/index.ts +19 -0
  454. package/src/components/features/knowledge-base/knowledge-base-article-view.tsx +134 -0
  455. package/src/components/features/knowledge-base/knowledge-base-item-icon.ts +14 -0
  456. package/src/components/features/knowledge-base/knowledge-base-status.ts +12 -0
  457. package/src/components/features/knowledge-base/knowledge-base-table.tsx +180 -0
  458. package/src/components/features/logs/index.ts +20 -0
  459. package/src/components/features/logs/log-drawer.tsx +138 -0
  460. package/src/components/features/logs/log-source-labels.ts +25 -0
  461. package/src/components/features/logs/logs-page-view.tsx +100 -0
  462. package/src/components/features/logs/logs-table-columns.ts +16 -0
  463. package/src/components/features/logs/logs-table-view.tsx +509 -0
  464. package/src/components/features/logs/types.ts +71 -0
  465. package/src/components/features/policies/compute-policy-summary.ts +115 -0
  466. package/src/components/features/policies/index.ts +14 -0
  467. package/src/components/features/policies/policies-table.tsx +235 -0
  468. package/src/components/features/policies/policy-summary-cards.tsx +69 -0
  469. package/src/components/features/policies/policy-table-row.ts +37 -0
  470. package/src/components/features/remote-session/index.ts +8 -0
  471. package/src/components/features/remote-session/remote-desktop-chat-message-row.tsx +56 -0
  472. package/src/components/features/remote-session/remote-desktop-chat-panel.tsx +102 -0
  473. package/src/components/features/remote-session/remote-desktop-fullscreen-toolbar.tsx +119 -0
  474. package/src/components/features/remote-session/remote-desktop-view.tsx +209 -0
  475. package/src/components/features/software/index.ts +39 -0
  476. package/src/components/features/software/package-managers.ts +54 -0
  477. package/src/components/features/software/package-search-field-placeholder.tsx +23 -0
  478. package/src/components/features/software/schedule-fields.tsx +105 -0
  479. package/src/components/features/software/software-action-copy.ts +70 -0
  480. package/src/components/features/software/software-action-form.tsx +199 -0
  481. package/src/components/features/software/software-row-fields.tsx +105 -0
  482. package/src/components/features/software/software-row.ts +22 -0
  483. package/src/components/features/sortable-list/index.ts +1 -0
  484. package/src/components/features/sortable-list/sortable-drag-handle.tsx +41 -0
  485. package/src/components/layout/page-heading.tsx +23 -6
  486. package/src/components/navigation/index.ts +5 -0
  487. package/src/components/navigation/mingo-ai-button.tsx +37 -13
  488. package/src/components/navigation/sticky-section-nav.tsx +99 -1
  489. package/src/components/product-demo/cast.tsx +78 -0
  490. package/src/components/product-demo/fixtures/cloud-tenants.ts +63 -0
  491. package/src/components/product-demo/fixtures/devices.ts +87 -0
  492. package/src/components/product-demo/fixtures/knowledge.ts +48 -0
  493. package/src/components/product-demo/fixtures/logs.ts +103 -0
  494. package/src/components/product-demo/fixtures/policies.ts +77 -0
  495. package/src/components/product-demo/fixtures/remote-session.ts +65 -0
  496. package/src/components/product-demo/fixtures/shared.ts +53 -0
  497. package/src/components/product-demo/fixtures/software-update.ts +63 -0
  498. package/src/components/product-demo/fixtures/tickets-board.ts +100 -0
  499. package/src/components/product-demo/index.ts +7 -0
  500. package/src/components/product-demo/product-screen.tsx +94 -0
  501. package/src/components/product-demo/registry.ts +20 -0
  502. package/src/components/product-demo/screen-keys.ts +31 -0
  503. package/src/components/product-demo/screens/cloud-tenants.tsx +23 -0
  504. package/src/components/product-demo/screens/devices.tsx +41 -0
  505. package/src/components/product-demo/screens/knowledge.tsx +27 -0
  506. package/src/components/product-demo/screens/logs.tsx +113 -0
  507. package/src/components/product-demo/screens/policies.tsx +29 -0
  508. package/src/components/product-demo/screens/remote-desktop-picture.tsx +118 -0
  509. package/src/components/product-demo/screens/remote-session.tsx +46 -0
  510. package/src/components/product-demo/screens/software-update.tsx +97 -0
  511. package/src/components/product-demo/screens/tickets-board.tsx +28 -0
  512. package/src/components/product-demo/types.ts +10 -0
  513. package/src/components/ui/index.ts +1 -0
  514. package/src/components/ui/product-screen-frame.tsx +136 -0
  515. package/src/components/ui/radio-group.tsx +16 -4
  516. package/src/components/ui/snap-carousel.tsx +26 -1
  517. package/src/components/ui/tag.tsx +5 -0
  518. package/src/hooks/ui/index.ts +1 -0
  519. package/src/hooks/ui/use-header-height.ts +51 -2
  520. package/src/hooks/ui/use-sticky-toolbar.ts +60 -0
  521. package/src/hooks/use-location-hash.ts +9 -5
  522. package/src/hooks/use-scroll-to-hash.ts +9 -1
  523. package/src/types/case-study.ts +21 -1
  524. package/src/utils/date-utils.ts +8 -1
  525. package/src/utils/index.ts +5 -0
  526. package/src/utils/open-in-new-tab.ts +12 -0
  527. package/src/utils/same-page-hash-nav.ts +57 -0
  528. package/src/utils/scroll-into-view.ts +21 -5
  529. package/dist/chunk-BM5MVGH3.cjs +0 -499
  530. package/dist/chunk-CUME3VTQ.js +0 -144
  531. package/dist/chunk-CZ7Y7UG4.js +0 -732
  532. package/dist/chunk-FLKJYMVB.js +0 -499
  533. package/dist/chunk-OF6GEI5A.cjs +0 -144
  534. package/dist/chunk-UVTD52MD.cjs +0 -732
@@ -0,0 +1,99 @@
1
+ 'use client';
2
+
3
+ import { cn } from '../../../utils/cn';
4
+ import { Filter02Icon } from '../../icons-v2-generated';
5
+ import { FiltersDropdown } from '../filters-dropdown';
6
+ import type { DeviceFilterColumn } from './devices-table-columns';
7
+
8
+ export interface DevicesGridFiltersProps {
9
+ filterColumns: DeviceFilterColumn[];
10
+ /** Current filter values keyed by column id (same shape as table's tableFilters). */
11
+ currentFilters: Record<string, string[]>;
12
+ /** Called with the next filters Record on apply/reset. Should write to URL params. */
13
+ onFilterChange: (filters: Record<string, string[]>) => void;
14
+ /** Server-side count for the "N results" tail. */
15
+ totalCount?: number;
16
+ /**
17
+ * The facet query is still out. Keeps every filterable column in the row even
18
+ * though its options haven't arrived, the LABELS are static, so the row can
19
+ * be drawn at its real height instead of collapsing to nothing and pushing the
20
+ * grid down a row the moment the facets land. Used by the panel's Suspense
21
+ * fallback, which renders this inert.
22
+ */
23
+ isLoading?: boolean;
24
+ }
25
+
26
+ /**
27
+ * DevicesGridFilters, horizontal row of dropdown filters shown above the
28
+ * devices grid. Mirrors the column-header filters from the table view so the
29
+ * same filter set is available in both layouts.
30
+ */
31
+ export function DevicesGridFilters({
32
+ filterColumns,
33
+ currentFilters,
34
+ onFilterChange,
35
+ totalCount,
36
+ isLoading = false,
37
+ }: DevicesGridFiltersProps) {
38
+ const filterableColumns = filterColumns.filter(
39
+ c => c.filterable && (isLoading || (c.filterOptions && c.filterOptions.length > 0)),
40
+ );
41
+
42
+ if (filterableColumns.length === 0 && totalCount === undefined) {
43
+ return null;
44
+ }
45
+
46
+ return (
47
+ <div className="sticky top-[96px] z-10 flex flex-wrap items-start gap-[var(--spacing-system-m)] bg-ods-bg px-[var(--spacing-system-m)]">
48
+ {filterableColumns.map(column => {
49
+ const selected = currentFilters[column.key] ?? [];
50
+ const active = selected.length > 0;
51
+
52
+ return (
53
+ <FiltersDropdown
54
+ key={column.key}
55
+ triggerElement={
56
+ <button
57
+ type="button"
58
+ className="group inline-flex cursor-pointer select-none items-center gap-[var(--spacing-system-xsf)] py-[var(--spacing-system-sf)]"
59
+ aria-label={`Filter by ${column.label}`}
60
+ >
61
+ <span className="whitespace-nowrap uppercase text-ods-text-secondary transition-colors text-h5 group-hover:text-ods-text-primary">
62
+ {column.label}
63
+ </span>
64
+ <Filter02Icon
65
+ className={cn(
66
+ 'h-4 w-4 transition-colors',
67
+ active ? 'text-ods-accent' : 'text-ods-text-secondary group-hover:text-ods-text-primary',
68
+ )}
69
+ />
70
+ </button>
71
+ }
72
+ sections={[
73
+ {
74
+ id: column.key,
75
+ title: column.label,
76
+ type: 'checkbox',
77
+ options: column.filterOptions ?? [],
78
+ allowSelectAll: true,
79
+ },
80
+ ]}
81
+ currentFilters={{ [column.key]: selected }}
82
+ onApply={applied => {
83
+ const next = applied[column.key] ?? [];
84
+ onFilterChange({ ...currentFilters, [column.key]: next });
85
+ }}
86
+ onReset={() => onFilterChange({ ...currentFilters, [column.key]: [] })}
87
+ placement="bottom-start"
88
+ dropdownClassName="min-w-60"
89
+ />
90
+ );
91
+ })}
92
+ {totalCount !== undefined && (
93
+ <div className="absolute inset-y-0 right-0 flex items-center">
94
+ <span className="whitespace-nowrap text-ods-text-secondary text-h6">{totalCount} results</span>
95
+ </div>
96
+ )}
97
+ </div>
98
+ );
99
+ }
@@ -0,0 +1,86 @@
1
+ 'use client';
2
+
3
+ import type React from 'react';
4
+ import { useRouter } from '../../../embed-shims/next-navigation';
5
+ import { DeviceCardSkeleton, DeviceCardSkeletonGrid } from '../../loading/device-card-skeleton';
6
+ import { DeviceCard } from '../../ui';
7
+ import { getDeviceName } from './device-name';
8
+ import { getDeviceOperatingSystem, getDeviceStatusConfig } from './device-status';
9
+ import { useDevicesViewConfig } from './devices-view-config';
10
+ import type { DeviceRow } from './types';
11
+
12
+ export interface DevicesGridProps<T extends DeviceRow = DeviceRow> {
13
+ devices: T[];
14
+ isLoading: boolean;
15
+ hasNextPage?: boolean;
16
+ isFetchingNextPage?: boolean;
17
+ sentinelRef?: React.RefObject<HTMLDivElement | null>;
18
+ emptyMessage?: string;
19
+ }
20
+
21
+ export function DevicesGrid<T extends DeviceRow = DeviceRow>({
22
+ devices,
23
+ isLoading,
24
+ hasNextPage,
25
+ isFetchingNextPage,
26
+ sentinelRef,
27
+ emptyMessage = 'No devices found. Try adjusting your search or filters.',
28
+ }: DevicesGridProps<T>) {
29
+ const router = useRouter();
30
+ const { getDeviceHref } = useDevicesViewConfig();
31
+
32
+ const handleDeviceClick = (device: T) => {
33
+ const href = device.machineId || device.id ? getDeviceHref?.(device) : undefined;
34
+ if (href) router.push(href);
35
+ };
36
+
37
+ return (
38
+ <div className="space-y-4">
39
+ {isLoading && devices.length === 0 ? (
40
+ <DeviceCardSkeletonGrid count={12} />
41
+ ) : devices.length === 0 ? (
42
+ <div className="flex h-64 items-center justify-center rounded-[6px] border border-ods-border bg-ods-card">
43
+ <p className="text-ods-text-secondary">{emptyMessage}</p>
44
+ </div>
45
+ ) : (
46
+ <>
47
+ <div className="grid grid-cols-1 gap-4 content-md:grid-cols-2 content-lg:grid-cols-3">
48
+ {devices.map(device => {
49
+ const statusConfig = getDeviceStatusConfig(device.status);
50
+ return (
51
+ <DeviceCard
52
+ key={device.id || device.machineId}
53
+ device={{
54
+ id: device.id,
55
+ machineId: device.machineId,
56
+ name: getDeviceName(device),
57
+ organization: device.organization || device.machineId,
58
+ lastSeen: device.lastSeen,
59
+ operatingSystem: getDeviceOperatingSystem(device.osType),
60
+ }}
61
+ statusTag={
62
+ device.status
63
+ ? {
64
+ label: statusConfig.label,
65
+ variant: statusConfig.variant,
66
+ }
67
+ : undefined
68
+ }
69
+ onDeviceClick={() => handleDeviceClick(device)}
70
+ actions={{
71
+ moreButton: {
72
+ visible: false,
73
+ },
74
+ }}
75
+ className="h-full"
76
+ />
77
+ );
78
+ })}
79
+ {isFetchingNextPage && Array.from({ length: 4 }, (_, i) => <DeviceCardSkeleton key={`skeleton-${i}`} />)}
80
+ </div>
81
+ {hasNextPage && <div ref={sentinelRef} className="h-1" aria-hidden="true" />}
82
+ </>
83
+ )}
84
+ </div>
85
+ );
86
+ }
@@ -0,0 +1,357 @@
1
+ 'use client';
2
+
3
+ import { type ReactNode, useCallback, useMemo } from 'react';
4
+ import { useStickyToolbar } from '../../../hooks/ui/use-sticky-toolbar';
5
+ import { type ColumnFiltersState, DataTable, type NoDataProps, type OnChangeFn } from '../../ui';
6
+ import { DevicesFilterToolbar } from './devices-filter-toolbar';
7
+ import { DevicesTableBody, getDeviceActionsColumn, getDeviceFilterColumns } from './devices-table-columns';
8
+ import type { DeviceFilters, DeviceRow } from './types';
9
+ import { useTagFilterModal } from './use-tag-filter-modal';
10
+
11
+ /**
12
+ * What the user has narrowed the list down to. One shape for every surface, so a
13
+ * caller can keep it in the URL, in local state, or hand it straight to a server
14
+ * filter without translating between vocabularies.
15
+ */
16
+ export interface DevicesListNarrowing {
17
+ search: string;
18
+ statuses: string[];
19
+ osTypes: string[];
20
+ organizationIds: string[];
21
+ /** Chips as typed. `key:value` narrows; a bare word stays visible and filters nothing. */
22
+ tags: string[];
23
+ }
24
+
25
+ export const EMPTY_DEVICES_NARROWING: DevicesListNarrowing = {
26
+ search: '',
27
+ statuses: [],
28
+ osTypes: [],
29
+ organizationIds: [],
30
+ tags: [],
31
+ };
32
+
33
+ /** True when anything at all is narrowing the list, an empty list then means "no matches", not "nothing here". */
34
+ export function isNarrowed(narrowing: DevicesListNarrowing): boolean {
35
+ return (
36
+ narrowing.search.trim().length > 0 ||
37
+ narrowing.statuses.length > 0 ||
38
+ narrowing.osTypes.length > 0 ||
39
+ narrowing.organizationIds.length > 0 ||
40
+ narrowing.tags.length > 0
41
+ );
42
+ }
43
+
44
+ export interface DevicesListProps<T extends DeviceRow = DeviceRow> {
45
+ /**
46
+ * The rows to render, already narrowed. This component never filters and never
47
+ * fetches, see the module docstring.
48
+ */
49
+ devices: T[];
50
+ isLoading?: boolean;
51
+
52
+ /**
53
+ * Facet counts behind the column funnels and the mobile filter modal, **from
54
+ * the server**, the `deviceFilters` query, scoped the same way the rows are.
55
+ *
56
+ * NEVER derive these from `devices`. Counts computed off the loaded rows read
57
+ * as facts about the list and are not: they change with every page fetched and
58
+ * disagree with the server the moment anything is narrowed. A surface with no
59
+ * facet query of its own passes `null` (or omits this) and the table drops the
60
+ * funnels entirely, a control that opens onto nothing is worse than none.
61
+ */
62
+ deviceFilters?: DeviceFilters | null;
63
+ /**
64
+ * The facet query has not answered yet, keeps the funnels drawn but inert,
65
+ * so they don't appear out of nowhere when it does. Key it on the DATA
66
+ * (`!deviceFilters`), never on a react-query `isLoading`, which reads false
67
+ * before the request has started.
68
+ */
69
+ filtersPending?: boolean;
70
+
71
+ /**
72
+ * True while the rows on screen are the PREVIOUS result and a refetch is in
73
+ * flight (deferred query variables, see `useDeferredQuery`). Dims them,
74
+ * rather than tearing the list down to a skeleton on every keystroke.
75
+ */
76
+ isPending?: boolean;
77
+
78
+ /**
79
+ * Row count beside the column header: the server's total for the CURRENT
80
+ * narrowing (a connection's `filteredCount`), not the number of rows fetched
81
+ * so far. Honest at any point precisely because the narrowing is the server's
82
+ * too, a count taken from a client-side filter would contradict it.
83
+ */
84
+ totalCount?: number;
85
+
86
+ /** Controlled narrowing. Omit both to render a read-only list (skeletons, previews). */
87
+ narrowing?: DevicesListNarrowing;
88
+ onNarrowingChange?: (next: DevicesListNarrowing) => void;
89
+
90
+ /** Column ids to drop, e.g. `['organization']` when the list is already scoped to one customer. */
91
+ hideColumns?: string[];
92
+ /** Filter keys to drop from the funnels AND the modal; the column itself stays. */
93
+ hideFilters?: string[];
94
+ /** Per-row overflow menu. Omit for a read-only list. */
95
+ rowActions?: (device: T) => ReactNode;
96
+
97
+ /**
98
+ * Shown when the list is empty and nothing is narrowing it, the design's
99
+ * `data-placeholder`: icon over title over description, rendered by the
100
+ * table's own `DataTableEmpty`.
101
+ */
102
+ emptyState?: NoDataProps;
103
+ /**
104
+ * Shown when narrowing is what emptied it. Defaults to the table's standard
105
+ * "no results" state (search icon, "Try adjusting your search or filters"),
106
+ * which is the right answer on every list, override only to name the rows.
107
+ */
108
+ narrowedEmptyState?: NoDataProps;
109
+
110
+ skeletonRows?: number;
111
+ infiniteScroll?: {
112
+ hasNextPage: boolean;
113
+ isFetchingNextPage: boolean;
114
+ onLoadMore: () => void;
115
+ skeletonRows?: number;
116
+ };
117
+
118
+ /**
119
+ * Pins the search / tag toolbar to the top of the scroll area, as the fleet
120
+ * list does. On by default: a list long enough to scroll is exactly the one
121
+ * whose search must stay reachable. Turn it off only where something else is
122
+ * already pinned at the top.
123
+ */
124
+ stickyToolbar?: boolean;
125
+ /**
126
+ * Overrides the wrapper around the toolbar and the table. By default it adds
127
+ * NO gap while the toolbar is pinned, the pinned row carries its own `p-l`,
128
+ * and a gap on top of it doubles the space under the search box.
129
+ */
130
+ /**
131
+ * Where the column header parks once the rows scroll under it. Defaults to the
132
+ * MEASURED height of the pinned toolbar, so the two never overlap and never
133
+ * leave a gap, the toolbar grows and shrinks with the tag-chip row, and is
134
+ * shorter on a phone. Only pass this to park the header somewhere else.
135
+ */
136
+ stickyHeaderOffset?: string;
137
+ className?: string;
138
+ }
139
+
140
+ const NOOP = () => {};
141
+
142
+ /**
143
+ * The devices list, search + tag chips + column funnels over the shared devices
144
+ * table, identical on every surface that shows devices.
145
+ *
146
+ * **It does not fetch, and it does not filter.** That is the whole point: in
147
+ * Relay the rows are a CONNECTION, and every surface has a different one
148
+ * (`devices` for the fleet, `scriptSchedule.assignedDevices` for a schedule's
149
+ * assignment, `availableDevices` for its picker). Baking a query in would tie
150
+ * the list to exactly one of them; taking `devices` + a controlled
151
+ * {@link DevicesListNarrowing} lets one component serve all of them.
152
+ *
153
+ * It follows that the narrowing this component reports belongs in the caller's
154
+ * QUERY, every devices connection takes the same `filter` / `search`, so every
155
+ * surface narrows server-side, over the whole list rather than the pages fetched
156
+ * so far. The funnel options come from the server too (`deviceFilters`), or not
157
+ * at all; see the `deviceFilters` prop.
158
+ *
159
+ * The rows-in / narrowing-out split is also what makes the two data layers
160
+ * coexist: the fleet list is still react-query over raw POST, the schedule reads
161
+ * Relay. When devices move to Relay, the natural next step is a colocated
162
+ * fragment on `Device` that each caller spreads on its own connection, the
163
+ * props here do not change.
164
+ */
165
+ export function DevicesList<T extends DeviceRow = DeviceRow>({
166
+ devices,
167
+ isLoading,
168
+ deviceFilters = null,
169
+ filtersPending,
170
+ isPending,
171
+ totalCount,
172
+ narrowing = EMPTY_DEVICES_NARROWING,
173
+ onNarrowingChange = NOOP,
174
+ hideColumns,
175
+ hideFilters,
176
+ rowActions,
177
+ emptyState,
178
+ narrowedEmptyState,
179
+ skeletonRows = 8,
180
+ infiniteScroll,
181
+ stickyToolbar = true,
182
+ stickyHeaderOffset,
183
+ className,
184
+ }: DevicesListProps<T>) {
185
+ const patch = useCallback(
186
+ (next: Partial<DevicesListNarrowing>) => onNarrowingChange({ ...narrowing, ...next }),
187
+ [narrowing, onNarrowingChange],
188
+ );
189
+
190
+ const filterColumns = useMemo(() => {
191
+ const hidden = new Set(hideFilters ?? []);
192
+ return getDeviceFilterColumns(deviceFilters).filter(column => !hidden.has(column.key));
193
+ }, [deviceFilters, hideFilters]);
194
+
195
+ // The column funnels speak in column ids; the narrowing speaks in the backend's
196
+ // field names. This pair is the only place that translation lives.
197
+ const columnFilters = useMemo<ColumnFiltersState>(
198
+ () => [
199
+ ...(narrowing.statuses.length ? [{ id: 'status', value: narrowing.statuses }] : []),
200
+ ...(narrowing.osTypes.length ? [{ id: 'os', value: narrowing.osTypes }] : []),
201
+ ...(narrowing.organizationIds.length ? [{ id: 'organization', value: narrowing.organizationIds }] : []),
202
+ ],
203
+ [narrowing.statuses, narrowing.osTypes, narrowing.organizationIds],
204
+ );
205
+
206
+ const onColumnFiltersChange = useCallback<OnChangeFn<ColumnFiltersState>>(
207
+ updater => {
208
+ const next = typeof updater === 'function' ? updater(columnFilters) : updater;
209
+ const pick = (id: string) => (next.find(f => f.id === id)?.value as string[] | undefined) ?? [];
210
+ patch({ statuses: pick('status'), osTypes: pick('os'), organizationIds: pick('organization') });
211
+ },
212
+ [columnFilters, patch],
213
+ );
214
+
215
+ // The mobile modal hands back one flat params object keyed by backend field.
216
+ const handleModalParams = useCallback(
217
+ (params: Record<string, unknown>) => {
218
+ const pick = (key: string) => (params[key] as string[] | undefined) ?? [];
219
+ patch({
220
+ statuses: pick('statuses'),
221
+ osTypes: pick('osTypes'),
222
+ organizationIds: pick('organizationIds'),
223
+ tags: pick('tags'),
224
+ });
225
+ },
226
+ [patch],
227
+ );
228
+
229
+ const {
230
+ isOpen: filterModalOpen,
231
+ open: openFilterModal,
232
+ close: closeFilterModal,
233
+ isMdUp,
234
+ filterGroups,
235
+ tagFilterKeys,
236
+ handleFilterChange: handleModalFilterChange,
237
+ handleTagsChange: handleModalTagsChange,
238
+ } = useTagFilterModal({
239
+ tags: narrowing.tags,
240
+ deviceFilters,
241
+ columns: filterColumns,
242
+ setParams: handleModalParams,
243
+ });
244
+
245
+ const tagOptions = useMemo(() => narrowing.tags.map(tag => ({ label: tag, value: tag })), [narrowing.tags]);
246
+
247
+ // The modal reads the current selection back in column-keyed form.
248
+ const tableFilters = useMemo(
249
+ () => ({ status: narrowing.statuses, os: narrowing.osTypes, organization: narrowing.organizationIds }),
250
+ [narrowing.statuses, narrowing.osTypes, narrowing.organizationIds],
251
+ );
252
+
253
+ const handleTagRemove = useCallback(
254
+ (value: string) => patch({ tags: narrowing.tags.filter(tag => tag !== value) }),
255
+ [patch, narrowing.tags],
256
+ );
257
+
258
+ const handleTagSubmit = useCallback(
259
+ (value: string) => {
260
+ const trimmed = value.trim();
261
+ if (!trimmed) return;
262
+ patch({ search: '', tags: narrowing.tags.includes(trimmed) ? narrowing.tags : [...narrowing.tags, trimmed] });
263
+ },
264
+ [patch, narrowing.tags],
265
+ );
266
+
267
+ const handleClearAll = useCallback(() => patch({ search: '', tags: [] }), [patch]);
268
+
269
+ const narrowed = isNarrowed(narrowing);
270
+
271
+ // Nothing here at all, the design's placeholder, and the one state with
272
+ // nothing to search: the box is dropped rather than left over an empty list.
273
+ // Narrowing that empties the list is NOT this case; there the toolbar is the
274
+ // only way back, so it stays (as does the column header above).
275
+ const isEmptyState = !isLoading && !isPending && !narrowed && devices.length === 0;
276
+
277
+ // The toolbar publishes its own height on the wrapper below, and the column
278
+ // header parks at exactly that. Measured, not a constant: the toolbar gains a
279
+ // row when the first tag chip lands and is shorter on a phone, and a fixed
280
+ // offset would either cover the first rows or leave a strip of them showing
281
+ // through above the header.
282
+ const { toolbarRef, containerStyle, stickyHeaderOffset: measuredOffset } = useStickyToolbar();
283
+ const headerOffset = stickyHeaderOffset ?? (stickyToolbar ? measuredOffset : undefined);
284
+
285
+ const actionsColumn = useMemo(() => (rowActions ? getDeviceActionsColumn<T>(rowActions) : undefined), [rowActions]);
286
+
287
+ return (
288
+ // No gap under a pinned toolbar: its own `p-l` is the space below the search
289
+ // box, and a gap here would double it. An unpinned toolbar has no padding of
290
+ // its own, so there it is the gap that separates the two.
291
+ <div
292
+ className={className ?? (stickyToolbar ? 'flex flex-col' : 'flex flex-col gap-[var(--spacing-system-l)]')}
293
+ style={containerStyle}
294
+ >
295
+ {!isEmptyState && (
296
+ <DevicesFilterToolbar
297
+ sticky={stickyToolbar}
298
+ toolbarRef={toolbarRef}
299
+ searchValue={narrowing.search}
300
+ onSearchChange={value => patch({ search: value })}
301
+ tags={tagOptions}
302
+ onTagRemove={handleTagRemove}
303
+ onClearAll={handleClearAll}
304
+ onSubmit={handleTagSubmit}
305
+ onOpenFilterModal={openFilterModal}
306
+ isFilterModalOpen={filterModalOpen}
307
+ onCloseFilterModal={closeFilterModal}
308
+ filterGroups={filterGroups}
309
+ onFilterChange={handleModalFilterChange}
310
+ currentFilters={isMdUp === false ? tableFilters : undefined}
311
+ tagFilterKeys={tagFilterKeys}
312
+ selectedTags={narrowing.tags}
313
+ onTagsChange={handleModalTagsChange}
314
+ />
315
+ )}
316
+
317
+ {/* Dim (don't unmount) the stale rows while a refetch is in flight, the
318
+ subtle fade is the pending feedback, and the search box above keeps its
319
+ focus because nothing under it is torn down. */}
320
+ <div className={`transition-opacity duration-200 ${isPending ? 'opacity-60' : ''}`}>
321
+ <DevicesTableBody
322
+ devices={devices}
323
+ isLoading={isLoading}
324
+ // Column labels above nothing explain nothing, but they stay while
325
+ // loading (the skeleton rows are what they label), while a refetch is
326
+ // pending, and whenever narrowing is what emptied the list, since the
327
+ // funnels live in that header and removing it would strip the only way
328
+ // to undo the filter.
329
+ showHeader={isLoading || isPending || devices.length > 0 || narrowed}
330
+ // Narrowed: `undefined` is what asks the table for its own standard
331
+ // "no results found / try adjusting your search or filters" state.
332
+ emptyState={narrowed ? narrowedEmptyState : emptyState}
333
+ skeletonRows={skeletonRows}
334
+ stickyHeaderOffset={headerOffset}
335
+ deviceFilters={deviceFilters}
336
+ filtersPending={filtersPending}
337
+ columnFilters={columnFilters}
338
+ onColumnFiltersChange={onColumnFiltersChange}
339
+ actionsColumn={actionsColumn}
340
+ hideColumns={hideColumns}
341
+ disableColumnFilters={hideFilters}
342
+ totalCount={totalCount}
343
+ footerSlot={
344
+ infiniteScroll && (
345
+ <DataTable.InfiniteFooter
346
+ hasNextPage={infiniteScroll.hasNextPage}
347
+ isFetchingNextPage={infiniteScroll.isFetchingNextPage}
348
+ onLoadMore={infiniteScroll.onLoadMore}
349
+ skeletonRows={infiniteScroll.skeletonRows}
350
+ />
351
+ )
352
+ }
353
+ />
354
+ </div>
355
+ </div>
356
+ );
357
+ }
@@ -0,0 +1,97 @@
1
+ 'use client';
2
+
3
+ import { BoxArchiveIcon, GridIcon, PlusCircleIcon, TableCellIcon } from '../../icons-v2-generated';
4
+ import type { PageActionButton } from '../../ui';
5
+
6
+ /**
7
+ * The panel header's contents, declared once for both the loaded panel and its
8
+ * `Suspense` fallback.
9
+ *
10
+ * Same reasoning as `scripts-table-columns` on the scripts pages: a loading
11
+ * state that RE-DECLARES the chrome it stands in for drifts from it, silently,
12
+ * and only in the frame nobody screenshots. Reading one declaration is what
13
+ * makes the two identical by construction rather than by review.
14
+ */
15
+
16
+ /** The table/grid switch. Fed by the `viewMode` URL param, so it needs no data. */
17
+ export const DEVICE_VIEW_MODE_ITEMS = [
18
+ { id: 'table', icon: <TableCellIcon className="h-6 w-6" /> },
19
+ { id: 'grid', icon: <GridIcon className="h-6 w-6" /> },
20
+ ];
21
+
22
+ export interface DevicePanelActionsOptions {
23
+ /** Shows the "Archive" button linking to the archived-devices page. */
24
+ archiveHref?: string;
25
+ showAddDevice?: boolean;
26
+ noOrganizations?: boolean;
27
+ /** Destination of the "Add Customer" button shown when the tenant has no customers. */
28
+ addCustomerHref?: string;
29
+ isCheckingOrganizations?: boolean;
30
+ /**
31
+ * Accent the "Add Device" button, the panel's pristine-empty state, which is
32
+ * the ONE thing here that needs the list to have answered. Left off while
33
+ * loading: it changes the button's colour, never its size, so the header does
34
+ * not move when the real answer lands.
35
+ */
36
+ accent?: boolean;
37
+ onAddDevice?: () => void;
38
+ /**
39
+ * Loading. Every button the loaded header will have is still rendered, same
40
+ * labels, same icons, same widths, but inert and without its destination, so
41
+ * the header is pixel-identical and nothing is clickable before the panel can
42
+ * honour the click.
43
+ */
44
+ disabled?: boolean;
45
+ }
46
+
47
+ /**
48
+ * The panel's header buttons. Every input is a prop or a URL value, nothing
49
+ * here is derived from the device query, which is what lets the fallback build
50
+ * the same set the loaded panel will.
51
+ */
52
+ export function buildDevicePanelActions({
53
+ archiveHref,
54
+ showAddDevice = true,
55
+ noOrganizations = false,
56
+ addCustomerHref,
57
+ isCheckingOrganizations = false,
58
+ accent = false,
59
+ onAddDevice,
60
+ disabled = false,
61
+ }: DevicePanelActionsOptions): PageActionButton[] {
62
+ const result: PageActionButton[] = [];
63
+
64
+ if (archiveHref) {
65
+ result.push({
66
+ label: 'Archive',
67
+ // A disabled `href` still renders a live link, so the loading copy carries
68
+ // no destination at all rather than a navigable one it cannot honour.
69
+ ...(disabled ? { disabled: true } : { href: archiveHref }),
70
+ icon: <BoxArchiveIcon className="h-5 w-5 text-ods-text-secondary" />,
71
+ variant: 'outline',
72
+ });
73
+ }
74
+
75
+ if (!showAddDevice) return result;
76
+
77
+ // A device must belong to an organization. With none, "Add Device" is disabled
78
+ // and an "Add Customer" action appears beside it.
79
+ if (noOrganizations) {
80
+ result.push({
81
+ label: 'Add Customer',
82
+ ...(disabled || !addCustomerHref ? { disabled: true } : { href: addCustomerHref }),
83
+ icon: <PlusCircleIcon className="h-5 w-5 text-ods-text-secondary" />,
84
+ variant: 'outline',
85
+ });
86
+ }
87
+
88
+ result.push({
89
+ label: 'Add Device',
90
+ onClick: disabled ? undefined : onAddDevice,
91
+ disabled: disabled || noOrganizations || isCheckingOrganizations,
92
+ icon: <PlusCircleIcon className={`h-5 w-5 ${accent ? 'text-ods-text-on-accent' : 'text-ods-text-secondary'}`} />,
93
+ variant: accent ? 'accent' : 'outline',
94
+ });
95
+
96
+ return result;
97
+ }