@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
package/dist/toast.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast.js","names":[],"sources":["../src/feedback/toast/toast.ts"],"sourcesContent":["import '../alert/alert';\nimport { uuid } from '@vielzeug/arsenal';\nimport { define, html, prop, ref, getHost, onCleanup, onMounted, useEmit } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\n\nimport type { SwipeControl } from '../../headless';\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { createSwipeControl } from '../../headless';\nimport { reducedMotionMixin } from '../../styles';\nimport componentStyles from './toast.css?inline';\n\n// ---------------------------------------------------------------------------\n// NOTE: Architecture\n//\n// Each toast has two DOM layers:\n// .toast-wrapper — layout / stacking / grid positioning (no animation)\n// .toast-inner — animation target (opacity fade in/out)\n//\n// This separation means stacking rules (nth-last-child, hover) and animation\n// rules never fight over the same element. No !important needed anywhere.\n//\n// State: a single signal<ToastEntry[]> owns all per-toast state (data, phase,\n// timer). There are no parallel Sets or Maps tracking lifecycle separately.\n//\n// Exit animation: .toast-inner.exiting fades opacity → 0.\n// The wrapper stays in-flow during the fade so the grid doesn't snap shut.\n// After transitionend (or TOAST_EXIT_MS fallback), finalize() removes the\n// toast from the entries array which removes the wrapper from the DOM.\n//\n// Swipe gesture animates .toast-inner (not .toast-wrapper) to avoid\n// polluting the wrapper's transition state used by the exit animation.\n// Swipe commit calls finalizeRemoval() directly — it owns the animation,\n// so the normal removeToast() path is not involved.\n//\n// Close button: owned by the toast template, not ore-alert. ore-alert renders\n// content only. This keeps ore-alert a pure presentational component with no\n// animation lifecycle coupling.\n//\n// Max eviction: when adding would exceed max, oldest non-exiting toasts are\n// dismissed via removeToast() — animated, with onDismiss callback + event.\n//\n// Dismiss queue: removed. Each toast exits independently in parallel.\n// ---------------------------------------------------------------------------\n\n/** Duration (ms) of the CSS opacity exit transition on .toast-inner.\n * Must match the value in toast.css: `transition: opacity 300ms`. */\nconst TOAST_EXIT_MS = 300;\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport type OreToastEvents = {\n add: { id: string };\n dismiss: { id: string };\n};\n\nexport type OreToastProps = {\n max?: number;\n position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification */\nexport type ToastItem = {\n actions?: Array<{\n color?: ThemeColor;\n label: string;\n onClick?: () => void;\n variant?: 'solid' | 'flat' | 'bordered';\n }>;\n color?: ThemeColor;\n dismissible?: boolean;\n /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000) */\n duration?: number;\n heading?: string;\n /** Show message and actions side-by-side (horizontal layout) */\n horizontal?: boolean;\n /** Auto-generated via crypto.randomUUID() if omitted */\n id?: string;\n message: string;\n /** Metadata text (e.g. timestamp) shown in the alert meta slot */\n meta?: string;\n /** Called after the toast is fully dismissed and removed */\n onDismiss?: () => void;\n rounded?: RoundedSize | '';\n size?: ComponentSize;\n /**\n * Urgency level for screen readers.\n * - `'polite'` (default): announced after the user finishes their current action.\n * - `'assertive'`: interrupts the user immediately. Use only for critical errors.\n */\n urgency?: 'polite' | 'assertive';\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype ToastPhase = 'entering' | 'active' | 'exiting';\n\ntype ToastTimer = {\n remaining: number;\n startedAt: number;\n timeoutId: ReturnType<typeof setTimeout>;\n};\n\n/** Internal: a ToastItem that has been normalized and given a lifecycle phase. */\ntype ToastEntry = Required<Pick<ToastItem, 'dismissible' | 'duration' | 'id'>> &\n Omit<ToastItem, 'dismissible' | 'duration' | 'id'> & {\n id: string;\n phase: ToastPhase;\n timer: ToastTimer | null;\n };\n\n/** Public API of the ore-toast element */\nexport interface ToastElement extends HTMLElement {\n add: (toast: ToastItem) => string;\n clear: () => void;\n dismiss: (id: string) => void;\n update: (id: string, updates: Partial<ToastItem>) => void;\n}\n\n// ─── Component ───────────────────────────────────────────────────────────────\n\n/**\n * An accessible toast stack with polite/assertive live regions and hover expansion.\n * Stacks up to 3 notifications with a 3D effect.\n *\n * @element ore-toast\n *\n * @attr {string} position - 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'\n * @attr {number} max - Max toasts in DOM at once (default: 5)\n *\n * @fires add - When a toast is added `{ id }`\n * @fires dismiss - When a toast is dismissed `{ id }`\n *\n * @slot - Manually placed `ore-alert` elements\n *\n * @cssprop --toast-position - Position type (default: fixed)\n * @cssprop --toast-inset-top - Top inset\n * @cssprop --toast-inset-bottom - Bottom inset\n * @cssprop --toast-inset-left - Left inset\n * @cssprop --toast-inset-right - Right inset\n * @cssprop --toast-z-index - Z-index (default: 9999)\n * @cssprop --toast-max-width - Max width (default: 400px)\n * @cssprop --toast-gap - Gap between expanded toasts (default: 0.5rem)\n * @cssprop --toast-exit-duration - Exit animation duration (default: 300ms)\n *\n * @example\n * ```html\n * <!-- Declarative: place once in HTML -->\n * <ore-toast position=\"bottom-right\"></ore-toast>\n *\n * <!-- Programmatic: use the singleton service -->\n * <script type=\"module\">\n * import { toast } from '@vielzeug/refine';\n * toast.success('Changes saved!');\n * </script>\n * ```\n */\n\n/** Renders the action buttons for a toast entry. */\nfunction renderToastActions(entry: ToastEntry, onDismiss: () => void) {\n if (!entry.actions?.length) return '';\n\n return html`\n <div slot=\"actions\" class=\"toast-actions\">\n ${entry.actions.map(\n (action) => html`\n <ore-button\n size=\"sm\"\n color=${action.color || entry.color || 'primary'}\n variant=${action.variant || 'solid'}\n @click=${() => {\n action.onClick?.();\n onDismiss();\n }}\n >${action.label}</ore-button\n >\n `,\n )}\n </div>\n `;\n}\n\nexport const TOAST_TAG = 'ore-toast' as const;\ndefine<OreToastProps>(TOAST_TAG, {\n props: {\n max: prop.number(5),\n position: prop.oneOf(\n ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'] as const,\n 'bottom-right',\n ),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreToastEvents>();\n\n // Single source of truth for all toast state.\n const entries = signal<ToastEntry[]>([]);\n const containerRef = ref<HTMLDivElement>();\n\n // Per-toast swipe-to-dismiss controls (keyed by id, cleaned up in finalizeRemoval).\n const swipeControls = new Map<string, SwipeControl>();\n\n // Pause state is reactive so computed derivations and watches can observe it.\n const hoverPaused = signal(false);\n const focusPaused = signal(false);\n const paused = computed(() => hoverPaused.value || focusPaused.value);\n\n // ── Helpers ────────────────────────────────────────────────────────────\n\n const updateEntry = (id: string, patch: Partial<ToastEntry>) => {\n entries.value = entries.value.map((e) => (e.id === id ? { ...e, ...patch } : e));\n };\n\n const getEntry = (id: string) => entries.value.find((e) => e.id === id);\n\n const getInner = (wrapperOrEvent: HTMLElement | Event): HTMLElement | null => {\n const wrapper = wrapperOrEvent instanceof Event ? (wrapperOrEvent.currentTarget as HTMLElement) : wrapperOrEvent;\n\n return wrapper.querySelector<HTMLElement>('.toast-inner');\n };\n\n // ── Timer management ───────────────────────────────────────────────────\n\n const clearEntryTimer = (entry: ToastEntry): ToastEntry => {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n return { ...entry, timer: null };\n };\n\n const scheduleTimer = (id: string, remaining: number) => {\n if (remaining <= 0) return;\n\n const timeoutId = setTimeout(() => removeToast(id), remaining);\n\n updateEntry(id, { timer: { remaining, startedAt: Date.now(), timeoutId } });\n };\n\n const pauseTimers = () => {\n entries.value = entries.value.map((e) => {\n if (!e.timer) return e;\n\n clearTimeout(e.timer.timeoutId);\n\n return {\n ...e,\n timer: { ...e.timer, remaining: Math.max(0, e.timer.remaining - (Date.now() - e.timer.startedAt)) },\n };\n });\n };\n\n const resumeTimers = () => {\n for (const e of entries.value) {\n if (!e.timer || e.timer.remaining <= 0) continue;\n\n const timeoutId = setTimeout(() => removeToast(e.id), e.timer.remaining);\n\n updateEntry(e.id, { timer: { ...e.timer, startedAt: Date.now(), timeoutId } });\n }\n };\n\n // Watch reactive pause state — automatically pauses/resumes all timers.\n watch(paused, (isPaused) => {\n if (isPaused) pauseTimers();\n else resumeTimers();\n });\n\n // ── Swipe gesture ──────────────────────────────────────────────────────\n // Animates .toast-inner to avoid polluting the wrapper transition state.\n // On commit, calls finalizeRemoval() directly (swipe owns the animation).\n\n const createToastSwipe = (id: string): SwipeControl => {\n // Same reset behavior whether the swipe was interrupted by the platform\n // (onCancel) or simply released without crossing the commit threshold\n // (onRelease) — the toast snaps back to rest either way.\n const resetSwipeStyles = ({ event }: { event: PointerEvent }): void => {\n const inner = getInner(event);\n\n if (!inner) return;\n\n inner.style.transition = '';\n inner.style.transform = '';\n inner.style.opacity = '';\n };\n\n return createSwipeControl({\n axis: () => 'x',\n // Do not capture pointers for toast swipe gestures; capture can steal\n // close-button clicks when the gesture does not move.\n captureTarget: () => null,\n disabled: computed(() => !(getEntry(id)?.dismissible ?? true)),\n onCancel: resetSwipeStyles,\n onCommit: ({ distance, event }) => {\n const inner = getInner(event);\n\n if (!inner) return;\n\n const dir = distance >= 0 ? 1 : -1;\n const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n const finish = () => finalizeRemoval(id);\n\n if (reducedMotion) {\n inner.style.opacity = '0';\n finish();\n\n return;\n }\n\n inner.style.transition = 'transform 0.22s ease-out, opacity 0.22s ease-out';\n void inner.offsetWidth;\n inner.style.transform = `translateX(${dir * 120}%)`;\n inner.style.opacity = '0';\n\n const onTransitionEnd = (e: TransitionEvent) => {\n if (e.target !== inner || e.propertyName !== 'transform') return;\n\n inner.removeEventListener('transitionend', onTransitionEnd);\n clearTimeout(fallback);\n finish();\n };\n\n const fallback = setTimeout(() => {\n inner.removeEventListener('transitionend', onTransitionEnd);\n finish();\n }, 300);\n\n inner.addEventListener('transitionend', onTransitionEnd);\n },\n onMove: ({ distance, event }) => {\n const inner = getInner(event);\n\n if (!inner) return;\n\n inner.style.transition = 'none';\n inner.style.transform = `translateX(${distance}px)`;\n inner.style.opacity = String(Math.max(0, 1 - Math.abs(distance) / 200));\n },\n onRelease: resetSwipeStyles,\n });\n };\n\n // ── Toast lifecycle ────────────────────────────────────────────────────\n\n /** Remove all per-entry resources and fire callbacks. Does not animate. */\n const finalizeRemoval = (id: string) => {\n const entry = getEntry(id);\n\n // Clean up timer and swipe control before removing from signal.\n if (entry?.timer) clearTimeout(entry.timer.timeoutId);\n\n swipeControls.delete(id);\n entries.value = entries.value.filter((e) => e.id !== id);\n entry?.onDismiss?.();\n emit('dismiss', { id });\n };\n\n const addToast = (item: ToastItem): string => {\n const id = item.id || uuid();\n const maxToasts = props.max?.value ?? 5;\n\n // Evict oldest non-exiting toasts to stay within max — animated, with callbacks.\n const active = entries.value.filter((e) => e.phase !== 'exiting');\n const overflow = active.length - (maxToasts - 1);\n\n if (overflow > 0) {\n for (const evicted of active.slice(0, overflow)) removeToast(evicted.id);\n }\n\n const entry: ToastEntry = {\n dismissible: true,\n duration: 5000,\n ...item,\n id,\n phase: 'entering',\n timer: null,\n };\n\n swipeControls.set(id, createToastSwipe(id));\n entries.value = [...entries.value, entry];\n emit('add', { id });\n\n requestAnimationFrame(() => {\n // Guard: if the toast was dismissed before this rAF fired (e.g. evicted\n // by max), do not overwrite its exiting phase back to active.\n if (getEntry(id)?.phase === 'entering') updateEntry(id, { phase: 'active' });\n });\n\n if (entry.duration > 0) scheduleTimer(id, entry.duration);\n\n return id;\n };\n\n const removeToast = (id: string) => {\n const entry = getEntry(id);\n\n // Already animating out or not found — ignore.\n if (!entry || entry.phase === 'exiting') return;\n\n // Clear the auto-dismiss timer: the user (or max-eviction) is dismissing now.\n updateEntry(id, { ...clearEntryTimer(entry), phase: 'exiting' });\n\n // Force a layout flush on the current inner element (if in DOM now) so the\n // browser snapshots the current opacity as the animation start value.\n const innerEl = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"] .toast-inner`);\n\n void innerEl?.offsetHeight;\n\n let done = false;\n const onDone = () => {\n if (done) return;\n\n done = true;\n finalizeRemoval(id);\n };\n\n // TOAST_EXIT_MS is the built-in default, matching the CSS opacity transition's own\n // default. Read the *actual* computed duration so a consumer-customized\n // `--toast-exit-duration` doesn't get cut off by a shorter hardcoded fallback.\n // Fallback fires if transitionend never arrives (jsdom, reduced-motion, etc.).\n const computedExitMs = innerEl ? parseFloat(getComputedStyle(innerEl).transitionDuration) * 1000 : NaN;\n const exitMs = Number.isFinite(computedExitMs) && computedExitMs > 0 ? computedExitMs : TOAST_EXIT_MS;\n const fallback = setTimeout(onDone, exitMs + 50);\n\n // Listen on the container with event delegation so we are immune to\n // ore re-rendering the entries list (e.g. rAF phase transitions that\n // rebuild DOM after our listener would have been set up).\n // transitionend bubbles, so it reaches the container regardless of which\n // generation of .toast-inner element fires it.\n const onTransitionEnd = (e: TransitionEvent) => {\n const wrapper = (e.target as HTMLElement | null)?.closest?.(`[data-toast-id=\"${id}\"]`);\n\n if (!wrapper) return;\n\n containerRef.value?.removeEventListener('transitionend', onTransitionEnd);\n clearTimeout(fallback);\n onDone();\n };\n\n containerRef.value?.addEventListener('transitionend', onTransitionEnd);\n };\n\n const updateToast = (id: string, updates: Partial<ToastItem>) => {\n const entry = getEntry(id);\n\n if (!entry) return;\n\n const cleared = updates.duration !== undefined ? clearEntryTimer(entry) : entry;\n\n updateEntry(id, { ...cleared, ...updates, id });\n\n if (updates.duration !== undefined && updates.duration > 0) scheduleTimer(id, updates.duration);\n };\n\n const clearAll = () => {\n // Fire all removals concurrently — parallel fades are visually correct.\n for (const e of entries.value) {\n if (e.phase !== 'exiting') removeToast(e.id);\n }\n };\n\n // ── Derived lists for live regions ─────────────────────────────────────\n\n const urgencyOf = (e: ToastEntry) => e.urgency ?? (e.color === 'error' ? 'assertive' : 'polite');\n const politeEntries = computed(() => entries.value.filter((e) => urgencyOf(e) === 'polite'));\n const assertiveEntries = computed(() => entries.value.filter((e) => urgencyOf(e) === 'assertive'));\n\n // ── Cleanup on disconnect ──────────────────────────────────────────────\n\n onCleanup(() => {\n for (const e of entries.value) {\n if (e.timer) clearTimeout(e.timer.timeoutId);\n }\n\n swipeControls.clear();\n });\n\n // ── Template ───────────────────────────────────────────────────────────\n\n const renderEntry = (entry: ToastEntry) => {\n const dismiss = () => removeToast(entry.id);\n\n return html`\n <div\n class=\"toast-wrapper\"\n data-toast-id=${entry.id}\n part=\"toast-wrapper\"\n @pointerdown=${(e: PointerEvent) => swipeControls.get(entry.id)?.handlePointerDown(e)}\n @pointermove=${(e: PointerEvent) => swipeControls.get(entry.id)?.handlePointerMove(e)}\n @pointerup=${(e: PointerEvent) => swipeControls.get(entry.id)?.handlePointerUp(e)}\n @pointercancel=${(e: PointerEvent) => swipeControls.get(entry.id)?.handlePointerCancel(e)}>\n <div class=\"${() => `toast-inner${entry.phase !== 'active' ? ` ${entry.phase}` : ''}`}\" part=\"toast-inner\">\n <ore-alert\n color=${entry.color || (entry.urgency === 'assertive' ? 'error' : 'primary')}\n variant=${entry.variant || 'solid'}\n size=${entry.size || 'md'}\n rounded=${entry.rounded || 'md'}\n ?horizontal=${entry.horizontal}\n heading=${entry.heading || ''}\n ?dismissible=${entry.dismissible !== false}\n @dismiss=${dismiss}>\n ${entry.meta ? html`<span slot=\"meta\">${entry.meta}</span>` : ''} ${entry.message}\n ${renderToastActions(entry, dismiss)}\n </ore-alert>\n </div>\n </div>\n `;\n };\n\n // Expose imperative API directly on mount — calls made before mount are\n // safe because ore mounts synchronously on connectedCallback.\n onMounted(() => {\n const toastEl = el as ToastElement;\n\n toastEl.add = addToast;\n toastEl.clear = clearAll;\n toastEl.dismiss = removeToast;\n toastEl.update = updateToast;\n });\n\n return html`\n <div\n class=\"toast-container\"\n ref=${containerRef}\n @pointerenter=${() => {\n hoverPaused.value = true;\n el.classList.add('hovered');\n }}\n @pointerleave=${() => {\n hoverPaused.value = false;\n el.classList.remove('hovered');\n }}\n @focusin=${() => {\n focusPaused.value = true;\n }}\n @focusout=${() => {\n focusPaused.value = false;\n }}\n part=\"container\">\n <!-- Polite live region: normal informational toasts -->\n <div\n role=\"region\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Notifications\"\n class=\"toast-live-region\">\n ${() => politeEntries.value.map(renderEntry)}\n </div>\n <!-- Assertive live region: critical errors that interrupt immediately -->\n <div\n role=\"region\"\n aria-live=\"assertive\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Critical notifications\"\n class=\"toast-live-region\">\n ${() => assertiveEntries.value.map(renderEntry)}\n </div>\n <slot></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n});\n\n// ─── Toast service ────────────────────────────────────────────────────────────\n\nexport type ToastServiceConfig = OreToastProps;\n\nexport interface ToastService {\n /** Add a toast and return its id */\n add(item: ToastItem): string;\n /** Dismiss all toasts (animated, in parallel) */\n clear(): void;\n /**\n * Configure the auto-created container.\n * Has no effect if called after the first `add()` — logs a dev warning in that case.\n */\n configure(config: ToastServiceConfig): void;\n /** Dismiss a toast by id (animated) */\n dismiss(id: string): void;\n /** Shortcut: error toast with red color (assertive live region) */\n error(message: string, opts?: Partial<ToastItem>): string;\n /** Shortcut: info toast */\n info(message: string, opts?: Partial<ToastItem>): string;\n /**\n * Shows a loading toast tied to a promise.\n * Updates to success/error when the promise settles.\n */\n promise<T>(\n promise: Promise<T>,\n messages: {\n error: string | ((err: unknown) => string);\n loading: string;\n success: string | ((data: T) => string);\n },\n ): Promise<T>;\n /** Shortcut: success toast with green color */\n success(message: string, opts?: Partial<ToastItem>): string;\n /** Update an existing toast in-place */\n update(id: string, updates: Partial<ToastItem>): void;\n /** Shortcut: warning toast */\n warning(message: string, opts?: Partial<ToastItem>): string;\n}\n\n/**\n * Creates a scoped toast service backed by an `ore-toast` element.\n *\n * The service lazily creates an `<ore-toast>` element inside `root` on first\n * use. Pass a custom root to scope notifications to a sub-tree (e.g. a drawer),\n * or use the pre-built `toast` singleton which targets `document.body`.\n *\n * @example\n * ```ts\n * // Scoped instance\n * const drawerToast = createToastService(drawerEl);\n * drawerToast.success('Saved inside drawer');\n *\n * // The default singleton\n * import { toast } from '@vielzeug/refine';\n * toast.success('Saved!');\n * ```\n */\nexport function createToastService(root: ParentNode = document.body): ToastService {\n let host: ToastElement | null = null;\n let configured = false;\n let pendingConfig: ToastServiceConfig | null = null;\n\n const getHost = (): ToastElement => {\n if (host?.isConnected) return host;\n\n // Re-use an existing element in the root (supports declarative placement).\n host = (root instanceof Element ? root : (root as Document | ShadowRoot)).querySelector<ToastElement>('ore-toast');\n\n if (!host) {\n host = document.createElement('ore-toast') as ToastElement;\n\n if (pendingConfig) {\n if (pendingConfig.position) host.setAttribute('position', pendingConfig.position);\n\n if (pendingConfig.max != null) host.setAttribute('max', String(pendingConfig.max));\n\n pendingConfig = null;\n }\n\n (root as Element | Document).appendChild(host);\n }\n\n configured = true;\n\n return host;\n };\n\n const service: ToastService = {\n add(item) {\n return getHost().add(item);\n },\n\n clear() {\n getHost().clear();\n },\n\n configure(config) {\n if (configured) {\n warn('toast.configure() called after the container was already created; options ignored.');\n\n return;\n }\n\n pendingConfig = { ...pendingConfig, ...config };\n },\n\n dismiss(id) {\n getHost().dismiss(id);\n },\n\n error(message, opts) {\n return service.add({ color: 'error', ...opts, message });\n },\n\n info(message, opts) {\n return service.add({ color: 'info', ...opts, message });\n },\n\n async promise(promise, messages) {\n const id = service.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n try {\n const data = await promise;\n\n service.update(id, {\n color: 'success',\n dismissible: true,\n duration: 5000,\n message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n });\n\n return data;\n } catch (err) {\n service.update(id, {\n color: 'error',\n dismissible: true,\n duration: 5000,\n message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n });\n throw err;\n }\n },\n\n success(message, opts) {\n return service.add({ color: 'success', ...opts, message });\n },\n\n update(id, updates) {\n getHost().update(id, updates);\n },\n\n warning(message, opts) {\n return service.add({ color: 'warning', ...opts, message });\n },\n };\n\n return service;\n}\n\n/**\n * Singleton toast service — finds or creates a single `<ore-toast>` on `document.body`.\n *\n * @example\n * ```ts\n * import { toast } from '@vielzeug/refine';\n *\n * toast.success('Changes saved!');\n * toast.error('Upload failed', { duration: 0 });\n *\n * const id = toast.add({ message: 'Uploading…', duration: 0, dismissible: false });\n * toast.update(id, { message: 'Done!', color: 'success', duration: 3000, dismissible: true });\n *\n * await toast.promise(uploadFile(), {\n * loading: 'Uploading…',\n * success: (url) => `Uploaded to ${url}`,\n * error: 'Upload failed',\n * });\n * ```\n */\nexport const toast: ToastService = createToastService();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toast.js","names":["#entries","#listeners","#eventListeners","#disposed","#max","#setEntries","#emit","#entry","#update","#scheduleTimer","#clearTimer"],"sources":["../src/feedback/toast/toast.ts"],"sourcesContent":["import '../alert/alert';\nimport { uuid } from '@vielzeug/arsenal/random';\nimport { define, getHost, html, onCleanup, onMounted, prop, ref, useEmit } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch } from '@vielzeug/ripple/watch';\n\nimport type { SwipeControl } from '../../core';\nimport type { ComponentSize, RoundedSize, ThemeColor } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { createSwipeControl } from '../../core';\nimport { reducedMotionMixin } from '../../styles';\nimport componentStyles from './toast.css?inline';\n\n/** Must match toast.css's default opacity transition duration. */\nconst TOAST_EXIT_MS = 300;\n\nexport type OreToastEvents = {\n add: { id: string };\n dismiss: { id: string };\n};\n\nexport type OreToastProps = {\n max?: number;\n position?: 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';\n};\n\n/** Individual toast notification. */\nexport type ToastItem = {\n actions?: Array<{\n color?: ThemeColor;\n label: string;\n onClick?: () => void;\n variant?: 'solid' | 'flat' | 'bordered';\n }>;\n color?: ThemeColor;\n dismissible?: boolean;\n /** Auto-dismiss delay in ms. Set to 0 for persistent toasts (default: 5000). */\n duration?: number;\n heading?: string;\n /** Show message and actions side-by-side (horizontal layout). */\n horizontal?: boolean;\n /** Auto-generated when omitted. */\n id?: string;\n message: string;\n /** Metadata text (for example, a timestamp) shown in the alert meta slot. */\n meta?: string;\n /** Called after the toast is fully dismissed and removed. */\n onDismiss?: () => void;\n rounded?: RoundedSize | '';\n size?: ComponentSize;\n /**\n * Screen-reader announcement urgency. Error-coloured toasts are assertive by\n * default; all other toasts are polite.\n */\n urgency?: 'polite' | 'assertive';\n variant?: 'solid' | 'flat' | 'bordered';\n};\n\ntype ToastPhase = 'entering' | 'active' | 'exiting';\n\ntype ToastTimer = {\n remaining: number;\n startedAt: number;\n timeoutId: ReturnType<typeof setTimeout>;\n};\n\ntype ToastEntry = Required<Pick<ToastItem, 'dismissible' | 'duration' | 'id'>> &\n Omit<ToastItem, 'dismissible' | 'duration' | 'id'> & {\n exitTimeoutId: ReturnType<typeof setTimeout> | null;\n id: string;\n phase: ToastPhase;\n timer: ToastTimer | null;\n };\n\ntype ToastStoreEvent = {\n id: string;\n type: 'add' | 'dismiss';\n};\n\n/**\n * Owns notification data and every timer. Renderers only subscribe to this\n * store; they never expose imperative mutation methods themselves.\n */\nclass ToastStore {\n readonly #entries = signal<ToastEntry[]>([]);\n readonly #listeners = new Set<(entries: ToastEntry[]) => void>();\n readonly #eventListeners = new Set<(event: ToastStoreEvent) => void>();\n #disposed = false;\n #max = 5;\n\n add(item: ToastItem): string {\n if (this.#disposed) return item.id ?? uuid();\n\n const id = item.id ?? uuid();\n const active = this.#entries.value.filter((entry) => entry.phase !== 'exiting');\n const overflow = active.length - (this.#max - 1);\n\n if (overflow > 0) {\n for (const entry of active.slice(0, overflow)) this.dismiss(entry.id);\n }\n\n const entry: ToastEntry = {\n dismissible: true,\n duration: 5000,\n ...item,\n exitTimeoutId: null,\n id,\n phase: 'entering',\n timer: null,\n };\n\n this.#setEntries([...this.#entries.value, entry]);\n this.#emit({ id, type: 'add' });\n\n requestAnimationFrame(() => {\n if (this.#entry(id)?.phase === 'entering') this.#update(id, { phase: 'active' });\n });\n\n if (entry.duration > 0) this.#scheduleTimer(id, entry.duration);\n\n return id;\n }\n\n clear(): void {\n for (const entry of this.#entries.value) {\n if (entry.phase !== 'exiting') this.dismiss(entry.id);\n }\n }\n\n dispose(): void {\n if (this.#disposed) return;\n\n this.#disposed = true;\n\n for (const entry of this.#entries.value) {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n }\n\n this.#setEntries([]);\n this.#listeners.clear();\n this.#eventListeners.clear();\n }\n\n dismiss(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || entry.phase === 'exiting' || this.#disposed) return;\n\n this.#update(id, { ...this.#clearTimer(entry), phase: 'exiting' });\n this.scheduleFinalization(id, TOAST_EXIT_MS + 50);\n }\n\n finalize(id: string): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n this.#setEntries(this.#entries.value.filter((candidate) => candidate.id !== id));\n entry.onDismiss?.();\n this.#emit({ id, type: 'dismiss' });\n }\n\n pauseTimers(): void {\n if (this.#disposed) return;\n\n this.#setEntries(\n this.#entries.value.map((entry) => {\n if (!entry.timer) return entry;\n\n clearTimeout(entry.timer.timeoutId);\n\n return {\n ...entry,\n timer: {\n ...entry.timer,\n remaining: Math.max(0, entry.timer.remaining - (Date.now() - entry.timer.startedAt)),\n },\n };\n }),\n );\n }\n\n resumeTimers(): void {\n if (this.#disposed) return;\n\n for (const entry of this.#entries.value) {\n if (entry.phase === 'active' && entry.timer && entry.timer.remaining > 0) {\n this.#scheduleTimer(entry.id, entry.timer.remaining);\n }\n }\n }\n\n scheduleFinalization(id: string, delay: number): void {\n const entry = this.#entry(id);\n\n if (!entry || entry.phase !== 'exiting' || this.#disposed) return;\n\n if (entry.exitTimeoutId) clearTimeout(entry.exitTimeoutId);\n\n const exitTimeoutId = setTimeout(() => this.finalize(id), delay);\n\n this.#update(id, { exitTimeoutId });\n }\n\n setMax(max: number | undefined): void {\n if (max != null) this.#max = Math.max(1, max);\n }\n\n subscribe(listener: (entries: ToastEntry[]) => void): () => void {\n listener(this.#entries.value);\n this.#listeners.add(listener);\n\n return () => this.#listeners.delete(listener);\n }\n\n subscribeEvents(listener: (event: ToastStoreEvent) => void): () => void {\n this.#eventListeners.add(listener);\n\n return () => this.#eventListeners.delete(listener);\n }\n\n update(id: string, updates: Partial<ToastItem>): void {\n const entry = this.#entry(id);\n\n if (!entry || this.#disposed) return;\n\n const cleared = updates.duration !== undefined ? this.#clearTimer(entry) : entry;\n\n this.#update(id, { ...cleared, ...updates, id });\n\n if (updates.duration !== undefined && updates.duration > 0) this.#scheduleTimer(id, updates.duration);\n }\n\n #clearTimer(entry: ToastEntry): ToastEntry {\n if (entry.timer) clearTimeout(entry.timer.timeoutId);\n\n return { ...entry, timer: null };\n }\n\n #emit(event: ToastStoreEvent): void {\n for (const listener of this.#eventListeners) listener(event);\n }\n\n #entry(id: string): ToastEntry | undefined {\n return this.#entries.value.find((entry) => entry.id === id);\n }\n\n #scheduleTimer(id: string, remaining: number): void {\n if (remaining <= 0 || this.#disposed) return;\n\n const timeoutId = setTimeout(() => this.dismiss(id), remaining);\n\n this.#update(id, { timer: { remaining, startedAt: Date.now(), timeoutId } });\n }\n\n #setEntries(entries: ToastEntry[]): void {\n this.#entries.value = entries;\n for (const listener of this.#listeners) listener(entries);\n }\n\n #update(id: string, patch: Partial<ToastEntry>): void {\n this.#setEntries(this.#entries.value.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)));\n }\n}\n\ntype ToastHostBinding = {\n bind: (store: ToastStore) => void;\n unbind: () => void;\n};\n\nconst hostBindings = new WeakMap<HTMLElement, ToastHostBinding>();\nconst hostStores = new WeakMap<HTMLElement, ToastStore>();\n\nconst bindToastHost = (host: HTMLElement, store: ToastStore): void => {\n hostStores.set(host, store);\n hostBindings.get(host)?.bind(store);\n};\n\n/** Renders the action buttons for a toast entry. */\nfunction renderToastActions(entry: ToastEntry, dismiss: () => void) {\n if (!entry.actions?.length) return '';\n\n return html`\n <div slot=\"actions\" class=\"toast-actions\">\n ${entry.actions.map(\n (action) => html`\n <ore-button\n size=\"sm\"\n color=${action.color || entry.color || 'primary'}\n variant=${action.variant || 'solid'}\n @click=${() => {\n action.onClick?.();\n dismiss();\n }}>\n ${action.label}\n </ore-button>\n `,\n )}\n </div>\n `;\n}\n\nexport const TOAST_TAG = 'ore-toast' as const;\n\n/**\n * Declarative toast host. It subscribes to the service for its scope and\n * renders notifications, but has no imperative mutation API of its own.\n *\n * @element ore-toast\n *\n * @attr {string} position - Stack placement.\n * @attr {number} max - Maximum live notifications for the scoped service.\n */\ndefine<OreToastProps>(TOAST_TAG, {\n props: {\n max: prop.number(5),\n position: prop.oneOf(\n ['top-left', 'top-center', 'top-right', 'bottom-left', 'bottom-center', 'bottom-right'] as const,\n 'bottom-right',\n ),\n },\n setup() {\n const el = getHost() as HTMLElement;\n const emit = useEmit<OreToastEvents>();\n const containerRef = ref<HTMLDivElement>();\n const entries = signal<ToastEntry[]>([]);\n const hoverPaused = signal(false);\n const focusPaused = signal(false);\n const paused = computed(() => hoverPaused.value || focusPaused.value);\n const swipeControls = new Map<string, SwipeControl>();\n const exiting = new Map<string, () => void>();\n const swiping = new Set<string>();\n let store: ToastStore | null = null;\n let unsubscribeEntries = () => {};\n let unsubscribeEvents = () => {};\n\n const getInner = (wrapperOrEvent: HTMLElement | Event): HTMLElement | null => {\n const wrapper = wrapperOrEvent instanceof Event ? (wrapperOrEvent.currentTarget as HTMLElement) : wrapperOrEvent;\n\n return wrapper.querySelector<HTMLElement>('.toast-inner');\n };\n\n const clearExitListener = (id: string): void => {\n exiting.get(id)?.();\n exiting.delete(id);\n };\n\n const finalizeSwipe = (id: string): void => {\n swiping.delete(id);\n store?.finalize(id);\n };\n\n const createToastSwipe = (id: string): SwipeControl => {\n const isDismissible = (): boolean => entries.value.find((entry) => entry.id === id)?.dismissible ?? true;\n\n return createSwipeControl({\n axis: () => 'x',\n captureTarget: () => null,\n disabled: {\n peek: () => !isDismissible(),\n subscribe: (listener) => entries.subscribe(listener),\n get value() {\n return !isDismissible();\n },\n },\n onCancel: ({ event }) => {\n const inner = getInner(event);\n\n if (!inner) return;\n\n inner.style.transition = '';\n inner.style.transform = '';\n inner.style.opacity = '';\n },\n onCommit: ({ distance, event }) => {\n const inner = getInner(event);\n\n if (!inner || !store) return;\n\n swiping.add(id);\n\n store.dismiss(id);\n\n const finish = () => finalizeSwipe(id);\n\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) {\n inner.style.opacity = '0';\n finish();\n\n return;\n }\n\n const direction = distance >= 0 ? 1 : -1;\n\n inner.style.transition = 'transform 0.22s ease-out, opacity 0.22s ease-out';\n void inner.offsetWidth;\n inner.style.transform = `translateX(${direction * 120}%)`;\n inner.style.opacity = '0';\n\n const onTransitionEnd = (transition: TransitionEvent) => {\n if (transition.target !== inner || transition.propertyName !== 'transform') return;\n\n inner.removeEventListener('transitionend', onTransitionEnd);\n finish();\n };\n\n inner.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, 300);\n },\n onMove: ({ distance, event }) => {\n const inner = getInner(event);\n\n if (!inner) return;\n\n inner.style.transition = 'none';\n inner.style.transform = `translateX(${distance}px)`;\n inner.style.opacity = String(Math.max(0, 1 - Math.abs(distance) / 200));\n },\n onRelease: ({ event }) => {\n const inner = getInner(event);\n\n if (!inner) return;\n\n inner.style.transition = '';\n inner.style.transform = '';\n inner.style.opacity = '';\n },\n });\n };\n\n const beginExit = (id: string): void => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n requestAnimationFrame(() => {\n if (!store || exiting.has(id) || swiping.has(id)) return;\n\n const inner = containerRef.value?.querySelector<HTMLElement>(`[data-toast-id=\"${id}\"] .toast-inner`);\n\n if (!inner) {\n store.scheduleFinalization(id, TOAST_EXIT_MS);\n\n return;\n }\n\n void inner.offsetHeight;\n\n const duration = parseFloat(getComputedStyle(inner).transitionDuration) * 1000;\n const exitMs = Number.isFinite(duration) && duration > 0 ? duration : TOAST_EXIT_MS;\n const onTransitionEnd = (event: TransitionEvent) => {\n const wrapper = (event.target as HTMLElement | null)?.closest?.(`[data-toast-id=\"${id}\"]`);\n\n if (!wrapper) return;\n\n clearExitListener(id);\n store?.finalize(id);\n };\n const remove = () => containerRef.value?.removeEventListener('transitionend', onTransitionEnd);\n\n exiting.set(id, remove);\n containerRef.value?.addEventListener('transitionend', onTransitionEnd);\n store.scheduleFinalization(id, exitMs + 50);\n });\n };\n\n const syncControls = (): void => {\n const currentIds = new Set(entries.value.map((entry) => entry.id));\n\n for (const [id, control] of swipeControls) {\n if (!currentIds.has(id)) {\n control.dispose();\n\n swipeControls.delete(id);\n clearExitListener(id);\n swiping.delete(id);\n }\n }\n\n for (const entry of entries.value) {\n if (!swipeControls.has(entry.id)) swipeControls.set(entry.id, createToastSwipe(entry.id));\n\n if (entry.phase === 'exiting') beginExit(entry.id);\n }\n };\n\n watch(entries, syncControls);\n watch(paused, (isPaused) => {\n if (isPaused) store?.pauseTimers();\n else store?.resumeTimers();\n });\n\n const bind = (nextStore: ToastStore): void => {\n if (store === nextStore) return;\n\n unsubscribeEntries();\n\n unsubscribeEvents();\n store = nextStore;\n unsubscribeEntries = store.subscribe((nextEntries) => {\n entries.value = nextEntries;\n });\n unsubscribeEvents = store.subscribeEvents((event) => emit(event.type, { id: event.id }));\n\n if (paused.value) store.pauseTimers();\n };\n\n const renderEntry = (entry: ToastEntry) => {\n const dismiss = () => store?.dismiss(entry.id);\n\n return html`\n <div\n class=\"toast-wrapper\"\n data-toast-id=${entry.id}\n part=\"toast-wrapper\"\n @pointerdown=${(event: PointerEvent) => swipeControls.get(entry.id)?.handlePointerDown(event)}\n @pointermove=${(event: PointerEvent) => swipeControls.get(entry.id)?.handlePointerMove(event)}\n @pointerup=${(event: PointerEvent) => swipeControls.get(entry.id)?.handlePointerUp(event)}\n @pointercancel=${(event: PointerEvent) => swipeControls.get(entry.id)?.handlePointerCancel(event)}>\n <div class=\"${() => `toast-inner${entry.phase !== 'active' ? ` ${entry.phase}` : ''}`}\" part=\"toast-inner\">\n <ore-alert\n color=${entry.color || (entry.urgency === 'assertive' ? 'error' : 'primary')}\n variant=${entry.variant || 'solid'}\n size=${entry.size || 'md'}\n rounded=${entry.rounded || 'md'}\n ?horizontal=${entry.horizontal}\n heading=${entry.heading || ''}\n ?dismissible=${entry.dismissible}\n @dismiss=${dismiss}>\n ${\n entry.meta\n ? html`\n <span slot=\"meta\">${entry.meta}</span>\n `\n : ''\n }\n ${entry.message} ${renderToastActions(entry, dismiss)}\n </ore-alert>\n </div>\n </div>\n `;\n };\n\n onMounted(() => {\n hostBindings.set(el, {\n bind,\n unbind() {\n unsubscribeEntries();\n unsubscribeEvents();\n store = null;\n entries.value = [];\n },\n });\n\n const boundStore = hostStores.get(el);\n\n if (boundStore) bind(boundStore);\n });\n\n onCleanup(() => {\n hostBindings.get(el)?.unbind();\n\n hostBindings.delete(el);\n\n for (const control of swipeControls.values()) control.dispose();\n for (const id of exiting.keys()) clearExitListener(id);\n });\n\n const urgencyOf = (entry: ToastEntry) => entry.urgency ?? (entry.color === 'error' ? 'assertive' : 'polite');\n const politeEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'polite'));\n const assertiveEntries = computed(() => entries.value.filter((entry) => urgencyOf(entry) === 'assertive'));\n\n return html`\n <div\n class=\"toast-container\"\n ref=${containerRef}\n @pointerenter=${() => {\n hoverPaused.value = true;\n el.classList.add('hovered');\n }}\n @pointerleave=${() => {\n hoverPaused.value = false;\n el.classList.remove('hovered');\n }}\n @focusin=${() => {\n focusPaused.value = true;\n }}\n @focusout=${() => {\n focusPaused.value = false;\n }}\n part=\"container\">\n <div\n role=\"region\"\n aria-live=\"polite\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Notifications\"\n class=\"toast-live-region\">\n ${() => politeEntries.value.map(renderEntry)}\n </div>\n <div\n role=\"region\"\n aria-live=\"assertive\"\n aria-relevant=\"additions removals\"\n aria-atomic=\"false\"\n aria-label=\"Critical notifications\"\n class=\"toast-live-region\">\n ${() => assertiveEntries.value.map(renderEntry)}\n </div>\n <slot></slot>\n </div>\n `;\n },\n styles: [reducedMotionMixin, componentStyles],\n});\n\nexport type ToastServiceConfig = OreToastProps;\n\nexport interface ToastService {\n add(item: ToastItem): string;\n clear(): void;\n configure(config: ToastServiceConfig): void;\n readonly disposed: boolean;\n dismiss(id: string): void;\n readonly disposalSignal: AbortSignal;\n dispose(): void;\n error(message: string, opts?: Partial<ToastItem>): string;\n info(message: string, opts?: Partial<ToastItem>): string;\n promise<T>(\n promise: Promise<T>,\n messages: {\n error: string | ((err: unknown) => string);\n loading: string;\n success: string | ((data: T) => string);\n },\n ): Promise<T>;\n success(message: string, opts?: Partial<ToastItem>): string;\n update(id: string, updates: Partial<ToastItem>): void;\n warning(message: string, opts?: Partial<ToastItem>): string;\n [Symbol.dispose](): void;\n}\n\nconst services = new WeakMap<ParentNode, ToastService>();\n\n/**\n * Creates a scoped toast service. The service owns its notification store and\n * binds it to the declarative `<ore-toast>` host inside `root`, creating that\n * host lazily when notifications are first requested.\n */\nexport function createToastService(root: ParentNode = document.body): ToastService {\n const existing = services.get(root);\n\n if (existing) return existing;\n\n const store = new ToastStore();\n const disposalController = new AbortController();\n let disposed = false;\n let configured = false;\n let pendingConfig: ToastServiceConfig | null = null;\n let host: HTMLElement | null = null;\n\n const assertActive = (): boolean => !disposed;\n const rootNode = root as Element | Document | ShadowRoot;\n const getHost = (): HTMLElement | null => {\n if (!assertActive()) return null;\n\n if (host?.isConnected) return host;\n\n host = rootNode.querySelector<HTMLElement>(TOAST_TAG);\n\n if (!host) {\n host = document.createElement(TOAST_TAG);\n\n if (pendingConfig?.position) host.setAttribute('position', pendingConfig.position);\n\n if (pendingConfig?.max != null) host.setAttribute('max', String(pendingConfig.max));\n\n rootNode.appendChild(host);\n }\n\n if (pendingConfig?.max != null) store.setMax(pendingConfig.max);\n else {\n const max = Number(host.getAttribute('max'));\n\n if (Number.isFinite(max) && max > 0) store.setMax(max);\n }\n\n pendingConfig = null;\n configured = true;\n bindToastHost(host, store);\n\n return host;\n };\n const ensureHost = (): boolean => Boolean(getHost());\n\n const service: ToastService = {\n add(item) {\n if (!ensureHost()) return item.id ?? uuid();\n\n return store.add(item);\n },\n\n clear() {\n if (ensureHost()) store.clear();\n },\n\n configure(config) {\n if (configured) {\n warn('toast.configure() called after the container was already created; options ignored.');\n\n return;\n }\n\n pendingConfig = { ...pendingConfig, ...config };\n },\n\n dismiss(id) {\n if (ensureHost()) store.dismiss(id);\n },\n\n get disposalSignal() {\n return disposalController.signal;\n },\n\n dispose() {\n if (disposed) return;\n\n disposed = true;\n\n disposalController.abort();\n\n store.dispose();\n\n if (services.get(root) === service) services.delete(root);\n },\n\n get disposed() {\n return disposed;\n },\n\n error(message, opts) {\n return service.add({ color: 'error', ...opts, message });\n },\n\n info(message, opts) {\n return service.add({ color: 'info', ...opts, message });\n },\n\n async promise(promise, messages) {\n const id = service.add({ color: 'primary', dismissible: false, duration: 0, message: messages.loading });\n\n try {\n const data = await promise;\n\n service.update(id, {\n color: 'success',\n dismissible: true,\n duration: 5000,\n message: typeof messages.success === 'function' ? messages.success(data) : messages.success,\n });\n\n return data;\n } catch (err) {\n service.update(id, {\n color: 'error',\n dismissible: true,\n duration: 5000,\n message: typeof messages.error === 'function' ? messages.error(err) : messages.error,\n });\n throw err;\n }\n },\n\n success(message, opts) {\n return service.add({ color: 'success', ...opts, message });\n },\n\n [Symbol.dispose]() {\n service.dispose();\n },\n\n update(id, updates) {\n if (ensureHost()) store.update(id, updates);\n },\n\n warning(message, opts) {\n return service.add({ color: 'warning', ...opts, message });\n },\n };\n\n services.set(root, service);\n\n return service;\n}\n\n/** Singleton service backed by a lazily created host in `document.body`. */\nexport const toast: ToastService = createToastService();\n"],"mappings":"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"}
|
package/dist/tooltip.cjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/theme.css.cjs"),t=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/theme.css.cjs"),t=require("./core/parse.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./overlay/shared/use-floating-trigger.cjs"),i=require("./overlay/tooltip/tooltip.css.cjs");let a=require("@vielzeug/ore"),o=require("@vielzeug/ripple");var s=4,c=[`hover`,`focus`],l=new Set([`click`,`focus`,`hover`]),u=e=>{if(e==null||e.trim()===``)return 0;let t=Number(e);return Number.isFinite(t)&&t>=0?t:0},d=e=>e==null?void 0:e===``||e===`true`,f=e=>t.parseStringTriggers(e,l,c),p=`ore-tooltip`;(0,a.define)(p,{props:{...n.sizableBundle,...n.disablableBundle,"close-delay":{default:0,parse:u},content:a.prop.string(),"default-open":a.prop.bool(!1),delay:{default:0,parse:u},open:{default:void 0,parse:d},placement:a.prop.oneOf([`top`,`bottom`,`left`,`right`],`top`),trigger:a.prop.string(`hover,focus`),variant:a.prop.string()},setup(e){let t=(0,a.getHost)(),n=(0,a.useEmit)(),i=(0,a.useSlots)(),c=t.shadowRoot,l=(0,o.computed)(()=>!!e.disabled.value),u=(0,o.computed)(()=>e.open.value!==void 0),d=(0,o.signal)(`top`),p=(0,a.createStableId)(`tooltip`),m=(0,o.computed)(()=>f(e.trigger.value)),h=null,g=null,_=null,v=()=>{g&&=(clearTimeout(g),null)},y=()=>{_&&=(clearTimeout(_),null)},b=r.useFloatingTrigger({bindTriggerAria:e=>(0,a.bind)({aria:{describedby:()=>p}},{target:e}),defaultOpen:e[`default-open`],disabled:l,getPanel:()=>h,offset:8,onCleanup:a.onCleanup,onClose:e=>n(`open-change`,{open:!1,reason:e}),onOpen:e=>n(`open-change`,{open:!0,reason:e}),onPlacementChange:e=>{let t=e.split(`-`)[0];d.value=t,t===`left`&&h&&(h.style.left=`${parseFloat(h.style.left)-s}px`)},openProp:e.open,placement:(0,o.computed)(()=>e.placement.value),slot:()=>c?.querySelector(`slot:not([name])`)??null,slotElements:i.elements(),triggers:(0,o.computed)(()=>[])});function x(t=`hover`){if(u.value||l.value||!e.content.value&&!i.has(`content`).value)return;y(),v();let n=Number(e.delay.value)||0;n>0?g=setTimeout(()=>{g=null,b.open(t),b.updatePosition()},n):(b.open(t),b.updatePosition())}function S(){if(u.value)return;v();let t=Number(e[`close-delay`].value)||0;t>0?(y(),_=setTimeout(()=>{_=null,b.close(`trigger`)},t)):b.close(`trigger`)}return(0,a.onMounted)(()=>{let e=c?.querySelector(`slot:not([name])`),t=[],n=(e,n,r)=>{e.addEventListener(n,r),t.push(()=>e.removeEventListener(n,r))},r=()=>{for(let e of t)e();t=[];let r=e?.assignedElements({flatten:!0})[0];if(!r)return;let i=m.value;i.includes(`hover`)&&(n(r,`pointerenter`,()=>x(`hover`)),n(r,`pointerleave`,S)),i.includes(`focus`)&&(n(r,`focusin`,()=>x(`focus`)),n(r,`focusout`,S)),i.includes(`click`)&&n(r,`click`,()=>b.visible.value?S():x(`click`))};e?.addEventListener(`slotchange`,r),r();let i=b.mount();return()=>{e?.removeEventListener(`slotchange`,r);for(let e of t)e();v(),y(),i()}}),a.html`
|
|
2
2
|
<slot></slot>
|
|
3
3
|
<div
|
|
4
4
|
class="tooltip"
|
|
5
5
|
part="tooltip"
|
|
6
|
-
id="${
|
|
6
|
+
id="${p}"
|
|
7
7
|
role="tooltip"
|
|
8
8
|
popover="manual"
|
|
9
|
-
ref=${e=>{
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
ref=${e=>{h=e}}
|
|
10
|
+
data-placement="${d}"
|
|
11
|
+
aria-hidden="${()=>String(!b.visible.value)}">
|
|
12
12
|
<slot name="content"><span class="tooltip-text">${e.content}</span></slot>
|
|
13
13
|
</div>
|
|
14
14
|
`},styles:[e.forcedColorsMixin,i.default]}),exports.TOOLTIP_TAG=p;
|
package/dist/tooltip.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.cjs","names":[],"sources":["../src/overlay/tooltip/tooltip.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport { createStableId, define, html, prop, aria, getHost, onCleanup, onMounted, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize } from '../../types';\n\nimport { parseStringTriggers } from '../../headless';\nimport { disablableBundle, sizableBundle } from '../../shared';\nimport { forcedColorsMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './tooltip.css?inline';\n\ntype TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\ntype TooltipTrigger = 'click' | 'focus' | 'hover';\n\nconst LEFT_GAP_COMPENSATION = 4;\nconst DEFAULT_TOOLTIP_TRIGGERS: TooltipTrigger[] = ['hover', 'focus'];\nconst VALID_TOOLTIP_TRIGGERS = new Set<TooltipTrigger>(['click', 'focus', 'hover']);\n\nconst parseDelayMs = (value: string | null): number => {\n if (value == null || value.trim() === '') return 0;\n\n const parsed = Number(value);\n\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;\n};\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: string | null | undefined): TooltipTrigger[] =>\n parseStringTriggers(value, VALID_TOOLTIP_TRIGGERS, DEFAULT_TOOLTIP_TRIGGERS);\n\n/** Tooltip component properties */\nexport type OreTooltipProps = {\n /** Hide delay in ms */\n 'close-delay'?: number;\n /** Tooltip text content */\n content?: string;\n /** Show delay in ms */\n delay?: number;\n /** Disable the tooltip */\n disabled?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to trigger */\n placement?: TooltipPlacement;\n /** Tooltip size */\n size?: ComponentSize;\n /** Which trigger(s) show/hide the tooltip */\n trigger?: string;\n /** Visual variant */\n variant?: 'dark' | 'light';\n};\n\n/**\n * A lightweight tooltip shown on hover/focus/click relative to the slotted trigger.\n *\n * @element ore-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} placement - 'top' | 'bottom' | 'left' | 'right' (default: 'top')\n * @attr {string} trigger - 'hover' | 'focus' | 'click' or comma-separated combination\n * @attr {number} delay - Show delay in milliseconds (default: 0)\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - 'dark' (default) | 'light'\n * @attr {boolean} disabled - Disable the tooltip\n *\n * @slot - Trigger element that the tooltip is anchored to\n * @slot content - Complex tooltip content (overrides the `content` attribute)\n *\n * @cssprop --tooltip-max-width - Max width of the tooltip bubble\n *\n * @part tooltip - Tooltip container.\n * @example\n * ```html\n * <!-- Simple text tooltip -->\n * <ore-tooltip content=\"Copy to clipboard\">\n * <button>Copy</button>\n * </ore-tooltip>\n *\n * <!-- Placement and delay -->\n * <ore-tooltip content=\"Save your work\" placement=\"right\" delay=\"300\">\n * <ore-icon name=\"save\"></ore-icon>\n * </ore-tooltip>\n *\n * <!-- Hover + focus trigger -->\n * <ore-tooltip content=\"Required field\" trigger=\"hover,focus\" placement=\"top\">\n * <ore-input label=\"Email\" type=\"email\"></ore-input>\n * </ore-tooltip>\n *\n * <!-- Rich content slot -->\n * <ore-tooltip>\n * <ore-button>Help</ore-button>\n * <div slot=\"content\">\n * <strong>Keyboard shortcuts</strong>\n * <p>Press Ctrl+S to save.</p>\n * </div>\n * </ore-tooltip>\n * ```\n */\nexport const TOOLTIP_TAG = 'ore-tooltip' as const;\ndefine<OreTooltipProps>(TOOLTIP_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'close-delay': { default: 0, parse: parseDelayMs },\n content: prop.string(),\n delay: { default: 0, parse: parseDelayMs },\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(['top', 'bottom', 'left', 'right'] as const, 'top'),\n trigger: prop.string('hover,focus'),\n variant: prop.string<'dark' | 'light'>(),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const isControlled = computed(() => props.open.value !== undefined);\n const activePlacement = signal<TooltipPlacement>('top');\n const tooltipId = createStableId('tooltip');\n const triggers = computed<TooltipTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let tooltipEl: HTMLElement | null = null;\n let showTimer: ReturnType<typeof setTimeout> | null = null;\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n const clearShowTimer = (): void => {\n if (!showTimer) return;\n\n clearTimeout(showTimer);\n showTimer = null;\n };\n const clearHideTimer = (): void => {\n if (!hideTimer) return;\n\n clearTimeout(hideTimer);\n hideTimer = null;\n };\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) => aria(triggerEl, { describedby: () => tooltipId }),\n disabled: isDisabled,\n getPanel: () => tooltipEl,\n offset: 8,\n onCleanup,\n onPlacementChange: (p) => {\n const side = p.split('-')[0] as TooltipPlacement;\n\n activePlacement.value = side;\n\n if (side === 'left' && tooltipEl) {\n tooltipEl.style.left = `${parseFloat(tooltipEl.style.left) - LEFT_GAP_COMPENSATION}px`;\n }\n },\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers: computed(() => [] as TooltipTrigger[]),\n });\n\n function show(): void {\n if (isControlled.value) return;\n\n if (isDisabled.value || (!props.content.value && !slots.has('content').value)) return;\n\n clearHideTimer();\n clearShowTimer();\n\n const delay = Number(props.delay.value) || 0;\n\n if (delay > 0) {\n showTimer = setTimeout(() => {\n showTimer = null;\n floating.open('hover');\n floating.updatePosition();\n }, delay);\n } else {\n floating.open('hover');\n floating.updatePosition();\n }\n }\n\n function hide(): void {\n if (isControlled.value) return;\n\n clearShowTimer();\n\n const closeDelay = Number(props['close-delay'].value) || 0;\n\n if (closeDelay > 0) {\n clearHideTimer();\n hideTimer = setTimeout(() => {\n hideTimer = null;\n floating.close('trigger');\n }, closeDelay);\n } else {\n floating.close('trigger');\n }\n }\n\n onMounted(() => {\n // Manually bind trigger events so we can wrap show/hide with delay timers.\n // useFloatingTrigger handles ARIA, positioning, controlled mode, and keyboard dismiss.\n const triggerSlot = shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n let eventCleanups: Array<() => void> = [];\n\n const addEvent = (target: EventTarget, event: string, handler: EventListener): void => {\n target.addEventListener(event, handler);\n eventCleanups.push(() => target.removeEventListener(event, handler));\n };\n\n const bindTriggerEvents = (): void => {\n for (const cleanup of eventCleanups) cleanup();\n eventCleanups = [];\n\n const triggerEl = triggerSlot?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) return;\n\n const t = triggers.value;\n\n if (t.includes('hover')) {\n addEvent(triggerEl, 'pointerenter', show);\n addEvent(triggerEl, 'pointerleave', hide);\n }\n\n if (t.includes('focus')) {\n addEvent(triggerEl, 'focusin', show);\n addEvent(triggerEl, 'focusout', hide);\n }\n\n if (t.includes('click')) {\n addEvent(triggerEl, 'click', () => (floating.visible.value ? hide() : show()));\n }\n };\n\n triggerSlot?.addEventListener('slotchange', bindTriggerEvents);\n bindTriggerEvents();\n\n const destroyFloating = floating.mount();\n\n return () => {\n triggerSlot?.removeEventListener('slotchange', bindTriggerEvents);\n for (const cleanup of eventCleanups) cleanup();\n clearShowTimer();\n clearHideTimer();\n destroyFloating();\n };\n });\n\n return html`\n <slot></slot>\n <div\n class=\"tooltip\"\n part=\"tooltip\"\n id=\"${tooltipId}\"\n role=\"tooltip\"\n popover=\"manual\"\n ref=${(ref: HTMLElement) => {\n tooltipEl = ref;\n }}\n :data-placement=\"${activePlacement}\"\n :aria-hidden=\"${() => String(!floating.visible.value)}\">\n <slot name=\"content\"><span class=\"tooltip-text\">${props.content}</span></slot>\n </div>\n `;\n },\n styles: [forcedColorsMixin, styles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tooltip.cjs","names":[],"sources":["../src/overlay/tooltip/tooltip.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport {\n createStableId,\n define,\n html,\n prop,\n bind,\n getHost,\n onCleanup,\n onMounted,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize } from '../../types';\n\nimport { type OverlayOpenChangeDetail, type OverlayOpenReason, parseStringTriggers } from '../../core';\nimport { disablableBundle, sizableBundle } from '../../shared';\nimport { forcedColorsMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './tooltip.css?inline';\n\ntype TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\ntype TooltipTrigger = 'click' | 'focus' | 'hover';\n\nconst LEFT_GAP_COMPENSATION = 4;\nconst DEFAULT_TOOLTIP_TRIGGERS: TooltipTrigger[] = ['hover', 'focus'];\nconst VALID_TOOLTIP_TRIGGERS = new Set<TooltipTrigger>(['click', 'focus', 'hover']);\n\nconst parseDelayMs = (value: string | null): number => {\n if (value == null || value.trim() === '') return 0;\n\n const parsed = Number(value);\n\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;\n};\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: string | null | undefined): TooltipTrigger[] =>\n parseStringTriggers(value, VALID_TOOLTIP_TRIGGERS, DEFAULT_TOOLTIP_TRIGGERS);\n\n/** Tooltip component properties */\nexport type OreTooltipEvents = {\n 'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreTooltipProps = {\n /** Hide delay in ms */\n 'close-delay'?: number;\n /** Tooltip text content */\n content?: string;\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n /** Show delay in ms */\n delay?: number;\n /** Disable the tooltip */\n disabled?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to trigger */\n placement?: TooltipPlacement;\n /** Tooltip size */\n size?: ComponentSize;\n /** Which trigger(s) show/hide the tooltip */\n trigger?: string;\n /** Visual variant */\n variant?: 'dark' | 'light';\n};\n\n/**\n * A lightweight tooltip shown on hover/focus/click relative to the slotted trigger.\n *\n * @element ore-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} placement - 'top' | 'bottom' | 'left' | 'right' (default: 'top')\n * @attr {string} trigger - 'hover' | 'focus' | 'click' or comma-separated combination\n * @attr {number} delay - Show delay in milliseconds (default: 0)\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - 'dark' (default) | 'light'\n * @attr {boolean} disabled - Disable the tooltip\n *\n * @slot - Trigger element that the tooltip is anchored to\n * @slot content - Complex tooltip content (overrides the `content` attribute)\n * @fires open-change - Fired when the tooltip state changes. detail: { open, reason }\n *\n * @cssprop --tooltip-max-width - Max width of the tooltip bubble\n *\n * @part tooltip - Tooltip container.\n * @example\n * ```html\n * <!-- Simple text tooltip -->\n * <ore-tooltip content=\"Copy to clipboard\">\n * <button>Copy</button>\n * </ore-tooltip>\n *\n * <!-- Placement and delay -->\n * <ore-tooltip content=\"Save your work\" placement=\"right\" delay=\"300\">\n * <ore-icon name=\"save\"></ore-icon>\n * </ore-tooltip>\n *\n * <!-- Hover + focus trigger -->\n * <ore-tooltip content=\"Required field\" trigger=\"hover,focus\" placement=\"top\">\n * <ore-input label=\"Email\" type=\"email\"></ore-input>\n * </ore-tooltip>\n *\n * <!-- Rich content slot -->\n * <ore-tooltip>\n * <ore-button>Help</ore-button>\n * <div slot=\"content\">\n * <strong>Keyboard shortcuts</strong>\n * <p>Press Ctrl+S to save.</p>\n * </div>\n * </ore-tooltip>\n * ```\n */\nexport const TOOLTIP_TAG = 'ore-tooltip' as const;\ndefine<OreTooltipProps>(TOOLTIP_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'close-delay': { default: 0, parse: parseDelayMs },\n content: prop.string(),\n 'default-open': prop.bool(false),\n delay: { default: 0, parse: parseDelayMs },\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(['top', 'bottom', 'left', 'right'] as const, 'top'),\n trigger: prop.string('hover,focus'),\n variant: prop.string<'dark' | 'light'>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreTooltipEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const isControlled = computed(() => props.open.value !== undefined);\n const activePlacement = signal<TooltipPlacement>('top');\n const tooltipId = createStableId('tooltip');\n const triggers = computed<TooltipTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let tooltipEl: HTMLElement | null = null;\n let showTimer: ReturnType<typeof setTimeout> | null = null;\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n const clearShowTimer = (): void => {\n if (!showTimer) return;\n\n clearTimeout(showTimer);\n showTimer = null;\n };\n const clearHideTimer = (): void => {\n if (!hideTimer) return;\n\n clearTimeout(hideTimer);\n hideTimer = null;\n };\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) => bind({ aria: { describedby: () => tooltipId } }, { target: triggerEl }),\n defaultOpen: props['default-open'],\n disabled: isDisabled,\n getPanel: () => tooltipEl,\n offset: 8,\n onCleanup,\n onClose: (reason) => emit('open-change', { open: false, reason }),\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n onPlacementChange: (p) => {\n const side = p.split('-')[0] as TooltipPlacement;\n\n activePlacement.value = side;\n\n if (side === 'left' && tooltipEl) {\n tooltipEl.style.left = `${parseFloat(tooltipEl.style.left) - LEFT_GAP_COMPENSATION}px`;\n }\n },\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers: computed(() => [] as TooltipTrigger[]),\n });\n\n function show(reason: OverlayOpenReason = 'hover'): void {\n if (isControlled.value) return;\n\n if (isDisabled.value || (!props.content.value && !slots.has('content').value)) return;\n\n clearHideTimer();\n clearShowTimer();\n\n const delay = Number(props.delay.value) || 0;\n\n if (delay > 0) {\n showTimer = setTimeout(() => {\n showTimer = null;\n floating.open(reason);\n floating.updatePosition();\n }, delay);\n } else {\n floating.open(reason);\n floating.updatePosition();\n }\n }\n\n function hide(): void {\n if (isControlled.value) return;\n\n clearShowTimer();\n\n const closeDelay = Number(props['close-delay'].value) || 0;\n\n if (closeDelay > 0) {\n clearHideTimer();\n hideTimer = setTimeout(() => {\n hideTimer = null;\n floating.close('trigger');\n }, closeDelay);\n } else {\n floating.close('trigger');\n }\n }\n\n onMounted(() => {\n // Manually bind trigger events so we can wrap show/hide with delay timers.\n // useFloatingTrigger handles ARIA, positioning, controlled mode, and keyboard dismiss.\n const triggerSlot = shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n let eventCleanups: Array<() => void> = [];\n\n const addEvent = (target: EventTarget, event: string, handler: EventListener): void => {\n target.addEventListener(event, handler);\n eventCleanups.push(() => target.removeEventListener(event, handler));\n };\n\n const bindTriggerEvents = (): void => {\n for (const cleanup of eventCleanups) cleanup();\n eventCleanups = [];\n\n const triggerEl = triggerSlot?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) return;\n\n const t = triggers.value;\n\n if (t.includes('hover')) {\n addEvent(triggerEl, 'pointerenter', () => show('hover'));\n addEvent(triggerEl, 'pointerleave', hide);\n }\n\n if (t.includes('focus')) {\n addEvent(triggerEl, 'focusin', () => show('focus'));\n addEvent(triggerEl, 'focusout', hide);\n }\n\n if (t.includes('click')) {\n addEvent(triggerEl, 'click', () => (floating.visible.value ? hide() : show('click')));\n }\n };\n\n triggerSlot?.addEventListener('slotchange', bindTriggerEvents);\n bindTriggerEvents();\n\n const destroyFloating = floating.mount();\n\n return () => {\n triggerSlot?.removeEventListener('slotchange', bindTriggerEvents);\n for (const cleanup of eventCleanups) cleanup();\n clearShowTimer();\n clearHideTimer();\n destroyFloating();\n };\n });\n\n return html`\n <slot></slot>\n <div\n class=\"tooltip\"\n part=\"tooltip\"\n id=\"${tooltipId}\"\n role=\"tooltip\"\n popover=\"manual\"\n ref=${(ref: HTMLElement) => {\n tooltipEl = ref;\n }}\n data-placement=\"${activePlacement}\"\n aria-hidden=\"${() => String(!floating.visible.value)}\">\n <slot name=\"content\"><span class=\"tooltip-text\">${props.content}</span></slot>\n </div>\n `;\n },\n styles: [forcedColorsMixin, styles],\n});\n"],"mappings":"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"}
|
package/dist/tooltip.js
CHANGED
|
@@ -1,36 +1,37 @@
|
|
|
1
1
|
import { forcedColorsMixin as e } from "./styles/mixins/theme.css.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { parseStringTriggers as t } from "./core/parse.js";
|
|
3
|
+
import { disablableBundle as n, sizableBundle as r } from "./shared/prop-bundles.js";
|
|
4
4
|
import { useFloatingTrigger as i } from "./overlay/shared/use-floating-trigger.js";
|
|
5
5
|
import a from "./overlay/tooltip/tooltip.css.js";
|
|
6
|
-
import {
|
|
7
|
-
import { computed as
|
|
6
|
+
import { bind as o, createStableId as s, define as c, getHost as l, html as u, onCleanup as d, onMounted as f, prop as p, useEmit as m, useSlots as h } from "@vielzeug/ore";
|
|
7
|
+
import { computed as g, signal as _ } from "@vielzeug/ripple";
|
|
8
8
|
//#region src/overlay/tooltip/tooltip.ts
|
|
9
|
-
var
|
|
9
|
+
var v = 4, y = ["hover", "focus"], b = /* @__PURE__ */ new Set([
|
|
10
10
|
"click",
|
|
11
11
|
"focus",
|
|
12
12
|
"hover"
|
|
13
|
-
]),
|
|
13
|
+
]), x = (e) => {
|
|
14
14
|
if (e == null || e.trim() === "") return 0;
|
|
15
15
|
let t = Number(e);
|
|
16
16
|
return Number.isFinite(t) && t >= 0 ? t : 0;
|
|
17
|
-
},
|
|
18
|
-
c(
|
|
17
|
+
}, S = (e) => e == null ? void 0 : e === "" || e === "true", C = (e) => t(e, b, y), w = "ore-tooltip";
|
|
18
|
+
c(w, {
|
|
19
19
|
props: {
|
|
20
|
+
...r,
|
|
20
21
|
...n,
|
|
21
|
-
...t,
|
|
22
22
|
"close-delay": {
|
|
23
23
|
default: 0,
|
|
24
|
-
parse:
|
|
24
|
+
parse: x
|
|
25
25
|
},
|
|
26
26
|
content: p.string(),
|
|
27
|
+
"default-open": p.bool(!1),
|
|
27
28
|
delay: {
|
|
28
29
|
default: 0,
|
|
29
|
-
parse:
|
|
30
|
+
parse: x
|
|
30
31
|
},
|
|
31
32
|
open: {
|
|
32
33
|
default: void 0,
|
|
33
|
-
parse:
|
|
34
|
+
parse: S
|
|
34
35
|
},
|
|
35
36
|
placement: p.oneOf([
|
|
36
37
|
"top",
|
|
@@ -42,73 +43,82 @@ c(C, {
|
|
|
42
43
|
variant: p.string()
|
|
43
44
|
},
|
|
44
45
|
setup(e) {
|
|
45
|
-
let t = l(), n = m(), r = t.shadowRoot,
|
|
46
|
-
|
|
47
|
-
},
|
|
48
|
-
|
|
49
|
-
},
|
|
50
|
-
bindTriggerAria: (e) => o(
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
let t = l(), n = m(), r = h(), a = t.shadowRoot, c = g(() => !!e.disabled.value), p = g(() => e.open.value !== void 0), y = _("top"), b = s("tooltip"), x = g(() => C(e.trigger.value)), S = null, w = null, T = null, E = () => {
|
|
47
|
+
w &&= (clearTimeout(w), null);
|
|
48
|
+
}, D = () => {
|
|
49
|
+
T &&= (clearTimeout(T), null);
|
|
50
|
+
}, O = i({
|
|
51
|
+
bindTriggerAria: (e) => o({ aria: { describedby: () => b } }, { target: e }),
|
|
52
|
+
defaultOpen: e["default-open"],
|
|
53
|
+
disabled: c,
|
|
54
|
+
getPanel: () => S,
|
|
53
55
|
offset: 8,
|
|
54
56
|
onCleanup: d,
|
|
57
|
+
onClose: (e) => n("open-change", {
|
|
58
|
+
open: !1,
|
|
59
|
+
reason: e
|
|
60
|
+
}),
|
|
61
|
+
onOpen: (e) => n("open-change", {
|
|
62
|
+
open: !0,
|
|
63
|
+
reason: e
|
|
64
|
+
}),
|
|
55
65
|
onPlacementChange: (e) => {
|
|
56
66
|
let t = e.split("-")[0];
|
|
57
|
-
|
|
67
|
+
y.value = t, t === "left" && S && (S.style.left = `${parseFloat(S.style.left) - v}px`);
|
|
58
68
|
},
|
|
59
69
|
openProp: e.open,
|
|
60
|
-
placement:
|
|
61
|
-
slot: () =>
|
|
62
|
-
slotElements:
|
|
63
|
-
triggers:
|
|
70
|
+
placement: g(() => e.placement.value),
|
|
71
|
+
slot: () => a?.querySelector("slot:not([name])") ?? null,
|
|
72
|
+
slotElements: r.elements(),
|
|
73
|
+
triggers: g(() => [])
|
|
64
74
|
});
|
|
65
|
-
function
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
let
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
},
|
|
75
|
+
function k(t = "hover") {
|
|
76
|
+
if (p.value || c.value || !e.content.value && !r.has("content").value) return;
|
|
77
|
+
D(), E();
|
|
78
|
+
let n = Number(e.delay.value) || 0;
|
|
79
|
+
n > 0 ? w = setTimeout(() => {
|
|
80
|
+
w = null, O.open(t), O.updatePosition();
|
|
81
|
+
}, n) : (O.open(t), O.updatePosition());
|
|
72
82
|
}
|
|
73
|
-
function
|
|
74
|
-
if (
|
|
75
|
-
|
|
83
|
+
function A() {
|
|
84
|
+
if (p.value) return;
|
|
85
|
+
E();
|
|
76
86
|
let t = Number(e["close-delay"].value) || 0;
|
|
77
|
-
t > 0 ? (
|
|
78
|
-
|
|
79
|
-
}, t)) :
|
|
87
|
+
t > 0 ? (D(), T = setTimeout(() => {
|
|
88
|
+
T = null, O.close("trigger");
|
|
89
|
+
}, t)) : O.close("trigger");
|
|
80
90
|
}
|
|
81
91
|
return f(() => {
|
|
82
|
-
let e =
|
|
92
|
+
let e = a?.querySelector("slot:not([name])"), t = [], n = (e, n, r) => {
|
|
83
93
|
e.addEventListener(n, r), t.push(() => e.removeEventListener(n, r));
|
|
84
|
-
},
|
|
94
|
+
}, r = () => {
|
|
85
95
|
for (let e of t) e();
|
|
86
96
|
t = [];
|
|
87
97
|
let r = e?.assignedElements({ flatten: !0 })[0];
|
|
88
98
|
if (!r) return;
|
|
89
|
-
let i =
|
|
90
|
-
i.includes("hover") && (n(r, "pointerenter",
|
|
99
|
+
let i = x.value;
|
|
100
|
+
i.includes("hover") && (n(r, "pointerenter", () => k("hover")), n(r, "pointerleave", A)), i.includes("focus") && (n(r, "focusin", () => k("focus")), n(r, "focusout", A)), i.includes("click") && n(r, "click", () => O.visible.value ? A() : k("click"));
|
|
91
101
|
};
|
|
92
|
-
e?.addEventListener("slotchange",
|
|
93
|
-
let
|
|
102
|
+
e?.addEventListener("slotchange", r), r();
|
|
103
|
+
let i = O.mount();
|
|
94
104
|
return () => {
|
|
95
|
-
e?.removeEventListener("slotchange",
|
|
105
|
+
e?.removeEventListener("slotchange", r);
|
|
96
106
|
for (let e of t) e();
|
|
97
|
-
|
|
107
|
+
E(), D(), i();
|
|
98
108
|
};
|
|
99
109
|
}), u`
|
|
100
110
|
<slot></slot>
|
|
101
111
|
<div
|
|
102
112
|
class="tooltip"
|
|
103
113
|
part="tooltip"
|
|
104
|
-
id="${
|
|
114
|
+
id="${b}"
|
|
105
115
|
role="tooltip"
|
|
106
116
|
popover="manual"
|
|
107
117
|
ref=${(e) => {
|
|
108
|
-
|
|
118
|
+
S = e;
|
|
109
119
|
}}
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
data-placement="${y}"
|
|
121
|
+
aria-hidden="${() => String(!O.visible.value)}">
|
|
112
122
|
<slot name="content"><span class="tooltip-text">${e.content}</span></slot>
|
|
113
123
|
</div>
|
|
114
124
|
`;
|
|
@@ -116,6 +126,6 @@ c(C, {
|
|
|
116
126
|
styles: [e, a]
|
|
117
127
|
});
|
|
118
128
|
//#endregion
|
|
119
|
-
export {
|
|
129
|
+
export { w as TOOLTIP_TAG };
|
|
120
130
|
|
|
121
131
|
//# sourceMappingURL=tooltip.js.map
|
package/dist/tooltip.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tooltip.js","names":[],"sources":["../src/overlay/tooltip/tooltip.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport { createStableId, define, html, prop, aria, getHost, onCleanup, onMounted, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize } from '../../types';\n\nimport { parseStringTriggers } from '../../headless';\nimport { disablableBundle, sizableBundle } from '../../shared';\nimport { forcedColorsMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './tooltip.css?inline';\n\ntype TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\ntype TooltipTrigger = 'click' | 'focus' | 'hover';\n\nconst LEFT_GAP_COMPENSATION = 4;\nconst DEFAULT_TOOLTIP_TRIGGERS: TooltipTrigger[] = ['hover', 'focus'];\nconst VALID_TOOLTIP_TRIGGERS = new Set<TooltipTrigger>(['click', 'focus', 'hover']);\n\nconst parseDelayMs = (value: string | null): number => {\n if (value == null || value.trim() === '') return 0;\n\n const parsed = Number(value);\n\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;\n};\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: string | null | undefined): TooltipTrigger[] =>\n parseStringTriggers(value, VALID_TOOLTIP_TRIGGERS, DEFAULT_TOOLTIP_TRIGGERS);\n\n/** Tooltip component properties */\nexport type OreTooltipProps = {\n /** Hide delay in ms */\n 'close-delay'?: number;\n /** Tooltip text content */\n content?: string;\n /** Show delay in ms */\n delay?: number;\n /** Disable the tooltip */\n disabled?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to trigger */\n placement?: TooltipPlacement;\n /** Tooltip size */\n size?: ComponentSize;\n /** Which trigger(s) show/hide the tooltip */\n trigger?: string;\n /** Visual variant */\n variant?: 'dark' | 'light';\n};\n\n/**\n * A lightweight tooltip shown on hover/focus/click relative to the slotted trigger.\n *\n * @element ore-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} placement - 'top' | 'bottom' | 'left' | 'right' (default: 'top')\n * @attr {string} trigger - 'hover' | 'focus' | 'click' or comma-separated combination\n * @attr {number} delay - Show delay in milliseconds (default: 0)\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - 'dark' (default) | 'light'\n * @attr {boolean} disabled - Disable the tooltip\n *\n * @slot - Trigger element that the tooltip is anchored to\n * @slot content - Complex tooltip content (overrides the `content` attribute)\n *\n * @cssprop --tooltip-max-width - Max width of the tooltip bubble\n *\n * @part tooltip - Tooltip container.\n * @example\n * ```html\n * <!-- Simple text tooltip -->\n * <ore-tooltip content=\"Copy to clipboard\">\n * <button>Copy</button>\n * </ore-tooltip>\n *\n * <!-- Placement and delay -->\n * <ore-tooltip content=\"Save your work\" placement=\"right\" delay=\"300\">\n * <ore-icon name=\"save\"></ore-icon>\n * </ore-tooltip>\n *\n * <!-- Hover + focus trigger -->\n * <ore-tooltip content=\"Required field\" trigger=\"hover,focus\" placement=\"top\">\n * <ore-input label=\"Email\" type=\"email\"></ore-input>\n * </ore-tooltip>\n *\n * <!-- Rich content slot -->\n * <ore-tooltip>\n * <ore-button>Help</ore-button>\n * <div slot=\"content\">\n * <strong>Keyboard shortcuts</strong>\n * <p>Press Ctrl+S to save.</p>\n * </div>\n * </ore-tooltip>\n * ```\n */\nexport const TOOLTIP_TAG = 'ore-tooltip' as const;\ndefine<OreTooltipProps>(TOOLTIP_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'close-delay': { default: 0, parse: parseDelayMs },\n content: prop.string(),\n delay: { default: 0, parse: parseDelayMs },\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(['top', 'bottom', 'left', 'right'] as const, 'top'),\n trigger: prop.string('hover,focus'),\n variant: prop.string<'dark' | 'light'>(),\n },\n setup(props) {\n const el = getHost();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const isControlled = computed(() => props.open.value !== undefined);\n const activePlacement = signal<TooltipPlacement>('top');\n const tooltipId = createStableId('tooltip');\n const triggers = computed<TooltipTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let tooltipEl: HTMLElement | null = null;\n let showTimer: ReturnType<typeof setTimeout> | null = null;\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n const clearShowTimer = (): void => {\n if (!showTimer) return;\n\n clearTimeout(showTimer);\n showTimer = null;\n };\n const clearHideTimer = (): void => {\n if (!hideTimer) return;\n\n clearTimeout(hideTimer);\n hideTimer = null;\n };\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) => aria(triggerEl, { describedby: () => tooltipId }),\n disabled: isDisabled,\n getPanel: () => tooltipEl,\n offset: 8,\n onCleanup,\n onPlacementChange: (p) => {\n const side = p.split('-')[0] as TooltipPlacement;\n\n activePlacement.value = side;\n\n if (side === 'left' && tooltipEl) {\n tooltipEl.style.left = `${parseFloat(tooltipEl.style.left) - LEFT_GAP_COMPENSATION}px`;\n }\n },\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers: computed(() => [] as TooltipTrigger[]),\n });\n\n function show(): void {\n if (isControlled.value) return;\n\n if (isDisabled.value || (!props.content.value && !slots.has('content').value)) return;\n\n clearHideTimer();\n clearShowTimer();\n\n const delay = Number(props.delay.value) || 0;\n\n if (delay > 0) {\n showTimer = setTimeout(() => {\n showTimer = null;\n floating.open('hover');\n floating.updatePosition();\n }, delay);\n } else {\n floating.open('hover');\n floating.updatePosition();\n }\n }\n\n function hide(): void {\n if (isControlled.value) return;\n\n clearShowTimer();\n\n const closeDelay = Number(props['close-delay'].value) || 0;\n\n if (closeDelay > 0) {\n clearHideTimer();\n hideTimer = setTimeout(() => {\n hideTimer = null;\n floating.close('trigger');\n }, closeDelay);\n } else {\n floating.close('trigger');\n }\n }\n\n onMounted(() => {\n // Manually bind trigger events so we can wrap show/hide with delay timers.\n // useFloatingTrigger handles ARIA, positioning, controlled mode, and keyboard dismiss.\n const triggerSlot = shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n let eventCleanups: Array<() => void> = [];\n\n const addEvent = (target: EventTarget, event: string, handler: EventListener): void => {\n target.addEventListener(event, handler);\n eventCleanups.push(() => target.removeEventListener(event, handler));\n };\n\n const bindTriggerEvents = (): void => {\n for (const cleanup of eventCleanups) cleanup();\n eventCleanups = [];\n\n const triggerEl = triggerSlot?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) return;\n\n const t = triggers.value;\n\n if (t.includes('hover')) {\n addEvent(triggerEl, 'pointerenter', show);\n addEvent(triggerEl, 'pointerleave', hide);\n }\n\n if (t.includes('focus')) {\n addEvent(triggerEl, 'focusin', show);\n addEvent(triggerEl, 'focusout', hide);\n }\n\n if (t.includes('click')) {\n addEvent(triggerEl, 'click', () => (floating.visible.value ? hide() : show()));\n }\n };\n\n triggerSlot?.addEventListener('slotchange', bindTriggerEvents);\n bindTriggerEvents();\n\n const destroyFloating = floating.mount();\n\n return () => {\n triggerSlot?.removeEventListener('slotchange', bindTriggerEvents);\n for (const cleanup of eventCleanups) cleanup();\n clearShowTimer();\n clearHideTimer();\n destroyFloating();\n };\n });\n\n return html`\n <slot></slot>\n <div\n class=\"tooltip\"\n part=\"tooltip\"\n id=\"${tooltipId}\"\n role=\"tooltip\"\n popover=\"manual\"\n ref=${(ref: HTMLElement) => {\n tooltipEl = ref;\n }}\n :data-placement=\"${activePlacement}\"\n :aria-hidden=\"${() => String(!floating.visible.value)}\">\n <slot name=\"content\"><span class=\"tooltip-text\">${props.content}</span></slot>\n </div>\n `;\n },\n styles: [forcedColorsMixin, styles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tooltip.js","names":[],"sources":["../src/overlay/tooltip/tooltip.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport {\n createStableId,\n define,\n html,\n prop,\n bind,\n getHost,\n onCleanup,\n onMounted,\n useEmit,\n useSlots,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\n\nimport type { ComponentSize } from '../../types';\n\nimport { type OverlayOpenChangeDetail, type OverlayOpenReason, parseStringTriggers } from '../../core';\nimport { disablableBundle, sizableBundle } from '../../shared';\nimport { forcedColorsMixin } from '../../styles';\nimport { useFloatingTrigger } from '../shared/use-floating-trigger';\nimport styles from './tooltip.css?inline';\n\ntype TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';\ntype TooltipTrigger = 'click' | 'focus' | 'hover';\n\nconst LEFT_GAP_COMPENSATION = 4;\nconst DEFAULT_TOOLTIP_TRIGGERS: TooltipTrigger[] = ['hover', 'focus'];\nconst VALID_TOOLTIP_TRIGGERS = new Set<TooltipTrigger>(['click', 'focus', 'hover']);\n\nconst parseDelayMs = (value: string | null): number => {\n if (value == null || value.trim() === '') return 0;\n\n const parsed = Number(value);\n\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;\n};\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\nconst normalizeTriggers = (value: string | null | undefined): TooltipTrigger[] =>\n parseStringTriggers(value, VALID_TOOLTIP_TRIGGERS, DEFAULT_TOOLTIP_TRIGGERS);\n\n/** Tooltip component properties */\nexport type OreTooltipEvents = {\n 'open-change': OverlayOpenChangeDetail;\n};\n\nexport type OreTooltipProps = {\n /** Hide delay in ms */\n 'close-delay'?: number;\n /** Tooltip text content */\n content?: string;\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n /** Show delay in ms */\n delay?: number;\n /** Disable the tooltip */\n disabled?: boolean;\n /** Controlled open state */\n open?: boolean;\n /** Preferred placement relative to trigger */\n placement?: TooltipPlacement;\n /** Tooltip size */\n size?: ComponentSize;\n /** Which trigger(s) show/hide the tooltip */\n trigger?: string;\n /** Visual variant */\n variant?: 'dark' | 'light';\n};\n\n/**\n * A lightweight tooltip shown on hover/focus/click relative to the slotted trigger.\n *\n * @element ore-tooltip\n *\n * @attr {string} content - Tooltip text content\n * @attr {string} placement - 'top' | 'bottom' | 'left' | 'right' (default: 'top')\n * @attr {string} trigger - 'hover' | 'focus' | 'click' or comma-separated combination\n * @attr {number} delay - Show delay in milliseconds (default: 0)\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n * @attr {string} variant - 'dark' (default) | 'light'\n * @attr {boolean} disabled - Disable the tooltip\n *\n * @slot - Trigger element that the tooltip is anchored to\n * @slot content - Complex tooltip content (overrides the `content` attribute)\n * @fires open-change - Fired when the tooltip state changes. detail: { open, reason }\n *\n * @cssprop --tooltip-max-width - Max width of the tooltip bubble\n *\n * @part tooltip - Tooltip container.\n * @example\n * ```html\n * <!-- Simple text tooltip -->\n * <ore-tooltip content=\"Copy to clipboard\">\n * <button>Copy</button>\n * </ore-tooltip>\n *\n * <!-- Placement and delay -->\n * <ore-tooltip content=\"Save your work\" placement=\"right\" delay=\"300\">\n * <ore-icon name=\"save\"></ore-icon>\n * </ore-tooltip>\n *\n * <!-- Hover + focus trigger -->\n * <ore-tooltip content=\"Required field\" trigger=\"hover,focus\" placement=\"top\">\n * <ore-input label=\"Email\" type=\"email\"></ore-input>\n * </ore-tooltip>\n *\n * <!-- Rich content slot -->\n * <ore-tooltip>\n * <ore-button>Help</ore-button>\n * <div slot=\"content\">\n * <strong>Keyboard shortcuts</strong>\n * <p>Press Ctrl+S to save.</p>\n * </div>\n * </ore-tooltip>\n * ```\n */\nexport const TOOLTIP_TAG = 'ore-tooltip' as const;\ndefine<OreTooltipProps>(TOOLTIP_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'close-delay': { default: 0, parse: parseDelayMs },\n content: prop.string(),\n 'default-open': prop.bool(false),\n delay: { default: 0, parse: parseDelayMs },\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(['top', 'bottom', 'left', 'right'] as const, 'top'),\n trigger: prop.string('hover,focus'),\n variant: prop.string<'dark' | 'light'>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreTooltipEvents>();\n const slots = useSlots();\n\n const shadowRoot = el.shadowRoot;\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const isControlled = computed(() => props.open.value !== undefined);\n const activePlacement = signal<TooltipPlacement>('top');\n const tooltipId = createStableId('tooltip');\n const triggers = computed<TooltipTrigger[]>(() => normalizeTriggers(props.trigger.value));\n let tooltipEl: HTMLElement | null = null;\n let showTimer: ReturnType<typeof setTimeout> | null = null;\n let hideTimer: ReturnType<typeof setTimeout> | null = null;\n\n const clearShowTimer = (): void => {\n if (!showTimer) return;\n\n clearTimeout(showTimer);\n showTimer = null;\n };\n const clearHideTimer = (): void => {\n if (!hideTimer) return;\n\n clearTimeout(hideTimer);\n hideTimer = null;\n };\n\n const floating = useFloatingTrigger({\n bindTriggerAria: (triggerEl) => bind({ aria: { describedby: () => tooltipId } }, { target: triggerEl }),\n defaultOpen: props['default-open'],\n disabled: isDisabled,\n getPanel: () => tooltipEl,\n offset: 8,\n onCleanup,\n onClose: (reason) => emit('open-change', { open: false, reason }),\n onOpen: (reason) => emit('open-change', { open: true, reason }),\n onPlacementChange: (p) => {\n const side = p.split('-')[0] as TooltipPlacement;\n\n activePlacement.value = side;\n\n if (side === 'left' && tooltipEl) {\n tooltipEl.style.left = `${parseFloat(tooltipEl.style.left) - LEFT_GAP_COMPENSATION}px`;\n }\n },\n openProp: props.open as typeof props.open & { value: boolean | undefined },\n placement: computed(() => props.placement.value as Placement),\n slot: () => shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])') ?? null,\n slotElements: slots.elements(),\n triggers: computed(() => [] as TooltipTrigger[]),\n });\n\n function show(reason: OverlayOpenReason = 'hover'): void {\n if (isControlled.value) return;\n\n if (isDisabled.value || (!props.content.value && !slots.has('content').value)) return;\n\n clearHideTimer();\n clearShowTimer();\n\n const delay = Number(props.delay.value) || 0;\n\n if (delay > 0) {\n showTimer = setTimeout(() => {\n showTimer = null;\n floating.open(reason);\n floating.updatePosition();\n }, delay);\n } else {\n floating.open(reason);\n floating.updatePosition();\n }\n }\n\n function hide(): void {\n if (isControlled.value) return;\n\n clearShowTimer();\n\n const closeDelay = Number(props['close-delay'].value) || 0;\n\n if (closeDelay > 0) {\n clearHideTimer();\n hideTimer = setTimeout(() => {\n hideTimer = null;\n floating.close('trigger');\n }, closeDelay);\n } else {\n floating.close('trigger');\n }\n }\n\n onMounted(() => {\n // Manually bind trigger events so we can wrap show/hide with delay timers.\n // useFloatingTrigger handles ARIA, positioning, controlled mode, and keyboard dismiss.\n const triggerSlot = shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n let eventCleanups: Array<() => void> = [];\n\n const addEvent = (target: EventTarget, event: string, handler: EventListener): void => {\n target.addEventListener(event, handler);\n eventCleanups.push(() => target.removeEventListener(event, handler));\n };\n\n const bindTriggerEvents = (): void => {\n for (const cleanup of eventCleanups) cleanup();\n eventCleanups = [];\n\n const triggerEl = triggerSlot?.assignedElements({ flatten: true })[0] as HTMLElement | undefined;\n\n if (!triggerEl) return;\n\n const t = triggers.value;\n\n if (t.includes('hover')) {\n addEvent(triggerEl, 'pointerenter', () => show('hover'));\n addEvent(triggerEl, 'pointerleave', hide);\n }\n\n if (t.includes('focus')) {\n addEvent(triggerEl, 'focusin', () => show('focus'));\n addEvent(triggerEl, 'focusout', hide);\n }\n\n if (t.includes('click')) {\n addEvent(triggerEl, 'click', () => (floating.visible.value ? hide() : show('click')));\n }\n };\n\n triggerSlot?.addEventListener('slotchange', bindTriggerEvents);\n bindTriggerEvents();\n\n const destroyFloating = floating.mount();\n\n return () => {\n triggerSlot?.removeEventListener('slotchange', bindTriggerEvents);\n for (const cleanup of eventCleanups) cleanup();\n clearShowTimer();\n clearHideTimer();\n destroyFloating();\n };\n });\n\n return html`\n <slot></slot>\n <div\n class=\"tooltip\"\n part=\"tooltip\"\n id=\"${tooltipId}\"\n role=\"tooltip\"\n popover=\"manual\"\n ref=${(ref: HTMLElement) => {\n tooltipEl = ref;\n }}\n data-placement=\"${activePlacement}\"\n aria-hidden=\"${() => String(!floating.visible.value)}\">\n <slot name=\"content\"><span class=\"tooltip-text\">${props.content}</span></slot>\n </div>\n `;\n },\n styles: [forcedColorsMixin, styles],\n});\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/shape.css.cjs"),n=require("./styles/mixins/theme.css.cjs"),r=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/accessibility.css.cjs"),t=require("./styles/mixins/shape.css.cjs"),n=require("./styles/mixins/theme.css.cjs"),r=require("./core/announcer.cjs"),i=require("./shared/prop-bundles.cjs"),a=require("./feedback/typing-indicator/typing-indicator.css.cjs");let o=require("@vielzeug/ore"),s=require("@vielzeug/ripple/watch");var c=`ore-typing-indicator`;(0,o.define)(c,{props:{...i.themableBundle,...i.sizableBundle,label:o.prop.string(`Typing…`)},setup(e){return(0,s.watch)(()=>e.label.value,e=>r.announce(e??``),{immediate:!0}),o.html`
|
|
2
2
|
<span class="dots" part="dots" aria-hidden="true">
|
|
3
3
|
<span class="dot" part="dot"></span>
|
|
4
4
|
<span class="dot" part="dot"></span>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typing-indicator.cjs","names":[],"sources":["../src/feedback/typing-indicator/typing-indicator.ts"],"sourcesContent":["import { define, html, prop } from '@vielzeug/ore';\nimport { watch } from '@vielzeug/ripple';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { announce } from '../../
|
|
1
|
+
{"version":3,"file":"typing-indicator.cjs","names":[],"sources":["../src/feedback/typing-indicator/typing-indicator.ts"],"sourcesContent":["import { define, html, prop } from '@vielzeug/ore';\nimport { watch } from '@vielzeug/ripple/watch';\n\nimport type { ComponentSize, ThemeColor } from '../../types';\n\nimport { announce } from '../../core';\nimport { sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, reducedMotionMixin, sizeVariantMixin } from '../../styles';\nimport componentStyles from './typing-indicator.css?inline';\n\n/** Typing indicator component properties */\nexport type OreTypingIndicatorProps = {\n /** Theme color for the dots */\n color?: ThemeColor;\n /** Accessible label announced once via a polite live region (default: `\"Typing…\"`) */\n label?: string;\n /** Dot size preset */\n size?: ComponentSize;\n};\n\n/**\n * Three bouncing dots signaling that the other side of a conversation is composing a reply —\n * the moment before any content exists. For a message whose content is already streaming in,\n * use `ore-chat-message`'s `streaming` attribute (a blinking cursor) instead.\n *\n * The dots are decorative (`aria-hidden`) — `label` is the entire accessibility contract,\n * announced through the shared singleton live region (`core/announcer.ts`) rather than a\n * static `aria-live` element in the template. A live region populated in the same paint as\n * its own insertion is unreliable across browsers/screen readers; routing through the shared\n * announcer (pre-existing region, clear-then-set) is the same pattern already used for other\n * transient status messages across this package.\n *\n * @element ore-typing-indicator\n *\n * @attr {string} label - Accessible label announced once via a polite live region (default: \"Typing…\")\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n *\n * @cssprop --typing-indicator-color - Dot color\n * @cssprop --typing-indicator-size - Dot diameter\n * @cssprop --typing-indicator-gap - Gap between dots\n *\n * @part dots - Dots container.\n * @part dot - Individual dot element.\n * @example\n * ```html\n * <ore-typing-indicator></ore-typing-indicator>\n * <ore-typing-indicator label=\"Assistant is typing…\" color=\"primary\"></ore-typing-indicator>\n * ```\n */\nexport const TYPING_INDICATOR_TAG = 'ore-typing-indicator' as const;\ndefine<OreTypingIndicatorProps>(TYPING_INDICATOR_TAG, {\n props: {\n ...themableBundle,\n ...sizableBundle,\n label: prop.string('Typing…'),\n },\n setup(props) {\n watch(\n () => props.label.value,\n (label) => announce(label ?? ''),\n { immediate: true },\n );\n\n return html`\n <span class=\"dots\" part=\"dots\" aria-hidden=\"true\">\n <span class=\"dot\" part=\"dot\"></span>\n <span class=\"dot\" part=\"dot\"></span>\n <span class=\"dot\" part=\"dot\"></span>\n </span>\n `;\n },\n styles: [\n colorThemeMixin,\n reducedMotionMixin,\n sizeVariantMixin({\n lg: {\n gap: 'var(--typing-indicator-gap, var(--size-1-5))',\n size: 'var(--typing-indicator-size, var(--size-2-5))',\n },\n md: { gap: 'var(--typing-indicator-gap, var(--size-1))', size: 'var(--typing-indicator-size, var(--size-2))' },\n sm: {\n gap: 'var(--typing-indicator-gap, var(--size-1))',\n size: 'var(--typing-indicator-size, var(--size-1-5))',\n },\n }),\n componentStyles,\n ],\n});\n"],"mappings":"gaAkDA,IAAa,EAAuB,wBACpC,EAAA,EAAA,OAAA,CAAgC,EAAsB,CACpD,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,cACH,MAAO,EAAA,KAAK,OAAO,SAAS,CAC9B,EACA,MAAM,EAAO,CAOX,OANA,EAAA,EAAA,MAAA,KACQ,EAAM,MAAM,MACjB,GAAU,EAAA,SAAS,GAAS,EAAE,EAC/B,CAAE,UAAW,EAAK,CACpB,EAEO,EAAA,IAAI;;;;;;KAOb,EACA,OAAQ,CACN,EAAA,gBACA,EAAA,mBACA,EAAA,iBAAiB,CACf,GAAI,CACF,IAAK,+CACL,KAAM,+CACR,EACA,GAAI,CAAE,IAAK,6CAA8C,KAAM,6CAA8C,EAC7G,GAAI,CACF,IAAK,6CACL,KAAM,+CACR,CACF,CAAC,EACD,EAAA,OACF,CACF,CAAC"}
|
package/dist/typing-indicator.js
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { reducedMotionMixin as e } from "./styles/mixins/accessibility.css.js";
|
|
2
2
|
import { sizeVariantMixin as t } from "./styles/mixins/shape.css.js";
|
|
3
3
|
import { colorThemeMixin as n } from "./styles/mixins/theme.css.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { announce as r } from "./core/announcer.js";
|
|
5
|
+
import { sizableBundle as i, themableBundle as a } from "./shared/prop-bundles.js";
|
|
6
6
|
import o from "./feedback/typing-indicator/typing-indicator.css.js";
|
|
7
7
|
import { define as s, html as c, prop as l } from "@vielzeug/ore";
|
|
8
|
-
import { watch as u } from "@vielzeug/ripple";
|
|
8
|
+
import { watch as u } from "@vielzeug/ripple/watch";
|
|
9
9
|
//#region src/feedback/typing-indicator/typing-indicator.ts
|
|
10
10
|
var d = "ore-typing-indicator";
|
|
11
11
|
s(d, {
|
|
12
12
|
props: {
|
|
13
|
+
...a,
|
|
13
14
|
...i,
|
|
14
|
-
...r,
|
|
15
15
|
label: l.string("Typing…")
|
|
16
16
|
},
|
|
17
17
|
setup(e) {
|
|
18
|
-
return u(() => e.label.value, (e) =>
|
|
18
|
+
return u(() => e.label.value, (e) => r(e ?? ""), { immediate: !0 }), c`
|
|
19
19
|
<span class="dots" part="dots" aria-hidden="true">
|
|
20
20
|
<span class="dot" part="dot"></span>
|
|
21
21
|
<span class="dot" part="dot"></span>
|