@gabvdl/ui 0.0.14

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 (330) hide show
  1. package/README.md +95 -0
  2. package/dist/components/button/button.d.ts +39 -0
  3. package/dist/components/button/button.d.ts.map +1 -0
  4. package/dist/components/button/button.js +72 -0
  5. package/dist/components/button/button.js.map +1 -0
  6. package/dist/components/button/index.d.ts +5 -0
  7. package/dist/components/button/index.d.ts.map +1 -0
  8. package/dist/components/button/tooltip.d.ts +31 -0
  9. package/dist/components/button/tooltip.d.ts.map +1 -0
  10. package/dist/components/button/tooltip.js +83 -0
  11. package/dist/components/button/tooltip.js.map +1 -0
  12. package/dist/components/changelog/changelog.d.ts +52 -0
  13. package/dist/components/changelog/changelog.d.ts.map +1 -0
  14. package/dist/components/changelog/changelog.js +164 -0
  15. package/dist/components/changelog/changelog.js.map +1 -0
  16. package/dist/components/changelog/index.d.ts +3 -0
  17. package/dist/components/changelog/index.d.ts.map +1 -0
  18. package/dist/components/copy-button/copy-button.d.ts +16 -0
  19. package/dist/components/copy-button/copy-button.d.ts.map +1 -0
  20. package/dist/components/copy-button/copy-button.js +40 -0
  21. package/dist/components/copy-button/copy-button.js.map +1 -0
  22. package/dist/components/copy-button/index.d.ts +3 -0
  23. package/dist/components/copy-button/index.d.ts.map +1 -0
  24. package/dist/components/drop-zone/drop-zone.d.ts +20 -0
  25. package/dist/components/drop-zone/drop-zone.d.ts.map +1 -0
  26. package/dist/components/drop-zone/drop-zone.js +54 -0
  27. package/dist/components/drop-zone/drop-zone.js.map +1 -0
  28. package/dist/components/drop-zone/index.d.ts +5 -0
  29. package/dist/components/drop-zone/index.d.ts.map +1 -0
  30. package/dist/components/drop-zone/use-file-drop.d.ts +45 -0
  31. package/dist/components/drop-zone/use-file-drop.d.ts.map +1 -0
  32. package/dist/components/drop-zone/use-file-drop.js +97 -0
  33. package/dist/components/drop-zone/use-file-drop.js.map +1 -0
  34. package/dist/components/element-picker/element-picker-field.d.ts +30 -0
  35. package/dist/components/element-picker/element-picker-field.d.ts.map +1 -0
  36. package/dist/components/element-picker/element-picker-field.js +273 -0
  37. package/dist/components/element-picker/element-picker-field.js.map +1 -0
  38. package/dist/components/element-picker/element-picker.d.ts +45 -0
  39. package/dist/components/element-picker/element-picker.d.ts.map +1 -0
  40. package/dist/components/element-picker/element-picker.js +179 -0
  41. package/dist/components/element-picker/element-picker.js.map +1 -0
  42. package/dist/components/element-picker/element-preview.d.ts +23 -0
  43. package/dist/components/element-picker/element-preview.d.ts.map +1 -0
  44. package/dist/components/element-picker/element-preview.js +72 -0
  45. package/dist/components/element-picker/element-preview.js.map +1 -0
  46. package/dist/components/element-picker/index.d.ts +12 -0
  47. package/dist/components/element-picker/index.d.ts.map +1 -0
  48. package/dist/components/element-picker/parse.d.ts +32 -0
  49. package/dist/components/element-picker/parse.d.ts.map +1 -0
  50. package/dist/components/element-picker/parse.js +230 -0
  51. package/dist/components/element-picker/parse.js.map +1 -0
  52. package/dist/components/element-picker/types.d.ts +72 -0
  53. package/dist/components/element-picker/types.d.ts.map +1 -0
  54. package/dist/components/element-picker/use-element-picker.d.ts +56 -0
  55. package/dist/components/element-picker/use-element-picker.d.ts.map +1 -0
  56. package/dist/components/element-picker/use-element-picker.js +201 -0
  57. package/dist/components/element-picker/use-element-picker.js.map +1 -0
  58. package/dist/components/empty-state/empty-state.d.ts +16 -0
  59. package/dist/components/empty-state/empty-state.d.ts.map +1 -0
  60. package/dist/components/empty-state/empty-state.js +41 -0
  61. package/dist/components/empty-state/empty-state.js.map +1 -0
  62. package/dist/components/empty-state/index.d.ts +3 -0
  63. package/dist/components/empty-state/index.d.ts.map +1 -0
  64. package/dist/components/floating-panel/dock-context.d.ts +66 -0
  65. package/dist/components/floating-panel/dock-context.d.ts.map +1 -0
  66. package/dist/components/floating-panel/dock-context.js +96 -0
  67. package/dist/components/floating-panel/dock-context.js.map +1 -0
  68. package/dist/components/floating-panel/dock.d.ts +26 -0
  69. package/dist/components/floating-panel/dock.d.ts.map +1 -0
  70. package/dist/components/floating-panel/dock.js +46 -0
  71. package/dist/components/floating-panel/dock.js.map +1 -0
  72. package/dist/components/floating-panel/floating-panel.d.ts +69 -0
  73. package/dist/components/floating-panel/floating-panel.d.ts.map +1 -0
  74. package/dist/components/floating-panel/floating-panel.js +285 -0
  75. package/dist/components/floating-panel/floating-panel.js.map +1 -0
  76. package/dist/components/floating-panel/index.d.ts +7 -0
  77. package/dist/components/floating-panel/index.d.ts.map +1 -0
  78. package/dist/components/fuzzy-list/fuzzy-list.d.ts +96 -0
  79. package/dist/components/fuzzy-list/fuzzy-list.d.ts.map +1 -0
  80. package/dist/components/fuzzy-list/fuzzy-list.js +127 -0
  81. package/dist/components/fuzzy-list/fuzzy-list.js.map +1 -0
  82. package/dist/components/fuzzy-list/index.d.ts +4 -0
  83. package/dist/components/fuzzy-list/index.d.ts.map +1 -0
  84. package/dist/components/global-search/global-search.d.ts +78 -0
  85. package/dist/components/global-search/global-search.d.ts.map +1 -0
  86. package/dist/components/global-search/global-search.js +181 -0
  87. package/dist/components/global-search/global-search.js.map +1 -0
  88. package/dist/components/global-search/hotkey.d.ts +23 -0
  89. package/dist/components/global-search/hotkey.d.ts.map +1 -0
  90. package/dist/components/global-search/hotkey.js +41 -0
  91. package/dist/components/global-search/hotkey.js.map +1 -0
  92. package/dist/components/global-search/index.d.ts +5 -0
  93. package/dist/components/global-search/index.d.ts.map +1 -0
  94. package/dist/components/iframe-preview/iframe-preview.d.ts +64 -0
  95. package/dist/components/iframe-preview/iframe-preview.d.ts.map +1 -0
  96. package/dist/components/iframe-preview/iframe-preview.js +257 -0
  97. package/dist/components/iframe-preview/iframe-preview.js.map +1 -0
  98. package/dist/components/iframe-preview/index.d.ts +3 -0
  99. package/dist/components/iframe-preview/index.d.ts.map +1 -0
  100. package/dist/components/image-viewer/image-viewer.d.ts +30 -0
  101. package/dist/components/image-viewer/image-viewer.d.ts.map +1 -0
  102. package/dist/components/image-viewer/image-viewer.js +226 -0
  103. package/dist/components/image-viewer/image-viewer.js.map +1 -0
  104. package/dist/components/image-viewer/index.d.ts +4 -0
  105. package/dist/components/image-viewer/index.d.ts.map +1 -0
  106. package/dist/components/image-viewer/progressive-image.d.ts +20 -0
  107. package/dist/components/image-viewer/progressive-image.d.ts.map +1 -0
  108. package/dist/components/image-viewer/progressive-image.js +62 -0
  109. package/dist/components/image-viewer/progressive-image.js.map +1 -0
  110. package/dist/components/image-viewer/viewable-image.d.ts +17 -0
  111. package/dist/components/image-viewer/viewable-image.d.ts.map +1 -0
  112. package/dist/components/image-viewer/viewable-image.js +38 -0
  113. package/dist/components/image-viewer/viewable-image.js.map +1 -0
  114. package/dist/components/input/index.d.ts +3 -0
  115. package/dist/components/input/index.d.ts.map +1 -0
  116. package/dist/components/input/input.d.ts +15 -0
  117. package/dist/components/input/input.d.ts.map +1 -0
  118. package/dist/components/input/input.js +56 -0
  119. package/dist/components/input/input.js.map +1 -0
  120. package/dist/components/modal/index.d.ts +5 -0
  121. package/dist/components/modal/index.d.ts.map +1 -0
  122. package/dist/components/modal/modal-context.d.ts +37 -0
  123. package/dist/components/modal/modal-context.d.ts.map +1 -0
  124. package/dist/components/modal/modal-context.js +81 -0
  125. package/dist/components/modal/modal-context.js.map +1 -0
  126. package/dist/components/modal/modal.d.ts +28 -0
  127. package/dist/components/modal/modal.d.ts.map +1 -0
  128. package/dist/components/modal/modal.js +94 -0
  129. package/dist/components/modal/modal.js.map +1 -0
  130. package/dist/components/nav-2d/index.d.ts +3 -0
  131. package/dist/components/nav-2d/index.d.ts.map +1 -0
  132. package/dist/components/nav-2d/nav-2d.d.ts +59 -0
  133. package/dist/components/nav-2d/nav-2d.d.ts.map +1 -0
  134. package/dist/components/nav-2d/nav-2d.js +290 -0
  135. package/dist/components/nav-2d/nav-2d.js.map +1 -0
  136. package/dist/components/phone-preview/index.d.ts +3 -0
  137. package/dist/components/phone-preview/index.d.ts.map +1 -0
  138. package/dist/components/phone-preview/phone-preview.d.ts +45 -0
  139. package/dist/components/phone-preview/phone-preview.d.ts.map +1 -0
  140. package/dist/components/phone-preview/phone-preview.js +117 -0
  141. package/dist/components/phone-preview/phone-preview.js.map +1 -0
  142. package/dist/components/progressive-bash/index.d.ts +7 -0
  143. package/dist/components/progressive-bash/index.d.ts.map +1 -0
  144. package/dist/components/progressive-bash/parse.d.ts +88 -0
  145. package/dist/components/progressive-bash/parse.d.ts.map +1 -0
  146. package/dist/components/progressive-bash/parse.js +120 -0
  147. package/dist/components/progressive-bash/parse.js.map +1 -0
  148. package/dist/components/progressive-bash/playback.d.ts +50 -0
  149. package/dist/components/progressive-bash/playback.d.ts.map +1 -0
  150. package/dist/components/progressive-bash/playback.js +19 -0
  151. package/dist/components/progressive-bash/playback.js.map +1 -0
  152. package/dist/components/progressive-bash/progressive-bash.d.ts +97 -0
  153. package/dist/components/progressive-bash/progressive-bash.d.ts.map +1 -0
  154. package/dist/components/progressive-bash/progressive-bash.js +377 -0
  155. package/dist/components/progressive-bash/progressive-bash.js.map +1 -0
  156. package/dist/components/progressive-list/index.d.ts +3 -0
  157. package/dist/components/progressive-list/index.d.ts.map +1 -0
  158. package/dist/components/progressive-list/progressive-list.d.ts +55 -0
  159. package/dist/components/progressive-list/progressive-list.d.ts.map +1 -0
  160. package/dist/components/progressive-list/progressive-list.js +83 -0
  161. package/dist/components/progressive-list/progressive-list.js.map +1 -0
  162. package/dist/components/progressive-table/index.d.ts +3 -0
  163. package/dist/components/progressive-table/index.d.ts.map +1 -0
  164. package/dist/components/progressive-table/progressive-table.d.ts +58 -0
  165. package/dist/components/progressive-table/progressive-table.d.ts.map +1 -0
  166. package/dist/components/progressive-table/progressive-table.js +86 -0
  167. package/dist/components/progressive-table/progressive-table.js.map +1 -0
  168. package/dist/components/progressive-text/index.d.ts +3 -0
  169. package/dist/components/progressive-text/index.d.ts.map +1 -0
  170. package/dist/components/progressive-text/progressive-text.d.ts +54 -0
  171. package/dist/components/progressive-text/progressive-text.d.ts.map +1 -0
  172. package/dist/components/progressive-text/progressive-text.js +97 -0
  173. package/dist/components/progressive-text/progressive-text.js.map +1 -0
  174. package/dist/components/progressive-timeline/index.d.ts +3 -0
  175. package/dist/components/progressive-timeline/index.d.ts.map +1 -0
  176. package/dist/components/progressive-timeline/progressive-timeline.d.ts +46 -0
  177. package/dist/components/progressive-timeline/progressive-timeline.d.ts.map +1 -0
  178. package/dist/components/progressive-timeline/progressive-timeline.js +62 -0
  179. package/dist/components/progressive-timeline/progressive-timeline.js.map +1 -0
  180. package/dist/components/relative-time/index.d.ts +3 -0
  181. package/dist/components/relative-time/index.d.ts.map +1 -0
  182. package/dist/components/relative-time/relative-time.d.ts +14 -0
  183. package/dist/components/relative-time/relative-time.d.ts.map +1 -0
  184. package/dist/components/relative-time/relative-time.js +15 -0
  185. package/dist/components/relative-time/relative-time.js.map +1 -0
  186. package/dist/components/resizable-layout/index.d.ts +3 -0
  187. package/dist/components/resizable-layout/index.d.ts.map +1 -0
  188. package/dist/components/resizable-layout/resizable-layout.d.ts +113 -0
  189. package/dist/components/resizable-layout/resizable-layout.d.ts.map +1 -0
  190. package/dist/components/resizable-layout/resizable-layout.js +398 -0
  191. package/dist/components/resizable-layout/resizable-layout.js.map +1 -0
  192. package/dist/components/rich-input/compose.d.ts +13 -0
  193. package/dist/components/rich-input/compose.d.ts.map +1 -0
  194. package/dist/components/rich-input/compose.js +28 -0
  195. package/dist/components/rich-input/compose.js.map +1 -0
  196. package/dist/components/rich-input/index.d.ts +5 -0
  197. package/dist/components/rich-input/index.d.ts.map +1 -0
  198. package/dist/components/rich-input/parts.d.ts +53 -0
  199. package/dist/components/rich-input/parts.d.ts.map +1 -0
  200. package/dist/components/rich-input/parts.js +285 -0
  201. package/dist/components/rich-input/parts.js.map +1 -0
  202. package/dist/components/rich-input/rich-input.d.ts +64 -0
  203. package/dist/components/rich-input/rich-input.d.ts.map +1 -0
  204. package/dist/components/rich-input/rich-input.js +351 -0
  205. package/dist/components/rich-input/rich-input.js.map +1 -0
  206. package/dist/components/rich-input/types.d.ts +92 -0
  207. package/dist/components/rich-input/types.d.ts.map +1 -0
  208. package/dist/components/rich-input/use-draft.d.ts +9 -0
  209. package/dist/components/rich-input/use-draft.d.ts.map +1 -0
  210. package/dist/components/rich-input/use-draft.js +47 -0
  211. package/dist/components/rich-input/use-draft.js.map +1 -0
  212. package/dist/components/rich-input/use-file-upload.d.ts +18 -0
  213. package/dist/components/rich-input/use-file-upload.d.ts.map +1 -0
  214. package/dist/components/rich-input/use-file-upload.js +88 -0
  215. package/dist/components/rich-input/use-file-upload.js.map +1 -0
  216. package/dist/components/rich-input/use-guidelines.d.ts +16 -0
  217. package/dist/components/rich-input/use-guidelines.d.ts.map +1 -0
  218. package/dist/components/rich-input/use-guidelines.js +85 -0
  219. package/dist/components/rich-input/use-guidelines.js.map +1 -0
  220. package/dist/components/rich-input/use-input-history.d.ts +22 -0
  221. package/dist/components/rich-input/use-input-history.d.ts.map +1 -0
  222. package/dist/components/rich-input/use-input-history.js +61 -0
  223. package/dist/components/rich-input/use-input-history.js.map +1 -0
  224. package/dist/components/rich-input/use-mention.d.ts +24 -0
  225. package/dist/components/rich-input/use-mention.d.ts.map +1 -0
  226. package/dist/components/rich-input/use-mention.js +54 -0
  227. package/dist/components/rich-input/use-mention.js.map +1 -0
  228. package/dist/components/search-input/index.d.ts +3 -0
  229. package/dist/components/search-input/index.d.ts.map +1 -0
  230. package/dist/components/search-input/search-input.d.ts +14 -0
  231. package/dist/components/search-input/search-input.d.ts.map +1 -0
  232. package/dist/components/search-input/search-input.js +63 -0
  233. package/dist/components/search-input/search-input.js.map +1 -0
  234. package/dist/components/skeleton/index.d.ts +3 -0
  235. package/dist/components/skeleton/index.d.ts.map +1 -0
  236. package/dist/components/skeleton/skeleton.d.ts +19 -0
  237. package/dist/components/skeleton/skeleton.d.ts.map +1 -0
  238. package/dist/components/skeleton/skeleton.js +29 -0
  239. package/dist/components/skeleton/skeleton.js.map +1 -0
  240. package/dist/components/spinner/index.d.ts +3 -0
  241. package/dist/components/spinner/index.d.ts.map +1 -0
  242. package/dist/components/spinner/spinner.d.ts +11 -0
  243. package/dist/components/spinner/spinner.d.ts.map +1 -0
  244. package/dist/components/spinner/spinner.js +32 -0
  245. package/dist/components/spinner/spinner.js.map +1 -0
  246. package/dist/components/status-badge/index.d.ts +3 -0
  247. package/dist/components/status-badge/index.d.ts.map +1 -0
  248. package/dist/components/status-badge/status-badge.d.ts +31 -0
  249. package/dist/components/status-badge/status-badge.d.ts.map +1 -0
  250. package/dist/components/status-badge/status-badge.js +53 -0
  251. package/dist/components/status-badge/status-badge.js.map +1 -0
  252. package/dist/components/theme/index.d.ts +5 -0
  253. package/dist/components/theme/index.d.ts.map +1 -0
  254. package/dist/components/theme/theme-toggle.d.ts +11 -0
  255. package/dist/components/theme/theme-toggle.d.ts.map +1 -0
  256. package/dist/components/theme/theme-toggle.js +57 -0
  257. package/dist/components/theme/theme-toggle.js.map +1 -0
  258. package/dist/components/theme/theme.d.ts +29 -0
  259. package/dist/components/theme/theme.d.ts.map +1 -0
  260. package/dist/components/theme/theme.js +70 -0
  261. package/dist/components/theme/theme.js.map +1 -0
  262. package/dist/components/toast/index.d.ts +3 -0
  263. package/dist/components/toast/index.d.ts.map +1 -0
  264. package/dist/components/toast/toast.d.ts +64 -0
  265. package/dist/components/toast/toast.d.ts.map +1 -0
  266. package/dist/components/toast/toast.js +155 -0
  267. package/dist/components/toast/toast.js.map +1 -0
  268. package/dist/components/virtual-list/index.d.ts +3 -0
  269. package/dist/components/virtual-list/index.d.ts.map +1 -0
  270. package/dist/components/virtual-list/virtual-list.d.ts +71 -0
  271. package/dist/components/virtual-list/virtual-list.d.ts.map +1 -0
  272. package/dist/components/virtual-list/virtual-list.js +65 -0
  273. package/dist/components/virtual-list/virtual-list.js.map +1 -0
  274. package/dist/hooks/index.d.ts +12 -0
  275. package/dist/hooks/index.d.ts.map +1 -0
  276. package/dist/hooks/use-copy-to-clipboard.d.ts +26 -0
  277. package/dist/hooks/use-copy-to-clipboard.d.ts.map +1 -0
  278. package/dist/hooks/use-copy-to-clipboard.js +36 -0
  279. package/dist/hooks/use-copy-to-clipboard.js.map +1 -0
  280. package/dist/hooks/use-debounced-value.d.ts +23 -0
  281. package/dist/hooks/use-debounced-value.d.ts.map +1 -0
  282. package/dist/hooks/use-debounced-value.js +19 -0
  283. package/dist/hooks/use-debounced-value.js.map +1 -0
  284. package/dist/hooks/use-intersection.d.ts +25 -0
  285. package/dist/hooks/use-intersection.d.ts.map +1 -0
  286. package/dist/hooks/use-intersection.js +38 -0
  287. package/dist/hooks/use-intersection.js.map +1 -0
  288. package/dist/hooks/use-local-storage.d.ts +12 -0
  289. package/dist/hooks/use-local-storage.d.ts.map +1 -0
  290. package/dist/hooks/use-local-storage.js +43 -0
  291. package/dist/hooks/use-local-storage.js.map +1 -0
  292. package/dist/hooks/use-long-press.d.ts +37 -0
  293. package/dist/hooks/use-long-press.d.ts.map +1 -0
  294. package/dist/hooks/use-long-press.js +39 -0
  295. package/dist/hooks/use-long-press.js.map +1 -0
  296. package/dist/hooks/use-media-query.d.ts +17 -0
  297. package/dist/hooks/use-media-query.d.ts.map +1 -0
  298. package/dist/hooks/use-media-query.js +37 -0
  299. package/dist/hooks/use-media-query.js.map +1 -0
  300. package/dist/hooks/use-overlay.d.ts +20 -0
  301. package/dist/hooks/use-overlay.d.ts.map +1 -0
  302. package/dist/hooks/use-overlay.js +42 -0
  303. package/dist/hooks/use-overlay.js.map +1 -0
  304. package/dist/image-viewer.css +152 -0
  305. package/dist/index.d.ts +67 -0
  306. package/dist/index.d.ts.map +1 -0
  307. package/dist/index.js +161 -0
  308. package/dist/index.js.map +1 -0
  309. package/dist/lib/format.d.ts +19 -0
  310. package/dist/lib/format.d.ts.map +1 -0
  311. package/dist/lib/format.js +62 -0
  312. package/dist/lib/format.js.map +1 -0
  313. package/dist/lib/highlight.d.ts +15 -0
  314. package/dist/lib/highlight.d.ts.map +1 -0
  315. package/dist/lib/highlight.js +39 -0
  316. package/dist/lib/highlight.js.map +1 -0
  317. package/dist/lib/search.d.ts +40 -0
  318. package/dist/lib/search.d.ts.map +1 -0
  319. package/dist/lib/search.js +91 -0
  320. package/dist/lib/search.js.map +1 -0
  321. package/dist/lib/utils.d.ts +4 -0
  322. package/dist/lib/utils.d.ts.map +1 -0
  323. package/dist/lib/utils.js +9 -0
  324. package/dist/lib/utils.js.map +1 -0
  325. package/dist/overlay.css +78 -0
  326. package/dist/styles.css +6 -0
  327. package/dist/theme.css +81 -0
  328. package/dist/tooltip.css +53 -0
  329. package/dist/virtual-list.css +29 -0
  330. package/package.json +77 -0
