@vamos-ui/react 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (665) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -2
  3. package/dist/blocks/block-heading.d.ts +29 -0
  4. package/dist/blocks/block-heading.js +39 -0
  5. package/dist/blocks/block-image.d.ts +52 -0
  6. package/dist/blocks/block-image.js +48 -0
  7. package/dist/blocks/block-link.d.ts +30 -0
  8. package/dist/blocks/block-link.js +36 -0
  9. package/dist/blocks/create-blocks.d.ts +54 -0
  10. package/dist/blocks/create-blocks.js +52 -0
  11. package/dist/blocks/index.d.ts +55 -0
  12. package/dist/blocks/index.js +59 -0
  13. package/dist/blocks/json-ld.d.ts +18 -0
  14. package/dist/blocks/json-ld.js +44 -0
  15. package/dist/blocks/labels.d.ts +20 -0
  16. package/dist/blocks/labels.js +43 -0
  17. package/dist/blocks/rich-text.d.ts +36 -0
  18. package/dist/blocks/rich-text.js +106 -0
  19. package/dist/blocks/schema/define-block.d.ts +151 -0
  20. package/dist/blocks/schema/define-block.js +120 -0
  21. package/dist/blocks/schema/emphasis.d.ts +17 -0
  22. package/dist/blocks/schema/emphasis.js +69 -0
  23. package/dist/blocks/schema/fields.d.ts +497 -0
  24. package/dist/blocks/schema/fields.js +240 -0
  25. package/dist/blocks/schema/icons.d.ts +2 -0
  26. package/dist/blocks/schema/icons.js +26 -0
  27. package/dist/blocks/schema/index.d.ts +18 -0
  28. package/dist/blocks/schema/index.js +21 -0
  29. package/dist/blocks/schema/lint-types.d.ts +16 -0
  30. package/dist/blocks/schema/lint-types.js +2 -0
  31. package/dist/blocks/schema/lint.d.ts +32 -0
  32. package/dist/blocks/schema/lint.js +164 -0
  33. package/dist/blocks/schema/localize.d.ts +20 -0
  34. package/dist/blocks/schema/localize.js +29 -0
  35. package/dist/blocks/schema/localized.d.ts +25 -0
  36. package/dist/blocks/schema/localized.js +53 -0
  37. package/dist/blocks/schema/migrate.d.ts +24 -0
  38. package/dist/blocks/schema/migrate.js +75 -0
  39. package/dist/blocks/schema/nodes.d.ts +196 -0
  40. package/dist/blocks/schema/nodes.js +78 -0
  41. package/dist/blocks/schema/rich-doc-schema.d.ts +32 -0
  42. package/dist/blocks/schema/rich-doc-schema.js +66 -0
  43. package/dist/blocks/schema/rich-doc.d.ts +90 -0
  44. package/dist/blocks/schema/rich-doc.js +62 -0
  45. package/dist/blocks/schema/safety.d.ts +20 -0
  46. package/dist/blocks/schema/safety.js +49 -0
  47. package/dist/blocks/schema/types.d.ts +172 -0
  48. package/dist/blocks/schema/types.js +3 -0
  49. package/dist/blocks/schema/validate.d.ts +17 -0
  50. package/dist/blocks/schema/validate.js +32 -0
  51. package/dist/blocks/schema/walk.d.ts +22 -0
  52. package/dist/blocks/schema/walk.js +60 -0
  53. package/dist/blocks/section-header.d.ts +38 -0
  54. package/dist/blocks/section-header.js +22 -0
  55. package/dist/blocks/section.d.ts +59 -0
  56. package/dist/blocks/section.js +66 -0
  57. package/dist/blocks/site/_kit-1.d.ts +100 -0
  58. package/dist/blocks/site/_kit-1.js +135 -0
  59. package/dist/blocks/site/_site-icon-1.d.ts +6 -0
  60. package/dist/blocks/site/_site-icon-1.js +15 -0
  61. package/dist/blocks/site/announcement-bar.d.ts +42 -0
  62. package/dist/blocks/site/announcement-bar.js +38 -0
  63. package/dist/blocks/site/announcement-dismiss.d.ts +18 -0
  64. package/dist/blocks/site/announcement-dismiss.js +28 -0
  65. package/dist/blocks/site/article-layout.d.ts +65 -0
  66. package/dist/blocks/site/article-layout.js +88 -0
  67. package/dist/blocks/site/blog-list.d.ts +79 -0
  68. package/dist/blocks/site/blog-list.js +78 -0
  69. package/dist/blocks/site/comparison-table.d.ts +54 -0
  70. package/dist/blocks/site/comparison-table.js +38 -0
  71. package/dist/blocks/site/consent-banner.d.ts +52 -0
  72. package/dist/blocks/site/consent-banner.js +33 -0
  73. package/dist/blocks/site/contact-dock.d.ts +52 -0
  74. package/dist/blocks/site/contact-dock.js +55 -0
  75. package/dist/blocks/site/contact-form.d.ts +60 -0
  76. package/dist/blocks/site/contact-form.js +45 -0
  77. package/dist/blocks/site/cta-booking.d.ts +43 -0
  78. package/dist/blocks/site/cta-booking.js +69 -0
  79. package/dist/blocks/site/cta.d.ts +74 -0
  80. package/dist/blocks/site/cta.js +112 -0
  81. package/dist/blocks/site/embed-facade.d.ts +20 -0
  82. package/dist/blocks/site/embed-facade.js +21 -0
  83. package/dist/blocks/site/faq.d.ts +48 -0
  84. package/dist/blocks/site/faq.js +51 -0
  85. package/dist/blocks/site/feature-grid.d.ts +46 -0
  86. package/dist/blocks/site/feature-grid.js +49 -0
  87. package/dist/blocks/site/feature-tabs.d.ts +22 -0
  88. package/dist/blocks/site/feature-tabs.js +11 -0
  89. package/dist/blocks/site/footer.d.ts +68 -0
  90. package/dist/blocks/site/footer.js +61 -0
  91. package/dist/blocks/site/gallery-section.d.ts +42 -0
  92. package/dist/blocks/site/gallery-section.js +47 -0
  93. package/dist/blocks/site/hero-video.d.ts +15 -0
  94. package/dist/blocks/site/hero-video.js +31 -0
  95. package/dist/blocks/site/hero.d.ts +64 -0
  96. package/dist/blocks/site/hero.js +67 -0
  97. package/dist/blocks/site/logo-strip.d.ts +42 -0
  98. package/dist/blocks/site/logo-strip.js +26 -0
  99. package/dist/blocks/site/map-hours.d.ts +83 -0
  100. package/dist/blocks/site/map-hours.js +125 -0
  101. package/dist/blocks/site/media-text.d.ts +45 -0
  102. package/dist/blocks/site/media-text.js +55 -0
  103. package/dist/blocks/site/menu-list.d.ts +74 -0
  104. package/dist/blocks/site/menu-list.js +84 -0
  105. package/dist/blocks/site/navbar-submenu.d.ts +18 -0
  106. package/dist/blocks/site/navbar-submenu.js +51 -0
  107. package/dist/blocks/site/navbar.d.ts +67 -0
  108. package/dist/blocks/site/navbar.js +64 -0
  109. package/dist/blocks/site/not-found.d.ts +40 -0
  110. package/dist/blocks/site/not-found.js +38 -0
  111. package/dist/blocks/site/page-intro.d.ts +46 -0
  112. package/dist/blocks/site/page-intro.js +44 -0
  113. package/dist/blocks/site/pricing-table.d.ts +67 -0
  114. package/dist/blocks/site/pricing-table.js +82 -0
  115. package/dist/blocks/site/process.d.ts +36 -0
  116. package/dist/blocks/site/process.js +41 -0
  117. package/dist/blocks/site/registry-1.d.ts +720 -0
  118. package/dist/blocks/site/registry-1.js +783 -0
  119. package/dist/blocks/site/registry-2.d.ts +914 -0
  120. package/dist/blocks/site/registry-2.js +563 -0
  121. package/dist/blocks/site/rich-text-section.d.ts +34 -0
  122. package/dist/blocks/site/rich-text-section.js +32 -0
  123. package/dist/blocks/site/shared/brand-icons.d.ts +21 -0
  124. package/dist/blocks/site/shared/brand-icons.js +56 -0
  125. package/dist/blocks/site/shared/consent-gate.d.ts +41 -0
  126. package/dist/blocks/site/shared/consent-gate.js +43 -0
  127. package/dist/blocks/site/shared/consent-island.d.ts +38 -0
  128. package/dist/blocks/site/shared/consent-island.js +63 -0
  129. package/dist/blocks/site/shared/consent.d.ts +49 -0
  130. package/dist/blocks/site/shared/consent.js +130 -0
  131. package/dist/blocks/site/shared/contact-form-island.d.ts +41 -0
  132. package/dist/blocks/site/shared/contact-form-island.js +100 -0
  133. package/dist/blocks/site/shared/copy-link.d.ts +10 -0
  134. package/dist/blocks/site/shared/copy-link.js +25 -0
  135. package/dist/blocks/site/shared/dock-avoid.d.ts +15 -0
  136. package/dist/blocks/site/shared/dock-avoid.js +107 -0
  137. package/dist/blocks/site/shared/dock-hours.d.ts +13 -0
  138. package/dist/blocks/site/shared/dock-hours.js +25 -0
  139. package/dist/blocks/site/shared/gallery-lightbox.d.ts +12 -0
  140. package/dist/blocks/site/shared/gallery-lightbox.js +10 -0
  141. package/dist/blocks/site/shared/island-keys.d.ts +10 -0
  142. package/dist/blocks/site/shared/island-keys.js +44 -0
  143. package/dist/blocks/site/shared/kit-2.d.ts +55 -0
  144. package/dist/blocks/site/shared/kit-2.js +84 -0
  145. package/dist/blocks/site/shared/labels-2.d.ts +209 -0
  146. package/dist/blocks/site/shared/labels-2.js +427 -0
  147. package/dist/blocks/site/shared/open-now.d.ts +22 -0
  148. package/dist/blocks/site/shared/open-now.js +27 -0
  149. package/dist/blocks/site/shared/opening-hours.d.ts +117 -0
  150. package/dist/blocks/site/shared/opening-hours.js +245 -0
  151. package/dist/blocks/site/shared/site-accent.d.ts +48 -0
  152. package/dist/blocks/site/shared/site-accent.js +249 -0
  153. package/dist/blocks/site/shared/site-form.d.ts +79 -0
  154. package/dist/blocks/site/shared/site-form.js +111 -0
  155. package/dist/blocks/site/shared/site-routing.d.ts +54 -0
  156. package/dist/blocks/site/shared/site-routing.js +86 -0
  157. package/dist/blocks/site/shared/testimonials-carousel.d.ts +17 -0
  158. package/dist/blocks/site/shared/testimonials-carousel.js +64 -0
  159. package/dist/blocks/site/site-shell.d.ts +97 -0
  160. package/dist/blocks/site/site-shell.js +227 -0
  161. package/dist/blocks/site/stats-band.d.ts +40 -0
  162. package/dist/blocks/site/stats-band.js +41 -0
  163. package/dist/blocks/site/team.d.ts +44 -0
  164. package/dist/blocks/site/team.js +48 -0
  165. package/dist/blocks/site/testimonials.d.ts +68 -0
  166. package/dist/blocks/site/testimonials.js +65 -0
  167. package/dist/blocks/types.d.ts +63 -0
  168. package/dist/blocks/types.js +2 -0
  169. package/dist/business/approval-flow.d.ts +152 -0
  170. package/dist/business/approval-flow.js +221 -0
  171. package/dist/business/export-core.d.ts +55 -0
  172. package/dist/business/export-core.js +101 -0
  173. package/dist/business/export.d.ts +148 -0
  174. package/dist/business/export.js +264 -0
  175. package/dist/business/import-core.d.ts +104 -0
  176. package/dist/business/import-core.js +281 -0
  177. package/dist/business/import-wizard.d.ts +186 -0
  178. package/dist/business/import-wizard.js +401 -0
  179. package/dist/business/index.d.ts +11 -0
  180. package/dist/business/index.js +20 -0
  181. package/dist/business/line-items-core.d.ts +129 -0
  182. package/dist/business/line-items-core.js +183 -0
  183. package/dist/business/line-items.d.ts +119 -0
  184. package/dist/business/line-items.js +299 -0
  185. package/dist/business/multi-step-form.d.ts +131 -0
  186. package/dist/business/multi-step-form.js +337 -0
  187. package/dist/business/permission-core.d.ts +59 -0
  188. package/dist/business/permission-core.js +99 -0
  189. package/dist/business/permission-matrix.d.ts +158 -0
  190. package/dist/business/permission-matrix.js +341 -0
  191. package/dist/business/setup-checklist.d.ts +80 -0
  192. package/dist/business/setup-checklist.js +92 -0
  193. package/dist/charts/area-chart.d.ts +35 -0
  194. package/dist/charts/area-chart.js +33 -0
  195. package/dist/charts/bar-chart.d.ts +27 -0
  196. package/dist/charts/bar-chart.js +42 -0
  197. package/dist/charts/bar-list.d.ts +47 -0
  198. package/dist/charts/bar-list.js +60 -0
  199. package/dist/charts/chart-shell.d.ts +173 -0
  200. package/dist/charts/chart-shell.js +205 -0
  201. package/dist/charts/chart.d.ts +73 -0
  202. package/dist/charts/chart.js +106 -0
  203. package/dist/charts/combo-chart.d.ts +29 -0
  204. package/dist/charts/combo-chart.js +47 -0
  205. package/dist/charts/donut-chart.d.ts +33 -0
  206. package/dist/charts/donut-chart.js +113 -0
  207. package/dist/charts/funnel.d.ts +51 -0
  208. package/dist/charts/funnel.js +69 -0
  209. package/dist/charts/gauge.d.ts +62 -0
  210. package/dist/charts/gauge.js +104 -0
  211. package/dist/charts/heatmap.d.ts +81 -0
  212. package/dist/charts/heatmap.js +338 -0
  213. package/dist/charts/index.d.ts +12 -0
  214. package/dist/charts/index.js +14 -0
  215. package/dist/charts/line-chart.d.ts +21 -0
  216. package/dist/charts/line-chart.js +36 -0
  217. package/dist/charts/test-utils.d.ts +2 -0
  218. package/dist/charts/test-utils.js +38 -0
  219. package/dist/charts/utils.d.ts +130 -0
  220. package/dist/charts/utils.js +262 -0
  221. package/dist/components/accordion.d.ts +47 -0
  222. package/dist/components/accordion.js +70 -0
  223. package/dist/components/activity-timeline.d.ts +149 -0
  224. package/dist/components/activity-timeline.js +122 -0
  225. package/dist/components/address-field.d.ts +116 -0
  226. package/dist/components/address-field.js +219 -0
  227. package/dist/components/alert-dialog.d.ts +99 -0
  228. package/dist/components/alert-dialog.js +192 -0
  229. package/dist/components/alert.d.ts +42 -0
  230. package/dist/components/alert.js +82 -0
  231. package/dist/components/app-shell.d.ts +159 -0
  232. package/dist/components/app-shell.js +289 -0
  233. package/dist/components/attachment-list.d.ts +96 -0
  234. package/dist/components/attachment-list.js +196 -0
  235. package/dist/components/audit-log.d.ts +150 -0
  236. package/dist/components/audit-log.js +205 -0
  237. package/dist/components/avatar.d.ts +87 -0
  238. package/dist/components/avatar.js +126 -0
  239. package/dist/components/badge.d.ts +41 -0
  240. package/dist/components/badge.js +68 -0
  241. package/dist/components/breadcrumb.d.ts +78 -0
  242. package/dist/components/breadcrumb.js +106 -0
  243. package/dist/components/button-group.d.ts +52 -0
  244. package/dist/components/button-group.js +77 -0
  245. package/dist/components/button.d.ts +58 -0
  246. package/dist/components/button.js +107 -0
  247. package/dist/components/calendar.d.ts +240 -0
  248. package/dist/components/calendar.js +483 -0
  249. package/dist/components/card.d.ts +66 -0
  250. package/dist/components/card.js +76 -0
  251. package/dist/components/carousel.d.ts +170 -0
  252. package/dist/components/carousel.js +348 -0
  253. package/dist/components/checkbox.d.ts +78 -0
  254. package/dist/components/checkbox.js +138 -0
  255. package/dist/components/color-picker.d.ts +112 -0
  256. package/dist/components/color-picker.js +235 -0
  257. package/dist/components/combobox.d.ts +136 -0
  258. package/dist/components/combobox.js +294 -0
  259. package/dist/components/command.d.ts +275 -0
  260. package/dist/components/command.js +493 -0
  261. package/dist/components/comment-thread.d.ts +252 -0
  262. package/dist/components/comment-thread.js +449 -0
  263. package/dist/components/context-menu.d.ts +77 -0
  264. package/dist/components/context-menu.js +82 -0
  265. package/dist/components/currency-input.d.ts +43 -0
  266. package/dist/components/currency-input.js +85 -0
  267. package/dist/components/date-picker.d.ts +141 -0
  268. package/dist/components/date-picker.js +241 -0
  269. package/dist/components/date-range-picker.d.ts +91 -0
  270. package/dist/components/date-range-picker.js +251 -0
  271. package/dist/components/description-list.d.ts +92 -0
  272. package/dist/components/description-list.js +42 -0
  273. package/dist/components/dialog.d.ts +139 -0
  274. package/dist/components/dialog.js +185 -0
  275. package/dist/components/dropdown-menu.d.ts +100 -0
  276. package/dist/components/dropdown-menu.js +102 -0
  277. package/dist/components/editor-layout.d.ts +166 -0
  278. package/dist/components/editor-layout.js +237 -0
  279. package/dist/components/empty-state.d.ts +49 -0
  280. package/dist/components/empty-state.js +68 -0
  281. package/dist/components/entity-card.d.ts +83 -0
  282. package/dist/components/entity-card.js +92 -0
  283. package/dist/components/file-upload.d.ts +256 -0
  284. package/dist/components/file-upload.js +490 -0
  285. package/dist/components/formatted-input.d.ts +177 -0
  286. package/dist/components/formatted-input.js +399 -0
  287. package/dist/components/hierarchy-chart.d.ts +190 -0
  288. package/dist/components/hierarchy-chart.js +890 -0
  289. package/dist/components/hover-card.d.ts +21 -0
  290. package/dist/components/hover-card.js +32 -0
  291. package/dist/components/iban-input.d.ts +38 -0
  292. package/dist/components/iban-input.js +112 -0
  293. package/dist/components/id-input.d.ts +65 -0
  294. package/dist/components/id-input.js +130 -0
  295. package/dist/components/image.d.ts +130 -0
  296. package/dist/components/image.js +168 -0
  297. package/dist/components/input-otp.d.ts +62 -0
  298. package/dist/components/input-otp.js +73 -0
  299. package/dist/components/input.d.ts +141 -0
  300. package/dist/components/input.js +187 -0
  301. package/dist/components/item.d.ts +96 -0
  302. package/dist/components/item.js +113 -0
  303. package/dist/components/kbd.d.ts +64 -0
  304. package/dist/components/kbd.js +119 -0
  305. package/dist/components/list-layout.d.ts +144 -0
  306. package/dist/components/list-layout.js +210 -0
  307. package/dist/components/native-select.d.ts +33 -0
  308. package/dist/components/native-select.js +48 -0
  309. package/dist/components/navigation-menu.d.ts +127 -0
  310. package/dist/components/navigation-menu.js +129 -0
  311. package/dist/components/notification-center.d.ts +164 -0
  312. package/dist/components/notification-center.js +399 -0
  313. package/dist/components/page-header.d.ts +60 -0
  314. package/dist/components/page-header.js +60 -0
  315. package/dist/components/pagination.d.ts +121 -0
  316. package/dist/components/pagination.js +174 -0
  317. package/dist/components/phone-input.d.ts +49 -0
  318. package/dist/components/phone-input.js +266 -0
  319. package/dist/components/popover.d.ts +38 -0
  320. package/dist/components/popover.js +69 -0
  321. package/dist/components/progress.d.ts +79 -0
  322. package/dist/components/progress.js +97 -0
  323. package/dist/components/radio-group.d.ts +43 -0
  324. package/dist/components/radio-group.js +81 -0
  325. package/dist/components/record-detail-layout.d.ts +167 -0
  326. package/dist/components/record-detail-layout.js +233 -0
  327. package/dist/components/record-picker.d.ts +199 -0
  328. package/dist/components/record-picker.js +650 -0
  329. package/dist/components/resizable.d.ts +50 -0
  330. package/dist/components/resizable.js +88 -0
  331. package/dist/components/scroll-area.d.ts +40 -0
  332. package/dist/components/scroll-area.js +56 -0
  333. package/dist/components/select.d.ts +126 -0
  334. package/dist/components/select.js +137 -0
  335. package/dist/components/separator.d.ts +31 -0
  336. package/dist/components/separator.js +41 -0
  337. package/dist/components/settings-layout.d.ts +134 -0
  338. package/dist/components/settings-layout.js +180 -0
  339. package/dist/components/sheet.d.ts +103 -0
  340. package/dist/components/sheet.js +165 -0
  341. package/dist/components/sidebar.d.ts +171 -0
  342. package/dist/components/sidebar.js +421 -0
  343. package/dist/components/signature-pad.d.ts +85 -0
  344. package/dist/components/signature-pad.js +283 -0
  345. package/dist/components/skeleton.d.ts +64 -0
  346. package/dist/components/skeleton.js +53 -0
  347. package/dist/components/slider.d.ts +57 -0
  348. package/dist/components/slider.js +133 -0
  349. package/dist/components/slug-input.d.ts +69 -0
  350. package/dist/components/slug-input.js +201 -0
  351. package/dist/components/sparkline.d.ts +54 -0
  352. package/dist/components/sparkline.js +122 -0
  353. package/dist/components/spinner.d.ts +34 -0
  354. package/dist/components/spinner.js +34 -0
  355. package/dist/components/stat.d.ts +135 -0
  356. package/dist/components/stat.js +130 -0
  357. package/dist/components/status-picker.d.ts +107 -0
  358. package/dist/components/status-picker.js +175 -0
  359. package/dist/components/stepper.d.ts +86 -0
  360. package/dist/components/stepper.js +103 -0
  361. package/dist/components/switch.d.ts +34 -0
  362. package/dist/components/switch.js +70 -0
  363. package/dist/components/table.d.ts +101 -0
  364. package/dist/components/table.js +72 -0
  365. package/dist/components/tabs.d.ts +103 -0
  366. package/dist/components/tabs.js +173 -0
  367. package/dist/components/tag-input.d.ts +77 -0
  368. package/dist/components/tag-input.js +305 -0
  369. package/dist/components/task-list.d.ts +89 -0
  370. package/dist/components/task-list.js +238 -0
  371. package/dist/components/time-picker.d.ts +119 -0
  372. package/dist/components/time-picker.js +399 -0
  373. package/dist/components/toast.d.ts +87 -0
  374. package/dist/components/toast.js +142 -0
  375. package/dist/components/toggle.d.ts +77 -0
  376. package/dist/components/toggle.js +109 -0
  377. package/dist/components/tooltip.d.ts +69 -0
  378. package/dist/components/tooltip.js +105 -0
  379. package/dist/components/top-bar.d.ts +87 -0
  380. package/dist/components/top-bar.js +99 -0
  381. package/dist/components/tree-select.d.ts +89 -0
  382. package/dist/components/tree-select.js +243 -0
  383. package/dist/components/tree-view.d.ts +109 -0
  384. package/dist/components/tree-view.js +170 -0
  385. package/dist/components/typography.d.ts +107 -0
  386. package/dist/components/typography.js +128 -0
  387. package/dist/components/user-picker.d.ts +89 -0
  388. package/dist/components/user-picker.js +162 -0
  389. package/dist/components/version-history.d.ts +191 -0
  390. package/dist/components/version-history.js +431 -0
  391. package/dist/data-table/csv.d.ts +27 -0
  392. package/dist/data-table/csv.js +68 -0
  393. package/dist/data-table/data-table.d.ts +423 -0
  394. package/dist/data-table/data-table.js +1259 -0
  395. package/dist/data-table/filter-bar.d.ts +146 -0
  396. package/dist/data-table/filter-bar.js +569 -0
  397. package/dist/data-table/filter-fns.d.ts +65 -0
  398. package/dist/data-table/filter-fns.js +382 -0
  399. package/dist/data-table/index.d.ts +8 -0
  400. package/dist/data-table/index.js +9 -0
  401. package/dist/data-table/saved-views.d.ts +100 -0
  402. package/dist/data-table/saved-views.js +251 -0
  403. package/dist/data-table/types.d.ts +168 -0
  404. package/dist/data-table/types.js +87 -0
  405. package/dist/data-table/url-state.d.ts +94 -0
  406. package/dist/data-table/url-state.js +303 -0
  407. package/dist/data-table/view-state.d.ts +16 -0
  408. package/dist/data-table/view-state.js +81 -0
  409. package/dist/editor/_test-setup.d.ts +1 -0
  410. package/dist/editor/_test-setup.js +33 -0
  411. package/dist/editor/block-editor.d.ts +137 -0
  412. package/dist/editor/block-editor.js +280 -0
  413. package/dist/editor/commands.d.ts +31 -0
  414. package/dist/editor/commands.js +150 -0
  415. package/dist/editor/context.d.ts +108 -0
  416. package/dist/editor/context.js +30 -0
  417. package/dist/editor/convert.d.ts +66 -0
  418. package/dist/editor/convert.js +567 -0
  419. package/dist/editor/drag-handle.d.ts +10 -0
  420. package/dist/editor/drag-handle.js +69 -0
  421. package/dist/editor/extensions.d.ts +34 -0
  422. package/dist/editor/extensions.js +239 -0
  423. package/dist/editor/index.d.ts +14 -0
  424. package/dist/editor/index.js +17 -0
  425. package/dist/editor/inserter.d.ts +12 -0
  426. package/dist/editor/inserter.js +88 -0
  427. package/dist/editor/inspector.d.ts +17 -0
  428. package/dist/editor/inspector.js +65 -0
  429. package/dist/editor/items.d.ts +62 -0
  430. package/dist/editor/items.js +195 -0
  431. package/dist/editor/labels.d.ts +119 -0
  432. package/dist/editor/labels.js +130 -0
  433. package/dist/editor/markdown.d.ts +14 -0
  434. package/dist/editor/markdown.js +209 -0
  435. package/dist/editor/menus.d.ts +20 -0
  436. package/dist/editor/menus.js +236 -0
  437. package/dist/editor/nodes.d.ts +14 -0
  438. package/dist/editor/nodes.js +201 -0
  439. package/dist/editor/outline.d.ts +11 -0
  440. package/dist/editor/outline.js +52 -0
  441. package/dist/editor/schema-form.d.ts +64 -0
  442. package/dist/editor/schema-form.js +290 -0
  443. package/dist/editor/slash-menu.d.ts +15 -0
  444. package/dist/editor/slash-menu.js +119 -0
  445. package/dist/fonts/catalog.d.ts +53 -0
  446. package/dist/fonts/catalog.js +121 -0
  447. package/dist/fonts/font-picker.d.ts +70 -0
  448. package/dist/fonts/font-picker.js +225 -0
  449. package/dist/fonts/index.d.ts +6 -0
  450. package/dist/fonts/index.js +7 -0
  451. package/dist/fonts/loader.d.ts +66 -0
  452. package/dist/fonts/loader.js +161 -0
  453. package/dist/fonts/pairing-picker.d.ts +31 -0
  454. package/dist/fonts/pairing-picker.js +81 -0
  455. package/dist/fonts/pairings.d.ts +84 -0
  456. package/dist/fonts/pairings.js +149 -0
  457. package/dist/fonts/provider.d.ts +34 -0
  458. package/dist/fonts/provider.js +51 -0
  459. package/dist/form/index.d.ts +1 -0
  460. package/dist/form/index.js +1 -0
  461. package/dist/format/core.d.ts +149 -0
  462. package/dist/format/core.js +357 -0
  463. package/dist/format/index.d.ts +4 -0
  464. package/dist/format/index.js +5 -0
  465. package/dist/format/use-format.d.ts +1 -0
  466. package/dist/format/use-format.js +3 -0
  467. package/dist/index.d.ts +86 -0
  468. package/dist/index.js +87 -0
  469. package/dist/lib/cn.d.ts +3 -0
  470. package/dist/lib/cn.js +16 -0
  471. package/dist/lib/color.d.ts +64 -0
  472. package/dist/lib/color.js +177 -0
  473. package/dist/lib/compose-refs.d.ts +24 -0
  474. package/dist/lib/compose-refs.js +45 -0
  475. package/dist/lib/data-islands.d.ts +194 -0
  476. package/dist/lib/data-islands.js +368 -0
  477. package/dist/lib/date.d.ts +129 -0
  478. package/dist/lib/date.js +386 -0
  479. package/dist/lib/field-context.d.ts +64 -0
  480. package/dist/lib/field-context.js +62 -0
  481. package/dist/lib/floating-arrow.d.ts +18 -0
  482. package/dist/lib/floating-arrow.js +15 -0
  483. package/dist/lib/islands.d.ts +38 -0
  484. package/dist/lib/islands.js +40 -0
  485. package/dist/lib/labels.d.ts +51 -0
  486. package/dist/lib/labels.js +56 -0
  487. package/dist/lib/layer.d.ts +36 -0
  488. package/dist/lib/layer.js +42 -0
  489. package/dist/lib/locale.d.ts +85 -0
  490. package/dist/lib/locale.js +105 -0
  491. package/dist/lib/menu.d.ts +58 -0
  492. package/dist/lib/menu.js +99 -0
  493. package/dist/lib/message-format.d.ts +20 -0
  494. package/dist/lib/message-format.js +116 -0
  495. package/dist/lib/nav.d.ts +132 -0
  496. package/dist/lib/nav.js +178 -0
  497. package/dist/lib/provider.d.ts +100 -0
  498. package/dist/lib/provider.js +105 -0
  499. package/dist/lib/public.d.ts +22 -0
  500. package/dist/lib/public.js +33 -0
  501. package/dist/lib/sr-name.d.ts +18 -0
  502. package/dist/lib/sr-name.js +17 -0
  503. package/dist/lib/text.d.ts +100 -0
  504. package/dist/lib/text.js +233 -0
  505. package/dist/lib/theme-scope.d.ts +58 -0
  506. package/dist/lib/theme-scope.js +59 -0
  507. package/dist/lib/use-async-list.d.ts +60 -0
  508. package/dist/lib/use-async-list.js +119 -0
  509. package/dist/lib/use-container-width.d.ts +19 -0
  510. package/dist/lib/use-container-width.js +39 -0
  511. package/dist/lib/use-controllable-state.d.ts +33 -0
  512. package/dist/lib/use-controllable-state.js +56 -0
  513. package/dist/lib/use-edge-fade.d.ts +13 -0
  514. package/dist/lib/use-edge-fade.js +43 -0
  515. package/dist/lib/use-formatted-input.d.ts +69 -0
  516. package/dist/lib/use-formatted-input.js +152 -0
  517. package/dist/lib/use-hotkeys.d.ts +80 -0
  518. package/dist/lib/use-hotkeys.js +221 -0
  519. package/dist/lib/use-hover-intent.d.ts +44 -0
  520. package/dist/lib/use-hover-intent.js +119 -0
  521. package/dist/lib/use-media-query.d.ts +21 -0
  522. package/dist/lib/use-media-query.js +28 -0
  523. package/dist/lib/use-reduced-motion.d.ts +8 -0
  524. package/dist/lib/use-reduced-motion.js +13 -0
  525. package/dist/lib/use-tree.d.ts +153 -0
  526. package/dist/lib/use-tree.js +534 -0
  527. package/dist/lib/value-format.d.ts +25 -0
  528. package/dist/lib/value-format.js +56 -0
  529. package/dist/lib/variants.d.ts +131 -0
  530. package/dist/lib/variants.js +109 -0
  531. package/dist/locale-data/core/date.d.ts +24 -0
  532. package/dist/locale-data/core/date.js +68 -0
  533. package/dist/locale-data/core/decimal.d.ts +19 -0
  534. package/dist/locale-data/core/decimal.js +79 -0
  535. package/dist/locale-data/core/holidays.d.ts +30 -0
  536. package/dist/locale-data/core/holidays.js +79 -0
  537. package/dist/locale-data/core/iban.d.ts +29 -0
  538. package/dist/locale-data/core/iban.js +74 -0
  539. package/dist/locale-data/core/index.d.ts +7 -0
  540. package/dist/locale-data/core/index.js +6 -0
  541. package/dist/locale-data/core/types.d.ts +173 -0
  542. package/dist/locale-data/core/types.js +6 -0
  543. package/dist/locale-data/core/week-info.d.ts +23 -0
  544. package/dist/locale-data/core/week-info.js +85 -0
  545. package/dist/locale-data/core/working-days.d.ts +27 -0
  546. package/dist/locale-data/core/working-days.js +133 -0
  547. package/dist/locale-data/index.d.ts +2 -0
  548. package/dist/locale-data/index.js +4 -0
  549. package/dist/locale-data/tr/address-tr.json +1 -0
  550. package/dist/locale-data/tr/address.d.ts +23 -0
  551. package/dist/locale-data/tr/address.js +52 -0
  552. package/dist/locale-data/tr/holidays.d.ts +31 -0
  553. package/dist/locale-data/tr/holidays.js +81 -0
  554. package/dist/locale-data/tr/iban.d.ts +21 -0
  555. package/dist/locale-data/tr/iban.js +45 -0
  556. package/dist/locale-data/tr/id.d.ts +36 -0
  557. package/dist/locale-data/tr/id.js +120 -0
  558. package/dist/locale-data/tr/index.d.ts +12 -0
  559. package/dist/locale-data/tr/index.js +33 -0
  560. package/dist/locale-data/tr/kdv.d.ts +91 -0
  561. package/dist/locale-data/tr/kdv.js +222 -0
  562. package/dist/locales/en.d.ts +2102 -0
  563. package/dist/locales/en.js +2088 -0
  564. package/dist/locales/tr.d.ts +2086 -0
  565. package/dist/locales/tr.js +2087 -0
  566. package/dist/media/focal-point.d.ts +42 -0
  567. package/dist/media/focal-point.js +96 -0
  568. package/dist/media/gallery-layout.d.ts +19 -0
  569. package/dist/media/gallery-layout.js +61 -0
  570. package/dist/media/gallery.d.ts +64 -0
  571. package/dist/media/gallery.js +138 -0
  572. package/dist/media/image-cropper.d.ts +86 -0
  573. package/dist/media/image-cropper.js +170 -0
  574. package/dist/media/image-field.d.ts +115 -0
  575. package/dist/media/image-field.js +212 -0
  576. package/dist/media/index.d.ts +19 -0
  577. package/dist/media/index.js +23 -0
  578. package/dist/media/lightbox.d.ts +82 -0
  579. package/dist/media/lightbox.js +171 -0
  580. package/dist/media/link-preview.d.ts +97 -0
  581. package/dist/media/link-preview.js +177 -0
  582. package/dist/media/media-library.d.ts +244 -0
  583. package/dist/media/media-library.js +776 -0
  584. package/dist/media/media-picker.d.ts +96 -0
  585. package/dist/media/media-picker.js +209 -0
  586. package/dist/media/media-provider.d.ts +23 -0
  587. package/dist/media/media-provider.js +44 -0
  588. package/dist/media/media-utils.d.ts +39 -0
  589. package/dist/media/media-utils.js +145 -0
  590. package/dist/media/memory-adapter.d.ts +22 -0
  591. package/dist/media/memory-adapter.js +162 -0
  592. package/dist/media/rest-adapter.d.ts +90 -0
  593. package/dist/media/rest-adapter.js +208 -0
  594. package/dist/media/serp.d.ts +62 -0
  595. package/dist/media/serp.js +108 -0
  596. package/dist/media/test-fixtures.d.ts +3 -0
  597. package/dist/media/test-fixtures.js +37 -0
  598. package/dist/media/types.d.ts +183 -0
  599. package/dist/media/types.js +3 -0
  600. package/dist/media/use-pan-zoom.d.ts +51 -0
  601. package/dist/media/use-pan-zoom.js +156 -0
  602. package/dist/media/use-upload-queue.d.ts +64 -0
  603. package/dist/media/use-upload-queue.js +115 -0
  604. package/dist/media/video-player.d.ts +135 -0
  605. package/dist/media/video-player.js +319 -0
  606. package/dist/next/index.d.ts +42 -0
  607. package/dist/next/index.js +36 -0
  608. package/dist/render/block-renderer.d.ts +56 -0
  609. package/dist/render/block-renderer.js +137 -0
  610. package/dist/render/index.d.ts +6 -0
  611. package/dist/render/index.js +7 -0
  612. package/dist/render/prepare.d.ts +61 -0
  613. package/dist/render/prepare.js +119 -0
  614. package/dist/scheduler/core/duration.d.ts +83 -0
  615. package/dist/scheduler/core/duration.js +174 -0
  616. package/dist/scheduler/core/gantt.d.ts +63 -0
  617. package/dist/scheduler/core/gantt.js +226 -0
  618. package/dist/scheduler/core/index.d.ts +6 -0
  619. package/dist/scheduler/core/index.js +7 -0
  620. package/dist/scheduler/core/layout.d.ts +97 -0
  621. package/dist/scheduler/core/layout.js +249 -0
  622. package/dist/scheduler/core/time-scale.d.ts +89 -0
  623. package/dist/scheduler/core/time-scale.js +173 -0
  624. package/dist/scheduler/gantt.d.ts +125 -0
  625. package/dist/scheduler/gantt.js +532 -0
  626. package/dist/scheduler/index.d.ts +6 -0
  627. package/dist/scheduler/index.js +7 -0
  628. package/dist/scheduler/resource-calendar.d.ts +218 -0
  629. package/dist/scheduler/resource-calendar.js +661 -0
  630. package/dist/scheduler/scheduler.d.ts +168 -0
  631. package/dist/scheduler/scheduler.js +768 -0
  632. package/dist/scheduler/shared.d.ts +63 -0
  633. package/dist/scheduler/shared.js +145 -0
  634. package/dist/scheduler/time-tracker.d.ts +138 -0
  635. package/dist/scheduler/time-tracker.js +403 -0
  636. package/dist/sortable/core.d.ts +67 -0
  637. package/dist/sortable/core.js +167 -0
  638. package/dist/sortable/index.d.ts +8 -0
  639. package/dist/sortable/index.js +10 -0
  640. package/dist/sortable/kanban-core.d.ts +70 -0
  641. package/dist/sortable/kanban-core.js +67 -0
  642. package/dist/sortable/kanban.d.ts +147 -0
  643. package/dist/sortable/kanban.js +472 -0
  644. package/dist/sortable/sortable-list.d.ts +71 -0
  645. package/dist/sortable/sortable-list.js +76 -0
  646. package/dist/sortable/sortable-tree.d.ts +101 -0
  647. package/dist/sortable/sortable-tree.js +450 -0
  648. package/dist/sortable/sortable.d.ts +188 -0
  649. package/dist/sortable/sortable.js +485 -0
  650. package/dist/sortable/use-pointer-drag.d.ts +75 -0
  651. package/dist/sortable/use-pointer-drag.js +173 -0
  652. package/dist/sortable/use-time-scale.d.ts +11 -0
  653. package/dist/sortable/use-time-scale.js +19 -0
  654. package/dist/styles/base.css +51 -0
  655. package/dist/styles/blocks.css +949 -0
  656. package/dist/styles/calendar.css +642 -0
  657. package/dist/styles/charts.css +264 -0
  658. package/dist/styles/data.css +474 -0
  659. package/dist/styles/editors.css +1022 -0
  660. package/dist/styles/forms.css +406 -0
  661. package/dist/styles/media.css +515 -0
  662. package/dist/styles/navigation.css +293 -0
  663. package/dist/styles/overlays.css +244 -0
  664. package/dist/styles.css +742 -0
  665. package/package.json +156 -4
