@vielzeug/refine 1.7.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -12
- package/dist/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +2 -5
- package/dist/_dev.js.map +1 -1
- package/dist/_virtual/_rolldown/runtime.cjs +1 -1
- package/dist/accordion-item.cjs +26 -24
- package/dist/accordion-item.cjs.map +1 -1
- package/dist/accordion-item.js +53 -51
- package/dist/accordion-item.js.map +1 -1
- package/dist/accordion.cjs +3 -1
- package/dist/accordion.cjs.map +1 -1
- package/dist/accordion.js +5 -3
- package/dist/accordion.js.map +1 -1
- package/dist/alert.cjs +1 -1
- package/dist/alert.cjs.map +1 -1
- package/dist/alert.js +1 -1
- package/dist/alert.js.map +1 -1
- package/dist/async.cjs +14 -12
- package/dist/async.cjs.map +1 -1
- package/dist/async.js +5 -4
- package/dist/async.js.map +1 -1
- package/dist/avatar-group.cjs +7 -0
- package/dist/avatar-group.cjs.map +1 -0
- package/dist/avatar-group.js +34 -0
- package/dist/avatar-group.js.map +1 -0
- package/dist/avatar.cjs +21 -16
- package/dist/avatar.cjs.map +1 -1
- package/dist/avatar.js +38 -54
- package/dist/avatar.js.map +1 -1
- package/dist/badge.cjs +4 -2
- package/dist/badge.cjs.map +1 -1
- package/dist/badge.js +6 -4
- package/dist/badge.js.map +1 -1
- package/dist/box.cjs +3 -1
- package/dist/box.cjs.map +1 -1
- package/dist/box.js +24 -18
- package/dist/box.js.map +1 -1
- package/dist/breadcrumb.cjs +4 -4
- package/dist/breadcrumb.cjs.map +1 -1
- package/dist/breadcrumb.js +4 -4
- package/dist/breadcrumb.js.map +1 -1
- package/dist/button-group.cjs +3 -3
- package/dist/button-group.cjs.map +1 -1
- package/dist/button-group.js +18 -16
- package/dist/button-group.js.map +1 -1
- package/dist/button.cjs +16 -12
- package/dist/button.cjs.map +1 -1
- package/dist/button.js +31 -28
- package/dist/button.js.map +1 -1
- package/dist/calendar.cjs +94 -69
- package/dist/calendar.cjs.map +1 -1
- package/dist/calendar.js +131 -99
- package/dist/calendar.js.map +1 -1
- package/dist/card.cjs +7 -7
- package/dist/card.cjs.map +1 -1
- package/dist/card.js +53 -49
- package/dist/card.js.map +1 -1
- package/dist/carousel.cjs +65 -57
- package/dist/carousel.cjs.map +1 -1
- package/dist/carousel.js +157 -201
- package/dist/carousel.js.map +1 -1
- package/dist/chat-message.cjs +21 -19
- package/dist/chat-message.cjs.map +1 -1
- package/dist/chat-message.js +18 -15
- package/dist/chat-message.js.map +1 -1
- package/dist/checkbox-group.cjs +12 -10
- package/dist/checkbox-group.cjs.map +1 -1
- package/dist/checkbox-group.js +75 -77
- package/dist/checkbox-group.js.map +1 -1
- package/dist/checkbox.cjs +4 -4
- package/dist/checkbox.cjs.map +1 -1
- package/dist/checkbox.js +55 -55
- package/dist/checkbox.js.map +1 -1
- package/dist/chip.cjs +22 -20
- package/dist/chip.cjs.map +1 -1
- package/dist/chip.js +15 -12
- package/dist/chip.js.map +1 -1
- package/dist/code-window.cjs +11 -5
- package/dist/code-window.cjs.map +1 -1
- package/dist/code-window.js +9 -4
- package/dist/code-window.js.map +1 -1
- package/dist/combobox.cjs +63 -58
- package/dist/combobox.cjs.map +1 -1
- package/dist/combobox.js +199 -197
- package/dist/combobox.js.map +1 -1
- package/dist/command-palette.cjs +49 -29
- package/dist/command-palette.cjs.map +1 -1
- package/dist/command-palette.js +150 -119
- package/dist/command-palette.js.map +1 -1
- package/dist/content/avatar/avatar-group.d.ts +33 -0
- package/dist/content/avatar/avatar-group.d.ts.map +1 -0
- package/dist/content/avatar/avatar.d.ts +0 -32
- package/dist/content/avatar/avatar.d.ts.map +1 -1
- package/dist/content/card/card.css.cjs +1 -1
- package/dist/content/card/card.css.cjs.map +1 -1
- package/dist/content/card/card.css.js +1 -1
- package/dist/content/card/card.css.js.map +1 -1
- package/dist/content/card/card.d.ts.map +1 -1
- package/dist/content/carousel/carousel-slide.cjs +3 -1
- package/dist/content/carousel/carousel-slide.cjs.map +1 -1
- package/dist/content/carousel/carousel-slide.css.cjs +1 -1
- package/dist/content/carousel/carousel-slide.css.cjs.map +1 -1
- package/dist/content/carousel/carousel-slide.css.js +1 -1
- package/dist/content/carousel/carousel-slide.css.js.map +1 -1
- package/dist/content/carousel/carousel-slide.js +3 -1
- package/dist/content/carousel/carousel-slide.js.map +1 -1
- package/dist/content/carousel/carousel.css.cjs +1 -1
- package/dist/content/carousel/carousel.css.cjs.map +1 -1
- package/dist/content/carousel/carousel.css.js +1 -1
- package/dist/content/carousel/carousel.css.js.map +1 -1
- package/dist/content/carousel/carousel.d.ts +5 -19
- package/dist/content/carousel/carousel.d.ts.map +1 -1
- package/dist/content/chat-message/chat-message.d.ts.map +1 -1
- package/dist/content/code-window/code-window.d.ts.map +1 -1
- package/dist/content/icon/icon.d.ts.map +1 -1
- package/dist/content/index.d.ts +10 -2
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/list/_list-item-reveal.cjs +1 -1
- package/dist/content/list/_list-item-reveal.cjs.map +1 -1
- package/dist/content/list/_list-item-reveal.d.ts +2 -2
- package/dist/content/list/_list-item-reveal.d.ts.map +1 -1
- package/dist/content/list/_list-item-reveal.js +2 -2
- package/dist/content/list/_list-item-reveal.js.map +1 -1
- package/dist/content/list/list.d.ts.map +1 -1
- package/dist/content/marquee/index.d.ts +2 -0
- package/dist/content/marquee/index.d.ts.map +1 -0
- package/dist/content/marquee/marquee.css.cjs +2 -0
- package/dist/content/marquee/marquee.css.cjs.map +1 -0
- package/dist/content/marquee/marquee.css.js +6 -0
- package/dist/content/marquee/marquee.css.js.map +1 -0
- package/dist/content/marquee/marquee.d.ts +44 -0
- package/dist/content/marquee/marquee.d.ts.map +1 -0
- package/dist/content/stepper/_is-step-navigable.cjs +2 -0
- package/dist/content/stepper/_is-step-navigable.cjs.map +1 -0
- package/dist/content/stepper/_is-step-navigable.d.ts +14 -0
- package/dist/content/stepper/_is-step-navigable.d.ts.map +1 -0
- package/dist/content/stepper/_is-step-navigable.js +8 -0
- package/dist/content/stepper/_is-step-navigable.js.map +1 -0
- package/dist/content/stepper/step.css.cjs +2 -0
- package/dist/content/stepper/step.css.cjs.map +1 -0
- package/dist/content/stepper/step.css.js +6 -0
- package/dist/content/stepper/step.css.js.map +1 -0
- package/dist/content/stepper/step.d.ts +63 -0
- package/dist/content/stepper/step.d.ts.map +1 -0
- package/dist/content/stepper/stepper.css.cjs +2 -0
- package/dist/content/stepper/stepper.css.cjs.map +1 -0
- package/dist/content/stepper/stepper.css.js +6 -0
- package/dist/content/stepper/stepper.css.js.map +1 -0
- package/dist/content/stepper/stepper.d.ts +88 -0
- package/dist/content/stepper/stepper.d.ts.map +1 -0
- package/dist/copy-command.cjs +9 -3
- package/dist/copy-command.cjs.map +1 -1
- package/dist/copy-command.js +9 -3
- package/dist/copy-command.js.map +1 -1
- package/dist/{headless → core}/_internal.d.ts +3 -5
- package/dist/core/_internal.d.ts.map +1 -0
- package/dist/core/announcer.cjs.map +1 -0
- package/dist/core/announcer.d.ts.map +1 -0
- package/dist/{headless → core}/announcer.js +1 -1
- package/dist/core/announcer.js.map +1 -0
- package/dist/core/aria-reflection.cjs.map +1 -0
- package/dist/core/aria-reflection.d.ts.map +1 -0
- package/dist/{headless → core}/aria-reflection.js +1 -1
- package/dist/core/aria-reflection.js.map +1 -0
- package/dist/core/auto-resize.cjs.map +1 -0
- package/dist/core/auto-resize.d.ts.map +1 -0
- package/dist/{headless → core}/auto-resize.js +1 -1
- package/dist/core/auto-resize.js.map +1 -0
- package/dist/core/checkable.cjs.map +1 -0
- package/dist/core/checkable.d.ts.map +1 -0
- package/dist/{headless → core}/checkable.js +1 -1
- package/dist/core/checkable.js.map +1 -0
- package/dist/core/choice-field.cjs +2 -0
- package/dist/core/choice-field.cjs.map +1 -0
- package/dist/core/choice-field.d.ts.map +1 -0
- package/dist/{headless → core}/choice-field.js +3 -2
- package/dist/core/choice-field.js.map +1 -0
- package/dist/core/composer.cjs.map +1 -0
- package/dist/core/composer.d.ts.map +1 -0
- package/dist/{headless → core}/composer.js +1 -1
- package/dist/core/composer.js.map +1 -0
- package/dist/{headless → core}/date-picker.cjs +1 -1
- package/dist/core/date-picker.cjs.map +1 -0
- package/dist/core/date-picker.d.ts.map +1 -0
- package/dist/{headless → core}/date-picker.js +3 -3
- package/dist/core/date-picker.js.map +1 -0
- package/dist/core/direction.cjs.map +1 -0
- package/dist/core/direction.d.ts.map +1 -0
- package/dist/{headless → core}/direction.js +1 -1
- package/dist/core/direction.js.map +1 -0
- package/dist/core/field-base.cjs +2 -0
- package/dist/core/field-base.cjs.map +1 -0
- package/dist/{headless → core}/field-base.d.ts +3 -3
- package/dist/core/field-base.d.ts.map +1 -0
- package/dist/core/field-base.js +66 -0
- package/dist/core/field-base.js.map +1 -0
- package/dist/core/focus.cjs.map +1 -0
- package/dist/core/focus.d.ts.map +1 -0
- package/dist/{headless → core}/focus.js +1 -1
- package/dist/core/focus.js.map +1 -0
- package/dist/{headless → core}/index.d.ts +7 -6
- package/dist/core/index.d.ts.map +1 -0
- package/dist/{headless → core}/keyboard.cjs +1 -1
- package/dist/core/keyboard.cjs.map +1 -0
- package/dist/core/keyboard.d.ts.map +1 -0
- package/dist/{headless → core}/keyboard.js +2 -2
- package/dist/core/keyboard.js.map +1 -0
- package/dist/core/light-dom.cjs.map +1 -0
- package/dist/core/light-dom.d.ts.map +1 -0
- package/dist/{headless → core}/light-dom.js +1 -1
- package/dist/core/light-dom.js.map +1 -0
- package/dist/core/nav.cjs.map +1 -0
- package/dist/core/nav.d.ts.map +1 -0
- package/dist/{headless → core}/nav.js +1 -1
- package/dist/core/nav.js.map +1 -0
- package/dist/core/numbers.cjs.map +1 -0
- package/dist/core/numbers.d.ts.map +1 -0
- package/dist/{headless → core}/numbers.js +1 -1
- package/dist/core/numbers.js.map +1 -0
- package/dist/core/option-list.cjs +2 -0
- package/dist/core/option-list.cjs.map +1 -0
- package/dist/core/option-list.d.ts +49 -0
- package/dist/core/option-list.d.ts.map +1 -0
- package/dist/core/option-list.js +65 -0
- package/dist/core/option-list.js.map +1 -0
- package/dist/core/ore.cjs.map +1 -0
- package/dist/{headless → core}/ore.d.ts +2 -2
- package/dist/core/ore.d.ts.map +1 -0
- package/dist/{headless → core}/ore.js +1 -1
- package/dist/core/ore.js.map +1 -0
- package/dist/core/overlay.cjs +2 -0
- package/dist/core/overlay.cjs.map +1 -0
- package/dist/core/overlay.d.ts +41 -0
- package/dist/core/overlay.d.ts.map +1 -0
- package/dist/core/overlay.js +17 -0
- package/dist/core/overlay.js.map +1 -0
- package/dist/core/paginated-list.d.ts.map +1 -0
- package/dist/core/parse.cjs.map +1 -0
- package/dist/core/parse.d.ts.map +1 -0
- package/dist/{headless → core}/parse.js +1 -1
- package/dist/core/parse.js.map +1 -0
- package/dist/core/positioner.cjs +2 -0
- package/dist/core/positioner.cjs.map +1 -0
- package/dist/core/positioner.d.ts.map +1 -0
- package/dist/{headless → core}/positioner.js +7 -7
- package/dist/core/positioner.js.map +1 -0
- package/dist/core/ref-callback.cjs +2 -0
- package/dist/core/ref-callback.cjs.map +1 -0
- package/dist/core/ref-callback.d.ts.map +1 -0
- package/dist/{headless → core}/ref-callback.js +2 -2
- package/dist/core/ref-callback.js.map +1 -0
- package/dist/core/signals.cjs +2 -0
- package/dist/core/signals.cjs.map +1 -0
- package/dist/core/signals.d.ts.map +1 -0
- package/dist/{headless → core}/signals.js +3 -2
- package/dist/core/signals.js.map +1 -0
- package/dist/core/slider.cjs +2 -0
- package/dist/core/slider.cjs.map +1 -0
- package/dist/core/slider.d.ts.map +1 -0
- package/dist/{headless → core}/slider.js +3 -3
- package/dist/{headless/slider.cjs.map → core/slider.js.map} +1 -1
- package/dist/core/spinner.cjs +2 -0
- package/dist/core/spinner.cjs.map +1 -0
- package/dist/core/spinner.d.ts.map +1 -0
- package/dist/{headless → core}/spinner.js +3 -3
- package/dist/{headless/spinner.cjs.map → core/spinner.js.map} +1 -1
- package/dist/core/swipe.cjs.map +1 -0
- package/dist/core/swipe.d.ts.map +1 -0
- package/dist/{headless → core}/swipe.js +1 -1
- package/dist/core/swipe.js.map +1 -0
- package/dist/core/text-field.cjs.map +1 -0
- package/dist/core/text-field.d.ts.map +1 -0
- package/dist/{headless → core}/text-field.js +1 -1
- package/dist/core/text-field.js.map +1 -0
- package/dist/core/typeahead.cjs.map +1 -0
- package/dist/core/typeahead.d.ts.map +1 -0
- package/dist/{headless → core}/typeahead.js +1 -1
- package/dist/core/typeahead.js.map +1 -0
- package/dist/custom-elements.json +4433 -3949
- package/dist/datagrid.cjs +320 -271
- package/dist/datagrid.cjs.map +1 -1
- package/dist/datagrid.js +489 -435
- package/dist/datagrid.js.map +1 -1
- package/dist/date-picker.cjs +77 -62
- package/dist/date-picker.cjs.map +1 -1
- package/dist/date-picker.js +169 -146
- package/dist/date-picker.js.map +1 -1
- package/dist/dialog.cjs +3 -3
- package/dist/dialog.cjs.map +1 -1
- package/dist/dialog.js +18 -7
- package/dist/dialog.js.map +1 -1
- package/dist/disclosure/tab-panel/tab-panel.d.ts.map +1 -1
- package/dist/disclosure/tabs/tabs.d.ts.map +1 -1
- package/dist/drawer.cjs +5 -5
- package/dist/drawer.cjs.map +1 -1
- package/dist/drawer.js +52 -47
- package/dist/drawer.js.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/feedback/async/async.d.ts.map +1 -1
- package/dist/feedback/chip/chip.d.ts.map +1 -1
- package/dist/feedback/progress/progress.d.ts.map +1 -1
- package/dist/feedback/skeleton/skeleton.d.ts.map +1 -1
- package/dist/feedback/toast/index.d.ts +1 -1
- package/dist/feedback/toast/index.d.ts.map +1 -1
- package/dist/feedback/toast/toast.d.ts +16 -68
- package/dist/feedback/toast/toast.d.ts.map +1 -1
- package/dist/feedback/typing-indicator/typing-indicator.d.ts +1 -1
- package/dist/file-input.cjs +111 -78
- package/dist/file-input.cjs.map +1 -1
- package/dist/file-input.js +220 -184
- package/dist/file-input.js.map +1 -1
- package/dist/grid-item.cjs +3 -1
- package/dist/grid-item.cjs.map +1 -1
- package/dist/grid-item.js +3 -1
- package/dist/grid-item.js.map +1 -1
- package/dist/grid.cjs +3 -1
- package/dist/grid.cjs.map +1 -1
- package/dist/grid.js +6 -5
- package/dist/grid.js.map +1 -1
- package/dist/icon.cjs +5 -1
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.js +50 -47
- package/dist/icon.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +7 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -67
- package/dist/input.cjs +44 -40
- package/dist/input.cjs.map +1 -1
- package/dist/input.js +132 -130
- package/dist/input.js.map +1 -1
- package/dist/inputs/button-group/button-group.css.cjs +1 -1
- package/dist/inputs/button-group/button-group.css.cjs.map +1 -1
- package/dist/inputs/button-group/button-group.css.js +1 -1
- package/dist/inputs/button-group/button-group.css.js.map +1 -1
- package/dist/inputs/button-group/button-group.d.ts +6 -3
- package/dist/inputs/button-group/button-group.d.ts.map +1 -1
- package/dist/inputs/calendar/calendar.d.ts.map +1 -1
- package/dist/inputs/checkbox/checkbox.d.ts +6 -5
- package/dist/inputs/checkbox/checkbox.d.ts.map +1 -1
- package/dist/inputs/checkbox-group/checkbox-group.d.ts +1 -1
- package/dist/inputs/checkbox-group/checkbox-group.d.ts.map +1 -1
- package/dist/inputs/combobox/combobox.d.ts +4 -2
- package/dist/inputs/combobox/combobox.d.ts.map +1 -1
- package/dist/inputs/combobox/combobox.types.d.ts +5 -7
- package/dist/inputs/combobox/combobox.types.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-column.cjs +1 -1
- package/dist/inputs/datagrid/datagrid-column.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid-column.d.ts +1 -1
- package/dist/inputs/datagrid/datagrid-column.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-column.js +5 -5
- package/dist/inputs/datagrid/datagrid-column.js.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs +2 -0
- package/dist/inputs/datagrid/datagrid-model.cjs.map +1 -0
- package/dist/inputs/datagrid/datagrid-model.d.ts +101 -0
- package/dist/inputs/datagrid/datagrid-model.d.ts.map +1 -0
- package/dist/inputs/datagrid/datagrid-model.js +202 -0
- package/dist/inputs/datagrid/datagrid-model.js.map +1 -0
- package/dist/inputs/datagrid/datagrid-nav.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid.d.ts +44 -45
- package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
- package/dist/inputs/date-picker/date-picker.d.ts +4 -4
- package/dist/inputs/date-picker/date-picker.d.ts.map +1 -1
- package/dist/inputs/file-input/file-input-upload.cjs +1 -1
- package/dist/inputs/file-input/file-input-upload.cjs.map +1 -1
- package/dist/inputs/file-input/file-input-upload.d.ts.map +1 -1
- package/dist/inputs/file-input/file-input-upload.js +6 -3
- package/dist/inputs/file-input/file-input-upload.js.map +1 -1
- package/dist/inputs/file-input/file-input.d.ts.map +1 -1
- package/dist/inputs/index.d.ts +0 -4
- package/dist/inputs/index.d.ts.map +1 -1
- package/dist/inputs/input/input.d.ts +4 -10
- package/dist/inputs/input/input.d.ts.map +1 -1
- package/dist/inputs/message-composer/message-composer.d.ts +6 -10
- package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
- package/dist/inputs/number-input/number-input.d.ts +4 -10
- package/dist/inputs/number-input/number-input.d.ts.map +1 -1
- package/dist/inputs/otp-input/otp-input.d.ts +4 -6
- package/dist/inputs/otp-input/otp-input.d.ts.map +1 -1
- package/dist/inputs/radio/radio.d.ts +4 -3
- package/dist/inputs/radio/radio.d.ts.map +1 -1
- package/dist/inputs/radio-group/radio-group.d.ts +1 -1
- package/dist/inputs/radio-group/radio-group.d.ts.map +1 -1
- package/dist/inputs/rating/rating.d.ts +4 -5
- package/dist/inputs/rating/rating.d.ts.map +1 -1
- package/dist/inputs/select/select.d.ts +7 -9
- package/dist/inputs/select/select.d.ts.map +1 -1
- package/dist/inputs/shared/field-binding.cjs.map +1 -1
- package/dist/inputs/shared/field-binding.d.ts +1 -1
- package/dist/inputs/shared/field-binding.js.map +1 -1
- package/dist/inputs/shared/index.d.ts +0 -1
- package/dist/inputs/shared/index.d.ts.map +1 -1
- package/dist/inputs/shared/native-field-event.cjs +2 -0
- package/dist/inputs/shared/native-field-event.cjs.map +1 -0
- package/dist/inputs/shared/native-field-event.d.ts +6 -0
- package/dist/inputs/shared/native-field-event.d.ts.map +1 -0
- package/dist/inputs/shared/native-field-event.js +29 -0
- package/dist/inputs/shared/native-field-event.js.map +1 -0
- package/dist/inputs/shared/templates.cjs +18 -12
- package/dist/inputs/shared/templates.cjs.map +1 -1
- package/dist/inputs/shared/templates.d.ts +1 -1
- package/dist/inputs/shared/templates.d.ts.map +1 -1
- package/dist/inputs/shared/templates.js +19 -13
- package/dist/inputs/shared/templates.js.map +1 -1
- package/dist/inputs/slider/slider.css.cjs +1 -1
- package/dist/inputs/slider/slider.css.cjs.map +1 -1
- package/dist/inputs/slider/slider.css.js +1 -1
- package/dist/inputs/slider/slider.css.js.map +1 -1
- package/dist/inputs/slider/slider.d.ts +7 -10
- package/dist/inputs/slider/slider.d.ts.map +1 -1
- package/dist/inputs/switch/switch.d.ts +4 -3
- package/dist/inputs/switch/switch.d.ts.map +1 -1
- package/dist/inputs/textarea/textarea.d.ts +4 -10
- package/dist/inputs/textarea/textarea.d.ts.map +1 -1
- package/dist/inputs/time-picker/time-picker.d.ts +4 -4
- package/dist/inputs/time-picker/time-picker.d.ts.map +1 -1
- package/dist/layout/box/box.d.ts.map +1 -1
- package/dist/layout/navbar/navbar.css.cjs +1 -1
- package/dist/layout/navbar/navbar.css.cjs.map +1 -1
- package/dist/layout/navbar/navbar.css.js +1 -1
- package/dist/layout/navbar/navbar.css.js.map +1 -1
- package/dist/layout/navbar/navbar.d.ts +10 -0
- package/dist/layout/navbar/navbar.d.ts.map +1 -1
- package/dist/layout/sidebar/sidebar-item.css.cjs +1 -1
- package/dist/layout/sidebar/sidebar-item.css.cjs.map +1 -1
- package/dist/layout/sidebar/sidebar-item.css.js +1 -1
- package/dist/layout/sidebar/sidebar-item.css.js.map +1 -1
- package/dist/layout/sidebar/sidebar.css.cjs +1 -1
- package/dist/layout/sidebar/sidebar.css.cjs.map +1 -1
- package/dist/layout/sidebar/sidebar.css.js +1 -1
- package/dist/layout/sidebar/sidebar.css.js.map +1 -1
- package/dist/layout/sidebar/sidebar.d.ts.map +1 -1
- package/dist/list-item.cjs +2 -2
- package/dist/list-item.cjs.map +1 -1
- package/dist/list-item.js +4 -4
- package/dist/list-item.js.map +1 -1
- package/dist/list.cjs +3 -1
- package/dist/list.cjs.map +1 -1
- package/dist/list.js +28 -25
- package/dist/list.js.map +1 -1
- package/dist/marquee.cjs +32 -0
- package/dist/marquee.cjs.map +1 -0
- package/dist/marquee.js +93 -0
- package/dist/marquee.js.map +1 -0
- package/dist/menu.cjs +7 -7
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js +135 -103
- package/dist/menu.js.map +1 -1
- package/dist/message-composer.cjs +33 -31
- package/dist/message-composer.cjs.map +1 -1
- package/dist/message-composer.js +123 -123
- package/dist/message-composer.js.map +1 -1
- package/dist/navbar.cjs +17 -15
- package/dist/navbar.cjs.map +1 -1
- package/dist/navbar.js +108 -89
- package/dist/navbar.js.map +1 -1
- package/dist/number-input.cjs +19 -19
- package/dist/number-input.cjs.map +1 -1
- package/dist/number-input.js +94 -97
- package/dist/number-input.js.map +1 -1
- package/dist/otp-input.cjs +15 -13
- package/dist/otp-input.cjs.map +1 -1
- package/dist/otp-input.js +83 -82
- package/dist/otp-input.js.map +1 -1
- package/dist/overlay/command-palette/command-palette.d.ts +2 -2
- package/dist/overlay/command-palette/command-palette.d.ts.map +1 -1
- package/dist/overlay/command-palette/command-palette.types.d.ts +4 -5
- package/dist/overlay/command-palette/command-palette.types.d.ts.map +1 -1
- package/dist/overlay/dialog/dialog.d.ts +7 -6
- package/dist/overlay/dialog/dialog.d.ts.map +1 -1
- package/dist/overlay/drawer/drawer.d.ts +7 -10
- package/dist/overlay/drawer/drawer.d.ts.map +1 -1
- package/dist/overlay/index.d.ts +1 -1
- package/dist/overlay/index.d.ts.map +1 -1
- package/dist/overlay/menu/menu.d.ts +9 -7
- package/dist/overlay/menu/menu.d.ts.map +1 -1
- package/dist/overlay/popover/popover.d.ts +6 -11
- package/dist/overlay/popover/popover.d.ts.map +1 -1
- package/dist/overlay/shared/await-exit.cjs +1 -1
- package/dist/overlay/shared/await-exit.cjs.map +1 -1
- package/dist/overlay/shared/await-exit.js +1 -1
- package/dist/overlay/shared/await-exit.js.map +1 -1
- package/dist/overlay/shared/use-dialog.cjs +1 -1
- package/dist/overlay/shared/use-dialog.cjs.map +1 -1
- package/dist/overlay/shared/use-dialog.d.ts +13 -3
- package/dist/overlay/shared/use-dialog.d.ts.map +1 -1
- package/dist/overlay/shared/use-dialog.js +80 -72
- package/dist/overlay/shared/use-dialog.js.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.cjs +1 -1
- package/dist/overlay/shared/use-floating-trigger.cjs.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.d.ts +3 -1
- package/dist/overlay/shared/use-floating-trigger.d.ts.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.js +64 -70
- package/dist/overlay/shared/use-floating-trigger.js.map +1 -1
- package/dist/overlay/tooltip/tooltip.d.ts +9 -0
- package/dist/overlay/tooltip/tooltip.d.ts.map +1 -1
- package/dist/pagination.cjs +69 -55
- package/dist/pagination.cjs.map +1 -1
- package/dist/pagination.js +70 -56
- package/dist/pagination.js.map +1 -1
- package/dist/password-strength.cjs +6 -4
- package/dist/password-strength.cjs.map +1 -1
- package/dist/password-strength.js +6 -4
- package/dist/password-strength.js.map +1 -1
- package/dist/popover.cjs +4 -4
- package/dist/popover.cjs.map +1 -1
- package/dist/popover.js +28 -17
- package/dist/popover.js.map +1 -1
- package/dist/progress.cjs +25 -17
- package/dist/progress.cjs.map +1 -1
- package/dist/progress.js +29 -22
- package/dist/progress.js.map +1 -1
- package/dist/radio-group.cjs +14 -12
- package/dist/radio-group.cjs.map +1 -1
- package/dist/radio-group.js +88 -90
- package/dist/radio-group.js.map +1 -1
- package/dist/radio.cjs +4 -4
- package/dist/radio.cjs.map +1 -1
- package/dist/radio.js +90 -90
- package/dist/radio.js.map +1 -1
- package/dist/rating.cjs +18 -16
- package/dist/rating.cjs.map +1 -1
- package/dist/rating.js +69 -69
- package/dist/rating.js.map +1 -1
- package/dist/refine.cjs +1670 -1325
- package/dist/refine.cjs.map +1 -1
- package/dist/refine.iife.js +1673 -1328
- package/dist/refine.iife.js.map +1 -1
- package/dist/refine.js +1758 -1413
- package/dist/refine.js.map +1 -1
- package/dist/register.d.ts +21 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/select.cjs +59 -51
- package/dist/select.cjs.map +1 -1
- package/dist/select.js +189 -182
- package/dist/select.js.map +1 -1
- package/dist/separator.cjs +9 -9
- package/dist/separator.cjs.map +1 -1
- package/dist/separator.js +9 -9
- package/dist/separator.js.map +1 -1
- package/dist/shared/index.d.ts +1 -1
- package/dist/shared/prop-bundles.cjs +1 -1
- package/dist/shared/prop-bundles.cjs.map +1 -1
- package/dist/shared/prop-bundles.js +4 -2
- package/dist/shared/prop-bundles.js.map +1 -1
- package/dist/shared/size-presets.cjs +1 -1
- package/dist/shared/size-presets.cjs.map +1 -1
- package/dist/shared/size-presets.d.ts +3 -0
- package/dist/shared/size-presets.d.ts.map +1 -1
- package/dist/shared/size-presets.js +4 -1
- package/dist/shared/size-presets.js.map +1 -1
- package/dist/sidebar.cjs +8 -8
- package/dist/sidebar.cjs.map +1 -1
- package/dist/sidebar.js +25 -25
- package/dist/sidebar.js.map +1 -1
- package/dist/skeleton.cjs +4 -6
- package/dist/skeleton.cjs.map +1 -1
- package/dist/skeleton.js +21 -22
- package/dist/skeleton.js.map +1 -1
- package/dist/slider.cjs +14 -14
- package/dist/slider.cjs.map +1 -1
- package/dist/slider.js +160 -168
- package/dist/slider.js.map +1 -1
- package/dist/step.cjs +47 -0
- package/dist/step.cjs.map +1 -0
- package/dist/step.js +127 -0
- package/dist/step.js.map +1 -0
- package/dist/stepper.cjs +8 -0
- package/dist/stepper.cjs.map +1 -0
- package/dist/stepper.js +101 -0
- package/dist/stepper.js.map +1 -0
- package/dist/styles/index.d.ts +0 -28
- package/dist/styles/index.d.ts.map +1 -1
- package/dist/styles/mixins/shape.css.cjs +2 -2
- package/dist/styles/mixins/shape.css.cjs.map +1 -1
- package/dist/styles/mixins/shape.css.js +6 -6
- package/dist/styles/mixins/shape.css.js.map +1 -1
- package/dist/styles/tokens.css +4 -0
- package/dist/switch.cjs +4 -4
- package/dist/switch.cjs.map +1 -1
- package/dist/switch.js +44 -44
- package/dist/switch.js.map +1 -1
- package/dist/tab-item.cjs +3 -3
- package/dist/tab-item.cjs.map +1 -1
- package/dist/tab-item.js +24 -24
- package/dist/tab-item.js.map +1 -1
- package/dist/tab-panel.cjs +9 -7
- package/dist/tab-panel.cjs.map +1 -1
- package/dist/tab-panel.js +15 -14
- package/dist/tab-panel.js.map +1 -1
- package/dist/table.cjs +3 -1
- package/dist/table.cjs.map +1 -1
- package/dist/table.js +3 -1
- package/dist/table.js.map +1 -1
- package/dist/tabs.cjs +6 -6
- package/dist/tabs.cjs.map +1 -1
- package/dist/tabs.js +30 -29
- package/dist/tabs.js.map +1 -1
- package/dist/text.cjs +3 -1
- package/dist/text.cjs.map +1 -1
- package/dist/text.js +3 -1
- package/dist/text.js.map +1 -1
- package/dist/textarea.cjs +22 -22
- package/dist/textarea.cjs.map +1 -1
- package/dist/textarea.js +110 -112
- package/dist/textarea.js.map +1 -1
- package/dist/time-picker.cjs +69 -61
- package/dist/time-picker.cjs.map +1 -1
- package/dist/time-picker.js +146 -132
- package/dist/time-picker.js.map +1 -1
- package/dist/toast.cjs +22 -22
- package/dist/toast.cjs.map +1 -1
- package/dist/toast.js +280 -173
- package/dist/toast.js.map +1 -1
- package/dist/tooltip.cjs +5 -5
- package/dist/tooltip.cjs.map +1 -1
- package/dist/tooltip.js +61 -51
- package/dist/tooltip.js.map +1 -1
- package/dist/typing-indicator.cjs +1 -1
- package/dist/typing-indicator.cjs.map +1 -1
- package/dist/typing-indicator.js +5 -5
- package/dist/typing-indicator.js.map +1 -1
- package/dist/utils/link.cjs.map +1 -1
- package/dist/utils/link.d.ts +2 -2
- package/package.json +36 -117
- package/dist/form.cjs +0 -11
- package/dist/form.cjs.map +0 -1
- package/dist/form.js +0 -59
- package/dist/form.js.map +0 -1
- package/dist/headless/_internal.d.ts.map +0 -1
- package/dist/headless/announcer.cjs.map +0 -1
- package/dist/headless/announcer.d.ts.map +0 -1
- package/dist/headless/announcer.js.map +0 -1
- package/dist/headless/aria-reflection.cjs.map +0 -1
- package/dist/headless/aria-reflection.d.ts.map +0 -1
- package/dist/headless/aria-reflection.js.map +0 -1
- package/dist/headless/auto-resize.cjs.map +0 -1
- package/dist/headless/auto-resize.d.ts.map +0 -1
- package/dist/headless/auto-resize.js.map +0 -1
- package/dist/headless/checkable.cjs.map +0 -1
- package/dist/headless/checkable.d.ts.map +0 -1
- package/dist/headless/checkable.js.map +0 -1
- package/dist/headless/choice-field.cjs +0 -2
- package/dist/headless/choice-field.cjs.map +0 -1
- package/dist/headless/choice-field.d.ts.map +0 -1
- package/dist/headless/choice-field.js.map +0 -1
- package/dist/headless/composer.cjs.map +0 -1
- package/dist/headless/composer.d.ts.map +0 -1
- package/dist/headless/composer.js.map +0 -1
- package/dist/headless/datagrid.cjs +0 -2
- package/dist/headless/datagrid.cjs.map +0 -1
- package/dist/headless/datagrid.d.ts +0 -158
- package/dist/headless/datagrid.d.ts.map +0 -1
- package/dist/headless/datagrid.js +0 -55
- package/dist/headless/datagrid.js.map +0 -1
- package/dist/headless/date-picker.cjs.map +0 -1
- package/dist/headless/date-picker.d.ts.map +0 -1
- package/dist/headless/date-picker.js.map +0 -1
- package/dist/headless/direction.cjs.map +0 -1
- package/dist/headless/direction.d.ts.map +0 -1
- package/dist/headless/direction.js.map +0 -1
- package/dist/headless/field-base.cjs +0 -2
- package/dist/headless/field-base.cjs.map +0 -1
- package/dist/headless/field-base.d.ts.map +0 -1
- package/dist/headless/field-base.js +0 -72
- package/dist/headless/field-base.js.map +0 -1
- package/dist/headless/focus.cjs.map +0 -1
- package/dist/headless/focus.d.ts.map +0 -1
- package/dist/headless/focus.js.map +0 -1
- package/dist/headless/index.d.ts.map +0 -1
- package/dist/headless/keyboard.cjs.map +0 -1
- package/dist/headless/keyboard.d.ts.map +0 -1
- package/dist/headless/keyboard.js.map +0 -1
- package/dist/headless/light-dom.cjs.map +0 -1
- package/dist/headless/light-dom.d.ts.map +0 -1
- package/dist/headless/light-dom.js.map +0 -1
- package/dist/headless/nav.cjs.map +0 -1
- package/dist/headless/nav.d.ts.map +0 -1
- package/dist/headless/nav.js.map +0 -1
- package/dist/headless/numbers.cjs.map +0 -1
- package/dist/headless/numbers.d.ts.map +0 -1
- package/dist/headless/numbers.js.map +0 -1
- package/dist/headless/option-list.cjs +0 -2
- package/dist/headless/option-list.cjs.map +0 -1
- package/dist/headless/option-list.d.ts +0 -107
- package/dist/headless/option-list.d.ts.map +0 -1
- package/dist/headless/option-list.js +0 -66
- package/dist/headless/option-list.js.map +0 -1
- package/dist/headless/ore.cjs.map +0 -1
- package/dist/headless/ore.d.ts.map +0 -1
- package/dist/headless/ore.js.map +0 -1
- package/dist/headless/overlay.cjs +0 -2
- package/dist/headless/overlay.cjs.map +0 -1
- package/dist/headless/overlay.d.ts +0 -64
- package/dist/headless/overlay.d.ts.map +0 -1
- package/dist/headless/overlay.js +0 -32
- package/dist/headless/overlay.js.map +0 -1
- package/dist/headless/paginated-list.cjs +0 -2
- package/dist/headless/paginated-list.cjs.map +0 -1
- package/dist/headless/paginated-list.d.ts.map +0 -1
- package/dist/headless/paginated-list.js +0 -34
- package/dist/headless/paginated-list.js.map +0 -1
- package/dist/headless/parse.cjs.map +0 -1
- package/dist/headless/parse.d.ts.map +0 -1
- package/dist/headless/parse.js.map +0 -1
- package/dist/headless/positioner.cjs +0 -2
- package/dist/headless/positioner.cjs.map +0 -1
- package/dist/headless/positioner.d.ts.map +0 -1
- package/dist/headless/positioner.js.map +0 -1
- package/dist/headless/ref-callback.cjs +0 -2
- package/dist/headless/ref-callback.cjs.map +0 -1
- package/dist/headless/ref-callback.d.ts.map +0 -1
- package/dist/headless/ref-callback.js.map +0 -1
- package/dist/headless/selection-control.cjs +0 -2
- package/dist/headless/selection-control.cjs.map +0 -1
- package/dist/headless/selection-control.d.ts +0 -30
- package/dist/headless/selection-control.d.ts.map +0 -1
- package/dist/headless/selection-control.js +0 -44
- package/dist/headless/selection-control.js.map +0 -1
- package/dist/headless/signals.cjs +0 -2
- package/dist/headless/signals.cjs.map +0 -1
- package/dist/headless/signals.d.ts.map +0 -1
- package/dist/headless/signals.js.map +0 -1
- package/dist/headless/slider.cjs +0 -2
- package/dist/headless/slider.d.ts.map +0 -1
- package/dist/headless/slider.js.map +0 -1
- package/dist/headless/sort-control.cjs +0 -2
- package/dist/headless/sort-control.cjs.map +0 -1
- package/dist/headless/sort-control.d.ts +0 -22
- package/dist/headless/sort-control.d.ts.map +0 -1
- package/dist/headless/sort-control.js +0 -36
- package/dist/headless/sort-control.js.map +0 -1
- package/dist/headless/spinner.cjs +0 -2
- package/dist/headless/spinner.d.ts.map +0 -1
- package/dist/headless/spinner.js.map +0 -1
- package/dist/headless/swipe.cjs.map +0 -1
- package/dist/headless/swipe.d.ts.map +0 -1
- package/dist/headless/swipe.js.map +0 -1
- package/dist/headless/text-field.cjs.map +0 -1
- package/dist/headless/text-field.d.ts.map +0 -1
- package/dist/headless/text-field.js.map +0 -1
- package/dist/headless/typeahead.cjs.map +0 -1
- package/dist/headless/typeahead.d.ts.map +0 -1
- package/dist/headless/typeahead.js.map +0 -1
- package/dist/headless.cjs +0 -1
- package/dist/headless.js +0 -30
- package/dist/inputs/datagrid/datagrid-controls.cjs +0 -2
- package/dist/inputs/datagrid/datagrid-controls.cjs.map +0 -1
- package/dist/inputs/datagrid/datagrid-controls.d.ts +0 -98
- package/dist/inputs/datagrid/datagrid-controls.d.ts.map +0 -1
- package/dist/inputs/datagrid/datagrid-controls.js +0 -147
- package/dist/inputs/datagrid/datagrid-controls.js.map +0 -1
- package/dist/inputs/form/form.css.cjs +0 -2
- package/dist/inputs/form/form.css.cjs.map +0 -1
- package/dist/inputs/form/form.css.js +0 -6
- package/dist/inputs/form/form.css.js.map +0 -1
- package/dist/inputs/form/form.d.ts +0 -59
- package/dist/inputs/form/form.d.ts.map +0 -1
- package/dist/inputs/shared/form-context.cjs +0 -2
- package/dist/inputs/shared/form-context.cjs.map +0 -1
- package/dist/inputs/shared/form-context.d.ts +0 -55
- package/dist/inputs/shared/form-context.d.ts.map +0 -1
- package/dist/inputs/shared/form-context.js +0 -15
- package/dist/inputs/shared/form-context.js.map +0 -1
- package/dist/keymap/dist/_dev.cjs +0 -2
- package/dist/keymap/dist/_dev.cjs.map +0 -1
- package/dist/keymap/dist/_dev.js +0 -4
- package/dist/keymap/dist/_dev.js.map +0 -1
- package/dist/keymap/dist/format.cjs +0 -1
- package/dist/keymap/dist/format.js +0 -1
- package/dist/keymap/dist/index.cjs +0 -1
- package/dist/keymap/dist/index.js +0 -4
- package/dist/keymap/dist/keymap.cjs +0 -2
- package/dist/keymap/dist/keymap.cjs.map +0 -1
- package/dist/keymap/dist/keymap.js +0 -221
- package/dist/keymap/dist/keymap.js.map +0 -1
- package/dist/keymap/dist/layer.cjs +0 -1
- package/dist/keymap/dist/layer.js +0 -1
- package/dist/styles/index.cjs +0 -2
- package/dist/styles/index.cjs.map +0 -1
- package/dist/styles/index.js +0 -25
- package/dist/styles/index.js.map +0 -1
- package/dist/styles/styles.css +0 -5
- package/dist/testing/index.d.ts +0 -233
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing.cjs +0 -2
- package/dist/testing.cjs.map +0 -1
- package/dist/testing.js +0 -43
- package/dist/testing.js.map +0 -1
- /package/dist/{headless → core}/announcer.cjs +0 -0
- /package/dist/{headless → core}/announcer.d.ts +0 -0
- /package/dist/{headless → core}/aria-reflection.cjs +0 -0
- /package/dist/{headless → core}/aria-reflection.d.ts +0 -0
- /package/dist/{headless → core}/auto-resize.cjs +0 -0
- /package/dist/{headless → core}/auto-resize.d.ts +0 -0
- /package/dist/{headless → core}/checkable.cjs +0 -0
- /package/dist/{headless → core}/checkable.d.ts +0 -0
- /package/dist/{headless → core}/choice-field.d.ts +0 -0
- /package/dist/{headless → core}/composer.cjs +0 -0
- /package/dist/{headless → core}/composer.d.ts +0 -0
- /package/dist/{headless → core}/date-picker.d.ts +0 -0
- /package/dist/{headless → core}/direction.cjs +0 -0
- /package/dist/{headless → core}/direction.d.ts +0 -0
- /package/dist/{headless → core}/focus.cjs +0 -0
- /package/dist/{headless → core}/focus.d.ts +0 -0
- /package/dist/{headless → core}/keyboard.d.ts +0 -0
- /package/dist/{headless → core}/light-dom.cjs +0 -0
- /package/dist/{headless → core}/light-dom.d.ts +0 -0
- /package/dist/{headless → core}/nav.cjs +0 -0
- /package/dist/{headless → core}/nav.d.ts +0 -0
- /package/dist/{headless → core}/numbers.cjs +0 -0
- /package/dist/{headless → core}/numbers.d.ts +0 -0
- /package/dist/{headless → core}/ore.cjs +0 -0
- /package/dist/{headless → core}/paginated-list.d.ts +0 -0
- /package/dist/{headless → core}/parse.cjs +0 -0
- /package/dist/{headless → core}/parse.d.ts +0 -0
- /package/dist/{headless → core}/positioner.d.ts +0 -0
- /package/dist/{headless → core}/ref-callback.d.ts +0 -0
- /package/dist/{headless → core}/signals.d.ts +0 -0
- /package/dist/{headless → core}/slider.d.ts +0 -0
- /package/dist/{headless → core}/spinner.d.ts +0 -0
- /package/dist/{headless → core}/swipe.cjs +0 -0
- /package/dist/{headless → core}/swipe.d.ts +0 -0
- /package/dist/{headless → core}/text-field.cjs +0 -0
- /package/dist/{headless → core}/text-field.d.ts +0 -0
- /package/dist/{headless → core}/typeahead.cjs +0 -0
- /package/dist/{headless → core}/typeahead.d.ts +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"date-picker.js","names":[],"sources":["../../src/headless/date-picker.ts"],"sourcesContent":["import { Temporal, format, parsePlainDate } from '@vielzeug/tempo';\n\n// ── Public ISO helpers (single source of truth for both components) ───────────\n\n/**\n * Parses an ISO 8601 date string (`yyyy-MM-dd`) into a `Temporal.PlainDate`.\n * Returns `null` for any invalid / empty input — never throws.\n */\nexport function parseIso(iso: string | undefined | null): Temporal.PlainDate | null {\n if (!iso) return null;\n\n try {\n return parsePlainDate(iso);\n } catch {\n return null;\n }\n}\n\n/**\n * Serialises a `Temporal.PlainDate` (or `null`) to an ISO 8601 string (`yyyy-MM-dd`).\n * Returns `null` when the input is `null`.\n */\nexport function toIsoString(date: Temporal.PlainDate | null): string | null {\n return date ? date.toString() : null;\n}\n\n/**\n * Formats a `Temporal.PlainDate` for display in a given locale.\n * e.g. \"15 Jun 2025\" (default medium pattern).\n */\nexport function formatDisplayDate(date: Temporal.PlainDate, locale: string): string {\n return format(date, { intl: { day: 'numeric', month: 'short', year: 'numeric' }, locale, tz: 'UTC' });\n}\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type DatePickerView = 'day' | 'month' | 'year';\n\nexport type DateCell = {\n /** Day-of-month number (1–31) */\n day: number;\n isDisabled: boolean;\n /** ISO date string yyyy-MM-dd — stable key for rendering */\n iso: string;\n isOutsideMonth: boolean;\n isSelected: boolean;\n isToday: boolean;\n plain: Temporal.PlainDate;\n};\n\nexport type MonthCell = {\n isDisabled: boolean;\n isSelected: boolean;\n label: string;\n /** 1-based month number (Temporal convention: 1 = January … 12 = December) */\n month: number;\n shortLabel: string;\n};\n\nexport type YearCell = {\n isDisabled: boolean;\n isSelected: boolean;\n year: number;\n};\n\nexport type DatePickerControlOptions = {\n /** Locale for day/month names, defaults to `navigator.language` or `'en'` */\n locale?: string;\n /** Maximum selectable date (inclusive) */\n max?: Temporal.PlainDate | null;\n /** Minimum selectable date (inclusive) */\n min?: Temporal.PlainDate | null;\n /** Called when a date is committed by the user */\n onChange: (date: Temporal.PlainDate | null) => void;\n /** Currently selected date */\n value?: Temporal.PlainDate | null;\n /**\n * Which days of the week to disable (0 = Sunday … 6 = Saturday).\n * @example [0, 6] disables weekends\n */\n weekendDays?: number[];\n};\n\nexport type DatePickerControl = {\n /** Ordered day cells for the visible month grid (includes leading/trailing days) */\n dayCells(): DateCell[];\n /** Month currently shown in the header (1-indexed, Temporal convention) */\n displayMonth(): number;\n /** Year currently shown in the header */\n displayYear(): number;\n /** Jump to a specific display month/year without selecting */\n goTo(year: number, month: number): void;\n /** All 12 month cells */\n monthCells(): MonthCell[];\n /** Move display month forward by one */\n nextMonth(): void;\n /** Move display year forward by one */\n nextYear(): void;\n /** Move display month backward by one */\n prevMonth(): void;\n /** Move display year backward by one */\n prevYear(): void;\n /** Select a date. Pass null to clear. */\n select(date: Temporal.PlainDate | null): void;\n /** The currently selected date, or null */\n selected(): Temporal.PlainDate | null;\n /** Switch the calendar view */\n setView(view: DatePickerView): void;\n /** Currently rendered calendar view */\n view(): DatePickerView;\n /** Short week-day labels in locale order e.g. [\"Su\",\"Mo\",…] */\n weekdayLabels(): string[];\n /** Year cells for the visible decade window */\n yearCells(): YearCell[];\n};\n\n// ── Internal helpers ──────────────────────────────────────────────────────────\n\n/**\n * Returns today as a `Temporal.PlainDate` in the ISO calendar.\n * @internal\n */\nfunction todayPlain(): Temporal.PlainDate {\n return Temporal.Now.plainDateISO();\n}\n\n/**\n * Converts a `Temporal.PlainDate.dayOfWeek` value (1=Mon…7=Sun) to the\n * 0-based weekday index (0=Sun…6=Sat) used in the `weekendDays` prop.\n * @internal\n */\nfunction temporalDowToIndex(dow: number): number {\n // Temporal: 1=Mon, 2=Tue, …, 7=Sun → 0=Sun, 1=Mon, …, 6=Sat\n return dow % 7;\n}\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Pure, framework-agnostic date-picker state machine backed by `Temporal.PlainDate`.\n *\n * All state is held in plain mutable variables — suitable for wrapping in any\n * reactive layer (ore `signal`, Vue ref, etc.). The factory returns a stable\n * handle object; callers are responsible for reactivity.\n *\n * Options with getter-based live bindings (e.g. `get min() { ... }`) are read\n * on every call so the control always reflects the latest reactive state.\n *\n * @example\n * ```ts\n * const ctrl = createDatePickerControl({\n * value: Temporal.PlainDate.from('2025-06-15'),\n * locale: 'en-US',\n * onChange: (date) => console.log(date?.toString()),\n * });\n *\n * ctrl.nextMonth();\n * ctrl.select(Temporal.PlainDate.from('2025-07-04'));\n * ```\n */\nexport function createDatePickerControl(options: DatePickerControlOptions): DatePickerControl {\n // ── Mutable state ─────────────────────────────────────────────────────────\n\n let _selected: Temporal.PlainDate | null = options.value ?? null;\n let _view: DatePickerView = 'day';\n\n const initial = _selected ?? todayPlain();\n\n let _displayYear = initial.year;\n let _displayMonth = initial.month; // 1-indexed (Temporal convention)\n\n // ── Live option accessors (always read from options for reactive compat) ───\n\n function locale(): string {\n return options.locale ?? (typeof navigator !== 'undefined' ? navigator.language : 'en');\n }\n\n function weekendDays(): number[] {\n return options.weekendDays ?? [];\n }\n\n // ── Range / disabled helpers ───────────────────────────────────────────────\n\n function isOutOfRange(date: Temporal.PlainDate): boolean {\n if (options.min && Temporal.PlainDate.compare(date, options.min) < 0) return true;\n\n if (options.max && Temporal.PlainDate.compare(date, options.max) > 0) return true;\n\n return false;\n }\n\n function isDayDisabled(date: Temporal.PlainDate): boolean {\n if (isOutOfRange(date)) return true;\n\n if (weekendDays().includes(temporalDowToIndex(date.dayOfWeek))) return true;\n\n return false;\n }\n\n // ── Grid builders ─────────────────────────────────────────────────────────\n\n function buildDayCells(): DateCell[] {\n const todayDate = todayPlain();\n const firstOfMonth = Temporal.PlainDate.from({ day: 1, month: _displayMonth, year: _displayYear });\n\n // Sunday-start grid: Temporal dayOfWeek is 1=Mon…7=Sun, convert to 0=Sun offset\n const startOffset = temporalDowToIndex(firstOfMonth.dayOfWeek);\n const cells: DateCell[] = [];\n\n // Leading days from previous month\n for (let i = startOffset - 1; i >= 0; i--) {\n const d = firstOfMonth.subtract({ days: i + 1 });\n\n cells.push({\n day: d.day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: true,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n // Days in current month\n const daysInMonth = firstOfMonth.daysInMonth;\n\n for (let day = 1; day <= daysInMonth; day++) {\n const d = Temporal.PlainDate.from({ day, month: _displayMonth, year: _displayYear });\n\n cells.push({\n day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: false,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n // Trailing days to fill last row (always end at multiple of 7)\n const remaining = (7 - (cells.length % 7)) % 7;\n const firstOfNext = firstOfMonth.add({ months: 1 });\n\n for (let i = 0; i < remaining; i++) {\n const d = firstOfNext.add({ days: i });\n\n cells.push({\n day: d.day,\n isDisabled: isDayDisabled(d),\n iso: d.toString(),\n isOutsideMonth: true,\n isSelected: _selected !== null && Temporal.PlainDate.compare(d, _selected) === 0,\n isToday: Temporal.PlainDate.compare(d, todayDate) === 0,\n plain: d,\n });\n }\n\n return cells;\n }\n\n function buildMonthCells(): MonthCell[] {\n const cells: MonthCell[] = [];\n const loc = locale();\n\n for (let m = 1; m <= 12; m++) {\n const plain = Temporal.PlainDate.from({ day: 1, month: m, year: _displayYear });\n const lastOfMonth = plain.with({ day: plain.daysInMonth });\n\n const isDisabled =\n (options.min !== null && options.min !== undefined\n ? Temporal.PlainDate.compare(lastOfMonth, options.min) < 0\n : false) ||\n (options.max !== null && options.max !== undefined\n ? Temporal.PlainDate.compare(plain, options.max) > 0\n : false);\n\n cells.push({\n isDisabled,\n isSelected: _selected !== null && _selected.year === _displayYear && _selected.month === m,\n label: format(plain, { intl: { month: 'long' }, locale: loc, tz: 'UTC' }),\n month: m,\n shortLabel: format(plain, { intl: { month: 'short' }, locale: loc, tz: 'UTC' }),\n });\n }\n\n return cells;\n }\n\n function buildYearCells(): YearCell[] {\n const decadeStart = Math.floor(_displayYear / 10) * 10;\n const cells: YearCell[] = [];\n\n for (let y = decadeStart; y < decadeStart + 12; y++) {\n const firstOfYear = Temporal.PlainDate.from({ day: 1, month: 1, year: y });\n const lastOfYear = Temporal.PlainDate.from({ day: 31, month: 12, year: y });\n\n const isDisabled =\n (options.min !== null && options.min !== undefined\n ? Temporal.PlainDate.compare(lastOfYear, options.min) < 0\n : false) ||\n (options.max !== null && options.max !== undefined\n ? Temporal.PlainDate.compare(firstOfYear, options.max) > 0\n : false);\n\n cells.push({\n isDisabled,\n isSelected: _selected !== null && _selected.year === y,\n year: y,\n });\n }\n\n return cells;\n }\n\n function buildWeekdayLabels(): string[] {\n // 2024-01-07 is a Sunday — use it as the Sunday anchor\n const sunday = parsePlainDate('2024-01-07');\n const loc = locale();\n\n return Array.from({ length: 7 }, (_, i) =>\n format(sunday.add({ days: i }), { intl: { weekday: 'short' }, locale: loc, tz: 'UTC' }),\n );\n }\n\n // ── Handle ────────────────────────────────────────────────────────────────\n\n return {\n dayCells: buildDayCells,\n displayMonth: () => _displayMonth,\n displayYear: () => _displayYear,\n\n goTo(year: number, month: number): void {\n if (!Number.isFinite(year)) return;\n\n _displayYear = year;\n _displayMonth = Math.max(1, Math.min(12, month));\n },\n\n monthCells: buildMonthCells,\n\n nextMonth(): void {\n if (_displayMonth === 12) {\n _displayMonth = 1;\n _displayYear++;\n } else {\n _displayMonth++;\n }\n },\n\n nextYear(): void {\n _displayYear++;\n },\n\n prevMonth(): void {\n if (_displayMonth === 1) {\n _displayMonth = 12;\n _displayYear--;\n } else {\n _displayMonth--;\n }\n },\n\n prevYear(): void {\n _displayYear--;\n },\n\n select(date: Temporal.PlainDate | null): void {\n if (date !== null && isDayDisabled(date)) return;\n\n _selected = date;\n\n if (_selected) {\n _displayYear = _selected.year;\n _displayMonth = _selected.month;\n }\n\n options.onChange(_selected);\n },\n\n selected: () => _selected,\n\n setView(view: DatePickerView): void {\n _view = view;\n },\n\n view: () => _view,\n\n weekdayLabels: buildWeekdayLabels,\n\n yearCells: buildYearCells,\n };\n}\n"],"mappings":";;AAQA,SAAgB,EAAS,GAA2D;CAClF,IAAI,CAAC,GAAK,OAAO;CAEjB,IAAI;EACF,OAAO,EAAe,CAAG;CAC3B,QAAQ;EACN,OAAO;CACT;AACF;AAMA,SAAgB,EAAY,GAAgD;CAC1E,OAAO,IAAO,EAAK,SAAS,IAAI;AAClC;AAMA,SAAgB,EAAkB,GAA0B,GAAwB;CAClF,OAAO,EAAO,GAAM;EAAE,MAAM;GAAE,KAAK;GAAW,OAAO;GAAS,MAAM;EAAU;EAAG;EAAQ,IAAI;CAAM,CAAC;AACtG;AA0FA,SAAS,IAAiC;CACxC,OAAO,EAAS,IAAI,aAAa;AACnC;AAOA,SAAS,EAAmB,GAAqB;CAE/C,OAAO,IAAM;AACf;AA0BA,SAAgB,EAAwB,GAAsD;CAG5F,IAAI,IAAuC,EAAQ,SAAS,MACxD,IAAwB,OAEtB,IAAU,KAAa,EAAW,GAEpC,IAAe,EAAQ,MACvB,IAAgB,EAAQ;CAI5B,SAAS,IAAiB;EACxB,OAAO,EAAQ,WAAW,OAAO,YAAc,MAAc,UAAU,WAAW;CACpF;CAEA,SAAS,IAAwB;EAC/B,OAAO,EAAQ,eAAe,CAAC;CACjC;CAIA,SAAS,EAAa,GAAmC;EAKvD,OAFA,GAFI,EAAQ,OAAO,EAAS,UAAU,QAAQ,GAAM,EAAQ,GAAG,IAAI,KAE/D,EAAQ,OAAO,EAAS,UAAU,QAAQ,GAAM,EAAQ,GAAG,IAAI;CAGrE;CAEA,SAAS,EAAc,GAAmC;EAKxD,OAFA,GAFI,EAAa,CAAI,KAEjB,EAAY,CAAC,CAAC,SAAS,EAAmB,EAAK,SAAS,CAAC;CAG/D;CAIA,SAAS,IAA4B;EACnC,IAAM,IAAY,EAAW,GACvB,IAAe,EAAS,UAAU,KAAK;GAAE,KAAK;GAAG,OAAO;GAAe,MAAM;EAAa,CAAC,GAG3F,IAAc,EAAmB,EAAa,SAAS,GACvD,IAAoB,CAAC;EAG3B,KAAK,IAAI,IAAI,IAAc,GAAG,KAAK,GAAG,KAAK;GACzC,IAAM,IAAI,EAAa,SAAS,EAAE,MAAM,IAAI,EAAE,CAAC;GAE/C,EAAM,KAAK;IACT,KAAK,EAAE;IACP,YAAY,EAAc,CAAC;IAC3B,KAAK,EAAE,SAAS;IAChB,gBAAgB;IAChB,YAAY,MAAc,QAAQ,EAAS,UAAU,QAAQ,GAAG,CAAS,MAAM;IAC/E,SAAS,EAAS,UAAU,QAAQ,GAAG,CAAS,MAAM;IACtD,OAAO;GACT,CAAC;EACH;EAGA,IAAM,IAAc,EAAa;EAEjC,KAAK,IAAI,IAAM,GAAG,KAAO,GAAa,KAAO;GAC3C,IAAM,IAAI,EAAS,UAAU,KAAK;IAAE;IAAK,OAAO;IAAe,MAAM;GAAa,CAAC;GAEnF,EAAM,KAAK;IACT;IACA,YAAY,EAAc,CAAC;IAC3B,KAAK,EAAE,SAAS;IAChB,gBAAgB;IAChB,YAAY,MAAc,QAAQ,EAAS,UAAU,QAAQ,GAAG,CAAS,MAAM;IAC/E,SAAS,EAAS,UAAU,QAAQ,GAAG,CAAS,MAAM;IACtD,OAAO;GACT,CAAC;EACH;EAGA,IAAM,KAAa,IAAK,EAAM,SAAS,KAAM,GACvC,IAAc,EAAa,IAAI,EAAE,QAAQ,EAAE,CAAC;EAElD,KAAK,IAAI,IAAI,GAAG,IAAI,GAAW,KAAK;GAClC,IAAM,IAAI,EAAY,IAAI,EAAE,MAAM,EAAE,CAAC;GAErC,EAAM,KAAK;IACT,KAAK,EAAE;IACP,YAAY,EAAc,CAAC;IAC3B,KAAK,EAAE,SAAS;IAChB,gBAAgB;IAChB,YAAY,MAAc,QAAQ,EAAS,UAAU,QAAQ,GAAG,CAAS,MAAM;IAC/E,SAAS,EAAS,UAAU,QAAQ,GAAG,CAAS,MAAM;IACtD,OAAO;GACT,CAAC;EACH;EAEA,OAAO;CACT;CAEA,SAAS,IAA+B;EACtC,IAAM,IAAqB,CAAC,GACtB,IAAM,EAAO;EAEnB,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,KAAK;GAC5B,IAAM,IAAQ,EAAS,UAAU,KAAK;IAAE,KAAK;IAAG,OAAO;IAAG,MAAM;GAAa,CAAC,GACxE,IAAc,EAAM,KAAK,EAAE,KAAK,EAAM,YAAY,CAAC,GAEnD,KACH,EAAQ,QAAQ,QAAQ,EAAQ,QAAQ,KAAA,IACrC,EAAS,UAAU,QAAQ,GAAa,EAAQ,GAAG,IAAI,IACvD,QACH,EAAQ,QAAQ,QAAQ,EAAQ,QAAQ,KAAA,IACrC,EAAS,UAAU,QAAQ,GAAO,EAAQ,GAAG,IAAI,IACjD;GAEN,EAAM,KAAK;IACT;IACA,YAAY,MAAc,QAAQ,EAAU,SAAS,KAAgB,EAAU,UAAU;IACzF,OAAO,EAAO,GAAO;KAAE,MAAM,EAAE,OAAO,OAAO;KAAG,QAAQ;KAAK,IAAI;IAAM,CAAC;IACxE,OAAO;IACP,YAAY,EAAO,GAAO;KAAE,MAAM,EAAE,OAAO,QAAQ;KAAG,QAAQ;KAAK,IAAI;IAAM,CAAC;GAChF,CAAC;EACH;EAEA,OAAO;CACT;CAEA,SAAS,IAA6B;EACpC,IAAM,IAAc,KAAK,MAAM,IAAe,EAAE,IAAI,IAC9C,IAAoB,CAAC;EAE3B,KAAK,IAAI,IAAI,GAAa,IAAI,IAAc,IAAI,KAAK;GACnD,IAAM,IAAc,EAAS,UAAU,KAAK;IAAE,KAAK;IAAG,OAAO;IAAG,MAAM;GAAE,CAAC,GACnE,IAAa,EAAS,UAAU,KAAK;IAAE,KAAK;IAAI,OAAO;IAAI,MAAM;GAAE,CAAC,GAEpE,KACH,EAAQ,QAAQ,QAAQ,EAAQ,QAAQ,KAAA,IACrC,EAAS,UAAU,QAAQ,GAAY,EAAQ,GAAG,IAAI,IACtD,QACH,EAAQ,QAAQ,QAAQ,EAAQ,QAAQ,KAAA,IACrC,EAAS,UAAU,QAAQ,GAAa,EAAQ,GAAG,IAAI,IACvD;GAEN,EAAM,KAAK;IACT;IACA,YAAY,MAAc,QAAQ,EAAU,SAAS;IACrD,MAAM;GACR,CAAC;EACH;EAEA,OAAO;CACT;CAEA,SAAS,IAA+B;EAEtC,IAAM,IAAS,EAAe,YAAY,GACpC,IAAM,EAAO;EAEnB,OAAO,MAAM,KAAK,EAAE,QAAQ,EAAE,IAAI,GAAG,MACnC,EAAO,EAAO,IAAI,EAAE,MAAM,EAAE,CAAC,GAAG;GAAE,MAAM,EAAE,SAAS,QAAQ;GAAG,QAAQ;GAAK,IAAI;EAAM,CAAC,CACxF;CACF;CAIA,OAAO;EACL,UAAU;EACV,oBAAoB;EACpB,mBAAmB;EAEnB,KAAK,GAAc,GAAqB;GACjC,OAAO,SAAS,CAAI,MAEzB,IAAe,GACf,IAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,IAAI,CAAK,CAAC;EACjD;EAEA,YAAY;EAEZ,YAAkB;GAChB,AAAI,MAAkB,MACpB,IAAgB,GAChB,OAEA;EAEJ;EAEA,WAAiB;GACf;EACF;EAEA,YAAkB;GAChB,AAAI,MAAkB,KACpB,IAAgB,IAChB,OAEA;EAEJ;EAEA,WAAiB;GACf;EACF;EAEA,OAAO,GAAuC;GACxC,MAAS,QAAQ,EAAc,CAAI,MAEvC,IAAY,GAER,MACF,IAAe,EAAU,MACzB,IAAgB,EAAU,QAG5B,EAAQ,SAAS,CAAS;EAC5B;EAEA,gBAAgB;EAEhB,QAAQ,GAA4B;GAClC,IAAQ;EACV;EAEA,YAAY;EAEZ,eAAe;EAEf,WAAW;CACb;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"direction.cjs","names":[],"sources":["../../src/headless/direction.ts"],"sourcesContent":["/**\n * Resolves the effective text direction for an element.\n *\n * The closest ancestor with an explicit `dir=\"ltr\"` or `dir=\"rtl\"` attribute wins — this\n * supports locally-scoped RTL sections (e.g. a single `dir=\"rtl\"` panel inside an otherwise\n * LTR page). When no explicit `dir` attribute is found up the tree, falls back to the\n * computed `direction` CSS property (e.g. set via a `direction: rtl` style rule with no\n * `dir` attribute). Defaults to `'ltr'` when `el` is `null`.\n */\nexport function elementDirection(el: Element | null): 'ltr' | 'rtl' {\n let node: Element | null = el;\n\n while (node) {\n const dir = node.getAttribute('dir');\n\n if (dir === 'rtl' || dir === 'ltr') return dir;\n\n node = node.parentElement;\n }\n\n return el !== null && getComputedStyle(el).direction === 'rtl' ? 'rtl' : 'ltr';\n}\n"],"mappings":"AASA,SAAgB,EAAiB,EAAmC,CAClE,IAAI,EAAuB,EAE3B,KAAO,GAAM,CACX,IAAM,EAAM,EAAK,aAAa,KAAK,EAEnC,GAAI,IAAQ,OAAS,IAAQ,MAAO,OAAO,EAE3C,EAAO,EAAK,aACd,CAEA,OAAO,IAAO,MAAQ,iBAAiB,CAAE,CAAC,CAAC,YAAc,MAAQ,MAAQ,KAC3E"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"direction.d.ts","sourceRoot":"","sources":["../../src/headless/direction.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,KAAK,CAYlE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"direction.js","names":[],"sources":["../../src/headless/direction.ts"],"sourcesContent":["/**\n * Resolves the effective text direction for an element.\n *\n * The closest ancestor with an explicit `dir=\"ltr\"` or `dir=\"rtl\"` attribute wins — this\n * supports locally-scoped RTL sections (e.g. a single `dir=\"rtl\"` panel inside an otherwise\n * LTR page). When no explicit `dir` attribute is found up the tree, falls back to the\n * computed `direction` CSS property (e.g. set via a `direction: rtl` style rule with no\n * `dir` attribute). Defaults to `'ltr'` when `el` is `null`.\n */\nexport function elementDirection(el: Element | null): 'ltr' | 'rtl' {\n let node: Element | null = el;\n\n while (node) {\n const dir = node.getAttribute('dir');\n\n if (dir === 'rtl' || dir === 'ltr') return dir;\n\n node = node.parentElement;\n }\n\n return el !== null && getComputedStyle(el).direction === 'rtl' ? 'rtl' : 'ltr';\n}\n"],"mappings":";AASA,SAAgB,EAAiB,GAAmC;CAClE,IAAI,IAAuB;CAE3B,OAAO,IAAM;EACX,IAAM,IAAM,EAAK,aAAa,KAAK;EAEnC,IAAI,MAAQ,SAAS,MAAQ,OAAO,OAAO;EAE3C,IAAO,EAAK;CACd;CAEA,OAAO,MAAO,QAAQ,iBAAiB,CAAE,CAAC,CAAC,cAAc,QAAQ,QAAQ;AAC3E"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../_dev.cjs");let t=require("@vielzeug/ore"),n=require("@vielzeug/ripple");var r=e=>(0,n.computed)(()=>({errorText:e.error?.value??``,helperText:e.helper?.value??``})),i=e=>(0,n.computed)(()=>{let t=e.value?.value??``,n=e.maxLength?.value,r=Number(n),i=Number.isFinite(r)&&r>0?r:null,a=i!==null,o=a?`${t.length} / ${i}`:``,s=a?t.length/i:0;return{counterAtLimit:a?s>=1:!1,counterNearLimit:a?s>=.9&&s<1:!1,counterText:o}}),a=(e,t=`counter`)=>e?e.counterAtLimit?`${t} at-limit`:e.counterNearLimit?`${t} near-limit`:t:t;function o(){let e=!1;return{clear:()=>{e=!1},get isDirty(){return e},markDirty:()=>{e=!0}}}var s=i=>{let a=(0,n.computed)(()=>!!i.disabled?.value),o=(0,t.createStableId)(`helper`),s=(0,t.createStableId)(`error`),c=r({error:i.error,helper:i.helper}),l=(0,n.computed)(()=>c.value.errorText||c.value.helperText?o:null),u=(0,n.computed)(()=>c.value.errorText?s:null),d=(0,n.computed)(()=>c.value.errorText?`true`:null),f=null;return{ariaDescribedBy:l,ariaErrorMessage:u,ariaInvalid:d,assistiveId:o,attachFormField:e=>{f=e},disabled:a,errorId:s,errorText:(0,n.computed)(()=>c.value.errorText),helperText:(0,n.computed)(()=>c.value.helperText),triggerValidation:t=>{if(i.validateOn?.value===t){if(!f){e.warn(`triggerValidation() called before attachFormField() — validation will not run. See createTextField()/createChoiceField()/createCheckable()'s attachFormField doc comment.`);return}f.reportValidity()}}}},c=e=>{let r=e.id??(0,t.createStableId)(e.prefix??`field`),i=(0,t.createStableId)(`label`),a=e.label??(0,n.computed)(()=>void 0),o=e.hasLabel??(0,n.computed)(()=>!!a.value);return{ariaLabelledBy:(0,n.computed)(()=>o.value?i:null),fieldId:r,labelId:i,labelVisible:o}},l=e=>({...s(e),...c(e)});exports.counterClassName=a,exports.createAssistiveState=s,exports.createCounterState=i,exports.createDirtyTracker=o,exports.createErrorHelperState=r,exports.createField=l,exports.createLabelState=c;
|
|
2
|
-
//# sourceMappingURL=field-base.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"field-base.cjs","names":[],"sources":["../../src/headless/field-base.ts"],"sourcesContent":["import { createStableId } from '@vielzeug/ore';\nimport { computed, type Readable } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\n\n// ── Validation / context types ────────────────────────────────────────────────\n\nexport type ValidationTrigger = 'blur' | 'change' | 'input' | 'submit';\nexport type ControlValidationMode = ValidationTrigger | undefined;\n\n// ── Error/helper assistive state ──────────────────────────────────────────────\n\nexport type ErrorHelperState = {\n errorText: string;\n helperText: string;\n};\n\nexport type ErrorHelperOptions = {\n error?: Readable<string | undefined>;\n helper?: Readable<string | undefined>;\n};\n\nexport const createErrorHelperState = (options: ErrorHelperOptions): Readable<ErrorHelperState> =>\n computed(() => ({\n errorText: options.error?.value ?? '',\n helperText: options.helper?.value ?? '',\n }));\n\n// ── Counter state (opt-in) ─────────────────────────────────────────────────────\n\n/** Counter state for text fields with `maxLength`. */\nexport type CounterState = {\n counterAtLimit: boolean;\n counterNearLimit: boolean;\n counterText: string;\n};\n\nexport type CounterOptions = {\n maxLength?: Readable<number | undefined>;\n value: Readable<string | undefined>;\n};\n\n/**\n * Creates a reactive counter state signal for text fields with `maxLength`.\n * Only call this when `maxLength` may be set — the state is genuinely opt-in.\n *\n * @example\n * ```ts\n * const counter = createCounterState({ value: tf.value, maxLength: props.maxlength });\n * ```\n */\nexport const createCounterState = (options: CounterOptions): Readable<CounterState> =>\n computed<CounterState>(() => {\n const value = options.value?.value ?? '';\n const maxLength = options.maxLength?.value;\n const parsedMaxLength = Number(maxLength);\n const validMaxLength = Number.isFinite(parsedMaxLength) && parsedMaxLength > 0 ? parsedMaxLength : null;\n const hasCounter = validMaxLength !== null;\n const counterText = hasCounter ? `${value.length} / ${validMaxLength}` : '';\n const ratio = hasCounter ? value.length / validMaxLength : 0;\n\n return {\n counterAtLimit: hasCounter ? ratio >= 1 : false,\n counterNearLimit: hasCounter ? ratio >= 0.9 && ratio < 1 : false,\n counterText,\n };\n });\n\n/**\n * The single implementation of \"which modifier class does this counter state map to\" —\n * every field with a character counter (`ore-input`, `ore-textarea`, `ore-message-composer`)\n * renders the identical near-limit/at-limit styling, so this is the one place that decides it.\n *\n * @example\n * ```ts\n * html`<span class=\"${() => counterClassName(counter?.value)}\">...</span>`\n * ```\n */\nexport const counterClassName = (counter: CounterState | undefined, base = 'counter'): string => {\n if (!counter) return base;\n\n if (counter.counterAtLimit) return `${base} at-limit`;\n\n if (counter.counterNearLimit) return `${base} near-limit`;\n\n return base;\n};\n\n// ── Dirty tracking (two-state reset) ───────────────────────────────────────────\n\n/**\n * Tracks whether a control's value has ever been changed by user interaction.\n *\n * Backs the \"two-state reset()\" pattern used by `createCheckable` (`checked`/\n * `indeterminate`) and `createChoiceField` (`selectedValues`): before the first\n * interaction, the live prop is still a reliable \"current default\" to resync from\n * (e.g. an async-loaded value arriving after mount); after it, the prop is\n * contaminated by interaction-driven attribute reflection, so only a snapshot taken\n * at creation still represents \"the default\" in the native sense. `reset()` callers\n * check `isDirty` to decide which source to revert to, then call `clear()`.\n */\nexport type DirtyTracker = {\n clear: () => void;\n readonly isDirty: boolean;\n markDirty: () => void;\n};\n\nexport function createDirtyTracker(): DirtyTracker {\n let dirty = false;\n\n return {\n clear: () => {\n dirty = false;\n },\n get isDirty() {\n return dirty;\n },\n markDirty: () => {\n dirty = true;\n },\n };\n}\n\n// ── Label placement ───────────────────────────────────────────────────────────\n\nexport type LabelPlacement = 'inset' | 'outside' | undefined;\n\n// ── Assistive state (error/helper text, describedby/errormessage/invalid) ─────\n\n/**\n * A field's error/helper/disabled/validation-trigger state — everything an input\n * needs *except* a visible `<label>`. Split out from label state (below) because\n * not every field has one: `ore-message-composer` names itself via `aria-label`\n * (a chat composer's accessible name conventionally comes from context/placeholder,\n * not a floating `<label>`), so it composes this directly instead of pulling in\n * label plumbing it can't use. `createField()` composes both for fields that do\n * render a `<label>`.\n */\nexport type AssistiveStateHandle = {\n /** `aria-describedby` value. Non-null when helper or error text is present. */\n ariaDescribedBy: Readable<string | null>;\n /** `aria-errormessage` value. Non-null when error text is present. */\n ariaErrorMessage: Readable<string | null>;\n /** `aria-invalid` value. `'true'` when error text is present, otherwise `null`. */\n ariaInvalid: Readable<'true' | null>;\n /**\n * The stable `id` used for `aria-describedby` on the input. Points at the\n * assistive-text region (covers both helper text and error text per WAI-ARIA).\n */\n assistiveId: string;\n /**\n * Registers the real form field handle (the return value of `useField()`) so that\n * `triggerValidation()` can call its `reportValidity()`. See `TextFieldHandle.attachFormField`\n * for why this is a post-hoc call instead of a constructor option — the same forward\n * reference applies here for choice fields.\n */\n attachFormField: (formField: { reportValidity(): void }) => void;\n disabled: Readable<boolean>;\n /** Stable `id` for the inline error message element (`aria-errormessage`). */\n errorId: string;\n /** Reactive error text. Empty string when no error is set. */\n errorText: Readable<string>;\n /** Reactive helper text. Empty string when no helper is set. */\n helperText: Readable<string>;\n triggerValidation: (on: Extract<ValidationTrigger, 'blur' | 'change'>) => void;\n};\n\nexport type AssistiveStateOptions = {\n disabled?: Readable<boolean | undefined>;\n error?: Readable<string | undefined>;\n helper?: Readable<string | undefined>;\n validateOn?: Readable<ControlValidationMode>;\n};\n\nexport const createAssistiveState = (options: AssistiveStateOptions): AssistiveStateHandle => {\n const disabled = computed(() => Boolean(options.disabled?.value));\n const assistiveId = createStableId('helper');\n const errorId = createStableId('error');\n const resolvedAssistive = createErrorHelperState({ error: options.error, helper: options.helper });\n\n const ariaDescribedBy = computed(() =>\n resolvedAssistive.value.errorText || resolvedAssistive.value.helperText ? assistiveId : null,\n );\n const ariaErrorMessage = computed(() => (resolvedAssistive.value.errorText ? errorId : null));\n const ariaInvalid = computed<'true' | null>(() => (resolvedAssistive.value.errorText ? 'true' : null));\n\n let formField: { reportValidity(): void } | null = null;\n const attachFormField = (nextFormField: { reportValidity(): void }): void => {\n formField = nextFormField;\n };\n\n const triggerValidation = (on: Extract<ValidationTrigger, 'blur' | 'change'>): void => {\n if (options.validateOn?.value !== on) return;\n\n if (!formField) {\n // Not user-facing — this only fires when a component author wired `validateOn` but\n // forgot the matching `attachFormField(useField(...))` call, so validation silently\n // never runs instead of erroring where the mistake actually is.\n warn(\n \"triggerValidation() called before attachFormField() — validation will not run. See createTextField()/createChoiceField()/createCheckable()'s attachFormField doc comment.\",\n );\n\n return;\n }\n\n formField.reportValidity();\n };\n\n return {\n ariaDescribedBy,\n ariaErrorMessage,\n ariaInvalid,\n assistiveId,\n attachFormField,\n disabled,\n errorId,\n errorText: computed(() => resolvedAssistive.value.errorText),\n helperText: computed(() => resolvedAssistive.value.helperText),\n triggerValidation,\n };\n};\n\n// ── Label state (visible `<label>` + `aria-labelledby`) ────────────────────────\n\nexport type LabelStateHandle = {\n /** `aria-labelledby` value. Non-null when a label is visible. */\n ariaLabelledBy: Readable<string | null>;\n /** Stable `id` for the underlying form control — the `<label for=\"...\">` target. */\n fieldId: string;\n /** Stable `id` for the label element. Stamp this on your `<label id=\"...\">`. */\n labelId: string;\n /** Whether the label should be visible. Use to toggle `hidden` on the `<label>`. */\n labelVisible: Readable<boolean>;\n};\n\nexport type LabelStateOptions = {\n /**\n * Override for label visibility that takes precedence over deriving it from\n * the `label` text signal. Pass a computed signal that checks both prop and\n * slot presence to enable slot-first composition.\n *\n * @example\n * ```ts\n * const hasLabel = computed(() => !!props.label.value || slots.has('label').value);\n * const label = createLabelState({ ...options, hasLabel });\n * ```\n */\n hasLabel?: Readable<boolean>;\n /**\n * When provided, used directly as `fieldId` instead of generating one via\n * `createStableId`. Useful in tests for deterministic ID assertions.\n */\n id?: string;\n /**\n * Label text signal. When provided, `labelVisible` and `ariaLabelledBy` are\n * computed reactively from this value (see `hasLabel` for the slot-first override).\n */\n label?: Readable<string | undefined>;\n /**\n * Label placement signal. Defaults to `'inset'`.\n *\n * Not consumed by `createLabelState()` itself — visibility is driven solely by\n * `hasLabel`/`label`. Threaded through so component authors can apply\n * placement-specific styling (`label-placement` attribute) without a second\n * option; if placement-dependent visibility is ever needed, wire it into\n * `labelVisible` here instead of adding a new option.\n */\n labelPlacement?: Readable<LabelPlacement>;\n prefix?: string;\n};\n\nexport const createLabelState = (options: LabelStateOptions): LabelStateHandle => {\n const fieldId = options.id ?? createStableId(options.prefix ?? 'field');\n const labelId = createStableId('label');\n const label$ = options.label ?? computed(() => undefined);\n\n // Slot-first composition: if the caller provides `hasLabel`, use it instead\n // of deriving visibility purely from the label text signal. This allows\n // components with a `<slot name=\"label\">` to stay visible even when the\n // `label` prop is empty but a slotted label element is present.\n const labelVisible = options.hasLabel ?? computed(() => Boolean(label$.value));\n const ariaLabelledBy = computed(() => (labelVisible.value ? labelId : null));\n\n return { ariaLabelledBy, fieldId, labelId, labelVisible };\n};\n\n// ── Field handle (assistive + label, composed) ──────────────────────────────\n\n/**\n * Common handle returned by `createField` — the base for both `TextFieldHandle`\n * and `ChoiceFieldHandle`. Composes `createAssistiveState` + `createLabelState`;\n * call those directly instead if a field has no visible `<label>` (see\n * `createAssistiveState`'s doc comment).\n *\n * ARIA signals and label state are flat on the handle — no nested `aria` or\n * `label` sub-objects. `labelId`/`labelVisible`/`ariaLabelledBy` are always\n * present but only meaningful when `label`/`hasLabel` was passed — omit both\n * and they resolve to an always-hidden, unreferenced label.\n *\n * @example\n * ```html\n * <label id=\"${labelId}\" ?hidden=\"${() => !labelVisible.value}\">...</label>\n * <input\n * :aria-labelledby=\"${ariaLabelledBy}\"\n * :aria-describedby=\"${ariaDescribedBy}\"\n * :aria-invalid=\"${ariaInvalid}\" />\n * ```\n */\nexport type FieldHandle = AssistiveStateHandle & LabelStateHandle;\n\n/** Options shared by both `createTextField` and `createChoiceField`. */\nexport type FieldOptions = AssistiveStateOptions & LabelStateOptions;\n\nexport const createField = (options: FieldOptions): FieldHandle => ({\n ...createAssistiveState(options),\n ...createLabelState(options),\n});\n"],"mappings":"4FAsBA,IAAa,EAA0B,IAAA,EAAA,EAAA,SAAA,MACrB,CACd,UAAW,EAAQ,OAAO,OAAS,GACnC,WAAY,EAAQ,QAAQ,OAAS,EACvC,EAAE,EAyBS,EAAsB,IAAA,EAAA,EAAA,SAAA,KACJ,CAC3B,IAAM,EAAQ,EAAQ,OAAO,OAAS,GAChC,EAAY,EAAQ,WAAW,MAC/B,EAAkB,OAAO,CAAS,EAClC,EAAiB,OAAO,SAAS,CAAe,GAAK,EAAkB,EAAI,EAAkB,KAC7F,EAAa,IAAmB,KAChC,EAAc,EAAa,GAAG,EAAM,OAAO,KAAK,IAAmB,GACnE,EAAQ,EAAa,EAAM,OAAS,EAAiB,EAE3D,MAAO,CACL,eAAgB,EAAa,GAAS,EAAI,GAC1C,iBAAkB,EAAa,GAAS,IAAO,EAAQ,EAAI,GAC3D,aACF,CACF,CAAC,EAYU,GAAoB,EAAmC,EAAO,YACpE,EAED,EAAQ,eAAuB,GAAG,EAAK,WAEvC,EAAQ,iBAAyB,GAAG,EAAK,aAEtC,EANc,EA4BvB,SAAgB,GAAmC,CACjD,IAAI,EAAQ,GAEZ,MAAO,CACL,UAAa,CACX,EAAQ,EACV,EACA,IAAI,SAAU,CACZ,OAAO,CACT,EACA,cAAiB,CACf,EAAQ,EACV,CACF,CACF,CAqDA,IAAa,EAAwB,GAAyD,CAC5F,IAAM,GAAA,EAAA,EAAA,SAAA,KAA0B,EAAQ,EAAQ,UAAU,KAAM,EAC1D,GAAA,EAAA,EAAA,eAAA,CAA6B,QAAQ,EACrC,GAAA,EAAA,EAAA,eAAA,CAAyB,OAAO,EAChC,EAAoB,EAAuB,CAAE,MAAO,EAAQ,MAAO,OAAQ,EAAQ,MAAO,CAAC,EAE3F,GAAA,EAAA,EAAA,SAAA,KACJ,EAAkB,MAAM,WAAa,EAAkB,MAAM,WAAa,EAAc,IAC1F,EACM,GAAA,EAAA,EAAA,SAAA,KAAmC,EAAkB,MAAM,UAAY,EAAU,IAAK,EACtF,GAAA,EAAA,EAAA,SAAA,KAA6C,EAAkB,MAAM,UAAY,OAAS,IAAK,EAEjG,EAA+C,KAsBnD,MAAO,CACL,kBACA,mBACA,cACA,cACA,gBA1BuB,GAAoD,CAC3E,EAAY,CACd,EAyBE,WACA,UACA,WAAA,EAAA,EAAA,SAAA,KAA0B,EAAkB,MAAM,SAAS,EAC3D,YAAA,EAAA,EAAA,SAAA,KAA2B,EAAkB,MAAM,UAAU,EAC7D,kBA3ByB,GAA4D,CACjF,KAAQ,YAAY,QAAU,EAElC,IAAI,CAAC,EAAW,CAId,EAAA,KACE,2KACF,EAEA,MACF,CAEA,EAAU,eAAe,CAFzB,CAGF,CAaA,CACF,EAmDa,EAAoB,GAAiD,CAChF,IAAM,EAAU,EAAQ,KAAA,EAAA,EAAA,eAAA,CAAqB,EAAQ,QAAU,OAAO,EAChE,GAAA,EAAA,EAAA,eAAA,CAAyB,OAAO,EAChC,EAAS,EAAQ,QAAA,EAAA,EAAA,SAAA,KAAwB,IAAA,EAAS,EAMlD,EAAe,EAAQ,WAAA,EAAA,EAAA,SAAA,KAA2B,EAAQ,EAAO,KAAM,EAG7E,MAAO,CAAE,gBAAA,EAAA,EAAA,SAAA,KAF8B,EAAa,MAAQ,EAAU,IAE7D,EAAgB,UAAS,UAAS,cAAa,CAC1D,EA6Ba,EAAe,IAAwC,CAClE,GAAG,EAAqB,CAAO,EAC/B,GAAG,EAAiB,CAAO,CAC7B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"field-base.d.ts","sourceRoot":"","sources":["../../src/headless/field-base.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { warn as e } from "../_dev.js";
|
|
2
|
-
import { createStableId as t } from "@vielzeug/ore";
|
|
3
|
-
import { computed as n } from "@vielzeug/ripple";
|
|
4
|
-
//#region src/headless/field-base.ts
|
|
5
|
-
var r = (e) => n(() => ({
|
|
6
|
-
errorText: e.error?.value ?? "",
|
|
7
|
-
helperText: e.helper?.value ?? ""
|
|
8
|
-
})), i = (e) => n(() => {
|
|
9
|
-
let t = e.value?.value ?? "", n = e.maxLength?.value, r = Number(n), i = Number.isFinite(r) && r > 0 ? r : null, a = i !== null, o = a ? `${t.length} / ${i}` : "", s = a ? t.length / i : 0;
|
|
10
|
-
return {
|
|
11
|
-
counterAtLimit: a ? s >= 1 : !1,
|
|
12
|
-
counterNearLimit: a ? s >= .9 && s < 1 : !1,
|
|
13
|
-
counterText: o
|
|
14
|
-
};
|
|
15
|
-
}), a = (e, t = "counter") => e ? e.counterAtLimit ? `${t} at-limit` : e.counterNearLimit ? `${t} near-limit` : t : t;
|
|
16
|
-
function o() {
|
|
17
|
-
let e = !1;
|
|
18
|
-
return {
|
|
19
|
-
clear: () => {
|
|
20
|
-
e = !1;
|
|
21
|
-
},
|
|
22
|
-
get isDirty() {
|
|
23
|
-
return e;
|
|
24
|
-
},
|
|
25
|
-
markDirty: () => {
|
|
26
|
-
e = !0;
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
var s = (i) => {
|
|
31
|
-
let a = n(() => !!i.disabled?.value), o = t("helper"), s = t("error"), c = r({
|
|
32
|
-
error: i.error,
|
|
33
|
-
helper: i.helper
|
|
34
|
-
}), l = n(() => c.value.errorText || c.value.helperText ? o : null), u = n(() => c.value.errorText ? s : null), d = n(() => c.value.errorText ? "true" : null), f = null;
|
|
35
|
-
return {
|
|
36
|
-
ariaDescribedBy: l,
|
|
37
|
-
ariaErrorMessage: u,
|
|
38
|
-
ariaInvalid: d,
|
|
39
|
-
assistiveId: o,
|
|
40
|
-
attachFormField: (e) => {
|
|
41
|
-
f = e;
|
|
42
|
-
},
|
|
43
|
-
disabled: a,
|
|
44
|
-
errorId: s,
|
|
45
|
-
errorText: n(() => c.value.errorText),
|
|
46
|
-
helperText: n(() => c.value.helperText),
|
|
47
|
-
triggerValidation: (t) => {
|
|
48
|
-
if (i.validateOn?.value === t) {
|
|
49
|
-
if (!f) {
|
|
50
|
-
e("triggerValidation() called before attachFormField() — validation will not run. See createTextField()/createChoiceField()/createCheckable()'s attachFormField doc comment.");
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
f.reportValidity();
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
}, c = (e) => {
|
|
58
|
-
let r = e.id ?? t(e.prefix ?? "field"), i = t("label"), a = e.label ?? n(() => void 0), o = e.hasLabel ?? n(() => !!a.value);
|
|
59
|
-
return {
|
|
60
|
-
ariaLabelledBy: n(() => o.value ? i : null),
|
|
61
|
-
fieldId: r,
|
|
62
|
-
labelId: i,
|
|
63
|
-
labelVisible: o
|
|
64
|
-
};
|
|
65
|
-
}, l = (e) => ({
|
|
66
|
-
...s(e),
|
|
67
|
-
...c(e)
|
|
68
|
-
});
|
|
69
|
-
//#endregion
|
|
70
|
-
export { a as counterClassName, s as createAssistiveState, i as createCounterState, o as createDirtyTracker, r as createErrorHelperState, l as createField, c as createLabelState };
|
|
71
|
-
|
|
72
|
-
//# sourceMappingURL=field-base.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"field-base.js","names":[],"sources":["../../src/headless/field-base.ts"],"sourcesContent":["import { createStableId } from '@vielzeug/ore';\nimport { computed, type Readable } from '@vielzeug/ripple';\n\nimport { warn } from '../_dev';\n\n// ── Validation / context types ────────────────────────────────────────────────\n\nexport type ValidationTrigger = 'blur' | 'change' | 'input' | 'submit';\nexport type ControlValidationMode = ValidationTrigger | undefined;\n\n// ── Error/helper assistive state ──────────────────────────────────────────────\n\nexport type ErrorHelperState = {\n errorText: string;\n helperText: string;\n};\n\nexport type ErrorHelperOptions = {\n error?: Readable<string | undefined>;\n helper?: Readable<string | undefined>;\n};\n\nexport const createErrorHelperState = (options: ErrorHelperOptions): Readable<ErrorHelperState> =>\n computed(() => ({\n errorText: options.error?.value ?? '',\n helperText: options.helper?.value ?? '',\n }));\n\n// ── Counter state (opt-in) ─────────────────────────────────────────────────────\n\n/** Counter state for text fields with `maxLength`. */\nexport type CounterState = {\n counterAtLimit: boolean;\n counterNearLimit: boolean;\n counterText: string;\n};\n\nexport type CounterOptions = {\n maxLength?: Readable<number | undefined>;\n value: Readable<string | undefined>;\n};\n\n/**\n * Creates a reactive counter state signal for text fields with `maxLength`.\n * Only call this when `maxLength` may be set — the state is genuinely opt-in.\n *\n * @example\n * ```ts\n * const counter = createCounterState({ value: tf.value, maxLength: props.maxlength });\n * ```\n */\nexport const createCounterState = (options: CounterOptions): Readable<CounterState> =>\n computed<CounterState>(() => {\n const value = options.value?.value ?? '';\n const maxLength = options.maxLength?.value;\n const parsedMaxLength = Number(maxLength);\n const validMaxLength = Number.isFinite(parsedMaxLength) && parsedMaxLength > 0 ? parsedMaxLength : null;\n const hasCounter = validMaxLength !== null;\n const counterText = hasCounter ? `${value.length} / ${validMaxLength}` : '';\n const ratio = hasCounter ? value.length / validMaxLength : 0;\n\n return {\n counterAtLimit: hasCounter ? ratio >= 1 : false,\n counterNearLimit: hasCounter ? ratio >= 0.9 && ratio < 1 : false,\n counterText,\n };\n });\n\n/**\n * The single implementation of \"which modifier class does this counter state map to\" —\n * every field with a character counter (`ore-input`, `ore-textarea`, `ore-message-composer`)\n * renders the identical near-limit/at-limit styling, so this is the one place that decides it.\n *\n * @example\n * ```ts\n * html`<span class=\"${() => counterClassName(counter?.value)}\">...</span>`\n * ```\n */\nexport const counterClassName = (counter: CounterState | undefined, base = 'counter'): string => {\n if (!counter) return base;\n\n if (counter.counterAtLimit) return `${base} at-limit`;\n\n if (counter.counterNearLimit) return `${base} near-limit`;\n\n return base;\n};\n\n// ── Dirty tracking (two-state reset) ───────────────────────────────────────────\n\n/**\n * Tracks whether a control's value has ever been changed by user interaction.\n *\n * Backs the \"two-state reset()\" pattern used by `createCheckable` (`checked`/\n * `indeterminate`) and `createChoiceField` (`selectedValues`): before the first\n * interaction, the live prop is still a reliable \"current default\" to resync from\n * (e.g. an async-loaded value arriving after mount); after it, the prop is\n * contaminated by interaction-driven attribute reflection, so only a snapshot taken\n * at creation still represents \"the default\" in the native sense. `reset()` callers\n * check `isDirty` to decide which source to revert to, then call `clear()`.\n */\nexport type DirtyTracker = {\n clear: () => void;\n readonly isDirty: boolean;\n markDirty: () => void;\n};\n\nexport function createDirtyTracker(): DirtyTracker {\n let dirty = false;\n\n return {\n clear: () => {\n dirty = false;\n },\n get isDirty() {\n return dirty;\n },\n markDirty: () => {\n dirty = true;\n },\n };\n}\n\n// ── Label placement ───────────────────────────────────────────────────────────\n\nexport type LabelPlacement = 'inset' | 'outside' | undefined;\n\n// ── Assistive state (error/helper text, describedby/errormessage/invalid) ─────\n\n/**\n * A field's error/helper/disabled/validation-trigger state — everything an input\n * needs *except* a visible `<label>`. Split out from label state (below) because\n * not every field has one: `ore-message-composer` names itself via `aria-label`\n * (a chat composer's accessible name conventionally comes from context/placeholder,\n * not a floating `<label>`), so it composes this directly instead of pulling in\n * label plumbing it can't use. `createField()` composes both for fields that do\n * render a `<label>`.\n */\nexport type AssistiveStateHandle = {\n /** `aria-describedby` value. Non-null when helper or error text is present. */\n ariaDescribedBy: Readable<string | null>;\n /** `aria-errormessage` value. Non-null when error text is present. */\n ariaErrorMessage: Readable<string | null>;\n /** `aria-invalid` value. `'true'` when error text is present, otherwise `null`. */\n ariaInvalid: Readable<'true' | null>;\n /**\n * The stable `id` used for `aria-describedby` on the input. Points at the\n * assistive-text region (covers both helper text and error text per WAI-ARIA).\n */\n assistiveId: string;\n /**\n * Registers the real form field handle (the return value of `useField()`) so that\n * `triggerValidation()` can call its `reportValidity()`. See `TextFieldHandle.attachFormField`\n * for why this is a post-hoc call instead of a constructor option — the same forward\n * reference applies here for choice fields.\n */\n attachFormField: (formField: { reportValidity(): void }) => void;\n disabled: Readable<boolean>;\n /** Stable `id` for the inline error message element (`aria-errormessage`). */\n errorId: string;\n /** Reactive error text. Empty string when no error is set. */\n errorText: Readable<string>;\n /** Reactive helper text. Empty string when no helper is set. */\n helperText: Readable<string>;\n triggerValidation: (on: Extract<ValidationTrigger, 'blur' | 'change'>) => void;\n};\n\nexport type AssistiveStateOptions = {\n disabled?: Readable<boolean | undefined>;\n error?: Readable<string | undefined>;\n helper?: Readable<string | undefined>;\n validateOn?: Readable<ControlValidationMode>;\n};\n\nexport const createAssistiveState = (options: AssistiveStateOptions): AssistiveStateHandle => {\n const disabled = computed(() => Boolean(options.disabled?.value));\n const assistiveId = createStableId('helper');\n const errorId = createStableId('error');\n const resolvedAssistive = createErrorHelperState({ error: options.error, helper: options.helper });\n\n const ariaDescribedBy = computed(() =>\n resolvedAssistive.value.errorText || resolvedAssistive.value.helperText ? assistiveId : null,\n );\n const ariaErrorMessage = computed(() => (resolvedAssistive.value.errorText ? errorId : null));\n const ariaInvalid = computed<'true' | null>(() => (resolvedAssistive.value.errorText ? 'true' : null));\n\n let formField: { reportValidity(): void } | null = null;\n const attachFormField = (nextFormField: { reportValidity(): void }): void => {\n formField = nextFormField;\n };\n\n const triggerValidation = (on: Extract<ValidationTrigger, 'blur' | 'change'>): void => {\n if (options.validateOn?.value !== on) return;\n\n if (!formField) {\n // Not user-facing — this only fires when a component author wired `validateOn` but\n // forgot the matching `attachFormField(useField(...))` call, so validation silently\n // never runs instead of erroring where the mistake actually is.\n warn(\n \"triggerValidation() called before attachFormField() — validation will not run. See createTextField()/createChoiceField()/createCheckable()'s attachFormField doc comment.\",\n );\n\n return;\n }\n\n formField.reportValidity();\n };\n\n return {\n ariaDescribedBy,\n ariaErrorMessage,\n ariaInvalid,\n assistiveId,\n attachFormField,\n disabled,\n errorId,\n errorText: computed(() => resolvedAssistive.value.errorText),\n helperText: computed(() => resolvedAssistive.value.helperText),\n triggerValidation,\n };\n};\n\n// ── Label state (visible `<label>` + `aria-labelledby`) ────────────────────────\n\nexport type LabelStateHandle = {\n /** `aria-labelledby` value. Non-null when a label is visible. */\n ariaLabelledBy: Readable<string | null>;\n /** Stable `id` for the underlying form control — the `<label for=\"...\">` target. */\n fieldId: string;\n /** Stable `id` for the label element. Stamp this on your `<label id=\"...\">`. */\n labelId: string;\n /** Whether the label should be visible. Use to toggle `hidden` on the `<label>`. */\n labelVisible: Readable<boolean>;\n};\n\nexport type LabelStateOptions = {\n /**\n * Override for label visibility that takes precedence over deriving it from\n * the `label` text signal. Pass a computed signal that checks both prop and\n * slot presence to enable slot-first composition.\n *\n * @example\n * ```ts\n * const hasLabel = computed(() => !!props.label.value || slots.has('label').value);\n * const label = createLabelState({ ...options, hasLabel });\n * ```\n */\n hasLabel?: Readable<boolean>;\n /**\n * When provided, used directly as `fieldId` instead of generating one via\n * `createStableId`. Useful in tests for deterministic ID assertions.\n */\n id?: string;\n /**\n * Label text signal. When provided, `labelVisible` and `ariaLabelledBy` are\n * computed reactively from this value (see `hasLabel` for the slot-first override).\n */\n label?: Readable<string | undefined>;\n /**\n * Label placement signal. Defaults to `'inset'`.\n *\n * Not consumed by `createLabelState()` itself — visibility is driven solely by\n * `hasLabel`/`label`. Threaded through so component authors can apply\n * placement-specific styling (`label-placement` attribute) without a second\n * option; if placement-dependent visibility is ever needed, wire it into\n * `labelVisible` here instead of adding a new option.\n */\n labelPlacement?: Readable<LabelPlacement>;\n prefix?: string;\n};\n\nexport const createLabelState = (options: LabelStateOptions): LabelStateHandle => {\n const fieldId = options.id ?? createStableId(options.prefix ?? 'field');\n const labelId = createStableId('label');\n const label$ = options.label ?? computed(() => undefined);\n\n // Slot-first composition: if the caller provides `hasLabel`, use it instead\n // of deriving visibility purely from the label text signal. This allows\n // components with a `<slot name=\"label\">` to stay visible even when the\n // `label` prop is empty but a slotted label element is present.\n const labelVisible = options.hasLabel ?? computed(() => Boolean(label$.value));\n const ariaLabelledBy = computed(() => (labelVisible.value ? labelId : null));\n\n return { ariaLabelledBy, fieldId, labelId, labelVisible };\n};\n\n// ── Field handle (assistive + label, composed) ──────────────────────────────\n\n/**\n * Common handle returned by `createField` — the base for both `TextFieldHandle`\n * and `ChoiceFieldHandle`. Composes `createAssistiveState` + `createLabelState`;\n * call those directly instead if a field has no visible `<label>` (see\n * `createAssistiveState`'s doc comment).\n *\n * ARIA signals and label state are flat on the handle — no nested `aria` or\n * `label` sub-objects. `labelId`/`labelVisible`/`ariaLabelledBy` are always\n * present but only meaningful when `label`/`hasLabel` was passed — omit both\n * and they resolve to an always-hidden, unreferenced label.\n *\n * @example\n * ```html\n * <label id=\"${labelId}\" ?hidden=\"${() => !labelVisible.value}\">...</label>\n * <input\n * :aria-labelledby=\"${ariaLabelledBy}\"\n * :aria-describedby=\"${ariaDescribedBy}\"\n * :aria-invalid=\"${ariaInvalid}\" />\n * ```\n */\nexport type FieldHandle = AssistiveStateHandle & LabelStateHandle;\n\n/** Options shared by both `createTextField` and `createChoiceField`. */\nexport type FieldOptions = AssistiveStateOptions & LabelStateOptions;\n\nexport const createField = (options: FieldOptions): FieldHandle => ({\n ...createAssistiveState(options),\n ...createLabelState(options),\n});\n"],"mappings":";;;;AAsBA,IAAa,KAA0B,MACrC,SAAgB;CACd,WAAW,EAAQ,OAAO,SAAS;CACnC,YAAY,EAAQ,QAAQ,SAAS;AACvC,EAAE,GAyBS,KAAsB,MACjC,QAA6B;CAC3B,IAAM,IAAQ,EAAQ,OAAO,SAAS,IAChC,IAAY,EAAQ,WAAW,OAC/B,IAAkB,OAAO,CAAS,GAClC,IAAiB,OAAO,SAAS,CAAe,KAAK,IAAkB,IAAI,IAAkB,MAC7F,IAAa,MAAmB,MAChC,IAAc,IAAa,GAAG,EAAM,OAAO,KAAK,MAAmB,IACnE,IAAQ,IAAa,EAAM,SAAS,IAAiB;CAE3D,OAAO;EACL,gBAAgB,IAAa,KAAS,IAAI;EAC1C,kBAAkB,IAAa,KAAS,MAAO,IAAQ,IAAI;EAC3D;CACF;AACF,CAAC,GAYU,KAAoB,GAAmC,IAAO,cACpE,IAED,EAAQ,iBAAuB,GAAG,EAAK,aAEvC,EAAQ,mBAAyB,GAAG,EAAK,eAEtC,IANc;AA4BvB,SAAgB,IAAmC;CACjD,IAAI,IAAQ;CAEZ,OAAO;EACL,aAAa;GACX,IAAQ;EACV;EACA,IAAI,UAAU;GACZ,OAAO;EACT;EACA,iBAAiB;GACf,IAAQ;EACV;CACF;AACF;AAqDA,IAAa,KAAwB,MAAyD;CAC5F,IAAM,IAAW,QAAe,EAAQ,EAAQ,UAAU,KAAM,GAC1D,IAAc,EAAe,QAAQ,GACrC,IAAU,EAAe,OAAO,GAChC,IAAoB,EAAuB;EAAE,OAAO,EAAQ;EAAO,QAAQ,EAAQ;CAAO,CAAC,GAE3F,IAAkB,QACtB,EAAkB,MAAM,aAAa,EAAkB,MAAM,aAAa,IAAc,IAC1F,GACM,IAAmB,QAAgB,EAAkB,MAAM,YAAY,IAAU,IAAK,GACtF,IAAc,QAA+B,EAAkB,MAAM,YAAY,SAAS,IAAK,GAEjG,IAA+C;CAsBnD,OAAO;EACL;EACA;EACA;EACA;EACA,kBA1BuB,MAAoD;GAC3E,IAAY;EACd;EAyBE;EACA;EACA,WAAW,QAAe,EAAkB,MAAM,SAAS;EAC3D,YAAY,QAAe,EAAkB,MAAM,UAAU;EAC7D,oBA3ByB,MAA4D;GACjF,MAAQ,YAAY,UAAU,GAElC;QAAI,CAAC,GAAW;KAId,EACE,2KACF;KAEA;IACF;IAEA,EAAU,eAAe;GAFzB;EAGF;CAaA;AACF,GAmDa,KAAoB,MAAiD;CAChF,IAAM,IAAU,EAAQ,MAAM,EAAe,EAAQ,UAAU,OAAO,GAChE,IAAU,EAAe,OAAO,GAChC,IAAS,EAAQ,SAAS,QAAe,KAAA,CAAS,GAMlD,IAAe,EAAQ,YAAY,QAAe,EAAQ,EAAO,KAAM;CAG7E,OAAO;EAAE,gBAFc,QAAgB,EAAa,QAAQ,IAAU,IAE7D;EAAgB;EAAS;EAAS;CAAa;AAC1D,GA6Ba,KAAe,OAAwC;CAClE,GAAG,EAAqB,CAAO;CAC/B,GAAG,EAAiB,CAAO;AAC7B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus.cjs","names":[],"sources":["../../src/headless/focus.ts"],"sourcesContent":["// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FocusManagerOptions = {\n /**\n * Returns the CSS selector for the element that should receive focus on open.\n *\n * **Security note:** this value is passed directly to `querySelector`. It must\n * come from trusted developer-controlled configuration, never from raw user input.\n */\n getInitialFocusSelector: () => string | undefined;\n /**\n * Returns whether focus should be restored to the previously focused element\n * on close. `undefined` or `true` means restore; `false` means skip.\n */\n getReturnFocus: () => boolean | undefined;\n /** Host element used for `querySelector` when resolving the initial focus target. */\n host: HTMLElement;\n /**\n * `AbortSignal` from the component lifecycle. Cancels a pending `applyInitialFocus()`\n * animation frame automatically on abort — prevents a stray `.focus()` call landing on an\n * element that's been disconnected in the meantime (e.g. the dialog closes and unmounts\n * before the deferred focus frame runs).\n */\n signal?: AbortSignal;\n};\n\nexport type FocusManager = {\n /** Move focus to the element matching `getInitialFocusSelector` (deferred one frame). */\n applyInitialFocus: () => void;\n /** Cancel a pending `applyInitialFocus` rAF, if any. */\n cancelInitialFocus: () => void;\n /** Capture the currently focused element so it can be restored later. */\n captureReturnFocus: () => void;\n /** Restore focus to the element captured by `captureReturnFocus`. */\n restoreFocus: () => void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Encapsulates the three-step focus lifecycle used by dialogs and drawers:\n * 1. Capture the element that triggered the open.\n * 2. Move focus inside the overlay (optionally to a specific element).\n * 3. Restore focus when the overlay closes.\n */\nexport function createFocusManager(options: FocusManagerOptions): FocusManager {\n let returnFocusEl: HTMLElement | null = null;\n let rafHandle: ReturnType<typeof requestAnimationFrame> | null = null;\n\n const cancelInitialFocus = (): void => {\n if (rafHandle !== null) {\n cancelAnimationFrame(rafHandle);\n rafHandle = null;\n }\n };\n\n options.signal?.addEventListener('abort', cancelInitialFocus, { once: true });\n\n return {\n applyInitialFocus() {\n cancelInitialFocus();\n\n const selector = options.getInitialFocusSelector();\n\n if (selector) {\n // Query the shadow root first (all refine components render into Shadow DOM),\n // falling back to the host's light-DOM tree for non-Shadow contexts.\n const root = options.host.shadowRoot ?? options.host;\n\n let target: HTMLElement | null = null;\n\n try {\n target = root.querySelector<HTMLElement>(selector);\n } catch {\n // Malformed selector (SyntaxError) — skip initial focus rather than throw.\n return;\n }\n\n if (target) {\n rafHandle = requestAnimationFrame(() => {\n rafHandle = null;\n target.focus();\n });\n }\n }\n },\n\n cancelInitialFocus,\n\n captureReturnFocus() {\n returnFocusEl = document.activeElement as HTMLElement;\n },\n\n restoreFocus() {\n if (options.getReturnFocus() !== false && returnFocusEl) {\n returnFocusEl.focus();\n returnFocusEl = null;\n }\n },\n };\n}\n"],"mappings":"AA6CA,SAAgB,EAAmB,EAA4C,CAC7E,IAAI,EAAoC,KACpC,EAA6D,KAE3D,MAAiC,CACjC,IAAc,OAChB,qBAAqB,CAAS,EAC9B,EAAY,KAEhB,EAIA,OAFA,EAAQ,QAAQ,iBAAiB,QAAS,EAAoB,CAAE,KAAM,EAAK,CAAC,EAErE,CACL,mBAAoB,CAClB,EAAmB,EAEnB,IAAM,EAAW,EAAQ,wBAAwB,EAEjD,GAAI,EAAU,CAGZ,IAAM,EAAO,EAAQ,KAAK,YAAc,EAAQ,KAE5C,EAA6B,KAEjC,GAAI,CACF,EAAS,EAAK,cAA2B,CAAQ,CACnD,MAAQ,CAEN,MACF,CAEI,IACF,EAAY,0BAA4B,CACtC,EAAY,KACZ,EAAO,MAAM,CACf,CAAC,EAEL,CACF,EAEA,qBAEA,oBAAqB,CACnB,EAAgB,SAAS,aAC3B,EAEA,cAAe,CACT,EAAQ,eAAe,IAAM,IAAS,IACxC,EAAc,MAAM,EACpB,EAAgB,KAEpB,CACF,CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../../src/headless/focus.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,mBAAmB,GAAG;IAChC;;;;;OAKG;IACH,uBAAuB,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAClD;;;OAGG;IACH,cAAc,EAAE,MAAM,OAAO,GAAG,SAAS,CAAC;IAC1C,qFAAqF;IACrF,IAAI,EAAE,WAAW,CAAC;IAClB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,yFAAyF;IACzF,iBAAiB,EAAE,MAAM,IAAI,CAAC;IAC9B,wDAAwD;IACxD,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,yEAAyE;IACzE,kBAAkB,EAAE,MAAM,IAAI,CAAC;IAC/B,qEAAqE;IACrE,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAIF;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,YAAY,CAuD7E"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"focus.js","names":[],"sources":["../../src/headless/focus.ts"],"sourcesContent":["// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type FocusManagerOptions = {\n /**\n * Returns the CSS selector for the element that should receive focus on open.\n *\n * **Security note:** this value is passed directly to `querySelector`. It must\n * come from trusted developer-controlled configuration, never from raw user input.\n */\n getInitialFocusSelector: () => string | undefined;\n /**\n * Returns whether focus should be restored to the previously focused element\n * on close. `undefined` or `true` means restore; `false` means skip.\n */\n getReturnFocus: () => boolean | undefined;\n /** Host element used for `querySelector` when resolving the initial focus target. */\n host: HTMLElement;\n /**\n * `AbortSignal` from the component lifecycle. Cancels a pending `applyInitialFocus()`\n * animation frame automatically on abort — prevents a stray `.focus()` call landing on an\n * element that's been disconnected in the meantime (e.g. the dialog closes and unmounts\n * before the deferred focus frame runs).\n */\n signal?: AbortSignal;\n};\n\nexport type FocusManager = {\n /** Move focus to the element matching `getInitialFocusSelector` (deferred one frame). */\n applyInitialFocus: () => void;\n /** Cancel a pending `applyInitialFocus` rAF, if any. */\n cancelInitialFocus: () => void;\n /** Capture the currently focused element so it can be restored later. */\n captureReturnFocus: () => void;\n /** Restore focus to the element captured by `captureReturnFocus`. */\n restoreFocus: () => void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Encapsulates the three-step focus lifecycle used by dialogs and drawers:\n * 1. Capture the element that triggered the open.\n * 2. Move focus inside the overlay (optionally to a specific element).\n * 3. Restore focus when the overlay closes.\n */\nexport function createFocusManager(options: FocusManagerOptions): FocusManager {\n let returnFocusEl: HTMLElement | null = null;\n let rafHandle: ReturnType<typeof requestAnimationFrame> | null = null;\n\n const cancelInitialFocus = (): void => {\n if (rafHandle !== null) {\n cancelAnimationFrame(rafHandle);\n rafHandle = null;\n }\n };\n\n options.signal?.addEventListener('abort', cancelInitialFocus, { once: true });\n\n return {\n applyInitialFocus() {\n cancelInitialFocus();\n\n const selector = options.getInitialFocusSelector();\n\n if (selector) {\n // Query the shadow root first (all refine components render into Shadow DOM),\n // falling back to the host's light-DOM tree for non-Shadow contexts.\n const root = options.host.shadowRoot ?? options.host;\n\n let target: HTMLElement | null = null;\n\n try {\n target = root.querySelector<HTMLElement>(selector);\n } catch {\n // Malformed selector (SyntaxError) — skip initial focus rather than throw.\n return;\n }\n\n if (target) {\n rafHandle = requestAnimationFrame(() => {\n rafHandle = null;\n target.focus();\n });\n }\n }\n },\n\n cancelInitialFocus,\n\n captureReturnFocus() {\n returnFocusEl = document.activeElement as HTMLElement;\n },\n\n restoreFocus() {\n if (options.getReturnFocus() !== false && returnFocusEl) {\n returnFocusEl.focus();\n returnFocusEl = null;\n }\n },\n };\n}\n"],"mappings":";AA6CA,SAAgB,EAAmB,GAA4C;CAC7E,IAAI,IAAoC,MACpC,IAA6D,MAE3D,UAAiC;EACrC,AAAI,MAAc,SAChB,qBAAqB,CAAS,GAC9B,IAAY;CAEhB;CAIA,OAFA,EAAQ,QAAQ,iBAAiB,SAAS,GAAoB,EAAE,MAAM,GAAK,CAAC,GAErE;EACL,oBAAoB;GAClB,EAAmB;GAEnB,IAAM,IAAW,EAAQ,wBAAwB;GAEjD,IAAI,GAAU;IAGZ,IAAM,IAAO,EAAQ,KAAK,cAAc,EAAQ,MAE5C,IAA6B;IAEjC,IAAI;KACF,IAAS,EAAK,cAA2B,CAAQ;IACnD,QAAQ;KAEN;IACF;IAEA,AAAI,MACF,IAAY,4BAA4B;KAEtC,AADA,IAAY,MACZ,EAAO,MAAM;IACf,CAAC;GAEL;EACF;EAEA;EAEA,qBAAqB;GACnB,IAAgB,SAAS;EAC3B;EAEA,eAAe;GACb,AAAI,EAAQ,eAAe,MAAM,MAAS,MACxC,EAAc,MAAM,GACpB,IAAgB;EAEpB;CACF;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/headless/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.cjs","names":[],"sources":["../../src/headless/keyboard.ts"],"sourcesContent":["import type { Readable } from '@vielzeug/ripple';\n\n// ── Keyboard dispatch ─────────────────────────────────────────────────────────\n\nexport type KeyboardDispatchOptions = {\n disabled?: Readable<boolean | undefined>;\n keymap: Record<string, (event: KeyboardEvent) => boolean | void>;\n preventDefault?: 'after' | 'before' | false;\n};\n\nexport const dispatchKeyboardAction = (event: KeyboardEvent, options: KeyboardDispatchOptions): boolean => {\n if (options.disabled?.value) return false;\n\n // `event.key` is attacker-influenceable on a synthetic KeyboardEvent (e.g. `new\n // KeyboardEvent('keydown', { key: '__proto__' })`). Guard with `Object.hasOwn` so a\n // crafted key name can never resolve to an inherited `Object.prototype` member\n // (`__proto__`, `constructor`, `toString`, …) instead of `undefined`.\n const action = Object.hasOwn(options.keymap, event.key) ? options.keymap[event.key] : undefined;\n\n if (!action) return false;\n\n const preventDefaultMode = options.preventDefault ?? 'before';\n\n if (preventDefaultMode === 'before') event.preventDefault();\n\n const handled = action(event) !== false;\n\n if (preventDefaultMode === 'after' && handled) event.preventDefault();\n\n return handled;\n};\n\n// ── Press control / Interaction ───────────────────────────────────────────────\n\nexport type PressTrigger = 'keyboard' | 'pointer';\n\n/**\n * Options for `createInteraction` — a unified press + focus/blur interaction\n * handler for accessible interactive elements.\n */\nexport type InteractionOptions = {\n /** `true` when the element is disabled. All handlers become no-ops. */\n disabled?: Readable<boolean | undefined>;\n /** Keys that trigger a press. Defaults to `['Enter', ' ']`. */\n keys?: string[];\n /** Called when the element loses focus. */\n onBlur?: (event: FocusEvent) => void;\n /** Called when the element receives focus. */\n onFocus?: (event: FocusEvent) => void;\n /** Called when the element is pressed via keyboard or pointer. */\n onPress?: (event: KeyboardEvent | MouseEvent, trigger: PressTrigger) => void;\n};\n\nexport type Interaction = {\n handleBlur: (event: FocusEvent) => void;\n handleClick: (event: MouseEvent) => boolean;\n handleFocus: (event: FocusEvent) => void;\n handleKeydown: (event: KeyboardEvent) => boolean;\n};\n\n/**\n * Creates a set of event handlers for an interactive element that responds to\n * keyboard and pointer presses, and optionally focus/blur events.\n *\n * @example\n * ```ts\n * const interaction = createInteraction({\n * disabled: props.disabled,\n * onPress: (event, trigger) => toggle(event),\n * onFocus: (event) => setFocused(true),\n * onBlur: (event) => setFocused(false),\n * });\n *\n * // In template:\n * // @click=\"${interaction.handleClick}\"\n * // @keydown=\"${interaction.handleKeydown}\"\n * // @focus=\"${interaction.handleFocus}\"\n * // @blur=\"${interaction.handleBlur}\"\n * ```\n */\nexport const createInteraction = (options: InteractionOptions): Interaction => {\n const isDisabled = (): boolean => Boolean(options.disabled?.value);\n const keyboardKeys = options.keys ?? ['Enter', ' '];\n const keymap = Object.fromEntries(\n keyboardKeys.map((key) => [key, (keyboardEvent: KeyboardEvent) => options.onPress?.(keyboardEvent, 'keyboard')]),\n );\n\n return {\n handleBlur: (event: FocusEvent): void => {\n if (!isDisabled()) options.onBlur?.(event);\n },\n handleClick: (event: MouseEvent): boolean => {\n if (isDisabled()) return false;\n\n options.onPress?.(event, 'pointer');\n\n return true;\n },\n handleFocus: (event: FocusEvent): void => {\n if (!isDisabled()) options.onFocus?.(event);\n },\n handleKeydown: (event: KeyboardEvent): boolean =>\n dispatchKeyboardAction(event, { disabled: options.disabled, keymap }),\n };\n};\n"],"mappings":"AAUA,IAAa,GAA0B,EAAsB,IAA8C,CACzG,GAAI,EAAQ,UAAU,MAAO,MAAO,GAMpC,IAAM,EAAS,OAAO,OAAO,EAAQ,OAAQ,EAAM,GAAG,EAAI,EAAQ,OAAO,EAAM,KAAO,IAAA,GAEtF,GAAI,CAAC,EAAQ,MAAO,GAEpB,IAAM,EAAqB,EAAQ,gBAAkB,SAEjD,IAAuB,UAAU,EAAM,eAAe,EAE1D,IAAM,EAAU,EAAO,CAAK,IAAM,GAIlC,OAFI,IAAuB,SAAW,GAAS,EAAM,eAAe,EAE7D,CACT,EAkDa,EAAqB,GAA6C,CAC7E,IAAM,MAA4B,EAAQ,EAAQ,UAAU,MACtD,EAAe,EAAQ,MAAQ,CAAC,QAAS,GAAG,EAC5C,EAAS,OAAO,YACpB,EAAa,IAAK,GAAQ,CAAC,EAAM,GAAiC,EAAQ,UAAU,EAAe,UAAU,CAAC,CAAC,CACjH,EAEA,MAAO,CACL,WAAa,GAA4B,CAClC,EAAW,GAAG,EAAQ,SAAS,CAAK,CAC3C,EACA,YAAc,GACR,EAAW,EAAU,IAEzB,EAAQ,UAAU,EAAO,SAAS,EAE3B,IAET,YAAc,GAA4B,CACnC,EAAW,GAAG,EAAQ,UAAU,CAAK,CAC5C,EACA,cAAgB,GACd,EAAuB,EAAO,CAAE,SAAU,EAAQ,SAAU,QAAO,CAAC,CACxE,CACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../../src/headless/keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAIjD,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC;IACjE,cAAc,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;CAC7C,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,OAAO,aAAa,EAAE,SAAS,uBAAuB,KAAG,OAoB/F,CAAC;AAIF,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,SAAS,CAAC;AAElD;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IACzC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,2CAA2C;IAC3C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACrC,8CAA8C;IAC9C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,kEAAkE;IAClE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,EAAE,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;CAC9E,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,WAAW,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC;IAC5C,WAAW,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,aAAa,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,OAAO,CAAC;CAClD,CAAC;AAEF;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,iBAAiB,GAAI,SAAS,kBAAkB,KAAG,WAwB/D,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard.js","names":[],"sources":["../../src/headless/keyboard.ts"],"sourcesContent":["import type { Readable } from '@vielzeug/ripple';\n\n// ── Keyboard dispatch ─────────────────────────────────────────────────────────\n\nexport type KeyboardDispatchOptions = {\n disabled?: Readable<boolean | undefined>;\n keymap: Record<string, (event: KeyboardEvent) => boolean | void>;\n preventDefault?: 'after' | 'before' | false;\n};\n\nexport const dispatchKeyboardAction = (event: KeyboardEvent, options: KeyboardDispatchOptions): boolean => {\n if (options.disabled?.value) return false;\n\n // `event.key` is attacker-influenceable on a synthetic KeyboardEvent (e.g. `new\n // KeyboardEvent('keydown', { key: '__proto__' })`). Guard with `Object.hasOwn` so a\n // crafted key name can never resolve to an inherited `Object.prototype` member\n // (`__proto__`, `constructor`, `toString`, …) instead of `undefined`.\n const action = Object.hasOwn(options.keymap, event.key) ? options.keymap[event.key] : undefined;\n\n if (!action) return false;\n\n const preventDefaultMode = options.preventDefault ?? 'before';\n\n if (preventDefaultMode === 'before') event.preventDefault();\n\n const handled = action(event) !== false;\n\n if (preventDefaultMode === 'after' && handled) event.preventDefault();\n\n return handled;\n};\n\n// ── Press control / Interaction ───────────────────────────────────────────────\n\nexport type PressTrigger = 'keyboard' | 'pointer';\n\n/**\n * Options for `createInteraction` — a unified press + focus/blur interaction\n * handler for accessible interactive elements.\n */\nexport type InteractionOptions = {\n /** `true` when the element is disabled. All handlers become no-ops. */\n disabled?: Readable<boolean | undefined>;\n /** Keys that trigger a press. Defaults to `['Enter', ' ']`. */\n keys?: string[];\n /** Called when the element loses focus. */\n onBlur?: (event: FocusEvent) => void;\n /** Called when the element receives focus. */\n onFocus?: (event: FocusEvent) => void;\n /** Called when the element is pressed via keyboard or pointer. */\n onPress?: (event: KeyboardEvent | MouseEvent, trigger: PressTrigger) => void;\n};\n\nexport type Interaction = {\n handleBlur: (event: FocusEvent) => void;\n handleClick: (event: MouseEvent) => boolean;\n handleFocus: (event: FocusEvent) => void;\n handleKeydown: (event: KeyboardEvent) => boolean;\n};\n\n/**\n * Creates a set of event handlers for an interactive element that responds to\n * keyboard and pointer presses, and optionally focus/blur events.\n *\n * @example\n * ```ts\n * const interaction = createInteraction({\n * disabled: props.disabled,\n * onPress: (event, trigger) => toggle(event),\n * onFocus: (event) => setFocused(true),\n * onBlur: (event) => setFocused(false),\n * });\n *\n * // In template:\n * // @click=\"${interaction.handleClick}\"\n * // @keydown=\"${interaction.handleKeydown}\"\n * // @focus=\"${interaction.handleFocus}\"\n * // @blur=\"${interaction.handleBlur}\"\n * ```\n */\nexport const createInteraction = (options: InteractionOptions): Interaction => {\n const isDisabled = (): boolean => Boolean(options.disabled?.value);\n const keyboardKeys = options.keys ?? ['Enter', ' '];\n const keymap = Object.fromEntries(\n keyboardKeys.map((key) => [key, (keyboardEvent: KeyboardEvent) => options.onPress?.(keyboardEvent, 'keyboard')]),\n );\n\n return {\n handleBlur: (event: FocusEvent): void => {\n if (!isDisabled()) options.onBlur?.(event);\n },\n handleClick: (event: MouseEvent): boolean => {\n if (isDisabled()) return false;\n\n options.onPress?.(event, 'pointer');\n\n return true;\n },\n handleFocus: (event: FocusEvent): void => {\n if (!isDisabled()) options.onFocus?.(event);\n },\n handleKeydown: (event: KeyboardEvent): boolean =>\n dispatchKeyboardAction(event, { disabled: options.disabled, keymap }),\n };\n};\n"],"mappings":";AAUA,IAAa,KAA0B,GAAsB,MAA8C;CACzG,IAAI,EAAQ,UAAU,OAAO,OAAO;CAMpC,IAAM,IAAS,OAAO,OAAO,EAAQ,QAAQ,EAAM,GAAG,IAAI,EAAQ,OAAO,EAAM,OAAO,KAAA;CAEtF,IAAI,CAAC,GAAQ,OAAO;CAEpB,IAAM,IAAqB,EAAQ,kBAAkB;CAErD,AAAI,MAAuB,YAAU,EAAM,eAAe;CAE1D,IAAM,IAAU,EAAO,CAAK,MAAM;CAIlC,OAFI,MAAuB,WAAW,KAAS,EAAM,eAAe,GAE7D;AACT,GAkDa,KAAqB,MAA6C;CAC7E,IAAM,UAA4B,EAAQ,EAAQ,UAAU,OACtD,IAAe,EAAQ,QAAQ,CAAC,SAAS,GAAG,GAC5C,IAAS,OAAO,YACpB,EAAa,KAAK,MAAQ,CAAC,IAAM,MAAiC,EAAQ,UAAU,GAAe,UAAU,CAAC,CAAC,CACjH;CAEA,OAAO;EACL,aAAa,MAA4B;GACvC,AAAK,EAAW,KAAG,EAAQ,SAAS,CAAK;EAC3C;EACA,cAAc,MACR,EAAW,IAAU,MAEzB,EAAQ,UAAU,GAAO,SAAS,GAE3B;EAET,cAAc,MAA4B;GACxC,AAAK,EAAW,KAAG,EAAQ,UAAU,CAAK;EAC5C;EACA,gBAAgB,MACd,EAAuB,GAAO;GAAE,UAAU,EAAQ;GAAU;EAAO,CAAC;CACxE;AACF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"light-dom.cjs","names":[],"sources":["../../src/headless/light-dom.ts"],"sourcesContent":["// ── Slot / light-DOM query helpers ────────────────────────────────────────────\n// Utilities for querying slotted light-DOM children and resolving labels from\n// option elements. Used by group components (checkbox-group, radio-group) and\n// choice-field components (select, combobox).\n\n/**\n * Returns all light-DOM descendants matching `tag` inside `host`.\n * Uses `getElementsByTagName` on the host's light DOM \\u2014 not Shadow DOM slot assignment.\n */\nexport const getLightChildrenByTag = (host: HTMLElement, tag: string): HTMLElement[] =>\n Array.from(host.getElementsByTagName(tag)) as HTMLElement[];\n\n/**\n * Returns the `textContent` of the item whose `value` attribute matches `value`,\n * falling back to `value` itself when no match is found.\n * Used by choice-field components to derive labels for emitted change events.\n */\nexport const getChoiceLabel = (items: HTMLElement[], value: string): string => {\n const item = items.find((el) => (el.getAttribute('value') ?? '') === value);\n\n return item?.textContent?.replace(/\\s+/g, ' ').trim() || value;\n};\n"],"mappings":"AASA,IAAa,GAAyB,EAAmB,IACvD,MAAM,KAAK,EAAK,qBAAqB,CAAG,CAAC,EAO9B,GAAkB,EAAsB,IACtC,EAAM,KAAM,IAAQ,EAAG,aAAa,OAAO,GAAK,MAAQ,CAE9D,CAAA,EAAM,aAAa,QAAQ,OAAQ,GAAG,CAAC,CAAC,KAAK,GAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"light-dom.d.ts","sourceRoot":"","sources":["../../src/headless/light-dom.ts"],"names":[],"mappings":"AAKA;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,WAAW,EAAE,KAAK,MAAM,KAAG,WAAW,EACrB,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,WAAW,EAAE,EAAE,OAAO,MAAM,KAAG,MAIpE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"light-dom.js","names":[],"sources":["../../src/headless/light-dom.ts"],"sourcesContent":["// ── Slot / light-DOM query helpers ────────────────────────────────────────────\n// Utilities for querying slotted light-DOM children and resolving labels from\n// option elements. Used by group components (checkbox-group, radio-group) and\n// choice-field components (select, combobox).\n\n/**\n * Returns all light-DOM descendants matching `tag` inside `host`.\n * Uses `getElementsByTagName` on the host's light DOM \\u2014 not Shadow DOM slot assignment.\n */\nexport const getLightChildrenByTag = (host: HTMLElement, tag: string): HTMLElement[] =>\n Array.from(host.getElementsByTagName(tag)) as HTMLElement[];\n\n/**\n * Returns the `textContent` of the item whose `value` attribute matches `value`,\n * falling back to `value` itself when no match is found.\n * Used by choice-field components to derive labels for emitted change events.\n */\nexport const getChoiceLabel = (items: HTMLElement[], value: string): string => {\n const item = items.find((el) => (el.getAttribute('value') ?? '') === value);\n\n return item?.textContent?.replace(/\\s+/g, ' ').trim() || value;\n};\n"],"mappings":";AASA,IAAa,KAAyB,GAAmB,MACvD,MAAM,KAAK,EAAK,qBAAqB,CAAG,CAAC,GAO9B,KAAkB,GAAsB,MACtC,EAAM,MAAM,OAAQ,EAAG,aAAa,OAAO,KAAK,QAAQ,CAE9D,CAAA,EAAM,aAAa,QAAQ,QAAQ,GAAG,CAAC,CAAC,KAAK,KAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nav.cjs","names":[],"sources":["../../src/headless/nav.ts"],"sourcesContent":["import { type Readable, signal } from '@vielzeug/ripple';\n\nimport { dispatchKeyboardAction } from './keyboard';\nimport { createTypeahead } from './typeahead';\n\n// ── Private array search helpers ────────────────────────────────────────────\nconst findForward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx < items.length; idx++) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\nconst findBackward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx >= 0; idx--) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\n/**\n * Arrow-key and Home/End navigation actions. Separate from `ListKeyAction` so\n * keymap declarations never need `Exclude<ListKeyAction, 'typeahead'>`.\n */\nexport type ListNavigationAction = 'first' | 'last' | 'next' | 'prev';\n\n/**\n * All possible navigation action names, including `'typeahead'` (character-key\n * search). Used in `onNavigate` callbacks where both nav and typeahead are valid.\n */\nexport type ListKeyAction = ListNavigationAction | 'typeahead';\n\n/**\n * Orientation-aware default key bindings for list navigation.\n * - `'vertical'` (default): Up/Down arrows, Home/End\n * - `'horizontal'`: Left/Right arrows, Home/End\n * - `'both'`: all four arrow keys + Home/End\n */\nconst DEFAULT_KEYS: Record<'both' | 'horizontal' | 'vertical', Record<ListNavigationAction, string[]>> = {\n both: { first: ['Home'], last: ['End'], next: ['ArrowDown', 'ArrowRight'], prev: ['ArrowUp', 'ArrowLeft'] },\n horizontal: { first: ['Home'], last: ['End'], next: ['ArrowRight'], prev: ['ArrowLeft'] },\n vertical: { first: ['Home'], last: ['End'], next: ['ArrowDown'], prev: ['ArrowUp'] },\n};\n\n/**\n * RTL mirror of `DEFAULT_KEYS`'s horizontal component (per WAI-ARIA APG — tabs/radiogroup\n * flip Left/Right in `dir=\"rtl\"` so \"next\" always advances in reading order, not screen-space\n * direction). Only the Left/Right bindings differ; Home/End and the vertical arrows are\n * direction-independent and stay identical to `DEFAULT_KEYS`.\n */\nconst DEFAULT_KEYS_RTL: Record<'both' | 'horizontal' | 'vertical', Record<ListNavigationAction, string[]>> = {\n both: { first: ['Home'], last: ['End'], next: ['ArrowDown', 'ArrowLeft'], prev: ['ArrowUp', 'ArrowRight'] },\n horizontal: { first: ['Home'], last: ['End'], next: ['ArrowLeft'], prev: ['ArrowRight'] },\n vertical: DEFAULT_KEYS.vertical,\n};\n\nexport type ListNavigationOptions<T> = {\n /**\n * Text direction, used to mirror the default Left/Right arrow-key bindings for\n * `'horizontal'`/`'both'` orientation (WAI-ARIA APG: `dir=\"rtl\"` flips which arrow key\n * means \"next\" vs \"prev\"). Pass a getter for dynamic/reactive direction (e.g. derived from\n * `elementDirection(getHost())`, since a `dir` ancestor attribute can change at runtime).\n * Has no effect when an explicit `keys` override is provided. Defaults to `'ltr'`.\n */\n direction?: 'ltr' | 'rtl' | (() => 'ltr' | 'rtl');\n disabled?: Readable<boolean | undefined>;\n /**\n * Returns a plain-text label for an item used by typeahead search.\n * When provided, pressing a printable character key jumps to the first enabled\n * item whose label starts with the accumulated type buffer (500 ms reset window).\n * Omit for contexts where the host element is a text input (e.g. combobox).\n */\n getItemLabel?: (item: T, index: number) => string;\n getItems: () => T[];\n isItemDisabled?: (item: T, index: number) => boolean;\n /** Override default key bindings for navigation actions. */\n keys?: Partial<Record<ListNavigationAction, string[]>>;\n loop?: boolean;\n /**\n * Called when navigation lands on a new index.\n * `event` is the originating `KeyboardEvent`, or `undefined` for programmatic navigation.\n * Use to sync side-effects such as focusing a DOM element.\n */\n onNavigate?: (action: ListKeyAction, index: number, event?: KeyboardEvent) => void;\n /**\n * Axis the list navigates along. Controls which arrow keys are treated as\n * `next`/`prev` when no explicit `keys` override is provided.\n * Pass a getter function for dynamic/reactive orientation (e.g. driven by a prop signal).\n *\n * - `'vertical'` (default): ↑↓ arrows\n * - `'horizontal'`: ←→ arrows\n * - `'both'`: all four arrow keys\n */\n orientation?: 'both' | 'horizontal' | 'vertical' | (() => 'both' | 'horizontal' | 'vertical');\n /** `AbortSignal` from the component lifecycle. Disposes typeahead timer on abort. */\n signal?: AbortSignal;\n};\n\nexport type ListControl<T> = {\n [Symbol.dispose](): void;\n /** Disposes the internal typeahead timer. Alias for `dispose()`. Conforms to the monorepo disposal convention. */\n dispose(): void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Current focused index. `-1` when nothing is focused. */\n readonly focusedIndex: Readable<number>;\n getActiveItem(): T | undefined;\n handleKeydown(event: KeyboardEvent): boolean;\n /**\n * Programmatically navigate to a named position.\n * Always fires `onNavigate` — consistent with keyboard navigation.\n * Returns the resolved index, or `-1` if no enabled item was found.\n */\n navigate(action: ListNavigationAction): number;\n /** Reset focused index to `-1`. */\n reset(): void;\n /**\n * Set focus to the item at `index`. Returns the resolved index.\n * Pass a negative index to clear focus (same as `reset()`).\n */\n set(index: number): number;\n};\n\nconst hasDisabledProp = (item: unknown): item is { disabled: boolean } =>\n typeof item === 'object' && item !== null && 'disabled' in item;\n\nexport const createListControl = <T>(options: ListNavigationOptions<T>): ListControl<T> => {\n const _index = signal(-1);\n\n const isItemDisabled = (item: T, index: number): boolean =>\n options.isItemDisabled?.(item, index) ?? (hasDisabledProp(item) ? item.disabled : false);\n\n const commitIndex = (idx: number, action: ListKeyAction, event?: KeyboardEvent): number => {\n if (idx >= 0) {\n _index.value = idx;\n options.onNavigate?.(action, idx, event);\n }\n\n return idx;\n };\n\n const findEnabledIndex = (items: T[], start: number, direction: 'forward' | 'backward'): number => {\n if (direction === 'forward') return findForward(items, start, (item, i) => !isItemDisabled(item, i));\n\n return findBackward(items, start, (item, i) => !isItemDisabled(item, i));\n };\n\n const set = (index: number): number => {\n if (index < 0) {\n reset();\n\n return -1;\n }\n\n const items = options.getItems();\n\n if (!items.length) return -1;\n\n const clamped = Math.min(index, items.length - 1);\n\n if (isItemDisabled(items[clamped], clamped)) return -1;\n\n _index.value = clamped;\n\n return clamped;\n };\n\n const move = (direction: 'forward' | 'backward', event?: KeyboardEvent): number => {\n const items = options.getItems();\n const current = _index.value;\n\n if (!items.length) return -1;\n\n const start: number =\n current < 0\n ? direction === 'forward'\n ? 0\n : items.length - 1\n : direction === 'forward'\n ? current + 1\n : current - 1;\n const idx = findEnabledIndex(items, start, direction);\n const action: ListNavigationAction = direction === 'forward' ? 'next' : 'prev';\n\n if (idx >= 0) return commitIndex(idx, action, event);\n\n if (options.loop) {\n const wrapStart = direction === 'forward' ? 0 : items.length - 1;\n const wrapped = findEnabledIndex(items, wrapStart, direction);\n\n if (wrapped >= 0) return commitIndex(wrapped, action, event);\n }\n\n return current;\n };\n\n const navigate = (action: ListNavigationAction): number => {\n const items = options.getItems();\n\n if (!items.length) return -1;\n\n if (action === 'first') {\n const idx = findEnabledIndex(items, 0, 'forward');\n\n return commitIndex(idx, 'first');\n }\n\n if (action === 'last') {\n const idx = findEnabledIndex(items, items.length - 1, 'backward');\n\n return commitIndex(idx, 'last');\n }\n\n return move(action === 'next' ? 'forward' : 'backward');\n };\n\n const getActiveItem = (): T | undefined => {\n const items = options.getItems();\n const index = _index.value;\n\n return index >= 0 && index < items.length ? items[index] : undefined;\n };\n\n const reset = (): void => {\n _index.value = -1;\n };\n\n // ── Keyboard handling ──────────────────────────────────────────────────────\n\n const isKeyDisabled = (): boolean => Boolean(options.disabled?.value);\n\n const resolveOrientation = (): 'both' | 'horizontal' | 'vertical' =>\n typeof options.orientation === 'function' ? options.orientation() : (options.orientation ?? 'vertical');\n\n const resolveDirection = (): 'ltr' | 'rtl' =>\n typeof options.direction === 'function' ? options.direction() : (options.direction ?? 'ltr');\n\n const buildKeymap = (): Record<string, (keyboardEvent: KeyboardEvent) => void> => {\n const keys = options.keys;\n const keyTable = resolveDirection() === 'rtl' ? DEFAULT_KEYS_RTL : DEFAULT_KEYS;\n const orientationDefaults = keyTable[resolveOrientation()];\n const resolved = {\n first: keys?.first ?? orientationDefaults.first,\n last: keys?.last ?? orientationDefaults.last,\n next: keys?.next ?? orientationDefaults.next,\n prev: keys?.prev ?? orientationDefaults.prev,\n };\n const km: Record<string, (keyboardEvent: KeyboardEvent) => void> = {};\n\n for (const action of ['next', 'prev', 'first', 'last'] as const) {\n for (const key of resolved[action]) {\n km[key] = (keyboardEvent: KeyboardEvent) => {\n if (action === 'first' || action === 'last') {\n const items = options.getItems();\n\n if (!items.length) return;\n\n const idx =\n action === 'first'\n ? findEnabledIndex(items, 0, 'forward')\n : findEnabledIndex(items, items.length - 1, 'backward');\n\n commitIndex(idx, action, keyboardEvent);\n } else {\n move(action === 'next' ? 'forward' : 'backward', keyboardEvent);\n }\n };\n }\n }\n\n return km;\n };\n\n // ── Typeahead ──────────────────────────────────────────────────────────────\n\n const typeahead = options.getItemLabel\n ? createTypeahead({\n getIndex: () => _index.value,\n getItemLabel: options.getItemLabel,\n getItems: options.getItems,\n isItemDisabled: (item, index) => isItemDisabled(item, index),\n onNavigate: (index, event) => {\n if (!isKeyDisabled()) {\n _index.value = index;\n options.onNavigate?.('typeahead', index, event);\n }\n },\n })\n : null;\n\n // Keymap depends on both orientation and direction — if either is dynamic, rebuild on every\n // keydown instead of caching once.\n const isDynamicKeymap = typeof options.orientation === 'function' || typeof options.direction === 'function';\n const _staticKeymap: Record<string, (e: KeyboardEvent) => void> | null = isDynamicKeymap ? null : buildKeymap();\n\n const handleKeydown = (event: KeyboardEvent): boolean => {\n const km = _staticKeymap ?? buildKeymap();\n\n if (dispatchKeyboardAction(event, { disabled: options.disabled, keymap: km })) return true;\n\n return typeahead?.handleKeydown(event) ?? false;\n };\n\n let disposed = false;\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n typeahead?.reset();\n };\n\n if (options.signal) {\n options.signal.addEventListener('abort', dispose, { once: true });\n }\n\n return {\n dispose,\n get disposed() {\n return disposed;\n },\n focusedIndex: _index,\n getActiveItem,\n handleKeydown,\n navigate,\n reset,\n set,\n [Symbol.dispose]: dispose,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nav.d.ts","sourceRoot":"","sources":["../../src/headless/nav.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAU,MAAM,kBAAkB,CAAC;AAwBzD;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEtE;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,WAAW,CAAC;AA0B/D,MAAM,MAAM,qBAAqB,CAAC,CAAC,IAAI;IACrC;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,CAAC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC;IAClD,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IACzC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACrD,4DAA4D;IAC5D,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,aAAa,KAAK,IAAI,CAAC;IACnF;;;;;;;;OAQG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,CAAC,MAAM,MAAM,GAAG,YAAY,GAAG,UAAU,CAAC,CAAC;IAC9F,qFAAqF;IACrF,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC;IACzB,kHAAkH;IAClH,OAAO,IAAI,IAAI,CAAC;IAChB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACxC,aAAa,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/B,aAAa,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAAC;IAC/C,mCAAmC;IACnC,KAAK,IAAI,IAAI,CAAC;IACd;;;OAGG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B,CAAC;AAKF,eAAO,MAAM,iBAAiB,GAAI,CAAC,EAAE,SAAS,qBAAqB,CAAC,CAAC,CAAC,KAAG,WAAW,CAAC,CAAC,CA2MrF,CAAC"}
|
package/dist/headless/nav.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"nav.js","names":[],"sources":["../../src/headless/nav.ts"],"sourcesContent":["import { type Readable, signal } from '@vielzeug/ripple';\n\nimport { dispatchKeyboardAction } from './keyboard';\nimport { createTypeahead } from './typeahead';\n\n// ── Private array search helpers ────────────────────────────────────────────\nconst findForward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx < items.length; idx++) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\nconst findBackward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx >= 0; idx--) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\n/**\n * Arrow-key and Home/End navigation actions. Separate from `ListKeyAction` so\n * keymap declarations never need `Exclude<ListKeyAction, 'typeahead'>`.\n */\nexport type ListNavigationAction = 'first' | 'last' | 'next' | 'prev';\n\n/**\n * All possible navigation action names, including `'typeahead'` (character-key\n * search). Used in `onNavigate` callbacks where both nav and typeahead are valid.\n */\nexport type ListKeyAction = ListNavigationAction | 'typeahead';\n\n/**\n * Orientation-aware default key bindings for list navigation.\n * - `'vertical'` (default): Up/Down arrows, Home/End\n * - `'horizontal'`: Left/Right arrows, Home/End\n * - `'both'`: all four arrow keys + Home/End\n */\nconst DEFAULT_KEYS: Record<'both' | 'horizontal' | 'vertical', Record<ListNavigationAction, string[]>> = {\n both: { first: ['Home'], last: ['End'], next: ['ArrowDown', 'ArrowRight'], prev: ['ArrowUp', 'ArrowLeft'] },\n horizontal: { first: ['Home'], last: ['End'], next: ['ArrowRight'], prev: ['ArrowLeft'] },\n vertical: { first: ['Home'], last: ['End'], next: ['ArrowDown'], prev: ['ArrowUp'] },\n};\n\n/**\n * RTL mirror of `DEFAULT_KEYS`'s horizontal component (per WAI-ARIA APG — tabs/radiogroup\n * flip Left/Right in `dir=\"rtl\"` so \"next\" always advances in reading order, not screen-space\n * direction). Only the Left/Right bindings differ; Home/End and the vertical arrows are\n * direction-independent and stay identical to `DEFAULT_KEYS`.\n */\nconst DEFAULT_KEYS_RTL: Record<'both' | 'horizontal' | 'vertical', Record<ListNavigationAction, string[]>> = {\n both: { first: ['Home'], last: ['End'], next: ['ArrowDown', 'ArrowLeft'], prev: ['ArrowUp', 'ArrowRight'] },\n horizontal: { first: ['Home'], last: ['End'], next: ['ArrowLeft'], prev: ['ArrowRight'] },\n vertical: DEFAULT_KEYS.vertical,\n};\n\nexport type ListNavigationOptions<T> = {\n /**\n * Text direction, used to mirror the default Left/Right arrow-key bindings for\n * `'horizontal'`/`'both'` orientation (WAI-ARIA APG: `dir=\"rtl\"` flips which arrow key\n * means \"next\" vs \"prev\"). Pass a getter for dynamic/reactive direction (e.g. derived from\n * `elementDirection(getHost())`, since a `dir` ancestor attribute can change at runtime).\n * Has no effect when an explicit `keys` override is provided. Defaults to `'ltr'`.\n */\n direction?: 'ltr' | 'rtl' | (() => 'ltr' | 'rtl');\n disabled?: Readable<boolean | undefined>;\n /**\n * Returns a plain-text label for an item used by typeahead search.\n * When provided, pressing a printable character key jumps to the first enabled\n * item whose label starts with the accumulated type buffer (500 ms reset window).\n * Omit for contexts where the host element is a text input (e.g. combobox).\n */\n getItemLabel?: (item: T, index: number) => string;\n getItems: () => T[];\n isItemDisabled?: (item: T, index: number) => boolean;\n /** Override default key bindings for navigation actions. */\n keys?: Partial<Record<ListNavigationAction, string[]>>;\n loop?: boolean;\n /**\n * Called when navigation lands on a new index.\n * `event` is the originating `KeyboardEvent`, or `undefined` for programmatic navigation.\n * Use to sync side-effects such as focusing a DOM element.\n */\n onNavigate?: (action: ListKeyAction, index: number, event?: KeyboardEvent) => void;\n /**\n * Axis the list navigates along. Controls which arrow keys are treated as\n * `next`/`prev` when no explicit `keys` override is provided.\n * Pass a getter function for dynamic/reactive orientation (e.g. driven by a prop signal).\n *\n * - `'vertical'` (default): ↑↓ arrows\n * - `'horizontal'`: ←→ arrows\n * - `'both'`: all four arrow keys\n */\n orientation?: 'both' | 'horizontal' | 'vertical' | (() => 'both' | 'horizontal' | 'vertical');\n /** `AbortSignal` from the component lifecycle. Disposes typeahead timer on abort. */\n signal?: AbortSignal;\n};\n\nexport type ListControl<T> = {\n [Symbol.dispose](): void;\n /** Disposes the internal typeahead timer. Alias for `dispose()`. Conforms to the monorepo disposal convention. */\n dispose(): void;\n /** `true` after `dispose()` has been called. */\n readonly disposed: boolean;\n /** Current focused index. `-1` when nothing is focused. */\n readonly focusedIndex: Readable<number>;\n getActiveItem(): T | undefined;\n handleKeydown(event: KeyboardEvent): boolean;\n /**\n * Programmatically navigate to a named position.\n * Always fires `onNavigate` — consistent with keyboard navigation.\n * Returns the resolved index, or `-1` if no enabled item was found.\n */\n navigate(action: ListNavigationAction): number;\n /** Reset focused index to `-1`. */\n reset(): void;\n /**\n * Set focus to the item at `index`. Returns the resolved index.\n * Pass a negative index to clear focus (same as `reset()`).\n */\n set(index: number): number;\n};\n\nconst hasDisabledProp = (item: unknown): item is { disabled: boolean } =>\n typeof item === 'object' && item !== null && 'disabled' in item;\n\nexport const createListControl = <T>(options: ListNavigationOptions<T>): ListControl<T> => {\n const _index = signal(-1);\n\n const isItemDisabled = (item: T, index: number): boolean =>\n options.isItemDisabled?.(item, index) ?? (hasDisabledProp(item) ? item.disabled : false);\n\n const commitIndex = (idx: number, action: ListKeyAction, event?: KeyboardEvent): number => {\n if (idx >= 0) {\n _index.value = idx;\n options.onNavigate?.(action, idx, event);\n }\n\n return idx;\n };\n\n const findEnabledIndex = (items: T[], start: number, direction: 'forward' | 'backward'): number => {\n if (direction === 'forward') return findForward(items, start, (item, i) => !isItemDisabled(item, i));\n\n return findBackward(items, start, (item, i) => !isItemDisabled(item, i));\n };\n\n const set = (index: number): number => {\n if (index < 0) {\n reset();\n\n return -1;\n }\n\n const items = options.getItems();\n\n if (!items.length) return -1;\n\n const clamped = Math.min(index, items.length - 1);\n\n if (isItemDisabled(items[clamped], clamped)) return -1;\n\n _index.value = clamped;\n\n return clamped;\n };\n\n const move = (direction: 'forward' | 'backward', event?: KeyboardEvent): number => {\n const items = options.getItems();\n const current = _index.value;\n\n if (!items.length) return -1;\n\n const start: number =\n current < 0\n ? direction === 'forward'\n ? 0\n : items.length - 1\n : direction === 'forward'\n ? current + 1\n : current - 1;\n const idx = findEnabledIndex(items, start, direction);\n const action: ListNavigationAction = direction === 'forward' ? 'next' : 'prev';\n\n if (idx >= 0) return commitIndex(idx, action, event);\n\n if (options.loop) {\n const wrapStart = direction === 'forward' ? 0 : items.length - 1;\n const wrapped = findEnabledIndex(items, wrapStart, direction);\n\n if (wrapped >= 0) return commitIndex(wrapped, action, event);\n }\n\n return current;\n };\n\n const navigate = (action: ListNavigationAction): number => {\n const items = options.getItems();\n\n if (!items.length) return -1;\n\n if (action === 'first') {\n const idx = findEnabledIndex(items, 0, 'forward');\n\n return commitIndex(idx, 'first');\n }\n\n if (action === 'last') {\n const idx = findEnabledIndex(items, items.length - 1, 'backward');\n\n return commitIndex(idx, 'last');\n }\n\n return move(action === 'next' ? 'forward' : 'backward');\n };\n\n const getActiveItem = (): T | undefined => {\n const items = options.getItems();\n const index = _index.value;\n\n return index >= 0 && index < items.length ? items[index] : undefined;\n };\n\n const reset = (): void => {\n _index.value = -1;\n };\n\n // ── Keyboard handling ──────────────────────────────────────────────────────\n\n const isKeyDisabled = (): boolean => Boolean(options.disabled?.value);\n\n const resolveOrientation = (): 'both' | 'horizontal' | 'vertical' =>\n typeof options.orientation === 'function' ? options.orientation() : (options.orientation ?? 'vertical');\n\n const resolveDirection = (): 'ltr' | 'rtl' =>\n typeof options.direction === 'function' ? options.direction() : (options.direction ?? 'ltr');\n\n const buildKeymap = (): Record<string, (keyboardEvent: KeyboardEvent) => void> => {\n const keys = options.keys;\n const keyTable = resolveDirection() === 'rtl' ? DEFAULT_KEYS_RTL : DEFAULT_KEYS;\n const orientationDefaults = keyTable[resolveOrientation()];\n const resolved = {\n first: keys?.first ?? orientationDefaults.first,\n last: keys?.last ?? orientationDefaults.last,\n next: keys?.next ?? orientationDefaults.next,\n prev: keys?.prev ?? orientationDefaults.prev,\n };\n const km: Record<string, (keyboardEvent: KeyboardEvent) => void> = {};\n\n for (const action of ['next', 'prev', 'first', 'last'] as const) {\n for (const key of resolved[action]) {\n km[key] = (keyboardEvent: KeyboardEvent) => {\n if (action === 'first' || action === 'last') {\n const items = options.getItems();\n\n if (!items.length) return;\n\n const idx =\n action === 'first'\n ? findEnabledIndex(items, 0, 'forward')\n : findEnabledIndex(items, items.length - 1, 'backward');\n\n commitIndex(idx, action, keyboardEvent);\n } else {\n move(action === 'next' ? 'forward' : 'backward', keyboardEvent);\n }\n };\n }\n }\n\n return km;\n };\n\n // ── Typeahead ──────────────────────────────────────────────────────────────\n\n const typeahead = options.getItemLabel\n ? createTypeahead({\n getIndex: () => _index.value,\n getItemLabel: options.getItemLabel,\n getItems: options.getItems,\n isItemDisabled: (item, index) => isItemDisabled(item, index),\n onNavigate: (index, event) => {\n if (!isKeyDisabled()) {\n _index.value = index;\n options.onNavigate?.('typeahead', index, event);\n }\n },\n })\n : null;\n\n // Keymap depends on both orientation and direction — if either is dynamic, rebuild on every\n // keydown instead of caching once.\n const isDynamicKeymap = typeof options.orientation === 'function' || typeof options.direction === 'function';\n const _staticKeymap: Record<string, (e: KeyboardEvent) => void> | null = isDynamicKeymap ? null : buildKeymap();\n\n const handleKeydown = (event: KeyboardEvent): boolean => {\n const km = _staticKeymap ?? buildKeymap();\n\n if (dispatchKeyboardAction(event, { disabled: options.disabled, keymap: km })) return true;\n\n return typeahead?.handleKeydown(event) ?? false;\n };\n\n let disposed = false;\n\n const dispose = (): void => {\n if (disposed) return;\n\n disposed = true;\n typeahead?.reset();\n };\n\n if (options.signal) {\n options.signal.addEventListener('abort', dispose, { once: true });\n }\n\n return {\n dispose,\n get disposed() {\n return disposed;\n },\n focusedIndex: _index,\n getActiveItem,\n handleKeydown,\n navigate,\n reset,\n set,\n [Symbol.dispose]: dispose,\n };\n};\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"numbers.cjs","names":[],"sources":["../../src/headless/numbers.ts"],"sourcesContent":["// ── Number helpers ────────────────────────────────────────────────────────────\n\n/**\n * Coerces `value` via `Number()` and returns it when finite, `undefined` otherwise.\n *\n * Caveat: `null` and `''` both coerce to `0` in JavaScript (`Number(null) === 0`,\n * `Number('') === 0`) and are therefore returned as the finite number `0`, not\n * `undefined` — this function does not treat \"absent\" values specially. Only\n * genuinely non-numeric input (`undefined`, `NaN`, non-numeric strings) yields\n * `undefined`. Callers that mean \"no bound set\" should pass `undefined`\n * explicitly rather than `null` or `''`.\n */\nexport const toFiniteNumber = (value: unknown): number | undefined => {\n const parsed = Number(value);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nexport const toFiniteNumberOr = (value: unknown, fallback: number): number => {\n return toFiniteNumber(value) ?? fallback;\n};\n\nexport const toPositiveStep = (value: unknown, fallback: number): number => {\n return Math.abs(toFiniteNumberOr(value, fallback)) || fallback;\n};\n"],"mappings":"AAYA,IAAa,EAAkB,GAAuC,CACpE,IAAM,EAAS,OAAO,CAAK,EAE3B,OAAO,OAAO,SAAS,CAAM,EAAI,EAAS,IAAA,EAC5C,EAEa,GAAoB,EAAgB,IACxC,EAAe,CAAK,GAAK,EAGrB,GAAkB,EAAgB,IACtC,KAAK,IAAI,EAAiB,EAAO,CAAQ,CAAC,GAAK"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"numbers.d.ts","sourceRoot":"","sources":["../../src/headless/numbers.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAIxD,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,EAAE,UAAU,MAAM,KAAG,MAEnE,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,EAAE,UAAU,MAAM,KAAG,MAEjE,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"numbers.js","names":[],"sources":["../../src/headless/numbers.ts"],"sourcesContent":["// ── Number helpers ────────────────────────────────────────────────────────────\n\n/**\n * Coerces `value` via `Number()` and returns it when finite, `undefined` otherwise.\n *\n * Caveat: `null` and `''` both coerce to `0` in JavaScript (`Number(null) === 0`,\n * `Number('') === 0`) and are therefore returned as the finite number `0`, not\n * `undefined` — this function does not treat \"absent\" values specially. Only\n * genuinely non-numeric input (`undefined`, `NaN`, non-numeric strings) yields\n * `undefined`. Callers that mean \"no bound set\" should pass `undefined`\n * explicitly rather than `null` or `''`.\n */\nexport const toFiniteNumber = (value: unknown): number | undefined => {\n const parsed = Number(value);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nexport const toFiniteNumberOr = (value: unknown, fallback: number): number => {\n return toFiniteNumber(value) ?? fallback;\n};\n\nexport const toPositiveStep = (value: unknown, fallback: number): number => {\n return Math.abs(toFiniteNumberOr(value, fallback)) || fallback;\n};\n"],"mappings":";AAYA,IAAa,KAAkB,MAAuC;CACpE,IAAM,IAAS,OAAO,CAAK;CAE3B,OAAO,OAAO,SAAS,CAAM,IAAI,IAAS,KAAA;AAC5C,GAEa,KAAoB,GAAgB,MACxC,EAAe,CAAK,KAAK,GAGrB,KAAkB,GAAgB,MACtC,KAAK,IAAI,EAAiB,GAAO,CAAQ,CAAC,KAAK"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("../errors.cjs"),t=require("./nav.cjs"),n=require("./overlay.cjs"),r=require("./positioner.cjs");let i=require("@vielzeug/ripple");var a=a=>{if(typeof a.getBoundary!=`function`)throw new e.RefineConfigError(`createOptionList: getBoundary is required`);if(typeof a.getPanel!=`function`)throw new e.RefineConfigError(`createOptionList: getPanel is required`);if(typeof a.getReference!=`function`)throw new e.RefineConfigError(`createOptionList: getReference is required`);let o=(0,i.signal)(!1),s=(0,i.computed)(()=>String(o.value)),c=r.createDropdownPositioner({...a.positioning,getFloating:a.getPanel,getReference:a.getReference}),l=()=>{a.getFocusedOptionElement?.()?.scrollIntoView({block:`nearest`})},u=t.createListControl({disabled:(0,i.computed)(()=>!o.value),getItemLabel:a.getItemLabel,getItems:a.getItems,isItemDisabled:a.isItemDisabled,keys:a.keys,loop:a.loop??!0,onNavigate:(e,t,n)=>{l(),t>=0&&a.onNavigate?.(e,t,n)},orientation:a.orientation,signal:a.signal}),d=(0,i.computed)(()=>{let e=u.focusedIndex.value;return a.getOptionId&&o.value&&e>=0?a.getOptionId(e):null}),f=n.createOverlayControl({getBoundary:a.getBoundary,getPanel:a.getPanel,getTrigger:a.getTrigger,isDisabled:a.isDisabled,isOpen:()=>o.value,onClose:a.onClose,onOpen:a.onOpen,positioner:c,restoreFocus:a.restoreFocus,setOpen:e=>{o.value=e,e||u.reset()},signal:a.signal});return{ariaActiveDescendant:d,ariaExpanded:s,close:e=>f.close(e),focusedIndex:u.focusedIndex,getActiveItem:u.getActiveItem,handleKeydown:e=>o.value?e.key===`Escape`?(e.preventDefault(),f.close(`escape`),!0):u.handleKeydown(e):!1,isOpen:o,navigate:u.navigate,open:e=>f.open(e),scrollFocusedIntoView:l,set:u.set,toggle:(e,t)=>f.toggle(e,t),updatePosition:c.update}};exports.createOptionList=a;
|
|
2
|
-
//# sourceMappingURL=option-list.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"option-list.cjs","names":[],"sources":["../../src/headless/option-list.ts"],"sourcesContent":["import { computed, type Readable, signal } from '@vielzeug/ripple';\n\nimport { RefineConfigError } from '../errors';\nimport { createListControl, type ListKeyAction, type ListNavigationAction } from './nav';\nimport { createOverlayControl, type DialogCloseReason, type OverlayOpenReason } from './overlay';\nimport { createDropdownPositioner, type DropdownPositionerOptions } from './positioner';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type BaseOptionItem = object;\n\n/** Placement-only options for the dropdown positioner (getFloating/getReference are injected from the option-list). */\nexport type PlacementOptions = Omit<DropdownPositionerOptions, 'getFloating' | 'getReference'>;\n\nexport type OptionListOptions<T extends BaseOptionItem> = {\n /** Returns the element used as the outside-click boundary. */\n getBoundary: () => HTMLElement | null;\n /**\n * Returns the currently focused option element for scroll-into-view.\n * When omitted, `scrollFocusedIntoView()` is a no-op.\n */\n getFocusedOptionElement?: () => HTMLElement | null;\n /**\n * Returns a plain-text label for the item at `index`.\n * When provided, the list control supports typeahead.\n */\n getItemLabel?: (item: T, index: number) => string;\n /** Returns the current list items. */\n getItems: () => T[];\n /**\n * Derives a stable `id` for the option at `index`.\n * When provided, `aria-activedescendant` is reactively set on the trigger element\n * to reflect the currently focused option (WAI-ARIA listbox / combobox pattern).\n */\n getOptionId?: (index: number) => string;\n /** Returns the floating panel element. */\n getPanel: () => HTMLElement | null;\n /** Returns the reference (trigger anchor) element for positioning. */\n getReference: () => HTMLElement | null;\n /** Returns the trigger element. Focus is restored here on close. */\n getTrigger?: () => HTMLElement | null;\n /** Returns `true` when all interactions should be suppressed (e.g. the host is disabled). */\n isDisabled?: () => boolean;\n isItemDisabled?: (item: T, index: number) => boolean;\n /** Override default keyboard bindings for navigation actions. */\n keys?: Partial<Record<ListNavigationAction, string[]>>;\n /** Whether list navigation wraps around at the first/last item. Default: `true`. */\n loop?: boolean;\n /** Called when the list closes. */\n onClose?: (reason: DialogCloseReason) => void;\n /**\n * Called when keyboard navigation lands on an item.\n * `event` is the originating `KeyboardEvent`, or `undefined` for programmatic navigation.\n */\n onNavigate?: (action: ListKeyAction, index: number, event?: KeyboardEvent) => void;\n /** Called when the list opens. */\n onOpen?: (reason: OverlayOpenReason) => void;\n /**\n * Restricts keyboard navigation direction for the option list.\n * Defaults to `'vertical'` when omitted (up/down arrow keys).\n */\n orientation?: 'both' | 'horizontal' | 'vertical';\n /** Placement and sizing options for the floating dropdown. */\n positioning?: PlacementOptions;\n /** Whether focus is restored to the trigger on close. Default: inferred from `restoreFocus`. */\n restoreFocus?: boolean | (() => boolean);\n /** `AbortSignal` from the component lifecycle. Disposes subscriptions and removes event listeners on abort. */\n signal: AbortSignal;\n};\n\nexport type OptionListHandle<T extends BaseOptionItem> = {\n /** Reactive `aria-activedescendant` value. `null` when no option is focused or the list is closed. */\n readonly ariaActiveDescendant: Readable<string | null>;\n /** Reactive `aria-expanded` value as string (`'true'` / `'false'`). */\n readonly ariaExpanded: Readable<string>;\n close(reason?: DialogCloseReason): void;\n /**\n * Focused item index (read-only). Write via `set(index)` to update through\n * the list control — this ensures scroll-into-view and disabled-item checks.\n */\n readonly focusedIndex: Readable<number>;\n getActiveItem(): T | undefined;\n handleKeydown(event: KeyboardEvent): boolean;\n /** Open state (read-only). Mutate via `open()`, `close()`, or `toggle()`. */\n readonly isOpen: Readable<boolean>;\n /**\n * Programmatically navigate to a named position. Always fires `onNavigate`\n * (scroll-into-view, aria-activedescendant update).\n * Returns the resolved index, or `-1` if no enabled item was found.\n */\n navigate(action: ListNavigationAction): number;\n open(reason?: OverlayOpenReason): void;\n scrollFocusedIntoView(): void;\n /**\n * Set focus to the item at `index`. Returns the resolved index.\n * Pass a negative index to clear focus (same as `reset()`).\n */\n set(index: number): number;\n /**\n * Toggles open state.\n * - Opens with `openReason` (default `'click'`).\n * - Closes with `closeReason` (default `'trigger'`).\n */\n toggle(openReason?: OverlayOpenReason, closeReason?: DialogCloseReason): void;\n /** Imperatively re-run dropdown positioning (e.g. after filter changes list height). */\n updatePosition(): void;\n};\n\n// ── Factory ───────────────────────────────────────────────────────────────────\n\n/**\n * Shared headless primitive for dropdown option lists (select, combobox, menu).\n *\n * Owns `isOpen`, `focusedIndex`, the dropdown positioner, list navigation, and\n * overlay wiring. Composes overlay.ts + nav.ts into a single complete API.\n */\nexport const createOptionList = <T extends BaseOptionItem>(options: OptionListOptions<T>): OptionListHandle<T> => {\n if (typeof options.getBoundary !== 'function') {\n throw new RefineConfigError('createOptionList: getBoundary is required');\n }\n\n if (typeof options.getPanel !== 'function') {\n throw new RefineConfigError('createOptionList: getPanel is required');\n }\n\n if (typeof options.getReference !== 'function') {\n throw new RefineConfigError('createOptionList: getReference is required');\n }\n\n const isOpen = signal(false);\n\n const ariaExpanded = computed(() => String(isOpen.value));\n\n const positioner = createDropdownPositioner({\n ...options.positioning,\n getFloating: options.getPanel,\n getReference: options.getReference,\n });\n\n const scrollFocusedIntoView = (): void => {\n options.getFocusedOptionElement?.()?.scrollIntoView({ block: 'nearest' });\n };\n\n const list = createListControl<T>({\n disabled: computed(() => !isOpen.value),\n getItemLabel: options.getItemLabel,\n getItems: options.getItems,\n isItemDisabled: options.isItemDisabled,\n keys: options.keys,\n loop: options.loop ?? true,\n onNavigate: (action, index, event) => {\n scrollFocusedIntoView();\n\n if (index >= 0) options.onNavigate?.(action, index, event);\n },\n orientation: options.orientation,\n signal: options.signal,\n });\n\n const ariaActiveDescendant = computed<string | null>(() => {\n const idx = list.focusedIndex.value;\n\n return options.getOptionId && isOpen.value && idx >= 0 ? options.getOptionId(idx) : null;\n });\n\n const overlay = createOverlayControl({\n getBoundary: options.getBoundary,\n getPanel: options.getPanel,\n getTrigger: options.getTrigger,\n isDisabled: options.isDisabled,\n isOpen: () => isOpen.value,\n onClose: options.onClose,\n onOpen: options.onOpen,\n positioner,\n restoreFocus: options.restoreFocus,\n setOpen: (next) => {\n isOpen.value = next;\n\n if (!next) list.reset();\n },\n signal: options.signal,\n });\n\n // Built-in Escape key handling: prevents each consumer from duplicating the\n // close-on-escape pattern. Fires only when the list is open; returns `true`\n // so callers know the event was handled and can stop further processing.\n const handleKeydown = (event: KeyboardEvent): boolean => {\n if (!isOpen.value) return false;\n\n if (event.key === 'Escape') {\n event.preventDefault();\n overlay.close('escape');\n\n return true;\n }\n\n return list.handleKeydown(event);\n };\n\n return {\n ariaActiveDescendant,\n ariaExpanded,\n close: (reason) => overlay.close(reason),\n focusedIndex: list.focusedIndex,\n getActiveItem: list.getActiveItem,\n handleKeydown,\n isOpen,\n navigate: list.navigate,\n open: (reason) => overlay.open(reason),\n scrollFocusedIntoView,\n set: list.set,\n toggle: (openReason, closeReason) => overlay.toggle(openReason, closeReason),\n updatePosition: positioner.update,\n };\n};\n"],"mappings":"mJAoHA,IAAa,EAA8C,GAAuD,CAChH,GAAI,OAAO,EAAQ,aAAgB,WACjC,MAAM,IAAI,EAAA,kBAAkB,2CAA2C,EAGzE,GAAI,OAAO,EAAQ,UAAa,WAC9B,MAAM,IAAI,EAAA,kBAAkB,wCAAwC,EAGtE,GAAI,OAAO,EAAQ,cAAiB,WAClC,MAAM,IAAI,EAAA,kBAAkB,4CAA4C,EAG1E,IAAM,GAAA,EAAA,EAAA,OAAA,CAAgB,EAAK,EAErB,GAAA,EAAA,EAAA,SAAA,KAA8B,OAAO,EAAO,KAAK,CAAC,EAElD,EAAa,EAAA,yBAAyB,CAC1C,GAAG,EAAQ,YACX,YAAa,EAAQ,SACrB,aAAc,EAAQ,YACxB,CAAC,EAEK,MAAoC,CACxC,EAAQ,0BAA0B,CAAC,EAAE,eAAe,CAAE,MAAO,SAAU,CAAC,CAC1E,EAEM,EAAO,EAAA,kBAAqB,CAChC,UAAA,EAAA,EAAA,SAAA,KAAyB,CAAC,EAAO,KAAK,EACtC,aAAc,EAAQ,aACtB,SAAU,EAAQ,SAClB,eAAgB,EAAQ,eACxB,KAAM,EAAQ,KACd,KAAM,EAAQ,MAAQ,GACtB,YAAa,EAAQ,EAAO,IAAU,CACpC,EAAsB,EAElB,GAAS,GAAG,EAAQ,aAAa,EAAQ,EAAO,CAAK,CAC3D,EACA,YAAa,EAAQ,YACrB,OAAQ,EAAQ,MAClB,CAAC,EAEK,GAAA,EAAA,EAAA,SAAA,KAAqD,CACzD,IAAM,EAAM,EAAK,aAAa,MAE9B,OAAO,EAAQ,aAAe,EAAO,OAAS,GAAO,EAAI,EAAQ,YAAY,CAAG,EAAI,IACtF,CAAC,EAEK,EAAU,EAAA,qBAAqB,CACnC,YAAa,EAAQ,YACrB,SAAU,EAAQ,SAClB,WAAY,EAAQ,WACpB,WAAY,EAAQ,WACpB,WAAc,EAAO,MACrB,QAAS,EAAQ,QACjB,OAAQ,EAAQ,OAChB,aACA,aAAc,EAAQ,aACtB,QAAU,GAAS,CACjB,EAAO,MAAQ,EAEV,GAAM,EAAK,MAAM,CACxB,EACA,OAAQ,EAAQ,MAClB,CAAC,EAkBD,MAAO,CACL,uBACA,eACA,MAAQ,GAAW,EAAQ,MAAM,CAAM,EACvC,aAAc,EAAK,aACnB,cAAe,EAAK,cACpB,cAnBqB,GAChB,EAAO,MAER,EAAM,MAAQ,UAChB,EAAM,eAAe,EACrB,EAAQ,MAAM,QAAQ,EAEf,IAGF,EAAK,cAAc,CAAK,EATL,GAmB1B,SACA,SAAU,EAAK,SACf,KAAO,GAAW,EAAQ,KAAK,CAAM,EACrC,wBACA,IAAK,EAAK,IACV,QAAS,EAAY,IAAgB,EAAQ,OAAO,EAAY,CAAW,EAC3E,eAAgB,EAAW,MAC7B,CACF"}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { type Readable } from '@vielzeug/ripple';
|
|
2
|
-
import { type ListKeyAction, type ListNavigationAction } from './nav';
|
|
3
|
-
import { type DialogCloseReason, type OverlayOpenReason } from './overlay';
|
|
4
|
-
import { type DropdownPositionerOptions } from './positioner';
|
|
5
|
-
export type BaseOptionItem = object;
|
|
6
|
-
/** Placement-only options for the dropdown positioner (getFloating/getReference are injected from the option-list). */
|
|
7
|
-
export type PlacementOptions = Omit<DropdownPositionerOptions, 'getFloating' | 'getReference'>;
|
|
8
|
-
export type OptionListOptions<T extends BaseOptionItem> = {
|
|
9
|
-
/** Returns the element used as the outside-click boundary. */
|
|
10
|
-
getBoundary: () => HTMLElement | null;
|
|
11
|
-
/**
|
|
12
|
-
* Returns the currently focused option element for scroll-into-view.
|
|
13
|
-
* When omitted, `scrollFocusedIntoView()` is a no-op.
|
|
14
|
-
*/
|
|
15
|
-
getFocusedOptionElement?: () => HTMLElement | null;
|
|
16
|
-
/**
|
|
17
|
-
* Returns a plain-text label for the item at `index`.
|
|
18
|
-
* When provided, the list control supports typeahead.
|
|
19
|
-
*/
|
|
20
|
-
getItemLabel?: (item: T, index: number) => string;
|
|
21
|
-
/** Returns the current list items. */
|
|
22
|
-
getItems: () => T[];
|
|
23
|
-
/**
|
|
24
|
-
* Derives a stable `id` for the option at `index`.
|
|
25
|
-
* When provided, `aria-activedescendant` is reactively set on the trigger element
|
|
26
|
-
* to reflect the currently focused option (WAI-ARIA listbox / combobox pattern).
|
|
27
|
-
*/
|
|
28
|
-
getOptionId?: (index: number) => string;
|
|
29
|
-
/** Returns the floating panel element. */
|
|
30
|
-
getPanel: () => HTMLElement | null;
|
|
31
|
-
/** Returns the reference (trigger anchor) element for positioning. */
|
|
32
|
-
getReference: () => HTMLElement | null;
|
|
33
|
-
/** Returns the trigger element. Focus is restored here on close. */
|
|
34
|
-
getTrigger?: () => HTMLElement | null;
|
|
35
|
-
/** Returns `true` when all interactions should be suppressed (e.g. the host is disabled). */
|
|
36
|
-
isDisabled?: () => boolean;
|
|
37
|
-
isItemDisabled?: (item: T, index: number) => boolean;
|
|
38
|
-
/** Override default keyboard bindings for navigation actions. */
|
|
39
|
-
keys?: Partial<Record<ListNavigationAction, string[]>>;
|
|
40
|
-
/** Whether list navigation wraps around at the first/last item. Default: `true`. */
|
|
41
|
-
loop?: boolean;
|
|
42
|
-
/** Called when the list closes. */
|
|
43
|
-
onClose?: (reason: DialogCloseReason) => void;
|
|
44
|
-
/**
|
|
45
|
-
* Called when keyboard navigation lands on an item.
|
|
46
|
-
* `event` is the originating `KeyboardEvent`, or `undefined` for programmatic navigation.
|
|
47
|
-
*/
|
|
48
|
-
onNavigate?: (action: ListKeyAction, index: number, event?: KeyboardEvent) => void;
|
|
49
|
-
/** Called when the list opens. */
|
|
50
|
-
onOpen?: (reason: OverlayOpenReason) => void;
|
|
51
|
-
/**
|
|
52
|
-
* Restricts keyboard navigation direction for the option list.
|
|
53
|
-
* Defaults to `'vertical'` when omitted (up/down arrow keys).
|
|
54
|
-
*/
|
|
55
|
-
orientation?: 'both' | 'horizontal' | 'vertical';
|
|
56
|
-
/** Placement and sizing options for the floating dropdown. */
|
|
57
|
-
positioning?: PlacementOptions;
|
|
58
|
-
/** Whether focus is restored to the trigger on close. Default: inferred from `restoreFocus`. */
|
|
59
|
-
restoreFocus?: boolean | (() => boolean);
|
|
60
|
-
/** `AbortSignal` from the component lifecycle. Disposes subscriptions and removes event listeners on abort. */
|
|
61
|
-
signal: AbortSignal;
|
|
62
|
-
};
|
|
63
|
-
export type OptionListHandle<T extends BaseOptionItem> = {
|
|
64
|
-
/** Reactive `aria-activedescendant` value. `null` when no option is focused or the list is closed. */
|
|
65
|
-
readonly ariaActiveDescendant: Readable<string | null>;
|
|
66
|
-
/** Reactive `aria-expanded` value as string (`'true'` / `'false'`). */
|
|
67
|
-
readonly ariaExpanded: Readable<string>;
|
|
68
|
-
close(reason?: DialogCloseReason): void;
|
|
69
|
-
/**
|
|
70
|
-
* Focused item index (read-only). Write via `set(index)` to update through
|
|
71
|
-
* the list control — this ensures scroll-into-view and disabled-item checks.
|
|
72
|
-
*/
|
|
73
|
-
readonly focusedIndex: Readable<number>;
|
|
74
|
-
getActiveItem(): T | undefined;
|
|
75
|
-
handleKeydown(event: KeyboardEvent): boolean;
|
|
76
|
-
/** Open state (read-only). Mutate via `open()`, `close()`, or `toggle()`. */
|
|
77
|
-
readonly isOpen: Readable<boolean>;
|
|
78
|
-
/**
|
|
79
|
-
* Programmatically navigate to a named position. Always fires `onNavigate`
|
|
80
|
-
* (scroll-into-view, aria-activedescendant update).
|
|
81
|
-
* Returns the resolved index, or `-1` if no enabled item was found.
|
|
82
|
-
*/
|
|
83
|
-
navigate(action: ListNavigationAction): number;
|
|
84
|
-
open(reason?: OverlayOpenReason): void;
|
|
85
|
-
scrollFocusedIntoView(): void;
|
|
86
|
-
/**
|
|
87
|
-
* Set focus to the item at `index`. Returns the resolved index.
|
|
88
|
-
* Pass a negative index to clear focus (same as `reset()`).
|
|
89
|
-
*/
|
|
90
|
-
set(index: number): number;
|
|
91
|
-
/**
|
|
92
|
-
* Toggles open state.
|
|
93
|
-
* - Opens with `openReason` (default `'click'`).
|
|
94
|
-
* - Closes with `closeReason` (default `'trigger'`).
|
|
95
|
-
*/
|
|
96
|
-
toggle(openReason?: OverlayOpenReason, closeReason?: DialogCloseReason): void;
|
|
97
|
-
/** Imperatively re-run dropdown positioning (e.g. after filter changes list height). */
|
|
98
|
-
updatePosition(): void;
|
|
99
|
-
};
|
|
100
|
-
/**
|
|
101
|
-
* Shared headless primitive for dropdown option lists (select, combobox, menu).
|
|
102
|
-
*
|
|
103
|
-
* Owns `isOpen`, `focusedIndex`, the dropdown positioner, list navigation, and
|
|
104
|
-
* overlay wiring. Composes overlay.ts + nav.ts into a single complete API.
|
|
105
|
-
*/
|
|
106
|
-
export declare const createOptionList: <T extends BaseOptionItem>(options: OptionListOptions<T>) => OptionListHandle<T>;
|
|
107
|
-
//# sourceMappingURL=option-list.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"option-list.d.ts","sourceRoot":"","sources":["../../src/headless/option-list.ts"],"names":[],"mappings":"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"}
|