@@ -0,0 +1,377 @@
1
+ import { jsxs as b, jsx as g } from "react/jsx-runtime";
2
+ import { useState as U, useRef as f, useCallback as V, useEffect as C, useMemo as Y, useImperativeHandle as ge } from "react";
3
+ import { cn as oe } from "../../lib/utils.js";
4
+ import { splitOutput as ve, tokenizeCommand as xe, splitBySubparts as ye } from "./parse.js";
5
+ import { DEFAULT_TUNING as R, computeGapMs as ie } from "./playback.js";
6
+ const ke = {
7
+ "--tb-bg": "#0a0d12",
8
+ "--tb-fg": "#c9d3e0",
9
+ "--tb-out": "#aab6c6",
10
+ "--tb-dim": "#5b6675",
11
+ "--tb-red": "#ff7b72",
12
+ "--tb-green": "#4bc98a",
13
+ "--tb-yellow": "#e3b341",
14
+ "--tb-blue": "#6cb6ff",
15
+ "--tb-cyan": "#56d4dd",
16
+ "--tb-magenta": "#d2a8ff",
17
+ "--tb-orange": "#ffa657",
18
+ "--tb-prompt": "#4bc98a",
19
+ "--tb-header": "#111722",
20
+ "--tb-border": "rgba(255,255,255,0.08)"
21
+ }, we = {
22
+ program: "var(--tb-fg)",
23
+ subcommand: "var(--tb-cyan)",
24
+ flag: "var(--tb-yellow)",
25
+ string: "var(--tb-green)",
26
+ operator: "var(--tb-magenta)",
27
+ path: "var(--tb-cyan)",
28
+ var: "var(--tb-magenta)",
29
+ number: "var(--tb-orange)",
30
+ comment: "var(--tb-dim)",
31
+ plain: "var(--tb-fg)"
32
+ }, Me = {
33
+ error: "var(--tb-red)",
34
+ warn: "var(--tb-yellow)",
35
+ success: "var(--tb-green)",
36
+ info: "var(--tb-blue)",
37
+ section: "var(--tb-cyan)",
38
+ plain: "var(--tb-out)"
39
+ }, Le = {
40
+ url: "var(--tb-blue)",
41
+ path: "var(--tb-cyan)",
42
+ number: "var(--tb-orange)",
43
+ string: "var(--tb-green)",
44
+ flag: "var(--tb-yellow)",
45
+ hash: "var(--tb-magenta)"
46
+ };
47
+ function Ne(a) {
48
+ const r = [];
49
+ for (const s of a) {
50
+ const l = ye(s.command ?? "", s.output ?? "");
51
+ if (!l || l.length <= 1) {
52
+ r.push(s);
53
+ continue;
54
+ }
55
+ l.forEach((d, o) => {
56
+ r.push({
57
+ ...s,
58
+ id: `${s.id}::sub${o}`,
59
+ command: d.command,
60
+ output: d.output,
61
+ description: d.title || (o === 0 ? s.description : void 0),
62
+ exitCode: o === l.length - 1 ? s.exitCode : void 0,
63
+ isError: o === l.length - 1 ? s.isError : void 0
64
+ });
65
+ });
66
+ }
67
+ return r;
68
+ }
69
+ function Ce(a, r) {
70
+ if (r <= 0) return [];
71
+ const s = [];
72
+ let l = 0;
73
+ for (const d of a) {
74
+ if (l + d.text.length <= r)
75
+ s.push(d), l += d.text.length;
76
+ else {
77
+ s.push({ ...d, text: d.text.slice(0, r - l) });
78
+ break;
79
+ }
80
+ if (l >= r) break;
81
+ }
82
+ return s;
83
+ }
84
+ function Re() {
85
+ return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
86
+ }
87
+ const Te = 40;
88
+ function _e({
89
+ entries: a,
90
+ typeSpeed: r = R.typeSpeed,
91
+ outputSpeed: s = R.outputSpeed,
92
+ delay: l,
93
+ minGap: d = R.minGapMs,
94
+ maxGap: o = R.maxGapMs,
95
+ gapReference: O = R.gapReferenceMs,
96
+ think: B = R.thinkMs,
97
+ instant: T = !1,
98
+ catchUp: k,
99
+ stickyPrompt: Z = !1,
100
+ experimentalSubparts: m = !1,
101
+ prompt: y = "❯",
102
+ showDescriptions: D = !0,
103
+ onIdle: w,
104
+ className: j,
105
+ bodyClassName: de,
106
+ style: pe,
107
+ apiRef: fe
108
+ }) {
109
+ const M = T || Re(), [z, ee] = U(() => a ?? []), $ = f(new Set((a ?? []).map((e) => e.id))), G = V((e) => {
110
+ const n = e.filter((p) => p && !$.current.has(p.id));
111
+ n.length !== 0 && (n.forEach((p) => $.current.add(p.id)), ee((p) => [...p, ...n]));
112
+ }, []);
113
+ C(() => {
114
+ a && G(a);
115
+ }, [a, G]);
116
+ const i = Y(
117
+ () => m ? Ne(z) : z,
118
+ [z, m]
119
+ ), _ = f(i);
120
+ _.current = i;
121
+ const W = Y(() => {
122
+ const e = /* @__PURE__ */ new Map();
123
+ for (const n of i)
124
+ e.set(n.id, {
125
+ tokens: xe(n.command ?? ""),
126
+ cmdLen: (n.command ?? "").length,
127
+ lines: n.output ? ve(n.output) : []
128
+ });
129
+ return e;
130
+ }, [i]), te = f(W);
131
+ te.current = W;
132
+ const F = Y(
133
+ () => ({
134
+ typeSpeed: r,
135
+ outputSpeed: s,
136
+ fixedDelay: l,
137
+ minGapMs: d,
138
+ maxGapMs: o,
139
+ gapReferenceMs: O,
140
+ thinkMs: B
141
+ }),
142
+ [r, s, l, d, o, O, B]
143
+ ), H = f(F);
144
+ H.current = F;
145
+ const [X, E] = U({ index: 0, phase: "gap", typed: 0, outLines: 0, acc: 0, gapMs: 0 }), u = f(X), I = f(0), A = f(!1), ne = f(() => {
146
+ }), q = f(w);
147
+ q.current = w, C(() => {
148
+ let e = 0;
149
+ const n = (c) => {
150
+ var se;
151
+ if (e === 0) {
152
+ e = c, I.current = requestAnimationFrame(n);
153
+ return;
154
+ }
155
+ const v = c - e;
156
+ e = c;
157
+ const h = _.current, t = u.current, x = H.current;
158
+ let L = !1;
159
+ if (t.index >= h.length) {
160
+ A.current = !1;
161
+ return;
162
+ }
163
+ const N = te.current.get(h[t.index].id), ce = (N == null ? void 0 : N.cmdLen) ?? 0, Q = (N == null ? void 0 : N.lines.length) ?? 0;
164
+ switch (t.acc += v, t.phase) {
165
+ case "gap":
166
+ t.acc >= t.gapMs && (t.phase = "type", t.acc = 0, L = !0);
167
+ break;
168
+ case "type": {
169
+ const S = 1e3 / Math.max(1, x.typeSpeed);
170
+ for (; t.typed < ce && t.acc >= S; )
171
+ t.acc -= S, t.typed++, L = !0;
172
+ t.typed >= ce && (t.phase = "think", t.acc = 0);
173
+ break;
174
+ }
175
+ case "think":
176
+ t.acc >= x.thinkMs && (t.acc = 0, Q > 0 ? t.phase = "output" : (p(t, h, x), L = !0));
177
+ break;
178
+ case "output": {
179
+ const S = 1e3 / Math.max(0.5, x.outputSpeed);
180
+ for (; t.outLines < Q && t.acc >= S; )
181
+ t.acc -= S, t.outLines++, L = !0;
182
+ t.outLines >= Q && (p(t, h, x), L = !0);
183
+ break;
184
+ }
185
+ }
186
+ if (L && E({ ...t }), t.index >= h.length) {
187
+ A.current = !1, (se = q.current) == null || se.call(q);
188
+ return;
189
+ }
190
+ I.current = requestAnimationFrame(n);
191
+ }, p = (c, v, h) => {
192
+ const t = v[c.index], x = c.index + 1;
193
+ c.index = x, c.typed = 0, c.outLines = 0, c.acc = 0, x >= v.length ? c.phase = "idle" : (c.gapMs = ie(t == null ? void 0 : t.timestamp, v[x].timestamp, h), c.phase = "gap");
194
+ };
195
+ return ne.current = () => {
196
+ if (A.current) return;
197
+ const c = u.current, v = _.current;
198
+ if (!(c.index >= v.length)) {
199
+ if (c.phase === "idle") {
200
+ const h = v[c.index - 1];
201
+ c.gapMs = c.index === 0 ? le(H.current) : ie(h == null ? void 0 : h.timestamp, v[c.index].timestamp, H.current), c.phase = "gap", c.acc = 0;
202
+ }
203
+ A.current = !0, e = 0, I.current = requestAnimationFrame(n);
204
+ }
205
+ }, () => {
206
+ cancelAnimationFrame(I.current), A.current = !1;
207
+ };
208
+ }, []), C(() => {
209
+ M && (u.current = { index: i.length, phase: "idle", typed: 0, outLines: 0, acc: 0, gapMs: 0 }, E({ ...u.current }));
210
+ }, [M, i.length]);
211
+ const re = f(!1);
212
+ C(() => {
213
+ if (re.current || M || !k || i.length === 0) return;
214
+ re.current = !0;
215
+ const e = typeof k == "number" ? k : Date.now();
216
+ let n = 0;
217
+ for (; n < i.length && i[n].timestamp != null && i[n].timestamp <= e; ) n++;
218
+ n <= 0 || (u.current = {
219
+ index: n,
220
+ phase: n >= i.length ? "idle" : "gap",
221
+ typed: 0,
222
+ outLines: 0,
223
+ acc: 0,
224
+ gapMs: 0
225
+ }, E({ ...u.current }));
226
+ }, [k, i, M]), C(() => {
227
+ M || i.length !== 0 && (u.current.index === 0 && u.current.phase === "gap" && u.current.typed === 0 && u.current.gapMs === 0 && (u.current.gapMs = le(F)), ne.current());
228
+ }, [i, M, F]);
229
+ const P = f(null), J = f(!0), [me, ae] = U(!0), K = V(() => {
230
+ const e = P.current;
231
+ e && (e.scrollTop = e.scrollHeight, J.current = !0, ae(!0));
232
+ }, []), he = V(() => {
233
+ const e = P.current;
234
+ if (!e) return;
235
+ const n = e.scrollHeight - e.scrollTop - e.clientHeight < Te;
236
+ J.current = n, ae((p) => p === n ? p : n);
237
+ }, []);
238
+ C(() => {
239
+ if (J.current) {
240
+ const e = P.current;
241
+ e && (e.scrollTop = e.scrollHeight);
242
+ }
243
+ }, [X]), ge(
244
+ fe,
245
+ () => ({
246
+ push: (e) => G(Array.isArray(e) ? e : [e]),
247
+ clear: () => {
248
+ $.current = /* @__PURE__ */ new Set(), u.current = { index: 0, phase: "gap", typed: 0, outLines: 0, acc: 0, gapMs: 0 }, E({ ...u.current }), ee([]);
249
+ },
250
+ skipToEnd: () => {
251
+ u.current = { index: _.current.length, phase: "idle", typed: 0, outLines: 0, acc: 0, gapMs: 0 }, E({ ...u.current });
252
+ },
253
+ scrollToBottom: K
254
+ }),
255
+ [G, K]
256
+ );
257
+ const be = { ...ke, ...pe, background: "var(--tb-bg)" };
258
+ return /* @__PURE__ */ b(
259
+ "div",
260
+ {
261
+ className: oe("ds-terminal relative flex h-full min-h-0 flex-col font-mono text-[12.5px] leading-[1.55]", j),
262
+ style: be,
263
+ children: [
264
+ /* @__PURE__ */ g(
265
+ "div",
266
+ {
267
+ ref: P,
268
+ onScroll: he,
269
+ className: oe("min-h-0 flex-1 overflow-y-auto px-3 py-2.5", de),
270
+ style: { color: "var(--tb-fg)" },
271
+ children: i.length === 0 ? /* @__PURE__ */ b("div", { className: "select-none py-6 text-center", style: { color: "var(--tb-dim)" }, children: [
272
+ y,
273
+ " waiting for commands…"
274
+ ] }) : i.map((e, n) => /* @__PURE__ */ g(
275
+ Ae,
276
+ {
277
+ entry: e,
278
+ parsed: W.get(e.id),
279
+ prompt: y,
280
+ showDescriptions: D,
281
+ stickyPrompt: Z,
282
+ state: Ee(n, X)
283
+ },
284
+ e.id
285
+ ))
286
+ }
287
+ ),
288
+ !me && /* @__PURE__ */ g(
289
+ "button",
290
+ {
291
+ type: "button",
292
+ onClick: K,
293
+ className: "absolute bottom-3 right-3 rounded-full px-2.5 py-1 text-[11px] shadow-lg",
294
+ style: { background: "var(--tb-header)", color: "var(--tb-fg)", border: "1px solid var(--tb-border)" },
295
+ children: "↓ live"
296
+ }
297
+ )
298
+ ]
299
+ }
300
+ );
301
+ }
302
+ function le(a) {
303
+ return a.fixedDelay != null ? Math.max(0, a.fixedDelay * 1e3) : Math.min(300, a.minGapMs);
304
+ }
305
+ function Ee(a, r) {
306
+ if (a < r.index) return { revealed: !0, typed: 1 / 0, outLines: 1 / 0, caret: null, full: !0 };
307
+ if (a > r.index) return { revealed: !1 };
308
+ const s = r.phase === "type" || r.phase === "think" ? "cmd" : r.phase === "output" ? "out" : null;
309
+ return { revealed: !0, typed: r.typed, outLines: r.outLines, caret: s, full: !1 };
310
+ }
311
+ function Ae({
312
+ entry: a,
313
+ parsed: r,
314
+ prompt: s,
315
+ showDescriptions: l,
316
+ stickyPrompt: d,
317
+ state: o
318
+ }) {
319
+ if (!o.revealed) return null;
320
+ const O = o.full ? r.tokens : Ce(r.tokens, o.typed), B = o.full || o.typed >= r.cmdLen, T = o.full ? r.lines : r.lines.slice(0, o.outLines), k = a.isError || a.exitCode != null && a.exitCode !== 0;
321
+ return /* @__PURE__ */ b("div", { className: "mb-1.5", children: [
322
+ /* @__PURE__ */ b("div", { className: "flex flex-col", style: d ? { position: "sticky", top: 0, zIndex: 2, background: "var(--tb-bg)" } : void 0, children: [
323
+ l && a.description && B && /* @__PURE__ */ b("div", { className: "whitespace-pre-wrap", style: { color: "var(--tb-dim)" }, children: [
324
+ "# ",
325
+ a.description
326
+ ] }),
327
+ /* @__PURE__ */ b("div", { className: "flex whitespace-pre-wrap break-all", children: [
328
+ /* @__PURE__ */ b(
329
+ "span",
330
+ {
331
+ className: "mr-1.5 shrink-0 select-none",
332
+ style: { color: k ? "var(--tb-red)" : "var(--tb-prompt)" },
333
+ children: [
334
+ a.cwd ? /* @__PURE__ */ b("span", { style: { color: "var(--tb-blue)" }, children: [
335
+ a.cwd,
336
+ " "
337
+ ] }) : null,
338
+ s
339
+ ]
340
+ }
341
+ ),
342
+ /* @__PURE__ */ b("span", { className: "min-w-0", children: [
343
+ O.map((m, y) => /* @__PURE__ */ g("span", { style: { color: we[m.kind], fontWeight: m.kind === "program" ? 600 : void 0 }, children: m.text }, y)),
344
+ o.caret === "cmd" && /* @__PURE__ */ g(ue, {})
345
+ ] })
346
+ ] })
347
+ ] }),
348
+ T.length > 0 && /* @__PURE__ */ g("div", { className: "mt-0.5", children: T.map(
349
+ (m, y) => {
350
+ var D;
351
+ return m.divider ? /* @__PURE__ */ b(
352
+ "div",
353
+ {
354
+ className: "my-1 flex items-center gap-2 text-[10.5px] font-semibold uppercase tracking-wider",
355
+ style: { color: "var(--tb-cyan)" },
356
+ children: [
357
+ /* @__PURE__ */ g("span", { className: "h-px flex-1", style: { background: "var(--tb-border)" } }),
358
+ (D = m.spans[0]) == null ? void 0 : D.text,
359
+ /* @__PURE__ */ g("span", { className: "h-px flex-1", style: { background: "var(--tb-border)" } })
360
+ ]
361
+ },
362
+ y
363
+ ) : /* @__PURE__ */ b("div", { className: "whitespace-pre-wrap break-all", style: { color: Me[m.kind] }, children: [
364
+ m.spans.map((w, j) => /* @__PURE__ */ g("span", { style: w.accent ? { color: Le[w.accent] } : void 0, children: w.text }, j)),
365
+ o.caret === "out" && y === T.length - 1 && /* @__PURE__ */ g(ue, {})
366
+ ] }, y);
367
+ }
368
+ ) })
369
+ ] });
370
+ }
371
+ function ue() {
372
+ return /* @__PURE__ */ g("span", { "aria-hidden": !0, className: "ml-px inline-block animate-pulse", style: { color: "var(--tb-fg)" }, children: "▋" });
373
+ }
374
+ export {
375
+ _e as ProgressiveBash
376
+ };
377
+ //# sourceMappingURL=progressive-bash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressive-bash.js","sources":["../../../src/components/progressive-bash/progressive-bash.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type Ref,\n} from 'react';\n\nimport { cn } from '../../lib/utils';\nimport {\n tokenizeCommand,\n splitOutput,\n splitBySubparts,\n type CmdToken,\n type OutputLine,\n type OutputSpan,\n} from './parse';\nimport { computeGapMs, DEFAULT_TUNING, type BashEntry, type PlaybackTuning } from './playback';\n\nexport type { BashEntry, PlaybackTuning } from './playback';\n\n/** Imperative handle for feeding entries and driving the terminal. */\nexport interface ProgressiveBashHandle {\n /** Append one or more entries (deduped by id). Plays continuously. */\n push: (entry: BashEntry | BashEntry[]) => void;\n /** Remove everything and reset the playhead. */\n clear: () => void;\n /** Reveal every entry instantly (skip the animation). */\n skipToEnd: () => void;\n /** Force the scroll view to the latest line. */\n scrollToBottom: () => void;\n}\n\nexport interface ProgressiveBashProps {\n /**\n * The command/output series to play, oldest → newest. Growing this array (a\n * fresh batch streamed in) appends to the queue; already-played entries are\n * never re-animated. You can also feed entries imperatively via\n * {@link ProgressiveBashHandle.push} — both merge, deduped by `id`.\n */\n entries?: BashEntry[];\n /** Command typing rate, chars/sec. @default 55 */\n typeSpeed?: number;\n /** Output reveal rate, lines/sec. @default 24 */\n outputSpeed?: number;\n /**\n * Fixed seconds between entries. When omitted, gaps are derived from each\n * entry's `timestamp` and compressed into a lively, bounded, continuous\n * playback (see {@link computeGapMs}).\n */\n delay?: number;\n /** Floor / ceiling / saturation for timestamp-derived gaps (ms). */\n minGap?: number;\n maxGap?: number;\n gapReference?: number;\n /** Pause between a typed command and its output (ms). @default 260 */\n think?: number;\n /** Reveal everything immediately (or honors `prefers-reduced-motion`). */\n instant?: boolean;\n /**\n * \"Join in progress\" — when the terminal mounts, every entry whose\n * `timestamp` is already in the past relative to this reference is rendered\n * fully-written (no replay), and live typing resumes at the first entry\n * at/after it. Pass a wall-clock ms reference, or `true` for `Date.now()`.\n * This is what stops a page reload from re-typing a whole finished session.\n */\n catchUp?: number | boolean;\n /**\n * Pin each command's prompt line to the top of the scroll viewport, so while\n * a long output scrolls by you can still see which command produced it (the\n * next command's prompt pushes the previous one up, like sticky table\n * headers). @default false\n */\n stickyPrompt?: boolean;\n /**\n * [EXPERIMENTAL] Split a chained `echo \"Title..[value]\" && cmd && …` command\n * (see {@link splitBySubparts}) into one separate command block per step, each\n * pairing the real command with the output printed after its marker — so the\n * terminal types several sequential commands instead of one long chain. Useful\n * to keep the terminal visually busy (and buy time) while a genuinely long\n * command elsewhere is still running. @default false\n */\n experimentalSubparts?: boolean;\n /** Prompt glyph shown before each command. @default '❯' */\n prompt?: string;\n /** Show each entry's `description` as a `# comment` line. @default true */\n showDescriptions?: boolean;\n /** Fired when the playhead catches up to the last known entry. */\n onIdle?: () => void;\n className?: string;\n bodyClassName?: string;\n /** Override any of the terminal color CSS vars (`--tb-*`). */\n style?: CSSProperties;\n apiRef?: Ref<ProgressiveBashHandle>;\n}\n\n// A GitHub-dark-ish palette. Set as CSS vars on the root so a consumer can\n// retheme by overriding `--tb-*` via `style`/`className`.\nconst PALETTE: Record<string, string> = {\n '--tb-bg': '#0a0d12',\n '--tb-fg': '#c9d3e0',\n '--tb-out': '#aab6c6',\n '--tb-dim': '#5b6675',\n '--tb-red': '#ff7b72',\n '--tb-green': '#4bc98a',\n '--tb-yellow': '#e3b341',\n '--tb-blue': '#6cb6ff',\n '--tb-cyan': '#56d4dd',\n '--tb-magenta': '#d2a8ff',\n '--tb-orange': '#ffa657',\n '--tb-prompt': '#4bc98a',\n '--tb-header': '#111722',\n '--tb-border': 'rgba(255,255,255,0.08)',\n};\n\nconst CMD_COLOR: Record<CmdToken['kind'], string> = {\n program: 'var(--tb-fg)',\n subcommand: 'var(--tb-cyan)',\n flag: 'var(--tb-yellow)',\n string: 'var(--tb-green)',\n operator: 'var(--tb-magenta)',\n path: 'var(--tb-cyan)',\n var: 'var(--tb-magenta)',\n number: 'var(--tb-orange)',\n comment: 'var(--tb-dim)',\n plain: 'var(--tb-fg)',\n};\n\nconst LINE_COLOR: Record<OutputLine['kind'], string> = {\n error: 'var(--tb-red)',\n warn: 'var(--tb-yellow)',\n success: 'var(--tb-green)',\n info: 'var(--tb-blue)',\n section: 'var(--tb-cyan)',\n plain: 'var(--tb-out)',\n};\n\nconst ACCENT_COLOR: Record<NonNullable<OutputSpan['accent']>, string> = {\n url: 'var(--tb-blue)',\n path: 'var(--tb-cyan)',\n number: 'var(--tb-orange)',\n string: 'var(--tb-green)',\n flag: 'var(--tb-yellow)',\n hash: 'var(--tb-magenta)',\n};\n\ninterface Parsed {\n tokens: CmdToken[];\n cmdLen: number;\n lines: OutputLine[];\n}\n\n/**\n * Expand each chained `echo \"Title..[value]\" && cmd` entry into one block per\n * step (the marker's title becomes the block's `# comment`), so the terminal\n * types several separate commands instead of one long chain. Entries without\n * markers (or with a single step) pass through untouched. Sub-blocks keep the\n * parent timestamp so they play back-to-back, and only the last carries the\n * parent's error status.\n */\nfunction expandSubparts(entries: BashEntry[]): BashEntry[] {\n const out: BashEntry[] = [];\n for (const e of entries) {\n const subs = splitBySubparts(e.command ?? '', e.output ?? '');\n if (!subs || subs.length <= 1) {\n out.push(e);\n continue;\n }\n subs.forEach((s, i) => {\n out.push({\n ...e,\n id: `${e.id}::sub${i}`,\n command: s.command,\n output: s.output,\n description: s.title || (i === 0 ? e.description : undefined),\n exitCode: i === subs.length - 1 ? e.exitCode : undefined,\n isError: i === subs.length - 1 ? e.isError : undefined,\n });\n });\n }\n return out;\n}\n\n/** Truncate a token stream to the first `n` visible characters. */\nfunction sliceTokens(tokens: CmdToken[], n: number): CmdToken[] {\n if (n <= 0) return [];\n const out: CmdToken[] = [];\n let used = 0;\n for (const t of tokens) {\n if (used + t.text.length <= n) {\n out.push(t);\n used += t.text.length;\n } else {\n out.push({ ...t, text: t.text.slice(0, n - used) });\n break;\n }\n if (used >= n) break;\n }\n return out;\n}\n\nfunction reducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\nconst NEAR_BOTTOM_PX = 40;\n\ninterface Cursor {\n index: number; // entry currently animating; === list.length ⇒ idle/caught-up\n phase: 'gap' | 'type' | 'think' | 'output' | 'idle';\n typed: number;\n outLines: number;\n acc: number; // ms accumulated in the current phase\n gapMs: number;\n}\n\n/**\n * An animated terminal that \"types\" a series of shell commands and reveals each\n * command's output line-by-line — turning an intermittent batch of\n * command/output records into a continuously-playing terminal. Commands and\n * output are regex-tokenized and colorized like a real shell + pager (programs,\n * flags, paths, URLs, pass/fail lines, `=== section ===` dividers).\n *\n * Feed it via the `entries` prop (append to stream more) or imperatively via\n * `apiRef.push(...)`. Timestamps on entries are compressed into a lively,\n * bounded inter-command delay so replay stays continuous no matter how sparse\n * the real timing was. The view auto-scrolls to the newest line but releases\n * that lock the moment you scroll up (like a chat log).\n *\n * Extras: `catchUp` renders already-past entries fully-written on mount (a\n * reload doesn't re-type a finished session); `stickyPrompt` pins each\n * command's prompt line to the top while its output scrolls; and\n * `experimentalSubparts` splits a chained `echo \"Title..[value]\" && cmd` command\n * into several separate, sequentially-typed command blocks.\n */\nexport function ProgressiveBash({\n entries,\n typeSpeed = DEFAULT_TUNING.typeSpeed,\n outputSpeed = DEFAULT_TUNING.outputSpeed,\n delay,\n minGap = DEFAULT_TUNING.minGapMs,\n maxGap = DEFAULT_TUNING.maxGapMs,\n gapReference = DEFAULT_TUNING.gapReferenceMs,\n think = DEFAULT_TUNING.thinkMs,\n instant = false,\n catchUp,\n stickyPrompt = false,\n experimentalSubparts = false,\n prompt = '❯',\n showDescriptions = true,\n onIdle,\n className,\n bodyClassName,\n style,\n apiRef,\n}: ProgressiveBashProps) {\n const skip = instant || reducedMotion();\n\n // The merged, deduped entry list (prop + imperative pushes). Dedup tracks the\n // raw ids; `experimentalSubparts` expansion happens downstream in `playList`.\n const [list, setList] = useState<BashEntry[]>(() => entries ?? []);\n const seen = useRef<Set<string>>(new Set((entries ?? []).map((e) => e.id)));\n\n const appendEntries = useCallback((incoming: BashEntry[]) => {\n const fresh = incoming.filter((e) => e && !seen.current.has(e.id));\n if (fresh.length === 0) return;\n fresh.forEach((e) => seen.current.add(e.id));\n setList((l) => [...l, ...fresh]);\n }, []);\n\n // Absorb new entries appended to the controlled prop.\n useEffect(() => {\n if (entries) appendEntries(entries);\n }, [entries, appendEntries]);\n\n // The list actually played/rendered: raw entries, optionally expanded so each\n // chained `echo \"Title..[value]\" && cmd` step becomes its own command block.\n const playList = useMemo(\n () => (experimentalSubparts ? expandSubparts(list) : list),\n [list, experimentalSubparts],\n );\n const listRef = useRef(playList);\n listRef.current = playList;\n\n const parsed = useMemo(() => {\n const map = new Map<string, Parsed>();\n for (const e of playList) {\n map.set(e.id, {\n tokens: tokenizeCommand(e.command ?? ''),\n cmdLen: (e.command ?? '').length,\n lines: e.output ? splitOutput(e.output) : [],\n });\n }\n return map;\n }, [playList]);\n const parsedRef = useRef(parsed);\n parsedRef.current = parsed;\n\n const tuning: PlaybackTuning = useMemo(\n () => ({\n typeSpeed,\n outputSpeed,\n fixedDelay: delay,\n minGapMs: minGap,\n maxGapMs: maxGap,\n gapReferenceMs: gapReference,\n thinkMs: think,\n }),\n [typeSpeed, outputSpeed, delay, minGap, maxGap, gapReference, think],\n );\n const tuningRef = useRef(tuning);\n tuningRef.current = tuning;\n\n // Progress mirror that drives the paint.\n const [render, setRender] = useState<Cursor>({ index: 0, phase: 'gap', typed: 0, outLines: 0, acc: 0, gapMs: 0 });\n const cursor = useRef<Cursor>(render);\n const rafRef = useRef(0);\n const runningRef = useRef(false);\n const kickRef = useRef<() => void>(() => {});\n const onIdleRef = useRef(onIdle);\n onIdleRef.current = onIdle;\n\n // The persistent playback loop — created once, reads everything via refs so a\n // growing entry list never restarts what already played (mirrors ProgressiveText).\n useEffect(() => {\n let lastTs = 0;\n const frame = (ts: number) => {\n if (lastTs === 0) {\n lastTs = ts;\n rafRef.current = requestAnimationFrame(frame);\n return;\n }\n const dt = ts - lastTs;\n lastTs = ts;\n\n const l = listRef.current;\n const cur = cursor.current;\n const t = tuningRef.current;\n let changed = false;\n\n if (cur.index >= l.length) {\n // Caught up: idle until more entries arrive.\n runningRef.current = false;\n return;\n }\n const p = parsedRef.current.get(l[cur.index].id);\n const cmdLen = p?.cmdLen ?? 0;\n const lineCount = p?.lines.length ?? 0;\n\n cur.acc += dt;\n switch (cur.phase) {\n case 'gap':\n if (cur.acc >= cur.gapMs) {\n cur.phase = 'type';\n cur.acc = 0;\n changed = true;\n }\n break;\n case 'type': {\n const iv = 1000 / Math.max(1, t.typeSpeed);\n while (cur.typed < cmdLen && cur.acc >= iv) {\n cur.acc -= iv;\n cur.typed++;\n changed = true;\n }\n if (cur.typed >= cmdLen) {\n cur.phase = 'think';\n cur.acc = 0;\n }\n break;\n }\n case 'think':\n if (cur.acc >= t.thinkMs) {\n cur.acc = 0;\n if (lineCount > 0) {\n cur.phase = 'output';\n } else {\n advance(cur, l, t);\n changed = true;\n }\n }\n break;\n case 'output': {\n const iv = 1000 / Math.max(0.5, t.outputSpeed);\n while (cur.outLines < lineCount && cur.acc >= iv) {\n cur.acc -= iv;\n cur.outLines++;\n changed = true;\n }\n if (cur.outLines >= lineCount) {\n advance(cur, l, t);\n changed = true;\n }\n break;\n }\n default:\n break;\n }\n\n if (changed) setRender({ ...cur });\n if (cur.index >= l.length) {\n runningRef.current = false;\n onIdleRef.current?.();\n return;\n }\n rafRef.current = requestAnimationFrame(frame);\n };\n\n // Move the cursor to the next entry, computing its compressed start gap.\n const advance = (cur: Cursor, l: BashEntry[], t: PlaybackTuning) => {\n const prev = l[cur.index];\n const nextIdx = cur.index + 1;\n cur.index = nextIdx;\n cur.typed = 0;\n cur.outLines = 0;\n cur.acc = 0;\n if (nextIdx >= l.length) {\n cur.phase = 'idle';\n } else {\n cur.gapMs = computeGapMs(prev?.timestamp, l[nextIdx].timestamp, t);\n cur.phase = 'gap';\n }\n };\n\n kickRef.current = () => {\n if (runningRef.current) return;\n const cur = cursor.current;\n const l = listRef.current;\n if (cur.index >= l.length) return; // nothing new to play\n if (cur.phase === 'idle') {\n // Resuming after a lull: schedule the fresh entry's gap.\n const prev = l[cur.index - 1];\n cur.gapMs = cur.index === 0 ? t0Gap(tuningRef.current) : computeGapMs(prev?.timestamp, l[cur.index].timestamp, tuningRef.current);\n cur.phase = 'gap';\n cur.acc = 0;\n }\n runningRef.current = true;\n lastTs = 0;\n rafRef.current = requestAnimationFrame(frame);\n };\n\n return () => {\n cancelAnimationFrame(rafRef.current);\n runningRef.current = false;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n // Skip / instant: jump straight to fully-revealed.\n useEffect(() => {\n if (!skip) return;\n cursor.current = { index: playList.length, phase: 'idle', typed: 0, outLines: 0, acc: 0, gapMs: 0 };\n setRender({ ...cursor.current });\n }, [skip, playList.length]);\n\n // Catch-up: on first paint, fast-forward past every entry already in the past\n // relative to the `catchUp` reference so a reload doesn't re-type finished\n // history — only entries at/after \"now\" animate live. Runs once.\n const caughtUp = useRef(false);\n useEffect(() => {\n if (caughtUp.current || skip || !catchUp || playList.length === 0) return;\n caughtUp.current = true;\n const ref = typeof catchUp === 'number' ? catchUp : Date.now();\n let idx = 0;\n while (idx < playList.length && playList[idx].timestamp != null && (playList[idx].timestamp as number) <= ref) idx++;\n if (idx <= 0) return; // nothing is in the past — play normally\n cursor.current = {\n index: idx,\n phase: idx >= playList.length ? 'idle' : 'gap',\n typed: 0,\n outLines: 0,\n acc: 0,\n gapMs: 0,\n };\n setRender({ ...cursor.current });\n }, [catchUp, playList, skip]);\n\n // React to list growth: (re)start the loop unless skipping.\n useEffect(() => {\n if (skip) return;\n if (playList.length === 0) return;\n // First entry's initial gap.\n if (cursor.current.index === 0 && cursor.current.phase === 'gap' && cursor.current.typed === 0 && cursor.current.gapMs === 0) {\n cursor.current.gapMs = t0Gap(tuning);\n }\n kickRef.current();\n }, [playList, skip, tuning]);\n\n // ---- Autoscroll-lock (release the moment the user scrolls up) -------------\n const scrollRef = useRef<HTMLDivElement>(null);\n const stick = useRef(true);\n const [atBottom, setAtBottom] = useState(true);\n\n const scrollToBottom = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n el.scrollTop = el.scrollHeight;\n stick.current = true;\n setAtBottom(true);\n }, []);\n\n const onScroll = useCallback(() => {\n const el = scrollRef.current;\n if (!el) return;\n const near = el.scrollHeight - el.scrollTop - el.clientHeight < NEAR_BOTTOM_PX;\n stick.current = near;\n setAtBottom((cur) => (cur === near ? cur : near));\n }, []);\n\n useEffect(() => {\n if (stick.current) {\n const el = scrollRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n }\n }, [render]);\n\n useImperativeHandle(\n apiRef,\n () => ({\n push: (e: BashEntry | BashEntry[]) => appendEntries(Array.isArray(e) ? e : [e]),\n clear: () => {\n seen.current = new Set();\n cursor.current = { index: 0, phase: 'gap', typed: 0, outLines: 0, acc: 0, gapMs: 0 };\n setRender({ ...cursor.current });\n setList([]);\n },\n skipToEnd: () => {\n cursor.current = { index: listRef.current.length, phase: 'idle', typed: 0, outLines: 0, acc: 0, gapMs: 0 };\n setRender({ ...cursor.current });\n },\n scrollToBottom,\n }),\n [appendEntries, scrollToBottom],\n );\n\n const rootStyle: CSSProperties = { ...PALETTE, ...style, background: 'var(--tb-bg)' } as CSSProperties;\n\n return (\n <div\n className={cn('ds-terminal relative flex h-full min-h-0 flex-col font-mono text-[12.5px] leading-[1.55]', className)}\n style={rootStyle}\n >\n <div\n ref={scrollRef}\n onScroll={onScroll}\n className={cn('min-h-0 flex-1 overflow-y-auto px-3 py-2.5', bodyClassName)}\n style={{ color: 'var(--tb-fg)' }}\n >\n {playList.length === 0 ? (\n <div className=\"select-none py-6 text-center\" style={{ color: 'var(--tb-dim)' }}>\n {prompt} waiting for commands…\n </div>\n ) : (\n playList.map((entry, i) => (\n <BashBlock\n key={entry.id}\n entry={entry}\n parsed={parsed.get(entry.id)!}\n prompt={prompt}\n showDescriptions={showDescriptions}\n stickyPrompt={stickyPrompt}\n state={blockState(i, render)}\n />\n ))\n )}\n </div>\n {!atBottom && (\n <button\n type=\"button\"\n onClick={scrollToBottom}\n className=\"absolute bottom-3 right-3 rounded-full px-2.5 py-1 text-[11px] shadow-lg\"\n style={{ background: 'var(--tb-header)', color: 'var(--tb-fg)', border: '1px solid var(--tb-border)' }}\n >\n ↓ live\n </button>\n )}\n </div>\n );\n}\n\n/** A short initial pause before the very first command types in. */\nfunction t0Gap(t: PlaybackTuning): number {\n return t.fixedDelay != null ? Math.max(0, t.fixedDelay * 1000) : Math.min(300, t.minGapMs);\n}\n\ntype BlockState =\n | { revealed: false }\n | { revealed: true; typed: number; outLines: number; caret: 'cmd' | 'out' | null; full: boolean };\n\nfunction blockState(i: number, cur: Cursor): BlockState {\n if (i < cur.index) return { revealed: true, typed: Infinity, outLines: Infinity, caret: null, full: true };\n if (i > cur.index) return { revealed: false };\n // The active block.\n const caret = cur.phase === 'type' || cur.phase === 'think' ? 'cmd' : cur.phase === 'output' ? 'out' : null;\n return { revealed: true, typed: cur.typed, outLines: cur.outLines, caret, full: false };\n}\n\nfunction BashBlock({\n entry,\n parsed,\n prompt,\n showDescriptions,\n stickyPrompt,\n state,\n}: {\n entry: BashEntry;\n parsed: Parsed;\n prompt: string;\n showDescriptions: boolean;\n stickyPrompt: boolean;\n state: BlockState;\n}) {\n if (!state.revealed) return null;\n const typedTokens = state.full ? parsed.tokens : sliceTokens(parsed.tokens, state.typed);\n const cmdDone = state.full || state.typed >= parsed.cmdLen;\n const lines = state.full ? parsed.lines : parsed.lines.slice(0, state.outLines);\n const failed = entry.isError || (entry.exitCode != null && entry.exitCode !== 0);\n\n const cmdRowStyle: CSSProperties | undefined = stickyPrompt\n ? { position: 'sticky', top: 0, zIndex: 2, background: 'var(--tb-bg)' }\n : undefined;\n\n return (\n <div className=\"mb-1.5\">\n <div className=\"flex flex-col\" style={cmdRowStyle}>\n {showDescriptions && entry.description && cmdDone && (\n <div className=\"whitespace-pre-wrap\" style={{ color: 'var(--tb-dim)' }}>\n # {entry.description}\n </div>\n )}\n <div className=\"flex whitespace-pre-wrap break-all\">\n <span\n className=\"mr-1.5 shrink-0 select-none\"\n style={{ color: failed ? 'var(--tb-red)' : 'var(--tb-prompt)' }}\n >\n {entry.cwd ? <span style={{ color: 'var(--tb-blue)' }}>{entry.cwd} </span> : null}\n {prompt}\n </span>\n <span className=\"min-w-0\">\n {typedTokens.map((t, idx) => (\n <span key={idx} style={{ color: CMD_COLOR[t.kind], fontWeight: t.kind === 'program' ? 600 : undefined }}>\n {t.text}\n </span>\n ))}\n {state.caret === 'cmd' && <Caret />}\n </span>\n </div>\n </div>\n {lines.length > 0 && (\n <div className=\"mt-0.5\">\n {lines.map((ln, idx) =>\n ln.divider ? (\n <div\n key={idx}\n className=\"my-1 flex items-center gap-2 text-[10.5px] font-semibold uppercase tracking-wider\"\n style={{ color: 'var(--tb-cyan)' }}\n >\n <span className=\"h-px flex-1\" style={{ background: 'var(--tb-border)' }} />\n {ln.spans[0]?.text}\n <span className=\"h-px flex-1\" style={{ background: 'var(--tb-border)' }} />\n </div>\n ) : (\n <div key={idx} className=\"whitespace-pre-wrap break-all\" style={{ color: LINE_COLOR[ln.kind] }}>\n {ln.spans.map((s, sIdx) => (\n <span key={sIdx} style={s.accent ? { color: ACCENT_COLOR[s.accent] } : undefined}>\n {s.text}\n </span>\n ))}\n {state.caret === 'out' && idx === lines.length - 1 && <Caret />}\n </div>\n ),\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction Caret() {\n return (\n <span aria-hidden className=\"ml-px inline-block animate-pulse\" style={{ color: 'var(--tb-fg)' }}>\n ▋\n </span>\n );\n}\n"],"names":["PALETTE","CMD_COLOR","LINE_COLOR","ACCENT_COLOR","expandSubparts","entries","out","e","subs","splitBySubparts","s","i","sliceTokens","tokens","n","used","t","reducedMotion","NEAR_BOTTOM_PX","ProgressiveBash","typeSpeed","DEFAULT_TUNING","outputSpeed","delay","minGap","maxGap","gapReference","think","instant","catchUp","stickyPrompt","experimentalSubparts","prompt","showDescriptions","onIdle","className","bodyClassName","style","apiRef","skip","list","setList","useState","seen","useRef","appendEntries","useCallback","incoming","fresh","l","useEffect","playList","useMemo","listRef","parsed","map","tokenizeCommand","splitOutput","parsedRef","tuning","tuningRef","render","setRender","cursor","rafRef","runningRef","kickRef","onIdleRef","lastTs","frame","ts","dt","cur","changed","p","cmdLen","lineCount","iv","advance","_a","prev","nextIdx","computeGapMs","t0Gap","caughtUp","ref","idx","scrollRef","stick","atBottom","setAtBottom","scrollToBottom","el","onScroll","near","useImperativeHandle","rootStyle","jsxs","cn","jsx","entry","BashBlock","blockState","caret","state","typedTokens","cmdDone","lines","failed","Caret","ln","sIdx"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ProgressiveList } from './progressive-list';
2
+ export type { ProgressiveListProps, ProgressiveListItemMeta } from './progressive-list';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/progressive-list/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { Key, ReactNode, Ref } from 'react';
2
+ export interface ProgressiveListItemMeta {
3
+ /** This item was revealed by the animation (appended after mount), not part of
4
+ * the instantly-shown initial batch. */
5
+ isNew: boolean;
6
+ }
7
+ export interface ProgressiveListProps<T> {
8
+ items: readonly T[];
9
+ /** Render one item. Wrap animating rows on `meta.isNew`. */
10
+ children: (item: T, index: number, meta: ProgressiveListItemMeta) => ReactNode;
11
+ /**
12
+ * Fallback pace for items that don't drive the timeline themselves: rows with
13
+ * no progressive child hand off this many items per second. Rows that *do*
14
+ * contain a progressive element (e.g. {@link ProgressiveText}) instead hold
15
+ * the timeline until their own inner animation reports done. @default 4
16
+ */
17
+ speed?: number;
18
+ /** Seconds to wait before the first newly-appended item is revealed. @default 0 */
19
+ delay?: number;
20
+ /**
21
+ * Per-item fallback delay, in seconds, before the timeline advances past it —
22
+ * overrides the `speed`-derived interval for rows that don't report a duration.
23
+ */
24
+ getDelay?: (item: T, index: number) => number;
25
+ /** Stable key per item. @default the index */
26
+ getKey?: (item: T, index: number) => Key;
27
+ /**
28
+ * How many leading items to show instantly on mount, with no animation.
29
+ * @default items.length — an already-populated list appears at once and only
30
+ * items appended *after* mount animate in. Pass `0` to replay the whole list.
31
+ */
32
+ initialReveal?: number;
33
+ /** Reveal everything immediately, no animation. */
34
+ instant?: boolean;
35
+ /** Ref forwarded to the wrapper `<div>` (e.g. for scroll / query access). */
36
+ containerRef?: Ref<HTMLDivElement>;
37
+ className?: string;
38
+ /** Extra classes on the reveal wrapper of each animating item. */
39
+ itemClassName?: string;
40
+ }
41
+ /**
42
+ * Reveals a list one item at a time, in order, and — crucially — waits for each
43
+ * item's *inner* animation before revealing the next. It does this through a
44
+ * timeline context ({@link useProgressiveSlot}): each animating row is wrapped in
45
+ * a slot; the row's progressive children (e.g. {@link ProgressiveText}) report
46
+ * how long they animate, and the next row only appears once that finishes. Rows
47
+ * without any progressive child fall back to a constant `speed`.
48
+ *
49
+ * Items present when the component mounts are shown instantly (see
50
+ * `initialReveal`); only items appended later run through the timeline — so a
51
+ * live, append-only feed animates only its genuinely-new rows and never replays
52
+ * history.
53
+ */
54
+ export declare function ProgressiveList<T>({ items, children, speed, delay, getDelay, getKey, initialReveal, instant, containerRef, className, itemClassName, }: ProgressiveListProps<T>): import("react").JSX.Element;
55
+ //# sourceMappingURL=progressive-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressive-list.d.ts","sourceRoot":"","sources":["../../../src/components/progressive-list/progressive-list.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,GAAG,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAKrG,MAAM,WAAW,uBAAuB;IACtC;6CACyC;IACzC,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB,CAAC,CAAC;IACrC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;IACpB,4DAA4D;IAC5D,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,uBAAuB,KAAK,SAAS,CAAC;IAC/E;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9C,8CAA8C;IAC9C,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,GAAG,CAAC;IACzC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAUD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,EACjC,KAAK,EACL,QAAQ,EACR,KAAS,EACT,KAAS,EACT,QAAQ,EACR,MAAM,EACN,aAAa,EACb,OAAe,EACf,YAAY,EACZ,SAAS,EACT,aAAa,GACd,EAAE,oBAAoB,CAAC,CAAC,CAAC,+BA+EzB"}
@@ -0,0 +1,83 @@
1
+ import { jsx as o, Fragment as q } from "react/jsx-runtime";
2
+ import { useRef as p, useState as w, useCallback as E, useEffect as S } from "react";
3
+ import { cn as L } from "../../lib/utils.js";
4
+ import { ProgressiveTimelineSlot as z } from "../progressive-timeline/progressive-timeline.js";
5
+ function B() {
6
+ return typeof window < "u" && typeof window.matchMedia == "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
7
+ }
8
+ function O({
9
+ items: e,
10
+ children: h,
11
+ speed: c = 4,
12
+ delay: a = 0,
13
+ getDelay: i,
14
+ getKey: s,
15
+ initialReveal: F,
16
+ instant: N = !1,
17
+ containerRef: T,
18
+ className: b,
19
+ itemClassName: g
20
+ }) {
21
+ const u = N || B(), m = p(-1);
22
+ m.current < 0 && (m.current = u ? e.length : Math.min(F ?? e.length, e.length));
23
+ const l = m.current, [r, v] = w(l), [M, A] = w(0), I = E(() => A((n) => n + 1), []), R = p(e);
24
+ R.current = e;
25
+ const y = p(i);
26
+ y.current = i, S(() => {
27
+ if (u) {
28
+ r !== e.length && v(e.length);
29
+ return;
30
+ }
31
+ if (r >= e.length) return;
32
+ const n = r - l;
33
+ if (M < n) return;
34
+ const t = n === 0 ? a * 1e3 : 0, f = window.setTimeout(
35
+ () => v((d) => Math.min(d + 1, R.current.length)),
36
+ t
37
+ );
38
+ return () => window.clearTimeout(f);
39
+ }, [r, M, e.length, u, a, l]);
40
+ const P = r - 1;
41
+ return /* @__PURE__ */ o("div", { ref: T, className: b, children: e.slice(0, r).map((n, t) => {
42
+ const f = s ? s(n, t) : t, d = t >= l, k = h(n, t, { isNew: d });
43
+ if (!d || u)
44
+ return /* @__PURE__ */ o(C, { animate: !1, className: g, children: k }, f);
45
+ const x = y.current, j = x ? x(n, t) * 1e3 : 1e3 / Math.max(1e-3, c);
46
+ return /* @__PURE__ */ o(
47
+ z,
48
+ {
49
+ active: t === P,
50
+ fallbackMs: j,
51
+ onComplete: I,
52
+ children: /* @__PURE__ */ o(C, { animate: !0, className: g, children: k })
53
+ },
54
+ f
55
+ );
56
+ }) });
57
+ }
58
+ function C({
59
+ animate: e,
60
+ className: h,
61
+ children: c
62
+ }) {
63
+ const [a, i] = w(!e);
64
+ return S(() => {
65
+ if (!e) return;
66
+ const s = requestAnimationFrame(() => i(!0));
67
+ return () => cancelAnimationFrame(s);
68
+ }, [e]), e ? /* @__PURE__ */ o(
69
+ "div",
70
+ {
71
+ className: L(
72
+ "transition-all duration-300 ease-out",
73
+ a ? "translate-y-0 opacity-100" : "translate-y-1 opacity-0",
74
+ h
75
+ ),
76
+ children: c
77
+ }
78
+ ) : /* @__PURE__ */ o(q, { children: c });
79
+ }
80
+ export {
81
+ O as ProgressiveList
82
+ };
83
+ //# sourceMappingURL=progressive-list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"progressive-list.js","sources":["../../../src/components/progressive-list/progressive-list.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState, type Key, type ReactNode, type Ref } from 'react';\n\nimport { cn } from '../../lib/utils';\nimport { ProgressiveTimelineSlot } from '../progressive-timeline';\n\nexport interface ProgressiveListItemMeta {\n /** This item was revealed by the animation (appended after mount), not part of\n * the instantly-shown initial batch. */\n isNew: boolean;\n}\n\nexport interface ProgressiveListProps<T> {\n items: readonly T[];\n /** Render one item. Wrap animating rows on `meta.isNew`. */\n children: (item: T, index: number, meta: ProgressiveListItemMeta) => ReactNode;\n /**\n * Fallback pace for items that don't drive the timeline themselves: rows with\n * no progressive child hand off this many items per second. Rows that *do*\n * contain a progressive element (e.g. {@link ProgressiveText}) instead hold\n * the timeline until their own inner animation reports done. @default 4\n */\n speed?: number;\n /** Seconds to wait before the first newly-appended item is revealed. @default 0 */\n delay?: number;\n /**\n * Per-item fallback delay, in seconds, before the timeline advances past it —\n * overrides the `speed`-derived interval for rows that don't report a duration.\n */\n getDelay?: (item: T, index: number) => number;\n /** Stable key per item. @default the index */\n getKey?: (item: T, index: number) => Key;\n /**\n * How many leading items to show instantly on mount, with no animation.\n * @default items.length — an already-populated list appears at once and only\n * items appended *after* mount animate in. Pass `0` to replay the whole list.\n */\n initialReveal?: number;\n /** Reveal everything immediately, no animation. */\n instant?: boolean;\n /** Ref forwarded to the wrapper `<div>` (e.g. for scroll / query access). */\n containerRef?: Ref<HTMLDivElement>;\n className?: string;\n /** Extra classes on the reveal wrapper of each animating item. */\n itemClassName?: string;\n}\n\nfunction reducedMotion(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\n/**\n * Reveals a list one item at a time, in order, and — crucially — waits for each\n * item's *inner* animation before revealing the next. It does this through a\n * timeline context ({@link useProgressiveSlot}): each animating row is wrapped in\n * a slot; the row's progressive children (e.g. {@link ProgressiveText}) report\n * how long they animate, and the next row only appears once that finishes. Rows\n * without any progressive child fall back to a constant `speed`.\n *\n * Items present when the component mounts are shown instantly (see\n * `initialReveal`); only items appended later run through the timeline — so a\n * live, append-only feed animates only its genuinely-new rows and never replays\n * history.\n */\nexport function ProgressiveList<T>({\n items,\n children,\n speed = 4,\n delay = 0,\n getDelay,\n getKey,\n initialReveal,\n instant = false,\n containerRef,\n className,\n itemClassName,\n}: ProgressiveListProps<T>) {\n const skip = instant || reducedMotion();\n\n // Fixed at mount: how many items were \"already there\" (shown instantly).\n const initialRef = useRef<number>(-1);\n if (initialRef.current < 0) {\n initialRef.current = skip ? items.length : Math.min(initialReveal ?? items.length, items.length);\n }\n const initialCount = initialRef.current;\n\n const [revealed, setRevealed] = useState(initialCount);\n // How many of the animating slots ([initialCount, revealed)) have handed off.\n const [completed, setCompleted] = useState(0);\n const handleComplete = useCallback(() => setCompleted((c) => c + 1), []);\n\n // Latest values read by the reveal scheduler without forcing it to reschedule.\n const itemsRef = useRef(items);\n itemsRef.current = items;\n const getDelayRef = useRef(getDelay);\n getDelayRef.current = getDelay;\n\n // Advance the timeline: reveal the next item only once every already-revealed\n // animating slot has completed its inner animation (or its fallback elapsed).\n useEffect(() => {\n if (skip) {\n if (revealed !== items.length) setRevealed(items.length);\n return;\n }\n if (revealed >= items.length) return;\n const animatingShown = revealed - initialCount;\n if (completed < animatingShown) return; // the current head is still animating\n // First item of a fresh batch waits the lead-in `delay`; the rest chain off\n // completions, so their spacing comes from each row's own inner animation.\n const wait = animatingShown === 0 ? delay * 1000 : 0;\n const t = window.setTimeout(\n () => setRevealed((r) => Math.min(r + 1, itemsRef.current.length)),\n wait,\n );\n return () => window.clearTimeout(t);\n }, [revealed, completed, items.length, skip, delay, initialCount]);\n\n const headIndex = revealed - 1; // the one currently animating\n\n return (\n <div ref={containerRef} className={className}>\n {items.slice(0, revealed).map((item, i) => {\n const key = getKey ? getKey(item, i) : i;\n const isNew = i >= initialCount;\n const content = children(item, i, { isNew });\n\n // Historical / instant rows: no timeline slot, a bare keyed child so the\n // container's own spacing (e.g. space-y) still targets the real row.\n if (!isNew || skip) {\n return (\n <RevealItem key={key} animate={false} className={itemClassName}>\n {content}\n </RevealItem>\n );\n }\n\n // Animating rows: a timeline slot gates the next reveal on this row's\n // inner animation (its progressive children report their duration).\n const gd = getDelayRef.current;\n const fallbackMs = gd ? gd(item, i) * 1000 : 1000 / Math.max(0.001, speed);\n return (\n <ProgressiveTimelineSlot\n key={key}\n active={i === headIndex}\n fallbackMs={fallbackMs}\n onComplete={handleComplete}\n >\n <RevealItem animate className={itemClassName}>\n {content}\n </RevealItem>\n </ProgressiveTimelineSlot>\n );\n })}\n </div>\n );\n}\n\n/** Fades/slides its child in on mount; a passthrough when `animate` is false. */\nfunction RevealItem({\n animate,\n className,\n children,\n}: {\n animate: boolean;\n className?: string;\n children: ReactNode;\n}) {\n const [shown, setShown] = useState(!animate);\n useEffect(() => {\n if (!animate) return;\n const id = requestAnimationFrame(() => setShown(true));\n return () => cancelAnimationFrame(id);\n }, [animate]);\n\n if (!animate) return <>{children}</>;\n return (\n <div\n className={cn(\n 'transition-all duration-300 ease-out',\n shown ? 'translate-y-0 opacity-100' : 'translate-y-1 opacity-0',\n className,\n )}\n >\n {children}\n </div>\n );\n}\n"],"names":["reducedMotion","ProgressiveList","items","children","speed","delay","getDelay","getKey","initialReveal","instant","containerRef","className","itemClassName","skip","initialRef","useRef","initialCount","revealed","setRevealed","useState","completed","setCompleted","handleComplete","useCallback","c","itemsRef","getDelayRef","useEffect","animatingShown","wait","t","r","headIndex","jsx","item","i","key","isNew","content","RevealItem","gd","fallbackMs","ProgressiveTimelineSlot","animate","shown","setShown","id","cn","Fragment"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { ProgressiveTable } from './progressive-table';
2
+ export type { ProgressiveTableProps, ProgressiveTableCellContext } from './progressive-table';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/progressive-table/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,YAAY,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC"}