sheer-ui 0.0.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 (635) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/package.json +369 -0
  4. package/src/lib/VENDORED.md +109 -0
  5. package/src/lib/assets/ui.css +733 -0
  6. package/src/lib/blocks/Appearance.svelte +104 -0
  7. package/src/lib/blocks/BoundaryFailed.svelte +33 -0
  8. package/src/lib/blocks/ErrorPage.svelte +65 -0
  9. package/src/lib/blocks/Footer.svelte +71 -0
  10. package/src/lib/blocks/Header.svelte +67 -0
  11. package/src/lib/blocks/Heading.svelte +86 -0
  12. package/src/lib/blocks/MobileNav.svelte +169 -0
  13. package/src/lib/blocks/PhoneInput.svelte +68 -0
  14. package/src/lib/blocks/Section.svelte +34 -0
  15. package/src/lib/blocks/alert-modal/AlertModal.svelte +83 -0
  16. package/src/lib/blocks/alert-modal/alert-modal.svelte.ts +81 -0
  17. package/src/lib/blocks/alert-modal/index.ts +2 -0
  18. package/src/lib/blocks/calendar.svelte +155 -0
  19. package/src/lib/blocks/copy-button/copy-button.svelte +43 -0
  20. package/src/lib/blocks/copy-button/copy.svelte.ts +52 -0
  21. package/src/lib/blocks/copy-button/index.ts +2 -0
  22. package/src/lib/blocks/date-picker/date-picker-with-presets.svelte +109 -0
  23. package/src/lib/blocks/date-picker/date-picker.svelte +91 -0
  24. package/src/lib/blocks/date-picker/index.ts +13 -0
  25. package/src/lib/blocks/date-picker/range-date-picker.svelte +128 -0
  26. package/src/lib/blocks/index.ts +12 -0
  27. package/src/lib/blocks/mockups/Browser.svelte +22 -0
  28. package/src/lib/blocks/mockups/Phone.svelte +44 -0
  29. package/src/lib/blocks/mockups/index.ts +2 -0
  30. package/src/lib/blocks/tab-nav/index.ts +1 -0
  31. package/src/lib/blocks/tab-nav/tab-nav.svelte +46 -0
  32. package/src/lib/blocks/time-picker/index.ts +16 -0
  33. package/src/lib/blocks/time-picker/time-input.svelte +118 -0
  34. package/src/lib/blocks/time-picker/time-picker.svelte +93 -0
  35. package/src/lib/blocks/time-picker/time-range-input.svelte +34 -0
  36. package/src/lib/blocks/time-picker/time-range-picker.svelte +180 -0
  37. package/src/lib/blocks/time-picker/time-slots.ts +61 -0
  38. package/src/lib/blocks/user-avatar/UserAvatar.svelte +36 -0
  39. package/src/lib/blocks/user-avatar/index.ts +1 -0
  40. package/src/lib/blocks/verification-code-field/VerificationCodeField.svelte +57 -0
  41. package/src/lib/blocks/verification-code-field/index.ts +1 -0
  42. package/src/lib/components/accordion/accordion.svelte.ts +43 -0
  43. package/src/lib/components/accordion/components/accordion-content.svelte +17 -0
  44. package/src/lib/components/accordion/components/accordion-item.svelte +58 -0
  45. package/src/lib/components/accordion/components/accordion-trigger.svelte +38 -0
  46. package/src/lib/components/accordion/components/accordion.svelte +24 -0
  47. package/src/lib/components/accordion/index.ts +11 -0
  48. package/src/lib/components/accordion/types.ts +19 -0
  49. package/src/lib/components/alert/alert-action.svelte +11 -0
  50. package/src/lib/components/alert/alert-description.svelte +18 -0
  51. package/src/lib/components/alert/alert-title.svelte +18 -0
  52. package/src/lib/components/alert/alert.svelte +37 -0
  53. package/src/lib/components/alert/index.ts +17 -0
  54. package/src/lib/components/avatar/avatar.svelte.ts +154 -0
  55. package/src/lib/components/avatar/components/avatar-fallback.svelte +38 -0
  56. package/src/lib/components/avatar/components/avatar-image.svelte +47 -0
  57. package/src/lib/components/avatar/components/avatar.svelte +57 -0
  58. package/src/lib/components/avatar/index.ts +9 -0
  59. package/src/lib/components/avatar/types.ts +46 -0
  60. package/src/lib/components/badge/badge.svelte +49 -0
  61. package/src/lib/components/badge/index.ts +1 -0
  62. package/src/lib/components/breadcrumb/breadcrumb-ellipsis.svelte +23 -0
  63. package/src/lib/components/breadcrumb/breadcrumb-item.svelte +11 -0
  64. package/src/lib/components/breadcrumb/breadcrumb-link.svelte +32 -0
  65. package/src/lib/components/breadcrumb/breadcrumb-list.svelte +15 -0
  66. package/src/lib/components/breadcrumb/breadcrumb-page.svelte +18 -0
  67. package/src/lib/components/breadcrumb/breadcrumb-separator.svelte +22 -0
  68. package/src/lib/components/breadcrumb/breadcrumb.svelte +10 -0
  69. package/src/lib/components/breadcrumb/index.ts +25 -0
  70. package/src/lib/components/button/button.svelte +55 -0
  71. package/src/lib/components/button/index.ts +12 -0
  72. package/src/lib/components/button/variants.ts +51 -0
  73. package/src/lib/components/calendar/calendar.svelte.ts +1081 -0
  74. package/src/lib/components/calendar/components/calendar-cell.svelte +34 -0
  75. package/src/lib/components/calendar/components/calendar-day.svelte +36 -0
  76. package/src/lib/components/calendar/components/calendar-grid-body.svelte +29 -0
  77. package/src/lib/components/calendar/components/calendar-grid-head.svelte +29 -0
  78. package/src/lib/components/calendar/components/calendar-grid-row.svelte +29 -0
  79. package/src/lib/components/calendar/components/calendar-grid.svelte +29 -0
  80. package/src/lib/components/calendar/components/calendar-head-cell.svelte +29 -0
  81. package/src/lib/components/calendar/components/calendar-header.svelte +29 -0
  82. package/src/lib/components/calendar/components/calendar-heading.svelte +33 -0
  83. package/src/lib/components/calendar/components/calendar-month-select.svelte +50 -0
  84. package/src/lib/components/calendar/components/calendar-next-button.svelte +37 -0
  85. package/src/lib/components/calendar/components/calendar-prev-button.svelte +37 -0
  86. package/src/lib/components/calendar/components/calendar-year-select.svelte +50 -0
  87. package/src/lib/components/calendar/components/calendar.svelte +123 -0
  88. package/src/lib/components/calendar/exports.ts +31 -0
  89. package/src/lib/components/calendar/index.ts +2 -0
  90. package/src/lib/components/calendar/types.ts +417 -0
  91. package/src/lib/components/card/card-action.svelte +15 -0
  92. package/src/lib/components/card/card-content.svelte +11 -0
  93. package/src/lib/components/card/card-description.svelte +11 -0
  94. package/src/lib/components/card/card-footer.svelte +11 -0
  95. package/src/lib/components/card/card-header.svelte +18 -0
  96. package/src/lib/components/card/card-title.svelte +11 -0
  97. package/src/lib/components/card/card.svelte +15 -0
  98. package/src/lib/components/card/index.ts +25 -0
  99. package/src/lib/components/carousel/carousel-arrow.svelte +42 -0
  100. package/src/lib/components/carousel/carousel-content.svelte +25 -0
  101. package/src/lib/components/carousel/carousel-dots.svelte +21 -0
  102. package/src/lib/components/carousel/carousel-item.svelte +21 -0
  103. package/src/lib/components/carousel/carousel-next.svelte +9 -0
  104. package/src/lib/components/carousel/carousel-previous.svelte +9 -0
  105. package/src/lib/components/carousel/carousel.svelte +245 -0
  106. package/src/lib/components/carousel/carouselState.svelte.ts +30 -0
  107. package/src/lib/components/carousel/index.ts +24 -0
  108. package/src/lib/components/chart/chart-container.svelte +52 -0
  109. package/src/lib/components/chart/chart-style.svelte +29 -0
  110. package/src/lib/components/chart/chart-tooltip.svelte +163 -0
  111. package/src/lib/components/chart/chart-utils.ts +50 -0
  112. package/src/lib/components/chart/index.ts +6 -0
  113. package/src/lib/components/checkbox/checkbox.svelte.ts +199 -0
  114. package/src/lib/components/checkbox/components/checkbox-group-label.svelte +29 -0
  115. package/src/lib/components/checkbox/components/checkbox-group.svelte +48 -0
  116. package/src/lib/components/checkbox/components/checkbox.svelte +85 -0
  117. package/src/lib/components/checkbox/index.ts +9 -0
  118. package/src/lib/components/checkbox/types.ts +131 -0
  119. package/src/lib/components/checkbox-native/checkbox.svelte +96 -0
  120. package/src/lib/components/checkbox-native/index.ts +8 -0
  121. package/src/lib/components/collapsible/components/collapsible-content.svelte +16 -0
  122. package/src/lib/components/collapsible/components/collapsible-trigger.svelte +14 -0
  123. package/src/lib/components/collapsible/components/collapsible.svelte +68 -0
  124. package/src/lib/components/collapsible/index.ts +9 -0
  125. package/src/lib/components/collapsible/types.ts +25 -0
  126. package/src/lib/components/combobox/components/combobox-arrow.svelte +8 -0
  127. package/src/lib/components/combobox/components/combobox-input.svelte +46 -0
  128. package/src/lib/components/combobox/components/combobox-trigger.svelte +44 -0
  129. package/src/lib/components/combobox/components/combobox.svelte +83 -0
  130. package/src/lib/components/combobox/index.ts +30 -0
  131. package/src/lib/components/combobox/select/components/select-content-static.svelte +56 -0
  132. package/src/lib/components/combobox/select/components/select-content.svelte +95 -0
  133. package/src/lib/components/combobox/select/components/select-group-heading.svelte +51 -0
  134. package/src/lib/components/combobox/select/components/select-group.svelte +51 -0
  135. package/src/lib/components/combobox/select/components/select-hidden-input.svelte +16 -0
  136. package/src/lib/components/combobox/select/components/select-item.svelte +86 -0
  137. package/src/lib/components/combobox/select/components/select-scroll-down-button.svelte +41 -0
  138. package/src/lib/components/combobox/select/components/select-scroll-up-button.svelte +34 -0
  139. package/src/lib/components/combobox/select/components/select-trigger.svelte +32 -0
  140. package/src/lib/components/combobox/select/components/select-value.svelte +40 -0
  141. package/src/lib/components/combobox/select/components/select-viewport.svelte +29 -0
  142. package/src/lib/components/combobox/select/components/select.svelte +92 -0
  143. package/src/lib/components/combobox/select/select.svelte.ts +1596 -0
  144. package/src/lib/components/combobox/select/types.ts +291 -0
  145. package/src/lib/components/combobox/types.ts +77 -0
  146. package/src/lib/components/command/command-dialog.svelte +42 -0
  147. package/src/lib/components/command/command.svelte.ts +1506 -0
  148. package/src/lib/components/command/components/_command-label.svelte +31 -0
  149. package/src/lib/components/command/components/command-empty.svelte +34 -0
  150. package/src/lib/components/command/components/command-group-heading.svelte +29 -0
  151. package/src/lib/components/command/components/command-group-items.svelte +31 -0
  152. package/src/lib/components/command/components/command-group.svelte +76 -0
  153. package/src/lib/components/command/components/command-input.svelte +55 -0
  154. package/src/lib/components/command/components/command-item.svelte +61 -0
  155. package/src/lib/components/command/components/command-link-item.svelte +61 -0
  156. package/src/lib/components/command/components/command-list.svelte +41 -0
  157. package/src/lib/components/command/components/command-loading.svelte +30 -0
  158. package/src/lib/components/command/components/command-separator.svelte +34 -0
  159. package/src/lib/components/command/components/command-viewport.svelte +29 -0
  160. package/src/lib/components/command/components/command.svelte +143 -0
  161. package/src/lib/components/command/compute-command-score.ts +207 -0
  162. package/src/lib/components/command/index.ts +29 -0
  163. package/src/lib/components/command/types.ts +222 -0
  164. package/src/lib/components/command/utils.ts +30 -0
  165. package/src/lib/components/context-menu/components/context-menu-content-static.svelte +22 -0
  166. package/src/lib/components/context-menu/components/context-menu-content.svelte +22 -0
  167. package/src/lib/components/context-menu/components/context-menu-trigger.svelte +46 -0
  168. package/src/lib/components/context-menu/components/context-menu.svelte +8 -0
  169. package/src/lib/components/context-menu/index.ts +39 -0
  170. package/src/lib/components/context-menu/types.ts +56 -0
  171. package/src/lib/components/data-table/column-helpers.ts +97 -0
  172. package/src/lib/components/data-table/data-table-checkbox.svelte +25 -0
  173. package/src/lib/components/data-table/data-table-sort-button.svelte +16 -0
  174. package/src/lib/components/data-table/flex-render.svelte +42 -0
  175. package/src/lib/components/data-table/index.ts +29 -0
  176. package/src/lib/components/data-table/render-helpers.ts +105 -0
  177. package/src/lib/components/data-table/table-cell.svelte +9 -0
  178. package/src/lib/components/data-table/table-column-header.svelte +51 -0
  179. package/src/lib/components/data-table/table-faceted-filter.svelte +109 -0
  180. package/src/lib/components/data-table/table-pagination.svelte +54 -0
  181. package/src/lib/components/data-table/table-priority-cell.svelte +22 -0
  182. package/src/lib/components/data-table/table-row-actions.svelte +29 -0
  183. package/src/lib/components/data-table/table-status-cell.svelte +34 -0
  184. package/src/lib/components/data-table/table-title-cell.svelte +24 -0
  185. package/src/lib/components/data-table/table-toolbar.svelte +55 -0
  186. package/src/lib/components/data-table/table-view-options.svelte +25 -0
  187. package/src/lib/components/date-field/components/date-field-hidden-input.svelte +9 -0
  188. package/src/lib/components/date-field/components/date-field-input.svelte +33 -0
  189. package/src/lib/components/date-field/components/date-field-label.svelte +29 -0
  190. package/src/lib/components/date-field/components/date-field-segment.svelte +29 -0
  191. package/src/lib/components/date-field/components/date-field.svelte +106 -0
  192. package/src/lib/components/date-field/date-field.svelte.ts +1474 -0
  193. package/src/lib/components/date-field/index.ts +11 -0
  194. package/src/lib/components/date-field/types.ts +165 -0
  195. package/src/lib/components/date-range-field/components/date-range-field-input.svelte +36 -0
  196. package/src/lib/components/date-range-field/components/date-range-field-label.svelte +29 -0
  197. package/src/lib/components/date-range-field/components/date-range-field.svelte +106 -0
  198. package/src/lib/components/date-range-field/date-range-field.svelte.ts +212 -0
  199. package/src/lib/components/date-range-field/index.ts +11 -0
  200. package/src/lib/components/date-range-field/types.ts +171 -0
  201. package/src/lib/components/dialog/components/dialog-close.svelte +31 -0
  202. package/src/lib/components/dialog/components/dialog-content-headless.svelte +104 -0
  203. package/src/lib/components/dialog/components/dialog-content.svelte +69 -0
  204. package/src/lib/components/dialog/components/dialog-description.svelte +29 -0
  205. package/src/lib/components/dialog/components/dialog-overlay.svelte +31 -0
  206. package/src/lib/components/dialog/components/dialog-title.svelte +30 -0
  207. package/src/lib/components/dialog/components/dialog-trigger.svelte +30 -0
  208. package/src/lib/components/dialog/components/dialog.svelte +21 -0
  209. package/src/lib/components/dialog/components/modal-surface.svelte +131 -0
  210. package/src/lib/components/dialog/dialog.svelte.ts +371 -0
  211. package/src/lib/components/dialog/index.ts +19 -0
  212. package/src/lib/components/dialog/types.ts +105 -0
  213. package/src/lib/components/drawer/drawer-close.svelte +7 -0
  214. package/src/lib/components/drawer/drawer-content.svelte +91 -0
  215. package/src/lib/components/drawer/drawer-description.svelte +8 -0
  216. package/src/lib/components/drawer/drawer-footer.svelte +11 -0
  217. package/src/lib/components/drawer/drawer-header.svelte +11 -0
  218. package/src/lib/components/drawer/drawer-nested.svelte +44 -0
  219. package/src/lib/components/drawer/drawer-overlay.svelte +60 -0
  220. package/src/lib/components/drawer/drawer-portal.svelte +10 -0
  221. package/src/lib/components/drawer/drawer-title.svelte +8 -0
  222. package/src/lib/components/drawer/drawer-trigger.svelte +7 -0
  223. package/src/lib/components/drawer/drawer.svelte +290 -0
  224. package/src/lib/components/drawer/index.ts +37 -0
  225. package/src/lib/components/dropdown-menu/components/dropdown-menu-content-static.svelte +22 -0
  226. package/src/lib/components/dropdown-menu/components/dropdown-menu-content.svelte +22 -0
  227. package/src/lib/components/dropdown-menu/index.ts +39 -0
  228. package/src/lib/components/dropdown-menu/types.ts +41 -0
  229. package/src/lib/components/empty/empty-content.svelte +15 -0
  230. package/src/lib/components/empty/empty-description.svelte +15 -0
  231. package/src/lib/components/empty/empty-header.svelte +15 -0
  232. package/src/lib/components/empty/empty-media.svelte +21 -0
  233. package/src/lib/components/empty/empty-title.svelte +11 -0
  234. package/src/lib/components/empty/empty.svelte +18 -0
  235. package/src/lib/components/empty/index.ts +22 -0
  236. package/src/lib/components/empty/variants.ts +16 -0
  237. package/src/lib/components/field/field-content.svelte +14 -0
  238. package/src/lib/components/field/field-description.svelte +19 -0
  239. package/src/lib/components/field/field-error.svelte +47 -0
  240. package/src/lib/components/field/field-group.svelte +17 -0
  241. package/src/lib/components/field/field-label.svelte +18 -0
  242. package/src/lib/components/field/field-legend.svelte +23 -0
  243. package/src/lib/components/field/field-separator.svelte +32 -0
  244. package/src/lib/components/field/field-set.svelte +14 -0
  245. package/src/lib/components/field/field-title.svelte +14 -0
  246. package/src/lib/components/field/field.svelte +36 -0
  247. package/src/lib/components/field/index.ts +32 -0
  248. package/src/lib/components/field/variants.ts +19 -0
  249. package/src/lib/components/input/file-input.svelte +26 -0
  250. package/src/lib/components/input/index.ts +12 -0
  251. package/src/lib/components/input/input.svelte +24 -0
  252. package/src/lib/components/input/variants.ts +28 -0
  253. package/src/lib/components/item/index.ts +34 -0
  254. package/src/lib/components/item/item-actions.svelte +11 -0
  255. package/src/lib/components/item/item-content.svelte +15 -0
  256. package/src/lib/components/item/item-description.svelte +18 -0
  257. package/src/lib/components/item/item-footer.svelte +11 -0
  258. package/src/lib/components/item/item-group.svelte +16 -0
  259. package/src/lib/components/item/item-header.svelte +11 -0
  260. package/src/lib/components/item/item-media.svelte +37 -0
  261. package/src/lib/components/item/item-separator.svelte +9 -0
  262. package/src/lib/components/item/item-title.svelte +15 -0
  263. package/src/lib/components/item/item.svelte +61 -0
  264. package/src/lib/components/kbd/index.ts +10 -0
  265. package/src/lib/components/kbd/kbd-group.svelte +11 -0
  266. package/src/lib/components/kbd/kbd.svelte +18 -0
  267. package/src/lib/components/label/exports.ts +2 -0
  268. package/src/lib/components/label/index.ts +2 -0
  269. package/src/lib/components/label/label.svelte +39 -0
  270. package/src/lib/components/label/label.svelte.ts +39 -0
  271. package/src/lib/components/label/types.ts +7 -0
  272. package/src/lib/components/link-preview/components/link-preview-content.svelte +60 -0
  273. package/src/lib/components/link-preview/components/link-preview-trigger.svelte +29 -0
  274. package/src/lib/components/link-preview/components/link-preview.svelte +34 -0
  275. package/src/lib/components/link-preview/exports.ts +11 -0
  276. package/src/lib/components/link-preview/index.ts +2 -0
  277. package/src/lib/components/link-preview/link-preview.svelte.ts +270 -0
  278. package/src/lib/components/link-preview/types.ts +102 -0
  279. package/src/lib/components/menu/components/menu-arrow.svelte +14 -0
  280. package/src/lib/components/menu/components/menu-checkbox-group.svelte +42 -0
  281. package/src/lib/components/menu/components/menu-checkbox-item.svelte +85 -0
  282. package/src/lib/components/menu/components/menu-content.svelte +98 -0
  283. package/src/lib/components/menu/components/menu-group-heading.svelte +47 -0
  284. package/src/lib/components/menu/components/menu-group.svelte +36 -0
  285. package/src/lib/components/menu/components/menu-item.svelte +58 -0
  286. package/src/lib/components/menu/components/menu-radio-group.svelte +44 -0
  287. package/src/lib/components/menu/components/menu-radio-item.svelte +65 -0
  288. package/src/lib/components/menu/components/menu-separator.svelte +38 -0
  289. package/src/lib/components/menu/components/menu-sub-content-static.svelte +8 -0
  290. package/src/lib/components/menu/components/menu-sub-content.svelte +133 -0
  291. package/src/lib/components/menu/components/menu-sub-trigger.svelte +60 -0
  292. package/src/lib/components/menu/components/menu-sub.svelte +23 -0
  293. package/src/lib/components/menu/components/menu-trigger.svelte +50 -0
  294. package/src/lib/components/menu/components/menu.svelte +58 -0
  295. package/src/lib/components/menu/exports.ts +38 -0
  296. package/src/lib/components/menu/menu.svelte.ts +1599 -0
  297. package/src/lib/components/menu/types.ts +285 -0
  298. package/src/lib/components/menu/utils.ts +68 -0
  299. package/src/lib/components/menubar/components/menubar-content-static.svelte +50 -0
  300. package/src/lib/components/menubar/components/menubar-content.svelte +54 -0
  301. package/src/lib/components/menubar/components/menubar-menu.svelte +34 -0
  302. package/src/lib/components/menubar/components/menubar-trigger.svelte +50 -0
  303. package/src/lib/components/menubar/components/menubar.svelte +57 -0
  304. package/src/lib/components/menubar/exports.ts +44 -0
  305. package/src/lib/components/menubar/index.ts +2 -0
  306. package/src/lib/components/menubar/menubar.svelte.ts +394 -0
  307. package/src/lib/components/menubar/types.ts +97 -0
  308. package/src/lib/components/meter/components/meter.svelte +41 -0
  309. package/src/lib/components/meter/exports.ts +2 -0
  310. package/src/lib/components/meter/index.ts +2 -0
  311. package/src/lib/components/meter/meter.svelte.ts +47 -0
  312. package/src/lib/components/meter/types.ts +28 -0
  313. package/src/lib/components/navigation-menu/components/navigation-menu-content-impl.svelte +85 -0
  314. package/src/lib/components/navigation-menu/components/navigation-menu-content.svelte +58 -0
  315. package/src/lib/components/navigation-menu/components/navigation-menu-indicator-impl.svelte +29 -0
  316. package/src/lib/components/navigation-menu/components/navigation-menu-indicator.svelte +56 -0
  317. package/src/lib/components/navigation-menu/components/navigation-menu-item.svelte +56 -0
  318. package/src/lib/components/navigation-menu/components/navigation-menu-link.svelte +64 -0
  319. package/src/lib/components/navigation-menu/components/navigation-menu-list.svelte +59 -0
  320. package/src/lib/components/navigation-menu/components/navigation-menu-sub.svelte +46 -0
  321. package/src/lib/components/navigation-menu/components/navigation-menu-trigger.svelte +80 -0
  322. package/src/lib/components/navigation-menu/components/navigation-menu-viewport.svelte +63 -0
  323. package/src/lib/components/navigation-menu/components/navigation-menu.svelte +80 -0
  324. package/src/lib/components/navigation-menu/index.ts +28 -0
  325. package/src/lib/components/navigation-menu/navigation-menu.svelte.ts +1092 -0
  326. package/src/lib/components/navigation-menu/types.ts +189 -0
  327. package/src/lib/components/pagination/components/pagination-next-button.svelte +60 -0
  328. package/src/lib/components/pagination/components/pagination-page.svelte +65 -0
  329. package/src/lib/components/pagination/components/pagination-prev-button.svelte +60 -0
  330. package/src/lib/components/pagination/components/pagination.svelte +65 -0
  331. package/src/lib/components/pagination/index.ts +11 -0
  332. package/src/lib/components/pagination/pagination.svelte.ts +275 -0
  333. package/src/lib/components/pagination/types.ts +100 -0
  334. package/src/lib/components/pin-input/components/pin-input-cell.svelte +49 -0
  335. package/src/lib/components/pin-input/components/pin-input.svelte +76 -0
  336. package/src/lib/components/pin-input/exports.ts +4 -0
  337. package/src/lib/components/pin-input/index.ts +2 -0
  338. package/src/lib/components/pin-input/pin-input.svelte.ts +541 -0
  339. package/src/lib/components/pin-input/types.ts +118 -0
  340. package/src/lib/components/pin-input/usePasswordManager.svelte.ts +122 -0
  341. package/src/lib/components/popover/components/popover-close.svelte +38 -0
  342. package/src/lib/components/popover/components/popover-content.svelte +70 -0
  343. package/src/lib/components/popover/components/popover-header.svelte +11 -0
  344. package/src/lib/components/popover/components/popover-title.svelte +11 -0
  345. package/src/lib/components/popover/components/popover-trigger.svelte +44 -0
  346. package/src/lib/components/popover/components/popover.svelte +26 -0
  347. package/src/lib/components/popover/exports.ts +13 -0
  348. package/src/lib/components/popover/index.ts +2 -0
  349. package/src/lib/components/popover/popover.svelte.ts +392 -0
  350. package/src/lib/components/popover/types.ts +92 -0
  351. package/src/lib/components/progress/components/progress.svelte +56 -0
  352. package/src/lib/components/progress/exports.ts +3 -0
  353. package/src/lib/components/progress/index.ts +2 -0
  354. package/src/lib/components/progress/progress.svelte.ts +58 -0
  355. package/src/lib/components/progress/types.ts +28 -0
  356. package/src/lib/components/radio-group/context.ts +13 -0
  357. package/src/lib/components/radio-group/index.ts +10 -0
  358. package/src/lib/components/radio-group/radio-group-item.svelte +67 -0
  359. package/src/lib/components/radio-group/radio-group.svelte +87 -0
  360. package/src/lib/components/range-calendar/components/range-calendar-cell.svelte +31 -0
  361. package/src/lib/components/range-calendar/components/range-calendar-day.svelte +33 -0
  362. package/src/lib/components/range-calendar/components/range-calendar.svelte +120 -0
  363. package/src/lib/components/range-calendar/exports.ts +31 -0
  364. package/src/lib/components/range-calendar/index.ts +2 -0
  365. package/src/lib/components/range-calendar/range-calendar.svelte.ts +739 -0
  366. package/src/lib/components/range-calendar/types.ts +258 -0
  367. package/src/lib/components/resizable/index.ts +15 -0
  368. package/src/lib/components/resizable/resizable-handle.svelte +30 -0
  369. package/src/lib/components/resizable/resizable-pane-group.svelte +19 -0
  370. package/src/lib/components/scroll-area/components/scroll-area-corner-impl.svelte +34 -0
  371. package/src/lib/components/scroll-area/components/scroll-area-corner.svelte +18 -0
  372. package/src/lib/components/scroll-area/components/scroll-area-scrollbar-auto.svelte +15 -0
  373. package/src/lib/components/scroll-area/components/scroll-area-scrollbar-hover.svelte +22 -0
  374. package/src/lib/components/scroll-area/components/scroll-area-scrollbar-scroll.svelte +16 -0
  375. package/src/lib/components/scroll-area/components/scroll-area-scrollbar-shared.svelte +19 -0
  376. package/src/lib/components/scroll-area/components/scroll-area-scrollbar-visible.svelte +16 -0
  377. package/src/lib/components/scroll-area/components/scroll-area-scrollbar-x.svelte +23 -0
  378. package/src/lib/components/scroll-area/components/scroll-area-scrollbar-y.svelte +24 -0
  379. package/src/lib/components/scroll-area/components/scroll-area-scrollbar.svelte +56 -0
  380. package/src/lib/components/scroll-area/components/scroll-area-thumb-impl.svelte +49 -0
  381. package/src/lib/components/scroll-area/components/scroll-area-thumb.svelte +21 -0
  382. package/src/lib/components/scroll-area/components/scroll-area-viewport.svelte +39 -0
  383. package/src/lib/components/scroll-area/components/scroll-area.svelte +82 -0
  384. package/src/lib/components/scroll-area/exports.ts +13 -0
  385. package/src/lib/components/scroll-area/index.ts +2 -0
  386. package/src/lib/components/scroll-area/scroll-area.svelte.ts +946 -0
  387. package/src/lib/components/scroll-area/types.ts +67 -0
  388. package/src/lib/components/select/index.ts +5 -0
  389. package/src/lib/components/select/select-opt-group.svelte +10 -0
  390. package/src/lib/components/select/select-option.svelte +15 -0
  391. package/src/lib/components/select/select.svelte +281 -0
  392. package/src/lib/components/separator/components/separator.svelte +49 -0
  393. package/src/lib/components/separator/index.ts +3 -0
  394. package/src/lib/components/separator/separator.svelte.ts +43 -0
  395. package/src/lib/components/separator/types.ts +22 -0
  396. package/src/lib/components/sheet/components/sheet-close.svelte +8 -0
  397. package/src/lib/components/sheet/components/sheet-content.svelte +108 -0
  398. package/src/lib/components/sheet/components/sheet-description.svelte +9 -0
  399. package/src/lib/components/sheet/components/sheet-footer.svelte +11 -0
  400. package/src/lib/components/sheet/components/sheet-header.svelte +11 -0
  401. package/src/lib/components/sheet/components/sheet-overlay.svelte +13 -0
  402. package/src/lib/components/sheet/components/sheet-title.svelte +9 -0
  403. package/src/lib/components/sheet/components/sheet-trigger.svelte +8 -0
  404. package/src/lib/components/sheet/index.ts +47 -0
  405. package/src/lib/components/sheet/variants.ts +20 -0
  406. package/src/lib/components/sidebar/constants.ts +6 -0
  407. package/src/lib/components/sidebar/context.svelte.ts +54 -0
  408. package/src/lib/components/sidebar/index.ts +77 -0
  409. package/src/lib/components/sidebar/sidebar-content.svelte +16 -0
  410. package/src/lib/components/sidebar/sidebar-desktop-surface.svelte +60 -0
  411. package/src/lib/components/sidebar/sidebar-footer.svelte +11 -0
  412. package/src/lib/components/sidebar/sidebar-group-action.svelte +34 -0
  413. package/src/lib/components/sidebar/sidebar-group-content.svelte +16 -0
  414. package/src/lib/components/sidebar/sidebar-group-label.svelte +34 -0
  415. package/src/lib/components/sidebar/sidebar-group.svelte +16 -0
  416. package/src/lib/components/sidebar/sidebar-header.svelte +11 -0
  417. package/src/lib/components/sidebar/sidebar-input.svelte +14 -0
  418. package/src/lib/components/sidebar/sidebar-inset.svelte +18 -0
  419. package/src/lib/components/sidebar/sidebar-menu-action.svelte +38 -0
  420. package/src/lib/components/sidebar/sidebar-menu-badge.svelte +19 -0
  421. package/src/lib/components/sidebar/sidebar-menu-button.svelte +99 -0
  422. package/src/lib/components/sidebar/sidebar-menu-item.svelte +21 -0
  423. package/src/lib/components/sidebar/sidebar-menu-skeleton.svelte +34 -0
  424. package/src/lib/components/sidebar/sidebar-menu-sub-button.svelte +40 -0
  425. package/src/lib/components/sidebar/sidebar-menu-sub-item.svelte +16 -0
  426. package/src/lib/components/sidebar/sidebar-menu-sub.svelte +19 -0
  427. package/src/lib/components/sidebar/sidebar-menu.svelte +21 -0
  428. package/src/lib/components/sidebar/sidebar-mobile-surface.svelte +48 -0
  429. package/src/lib/components/sidebar/sidebar-provider.svelte +60 -0
  430. package/src/lib/components/sidebar/sidebar-rail.svelte +36 -0
  431. package/src/lib/components/sidebar/sidebar-separator.svelte +9 -0
  432. package/src/lib/components/sidebar/sidebar-trigger.svelte +35 -0
  433. package/src/lib/components/sidebar/sidebar.svelte +30 -0
  434. package/src/lib/components/sidebar/types.ts +14 -0
  435. package/src/lib/components/skeleton/index.ts +7 -0
  436. package/src/lib/components/skeleton/skeleton.svelte +9 -0
  437. package/src/lib/components/slider/components/slider-range.svelte +37 -0
  438. package/src/lib/components/slider/components/slider-thumb-label.svelte +42 -0
  439. package/src/lib/components/slider/components/slider-thumb.svelte +46 -0
  440. package/src/lib/components/slider/components/slider-tick-label.svelte +42 -0
  441. package/src/lib/components/slider/components/slider-tick.svelte +28 -0
  442. package/src/lib/components/slider/components/slider.svelte +136 -0
  443. package/src/lib/components/slider/helpers.ts +249 -0
  444. package/src/lib/components/slider/index.ts +15 -0
  445. package/src/lib/components/slider/slider.svelte.ts +979 -0
  446. package/src/lib/components/slider/types.ts +294 -0
  447. package/src/lib/components/sonner/Toast.svelte +558 -0
  448. package/src/lib/components/sonner/Toaster.svelte +603 -0
  449. package/src/lib/components/sonner/index.ts +15 -0
  450. package/src/lib/components/sonner/toast-state.svelte.ts +217 -0
  451. package/src/lib/components/sonner/types.ts +384 -0
  452. package/src/lib/components/switch/index.ts +8 -0
  453. package/src/lib/components/switch/switch.svelte +78 -0
  454. package/src/lib/components/table/index.ts +28 -0
  455. package/src/lib/components/table/table-body.svelte +15 -0
  456. package/src/lib/components/table/table-caption.svelte +10 -0
  457. package/src/lib/components/table/table-cell.svelte +14 -0
  458. package/src/lib/components/table/table-footer.svelte +19 -0
  459. package/src/lib/components/table/table-head.svelte +17 -0
  460. package/src/lib/components/table/table-header.svelte +15 -0
  461. package/src/lib/components/table/table-row.svelte +14 -0
  462. package/src/lib/components/table/table.svelte +12 -0
  463. package/src/lib/components/tabs/components/tabs-content.svelte +30 -0
  464. package/src/lib/components/tabs/components/tabs-list.svelte +38 -0
  465. package/src/lib/components/tabs/components/tabs-trigger.svelte +51 -0
  466. package/src/lib/components/tabs/components/tabs.svelte +52 -0
  467. package/src/lib/components/tabs/index.ts +11 -0
  468. package/src/lib/components/tabs/tabs.svelte.ts +253 -0
  469. package/src/lib/components/tabs/types.ts +86 -0
  470. package/src/lib/components/textarea/index.ts +7 -0
  471. package/src/lib/components/textarea/textarea.svelte +23 -0
  472. package/src/lib/components/theme-toggle/index.ts +5 -0
  473. package/src/lib/components/theme-toggle/theme-toggle.svelte +49 -0
  474. package/src/lib/components/theme-toggle/theme.svelte.ts +81 -0
  475. package/src/lib/components/time-field/components/time-field-hidden-input.svelte +9 -0
  476. package/src/lib/components/time-field/components/time-field-input.svelte +33 -0
  477. package/src/lib/components/time-field/components/time-field-label.svelte +29 -0
  478. package/src/lib/components/time-field/components/time-field-segment.svelte +29 -0
  479. package/src/lib/components/time-field/components/time-field.svelte +99 -0
  480. package/src/lib/components/time-field/index.ts +11 -0
  481. package/src/lib/components/time-field/time-field.svelte.ts +1198 -0
  482. package/src/lib/components/time-field/types.ts +174 -0
  483. package/src/lib/components/time-range-field/components/time-range-field-input.svelte +36 -0
  484. package/src/lib/components/time-range-field/components/time-range-field-label.svelte +29 -0
  485. package/src/lib/components/time-range-field/components/time-range-field.svelte +104 -0
  486. package/src/lib/components/time-range-field/index.ts +11 -0
  487. package/src/lib/components/time-range-field/time-range-field.svelte.ts +235 -0
  488. package/src/lib/components/time-range-field/types.ts +181 -0
  489. package/src/lib/components/toggle/components/toggle.svelte +55 -0
  490. package/src/lib/components/toggle/index.ts +3 -0
  491. package/src/lib/components/toggle/toggle.svelte.ts +57 -0
  492. package/src/lib/components/toggle/types.ts +33 -0
  493. package/src/lib/components/toggle/variants.ts +25 -0
  494. package/src/lib/components/toggle-group/components/toggle-group-item.svelte +67 -0
  495. package/src/lib/components/toggle-group/components/toggle-group.svelte +109 -0
  496. package/src/lib/components/toggle-group/index.ts +7 -0
  497. package/src/lib/components/toggle-group/toggle-group.svelte.ts +235 -0
  498. package/src/lib/components/toggle-group/types.ts +89 -0
  499. package/src/lib/components/toolbar/components/toolbar-button.svelte +46 -0
  500. package/src/lib/components/toolbar/components/toolbar-group-item.svelte +56 -0
  501. package/src/lib/components/toolbar/components/toolbar-group.svelte +69 -0
  502. package/src/lib/components/toolbar/components/toolbar-link.svelte +39 -0
  503. package/src/lib/components/toolbar/components/toolbar.svelte +39 -0
  504. package/src/lib/components/toolbar/index.ts +13 -0
  505. package/src/lib/components/toolbar/toolbar.svelte.ts +373 -0
  506. package/src/lib/components/toolbar/types.ts +60 -0
  507. package/src/lib/components/tooltip/components/tooltip-content.svelte +81 -0
  508. package/src/lib/components/tooltip/components/tooltip-provider.svelte +26 -0
  509. package/src/lib/components/tooltip/components/tooltip-trigger.svelte +48 -0
  510. package/src/lib/components/tooltip/components/tooltip.svelte +55 -0
  511. package/src/lib/components/tooltip/index.ts +17 -0
  512. package/src/lib/components/tooltip/tooltip.svelte.ts +796 -0
  513. package/src/lib/components/tooltip/types.ts +175 -0
  514. package/src/lib/components/tooltip/utils.ts +1 -0
  515. package/src/lib/icons/google-icon.svelte +10 -0
  516. package/src/lib/icons/google-workspace.svelte +18 -0
  517. package/src/lib/icons/icon.d.ts +19 -0
  518. package/src/lib/icons/instagram.svelte +9 -0
  519. package/src/lib/icons/instantly.svelte +10 -0
  520. package/src/lib/icons/linkedin.svelte +9 -0
  521. package/src/lib/icons/mailshake.svelte +10 -0
  522. package/src/lib/icons/microsoft-365.svelte +7 -0
  523. package/src/lib/icons/passcode.svelte +12 -0
  524. package/src/lib/icons/replyio.svelte +10 -0
  525. package/src/lib/icons/smartlead.svelte +19 -0
  526. package/src/lib/icons/smtp.svelte +10 -0
  527. package/src/lib/icons/x-logo.svelte +9 -0
  528. package/src/lib/internal/animations-settled.svelte.ts +119 -0
  529. package/src/lib/internal/arrays.ts +253 -0
  530. package/src/lib/internal/attribute-types.ts +53 -0
  531. package/src/lib/internal/attrs.ts +64 -0
  532. package/src/lib/internal/body-scroll-lock.svelte.ts +330 -0
  533. package/src/lib/internal/create-id.ts +12 -0
  534. package/src/lib/internal/date-time/announcer.ts +74 -0
  535. package/src/lib/internal/date-time/calendar-helpers.svelte.ts +399 -0
  536. package/src/lib/internal/date-time/field/helpers.ts +431 -0
  537. package/src/lib/internal/date-time/field/parts.ts +15 -0
  538. package/src/lib/internal/date-time/field/range-field.svelte.ts +45 -0
  539. package/src/lib/internal/date-time/field/segments.ts +89 -0
  540. package/src/lib/internal/date-time/field/time-helpers.ts +311 -0
  541. package/src/lib/internal/date-time/formatter.ts +86 -0
  542. package/src/lib/internal/date-time/placeholders.ts +131 -0
  543. package/src/lib/internal/date-time/types.ts +121 -0
  544. package/src/lib/internal/date-time/utils.ts +243 -0
  545. package/src/lib/internal/dismissible-layer/index.ts +3 -0
  546. package/src/lib/internal/dismissible-layer/scheduler.ts +48 -0
  547. package/src/lib/internal/dismissible-layer/types.ts +57 -0
  548. package/src/lib/internal/dismissible-layer/use-dismissable-layer.svelte.ts +291 -0
  549. package/src/lib/internal/escape-layer/index.ts +3 -0
  550. package/src/lib/internal/escape-layer/types.ts +34 -0
  551. package/src/lib/internal/escape-layer/use-escape-layer.svelte.ts +91 -0
  552. package/src/lib/internal/floating-layer/components/floating-layer-arrow.svelte +35 -0
  553. package/src/lib/internal/floating-layer/components/floating-layer-content-static.svelte +19 -0
  554. package/src/lib/internal/floating-layer/components/floating-layer-content.svelte +52 -0
  555. package/src/lib/internal/floating-layer/components/floating-layer.svelte +12 -0
  556. package/src/lib/internal/floating-layer/components/index.ts +6 -0
  557. package/src/lib/internal/floating-layer/index.ts +2 -0
  558. package/src/lib/internal/floating-layer/types.ts +126 -0
  559. package/src/lib/internal/floating-layer/use-floating-layer.svelte.ts +471 -0
  560. package/src/lib/internal/focus-scope/focus-scope.svelte.ts +310 -0
  561. package/src/lib/internal/focus-scope/index.ts +4 -0
  562. package/src/lib/internal/focus-scope/types.ts +45 -0
  563. package/src/lib/internal/focus.ts +14 -0
  564. package/src/lib/internal/global-singleton.ts +10 -0
  565. package/src/lib/internal/group-value.svelte.ts +36 -0
  566. package/src/lib/internal/hover-intent-geometry.ts +96 -0
  567. package/src/lib/internal/index.ts +44 -0
  568. package/src/lib/internal/kbd.ts +60 -0
  569. package/src/lib/internal/layer-stack.ts +37 -0
  570. package/src/lib/internal/math.ts +11 -0
  571. package/src/lib/internal/merge-props.ts +7 -0
  572. package/src/lib/internal/native-dialog-controller.svelte.ts +102 -0
  573. package/src/lib/internal/native-popover.svelte.ts +173 -0
  574. package/src/lib/internal/open-cell.svelte.ts +41 -0
  575. package/src/lib/internal/paneforge/index.ts +5 -0
  576. package/src/lib/internal/paneforge/internal/constants.ts +2 -0
  577. package/src/lib/internal/paneforge/internal/helpers.ts +354 -0
  578. package/src/lib/internal/paneforge/internal/types.ts +33 -0
  579. package/src/lib/internal/paneforge/internal/utils/adjust-layout.ts +122 -0
  580. package/src/lib/internal/paneforge/internal/utils/aria.ts +36 -0
  581. package/src/lib/internal/paneforge/internal/utils/compare.ts +15 -0
  582. package/src/lib/internal/paneforge/internal/utils/is.ts +13 -0
  583. package/src/lib/internal/paneforge/internal/utils/resize.ts +31 -0
  584. package/src/lib/internal/paneforge/internal/utils/storage.ts +116 -0
  585. package/src/lib/internal/paneforge/internal/utils/style.ts +104 -0
  586. package/src/lib/internal/paneforge/pane-group.svelte +48 -0
  587. package/src/lib/internal/paneforge/pane-resizer.svelte +40 -0
  588. package/src/lib/internal/paneforge/pane.svelte +60 -0
  589. package/src/lib/internal/paneforge/paneforge.svelte.ts +821 -0
  590. package/src/lib/internal/paneforge/types.ts +179 -0
  591. package/src/lib/internal/popper-layer/index.ts +2 -0
  592. package/src/lib/internal/popper-layer/popper-content.svelte +19 -0
  593. package/src/lib/internal/popper-layer/popper-layer-inner.svelte +122 -0
  594. package/src/lib/internal/popper-layer/popper-layer.svelte +71 -0
  595. package/src/lib/internal/popper-layer/types.ts +65 -0
  596. package/src/lib/internal/portal/index.ts +2 -0
  597. package/src/lib/internal/portal/portal.svelte +61 -0
  598. package/src/lib/internal/prop-resolvers.ts +14 -0
  599. package/src/lib/internal/roving-focus-group.ts +147 -0
  600. package/src/lib/internal/roving-focus-item.svelte.ts +51 -0
  601. package/src/lib/internal/safe-polygon.svelte.ts +239 -0
  602. package/src/lib/internal/shared-state.svelte.ts +39 -0
  603. package/src/lib/internal/state-machine.ts +32 -0
  604. package/src/lib/internal/svelte-resize-observer.svelte.ts +37 -0
  605. package/src/lib/internal/tabbable.ts +398 -0
  606. package/src/lib/internal/table/core.ts +53 -0
  607. package/src/lib/internal/table/filter-fns.ts +10 -0
  608. package/src/lib/internal/table/index.ts +2 -0
  609. package/src/lib/internal/table/sorting-fns.ts +84 -0
  610. package/src/lib/internal/table/table.svelte.ts +330 -0
  611. package/src/lib/internal/table/types.ts +33 -0
  612. package/src/lib/internal/timeout-fn.svelte.ts +36 -0
  613. package/src/lib/internal/tools/box.svelte.ts +153 -0
  614. package/src/lib/internal/tools/index.ts +22 -0
  615. package/src/lib/internal/tools/types.ts +44 -0
  616. package/src/lib/internal/tools/utils/attach-ref.ts +74 -0
  617. package/src/lib/internal/tools/utils/compose-handlers.ts +36 -0
  618. package/src/lib/internal/tools/utils/dom-context.svelte.ts +63 -0
  619. package/src/lib/internal/tools/utils/dom.ts +62 -0
  620. package/src/lib/internal/tools/utils/events.ts +1 -0
  621. package/src/lib/internal/tools/utils/index.ts +5 -0
  622. package/src/lib/internal/tools/utils/strings.ts +28 -0
  623. package/src/lib/internal/typeahead.svelte.ts +48 -0
  624. package/src/lib/internal/types.ts +119 -0
  625. package/src/lib/internal/utils.ts +10 -0
  626. package/src/lib/internal/vaul/browser.ts +8 -0
  627. package/src/lib/internal/vaul/constants.ts +19 -0
  628. package/src/lib/internal/vaul/helpers.ts +39 -0
  629. package/src/lib/internal/vaul/types.ts +142 -0
  630. package/src/lib/internal/vaul/use-drawer-content.svelte.ts +219 -0
  631. package/src/lib/internal/vaul/use-drawer-root.svelte.ts +682 -0
  632. package/src/lib/internal/vaul/use-position-fixed.svelte.ts +142 -0
  633. package/src/lib/internal/vaul/use-prevent-scroll.svelte.ts +267 -0
  634. package/src/lib/internal/vaul/use-snap-points.svelte.ts +246 -0
  635. package/src/lib/time.ts +73 -0
