@flamingo-stack/openframe-frontend-core 0.0.711 → 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 (523) 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-3UNL26CD.cjs → chunk-3RKBJT6K.cjs} +8 -6
  8. package/dist/{chunk-6GLQLTJI.js → chunk-3SEEGNRE.js} +35 -27
  9. package/dist/{chunk-FEMAJES4.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-2JTGK64G.js → chunk-4UYKNOZG.js} +12 -10
  14. package/dist/{chunk-TKZXHVBG.js → chunk-5SDELRH3.js} +5 -5
  15. package/dist/{chunk-Q6B35Y7O.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-WJUIXU6Y.js → chunk-7HNYYNKE.js} +28 -22
  19. package/dist/{chunk-P6G3JZNC.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-XWEBHS7O.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-G47AP6LX.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-NF7GNGYG.js → chunk-DDWFCWOE.js} +5 -7
  36. package/dist/{chunk-K4PTDK34.js → chunk-EFNKS5W4.js} +322 -428
  37. package/dist/{chunk-QA6TROME.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-5HB7FLCV.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-VWFZRMQR.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-AGDVEUVL.js → chunk-H5R7U2D2.js} +206 -5
  50. package/dist/{chunk-7AM6C6XH.cjs → chunk-HETQETPV.cjs} +9641 -9678
  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-C4HRRB3V.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-PRX7HVLE.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-FYOKS5RI.cjs → chunk-L6ZQGWCX.cjs} +4521 -6234
  65. package/dist/{chunk-PLYEKV3N.cjs → chunk-MA4Q5RBP.cjs} +6 -6
  66. package/dist/{chunk-VMMHJFHG.js → chunk-N67XG5GY.js} +10 -8
  67. package/dist/chunk-NPAQSMRY.js +2087 -0
  68. package/dist/{chunk-IFWLJ66M.js → chunk-NQWJAOHO.js} +6 -4
  69. package/dist/{chunk-6K7QZDA6.cjs → chunk-OBZJICEA.cjs} +8 -8
  70. package/dist/{chunk-62KNLDXK.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-EQWD4IJE.js → chunk-RBYVFPER.js} +74 -46
  75. package/dist/{chunk-SMAAV3HL.js → chunk-ROBQ5TR7.js} +10541 -10578
  76. package/dist/{chunk-K6Y5NX6L.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-EX6GGCAC.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-6AMIRXKM.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-QGZPZ3RL.js → chunk-YBS5QGON.js} +70 -128
  91. package/dist/{chunk-CDM7OSFB.cjs → chunk-Z5SWJW5Q.cjs} +125 -117
  92. package/dist/{chunk-YD4LJZV4.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/index.cjs +27 -8
  102. package/dist/components/chat/index.d.ts +1 -0
  103. package/dist/components/chat/index.d.ts.map +1 -1
  104. package/dist/components/chat/index.js +57 -38
  105. package/dist/components/chat/quick-action-chip.d.ts +7 -3
  106. package/dist/components/chat/quick-action-chip.d.ts.map +1 -1
  107. package/dist/components/contact/index.cjs +29 -13
  108. package/dist/components/contact/index.js +28 -12
  109. package/dist/components/docs/index.cjs +33 -16
  110. package/dist/components/docs/index.js +33 -16
  111. package/dist/components/docs/use-scroll-spy.d.ts +23 -1
  112. package/dist/components/docs/use-scroll-spy.d.ts.map +1 -1
  113. package/dist/components/embeds/index.cjs +29 -13
  114. package/dist/components/embeds/index.js +28 -12
  115. package/dist/components/faq/faq-section.d.ts +8 -1
  116. package/dist/components/faq/faq-section.d.ts.map +1 -1
  117. package/dist/components/faq/index.cjs +30 -14
  118. package/dist/components/faq/index.js +29 -13
  119. package/dist/components/features/array-entry-manager.d.ts +5 -1
  120. package/dist/components/features/array-entry-manager.d.ts.map +1 -1
  121. package/dist/components/features/board/board.d.ts +2 -0
  122. package/dist/components/features/board/board.d.ts.map +1 -1
  123. package/dist/components/features/board/ticket-card.d.ts.map +1 -1
  124. package/dist/components/features/board/touch-board.d.ts +1 -1
  125. package/dist/components/features/board/touch-board.d.ts.map +1 -1
  126. package/dist/components/features/board/types.d.ts +3 -0
  127. package/dist/components/features/board/types.d.ts.map +1 -1
  128. package/dist/components/features/board/use-board-collapse.d.ts +6 -1
  129. package/dist/components/features/board/use-board-collapse.d.ts.map +1 -1
  130. package/dist/components/features/capability-explorer.d.ts +94 -0
  131. package/dist/components/features/capability-explorer.d.ts.map +1 -0
  132. package/dist/components/features/cloud-tenants/index.d.ts +14 -0
  133. package/dist/components/features/cloud-tenants/index.d.ts.map +1 -0
  134. package/dist/components/features/cloud-tenants/tenant-access-cell.d.ts +9 -0
  135. package/dist/components/features/cloud-tenants/tenant-access-cell.d.ts.map +1 -0
  136. package/dist/components/features/cloud-tenants/tenant-cell.d.ts +8 -0
  137. package/dist/components/features/cloud-tenants/tenant-cell.d.ts.map +1 -0
  138. package/dist/components/features/cloud-tenants/tenant-customer-cell.d.ts +9 -0
  139. package/dist/components/features/cloud-tenants/tenant-customer-cell.d.ts.map +1 -0
  140. package/dist/components/features/cloud-tenants/tenant-presentation.d.ts +42 -0
  141. package/dist/components/features/cloud-tenants/tenant-presentation.d.ts.map +1 -0
  142. package/dist/components/features/cloud-tenants/tenant-row.d.ts +22 -0
  143. package/dist/components/features/cloud-tenants/tenant-row.d.ts.map +1 -0
  144. package/dist/components/features/cloud-tenants/tenants-table-columns.d.ts +42 -0
  145. package/dist/components/features/cloud-tenants/tenants-table-columns.d.ts.map +1 -0
  146. package/dist/components/features/cloud-tenants/tenants-table-view.d.ts +26 -0
  147. package/dist/components/features/cloud-tenants/tenants-table-view.d.ts.map +1 -0
  148. package/dist/components/features/devices/device-last-online.d.ts +3 -0
  149. package/dist/components/features/devices/device-last-online.d.ts.map +1 -0
  150. package/dist/components/features/devices/device-name.d.ts +42 -0
  151. package/dist/components/features/devices/device-name.d.ts.map +1 -0
  152. package/dist/components/features/devices/device-selector/device-selection-mode-radio.d.ts +26 -0
  153. package/dist/components/features/devices/device-selector/device-selection-mode-radio.d.ts.map +1 -0
  154. package/dist/components/features/devices/device-selector/device-selector-skeleton.d.ts +25 -0
  155. package/dist/components/features/devices/device-selector/device-selector-skeleton.d.ts.map +1 -0
  156. package/dist/components/features/devices/device-selector/device-selector.d.ts +38 -0
  157. package/dist/components/features/devices/device-selector/device-selector.d.ts.map +1 -0
  158. package/dist/components/features/devices/device-selector/device-selector.types.d.ts +133 -0
  159. package/dist/components/features/devices/device-selector/device-selector.types.d.ts.map +1 -0
  160. package/dist/components/features/devices/device-selector/narrowing.d.ts +13 -0
  161. package/dist/components/features/devices/device-selector/narrowing.d.ts.map +1 -0
  162. package/dist/components/features/devices/device-selector/use-device-selector.d.ts +17 -0
  163. package/dist/components/features/devices/device-selector/use-device-selector.d.ts.map +1 -0
  164. package/dist/components/features/devices/device-status.d.ts +23 -0
  165. package/dist/components/features/devices/device-status.d.ts.map +1 -0
  166. package/dist/components/features/devices/device-statuses.d.ts +40 -0
  167. package/dist/components/features/devices/device-statuses.d.ts.map +1 -0
  168. package/dist/components/features/devices/device-tags-filter-button.d.ts +22 -0
  169. package/dist/components/features/devices/device-tags-filter-button.d.ts.map +1 -0
  170. package/dist/components/features/devices/device-type-icon.d.ts +11 -0
  171. package/dist/components/features/devices/device-type-icon.d.ts.map +1 -0
  172. package/dist/components/features/devices/device-type-tile.d.ts +9 -0
  173. package/dist/components/features/devices/device-type-tile.d.ts.map +1 -0
  174. package/dist/components/features/devices/devices-filter-toolbar.d.ts +46 -0
  175. package/dist/components/features/devices/devices-filter-toolbar.d.ts.map +1 -0
  176. package/dist/components/features/devices/devices-grid-filters.d.ts +25 -0
  177. package/dist/components/features/devices/devices-grid-filters.d.ts.map +1 -0
  178. package/dist/components/features/devices/devices-grid.d.ts +12 -0
  179. package/dist/components/features/devices/devices-grid.d.ts.map +1 -0
  180. package/dist/components/features/devices/devices-list.d.ts +131 -0
  181. package/dist/components/features/devices/devices-list.d.ts.map +1 -0
  182. package/dist/components/features/devices/devices-panel-header.d.ts +46 -0
  183. package/dist/components/features/devices/devices-panel-header.d.ts.map +1 -0
  184. package/dist/components/features/devices/devices-panel-view.d.ts +79 -0
  185. package/dist/components/features/devices/devices-panel-view.d.ts.map +1 -0
  186. package/dist/components/features/devices/devices-table-columns.d.ts +76 -0
  187. package/dist/components/features/devices/devices-table-columns.d.ts.map +1 -0
  188. package/dist/components/features/devices/devices-view-config.d.ts +25 -0
  189. package/dist/components/features/devices/devices-view-config.d.ts.map +1 -0
  190. package/dist/components/features/devices/index.d.ts +24 -0
  191. package/dist/components/features/devices/index.d.ts.map +1 -0
  192. package/dist/components/features/devices/types.d.ts +68 -0
  193. package/dist/components/features/devices/types.d.ts.map +1 -0
  194. package/dist/components/features/devices/use-tag-filter-modal.d.ts +50 -0
  195. package/dist/components/features/devices/use-tag-filter-modal.d.ts.map +1 -0
  196. package/dist/components/features/index.cjs +227 -12
  197. package/dist/components/features/index.d.ts +7 -0
  198. package/dist/components/features/index.d.ts.map +1 -1
  199. package/dist/components/features/index.js +266 -51
  200. package/dist/components/features/knowledge-base/index.d.ts +7 -0
  201. package/dist/components/features/knowledge-base/index.d.ts.map +1 -0
  202. package/dist/components/features/knowledge-base/knowledge-base-article-view.d.ts +44 -0
  203. package/dist/components/features/knowledge-base/knowledge-base-article-view.d.ts.map +1 -0
  204. package/dist/components/features/knowledge-base/knowledge-base-item-icon.d.ts +13 -0
  205. package/dist/components/features/knowledge-base/knowledge-base-item-icon.d.ts.map +1 -0
  206. package/dist/components/features/knowledge-base/knowledge-base-status.d.ts +8 -0
  207. package/dist/components/features/knowledge-base/knowledge-base-status.d.ts.map +1 -0
  208. package/dist/components/features/knowledge-base/knowledge-base-table.d.ts +52 -0
  209. package/dist/components/features/knowledge-base/knowledge-base-table.d.ts.map +1 -0
  210. package/dist/components/features/logs/index.d.ts +12 -0
  211. package/dist/components/features/logs/index.d.ts.map +1 -0
  212. package/dist/components/features/logs/log-drawer.d.ts +29 -0
  213. package/dist/components/features/logs/log-drawer.d.ts.map +1 -0
  214. package/dist/components/features/logs/log-source-labels.d.ts +11 -0
  215. package/dist/components/features/logs/log-source-labels.d.ts.map +1 -0
  216. package/dist/components/features/logs/logs-page-view.d.ts +32 -0
  217. package/dist/components/features/logs/logs-page-view.d.ts.map +1 -0
  218. package/dist/components/features/logs/logs-table-columns.d.ts +15 -0
  219. package/dist/components/features/logs/logs-table-columns.d.ts.map +1 -0
  220. package/dist/components/features/logs/logs-table-view.d.ts +64 -0
  221. package/dist/components/features/logs/logs-table-view.d.ts.map +1 -0
  222. package/dist/components/features/logs/types.d.ts +52 -0
  223. package/dist/components/features/logs/types.d.ts.map +1 -0
  224. package/dist/components/features/policies/compute-policy-summary.d.ts +37 -0
  225. package/dist/components/features/policies/compute-policy-summary.d.ts.map +1 -0
  226. package/dist/components/features/policies/index.d.ts +8 -0
  227. package/dist/components/features/policies/index.d.ts.map +1 -0
  228. package/dist/components/features/policies/policies-table.d.ts +34 -0
  229. package/dist/components/features/policies/policies-table.d.ts.map +1 -0
  230. package/dist/components/features/policies/policy-summary-cards.d.ts +17 -0
  231. package/dist/components/features/policies/policy-summary-cards.d.ts.map +1 -0
  232. package/dist/components/features/policies/policy-table-row.d.ts +37 -0
  233. package/dist/components/features/policies/policy-table-row.d.ts.map +1 -0
  234. package/dist/components/features/remote-session/index.d.ts +8 -0
  235. package/dist/components/features/remote-session/index.d.ts.map +1 -1
  236. package/dist/components/features/remote-session/remote-desktop-chat-message-row.d.ts +21 -0
  237. package/dist/components/features/remote-session/remote-desktop-chat-message-row.d.ts.map +1 -0
  238. package/dist/components/features/remote-session/remote-desktop-chat-panel.d.ts +31 -0
  239. package/dist/components/features/remote-session/remote-desktop-chat-panel.d.ts.map +1 -0
  240. package/dist/components/features/remote-session/remote-desktop-fullscreen-toolbar.d.ts +21 -0
  241. package/dist/components/features/remote-session/remote-desktop-fullscreen-toolbar.d.ts.map +1 -0
  242. package/dist/components/features/remote-session/remote-desktop-view.d.ts +50 -0
  243. package/dist/components/features/remote-session/remote-desktop-view.d.ts.map +1 -0
  244. package/dist/components/features/software/index.d.ts +8 -0
  245. package/dist/components/features/software/index.d.ts.map +1 -0
  246. package/dist/components/features/software/package-managers.d.ts +30 -0
  247. package/dist/components/features/software/package-managers.d.ts.map +1 -0
  248. package/dist/components/features/software/package-search-field-placeholder.d.ts +7 -0
  249. package/dist/components/features/software/package-search-field-placeholder.d.ts.map +1 -0
  250. package/dist/components/features/software/schedule-fields.d.ts +34 -0
  251. package/dist/components/features/software/schedule-fields.d.ts.map +1 -0
  252. package/dist/components/features/software/software-action-copy.d.ts +25 -0
  253. package/dist/components/features/software/software-action-copy.d.ts.map +1 -0
  254. package/dist/components/features/software/software-action-form.d.ts +71 -0
  255. package/dist/components/features/software/software-action-form.d.ts.map +1 -0
  256. package/dist/components/features/software/software-row-fields.d.ts +23 -0
  257. package/dist/components/features/software/software-row-fields.d.ts.map +1 -0
  258. package/dist/components/features/software/software-row.d.ts +18 -0
  259. package/dist/components/features/software/software-row.d.ts.map +1 -0
  260. package/dist/components/features/sortable-list/index.d.ts +1 -0
  261. package/dist/components/features/sortable-list/index.d.ts.map +1 -1
  262. package/dist/components/features/sortable-list/sortable-drag-handle.d.ts +21 -0
  263. package/dist/components/features/sortable-list/sortable-drag-handle.d.ts.map +1 -0
  264. package/dist/components/help-center-pages/index.cjs +133 -114
  265. package/dist/components/help-center-pages/index.js +58 -39
  266. package/dist/components/index.cjs +320 -82
  267. package/dist/components/index.js +451 -213
  268. package/dist/components/layout/page-heading.d.ts +12 -3
  269. package/dist/components/layout/page-heading.d.ts.map +1 -1
  270. package/dist/components/meeting-scheduler/index.cjs +120 -98
  271. package/dist/components/meeting-scheduler/index.js +50 -28
  272. package/dist/components/navigation/index.cjs +36 -17
  273. package/dist/components/navigation/index.d.ts +3 -0
  274. package/dist/components/navigation/index.d.ts.map +1 -1
  275. package/dist/components/navigation/index.js +36 -17
  276. package/dist/components/navigation/mingo-ai-button.d.ts +23 -10
  277. package/dist/components/navigation/mingo-ai-button.d.ts.map +1 -1
  278. package/dist/components/navigation/sticky-section-nav.d.ts +14 -1
  279. package/dist/components/navigation/sticky-section-nav.d.ts.map +1 -1
  280. package/dist/components/onboarding-guides/index.cjs +32 -16
  281. package/dist/components/onboarding-guides/index.js +31 -15
  282. package/dist/components/product-demo/cast.d.ts +58 -0
  283. package/dist/components/product-demo/cast.d.ts.map +1 -0
  284. package/dist/components/product-demo/fixtures/cloud-tenants.d.ts +10 -0
  285. package/dist/components/product-demo/fixtures/cloud-tenants.d.ts.map +1 -0
  286. package/dist/components/product-demo/fixtures/devices.d.ts +14 -0
  287. package/dist/components/product-demo/fixtures/devices.d.ts.map +1 -0
  288. package/dist/components/product-demo/fixtures/knowledge.d.ts +14 -0
  289. package/dist/components/product-demo/fixtures/knowledge.d.ts.map +1 -0
  290. package/dist/components/product-demo/fixtures/logs.d.ts +15 -0
  291. package/dist/components/product-demo/fixtures/logs.d.ts.map +1 -0
  292. package/dist/components/product-demo/fixtures/policies.d.ts +13 -0
  293. package/dist/components/product-demo/fixtures/policies.d.ts.map +1 -0
  294. package/dist/components/product-demo/fixtures/remote-session.d.ts +20 -0
  295. package/dist/components/product-demo/fixtures/remote-session.d.ts.map +1 -0
  296. package/dist/components/product-demo/fixtures/shared.d.ts +156 -0
  297. package/dist/components/product-demo/fixtures/shared.d.ts.map +1 -0
  298. package/dist/components/product-demo/fixtures/software-update.d.ts +19 -0
  299. package/dist/components/product-demo/fixtures/software-update.d.ts.map +1 -0
  300. package/dist/components/product-demo/fixtures/tickets-board.d.ts +8 -0
  301. package/dist/components/product-demo/fixtures/tickets-board.d.ts.map +1 -0
  302. package/dist/components/product-demo/index.cjs +112 -0
  303. package/dist/components/product-demo/index.d.ts +6 -0
  304. package/dist/components/product-demo/index.d.ts.map +1 -0
  305. package/dist/components/product-demo/index.js +112 -0
  306. package/dist/components/product-demo/product-screen.d.ts +22 -0
  307. package/dist/components/product-demo/product-screen.d.ts.map +1 -0
  308. package/dist/components/product-demo/registry.d.ts +13 -0
  309. package/dist/components/product-demo/registry.d.ts.map +1 -0
  310. package/dist/components/product-demo/screen-keys.cjs +25 -0
  311. package/dist/components/product-demo/screen-keys.d.ts +27 -0
  312. package/dist/components/product-demo/screen-keys.d.ts.map +1 -0
  313. package/dist/components/product-demo/screen-keys.js +20 -0
  314. package/dist/components/product-demo/screens/cloud-tenants.d.ts +8 -0
  315. package/dist/components/product-demo/screens/cloud-tenants.d.ts.map +1 -0
  316. package/dist/components/product-demo/screens/devices.d.ts +10 -0
  317. package/dist/components/product-demo/screens/devices.d.ts.map +1 -0
  318. package/dist/components/product-demo/screens/knowledge.d.ts +9 -0
  319. package/dist/components/product-demo/screens/knowledge.d.ts.map +1 -0
  320. package/dist/components/product-demo/screens/logs.d.ts +4 -0
  321. package/dist/components/product-demo/screens/logs.d.ts.map +1 -0
  322. package/dist/components/product-demo/screens/policies.d.ts +8 -0
  323. package/dist/components/product-demo/screens/policies.d.ts.map +1 -0
  324. package/dist/components/product-demo/screens/remote-desktop-picture.d.ts +11 -0
  325. package/dist/components/product-demo/screens/remote-desktop-picture.d.ts.map +1 -0
  326. package/dist/components/product-demo/screens/remote-session.d.ts +8 -0
  327. package/dist/components/product-demo/screens/remote-session.d.ts.map +1 -0
  328. package/dist/components/product-demo/screens/software-update.d.ts +12 -0
  329. package/dist/components/product-demo/screens/software-update.d.ts.map +1 -0
  330. package/dist/components/product-demo/screens/tickets-board.d.ts +4 -0
  331. package/dist/components/product-demo/screens/tickets-board.d.ts.map +1 -0
  332. package/dist/components/product-demo/types.d.ts +9 -0
  333. package/dist/components/product-demo/types.d.ts.map +1 -0
  334. package/dist/components/related-content/index.cjs +14 -8
  335. package/dist/components/related-content/index.js +13 -7
  336. package/dist/components/tickets/index.cjs +36 -20
  337. package/dist/components/tickets/index.js +35 -19
  338. package/dist/components/ui/file-manager/index.cjs +38 -34
  339. package/dist/components/ui/file-manager/index.js +8 -4
  340. package/dist/components/ui/index.cjs +57 -17
  341. package/dist/components/ui/index.d.ts +1 -0
  342. package/dist/components/ui/index.d.ts.map +1 -1
  343. package/dist/components/ui/index.js +141 -101
  344. package/dist/components/ui/product-screen-frame.d.ts +45 -0
  345. package/dist/components/ui/product-screen-frame.d.ts.map +1 -0
  346. package/dist/components/ui/radio-group.d.ts +5 -0
  347. package/dist/components/ui/radio-group.d.ts.map +1 -1
  348. package/dist/components/ui/snap-carousel.d.ts +11 -1
  349. package/dist/components/ui/snap-carousel.d.ts.map +1 -1
  350. package/dist/components/ui/tag.d.ts +1 -1
  351. package/dist/components/ui/tag.d.ts.map +1 -1
  352. package/dist/devices-LBMG42K6.js +81 -0
  353. package/dist/devices-YGYJIXQY.cjs +81 -0
  354. package/dist/hooks/index.cjs +17 -8
  355. package/dist/hooks/index.js +32 -23
  356. package/dist/hooks/ui/index.d.ts +1 -0
  357. package/dist/hooks/ui/index.d.ts.map +1 -1
  358. package/dist/hooks/ui/use-header-height.d.ts +12 -0
  359. package/dist/hooks/ui/use-header-height.d.ts.map +1 -1
  360. package/dist/hooks/ui/use-sticky-toolbar.d.ts +29 -0
  361. package/dist/hooks/ui/use-sticky-toolbar.d.ts.map +1 -0
  362. package/dist/hooks/use-location-hash.d.ts +2 -2
  363. package/dist/hooks/use-location-hash.d.ts.map +1 -1
  364. package/dist/hooks/use-scroll-to-hash.d.ts +7 -0
  365. package/dist/hooks/use-scroll-to-hash.d.ts.map +1 -1
  366. package/dist/index.cjs +276 -25
  367. package/dist/index.js +729 -478
  368. package/dist/knowledge-H5BIWJVI.js +108 -0
  369. package/dist/knowledge-KTCVJIWN.cjs +108 -0
  370. package/dist/logs-DB5Z7M5Q.js +216 -0
  371. package/dist/logs-RVCC2UQW.cjs +216 -0
  372. package/dist/policies-EWUULFBR.js +121 -0
  373. package/dist/policies-HV4IQCBV.cjs +121 -0
  374. package/dist/remote-session-GSGZOFDX.js +196 -0
  375. package/dist/remote-session-R6VAFESR.cjs +196 -0
  376. package/dist/software-update-6PXKRKBT.js +179 -0
  377. package/dist/software-update-D4OVSWSG.cjs +179 -0
  378. package/dist/tickets-board-BHLPAVNJ.cjs +137 -0
  379. package/dist/tickets-board-PYDNELSK.js +137 -0
  380. package/dist/types/case-study.d.ts +15 -1
  381. package/dist/types/case-study.d.ts.map +1 -1
  382. package/dist/utils/date-utils.d.ts +5 -0
  383. package/dist/utils/date-utils.d.ts.map +1 -1
  384. package/dist/utils/index.cjs +45 -2
  385. package/dist/utils/index.d.ts +2 -1
  386. package/dist/utils/index.d.ts.map +1 -1
  387. package/dist/utils/index.js +41 -3
  388. package/dist/utils/open-in-new-tab.d.ts +7 -0
  389. package/dist/utils/open-in-new-tab.d.ts.map +1 -0
  390. package/dist/utils/same-page-hash-nav.d.ts +31 -0
  391. package/dist/utils/same-page-hash-nav.d.ts.map +1 -1
  392. package/dist/utils/scroll-into-view.d.ts +14 -1
  393. package/dist/utils/scroll-into-view.d.ts.map +1 -1
  394. package/package.json +13 -1
  395. package/src/components/chat/ask-prompts.tsx +226 -0
  396. package/src/components/chat/embeddable-chat.tsx +36 -2
  397. package/src/components/chat/entity-cards/case-study-card.tsx +122 -46
  398. package/src/components/chat/index.ts +1 -0
  399. package/src/components/chat/quick-action-chip.tsx +33 -9
  400. package/src/components/docs/use-scroll-spy.ts +93 -18
  401. package/src/components/faq/faq-section.tsx +82 -43
  402. package/src/components/features/array-entry-manager.tsx +10 -1
  403. package/src/components/features/board/board.tsx +4 -1
  404. package/src/components/features/board/ticket-card.tsx +11 -1
  405. package/src/components/features/board/touch-board.tsx +2 -1
  406. package/src/components/features/board/types.ts +3 -0
  407. package/src/components/features/board/use-board-collapse.ts +7 -2
  408. package/src/components/features/capability-explorer.tsx +412 -0
  409. package/src/components/features/cloud-tenants/index.ts +28 -0
  410. package/src/components/features/cloud-tenants/tenant-access-cell.tsx +24 -0
  411. package/src/components/features/cloud-tenants/tenant-cell.tsx +26 -0
  412. package/src/components/features/cloud-tenants/tenant-customer-cell.tsx +27 -0
  413. package/src/components/features/cloud-tenants/tenant-presentation.ts +111 -0
  414. package/src/components/features/cloud-tenants/tenant-row.ts +21 -0
  415. package/src/components/features/cloud-tenants/tenants-table-columns.ts +30 -0
  416. package/src/components/features/cloud-tenants/tenants-table-view.tsx +142 -0
  417. package/src/components/features/devices/device-last-online.ts +6 -0
  418. package/src/components/features/devices/device-name.ts +51 -0
  419. package/src/components/features/devices/device-selector/device-selection-mode-radio.tsx +107 -0
  420. package/src/components/features/devices/device-selector/device-selector-skeleton.tsx +32 -0
  421. package/src/components/features/devices/device-selector/device-selector.tsx +799 -0
  422. package/src/components/features/devices/device-selector/device-selector.types.ts +138 -0
  423. package/src/components/features/devices/device-selector/narrowing.ts +33 -0
  424. package/src/components/features/devices/device-selector/use-device-selector.ts +51 -0
  425. package/src/components/features/devices/device-status.ts +102 -0
  426. package/src/components/features/devices/device-statuses.ts +88 -0
  427. package/src/components/features/devices/device-tags-filter-button.tsx +49 -0
  428. package/src/components/features/devices/device-type-icon.tsx +29 -0
  429. package/src/components/features/devices/device-type-tile.tsx +17 -0
  430. package/src/components/features/devices/devices-filter-toolbar.tsx +114 -0
  431. package/src/components/features/devices/devices-grid-filters.tsx +99 -0
  432. package/src/components/features/devices/devices-grid.tsx +86 -0
  433. package/src/components/features/devices/devices-list.tsx +357 -0
  434. package/src/components/features/devices/devices-panel-header.tsx +97 -0
  435. package/src/components/features/devices/devices-panel-view.tsx +261 -0
  436. package/src/components/features/devices/devices-table-columns.tsx +356 -0
  437. package/src/components/features/devices/devices-view-config.tsx +38 -0
  438. package/src/components/features/devices/index.ts +89 -0
  439. package/src/components/features/devices/types.ts +74 -0
  440. package/src/components/features/devices/use-tag-filter-modal.ts +109 -0
  441. package/src/components/features/index.ts +9 -0
  442. package/src/components/features/knowledge-base/index.ts +19 -0
  443. package/src/components/features/knowledge-base/knowledge-base-article-view.tsx +134 -0
  444. package/src/components/features/knowledge-base/knowledge-base-item-icon.ts +14 -0
  445. package/src/components/features/knowledge-base/knowledge-base-status.ts +12 -0
  446. package/src/components/features/knowledge-base/knowledge-base-table.tsx +180 -0
  447. package/src/components/features/logs/index.ts +20 -0
  448. package/src/components/features/logs/log-drawer.tsx +138 -0
  449. package/src/components/features/logs/log-source-labels.ts +25 -0
  450. package/src/components/features/logs/logs-page-view.tsx +100 -0
  451. package/src/components/features/logs/logs-table-columns.ts +16 -0
  452. package/src/components/features/logs/logs-table-view.tsx +509 -0
  453. package/src/components/features/logs/types.ts +71 -0
  454. package/src/components/features/policies/compute-policy-summary.ts +115 -0
  455. package/src/components/features/policies/index.ts +14 -0
  456. package/src/components/features/policies/policies-table.tsx +235 -0
  457. package/src/components/features/policies/policy-summary-cards.tsx +69 -0
  458. package/src/components/features/policies/policy-table-row.ts +37 -0
  459. package/src/components/features/remote-session/index.ts +8 -0
  460. package/src/components/features/remote-session/remote-desktop-chat-message-row.tsx +56 -0
  461. package/src/components/features/remote-session/remote-desktop-chat-panel.tsx +102 -0
  462. package/src/components/features/remote-session/remote-desktop-fullscreen-toolbar.tsx +119 -0
  463. package/src/components/features/remote-session/remote-desktop-view.tsx +209 -0
  464. package/src/components/features/software/index.ts +39 -0
  465. package/src/components/features/software/package-managers.ts +54 -0
  466. package/src/components/features/software/package-search-field-placeholder.tsx +23 -0
  467. package/src/components/features/software/schedule-fields.tsx +105 -0
  468. package/src/components/features/software/software-action-copy.ts +70 -0
  469. package/src/components/features/software/software-action-form.tsx +199 -0
  470. package/src/components/features/software/software-row-fields.tsx +105 -0
  471. package/src/components/features/software/software-row.ts +22 -0
  472. package/src/components/features/sortable-list/index.ts +1 -0
  473. package/src/components/features/sortable-list/sortable-drag-handle.tsx +41 -0
  474. package/src/components/layout/page-heading.tsx +23 -6
  475. package/src/components/navigation/index.ts +5 -0
  476. package/src/components/navigation/mingo-ai-button.tsx +37 -13
  477. package/src/components/navigation/sticky-section-nav.tsx +99 -1
  478. package/src/components/product-demo/cast.tsx +78 -0
  479. package/src/components/product-demo/fixtures/cloud-tenants.ts +63 -0
  480. package/src/components/product-demo/fixtures/devices.ts +87 -0
  481. package/src/components/product-demo/fixtures/knowledge.ts +48 -0
  482. package/src/components/product-demo/fixtures/logs.ts +103 -0
  483. package/src/components/product-demo/fixtures/policies.ts +77 -0
  484. package/src/components/product-demo/fixtures/remote-session.ts +65 -0
  485. package/src/components/product-demo/fixtures/shared.ts +53 -0
  486. package/src/components/product-demo/fixtures/software-update.ts +63 -0
  487. package/src/components/product-demo/fixtures/tickets-board.ts +100 -0
  488. package/src/components/product-demo/index.ts +7 -0
  489. package/src/components/product-demo/product-screen.tsx +94 -0
  490. package/src/components/product-demo/registry.ts +20 -0
  491. package/src/components/product-demo/screen-keys.ts +31 -0
  492. package/src/components/product-demo/screens/cloud-tenants.tsx +23 -0
  493. package/src/components/product-demo/screens/devices.tsx +41 -0
  494. package/src/components/product-demo/screens/knowledge.tsx +27 -0
  495. package/src/components/product-demo/screens/logs.tsx +113 -0
  496. package/src/components/product-demo/screens/policies.tsx +29 -0
  497. package/src/components/product-demo/screens/remote-desktop-picture.tsx +118 -0
  498. package/src/components/product-demo/screens/remote-session.tsx +46 -0
  499. package/src/components/product-demo/screens/software-update.tsx +97 -0
  500. package/src/components/product-demo/screens/tickets-board.tsx +28 -0
  501. package/src/components/product-demo/types.ts +10 -0
  502. package/src/components/ui/index.ts +1 -0
  503. package/src/components/ui/product-screen-frame.tsx +136 -0
  504. package/src/components/ui/radio-group.tsx +16 -4
  505. package/src/components/ui/snap-carousel.tsx +26 -1
  506. package/src/components/ui/tag.tsx +5 -0
  507. package/src/hooks/ui/index.ts +1 -0
  508. package/src/hooks/ui/use-header-height.ts +51 -2
  509. package/src/hooks/ui/use-sticky-toolbar.ts +60 -0
  510. package/src/hooks/use-location-hash.ts +9 -5
  511. package/src/hooks/use-scroll-to-hash.ts +9 -1
  512. package/src/types/case-study.ts +21 -1
  513. package/src/utils/date-utils.ts +8 -1
  514. package/src/utils/index.ts +5 -0
  515. package/src/utils/open-in-new-tab.ts +12 -0
  516. package/src/utils/same-page-hash-nav.ts +57 -0
  517. package/src/utils/scroll-into-view.ts +21 -5
  518. package/dist/chunk-BM5MVGH3.cjs +0 -499
  519. package/dist/chunk-CUME3VTQ.js +0 -144
  520. package/dist/chunk-CZ7Y7UG4.js +0 -732
  521. package/dist/chunk-FLKJYMVB.js +0 -499
  522. package/dist/chunk-OF6GEI5A.cjs +0 -144
  523. package/dist/chunk-UVTD52MD.cjs +0 -732
@@ -2,11 +2,20 @@
2
2
 
3
3
  import { useEffect, useState } from 'react';
4
4
 
5
+ /** The site header's own element (`SiteHeader`'s hook point). */
6
+ const SITE_HEADER_SELECTOR = '[data-site-header]';
7
+
5
8
  /**
6
9
  * Returns the combined height (px) of the sticky page header and announcement
7
10
  * bar (if present), updated live via ResizeObserver / MutationObserver.
8
11
  * Useful for offsetting fixed/absolute-positioned panels so they don't
9
12
  * overlap the header.
13
+ *
14
+ * With `stuckOnly` it answers a different question: where the header's bottom
15
+ * edge sits once the page has scrolled, the `top` of anything that sticks
16
+ * directly under it. That is the site header ALONE (the announcement bar
17
+ * scrolls away with the page, so adding it leaves a gap the content shows
18
+ * through), and 0 while the header has slid itself out of view.
10
19
  */
11
20
  export function useHeaderHeight(
12
21
  // First-paint fallback = the unified top-navigation `big` bar (72px), the
@@ -21,14 +30,54 @@ export function useHeaderHeight(
21
30
  * @default true
22
31
  */
23
32
  enabled?: boolean;
33
+ /**
34
+ * Measure only what stays stuck to the top of a scrolled page: the site
35
+ * header, without the announcement bar, and 0 while the header is hidden.
36
+ * @default false
37
+ */
38
+ stuckOnly?: boolean;
24
39
  } = {},
25
40
  ): number {
26
- const { enabled = true } = options;
41
+ const { enabled = true, stuckOnly = false } = options;
27
42
  const [height, setHeight] = useState(defaultHeight);
28
43
 
29
44
  useEffect(() => {
30
45
  if (!enabled) return undefined;
31
46
 
47
+ if (stuckOnly) {
48
+ let stop: (() => void) | undefined;
49
+ const watch = (header: HTMLElement) => {
50
+ // The header hides by translating itself up by its own height.
51
+ const measureStuck = () => setHeight(header.style.transform.includes('-100%') ? 0 : header.offsetHeight);
52
+ measureStuck();
53
+ const resize = new ResizeObserver(measureStuck);
54
+ resize.observe(header);
55
+ const mutation = new MutationObserver(measureStuck);
56
+ mutation.observe(header, { attributes: true, attributeFilter: ['style'] });
57
+ stop = () => {
58
+ resize.disconnect();
59
+ mutation.disconnect();
60
+ };
61
+ };
62
+ const present = document.querySelector<HTMLElement>(SITE_HEADER_SELECTOR);
63
+ if (present) {
64
+ watch(present);
65
+ return () => stop?.();
66
+ }
67
+ // A header that mounts after this hook: wait for it, then watch it.
68
+ const arrival = new MutationObserver(() => {
69
+ const header = document.querySelector<HTMLElement>(SITE_HEADER_SELECTOR);
70
+ if (!header) return;
71
+ arrival.disconnect();
72
+ watch(header);
73
+ });
74
+ arrival.observe(document.body, { childList: true, subtree: true });
75
+ return () => {
76
+ arrival.disconnect();
77
+ stop?.();
78
+ };
79
+ }
80
+
32
81
  const measure = () => {
33
82
  let total = 0;
34
83
  const header = document.querySelector('header');
@@ -66,7 +115,7 @@ export function useHeaderHeight(
66
115
  resizeObserver.disconnect();
67
116
  mutationObserver.disconnect();
68
117
  };
69
- }, [defaultHeight, enabled]);
118
+ }, [defaultHeight, enabled, stuckOnly]);
70
119
 
71
120
  return height;
72
121
  }
