@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,88 @@
1
+ import { useState as h, useCallback as p } from "react";
2
+ function R(t, a) {
3
+ const o = typeof URL < "u" && t.type.startsWith("image/") ? URL.createObjectURL(t) : void 0;
4
+ return {
5
+ id: `${t.name}:${t.size}:${t.lastModified}:${a}`,
6
+ name: t.name,
7
+ size: t.size,
8
+ contentType: t.type || "application/octet-stream",
9
+ url: o,
10
+ meta: t
11
+ };
12
+ }
13
+ function W(t, a) {
14
+ if (!t) return !0;
15
+ const o = t.split(",").map((n) => n.trim().toLowerCase()).filter(Boolean);
16
+ if (o.length === 0) return !0;
17
+ const u = a.name.toLowerCase(), l = a.type.toLowerCase();
18
+ return o.some((n) => n.startsWith(".") ? u.endsWith(n) : n.endsWith("/*") ? l.startsWith(n.slice(0, -1)) : l === n);
19
+ }
20
+ function j({
21
+ upload: t,
22
+ accept: a,
23
+ maxFiles: o,
24
+ filter: u
25
+ }) {
26
+ const [l, n] = h([]), [y, g] = h(!1), [$, s] = h(null), L = p(
27
+ async (f) => {
28
+ const i = Array.from(f ?? []);
29
+ if (i.length === 0) return;
30
+ s(null);
31
+ const r = [];
32
+ for (const e of i) {
33
+ if (!W(a, e)) {
34
+ s(`${e.name}: type not accepted`);
35
+ continue;
36
+ }
37
+ const m = u == null ? void 0 : u(e);
38
+ if (m === !1) {
39
+ s(`${e.name}: rejected`);
40
+ continue;
41
+ }
42
+ if (typeof m == "string") {
43
+ s(`${e.name}: ${m}`);
44
+ continue;
45
+ }
46
+ r.push(e);
47
+ }
48
+ if (r.length === 0) return;
49
+ const d = o == null ? r.length : Math.max(0, o - l.length);
50
+ if (d <= 0) {
51
+ s(`At most ${o} file${o === 1 ? "" : "s"}`);
52
+ return;
53
+ }
54
+ const c = r.slice(0, d);
55
+ if (c.length < r.length && s(`At most ${o} files`), !t) {
56
+ n((e) => [...e, ...c.map(R)]);
57
+ return;
58
+ }
59
+ g(!0);
60
+ try {
61
+ const e = await t(c);
62
+ n((m) => [...m, ...e]);
63
+ } catch (e) {
64
+ s(e instanceof Error ? e.message : String(e));
65
+ } finally {
66
+ g(!1);
67
+ }
68
+ },
69
+ [a, o, u, t, l.length]
70
+ ), U = p((f) => {
71
+ n((i) => {
72
+ var d;
73
+ const r = i.find((c) => c.id === f);
74
+ return (d = r == null ? void 0 : r.url) != null && d.startsWith("blob:") && URL.revokeObjectURL(r.url), i.filter((c) => c.id !== f);
75
+ });
76
+ }, []), b = p(() => {
77
+ n((f) => {
78
+ var i;
79
+ for (const r of f) (i = r.url) != null && i.startsWith("blob:") && URL.revokeObjectURL(r.url);
80
+ return [];
81
+ }), s(null);
82
+ }, []);
83
+ return { files: l, uploading: y, error: $, add: L, remove: U, reset: b, setFiles: n };
84
+ }
85
+ export {
86
+ j as useFileUpload
87
+ };
88
+ //# sourceMappingURL=use-file-upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-file-upload.js","sources":["../../../src/components/rich-input/use-file-upload.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\n\nimport type { RichFile } from './types';\n\n/** Turn a browser File into a local RichFile (used when no uploader is given). */\nfunction localFile(file: File, i: number): RichFile {\n const url =\n typeof URL !== 'undefined' && file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined;\n return {\n id: `${file.name}:${file.size}:${file.lastModified}:${i}`,\n name: file.name,\n size: file.size,\n contentType: file.type || 'application/octet-stream',\n url,\n meta: file,\n };\n}\n\n/** Does `accept` (an <input accept> string) admit this file? */\nfunction acceptsFile(accept: string | undefined, file: File): boolean {\n if (!accept) return true;\n const parts = accept.split(',').map((p) => p.trim().toLowerCase()).filter(Boolean);\n if (parts.length === 0) return true;\n const name = file.name.toLowerCase();\n const type = file.type.toLowerCase();\n return parts.some((p) => {\n if (p.startsWith('.')) return name.endsWith(p);\n if (p.endsWith('/*')) return type.startsWith(p.slice(0, -1));\n return type === p;\n });\n}\n\nexport interface FileUpload {\n files: RichFile[];\n uploading: boolean;\n error: string | null;\n add: (list: FileList | File[] | null) => Promise<void>;\n remove: (id: string) => void;\n reset: () => void;\n setFiles: (files: RichFile[]) => void;\n}\n\nexport function useFileUpload({\n upload,\n accept,\n maxFiles,\n filter,\n}: {\n upload?: (files: File[]) => Promise<RichFile[]>;\n accept?: string;\n maxFiles?: number;\n /** Return `true` to keep, `false`/reason-string to reject a file. */\n filter?: (file: File) => boolean | string;\n}): FileUpload {\n const [files, setFilesState] = useState<RichFile[]>([]);\n const [uploading, setUploading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const add = useCallback(\n async (list: FileList | File[] | null) => {\n const picked = Array.from(list ?? []);\n if (picked.length === 0) return;\n setError(null);\n\n const kept: File[] = [];\n for (const f of picked) {\n if (!acceptsFile(accept, f)) {\n setError(`${f.name}: type not accepted`);\n continue;\n }\n const verdict = filter?.(f);\n if (verdict === false) {\n setError(`${f.name}: rejected`);\n continue;\n }\n if (typeof verdict === 'string') {\n setError(`${f.name}: ${verdict}`);\n continue;\n }\n kept.push(f);\n }\n if (kept.length === 0) return;\n\n const room = maxFiles == null ? kept.length : Math.max(0, maxFiles - files.length);\n if (room <= 0) {\n setError(`At most ${maxFiles} file${maxFiles === 1 ? '' : 's'}`);\n return;\n }\n const admitted = kept.slice(0, room);\n if (admitted.length < kept.length) setError(`At most ${maxFiles} files`);\n\n if (!upload) {\n setFilesState((prev) => [...prev, ...admitted.map(localFile)]);\n return;\n }\n\n setUploading(true);\n try {\n const stored = await upload(admitted);\n setFilesState((prev) => [...prev, ...stored]);\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n } finally {\n setUploading(false);\n }\n },\n [accept, maxFiles, filter, upload, files.length],\n );\n\n const remove = useCallback((id: string) => {\n setFilesState((prev) => {\n const gone = prev.find((f) => f.id === id);\n if (gone?.url?.startsWith('blob:')) URL.revokeObjectURL(gone.url);\n return prev.filter((f) => f.id !== id);\n });\n }, []);\n\n const reset = useCallback(() => {\n setFilesState((prev) => {\n for (const f of prev) if (f.url?.startsWith('blob:')) URL.revokeObjectURL(f.url);\n return [];\n });\n setError(null);\n }, []);\n\n return { files, uploading, error, add, remove, reset, setFiles: setFilesState };\n}\n"],"names":["localFile","file","i","url","acceptsFile","accept","parts","p","name","type","useFileUpload","upload","maxFiles","filter","files","setFilesState","useState","uploading","setUploading","error","setError","add","useCallback","list","picked","kept","f","verdict","room","admitted","prev","stored","remove","id","gone","_a","reset"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { GuidelineTag } from './types';
2
+ export interface Guidelines {
3
+ /** Ids of tags currently on. */
4
+ selected: Set<string>;
5
+ toggle: (id: string) => void;
6
+ setOn: (id: string, on: boolean) => void;
7
+ clear: () => void;
8
+ /** Tags that are active (toggle-on, or mention-picked). */
9
+ active: GuidelineTag[];
10
+ /** Injected guideline lines for the current selection. */
11
+ lines: string[];
12
+ /** Toggle tags (the chip row); mention-only tags are excluded. */
13
+ toggles: GuidelineTag[];
14
+ }
15
+ export declare function useGuidelines(tags: GuidelineTag[]): Guidelines;
16
+ //# sourceMappingURL=use-guidelines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-guidelines.d.ts","sourceRoot":"","sources":["../../../src/components/rich-input/use-guidelines.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,2DAA2D;IAC3D,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,kEAAkE;IAClE,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB;AAiBD,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,UAAU,CA8F9D"}
@@ -0,0 +1,85 @@
1
+ import { useState as O, useCallback as u, useRef as g, useEffect as y, useMemo as a } from "react";
2
+ import { tagGuideline as z } from "./compose.js";
3
+ function h(o) {
4
+ const l = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set();
5
+ for (const c of o)
6
+ if (!((c.kind ?? "toggle") !== "toggle" || !c.defaultOn)) {
7
+ if (c.exclusive) {
8
+ if (r.has(c.exclusive)) continue;
9
+ r.add(c.exclusive);
10
+ }
11
+ l.add(c.id);
12
+ }
13
+ return l;
14
+ }
15
+ function j(o) {
16
+ const [l, r] = O(() => h(o)), c = u(
17
+ (e) => {
18
+ var t;
19
+ const s = (t = o.find((i) => i.id === e)) == null ? void 0 : t.exclusive;
20
+ return s ? o.filter((i) => i.exclusive === s && i.id !== e).map((i) => i.id) : [];
21
+ },
22
+ [o]
23
+ ), m = g(new Set(o.map((e) => e.id))), x = o.map((e) => e.id).join(",");
24
+ y(() => {
25
+ r((e) => {
26
+ const s = new Set(o.map((n) => n.id)), t = new Set([...e].filter((n) => s.has(n))), i = new Set(
27
+ o.filter((n) => n.exclusive && t.has(n.id)).map((n) => n.exclusive)
28
+ );
29
+ for (const n of o)
30
+ if (!((n.kind ?? "toggle") !== "toggle" || !n.defaultOn || m.current.has(n.id))) {
31
+ if (n.exclusive) {
32
+ if (i.has(n.exclusive)) continue;
33
+ i.add(n.exclusive);
34
+ }
35
+ t.add(n.id);
36
+ }
37
+ return m.current = s, t.size === e.size && [...t].every((n) => e.has(n)) ? e : t;
38
+ });
39
+ }, [x]);
40
+ const p = u(
41
+ (e) => {
42
+ r((s) => {
43
+ const t = new Set(s);
44
+ if (t.has(e))
45
+ t.delete(e);
46
+ else {
47
+ for (const i of c(e)) t.delete(i);
48
+ t.add(e);
49
+ }
50
+ return t;
51
+ });
52
+ },
53
+ [c]
54
+ ), S = u(
55
+ (e, s) => {
56
+ r((t) => {
57
+ const i = s ? c(e) : [];
58
+ if (t.has(e) === s && !i.some((d) => t.has(d))) return t;
59
+ const n = new Set(t);
60
+ if (s) {
61
+ for (const d of i) n.delete(d);
62
+ n.add(e);
63
+ } else
64
+ n.delete(e);
65
+ return n;
66
+ });
67
+ },
68
+ [c]
69
+ ), w = u(() => r(h(o)), [o]), f = a(() => o.filter((e) => (e.kind ?? "toggle") === "toggle"), [o]), k = a(() => o.filter((e) => l.has(e.id)), [o, l]), v = a(() => {
70
+ var s;
71
+ const e = [];
72
+ for (const t of f) {
73
+ const i = z(t, l.has(t.id));
74
+ i && e.push(i);
75
+ }
76
+ for (const t of o)
77
+ (t.kind ?? "toggle") === "mention" && l.has(t.id) && ((s = t.prompt) != null && s.trim()) && e.push(t.prompt);
78
+ return e;
79
+ }, [f, o, l]);
80
+ return { selected: l, toggle: p, setOn: S, clear: w, active: k, lines: v, toggles: f };
81
+ }
82
+ export {
83
+ j as useGuidelines
84
+ };
85
+ //# sourceMappingURL=use-guidelines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-guidelines.js","sources":["../../../src/components/rich-input/use-guidelines.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport { tagGuideline } from './compose';\nimport type { GuidelineTag } from './types';\n\nexport interface Guidelines {\n /** Ids of tags currently on. */\n selected: Set<string>;\n toggle: (id: string) => void;\n setOn: (id: string, on: boolean) => void;\n clear: () => void;\n /** Tags that are active (toggle-on, or mention-picked). */\n active: GuidelineTag[];\n /** Injected guideline lines for the current selection. */\n lines: string[];\n /** Toggle tags (the chip row); mention-only tags are excluded. */\n toggles: GuidelineTag[];\n}\n\nfunction initialSelection(tags: GuidelineTag[]): Set<string> {\n const out = new Set<string>();\n const claimed = new Set<string>();\n for (const t of tags) {\n if ((t.kind ?? 'toggle') !== 'toggle' || !t.defaultOn) continue;\n // At most one default-on tag per exclusive key — the first wins.\n if (t.exclusive) {\n if (claimed.has(t.exclusive)) continue;\n claimed.add(t.exclusive);\n }\n out.add(t.id);\n }\n return out;\n}\n\nexport function useGuidelines(tags: GuidelineTag[]): Guidelines {\n const [selected, setSelected] = useState<Set<string>>(() => initialSelection(tags));\n\n // Ids to drop when `id` is turned on: the rest of its exclusive key.\n const peersOf = useCallback(\n (id: string): string[] => {\n const key = tags.find((t) => t.id === id)?.exclusive;\n if (!key) return [];\n return tags.filter((t) => t.exclusive === key && t.id !== id).map((t) => t.id);\n },\n [tags],\n );\n\n // Keep selection in sync as the tag set changes: drop ids that no longer\n // exist, seed newly-appeared default-on toggles.\n const knownIds = useRef<Set<string>>(new Set(tags.map((t) => t.id)));\n const idKey = tags.map((t) => t.id).join(',');\n useEffect(() => {\n setSelected((prev) => {\n const ids = new Set(tags.map((t) => t.id));\n const next = new Set([...prev].filter((id) => ids.has(id)));\n const taken = new Set(\n tags.filter((t) => t.exclusive && next.has(t.id)).map((t) => t.exclusive as string),\n );\n for (const t of tags) {\n if ((t.kind ?? 'toggle') !== 'toggle' || !t.defaultOn || knownIds.current.has(t.id)) continue;\n // A default-on newcomer can't claim an exclusive key that's already taken.\n if (t.exclusive) {\n if (taken.has(t.exclusive)) continue;\n taken.add(t.exclusive);\n }\n next.add(t.id);\n }\n knownIds.current = ids;\n return next.size === prev.size && [...next].every((id) => prev.has(id)) ? prev : next;\n });\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [idKey]);\n\n const toggle = useCallback(\n (id: string) => {\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(id)) {\n next.delete(id);\n } else {\n for (const peer of peersOf(id)) next.delete(peer);\n next.add(id);\n }\n return next;\n });\n },\n [peersOf],\n );\n\n const setOn = useCallback(\n (id: string, on: boolean) => {\n setSelected((prev) => {\n const peers = on ? peersOf(id) : [];\n if (prev.has(id) === on && !peers.some((p) => prev.has(p))) return prev;\n const next = new Set(prev);\n if (on) {\n for (const peer of peers) next.delete(peer);\n next.add(id);\n } else {\n next.delete(id);\n }\n return next;\n });\n },\n [peersOf],\n );\n\n const clear = useCallback(() => setSelected(initialSelection(tags)), [tags]);\n\n const toggles = useMemo(() => tags.filter((t) => (t.kind ?? 'toggle') === 'toggle'), [tags]);\n\n const active = useMemo(() => tags.filter((t) => selected.has(t.id)), [tags, selected]);\n\n const lines = useMemo(() => {\n const out: string[] = [];\n for (const t of toggles) {\n const line = tagGuideline(t, selected.has(t.id));\n if (line) out.push(line);\n }\n for (const t of tags) {\n if ((t.kind ?? 'toggle') === 'mention' && selected.has(t.id) && t.prompt?.trim()) {\n out.push(t.prompt);\n }\n }\n return out;\n }, [toggles, tags, selected]);\n\n return { selected, toggle, setOn, clear, active, lines, toggles };\n}\n"],"names":["initialSelection","tags","out","claimed","t","useGuidelines","selected","setSelected","useState","peersOf","useCallback","id","key","_a","knownIds","useRef","idKey","useEffect","prev","ids","next","taken","toggle","peer","setOn","on","peers","p","clear","toggles","useMemo","active","lines","line","tagGuideline"],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface InputHistory {
2
+ /** Newest-last list of past submissions. */
3
+ entries: string[];
4
+ /** Record a value (skips blanks and consecutive duplicates). */
5
+ push: (value: string) => void;
6
+ /** Move to an older entry. `draft` is stashed the first time. */
7
+ prev: (draft: string) => string | null;
8
+ /** Move to a newer entry, or back to the stashed draft at the end. */
9
+ next: () => string | null;
10
+ /** Whether the cursor is currently browsing history (not on the draft). */
11
+ browsing: boolean;
12
+ /** Drop the cursor back to the draft (call when the user edits manually). */
13
+ resetCursor: () => void;
14
+ /** Newest-first match for a reverse (Ctrl+R) search; `bump` cycles matches. */
15
+ reverseSearch: (query: string, bump?: boolean) => string | null;
16
+ /** Reset the reverse-search cursor. */
17
+ resetSearch: () => void;
18
+ clear: () => void;
19
+ }
20
+ /** A shell-style command history for the composer. */
21
+ export declare function useInputHistory(cacheKey: string | null | undefined, max?: number): InputHistory;
22
+ //# sourceMappingURL=use-input-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-input-history.d.ts","sourceRoot":"","sources":["../../../src/components/rich-input/use-input-history.ts"],"names":[],"mappings":"AAyBA,MAAM,WAAW,YAAY;IAC3B,4CAA4C;IAC5C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,gEAAgE;IAChE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,iEAAiE;IACjE,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACvC,sEAAsE;IACtE,IAAI,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,+EAA+E;IAC/E,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,IAAI,CAAC;IAChE,uCAAuC;IACvC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,SAAc,GAAG,YAAY,CA4FpG"}
@@ -0,0 +1,61 @@
1
+ import { useState as x, useRef as g, useCallback as l, useMemo as F } from "react";
2
+ const J = "rich-input:history:", M = 100;
3
+ function L(u) {
4
+ if (!u || typeof window > "u") return [];
5
+ try {
6
+ const s = window.localStorage.getItem(u), e = s ? JSON.parse(s) : [];
7
+ return Array.isArray(e) ? e.filter((t) => typeof t == "string") : [];
8
+ } catch {
9
+ return [];
10
+ }
11
+ }
12
+ function b(u, s) {
13
+ if (!(!u || typeof window > "u"))
14
+ try {
15
+ window.localStorage.setItem(u, JSON.stringify(s));
16
+ } catch {
17
+ }
18
+ }
19
+ function O(u, s = M) {
20
+ const e = u ? J + u : null, [t, a] = x(() => L(e)), w = g(e);
21
+ w.current !== e && (w.current = e, a(L(e)));
22
+ const r = g(t.length), d = g(""), o = g(-1), p = l(
23
+ (h) => {
24
+ const i = h.trim();
25
+ r.current = t.length, i && a((c) => {
26
+ if (c[c.length - 1] === i)
27
+ return r.current = c.length, c;
28
+ const n = [...c.filter((f) => f !== i), i].slice(-s);
29
+ return r.current = n.length, b(e, n), n;
30
+ });
31
+ },
32
+ [t.length, s, e]
33
+ ), y = l(
34
+ (h) => t.length === 0 ? null : (r.current >= t.length ? (d.current = h, r.current = t.length - 1) : r.current > 0 && (r.current -= 1), t[r.current] ?? null),
35
+ [t]
36
+ ), m = l(() => r.current >= t.length ? null : (r.current += 1, r.current >= t.length ? d.current : t[r.current] ?? null), [t]), S = l(() => {
37
+ r.current = t.length;
38
+ }, [t.length]), A = l(
39
+ (h, i = !1) => {
40
+ const c = h.trim().toLowerCase();
41
+ if (!c) return null;
42
+ const n = [];
43
+ for (let f = t.length - 1; f >= 0; f--)
44
+ t[f].toLowerCase().includes(c) && n.push(t[f]);
45
+ return n.length === 0 ? null : (i ? o.current = (o.current + 1) % n.length : (o.current < 0 || o.current >= n.length) && (o.current = 0), n[o.current]);
46
+ },
47
+ [t]
48
+ ), C = l(() => {
49
+ o.current = -1;
50
+ }, []), I = l(() => {
51
+ a([]), r.current = 0, b(e, []);
52
+ }, [e]), E = r.current < t.length;
53
+ return F(
54
+ () => ({ entries: t, push: p, prev: y, next: m, browsing: E, resetCursor: S, reverseSearch: A, resetSearch: C, clear: I }),
55
+ [t, p, y, m, E, S, A, C, I]
56
+ );
57
+ }
58
+ export {
59
+ O as useInputHistory
60
+ };
61
+ //# sourceMappingURL=use-input-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-input-history.js","sources":["../../../src/components/rich-input/use-input-history.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, useState } from 'react';\n\nconst PREFIX = 'rich-input:history:';\nconst DEFAULT_MAX = 100;\n\nfunction load(key: string | null): string[] {\n if (!key || typeof window === 'undefined') return [];\n try {\n const raw = window.localStorage.getItem(key);\n const parsed = raw ? (JSON.parse(raw) as unknown) : [];\n return Array.isArray(parsed) ? parsed.filter((x): x is string => typeof x === 'string') : [];\n } catch {\n return [];\n }\n}\n\nfunction save(key: string | null, entries: string[]) {\n if (!key || typeof window === 'undefined') return;\n try {\n window.localStorage.setItem(key, JSON.stringify(entries));\n } catch {\n /* best-effort */\n }\n}\n\nexport interface InputHistory {\n /** Newest-last list of past submissions. */\n entries: string[];\n /** Record a value (skips blanks and consecutive duplicates). */\n push: (value: string) => void;\n /** Move to an older entry. `draft` is stashed the first time. */\n prev: (draft: string) => string | null;\n /** Move to a newer entry, or back to the stashed draft at the end. */\n next: () => string | null;\n /** Whether the cursor is currently browsing history (not on the draft). */\n browsing: boolean;\n /** Drop the cursor back to the draft (call when the user edits manually). */\n resetCursor: () => void;\n /** Newest-first match for a reverse (Ctrl+R) search; `bump` cycles matches. */\n reverseSearch: (query: string, bump?: boolean) => string | null;\n /** Reset the reverse-search cursor. */\n resetSearch: () => void;\n clear: () => void;\n}\n\n/** A shell-style command history for the composer. */\nexport function useInputHistory(cacheKey: string | null | undefined, max = DEFAULT_MAX): InputHistory {\n const storageKey = cacheKey ? PREFIX + cacheKey : null;\n const [entries, setEntries] = useState<string[]>(() => load(storageKey));\n\n // Reload if the key changed.\n const prevKey = useRef(storageKey);\n if (prevKey.current !== storageKey) {\n prevKey.current = storageKey;\n setEntries(load(storageKey));\n }\n\n const cursor = useRef<number>(entries.length); // === length → on the draft\n const stash = useRef<string>('');\n const search = useRef<number>(-1); // match index for reverse search\n\n const push = useCallback(\n (value: string) => {\n const v = value.trim();\n cursor.current = entries.length; // logical reset; recomputed below on set\n if (!v) return;\n setEntries((prev) => {\n if (prev[prev.length - 1] === v) {\n cursor.current = prev.length;\n return prev;\n }\n const next = [...prev.filter((e) => e !== v), v].slice(-max);\n cursor.current = next.length;\n save(storageKey, next);\n return next;\n });\n },\n [entries.length, max, storageKey],\n );\n\n const prev = useCallback(\n (draft: string): string | null => {\n if (entries.length === 0) return null;\n if (cursor.current >= entries.length) {\n stash.current = draft; // leaving the draft\n cursor.current = entries.length - 1;\n } else if (cursor.current > 0) {\n cursor.current -= 1;\n }\n return entries[cursor.current] ?? null;\n },\n [entries],\n );\n\n const next = useCallback((): string | null => {\n if (cursor.current >= entries.length) return null; // already on the draft\n cursor.current += 1;\n if (cursor.current >= entries.length) return stash.current;\n return entries[cursor.current] ?? null;\n }, [entries]);\n\n const resetCursor = useCallback(() => {\n cursor.current = entries.length;\n }, [entries.length]);\n\n const reverseSearch = useCallback(\n (query: string, bump = false): string | null => {\n const q = query.trim().toLowerCase();\n if (!q) return null;\n // Newest-first list of matches.\n const matches: string[] = [];\n for (let i = entries.length - 1; i >= 0; i--) {\n if (entries[i].toLowerCase().includes(q)) matches.push(entries[i]);\n }\n if (matches.length === 0) return null;\n if (bump) search.current = (search.current + 1) % matches.length;\n else if (search.current < 0 || search.current >= matches.length) search.current = 0;\n return matches[search.current];\n },\n [entries],\n );\n\n const resetSearch = useCallback(() => {\n search.current = -1;\n }, []);\n\n const clear = useCallback(() => {\n setEntries([]);\n cursor.current = 0;\n save(storageKey, []);\n }, [storageKey]);\n\n const browsing = cursor.current < entries.length;\n\n return useMemo(\n () => ({ entries, push, prev, next, browsing, resetCursor, reverseSearch, resetSearch, clear }),\n [entries, push, prev, next, browsing, resetCursor, reverseSearch, resetSearch, clear],\n );\n}\n"],"names":["PREFIX","DEFAULT_MAX","load","key","raw","parsed","x","save","entries","useInputHistory","cacheKey","max","storageKey","setEntries","useState","prevKey","useRef","cursor","stash","search","push","useCallback","value","v","prev","next","e","draft","resetCursor","reverseSearch","query","bump","q","matches","i","resetSearch","clear","browsing","useMemo"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { KeyboardEvent, RefObject } from 'react';
2
+ import { GuidelineTag } from './types';
3
+ export declare function tagSlug(tag: GuidelineTag): string;
4
+ export interface MentionApi {
5
+ open: boolean;
6
+ matches: GuidelineTag[];
7
+ active: number;
8
+ query: string | null;
9
+ setActive: (i: number) => void;
10
+ pick: (tag: GuidelineTag) => void;
11
+ /** Handle a key while the menu is open; returns true if it consumed the key. */
12
+ onKeyDown: (e: KeyboardEvent<HTMLTextAreaElement>) => boolean;
13
+ /** Keep the caret position in sync (call from onSelect / onChange). */
14
+ syncCaret: () => void;
15
+ }
16
+ export declare function useMention({ tags, value, setValue, taRef, prefix, onPick, }: {
17
+ tags: GuidelineTag[];
18
+ value: string;
19
+ setValue: (v: string) => void;
20
+ taRef: RefObject<HTMLTextAreaElement | null>;
21
+ prefix: string;
22
+ onPick: (tag: GuidelineTag) => void;
23
+ }): MentionApi;
24
+ //# sourceMappingURL=use-mention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mention.d.ts","sourceRoot":"","sources":["../../../src/components/rich-input/use-mention.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAEnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,wBAAgB,OAAO,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAEjD;AAWD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,IAAI,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAC;IAClC,gFAAgF;IAChF,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,CAAC,mBAAmB,CAAC,KAAK,OAAO,CAAC;IAC9D,uEAAuE;IACvE,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,KAAK,EACL,MAAM,EACN,MAAM,GACP,EAAE;IACD,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,KAAK,EAAE,SAAS,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,GAAG,EAAE,YAAY,KAAK,IAAI,CAAC;CACrC,GAAG,UAAU,CAuEb"}
@@ -0,0 +1,54 @@
1
+ import { useState as M, useRef as E, useMemo as $, useCallback as k } from "react";
2
+ const b = 8, v = /[\w.-]/;
3
+ function d(n) {
4
+ return n.slug ?? n.id;
5
+ }
6
+ function L(n, s, l) {
7
+ let e = s - 1;
8
+ for (; e >= 0 && v.test(n[e]); ) e--;
9
+ return e < 0 || n[e] !== l || e > 0 && !/\s/.test(n[e - 1]) ? null : { start: e, query: n.slice(e + 1, s) };
10
+ }
11
+ function H({
12
+ tags: n,
13
+ value: s,
14
+ setValue: l,
15
+ taRef: e,
16
+ prefix: i,
17
+ onPick: m
18
+ }) {
19
+ const [f, p] = M(0), [w, y] = M(0), g = E(null), u = L(s, f, i), r = (u == null ? void 0 : u.query) ?? null, o = $(() => {
20
+ if (r === null) return [];
21
+ const t = r.toLowerCase();
22
+ return n.filter((c) => d(c).toLowerCase().startsWith(t) || c.label.toLowerCase().includes(t)).slice(0, b);
23
+ }, [n, r]), h = r !== null && g.current !== r && o.length > 0, q = k(() => {
24
+ const t = e.current;
25
+ t && p(t.selectionStart ?? 0);
26
+ }, [e]), A = k(
27
+ (t) => {
28
+ if (!u) return;
29
+ const c = d(t), a = `${s.slice(0, u.start)}${i}${c} ${s.slice(f)}`, C = u.start + c.length + i.length + 1;
30
+ l(a), m(t), y(0), g.current = null, requestAnimationFrame(() => {
31
+ const D = e.current;
32
+ D && (D.setSelectionRange(C, C), p(C));
33
+ });
34
+ },
35
+ [u, s, f, i, l, m, e]
36
+ ), S = k(
37
+ (t) => {
38
+ if (!h) return !1;
39
+ if (t.key === "ArrowDown" || t.key === "ArrowUp") {
40
+ t.preventDefault();
41
+ const c = t.key === "ArrowDown" ? 1 : -1;
42
+ return y((a) => (a + c + o.length) % o.length), !0;
43
+ }
44
+ return t.key === "Enter" || t.key === "Tab" ? (t.preventDefault(), A(o[Math.min(w, o.length - 1)]), !0) : t.key === "Escape" ? (t.preventDefault(), g.current = r, !0) : !1;
45
+ },
46
+ [h, o, w, A, r]
47
+ );
48
+ return { open: h, matches: o, active: w, query: r, setActive: y, pick: A, onKeyDown: S, syncCaret: q };
49
+ }
50
+ export {
51
+ d as tagSlug,
52
+ H as useMention
53
+ };
54
+ //# sourceMappingURL=use-mention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-mention.js","sources":["../../../src/components/rich-input/use-mention.ts"],"sourcesContent":["import { useCallback, useMemo, useRef, useState, type KeyboardEvent, type RefObject } from 'react';\n\nimport type { GuidelineTag } from './types';\n\nconst MAX_MATCHES = 8;\nconst TOKEN_CHAR = /[\\w.-]/;\n\nexport function tagSlug(tag: GuidelineTag): string {\n return tag.slug ?? tag.id;\n}\n\n/** Detect a `<prefix><token>` under the caret, at a word boundary. */\nfunction activeMention(text: string, caret: number, prefix: string): { start: number; query: string } | null {\n let i = caret - 1;\n while (i >= 0 && TOKEN_CHAR.test(text[i])) i--;\n if (i < 0 || text[i] !== prefix) return null;\n if (i > 0 && !/\\s/.test(text[i - 1])) return null; // must follow whitespace / line start\n return { start: i, query: text.slice(i + 1, caret) };\n}\n\nexport interface MentionApi {\n open: boolean;\n matches: GuidelineTag[];\n active: number;\n query: string | null;\n setActive: (i: number) => void;\n pick: (tag: GuidelineTag) => void;\n /** Handle a key while the menu is open; returns true if it consumed the key. */\n onKeyDown: (e: KeyboardEvent<HTMLTextAreaElement>) => boolean;\n /** Keep the caret position in sync (call from onSelect / onChange). */\n syncCaret: () => void;\n}\n\nexport function useMention({\n tags,\n value,\n setValue,\n taRef,\n prefix,\n onPick,\n}: {\n tags: GuidelineTag[];\n value: string;\n setValue: (v: string) => void;\n taRef: RefObject<HTMLTextAreaElement | null>;\n prefix: string;\n onPick: (tag: GuidelineTag) => void;\n}): MentionApi {\n const [caret, setCaret] = useState(0);\n const [active, setActive] = useState(0);\n const dismissed = useRef<string | null>(null);\n\n const mention = activeMention(value, caret, prefix);\n const query = mention?.query ?? null;\n\n const matches = useMemo(() => {\n if (query === null) return [];\n const q = query.toLowerCase();\n return tags\n .filter((t) => {\n const slug = tagSlug(t).toLowerCase();\n return slug.startsWith(q) || t.label.toLowerCase().includes(q);\n })\n .slice(0, MAX_MATCHES);\n }, [tags, query]);\n\n const open = query !== null && dismissed.current !== query && matches.length > 0;\n\n const syncCaret = useCallback(() => {\n const el = taRef.current;\n if (el) setCaret(el.selectionStart ?? 0);\n }, [taRef]);\n\n const pick = useCallback(\n (tag: GuidelineTag) => {\n if (!mention) return;\n const slug = tagSlug(tag);\n const next = `${value.slice(0, mention.start)}${prefix}${slug} ${value.slice(caret)}`;\n const pos = mention.start + slug.length + prefix.length + 1;\n setValue(next);\n onPick(tag);\n setActive(0);\n dismissed.current = null;\n requestAnimationFrame(() => {\n const el = taRef.current;\n if (!el) return;\n el.setSelectionRange(pos, pos);\n setCaret(pos);\n });\n },\n [mention, value, caret, prefix, setValue, onPick, taRef],\n );\n\n const onKeyDown = useCallback(\n (e: KeyboardEvent<HTMLTextAreaElement>): boolean => {\n if (!open) return false;\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n const d = e.key === 'ArrowDown' ? 1 : -1;\n setActive((i) => (i + d + matches.length) % matches.length);\n return true;\n }\n if (e.key === 'Enter' || e.key === 'Tab') {\n e.preventDefault();\n pick(matches[Math.min(active, matches.length - 1)]);\n return true;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n dismissed.current = query;\n return true;\n }\n return false;\n },\n [open, matches, active, pick, query],\n );\n\n return { open, matches, active, query, setActive, pick, onKeyDown, syncCaret };\n}\n"],"names":["MAX_MATCHES","TOKEN_CHAR","tagSlug","tag","activeMention","text","caret","prefix","i","useMention","tags","value","setValue","taRef","onPick","setCaret","useState","active","setActive","dismissed","useRef","mention","query","matches","useMemo","q","t","open","syncCaret","useCallback","el","pick","slug","next","pos","onKeyDown","e","d"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { SearchInput } from './search-input';
2
+ export type { SearchInputProps } from './search-input';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/search-input/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ export interface SearchInputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {
3
+ value: string;
4
+ onValueChange: (value: string) => void;
5
+ /** Focus on `⌘K` / `Ctrl-K` (and `/`), and show the hint key. */
6
+ shortcut?: boolean;
7
+ className?: string;
8
+ }
9
+ /**
10
+ * A search field with the leading icon, a clear button, and Escape-to-clear —
11
+ * the input every list in the lab puts above itself. Pairs with `FuzzyList`.
12
+ */
13
+ export declare function SearchInput({ value, onValueChange, shortcut, className, placeholder, ...props }: SearchInputProps): React.JSX.Element;
14
+ //# sourceMappingURL=search-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-input.d.ts","sourceRoot":"","sources":["../../../src/components/search-input/search-input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,MAAM,WAAW,gBACf,SAAQ,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;IACxF,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,aAAa,EACb,QAAgB,EAChB,SAAS,EACT,WAAuB,EACvB,GAAG,KAAK,EACT,EAAE,gBAAgB,qBA6DlB"}
@@ -0,0 +1,63 @@
1
+ import { jsxs as g, jsx as t } from "react/jsx-runtime";
2
+ import * as l from "react";
3
+ import { Search as y, X as h } from "lucide-react";
4
+ import { cn as u } from "../../lib/utils.js";
5
+ function N({
6
+ value: n,
7
+ onValueChange: i,
8
+ shortcut: o = !1,
9
+ className: f,
10
+ placeholder: m = "Search…",
11
+ ...p
12
+ }) {
13
+ const s = l.useRef(null);
14
+ return l.useEffect(() => {
15
+ if (!o) return;
16
+ const e = (r) => {
17
+ var a, d, c;
18
+ const b = /^(INPUT|TEXTAREA)$/.test(((a = r.target) == null ? void 0 : a.tagName) ?? "");
19
+ (r.key === "k" && (r.metaKey || r.ctrlKey) || r.key === "/" && !b) && (r.preventDefault(), (d = s.current) == null || d.focus(), (c = s.current) == null || c.select());
20
+ };
21
+ return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
22
+ }, [o]), /* @__PURE__ */ g("div", { className: u("relative flex items-center", f), children: [
23
+ /* @__PURE__ */ t(y, { className: "pointer-events-none absolute left-3 size-4 text-muted-foreground" }),
24
+ /* @__PURE__ */ t(
25
+ "input",
26
+ {
27
+ ref: s,
28
+ type: "search",
29
+ value: n,
30
+ placeholder: m,
31
+ onChange: (e) => i(e.target.value),
32
+ onKeyDown: (e) => {
33
+ e.key === "Escape" && n && (e.preventDefault(), i(""));
34
+ },
35
+ className: u(
36
+ "h-9 w-full rounded-lg border border-border bg-transparent pl-9 text-sm outline-none transition-colors",
37
+ "placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40",
38
+ "[&::-webkit-search-cancel-button]:hidden",
39
+ // we ship our own clear button
40
+ n ? "pr-9" : o ? "pr-12" : "pr-3"
41
+ ),
42
+ ...p
43
+ }
44
+ ),
45
+ n ? /* @__PURE__ */ t(
46
+ "button",
47
+ {
48
+ type: "button",
49
+ onClick: () => {
50
+ var e;
51
+ i(""), (e = s.current) == null || e.focus();
52
+ },
53
+ "aria-label": "Clear search",
54
+ className: "absolute right-2 rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
55
+ children: /* @__PURE__ */ t(h, { className: "size-3.5" })
56
+ }
57
+ ) : o && /* @__PURE__ */ t("kbd", { className: "pointer-events-none absolute right-2.5 rounded border border-border px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground", children: "⌘K" })
58
+ ] });
59
+ }
60
+ export {
61
+ N as SearchInput
62
+ };
63
+ //# sourceMappingURL=search-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-input.js","sources":["../../../src/components/search-input/search-input.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Search, X } from 'lucide-react';\n\nimport { cn } from '../../lib/utils';\n\nexport interface SearchInputProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'> {\n value: string;\n onValueChange: (value: string) => void;\n /** Focus on `⌘K` / `Ctrl-K` (and `/`), and show the hint key. */\n shortcut?: boolean;\n className?: string;\n}\n\n/**\n * A search field with the leading icon, a clear button, and Escape-to-clear —\n * the input every list in the lab puts above itself. Pairs with `FuzzyList`.\n */\nexport function SearchInput({\n value,\n onValueChange,\n shortcut = false,\n className,\n placeholder = 'Search…',\n ...props\n}: SearchInputProps) {\n const ref = React.useRef<HTMLInputElement>(null);\n\n React.useEffect(() => {\n if (!shortcut) return;\n const onKey = (e: KeyboardEvent) => {\n const typing = /^(INPUT|TEXTAREA)$/.test((e.target as HTMLElement)?.tagName ?? '');\n const hotkey = (e.key === 'k' && (e.metaKey || e.ctrlKey)) || (e.key === '/' && !typing);\n if (!hotkey) return;\n e.preventDefault();\n ref.current?.focus();\n ref.current?.select();\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [shortcut]);\n\n return (\n <div className={cn('relative flex items-center', className)}>\n <Search className=\"pointer-events-none absolute left-3 size-4 text-muted-foreground\" />\n <input\n ref={ref}\n type=\"search\"\n value={value}\n placeholder={placeholder}\n onChange={(e) => onValueChange(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Escape' && value) {\n e.preventDefault(); // don't let it bubble up and close the dialog too\n onValueChange('');\n }\n }}\n className={cn(\n 'h-9 w-full rounded-lg border border-border bg-transparent pl-9 text-sm outline-none transition-colors',\n 'placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40',\n '[&::-webkit-search-cancel-button]:hidden', // we ship our own clear button\n value ? 'pr-9' : shortcut ? 'pr-12' : 'pr-3',\n )}\n {...props}\n />\n {value ? (\n <button\n type=\"button\"\n onClick={() => {\n onValueChange('');\n ref.current?.focus();\n }}\n aria-label=\"Clear search\"\n className=\"absolute right-2 rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground\"\n >\n <X className=\"size-3.5\" />\n </button>\n ) : (\n shortcut && (\n <kbd className=\"pointer-events-none absolute right-2.5 rounded border border-border px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground\">\n ⌘K\n </kbd>\n )\n )}\n </div>\n );\n}\n"],"names":["SearchInput","value","onValueChange","shortcut","className","placeholder","props","ref","React","onKey","e","typing","_a","_b","_c","cn","jsx","Search","X"],"mappings":";;;;AAkBO,SAASA,EAAY;AAAA,EAC1B,OAAAC;AAAA,EACA,eAAAC;AAAA,EACA,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,GAAGC;AACL,GAAqB;AACnB,QAAMC,IAAMC,EAAM,OAAyB,IAAI;AAE/C,SAAAA,EAAM,UAAU,MAAM;AACpB,QAAI,CAACL,EAAU;AACf,UAAMM,IAAQ,CAACC,MAAqB;;AAClC,YAAMC,IAAS,qBAAqB,OAAMC,IAAAF,EAAE,WAAF,gBAAAE,EAA0B,YAAW,EAAE;AAEjF,OADgBF,EAAE,QAAQ,QAAQA,EAAE,WAAWA,EAAE,YAAcA,EAAE,QAAQ,OAAO,CAACC,OAEjFD,EAAE,eAAA,IACFG,IAAAN,EAAI,YAAJ,QAAAM,EAAa,UACbC,IAAAP,EAAI,YAAJ,QAAAO,EAAa;AAAA,IACf;AACA,kBAAO,iBAAiB,WAAWL,CAAK,GACjC,MAAM,OAAO,oBAAoB,WAAWA,CAAK;AAAA,EAC1D,GAAG,CAACN,CAAQ,CAAC,qBAGV,OAAA,EAAI,WAAWY,EAAG,8BAA8BX,CAAS,GACxD,UAAA;AAAA,IAAA,gBAAAY,EAACC,GAAA,EAAO,WAAU,mEAAA,CAAmE;AAAA,IACrF,gBAAAD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAT;AAAA,QACA,MAAK;AAAA,QACL,OAAAN;AAAA,QACA,aAAAI;AAAA,QACA,UAAU,CAAC,MAAMH,EAAc,EAAE,OAAO,KAAK;AAAA,QAC7C,WAAW,CAAC,MAAM;AAChB,UAAI,EAAE,QAAQ,YAAYD,MACxB,EAAE,eAAA,GACFC,EAAc,EAAE;AAAA,QAEpB;AAAA,QACA,WAAWa;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA;AAAA,UACAd,IAAQ,SAASE,IAAW,UAAU;AAAA,QAAA;AAAA,QAEvC,GAAGG;AAAA,MAAA;AAAA,IAAA;AAAA,IAELL,IACC,gBAAAe;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,MAAM;;AACb,UAAAd,EAAc,EAAE,IAChBU,IAAAL,EAAI,YAAJ,QAAAK,EAAa;AAAA,QACf;AAAA,QACA,cAAW;AAAA,QACX,WAAU;AAAA,QAEV,UAAA,gBAAAI,EAACE,GAAA,EAAE,WAAU,WAAA,CAAW;AAAA,MAAA;AAAA,IAAA,IAG1Bf,KACE,gBAAAa,EAAC,OAAA,EAAI,WAAU,mIAAkI,UAAA,KAAA,CAEjJ;AAAA,EAAA,GAGN;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ export { Skeleton, SkeletonGrid, SkeletonText } from './skeleton';
2
+ export type { SkeletonGridProps, SkeletonTextProps } from './skeleton';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/skeleton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ /** A pulsing placeholder block. Give it a size with `className`. */
3
+ export declare function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
4
+ export interface SkeletonTextProps {
5
+ /** Number of lines. The last one is short, like real ragged text. */
6
+ lines?: number;
7
+ className?: string;
8
+ }
9
+ /** A paragraph of skeleton lines — the shape text actually loads into. */
10
+ export declare function SkeletonText({ lines, className }: SkeletonTextProps): React.JSX.Element;
11
+ export interface SkeletonGridProps {
12
+ count?: number;
13
+ /** Tailwind aspect class for each tile. */
14
+ aspect?: string;
15
+ className?: string;
16
+ }
17
+ /** A grid of tiles — the gallery/card placeholder. */
18
+ export declare function SkeletonGrid({ count, aspect, className, }: SkeletonGridProps): React.JSX.Element;
19
+ //# sourceMappingURL=skeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/skeleton/skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,oEAAoE;AACpE,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,qBAQrF;AAED,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,EAAE,KAAS,EAAE,SAAS,EAAE,EAAE,iBAAiB,qBAQvE;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2CAA2C;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,EAC3B,KAAS,EACT,MAAwB,EACxB,SAAS,GACV,EAAE,iBAAiB,qBAQnB"}
@@ -0,0 +1,29 @@
1
+ import { jsx as a } from "react/jsx-runtime";
2
+ import "react";
3
+ import { cn as n } from "../../lib/utils.js";
4
+ function o({ className: e, ...r }) {
5
+ return /* @__PURE__ */ a(
6
+ "div",
7
+ {
8
+ "aria-hidden": !0,
9
+ className: n("animate-pulse rounded-md bg-muted", e),
10
+ ...r
11
+ }
12
+ );
13
+ }
14
+ function c({ lines: e = 3, className: r }) {
15
+ return /* @__PURE__ */ a("div", { className: n("space-y-2", r), children: Array.from({ length: e }, (l, t) => /* @__PURE__ */ a(o, { className: n("h-3.5", t === e - 1 ? "w-2/5" : "w-full") }, t)) });
16
+ }
17
+ function u({
18
+ count: e = 6,
19
+ aspect: r = "aspect-square",
20
+ className: l
21
+ }) {
22
+ return /* @__PURE__ */ a("div", { className: n("grid grid-cols-2 gap-3 sm:grid-cols-3", l), children: Array.from({ length: e }, (t, d) => /* @__PURE__ */ a(o, { className: n("w-full rounded-xl", r) }, d)) });
23
+ }
24
+ export {
25
+ o as Skeleton,
26
+ u as SkeletonGrid,
27
+ c as SkeletonText
28
+ };
29
+ //# sourceMappingURL=skeleton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skeleton.js","sources":["../../../src/components/skeleton/skeleton.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { cn } from '../../lib/utils';\n\n/** A pulsing placeholder block. Give it a size with `className`. */\nexport function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n aria-hidden\n className={cn('animate-pulse rounded-md bg-muted', className)}\n {...props}\n />\n );\n}\n\nexport interface SkeletonTextProps {\n /** Number of lines. The last one is short, like real ragged text. */\n lines?: number;\n className?: string;\n}\n\n/** A paragraph of skeleton lines — the shape text actually loads into. */\nexport function SkeletonText({ lines = 3, className }: SkeletonTextProps) {\n return (\n <div className={cn('space-y-2', className)}>\n {Array.from({ length: lines }, (_, i) => (\n <Skeleton key={i} className={cn('h-3.5', i === lines - 1 ? 'w-2/5' : 'w-full')} />\n ))}\n </div>\n );\n}\n\nexport interface SkeletonGridProps {\n count?: number;\n /** Tailwind aspect class for each tile. */\n aspect?: string;\n className?: string;\n}\n\n/** A grid of tiles — the gallery/card placeholder. */\nexport function SkeletonGrid({\n count = 6,\n aspect = 'aspect-square',\n className,\n}: SkeletonGridProps) {\n return (\n <div className={cn('grid grid-cols-2 gap-3 sm:grid-cols-3', className)}>\n {Array.from({ length: count }, (_, i) => (\n <Skeleton key={i} className={cn('w-full rounded-xl', aspect)} />\n ))}\n </div>\n );\n}\n"],"names":["Skeleton","className","props","jsx","cn","SkeletonText","lines","_","i","SkeletonGrid","count","aspect"],"mappings":";;;AAKO,SAASA,EAAS,EAAE,WAAAC,GAAW,GAAGC,KAA+C;AACtF,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAW;AAAA,MACX,WAAWC,EAAG,qCAAqCH,CAAS;AAAA,MAC3D,GAAGC;AAAA,IAAA;AAAA,EAAA;AAGV;AASO,SAASG,EAAa,EAAE,OAAAC,IAAQ,GAAG,WAAAL,KAAgC;AACxE,SACE,gBAAAE,EAAC,OAAA,EAAI,WAAWC,EAAG,aAAaH,CAAS,GACtC,UAAA,MAAM,KAAK,EAAE,QAAQK,EAAA,GAAS,CAACC,GAAGC,MACjC,gBAAAL,EAACH,GAAA,EAAiB,WAAWI,EAAG,SAASI,MAAMF,IAAQ,IAAI,UAAU,QAAQ,EAAA,GAA9DE,CAAiE,CACjF,EAAA,CACH;AAEJ;AAUO,SAASC,EAAa;AAAA,EAC3B,OAAAC,IAAQ;AAAA,EACR,QAAAC,IAAS;AAAA,EACT,WAAAV;AACF,GAAsB;AACpB,SACE,gBAAAE,EAAC,OAAA,EAAI,WAAWC,EAAG,yCAAyCH,CAAS,GAClE,UAAA,MAAM,KAAK,EAAE,QAAQS,KAAS,CAACH,GAAGC,MACjC,gBAAAL,EAACH,GAAA,EAAiB,WAAWI,EAAG,qBAAqBO,CAAM,EAAA,GAA5CH,CAA+C,CAC/D,EAAA,CACH;AAEJ;"}
@@ -0,0 +1,3 @@
1
+ export { Spinner } from './spinner';
2
+ export type { SpinnerProps } from './spinner';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/spinner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}