@llui/components 0.0.13 → 0.0.15
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/dist/components/accordion.js +1 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert-dialog.d.ts +1 -1
- package/dist/components/alert-dialog.d.ts.map +1 -1
- package/dist/components/alert-dialog.js +2 -1
- package/dist/components/alert-dialog.js.map +1 -0
- package/dist/components/angle-slider.js +2 -1
- package/dist/components/angle-slider.js.map +1 -0
- package/dist/components/async-list.js +1 -0
- package/dist/components/async-list.js.map +1 -0
- package/dist/components/avatar.js +1 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/carousel.js +2 -1
- package/dist/components/carousel.js.map +1 -0
- package/dist/components/cascade-select.js +2 -1
- package/dist/components/cascade-select.js.map +1 -0
- package/dist/components/checkbox.js +1 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/clipboard.js +2 -1
- package/dist/components/clipboard.js.map +1 -0
- package/dist/components/collapsible.js +1 -0
- package/dist/components/collapsible.js.map +1 -0
- package/dist/components/color-picker.js +2 -1
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/combobox.d.ts +1 -1
- package/dist/components/combobox.d.ts.map +1 -1
- package/dist/components/combobox.js +4 -3
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/context-menu.js +2 -1
- package/dist/components/context-menu.js.map +1 -0
- package/dist/components/date-input.js +2 -1
- package/dist/components/date-input.js.map +1 -0
- package/dist/components/date-picker.js +3 -2
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/dialog.js +6 -5
- package/dist/components/dialog.js.map +1 -0
- package/dist/components/drawer.js +6 -5
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/editable.js +1 -0
- package/dist/components/editable.js.map +1 -0
- package/dist/components/file-upload.js +2 -1
- package/dist/components/file-upload.js.map +1 -0
- package/dist/components/floating-panel.js +2 -1
- package/dist/components/floating-panel.js.map +1 -0
- package/dist/components/form.js +1 -0
- package/dist/components/form.js.map +1 -0
- package/dist/components/hover-card.d.ts +1 -1
- package/dist/components/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card.js +2 -1
- package/dist/components/hover-card.js.map +1 -0
- package/dist/components/image-cropper.js +2 -1
- package/dist/components/image-cropper.js.map +1 -0
- package/dist/components/in-view.js +1 -0
- package/dist/components/in-view.js.map +1 -0
- package/dist/components/index.d.ts +119 -119
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +62 -61
- package/dist/components/index.js.map +1 -0
- package/dist/components/listbox.js +2 -1
- package/dist/components/listbox.js.map +1 -0
- package/dist/components/marquee.js +1 -0
- package/dist/components/marquee.js.map +1 -0
- package/dist/components/menu.d.ts +1 -1
- package/dist/components/menu.d.ts.map +1 -1
- package/dist/components/menu.js +4 -3
- package/dist/components/menu.js.map +1 -0
- package/dist/components/navigation-menu.js +2 -1
- package/dist/components/navigation-menu.js.map +1 -0
- package/dist/components/number-input.js +2 -1
- package/dist/components/number-input.js.map +1 -0
- package/dist/components/pagination.js +2 -1
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/password-input.js +2 -1
- package/dist/components/password-input.js.map +1 -0
- package/dist/components/pin-input.js +3 -2
- package/dist/components/pin-input.js.map +1 -0
- package/dist/components/popover.d.ts +1 -1
- package/dist/components/popover.d.ts.map +1 -1
- package/dist/components/popover.js +5 -4
- package/dist/components/popover.js.map +1 -0
- package/dist/components/presence.js +1 -0
- package/dist/components/presence.js.map +1 -0
- package/dist/components/progress.js +2 -1
- package/dist/components/progress.js.map +1 -0
- package/dist/components/qr-code.js +2 -1
- package/dist/components/qr-code.js.map +1 -0
- package/dist/components/radio-group.js +2 -1
- package/dist/components/radio-group.js.map +1 -0
- package/dist/components/rating-group.js +2 -1
- package/dist/components/rating-group.js.map +1 -0
- package/dist/components/scroll-area.js +1 -0
- package/dist/components/scroll-area.js.map +1 -0
- package/dist/components/select.d.ts +1 -1
- package/dist/components/select.d.ts.map +1 -1
- package/dist/components/select.js +4 -3
- package/dist/components/select.js.map +1 -0
- package/dist/components/signature-pad.js +2 -1
- package/dist/components/signature-pad.js.map +1 -0
- package/dist/components/slider.js +2 -1
- package/dist/components/slider.js.map +1 -0
- package/dist/components/sortable.js +1 -0
- package/dist/components/sortable.js.map +1 -0
- package/dist/components/splitter.js +2 -1
- package/dist/components/splitter.js.map +1 -0
- package/dist/components/steps.js +2 -1
- package/dist/components/steps.js.map +1 -0
- package/dist/components/switch.js +1 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/tabs.js +2 -1
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tags-input.js +3 -2
- package/dist/components/tags-input.js.map +1 -0
- package/dist/components/theme-switch.js +1 -0
- package/dist/components/theme-switch.js.map +1 -0
- package/dist/components/time-picker.js +2 -1
- package/dist/components/time-picker.js.map +1 -0
- package/dist/components/timer.js +2 -1
- package/dist/components/timer.js.map +1 -0
- package/dist/components/toast.js +2 -1
- package/dist/components/toast.js.map +1 -0
- package/dist/components/toc.js +2 -1
- package/dist/components/toc.js.map +1 -0
- package/dist/components/toggle-group.js +2 -1
- package/dist/components/toggle-group.js.map +1 -0
- package/dist/components/toggle.js +1 -0
- package/dist/components/toggle.js.map +1 -0
- package/dist/components/tooltip.d.ts +1 -1
- package/dist/components/tooltip.d.ts.map +1 -1
- package/dist/components/tooltip.js +2 -1
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/tour.js +2 -1
- package/dist/components/tour.js.map +1 -0
- package/dist/components/tree-view.js +3 -2
- package/dist/components/tree-view.js.map +1 -0
- package/dist/format/cache.js +1 -0
- package/dist/format/cache.js.map +1 -0
- package/dist/format/defaults.js +1 -0
- package/dist/format/defaults.js.map +1 -0
- package/dist/format/format-date.js +3 -2
- package/dist/format/format-date.js.map +1 -0
- package/dist/format/format-display-name.js +3 -2
- package/dist/format/format-display-name.js.map +1 -0
- package/dist/format/format-file-size.js +3 -2
- package/dist/format/format-file-size.js.map +1 -0
- package/dist/format/format-list.js +3 -2
- package/dist/format/format-list.js.map +1 -0
- package/dist/format/format-number.js +3 -2
- package/dist/format/format-number.js.map +1 -0
- package/dist/format/format-plural.js +3 -2
- package/dist/format/format-plural.js.map +1 -0
- package/dist/format/format-relative-time.js +3 -2
- package/dist/format/format-relative-time.js.map +1 -0
- package/dist/format/index.d.ts +7 -7
- package/dist/format/index.d.ts.map +1 -1
- package/dist/format/index.js +8 -7
- package/dist/format/index.js.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -0
- package/dist/locale.js +1 -0
- package/dist/locale.js.map +1 -0
- package/dist/patterns/confirm-dialog.d.ts +1 -1
- package/dist/patterns/confirm-dialog.d.ts.map +1 -1
- package/dist/patterns/confirm-dialog.js +2 -1
- package/dist/patterns/confirm-dialog.js.map +1 -0
- package/dist/patterns/index.d.ts +2 -2
- package/dist/patterns/index.d.ts.map +1 -1
- package/dist/patterns/index.js +2 -1
- package/dist/patterns/index.js.map +1 -0
- package/dist/styles/classes/accordion.d.ts +1 -1
- package/dist/styles/classes/accordion.d.ts.map +1 -1
- package/dist/styles/classes/accordion.js +2 -1
- package/dist/styles/classes/accordion.js.map +1 -0
- package/dist/styles/classes/angle-slider.d.ts +1 -1
- package/dist/styles/classes/angle-slider.d.ts.map +1 -1
- package/dist/styles/classes/angle-slider.js +2 -1
- package/dist/styles/classes/angle-slider.js.map +1 -0
- package/dist/styles/classes/async-list.d.ts +1 -1
- package/dist/styles/classes/async-list.d.ts.map +1 -1
- package/dist/styles/classes/async-list.js +1 -0
- package/dist/styles/classes/async-list.js.map +1 -0
- package/dist/styles/classes/avatar.d.ts +1 -1
- package/dist/styles/classes/avatar.d.ts.map +1 -1
- package/dist/styles/classes/avatar.js +2 -1
- package/dist/styles/classes/avatar.js.map +1 -0
- package/dist/styles/classes/carousel.d.ts +1 -1
- package/dist/styles/classes/carousel.d.ts.map +1 -1
- package/dist/styles/classes/carousel.js +2 -1
- package/dist/styles/classes/carousel.js.map +1 -0
- package/dist/styles/classes/cascade-select.d.ts +1 -1
- package/dist/styles/classes/cascade-select.d.ts.map +1 -1
- package/dist/styles/classes/cascade-select.js +2 -1
- package/dist/styles/classes/cascade-select.js.map +1 -0
- package/dist/styles/classes/checkbox.d.ts +1 -1
- package/dist/styles/classes/checkbox.d.ts.map +1 -1
- package/dist/styles/classes/checkbox.js +2 -1
- package/dist/styles/classes/checkbox.js.map +1 -0
- package/dist/styles/classes/clipboard.d.ts +1 -1
- package/dist/styles/classes/clipboard.d.ts.map +1 -1
- package/dist/styles/classes/clipboard.js +1 -0
- package/dist/styles/classes/clipboard.js.map +1 -0
- package/dist/styles/classes/collapsible.d.ts +1 -1
- package/dist/styles/classes/collapsible.d.ts.map +1 -1
- package/dist/styles/classes/collapsible.js +2 -1
- package/dist/styles/classes/collapsible.js.map +1 -0
- package/dist/styles/classes/color-picker.d.ts +1 -1
- package/dist/styles/classes/color-picker.d.ts.map +1 -1
- package/dist/styles/classes/color-picker.js +1 -0
- package/dist/styles/classes/color-picker.js.map +1 -0
- package/dist/styles/classes/combobox.d.ts +1 -1
- package/dist/styles/classes/combobox.d.ts.map +1 -1
- package/dist/styles/classes/combobox.js +2 -1
- package/dist/styles/classes/combobox.js.map +1 -0
- package/dist/styles/classes/context-menu.d.ts +1 -1
- package/dist/styles/classes/context-menu.d.ts.map +1 -1
- package/dist/styles/classes/context-menu.js +2 -1
- package/dist/styles/classes/context-menu.js.map +1 -0
- package/dist/styles/classes/date-input.d.ts +1 -1
- package/dist/styles/classes/date-input.d.ts.map +1 -1
- package/dist/styles/classes/date-input.js +2 -1
- package/dist/styles/classes/date-input.js.map +1 -0
- package/dist/styles/classes/date-picker.d.ts +1 -1
- package/dist/styles/classes/date-picker.d.ts.map +1 -1
- package/dist/styles/classes/date-picker.js +2 -1
- package/dist/styles/classes/date-picker.js.map +1 -0
- package/dist/styles/classes/dialog.d.ts +1 -1
- package/dist/styles/classes/dialog.d.ts.map +1 -1
- package/dist/styles/classes/dialog.js +2 -1
- package/dist/styles/classes/dialog.js.map +1 -0
- package/dist/styles/classes/drawer.d.ts +1 -1
- package/dist/styles/classes/drawer.d.ts.map +1 -1
- package/dist/styles/classes/drawer.js +2 -1
- package/dist/styles/classes/drawer.js.map +1 -0
- package/dist/styles/classes/editable.d.ts +1 -1
- package/dist/styles/classes/editable.d.ts.map +1 -1
- package/dist/styles/classes/editable.js +2 -1
- package/dist/styles/classes/editable.js.map +1 -0
- package/dist/styles/classes/file-upload.d.ts +1 -1
- package/dist/styles/classes/file-upload.d.ts.map +1 -1
- package/dist/styles/classes/file-upload.js +1 -0
- package/dist/styles/classes/file-upload.js.map +1 -0
- package/dist/styles/classes/floating-panel.d.ts +1 -1
- package/dist/styles/classes/floating-panel.d.ts.map +1 -1
- package/dist/styles/classes/floating-panel.js +2 -1
- package/dist/styles/classes/floating-panel.js.map +1 -0
- package/dist/styles/classes/hover-card.d.ts +1 -1
- package/dist/styles/classes/hover-card.d.ts.map +1 -1
- package/dist/styles/classes/hover-card.js +2 -1
- package/dist/styles/classes/hover-card.js.map +1 -0
- package/dist/styles/classes/image-cropper.d.ts +1 -1
- package/dist/styles/classes/image-cropper.d.ts.map +1 -1
- package/dist/styles/classes/image-cropper.js +1 -0
- package/dist/styles/classes/image-cropper.js.map +1 -0
- package/dist/styles/classes/index.d.ts +53 -53
- package/dist/styles/classes/index.d.ts.map +1 -1
- package/dist/styles/classes/index.js +54 -53
- package/dist/styles/classes/index.js.map +1 -0
- package/dist/styles/classes/listbox.d.ts +1 -1
- package/dist/styles/classes/listbox.d.ts.map +1 -1
- package/dist/styles/classes/listbox.js +2 -1
- package/dist/styles/classes/listbox.js.map +1 -0
- package/dist/styles/classes/marquee.d.ts +1 -1
- package/dist/styles/classes/marquee.d.ts.map +1 -1
- package/dist/styles/classes/marquee.js +1 -0
- package/dist/styles/classes/marquee.js.map +1 -0
- package/dist/styles/classes/menu.d.ts +1 -1
- package/dist/styles/classes/menu.d.ts.map +1 -1
- package/dist/styles/classes/menu.js +2 -1
- package/dist/styles/classes/menu.js.map +1 -0
- package/dist/styles/classes/navigation-menu.d.ts +1 -1
- package/dist/styles/classes/navigation-menu.d.ts.map +1 -1
- package/dist/styles/classes/navigation-menu.js +1 -0
- package/dist/styles/classes/navigation-menu.js.map +1 -0
- package/dist/styles/classes/number-input.d.ts +1 -1
- package/dist/styles/classes/number-input.d.ts.map +1 -1
- package/dist/styles/classes/number-input.js +2 -1
- package/dist/styles/classes/number-input.js.map +1 -0
- package/dist/styles/classes/pagination.d.ts +1 -1
- package/dist/styles/classes/pagination.d.ts.map +1 -1
- package/dist/styles/classes/pagination.js +2 -1
- package/dist/styles/classes/pagination.js.map +1 -0
- package/dist/styles/classes/password-input.d.ts +1 -1
- package/dist/styles/classes/password-input.d.ts.map +1 -1
- package/dist/styles/classes/password-input.js +2 -1
- package/dist/styles/classes/password-input.js.map +1 -0
- package/dist/styles/classes/pin-input.d.ts +1 -1
- package/dist/styles/classes/pin-input.d.ts.map +1 -1
- package/dist/styles/classes/pin-input.js +2 -1
- package/dist/styles/classes/pin-input.js.map +1 -0
- package/dist/styles/classes/popover.d.ts +1 -1
- package/dist/styles/classes/popover.d.ts.map +1 -1
- package/dist/styles/classes/popover.js +2 -1
- package/dist/styles/classes/popover.js.map +1 -0
- package/dist/styles/classes/presence.d.ts +1 -1
- package/dist/styles/classes/presence.d.ts.map +1 -1
- package/dist/styles/classes/presence.js +1 -0
- package/dist/styles/classes/presence.js.map +1 -0
- package/dist/styles/classes/progress.d.ts +1 -1
- package/dist/styles/classes/progress.d.ts.map +1 -1
- package/dist/styles/classes/progress.js +2 -1
- package/dist/styles/classes/progress.js.map +1 -0
- package/dist/styles/classes/qr-code.d.ts +1 -1
- package/dist/styles/classes/qr-code.d.ts.map +1 -1
- package/dist/styles/classes/qr-code.js +1 -0
- package/dist/styles/classes/qr-code.js.map +1 -0
- package/dist/styles/classes/radio-group.d.ts +1 -1
- package/dist/styles/classes/radio-group.d.ts.map +1 -1
- package/dist/styles/classes/radio-group.js +2 -1
- package/dist/styles/classes/radio-group.js.map +1 -0
- package/dist/styles/classes/rating-group.d.ts +1 -1
- package/dist/styles/classes/rating-group.d.ts.map +1 -1
- package/dist/styles/classes/rating-group.js +2 -1
- package/dist/styles/classes/rating-group.js.map +1 -0
- package/dist/styles/classes/scroll-area.d.ts +1 -1
- package/dist/styles/classes/scroll-area.d.ts.map +1 -1
- package/dist/styles/classes/scroll-area.js +1 -0
- package/dist/styles/classes/scroll-area.js.map +1 -0
- package/dist/styles/classes/select.d.ts +1 -1
- package/dist/styles/classes/select.d.ts.map +1 -1
- package/dist/styles/classes/select.js +2 -1
- package/dist/styles/classes/select.js.map +1 -0
- package/dist/styles/classes/signature-pad.d.ts +1 -1
- package/dist/styles/classes/signature-pad.d.ts.map +1 -1
- package/dist/styles/classes/signature-pad.js +1 -0
- package/dist/styles/classes/signature-pad.js.map +1 -0
- package/dist/styles/classes/slider.d.ts +1 -1
- package/dist/styles/classes/slider.d.ts.map +1 -1
- package/dist/styles/classes/slider.js +2 -1
- package/dist/styles/classes/slider.js.map +1 -0
- package/dist/styles/classes/splitter.d.ts +1 -1
- package/dist/styles/classes/splitter.d.ts.map +1 -1
- package/dist/styles/classes/splitter.js +2 -1
- package/dist/styles/classes/splitter.js.map +1 -0
- package/dist/styles/classes/steps.d.ts +1 -1
- package/dist/styles/classes/steps.d.ts.map +1 -1
- package/dist/styles/classes/steps.js +2 -1
- package/dist/styles/classes/steps.js.map +1 -0
- package/dist/styles/classes/switch.d.ts +1 -1
- package/dist/styles/classes/switch.d.ts.map +1 -1
- package/dist/styles/classes/switch.js +2 -1
- package/dist/styles/classes/switch.js.map +1 -0
- package/dist/styles/classes/tabs.d.ts +1 -1
- package/dist/styles/classes/tabs.d.ts.map +1 -1
- package/dist/styles/classes/tabs.js +2 -1
- package/dist/styles/classes/tabs.js.map +1 -0
- package/dist/styles/classes/tags-input.d.ts +1 -1
- package/dist/styles/classes/tags-input.d.ts.map +1 -1
- package/dist/styles/classes/tags-input.js +2 -1
- package/dist/styles/classes/tags-input.js.map +1 -0
- package/dist/styles/classes/time-picker.d.ts +1 -1
- package/dist/styles/classes/time-picker.d.ts.map +1 -1
- package/dist/styles/classes/time-picker.js +2 -1
- package/dist/styles/classes/time-picker.js.map +1 -0
- package/dist/styles/classes/timer.d.ts +1 -1
- package/dist/styles/classes/timer.d.ts.map +1 -1
- package/dist/styles/classes/timer.js +2 -1
- package/dist/styles/classes/timer.js.map +1 -0
- package/dist/styles/classes/toast.d.ts +1 -1
- package/dist/styles/classes/toast.d.ts.map +1 -1
- package/dist/styles/classes/toast.js +2 -1
- package/dist/styles/classes/toast.js.map +1 -0
- package/dist/styles/classes/toc.d.ts +1 -1
- package/dist/styles/classes/toc.d.ts.map +1 -1
- package/dist/styles/classes/toc.js +2 -1
- package/dist/styles/classes/toc.js.map +1 -0
- package/dist/styles/classes/toggle-group.d.ts +1 -1
- package/dist/styles/classes/toggle-group.d.ts.map +1 -1
- package/dist/styles/classes/toggle-group.js +2 -1
- package/dist/styles/classes/toggle-group.js.map +1 -0
- package/dist/styles/classes/toggle.d.ts +1 -1
- package/dist/styles/classes/toggle.d.ts.map +1 -1
- package/dist/styles/classes/toggle.js +2 -1
- package/dist/styles/classes/toggle.js.map +1 -0
- package/dist/styles/classes/tooltip.d.ts +1 -1
- package/dist/styles/classes/tooltip.d.ts.map +1 -1
- package/dist/styles/classes/tooltip.js +2 -1
- package/dist/styles/classes/tooltip.js.map +1 -0
- package/dist/styles/classes/tour.d.ts +1 -1
- package/dist/styles/classes/tour.d.ts.map +1 -1
- package/dist/styles/classes/tour.js +1 -0
- package/dist/styles/classes/tour.js.map +1 -0
- package/dist/styles/classes/tree-view.d.ts +1 -1
- package/dist/styles/classes/tree-view.d.ts.map +1 -1
- package/dist/styles/classes/tree-view.js +2 -1
- package/dist/styles/classes/tree-view.js.map +1 -0
- package/dist/styles/index.d.ts +4 -4
- package/dist/styles/index.d.ts.map +1 -1
- package/dist/styles/index.js +3 -2
- package/dist/styles/index.js.map +1 -0
- package/dist/styles/theme.js +1 -0
- package/dist/styles/theme.js.map +1 -0
- package/dist/styles/utils/cx.js +1 -0
- package/dist/styles/utils/cx.js.map +1 -0
- package/dist/styles/utils/index.d.ts +2 -2
- package/dist/styles/utils/index.d.ts.map +1 -1
- package/dist/styles/utils/index.js +3 -2
- package/dist/styles/utils/index.js.map +1 -0
- package/dist/styles/utils/variants.js +2 -1
- package/dist/styles/utils/variants.js.map +1 -0
- package/dist/utils/anatomy.js +1 -0
- package/dist/utils/anatomy.js.map +1 -0
- package/dist/utils/aria-hidden.js +1 -0
- package/dist/utils/aria-hidden.js.map +1 -0
- package/dist/utils/direction.js +1 -0
- package/dist/utils/direction.js.map +1 -0
- package/dist/utils/dismissable.d.ts +1 -1
- package/dist/utils/dismissable.d.ts.map +1 -1
- package/dist/utils/dismissable.js +2 -1
- package/dist/utils/dismissable.js.map +1 -0
- package/dist/utils/dom.js +1 -0
- package/dist/utils/dom.js.map +1 -0
- package/dist/utils/floating.js +1 -0
- package/dist/utils/floating.js.map +1 -0
- package/dist/utils/focus-trap.d.ts +1 -1
- package/dist/utils/focus-trap.d.ts.map +1 -1
- package/dist/utils/focus-trap.js +3 -2
- package/dist/utils/focus-trap.js.map +1 -0
- package/dist/utils/focusables.js +1 -0
- package/dist/utils/focusables.js.map +1 -0
- package/dist/utils/index.d.ts +18 -18
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +12 -11
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/interact-outside.d.ts +1 -1
- package/dist/utils/interact-outside.d.ts.map +1 -1
- package/dist/utils/interact-outside.js +2 -1
- package/dist/utils/interact-outside.js.map +1 -0
- package/dist/utils/remove-scroll.js +1 -0
- package/dist/utils/remove-scroll.js.map +1 -0
- package/dist/utils/tree-collection.js +1 -0
- package/dist/utils/tree-collection.js.map +1 -0
- package/dist/utils/typeahead.js +1 -0
- package/dist/utils/typeahead.js.map +1 -0
- package/package.json +12 -12
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marquee.js","sourceRoot":"","sources":["../../src/components/marquee.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\n\n/**\n * Marquee — continuously-scrolling content. The state machine tracks\n * play/pause + direction + speed; the scrolling itself is driven by CSS\n * animations or JS requestAnimationFrame (the consumer owns that).\n *\n * Expose the active state via CSS custom properties the consumer reads\n * in their stylesheet:\n * --marquee-duration: {N}s\n * --marquee-direction: 'normal' | 'reverse'\n * --marquee-playstate: 'running' | 'paused'\n */\n\nexport type MarqueeDirection = 'left' | 'right' | 'up' | 'down'\n\nexport interface MarqueeState {\n /** User-intended running state (what play/pause/toggle set). The actual\n * effective state is derived via `isRunning()` — it combines this with\n * `hovered` + `pauseOnHover`. */\n running: boolean\n direction: MarqueeDirection\n /** Duration of one full loop in seconds. Larger = slower. */\n durationSec: number\n pauseOnHover: boolean\n hovered: boolean\n disabled: boolean\n}\n\nexport type MarqueeMsg =\n | { type: 'play' }\n | { type: 'pause' }\n | { type: 'toggle' }\n | { type: 'hoverPause' }\n | { type: 'hoverResume' }\n | { type: 'setDirection'; direction: MarqueeDirection }\n | { type: 'setDuration'; durationSec: number }\n\nexport interface MarqueeInit {\n running?: boolean\n direction?: MarqueeDirection\n durationSec?: number\n pauseOnHover?: boolean\n disabled?: boolean\n}\n\nexport function init(opts: MarqueeInit = {}): MarqueeState {\n return {\n running: opts.running ?? true,\n direction: opts.direction ?? 'left',\n durationSec: opts.durationSec ?? 20,\n pauseOnHover: opts.pauseOnHover ?? false,\n hovered: false,\n disabled: opts.disabled ?? false,\n }\n}\n\n/** Derived: whether the marquee is currently animating. */\nexport function isRunning(state: MarqueeState): boolean {\n if (!state.running || state.disabled) return false\n if (state.pauseOnHover && state.hovered) return false\n return true\n}\n\nexport function update(state: MarqueeState, msg: MarqueeMsg): [MarqueeState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'play':\n return [{ ...state, running: true }, []]\n case 'pause':\n return [{ ...state, running: false }, []]\n case 'toggle':\n return [{ ...state, running: !state.running }, []]\n case 'hoverPause':\n return [{ ...state, hovered: true }, []]\n case 'hoverResume':\n return [{ ...state, hovered: false }, []]\n case 'setDirection':\n return [{ ...state, direction: msg.direction }, []]\n case 'setDuration':\n return [{ ...state, durationSec: Math.max(0, msg.durationSec) }, []]\n }\n}\n\n/** Returns 'normal' (left/up) or 'reverse' (right/down) for CSS animation-direction. */\nexport function cssAnimationDirection(direction: MarqueeDirection): 'normal' | 'reverse' {\n return direction === 'right' || direction === 'down' ? 'reverse' : 'normal'\n}\n\n/** Returns 'horizontal' or 'vertical' based on direction. */\nexport function axis(direction: MarqueeDirection): 'horizontal' | 'vertical' {\n return direction === 'up' || direction === 'down' ? 'vertical' : 'horizontal'\n}\n\nexport interface MarqueeParts<S> {\n root: {\n 'data-scope': 'marquee'\n 'data-part': 'root'\n 'data-running': (s: S) => '' | undefined\n 'data-direction': (s: S) => MarqueeDirection\n 'data-axis': (s: S) => 'horizontal' | 'vertical'\n 'data-disabled': (s: S) => '' | undefined\n style: (s: S) => string\n onMouseEnter: (e: MouseEvent) => void\n onMouseLeave: (e: MouseEvent) => void\n }\n content: {\n 'data-scope': 'marquee'\n 'data-part': 'content'\n }\n}\n\nexport function connect<S>(get: (s: S) => MarqueeState, send: Send<MarqueeMsg>): MarqueeParts<S> {\n return {\n root: {\n 'data-scope': 'marquee',\n 'data-part': 'root',\n 'data-running': (s) => (isRunning(get(s)) ? '' : undefined),\n 'data-direction': (s) => get(s).direction,\n 'data-axis': (s) => axis(get(s).direction),\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n style: (s) => {\n const st = get(s)\n return (\n `--marquee-duration:${st.durationSec}s;` +\n `--marquee-direction:${cssAnimationDirection(st.direction)};` +\n `--marquee-playstate:${isRunning(st) ? 'running' : 'paused'};`\n )\n },\n // Always fire hover messages; the reducer no-ops unless\n // state.pauseOnHover is true.\n onMouseEnter: () => send({ type: 'hoverPause' }),\n onMouseLeave: () => send({ type: 'hoverResume' }),\n },\n content: {\n 'data-scope': 'marquee',\n 'data-part': 'content',\n },\n }\n}\n\nexport const marquee = { init, update, connect, isRunning, cssAnimationDirection, axis }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Send, TransitionOptions } from '@llui/dom';
|
|
2
|
-
import { type Placement } from '../utils/floating';
|
|
2
|
+
import { type Placement } from '../utils/floating.js';
|
|
3
3
|
/**
|
|
4
4
|
* Menu — a dropdown list of items triggered by a button. Keyboard navigation
|
|
5
5
|
* (arrows, Home, End), typeahead (first-letter matching), Enter/Space to
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/components/menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAGxD,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../src/components/menu.ts"],"names":[],"mappings":"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"}
|
package/dist/components/menu.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { show, portal, onMount, div } from '@llui/dom';
|
|
2
|
-
import { pushDismissable } from '../utils/dismissable';
|
|
3
|
-
import { attachFloating } from '../utils/floating';
|
|
4
|
-
import { typeaheadAccumulate, typeaheadMatchByItems, isTypeaheadKey, TYPEAHEAD_TIMEOUT_MS, } from '../utils/typeahead';
|
|
2
|
+
import { pushDismissable } from '../utils/dismissable.js';
|
|
3
|
+
import { attachFloating } from '../utils/floating.js';
|
|
4
|
+
import { typeaheadAccumulate, typeaheadMatchByItems, isTypeaheadKey, TYPEAHEAD_TIMEOUT_MS, } from '../utils/typeahead.js';
|
|
5
5
|
export function init(opts = {}) {
|
|
6
6
|
return {
|
|
7
7
|
open: opts.open ?? false,
|
|
@@ -260,3 +260,4 @@ export function overlay(opts) {
|
|
|
260
260
|
});
|
|
261
261
|
}
|
|
262
262
|
export const menu = { init, update, connect, overlay };
|
|
263
|
+
//# sourceMappingURL=menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"menu.js","sourceRoot":"","sources":["../../src/components/menu.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, TransitionOptions } from '@llui/dom'\nimport { show, portal, onMount, div } from '@llui/dom'\nimport { pushDismissable } from '../utils/dismissable.js'\nimport { attachFloating, type Placement } from '../utils/floating.js'\nimport {\n typeaheadAccumulate,\n typeaheadMatchByItems,\n isTypeaheadKey,\n TYPEAHEAD_TIMEOUT_MS,\n} from '../utils/typeahead.js'\n\n/**\n * Menu — a dropdown list of items triggered by a button. Keyboard navigation\n * (arrows, Home, End), typeahead (first-letter matching), Enter/Space to\n * activate the focused item, Escape to close.\n *\n * Items are opaque string values (keys); the user's view renders the\n * label/icon/etc. The machine tracks which item is currently \"highlighted\"\n * (= the one that will activate on Enter). On open, the first item is\n * highlighted by default unless `defaultHighlighted` is provided.\n */\n\nexport interface MenuState {\n open: boolean\n items: string[]\n disabledItems: string[]\n highlighted: string | null\n /** Accumulator for typeahead search. */\n typeahead: string\n typeaheadExpiresAt: number\n}\n\nexport type MenuMsg =\n | { type: 'open' }\n | { type: 'close' }\n | { type: 'toggle' }\n | { type: 'highlight'; value: string | null }\n | { type: 'highlightNext' }\n | { type: 'highlightPrev' }\n | { type: 'highlightFirst' }\n | { type: 'highlightLast' }\n | { type: 'selectHighlighted' }\n | { type: 'select'; value: string }\n | { type: 'setItems'; items: string[]; disabled?: string[] }\n | { type: 'typeahead'; char: string; now: number }\n\nexport interface MenuInit {\n open?: boolean\n items?: string[]\n disabledItems?: string[]\n highlighted?: string | null\n}\n\nexport function init(opts: MenuInit = {}): MenuState {\n return {\n open: opts.open ?? false,\n items: opts.items ?? [],\n disabledItems: opts.disabledItems ?? [],\n highlighted: opts.highlighted ?? null,\n typeahead: '',\n typeaheadExpiresAt: 0,\n }\n}\n\nfunction firstEnabled(items: string[], disabled: string[]): string | null {\n for (const v of items) if (!disabled.includes(v)) return v\n return null\n}\n\nfunction lastEnabled(items: string[], disabled: string[]): string | null {\n for (let i = items.length - 1; i >= 0; i--) {\n const v = items[i]!\n if (!disabled.includes(v)) return v\n }\n return null\n}\n\nfunction nextEnabled(\n items: string[],\n disabled: string[],\n from: string | null,\n delta: 1 | -1,\n): string | null {\n if (items.length === 0) return null\n const start = from === null ? -1 : items.indexOf(from)\n const n = items.length\n for (let i = 1; i <= n; i++) {\n const idx = start === -1 && delta === 1 ? i - 1 : (start + delta * i + n * n) % n\n const v = items[idx]!\n if (!disabled.includes(v)) return v\n }\n return null\n}\n\nexport function update(state: MenuState, msg: MenuMsg): [MenuState, never[]] {\n switch (msg.type) {\n case 'open': {\n const highlighted = state.highlighted ?? firstEnabled(state.items, state.disabledItems)\n return [{ ...state, open: true, highlighted }, []]\n }\n case 'close':\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'toggle':\n if (state.open) {\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n }\n return [\n {\n ...state,\n open: true,\n highlighted: state.highlighted ?? firstEnabled(state.items, state.disabledItems),\n },\n [],\n ]\n case 'highlight':\n if (msg.value !== null && state.disabledItems.includes(msg.value)) return [state, []]\n return [{ ...state, highlighted: msg.value }, []]\n case 'highlightNext': {\n const to = nextEnabled(state.items, state.disabledItems, state.highlighted, 1)\n return [{ ...state, highlighted: to }, []]\n }\n case 'highlightPrev': {\n const to = nextEnabled(state.items, state.disabledItems, state.highlighted, -1)\n return [{ ...state, highlighted: to }, []]\n }\n case 'highlightFirst':\n return [{ ...state, highlighted: firstEnabled(state.items, state.disabledItems) }, []]\n case 'highlightLast':\n return [{ ...state, highlighted: lastEnabled(state.items, state.disabledItems) }, []]\n case 'selectHighlighted':\n if (state.highlighted === null) return [state, []]\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'select':\n if (state.disabledItems.includes(msg.value)) return [state, []]\n return [{ ...state, open: false, highlighted: null, typeahead: '' }, []]\n case 'setItems': {\n const disabled = msg.disabled ?? state.disabledItems\n const highlighted =\n state.highlighted &&\n msg.items.includes(state.highlighted) &&\n !disabled.includes(state.highlighted)\n ? state.highlighted\n : null\n return [{ ...state, items: msg.items, disabledItems: disabled, highlighted }, []]\n }\n case 'typeahead': {\n const acc = typeaheadAccumulate(state.typeahead, msg.char, msg.now, state.typeaheadExpiresAt)\n const startIdx = state.highlighted ? state.items.indexOf(state.highlighted) : null\n const matchIdx = typeaheadMatchByItems(state.items, state.disabledItems, acc, startIdx)\n const match = matchIdx === null ? null : state.items[matchIdx]!\n return [\n {\n ...state,\n typeahead: acc,\n typeaheadExpiresAt: msg.now + TYPEAHEAD_TIMEOUT_MS,\n highlighted: match ?? state.highlighted,\n },\n [],\n ]\n }\n }\n}\n\nexport interface MenuItemParts<S> {\n item: {\n role: 'menuitem'\n id: string\n 'aria-disabled': (s: S) => 'true' | undefined\n 'data-state': (s: S) => 'highlighted' | undefined\n 'data-disabled': (s: S) => '' | undefined\n 'data-scope': 'menu'\n 'data-part': 'item'\n 'data-value': string\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n onPointerMove: (e: PointerEvent) => void\n }\n}\n\nexport interface MenuParts<S> {\n trigger: {\n type: 'button'\n 'aria-haspopup': 'menu'\n 'aria-expanded': (s: S) => boolean\n 'aria-controls': string\n id: string\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'menu'\n 'data-part': 'trigger'\n onClick: (e: MouseEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n positioner: {\n 'data-scope': 'menu'\n 'data-part': 'positioner'\n style: string\n }\n content: {\n role: 'menu'\n id: string\n 'aria-labelledby': string\n tabIndex: -1\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'menu'\n 'data-part': 'content'\n onKeyDown: (e: KeyboardEvent) => void\n }\n item: (value: string) => MenuItemParts<S>\n}\n\nexport interface ConnectOptions {\n id: string\n /** Called when an item is activated (Enter/Space/click). */\n onSelect?: (value: string) => void\n}\n\nexport function connect<S>(\n get: (s: S) => MenuState,\n send: Send<MenuMsg>,\n opts: ConnectOptions,\n): MenuParts<S> {\n const base = opts.id\n const triggerId = `${base}:trigger`\n const contentId = `${base}:content`\n const itemId = (v: string): string => `${base}:item:${v}`\n\n const handleMenuKey = (e: KeyboardEvent): void => {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'highlightNext' })\n return\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'highlightPrev' })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'highlightFirst' })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'highlightLast' })\n return\n case 'Enter':\n case ' ':\n e.preventDefault()\n send({ type: 'selectHighlighted' })\n return\n case 'Escape':\n e.preventDefault()\n send({ type: 'close' })\n return\n default:\n if (isTypeaheadKey(e)) {\n send({ type: 'typeahead', char: e.key, now: Date.now() })\n }\n }\n }\n\n return {\n trigger: {\n type: 'button',\n 'aria-haspopup': 'menu',\n 'aria-expanded': (s) => get(s).open,\n 'aria-controls': contentId,\n id: triggerId,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'menu',\n 'data-part': 'trigger',\n onClick: () => send({ type: 'toggle' }),\n onKeyDown: (e: KeyboardEvent) => {\n if (e.key === 'ArrowDown' || e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n send({ type: 'open' })\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n send({ type: 'open' })\n send({ type: 'highlightLast' })\n }\n },\n },\n positioner: {\n 'data-scope': 'menu',\n 'data-part': 'positioner',\n style: 'position:absolute;top:0;left:0;',\n },\n content: {\n role: 'menu',\n id: contentId,\n 'aria-labelledby': triggerId,\n tabIndex: -1,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'menu',\n 'data-part': 'content',\n onKeyDown: handleMenuKey,\n },\n item: (value: string): MenuItemParts<S> => ({\n item: {\n role: 'menuitem',\n id: itemId(value),\n 'aria-disabled': (s) => (get(s).disabledItems.includes(value) ? 'true' : undefined),\n 'data-state': (s) => (get(s).highlighted === value ? 'highlighted' : undefined),\n 'data-disabled': (s) => (get(s).disabledItems.includes(value) ? '' : undefined),\n 'data-scope': 'menu',\n 'data-part': 'item',\n 'data-value': value,\n tabIndex: -1,\n onClick: () => {\n send({ type: 'select', value })\n opts.onSelect?.(value)\n },\n onPointerMove: () => send({ type: 'highlight', value }),\n },\n }),\n }\n}\n\nexport interface OverlayOptions<S> {\n get: (s: S) => MenuState\n send: Send<MenuMsg>\n parts: MenuParts<S>\n content: () => Node[]\n placement?: Placement\n offset?: number\n flip?: boolean\n shift?: boolean\n transition?: TransitionOptions\n target?: string | HTMLElement\n}\n\nexport function overlay<S>(opts: OverlayOptions<S>): Node[] {\n const target = opts.target ?? 'body'\n const placement = opts.placement ?? 'bottom-start'\n const offset = opts.offset ?? 4\n const flip = opts.flip !== false\n const shift = opts.shift !== false\n const parts = opts.parts\n const contentId = parts.content.id\n const triggerId = parts.trigger.id\n\n return show<S, MenuMsg>({\n when: (s) => opts.get(s).open,\n render: () =>\n portal({\n target,\n render: () => {\n onMount(() => {\n const contentEl = document.getElementById(contentId)\n const triggerEl = document.getElementById(triggerId)\n if (!contentEl || !triggerEl) return\n\n const cleanups: Array<() => void> = []\n\n const positioner = contentEl.closest('[data-part=\"positioner\"]') as HTMLElement | null\n const floatingEl = positioner ?? contentEl\n cleanups.push(\n attachFloating({\n anchor: triggerEl,\n floating: floatingEl,\n placement,\n offset,\n flip,\n shift,\n }),\n )\n\n cleanups.push(\n pushDismissable({\n element: contentEl,\n ignore: () => [triggerEl],\n onDismiss: () => {\n opts.send({ type: 'close' })\n triggerEl.focus()\n },\n }),\n )\n\n // Auto-focus content so keyboard navigation works immediately.\n // preventScroll avoids a page jump when the portaled content\n // is briefly at position (0,0) before floating-ui positions it.\n contentEl.focus({ preventScroll: true })\n\n return () => {\n for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]!()\n }\n })\n return [div(parts.positioner, opts.content())]\n },\n }),\n enter: opts.transition?.enter,\n leave: opts.transition?.leave,\n })\n}\n\nexport const menu = { init, update, connect, overlay }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useContext } from '@llui/dom';
|
|
2
|
-
import { LocaleContext } from '../locale';
|
|
2
|
+
import { LocaleContext } from '../locale.js';
|
|
3
3
|
export function init(opts = {}) {
|
|
4
4
|
return {
|
|
5
5
|
open: opts.open ?? [],
|
|
@@ -125,3 +125,4 @@ export function connect(get, send, opts) {
|
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
127
|
export const navigationMenu = { init, update, connect, isOpen };
|
|
128
|
+
//# sourceMappingURL=navigation-menu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation-menu.js","sourceRoot":"","sources":["../../src/components/navigation-menu.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Navigation menu — multi-level menu bar with hover/focus-triggered\n * submenus. Unlike `menu` (a single dropdown), navigation-menu supports\n * nested submenus arbitrarily deep and is typically used for primary\n * site navigation.\n *\n * State tracks the currently focused item id and the ids of all\n * currently-open branches. The consumer provides the tree structure\n * (items with optional children); the machine doesn't index the\n * hierarchy itself — it just maintains open-paths and lets the view\n * handle traversal.\n *\n * Typical interaction model (delay-based):\n * - Pointer enter on a branch → openBranch after openDelay\n * - Pointer leave of the whole tree → closeAll after closeDelay\n * - Click/keyboard activation → toggleBranch immediately\n *\n * The consumer is responsible for debouncing via setTimeout; the machine\n * just responds to the dispatched messages.\n */\n\nexport interface NavMenuState {\n /** Ids of open branches, in open order (root-first). Closing an\n * ancestor automatically closes its descendants. */\n open: string[]\n focused: string | null\n disabled: boolean\n}\n\nexport type NavMenuMsg =\n | { type: 'openBranch'; id: string; ancestorIds: string[] }\n | { type: 'closeBranch'; id: string }\n | { type: 'toggleBranch'; id: string; ancestorIds: string[] }\n | { type: 'closeAll' }\n | { type: 'focus'; id: string | null }\n\nexport interface NavMenuInit {\n open?: string[]\n focused?: string | null\n disabled?: boolean\n}\n\nexport function init(opts: NavMenuInit = {}): NavMenuState {\n return {\n open: opts.open ?? [],\n focused: opts.focused ?? null,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(state: NavMenuState, msg: NavMenuMsg): [NavMenuState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'openBranch': {\n // Close any siblings of `id` at the same ancestor path, then add it.\n // Sibling detection: an entry is a sibling if its ancestor set matches\n // msg.ancestorIds and it isn't msg.id. We don't track ancestors in\n // state, so: filter `open` to keep only entries that are themselves\n // an ancestor of msg.id, plus msg.id.\n const keep = new Set([...msg.ancestorIds, msg.id])\n const open = state.open.filter((o) => keep.has(o))\n if (!open.includes(msg.id)) open.push(msg.id)\n return [{ ...state, open }, []]\n }\n case 'closeBranch': {\n // Close this branch and any descendants that follow it in the open\n // list. Since open is ordered root-first, descendants come after.\n const idx = state.open.indexOf(msg.id)\n if (idx === -1) return [state, []]\n const open = state.open.slice(0, idx)\n return [{ ...state, open }, []]\n }\n case 'toggleBranch':\n if (state.open.includes(msg.id)) {\n return update(state, { type: 'closeBranch', id: msg.id })\n }\n return update(state, { type: 'openBranch', id: msg.id, ancestorIds: msg.ancestorIds })\n case 'closeAll':\n return [{ ...state, open: [] }, []]\n case 'focus':\n return [{ ...state, focused: msg.id }, []]\n }\n}\n\nexport function isOpen(state: NavMenuState, id: string): boolean {\n return state.open.includes(id)\n}\n\nexport interface NavItemParts<S> {\n trigger: {\n type: 'button'\n role: 'menuitem'\n id: string\n 'aria-haspopup': 'menu' | undefined\n 'aria-expanded': (s: S) => boolean | undefined\n 'data-scope': 'navigation-menu'\n 'data-part': 'trigger'\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-value': string\n tabIndex: (s: S) => number\n onClick: (e: MouseEvent) => void\n onPointerEnter: (e: PointerEvent) => void\n onFocus: (e: FocusEvent) => void\n }\n content: {\n role: 'menu'\n id: string\n 'aria-labelledby': string\n 'data-scope': 'navigation-menu'\n 'data-part': 'content'\n 'data-state': (s: S) => 'open' | 'closed'\n hidden: (s: S) => boolean\n onPointerEnter: (e: PointerEvent) => void\n }\n}\n\nexport interface NavMenuParts<S> {\n root: {\n role: 'menubar'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'navigation-menu'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n onPointerLeave: (e: PointerEvent) => void\n onPointerEnter: (e: PointerEvent) => void\n }\n item: (id: string, options: { isBranch: boolean; ancestorIds?: string[] }) => NavItemParts<S>\n}\n\nexport interface ConnectOptions {\n id: string\n label?: string\n /**\n * Whether pointer-leaving the whole menu closes everything. Default: true.\n * The consumer can inject their own close delay by intercepting\n * onPointerLeave + calling setTimeout + dispatching closeAll.\n */\n closeOnLeave?: boolean\n}\n\nexport function connect<S>(\n get: (s: S) => NavMenuState,\n send: Send<NavMenuMsg>,\n opts: ConnectOptions,\n): NavMenuParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const triggerId = (v: string): string => `${opts.id}:trigger:${v}`\n const contentId = (v: string): string => `${opts.id}:content:${v}`\n const closeOnLeave = opts.closeOnLeave !== false\n let closeTimer: ReturnType<typeof setTimeout> | null = null\n\n const scheduleClose = (): void => {\n if (!closeOnLeave) return\n if (closeTimer) clearTimeout(closeTimer)\n closeTimer = setTimeout(() => {\n send({ type: 'closeAll' })\n closeTimer = null\n }, 150)\n }\n\n const cancelClose = (): void => {\n if (closeTimer) {\n clearTimeout(closeTimer)\n closeTimer = null\n }\n }\n\n return {\n root: {\n role: 'menubar',\n 'aria-label': opts.label ?? ((s: S) => locale(s).navigationMenu.label),\n 'data-scope': 'navigation-menu',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n onPointerLeave: () => scheduleClose(),\n onPointerEnter: () => cancelClose(),\n },\n item: (id: string, options: { isBranch: boolean; ancestorIds?: string[] }): NavItemParts<S> => {\n const ancestorIds = options.ancestorIds ?? []\n return {\n trigger: {\n type: 'button',\n role: 'menuitem',\n id: triggerId(id),\n 'aria-haspopup': options.isBranch ? 'menu' : undefined,\n 'aria-expanded': (s) => (options.isBranch ? isOpen(get(s), id) : undefined),\n 'data-scope': 'navigation-menu',\n 'data-part': 'trigger',\n 'data-state': (s) => (isOpen(get(s), id) ? 'open' : 'closed'),\n 'data-value': id,\n tabIndex: (s) => (get(s).focused === id ? 0 : -1),\n onClick: () => {\n if (options.isBranch) {\n send({ type: 'toggleBranch', id, ancestorIds })\n }\n },\n onPointerEnter: () => {\n cancelClose()\n if (options.isBranch) {\n send({ type: 'openBranch', id, ancestorIds })\n }\n },\n onFocus: () => send({ type: 'focus', id }),\n },\n content: {\n role: 'menu',\n id: contentId(id),\n 'aria-labelledby': triggerId(id),\n 'data-scope': 'navigation-menu',\n 'data-part': 'content',\n 'data-state': (s) => (isOpen(get(s), id) ? 'open' : 'closed'),\n hidden: (s) => !isOpen(get(s), id),\n onPointerEnter: () => {\n cancelClose()\n if (options.isBranch) {\n send({ type: 'openBranch', id, ancestorIds })\n }\n },\n },\n }\n },\n }\n}\n\nexport const navigationMenu = { init, update, connect, isOpen }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useContext } from '@llui/dom';
|
|
2
|
-
import { LocaleContext } from '../locale';
|
|
2
|
+
import { LocaleContext } from '../locale.js';
|
|
3
3
|
export function init(opts = {}) {
|
|
4
4
|
const value = opts.value ?? null;
|
|
5
5
|
return {
|
|
@@ -179,3 +179,4 @@ export function connect(get, send, opts = {}) {
|
|
|
179
179
|
};
|
|
180
180
|
}
|
|
181
181
|
export const numberInput = { init, update, connect };
|
|
182
|
+
//# sourceMappingURL=number-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"number-input.js","sourceRoot":"","sources":["../../src/components/number-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Number input — numeric field with increment/decrement buttons. Clamps\n * to min/max and snaps to step. Keyboard: Arrow Up/Down, PageUp/PageDown,\n * Home/End.\n */\n\nexport interface NumberInputState {\n value: number | null\n min: number\n max: number\n step: number\n disabled: boolean\n readOnly: boolean\n /** Allow a free-text input value while the user is typing. */\n rawText: string\n}\n\nexport type NumberInputMsg =\n | { type: 'setValue'; value: number | null }\n | { type: 'setRawText'; text: string }\n | { type: 'commit' }\n | { type: 'increment'; multiplier?: number }\n | { type: 'decrement'; multiplier?: number }\n | { type: 'toMin' }\n | { type: 'toMax' }\n | { type: 'setDisabled'; disabled: boolean }\n\nexport interface NumberInputInit {\n value?: number | null\n min?: number\n max?: number\n step?: number\n disabled?: boolean\n readOnly?: boolean\n}\n\nexport function init(opts: NumberInputInit = {}): NumberInputState {\n const value = opts.value ?? null\n return {\n value,\n min: opts.min ?? -Infinity,\n max: opts.max ?? Infinity,\n step: opts.step ?? 1,\n disabled: opts.disabled ?? false,\n readOnly: opts.readOnly ?? false,\n rawText: value === null ? '' : String(value),\n }\n}\n\nfunction clamp(n: number, min: number, max: number): number {\n if (n < min) return min\n if (n > max) return max\n return n\n}\n\nfunction snap(n: number, step: number, anchor = 0): number {\n if (step <= 0) return n\n const origin = isFinite(anchor) ? anchor : 0\n const decimals = decimalPlaces(step)\n const steps = Math.round((n - origin) / step)\n const snapped = origin + steps * step\n return Number(snapped.toFixed(decimals))\n}\n\nfunction decimalPlaces(n: number): number {\n if (Math.floor(n) === n) return 0\n const str = n.toString()\n const dot = str.indexOf('.')\n return dot === -1 ? 0 : str.length - dot - 1\n}\n\nexport function update(state: NumberInputState, msg: NumberInputMsg): [NumberInputState, never[]] {\n if (msg.type !== 'setDisabled' && (state.disabled || state.readOnly)) {\n // Allow setRawText for controlled typing? No — disabled means no interaction.\n return [state, []]\n }\n switch (msg.type) {\n case 'setValue': {\n const v =\n msg.value === null\n ? null\n : clamp(snap(msg.value, state.step, state.min), state.min, state.max)\n return [{ ...state, value: v, rawText: v === null ? '' : String(v) }, []]\n }\n case 'setRawText':\n return [{ ...state, rawText: msg.text }, []]\n case 'commit': {\n const parsed = parseFloat(state.rawText)\n if (isNaN(parsed))\n return [{ ...state, rawText: state.value === null ? '' : String(state.value) }, []]\n const v = clamp(snap(parsed, state.step, state.min), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'increment': {\n const base = state.value ?? 0\n const raw = base + state.step * (msg.multiplier ?? 1)\n const decimals = decimalPlaces(state.step)\n const v = clamp(Number(raw.toFixed(decimals)), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'decrement': {\n const base = state.value ?? 0\n const raw = base - state.step * (msg.multiplier ?? 1)\n const decimals = decimalPlaces(state.step)\n const v = clamp(Number(raw.toFixed(decimals)), state.min, state.max)\n return [{ ...state, value: v, rawText: String(v) }, []]\n }\n case 'toMin':\n return [{ ...state, value: state.min, rawText: String(state.min) }, []]\n case 'toMax':\n return [{ ...state, value: state.max, rawText: String(state.max) }, []]\n case 'setDisabled':\n return [{ ...state, disabled: msg.disabled }, []]\n }\n}\n\nexport interface NumberInputParts<S> {\n root: {\n 'data-scope': 'number-input'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n }\n input: {\n type: 'text'\n role: 'spinbutton'\n inputMode: 'decimal'\n 'aria-valuemin': (s: S) => number | undefined\n 'aria-valuemax': (s: S) => number | undefined\n 'aria-valuenow': (s: S) => number | undefined\n 'aria-disabled': (s: S) => 'true' | undefined\n 'aria-readonly': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n readOnly: (s: S) => boolean\n value: (s: S) => string\n 'data-scope': 'number-input'\n 'data-part': 'input'\n onInput: (e: Event) => void\n onBlur: (e: FocusEvent) => void\n onKeyDown: (e: KeyboardEvent) => void\n }\n increment: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'number-input'\n 'data-part': 'increment'\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n }\n decrement: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'number-input'\n 'data-part': 'decrement'\n tabIndex: -1\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n incrementLabel?: string\n decrementLabel?: string\n /** Validate the numeric value before committing. Non-empty array blocks setValue. */\n validate?: (value: number) => string[] | null\n}\n\nexport function connect<S>(\n get: (s: S) => NumberInputState,\n send: Send<NumberInputMsg>,\n opts: ConnectOptions = {},\n): NumberInputParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const incrementLabel: string | ((s: S) => string) =\n opts.incrementLabel ?? ((s: S) => locale(s).numberInput.increment)\n const decrementLabel: string | ((s: S) => string) =\n opts.decrementLabel ?? ((s: S) => locale(s).numberInput.decrement)\n const validate = opts.validate\n\n const trySetValue = (value: number) => {\n if (validate) {\n const errors = validate(value)\n if (errors && errors.length > 0) return\n }\n send({ type: 'setValue', value })\n }\n\n return {\n root: {\n 'data-scope': 'number-input',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n input: {\n type: 'text',\n role: 'spinbutton',\n inputMode: 'decimal',\n 'aria-valuemin': (s) => (isFinite(get(s).min) ? get(s).min : undefined),\n 'aria-valuemax': (s) => (isFinite(get(s).max) ? get(s).max : undefined),\n 'aria-valuenow': (s) => get(s).value ?? undefined,\n 'aria-disabled': (s) => (get(s).disabled ? 'true' : undefined),\n 'aria-readonly': (s) => (get(s).readOnly ? 'true' : undefined),\n disabled: (s) => get(s).disabled,\n readOnly: (s) => get(s).readOnly,\n value: (s) => get(s).rawText,\n 'data-scope': 'number-input',\n 'data-part': 'input',\n onInput: (e) => {\n const text = (e.target as HTMLInputElement).value\n send({ type: 'setRawText', text })\n const parsed = parseFloat(text)\n if (!isNaN(parsed)) trySetValue(parsed)\n },\n onBlur: () => send({ type: 'commit' }),\n onKeyDown: (e) => {\n switch (e.key) {\n case 'ArrowUp':\n e.preventDefault()\n send({ type: 'increment' })\n return\n case 'ArrowDown':\n e.preventDefault()\n send({ type: 'decrement' })\n return\n case 'PageUp':\n e.preventDefault()\n send({ type: 'increment', multiplier: 10 })\n return\n case 'PageDown':\n e.preventDefault()\n send({ type: 'decrement', multiplier: 10 })\n return\n case 'Home':\n e.preventDefault()\n send({ type: 'toMin' })\n return\n case 'End':\n e.preventDefault()\n send({ type: 'toMax' })\n return\n case 'Enter':\n e.preventDefault()\n send({ type: 'commit' })\n return\n }\n },\n },\n increment: {\n type: 'button',\n 'aria-label': incrementLabel,\n 'aria-disabled': (s) =>\n get(s).disabled || get(s).readOnly || (get(s).value ?? 0) >= get(s).max\n ? 'true'\n : undefined,\n disabled: (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) >= get(s).max,\n 'data-scope': 'number-input',\n 'data-part': 'increment',\n tabIndex: -1,\n onClick: () => send({ type: 'increment' }),\n },\n decrement: {\n type: 'button',\n 'aria-label': decrementLabel,\n 'aria-disabled': (s) =>\n get(s).disabled || get(s).readOnly || (get(s).value ?? 0) <= get(s).min\n ? 'true'\n : undefined,\n disabled: (s) => get(s).disabled || get(s).readOnly || (get(s).value ?? 0) <= get(s).min,\n 'data-scope': 'number-input',\n 'data-part': 'decrement',\n tabIndex: -1,\n onClick: () => send({ type: 'decrement' }),\n },\n }\n}\n\nexport const numberInput = { init, update, connect }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useContext } from '@llui/dom';
|
|
2
|
-
import { LocaleContext, en } from '../locale';
|
|
2
|
+
import { LocaleContext, en } from '../locale.js';
|
|
3
3
|
export function init(opts = {}) {
|
|
4
4
|
return {
|
|
5
5
|
page: opts.page ?? 1,
|
|
@@ -136,3 +136,4 @@ export function connect(get, send, opts = {}) {
|
|
|
136
136
|
};
|
|
137
137
|
}
|
|
138
138
|
export const pagination = { init, update, connect, totalPages, pageItems };
|
|
139
|
+
//# sourceMappingURL=pagination.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.js","sourceRoot":"","sources":["../../src/components/pagination.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext } from '@llui/dom'\nimport { LocaleContext, en } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Pagination — page navigation with ellipses for large ranges.\n * `page` is 1-based. Siblings are the count of pages shown on each side\n * of the current page. Boundaries are shown at the start/end.\n */\n\nexport interface PaginationState {\n page: number\n pageSize: number\n total: number\n siblings: number\n boundaries: number\n disabled: boolean\n}\n\nexport type PaginationMsg =\n | { type: 'goTo'; page: number }\n | { type: 'next' }\n | { type: 'prev' }\n | { type: 'first' }\n | { type: 'last' }\n | { type: 'setPageSize'; pageSize: number }\n | { type: 'setTotal'; total: number }\n\nexport interface PaginationInit {\n page?: number\n pageSize?: number\n total?: number\n siblings?: number\n boundaries?: number\n disabled?: boolean\n}\n\nexport function init(opts: PaginationInit = {}): PaginationState {\n return {\n page: opts.page ?? 1,\n pageSize: opts.pageSize ?? 10,\n total: opts.total ?? 0,\n siblings: opts.siblings ?? 1,\n boundaries: opts.boundaries ?? 1,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function totalPages(state: PaginationState): number {\n if (state.pageSize <= 0 || state.total <= 0) return 0\n return Math.max(1, Math.ceil(state.total / state.pageSize))\n}\n\nfunction clampPage(page: number, total: number): number {\n if (total === 0) return 1\n return Math.max(1, Math.min(page, total))\n}\n\nexport function update(state: PaginationState, msg: PaginationMsg): [PaginationState, never[]] {\n if (state.disabled) return [state, []]\n const pages = totalPages(state)\n switch (msg.type) {\n case 'goTo':\n return [{ ...state, page: clampPage(msg.page, pages) }, []]\n case 'next':\n return [{ ...state, page: clampPage(state.page + 1, pages) }, []]\n case 'prev':\n return [{ ...state, page: clampPage(state.page - 1, pages) }, []]\n case 'first':\n return [{ ...state, page: 1 }, []]\n case 'last':\n return [{ ...state, page: pages }, []]\n case 'setPageSize': {\n // Preserve first visible item when pageSize changes\n const firstItem = (state.page - 1) * state.pageSize\n const nextPage = Math.floor(firstItem / msg.pageSize) + 1\n const nextPages = Math.max(1, Math.ceil(state.total / msg.pageSize))\n return [{ ...state, pageSize: msg.pageSize, page: Math.min(nextPage, nextPages) }, []]\n }\n case 'setTotal': {\n const nextPages = Math.max(1, Math.ceil(msg.total / state.pageSize))\n return [{ ...state, total: msg.total, page: Math.min(state.page, nextPages) }, []]\n }\n }\n}\n\nexport type PageItem =\n | { type: 'page'; page: number }\n | { type: 'ellipsis'; position: 'start' | 'end' }\n\n/**\n * Compute the visible page buttons with ellipses:\n * `[first ..boundaries] … [siblings around current] … [boundaries ..last]`.\n */\nexport function pageItems(state: PaginationState): PageItem[] {\n const pages = totalPages(state)\n if (pages === 0) return []\n\n // Build the set of pages we want to show: first boundary, last boundary,\n // and current ± siblings.\n const pageSet = new Set<number>()\n for (let i = 1; i <= Math.min(state.boundaries, pages); i++) pageSet.add(i)\n for (let i = Math.max(pages - state.boundaries + 1, 1); i <= pages; i++) pageSet.add(i)\n const start = Math.max(1, state.page - state.siblings)\n const end = Math.min(pages, state.page + state.siblings)\n for (let i = start; i <= end; i++) pageSet.add(i)\n\n // Emit items in order, inserting ellipses for gaps > 1.\n const sorted = [...pageSet].sort((a, b) => a - b)\n const items: PageItem[] = []\n for (let i = 0; i < sorted.length; i++) {\n const page = sorted[i]!\n items.push({ type: 'page', page })\n if (i < sorted.length - 1 && sorted[i + 1]! - page > 1) {\n items.push({ type: 'ellipsis', position: page < state.page ? 'start' : 'end' })\n }\n }\n return items\n}\n\nexport interface PaginationParts<S> {\n root: {\n role: 'navigation'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'pagination'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n }\n prevTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'pagination'\n 'data-part': 'prev-trigger'\n onClick: (e: MouseEvent) => void\n }\n nextTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'aria-disabled': (s: S) => 'true' | undefined\n disabled: (s: S) => boolean\n 'data-scope': 'pagination'\n 'data-part': 'next-trigger'\n onClick: (e: MouseEvent) => void\n }\n item: (page: number) => {\n type: 'button'\n 'aria-label': string\n 'aria-current': (s: S) => 'page' | undefined\n 'data-selected': (s: S) => '' | undefined\n 'data-scope': 'pagination'\n 'data-part': 'item'\n 'data-value': string\n onClick: (e: MouseEvent) => void\n }\n ellipsis: (position: 'start' | 'end') => {\n 'aria-hidden': 'true'\n 'data-scope': 'pagination'\n 'data-part': 'ellipsis'\n 'data-position': 'start' | 'end'\n }\n}\n\nexport interface ConnectOptions {\n label?: string\n prevLabel?: string\n nextLabel?: string\n pageLabel?: (page: number) => string\n}\n\nexport function connect<S>(\n get: (s: S) => PaginationState,\n send: Send<PaginationMsg>,\n opts: ConnectOptions = {},\n): PaginationParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const label: string | ((s: S) => string) = opts.label ?? ((s: S) => locale(s).pagination.label)\n const prevLabel: string | ((s: S) => string) =\n opts.prevLabel ?? ((s: S) => locale(s).pagination.prev)\n const nextLabel: string | ((s: S) => string) =\n opts.nextLabel ?? ((s: S) => locale(s).pagination.next)\n const pageLabel = opts.pageLabel ?? en.pagination.page\n\n return {\n root: {\n role: 'navigation',\n 'aria-label': label,\n 'data-scope': 'pagination',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n prevTrigger: {\n type: 'button',\n 'aria-label': prevLabel,\n 'aria-disabled': (s) => (get(s).page <= 1 || get(s).disabled ? 'true' : undefined),\n disabled: (s) => get(s).page <= 1 || get(s).disabled,\n 'data-scope': 'pagination',\n 'data-part': 'prev-trigger',\n onClick: () => send({ type: 'prev' }),\n },\n nextTrigger: {\n type: 'button',\n 'aria-label': nextLabel,\n 'aria-disabled': (s) => {\n const st = get(s)\n return st.page >= totalPages(st) || st.disabled ? 'true' : undefined\n },\n disabled: (s) => {\n const st = get(s)\n return st.page >= totalPages(st) || st.disabled\n },\n 'data-scope': 'pagination',\n 'data-part': 'next-trigger',\n onClick: () => send({ type: 'next' }),\n },\n item: (page: number) => ({\n type: 'button',\n 'aria-label': pageLabel(page),\n 'aria-current': (s) => (get(s).page === page ? 'page' : undefined),\n 'data-selected': (s) => (get(s).page === page ? '' : undefined),\n 'data-scope': 'pagination',\n 'data-part': 'item',\n 'data-value': String(page),\n onClick: () => send({ type: 'goTo', page }),\n }),\n ellipsis: (position: 'start' | 'end') => ({\n 'aria-hidden': 'true',\n 'data-scope': 'pagination',\n 'data-part': 'ellipsis',\n 'data-position': position,\n }),\n }\n}\n\nexport const pagination = { init, update, connect, totalPages, pageItems }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useContext } from '@llui/dom';
|
|
2
|
-
import { LocaleContext } from '../locale';
|
|
2
|
+
import { LocaleContext } from '../locale.js';
|
|
3
3
|
export function init(opts = {}) {
|
|
4
4
|
return {
|
|
5
5
|
value: opts.value ?? '',
|
|
@@ -55,3 +55,4 @@ export function connect(get, send, opts = {}) {
|
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
export const passwordInput = { init, update, connect };
|
|
58
|
+
//# sourceMappingURL=password-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"password-input.js","sourceRoot":"","sources":["../../src/components/password-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * Password input — text input with show/hide visibility toggle.\n */\n\nexport interface PasswordInputState {\n value: string\n visible: boolean\n disabled: boolean\n}\n\nexport type PasswordInputMsg =\n | { type: 'setValue'; value: string }\n | { type: 'toggleVisibility' }\n | { type: 'setVisible'; visible: boolean }\n\nexport interface PasswordInputInit {\n value?: string\n visible?: boolean\n disabled?: boolean\n}\n\nexport function init(opts: PasswordInputInit = {}): PasswordInputState {\n return {\n value: opts.value ?? '',\n visible: opts.visible ?? false,\n disabled: opts.disabled ?? false,\n }\n}\n\nexport function update(\n state: PasswordInputState,\n msg: PasswordInputMsg,\n): [PasswordInputState, never[]] {\n if (state.disabled && msg.type !== 'setValue') return [state, []]\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value }, []]\n case 'toggleVisibility':\n return [{ ...state, visible: !state.visible }, []]\n case 'setVisible':\n return [{ ...state, visible: msg.visible }, []]\n }\n}\n\nexport interface PasswordInputParts<S> {\n root: {\n 'data-scope': 'password-input'\n 'data-part': 'root'\n 'data-visible': (s: S) => '' | undefined\n 'data-disabled': (s: S) => '' | undefined\n }\n input: {\n type: (s: S) => 'text' | 'password'\n autoComplete: string\n disabled: (s: S) => boolean\n value: (s: S) => string\n 'data-scope': 'password-input'\n 'data-part': 'input'\n onInput: (e: Event) => void\n }\n visibilityTrigger: {\n type: 'button'\n 'aria-label': (s: S) => string\n 'aria-pressed': (s: S) => boolean\n disabled: (s: S) => boolean\n tabIndex: -1\n 'data-scope': 'password-input'\n 'data-part': 'visibility-trigger'\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n autoComplete?: string\n showLabel?: string\n hideLabel?: string\n}\n\nexport function connect<S>(\n get: (s: S) => PasswordInputState,\n send: Send<PasswordInputMsg>,\n opts: ConnectOptions = {},\n): PasswordInputParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const autoComplete = opts.autoComplete ?? 'current-password'\n const showLabel = opts.showLabel\n const hideLabel = opts.hideLabel\n\n return {\n root: {\n 'data-scope': 'password-input',\n 'data-part': 'root',\n 'data-visible': (s) => (get(s).visible ? '' : undefined),\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n input: {\n type: (s) => (get(s).visible ? 'text' : 'password'),\n autoComplete,\n disabled: (s) => get(s).disabled,\n value: (s) => get(s).value,\n 'data-scope': 'password-input',\n 'data-part': 'input',\n onInput: (e) => send({ type: 'setValue', value: (e.target as HTMLInputElement).value }),\n },\n visibilityTrigger: {\n type: 'button',\n 'aria-label': (s) =>\n get(s).visible\n ? (hideLabel ?? locale(s).passwordInput.hide)\n : (showLabel ?? locale(s).passwordInput.show),\n 'aria-pressed': (s) => get(s).visible,\n disabled: (s) => get(s).disabled,\n tabIndex: -1,\n 'data-scope': 'password-input',\n 'data-part': 'visibility-trigger',\n onClick: () => send({ type: 'toggleVisibility' }),\n },\n }\n}\n\nexport const passwordInput = { init, update, connect }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { flipArrow } from '../utils/direction';
|
|
2
|
-
import { en } from '../locale';
|
|
1
|
+
import { flipArrow } from '../utils/direction.js';
|
|
2
|
+
import { en } from '../locale.js';
|
|
3
3
|
export function init(opts = {}) {
|
|
4
4
|
const length = opts.length ?? 4;
|
|
5
5
|
const values = opts.values ?? new Array(length).fill('');
|
|
@@ -140,3 +140,4 @@ export function connect(get, send, opts) {
|
|
|
140
140
|
};
|
|
141
141
|
}
|
|
142
142
|
export const pinInput = { init, update, connect, isComplete, getValue };
|
|
143
|
+
//# sourceMappingURL=pin-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pin-input.js","sourceRoot":"","sources":["../../src/components/pin-input.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { flipArrow } from '../utils/direction.js'\nimport { en } from '../locale.js'\n\n/**\n * Pin input — a sequence of single-character fields for OTP codes, etc.\n * Auto-advances on input, handles backspace to previous field, supports\n * paste-to-fill across multiple fields.\n */\n\nexport type PinType = 'numeric' | 'alphanumeric' | 'alphabetic'\n\nexport interface PinInputState {\n values: string[]\n length: number\n type: PinType\n mask: boolean\n disabled: boolean\n focusedIndex: number\n}\n\nexport type PinInputMsg =\n | { type: 'setValue'; index: number; value: string }\n | { type: 'setAll'; values: string[] }\n | { type: 'focus'; index: number }\n | { type: 'clear' }\n | { type: 'backspace'; index: number }\n\nexport interface PinInputInit {\n length?: number\n type?: PinType\n mask?: boolean\n disabled?: boolean\n values?: string[]\n}\n\nexport function init(opts: PinInputInit = {}): PinInputState {\n const length = opts.length ?? 4\n const values = opts.values ?? new Array<string>(length).fill('')\n return {\n values,\n length,\n type: opts.type ?? 'numeric',\n mask: opts.mask ?? false,\n disabled: opts.disabled ?? false,\n focusedIndex: 0,\n }\n}\n\nfunction sanitize(char: string, type: PinType): string {\n if (char.length !== 1) return ''\n if (type === 'numeric' && !/\\d/.test(char)) return ''\n if (type === 'alphabetic' && !/[a-zA-Z]/.test(char)) return ''\n if (type === 'alphanumeric' && !/[a-zA-Z0-9]/.test(char)) return ''\n return char\n}\n\nexport function update(state: PinInputState, msg: PinInputMsg): [PinInputState, never[]] {\n if (state.disabled) return [state, []]\n switch (msg.type) {\n case 'setValue': {\n const char = sanitize(msg.value.slice(-1), state.type)\n if (!char && msg.value !== '') return [state, []]\n const values = [...state.values]\n values[msg.index] = char\n // Auto-advance\n const nextIndex = char ? Math.min(msg.index + 1, state.length - 1) : msg.index\n return [{ ...state, values, focusedIndex: nextIndex }, []]\n }\n case 'setAll': {\n const values = new Array<string>(state.length).fill('')\n for (let i = 0; i < Math.min(msg.values.length, state.length); i++) {\n values[i] = sanitize(msg.values[i]!, state.type)\n }\n const lastFilled = values.findIndex((v) => v === '')\n const focusedIndex = lastFilled === -1 ? state.length - 1 : lastFilled\n return [{ ...state, values, focusedIndex }, []]\n }\n case 'focus':\n return [{ ...state, focusedIndex: Math.max(0, Math.min(msg.index, state.length - 1)) }, []]\n case 'clear':\n return [{ ...state, values: new Array<string>(state.length).fill(''), focusedIndex: 0 }, []]\n case 'backspace': {\n const values = [...state.values]\n if (values[msg.index]) {\n values[msg.index] = ''\n return [{ ...state, values }, []]\n }\n // Field is empty — move focus back and clear prior\n const prev = Math.max(0, msg.index - 1)\n values[prev] = ''\n return [{ ...state, values, focusedIndex: prev }, []]\n }\n }\n}\n\nexport function isComplete(state: PinInputState): boolean {\n return state.values.every((v) => v !== '')\n}\n\nexport function getValue(state: PinInputState): string {\n return state.values.join('')\n}\n\nexport interface PinInputParts<S> {\n root: {\n role: 'group'\n 'aria-labelledby': string\n 'data-scope': 'pin-input'\n 'data-part': 'root'\n 'data-disabled': (s: S) => '' | undefined\n }\n label: {\n id: string\n 'data-scope': 'pin-input'\n 'data-part': 'label'\n }\n /** Props for the input at a given index. */\n input: (index: number) => {\n type: (s: S) => 'text' | 'password'\n inputMode: (s: S) => 'numeric' | 'text'\n pattern: (s: S) => string\n maxLength: 1\n autoComplete: 'off'\n 'aria-label': string\n disabled: (s: S) => boolean\n value: (s: S) => string\n 'data-scope': 'pin-input'\n 'data-part': 'input'\n 'data-index': string\n onInput: (e: Event) => void\n onKeyDown: (e: KeyboardEvent) => void\n onFocus: (e: FocusEvent) => void\n onPaste: (e: ClipboardEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n id: string\n inputLabel?: (index: number) => string\n /** Validate each character before setting. Non-empty array blocks setDigit. */\n validate?: (value: string) => string[] | null\n}\n\nexport function connect<S>(\n get: (s: S) => PinInputState,\n send: Send<PinInputMsg>,\n opts: ConnectOptions,\n): PinInputParts<S> {\n const labelId = `${opts.id}:label`\n const inputLabel = opts.inputLabel ?? en.pinInput.input\n const validate = opts.validate\n\n return {\n root: {\n role: 'group',\n 'aria-labelledby': labelId,\n 'data-scope': 'pin-input',\n 'data-part': 'root',\n 'data-disabled': (s) => (get(s).disabled ? '' : undefined),\n },\n label: {\n id: labelId,\n 'data-scope': 'pin-input',\n 'data-part': 'label',\n },\n input: (index: number) => ({\n type: (s) => (get(s).mask ? 'password' : 'text'),\n inputMode: (s) => (get(s).type === 'numeric' ? 'numeric' : 'text'),\n pattern: (s) => {\n switch (get(s).type) {\n case 'numeric':\n return '[0-9]*'\n case 'alphabetic':\n return '[a-zA-Z]*'\n case 'alphanumeric':\n return '[a-zA-Z0-9]*'\n }\n },\n maxLength: 1,\n autoComplete: 'off',\n 'aria-label': inputLabel(index),\n disabled: (s) => get(s).disabled,\n value: (s) => get(s).values[index] ?? '',\n 'data-scope': 'pin-input',\n 'data-part': 'input',\n 'data-index': String(index),\n onInput: (e) => {\n const value = (e.target as HTMLInputElement).value\n if (validate && value !== '') {\n const errors = validate(value.slice(-1))\n if (errors && errors.length > 0) return\n }\n send({ type: 'setValue', index, value })\n },\n onKeyDown: (e) => {\n const key = flipArrow(e.key, e.currentTarget as Element)\n if (key === 'Backspace') {\n send({ type: 'backspace', index })\n } else if (key === 'ArrowLeft') {\n e.preventDefault()\n send({ type: 'focus', index: index - 1 })\n } else if (key === 'ArrowRight') {\n e.preventDefault()\n send({ type: 'focus', index: index + 1 })\n }\n },\n onFocus: () => send({ type: 'focus', index }),\n onPaste: (e) => {\n e.preventDefault()\n const text = e.clipboardData?.getData('text') ?? ''\n send({ type: 'setAll', values: text.split('') })\n },\n }),\n }\n}\n\nexport const pinInput = { init, update, connect, isComplete, getValue }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Send, TransitionOptions } from '@llui/dom';
|
|
2
|
-
import { type Placement } from '../utils/floating';
|
|
2
|
+
import { type Placement } from '../utils/floating.js';
|
|
3
3
|
/**
|
|
4
4
|
* Popover — click-triggered, non-modal floating overlay anchored to its
|
|
5
5
|
* trigger. Use for menus, date pickers, color pickers, filters, etc.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/components/popover.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAMxD,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/components/popover.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { show, portal, onMount, div, useContext } from '@llui/dom';
|
|
2
|
-
import { LocaleContext } from '../locale';
|
|
3
|
-
import { pushDismissable } from '../utils/dismissable';
|
|
4
|
-
import { pushFocusTrap } from '../utils/focus-trap';
|
|
5
|
-
import { attachFloating } from '../utils/floating';
|
|
2
|
+
import { LocaleContext } from '../locale.js';
|
|
3
|
+
import { pushDismissable } from '../utils/dismissable.js';
|
|
4
|
+
import { pushFocusTrap } from '../utils/focus-trap.js';
|
|
5
|
+
import { attachFloating } from '../utils/floating.js';
|
|
6
6
|
export function init(opts = {}) {
|
|
7
7
|
return { open: opts.open ?? false };
|
|
8
8
|
}
|
|
@@ -146,3 +146,4 @@ export function overlay(opts) {
|
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
148
|
export const popover = { init, update, connect, overlay };
|
|
149
|
+
//# sourceMappingURL=popover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover.js","sourceRoot":"","sources":["../../src/components/popover.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send, TransitionOptions } from '@llui/dom'\nimport { show, portal, onMount, div, useContext } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\nimport { pushDismissable } from '../utils/dismissable.js'\nimport { pushFocusTrap } from '../utils/focus-trap.js'\nimport { attachFloating, type Placement } from '../utils/floating.js'\n\n/**\n * Popover — click-triggered, non-modal floating overlay anchored to its\n * trigger. Use for menus, date pickers, color pickers, filters, etc.\n *\n * Like dialog, has a pure state machine + a view helper (`overlay()`) that\n * wires floating-ui positioning, dismissable, and optional focus trapping.\n */\n\nexport interface PopoverState {\n open: boolean\n}\n\nexport type PopoverMsg =\n | { type: 'open' }\n | { type: 'close' }\n | { type: 'toggle' }\n | { type: 'setOpen'; open: boolean }\n\nexport interface PopoverInit {\n open?: boolean\n}\n\nexport function init(opts: PopoverInit = {}): PopoverState {\n return { open: opts.open ?? false }\n}\n\nexport function update(state: PopoverState, msg: PopoverMsg): [PopoverState, never[]] {\n switch (msg.type) {\n case 'open':\n return [{ ...state, open: true }, []]\n case 'close':\n return [{ ...state, open: false }, []]\n case 'toggle':\n return [{ ...state, open: !state.open }, []]\n case 'setOpen':\n return [{ ...state, open: msg.open }, []]\n }\n}\n\nexport interface PopoverParts<S> {\n trigger: {\n type: 'button'\n 'aria-haspopup': 'dialog'\n 'aria-expanded': (s: S) => boolean\n 'aria-controls': string\n id: string\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'popover'\n 'data-part': 'trigger'\n onClick: (e: MouseEvent) => void\n }\n positioner: {\n 'data-scope': 'popover'\n 'data-part': 'positioner'\n style: string\n }\n content: {\n role: 'dialog'\n id: string\n 'aria-labelledby': string\n tabIndex: -1\n 'data-state': (s: S) => 'open' | 'closed'\n 'data-scope': 'popover'\n 'data-part': 'content'\n }\n title: {\n id: string\n 'data-scope': 'popover'\n 'data-part': 'title'\n }\n description: {\n id: string\n 'data-scope': 'popover'\n 'data-part': 'description'\n }\n arrow: {\n 'data-scope': 'popover'\n 'data-part': 'arrow'\n }\n closeTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'popover'\n 'data-part': 'close-trigger'\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n id: string\n closeLabel?: string\n}\n\nexport function connect<S>(\n get: (s: S) => PopoverState,\n send: Send<PopoverMsg>,\n opts: ConnectOptions,\n): PopoverParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const base = opts.id\n const triggerId = `${base}:trigger`\n const contentId = `${base}:content`\n const titleId = `${base}:title`\n const descId = `${base}:description`\n const closeLabel: string | ((s: S) => string) =\n opts.closeLabel ?? ((s: S) => locale(s).popover.close)\n\n return {\n trigger: {\n type: 'button',\n 'aria-haspopup': 'dialog',\n 'aria-expanded': (s) => get(s).open,\n 'aria-controls': contentId,\n id: triggerId,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'popover',\n 'data-part': 'trigger',\n onClick: () => send({ type: 'toggle' }),\n },\n positioner: {\n 'data-scope': 'popover',\n 'data-part': 'positioner',\n style: 'position:absolute;top:0;left:0;',\n },\n content: {\n role: 'dialog',\n id: contentId,\n 'aria-labelledby': titleId,\n tabIndex: -1,\n 'data-state': (s) => (get(s).open ? 'open' : 'closed'),\n 'data-scope': 'popover',\n 'data-part': 'content',\n },\n title: {\n id: titleId,\n 'data-scope': 'popover',\n 'data-part': 'title',\n },\n description: {\n id: descId,\n 'data-scope': 'popover',\n 'data-part': 'description',\n },\n arrow: {\n 'data-scope': 'popover',\n 'data-part': 'arrow',\n },\n closeTrigger: {\n type: 'button',\n 'aria-label': closeLabel,\n 'data-scope': 'popover',\n 'data-part': 'close-trigger',\n onClick: () => send({ type: 'close' }),\n },\n }\n}\n\nexport interface OverlayOptions<S> {\n get: (s: S) => PopoverState\n send: Send<PopoverMsg>\n parts: PopoverParts<S>\n content: () => Node[]\n /** Placement preference — bottom | top | right | left with -start/-end variants. */\n placement?: Placement\n /** Offset between trigger and content, px (default: 8). */\n offset?: number\n /** Auto-flip to opposite side (default: true). */\n flip?: boolean\n /** Shift to keep in viewport (default: true). */\n shift?: boolean\n /** Optional transition. */\n transition?: TransitionOptions\n /** Close on Escape (default: true). */\n closeOnEscape?: boolean\n /** Close on outside click (default: true). */\n closeOnOutsideClick?: boolean\n /** Trap focus inside popover while open (default: false — non-modal). */\n trapFocus?: boolean\n /** Restore focus to trigger on close (default: true). */\n restoreFocus?: boolean\n /** Portal target (default: 'body'). */\n target?: string | HTMLElement\n /** Arrow element selector within content (optional). */\n arrowSelector?: string\n}\n\nexport function overlay<S>(opts: OverlayOptions<S>): Node[] {\n const target = opts.target ?? 'body'\n const placement = opts.placement ?? 'bottom'\n const offset = opts.offset ?? 8\n const flip = opts.flip !== false\n const shift = opts.shift !== false\n const closeOnEscape = opts.closeOnEscape !== false\n const closeOnOutsideClick = opts.closeOnOutsideClick !== false\n const trapFocus = opts.trapFocus === true\n const restoreFocus = opts.restoreFocus !== false\n const parts = opts.parts\n const contentId = parts.content.id\n const triggerId = parts.trigger.id\n\n return show<S, PopoverMsg>({\n when: (s) => opts.get(s).open,\n render: () =>\n portal({\n target,\n render: () => {\n onMount(() => {\n const contentEl = document.getElementById(contentId)\n const triggerEl = document.getElementById(triggerId)\n if (!contentEl || !triggerEl) return\n\n const cleanups: Array<() => void> = []\n\n // Position content relative to trigger\n const positioner = contentEl.closest('[data-part=\"positioner\"]') as HTMLElement | null\n const floatingEl = positioner ?? contentEl\n const arrow = opts.arrowSelector\n ? (contentEl.querySelector(opts.arrowSelector) as HTMLElement | null)\n : null\n cleanups.push(\n attachFloating({\n anchor: triggerEl,\n floating: floatingEl,\n placement,\n offset,\n flip,\n shift,\n arrow: arrow ?? undefined,\n }),\n )\n\n if (trapFocus) {\n cleanups.push(\n pushFocusTrap({\n container: contentEl,\n restoreFocus,\n }),\n )\n }\n\n if (closeOnEscape || closeOnOutsideClick) {\n cleanups.push(\n pushDismissable({\n element: contentEl,\n ignore: () => [triggerEl],\n disableEscape: !closeOnEscape,\n disableOutside: !closeOnOutsideClick,\n onDismiss: () => {\n opts.send({ type: 'close' })\n if (restoreFocus) triggerEl.focus()\n },\n }),\n )\n }\n\n return () => {\n for (let i = cleanups.length - 1; i >= 0; i--) cleanups[i]!()\n }\n })\n return [div(parts.positioner, opts.content())]\n },\n }),\n enter: opts.transition?.enter,\n leave: opts.transition?.leave,\n })\n}\n\nexport const popover = { init, update, connect, overlay }\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presence.js","sourceRoot":"","sources":["../../src/components/presence.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\n\n/**\n * Presence — track mount/unmount lifecycle with exit-delay support.\n *\n * In many components (dialogs, tooltips, menus) the consumer wants to:\n * 1. close the overlay (fire exit animation)\n * 2. keep it mounted long enough for the animation to finish\n * 3. unmount it\n *\n * LLui already provides `@llui/transitions` for most of this, but a\n * presence machine is useful when you want to coordinate multiple\n * elements or expose state outside the transition primitive.\n *\n * State flow:\n * closed → (open) → opening → open\n * open → (close) → closing → closed\n *\n * The consumer fires `animationEnd` to advance past opening/closing.\n * If `unmountOnExit` is true, `closed` means \"safe to remove from DOM\";\n * otherwise the element stays mounted even when closed (display:none).\n */\n\nexport type PresenceStatus = 'closed' | 'opening' | 'open' | 'closing'\n\nexport interface PresenceState {\n status: PresenceStatus\n unmountOnExit: boolean\n}\n\nexport type PresenceMsg =\n | { type: 'open' }\n | { type: 'close' }\n | { type: 'toggle' }\n | { type: 'animationEnd' }\n | { type: 'setPresent'; present: boolean }\n\nexport interface PresenceInit {\n /** Initial presence — true starts in 'open', false starts in 'closed'. */\n present?: boolean\n /** Whether 'closed' means \"unmount\" (true) or \"hidden but mounted\" (false). Default: true. */\n unmountOnExit?: boolean\n}\n\nexport function init(opts: PresenceInit = {}): PresenceState {\n return {\n status: opts.present ? 'open' : 'closed',\n unmountOnExit: opts.unmountOnExit ?? true,\n }\n}\n\nexport function update(state: PresenceState, msg: PresenceMsg): [PresenceState, never[]] {\n switch (msg.type) {\n case 'open':\n if (state.status === 'open' || state.status === 'opening') return [state, []]\n return [{ ...state, status: 'opening' }, []]\n case 'close':\n if (state.status === 'closed' || state.status === 'closing') return [state, []]\n return [{ ...state, status: 'closing' }, []]\n case 'toggle': {\n const present = state.status === 'open' || state.status === 'opening'\n return update(state, { type: present ? 'close' : 'open' })\n }\n case 'animationEnd':\n if (state.status === 'opening') return [{ ...state, status: 'open' }, []]\n if (state.status === 'closing') return [{ ...state, status: 'closed' }, []]\n return [state, []]\n case 'setPresent':\n return [{ ...state, status: msg.present ? 'open' : 'closed' }, []]\n }\n}\n\n/** Whether the element should be in the DOM (mounted). */\nexport function isMounted(state: PresenceState): boolean {\n if (!state.unmountOnExit) return true\n return state.status !== 'closed'\n}\n\n/** Whether the element is visible (not running an exit animation). */\nexport function isVisible(state: PresenceState): boolean {\n return state.status === 'open' || state.status === 'opening'\n}\n\nexport function isAnimating(state: PresenceState): boolean {\n return state.status === 'opening' || state.status === 'closing'\n}\n\nexport interface PresenceParts<S> {\n root: {\n 'data-scope': 'presence'\n 'data-part': 'root'\n 'data-state': (s: S) => PresenceStatus\n hidden: (s: S) => boolean\n onAnimationEnd: (e: AnimationEvent) => void\n onTransitionEnd: (e: TransitionEvent) => void\n }\n}\n\nexport function connect<S>(\n get: (s: S) => PresenceState,\n send: Send<PresenceMsg>,\n): PresenceParts<S> {\n const onEnd = (): void => send({ type: 'animationEnd' })\n return {\n root: {\n 'data-scope': 'presence',\n 'data-part': 'root',\n 'data-state': (s) => get(s).status,\n hidden: (s) => (get(s).status === 'closed' && !get(s).unmountOnExit ? true : false),\n onAnimationEnd: onEnd,\n onTransitionEnd: onEnd,\n },\n }\n}\n\nexport const presence = { init, update, connect, isMounted, isVisible, isAnimating }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { en } from '../locale';
|
|
1
|
+
import { en } from '../locale.js';
|
|
2
2
|
export function init(opts = {}) {
|
|
3
3
|
return {
|
|
4
4
|
value: 'value' in opts ? opts.value : 0,
|
|
@@ -79,3 +79,4 @@ function rangeStyle(state) {
|
|
|
79
79
|
return state.orientation === 'horizontal' ? `width:${clamped}%;` : `height:${clamped}%;`;
|
|
80
80
|
}
|
|
81
81
|
export const progress = { init, update, connect, percent, valueState };
|
|
82
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/components/progress.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { en } from '../locale.js'\n\n/**\n * Progress — linear or circular progress indicator. Determinate (0..max) or\n * indeterminate (`value: null`).\n */\n\nexport type ProgressOrientation = 'horizontal' | 'vertical'\n\nexport interface ProgressState {\n value: number | null\n min: number\n max: number\n orientation: ProgressOrientation\n}\n\nexport type ProgressMsg =\n | { type: 'setValue'; value: number | null }\n | { type: 'setMax'; max: number }\n\nexport interface ProgressInit {\n value?: number | null\n min?: number\n max?: number\n orientation?: ProgressOrientation\n}\n\nexport function init(opts: ProgressInit = {}): ProgressState {\n return {\n value: 'value' in opts ? (opts.value as number | null) : 0,\n min: opts.min ?? 0,\n max: opts.max ?? 100,\n orientation: opts.orientation ?? 'horizontal',\n }\n}\n\nexport function update(state: ProgressState, msg: ProgressMsg): [ProgressState, never[]] {\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value }, []]\n case 'setMax':\n return [{ ...state, max: msg.max }, []]\n }\n}\n\nexport function percent(state: ProgressState): number | null {\n if (state.value === null) return null\n const range = state.max - state.min\n if (range <= 0) return 0\n return ((state.value - state.min) / range) * 100\n}\n\nexport function valueState(state: ProgressState): 'indeterminate' | 'complete' | 'loading' {\n if (state.value === null) return 'indeterminate'\n if (state.value >= state.max) return 'complete'\n return 'loading'\n}\n\nexport interface ProgressParts<S> {\n root: {\n role: 'progressbar'\n 'aria-valuemin': (s: S) => number\n 'aria-valuemax': (s: S) => number\n 'aria-valuenow': (s: S) => number | undefined\n 'aria-label': string | undefined\n 'data-state': (s: S) => 'indeterminate' | 'complete' | 'loading'\n 'data-orientation': (s: S) => ProgressOrientation\n 'data-scope': 'progress'\n 'data-part': 'root'\n }\n track: {\n 'data-state': (s: S) => 'indeterminate' | 'complete' | 'loading'\n 'data-orientation': (s: S) => ProgressOrientation\n 'data-scope': 'progress'\n 'data-part': 'track'\n }\n range: {\n 'data-state': (s: S) => 'indeterminate' | 'complete' | 'loading'\n 'data-orientation': (s: S) => ProgressOrientation\n 'data-scope': 'progress'\n 'data-part': 'range'\n style: (s: S) => string\n }\n label: {\n 'data-scope': 'progress'\n 'data-part': 'label'\n }\n valueText: (s: S) => string\n}\n\nexport interface ConnectOptions {\n label?: string\n /** Custom formatter for value text. */\n format?: (value: number | null, max: number) => string\n}\n\nexport function connect<S>(\n get: (s: S) => ProgressState,\n _send: Send<ProgressMsg>,\n opts: ConnectOptions = {},\n): ProgressParts<S> {\n const label = opts.label\n const format = opts.format ?? defaultFormat\n\n return {\n root: {\n role: 'progressbar',\n 'aria-valuemin': (s) => get(s).min,\n 'aria-valuemax': (s) => get(s).max,\n 'aria-valuenow': (s) => get(s).value ?? undefined,\n 'aria-label': label,\n 'data-state': (s) => valueState(get(s)),\n 'data-orientation': (s) => get(s).orientation,\n 'data-scope': 'progress',\n 'data-part': 'root',\n },\n track: {\n 'data-state': (s) => valueState(get(s)),\n 'data-orientation': (s) => get(s).orientation,\n 'data-scope': 'progress',\n 'data-part': 'track',\n },\n range: {\n 'data-state': (s) => valueState(get(s)),\n 'data-orientation': (s) => get(s).orientation,\n 'data-scope': 'progress',\n 'data-part': 'range',\n style: (s) => rangeStyle(get(s)),\n },\n label: {\n 'data-scope': 'progress',\n 'data-part': 'label',\n },\n valueText: (s) => format(get(s).value, get(s).max),\n }\n}\n\nfunction defaultFormat(value: number | null, max: number): string {\n if (value === null) return en.progress.loading\n const pct = Math.round((value / max) * 100)\n return `${pct}%`\n}\n\nfunction rangeStyle(state: ProgressState): string {\n const p = percent(state)\n if (p === null) return ''\n const clamped = Math.max(0, Math.min(100, p))\n return state.orientation === 'horizontal' ? `width:${clamped}%;` : `height:${clamped}%;`\n}\n\nexport const progress = { init, update, connect, percent, valueState }\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useContext } from '@llui/dom';
|
|
2
|
-
import { LocaleContext } from '../locale';
|
|
2
|
+
import { LocaleContext } from '../locale.js';
|
|
3
3
|
export function init(opts = {}) {
|
|
4
4
|
return {
|
|
5
5
|
value: opts.value ?? '',
|
|
@@ -109,3 +109,4 @@ export function connect(get, send, opts = {}) {
|
|
|
109
109
|
};
|
|
110
110
|
}
|
|
111
111
|
export const qrCode = { init, update, connect, size, toSvgPath, toDataUrl };
|
|
112
|
+
//# sourceMappingURL=qr-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qr-code.js","sourceRoot":"","sources":["../../src/components/qr-code.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Send } from '@llui/dom'\nimport { useContext } from '@llui/dom'\nimport { LocaleContext } from '../locale.js'\nimport type { Locale } from '../locale.js'\n\n/**\n * QR code — renders a QR matrix as SVG. llui does not bundle a QR\n * encoder (encoders are sizable and consumer apps typically already\n * have one); instead, the consumer provides the encoded matrix via\n * `setMatrix` (or through the optional `encode` callback on\n * ConnectOptions, invoked when the value changes).\n *\n * Minimum usage with a BYOE (bring-your-own-encoder) library — the\n * consumer dispatches `setMatrix` with the encoded bits from their\n * update handler:\n *\n * import QRCode from 'qrcode-generator'\n *\n * update: (state, msg) => {\n * if (msg.type === 'updateQr') {\n * const q = QRCode(0, state.qr.errorCorrection)\n * q.addData(msg.value); q.make()\n * const n = q.getModuleCount()\n * const matrix: boolean[][] = []\n * for (let y = 0; y < n; y++) {\n * const row: boolean[] = []\n * for (let x = 0; x < n; x++) row.push(q.isDark(y, x))\n * matrix.push(row)\n * }\n * return [{ ...state, qr: { ...state.qr, value: msg.value, matrix } }, []]\n * }\n * }\n */\n\nexport type ErrorCorrectionLevel = 'L' | 'M' | 'Q' | 'H'\n\nexport interface QrCodeState {\n value: string\n /** NxN boolean matrix — true means dark (filled) module. */\n matrix: boolean[][]\n errorCorrection: ErrorCorrectionLevel\n}\n\nexport type QrCodeMsg =\n | { type: 'setValue'; value: string }\n | { type: 'setMatrix'; matrix: boolean[][] }\n | { type: 'setErrorCorrection'; level: ErrorCorrectionLevel }\n\nexport interface QrCodeInit {\n value?: string\n matrix?: boolean[][]\n errorCorrection?: ErrorCorrectionLevel\n}\n\nexport function init(opts: QrCodeInit = {}): QrCodeState {\n return {\n value: opts.value ?? '',\n matrix: opts.matrix ?? [],\n errorCorrection: opts.errorCorrection ?? 'M',\n }\n}\n\nexport function update(state: QrCodeState, msg: QrCodeMsg): [QrCodeState, never[]] {\n switch (msg.type) {\n case 'setValue':\n return [{ ...state, value: msg.value }, []]\n case 'setMatrix':\n return [{ ...state, matrix: msg.matrix }, []]\n case 'setErrorCorrection':\n return [{ ...state, errorCorrection: msg.level }, []]\n }\n}\n\n/** Matrix side length (in modules). Returns 0 for empty matrix. */\nexport function size(state: QrCodeState): number {\n return state.matrix.length\n}\n\n/**\n * Compute an SVG path string that fills every dark module. Each dark\n * module becomes a unit-sized square at (col, row) coordinates in module\n * space; the caller scales via `viewBox` or CSS. Using a single path\n * is vastly more performant than rendering N² individual <rect>s.\n */\nexport function toSvgPath(matrix: boolean[][]): string {\n const parts: string[] = []\n for (let y = 0; y < matrix.length; y++) {\n const row = matrix[y]!\n for (let x = 0; x < row.length; x++) {\n if (row[x]) parts.push(`M${x},${y}h1v1h-1z`)\n }\n }\n return parts.join('')\n}\n\n/**\n * Encode the matrix as a monochrome 1-bit-per-pixel PNG-ish URL. This\n * is a helper for <img src> consumption — it generates a `data:image/svg+xml`\n * URL (SVG is simpler and scales losslessly).\n */\nexport function toDataUrl(\n matrix: boolean[][],\n foreground: string = '#000',\n background: string = '#fff',\n): string {\n const s = matrix.length\n if (s === 0) return ''\n const path = toSvgPath(matrix)\n const svg =\n `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 ${s} ${s}\" shape-rendering=\"crispEdges\">` +\n `<rect width=\"${s}\" height=\"${s}\" fill=\"${background}\"/>` +\n `<path d=\"${path}\" fill=\"${foreground}\"/>` +\n `</svg>`\n return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`\n}\n\nexport interface QrCodeParts<S> {\n root: {\n 'data-scope': 'qr-code'\n 'data-part': 'root'\n 'aria-label': string | ((s: S) => string)\n }\n svg: {\n 'data-scope': 'qr-code'\n 'data-part': 'svg'\n role: 'img'\n viewBox: (s: S) => string\n 'shape-rendering': 'crispEdges'\n }\n background: {\n 'data-scope': 'qr-code'\n 'data-part': 'background'\n }\n foreground: {\n 'data-scope': 'qr-code'\n 'data-part': 'foreground'\n d: (s: S) => string\n }\n downloadTrigger: {\n type: 'button'\n 'aria-label': string | ((s: S) => string)\n 'data-scope': 'qr-code'\n 'data-part': 'download-trigger'\n onClick: (e: MouseEvent) => void\n }\n}\n\nexport interface ConnectOptions {\n label?: string\n downloadLabel?: string\n /** Filename for the downloaded SVG. */\n downloadFilename?: string\n}\n\nexport function connect<S>(\n get: (s: S) => QrCodeState,\n send: Send<QrCodeMsg>,\n opts: ConnectOptions = {},\n): QrCodeParts<S> {\n const locale = useContext<S, Locale>(LocaleContext)\n const label: string | ((s: S) => string) = opts.label ?? ((s: S) => locale(s).qrCode.label)\n const filename = opts.downloadFilename ?? 'qrcode.svg'\n\n return {\n root: {\n 'data-scope': 'qr-code',\n 'data-part': 'root',\n 'aria-label': label,\n },\n svg: {\n 'data-scope': 'qr-code',\n 'data-part': 'svg',\n role: 'img',\n viewBox: (s) => {\n const n = size(get(s))\n return n > 0 ? `0 0 ${n} ${n}` : '0 0 1 1'\n },\n 'shape-rendering': 'crispEdges',\n },\n background: {\n 'data-scope': 'qr-code',\n 'data-part': 'background',\n },\n foreground: {\n 'data-scope': 'qr-code',\n 'data-part': 'foreground',\n d: (s) => toSvgPath(get(s).matrix),\n },\n downloadTrigger: {\n type: 'button',\n 'aria-label': opts.downloadLabel ?? ((s: S) => locale(s).qrCode.download),\n 'data-scope': 'qr-code',\n 'data-part': 'download-trigger',\n onClick: () => {\n // Generate an SVG blob and trigger a download via a hidden link.\n // State isn't accessible here; caller should use the current value\n // in a DOM query or run this inside a closure with state access.\n // We dispatch a best-effort via the document for now.\n const root = document.querySelector<HTMLElement>('[data-scope=\"qr-code\"][data-part=\"svg\"]')\n if (!root) return\n const xml = new XMLSerializer().serializeToString(root)\n const blob = new Blob([xml], { type: 'image/svg+xml' })\n const url = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = url\n a.download = filename\n a.click()\n URL.revokeObjectURL(url)\n },\n },\n }\n}\n\nexport const qrCode = { init, update, connect, size, toSvgPath, toDataUrl }\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { flipArrow } from '../utils/direction';
|
|
1
|
+
import { flipArrow } from '../utils/direction.js';
|
|
2
2
|
export function init(opts = {}) {
|
|
3
3
|
return {
|
|
4
4
|
value: opts.value ?? null,
|
|
@@ -161,3 +161,4 @@ export function connect(get, send, opts) {
|
|
|
161
161
|
};
|
|
162
162
|
}
|
|
163
163
|
export const radioGroup = { init, update, connect };
|
|
164
|
+
//# sourceMappingURL=radio-group.js.map
|