@@ -0,0 +1,60 @@
1
+ 'use client';
2
+
3
+ import { type CSSProperties, useCallback, useEffect, useState } from 'react';
4
+
5
+ interface StickyToolbar {
6
+ /** Attach to the sticky toolbar element whose height drives the table-header offset. */
7
+ toolbarRef: (node: HTMLDivElement | null) => void;
8
+ /** Apply to the element wrapping both the toolbar and the table; publishes the measured height. */
9
+ containerStyle: CSSProperties;
10
+ /** Pass to DataTable.Header's `stickyHeaderOffset` so it pins right below the toolbar. */
11
+ stickyHeaderOffset: string;
12
+ }
13
+
14
+ /**
15
+ * Keeps a sticky filter toolbar pinned above a sticky table header. (The page's
16
+ * OWN header and announcement bar are `useHeaderHeight`'s: that one reads the
17
+ * document's chrome; this one measures the toolbar element it is handed.)
18
+ *
19
+ * How: The toolbar
20
+ * height is measured (it changes as the single-row tag list appears or collapses)
21
+ * and published as `--sticky-toolbar-h` on the container, which the table header
22
+ * reads via `top-[var(--sticky-toolbar-h)]`, so the header always pins flush
23
+ * below the toolbar without a hard-coded offset.
24
+ *
25
+ * A CALLBACK ref, not a ref object: a toolbar can be conditionally rendered (a
26
+ * list with nothing in it hides its search box), and a plain `useRef` + mount
27
+ * effect would neither measure a toolbar that appears later nor zero the offset
28
+ * for one that goes away, the header would then pin below a strip that is no
29
+ * longer there.
30
+ */
31
+ export function useStickyToolbar(): StickyToolbar {
32
+ const [node, setNode] = useState<HTMLDivElement | null>(null);
33
+ const [height, setHeight] = useState(0);
34
+
35
+ const toolbarRef = useCallback((el: HTMLDivElement | null) => setNode(el), []);
36
+
37
+ // No toolbar mounted → no offset. Derived during render rather than in the
38
+ // effect: the effect's job is the ResizeObserver, and zeroing here means the
39
+ // header never pins below a strip that has already gone.
40
+ const [lastNode, setLastNode] = useState(node);
41
+ if (node !== lastNode) {
42
+ setLastNode(node);
43
+ if (!node) setHeight(0);
44
+ }
45
+
46
+ useEffect(() => {
47
+ if (!node) return undefined;
48
+ const update = () => setHeight(node.offsetHeight);
49
+ update();
50
+ const observer = new ResizeObserver(update);
51
+ observer.observe(node);
52
+ return () => observer.disconnect();
53
+ }, [node]);
54
+
55
+ return {
56
+ toolbarRef,
57
+ containerStyle: { '--sticky-toolbar-h': `${height}px` } as CSSProperties,
58
+ stickyHeaderOffset: 'top-[var(--sticky-toolbar-h)]',
59
+ };
60
+ }
@@ -1,10 +1,14 @@
1
1
  'use client';
