@vielzeug/refine 2.1.0 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion-item.cjs +1 -1
- package/dist/accordion-item.cjs.map +1 -1
- package/dist/accordion-item.js +1 -1
- package/dist/accordion-item.js.map +1 -1
- package/dist/accordion.cjs +1 -1
- package/dist/accordion.cjs.map +1 -1
- package/dist/accordion.js +1 -1
- package/dist/accordion.js.map +1 -1
- package/dist/alert.cjs.map +1 -1
- package/dist/alert.js.map +1 -1
- package/dist/async.cjs.map +1 -1
- package/dist/async.js.map +1 -1
- package/dist/avatar-group.cjs.map +1 -1
- package/dist/avatar-group.js.map +1 -1
- package/dist/avatar.cjs +6 -6
- package/dist/avatar.cjs.map +1 -1
- package/dist/avatar.js +1 -2
- package/dist/avatar.js.map +1 -1
- package/dist/badge.cjs.map +1 -1
- package/dist/badge.js.map +1 -1
- package/dist/box.cjs.map +1 -1
- package/dist/box.js.map +1 -1
- package/dist/breadcrumb.cjs +3 -3
- 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 +1 -1
- package/dist/button-group.cjs.map +1 -1
- package/dist/button-group.js +0 -1
- package/dist/button-group.js.map +1 -1
- package/dist/button.cjs.map +1 -1
- package/dist/button.js.map +1 -1
- package/dist/calendar.cjs.map +1 -1
- package/dist/calendar.js.map +1 -1
- package/dist/card.cjs +7 -7
- package/dist/card.cjs.map +1 -1
- package/dist/card.js +27 -27
- package/dist/card.js.map +1 -1
- package/dist/carousel.cjs +20 -20
- package/dist/carousel.cjs.map +1 -1
- package/dist/carousel.js +7 -8
- package/dist/carousel.js.map +1 -1
- package/dist/chat-message.cjs +10 -10
- package/dist/chat-message.cjs.map +1 -1
- package/dist/chat-message.js +1 -2
- package/dist/chat-message.js.map +1 -1
- package/dist/checkbox-group.cjs +7 -7
- package/dist/checkbox-group.cjs.map +1 -1
- package/dist/checkbox-group.js +26 -26
- package/dist/checkbox-group.js.map +1 -1
- package/dist/checkbox.cjs +2 -2
- package/dist/checkbox.cjs.map +1 -1
- package/dist/checkbox.js +33 -33
- package/dist/checkbox.js.map +1 -1
- package/dist/chip.cjs +16 -16
- package/dist/chip.cjs.map +1 -1
- package/dist/chip.js +1 -2
- package/dist/chip.js.map +1 -1
- package/dist/combobox.cjs +28 -28
- package/dist/combobox.cjs.map +1 -1
- package/dist/combobox.js +211 -211
- package/dist/combobox.js.map +1 -1
- package/dist/command-palette.cjs +21 -21
- package/dist/command-palette.cjs.map +1 -1
- package/dist/command-palette.js +27 -28
- package/dist/command-palette.js.map +1 -1
- package/dist/content/avatar/avatar.css.cjs +1 -1
- package/dist/content/avatar/avatar.css.js +1 -1
- package/dist/content/avatar/avatar.d.ts.map +1 -1
- package/dist/content/breadcrumb/breadcrumb.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.map +1 -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.map +1 -1
- package/dist/content/carousel/index.d.ts +1 -1
- package/dist/content/carousel/index.d.ts.map +1 -1
- package/dist/content/chat-message/chat-message.css.cjs +1 -1
- package/dist/content/chat-message/chat-message.css.js +1 -1
- package/dist/content/chat-message/chat-message.d.ts.map +1 -1
- package/dist/content/code-window/code-window.css.cjs +1 -1
- package/dist/content/code-window/code-window.css.js +1 -1
- package/dist/content/copy-command/copy-command.css.cjs +1 -1
- package/dist/content/copy-command/copy-command.css.js +1 -1
- package/dist/content/copy-command/copy-command.d.ts.map +1 -1
- package/dist/content/index.d.ts +22 -22
- package/dist/content/index.d.ts.map +1 -1
- package/dist/content/list/_list-item-reveal.cjs.map +1 -1
- package/dist/content/list/_list-item-reveal.d.ts +1 -1
- package/dist/content/list/_list-item-reveal.d.ts.map +1 -1
- package/dist/content/list/_list-item-reveal.js.map +1 -1
- package/dist/content/list/list-item.css.cjs +1 -1
- package/dist/content/list/list-item.css.cjs.map +1 -1
- package/dist/content/list/list-item.css.js +1 -1
- package/dist/content/list/list-item.css.js.map +1 -1
- package/dist/content/list/list.d.ts.map +1 -1
- package/dist/content/marquee/marquee.css.cjs +1 -1
- package/dist/content/marquee/marquee.css.js +1 -1
- package/dist/content/pagination/pagination.css.cjs +1 -1
- package/dist/content/pagination/pagination.css.js +1 -1
- package/dist/content/pagination/pagination.d.ts.map +1 -1
- package/dist/content/separator/separator.css.cjs +1 -1
- package/dist/content/separator/separator.css.js +1 -1
- package/dist/content/separator/separator.d.ts.map +1 -1
- package/dist/content/stepper/step.css.cjs.map +1 -1
- package/dist/content/stepper/step.css.js.map +1 -1
- package/dist/content/stepper/stepper.d.ts.map +1 -1
- package/dist/content/table/table.css.cjs +1 -1
- package/dist/content/table/table.css.js +1 -1
- package/dist/content/text/text.css.cjs +1 -1
- package/dist/content/text/text.css.js +1 -1
- package/dist/copy-command.cjs.map +1 -1
- package/dist/copy-command.js.map +1 -1
- package/dist/core/checkable.cjs +1 -1
- package/dist/core/checkable.cjs.map +1 -1
- package/dist/core/checkable.d.ts.map +1 -1
- package/dist/core/checkable.js +4 -4
- package/dist/core/checkable.js.map +1 -1
- package/dist/core/choice-field.cjs +1 -1
- package/dist/core/choice-field.cjs.map +1 -1
- package/dist/core/choice-field.d.ts.map +1 -1
- package/dist/core/choice-field.js +1 -2
- package/dist/core/choice-field.js.map +1 -1
- package/dist/core/date-picker.cjs +1 -1
- package/dist/core/date-picker.cjs.map +1 -1
- package/dist/core/date-picker.d.ts.map +1 -1
- package/dist/core/date-picker.js +3 -3
- package/dist/core/date-picker.js.map +1 -1
- package/dist/core/index.d.ts +17 -17
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/option-list.cjs +1 -1
- package/dist/core/option-list.cjs.map +1 -1
- package/dist/core/option-list.d.ts.map +1 -1
- package/dist/core/option-list.js +4 -4
- package/dist/core/option-list.js.map +1 -1
- package/dist/core/ref-callback.cjs +1 -1
- package/dist/core/ref-callback.cjs.map +1 -1
- package/dist/core/ref-callback.d.ts.map +1 -1
- package/dist/core/ref-callback.js +1 -1
- package/dist/core/ref-callback.js.map +1 -1
- package/dist/core/signals.cjs +1 -1
- package/dist/core/signals.cjs.map +1 -1
- package/dist/core/signals.d.ts.map +1 -1
- package/dist/core/signals.js +1 -2
- package/dist/core/signals.js.map +1 -1
- package/dist/core/slider.cjs.map +1 -1
- package/dist/core/slider.d.ts.map +1 -1
- package/dist/core/slider.js.map +1 -1
- package/dist/core/spinner.cjs.map +1 -1
- package/dist/core/spinner.d.ts.map +1 -1
- package/dist/core/spinner.js.map +1 -1
- package/dist/core/text-field.cjs +1 -1
- package/dist/core/text-field.cjs.map +1 -1
- package/dist/core/text-field.js +1 -1
- package/dist/core/text-field.js.map +1 -1
- package/dist/custom-elements.json +4253 -4253
- package/dist/datagrid.cjs +114 -114
- package/dist/datagrid.cjs.map +1 -1
- package/dist/datagrid.js +42 -43
- package/dist/datagrid.js.map +1 -1
- package/dist/date-picker.cjs.map +1 -1
- package/dist/date-picker.js.map +1 -1
- package/dist/dialog.cjs.map +1 -1
- package/dist/dialog.js.map +1 -1
- package/dist/disclosure/accordion/accordion.d.ts.map +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.cjs +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.cjs.map +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.js +1 -1
- package/dist/disclosure/accordion-item/accordion-item.css.js.map +1 -1
- package/dist/disclosure/index.d.ts +6 -6
- package/dist/disclosure/index.d.ts.map +1 -1
- package/dist/disclosure/tab-item/tab-item.css.cjs.map +1 -1
- package/dist/disclosure/tab-item/tab-item.css.js.map +1 -1
- package/dist/disclosure/tab-item/tab-item.d.ts.map +1 -1
- package/dist/disclosure/tabs/tabs.css.cjs +1 -1
- package/dist/disclosure/tabs/tabs.css.cjs.map +1 -1
- package/dist/disclosure/tabs/tabs.css.js +1 -1
- package/dist/disclosure/tabs/tabs.css.js.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 +26 -26
- package/dist/drawer.js.map +1 -1
- package/dist/feedback/alert/alert.css.cjs +1 -1
- package/dist/feedback/alert/alert.css.js +1 -1
- package/dist/feedback/async/async.d.ts +1 -1
- package/dist/feedback/async/async.d.ts.map +1 -1
- package/dist/feedback/badge/badge.css.cjs +1 -1
- package/dist/feedback/badge/badge.css.js +1 -1
- package/dist/feedback/badge/badge.d.ts.map +1 -1
- package/dist/feedback/chip/chip.css.cjs.map +1 -1
- package/dist/feedback/chip/chip.css.js.map +1 -1
- package/dist/feedback/chip/chip.d.ts.map +1 -1
- package/dist/feedback/index.d.ts +12 -12
- package/dist/feedback/index.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.css.cjs +1 -1
- package/dist/feedback/toast/toast.css.cjs.map +1 -1
- package/dist/feedback/toast/toast.css.js +1 -1
- package/dist/feedback/toast/toast.css.js.map +1 -1
- package/dist/feedback/toast/toast.d.ts +1 -1
- package/dist/feedback/toast/toast.d.ts.map +1 -1
- package/dist/feedback/typing-indicator/typing-indicator.d.ts.map +1 -1
- package/dist/file-input.cjs +67 -67
- package/dist/file-input.cjs.map +1 -1
- package/dist/file-input.js +129 -130
- package/dist/file-input.js.map +1 -1
- package/dist/grid.cjs.map +1 -1
- package/dist/grid.js.map +1 -1
- package/dist/icon.cjs.map +1 -1
- package/dist/icon.js.map +1 -1
- package/dist/input.cjs +21 -21
- package/dist/input.cjs.map +1 -1
- package/dist/input.js +58 -58
- package/dist/input.js.map +1 -1
- package/dist/inputs/button/button.css.cjs +1 -1
- package/dist/inputs/button/button.css.js +1 -1
- package/dist/inputs/button/button.d.ts.map +1 -1
- package/dist/inputs/button-group/button-group.css.cjs.map +1 -1
- package/dist/inputs/button-group/button-group.css.js.map +1 -1
- package/dist/inputs/button-group/button-group.d.ts +1 -1
- package/dist/inputs/button-group/button-group.d.ts.map +1 -1
- package/dist/inputs/calendar/calendar.css.cjs +1 -1
- package/dist/inputs/calendar/calendar.css.cjs.map +1 -1
- package/dist/inputs/calendar/calendar.css.js +1 -1
- package/dist/inputs/calendar/calendar.css.js.map +1 -1
- package/dist/inputs/calendar/calendar.d.ts.map +1 -1
- package/dist/inputs/checkbox/checkbox.css.cjs +1 -1
- package/dist/inputs/checkbox/checkbox.css.js +1 -1
- 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.css.cjs +1 -1
- package/dist/inputs/combobox/combobox.css.js +1 -1
- package/dist/inputs/combobox/combobox.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-column.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid-column.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-column.js.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs +1 -1
- package/dist/inputs/datagrid/datagrid-model.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.d.ts.map +1 -1
- package/dist/inputs/datagrid/datagrid-model.js +1 -2
- package/dist/inputs/datagrid/datagrid-model.js.map +1 -1
- package/dist/inputs/datagrid/datagrid.css.cjs +1 -1
- package/dist/inputs/datagrid/datagrid.css.cjs.map +1 -1
- package/dist/inputs/datagrid/datagrid.css.js +1 -1
- package/dist/inputs/datagrid/datagrid.css.js.map +1 -1
- package/dist/inputs/datagrid/datagrid.d.ts +1 -1
- package/dist/inputs/datagrid/datagrid.d.ts.map +1 -1
- package/dist/inputs/date-picker/date-picker.css.cjs +1 -1
- package/dist/inputs/date-picker/date-picker.css.cjs.map +1 -1
- package/dist/inputs/date-picker/date-picker.css.js +1 -1
- package/dist/inputs/date-picker/date-picker.css.js.map +1 -1
- 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 +2 -3
- package/dist/inputs/file-input/file-input-upload.js.map +1 -1
- package/dist/inputs/file-input/file-input.css.cjs +1 -1
- package/dist/inputs/file-input/file-input.css.js +1 -1
- package/dist/inputs/file-input/file-input.d.ts.map +1 -1
- package/dist/inputs/index.d.ts +28 -28
- package/dist/inputs/index.d.ts.map +1 -1
- package/dist/inputs/input/input.css.cjs +1 -1
- package/dist/inputs/input/input.css.js +1 -1
- package/dist/inputs/input/input.d.ts.map +1 -1
- package/dist/inputs/message-composer/message-composer.css.cjs +1 -1
- package/dist/inputs/message-composer/message-composer.css.js +1 -1
- package/dist/inputs/message-composer/message-composer.d.ts +1 -1
- package/dist/inputs/message-composer/message-composer.d.ts.map +1 -1
- package/dist/inputs/number-input/number-input.d.ts.map +1 -1
- package/dist/inputs/otp-input/otp-input.d.ts.map +1 -1
- package/dist/inputs/radio/radio.css.cjs +1 -1
- package/dist/inputs/radio/radio.css.js +1 -1
- package/dist/inputs/radio/radio.d.ts.map +1 -1
- package/dist/inputs/radio-group/radio-group.d.ts +2 -2
- package/dist/inputs/radio-group/radio-group.d.ts.map +1 -1
- package/dist/inputs/rating/rating.d.ts.map +1 -1
- package/dist/inputs/select/select.css.cjs +1 -1
- package/dist/inputs/select/select.css.js +1 -1
- 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.map +1 -1
- package/dist/inputs/shared/field-binding.js.map +1 -1
- package/dist/inputs/shared/templates.cjs.map +1 -1
- package/dist/inputs/shared/templates.d.ts.map +1 -1
- package/dist/inputs/shared/templates.js.map +1 -1
- package/dist/inputs/slider/slider.d.ts.map +1 -1
- package/dist/inputs/switch/switch.css.cjs +1 -1
- package/dist/inputs/switch/switch.css.js +1 -1
- package/dist/inputs/switch/switch.d.ts.map +1 -1
- package/dist/inputs/textarea/textarea.css.cjs +1 -1
- package/dist/inputs/textarea/textarea.css.js +1 -1
- package/dist/inputs/textarea/textarea.d.ts.map +1 -1
- package/dist/inputs/time-picker/time-picker.css.cjs +1 -1
- package/dist/inputs/time-picker/time-picker.css.cjs.map +1 -1
- package/dist/inputs/time-picker/time-picker.css.js +1 -1
- package/dist/inputs/time-picker/time-picker.css.js.map +1 -1
- 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/grid/grid.d.ts.map +1 -1
- package/dist/layout/index.d.ts +6 -6
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/navbar/navbar.css.cjs +1 -1
- package/dist/layout/navbar/navbar.css.js +1 -1
- package/dist/layout/navbar/navbar.d.ts.map +1 -1
- package/dist/layout/sidebar/sidebar-group.css.cjs +1 -1
- package/dist/layout/sidebar/sidebar-group.css.cjs.map +1 -1
- package/dist/layout/sidebar/sidebar-group.css.js +1 -1
- package/dist/layout/sidebar/sidebar-group.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.map +1 -1
- package/dist/list-item.js.map +1 -1
- package/dist/list.cjs +2 -2
- package/dist/list.cjs.map +1 -1
- package/dist/list.js +15 -16
- package/dist/list.js.map +1 -1
- package/dist/marquee.cjs +1 -1
- package/dist/marquee.cjs.map +1 -1
- package/dist/marquee.js +1 -1
- package/dist/marquee.js.map +1 -1
- package/dist/menu.cjs +5 -5
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.js +38 -39
- package/dist/menu.js.map +1 -1
- package/dist/message-composer.cjs +16 -16
- package/dist/message-composer.cjs.map +1 -1
- package/dist/message-composer.js +61 -61
- package/dist/message-composer.js.map +1 -1
- package/dist/navbar.cjs +9 -9
- package/dist/navbar.cjs.map +1 -1
- package/dist/navbar.js +1 -2
- package/dist/navbar.js.map +1 -1
- package/dist/navigation-menu.cjs +5 -5
- package/dist/navigation-menu.cjs.map +1 -1
- package/dist/navigation-menu.js +33 -34
- package/dist/navigation-menu.js.map +1 -1
- package/dist/number-input.cjs +24 -24
- package/dist/number-input.cjs.map +1 -1
- package/dist/number-input.js +41 -42
- package/dist/number-input.js.map +1 -1
- package/dist/otp-input.cjs +13 -13
- package/dist/otp-input.cjs.map +1 -1
- package/dist/otp-input.js +32 -33
- package/dist/otp-input.js.map +1 -1
- package/dist/overlay/command-palette/command-palette-items.cjs.map +1 -1
- package/dist/overlay/command-palette/command-palette-items.d.ts.map +1 -1
- package/dist/overlay/command-palette/command-palette-items.js.map +1 -1
- package/dist/overlay/command-palette/command-palette.css.cjs +1 -1
- package/dist/overlay/command-palette/command-palette.css.cjs.map +1 -1
- package/dist/overlay/command-palette/command-palette.css.js +1 -1
- package/dist/overlay/command-palette/command-palette.css.js.map +1 -1
- package/dist/overlay/command-palette/command-palette.d.ts.map +1 -1
- package/dist/overlay/dialog/dialog.css.cjs +1 -1
- package/dist/overlay/dialog/dialog.css.js +1 -1
- package/dist/overlay/dialog/dialog.d.ts.map +1 -1
- package/dist/overlay/drawer/drawer.css.cjs +1 -1
- package/dist/overlay/drawer/drawer.css.js +1 -1
- package/dist/overlay/drawer/drawer.d.ts +2 -2
- package/dist/overlay/drawer/drawer.d.ts.map +1 -1
- package/dist/overlay/index.d.ts +6 -6
- package/dist/overlay/index.d.ts.map +1 -1
- package/dist/overlay/menu/menu.css.cjs +1 -1
- package/dist/overlay/menu/menu.css.js +1 -1
- package/dist/overlay/menu/menu.d.ts +2 -2
- package/dist/overlay/menu/menu.d.ts.map +1 -1
- package/dist/overlay/navigation-menu/navigation-menu.d.ts.map +1 -1
- package/dist/overlay/popover/popover.d.ts +1 -1
- package/dist/overlay/popover/popover.d.ts.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.map +1 -1
- package/dist/overlay/shared/use-dialog.js +4 -5
- 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.map +1 -1
- package/dist/overlay/shared/use-floating-trigger.js +1 -2
- package/dist/overlay/shared/use-floating-trigger.js.map +1 -1
- package/dist/overlay/tooltip/tooltip.d.ts +1 -1
- package/dist/overlay/tooltip/tooltip.d.ts.map +1 -1
- package/dist/pagination.cjs.map +1 -1
- package/dist/pagination.js.map +1 -1
- package/dist/popover.cjs +1 -1
- package/dist/popover.cjs.map +1 -1
- package/dist/popover.js +0 -1
- package/dist/popover.js.map +1 -1
- package/dist/progress.cjs.map +1 -1
- package/dist/progress.js.map +1 -1
- package/dist/radio-group.cjs +5 -5
- package/dist/radio-group.cjs.map +1 -1
- package/dist/radio-group.js +26 -27
- package/dist/radio-group.js.map +1 -1
- package/dist/radio.cjs +2 -2
- package/dist/radio.cjs.map +1 -1
- package/dist/radio.js +41 -41
- package/dist/radio.js.map +1 -1
- package/dist/rating.cjs +4 -4
- package/dist/rating.cjs.map +1 -1
- package/dist/rating.js +36 -36
- package/dist/rating.js.map +1 -1
- package/dist/refine.cjs +686 -686
- package/dist/refine.cjs.map +1 -1
- package/dist/refine.iife.js +686 -686
- package/dist/refine.iife.js.map +1 -1
- package/dist/refine.js +737 -737
- package/dist/refine.js.map +1 -1
- package/dist/select.cjs +42 -42
- package/dist/select.cjs.map +1 -1
- package/dist/select.js +146 -147
- package/dist/select.js.map +1 -1
- package/dist/separator.cjs.map +1 -1
- package/dist/separator.js.map +1 -1
- package/dist/sidebar.cjs +17 -17
- package/dist/sidebar.cjs.map +1 -1
- package/dist/sidebar.js +7 -8
- package/dist/sidebar.js.map +1 -1
- package/dist/skeleton.cjs +3 -3
- package/dist/skeleton.cjs.map +1 -1
- package/dist/skeleton.js +1 -2
- package/dist/skeleton.js.map +1 -1
- package/dist/slider.cjs +12 -12
- package/dist/slider.cjs.map +1 -1
- package/dist/slider.js +54 -55
- package/dist/slider.js.map +1 -1
- package/dist/step.cjs.map +1 -1
- package/dist/step.js.map +1 -1
- package/dist/stepper.cjs +2 -2
- package/dist/stepper.cjs.map +1 -1
- package/dist/stepper.js +8 -7
- package/dist/stepper.js.map +1 -1
- package/dist/styles/index.d.ts +2 -2
- package/dist/styles/index.d.ts.map +1 -1
- package/dist/styles/preflight.css +1 -1
- package/dist/styles/theme.css +15 -30
- package/dist/switch.cjs +3 -3
- package/dist/switch.cjs.map +1 -1
- package/dist/switch.js +28 -28
- package/dist/switch.js.map +1 -1
- package/dist/tab-item.cjs +2 -2
- package/dist/tab-item.cjs.map +1 -1
- package/dist/tab-item.js +21 -21
- package/dist/tab-item.js.map +1 -1
- package/dist/tab-panel.cjs +2 -2
- package/dist/tab-panel.cjs.map +1 -1
- package/dist/tab-panel.js +9 -9
- package/dist/tab-panel.js.map +1 -1
- package/dist/table.cjs +1 -1
- package/dist/table.cjs.map +1 -1
- package/dist/table.js +1 -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 +14 -15
- package/dist/tabs.js.map +1 -1
- package/dist/textarea.cjs +11 -11
- package/dist/textarea.cjs.map +1 -1
- package/dist/textarea.js +59 -59
- package/dist/textarea.js.map +1 -1
- package/dist/time-picker.cjs.map +1 -1
- package/dist/time-picker.js.map +1 -1
- package/dist/toast.cjs +16 -16
- package/dist/toast.cjs.map +1 -1
- package/dist/toast.js +20 -21
- package/dist/toast.js.map +1 -1
- package/dist/tooltip.cjs.map +1 -1
- 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 +1 -1
- package/dist/typing-indicator.js.map +1 -1
- package/package.json +96 -97
package/dist/number-input.cjs
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/states.css.cjs"),t=require("./core/spinner.cjs"),n=require("./shared/prop-bundles.cjs"),r=require("./inputs/shared/native-field-event.cjs"),i=require("./inputs/number-input/number-input.css.cjs");let a=require("@vielzeug/ore"),o=require("@vielzeug/ripple"),s=require("@vielzeug/arsenal/math");var c=`ore-number-input`;(0,a.define)(c,{formAssociated:!0,props:{...n.themableBundle,...n.sizableBundle,...n.disablableBundle,...n.roundableBundle,error:a.prop.string(),fullwidth:a.prop.bool(!1),helper:a.prop.string(),label:a.prop.string(),"label-placement":a.prop.oneOf([`inset`,`outside`],`inset`),"large-step":a.prop.json(void 0),loading:a.prop.bool(!1),max:a.prop.json(void 0),min:a.prop.json(void 0),name:a.prop.string(),placeholder:a.prop.string(),readonly:a.prop.bool(!1),ref:a.prop.data(),step:a.prop.number(1),success:a.prop.bool(!1),value:a.prop.json(void 0),variant:a.prop.string()},setup(e){let n=(0,a.getHost)(),i=a.watchEffect,c=(0,o.computed)(()=>e.disabled.value||e.loading.value),l=(0,o.computed)(()=>!!e.readonly.value),u=(0,o.signal)(e.value.value==null?``:String(e.value.value));r.defineFieldValue(n,()=>u.value,e=>{u.value=e}),(0,o.watch)(e.value,e=>{let t=e==null?``:String(e);u.value!==t&&(u.value=t)});function d(){let e=u.value.trim();if(!e)return null;let t=Number.parseFloat(e);return Number.isNaN(t)?null:t}function f(t,i){let a=e.min.value==null?void 0:Number(e.min.value),o=e.max.value==null?void 0:Number(e.max.value),c=t==null?null:(0,s.clamp)(t,a,o),l=c==null?``:String(c);u.value!==l&&(u.value=l),r.setFieldValue(n,l),r.dispatchNativeFieldEvent(n,`change`)}let p=t.createSpinnerControl({commit:f,disabled:c,largeStep:e[`large-step`],max:e.max,min:e.min,parse:d,readonly:l,step:e.step}),m=(0,a.ref)(),h=null,g=null,_=null,v=t=>{if(!t){h?.(),g?.(),_?.dispose(),h=null,g=null,_=null,e.ref.value?.(null);return}t.setAttribute(`inputmode`,`decimal`),t.setAttribute(`role`,`spinbutton`);let a=e=>{let t=e.target.value,n=t===``?null:Number.parseFloat(t);f(Number.isNaN(n??NaN)?null:n,e)},s=e=>{let t=e.target.value;u.value=t,r.setFieldValue(n,t),r.dispatchNativeFieldEvent(n,`input`)};t.addEventListener(`change`,a),t.addEventListener(`input`,s),g=()=>{t.removeEventListener(`change`,a),t.removeEventListener(`input`,s)},h=i(()=>{let n=d();n==null?t.removeAttribute(`aria-valuenow`):t.setAttribute(`aria-valuenow`,String(n)),e.min.value==null?t.removeAttribute(`aria-valuemin`):t.setAttribute(`aria-valuemin`,String(e.min.value)),e.max.value==null?t.removeAttribute(`aria-valuemax`):t.setAttribute(`aria-valuemax`,String(e.max.value)),l.value?t.setAttribute(`aria-readonly`,`true`):t.removeAttribute(`aria-readonly`)}),e.ref.value?.(t),_=(0,o.watch)(e.ref,e=>{e?.(t)})};(0,a.onElement)(m,e=>{e.ref=v}),(0,a.bind)({attr:{size:e.size,value:()=>u.value||null,variant:e.variant}});let y=(0,o.computed)(()=>c.value||l.value);return a.html`
|
|
2
2
|
<ore-input
|
|
3
3
|
class="field"
|
|
4
4
|
part="field control"
|
|
5
|
-
ref="${
|
|
6
|
-
value="${()=>
|
|
7
|
-
label="${()=>
|
|
8
|
-
label-placement="${()=>
|
|
9
|
-
placeholder="${()=>
|
|
10
|
-
name="${()=>
|
|
11
|
-
helper="${()=>
|
|
12
|
-
error="${()=>
|
|
13
|
-
size="${
|
|
14
|
-
color="${()=>
|
|
15
|
-
variant="${
|
|
16
|
-
rounded="${()=>
|
|
17
|
-
?disabled="${
|
|
18
|
-
?readonly="${
|
|
19
|
-
?fullwidth="${()=>
|
|
20
|
-
?loading="${()=>
|
|
21
|
-
?success="${()=>
|
|
22
|
-
@keydown="${e=>
|
|
5
|
+
ref="${m}"
|
|
6
|
+
value="${()=>u.value??0}"
|
|
7
|
+
label="${()=>e.label.value??``}"
|
|
8
|
+
label-placement="${()=>e[`label-placement`].value??`inset`}"
|
|
9
|
+
placeholder="${()=>e.placeholder.value??``}"
|
|
10
|
+
name="${()=>e.name.value??``}"
|
|
11
|
+
helper="${()=>e.helper.value??``}"
|
|
12
|
+
error="${()=>e.error.value??``}"
|
|
13
|
+
size="${e.size}"
|
|
14
|
+
color="${()=>e.color.value??``}"
|
|
15
|
+
variant="${e.variant}"
|
|
16
|
+
rounded="${()=>e.rounded.value}"
|
|
17
|
+
?disabled="${e.disabled}"
|
|
18
|
+
?readonly="${l}"
|
|
19
|
+
?fullwidth="${()=>e.fullwidth.value}"
|
|
20
|
+
?loading="${()=>e.loading.value}"
|
|
21
|
+
?success="${()=>e.success.value}"
|
|
22
|
+
@keydown="${e=>p.handleKeydown(e)}">
|
|
23
23
|
<button
|
|
24
24
|
slot="prefix"
|
|
25
25
|
type="button"
|
|
26
26
|
part="decrement-btn"
|
|
27
27
|
aria-label="Decrease"
|
|
28
|
-
?disabled="${()=>
|
|
29
|
-
@click="${
|
|
28
|
+
?disabled="${()=>y.value||p.atMin()}"
|
|
29
|
+
@click="${t=>p.incrementBy(-(Number(e.step.value)||1),t)}">
|
|
30
30
|
<ore-icon name="minus" size="14" stroke-width="2.5" aria-hidden="true"></ore-icon>
|
|
31
31
|
</button>
|
|
32
32
|
<button
|
|
@@ -34,10 +34,10 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
|
|
|
34
34
|
type="button"
|
|
35
35
|
part="increment-btn"
|
|
36
36
|
aria-label="Increase"
|
|
37
|
-
?disabled="${()=>
|
|
38
|
-
@click="${
|
|
37
|
+
?disabled="${()=>y.value||p.atMax()}"
|
|
38
|
+
@click="${t=>p.incrementBy(Number(e.step.value)||1,t)}">
|
|
39
39
|
<ore-icon name="plus" size="14" stroke-width="2.5" aria-hidden="true"></ore-icon>
|
|
40
40
|
</button>
|
|
41
41
|
</ore-input>
|
|
42
|
-
`},shadow:{delegatesFocus:!0},styles:[
|
|
42
|
+
`},shadow:{delegatesFocus:!0},styles:[e.disabledLoadingMixin,i.default]}),exports.NUMBER_INPUT_TAG=c;
|
|
43
43
|
//# sourceMappingURL=number-input.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-input.cjs","names":[],"sources":["../src/inputs/number-input/number-input.ts"],"sourcesContent":["import { clamp } from '@vielzeug/arsenal/math';\nimport { define, html, prop, ref, bind, getHost, onElement, watchEffect } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch as rippleWatch } from '@vielzeug/ripple/watch';\n\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { createSpinnerControl } from '../../core';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledLoadingMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './number-input.css?inline';\n\nexport type OreNumberInputEvents = {\n change: Event;\n input: InputEvent;\n};\n\n/** Number Input props */\nexport type OreNumberInputProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /** Stretch to full width of container */\n fullwidth?: boolean;\n /** Helper text */\n helper?: string;\n /** Visible label */\n label?: string;\n /** Label placement: 'inset' renders the label inside the control box, 'outside' renders it above */\n 'label-placement'?: 'inset' | 'outside';\n /** Large step (for Page Up/Down, default: 10 × step) */\n 'large-step'?: number;\n /**\n * Shows an inline spinner inside the field and forces the control into `disabled` for the\n * duration — use while an async validation/submission request is in flight to prevent\n * double-submits.\n */\n loading?: boolean;\n /** Maximum allowed value */\n max?: number;\n /** Minimum allowed value */\n min?: number;\n /** Form field name */\n name?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Make the input read-only */\n readonly?: boolean;\n /**\n * JS-only callback fired with the inner `<input>` element when it mounts,\n * and with `null` when it unmounts.\n * Set as a JS property: `bitNumberInput.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLInputElement | null) => void) | null;\n /** Border radius */\n rounded?: string;\n /** Component size */\n size?: ComponentSize;\n /** Step size for increment/decrement */\n step?: number;\n /**\n * Shows an inline green check icon inside the field to confirm the value has\n * passed validation. Ignored while `error` is set — an error always wins.\n */\n success?: boolean;\n /** Current numeric value */\n value?: number;\n /** Visual variant */\n variant?: VisualVariant;\n};\n\n/**\n * A numeric spin-button input with +/− controls, min/max clamping, and full keyboard support.\n *\n * @element ore-number-input\n *\n * @attr {number} value - Current value\n * @attr {number} min - Minimum value\n * @attr {number} max - Maximum value\n * @attr {number} step - Increment/decrement step (default: 1)\n * @attr {number} large-step - Step for Page Up/Down (default: 10)\n * @attr {boolean} disabled - Disables the control\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} loading - Show an inline spinner and force the control disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} label - Visible label\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} placeholder - Input placeholder\n *\n * @fires input - On every keystroke.\n * @fires change - On committed value change.\n *\n * @slot prefix - Content before the input (e.g. icon)\n * @slot suffix - Content after the input (e.g. unit label)\n * @slot label - Custom label content\n * @slot helper - Custom helper text content\n * @slot error - Custom error content\n *\n * @cssprop --number-input-height - Control height\n * @cssprop --number-input-border-color - Border color\n * @cssprop --number-input-radius - Border radius\n * @cssprop --number-input-bg - Background\n * @cssprop --number-input-btn-bg - Spin button background\n *\n * @part control - Control container.\n * @part decrement-btn - Decrement stepper button.\n * @part input - Input element.\n * @part increment-btn - Increment stepper button.\n * @example\n * ```html\n * <ore-number-input label=\"Quantity\" value=\"1\" min=\"1\" max=\"99\" step=\"1\"></ore-number-input>\n * <ore-number-input label=\"Quantity\" success></ore-number-input>\n * <ore-number-input label=\"Quantity\" loading></ore-number-input>\n * ```\n */\nexport const NUMBER_INPUT_TAG = 'ore-number-input' as const;\ndefine<OreNumberInputProps>(NUMBER_INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n 'large-step': prop.json(undefined as number | undefined),\n loading: prop.bool(false),\n max: prop.json(undefined as number | undefined),\n min: prop.json(undefined as number | undefined),\n name: prop.string(),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n step: prop.number(1),\n success: prop.bool(false),\n value: prop.json(undefined as number | undefined),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // `loading` behaves like a temporary `disabled` — see ore-input's identical computation.\n const isDisabled = computed(() => props.disabled.value || props.loading.value);\n const isReadonly = computed(() => Boolean(props.readonly.value));\n\n // Internal numeric value signal (string representation for the input)\n const fieldValue = signal(props.value.value != null ? String(props.value.value) : '');\n\n defineFieldValue(\n el,\n () => fieldValue.value,\n (value) => {\n fieldValue.value = value;\n },\n );\n\n // Keep fieldValue in sync when props.value changes externally\n rippleWatch(props.value, (v) => {\n const next = v != null ? String(v) : '';\n\n if (fieldValue.value !== next) fieldValue.value = next;\n });\n\n function parseValue(): number | null {\n const v = fieldValue.value.trim();\n\n if (!v) return null;\n\n const n = Number.parseFloat(v);\n\n return Number.isNaN(n) ? null : n;\n }\n\n function commit(val: number | null, _originalEvent?: Event) {\n const min = props.min.value != null ? Number(props.min.value) : undefined;\n const max = props.max.value != null ? Number(props.max.value) : undefined;\n const clamped = val != null ? clamp(val, min, max) : null;\n const nextValue = clamped != null ? String(clamped) : '';\n\n if (fieldValue.value !== nextValue) fieldValue.value = nextValue;\n\n setFieldValue(el, nextValue);\n dispatchNativeFieldEvent(el, 'change');\n }\n\n const spinner = createSpinnerControl({\n commit,\n disabled: isDisabled,\n largeStep: props['large-step'],\n max: props.max,\n min: props.min,\n parse: parseValue,\n readonly: isReadonly,\n step: props.step,\n });\n\n // Composition uses ore-input's own documented `ref` prop (fired with the raw\n // <input> on mount, `null` on unmount) instead of reaching into its shadow DOM —\n // see `packages/refine/AGENTS.md` / input.ts's `ref` JSDoc for the supported contract.\n // Set imperatively (rather than declared in the template) because ore's template\n // engine treats a function-valued attr binding as a reactive getter to invoke, not\n // a literal value to assign — a plain property assignment avoids that entirely.\n const bitInputRef = ref<HTMLElementTagNameMap['ore-input']>();\n let stopAriaWatch: (() => void) | null = null;\n let detachListeners: (() => void) | null = null;\n let refSub: { dispose(): void } | null = null;\n\n const handleFieldRef = (rawInput: HTMLInputElement | null): void => {\n if (!rawInput) {\n stopAriaWatch?.();\n detachListeners?.();\n refSub?.dispose();\n stopAriaWatch = null;\n detachListeners = null;\n refSub = null;\n props.ref.value?.(null);\n\n return;\n }\n\n rawInput.setAttribute('inputmode', 'decimal');\n // The wrapper div is a plain layout container — WAI-ARIA spinbutton semantics\n // live on the actually-focusable element (the raw <input> rendered by ore-input).\n rawInput.setAttribute('role', 'spinbutton');\n\n const handleChange = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n const n = val !== '' ? Number.parseFloat(val) : null;\n\n commit(Number.isNaN(n ?? NaN) ? null : n, e);\n };\n\n const handleInput = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n\n fieldValue.value = val;\n setFieldValue(el, val);\n dispatchNativeFieldEvent(el, 'input');\n };\n\n rawInput.addEventListener('change', handleChange);\n rawInput.addEventListener('input', handleInput);\n detachListeners = () => {\n rawInput.removeEventListener('change', handleChange);\n rawInput.removeEventListener('input', handleInput);\n };\n\n stopAriaWatch = watch(() => {\n const now = parseValue();\n\n if (now == null) rawInput.removeAttribute('aria-valuenow');\n else rawInput.setAttribute('aria-valuenow', String(now));\n\n if (props.min.value != null) rawInput.setAttribute('aria-valuemin', String(props.min.value));\n else rawInput.removeAttribute('aria-valuemin');\n\n if (props.max.value != null) rawInput.setAttribute('aria-valuemax', String(props.max.value));\n else rawInput.removeAttribute('aria-valuemax');\n\n if (isReadonly.value) rawInput.setAttribute('aria-readonly', 'true');\n else rawInput.removeAttribute('aria-readonly');\n });\n\n // Fire user ref callback\n props.ref.value?.(rawInput);\n\n refSub = rippleWatch(props.ref, (cb) => {\n cb?.(rawInput);\n });\n };\n\n // ore-input's own onElement/ref lifecycle calls this back with `null` when its\n // inner <input> unmounts, so no explicit teardown is needed here.\n onElement(bitInputRef, (bitInputEl) => {\n bitInputEl.ref = handleFieldRef;\n });\n\n bind({\n attr: {\n size: props.size,\n value: () => fieldValue.value || null,\n variant: props.variant,\n },\n });\n\n const isNonInteractive = computed(() => isDisabled.value || isReadonly.value);\n\n // The stepper buttons are slotted *into* ore-input's own `prefix`/`suffix` slots instead of\n // sitting outside it in a separate wrapper — they render inside ore-input's own bordered\n // box (same as its built-in clear/password-toggle buttons), matching every other field's\n // single-box look instead of floating as two detached icon buttons either side of a\n // narrow field. `@keydown` moves to ore-input itself: native keyboard events are\n // `composed: true` and bubble out past a shadow boundary, so it still sees keydowns\n // originating from ore-input's internal <input> as well as from these slotted buttons.\n return html`\n <ore-input\n class=\"field\"\n part=\"field control\"\n ref=\"${bitInputRef}\"\n value=\"${() => fieldValue.value ?? 0}\"\n label=\"${() => props.label.value ?? ''}\"\n label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n placeholder=\"${() => props.placeholder.value ?? ''}\"\n name=\"${() => props.name.value ?? ''}\"\n helper=\"${() => props.helper.value ?? ''}\"\n error=\"${() => props.error.value ?? ''}\"\n size=\"${props.size}\"\n color=\"${() => props.color.value ?? ''}\"\n variant=\"${props.variant}\"\n rounded=\"${() => props.rounded.value}\"\n ?disabled=\"${props.disabled}\"\n ?readonly=\"${isReadonly}\"\n ?fullwidth=\"${() => props.fullwidth.value}\"\n ?loading=\"${() => props.loading.value}\"\n ?success=\"${() => props.success.value}\"\n @keydown=\"${(e: KeyboardEvent) => spinner.handleKeydown(e)}\">\n <button\n slot=\"prefix\"\n type=\"button\"\n part=\"decrement-btn\"\n aria-label=\"Decrease\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMin()}\"\n @click=\"${(e: Event) => spinner.incrementBy(-(Number(props.step.value) || 1), e)}\">\n <ore-icon name=\"minus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n <button\n slot=\"suffix\"\n type=\"button\"\n part=\"increment-btn\"\n aria-label=\"Increase\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMax()}\"\n @click=\"${(e: Event) => spinner.incrementBy(Number(props.step.value) || 1, e)}\">\n <ore-icon name=\"plus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n </ore-input>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [disabledLoadingMixin, componentStyles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"number-input.cjs","names":[],"sources":["../src/inputs/number-input/number-input.ts"],"sourcesContent":["import { clamp } from '@vielzeug/arsenal/math';\nimport { bind, define, getHost, html, onElement, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport { createSpinnerControl } from '../../core';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledLoadingMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './number-input.css?inline';\n\nexport type OreNumberInputEvents = {\n change: Event;\n input: InputEvent;\n};\n\n/** Number Input props */\nexport type OreNumberInputProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /** Stretch to full width of container */\n fullwidth?: boolean;\n /** Helper text */\n helper?: string;\n /** Visible label */\n label?: string;\n /** Label placement: 'inset' renders the label inside the control box, 'outside' renders it above */\n 'label-placement'?: 'inset' | 'outside';\n /** Large step (for Page Up/Down, default: 10 × step) */\n 'large-step'?: number;\n /**\n * Shows an inline spinner inside the field and forces the control into `disabled` for the\n * duration — use while an async validation/submission request is in flight to prevent\n * double-submits.\n */\n loading?: boolean;\n /** Maximum allowed value */\n max?: number;\n /** Minimum allowed value */\n min?: number;\n /** Form field name */\n name?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Make the input read-only */\n readonly?: boolean;\n /**\n * JS-only callback fired with the inner `<input>` element when it mounts,\n * and with `null` when it unmounts.\n * Set as a JS property: `bitNumberInput.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLInputElement | null) => void) | null;\n /** Border radius */\n rounded?: string;\n /** Component size */\n size?: ComponentSize;\n /** Step size for increment/decrement */\n step?: number;\n /**\n * Shows an inline green check icon inside the field to confirm the value has\n * passed validation. Ignored while `error` is set — an error always wins.\n */\n success?: boolean;\n /** Current numeric value */\n value?: number;\n /** Visual variant */\n variant?: VisualVariant;\n};\n\n/**\n * A numeric spin-button input with +/− controls, min/max clamping, and full keyboard support.\n *\n * @element ore-number-input\n *\n * @attr {number} value - Current value\n * @attr {number} min - Minimum value\n * @attr {number} max - Maximum value\n * @attr {number} step - Increment/decrement step (default: 1)\n * @attr {number} large-step - Step for Page Up/Down (default: 10)\n * @attr {boolean} disabled - Disables the control\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} loading - Show an inline spinner and force the control disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} label - Visible label\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} placeholder - Input placeholder\n *\n * @fires input - On every keystroke.\n * @fires change - On committed value change.\n *\n * @slot prefix - Content before the input (e.g. icon)\n * @slot suffix - Content after the input (e.g. unit label)\n * @slot label - Custom label content\n * @slot helper - Custom helper text content\n * @slot error - Custom error content\n *\n * @cssprop --number-input-height - Control height\n * @cssprop --number-input-border-color - Border color\n * @cssprop --number-input-radius - Border radius\n * @cssprop --number-input-bg - Background\n * @cssprop --number-input-btn-bg - Spin button background\n *\n * @part control - Control container.\n * @part decrement-btn - Decrement stepper button.\n * @part input - Input element.\n * @part increment-btn - Increment stepper button.\n * @example\n * ```html\n * <ore-number-input label=\"Quantity\" value=\"1\" min=\"1\" max=\"99\" step=\"1\"></ore-number-input>\n * <ore-number-input label=\"Quantity\" success></ore-number-input>\n * <ore-number-input label=\"Quantity\" loading></ore-number-input>\n * ```\n */\nexport const NUMBER_INPUT_TAG = 'ore-number-input' as const;\ndefine<OreNumberInputProps>(NUMBER_INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n 'large-step': prop.json(undefined as number | undefined),\n loading: prop.bool(false),\n max: prop.json(undefined as number | undefined),\n min: prop.json(undefined as number | undefined),\n name: prop.string(),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n step: prop.number(1),\n success: prop.bool(false),\n value: prop.json(undefined as number | undefined),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // `loading` behaves like a temporary `disabled` — see ore-input's identical computation.\n const isDisabled = computed(() => props.disabled.value || props.loading.value);\n const isReadonly = computed(() => Boolean(props.readonly.value));\n\n // Internal numeric value signal (string representation for the input)\n const fieldValue = signal(props.value.value != null ? String(props.value.value) : '');\n\n defineFieldValue(\n el,\n () => fieldValue.value,\n (value) => {\n fieldValue.value = value;\n },\n );\n\n // Keep fieldValue in sync when props.value changes externally\n rippleWatch(props.value, (v) => {\n const next = v != null ? String(v) : '';\n\n if (fieldValue.value !== next) fieldValue.value = next;\n });\n\n function parseValue(): number | null {\n const v = fieldValue.value.trim();\n\n if (!v) return null;\n\n const n = Number.parseFloat(v);\n\n return Number.isNaN(n) ? null : n;\n }\n\n function commit(val: number | null, _originalEvent?: Event) {\n const min = props.min.value != null ? Number(props.min.value) : undefined;\n const max = props.max.value != null ? Number(props.max.value) : undefined;\n const clamped = val != null ? clamp(val, min, max) : null;\n const nextValue = clamped != null ? String(clamped) : '';\n\n if (fieldValue.value !== nextValue) fieldValue.value = nextValue;\n\n setFieldValue(el, nextValue);\n dispatchNativeFieldEvent(el, 'change');\n }\n\n const spinner = createSpinnerControl({\n commit,\n disabled: isDisabled,\n largeStep: props['large-step'],\n max: props.max,\n min: props.min,\n parse: parseValue,\n readonly: isReadonly,\n step: props.step,\n });\n\n // Composition uses ore-input's own documented `ref` prop (fired with the raw\n // <input> on mount, `null` on unmount) instead of reaching into its shadow DOM —\n // see `packages/refine/AGENTS.md` / input.ts's `ref` JSDoc for the supported contract.\n // Set imperatively (rather than declared in the template) because ore's template\n // engine treats a function-valued attr binding as a reactive getter to invoke, not\n // a literal value to assign — a plain property assignment avoids that entirely.\n const bitInputRef = ref<HTMLElementTagNameMap['ore-input']>();\n let stopAriaWatch: (() => void) | null = null;\n let detachListeners: (() => void) | null = null;\n let refSub: { dispose(): void } | null = null;\n\n const handleFieldRef = (rawInput: HTMLInputElement | null): void => {\n if (!rawInput) {\n stopAriaWatch?.();\n detachListeners?.();\n refSub?.dispose();\n stopAriaWatch = null;\n detachListeners = null;\n refSub = null;\n props.ref.value?.(null);\n\n return;\n }\n\n rawInput.setAttribute('inputmode', 'decimal');\n // The wrapper div is a plain layout container — WAI-ARIA spinbutton semantics\n // live on the actually-focusable element (the raw <input> rendered by ore-input).\n rawInput.setAttribute('role', 'spinbutton');\n\n const handleChange = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n const n = val !== '' ? Number.parseFloat(val) : null;\n\n commit(Number.isNaN(n ?? NaN) ? null : n, e);\n };\n\n const handleInput = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n\n fieldValue.value = val;\n setFieldValue(el, val);\n dispatchNativeFieldEvent(el, 'input');\n };\n\n rawInput.addEventListener('change', handleChange);\n rawInput.addEventListener('input', handleInput);\n detachListeners = () => {\n rawInput.removeEventListener('change', handleChange);\n rawInput.removeEventListener('input', handleInput);\n };\n\n stopAriaWatch = watch(() => {\n const now = parseValue();\n\n if (now == null) rawInput.removeAttribute('aria-valuenow');\n else rawInput.setAttribute('aria-valuenow', String(now));\n\n if (props.min.value != null) rawInput.setAttribute('aria-valuemin', String(props.min.value));\n else rawInput.removeAttribute('aria-valuemin');\n\n if (props.max.value != null) rawInput.setAttribute('aria-valuemax', String(props.max.value));\n else rawInput.removeAttribute('aria-valuemax');\n\n if (isReadonly.value) rawInput.setAttribute('aria-readonly', 'true');\n else rawInput.removeAttribute('aria-readonly');\n });\n\n // Fire user ref callback\n props.ref.value?.(rawInput);\n\n refSub = rippleWatch(props.ref, (cb) => {\n cb?.(rawInput);\n });\n };\n\n // ore-input's own onElement/ref lifecycle calls this back with `null` when its\n // inner <input> unmounts, so no explicit teardown is needed here.\n onElement(bitInputRef, (bitInputEl) => {\n bitInputEl.ref = handleFieldRef;\n });\n\n bind({\n attr: {\n size: props.size,\n value: () => fieldValue.value || null,\n variant: props.variant,\n },\n });\n\n const isNonInteractive = computed(() => isDisabled.value || isReadonly.value);\n\n // The stepper buttons are slotted *into* ore-input's own `prefix`/`suffix` slots instead of\n // sitting outside it in a separate wrapper — they render inside ore-input's own bordered\n // box (same as its built-in clear/password-toggle buttons), matching every other field's\n // single-box look instead of floating as two detached icon buttons either side of a\n // narrow field. `@keydown` moves to ore-input itself: native keyboard events are\n // `composed: true` and bubble out past a shadow boundary, so it still sees keydowns\n // originating from ore-input's internal <input> as well as from these slotted buttons.\n return html`\n <ore-input\n class=\"field\"\n part=\"field control\"\n ref=\"${bitInputRef}\"\n value=\"${() => fieldValue.value ?? 0}\"\n label=\"${() => props.label.value ?? ''}\"\n label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n placeholder=\"${() => props.placeholder.value ?? ''}\"\n name=\"${() => props.name.value ?? ''}\"\n helper=\"${() => props.helper.value ?? ''}\"\n error=\"${() => props.error.value ?? ''}\"\n size=\"${props.size}\"\n color=\"${() => props.color.value ?? ''}\"\n variant=\"${props.variant}\"\n rounded=\"${() => props.rounded.value}\"\n ?disabled=\"${props.disabled}\"\n ?readonly=\"${isReadonly}\"\n ?fullwidth=\"${() => props.fullwidth.value}\"\n ?loading=\"${() => props.loading.value}\"\n ?success=\"${() => props.success.value}\"\n @keydown=\"${(e: KeyboardEvent) => spinner.handleKeydown(e)}\">\n <button\n slot=\"prefix\"\n type=\"button\"\n part=\"decrement-btn\"\n aria-label=\"Decrease\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMin()}\"\n @click=\"${(e: Event) => spinner.incrementBy(-(Number(props.step.value) || 1), e)}\">\n <ore-icon name=\"minus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n <button\n slot=\"suffix\"\n type=\"button\"\n part=\"increment-btn\"\n aria-label=\"Increase\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMax()}\"\n @click=\"${(e: Event) => spinner.incrementBy(Number(props.step.value) || 1, e)}\">\n <ore-icon name=\"plus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n </ore-input>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [disabledLoadingMixin, componentStyles],\n});\n"],"mappings":"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"}
|
package/dist/number-input.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { disabledLoadingMixin as e } from "./styles/mixins/states.css.js";
|
|
2
|
+
import { createSpinnerControl as t } from "./core/spinner.js";
|
|
3
3
|
import { disablableBundle as n, roundableBundle as r, sizableBundle as i, themableBundle as a } from "./shared/prop-bundles.js";
|
|
4
4
|
import { defineFieldValue as o, dispatchNativeFieldEvent as s, setFieldValue as c } from "./inputs/shared/native-field-event.js";
|
|
5
5
|
import l from "./inputs/number-input/number-input.css.js";
|
|
6
6
|
import { bind as u, define as d, getHost as f, html as p, onElement as m, prop as h, ref as g, watchEffect as _ } from "@vielzeug/ore";
|
|
7
|
-
import { computed as v, signal as y } from "@vielzeug/ripple";
|
|
8
|
-
import { watch as b } from "@vielzeug/ripple/watch";
|
|
7
|
+
import { computed as v, signal as y, watch as b } from "@vielzeug/ripple";
|
|
9
8
|
import { clamp as x } from "@vielzeug/arsenal/math";
|
|
10
9
|
//#region src/inputs/number-input/number-input.ts
|
|
11
10
|
var S = "ore-number-input";
|
|
@@ -34,11 +33,11 @@ d(S, {
|
|
|
34
33
|
value: h.json(void 0),
|
|
35
34
|
variant: h.string()
|
|
36
35
|
},
|
|
37
|
-
setup(
|
|
38
|
-
let n = f(), r = _, i = v(() =>
|
|
36
|
+
setup(e) {
|
|
37
|
+
let n = f(), r = _, i = v(() => e.disabled.value || e.loading.value), a = v(() => !!e.readonly.value), l = y(e.value.value == null ? "" : String(e.value.value));
|
|
39
38
|
o(n, () => l.value, (e) => {
|
|
40
39
|
l.value = e;
|
|
41
|
-
}), b(
|
|
40
|
+
}), b(e.value, (e) => {
|
|
42
41
|
let t = e == null ? "" : String(e);
|
|
43
42
|
l.value !== t && (l.value = t);
|
|
44
43
|
});
|
|
@@ -48,25 +47,25 @@ d(S, {
|
|
|
48
47
|
let t = Number.parseFloat(e);
|
|
49
48
|
return Number.isNaN(t) ? null : t;
|
|
50
49
|
}
|
|
51
|
-
function h(
|
|
52
|
-
let i =
|
|
50
|
+
function h(t, r) {
|
|
51
|
+
let i = e.min.value == null ? void 0 : Number(e.min.value), a = e.max.value == null ? void 0 : Number(e.max.value), o = t == null ? null : x(t, i, a), u = o == null ? "" : String(o);
|
|
53
52
|
l.value !== u && (l.value = u), c(n, u), s(n, "change");
|
|
54
53
|
}
|
|
55
|
-
let S =
|
|
54
|
+
let S = t({
|
|
56
55
|
commit: h,
|
|
57
56
|
disabled: i,
|
|
58
|
-
largeStep:
|
|
59
|
-
max:
|
|
60
|
-
min:
|
|
57
|
+
largeStep: e["large-step"],
|
|
58
|
+
max: e.max,
|
|
59
|
+
min: e.min,
|
|
61
60
|
parse: d,
|
|
62
61
|
readonly: a,
|
|
63
|
-
step:
|
|
64
|
-
}), C = g(), w = null, T = null, E = null, D = (
|
|
65
|
-
if (!
|
|
66
|
-
w?.(), T?.(), E?.dispose(), w = null, T = null, E = null,
|
|
62
|
+
step: e.step
|
|
63
|
+
}), C = g(), w = null, T = null, E = null, D = (t) => {
|
|
64
|
+
if (!t) {
|
|
65
|
+
w?.(), T?.(), E?.dispose(), w = null, T = null, E = null, e.ref.value?.(null);
|
|
67
66
|
return;
|
|
68
67
|
}
|
|
69
|
-
|
|
68
|
+
t.setAttribute("inputmode", "decimal"), t.setAttribute("role", "spinbutton");
|
|
70
69
|
let i = (e) => {
|
|
71
70
|
let t = e.target.value, n = t === "" ? null : Number.parseFloat(t);
|
|
72
71
|
h(Number.isNaN(n ?? NaN) ? null : n, e);
|
|
@@ -74,21 +73,21 @@ d(S, {
|
|
|
74
73
|
let t = e.target.value;
|
|
75
74
|
l.value = t, c(n, t), s(n, "input");
|
|
76
75
|
};
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
t.addEventListener("change", i), t.addEventListener("input", o), T = () => {
|
|
77
|
+
t.removeEventListener("change", i), t.removeEventListener("input", o);
|
|
79
78
|
}, w = r(() => {
|
|
80
79
|
let n = d();
|
|
81
|
-
n == null ?
|
|
82
|
-
}),
|
|
83
|
-
|
|
80
|
+
n == null ? t.removeAttribute("aria-valuenow") : t.setAttribute("aria-valuenow", String(n)), e.min.value == null ? t.removeAttribute("aria-valuemin") : t.setAttribute("aria-valuemin", String(e.min.value)), e.max.value == null ? t.removeAttribute("aria-valuemax") : t.setAttribute("aria-valuemax", String(e.max.value)), a.value ? t.setAttribute("aria-readonly", "true") : t.removeAttribute("aria-readonly");
|
|
81
|
+
}), e.ref.value?.(t), E = b(e.ref, (e) => {
|
|
82
|
+
e?.(t);
|
|
84
83
|
});
|
|
85
84
|
};
|
|
86
85
|
m(C, (e) => {
|
|
87
86
|
e.ref = D;
|
|
88
87
|
}), u({ attr: {
|
|
89
|
-
size:
|
|
88
|
+
size: e.size,
|
|
90
89
|
value: () => l.value || null,
|
|
91
|
-
variant:
|
|
90
|
+
variant: e.variant
|
|
92
91
|
} });
|
|
93
92
|
let O = v(() => i.value || a.value);
|
|
94
93
|
return p`
|
|
@@ -97,21 +96,21 @@ d(S, {
|
|
|
97
96
|
part="field control"
|
|
98
97
|
ref="${C}"
|
|
99
98
|
value="${() => l.value ?? 0}"
|
|
100
|
-
label="${() =>
|
|
101
|
-
label-placement="${() =>
|
|
102
|
-
placeholder="${() =>
|
|
103
|
-
name="${() =>
|
|
104
|
-
helper="${() =>
|
|
105
|
-
error="${() =>
|
|
106
|
-
size="${
|
|
107
|
-
color="${() =>
|
|
108
|
-
variant="${
|
|
109
|
-
rounded="${() =>
|
|
110
|
-
?disabled="${
|
|
99
|
+
label="${() => e.label.value ?? ""}"
|
|
100
|
+
label-placement="${() => e["label-placement"].value ?? "inset"}"
|
|
101
|
+
placeholder="${() => e.placeholder.value ?? ""}"
|
|
102
|
+
name="${() => e.name.value ?? ""}"
|
|
103
|
+
helper="${() => e.helper.value ?? ""}"
|
|
104
|
+
error="${() => e.error.value ?? ""}"
|
|
105
|
+
size="${e.size}"
|
|
106
|
+
color="${() => e.color.value ?? ""}"
|
|
107
|
+
variant="${e.variant}"
|
|
108
|
+
rounded="${() => e.rounded.value}"
|
|
109
|
+
?disabled="${e.disabled}"
|
|
111
110
|
?readonly="${a}"
|
|
112
|
-
?fullwidth="${() =>
|
|
113
|
-
?loading="${() =>
|
|
114
|
-
?success="${() =>
|
|
111
|
+
?fullwidth="${() => e.fullwidth.value}"
|
|
112
|
+
?loading="${() => e.loading.value}"
|
|
113
|
+
?success="${() => e.success.value}"
|
|
115
114
|
@keydown="${(e) => S.handleKeydown(e)}">
|
|
116
115
|
<button
|
|
117
116
|
slot="prefix"
|
|
@@ -119,7 +118,7 @@ d(S, {
|
|
|
119
118
|
part="decrement-btn"
|
|
120
119
|
aria-label="Decrease"
|
|
121
120
|
?disabled="${() => O.value || S.atMin()}"
|
|
122
|
-
@click="${(
|
|
121
|
+
@click="${(t) => S.incrementBy(-(Number(e.step.value) || 1), t)}">
|
|
123
122
|
<ore-icon name="minus" size="14" stroke-width="2.5" aria-hidden="true"></ore-icon>
|
|
124
123
|
</button>
|
|
125
124
|
<button
|
|
@@ -128,14 +127,14 @@ d(S, {
|
|
|
128
127
|
part="increment-btn"
|
|
129
128
|
aria-label="Increase"
|
|
130
129
|
?disabled="${() => O.value || S.atMax()}"
|
|
131
|
-
@click="${(
|
|
130
|
+
@click="${(t) => S.incrementBy(Number(e.step.value) || 1, t)}">
|
|
132
131
|
<ore-icon name="plus" size="14" stroke-width="2.5" aria-hidden="true"></ore-icon>
|
|
133
132
|
</button>
|
|
134
133
|
</ore-input>
|
|
135
134
|
`;
|
|
136
135
|
},
|
|
137
136
|
shadow: { delegatesFocus: !0 },
|
|
138
|
-
styles: [
|
|
137
|
+
styles: [e, l]
|
|
139
138
|
});
|
|
140
139
|
//#endregion
|
|
141
140
|
export { S as NUMBER_INPUT_TAG };
|
package/dist/number-input.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-input.js","names":[],"sources":["../src/inputs/number-input/number-input.ts"],"sourcesContent":["import { clamp } from '@vielzeug/arsenal/math';\nimport { define, html, prop, ref, bind, getHost, onElement, watchEffect } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch as rippleWatch } from '@vielzeug/ripple/watch';\n\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { createSpinnerControl } from '../../core';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledLoadingMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './number-input.css?inline';\n\nexport type OreNumberInputEvents = {\n change: Event;\n input: InputEvent;\n};\n\n/** Number Input props */\nexport type OreNumberInputProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /** Stretch to full width of container */\n fullwidth?: boolean;\n /** Helper text */\n helper?: string;\n /** Visible label */\n label?: string;\n /** Label placement: 'inset' renders the label inside the control box, 'outside' renders it above */\n 'label-placement'?: 'inset' | 'outside';\n /** Large step (for Page Up/Down, default: 10 × step) */\n 'large-step'?: number;\n /**\n * Shows an inline spinner inside the field and forces the control into `disabled` for the\n * duration — use while an async validation/submission request is in flight to prevent\n * double-submits.\n */\n loading?: boolean;\n /** Maximum allowed value */\n max?: number;\n /** Minimum allowed value */\n min?: number;\n /** Form field name */\n name?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Make the input read-only */\n readonly?: boolean;\n /**\n * JS-only callback fired with the inner `<input>` element when it mounts,\n * and with `null` when it unmounts.\n * Set as a JS property: `bitNumberInput.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLInputElement | null) => void) | null;\n /** Border radius */\n rounded?: string;\n /** Component size */\n size?: ComponentSize;\n /** Step size for increment/decrement */\n step?: number;\n /**\n * Shows an inline green check icon inside the field to confirm the value has\n * passed validation. Ignored while `error` is set — an error always wins.\n */\n success?: boolean;\n /** Current numeric value */\n value?: number;\n /** Visual variant */\n variant?: VisualVariant;\n};\n\n/**\n * A numeric spin-button input with +/− controls, min/max clamping, and full keyboard support.\n *\n * @element ore-number-input\n *\n * @attr {number} value - Current value\n * @attr {number} min - Minimum value\n * @attr {number} max - Maximum value\n * @attr {number} step - Increment/decrement step (default: 1)\n * @attr {number} large-step - Step for Page Up/Down (default: 10)\n * @attr {boolean} disabled - Disables the control\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} loading - Show an inline spinner and force the control disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} label - Visible label\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} placeholder - Input placeholder\n *\n * @fires input - On every keystroke.\n * @fires change - On committed value change.\n *\n * @slot prefix - Content before the input (e.g. icon)\n * @slot suffix - Content after the input (e.g. unit label)\n * @slot label - Custom label content\n * @slot helper - Custom helper text content\n * @slot error - Custom error content\n *\n * @cssprop --number-input-height - Control height\n * @cssprop --number-input-border-color - Border color\n * @cssprop --number-input-radius - Border radius\n * @cssprop --number-input-bg - Background\n * @cssprop --number-input-btn-bg - Spin button background\n *\n * @part control - Control container.\n * @part decrement-btn - Decrement stepper button.\n * @part input - Input element.\n * @part increment-btn - Increment stepper button.\n * @example\n * ```html\n * <ore-number-input label=\"Quantity\" value=\"1\" min=\"1\" max=\"99\" step=\"1\"></ore-number-input>\n * <ore-number-input label=\"Quantity\" success></ore-number-input>\n * <ore-number-input label=\"Quantity\" loading></ore-number-input>\n * ```\n */\nexport const NUMBER_INPUT_TAG = 'ore-number-input' as const;\ndefine<OreNumberInputProps>(NUMBER_INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n 'large-step': prop.json(undefined as number | undefined),\n loading: prop.bool(false),\n max: prop.json(undefined as number | undefined),\n min: prop.json(undefined as number | undefined),\n name: prop.string(),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n step: prop.number(1),\n success: prop.bool(false),\n value: prop.json(undefined as number | undefined),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // `loading` behaves like a temporary `disabled` — see ore-input's identical computation.\n const isDisabled = computed(() => props.disabled.value || props.loading.value);\n const isReadonly = computed(() => Boolean(props.readonly.value));\n\n // Internal numeric value signal (string representation for the input)\n const fieldValue = signal(props.value.value != null ? String(props.value.value) : '');\n\n defineFieldValue(\n el,\n () => fieldValue.value,\n (value) => {\n fieldValue.value = value;\n },\n );\n\n // Keep fieldValue in sync when props.value changes externally\n rippleWatch(props.value, (v) => {\n const next = v != null ? String(v) : '';\n\n if (fieldValue.value !== next) fieldValue.value = next;\n });\n\n function parseValue(): number | null {\n const v = fieldValue.value.trim();\n\n if (!v) return null;\n\n const n = Number.parseFloat(v);\n\n return Number.isNaN(n) ? null : n;\n }\n\n function commit(val: number | null, _originalEvent?: Event) {\n const min = props.min.value != null ? Number(props.min.value) : undefined;\n const max = props.max.value != null ? Number(props.max.value) : undefined;\n const clamped = val != null ? clamp(val, min, max) : null;\n const nextValue = clamped != null ? String(clamped) : '';\n\n if (fieldValue.value !== nextValue) fieldValue.value = nextValue;\n\n setFieldValue(el, nextValue);\n dispatchNativeFieldEvent(el, 'change');\n }\n\n const spinner = createSpinnerControl({\n commit,\n disabled: isDisabled,\n largeStep: props['large-step'],\n max: props.max,\n min: props.min,\n parse: parseValue,\n readonly: isReadonly,\n step: props.step,\n });\n\n // Composition uses ore-input's own documented `ref` prop (fired with the raw\n // <input> on mount, `null` on unmount) instead of reaching into its shadow DOM —\n // see `packages/refine/AGENTS.md` / input.ts's `ref` JSDoc for the supported contract.\n // Set imperatively (rather than declared in the template) because ore's template\n // engine treats a function-valued attr binding as a reactive getter to invoke, not\n // a literal value to assign — a plain property assignment avoids that entirely.\n const bitInputRef = ref<HTMLElementTagNameMap['ore-input']>();\n let stopAriaWatch: (() => void) | null = null;\n let detachListeners: (() => void) | null = null;\n let refSub: { dispose(): void } | null = null;\n\n const handleFieldRef = (rawInput: HTMLInputElement | null): void => {\n if (!rawInput) {\n stopAriaWatch?.();\n detachListeners?.();\n refSub?.dispose();\n stopAriaWatch = null;\n detachListeners = null;\n refSub = null;\n props.ref.value?.(null);\n\n return;\n }\n\n rawInput.setAttribute('inputmode', 'decimal');\n // The wrapper div is a plain layout container — WAI-ARIA spinbutton semantics\n // live on the actually-focusable element (the raw <input> rendered by ore-input).\n rawInput.setAttribute('role', 'spinbutton');\n\n const handleChange = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n const n = val !== '' ? Number.parseFloat(val) : null;\n\n commit(Number.isNaN(n ?? NaN) ? null : n, e);\n };\n\n const handleInput = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n\n fieldValue.value = val;\n setFieldValue(el, val);\n dispatchNativeFieldEvent(el, 'input');\n };\n\n rawInput.addEventListener('change', handleChange);\n rawInput.addEventListener('input', handleInput);\n detachListeners = () => {\n rawInput.removeEventListener('change', handleChange);\n rawInput.removeEventListener('input', handleInput);\n };\n\n stopAriaWatch = watch(() => {\n const now = parseValue();\n\n if (now == null) rawInput.removeAttribute('aria-valuenow');\n else rawInput.setAttribute('aria-valuenow', String(now));\n\n if (props.min.value != null) rawInput.setAttribute('aria-valuemin', String(props.min.value));\n else rawInput.removeAttribute('aria-valuemin');\n\n if (props.max.value != null) rawInput.setAttribute('aria-valuemax', String(props.max.value));\n else rawInput.removeAttribute('aria-valuemax');\n\n if (isReadonly.value) rawInput.setAttribute('aria-readonly', 'true');\n else rawInput.removeAttribute('aria-readonly');\n });\n\n // Fire user ref callback\n props.ref.value?.(rawInput);\n\n refSub = rippleWatch(props.ref, (cb) => {\n cb?.(rawInput);\n });\n };\n\n // ore-input's own onElement/ref lifecycle calls this back with `null` when its\n // inner <input> unmounts, so no explicit teardown is needed here.\n onElement(bitInputRef, (bitInputEl) => {\n bitInputEl.ref = handleFieldRef;\n });\n\n bind({\n attr: {\n size: props.size,\n value: () => fieldValue.value || null,\n variant: props.variant,\n },\n });\n\n const isNonInteractive = computed(() => isDisabled.value || isReadonly.value);\n\n // The stepper buttons are slotted *into* ore-input's own `prefix`/`suffix` slots instead of\n // sitting outside it in a separate wrapper — they render inside ore-input's own bordered\n // box (same as its built-in clear/password-toggle buttons), matching every other field's\n // single-box look instead of floating as two detached icon buttons either side of a\n // narrow field. `@keydown` moves to ore-input itself: native keyboard events are\n // `composed: true` and bubble out past a shadow boundary, so it still sees keydowns\n // originating from ore-input's internal <input> as well as from these slotted buttons.\n return html`\n <ore-input\n class=\"field\"\n part=\"field control\"\n ref=\"${bitInputRef}\"\n value=\"${() => fieldValue.value ?? 0}\"\n label=\"${() => props.label.value ?? ''}\"\n label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n placeholder=\"${() => props.placeholder.value ?? ''}\"\n name=\"${() => props.name.value ?? ''}\"\n helper=\"${() => props.helper.value ?? ''}\"\n error=\"${() => props.error.value ?? ''}\"\n size=\"${props.size}\"\n color=\"${() => props.color.value ?? ''}\"\n variant=\"${props.variant}\"\n rounded=\"${() => props.rounded.value}\"\n ?disabled=\"${props.disabled}\"\n ?readonly=\"${isReadonly}\"\n ?fullwidth=\"${() => props.fullwidth.value}\"\n ?loading=\"${() => props.loading.value}\"\n ?success=\"${() => props.success.value}\"\n @keydown=\"${(e: KeyboardEvent) => spinner.handleKeydown(e)}\">\n <button\n slot=\"prefix\"\n type=\"button\"\n part=\"decrement-btn\"\n aria-label=\"Decrease\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMin()}\"\n @click=\"${(e: Event) => spinner.incrementBy(-(Number(props.step.value) || 1), e)}\">\n <ore-icon name=\"minus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n <button\n slot=\"suffix\"\n type=\"button\"\n part=\"increment-btn\"\n aria-label=\"Increase\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMax()}\"\n @click=\"${(e: Event) => spinner.incrementBy(Number(props.step.value) || 1, e)}\">\n <ore-icon name=\"plus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n </ore-input>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [disabledLoadingMixin, componentStyles],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"number-input.js","names":[],"sources":["../src/inputs/number-input/number-input.ts"],"sourcesContent":["import { clamp } from '@vielzeug/arsenal/math';\nimport { bind, define, getHost, html, onElement, prop, ref, watchEffect } from '@vielzeug/ore';\nimport { computed, watch as rippleWatch, signal } from '@vielzeug/ripple';\nimport { createSpinnerControl } from '../../core';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport '../../content/icon/icon';\nimport '../input/input';\nimport { disablableBundle, roundableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { disabledLoadingMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './number-input.css?inline';\n\nexport type OreNumberInputEvents = {\n change: Event;\n input: InputEvent;\n};\n\n/** Number Input props */\nexport type OreNumberInputProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Disable interaction */\n disabled?: boolean;\n /** Error message */\n error?: string;\n /** Stretch to full width of container */\n fullwidth?: boolean;\n /** Helper text */\n helper?: string;\n /** Visible label */\n label?: string;\n /** Label placement: 'inset' renders the label inside the control box, 'outside' renders it above */\n 'label-placement'?: 'inset' | 'outside';\n /** Large step (for Page Up/Down, default: 10 × step) */\n 'large-step'?: number;\n /**\n * Shows an inline spinner inside the field and forces the control into `disabled` for the\n * duration — use while an async validation/submission request is in flight to prevent\n * double-submits.\n */\n loading?: boolean;\n /** Maximum allowed value */\n max?: number;\n /** Minimum allowed value */\n min?: number;\n /** Form field name */\n name?: string;\n /** Placeholder text */\n placeholder?: string;\n /** Make the input read-only */\n readonly?: boolean;\n /**\n * JS-only callback fired with the inner `<input>` element when it mounts,\n * and with `null` when it unmounts.\n * Set as a JS property: `bitNumberInput.ref = (el) => { ... }`.\n */\n ref?: ((el: HTMLInputElement | null) => void) | null;\n /** Border radius */\n rounded?: string;\n /** Component size */\n size?: ComponentSize;\n /** Step size for increment/decrement */\n step?: number;\n /**\n * Shows an inline green check icon inside the field to confirm the value has\n * passed validation. Ignored while `error` is set — an error always wins.\n */\n success?: boolean;\n /** Current numeric value */\n value?: number;\n /** Visual variant */\n variant?: VisualVariant;\n};\n\n/**\n * A numeric spin-button input with +/− controls, min/max clamping, and full keyboard support.\n *\n * @element ore-number-input\n *\n * @attr {number} value - Current value\n * @attr {number} min - Minimum value\n * @attr {number} max - Maximum value\n * @attr {number} step - Increment/decrement step (default: 1)\n * @attr {number} large-step - Step for Page Up/Down (default: 10)\n * @attr {boolean} disabled - Disables the control\n * @attr {boolean} readonly - Read-only mode\n * @attr {boolean} loading - Show an inline spinner and force the control disabled\n * @attr {boolean} success - Show an inline success check icon (suppressed while `error` is set)\n * @attr {string} label - Visible label\n * @attr {string} name - Form field name\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} placeholder - Input placeholder\n *\n * @fires input - On every keystroke.\n * @fires change - On committed value change.\n *\n * @slot prefix - Content before the input (e.g. icon)\n * @slot suffix - Content after the input (e.g. unit label)\n * @slot label - Custom label content\n * @slot helper - Custom helper text content\n * @slot error - Custom error content\n *\n * @cssprop --number-input-height - Control height\n * @cssprop --number-input-border-color - Border color\n * @cssprop --number-input-radius - Border radius\n * @cssprop --number-input-bg - Background\n * @cssprop --number-input-btn-bg - Spin button background\n *\n * @part control - Control container.\n * @part decrement-btn - Decrement stepper button.\n * @part input - Input element.\n * @part increment-btn - Increment stepper button.\n * @example\n * ```html\n * <ore-number-input label=\"Quantity\" value=\"1\" min=\"1\" max=\"99\" step=\"1\"></ore-number-input>\n * <ore-number-input label=\"Quantity\" success></ore-number-input>\n * <ore-number-input label=\"Quantity\" loading></ore-number-input>\n * ```\n */\nexport const NUMBER_INPUT_TAG = 'ore-number-input' as const;\ndefine<OreNumberInputProps>(NUMBER_INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n ...roundableBundle,\n error: prop.string(),\n fullwidth: prop.bool(false),\n helper: prop.string(),\n label: prop.string(),\n 'label-placement': prop.oneOf(['inset', 'outside'] as const, 'inset'),\n 'large-step': prop.json(undefined as number | undefined),\n loading: prop.bool(false),\n max: prop.json(undefined as number | undefined),\n min: prop.json(undefined as number | undefined),\n name: prop.string(),\n placeholder: prop.string(),\n readonly: prop.bool(false),\n ref: prop.data<((el: HTMLInputElement | null) => void) | null>(),\n step: prop.number(1),\n success: prop.bool(false),\n value: prop.json(undefined as number | undefined),\n variant: prop.string<VisualVariant>(),\n },\n setup(props) {\n const el = getHost();\n const watch = watchEffect;\n\n // `loading` behaves like a temporary `disabled` — see ore-input's identical computation.\n const isDisabled = computed(() => props.disabled.value || props.loading.value);\n const isReadonly = computed(() => Boolean(props.readonly.value));\n\n // Internal numeric value signal (string representation for the input)\n const fieldValue = signal(props.value.value != null ? String(props.value.value) : '');\n\n defineFieldValue(\n el,\n () => fieldValue.value,\n (value) => {\n fieldValue.value = value;\n },\n );\n\n // Keep fieldValue in sync when props.value changes externally\n rippleWatch(props.value, (v) => {\n const next = v != null ? String(v) : '';\n\n if (fieldValue.value !== next) fieldValue.value = next;\n });\n\n function parseValue(): number | null {\n const v = fieldValue.value.trim();\n\n if (!v) return null;\n\n const n = Number.parseFloat(v);\n\n return Number.isNaN(n) ? null : n;\n }\n\n function commit(val: number | null, _originalEvent?: Event) {\n const min = props.min.value != null ? Number(props.min.value) : undefined;\n const max = props.max.value != null ? Number(props.max.value) : undefined;\n const clamped = val != null ? clamp(val, min, max) : null;\n const nextValue = clamped != null ? String(clamped) : '';\n\n if (fieldValue.value !== nextValue) fieldValue.value = nextValue;\n\n setFieldValue(el, nextValue);\n dispatchNativeFieldEvent(el, 'change');\n }\n\n const spinner = createSpinnerControl({\n commit,\n disabled: isDisabled,\n largeStep: props['large-step'],\n max: props.max,\n min: props.min,\n parse: parseValue,\n readonly: isReadonly,\n step: props.step,\n });\n\n // Composition uses ore-input's own documented `ref` prop (fired with the raw\n // <input> on mount, `null` on unmount) instead of reaching into its shadow DOM —\n // see `packages/refine/AGENTS.md` / input.ts's `ref` JSDoc for the supported contract.\n // Set imperatively (rather than declared in the template) because ore's template\n // engine treats a function-valued attr binding as a reactive getter to invoke, not\n // a literal value to assign — a plain property assignment avoids that entirely.\n const bitInputRef = ref<HTMLElementTagNameMap['ore-input']>();\n let stopAriaWatch: (() => void) | null = null;\n let detachListeners: (() => void) | null = null;\n let refSub: { dispose(): void } | null = null;\n\n const handleFieldRef = (rawInput: HTMLInputElement | null): void => {\n if (!rawInput) {\n stopAriaWatch?.();\n detachListeners?.();\n refSub?.dispose();\n stopAriaWatch = null;\n detachListeners = null;\n refSub = null;\n props.ref.value?.(null);\n\n return;\n }\n\n rawInput.setAttribute('inputmode', 'decimal');\n // The wrapper div is a plain layout container — WAI-ARIA spinbutton semantics\n // live on the actually-focusable element (the raw <input> rendered by ore-input).\n rawInput.setAttribute('role', 'spinbutton');\n\n const handleChange = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n const n = val !== '' ? Number.parseFloat(val) : null;\n\n commit(Number.isNaN(n ?? NaN) ? null : n, e);\n };\n\n const handleInput = (e: Event) => {\n const val = (e.target as HTMLInputElement).value;\n\n fieldValue.value = val;\n setFieldValue(el, val);\n dispatchNativeFieldEvent(el, 'input');\n };\n\n rawInput.addEventListener('change', handleChange);\n rawInput.addEventListener('input', handleInput);\n detachListeners = () => {\n rawInput.removeEventListener('change', handleChange);\n rawInput.removeEventListener('input', handleInput);\n };\n\n stopAriaWatch = watch(() => {\n const now = parseValue();\n\n if (now == null) rawInput.removeAttribute('aria-valuenow');\n else rawInput.setAttribute('aria-valuenow', String(now));\n\n if (props.min.value != null) rawInput.setAttribute('aria-valuemin', String(props.min.value));\n else rawInput.removeAttribute('aria-valuemin');\n\n if (props.max.value != null) rawInput.setAttribute('aria-valuemax', String(props.max.value));\n else rawInput.removeAttribute('aria-valuemax');\n\n if (isReadonly.value) rawInput.setAttribute('aria-readonly', 'true');\n else rawInput.removeAttribute('aria-readonly');\n });\n\n // Fire user ref callback\n props.ref.value?.(rawInput);\n\n refSub = rippleWatch(props.ref, (cb) => {\n cb?.(rawInput);\n });\n };\n\n // ore-input's own onElement/ref lifecycle calls this back with `null` when its\n // inner <input> unmounts, so no explicit teardown is needed here.\n onElement(bitInputRef, (bitInputEl) => {\n bitInputEl.ref = handleFieldRef;\n });\n\n bind({\n attr: {\n size: props.size,\n value: () => fieldValue.value || null,\n variant: props.variant,\n },\n });\n\n const isNonInteractive = computed(() => isDisabled.value || isReadonly.value);\n\n // The stepper buttons are slotted *into* ore-input's own `prefix`/`suffix` slots instead of\n // sitting outside it in a separate wrapper — they render inside ore-input's own bordered\n // box (same as its built-in clear/password-toggle buttons), matching every other field's\n // single-box look instead of floating as two detached icon buttons either side of a\n // narrow field. `@keydown` moves to ore-input itself: native keyboard events are\n // `composed: true` and bubble out past a shadow boundary, so it still sees keydowns\n // originating from ore-input's internal <input> as well as from these slotted buttons.\n return html`\n <ore-input\n class=\"field\"\n part=\"field control\"\n ref=\"${bitInputRef}\"\n value=\"${() => fieldValue.value ?? 0}\"\n label=\"${() => props.label.value ?? ''}\"\n label-placement=\"${() => props['label-placement'].value ?? 'inset'}\"\n placeholder=\"${() => props.placeholder.value ?? ''}\"\n name=\"${() => props.name.value ?? ''}\"\n helper=\"${() => props.helper.value ?? ''}\"\n error=\"${() => props.error.value ?? ''}\"\n size=\"${props.size}\"\n color=\"${() => props.color.value ?? ''}\"\n variant=\"${props.variant}\"\n rounded=\"${() => props.rounded.value}\"\n ?disabled=\"${props.disabled}\"\n ?readonly=\"${isReadonly}\"\n ?fullwidth=\"${() => props.fullwidth.value}\"\n ?loading=\"${() => props.loading.value}\"\n ?success=\"${() => props.success.value}\"\n @keydown=\"${(e: KeyboardEvent) => spinner.handleKeydown(e)}\">\n <button\n slot=\"prefix\"\n type=\"button\"\n part=\"decrement-btn\"\n aria-label=\"Decrease\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMin()}\"\n @click=\"${(e: Event) => spinner.incrementBy(-(Number(props.step.value) || 1), e)}\">\n <ore-icon name=\"minus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n <button\n slot=\"suffix\"\n type=\"button\"\n part=\"increment-btn\"\n aria-label=\"Increase\"\n ?disabled=\"${() => isNonInteractive.value || spinner.atMax()}\"\n @click=\"${(e: Event) => spinner.incrementBy(Number(props.step.value) || 1, e)}\">\n <ore-icon name=\"plus\" size=\"14\" stroke-width=\"2.5\" aria-hidden=\"true\"></ore-icon>\n </button>\n </ore-input>\n `;\n },\n shadow: { delegatesFocus: true },\n styles: [disabledLoadingMixin, componentStyles],\n});\n"],"mappings":"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"}
|
package/dist/otp-input.cjs
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./
|
|
2
|
-
<div class="otp-group" part="group" role="group" aria-label="${
|
|
3
|
-
${()=>
|
|
4
|
-
${()=>
|
|
5
|
-
<span class="separator" aria-hidden="true">${()=>
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./styles/mixins/field-variants.css.cjs"),t=require("./styles/mixins/shape.css.cjs"),n=require("./styles/mixins/theme.css.cjs"),r=require("./core/ore.cjs"),i=require("./core/nav.cjs"),a=require("./shared/prop-bundles.cjs"),o=require("./inputs/shared/native-field-event.cjs"),s=require("./inputs/otp-input/otp-input.css.cjs");let c=require("@vielzeug/ore"),l=require("@vielzeug/ripple");var u=`ore-otp-input`;(0,c.define)(u,{formAssociated:!0,props:{...a.themableBundle,...a.sizableBundle,...a.disablableBundle,label:c.prop.string(`One-time password`),length:c.prop.number(6),masked:c.prop.bool(!1),name:c.prop.string(),separator:c.prop.string(),type:c.prop.oneOf([`numeric`,`alphanumeric`],`numeric`),value:c.prop.string(),variant:c.prop.string()},setup(e){let t=(0,c.getHost)(),n=(0,c.useEmit)(),a=(0,l.computed)(()=>Number(e.length.value)||6),s=(0,l.computed)(()=>!!e.disabled.value),u=(0,l.computed)(()=>Array.from({length:a.value},(e,t)=>t)),d=(0,l.signal)(String(e.value.value||``)),f=()=>String(e.value.value||``);(0,c.useField)({disabled:s,toFormValue:e=>e,value:d}),(0,c.bind)({attr:{size:e.size,value:()=>d.value||null,variant:e.variant}});function p(){return[...t.shadowRoot?.querySelectorAll(`input.cell`)??[]]}let m=i.createListControl({getItems:()=>p(),keys:{next:[`ArrowRight`],prev:[`ArrowLeft`]},loop:!1,onNavigate:(e,t)=>{p()[t]?.focus()},signal:r.lifecycleSignal(c.onCleanup)});function h(){return p().map(e=>e.value).join(``)}function g(e){let t=p(),n=String(e||``).slice(0,t.length);for(let e of t)e.value=``;n.split(``).forEach((e,n)=>{t[n]&&(t[n].value=e)}),d.value=h()}o.defineFieldValue(t,()=>d.value,e=>{g(e)});function _(e,r){let i=p(),a=h(),s=r??(a.length===i.length&&a.split(``).every(Boolean));d.value=a,o.setFieldValue(t,a),o.dispatchNativeFieldEvent(t,`input`),o.dispatchNativeFieldEvent(t,`change`),s&&n(`complete`,{originalEvent:e,value:a})}function v(t){return e.type.value===`numeric`?/^\d$/.test(t):/^[a-z\d]$/i.test(t)}function y(e,t){let n=e.target,r=n.value;if(r.length>1&&(r=r.slice(-1)),r&&!v(r)){n.value=``;return}n.value=r;let i=p();_(e),r&&t<i.length-1&&(i[t+1].focus(),i[t+1].select())}function b(e,t){let n=e.target,r=p();if(m.set(t),e.key===`Backspace`){if(n.value)n.value=``;else if(t>0){let e=r[m.navigate(`prev`)];e&&(e.select(),e.value=``)}_(e,!1),e.preventDefault()}else m.handleKeydown(e)}function x(e){e.preventDefault();let t=(e.clipboardData?.getData(`text`)??``).split(``).filter(e=>v(e)).slice(0,a.value),n=p();t.forEach((e,t)=>{n[t]&&(n[t].value=e)}),_(e),n[Math.min(t.length,n.length-1)]?.focus()}(0,l.watch)(e.value,e=>{g(String(e||``))}),(0,l.watch)(e.length,()=>{requestAnimationFrame(()=>g(f()))});let S=(0,l.computed)(()=>{let t=Number(e.length.value)||6;return e.separator.value==null?-1:Math.floor(t/2)});return(0,c.onMounted)(()=>{g(f())}),c.html`
|
|
2
|
+
<div class="otp-group" part="group" role="group" aria-label="${e.label}">
|
|
3
|
+
${()=>u.value.map(t=>c.html`
|
|
4
|
+
${()=>S.value>0&&t===S.value?c.html`
|
|
5
|
+
<span class="separator" aria-hidden="true">${()=>e.separator.value||`-`}</span>
|
|
6
6
|
`:``}
|
|
7
7
|
<input
|
|
8
8
|
class="cell"
|
|
9
9
|
part="cell"
|
|
10
|
-
type="${()=>
|
|
11
|
-
inputmode="${()=>
|
|
10
|
+
type="${()=>e.masked.value?`password`:`text`}"
|
|
11
|
+
inputmode="${()=>e.type.value===`numeric`?`numeric`:`text`}"
|
|
12
12
|
maxlength="1"
|
|
13
|
-
autocomplete="${()=>
|
|
14
|
-
aria-label="${()=>`Digit ${
|
|
13
|
+
autocomplete="${()=>t===0?`one-time-code`:`off`}"
|
|
14
|
+
aria-label="${()=>`Digit ${t+1} of ${a.value}`}"
|
|
15
15
|
disabled="${()=>s.value?!0:null}"
|
|
16
|
-
@input="${
|
|
17
|
-
@keydown="${
|
|
18
|
-
@paste="${t
|
|
16
|
+
@input="${e=>y(e,t)}"
|
|
17
|
+
@keydown="${e=>b(e,t)}"
|
|
18
|
+
@paste="${e=>t===0?x(e):e.preventDefault()}"
|
|
19
19
|
@focus="${e=>e.target.select()}" />
|
|
20
20
|
`)}
|
|
21
21
|
</div>
|
|
22
|
-
`},styles:[n.colorThemeMixin,t.sizeVariantMixin({}),n.forcedColorsFocusMixin(`.cell`),s.default,
|
|
22
|
+
`},styles:[n.colorThemeMixin,t.sizeVariantMixin({}),n.forcedColorsFocusMixin(`.cell`),s.default,e.fieldVariantMixin({accentVar:`--_cell-focus-border`,container:`.cell`,tokenPrefix:`otp-cell`})]}),exports.OTP_INPUT_TAG=u;
|
|
23
23
|
//# sourceMappingURL=otp-input.cjs.map
|
package/dist/otp-input.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"otp-input.cjs","names":[],"sources":["../src/inputs/otp-input/otp-input.ts"],"sourcesContent":["import { define, html, prop, bind, getHost, onCleanup, onMounted, useEmit } from '@vielzeug/ore';\nimport { useField } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch } from '@vielzeug/ripple/watch';\n\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\n\nimport { createListControl, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, fieldVariantMixin, forcedColorsFocusMixin, sizeVariantMixin } from '../../styles';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './otp-input.css?inline';\n\nexport type OreOtpInputEvents = {\n change: Event;\n complete: { originalEvent?: Event; value: string };\n input: Event;\n};\n\n/** OTP Input props */\nexport type OreOtpInputProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Make inputs disabled */\n disabled?: boolean;\n /** Accessible label */\n label?: string;\n /** Number of input cells */\n length?: number;\n /** Mask input (show dots instead of characters) */\n masked?: boolean;\n /** Form field name */\n name?: string;\n /** Show a separator in the middle (e.g. \"–\") */\n separator?: string;\n /** Component size */\n size?: ComponentSize;\n /** Input type: 'numeric' (digits only) or 'alphanumeric' */\n type?: 'numeric' | 'alphanumeric';\n /** Current value */\n value?: string;\n /** Visual variant */\n variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\n/**\n * A segmented OTP (One-Time Password) input with N individual cells.\n * Auto-advances focus on input, auto-backs on Backspace, handles paste.\n *\n * @element ore-otp-input\n *\n * @attr {number} length - Number of cells (default: 6)\n * @attr {string} type - 'numeric' (default) | 'alphanumeric'\n * @attr {string} value - Current code value\n * @attr {boolean} disabled - Disable all cells\n * @attr {boolean} masked - Show as password\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} name - Form field name\n * @attr {string} label - Group aria-label\n * @attr {string} separator - Optional separator character shown in the middle\n *\n * @fires input - Emitted whenever a cell changes.\n * @fires change - Emitted whenever a cell changes.\n * @fires complete - Emitted when all cells are filled. detail: { value: string, originalEvent?: Event }\n *\n * @slot label - Custom label above the OTP input\n * @slot helper - Custom helper text below the OTP input\n * @slot error - Custom error content below the OTP input\n *\n * @cssprop --otp-cell-size - Width and height of each cell\n * @cssprop --otp-cell-gap - Gap between cells\n * @cssprop --otp-cell-font-size - Font size inside cells\n * @cssprop --otp-cell-radius - Border radius of cells\n * @cssprop --otp-cell-bg - Cell background color\n * @cssprop --otp-cell-border-color - Default border color\n * @cssprop --otp-cell-focus-border - Focused border/caret color\n * @cssprop --otp-cell-hover-bg - Cell background on hover (flat/ghost variants)\n * @cssprop --otp-cell-hover-border-color - Cell border on hover (flat/bordered variants)\n * @cssprop --otp-cell-focus-bg - Cell background when focused (flat variant)\n * @cssprop --otp-cell-focus-border-color - Cell border when focused (flat variant)\n *\n * @part group - Group container.\n * @part cell - Shadow part for the `cell` element.\n * @example\n * ```html\n * <ore-otp-input length=\"6\" color=\"primary\"></ore-otp-input>\n * ```\n */\nexport const OTP_INPUT_TAG = 'ore-otp-input' as const;\ndefine<OreOtpInputProps>(OTP_INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n label: prop.string('One-time password'),\n length: prop.number(6),\n masked: prop.bool(false),\n name: prop.string(),\n separator: prop.string(),\n type: prop.oneOf(['numeric', 'alphanumeric'] as const, 'numeric'),\n value: prop.string(),\n variant: prop.string<Exclude<VisualVariant, 'text' | 'frost'>>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreOtpInputEvents>();\n\n const lengthValue = computed(() => Number(props.length.value) || 6);\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const cells = computed(() => Array.from({ length: lengthValue.value }, (_, i) => i));\n const otpValue = signal(String(props.value.value || ''));\n const normalizedPropValue = () => String(props.value.value || '');\n\n // Form association: the joined cell value is the single form value for `name`,\n // since individual per-cell <input> elements inside the shadow root cannot\n // participate in an ancestor <form>'s submission on their own.\n useField<string>({ disabled: isDisabled, toFormValue: (v) => v, value: otpValue });\n\n bind({\n attr: {\n size: props.size,\n value: () => otpValue.value || null,\n variant: props.variant,\n },\n });\n\n function getInputs(): HTMLInputElement[] {\n return [...(el.shadowRoot?.querySelectorAll<HTMLInputElement>('input.cell') ?? [])];\n }\n\n const listControl = createListControl({\n getItems: () => getInputs(),\n keys: { next: ['ArrowRight'], prev: ['ArrowLeft'] },\n loop: false,\n onNavigate: (_action, index) => {\n const inputs = getInputs();\n\n inputs[index]?.focus();\n },\n signal: lifecycleSignal(onCleanup),\n });\n\n function getValue(): string {\n return getInputs()\n .map((i) => i.value)\n .join('');\n }\n function syncInputsFromValue(raw: string) {\n const allInputs = getInputs();\n const normalized = String(raw || '').slice(0, allInputs.length);\n\n for (const input of allInputs) input.value = '';\n\n normalized.split('').forEach((c, i) => {\n if (allInputs[i]) allInputs[i].value = c;\n });\n\n otpValue.value = getValue();\n }\n defineFieldValue(\n el,\n () => otpValue.value,\n (value) => {\n syncInputsFromValue(value);\n },\n );\n function emitOtpState(originalEvent?: Event, forceComplete?: boolean): void {\n const allInputs = getInputs();\n const full = getValue();\n const complete = forceComplete ?? (full.length === allInputs.length && full.split('').every(Boolean));\n\n otpValue.value = full;\n setFieldValue(el, full);\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n\n if (complete) emit('complete', { originalEvent, value: full });\n }\n function isAllowed(char: string): boolean {\n if (props.type.value === 'numeric') return /^\\d$/.test(char);\n\n return /^[a-z\\d]$/i.test(char);\n }\n function handleInput(e: Event, index: number) {\n const input = e.target as HTMLInputElement;\n let val = input.value;\n\n // Keep only last character if multiple were typed somehow\n if (val.length > 1) val = val.slice(-1);\n\n // Validate character\n if (val && !isAllowed(val)) {\n input.value = '';\n\n return;\n }\n\n input.value = val;\n\n const allInputs = getInputs();\n\n emitOtpState(e);\n\n // Auto-advance\n if (val && index < allInputs.length - 1) {\n allInputs[index + 1].focus();\n allInputs[index + 1].select();\n }\n }\n function handleKeydown(e: KeyboardEvent, index: number) {\n const input = e.target as HTMLInputElement;\n const allInputs = getInputs();\n\n listControl.set(index);\n\n if (e.key === 'Backspace') {\n if (input.value) {\n input.value = '';\n } else if (index > 0) {\n const prevIndex = listControl.navigate('prev');\n const prevInput = allInputs[prevIndex];\n\n if (prevInput) {\n prevInput.select();\n prevInput.value = '';\n }\n }\n\n emitOtpState(e, false);\n e.preventDefault();\n } else {\n listControl.handleKeydown(e);\n }\n }\n function handlePaste(e: ClipboardEvent) {\n e.preventDefault();\n\n const pasted = e.clipboardData?.getData('text') ?? '';\n const chars = pasted\n .split('')\n .filter((c) => isAllowed(c))\n .slice(0, lengthValue.value);\n const allInputs = getInputs();\n\n chars.forEach((char, i) => {\n if (allInputs[i]) allInputs[i].value = char;\n });\n\n emitOtpState(e);\n\n // Focus the cell after last pasted char\n const focusIdx = Math.min(chars.length, allInputs.length - 1);\n\n allInputs[focusIdx]?.focus();\n }\n\n watch(props.value, (value) => {\n syncInputsFromValue(String(value || ''));\n });\n\n watch(props.length, () => {\n // Cells re-render when length changes; sync after DOM updates.\n requestAnimationFrame(() => syncInputsFromValue(normalizedPropValue()));\n });\n\n const separatorIdx = computed(() => {\n const len = Number(props.length.value) || 6;\n\n return props.separator.value != null ? Math.floor(len / 2) : -1;\n });\n\n onMounted(() => {\n // Populate cells from value prop on mount\n syncInputsFromValue(normalizedPropValue());\n });\n\n return html`\n <div class=\"otp-group\" part=\"group\" role=\"group\" aria-label=\"${props.label}\">\n ${() =>\n cells.value.map(\n (i) => html`\n ${() =>\n separatorIdx.value > 0 && i === separatorIdx.value\n ? html`\n <span class=\"separator\" aria-hidden=\"true\">${() => props.separator.value || '-'}</span>\n `\n : ''}\n <input\n class=\"cell\"\n part=\"cell\"\n type=\"${() => (props.masked.value ? 'password' : 'text')}\"\n inputmode=\"${() => (props.type.value === 'numeric' ? 'numeric' : 'text')}\"\n maxlength=\"1\"\n autocomplete=\"${() => (i === 0 ? 'one-time-code' : 'off')}\"\n aria-label=\"${() => `Digit ${i + 1} of ${lengthValue.value}`}\"\n disabled=\"${() => (isDisabled.value ? true : null)}\"\n @input=\"${(e: Event) => handleInput(e, i)}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, i)}\"\n @paste=\"${(e: ClipboardEvent) => (i === 0 ? handlePaste(e) : e.preventDefault())}\"\n @focus=\"${(e: FocusEvent) => (e.target as HTMLInputElement).select()}\" />\n `,\n )}\n </div>\n `;\n },\n styles: [\n colorThemeMixin,\n sizeVariantMixin({}),\n forcedColorsFocusMixin('.cell'),\n componentStyles,\n // Must come after `componentStyles` — see `ore-input`'s identical ordering note for why.\n fieldVariantMixin({ accentVar: '--_cell-focus-border', container: '.cell', tokenPrefix: 'otp-cell' }),\n ],\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"otp-input.cjs","names":[],"sources":["../src/inputs/otp-input/otp-input.ts"],"sourcesContent":["import { bind, define, getHost, html, onCleanup, onMounted, prop, useEmit, useField } from '@vielzeug/ore';\nimport { computed, signal, watch } from '@vielzeug/ripple';\nimport { createListControl, lifecycleSignal } from '../../core';\nimport { disablableBundle, sizableBundle, themableBundle } from '../../shared';\nimport { colorThemeMixin, fieldVariantMixin, forcedColorsFocusMixin, sizeVariantMixin } from '../../styles';\nimport type { ComponentSize, ThemeColor, VisualVariant } from '../../types';\nimport { defineFieldValue, dispatchNativeFieldEvent, setFieldValue } from '../shared/native-field-event';\nimport componentStyles from './otp-input.css?inline';\n\nexport type OreOtpInputEvents = {\n change: Event;\n complete: { originalEvent?: Event; value: string };\n input: Event;\n};\n\n/** OTP Input props */\nexport type OreOtpInputProps = {\n /** Theme color */\n color?: ThemeColor;\n /** Make inputs disabled */\n disabled?: boolean;\n /** Accessible label */\n label?: string;\n /** Number of input cells */\n length?: number;\n /** Mask input (show dots instead of characters) */\n masked?: boolean;\n /** Form field name */\n name?: string;\n /** Show a separator in the middle (e.g. \"–\") */\n separator?: string;\n /** Component size */\n size?: ComponentSize;\n /** Input type: 'numeric' (digits only) or 'alphanumeric' */\n type?: 'numeric' | 'alphanumeric';\n /** Current value */\n value?: string;\n /** Visual variant */\n variant?: Exclude<VisualVariant, 'text' | 'frost'>;\n};\n\n/**\n * A segmented OTP (One-Time Password) input with N individual cells.\n * Auto-advances focus on input, auto-backs on Backspace, handles paste.\n *\n * @element ore-otp-input\n *\n * @attr {number} length - Number of cells (default: 6)\n * @attr {string} type - 'numeric' (default) | 'alphanumeric'\n * @attr {string} value - Current code value\n * @attr {boolean} disabled - Disable all cells\n * @attr {boolean} masked - Show as password\n * @attr {string} size - 'sm' | 'md' | 'lg'\n * @attr {string} color - Theme color: 'primary' | 'secondary' | 'info' | 'success' | 'warning' | 'error'\n * @attr {string} name - Form field name\n * @attr {string} label - Group aria-label\n * @attr {string} separator - Optional separator character shown in the middle\n *\n * @fires input - Emitted whenever a cell changes.\n * @fires change - Emitted whenever a cell changes.\n * @fires complete - Emitted when all cells are filled. detail: { value: string, originalEvent?: Event }\n *\n * @slot label - Custom label above the OTP input\n * @slot helper - Custom helper text below the OTP input\n * @slot error - Custom error content below the OTP input\n *\n * @cssprop --otp-cell-size - Width and height of each cell\n * @cssprop --otp-cell-gap - Gap between cells\n * @cssprop --otp-cell-font-size - Font size inside cells\n * @cssprop --otp-cell-radius - Border radius of cells\n * @cssprop --otp-cell-bg - Cell background color\n * @cssprop --otp-cell-border-color - Default border color\n * @cssprop --otp-cell-focus-border - Focused border/caret color\n * @cssprop --otp-cell-hover-bg - Cell background on hover (flat/ghost variants)\n * @cssprop --otp-cell-hover-border-color - Cell border on hover (flat/bordered variants)\n * @cssprop --otp-cell-focus-bg - Cell background when focused (flat variant)\n * @cssprop --otp-cell-focus-border-color - Cell border when focused (flat variant)\n *\n * @part group - Group container.\n * @part cell - Shadow part for the `cell` element.\n * @example\n * ```html\n * <ore-otp-input length=\"6\" color=\"primary\"></ore-otp-input>\n * ```\n */\nexport const OTP_INPUT_TAG = 'ore-otp-input' as const;\ndefine<OreOtpInputProps>(OTP_INPUT_TAG, {\n formAssociated: true,\n props: {\n ...themableBundle,\n ...sizableBundle,\n ...disablableBundle,\n label: prop.string('One-time password'),\n length: prop.number(6),\n masked: prop.bool(false),\n name: prop.string(),\n separator: prop.string(),\n type: prop.oneOf(['numeric', 'alphanumeric'] as const, 'numeric'),\n value: prop.string(),\n variant: prop.string<Exclude<VisualVariant, 'text' | 'frost'>>(),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreOtpInputEvents>();\n\n const lengthValue = computed(() => Number(props.length.value) || 6);\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const cells = computed(() => Array.from({ length: lengthValue.value }, (_, i) => i));\n const otpValue = signal(String(props.value.value || ''));\n const normalizedPropValue = () => String(props.value.value || '');\n\n // Form association: the joined cell value is the single form value for `name`,\n // since individual per-cell <input> elements inside the shadow root cannot\n // participate in an ancestor <form>'s submission on their own.\n useField<string>({ disabled: isDisabled, toFormValue: (v) => v, value: otpValue });\n\n bind({\n attr: {\n size: props.size,\n value: () => otpValue.value || null,\n variant: props.variant,\n },\n });\n\n function getInputs(): HTMLInputElement[] {\n return [...(el.shadowRoot?.querySelectorAll<HTMLInputElement>('input.cell') ?? [])];\n }\n\n const listControl = createListControl({\n getItems: () => getInputs(),\n keys: { next: ['ArrowRight'], prev: ['ArrowLeft'] },\n loop: false,\n onNavigate: (_action, index) => {\n const inputs = getInputs();\n\n inputs[index]?.focus();\n },\n signal: lifecycleSignal(onCleanup),\n });\n\n function getValue(): string {\n return getInputs()\n .map((i) => i.value)\n .join('');\n }\n function syncInputsFromValue(raw: string) {\n const allInputs = getInputs();\n const normalized = String(raw || '').slice(0, allInputs.length);\n\n for (const input of allInputs) input.value = '';\n\n normalized.split('').forEach((c, i) => {\n if (allInputs[i]) allInputs[i].value = c;\n });\n\n otpValue.value = getValue();\n }\n defineFieldValue(\n el,\n () => otpValue.value,\n (value) => {\n syncInputsFromValue(value);\n },\n );\n function emitOtpState(originalEvent?: Event, forceComplete?: boolean): void {\n const allInputs = getInputs();\n const full = getValue();\n const complete = forceComplete ?? (full.length === allInputs.length && full.split('').every(Boolean));\n\n otpValue.value = full;\n setFieldValue(el, full);\n dispatchNativeFieldEvent(el, 'input');\n dispatchNativeFieldEvent(el, 'change');\n\n if (complete) emit('complete', { originalEvent, value: full });\n }\n function isAllowed(char: string): boolean {\n if (props.type.value === 'numeric') return /^\\d$/.test(char);\n\n return /^[a-z\\d]$/i.test(char);\n }\n function handleInput(e: Event, index: number) {\n const input = e.target as HTMLInputElement;\n let val = input.value;\n\n // Keep only last character if multiple were typed somehow\n if (val.length > 1) val = val.slice(-1);\n\n // Validate character\n if (val && !isAllowed(val)) {\n input.value = '';\n\n return;\n }\n\n input.value = val;\n\n const allInputs = getInputs();\n\n emitOtpState(e);\n\n // Auto-advance\n if (val && index < allInputs.length - 1) {\n allInputs[index + 1].focus();\n allInputs[index + 1].select();\n }\n }\n function handleKeydown(e: KeyboardEvent, index: number) {\n const input = e.target as HTMLInputElement;\n const allInputs = getInputs();\n\n listControl.set(index);\n\n if (e.key === 'Backspace') {\n if (input.value) {\n input.value = '';\n } else if (index > 0) {\n const prevIndex = listControl.navigate('prev');\n const prevInput = allInputs[prevIndex];\n\n if (prevInput) {\n prevInput.select();\n prevInput.value = '';\n }\n }\n\n emitOtpState(e, false);\n e.preventDefault();\n } else {\n listControl.handleKeydown(e);\n }\n }\n function handlePaste(e: ClipboardEvent) {\n e.preventDefault();\n\n const pasted = e.clipboardData?.getData('text') ?? '';\n const chars = pasted\n .split('')\n .filter((c) => isAllowed(c))\n .slice(0, lengthValue.value);\n const allInputs = getInputs();\n\n chars.forEach((char, i) => {\n if (allInputs[i]) allInputs[i].value = char;\n });\n\n emitOtpState(e);\n\n // Focus the cell after last pasted char\n const focusIdx = Math.min(chars.length, allInputs.length - 1);\n\n allInputs[focusIdx]?.focus();\n }\n\n watch(props.value, (value) => {\n syncInputsFromValue(String(value || ''));\n });\n\n watch(props.length, () => {\n // Cells re-render when length changes; sync after DOM updates.\n requestAnimationFrame(() => syncInputsFromValue(normalizedPropValue()));\n });\n\n const separatorIdx = computed(() => {\n const len = Number(props.length.value) || 6;\n\n return props.separator.value != null ? Math.floor(len / 2) : -1;\n });\n\n onMounted(() => {\n // Populate cells from value prop on mount\n syncInputsFromValue(normalizedPropValue());\n });\n\n return html`\n <div class=\"otp-group\" part=\"group\" role=\"group\" aria-label=\"${props.label}\">\n ${() =>\n cells.value.map(\n (i) => html`\n ${() =>\n separatorIdx.value > 0 && i === separatorIdx.value\n ? html`\n <span class=\"separator\" aria-hidden=\"true\">${() => props.separator.value || '-'}</span>\n `\n : ''}\n <input\n class=\"cell\"\n part=\"cell\"\n type=\"${() => (props.masked.value ? 'password' : 'text')}\"\n inputmode=\"${() => (props.type.value === 'numeric' ? 'numeric' : 'text')}\"\n maxlength=\"1\"\n autocomplete=\"${() => (i === 0 ? 'one-time-code' : 'off')}\"\n aria-label=\"${() => `Digit ${i + 1} of ${lengthValue.value}`}\"\n disabled=\"${() => (isDisabled.value ? true : null)}\"\n @input=\"${(e: Event) => handleInput(e, i)}\"\n @keydown=\"${(e: KeyboardEvent) => handleKeydown(e, i)}\"\n @paste=\"${(e: ClipboardEvent) => (i === 0 ? handlePaste(e) : e.preventDefault())}\"\n @focus=\"${(e: FocusEvent) => (e.target as HTMLInputElement).select()}\" />\n `,\n )}\n </div>\n `;\n },\n styles: [\n colorThemeMixin,\n sizeVariantMixin({}),\n forcedColorsFocusMixin('.cell'),\n componentStyles,\n // Must come after `componentStyles` — see `ore-input`'s identical ordering note for why.\n fieldVariantMixin({ accentVar: '--_cell-focus-border', container: '.cell', tokenPrefix: 'otp-cell' }),\n ],\n});\n"],"mappings":"qdAqFA,IAAa,EAAgB,iBAC7B,EAAA,EAAA,OAAA,CAAyB,EAAe,CACtC,eAAgB,GAChB,MAAO,CACL,GAAG,EAAA,eACH,GAAG,EAAA,cACH,GAAG,EAAA,iBACH,MAAO,EAAA,KAAK,OAAO,mBAAmB,EACtC,OAAQ,EAAA,KAAK,OAAO,CAAC,EACrB,OAAQ,EAAA,KAAK,KAAK,EAAK,EACvB,KAAM,EAAA,KAAK,OAAO,EAClB,UAAW,EAAA,KAAK,OAAO,EACvB,KAAM,EAAA,KAAK,MAAM,CAAC,UAAW,cAAc,EAAY,SAAS,EAChE,MAAO,EAAA,KAAK,OAAO,EACnB,QAAS,EAAA,KAAK,OAAiD,CACjE,EACA,MAAM,EAAO,CACX,IAAM,GAAA,EAAK,EAAA,QAAA,CAAQ,EACb,GAAA,EAAO,EAAA,QAAA,CAA2B,EAElC,GAAA,EAAc,EAAA,SAAA,KAAe,OAAO,EAAM,OAAO,KAAK,GAAK,CAAC,EAC5D,GAAA,EAAa,EAAA,SAAA,KAAe,EAAQ,EAAM,SAAS,KAAM,EACzD,GAAA,EAAQ,EAAA,SAAA,KAAe,MAAM,KAAK,CAAE,OAAQ,EAAY,KAAM,GAAI,EAAG,IAAM,CAAC,CAAC,EAC7E,GAAA,EAAW,EAAA,OAAA,CAAO,OAAO,EAAM,MAAM,OAAS,EAAE,CAAC,EACjD,MAA4B,OAAO,EAAM,MAAM,OAAS,EAAE,GAKhE,EAAA,EAAA,SAAA,CAAiB,CAAE,SAAU,EAAY,YAAc,GAAM,EAAG,MAAO,CAAS,CAAC,GAEjF,EAAA,EAAA,KAAA,CAAK,CACH,KAAM,CACJ,KAAM,EAAM,KACZ,UAAa,EAAS,OAAS,KAC/B,QAAS,EAAM,OACjB,CACF,CAAC,EAED,SAAS,GAAgC,CACvC,MAAO,CAAC,GAAI,EAAG,YAAY,iBAAmC,YAAY,GAAK,CAAC,CAAE,CACpF,CAEA,IAAM,EAAc,EAAA,kBAAkB,CACpC,aAAgB,EAAU,EAC1B,KAAM,CAAE,KAAM,CAAC,YAAY,EAAG,KAAM,CAAC,WAAW,CAAE,EAClD,KAAM,GACN,YAAa,EAAS,IAAU,CAG9B,EAAA,CAAA,CAAO,EAAM,EAAE,MAAM,CACvB,EACA,OAAQ,EAAA,gBAAgB,EAAA,SAAS,CACnC,CAAC,EAED,SAAS,GAAmB,CAC1B,OAAO,EAAU,CAAC,CACf,IAAK,GAAM,EAAE,KAAK,CAAC,CACnB,KAAK,EAAE,CACZ,CACA,SAAS,EAAoB,EAAa,CACxC,IAAM,EAAY,EAAU,EACtB,EAAa,OAAO,GAAO,EAAE,CAAC,CAAC,MAAM,EAAG,EAAU,MAAM,EAE9D,IAAK,IAAM,KAAS,EAAW,EAAM,MAAQ,GAE7C,EAAW,MAAM,EAAE,CAAC,CAAC,SAAS,EAAG,IAAM,CACjC,EAAU,KAAI,EAAU,EAAE,CAAC,MAAQ,EACzC,CAAC,EAED,EAAS,MAAQ,EAAS,CAC5B,CACA,EAAA,iBACE,MACM,EAAS,MACd,GAAU,CACT,EAAoB,CAAK,CAC3B,CACF,EACA,SAAS,EAAa,EAAuB,EAA+B,CAC1E,IAAM,EAAY,EAAU,EACtB,EAAO,EAAS,EAChB,EAAW,IAAkB,EAAK,SAAW,EAAU,QAAU,EAAK,MAAM,EAAE,CAAC,CAAC,MAAM,OAAO,GAEnG,EAAS,MAAQ,EACjB,EAAA,cAAc,EAAI,CAAI,EACtB,EAAA,yBAAyB,EAAI,OAAO,EACpC,EAAA,yBAAyB,EAAI,QAAQ,EAEjC,GAAU,EAAK,WAAY,CAAE,gBAAe,MAAO,CAAK,CAAC,CAC/D,CACA,SAAS,EAAU,EAAuB,CAGxC,OAFI,EAAM,KAAK,QAAU,UAAkB,OAAO,KAAK,CAAI,EAEpD,aAAa,KAAK,CAAI,CAC/B,CACA,SAAS,EAAY,EAAU,EAAe,CAC5C,IAAM,EAAQ,EAAE,OACZ,EAAM,EAAM,MAMhB,GAHI,EAAI,OAAS,IAAG,EAAM,EAAI,MAAM,EAAE,GAGlC,GAAO,CAAC,EAAU,CAAG,EAAG,CAC1B,EAAM,MAAQ,GAEd,MACF,CAEA,EAAM,MAAQ,EAEd,IAAM,EAAY,EAAU,EAE5B,EAAa,CAAC,EAGV,GAAO,EAAQ,EAAU,OAAS,IACpC,EAAU,EAAQ,EAAE,CAAC,MAAM,EAC3B,EAAU,EAAQ,EAAE,CAAC,OAAO,EAEhC,CACA,SAAS,EAAc,EAAkB,EAAe,CACtD,IAAM,EAAQ,EAAE,OACV,EAAY,EAAU,EAI5B,GAFA,EAAY,IAAI,CAAK,EAEjB,EAAE,MAAQ,YAAa,CACzB,GAAI,EAAM,MACR,EAAM,MAAQ,QACT,GAAI,EAAQ,EAAG,CAEpB,IAAM,EAAY,EADA,EAAY,SAAS,MACX,GAExB,IACF,EAAU,OAAO,EACjB,EAAU,MAAQ,GAEtB,CAEA,EAAa,EAAG,EAAK,EACrB,EAAE,eAAe,CACnB,MACE,EAAY,cAAc,CAAC,CAE/B,CACA,SAAS,EAAY,EAAmB,CACtC,EAAE,eAAe,EAGjB,IAAM,GADS,EAAE,eAAe,QAAQ,MAAM,GAAK,GAAA,CAEhD,MAAM,EAAE,CAAC,CACT,OAAQ,GAAM,EAAU,CAAC,CAAC,CAAC,CAC3B,MAAM,EAAG,EAAY,KAAK,EACvB,EAAY,EAAU,EAE5B,EAAM,SAAS,EAAM,IAAM,CACrB,EAAU,KAAI,EAAU,EAAE,CAAC,MAAQ,EACzC,CAAC,EAED,EAAa,CAAC,EAKd,EAFiB,KAAK,IAAI,EAAM,OAAQ,EAAU,OAAS,CAEjD,EAAS,EAAE,MAAM,CAC7B,EAEA,EAAA,EAAA,MAAA,CAAM,EAAM,MAAQ,GAAU,CAC5B,EAAoB,OAAO,GAAS,EAAE,CAAC,CACzC,CAAC,GAED,EAAA,EAAA,MAAA,CAAM,EAAM,WAAc,CAExB,0BAA4B,EAAoB,EAAoB,CAAC,CAAC,CACxE,CAAC,EAED,IAAM,GAAA,EAAe,EAAA,SAAA,KAAe,CAClC,IAAM,EAAM,OAAO,EAAM,OAAO,KAAK,GAAK,EAE1C,OAAO,EAAM,UAAU,OAAS,KAA6B,GAAtB,KAAK,MAAM,EAAM,CAAC,CAC3D,CAAC,EAOD,OALA,EAAA,EAAA,UAAA,KAAgB,CAEd,EAAoB,EAAoB,CAAC,CAC3C,CAAC,EAEM,EAAA,IAAI;qEACsD,EAAM,MAAM;cAEvE,EAAM,MAAM,IACT,GAAM,EAAA,IAAI;oBAEP,EAAa,MAAQ,GAAK,IAAM,EAAa,MACzC,EAAA,IAAI;uEACiD,EAAM,UAAU,OAAS,IAAI;sBAElF,GAAG;;;;4BAIQ,EAAM,OAAO,MAAQ,WAAa,OAAQ;iCACrC,EAAM,KAAK,QAAU,UAAY,UAAY,OAAQ;;oCAElD,IAAM,EAAI,gBAAkB,MAAO;kCACtC,SAAS,EAAI,EAAE,MAAM,EAAY,QAAQ;gCAC1C,EAAW,MAAQ,GAAO,KAAM;0BACxC,GAAa,EAAY,EAAG,CAAC,EAAE;4BAC7B,GAAqB,EAAc,EAAG,CAAC,EAAE;0BAC3C,GAAuB,IAAM,EAAI,EAAY,CAAC,EAAI,EAAE,eAAe,EAAG;0BACtE,GAAmB,EAAE,OAA4B,OAAO,EAAE;aAE3E,EAAE;;KAGV,EACA,OAAQ,CACN,EAAA,gBACA,EAAA,iBAAiB,CAAC,CAAC,EACnB,EAAA,uBAAuB,OAAO,EAC9B,EAAA,QAEA,EAAA,kBAAkB,CAAE,UAAW,uBAAwB,UAAW,QAAS,YAAa,UAAW,CAAC,CACtG,CACF,CAAC"}
|