@@ -0,0 +1,403 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ /**
4
+ * Time tracker: one running timer across tabs (`TimerButton` + a `TimerAdapter`), a weekly
5
+ * timesheet grid with typed durations and totals (`Timesheet`), and a day-grouped entry list
6
+ * (`TimeEntryList`). Attendance sheets use `ResourceCalendar variant="codes"`.
7
+ */
8
+ import * as React from "react";
9
+ import { cva } from "class-variance-authority";
10
+ import { Lock, Play, Square, TriangleAlert } from "lucide-react";
11
+ import { cn } from "../lib/cn.js";
12
+ import { useLocale } from "../lib/locale.js";
13
+ import { useLabels } from "../lib/labels.js";
14
+ import { SrName } from "../lib/sr-name.js";
15
+ import { useControllableState } from "../lib/use-controllable-state.js";
16
+ import { Badge } from "../components/badge.js";
17
+ import { Button } from "../components/button.js";
18
+ import { NativeSelect } from "../components/native-select.js";
19
+ import { Input } from "../components/input.js";
20
+ import { EmptyState } from "../components/empty-state.js";
21
+ import { toast } from "../components/toast.js";
22
+ import { addDays } from "../locale-data/core/date.js";
23
+ import { localDate } from "./core/layout.js";
24
+ import { entryMinutes, formatDuration, parseDuration, timesheetTotals } from "./core/duration.js";
25
+ import { dayInfo, dtf, fmtDay, resolveWorkCalendar, todayIn, useAnnouncer, useNow, uses24h } from "./shared.js";
26
+ /** Tab id written into `entry.origin` so a tab knows the timer runs elsewhere. */
27
+ const TAB_ID = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `tab-${Math.random().toString(36).slice(2)}`;
28
+ const newEntryId = () => (typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `te-${Date.now().toString(36)}`);
29
+ /** In-memory adapter (docs, tests, prototypes). `onStop` receives finished entries. */
30
+ export function createMemoryTimerAdapter(opts = {}) {
31
+ let active = opts.initial ?? null;
32
+ const listeners = new Set();
33
+ const now = opts.now ?? Date.now;
34
+ const emit = () => listeners.forEach((l) => l(active));
35
+ return {
36
+ async getActive() {
37
+ return active;
38
+ },
39
+ async start(draft) {
40
+ active = { id: newEntryId(), ...draft, start: new Date(now()).toISOString(), end: undefined, origin: TAB_ID };
41
+ emit();
42
+ return active;
43
+ },
44
+ async stop(id) {
45
+ if (!active || active.id !== id)
46
+ throw new Error("No running timer with that id");
47
+ const done = { ...active, end: new Date(now()).toISOString() };
48
+ active = null;
49
+ opts.onStop?.(done);
50
+ emit();
51
+ return done;
52
+ },
53
+ subscribe(l) {
54
+ listeners.add(l);
55
+ return () => listeners.delete(l);
56
+ },
57
+ };
58
+ }
59
+ /**
60
+ * Browser adapter: `localStorage` + `BroadcastChannel`, so starting in one tab shows the timer
61
+ * running in all of them. Persist finished entries in `onStop` (your API).
62
+ */
63
+ export function createLocalTimerAdapter(opts = {}) {
64
+ const key = opts.key ?? "vamos-ui:timer";
65
+ const read = () => {
66
+ try {
67
+ const raw = window.localStorage.getItem(key);
68
+ return raw ? JSON.parse(raw) : null;
69
+ }
70
+ catch {
71
+ return null;
72
+ }
73
+ };
74
+ const write = (v) => {
75
+ try {
76
+ if (v)
77
+ window.localStorage.setItem(key, JSON.stringify(v));
78
+ else
79
+ window.localStorage.removeItem(key);
80
+ }
81
+ catch {
82
+ /* private mode: in-tab only */
83
+ }
84
+ channel?.postMessage(v);
85
+ };
86
+ const channel = typeof BroadcastChannel !== "undefined" ? new BroadcastChannel(key) : null;
87
+ return {
88
+ async getActive() {
89
+ return read();
90
+ },
91
+ async start(draft) {
92
+ const entry = { id: newEntryId(), ...draft, start: new Date().toISOString(), end: undefined, origin: TAB_ID };
93
+ write(entry);
94
+ return entry;
95
+ },
96
+ async stop(id) {
97
+ const cur = read();
98
+ if (!cur || cur.id !== id)
99
+ throw new Error("No running timer with that id");
100
+ const done = { ...cur, end: new Date().toISOString() };
101
+ write(null);
102
+ await opts.onStop?.(done);
103
+ return done;
104
+ },
105
+ subscribe(listener) {
106
+ const onMsg = (e) => listener(e.data ?? null);
107
+ const onStorage = (e) => e.key === key && listener(read());
108
+ channel?.addEventListener("message", onMsg);
109
+ window.addEventListener("storage", onStorage);
110
+ return () => {
111
+ channel?.removeEventListener("message", onMsg);
112
+ window.removeEventListener("storage", onStorage);
113
+ };
114
+ },
115
+ };
116
+ }
117
+ /* ------------------------------------------------------------------ */
118
+ /* TimerButton */
119
+ /* ------------------------------------------------------------------ */
120
+ export const timeTrackerLabels = {
121
+ start: "Start timer",
122
+ startFor: "Start timer for {project}",
123
+ stop: "Stop timer",
124
+ stopFor: "Stop timer for {project}",
125
+ started: "Timer started for {project}",
126
+ stopped: "Timer stopped. {duration} on {project}",
127
+ noProject: "No project",
128
+ project: "Project",
129
+ note: "What are you working on?",
130
+ notePlaceholder: "Add a note",
131
+ elsewhere: "Running in another tab",
132
+ stale: "Running for {duration}. Still on it?",
133
+ adjust: "Adjust end time",
134
+ failed: "The timer couldn't be updated. Try again.",
135
+ // timesheet
136
+ timesheet: "Timesheet",
137
+ row: "Project",
138
+ total: "Total",
139
+ weekTotal: "Week total",
140
+ rowTotal: "{label}, total {duration}",
141
+ dayTotal: "{day}, total {duration}",
142
+ underTarget: "under the {target} target",
143
+ invalid: "Use 1.5, 1:30, 90m or 1h 30m",
144
+ locked: "Approved. This week is read-only.",
145
+ editHint: "Type a duration, Enter saves, Escape cancels",
146
+ saveFailed: "Couldn't save {duration}. The cell was reset.",
147
+ empty: "No time tracked yet",
148
+ emptyHint: "Start the timer or add an entry.",
149
+ billable: "Billable",
150
+ running: "running",
151
+ };
152
+ const clock = (sec) => {
153
+ const h = Math.floor(sec / 3600);
154
+ const m = Math.floor((sec % 3600) / 60);
155
+ const s = Math.floor(sec % 60);
156
+ return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
157
+ };
158
+ /**
159
+ * ```tsx
160
+ * const adapter = React.useMemo(() => createLocalTimerAdapter({ onStop: api.entries.create }), []);
161
+ * <TimerButton adapter={adapter} projects={projects} defaultProjectId="mobile-app" />
162
+ * ```
163
+ */
164
+ export const TimerButton = React.forwardRef(function TimerButton({ adapter, projects = [], projectId: projectIdProp, defaultProjectId, onProjectChange, variant = "compact", staleAfterMin = 600, onStart, onStop, onAdjust, titleTicker = false, labels, className, ...props }, ref) {
165
+ const t = useLabels("timeTracker", timeTrackerLabels, labels);
166
+ const { locale } = useLocale();
167
+ const [projectId, setProjectId] = useControllableState({ value: projectIdProp, defaultValue: defaultProjectId ?? projects[0]?.id ?? "", onChange: onProjectChange });
168
+ const [active, setActive] = React.useState(null);
169
+ const [busy, setBusy] = React.useState(false);
170
+ const [note, setNote] = React.useState("");
171
+ const { message, announce } = useAnnouncer();
172
+ const now = useNow(Boolean(active), 1000);
173
+ React.useEffect(() => {
174
+ let alive = true;
175
+ adapter.getActive().then((a) => alive && setActive(a));
176
+ const off = adapter.subscribe?.((a) => setActive(a));
177
+ return () => {
178
+ alive = false;
179
+ off?.();
180
+ };
181
+ }, [adapter]);
182
+ const running = Boolean(active);
183
+ const elapsedSec = active ? Math.max(0, (now - Date.parse(active.start)) / 1000) : 0;
184
+ const project = projects.find((p) => p.id === (active?.projectId ?? projectId));
185
+ const projectName = active?.projectLabel ?? project?.label ?? t("noProject");
186
+ const stale = running && elapsedSec / 60 > staleAfterMin;
187
+ const elsewhere = running && active?.origin !== undefined && active.origin !== TAB_ID;
188
+ // Opt-in document title ticker.
189
+ const baseTitle = React.useRef(null);
190
+ React.useEffect(() => {
191
+ if (!titleTicker || typeof document === "undefined")
192
+ return;
193
+ if (running) {
194
+ baseTitle.current ??= document.title;
195
+ document.title = `${clock(elapsedSec).replace(/^00:/, "")} · ${baseTitle.current}`;
196
+ }
197
+ else if (baseTitle.current !== null) {
198
+ document.title = baseTitle.current;
199
+ baseTitle.current = null;
200
+ }
201
+ }, [titleTicker, running, elapsedSec]);
202
+ React.useEffect(() => () => {
203
+ if (baseTitle.current !== null)
204
+ document.title = baseTitle.current;
205
+ }, []);
206
+ const toggle = async () => {
207
+ if (busy)
208
+ return;
209
+ setBusy(true);
210
+ try {
211
+ if (active) {
212
+ const done = await adapter.stop(active.id);
213
+ setActive(null);
214
+ announce(t("stopped", { duration: formatDuration(entryMinutes(done), locale), project: projectName }));
215
+ onStop?.(done);
216
+ }
217
+ else {
218
+ const entry = await adapter.start({ projectId: project?.id, projectLabel: project?.label, note: note || undefined });
219
+ setActive(entry);
220
+ announce(t("started", { project: projectName }));
221
+ onStart?.(entry);
222
+ }
223
+ }
224
+ catch {
225
+ toast.danger(t("failed"));
226
+ }
227
+ finally {
228
+ setBusy(false);
229
+ }
230
+ };
231
+ const name = running ? t("stopFor", { project: projectName }) : project ? t("startFor", { project: projectName }) : t("start");
232
+ const button = (_jsxs("button", { type: "button", "aria-pressed": running, "aria-busy": busy || undefined, "data-slot": "timer-button", "data-running": running ? "" : undefined, disabled: busy, onClick: toggle, className: cn("ui-tt-btn focus-ring", variant === "full" && "ui-tt-btn-lg"), children: [_jsx("span", { className: "sr-only", children: name }), running ? _jsx("span", { "aria-hidden": true, className: "ui-tt-pulse" }) : _jsx(Play, { "aria-hidden": true, className: "ui-tt-ico" }), _jsx("span", { "aria-hidden": true, className: "tabular", children: clock(elapsedSec) }), variant === "compact" ? _jsx("span", { "aria-hidden": true, className: "ui-tt-proj", children: projectName }) : null, running && variant === "full" ? _jsx(Square, { "aria-hidden": true, className: "ui-tt-ico" }) : null] }));
233
+ return (_jsxs("div", { ref: ref, "data-slot": "timer", "data-variant": variant, className: cn(variant === "full" ? "ui-tt-full grid gap-3" : "inline-flex items-center gap-2", className), ...props, children: [variant === "full" ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-wrap items-end gap-2", children: [_jsxs("label", { className: "grid min-w-[12rem] flex-1 gap-1", children: [_jsx("span", { className: "text-[12px] font-medium text-fg-muted", children: t("project") }), _jsx(NativeSelect, { value: active?.projectId ?? projectId, disabled: running, onChange: (e) => setProjectId(e.target.value), items: projects.map((p) => ({ value: p.id, label: p.meta ? `${p.label} · ${p.meta}` : p.label })) })] }), _jsxs("label", { className: "grid min-w-[14rem] flex-[2] gap-1", children: [_jsx("span", { className: "text-[12px] font-medium text-fg-muted", children: t("note") }), _jsx(Input, { value: active?.note ?? note, disabled: running, onChange: (e) => setNote(e.target.value), placeholder: t("notePlaceholder") })] }), button] }), elsewhere || stale ? (_jsxs("p", { className: "flex items-center gap-2 text-[12.5px]", "data-slot": "timer-note", children: [stale ? _jsx(TriangleAlert, { "aria-hidden": true, className: "size-3.5 text-warning" }) : null, _jsx("span", { className: stale ? "text-warning" : "text-fg-muted", children: stale ? t("stale", { duration: formatDuration(elapsedSec / 60, locale) }) : t("elsewhere") }), stale && onAdjust && active ? _jsx(Button, { size: "xs", variant: "ghost", onClick: () => onAdjust(active), children: t("adjust") }) : null] })) : null] })) : (_jsxs(_Fragment, { children: [button, stale ? _jsx("span", { className: "sr-only", children: t("stale", { duration: formatDuration(elapsedSec / 60, locale) }) }) : null, stale ? _jsx(TriangleAlert, { "aria-hidden": true, className: "size-3.5 text-warning" }) : null] })), _jsx("span", { className: "sr-only", "aria-live": "polite", children: message })] }));
234
+ });
235
+ export const timesheetVariants = cva("ui-ts relative min-w-0", {
236
+ variants: { framed: { true: "surface rounded-ui-lg", false: "" } },
237
+ defaultVariants: { framed: true },
238
+ });
239
+ /**
240
+ * ```tsx
241
+ * <Timesheet weekStart="2026-11-09" rows={projects} value={hours} onCellChange={save} dailyTarget={8 * 60} />
242
+ * ```
243
+ */
244
+ export const Timesheet = React.forwardRef(function Timesheet({ weekStart, days: dayCount = 7, rows, value: valueProp, defaultValue, onCellChange, dailyTarget, locked = false, workCalendar, display = "clock", labels, className, ...props }, ref) {
245
+ const t = useLabels("timeTracker", timeTrackerLabels, labels);
246
+ const { locale, timeZone } = useLocale();
247
+ const cal = React.useMemo(() => resolveWorkCalendar(workCalendar, locale), [workCalendar, locale]);
248
+ const today = todayIn(timeZone);
249
+ const days = React.useMemo(() => Array.from({ length: dayCount }, (_, i) => addDays(weekStart, i)), [weekStart, dayCount]);
250
+ const infos = React.useMemo(() => days.map((d) => dayInfo(d, cal, today)), [days, cal, today]);
251
+ const [value, setValue] = useControllableState({ value: valueProp, defaultValue: defaultValue ?? {} });
252
+ const [overrides, setOverrides] = React.useState({});
253
+ React.useEffect(() => setOverrides({}), [valueProp]);
254
+ const cellValue = (rowId, day) => overrides[`${rowId}|${day}`] ?? value[rowId]?.[day] ?? 0;
255
+ const merged = React.useMemo(() => {
256
+ const out = {};
257
+ for (const r of rows) {
258
+ out[r.id] = {};
259
+ for (const d of days)
260
+ out[r.id][d] = cellValue(r.id, d);
261
+ }
262
+ return out;
263
+ // eslint-disable-next-line react-hooks/exhaustive-deps
264
+ }, [rows, days, value, overrides]);
265
+ const totals = timesheetTotals(merged, days);
266
+ const fmt = (min) => (min ? formatDuration(min, locale, display) : "");
267
+ const fmtFull = (min) => formatDuration(min, locale);
268
+ const [active, setActive] = React.useState({ r: 0, c: 0 });
269
+ const [edit, setEdit] = React.useState(null);
270
+ const gridRef = React.useRef(null);
271
+ const focus = (r, c) => {
272
+ setActive({ r, c });
273
+ requestAnimationFrame(() => gridRef.current?.querySelector(`[data-ts-cell="${r}:${c}"]`)?.focus());
274
+ };
275
+ const editable = (r) => !locked && !rows[r]?.readOnly;
276
+ const commit = (r, c, text) => {
277
+ const minutes = parseDuration(text, locale);
278
+ if (minutes === null || minutes < 0 || minutes > 24 * 60) {
279
+ setEdit({ r, c, text, error: true });
280
+ return false;
281
+ }
282
+ const row = rows[r];
283
+ const day = days[c];
284
+ const prev = cellValue(row.id, day);
285
+ setEdit(null);
286
+ if (minutes === prev)
287
+ return true;
288
+ const key = `${row.id}|${day}`;
289
+ setOverrides((o) => ({ ...o, [key]: minutes }));
290
+ if (valueProp === undefined)
291
+ setValue((v) => ({ ...v, [row.id]: { ...v[row.id], [day]: minutes } }));
292
+ Promise.resolve()
293
+ .then(() => onCellChange?.(row.id, day, minutes))
294
+ .catch(() => {
295
+ setOverrides((o) => {
296
+ const n = { ...o };
297
+ delete n[key];
298
+ return n;
299
+ });
300
+ if (valueProp === undefined)
301
+ setValue((v) => ({ ...v, [row.id]: { ...v[row.id], [day]: prev } }));
302
+ toast.danger(t("saveFailed", { duration: fmtFull(minutes) }));
303
+ });
304
+ return true;
305
+ };
306
+ const onKeyDown = (k) => {
307
+ if (edit)
308
+ return;
309
+ const { r, c } = active;
310
+ const map = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1] };
311
+ if (k.key in map) {
312
+ k.preventDefault();
313
+ const [dr, dc] = map[k.key];
314
+ return focus(Math.max(0, Math.min(rows.length - 1, r + dr)), Math.max(0, Math.min(days.length - 1, c + dc)));
315
+ }
316
+ if (k.key === "Home") {
317
+ k.preventDefault();
318
+ return focus(r, 0);
319
+ }
320
+ if (k.key === "End") {
321
+ k.preventDefault();
322
+ return focus(r, days.length - 1);
323
+ }
324
+ if (!editable(r))
325
+ return;
326
+ if (k.key === "Enter" || k.key === "F2") {
327
+ k.preventDefault();
328
+ setEdit({ r, c, text: cellValue(rows[r].id, days[c]) ? formatDuration(cellValue(rows[r].id, days[c]), locale, "clock") : "" });
329
+ }
330
+ else if (k.key === "Delete" || k.key === "Backspace") {
331
+ k.preventDefault();
332
+ commit(r, c, "");
333
+ }
334
+ else if (k.key.length === 1 && !k.metaKey && !k.ctrlKey && !k.altKey && /[\d.,:]/.test(k.key)) {
335
+ k.preventDefault();
336
+ setEdit({ r, c, text: k.key });
337
+ }
338
+ };
339
+ const titleId = React.useId();
340
+ const hintId = React.useId();
341
+ return (_jsxs("div", { ref: ref, "data-slot": "timesheet", "data-locked": locked ? "" : undefined, className: cn(timesheetVariants(), className), ...props, children: [_jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 border-b border-line px-4 py-2.5", children: [_jsxs("h3", { id: titleId, className: "me-auto font-heading text-[14px] font-semibold text-fg", children: [t("timesheet"), " ", _jsxs("span", { className: "font-normal text-fg-muted", children: ["\u00B7 ", fmtDay(locale, days[0], { day: "numeric", month: "short" }), " \u2013 ", fmtDay(locale, days.at(-1), { day: "numeric", month: "short", year: "numeric" })] })] }), locked ? (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-[12px] text-fg-muted", children: [_jsx(Lock, { "aria-hidden": true, className: "size-3.5" }), t("locked")] })) : null, _jsx("span", { id: hintId, className: "sr-only", children: t("editHint") })] }), _jsx("div", { className: "overflow-x-auto", children: _jsxs("div", { ref: gridRef, role: "grid", "aria-labelledby": titleId, "aria-describedby": hintId, "aria-readonly": locked || undefined, "aria-rowcount": rows.length + 2, className: "ui-ts-grid min-w-max", style: { gridTemplateColumns: `minmax(11rem, 1.6fr) repeat(${days.length}, minmax(4.25rem, 1fr)) minmax(5rem, 1fr)` }, onKeyDown: onKeyDown, children: [_jsxs("div", { role: "row", className: "ui-ts-row ui-ts-head", children: [_jsx("div", { role: "columnheader", className: "ui-ts-rh", children: t("row") }), days.map((d, i) => (_jsxs("div", { role: "columnheader", "aria-label": fmtDay(locale, d, { weekday: "long", day: "numeric", month: "long" }), "data-off": infos[i].working === 0 ? "" : undefined, "data-today": infos[i].today ? "" : undefined, className: "ui-ts-ch", title: infos[i].holidays[0]?.name, children: [_jsx("span", { className: "text-[10.5px] font-medium text-fg-muted", children: fmtDay(locale, d, { weekday: "short" }) }), _jsx("span", { className: "ui-ts-daynum tabular", children: fmtDay(locale, d, { day: "numeric" }) })] }, d))), _jsx("div", { role: "columnheader", className: "ui-ts-ch ui-ts-totalcol", children: t("total") })] }), rows.length === 0 ? (_jsx("div", { role: "row", className: "ui-ts-row", children: _jsx("div", { role: "gridcell", "aria-colspan": days.length + 2, className: "col-span-full p-4", children: _jsx(EmptyState, { size: "sm", title: t("empty"), description: t("emptyHint") }) }) })) : null, rows.map((row, r) => (_jsxs("div", { role: "row", className: "ui-ts-row", children: [_jsxs("div", { role: "rowheader", className: "ui-ts-rh", children: [_jsx("span", { className: "block truncate text-[13px] font-medium text-fg", children: row.label }), row.meta ? _jsx("span", { className: "block truncate text-[11.5px] text-fg-muted", children: row.meta }) : null] }), days.map((d, c) => {
342
+ const v = cellValue(row.id, d);
343
+ const isActive = active.r === r && active.c === c;
344
+ const editing = edit && edit.r === r && edit.c === c ? edit : null;
345
+ const dayName = fmtDay(locale, d, { weekday: "long", day: "numeric", month: "long" });
346
+ return (_jsxs("div", { role: "gridcell", "data-ts-cell": `${r}:${c}`, "data-off": infos[c].working === 0 ? "" : undefined, "data-pending": overrides[`${row.id}|${d}`] !== undefined ? "" : undefined, "aria-readonly": !editable(r) || undefined, tabIndex: isActive && !editing ? 0 : -1, className: "ui-ts-cell tabular", onFocus: () => !isActive && setActive({ r, c }), onDoubleClick: () => editable(r) && setEdit({ r, c, text: v ? formatDuration(v, locale, "clock") : "" }), children: [editing ? (_jsx("input", { autoFocus: true, "aria-label": `${row.label}, ${dayName}`, "aria-invalid": editing.error || undefined, "aria-describedby": editing.error ? `${hintId}-err` : undefined, inputMode: "decimal", className: "ui-ts-input tabular", value: editing.text, onFocus: (e) => e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length), onChange: (e) => setEdit({ ...editing, text: e.target.value, error: false }), onKeyDown: (e) => {
347
+ e.stopPropagation();
348
+ if (e.key === "Enter") {
349
+ e.preventDefault();
350
+ if (commit(r, c, editing.text))
351
+ focus(Math.min(rows.length - 1, r + 1), c);
352
+ }
353
+ else if (e.key === "Escape") {
354
+ e.preventDefault();
355
+ setEdit(null);
356
+ focus(r, c);
357
+ }
358
+ else if (e.key === "Tab") {
359
+ if (commit(r, c, editing.text))
360
+ return;
361
+ e.preventDefault();
362
+ }
363
+ }, onBlur: () => {
364
+ if (edit && !edit.error)
365
+ commit(r, c, editing.text);
366
+ } })) : (_jsx(SrName, { name: `${row.label}, ${dayName}, ${v ? fmtFull(v) : "0"}`, children: fmt(v) })), editing?.error ? (_jsx("span", { id: `${hintId}-err`, role: "alert", className: "ui-ts-error", children: t("invalid") })) : null] }, d));
367
+ }), _jsx("div", { role: "gridcell", className: "ui-ts-cell ui-ts-totalcol tabular", children: _jsx(SrName, { name: t("rowTotal", { label: row.label, duration: fmtFull(totals.rows[row.id] ?? 0) }), children: fmt(totals.rows[row.id] ?? 0) || "–" }) })] }, row.id))), _jsxs("div", { role: "row", className: "ui-ts-row ui-ts-foot", children: [_jsx("div", { role: "rowheader", className: "ui-ts-rh text-[12px] font-semibold", children: t("total") }), days.map((d, c) => {
368
+ const sum = totals.days[d] ?? 0;
369
+ const under = dailyTarget !== undefined && infos[c].working > 0 && sum < dailyTarget * infos[c].working && compareDay(d, today) <= 0;
370
+ return (_jsx("div", { role: "gridcell", "data-under": under ? "" : undefined, className: "ui-ts-cell tabular", children: _jsx(SrName, { name: `${t("dayTotal", { day: fmtDay(locale, d, { weekday: "long", day: "numeric", month: "long" }), duration: fmtFull(sum) })}${under ? `, ${t("underTarget", { target: fmtFull(dailyTarget * infos[c].working) })}` : ""}`, children: fmt(sum) || "–" }) }, d));
371
+ }), _jsx("div", { role: "gridcell", className: "ui-ts-cell ui-ts-totalcol ui-ts-grand tabular", children: _jsx(SrName, { name: `${t("weekTotal")}, ${fmtFull(totals.total)}`, children: fmt(totals.total) || "–" }) })] })] }) })] }));
372
+ });
373
+ const compareDay = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
374
+ /** Entries grouped by day (newest first) with day totals. */
375
+ export const TimeEntryList = React.forwardRef(function TimeEntryList({ entries, onEntryOpen, showAmounts = false, labels, className, ...props }, ref) {
376
+ const t = useLabels("timeTracker", timeTrackerLabels, labels);
377
+ const { locale, timeZone, format } = useLocale();
378
+ const now = useNow(entries.some((e) => !e.end && e.durationMin === undefined), 30_000);
379
+ const h24 = uses24h(locale);
380
+ const timeFmt = dtf(locale, { hour: h24 ? "2-digit" : "numeric", minute: "2-digit", hourCycle: h24 ? "h23" : "h12", timeZone });
381
+ const groups = React.useMemo(() => {
382
+ const map = new Map();
383
+ for (const e of [...entries].sort((a, b) => Date.parse(b.start) - Date.parse(a.start))) {
384
+ const d = localDate(e.start, timeZone);
385
+ map.set(d, [...(map.get(d) ?? []), e]);
386
+ }
387
+ return [...map];
388
+ }, [entries, timeZone]);
389
+ if (!entries.length) {
390
+ return (_jsx("div", { ref: ref, className: cn("p-4", className), ...props, children: _jsx(EmptyState, { size: "sm", title: t("empty"), description: t("emptyHint") }) }));
391
+ }
392
+ return (_jsx("div", { ref: ref, "data-slot": "time-entry-list", className: cn("ui-tl grid", className), ...props, children: groups.map(([day, list]) => {
393
+ const total = list.reduce((s, e) => s + entryMinutes(e, now), 0);
394
+ const headId = `tl-${day}`;
395
+ return (_jsxs("section", { "aria-labelledby": headId, className: "ui-tl-group", children: [_jsxs("h4", { id: headId, className: "ui-tl-head", children: [_jsx("span", { children: fmtDay(locale, day, { weekday: "long", day: "numeric", month: "long" }) }), _jsx("span", { className: "tabular text-fg-muted", children: formatDuration(total, locale) })] }), _jsx("ul", { className: "grid", children: list.map((e) => {
396
+ const mins = entryMinutes(e, now);
397
+ const runningNow = !e.end && e.durationMin === undefined;
398
+ const amount = showAmounts && e.billable && e.rate ? format.currency(((Number(e.rate.amount) * mins) / 60).toFixed(2), e.rate.currency) : null;
399
+ const body = (_jsxs(_Fragment, { children: [_jsxs("span", { className: "min-w-0 flex-1", children: [_jsx("span", { className: "block truncate text-[13px] font-medium text-fg", children: e.projectLabel ?? e.projectId ?? t("noProject") }), e.note ? _jsx("span", { className: "block truncate text-[12px] text-fg-muted", children: e.note }) : null] }), e.billable ? _jsx(Badge, { size: "sm", tone: "accent", children: t("billable") }) : null, _jsxs("span", { className: "hidden w-40 shrink-0 whitespace-nowrap text-end text-[12px] tabular text-fg-muted sm:block", children: [timeFmt.format(Date.parse(e.start)), "\u2013", e.end ? timeFmt.format(Date.parse(e.end)) : "…"] }), _jsxs("span", { className: "w-20 shrink-0 text-end text-[13px] font-medium tabular text-fg", children: [runningNow ? _jsx("span", { role: "img", className: "ui-tt-pulse me-1.5 inline-block align-middle", "aria-label": t("running") }) : null, formatDuration(mins, locale, "clock")] }), amount ? _jsx("span", { className: "w-24 shrink-0 text-end text-[12.5px] tabular text-fg-muted", children: amount }) : null] }));
400
+ return (_jsx("li", { children: onEntryOpen ? (_jsx("button", { type: "button", className: "ui-tl-row focus-ring", onClick: () => onEntryOpen(e), children: body })) : (_jsx("div", { className: "ui-tl-row", children: body })) }, e.id));
401
+ }) })] }, day));
402
+ }) }));
403
+ });
@@ -0,0 +1,67 @@
1
+ /**
2
+ * React-free reorder math: array moves, multi-container moves, tree flattening and the
3
+ * drag-depth projection used by tree reordering. No drag-engine types leak from here.
4
+ */
5
+ /** Returns a copy of `items` with the element at `from` moved to `to`. */
6
+ export declare function arrayMove<T>(items: readonly T[], from: number, to: number): T[];
7
+ export type MoveOp = "up" | "down" | "top" | "bottom";
8
+ /** Target index for a Move-menu operation, or `null` when the item can't move that way. */
9
+ export declare function moveTargetIndex(index: number, length: number, op: MoveOp): number | null;
10
+ export interface ContainerState {
11
+ id: string;
12
+ items: string[];
13
+ }
14
+ /** Moves `id` into container `to` at `index` (clamped). Returns new container arrays. */
15
+ export declare function moveBetweenContainers(containers: readonly ContainerState[], id: string, to: string, index: number): ContainerState[];
16
+ /** The container holding `id`. */
17
+ export declare function findContainer(containers: readonly ContainerState[], id: string): ContainerState | undefined;
18
+ export interface SortableTreeNode {
19
+ id: string;
20
+ children?: SortableTreeNode[];
21
+ collapsed?: boolean;
22
+ }
23
+ export interface FlatTreeItem<N extends SortableTreeNode = SortableTreeNode> {
24
+ id: string;
25
+ parentId: string | null;
26
+ depth: number;
27
+ /** Index among siblings. */
28
+ index: number;
29
+ node: N;
30
+ }
31
+ /** Depth-first flattening. Children of collapsed nodes (or of `skip` ids) are left out. */
32
+ export declare function flattenTree<N extends SortableTreeNode>(nodes: readonly N[], skip?: ReadonlySet<string>): FlatTreeItem<N>[];
33
+ /** All descendant ids of `id`. */
34
+ export declare function descendantIds(nodes: readonly SortableTreeNode[], id: string): Set<string>;
35
+ export interface TreeProjection {
36
+ parentId: string | null;
37
+ depth: number;
38
+ /** Index among the new siblings. */
39
+ index: number;
40
+ /** Why the drop is invalid ("maxDepth"), when it is. */
41
+ invalid?: "maxDepth";
42
+ }
43
+ /**
44
+ * Where a dragged tree item would land: the vertical position comes from `overId`, the depth
45
+ * from the horizontal drag offset (`offsetX / indent`, sign flipped in RTL), clamped between
46
+ * the depth allowed by the item above and the item below.
47
+ */
48
+ export declare function projectTreeMove(flat: readonly FlatTreeItem[], activeId: string, overId: string, offsetX: number, indent: number, opts?: {
49
+ maxDepth?: number;
50
+ dir?: "ltr" | "rtl";
51
+ }): TreeProjection | null;
52
+ /** Moves a node to `parentId` at `index` (immutable). */
53
+ export declare function moveTreeNode<N extends SortableTreeNode>(nodes: readonly N[], id: string, parentId: string | null, index: number): N[];
54
+ /**
55
+ * A `rangeExtractor` for `@tanstack/react-virtual` that keeps the dragged row mounted (dnd-kit
56
+ * needs the active node while it is scrolled out of view).
57
+ *
58
+ * ```ts
59
+ * useVirtualizer({ …, rangeExtractor: keepMountedRange(activeIndex) });
60
+ * ```
61
+ */
62
+ export declare function keepMountedRange(keepIndex: number | null | undefined): (range: {
63
+ startIndex: number;
64
+ endIndex: number;
65
+ overscan: number;
66
+ count: number;
67
+ }) => number[];
@@ -0,0 +1,167 @@
1
+ /**
2
+ * React-free reorder math: array moves, multi-container moves, tree flattening and the
3
+ * drag-depth projection used by tree reordering. No drag-engine types leak from here.
4
+ */
5
+ /** Returns a copy of `items` with the element at `from` moved to `to`. */
6
+ export function arrayMove(items, from, to) {
7
+ const out = items.slice();
8
+ if (from < 0 || from >= out.length)
9
+ return out;
10
+ const clamped = Math.max(0, Math.min(out.length - 1, to));
11
+ const [item] = out.splice(from, 1);
12
+ out.splice(clamped, 0, item);
13
+ return out;
14
+ }
15
+ /** Target index for a Move-menu operation, or `null` when the item can't move that way. */
16
+ export function moveTargetIndex(index, length, op) {
17
+ const to = op === "up" ? index - 1 : op === "down" ? index + 1 : op === "top" ? 0 : length - 1;
18
+ return to < 0 || to >= length || to === index ? null : to;
19
+ }
20
+ /** Moves `id` into container `to` at `index` (clamped). Returns new container arrays. */
21
+ export function moveBetweenContainers(containers, id, to, index) {
22
+ const without = containers.map((c) => ({ ...c, items: c.items.filter((x) => x !== id) }));
23
+ return without.map((c) => {
24
+ if (c.id !== to)
25
+ return c;
26
+ const items = c.items.slice();
27
+ items.splice(Math.max(0, Math.min(items.length, index)), 0, id);
28
+ return { ...c, items };
29
+ });
30
+ }
31
+ /** The container holding `id`. */
32
+ export function findContainer(containers, id) {
33
+ return containers.find((c) => c.id === id) ?? containers.find((c) => c.items.includes(id));
34
+ }
35
+ /** Depth-first flattening. Children of collapsed nodes (or of `skip` ids) are left out. */
36
+ export function flattenTree(nodes, skip) {
37
+ const out = [];
38
+ const walk = (list, parentId, depth) => {
39
+ list.forEach((node, index) => {
40
+ out.push({ id: node.id, parentId, depth, index, node });
41
+ if (node.children?.length && !node.collapsed && !skip?.has(node.id))
42
+ walk(node.children, node.id, depth + 1);
43
+ });
44
+ };
45
+ walk(nodes, null, 0);
46
+ return out;
47
+ }
48
+ /** All descendant ids of `id`. */
49
+ export function descendantIds(nodes, id) {
50
+ const out = new Set();
51
+ const visit = (list, inside) => {
52
+ for (const n of list) {
53
+ if (inside)
54
+ out.add(n.id);
55
+ if (n.children)
56
+ visit(n.children, inside || n.id === id);
57
+ }
58
+ };
59
+ visit(nodes, false);
60
+ return out;
61
+ }
62
+ /**
63
+ * Where a dragged tree item would land: the vertical position comes from `overId`, the depth
64
+ * from the horizontal drag offset (`offsetX / indent`, sign flipped in RTL), clamped between
65
+ * the depth allowed by the item above and the item below.
66
+ */
67
+ export function projectTreeMove(flat, activeId, overId, offsetX, indent, opts = {}) {
68
+ const activeIndex = flat.findIndex((f) => f.id === activeId);
69
+ const overIndex = flat.findIndex((f) => f.id === overId);
70
+ if (activeIndex === -1 || overIndex === -1)
71
+ return null;
72
+ const active = flat[activeIndex];
73
+ // Drop the active item's descendants: they move with it.
74
+ const hidden = new Set();
75
+ for (let i = activeIndex + 1; i < flat.length && flat[i].depth > active.depth; i++)
76
+ hidden.add(flat[i].id);
77
+ const visible = flat.filter((f) => !hidden.has(f.id));
78
+ const from = visible.findIndex((f) => f.id === activeId);
79
+ const to = Math.max(0, visible.findIndex((f) => f.id === overId));
80
+ const reordered = arrayMove(visible, from, to);
81
+ const at = reordered.findIndex((f) => f.id === activeId);
82
+ const prev = reordered[at - 1];
83
+ const next = reordered[at + 1];
84
+ const dragDepth = Math.round(((opts.dir === "rtl" ? -1 : 1) * offsetX) / Math.max(1, indent));
85
+ const projected = active.depth + dragDepth;
86
+ const maxAllowed = prev ? prev.depth + 1 : 0;
87
+ const minAllowed = next ? next.depth : 0;
88
+ let depth = Math.max(minAllowed, Math.min(maxAllowed, projected));
89
+ // Subtree height of the active item counts against maxDepth.
90
+ let subtree = 0;
91
+ for (let i = activeIndex + 1; i < flat.length && flat[i].depth > active.depth; i++)
92
+ subtree = Math.max(subtree, flat[i].depth - active.depth);
93
+ let invalid;
94
+ if (opts.maxDepth !== undefined && depth + subtree > opts.maxDepth - 1) {
95
+ const capped = opts.maxDepth - 1 - subtree;
96
+ if (capped < minAllowed)
97
+ invalid = "maxDepth";
98
+ depth = Math.max(minAllowed, Math.min(depth, capped));
99
+ }
100
+ // Parent: the nearest item above with depth − 1.
101
+ let parentId = null;
102
+ if (depth > 0) {
103
+ for (let i = at - 1; i >= 0; i--) {
104
+ if (reordered[i].depth === depth - 1) {
105
+ parentId = reordered[i].id;
106
+ break;
107
+ }
108
+ }
109
+ }
110
+ // Index among the new siblings.
111
+ let index = 0;
112
+ for (let i = 0; i < at; i++) {
113
+ const f = reordered[i];
114
+ if (f.parentId === parentId && f.depth === depth && f.id !== activeId)
115
+ index++;
116
+ }
117
+ return { parentId, depth, index, ...(invalid ? { invalid } : {}) };
118
+ }
119
+ /** Moves a node to `parentId` at `index` (immutable). */
120
+ export function moveTreeNode(nodes, id, parentId, index) {
121
+ let moving;
122
+ const remove = (list) => list.flatMap((n) => {
123
+ if (n.id === id) {
124
+ moving = n;
125
+ return [];
126
+ }
127
+ return n.children ? [{ ...n, children: remove(n.children) }] : [n];
128
+ });
129
+ const without = remove(nodes);
130
+ if (!moving)
131
+ return nodes.slice();
132
+ const node = moving;
133
+ const insert = (list, pid) => {
134
+ if (pid === parentId) {
135
+ const out = list.slice();
136
+ out.splice(Math.max(0, Math.min(out.length, index)), 0, node);
137
+ return out;
138
+ }
139
+ return list.map((n) => (n.children || n.id === parentId ? { ...n, children: insert((n.children ?? []), n.id) } : n));
140
+ };
141
+ return insert(without, null);
142
+ }
143
+ // ---------------------------------------------------------------------------------------------
144
+ // Virtualization helper
145
+ // ---------------------------------------------------------------------------------------------
146
+ /**
147
+ * A `rangeExtractor` for `@tanstack/react-virtual` that keeps the dragged row mounted (dnd-kit
148
+ * needs the active node while it is scrolled out of view).
149
+ *
150
+ * ```ts
151
+ * useVirtualizer({ …, rangeExtractor: keepMountedRange(activeIndex) });
152
+ * ```
153
+ */
154
+ export function keepMountedRange(keepIndex) {
155
+ return (range) => {
156
+ const start = Math.max(range.startIndex - range.overscan, 0);
157
+ const end = Math.min(range.endIndex + range.overscan, range.count - 1);
158
+ const out = [];
159
+ for (let i = start; i <= end; i++)
160
+ out.push(i);
161
+ if (keepIndex != null && keepIndex >= 0 && keepIndex < range.count && (keepIndex < start || keepIndex > end)) {
162
+ out.push(keepIndex);
163
+ out.sort((a, b) => a - b);
164
+ }
165
+ return out;
166
+ };
167
+ }
@@ -0,0 +1,8 @@
1
+ export { Sortable, SortableItem, SortableHandle, SortableOverlay, SortableMoveMenu, SortableContainer, useSortableItem, useSortableItemContext, useSortableActiveId, useSortableContainerItems, sortableLabels, type SortableProps, type SortableItemProps, type SortableHandleProps, type SortableOverlayProps, type SortableMoveMenuProps, type SortableContainerProps, type SortableContainerSpec, type SortableMoveEvent, type SortableMoveBetweenEvent, type SortableOrientation, type SortableLabels, type UseSortableItemResult, } from "./sortable.js";
2
+ export { SortableList, SortableGrid, sortableListVariants, sortableRowVariants, type SortableListProps, type SortableGridProps, type SortableRenderState, } from "./sortable-list.js";
3
+ export { arrayMove, moveTargetIndex, moveBetweenContainers, findContainer, flattenTree, descendantIds, projectTreeMove, moveTreeNode, keepMountedRange, type MoveOp, type ContainerState, type SortableTreeNode, type FlatTreeItem, type TreeProjection, } from "./core.js";
4
+ export { usePointerDrag, snapToGrid, type UsePointerDragOptions, type UsePointerDragResult, type PointerDragState, type PointerDragPoint, } from "./use-pointer-drag.js";
5
+ export { useTimeScale } from "./use-time-scale.js";
6
+ export { SortableTree, sortableTreeLabels, type SortableTreeProps, type SortableTreeMoveEvent, type SortableTreeDropCheck, type SortableTreeRenderState, type SortableTreeLabels, } from "./sortable-tree.js";
7
+ export { Kanban, KanbanColumnHeader, KanbanCardTitle, KanbanCardMeta, KanbanCardFooter, kanbanLabels, kanbanColumnVariants, type KanbanProps, type KanbanCardState, type KanbanLane, type KanbanColumnHeaderProps, type KanbanLabels, } from "./kanban.js";
8
+ export { groupByStage, sumBy, weightedSum, applyKanbanMove, stageToneColor, type Stage, type StageTone, type KanbanMoveEvent, } from "./kanban-core.js";