2
2
 
3
3
  import { useSyncExternalStore } from 'react';
4
- import { normalizeHashFragment } from '../utils/same-page-hash-nav';
4
+ import { LOCATION_HASH_SYNC_EVENT, normalizeHashFragment } from '../utils/same-page-hash-nav';
5
5
 
6
- /** `navigateSamePageHash` dispatches `hashchange` itself; `popstate` covers back and forward. */
7
- const HASH_EVENTS = ['hashchange', 'popstate'] as const;
6
+ /**
7
+ * `navigateSamePageHash` dispatches `hashchange` itself; `popstate` covers back
8
+ * and forward; `replaceLocationHash` (a scroll spy, a tab naming itself)
9
+ * announces its silent writes with its own event.
10
+ */
11
+ const HASH_EVENTS = ['hashchange', 'popstate', LOCATION_HASH_SYNC_EVENT] as const;
8
12
 
9
13
  function subscribe(onChange: () => void): () => void {
10
14
  for (const event of HASH_EVENTS) window.addEventListener(event, onChange);
@@ -24,8 +28,8 @@ function readHash(): string {
24
28
 
25
29
  /**
26
30
  * The URL's hash without its `#`, or `''`: the READ side of same-page anchor
27
- * navigation (`navigateSamePageHash` writes it, `useScrollToHash` scrolls to
28
- * it). For a component whose state follows the anchor: a tab group that opens
31
+ * navigation (`navigateSamePageHash` and `replaceLocationHash` write it,
32
+ * `useScrollToHash` scrolls to it when it was a navigation). For a component whose state follows the anchor: a tab group that opens
29
33
  * the tab a link names. Empty on the server and during hydration (the server
30
34
  * never sees a hash), then the real one.
31
35
  */
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useEffect } from 'react';
4
- import { getHashTargetElement, normalizeHashFragment } from '../utils/same-page-hash-nav';
4
+ import { getHashTargetElement, isScrollSyncedHash, normalizeHashFragment } from '../utils/same-page-hash-nav';
5
5
  import { scrollElementIntoView } from '../utils/scroll-into-view';
6
6
 
7
7
  /** ~1s at 60fps — long enough to outlast Radix accordion expand + SWR
@@ -20,6 +20,13 @@ export interface UseScrollToHashOptions {
20
20
  * reference change AND on `hashchange` (browser back/forward + the
21
21
  * synthetic event `navigateSamePageHash` dispatches).
22
22
  *
23
+ * A hash the reader's own scrolling left in the URL (`replaceLocationHash`,
24
+ * written by a scroll spy with `syncHash`) is not a navigation: on a reload,
25
+ * and on back or forward to such an entry, the browser restores the exact
26
+ * scroll position, which that hash only mirrors, so it is left alone
27
+ * (`isScrollSyncedHash`). On a load the spy checks the restored position
28
+ * against the hash and scrolls only when they disagree.
29
+ *
23
30
  * Skipped when `readyDep == null || readyDep === false`. Default
24
31
  * `true` makes the hook run on mount for pages whose target is in the
25
32
  * initial SSR render.
@@ -37,6 +44,7 @@ export function useScrollToHash(readyDep: unknown = true, options?: UseScrollToH
37
44
  }
38
45
  };
39
46
  const tryScrollToHash = () => {
47
+ if (isScrollSyncedHash()) return;
40
48
  // `normalizeHashFragment` heals a malformed multi-fragment hash
41
49
  // so `getElementById` resolves on deep-link entries that bypass
42
50
  // `navigateSamePageHash`'s own normalize.
@@ -9,6 +9,15 @@ import type { MSP } from './stack';
9
9
  import type { UserProfile } from './user';
10
10
  import type { EntityQuote } from './video-processing';
11
11
 
12
+ /**
13
+ * One headline number of a story ("50%" / "of routine tasks automated"). A
14
+ * story carries at most three; a card shows the first, the story's page all.
15
+ */
16
+ export interface CaseStudyMetric {
17
+ value: string;
18
+ label: string;
19
+ }
20
+
12
21
  export interface CaseStudy {
13
22
  id: number;
14
23
  title: string;
@@ -24,6 +33,8 @@ export interface CaseStudy {
24
33
  challenge: string | null;
25
34
  solution: string | null;
26
35
  results: string | null;
36
+ /** Headline metrics (jsonb, at most three). Null or empty: the story has none. */
37
+ metrics?: CaseStudyMetric[] | null;
27
38
 
28
39
  // Testimonial video (text testimonials come from MSP profile)
29
40
  testimonial_video_url: string | null; // YouTube URL (preferred when both exist)
@@ -91,7 +102,12 @@ export type CaseStudyCardData = Pick<CaseStudy, 'id' | 'title' | 'summary' | 'fe
91
102
  Partial<
92
103
  Pick<
93
104
  CaseStudy,
94
- 'main_video_url' | 'main_video_thumbnail' | 'highlight_video_url' | 'highlight_video_thumbnail' | 'video_bites'
105
+ | 'main_video_url'
106
+ | 'main_video_thumbnail'
107
+ | 'highlight_video_url'
108
+ | 'highlight_video_thumbnail'
109
+ | 'video_bites'
110
+ | 'metrics'
95
111
  >
96
112
  > & {
97
113
  user?: Pick<UserProfile, 'full_name' | 'job_title'> & Partial<Pick<UserProfile, 'avatar_url'>>;
@@ -107,6 +123,8 @@ export interface CreateCaseStudyData {
107
123
  challenge?: string;
108
124
  solution?: string;
109
125
  results?: string;
126
+ /** Headline metrics, at most three. Null or an empty list clears them. */
127
+ metrics?: CaseStudyMetric[] | null;
110
128
  testimonial_video_url?: string; // YouTube URL
111
129
  main_video_url?: string; // Uploaded video file URL
112
130
  main_video_thumbnail?: string | null; // Manual poster image URL for testimonial video (standardized name across all video-bearing entities). Nullable so admin form can explicitly clear a stale poster from the DB when the testimonial video is removed or the source is switched to YouTube.
@@ -149,6 +167,8 @@ export interface CaseStudyFilters {
149
167
  company_size?: string; // Filtered from MSP profile data
150
168
  search?: string;
151
169
  featured?: boolean;
170
+ /** Only stories that carry at least one headline metric. */
171
+ withMetrics?: boolean;
152
172
  status?: string;
153
173
  limit?: number;
154
174
  offset?: number;
@@ -56,7 +56,14 @@ export function formatTicketFullTimestamp(iso: string): string {
56
56
  * formatRelativeTime(new Date()) // 'Just now'
57
57
  */
58
58
  export function formatRelativeTime(timestamp: string | Date): string {
59
- const now = new Date();
59
+ return formatRelativeTimeFrom(timestamp, new Date());
60
+ }
61
+
62
+ /**
63
+ * {@link formatRelativeTime} against a given "now": for a view that renders
64
+ * with a fixed clock (a product screen fed by a fixture, a test).
65
+ */
66
+ export function formatRelativeTimeFrom(timestamp: string | Date, now: Date): string {
60
67
  const targetTime = typeof timestamp === 'string' ? new Date(timestamp) : timestamp;
61
68
 
62
69
  // Validate the date
@@ -331,6 +331,7 @@ export * from './dev-sections';
331
331
  // pre-computed pixel value avoids the mid-animation jitter that
332
332
  // `element.scrollIntoView()` produces when layout shifts during the
333
333
  // scroll).
334
+ export { openInNewTab } from './open-in-new-tab';
334
335
  export { type ScrollElementIntoViewOptions, scrollElementIntoView } from './scroll-into-view';
335
336
 
336
337
  // Same-page hash navigation — owns pushState + synthetic hashchange +
@@ -338,8 +339,12 @@ export { type ScrollElementIntoViewOptions, scrollElementIntoView } from './scro
338
339
  // hub's `useUnifiedNav` + chat-runtime `navigate`, AND by every
339
340
  // embeddable surface that drives state off the URL hash.
340
341
  export {
342
+ ACTIVE_ANCHOR_ATTRIBUTE,
343
+ isScrollSyncedHash,
344
+ LOCATION_HASH_SYNC_EVENT,
341
345
  navigateSamePageHash,
342
346
  normalizeHashFragment,
347
+ replaceLocationHash,
343
348
  STICKY_HEADER_OFFSET_PX,
344
349
  HUB_HEADER_OFFSET_PX,
345
350
  type NavigateSamePageHashOptions,
@@ -0,0 +1,12 @@
1
+ import type { MouseEvent } from 'react';
2
+
3
+ /**
4
+ * A click handler that opens `href` in a new tab and does nothing else: the
5
+ * "open in new tab" cell of a table whose rows are links themselves.
6
+ */
7
+ export function openInNewTab(href: string) {
8
+ return (event: MouseEvent) => {
9
+ event.preventDefault();
10
+ window.open(href, '_blank', 'noopener,noreferrer');
11
+ };
12
+ }
@@ -63,6 +63,63 @@ export function getHashTargetElement(id: string): HTMLElement | null {
63
63
  return findAnchorElementByNormalizedId(decoded, document);
64
64
  }
65
65
 
66
+ /**
67
+ * Fired on `window` after {@link replaceLocationHash} changed the hash. NOT
68
+ * `hashchange`: a listener of this event follows the hash as STATE (which tab
69
+ * is open, `useLocationHash`); a listener of `hashchange` treats it as a
70
+ * NAVIGATION and scrolls (`useScrollToHash`). A scroll spy that keeps the URL
71
+ * on the section being read must reach the first and never the second.
72
+ */
73
+ export const LOCATION_HASH_SYNC_EVENT = 'locationhashsync';
74
+
75
+ /** Marks, on an element inside a section, the child anchor a scroll spy writes for that section (see `useScrollSpy`). */
76
+ export const ACTIVE_ANCHOR_ATTRIBUTE = 'data-active-anchor';
77
+
78
+ /** The key, in the history entry's state, of the hash {@link replaceLocationHash} last gave that entry. */
79
+ const HASH_SYNC_STATE_KEY = '__hashSync';
80
+
81
+ const isRecord = (value: unknown): value is Record<string, unknown> => typeof value === 'object' && value !== null;
82
+
83
+ /**
84
+ * Point the URL's hash at `id` (or clear it) to say where the reader IS, as
85
+ * opposed to sending them somewhere: no history entry (`replaceState`), no
86
+ * `hashchange`, no scroll. THE writer for a scroll spy's hash and for a tab
87
+ * that names itself in the URL. State followers hear
88
+ * {@link LOCATION_HASH_SYNC_EVENT}.
89
+ *
90
+ * The hash is also noted in the history ENTRY's state (beside whatever the
91
+ * host router keeps there), which survives a reload and comes back on back
92
+ * and forward: {@link isScrollSyncedHash}. For such an entry the hash only
93
+ * mirrors a scroll position the browser restores by itself, so
94
+ * `useScrollToHash` does not scroll to it again. Any navigation writes its own
95
+ * state and drops the note.
96
+ */
97
+ export function replaceLocationHash(id: string | null): void {
98
+ if (typeof window === 'undefined') return;
99
+ const { pathname, search, hash } = window.location;
100
+ const next = id ? `#${id}` : '';
101
+ const state: unknown = window.history.state;
102
+ const noted = isRecord(state) ? state[HASH_SYNC_STATE_KEY] : undefined;
103
+ if (hash === next && (noted === next || !next)) return;
104
+ window.history.replaceState(
105
+ { ...(isRecord(state) ? state : {}), [HASH_SYNC_STATE_KEY]: next },
106
+ '',
107
+ `${pathname}${search}${next}`,
108
+ );
109
+ if (hash !== next) window.dispatchEvent(new Event(LOCATION_HASH_SYNC_EVENT));
110
+ }
111
+
112
+ /**
113
+ * Whether the hash in the URL was put there by {@link replaceLocationHash}
114
+ * (the reader scrolled or opened a tab) rather than by a navigation. False
115
+ * with no hash, on a fresh visit, and once any navigation rewrote the entry.
116
+ */
117
+ export function isScrollSyncedHash(): boolean {
118
+ if (typeof window === 'undefined' || !window.location.hash) return false;
119
+ const state: unknown = window.history.state;
120
+ return isRecord(state) && state[HASH_SYNC_STATE_KEY] === window.location.hash;
121
+ }
122
+
66
123
  export interface NavigateSamePageHashOptions {
67
124
  /** Pixels to subtract for sticky chrome. */
68
125
  headerOffset?: number;
@@ -49,7 +49,9 @@
49
49
 
50
50
  export interface ScrollElementIntoViewOptions {
51
51
  /** Pixels to subtract from the target element's `top` so it lands BELOW
52
- * sticky chrome. Defaults to 0. Pass `96` for the standard hub header. */
52
+ * sticky chrome. Defaults to 0. Pass `96` for the standard hub header.
53
+ * A target that declares a larger `scroll-margin-top` in CSS wins: see
54
+ * {@link declaredScrollMarginTop}. */
53
55
  headerOffset?: number;
54
56
  /** `'smooth'` (default) runs the self-driven tween; `'instant'` / `'auto'`
55
57
  * jump in one synchronous write (deep-link land, programmatic focus moves). */
@@ -104,6 +106,21 @@ export function getScrollableAncestor(el: HTMLElement): HTMLElement | null {
104
106
  return null;
105
107
  }
106
108
 
109
+ /**
110
+ * The offset the target ITSELF declares in CSS (`scroll-margin-top`), in px.
111
+ *
112
+ * A page with more sticky chrome than the standard header (a second bar under
113
+ * it) says so on its anchors with `scroll-margin-top`, which is what a native
114
+ * anchor jump (a URL that loads with the hash, the router's own hash scroll)
115
+ * honours. The tween honours the same declaration, so a link clicked on the
116
+ * page and a link that loads the page land on the same pixel: the caller's
117
+ * `headerOffset` is the floor, the anchor's own margin wins when it is larger.
118
+ */
119
+ export function declaredScrollMarginTop(target: HTMLElement): number {
120
+ const margin = Number.parseFloat(getComputedStyle(target).scrollMarginTop);
121
+ return Number.isFinite(margin) ? margin : 0;
122
+ }
123
+
107
124
  /**
108
125
  * Scroll the page so `target` lands at the top of the viewport (below sticky
109
126
  * chrome via `headerOffset`). SSR-safe; `null`/`undefined` target is a no-op so
@@ -130,11 +147,10 @@ export function scrollElementIntoView(
130
147
  // the page reflows (a sibling drawer collapsing) and the reachable max grows
131
148
  // as the just-opened drawer expands. Clamp to the LIVE max each frame.
132
149
  const computeTarget = (): number => {
150
+ const offset = Math.max(headerOffset, declaredScrollMarginTop(target));
133
151
  const raw = container
134
- ? container.scrollTop +
135
- (target.getBoundingClientRect().top - container.getBoundingClientRect().top) -
136
- headerOffset
137
- : target.getBoundingClientRect().top + window.scrollY - headerOffset;
152
+ ? container.scrollTop + (target.getBoundingClientRect().top - container.getBoundingClientRect().top) - offset
153
+ : target.getBoundingClientRect().top + window.scrollY - offset;
138
154
  const adjusted = adjustTargetY ? adjustTargetY(raw) : raw;
139
155
  const maxScroll = container
140
156
  ? Math.max(0, container.scrollHeight - container.clientHeight)