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.
- package/LICENSE +21 -0
- package/README.md +42 -0
- package/package.json +369 -0
- package/src/lib/VENDORED.md +109 -0
- package/src/lib/assets/ui.css +733 -0
- package/src/lib/blocks/Appearance.svelte +104 -0
- package/src/lib/blocks/BoundaryFailed.svelte +33 -0
- package/src/lib/blocks/ErrorPage.svelte +65 -0
- package/src/lib/blocks/Footer.svelte +71 -0
- package/src/lib/blocks/Header.svelte +67 -0
- package/src/lib/blocks/Heading.svelte +86 -0
- package/src/lib/blocks/MobileNav.svelte +169 -0
- package/src/lib/blocks/PhoneInput.svelte +68 -0
- package/src/lib/blocks/Section.svelte +34 -0
- package/src/lib/blocks/alert-modal/AlertModal.svelte +83 -0
- package/src/lib/blocks/alert-modal/alert-modal.svelte.ts +81 -0
- package/src/lib/blocks/alert-modal/index.ts +2 -0
- package/src/lib/blocks/calendar.svelte +155 -0
- package/src/lib/blocks/copy-button/copy-button.svelte +43 -0
- package/src/lib/blocks/copy-button/copy.svelte.ts +52 -0
- package/src/lib/blocks/copy-button/index.ts +2 -0
- package/src/lib/blocks/date-picker/date-picker-with-presets.svelte +109 -0
- package/src/lib/blocks/date-picker/date-picker.svelte +91 -0
- package/src/lib/blocks/date-picker/index.ts +13 -0
- package/src/lib/blocks/date-picker/range-date-picker.svelte +128 -0
- package/src/lib/blocks/index.ts +12 -0
- package/src/lib/blocks/mockups/Browser.svelte +22 -0
- package/src/lib/blocks/mockups/Phone.svelte +44 -0
- package/src/lib/blocks/mockups/index.ts +2 -0
- package/src/lib/blocks/tab-nav/index.ts +1 -0
- package/src/lib/blocks/tab-nav/tab-nav.svelte +46 -0
- package/src/lib/blocks/time-picker/index.ts +16 -0
- package/src/lib/blocks/time-picker/time-input.svelte +118 -0
- package/src/lib/blocks/time-picker/time-picker.svelte +93 -0
- package/src/lib/blocks/time-picker/time-range-input.svelte +34 -0
- package/src/lib/blocks/time-picker/time-range-picker.svelte +180 -0
- package/src/lib/blocks/time-picker/time-slots.ts +61 -0
- package/src/lib/blocks/user-avatar/UserAvatar.svelte +36 -0
- package/src/lib/blocks/user-avatar/index.ts +1 -0
- package/src/lib/blocks/verification-code-field/VerificationCodeField.svelte +57 -0
- package/src/lib/blocks/verification-code-field/index.ts +1 -0
- package/src/lib/components/accordion/accordion.svelte.ts +43 -0
- package/src/lib/components/accordion/components/accordion-content.svelte +17 -0
- package/src/lib/components/accordion/components/accordion-item.svelte +58 -0
- package/src/lib/components/accordion/components/accordion-trigger.svelte +38 -0
- package/src/lib/components/accordion/components/accordion.svelte +24 -0
- package/src/lib/components/accordion/index.ts +11 -0
- package/src/lib/components/accordion/types.ts +19 -0
- package/src/lib/components/alert/alert-action.svelte +11 -0
- package/src/lib/components/alert/alert-description.svelte +18 -0
- package/src/lib/components/alert/alert-title.svelte +18 -0
- package/src/lib/components/alert/alert.svelte +37 -0
- package/src/lib/components/alert/index.ts +17 -0
- package/src/lib/components/avatar/avatar.svelte.ts +154 -0
- package/src/lib/components/avatar/components/avatar-fallback.svelte +38 -0
- package/src/lib/components/avatar/components/avatar-image.svelte +47 -0
- package/src/lib/components/avatar/components/avatar.svelte +57 -0
- package/src/lib/components/avatar/index.ts +9 -0
- package/src/lib/components/avatar/types.ts +46 -0
- package/src/lib/components/badge/badge.svelte +49 -0
- package/src/lib/components/badge/index.ts +1 -0
- package/src/lib/components/breadcrumb/breadcrumb-ellipsis.svelte +23 -0
- package/src/lib/components/breadcrumb/breadcrumb-item.svelte +11 -0
- package/src/lib/components/breadcrumb/breadcrumb-link.svelte +32 -0
- package/src/lib/components/breadcrumb/breadcrumb-list.svelte +15 -0
- package/src/lib/components/breadcrumb/breadcrumb-page.svelte +18 -0
- package/src/lib/components/breadcrumb/breadcrumb-separator.svelte +22 -0
- package/src/lib/components/breadcrumb/breadcrumb.svelte +10 -0
- package/src/lib/components/breadcrumb/index.ts +25 -0
- package/src/lib/components/button/button.svelte +55 -0
- package/src/lib/components/button/index.ts +12 -0
- package/src/lib/components/button/variants.ts +51 -0
- package/src/lib/components/calendar/calendar.svelte.ts +1081 -0
- package/src/lib/components/calendar/components/calendar-cell.svelte +34 -0
- package/src/lib/components/calendar/components/calendar-day.svelte +36 -0
- package/src/lib/components/calendar/components/calendar-grid-body.svelte +29 -0
- package/src/lib/components/calendar/components/calendar-grid-head.svelte +29 -0
- package/src/lib/components/calendar/components/calendar-grid-row.svelte +29 -0
- package/src/lib/components/calendar/components/calendar-grid.svelte +29 -0
- package/src/lib/components/calendar/components/calendar-head-cell.svelte +29 -0
- package/src/lib/components/calendar/components/calendar-header.svelte +29 -0
- package/src/lib/components/calendar/components/calendar-heading.svelte +33 -0
- package/src/lib/components/calendar/components/calendar-month-select.svelte +50 -0
- package/src/lib/components/calendar/components/calendar-next-button.svelte +37 -0
- package/src/lib/components/calendar/components/calendar-prev-button.svelte +37 -0
- package/src/lib/components/calendar/components/calendar-year-select.svelte +50 -0
- package/src/lib/components/calendar/components/calendar.svelte +123 -0
- package/src/lib/components/calendar/exports.ts +31 -0
- package/src/lib/components/calendar/index.ts +2 -0
- package/src/lib/components/calendar/types.ts +417 -0
- package/src/lib/components/card/card-action.svelte +15 -0
- package/src/lib/components/card/card-content.svelte +11 -0
- package/src/lib/components/card/card-description.svelte +11 -0
- package/src/lib/components/card/card-footer.svelte +11 -0
- package/src/lib/components/card/card-header.svelte +18 -0
- package/src/lib/components/card/card-title.svelte +11 -0
- package/src/lib/components/card/card.svelte +15 -0
- package/src/lib/components/card/index.ts +25 -0
- package/src/lib/components/carousel/carousel-arrow.svelte +42 -0
- package/src/lib/components/carousel/carousel-content.svelte +25 -0
- package/src/lib/components/carousel/carousel-dots.svelte +21 -0
- package/src/lib/components/carousel/carousel-item.svelte +21 -0
- package/src/lib/components/carousel/carousel-next.svelte +9 -0
- package/src/lib/components/carousel/carousel-previous.svelte +9 -0
- package/src/lib/components/carousel/carousel.svelte +245 -0
- package/src/lib/components/carousel/carouselState.svelte.ts +30 -0
- package/src/lib/components/carousel/index.ts +24 -0
- package/src/lib/components/chart/chart-container.svelte +52 -0
- package/src/lib/components/chart/chart-style.svelte +29 -0
- package/src/lib/components/chart/chart-tooltip.svelte +163 -0
- package/src/lib/components/chart/chart-utils.ts +50 -0
- package/src/lib/components/chart/index.ts +6 -0
- package/src/lib/components/checkbox/checkbox.svelte.ts +199 -0
- package/src/lib/components/checkbox/components/checkbox-group-label.svelte +29 -0
- package/src/lib/components/checkbox/components/checkbox-group.svelte +48 -0
- package/src/lib/components/checkbox/components/checkbox.svelte +85 -0
- package/src/lib/components/checkbox/index.ts +9 -0
- package/src/lib/components/checkbox/types.ts +131 -0
- package/src/lib/components/checkbox-native/checkbox.svelte +96 -0
- package/src/lib/components/checkbox-native/index.ts +8 -0
- package/src/lib/components/collapsible/components/collapsible-content.svelte +16 -0
- package/src/lib/components/collapsible/components/collapsible-trigger.svelte +14 -0
- package/src/lib/components/collapsible/components/collapsible.svelte +68 -0
- package/src/lib/components/collapsible/index.ts +9 -0
- package/src/lib/components/collapsible/types.ts +25 -0
- package/src/lib/components/combobox/components/combobox-arrow.svelte +8 -0
- package/src/lib/components/combobox/components/combobox-input.svelte +46 -0
- package/src/lib/components/combobox/components/combobox-trigger.svelte +44 -0
- package/src/lib/components/combobox/components/combobox.svelte +83 -0
- package/src/lib/components/combobox/index.ts +30 -0
- package/src/lib/components/combobox/select/components/select-content-static.svelte +56 -0
- package/src/lib/components/combobox/select/components/select-content.svelte +95 -0
- package/src/lib/components/combobox/select/components/select-group-heading.svelte +51 -0
- package/src/lib/components/combobox/select/components/select-group.svelte +51 -0
- package/src/lib/components/combobox/select/components/select-hidden-input.svelte +16 -0
- package/src/lib/components/combobox/select/components/select-item.svelte +86 -0
- package/src/lib/components/combobox/select/components/select-scroll-down-button.svelte +41 -0
- package/src/lib/components/combobox/select/components/select-scroll-up-button.svelte +34 -0
- package/src/lib/components/combobox/select/components/select-trigger.svelte +32 -0
- package/src/lib/components/combobox/select/components/select-value.svelte +40 -0
- package/src/lib/components/combobox/select/components/select-viewport.svelte +29 -0
- package/src/lib/components/combobox/select/components/select.svelte +92 -0
- package/src/lib/components/combobox/select/select.svelte.ts +1596 -0
- package/src/lib/components/combobox/select/types.ts +291 -0
- package/src/lib/components/combobox/types.ts +77 -0
- package/src/lib/components/command/command-dialog.svelte +42 -0
- package/src/lib/components/command/command.svelte.ts +1506 -0
- package/src/lib/components/command/components/_command-label.svelte +31 -0
- package/src/lib/components/command/components/command-empty.svelte +34 -0
- package/src/lib/components/command/components/command-group-heading.svelte +29 -0
- package/src/lib/components/command/components/command-group-items.svelte +31 -0
- package/src/lib/components/command/components/command-group.svelte +76 -0
- package/src/lib/components/command/components/command-input.svelte +55 -0
- package/src/lib/components/command/components/command-item.svelte +61 -0
- package/src/lib/components/command/components/command-link-item.svelte +61 -0
- package/src/lib/components/command/components/command-list.svelte +41 -0
- package/src/lib/components/command/components/command-loading.svelte +30 -0
- package/src/lib/components/command/components/command-separator.svelte +34 -0
- package/src/lib/components/command/components/command-viewport.svelte +29 -0
- package/src/lib/components/command/components/command.svelte +143 -0
- package/src/lib/components/command/compute-command-score.ts +207 -0
- package/src/lib/components/command/index.ts +29 -0
- package/src/lib/components/command/types.ts +222 -0
- package/src/lib/components/command/utils.ts +30 -0
- package/src/lib/components/context-menu/components/context-menu-content-static.svelte +22 -0
- package/src/lib/components/context-menu/components/context-menu-content.svelte +22 -0
- package/src/lib/components/context-menu/components/context-menu-trigger.svelte +46 -0
- package/src/lib/components/context-menu/components/context-menu.svelte +8 -0
- package/src/lib/components/context-menu/index.ts +39 -0
- package/src/lib/components/context-menu/types.ts +56 -0
- package/src/lib/components/data-table/column-helpers.ts +97 -0
- package/src/lib/components/data-table/data-table-checkbox.svelte +25 -0
- package/src/lib/components/data-table/data-table-sort-button.svelte +16 -0
- package/src/lib/components/data-table/flex-render.svelte +42 -0
- package/src/lib/components/data-table/index.ts +29 -0
- package/src/lib/components/data-table/render-helpers.ts +105 -0
- package/src/lib/components/data-table/table-cell.svelte +9 -0
- package/src/lib/components/data-table/table-column-header.svelte +51 -0
- package/src/lib/components/data-table/table-faceted-filter.svelte +109 -0
- package/src/lib/components/data-table/table-pagination.svelte +54 -0
- package/src/lib/components/data-table/table-priority-cell.svelte +22 -0
- package/src/lib/components/data-table/table-row-actions.svelte +29 -0
- package/src/lib/components/data-table/table-status-cell.svelte +34 -0
- package/src/lib/components/data-table/table-title-cell.svelte +24 -0
- package/src/lib/components/data-table/table-toolbar.svelte +55 -0
- package/src/lib/components/data-table/table-view-options.svelte +25 -0
- package/src/lib/components/date-field/components/date-field-hidden-input.svelte +9 -0
- package/src/lib/components/date-field/components/date-field-input.svelte +33 -0
- package/src/lib/components/date-field/components/date-field-label.svelte +29 -0
- package/src/lib/components/date-field/components/date-field-segment.svelte +29 -0
- package/src/lib/components/date-field/components/date-field.svelte +106 -0
- package/src/lib/components/date-field/date-field.svelte.ts +1474 -0
- package/src/lib/components/date-field/index.ts +11 -0
- package/src/lib/components/date-field/types.ts +165 -0
- package/src/lib/components/date-range-field/components/date-range-field-input.svelte +36 -0
- package/src/lib/components/date-range-field/components/date-range-field-label.svelte +29 -0
- package/src/lib/components/date-range-field/components/date-range-field.svelte +106 -0
- package/src/lib/components/date-range-field/date-range-field.svelte.ts +212 -0
- package/src/lib/components/date-range-field/index.ts +11 -0
- package/src/lib/components/date-range-field/types.ts +171 -0
- package/src/lib/components/dialog/components/dialog-close.svelte +31 -0
- package/src/lib/components/dialog/components/dialog-content-headless.svelte +104 -0
- package/src/lib/components/dialog/components/dialog-content.svelte +69 -0
- package/src/lib/components/dialog/components/dialog-description.svelte +29 -0
- package/src/lib/components/dialog/components/dialog-overlay.svelte +31 -0
- package/src/lib/components/dialog/components/dialog-title.svelte +30 -0
- package/src/lib/components/dialog/components/dialog-trigger.svelte +30 -0
- package/src/lib/components/dialog/components/dialog.svelte +21 -0
- package/src/lib/components/dialog/components/modal-surface.svelte +131 -0
- package/src/lib/components/dialog/dialog.svelte.ts +371 -0
- package/src/lib/components/dialog/index.ts +19 -0
- package/src/lib/components/dialog/types.ts +105 -0
- package/src/lib/components/drawer/drawer-close.svelte +7 -0
- package/src/lib/components/drawer/drawer-content.svelte +91 -0
- package/src/lib/components/drawer/drawer-description.svelte +8 -0
- package/src/lib/components/drawer/drawer-footer.svelte +11 -0
- package/src/lib/components/drawer/drawer-header.svelte +11 -0
- package/src/lib/components/drawer/drawer-nested.svelte +44 -0
- package/src/lib/components/drawer/drawer-overlay.svelte +60 -0
- package/src/lib/components/drawer/drawer-portal.svelte +10 -0
- package/src/lib/components/drawer/drawer-title.svelte +8 -0
- package/src/lib/components/drawer/drawer-trigger.svelte +7 -0
- package/src/lib/components/drawer/drawer.svelte +290 -0
- package/src/lib/components/drawer/index.ts +37 -0
- package/src/lib/components/dropdown-menu/components/dropdown-menu-content-static.svelte +22 -0
- package/src/lib/components/dropdown-menu/components/dropdown-menu-content.svelte +22 -0
- package/src/lib/components/dropdown-menu/index.ts +39 -0
- package/src/lib/components/dropdown-menu/types.ts +41 -0
- package/src/lib/components/empty/empty-content.svelte +15 -0
- package/src/lib/components/empty/empty-description.svelte +15 -0
- package/src/lib/components/empty/empty-header.svelte +15 -0
- package/src/lib/components/empty/empty-media.svelte +21 -0
- package/src/lib/components/empty/empty-title.svelte +11 -0
- package/src/lib/components/empty/empty.svelte +18 -0
- package/src/lib/components/empty/index.ts +22 -0
- package/src/lib/components/empty/variants.ts +16 -0
- package/src/lib/components/field/field-content.svelte +14 -0
- package/src/lib/components/field/field-description.svelte +19 -0
- package/src/lib/components/field/field-error.svelte +47 -0
- package/src/lib/components/field/field-group.svelte +17 -0
- package/src/lib/components/field/field-label.svelte +18 -0
- package/src/lib/components/field/field-legend.svelte +23 -0
- package/src/lib/components/field/field-separator.svelte +32 -0
- package/src/lib/components/field/field-set.svelte +14 -0
- package/src/lib/components/field/field-title.svelte +14 -0
- package/src/lib/components/field/field.svelte +36 -0
- package/src/lib/components/field/index.ts +32 -0
- package/src/lib/components/field/variants.ts +19 -0
- package/src/lib/components/input/file-input.svelte +26 -0
- package/src/lib/components/input/index.ts +12 -0
- package/src/lib/components/input/input.svelte +24 -0
- package/src/lib/components/input/variants.ts +28 -0
- package/src/lib/components/item/index.ts +34 -0
- package/src/lib/components/item/item-actions.svelte +11 -0
- package/src/lib/components/item/item-content.svelte +15 -0
- package/src/lib/components/item/item-description.svelte +18 -0
- package/src/lib/components/item/item-footer.svelte +11 -0
- package/src/lib/components/item/item-group.svelte +16 -0
- package/src/lib/components/item/item-header.svelte +11 -0
- package/src/lib/components/item/item-media.svelte +37 -0
- package/src/lib/components/item/item-separator.svelte +9 -0
- package/src/lib/components/item/item-title.svelte +15 -0
- package/src/lib/components/item/item.svelte +61 -0
- package/src/lib/components/kbd/index.ts +10 -0
- package/src/lib/components/kbd/kbd-group.svelte +11 -0
- package/src/lib/components/kbd/kbd.svelte +18 -0
- package/src/lib/components/label/exports.ts +2 -0
- package/src/lib/components/label/index.ts +2 -0
- package/src/lib/components/label/label.svelte +39 -0
- package/src/lib/components/label/label.svelte.ts +39 -0
- package/src/lib/components/label/types.ts +7 -0
- package/src/lib/components/link-preview/components/link-preview-content.svelte +60 -0
- package/src/lib/components/link-preview/components/link-preview-trigger.svelte +29 -0
- package/src/lib/components/link-preview/components/link-preview.svelte +34 -0
- package/src/lib/components/link-preview/exports.ts +11 -0
- package/src/lib/components/link-preview/index.ts +2 -0
- package/src/lib/components/link-preview/link-preview.svelte.ts +270 -0
- package/src/lib/components/link-preview/types.ts +102 -0
- package/src/lib/components/menu/components/menu-arrow.svelte +14 -0
- package/src/lib/components/menu/components/menu-checkbox-group.svelte +42 -0
- package/src/lib/components/menu/components/menu-checkbox-item.svelte +85 -0
- package/src/lib/components/menu/components/menu-content.svelte +98 -0
- package/src/lib/components/menu/components/menu-group-heading.svelte +47 -0
- package/src/lib/components/menu/components/menu-group.svelte +36 -0
- package/src/lib/components/menu/components/menu-item.svelte +58 -0
- package/src/lib/components/menu/components/menu-radio-group.svelte +44 -0
- package/src/lib/components/menu/components/menu-radio-item.svelte +65 -0
- package/src/lib/components/menu/components/menu-separator.svelte +38 -0
- package/src/lib/components/menu/components/menu-sub-content-static.svelte +8 -0
- package/src/lib/components/menu/components/menu-sub-content.svelte +133 -0
- package/src/lib/components/menu/components/menu-sub-trigger.svelte +60 -0
- package/src/lib/components/menu/components/menu-sub.svelte +23 -0
- package/src/lib/components/menu/components/menu-trigger.svelte +50 -0
- package/src/lib/components/menu/components/menu.svelte +58 -0
- package/src/lib/components/menu/exports.ts +38 -0
- package/src/lib/components/menu/menu.svelte.ts +1599 -0
- package/src/lib/components/menu/types.ts +285 -0
- package/src/lib/components/menu/utils.ts +68 -0
- package/src/lib/components/menubar/components/menubar-content-static.svelte +50 -0
- package/src/lib/components/menubar/components/menubar-content.svelte +54 -0
- package/src/lib/components/menubar/components/menubar-menu.svelte +34 -0
- package/src/lib/components/menubar/components/menubar-trigger.svelte +50 -0
- package/src/lib/components/menubar/components/menubar.svelte +57 -0
- package/src/lib/components/menubar/exports.ts +44 -0
- package/src/lib/components/menubar/index.ts +2 -0
- package/src/lib/components/menubar/menubar.svelte.ts +394 -0
- package/src/lib/components/menubar/types.ts +97 -0
- package/src/lib/components/meter/components/meter.svelte +41 -0
- package/src/lib/components/meter/exports.ts +2 -0
- package/src/lib/components/meter/index.ts +2 -0
- package/src/lib/components/meter/meter.svelte.ts +47 -0
- package/src/lib/components/meter/types.ts +28 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-content-impl.svelte +85 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-content.svelte +58 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-indicator-impl.svelte +29 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-indicator.svelte +56 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-item.svelte +56 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-link.svelte +64 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-list.svelte +59 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-sub.svelte +46 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-trigger.svelte +80 -0
- package/src/lib/components/navigation-menu/components/navigation-menu-viewport.svelte +63 -0
- package/src/lib/components/navigation-menu/components/navigation-menu.svelte +80 -0
- package/src/lib/components/navigation-menu/index.ts +28 -0
- package/src/lib/components/navigation-menu/navigation-menu.svelte.ts +1092 -0
- package/src/lib/components/navigation-menu/types.ts +189 -0
- package/src/lib/components/pagination/components/pagination-next-button.svelte +60 -0
- package/src/lib/components/pagination/components/pagination-page.svelte +65 -0
- package/src/lib/components/pagination/components/pagination-prev-button.svelte +60 -0
- package/src/lib/components/pagination/components/pagination.svelte +65 -0
- package/src/lib/components/pagination/index.ts +11 -0
- package/src/lib/components/pagination/pagination.svelte.ts +275 -0
- package/src/lib/components/pagination/types.ts +100 -0
- package/src/lib/components/pin-input/components/pin-input-cell.svelte +49 -0
- package/src/lib/components/pin-input/components/pin-input.svelte +76 -0
- package/src/lib/components/pin-input/exports.ts +4 -0
- package/src/lib/components/pin-input/index.ts +2 -0
- package/src/lib/components/pin-input/pin-input.svelte.ts +541 -0
- package/src/lib/components/pin-input/types.ts +118 -0
- package/src/lib/components/pin-input/usePasswordManager.svelte.ts +122 -0
- package/src/lib/components/popover/components/popover-close.svelte +38 -0
- package/src/lib/components/popover/components/popover-content.svelte +70 -0
- package/src/lib/components/popover/components/popover-header.svelte +11 -0
- package/src/lib/components/popover/components/popover-title.svelte +11 -0
- package/src/lib/components/popover/components/popover-trigger.svelte +44 -0
- package/src/lib/components/popover/components/popover.svelte +26 -0
- package/src/lib/components/popover/exports.ts +13 -0
- package/src/lib/components/popover/index.ts +2 -0
- package/src/lib/components/popover/popover.svelte.ts +392 -0
- package/src/lib/components/popover/types.ts +92 -0
- package/src/lib/components/progress/components/progress.svelte +56 -0
- package/src/lib/components/progress/exports.ts +3 -0
- package/src/lib/components/progress/index.ts +2 -0
- package/src/lib/components/progress/progress.svelte.ts +58 -0
- package/src/lib/components/progress/types.ts +28 -0
- package/src/lib/components/radio-group/context.ts +13 -0
- package/src/lib/components/radio-group/index.ts +10 -0
- package/src/lib/components/radio-group/radio-group-item.svelte +67 -0
- package/src/lib/components/radio-group/radio-group.svelte +87 -0
- package/src/lib/components/range-calendar/components/range-calendar-cell.svelte +31 -0
- package/src/lib/components/range-calendar/components/range-calendar-day.svelte +33 -0
- package/src/lib/components/range-calendar/components/range-calendar.svelte +120 -0
- package/src/lib/components/range-calendar/exports.ts +31 -0
- package/src/lib/components/range-calendar/index.ts +2 -0
- package/src/lib/components/range-calendar/range-calendar.svelte.ts +739 -0
- package/src/lib/components/range-calendar/types.ts +258 -0
- package/src/lib/components/resizable/index.ts +15 -0
- package/src/lib/components/resizable/resizable-handle.svelte +30 -0
- package/src/lib/components/resizable/resizable-pane-group.svelte +19 -0
- package/src/lib/components/scroll-area/components/scroll-area-corner-impl.svelte +34 -0
- package/src/lib/components/scroll-area/components/scroll-area-corner.svelte +18 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar-auto.svelte +15 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar-hover.svelte +22 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar-scroll.svelte +16 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar-shared.svelte +19 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar-visible.svelte +16 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar-x.svelte +23 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar-y.svelte +24 -0
- package/src/lib/components/scroll-area/components/scroll-area-scrollbar.svelte +56 -0
- package/src/lib/components/scroll-area/components/scroll-area-thumb-impl.svelte +49 -0
- package/src/lib/components/scroll-area/components/scroll-area-thumb.svelte +21 -0
- package/src/lib/components/scroll-area/components/scroll-area-viewport.svelte +39 -0
- package/src/lib/components/scroll-area/components/scroll-area.svelte +82 -0
- package/src/lib/components/scroll-area/exports.ts +13 -0
- package/src/lib/components/scroll-area/index.ts +2 -0
- package/src/lib/components/scroll-area/scroll-area.svelte.ts +946 -0
- package/src/lib/components/scroll-area/types.ts +67 -0
- package/src/lib/components/select/index.ts +5 -0
- package/src/lib/components/select/select-opt-group.svelte +10 -0
- package/src/lib/components/select/select-option.svelte +15 -0
- package/src/lib/components/select/select.svelte +281 -0
- package/src/lib/components/separator/components/separator.svelte +49 -0
- package/src/lib/components/separator/index.ts +3 -0
- package/src/lib/components/separator/separator.svelte.ts +43 -0
- package/src/lib/components/separator/types.ts +22 -0
- package/src/lib/components/sheet/components/sheet-close.svelte +8 -0
- package/src/lib/components/sheet/components/sheet-content.svelte +108 -0
- package/src/lib/components/sheet/components/sheet-description.svelte +9 -0
- package/src/lib/components/sheet/components/sheet-footer.svelte +11 -0
- package/src/lib/components/sheet/components/sheet-header.svelte +11 -0
- package/src/lib/components/sheet/components/sheet-overlay.svelte +13 -0
- package/src/lib/components/sheet/components/sheet-title.svelte +9 -0
- package/src/lib/components/sheet/components/sheet-trigger.svelte +8 -0
- package/src/lib/components/sheet/index.ts +47 -0
- package/src/lib/components/sheet/variants.ts +20 -0
- package/src/lib/components/sidebar/constants.ts +6 -0
- package/src/lib/components/sidebar/context.svelte.ts +54 -0
- package/src/lib/components/sidebar/index.ts +77 -0
- package/src/lib/components/sidebar/sidebar-content.svelte +16 -0
- package/src/lib/components/sidebar/sidebar-desktop-surface.svelte +60 -0
- package/src/lib/components/sidebar/sidebar-footer.svelte +11 -0
- package/src/lib/components/sidebar/sidebar-group-action.svelte +34 -0
- package/src/lib/components/sidebar/sidebar-group-content.svelte +16 -0
- package/src/lib/components/sidebar/sidebar-group-label.svelte +34 -0
- package/src/lib/components/sidebar/sidebar-group.svelte +16 -0
- package/src/lib/components/sidebar/sidebar-header.svelte +11 -0
- package/src/lib/components/sidebar/sidebar-input.svelte +14 -0
- package/src/lib/components/sidebar/sidebar-inset.svelte +18 -0
- package/src/lib/components/sidebar/sidebar-menu-action.svelte +38 -0
- package/src/lib/components/sidebar/sidebar-menu-badge.svelte +19 -0
- package/src/lib/components/sidebar/sidebar-menu-button.svelte +99 -0
- package/src/lib/components/sidebar/sidebar-menu-item.svelte +21 -0
- package/src/lib/components/sidebar/sidebar-menu-skeleton.svelte +34 -0
- package/src/lib/components/sidebar/sidebar-menu-sub-button.svelte +40 -0
- package/src/lib/components/sidebar/sidebar-menu-sub-item.svelte +16 -0
- package/src/lib/components/sidebar/sidebar-menu-sub.svelte +19 -0
- package/src/lib/components/sidebar/sidebar-menu.svelte +21 -0
- package/src/lib/components/sidebar/sidebar-mobile-surface.svelte +48 -0
- package/src/lib/components/sidebar/sidebar-provider.svelte +60 -0
- package/src/lib/components/sidebar/sidebar-rail.svelte +36 -0
- package/src/lib/components/sidebar/sidebar-separator.svelte +9 -0
- package/src/lib/components/sidebar/sidebar-trigger.svelte +35 -0
- package/src/lib/components/sidebar/sidebar.svelte +30 -0
- package/src/lib/components/sidebar/types.ts +14 -0
- package/src/lib/components/skeleton/index.ts +7 -0
- package/src/lib/components/skeleton/skeleton.svelte +9 -0
- package/src/lib/components/slider/components/slider-range.svelte +37 -0
- package/src/lib/components/slider/components/slider-thumb-label.svelte +42 -0
- package/src/lib/components/slider/components/slider-thumb.svelte +46 -0
- package/src/lib/components/slider/components/slider-tick-label.svelte +42 -0
- package/src/lib/components/slider/components/slider-tick.svelte +28 -0
- package/src/lib/components/slider/components/slider.svelte +136 -0
- package/src/lib/components/slider/helpers.ts +249 -0
- package/src/lib/components/slider/index.ts +15 -0
- package/src/lib/components/slider/slider.svelte.ts +979 -0
- package/src/lib/components/slider/types.ts +294 -0
- package/src/lib/components/sonner/Toast.svelte +558 -0
- package/src/lib/components/sonner/Toaster.svelte +603 -0
- package/src/lib/components/sonner/index.ts +15 -0
- package/src/lib/components/sonner/toast-state.svelte.ts +217 -0
- package/src/lib/components/sonner/types.ts +384 -0
- package/src/lib/components/switch/index.ts +8 -0
- package/src/lib/components/switch/switch.svelte +78 -0
- package/src/lib/components/table/index.ts +28 -0
- package/src/lib/components/table/table-body.svelte +15 -0
- package/src/lib/components/table/table-caption.svelte +10 -0
- package/src/lib/components/table/table-cell.svelte +14 -0
- package/src/lib/components/table/table-footer.svelte +19 -0
- package/src/lib/components/table/table-head.svelte +17 -0
- package/src/lib/components/table/table-header.svelte +15 -0
- package/src/lib/components/table/table-row.svelte +14 -0
- package/src/lib/components/table/table.svelte +12 -0
- package/src/lib/components/tabs/components/tabs-content.svelte +30 -0
- package/src/lib/components/tabs/components/tabs-list.svelte +38 -0
- package/src/lib/components/tabs/components/tabs-trigger.svelte +51 -0
- package/src/lib/components/tabs/components/tabs.svelte +52 -0
- package/src/lib/components/tabs/index.ts +11 -0
- package/src/lib/components/tabs/tabs.svelte.ts +253 -0
- package/src/lib/components/tabs/types.ts +86 -0
- package/src/lib/components/textarea/index.ts +7 -0
- package/src/lib/components/textarea/textarea.svelte +23 -0
- package/src/lib/components/theme-toggle/index.ts +5 -0
- package/src/lib/components/theme-toggle/theme-toggle.svelte +49 -0
- package/src/lib/components/theme-toggle/theme.svelte.ts +81 -0
- package/src/lib/components/time-field/components/time-field-hidden-input.svelte +9 -0
- package/src/lib/components/time-field/components/time-field-input.svelte +33 -0
- package/src/lib/components/time-field/components/time-field-label.svelte +29 -0
- package/src/lib/components/time-field/components/time-field-segment.svelte +29 -0
- package/src/lib/components/time-field/components/time-field.svelte +99 -0
- package/src/lib/components/time-field/index.ts +11 -0
- package/src/lib/components/time-field/time-field.svelte.ts +1198 -0
- package/src/lib/components/time-field/types.ts +174 -0
- package/src/lib/components/time-range-field/components/time-range-field-input.svelte +36 -0
- package/src/lib/components/time-range-field/components/time-range-field-label.svelte +29 -0
- package/src/lib/components/time-range-field/components/time-range-field.svelte +104 -0
- package/src/lib/components/time-range-field/index.ts +11 -0
- package/src/lib/components/time-range-field/time-range-field.svelte.ts +235 -0
- package/src/lib/components/time-range-field/types.ts +181 -0
- package/src/lib/components/toggle/components/toggle.svelte +55 -0
- package/src/lib/components/toggle/index.ts +3 -0
- package/src/lib/components/toggle/toggle.svelte.ts +57 -0
- package/src/lib/components/toggle/types.ts +33 -0
- package/src/lib/components/toggle/variants.ts +25 -0
- package/src/lib/components/toggle-group/components/toggle-group-item.svelte +67 -0
- package/src/lib/components/toggle-group/components/toggle-group.svelte +109 -0
- package/src/lib/components/toggle-group/index.ts +7 -0
- package/src/lib/components/toggle-group/toggle-group.svelte.ts +235 -0
- package/src/lib/components/toggle-group/types.ts +89 -0
- package/src/lib/components/toolbar/components/toolbar-button.svelte +46 -0
- package/src/lib/components/toolbar/components/toolbar-group-item.svelte +56 -0
- package/src/lib/components/toolbar/components/toolbar-group.svelte +69 -0
- package/src/lib/components/toolbar/components/toolbar-link.svelte +39 -0
- package/src/lib/components/toolbar/components/toolbar.svelte +39 -0
- package/src/lib/components/toolbar/index.ts +13 -0
- package/src/lib/components/toolbar/toolbar.svelte.ts +373 -0
- package/src/lib/components/toolbar/types.ts +60 -0
- package/src/lib/components/tooltip/components/tooltip-content.svelte +81 -0
- package/src/lib/components/tooltip/components/tooltip-provider.svelte +26 -0
- package/src/lib/components/tooltip/components/tooltip-trigger.svelte +48 -0
- package/src/lib/components/tooltip/components/tooltip.svelte +55 -0
- package/src/lib/components/tooltip/index.ts +17 -0
- package/src/lib/components/tooltip/tooltip.svelte.ts +796 -0
- package/src/lib/components/tooltip/types.ts +175 -0
- package/src/lib/components/tooltip/utils.ts +1 -0
- package/src/lib/icons/google-icon.svelte +10 -0
- package/src/lib/icons/google-workspace.svelte +18 -0
- package/src/lib/icons/icon.d.ts +19 -0
- package/src/lib/icons/instagram.svelte +9 -0
- package/src/lib/icons/instantly.svelte +10 -0
- package/src/lib/icons/linkedin.svelte +9 -0
- package/src/lib/icons/mailshake.svelte +10 -0
- package/src/lib/icons/microsoft-365.svelte +7 -0
- package/src/lib/icons/passcode.svelte +12 -0
- package/src/lib/icons/replyio.svelte +10 -0
- package/src/lib/icons/smartlead.svelte +19 -0
- package/src/lib/icons/smtp.svelte +10 -0
- package/src/lib/icons/x-logo.svelte +9 -0
- package/src/lib/internal/animations-settled.svelte.ts +119 -0
- package/src/lib/internal/arrays.ts +253 -0
- package/src/lib/internal/attribute-types.ts +53 -0
- package/src/lib/internal/attrs.ts +64 -0
- package/src/lib/internal/body-scroll-lock.svelte.ts +330 -0
- package/src/lib/internal/create-id.ts +12 -0
- package/src/lib/internal/date-time/announcer.ts +74 -0
- package/src/lib/internal/date-time/calendar-helpers.svelte.ts +399 -0
- package/src/lib/internal/date-time/field/helpers.ts +431 -0
- package/src/lib/internal/date-time/field/parts.ts +15 -0
- package/src/lib/internal/date-time/field/range-field.svelte.ts +45 -0
- package/src/lib/internal/date-time/field/segments.ts +89 -0
- package/src/lib/internal/date-time/field/time-helpers.ts +311 -0
- package/src/lib/internal/date-time/formatter.ts +86 -0
- package/src/lib/internal/date-time/placeholders.ts +131 -0
- package/src/lib/internal/date-time/types.ts +121 -0
- package/src/lib/internal/date-time/utils.ts +243 -0
- package/src/lib/internal/dismissible-layer/index.ts +3 -0
- package/src/lib/internal/dismissible-layer/scheduler.ts +48 -0
- package/src/lib/internal/dismissible-layer/types.ts +57 -0
- package/src/lib/internal/dismissible-layer/use-dismissable-layer.svelte.ts +291 -0
- package/src/lib/internal/escape-layer/index.ts +3 -0
- package/src/lib/internal/escape-layer/types.ts +34 -0
- package/src/lib/internal/escape-layer/use-escape-layer.svelte.ts +91 -0
- package/src/lib/internal/floating-layer/components/floating-layer-arrow.svelte +35 -0
- package/src/lib/internal/floating-layer/components/floating-layer-content-static.svelte +19 -0
- package/src/lib/internal/floating-layer/components/floating-layer-content.svelte +52 -0
- package/src/lib/internal/floating-layer/components/floating-layer.svelte +12 -0
- package/src/lib/internal/floating-layer/components/index.ts +6 -0
- package/src/lib/internal/floating-layer/index.ts +2 -0
- package/src/lib/internal/floating-layer/types.ts +126 -0
- package/src/lib/internal/floating-layer/use-floating-layer.svelte.ts +471 -0
- package/src/lib/internal/focus-scope/focus-scope.svelte.ts +310 -0
- package/src/lib/internal/focus-scope/index.ts +4 -0
- package/src/lib/internal/focus-scope/types.ts +45 -0
- package/src/lib/internal/focus.ts +14 -0
- package/src/lib/internal/global-singleton.ts +10 -0
- package/src/lib/internal/group-value.svelte.ts +36 -0
- package/src/lib/internal/hover-intent-geometry.ts +96 -0
- package/src/lib/internal/index.ts +44 -0
- package/src/lib/internal/kbd.ts +60 -0
- package/src/lib/internal/layer-stack.ts +37 -0
- package/src/lib/internal/math.ts +11 -0
- package/src/lib/internal/merge-props.ts +7 -0
- package/src/lib/internal/native-dialog-controller.svelte.ts +102 -0
- package/src/lib/internal/native-popover.svelte.ts +173 -0
- package/src/lib/internal/open-cell.svelte.ts +41 -0
- package/src/lib/internal/paneforge/index.ts +5 -0
- package/src/lib/internal/paneforge/internal/constants.ts +2 -0
- package/src/lib/internal/paneforge/internal/helpers.ts +354 -0
- package/src/lib/internal/paneforge/internal/types.ts +33 -0
- package/src/lib/internal/paneforge/internal/utils/adjust-layout.ts +122 -0
- package/src/lib/internal/paneforge/internal/utils/aria.ts +36 -0
- package/src/lib/internal/paneforge/internal/utils/compare.ts +15 -0
- package/src/lib/internal/paneforge/internal/utils/is.ts +13 -0
- package/src/lib/internal/paneforge/internal/utils/resize.ts +31 -0
- package/src/lib/internal/paneforge/internal/utils/storage.ts +116 -0
- package/src/lib/internal/paneforge/internal/utils/style.ts +104 -0
- package/src/lib/internal/paneforge/pane-group.svelte +48 -0
- package/src/lib/internal/paneforge/pane-resizer.svelte +40 -0
- package/src/lib/internal/paneforge/pane.svelte +60 -0
- package/src/lib/internal/paneforge/paneforge.svelte.ts +821 -0
- package/src/lib/internal/paneforge/types.ts +179 -0
- package/src/lib/internal/popper-layer/index.ts +2 -0
- package/src/lib/internal/popper-layer/popper-content.svelte +19 -0
- package/src/lib/internal/popper-layer/popper-layer-inner.svelte +122 -0
- package/src/lib/internal/popper-layer/popper-layer.svelte +71 -0
- package/src/lib/internal/popper-layer/types.ts +65 -0
- package/src/lib/internal/portal/index.ts +2 -0
- package/src/lib/internal/portal/portal.svelte +61 -0
- package/src/lib/internal/prop-resolvers.ts +14 -0
- package/src/lib/internal/roving-focus-group.ts +147 -0
- package/src/lib/internal/roving-focus-item.svelte.ts +51 -0
- package/src/lib/internal/safe-polygon.svelte.ts +239 -0
- package/src/lib/internal/shared-state.svelte.ts +39 -0
- package/src/lib/internal/state-machine.ts +32 -0
- package/src/lib/internal/svelte-resize-observer.svelte.ts +37 -0
- package/src/lib/internal/tabbable.ts +398 -0
- package/src/lib/internal/table/core.ts +53 -0
- package/src/lib/internal/table/filter-fns.ts +10 -0
- package/src/lib/internal/table/index.ts +2 -0
- package/src/lib/internal/table/sorting-fns.ts +84 -0
- package/src/lib/internal/table/table.svelte.ts +330 -0
- package/src/lib/internal/table/types.ts +33 -0
- package/src/lib/internal/timeout-fn.svelte.ts +36 -0
- package/src/lib/internal/tools/box.svelte.ts +153 -0
- package/src/lib/internal/tools/index.ts +22 -0
- package/src/lib/internal/tools/types.ts +44 -0
- package/src/lib/internal/tools/utils/attach-ref.ts +74 -0
- package/src/lib/internal/tools/utils/compose-handlers.ts +36 -0
- package/src/lib/internal/tools/utils/dom-context.svelte.ts +63 -0
- package/src/lib/internal/tools/utils/dom.ts +62 -0
- package/src/lib/internal/tools/utils/events.ts +1 -0
- package/src/lib/internal/tools/utils/index.ts +5 -0
- package/src/lib/internal/tools/utils/strings.ts +28 -0
- package/src/lib/internal/typeahead.svelte.ts +48 -0
- package/src/lib/internal/types.ts +119 -0
- package/src/lib/internal/utils.ts +10 -0
- package/src/lib/internal/vaul/browser.ts +8 -0
- package/src/lib/internal/vaul/constants.ts +19 -0
- package/src/lib/internal/vaul/helpers.ts +39 -0
- package/src/lib/internal/vaul/types.ts +142 -0
- package/src/lib/internal/vaul/use-drawer-content.svelte.ts +219 -0
- package/src/lib/internal/vaul/use-drawer-root.svelte.ts +682 -0
- package/src/lib/internal/vaul/use-position-fixed.svelte.ts +142 -0
- package/src/lib/internal/vaul/use-prevent-scroll.svelte.ts +267 -0
- package/src/lib/internal/vaul/use-snap-points.svelte.ts +246 -0
- 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
|
+
}
|