@@ -0,0 +1,253 @@
1
+ /**
2
+ * Checks if two arrays are equal by comparing their values.
3
+ */
4
+ export const arraysAreEqual = <T extends Array<unknown>>(arr1: T, arr2: T): boolean =>
5
+ arr1.length === arr2.length && arr1.every((value, index) => isEqual(value, arr2[index]));
6
+
7
+ /**
8
+ * A utility function that compares two values for equality.
9
+ */
10
+ function isEqual(a: unknown, b: unknown): boolean {
11
+ if (Number.isNaN(a as number) && Number.isNaN(b as number)) return true;
12
+
13
+ if (Array.isArray(a) && Array.isArray(b)) return arraysAreEqual(a as unknown[], b as unknown[]);
14
+
15
+ if (typeof a === 'object' && typeof b === 'object') return isDeepEqual(a, b);
16
+
17
+ return Object.is(a, b);
18
+ }
19
+
20
+ /**
21
+ * A utility function that compares two values for deep equality.
22
+ */
23
+ function isDeepEqual(a: unknown, b: unknown): boolean {
24
+ if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;
25
+
26
+ const aKeys = Object.keys(a);
27
+ const bKeys = Object.keys(b);
28
+
29
+ if (aKeys.length !== bKeys.length) return false;
30
+
31
+ for (const key of aKeys) {
32
+ if (!bKeys.includes(key)) return false;
33
+ if (!isEqual((a as Record<string, unknown>)[key], (b as Record<string, unknown>)[key])) {
34
+ return false;
35
+ }
36
+ }
37
+
38
+ return true;
39
+ }
40
+
41
+ /**
42
+ * Splits an array into chunks of a given size.
43
+ * @param arr The array to split.
44
+ * @param size The size of each chunk.
45
+ * @returns An array of arrays, where each sub-array has `size` elements from the original array.
46
+ * @example ```ts
47
+ * const arr = [1, 2, 3, 4, 5, 6, 7, 8];
48
+ * const chunks = chunk(arr, 3);
49
+ * // chunks = [[1, 2, 3], [4, 5, 6], [7, 8]]
50
+ * ```
51
+ */
52
+ export function chunk<T>(arr: T[], size: number): T[][] {
53
+ if (size <= 0) return [];
54
+
55
+ const result = [];
56
+ for (let i = 0; i < arr.length; i += size) {
57
+ result.push(arr.slice(i, i + size));
58
+ }
59
+ return result;
60
+ }
61
+
62
+ /**
63
+ * Checks if the given index is valid for the given array.
64
+ *
65
+ * @param index - The index to check
66
+ * @param arr - The array to check
67
+ */
68
+
69
+ export const isValidIndex = (index: number, arr: unknown[]) => index >= 0 && index < arr.length;
70
+
71
+ /**
72
+ * Returns the array element after the given index, or undefined for out-of-bounds or empty arrays.
73
+ * @param array the array.
74
+ * @param index the index of the current element.
75
+ * @param loop loop to the beginning of the array if the next index is out of bounds?
76
+ */
77
+ /**
78
+ * Returns the array element after the given index, or undefined for out-of-bounds or empty arrays.
79
+ * For single-element arrays, returns the element if the index is 0.
80
+ * @param array the array.
81
+ * @param index the index of the current element.
82
+ * @param loop loop to the beginning of the array if the next index is out of bounds?
83
+ */
84
+ export function next<T>(array: T[], index: number, loop = true): T | undefined {
85
+ if (array.length === 0 || index < 0 || index >= array.length) return;
86
+ if (array.length === 1 && index === 0) return array[0];
87
+ if (index === array.length - 1) return loop ? array[0] : undefined;
88
+ return array[index + 1];
89
+ }
90
+
91
+ /**
92
+ * Returns the array element prior to the given index, or undefined for out-of-bounds or empty arrays.
93
+ * For single-element arrays, returns the element if the index is 0.
94
+ * @param array the array.
95
+ * @param index the index of the current element.
96
+ * @param loop loop to the end of the array if the previous index is out of bounds?
97
+ */
98
+ export function prev<T>(array: T[], index: number, loop = true): T | undefined {
99
+ if (array.length === 0 || index < 0 || index >= array.length) return;
100
+ if (array.length === 1 && index === 0) return array[0];
101
+ if (index === 0) return loop ? array[array.length - 1] : undefined;
102
+ return array[index - 1];
103
+ }
104
+
105
+ /**
106
+ * Returns the element some number after the given index. If the target index is out of bounds:
107
+ * - If looping is disabled, the first or last element will be returned.
108
+ * - If looping is enabled, it will wrap around the array.
109
+ * Returns undefined for empty arrays or out-of-bounds initial indices.
110
+ * @param array the array.
111
+ * @param index the index of the current element.
112
+ * @param increment the number of elements to move forward (can be negative).
113
+ * @param loop loop around the array if the target index is out of bounds?
114
+ */
115
+ export function forward<T>(array: T[], index: number, increment: number, loop = true): T | undefined {
116
+ if (array.length === 0 || index < 0 || index >= array.length) return;
117
+
118
+ let targetIndex = index + increment;
119
+
120
+ if (loop) {
121
+ // Ensure positive modulus
122
+ targetIndex = ((targetIndex % array.length) + array.length) % array.length;
123
+ } else {
124
+ // Clamp to array bounds when not looping
125
+ targetIndex = Math.max(0, Math.min(targetIndex, array.length - 1));
126
+ }
127
+
128
+ return array[targetIndex];
129
+ }
130
+
131
+ /**
132
+ * Returns the element some number before the given index. If the target index is out of bounds:
133
+ * - If looping is disabled, the first or last element will be returned.
134
+ * - If looping is enabled, it will wrap around the array.
135
+ * Returns undefined for empty arrays or out-of-bounds initial indices.
136
+ * @param array the array.
137
+ * @param index the index of the current element.
138
+ * @param decrement the number of elements to move backward (can be negative).
139
+ * @param loop loop around the array if the target index is out of bounds?
140
+ */
141
+ export function backward<T>(array: T[], index: number, decrement: number, loop = true): T | undefined {
142
+ if (array.length === 0 || index < 0 || index >= array.length) return;
143
+
144
+ let targetIndex = index - decrement;
145
+
146
+ if (loop) {
147
+ // Ensure positive modulus
148
+ targetIndex = ((targetIndex % array.length) + array.length) % array.length;
149
+ } else {
150
+ // Clamp to array bounds when not looping
151
+ targetIndex = Math.max(0, Math.min(targetIndex, array.length - 1));
152
+ }
153
+
154
+ return array[targetIndex];
155
+ }
156
+
157
+ /**
158
+ * Finds the next matching item from a list of values based on a search string.
159
+ *
160
+ * This function handles several special cases in typeahead behavior:
161
+ *
162
+ * 1. Space handling: When a search string ends with a space, it handles it specially:
163
+ * - If there's only one match for the text before the space, it ignores the space
164
+ * - If there are multiple matches and the current match already starts with the search prefix
165
+ * followed by a space, it keeps the current match (doesn't change selection on space)
166
+ * - Only after typing characters beyond the space will it move to a more specific match
167
+ *
168
+ * 2. Repeated character handling: If a search consists of repeated characters (e.g., "aaa"),
169
+ * it treats it as a single character for matching purposes
170
+ *
171
+ * 3. Cycling behavior: The function wraps around the values array starting from the current match
172
+ * to find the next appropriate match, creating a cycling selection behavior
173
+ *
174
+ * @param values - Array of string values to search through (e.g., the text content of menu items)
175
+ * @param search - The current search string typed by the user
176
+ * @param currentMatch - The currently selected/matched item, if any
177
+ * @returns The next matching value that should be selected, or undefined if no match is found
178
+ */
179
+ export function getNextMatch(values: string[], search: string, currentMatch?: string) {
180
+ const lowerSearch = search.toLowerCase();
181
+
182
+ if (lowerSearch.endsWith(' ')) {
183
+ const searchWithoutSpace = lowerSearch.slice(0, -1);
184
+ const matchesWithoutSpace = values.filter((value) => value.toLowerCase().startsWith(searchWithoutSpace));
185
+
186
+ /**
187
+ * If there's only one match for the prefix without space, we don't
188
+ * watch to match with space.
189
+ */
190
+ if (matchesWithoutSpace.length <= 1) {
191
+ return getNextMatch(values, searchWithoutSpace, currentMatch);
192
+ }
193
+
194
+ const currentMatchLowercase = currentMatch?.toLowerCase();
195
+
196
+ /**
197
+ * If the current match already starts with the search prefix and has a space afterward,
198
+ * and the user has only typed up to that space, keep the current match until they
199
+ * disambiguate.
200
+ */
201
+ if (
202
+ currentMatchLowercase &&
203
+ currentMatchLowercase.startsWith(searchWithoutSpace) &&
204
+ currentMatchLowercase.charAt(searchWithoutSpace.length) === ' ' &&
205
+ search.trim() === searchWithoutSpace
206
+ ) {
207
+ return currentMatch;
208
+ }
209
+
210
+ /**
211
+ * With multiple matches, find items that match the full search string with space
212
+ */
213
+ const spacedMatches = values.filter((value) => value.toLowerCase().startsWith(lowerSearch));
214
+
215
+ /**
216
+ * If we found matches with the space, use the first one that's not the current match
217
+ */
218
+ if (spacedMatches.length > 0) {
219
+ const currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
220
+
221
+ // the first match that is not the current one, falling back to current if no other is found.
222
+ const nextMatch = findWrapped(spacedMatches, Math.max(currentMatchIndex, 0), (match) => match !== currentMatch);
223
+ return nextMatch || currentMatch;
224
+ }
225
+ }
226
+
227
+ const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
228
+ const normalizedSearch = isRepeated ? search[0]! : search;
229
+ const normalizedLowerSearch = normalizedSearch.toLowerCase();
230
+
231
+ const currentMatchIndex = currentMatch ? values.indexOf(currentMatch) : -1;
232
+ const excludeCurrentMatch = normalizedSearch.length === 1;
233
+ const nextMatch = findWrapped(
234
+ values,
235
+ Math.max(currentMatchIndex, 0),
236
+ (value) => (!excludeCurrentMatch || value !== currentMatch) && value.toLowerCase().startsWith(normalizedLowerSearch),
237
+ );
238
+
239
+ return nextMatch !== currentMatch ? nextMatch : undefined;
240
+ }
241
+
242
+ /**
243
+ * Circular find: scans `array` from `startIndex` (wrapping past the end) and returns the first element
244
+ * satisfying `predicate`. What every caller of the old rotate-copy (`wrapArray`) actually consumed —
245
+ * same visit order, without allocating the rotation.
246
+ */
247
+ export const findWrapped = <T>(array: T[], startIndex: number, predicate: (item: T) => boolean): T | undefined => {
248
+ for (let step = 0; step < array.length; step++) {
249
+ const item = array[(startIndex + step) % array.length]!;
250
+ if (predicate(item)) return item;
251
+ }
252
+ return undefined;
253
+ };
@@ -0,0 +1,53 @@
1
+ import type {
2
+ HTMLAnchorAttributes,
3
+ HTMLAttributes,
4
+ HTMLButtonAttributes,
5
+ HTMLImgAttributes,
6
+ HTMLInputAttributes,
7
+ HTMLLabelAttributes,
8
+ HTMLLiAttributes,
9
+ HTMLSelectAttributes,
10
+ HTMLTableAttributes,
11
+ HTMLTdAttributes,
12
+ HTMLThAttributes,
13
+ SVGAttributes,
14
+ } from 'svelte/elements';
15
+
16
+ export type BitsDivAttributes = HTMLAttributes<HTMLDivElement>;
17
+ export type BitsSpanAttributes = HTMLAttributes<HTMLSpanElement>;
18
+ export type BitsHeadingAttributes = HTMLAttributes<HTMLHeadingElement>;
19
+ export type BitsUListAttributes = HTMLAttributes<HTMLUListElement>;
20
+ export type BitsElementAttributes = HTMLAttributes<HTMLElement>;
21
+ export type BitsTableSectionAttributes = HTMLAttributes<HTMLTableSectionElement>;
22
+ export type BitsTableRowAttributes = HTMLAttributes<HTMLTableRowElement>;
23
+ export type BitsSVGElementAttributes = SVGAttributes<SVGElement>;
24
+ export type BitsSelectAttributes = HTMLSelectAttributes;
25
+
26
+ /**
27
+ * We override the `id` prop type to not allow it to be `null`. We rely on the
28
+ * `id` heavily in the internals of Bits UI for node references. We also override
29
+ * children to allow for custom children snippet props. We extend `style` to allow
30
+ * for either a `StyleProperties` object or a string of CSS properties.
31
+ */
32
+ type BitsPrimitive<T> = Omit<T, 'style' | 'id' | 'children'> & { id?: string };
33
+
34
+ export type BitsPrimitiveButtonAttributes = BitsPrimitive<HTMLButtonAttributes>;
35
+ export type BitsPrimitiveDivAttributes = BitsPrimitive<BitsDivAttributes>;
36
+ export type BitsPrimitiveInputAttributes = BitsPrimitive<HTMLInputAttributes>;
37
+ export type BitsPrimitiveSpanAttributes = BitsPrimitive<BitsSpanAttributes>;
38
+ export type BitsPrimitiveImgAttributes = BitsPrimitive<HTMLImgAttributes>;
39
+ export type BitsPrimitiveHeadingAttributes = BitsPrimitive<BitsHeadingAttributes>;
40
+ export type BitsPrimitiveLabelAttributes = BitsPrimitive<HTMLLabelAttributes>;
41
+ export type BitsPrimitiveSVGAttributes = BitsPrimitive<BitsSVGElementAttributes>;
42
+ export type BitsPrimitiveAnchorAttributes = BitsPrimitive<HTMLAnchorAttributes>;
43
+ export type BitsPrimitiveLiAttributes = BitsPrimitive<HTMLLiAttributes>;
44
+ export type BitsPrimitiveElementAttributes = BitsPrimitive<BitsElementAttributes>;
45
+ export type BitsPrimitiveUListAttributes = BitsPrimitive<BitsUListAttributes>;
46
+ export type BitsPrimitiveTdAttributes = BitsPrimitive<HTMLTdAttributes>;
47
+ export type BitsPrimitiveThAttributes = BitsPrimitive<HTMLThAttributes>;
48
+ export type BitsPrimitiveTableAttributes = BitsPrimitive<HTMLTableAttributes>;
49
+ export type BitsPrimitiveTbodyAttributes = BitsPrimitive<BitsTableSectionAttributes>;
50
+ export type BitsPrimitiveTrAttributes = BitsPrimitive<BitsTableRowAttributes>;
51
+ export type BitsPrimitiveTheadAttributes = BitsPrimitive<BitsTableSectionAttributes>;
52
+ export type BitsPrimitiveHeaderAttributes = BitsPrimitive<BitsElementAttributes>;
53
+ export type BitsPrimitiveSelectAttributes = BitsPrimitive<BitsSelectAttributes>;
@@ -0,0 +1,64 @@
1
+ export const boolToStr = (condition: boolean): 'true' | 'false' => condition ? 'true' : 'false';
2
+
3
+ export const boolToStrTrueOrUndef = (condition: boolean): 'true' | undefined => condition ? 'true' : undefined;
4
+
5
+ export const boolToEmptyStrOrUndef = (condition: boolean): '' | undefined => condition ? '' : undefined;
6
+
7
+ export const boolToTrueOrUndef = (condition: boolean): true | undefined => condition ? true : undefined;
8
+
9
+ export const getDataOpenClosed = (condition: boolean): 'open' | 'closed' => condition ? 'open' : 'closed';
10
+
11
+ export type TransitionState = 'starting' | 'ending' | 'idle' | undefined;
12
+
13
+ export const getAriaChecked = (checked: boolean, indeterminate: boolean): 'true' | 'false' | 'mixed' =>
14
+ indeterminate ? 'mixed' : checked ? 'true' : 'false';
15
+
16
+ export type BitsAttrsConfig<T extends readonly string[]> = {
17
+ component: string;
18
+ parts: T;
19
+ getVariant?: () => string | null;
20
+ };
21
+
22
+ export type CreateBitsAttrsReturn<T extends readonly string[]> = {
23
+ [K in T[number]]: string;
24
+ } & {
25
+ selector: (part: T[number]) => string;
26
+ getAttr: (part: T[number], variant?: string) => string;
27
+ };
28
+
29
+ export class BitsAttrs<T extends readonly string[]> {
30
+ readonly #variant: string | null;
31
+ readonly #prefix: string;
32
+ attrs: Record<T[number], string>;
33
+
34
+ constructor(config: BitsAttrsConfig<T>) {
35
+ this.#variant = config.getVariant ? config.getVariant() : null;
36
+ this.#prefix = this.#variant ? `data-${this.#variant}-` : `data-${config.component}-`;
37
+
38
+ this.getAttr = this.getAttr.bind(this);
39
+ this.selector = this.selector.bind(this);
40
+
41
+ this.attrs = Object.fromEntries(config.parts.map((part) => [part, this.getAttr(part)])) as Record<T[number], string>;
42
+ }
43
+
44
+ getAttr(part: T[number], variantOverride?: string): string {
45
+ if (variantOverride) return `data-${variantOverride}-${part}`;
46
+ return `${this.#prefix}${part}`;
47
+ }
48
+
49
+ selector(part: T[number], variantOverride?: string): string {
50
+ return `[${this.getAttr(part, variantOverride)}]`;
51
+ }
52
+ }
53
+
54
+ export function createBitsAttrs<const T extends readonly string[]>(
55
+ config: Omit<BitsAttrsConfig<T>, 'parts'> & { parts: T },
56
+ ): CreateBitsAttrsReturn<T> {
57
+ const bitsAttrs = new BitsAttrs(config);
58
+
59
+ return {
60
+ ...bitsAttrs.attrs,
61
+ selector: bitsAttrs.selector,
62
+ getAttr: bitsAttrs.getAttr,
63
+ } as CreateBitsAttrsReturn<T>;
64
+ }
@@ -0,0 +1,330 @@
1
+ import { SvelteMap } from 'svelte/reactivity';
2
+ import { type Attachment, createAttachmentKey } from 'svelte/attachments';
3
+ import { type Getter, type ReadableBox, boxWith } from './tools/index.js';
4
+ import type { Fn } from './types.js';
5
+ import { isIOS } from './tools/utils/dom.js';
6
+ import { BROWSER } from 'esm-env';
7
+ import { SharedState } from './shared-state.svelte.js';
8
+ import { on } from 'svelte/events';
9
+ import { getAbortSignal, onMount, tick, untrack } from 'svelte';
10
+
11
+ export interface ScrollBodyOption {
12
+ padding?: boolean | number;
13
+ margin?: boolean | number;
14
+ }
15
+ /** A map of lock instances to their `locked` state. */
16
+ const lockMap = new SvelteMap<BodyScrollLock, boolean>();
17
+
18
+ let initialBodyStyle: string | null = $state<string | null>(null);
19
+ let stopTouchMoveListener: Fn | null = null;
20
+ let cleanupTimeoutId: number | null = null;
21
+ let isInCleanupTransition = false;
22
+
23
+ function cleanupTouchMoveListener() {
24
+ stopTouchMoveListener?.();
25
+ stopTouchMoveListener = null;
26
+ }
27
+
28
+ const anyLocked = boxWith(() => {
29
+ for (const value of lockMap.values()) {
30
+ if (value) return true;
31
+ }
32
+ return false;
33
+ });
34
+
35
+ /**
36
+ * We track the time we scheduled the cleanup to prevent race conditions
37
+ * when multiple locks are created/destroyed in the same tick, ensuring
38
+ * only the last one to schedule the cleanup will run.
39
+ *
40
+ * reference: https://github.com/huntabyte/bits-ui/issues/1639
41
+ */
42
+ let cleanupScheduledAt: number | null = null;
43
+
44
+ const bodyLockStackCount = new SharedState(() => {
45
+ const doc = BROWSER && typeof document !== 'undefined' ? document : null;
46
+ const win = doc?.defaultView ?? (BROWSER && typeof window !== 'undefined' ? window : null);
47
+
48
+ function getDOM() {
49
+ if (!doc?.body || !doc.documentElement || !win) return null;
50
+ return {
51
+ body: doc.body,
52
+ documentElement: doc.documentElement,
53
+ doc,
54
+ win,
55
+ };
56
+ }
57
+
58
+ function resetBodyStyle() {
59
+ const dom = getDOM();
60
+ if (!dom) {
61
+ initialBodyStyle = null;
62
+ return;
63
+ }
64
+ dom.body.setAttribute('style', initialBodyStyle ?? '');
65
+ if (isIOS) {
66
+ cleanupTouchMoveListener();
67
+ }
68
+ // reset initialBodyStyle so next locker captures the correct styles
69
+ initialBodyStyle = null;
70
+ }
71
+
72
+ function cancelPendingCleanup() {
73
+ if (cleanupTimeoutId === null) return;
74
+ win?.clearTimeout(cleanupTimeoutId);
75
+ cleanupTimeoutId = null;
76
+ }
77
+
78
+ function scheduleCleanupIfNoNewLocks(delay: number | null, callback: () => void) {
79
+ cancelPendingCleanup();
80
+ if (!win) {
81
+ isInCleanupTransition = false;
82
+ return;
83
+ }
84
+ isInCleanupTransition = true;
85
+
86
+ cleanupScheduledAt = Date.now();
87
+ const currentCleanupId = cleanupScheduledAt;
88
+
89
+ /**
90
+ * We schedule the cleanup to run after a delay to allow new locks to register
91
+ * that might have been added in the same tick as the current cleanup.
92
+ *
93
+ * If a new lock is added in the same tick, the cleanup will be cancelled and
94
+ * a new cleanup will be scheduled.
95
+ *
96
+ * This is to prevent the cleanup from running too early and resetting the body
97
+ * style before the new lock has had a chance to apply its styles.
98
+ */
99
+ const cleanupFn = () => {
100
+ cleanupTimeoutId = null;
101
+
102
+ // check if this cleanup is still valid (no newer cleanups scheduled)
103
+ if (cleanupScheduledAt !== currentCleanupId) return;
104
+
105
+ // ensure no new locks were added during the delay
106
+ if (!isAnyLocked(lockMap)) {
107
+ isInCleanupTransition = false;
108
+ callback();
109
+ } else {
110
+ isInCleanupTransition = false;
111
+ }
112
+ };
113
+
114
+ const actualDelay = delay === null ? 24 : delay;
115
+ cleanupTimeoutId = win.setTimeout(cleanupFn, actualDelay);
116
+ }
117
+
118
+ function ensureInitialStyleCaptured() {
119
+ const dom = getDOM();
120
+ if (!dom) return;
121
+ // only capture initial style once, when no locks exist and no cleanup is in progress
122
+ if (initialBodyStyle === null && lockMap.size === 0 && !isInCleanupTransition) {
123
+ initialBodyStyle = dom.body.getAttribute('style');
124
+ }
125
+ }
126
+
127
+ $effect(() => {
128
+ anyLocked.current;
129
+ const signal = getAbortSignal();
130
+ untrack(() => {
131
+ if (!anyLocked.current) return;
132
+ const dom = getDOM();
133
+ if (!dom) return;
134
+
135
+ // ensure we've captured the initial style before applying any lock styles
136
+ ensureInitialStyleCaptured();
137
+
138
+ // if we're applying lock styles, we're no longer in a cleanup transition
139
+ isInCleanupTransition = false;
140
+
141
+ const htmlStyle = dom.win.getComputedStyle(dom.documentElement);
142
+ const bodyStyle = dom.win.getComputedStyle(dom.body);
143
+
144
+ // ui.css sets `scrollbar-gutter: stable` on html, so the measurement branch below is
145
+ // the fallback for engines without support (Safari <18.2).
146
+ const hasStableGutter = htmlStyle.scrollbarGutter?.includes('stable') || bodyStyle.scrollbarGutter?.includes('stable');
147
+
148
+ // TODO: account for RTL direction, etc.
149
+ const verticalScrollbarWidth = dom.win.innerWidth - dom.documentElement.clientWidth;
150
+ const paddingRight = Number.parseInt(bodyStyle.paddingRight ?? '0', 10);
151
+
152
+ const config = {
153
+ padding: paddingRight + verticalScrollbarWidth,
154
+ margin: Number.parseInt(bodyStyle.marginRight ?? '0', 10),
155
+ };
156
+
157
+ // only add padding compensation if stable gutter isn't handling it
158
+ if (verticalScrollbarWidth > 0 && !hasStableGutter) {
159
+ dom.body.style.paddingRight = `${config.padding}px`;
160
+ dom.body.style.marginRight = `${config.margin}px`;
161
+ }
162
+ dom.body.style.overflow = 'hidden';
163
+
164
+ if (isIOS && !stopTouchMoveListener) {
165
+ // IOS devices are special and require a touchmove listener to prevent scrolling.
166
+ // Guard against duplicate listeners when concurrent locks mutate lockMap.
167
+ stopTouchMoveListener = on(
168
+ dom.doc,
169
+ 'touchmove',
170
+ (e) => {
171
+ if (e.target !== dom.documentElement) return;
172
+
173
+ if (e.touches.length > 1) return;
174
+ e.preventDefault();
175
+ },
176
+ { passive: false },
177
+ );
178
+ }
179
+
180
+ /**
181
+ * We ensure pointer-events: none is applied _after_ DOM updates, so that any focus/
182
+ * interaction changes from opening overlays/menus complete _before_ we block pointer
183
+ * events.
184
+ *
185
+ * this avoids race conditions where pointer-events could be set too early and break
186
+ * focus/interaction.
187
+ */
188
+ tick().then(() => {
189
+ const latestDOM = getDOM();
190
+ if (signal.aborted || !latestDOM || !isAnyLocked(lockMap)) return;
191
+ latestDOM.body.style.pointerEvents = 'none';
192
+ latestDOM.body.style.overflow = 'hidden';
193
+ });
194
+ });
195
+ });
196
+
197
+ $effect(() => {
198
+ return () => {
199
+ cleanupTouchMoveListener();
200
+ };
201
+ });
202
+
203
+ return {
204
+ get lockMap() {
205
+ return lockMap;
206
+ },
207
+ resetBodyStyle,
208
+ scheduleCleanupIfNoNewLocks,
209
+ cancelPendingCleanup,
210
+ ensureInitialStyleCaptured,
211
+ };
212
+ });
213
+
214
+ export class BodyScrollLock {
215
+ readonly #initialState: boolean | undefined;
216
+ readonly #restoreScrollDelay: Getter<number | null> = () => null;
217
+ readonly #countState: ReturnType<typeof bodyLockStackCount.get>;
218
+ readonly locked: ReadableBox<boolean> | undefined;
219
+ #released = false;
220
+
221
+ constructor(initialState?: boolean | undefined, restoreScrollDelay: Getter<number | null> = () => null) {
222
+ this.#initialState = initialState;
223
+ this.#restoreScrollDelay = restoreScrollDelay;
224
+ this.#countState = bodyLockStackCount.get();
225
+
226
+ if (!this.#countState) return;
227
+
228
+ /**
229
+ * Since a new lock is being created, we cancel any pending cleanup to
230
+ * prevent the cleanup from running too early and resetting the body style
231
+ * before the new lock has had a chance to apply its styles.
232
+ *
233
+ * reference: https://github.com/huntabyte/bits-ui/issues/1639
234
+ */
235
+ this.#countState.cancelPendingCleanup();
236
+
237
+ // capture initial style before this lock is registered
238
+ this.#countState.ensureInitialStyleCaptured();
239
+
240
+ this.#countState.lockMap.set(this, this.#initialState ?? false);
241
+
242
+ this.locked = boxWith(
243
+ () => this.#countState.lockMap.get(this) ?? false,
244
+ (v) => this.#countState.lockMap.set(this, v),
245
+ );
246
+
247
+ // Component-form owners (a lock constructed during init) release on unmount; effect owners
248
+ // release through their cleanup, for which this is a no-op.
249
+ onMount(() => () => this.release());
250
+ }
251
+
252
+ /**
253
+ * Unregisters the lock; the owner returns this as its effect cleanup. Registration is
254
+ * synchronous in the constructor, so the release must not depend on a child effect having
255
+ * run: an owner effect that re-runs before its children execute (an attachment re-run in
256
+ * the same flush) would otherwise never unregister the lock, and the body stays locked.
257
+ */
258
+ release() {
259
+ if (this.#released || !this.#countState) return;
260
+ this.#released = true;
261
+ this.#countState.lockMap.delete(this);
262
+
263
+ // if not the last lock, we don't need to do anything
264
+ if (isAnyLocked(this.#countState.lockMap)) return;
265
+
266
+ /**
267
+ * We schedule the cleanup to run after a delay to handle same-tick
268
+ * destroy/create scenarios.
269
+ *
270
+ * reference: https://github.com/huntabyte/bits-ui/issues/1639
271
+ */
272
+ this.#countState.scheduleCleanupIfNoNewLocks(this.#restoreScrollDelay(), () => {
273
+ this.#countState.resetBodyStyle();
274
+ });
275
+ }
276
+ }
277
+
278
+ function isAnyLocked(map: Map<BodyScrollLock, boolean>) {
279
+ for (const [_, value] of map) {
280
+ if (value) return true;
281
+ }
282
+ return false;
283
+ }
284
+
285
+ /** Surface props shared by every scroll-locking overlay (moved from the retired internal/scroll-lock). */
286
+ export type ScrollLockProps = {
287
+ /**
288
+ * Whether to prevent body scrolling when the content is open.
289
+ *
290
+ * @default true
291
+ */
292
+ preventScroll?: boolean;
293
+
294
+ /**
295
+ * The delay in milliseconds before the scrollbar is restored after closing the
296
+ * dialog. This is only applicable when using the `child` snippet for custom
297
+ * transitions and `preventScroll` is `true`. You should set this to a value
298
+ * greater than the transition duration to prevent content from shifting during
299
+ * the transition.
300
+ *
301
+ * @default null
302
+ */
303
+ restoreScrollDelay?: number | null;
304
+ };
305
+
306
+ /**
307
+ * Attachment form of the body lock — replaces the renderless `<ScrollLock>` component.
308
+ * Locks while the host element is connected AND `enabled()` is true; `enabled` is a tracked
309
+ * read, so surfaces whose element persists across open/close re-run the attachment as their
310
+ * open state flips, and the lock is released through the attachment's own cleanup (see
311
+ * `BodyScrollLock.release`).
312
+ *
313
+ * Spreadable (`{...lock}` / a `mergeProps` argument); create it ONCE in the script so the
314
+ * attachment's identity is stable across renders.
315
+ */
316
+ export function scrollLockAttachment(opts: {
317
+ enabled?: Getter<boolean>;
318
+ restoreScrollDelay?: Getter<number | null>;
319
+ } = {}): Record<symbol, Attachment> {
320
+ const { enabled = () => true, restoreScrollDelay = () => null } = opts;
321
+ return {
322
+ [createAttachmentKey()]: () => {
323
+ if (!enabled()) return;
324
+ // untracked: registering in the shared lockMap is a deliberate write from a tracked
325
+ // context (the attach effect).
326
+ const lock = untrack(() => new BodyScrollLock(true, restoreScrollDelay));
327
+ return () => lock.release();
328
+ },
329
+ };
330
+ }